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

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #ifdef XP_MAC
  35. #include "platform.h"
  36. #endif
  37. #include "advisor.h"
  38. #include "nlsutil.h"
  39. #include "minihttp.h"
  40. #include "p12res.h"
  41. #include "textgen.h"
  42. #include "sslskst.h"
  43. #include "certlist.h"
  44. #include "ocsp.h"
  45. #include "secoid.h"
  46. #include "prefs.h"
  47. #include "messages.h"
  48. #include "secerr.h"
  49. #include "sslerr.h"
  50. #include "base64.h"
  51. /*
  52.  * This is the structure used to gather all of the CA's that can be used
  53.  * for OCSP responders.
  54.  */
  55. typedef struct SSMDefaultOCSPRespondersListStr{
  56.     SSMSortedList *respondersWithAIA;
  57.     SSMSortedList *respondersWithoutAIA;
  58.     SSMTextGenContext *cx;
  59.     char *wrapper, *defaultSigner;
  60. } SSMDefaultOCSPRespondersList;
  61. SSMStatus SSM_SetSelectedItemInfo(SSMSecurityAdvisorContext* cx);
  62. #define SSMRESOURCE(object) (&object->super)
  63. #define SSM_NO_INFO "sa_no_info"
  64. #define SSM_NAVIGATOR_NO_SEC            "sa_navigator_no_sec"
  65. #define SSM_NAVIGATOR_SSL               "sa_navigator_ssl"
  66. #define SSM_NAVIGATOR_BAD_SSL "sa_navigator_bad_ssl"
  67. #define SSM_MESSAGE "sa_message"
  68. #define SSM_MESSAGE_NOT_SIGNED "sa_message_not_signed"
  69. #define SSM_MESSAGE_NOT_ENCRYPTED "sa_message_not_encrypted"
  70. #define SSM_MESSAGE_SIGNED "sa_message_signed"
  71. #define SSM_MESSAGE_ENCRYPTED "sa_message_encrypted"
  72. #define SSM_MESSAGE_BAD_SIGNED "sa_message_bad_signed"
  73. #define SSM_MESSAGE_BAD_ENCRYPTED "sa_message_bad_encrypted"
  74. /* A list of User agent strings that we know can do S/MIME
  75.  * and want the Java tab as well.
  76.  */
  77. #define COMMON_TO_SMIME_AND_JAVA "Mozilla/4.7"
  78. const char *kSMimeApps[]  = {COMMON_TO_SMIME_AND_JAVA, NULL};
  79. const char *kJavaJSApps[] = {COMMON_TO_SMIME_AND_JAVA, NULL};
  80. char * SSM_ConvertStringToHTMLString(char * string);
  81. char * SSMUI_GetPKCS12Error(PRIntn error, PRBool isBackup);
  82. PRBool
  83. SSM_IsCRLPresent(SSMControlConnection *ctrl)
  84. {
  85.     SECStatus rv = SECFailure;
  86.     CERTCrlHeadNode *head = NULL;
  87.     PRBool retVal = PR_FALSE;
  88.     
  89.     rv = SEC_LookupCrls(ctrl->m_certdb, &head, -1);
  90.     if (rv != SECSuccess) {
  91.         goto done;
  92.     }
  93.     if (head == NULL) {
  94.         goto done;
  95.     }
  96.     retVal = (head->first == NULL) ? PR_FALSE : PR_TRUE;
  97.     PORT_FreeArena(head->arena, PR_FALSE);
  98.  done:
  99.     return retVal;
  100. }
  101. SSMStatus 
  102. SSMSecurityAdvisorContext_Create(SSMControlConnection *ctrl, 
  103.                                  InfoSecAdvisor *info, 
  104.                                  SSMResource **res)
  105. {
  106.     SSMStatus rv = PR_SUCCESS;
  107.     SSMSecurityAdvisorContext *ct;
  108. int i;
  109.     *res = NULL; /* in case we fail */
  110.     
  111.     ct = (SSMSecurityAdvisorContext *) 
  112.         PR_CALLOC(sizeof(SSMSecurityAdvisorContext));
  113.     if (!ct) 
  114.         goto loser;
  115.     rv = SSMResource_Init(ctrl, &ct->super, SSM_RESTYPE_SECADVISOR_CONTEXT);
  116.     if (rv != PR_SUCCESS) 
  117.         goto loser;
  118.     
  119.     /* this hash will contail list of formatted certs nickname to display */
  120.     ct->m_certhash = NULL;
  121.     ct->m_certsIncluded = 0;
  122.     
  123.     /* register us with ControlConection */
  124.     if (!ctrl->m_secAdvisorList) {
  125.         ctrl->m_secAdvisorList = (SECItem *) PR_Malloc(sizeof(SECItem));
  126.         ctrl->m_secAdvisorList->len = 0;
  127.         ctrl->m_secAdvisorList->data = NULL;
  128.     } 
  129.     ctrl->m_secAdvisorList->len++;
  130.     ctrl->m_secAdvisorList->data = (unsigned char *) PR_REALLOC(ctrl->m_secAdvisorList->data, 
  131.                                                ctrl->m_secAdvisorList->len);
  132.     ctrl->m_secAdvisorList->data[ ctrl->m_secAdvisorList->len - 1 ] = 
  133.         ((SSMResource *)ct)->m_id;
  134.     if (info) {
  135.         ct->infoContext = info->infoContext;
  136.         ct->resID = info->resID;
  137.         ct->hostname = info->hostname ? PL_strdup(info->hostname) : NULL;
  138. ct->senderAddr = info->senderAddr ? PL_strdup(info->senderAddr) : NULL;
  139. ct->encryptedP7CInfo = info->encryptedP7CInfo;
  140. ct->signedP7CInfo = info->signedP7CInfo;
  141. ct->decodeError = info->decodeError;
  142. ct->verifyError = info->verifyError;
  143. ct->encryptthis = info->encryptthis;
  144. ct->signthis = info->signthis;
  145. ct->numRecipients = info->numRecipients;
  146.     if (info->numRecipients > 0) {
  147. ct->recipients = (char **) PR_CALLOC(sizeof(char*)*(info->numRecipients));
  148. if (!ct->recipients) {
  149. goto loser;
  150. }
  151.         for (i=0;i<info->numRecipients;i++) {
  152.         ct->recipients[i] = PL_strdup(info->recipients[i]);
  153. }
  154. }
  155.         SSM_SetSelectedItemInfo(ct);
  156.     }
  157.     /* Create a URL for the security advisor window. */
  158.     rv = (SSMStatus) SSM_GenerateURL(ctrl, "get", "secadvisor", 
  159.                          &ct->super, NULL, 
  160.                          &ct->m_width, &ct->m_height, 
  161.                          &ct->m_url);
  162.     if (rv != SSM_SUCCESS)
  163.         goto loser;
  164.     SSMSecurityAdvisorContext_Invariant(ct);
  165.     *res = &ct->super;
  166.     return PR_SUCCESS;
  167.  loser:
  168.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  169.     if (ct) 
  170.     {
  171.         ct->super.m_refCount = 1; /* force destroy */
  172.         SSM_FreeResource(&ct->super);
  173.     }
  174.         
  175.     return rv;
  176. }
  177. char * SSMUI_GetPKCS12Error(PRIntn error, PRBool isBackup)
  178. {
  179.     char * responseKey;
  180.     
  181.     switch (error) { 
  182.     case SSM_ERR_NO_PASSWORD:
  183.         responseKey = "pkcs12_bad_portable_password_restore";
  184.         break;
  185.     case SSM_ERR_BAD_DB_PASSWORD:
  186.         responseKey = "pkcs12_bad_db_password";
  187.         break;
  188.     case SSM_ERR_BAD_FILENAME:
  189.         responseKey = "pkcs12_bad_filepath";
  190.         break;
  191.     case SSM_ERR_NEED_USER_INIT_DB:
  192.         responseKey = "pkcs12_need_db_init";
  193.         break;
  194.     case SSM_ERR_CANNOT_DECODE:
  195.         responseKey="pkcs12_cannot_decode";
  196.         break;
  197.     case SSM_PKCS12_CERT_ALREADY_EXISTS:
  198.         responseKey="pkcs12_cert_already_exists";
  199.         break;
  200.     case SSM_ERR_BAD_REQUEST:
  201.     default:
  202.         responseKey = (isBackup) ? "pkcs12_backup_failure" : 
  203.                                    "pkcs12_restore_failure";
  204.     }
  205.     return responseKey;
  206. }
  207. SSMStatus 
  208. SSMSecurityAdvisorContext_Destroy(SSMResource *res, PRBool doFree)
  209. {
  210.     SSMSecurityAdvisorContext *ct = (SSMSecurityAdvisorContext *) res;
  211.     PRIntn i = 0, others = 0;
  212.     if (ct)
  213.     {
  214.         PR_ASSERT(SSM_IsAKindOf(res, SSM_RESTYPE_SECADVISOR_CONTEXT));
  215.         SSMResource_Destroy(res, PR_FALSE);
  216.         
  217.         /* Dereference the security info object */
  218.         if (ct->m_infoSource)
  219.         {
  220.             SSM_FreeResource(ct->m_infoSource);
  221.             ct->m_infoSource = NULL;
  222.         }
  223.         /* Free the URL */
  224.         PR_FREEIF(ct->m_url);
  225.         if (ct->m_certhash)
  226.             SSMSortedList_Destroy(ct->m_certhash);
  227.         
  228.         /* deregister with control connection */
  229.         while (i < res->m_connection->m_secAdvisorList->len) {
  230.             if (res->m_connection->m_secAdvisorList->data[i] == res->m_id)
  231.                 res->m_connection->m_secAdvisorList->data[i] = 0;
  232.             if (res->m_connection->m_secAdvisorList->data[i])
  233.                 others ++;
  234.             i++;
  235.         }
  236.         if (!others) {
  237.             SECITEM_ZfreeItem(res->m_connection->m_secAdvisorList, PR_TRUE);
  238.             res->m_connection->m_secAdvisorList = NULL;
  239.         }
  240.         if (ct->socketStatus) {
  241.             SSM_FreeResource(&ct->socketStatus->super);
  242.         }
  243.         PR_FREEIF(ct->hostname);
  244.         PR_FREEIF(ct->senderAddr);
  245.         if (ct->recipients) {
  246.             for (i=0; i<ct->numRecipients; i++) {
  247.                 PR_FREEIF(ct->recipients[i]);
  248.             }
  249.             PR_FREEIF(ct->recipients);
  250.         }
  251.         /* Free if asked */
  252.         if (doFree)
  253.             PR_Free(ct);
  254.     }
  255.     return PR_SUCCESS; /* no way to fail, really */
  256. }
  257. void 
  258. SSMSecurityAdvisorContext_Invariant(SSMSecurityAdvisorContext *ct)
  259. {
  260.     /* Check superclass. */
  261.     SSMResource_Invariant(&ct->super);
  262.     /* Make sure we always have a URL. */
  263.     PR_ASSERT(ct->m_url != NULL);
  264. }
  265. SSMStatus 
  266. SSMSecurityAdvisorContext_GetAttrIDs(SSMResource *res,
  267.                                      SSMAttributeID **ids,
  268.                                      PRIntn *count)
  269. {
  270.     SSMStatus rv;
  271.     rv = SSMResource_GetAttrIDs(res, ids, count);
  272.     if (rv != PR_SUCCESS)
  273.         goto loser;
  274.     *ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 4) * sizeof(SSMAttributeID));
  275.     if (! *ids) goto loser;
  276.     (*ids)[*count++] = SSM_FID_SECADVISOR_URL;
  277.     (*ids)[*count++] = SSM_FID_SECADVISOR_WIDTH;
  278.     (*ids)[*count++] = SSM_FID_SECADVISOR_HEIGHT;
  279.     (*ids)[*count++] = SSM_FID_CLIENT_CONTEXT;
  280.     goto done;
  281.  loser:
  282.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  283.  done:
  284.     return rv;
  285. }
  286. SSMStatus 
  287. SSMSecurityAdvisorContext_GetAttr(SSMResource *res,
  288.                                   SSMAttributeID attrID,
  289.                                   SSMResourceAttrType attrType,
  290.                                   SSMAttributeValue *value)
  291. {
  292.     SSMStatus rv = PR_SUCCESS;
  293.     SSMSecurityAdvisorContext *ct = (SSMSecurityAdvisorContext *) res;
  294.     SSMSecurityAdvisorContext_Invariant(ct);
  295.     switch(attrID)
  296.     {
  297.     case SSM_FID_SECADVISOR_URL:
  298.         /* Duplicate and return the string. */
  299.         value->type = SSM_STRING_ATTRIBUTE;
  300.         value->u.string.len = PL_strlen(ct->m_url);
  301.         value->u.string.data = (unsigned char *) PL_strdup(ct->m_url);
  302.         break;
  303.     case SSM_FID_SECADVISOR_WIDTH:
  304.     case SSM_FID_SECADVISOR_HEIGHT:
  305.         value->type = SSM_NUMERIC_ATTRIBUTE;
  306.         value->u.numeric = (attrID == SSM_FID_SECADVISOR_WIDTH) ?
  307.             ct->m_width : ct->m_height;
  308.         break;
  309.     case SSM_FID_CLIENT_CONTEXT:
  310.       SSM_DEBUG("Getting security advisor client context");
  311.       value->type = SSM_STRING_ATTRIBUTE;
  312.       if (!(value->u.string.data = (unsigned char *) PR_Malloc(res->m_clientContext.len))) {
  313.           goto loser;
  314.       }
  315.       memcpy(value->u.string.data, res->m_clientContext.data, res->m_clientContext.len);
  316.       value->u.string.len = res->m_clientContext.len;
  317.       break;
  318.     default:
  319.         rv = SSMResource_GetAttr(res,attrID,attrType,value);
  320.         if (rv != PR_SUCCESS)
  321.             goto loser;
  322.     }
  323.     goto done;
  324.  loser:
  325.     value->type = SSM_NO_ATTRIBUTE;
  326.     if (rv == PR_SUCCESS)
  327.         rv = PR_FAILURE;
  328.  done:
  329.     return rv;
  330. }
  331. SSMStatus SSMSecurityAdvisorContext_SetAttr(SSMResource *res,
  332.                                   SSMAttributeID attrID,
  333.                                   SSMAttributeValue *value)
  334. {
  335.     switch(attrID) {
  336.     case SSM_FID_CLIENT_CONTEXT:
  337.       SSM_DEBUG("Setting security advisor client contextn");
  338.       if (value->type != SSM_STRING_ATTRIBUTE) {
  339.           goto loser;
  340.       }
  341.       if (!(res->m_clientContext.data = (unsigned char *) PR_Malloc(value->u.string.len))) {
  342.           goto loser;
  343.       }
  344.       memcpy(res->m_clientContext.data, value->u.string.data, value->u.string.len);
  345.       res->m_clientContext.len = value->u.string.len;
  346.       break;
  347.     default:
  348.       SSM_DEBUG("Got unknown security advisor Set Attribute Request %dn", attrID);
  349.       goto loser;
  350.       break;
  351.     }
  352.     return PR_SUCCESS;
  353. loser:
  354.     return PR_FAILURE;
  355. }
  356. /* Preference keys used in Security Advisor JavaScript.
  357.  * They are used to cache temporary changes the user has made.
  358.  */
  359. #define SSL2_SPK "enable_ssl2"
  360. #define SSL3_SPK "enable_ssl3"
  361. #define CLIENT_AUTH_SPK "client_auth_auto_select"
  362. #define EMAIL_CERT_SPK "default_email_cert"
  363. #define WARN_ENTER_SECURE_SPK "warn_entering_secure"
  364. #define WARN_LEAVE_SECURE_SPK "warn_leaving_secure"
  365. #define WARN_VIEW_MIXED_SPK "warn_viewing_mixed"
  366. #define WARN_SUBMIT_INSECURE_SPK "warn_submit_insecure"
  367. #define ENCRYPT_MAIL_SPK "mail_encrypt_outgoing_mail"
  368. #define SIGN_MAIL_SPK "mail_crypto_sign_outgoing_mail"
  369. #define SIGN_NEWS_SPK "mail_crypto_sign_outgoing_news"
  370. /* maximum number of pref items that will be sent back to the client */
  371. #define ITEMS_MAX 11
  372. static SSMStatus SSMSecurityAdvisor_get_bool_value(HTTPRequest* req,
  373.                                                    char* key, PRBool* value)
  374. {
  375.     SSMStatus rv;
  376.     char* tmpStr = NULL;
  377.     rv = SSM_HTTPParamValue(req, key, &tmpStr);
  378.     if (rv != SSM_SUCCESS) {
  379.         return rv;
  380.     }
  381.     if (PL_strcmp(tmpStr, "true") == 0) {
  382.         *value = PR_TRUE;
  383.     }
  384.     else if (PL_strcmp(tmpStr, "false") == 0) {
  385.         *value = PR_FALSE;
  386.     }
  387.     else {
  388.         SSM_DEBUG("I don't understand the value.n");
  389.         return SSM_FAILURE;
  390.     }
  391.     return rv;
  392. }
  393. static SSMStatus ssm_set_pack_bool_pref(PrefSet* prefs, char* key, 
  394.                                         PRBool value, SetPrefElement* list,
  395.                                         PRIntn* n)
  396. {
  397.     SSMStatus rv;
  398.     /* set the change to memory */
  399.     rv = PREF_SetBoolPref(prefs, key, value);
  400.     if (rv != PR_SUCCESS) {
  401.         return rv;
  402.     }
  403.     /* pack the change */
  404.     list[*n].key = PL_strdup(key);
  405.     list[*n].type = BOOL_PREF;
  406.     if (value == PR_TRUE) {
  407.         list[*n].value = PL_strdup("true");
  408.     }
  409.     else {
  410.         list[*n].value = PL_strdup("false");
  411.     }
  412.     (*n)++;
  413.     return rv;
  414. }
  415. static SSMStatus
  416. SSMSecurityAdvisorContext_SavePrefs(SSMSecurityAdvisorContext* cx,
  417.                                     HTTPRequest* req)
  418. {
  419.     SSMStatus rv;
  420.     SSMControlConnection* ctrl = NULL;
  421.     PrefSet* prefs = NULL;
  422.     PRBool ssl2on;
  423.     PRBool ssl3on;
  424.     PRBool autoSelect;
  425.     PRBool warnEnterSecure;
  426.     PRBool warnLeaveSecure;
  427.     PRBool warnViewMixed;
  428.     PRBool warnSubmitInsecure;
  429.     PRBool encryptMail;
  430.     PRBool signMail;
  431.     PRBool signNews;
  432.     char* autoStr = NULL;
  433.     char* defaultCert = NULL;
  434.     SetPrefElement list[ITEMS_MAX];
  435.     SetPrefListMessage request;
  436.     PRIntn n = 0;    /* counter */
  437.     int i;
  438.     CMTItem message;
  439.     PR_ASSERT(cx != NULL && cx->super.m_connection != NULL &&
  440.               cx->super.m_connection->m_prefs != NULL);
  441.     ctrl = cx->super.m_connection;
  442.     prefs = ctrl->m_prefs;
  443.     /* retrieve pref values */
  444.     rv = SSMSecurityAdvisor_get_bool_value(req, SSL2_SPK, &ssl2on);
  445.     if (rv != SSM_SUCCESS) {
  446.         goto loser;
  447.     }
  448.     rv = SSMSecurityAdvisor_get_bool_value(req, SSL3_SPK, &ssl3on);
  449.     if (rv != SSM_SUCCESS) {
  450.         goto loser;
  451.     }
  452.     rv = SSMSecurityAdvisor_get_bool_value(req, CLIENT_AUTH_SPK, &autoSelect);
  453.     if (rv != SSM_SUCCESS) {
  454.         goto loser;
  455.     }
  456.     if (autoSelect == PR_TRUE) {
  457.         autoStr = "Select Automatically";
  458.     }
  459.     else {
  460.         autoStr = "Ask Every Time";
  461.     }
  462.     rv = SSM_HTTPParamValue(req, EMAIL_CERT_SPK, &defaultCert);
  463.     if (defaultCert[0] == '') {
  464.         defaultCert = NULL;
  465.         rv = SSM_SUCCESS;
  466.     }
  467.     if (rv != SSM_SUCCESS) {
  468.         goto loser;
  469.     }
  470.     rv = SSMSecurityAdvisor_get_bool_value(req, WARN_ENTER_SECURE_SPK,
  471.                                            &warnEnterSecure);
  472.     if (rv != SSM_SUCCESS) {
  473.         goto loser;
  474.     }
  475.     rv = SSMSecurityAdvisor_get_bool_value(req, WARN_LEAVE_SECURE_SPK,
  476.                                            &warnLeaveSecure);
  477.     if (rv != SSM_SUCCESS) {
  478.         goto loser;
  479.     }
  480.     rv = SSMSecurityAdvisor_get_bool_value(req, WARN_VIEW_MIXED_SPK,
  481.                                            &warnViewMixed);
  482.     if (rv != SSM_SUCCESS) {
  483.         goto loser;
  484.     }
  485.     rv = SSMSecurityAdvisor_get_bool_value(req, WARN_SUBMIT_INSECURE_SPK,
  486.                                            &warnSubmitInsecure);
  487.     if (rv != SSM_SUCCESS) {
  488.         goto loser;
  489.     }
  490.     rv = SSMSecurityAdvisor_get_bool_value(req, ENCRYPT_MAIL_SPK, 
  491.                                            &encryptMail);
  492.     if (rv != SSM_SUCCESS) {
  493.         goto loser;
  494.     }
  495.     rv = SSMSecurityAdvisor_get_bool_value(req, SIGN_MAIL_SPK, &signMail);
  496.     if (rv != SSM_SUCCESS) {
  497.         goto loser;
  498.     }
  499.     rv = SSMSecurityAdvisor_get_bool_value(req, SIGN_NEWS_SPK, &signNews);
  500.     if (rv != SSM_SUCCESS) {
  501.         goto loser;
  502.     }
  503.     /* commit the changes */
  504.     if (PREF_BoolPrefChanged(prefs, "security.enable_ssl2", ssl2on)) {
  505.         /* value has changed */
  506.         rv = ssm_set_pack_bool_pref(prefs, "security.enable_ssl2", ssl2on,
  507.                                     (SetPrefElement*)list, &n);
  508.         SSL_EnableDefault(SSL_ENABLE_SSL2, ssl2on);
  509.     }
  510.     if (PREF_BoolPrefChanged(prefs, "security.enable_ssl3", ssl3on)) {
  511.         rv = ssm_set_pack_bool_pref(prefs, "security.enable_ssl3", ssl3on,
  512.                                     (SetPrefElement*)list, &n);
  513.         SSL_EnableDefault(SSL_ENABLE_SSL3, ssl3on);
  514.     }
  515.     if (PREF_StringPrefChanged(prefs, "security.default_personal_cert", 
  516.                                autoStr)) {
  517.         rv = PREF_SetStringPref(prefs, "security.default_personal_cert", 
  518.                                 autoStr);
  519.         
  520.         list[n].key = PL_strdup("security.default_personal_cert");
  521.         list[n].type = STRING_PREF;
  522.         list[n].value = PL_strdup(autoStr);
  523.         n++;
  524.     }
  525.     
  526.     if (PREF_StringPrefChanged(prefs, "security.default_mail_cert",
  527.                                defaultCert)) {
  528.         rv = PREF_SetStringPref(prefs, "security.default_mail_cert", 
  529.                                 defaultCert);
  530.         list[n].key = PL_strdup("security.default_mail_cert");
  531.         list[n].type = STRING_PREF;
  532.         list[n].value = PL_strdup(defaultCert);
  533.         n++;
  534.     }
  535.     if (PREF_BoolPrefChanged(prefs, "security.warn_entering_secure", 
  536.                              warnEnterSecure)) {
  537.         rv = ssm_set_pack_bool_pref(prefs, "security.warn_entering_secure",
  538.                                     warnEnterSecure, (SetPrefElement*)list,
  539.                                     &n);
  540.     }
  541.     if (PREF_BoolPrefChanged(prefs, "security.warn_leaving_secure", 
  542.                              warnLeaveSecure)) {
  543.         rv = ssm_set_pack_bool_pref(prefs, "security.warn_leaving_secure",
  544.                                     warnLeaveSecure, (SetPrefElement*)list,
  545.                                     &n);
  546.     }
  547.     if (PREF_BoolPrefChanged(prefs, "security.warn_viewing_mixed", 
  548.                              warnViewMixed)) {
  549.         rv = ssm_set_pack_bool_pref(prefs, "security.warn_viewing_mixed",
  550.                                     warnViewMixed, (SetPrefElement*)list, &n);
  551.     }
  552.     if (PREF_BoolPrefChanged(prefs, "security.warn_submit_insecure", 
  553.                              warnSubmitInsecure)) {
  554.         rv = ssm_set_pack_bool_pref(prefs, "security.warn_submit_insecure",
  555.                                     warnSubmitInsecure, (SetPrefElement*)list,
  556.                                     &n);
  557.     }
  558.     if (PREF_BoolPrefChanged(prefs, "mail.encrypt_outgoing_mail", 
  559.                              encryptMail)) {
  560.         rv = ssm_set_pack_bool_pref(prefs, "mail.encrypt_outgoing_mail",
  561.                                     encryptMail, (SetPrefElement*)list, &n);
  562.     }
  563.     if (PREF_BoolPrefChanged(prefs, "mail.crypto_sign_outgoing_mail", 
  564.                              signMail)) {
  565.         rv = ssm_set_pack_bool_pref(prefs, "mail.crypto_sign_outgoing_mail",
  566.                                     signMail, (SetPrefElement*)list, &n);
  567.     }
  568.     if (PREF_BoolPrefChanged(prefs, "mail.crypto_sign_outgoing_news", 
  569.                              signNews)) {
  570.         rv = ssm_set_pack_bool_pref(prefs, "mail.crypto_sign_outgoing_news",
  571.                                     signNews, (SetPrefElement*)list, &n);
  572.     }
  573.     rv = SSM_HTTPDefaultCommandHandler(req);
  574.     if (rv != PR_SUCCESS) {
  575.         goto loser;
  576.     }
  577.     /* finally, send the changes to the plugin so that it can save the
  578.      * changes
  579.      */
  580.     if (n > 0) {
  581.         /* we need to send this event only if prefs changed */
  582.         request.length = n;
  583.         request.list = list;
  584.         message.type = SSM_EVENT_MESSAGE | SSM_SAVE_PREF_EVENT;
  585.         if (CMT_EncodeMessage(SetPrefListMessageTemplate, &message, 
  586.                               &request) != CMTSuccess) {
  587.             goto loser;
  588.         }
  589.         /* send the message through the control out queue */
  590.         SSM_SendQMessage(ctrl->m_controlOutQ, SSM_PRIORITY_NORMAL, 
  591.                          message.type, message.len, (char*)message.data,
  592.                          PR_TRUE);
  593.     }
  594. loser:
  595.     /* clean out list */
  596.     for (i = 0; i < n; i++) {
  597.         if (list[i].key != NULL) {
  598.             PR_Free(list[i].key);
  599.         }
  600.         if (list[i].value != NULL) {
  601.             PR_Free(list[i].value);
  602.         }
  603.     }
  604.     return rv;
  605. }
  606. SSMStatus
  607. SSMSecurityAdvisorContext_DoPKCS12Response(SSMSecurityAdvisorContext *advisor,
  608.                                            HTTPRequest *req,
  609.                                            const char  *responseKey)
  610. {
  611.     SSMTextGenContext *cx = NULL;
  612.     SSMStatus rv = SSM_FAILURE;
  613.     char name[256];
  614.     char *page = "pkcs12_action_followup";
  615.     char *type = NULL, *hdrs = NULL, *content = NULL;
  616.     char *alertMessage = NULL, *out = NULL;
  617.     rv = SSMTextGen_NewTopLevelContext(req, &cx);
  618.     if (rv != SSM_SUCCESS) {
  619.         SSM_HTTPReportSpecificError(req, "DoPKCS12Response: Error%d "
  620.                                     "attempting to create textgen context.",
  621.                                     rv);
  622.         goto loser;
  623.     }
  624.     PR_snprintf(name, 256, "%s_type", page);
  625.     rv = SSM_GetUTF8Text(cx, name, &type);
  626.     if (rv != SSM_SUCCESS) {
  627.         goto loser;
  628.     }
  629.     PR_snprintf(name, 256, "%s_content", page);
  630.     rv = SSM_GetAndExpandText(cx, name, &content);
  631.     if (rv != SSM_SUCCESS) {
  632.         goto loser;
  633.     }
  634.     rv = SSM_GetUTF8Text(cx, responseKey, &alertMessage);
  635.     if (rv != SSM_SUCCESS) {
  636.         goto loser;
  637.     }
  638.     out = PR_smprintf(content, alertMessage, advisor->super.m_id);
  639.     rv = SSM_HTTPSendOKHeader(req, hdrs, type);
  640.     if (rv != SSM_SUCCESS) {
  641.         goto loser;
  642.     }
  643.     rv = SSM_HTTPSendUTF8String(req, out);
  644.     if (rv != SSM_SUCCESS) {
  645.         goto loser;
  646.     }
  647.     req->sentResponse = PR_TRUE;
  648.     goto done;
  649.  loser:
  650.     if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  651.  done:
  652.     if (cx != NULL) {
  653.         SSMTextGen_DestroyContext(cx);
  654.     }
  655.     PR_FREEIF(type);
  656.     PR_FREEIF(hdrs);
  657.     PR_FREEIF(content);
  658.     PR_FREEIF(out);
  659.     PR_FREEIF(alertMessage);
  660.     return rv;
  661. }
  662. static SSMStatus
  663. SSMSecurityAdvisorContext_DoNewDefMailReponse(SSMPKCS12Context *p12Cxt,
  664.                                               HTTPRequest      *req)
  665. {
  666.     SSMTextGenContext *cx = NULL;
  667.     char *fmt=NULL, *content=NULL, *defEmailCert=NULL, *expContent=NULL;
  668.     SSMStatus rv;
  669.     rv = SSMTextGen_NewTopLevelContext(req, &cx);
  670.     if (rv != SSM_SUCCESS) {
  671.         SSM_HTTPReportSpecificError(req, "DoNewDefMailReponse: Failed to "
  672.                                          "create new TextGenContext.");
  673.         goto loser;
  674.     }
  675.     rv = SSM_FindUTF8StringInBundles(cx, "pkcs12_restore_success_new_mail", 
  676.                                      &fmt);
  677.     if (rv != SSM_SUCCESS || fmt == NULL) {
  678.         goto loser;
  679.     }
  680.     
  681.     rv = PREF_GetStringPref(req->ctrlconn->m_prefs, 
  682.                             "security.default_mail_cert", &defEmailCert);
  683.     if (rv != SSM_SUCCESS || defEmailCert == NULL) {
  684.         goto loser;
  685.     }
  686.     content = PR_smprintf(fmt, defEmailCert);
  687.     if (content == NULL) {
  688.         goto loser;
  689.     }
  690.     rv = SSMTextGen_SubstituteString(cx, content, &expContent);
  691.     if (rv != SSM_SUCCESS || expContent == NULL) {
  692.         goto loser;
  693.     }
  694.     rv = SSM_HTTPSendOKHeader(req, "", "text/html");
  695.     if (rv != SSM_SUCCESS) {
  696.         goto loser;
  697.     }
  698.     rv = SSM_HTTPSendUTF8String(req, expContent);
  699.     if (rv != SSM_SUCCESS) {
  700.         goto loser;
  701.     }
  702.     PR_Free(expContent);
  703.     PR_Free(content);
  704.     PR_Free(fmt);
  705.     req->sentResponse = PR_TRUE;
  706.     return SSM_SUCCESS;
  707.  loser:
  708.     if (cx != NULL) {
  709.         SSMTextGen_DestroyContext(cx);
  710.     }
  711.     PR_FREEIF(fmt);
  712.     PR_FREEIF(content);
  713.     PR_FREEIF(expContent);
  714.     return SSM_FAILURE;
  715. }
  716. SSMStatus SSMSecurityAdvisorContext_DoPKCS12Restore(
  717.                                               SSMSecurityAdvisorContext *res,
  718.                                               HTTPRequest               *req)
  719. {
  720.     SSMStatus           rv;
  721.     SSMPKCS12CreateArg  p12Create;
  722.     SSMPKCS12Context   *p12Cxt=NULL;
  723.     SSMResourceID       rid;
  724.     const char         *responseKey;
  725.     p12Create.isExportContext = PR_FALSE;
  726.     rv = (SSMStatus) SSM_CreateResource(SSM_RESTYPE_PKCS12_CONTEXT, 
  727.                                         (void*)&p12Create,
  728.                                         SSMRESOURCE(res)->m_connection,
  729.                                         &rid, (SSMResource **)(&p12Cxt));
  730.     if (rv != PR_SUCCESS) {
  731.         goto done;
  732.     }
  733.     /* pass along Advisor's client context for window management */
  734.       /* pass along Advisor's client context for window management */
  735.     SSM_CopyCMTItem(&((SSMResource *)p12Cxt)->m_clientContext,
  736.                     &((SSMResource *)res)->m_clientContext);
  737.     
  738.     rv = SSMPKCS12Context_RestoreCertFromPKCS12File(p12Cxt);
  739.     if (rv == SSM_ERR_NEW_DEF_MAIL_CERT) {
  740.         SSM_ChangeCertSecAdvisorList(req, NULL, certHashAdd);
  741.         rv = SSMSecurityAdvisorContext_DoNewDefMailReponse(p12Cxt,req);
  742.     } else {
  743.         if (p12Cxt->super.m_buttonType == SSM_BUTTON_CANCEL){
  744.             rv = SSM_SUCCESS;
  745.             SSM_HTTPReportError(req, HTTP_NO_CONTENT);
  746.         } else if (rv != SSM_SUCCESS) {
  747.             responseKey = SSMUI_GetPKCS12Error(rv, PR_FALSE);
  748.         } else {
  749.             responseKey = "pkcs12_restore_success";
  750.             SSM_ChangeCertSecAdvisorList(req, NULL, certHashAdd);
  751.         }
  752.         rv = SSMSecurityAdvisorContext_DoPKCS12Response(res, req, responseKey);
  753.     }
  754.  done:
  755.     if (p12Cxt != NULL) {
  756.         SSM_FreeResource(SSMRESOURCE(p12Cxt));
  757.     }
  758.     return rv;
  759. }
  760. static CERTCertificate*
  761. SSMSecurityAdvisorContext_FindCertByNickname(SSMSecurityAdvisorContext *cx, 
  762.                                              HTTPRequest *req,
  763.                                              char *certNickname)
  764. {
  765.     CERTCertList      *certList     = NULL;
  766.     CERTCertificate   *cert         = NULL;
  767.     CERTCertListNode  *certListNode = NULL;
  768.     PRInt32            numcerts     = 0;
  769.     SSMTextGenContext *textGenCx    = NULL;
  770.     SSMStatus          rv;
  771.     char              *htmlTemplate = NULL;
  772.     certList = CERT_NewCertList();
  773.     certList = CERT_CreateNicknameCertList(certList, 
  774.                                            cx->super.m_connection->m_certdb,
  775.                                            certNickname, PR_Now(), PR_FALSE);
  776.     if (certList == NULL) {
  777.         certList = PK11_FindCertsFromNickname(certNickname, &cx->super);
  778.         if (certList == NULL) {
  779.             SSM_DEBUG("Could not find a certificate with nick '%s' "
  780.                       "in cert databasen", certNickname);
  781.             goto loser;
  782.         }
  783.     }
  784.     certListNode = CERT_LIST_HEAD(certList);
  785.     while (!CERT_LIST_END(certListNode, certList)) {
  786.         numcerts++;
  787.         certListNode = CERT_LIST_NEXT(certListNode);
  788.     }
  789.     if (numcerts > 1) {
  790.         char * formName = NULL, *params = NULL;
  791.         rv = SSM_HTTPParamValue(req, "formName", &formName);
  792.         if (rv != SSM_SUCCESS || !formName)
  793.             SSM_DEBUG("AdvisorContext_FindCertByNickname:Can't get original formn");
  794.         params = PR_smprintf("origin=%s",formName);
  795.         cx->m_nickname = PL_strdup(certNickname);
  796.         rv = SSMControlConnection_SendUIEvent(cx->super.m_connection,
  797.                                               "get", 
  798.                                               "choose_cert", 
  799.                                               &cx->super,
  800.                                               params,
  801.                                               &cx->super.m_clientContext,
  802.                                               PR_TRUE);
  803.         /* Now wait until we are notified by the handler that the user 
  804.          * has selected a cert.
  805.          */
  806.         SSM_LockUIEvent(&cx->super);
  807.         SSM_WaitUIEvent(&cx->super, PR_INTERVAL_NO_TIMEOUT);
  808.         cert = (CERTCertificate*)cx->super.m_connection->super.super.m_uiData;
  809.         if (cx->super.m_buttonType != SSM_BUTTON_CANCEL) {
  810.             /* 
  811.              * If we don't sleep for a bit here, we cause Communicator to crash
  812.              * because it tries to re-use a Window that gets killed.  Guess
  813.              * we're just too fast for Communicator.
  814.              */
  815.             PR_Sleep(PR_TicksPerSecond()*1);
  816.         }
  817.         PR_FREEIF(cx->m_nickname);
  818.         cx->m_nickname = NULL;
  819.         PR_FREEIF(params);
  820.     } else {
  821.         cert = CERT_FindCertByNickname(cx->super.m_connection->m_certdb,
  822.                                        certNickname);
  823.         cx->super.m_buttonType = SSM_BUTTON_OK;
  824.     }
  825.     CERT_DestroyCertList(certList);
  826.     return cert;
  827.  loser:
  828.     PR_FREEIF(htmlTemplate);
  829.     if (certList != NULL) {
  830.         CERT_DestroyCertList(certList);
  831.     }
  832.     if (cert != NULL) {
  833.         CERT_DestroyCertificate(cert);
  834.     }
  835.     if (textGenCx != NULL) {
  836.         SSMTextGen_DestroyContext(textGenCx);
  837.     }
  838.     return NULL;
  839. }
  840. typedef struct SSMFindMineArgStr {
  841.     CERTCertList *certList;
  842.     SSMControlConnection *ctrl;
  843. } SSMFindMineArg;
  844. static SSMStatus
  845. ssm_find_all_mine(PRIntn index, void *arg, void *key, void *itemdata)
  846. {
  847.     ssmCertData * data = (ssmCertData*)itemdata;
  848.     SSMFindMineArg *findArg = (SSMFindMineArg*) arg;
  849.     char *nick = (char*)key;
  850.     SSMStatus rv = SSM_FAILURE;
  851.     if (data->usage == clAllMine) {
  852.         CERTCertList *tmpList;
  853.         tmpList = CERT_CreateNicknameCertList(findArg->certList,
  854.                                               findArg->ctrl->m_certdb,
  855.                                               nick, PR_Now(), PR_FALSE);
  856.         if (tmpList != NULL) {
  857.             rv = SSM_SUCCESS;
  858.         }
  859.     }
  860.     return rv;
  861. }
  862. SSMStatus
  863. SSMSecurityAdvisorContext_BackupAllMineCerts(SSMSecurityAdvisorContext *cx, 
  864.                                              HTTPRequest               *req)
  865. {
  866.     SSMFindMineArg arg;
  867.     CERTCertList *certList=NULL;
  868.     SSMPKCS12Context *p12Cxt=NULL;
  869.     SSMPKCS12CreateArg p12Create;
  870.     SSMResourceID rid;
  871.     SSMStatus rv;
  872.     CERTCertificate **certArr = NULL;
  873.     int numCerts,i, finalCerts, currIndex;
  874.     CERTCertListNode *node;
  875.     PRIntn numNicks;
  876.     const char *responseKey;
  877.     certList = CERT_NewCertList();
  878.     if (certList == NULL) {
  879.         goto loser;
  880.     }
  881.     arg.certList = certList;
  882.     arg.ctrl     = req->ctrlconn;
  883.     numNicks = SSMSortedList_Enumerate(cx->m_certhash, ssm_find_all_mine, 
  884.                                        &arg);
  885.     if (numNicks <= 0){
  886.         /* No certs to backup */
  887.         SSM_HTTPReportError(req, HTTP_NO_CONTENT);
  888.         goto loser;
  889.     }
  890.     certList = arg.certList;
  891.     p12Create.isExportContext = PR_TRUE;
  892.     rv = (SSMStatus) SSM_CreateResource(SSM_RESTYPE_PKCS12_CONTEXT,
  893.                                         (void*)&p12Create, req->ctrlconn,
  894.                                         &rid, (SSMResource**)(&p12Cxt));
  895.     if (rv != SSM_SUCCESS) {
  896.         goto loser;
  897.     }
  898.     SSM_CopyCMTItem(&p12Cxt->super.m_clientContext, 
  899.                     &cx->super.m_clientContext);
  900.     
  901.     numCerts = SSM_CertListCount(certList);
  902.     certArr = SSM_NEW_ARRAY(CERTCertificate*,numCerts);
  903.     if (certArr == NULL) {
  904.         goto loser;
  905.     }
  906.     node = CERT_LIST_HEAD(certList);
  907.     for (i=0, currIndex=0, finalCerts=numCerts; i<numCerts; i++) {
  908.         if (node->cert->slot == NULL ||
  909.             PK11_IsInternal(node->cert->slot)) {
  910.             certArr[currIndex] = node->cert;
  911.             currIndex++;
  912.         } else {
  913.             finalCerts--;
  914.         }
  915.         node = CERT_LIST_NEXT(node);
  916.     }
  917.     rv = SSMPKCS12Context_CreatePKCS12FileForMultipleCerts(p12Cxt,
  918.                                                            PR_TRUE,
  919.                                                            certArr,
  920.                                                            finalCerts);
  921.     PR_Free(certArr);
  922.     certArr = NULL;
  923.     CERT_DestroyCertList(certList);
  924.     certList = NULL;
  925.     if (rv == SSM_SUCCESS) {
  926.         responseKey = (finalCerts > 1) ? "pkcs12_backup_multiple_success" :
  927.                                          "pkcs12_backup_success";
  928.     } else {
  929.         if (p12Cxt->super.m_buttonType == SSM_BUTTON_CANCEL) {
  930.             goto loser;
  931.         } else {
  932.             responseKey = SSMUI_GetPKCS12Error(rv, PR_TRUE);
  933.         }
  934.     }
  935.     SSM_FreeResource(&p12Cxt->super);
  936.     p12Cxt = NULL;
  937.     if (SSMSecurityAdvisorContext_DoPKCS12Response(cx, req, responseKey)
  938.         != SSM_SUCCESS) {
  939.         goto loser;
  940.     }
  941.     return SSM_SUCCESS;
  942.  loser:
  943.     PR_FREEIF(certArr);
  944.     if (certList != NULL) {
  945.         CERT_DestroyCertList(certList);
  946.     }
  947.     if (p12Cxt != NULL) {
  948.         SSM_FreeResource(&p12Cxt->super);
  949.     }
  950.     SSM_HTTPReportError(req, HTTP_NO_CONTENT);
  951.     return SSM_FAILURE;
  952. }
  953. SSMStatus SSMSecurityAdvisorContext_DoPKCS12Backup(
  954.                                               SSMSecurityAdvisorContext *cx,
  955.                                               HTTPRequest               *req)
  956. {
  957.     SSMStatus rv;
  958.     char *certNickname;
  959.     const char *responseKey;
  960.     SSMPKCS12CreateArg p12Create;
  961.     SSMResourceID rid;
  962.     SSMPKCS12Context *p12Cxt;
  963.     p12Create.isExportContext = PR_TRUE;
  964.     rv = (SSMStatus) SSM_CreateResource(SSM_RESTYPE_PKCS12_CONTEXT, 
  965.                                         (void*)&p12Create,
  966.                                         SSMRESOURCE(cx)->m_connection,
  967.                                         &rid, (SSMResource **)(&p12Cxt));
  968.     if (rv != PR_SUCCESS) {
  969.         goto loser;
  970.     }
  971.     /* pass along Advisor's client context for window management */
  972.     SSM_CopyCMTItem(&((SSMResource *)p12Cxt)->m_clientContext,
  973.                     &((SSMResource *)cx)->m_clientContext);
  974.     rv = SSM_HTTPParamValue(req, "selectCert", &certNickname);
  975.     if (rv != SSM_SUCCESS) {
  976.         goto loser;
  977.     }
  978.     
  979.     p12Cxt->m_cert = 
  980.         SSMSecurityAdvisorContext_FindCertByNickname(cx, req, certNickname);
  981.     if (cx->super.m_buttonType == SSM_BUTTON_CANCEL) {
  982.         goto loser;
  983.     }
  984.     if (p12Cxt->m_cert == NULL) {
  985.         goto loser;
  986.     }
  987.     /* p12Cxt->super.m_clientContext = cx->super.m_clientContext; */
  988.     rv = SSMPKCS12Context_CreatePKCS12File(p12Cxt, PR_TRUE);
  989.     if (rv == SSM_SUCCESS) {
  990.         responseKey = "pkcs12_backup_success";
  991.     } else {
  992.         if (p12Cxt->super.m_buttonType == SSM_BUTTON_CANCEL) {
  993.             goto loser;
  994.         } else {
  995.             responseKey = SSMUI_GetPKCS12Error(rv, PR_TRUE);
  996.         }
  997.     }
  998.     if (SSMSecurityAdvisorContext_DoPKCS12Response(cx, req, responseKey)
  999.         != SSM_SUCCESS) {
  1000.         goto loser;
  1001.     }
  1002.     SSM_FreeResource(&p12Cxt->super);
  1003.     return SSM_SUCCESS;
  1004.  loser:
  1005.     if (p12Cxt != NULL) {
  1006.         SSM_FreeResource(&p12Cxt->super);
  1007.     }
  1008.     SSM_HTTPReportError(req, HTTP_NO_CONTENT);
  1009.     return SSM_FAILURE;
  1010. }
  1011. char *
  1012. ssm_packb64_name(char *b64Name)
  1013. {
  1014.     char *htmlString = NULL;
  1015.     int numPercentSigns = 0;
  1016.     char *cursor, *retString;
  1017.     int i, newLen, origHTMLStrLen; 
  1018.     htmlString = SSM_ConvertStringToHTMLString(b64Name);
  1019.     /*
  1020.      * Now let's see if there are any '%' characters that need
  1021.      * to be escaped so that printf statements succeed.
  1022.      */
  1023.     cursor = htmlString;
  1024.     while ((cursor = PL_strchr(cursor, '%')) != NULL) {
  1025.         numPercentSigns++;
  1026.         cursor++;
  1027.     }
  1028.     if (numPercentSigns == 0) {
  1029.         htmlString;
  1030.     }
  1031.     origHTMLStrLen = PL_strlen(htmlString);
  1032.     newLen = origHTMLStrLen + numPercentSigns + 1;
  1033.     retString = SSM_NEW_ARRAY(char, newLen);
  1034.     for (i=0,cursor=retString; i<origHTMLStrLen+1; i++,cursor++) {
  1035.         if (htmlString[i] == '%') {
  1036.             char *dollarSign, *placeHolder;
  1037.             /*
  1038.              * Let's see if this a urlencoded escape or a printf parameter.
  1039.              */
  1040.             placeHolder = &htmlString[i];
  1041.             dollarSign = PL_strchr(placeHolder, '$');
  1042.             if (dollarSign && ((dollarSign - placeHolder) < 2)) {
  1043.                 /*
  1044.                  * OK, this is a numbered parameter for printf
  1045.                  */
  1046.                 *cursor = htmlString[i];
  1047.             } else {
  1048.                 /*
  1049.                  * This is an escape for url encoding.  Escape it so printf
  1050.                  * doesn't blow up.
  1051.                  */
  1052.                 *cursor = '%';
  1053.                 cursor++;
  1054.                 *cursor = '%';
  1055.             }
  1056.         } else {
  1057.             *cursor = htmlString[i];
  1058.         }
  1059.     }
  1060.     PR_Free(htmlString);
  1061.     return retString;
  1062. }
  1063. SSMStatus
  1064. SSMSecurityAdvisorContext_ProcessCRLDialog (HTTPRequest *req)
  1065. {
  1066.     SSMHTTPParamMultValues crlNames={NULL, NULL, 0};
  1067.     CERTSignedCrl *realCrl;
  1068.     SECItem crlDERName;
  1069.     PRBool flushSSLCache = PR_FALSE;
  1070.     SSMStatus rv;
  1071.     SECStatus srv;
  1072.     int i, type;
  1073.     rv = SSM_HTTPParamValueMultiple(req, "crlNames", &crlNames);
  1074.     if (rv != SSM_SUCCESS || crlNames.numValues == 0) {
  1075.         goto loser;
  1076.     }
  1077.     memset (&crlDERName, 0, sizeof(SECItem));
  1078.     for (i=0; i<crlNames.numValues; i++) {
  1079.         /*
  1080.          * The first character in the value string represents the type,
  1081.          * either 1 (SEC_CRL_TYPE) or 0 (SEC_KRL_TYPE)
  1082.          */
  1083.         srv = ATOB_ConvertAsciiToItem(&crlDERName, crlNames.values[i]+1);
  1084.         if (srv != SECSuccess) {
  1085.             goto loser;
  1086.         }
  1087.         type = (crlNames.values[i][0] == '1') ? SEC_CRL_TYPE : SEC_KRL_TYPE;
  1088.         realCrl = SEC_FindCrlByName(req->ctrlconn->m_certdb, 
  1089.                                     &crlDERName, type);
  1090.         SECITEM_FreeItem(&crlDERName, PR_FALSE);
  1091.         if (realCrl) {
  1092.             SEC_DeletePermCRL(realCrl);
  1093.             SEC_DestroyCrl(realCrl);
  1094.             flushSSLCache = PR_TRUE;            
  1095.         }
  1096.     }
  1097.     if (flushSSLCache) {
  1098.         SSL_ClearSessionCache();
  1099.     }
  1100.     if (!SSM_IsCRLPresent(req->ctrlconn)) {
  1101.         /*
  1102.          * In this case, there are no more CRLs in the database,
  1103.          * so we'll replace the baseRef with one that will cause
  1104.          * the security advisor to refresh itself and elminate the
  1105.          * "Delete CRLs" button.
  1106.          */
  1107.         for (i=0; i<req->numParams; i++) {
  1108.             char *crlCloseKey = "crlclose_doclose_js";
  1109.             if (PL_strcmp(req->paramNames[i], "baseRef") == 0) {
  1110.                 memcpy (req->paramValues[i], crlCloseKey, 
  1111.                         PL_strlen(crlCloseKey)+1);
  1112.                 break;
  1113.             }
  1114.         }
  1115.     }
  1116.     if (SSM_HTTPDefaultCommandHandler(req) != SSM_SUCCESS) {
  1117.         goto loser;
  1118.     }
  1119.     PR_FREEIF(crlNames.values);
  1120.     return SSM_SUCCESS;
  1121.  loser:
  1122.     PR_FREEIF(crlNames.values);
  1123.     return SSM_FAILURE;
  1124. }
  1125. SSMStatus SSMSecurityAdvisorContext_Process_cert_mine_form(
  1126.                                                 SSMSecurityAdvisorContext *res,
  1127.                                                 HTTPRequest *req)
  1128. {
  1129.     SSMStatus  rv= SSM_FAILURE;
  1130.     char      *button;
  1131.     
  1132.     /* Figure out which one of the buttons on the form was pressed. */
  1133.     if (SSM_HTTPParamValue(req, "backup", &button) == SSM_SUCCESS) {
  1134.       if (button != NULL) {
  1135.         rv = SSMSecurityAdvisorContext_DoPKCS12Backup(res, req);
  1136.       }
  1137.     } else if (SSM_HTTPParamValue(req, "restore", &button) == SSM_SUCCESS) {
  1138.       if (button != NULL) {
  1139.         rv = SSMSecurityAdvisorContext_DoPKCS12Restore(res, req);
  1140.       }
  1141.     } else if (SSM_HTTPParamValue(req, "delete", &button) == SSM_SUCCESS) {
  1142.         if (button != NULL) {
  1143.             rv = SSM_ProcessCertDeleteButton(req);
  1144.         }
  1145.     } else if (SSM_HTTPParamValue(req, "password", &button) == SSM_SUCCESS) {
  1146.         if (button != NULL) {
  1147.             rv = SSM_ProcessPasswordWindow(req);
  1148.         }
  1149.     } else if (SSM_HTTPParamValue(req, "ldap", &button) == SSM_SUCCESS) {
  1150.         if (button != NULL) {
  1151.             rv = SSM_ProcessLDAPWindow(req);
  1152.         }
  1153.     } else if (SSM_HTTPParamValue(req, "backup_all", &button) == SSM_SUCCESS) {
  1154.         if (button != NULL) {
  1155.             rv = SSMSecurityAdvisorContext_BackupAllMineCerts(res, req);
  1156.         }
  1157.     } else if (SSM_HTTPParamValue(req, "crlButton", &button) == SSM_SUCCESS) {
  1158.         if (button != NULL) {
  1159.     rv = SSM_HTTPReportError(req, HTTP_NO_CONTENT);
  1160. }
  1161.     }
  1162.     return rv;
  1163. }
  1164. static SSMStatus
  1165. SSMSecurityAdvisorContext_SetConfigOCSP(SSMSecurityAdvisorContext *cx, 
  1166.                                         HTTPRequest               *req)
  1167. {
  1168.     char *responderURL = NULL, *caNickname = NULL;
  1169.     char *enableOCSP = NULL;
  1170.     CERTCertDBHandle  *db;
  1171.     SSMStatus rv;
  1172.     SECStatus srv;
  1173.     db = cx->super.m_connection->m_certdb;
  1174.     rv = SSM_HTTPParamValue(req, "enableOCSP", &enableOCSP);
  1175.     if (rv != SSM_SUCCESS) {
  1176.         goto loser;
  1177.     }
  1178.     if (!strcmp(enableOCSP,"noOCSP")) {
  1179.         CERT_DisableOCSPChecking(db);
  1180.         SSMControlConnection_SaveBoolPref(req->ctrlconn, 
  1181.                                           "security.OCSP.enabled", 
  1182.                                           PR_FALSE);
  1183.         SSMControlConnection_SaveBoolPref(req->ctrlconn, 
  1184.                                           "security.OCSP.useDefaultResponder", 
  1185.                                           PR_FALSE);
  1186.         CERT_DisableOCSPChecking(db);
  1187.         CERT_DisableOCSPDefaultResponder(db);
  1188.     } else if (!strcmp(enableOCSP,"noDefaultResponder")) {
  1189.         srv = CERT_EnableOCSPChecking(db);
  1190.         SSMControlConnection_SaveBoolPref(req->ctrlconn, 
  1191.                                           "security.OCSP.enabled", 
  1192.                                           PR_TRUE);
  1193.         SSMControlConnection_SaveBoolPref(req->ctrlconn, 
  1194.                                           "security.OCSP.useDefaultResponder", 
  1195.                                           PR_FALSE);
  1196.         if (srv != SECSuccess) {
  1197.             goto loser;
  1198.         }
  1199.         CERT_DisableOCSPDefaultResponder(db);
  1200.     } else if (!strcmp(enableOCSP,"useDefaultResponder")) {
  1201.         srv = CERT_EnableOCSPChecking(db);
  1202.         SSMControlConnection_SaveBoolPref(req->ctrlconn, 
  1203.                                           "security.OCSP.enabled", 
  1204.                                           PR_TRUE);
  1205.         SSMControlConnection_SaveBoolPref(req->ctrlconn, 
  1206.                                           "security.OCSP.useDefaultResponder", 
  1207.                                           PR_TRUE);
  1208.         if (srv != SECSuccess) {
  1209.             goto loser;
  1210.         }
  1211.         rv = SSM_HTTPParamValue(req, "ocspURL", &responderURL);
  1212.         if (rv != SSM_SUCCESS) {
  1213.             goto loser;
  1214.         }
  1215.         SSMControlConnection_SaveStringPref(req->ctrlconn, 
  1216.                                             "security.OCSP.URL", 
  1217.                                             responderURL);
  1218.         rv = SSM_HTTPParamValue(req, "selectCert", &caNickname);
  1219.         if (rv != SSM_SUCCESS) {
  1220.             goto loser;
  1221.         }
  1222.         SSMControlConnection_SaveStringPref(req->ctrlconn, 
  1223.                                             "security.OCSP.signingCA", 
  1224.                                             caNickname);
  1225.         srv = CERT_SetOCSPDefaultResponder(db, responderURL, caNickname);
  1226.         if (srv != SECSuccess) {
  1227.             goto loser;
  1228.         }
  1229.         srv = CERT_EnableOCSPDefaultResponder(db);
  1230.         if (srv != SECSuccess) {
  1231.             goto loser;
  1232.         }
  1233.     } else {
  1234.         goto loser;
  1235.     }
  1236.     return SSM_SUCCESS;
  1237.  loser:
  1238.     return SSM_FAILURE;
  1239. }
  1240. static SSMStatus
  1241. SSMSecurityAdvisorContext_ProcessOCSPForm(SSMSecurityAdvisorContext *cx, 
  1242.                                           HTTPRequest               *req)
  1243. {
  1244.     SSMStatus rv = SSM_SUCCESS;
  1245.     /*
  1246.      * First, if the Cancel button was pressed, then don't 
  1247.      * process the form.
  1248.      */
  1249.     if (cx->super.m_buttonType == SSM_BUTTON_OK) {
  1250.         rv = SSMSecurityAdvisorContext_SetConfigOCSP(cx, req);
  1251.     }
  1252.     SSM_HTTPDefaultCommandHandler(req);
  1253.     return rv;
  1254. }
  1255. SSMStatus SSMSecurityAdvisorContext_FormSubmitHandler(SSMResource *res,
  1256.                                                       HTTPRequest *req)
  1257. {
  1258.     SSMStatus  rv;
  1259.     char      *formName;
  1260.     if (!SSM_IsAKindOf(res, SSM_RESTYPE_SECADVISOR_CONTEXT)) {
  1261.         return SSM_FAILURE;
  1262.     }
  1263.     /* First figure out which form we're processing. */
  1264.     rv = SSM_HTTPParamValue(req, "formName", &formName);
  1265.     if (rv != SSM_SUCCESS) {
  1266.         goto loser;
  1267.     }
  1268.     if (PL_strcmp(formName, "prefs_submit_form") == 0) {
  1269.         /* save pref changes and close the Security Advisor */
  1270.         rv = SSMSecurityAdvisorContext_SavePrefs
  1271.             ((SSMSecurityAdvisorContext*)res, req);
  1272.     }
  1273.     else if (!strcmp(formName, "cert_mine_form") ||
  1274.              !strcmp(formName, "cert_others_form") ||
  1275.              !strcmp(formName, "cert_websites_form") ||
  1276.              !strcmp(formName, "cert_authorities_form")) {
  1277.       rv = SSMSecurityAdvisorContext_Process_cert_mine_form
  1278.         ((SSMSecurityAdvisorContext*)res, req);
  1279.     } else if (!strcmp(formName, "choose_cert_by_usage")) {
  1280.       rv = SSM_ChooseCertUsageHandler(req);
  1281.     } else if (!strcmp(formName, "set_db_password")) {
  1282.       rv = SSM_SetDBPasswordHandler(req);
  1283.     } else if (!strcmp(formName, "configureOCSPForm")){
  1284.       rv = SSMSecurityAdvisorContext_ProcessOCSPForm
  1285.                                        ((SSMSecurityAdvisorContext*)res, req);
  1286.     } else if (!strcmp(formName, "crlDialog")){
  1287.         rv = SSMSecurityAdvisorContext_ProcessCRLDialog(req);
  1288.     }else {
  1289.       rv = SSM_ERR_BAD_REQUEST; 
  1290.       SSM_HTTPReportSpecificError(req, "Do not know how to process form %s",
  1291.                                   formName);
  1292.     }
  1293.   loser:
  1294.     return rv;
  1295. }
  1296. SSMStatus
  1297. SSMSecurityAdvisorContext_Print(SSMResource *res,
  1298.                                 char *fmt, PRIntn numParam,
  1299.                                 char **value, char **resultStr)
  1300. {
  1301.     SSMSecurityAdvisorContext *cx = (SSMSecurityAdvisorContext*)res;
  1302.     SSMStatus rv;
  1303.     PR_ASSERT(fmt != NULL && resultStr != NULL);
  1304.     if (!SSM_IsAKindOf(res, SSM_RESTYPE_SECADVISOR_CONTEXT)) {
  1305.         return PR_FAILURE;
  1306.     }
  1307.     /* We don't use the extra parameters */
  1308.     if (cx->m_nickname != NULL) {
  1309.         *resultStr = PR_smprintf(fmt, res->m_id, "backup", cx->m_nickname, *value);
  1310.         rv = (*resultStr == NULL) ? PR_FAILURE : PR_SUCCESS;
  1311.     } else {
  1312.         rv = SSMResource_Print(res, fmt, numParam, value, resultStr);
  1313.     }
  1314.     return rv;
  1315. }
  1316. SSMStatus SSM_SetSelectedItemInfo(SSMSecurityAdvisorContext* cx)
  1317. {
  1318. SSMStatus rv = SSM_SUCCESS;
  1319.     switch (cx->infoContext)
  1320.     {
  1321.         case SSM_NOINFO:
  1322.             cx->selectedItemPage = SSM_NO_INFO;
  1323.             break;
  1324.         case SSM_COMPOSE:
  1325.             break;
  1326. case SSM_SNEWS_MESSAGE:
  1327. case SSM_NEWS_MESSAGE:
  1328.         case SSM_MAIL_MESSAGE:
  1329.             cx->selectedItemPage = SSM_MESSAGE;
  1330. if (cx->encryptedP7CInfo) {
  1331.     /* Get the P7 Content info resource */
  1332. rv = SSMControlConnection_GetResource(SSMRESOURCE(cx)->m_connection, (SSMResourceID)cx->encryptedP7CInfo,
  1333.   (SSMResource**)&cx->encryptedP7CInfoRes);
  1334. if ((rv != PR_SUCCESS) || (cx->encryptedP7CInfoRes == NULL)) {
  1335. goto loser;
  1336. }
  1337. }
  1338. if (cx->signedP7CInfo) {
  1339.     /* Get the P7 Content info resource */
  1340. rv = SSMControlConnection_GetResource(SSMRESOURCE(cx)->m_connection, (SSMResourceID)cx->signedP7CInfo,
  1341.   (SSMResource**)&cx->signedP7CInfoRes);
  1342. if ((rv != PR_SUCCESS) || (cx->signedP7CInfoRes == NULL)) {
  1343. goto loser;
  1344. }
  1345. }
  1346. if (!cx->encryptedP7CInfo &&
  1347. !cx->signedP7CInfo &&
  1348. cx->verifyError &&
  1349. !cx->decodeError) {
  1350. /* Somehow we have the error code backwards */
  1351. cx->decodeError = cx->verifyError;
  1352. cx->verifyError = 0;
  1353. }
  1354. cx->encrypted_b = (cx->decodeError ||
  1355. (cx->encryptedP7CInfo &&
  1356. SEC_PKCS7ContentIsEncrypted(cx->encryptedP7CInfoRes->m_cinfo)) ||
  1357. (cx->signedP7CInfo &&
  1358. SEC_PKCS7ContentIsEncrypted(cx->signedP7CInfoRes->m_cinfo)));
  1359. cx->signed_b = (cx->verifyError ||
  1360. (cx->encryptedP7CInfo &&
  1361. SEC_PKCS7ContentIsSigned(cx->encryptedP7CInfoRes->m_cinfo)) ||
  1362. (cx->signedP7CInfo &&
  1363. SEC_PKCS7ContentIsSigned(cx->signedP7CInfoRes->m_cinfo)));
  1364.             break;
  1365.         case SSM_BROWSER:
  1366.             if (cx->resID == 0) {
  1367.                 cx->selectedItemPage = SSM_NAVIGATOR_NO_SEC;
  1368.             } else {
  1369.                 cx->selectedItemPage = SSM_NAVIGATOR_SSL;
  1370.             }
  1371.             break;
  1372.         default:
  1373.             cx->selectedItemPage = SSM_NO_INFO;
  1374.             break;
  1375.     }
  1376. return rv;
  1377. loser:
  1378. return SSM_FAILURE;
  1379. }
  1380. SSMStatus sa_noinfo(SSMTextGenContext *cx)
  1381. {
  1382.     SSMStatus rv = SSM_SUCCESS;
  1383.     SSMResource *target = NULL;
  1384.     SSMSecurityAdvisorContext* res = NULL;
  1385. char *fmt = NULL;
  1386.     /* get the connection object */
  1387.     target = SSMTextGen_GetTargetObject(cx);
  1388.     PR_ASSERT(target != NULL);
  1389.     res = (SSMSecurityAdvisorContext*)target;
  1390. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_noinfo", &fmt);
  1391. if (rv != SSM_SUCCESS) {
  1392. goto loser;
  1393. }
  1394.         PR_FREEIF(cx->m_result);
  1395. cx->m_result = fmt;
  1396. return SSM_SUCCESS;
  1397. loser:
  1398. return SSM_FAILURE;
  1399. }
  1400. SSMStatus sa_navigator(SSMTextGenContext *cx)
  1401. {
  1402.     SSMStatus rv = SSM_SUCCESS;
  1403.     SSMResource *target = NULL;
  1404.     SSMSecurityAdvisorContext* res = NULL;
  1405. char *fmt = NULL;
  1406. SSMSSLSocketStatus *socketStatusRes = NULL;
  1407. char * encryption_level = NULL;
  1408. char * serverCN = NULL;
  1409. char * issuerName = NULL;
  1410. CERTCertificate *issuerCert = NULL;
  1411. SSMResourceCert *serverCertRes = NULL, *issuerCertRes = NULL;
  1412. int serverCertResID, issuerCertResID;
  1413.     /* get the connection object */
  1414.     target = SSMTextGen_GetTargetObject(cx);
  1415.     PR_ASSERT(target != NULL);
  1416.     res = (SSMSecurityAdvisorContext*)target;
  1417. if (res->resID == 0) {
  1418. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_navigator_no_sec", &fmt);
  1419. if (rv != SSM_SUCCESS) {
  1420. goto loser;
  1421. }
  1422.                 PR_FREEIF(cx->m_result);
  1423. cx->m_result = PR_smprintf(fmt, res->hostname, res->hostname);
  1424. PR_Free(fmt);
  1425. return SSM_SUCCESS;
  1426. } else {
  1427.     /* Get the socket status resource */
  1428. rv = SSMControlConnection_GetResource(SSMRESOURCE(res)->m_connection, (SSMResourceID)res->resID,
  1429.   (SSMResource**)&socketStatusRes);
  1430. if ((rv != PR_SUCCESS) || (socketStatusRes == NULL)) {
  1431. goto loser;
  1432. }
  1433.         /*
  1434.          * We inherit the client's reference here.
  1435.          */
  1436.         res->socketStatus = socketStatusRes;
  1437. /* Do we have an error */
  1438. if (!socketStatusRes->m_error) {
  1439. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_navigator_ssl", &fmt);
  1440. if (rv != SSM_SUCCESS) {
  1441. goto loser;
  1442. }
  1443. #if 0
  1444. /* Create a resource for this cert */
  1445. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1446. socketStatusRes->m_cert,
  1447. SSMRESOURCE(res)->m_connection,
  1448. (long *) &serverCertResID,
  1449. (SSMResource**)&serverCertRes);
  1450. if (rv != PR_SUCCESS) {
  1451. goto loser;
  1452. }
  1453. #else
  1454.             serverCertResID = socketStatusRes->m_cert->super.m_id;
  1455.             serverCertRes = socketStatusRes->m_cert;
  1456. #endif
  1457. issuerName = CERT_NameToAscii(&socketStatusRes->m_cert->cert->issuer);
  1458. if (socketStatusRes->m_level == SSL_SECURITY_STATUS_ON_HIGH) {
  1459. SSM_GetUTF8Text(cx, "high_grade_encryption", &encryption_level);
  1460. } else {
  1461. SSM_GetUTF8Text(cx, "low_grade_encryption", &encryption_level);
  1462. }
  1463.             PR_FREEIF(cx->m_result);
  1464. cx->m_result = PR_smprintf(fmt, res->hostname, issuerName, target->m_id, serverCertResID,
  1465. encryption_level, socketStatusRes->m_cipherName,
  1466. socketStatusRes->m_secretKeySize);
  1467. PR_Free(issuerName);
  1468. PR_Free(encryption_level);
  1469. PR_Free(fmt);
  1470.             SSM_FreeResource(&socketStatusRes->super);
  1471. return SSM_SUCCESS;
  1472. } else {
  1473. if (socketStatusRes->m_error == SEC_ERROR_UNKNOWN_ISSUER ||
  1474. socketStatusRes->m_error == SEC_ERROR_CA_CERT_INVALID ) {
  1475. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_navigator_ssl_unknown_issuer", &fmt);
  1476. if (rv != SSM_SUCCESS) {
  1477. goto loser;
  1478. }
  1479. /* Get the common name of the issuer */
  1480. issuerName = CERT_NameToAscii(&socketStatusRes->m_cert->cert->issuer);
  1481. if (!issuerName) {
  1482. goto loser;
  1483. }
  1484. /* Get the common name of the server cert */
  1485. serverCN = CERT_GetCommonName(&socketStatusRes->m_cert->cert->subject);
  1486. if (!serverCN) {
  1487. goto loser;
  1488. }
  1489. #if 0
  1490. /* Create resource for the server cert */
  1491. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1492. socketStatusRes->m_cert,
  1493. SSMRESOURCE(res)->m_connection,
  1494. (long *) &serverCertResID,
  1495. (SSMResource**)&serverCertRes);
  1496. if (rv != PR_SUCCESS) {
  1497. goto loser;
  1498. }
  1499. #else 
  1500.                 serverCertRes = socketStatusRes->m_cert;
  1501.                 serverCertResID = serverCertRes->super.m_id;
  1502. #endif
  1503. if (socketStatusRes->m_level == SSL_SECURITY_STATUS_ON_HIGH) {
  1504. SSM_GetUTF8Text(cx, "high_grade_encryption", &encryption_level);
  1505. } else {
  1506. SSM_GetUTF8Text(cx, "low_grade_encryption", &encryption_level);
  1507. }
  1508.                                 PR_FREEIF(cx->m_result);
  1509. cx->m_result = PR_smprintf(fmt, res->hostname, issuerName, target->m_id, serverCertResID,
  1510. encryption_level, socketStatusRes->m_cipherName,
  1511. socketStatusRes->m_secretKeySize);
  1512. PR_Free(fmt);
  1513. PR_Free(issuerName);
  1514. PR_Free(serverCN);
  1515. PR_Free(encryption_level);
  1516.                 SSM_FreeResource(&socketStatusRes->super);
  1517. return SSM_SUCCESS;
  1518. } else if(socketStatusRes->m_error == SEC_ERROR_UNTRUSTED_ISSUER) {
  1519. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_navigator_ssl_bad_issuer", &fmt);
  1520. if (rv != SSM_SUCCESS) {
  1521. goto loser;
  1522. }
  1523. /* Get the common name of the issuer */
  1524. issuerName = CERT_NameToAscii(&socketStatusRes->m_cert->cert->issuer);
  1525. if (!issuerName) {
  1526. goto loser;
  1527. }
  1528. /* Get the common name of the server cert */
  1529. serverCN = CERT_GetCommonName(&socketStatusRes->m_cert->cert->subject);
  1530. if (!serverCN) {
  1531. goto loser;
  1532. }
  1533. #if 0
  1534. /* Create resource for the server cert */
  1535. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1536. socketStatusRes->m_cert,
  1537. SSMRESOURCE(res)->m_connection,
  1538. (long *) &serverCertResID,
  1539. (SSMResource**)&serverCertRes);
  1540. if (rv != PR_SUCCESS) {
  1541. goto loser;
  1542. }
  1543. #else 
  1544.                 serverCertRes = socketStatusRes->m_cert;
  1545.                 serverCertResID = serverCertRes->super.m_id;
  1546. #endif
  1547. /* Create a resource for the issuer cert (if it exists) */
  1548. issuerCert = CERT_FindCertIssuer(socketStatusRes->m_cert->cert,
  1549.                                                  PR_Now(), certUsageAnyCA);
  1550. if (issuerCert) {
  1551. /* Create resource for the issuer cert */
  1552. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1553. issuerCert,
  1554. SSMRESOURCE(res)->m_connection,
  1555. (long *) &issuerCertResID,
  1556. (SSMResource**)&issuerCertRes);
  1557. if (rv != PR_SUCCESS) {
  1558. goto loser;
  1559. }
  1560. } else {
  1561. issuerCertResID = 0;
  1562. }
  1563. if (socketStatusRes->m_level == SSL_SECURITY_STATUS_ON_HIGH) {
  1564. SSM_GetUTF8Text(cx, "high_grade_encryption", &encryption_level);
  1565. } else {
  1566. SSM_GetUTF8Text(cx, "low_grade_encryption", &encryption_level);
  1567. }
  1568.                                 PR_FREEIF(cx->m_result);
  1569. cx->m_result = PR_smprintf(fmt, res->hostname, issuerName, target->m_id, serverCertResID,
  1570. issuerCertResID, encryption_level, socketStatusRes->m_cipherName,
  1571. socketStatusRes->m_secretKeySize);
  1572. PR_Free(fmt);
  1573. PR_Free(issuerName);
  1574. PR_Free(serverCN);
  1575. PR_Free(encryption_level);
  1576.                 SSM_FreeResource(&socketStatusRes->super);
  1577. return SSM_SUCCESS;
  1578. } else if (socketStatusRes->m_error == SSL_ERROR_BAD_CERT_DOMAIN) {
  1579. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_navigator_ssl_bad_cert_domain", &fmt);
  1580. if (rv != SSM_SUCCESS) {
  1581. goto loser;
  1582. }
  1583. /* Get the common name of the server cert */
  1584. serverCN = CERT_GetCommonName(&socketStatusRes->m_cert->cert->subject);
  1585. if (!serverCN) {
  1586. goto loser;
  1587. }
  1588. if (socketStatusRes->m_level == SSL_SECURITY_STATUS_ON_HIGH) {
  1589. SSM_GetUTF8Text(cx, "high_grade_encryption", &encryption_level);
  1590. } else {
  1591. SSM_GetUTF8Text(cx, "low_grade_encryption", &encryption_level);
  1592. }
  1593.                     PR_FREEIF(cx->m_result);
  1594. cx->m_result = PR_smprintf(fmt, res->hostname, serverCN, encryption_level, socketStatusRes->m_cipherName,
  1595. socketStatusRes->m_secretKeySize);
  1596. PR_Free(fmt);
  1597. PR_Free(serverCN);
  1598. PR_Free(encryption_level);
  1599.                     SSM_FreeResource(&socketStatusRes->super);
  1600. return SSM_SUCCESS;
  1601. } else {
  1602. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_navigator_ssl_unknown_error", &fmt);
  1603. if (rv != SSM_SUCCESS) {
  1604. goto loser;
  1605. }
  1606. #if 0
  1607. /* Create resource for the server cert */
  1608. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1609. socketStatusRes->m_cert,
  1610. SSMRESOURCE(res)->m_connection,
  1611. (long *) &serverCertResID,
  1612. (SSMResource**)&serverCertRes);
  1613. if (rv != PR_SUCCESS) {
  1614. goto loser;
  1615. }
  1616. #else
  1617.                 serverCertRes = socketStatusRes->m_cert;
  1618.                 serverCertResID = serverCertRes->super.m_id;
  1619. #endif
  1620. if (socketStatusRes->m_level == SSL_SECURITY_STATUS_ON_HIGH) {
  1621. SSM_GetUTF8Text(cx, "high_grade_encryption", &encryption_level);
  1622. } else {
  1623. SSM_GetUTF8Text(cx, "low_grade_encryption", &encryption_level);
  1624. }
  1625.                 PR_FREEIF(cx->m_result);
  1626. cx->m_result = PR_smprintf(fmt, res->hostname, target->m_id, serverCertResID, encryption_level, socketStatusRes->m_cipherName,
  1627. socketStatusRes->m_secretKeySize);
  1628. PR_Free(fmt);
  1629.                 SSM_FreeResource(&socketStatusRes->super);
  1630. return SSM_SUCCESS;
  1631. }
  1632. }
  1633. }
  1634. loser:
  1635. PR_FREEIF(fmt);
  1636. PR_FREEIF(serverCN);
  1637. PR_FREEIF(issuerName);
  1638.     if (socketStatusRes) {
  1639.         SSM_FreeResource(&socketStatusRes->super);
  1640.     }
  1641. return SSM_FAILURE;
  1642. }
  1643. static CERTCertificate * get_signer_cert(SSMSecurityAdvisorContext *res)
  1644. {
  1645. CERTCertificate * cert = NULL;
  1646. /* Get the signing cert */
  1647. if (res->signedP7CInfoRes ||
  1648. res->encryptedP7CInfoRes) {
  1649. SEC_PKCS7SignerInfo **signerinfos;
  1650. SEC_PKCS7ContentInfo *ci = res->signedP7CInfoRes->m_cinfo;
  1651. if (!ci) ci = res->encryptedP7CInfoRes->m_cinfo;
  1652. /* Finding the signers cert */
  1653. switch(ci->contentTypeTag->offset) {
  1654. default:
  1655. case SEC_OID_PKCS7_DATA:
  1656. case SEC_OID_PKCS7_DIGESTED_DATA:
  1657. case SEC_OID_PKCS7_ENVELOPED_DATA:
  1658. case SEC_OID_PKCS7_ENCRYPTED_DATA:
  1659. /* Could only get here if SEC_PKCS7ContentIsSigned
  1660. * is broken. */
  1661. {
  1662. PORT_Assert (0);
  1663. cert=NULL;
  1664. }
  1665. break;
  1666. case SEC_OID_PKCS7_SIGNED_DATA:
  1667. {
  1668. SEC_PKCS7SignedData *sdp;
  1669. sdp = ci->content.signedData;
  1670. signerinfos = sdp->signerInfos;
  1671. cert = signerinfos[0]->cert;
  1672. }
  1673. break;
  1674. case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
  1675. {
  1676. SEC_PKCS7SignedAndEnvelopedData *saedp;
  1677. saedp = ci->content.signedAndEnvelopedData;
  1678. signerinfos = saedp->signerInfos;
  1679. cert = signerinfos[0]->cert;
  1680. }
  1681. break;
  1682. } /* finding the signer cert */
  1683. }
  1684. return cert;
  1685. }
  1686. char*
  1687. SSM_GetOCSPURL(CERTCertificate *cert, PrefSet *prefs)
  1688. {
  1689.     SSMStatus rv;
  1690.     PRBool boolval = PR_FALSE;
  1691.     char *responderURL = NULL;
  1692.     /* Is there a default responder installed */
  1693.     rv = PREF_GetBoolPref(prefs, "security.OCSP.useDefaultResponder", &boolval);
  1694.     if (boolval) {
  1695.         PREF_CopyStringPref(prefs, "security.OCSP.URL", &responderURL);
  1696.     } else {
  1697. responderURL = CERT_GetOCSPAuthorityInfoAccessLocation(cert);
  1698.     }
  1699.     return responderURL;
  1700. }
  1701. static CERTCertificate * get_encryption_cert(SSMSecurityAdvisorContext *res)
  1702. {
  1703. return NULL;
  1704. }
  1705. static char *
  1706. sa_get_algorithm_string(SEC_PKCS7ContentInfo *cinfo)
  1707. {
  1708. SECAlgorithmID *algid;
  1709. SECOidTag algtag;
  1710. const char *alg_name;
  1711. int key_size;
  1712. if (!cinfo) return 0;
  1713. algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
  1714. if (!algid) return 0;
  1715. algtag = SECOID_GetAlgorithmTag(algid);
  1716. alg_name = SECOID_FindOIDTagDescription(algtag);
  1717. key_size = SEC_PKCS7GetKeyLength(cinfo);
  1718. if (!alg_name || !*alg_name)
  1719. return 0;
  1720. else if (key_size > 0)
  1721. return PR_smprintf("%d-bits %s",
  1722.        key_size, alg_name);
  1723. else
  1724. return PL_strdup(alg_name);
  1725. }
  1726. PRBool
  1727. SSM_IsOCSPEnabled(SSMControlConnection *connection) 
  1728. {
  1729.     SSMStatus rv;
  1730.     PRBool isOCSPEnabled = PR_FALSE;
  1731.     rv = PREF_GetBoolPref(connection->m_prefs, "security.OCSP.enabled",
  1732.                           &isOCSPEnabled);
  1733.     return (rv == SSM_SUCCESS) ? isOCSPEnabled : PR_FALSE; 
  1734. }
  1735. char *
  1736. SSM_GetGenericOCSPWarning(SSMControlConnection *ctrl,
  1737.                           CERTCertificate *cert)
  1738. {
  1739.     char *retString = NULL;
  1740.     char *responderURL = NULL;
  1741.     SSMTextGenContext *cx = NULL;
  1742.     SSMStatus rv;
  1743.     retString = PL_strdup("");
  1744.     if (SSM_IsOCSPEnabled(ctrl)) {
  1745.         responderURL = SSM_GetOCSPURL(cert, ctrl->m_prefs);
  1746.         if (responderURL == NULL) {
  1747.             goto done;
  1748.         }
  1749.         rv = SSMTextGen_NewTopLevelContext(NULL, &cx);
  1750.         if (rv != SSM_SUCCESS) {
  1751.             goto done;
  1752.         }
  1753.         SSM_GetAndExpandTextKeyedByString(cx, "ocsp_fail_message_generic",
  1754.                                           &retString);
  1755.     } 
  1756.  done:
  1757.     PR_FREEIF(responderURL);
  1758.     if (cx) {
  1759.         SSMTextGen_DestroyContext(cx);
  1760.     }
  1761.     return retString;
  1762. }
  1763. SSMStatus sa_message(SSMTextGenContext *cx)
  1764. {
  1765.     SSMStatus rv = SSM_SUCCESS;
  1766.     SSMResource *target = NULL;
  1767.     SSMSecurityAdvisorContext* res = NULL;
  1768. char *fmt = NULL, *fmtSigned = NULL, *fmtEncrypted = NULL;
  1769.     char *genericOCSPWarning = NULL;
  1770.     /* get the connection object */
  1771.     target = SSMTextGen_GetTargetObject(cx);
  1772.     PR_ASSERT(target != NULL);
  1773.     res = (SSMSecurityAdvisorContext*)target;
  1774. /* Deal with the signed part first */
  1775. if (!res->signed_b) {
  1776. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_not_signed", &fmtSigned);
  1777. if (rv != SSM_SUCCESS) {
  1778. goto loser;
  1779. }
  1780. } else {
  1781. if (res->verifyError == 0) {
  1782. char *signer_email;
  1783. CERTCertificate *signerCert = NULL;
  1784. SSMResourceCert *signerCertRes = NULL;
  1785. int signerCertResID;
  1786. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed", &fmt);
  1787. if (rv != SSM_SUCCESS) {
  1788. goto loser;
  1789. }
  1790. signerCert = get_signer_cert(res);
  1791. if (!signerCert) {
  1792. goto loser;
  1793. }
  1794. /* Get the signers email address */
  1795. if (res->signedP7CInfoRes) {
  1796. signer_email = SEC_PKCS7GetSignerEmailAddress(res->signedP7CInfoRes->m_cinfo);
  1797. }
  1798. if (!signer_email && res->encryptedP7CInfoRes) {
  1799. signer_email = SEC_PKCS7GetSignerEmailAddress(res->encryptedP7CInfoRes->m_cinfo);
  1800. }
  1801. /* Create a cert resource for this certificate */
  1802.     rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1803.                         signerCert,
  1804.                     SSMRESOURCE(res)->m_connection,
  1805.                 (long *) &signerCertResID,
  1806.             (SSMResource**)&signerCertRes);
  1807. if (rv != PR_SUCCESS) {
  1808.             goto loser;
  1809.     }
  1810. fmtSigned = PR_smprintf(fmt, signer_email, target->m_id, signerCertResID);
  1811. PR_Free(fmt);
  1812. } else {
  1813.             CERTCertificate *signerCert;
  1814.             /* Get the signing certificate */
  1815.             signerCert = get_signer_cert(res);
  1816.             if (!signerCert) {
  1817.                 goto loser;
  1818.             }
  1819.             genericOCSPWarning = 
  1820.                 SSM_GetGenericOCSPWarning(target->m_connection,
  1821.                                           signerCert);
  1822. switch(res->verifyError) {
  1823. case SEC_ERROR_PKCS7_BAD_SIGNATURE:
  1824. {
  1825. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_bad_signature", &fmt);
  1826. if (rv != SSM_SUCCESS) {
  1827. goto loser;
  1828. }
  1829.                         fmtSigned = PR_smprintf(fmt, genericOCSPWarning);
  1830.                         PR_FREEIF(fmt);
  1831. }
  1832. break;
  1833. /* This case handles both expired and not yet valid certs */
  1834. case SEC_ERROR_EXPIRED_CERTIFICATE:
  1835. {
  1836. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_expired_signing_cert", &fmt);
  1837. if (rv != SSM_SUCCESS) {
  1838. goto loser;
  1839. }
  1840.                         fmtSigned = PR_smprintf(fmt, genericOCSPWarning);
  1841.                         PR_FREEIF(fmt);
  1842. }
  1843. break;
  1844. case SEC_ERROR_REVOKED_CERTIFICATE:
  1845. {
  1846. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_revoked_signing_cert", &fmt);
  1847. if (rv != SSM_SUCCESS) {
  1848. goto loser;
  1849. }
  1850.                         fmtSigned = PR_smprintf(fmt, genericOCSPWarning);
  1851.                         PR_FREEIF(fmt);
  1852. }
  1853. break;
  1854. case SEC_ERROR_UNKNOWN_ISSUER:
  1855. {
  1856. SSMResourceCert *signerCertRes;
  1857. PRUint32 signerCertResID;
  1858. char *fmt;
  1859. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_unknown_issuer", &fmt);
  1860. if (rv != SSM_SUCCESS) {
  1861. goto loser;
  1862. }
  1863. /* Create a cert resource for this certificate */
  1864. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1865. signerCert,
  1866. SSMRESOURCE(res)->m_connection,
  1867. (long *) &signerCertResID,
  1868. (SSMResource**)&signerCertRes);
  1869. if (rv != PR_SUCCESS) {
  1870. goto loser;
  1871. }
  1872. fmtSigned = PR_smprintf(fmt, target->m_id, 
  1873.                                                 signerCertResID, 
  1874.                                                 genericOCSPWarning);
  1875. PR_Free(fmt);
  1876. }
  1877. break;
  1878. case SEC_ERROR_CA_CERT_INVALID:
  1879. case SEC_ERROR_UNTRUSTED_ISSUER:
  1880. {
  1881. CERTCertificate *issuerCert;
  1882. SSMResourceCert * signerCertRes, issuerCertRes;
  1883. PRInt32 signerCertResID, issuerCertResID;
  1884. char *fmt = NULL;
  1885. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_untrusted_issuer", &fmt);
  1886. if (rv != SSM_SUCCESS) {
  1887. goto loser;
  1888. }
  1889. /* Get the isser cert */
  1890. issuerCert = CERT_FindCertIssuer(signerCert, PR_Now(), certUsageAnyCA);
  1891. if (!issuerCert) {
  1892. goto loser;
  1893. }
  1894. /* Create resources for these certs */
  1895. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1896. signerCert,
  1897. SSMRESOURCE(res)->m_connection,
  1898. (long *) &signerCertResID,
  1899. (SSMResource**)&signerCertRes);
  1900. if (rv != SSM_SUCCESS) {
  1901. goto loser;
  1902. }
  1903. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1904. issuerCert,
  1905. SSMRESOURCE(res)->m_connection,
  1906. (long *) &issuerCertResID,
  1907. (SSMResource**)&issuerCertRes);
  1908. if (rv != SSM_SUCCESS) {
  1909. goto loser;
  1910. }
  1911. fmtSigned = PR_smprintf(fmt, target->m_id, 
  1912.                                                 signerCertResID, 
  1913.                                                 issuerCertResID,
  1914.                                                 genericOCSPWarning);
  1915. PR_Free(fmt);
  1916. }
  1917. break;
  1918. /* This case handles both expired and not yet valid certs */
  1919. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  1920. {
  1921. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_expired_issuer_cert", &fmt);
  1922. if (rv != SSM_SUCCESS) {
  1923. goto loser;
  1924. }
  1925.                         fmtSigned = PR_smprintf(fmt, genericOCSPWarning);
  1926.                         PR_FREEIF(fmt);
  1927. }
  1928. break;
  1929. /* Cert address mismatch */
  1930. case SEC_ERROR_CERT_ADDR_MISMATCH:
  1931. {
  1932. char * signer_email = NULL;
  1933. char * signerCN = NULL;
  1934. CERTCertificate *signerCert = NULL;
  1935. SSMResourceCert *signerCertRes = NULL;
  1936. PRInt32 signerCertResID;
  1937. SECItem * item = NULL;
  1938. char *signTime = NULL;
  1939. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_addr_mismatch", &fmt);
  1940. if (rv != SSM_SUCCESS) {
  1941. goto loser;
  1942. }
  1943. /* Get the signer cert */
  1944. signerCert = get_signer_cert(res);
  1945. if (!signerCert) {
  1946. goto loser;
  1947. }
  1948. /* Get the signer common name */
  1949. signerCN = CERT_GetCommonName(&signerCert->subject);
  1950. /* Get the signing time */
  1951. item = SEC_PKCS7GetSigningTime(res->signedP7CInfoRes->m_cinfo);
  1952. signTime = (item ? DER_UTCTimeToAscii(item) : 0);
  1953. /* Create resources for these certs */
  1954. rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE,
  1955. signerCert,
  1956. SSMRESOURCE(res)->m_connection,
  1957. (long *) &signerCertResID,
  1958. (SSMResource**)&signerCertRes);
  1959. if (rv != SSM_SUCCESS) {
  1960. goto loser;
  1961. }
  1962. /* Get the signers email address */
  1963. if (res->signedP7CInfoRes) {
  1964. signer_email = SEC_PKCS7GetSignerEmailAddress(res->signedP7CInfoRes->m_cinfo);
  1965. }
  1966. if (!signer_email && res->encryptedP7CInfoRes) {
  1967. signer_email = SEC_PKCS7GetSignerEmailAddress(res->encryptedP7CInfoRes->m_cinfo);
  1968. }
  1969. fmtSigned = PR_smprintf(fmt,res->senderAddr,signer_email,signerCN,signTime, target->m_id, signerCertResID);
  1970. PR_Free(fmt);
  1971. PR_FREEIF(signer_email);
  1972. PR_FREEIF(signTime);
  1973. }
  1974. break;
  1975. default:
  1976. {
  1977. CERTCertificate *signerCert = NULL;
  1978. SSMStatus rv = SSM_SUCCESS;
  1979. PrefSet* prefs = NULL;
  1980. char *responderURL = NULL;
  1981. prefs = res->super.m_connection->m_prefs;
  1982. if (SSM_IsOCSPEnabled(res->super.m_connection)) {
  1983.     
  1984.         responderURL = SSM_GetOCSPURL(get_signer_cert(res), prefs);
  1985. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_ocsp_error", &fmt);
  1986. if (rv != SSM_SUCCESS) {
  1987. goto loser;
  1988. }
  1989. fmtSigned = PR_smprintf(fmt,responderURL,res->verifyError);
  1990. PR_Free(fmt);
  1991. PR_Free(responderURL);
  1992. } else {
  1993. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_signed_unknown_error", &fmtSigned);
  1994. if (rv != SSM_SUCCESS) {
  1995. goto loser;
  1996. }
  1997. }
  1998. }
  1999. break;
  2000. /* XXX Missing the case where the issuer cert has been revoked XXX */
  2001. }
  2002. }
  2003. }
  2004.     PR_FREEIF(genericOCSPWarning);
  2005. /* Now deal with the encrypted part */
  2006. if (!res->encrypted_b) {
  2007. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_not_encrypted", &fmtEncrypted);
  2008. if (rv != SSM_SUCCESS) {
  2009. goto loser;
  2010. }
  2011. } else {
  2012. if (res->decodeError == 0) {
  2013. SECAlgorithmID *algid;
  2014. SECOidTag algtag;
  2015. const char *alg_name;
  2016. char *encryption_level;
  2017. int key_size;
  2018. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_encrypted", &fmt);
  2019. if (rv != SSM_SUCCESS) {
  2020. goto loser;
  2021. }
  2022.             if (res->encryptedP7CInfoRes == NULL) {
  2023. algid = SEC_PKCS7GetEncryptionAlgorithm(res->signedP7CInfoRes->m_cinfo);
  2024.             } else {
  2025. algid = SEC_PKCS7GetEncryptionAlgorithm(res->encryptedP7CInfoRes->m_cinfo);
  2026.             }
  2027. if (!algid) {
  2028. goto loser;
  2029. }
  2030. algtag = SECOID_GetAlgorithmTag(algid);
  2031. alg_name = SECOID_FindOIDTagDescription(algtag);
  2032.             if (res->encryptedP7CInfoRes) {
  2033. key_size = SEC_PKCS7GetKeyLength(res->encryptedP7CInfoRes->m_cinfo);
  2034.             } else {
  2035. key_size = SEC_PKCS7GetKeyLength(res->signedP7CInfoRes->m_cinfo);
  2036.             }
  2037. if (key_size == 40) {
  2038. SSM_GetUTF8Text(cx, "low_grade_encryption", &encryption_level);
  2039. } else if (key_size == 56 || key_size == 64) {
  2040. SSM_GetUTF8Text(cx, "medium_grade_encryption", &encryption_level);
  2041. } else {
  2042. SSM_GetUTF8Text(cx, "high_grade_encryption", &encryption_level);
  2043. }
  2044. fmtEncrypted = PR_smprintf(fmt, encryption_level, key_size, alg_name);
  2045. PR_Free(fmt);
  2046. } else {
  2047. switch (res->decodeError) {
  2048. case SEC_ERROR_NOT_A_RECIPIENT:
  2049. {
  2050. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_encrypted_no_recipient", &fmtEncrypted);
  2051. if (rv != SSM_SUCCESS) {
  2052. goto loser;
  2053. }
  2054. }
  2055. break;
  2056. case SEC_ERROR_BAD_PASSWORD:
  2057. {
  2058. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_encrypted_bad_password", &fmtEncrypted);
  2059. if (rv != SSM_SUCCESS) {
  2060. goto loser;
  2061. }
  2062. }
  2063. break;
  2064. /* XXX Missing cases for contents altered and encryption strength mismatch XXX */
  2065. default:
  2066. {
  2067. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_message_encrypted_unknown_error", &fmtEncrypted);
  2068. if (rv != SSM_SUCCESS) {
  2069. goto loser;
  2070. }
  2071. }
  2072. }
  2073. }
  2074. }
  2075. /* Output the stirngs */
  2076. PR_FREEIF(cx->m_result);
  2077. cx->m_result = PR_smprintf("%s%s", fmtSigned, fmtEncrypted);
  2078. PR_Free(fmtSigned);
  2079. PR_Free(fmtEncrypted);
  2080. return SSM_SUCCESS;
  2081. loser:
  2082. PR_FREEIF(fmt);
  2083. PR_FREEIF(fmtSigned);
  2084. PR_FREEIF(fmtEncrypted);
  2085. return SSM_FAILURE;
  2086. }
  2087. SSMStatus sa_compose(SSMTextGenContext *cx)
  2088. {
  2089.     SSMStatus rv = SSM_SUCCESS;
  2090.     SSMResource *target = NULL;
  2091.     SSMSecurityAdvisorContext* res = NULL;
  2092. char *fmt = NULL, *fmtSigned = NULL, *fmtEncrypted = NULL;
  2093. CERTCertificate *cert = NULL;
  2094. char *certNickname = NULL;
  2095. int err;
  2096. char ** errCerts = NULL;
  2097. int numErrCerts, i;
  2098.     /* get the connection object */
  2099.     target = SSMTextGen_GetTargetObject(cx);
  2100.     PR_ASSERT(target != NULL);
  2101.     res = (SSMSecurityAdvisorContext*)target;
  2102. /* Get the default email certificate */
  2103. rv = PREF_GetStringPref(target->m_connection->m_prefs, "security.default_mail_cert",
  2104.                  &certNickname);
  2105. if (rv != PR_SUCCESS) {
  2106. goto loser;
  2107. }
  2108. /* Deal with the signing part first */
  2109. if (!res->signthis) {
  2110. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_not_to_be_signed", &fmtSigned);
  2111. if (rv != SSM_SUCCESS) {
  2112. goto loser;
  2113. }
  2114. } else {
  2115. /* Do we have a default cert installed */
  2116. if (!certNickname) {
  2117. /* We have no signing cert */
  2118. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_sign_no_cert", &fmtSigned);
  2119. if (rv != SSM_SUCCESS) {
  2120. goto loser;
  2121. }
  2122. } else {
  2123. cert = CERT_FindUserCertByUsage(target->m_connection->m_certdb, 
  2124. certNickname, 
  2125. certUsageEmailSigner,
  2126. PR_FALSE,
  2127. target->m_connection);
  2128. if (!cert){
  2129. /* We have no signing cert */
  2130. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_sign_no_cert", &fmtSigned);
  2131. if (rv != SSM_SUCCESS) {
  2132. goto loser;
  2133. }
  2134. } else {
  2135. /* Verify the cert */
  2136. if (CERT_VerifyCert(target->m_connection->m_certdb,
  2137. cert,
  2138. PR_TRUE, 
  2139. certUsageEmailSigner,
  2140. PR_Now(),
  2141. target->m_connection,
  2142. NULL) == SECSuccess) {
  2143. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_can_be_signed", &fmtSigned);
  2144. if (rv != SSM_SUCCESS) {
  2145. goto loser;
  2146. }
  2147. } else {
  2148. err = PR_GetError();
  2149. switch (err) {
  2150. case SEC_ERROR_EXPIRED_CERTIFICATE:
  2151. {
  2152. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_sign_expired_cert", &fmtSigned);
  2153. if (rv != SSM_SUCCESS) {
  2154. goto loser;
  2155. }
  2156. }
  2157. break;
  2158. case SEC_ERROR_REVOKED_CERTIFICATE:
  2159. {
  2160. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_sign_revoked_cert", &fmtSigned);
  2161. if (rv != SSM_SUCCESS) {
  2162. goto loser;
  2163. }
  2164. }
  2165. break;
  2166. case SEC_ERROR_CERT_USAGES_INVALID:
  2167. {
  2168. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_sign_invalid_cert", &fmtSigned);
  2169. if (rv != SSM_SUCCESS) {
  2170. goto loser;
  2171. }
  2172. }
  2173. break;
  2174. default:
  2175. {
  2176. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_sign_unknown_error", &fmtSigned);
  2177. if (rv != SSM_SUCCESS) {
  2178. goto loser;
  2179. }
  2180. }
  2181. }
  2182. }
  2183. }
  2184. }
  2185. }
  2186. /* Now deal with the encryption part */
  2187. if (!res->encryptthis) {
  2188. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_not_to_be_encrypted", &fmtEncrypted);
  2189. if (rv != SSM_SUCCESS) {
  2190. goto loser;
  2191. }
  2192. } else {
  2193. if (!res->numRecipients) {
  2194. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_no_recipients", &fmtEncrypted);
  2195. if (rv != SSM_SUCCESS) {
  2196. goto loser;
  2197. }
  2198. } else {
  2199. /* Do we have a default cert installed */
  2200. if (!certNickname) {
  2201. /* We have no cert */
  2202. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_no_cert", &fmtEncrypted);
  2203. if (rv != SSM_SUCCESS) {
  2204. goto loser;
  2205. }
  2206. } else {
  2207. cert = CERT_FindUserCertByUsage(target->m_connection->m_certdb,
  2208. certNickname,
  2209. certUsageEmailRecipient,
  2210. PR_FALSE,
  2211. target->m_connection);
  2212. if (!cert) {
  2213. /* We have no cert */
  2214. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_no_cert", &fmtEncrypted);
  2215. if (rv != SSM_SUCCESS) {
  2216. goto loser;
  2217. }
  2218. } else {
  2219. /* Verify the cert */
  2220. if (CERT_VerifyCert(target->m_connection->m_certdb,
  2221. cert,
  2222. PR_TRUE, 
  2223. certUsageEmailRecipient,
  2224. PR_Now(),
  2225. target->m_connection,
  2226. NULL) == SECSuccess) {
  2227. errCerts = (char **) PR_CALLOC(sizeof(char*)*res->numRecipients);
  2228. if (!errCerts) {
  2229. goto loser;
  2230. }
  2231. /* Verify the recipient certs */
  2232. for (i=0,numErrCerts=0; i<res->numRecipients; i++) {
  2233. cert = CERT_FindCertByEmailAddr(target->m_connection->m_certdb, res->recipients[i]);
  2234. if (!cert) {
  2235. errCerts[numErrCerts++] = PL_strdup(res->recipients[i]);
  2236. continue;
  2237. }
  2238. if (CERT_VerifyCertNow(target->m_connection->m_certdb,
  2239.    cert,
  2240.    PR_TRUE,
  2241.    certUsageEmailRecipient,
  2242.    target->m_connection) == SECFailure) {
  2243. errCerts[numErrCerts++] = PL_strdup(res->recipients[i]);
  2244. continue;
  2245. }
  2246. CERT_DestroyCertificate(cert);
  2247. }
  2248. if (!numErrCerts) {
  2249. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_can_be_encrypted", &fmtEncrypted);
  2250. if (rv != SSM_SUCCESS) {
  2251. goto loser;
  2252. }
  2253. } else {
  2254. char *option = NULL;
  2255. char *out = NULL;
  2256. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_bad_recipients", &fmt);
  2257. if (rv != SSM_SUCCESS) {
  2258. goto loser;
  2259. }
  2260. for (i=0; i < numErrCerts; i++) {
  2261. option = PR_smprintf("<option selected>%s</option>n", errCerts[i]);
  2262. SSM_ConcatenateUTF8String(&out, option);
  2263. }
  2264. fmtEncrypted = PR_smprintf(fmt, target->m_id, numErrCerts, out);
  2265. PR_Free(fmt);
  2266. }
  2267. } else {
  2268. err = PR_GetError();
  2269. switch (err) {
  2270. case SEC_ERROR_EXPIRED_CERTIFICATE:
  2271. {
  2272. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_expired_cert", &fmtEncrypted);
  2273. if (rv != SSM_SUCCESS) {
  2274. goto loser;
  2275. }
  2276. }
  2277. break;
  2278. case SEC_ERROR_REVOKED_CERTIFICATE:
  2279. {
  2280. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_revoked_cert", &fmtEncrypted);
  2281. if (rv != SSM_SUCCESS) {
  2282. goto loser;
  2283. }
  2284. }
  2285. break;
  2286. case SEC_ERROR_CERT_USAGES_INVALID:
  2287. {
  2288. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_invalid_cert", &fmtEncrypted);
  2289. if (rv != SSM_SUCCESS) {
  2290. goto loser;
  2291. }
  2292. }
  2293. break;
  2294. default:
  2295. {
  2296. rv = SSM_GetAndExpandTextKeyedByString(cx, "sa_compose_encrypted_unknown_error", &fmtEncrypted);
  2297. if (rv != SSM_SUCCESS) {
  2298. goto loser;
  2299. }
  2300. }
  2301. }
  2302. }
  2303. }
  2304. }
  2305. }
  2306. }
  2307. /* Output the stirngs */
  2308.     PR_FREEIF(cx->m_result);
  2309. cx->m_result = PR_smprintf("%s%s", fmtSigned, fmtEncrypted);
  2310. PR_Free(fmtSigned);
  2311. PR_Free(fmtEncrypted);
  2312. return SSM_SUCCESS;
  2313. loser:
  2314. PR_FREEIF(fmt);
  2315. PR_FREEIF(fmtSigned);
  2316. PR_FREEIF(fmtEncrypted);
  2317. return SSM_FAILURE;
  2318. }
  2319. SSMStatus SSMSecurityAdvisorContext_sa_selected_item(SSMTextGenContext* cx)
  2320. {
  2321.     SSMStatus rv = SSM_SUCCESS;
  2322.     SSMResource *target = NULL;
  2323.     SSMSecurityAdvisorContext* res = NULL;
  2324.     /* get the connection object */
  2325.     target = SSMTextGen_GetTargetObject(cx);
  2326.     PR_ASSERT(target != NULL);
  2327.     res = (SSMSecurityAdvisorContext*)target;
  2328. /* Load the correct page */
  2329. switch (res->infoContext) 
  2330. {
  2331. case SSM_NOINFO:
  2332. rv = sa_noinfo(cx);
  2333. break;
  2334. case SSM_BROWSER:
  2335. rv = sa_navigator(cx);
  2336. break;
  2337. case SSM_SNEWS_MESSAGE:
  2338. case SSM_NEWS_MESSAGE:
  2339. case SSM_MAIL_MESSAGE:
  2340. rv = sa_message(cx);
  2341. break;
  2342. case SSM_COMPOSE:
  2343. rv = sa_compose(cx);
  2344. break;
  2345. default:
  2346. rv = SSM_FAILURE;
  2347. break;
  2348. }
  2349. goto done;
  2350. done:
  2351.     return rv;
  2352. }
  2353. SSMStatus 
  2354. SSMSecurityAdvisorContext_GetPrefListKeywordHandler(SSMTextGenContext* cx)
  2355. {
  2356.     SSMStatus rv = SSM_SUCCESS;
  2357.     SSMSecurityAdvisorContext* adv = NULL;
  2358.     PrefSet* prefs = NULL;
  2359.     char* subboolfmt;
  2360.     char* subfmt;
  2361.     char* fmt;
  2362.     PRBool boolval;
  2363.     char* strval = NULL;
  2364.     char* str1 = NULL;
  2365.     char* str2 = NULL;
  2366.     char* str3 = NULL;
  2367.     char* str4 = NULL;
  2368.     char* str5 = NULL;
  2369.     char* str6 = NULL;
  2370.     char* str7 = NULL;
  2371.     char* str8 = NULL;
  2372.     char* str9 = NULL;
  2373.     char* str10 = NULL;
  2374.     char* str11 = NULL;
  2375.     if ((cx == NULL) || (cx->m_request == NULL) || (cx->m_result == NULL)) {
  2376.         goto loser;
  2377.     }
  2378.     adv = (SSMSecurityAdvisorContext*)SSMTextGen_GetTargetObject(cx);
  2379.     if ((adv == NULL) ||
  2380.         !SSM_IsA((SSMResource*)adv, SSM_RESTYPE_SECADVISOR_CONTEXT)) {
  2381.         goto loser;
  2382.     }
  2383.     /* get the prefs object */
  2384.     if ((adv->super.m_connection == NULL) || 
  2385.         (adv->super.m_connection->m_prefs == NULL)) {
  2386.         goto loser;
  2387.     }
  2388.     prefs = adv->super.m_connection->m_prefs;
  2389.     /* strings and formats */
  2390.     subboolfmt = "var %1$s = %2$s;n";
  2391.     subfmt = "var %1$s = "%2$s";n";
  2392.     /* since nickname may contain ', I really should use " for quotes */
  2393.     fmt = "%1$s%2$s%3$s%4$s%5$s%6$s%7$s%8$s%9$s%10$s%11$s";
  2394.     /* make sure all the right default values are enforced */
  2395.     rv = PREF_GetBoolPref(prefs, "security.enable_ssl2", &boolval);
  2396.     if ((rv == SSM_SUCCESS) && (boolval == PR_FALSE)) {
  2397.         str1 = PR_smprintf(subboolfmt, SSL2_SPK, "false");
  2398.     }
  2399.     else { /* default */
  2400.         str1 = PR_smprintf(subboolfmt, SSL2_SPK, "true");
  2401.     }
  2402.     rv = PREF_GetBoolPref(prefs, "security.enable_ssl3", &boolval);
  2403.     if ((rv == SSM_SUCCESS) && (boolval == PR_FALSE)) {
  2404.         str2 = PR_smprintf(subboolfmt, SSL3_SPK, "false");
  2405.     }
  2406.     else { /* default */
  2407.         str2 = PR_smprintf(subboolfmt, SSL3_SPK, "true");
  2408.     }
  2409.     rv = PREF_GetStringPref(prefs, "security.default_personal_cert", &strval);
  2410.     if ((strval != NULL) && (PL_strcmp(strval, "Select Automatically") == 0)) {
  2411.         str3 = PR_smprintf(subboolfmt, CLIENT_AUTH_SPK, "true");
  2412.     }
  2413.     else { /* default */
  2414.         str3 = PR_smprintf(subboolfmt, CLIENT_AUTH_SPK, "false");
  2415.     }
  2416.     rv = PREF_GetStringPref(prefs, "security.default_mail_cert", &strval);
  2417.     if (strval != NULL) {
  2418.         str4 = PR_smprintf(subfmt, EMAIL_CERT_SPK, strval);
  2419.     }
  2420.     else {
  2421.         str4 = PR_smprintf(subfmt, EMAIL_CERT_SPK, "");
  2422.     }
  2423.     rv = PREF_GetBoolPref(prefs, "security.warn_entering_secure", &boolval);
  2424.     if ((rv == SSM_SUCCESS) && (boolval == PR_FALSE)) {
  2425.         str5 = PR_smprintf(subboolfmt, WARN_ENTER_SECURE_SPK, "false");
  2426.     }
  2427.     else { /* default */
  2428.         str5 = PR_smprintf(subboolfmt, WARN_ENTER_SECURE_SPK, "true");
  2429.     }
  2430.     rv = PREF_GetBoolPref(prefs, "security.warn_leaving_secure", &boolval);
  2431.     if ((rv == SSM_SUCCESS) && (boolval == PR_FALSE)) {
  2432.         str6 = PR_smprintf(subboolfmt, WARN_LEAVE_SECURE_SPK, "false");
  2433.     }
  2434.     else { /* default */
  2435.         str6 = PR_smprintf(subboolfmt, WARN_LEAVE_SECURE_SPK, "true");
  2436.     }
  2437.     rv = PREF_GetBoolPref(prefs, "security.warn_viewing_mixed", &boolval);
  2438.     if ((rv == SSM_SUCCESS) && (boolval == PR_FALSE)) {
  2439.         str7 = PR_smprintf(subboolfmt, WARN_VIEW_MIXED_SPK, "false");
  2440.     }
  2441.     else { /* default */
  2442.         str7 = PR_smprintf(subboolfmt, WARN_VIEW_MIXED_SPK, "true");
  2443.     }
  2444.     rv = PREF_GetBoolPref(prefs, "security.warn_submit_insecure", &boolval);
  2445.     if ((rv == SSM_SUCCESS) && (boolval == PR_FALSE)) {
  2446.         str8 = PR_smprintf(subboolfmt, WARN_SUBMIT_INSECURE_SPK, "false");
  2447.     }
  2448.     else { /* default */
  2449.         str8 = PR_smprintf(subboolfmt, WARN_SUBMIT_INSECURE_SPK, "true");
  2450.     }
  2451.     rv = PREF_GetBoolPref(prefs, "mail.encrypt_outgoing_mail", &boolval);
  2452.     if ((rv == SSM_SUCCESS) && (boolval == PR_TRUE)) {
  2453.         str9 = PR_smprintf(subboolfmt, ENCRYPT_MAIL_SPK, "true");
  2454.     }
  2455.     else { /* default */
  2456.         str9 = PR_smprintf(subboolfmt, ENCRYPT_MAIL_SPK, "false");
  2457.     }
  2458.     rv = PREF_GetBoolPref(prefs, "mail.crypto_sign_outgoing_mail", &boolval);
  2459.     if ((rv == SSM_SUCCESS) && (boolval == PR_TRUE)) {
  2460.         str10 = PR_smprintf(subboolfmt, SIGN_MAIL_SPK, "true");
  2461.     }
  2462.     else { /* default */
  2463.         str10 = PR_smprintf(subboolfmt, SIGN_MAIL_SPK, "false");
  2464.     }
  2465.     rv = PREF_GetBoolPref(prefs, "mail.crypto_sign_outgoing_news", &boolval);
  2466.     if ((rv == SSM_SUCCESS) && (boolval == PR_TRUE)) {
  2467.         str11 = PR_smprintf(subboolfmt, SIGN_NEWS_SPK, "true");
  2468.     }
  2469.     else { /* default */
  2470.         str11 = PR_smprintf(subboolfmt, SIGN_NEWS_SPK, "false");
  2471.     }
  2472.     PR_FREEIF(cx->m_result);
  2473.     cx->m_result = PR_smprintf(fmt, str1, str2, str3, str4, str5, str6, str7,
  2474.                                str8, str9, str10, str11);
  2475.     SSM_DebugUTF8String("security advisor prefs list", cx->m_result);
  2476.     goto done;
  2477. loser:
  2478.     if (rv == SSM_SUCCESS) {
  2479.         rv = SSM_FAILURE;
  2480.     }
  2481. done:
  2482.     PR_FREEIF(str1);
  2483.     PR_FREEIF(str2);
  2484.     PR_FREEIF(str3);
  2485.     PR_FREEIF(str4);
  2486.     PR_FREEIF(str5);
  2487.     PR_FREEIF(str6);
  2488.     PR_FREEIF(str7);
  2489.     PR_FREEIF(str8);
  2490.     PR_FREEIF(str9);
  2491.     PR_FREEIF(str10);
  2492.     PR_FREEIF(str11);
  2493.     return SSM_SUCCESS;
  2494. }
  2495. SSMStatus
  2496. SSM_FreeTarget(SSMTextGenContext *cx)
  2497. {
  2498.     SSMResource *res = NULL;
  2499.     res = SSMTextGen_GetTargetObject(cx);
  2500.     if (res != NULL) {
  2501.         SSM_FreeResource(res);
  2502.     }
  2503.     return SSM_SUCCESS;
  2504. }
  2505. #if 0
  2506. /*---- Functions for handling Java principal certs ----*/
  2507. static SSMStatus ssm_parse_token(char* start, char** dest)
  2508. {
  2509.     char* openQuote = NULL;
  2510.     char* closeQuote = NULL;
  2511.     *dest = NULL;
  2512.     openQuote = strchr(start, '"');
  2513.     if (openQuote == NULL) {
  2514.         return SSM_FAILURE;
  2515.     }
  2516.     closeQuote = strchr(openQuote+1, '"');
  2517.     if (closeQuote == NULL) {
  2518.         return SSM_FAILURE;
  2519.     }
  2520.     *dest = (char*)PR_Calloc(closeQuote-openQuote, sizeof(char));
  2521.     if (*dest == NULL) {
  2522.         return SSM_FAILURE;
  2523.     }
  2524.     /* copy the string */
  2525.     memcpy(*dest, openQuote+1, closeQuote-openQuote-1);
  2526.     
  2527.     return SSM_SUCCESS;
  2528. }
  2529. static SSMStatus ssm_parse_principals(char* principalsData, 
  2530.                                       char*** principals, PRIntn* size)
  2531. {
  2532.     SSMStatus rv;
  2533.     PRIntn i = 1;
  2534.     char* start = NULL;
  2535.     *principals = NULL;
  2536.     /* first check whether the data is empty */
  2537.     if (*principalsData == '') {
  2538.         /* this is not a failure */
  2539.         *size = 0;
  2540.         return SSM_SUCCESS;
  2541.     }
  2542.     /* data looks like ""Netscape", "AOL"": tokenize the string */
  2543.     /* first determine the number of tokens */
  2544.     start = principalsData;
  2545.     while ((start = strchr(start+1, ',')) != NULL) {
  2546.         i++;
  2547.     }
  2548.     *principals = (char**)PR_Calloc(i, sizeof(char*));
  2549.     if (*principals == NULL) {
  2550.         return SSM_FAILURE;
  2551.     }
  2552.     *size = i;
  2553.     /* parse the tokens and store them in principals */
  2554.     for (start = principalsData, i = 0; start != NULL; 
  2555.          start = strchr(start, ','), i++) {
  2556.         rv = ssm_parse_token(start, &((*principals)[i]));
  2557.         if (rv != SSM_SUCCESS) {
  2558.             goto loser;
  2559.         }
  2560.     }
  2561.     return SSM_SUCCESS;
  2562.  loser:
  2563.     for (i = 0; i < *size; i++) {
  2564.         PR_FREEIF((*principals)[i]);
  2565.     }
  2566.     return SSM_FAILURE;
  2567. }
  2568. static SSMStatus ssm_retrieve_principals(SSMSecurityAdvisorContext* adv,
  2569.                                          char*** principals, PRIntn* size)
  2570. {
  2571.     SSMStatus rv;
  2572.     SingleNumMessage request;
  2573.     CMTItem message;
  2574.     /* first, clear data */
  2575.     PR_FREEIF(adv->m_principalsData);
  2576.     /* pack the request */
  2577.     request.value = (PRIntn)adv->super.m_id;
  2578.     if (CMT_EncodeMessage(SingleNumMessageTemplate, &message, &request) !=
  2579.         CMTSuccess) {
  2580.         return SSM_FAILURE;
  2581.     }
  2582.     message.type = SSM_EVENT_MESSAGE | SSM_GET_JAVA_PRINCIPALS_EVENT;
  2583.     /* send the message through the control out queue */
  2584.     SSM_SendQMessage(adv->super.m_connection->m_controlOutQ, 
  2585.                      SSM_PRIORITY_NORMAL, message.type, message.len,
  2586.                      (char*)message.data, PR_TRUE);
  2587.     /* awkward way of blocking, but can't be helped */
  2588.     SSM_LockUIEvent(SSMRESOURCE(adv));
  2589.     while (adv->m_principalsData == NULL) {
  2590.         SSM_WaitUIEvent(SSMRESOURCE(adv), PR_INTERVAL_NO_TIMEOUT);
  2591.     }
  2592.     SSM_UnlockUIEvent(SSMRESOURCE(adv));
  2593.     /* parse the date that came from the plugin */
  2594.     rv = ssm_parse_principals(adv->m_principalsData, principals, size);
  2595.     return rv;
  2596. }
  2597. SSMStatus SSM_JavaPrincipalsKeywordHandler(SSMTextGenContext* cx)
  2598. {
  2599.     SSMStatus rv;
  2600.     SSMSecurityAdvisorContext* adv = NULL;
  2601.     char* prefix = NULL;
  2602.     char* wrapper = NULL;
  2603.     char* suffix = NULL;
  2604.     char* prefixKey = NULL;
  2605.     char* wrapperKey = NULL;
  2606.     char* suffixKey = NULL;
  2607.     char* tmpStr = NULL;
  2608.     char* finalStr = NULL;
  2609.     const PRIntn CERT_PREFIX = 0;
  2610.     const PRIntn CERT_WRAPPER = 1;
  2611.     const PRIntn CERT_SUFFIX = 2;
  2612.     PRIntn i;
  2613. #if 0
  2614.     char* principals[5] = {"Macromedia", "NetCenter", "Sun Microsystems",
  2615.                            "MindSpring", "Hong Kong Telecom"};
  2616. #else
  2617.     char** principals = NULL;
  2618.     PRIntn size;
  2619. #endif
  2620.     if ((cx == NULL) || (cx->m_result == NULL)) {
  2621.         goto loser;
  2622.     }
  2623.     cx->m_result = NULL; /* in case we fail */
  2624.     adv = (SSMSecurityAdvisorContext*)SSMTextGen_GetTargetObject(cx);
  2625.     if ((adv == NULL) ||
  2626.         !SSM_IsA((SSMResource*)adv, SSM_RESTYPE_SECADVISOR_CONTEXT)) {
  2627.         goto loser;
  2628.     }
  2629.     /* retrieve the principals in string form from the plugin */
  2630.     rv = ssm_retrieve_principals(adv, &principals, &size);
  2631.     if (rv != SSM_SUCCESS) {
  2632.         goto loser;
  2633.     }
  2634.     prefixKey = (char*)SSM_At(cx->m_params, CERT_PREFIX);
  2635.     wrapperKey = (char*)SSM_At(cx->m_params, CERT_WRAPPER);
  2636.     suffixKey = (char*)SSM_At(cx->m_params, CERT_SUFFIX);
  2637.     rv = SSM_GetAndExpandTextKeyedByString(cx, prefixKey, &prefix);
  2638.     if (rv != SSM_SUCCESS) {
  2639.         goto loser;
  2640.     }
  2641.     
  2642.     rv = SSM_GetAndExpandTextKeyedByString(cx, suffixKey, &suffix);
  2643.     if (rv != SSM_SUCCESS) {
  2644.         goto loser;
  2645.     }
  2646.     finalStr = PL_strdup(prefix);
  2647.     if (finalStr == NULL) {
  2648.         goto loser;
  2649.     }
  2650.     /* add individual certs */
  2651.     if (principals != NULL) {
  2652.         rv = SSM_GetAndExpandTextKeyedByString(cx, wrapperKey, &wrapper);
  2653.         if (rv != SSM_SUCCESS) {
  2654.             goto loser;
  2655.         }
  2656.         for (i = 0; i < size; i++) {
  2657.             tmpStr = PR_smprintf(wrapper, principals[i]);
  2658.             if (SSM_ConcatenateUTF8String(&finalStr, tmpStr) != SSM_SUCCESS) {
  2659.                 goto loser;
  2660.             }
  2661.             PR_Free(tmpStr);
  2662.             tmpStr = NULL;
  2663.         }
  2664.     }
  2665.     rv = SSM_ConcatenateUTF8String(&finalStr, suffix);
  2666.     if (rv != SSM_SUCCESS) {
  2667.         goto loser;
  2668.     }
  2669.     cx->m_result = finalStr;
  2670.     goto done;
  2671. loser:
  2672.     if (rv == SSM_SUCCESS) {
  2673.         rv = SSM_FAILURE;
  2674.     }
  2675.     PR_FREEIF(finalStr);
  2676.     PR_FREEIF(tmpStr);
  2677. done:
  2678.     PR_FREEIF(prefix);
  2679.     PR_FREEIF(wrapper);
  2680.     PR_FREEIF(suffix);
  2681.     return rv;
  2682. }
  2683. void SSM_HandleGetJavaPrincipalsReply(SSMControlConnection* ctrl,
  2684.                                       SECItem* message)
  2685. {
  2686.     SSMStatus rv;
  2687.     GetJavaPrincipalsReply reply;
  2688.     SSMResource* res = NULL;
  2689.     SSMSecurityAdvisorContext* adv = NULL;
  2690.     if (CMT_DecodeMessage(GetJavaPrincipalsReplyTemplate, &reply, 
  2691.                           (CMTItem*)message) != CMTSuccess) {
  2692.         goto loser;
  2693.     }
  2694.     rv = SSMControlConnection_GetResource(ctrl, reply.resID, &res);
  2695.     if (rv != PR_SUCCESS || res == NULL) {
  2696.         goto loser;
  2697.     }
  2698.     /* make sure it is a Security Advisor context */
  2699.     if (!SSM_IsA(res, SSM_RESTYPE_SECADVISOR_CONTEXT)) {
  2700.         goto loser;
  2701.     }
  2702.     adv = (SSMSecurityAdvisorContext*)res;
  2703.     SSM_LockUIEvent(res);
  2704.     adv->m_principalsData = reply.principals;
  2705.     /* it will be freed by the Security Advisor */
  2706.     if (adv->m_principalsData == NULL) {
  2707.         adv->m_principalsData = PL_strdup("");
  2708.     }
  2709.     SSM_NotifyUIEvent(res);
  2710.     SSM_UnlockUIEvent(res);
  2711.     return;
  2712. loser:
  2713.     /* XXX we can't really wake up the waiting Security Advisor object 
  2714.      *     because we don't know which resource to wake up.  Bad.
  2715.      */
  2716.     PR_FREEIF(reply.principals);
  2717.     return;
  2718. }
  2719. #endif
  2720. /* platform-dependent names for signed.db */
  2721. #ifdef XP_UNIX
  2722. #define SIGNED "/signedapplet.db"
  2723. #else
  2724. #ifdef XP_MAC
  2725. #define SIGNED ":SignedAppletDB"
  2726. #else
  2727. #define SIGNED "\signed.db"
  2728. #endif
  2729. #endif
  2730. SSMStatus SSM_RemovePrivilegesHandler(HTTPRequest* req)
  2731. {
  2732.     SSMResource* res = NULL;
  2733.     char* buttonValue;
  2734.     SSMStatus rv;
  2735.     res = (req->target) ? req->target : (SSMResource*)req->ctrlconn;
  2736.     rv = SSM_HTTPParamValue(req, "OK", &buttonValue);
  2737.     if (rv == SSM_SUCCESS) {
  2738.         /* do action */
  2739.         char* signeddb;
  2740.         signeddb = PR_smprintf("%s%s", req->ctrlconn->m_dirRoot, SIGNED);
  2741.         /* XXX we delete the signed.db file here, but we do not actively
  2742.          *     check the return value.  There may be failures (file does
  2743.          *     not exist, file may be already open, etc.) but we do not
  2744.          *     have other recourses.  Sigh.
  2745.          */
  2746.         PR_Delete(signeddb);
  2747.         PR_Free(signeddb);
  2748.     }
  2749.     else {
  2750.         rv = SSM_HTTPParamValue(req, "Cancel", &buttonValue);
  2751.     }
  2752.     if (rv != SSM_SUCCESS) {
  2753.         rv = SSM_ERR_NO_BUTTON;
  2754.         goto done;
  2755.     }
  2756.  done:
  2757.     rv = SSM_HTTPDefaultCommandHandler(req);
  2758.     return rv;
  2759. }
  2760. static PRBool 
  2761. ocsplist_is_default_signer(CERTCertificate *cert,
  2762.                            SSMDefaultOCSPRespondersList *potResponders)
  2763. {
  2764.     if (!cert->nickname) {
  2765.         return PR_FALSE;
  2766.     }
  2767.     return (PL_strcmp(cert->nickname, potResponders->defaultSigner) == 0) ? 
  2768.             PR_TRUE : PR_FALSE;
  2769. }
  2770. static PRBool ocsplist_include_cert(CERTCertificate *cert)
  2771. {
  2772.     CERTCertTrust *trust;
  2773.     char *nickname;
  2774.     trust = cert->trust;
  2775.     nickname = cert->nickname;
  2776.     
  2777.     if ( ( ( trust->sslFlags & CERTDB_INVISIBLE_CA ) ||
  2778.            (trust->emailFlags & CERTDB_INVISIBLE_CA ) ||
  2779.            (trust->objectSigningFlags & CERTDB_INVISIBLE_CA ) ) ||
  2780.          nickname == NULL) {
  2781.         return PR_FALSE;
  2782.     }
  2783.     if ((trust->sslFlags & CERTDB_VALID_CA) ||
  2784.         (trust->emailFlags & CERTDB_VALID_CA) ||
  2785.         (trust->objectSigningFlags & CERTDB_VALID_CA)) {
  2786.         return PR_TRUE;
  2787.     }
  2788.     return PR_FALSE;
  2789. }
  2790. static SECStatus ssm_get_potential_ocsp_signers(CERTCertificate *cert,
  2791.                                                 SECItem         *dbKey,
  2792.                                                 void            *arg)
  2793. {
  2794.     SSMDefaultOCSPRespondersList *potResponders;
  2795.     char *serviceURL, *nickname;
  2796.     potResponders = (SSMDefaultOCSPRespondersList*)arg;
  2797.     if (!ocsplist_include_cert(cert) ||
  2798.         ocsplist_is_default_signer(cert, potResponders)) {
  2799.         goto done;
  2800.     }
  2801.     /*
  2802.      * We've got a CA cert, now we need to figure out if it has the AIA
  2803.      * extension that points to a responder somewhere. Get our own copy
  2804.      * of the nickname.
  2805.      */
  2806.     nickname = PL_strdup(cert->nickname);
  2807.     serviceURL = CERT_GetOCSPAuthorityInfoAccessLocation(cert);
  2808.     if (serviceURL != NULL) {
  2809.         /*
  2810.          * This CA has an AIA extension so we'll bundle it with the group
  2811.          * certs that have the 
  2812.          */
  2813.         SSMSortedList_Insert(potResponders->respondersWithAIA,
  2814.                              nickname, serviceURL);
  2815.     } else {
  2816.         /*
  2817.          * This CA doesn't have an AIA extension so we lump with the
  2818.          * rest of the CA's.
  2819.          */
  2820.         SSMSortedList_Insert(potResponders->respondersWithoutAIA,
  2821.                              nickname, NULL);
  2822.     }
  2823.     
  2824.  done:
  2825.     return SECSuccess;
  2826. }
  2827. static void
  2828. ocsplist_freedata(void *data)
  2829. {
  2830.     if (data) {
  2831.         PR_Free(data);
  2832.     }
  2833. }
  2834. static void
  2835. ocsplist_freekey(void *data)
  2836. {
  2837.     ocsplist_freedata(data);
  2838. }
  2839. static SSMStatus 
  2840. ocsplist_aiacerts_enumerator(PRIntn index, void * arg, void *key,
  2841.                              void *data)
  2842. {
  2843.     SSMDefaultOCSPRespondersList *potResps;
  2844.     char *nextChunk;
  2845.     SSMStatus rv;
  2846.     potResps = (SSMDefaultOCSPRespondersList*)arg;
  2847.     nextChunk = PR_smprintf(potResps->wrapper, (char*)key, 
  2848.                             (data == NULL) ? "http://" : (char*)data);
  2849.     rv = SSM_ConcatenateUTF8String(&potResps->cx->m_result, nextChunk);
  2850.     PR_Free(nextChunk);
  2851.     return rv;
  2852. }
  2853. static SSMStatus 
  2854. ocsplist_cacerts_enumerator(PRIntn index, void * arg, void *key,
  2855.                             void *data)
  2856. {
  2857.     return ocsplist_aiacerts_enumerator(index, arg, key, data);
  2858. }
  2859. SSMStatus 
  2860. SSM_OCSPResponderList(SSMTextGenContext *cx)
  2861. {
  2862.     SECStatus srv;
  2863.     SSMDefaultOCSPRespondersList potentialResponders = {NULL, NULL, 
  2864.                                                         NULL, NULL, NULL};
  2865.     SSMSortedListFn funcs;
  2866.     char *prefix, *suffix, *tmpStr, *prefService, *prefSigner;
  2867.     SSMStatus rv;
  2868.     PR_ASSERT(cx != NULL);
  2869.     funcs.keyCompare       = certlist_compare_strings;
  2870.     funcs.freeListItemData = ocsplist_freedata;
  2871.     funcs.freeListItemKey  = ocsplist_freekey;
  2872.     potentialResponders.respondersWithAIA    = SSMSortedList_New(&funcs);
  2873.     potentialResponders.respondersWithoutAIA = SSMSortedList_New(&funcs);
  2874.     PREF_GetStringPref(cx->m_request->ctrlconn->m_prefs,
  2875.                        "security.OCSP.signingCA", 
  2876.                        &potentialResponders.defaultSigner);
  2877.     srv = SEC_TraversePermCerts(cx->m_request->ctrlconn->m_certdb,
  2878.                                 ssm_get_potential_ocsp_signers,
  2879.                                 &potentialResponders);
  2880.     if (srv == SECSuccess) {
  2881.         srv = PK11_TraverseSlotCerts(ssm_get_potential_ocsp_signers,
  2882.                                      &potentialResponders, 
  2883.                                      cx->m_request->ctrlconn);
  2884.     }
  2885.     if (srv != SECSuccess) {
  2886.         goto loser;
  2887.     }
  2888.     prefix = (char*)SSM_At(cx->m_params, 0);
  2889.     suffix = (char*)SSM_At(cx->m_params, 1);
  2890.     PR_ASSERT(prefix);
  2891.     PR_ASSERT(suffix);
  2892.     if (prefix == NULL || suffix == NULL) {
  2893.         goto loser;
  2894.     }
  2895.     rv = SSM_GetAndExpandTextKeyedByString(cx, prefix, &tmpStr);
  2896.     if (rv != SSM_SUCCESS) {
  2897.         goto loser;
  2898.     }
  2899.     rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
  2900.     PR_Free(tmpStr);
  2901.     if (rv != SSM_SUCCESS) {
  2902.         goto loser;
  2903.     }
  2904.     rv = SSM_GetAndExpandTextKeyedByString(cx, "ocsp_list_wrapper",
  2905.                                            &potentialResponders.wrapper);
  2906.     if (rv != SSM_SUCCESS) {
  2907.         goto loser;
  2908.     }
  2909.     potentialResponders.cx = cx;
  2910.     /*
  2911.      * Now it's time to build the list of potential OCSP Responders.
  2912.      */
  2913.     SSMSortedList_Enumerate(potentialResponders.respondersWithAIA, 
  2914.                             ocsplist_aiacerts_enumerator, 
  2915.                             &potentialResponders);
  2916.     SSMSortedList_Enumerate(potentialResponders.respondersWithoutAIA,
  2917.                             ocsplist_cacerts_enumerator,
  2918.                             &potentialResponders);
  2919.     /*
  2920.      * If there was a default responder enabled, let's over-ride whatever
  2921.      * the cert said with what the user entered as the appropriate value.
  2922.      */
  2923.     if (PREF_GetStringPref(cx->m_request->ctrlconn->m_prefs,
  2924.                            "security.OCSP.URL", &prefService) == SSM_SUCCESS) {
  2925.         if (PREF_GetStringPref(cx->m_request->ctrlconn->m_prefs,
  2926.                       "security.OCSP.signingCA", &prefSigner) == SSM_SUCCESS) {
  2927.             tmpStr = PR_smprintf("addNewServiceURL("%1$s","%2$s");n",
  2928.                                  prefSigner, prefService);
  2929.             rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
  2930.             if (rv != SSM_SUCCESS) {
  2931.                 goto loser;
  2932.             }
  2933.             PR_Free(tmpStr);
  2934.         }
  2935.     }
  2936.     rv = SSM_GetAndExpandTextKeyedByString(cx, suffix, &tmpStr);
  2937.     if (rv != SSM_SUCCESS) {
  2938.         goto loser;
  2939.     }
  2940.     rv = SSM_ConcatenateUTF8String(&cx->m_result, tmpStr);
  2941.     PR_Free(tmpStr);
  2942.     if (rv != SSM_SUCCESS) {
  2943.         goto loser;
  2944.     }
  2945.     PR_Free(potentialResponders.wrapper);
  2946.     SSMSortedList_Destroy(potentialResponders.respondersWithAIA);
  2947.     SSMSortedList_Destroy(potentialResponders.respondersWithoutAIA);
  2948.     return SSM_SUCCESS;
  2949.  loser:
  2950.     PR_FREEIF(potentialResponders.wrapper);
  2951.     if (potentialResponders.respondersWithAIA) {
  2952.         SSMSortedList_Destroy(potentialResponders.respondersWithAIA);
  2953.     }
  2954.     if (potentialResponders.respondersWithoutAIA) {
  2955.         SSMSortedList_Destroy(potentialResponders.respondersWithoutAIA);
  2956.     }
  2957.     return SSM_FAILURE;
  2958. }
  2959. SSMStatus
  2960. SSM_DisplayCRLButton(SSMTextGenContext *cx)
  2961. {
  2962.     SSMControlConnection *ctrl;
  2963.     char *crlHTML = NULL;
  2964.     SSMStatus rv;
  2965.     ctrl = SSMTextGen_GetControlConnection(cx);
  2966.     if (ctrl == NULL) {
  2967.         goto loser;
  2968.     }
  2969.     if (SSM_IsCRLPresent(ctrl)) {
  2970.         rv = SSM_GetAndExpandTextKeyedByString(cx, "crlButtonHTML", &crlHTML);
  2971.         if (rv == SSM_SUCCESS) {
  2972.             PR_FREEIF(cx->m_result);
  2973.             cx->m_result = crlHTML;
  2974.         }
  2975.     }
  2976.     return SSM_SUCCESS;
  2977.  loser:
  2978.     return SSM_FAILURE;
  2979. }
  2980. SSMStatus
  2981. SSM_ListCRLs(SSMTextGenContext *cx)
  2982. {
  2983.     SECStatus srv;
  2984.     CERTCrlHeadNode *head = NULL;
  2985.     CERTCrlNode *node;
  2986.     SSMControlConnection *ctrl;
  2987.     char *retString = NULL;
  2988.     char *currString ;
  2989.     char *emptyString = "";
  2990.     char *currCRLName = NULL;
  2991.     char *name = NULL;
  2992.     char *b64Name = NULL, *b64HTMLName;
  2993.     
  2994.     ctrl = SSMTextGen_GetControlConnection(cx);
  2995.     srv = SEC_LookupCrls(ctrl->m_certdb, &head, -1);
  2996.     if (srv != SECSuccess || head == NULL) {
  2997.         goto loser;
  2998.     }
  2999.     currString = emptyString;
  3000.     for (node=head->first; node != NULL; node = node->next) {
  3001.         name = CERT_GetCommonName(&(node->crl->crl.name));
  3002.         b64Name = BTOA_ConvertItemToAscii(&node->crl->crl.derName);
  3003.         b64HTMLName = ssm_packb64_name(b64Name);
  3004.         retString = PR_smprintf("%1$sn<option value="%4$d%2$s">%3$s", 
  3005.                                 currString, b64HTMLName, name, node->type);
  3006.         PR_Free(name);
  3007.         PR_Free(b64Name);
  3008.         PR_Free(b64HTMLName);
  3009.         if (currString != emptyString)
  3010.             PR_Free(currString);
  3011.         currString = retString;
  3012.     }
  3013.     PR_FREEIF(cx->m_result);
  3014.     cx->m_result = retString;
  3015.     return SSM_SUCCESS;
  3016.  loser:
  3017.     return SSM_FAILURE;
  3018. }
  3019. SSMStatus
  3020. ssm_getStringForAbleAgent(SSMTextGenContext *cx, const char *agents[])
  3021. {
  3022.     int i;
  3023.     SSMStatus rv;
  3024.     char *key;
  3025.     
  3026.     key = SSM_At(cx->m_params, 0);
  3027.     for (i=0; agents[i] != NULL; i++) {
  3028.         if (PL_strstr(cx->m_request->agent, agents[i]) != NULL) {
  3029.             PR_FREEIF(cx->m_result);
  3030.             rv = SSM_GetAndExpandText(cx, key, &cx->m_result);
  3031.             if (rv != SSM_SUCCESS) {
  3032.                 return rv;
  3033.             }
  3034.             break;
  3035.         }
  3036.     }
  3037.     return SSM_SUCCESS;
  3038. }
  3039. SSMStatus SSM_LayoutSMIMETab(SSMTextGenContext *cx)
  3040. {
  3041.     return ssm_getStringForAbleAgent(cx, kSMimeApps);
  3042. }
  3043. SSMStatus SSM_LayoutJavaJSTab(SSMTextGenContext *cx)
  3044. {
  3045.     return ssm_getStringForAbleAgent(cx, kJavaJSApps);
  3046. }
  3047. SSMStatus SSM_LayoutOthersTab(SSMTextGenContext *cx)
  3048. {
  3049.     return ssm_getStringForAbleAgent(cx, kSMimeApps);
  3050. }