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

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * Implementation of OCSP services, for both client and server.
  35.  * (XXX, really, mostly just for client right now, but intended to do both.)
  36.  *
  37.  * $Id: ocsp.c,v 1.1 2000/03/31 19:43:00 relyea%netscape.com Exp $
  38.  */
  39. #include "prerror.h"
  40. #include "prprf.h"
  41. #include "plarena.h"
  42. #include "prnetdb.h"
  43. #include "seccomon.h"
  44. #include "secitem.h"
  45. #include "secoidt.h"
  46. #include "secasn1.h"
  47. #include "secder.h"
  48. #include "cert.h"
  49. #include "xconst.h"
  50. #include "secerr.h"
  51. #include "secoid.h"
  52. #include "hasht.h"
  53. #include "sechash.h"
  54. #include "secasn1.h"
  55. #include "keyhi.h"
  56. #include "cryptohi.h"
  57. #include "ocsp.h"
  58. #include "ocspti.h"
  59. #include "genname.h"
  60. #include "certxutl.h"
  61. #include "pk11func.h" /* for PK11_HashBuf */
  62. #include <stdarg.h>
  63. /*
  64.  * The following structure is only used internally.  It is allocated when
  65.  * someone turns on OCSP checking, and hangs off of the status-configuration
  66.  * structure in the certdb structure.  We use it to keep configuration
  67.  * information specific to OCSP checking.
  68.  */
  69. typedef struct ocspCheckingContextStr {
  70.     PRBool useDefaultResponder;
  71.     char *defaultResponderURI;
  72.     char *defaultResponderNickname;
  73.     CERTCertificate *defaultResponderCert;
  74. } ocspCheckingContext;
  75. /*
  76.  * Forward declarations of sub-types, so I can lay out the types in the
  77.  * same order as the ASN.1 is laid out in the OCSP spec itself.
  78.  *
  79.  * These are in alphabetical order (case-insensitive); please keep it that way!
  80.  */
  81. extern const SEC_ASN1Template ocsp_CertIDTemplate[];
  82. extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[];
  83. extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[];
  84. extern const SEC_ASN1Template ocsp_ResponseDataTemplate[];
  85. extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[];
  86. extern const SEC_ASN1Template ocsp_SingleRequestTemplate[];
  87. extern const SEC_ASN1Template ocsp_SingleResponseTemplate[];
  88. extern const SEC_ASN1Template ocsp_TBSRequestTemplate[];
  89. /*
  90.  * Request-related templates...
  91.  */
  92. /*
  93.  * OCSPRequest ::= SEQUENCE {
  94.  * tbsRequest TBSRequest,
  95.  * optionalSignature [0] EXPLICIT Signature OPTIONAL }
  96.  */
  97. static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = {
  98.     { SEC_ASN1_SEQUENCE,
  99. 0, NULL, sizeof(CERTOCSPRequest) },
  100.     { SEC_ASN1_POINTER,
  101. offsetof(CERTOCSPRequest, tbsRequest),
  102. ocsp_TBSRequestTemplate },
  103.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  104.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  105. offsetof(CERTOCSPRequest, optionalSignature),
  106. ocsp_PointerToSignatureTemplate },
  107.     { 0 }
  108. };
  109. /*
  110.  * TBSRequest ::= SEQUENCE {
  111.  * version [0] EXPLICIT Version DEFAULT v1,
  112.  * requestorName [1] EXPLICIT GeneralName OPTIONAL,
  113.  * requestList SEQUENCE OF Request,
  114.  * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
  115.  *
  116.  * Version ::= INTEGER { v1(0) }
  117.  *
  118.  * Note: this should be static but the AIX compiler doesn't like it (because it
  119.  * was forward-declared above); it is not meant to be exported, but this
  120.  * is the only way it will compile.
  121.  */
  122. const SEC_ASN1Template ocsp_TBSRequestTemplate[] = {
  123.     { SEC_ASN1_SEQUENCE,
  124. 0, NULL, sizeof(ocspTBSRequest) },
  125.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
  126.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  127. offsetof(ocspTBSRequest, version),
  128. SEC_IntegerTemplate },
  129.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  130.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  131. offsetof(ocspTBSRequest, derRequestorName),
  132. SEC_PointerToAnyTemplate },
  133.     { SEC_ASN1_SEQUENCE_OF,
  134. offsetof(ocspTBSRequest, requestList),
  135. ocsp_SingleRequestTemplate },
  136.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  137.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
  138. offsetof(ocspTBSRequest, requestExtensions),
  139. CERT_SequenceOfCertExtensionTemplate },
  140.     { 0 }
  141. };
  142. /*
  143.  * Signature ::= SEQUENCE {
  144.  * signatureAlgorithm AlgorithmIdentifier,
  145.  * signature BIT STRING,
  146.  * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
  147.  */
  148. static const SEC_ASN1Template ocsp_SignatureTemplate[] = {
  149.     { SEC_ASN1_SEQUENCE,
  150. 0, NULL, sizeof(ocspSignature) },
  151.     { SEC_ASN1_INLINE,
  152. offsetof(ocspSignature, signatureAlgorithm),
  153. SECOID_AlgorithmIDTemplate },
  154.     { SEC_ASN1_BIT_STRING,
  155. offsetof(ocspSignature, signature) },
  156.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  157.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  158. offsetof(ocspSignature, derCerts), 
  159. SEC_SequenceOfAnyTemplate },
  160.     { 0 }
  161. };
  162. /*
  163.  * This template is just an extra level to use in an explicitly-tagged
  164.  * reference to a Signature.
  165.  *
  166.  * Note: this should be static but the AIX compiler doesn't like it (because it
  167.  * was forward-declared above); it is not meant to be exported, but this
  168.  * is the only way it will compile.
  169.  */
  170. const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = {
  171.     { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate }
  172. };
  173. /*
  174.  * Request ::= SEQUENCE {
  175.  * reqCert CertID,
  176.  * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
  177.  *
  178.  * Note: this should be static but the AIX compiler doesn't like it (because it
  179.  * was forward-declared above); it is not meant to be exported, but this
  180.  * is the only way it will compile.
  181.  */
  182. const SEC_ASN1Template ocsp_SingleRequestTemplate[] = {
  183.     { SEC_ASN1_SEQUENCE, 
  184. 0, NULL, sizeof(ocspSingleRequest) },
  185.     { SEC_ASN1_POINTER,
  186. offsetof(ocspSingleRequest, reqCert),
  187. ocsp_CertIDTemplate },
  188.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  189.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  190. offsetof(ocspSingleRequest, singleRequestExtensions),
  191. CERT_SequenceOfCertExtensionTemplate },
  192.     { 0 }
  193. };
  194. /*
  195.  * This data structure and template (CertID) is used by both OCSP
  196.  * requests and responses.  It is the only one that is shared.
  197.  *
  198.  * CertID ::= SEQUENCE {
  199.  * hashAlgorithm AlgorithmIdentifier,
  200.  * issuerNameHash OCTET STRING, -- Hash of Issuer DN
  201.  * issuerKeyHash OCTET STRING, -- Hash of Issuer public key
  202.  * serialNumber CertificateSerialNumber }
  203.  *
  204.  * CertificateSerialNumber ::= INTEGER
  205.  *
  206.  * Note: this should be static but the AIX compiler doesn't like it (because it
  207.  * was forward-declared above); it is not meant to be exported, but this
  208.  * is the only way it will compile.
  209.  */
  210. const SEC_ASN1Template ocsp_CertIDTemplate[] = {
  211.     { SEC_ASN1_SEQUENCE, 
  212. 0, NULL, sizeof(CERTOCSPCertID) },
  213.     { SEC_ASN1_INLINE,
  214. offsetof(CERTOCSPCertID, hashAlgorithm),
  215. SECOID_AlgorithmIDTemplate },
  216.     { SEC_ASN1_OCTET_STRING,
  217. offsetof(CERTOCSPCertID, issuerNameHash) },
  218.     { SEC_ASN1_OCTET_STRING,
  219. offsetof(CERTOCSPCertID, issuerKeyHash) },
  220.     { SEC_ASN1_INTEGER, 
  221. offsetof(CERTOCSPCertID, serialNumber) },
  222.     { 0 }
  223. };
  224. /*
  225.  * Response-related templates...
  226.  */
  227. /*
  228.  * OCSPResponse ::= SEQUENCE {
  229.  * responseStatus OCSPResponseStatus,
  230.  * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
  231.  */
  232. static const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = {
  233.     { SEC_ASN1_SEQUENCE, 
  234. 0, NULL, sizeof(CERTOCSPResponse) },
  235.     { SEC_ASN1_ENUMERATED, 
  236. offsetof(CERTOCSPResponse, responseStatus) },
  237.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  238.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  239. offsetof(CERTOCSPResponse, responseBytes),
  240. ocsp_PointerToResponseBytesTemplate },
  241.     { 0 }
  242. };
  243. /*
  244.  * ResponseBytes ::= SEQUENCE {
  245.  * responseType OBJECT IDENTIFIER,
  246.  * response OCTET STRING }
  247.  */
  248. static const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = {
  249.     { SEC_ASN1_SEQUENCE,
  250. 0, NULL, sizeof(ocspResponseBytes) },
  251.     { SEC_ASN1_OBJECT_ID,
  252. offsetof(ocspResponseBytes, responseType) },
  253.     { SEC_ASN1_OCTET_STRING,
  254. offsetof(ocspResponseBytes, response) },
  255.     { 0 }
  256. };
  257. /*
  258.  * This template is just an extra level to use in an explicitly-tagged
  259.  * reference to a ResponseBytes.
  260.  *
  261.  * Note: this should be static but the AIX compiler doesn't like it (because it
  262.  * was forward-declared above); it is not meant to be exported, but this
  263.  * is the only way it will compile.
  264.  */
  265. const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = {
  266.     { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate }
  267. };
  268. /*
  269.  * BasicOCSPResponse ::= SEQUENCE {
  270.  * tbsResponseData ResponseData,
  271.  * signatureAlgorithm AlgorithmIdentifier,
  272.  * signature BIT STRING,
  273.  * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
  274.  */
  275. static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = {
  276.     { SEC_ASN1_SEQUENCE,
  277. 0, NULL, sizeof(ocspBasicOCSPResponse) },
  278.     { SEC_ASN1_POINTER,
  279. offsetof(ocspBasicOCSPResponse, tbsResponseData),
  280. ocsp_ResponseDataTemplate },
  281.     { SEC_ASN1_INLINE,
  282. offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
  283. SECOID_AlgorithmIDTemplate },
  284.     { SEC_ASN1_BIT_STRING,
  285. offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
  286.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  287.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  288. offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
  289. SEC_SequenceOfAnyTemplate },
  290.     { 0 }
  291. };
  292. /*
  293.  * ResponseData ::= SEQUENCE {
  294.  * version [0] EXPLICIT Version DEFAULT v1,
  295.  * responderID ResponderID,
  296.  * producedAt GeneralizedTime,
  297.  * responses SEQUENCE OF SingleResponse,
  298.  * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
  299.  *
  300.  * Note: this should be static but the AIX compiler doesn't like it (because it
  301.  * was forward-declared above); it is not meant to be exported, but this
  302.  * is the only way it will compile.
  303.  */
  304. const SEC_ASN1Template ocsp_ResponseDataTemplate[] = {
  305.     { SEC_ASN1_SEQUENCE,
  306. 0, NULL, sizeof(ocspResponseData) },
  307.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
  308.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  309. offsetof(ocspResponseData, version),
  310. SEC_IntegerTemplate },
  311.     { SEC_ASN1_ANY,
  312. offsetof(ocspResponseData, derResponderID) },
  313.     { SEC_ASN1_GENERALIZED_TIME,
  314. offsetof(ocspResponseData, producedAt) },
  315.     { SEC_ASN1_SEQUENCE_OF,
  316. offsetof(ocspResponseData, responses),
  317. ocsp_SingleResponseTemplate },
  318.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  319.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  320. offsetof(ocspResponseData, responseExtensions),
  321. CERT_SequenceOfCertExtensionTemplate },
  322.     { 0 }
  323. };
  324. /*
  325.  * ResponderID ::= CHOICE {
  326.  * byName [1] EXPLICIT Name,
  327.  * byKey [2] EXPLICIT KeyHash }
  328.  *
  329.  * KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
  330.  * (excluding the tag and length fields)
  331.  *
  332.  * XXX Because the ASN.1 encoder and decoder currently do not provide
  333.  * a way to automatically handle a CHOICE, we need to do it in two
  334.  * steps, looking at the type tag and feeding the exact choice back
  335.  * to the ASN.1 code.  Hopefully that will change someday and this
  336.  * can all be simplified down into a single template.  Anyway, for
  337.  * now we list each choice as its own template:
  338.  */
  339. static const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = {
  340.     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  341. offsetof(ocspResponderID, responderIDValue.name),
  342. CERT_NameTemplate }
  343. };
  344. static const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = {
  345.     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
  346. offsetof(ocspResponderID, responderIDValue.keyHash),
  347. SEC_OctetStringTemplate }
  348. };
  349. static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = {
  350.     { SEC_ASN1_ANY,
  351. offsetof(ocspResponderID, responderIDValue.other) }
  352. };
  353. /*
  354.  * SingleResponse ::= SEQUENCE {
  355.  * certID CertID,
  356.  * certStatus CertStatus,
  357.  * thisUpdate GeneralizedTime,
  358.  * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
  359.  * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
  360.  *
  361.  * Note: this should be static but the AIX compiler doesn't like it (because it
  362.  * was forward-declared above); it is not meant to be exported, but this
  363.  * is the only way it will compile.
  364.  */
  365. const SEC_ASN1Template ocsp_SingleResponseTemplate[] = {
  366.     { SEC_ASN1_SEQUENCE,
  367. 0, NULL, sizeof(CERTOCSPSingleResponse) },
  368.     { SEC_ASN1_POINTER,
  369. offsetof(CERTOCSPSingleResponse, certID),
  370. ocsp_CertIDTemplate },
  371.     { SEC_ASN1_ANY,
  372. offsetof(CERTOCSPSingleResponse, derCertStatus) },
  373.     { SEC_ASN1_GENERALIZED_TIME,
  374. offsetof(CERTOCSPSingleResponse, thisUpdate) },
  375.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  376.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  377. offsetof(CERTOCSPSingleResponse, nextUpdate),
  378. SEC_PointerToGeneralizedTimeTemplate },
  379.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  380.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
  381. offsetof(CERTOCSPSingleResponse, singleExtensions),
  382. CERT_SequenceOfCertExtensionTemplate },
  383.     { 0 }
  384. };
  385. /*
  386.  * CertStatus ::= CHOICE {
  387.  * good [0] IMPLICIT NULL,
  388.  * revoked [1] IMPLICIT RevokedInfo,
  389.  * unknown [2] IMPLICIT UnknownInfo }
  390.  *
  391.  * Because the ASN.1 encoder and decoder currently do not provide
  392.  * a way to automatically handle a CHOICE, we need to do it in two
  393.  * steps, looking at the type tag and feeding the exact choice back
  394.  * to the ASN.1 code.  Hopefully that will change someday and this
  395.  * can all be simplified down into a single template.  Anyway, for
  396.  * now we list each choice as its own template:
  397.  */
  398. static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = {
  399.     { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  400. offsetof(ocspCertStatus, certStatusInfo.goodInfo),
  401. SEC_NullTemplate }
  402. };
  403. static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = {
  404.     { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
  405. offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
  406. ocsp_RevokedInfoTemplate }
  407. };
  408. static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = {
  409.     { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 2,
  410. offsetof(ocspCertStatus, certStatusInfo.unknownInfo),
  411. SEC_NullTemplate }
  412. };
  413. static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = {
  414.     { SEC_ASN1_POINTER,
  415. offsetof(ocspCertStatus, certStatusInfo.otherInfo),
  416. SEC_AnyTemplate }
  417. };
  418. /*
  419.  * RevokedInfo ::= SEQUENCE {
  420.  * revocationTime GeneralizedTime,
  421.  * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
  422.  *
  423.  * Note: this should be static but the AIX compiler doesn't like it (because it
  424.  * was forward-declared above); it is not meant to be exported, but this
  425.  * is the only way it will compile.
  426.  */
  427. const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = {
  428.     { SEC_ASN1_SEQUENCE,
  429. 0, NULL, sizeof(ocspRevokedInfo) },
  430.     { SEC_ASN1_GENERALIZED_TIME,
  431. offsetof(ocspRevokedInfo, revocationTime) },
  432.     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
  433.       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
  434. offsetof(ocspRevokedInfo, revocationReason), 
  435. SEC_PointerToEnumeratedTemplate },
  436.     { 0 }
  437. };
  438. /*
  439.  * OCSP-specific extension templates:
  440.  */
  441. /*
  442.  * ServiceLocator ::= SEQUENCE {
  443.  * issuer Name,
  444.  * locator AuthorityInfoAccessSyntax OPTIONAL }
  445.  */
  446. static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = {
  447.     { SEC_ASN1_SEQUENCE,
  448. 0, NULL, sizeof(ocspServiceLocator) },
  449.     { SEC_ASN1_POINTER,
  450. offsetof(ocspServiceLocator, issuer),
  451. CERT_NameTemplate },
  452.     { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
  453. offsetof(ocspServiceLocator, locator) },
  454.     { 0 }
  455. };
  456. /*
  457.  * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy):
  458.  */
  459. /* 
  460.  * FUNCTION: CERT_EncodeOCSPRequest
  461.  *   DER encodes an OCSP Request, possibly adding a signature as well.
  462.  *   XXX Signing is not yet supported, however; see comments in code.
  463.  * INPUTS: 
  464.  *   PRArenaPool *arena
  465.  *     The return value is allocated from here.
  466.  *     If a NULL is passed in, allocation is done from the heap instead.
  467.  *   CERTOCSPRequest *request
  468.  *     The request to be encoded.
  469.  *   void *pwArg
  470.  *     Pointer to argument for password prompting, if needed.  (Definitely
  471.  *     not needed if not signing.)
  472.  * RETURN:
  473.  *   Returns a NULL on error and a pointer to the SECItem with the
  474.  *   encoded value otherwise.  Any error is likely to be low-level
  475.  *   (e.g. no memory).
  476.  */
  477. SECItem *
  478. CERT_EncodeOCSPRequest(PRArenaPool *arena, CERTOCSPRequest *request, 
  479.        void *pwArg)
  480. {
  481.     ocspTBSRequest *tbsRequest;
  482.     SECStatus rv;
  483.     /* XXX All of these should generate errors if they fail. */
  484.     PORT_Assert(request);
  485.     PORT_Assert(request->tbsRequest);
  486.     tbsRequest = request->tbsRequest;
  487.     if (request->tbsRequest->extensionHandle != NULL) {
  488. rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle);
  489. request->tbsRequest->extensionHandle = NULL;
  490. if (rv != SECSuccess)
  491.     return NULL;
  492.     }
  493.     /*
  494.      * XXX When signed requests are supported and request->optionalSignature
  495.      * is not NULL:
  496.      *  - need to encode tbsRequest->requestorName
  497.      *  - need to encode tbsRequest
  498.      *  - need to sign that encoded result (using cert in sig), filling in the
  499.      *    request->optionalSignature structure with the result, the signing
  500.      *    algorithm and (perhaps?) the cert (and its chain?) in derCerts
  501.      */
  502.     return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate);
  503. }
  504. /*
  505.  * FUNCTION: CERT_DecodeOCSPRequest
  506.  *   Decode a DER encoded OCSP Request.
  507.  * INPUTS:
  508.  *   SECItem *src
  509.  *     Pointer to a SECItem holding DER encoded OCSP Request.
  510.  * RETURN:
  511.  *   Returns a pointer to a CERTOCSPRequest containing the decoded request.
  512.  *   On error, returns NULL.  Most likely error is trouble decoding
  513.  *   (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory).
  514.  */
  515. CERTOCSPRequest *
  516. CERT_DecodeOCSPRequest(SECItem *src)
  517. {
  518.     PRArenaPool *arena = NULL;
  519.     SECStatus rv = SECFailure;
  520.     CERTOCSPRequest *dest = NULL;
  521.     int i;
  522.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  523.     if (arena == NULL) {
  524. goto loser;
  525.     }
  526.     dest = (CERTOCSPRequest *) PORT_ArenaZAlloc(arena, 
  527. sizeof(CERTOCSPRequest));
  528.     if (dest == NULL) {
  529. goto loser;
  530.     }
  531.     dest->arena = arena;
  532.     rv = SEC_ASN1DecodeItem(arena, dest, ocsp_OCSPRequestTemplate, src);
  533.     if (rv != SECSuccess) {
  534. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  535.     PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
  536. goto loser;
  537.     }
  538.     /*
  539.      * XXX I would like to find a way to get rid of the necessity
  540.      * of doing this copying of the arena pointer.
  541.      */
  542.     for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) {
  543. dest->tbsRequest->requestList[i]->arena = arena;
  544.     }
  545.     return dest;
  546. loser:
  547.     if (arena != NULL) {
  548. PORT_FreeArena(arena, PR_FALSE);
  549.     }
  550.     return NULL;
  551. }
  552. /*
  553.  * Create and fill-in a CertID.  This function fills in the hash values
  554.  * (issuerNameHash and issuerKeyHash), and is hardwired to use SHA1.
  555.  * Someday it might need to be more flexible about hash algorithm, but
  556.  * for now we have no intention/need to create anything else, and until
  557.  * we have more flexible underlying interfaces, it's just not as easy
  558.  * as it should be to just take an algorithm id and call some helper
  559.  * functions to do all the work (no algid->length translation, no function
  560.  * to hash from and into a SECItem, etc.).
  561.  *
  562.  * Error causes a null to be returned; most likely cause is trouble
  563.  * finding the certificate issuer (SEC_ERROR_UNKNOWN_ISSUER).
  564.  * Other errors are low-level problems (no memory, bad database, etc.).
  565.  */
  566. static CERTOCSPCertID *
  567. ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time)
  568. {
  569.     CERTOCSPCertID *certID;
  570.     CERTCertificate *issuerCert = NULL;
  571.     SECItem *tempItem = NULL;
  572.     void *mark = PORT_ArenaMark(arena);
  573.     SECStatus rv;
  574.     PORT_Assert(arena != NULL);
  575.     certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
  576.     if (certID == NULL) {
  577. goto loser;
  578.     }
  579.     rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
  580.        NULL);
  581.     if (rv != SECSuccess) {
  582. goto loser; 
  583.     }
  584.     issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
  585.     if (issuerCert == NULL) {
  586. goto loser;
  587.     }
  588.     tempItem = SEC_ASN1EncodeItem(NULL, NULL, &issuerCert->subject,
  589.   CERT_NameTemplate);
  590.     if (tempItem == NULL) {
  591. goto loser;
  592.     }
  593.     if (SECITEM_AllocItem(arena, &(certID->issuerNameHash),
  594.   SHA1_LENGTH) == NULL) {
  595. goto loser;
  596.     }
  597.     rv = PK11_HashBuf(SEC_OID_SHA1, certID->issuerNameHash.data,
  598.       tempItem->data, tempItem->len);
  599.     if (rv != SECSuccess) {
  600. goto loser; 
  601.     }
  602.     SECITEM_FreeItem(tempItem, PR_TRUE);
  603.     tempItem = NULL;
  604.     if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_SHA1,
  605.    &(certID->issuerKeyHash)) == NULL) {
  606. goto loser;
  607.     }
  608.     /* now we are done with issuerCert */
  609.     CERT_DestroyCertificate(issuerCert);
  610.     issuerCert = NULL;
  611.     rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber);
  612.     if (rv != SECSuccess) {
  613. goto loser; 
  614.     }
  615.     PORT_ArenaUnmark(arena, mark);
  616.     return certID;
  617. loser:
  618.     if (issuerCert != NULL) {
  619. CERT_DestroyCertificate(issuerCert);
  620.     }
  621.     if (tempItem != NULL) {
  622. SECITEM_FreeItem(tempItem, PR_TRUE);
  623.     }
  624.     PORT_ArenaRelease(arena, mark);
  625.     return NULL;
  626. }
  627. /*
  628.  * Callback to set Extensions in request object
  629.  */
  630. void SetSingleReqExts(void *object, CERTCertExtension **exts)
  631. {
  632.   ocspSingleRequest *singleRequest =
  633.     (ocspSingleRequest *)object;
  634.   singleRequest->singleRequestExtensions = exts;
  635. }
  636. /*
  637.  * Add the Service Locator extension to the singleRequestExtensions
  638.  * for the given singleRequest.
  639.  *
  640.  * All errors are internal or low-level problems (e.g. no memory).
  641.  */
  642. static SECStatus
  643. ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest,
  644. CERTCertificate *cert)
  645. {
  646.     ocspServiceLocator *serviceLocator = NULL;
  647.     void *extensionHandle = NULL;
  648.     SECStatus rv = SECFailure;
  649.     serviceLocator = PORT_ZNew(ocspServiceLocator);
  650.     if (serviceLocator == NULL)
  651. goto loser;
  652.     /*
  653.      * Normally it would be a bad idea to do a direct reference like
  654.      * this rather than allocate and copy the name *or* at least dup
  655.      * a reference of the cert.  But all we need is to be able to read
  656.      * the issuer name during the encoding we are about to do, so a
  657.      * copy is just a waste of time.
  658.      */
  659.     serviceLocator->issuer = &cert->issuer;
  660.     rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
  661. &serviceLocator->locator);
  662.     if (rv != SECSuccess) {
  663. if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
  664.     goto loser;
  665.     }
  666.     /* prepare for following loser gotos */
  667.     rv = SECFailure;
  668.     extensionHandle = cert_StartExtensions(singleRequest,
  669.                        singleRequest->arena, SetSingleReqExts);
  670.     if (extensionHandle == NULL)
  671. goto loser;
  672.     rv = CERT_EncodeAndAddExtension(extensionHandle,
  673.     SEC_OID_PKIX_OCSP_SERVICE_LOCATOR,
  674.     serviceLocator, PR_FALSE,
  675.     ocsp_ServiceLocatorTemplate);
  676. loser:
  677.     if (extensionHandle != NULL) {
  678. /*
  679.  * Either way we have to finish out the extension context (so it gets
  680.  * freed).  But careful not to override any already-set bad status.
  681.  */
  682. SECStatus tmprv = CERT_FinishExtensions(extensionHandle);
  683. if (rv == SECSuccess)
  684.     rv = tmprv;
  685.     }
  686.     /*
  687.      * Finally, free the serviceLocator structure itself and we are done.
  688.      */
  689.     if (serviceLocator != NULL) {
  690. if (serviceLocator->locator.data != NULL)
  691.     SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE);
  692. PORT_Free(serviceLocator);
  693.     }
  694.     return rv;
  695. }
  696. /*
  697.  * Creates an array of ocspSingleRequest based on a list of certs.
  698.  * Note that the code which later compares the request list with the
  699.  * response expects this array to be in the exact same order as the
  700.  * certs are found in the list.  It would be harder to change that
  701.  * order than preserve it, but since the requirement is not obvious,
  702.  * it deserves to be mentioned.
  703.  *
  704.  * Any problem causes a null return and error set:
  705.  * SEC_ERROR_UNKNOWN_ISSUER
  706.  * Other errors are low-level problems (no memory, bad database, etc.).
  707.  */
  708. static ocspSingleRequest **
  709. ocsp_CreateSingleRequestList(PRArenaPool *arena, CERTCertList *certList,
  710.      int64 time, PRBool includeLocator)
  711. {
  712.     ocspSingleRequest **requestList = NULL;
  713.     CERTCertListNode *node;
  714.     int i, count;
  715.     void *mark = PORT_ArenaMark(arena);
  716.  
  717.     node = CERT_LIST_HEAD(certList);
  718.     for (count = 0; !CERT_LIST_END(node, certList); count++) {
  719. node = CERT_LIST_NEXT(node);
  720.     }
  721.     if (count == 0)
  722. goto loser;
  723.     requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1);
  724.     if (requestList == NULL)
  725. goto loser;
  726.     node = CERT_LIST_HEAD(certList);
  727.     for (i = 0; !CERT_LIST_END(node, certList); i++) {
  728.         requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest);
  729. if (requestList[i] == NULL)
  730.     goto loser;
  731. requestList[i]->arena = arena;
  732. requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
  733. if (requestList[i]->reqCert == NULL)
  734.     goto loser;
  735. if (includeLocator == PR_TRUE) {
  736.     SECStatus rv;
  737.     rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
  738.     if (rv != SECSuccess)
  739. goto loser;
  740. }
  741. node = CERT_LIST_NEXT(node);
  742.     }
  743.     PORT_Assert(i == count);
  744.     PORT_ArenaUnmark(arena, mark);
  745.     requestList[i] = NULL;
  746.     return requestList;
  747. loser:
  748.     PORT_ArenaRelease(arena, mark);
  749.     return NULL;
  750. }
  751. /*
  752.  * FUNCTION: CERT_CreateOCSPRequest
  753.  *   Creates a CERTOCSPRequest, requesting the status of the certs in 
  754.  *   the given list.
  755.  * INPUTS:
  756.  *   CERTCertList *certList
  757.  *     A list of certs for which status will be requested.
  758.  *     Note that all of these certificates should have the same issuer,
  759.  *     or it's expected the response will be signed by a trusted responder.
  760.  *     If the certs need to be broken up into multiple requests, that
  761.  *     must be handled by the caller (and thus by having multiple calls
  762.  *     to this routine), who knows about where the request(s) are being
  763.  *     sent and whether there are any trusted responders in place.
  764.  *   int64 time
  765.  *     Indicates the time for which the certificate status is to be 
  766.  *     determined -- this may be used in the search for the cert's issuer
  767.  *     but has no effect on the request itself.
  768.  *   PRBool addServiceLocator
  769.  *     If true, the Service Locator extension should be added to the
  770.  *     single request(s) for each cert.
  771.  *   CERTCertificate *signerCert
  772.  *     If non-NULL, means sign the request using this cert.  Otherwise,
  773.  *     do not sign.
  774.  *     XXX note that request signing is not yet supported; see comment in code
  775.  * RETURN:
  776.  *   A pointer to a CERTOCSPRequest structure containing an OCSP request
  777.  *   for the cert list.  On error, null is returned, with an error set
  778.  *   indicating the reason.  This is likely SEC_ERROR_UNKNOWN_ISSUER.
  779.  *   (The issuer is needed to create a request for the certificate.)
  780.  *   Other errors are low-level problems (no memory, bad database, etc.).
  781.  */
  782. CERTOCSPRequest *
  783. CERT_CreateOCSPRequest(CERTCertList *certList, int64 time, 
  784.        PRBool addServiceLocator,
  785.        CERTCertificate *signerCert)
  786. {
  787.     PRArenaPool *arena = NULL;
  788.     CERTOCSPRequest *request = NULL;
  789.     ocspTBSRequest *tbsRequest = NULL;
  790.     /*
  791.      * XXX This should set an error, but since it is only temporary and
  792.      * since PSM will not initially provide a way to turn on signing of
  793.      * requests anyway, I figure we can just skip defining an error that
  794.      * will be obsolete in the next release.  When we are prepared to
  795.      * put signing of requests back in, this entire check will go away,
  796.      * and later in this function we will need to allocate a signature
  797.      * structure for the request, fill in the "derCerts" field in it,
  798.      * save the signerCert there, as well as fill in the "requestorName"
  799.      * field of the tbsRequest.
  800.      */
  801.     if (signerCert != NULL) {
  802. return NULL;
  803.     }
  804.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  805.     if (arena == NULL) {
  806. goto loser;
  807.     }
  808.     request = PORT_ArenaZNew(arena, CERTOCSPRequest);
  809.     if (request == NULL) {
  810. goto loser;
  811.     }
  812.     request->arena = arena;
  813.     tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
  814.     if (tbsRequest == NULL) {
  815. goto loser;
  816.     }
  817.     request->tbsRequest = tbsRequest;
  818.     /* version 1 is the default, so we need not fill in a version number */
  819.     /*
  820.      * Now create the list of single requests, one for each cert.
  821.      */
  822.     tbsRequest->requestList = ocsp_CreateSingleRequestList(arena, certList,
  823.    time,
  824.    addServiceLocator);
  825.     if (tbsRequest->requestList == NULL) {
  826. goto loser;
  827.     }
  828.     return request;
  829. loser:
  830.     if (arena != NULL) {
  831. PORT_FreeArena(arena, PR_FALSE);
  832.     }
  833.     return NULL;
  834. }
  835. /*
  836.  * FUNCTION: CERT_AddOCSPAcceptableResponses
  837.  *   Add the AcceptableResponses extension to an OCSP Request.
  838.  * INPUTS:
  839.  *   CERTOCSPRequest *request
  840.  *     The request to which the extension should be added.
  841.  *   ...
  842.  *     A list (of one or more) of SECOidTag -- each of the response types
  843.  *     to be added.  The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE.
  844.  *     (This marks the end of the list, and it must be specified because a
  845.  *     client conforming to the OCSP standard is required to handle the basic
  846.  *     response type.)  The OIDs are not checked in any way.
  847.  * RETURN:
  848.  *   SECSuccess if the extension is added; SECFailure if anything goes wrong.
  849.  *   All errors are internal or low-level problems (e.g. no memory).
  850.  */
  851. void SetRequestExts(void *object, CERTCertExtension **exts)
  852. {
  853.   CERTOCSPRequest *request = (CERTOCSPRequest *)object;
  854.   request->tbsRequest->requestExtensions = exts;
  855. }
  856. SECStatus
  857. CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request, ...)
  858. {
  859.     void *extHandle;
  860.     va_list ap;
  861.     int i, count;
  862.     SECOidTag responseType;
  863.     SECOidData *responseOid;
  864.     SECItem **acceptableResponses = NULL;
  865.     SECStatus rv = SECFailure;
  866.     extHandle = request->tbsRequest->extensionHandle;
  867.     if (extHandle == NULL) {
  868. extHandle = cert_StartExtensions(request, request->arena, SetRequestExts);
  869. if (extHandle == NULL)
  870.     goto loser;
  871.     }
  872.     /* Count number of OIDS going into the extension value. */
  873.     count = 0;
  874.     va_start(ap, request);
  875.     do {
  876. count++;
  877. responseType = va_arg(ap, SECOidTag);
  878.     } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  879.     va_end(ap);
  880.     acceptableResponses = PORT_NewArray(SECItem *, count + 1);
  881.     if (acceptableResponses == NULL)
  882. goto loser;
  883.     va_start(ap, request);
  884.     for (i = 0; i < count; i++) {
  885. responseType = va_arg(ap, SECOidTag);
  886. responseOid = SECOID_FindOIDByTag(responseType);
  887. acceptableResponses[i] = &(responseOid->oid);
  888.     }
  889.     va_end(ap);
  890.     acceptableResponses[i] = NULL;
  891.     rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE,
  892.     &acceptableResponses, PR_FALSE,
  893.     SEC_SequenceOfObjectIDTemplate);
  894.     if (rv != SECSuccess)
  895. goto loser;
  896.     PORT_Free(acceptableResponses);
  897.     if (request->tbsRequest->extensionHandle == NULL)
  898. request->tbsRequest->extensionHandle = extHandle;
  899.     return SECSuccess;
  900. loser:
  901.     if (acceptableResponses != NULL)
  902. PORT_Free(acceptableResponses);
  903.     if (extHandle != NULL)
  904. (void) CERT_FinishExtensions(extHandle);
  905.     return rv;
  906. }
  907. /*
  908.  * FUNCTION: CERT_DestroyOCSPRequest
  909.  *   Frees an OCSP Request structure.
  910.  * INPUTS:
  911.  *   CERTOCSPRequest *request
  912.  *     Pointer to CERTOCSPRequest to be freed.
  913.  * RETURN:
  914.  *   No return value; no errors.
  915.  */
  916. void
  917. CERT_DestroyOCSPRequest(CERTOCSPRequest *request)
  918. {
  919.     if (request == NULL)
  920. return;
  921.     if (request->tbsRequest != NULL) {
  922. if (request->tbsRequest->requestorName != NULL)
  923.     CERT_DestroyGeneralNameList(request->tbsRequest->requestorName);
  924. if (request->tbsRequest->extensionHandle != NULL)
  925.     (void) CERT_FinishExtensions(request->tbsRequest->extensionHandle);
  926.     }
  927.     if (request->optionalSignature != NULL) {
  928. if (request->optionalSignature->cert != NULL)
  929.     CERT_DestroyCertificate(request->optionalSignature->cert);
  930. /*
  931.  * XXX Need to free derCerts?  Or do they come out of arena?
  932.  * (Currently we never fill in derCerts, which is why the
  933.  * answer is not obvious.  Once we do, add any necessary code
  934.  * here and remove this comment.)
  935.  */
  936.     }
  937.     /*
  938.      * We should actually never have a request without an arena,
  939.      * but check just in case.  (If there isn't one, there is not
  940.      * much we can do about it...)
  941.      */
  942.     PORT_Assert(request->arena != NULL);
  943.     if (request->arena != NULL)
  944. PORT_FreeArena(request->arena, PR_FALSE);
  945. }
  946. /*
  947.  * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy):
  948.  */
  949. /*
  950.  * Helper function for encoding or decoding a ResponderID -- based on the
  951.  * given type, return the associated template for that choice.
  952.  */
  953. static const SEC_ASN1Template *
  954. ocsp_ResponderIDTemplateByType(ocspResponderIDType responderIDType)
  955. {
  956.     const SEC_ASN1Template *responderIDTemplate;
  957.     switch (responderIDType) {
  958. case ocspResponderID_byName:
  959.     responderIDTemplate = ocsp_ResponderIDByNameTemplate;
  960.     break;
  961. case ocspResponderID_byKey:
  962.     responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
  963.     break;
  964. case ocspResponderID_other:
  965. default:
  966.     PORT_Assert(responderIDType == ocspResponderID_other);
  967.     responderIDTemplate = ocsp_ResponderIDOtherTemplate;
  968.     break;
  969.     }
  970.     return responderIDTemplate;
  971. }
  972. /*
  973.  * Helper function for encoding or decoding a CertStatus -- based on the
  974.  * given type, return the associated template for that choice.
  975.  */
  976. static const SEC_ASN1Template *
  977. ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType)
  978. {
  979.     const SEC_ASN1Template *certStatusTemplate;
  980.     switch (certStatusType) {
  981. case ocspCertStatus_good:
  982.     certStatusTemplate = ocsp_CertStatusGoodTemplate;
  983.     break;
  984. case ocspCertStatus_revoked:
  985.     certStatusTemplate = ocsp_CertStatusRevokedTemplate;
  986.     break;
  987. case ocspCertStatus_unknown:
  988.     certStatusTemplate = ocsp_CertStatusUnknownTemplate;
  989.     break;
  990. case ocspCertStatus_other:
  991. default:
  992.     PORT_Assert(certStatusType == ocspCertStatus_other);
  993.     certStatusTemplate = ocsp_CertStatusOtherTemplate;
  994.     break;
  995.     }
  996.     return certStatusTemplate;
  997. }
  998. /*
  999.  * Helper function for decoding a certStatus -- turn the actual DER tag
  1000.  * into our local translation.
  1001.  */
  1002. static ocspCertStatusType
  1003. ocsp_CertStatusTypeByTag(int derTag)
  1004. {
  1005.     ocspCertStatusType certStatusType;
  1006.     switch (derTag) {
  1007. case 0:
  1008.     certStatusType = ocspCertStatus_good;
  1009.     break;
  1010. case 1:
  1011.     certStatusType = ocspCertStatus_revoked;
  1012.     break;
  1013. case 2:
  1014.     certStatusType = ocspCertStatus_unknown;
  1015.     break;
  1016. default:
  1017.     certStatusType = ocspCertStatus_other;
  1018.     break;
  1019.     }
  1020.     return certStatusType;
  1021. }
  1022. /*
  1023.  * Helper function for decoding SingleResponses -- they each contain
  1024.  * a status which is encoded as CHOICE, which needs to be decoded "by hand".
  1025.  *
  1026.  * Note -- on error, this routine does not release the memory it may
  1027.  * have allocated; it expects its caller to do that.
  1028.  */
  1029. static SECStatus
  1030. ocsp_FinishDecodingSingleResponses(PRArenaPool *arena,
  1031.    CERTOCSPSingleResponse **responses)
  1032. {
  1033.     ocspCertStatus *certStatus;
  1034.     ocspCertStatusType certStatusType;
  1035.     const SEC_ASN1Template *certStatusTemplate;
  1036.     int derTag;
  1037.     int i;
  1038.     SECStatus rv = SECFailure;
  1039.     if (responses == NULL) /* nothing to do */
  1040. return SECSuccess;
  1041.     for (i = 0; responses[i] != NULL; i++) {
  1042. /*
  1043.  * The following assert points out internal errors (problems in
  1044.  * the template definitions or in the ASN.1 decoder itself, etc.).
  1045.  */
  1046. PORT_Assert(responses[i]->derCertStatus.data != NULL);
  1047. derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK;
  1048. certStatusType = ocsp_CertStatusTypeByTag(derTag);
  1049. certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType);
  1050. certStatus = PORT_ArenaZAlloc(arena, sizeof(ocspCertStatus));
  1051. if (certStatus == NULL) {
  1052.     goto loser;
  1053. }
  1054. rv = SEC_ASN1DecodeItem(arena, certStatus, certStatusTemplate,
  1055. &responses[i]->derCertStatus);
  1056. if (rv != SECSuccess) {
  1057.     if (PORT_GetError() == SEC_ERROR_BAD_DER)
  1058. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  1059.     goto loser;
  1060. }
  1061. certStatus->certStatusType = certStatusType;
  1062. responses[i]->certStatus = certStatus;
  1063.     }
  1064.     return SECSuccess;
  1065. loser:
  1066.     return rv;
  1067. }
  1068. /*
  1069.  * Helper function for decoding a responderID -- turn the actual DER tag
  1070.  * into our local translation.
  1071.  */
  1072. static ocspResponderIDType
  1073. ocsp_ResponderIDTypeByTag(int derTag)
  1074. {
  1075.     ocspResponderIDType responderIDType;
  1076.     switch (derTag) {
  1077. case 1:
  1078.     responderIDType = ocspResponderID_byName;
  1079.     break;
  1080. case 2:
  1081.     responderIDType = ocspResponderID_byKey;
  1082.     break;
  1083. default:
  1084.     responderIDType = ocspResponderID_other;
  1085.     break;
  1086.     }
  1087.     return responderIDType;
  1088. }
  1089. /*
  1090.  * Decode "src" as a BasicOCSPResponse, returning the result.
  1091.  */
  1092. static ocspBasicOCSPResponse *
  1093. ocsp_DecodeBasicOCSPResponse(PRArenaPool *arena, SECItem *src)
  1094. {
  1095.     void *mark;
  1096.     ocspBasicOCSPResponse *basicResponse;
  1097.     ocspResponseData *responseData;
  1098.     ocspResponderID *responderID;
  1099.     ocspResponderIDType responderIDType;
  1100.     const SEC_ASN1Template *responderIDTemplate;
  1101.     int derTag;
  1102.     SECStatus rv;
  1103.     mark = PORT_ArenaMark(arena);
  1104.     basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse));
  1105.     if (basicResponse == NULL) {
  1106. goto loser;
  1107.     }
  1108.     rv = SEC_ASN1DecodeItem(arena, basicResponse,
  1109.     ocsp_BasicOCSPResponseTemplate, src);
  1110.     if (rv != SECSuccess) {
  1111. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  1112.     PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  1113. goto loser;
  1114.     }
  1115.     responseData = basicResponse->tbsResponseData;
  1116.     /*
  1117.      * The following asserts point out internal errors (problems in
  1118.      * the template definitions or in the ASN.1 decoder itself, etc.).
  1119.      */
  1120.     PORT_Assert(responseData != NULL);
  1121.     PORT_Assert(responseData->derResponderID.data != NULL);
  1122.     /*
  1123.      * XXX Because responderID is a CHOICE, which is not currently handled
  1124.      * by our ASN.1 decoder, we have to decode it "by hand".
  1125.      */
  1126.     derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK;
  1127.     responderIDType = ocsp_ResponderIDTypeByTag(derTag);
  1128.     responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType);
  1129.     responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID));
  1130.     if (responderID == NULL) {
  1131. goto loser;
  1132.     }
  1133.     rv = SEC_ASN1DecodeItem(arena, responderID, responderIDTemplate,
  1134.     &responseData->derResponderID);
  1135.     if (rv != SECSuccess) {
  1136. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  1137.     PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  1138. goto loser;
  1139.     }
  1140.     responderID->responderIDType = responderIDType;
  1141.     responseData->responderID = responderID;
  1142.     /*
  1143.      * XXX Each SingleResponse also contains a CHOICE, which has to be
  1144.      * fixed up by hand.
  1145.      */
  1146.     rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses);
  1147.     if (rv != SECSuccess) {
  1148. goto loser;
  1149.     }
  1150.     PORT_ArenaUnmark(arena, mark);
  1151.     return basicResponse;
  1152. loser:
  1153.     PORT_ArenaRelease(arena, mark);
  1154.     return NULL;
  1155. }
  1156. /*
  1157.  * Decode the responseBytes based on the responseType found in "rbytes",
  1158.  * leaving the resulting translated/decoded information in there as well.
  1159.  */
  1160. static SECStatus
  1161. ocsp_DecodeResponseBytes(PRArenaPool *arena, ocspResponseBytes *rbytes)
  1162. {
  1163.     PORT_Assert(rbytes != NULL); /* internal error, really */
  1164.     if (rbytes == NULL)
  1165. PORT_SetError(SEC_ERROR_INVALID_ARGS); /* XXX set better error? */
  1166.     rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType);
  1167.     switch (rbytes->responseTypeTag) {
  1168. case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
  1169.     {
  1170. ocspBasicOCSPResponse *basicResponse;
  1171. basicResponse = ocsp_DecodeBasicOCSPResponse(arena,
  1172.      &rbytes->response);
  1173. if (basicResponse == NULL)
  1174.     return SECFailure;
  1175. rbytes->decodedResponse.basic = basicResponse;
  1176.     }
  1177.     break;
  1178. /*
  1179.  * Add new/future response types here.
  1180.  */
  1181. default:
  1182.     PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE);
  1183.     return SECFailure;
  1184.     }
  1185.     return SECSuccess;
  1186. }
  1187. /*
  1188.  * FUNCTION: CERT_DecodeOCSPResponse
  1189.  *   Decode a DER encoded OCSP Response.
  1190.  * INPUTS:
  1191.  *   SECItem *src
  1192.  *     Pointer to a SECItem holding DER encoded OCSP Response.
  1193.  * RETURN:
  1194.  *   Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response);
  1195.  *   the caller is responsible for destroying it.  Or NULL if error (either
  1196.  *   response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE),
  1197.  *   it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE),
  1198.  *   or a low-level or internal error occurred).
  1199.  */
  1200. CERTOCSPResponse *
  1201. CERT_DecodeOCSPResponse(SECItem *src)
  1202. {
  1203.     PRArenaPool *arena = NULL;
  1204.     CERTOCSPResponse *response = NULL;
  1205.     SECStatus rv = SECFailure;
  1206.     ocspResponseStatus sv;
  1207.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1208.     if (arena == NULL) {
  1209. goto loser;
  1210.     }
  1211.     response = (CERTOCSPResponse *) PORT_ArenaZAlloc(arena,
  1212.      sizeof(CERTOCSPResponse));
  1213.     if (response == NULL) {
  1214. goto loser;
  1215.     }
  1216.     response->arena = arena;
  1217.     rv = SEC_ASN1DecodeItem(arena, response, ocsp_OCSPResponseTemplate, src);
  1218.     if (rv != SECSuccess) {
  1219. if (PORT_GetError() == SEC_ERROR_BAD_DER)
  1220.     PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  1221. goto loser;
  1222.     }
  1223.     sv = (ocspResponseStatus) DER_GetInteger(&response->responseStatus);
  1224.     response->statusValue = sv;
  1225.     if (sv != ocspResponse_successful) {
  1226. /*
  1227.  * If the response status is anything but successful, then we
  1228.  * are all done with decoding; the status is all there is.
  1229.  */
  1230. return response;
  1231.     }
  1232.     /*
  1233.      * A successful response contains much more information, still encoded.
  1234.      * Now we need to decode that.
  1235.      */
  1236.     rv = ocsp_DecodeResponseBytes(arena, response->responseBytes);
  1237.     if (rv != SECSuccess) {
  1238. goto loser;
  1239.     }
  1240.     return response;
  1241. loser:
  1242.     if (arena != NULL) {
  1243. PORT_FreeArena(arena, PR_FALSE);
  1244.     }
  1245.     return NULL;
  1246. }
  1247. /*
  1248.  * The way an OCSPResponse is defined, there are many levels to descend
  1249.  * before getting to the actual response information.  And along the way
  1250.  * we need to check that the response *type* is recognizable, which for
  1251.  * now means that it is a BasicOCSPResponse, because that is the only
  1252.  * type currently defined.  Rather than force all routines to perform
  1253.  * a bunch of sanity checking every time they want to work on a response,
  1254.  * this function isolates that and gives back the interesting part.
  1255.  * Note that no copying is done, this just returns a pointer into the
  1256.  * substructure of the response which is passed in.
  1257.  *
  1258.  * XXX This routine only works when a valid response structure is passed
  1259.  * into it; this is checked with many assertions.  Assuming the response
  1260.  * was creating by decoding, it wouldn't make it this far without being
  1261.  * okay.  That is a sufficient assumption since the entire OCSP interface
  1262.  * is only used internally.  When this interface is officially exported,
  1263.  * each assertion below will need to be followed-up with setting an error
  1264.  * and returning (null).
  1265.  */
  1266. static ocspResponseData *
  1267. ocsp_GetResponseData(CERTOCSPResponse *response)
  1268. {
  1269.     ocspBasicOCSPResponse *basic;
  1270.     ocspResponseData *responseData;
  1271.     PORT_Assert(response != NULL);
  1272.     PORT_Assert(response->responseBytes != NULL);
  1273.     PORT_Assert(response->responseBytes->responseTypeTag
  1274. == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  1275.     basic = response->responseBytes->decodedResponse.basic;
  1276.     PORT_Assert(basic != NULL);
  1277.     responseData = basic->tbsResponseData;
  1278.     PORT_Assert(responseData != NULL);
  1279.     return responseData;
  1280. }
  1281. /*
  1282.  * Much like the routine above, except it returns the response signature.
  1283.  * Again, no copy is done.
  1284.  */
  1285. static ocspSignature *
  1286. ocsp_GetResponseSignature(CERTOCSPResponse *response)
  1287. {
  1288.     ocspBasicOCSPResponse *basic;
  1289.     PORT_Assert(response != NULL);
  1290.     PORT_Assert(response->responseBytes != NULL);
  1291.     PORT_Assert(response->responseBytes->responseTypeTag
  1292. == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  1293.     basic = response->responseBytes->decodedResponse.basic;
  1294.     PORT_Assert(basic != NULL);
  1295.     return &(basic->responseSignature);
  1296. }
  1297. /*
  1298.  * FUNCTION: CERT_DestroyOCSPResponse
  1299.  *   Frees an OCSP Response structure.
  1300.  * INPUTS:
  1301.  *   CERTOCSPResponse *request
  1302.  *     Pointer to CERTOCSPResponse to be freed.
  1303.  * RETURN:
  1304.  *   No return value; no errors.
  1305.  */
  1306. void
  1307. CERT_DestroyOCSPResponse(CERTOCSPResponse *response)
  1308. {
  1309.     if (response != NULL) {
  1310. ocspSignature *signature = ocsp_GetResponseSignature(response);
  1311. if (signature->cert != NULL)
  1312.     CERT_DestroyCertificate(signature->cert);
  1313. /*
  1314.  * We should actually never have a response without an arena,
  1315.  * but check just in case.  (If there isn't one, there is not
  1316.  * much we can do about it...)
  1317.  */
  1318. PORT_Assert(response->arena != NULL);
  1319. if (response->arena != NULL) {
  1320.     PORT_FreeArena(response->arena, PR_FALSE);
  1321. }
  1322.     }
  1323. }
  1324. /*
  1325.  * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response):
  1326.  */
  1327. /*
  1328.  * Pick apart a URL, saving the important things in the passed-in pointers.
  1329.  *
  1330.  * We expect to find "http://<hostname>[:<port>]/[path]", though we will
  1331.  * tolerate that final slash character missing, as well as beginning and
  1332.  * trailing whitespace, and any-case-characters for "http".  All of that
  1333.  * tolerance is what complicates this routine.  What we want is just to
  1334.  * pick out the hostname, the port, and the path.
  1335.  *
  1336.  * On a successful return, the caller will need to free the output pieces
  1337.  * of hostname and path, which are copies of the values found in the url.
  1338.  */
  1339. static SECStatus
  1340. ocsp_ParseURL(char *url, char **pHostname, PRUint16 *pPort, char **pPath)
  1341. {
  1342.     unsigned short port = 80; /* default, in case not in url */
  1343.     char *hostname = NULL;
  1344.     char *path = NULL;
  1345.     char *save;
  1346.     char c;
  1347.     int len;
  1348.     if (url == NULL)
  1349. goto loser;
  1350.     /*
  1351.      * Skip beginning whitespace.
  1352.      */
  1353.     c = *url;
  1354.     while ((c == ' ' || c == 't') && c != '') {
  1355. url++;
  1356. c = *url;
  1357.     }
  1358.     if (c == '')
  1359. goto loser;
  1360.     /*
  1361.      * Confirm, then skip, protocol.  (Since we only know how to do http,
  1362.      * that is all we will accept).
  1363.      */
  1364.     if (PORT_Strncasecmp(url, "http://", 7) != 0)
  1365. goto loser;
  1366.     url += 7;
  1367.     /*
  1368.      * Whatever comes next is the hostname (or host IP address).  We just
  1369.      * save it aside and then search for its end so we can determine its
  1370.      * length and copy it.
  1371.      *
  1372.      * XXX Note that because we treat a ':' as a terminator character
  1373.      * (and below, we expect that to mean there is a port specification
  1374.      * immediately following), we will not handle IPv6 addresses.  That is
  1375.      * apparently an acceptable limitation, for the time being.  Some day,
  1376.      * when there is a clear way to specify a URL with an IPv6 address that
  1377.      * can be parsed unambiguously, this code should be made to do that.
  1378.      */
  1379.     save = url;
  1380.     c = *url;
  1381.     while (c != '/' && c != ':' && c != '' && c != ' ' && c != 't') {
  1382. url++;
  1383. c = *url;
  1384.     }
  1385.     len = url - save;
  1386.     hostname = PORT_Alloc(len + 1);
  1387.     if (hostname == NULL)
  1388. goto loser;
  1389.     PORT_Memcpy(hostname, save, len);
  1390.     hostname[len] = '';
  1391.     /*
  1392.      * Now we figure out if there was a port specified or not.
  1393.      * If so, we need to parse it (as a number) and skip it.
  1394.      */
  1395.     if (c == ':') {
  1396. url++;
  1397. port = (unsigned short) PORT_Atoi(url);
  1398. c = *url;
  1399. while (c != '/' && c != '' && c != ' ' && c != 't') {
  1400.     if (c < '0' || c > '9')
  1401. goto loser;
  1402.     url++;
  1403.     c = *url;
  1404. }
  1405.     }
  1406.     /*
  1407.      * Last thing to find is a path.  There *should* be a slash,
  1408.      * if nothing else -- but if there is not we provide one.
  1409.      */
  1410.     if (c == '/') {
  1411. save = url;
  1412. while (c != '' && c != ' ' && c != 't') {
  1413.     url++;
  1414.     c = *url;
  1415. }
  1416. len = url - save;
  1417. path = PORT_Alloc(len + 1);
  1418. if (path == NULL)
  1419.     goto loser;
  1420. PORT_Memcpy(path, save, len);
  1421. path[len] = '';
  1422.     } else {
  1423. path = PORT_Strdup("/");
  1424.     }
  1425.     *pHostname = hostname;
  1426.     *pPort = port;
  1427.     *pPath = path;
  1428.     return SECSuccess;
  1429. loser:
  1430.     if (hostname != NULL)
  1431. PORT_Free(hostname);
  1432.     if (path != NULL)
  1433. PORT_Free(path);
  1434.     PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
  1435.     return SECFailure;
  1436. }
  1437. /*
  1438.  * Open a socket to the specified host on the specified port, and return it.
  1439.  * The host is either a hostname or an IP address.
  1440.  */
  1441. static PRFileDesc *
  1442. ocsp_ConnectToHost(const char *host, PRUint16 port)
  1443. {
  1444.     PRFileDesc *sock = NULL;
  1445.     PRIntervalTime timeout;
  1446.     PRNetAddr addr;
  1447.     char *netdbbuf = NULL;
  1448.     sock = PR_NewTCPSocket();
  1449.     if (sock == NULL)
  1450. goto loser;
  1451.     /* XXX Some day need a way to set (and get?) the following value */
  1452.     timeout = PR_SecondsToInterval(30);
  1453.     /*
  1454.      * If the following converts an IP address string in "dot notation"
  1455.      * into a PRNetAddr.  If it fails, we assume that is because we do not
  1456.      * have such an address, but instead a host *name*.  In that case we
  1457.      * then lookup the host by name.  Using the NSPR function this way
  1458.      * means we do not have to have our own logic for distinguishing a
  1459.      * valid numerical IP address from a hostname.
  1460.      */
  1461.     if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) {
  1462. PRIntn hostIndex;
  1463. PRHostEnt hostEntry;
  1464. netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE);
  1465. if (netdbbuf == NULL)
  1466.     goto loser;
  1467. if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE,
  1468.      &hostEntry) != PR_SUCCESS)
  1469.     goto loser;
  1470. hostIndex = 0;
  1471. do {
  1472.     hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr);
  1473.     if (hostIndex < 0)
  1474. goto loser;
  1475. } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS
  1476.  && hostIndex > 0);
  1477.         if (hostIndex == 0)
  1478.     goto loser;
  1479. PORT_Free(netdbbuf);
  1480.     } else {
  1481. /*
  1482.  * First put the port into the address, then connect.
  1483.  */
  1484. if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS)
  1485.     goto loser;
  1486. if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS)
  1487.     goto loser;
  1488.     }
  1489.     return sock;
  1490. loser:
  1491.     if (sock != NULL)
  1492. PR_Close(sock);
  1493.     if (netdbbuf != NULL)
  1494. PORT_Free(netdbbuf);
  1495.     return NULL;
  1496. }
  1497. /*
  1498.  * Sends an encoded OCSP request to the server identified by "location",
  1499.  * and returns the socket on which it was sent (so can listen for the reply).
  1500.  * "location" is expected to be a valid URL -- an error parsing it produces
  1501.  * SEC_ERROR_CERT_BAD_ACCESS_LOCATION.  Other errors are likely problems
  1502.  * connecting to it, or writing to it, or allocating memory, and the low-level
  1503.  * errors appropriate to the problem will be set.
  1504.  */
  1505. static PRFileDesc *
  1506. ocsp_SendEncodedRequest(char *location, SECItem *encodedRequest)
  1507. {
  1508.     char *hostname = NULL;
  1509.     char *path = NULL;
  1510.     PRUint16 port;
  1511.     SECStatus rv;
  1512.     PRFileDesc *sock = NULL;
  1513.     PRFileDesc *returnSock = NULL;
  1514.     char *header = NULL;
  1515.     /*
  1516.      * Take apart the location, getting the hostname, port, and path.
  1517.      */
  1518.     rv = ocsp_ParseURL(location, &hostname, &port, &path);
  1519.     if (rv != SECSuccess)
  1520. goto loser;
  1521.     PORT_Assert(hostname != NULL);
  1522.     PORT_Assert(path != NULL);
  1523.     sock = ocsp_ConnectToHost(hostname, port);
  1524.     if (sock == NULL)
  1525. goto loser;
  1526.     header = PR_smprintf("POST %s HTTP/1.0rn"
  1527.  "Host: %s:%drn"
  1528.  "Content-Type: application/ocsp-requestrn"
  1529.  "Content-Length: %urnrn",
  1530.  path, hostname, port, encodedRequest->len);
  1531.     if (header == NULL)
  1532. goto loser;
  1533.     /*
  1534.      * The NSPR documentation promises that if it can, it will write the full
  1535.      * amount; this will not return a partial value expecting us to loop.
  1536.      */
  1537.     if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0)
  1538. goto loser;
  1539.     if (PR_Write(sock, encodedRequest->data,
  1540.  (PRInt32) encodedRequest->len) < 0)
  1541. goto loser;
  1542.     returnSock = sock;
  1543.     sock = NULL;
  1544. loser:
  1545.     if (header != NULL)
  1546. PORT_Free(header);
  1547.     if (sock != NULL)
  1548. PR_Close(sock);
  1549.     if (path != NULL)
  1550. PORT_Free(path);
  1551.     if (hostname != NULL)
  1552. PORT_Free(hostname);
  1553.     return returnSock;
  1554. }
  1555. /*
  1556.  * Read from "fd" into "buf" -- expect/attempt to read a "minimum" number
  1557.  * of bytes, but do not exceed "maximum".  (Obviously, stop at less than
  1558.  * "minimum" if hit end-of-stream.)  Only problems are low-level i/o errors.
  1559.  */
  1560. static int
  1561. ocsp_MinMaxRead(PRFileDesc *fd, unsigned char *buf, int minimum, int maximum)
  1562. {
  1563.     int total = 0;
  1564.     while (total < minimum) {
  1565. PRInt32 got;
  1566. got = PR_Read(fd, buf + total, (PRInt32) (maximum - total));
  1567. if (got < 0) {
  1568.     if (PR_GetError() != PR_WOULD_BLOCK_ERROR) {
  1569. break;
  1570.     }
  1571.     continue;
  1572. } else if (got == 0) { /* EOS */
  1573.     break;
  1574. }
  1575. total += got;
  1576.     }
  1577.     return total;
  1578. }
  1579. #ifdef BUFSIZ
  1580. #define OCSP_BUFSIZE BUFSIZ
  1581. #else
  1582. #define OCSP_BUFSIZE 1024
  1583. #endif
  1584. /*
  1585.  * Listens on the given socket and returns an encoded response when received.
  1586.  * Properly formatted HTTP response headers are expected to be read from the
  1587.  * socket, preceding a binary-encoded OCSP response.  Problems with parsing
  1588.  * cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be set; any other
  1589.  * problems are likely low-level i/o or memory allocation errors.
  1590.  */
  1591. static SECItem *
  1592. ocsp_GetEncodedResponse(PRArenaPool *arena, PRFileDesc *sock)
  1593. {
  1594.     unsigned char *buf = NULL;
  1595.     int bufsize, bytesRead, len;
  1596.     const unsigned char *bufEnd;
  1597.     const char *s;
  1598.     const char *newline = NULL;
  1599.     PRBool headersDone = PR_FALSE;
  1600.     PRBool pendingCR = PR_FALSE;
  1601.     PRBool contentTypeOK = PR_FALSE;
  1602.     unsigned int contentLength = 0;
  1603.     void *mark = NULL;
  1604.     SECItem *result = NULL;
  1605.     bufsize = OCSP_BUFSIZE;
  1606.     buf = PORT_Alloc(bufsize);
  1607.     if (buf == NULL) {
  1608. goto loser;
  1609.     }
  1610.     /*
  1611.      * I picked 128 because:
  1612.      * - It is a nice "round" number. ;-)
  1613.      *  - I am sure it should cover at least the first line of the http
  1614.      *   response (on the order of 20 should be enough but I am allowing
  1615.      *   for excessive leading whitespace) so that I don't have to keep
  1616.      *   checking for going past the end of the buffer until after that.
  1617.      * - I am sure that any interesting response will be bigger than that;
  1618.      *    the exception is one that is status-only, like "tryLater".
  1619.      *  - Given a trim response (no extra whitespace), it should cover
  1620.      *   all of the http headers, and just a bit of the content.
  1621.      *   This is what I was aiming for, to minimize data copying.
  1622.      */
  1623.     bytesRead = ocsp_MinMaxRead(sock, buf, 128, bufsize);
  1624.     if (bytesRead <= 0) {
  1625. if (bytesRead == 0)
  1626.     PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1627. goto loser;
  1628.     }
  1629.     bufEnd = buf + bytesRead;
  1630.     /*
  1631.      * Skip leading whitespace.
  1632.      */
  1633.     for (s = (char *)buf; s < (char *)bufEnd; s++) {
  1634. if (*s != ' ' && *s != 't') {
  1635.     break;
  1636. }
  1637.     }
  1638.     /*
  1639.      * Here we expect to find something like "HTTP/1.x 200 OKrn".
  1640.      * (The status code may be anything, but should be 3 digits.
  1641.      * The comment (e.g. "OK") may be anything as well.)  I figure that
  1642.      * the minimal line would be "HTTP/x.y zzzn", which is 13 chars.
  1643.      * That may not even meet the spec, but we will accept it -- anything
  1644.      * less than that, though, we will not.
  1645.      */
  1646.     if (((char *)bufEnd - s) < 13 || PORT_Strncasecmp(s, "http/", 5) != 0) {
  1647. PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1648. goto loser;
  1649.     }
  1650.     s += 5; /* skip "http/" */
  1651.     /*
  1652.      * I don't see a reason to look at the version number.  Assuming that
  1653.      * whatever version it is, it supports the one or two headers we are
  1654.      * looking for, and doesn't completely change the interpretation of
  1655.      * status values, it shouldn't matter.  We shouldn't reject something
  1656.      * that would otherwise work just because the code was picky about
  1657.      * version number.  So we just skip it, hoping real incompatibility
  1658.      * will manifest itself in the parsing.
  1659.      */
  1660.     while (*s++ != ' ') { /* skip "x.y ", without interpretation */
  1661. /*
  1662.  * We expect the version number to be only a few characters,
  1663.  * and that we should easily have enough in the buffer to cover.
  1664.  * So, if we go past the end, just bail.
  1665.  */
  1666. if (s >= (char *)bufEnd) {
  1667.     PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1668.     goto loser;
  1669. }
  1670.     }
  1671.     /*
  1672.      * Now get, and check, the status.  Accept 200-299; reject all else.
  1673.      * There are some 200s that basically have no content, but that will
  1674.      * fall out as bad below, and it's just easier to handle it that way
  1675.      * than to try to know all the different status values.
  1676.      */
  1677.     {
  1678. int statusCode = PORT_Atoi(s);
  1679. if (statusCode < 200 || statusCode >= 300) {
  1680.     PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1681.     goto loser;
  1682. }
  1683.     }
  1684.     s += 3; /* skip 3-digit status code */
  1685.     /*
  1686.      * The rest of the line is a comment, which we just want to skip.
  1687.      * The next thing to do is continue through all of the HTTP headers,
  1688.      * watching for the couple we are interested in.  The end of the
  1689.      * headers (and thus the beginning of the content) is marked by
  1690.      * two consecutive newlines.  (According to spec that should be
  1691.      * CRLF followed by CRLF, but we are being generous and allowing
  1692.      * for people who send only CRs or only LFs, too.)
  1693.      *
  1694.      * XXX Explain better about how the following code works.
  1695.      * Especially what the potential values of "newline" are and what
  1696.      * each one means.
  1697.      */
  1698.     while (1) {
  1699. /*
  1700.  * Move forward to the next line, stopping when we find a CRLF,
  1701.  * CR, or LF, or the end of the buffer.  We have to be careful
  1702.  * when we find a lone CR at the end of the buffer, because if
  1703.  * the next character read is an LF we want to treat it as one
  1704.  * newline altogether.
  1705.  *
  1706.  * We also need to detect two newlines in a row, which is what
  1707.  * marks the end of the headers and time for us to quit out of
  1708.  * the outer loop.
  1709.  */
  1710. for (; s < (char *)bufEnd; s++) {
  1711.     if (*s == 'r' || *s == 'n') {
  1712. if (s == newline) {
  1713.     headersDone = PR_TRUE; /* 2nd consecutive newline */
  1714. }
  1715. newline = s;
  1716. if (newline[0] == 'r') {
  1717.     if (s == (char *)bufEnd - 1) {
  1718. /* CR at end - wait for the next character */
  1719. newline = NULL;
  1720. pendingCR = PR_TRUE;
  1721. break;
  1722.     } else if (newline[1] == 'n') {
  1723. /* CRLF seen; swallow both */
  1724. newline++;
  1725.     }
  1726. }
  1727. newline++;
  1728. break;
  1729.     }
  1730.     /*
  1731.      * After the first time through, we no longer need to remember
  1732.      * where the previous line started.  We needed it for checking
  1733.      * for consecutive newlines, but now we need it to be clear in
  1734.      * case we finish the loop by finishing off the buffer.
  1735.      */
  1736.     newline = NULL;
  1737. }
  1738. if (headersDone) {
  1739.     s = newline;
  1740.     break;
  1741. }
  1742. /*
  1743.  * When we are here, either:
  1744.  * - newline is NULL, meaning we're at the end of the buffer
  1745.  *   and we need to refill it, or
  1746.  * - newline points to the first character on the new line
  1747.  */
  1748. if (newline == NULL) {
  1749.     /* So, we need to refill the buffer. */
  1750.     len = pendingCR ? 1 : 0;
  1751.     bytesRead = ocsp_MinMaxRead(sock, buf + len, 64 - len,
  1752. bufsize - len);
  1753.     if (bytesRead <= 0) {
  1754. if (bytesRead == 0)
  1755.     PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1756. goto loser;
  1757.     }
  1758.     s = (char *)buf;
  1759.     bufEnd = buf + len + bytesRead;
  1760.     if (pendingCR) {
  1761. buf[0] = 'r';
  1762. pendingCR = PR_FALSE;
  1763.     }
  1764.     continue;
  1765. }
  1766. /*
  1767.  * So, we have a good newline pointer (just past a CR, LF or CRLF),
  1768.  * but now we want to make sure that what it points to is long
  1769.  * enough to be something we are looking for.  If it isn't, add
  1770.  * more to the buffer after first copying what's left to the
  1771.  * beginning.
  1772.  */
  1773. if (((char *)bufEnd - newline) < 40) {
  1774.     len = (char *)bufEnd - newline;
  1775.     PORT_Memmove(buf, newline, len);
  1776.     bytesRead = ocsp_MinMaxRead(sock, buf + len, 40 - len,
  1777. bufsize - len);
  1778.     if (bytesRead <= 0) {
  1779. if (bytesRead == 0)
  1780.     PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1781. goto loser;
  1782.     }
  1783.     newline = (char *)buf;
  1784.     bufEnd = buf + len + bytesRead;
  1785. }
  1786. /*
  1787.  * Okay, now we know that we are looking at an HTTP header line
  1788.  * with enough length to be safe for our comparisons.  See if it is
  1789.  * one of the ones we are interested in.  (That is, "Content-Length"
  1790.  * or "Content-Type".)
  1791.  */
  1792. if (PORT_Strncasecmp(newline, "content-", 8) == 0) {
  1793.     s = newline + 8;
  1794.     if (PORT_Strncasecmp(s, "type: ", 6) == 0) {
  1795. s += 6;
  1796. if (PORT_Strncasecmp(s, "application/ocsp-response",
  1797.      25) != 0) {
  1798.     break;
  1799. }
  1800. contentTypeOK = PR_TRUE;
  1801. s += 25;
  1802.     } else if (PORT_Strncasecmp(s, "length: ", 8) == 0) {
  1803. s += 8;
  1804. contentLength = PORT_Atoi(s);
  1805.     }
  1806.     newline = NULL;
  1807. } else {
  1808.     /*
  1809.      * Not an interesting header.  We will go around the loop
  1810.      * again to find the next line.
  1811.      */
  1812.     s = newline;
  1813. }
  1814.     }
  1815.     /*
  1816.      * Check that we got the correct content type.  (If !contentTypeOK,
  1817.      * the content-type header was either bad or missing.)
  1818.      */
  1819.     if (!contentTypeOK) {
  1820. PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1821. goto loser;
  1822.     }
  1823.     /*
  1824.      * Now we need to handle the actual content.  We may not have a
  1825.      * good content-length; things are harder if we do not -- in that
  1826.      * case we will just read until we get EOS.
  1827.      */
  1828.     /*
  1829.      * We are finally about the allocate the return area; before that
  1830.      * mark the arena so we can release-back on error.
  1831.      */
  1832.     if (arena != NULL) {
  1833. mark = PORT_ArenaMark(arena);
  1834.     }
  1835.     /*
  1836.      * How much of the content is already in the buffer?
  1837.      */ 
  1838.     if (s == NULL) {
  1839. len = 0;
  1840.     } else {
  1841. len = (char *)bufEnd - s;
  1842. if (contentLength && len > contentLength) {
  1843.     len = contentLength;
  1844. }
  1845.     }
  1846.     /*
  1847.      * Now allocate the item to hold the data.
  1848.      */
  1849.     result = SECITEM_AllocItem(arena, NULL,
  1850.        contentLength ? contentLength : len);
  1851.     if (result == NULL) {
  1852. goto loser;
  1853.     }
  1854.     /*
  1855.      * And copy the data left in the buffer.
  1856.      */
  1857.     if (len) {
  1858. PORT_Memcpy(result->data, s, len);
  1859.     }
  1860.     /*
  1861.      * Now we need to read all of the (rest of the) content.  If we know
  1862.      * the length, it's easy, just one big read.  If not, we need to loop,
  1863.      * reading until there is nothing left to read.
  1864.      */
  1865.     if (contentLength) {
  1866. int remaining;
  1867. /*
  1868.  * It may be the case that our last buffer ended exactly on the
  1869.  * second CR of the CRLF pair which denotes the end of the headers.
  1870.  * If so, we have to be prepared to read, and skip over, an LF.
  1871.  * Since we want to read the rest of the content directly into
  1872.  * the buffer we are returning, we read one byte specifically and
  1873.  * see if it is an LF.  If not, we just copy that byte into the
  1874.  * first byte of our return value.
  1875.  */
  1876. if (pendingCR) {
  1877.     PORT_Assert(len == 0);
  1878.     bytesRead = ocsp_MinMaxRead(sock, buf, 1, 1);
  1879.     if (bytesRead < 1) {
  1880. goto loser;
  1881.     }
  1882.     if (buf[0] != 'n') {
  1883. result->data[0] = buf[0];
  1884. len = 1;
  1885.     }
  1886. }
  1887. remaining = contentLength - len;
  1888. if (remaining) {
  1889.     bytesRead = ocsp_MinMaxRead(sock, result->data + len,
  1890. remaining, remaining);
  1891.     if (bytesRead < remaining) {
  1892. if (bytesRead > 0) {
  1893.     PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
  1894. }
  1895. goto loser;
  1896.     }
  1897. }
  1898.     } else while (1) {
  1899. /*
  1900.  * Read as much as we can.  There is no real minimum here,
  1901.  * we will just take whatever we can get and copy it over
  1902.  * into our result area.
  1903.  */
  1904. bytesRead = ocsp_MinMaxRead(sock, buf, 1, bufsize);
  1905. if (bytesRead < 0) {
  1906.     goto loser;
  1907. }
  1908. if (bytesRead == 0) { /* EOS: all done reading */
  1909.     break;
  1910. }
  1911. /*
  1912.  * Now make room for that many more bytes in our result area.
  1913.  */
  1914. if (SECITEM_ReallocItem(arena, result, len,
  1915. len + bytesRead) != SECSuccess) {
  1916.     goto loser;
  1917. }
  1918. /*
  1919.  * The first time through this loop, it may be the case that
  1920.  * we have the final LF of our CRLF pair that ended the headers.
  1921.  * If so, we need to skip over it.
  1922.  */
  1923. if (pendingCR && buf[0] == 'n') {
  1924.     PORT_Memcpy(result->data + len, buf + 1, bytesRead - 1);
  1925.     len += bytesRead - 1;
  1926. } else {
  1927.     PORT_Memcpy(result->data + len, buf, bytesRead);
  1928.     len += bytesRead;
  1929. }
  1930. /*
  1931.  * In any case, after the first time through, we are done
  1932.  * looking for that LF.
  1933.  */
  1934. pendingCR = PR_FALSE;
  1935. /*
  1936.  * If we are reading "slowly", get ourselves a bigger buffer.
  1937.  */
  1938. if (bytesRead == bufsize) {
  1939.     bufsize *= 2;
  1940.     PORT_Free(buf);
  1941.     buf = PORT_Alloc(bufsize);
  1942.     if (buf == NULL) {
  1943. goto loser;
  1944.     }
  1945. }
  1946.     }
  1947.     /*
  1948.      * Finally, we are done!  The encoded response (the content of the
  1949.      * HTTP response) is now in "result".  We just have a little cleaning
  1950.      * up to do before we return.
  1951.      */
  1952.     if (mark != NULL) {
  1953. PORT_ArenaUnmark(arena, mark);
  1954.     }
  1955.     PORT_Free(buf);
  1956.     return result;
  1957. loser:
  1958.     if (mark != NULL) {
  1959. PORT_ArenaRelease(arena, mark);
  1960.     } else if (result != NULL) {
  1961. SECITEM_FreeItem(result, PR_TRUE);
  1962.     }
  1963.     if (buf != NULL) {
  1964. PORT_Free(buf);
  1965.     }
  1966.     return NULL;
  1967. }
  1968. /*
  1969.  * FUNCTION: CERT_GetEncodedOCSPResponse
  1970.  *   Creates and sends a request to an OCSP responder, then reads and
  1971.  *   returns the (encoded) response.
  1972.  * INPUTS:
  1973.  *   PRArenaPool *arena
  1974.  *     Pointer to arena from which return value will be allocated.
  1975.  *     If NULL, result will be allocated from the heap (and thus should
  1976.  *     be freed via SECITEM_FreeItem).
  1977.  *   CERTCertList *certList
  1978.  *     A list of certs for which status will be requested.
  1979.  *     Note that all of these certificates should have the same issuer,
  1980.  *     or it's expected the response will be signed by a trusted responder.
  1981.  *     If the certs need to be broken up into multiple requests, that
  1982.  *     must be handled by the caller (and thus by having multiple calls
  1983.  *     to this routine), who knows about where the request(s) are being
  1984.  *     sent and whether there are any trusted responders in place.
  1985.  *   char *location
  1986.  *     The location of the OCSP responder (a URL).
  1987.  *   int64 time
  1988.  *     Indicates the time for which the certificate status is to be 
  1989.  *     determined -- this may be used in the search for the cert's issuer
  1990.  *     but has no other bearing on the operation.
  1991.  *   PRBool addServiceLocator
  1992.  *     If true, the Service Locator extension should be added to the
  1993.  *     single request(s) for each cert.
  1994.  *   CERTCertificate *signerCert
  1995.  *     If non-NULL, means sign the request using this cert.  Otherwise,
  1996.  *     do not sign.
  1997.  *   void *pwArg
  1998.  *     Pointer to argument for password prompting, if needed.  (Definitely
  1999.  *     not needed if not signing.)
  2000.  * OUTPUTS:
  2001.  *   CERTOCSPRequest **pRequest
  2002.  *     Pointer in which to store the OCSP request created for the given
  2003.  *     list of certificates.  It is only filled in if the entire operation
  2004.  *     is successful and the pointer is not null -- and in that case the
  2005.  *     caller is then reponsible for destroying it.
  2006.  * RETURN:
  2007.  *   Returns a pointer to the SECItem holding the response.
  2008.  *   On error, returns null with error set describing the reason:
  2009.  * SEC_ERROR_UNKNOWN_ISSUER
  2010.  * SEC_ERROR_CERT_BAD_ACCESS_LOCATION
  2011.  * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
  2012.  *   Other errors are low-level problems (no memory, bad database, etc.).
  2013.  */
  2014. SECItem *
  2015. CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList,
  2016.     char *location, int64 time,
  2017.     PRBool addServiceLocator,
  2018.     CERTCertificate *signerCert, void *pwArg,
  2019.     CERTOCSPRequest **pRequest)
  2020. {
  2021.     CERTOCSPRequest *request = NULL;
  2022.     SECItem *encodedRequest = NULL;
  2023.     SECItem *encodedResponse = NULL;
  2024.     PRFileDesc *sock = NULL;
  2025.     SECStatus rv;
  2026.     request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
  2027.      signerCert);
  2028.     if (request == NULL)
  2029. goto loser;
  2030.     rv = CERT_AddOCSPAcceptableResponses(request,
  2031.  SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
  2032.     if (rv != SECSuccess)
  2033. goto loser;
  2034.     encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg);
  2035.     if (encodedRequest == NULL)
  2036. goto loser;
  2037.     sock = ocsp_SendEncodedRequest(location, encodedRequest);
  2038.     if (sock == NULL)
  2039. goto loser;
  2040.     encodedResponse = ocsp_GetEncodedResponse(arena, sock);
  2041.     if (encodedResponse != NULL && pRequest != NULL) {
  2042. *pRequest = request;
  2043. request = NULL; /* avoid destroying below */
  2044.     }
  2045. loser:
  2046.     if (request != NULL)
  2047. CERT_DestroyOCSPRequest(request);
  2048.     if (encodedRequest != NULL)
  2049. SECITEM_FreeItem(encodedRequest, PR_TRUE);
  2050.     if (sock != NULL)
  2051. PR_Close(sock);
  2052.     return encodedResponse;
  2053. }
  2054. /* Checks a certificate for the key usage extension of OCSP signer. */
  2055. static PRBool
  2056. ocsp_CertIsOCSPSigner(CERTCertificate *cert)
  2057. {
  2058.     SECStatus rv;
  2059.     SECItem extItem;
  2060.     SECItem **oids;
  2061.     SECItem *oid;
  2062.     SECOidTag oidTag;
  2063.     PRBool retval;
  2064.     CERTOidSequence *oidSeq = NULL;
  2065.     extItem.data = NULL;
  2066.     rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
  2067.     if ( rv != SECSuccess ) {
  2068. goto loser;
  2069.     }
  2070.     oidSeq = CERT_DecodeOidSequence(&extItem);
  2071.     if ( oidSeq == NULL ) {
  2072. goto loser;
  2073.     }
  2074.     oids = oidSeq->oids;
  2075.     while ( *oids != NULL ) {
  2076. oid = *oids;
  2077. oidTag = SECOID_FindOIDTag(oid);
  2078. if ( oidTag == SEC_OID_OCSP_RESPONDER ) {
  2079.     goto success;
  2080. }
  2081. oids++;
  2082.     }
  2083. loser:
  2084.     retval = PR_FALSE;
  2085.     goto done;
  2086. success:
  2087.     retval = PR_TRUE;
  2088. done:
  2089.     if ( extItem.data != NULL ) {
  2090. PORT_Free(extItem.data);
  2091.     }
  2092.     if ( oidSeq != NULL ) {
  2093. CERT_DestroyOidSequence(oidSeq);
  2094.     }
  2095.     
  2096.     return(retval);
  2097. }
  2098. #ifdef LATER /*
  2099.  * XXX This function is not currently used, but will
  2100.  * be needed later when we do revocation checking of
  2101.  * the responder certificate.  Of course, it may need
  2102.  * revising then, if the cert extension interface has
  2103.  * changed.  (Hopefully it will!)
  2104.  */
  2105. /* Checks a certificate to see if it has the OCSP no check extension. */
  2106. static PRBool
  2107. ocsp_CertHasNoCheckExtension(CERTCertificate *cert)
  2108. {
  2109.     SECStatus rv;
  2110.     SECItem extItem;
  2111.     
  2112.     extItem.data = NULL;
  2113.     rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK, 
  2114. &extItem);
  2115.     if (extItem.data != NULL) {
  2116. PORT_Free(extItem.data);
  2117.     }
  2118.     if (rv == SECSuccess) {
  2119. return PR_TRUE;
  2120.     }
  2121.     return PR_FALSE;
  2122. }
  2123. #endif /* LATER */
  2124. /*
  2125.  * Check the signature on some OCSP data.  This is a helper function that
  2126.  * can be used to check either a request or a response.  The result is
  2127.  * saved in the signature structure itself for future reference (to avoid
  2128.  * repeating the expensive verification operation), as well as returned.
  2129.  * In addition to checking the signature, the certificate (and its chain)
  2130.  * are also checked for validity (at the specified time) and usage.
  2131.  *
  2132.  * The type of cert lookup to be performed is specified by "lookupByName":
  2133.  * if true, then "certIndex" is actually a CERTName; otherwise it is a
  2134.  * SECItem which contains a key hash.
  2135.  *
  2136.  * If the signature verifies okay, and the argument "pSignerCert" is not
  2137.  * null, that parameter will be filled-in with a pointer to the signer's
  2138.  * certificate.  The caller is then responsible for destroying the cert.
  2139.  *
  2140.  * A return of SECSuccess means the verification succeeded.  If not,
  2141.  * an error will be set with the reason.  Most likely are:
  2142.  * SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
  2143.  * SEC_ERROR_BAD_SIGNATURE - the signature did not verify
  2144.  * Other errors are any of the many possible failures in cert verification
  2145.  * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
  2146.  * verifying the signer's cert, or low-level problems (no memory, etc.)
  2147.  */
  2148. static SECStatus
  2149. ocsp_CheckSignature(ocspSignature *signature, void *tbs,
  2150.     const SEC_ASN1Template *encodeTemplate,
  2151.     CERTCertDBHandle *handle, SECCertUsage certUsage,
  2152.     int64 checkTime, PRBool lookupByName, void *certIndex,
  2153.     void *pwArg, CERTCertificate **pSignerCert)
  2154. {
  2155.     SECItem rawSignature;
  2156.     SECItem *encodedTBS = NULL;
  2157.     CERTCertificate *signerCert = NULL;
  2158.     SECKEYPublicKey *signerKey = NULL;
  2159.     CERTCertificate **certs = NULL;
  2160.     SECStatus rv = SECFailure;
  2161.     int certCount;
  2162.     /*
  2163.      * If this signature has already gone through verification, just
  2164.      * return the cached result.
  2165.      */
  2166.     if (signature->wasChecked) {
  2167. if (signature->status == SECSuccess) {
  2168.     if (pSignerCert != NULL)
  2169. *pSignerCert = CERT_DupCertificate(signature->cert);
  2170. } else {
  2171.     PORT_SetError(signature->failureReason);
  2172. }
  2173. return signature->status;
  2174.     }
  2175.     /*
  2176.      * If the signature contains some certificates as well, temporarily
  2177.      * import them in case they are needed for verification.
  2178.      *
  2179.      * Note that the result of this is that each cert in "certs" needs
  2180.      * to be destroyed.
  2181.      */
  2182.     certCount = 0;
  2183.     if (signature->derCerts != NULL) {
  2184. for (; signature->derCerts[certCount] != NULL; certCount++) {
  2185.     /* just counting */
  2186. }
  2187.     }
  2188.     rv = CERT_ImportCerts(handle, certUsage, certCount,
  2189.   signature->derCerts, &certs,
  2190.   PR_FALSE, PR_FALSE, NULL);
  2191.     if (rv != SECSuccess)
  2192. goto finish;
  2193.     /*
  2194.      * Now look up the certificate that did the signing.
  2195.      * The signer can be specified either by name or by key hash.
  2196.      */
  2197.     if (lookupByName) {
  2198. SECItem *encodedName;
  2199. encodedName = SEC_ASN1EncodeItem(NULL, NULL, certIndex,
  2200.  CERT_NameTemplate);
  2201. if (encodedName == NULL)
  2202.     goto finish;
  2203. signerCert = CERT_FindCertByName(handle, encodedName);
  2204. SECITEM_FreeItem(encodedName, PR_TRUE);
  2205.     } else {
  2206. signerCert = CERT_FindCertBySPKDigest(handle, certIndex);
  2207.     }
  2208.     if (signerCert == NULL) {
  2209. rv = SECFailure;
  2210. if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
  2211.     /* Make the error a little more specific. */
  2212.     PORT_SetError(SEC_ERROR_UNKNOWN_SIGNER);
  2213. }
  2214. goto finish;
  2215.     }
  2216.     /*
  2217.      * We could mark this true at the top of this function, or always
  2218.      * below at "finish", but if the problem was just that we could not
  2219.      * find the signer's cert, leave that as if the signature hasn't
  2220.      * been checked in case a subsequent call might have better luck.
  2221.      */
  2222.     signature->wasChecked = PR_TRUE;
  2223.     /*
  2224.      * Just because we have a cert does not mean it is any good; check
  2225.      * it for validity, trust and usage.
  2226.      */
  2227.     rv = CERT_VerifyCert(handle, signerCert, PR_TRUE, certUsage, checkTime,
  2228.  pwArg, NULL);
  2229.     if (rv != SECSuccess)
  2230. goto finish;
  2231.     /*
  2232.      * Now get the public key from the signer's certificate; we need
  2233.      * it to perform the verification.
  2234.      */
  2235.     signerKey = CERT_ExtractPublicKey(signerCert);
  2236.     if (signerKey == NULL)
  2237. goto finish;
  2238.     /*
  2239.      * Prepare the data to be verified; it needs to be DER encoded first.
  2240.      */
  2241.     encodedTBS = SEC_ASN1EncodeItem(NULL, NULL, tbs, encodeTemplate);
  2242.     if (encodedTBS == NULL)
  2243. goto finish;
  2244.     /*
  2245.      * We copy the signature data *pointer* and length, so that we can
  2246.      * modify the length without damaging the original copy.  This is a
  2247.      * simple copy, not a dup, so no destroy/free is necessary.
  2248.      */
  2249.     rawSignature = signature->signature;
  2250.     /*
  2251.      * The raw signature is a bit string, but we need to represent its
  2252.      * length in bytes, because that is what the verify function expects.
  2253.      */
  2254.     DER_ConvertBitString(&rawSignature);
  2255.     rv = VFY_VerifyData(encodedTBS->data, encodedTBS->len, signerKey,
  2256. &rawSignature,
  2257. SECOID_GetAlgorithmTag(&signature->signatureAlgorithm),
  2258. pwArg);
  2259. finish:
  2260.     if (signature->wasChecked)
  2261. signature->status = rv;
  2262.     if (rv != SECSuccess) {
  2263. signature->failureReason = PORT_GetError();
  2264. if (signerCert != NULL)
  2265.     CERT_DestroyCertificate(signerCert);
  2266.     } else {
  2267. /*
  2268.  * Save signer's certificate in signature.
  2269.  */
  2270. signature->cert = signerCert;
  2271. if (pSignerCert != NULL) {
  2272.     /*
  2273.      * Pass pointer to signer's certificate back to our caller,
  2274.      * who is also now responsible for destroying it.
  2275.      */
  2276.     *pSignerCert = CERT_DupCertificate(signerCert);
  2277. }
  2278.     }
  2279.     if (encodedTBS != NULL)
  2280. SECITEM_FreeItem(encodedTBS, PR_TRUE);
  2281.     if (signerKey != NULL)
  2282. SECKEY_DestroyPublicKey(signerKey);
  2283.     if (certs != NULL)
  2284. CERT_DestroyCertArray(certs, certCount);
  2285.     return rv;
  2286. }
  2287. /*
  2288.  * FUNCTION: CERT_VerifyOCSPResponseSignature
  2289.  *   Check the signature on an OCSP Response.  Will also perform a
  2290.  *   verification of the signer's certificate.  Note, however, that a
  2291.  *   successful verification does not make any statement about the
  2292.  *   signer's *authority* to provide status for the certificate(s),
  2293.  *   that must be checked individually for each certificate.
  2294.  * INPUTS:
  2295.  *   CERTOCSPResponse *response
  2296.  *     Pointer to response structure with signature to be checked.
  2297.  *   CERTCertDBHandle *handle
  2298.  *     Pointer to CERTCertDBHandle for certificate DB to use for verification.
  2299.  *   void *pwArg
  2300.  *     Pointer to argument for password prompting, if needed.
  2301.  * OUTPUTS:
  2302.  *   CERTCertificate **pSignerCert
  2303.  *     Pointer in which to store signer's certificate; only filled-in if
  2304.  *     non-null.
  2305.  * RETURN:
  2306.  *   Returns SECSuccess when signature is valid, anything else means invalid.
  2307.  *   Possible errors set:
  2308.  * SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
  2309.  * SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
  2310.  * SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
  2311.  * SEC_ERROR_BAD_SIGNATURE - the signature did not verify
  2312.  *   Other errors are any of the many possible failures in cert verification
  2313.  *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
  2314.  *   verifying the signer's cert, or low-level problems (no memory, etc.)
  2315.  */
  2316. SECStatus
  2317. CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,
  2318.  CERTCertDBHandle *handle, void *pwArg,
  2319.  CERTCertificate **pSignerCert)
  2320. {
  2321.     ocspResponseData *tbsData; /* this is what is signed */
  2322.     PRBool byName;
  2323.     void *certIndex;
  2324.     int64 producedAt;
  2325.     SECStatus rv;
  2326.     tbsData = ocsp_GetResponseData(response);
  2327.     PORT_Assert(tbsData->responderID != NULL);
  2328.     switch (tbsData->responderID->responderIDType) {
  2329.       case ocspResponderID_byName:
  2330. byName = PR_TRUE;
  2331. certIndex = &tbsData->responderID->responderIDValue.name;
  2332. break;
  2333.       case ocspResponderID_byKey:
  2334. byName = PR_FALSE;
  2335. certIndex = &tbsData->responderID->responderIDValue.keyHash;
  2336. break;
  2337.       case ocspResponderID_other:
  2338.       default:
  2339. PORT_Assert(0);
  2340. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  2341. return SECFailure;
  2342.     }
  2343.     /*
  2344.      * ocsp_CheckSignature will also verify the signer certificate; we
  2345.      * need to tell it *when* that certificate must be valid -- for our
  2346.      * purposes we expect it to be valid when the response was signed.
  2347.      * The value of "producedAt" is the signing time.
  2348.      */
  2349.     rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
  2350.     if (rv != SECSuccess)
  2351. return rv;
  2352.     return ocsp_CheckSignature(ocsp_GetResponseSignature(response),
  2353.        tbsData, ocsp_ResponseDataTemplate,
  2354.        handle, certUsageStatusResponder, producedAt,
  2355.        byName, certIndex, pwArg, pSignerCert);
  2356. }
  2357. /*
  2358.  * See if two certIDs match.  This can be easy or difficult, depending
  2359.  * on whether the same hash algorithm was used.
  2360.  */
  2361. static PRBool
  2362. ocsp_CertIDsMatch(CERTCertDBHandle *handle,
  2363.   CERTOCSPCertID *certID1, CERTOCSPCertID *certID2)
  2364. {
  2365.     PRBool match = PR_FALSE;
  2366.     CERTCertificate *issuer1 = NULL;
  2367.     CERTCertificate *issuer2 = NULL;
  2368.     SECItem *foundHash = NULL;
  2369.     CERTCertificate *found;
  2370.     SECOidTag hashAlg;
  2371.     SECItem *givenHash;
  2372.     /*
  2373.      * In order to match, they must have the same issuer and the same
  2374.      * serial number.
  2375.      *
  2376.      * We just compare the easier things first.
  2377.      */
  2378.     if (SECITEM_CompareItem(&certID1->serialNumber,
  2379.     &certID2->serialNumber) != SECEqual) {
  2380. goto done;
  2381.     }
  2382.     if (SECOID_CompareAlgorithmID(&certID1->hashAlgorithm,
  2383.   &certID2->hashAlgorithm) == SECEqual) {
  2384. /*
  2385.  * If the hash algorithms match then we can do a simple compare
  2386.  * of the hash values themselves.
  2387.  */
  2388. if ((SECITEM_CompareItem(&certID1->issuerNameHash,
  2389.  &certID2->issuerNameHash) == SECEqual)
  2390.     && (SECITEM_CompareItem(&certID1->issuerKeyHash,
  2391.     &certID2->issuerKeyHash) == SECEqual)) {
  2392.     match = PR_TRUE;
  2393. }
  2394. goto done;
  2395.     }
  2396.     /*
  2397.      * The hash algorithms are different; this is harder.  We have
  2398.      * to do a lookup of each one and compare them.
  2399.      */
  2400.     issuer1 = CERT_FindCertBySPKDigest(handle, &certID1->issuerKeyHash);
  2401.     issuer2 = CERT_FindCertBySPKDigest(handle, &certID2->issuerKeyHash);
  2402.     if (issuer1 == NULL && issuer2 == NULL) {
  2403. /* If we cannot find an issuer cert, we have no way to compare. */
  2404. goto done;
  2405.     }
  2406.     if (issuer1 != NULL && issuer2 != NULL) {
  2407. /* If we found a cert for each hash, we can just compare them. */
  2408. if (issuer1 == issuer2)
  2409.     match = PR_TRUE;
  2410. goto done;
  2411.     }
  2412.     /*
  2413.      * We found one issuer, but not both.  So we have to use the other certID
  2414.      * hash algorithm on the key in the found issuer cert to see if they match.
  2415.      */
  2416.     if (issuer1 != NULL) {
  2417. found = issuer1;
  2418. hashAlg = SECOID_FindOIDTag(&certID2->hashAlgorithm.algorithm);
  2419. givenHash = &certID2->issuerKeyHash;
  2420.     } else {
  2421. found = issuer2;
  2422. hashAlg = SECOID_FindOIDTag(&certID1->hashAlgorithm.algorithm);
  2423. givenHash = &certID1->issuerKeyHash;
  2424.     }
  2425.     foundHash = CERT_SPKDigestValueForCert(NULL, found, hashAlg, NULL);
  2426.     if (foundHash == NULL) {
  2427. goto done;
  2428.     }
  2429.     if (SECITEM_CompareItem(foundHash, givenHash) == SECEqual) {
  2430. /*
  2431.  * Strictly speaking, we should compare the issuerNameHash, too,
  2432.  * but I think the added complexity doesn't actually buy anything.
  2433.  */
  2434. match = PR_TRUE;
  2435.     }
  2436. done:
  2437.     if (issuer1 != NULL) {
  2438. CERT_DestroyCertificate(issuer1);
  2439.     }
  2440.     if (issuer2 != NULL) {
  2441. CERT_DestroyCertificate(issuer2);
  2442.     }
  2443.     if (foundHash != NULL) {
  2444. SECITEM_FreeItem(foundHash, PR_TRUE);
  2445.     }
  2446.     return match;
  2447. }
  2448. /*
  2449.  * Find the single response for the cert specified by certID.
  2450.  * No copying is done; this just returns a pointer to the appropriate
  2451.  * response within responses, if it is found (and null otherwise).
  2452.  * This is fine, of course, since this function is internal-use only.
  2453.  */
  2454. static CERTOCSPSingleResponse *
  2455. ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses,
  2456. CERTCertDBHandle *handle,
  2457. CERTOCSPCertID *certID)
  2458. {
  2459.     CERTOCSPSingleResponse *single;
  2460.     int i;
  2461.     if (responses == NULL)
  2462. return NULL;
  2463.     for (i = 0; responses[i] != NULL; i++) {
  2464. single = responses[i];
  2465. if (ocsp_CertIDsMatch(handle, certID, single->certID) == PR_TRUE) {
  2466.     return single;
  2467. }
  2468.     }
  2469.     /*
  2470.      * The OCSP server should have included a response even if it knew
  2471.      * nothing about the certificate in question.  Since it did not,
  2472.      * this will make it look as if it had.
  2473.      * 
  2474.      * XXX Should we make this a separate error to notice the server's
  2475.      * bad behavior?
  2476.      */
  2477.     PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
  2478.     return NULL;
  2479. }
  2480. static ocspCheckingContext *
  2481. ocsp_GetCheckingContext(CERTCertDBHandle *handle)
  2482. {
  2483.     CERTStatusConfig *statusConfig;
  2484.     ocspCheckingContext *ocspcx = NULL;
  2485.     statusConfig = CERT_GetStatusConfig(handle);
  2486.     if (statusConfig != NULL) {
  2487. ocspcx = statusConfig->statusContext;
  2488. /*
  2489.  * This is actually an internal error, because we should never
  2490.  * have a good statusConfig without a good statusContext, too.
  2491.  * For lack of anything better, though, we just assert and use
  2492.  * the same error as if there were no statusConfig (set below).
  2493.  */
  2494. PORT_Assert(ocspcx != NULL);
  2495.     }
  2496.     if (ocspcx == NULL)
  2497. PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
  2498.     return ocspcx;
  2499. }
  2500. /*
  2501.  * Return true if the given signerCert is the default responder for
  2502.  * the given certID.  If not, or if any error, return false.
  2503.  */
  2504. static PRBool
  2505. ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle,
  2506.      CERTCertificate *signerCert,
  2507.      CERTOCSPCertID *certID)
  2508. {
  2509.     ocspCheckingContext *ocspcx;
  2510.     ocspcx = ocsp_GetCheckingContext(handle);
  2511.     if (ocspcx == NULL)
  2512. goto loser;
  2513.    /*
  2514.     * Right now we have only one default responder.  It applies to
  2515.     * all certs when it is used, so the check is simple and certID
  2516.     * has no bearing on the answer.  Someday in the future we may
  2517.     * allow configuration of different responders for different
  2518.     * issuers, and then we would have to use the issuer specified
  2519.     * in certID to determine if signerCert is the right one.
  2520.     */
  2521.     if (ocspcx->useDefaultResponder) {
  2522. PORT_Assert(ocspcx->defaultResponderCert != NULL);
  2523. if (ocspcx->defaultResponderCert == signerCert)
  2524.     return PR_TRUE;
  2525.     }
  2526. loser:
  2527.     return PR_FALSE;
  2528. }
  2529. /*
  2530.  * Check that the given signer certificate is authorized to sign status
  2531.  * information for the given certID.  Return true if it is, false if not
  2532.  * (or if there is any error along the way).  If false is returned because
  2533.  * the signer is not authorized, the following error will be set:
  2534.  * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
  2535.  * Other errors are low-level problems (no memory, bad database, etc.).
  2536.  *
  2537.  * There are three ways to be authorized.  In the order in which we check,
  2538.  * using the terms used in the OCSP spec, the signer must be one of:
  2539.  *  1.  A "trusted responder" -- it matches a local configuration
  2540.  *      of OCSP signing authority for the certificate in question.
  2541.  *  2.  The CA who issued the certificate in question.
  2542.  *  3.  A "CA designated responder", aka an "authorized responder" -- it
  2543.  *      must be represented by a special cert issued by the CA who issued
  2544.  *      the certificate in question.
  2545.  */
  2546. static PRBool
  2547. ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle,
  2548.   CERTCertificate *signerCert,
  2549.   CERTOCSPCertID *certID,
  2550.   int64 thisUpdate)
  2551. {
  2552.     CERTCertificate *issuerCert = NULL;
  2553.     SECItem *issuerKeyHash = NULL;
  2554.     SECOidTag hashAlg;
  2555.     PRBool okay = PR_FALSE;
  2556.     /*
  2557.      * Check first for a trusted responder, which overrides everything else.
  2558.      */
  2559.     if (ocsp_CertIsDefaultResponderForCertID(handle, signerCert, certID))
  2560. return PR_TRUE;
  2561.     /*
  2562.      * In the other two cases, we need to do an issuer comparison.
  2563.      * How we do it depends on whether the signer certificate has the
  2564.      * special extension (for a designated responder) or not.
  2565.      */
  2566.     if (ocsp_CertIsOCSPSigner(signerCert)) {
  2567. /*
  2568.  * The signer is a designated responder.  Its issuer must match
  2569.  * the issuer of the cert being checked.
  2570.  */
  2571. issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
  2572.  certUsageAnyCA);
  2573. if (issuerCert == NULL) {
  2574.     /*
  2575.      * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
  2576.      * but the following will give slightly more information.
  2577.      * Once we have an error stack, things will be much better.
  2578.      */
  2579.     PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
  2580.     goto loser;
  2581. }
  2582.     } else {
  2583. /*
  2584.  * The signer must *be* the issuer of the cert being checked.
  2585.  */
  2586. issuerCert = signerCert;
  2587.     }
  2588.     hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);
  2589.     issuerKeyHash = CERT_SPKDigestValueForCert(NULL, issuerCert, hashAlg, NULL);
  2590.     if (issuerKeyHash == NULL)
  2591. goto loser;
  2592.     if (SECITEM_CompareItem(issuerKeyHash,
  2593.     &certID->issuerKeyHash) != SECEqual) {
  2594. PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
  2595. goto loser;
  2596.     }
  2597.     okay = PR_TRUE;
  2598. loser:
  2599.     if (issuerKeyHash != NULL)
  2600. SECITEM_FreeItem(issuerKeyHash, PR_TRUE);
  2601.     if (issuerCert != NULL && issuerCert != signerCert)
  2602. CERT_DestroyCertificate(issuerCert);
  2603.     return okay;
  2604. }
  2605. /*
  2606.  * We need to check that a responder gives us "recent" information.
  2607.  * Since a responder can pre-package responses, we need to pick an amount
  2608.  * of time that is acceptable to us, and reject any response that is
  2609.  * older than that.
  2610.  *
  2611.  * XXX This *should* be based on some configuration parameter, so that
  2612.  * different usages could specify exactly what constitutes "sufficiently
  2613.  * recent".  But that is not going to happen right away.  For now, we
  2614.  * want something from within the last 24 hours.  This macro defines that
  2615.  * number in seconds.
  2616.  */
  2617. #define OCSP_ALLOWABLE_LAPSE_SECONDS (24L * 60L * 60L)
  2618. static PRBool
  2619. ocsp_TimeIsRecent(int64 checkTime)
  2620. {
  2621.     int64 now = PR_Now();
  2622.     int64 lapse, tmp;
  2623.     LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS);
  2624.     LL_I2L(tmp, PR_USEC_PER_SEC);
  2625.     LL_MUL(lapse, lapse, tmp); /* allowable lapse in microseconds */
  2626.     LL_ADD(checkTime, checkTime, lapse);
  2627.     if (LL_CMP(now, >, checkTime))
  2628. return PR_FALSE;
  2629.     return PR_TRUE;
  2630. }
  2631. /*
  2632.  * Check that this single response is okay.  A return of SECSuccess means:
  2633.  *   1. The signer (represented by "signerCert") is authorized to give status
  2634.  * for the cert represented by the individual response in "single".
  2635.  *   2. The value of thisUpdate is earlier than now.
  2636.  *   3. The value of producedAt is later than or the same as thisUpdate.
  2637.  *   4. If nextUpdate is given:
  2638.  * - The value of nextUpdate is later than now.
  2639.  * - The value of producedAt is earlier than nextUpdate.
  2640.  * Else if no nextUpdate:
  2641.  * - The value of thisUpdate is fairly recent.
  2642.  * - The value of producedAt is fairly recent.
  2643.  * However we do not need to perform an explicit check for this last
  2644.  * constraint because it is already guaranteed by checking that
  2645.  * producedAt is later than thisUpdate and thisUpdate is recent.
  2646.  * Oh, and any responder is "authorized" to say that a cert is unknown to it.
  2647.  *
  2648.  * If any of those checks fail, SECFailure is returned and an error is set:
  2649.  * SEC_ERROR_OCSP_FUTURE_RESPONSE
  2650.  * SEC_ERROR_OCSP_OLD_RESPONSE
  2651.  * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
  2652.  * Other errors are low-level problems (no memory, bad database, etc.).
  2653.  */ 
  2654. static SECStatus
  2655. ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single,
  2656.   CERTCertDBHandle *handle,
  2657.   CERTCertificate *signerCert,
  2658.   int64 producedAt)
  2659. {
  2660.     CERTOCSPCertID *certID = single->certID;
  2661.     int64 now, thisUpdate, nextUpdate;
  2662.     SECStatus rv;
  2663.     /*
  2664.      * If all the responder said was that the given cert was unknown to it,
  2665.      * that is a valid response.  Not very interesting to us, of course,
  2666.      * but all this function is concerned with is validity of the response,
  2667.      * not the status of the cert.
  2668.      */
  2669.     PORT_Assert(single->certStatus != NULL);
  2670.     if (single->certStatus->certStatusType == ocspCertStatus_unknown)
  2671. return SECSuccess;
  2672.     /*
  2673.      * We need to extract "thisUpdate" for use below and to pass along
  2674.      * to AuthorizedResponderForCertID in case it needs it for doing an
  2675.      * issuer look-up.
  2676.      */
  2677.     rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate);
  2678.     if (rv != SECSuccess)
  2679. return rv;
  2680.     /*
  2681.      * First confirm that signerCert is authorized to give this status.
  2682.      */
  2683.     if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID,
  2684.   thisUpdate) != PR_TRUE)
  2685. return SECFailure;
  2686.     /*
  2687.      * Now check the time stuff, as described above.
  2688.      */
  2689.     now = PR_Now();
  2690.     if (LL_CMP(thisUpdate, >, now) || LL_CMP(producedAt, <, thisUpdate)) {
  2691. PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE);
  2692. return SECFailure;
  2693.     }
  2694.     if (single->nextUpdate != NULL) {
  2695. rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate);
  2696. if (rv != SECSuccess)
  2697.     return rv;
  2698. if (LL_CMP(nextUpdate, <, now) || LL_CMP(producedAt, >, nextUpdate)) {
  2699.     PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
  2700.     return SECFailure;
  2701. }
  2702.     } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) {
  2703. PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
  2704. return SECFailure;
  2705.     }
  2706.     return SECSuccess;
  2707. }
  2708. /*
  2709.  * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation
  2710.  *   Get the value of the URI of the OCSP responder for the given cert.
  2711.  *   This is found in the (optional) Authority Information Access extension
  2712.  *   in the cert.
  2713.  * INPUTS:
  2714.  *   CERTCertificate *cert
  2715.  *     The certificate being examined.
  2716.  * RETURN:
  2717.  *   char *
  2718.  *     A copy of the URI for the OCSP method, if found.  If either the
  2719.  *     extension is not present or it does not contain an entry for OCSP,
  2720.  *     SEC_ERROR_EXTENSION_NOT_FOUND will be set and a NULL returned.
  2721.  *     Any other error will also result in a NULL being returned.
  2722.  *     
  2723.  *     This result should be freed (via PORT_Free) when no longer in use.
  2724.  */
  2725. char *
  2726. CERT_GetOCSPAuthorityInfoAccessLocation(CERTCertificate *cert)
  2727. {
  2728.     CERTGeneralName *locname = NULL;
  2729.     SECItem *location = NULL;
  2730.     SECItem *encodedAuthInfoAccess = NULL;
  2731.     CERTAuthInfoAccess **authInfoAccess = NULL;
  2732.     char *locURI = NULL;
  2733.     PRArenaPool *arena = NULL;
  2734.     SECStatus rv;
  2735.     int i;
  2736.     /*
  2737.      * Allocate this one from the heap because it will get filled in
  2738.      * by CERT_FindCertExtension which will also allocate from the heap,
  2739.      * and we can free the entire thing on our way out.
  2740.      */
  2741.     encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
  2742.     if (encodedAuthInfoAccess == NULL)
  2743. goto loser;
  2744.     rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
  2745. encodedAuthInfoAccess);
  2746.     if (rv == SECFailure)
  2747. goto loser;
  2748.     /*
  2749.      * The rest of the things allocated in the routine will come out of
  2750.      * this arena, which is temporary just for us to decode and get at the
  2751.      * AIA extension.  The whole thing will be destroyed on our way out,
  2752.      * after we have copied the location string (url) itself (if found).
  2753.      */
  2754.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  2755.     if (arena == NULL)
  2756. goto loser;
  2757.     authInfoAccess = cert_DecodeAuthInfoAccessExtension(arena,
  2758. encodedAuthInfoAccess);
  2759.     if (authInfoAccess == NULL)
  2760. goto loser;
  2761.     for (i = 0; authInfoAccess[i] != NULL; i++) {
  2762. if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP)
  2763.     locname = authInfoAccess[i]->location;
  2764.     }
  2765.     /*
  2766.      * If we found an AIA extension, but it did not include an OCSP method,
  2767.      * that should look to our caller as if we did not find the extension
  2768.      * at all, because it is only an OCSP method that we care about.
  2769.      * So set the same error that would be set if the AIA extension was
  2770.      * not there at all.
  2771.      */
  2772.     if (locname == NULL) {
  2773. PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
  2774. goto loser;
  2775.     }
  2776.     /*
  2777.      * The following is just a pointer back into locname (i.e. not a copy);
  2778.      * thus it should not be freed.
  2779.      */
  2780.     location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
  2781.     if (location == NULL) {
  2782. /*
  2783.  * XXX Appears that CERT_GetGeneralNameByType does not set an
  2784.  * error if there is no name by that type.  For lack of anything
  2785.  * better, act as if the extension was not found.  In the future
  2786.  * this should probably be something more like the extension was
  2787.  * badly formed.
  2788.  */
  2789. PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
  2790. goto loser;
  2791.     }
  2792.     /*
  2793.      * That location is really a string, but it has a specified length
  2794.      * without a null-terminator.  We need a real string that does have
  2795.      * a null-terminator, and we need a copy of it anyway to return to
  2796.      * our caller -- so allocate and copy.
  2797.      */
  2798.     locURI = PORT_Alloc(location->len + 1);
  2799.     if (locURI == NULL) {
  2800. goto loser;
  2801.     }
  2802.     PORT_Memcpy(locURI, location->data, location->len);
  2803.     locURI[location->len] = '';
  2804. loser:
  2805.     if (arena != NULL)
  2806. PORT_FreeArena(arena, PR_FALSE);
  2807.     if (encodedAuthInfoAccess != NULL)
  2808. SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);
  2809.     return locURI;
  2810. }
  2811. /*
  2812.  * Figure out where we should go to find out the status of the given cert
  2813.  * via OCSP.  If a default responder is set up, that is our answer.
  2814.  * If not, see if the certificate has an Authority Information Access (AIA)
  2815.  * extension for OCSP, and return the value of that.  Otherwise return NULL.
  2816.  * We also let our caller know whether or not the responder chosen was
  2817.  * a default responder or not through the output variable isDefault;
  2818.  * its value has no meaning unless a good (non-null) value is returned
  2819.  * for the location.
  2820.  *
  2821.  * The result needs to be freed (PORT_Free) when no longer in use.
  2822.  */
  2823. static char *
  2824. ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert,
  2825.   PRBool *isDefault)
  2826. {
  2827.     ocspCheckingContext *ocspcx;
  2828.     ocspcx = ocsp_GetCheckingContext(handle);
  2829.     if (ocspcx != NULL && ocspcx->useDefaultResponder) {
  2830. /*
  2831.  * A default responder wins out, if specified.
  2832.  * XXX Someday this may be a more complicated determination based
  2833.  * on the cert's issuer.  (That is, we could have different default
  2834.  * responders configured for different issuers.)
  2835.  */
  2836. PORT_Assert(ocspcx->defaultResponderURI != NULL);
  2837. *isDefault = PR_TRUE;
  2838. return (PORT_Strdup(ocspcx->defaultResponderURI));
  2839.     }
  2840.     /*
  2841.      * No default responder set up, so go see if we can find an AIA
  2842.      * extension that has a value for OCSP, and get the url from that.
  2843.      */
  2844.     *isDefault = PR_FALSE;
  2845.     return CERT_GetOCSPAuthorityInfoAccessLocation(cert);
  2846. }
  2847. /*
  2848.  * Return SECSuccess if the cert was revoked *after* "time",
  2849.  * SECFailure otherwise.
  2850.  */
  2851. static SECStatus
  2852. ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time)
  2853. {
  2854.     int64 revokedTime;
  2855.     SECStatus rv;
  2856.     rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime);
  2857.     if (rv != SECSuccess)
  2858. return rv;
  2859.     /*
  2860.      * Set the error even if we will return success; someone might care.
  2861.      */
  2862.     PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
  2863.     if (LL_CMP(revokedTime, >, time))
  2864. return SECSuccess;
  2865.     return SECFailure;
  2866. }
  2867. /*
  2868.  * See if the cert represented in the single response had a good status
  2869.  * at the specified time.
  2870.  */
  2871. static SECStatus
  2872. ocsp_CertHasGoodStatus(CERTOCSPSingleResponse *single, int64 time)
  2873. {
  2874.     ocspCertStatus *status;
  2875.     SECStatus rv;
  2876.     status = single->certStatus;
  2877.     switch (status->certStatusType) {
  2878.       case ocspCertStatus_good:
  2879. rv = SECSuccess;
  2880. break;
  2881.       case ocspCertStatus_revoked:
  2882. rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
  2883. break;
  2884.       case ocspCertStatus_unknown:
  2885. PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
  2886. rv = SECFailure;
  2887. break;
  2888.       case ocspCertStatus_other:
  2889.       default:
  2890. PORT_Assert(0);
  2891. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  2892. rv = SECFailure;
  2893. break;
  2894.     }
  2895.     return rv;
  2896. }
  2897. /*
  2898.  * FUNCTION: CERT_CheckOCSPStatus
  2899.  *   Checks the status of a certificate via OCSP.  Will only check status for
  2900.  *   a certificate that has an AIA (Authority Information Access) extension
  2901.  *   for OCSP *or* when a "default responder" is specified and enabled.
  2902.  *   (If no AIA extension for OCSP and no default responder in place, the
  2903.  *   cert is considered to have a good status and SECSuccess is returned.)
  2904.  * INPUTS:
  2905.  *   CERTCertDBHandle *handle
  2906.  *     certificate DB of the cert that is being checked
  2907.  *   CERTCertificate *cert
  2908.  *     the certificate being checked
  2909.  *   XXX in the long term also need a boolean parameter that specifies
  2910.  * whether to check the cert chain, as well; for now we check only
  2911.  * the leaf (the specified certificate)
  2912.  *   int64 time
  2913.  *     time for which status is to be determined
  2914.  *   void *pwArg
  2915.  *     argument for password prompting, if needed
  2916.  * RETURN:
  2917.  *   Returns SECSuccess if an approved OCSP responder "knows" the cert
  2918.  *   *and* returns a non-revoked status for it; SECFailure otherwise,
  2919.  *   with an error set describing the reason:
  2920.  *
  2921.  * SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
  2922.  * SEC_ERROR_OCSP_FUTURE_RESPONSE
  2923.  * SEC_ERROR_OCSP_MALFORMED_REQUEST
  2924.  * SEC_ERROR_OCSP_MALFORMED_RESPONSE
  2925.  * SEC_ERROR_OCSP_OLD_RESPONSE
  2926.  * SEC_ERROR_OCSP_REQUEST_NEEDS_SIG
  2927.  * SEC_ERROR_OCSP_SERVER_ERROR
  2928.  * SEC_ERROR_OCSP_TRY_SERVER_LATER
  2929.  * SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST
  2930.  * SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
  2931.  * SEC_ERROR_OCSP_UNKNOWN_CERT
  2932.  * SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
  2933.  * SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE
  2934.  *
  2935.  * SEC_ERROR_BAD_SIGNATURE
  2936.  * SEC_ERROR_CERT_BAD_ACCESS_LOCATION
  2937.  * SEC_ERROR_INVALID_TIME
  2938.  * SEC_ERROR_REVOKED_CERTIFICATE
  2939.  * SEC_ERROR_UNKNOWN_ISSUER
  2940.  * SEC_ERROR_UNKNOWN_SIGNER
  2941.  *
  2942.  *   Other errors are any of the many possible failures in cert verification
  2943.  *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
  2944.  *   verifying the signer's cert, or low-level problems (error allocating
  2945.  *   memory, error performing ASN.1 decoding, etc.).
  2946.  */    
  2947. SECStatus 
  2948. CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
  2949.      int64 time, void *pwArg)
  2950. {
  2951.     char *location = NULL;
  2952.     PRBool locationIsDefault;
  2953.     CERTCertList *certList = NULL;
  2954.     SECItem *encodedResponse = NULL;
  2955.     CERTOCSPRequest *request = NULL;
  2956.     CERTOCSPResponse *response = NULL;
  2957.     CERTCertificate *signerCert = NULL;
  2958.     ocspResponseData *responseData;
  2959.     int64 producedAt;
  2960.     CERTOCSPCertID *certID;
  2961.     CERTOCSPSingleResponse *single;
  2962.     SECStatus rv = SECFailure;
  2963.     /*
  2964.      * The first thing we need to do is find the location of the responder.
  2965.      * This will be the value of the default responder (if enabled), else
  2966.      * it will come out of the AIA extension in the cert (if present).
  2967.      * If we have no such location, then this cert does not "deserve" to
  2968.      * be checked -- that is, we consider it a success and just return.
  2969.      * The way we tell that is by looking at the error number to see if
  2970.      * the problem was no AIA extension was found; any other error was
  2971.      * a true failure that we unfortunately have to treat as an overall
  2972.      * failure here.
  2973.      */
  2974.     location = ocsp_GetResponderLocation(handle, cert, &locationIsDefault);
  2975.     if (location == NULL) {
  2976. if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND)
  2977.     return SECSuccess;
  2978. else
  2979.     return SECFailure;
  2980.     }
  2981.     /*
  2982.      * For now, create a cert-list of one.
  2983.      * XXX In the fullness of time, we will want/need to handle a
  2984.      * certificate chain.  This will be done either when a new parameter
  2985.      * tells us to, or some configuration variable tells us to.  In any
  2986.      * case, handling it is complicated because we may need to send as
  2987.      * many requests (and receive as many responses) as we have certs
  2988.      * in the chain.  If we are going to talk to a default responder,
  2989.      * and we only support one default responder, we can put all of the
  2990.      * certs together into one request.  Otherwise, we must break them up
  2991.      * into multiple requests.  (Even if all of the requests will go to
  2992.      * the same location, the signature on each response will be different,
  2993.      * because each issuer is different.  Carefully read the OCSP spec
  2994.      * if you do not understand this.)
  2995.      */
  2996.     certList = CERT_NewCertList();
  2997.     if (certList == NULL)
  2998. goto loser;
  2999.     /* dup it because freeing the list will destroy the cert, too */
  3000.     cert = CERT_DupCertificate(cert);
  3001.     if (cert == NULL)
  3002. goto loser;
  3003.     if (CERT_AddCertToListTail(certList, cert) != SECSuccess) {
  3004. CERT_DestroyCertificate(cert);
  3005. goto loser;
  3006.     }
  3007.     /*
  3008.      * XXX If/when signing of requests is supported, that second NULL
  3009.      * should be changed to be the signer certificate.  Not sure if that
  3010.      * should be passed into this function or retrieved via some operation
  3011.      * on the handle/context.
  3012.      */
  3013.     encodedResponse = CERT_GetEncodedOCSPResponse(NULL, certList, location,
  3014.   time, locationIsDefault,
  3015.   NULL, pwArg, &request);
  3016.     if (encodedResponse == NULL) {
  3017. goto loser;
  3018.     }
  3019.     response = CERT_DecodeOCSPResponse(encodedResponse);
  3020.     if (response == NULL) {
  3021. goto loser;
  3022.     }
  3023.     /*
  3024.      * Okay, we at least have a response that *looks* like a response!
  3025.      * Now see if the overall response status value is good or not.
  3026.      * If not, we set an error and give up.  (It means that either the
  3027.      * server had a problem, or it didn't like something about our
  3028.      * request.  Either way there is nothing to do but give up.)
  3029.      * Otherwise, we continue to find the actual per-cert status
  3030.      * in the response.
  3031.      */
  3032.     switch (response->statusValue) {
  3033.       case ocspResponse_successful:
  3034. break;
  3035.       case ocspResponse_malformedRequest:
  3036. PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
  3037. goto loser;
  3038.       case ocspResponse_internalError:
  3039. PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
  3040. goto loser;
  3041.       case ocspResponse_tryLater:
  3042. PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER);
  3043. goto loser;
  3044.       case ocspResponse_sigRequired:
  3045. /* XXX We *should* retry with a signature, if possible. */
  3046. PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
  3047. goto loser;
  3048.       case ocspResponse_unauthorized:
  3049. PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
  3050. goto loser;
  3051.       case ocspResponse_other:
  3052.       case ocspResponse_unused:
  3053.       default:
  3054. PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
  3055. goto loser;
  3056.     }
  3057.     /*
  3058.      * If we've made it this far, we expect a response with a good signature.
  3059.      * So, check for that.
  3060.      */
  3061.     rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert);
  3062.     if (rv != SECSuccess)
  3063. goto loser;
  3064.     PORT_Assert(signerCert != NULL); /* internal consistency check */
  3065.     /* XXX probably should set error, return failure if signerCert is null */
  3066.     /*
  3067.      * The ResponseData part is the real guts of the response.
  3068.      */
  3069.     responseData = ocsp_GetResponseData(response);
  3070.     if (responseData == NULL) {
  3071. rv = SECFailure;
  3072. goto loser;
  3073.     }
  3074.     /*
  3075.      * There is one producedAt time for the entire response (and a separate
  3076.      * thisUpdate time for each individual single response).  We need to
  3077.      * compare them, so get the overall time to pass into the check of each
  3078.      * single response.
  3079.      */
  3080.     rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt);
  3081.     if (rv != SECSuccess)
  3082. goto loser;
  3083.     /*
  3084.      * Again, we are only doing one request for one cert.
  3085.      * XXX When we handle cert chains, the following code will obviously
  3086.      * have to be modified, in coordation with the code above that will
  3087.      * have to determine how to make multiple requests, etc.  It will need
  3088.      * to loop, and for each certID in the request, find the matching
  3089.      * single response and check the status specified by it.
  3090.      *
  3091.      * We are helped here in that we know that the requests are made with
  3092.      * the request list in the same order as the order of the certs we hand
  3093.      * to it.  This is why I can directly access the first member of the
  3094.      * single request array for the one cert I care about.
  3095.      */
  3096.     certID = request->tbsRequest->requestList[0]->reqCert;
  3097.     single = ocsp_GetSingleResponseForCertID(responseData->responses,
  3098.      handle, certID);
  3099.     if (single == NULL)
  3100. goto loser;
  3101.     rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
  3102.     if (rv != SECSuccess)
  3103. goto loser;
  3104.     /*
  3105.      * Okay, the last step is to check whether the status says revoked,
  3106.      * and if so how that compares to the time value passed into this routine.
  3107.      */
  3108.     rv = ocsp_CertHasGoodStatus(single, time);
  3109. loser:
  3110.     if (signerCert != NULL)
  3111. CERT_DestroyCertificate(signerCert);
  3112.     if (response != NULL)
  3113. CERT_DestroyOCSPResponse(response);
  3114.     if (request != NULL)
  3115. CERT_DestroyOCSPRequest(request);
  3116.     if (encodedResponse != NULL)
  3117. SECITEM_FreeItem(encodedResponse, PR_TRUE);
  3118.     if (certList != NULL)
  3119. CERT_DestroyCertList(certList);
  3120.     if (location != NULL)
  3121. PORT_Free(location);
  3122.     return rv;
  3123. }
  3124. /*
  3125.  * Disable status checking and destroy related structures/data.
  3126.  */
  3127. static SECStatus
  3128. ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig)
  3129. {
  3130.     ocspCheckingContext *statusContext;
  3131.     /*
  3132.      * Disable OCSP checking
  3133.      */
  3134.     statusConfig->statusChecker = NULL;
  3135.     statusContext = statusConfig->statusContext;
  3136.     PORT_Assert(statusContext != NULL);
  3137.     if (statusContext == NULL)
  3138. return SECFailure;
  3139.     if (statusContext->defaultResponderURI != NULL)
  3140. PORT_Free(statusContext->defaultResponderURI);
  3141.     if (statusContext->defaultResponderNickname != NULL)
  3142. PORT_Free(statusContext->defaultResponderNickname);
  3143.     PORT_Free(statusContext);
  3144.     statusConfig->statusContext = NULL;
  3145.     PORT_Free(statusConfig);
  3146.     return SECSuccess;
  3147. }
  3148. /*
  3149.  * FUNCTION: CERT_DisableOCSPChecking
  3150.  *   Turns off OCSP checking for the given certificate database.
  3151.  *   This routine disables OCSP checking.  Though it will return
  3152.  *   SECFailure if OCSP checking is not enabled, it is "safe" to
  3153.  *   call it that way and just ignore the return value, if it is
  3154.  *   easier to just call it than to "remember" whether it is enabled.
  3155.  * INPUTS:
  3156.  *   CERTCertDBHandle *handle
  3157.  *     Certificate database for which OCSP checking will be disabled.
  3158.  * RETURN:
  3159.  *   Returns SECFailure if an error occurred (usually means that OCSP
  3160.  *   checking was not enabled or status contexts were not initialized --
  3161.  *   error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise.
  3162.  */
  3163. SECStatus
  3164. CERT_DisableOCSPChecking(CERTCertDBHandle *handle)
  3165. {
  3166.     CERTStatusConfig *statusConfig;
  3167.     ocspCheckingContext *statusContext;
  3168.     if (handle == NULL) {
  3169. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3170. return SECFailure;
  3171.     }
  3172.     statusConfig = CERT_GetStatusConfig(handle);
  3173.     statusContext = ocsp_GetCheckingContext(handle);
  3174.     if (statusContext == NULL)
  3175. return SECFailure;
  3176.     if (statusConfig->statusChecker != CERT_CheckOCSPStatus) {
  3177. /*
  3178.  * Status configuration is present, but either not currently
  3179.  * enabled or not for OCSP.
  3180.  */
  3181. PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
  3182. return SECFailure;
  3183.     }
  3184.     /*
  3185.      * This is how we disable status checking.  Everything else remains
  3186.      * in place in case we are enabled again.
  3187.      */
  3188.     statusConfig->statusChecker = NULL;
  3189.     return SECSuccess;
  3190. }
  3191. /*
  3192.  * Allocate and initialize the informational structures for status checking.
  3193.  * This is done when some configuration of OCSP is being done or when OCSP
  3194.  * checking is being turned on, whichever comes first.
  3195.  */
  3196. static SECStatus
  3197. ocsp_InitStatusChecking(CERTCertDBHandle *handle)
  3198. {
  3199.     CERTStatusConfig *statusConfig = NULL;
  3200.     ocspCheckingContext *statusContext = NULL;
  3201.     PORT_Assert(CERT_GetStatusConfig(handle) == NULL);
  3202.     if (CERT_GetStatusConfig(handle) != NULL) {
  3203. /* XXX or call statusConfig->statusDestroy and continue? */
  3204. return SECFailure;
  3205.     }
  3206.     statusConfig = PORT_ZNew(CERTStatusConfig);
  3207.     if (statusConfig == NULL)
  3208. goto loser;
  3209.     statusContext = PORT_ZNew(ocspCheckingContext);
  3210.     if (statusContext == NULL)
  3211. goto loser;
  3212.     statusConfig->statusDestroy = ocsp_DestroyStatusChecking;
  3213.     statusConfig->statusContext = statusContext;
  3214.     CERT_SetStatusConfig(handle, statusConfig);
  3215.     return SECSuccess;
  3216. loser:
  3217.     if (statusContext != NULL)
  3218. PORT_Free(statusContext);
  3219.     if (statusConfig != NULL)
  3220. PORT_Free(statusConfig);
  3221.     return SECFailure;
  3222. }
  3223. /*
  3224.  * FUNCTION: CERT_EnableOCSPChecking
  3225.  *   Turns on OCSP checking for the given certificate database.
  3226.  * INPUTS:
  3227.  *   CERTCertDBHandle *handle
  3228.  *     Certificate database for which OCSP checking will be enabled.
  3229.  * RETURN:
  3230.  *   Returns SECFailure if an error occurred (likely only problem
  3231.  *   allocating memory); SECSuccess otherwise.
  3232.  */
  3233. SECStatus
  3234. CERT_EnableOCSPChecking(CERTCertDBHandle *handle)
  3235. {
  3236.     CERTStatusConfig *statusConfig;
  3237.     
  3238.     SECStatus rv;
  3239.     if (handle == NULL) {
  3240. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3241. return SECFailure;
  3242.     }
  3243.     statusConfig = CERT_GetStatusConfig(handle);
  3244.     if (statusConfig == NULL) {
  3245. rv = ocsp_InitStatusChecking(handle);
  3246. if (rv != SECSuccess)
  3247.     return rv;
  3248. /* Get newly established value */
  3249. statusConfig = CERT_GetStatusConfig(handle);
  3250. PORT_Assert(statusConfig != NULL);
  3251.     }
  3252.     /*
  3253.      * Setting the checker function is what really enables the checking
  3254.      * when each cert verification is done.
  3255.      */
  3256.     statusConfig->statusChecker = CERT_CheckOCSPStatus;
  3257.     return SECSuccess;
  3258. }
  3259. /*
  3260.  * FUNCTION: CERT_SetOCSPDefaultResponder
  3261.  *   Specify the location and cert of the default responder.
  3262.  *   If OCSP checking is already enabled *and* use of a default responder
  3263.  *   is also already enabled, all OCSP checking from now on will go directly
  3264.  *   to the specified responder.  If OCSP checking is not enabled, or if
  3265.  *   it is but use of a default responder is not enabled, the information
  3266.  *   will be recorded and take effect whenever both are enabled.
  3267.  * INPUTS:
  3268.  *   CERTCertDBHandle *handle
  3269.  *     Cert database on which OCSP checking should use the default responder.
  3270.  *   char *url
  3271.  *     The location of the default responder (e.g. "http://foo.com:80/ocsp")
  3272.  *     Note that the location will not be tested until the first attempt
  3273.  *     to send a request there.
  3274.  *   char *name
  3275.  *     The nickname of the cert to trust (expected) to sign the OCSP responses.
  3276.  *     If the corresponding cert cannot be found, SECFailure is returned.
  3277.  * RETURN:
  3278.  *   Returns SECFailure if an error occurred; SECSuccess otherwise.
  3279.  *   The most likely error is that the cert for "name" could not be found
  3280.  *   (probably SEC_ERROR_UNKNOWN_CERT).  Other errors are low-level (no memory,
  3281.  *   bad database, etc.).
  3282.  */
  3283. SECStatus
  3284. CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle,
  3285.      const char *url, const char *name)
  3286. {
  3287.     CERTCertificate *cert;
  3288.     ocspCheckingContext *statusContext;
  3289.     char *url_copy = NULL;
  3290.     char *name_copy = NULL;
  3291.     SECStatus rv;
  3292.     if (handle == NULL || url == NULL || name == NULL) {
  3293. /*
  3294.  * XXX When interface is exported, probably want better errors;
  3295.  * perhaps different one for each parameter.
  3296.  */
  3297. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3298. return SECFailure;
  3299.     }
  3300.     /*
  3301.      * Find the certificate for the specified nickname.  Do this first
  3302.      * because it seems the most likely to fail.
  3303.      *
  3304.      * XXX Shouldn't need that cast if the FindCertByNickname interface
  3305.      * used const to convey that it does not modify the name.  Maybe someday.
  3306.      */
  3307.     cert = CERT_FindCertByNickname(handle, (char *) name);
  3308.     if (cert == NULL)
  3309. return SECFailure;
  3310.     /*
  3311.      * Make a copy of the url and nickname.
  3312.      */
  3313.     url_copy = PORT_Strdup(url);
  3314.     name_copy = PORT_Strdup(name);
  3315.     if (url_copy == NULL || name_copy == NULL) {
  3316. rv = SECFailure;
  3317. goto loser;
  3318.     }
  3319.     statusContext = ocsp_GetCheckingContext(handle);
  3320.     /*
  3321.      * Allocate and init the context if it doesn't already exist.
  3322.      */
  3323.     if (statusContext == NULL) {
  3324. rv = ocsp_InitStatusChecking(handle);
  3325. if (rv != SECSuccess)
  3326.     goto loser;
  3327. statusContext = ocsp_GetCheckingContext(handle);
  3328. PORT_Assert(statusContext != NULL); /* extreme paranoia */
  3329.     }
  3330.     /*
  3331.      * Note -- we do not touch the status context until after all of
  3332.      * the steps which could cause errors.  If something goes wrong,
  3333.      * we want to leave things as they were.
  3334.      */
  3335.     /*
  3336.      * Get rid of old url and name if there.
  3337.      */
  3338.     if (statusContext->defaultResponderNickname != NULL)
  3339. PORT_Free(statusContext->defaultResponderNickname);
  3340.     if (statusContext->defaultResponderURI != NULL)
  3341. PORT_Free(statusContext->defaultResponderURI);
  3342.     /*
  3343.      * And replace them with the new ones.
  3344.      */
  3345.     statusContext->defaultResponderURI = url_copy;
  3346.     statusContext->defaultResponderNickname = name_copy;
  3347.     /*
  3348.      * If there was already a cert in place, get rid of it and replace it.
  3349.      * Otherwise, we are not currently enabled, so we don't want to save it;
  3350.      * it will get re-found and set whenever use of a default responder is
  3351.      * enabled.
  3352.      */
  3353.     if (statusContext->defaultResponderCert != NULL) {
  3354. CERT_DestroyCertificate(statusContext->defaultResponderCert);
  3355. statusContext->defaultResponderCert = cert;
  3356.     } else {
  3357. PORT_Assert(statusContext->useDefaultResponder == PR_FALSE);
  3358. CERT_DestroyCertificate(cert);
  3359.     }
  3360.     return SECSuccess;
  3361. loser:
  3362.     CERT_DestroyCertificate(cert);
  3363.     if (url_copy != NULL)
  3364. PORT_Free(url_copy);
  3365.     if (name_copy != NULL)
  3366. PORT_Free(name_copy);
  3367.     return rv;
  3368. }
  3369. /*
  3370.  * FUNCTION: CERT_EnableOCSPDefaultResponder
  3371.  *   Turns on use of a default responder when OCSP checking.
  3372.  *   If OCSP checking is already enabled, this will make subsequent checks
  3373.  *   go directly to the default responder.  (The location of the responder
  3374.  *   and the nickname of the responder cert must already be specified.)
  3375.  *   If OCSP checking is not enabled, this will be recorded and take effect
  3376.  *   whenever it is enabled.
  3377.  * INPUTS:
  3378.  *   CERTCertDBHandle *handle
  3379.  *     Cert database on which OCSP checking should use the default responder.
  3380.  * RETURN:
  3381.  *   Returns SECFailure if an error occurred; SECSuccess otherwise.
  3382.  *   No errors are especially likely unless the caller did not previously
  3383.  *   perform a successful call to SetOCSPDefaultResponder (in which case
  3384.  *   the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER).
  3385.  */
  3386. SECStatus
  3387. CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle)
  3388. {
  3389.     ocspCheckingContext *statusContext;
  3390.     CERTCertificate *cert;
  3391.     if (handle == NULL) {
  3392. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3393. return SECFailure;
  3394.     }
  3395.     statusContext = ocsp_GetCheckingContext(handle);
  3396.     if (statusContext == NULL) {
  3397. /*
  3398.  * Strictly speaking, the error already set is "correct",
  3399.  * but cover over it with one more helpful in this context.
  3400.  */
  3401. PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
  3402. return SECFailure;
  3403.     }
  3404.     if (statusContext->defaultResponderURI == NULL) {
  3405. PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
  3406. return SECFailure;
  3407.     }
  3408.     if (statusContext->defaultResponderNickname == NULL) {
  3409. PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
  3410. return SECFailure;
  3411.     }
  3412.     /*
  3413.      * Find the cert for the nickname.
  3414.      */
  3415.     cert = CERT_FindCertByNickname(handle,
  3416.    statusContext->defaultResponderNickname);
  3417.     /*
  3418.      * We should never have trouble finding the cert, because its
  3419.      * existence should have been proven by SetOCSPDefaultResponder.
  3420.      */
  3421.     PORT_Assert(cert != NULL);
  3422.     if (cert == NULL)
  3423. return SECFailure;
  3424.     /*
  3425.      * And hang onto it.
  3426.      */
  3427.     statusContext->defaultResponderCert = cert;
  3428.     /*
  3429.      * Finally, record the fact that we now have a default responder enabled.
  3430.      */
  3431.     statusContext->useDefaultResponder = PR_TRUE;
  3432.     return SECSuccess;
  3433. }
  3434. /*
  3435.  * FUNCTION: CERT_DisableOCSPDefaultResponder
  3436.  *   Turns off use of a default responder when OCSP checking.
  3437.  *   (Does nothing if use of a default responder is not enabled.)
  3438.  * INPUTS:
  3439.  *   CERTCertDBHandle *handle
  3440.  *     Cert database on which OCSP checking should stop using a default
  3441.  *     responder.
  3442.  * RETURN:
  3443.  *   Returns SECFailure if an error occurred; SECSuccess otherwise.
  3444.  *   Errors very unlikely (like random memory corruption...).
  3445.  */
  3446. SECStatus
  3447. CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle)
  3448. {
  3449.     CERTStatusConfig *statusConfig;
  3450.     ocspCheckingContext *statusContext;
  3451.     if (handle == NULL) {
  3452. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  3453. return SECFailure;
  3454.     }
  3455.     statusConfig = CERT_GetStatusConfig(handle);
  3456.     if (statusConfig == NULL)
  3457. return SECSuccess;
  3458.     statusContext = ocsp_GetCheckingContext(handle);
  3459.     PORT_Assert(statusContext != NULL);
  3460.     if (statusContext == NULL)
  3461. return SECFailure;
  3462.     if (statusContext->defaultResponderCert != NULL) {
  3463. CERT_DestroyCertificate(statusContext->defaultResponderCert);
  3464. statusContext->defaultResponderCert = NULL;
  3465.     }
  3466.     /*
  3467.      * Finally, record the fact.
  3468.      */
  3469.     statusContext->useDefaultResponder = PR_FALSE;
  3470.     return SECSuccess;
  3471. }