Changeset 846 for trunk/bin/patch_capabilities.pl
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/bin/patch_capabilities.pl
r651 r846 2 2 ############################################################################# 3 3 ## 4 ## Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).4 ## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 5 5 ## All rights reserved. 6 6 ## Contact: Nokia Corporation (qt-info@nokia.com) … … 47 47 ####################################################################### 48 48 49 # 50 # Note: Please make sure to output all changes done to the pkg file in a print statements 51 # starting with "Patching: " to ease integration into IDEs! 52 # 53 54 use File::Copy; 55 use File::Spec; 56 49 57 sub Usage() { 50 58 print("This script can be used to set capabilities of all binaries\n"); 51 59 print("specified for deployment in a .pkg file.\n"); 52 60 print("If no capabilities are given, the binaries will be given the\n"); 53 print("capabilities supported by self-signed certificates.\n"); 54 print("\n *** NOTE: If *_template.pkg file is given, 'target-platform' is REQUIRED. ***\n"); 55 print("\nUsage: patch_capabilities.pl pkg_filename <target-platform> [capability list]\n"); 61 print("capabilities supported by self-signed certificates.\n\n"); 62 print(" *** NOTE: If *_template.pkg file is given and one is using symbian-abld or\n"); 63 print(" symbian-sbsv2 platform, 'target-platform' is REQUIRED. ***\n\n"); 64 print(" *** NOTE2: When patching gcce binaries built with symbian-sbsv2 toolchain,\n"); 65 print(" armv5 must be specified as platform.\n"); 66 print("\nUsage: patch_capabilities.pl [-c] pkg_filename [target-platform [capability list]]\n"); 56 67 print("\nE.g. patch_capabilities.pl myapp_template.pkg release-armv5 \"All -TCB\"\n"); 68 print("\nThe parameter -c can be used to just check if package is compatible with self-signing\n"); 69 print("without actually doing any patching.\n"); 70 print("Explicit capability list cannot be used with -c parameter.\n"); 57 71 exit(); 58 72 } 59 73 60 my @capabilitiesToSet = ("LocalServices", "NetworkServices", "ReadUserData", "UserEnvironment", "WriteUserData"); 74 sub trim($) { 75 my $string = shift; 76 $string =~ s/^\s+//; 77 $string =~ s/\s+$//; 78 return $string; 79 } 80 81 my $epocroot = $ENV{EPOCROOT}; 82 my $epocToolsDir = ""; 83 if ($epocroot ne "") { 84 $epocroot =~ s,\\,/,g; 85 if ($epocroot =~ m,[^/]$,) { 86 $epocroot = $epocroot."/"; 87 } 88 $epocToolsDir = "${epocroot}epoc32/tools/"; 89 } 90 91 my $nullDevice = "/dev/null"; 92 $nullDevice = "NUL" if ($^O =~ /MSWin/); 93 94 my @capabilitiesToAllow = ("LocalServices", "NetworkServices", "ReadUserData", "UserEnvironment", "WriteUserData", "Location"); 95 my @capabilitiesSpecified = (); 61 96 62 97 # If arguments were given to the script, … … 65 100 # Parse the first given script argument as a ".pkg" file name. 66 101 my $pkgFileName = shift(@ARGV); 102 my $justCheck = ""; 103 my $msgPrefix = "Patching:"; 104 105 if ($pkgFileName eq "-c") { 106 $pkgFileName = shift(@ARGV); 107 $justCheck = true; 108 $msgPrefix = "Warning:"; 109 } 67 110 68 111 # These variables will only be set for template .pkg files. … … 74 117 { 75 118 my $targetplatform; 76 unless ($targetplatform = shift(@ARGV)) 119 my $templateFile; 120 my $templateContents; 121 open($templateFile, "< $pkgFileName") or die ("Could not open $pkgFileName"); 122 $templateContents = <$templateFile>; 123 close($templateFile); 124 unless (($targetplatform = shift(@ARGV)) || $templateContents !~ /\$\(PLATFORM\)/) 77 125 { 78 126 Usage(); 79 127 } 80 128 $targetplatform = "-" if (!$targetplatform); 81 129 my @tmpvalues = split('-', $targetplatform); 82 130 $target = $tmpvalues[0]; … … 86 134 $target =~ s/debug/udeb/i; 87 135 $target =~ s/release/urel/i; 136 137 if (($platform =~ m/^gcce$/i) && ($ENV{SBS_HOME})) { 138 # Print a informative note in case suspected misuse is detected. 139 print "\nNote: You must use armv5 as platform when packaging gcce binaries built using symbian-sbsv2 mkspec.\n"; 140 } 88 141 } 89 142 … … 91 144 if (($pkgFileName =~ m|\.pkg$|i) && -r($pkgFileName)) 92 145 { 93 # If there are more arguments given, parse them as capabilities. 94 if (@ARGV) 95 { 96 @capabilitiesToSet = (); 97 while (@ARGV) 146 print ("\n"); 147 if ($justCheck) { 148 print ("Checking"); 149 } else { 150 print ("Patching"); 151 } 152 print (" package file and relevant binaries...\n"); 153 154 if (!$justCheck) { 155 # If there are more arguments given, parse them as capabilities. 156 if (@ARGV) 98 157 { 99 push (@capabilitiesToSet, pop(@ARGV)); 158 @capabilitiesSpecified = (); 159 while (@ARGV) 160 { 161 push (@capabilitiesSpecified, pop(@ARGV)); 162 } 100 163 } 101 164 } … … 105 168 106 169 my $tempPkgFileName = $pkgFileName."_@@TEMP@@"; 107 unlink($tempPkgFileName); 108 open (NEW_PKG, ">>".$tempPkgFileName); 170 171 if (!$justCheck) { 172 unlink($tempPkgFileName); 173 open (NEW_PKG, ">>".$tempPkgFileName); 174 } 109 175 open (PKG, "<".$pkgFileName); 110 176 111 my $manufacturerElseBlock = 0; 177 my $checkFailed = ""; 178 my $somethingPatched = ""; 112 179 113 180 # Parse each line. 114 181 while (<PKG>) 115 182 { 116 # Patch pkg UID117 183 my $line = $_; 118 184 my $newLine = $line; 119 if ($line =~ m/^\#.*\(0x[0-9|a-f|A-F]*\).*$/) 185 186 # Patch pkg UID if it's in protected range 187 if ($line =~ m/^\#.*\((0x[0-7][0-9a-fA-F]*)\).*$/) 120 188 { 121 $newLine =~ s/\(0x./\(0xE/; 122 } 123 124 # Patch embedded sis name and UID 125 if ($line =~ m/^@.*\.sis.*\(0x[0-9|a-f|A-F]*\).*$/) 126 { 127 $newLine =~ s/\(0x./\(0xE/; 128 if ($line !~ m/^.*_selfsigned.sis.*$/) 129 { 130 $newLine =~ s/\.sis/_selfsigned\.sis/i; 131 } 132 } 133 134 # Remove dependencies to known problem packages (i.e. packages that are likely to be patched, also) 135 # to reduce unnecessary error messages. 136 if ($line =~ m/^\(0x2002af5f\).*\{.*\}$/) 137 { 138 $newLine = "\n" 139 } 140 if ($line =~ m/^\(0x2001E61C\).*\{.*\}$/) 141 { 142 $newLine = "\n" 143 } 144 145 # Remove manufacturer ifdef 146 if ($line =~ m/^.*\(MANUFACTURER\)\=\(.*\).*$/) 147 { 148 $newLine = "\n"; 149 } 150 151 if ($line =~ m/^ELSEIF.*MANUFACTURER$/) 152 { 153 $manufacturerElseBlock = 1; 154 } 155 156 if ($manufacturerElseBlock eq 1) 157 { 158 $newLine = "\n"; 159 } 160 161 if ($line =~ m/^ENDIF.*MANUFACTURER$/) 162 { 163 $manufacturerElseBlock = 0; 164 } 165 166 print NEW_PKG $newLine; 167 168 chomp ($line); 189 my $oldUID = $1; 190 print ("$msgPrefix UID $oldUID is not compatible with self-signing!\n"); 191 192 if ($justCheck) { 193 $checkFailed = true; 194 } else { 195 my $newUID = $oldUID; 196 $newUID =~ s/0x./0xE/i; 197 $newLine =~ s/$oldUID/$newUID/; 198 print ("$msgPrefix Package UID changed to: $newUID.\n"); 199 $somethingPatched = true; 200 } 201 } 169 202 170 203 # If the line specifies a file, parse the source and destination locations. 171 if ($line =~ m| \"([^\"]+)\"\s*\-\s*\"([^\"]+)\"|)204 if ($line =~ m|^ *\"([^\"]+)\"\s*\-\s*\"([^\"]+)\"|) 172 205 { 173 206 my $sourcePath = $1; 174 my $destinationPath = $2;175 207 176 208 # If the given file is a binary, check the target and binary type (+ the actual filename) from its path. 177 if ($sourcePath =~ m: /epoc32/release/([^/]+)/(udeb|urel|\$\(TARGET\))/(\w+(\.dll|\.exe)):i)209 if ($sourcePath =~ m:\w+(\.dll|\.exe)$:i) 178 210 { 179 211 # Do preprocessing for template pkg, … … 185 217 } 186 218 187 push (@binaries, $sourcePath); 188 } 189 } 219 if ($justCheck) { 220 push (@binaries, $sourcePath); 221 } else { 222 # Change the source file name (but only if not already patched) 223 my $patchedSourcePath = $sourcePath; 224 if ($patchedSourcePath !~ m/_patched_caps/) 225 { 226 $newLine =~ s/(^.*)(\.dll|\.exe)(.*)(\.dll|\.exe)/$1_patched_caps$2$3$4/i; 227 $patchedSourcePath =~ s/(^.*)(\.dll|\.exe)/$1_patched_caps$2/i; 228 229 copy($sourcePath, $patchedSourcePath) or die "$sourcePath cannot be copied for patching."; 230 } 231 push (@binaries, $patchedSourcePath); 232 } 233 } 234 } 235 236 print NEW_PKG $newLine; 237 238 chomp ($line); 190 239 } 191 240 192 241 close (PKG); 193 close (NEW_PKG); 194 195 unlink($pkgFileName); 196 rename($tempPkgFileName, $pkgFileName); 197 242 if (!$justCheck) { 243 close (NEW_PKG); 244 245 unlink($pkgFileName); 246 rename($tempPkgFileName, $pkgFileName); 247 } 198 248 print ("\n"); 199 249 200 my $baseCommandToExecute = "elftran -vid 0x0 -capability \""; 201 if (@capabilitiesToSet) 202 { 203 $baseCommandToExecute .= join(" ", @capabilitiesToSet); 204 } 205 $baseCommandToExecute .= "\" "; 250 my $baseCommandToExecute = "${epocToolsDir}elftran -vid 0x0 -capability \"%s\" "; 206 251 207 252 # Actually set the capabilities of the listed binaries. … … 209 254 { 210 255 # Create the command line for setting the capabilities. 256 my ($binaryVolume, $binaryDirs, $binaryBaseName) = File::Spec->splitpath($binaryPath); 211 257 my $commandToExecute = $baseCommandToExecute; 258 my $executeNeeded = ""; 259 if (@capabilitiesSpecified) 260 { 261 $commandToExecute = sprintf($baseCommandToExecute, join(" ", @capabilitiesSpecified)); 262 $executeNeeded = true; 263 my $capString = join(" ", @capabilitiesSpecified); 264 print ("$msgPrefix Patching the the Vendor ID to 0 and the capabilities used to: \"$capString\" in \"$binaryBaseName\".\n"); 265 } else { 266 # Test which capabilities are present and then restrict them to the allowed set. 267 # This avoid raising the capabilities of apps that already have none. 268 my $dllCaps; 269 open($dllCaps, "${epocToolsDir}elftran -dump s $binaryPath |") or die ("ERROR: Could not execute elftran"); 270 my $capsFound = 0; 271 my $originalVid; 272 my @capabilitiesToSet; 273 my $capabilitiesToAllow = join(" ", @capabilitiesToAllow); 274 my @capabilitiesToDrop; 275 while (<$dllCaps>) { 276 if (/^Secure ID: ([0-7][0-9a-fA-F]*)$/) { 277 my $exeSid = $1; 278 if ($binaryBaseName =~ /\.exe$/) { 279 # Installer refuses to install protected executables in a self signed package, so abort if one is detected. 280 # We can't simply just patch the executable SID, as any registration resources executable uses will be linked to it via SID. 281 print ("$msgPrefix Executable with SID in the protected range (0x$exeSid) detected: \"$binaryBaseName\". A self-signed sis with protected executables is not supported.\n\n"); 282 $checkFailed = true; 283 } 284 } 285 if (/^Vendor ID: ([0-9a-fA-F]*)$/) { 286 $originalVid = "$1"; 287 } 288 if (!$capsFound) { 289 $capsFound = 1 if (/Capabilities:/); 290 } else { 291 $_ = trim($_); 292 if ($capabilitiesToAllow =~ /$_/) { 293 push(@capabilitiesToSet, $_); 294 if (Location =~ /$_/i) { 295 print ("$msgPrefix \"Location\" capability detected for binary: \"$binaryBaseName\". This capability is not self-signable for S60 3rd edition feature pack 1 devices, so installing this package on those devices will most likely not work.\n\n"); 296 } 297 } else { 298 push(@capabilitiesToDrop, $_); 299 } 300 } 301 } 302 close($dllCaps); 303 if ($originalVid !~ "00000000") { 304 print ("$msgPrefix Non-zero vendor ID (0x$originalVid) is incompatible with self-signed packages in \"$binaryBaseName\""); 305 if ($justCheck) { 306 print (".\n\n"); 307 $checkFailed = true; 308 } else { 309 print (", setting it to zero.\n\n"); 310 $executeNeeded = true; 311 } 312 } 313 if ($#capabilitiesToDrop) { 314 my $capsToDropStr = join("\", \"", @capabilitiesToDrop); 315 $capsToDropStr =~ s/\", \"$//; 316 317 if ($justCheck) { 318 print ("$msgPrefix The following capabilities used in \"$binaryBaseName\" are not compatible with a self-signed package: \"$capsToDropStr\".\n\n"); 319 $checkFailed = true; 320 } else { 321 if ($binaryBaseName =~ /\.exe$/) { 322 # While libraries often have capabilities they do not themselves need just to enable them to be loaded by wider variety of processes, 323 # executables are more likely to need every capability they have been assigned or they won't function correctly. 324 print ("$msgPrefix Executable with capabilities incompatible with self-signing detected: \"$binaryBaseName\". (Incompatible capabilities: \"$capsToDropStr\".) Reducing capabilities is only supported for libraries.\n"); 325 $checkFailed = true; 326 } else { 327 print ("$msgPrefix The following capabilities used in \"$binaryBaseName\" are not compatible with a self-signed package and will be removed: \"$capsToDropStr\".\n"); 328 $executeNeeded = true; 329 } 330 } 331 } 332 $commandToExecute = sprintf($baseCommandToExecute, join(" ", @capabilitiesToSet)); 333 } 212 334 $commandToExecute .= $binaryPath; 213 335 214 # Actually execute the elftran command to set the capabilities. 215 system ($commandToExecute." > NUL"); 216 print ("Executed ".$commandToExecute."\n"); 217 218 ## Create another command line to check that the set capabilities are correct. 219 #$commandToExecute = "elftran -dump s ".$binaryPath; 220 } 221 336 if ($executeNeeded) { 337 # Actually execute the elftran command to set the capabilities. 338 print ("\n"); 339 system ("$commandToExecute > $nullDevice"); 340 $somethingPatched = true; 341 } 342 } 343 344 if ($checkFailed) { 345 print ("\n"); 346 if ($justCheck) { 347 print ("$msgPrefix The package is not compatible with self-signing.\n"); 348 } else { 349 print ("$msgPrefix Unable to patch the package for self-singing.\n"); 350 } 351 print ("Use a proper developer certificate for signing this package.\n\n"); 352 exit(1); 353 } 354 355 if ($justCheck) { 356 print ("Package is compatible with self-signing.\n"); 357 } else { 358 if ($somethingPatched) { 359 print ("NOTE: A patched package may not work as expected due to reduced capabilities and other modifications,\n"); 360 print (" so it should not be used for any kind of Symbian signing or distribution!\n"); 361 print (" Use a proper certificate to avoid the need to patch the package.\n"); 362 } else { 363 print ("No patching was required!\n"); 364 } 365 } 222 366 print ("\n"); 367 } else { 368 Usage(); 223 369 } 224 370 }
Note:
See TracChangeset
for help on using the changeset viewer.