⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sslconn.c

📁 安全开发库。含客户端建立ssl连接、签名、证书验证、证书发布和撤销等。编译用到nss
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- 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 "ctrlconn.h"#include "sslerror.h"#include "serv.h"#include "servimpl.h"#include "sslskst.h"#include "ssmerrs.h"#include "ssldlgs.h"#include "collectn.h"#include "prefs.h"/* NSS headers */#include "seccomon.h"#include "keyt.h"#include "cert.h"/* Shorthand macros for inherited classes */#define SSMRESOURCE(sslconn) (&(sslconn)->super.super.super)#define SSMCONNECTION(sslconn) (&(sslconn)->super.super)#define SSMDATACONNECTION(sslconn) (&(sslconn)->super)#define SSMCONTROLCONNECTION(sslconn) ((SSMControlConnection*)(sslconn->super.super.m_parent))/* SSM_UserCertChoice: enum for cert choice info */typedef enum {ASK, AUTO} SSM_UserCertChoice;/* persistent cert choice object we will use here */static SSM_UserCertChoice certChoice;/* strings for marking invalid user cert nicknames */#define NICKNAME_EXPIRED_STRING " (expired)"#define NICKNAME_NOT_YET_VALID_STRING " (not yet valid)"/* private function prototypes */void SSMSSLDataConnection_InitializeUIInfo(SSMSSLUIInfo* info);void SSMSSLDataConnection_DestroyUIInfo(SSMSSLUIInfo* info);SSMStatus SSMSSLDataConnection_UpdateSecurityStatus(SSMSSLDataConnection* conn);SECStatus SSM_SetupSSLSocket(PRFileDesc* socket, PRFileDesc** sslsocket,                             CERTCertDBHandle* handle, char* hostname,                             void* wincx);SSMStatus SSM_GetSSLSocket(SSMSSLDataConnection* conn);void SSM_SSLDataServiceThread(void* arg);SSMStatus SSM_SetUserCertChoice(SSMSSLDataConnection* conn);SECStatus SSM_ConvertCANamesToStrings(PRArenaPool* arena, char** caNameStrings,                                      CERTDistNames* caNames);SSMStatus ssm_client_auth_prepare_nicknames(SSMSSLDataConnection* conn,                                            CERTCertNicknames* nicknames);PRBool SSM_SSLErrorNeedsDialog(int error);SECStatus SSM_SSLMakeBadServerCertDialog(int error,                                          CERTCertificate* cert,                                         SSMSSLDataConnection* conn);SECStatus SSM_SSLVerifyServerCert(CERTCertDBHandle* handle,                                  CERTCertificate* cert, PRBool checkSig,                                   SSMSSLDataConnection* conn);/* callback functions */SECStatus SSM_SSLAuthCertificate(void* arg, PRFileDesc* socket,                                 PRBool checkSig, PRBool isServer);SECStatus SSM_SSLBadCertHandler(void* arg, PRFileDesc* socket);SECStatus SSM_SSLGetClientAuthData(void* arg,                                   PRFileDesc* socket,								   struct CERTDistNamesStr* caNames,								   struct CERTCertificateStr** pRetCert,								   struct SECKEYPrivateKeyStr** pRetKey);void SSM_SSLHandshakeCallback(PRFileDesc* socket, void* clientData);/* implementations *//* class functions */SSMStatus SSMSSLDataConnection_Create(void* arg,                                      SSMControlConnection* ctrlconn,                                     SSMResource** res){    SSMStatus rv = PR_SUCCESS;    SSMSSLDataConnection* conn;	/* check arguments */	if (arg == NULL || res == NULL) {		goto loser;	}	    *res = NULL; /* in case we fail */        conn = (SSMSSLDataConnection*)PR_CALLOC(sizeof(SSMSSLDataConnection));    if (!conn) {		goto loser;	}    rv = SSMSSLDataConnection_Init(conn, (SSMInfoSSL*)arg,                                    SSM_RESTYPE_SSL_DATA_CONNECTION);    if (rv != PR_SUCCESS) {		goto loser;	}    SSMSSLDataConnection_Invariant(conn);        *res = &conn->super.super.super;    return PR_SUCCESS;loser:    if (rv == PR_SUCCESS) {		rv = PR_FAILURE;	}    if (conn) {		SSM_ShutdownResource(SSMRESOURCE(conn), rv);        SSM_FreeResource(SSMRESOURCE(conn));    }            return rv;}SSMStatus SSMSSLDataConnection_Shutdown(SSMResource* arg, SSMStatus status){    SSMStatus rv;    SSMSSLDataConnection* conn = (SSMSSLDataConnection*)arg;	PRBool firstTime = PR_TRUE;    /* ### sjlee: firstTime doesn't seem to be set anywhere */    	/* check argument */	if (arg == NULL) {		return PR_FAILURE;	}	    /*SSMSSLDataConnection_Invariant(conn); -- this could have been called from loser */    SSM_LockResource(arg);    /* shut down base class */    rv = SSMDataConnection_Shutdown(arg, status);	if (firstTime) {		SSM_DEBUG("First time shutting down SSL connection.\n");	}    /* If service threads are done, close the SSL socket */    if (SSMRESOURCE(conn)->m_threadCount == 0) {        if (conn->socketSSL) {			SSM_DEBUG("Closing SSL socket with linger.\n");            rv = PR_Close(conn->socketSSL);            conn->socketSSL = NULL;            SSM_DEBUG("Closed SSL socket (rv == %d).\n", rv);        }    }    SSM_UnlockResource(arg);	if (!firstTime) {		rv = (SSMStatus)SSM_ERR_ALREADY_SHUT_DOWN;	}    return rv;}SSMStatus SSMSSLDataConnection_Init(SSMSSLDataConnection* conn, 								   SSMInfoSSL* info, SSMResourceType type){    SSMStatus rv = PR_SUCCESS;    SSMControlConnection* parent;  	/* check arguments */	if (conn == NULL || info == NULL) {		goto loser;	}    /* fill in the information we got from the request packet */	parent = info->parent;    rv = SSMDataConnection_Init(SSMDATACONNECTION(conn), parent, type);    if (rv != PR_SUCCESS) {		goto loser;	}    conn->isTLS = info->isTLS;    conn->port = info->port;    conn->hostIP = info->hostIP;    conn->hostName = info->hostName;    /* Initialize UI info */    SSMSSLDataConnection_InitializeUIInfo(&conn->m_UIInfo);    if (conn->isTLS == PR_TRUE) {        conn->isSecure = PR_FALSE;        /* Create the step-up FD so that the control connection           can wake us up */        conn->stepUpFD = PR_NewPollableEvent();        if (conn->stepUpFD == NULL)            goto loser;    }    else {        conn->isSecure = PR_TRUE;        conn->forceHandshake = info->forceHandshake;        /* Save the client context */        SSMRESOURCE(conn)->m_clientContext = info->clientContext;    }    /* Spawn the data service thread */    SSM_DEBUG("Creating SSL data service thread.  Getting ref on SSL "              "connection.\n");    SSM_GetResourceReference(SSMRESOURCE(conn));    SSMDATACONNECTION(conn)->m_dataServiceThread =        SSM_CreateThread(SSMRESOURCE(conn), SSM_SSLDataServiceThread);    if (SSMDATACONNECTION(conn)->m_dataServiceThread == NULL) {        goto loser;    }    return PR_SUCCESS;loser:    if (rv == PR_SUCCESS) {		rv = PR_FAILURE;	}    return rv;}SSMStatus SSMSSLDataConnection_Destroy(SSMResource* res, PRBool doFree){    SSMSSLDataConnection* conn = (SSMSSLDataConnection*)res;	if (res == NULL) {		return PR_FAILURE;	}    /* We should be shut down. */    PR_ASSERT(res->m_threadCount == 0);    /* Destroy our fields. */    PR_FREEIF(conn->hostIP);    PR_FREEIF(conn->hostName);    /* Destroy UI info. */    SSMSSLDataConnection_DestroyUIInfo(&conn->m_UIInfo);    /* Destroy step-up FD if we still have one. */    if (conn->stepUpFD)        PR_DestroyPollableEvent(conn->stepUpFD);    /* Destroy superclass fields. */    SSMDataConnection_Destroy(SSMRESOURCE(conn), PR_FALSE);    /* Free the connection object if asked. */    if (doFree) {        PR_DELETE(conn);	}    return PR_SUCCESS;}void SSMSSLDataConnection_Invariant(SSMSSLDataConnection* conn){    SSMDataConnection_Invariant(SSMDATACONNECTION(conn));    SSM_LockResource(SSMRESOURCE(conn));    PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn),                             SSM_RESTYPE_SSL_DATA_CONNECTION));    SSM_UnlockResource(SSMRESOURCE(conn));}SSMStatus SSMSSLDataConnection_GetAttrIDs(SSMResource* res,										 SSMAttributeID** ids, PRIntn* count){    SSMStatus rv;	if (res == NULL || ids == NULL || count == NULL) {		goto loser;	}    rv = SSMDataConnection_GetAttrIDs(res, ids, count);    if (rv != PR_SUCCESS) {        goto loser;	}    *ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 1)*sizeof(SSMAttributeID));    if (!*ids) {		goto loser;	}    (*ids)[*count++] = SSM_FID_SSLDATA_SOCKET_STATUS;    goto done;loser:    if (rv == PR_SUCCESS) {		rv = PR_FAILURE;	}done:    return rv;}SSMStatus SSMSSLDataConnection_GetAttr(SSMResource *res, SSMAttributeID attrID,                                       SSMResourceAttrType attrType,                                       SSMAttributeValue *value){    SSMSSLDataConnection* conn = (SSMSSLDataConnection*)res;    SSMStatus rv = PR_SUCCESS;	if (res == NULL || value == NULL) {		goto loser;	}    /* see what it is */    switch(attrID) {    case SSM_FID_SSLDATA_SOCKET_STATUS:        /* if the socket status does not exist at this time (which         * is very unlikely usually), we will wait until the handshake         * callback creates it         */        SSM_LockResource(SSMRESOURCE(conn));        while (conn->m_sockStat == NULL ||                conn->m_sockStat->m_cipherName == NULL) {            SSM_DEBUG("Oops, the security status has not been updated.  Waiting...\n");            SSM_WaitResource(SSMRESOURCE(conn), PR_INTERVAL_NO_TIMEOUT);        }        if (conn->m_sockStat == NULL) {            SSM_DEBUG("No socket status on dead socket.\n");            SSM_UnlockResource(SSMRESOURCE(conn));            goto loser;        }        /* We have a socket status object, return its resource ID. */        value->u.rid = conn->m_sockStat->super.m_id;        value->type = SSM_RID_ATTRIBUTE;        SSM_UnlockResource(SSMRESOURCE(conn));        /*        if (conn->m_sockStat) {        }        else {            rv = SSM_ERR_ATTRIBUTE_MISSING;            goto loser;        }        */		break;    case SSM_FID_SSLDATA_ERROR_VALUE:        value->type = SSM_NUMERIC_ATTRIBUTE;        SSM_LockResource(SSMRESOURCE(conn));        value->u.numeric = conn->m_error;        SSM_DEBUG("Reported error: %ld\n", conn->m_error);        SSM_UnlockResource(SSMRESOURCE(conn));        break;    default:        rv = SSMConnection_GetAttr(res, attrID, attrType, value);        if (rv != PR_SUCCESS) {			goto loser;		}    }    goto done;loser:    value->type = SSM_NO_ATTRIBUTE;    if (rv == PR_SUCCESS) {		rv = PR_FAILURE;	}done:    return rv;}/* * Function: SSMStatus SSMSSLDataConnection_PickleSecurityStatus() * Purpose: fills in information on security status (pickled socket status *          and the security level) on PickleSecurityStatus request * * Arguments and return values: * - conn: SSL connection object * - len: length of the pickled data * - blob: pickled data * - securityLevel: security level * - returns: PR_SUCCESS if successful; error code otherwise * * Note: Note that this is not really a pickle class function.  This is *       specially designed to handle security status requests efficiently. */SSMStatus SSMSSLDataConnection_PickleSecurityStatus(SSMSSLDataConnection* conn,                                                   PRIntn* len, void** blob,                                                   PRIntn* securityLevel){    SSMStatus rv = PR_SUCCESS;    PR_ASSERT(conn != NULL);    /* if the socket status does not exist at this time (which is usually     * very unlikely), we will wait until the handshake callback creates it     */    SSM_LockResource(SSMRESOURCE(conn));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -