예제 #1
0
파일: shvfy.c 프로젝트: MekliCZ/positron
static char *
mkCheckFileName(const char *libName)
{
    int ln_len = PORT_Strlen(libName);
    char *output = PORT_Alloc(ln_len+sizeof(SGN_SUFFIX));
    int index = ln_len + 1 - sizeof("."SHLIB_SUFFIX);

    if ((index > 0) &&
        (PORT_Strncmp(&libName[index],
                        "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
        ln_len = index;
    }
    PORT_Memcpy(output,libName,ln_len);
    PORT_Memcpy(&output[ln_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
    return output;
}
예제 #2
0
// nickname_collision
// what to do when the nickname collides with one already in the db.
// Based on P12U_NicknameCollisionCallback from nss/cmd/pk12util/pk12util.c
SECItem* PR_CALLBACK
nickname_collision(SECItem *old_nick, PRBool *cancel, void *wincx)
{
    char           *nick     = NULL;
    SECItem        *ret_nick = NULL;
    CERTCertificate* cert    = (CERTCertificate*)wincx;

    if (!cancel || !cert) {
        // pk12util calls this error user cancelled?
        return NULL;
    }

    if (!old_nick)
        VLOG(1) << "no nickname for cert in PKCS12 file.";

    nick = CERT_MakeCANickname(cert);
    if (!nick) {
        return NULL;
    }

    if(old_nick && old_nick->data && old_nick->len &&
            PORT_Strlen(nick) == old_nick->len &&
            !PORT_Strncmp((char *)old_nick->data, nick, old_nick->len)) {
        PORT_Free(nick);
        PORT_SetError(SEC_ERROR_IO);
        return NULL;
    }

    VLOG(1) << "using nickname " << nick;
    ret_nick = PORT_ZNew(SECItem);
    if(ret_nick == NULL) {
        PORT_Free(nick);
        return NULL;
    }

    ret_nick->data = (unsigned char *)nick;
    ret_nick->len = PORT_Strlen(nick);

    return ret_nick;
}
예제 #3
0
파일: lginit.c 프로젝트: Jar-win/Waterfox
const char *
lg_EvaluateConfigDir(const char *configdir,char **appName)
{
    if (PORT_Strncmp(configdir, MULTIACCESS, sizeof(MULTIACCESS)-1) == 0) {
	char *cdir;

	*appName = PORT_Strdup(configdir+sizeof(MULTIACCESS)-1);
	if (*appName == NULL) {
	    return configdir;
	}
	cdir = *appName;
	while (*cdir && *cdir != ':') {
	    cdir++;
	}
	if (*cdir == ':') {
	   *cdir = 0;
	   cdir++;
	}
	configdir = cdir;
    }
    return configdir;
}
예제 #4
0
char *
SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
{
  char* phrases, *phrase;
  PRFileDesc *fd;
  int32_t nb;
  char *pwFile = arg;
  int i;
  const long maxPwdFileSize = 4096;
  char* tokenName = NULL;
  int tokenLen = 0;

  if (!pwFile)
    return 0;

  if (retry) {
    return 0;  /* no good retrying - the files contents will be the same */
  }

  phrases = PORT_ZAlloc(maxPwdFileSize);

  if (!phrases) {
    return 0; /* out of memory */
  }

  fd = PR_Open(pwFile, PR_RDONLY, 0);
  if (!fd) {
    fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
    PORT_Free(phrases);
    return NULL;
  }

  nb = PR_Read(fd, phrases, maxPwdFileSize);

  PR_Close(fd);

  if (nb == 0) {
    fprintf(stderr,"password file contains no data\n");
    PORT_Free(phrases);
    return NULL;
  }

  if (slot) {
    tokenName = PK11_GetTokenName(slot);
    if (tokenName) {
      tokenLen = PORT_Strlen(tokenName);
    }
  }
  i = 0;
  do
  {
    int startphrase = i;
    int phraseLen;

    /* handle the Windows EOL case */
    while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
    /* terminate passphrase */
    phrases[i++] = '\0';
    /* clean up any EOL before the start of the next passphrase */
    while ( (i<nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
      phrases[i++] = '\0';
    }
    /* now analyze the current passphrase */
    phrase = &phrases[startphrase];
    if (!tokenName)
      break;
    if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue;
    phraseLen = PORT_Strlen(phrase);
    if (phraseLen < (tokenLen+1)) continue;
    if (phrase[tokenLen] != ':') continue;
    phrase = &phrase[tokenLen+1];
    break;

  } while (i<nb);

  phrase = PORT_Strdup((char*)phrase);
  PORT_Free(phrases);
  return phrase;
}
예제 #5
0
파일: sftkmod.c 프로젝트: jianglu/v8monkey
/*
 * Add a module to the Data base 
 */
SECStatus
sftkdb_AddSecmodDB(SDBType dbType, const char *appName, 
		   const char *filename, const char *dbname, 
		   char *module, PRBool rw)
{
    FILE *fd = NULL;
    char *block = NULL;
    PRBool libFound = PR_FALSE;

    if (dbname == NULL) {
	return SECFailure;
    }

    if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
	return sftkdbCall_AddSecmodDB(appName, filename, dbname, module, rw);
    }

    /* can't write to a read only module */
    if (!rw) {
	return SECFailure;
    }

    /* remove the previous version if it exists */
    (void) sftkdb_DeleteSecmodDB(dbType, appName, filename, dbname, module, rw);

#ifdef WINCE
    fd = fopen(dbname, "a+");
#else
    fd = lfopen(dbname, "a+", O_CREAT|O_RDWR|O_APPEND);
#endif
    if (fd == NULL) {
	return SECFailure;
    }
    module = sftk_argStrip(module);
    while (*module) {
	int count;
	char *keyEnd = PORT_Strchr(module,'=');
	char *value;

	if (PORT_Strncmp(module, "library=", 8) == 0) {
	   libFound=PR_TRUE;
	}
	if (keyEnd == NULL) {
	    block = sftkdb_DupCat(block, module);
	    break;
	}
	block = sftkdb_DupnCat(block, module, keyEnd-module+1);
	if (block == NULL) { goto loser; }
	value = sftk_argFetchValue(&keyEnd[1], &count);
	if (value) {
	    block = sftkdb_DupCat(block, sftk_argStrip(value));
	    PORT_Free(value);
	}
	if (block == NULL) { goto loser; }
	block = sftkdb_DupnCat(block, "\n", 1);
	module = keyEnd + 1 + count;
	module = sftk_argStrip(module);
    }
    if (block) {
	if (!libFound) {
	    fprintf(fd,"library=\n");
	}
	fwrite(block, PORT_Strlen(block), 1, fd);
	fprintf(fd,"\n");
	PORT_Free(block);
	block = NULL;
    }
    fclose(fd);
    return SECSuccess;

loser:
    PORT_Free(block);
    fclose(fd);
    return SECFailure;
}
예제 #6
0
파일: sftkmod.c 프로젝트: jianglu/v8monkey
/*
 * Delete a module from the Data Base
 */
SECStatus
sftkdb_DeleteSecmodDB(SDBType dbType, const char *appName, 
		      const char *filename, const char *dbname, 
		      char *args, PRBool rw)
{
    /* SHDB_FIXME implement */
    FILE *fd = NULL;
    FILE *fd2 = NULL;
    char line[MAX_LINE_LENGTH];
    char *dbname2 = NULL;
    char *block = NULL;
    char *name = NULL;
    char *lib = NULL;
    int name_len, lib_len;
    PRBool skip = PR_FALSE;
    PRBool found = PR_FALSE;

    if (dbname == NULL) {
	return SECFailure;
    }

    if ((dbType == SDB_LEGACY) || (dbType == SDB_MULTIACCESS)) {
	return sftkdbCall_DeleteSecmodDB(appName, filename, dbname, args, rw);
    }

    if (!rw) {
	return SECFailure;
    }

    dbname2 = strdup(dbname);
    if (dbname2 == NULL) goto loser;
    dbname2[strlen(dbname)-1]++;

    /* do we really want to use streams here */
    fd = fopen(dbname, "r");
    if (fd == NULL) goto loser;
#ifdef WINCE
    fd2 = fopen(dbname2, "w+");
#else
    fd2 = lfopen(dbname2, "w+", O_CREAT|O_RDWR|O_TRUNC);
#endif
    if (fd2 == NULL) goto loser;

    name = sftk_argGetParamValue("name",args);
    if (name) {
	name_len = PORT_Strlen(name);
    }
    lib = sftk_argGetParamValue("library",args);
    if (lib) {
	lib_len = PORT_Strlen(lib);
    }


    /*
     * the following loop takes line separated config files and collapses
     * the lines to a single string, escaping and quoting as necessary.
     */
    /* loop state variables */
    block = NULL;
    skip = PR_FALSE;
    while (fgets(line, sizeof(line), fd) != NULL) { 
	/* If we are processing a block (we haven't hit a blank line yet */
	if (*line != '\n') {
	    /* skip means we are in the middle of a block we are deleting */
	    if (skip) {
		continue;
	    }
	    /* if we haven't found the block yet, check to see if this block
	     * matches our requirements */
	    if (!found && ((name && (PORT_Strncasecmp(line,"name=",5) == 0) &&
		 (PORT_Strncmp(line+5,name,name_len) == 0))  ||
	        (lib && (PORT_Strncasecmp(line,"library=",8) == 0) &&
		 (PORT_Strncmp(line+8,lib,lib_len) == 0)))) {

		/* yup, we don't need to save any more data, */
		PORT_Free(block);
		block=NULL;
		/* we don't need to collect more of this block */
		skip = PR_TRUE;
		/* we don't need to continue searching for the block */
		found =PR_TRUE;
		continue;
	    }
	    /* not our match, continue to collect data in this block */
	    block = sftkdb_DupCat(block,line);
	    continue;
	}
	/* we've collected a block of data that wasn't the module we were
	 * looking for, write it out */
	if (block) {
	    fwrite(block, PORT_Strlen(block), 1, fd2);
	    PORT_Free(block);
	    block = NULL;
	}
	/* If we didn't just delete the this block, keep the blank line */
	if (!skip) {
	    fputs(line,fd2);
	}
	/* we are definately not in a deleted block anymore */
	skip = PR_FALSE;
    } 
    fclose(fd);
    fclose(fd2);
    if (found) {
	/* rename dbname2 to dbname */
	PR_Delete(dbname);
	PR_Rename(dbname2,dbname);
    } else {
	PR_Delete(dbname2);
    }
    PORT_Free(dbname2);
    PORT_Free(lib);
    PORT_Free(name);
    PORT_Free(block);
    return SECSuccess;

loser:
    if (fd != NULL) {
	fclose(fd);
    }
    if (fd2 != NULL) {
	fclose(fd2);
    }
    if (dbname2) {
	PR_Delete(dbname2);
	PORT_Free(dbname2);
    }
    PORT_Free(lib);
    PORT_Free(name);
    return SECFailure;
}
예제 #7
0
/***************************************************************************
 *
 * v e r i f y _ g l o b a l
 */
static int
verify_global(JAR *jar)
{
    FILE *fp;
    JAR_Context *ctx;
    JAR_Item *it;
    JAR_Digest *globaldig;
    char *ext;
    unsigned char *md5_digest, *sha1_digest;
    unsigned int sha1_length, md5_length;
    int retval = 0;
    char buf[BUFSIZ];

    ctx = JAR_find(jar, "*", jarTypePhy);

    while (JAR_find_next(ctx, &it) >= 0) {
        if (!PORT_Strncmp(it->pathname, "META-INF", 8)) {
            for (ext = it->pathname; *ext; ext++)
                ;
            while (ext > it->pathname && *ext != '.')
                ext--;

            if (verbosity >= 0) {
                if (!PORT_Strcasecmp(ext, ".rsa")) {
                    PR_fprintf(outputFD, "found a RSA signature file: %s\n",
                               it->pathname);
                }

                if (!PORT_Strcasecmp(ext, ".dsa")) {
                    PR_fprintf(outputFD, "found a DSA signature file: %s\n",
                               it->pathname);
                }

                if (!PORT_Strcasecmp(ext, ".mf")) {
                    PR_fprintf(outputFD,
                               "found a MF master manifest file: %s\n",
                               it->pathname);
                }
            }

            if (!PORT_Strcasecmp(ext, ".sf")) {
                if (verbosity >= 0) {
                    PR_fprintf(outputFD,
                               "found a SF signature manifest file: %s\n",
                               it->pathname);
                }

                rm_dash_r(TMP_OUTPUT);
                if (JAR_extract(jar, it->pathname, TMP_OUTPUT) < 0) {
                    PR_fprintf(errorFD, "%s: error extracting %s\n",
                               PROGRAM_NAME, it->pathname);
                    errorCount++;
                    retval = -1;
                    continue;
                }

                md5_digest = NULL;
                sha1_digest = NULL;

                if ((fp = fopen(TMP_OUTPUT, "rb")) != NULL) {
                    while (fgets(buf, BUFSIZ, fp)) {
                        char *s;

                        if (*buf == 0 || *buf == '\n' || *buf == '\r')
                            break;

                        for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
                            ;
                        *s = 0;

                        if (!PORT_Strncmp(buf, "MD5-Digest: ", 12)) {
                            md5_digest =
                                ATOB_AsciiToData(buf + 12, &md5_length);
                        }
                        if (!PORT_Strncmp(buf, "SHA1-Digest: ", 13)) {
                            sha1_digest =
                                ATOB_AsciiToData(buf + 13, &sha1_length);
                        }
                        if (!PORT_Strncmp(buf, "SHA-Digest: ", 12)) {
                            sha1_digest =
                                ATOB_AsciiToData(buf + 12, &sha1_length);
                        }
                    }

                    globaldig = jar->globalmeta;

                    if (globaldig && md5_digest && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "  md5 digest on global metainfo: %s\n",
                                   PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
                                       ? "no match"
                                       : "match");
                    }

                    if (globaldig && sha1_digest && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "  sha digest on global metainfo: %s\n",
                                   PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH)
                                       ? "no match"
                                       : "match");
                    }

                    if (globaldig == NULL && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "global metadigest is not available, strange.\n");
                    }

                    PORT_Free(md5_digest);
                    PORT_Free(sha1_digest);
                    fclose(fp);
                }
            }
        }
    }

    JAR_find_end(ctx);

    return retval;
}
예제 #8
0
/*
 * Add a module to the Data base 
 */
static SECStatus
nssutil_AddSecmodDBEntry(const char *appName,
                        const char *filename, const char *dbname,
                         char *module, PRBool rw)
{
    os_stat_type stat_existing;
    os_open_permissions_type file_mode;
    FILE *fd = NULL;
    char *block = NULL;
    PRBool libFound = PR_FALSE;

    if (dbname == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* can't write to a read only module */
    if (!rw) {
	PORT_SetError(SEC_ERROR_READ_ONLY);
	return SECFailure;
    }

    /* remove the previous version if it exists */
    (void) nssutil_DeleteSecmodDBEntry(appName, filename, dbname, module, rw);

    /* get the permissions of the existing file, or use the default */
    if (!os_stat(dbname, &stat_existing)) {
	file_mode = stat_existing.st_mode;
    } else {
	file_mode = os_open_permissions_default;
    }

    fd = lfopen(dbname, lfopen_append, file_mode);
    if (fd == NULL) {
	return SECFailure;
    }
    module = NSSUTIL_ArgStrip(module);
    while (*module) {
	int count;
	char *keyEnd = PORT_Strchr(module,'=');
	char *value;

	if (PORT_Strncmp(module, "library=", 8) == 0) {
	   libFound=PR_TRUE;
	}
	if (keyEnd == NULL) {
	    block = nssutil_DupCat(block, module);
	    break;
	}
	block = nssutil_DupnCat(block, module, keyEnd-module+1);
	if (block == NULL) { goto loser; }
	value = NSSUTIL_ArgFetchValue(&keyEnd[1], &count);
	if (value) {
	    block = nssutil_DupCat(block, NSSUTIL_ArgStrip(value));
	    PORT_Free(value);
	}
	if (block == NULL) { goto loser; }
	block = nssutil_DupnCat(block, "\n", 1);
	module = keyEnd + 1 + count;
	module = NSSUTIL_ArgStrip(module);
    }
    if (block) {
	if (!libFound) {
	    fprintf(fd,"library=\n");
	}
	fwrite(block, PORT_Strlen(block), 1, fd);
	fprintf(fd,"\n");
	PORT_Free(block);
	block = NULL;
    }
    fclose(fd);
    return SECSuccess;

loser:
    PORT_Free(block);
    fclose(fd);
    return SECFailure;
}
예제 #9
0
/*
 * Delete a module from the Data Base
 */
static SECStatus
nssutil_DeleteSecmodDBEntry(const char *appName,
                            const char *filename,
                            const char *dbname,
                            char *args,
                            PRBool rw)
{
    /* SHDB_FIXME implement */
    os_stat_type stat_existing;
    os_open_permissions_type file_mode;
    FILE *fd = NULL;
    FILE *fd2 = NULL;
    char line[MAX_LINE_LENGTH];
    char *dbname2 = NULL;
    char *block = NULL;
    char *name = NULL;
    char *lib = NULL;
    int name_len = 0, lib_len = 0;
    PRBool skip = PR_FALSE;
    PRBool found = PR_FALSE;

    if (dbname == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    if (!rw) {
	PORT_SetError(SEC_ERROR_READ_ONLY);
	return SECFailure;
    }

    dbname2 = PORT_Strdup(dbname);
    if (dbname2 == NULL) goto loser;
    dbname2[strlen(dbname)-1]++;

    /* get the permissions of the existing file, or use the default */
    if (!os_stat(dbname, &stat_existing)) {
	file_mode = stat_existing.st_mode;
    } else {
	file_mode = os_open_permissions_default;
    }

    /* do we really want to use streams here */
    fd = fopen(dbname, "r");
    if (fd == NULL) goto loser;

    fd2 = lfopen(dbname2, lfopen_truncate, file_mode);

    if (fd2 == NULL) goto loser;

    name = NSSUTIL_ArgGetParamValue("name",args);
    if (name) {
	name_len = PORT_Strlen(name);
    }
    lib = NSSUTIL_ArgGetParamValue("library",args);
    if (lib) {
	lib_len = PORT_Strlen(lib);
    }


    /*
     * the following loop takes line separated config files and collapses
     * the lines to a single string, escaping and quoting as necessary.
     */
    /* loop state variables */
    block = NULL;
    skip = PR_FALSE;
    while (fgets(line, sizeof(line), fd) != NULL) { 
	/* If we are processing a block (we haven't hit a blank line yet */
	if (*line != '\n') {
	    /* skip means we are in the middle of a block we are deleting */
	    if (skip) {
		continue;
	    }
	    /* if we haven't found the block yet, check to see if this block
	     * matches our requirements */
	    if (!found && ((name && (PORT_Strncasecmp(line,"name=",5) == 0) &&
		 (PORT_Strncmp(line+5,name,name_len) == 0))  ||
	        (lib && (PORT_Strncasecmp(line,"library=",8) == 0) &&
		 (PORT_Strncmp(line+8,lib,lib_len) == 0)))) {

		/* yup, we don't need to save any more data, */
		PORT_Free(block);
		block=NULL;
		/* we don't need to collect more of this block */
		skip = PR_TRUE;
		/* we don't need to continue searching for the block */
		found =PR_TRUE;
		continue;
	    }
	    /* not our match, continue to collect data in this block */
	    block = nssutil_DupCat(block,line);
	    continue;
	}
	/* we've collected a block of data that wasn't the module we were
	 * looking for, write it out */
	if (block) {
	    fwrite(block, PORT_Strlen(block), 1, fd2);
	    PORT_Free(block);
	    block = NULL;
	}
	/* If we didn't just delete the this block, keep the blank line */
	if (!skip) {
	    fputs(line,fd2);
	}
	/* we are definately not in a deleted block anymore */
	skip = PR_FALSE;
    } 
    fclose(fd);
    fclose(fd2);
    if (found) {
	/* rename dbname2 to dbname */
	PR_Delete(dbname);
	PR_Rename(dbname2,dbname);
    } else {
	PR_Delete(dbname2);
    }
    PORT_Free(dbname2);
    PORT_Free(lib);
    PORT_Free(name);
    PORT_Free(block);
    return SECSuccess;

loser:
    if (fd != NULL) {
	fclose(fd);
    }
    if (fd2 != NULL) {
	fclose(fd2);
    }
    if (dbname2) {
	PR_Delete(dbname2);
	PORT_Free(dbname2);
    }
    PORT_Free(lib);
    PORT_Free(name);
    return SECFailure;
}
예제 #10
0
char *getNSSPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
{
    secuPWData *pwdInfo = (secuPWData *)arg;
    PRFileDesc *fd;
    PRInt32 nb; /*number of bytes*/
    char* password;
    char* strings;
    char* token=NULL;
    const long maxPwdFileSize = NSSpwdfilesize;
    int i, tlen=0;

    if (slot) {
        token = PK11_GetTokenName(slot);
        if (token) {
            tlen = PORT_Strlen(token);
            /* openswan_log("authentication needed for token name %s with length %d",token,tlen); */
        }
        else {
            return 0;
        }
    }
    else {
        return 0;
    }

    if(retry) return 0;

    strings=PORT_ZAlloc(maxPwdFileSize);
    if(!strings) {
        openswan_log("Not able to allocate memory for reading NSS password file");
        return 0;
    }


    if(pwdInfo->source == PW_FROMFILE) {
        if(pwdInfo->data !=NULL) {
            fd = PR_Open(pwdInfo->data, PR_RDONLY, 0);
            if (!fd) {
                PORT_Free(strings);
                openswan_log("No password file \"%s\" exists.", pwdInfo->data);
                return 0;
            }

            nb = PR_Read(fd, strings, maxPwdFileSize);
            PR_Close(fd);

            if (nb == 0) {
                openswan_log("password file contains no data");
                PORT_Free(strings);
                return 0;
            }

            i = 0;
            do
            {
                int start = i;
                int slen;

                while (strings[i] != '\r' && strings[i] != '\n' && i < nb) i++;
                strings[i++] = '\0';

                while ( (i<nb) && (strings[i] == '\r' || strings[i] == '\n')) {
                    strings[i++] = '\0';
                }

                password = &strings[start];

                if (PORT_Strncmp(password, token, tlen)) continue;
                slen = PORT_Strlen(password);

                if (slen < (tlen+1)) continue;
                if (password[tlen] != ':') continue;
                password = &password[tlen+1];
                break;

            } while (i<nb);

            password = PORT_Strdup((char*)password);
            PORT_Free(strings);

            /* openswan_log("Password passed to NSS is %s with length %d", password, PORT_Strlen(password)); */
            return password;
        }
        else {
            openswan_log("File with Password to NSS DB is not provided");
            return 0;
        }
    }

    openswan_log("nss password source is not specified as file");
    return 0;
}
예제 #11
0
/*
 * Add a module to the Data base 
 */
static SECStatus
nssutil_AddSecmodDB(const char *appName, 
		   const char *filename, const char *dbname, 
		   char *module, PRBool rw)
{
    FILE *fd = NULL;
    char *block = NULL;
    PRBool libFound = PR_FALSE;

    if (dbname == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* can't write to a read only module */
    if (!rw) {
	PORT_SetError(SEC_ERROR_READ_ONLY);
	return SECFailure;
    }

    /* remove the previous version if it exists */
    (void) nssutil_DeleteSecmodDB(appName, filename, 
				  dbname, module, rw);

    fd = lfopen(dbname, "a+", O_CREAT|O_RDWR|O_APPEND);
    if (fd == NULL) {
	return SECFailure;
    }
    module = NSSUTIL_ArgStrip(module);
    while (*module) {
	int count;
	char *keyEnd = PORT_Strchr(module,'=');
	char *value;

	if (PORT_Strncmp(module, "library=", 8) == 0) {
	   libFound=PR_TRUE;
	}
	if (keyEnd == NULL) {
	    block = nssutil_DupCat(block, module);
	    break;
	}
	block = nssutil_DupnCat(block, module, keyEnd-module+1);
	if (block == NULL) { goto loser; }
	value = NSSUTIL_ArgFetchValue(&keyEnd[1], &count);
	if (value) {
	    block = nssutil_DupCat(block, NSSUTIL_ArgStrip(value));
	    PORT_Free(value);
	}
	if (block == NULL) { goto loser; }
	block = nssutil_DupnCat(block, "\n", 1);
	module = keyEnd + 1 + count;
	module = NSSUTIL_ArgStrip(module);
    }
    if (block) {
	if (!libFound) {
	    fprintf(fd,"library=\n");
	}
	fwrite(block, PORT_Strlen(block), 1, fd);
	fprintf(fd,"\n");
	PORT_Free(block);
	block = NULL;
    }
    fclose(fd);
    return SECSuccess;

loser:
    PORT_Free(block);
    fclose(fd);
    return SECFailure;
}