📄 sslskst.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 "ctrlconn.h"#include "serv.h"#include "servimpl.h"/* Shorthand macros for inherited classes */#define SSMRESOURCE(ss) (&(ss)->super)/* implemented in resource.c: this should belong to resource.h! */SSMStatus SSM_UnpickleResource(SSMResource** res, SSMResourceType type, SSMControlConnection* connection, PRIntn len, void* value);SSMStatusSSMSSLSocketStatus_Create(void *arg, SSMControlConnection * connection, SSMResource **res){ SSMStatus rv = PR_SUCCESS; SSMSSLSocketStatus *ss; *res = NULL; /* in case we fail */ ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus)); if (!ss) goto loser; rv = SSMSSLSocketStatus_Init(ss, connection, (PRFileDesc *) arg, SSM_RESTYPE_SSL_SOCKET_STATUS); if (rv != PR_SUCCESS) goto loser; SSMSSLSocketStatus_Invariant(ss); *res = &ss->super; return PR_SUCCESS; loser: if (rv == PR_SUCCESS) rv = PR_FAILURE; if (ss) { SSMRESOURCE(ss)->m_refCount = 1; /* force destroy */ SSM_FreeResource(SSMRESOURCE(ss)); } return rv;}SSMStatus SSMSSLSocketStatus_Init(SSMSSLSocketStatus *ss, SSMControlConnection * connection, PRFileDesc *fd, SSMResourceType type){ SSMStatus rv = PR_SUCCESS; int keySize, secretKeySize, level; SSMResource *certObj; SSMResourceID certRID; /* Initialize superclass */ SSMResource_Init(connection, SSMRESOURCE(ss), type); /* Get the peer cert and import it into a PSM object */ ss->m_cert = SSL_PeerCertificate(fd); if (!ss->m_cert) goto loser; rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, ss->m_cert, SSMRESOURCE(ss)->m_connection, &certRID, &certObj); if (rv != PR_SUCCESS) goto loser; ss->m_certID = certObj->m_id; /* Get the other socket status information */ rv = SSL_SecurityStatus(fd, &level, &ss->m_cipherName, &keySize, &secretKeySize, NULL, NULL); if (rv != PR_SUCCESS) goto loser; ss->m_keySize = keySize; ss->m_secretKeySize = secretKeySize; ss->m_level = level; /* Sanity check before returning */ SSMSSLSocketStatus_Invariant(ss); goto done;loser: /* member destruct, if any are allocated, will happen in the _Destroy method */ if (rv == PR_SUCCESS) rv = PR_FAILURE;done: return rv;}SSMStatus SSMSSLSocketStatus_Destroy(SSMResource *res, PRBool doFree){ SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res; SSMSSLSocketStatus_Invariant(ss); /* Destroy our members. */ if (ss->m_cert) { CERT_DestroyCertificate(ss->m_cert); ss->m_cert = NULL; } if (ss->m_cipherName) { PORT_Free(ss->m_cipherName); ss->m_cipherName = NULL; } /* Destroy superclass. */ SSMResource_Destroy(res, PR_FALSE); /* Free if asked. */ if (doFree) PR_Free(res); return PR_SUCCESS;}void SSMSSLSocketStatus_Invariant(SSMSSLSocketStatus *ss){ /* Superclass invariant */ SSMResource_Invariant(SSMRESOURCE(ss)); /* Class check */ PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ss), SSM_RESTYPE_SSL_SOCKET_STATUS)); /* Member check */ /* Make sure we used a cert to initialize ourselves */ if (ss->m_certID) PR_ASSERT(ss->m_cert != NULL);}SSMStatus SSMSSLSocketStatus_GetAttrIDs(SSMResource *res, SSMAttributeID **ids, PRIntn *count){ SSMStatus rv; rv = SSMResource_GetAttrIDs(res, ids, count); if (rv != PR_SUCCESS) goto loser; *ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 4) * sizeof(SSMAttributeID)); if (! *ids) goto loser; (*ids)[*count++] = SSM_FID_SSS_KEYSIZE; (*ids)[*count++] = SSM_FID_SSS_SECRET_KEYSIZE; (*ids)[*count++] = SSM_FID_SSS_CERT_ID; (*ids)[*count++] = SSM_FID_SSS_CIPHER_NAME; goto done; loser: if (rv == PR_SUCCESS) rv = PR_FAILURE; done: return rv;}SSMStatus SSMSSLSocketStatus_GetAttr(SSMResource *res, SSMAttributeID attrID, SSMResourceAttrType attrType, SSMAttributeValue *value){ SSMStatus rv = PR_SUCCESS; SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res; char *tmpstr = NULL; SSM_DEBUG("socket status get attr is called.\n"); SSMSSLSocketStatus_Invariant(ss); /* see what it is */ switch(attrID) { case SSM_FID_SSS_KEYSIZE: value->type = SSM_NUMERIC_ATTRIBUTE; value->u.numeric = ss->m_keySize; break; case SSM_FID_SSS_SECRET_KEYSIZE: value->type = SSM_NUMERIC_ATTRIBUTE; value->u.numeric = ss->m_secretKeySize; break; case SSM_FID_SSS_CERT_ID: value->type = SSM_RID_ATTRIBUTE; value->u.numeric = ss->m_certID; break; case SSM_FID_SSS_SECURITY_LEVEL: value->type = SSM_NUMERIC_ATTRIBUTE; value->u.numeric = ss->m_level; break; case SSM_FID_SSS_CIPHER_NAME: value->type = SSM_STRING_ATTRIBUTE; value->u.string.len = PL_strlen(ss->m_cipherName); value->u.string.data = (unsigned char *) PL_strdup(ss->m_cipherName); break; case SSM_FID_SSS_HTML_STATUS: value->type = SSM_STRING_ATTRIBUTE; rv = (*res->m_html_func)(res, NULL, (void**)&tmpstr); value->u.string.len = PL_strlen(tmpstr); value->u.string.data = (unsigned char *) PL_strdup(tmpstr); break; default: rv = SSMResource_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: if (tmpstr != NULL) PR_Free(tmpstr); return rv;}SSMStatus SSMSSLSocketStatus_Pickle(SSMResource *res, PRIntn * len, void **value){ int blobSize, certSize; SSMStatus rv; SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res; SSMResourceCert *certObj; void * certBlob, *curptr, *tmpStr = NULL; if (!res || !value) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } /* in case we fail */ *value = NULL; if (len) *len = 0; /* first, pickle cert */ rv = SSMControlConnection_GetResource(res->m_connection, resource->m_certID, (SSMResource **)&certObj); if (rv != PR_SUCCESS) goto loser; rv = SSM_PickleResource(SSMRESOURCE(certObj), &certSize, &certBlob); if (rv != PR_SUCCESS) goto loser; /* allocate memory for the pickled blob */ blobSize = certSize + sizeof(PRUint32)*5 + SSMSTRING_PADDED_LENGTH(strlen(resource->m_cipherName)); curptr = PORT_ZAlloc(blobSize); if (!curptr) { rv = PR_OUT_OF_MEMORY_ERROR; goto loser; } *value = curptr; *(PRUint32 *)curptr = resource->m_keySize; curptr = (PRUint32 *)curptr + 1; *(PRUint32 *)curptr = resource->m_secretKeySize; curptr = (PRUint32 *)curptr + 1; *(PRInt32*)curptr = resource->m_level; curptr = (PRInt32 *)curptr + 1; *(PRInt32*)curptr = resource->m_error; curptr = (PRInt32 *)curptr + 1; rv = SSM_StringToSSMString((SSMString **)&tmpStr, 0, resource->m_cipherName); if (rv != PR_SUCCESS) goto loser; memcpy(curptr, tmpStr, SSM_SIZEOF_STRING(*(SSMString *)tmpStr)); curptr = (char *)curptr + SSM_SIZEOF_STRING(*(SSMString *)tmpStr); PR_Free(tmpStr); tmpStr = NULL; /* copy cert into the blob */ memcpy(curptr, certBlob, certSize); if (len) *len = blobSize; return rv; loser: if (rv == PR_SUCCESS) rv = PR_FAILURE; if (value && *value) PR_Free(*value); if (len) *len = 0; if (tmpStr) PR_Free(tmpStr); return rv;}SSMStatus SSMSSLSocketStatus_Unpickle(SSMResource ** res, SSMControlConnection * connection, PRInt32 len, void *value){ SSMStatus rv = PR_SUCCESS; SSMSSLSocketStatus *ss; void * curptr = NULL; PRUint32 strLength = 0, certLength = 0; SSMResource * certResource = NULL; if (!res || !value) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } *res = NULL; /* in case we fail */ ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus)); if (!ss) goto loser; ss->m_cipherName = NULL; ss->m_certID = 0; /* Initialize superclass */ SSMResource_Init(connection, SSMRESOURCE(ss), SSM_RESTYPE_SSL_SOCKET_STATUS); /* Unpickle socket status data */ curptr = value; ss->m_keySize = *(PRUint32 *)curptr; curptr =(PRUint32 *)curptr + 1; ss->m_secretKeySize = *(PRUint32 *)curptr; curptr =(PRUint32 *)curptr + 1; ss->m_level = *(PRInt32 *)curptr; curptr = (PRInt32 *)curptr + 1; ss->m_error = *(PRInt32 *)curptr; curptr = (PRInt32 *)curptr + 1; /* Fix this */ rv = SSM_SSMStringToString(&ss->m_cipherName, (int *) &strLength, (SSMString *)curptr); if (rv != PR_SUCCESS || ss->m_cipherName == NULL || strLength == 0) goto loser; curptr = (char *)curptr + SSMSTRING_PADDED_LENGTH(strLength) + sizeof(PRUint32); /* Unpickle cert */ certLength = len - ((unsigned long)curptr - (unsigned long)value); rv = SSM_UnpickleResource(&certResource, SSM_RESTYPE_CERTIFICATE, connection, certLength, curptr); if (rv != PR_SUCCESS || !certResource) goto loser; ss->m_certID = certResource->m_id; ss->m_cert = ((SSMResourceCert *)certResource)->cert; /* Sanity check before returning */ SSMSSLSocketStatus_Invariant(ss); *res = SSMRESOURCE(ss); goto done; loser: if (ss) { if (ss->m_cipherName) PR_Free(ss->m_cipherName); if (ss->m_certID && certResource) (*(certResource->m_destroy_func))(certResource, PR_TRUE); PR_Free(certResource); } if (rv == PR_SUCCESS) rv = PR_FAILURE;done: return rv;}SSMStatus SSMSSLSocketStatus_HTML(SSMResource *res, PRIntn *len, void ** value){ SSMStatus rv = PR_SUCCESS; SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res; char * line = NULL; if (!res || !value) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } if (len) *len = 0; *value = NULL; switch (resource->m_level) { case SSL_SECURITY_STATUS_ON_HIGH:#ifdef FORTEZZA case SSL_SECURITY_STATUS_FORTEZZA:#endif line = PR_smprintf("%s", SECURITY_HIGH_MESSAGE); break; case SSL_SECURITY_STATUS_ON_LOW: line = PR_smprintf("%s", SECURITY_LOW_MESSAGE); break; default: *value = PR_smprintf("%s", SECURITY_NO_MESSAGE); goto done; } if (resource->m_keySize != resource->m_secretKeySize) { *value = PR_smprintf("%s (%s, %d bit with %d secret).", line, resource->m_cipherName, resource->m_keySize, resource->m_secretKeySize); } else { *value = PR_smprintf("%s (%s, %d bit).", line, resource->m_cipherName, resource->m_keySize); } goto done;loser: if (value && *value) PR_Free(*value); *value = NULL; if (len && *len) *len = 0; if (rv == PR_SUCCESS) rv = PR_FAILURE;done: if (value && *value && len) *len = strlen((char *)*value)+1; if (line) PR_Free(line); return rv;}SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus(SSMSSLSocketStatus* ss, PRFileDesc* socket){ SSMStatus rv = PR_SUCCESS; int keySize, secretKeySize, level; /* ss should not be NULL when this function is called */ PR_ASSERT(ss != NULL); /* Get the security status information */ if (ss->m_cipherName != NULL) { PR_Free(ss->m_cipherName); ss->m_cipherName = NULL; } rv = SSL_SecurityStatus(socket, &level, &ss->m_cipherName, &keySize, &secretKeySize, NULL, NULL); if (rv != PR_SUCCESS) { goto loser; } ss->m_keySize = keySize; ss->m_secretKeySize = secretKeySize; ss->m_level = level; /* Sanity check before returning */ SSMSSLSocketStatus_Invariant(ss); goto done;loser: if (rv == PR_SUCCESS) { rv = PR_FAILURE; } if (ss->m_cipherName != NULL) { PR_Free(ss->m_cipherName); ss->m_cipherName = NULL; }done: return rv;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -