OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import argparse | 5 import argparse |
6 import fnmatch | 6 import fnmatch |
7 import glob | 7 import glob |
8 import os | 8 import os |
9 import plistlib | 9 import plistlib |
10 import shutil | 10 import shutil |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 'no mobile provisioning profile for "%s"', | 199 'no mobile provisioning profile for "%s"', |
200 bundle.identifier) | 200 bundle.identifier) |
201 | 201 |
202 # Select the most specific mobile provisioning profile, i.e. the one with | 202 # Select the most specific mobile provisioning profile, i.e. the one with |
203 # the longest application identifier pattern. | 203 # the longest application identifier pattern. |
204 return max( | 204 return max( |
205 valid_provisioning_profiles, | 205 valid_provisioning_profiles, |
206 key=lambda p: len(p.application_identifier_pattern)) | 206 key=lambda p: len(p.application_identifier_pattern)) |
207 | 207 |
208 | 208 |
209 def CodeSignBundle(binary, bundle, args): | 209 def InstallFramework(framework_path, bundle, args): |
| 210 """Install framework from |framework_path| to |bundle| and code-re-sign it.""" |
| 211 installed_framework_path = os.path.join( |
| 212 bundle.path, 'Frameworks', os.path.basename(framework_path)) |
| 213 |
| 214 if os.path.exists(installed_framework_path): |
| 215 shutil.rmtree(installed_framework_path) |
| 216 |
| 217 shutil.copytree(framework_path, installed_framework_path) |
| 218 |
| 219 framework_bundle = Bundle(installed_framework_path) |
| 220 CodeSignBundle(framework_bundle.binary_path, framework_bundle, args, True) |
| 221 |
| 222 |
| 223 def CodeSignBundle(binary, bundle, args, preserve=False): |
210 """Cryptographically signs bundle. | 224 """Cryptographically signs bundle. |
211 | 225 |
212 Args: | 226 Args: |
213 bundle: the Bundle object to sign. | 227 bundle: the Bundle object to sign. |
214 args: a dictionary with configuration settings for the code signature, | 228 args: a dictionary with configuration settings for the code signature, |
215 need to define 'entitlements_path', 'provisioning_profile_short_name', | 229 need to define 'entitlements_path', 'provisioning_profile_short_name', |
216 'deep_signature' and 'identify' keys. | 230 'deep_signature' and 'identify' keys. |
217 """ | 231 """ |
218 provisioning_profile = FindProvisioningProfile( | 232 provisioning_profile = FindProvisioningProfile( |
219 bundle, args.provisioning_profile_short_name) | 233 bundle, args.provisioning_profile_short_name) |
220 provisioning_profile.Install(bundle) | 234 provisioning_profile.Install(bundle) |
221 | 235 |
222 signature_file = os.path.join(bundle.path, '_CodeSignature', 'CodeResources') | 236 if preserve: |
223 if os.path.isfile(signature_file): | 237 process = subprocess.Popen([ |
224 os.unlink(signature_file) | |
225 | |
226 shutil.copy(binary, bundle.binary_path) | |
227 | |
228 if args.preserve: | |
229 subprocess.check_call([ | |
230 'xcrun', 'codesign', '--force', '--sign', args.identity, | 238 'xcrun', 'codesign', '--force', '--sign', args.identity, |
231 '--deep', '--preserve-metadata=identifier,entitlements', | 239 '--deep', '--preserve-metadata=identifier,entitlements', |
232 '--timestamp=none', bundle.path]) | 240 '--timestamp=none', bundle.path], stderr=subprocess.PIPE) |
| 241 _, stderr = process.communicate() |
| 242 if process.returncode: |
| 243 sys.stderr.write(stderr) |
| 244 sys.exit(process.returncode) |
| 245 for line in stderr.splitlines(): |
| 246 # Ignore expected warning as we are replacing the signature on purpose. |
| 247 if not line.endswith(': replacing existing signature'): |
| 248 sys.stderr.write(line + '\n') |
233 else: | 249 else: |
| 250 signature_file = os.path.join( |
| 251 bundle.path, '_CodeSignature', 'CodeResources') |
| 252 if os.path.isfile(signature_file): |
| 253 os.unlink(signature_file) |
| 254 |
| 255 if os.path.isfile(bundle.binary_path): |
| 256 os.unlink(bundle.binary_path) |
| 257 shutil.copy(binary, bundle.binary_path) |
| 258 |
234 entitlements = Entitlements(args.entitlements_path) | 259 entitlements = Entitlements(args.entitlements_path) |
235 entitlements.LoadDefaults(provisioning_profile.entitlements) | 260 entitlements.LoadDefaults(provisioning_profile.entitlements) |
236 entitlements.ExpandVariables({ | 261 entitlements.ExpandVariables({ |
237 'CFBundleIdentifier': bundle.identifier, | 262 'CFBundleIdentifier': bundle.identifier, |
238 'AppIdentifierPrefix': '%s.' % (provisioning_profile.team_identifier,) | 263 'AppIdentifierPrefix': '%s.' % (provisioning_profile.team_identifier,) |
239 }) | 264 }) |
240 | 265 |
241 with tempfile.NamedTemporaryFile(suffix='.xcent') as temporary_file_path: | 266 with tempfile.NamedTemporaryFile(suffix='.xcent') as temporary_file_path: |
242 entitlements.WriteTo(temporary_file_path.name) | 267 entitlements.WriteTo(temporary_file_path.name) |
243 subprocess.check_call([ | 268 subprocess.check_call([ |
(...skipping 10 matching lines...) Expand all Loading... |
254 '--binary', '-b', required=True, | 279 '--binary', '-b', required=True, |
255 help='path to the iOS bundle binary') | 280 help='path to the iOS bundle binary') |
256 parser.add_argument( | 281 parser.add_argument( |
257 '--provisioning-profile', '-p', dest='provisioning_profile_short_name', | 282 '--provisioning-profile', '-p', dest='provisioning_profile_short_name', |
258 help='short name of the mobile provisioning profile to use (' | 283 help='short name of the mobile provisioning profile to use (' |
259 'if undefined, will autodetect the mobile provisioning ' | 284 'if undefined, will autodetect the mobile provisioning ' |
260 'to use)') | 285 'to use)') |
261 parser.add_argument( | 286 parser.add_argument( |
262 '--identity', '-i', required=True, | 287 '--identity', '-i', required=True, |
263 help='identity to use to codesign') | 288 help='identity to use to codesign') |
264 group = parser.add_mutually_exclusive_group(required=True) | 289 parser.add_argument( |
265 group.add_argument( | |
266 '--entitlements', '-e', dest='entitlements_path', | 290 '--entitlements', '-e', dest='entitlements_path', |
267 help='path to the entitlements file to use') | 291 help='path to the entitlements file to use') |
268 group.add_argument( | 292 parser.add_argument( |
269 '--deep', '-d', action='store_true', default=False, dest='preserve', | 293 '--framework', '-F', action='append', default=[], dest="frameworks", |
270 help='deep signature (default: %(default)s)') | 294 help='install and resign system framework') |
271 args = parser.parse_args() | 295 args = parser.parse_args() |
272 | 296 |
273 CodeSignBundle(args.binary, Bundle(args.path), args) | 297 bundle = Bundle(args.path) |
| 298 for framework in args.frameworks: |
| 299 InstallFramework(framework, bundle, args) |
| 300 |
| 301 CodeSignBundle(args.binary, bundle, args) |
274 | 302 |
275 | 303 |
276 if __name__ == '__main__': | 304 if __name__ == '__main__': |
277 sys.exit(Main()) | 305 sys.exit(Main()) |
OLD | NEW |