security/nss/cmd/signtool/certgen.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "signtool.h"
     7 #include "secoid.h"
     8 #include "cryptohi.h"
     9 #include "certdb.h"
    11 static char	*GetSubjectFromUser(unsigned long serial);
    12 static CERTCertificate*GenerateSelfSignedObjectSigningCert(char *nickname,
    13  	CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
    14         char *token);
    15 static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
    16 	CERTCertificate *cert, char *trusts);
    17 static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
    18 static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
    19 static CERTCertificate*install_cert(CERTCertDBHandle *db, SECItem *derCert,
    20             char *nickname);
    21 static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
    22  	SECKEYPrivateKey **privk, int keysize);
    23 static CERTCertificateRequest*make_cert_request(char *subject,
    24 	SECKEYPublicKey *pubk);
    25 static CERTCertificate *make_cert(CERTCertificateRequest *req,
    26 	unsigned long serial, CERTName *ca_subject);
    27 static void	output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db);
    30 /***********************************************************************
    31  *
    32  * G e n e r a t e C e r t
    33  *
    34  * Runs the whole process of creating a new cert, getting info from the
    35  * user, etc.
    36  */
    37 int
    38 GenerateCert(char *nickname, int keysize, char *token)
    39 {
    40     CERTCertDBHandle * db;
    41     CERTCertificate * cert;
    42     char	*subject;
    43     unsigned long	serial;
    44     char	stdinbuf[160];
    46     /* Print warning about having the browser open */
    47     PR_fprintf(PR_STDOUT /*always go to console*/,
    48         "\nWARNING: Performing this operation while the browser is running could cause"
    49         "\ncorruption of your security databases. If the browser is currently running,"
    50         "\nyou should exit the browser before continuing this operation. Enter "
    51         "\n\"y\" to continue, or anything else to abort: ");
    52     pr_fgets(stdinbuf, 160, PR_STDIN);
    53     PR_fprintf(PR_STDOUT, "\n");
    54     if (tolower(stdinbuf[0]) != 'y') {
    55 	PR_fprintf(errorFD, "Operation aborted at user's request.\n");
    56 	errorCount++;
    57 	return - 1;
    58     }
    60     db = CERT_GetDefaultCertDB();
    61     if (!db) {
    62 	FatalError("Unable to open certificate database");
    63     }
    65     if (PK11_FindCertFromNickname(nickname, &pwdata)) {
    66 	PR_fprintf(errorFD,
    67 	    "ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
    68 	    "must choose a different nickname.\n", nickname);
    69 	errorCount++;
    70 	exit(ERRX);
    71     }
    73     LL_L2UI(serial, PR_Now());
    75     subject = GetSubjectFromUser(serial);
    77     cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
    78          		serial, keysize, token);
    80     if (cert) {
    81 	output_ca_cert(cert, db);
    82 	CERT_DestroyCertificate(cert);
    83     }
    85     PORT_Free(subject);
    86     return 0;
    87 }
    90 #undef VERBOSE_PROMPTS
    92 /*********************************************************************8
    93  * G e t S u b j e c t F r o m U s e r
    94  *
    95  * Construct the subject information line for a certificate by querying
    96  * the user on stdin.
    97  */
    98 static char	*
    99 GetSubjectFromUser(unsigned long serial)
   100 {
   101     char	buf[STDIN_BUF_SIZE];
   102     char	common_name_buf[STDIN_BUF_SIZE];
   103     char	*common_name, *state, *orgunit, *country, *org, *locality;
   104     char	*email, *uid;
   105     char	*subject;
   106     char	*cp;
   107     int	subjectlen = 0;
   109     common_name = state = orgunit = country = org = locality = email =
   110         uid = subject = NULL;
   112     /* Get subject information */
   113     PR_fprintf(PR_STDOUT,
   114         "\nEnter certificate information.  All fields are optional. Acceptable\n"
   115         "characters are numbers, letters, spaces, and apostrophes.\n");
   117 #ifdef VERBOSE_PROMPTS
   118     PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n"
   119         "Enter the full name you want to give your certificate. (Example: Test-Only\n"
   120         "Object Signing Certificate)\n"
   121         "-->");
   122 #else
   123     PR_fprintf(PR_STDOUT, "certificate common name: ");
   124 #endif
   125     fgets(buf, STDIN_BUF_SIZE, stdin);
   126     cp = chop(buf);
   127     if (*cp == '\0') {
   128 	sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME,
   129 	     serial);
   130 	cp = common_name_buf;
   131     }
   132     common_name = PORT_ZAlloc(strlen(cp) + 6);
   133     if (!common_name) {
   134 	out_of_memory();
   135     }
   136     sprintf(common_name, "CN=%s, ", cp);
   137     subjectlen += strlen(common_name);
   139 #ifdef VERBOSE_PROMPTS
   140     PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n"
   141         "Enter the name of your organization. For example, this could be the name\n"
   142         "of your company.\n"
   143         "-->");
   144 #else
   145     PR_fprintf(PR_STDOUT, "organization: ");
   146 #endif
   147     fgets(buf, STDIN_BUF_SIZE, stdin);
   148     cp = chop(buf);
   149     if (*cp != '\0') {
   150 	org = PORT_ZAlloc(strlen(cp) + 5);
   151 	if (!org) {
   152 	    out_of_memory();
   153 	}
   154 	sprintf(org, "O=%s, ", cp);
   155 	subjectlen += strlen(org);
   156     }
   158 #ifdef VERBOSE_PROMPTS
   159     PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n"
   160         "Enter the name of your organization unit.  For example, this could be the\n"
   161         "name of your department.\n"
   162         "-->");
   163 #else
   164     PR_fprintf(PR_STDOUT, "organization unit: ");
   165 #endif
   166     fgets(buf, STDIN_BUF_SIZE, stdin);
   167     cp = chop(buf);
   168     if (*cp != '\0') {
   169 	orgunit = PORT_ZAlloc(strlen(cp) + 6);
   170 	if (!orgunit) {
   171 	    out_of_memory();
   172 	}
   173 	sprintf(orgunit, "OU=%s, ", cp);
   174 	subjectlen += strlen(orgunit);
   175     }
   177 #ifdef VERBOSE_PROMPTS
   178     PR_fprintf(PR_STDOUT, "\nSTATE\n"
   179         "Enter the name of your state or province.\n"
   180         "-->");
   181 #else
   182     PR_fprintf(PR_STDOUT, "state or province: ");
   183 #endif
   184     fgets(buf, STDIN_BUF_SIZE, stdin);
   185     cp = chop(buf);
   186     if (*cp != '\0') {
   187 	state = PORT_ZAlloc(strlen(cp) + 6);
   188 	if (!state) {
   189 	    out_of_memory();
   190 	}
   191 	sprintf(state, "ST=%s, ", cp);
   192 	subjectlen += strlen(state);
   193     }
   195 #ifdef VERBOSE_PROMPTS
   196     PR_fprintf(PR_STDOUT, "\nCOUNTRY\n"
   197         "Enter the 2-character abbreviation for the name of your country.\n"
   198         "-->");
   199 #else
   200     PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): ");
   201 #endif
   202     fgets(buf, STDIN_BUF_SIZE, stdin);
   203     cp = chop(cp);
   204     if (strlen(cp) != 2) {
   205 	*cp = '\0';	/* country code must be 2 chars */
   206     }
   207     if (*cp != '\0') {
   208 	country = PORT_ZAlloc(strlen(cp) + 5);
   209 	if (!country) {
   210 	    out_of_memory();
   211 	}
   212 	sprintf(country, "C=%s, ", cp);
   213 	subjectlen += strlen(country);
   214     }
   216 #ifdef VERBOSE_PROMPTS
   217     PR_fprintf(PR_STDOUT, "\nUSERNAME\n"
   218         "Enter your system username or UID\n"
   219         "-->");
   220 #else
   221     PR_fprintf(PR_STDOUT, "username: ");
   222 #endif
   223     fgets(buf, STDIN_BUF_SIZE, stdin);
   224     cp = chop(buf);
   225     if (*cp != '\0') {
   226 	uid = PORT_ZAlloc(strlen(cp) + 7);
   227 	if (!uid) {
   228 	    out_of_memory();
   229 	}
   230 	sprintf(uid, "UID=%s, ", cp);
   231 	subjectlen += strlen(uid);
   232     }
   234 #ifdef VERBOSE_PROMPTS
   235     PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n"
   236         "Enter your email address.\n"
   237         "-->");
   238 #else
   239     PR_fprintf(PR_STDOUT, "email address: ");
   240 #endif
   241     fgets(buf, STDIN_BUF_SIZE, stdin);
   242     cp = chop(buf);
   243     if (*cp != '\0') {
   244 	email = PORT_ZAlloc(strlen(cp) + 5);
   245 	if (!email) {
   246 	    out_of_memory();
   247 	}
   248 	sprintf(email, "E=%s,", cp);
   249 	subjectlen += strlen(email);
   250     }
   252     subjectlen++;
   254     subject = PORT_ZAlloc(subjectlen);
   255     if (!subject) {
   256 	out_of_memory();
   257     }
   259     sprintf(subject, "%s%s%s%s%s%s%s",
   260         common_name ? common_name : "",
   261         org ? org : "",
   262         orgunit ? orgunit : "",
   263         state ? state : "",
   264         country ? country : "",
   265         uid ? uid : "",
   266         email ? email : ""
   267         );
   268     if ( (strlen(subject) > 1) && (subject[strlen(subject)-1] == ' ') ) {
   269 	subject[strlen(subject)-2] = '\0';
   270     }
   272     PORT_Free(common_name);
   273     PORT_Free(org);
   274     PORT_Free(orgunit);
   275     PORT_Free(state);
   276     PORT_Free(country);
   277     PORT_Free(uid);
   278     PORT_Free(email);
   280     return subject;
   281 }
   284 /**************************************************************************
   285  *
   286  * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t
   287  *														   		  *phew*^
   288  *
   289  */
   290 static CERTCertificate*
   291 GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
   292  	char *subject, unsigned long serial, int keysize, char *token)
   293 {
   294     CERTCertificate * cert, *temp_cert;
   295     SECItem * derCert;
   296     CERTCertificateRequest * req;
   298     PK11SlotInfo * slot = NULL;
   299     SECKEYPrivateKey * privk = NULL;
   300     SECKEYPublicKey * pubk = NULL;
   302     if ( token ) {
   303 	slot = PK11_FindSlotByName(token);
   304     } else {
   305 	slot = PK11_GetInternalKeySlot();
   306     }
   308     if (slot == NULL) {
   309 	PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
   310 	    token ? token : "");
   311 	errorCount++;
   312 	exit (ERRX);
   313     }
   315     if ( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
   316 	FatalError("Error generating keypair.");
   317     }
   318     req = make_cert_request (subject, pubk);
   319     temp_cert = make_cert (req, serial, &req->subject);
   320     if (set_cert_type(temp_cert,
   321         NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA)
   322          != SECSuccess) {
   323 	FatalError("Unable to set cert type");
   324     }
   326     derCert = sign_cert (temp_cert, privk);
   327     cert = install_cert(db, derCert, nickname);
   328     if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
   329 	FatalError("Unable to change trust on generated certificate");
   330     }
   332     /* !!! Free memory ? !!! */
   333     PK11_FreeSlot(slot);
   334     SECKEY_DestroyPrivateKey(privk);
   335     SECKEY_DestroyPublicKey(pubk);
   337     return cert;
   338 }
   341 /**************************************************************************
   342  *
   343  * C h a n g e T r u s t A t t r i b u t e s
   344  */
   345 static SECStatus
   346 ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
   347 {
   349     CERTCertTrust	 * trust;
   351     if (!db || !cert || !trusts) {
   352 	PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n");
   353 	errorCount++;
   354 	return SECFailure;
   355     }
   357     trust = (CERTCertTrust * ) PORT_ZAlloc(sizeof(CERTCertTrust));
   358     if (!trust) {
   359 	PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
   360 	    "CERTCertTrust\n");
   361 	errorCount++;
   362 	return SECFailure;
   363     }
   365     if ( CERT_DecodeTrustString(trust, trusts) ) {
   366 	return SECFailure;
   367     }
   369     if ( CERT_ChangeCertTrust(db, cert, trust) ) {
   370 	PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
   371 	     		 cert->nickname ? cert->nickname : "");
   372 	errorCount++;
   373 	return SECFailure;
   374     }
   376     return SECSuccess;
   377 }
   380 /*************************************************************************
   381  *
   382  * s e t _ c e r t _ t y p e
   383  */
   384 static SECStatus
   385 set_cert_type(CERTCertificate *cert, unsigned int type)
   386 {
   387     void	*context;
   388     SECStatus status = SECSuccess;
   389     SECItem certType;
   390     char	ctype;
   392     context = CERT_StartCertExtensions(cert);
   394     certType.type = siBuffer;
   395     certType.data = (unsigned char * ) &ctype;
   396     certType.len = 1;
   397     ctype = (unsigned char)type;
   398     if (CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
   399          	 &certType, PR_TRUE /*critical*/) != SECSuccess) {
   400 	status = SECFailure;
   401     }
   403     if (CERT_FinishExtensions(context) != SECSuccess) {
   404 	status = SECFailure;
   405     }
   407     return status;
   408 }
   411 /********************************************************************
   412  *
   413  * s i g n _ c e r t
   414  */
   415 static SECItem *
   416 sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
   417 {
   418     SECStatus rv;
   420     SECItem der2;
   421     SECItem * result2;
   423     void	*dummy;
   424     SECOidTag alg = SEC_OID_UNKNOWN;
   426     alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN);
   427     if (alg == SEC_OID_UNKNOWN) {
   428 	FatalError("Unknown key type");
   429     }
   431     rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
   433     if (rv != SECSuccess) {
   434 	PR_fprintf(errorFD, "%s: unable to set signature alg id\n",
   435 	     PROGRAM_NAME);
   436 	errorCount++;
   437 	exit (ERRX);
   438     }
   440     der2.len = 0;
   441     der2.data = NULL;
   443     dummy = SEC_ASN1EncodeItem
   444         (cert->arena, &der2, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
   446     if (rv != SECSuccess) {
   447 	PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME);
   448 	errorCount++;
   449 	exit (ERRX);
   450     }
   452     result2 = (SECItem * ) PORT_ArenaZAlloc (cert->arena, sizeof (SECItem));
   453     if (result2 == NULL)
   454 	out_of_memory();
   456     rv = SEC_DerSignData 
   457         (cert->arena, result2, der2.data, der2.len, privk, alg);
   459     if (rv != SECSuccess) {
   460 	PR_fprintf(errorFD, "can't sign encoded certificate data\n");
   461 	errorCount++;
   462 	exit (ERRX);
   463     } else if (verbosity >= 0) {
   464 	PR_fprintf(outputFD, "certificate has been signed\n");
   465     }
   467     cert->derCert = *result2;
   469     return result2;
   470 }
   473 /*********************************************************************
   474  *
   475  * i n s t a l l _ c e r t
   476  *
   477  * Installs the cert in the permanent database.
   478  */
   479 static CERTCertificate*
   480 install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
   481 {
   482     CERTCertificate * newcert;
   483     PK11SlotInfo * newSlot;
   486     newSlot = PK11_ImportDERCertForKey(derCert, nickname, &pwdata);
   487     if ( newSlot == NULL ) {
   488 	PR_fprintf(errorFD, "Unable to install certificate\n");
   489 	errorCount++;
   490 	exit(ERRX);
   491     }
   493     newcert = PK11_FindCertFromDERCertItem(newSlot, derCert, &pwdata);
   494     PK11_FreeSlot(newSlot);
   495     if (newcert == NULL) {
   496 	PR_fprintf(errorFD, "%s: can't find new certificate\n",
   497 	     PROGRAM_NAME);
   498 	errorCount++;
   499 	exit (ERRX);
   500     }
   502     if (verbosity >= 0) {
   503 	PR_fprintf(outputFD, "certificate \"%s\" added to database\n",
   504 	     nickname);
   505     }
   507     return newcert;
   508 }
   511 /******************************************************************
   512  *
   513  * G e n e r a t e K e y P a i r
   514  */
   515 static SECStatus
   516 GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
   517 SECKEYPrivateKey **privk, int keysize)
   518 {
   520     PK11RSAGenParams rsaParams;
   522     if ( keysize == -1 ) {
   523 	rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE;
   524     } else {
   525 	rsaParams.keySizeInBits = keysize;
   526     }
   527     rsaParams.pe = 0x10001;
   529     if (PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, &pwdata)
   530          != SECSuccess) {
   531 	SECU_PrintError(progName, "failure authenticating to key database.\n");
   532 	exit(ERRX);
   533     }
   535     *privk = PK11_GenerateKeyPair (slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams,
   537         pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, &pwdata);
   539     if (*privk != NULL && *pubk != NULL) {
   540 	if (verbosity >= 0) {
   541 	    PR_fprintf(outputFD, "generated public/private key pair\n");
   542 	}
   543     } else {
   544 	SECU_PrintError(progName, "failure generating key pair\n");
   545 	exit (ERRX);
   546     }
   548     return SECSuccess;
   549 }
   553 /******************************************************************
   554  *
   555  * m a k e _ c e r t _ r e q u e s t
   556  */
   557 static CERTCertificateRequest*
   558 make_cert_request(char *subject, SECKEYPublicKey *pubk)
   559 {
   560     CERTName * subj;
   561     CERTSubjectPublicKeyInfo * spki;
   563     CERTCertificateRequest * req;
   565     /* Create info about public key */
   566     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
   567     if (!spki) {
   568 	SECU_PrintError(progName, "unable to create subject public key");
   569 	exit (ERRX);
   570     }
   572     subj = CERT_AsciiToName (subject);
   573     if (subj == NULL) {
   574 	FatalError("Invalid data in certificate description");
   575     }
   577     /* Generate certificate request */
   578     req = CERT_CreateCertificateRequest(subj, spki, 0);
   579     if (!req) {
   580 	SECU_PrintError(progName, "unable to make certificate request");
   581 	exit (ERRX);
   582     }
   584     SECKEY_DestroySubjectPublicKeyInfo(spki);
   585     CERT_DestroyName(subj);
   587     if (verbosity >= 0) {
   588 	PR_fprintf(outputFD, "certificate request generated\n");
   589     }
   591     return req;
   592 }
   595 /******************************************************************
   596  *
   597  * m a k e _ c e r t
   598  */
   599 static CERTCertificate *
   600 make_cert(CERTCertificateRequest *req, unsigned long serial,
   601 CERTName *ca_subject)
   602 {
   603     CERTCertificate * cert;
   605     CERTValidity * validity = NULL;
   607     PRTime now, after;
   608     PRExplodedTime printableTime;
   610     now = PR_Now();
   611     PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
   613     printableTime.tm_month += 3;
   614     after = PR_ImplodeTime (&printableTime);
   616     validity = CERT_CreateValidity (now, after);
   618     if (validity == NULL) {
   619 	PR_fprintf(errorFD, "%s: error creating certificate validity\n",
   620 	     PROGRAM_NAME);
   621 	errorCount++;
   622 	exit (ERRX);
   623     }
   625     cert = CERT_CreateCertificate
   626         (serial, ca_subject, validity, req);
   628     if (cert == NULL) {
   629 	/* should probably be more precise here */
   630 	PR_fprintf(errorFD, "%s: error while generating certificate\n",
   631 	     PROGRAM_NAME);
   632 	errorCount++;
   633 	exit (ERRX);
   634     }
   636     return cert;
   637 }
   640 /*************************************************************************
   641  *
   642  * o u t p u t _ c a _ c e r t
   643  */
   644 static void	
   645 output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db)
   646 {
   647     FILE * out;
   649     SECItem * encodedCertChain;
   650     SEC_PKCS7ContentInfo * certChain;
   651     char	*filename;
   653     /* the raw */
   655     filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8);
   656     if (!filename) 
   657 	out_of_memory();
   659     sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
   660     if ((out = fopen (filename, "wb")) == NULL) {
   661 	PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
   662 	     filename);
   663 	errorCount++;
   664 	exit(ERRX);
   665     }
   667     certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db);
   668     encodedCertChain 
   669          = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL);
   670     SEC_PKCS7DestroyContentInfo (certChain);
   672     if (encodedCertChain) {
   673 	fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
   674 	fwrite (encodedCertChain->data, 1, encodedCertChain->len,
   675 	     out);
   676 	SECITEM_FreeItem(encodedCertChain, PR_TRUE);
   677     } else {
   678 	PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n",
   679 	     PROGRAM_NAME);
   680 	errorCount++;
   681 	exit(ERRX);
   682     }
   684     fclose (out);
   686     /* and the cooked */
   688     sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
   689     if ((out = fopen (filename, "wb")) == NULL) {
   690 	PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
   691 	     filename);
   692 	errorCount++;
   693 	return;
   694     }
   696     fprintf (out, "%s\n%s\n%s\n", 
   697         NS_CERT_HEADER,
   698         BTOA_DataToAscii (cert->derCert.data, cert->derCert.len), 
   699         NS_CERT_TRAILER);
   701     fclose (out);
   703     if (verbosity >= 0) {
   704 	PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
   705 	     			DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
   706     }
   707 }

mercurial