ssldlgs.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:41k
- /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
- #include "sslconn.h"
- #include "ssldlgs.h"
- #include "ctrlconn.h"
- #include "textgen.h"
- #include "resource.h"
- #include "certres.h"
- #include "minihttp.h"
- #include "cert.h"
- #include "certt.h"
- #include "certdb.h"
- #include "sechash.h"
- #include "nlsutil.h"
- #include "nlslayer.h"
- #define SSMRESOURCE(sslconn) (&(sslconn)->super.super.super)
- #define SSMCONTROLCONNECTION(sslconn) ((SSMControlConnection*)(sslconn->super.super.m_parent))
- /* private functions */
- SSMStatus ssm_client_auth_get_utf8_cert_list(SSMSSLDataConnection* conn,
- char* fmt,
- char** result);
- SSMStatus ssm_http_client_auth_handle_ok_button(HTTPRequest* req);
- SSMStatus ssm_http_client_auth_handle_cancel_button(HTTPRequest* req);
- SECStatus SSM_SSLServerCertResetTrust(CERTCertificate* cert,
- SSMBadServerCertAccept accept);
- static char* ssm_default_server_nickname(CERTCertificate* cert);
- SSMStatus ssm_http_server_auth_handle_ok_button(HTTPRequest* req);
- SSMStatus ssm_http_server_auth_handle_cancel_button(HTTPRequest* req);
- SSMStatus ssm_http_unknown_issuer_step1_handle_next_button(HTTPRequest* req);
- SSMStatus SSM_FormatCert(CERTCertificate* cert, char* fmt,
- char** result)
- {
- char* hostname = NULL;
- char* orgname = NULL;
- char* issuer = NULL;
- char * notBefore = NULL, * notAfter = NULL;
- SSMStatus rv = SSM_SUCCESS;
-
- /* check arguments */
- if (cert == NULL || fmt == NULL || result == NULL) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
-
- /* retrieve cert information */
- hostname = CERT_GetCommonName(&cert->subject);
- if (hostname == NULL) {
- goto loser;
- }
- orgname = CERT_GetOrgName(&cert->subject);
- if (orgname == NULL) {
- goto loser;
- }
- issuer = CERT_GetOrgName(&cert->issuer);
- if (issuer == NULL)
- {
- goto loser;
- }
- /* ### sjlee: should issuer be a localizable string? */
- notBefore = DER_UTCDayToAscii(&cert->validity.notBefore);
- if (!notBefore)
- notBefore = PL_strdup("No date found");
- notAfter = DER_UTCDayToAscii(&cert->validity.notAfter);
- if (!notAfter)
- notAfter = PL_strdup("No date found");
-
- *result = PR_smprintf(fmt, hostname, notBefore, notAfter, issuer, orgname);
- SSM_DebugUTF8String("wrapped cert", *result);
- goto done;
- loser:
- SSM_DEBUG("Formatting cert failed.n");
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- if (hostname != NULL) {
- PR_Free(hostname);
- }
- if (orgname != NULL) {
- PR_Free(orgname);
- }
- if (issuer != NULL) {
- PR_Free(issuer);
- }
-
- PR_FREEIF(notBefore);
- PR_FREEIF(notAfter);
- return rv;
- }
- SSMStatus SSM_ServerCertKeywordHandler(SSMTextGenContext* cx)
- {
- SSMResource* target = NULL;
- SSMSSLDataConnection* sslconn = NULL;
- SSMStatus rv;
- char* pattern = NULL;
- char* key = NULL;
- char* formatKey = NULL;
- char* simpleStr = NULL;
- char* prettyStr = NULL;
- CERTCertificate* serverCert = NULL;
- const PRIntn CERT_FORMAT = (PRIntn)0;
- const PRIntn CERT_WRAPPER = (PRIntn)1;
- const PRIntn CERT_WRAPPER_NO_COMMENT = (PRIntn)2;
- PRIntn wrapper;
- /* check arguments */
- /* ### sjlee: might as well make this a helper function because most
- * keyword handlers will use this checking
- */
- PR_ASSERT(cx != NULL);
- PR_ASSERT(cx->m_request != NULL);
- PR_ASSERT(cx->m_params != NULL);
- PR_ASSERT(cx->m_result != NULL);
- if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
- cx->m_result == NULL) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
-
- simpleStr = "simple";
- prettyStr = "pretty";
- /* retrieve the server cert */
- target = SSMTextGen_GetTargetObject(cx);
- PR_ASSERT(SSM_IsA(target, SSM_RESTYPE_SSL_DATA_CONNECTION));
- sslconn = (SSMSSLDataConnection*)target;
- serverCert = SSL_PeerCertificate(sslconn->socketSSL);
- if (serverCert == NULL) {
- /* couldn't get the server cert: what do I do? */
- goto loser;
- }
- /* form the Format object */
- /* first, find the keys */
- formatKey = (char *) SSM_At(cx->m_params, CERT_FORMAT);
- /* only show comments field if there are comments */
- if (CERT_GetCertCommentString(serverCert))
- wrapper = CERT_WRAPPER;
- else
- wrapper = CERT_WRAPPER_NO_COMMENT;
- key = (char *) SSM_At(cx->m_params, wrapper);
-
- /* second, grab and expand the keyword objects */
- rv = SSM_GetAndExpandTextKeyedByString(cx, key, &pattern);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("server cert info pattern", pattern);
- /* Now let's figure out if we're doing pretty print or simple print. */
- PR_FREEIF(cx->m_result);
- if (formatKey[0] == 's') {
- rv = SSM_FormatCert(serverCert, pattern, &cx->m_result);
- } else if (formatKey[0] == 'p') {
- rv = SSM_PrettyFormatCert(serverCert, pattern,
- &cx->m_result, PR_FALSE);
- } else {
- SSM_DEBUG("cannot understand the format key.n");
- rv = SSM_FAILURE;
- }
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- goto done;
- loser:
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- if (serverCert != NULL) {
- CERT_DestroyCertificate(serverCert);
- }
- PR_FREEIF(pattern);
- return rv;
- }
- SSMStatus SSM_HTTPBadClientAuthButtonHandler(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- char* tmpStr = NULL;
- PR_ASSERT(req->target != NULL);
- conn = (SSMSSLDataConnection*)(req->target);
- /* make sure you got the right baseRef */
- rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
- if (rv != SSM_SUCCESS ||
- PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
- goto loser;
- }
- return ssm_http_client_auth_handle_cancel_button(req);
- loser:
- /* set the predicate to true and unblock the SSL thread */
- SSM_LockResource(req->target);
- conn->m_UIInfo.UICompleted = PR_TRUE;
- conn->m_UIInfo.chosen = -1;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- return rv;
- }
- SSMStatus SSM_SSLMakeClientAuthDialog(SSMSSLDataConnection* conn)
- {
- SSMStatus rv;
- /* enter the SSL monitor */
- SSM_LockResource(SSMRESOURCE(conn));
- conn->m_UIInfo.UICompleted = PR_FALSE;
- /* fire up the UI */
- rv = SSMControlConnection_SendUIEvent(SSMCONTROLCONNECTION(conn), "get",
- "client_auth", SSMRESOURCE(conn),
- NULL, &SSMRESOURCE(conn)->m_clientContext, PR_TRUE);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- while (!conn->m_UIInfo.UICompleted) {
- SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT);
- }
- if (conn->m_UIInfo.chosen < 0) {
- /* "cancel" button clicked: bring up the no cert dialog? */
- if (rv == SSM_SUCCESS) {
- rv = SSM_ERR_USER_CANCEL;
- }
- }
- /* the user selected a nickname; let's exit in orderly fashion */
- loser:
- /* reset this bit to facilitate future UI events */
- conn->m_UIInfo.UICompleted = PR_FALSE;
- SSM_UnlockResource(SSMRESOURCE(conn));
- return rv;
- }
- SSMStatus SSM_ClientAuthCertListKeywordHandler(SSMTextGenContext* cx)
- {
- SSMStatus rv = SSM_SUCCESS;
- SSMResource* target = NULL;
- SSMSSLDataConnection* conn;
- char* prefix = NULL;
- char* wrapper = NULL;
- char* suffix = NULL;
- char* tmpStr = NULL;
- char* prefixExp = NULL;
- char* fmt = NULL;
- char* certList = NULL;
- const PRIntn CERT_LIST_PREFIX = (PRIntn)0;
- const PRIntn CERT_LIST_WRAPPER = (PRIntn)1;
- const PRIntn CERT_LIST_SUFFIX = (PRIntn)2;
- const PRIntn CERT_LIST_PARAM_COUNT = (PRIntn)3;
- /*
- * make sure cx, cx->m_request, cx->m_params, cx->m_result are not
- * NULL
- */
- PR_ASSERT(cx != NULL && cx->m_request != NULL && cx->m_params != NULL &&
- cx->m_result != NULL);
- if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
- cx->m_result == NULL) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
- if (SSM_Count(cx->m_params) != CERT_LIST_PARAM_COUNT) {
- SSM_HTTPReportSpecificError(cx->m_request, "_client_auth_certList: ",
- "Incorrect number of parameters "
- " (%d supplied, %d needed).n",
- SSM_Count(cx->m_params),
- CERT_LIST_PARAM_COUNT);
- goto loser;
- }
- /* get the connection object */
- target = SSMTextGen_GetTargetObject(cx);
- PR_ASSERT(target != NULL);
- conn = (SSMSSLDataConnection*)target;
- /* form the MessageFormat object */
- /* find arguments (prefix, wrapper, and suffix) */
- prefix = (char *) SSM_At(cx->m_params, CERT_LIST_PREFIX);
- wrapper = (char *) SSM_At(cx->m_params, CERT_LIST_WRAPPER);
- suffix = (char *) SSM_At(cx->m_params, CERT_LIST_SUFFIX);
- PR_ASSERT(prefix != NULL && wrapper != NULL && suffix != NULL);
- /* grab the prefix and expand it */
- rv = SSM_GetAndExpandTextKeyedByString(cx, prefix, &prefixExp);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("client cert list prefix", prefixExp);
- /* grab the wrapper */
- rv = SSM_GetAndExpandTextKeyedByString(cx, wrapper, &fmt);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("client cert list wrapper", fmt);
- /* form the wrapped cert list UnicodeString */
- rv = ssm_client_auth_get_utf8_cert_list(conn, fmt, &certList);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- /* grab the suffix and expand it */
- rv = SSM_GetAndExpandTextKeyedByString(cx, suffix, &tmpStr);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("client cert list suffix", tmpStr);
- cx->m_result = PR_smprintf("%s%s%s", prefixExp, certList, tmpStr);
- goto done;
- loser:
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- PR_FREEIF(tmpStr);
- PR_FREEIF(prefixExp);
- PR_FREEIF(fmt);
- PR_FREEIF(certList);
- return rv;
- }
- /*
- * Function: SSMStatus ssm_client_auth_get_utf8_cert_list()
- * Purpose: forms the cert list UnicodeString
- *
- * Arguments and return values:
- * - conn: SSL connection object
- * - fmt: cert wrapper UnicodeString format
- * - result: resulting UnicodeString
- *
- * Note: if we include the expired certs, we need to append to the end as
- * well
- */
- SSMStatus ssm_client_auth_get_utf8_cert_list(SSMSSLDataConnection* conn,
- char* fmt,
- char** result)
- {
- SSMStatus rv = SSM_SUCCESS;
- char* tmpStr = NULL;
- char* finalStr = NULL;
- int i;
- PR_ASSERT(conn != NULL && fmt != NULL && result != NULL);
- /* in case we fail */
- *result = NULL;
- finalStr = PL_strdup("");
- /* concatenate the string using the nicknames */
- for (i = 0; i < conn->m_UIInfo.numFilteredCerts; i++) {
- tmpStr = PR_smprintf(fmt, i, conn->m_UIInfo.certNicknames[i]);
- if (SSM_ConcatenateUTF8String(&finalStr, tmpStr) != SSM_SUCCESS) {
- goto loser;
- }
- PR_Free(tmpStr);
- tmpStr = NULL;
- }
-
- SSM_DebugUTF8String("client auth: final cert list", finalStr);
- *result = finalStr;
- return SSM_SUCCESS;
- loser:
- SSM_DEBUG("client auth: wrapping cert list failed.n");
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- PR_FREEIF(finalStr);
- PR_FREEIF(tmpStr);
- return rv;
- }
- SSMStatus SSM_ClientAuthCertSelectionButtonHandler(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMResource* res;
- SSMSSLDataConnection* conn;
- res = (SSMResource*)(req->target);
- conn = (SSMSSLDataConnection*)(req->target);
- if (res->m_buttonType == SSM_BUTTON_OK) {
- /* "OK" button was clicked */
- rv = ssm_http_client_auth_handle_ok_button(req);
- goto done;
- }
- else if (res->m_buttonType == SSM_BUTTON_CANCEL) {
- /* "Cancel" button was clicked */
- rv = ssm_http_client_auth_handle_cancel_button(req);
- goto done;
- }
- else {
- SSM_DEBUG("Don't know which button was clicked.n");
- rv = SSM_FAILURE;
- }
- SSM_LockResource(res);
- conn->m_UIInfo.chosen = -1;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(res);
- SSM_UnlockResource(res);
- done:
- /* this actually includes the error cases returned from individual
- * button handlers
- */
- return rv;
- }
-
-
- SSMStatus SSM_HTTPClientAuthButtonHandler(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- char* tmpStr = NULL;
- PR_ASSERT(req->target != NULL);
- conn = (SSMSSLDataConnection*)(req->target);
- /* make sure you got the right baseRef */
- rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
- if (rv != SSM_SUCCESS ||
- PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
- goto loser;
- }
- /* ### sjlee: this is a very ugly way to differentiate among different
- * buttons
- */
- rv = SSM_HTTPParamValue(req, "do_ok", &tmpStr);
- if (rv == SSM_SUCCESS) {
- /* "OK" button was clicked */
- rv = ssm_http_client_auth_handle_ok_button(req);
- goto done;
- }
- rv = SSM_HTTPParamValue(req, "do_cancel", &tmpStr);
- if (rv == SSM_SUCCESS) {
- /* "Cancel" button was clicked */
- rv = ssm_http_client_auth_handle_cancel_button(req);
- goto done;
- }
- rv = SSM_HTTPParamValue(req, "do_help", &tmpStr);
- if (rv == SSM_SUCCESS) {
- /* "help" button was clicked */
- /* just use cancel handler for now */
- rv = ssm_http_client_auth_handle_cancel_button(req);
- goto done;
- }
- loser:
- if (rv == SSM_SUCCESS) {
- SSM_DEBUG("Don't know which button was clicked.n");
- rv = SSM_FAILURE;
- }
- SSM_LockResource(req->target);
- conn->m_UIInfo.chosen = -1;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- done:
- /* this actually includes the error cases returned from individual
- * button handlers
- */
- return rv;
- }
- SSMStatus ssm_http_client_auth_handle_ok_button(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- char* chosen = NULL;
- int i;
- conn = (SSMSSLDataConnection*)(req->target);
- SSM_LockResource(req->target);
- /* retrieve the chosen nickname */
- rv = SSM_HTTPParamValue(req, "chosen", &chosen);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- PR_ASSERT(chosen != NULL);
- PR_sscanf(chosen, "%ld", &i);
- PR_ASSERT(i >= 0 && i < conn->m_UIInfo.numFilteredCerts);
- rv = SSM_HTTPCloseAndSleep(req);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- /* set the predicate to true and unblock the SSL thread */
- conn->m_UIInfo.chosen = i;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- return rv; /* SSM_SUCCESS */
- loser:
- /* still we want to unblock the SSL thread: it will see NULL nickname */
- conn->m_UIInfo.chosen = -1;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- return rv;
- }
- SSMStatus ssm_http_client_auth_handle_cancel_button(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- conn = (SSMSSLDataConnection*)(req->target);
- SSM_LockResource(req->target);
- /* close the window */
- rv = SSM_HTTPCloseAndSleep(req);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- loser:
- /* set the predicate to true and unblock the SSL thread */
- conn->m_UIInfo.chosen = -1;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- return rv;
- }
- /*
- * Function: SECStatus SSM_SSLMakeCertExpiredDialog()
- * Purpose: dispatch the UI event to create the server cert expired
- * dialog
- * Arguments and return values
- * - cert: server cert we are dealing with
- * - conn: SSL connection object
- * - returns: SECSuccess if successful *and* the user decides to trust
- * the cert; appropriate error code otherwise
- */
- SECStatus SSM_SSLMakeCertExpiredDialog(CERTCertificate* cert,
- SSMSSLDataConnection* conn)
- {
- SECStatus rv;
- int64 now;
- int64 notBefore;
- int64 notAfter;
- char* baseRef = NULL;
- /* compare the time and determine which dialog box to bring up */
- now = PR_Now();
- rv = CERT_GetCertTimes(cert, ¬Before, ¬After);
- if (rv != SECSuccess) {
- return rv;
- }
- if (LL_CMP(now, >, notAfter)) {
- baseRef = PL_strdup("bad_server_cert_expired");
- }
- else {
- baseRef = PL_strdup("bad_server_cert_not_yet_valid");
- }
- if (baseRef == NULL) {
- return SECFailure;
- }
- SSM_LockResource(SSMRESOURCE(conn));
- conn->m_UIInfo.UICompleted = PR_FALSE;
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- /* fire up the UI */
- if (SSMControlConnection_SendUIEvent(SSMCONTROLCONNECTION(conn), "get",
- baseRef, SSMRESOURCE(conn), NULL,&SSMRESOURCE(conn)->m_clientContext, PR_TRUE) != SSM_SUCCESS) {
- rv = SECFailure;
- goto loser;
- }
- /* wait until the UI event is complete */
- while (!conn->m_UIInfo.UICompleted) {
- SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT);
- }
- if (conn->m_UIInfo.trustBadServerCert == BSCA_NO) {
- /* user did not want to continue. Cancel here. */
- if (rv == SECSuccess) {
- rv = SECFailure;
- }
- goto loser;
- }
- /* ### sjlee: ugliness warning! accessing cert fields directly */
- cert->timeOK = PR_TRUE;
- #if 0 /* Setting timeOK suffices. Setting trust flags is unnecessary. */
- rv = SSM_SSLServerCertResetTrust(cert, conn->m_UIInfo.trustBadServerCert);
- if (rv != SECSuccess) {
- goto loser;
- }
- #endif
- loser:
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- conn->m_UIInfo.UICompleted = PR_FALSE;
- SSM_UnlockResource(SSMRESOURCE(conn));
- if (baseRef != NULL) {
- PR_Free(baseRef);
- }
- return rv;
- }
- SECStatus SSM_SSLServerCertResetTrust(CERTCertificate* cert,
- SSMBadServerCertAccept accept)
- {
- char* nickname = NULL;
- CERTCertTrust trust;
- CERTCertTrust* trustPtr = NULL;
- SECStatus rv;
-
- if (accept == BSCA_NO) {
- /* this usually shouldn't happen */
- goto loser;
- }
- else if (accept == BSCA_PERMANENT) {
- memset((void*)&trust, 0, sizeof(trust));
- /*trust.sslFlags = CERTDB_VALID_PEER | CERTDB_TRUSTED;*/
- /* this resets the SSL flags CERTDB_VALID_PEER | CERTDB_TRUSTED */
- rv = CERT_DecodeTrustString(&trust, "P");
- if (rv != SECSuccess) {
- goto loser;
- }
- /* XXX not neccessary? */
- /*
- if (mystate->postwarn) {
- trust.sslFlags |= CERTDB_SEND_WARN;
- rv = CERT_DecodeTrustString(&trust, "w");
- }
- */
- nickname = ssm_default_server_nickname(cert);
- if (nickname == NULL) {
- goto loser;
- }
-
- /* add a temporary certificate to the permanent database */
- rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
- if (nickname != NULL) {
- PR_Free(nickname);
- }
- if (rv != SECSuccess) {
- goto loser;
- }
- } else if (accept == BSCA_SESSION) {
- /* bump the ref count on the cert so that it stays around for
- * the entire session
- */
- /* ### sjlee: ugliness warning: accessing fields directly */
- cert->keepSession = PR_TRUE;
- if (cert->trust != NULL) {
- trustPtr = cert->trust;
- }
- else {
- trustPtr = (CERTCertTrust*)PORT_ArenaZAlloc(cert->arena,
- sizeof(CERTCertTrust));
- cert->trust = trustPtr;
- }
- if (trustPtr == NULL) {
- goto loser;
- }
- /* set the trust value */
- /*trustptr->sslFlags |= (CERTDB_VALID_PEER | CERTDB_TRUSTED);*/
- /* reset the trust SSL bit to CERTDB_VALID_PEER | CERTDB_TRUSTED */
- rv = CERT_DecodeTrustString(trustPtr, "P");
- if (rv != SECSuccess) {
- goto loser;
- }
- /*
- if (mystate->postwarn) {
- trustptr->sslFlags |= CERTDB_SEND_WARN;
- rv = CERT_DecodeTrustString(trustptr, "w");
- }
- */
- }
- return rv;
- loser:
- if (rv == SECSuccess) {
- rv = SECFailure;
- }
- return rv;
- }
- /* This is also called in oldfunc.c when creating default nickname for
- * a new certificate.
- */
- void _ssm_compress_spaces(char* psrc)
- {
- char* pdst;
- char c;
- PRBool lastspace = PR_FALSE;
-
- if (psrc == NULL) {
- return;
- }
-
- pdst = psrc;
- while (((c = *psrc) != 0) && isspace(c)) {
- psrc++;
- /* swallow leading spaces */
- }
-
-
- while ((c = *psrc++) != 0) {
- if (isspace(c)) {
- if (!lastspace) {
- *pdst++ = ' ';
- }
- lastspace = PR_TRUE;
- } else {
- *pdst++ = c;
- lastspace = PR_FALSE;
- }
- }
- *pdst = ' ';
- /* if the last character is a space, then remove it too */
- pdst--;
- c = *pdst;
- if (isspace(c)) {
- *pdst = ' ';
- }
-
- return;
- }
- /*
- * Function: char* ssm_default_server_nickname()
- * Purpose: creates a default nickname for a bad server cert in case the
- * user wanted to continue
- * Arguments and return values
- * - cert: cert in question
- * - returns: the composed nickname; NULL if failure
- *
- * Note: shamelessly copied from the Nova code
- */
- static char* ssm_default_server_nickname(CERTCertificate* cert)
- {
- char* nickname = NULL;
- int count;
- PRBool conflict;
- char* servername = NULL;
-
- servername = CERT_GetCommonName(&cert->subject);
- if (servername == NULL) {
- goto loser;
- }
-
- count = 1;
- while (1) {
- if (count == 1) {
- nickname = PR_smprintf("%s", servername);
- }
- else {
- nickname = PR_smprintf("%s #%d", servername, count);
- }
- if (nickname == NULL) {
- goto loser;
- }
- _ssm_compress_spaces(nickname);
-
- conflict = SEC_CertNicknameConflict(nickname, &cert->derSubject,
- cert->dbhandle);
- if (conflict == PR_SUCCESS) {
- goto done;
- }
- /* free the nickname */
- PORT_Free(nickname);
- count++;
- }
-
- loser:
- if (nickname != NULL) {
- PR_Free(nickname);
- nickname = NULL;
- }
- done:
- if (servername != NULL) {
- PR_Free(servername);
- }
-
- return nickname;
- }
- SSMStatus SSM_CurrentTimeKeywordHandler(SSMTextGenContext* cx)
- {
- SSMStatus rv;
- char* wrapper = NULL;
- char* key = NULL;
- void* dfmt = NULL;
- char* utf8Now = NULL;
- int64 now;
- const PRIntn TIME_WRAPPER = (PRIntn)0;
- /* we have one keyword */
-
- /* check arguments */
- /* ### sjlee: might as well make this a helper function because most
- * keyword handlers will use this checking
- */
- PR_ASSERT(cx != NULL);
- /* PR_ASSERT(cx->m_request != NULL);*/
- PR_ASSERT(cx->m_params != NULL);
- PR_ASSERT(cx->m_result != NULL);
- if (cx == NULL || cx->m_params == NULL || cx->m_result == NULL) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
-
- /* form the DateFormat object */
- dfmt = nlsNewDateFormat();
- if (!dfmt) {
- goto loser;
- }
-
- /* form the MessageFormat object */
- /* first, find the key (wrapper) */
- key = (char *) SSM_At(cx->m_params, TIME_WRAPPER);
-
- /* second, grab and expand the key word object */
- rv = SSM_GetAndExpandTextKeyedByString(cx, key, &wrapper);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("current time wrapper", wrapper);
- now = PR_Now();
- utf8Now = nslPRTimeToUTF8String(dfmt, now);
- if (!utf8Now) {
- goto loser;
- }
-
- SSMTextGen_UTF8StringClear(&cx->m_result);
- PR_FREEIF(cx->m_result);
- cx->m_result = PR_smprintf(wrapper, utf8Now);
- SSM_DebugUTF8String("result of wrapping", cx->m_result);
- goto done;
- loser:
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- PR_FREEIF(wrapper);
- if (dfmt != NULL) {
- nlsFreeDateFormat(dfmt);
- }
- return rv;
- }
- /* this function handles the button clicks for all server auth failure dialogs
- * except the unknown issuers case
- */
- SSMStatus SSM_ServerAuthFailureButtonHandler(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMResource* res;
- SSMSSLDataConnection* conn;
- res = (SSMResource*)(req->target);
- conn = (SSMSSLDataConnection*)(req->target);
- if (res->m_buttonType == SSM_BUTTON_OK) {
- /* "OK" button was clicked */
- rv = ssm_http_server_auth_handle_ok_button(req);
- goto done;
- }
- else if (res->m_buttonType == SSM_BUTTON_CANCEL) {
- /* "Cancel" button was clicked */
- rv = ssm_http_server_auth_handle_cancel_button(req);
- goto done;
- }
- else {
- SSM_DEBUG("Don't know which button was clicked.n");
- rv = SSM_FAILURE;
- }
- SSM_LockResource(res);
- conn->m_UIInfo.UICompleted = PR_TRUE;
- /* the default course of action if something goes wrong is not to trust */
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- SSM_NotifyResource(res);
- SSM_UnlockResource(res);
- done:
- /* this actually includes the error cases returned from individual
- * button handlers
- */
- return rv;
- }
- SSMStatus ssm_http_server_auth_handle_ok_button(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- char* accept = NULL;
- conn = (SSMSSLDataConnection*)(req->target);
- SSM_LockResource(req->target);
- /* if the user wanted to go ahead, accept="session" */
- rv = SSM_HTTPParamValue(req, "accept", &accept);
- if (rv != SSM_SUCCESS) {
- /* either the user did not want to continue or something went wrong */
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- goto loser;
- }
- PR_ASSERT(accept != NULL);
- if (PL_strcmp(accept, "session") == 0) {
- conn->m_UIInfo.trustBadServerCert = BSCA_SESSION;
- }
- else if (PL_strcmp(accept, "permanent") == 0) {
- conn->m_UIInfo.trustBadServerCert = BSCA_PERMANENT;
- }
- else {
- /* either something went wrong or the user did not want to continue */
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- }
- loser:
- /* close the window */
- rv = SSM_HTTPCloseAndSleep(req);
- /* set the predicate to true and unblock the SSL thread */
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- return rv;
- }
- SSMStatus ssm_http_server_auth_handle_cancel_button(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
-
- conn = (SSMSSLDataConnection*)(req->target);
- SSM_LockResource(req->target);
- /* close the window */
- rv = SSM_HTTPCloseAndSleep(req);
- /* leave the cert untrusted */
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- return rv;
- }
- SSMStatus SSM_ServerAuthDomainNameKeywordHandler(SSMTextGenContext* cx)
- {
- SSMResource* target = NULL;
- SSMSSLDataConnection* sslconn = NULL;
- SSMStatus rv;
- char* pattern = NULL;
- char* key = NULL;
- CERTCertificate* serverCert = NULL;
- char* hostname = NULL;
- char* URLHostname = NULL;
- const PRIntn DOMAIN_NAME_FORMAT = (PRIntn)0;
- /* we have one keyword */
-
- /* check arguments */
- /* ### sjlee: might as well make this a helper function because most
- * keyword handlers will use this checking
- */
- PR_ASSERT(cx != NULL);
- PR_ASSERT(cx->m_request != NULL);
- PR_ASSERT(cx->m_params != NULL);
- PR_ASSERT(cx->m_result != NULL);
- if (cx == NULL || cx->m_request == NULL || cx->m_params == NULL ||
- cx->m_result == NULL) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
-
- /* retrieve the server cert */
- target = SSMTextGen_GetTargetObject(cx);
- PR_ASSERT(SSM_IsA(target, SSM_RESTYPE_SSL_DATA_CONNECTION));
- sslconn = (SSMSSLDataConnection*)target;
- serverCert = SSL_PeerCertificate(sslconn->socketSSL);
- if (serverCert == NULL) {
- /* couldn't get the server cert: what do I do? */
- goto loser;
- }
- /* get the hostname from the cert */
- hostname = CERT_GetCommonName(&serverCert->subject);
- if (hostname == NULL) {
- goto loser;
- }
- /* get the URL hostname from the socket */
- URLHostname = SSL_RevealURL(sslconn->socketSSL);
- if (URLHostname == NULL) {
- goto loser;
- }
- /* form the MessageFormat object */
- /* first, find the key (format argument) */
- key = (char *) SSM_At(cx->m_params, DOMAIN_NAME_FORMAT);
- /* second, grab and expand the key word object */
- rv = SSM_GetAndExpandTextKeyedByString(cx, key, &pattern);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("domain name string pattern", pattern);
- SSMTextGen_UTF8StringClear(&cx->m_result);
-
- PR_FREEIF(cx->m_result);
- cx->m_result = PR_smprintf(pattern, URLHostname, hostname);
- if (cx->m_result == NULL) {
- goto loser;
- }
- SSM_DebugUTF8String("wrapped domain name string", cx->m_result);
- goto done;
- loser:
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- if (serverCert != NULL) {
- CERT_DestroyCertificate(serverCert);
- }
- if (hostname != NULL) {
- PR_Free(hostname);
- }
- if (URLHostname != NULL) {
- PR_Free(URLHostname);
- }
- PR_FREEIF(pattern);
- return rv;
- }
- /*
- * Function: SECStatus SSM_SSLMakeCertBadDomainDialog()
- * Purpose: dispatch the UI event to create the server cert domain name
- * mismatch dialog
- * Arguments and return values
- * - cert: server cert we are dealing with
- * - conn: SSL connection object
- * - returns: SECSuccess if successful *and* the user decides to trust
- * the cert; appropriate error code otherwise
- */
- SECStatus SSM_SSLMakeCertBadDomainDialog(CERTCertificate* cert,
- SSMSSLDataConnection* conn)
- {
- char * sslHostname = NULL;
- SECStatus rv = SECSuccess;
- SSM_LockResource(SSMRESOURCE(conn));
- conn->m_UIInfo.UICompleted = PR_FALSE;
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- /* fire up the UI */
- if (SSMControlConnection_SendUIEvent(SSMCONTROLCONNECTION(conn), "get",
- "bad_server_cert_domain",
- SSMRESOURCE(conn), NULL,
- &SSMRESOURCE(conn)->m_clientContext,
- PR_TRUE) != SSM_SUCCESS) {
- rv = SECFailure;
- goto loser;
- }
- /* wait until the UI event is complete */
- while (!conn->m_UIInfo.UICompleted) {
- SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT);
- }
- if (conn->m_UIInfo.trustBadServerCert == BSCA_NO) {
- /* user did not want to continue. Cancel here. */
- if (rv == SECSuccess) {
- rv = SECFailure;
- }
- goto loser;
- }
- sslHostname = SSL_RevealURL(conn->socketSSL);
- if (!sslHostname)
- goto loser;
- rv = CERT_AddOKDomainName(cert, sslHostname);
- PORT_Free(sslHostname);
- #if 0 /* this is not neccessary, and is wrong (in this case) */
- rv = SSM_SSLServerCertResetTrust(cert, conn->m_UIInfo.trustBadServerCert);
- #endif
- if (rv != SECSuccess) {
- goto loser;
- }
- loser:
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- conn->m_UIInfo.UICompleted = PR_FALSE;
- SSM_UnlockResource(SSMRESOURCE(conn));
- return rv;
- }
- SSMStatus SSM_PrettyFormatCert(CERTCertificate* cert, char* fmt,
- char** result,PRBool addIssuerLink)
- {
- SSMStatus rv = SSM_SUCCESS;
- char * displayName = NULL, *location=NULL, *state = NULL, *country = NULL;
- char * emailaddr = NULL, * orgName = NULL, *unitName = NULL;
- char* issuer = NULL;
- char* serialNumber = NULL;
- char * notBefore = NULL;
- char * notAfter = NULL;
- char * tmp = NULL;
- unsigned char fingerprint[16];
- SECItem fpItem;
- char* fpStr = NULL;
- char* commentString = NULL;
- /* check arguments */
- if (cert == NULL || fmt == NULL || result == NULL) {
- PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
- goto loser;
- }
-
- /* retrieve cert information */
-
- displayName = CERT_GetCommonName(&cert->subject);
- emailaddr = CERT_GetCertEmailAddress(&cert->subject);
- orgName = CERT_GetOrgName(&cert->subject);
- unitName = CERT_GetOrgUnitName(&cert->subject);
- if (!displayName)
- displayName = PL_strdup("");
- if (!emailaddr)
- emailaddr = PL_strdup("");
- if (!orgName)
- orgName = PL_strdup("");
- if (!unitName)
- unitName = PL_strdup("");
-
- location = CERT_GetLocalityName(&cert->subject);
- if (!location)
- location = PL_strdup("");
- state = CERT_GetStateName(&cert->subject);
- if (!state)
- state = PL_strdup("");
- country = CERT_GetCountryName(&cert->subject);
- if (!country)
- country = PL_strdup("");
- issuer = CERT_GetOrgName(&cert->issuer);
- if (issuer == NULL) {
- issuer = PL_strdup("");
- } else {
- /*
- * Don't add the extra link if this is a self-signed cert.
- */
- if (addIssuerLink &&
- CERT_CompareName(&cert->subject, &cert->issuer) != SECEqual) {
- tmp=PR_smprintf("<a href="javascript:openIssuerWindow();">%s</a>",
- issuer);
- PR_Free(issuer);
- issuer = tmp;
- tmp = NULL;
- }
- }
- serialNumber = CERT_Hexify(&cert->serialNumber, 1);
- if (serialNumber == NULL) {
- serialNumber = PL_strdup("");
- }
- notBefore = DER_UTCDayToAscii(&cert->validity.notBefore);
- if (!notBefore)
- notBefore = PL_strdup("");
- notAfter = DER_UTCDayToAscii(&cert->validity.notAfter);
- if (!notAfter)
- notAfter = PL_strdup("");
- MD5_HashBuf(fingerprint, cert->derCert.data, cert->derCert.len);
- fpItem.data = fingerprint;
- fpItem.len = sizeof(fingerprint);
- fpStr = CERT_Hexify(&fpItem, 1);
- if (fpStr == NULL) {
- fpStr = PL_strdup("");
- }
- commentString = CERT_GetCertCommentString(cert);
- if (commentString == NULL) {
- commentString = PL_strdup(" ");
- }
- /* comments can be NULL */
- *result = PR_smprintf(fmt, displayName, emailaddr, unitName, orgName,
- location, state, country, issuer, serialNumber,
- notBefore, notAfter, fpStr, commentString);
- if (*result == NULL) {
- goto loser;
- }
- SSM_DebugUTF8String("wrapped view cert string", *result);
- goto done;
- loser:
- SSM_DEBUG("Pretty formatting cert failed.n");
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- if (issuer != NULL) {
- PR_Free(issuer);
- }
- if (serialNumber != NULL) {
- PR_Free(serialNumber);
- }
- if (fpStr != NULL) {
- PR_Free(fpStr);
- }
- if (commentString != NULL) {
- PR_Free(commentString);
- }
- PR_FREEIF(notBefore);
- PR_FREEIF(notAfter);
- PR_FREEIF(displayName);
- PR_FREEIF(emailaddr);
- PR_FREEIF(orgName);
- PR_FREEIF(unitName);
- return rv;
- }
- SSMStatus SSM_VerifyServerCertKeywordHandler(SSMTextGenContext* cx)
- {
- SSMStatus rv;
- SSMResource* target = NULL;
- SSMSSLDataConnection* sslconn = NULL;
- CERTCertDBHandle* handle = NULL;
- CERTCertificate* serverCert = NULL;
- char* nickname = NULL;
- char* pattern = NULL;
- PR_ASSERT(cx != NULL);
- PR_ASSERT(cx->m_request != NULL);
- PR_ASSERT(cx->m_params != NULL);
- PR_ASSERT(cx->m_result != NULL);
- /* retrieve the server cert */
- target = SSMTextGen_GetTargetObject(cx);
- PR_ASSERT(SSM_IsA(target, SSM_RESTYPE_SSL_DATA_CONNECTION));
- sslconn = (SSMSSLDataConnection*)target;
- handle = SSMCONTROLCONNECTION(sslconn)->m_certdb;
-
- serverCert = SSL_PeerCertificate(sslconn->socketSSL);
- if (serverCert == NULL) {
- goto loser;
- }
- nickname = CERT_GetNickName(serverCert, handle, serverCert->arena);
- if (nickname == NULL) {
- /* nickname was not found: that's still OK, let's do this */
- nickname = PL_strdup("Unknown");
- if (nickname == NULL) {
- goto loser;
- }
- }
- /* don't free it! */
- /* if we want to verify the cert, we would do something like this...
- srv = CERT_VerifyCertNow(ctrlconn->m_certdb, cert, PR_TRUE, certSSLServer,
- conn);
- */
- SSMTextGen_UTF8StringClear(&cx->m_result);
- rv = SSM_GetAndExpandTextKeyedByString(cx, "not_verified_text",
- &cx->m_result);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- SSM_DebugUTF8String("wrapped verification string %s", cx->m_result);
- goto done;
- loser:
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- done:
- if (serverCert != NULL) {
- CERT_DestroyCertificate(serverCert);
- }
- if (nickname != NULL) {
- PR_Free(nickname);
- }
- PR_FREEIF(pattern);
- return rv;
- }
- /*
- * Function: SECStatus SSM_SSLMakeUnknownIssuerDialog()
- * Purpose: dispatch the UI event to create the unknown issuer dialog
- * Arguments and return values
- * - cert: server cert we are dealing with
- * - conn: SSL connection object
- * - returns: SECSuccess if successful *and* the user decides to trust
- * the cert; appropriate error code otherwise
- */
- SECStatus SSM_SSLMakeUnknownIssuerDialog(CERTCertificate* cert,
- SSMSSLDataConnection* conn)
- {
- SECStatus rv = SECSuccess;
- SSM_LockResource(SSMRESOURCE(conn));
- conn->m_UIInfo.UICompleted = PR_FALSE;
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- /* fire up the UI */
- if (SSMControlConnection_SendUIEvent(SSMCONTROLCONNECTION(conn), "get",
- "bad_server_cert_unknown_issuer1",
- SSMRESOURCE(conn), NULL,
- &SSMRESOURCE(conn)->m_clientContext, PR_TRUE) != SSM_SUCCESS) {
- rv = SECFailure;
- goto loser;
- }
- /* wait until the UI event is complete */
- while (!conn->m_UIInfo.UICompleted) {
- SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT);
- }
- if (conn->m_UIInfo.trustBadServerCert == BSCA_NO) {
- /* user did not want to continue. Cancel here. */
- if (rv == SECSuccess) {
- rv = SECFailure;
- }
- goto loser;
- }
- /* reset the trust bit for the session and continue */
- rv = SSM_SSLServerCertResetTrust(cert, conn->m_UIInfo.trustBadServerCert);
- if (rv != SECSuccess) {
- goto loser;
- }
- loser:
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- conn->m_UIInfo.UICompleted = PR_FALSE;
- SSM_UnlockResource(SSMRESOURCE(conn));
- return rv;
- }
- SSMStatus SSM_HTTPUnknownIssuerStep1ButtonHandler(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- char* tmpStr = NULL;
- PR_ASSERT(req->target != NULL);
- conn = (SSMSSLDataConnection*)(req->target);
- /* make sure you got the right baseRef */
- rv = SSM_HTTPParamValue(req, "baseRef", &tmpStr);
- if (rv != SSM_SUCCESS ||
- PL_strcmp(tmpStr, "windowclose_doclose_js") != 0) {
- goto loser;
- }
- rv = SSM_HTTPParamValue(req, "do_cancel", &tmpStr);
- if (rv == SSM_SUCCESS) {
- /* cancel button was clicked */
- req->target->m_buttonType = SSM_BUTTON_CANCEL;
- }
- else {
- rv = SSM_HTTPParamValue(req, "do_next", &tmpStr);
- if (rv == SSM_SUCCESS) {
- /* next button was clicked */
- req->target->m_buttonType = SSM_BUTTON_OK; /* close enough */
- }
- }
- if (rv != SSM_SUCCESS) {
- rv = SSM_ERR_NO_BUTTON;
- goto loser;
- }
- switch (req->target->m_buttonType)
- {
- case SSM_BUTTON_CANCEL:
- rv = ssm_http_server_auth_handle_cancel_button(req);
- break;
- case SSM_BUTTON_OK:
- rv = ssm_http_unknown_issuer_step1_handle_next_button(req);
- break;
- default:
- break;
- }
- return rv; /* error code will be properly set */
- loser:
- /* set the predicate to true and unblock the SSL thread */
- SSM_LockResource(req->target);
- conn->m_UIInfo.UICompleted = PR_TRUE;
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- if (rv == SSM_SUCCESS) {
- rv = SSM_FAILURE;
- }
- return rv;
- }
- SSMStatus ssm_http_unknown_issuer_step1_handle_next_button(HTTPRequest* req)
- {
- SSMStatus rv;
- SSMSSLDataConnection* conn;
- conn = (SSMSSLDataConnection*)(req->target);
- SSM_LockResource(req->target);
- /* do away with the first dialog */
- rv = SSM_HTTPCloseAndSleep(req);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- /* fire up the next dialog */
- rv = SSMControlConnection_SendUIEvent(SSMCONTROLCONNECTION(conn), "get",
- "bad_server_cert_unknown_issuer2",
- SSMRESOURCE(conn), NULL, &SSMRESOURCE(conn)->m_clientContext, PR_TRUE);
- if (rv != SSM_SUCCESS) {
- goto loser;
- }
- conn->m_UIInfo.UICompleted = PR_FALSE;
- /* the above is redundant but for peace of mind */
- SSM_UnlockResource(req->target);
- return rv; /* SSM_SUCCESS */
- loser:
- /* still we want to unblock the SSL thread: the connection will fail */
- conn->m_UIInfo.trustBadServerCert = BSCA_NO;
- conn->m_UIInfo.UICompleted = PR_TRUE;
- SSM_NotifyResource(req->target);
- SSM_UnlockResource(req->target);
- return rv;
- }