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

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 "connect.h"
  35. #include "ssmerrs.h"
  36. #include "ctrlconn.h"
  37. #include "prinrval.h"
  38. #include "crmf.h"
  39. #define SSMRESOURCE(conn) (&(conn)->super)
  40. /* 
  41.    ssm_ConnectionCreate creates an SSMConnection object. 
  42.    The value argument is ignored.
  43. */
  44. SSMStatus
  45. SSMConnection_Create(void *arg, SSMControlConnection * connection, 
  46.                      SSMResource **res)
  47. {
  48.     SSMStatus rv = PR_SUCCESS;
  49.     SSMConnection *conn;
  50.     SSMControlConnection * owner;
  51.     *res = NULL; /* in case we fail */
  52.     
  53.     conn = (SSMConnection *) PR_CALLOC(sizeof(SSMConnection));
  54.     if (!conn) 
  55.        goto loser;
  56.     if (connection) 
  57.         owner = connection;
  58.     else 
  59.         owner = (SSMControlConnection *)conn;
  60.     rv = SSMConnection_Init(owner, (SSMConnection *) arg, 
  61.                             SSM_RESTYPE_CONNECTION);
  62.     if (rv != PR_SUCCESS) goto loser;
  63.     SSMConnection_Invariant(conn);
  64.     
  65.     *res = &conn->super;
  66.     return PR_SUCCESS;
  67.  loser:
  68.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  69.     if (conn) 
  70.     {
  71. SSM_ShutdownResource(SSMRESOURCE(conn), rv);
  72.       
  73.         SSM_FreeResource(&conn->super);
  74.     }
  75.         
  76.     return rv;
  77. }
  78. /* As a sanity check, make sure we have data structures consistent
  79.    with our type. */
  80. void SSMConnection_Invariant(SSMConnection *conn)
  81. {
  82. #ifdef DEBUG
  83.     if (conn)
  84.     {
  85.         SSMResource_Invariant(&(conn->super));
  86.         SSM_LockResource(SSMRESOURCE(conn));
  87.         PR_ASSERT(SSM_IsAKindOf(SSMRESOURCE(conn), SSM_RESTYPE_CONNECTION));
  88.         PR_ASSERT(conn->m_children != NULL);
  89.         SSM_UnlockResource(SSMRESOURCE(conn));
  90. #if 0
  91.         if (conntype == SSM_DATA_CONNECTION)
  92.         {
  93.             PR_ASSERT(!conn->m_children);
  94.             PR_ASSERT(!conn->m_readThread);
  95.             PR_ASSERT(!conn->m_writeThread);
  96.             PR_ASSERT(!conn->m_controlOutQ);
  97.         }
  98.         else /* control connection */
  99.         {
  100.             PR_ASSERT(conn->m_children);
  101.             PR_ASSERT(!conn->m_readClientThread);
  102.             PR_ASSERT(!conn->m_writeClientThread);
  103.             PR_ASSERT(!conn->m_readTargetThread);
  104.             PR_ASSERT(!conn->m_writeTargetThread);
  105.             PR_ASSERT(!conn->m_incomingQ);
  106.             PR_ASSERT(!conn->m_outgoingQ);
  107.             PR_ASSERT(conn->m_resourceID == 0);
  108.         }
  109. #endif
  110.     }
  111. #endif
  112. }
  113. SSMStatus
  114. SSMConnection_DetachChild(SSMConnection *parent, SSMConnection *child)
  115. {
  116.     SSMStatus rv;
  117.     SSM_LockResource(&parent->super);
  118.     /* Remove the child from the parent's collection of children. */
  119.     rv = SSM_Remove(parent->m_children, child);
  120.     child->m_parent = NULL;
  121.     /* If the parent is detaching (due to destruction), free the child. */
  122.     if (&parent->super.m_refCount == 0)
  123.         SSM_FreeResource(&child->super); 
  124.     SSM_UnlockResource(&parent->super);
  125.     return rv;
  126. }
  127. SSMStatus
  128. SSMConnection_AttachChild(SSMConnection *parent, SSMConnection *child)
  129. {
  130.     SSMStatus rv;
  131.     SSM_LockResource(&parent->super);
  132.     rv = SSM_Insert(parent->m_children, SSM_PRIORITY_NORMAL, child, NULL);
  133.     SSM_UnlockResource(&parent->super);
  134.     return rv;
  135. }
  136. SSMStatus
  137. SSMConnection_Shutdown(SSMResource *res, SSMStatus status)
  138. {
  139.     SSMConnection *conn = (SSMConnection *) res;
  140.     SSMStatus rv;
  141.     SSM_LockResource(SSMRESOURCE(conn));
  142.     rv = SSMResource_Shutdown(res, status);
  143.     if (SSMRESOURCE(conn)->m_threadCount == 0)
  144.     {
  145.         SSMConnection *child;
  146.         /* Shut down child connections. */
  147.         SSM_Dequeue(conn->m_children, SSM_PRIORITY_ANY, 
  148.                     (void **) &child, PR_FALSE);
  149.         while(child != NULL)
  150.         {
  151.             SSM_ShutdownResource(&child->super, (SSMStatus) PR_PENDING_INTERRUPT_ERROR);
  152.             SSMConnection_DetachChild(conn, child);
  153.             child = NULL;
  154.         }
  155.     }
  156.     SSM_UnlockResource(SSMRESOURCE(conn));
  157.     
  158.     return rv;
  159. }
  160. SSMStatus
  161. SSMConnection_Destroy(SSMResource *res, PRBool doFree)
  162. {
  163.     SSMStatus rv = PR_SUCCESS;
  164.     
  165.     SSMConnection *conn = (SSMConnection *) res;
  166.     SSMResource *child = NULL;
  167.     /* Destroy the collection of child connections. */
  168.     if (conn->m_children)
  169.     {
  170.         /* Detach all children. */
  171.         do
  172.         {
  173.             SSM_Dequeue(conn->m_children, SSM_PRIORITY_ANY,
  174.                         (void **) &child, PR_FALSE);
  175.             if (child && (child != SSMRESOURCE(conn)))
  176.             {
  177.                 SSM_DEBUG("Freeing child connection %lx.n",
  178.                           (unsigned long) child);
  179. SSM_FreeResource(child);
  180.             }
  181.         }
  182.         while (child != NULL);
  183.         PR_ASSERT(SSM_Count(conn->m_children) == 0);
  184.         SSM_DestroyCollection(conn->m_children);
  185.     }
  186.     /* If we're attached to a parent, detach from the parent's collection. */
  187.     if (conn->m_parent)
  188.         SSMConnection_DetachChild(conn->m_parent, conn);
  189.     SSMResource_Destroy(res, PR_FALSE);
  190.     if (doFree) {
  191.         PR_Free(res);
  192.     }
  193.     return rv;
  194. }
  195. SSMStatus
  196. SSMConnection_GetAttrIDs(SSMResource *res,
  197.                          SSMAttributeID **ids,
  198.                          PRIntn *count)
  199. {
  200.     SSMStatus rv;
  201.     rv = SSMResource_GetAttrIDs(res, ids, count);
  202.     if (rv != PR_SUCCESS)
  203.         goto loser;
  204.     *ids = (SSMAttributeID *) PR_REALLOC(*ids, (*count + 2) * sizeof(SSMResourceID));
  205.     if (! *ids) goto loser;
  206.     (*ids)[*count++] = SSM_FID_CONN_ALIVE;
  207.     (*ids)[*count++] = SSM_FID_CONN_PARENT;
  208.     goto done;
  209.  loser:
  210.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  211.  done:
  212.     return rv;
  213. }
  214. SSMStatus
  215. SSMConnection_GetAttr(SSMResource *res,
  216.                       SSMAttributeID attrID, 
  217.                       SSMResourceAttrType attrType,
  218.                       SSMAttributeValue *value)
  219. {
  220.     SSMConnection *conn = (SSMConnection *) res;
  221.     SSMStatus rv = PR_SUCCESS;
  222.     /* see what it is */
  223.     switch(attrID)
  224.     {
  225.     case SSM_FID_CONN_ALIVE:
  226.         value->u.numeric = (PRUint32) (conn->super.m_threadCount > 0);
  227.         value->type = SSM_NUMERIC_ATTRIBUTE;
  228.         break;
  229.     case SSM_FID_CONN_PARENT:
  230.         rv = SSM_ClientGetResourceReference(SSMRESOURCE(conn->m_parent),
  231.                                             &value->u.rid);
  232.         value->type = SSM_RID_ATTRIBUTE;
  233.         break;
  234.     default:
  235.         rv = SSMResource_GetAttr(res,attrID,attrType,value);
  236.         if (rv != PR_SUCCESS)
  237.             goto loser;
  238.     }
  239.  loser:
  240.     return rv;
  241. }
  242. SSMStatus
  243. SSMConnection_SetAttr(SSMResource *res,
  244.                       SSMAttributeID attrID,
  245.                       SSMAttributeValue *value)
  246. {
  247.     SSMStatus rv;
  248.     /* we own nothing, defer to superclass */
  249. rv = SSMResource_SetAttr(res,attrID,value);
  250.     return rv;
  251. }
  252. SSMStatus
  253. SSMConnection_Init(SSMControlConnection *ctrl, SSMConnection *connection, 
  254. SSMResourceType type)
  255. {
  256.     SSMStatus rv = PR_SUCCESS;
  257.     SSMControlConnection * owner;
  258.     if (type == SSM_RESTYPE_CONTROL_CONNECTION) 
  259. owner = (SSMControlConnection *)connection;
  260.     else owner = ctrl;
  261.     rv = SSMResource_Init(owner, &connection->super, type);
  262.     if (rv != PR_SUCCESS) goto loser;
  263.     /* Attach ourselves to the parent first, then set the member */
  264.     if (ctrl != NULL) {
  265.         rv = SSMConnection_AttachChild(&(ctrl->super), connection);
  266.         if (rv != PR_SUCCESS) 
  267.             goto loser;
  268.     }
  269.     connection->m_parent = &(ctrl->super);
  270.    
  271.     
  272.     connection->m_children = SSM_NewCollection();
  273.     if (!connection->m_children) goto loser;
  274.     /* hang our hooks */
  275. connection->m_auth_func = SSMConnection_Authenticate;
  276.     return PR_SUCCESS;
  277.  loser:
  278.     if (rv == PR_SUCCESS)
  279.         rv = PR_FAILURE;
  280.     return rv;
  281. }
  282. SSMStatus SSMConnection_Authenticate(SSMConnection *conn, char *nonce)
  283. {
  284. /* Abstract method, report failure by default */
  285. return SSM_FAILURE;
  286. }
  287. /* Given a RID and a proposed nonce, see if the connection exists
  288.    and if the nonce matches. */
  289. SSMStatus SSM_AuthenticateConnection(SSMControlConnection * ctrl, 
  290.                                      SSMResourceID rid, char *nonce)
  291. {
  292. SSMResource *obj = NULL;
  293. SSMConnection *conn;
  294.     SSMStatus rv;
  295. /* Find the connection object. */
  296. rv = (SSMStatus) SSMControlConnection_GetResource(ctrl, rid, &obj);
  297. if (rv != SSM_SUCCESS)
  298. goto loser;
  299. PR_ASSERT(obj);
  300. SSM_LockResource(obj);
  301. if (!SSM_IsAKindOf(obj, SSM_RESTYPE_CONNECTION))
  302. goto loser;
  303. conn = (SSMConnection *) obj;
  304. if (!conn->m_auth_func)
  305. goto loser;
  306. rv = (*conn->m_auth_func)(conn, nonce);
  307. goto done;
  308.  loser:
  309. if (rv == SSM_SUCCESS) rv = SSM_FAILURE;
  310.  done:
  311. if (obj) SSM_UnlockResource(obj);
  312. return rv;
  313. }