📄 ssldlgs.c
字号:
/* -*- 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"#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_SSLMakeBadClientAuthDialog(SSMSSLDataConnection* conn){ SSMStatus rv; SSM_DEBUG("Client authentication failed.\n"); PR_ASSERT(conn != NULL); SSM_LockResource(SSMRESOURCE(conn)); conn->m_UIInfo.UICompleted = PR_FALSE; /* fire up the UI */ rv = SSMControlConnection_SendUIEvent(SSMCONTROLCONNECTION(conn), "get", "bad_client_auth", SSMRESOURCE(conn), NULL,&SSMRESOURCE(conn)->m_clientContext); if (rv != SSM_SUCCESS) { goto loser; } /* wait until the UI event is complete */ while (conn->m_UIInfo.UICompleted == PR_FALSE) { SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT); }loser: conn->m_UIInfo.UICompleted = PR_FALSE; SSM_UnlockResource(SSMRESOURCE(conn)); return rv;}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; } /* 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); } 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); if (rv != SSM_SUCCESS) { goto loser; } while (conn->m_UIInfo.UICompleted == PR_FALSE) { 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; /* 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); 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() */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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -