oldfunc.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:36k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include "oldfunc.h"
  34. #include "newproto.h"
  35. #include "messages.h"
  36. /*
  37.  * All possible key size choices.
  38.  */
  39. static SECKeySizeChoiceInfo SECKeySizeChoiceList[] = {
  40.     { NULL, 2048, 0 },
  41.     { NULL, 1024, 1 },
  42.     { NULL, 512,  1 },
  43.     { NULL, 0,    0 }
  44. };
  45. DERTemplate CERTSubjectPublicKeyInfoTemplate[] = {
  46.     { DER_SEQUENCE,
  47.           0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
  48.     { DER_INLINE,
  49.           offsetof(CERTSubjectPublicKeyInfo,algorithm),
  50.           SECAlgorithmIDTemplate, },
  51.     { DER_BIT_STRING,
  52.           offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), },
  53.     { 0, }
  54. };
  55. DERTemplate CERTPublicKeyAndChallengeTemplate[] =
  56. {
  57.     { DER_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
  58.     { DER_ANY, offsetof(CERTPublicKeyAndChallenge,spki), },
  59.     { DER_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge), },
  60.     { 0, }
  61. };
  62. typedef struct {
  63.   SSMControlConnection * ctrl;
  64.   CERTCertificate * cert;
  65.   CERTDERCerts * derCerts;
  66. } caImportCertArg;
  67. /* Used for accepting CA certificate. */
  68. static PRBool acceptssl, acceptmime, acceptobjectsign, acceptcacert;
  69. static  char *nickFmt=NULL, *nickFmtWithNum = NULL;
  70.   
  71. static int pqg_prime_bits(char *str);
  72. static PQGParams * decode_pqg_params(char *str);
  73. static char * GenKey(SSMControlConnection * ctrl, int keysize, char *challenge,
  74.      PRUint32 type, PQGParams *pqg, PK11SlotInfo * slot);
  75. static SSMStatus handle_user_cert(SSMControlConnection * ctrl,
  76.                         CERTCertificate *cert, CERTDERCerts *derCerts);
  77. static SSMStatus handle_ca_cert(SSMControlConnection * ctrl,
  78.        CERTCertificate *cert, CERTDERCerts *derCerts);
  79. static SSMStatus handle_email_cert(SSMControlConnection * ctrl, 
  80.   CERTCertificate * cert,
  81.                               CERTDERCerts * derCerts);
  82. static void SSM_ImportCACert(void * arg);
  83. static int init = 0;
  84. SSMStatus SSM_EnableHighGradeKeyGen(void)
  85. {
  86.   SECKeySizeChoiceList[0].enabled = 1;
  87.   return SSM_SUCCESS;
  88. }
  89. PRBool SSM_KeyGenAllowedForSize(int size)
  90. {
  91.   int i;
  92.   int numChoices = sizeof(SECKeySizeChoiceList)/sizeof(SECKeySizeChoiceInfo);
  93.   for (i=0; i<numChoices; i++) {
  94.     if (SECKeySizeChoiceList[i].size == size && 
  95. SECKeySizeChoiceList[i].enabled) {
  96.       return PR_TRUE;
  97.     }
  98.   }
  99.   return PR_FALSE;
  100. }
  101. SSMStatus InitChoiceList(void) 
  102. {
  103.   SSMTextGenContext *cx;
  104.   
  105.   if (SSMTextGen_NewTopLevelContext(NULL, &cx) != SSM_SUCCESS) {
  106.     goto loser;
  107.   }
  108.   if (SSM_GetUTF8Text(cx, "high_grade", 
  109.      &SECKeySizeChoiceList[0].name) != SSM_SUCCESS) {
  110.     goto loser;
  111.   }
  112.   if (SSM_GetUTF8Text(cx, "medium_grade", 
  113.       &SECKeySizeChoiceList[1].name) != SSM_SUCCESS) {
  114.     goto loser;
  115.   }
  116.   if (SSM_GetUTF8Text(cx, "low_grade", 
  117.       &SECKeySizeChoiceList[2].name) != SSM_SUCCESS) {
  118.     goto loser;
  119.   }
  120.   SSMTextGen_DestroyContext(cx);
  121.   return SSM_SUCCESS;
  122.   loser:
  123.   if (cx != NULL) {
  124.     SSMTextGen_DestroyContext(cx);
  125.   }
  126.   return SSM_FAILURE;
  127. }
  128. char ** SSM_GetKeyChoiceList(char * type, char * pqgString, int *nchoices)
  129. {
  130.   char **     list, *pqg, *end;
  131.   int         i, j, len, primeBits;
  132.   SSMStatus rv;
  133.   if (!init) {
  134.     rv = InitChoiceList();
  135.     if (rv != SSM_SUCCESS) {
  136.       PR_ASSERT(!"Could not initialize the choice list for key gen layout!!");
  137.       return NULL;
  138.     }
  139.     init = 1;
  140.   }
  141.   len = sizeof (SECKeySizeChoiceList) / sizeof (SECKeySizeChoiceInfo);
  142.   list = SSM_ZNEW_ARRAY(char*, len);
  143.   if (type && (PORT_Strcasecmp(type, "dsa") == 0)) {
  144.         if (pqgString == NULL) {
  145.             list[0] = NULL;
  146.             return list;
  147.         }
  148.         pqg = pqgString;
  149.         j = 0;
  150.         do {
  151.             end = PORT_Strchr(pqg, ',');
  152.             if (end != NULL)
  153.                 *end = '';
  154.             primeBits = pqg_prime_bits(pqg);
  155.             for (i = 0; SECKeySizeChoiceList[i].size != 0; i++) {
  156.                 if (SECKeySizeChoiceList[i].size == primeBits) {
  157.                     list[j++] = strdup(SECKeySizeChoiceList[i].name);
  158.                     break;
  159.                 }
  160.             }
  161.             pqg = end + 1;
  162.         } while (end != NULL);
  163.     } else {
  164.         int maxKeyBits = SSM_MAX_KEY_BITS;
  165.         j = 0;
  166.         for (i = (policyType == ssmDomestic) ? 0 : 1; 
  167.      SECKeySizeChoiceList[i].size != 0; i++) {
  168.             if (SECKeySizeChoiceList[i].size <= maxKeyBits)
  169.                 list[j++] = strdup(SECKeySizeChoiceList[i].name);
  170.         }
  171.     }
  172.     if (pqgString != NULL)
  173.         PORT_Free(pqgString);
  174.     *nchoices = j;
  175.     return list;
  176. }
  177. char * SSMControlConnection_GenerateKeyOldStyle(SSMControlConnection * ctrl,
  178.    char *choiceString, char *challenge,
  179.                    char *typeString, char *pqgString)
  180. {
  181.   SECKeySizeChoiceInfo *choice = SECKeySizeChoiceList;
  182.   char *end, *str;
  183.   PQGParams *pqg = NULL;
  184.   int primeBits;
  185.   KeyType type; 
  186.   char * keystring = NULL;
  187.   PK11SlotInfo *slot;
  188.   SSMKeyGenContext * ct = NULL;
  189.   SSMKeyGenContextCreateArg arg;
  190.   PRUint32 keyGenMechanism;
  191.   SSMStatus rv;
  192.   if (choiceString == NULL) {
  193.     goto loser;
  194.   }
  195.   while (PORT_Strcmp(choice->name, choiceString) != 0)
  196.     choice++;
  197.   if (PORT_Strcmp(challenge, "null") == 0) {
  198.     challenge = NULL;
  199.   }
  200.   if ((PORT_Strcmp(typeString, "null") == 0) || 
  201.       (PORT_Strcasecmp(typeString, "rsa") == 0)) {
  202.     type = rsaKey;
  203.     keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
  204.   } else if (PORT_Strcasecmp(typeString, "dsa") == 0) {
  205.     type = dsaKey;
  206.     keyGenMechanism = CKM_DSA_KEY_PAIR_GEN;
  207.     if (PORT_Strcmp(pqgString, "null") == 0)
  208.       goto loser;
  209.     str = pqgString;
  210.     do {
  211.       end = PORT_Strchr(str, ',');
  212.       if (end != NULL)
  213.         *end = '';
  214.       primeBits = pqg_prime_bits(str);
  215.       if (choice->size == primeBits)
  216.         goto found_match;
  217.       str = end + 1;
  218.     } while (end != NULL);
  219.     goto loser;
  220. found_match:
  221.     pqg = decode_pqg_params(str);
  222.   } else {
  223.     goto loser; 
  224.   }  
  225.  
  226.   /* 
  227.    * To get slot we first create a keygen context, and 
  228.    * use its facilities to find a slot for our key generation
  229.    */   
  230.   arg.parent  = ctrl;
  231.   arg.type = SSM_OLD_STYLE_KEYGEN;
  232.   arg.param = NULL;
  233.   SSM_DEBUG("Creating key gen context.n");
  234.   rv = SSMKeyGenContext_Create(&arg, ctrl, (SSMResource **)&ct);
  235.   if (rv != PR_SUCCESS) {
  236.     SSM_DEBUG("Could not create KeyGenContext for oldStyleKeyGen.n");
  237.     goto loser;
  238.   }
  239.   ct->mech = keyGenMechanism;
  240.   rv = SSMKeyGenContext_GetSlot(ct, keyGenMechanism);
  241.   if (rv != SSM_SUCCESS)
  242.     goto loser;
  243.   slot = ct->slot;
  244.   keystring = GenKey(ctrl,choice->size, challenge, keyGenMechanism, pqg, slot);
  245.   /* received a Cancel event from UI */
  246.   if (ct->m_userCancel) {
  247.     PR_Free(keystring);
  248.     keystring = NULL;
  249.   }
  250. loser:
  251.   if (ct) 
  252.     SSMKeyGenContext_Shutdown((SSMResource *)ct, rv);
  253.   return keystring; 
  254. }
  255. static PQGParams *
  256. decode_pqg_params(char *str)
  257. {
  258.     char *buf;
  259.     unsigned int len;
  260.     PRArenaPool *arena;
  261.     PQGParams *params;
  262.     SECStatus status;
  263.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  264.     if (arena == NULL)
  265.         return NULL;
  266.     params = (PQGParams *) PORT_ArenaZAlloc(arena, sizeof(PQGParams));
  267.     if (params == NULL)
  268.         goto loser;
  269.     params->arena = arena;
  270.     buf = (char *)ATOB_AsciiToData(str, &len);
  271.     if ((buf == NULL) || (len == 0))
  272.         goto loser;
  273.     status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
  274.     if (status != SECSuccess)
  275.         goto loser;
  276.     return params;
  277. loser:
  278.     if (arena != NULL)
  279.         PORT_FreeArena(arena, PR_FALSE);
  280.     return NULL;
  281. }
  282. static int
  283. pqg_prime_bits(char *str)
  284. {
  285.     PQGParams *params = NULL;
  286.     int primeBits = 0, i;
  287.     params = decode_pqg_params(str);
  288.     if (params == NULL)
  289.         goto done; /* lose */
  290.     for (i = 0; params->prime.data[i] == 0; i++)
  291.         /* empty */;
  292.     primeBits = (params->prime.len - i) * 8;
  293. done:
  294.     if (params != NULL)
  295.         PQG_DestroyParams(params);
  296.     return primeBits;
  297. }
  298. static char * 
  299. GenKey(SSMControlConnection * ctrl, int keysize, char *challenge, 
  300.        PRUint32 type, PQGParams *pqg, PK11SlotInfo *slot)
  301. {
  302.     SECKEYPrivateKey *privateKey = NULL;
  303.     SECKEYPublicKey *publicKey = NULL;
  304.     CERTSubjectPublicKeyInfo *spkInfo = NULL;
  305.     PRArenaPool *arena = NULL;
  306.     SECStatus rv = SECFailure;
  307.     SECItem spkiItem;
  308.     SECItem pkacItem;
  309.     SECItem signedItem;
  310.     CERTPublicKeyAndChallenge pkac;
  311.     char *keystring = NULL;
  312.     CK_MECHANISM_TYPE mechanism = type;
  313.     PK11RSAGenParams rsaParams;
  314.     void *params;
  315.     SECOidTag algTag;
  316.     
  317.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  318.     if (arena == NULL) {
  319. goto done;
  320.     }
  321.     /*
  322.      * Create a new key pair.
  323.      */
  324.     /* Switch statement goes here for DSA */
  325.     switch (mechanism) {
  326.       case CKM_RSA_PKCS_KEY_PAIR_GEN:
  327. rsaParams.keySizeInBits = keysize;
  328. rsaParams.pe = 65537L;
  329. algTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
  330. params = &rsaParams;
  331. break;
  332.       case CKM_DSA_KEY_PAIR_GEN:
  333. params = pqg;
  334. algTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
  335. break;
  336.       default:
  337. goto done;
  338. break;
  339.     }
  340.     privateKey = PK11_GenerateKeyPair(slot, mechanism, params,
  341.      &publicKey, PR_TRUE, PR_TRUE, NULL);
  342.     if (privateKey == NULL) {
  343. goto done;
  344.     }
  345.     /* just in case we'll need to authenticate to the db -jp */
  346.     privateKey->wincx = ctrl;
  347.     /*
  348.      * Create a subject public key info from the public key.
  349.      */
  350.     spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey);
  351.     if ( spkInfo == NULL ) {
  352. goto done;
  353.     }
  354.     
  355.     /*
  356.      * Now DER encode the whole subjectPublicKeyInfo.
  357.      */
  358.     rv=DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate, spkInfo);
  359.     if (rv != SECSuccess) {
  360. goto done;
  361.     }
  362.     /*
  363.      * set up the PublicKeyAndChallenge data structure, then DER encode it
  364.      */
  365.     pkac.spki = spkiItem;
  366.     if ( challenge ) {
  367. pkac.challenge.len = PORT_Strlen(challenge);
  368.     } else {
  369. pkac.challenge.len = 0;
  370.     }
  371.     pkac.challenge.data = (unsigned char *)challenge;
  372.     
  373.     rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate, &pkac);
  374.     if ( rv != SECSuccess ) {
  375. goto done;
  376.     }
  377.     /*
  378.      * now sign the DER encoded PublicKeyAndChallenge
  379.      */
  380.     rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len,
  381.  privateKey, algTag);
  382.     if ( rv != SECSuccess ) {
  383. goto done;
  384.     }
  385.     
  386.     /*
  387.      * Convert the signed public key and challenge into base64/ascii.
  388.      */
  389.     keystring = BTOA_DataToAscii(signedItem.data, signedItem.len);
  390.     SSM_DEBUG("Created following string for KEYGEN:n%sn", keystring);
  391.     
  392.  done:
  393.     /*
  394.      * Destroy the private key ASAP, so that we don't leave a copy in
  395.      * memory that some evil hacker can get at.
  396.      */
  397.     if ( rv != SECSuccess ) {
  398. if ( privateKey ) {
  399.   PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID);
  400.   SECKEY_DestroyPrivateKey(privateKey);
  401. }
  402. if ( publicKey ) 
  403.   PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID);
  404.     }
  405.     if ( spkInfo ) 
  406.       SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
  407.     if ( publicKey ) 
  408. SECKEY_DestroyPublicKey(publicKey);
  409.     if ( arena ) 
  410.       PORT_FreeArena(arena, PR_TRUE);
  411.     return keystring;
  412. }
  413. static SECStatus
  414. collect_certs(void *arg, SECItem **certs, int numcerts)
  415. {
  416.     CERTDERCerts *collectArgs;
  417.     SECItem *cert;
  418.     SECStatus rv;
  419.     collectArgs = (CERTDERCerts *)arg;
  420.     collectArgs->numcerts = numcerts;
  421.     collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena,
  422.                                            sizeof(SECItem) * numcerts);
  423.     if ( collectArgs->rawCerts == NULL ) 
  424.       return(SECFailure);
  425.     cert = collectArgs->rawCerts;
  426.     while ( numcerts-- ) {
  427.         rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs);
  428.         if ( rv == SECFailure ) 
  429.   return(SECFailure);
  430. cert++;
  431. certs++;
  432.     }
  433.     return (SECSuccess);
  434. }
  435. static SSMStatus handle_user_cert(SSMControlConnection * ctrl, 
  436. CERTCertificate *cert, CERTDERCerts *derCerts)
  437. {
  438.     PK11SlotInfo *slot;
  439.     char * nickname = NULL;
  440.     SECStatus rv;
  441.     int numCACerts;
  442.     SECItem *CACerts;
  443.     slot = PK11_KeyForCertExists(cert, NULL, ctrl);
  444.     if ( slot == NULL ) {
  445.       SSM_DEBUG("Can't find keydb with the key for the new cert!n");
  446.       goto loser;
  447.     }
  448.     PK11_FreeSlot(slot);
  449.     if (!certificate_conflict(ctrl, &cert->derCert, 
  450.       ctrl->m_certdb, PR_TRUE)) {
  451.       /*
  452.        * This cert is already in the database, no need to re-import.
  453.        */
  454.       goto loser;
  455.     }
  456.     /* pick a nickname for the cert */
  457.     if (cert->subjectList && cert->subjectList->entry && 
  458.         cert->subjectList->entry->nickname)
  459.       nickname = cert->subjectList->entry->nickname;
  460.     else nickname = default_nickname(cert, ctrl);
  461.     /*
  462.     UI for cert installation goes here - no UI here?
  463.     */
  464.     /* user wants to import the cert */
  465.     slot = PK11_ImportCertForKey(cert, nickname, ctrl);
  466.     if (!slot) 
  467.       goto loser;
  468.     PK11_FreeSlot(slot);
  469.     SSM_UseAsDefaultEmailIfNoneSet(ctrl, cert, PR_FALSE);
  470.     numCACerts = derCerts->numcerts - 1;
  471.     if (numCACerts) {
  472.       CACerts = derCerts->rawCerts+1;
  473.       
  474.       rv = CERT_ImportCAChain(CACerts, numCACerts, certUsageUserCertImport);
  475.       /* We really should send some notice to the user that importing the
  476.        * CA certs failed if rv is SECSuccess.
  477.        */
  478.     }
  479.     
  480.     return PR_SUCCESS;
  481.  loser:
  482.     CERT_DestroyCertificate(cert);
  483.     return PR_FAILURE;
  484. }
  485. static SSMStatus handle_ca_cert(SSMControlConnection * ctrl, 
  486.        CERTCertificate *cert, CERTDERCerts *derCerts)
  487. {
  488.   caImportCertArg * arg = NULL;
  489.   arg = (caImportCertArg *) PORT_ZAlloc(sizeof(caImportCertArg));
  490.   arg->ctrl = ctrl;
  491.   arg->cert = CERT_DupCertificate(cert);
  492.   arg->derCerts = derCerts;
  493.   SSM_CreateAndRegisterThread(PR_USER_THREAD, SSM_ImportCACert, (void *)arg, 
  494.   PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, 
  495.   PR_UNJOINABLE_THREAD, 0);
  496.   return PR_SUCCESS;
  497. }
  498. PRBool
  499. certificate_conflict(SSMControlConnection * cx, SECItem * derCert, 
  500.                      CERTCertDBHandle * handle, PRBool sendUIEvent)
  501. {
  502.    SECStatus rv;
  503.    SECItem key;
  504.    PRArenaPool *arena = NULL;
  505.    PRBool ret;
  506.    CERTCertificate *cert;
  507.    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  508.    if (!arena) 
  509.      goto loser;
  510.    
  511.    /* get the key (issuer+cn) from the cert */
  512.    rv = CERT_KeyFromDERCert(arena, derCert, &key);
  513.    if ( rv != SECSuccess ) 
  514.      goto loser;
  515.    
  516.    /* check if the same cert already exists */
  517.    cert = CERT_FindCertByKey(handle, &key);
  518.    if ( cert ) {
  519.        if ( cert->isperm && ( cert->nickname == NULL ) &&
  520.            ( cert->emailAddr == NULL ) ) {
  521.            /* if the cert doesn't have a nickname or email addr, it is
  522.             * bogus cruft, so delete it
  523.             */
  524.            SEC_DeletePermCertificate(cert);
  525.        } else if ( cert->isperm ) {
  526.            SSM_DEBUG("Found existing cert with the same key!n");
  527.            rv = SECFailure;
  528.            if (sendUIEvent && (SSMControlConnection_SendUIEvent(cx, 
  529.                                                 "get", "cert_already_exists",
  530. NULL, NULL, NULL, PR_TRUE)) == SSM_SUCCESS)
  531.      rv = SECSuccess;
  532.            ret = PR_FALSE;
  533.            goto done;
  534.        } else 
  535.  CERT_DestroyCertificate(cert);
  536.    } /* end of same-cert-exists */
  537.    
  538.    ret = PR_TRUE;
  539.    goto done;
  540.    
  541. loser:
  542.     ret = PR_FALSE;
  543. done:
  544.     if ( arena ) 
  545.       PORT_FreeArena(arena, PR_FALSE);
  546.     return ret;
  547. }
  548. typedef struct UserCertImprtArgStr {
  549.   SSMControlConnection *ctrl;
  550.   SECItem *msg;
  551. } UserCertImportArg;
  552. void ssm_import_user_cert_thread(void *arg) {
  553.   UserCertImportArg *impArg = (UserCertImportArg*)arg;
  554.   SSMControlConnection *ctrl = impArg->ctrl;
  555.   SECItem *msg = impArg->msg;
  556.   SSMStatus rv = PR_FAILURE;
  557.   CERTDERCerts * collectArgs;
  558.   PRArenaPool *arena;
  559.   CERTCertificate * cert=NULL;
  560.   SSMResourceID certID;
  561.   SSMResource * certResource;
  562.   PRBool noconflict;
  563.   DecodeAndCreateTempCertRequest request;
  564.   SingleNumMessage reply;
  565.   
  566.   if (!msg || !msg->data)
  567.     goto loser;
  568.  
  569.   SSM_RegisterThread("cert import", NULL);
  570.   if (CMT_DecodeMessage(DecodeAndCreateTempCertRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
  571.       goto loser;
  572.   }
  573.   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  574.   if ( arena == NULL ) 
  575.     goto loser;
  576.   collectArgs = (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts));
  577.   if ( collectArgs == NULL ) 
  578.     goto loser;
  579.   collectArgs->arena = arena;
  580.   rv = CERT_DecodeCertPackage((char *) request.cert.data, (int) request.cert.len, collect_certs, 
  581.       (void *)collectArgs);
  582.   if (rv != PR_SUCCESS)
  583.     goto loser;
  584.   /* check for conflicts */
  585.   noconflict = certificate_conflict(ctrl,collectArgs->rawCerts,
  586.                                     ctrl->m_certdb, PR_TRUE);
  587.   if (!noconflict) 
  588.     goto loser;   /* certificate with this key already exists in the db */
  589.   cert = CERT_NewTempCertificate(ctrl->m_certdb, collectArgs->rawCerts,
  590.                         (char *)NULL, PR_FALSE, PR_TRUE);
  591.   if (!cert)
  592.     goto loser;
  593.   /* create certificate resource so we can return it to client */
  594.   rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert, ctrl, &certID, &certResource);
  595.   if (rv != PR_SUCCESS) {
  596.     SSM_DEBUG("In decode&create tmp cert: can't create certificate resource.n");
  597.   goto loser;
  598.   }
  599.   /* Get a client reference to it */
  600.   SSM_ClientGetResourceReference(certResource, &certID);
  601.   switch (request.type) {
  602.     case SEC_CERT_CLASS_USER:
  603.       rv = handle_user_cert(ctrl, cert, collectArgs);
  604.       break;
  605.     case SEC_CERT_CLASS_CA:  
  606.       rv = handle_ca_cert(ctrl, cert, collectArgs);
  607.       break;
  608.     case SEC_CERT_CLASS_SERVER:
  609.       /* why destroy class server certs? */
  610.       CERT_DestroyCertificate(cert);
  611.       break;
  612.     case SEC_CERT_CLASS_EMAIL:
  613.       rv = handle_email_cert(ctrl, cert, collectArgs);
  614.       break;
  615.     default:
  616.       rv = PR_FAILURE;
  617.       SSM_DEBUG("ProcessDecodeAndCreateCertRequest: unknown cert classn");
  618.   }
  619.   if (rv != PR_SUCCESS) 
  620.     goto loser;
  621.  
  622.   /* create reply */
  623.   msg->type = (SECItemType) (SSM_REPLY_OK_MESSAGE | SSM_CERT_ACTION | SSM_DECODE_TEMP_CERT);
  624.   msg->len  = 0;
  625.   reply.value = certID;
  626.   if (CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply) != CMTSuccess) {
  627.       goto loser;
  628.   }
  629.   SSM_DEBUG("queueing reply: type %lx, len %ld.n", msg->type, msg->len);
  630.   SSM_SendQMessage(ctrl->m_controlOutQ, 
  631.    SSM_PRIORITY_NORMAL,
  632.    msg->type, msg->len, 
  633.    (char *)msg->data, PR_TRUE);
  634.   if (rv == PR_SUCCESS)
  635.     goto done;
  636.  loser:
  637.   {
  638.     SingleNumMessage reply;
  639.     
  640.     msg->type = (SECItemType) SSM_REPLY_ERR_MESSAGE;
  641.     reply.value = rv;
  642.     CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
  643.     if (!msg->data || msg->len == 0)
  644.       goto loser;
  645.     else rv = PR_SUCCESS;
  646.   }
  647.   SSM_DEBUG("queueing reply: type %lx, len %ld.n", msg->type, msg->len);
  648.   SSM_SendQMessage(ctrl->m_controlOutQ, 
  649.    SSM_PRIORITY_NORMAL,
  650.    msg->type, msg->len, 
  651.    (char *)msg->data, PR_TRUE);
  652.   
  653.   if (rv == PR_SUCCESS)
  654.     rv = PR_FAILURE;
  655.   if (arena) 
  656.     PORT_FreeArena(arena, PR_TRUE);
  657.  done:
  658.   SECITEM_FreeItem(msg, PR_TRUE);
  659.   SSM_FreeResource(&ctrl->super.super);
  660.   if (cert != NULL)
  661.     CERT_DestroyCertificate(cert);
  662.   return;
  663. }
  664. SSMStatus
  665. SSMControlConnection_ProcessDecodeAndCreateTempCert(SSMControlConnection * 
  666.     ctrl, SECItem * msg)
  667. {
  668.   UserCertImportArg *impArg;
  669.   impArg = SSM_ZNEW(UserCertImportArg);
  670.   if (impArg == NULL) {
  671.     return SSM_FAILURE;
  672.   }
  673.   impArg->ctrl = ctrl;
  674.   impArg->msg = SECITEM_DupItem(msg);
  675.   SSMControlConnection_RecycleItem(msg);
  676.   SSM_GetResourceReference(&ctrl->super.super);
  677.   if (SSM_CreateAndRegisterThread(PR_USER_THREAD,
  678.      ssm_import_user_cert_thread,
  679.      (void*)impArg,
  680.      PR_PRIORITY_NORMAL,
  681.      PR_LOCAL_THREAD,
  682.      PR_UNJOINABLE_THREAD, 0) == NULL) {
  683.     SSM_DEBUG("Couldn't create thread for importing cert.");
  684.     return SSM_FAILURE;
  685.   }
  686.   return SSM_ERR_DEFER_RESPONSE;
  687. }
  688. static SSMStatus 
  689. handle_email_cert(SSMControlConnection * ctrl, CERTCertificate * cert, 
  690.   CERTDERCerts * derCerts)
  691. {
  692.   SSMStatus rv = PR_FAILURE;
  693.   SECItem **rawCerts;
  694.   int numcerts;
  695.   int i;
  696.   
  697.   numcerts = derCerts->numcerts;
  698.   
  699.   rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
  700.   if ( !rawCerts ) 
  701.     goto loser;
  702.   for ( i = 0; i < numcerts; i++ ) {
  703.     rawCerts[i] = &derCerts->rawCerts[i];
  704.   }
  705.   
  706.   rv = CERT_ImportCerts(cert->dbhandle, certUsageEmailSigner,
  707. numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE,
  708. NULL);
  709.   if ( rv == SECSuccess ) {
  710.     rv = CERT_SaveSMimeProfile(cert, NULL, NULL);
  711.   }
  712.   
  713.   PORT_Free(rawCerts);
  714.   
  715.  loser:
  716.   return rv;
  717. }
  718. char *
  719. default_nickname(CERTCertificate *cert, SSMControlConnection *conn)
  720. {   
  721.   char *username = NULL;
  722.   char *caname = NULL;
  723.   char *nickname = NULL;
  724.   char *tmp = NULL;
  725.   int count;
  726.   CERTCertificate *dummycert;
  727.   SSMTextGenContext *cx = NULL;
  728.   PK11SlotInfo *slot=NULL;
  729.   CK_OBJECT_HANDLE keyHandle;
  730.   username = CERT_GetCommonName(&cert->subject);
  731.   if ( username == NULL ) 
  732.     username = strdup("");
  733.   if ( username == NULL ) 
  734.     goto loser;
  735.     
  736.   caname = CERT_GetOrgName(&cert->issuer);
  737.   if ( caname == NULL ) 
  738.     caname = strdup("");
  739.   
  740.   if ( caname == NULL ) 
  741.     goto loser;
  742.   
  743.   count = 1;
  744.   if (nickFmt == NULL) {
  745.     if (SSMTextGen_NewTopLevelContext(NULL, &cx) != SSM_SUCCESS) {
  746.       goto loser;
  747.     }
  748.     if (SSM_FindUTF8StringInBundles(cx, "nick_template", 
  749.     &nickFmt) != SSM_SUCCESS) {
  750.       goto loser;
  751.     }
  752.     if (SSM_FindUTF8StringInBundles(cx, "nick_template_with_num", 
  753.     &nickFmtWithNum) != SSM_SUCCESS) {
  754.       goto loser;
  755.     }
  756.   }
  757.   nickname = PR_smprintf(nickFmt, username, caname);
  758.   /*
  759.    * We need to see if the private key exists on a token, if it does
  760.    * then we need to check for nicknames that already exist on the smart
  761.    * card.
  762.    */
  763.   slot = PK11_KeyForCertExists(cert, &keyHandle, conn);
  764.   if (slot == NULL) {
  765.     goto loser;
  766.   }
  767.   if (!PK11_IsInternal(slot)) {
  768.     tmp = PR_smprintf("%s:%s", PK11_GetTokenName(slot), nickname);
  769.     PR_Free(nickname);
  770.     nickname = tmp;
  771.     tmp = NULL;
  772.   }
  773.   tmp = nickname;
  774.   while ( 1 ) {
  775.     if ( count > 1 ) {
  776.       nickname = PR_smprintf("%s #%d", tmp, count);
  777.     }
  778.     
  779.     if ( nickname == NULL ) 
  780.       goto loser;
  781.  
  782.     _ssm_compress_spaces(nickname);
  783.     if (PK11_IsInternal(slot)) {
  784.       /* look up the nickname to make sure it isn't in use already */
  785.       dummycert = CERT_FindCertByNickname(conn->m_certdb, nickname);
  786.       
  787.     } else {
  788.       /*
  789.        * Check the cert against others that already live on the smart 
  790.        * card.
  791.        */
  792.       dummycert = PK11_FindCertFromNickname(nickname, conn);
  793.       if (dummycert != NULL) {
  794. /*
  795.  * Make sure the subject names are different.
  796.  */ 
  797. if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual)
  798. {
  799.   /*
  800.    * There is another certificate with the same nickname and
  801.    * the same subject name on the smart card, so let's use this
  802.    * nickname.
  803.    */
  804.   CERT_DestroyCertificate(dummycert);
  805.   dummycert = NULL;
  806. }
  807.       }
  808.     }
  809.     if ( dummycert == NULL ) 
  810.       goto done;
  811.     
  812.     /* found a cert, destroy it and loop */
  813.     CERT_DestroyCertificate(dummycert);
  814.     if (tmp != nickname) PR_Free(nickname);
  815.     count++;
  816.   } /* end of while(1) */
  817.     
  818. loser:
  819.     if ( nickname ) 
  820.       PORT_Free(nickname);
  821.     nickname = NULL;
  822. done:
  823.     if ( caname ) 
  824.       PORT_Free(caname);
  825.     if ( username ) 
  826.       PORT_Free(username);
  827.     if ( cx )
  828.       SSMTextGen_DestroyContext(cx);
  829.     if (slot != NULL) {
  830.       PK11_FreeSlot(slot);
  831.       if (nickname != NULL) {
  832. tmp = nickname;
  833. nickname = PL_strchr(tmp, ':');
  834. if (nickname != NULL) {
  835.   nickname++;
  836.   nickname = PL_strdup(nickname);
  837.   PR_Free(tmp);
  838. } else {
  839.   nickname = tmp;
  840.   tmp = NULL;
  841. }
  842.       }
  843.     }
  844.     PR_FREEIF(tmp);
  845.     return(nickname);
  846. }
  847. SSMStatus SSM_OKButtonCommandHandler(HTTPRequest * req)
  848. {
  849.   char * tmpStr = NULL;
  850.   SSMStatus rv;
  851.   /* check the base ref */
  852.   rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
  853.   if (rv != SSM_SUCCESS ||
  854.     PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
  855.     goto loser;
  856.   }
  857.   /* close the window */
  858.   rv = SSM_HTTPCloseAndSleep(req);
  859.   
  860. loser:
  861.   return rv;
  862. }
  863. SSMStatus SSM_CertCAImportCommandHandler1(HTTPRequest *req)
  864. {
  865.     SSMStatus rv;
  866.     char * tmpStr = NULL;
  867.     /* make sure you got the right baseRef */
  868.     rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
  869.     if (rv != SSM_SUCCESS ||
  870.         PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
  871.         goto loser;
  872.     }
  873.     /* close the first window */
  874.     rv = SSM_HTTPCloseAndSleep(req);
  875.     if (rv != SSM_SUCCESS)
  876.       SSM_DEBUG("Errors closing ImportCAStep1 window: %dn", rv);
  877.  
  878.     /* figure out the buttons */
  879.     rv =  SSM_HTTPParamValue(req, "do_cancel", &tmpStr);
  880.     if (rv == SSM_SUCCESS) {
  881.       /* cancel button was clicked */
  882.       return SSM_SUCCESS;
  883.     }
  884.     rv = SSM_HTTPParamValue(req, "do_ok", &tmpStr);
  885.     if (rv == SSM_SUCCESS) {
  886.       /* user wants to proceed */
  887.       rv=SSMControlConnection_SendUIEvent(req->ctrlconn, 
  888.           "get", "import_ca_cert2", 
  889.   req->target, NULL, 
  890.   &req->target->m_clientContext, 
  891.   PR_TRUE);
  892.       if (rv != PR_SUCCESS) {
  893.       /* problem! */
  894.         SSM_DEBUG("Cannot fire second dialog for CA cert importation!n");
  895. SSM_NotifyUIEvent(req->target);
  896.       }
  897.     }
  898.     else 
  899.       SSM_DEBUG("Cannot identify button pressed in first importCACert dialog!n");
  900. loser:
  901.     return rv; 
  902. }
  903. SSMStatus SSM_CertCAImportCommandHandler2(HTTPRequest * req)
  904. {
  905.     SSMStatus rv;
  906.     char * tmpStr = NULL;
  907.     /* if we got here, user must have hit OK for import CA cert */
  908.     acceptcacert = PR_TRUE;
  909.     /* check parameters */
  910.     rv = SSM_HTTPParamValue(req, "acceptssl", &tmpStr);
  911.     if (rv == SSM_SUCCESS) 
  912.       acceptssl = PR_TRUE;
  913.     
  914.     rv = SSM_HTTPParamValue(req, "acceptemail", &tmpStr);
  915.     if (rv == SSM_SUCCESS) 
  916.       acceptmime = PR_TRUE;
  917.     
  918.     rv = SSM_HTTPParamValue(req, "acceptobject", &tmpStr);
  919.     if (rv == SSM_SUCCESS) 
  920.       acceptobjectsign = PR_TRUE;
  921.     
  922.  
  923.     SSM_NotifyUIEvent(req->target);
  924.     return rv;
  925. }
  926. SSMStatus SSM_SubmitFormFromButtonAndFreeTarget(HTTPRequest *req)
  927. {
  928.    SSMStatus rv;
  929.    rv = SSM_SubmitFormFromButtonHandler(req);
  930.    if (req->target) {
  931.      SSM_FreeResource(req->target);
  932.    }
  933.    return rv;
  934. }
  935. SSMStatus SSM_SubmitFormFromButtonHandler(HTTPRequest *req)
  936. {
  937.    SSMResource * res = NULL;
  938.    char * value;
  939.    SSMStatus rv = SSM_FAILURE;
  940.    res = (req->target) ? req->target : (SSMResource *) req->ctrlconn;
  941.    rv = SSM_HTTPParamValue(req, "do_cancel", &value);
  942.    if (rv == SSM_SUCCESS) {
  943.      /* user hit "Cancel", exit */
  944.      res->m_buttonType = SSM_BUTTON_CANCEL;
  945.      goto finished; 
  946.    }
  947.    res->m_buttonType = SSM_BUTTON_OK;
  948.    /* set up the stage to process the main form */ 
  949.    rv = SSM_HTTPParamValue(req, "formName", &value);
  950.    if (rv != SSM_SUCCESS) {
  951.      SSM_DEBUG("Error in SubmitFormHandler: no form name given!n");
  952.      goto finished;
  953.    }
  954.    if (res->m_formName)  /* hmm... will it crash here? */
  955.      PR_Free(res->m_formName);
  956.    res->m_formName = PL_strdup(value);
  957.         
  958.    rv = SSM_HTTPCloseAndSleep(req);
  959.    if (rv != PR_SUCCESS)
  960.      SSM_DEBUG("SubmitForm: Problem closing dialog box!n");
  961.    
  962.    return rv;
  963. finished:
  964.    /* no more event handlers called on this event, notify ctrlconn */
  965.    SSM_HTTPCloseWindow(req);
  966.    /* if this is a UIEvent, notify owner connection */
  967.    if (res->m_UILock)
  968.      SSM_NotifyUIEvent(res);
  969.    return rv;
  970. }
  971.    
  972. static void SSM_ImportCACert(void * arg)
  973. {
  974.   CERTCertTrust trust;
  975.   char * nickname = NULL;
  976.   caImportCertArg * certArg = (caImportCertArg *)arg;
  977.   CERTCertificate * cert = certArg->cert;
  978.   SSMControlConnection * ctrl = certArg->ctrl;
  979.   CERTDERCerts * derCerts = certArg->derCerts;
  980.   SSMResource * certObj = NULL;
  981.   SSMResourceID certRID;
  982.   SSMStatus rv;
  983.   char * params;
  984.   char * htmlNickname;
  985.   /* UI asks - do you want to import this cert for 
  986.    * 1) email
  987.    * 2) web sites
  988.    * 3) objects
  989.    * UI sets accept, acceptssl, acceptmime, acceptobjectsign
  990.    */
  991.   acceptssl = acceptmime = acceptobjectsign = acceptcacert = PR_FALSE;
  992.   /* create resource for that cert */
  993.   rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert, 
  994.   ctrl, &certRID, &certObj);
  995.   if (rv != SSM_SUCCESS) {
  996.     SSM_DEBUG("SSM_ImportCACert: can't create certificate resource!n");
  997.     goto done;
  998.   }
  999.   
  1000.   /* pick a nickname for the cert */
  1001.   nickname = CERT_GetCommonName(&cert->subject);
  1002.   if (nickname == NULL) {
  1003.     char *ou = NULL;
  1004.     char *orgName = NULL;
  1005.     /* Let's find something we can use as a nickname.*/
  1006.     ou = CERT_GetOrgUnitName(&cert->subject);
  1007.     orgName = CERT_GetOrgName(&cert->subject);
  1008.     PR_ASSERT(orgName || ou);
  1009.     nickname = PR_smprintf("%s%s%s", (orgName) ? orgName : "",
  1010.              (orgName  && ou) ? " - " : "",
  1011.              (ou) ? ou : "");
  1012.     PR_FREEIF(ou);
  1013.     PR_FREEIF(orgName);
  1014.   }
  1015.   htmlNickname = SSM_ConvertStringToHTMLString(nickname);
  1016.   PR_ASSERT(htmlNickname);
  1017.   params = PR_smprintf("certresource=%d&nickname=%s", certRID, htmlNickname);
  1018.   PR_Free(htmlNickname);
  1019.   SSM_LockUIEvent(certObj);
  1020.   rv = SSMControlConnection_SendUIEvent(ctrl, "get", "import_ca_cert1", 
  1021. certObj, params, 
  1022. &certObj->m_clientContext, PR_TRUE);
  1023.   if (rv != PR_SUCCESS)  {
  1024.     SSM_DEBUG("Cannot fire up first import CA cert dialog!n");
  1025.     goto done;
  1026.   }
  1027.   SSM_WaitUIEvent(certObj, PR_INTERVAL_NO_TIMEOUT);
  1028.   if (!acceptcacert)
  1029.     goto done;
  1030.   PORT_Memset((void *)&trust, 0, sizeof(trust));
  1031.   if (acceptssl) 
  1032.     trust.sslFlags = CERTDB_VALID_CA | CERTDB_TRUSTED_CA;
  1033.   else trust.sslFlags = CERTDB_VALID_CA;
  1034.   if (acceptmime) 
  1035.     trust.emailFlags = CERTDB_VALID_CA | CERTDB_TRUSTED_CA;
  1036.   else trust.emailFlags = CERTDB_VALID_CA;
  1037.   if (acceptobjectsign)
  1038.     trust.objectSigningFlags = CERTDB_VALID_CA | CERTDB_TRUSTED_CA;
  1039.   else
  1040.     trust.objectSigningFlags = CERTDB_VALID_CA;
  1041.   rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
  1042.   if (rv != PR_SUCCESS) {
  1043.     /* tell user we're having problems */;
  1044.     goto done;
  1045.   }
  1046.   if (derCerts->numcerts > 1) {
  1047.     rv = CERT_ImportCAChain(derCerts->rawCerts + 1, derCerts->numcerts - 1,
  1048.     certUsageSSLCA); 
  1049.     if (rv != PR_SUCCESS) 
  1050.       /* tell user we're having problems */
  1051.       SSM_DEBUG("Cannot import CA chainn");
  1052.   }
  1053.  done:
  1054.   if (certObj) 
  1055.     SSM_FreeResource(certObj);
  1056.   if (nickname)
  1057.     PR_Free(nickname);
  1058.   CERT_DestroyCertificate(cert);
  1059.   PR_Free(arg);
  1060.   return;
  1061. }
  1062. SSMStatus SSM_CAPolicyKeywordHandler(SSMTextGenContext * cx)
  1063. {
  1064.   SSMStatus rv = SSM_FAILURE;
  1065.   char * policyString = NULL, * certresStr = NULL;
  1066.   CERTCertificate * caCert;
  1067.   SSMResource * resource;
  1068.   SSMResourceID certRID;
  1069.   SSMControlConnection * ctrl;
  1070.   
  1071.   PR_ASSERT(cx != NULL);
  1072.   PR_ASSERT(cx->m_request != NULL);
  1073.   PR_ASSERT(cx->m_params != NULL);
  1074.   PR_ASSERT(cx->m_result != NULL);
  1075.   if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
  1076.       cx->m_result == NULL) {
  1077.     PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1078.     goto loser;
  1079.   }
  1080.   /* find the certificate we're talking about */
  1081.   rv = SSM_HTTPParamValue(cx->m_request, "action", &certresStr);
  1082.   if (rv != SSM_SUCCESS) {
  1083.     goto loser;
  1084.   }
  1085.   certRID = atoi(certresStr);
  1086.   resource = SSMTextGen_GetTargetObject(cx);
  1087.   if (!resource) {
  1088.     SSM_DEBUG("SSM_CAPolicyKeywordHandler: can't get target object!n");
  1089.     goto loser;
  1090.   }
  1091.   if (SSM_IsAKindOf(resource, SSM_RESTYPE_CONTROL_CONNECTION)) {
  1092.     ctrl = (SSMControlConnection *)resource;
  1093.     rv = SSMControlConnection_GetResource(ctrl, certRID, &resource);
  1094.     if (rv != SSM_SUCCESS) {
  1095.       SSM_DEBUG("SSM_CAPolicyKeywordHandler: can't find cert resource %dn", 
  1096. certRID);
  1097.       goto loser;
  1098.     }
  1099.   } else
  1100.     PR_ASSERT(SSM_IsAKindOf(resource, SSM_RESTYPE_CERTIFICATE));
  1101.   
  1102.   caCert = ((SSMResourceCert *)resource)->cert;
  1103.   
  1104.   /* For some reason, this function is going to return policy */
  1105.   policyString = CERT_GetCertCommentString(caCert);
  1106.   if (!policyString) {
  1107.     rv = SSM_GetUTF8Text(cx, "no_ca_policy", &policyString);
  1108.     if (rv != SSM_SUCCESS) {
  1109.       SSM_DEBUG("Could not find text %s in policy files.n", "no_ca_policy");
  1110.       goto loser;
  1111.     }
  1112.     SSM_DEBUG("No policy is available for new CA cert: %s!n", policyString);
  1113.   }
  1114.   PR_FREEIF(cx->m_result);
  1115.   cx->m_result = policyString;
  1116.   policyString = NULL;
  1117.   rv = SSM_SUCCESS;
  1118.   goto done;
  1119.  loser:
  1120.   SSMTextGen_UTF8StringClear(&cx->m_result);
  1121.   rv = SSM_FAILURE;
  1122.   SSM_DEBUG("Failed formatting CA policy from signers certn");
  1123.  done: 
  1124.   if (policyString) 
  1125.     PR_Free(policyString);
  1126.   
  1127.   return rv;
  1128. }
  1129. SSMStatus SSM_CACertKeywordHandler(SSMTextGenContext* cx)
  1130. {
  1131.   SSMStatus rv = SSM_FAILURE;
  1132.   char* pattern = NULL;
  1133.   char* key = NULL;
  1134.   char * style = NULL;
  1135.   const PRIntn CERT_FORMAT = (PRIntn)0;
  1136.   const PRIntn CERT_WRAPPER = (PRIntn)1;
  1137.   const PRIntn CERT_WRAPPER_NO_COMMENT = (PRIntn)2;
  1138.   PRIntn wrapper;
  1139.   CERTCertificate * caCert = NULL;
  1140.   char * certresStr = NULL;
  1141.   SSMControlConnection * ctrl;
  1142.   SSMResource * resource;
  1143.   SSMResourceID certRID;
  1144.   
  1145.   PR_ASSERT(cx != NULL);
  1146.   PR_ASSERT(cx->m_request != NULL);
  1147.   PR_ASSERT(cx->m_params != NULL);
  1148.   PR_ASSERT(cx->m_result != NULL);
  1149.   if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
  1150.       cx->m_result == NULL) {
  1151.     PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  1152.     goto loser;
  1153.   }
  1154.   /* find the certificate we're talking about */
  1155.   rv = SSM_HTTPParamValue(cx->m_request, "action", &certresStr);
  1156.   if (rv != SSM_SUCCESS) {
  1157.     goto loser;
  1158.   }
  1159.   certRID = atoi(certresStr);
  1160.   resource = SSMTextGen_GetTargetObject(cx);
  1161.   if (!resource) {
  1162.     SSM_DEBUG("SSM_CAPolicyKeywordHandler: can't get target object!n");
  1163.     goto loser;
  1164.   }
  1165.   if (SSM_IsAKindOf(resource, SSM_RESTYPE_CONTROL_CONNECTION)) {
  1166.     ctrl = (SSMControlConnection *)resource;
  1167.     rv = SSMControlConnection_GetResource(ctrl, certRID, &resource);
  1168.     if (rv != SSM_SUCCESS) {
  1169.       SSM_DEBUG("SSM_CACertKeywordHandler: can't find cert resource %dn", 
  1170. certRID);
  1171.       goto loser;
  1172.     }
  1173.   } else
  1174.     PR_ASSERT(SSM_IsAKindOf(resource, SSM_RESTYPE_CERTIFICATE));
  1175.   caCert = ((SSMResourceCert *)resource)->cert;
  1176.   /* form the MessageFormat object */
  1177.   /* get the correct wrapper */
  1178.   if (CERT_GetCertCommentString(caCert))
  1179.     wrapper = CERT_WRAPPER;
  1180.   else wrapper = CERT_WRAPPER_NO_COMMENT;
  1181.   key = (char *) SSM_At(cx->m_params, wrapper);
  1182.   
  1183.   /* second, grab and expand the keyword objects */
  1184.   rv = SSM_GetAndExpandTextKeyedByString(cx, key, &pattern);
  1185.   if (rv != SSM_SUCCESS) {
  1186.     goto loser;
  1187.   }
  1188.   SSM_DebugUTF8String("ca cert info pattern <%s>", pattern);
  1189.   style = (char *) SSM_At(cx->m_params, CERT_FORMAT);
  1190.   PR_FREEIF(cx->m_result);
  1191.   if (!strcmp(style, "pretty"))
  1192.     rv = SSM_PrettyFormatCert(caCert, pattern, &cx->m_result, PR_FALSE);
  1193.   else if (!strcmp(style, "simple"))
  1194.     rv = SSM_FormatCert(caCert, pattern, &cx->m_result);
  1195.   else {
  1196.     SSM_DEBUG("SSM_CACertKeywordHandler: bad formatting parameter!n");
  1197.     rv =  SSM_ERR_INVALID_FUNC;
  1198.   }
  1199.   goto done;
  1200. loser:
  1201.   if (rv == SSM_SUCCESS)
  1202.     rv = SSM_FAILURE;
  1203.  done:
  1204.   if (pattern != NULL) {
  1205.     PR_Free(pattern);
  1206.   }
  1207.   return rv;
  1208. }