1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/modutil/install.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,957 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "install.h" 1.9 +#include "install-ds.h" 1.10 +#include <prerror.h> 1.11 +#include <prlock.h> 1.12 +#include <prio.h> 1.13 +#include <prmem.h> 1.14 +#include <prprf.h> 1.15 +#include <prsystem.h> 1.16 +#include <prproces.h> 1.17 + 1.18 +#ifdef XP_UNIX 1.19 +/* for chmod */ 1.20 +#include <sys/types.h> 1.21 +#include <sys/stat.h> 1.22 +#endif 1.23 + 1.24 +/*extern "C" {*/ 1.25 +#include <jar.h> 1.26 +/*}*/ 1.27 + 1.28 +extern /*"C"*/ 1.29 +int Pk11Install_AddNewModule(char* moduleName, char* dllPath, 1.30 + unsigned long defaultMechanismFlags, 1.31 + unsigned long cipherEnableFlags); 1.32 +extern /*"C"*/ 1.33 +short Pk11Install_UserVerifyJar(JAR *jar, PRFileDesc *out, 1.34 + PRBool query); 1.35 +extern /*"C"*/ 1.36 +const char* mySECU_ErrorString(PRErrorCode errnum); 1.37 +extern 1.38 +int Pk11Install_yyparse(); 1.39 + 1.40 +#define INSTALL_METAINFO_TAG "Pkcs11_install_script" 1.41 +#define SCRIPT_TEMP_FILE "pkcs11inst.tmp" 1.42 +#define ROOT_MARKER "%root%" 1.43 +#define TEMP_MARKER "%temp%" 1.44 +#define PRINTF_ROOT_MARKER "%%root%%" 1.45 +#define TEMPORARY_DIRECTORY_NAME "pk11inst.dir" 1.46 +#define JAR_BASE_END (JAR_BASE+100) 1.47 + 1.48 +static PRLock* errorHandlerLock=NULL; 1.49 +static Pk11Install_ErrorHandler errorHandler=NULL; 1.50 +static char* PR_Strdup(const char* str); 1.51 +static int rm_dash_r (char *path); 1.52 +static int make_dirs(char *path, int file_perms); 1.53 +static int dir_perms(int perms); 1.54 + 1.55 +static Pk11Install_Error DoInstall(JAR *jar, const char *installDir, 1.56 + const char* tempDir, Pk11Install_Platform *platform, 1.57 + PRFileDesc *feedback, PRBool noverify); 1.58 + 1.59 +static char *errorString[]= { 1.60 + "Operation was successful", /* PK11_INSTALL_NO_ERROR */ 1.61 + "Directory \"%s\" does not exist", /* PK11_INSTALL_DIR_DOESNT_EXIST */ 1.62 + "File \"%s\" does not exist", /* PK11_INSTALL_FILE_DOESNT_EXIST */ 1.63 + "File \"%s\" is not readable", /* PK11_INSTALL_FILE_NOT_READABLE */ 1.64 + "%s", /* PK11_INSTALL_ERROR_STRING */ 1.65 + "Error in JAR file %s: %s", /* PK11_INSTALL_JAR_ERROR */ 1.66 + "No Pkcs11_install_script specified in JAR metainfo file", 1.67 + /* PK11_INSTALL_NO_INSTALLER_SCRIPT */ 1.68 + "Could not delete temporary file \"%s\"", 1.69 + /*PK11_INSTALL_DELETE_TEMP_FILE */ 1.70 + "Could not open temporary file \"%s\"", /*PK11_INSTALL_OPEN_SCRIPT_FILE*/ 1.71 + "%s: %s", /* PK11_INSTALL_SCRIPT_PARSE */ 1.72 + "Error in script: %s", 1.73 + "Unable to obtain system platform information", 1.74 + "Installer script has no information about the current platform (%s)", 1.75 + "Relative directory \"%s\" does not contain "PRINTF_ROOT_MARKER, 1.76 + "Module File \"%s\" not found", 1.77 + "Error occurred installing module \"%s\" into database", 1.78 + "Error extracting \"%s\" from JAR file: %s", 1.79 + "Directory \"%s\" is not writeable", 1.80 + "Could not create directory \"%s\"", 1.81 + "Could not remove directory \"%s\"", 1.82 + "Unable to execute \"%s\"", 1.83 + "Unable to wait for process \"%s\"", 1.84 + "\"%s\" returned error code %d", 1.85 + "User aborted operation", 1.86 + "Unspecified error" 1.87 +}; 1.88 + 1.89 +enum { 1.90 + INSTALLED_FILE_MSG=0, 1.91 + INSTALLED_MODULE_MSG, 1.92 + INSTALLER_SCRIPT_NAME, 1.93 + MY_PLATFORM_IS, 1.94 + USING_PLATFORM, 1.95 + PARSED_INSTALL_SCRIPT, 1.96 + EXEC_FILE_MSG, 1.97 + EXEC_SUCCESS, 1.98 + INSTALLATION_COMPLETE_MSG, 1.99 + USER_ABORT 1.100 +}; 1.101 + 1.102 +static char *msgStrings[] = { 1.103 + "Installed file %s to %s\n", 1.104 + "Installed module \"%s\" into module database\n", 1.105 + "Using installer script \"%s\"\n", 1.106 + "Current platform is %s\n", 1.107 + "Using installation parameters for platform %s\n", 1.108 + "Successfully parsed installation script\n", 1.109 + "Executing \"%s\"...\n", 1.110 + "\"%s\" executed successfully\n", 1.111 + "\nInstallation completed successfully\n", 1.112 + "\nAborting...\n" 1.113 +}; 1.114 + 1.115 +/************************************************************************** 1.116 + * S t r i n g N o d e 1.117 + */ 1.118 +typedef struct StringNode_str { 1.119 + char *str; 1.120 + struct StringNode_str* next; 1.121 +} StringNode; 1.122 + 1.123 +StringNode* StringNode_new() 1.124 +{ 1.125 + StringNode* new_this; 1.126 + new_this = (StringNode*)malloc(sizeof(StringNode)); 1.127 + new_this->str=NULL; 1.128 + new_this->next=NULL; 1.129 + return new_this; 1.130 +} 1.131 + 1.132 +void StringNode_delete(StringNode* s) 1.133 +{ 1.134 + if(s->str) { 1.135 + PR_Free(s->str); 1.136 + s->str=NULL; 1.137 + } 1.138 +} 1.139 + 1.140 +/************************************************************************* 1.141 + * S t r i n g L i s t 1.142 + */ 1.143 +typedef struct StringList_str { 1.144 + StringNode* head; 1.145 + StringNode* tail; 1.146 +} StringList; 1.147 + 1.148 +void StringList_new(StringList* list) 1.149 +{ 1.150 + list->head=NULL; 1.151 + list->tail=NULL; 1.152 +} 1.153 + 1.154 +void StringList_delete(StringList* list) 1.155 +{ 1.156 + StringNode *tmp; 1.157 + while(list->head) { 1.158 + tmp = list->head; 1.159 + list->head = list->head->next; 1.160 + StringNode_delete(tmp); 1.161 + } 1.162 +} 1.163 + 1.164 +void 1.165 +StringList_Append(StringList* list, char* str) 1.166 +{ 1.167 + if(!str) { 1.168 + return; 1.169 + } 1.170 + 1.171 + if(!list->tail) { 1.172 + /* This is the first element */ 1.173 + list->head = list->tail = StringNode_new(); 1.174 + } else { 1.175 + list->tail->next = StringNode_new(); 1.176 + list->tail = list->tail->next; 1.177 + } 1.178 + 1.179 + list->tail->str = PR_Strdup(str); 1.180 + list->tail->next = NULL; /* just to be sure */ 1.181 +} 1.182 + 1.183 +/************************************************************************** 1.184 + * 1.185 + * P k 1 1 I n s t a l l _ S e t E r r o r H a n d l e r 1.186 + * 1.187 + * Sets the error handler to be used by the library. Returns the current 1.188 + * error handler function. 1.189 + */ 1.190 +Pk11Install_ErrorHandler 1.191 +Pk11Install_SetErrorHandler(Pk11Install_ErrorHandler handler) 1.192 +{ 1.193 + Pk11Install_ErrorHandler old; 1.194 + 1.195 + if(!errorHandlerLock) { 1.196 + errorHandlerLock = PR_NewLock(); 1.197 + } 1.198 + 1.199 + PR_Lock(errorHandlerLock); 1.200 + 1.201 + old = errorHandler; 1.202 + errorHandler = handler; 1.203 + 1.204 + PR_Unlock(errorHandlerLock); 1.205 + 1.206 + return old; 1.207 +} 1.208 + 1.209 +/************************************************************************** 1.210 + * 1.211 + * P k 1 1 I n s t a l l _ I n i t 1.212 + * 1.213 + * Does initialization that otherwise would be done on the fly. Only 1.214 + * needs to be called by multithreaded apps, before they make any calls 1.215 + * to this library. 1.216 + */ 1.217 +void 1.218 +Pk11Install_Init() 1.219 +{ 1.220 + if(!errorHandlerLock) { 1.221 + errorHandlerLock = PR_NewLock(); 1.222 + } 1.223 +} 1.224 + 1.225 +/************************************************************************** 1.226 + * 1.227 + * P k 1 1 I n s t a l l _ R e l e a s e 1.228 + * 1.229 + * Releases static data structures used by the library. Don't use the 1.230 + * library after calling this, unless you call Pk11Install_Init() 1.231 + * first. This function doesn't have to be called at all unless you're 1.232 + * really anal about freeing memory before your program exits. 1.233 + */ 1.234 +void 1.235 +Pk11Install_Release() 1.236 +{ 1.237 + if(errorHandlerLock) { 1.238 + PR_Free(errorHandlerLock); 1.239 + errorHandlerLock = NULL; 1.240 + } 1.241 +} 1.242 + 1.243 +/************************************************************************* 1.244 + * 1.245 + * e r r o r 1.246 + * 1.247 + * Takes an error code and its arguments, creates the error string, 1.248 + * and sends the string to the handler function if it exists. 1.249 + */ 1.250 + 1.251 +#ifdef OSF1 1.252 +/* stdarg has already been pulled in from NSPR */ 1.253 +#undef va_start 1.254 +#undef va_end 1.255 +#undef va_arg 1.256 +#include <varargs.h> 1.257 +#else 1.258 +#include <stdarg.h> 1.259 +#endif 1.260 + 1.261 +#ifdef OSF1 1.262 +static void 1.263 +error(long va_alist, ...) 1.264 +#else 1.265 +static void 1.266 +error(Pk11Install_Error errcode, ...) 1.267 +#endif 1.268 +{ 1.269 + 1.270 + va_list ap; 1.271 + char *errstr; 1.272 + Pk11Install_ErrorHandler handler; 1.273 + 1.274 + if(!errorHandlerLock) { 1.275 + errorHandlerLock = PR_NewLock(); 1.276 + } 1.277 + 1.278 + PR_Lock(errorHandlerLock); 1.279 + 1.280 + handler = errorHandler; 1.281 + 1.282 + PR_Unlock(errorHandlerLock); 1.283 + 1.284 + if(handler) { 1.285 +#ifdef OSF1 1.286 + va_start(ap); 1.287 + errstr = PR_vsmprintf(errorString[va_arg(ap, Pk11Install_Error)], ap); 1.288 +#else 1.289 + va_start(ap, errcode); 1.290 + errstr = PR_vsmprintf(errorString[errcode], ap); 1.291 +#endif 1.292 + handler(errstr); 1.293 + PR_smprintf_free(errstr); 1.294 + va_end(ap); 1.295 + } 1.296 +} 1.297 + 1.298 +/************************************************************************* 1.299 + * 1.300 + * j a r _ c a l l b a c k 1.301 + */ 1.302 +static int 1.303 +jar_callback(int status, JAR *foo, const char *bar, char *pathname, 1.304 + char *errortext) { 1.305 + char *string; 1.306 + 1.307 + string = PR_smprintf("JAR error %d: %s in file %s\n", status, errortext, 1.308 + pathname); 1.309 + error(PK11_INSTALL_ERROR_STRING, string); 1.310 + PR_smprintf_free(string); 1.311 + return 0; 1.312 +} 1.313 + 1.314 +/************************************************************************* 1.315 + * 1.316 + * P k 1 1 I n s t a l l _ D o I n s t a l l 1.317 + * 1.318 + * jarFile is the path of a JAR in the PKCS #11 module JAR format. 1.319 + * installDir is the directory relative to which files will be 1.320 + * installed. 1.321 + */ 1.322 +Pk11Install_Error 1.323 +Pk11Install_DoInstall(char *jarFile, const char *installDir, 1.324 + const char *tempDir, PRFileDesc *feedback, short force, PRBool noverify) 1.325 +{ 1.326 + JAR *jar; 1.327 + char *installer; 1.328 + unsigned long installer_len; 1.329 + int status; 1.330 + Pk11Install_Error ret; 1.331 + PRBool made_temp_file; 1.332 + Pk11Install_Info installInfo; 1.333 + Pk11Install_Platform *platform; 1.334 + char* errMsg; 1.335 + char sysname[SYS_INFO_BUFFER_LENGTH], release[SYS_INFO_BUFFER_LENGTH], 1.336 + arch[SYS_INFO_BUFFER_LENGTH]; 1.337 + char *myPlatform; 1.338 + 1.339 + jar=NULL; 1.340 + ret = PK11_INSTALL_UNSPECIFIED; 1.341 + made_temp_file=PR_FALSE; 1.342 + errMsg=NULL; 1.343 + Pk11Install_Info_init(&installInfo); 1.344 + 1.345 + /* 1.346 + printf("Inside DoInstall, jarFile=%s, installDir=%s, tempDir=%s\n", 1.347 + jarFile, installDir, tempDir); 1.348 + */ 1.349 + 1.350 + /* 1.351 + * Check out jarFile and installDir for validity 1.352 + */ 1.353 + if( PR_Access(installDir, PR_ACCESS_EXISTS) != PR_SUCCESS ) { 1.354 + error(PK11_INSTALL_DIR_DOESNT_EXIST, installDir); 1.355 + return PK11_INSTALL_DIR_DOESNT_EXIST; 1.356 + } 1.357 + if(!tempDir) { 1.358 + tempDir = "."; 1.359 + } 1.360 + if( PR_Access(tempDir, PR_ACCESS_EXISTS) != PR_SUCCESS ) { 1.361 + error(PK11_INSTALL_DIR_DOESNT_EXIST, tempDir); 1.362 + return PK11_INSTALL_DIR_DOESNT_EXIST; 1.363 + } 1.364 + if( PR_Access(tempDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS ) { 1.365 + error(PK11_INSTALL_DIR_NOT_WRITEABLE, tempDir); 1.366 + return PK11_INSTALL_DIR_NOT_WRITEABLE; 1.367 + } 1.368 + if( (PR_Access(jarFile, PR_ACCESS_EXISTS) != PR_SUCCESS) ) { 1.369 + error(PK11_INSTALL_FILE_DOESNT_EXIST, jarFile); 1.370 + return PK11_INSTALL_FILE_DOESNT_EXIST; 1.371 + } 1.372 + if( PR_Access(jarFile, PR_ACCESS_READ_OK) != PR_SUCCESS ) { 1.373 + error(PK11_INSTALL_FILE_NOT_READABLE, jarFile); 1.374 + return PK11_INSTALL_FILE_NOT_READABLE; 1.375 + } 1.376 + 1.377 + /* 1.378 + * Extract the JAR file 1.379 + */ 1.380 + jar = JAR_new(); 1.381 + JAR_set_callback(JAR_CB_SIGNAL, jar, jar_callback); 1.382 + 1.383 + if(noverify) { 1.384 + status = JAR_pass_archive_unverified(jar, jarArchGuess, jarFile, "url"); 1.385 + } else { 1.386 + status = JAR_pass_archive(jar, jarArchGuess, jarFile, "url"); 1.387 + } 1.388 + if( (status < 0) || (jar->valid < 0) ) { 1.389 + if (status >= JAR_BASE && status <= JAR_BASE_END) { 1.390 + error(PK11_INSTALL_JAR_ERROR, jarFile, JAR_get_error(status)); 1.391 + } else { 1.392 + error(PK11_INSTALL_JAR_ERROR, jarFile, 1.393 + mySECU_ErrorString(PORT_GetError())); 1.394 + } 1.395 + ret=PK11_INSTALL_JAR_ERROR; 1.396 + goto loser; 1.397 + } 1.398 + /*printf("passed the archive\n");*/ 1.399 + 1.400 + /* 1.401 + * Show the user security information, allow them to abort or continue 1.402 + */ 1.403 + if( Pk11Install_UserVerifyJar(jar, PR_STDOUT, 1.404 + force?PR_FALSE:PR_TRUE) && !force) { 1.405 + if(feedback) { 1.406 + PR_fprintf(feedback, msgStrings[USER_ABORT]); 1.407 + } 1.408 + ret=PK11_INSTALL_USER_ABORT; 1.409 + goto loser; 1.410 + } 1.411 + 1.412 + /* 1.413 + * Get the name of the installation file 1.414 + */ 1.415 + if( JAR_get_metainfo(jar, NULL, INSTALL_METAINFO_TAG, (void**)&installer, 1.416 + (unsigned long*)&installer_len) ) { 1.417 + error(PK11_INSTALL_NO_INSTALLER_SCRIPT); 1.418 + ret=PK11_INSTALL_NO_INSTALLER_SCRIPT; 1.419 + goto loser; 1.420 + } 1.421 + if(feedback) { 1.422 + PR_fprintf(feedback, msgStrings[INSTALLER_SCRIPT_NAME], installer); 1.423 + } 1.424 + 1.425 + /* 1.426 + * Extract the installation file 1.427 + */ 1.428 + if( PR_Access(SCRIPT_TEMP_FILE, PR_ACCESS_EXISTS) == PR_SUCCESS) { 1.429 + if( PR_Delete(SCRIPT_TEMP_FILE) != PR_SUCCESS) { 1.430 + error(PK11_INSTALL_DELETE_TEMP_FILE, SCRIPT_TEMP_FILE); 1.431 + ret=PK11_INSTALL_DELETE_TEMP_FILE; 1.432 + goto loser; 1.433 + } 1.434 + } 1.435 + if(noverify) { 1.436 + status = JAR_extract(jar, installer, SCRIPT_TEMP_FILE); 1.437 + } else { 1.438 + status = JAR_verified_extract(jar, installer, SCRIPT_TEMP_FILE); 1.439 + } 1.440 + if(status) { 1.441 + if (status >= JAR_BASE && status <= JAR_BASE_END) { 1.442 + error(PK11_INSTALL_JAR_EXTRACT, installer, JAR_get_error(status)); 1.443 + } else { 1.444 + error(PK11_INSTALL_JAR_EXTRACT, installer, 1.445 + mySECU_ErrorString(PORT_GetError())); 1.446 + } 1.447 + ret = PK11_INSTALL_JAR_EXTRACT; 1.448 + goto loser; 1.449 + } else { 1.450 + made_temp_file = PR_TRUE; 1.451 + } 1.452 + 1.453 + /* 1.454 + * Parse the installation file into a syntax tree 1.455 + */ 1.456 + Pk11Install_FD = PR_Open(SCRIPT_TEMP_FILE, PR_RDONLY, 0); 1.457 + if(!Pk11Install_FD) { 1.458 + error(PK11_INSTALL_OPEN_SCRIPT_FILE, SCRIPT_TEMP_FILE); 1.459 + ret=PK11_INSTALL_OPEN_SCRIPT_FILE; 1.460 + goto loser; 1.461 + } 1.462 + if(Pk11Install_yyparse()) { 1.463 + error(PK11_INSTALL_SCRIPT_PARSE, installer, 1.464 + Pk11Install_yyerrstr ? Pk11Install_yyerrstr : ""); 1.465 + ret=PK11_INSTALL_SCRIPT_PARSE; 1.466 + goto loser; 1.467 + } 1.468 + 1.469 +#if 0 1.470 + /* for debugging */ 1.471 + Pk11Install_valueList->Print(0); 1.472 +#endif 1.473 + 1.474 + /* 1.475 + * From the syntax tree, build a semantic structure 1.476 + */ 1.477 + errMsg = Pk11Install_Info_Generate(&installInfo,Pk11Install_valueList); 1.478 + if(errMsg) { 1.479 + error(PK11_INSTALL_SEMANTIC, errMsg); 1.480 + ret=PK11_INSTALL_SEMANTIC; 1.481 + goto loser; 1.482 + } 1.483 +#if 0 1.484 + installInfo.Print(0); 1.485 +#endif 1.486 + 1.487 + if(feedback) { 1.488 + PR_fprintf(feedback, msgStrings[PARSED_INSTALL_SCRIPT]); 1.489 + } 1.490 + 1.491 + /* 1.492 + * Figure out which platform to use 1.493 + */ 1.494 + { 1.495 + sysname[0] = release[0] = arch[0] = '\0'; 1.496 + 1.497 + if( (PR_GetSystemInfo(PR_SI_SYSNAME, sysname, SYS_INFO_BUFFER_LENGTH) 1.498 + != PR_SUCCESS) || 1.499 + (PR_GetSystemInfo(PR_SI_RELEASE, release, SYS_INFO_BUFFER_LENGTH) 1.500 + != PR_SUCCESS) || 1.501 + (PR_GetSystemInfo(PR_SI_ARCHITECTURE, arch, SYS_INFO_BUFFER_LENGTH) 1.502 + != PR_SUCCESS) ) { 1.503 + error(PK11_INSTALL_SYSINFO); 1.504 + ret=PK11_INSTALL_SYSINFO; 1.505 + goto loser; 1.506 + } 1.507 + myPlatform = PR_smprintf("%s:%s:%s", sysname, release, arch); 1.508 + platform = Pk11Install_Info_GetBestPlatform(&installInfo,myPlatform); 1.509 + if(!platform) { 1.510 + error(PK11_INSTALL_NO_PLATFORM, myPlatform); 1.511 + PR_smprintf_free(myPlatform); 1.512 + ret=PK11_INSTALL_NO_PLATFORM; 1.513 + goto loser; 1.514 + } 1.515 + if(feedback) { 1.516 + PR_fprintf(feedback, msgStrings[MY_PLATFORM_IS], myPlatform); 1.517 + PR_fprintf(feedback, msgStrings[USING_PLATFORM], 1.518 + Pk11Install_PlatformName_GetString(&platform->name)); 1.519 + } 1.520 + PR_smprintf_free(myPlatform); 1.521 + } 1.522 + 1.523 + /* Run the install for that platform */ 1.524 + ret = DoInstall(jar, installDir, tempDir, platform, feedback, noverify); 1.525 + if(ret) { 1.526 + goto loser; 1.527 + } 1.528 + 1.529 + ret = PK11_INSTALL_SUCCESS; 1.530 +loser: 1.531 + if(Pk11Install_valueList) { 1.532 + Pk11Install_ValueList_delete(Pk11Install_valueList); 1.533 + PR_Free(Pk11Install_valueList); 1.534 + Pk11Install_valueList = NULL; 1.535 + } 1.536 + if(jar) { 1.537 + JAR_destroy(jar); 1.538 + } 1.539 + if(made_temp_file) { 1.540 + PR_Delete(SCRIPT_TEMP_FILE); 1.541 + } 1.542 + if(errMsg) { 1.543 + PR_smprintf_free(errMsg); 1.544 + } 1.545 + return ret; 1.546 +} 1.547 + 1.548 +/* 1.549 +///////////////////////////////////////////////////////////////////////// 1.550 +// actually run the installation, copying files to and fro 1.551 +*/ 1.552 +static Pk11Install_Error 1.553 +DoInstall(JAR *jar, const char *installDir, const char *tempDir, 1.554 + Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify) 1.555 +{ 1.556 + Pk11Install_File *file; 1.557 + Pk11Install_Error ret; 1.558 + char *reldir; 1.559 + char *dest; 1.560 + char *modDest; 1.561 + char *cp; 1.562 + int i; 1.563 + int status; 1.564 + char *tempname, *temp; 1.565 + StringList executables; 1.566 + StringNode *execNode; 1.567 + PRProcessAttr *attr; 1.568 + PRProcess *proc; 1.569 + char *argv[2]; 1.570 + char *envp[1]; 1.571 + int errcode; 1.572 + 1.573 + ret=PK11_INSTALL_UNSPECIFIED; 1.574 + reldir=NULL; 1.575 + dest=NULL; 1.576 + modDest=NULL; 1.577 + tempname=NULL; 1.578 + 1.579 + StringList_new(&executables); 1.580 + /* 1.581 + // Create Temporary directory 1.582 + */ 1.583 + tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME); 1.584 + if( PR_Access(tempname, PR_ACCESS_EXISTS)==PR_SUCCESS ) { 1.585 + /* Left over from previous run? Delete it. */ 1.586 + rm_dash_r(tempname); 1.587 + } 1.588 + if(PR_MkDir(tempname, 0700) != PR_SUCCESS) { 1.589 + error(PK11_INSTALL_CREATE_DIR, tempname); 1.590 + ret = PK11_INSTALL_CREATE_DIR; 1.591 + goto loser; 1.592 + } 1.593 + 1.594 + /* 1.595 + // Install all the files 1.596 + */ 1.597 + for(i=0; i < platform->numFiles; i++) { 1.598 + file = &platform->files[i]; 1.599 + 1.600 + if(file->relativePath) { 1.601 + PRBool foundMarker = PR_FALSE; 1.602 + reldir = PR_Strdup(file->relativePath); 1.603 + 1.604 + /* Replace all the markers with the directories for which they stand */ 1.605 + while(1) { 1.606 + if( (cp=PL_strcasestr(reldir, ROOT_MARKER)) ) { 1.607 + /* Has a %root% marker */ 1.608 + *cp = '\0'; 1.609 + temp = PR_smprintf("%s%s%s", reldir, installDir, 1.610 + cp+strlen(ROOT_MARKER)); 1.611 + PR_Free(reldir); 1.612 + reldir = temp; 1.613 + foundMarker = PR_TRUE; 1.614 + } else if( (cp = PL_strcasestr(reldir, TEMP_MARKER)) ) { 1.615 + /* Has a %temp% marker */ 1.616 + *cp = '\0'; 1.617 + temp = PR_smprintf("%s%s%s", reldir, tempname, 1.618 + cp+strlen(TEMP_MARKER)); 1.619 + PR_Free(reldir); 1.620 + reldir = temp; 1.621 + foundMarker = PR_TRUE; 1.622 + } else { 1.623 + break; 1.624 + } 1.625 + } 1.626 + if(!foundMarker) { 1.627 + /* Has no markers...this isn't really a relative directory */ 1.628 + error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath); 1.629 + ret = PK11_INSTALL_BOGUS_REL_DIR; 1.630 + goto loser; 1.631 + } 1.632 + dest = reldir; 1.633 + reldir = NULL; 1.634 + } else if(file->absolutePath) { 1.635 + dest = PR_Strdup(file->absolutePath); 1.636 + } 1.637 + 1.638 + /* Remember if this is the module file, we'll need to add it later */ 1.639 + if(i == platform->modFile) { 1.640 + modDest = PR_Strdup(dest); 1.641 + } 1.642 + 1.643 + /* Remember is this is an executable, we'll need to run it later */ 1.644 + if(file->executable) { 1.645 + StringList_Append(&executables,dest); 1.646 + /*executables.Append(dest);*/ 1.647 + } 1.648 + 1.649 + /* Make sure the directory we are targetting exists */ 1.650 + if( make_dirs(dest, file->permissions) ) { 1.651 + ret=PK11_INSTALL_CREATE_DIR; 1.652 + goto loser; 1.653 + } 1.654 + 1.655 + /* Actually extract the file onto the filesystem */ 1.656 + if(noverify) { 1.657 + status = JAR_extract(jar, (char*)file->jarPath, dest); 1.658 + } else { 1.659 + status = JAR_verified_extract(jar, (char*)file->jarPath, dest); 1.660 + } 1.661 + if(status) { 1.662 + if (status >= JAR_BASE && status <= JAR_BASE_END) { 1.663 + error(PK11_INSTALL_JAR_EXTRACT, file->jarPath, 1.664 + JAR_get_error(status)); 1.665 + } else { 1.666 + error(PK11_INSTALL_JAR_EXTRACT, file->jarPath, 1.667 + mySECU_ErrorString(PORT_GetError())); 1.668 + } 1.669 + ret=PK11_INSTALL_JAR_EXTRACT; 1.670 + goto loser; 1.671 + } 1.672 + if(feedback) { 1.673 + PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG], 1.674 + file->jarPath, dest); 1.675 + } 1.676 + 1.677 + /* no NSPR command to change permissions? */ 1.678 +#ifdef XP_UNIX 1.679 + chmod(dest, file->permissions); 1.680 +#endif 1.681 + 1.682 + /* Memory clean-up tasks */ 1.683 + if(reldir) { 1.684 + PR_Free(reldir); 1.685 + reldir = NULL; 1.686 + } 1.687 + if(dest) { 1.688 + PR_Free(dest); 1.689 + dest = NULL; 1.690 + } 1.691 + } 1.692 + /* Make sure we found the module file */ 1.693 + if(!modDest) { 1.694 + /* Internal problem here, since every platform is supposed to have 1.695 + a module file */ 1.696 + error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName); 1.697 + ret=PK11_INSTALL_NO_MOD_FILE; 1.698 + goto loser; 1.699 + } 1.700 + 1.701 + /* 1.702 + // Execute any executable files 1.703 + */ 1.704 + { 1.705 + argv[1] = NULL; 1.706 + envp[0] = NULL; 1.707 + for(execNode = executables.head; execNode; execNode = execNode->next) { 1.708 + attr = PR_NewProcessAttr(); 1.709 + argv[0] = PR_Strdup(execNode->str); 1.710 + 1.711 + /* Announce our intentions */ 1.712 + if(feedback) { 1.713 + PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str); 1.714 + } 1.715 + 1.716 + /* start the process */ 1.717 + if( !(proc=PR_CreateProcess(execNode->str, argv, envp, attr)) ) { 1.718 + PR_Free(argv[0]); 1.719 + PR_DestroyProcessAttr(attr); 1.720 + error(PK11_INSTALL_EXEC_FILE, execNode->str); 1.721 + ret=PK11_INSTALL_EXEC_FILE; 1.722 + goto loser; 1.723 + } 1.724 + 1.725 + /* wait for it to finish */ 1.726 + if( PR_WaitProcess(proc, &errcode) != PR_SUCCESS) { 1.727 + PR_Free(argv[0]); 1.728 + PR_DestroyProcessAttr(attr); 1.729 + error(PK11_INSTALL_WAIT_PROCESS, execNode->str); 1.730 + ret=PK11_INSTALL_WAIT_PROCESS; 1.731 + goto loser; 1.732 + } 1.733 + 1.734 + /* What happened? */ 1.735 + if(errcode) { 1.736 + /* process returned an error */ 1.737 + error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode); 1.738 + } else if(feedback) { 1.739 + /* process ran successfully */ 1.740 + PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str); 1.741 + } 1.742 + 1.743 + PR_Free(argv[0]); 1.744 + PR_DestroyProcessAttr(attr); 1.745 + } 1.746 + } 1.747 + 1.748 + /* 1.749 + // Add the module 1.750 + */ 1.751 + status = Pk11Install_AddNewModule((char*)platform->moduleName, 1.752 + (char*)modDest, platform->mechFlags, platform->cipherFlags ); 1.753 + 1.754 + if(status != SECSuccess) { 1.755 + error(PK11_INSTALL_ADD_MODULE, platform->moduleName); 1.756 + ret=PK11_INSTALL_ADD_MODULE; 1.757 + goto loser; 1.758 + } 1.759 + if(feedback) { 1.760 + PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG], 1.761 + platform->moduleName); 1.762 + } 1.763 + 1.764 + if(feedback) { 1.765 + PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]); 1.766 + } 1.767 + 1.768 + ret = PK11_INSTALL_SUCCESS; 1.769 + 1.770 +loser: 1.771 + if(reldir) { 1.772 + PR_Free(reldir); 1.773 + } 1.774 + if(dest) { 1.775 + PR_Free(dest); 1.776 + } 1.777 + if(modDest) { 1.778 + PR_Free(modDest); 1.779 + } 1.780 + if(tempname) { 1.781 + PRFileInfo info; 1.782 + if(PR_GetFileInfo(tempname, &info) == PR_SUCCESS) { 1.783 + if(info.type == PR_FILE_DIRECTORY) { 1.784 + /* Recursively remove temporary directory */ 1.785 + if(rm_dash_r(tempname)) { 1.786 + error(PK11_INSTALL_REMOVE_DIR, 1.787 + tempname); 1.788 + ret=PK11_INSTALL_REMOVE_DIR; 1.789 + } 1.790 + 1.791 + } 1.792 + } 1.793 + PR_Free(tempname); 1.794 + } 1.795 + StringList_delete(&executables); 1.796 + return ret; 1.797 +} 1.798 + 1.799 +/* 1.800 +////////////////////////////////////////////////////////////////////////// 1.801 +*/ 1.802 +static char* 1.803 +PR_Strdup(const char* str) 1.804 +{ 1.805 + char *tmp = (char*) PR_Malloc(strlen(str)+1); 1.806 + strcpy(tmp, str); 1.807 + return tmp; 1.808 +} 1.809 + 1.810 +/* 1.811 + * r m _ d a s h _ r 1.812 + * 1.813 + * Remove a file, or a directory recursively. 1.814 + * 1.815 + */ 1.816 +static int 1.817 +rm_dash_r (char *path) 1.818 +{ 1.819 + PRDir *dir; 1.820 + PRDirEntry *entry; 1.821 + PRFileInfo fileinfo; 1.822 + char filename[240]; 1.823 + 1.824 + if(PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) { 1.825 + /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/ 1.826 + return -1; 1.827 + } 1.828 + if(fileinfo.type == PR_FILE_DIRECTORY) { 1.829 + 1.830 + dir = PR_OpenDir(path); 1.831 + if(!dir) { 1.832 + return -1; 1.833 + } 1.834 + 1.835 + /* Recursively delete all entries in the directory */ 1.836 + while((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) { 1.837 + sprintf(filename, "%s/%s", path, entry->name); 1.838 + if(rm_dash_r(filename)) return -1; 1.839 + } 1.840 + 1.841 + if(PR_CloseDir(dir) != PR_SUCCESS) { 1.842 + return -1; 1.843 + } 1.844 + 1.845 + /* Delete the directory itself */ 1.846 + if(PR_RmDir(path) != PR_SUCCESS) { 1.847 + return -1; 1.848 + } 1.849 + } else { 1.850 + if(PR_Delete(path) != PR_SUCCESS) { 1.851 + return -1; 1.852 + } 1.853 + } 1.854 + return 0; 1.855 +} 1.856 + 1.857 +/*************************************************************************** 1.858 + * 1.859 + * m a k e _ d i r s 1.860 + * 1.861 + * Ensure that the directory portion of the path exists. This may require 1.862 + * making the directory, and its parent, and its parent's parent, etc. 1.863 + */ 1.864 +static int 1.865 +make_dirs(char *path, int file_perms) 1.866 +{ 1.867 + char *Path; 1.868 + char *start; 1.869 + char *sep; 1.870 + int ret = 0; 1.871 + PRFileInfo info; 1.872 + 1.873 + if(!path) { 1.874 + return 0; 1.875 + } 1.876 + 1.877 + Path = PR_Strdup(path); 1.878 + start = strpbrk(Path, "/\\"); 1.879 + if(!start) { 1.880 + return 0; 1.881 + } 1.882 + start++; /* start right after first slash */ 1.883 + 1.884 + /* Each time through the loop add one more directory. */ 1.885 + while( (sep=strpbrk(start, "/\\")) ) { 1.886 + *sep = '\0'; 1.887 + 1.888 + if( PR_GetFileInfo(Path, &info) != PR_SUCCESS) { 1.889 + /* No such dir, we have to create it */ 1.890 + if( PR_MkDir(Path, dir_perms(file_perms)) != PR_SUCCESS) { 1.891 + error(PK11_INSTALL_CREATE_DIR, Path); 1.892 + ret = PK11_INSTALL_CREATE_DIR; 1.893 + goto loser; 1.894 + } 1.895 + } else { 1.896 + /* something exists by this name, make sure it's a directory */ 1.897 + if( info.type != PR_FILE_DIRECTORY ) { 1.898 + error(PK11_INSTALL_CREATE_DIR, Path); 1.899 + ret = PK11_INSTALL_CREATE_DIR; 1.900 + goto loser; 1.901 + } 1.902 + } 1.903 + 1.904 + /* If this is the lowest directory level, make sure it is writeable */ 1.905 + if(!strpbrk(sep+1, "/\\")) { 1.906 + if( PR_Access(Path, PR_ACCESS_WRITE_OK)!=PR_SUCCESS) { 1.907 + error(PK11_INSTALL_DIR_NOT_WRITEABLE, Path); 1.908 + ret = PK11_INSTALL_DIR_NOT_WRITEABLE; 1.909 + goto loser; 1.910 + } 1.911 + } 1.912 + 1.913 + start = sep+1; /* start after the next slash */ 1.914 + *sep = '/'; 1.915 + } 1.916 + 1.917 +loser: 1.918 + PR_Free(Path); 1.919 + return ret; 1.920 +} 1.921 + 1.922 +/************************************************************************* 1.923 + * d i r _ p e r m s 1.924 + * 1.925 + * Guesses the desired permissions on a directory based on the permissions 1.926 + * of a file that will be stored in it. Give read, write, and 1.927 + * execute to the owner (so we can create the file), read and 1.928 + * execute to anyone who has read permissions on the file, and write 1.929 + * to anyone who has write permissions on the file. 1.930 + */ 1.931 +static int 1.932 +dir_perms(int perms) 1.933 +{ 1.934 + int ret = 0; 1.935 + 1.936 + /* owner */ 1.937 + ret |= 0700; 1.938 + 1.939 + /* group */ 1.940 + if(perms & 0040) { 1.941 + /* read on the file -> read and execute on the directory */ 1.942 + ret |= 0050; 1.943 + } 1.944 + if(perms & 0020) { 1.945 + /* write on the file -> write on the directory */ 1.946 + ret |= 0020; 1.947 + } 1.948 + 1.949 + /* others */ 1.950 + if(perms & 0004) { 1.951 + /* read on the file -> read and execute on the directory */ 1.952 + ret |= 0005; 1.953 + } 1.954 + if(perms & 0002) { 1.955 + /* write on the file -> write on the directory */ 1.956 + ret |= 0002; 1.957 + } 1.958 + 1.959 + return ret; 1.960 +}