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

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 "resource.h"
  35. #include "hashtbl.h"
  36. #include "collectn.h"
  37. #include "connect.h"
  38. #include "ctrlconn.h"
  39. #include "dataconn.h"
  40. #include "sslconn.h"
  41. #include "sslskst.h"
  42. #include "certres.h"
  43. #include "keyres.h"
  44. #include "crmfres.h"
  45. #include "p7dconn.h"
  46. #include "p7cinfo.h"
  47. #include "p7econn.h"
  48. #include "hashconn.h"
  49. #include "kgenctxt.h"
  50. #include "servimpl.h"
  51. #include "ssmerrs.h"
  52. #include "nlsutil.h"
  53. #include "advisor.h"
  54. #include "p12res.h"
  55. #include "signtextres.h"
  56. #include "sdrres.h"
  57. #include <stdarg.h>
  58. /* Type registration */
  59. struct SSMResourceClass
  60. {
  61.     /* The type of resource. */
  62.     SSMResourceType        m_classType;
  63.     SSMResourceType        m_superclass;
  64.     /* Name. */
  65.     char *                 m_className;
  66.     /* Data pertaining to each class. */
  67.     SSMClientDestroyAction m_clientDest;
  68.     
  69.     /* Accessor functions. */
  70.     SSMResourceCreateFunc  m_create_func;
  71.     SSMResourceDestroyFunc m_destroy_func;
  72.     SSMResourceShutdownFunc m_shutdown_func;
  73.     SSMResourceGetAttrIDsFunc m_getids_func;
  74.     SSMResourceGetAttrFunc m_get_func;
  75.     SSMResourceSetAttrFunc m_set_func;
  76.     SSMResourcePickleFunc m_pickle_func;
  77.     SSMResourceUnpickleFunc m_unpickle_func;
  78.     SSMResourceHTMLFunc m_html_func;
  79.     SSMResourcePrintFunc m_print_func;
  80.     SSMSubmitHandlerFunc m_submit_func;
  81. };
  82. SSMHashTable *ssm_classRegistry = NULL;
  83. /* Declarations to keep the compiler happy */
  84. SSMStatus SSM_FindResourceClass(SSMResourceType type, SSMResourceClass **cls);
  85. SSMStatus
  86. SSM_ResourceInit()
  87. {
  88.     SSMStatus rv = PR_SUCCESS;
  89.     
  90.     if (ssm_classRegistry == NULL)
  91.         {
  92.         rv = SSM_HashCreate(&ssm_classRegistry);
  93.         PR_ASSERT(ssm_classRegistry != NULL);
  94.         /* Register well-known types. 
  95.            Connection classes fall into this category. */
  96.         SSM_RegisterResourceType("Resource",
  97.                                  SSM_RESTYPE_RESOURCE,
  98.                                  SSM_RESTYPE_NULL,
  99.                                  SSM_CLIENTDEST_NOTHING,
  100.                                  SSMResource_Create,
  101.                                  SSMResource_Destroy,
  102.                                  SSMResource_Shutdown,
  103.                                  SSMResource_GetAttrIDs,
  104.                                  SSMResource_GetAttr,
  105.                                  SSMResource_SetAttr,
  106.                                  SSMResource_Pickle,
  107.                                  SSMResource_Unpickle,
  108.                                  SSMResource_HTML,
  109.                                  SSMResource_Print,
  110.                                  SSMResource_FormSubmitHandler);
  111.         SSM_RegisterResourceType("Connection",
  112.                                  SSM_RESTYPE_CONNECTION,
  113.                                  SSM_RESTYPE_RESOURCE,
  114.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  115.                                  SSMConnection_Create,
  116.                                  SSMConnection_Destroy,
  117.                                  SSMConnection_Shutdown,
  118.                                  SSMConnection_GetAttrIDs,
  119.                                  SSMConnection_GetAttr,
  120.                                  SSMConnection_SetAttr, 
  121.                                  NULL, 
  122.                                  NULL,
  123.                                  NULL,
  124.                                  NULL,
  125.                                  NULL);
  126.         SSM_RegisterResourceType("Control connection",
  127.                                  SSM_RESTYPE_CONTROL_CONNECTION,
  128.                                  SSM_RESTYPE_CONNECTION,
  129.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  130.                                  SSMControlConnection_Create,
  131.                                  SSMControlConnection_Destroy,
  132.                                  SSMControlConnection_Shutdown,
  133.                                  SSMControlConnection_GetAttrIDs,
  134.                                  SSMControlConnection_GetAttr,
  135.                                  NULL, 
  136.                                  NULL, 
  137.                                  NULL,
  138.                                  NULL,
  139.                                  NULL,
  140.                                  SSMControlConnection_FormSubmitHandler);
  141.         SSM_RegisterResourceType("Data connection",
  142.                                  SSM_RESTYPE_DATA_CONNECTION,
  143.                                  SSM_RESTYPE_CONNECTION,
  144.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  145.                                  SSMDataConnection_Create,
  146.                                  SSMDataConnection_Destroy,
  147.                                  SSMDataConnection_Shutdown,
  148.                                  SSMDataConnection_GetAttrIDs,
  149.                                  SSMDataConnection_GetAttr,
  150.                                  NULL, 
  151.                                  NULL, 
  152.                                  NULL,
  153.                                  NULL,
  154.                                  NULL,
  155.                                  NULL);
  156.         SSM_RegisterResourceType("SSL connection",
  157.                                  SSM_RESTYPE_SSL_DATA_CONNECTION,
  158.                                  SSM_RESTYPE_DATA_CONNECTION,
  159.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  160.                                  SSMSSLDataConnection_Create,
  161.                                  SSMSSLDataConnection_Destroy,
  162.                                  SSMSSLDataConnection_Shutdown,
  163.                                  SSMSSLDataConnection_GetAttrIDs,
  164.                                  SSMSSLDataConnection_GetAttr,
  165.                                  SSMSSLDataConnection_SetAttr,
  166.                                  NULL, 
  167.                                  NULL,
  168.                                  NULL,
  169.                                  NULL,
  170.                                  SSMSSLDataConnection_FormSubmitHandler);
  171.         SSM_RegisterResourceType("Hash connection",
  172.                                  SSM_RESTYPE_HASH_CONNECTION,
  173.                                  SSM_RESTYPE_DATA_CONNECTION,
  174.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  175.                                  SSMHashConnection_Create,
  176.                                  SSMHashConnection_Destroy,
  177.                                  SSMHashConnection_Shutdown,
  178.                                  SSMHashConnection_GetAttrIDs,
  179.                                  SSMHashConnection_GetAttr,
  180.                                  NULL,
  181.                                  NULL, 
  182.                                  NULL,
  183.                                  NULL,
  184.                                  NULL,
  185.                                  NULL);
  186.         SSM_RegisterResourceType("PKCS7 decode connection",
  187.                                  SSM_RESTYPE_PKCS7_DECODE_CONNECTION,
  188.                                  SSM_RESTYPE_DATA_CONNECTION,
  189.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  190.                                  SSMP7DecodeConnection_Create,
  191.                                  SSMP7DecodeConnection_Destroy,
  192.                                  SSMP7DecodeConnection_Shutdown,
  193.                                  SSMP7DecodeConnection_GetAttrIDs,
  194.                                  SSMP7DecodeConnection_GetAttr,
  195.                                  NULL,
  196.                                  NULL, 
  197.                                  NULL,
  198.                                  NULL,
  199.                                  NULL,
  200.                                  NULL);
  201.         SSM_RegisterResourceType("PKCS7 encode connection",
  202.                                  SSM_RESTYPE_PKCS7_ENCODE_CONNECTION,
  203.                                  SSM_RESTYPE_DATA_CONNECTION,
  204.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  205.                                  SSMP7EncodeConnection_Create,
  206.                                  SSMP7EncodeConnection_Destroy,
  207.                                  SSMP7EncodeConnection_Shutdown,
  208.                                  NULL,
  209.                                  SSMP7EncodeConnection_GetAttr,
  210.                                  SSMP7EncodeConnection_SetAttr,
  211.                                  NULL, 
  212.                                  NULL,
  213.                                  NULL,
  214.                                  NULL,
  215.                                  NULL);
  216.         SSM_RegisterResourceType("PKCS7 content info",
  217.                                  SSM_RESTYPE_PKCS7_CONTENT_INFO,
  218.                                  SSM_RESTYPE_RESOURCE,
  219.                                  SSM_CLIENTDEST_FREE, /* client destroy */
  220.                                  SSMP7ContentInfo_Create,
  221.                                  SSMP7ContentInfo_Destroy,
  222.                                  NULL,
  223.                                  SSMP7ContentInfo_GetAttrIDs,
  224.                                  SSMP7ContentInfo_GetAttr,
  225.                                  NULL,
  226.                                  NULL, 
  227.                                  NULL,
  228.                                  NULL,
  229.                                  NULL,
  230.                                  NULL);
  231.         SSM_RegisterResourceType("SSL socket status object",
  232.                                  SSM_RESTYPE_SSL_SOCKET_STATUS,
  233.                                  SSM_RESTYPE_RESOURCE,
  234.                                  SSM_CLIENTDEST_FREE, /* client destroy */
  235.                                  SSMSSLSocketStatus_Create,
  236.                                  SSMSSLSocketStatus_Destroy,
  237.                                  NULL,
  238.                                  SSMSSLSocketStatus_GetAttrIDs,
  239.                                  SSMSSLSocketStatus_GetAttr,
  240.                                  NULL,
  241.                                  SSMSSLSocketStatus_Pickle, 
  242.                                  SSMSSLSocketStatus_Unpickle,
  243.                                  SSMSSLSocketStatus_HTML,
  244.                                  NULL,
  245.                                  NULL);
  246.         SSM_RegisterResourceType("Certificate",
  247.                                  SSM_RESTYPE_CERTIFICATE,
  248.                                  SSM_RESTYPE_RESOURCE,
  249.                                  SSM_CLIENTDEST_FREE, /* client destroy */
  250.                                  SSMResourceCert_Create,
  251.                                  SSMResourceCert_Destroy,
  252.                                  NULL,
  253.                                  SSMResourceCert_GetAttrIDs,
  254.                                  SSMResourceCert_GetAttr,
  255.                                  NULL,
  256.                                  SSMResourceCert_Pickle, 
  257.                                  SSMResourceCert_Unpickle,
  258.                                  SSMResourceCert_HTML,
  259.                                  NULL,
  260.                                  SSMResourceCert_FormSubmitHandler);
  261.         SSM_RegisterResourceType("Key pair",
  262.                                  SSM_RESTYPE_KEY_PAIR,
  263.                                  SSM_RESTYPE_RESOURCE,
  264.                                  SSM_CLIENTDEST_FREE, /* client destroy */
  265.                                  SSMKeyPair_Create,
  266.                                  SSMKeyPair_Destroy,
  267.                                  NULL,
  268.                                  NULL,
  269.                                  NULL,
  270.                                  SSMKeyPair_SetAttr,
  271.                                  NULL,
  272.                                  NULL,
  273.                                  NULL,
  274.                                  NULL,
  275.                                  NULL);
  276.         SSM_RegisterResourceType("CRMF request",
  277.                                  SSM_RESTYPE_CRMF_REQUEST,
  278.                                  SSM_RESTYPE_RESOURCE,
  279.                                  SSM_CLIENTDEST_FREE, /* client destroy */
  280.                                  SSMCRMFRequest_Create,
  281.                                  SSMCRMFRequest_Destroy,
  282.                                  NULL,
  283.                                  NULL,
  284.                                  NULL,
  285.                                  SSMCRMFRequest_SetAttr,
  286.                                  NULL,
  287.                                  NULL,
  288.                                  NULL,
  289.                                  NULL,
  290.                                  NULL);
  291.         SSM_RegisterResourceType("Key gen context",
  292.                                  SSM_RESTYPE_KEYGEN_CONTEXT, /* type */
  293.                                  SSM_RESTYPE_RESOURCE, /* superclass */
  294.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  295.                                  SSMKeyGenContext_Create, /* create */
  296.                                  SSMKeyGenContext_Destroy, /* destroy */
  297.                                  SSMKeyGenContext_Shutdown, /* shutdown */
  298.                                  NULL, /* get attr IDs */
  299.                                  SSMKeyGenContext_GetAttr, /* get attr */
  300.                                  SSMKeyGenContext_SetAttr,
  301.                                  NULL, /* pickle */
  302.                                  NULL, /* unpickle */
  303.                                  NULL, /* HTML */
  304.                                  SSMKeyGenContext_Print, /* Print */
  305.                                  SSMKeyGenContext_FormSubmitHandler);
  306.         SSM_RegisterResourceType("Security advisor context",
  307.                                  SSM_RESTYPE_SECADVISOR_CONTEXT,
  308.                                  SSM_RESTYPE_RESOURCE,
  309.                                  SSM_CLIENTDEST_SHUTDOWN, /* client destroy */
  310.                                  NULL,
  311.                                  SSMSecurityAdvisorContext_Destroy,
  312.                                  NULL, 
  313.                                  SSMSecurityAdvisorContext_GetAttrIDs,
  314.                                  SSMSecurityAdvisorContext_GetAttr,
  315.                                  SSMSecurityAdvisorContext_SetAttr,
  316.                                  NULL, 
  317.                                  NULL,
  318.                                  NULL,
  319.                                  SSMSecurityAdvisorContext_Print,
  320.                                  SSMSecurityAdvisorContext_FormSubmitHandler);
  321.         SSM_RegisterResourceType("PKCS12 Context",
  322.                                  SSM_RESTYPE_PKCS12_CONTEXT,
  323.                                  SSM_RESTYPE_RESOURCE,
  324.                                  SSM_CLIENTDEST_FREE,
  325.                                  SSMPKCS12Context_Create,
  326.                                  SSMPKCS12Context_Destroy,
  327.                                  NULL,
  328.                                  NULL,
  329.                                  NULL,
  330.                                  NULL,
  331.                                  NULL,
  332.                                  NULL,
  333.                                  NULL,
  334.                                  SSMPKCS12Context_Print,
  335.                                  SSMPKCS12Context_FormSubmitHandler);
  336.         SSM_RegisterResourceType("SignText Context",
  337.                                  SSM_RESTYPE_SIGNTEXT,
  338.                                  SSM_RESTYPE_RESOURCE,
  339.                                  SSM_CLIENTDEST_FREE,
  340.                                  SSMSignTextResource_Create,
  341.                                  SSMSignTextResource_Destroy,
  342.                                  SSMSignTextResource_Shutdown,
  343.                                  NULL,
  344.                                  SSMSignTextResource_GetAttr,
  345.                                  NULL,
  346.                                  NULL,
  347.                                  NULL,
  348.                                  NULL,
  349.                                  SSMSignTextResource_Print,
  350.                                  SSMSignTextResource_FormSubmitHandler);
  351.         SSM_RegisterResourceType("SDR Context",
  352.                                  SSM_RESTYPE_SDR_CONTEXT,
  353.                                  SSM_RESTYPE_RESOURCE,
  354.                                  SSM_CLIENTDEST_FREE,
  355.                                  SSMSDRContext_Create,
  356.                                  SSMSDRContext_Destroy,
  357.                                  NULL,  /* Shutdown */
  358.                                  NULL,
  359.                                  NULL,
  360.                                  NULL,
  361.                                  NULL,
  362.                                  NULL,
  363.                                  NULL,
  364.                                  NULL,
  365.                                  SSMSDRContext_FormSubmitHandler);
  366.     }
  367.     
  368.     return rv;
  369. }
  370. SSMStatus
  371. SSMResource_Destroy(SSMResource *res, PRBool doFree)
  372. {
  373.     SSMStatus rv;
  374.     SSMResourceID tmpID;
  375.     /* We should have been called from a subclass destructor. */
  376.     PR_ASSERT(doFree == PR_FALSE);
  377.     SSM_DEBUG("Destroying %s (rid %ld).n", res->m_class->m_className, 
  378.               (long) res->m_id);
  379.     rv = SSM_HashRemove(res->m_connection->m_resourceDB, res->m_id,
  380.                         (void **) &res);
  381.     if (rv != PR_SUCCESS)
  382.         return PR_FAILURE;
  383.     rv = SSM_HashRemove(res->m_connection->m_resourceIdDB, (SSMHashKey)res,
  384.                         (void **) &tmpID);
  385.     if (rv != PR_SUCCESS)
  386.         return PR_FAILURE;
  387.     if (res->m_lock)
  388.     {
  389.         PR_DestroyMonitor(res->m_lock);
  390.         res->m_lock = NULL;
  391.     }
  392.     
  393.     if (res->m_UILock)
  394.     {
  395.         PR_DestroyMonitor(res->m_UILock);
  396.         res->m_UILock = NULL;
  397.     }
  398.     if (res->m_formName) {
  399.         PR_Free(res->m_formName);
  400.         res->m_formName = NULL;
  401.     }
  402.     
  403.     return PR_SUCCESS;
  404. }
  405. SSMStatus
  406. SSMResource_Init(SSMControlConnection * conn, SSMResource *res, 
  407.                  SSMResourceType type)
  408. {
  409.     SSMResourceClass *cls;
  410.     SSMStatus rv;
  411.     rv = SSM_FindResourceClass(type, &cls);
  412.     if (rv != PR_SUCCESS)
  413.         goto loser;
  414.     res->m_class = cls;
  415.     res->m_classType = type;
  416.     res->m_buttonType = SSM_BUTTON_NONE;
  417.     res->m_clientDest = cls->m_clientDest;
  418.     res->m_destroy_func = cls->m_destroy_func;
  419.     res->m_shutdown_func = cls->m_shutdown_func;
  420.     res->m_getids_func = cls->m_getids_func;
  421.     res->m_get_func = cls->m_get_func;
  422.     res->m_set_func = cls->m_set_func;
  423.     res->m_pickle_func = cls->m_pickle_func;
  424.     res->m_html_func = cls->m_html_func;
  425.     res->m_print_func = cls->m_print_func;
  426.     res->m_submit_func = cls->m_submit_func;
  427.     res->m_connection = conn;
  428.     res->m_lock = PR_NewMonitor();
  429.     if (!res->m_lock)
  430.         goto loser;
  431.     if (conn != NULL)
  432.         res->m_id = SSMControlConnection_GenerateResourceID(conn);
  433.     /* will create this monitor when needed */
  434.     res->m_UILock = NULL;
  435.     res->m_formName = NULL;
  436.     res->m_fileName = NULL;
  437.     res->m_clientContext.len = 0;
  438.     res->m_clientContext.data = NULL;
  439.     
  440.     res->m_clientCount = 0;
  441.     res->m_refCount = 1;
  442.     res->m_resourceShutdown = PR_FALSE;
  443.     SSM_DEBUG("Created %s with rid %ld.n", cls->m_className,
  444.               (long)res->m_id);
  445.     if (SSMControlConnection_AddResource(res, res->m_id) != PR_SUCCESS)
  446.         goto loser;
  447.     
  448.     return PR_SUCCESS;
  449.  loser:
  450.     if (rv == PR_SUCCESS)
  451.         rv = PR_FAILURE;
  452.     return rv;
  453. }
  454. SSMStatus
  455. SSM_FindResourceClass(SSMResourceType type, SSMResourceClass **cls)
  456. {
  457.     SSMStatus rv = PR_SUCCESS;
  458.     *cls = NULL; /* in case we fail */
  459.     PR_ASSERT(ssm_classRegistry != NULL);
  460.     rv = SSM_HashFind(ssm_classRegistry, type, (void **) cls);
  461.     return rv;
  462. }
  463. PRBool
  464. SSM_IsA(SSMResource *res, SSMResourceType type)
  465. {
  466.     return (res && (res->m_classType == type));
  467. }
  468. PRBool
  469. SSM_IsAKindOf(SSMResource *res, SSMResourceType type)
  470. {
  471.     PRBool result = PR_FALSE;
  472.     SSMResourceClass *cls;
  473.     if (!res) return PR_FALSE;
  474.     SSM_FindResourceClass( res->m_classType, &cls);
  475.     while (cls && (cls->m_classType != type))
  476.         SSM_FindResourceClass(cls->m_superclass, &cls);
  477.     result = (cls != NULL);
  478.     return result;
  479. }
  480. SSMStatus
  481. SSM_RegisterResourceType(char *name,
  482.                          SSMResourceType type,
  483.                          SSMResourceType superClass,
  484.                          SSMClientDestroyAction destAction,
  485.                          SSMResourceCreateFunc createFunc,
  486.                          SSMResourceDestroyFunc destFunc,
  487.                          SSMResourceShutdownFunc shutFunc,
  488.                          SSMResourceGetAttrIDsFunc getIDsFunc,
  489.                          SSMResourceGetAttrFunc getFunc,
  490.                          SSMResourceSetAttrFunc setFunc,
  491.                          SSMResourcePickleFunc  pickleFunc, 
  492.                          SSMResourceUnpickleFunc unpickleFunc,
  493.                          SSMResourceHTMLFunc    htmlFunc,
  494.                          SSMResourcePrintFunc   printFunc,
  495.                          SSMSubmitHandlerFunc   submitFunc)
  496. {
  497.     SSMResourceClass *cls, *super = NULL;
  498.     SSMStatus rv = PR_SUCCESS;
  499.     /* If a superclass was specified, find it. */
  500.     if (superClass)
  501.     {
  502.         rv = SSM_FindResourceClass(superClass, &super);
  503.         if (rv != PR_SUCCESS) goto loser;
  504.     }
  505.         
  506.     /* Create a new entry for the class. */
  507.     cls = (SSMResourceClass *) PR_CALLOC(sizeof(SSMResourceClass));
  508.     if (!cls) goto loser;
  509.     /* Start with the superclass' methods, then overlay the new ones. */
  510.     if (super)
  511.         (void) memcpy(cls, super, sizeof(SSMResourceClass));
  512.     cls->m_className = name;
  513.     cls->m_classType = type;
  514.     cls->m_superclass = superClass;
  515.     cls->m_clientDest = destAction;
  516.     if (createFunc != NULL)
  517.         cls->m_create_func = createFunc;
  518.     if (destFunc != NULL)
  519.         cls->m_destroy_func = destFunc;
  520.     if (shutFunc != NULL)
  521.         cls->m_shutdown_func = shutFunc;
  522.     if (getIDsFunc != NULL)
  523.         cls->m_getids_func = getIDsFunc;
  524.     if (getFunc != NULL)
  525.         cls->m_get_func = getFunc;
  526.     if (setFunc != NULL)
  527.         cls->m_set_func = setFunc;
  528.     if (pickleFunc != NULL)
  529.         cls->m_pickle_func = pickleFunc;
  530.     if (unpickleFunc != NULL) 
  531.         cls->m_unpickle_func = unpickleFunc;
  532.     if (htmlFunc != NULL)
  533.         cls->m_html_func = htmlFunc;
  534.     if (printFunc != NULL)
  535.         cls->m_print_func = printFunc;
  536.     if (submitFunc != NULL)
  537.         cls->m_submit_func = submitFunc;
  538.     rv = SSM_HashInsert(ssm_classRegistry, type, cls);
  539.     if (rv != PR_SUCCESS) goto loser;
  540.     return PR_SUCCESS;
  541.  loser:
  542.     if (rv == PR_SUCCESS) rv = PR_FAILURE;
  543.     if (cls) PR_Free(cls);
  544.     return rv;
  545. }
  546. SSMStatus
  547. SSM_CreateResource(SSMResourceType type, void *arg, 
  548.                    SSMControlConnection * connection,
  549.                    SSMResourceID *resID, SSMResource **result)
  550. {
  551.     SSMStatus rv;
  552.     SSMResourceClass *cls = NULL;
  553.     SSMResource *res = NULL;
  554.     
  555.     rv = SSM_FindResourceClass(type, &cls);
  556.     if (rv != PR_SUCCESS) goto loser;
  557.     PR_ASSERT(cls != NULL);
  558.     
  559.     /* Call the create function in this class. */
  560.     rv = (*cls->m_create_func)(arg, connection, &res);
  561.     if ((rv != PR_SUCCESS) && (rv != SSM_ERR_DEFER_RESPONSE))
  562.         goto loser;
  563.     *resID = res->m_id;
  564.     *result = res;
  565.     return rv;
  566.  loser:
  567.     if (res) 
  568.     {
  569.         res->m_refCount = 1; /* so that it is destroyed */
  570.         SSM_FreeResource(res);
  571.     }
  572.     return rv;
  573. }
  574. SSMStatus
  575. SSM_GetResourceReference(SSMResource *res)
  576. {
  577.     SSMResource_Invariant(res);
  578.     SSM_LockResource(res);
  579.     res->m_refCount++;
  580.     SSM_DEBUG("Get ref - rsrcid: %ld ++refcnt: %ldn", res->m_id, res->m_refCount);
  581.     switch (res->m_classType) {
  582.     case SSM_RESTYPE_CONTROL_CONNECTION:
  583.         SSM_DEBUG("Getting a reference for the control connectionn");
  584.         break;
  585.     default:
  586.         break;
  587.     }
  588.     SSM_UnlockResource(res);
  589.     return PR_SUCCESS;
  590. }
  591. SSMStatus
  592. SSM_FreeResource(SSMResource *res)
  593. {
  594.     PRIntn refcnt;
  595.     PR_ASSERT(res != NULL);
  596.     SSMResource_Invariant(res);
  597. PR_ASSERT(res->m_refCount > 0);
  598.     SSM_LockResource(res);
  599.     refcnt = --(res->m_refCount);
  600.     SSM_DEBUG("Free ref - rsrcid: %ld --refcnt: %ldn", res->m_id, res->m_refCount);
  601.     res->m_refCount = refcnt;
  602.     switch (res->m_classType) {
  603.     case SSM_RESTYPE_CONTROL_CONNECTION:
  604.         SSM_DEBUG("Giving up a reference to the control connectionn");
  605.         break;
  606.     default:
  607.         break;
  608.     }
  609.     SSM_UnlockResource(res);
  610.     /* need to handle race condition on destroy */
  611.     if (refcnt <= 0)
  612.     {
  613.         SSM_DEBUG("Destroying resource.n", 
  614.                                    refcnt);
  615.         return (*res->m_destroy_func)(res, PR_TRUE);
  616.     }
  617.     return PR_SUCCESS;
  618. }
  619. SSMStatus
  620. SSM_GetResAttribute(SSMResource *res, SSMAttributeID fieldID,
  621.                     SSMResourceAttrType attrType, SSMAttributeValue *value)
  622. {
  623.     PR_ASSERT(res != NULL);
  624.     SSMResource_Invariant(res);
  625.     return (*res->m_get_func)(res,fieldID,attrType,value);
  626. }
  627. SSMStatus
  628. SSM_SetResAttribute(SSMResource *res, SSMAttributeID fieldID,
  629.                     SSMAttributeValue *value)
  630. {
  631.     PR_ASSERT(res != NULL);
  632.     SSMResource_Invariant(res);
  633.     return (*res->m_set_func)(res,fieldID,value);
  634. }
  635. SSMStatus 
  636. SSM_PickleResource(SSMResource * res, PRIntn * len, void ** value)
  637. {
  638.     PR_ASSERT(res != NULL);
  639.     return(*res->m_pickle_func)(res, len, value);
  640. }
  641. SSMStatus 
  642. SSM_HTMLResource(SSMResource *res, PRIntn *len, void **value)
  643. {
  644.     PR_ASSERT(res != NULL);
  645.     return(*res->m_html_func)(res, len, value);
  646. }
  647. SSMStatus
  648. SSM_ClientGetResourceReference(SSMResource *res, SSMResourceID *id)
  649. {
  650.     SSM_LockResource(res);
  651.     res->m_clientCount++;
  652.     SSM_DEBUG("Get client ref - rsrcid: %ld ++clientcnt: %ldn",
  653.               res->m_id, res->m_clientCount);
  654.     SSM_GetResourceReference(res);
  655.     if (id)
  656.         *id = res->m_id;
  657.     SSM_UnlockResource(res);
  658.     return PR_SUCCESS;
  659. }
  660.   
  661. /*
  662.  * Unpickle function is similar to create function. Need the switch statement
  663.  * to call  
  664.  * Unpickle function for different resources.  
  665.  */  
  666. SSMStatus 
  667. SSM_UnpickleResource(SSMResource ** res, SSMResourceType type, 
  668.                      SSMControlConnection * connection,
  669.                      PRIntn len, void * value)
  670. {
  671.     SSMStatus rv = PR_SUCCESS;
  672.     PR_ASSERT(res != NULL);
  673.     if (!res || !value) {
  674.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  675.         goto loser;
  676.     }
  677.     *res = NULL; /* in case we fail */
  678.     switch (type) { 
  679.     case SSM_RESTYPE_CERTIFICATE:
  680.         rv = SSMResourceCert_Unpickle(res, connection, len, value);
  681.         break;
  682.     case SSM_RESTYPE_SSL_SOCKET_STATUS:
  683.         rv = SSMSSLSocketStatus_Unpickle(res, connection, len, value);
  684.         break;
  685.     case SSM_RESTYPE_HASH_CONNECTION:
  686.     case SSM_RESTYPE_PKCS7_DECODE_CONNECTION:
  687.     case SSM_RESTYPE_SSL_DATA_CONNECTION:
  688.     default:
  689.         rv = PR_FAILURE;
  690.     }
  691.     goto done;
  692. loser:
  693.     if (rv == PR_SUCCESS) 
  694.         rv = PR_FAILURE;
  695.     if (res && *res) {
  696.         PR_Free(*res);
  697.         *res = NULL;
  698.     }
  699. done:
  700.     return rv;
  701. }
  702. SSMStatus
  703. SSM_ShutdownResource(SSMResource *res, SSMStatus status)
  704. {
  705.     PR_ASSERT(res->m_shutdown_func);
  706.     if (res->m_shutdown_func)
  707.         return (*res->m_shutdown_func)(res, status);
  708.     else
  709.         return PR_FAILURE;
  710. }
  711. SSMStatus 
  712. SSM_ClientDestroyResource(SSMControlConnection * connection, 
  713.                           SSMResourceID rid, SSMResourceType objType)
  714. {
  715.     SSMStatus rv;
  716.     SSMResource *res = NULL;
  717.     PRIntn clientCount;
  718.     rv = SSMControlConnection_GetResource(connection, rid, &res);
  719.     if (rv != PR_SUCCESS)
  720.         goto done;
  721.     PR_ASSERT(res);
  722.     /* If the object is of the right type, free the reference. */
  723.     if (!SSM_IsAKindOf(res, objType))
  724.     {
  725.         rv = SSM_ERR_BAD_RESOURCE_TYPE;
  726.         goto done;
  727.     }
  728.     SSM_LockResource(res);
  729.     clientCount = --(res->m_clientCount);
  730.     SSM_DEBUG("Free client ref - rsrcid: %ld --clientcnt: %ldn",
  731.               res->m_id, res->m_clientCount);
  732.     /* Also release the resource that was added when the client got
  733.      * its resource
  734.      */
  735.     SSM_FreeResource(res);
  736.     PR_ASSERT(clientCount >= 0);
  737.     if((clientCount == 0)  && (res->m_threadCount > 0))
  738.     {
  739.         SSM_DEBUG("ClientDestroy: Shutting down resource %ld.n",
  740.                   (long)res->m_id);
  741.         rv = SSM_ShutdownResource(res, SSM_ERR_CLIENT_DESTROY);
  742.         if (rv != PR_SUCCESS)
  743.             goto locked_done;
  744.     }
  745. locked_done:
  746.     SSM_UnlockResource(res);
  747. done:
  748.     if (res != NULL)
  749.         rv = SSM_FreeResource(res);
  750.     SSM_DEBUG("ClientDestroy returning status %d.n", rv);
  751.     return rv;
  752. }
  753. SSMStatus 
  754. SSM_MessageFormatResource(SSMResource *res,
  755.                           char *fmt,
  756.                           PRIntn numParams,
  757.   char ** value,
  758.                           char **resultStr)
  759. {
  760.     SSMStatus rv = SSM_FAILURE;
  761.     if (res->m_print_func)
  762.         rv = (*(res->m_print_func))(res, fmt, numParams, value, resultStr);
  763.     return rv;
  764. }
  765. SSMStatus
  766. SSMResource_Shutdown(SSMResource *res, SSMStatus status)
  767. {
  768.     SSMStatus rv = PR_SUCCESS;
  769.     SSM_LockResource(res);
  770.     if ((res->m_status == PR_SUCCESS) || (res->m_status == SSM_ERR_CLIENT_DESTROY))
  771.     {
  772.         SSM_DEBUG("Shutting down %s with rid %ld. Status == %d.n", 
  773.                   res->m_class->m_className, 
  774.                   (long) res->m_id, status);
  775.         res->m_status = status;
  776.         /* If there is a thread waiting for us to shut down, notify it. */
  777.         if (res->m_waitThread)
  778.             SSM_NotifyResource(res);
  779.     }
  780.     else
  781.         rv = SSM_ERR_ALREADY_SHUT_DOWN;
  782.     res->m_resourceShutdown = PR_TRUE;
  783.     SSM_UnlockResource(res);
  784.     return rv;
  785. }
  786. void
  787. SSMResource_Invariant(SSMResource *res)
  788. {
  789. #ifdef DEBUG
  790.     if (res)
  791.     {
  792.         PR_ASSERT(res->m_id != 0);
  793.         PR_ASSERT(SSM_IsAKindOf(res, SSM_RESTYPE_RESOURCE));
  794.         PR_ASSERT(res->m_refCount >= 0);
  795.         PR_ASSERT(res->m_destroy_func != NULL);
  796.         PR_ASSERT(res->m_shutdown_func != NULL);
  797.         PR_ASSERT(res->m_getids_func != NULL);
  798.         PR_ASSERT(res->m_get_func != NULL);
  799.         PR_ASSERT(res->m_set_func != NULL);
  800.         PR_ASSERT(res->m_connection != NULL);
  801.     }
  802. #endif
  803. }
  804. SSMStatus
  805. SSMResource_Create(void *arg, SSMControlConnection * connection, 
  806.                    SSMResource **res)
  807. {
  808.     /* never instantiate a bare SSMResource */
  809.     *res = NULL;
  810.     return PR_FAILURE;
  811. }
  812. SSMStatus
  813. SSMResource_GetAttr(SSMResource *res,
  814.                     SSMAttributeID fieldID, 
  815.                     SSMResourceAttrType attrType,
  816.                     SSMAttributeValue *value)
  817. {
  818.     return SSM_ERR_BAD_ATTRIBUTE_ID;
  819. }
  820. SSMStatus
  821. SSMResource_GetAttrIDs(SSMResource *res,
  822.                        SSMAttributeID **ids,
  823.                        PRIntn *count)
  824. {
  825.     /* return 0 attributes */
  826.     *ids = (SSMAttributeID *) PR_CALLOC(0);
  827.     *count = 0;
  828.     return PR_SUCCESS;
  829. }
  830. SSMStatus
  831. SSMResource_SetAttr(SSMResource *res,
  832.                     SSMAttributeID attrID,
  833.                     SSMAttributeValue *value)
  834. {
  835.     return PR_FAILURE; /* nothing client-accessible in the base class */
  836. }
  837. SSMStatus
  838. SSMResource_Pickle(SSMResource *res, PRIntn * len, void **value)
  839. {
  840.     return PR_FAILURE;
  841. }
  842. SSMStatus
  843. SSMResource_Unpickle(SSMResource ** res, SSMControlConnection *conn,
  844.                      PRIntn len, void * value)
  845. {
  846.     return PR_FAILURE;
  847. }
  848. SSMStatus
  849. SSMResource_HTML(SSMResource *res, PRIntn * len, void ** value)
  850. {
  851.     return PR_FAILURE;
  852. }
  853. SSMStatus 
  854. SSMResource_Print(SSMResource   *res, char *fmt, PRIntn numParams, 
  855.   char ** value, char **resultStr)
  856. {
  857.     PR_ASSERT(res != NULL && fmt != NULL && resultStr != NULL);
  858.     if (numParams > 3) 
  859.       SSM_DEBUG("SSMResource_Print: too many parameters!n");
  860.     switch (numParams) {
  861.       case (3): 
  862.         *resultStr = PR_smprintf(fmt, res->m_id, *value, *(value+1),*(value+2));
  863.         break;
  864.       case (2): 
  865. *resultStr = PR_smprintf(fmt, res->m_id, *value, *(value+1));
  866.         break;
  867.       case (1):
  868.         *resultStr = PR_smprintf(fmt, res->m_id, *value);
  869.         break;
  870.       default:
  871.         *resultStr = PR_smprintf(fmt, res->m_id);
  872.     }
  873.     if (*resultStr == NULL) {
  874.         return PR_FAILURE;
  875.     }
  876.     return PR_SUCCESS;
  877. }
  878. SSMStatus
  879. SSMResource_FormSubmitHandler(SSMResource *res,
  880.                               HTTPRequest *req)
  881. {
  882.     return SSM_HTTPDefaultCommandHandler(req);
  883. }
  884. void
  885. SSM_LockResource(SSMResource *res)
  886. {
  887.     PR_EnterMonitor(res->m_lock);
  888. }
  889. SSMStatus
  890. SSM_UnlockResource(SSMResource *res)
  891. {
  892.     return PR_ExitMonitor(res->m_lock);
  893. }
  894. SSMStatus
  895. SSM_WaitResource(SSMResource *res, PRIntervalTime ticks)
  896. {
  897.     return PR_Wait(res->m_lock, ticks);
  898. }
  899. SSMStatus
  900. SSM_NotifyResource(SSMResource *res)
  901. {
  902.     return PR_Notify(res->m_lock);
  903. }
  904. /* 
  905.    Wait for a resource to shut down. 
  906.    ### mwelch We use WaitResource() in another context, namely where
  907.    data connections hand over a newly opened port number to their
  908.    control connections. Can we guard against the case where we have an
  909.    initializing data connection upon which a thread decides to wait for 
  910.    shutdown?
  911. */
  912. SSMStatus
  913. SSM_WaitForResourceShutdown(SSMResource *res)
  914. {
  915.     SSMStatus rv = PR_SUCCESS;
  916.     SSM_LockResource(res);
  917.     PR_ASSERT(res->m_waitThread == NULL);
  918.     if (res->m_waitThread)
  919.         rv = PR_FAILURE;
  920.     else if (!res->m_resourceShutdown)
  921.     {
  922.         res->m_waitThread = PR_GetCurrentThread();
  923.         do 
  924.             SSM_WaitResource(res, PR_INTERVAL_NO_TIMEOUT);
  925.         while (res->m_threadCount > 0);
  926.         res->m_waitThread = NULL;
  927.     } 
  928.     else 
  929.     {
  930.         rv = SSM_ERR_ALREADY_SHUT_DOWN;
  931.     }
  932.     
  933.     SSM_UnlockResource(res);
  934.     return rv;
  935. }
  936. char * 
  937. SSM_ResourceClassName(SSMResource *res)
  938. {
  939.     return res->m_class->m_className;
  940. }
  941. void SSM_LockUIEvent(SSMResource * res)
  942. {
  943.   if (res->m_UILock == NULL)
  944.     res->m_UILock = PR_NewMonitor();
  945.   PR_ASSERT(res->m_UILock);
  946.   PR_EnterMonitor(res->m_UILock);
  947. }
  948. SSMStatus SSM_UnlockUIEvent(SSMResource *res)
  949. {
  950.   PR_ASSERT(res->m_UILock);
  951.   if (res->m_UILock != NULL) {
  952.     return PR_ExitMonitor(res->m_UILock);
  953.   }
  954.   return PR_FAILURE;
  955. }
  956. SSMStatus SSM_WaitUIEvent(SSMResource * res, PRIntervalTime ticks)
  957.   PR_ASSERT(res->m_UILock);
  958.   if (res->m_UILock)
  959.     {
  960.      res->m_UIBoolean = PR_FALSE;
  961.      while (!res->m_UIBoolean)
  962.        PR_Wait(res->m_UILock, ticks);
  963.      return PR_ExitMonitor(res->m_UILock);
  964.     }
  965.   /* if we used UILock once, chances are we'll need it again? */
  966.   return PR_FAILURE;
  967. }
  968. SSMStatus SSM_NotifyUIEvent(SSMResource * res)
  969. {
  970.   SSMStatus rv = PR_FAILURE;
  971.   PR_ASSERT(res->m_UILock);
  972.   if (res->m_UILock)
  973.     {
  974.      PR_EnterMonitor(res->m_UILock);
  975.      res->m_UIBoolean = PR_TRUE;
  976.      rv =PR_Notify(res->m_UILock);
  977.      PR_ExitMonitor(res->m_UILock);
  978.     }
  979.   return rv;
  980. }
  981. SSMStatus SSM_WaitForOKCancelEvent(SSMResource *res, PRIntervalTime ticks)
  982. {
  983.   PRStatus rv;
  984.   if (res->m_UILock == NULL) {
  985.     /* We might have been waken up by a spurious notify,
  986.      * so we don't allocate a new monitor every time.
  987.      */
  988.     res->m_UILock = PR_NewMonitor();
  989.   }
  990.   PR_EnterMonitor(res->m_UILock);
  991.   rv = PR_Wait(res->m_UILock, ticks);
  992.   PR_ExitMonitor(res->m_UILock);
  993.   return rv;
  994. }
  995. SSMStatus SSM_NotifyOKCancelEvent(SSMResource *res)
  996. {
  997.   SSMStatus rv = PR_FAILURE;
  998.   if (res->m_UILock) {
  999.     PR_EnterMonitor(res->m_UILock);
  1000.     rv = PR_Notify(res->m_UILock);
  1001.     PR_ExitMonitor(res->m_UILock);
  1002.   }
  1003.   return rv;
  1004. }
  1005. SSMStatus
  1006. SSM_HandlePromptReply(SSMResource *res, char *reply)
  1007. {
  1008.     /* Currently, only SSMPKCS12Context supports this, 
  1009.      * perhaps in the future we'll add more general support.
  1010.      */
  1011.     if (!SSM_IsAKindOf(res, SSM_RESTYPE_PKCS12_CONTEXT)) {
  1012.         return PR_FAILURE;
  1013.     }
  1014.     return SSMPKCS12Context_ProcessPromptReply(res, reply);
  1015. }
  1016. PRThread *
  1017. SSM_CreateThread(SSMResource *res, void (*func)(void *arg))
  1018. {
  1019.     PRThread *thd = NULL;
  1020.     PR_ASSERT(res != NULL);
  1021.     PR_ASSERT(func != NULL);
  1022.     SSM_LockResource(res);
  1023.     thd = SSM_CreateAndRegisterThread(PR_USER_THREAD, 
  1024.                           func, 
  1025.                           (void *)res, 
  1026.                           PR_PRIORITY_NORMAL,
  1027.                           PR_LOCAL_THREAD,
  1028.                           PR_UNJOINABLE_THREAD, 0);
  1029.     if (thd) {
  1030.         res->m_threadCount++;
  1031.     }
  1032.     SSM_UnlockResource(res);
  1033.     return thd;
  1034. }