Milán Major

netscape-revival

1 branch
Code

security/cmd/p12exprt.c

#include "secutil.h"
#include <stdio.h>
#include <stdlib.h>
#include "prarena.h"
#include "secitem.h"
#include "pkcs12.h"
#include "secport.h"
#include "secutil.h"
#include "secitem.h"
#include "cert.h"
#include "key.h"
#include "secrng.h"

#if defined(LINUX)
#include <getopt.h>
#endif

static PRArenaPool *arena;
static char *progName;

#if defined(__sun) && !defined(SVR4)
extern int fclose(FILE*);
extern int fprintf(FILE *, char *, ...);
extern int getopt(int, char**, char*);
extern int isatty(int);
extern char *optarg;
extern char *sys_errlist[];
#define strerror(errno) sys_errlist[errno]
#endif

#define MIN_KEY_BITS	256

#ifdef US_VERSION
#define MAX_KEY_BITS	1024
#else
#define MAX_KEY_BITS	512
#endif

#define NUM_KEYSTROKES 120
#define RAND_BUF_SIZE 60

#define SEC_KEY_DB_EXISTS 0
#define SEC_CREATE_KEY_DB 1

#define SEC_CERT_DB_EXISTS 0
#define SEC_CREATE_CERT_DB 1

static SECKEYKeyDBHandle *
OpenKeyDB(int createnew)
{
    SECKEYKeyDBHandle *keyHandle;
    struct stat stat_buf;
    int ret;
    char *fName;

    fName = SECU_DatabaseFileName(xpKeyDB);

    /* if we expect database to exist, check for it */
    if (!createnew) {
	ret = stat(fName, &stat_buf);
	if (ret < 0) {
	    if (errno == ENOENT) {
		/* no key.db */
		SECU_PrintError(progName, "unable to locate database");
		return NULL;
	    } else {
		/* stat error */
		SECU_PrintError(progName, "stat: ", strerror(errno));
		return NULL;
	    }
	}
    }

    keyHandle = SECKEY_OpenKeyDB(fName);
    if (keyHandle == NULL) {
        SECU_PrintError(progName, "could not open key database %s", fName);
	return NULL;
    }

    return(keyHandle);
}

static CERTCertDBHandle
*OpenCertDB(int createNew)
  /* NOTE: This routine has been modified to allow the libsec/pcertdb.c  routines to automatically
  ** find and convert the old cert database into the new v3.0 format (cert db version 5).
  */
{
    CERTCertDBHandle *certHandle;
    SECStatus rv;
    struct stat stat_buf;
    char *conf_dir, *dbFilename;
    int ret;

    /* Allocate a handle to fill with CERT_OpenCertDB below */
    certHandle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle));
    if (!certHandle) {
	SECU_PrintError(progName, "unable to get database handle");
	return NULL;
    }

    dbFilename = SECU_DatabaseFileName(xpCertDB); /* This is the latest name, defined in Secutil.c */

    ret = stat(dbFilename, &stat_buf);

    if (ret == -1) {
      SECU_PrintError(progName, "Did not find Cert DB file: %s",dbFilename);
      SECU_PrintError(progName, "Will attempt to update any existing Cert.db file.","");
      rv = CERT_OpenCertDB(certHandle, NULL, FALSE);
    }
    else {
      SECU_PrintError(progName, "Using Cert DB file: %s",dbFilename);
      rv = CERT_OpenCertDB(certHandle, dbFilename, FALSE);
    }

    if (rv) {
	SECU_PrintError(progName, "could not open certificate database");
	if (certHandle) free (certHandle);  /* we don't want to leave anything behind... */
	return NULL;
    }

    return certHandle;
}

void init(void)
{
    /* Call the libsec initialization routines */                               
    PR_Init("key", 1, 1, 0); 
    SEC_Init();
    RNG_SystemInfoForRNG(); 

    /* XXX Try to use these files for RNG seed.  If
	 * they're not there (i.e. 
	 *      * installed somewhere else) oh well. */ 
	RNG_FileForRNG("/usr/ns-home/https-443/config/magnus.conf"); 
	RNG_FileForRNG("/usr/ns-home/https-443/config/obj.conf"); 
}

int main(int argc, char **argv)
{
    char **nicks;
    FILE *out_file;
    SECItem *dest;
    int i;
    CERTCertDBHandle *certdb;
    SECKEYKeyDBHandle *keydb;

    if(argc < 3)
    {
    	fprintf(stdout, "Usage -- %s <out_file> <nickname 1> ... <nickname n>",
    	    progName);
    	exit(-1);
    }

    init();

    progName = argv[0];	
	
    certdb = OpenCertDB(0);
    keydb = OpenKeyDB(0);

    nicks = PORT_ZAlloc(argc-1);
    for(i = 0; i < argc-1; i++)
	nicks[i] = argv[i+2];
	
    dest = SEC_PKCS12GetPFX(nicks, keydb, SECU_GetPassword, NULL,
	PR_TRUE, SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4,
	SECU_GetPBEPassword, NULL, certdb, 
	SEC_OID_PKCS12_OFFLINE_TRANSPORT_MODE,
	SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4);
    if(dest != NULL)
    {
	out_file = fopen(argv[1], "wb");
	for(i = 0; i < dest->len; i++)
	    fwrite(&dest->data[i], 1, 1, out_file);
	fclose(out_file);
    }
}