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

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. #include "sslconn.h"
  35. #include "ctrlconn.h"
  36. #include "serv.h"
  37. #include "servimpl.h"
  38. /* Shorthand macros for inherited classes */
  39. #define SSMRESOURCE(ss) (&(ss)->super)
  40. /* implemented in resource.c: this should belong to resource.h! */
  41. SSMStatus SSM_UnpickleResource(SSMResource** res, SSMResourceType type, 
  42.                               SSMControlConnection* connection,
  43.                               PRIntn len, void* value);
  44. SSMStatus
  45. SSMSSLSocketStatus_Create(void *arg, SSMControlConnection * connection, 
  46.                           SSMResource **res)
  47. {
  48.     SSMStatus rv = PR_SUCCESS;
  49.     SSMSSLSocketStatus *ss;
  50.     *res = NULL; /* in case we fail */
  51.     
  52.     ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus));
  53.     if (!ss) goto loser;
  54.     rv = SSMSSLSocketStatus_Init(ss, connection, 
  55.  (PRFileDesc *) arg, 
  56.                                  SSM_RESTYPE_SSL_SOCKET_STATUS);
  57.     if (rv != PR_SUCCESS) goto loser;
  58.     SSMSSLSocketStatus_Invariant(ss);
  59.     *res = &ss->super;
  60.     return PR_SUCCESS;
  61.  loser:
  62.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  63.     if (ss) 
  64.     {
  65.         SSMRESOURCE(ss)->m_refCount = 1; /* force destroy */
  66.         SSM_FreeResource(SSMRESOURCE(ss));
  67.     }
  68.         
  69.     return rv;
  70. }
  71. SSMStatus 
  72. SSMSSLSocketStatus_Init(SSMSSLSocketStatus *ss, 
  73.   SSMControlConnection * connection, 
  74.                         PRFileDesc *fd, SSMResourceType type)
  75. {
  76.     SSMStatus rv = PR_SUCCESS;
  77.     int keySize, secretKeySize, level;
  78.     SSMResource *certObj;
  79.     SSMResourceID certRID;
  80.     CERTCertificate *cert;
  81.     /* Initialize superclass */
  82.     SSMResource_Init(connection, SSMRESOURCE(ss), type);
  83.     /* Get the peer cert and import it into an NSM object */
  84.     cert = SSL_PeerCertificate(fd);
  85.     if (!cert) goto loser;
  86.     rv = SSM_CreateResource(SSM_RESTYPE_CERTIFICATE, cert, 
  87.                             SSMRESOURCE(ss)->m_connection, &certRID, 
  88.                             &certObj); 
  89.     if (rv != PR_SUCCESS) goto loser;
  90.     ss->m_cert = (SSMResourceCert*)certObj;
  91.     /* Get the other socket status information */
  92.     rv = SSL_SecurityStatus(fd, &level, &ss->m_cipherName,
  93.                             &keySize,
  94.                             &secretKeySize,
  95.                             NULL, NULL);
  96.     if (rv != PR_SUCCESS) goto loser;
  97.     ss->m_keySize = keySize;
  98.     ss->m_secretKeySize = secretKeySize;
  99.     ss->m_level = level;
  100.     /* Sanity check before returning */
  101.     SSMSSLSocketStatus_Invariant(ss);
  102.     
  103.     goto done;
  104. loser:
  105.     /* member destruct, if any are allocated, will happen in the
  106.        _Destroy method */
  107.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  108. done:
  109.     return rv;
  110. }
  111. SSMStatus 
  112. SSMSSLSocketStatus_Destroy(SSMResource *res, PRBool doFree)
  113. {
  114.     SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res;
  115.     SSMSSLSocketStatus_Invariant(ss);
  116.     /* Destroy our members. */
  117.     if (ss->m_cert)
  118.     {
  119.         SSM_FreeResource(&ss->m_cert->super);
  120.         ss->m_cert = NULL;
  121.     }
  122.     if (ss->m_cipherName)
  123.     {
  124.         PORT_Free(ss->m_cipherName);
  125.         ss->m_cipherName = NULL;
  126.     }
  127.     /* Destroy superclass. */
  128.     SSMResource_Destroy(res, PR_FALSE);
  129.     
  130.     /* Free if asked. */
  131.     if (doFree)
  132.         PR_Free(res);
  133.     return PR_SUCCESS;
  134. }
  135. void 
  136. SSMSSLSocketStatus_Invariant(SSMSSLSocketStatus *ss)
  137. {
  138.     /* Superclass invariant */
  139.     SSMResource_Invariant(SSMRESOURCE(ss));
  140.     
  141.     /* Class check */
  142.     PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(ss), SSM_RESTYPE_SSL_SOCKET_STATUS));
  143.     /* Member check */
  144. #if 0
  145.     /* Make sure we used a cert to initialize ourselves */
  146.     if (ss->m_cert)
  147.         PR_ASSERT(ss->m_cert != NULL);
  148. #endif
  149. }
  150. SSMStatus 
  151. SSMSSLSocketStatus_GetAttrIDs(SSMResource *res,
  152.                               SSMAttributeID **ids,
  153.                               PRIntn *count)
  154. {
  155.     SSMStatus rv;
  156.     rv = SSMResource_GetAttrIDs(res, ids, count);
  157.     if (rv != PR_SUCCESS)
  158.         goto loser;
  159.     *ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 4) * sizeof(SSMAttributeID));
  160.     if (! *ids) goto loser;
  161.     (*ids)[*count++] = SSM_FID_SSS_KEYSIZE;
  162.     (*ids)[*count++] = SSM_FID_SSS_SECRET_KEYSIZE;
  163.     (*ids)[*count++] = SSM_FID_SSS_CERT_ID;
  164.     (*ids)[*count++] = SSM_FID_SSS_CIPHER_NAME;
  165.     goto done;
  166.  loser:
  167.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  168.  done:
  169.     return rv;
  170. }
  171. SSMStatus 
  172. SSMSSLSocketStatus_GetAttr(SSMResource *res,
  173.                            SSMAttributeID attrID,
  174.                            SSMResourceAttrType attrType,
  175.                            SSMAttributeValue *value)
  176. {
  177.     SSMStatus rv = PR_SUCCESS;
  178.     SSMSSLSocketStatus *ss = (SSMSSLSocketStatus *) res;
  179.     char *tmpstr = NULL;
  180.     SSM_DEBUG("socket status get attr is called.n");
  181.     SSMSSLSocketStatus_Invariant(ss);
  182.     /* see what it is */
  183.     switch(attrID)
  184.     {
  185.     case SSM_FID_SSS_KEYSIZE: 
  186.         value->type = SSM_NUMERIC_ATTRIBUTE;
  187.         value->u.numeric = ss->m_keySize;
  188.         break;
  189.     case SSM_FID_SSS_SECRET_KEYSIZE:
  190.         value->type = SSM_NUMERIC_ATTRIBUTE;
  191.         value->u.numeric = ss->m_secretKeySize;
  192.         break;
  193.     case SSM_FID_SSS_CERT_ID:
  194.         value->type = SSM_RID_ATTRIBUTE;
  195.         value->u.numeric = ss->m_cert->super.m_id;
  196.         break;
  197.     case SSM_FID_SSS_SECURITY_LEVEL:
  198.         value->type = SSM_NUMERIC_ATTRIBUTE;
  199.         value->u.numeric = ss->m_level;
  200.         break;
  201.     case SSM_FID_SSS_CIPHER_NAME:
  202.         value->type = SSM_STRING_ATTRIBUTE;
  203.         value->u.string.len = PL_strlen(ss->m_cipherName);
  204.         value->u.string.data = (unsigned char *) PL_strdup(ss->m_cipherName);
  205.         break;
  206.     case SSM_FID_SSS_HTML_STATUS:
  207.         value->type = SSM_STRING_ATTRIBUTE;
  208.         rv = (*res->m_html_func)(res, NULL, (void**)&tmpstr);
  209.         value->u.string.len = PL_strlen(tmpstr);
  210.         value->u.string.data = (unsigned char *) PL_strdup(tmpstr);
  211.         break;
  212. case SSM_FID_SSS_CA_NAME:
  213. {
  214. char * caName = NULL;
  215. value->type = SSM_STRING_ATTRIBUTE;
  216. caName = CERT_GetOrgName(&ss->m_cert->cert->issuer);
  217. if (caName == NULL) {
  218. caName = PL_strdup("");
  219. }
  220. value->u.string.len = PL_strlen(caName);
  221. value->u.string.data = (unsigned char *)PL_strdup(caName);
  222. PR_FREEIF(caName);
  223. }
  224. break;
  225.     default:
  226.         rv = SSMResource_GetAttr(res,attrID,attrType,value);
  227.         if (rv != PR_SUCCESS)
  228.             goto loser;
  229.     }
  230.     goto done;
  231.  loser:
  232.     value->type = SSM_NO_ATTRIBUTE;
  233.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  234.  done:
  235.     if (tmpstr != NULL)
  236.         PR_Free(tmpstr);
  237.     return rv;
  238. }
  239. SSMStatus SSMSSLSocketStatus_Pickle(SSMResource *res, PRIntn * len,
  240.                                    void **value)
  241.     int blobSize, certSize;
  242.     SSMStatus rv;
  243.     SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res;
  244.     void * certBlob, *curptr, *tmpStr = NULL;
  245.     if (!res || !value) {
  246.         rv = PR_INVALID_ARGUMENT_ERROR;
  247.         goto loser;
  248.     }
  249.     /* in case we fail */
  250.     *value = NULL;
  251.     if (len) *len = 0;
  252. #if 0    
  253.     /* first, pickle cert */
  254.     rv = SSMControlConnection_GetResource(res->m_connection, 
  255.                                           resource->m_certID,
  256.                                           (SSMResource **)&certObj);
  257.     if (rv != PR_SUCCESS) goto loser;
  258. #endif
  259.     
  260.     rv = SSM_PickleResource(&resource->m_cert->super, &certSize, &certBlob); 
  261.     if (rv != PR_SUCCESS) 
  262.         goto loser;
  263.     
  264.     /* allocate memory for the pickled blob */
  265.     blobSize = certSize + sizeof(PRUint32)*5 + 
  266.         SSMSTRING_PADDED_LENGTH(strlen(resource->m_cipherName));
  267.     curptr = PORT_ZAlloc(blobSize);
  268.     if (!curptr) {
  269.         rv = PR_OUT_OF_MEMORY_ERROR;
  270.         goto loser;
  271.     }
  272.     *value = curptr;
  273.     *(PRUint32 *)curptr = resource->m_keySize;
  274.     curptr = (PRUint32 *)curptr + 1;
  275.     *(PRUint32 *)curptr = resource->m_secretKeySize;
  276.     curptr = (PRUint32 *)curptr + 1;
  277. *(PRInt32*)curptr = resource->m_level;
  278. curptr = (PRInt32 *)curptr + 1;
  279. *(PRInt32*)curptr = resource->m_error;
  280. curptr = (PRInt32 *)curptr + 1;
  281. rv = SSM_StringToSSMString((SSMString **)&tmpStr, 0, resource->m_cipherName);
  282.     if (rv != PR_SUCCESS) 
  283.         goto loser;
  284.     memcpy(curptr, tmpStr, SSM_SIZEOF_STRING(*(SSMString *)tmpStr));
  285.     curptr = (char *)curptr + SSM_SIZEOF_STRING(*(SSMString *)tmpStr);
  286.     PR_Free(tmpStr);
  287.     tmpStr = NULL;
  288.     /* copy cert into the blob */
  289.     memcpy(curptr, certBlob, certSize);
  290.     if (len) *len = blobSize;
  291.         
  292.     return rv;
  293.     
  294. loser:
  295.     if (rv == PR_SUCCESS)
  296.         rv = PR_FAILURE;
  297.     if (value && *value)
  298.         PR_Free(*value);
  299.     if (len) 
  300.         *len = 0;
  301.     if (tmpStr) 
  302.         PR_Free(tmpStr);
  303.     return rv;
  304. }
  305. SSMStatus SSMSSLSocketStatus_Unpickle(SSMResource ** res, 
  306.                                      SSMControlConnection * connection, 
  307.                                      PRInt32 len, 
  308.                                      void *value)
  309. {
  310.     SSMStatus rv = PR_SUCCESS;
  311.     SSMSSLSocketStatus *ss;
  312.     void * curptr = NULL;
  313.     PRUint32 strLength = 0, certLength = 0;
  314.     SSMResource * certResource = NULL;
  315.     if (!res || !value) {
  316.         rv = PR_INVALID_ARGUMENT_ERROR;
  317.         goto loser;
  318.     }
  319.     *res = NULL; /* in case we fail */
  320.     
  321.     ss = (SSMSSLSocketStatus *) PR_CALLOC(sizeof(SSMSSLSocketStatus));
  322.     if (!ss) goto loser;
  323.     ss->m_cipherName = NULL;
  324.     ss->m_cert = NULL;
  325.     /* Initialize superclass */
  326.     SSMResource_Init(connection, SSMRESOURCE(ss), 
  327.      SSM_RESTYPE_SSL_SOCKET_STATUS);
  328.     /* Unpickle socket status data */
  329.     curptr = value;
  330.     
  331.     ss->m_keySize = *(PRUint32 *)curptr;
  332.     curptr =(PRUint32 *)curptr + 1;  
  333.     ss->m_secretKeySize = *(PRUint32 *)curptr;
  334.     curptr =(PRUint32 *)curptr + 1; 
  335.     ss->m_level = *(PRInt32 *)curptr;
  336. curptr = (PRInt32 *)curptr + 1;
  337. ss->m_error = *(PRInt32 *)curptr;
  338. curptr = (PRInt32 *)curptr + 1;
  339.     /* Fix this */
  340.     rv = SSM_SSMStringToString(&ss->m_cipherName, (int *) &strLength, 
  341.                                (SSMString *)curptr);
  342.     if (rv != PR_SUCCESS || ss->m_cipherName == NULL || strLength == 0) 
  343.         goto loser;
  344.     curptr = (char *)curptr + SSMSTRING_PADDED_LENGTH(strLength) + 
  345.         sizeof(PRUint32);
  346.     
  347.     /* Unpickle cert */
  348.     certLength = len - ((unsigned long)curptr - (unsigned long)value);
  349.     rv = SSM_UnpickleResource(&certResource, SSM_RESTYPE_CERTIFICATE, 
  350.                               connection, certLength, curptr);
  351.     if (rv != PR_SUCCESS || !certResource)
  352.         goto loser;
  353. #if 0
  354.     ss->m_certID = certResource->m_id;
  355. #endif
  356.     ss->m_cert = (SSMResourceCert*)certResource; 
  357.     /* Sanity check before returning */
  358.     SSMSSLSocketStatus_Invariant(ss);
  359.     
  360.     *res = SSMRESOURCE(ss);
  361.     goto done;
  362.     
  363. loser:
  364.     if (ss) {
  365.         if (ss->m_cipherName)
  366.             PR_Free(ss->m_cipherName);
  367.         if (ss->m_cert) {
  368.             SSM_FreeResource(&ss->m_cert->super);
  369. #if 0
  370.             (*(certResource->m_destroy_func))(certResource, PR_TRUE);
  371. #endif
  372.         }
  373.         PR_Free(certResource);
  374.     }
  375.     if (rv == PR_SUCCESS) 
  376.         rv = PR_FAILURE;
  377. done: 
  378.     return rv;
  379. }
  380. SSMStatus SSMSSLSocketStatus_HTML(SSMResource *res, PRIntn *len, void ** value)
  381.     SSMStatus rv = PR_SUCCESS;
  382.     SSMSSLSocketStatus * resource = (SSMSSLSocketStatus *)res;
  383.     char * line = NULL;
  384.  
  385.     if (!res || !value) {
  386.         rv = PR_INVALID_ARGUMENT_ERROR;
  387.         goto loser;
  388.     }
  389.     if (len) *len = 0;
  390.     *value = NULL;
  391.     
  392.     switch (resource->m_level) {
  393.     case SSL_SECURITY_STATUS_ON_HIGH:
  394. #ifdef FORTEZZA
  395.     case SSL_SECURITY_STATUS_FORTEZZA:
  396. #endif
  397.         line = PR_smprintf("%s", SECURITY_HIGH_MESSAGE);
  398.         break;  
  399.     case SSL_SECURITY_STATUS_ON_LOW:
  400.         line = PR_smprintf("%s", SECURITY_LOW_MESSAGE);
  401.         break;
  402.     default:
  403.         *value = PR_smprintf("%s", SECURITY_NO_MESSAGE);
  404.         goto done;
  405.     }
  406.  
  407.     if (resource->m_keySize != resource->m_secretKeySize) {
  408.         *value = PR_smprintf("%s (%s, %d bit with %d secret).", line,
  409.                              resource->m_cipherName, 
  410.                              resource->m_keySize, 
  411.                              resource->m_secretKeySize);
  412.     } else {
  413.         *value = PR_smprintf("%s (%s, %d bit).", line, 
  414.                              resource->m_cipherName,
  415.                              resource->m_keySize);
  416.     }
  417.     
  418.     goto done;
  419. loser:
  420.     if (value && *value)
  421.         PR_Free(*value);
  422.     *value = NULL;
  423.     if (len && *len)
  424.         *len = 0;
  425.     if (rv == PR_SUCCESS) 
  426.         rv = PR_FAILURE;
  427. done:
  428.     if (value && *value && len) 
  429.         *len = strlen((char *)*value)+1;
  430.     if (line) 
  431.         PR_Free(line);
  432.     return rv;
  433. }
  434. SSMStatus SSMSSLSocketStatus_UpdateSecurityStatus(SSMSSLSocketStatus* ss,
  435.                                                  PRFileDesc* socket)
  436. {
  437.     SSMStatus rv = PR_SUCCESS;
  438.     int keySize, secretKeySize, level;
  439.     /* ss should not be NULL when this function is called */
  440.     PR_ASSERT(ss != NULL);
  441.     /* Get the security status information */
  442.     if (ss->m_cipherName != NULL) {
  443.         PR_Free(ss->m_cipherName);
  444.         ss->m_cipherName = NULL;
  445.     }
  446.     rv = SSL_SecurityStatus(socket, &level, &ss->m_cipherName, &keySize, 
  447.                             &secretKeySize, NULL, NULL);
  448.     if (rv != PR_SUCCESS) {
  449.         goto loser;
  450.     }
  451.     ss->m_keySize = keySize;
  452.     ss->m_secretKeySize = secretKeySize;
  453.     ss->m_level = level;
  454.     /* Sanity check before returning */
  455.     SSMSSLSocketStatus_Invariant(ss);
  456.     
  457.     goto done;
  458. loser:
  459.     if (rv == PR_SUCCESS) {
  460.         rv = PR_FAILURE;
  461.     }
  462.     if (ss->m_cipherName != NULL) {
  463.         PR_Free(ss->m_cipherName);
  464.         ss->m_cipherName = NULL;
  465.     }
  466. done:
  467.     return rv;
  468. }