andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public
andre@0:  * License, v. 2.0. If a copy of the MPL was not distributed with this
andre@0:  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
andre@0: /* 
andre@0:  *  The following code handles the storage of PKCS 11 modules used by the
andre@0:  * NSS. This file is written to abstract away how the modules are
andre@0:  * stored so we can deside that later.
andre@0:  */
andre@0: #include "pkcs11i.h"
andre@0: #include "sdb.h"
andre@0: #include "prprf.h" 
andre@0: #include "prenv.h"
andre@0: #include "utilpars.h"
andre@0: 
andre@0: #define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; }
andre@0: 
andre@0: static void
andre@0: sftk_parseTokenFlags(char *tmp, sftk_token_parameters *parsed) { 
andre@0:     parsed->readOnly = NSSUTIL_ArgHasFlag("flags","readOnly",tmp);
andre@0:     parsed->noCertDB = NSSUTIL_ArgHasFlag("flags","noCertDB",tmp);
andre@0:     parsed->noKeyDB = NSSUTIL_ArgHasFlag("flags","noKeyDB",tmp);
andre@0:     parsed->forceOpen = NSSUTIL_ArgHasFlag("flags","forceOpen",tmp);
andre@0:     parsed->pwRequired = NSSUTIL_ArgHasFlag("flags","passwordRequired",tmp);
andre@0:     parsed->optimizeSpace = NSSUTIL_ArgHasFlag("flags","optimizeSpace",tmp);
andre@0:     return;
andre@0: }
andre@0: 
andre@0: static void
andre@0: sftk_parseFlags(char *tmp, sftk_parameters *parsed) { 
andre@0:     parsed->noModDB = NSSUTIL_ArgHasFlag("flags","noModDB",tmp);
andre@0:     parsed->readOnly = NSSUTIL_ArgHasFlag("flags","readOnly",tmp);
andre@0:     /* keep legacy interface working */
andre@0:     parsed->noCertDB = NSSUTIL_ArgHasFlag("flags","noCertDB",tmp);
andre@0:     parsed->forceOpen = NSSUTIL_ArgHasFlag("flags","forceOpen",tmp);
andre@0:     parsed->pwRequired = NSSUTIL_ArgHasFlag("flags","passwordRequired",tmp);
andre@0:     parsed->optimizeSpace = NSSUTIL_ArgHasFlag("flags","optimizeSpace",tmp);
andre@0:     return;
andre@0: }
andre@0: 
andre@0: static CK_RV
andre@0: sftk_parseTokenParameters(char *param, sftk_token_parameters *parsed) 
andre@0: {
andre@0:     int next;
andre@0:     char *tmp = NULL;
andre@0:     char *index;
andre@0:     index = NSSUTIL_ArgStrip(param);
andre@0: 
andre@0:     while (*index) {
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updatedir,"updateDir=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updCertPrefix,
andre@0: 						"updateCertPrefix=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updKeyPrefix,
andre@0: 						"updateKeyPrefix=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updateID,"updateID=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->certPrefix,"certPrefix=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyPrefix=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updtokdes,
andre@0: 						"updateTokenDescription=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,tmp,"minPWLen=", 
andre@0: 	   if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); tmp = NULL; })
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,tmp,"flags=", 
andre@0: 	   if(tmp) { sftk_parseTokenFlags(param,parsed); PORT_Free(tmp); 
andre@0: 		     tmp = NULL; })
andre@0: 	NSSUTIL_HANDLE_FINAL_ARG(index)
andre@0:    }
andre@0:    return CKR_OK;
andre@0: }
andre@0: 
andre@0: static void
andre@0: sftk_parseTokens(char *tokenParams, sftk_parameters *parsed)
andre@0: {
andre@0:     char *tokenIndex;
andre@0:     sftk_token_parameters *tokens = NULL;
andre@0:     int i=0,count = 0,next;
andre@0: 
andre@0:     if ((tokenParams == NULL) || (*tokenParams == 0))  return;
andre@0: 
andre@0:     /* first count the number of slots */
andre@0:     for (tokenIndex = NSSUTIL_ArgStrip(tokenParams); *tokenIndex;
andre@0: 	 tokenIndex = NSSUTIL_ArgStrip(NSSUTIL_ArgSkipParameter(tokenIndex))) {
andre@0: 	count++;
andre@0:     }
andre@0: 
andre@0:     /* get the data structures */
andre@0:     tokens = (sftk_token_parameters *) 
andre@0: 			PORT_ZAlloc(count*sizeof(sftk_token_parameters));
andre@0:     if (tokens == NULL) return;
andre@0: 
andre@0:     for (tokenIndex = NSSUTIL_ArgStrip(tokenParams), i = 0;
andre@0: 					*tokenIndex && i < count ; i++ ) {
andre@0: 	char *name;
andre@0: 	name = NSSUTIL_ArgGetLabel(tokenIndex,&next);
andre@0: 	tokenIndex += next;
andre@0: 
andre@0: 	tokens[i].slotID = NSSUTIL_ArgDecodeNumber(name);
andre@0:         tokens[i].readOnly = PR_FALSE;
andre@0: 	tokens[i].noCertDB = PR_FALSE;
andre@0: 	tokens[i].noKeyDB = PR_FALSE;
andre@0: 	if (!NSSUTIL_ArgIsBlank(*tokenIndex)) {
andre@0: 	    char *args = NSSUTIL_ArgFetchValue(tokenIndex,&next);
andre@0: 	    tokenIndex += next;
andre@0: 	    if (args) {
andre@0: 		sftk_parseTokenParameters(args,&tokens[i]);
andre@0: 		PORT_Free(args);
andre@0: 	    }
andre@0: 	}
andre@0: 	if (name) PORT_Free(name);
andre@0: 	tokenIndex = NSSUTIL_ArgStrip(tokenIndex);
andre@0:     }
andre@0:     parsed->token_count = i;
andre@0:     parsed->tokens = tokens;
andre@0:     return; 
andre@0: }
andre@0: 
andre@0: CK_RV
andre@0: sftk_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS) 
andre@0: {
andre@0:     int next;
andre@0:     char *tmp = NULL;
andre@0:     char *index;
andre@0:     char *certPrefix = NULL, *keyPrefix = NULL;
andre@0:     char *tokdes = NULL, *ptokdes = NULL, *pupdtokdes = NULL;
andre@0:     char *slotdes = NULL, *pslotdes = NULL;
andre@0:     char *fslotdes = NULL, *ftokdes = NULL;
andre@0:     char *minPW = NULL;
andre@0:     index = NSSUTIL_ArgStrip(param);
andre@0: 
andre@0:     PORT_Memset(parsed, 0, sizeof(sftk_parameters));
andre@0: 
andre@0:     while (*index) {
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->configdir,"configDir=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updatedir,"updateDir=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->updateID,"updateID=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->man,"manufacturerID=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;)
andre@0: 	/* constructed values, used so legacy interfaces still work */
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,certPrefix,"certPrefix=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,keyPrefix,"keyPrefix=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;)
andre@0:         NSSUTIL_HANDLE_STRING_ARG(index,ftokdes,"FIPSTokenDescription=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,pupdtokdes, "updateTokenDescription=",;)
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,minPW,"minPWLen=",;)
andre@0: 
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,tmp,"flags=", 
andre@0: 		if(tmp) { sftk_parseFlags(param,parsed); PORT_Free(tmp); 
andre@0: 			  tmp = NULL; })
andre@0: 	NSSUTIL_HANDLE_STRING_ARG(index,tmp,"tokens=", 
andre@0: 		if(tmp) { sftk_parseTokens(tmp,parsed); PORT_Free(tmp); 				  tmp = NULL; })
andre@0: 	NSSUTIL_HANDLE_FINAL_ARG(index)
andre@0:     }
andre@0:     if (parsed->tokens == NULL) {
andre@0: 	int  count = isFIPS ? 1 : 2;
andre@0: 	int  index = count-1;
andre@0: 	sftk_token_parameters *tokens = NULL;
andre@0: 
andre@0: 	tokens = (sftk_token_parameters *) 
andre@0: 			PORT_ZAlloc(count*sizeof(sftk_token_parameters));
andre@0: 	if (tokens == NULL) {
andre@0: 	    goto loser;
andre@0: 	}
andre@0: 	parsed->tokens = tokens;
andre@0:     	parsed->token_count = count;
andre@0: 	tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID;
andre@0: 	tokens[index].certPrefix = certPrefix;
andre@0: 	tokens[index].keyPrefix = keyPrefix;
andre@0: 	tokens[index].minPW = minPW ? atoi(minPW) : 0;
andre@0: 	tokens[index].readOnly = parsed->readOnly;
andre@0: 	tokens[index].noCertDB = parsed->noCertDB;
andre@0: 	tokens[index].noKeyDB = parsed->noCertDB;
andre@0: 	tokens[index].forceOpen = parsed->forceOpen;
andre@0: 	tokens[index].pwRequired = parsed->pwRequired;
andre@0: 	tokens[index].optimizeSpace = parsed->optimizeSpace;
andre@0: 	tokens[0].optimizeSpace = parsed->optimizeSpace;
andre@0: 	certPrefix = NULL;
andre@0: 	keyPrefix = NULL;
andre@0: 	if (isFIPS) {
andre@0: 	    tokens[index].tokdes = ftokdes;
andre@0: 	    tokens[index].updtokdes = pupdtokdes;
andre@0: 	    tokens[index].slotdes = fslotdes;
andre@0: 	    fslotdes = NULL;
andre@0: 	    ftokdes = NULL;
andre@0: 	    pupdtokdes = NULL;
andre@0: 	} else {
andre@0: 	    tokens[index].tokdes = ptokdes;
andre@0: 	    tokens[index].updtokdes = pupdtokdes;
andre@0: 	    tokens[index].slotdes = pslotdes;
andre@0: 	    tokens[0].slotID = NETSCAPE_SLOT_ID;
andre@0: 	    tokens[0].tokdes = tokdes;
andre@0: 	    tokens[0].slotdes = slotdes;
andre@0: 	    tokens[0].noCertDB = PR_TRUE;
andre@0: 	    tokens[0].noKeyDB = PR_TRUE;
andre@0: 	    pupdtokdes = NULL;
andre@0: 	    ptokdes = NULL;
andre@0: 	    pslotdes = NULL;
andre@0: 	    tokdes = NULL;
andre@0: 	    slotdes = NULL;
andre@0: 	}
andre@0:     }
andre@0: 
andre@0: loser:
andre@0:     FREE_CLEAR(certPrefix);
andre@0:     FREE_CLEAR(keyPrefix);
andre@0:     FREE_CLEAR(tokdes);
andre@0:     FREE_CLEAR(ptokdes);
andre@0:     FREE_CLEAR(pupdtokdes);
andre@0:     FREE_CLEAR(slotdes);
andre@0:     FREE_CLEAR(pslotdes);
andre@0:     FREE_CLEAR(fslotdes);
andre@0:     FREE_CLEAR(ftokdes);
andre@0:     FREE_CLEAR(minPW);
andre@0:     return CKR_OK;
andre@0: }
andre@0: 
andre@0: void
andre@0: sftk_freeParams(sftk_parameters *params)
andre@0: {
andre@0:     int i;
andre@0: 
andre@0:     for (i=0; i < params->token_count; i++) {
andre@0: 	FREE_CLEAR(params->tokens[i].configdir);
andre@0: 	FREE_CLEAR(params->tokens[i].certPrefix);
andre@0: 	FREE_CLEAR(params->tokens[i].keyPrefix);
andre@0: 	FREE_CLEAR(params->tokens[i].tokdes);
andre@0: 	FREE_CLEAR(params->tokens[i].slotdes);
andre@0: 	FREE_CLEAR(params->tokens[i].updatedir);
andre@0: 	FREE_CLEAR(params->tokens[i].updCertPrefix);
andre@0: 	FREE_CLEAR(params->tokens[i].updKeyPrefix);
andre@0: 	FREE_CLEAR(params->tokens[i].updateID);
andre@0: 	FREE_CLEAR(params->tokens[i].updtokdes);
andre@0:     }
andre@0: 
andre@0:     FREE_CLEAR(params->configdir);
andre@0:     FREE_CLEAR(params->secmodName);
andre@0:     FREE_CLEAR(params->man);
andre@0:     FREE_CLEAR(params->libdes); 
andre@0:     FREE_CLEAR(params->tokens);
andre@0:     FREE_CLEAR(params->updatedir);
andre@0:     FREE_CLEAR(params->updateID);
andre@0: }
andre@0: