Back to index

lightning-sunbird  0.9+nobinonly
certgen.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "signtool.h"
00038 
00039 #include "secoid.h"
00040 #include "cryptohi.h"
00041 #include "certdb.h"
00042 
00043 static char   *GetSubjectFromUser(unsigned long serial);
00044 static CERTCertificate*GenerateSelfSignedObjectSigningCert(char *nickname,
00045        CERTCertDBHandle *db, char *subject, unsigned long serial, int keysize,
00046         char *token);
00047 static SECStatus ChangeTrustAttributes(CERTCertDBHandle *db,
00048        CERTCertificate *cert, char *trusts);
00049 static SECStatus set_cert_type(CERTCertificate *cert, unsigned int type);
00050 static SECItem *sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk);
00051 static CERTCertificate*install_cert(CERTCertDBHandle *db, SECItem *derCert,
00052             char *nickname);
00053 static SECStatus GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
00054        SECKEYPrivateKey **privk, int keysize);
00055 static CERTCertificateRequest*make_cert_request(char *subject,
00056        SECKEYPublicKey *pubk);
00057 static CERTCertificate *make_cert(CERTCertificateRequest *req,
00058        unsigned long serial, CERTName *ca_subject);
00059 static void   output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db);
00060 
00061 
00062 /***********************************************************************
00063  *
00064  * G e n e r a t e C e r t
00065  *
00066  * Runs the whole process of creating a new cert, getting info from the
00067  * user, etc.
00068  */
00069 int
00070 GenerateCert(char *nickname, int keysize, char *token)
00071 {
00072     CERTCertDBHandle * db;
00073     CERTCertificate * cert;
00074     char      *subject;
00075     unsigned long    serial;
00076     char      stdinbuf[160];
00077 
00078     /* Print warning about having the browser open */
00079     PR_fprintf(PR_STDOUT /*always go to console*/,
00080         "\nWARNING: Performing this operation while the browser is running could cause"
00081         "\ncorruption of your security databases. If the browser is currently running,"
00082         "\nyou should exit the browser before continuing this operation. Enter "
00083         "\n\"y\" to continue, or anything else to abort: ");
00084     pr_fgets(stdinbuf, 160, PR_STDIN);
00085     PR_fprintf(PR_STDOUT, "\n");
00086     if (tolower(stdinbuf[0]) != 'y') {
00087        PR_fprintf(errorFD, "Operation aborted at user's request.\n");
00088        errorCount++;
00089        return - 1;
00090     }
00091 
00092     db = CERT_GetDefaultCertDB();
00093     if (!db) {
00094        FatalError("Unable to open certificate database");
00095     }
00096 
00097     if (PK11_FindCertFromNickname(nickname, NULL)) {
00098        PR_fprintf(errorFD,
00099            "ERROR: Certificate with nickname \"%s\" already exists in database. You\n"
00100            "must choose a different nickname.\n", nickname);
00101        errorCount++;
00102        exit(ERRX);
00103     }
00104 
00105     LL_L2UI(serial, PR_Now());
00106 
00107     subject = GetSubjectFromUser(serial);
00108 
00109     cert = GenerateSelfSignedObjectSigningCert(nickname, db, subject,
00110                      serial, keysize, token);
00111 
00112     if (cert) {
00113        output_ca_cert(cert, db);
00114        CERT_DestroyCertificate(cert);
00115     }
00116 
00117     PORT_Free(subject);
00118     return 0;
00119 }
00120 
00121 
00122 #undef VERBOSE_PROMPTS
00123 
00124 /*********************************************************************8
00125  * G e t S u b j e c t F r o m U s e r
00126  *
00127  * Construct the subject information line for a certificate by querying
00128  * the user on stdin.
00129  */
00130 static char   *
00131 GetSubjectFromUser(unsigned long serial)
00132 {
00133     char      buf[STDIN_BUF_SIZE];
00134     char      common_name_buf[STDIN_BUF_SIZE];
00135     char      *common_name, *state, *orgunit, *country, *org, *locality;
00136     char      *email, *uid;
00137     char      *subject;
00138     char      *cp;
00139     int       subjectlen = 0;
00140 
00141     common_name = state = orgunit = country = org = locality = email =
00142         uid = subject = NULL;
00143 
00144     /* Get subject information */
00145     PR_fprintf(PR_STDOUT,
00146         "\nEnter certificate information.  All fields are optional. Acceptable\n"
00147         "characters are numbers, letters, spaces, and apostrophes.\n");
00148 
00149 #ifdef VERBOSE_PROMPTS
00150     PR_fprintf(PR_STDOUT, "\nCOMMON NAME\n"
00151         "Enter the full name you want to give your certificate. (Example: Test-Only\n"
00152         "Object Signing Certificate)\n"
00153         "-->");
00154 #else
00155     PR_fprintf(PR_STDOUT, "certificate common name: ");
00156 #endif
00157     fgets(buf, STDIN_BUF_SIZE, stdin);
00158     cp = chop(buf);
00159     if (*cp == '\0') {
00160        sprintf(common_name_buf, "%s (%lu)", DEFAULT_COMMON_NAME,
00161             serial);
00162        cp = common_name_buf;
00163     }
00164     common_name = PORT_ZAlloc(strlen(cp) + 6);
00165     if (!common_name) {
00166        out_of_memory();
00167     }
00168     sprintf(common_name, "CN=%s, ", cp);
00169     subjectlen += strlen(common_name);
00170 
00171 #ifdef VERBOSE_PROMPTS
00172     PR_fprintf(PR_STDOUT, "\nORGANIZATION NAME\n"
00173         "Enter the name of your organization. For example, this could be the name\n"
00174         "of your company.\n"
00175         "-->");
00176 #else
00177     PR_fprintf(PR_STDOUT, "organization: ");
00178 #endif
00179     fgets(buf, STDIN_BUF_SIZE, stdin);
00180     cp = chop(buf);
00181     if (*cp != '\0') {
00182        org = PORT_ZAlloc(strlen(cp) + 5);
00183        if (!org) {
00184            out_of_memory();
00185        }
00186        sprintf(org, "O=%s, ", cp);
00187        subjectlen += strlen(org);
00188     }
00189 
00190 #ifdef VERBOSE_PROMPTS
00191     PR_fprintf(PR_STDOUT, "\nORGANIZATION UNIT\n"
00192         "Enter the name of your organization unit.  For example, this could be the\n"
00193         "name of your department.\n"
00194         "-->");
00195 #else
00196     PR_fprintf(PR_STDOUT, "organization unit: ");
00197 #endif
00198     fgets(buf, STDIN_BUF_SIZE, stdin);
00199     cp = chop(buf);
00200     if (*cp != '\0') {
00201        orgunit = PORT_ZAlloc(strlen(cp) + 6);
00202        if (!orgunit) {
00203            out_of_memory();
00204        }
00205        sprintf(orgunit, "OU=%s, ", cp);
00206        subjectlen += strlen(orgunit);
00207     }
00208 
00209 #ifdef VERBOSE_PROMPTS
00210     PR_fprintf(PR_STDOUT, "\nSTATE\n"
00211         "Enter the name of your state or province.\n"
00212         "-->");
00213 #else
00214     PR_fprintf(PR_STDOUT, "state or province: ");
00215 #endif
00216     fgets(buf, STDIN_BUF_SIZE, stdin);
00217     cp = chop(buf);
00218     if (*cp != '\0') {
00219        state = PORT_ZAlloc(strlen(cp) + 6);
00220        if (!state) {
00221            out_of_memory();
00222        }
00223        sprintf(state, "ST=%s, ", cp);
00224        subjectlen += strlen(state);
00225     }
00226 
00227 #ifdef VERBOSE_PROMPTS
00228     PR_fprintf(PR_STDOUT, "\nCOUNTRY\n"
00229         "Enter the 2-character abbreviation for the name of your country.\n"
00230         "-->");
00231 #else
00232     PR_fprintf(PR_STDOUT, "country (must be exactly 2 characters): ");
00233 #endif
00234     fgets(buf, STDIN_BUF_SIZE, stdin);
00235     cp = chop(cp);
00236     if (strlen(cp) != 2) {
00237        *cp = '\0';   /* country code must be 2 chars */
00238     }
00239     if (*cp != '\0') {
00240        country = PORT_ZAlloc(strlen(cp) + 5);
00241        if (!country) {
00242            out_of_memory();
00243        }
00244        sprintf(country, "C=%s, ", cp);
00245        subjectlen += strlen(country);
00246     }
00247 
00248 #ifdef VERBOSE_PROMPTS
00249     PR_fprintf(PR_STDOUT, "\nUSERNAME\n"
00250         "Enter your system username or UID\n"
00251         "-->");
00252 #else
00253     PR_fprintf(PR_STDOUT, "username: ");
00254 #endif
00255     fgets(buf, STDIN_BUF_SIZE, stdin);
00256     cp = chop(buf);
00257     if (*cp != '\0') {
00258        uid = PORT_ZAlloc(strlen(cp) + 7);
00259        if (!uid) {
00260            out_of_memory();
00261        }
00262        sprintf(uid, "UID=%s, ", cp);
00263        subjectlen += strlen(uid);
00264     }
00265 
00266 #ifdef VERBOSE_PROMPTS
00267     PR_fprintf(PR_STDOUT, "\nEMAIL ADDRESS\n"
00268         "Enter your email address.\n"
00269         "-->");
00270 #else
00271     PR_fprintf(PR_STDOUT, "email address: ");
00272 #endif
00273     fgets(buf, STDIN_BUF_SIZE, stdin);
00274     cp = chop(buf);
00275     if (*cp != '\0') {
00276        email = PORT_ZAlloc(strlen(cp) + 5);
00277        if (!email) {
00278            out_of_memory();
00279        }
00280        sprintf(email, "E=%s,", cp);
00281        subjectlen += strlen(email);
00282     }
00283 
00284     subjectlen++;
00285 
00286     subject = PORT_ZAlloc(subjectlen);
00287     if (!subject) {
00288        out_of_memory();
00289     }
00290 
00291     sprintf(subject, "%s%s%s%s%s%s%s",
00292         common_name ? common_name : "",
00293         org ? org : "",
00294         orgunit ? orgunit : "",
00295         state ? state : "",
00296         country ? country : "",
00297         uid ? uid : "",
00298         email ? email : ""
00299         );
00300     if ( (strlen(subject) > 1) && (subject[strlen(subject)-1] == ' ') ) {
00301        subject[strlen(subject)-2] = '\0';
00302     }
00303 
00304     PORT_Free(common_name);
00305     PORT_Free(org);
00306     PORT_Free(orgunit);
00307     PORT_Free(state);
00308     PORT_Free(country);
00309     PORT_Free(uid);
00310     PORT_Free(email);
00311 
00312     return subject;
00313 }
00314 
00315 
00316 /**************************************************************************
00317  *
00318  * 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
00319  *                                                                                                                *phew*^
00320  *
00321  */
00322 static CERTCertificate*
00323 GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
00324        char *subject, unsigned long serial, int keysize, char *token)
00325 {
00326     CERTCertificate * cert, *temp_cert;
00327     SECItem * derCert;
00328     CERTCertificateRequest * req;
00329 
00330     PK11SlotInfo * slot = NULL;
00331     SECKEYPrivateKey * privk = NULL;
00332     SECKEYPublicKey * pubk = NULL;
00333 
00334     if ( token ) {
00335        slot = PK11_FindSlotByName(token);
00336     } else {
00337        slot = PK11_GetInternalKeySlot();
00338     }
00339 
00340     if (slot == NULL) {
00341        PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
00342            token ? token : "");
00343        errorCount++;
00344        exit (ERRX);
00345     }
00346 
00347     if ( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
00348        FatalError("Error generating keypair.");
00349     }
00350     req = make_cert_request (subject, pubk);
00351     temp_cert = make_cert (req, serial, &req->subject);
00352     if (set_cert_type(temp_cert,
00353         NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA)
00354          != SECSuccess) {
00355        FatalError("Unable to set cert type");
00356     }
00357 
00358     derCert = sign_cert (temp_cert, privk);
00359     cert = install_cert(db, derCert, nickname);
00360     if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
00361        FatalError("Unable to change trust on generated certificate");
00362     }
00363 
00364     /* !!! Free memory ? !!! */
00365     PK11_FreeSlot(slot);
00366     SECKEY_DestroyPrivateKey(privk);
00367     SECKEY_DestroyPublicKey(pubk);
00368 
00369     return cert;
00370 }
00371 
00372 
00373 /**************************************************************************
00374  *
00375  * C h a n g e T r u s t A t t r i b u t e s
00376  */
00377 static SECStatus
00378 ChangeTrustAttributes(CERTCertDBHandle *db, CERTCertificate *cert, char *trusts)
00379 {
00380 
00381     CERTCertTrust     * trust;
00382 
00383     if (!db || !cert || !trusts) {
00384        PR_fprintf(errorFD, "ChangeTrustAttributes got incomplete arguments.\n");
00385        errorCount++;
00386        return SECFailure;
00387     }
00388 
00389     trust = (CERTCertTrust * ) PORT_ZAlloc(sizeof(CERTCertTrust));
00390     if (!trust) {
00391        PR_fprintf(errorFD, "ChangeTrustAttributes unable to allocate "
00392            "CERTCertTrust\n");
00393        errorCount++;
00394        return SECFailure;
00395     }
00396 
00397     if ( CERT_DecodeTrustString(trust, trusts) ) {
00398        return SECFailure;
00399     }
00400 
00401     if ( CERT_ChangeCertTrust(db, cert, trust) ) {
00402        PR_fprintf(errorFD, "unable to modify trust attributes for cert %s\n",
00403                       cert->nickname ? cert->nickname : "");
00404        errorCount++;
00405        return SECFailure;
00406     }
00407 
00408     return SECSuccess;
00409 }
00410 
00411 
00412 /*************************************************************************
00413  *
00414  * s e t _ c e r t _ t y p e
00415  */
00416 static SECStatus
00417 set_cert_type(CERTCertificate *cert, unsigned int type)
00418 {
00419     void      *context;
00420     SECStatus status = SECSuccess;
00421     SECItem certType;
00422     char      ctype;
00423 
00424     context = CERT_StartCertExtensions(cert);
00425 
00426     certType.type = siBuffer;
00427     certType.data = (unsigned char * ) &ctype;
00428     certType.len = 1;
00429     ctype = (unsigned char)type;
00430     if (CERT_EncodeAndAddBitStrExtension(context, SEC_OID_NS_CERT_EXT_CERT_TYPE,
00431                &certType, PR_TRUE /*critical*/) != SECSuccess) {
00432        status = SECFailure;
00433     }
00434 
00435     if (CERT_FinishExtensions(context) != SECSuccess) {
00436        status = SECFailure;
00437     }
00438 
00439     return status;
00440 }
00441 
00442 
00443 /********************************************************************
00444  *
00445  * s i g n _ c e r t
00446  */
00447 static SECItem *
00448 sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
00449 {
00450     SECStatus rv;
00451 
00452     SECItem der2;
00453     SECItem * result2;
00454 
00455     void      *dummy;
00456     SECOidTag alg = SEC_OID_UNKNOWN;
00457 
00458     switch (privk->keyType) {
00459     case rsaKey:
00460        alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
00461        break;
00462 
00463     case dsaKey:
00464        alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
00465        break;
00466     default:
00467        FatalError("Unknown key type");
00468     }
00469     PORT_Assert(alg != SEC_OID_UNKNOWN);
00470 
00471     rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
00472 
00473     if (rv != SECSuccess) {
00474        PR_fprintf(errorFD, "%s: unable to set signature alg id\n",
00475             PROGRAM_NAME);
00476        errorCount++;
00477        exit (ERRX);
00478     }
00479 
00480     der2.len = 0;
00481     der2.data = NULL;
00482 
00483     dummy = SEC_ASN1EncodeItem
00484         (cert->arena, &der2, cert, CERT_CertificateTemplate);
00485 
00486     if (rv != SECSuccess) {
00487        PR_fprintf(errorFD, "%s: error encoding cert\n", PROGRAM_NAME);
00488        errorCount++;
00489        exit (ERRX);
00490     }
00491 
00492     result2 = (SECItem * ) PORT_ArenaZAlloc (cert->arena, sizeof (SECItem));
00493     if (result2 == NULL)
00494        out_of_memory();
00495 
00496     rv = SEC_DerSignData 
00497         (cert->arena, result2, der2.data, der2.len, privk, alg);
00498 
00499     if (rv != SECSuccess) {
00500        PR_fprintf(errorFD, "can't sign encoded certificate data\n");
00501        errorCount++;
00502        exit (ERRX);
00503     } else if (verbosity >= 0) {
00504        PR_fprintf(outputFD, "certificate has been signed\n");
00505     }
00506 
00507     cert->derCert = *result2;
00508 
00509     return result2;
00510 }
00511 
00512 
00513 /*********************************************************************
00514  *
00515  * i n s t a l l _ c e r t
00516  *
00517  * Installs the cert in the permanent database.
00518  */
00519 static CERTCertificate*
00520 install_cert(CERTCertDBHandle *db, SECItem *derCert, char *nickname)
00521 {
00522     CERTCertificate * newcert;
00523     PK11SlotInfo * newSlot;
00524 
00525     newcert = CERT_DecodeDERCertificate(derCert, PR_TRUE, NULL);
00526 
00527     if (newcert == NULL) {
00528        PR_fprintf(errorFD, "%s: can't create new certificate\n",
00529             PROGRAM_NAME);
00530        errorCount++;
00531        exit (ERRX);
00532     }
00533 
00534     newSlot = PK11_ImportCertForKey(newcert, nickname, NULL /*wincx*/);
00535     if ( newSlot == NULL ) {
00536        PR_fprintf(errorFD, "Unable to install certificate\n");
00537        errorCount++;
00538        exit(ERRX);
00539     }
00540     PK11_FreeSlot(newSlot);
00541 
00542     if (verbosity >= 0) {
00543        PR_fprintf(outputFD, "certificate \"%s\" added to database\n",
00544             nickname);
00545     }
00546 
00547     return newcert;
00548 }
00549 
00550 
00551 /******************************************************************
00552  *
00553  * G e n e r a t e K e y P a i r
00554  */
00555 static SECStatus
00556 GenerateKeyPair(PK11SlotInfo *slot, SECKEYPublicKey **pubk,
00557 SECKEYPrivateKey **privk, int keysize)
00558 {
00559 
00560     PK11RSAGenParams rsaParams;
00561 
00562     if ( keysize == -1 ) {
00563        rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE;
00564     } else {
00565        rsaParams.keySizeInBits = keysize;
00566     }
00567     rsaParams.pe = 0x10001;
00568 
00569     if (PK11_Authenticate( slot, PR_FALSE /*loadCerts*/, NULL /*wincx*/)
00570          != SECSuccess) {
00571        SECU_PrintError(progName, "failure authenticating to key database.\n");
00572        exit(ERRX);
00573     }
00574 
00575     *privk = PK11_GenerateKeyPair (slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams,
00576          
00577         pubk, PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, NULL /*wincx*/ );
00578 
00579     if (*privk != NULL && *pubk != NULL) {
00580        if (verbosity >= 0) {
00581            PR_fprintf(outputFD, "generated public/private key pair\n");
00582        }
00583     } else {
00584        SECU_PrintError(progName, "failure generating key pair\n");
00585        exit (ERRX);
00586     }
00587 
00588     return SECSuccess;
00589 }
00590 
00591 
00592 
00593 /******************************************************************
00594  *
00595  * m a k e _ c e r t _ r e q u e s t
00596  */
00597 static CERTCertificateRequest*
00598 make_cert_request(char *subject, SECKEYPublicKey *pubk)
00599 {
00600     CERTName * subj;
00601     CERTSubjectPublicKeyInfo * spki;
00602 
00603     CERTCertificateRequest * req;
00604 
00605     /* Create info about public key */
00606     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
00607     if (!spki) {
00608        SECU_PrintError(progName, "unable to create subject public key");
00609        exit (ERRX);
00610     }
00611 
00612     subj = CERT_AsciiToName (subject);
00613     if (subj == NULL) {
00614        FatalError("Invalid data in certificate description");
00615     }
00616 
00617     /* Generate certificate request */
00618     req = CERT_CreateCertificateRequest(subj, spki, 0);
00619     if (!req) {
00620        SECU_PrintError(progName, "unable to make certificate request");
00621        exit (ERRX);
00622     }
00623 
00624     if (verbosity >= 0) {
00625        PR_fprintf(outputFD, "certificate request generated\n");
00626     }
00627 
00628     return req;
00629 }
00630 
00631 
00632 /******************************************************************
00633  *
00634  * m a k e _ c e r t
00635  */
00636 static CERTCertificate *
00637 make_cert(CERTCertificateRequest *req, unsigned long serial,
00638 CERTName *ca_subject)
00639 {
00640     CERTCertificate * cert;
00641 
00642     CERTValidity * validity = NULL;
00643 
00644     PRTime now, after;
00645     PRExplodedTime printableTime;
00646 
00647     now = PR_Now();
00648     PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
00649 
00650     printableTime.tm_month += 3;
00651     after = PR_ImplodeTime (&printableTime);
00652 
00653     validity = CERT_CreateValidity (now, after);
00654 
00655     if (validity == NULL) {
00656        PR_fprintf(errorFD, "%s: error creating certificate validity\n",
00657             PROGRAM_NAME);
00658        errorCount++;
00659        exit (ERRX);
00660     }
00661 
00662     cert = CERT_CreateCertificate
00663         (serial, ca_subject, validity, req);
00664 
00665     if (cert == NULL) {
00666        /* should probably be more precise here */
00667        PR_fprintf(errorFD, "%s: error while generating certificate\n",
00668             PROGRAM_NAME);
00669        errorCount++;
00670        exit (ERRX);
00671     }
00672 
00673     return cert;
00674 }
00675 
00676 
00677 /*************************************************************************
00678  *
00679  * o u t p u t _ c a _ c e r t
00680  */
00681 static void   
00682 output_ca_cert (CERTCertificate *cert, CERTCertDBHandle *db)
00683 {
00684     FILE * out;
00685 
00686     SECItem * encodedCertChain;
00687     SEC_PKCS7ContentInfo * certChain;
00688     char      *filename;
00689 
00690     /* the raw */
00691 
00692     filename = PORT_ZAlloc(strlen(DEFAULT_X509_BASENAME) + 8);
00693     if (!filename) 
00694        out_of_memory();
00695 
00696     sprintf(filename, "%s.raw", DEFAULT_X509_BASENAME);
00697     if ((out = fopen (filename, "wb")) == NULL) {
00698        PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
00699             filename);
00700        errorCount++;
00701        exit(ERRX);
00702     }
00703 
00704     certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, db);
00705     encodedCertChain 
00706          = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, NULL);
00707     SEC_PKCS7DestroyContentInfo (certChain);
00708 
00709     if (encodedCertChain) {
00710        fprintf(out, "Content-type: application/x-x509-ca-cert\n\n");
00711        fwrite (encodedCertChain->data, 1, encodedCertChain->len,
00712             out);
00713        SECITEM_FreeItem(encodedCertChain, PR_TRUE);
00714     } else {
00715        PR_fprintf(errorFD, "%s: Can't DER encode this certificate\n",
00716             PROGRAM_NAME);
00717        errorCount++;
00718        exit(ERRX);
00719     }
00720 
00721     fclose (out);
00722 
00723     /* and the cooked */
00724 
00725     sprintf(filename, "%s.cacert", DEFAULT_X509_BASENAME);
00726     if ((out = fopen (filename, "wb")) == NULL) {
00727        PR_fprintf(errorFD, "%s: Can't open %s output file\n", PROGRAM_NAME,
00728             filename);
00729        errorCount++;
00730        return;
00731     }
00732 
00733     fprintf (out, "%s\n%s\n%s\n", 
00734         NS_CERT_HEADER,
00735         BTOA_DataToAscii (cert->derCert.data, cert->derCert.len), 
00736         NS_CERT_TRAILER);
00737 
00738     fclose (out);
00739 
00740     if (verbosity >= 0) {
00741        PR_fprintf(outputFD, "Exported certificate to %s.raw and %s.cacert.\n",
00742                             DEFAULT_X509_BASENAME, DEFAULT_X509_BASENAME);
00743     }
00744 }
00745 
00746