Back to index

lightning-sunbird  0.9+nobinonly
ocsp.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * Implementation of OCSP services, for both client and server.
00039  * (XXX, really, mostly just for client right now, but intended to do both.)
00040  *
00041  * $Id: ocsp.c,v 1.21.2.8 2006/11/13 18:22:26 wtchang%redhat.com Exp $
00042  */
00043 
00044 #include "prerror.h"
00045 #include "prprf.h"
00046 #include "plarena.h"
00047 #include "prnetdb.h"
00048 
00049 #include "seccomon.h"
00050 #include "secitem.h"
00051 #include "secoidt.h"
00052 #include "secasn1.h"
00053 #include "secder.h"
00054 #include "cert.h"
00055 #include "xconst.h"
00056 #include "secerr.h"
00057 #include "secoid.h"
00058 #include "hasht.h"
00059 #include "sechash.h"
00060 #include "secasn1.h"
00061 #include "keyhi.h"
00062 #include "cryptohi.h"
00063 #include "ocsp.h"
00064 #include "ocspti.h"
00065 #include "genname.h"
00066 #include "certxutl.h"
00067 #include "pk11func.h"       /* for PK11_HashBuf */
00068 #include <stdarg.h>
00069 
00070 
00071 static struct OCSPGlobalStruct {
00072     PRLock *lock;
00073     const SEC_HttpClientFcn *defaultHttpClientFcn;
00074 } OCSP_Global = { NULL, NULL };
00075 
00076 SECStatus
00077 SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable)
00078 {
00079     if (!OCSP_Global.lock) {
00080       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
00081       return SECFailure;
00082     }
00083     
00084     PR_Lock(OCSP_Global.lock);
00085     OCSP_Global.defaultHttpClientFcn = fcnTable;
00086     PR_Unlock(OCSP_Global.lock);
00087     
00088     return SECSuccess;
00089 }
00090 
00091 /* this function is called at NSS initialization time */
00092 SECStatus InitOCSPGlobal(void)
00093 {
00094   if (OCSP_Global.lock != NULL) {
00095     /* already initialized */
00096     return SECSuccess;
00097   }
00098   
00099   OCSP_Global.lock = PR_NewLock();
00100   
00101   return (OCSP_Global.lock) ? SECSuccess : SECFailure;
00102 }
00103 
00104 /*
00105  * A return value of NULL means: 
00106  *   The application did not register it's own HTTP client.
00107  */
00108 static const SEC_HttpClientFcn *GetRegisteredHttpClient()
00109 {
00110     const SEC_HttpClientFcn *retval;
00111 
00112     if (!OCSP_Global.lock) {
00113       PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
00114       return NULL;
00115     }
00116 
00117     PR_Lock(OCSP_Global.lock);
00118     retval = OCSP_Global.defaultHttpClientFcn;
00119     PR_Unlock(OCSP_Global.lock);
00120     
00121     return retval;
00122 }
00123 
00124 /*
00125  * The following structure is only used internally.  It is allocated when
00126  * someone turns on OCSP checking, and hangs off of the status-configuration
00127  * structure in the certdb structure.  We use it to keep configuration
00128  * information specific to OCSP checking.
00129  */
00130 typedef struct ocspCheckingContextStr {
00131     PRBool useDefaultResponder;
00132     char *defaultResponderURI;
00133     char *defaultResponderNickname;
00134     CERTCertificate *defaultResponderCert;
00135 } ocspCheckingContext;
00136 
00137 
00138 /*
00139  * Forward declarations of sub-types, so I can lay out the types in the
00140  * same order as the ASN.1 is laid out in the OCSP spec itself.
00141  *
00142  * These are in alphabetical order (case-insensitive); please keep it that way!
00143  */
00144 extern const SEC_ASN1Template ocsp_CertIDTemplate[];
00145 extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[];
00146 extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[];
00147 extern const SEC_ASN1Template ocsp_ResponseDataTemplate[];
00148 extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[];
00149 extern const SEC_ASN1Template ocsp_SingleRequestTemplate[];
00150 extern const SEC_ASN1Template ocsp_SingleResponseTemplate[];
00151 extern const SEC_ASN1Template ocsp_TBSRequestTemplate[];
00152 
00153 
00154 /*
00155  * Request-related templates...
00156  */
00157 
00158 /*
00159  * OCSPRequest       ::=    SEQUENCE {
00160  *     tbsRequest           TBSRequest,
00161  *     optionalSignature    [0] EXPLICIT Signature OPTIONAL }
00162  */
00163 static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = {
00164     { SEC_ASN1_SEQUENCE,
00165        0, NULL, sizeof(CERTOCSPRequest) },
00166     { SEC_ASN1_POINTER,
00167        offsetof(CERTOCSPRequest, tbsRequest),
00168        ocsp_TBSRequestTemplate },
00169     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00170       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00171        offsetof(CERTOCSPRequest, optionalSignature),
00172        ocsp_PointerToSignatureTemplate },
00173     { 0 }
00174 };
00175 
00176 /*
00177  * TBSRequest ::=    SEQUENCE {
00178  *     version                     [0] EXPLICIT Version DEFAULT v1,
00179  *     requestorName        [1] EXPLICIT GeneralName OPTIONAL,
00180  *     requestList          SEQUENCE OF Request,
00181  *     requestExtensions    [2] EXPLICIT Extensions OPTIONAL }
00182  *
00183  * Version    ::=    INTEGER { v1(0) }
00184  *
00185  * Note: this should be static but the AIX compiler doesn't like it (because it
00186  * was forward-declared above); it is not meant to be exported, but this
00187  * is the only way it will compile.
00188  */
00189 const SEC_ASN1Template ocsp_TBSRequestTemplate[] = {
00190     { SEC_ASN1_SEQUENCE,
00191        0, NULL, sizeof(ocspTBSRequest) },
00192     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |           /* XXX DER_DEFAULT */
00193       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00194        offsetof(ocspTBSRequest, version),
00195        SEC_IntegerTemplate },
00196     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00197       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
00198        offsetof(ocspTBSRequest, derRequestorName),
00199        SEC_PointerToAnyTemplate },
00200     { SEC_ASN1_SEQUENCE_OF,
00201        offsetof(ocspTBSRequest, requestList),
00202        ocsp_SingleRequestTemplate },
00203     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00204       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
00205        offsetof(ocspTBSRequest, requestExtensions),
00206        CERT_SequenceOfCertExtensionTemplate },
00207     { 0 }
00208 };
00209 
00210 /*
00211  * Signature  ::=    SEQUENCE {
00212  *     signatureAlgorithm   AlgorithmIdentifier,
00213  *     signature            BIT STRING,
00214  *     certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
00215  */
00216 static const SEC_ASN1Template ocsp_SignatureTemplate[] = {
00217     { SEC_ASN1_SEQUENCE,
00218        0, NULL, sizeof(ocspSignature) },
00219     { SEC_ASN1_INLINE,
00220        offsetof(ocspSignature, signatureAlgorithm),
00221        SECOID_AlgorithmIDTemplate },
00222     { SEC_ASN1_BIT_STRING,
00223        offsetof(ocspSignature, signature) },
00224     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00225       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00226        offsetof(ocspSignature, derCerts), 
00227        SEC_SequenceOfAnyTemplate },
00228     { 0 }
00229 };
00230 
00231 /*
00232  * This template is just an extra level to use in an explicitly-tagged
00233  * reference to a Signature.
00234  *
00235  * Note: this should be static but the AIX compiler doesn't like it (because it
00236  * was forward-declared above); it is not meant to be exported, but this
00237  * is the only way it will compile.
00238  */
00239 const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = {
00240     { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate }
00241 };
00242 
00243 /*
00244  * Request    ::=    SEQUENCE {
00245  *     reqCert                     CertID,
00246  *     singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
00247  *
00248  * Note: this should be static but the AIX compiler doesn't like it (because it
00249  * was forward-declared above); it is not meant to be exported, but this
00250  * is the only way it will compile.
00251  */
00252 const SEC_ASN1Template ocsp_SingleRequestTemplate[] = {
00253     { SEC_ASN1_SEQUENCE, 
00254        0, NULL, sizeof(ocspSingleRequest) },
00255     { SEC_ASN1_POINTER,
00256        offsetof(ocspSingleRequest, reqCert),
00257        ocsp_CertIDTemplate },
00258     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00259       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00260        offsetof(ocspSingleRequest, singleRequestExtensions),
00261        CERT_SequenceOfCertExtensionTemplate },
00262     { 0 }
00263 };
00264 
00265 
00266 /*
00267  * This data structure and template (CertID) is used by both OCSP
00268  * requests and responses.  It is the only one that is shared.
00269  *
00270  * CertID     ::=    SEQUENCE {
00271  *     hashAlgorithm        AlgorithmIdentifier,
00272  *     issuerNameHash              OCTET STRING, -- Hash of Issuer DN
00273  *     issuerKeyHash        OCTET STRING, -- Hash of Issuer public key
00274  *     serialNumber         CertificateSerialNumber }
00275  *
00276  * CertificateSerialNumber ::=     INTEGER
00277  *
00278  * Note: this should be static but the AIX compiler doesn't like it (because it
00279  * was forward-declared above); it is not meant to be exported, but this
00280  * is the only way it will compile.
00281  */
00282 const SEC_ASN1Template ocsp_CertIDTemplate[] = {
00283     { SEC_ASN1_SEQUENCE, 
00284        0, NULL, sizeof(CERTOCSPCertID) },
00285     { SEC_ASN1_INLINE,
00286        offsetof(CERTOCSPCertID, hashAlgorithm),
00287        SECOID_AlgorithmIDTemplate },
00288     { SEC_ASN1_OCTET_STRING,
00289        offsetof(CERTOCSPCertID, issuerNameHash) },
00290     { SEC_ASN1_OCTET_STRING,
00291        offsetof(CERTOCSPCertID, issuerKeyHash) },
00292     { SEC_ASN1_INTEGER, 
00293        offsetof(CERTOCSPCertID, serialNumber) },
00294     { 0 }
00295 };
00296 
00297 
00298 /*
00299  * Response-related templates...
00300  */
00301 
00302 /*
00303  * OCSPResponse      ::=    SEQUENCE {
00304  *     responseStatus              OCSPResponseStatus,
00305  *     responseBytes        [0] EXPLICIT ResponseBytes OPTIONAL }
00306  */
00307 static const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = {
00308     { SEC_ASN1_SEQUENCE, 
00309        0, NULL, sizeof(CERTOCSPResponse) },
00310     { SEC_ASN1_ENUMERATED, 
00311        offsetof(CERTOCSPResponse, responseStatus) },
00312     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00313       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00314        offsetof(CERTOCSPResponse, responseBytes),
00315        ocsp_PointerToResponseBytesTemplate },
00316     { 0 }
00317 };
00318 
00319 /*
00320  * ResponseBytes     ::=    SEQUENCE {
00321  *     responseType         OBJECT IDENTIFIER,
00322  *     response             OCTET STRING }
00323  */
00324 static const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = {
00325     { SEC_ASN1_SEQUENCE,
00326        0, NULL, sizeof(ocspResponseBytes) },
00327     { SEC_ASN1_OBJECT_ID,
00328        offsetof(ocspResponseBytes, responseType) },
00329     { SEC_ASN1_OCTET_STRING,
00330        offsetof(ocspResponseBytes, response) },
00331     { 0 }
00332 };
00333 
00334 /*
00335  * This template is just an extra level to use in an explicitly-tagged
00336  * reference to a ResponseBytes.
00337  *
00338  * Note: this should be static but the AIX compiler doesn't like it (because it
00339  * was forward-declared above); it is not meant to be exported, but this
00340  * is the only way it will compile.
00341  */
00342 const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = {
00343     { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate }
00344 };
00345 
00346 /*
00347  * BasicOCSPResponse ::=    SEQUENCE {
00348  *     tbsResponseData             ResponseData,
00349  *     signatureAlgorithm   AlgorithmIdentifier,
00350  *     signature            BIT STRING,
00351  *     certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
00352  */
00353 static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = {
00354     { SEC_ASN1_SEQUENCE,
00355        0, NULL, sizeof(ocspBasicOCSPResponse) },
00356     { SEC_ASN1_POINTER,
00357        offsetof(ocspBasicOCSPResponse, tbsResponseData),
00358        ocsp_ResponseDataTemplate },
00359     { SEC_ASN1_INLINE,
00360        offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
00361        SECOID_AlgorithmIDTemplate },
00362     { SEC_ASN1_BIT_STRING,
00363        offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
00364     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00365       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00366        offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
00367        SEC_SequenceOfAnyTemplate },
00368     { 0 }
00369 };
00370 
00371 /*
00372  * ResponseData      ::=    SEQUENCE {
00373  *     version                     [0] EXPLICIT Version DEFAULT v1,
00374  *     responderID          ResponderID,
00375  *     producedAt           GeneralizedTime,
00376  *     responses            SEQUENCE OF SingleResponse,
00377  *     responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
00378  *
00379  * Note: this should be static but the AIX compiler doesn't like it (because it
00380  * was forward-declared above); it is not meant to be exported, but this
00381  * is the only way it will compile.
00382  */
00383 const SEC_ASN1Template ocsp_ResponseDataTemplate[] = {
00384     { SEC_ASN1_SEQUENCE,
00385        0, NULL, sizeof(ocspResponseData) },
00386     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |           /* XXX DER_DEFAULT */
00387       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00388        offsetof(ocspResponseData, version),
00389        SEC_IntegerTemplate },
00390     { SEC_ASN1_ANY,
00391        offsetof(ocspResponseData, derResponderID) },
00392     { SEC_ASN1_GENERALIZED_TIME,
00393        offsetof(ocspResponseData, producedAt) },
00394     { SEC_ASN1_SEQUENCE_OF,
00395        offsetof(ocspResponseData, responses),
00396        ocsp_SingleResponseTemplate },
00397     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00398       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
00399        offsetof(ocspResponseData, responseExtensions),
00400        CERT_SequenceOfCertExtensionTemplate },
00401     { 0 }
00402 };
00403 
00404 /*
00405  * ResponderID       ::=    CHOICE {
00406  *     byName               [1] EXPLICIT Name,
00407  *     byKey                [2] EXPLICIT KeyHash }
00408  *
00409  * KeyHash ::=       OCTET STRING -- SHA-1 hash of responder's public key
00410  * (excluding the tag and length fields)
00411  *
00412  * XXX Because the ASN.1 encoder and decoder currently do not provide
00413  * a way to automatically handle a CHOICE, we need to do it in two
00414  * steps, looking at the type tag and feeding the exact choice back
00415  * to the ASN.1 code.  Hopefully that will change someday and this
00416  * can all be simplified down into a single template.  Anyway, for
00417  * now we list each choice as its own template:
00418  */
00419 static const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = {
00420     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
00421        offsetof(ocspResponderID, responderIDValue.name),
00422        CERT_NameTemplate }
00423 };
00424 static const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = {
00425     { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
00426        offsetof(ocspResponderID, responderIDValue.keyHash),
00427        SEC_OctetStringTemplate }
00428 };
00429 static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = {
00430     { SEC_ASN1_ANY,
00431        offsetof(ocspResponderID, responderIDValue.other) }
00432 };
00433 
00434 /*
00435  * SingleResponse    ::=    SEQUENCE {
00436  *     certID               CertID,
00437  *     certStatus           CertStatus,
00438  *     thisUpdate           GeneralizedTime,
00439  *     nextUpdate           [0] EXPLICIT GeneralizedTime OPTIONAL,
00440  *     singleExtensions     [1] EXPLICIT Extensions OPTIONAL }
00441  *
00442  * Note: this should be static but the AIX compiler doesn't like it (because it
00443  * was forward-declared above); it is not meant to be exported, but this
00444  * is the only way it will compile.
00445  */
00446 const SEC_ASN1Template ocsp_SingleResponseTemplate[] = {
00447     { SEC_ASN1_SEQUENCE,
00448        0, NULL, sizeof(CERTOCSPSingleResponse) },
00449     { SEC_ASN1_POINTER,
00450        offsetof(CERTOCSPSingleResponse, certID),
00451        ocsp_CertIDTemplate },
00452     { SEC_ASN1_ANY,
00453        offsetof(CERTOCSPSingleResponse, derCertStatus) },
00454     { SEC_ASN1_GENERALIZED_TIME,
00455        offsetof(CERTOCSPSingleResponse, thisUpdate) },
00456     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00457       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00458        offsetof(CERTOCSPSingleResponse, nextUpdate),
00459        SEC_PointerToGeneralizedTimeTemplate },
00460     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00461       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
00462        offsetof(CERTOCSPSingleResponse, singleExtensions),
00463        CERT_SequenceOfCertExtensionTemplate },
00464     { 0 }
00465 };
00466 
00467 /*
00468  * CertStatus ::=    CHOICE {
00469  *     good                 [0] IMPLICIT NULL,
00470  *     revoked                     [1] IMPLICIT RevokedInfo,
00471  *     unknown                     [2] IMPLICIT UnknownInfo }
00472  *
00473  * Because the ASN.1 encoder and decoder currently do not provide
00474  * a way to automatically handle a CHOICE, we need to do it in two
00475  * steps, looking at the type tag and feeding the exact choice back
00476  * to the ASN.1 code.  Hopefully that will change someday and this
00477  * can all be simplified down into a single template.  Anyway, for
00478  * now we list each choice as its own template:
00479  */
00480 static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = {
00481     { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00482        offsetof(ocspCertStatus, certStatusInfo.goodInfo),
00483        SEC_NullTemplate }
00484 };
00485 static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = {
00486     { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
00487        offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
00488        ocsp_RevokedInfoTemplate }
00489 };
00490 static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = {
00491     { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 2,
00492        offsetof(ocspCertStatus, certStatusInfo.unknownInfo),
00493        SEC_NullTemplate }
00494 };
00495 static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = {
00496     { SEC_ASN1_POINTER,
00497        offsetof(ocspCertStatus, certStatusInfo.otherInfo),
00498        SEC_AnyTemplate }
00499 };
00500 
00501 /*
00502  * RevokedInfo       ::=    SEQUENCE {
00503  *     revocationTime              GeneralizedTime,
00504  *     revocationReason     [0] EXPLICIT CRLReason OPTIONAL }
00505  *
00506  * Note: this should be static but the AIX compiler doesn't like it (because it
00507  * was forward-declared above); it is not meant to be exported, but this
00508  * is the only way it will compile.
00509  */
00510 const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = {
00511     { SEC_ASN1_SEQUENCE,
00512        0, NULL, sizeof(ocspRevokedInfo) },
00513     { SEC_ASN1_GENERALIZED_TIME,
00514        offsetof(ocspRevokedInfo, revocationTime) },
00515     { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
00516       SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
00517        offsetof(ocspRevokedInfo, revocationReason), 
00518        SEC_PointerToEnumeratedTemplate },
00519     { 0 }
00520 };
00521 
00522 
00523 /*
00524  * OCSP-specific extension templates:
00525  */
00526 
00527 /*
00528  * ServiceLocator    ::=    SEQUENCE {
00529  *     issuer               Name,
00530  *     locator                     AuthorityInfoAccessSyntax OPTIONAL }
00531  */
00532 static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = {
00533     { SEC_ASN1_SEQUENCE,
00534        0, NULL, sizeof(ocspServiceLocator) },
00535     { SEC_ASN1_POINTER,
00536        offsetof(ocspServiceLocator, issuer),
00537        CERT_NameTemplate },
00538     { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
00539        offsetof(ocspServiceLocator, locator) },
00540     { 0 }
00541 };
00542 
00543 
00544 /*
00545  * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy):
00546  */
00547 
00548 /* 
00549  * FUNCTION: CERT_EncodeOCSPRequest
00550  *   DER encodes an OCSP Request, possibly adding a signature as well.
00551  *   XXX Signing is not yet supported, however; see comments in code.
00552  * INPUTS: 
00553  *   PRArenaPool *arena
00554  *     The return value is allocated from here.
00555  *     If a NULL is passed in, allocation is done from the heap instead.
00556  *   CERTOCSPRequest *request
00557  *     The request to be encoded.
00558  *   void *pwArg
00559  *     Pointer to argument for password prompting, if needed.  (Definitely
00560  *     not needed if not signing.)
00561  * RETURN:
00562  *   Returns a NULL on error and a pointer to the SECItem with the
00563  *   encoded value otherwise.  Any error is likely to be low-level
00564  *   (e.g. no memory).
00565  */
00566 SECItem *
00567 CERT_EncodeOCSPRequest(PRArenaPool *arena, CERTOCSPRequest *request, 
00568                      void *pwArg)
00569 {
00570     ocspTBSRequest *tbsRequest;
00571     SECStatus rv;
00572 
00573     /* XXX All of these should generate errors if they fail. */
00574     PORT_Assert(request);
00575     PORT_Assert(request->tbsRequest);
00576 
00577     tbsRequest = request->tbsRequest;
00578 
00579     if (request->tbsRequest->extensionHandle != NULL) {
00580        rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle);
00581        request->tbsRequest->extensionHandle = NULL;
00582        if (rv != SECSuccess)
00583            return NULL;
00584     }
00585 
00586     /*
00587      * XXX When signed requests are supported and request->optionalSignature
00588      * is not NULL:
00589      *  - need to encode tbsRequest->requestorName
00590      *  - need to encode tbsRequest
00591      *  - need to sign that encoded result (using cert in sig), filling in the
00592      *    request->optionalSignature structure with the result, the signing
00593      *    algorithm and (perhaps?) the cert (and its chain?) in derCerts
00594      */
00595 
00596     return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate);
00597 }
00598 
00599 
00600 /*
00601  * FUNCTION: CERT_DecodeOCSPRequest
00602  *   Decode a DER encoded OCSP Request.
00603  * INPUTS:
00604  *   SECItem *src
00605  *     Pointer to a SECItem holding DER encoded OCSP Request.
00606  * RETURN:
00607  *   Returns a pointer to a CERTOCSPRequest containing the decoded request.
00608  *   On error, returns NULL.  Most likely error is trouble decoding
00609  *   (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory).
00610  */
00611 CERTOCSPRequest *
00612 CERT_DecodeOCSPRequest(SECItem *src)
00613 {
00614     PRArenaPool *arena = NULL;
00615     SECStatus rv = SECFailure;
00616     CERTOCSPRequest *dest = NULL;
00617     int i;
00618     SECItem newSrc;
00619 
00620     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00621     if (arena == NULL) {
00622        goto loser;
00623     }
00624     dest = (CERTOCSPRequest *) PORT_ArenaZAlloc(arena, 
00625                                           sizeof(CERTOCSPRequest));
00626     if (dest == NULL) {
00627        goto loser;
00628     }
00629     dest->arena = arena;
00630 
00631     /* copy the DER into the arena, since Quick DER returns data that points
00632        into the DER input, which may get freed by the caller */
00633     rv = SECITEM_CopyItem(arena, &newSrc, src);
00634     if ( rv != SECSuccess ) {
00635        goto loser;
00636     }
00637 
00638     rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc);
00639     if (rv != SECSuccess) {
00640        if (PORT_GetError() == SEC_ERROR_BAD_DER)
00641            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
00642        goto loser;
00643     }
00644 
00645     /*
00646      * XXX I would like to find a way to get rid of the necessity
00647      * of doing this copying of the arena pointer.
00648      */
00649     for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) {
00650        dest->tbsRequest->requestList[i]->arena = arena;
00651     }
00652 
00653     return dest;
00654 
00655 loser:
00656     if (arena != NULL) {
00657        PORT_FreeArena(arena, PR_FALSE);
00658     }
00659     return NULL;
00660 }
00661 
00662 SECStatus
00663 CERT_DestroyOCSPCertID(CERTOCSPCertID* certID)
00664 {
00665     if (certID->poolp) {
00666        PORT_FreeArena(certID->poolp, PR_FALSE);
00667        return SECSuccess;
00668     }
00669     return SECFailure;
00670 }
00671 
00672 
00673 /*
00674  * Create and fill-in a CertID.  This function fills in the hash values
00675  * (issuerNameHash and issuerKeyHash), and is hardwired to use SHA1.
00676  * Someday it might need to be more flexible about hash algorithm, but
00677  * for now we have no intention/need to create anything else.
00678  *
00679  * Error causes a null to be returned; most likely cause is trouble
00680  * finding the certificate issuer (SEC_ERROR_UNKNOWN_ISSUER).
00681  * Other errors are low-level problems (no memory, bad database, etc.).
00682  */
00683 static CERTOCSPCertID *
00684 ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time)
00685 {
00686     CERTOCSPCertID *certID;
00687     CERTCertificate *issuerCert = NULL;
00688     SECItem *tempItem = NULL;
00689     void *mark = PORT_ArenaMark(arena);
00690     SECStatus rv;
00691 
00692     PORT_Assert(arena != NULL);
00693 
00694     certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
00695     if (certID == NULL) {
00696        goto loser;
00697     }
00698 
00699     rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
00700                             NULL);
00701     if (rv != SECSuccess) {
00702        goto loser; 
00703     }
00704 
00705     issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
00706     if (issuerCert == NULL) {
00707        goto loser;
00708     }
00709 
00710     tempItem = SEC_ASN1EncodeItem(NULL, NULL, &issuerCert->subject,
00711                               CERT_NameTemplate);
00712     if (tempItem == NULL) {
00713        goto loser;
00714     }
00715 
00716     if (SECITEM_AllocItem(arena, &(certID->issuerNameHash),
00717                        SHA1_LENGTH) == NULL) {
00718        goto loser;
00719     }
00720     rv = PK11_HashBuf(SEC_OID_SHA1, certID->issuerNameHash.data,
00721                     tempItem->data, tempItem->len);
00722     if (rv != SECSuccess) {
00723        goto loser; 
00724     }
00725     certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
00726     certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
00727     /* cache the other two hash algorithms as well */
00728     if (SECITEM_AllocItem(arena, &(certID->issuerMD5NameHash),
00729                        MD5_LENGTH) == NULL) {
00730        goto loser;
00731     }
00732     rv = PK11_HashBuf(SEC_OID_MD5, certID->issuerMD5NameHash.data,
00733                     tempItem->data, tempItem->len);
00734     if (rv != SECSuccess) {
00735        goto loser; 
00736     }
00737     if (SECITEM_AllocItem(arena, &(certID->issuerMD2NameHash),
00738                        MD2_LENGTH) == NULL) {
00739        goto loser;
00740     }
00741     rv = PK11_HashBuf(SEC_OID_MD2, certID->issuerMD2NameHash.data,
00742                     tempItem->data, tempItem->len);
00743     if (rv != SECSuccess) {
00744        goto loser; 
00745     }
00746 
00747     SECITEM_FreeItem(tempItem, PR_TRUE);
00748     tempItem = NULL;
00749 
00750     if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_SHA1,
00751                                &(certID->issuerKeyHash)) == NULL) {
00752        goto loser;
00753     }
00754     certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
00755     certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
00756     /* cache the other two hash algorithms as well */
00757     if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD5,
00758                                &(certID->issuerMD5KeyHash)) == NULL) {
00759        goto loser;
00760     }
00761     if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD2,
00762                                &(certID->issuerMD2KeyHash)) == NULL) {
00763        goto loser;
00764     }
00765 
00766 
00767     /* now we are done with issuerCert */
00768     CERT_DestroyCertificate(issuerCert);
00769     issuerCert = NULL;
00770 
00771     rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber);
00772     if (rv != SECSuccess) {
00773        goto loser; 
00774     }
00775 
00776     PORT_ArenaUnmark(arena, mark);
00777     return certID;
00778 
00779 loser:
00780     if (issuerCert != NULL) {
00781        CERT_DestroyCertificate(issuerCert);
00782     }
00783     if (tempItem != NULL) {
00784        SECITEM_FreeItem(tempItem, PR_TRUE);
00785     }
00786     PORT_ArenaRelease(arena, mark);
00787     return NULL;
00788 }
00789 
00790 CERTOCSPCertID*
00791 CERT_CreateOCSPCertID(CERTCertificate *cert, int64 time)
00792 {
00793     PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00794     CERTOCSPCertID *certID;
00795     PORT_Assert(arena != NULL);
00796     if (!arena)
00797        return NULL;
00798     
00799     certID = ocsp_CreateCertID(arena, cert, time);
00800     if (!certID) {
00801        PORT_FreeArena(arena, PR_FALSE);
00802        return NULL;
00803     }
00804     certID->poolp = arena;
00805     return certID;
00806 }
00807 
00808 
00809 
00810 /*
00811  * Callback to set Extensions in request object
00812  */
00813 void SetSingleReqExts(void *object, CERTCertExtension **exts)
00814 {
00815   ocspSingleRequest *singleRequest =
00816     (ocspSingleRequest *)object;
00817 
00818   singleRequest->singleRequestExtensions = exts;
00819 }
00820 
00821 /*
00822  * Add the Service Locator extension to the singleRequestExtensions
00823  * for the given singleRequest.
00824  *
00825  * All errors are internal or low-level problems (e.g. no memory).
00826  */
00827 static SECStatus
00828 ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest,
00829                             CERTCertificate *cert)
00830 {
00831     ocspServiceLocator *serviceLocator = NULL;
00832     void *extensionHandle = NULL;
00833     SECStatus rv = SECFailure;
00834 
00835     serviceLocator = PORT_ZNew(ocspServiceLocator);
00836     if (serviceLocator == NULL)
00837        goto loser;
00838 
00839     /*
00840      * Normally it would be a bad idea to do a direct reference like
00841      * this rather than allocate and copy the name *or* at least dup
00842      * a reference of the cert.  But all we need is to be able to read
00843      * the issuer name during the encoding we are about to do, so a
00844      * copy is just a waste of time.
00845      */
00846     serviceLocator->issuer = &cert->issuer;
00847 
00848     rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
00849                             &serviceLocator->locator);
00850     if (rv != SECSuccess) {
00851        if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
00852            goto loser;
00853     }
00854 
00855     /* prepare for following loser gotos */
00856     rv = SECFailure;
00857     PORT_SetError(0);
00858 
00859     extensionHandle = cert_StartExtensions(singleRequest,
00860                        singleRequest->arena, SetSingleReqExts);
00861     if (extensionHandle == NULL)
00862        goto loser;
00863 
00864     rv = CERT_EncodeAndAddExtension(extensionHandle,
00865                                 SEC_OID_PKIX_OCSP_SERVICE_LOCATOR,
00866                                 serviceLocator, PR_FALSE,
00867                                 ocsp_ServiceLocatorTemplate);
00868 
00869 loser:
00870     if (extensionHandle != NULL) {
00871        /*
00872         * Either way we have to finish out the extension context (so it gets
00873         * freed).  But careful not to override any already-set bad status.
00874         */
00875        SECStatus tmprv = CERT_FinishExtensions(extensionHandle);
00876        if (rv == SECSuccess)
00877            rv = tmprv;
00878     }
00879 
00880     /*
00881      * Finally, free the serviceLocator structure itself and we are done.
00882      */
00883     if (serviceLocator != NULL) {
00884        if (serviceLocator->locator.data != NULL)
00885            SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE);
00886        PORT_Free(serviceLocator);
00887     }
00888 
00889     return rv;
00890 }
00891 
00892 /*
00893  * Creates an array of ocspSingleRequest based on a list of certs.
00894  * Note that the code which later compares the request list with the
00895  * response expects this array to be in the exact same order as the
00896  * certs are found in the list.  It would be harder to change that
00897  * order than preserve it, but since the requirement is not obvious,
00898  * it deserves to be mentioned.
00899  *
00900  * Any problem causes a null return and error set:
00901  *     SEC_ERROR_UNKNOWN_ISSUER
00902  * Other errors are low-level problems (no memory, bad database, etc.).
00903  */
00904 static ocspSingleRequest **
00905 ocsp_CreateSingleRequestList(PRArenaPool *arena, CERTCertList *certList,
00906                           int64 time, PRBool includeLocator)
00907 {
00908     ocspSingleRequest **requestList = NULL;
00909     CERTCertListNode *node;
00910     int i, count;
00911     void *mark = PORT_ArenaMark(arena);
00912  
00913     node = CERT_LIST_HEAD(certList);
00914     for (count = 0; !CERT_LIST_END(node, certList); count++) {
00915        node = CERT_LIST_NEXT(node);
00916     }
00917 
00918     if (count == 0)
00919        goto loser;
00920 
00921     requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1);
00922     if (requestList == NULL)
00923        goto loser;
00924 
00925     node = CERT_LIST_HEAD(certList);
00926     for (i = 0; !CERT_LIST_END(node, certList); i++) {
00927         requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest);
00928        if (requestList[i] == NULL)
00929            goto loser;
00930 
00931        requestList[i]->arena = arena;
00932        requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
00933        if (requestList[i]->reqCert == NULL)
00934            goto loser;
00935 
00936        if (includeLocator == PR_TRUE) {
00937            SECStatus rv;
00938 
00939            rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
00940            if (rv != SECSuccess)
00941               goto loser;
00942        }
00943 
00944        node = CERT_LIST_NEXT(node);
00945     }
00946 
00947     PORT_Assert(i == count);
00948 
00949     PORT_ArenaUnmark(arena, mark);
00950     requestList[i] = NULL;
00951     return requestList;
00952 
00953 loser:
00954     PORT_ArenaRelease(arena, mark);
00955     return NULL;
00956 }
00957 
00958 
00959 /*
00960  * FUNCTION: CERT_CreateOCSPRequest
00961  *   Creates a CERTOCSPRequest, requesting the status of the certs in 
00962  *   the given list.
00963  * INPUTS:
00964  *   CERTCertList *certList
00965  *     A list of certs for which status will be requested.
00966  *     Note that all of these certificates should have the same issuer,
00967  *     or it's expected the response will be signed by a trusted responder.
00968  *     If the certs need to be broken up into multiple requests, that
00969  *     must be handled by the caller (and thus by having multiple calls
00970  *     to this routine), who knows about where the request(s) are being
00971  *     sent and whether there are any trusted responders in place.
00972  *   int64 time
00973  *     Indicates the time for which the certificate status is to be 
00974  *     determined -- this may be used in the search for the cert's issuer
00975  *     but has no effect on the request itself.
00976  *   PRBool addServiceLocator
00977  *     If true, the Service Locator extension should be added to the
00978  *     single request(s) for each cert.
00979  *   CERTCertificate *signerCert
00980  *     If non-NULL, means sign the request using this cert.  Otherwise,
00981  *     do not sign.
00982  *     XXX note that request signing is not yet supported; see comment in code
00983  * RETURN:
00984  *   A pointer to a CERTOCSPRequest structure containing an OCSP request
00985  *   for the cert list.  On error, null is returned, with an error set
00986  *   indicating the reason.  This is likely SEC_ERROR_UNKNOWN_ISSUER.
00987  *   (The issuer is needed to create a request for the certificate.)
00988  *   Other errors are low-level problems (no memory, bad database, etc.).
00989  */
00990 CERTOCSPRequest *
00991 CERT_CreateOCSPRequest(CERTCertList *certList, int64 time, 
00992                      PRBool addServiceLocator,
00993                      CERTCertificate *signerCert)
00994 {
00995     PRArenaPool *arena = NULL;
00996     CERTOCSPRequest *request = NULL;
00997     ocspTBSRequest *tbsRequest = NULL;
00998 
00999     /*
01000      * XXX This should set an error, but since it is only temporary and
01001      * since PSM will not initially provide a way to turn on signing of
01002      * requests anyway, I figure we can just skip defining an error that
01003      * will be obsolete in the next release.  When we are prepared to
01004      * put signing of requests back in, this entire check will go away,
01005      * and later in this function we will need to allocate a signature
01006      * structure for the request, fill in the "derCerts" field in it,
01007      * save the signerCert there, as well as fill in the "requestorName"
01008      * field of the tbsRequest.
01009      */
01010     if (signerCert != NULL) {
01011        return NULL;
01012     }
01013 
01014     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01015     if (arena == NULL) {
01016        goto loser;
01017     }
01018 
01019     request = PORT_ArenaZNew(arena, CERTOCSPRequest);
01020     if (request == NULL) {
01021        goto loser;
01022     }
01023     request->arena = arena;
01024 
01025     tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
01026     if (tbsRequest == NULL) {
01027        goto loser;
01028     }
01029     request->tbsRequest = tbsRequest;
01030 
01031     /* version 1 is the default, so we need not fill in a version number */
01032 
01033     /*
01034      * Now create the list of single requests, one for each cert.
01035      */
01036     tbsRequest->requestList = ocsp_CreateSingleRequestList(arena, certList,
01037                                                     time,
01038                                                     addServiceLocator);
01039     if (tbsRequest->requestList == NULL) {
01040        goto loser;
01041     }
01042     return request;
01043 
01044 loser:
01045     if (arena != NULL) {
01046        PORT_FreeArena(arena, PR_FALSE);
01047     }
01048     return NULL;
01049 }
01050 
01051 
01052 /*
01053  * FUNCTION: CERT_AddOCSPAcceptableResponses
01054  *   Add the AcceptableResponses extension to an OCSP Request.
01055  * INPUTS:
01056  *   CERTOCSPRequest *request
01057  *     The request to which the extension should be added.
01058  *   ...
01059  *     A list (of one or more) of SECOidTag -- each of the response types
01060  *     to be added.  The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE.
01061  *     (This marks the end of the list, and it must be specified because a
01062  *     client conforming to the OCSP standard is required to handle the basic
01063  *     response type.)  The OIDs are not checked in any way.
01064  * RETURN:
01065  *   SECSuccess if the extension is added; SECFailure if anything goes wrong.
01066  *   All errors are internal or low-level problems (e.g. no memory).
01067  */
01068 
01069 void SetRequestExts(void *object, CERTCertExtension **exts)
01070 {
01071   CERTOCSPRequest *request = (CERTOCSPRequest *)object;
01072 
01073   request->tbsRequest->requestExtensions = exts;
01074 }
01075 
01076 SECStatus
01077 CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request,
01078                             SECOidTag responseType0, ...)
01079 {
01080     void *extHandle;
01081     va_list ap;
01082     int i, count;
01083     SECOidTag responseType;
01084     SECOidData *responseOid;
01085     SECItem **acceptableResponses = NULL;
01086     SECStatus rv = SECFailure;
01087 
01088     extHandle = request->tbsRequest->extensionHandle;
01089     if (extHandle == NULL) {
01090        extHandle = cert_StartExtensions(request, request->arena, SetRequestExts);
01091        if (extHandle == NULL)
01092            goto loser;
01093     }
01094 
01095     /* Count number of OIDS going into the extension value. */
01096     count = 1;
01097     if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) {
01098        va_start(ap, responseType0);
01099        do {
01100            count++;
01101            responseType = va_arg(ap, SECOidTag);
01102        } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
01103        va_end(ap);
01104     }
01105 
01106     acceptableResponses = PORT_NewArray(SECItem *, count + 1);
01107     if (acceptableResponses == NULL)
01108        goto loser;
01109 
01110     i = 0;
01111     responseOid = SECOID_FindOIDByTag(responseType0);
01112     acceptableResponses[i++] = &(responseOid->oid);
01113     if (count > 1) {
01114        va_start(ap, responseType0);
01115        for ( ; i < count; i++) {
01116            responseType = va_arg(ap, SECOidTag);
01117            responseOid = SECOID_FindOIDByTag(responseType);
01118            acceptableResponses[i] = &(responseOid->oid);
01119        }
01120        va_end(ap);
01121     }
01122     acceptableResponses[i] = NULL;
01123 
01124     rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE,
01125                                 &acceptableResponses, PR_FALSE,
01126                                 SEC_SequenceOfObjectIDTemplate);
01127     if (rv != SECSuccess)
01128        goto loser;
01129 
01130     PORT_Free(acceptableResponses);
01131     if (request->tbsRequest->extensionHandle == NULL)
01132        request->tbsRequest->extensionHandle = extHandle;
01133     return SECSuccess;
01134 
01135 loser:
01136     if (acceptableResponses != NULL)
01137        PORT_Free(acceptableResponses);
01138     if (extHandle != NULL)
01139        (void) CERT_FinishExtensions(extHandle);
01140     return rv;
01141 }
01142 
01143 
01144 /*
01145  * FUNCTION: CERT_DestroyOCSPRequest
01146  *   Frees an OCSP Request structure.
01147  * INPUTS:
01148  *   CERTOCSPRequest *request
01149  *     Pointer to CERTOCSPRequest to be freed.
01150  * RETURN:
01151  *   No return value; no errors.
01152  */
01153 void
01154 CERT_DestroyOCSPRequest(CERTOCSPRequest *request)
01155 {
01156     if (request == NULL)
01157        return;
01158 
01159     if (request->tbsRequest != NULL) {
01160        if (request->tbsRequest->requestorName != NULL)
01161            CERT_DestroyGeneralNameList(request->tbsRequest->requestorName);
01162        if (request->tbsRequest->extensionHandle != NULL)
01163            (void) CERT_FinishExtensions(request->tbsRequest->extensionHandle);
01164     }
01165 
01166     if (request->optionalSignature != NULL) {
01167        if (request->optionalSignature->cert != NULL)
01168            CERT_DestroyCertificate(request->optionalSignature->cert);
01169 
01170        /*
01171         * XXX Need to free derCerts?  Or do they come out of arena?
01172         * (Currently we never fill in derCerts, which is why the
01173         * answer is not obvious.  Once we do, add any necessary code
01174         * here and remove this comment.)
01175         */
01176     }
01177 
01178     /*
01179      * We should actually never have a request without an arena,
01180      * but check just in case.  (If there isn't one, there is not
01181      * much we can do about it...)
01182      */
01183     PORT_Assert(request->arena != NULL);
01184     if (request->arena != NULL)
01185        PORT_FreeArena(request->arena, PR_FALSE);
01186 }
01187 
01188 
01189 /*
01190  * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy):
01191  */
01192 
01193 /*
01194  * Helper function for encoding or decoding a ResponderID -- based on the
01195  * given type, return the associated template for that choice.
01196  */
01197 static const SEC_ASN1Template *
01198 ocsp_ResponderIDTemplateByType(ocspResponderIDType responderIDType)
01199 {
01200     const SEC_ASN1Template *responderIDTemplate;
01201 
01202     switch (responderIDType) {
01203        case ocspResponderID_byName:
01204            responderIDTemplate = ocsp_ResponderIDByNameTemplate;
01205            break;
01206        case ocspResponderID_byKey:
01207            responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
01208            break;
01209        case ocspResponderID_other:
01210        default:
01211            PORT_Assert(responderIDType == ocspResponderID_other);
01212            responderIDTemplate = ocsp_ResponderIDOtherTemplate;
01213            break;
01214     }
01215 
01216     return responderIDTemplate;
01217 }
01218 
01219 /*
01220  * Helper function for encoding or decoding a CertStatus -- based on the
01221  * given type, return the associated template for that choice.
01222  */
01223 static const SEC_ASN1Template *
01224 ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType)
01225 {
01226     const SEC_ASN1Template *certStatusTemplate;
01227 
01228     switch (certStatusType) {
01229        case ocspCertStatus_good:
01230            certStatusTemplate = ocsp_CertStatusGoodTemplate;
01231            break;
01232        case ocspCertStatus_revoked:
01233            certStatusTemplate = ocsp_CertStatusRevokedTemplate;
01234            break;
01235        case ocspCertStatus_unknown:
01236            certStatusTemplate = ocsp_CertStatusUnknownTemplate;
01237            break;
01238        case ocspCertStatus_other:
01239        default:
01240            PORT_Assert(certStatusType == ocspCertStatus_other);
01241            certStatusTemplate = ocsp_CertStatusOtherTemplate;
01242            break;
01243     }
01244 
01245     return certStatusTemplate;
01246 }
01247 
01248 /*
01249  * Helper function for decoding a certStatus -- turn the actual DER tag
01250  * into our local translation.
01251  */
01252 static ocspCertStatusType
01253 ocsp_CertStatusTypeByTag(int derTag)
01254 {
01255     ocspCertStatusType certStatusType;
01256 
01257     switch (derTag) {
01258        case 0:
01259            certStatusType = ocspCertStatus_good;
01260            break;
01261        case 1:
01262            certStatusType = ocspCertStatus_revoked;
01263            break;
01264        case 2:
01265            certStatusType = ocspCertStatus_unknown;
01266            break;
01267        default:
01268            certStatusType = ocspCertStatus_other;
01269            break;
01270     }
01271 
01272     return certStatusType;
01273 }
01274 
01275 /*
01276  * Helper function for decoding SingleResponses -- they each contain
01277  * a status which is encoded as CHOICE, which needs to be decoded "by hand".
01278  *
01279  * Note -- on error, this routine does not release the memory it may
01280  * have allocated; it expects its caller to do that.
01281  */
01282 static SECStatus
01283 ocsp_FinishDecodingSingleResponses(PRArenaPool *arena,
01284                                CERTOCSPSingleResponse **responses)
01285 {
01286     ocspCertStatus *certStatus;
01287     ocspCertStatusType certStatusType;
01288     const SEC_ASN1Template *certStatusTemplate;
01289     int derTag;
01290     int i;
01291     SECStatus rv = SECFailure;
01292 
01293     if (responses == NULL)                /* nothing to do */
01294        return SECSuccess;
01295 
01296     for (i = 0; responses[i] != NULL; i++) {
01297        /*
01298         * The following assert points out internal errors (problems in
01299         * the template definitions or in the ASN.1 decoder itself, etc.).
01300         */
01301        PORT_Assert(responses[i]->derCertStatus.data != NULL);
01302 
01303        derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK;
01304        certStatusType = ocsp_CertStatusTypeByTag(derTag);
01305        certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType);
01306 
01307        certStatus = PORT_ArenaZAlloc(arena, sizeof(ocspCertStatus));
01308        if (certStatus == NULL) {
01309            goto loser;
01310        }
01311        rv = SEC_ASN1DecodeItem(arena, certStatus, certStatusTemplate,
01312                             &responses[i]->derCertStatus);
01313        if (rv != SECSuccess) {
01314            if (PORT_GetError() == SEC_ERROR_BAD_DER)
01315               PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
01316            goto loser;
01317        }
01318 
01319        certStatus->certStatusType = certStatusType;
01320        responses[i]->certStatus = certStatus;
01321     }
01322 
01323     return SECSuccess;
01324 
01325 loser:
01326     return rv;
01327 }
01328 
01329 /*
01330  * Helper function for decoding a responderID -- turn the actual DER tag
01331  * into our local translation.
01332  */
01333 static ocspResponderIDType
01334 ocsp_ResponderIDTypeByTag(int derTag)
01335 {
01336     ocspResponderIDType responderIDType;
01337 
01338     switch (derTag) {
01339        case 1:
01340            responderIDType = ocspResponderID_byName;
01341            break;
01342        case 2:
01343            responderIDType = ocspResponderID_byKey;
01344            break;
01345        default:
01346            responderIDType = ocspResponderID_other;
01347            break;
01348     }
01349 
01350     return responderIDType;
01351 }
01352 
01353 /*
01354  * Decode "src" as a BasicOCSPResponse, returning the result.
01355  */
01356 static ocspBasicOCSPResponse *
01357 ocsp_DecodeBasicOCSPResponse(PRArenaPool *arena, SECItem *src)
01358 {
01359     void *mark;
01360     ocspBasicOCSPResponse *basicResponse;
01361     ocspResponseData *responseData;
01362     ocspResponderID *responderID;
01363     ocspResponderIDType responderIDType;
01364     const SEC_ASN1Template *responderIDTemplate;
01365     int derTag;
01366     SECStatus rv;
01367     SECItem newsrc;
01368 
01369     mark = PORT_ArenaMark(arena);
01370 
01371     basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse));
01372     if (basicResponse == NULL) {
01373        goto loser;
01374     }
01375 
01376     /* copy the DER into the arena, since Quick DER returns data that points
01377        into the DER input, which may get freed by the caller */
01378     rv = SECITEM_CopyItem(arena, &newsrc, src);
01379     if ( rv != SECSuccess ) {
01380        goto loser;
01381     }
01382 
01383     rv = SEC_QuickDERDecodeItem(arena, basicResponse,
01384                          ocsp_BasicOCSPResponseTemplate, &newsrc);
01385     if (rv != SECSuccess) {
01386        if (PORT_GetError() == SEC_ERROR_BAD_DER)
01387            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
01388        goto loser;
01389     }
01390 
01391     responseData = basicResponse->tbsResponseData;
01392 
01393     /*
01394      * The following asserts point out internal errors (problems in
01395      * the template definitions or in the ASN.1 decoder itself, etc.).
01396      */
01397     PORT_Assert(responseData != NULL);
01398     PORT_Assert(responseData->derResponderID.data != NULL);
01399 
01400     /*
01401      * XXX Because responderID is a CHOICE, which is not currently handled
01402      * by our ASN.1 decoder, we have to decode it "by hand".
01403      */
01404     derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK;
01405     responderIDType = ocsp_ResponderIDTypeByTag(derTag);
01406     responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType);
01407 
01408     responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID));
01409     if (responderID == NULL) {
01410        goto loser;
01411     }
01412 
01413     rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate,
01414                          &responseData->derResponderID);
01415     if (rv != SECSuccess) {
01416        if (PORT_GetError() == SEC_ERROR_BAD_DER)
01417            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
01418        goto loser;
01419     }
01420 
01421     responderID->responderIDType = responderIDType;
01422     responseData->responderID = responderID;
01423 
01424     /*
01425      * XXX Each SingleResponse also contains a CHOICE, which has to be
01426      * fixed up by hand.
01427      */
01428     rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses);
01429     if (rv != SECSuccess) {
01430        goto loser;
01431     }
01432 
01433     PORT_ArenaUnmark(arena, mark);
01434     return basicResponse;
01435 
01436 loser:
01437     PORT_ArenaRelease(arena, mark);
01438     return NULL;
01439 }
01440 
01441 
01442 /*
01443  * Decode the responseBytes based on the responseType found in "rbytes",
01444  * leaving the resulting translated/decoded information in there as well.
01445  */
01446 static SECStatus
01447 ocsp_DecodeResponseBytes(PRArenaPool *arena, ocspResponseBytes *rbytes)
01448 {
01449     PORT_Assert(rbytes != NULL);          /* internal error, really */
01450     if (rbytes == NULL)
01451        PORT_SetError(SEC_ERROR_INVALID_ARGS);    /* XXX set better error? */
01452 
01453     rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType);
01454     switch (rbytes->responseTypeTag) {
01455        case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
01456            {
01457               ocspBasicOCSPResponse *basicResponse;
01458 
01459               basicResponse = ocsp_DecodeBasicOCSPResponse(arena,
01460                                                       &rbytes->response);
01461               if (basicResponse == NULL)
01462                   return SECFailure;
01463 
01464               rbytes->decodedResponse.basic = basicResponse;
01465            }
01466            break;
01467 
01468        /*
01469         * Add new/future response types here.
01470         */
01471 
01472        default:
01473            PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE);
01474            return SECFailure;
01475     }
01476 
01477     return SECSuccess;
01478 }
01479 
01480 
01481 /*
01482  * FUNCTION: CERT_DecodeOCSPResponse
01483  *   Decode a DER encoded OCSP Response.
01484  * INPUTS:
01485  *   SECItem *src
01486  *     Pointer to a SECItem holding DER encoded OCSP Response.
01487  * RETURN:
01488  *   Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response);
01489  *   the caller is responsible for destroying it.  Or NULL if error (either
01490  *   response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE),
01491  *   it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE),
01492  *   or a low-level or internal error occurred).
01493  */
01494 CERTOCSPResponse *
01495 CERT_DecodeOCSPResponse(SECItem *src)
01496 {
01497     PRArenaPool *arena = NULL;
01498     CERTOCSPResponse *response = NULL;
01499     SECStatus rv = SECFailure;
01500     ocspResponseStatus sv;
01501     SECItem newSrc;
01502 
01503     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01504     if (arena == NULL) {
01505        goto loser;
01506     }
01507     response = (CERTOCSPResponse *) PORT_ArenaZAlloc(arena,
01508                                                sizeof(CERTOCSPResponse));
01509     if (response == NULL) {
01510        goto loser;
01511     }
01512     response->arena = arena;
01513 
01514     /* copy the DER into the arena, since Quick DER returns data that points
01515        into the DER input, which may get freed by the caller */
01516     rv = SECITEM_CopyItem(arena, &newSrc, src);
01517     if ( rv != SECSuccess ) {
01518        goto loser;
01519     }
01520 
01521     rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &newSrc);
01522     if (rv != SECSuccess) {
01523        if (PORT_GetError() == SEC_ERROR_BAD_DER)
01524            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
01525        goto loser;
01526     }
01527 
01528     sv = (ocspResponseStatus) DER_GetInteger(&response->responseStatus);
01529     response->statusValue = sv;
01530     if (sv != ocspResponse_successful) {
01531        /*
01532         * If the response status is anything but successful, then we
01533         * are all done with decoding; the status is all there is.
01534         */
01535        return response;
01536     }
01537 
01538     /*
01539      * A successful response contains much more information, still encoded.
01540      * Now we need to decode that.
01541      */
01542     rv = ocsp_DecodeResponseBytes(arena, response->responseBytes);
01543     if (rv != SECSuccess) {
01544        goto loser;
01545     }
01546 
01547     return response;
01548 
01549 loser:
01550     if (arena != NULL) {
01551        PORT_FreeArena(arena, PR_FALSE);
01552     }
01553     return NULL;
01554 }
01555 
01556 /*
01557  * The way an OCSPResponse is defined, there are many levels to descend
01558  * before getting to the actual response information.  And along the way
01559  * we need to check that the response *type* is recognizable, which for
01560  * now means that it is a BasicOCSPResponse, because that is the only
01561  * type currently defined.  Rather than force all routines to perform
01562  * a bunch of sanity checking every time they want to work on a response,
01563  * this function isolates that and gives back the interesting part.
01564  * Note that no copying is done, this just returns a pointer into the
01565  * substructure of the response which is passed in.
01566  *
01567  * XXX This routine only works when a valid response structure is passed
01568  * into it; this is checked with many assertions.  Assuming the response
01569  * was creating by decoding, it wouldn't make it this far without being
01570  * okay.  That is a sufficient assumption since the entire OCSP interface
01571  * is only used internally.  When this interface is officially exported,
01572  * each assertion below will need to be followed-up with setting an error
01573  * and returning (null).
01574  */
01575 static ocspResponseData *
01576 ocsp_GetResponseData(CERTOCSPResponse *response)
01577 {
01578     ocspBasicOCSPResponse *basic;
01579     ocspResponseData *responseData;
01580 
01581     PORT_Assert(response != NULL);
01582 
01583     PORT_Assert(response->responseBytes != NULL);
01584 
01585     PORT_Assert(response->responseBytes->responseTypeTag
01586               == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
01587 
01588     basic = response->responseBytes->decodedResponse.basic;
01589     PORT_Assert(basic != NULL);
01590 
01591     responseData = basic->tbsResponseData;
01592     PORT_Assert(responseData != NULL);
01593 
01594     return responseData;
01595 }
01596 
01597 /*
01598  * Much like the routine above, except it returns the response signature.
01599  * Again, no copy is done.
01600  */
01601 static ocspSignature *
01602 ocsp_GetResponseSignature(CERTOCSPResponse *response)
01603 {
01604     ocspBasicOCSPResponse *basic;
01605 
01606     PORT_Assert(response != NULL);
01607     if (NULL == response->responseBytes) {
01608         return NULL;
01609     }
01610     PORT_Assert(response->responseBytes != NULL);
01611     PORT_Assert(response->responseBytes->responseTypeTag
01612               == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
01613 
01614     basic = response->responseBytes->decodedResponse.basic;
01615     PORT_Assert(basic != NULL);
01616 
01617     return &(basic->responseSignature);
01618 }
01619 
01620 
01621 /*
01622  * FUNCTION: CERT_DestroyOCSPResponse
01623  *   Frees an OCSP Response structure.
01624  * INPUTS:
01625  *   CERTOCSPResponse *request
01626  *     Pointer to CERTOCSPResponse to be freed.
01627  * RETURN:
01628  *   No return value; no errors.
01629  */
01630 void
01631 CERT_DestroyOCSPResponse(CERTOCSPResponse *response)
01632 {
01633     if (response != NULL) {
01634        ocspSignature *signature = ocsp_GetResponseSignature(response);
01635        if (signature && signature->cert != NULL)
01636            CERT_DestroyCertificate(signature->cert);
01637 
01638        /*
01639         * We should actually never have a response without an arena,
01640         * but check just in case.  (If there isn't one, there is not
01641         * much we can do about it...)
01642         */
01643        PORT_Assert(response->arena != NULL);
01644        if (response->arena != NULL) {
01645            PORT_FreeArena(response->arena, PR_FALSE);
01646        }
01647     }
01648 }
01649 
01650 
01651 /*
01652  * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response):
01653  */
01654 
01655 
01656 /*
01657  * Pick apart a URL, saving the important things in the passed-in pointers.
01658  *
01659  * We expect to find "http://<hostname>[:<port>]/[path]", though we will
01660  * tolerate that final slash character missing, as well as beginning and
01661  * trailing whitespace, and any-case-characters for "http".  All of that
01662  * tolerance is what complicates this routine.  What we want is just to
01663  * pick out the hostname, the port, and the path.
01664  *
01665  * On a successful return, the caller will need to free the output pieces
01666  * of hostname and path, which are copies of the values found in the url.
01667  */
01668 static SECStatus
01669 ocsp_ParseURL(char *url, char **pHostname, PRUint16 *pPort, char **pPath)
01670 {
01671     unsigned short port = 80;             /* default, in case not in url */
01672     char *hostname = NULL;
01673     char *path = NULL;
01674     char *save;
01675     char c;
01676     int len;
01677 
01678     if (url == NULL)
01679        goto loser;
01680 
01681     /*
01682      * Skip beginning whitespace.
01683      */
01684     c = *url;
01685     while ((c == ' ' || c == '\t') && c != '\0') {
01686        url++;
01687        c = *url;
01688     }
01689     if (c == '\0')
01690        goto loser;
01691 
01692     /*
01693      * Confirm, then skip, protocol.  (Since we only know how to do http,
01694      * that is all we will accept).
01695      */
01696     if (PORT_Strncasecmp(url, "http://", 7) != 0)
01697        goto loser;
01698     url += 7;
01699 
01700     /*
01701      * Whatever comes next is the hostname (or host IP address).  We just
01702      * save it aside and then search for its end so we can determine its
01703      * length and copy it.
01704      *
01705      * XXX Note that because we treat a ':' as a terminator character
01706      * (and below, we expect that to mean there is a port specification
01707      * immediately following), we will not handle IPv6 addresses.  That is
01708      * apparently an acceptable limitation, for the time being.  Some day,
01709      * when there is a clear way to specify a URL with an IPv6 address that
01710      * can be parsed unambiguously, this code should be made to do that.
01711      */
01712     save = url;
01713     c = *url;
01714     while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') {
01715        url++;
01716        c = *url;
01717     }
01718     len = url - save;
01719     hostname = PORT_Alloc(len + 1);
01720     if (hostname == NULL)
01721        goto loser;
01722     PORT_Memcpy(hostname, save, len);
01723     hostname[len] = '\0';
01724 
01725     /*
01726      * Now we figure out if there was a port specified or not.
01727      * If so, we need to parse it (as a number) and skip it.
01728      */
01729     if (c == ':') {
01730        url++;
01731        port = (unsigned short) PORT_Atoi(url);
01732        c = *url;
01733        while (c != '/' && c != '\0' && c != ' ' && c != '\t') {
01734            if (c < '0' || c > '9')
01735               goto loser;
01736            url++;
01737            c = *url;
01738        }
01739     }
01740 
01741     /*
01742      * Last thing to find is a path.  There *should* be a slash,
01743      * if nothing else -- but if there is not we provide one.
01744      */
01745     if (c == '/') {
01746        save = url;
01747        while (c != '\0' && c != ' ' && c != '\t') {
01748            url++;
01749            c = *url;
01750        }
01751        len = url - save;
01752        path = PORT_Alloc(len + 1);
01753        if (path == NULL)
01754            goto loser;
01755        PORT_Memcpy(path, save, len);
01756        path[len] = '\0';
01757     } else {
01758        path = PORT_Strdup("/");
01759        if (path == NULL)
01760            goto loser;
01761     }
01762 
01763     *pHostname = hostname;
01764     *pPort = port;
01765     *pPath = path;
01766     return SECSuccess;
01767 
01768 loser:
01769     if (hostname != NULL)
01770        PORT_Free(hostname);
01771     PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
01772     return SECFailure;
01773 }
01774 
01775 /*
01776  * Open a socket to the specified host on the specified port, and return it.
01777  * The host is either a hostname or an IP address.
01778  */
01779 static PRFileDesc *
01780 ocsp_ConnectToHost(const char *host, PRUint16 port)
01781 {
01782     PRFileDesc *sock = NULL;
01783     PRIntervalTime timeout;
01784     PRNetAddr addr;
01785     char *netdbbuf = NULL;
01786 
01787     sock = PR_NewTCPSocket();
01788     if (sock == NULL)
01789        goto loser;
01790 
01791     /* XXX Some day need a way to set (and get?) the following value */
01792     timeout = PR_SecondsToInterval(30);
01793 
01794     /*
01795      * If the following converts an IP address string in "dot notation"
01796      * into a PRNetAddr.  If it fails, we assume that is because we do not
01797      * have such an address, but instead a host *name*.  In that case we
01798      * then lookup the host by name.  Using the NSPR function this way
01799      * means we do not have to have our own logic for distinguishing a
01800      * valid numerical IP address from a hostname.
01801      */
01802     if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) {
01803        PRIntn hostIndex;
01804        PRHostEnt hostEntry;
01805 
01806        netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE);
01807        if (netdbbuf == NULL)
01808            goto loser;
01809 
01810        if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE,
01811                           &hostEntry) != PR_SUCCESS)
01812            goto loser;
01813 
01814        hostIndex = 0;
01815        do {
01816            hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr);
01817            if (hostIndex <= 0)
01818               goto loser;
01819        } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS);
01820 
01821        PORT_Free(netdbbuf);
01822     } else {
01823        /*
01824         * First put the port into the address, then connect.
01825         */
01826        if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS)
01827            goto loser;
01828        if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS)
01829            goto loser;
01830     }
01831 
01832     return sock;
01833 
01834 loser:
01835     if (sock != NULL)
01836        PR_Close(sock);
01837     if (netdbbuf != NULL)
01838        PORT_Free(netdbbuf);
01839     return NULL;
01840 }
01841 
01842 /*
01843  * Sends an encoded OCSP request to the server identified by "location",
01844  * and returns the socket on which it was sent (so can listen for the reply).
01845  * "location" is expected to be a valid URL -- an error parsing it produces
01846  * SEC_ERROR_CERT_BAD_ACCESS_LOCATION.  Other errors are likely problems
01847  * connecting to it, or writing to it, or allocating memory, and the low-level
01848  * errors appropriate to the problem will be set.
01849  */
01850 static PRFileDesc *
01851 ocsp_SendEncodedRequest(char *location, SECItem *encodedRequest)
01852 {
01853     char *hostname = NULL;
01854     char *path = NULL;
01855     PRUint16 port;
01856     SECStatus rv;
01857     PRFileDesc *sock = NULL;
01858     PRFileDesc *returnSock = NULL;
01859     char *header = NULL;
01860 
01861     /*
01862      * Take apart the location, getting the hostname, port, and path.
01863      */
01864     rv = ocsp_ParseURL(location, &hostname, &port, &path);
01865     if (rv != SECSuccess)
01866        goto loser;
01867 
01868     PORT_Assert(hostname != NULL);
01869     PORT_Assert(path != NULL);
01870 
01871     sock = ocsp_ConnectToHost(hostname, port);
01872     if (sock == NULL)
01873        goto loser;
01874 
01875     header = PR_smprintf("POST %s HTTP/1.0\r\n"
01876                       "Host: %s:%d\r\n"
01877                       "Content-Type: application/ocsp-request\r\n"
01878                       "Content-Length: %u\r\n\r\n",
01879                       path, hostname, port, encodedRequest->len);
01880     if (header == NULL)
01881        goto loser;
01882 
01883     /*
01884      * The NSPR documentation promises that if it can, it will write the full
01885      * amount; this will not return a partial value expecting us to loop.
01886      */
01887     if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0)
01888        goto loser;
01889 
01890     if (PR_Write(sock, encodedRequest->data,
01891                (PRInt32) encodedRequest->len) < 0)
01892        goto loser;
01893 
01894     returnSock = sock;
01895     sock = NULL;
01896 
01897 loser:
01898     if (header != NULL)
01899        PORT_Free(header);
01900     if (sock != NULL)
01901        PR_Close(sock);
01902     if (path != NULL)
01903        PORT_Free(path);
01904     if (hostname != NULL)
01905        PORT_Free(hostname);
01906 
01907     return returnSock;
01908 }
01909 
01910 /*
01911  * Read from "fd" into "buf" -- expect/attempt to read a given number of bytes
01912  * Obviously, stop if hit end-of-stream. Timeout is passed in.
01913  */
01914 
01915 static int
01916 ocsp_read(PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout)
01917 {
01918     int total = 0;
01919 
01920     while (total < toread)
01921     {
01922         PRInt32 got;
01923 
01924         got = PR_Recv(fd, buf + total, (PRInt32) (toread - total), 0, timeout);
01925         if (got < 0)
01926         {
01927             if (0 == total)
01928             {
01929                 total = -1; /* report the error if we didn't read anything yet */
01930             }
01931             break;
01932         }
01933         else
01934         if (got == 0)
01935         {                   /* EOS */
01936             break;
01937         }
01938 
01939         total += got;
01940     }
01941 
01942     return total;
01943 }
01944 
01945 #define OCSP_BUFSIZE 1024
01946 
01947 #define AbortHttpDecode(error) \
01948 { \
01949         if (inBuffer) \
01950             PORT_Free(inBuffer); \
01951         PORT_SetError(error); \
01952         return NULL; \
01953 }
01954 
01955 
01956 /*
01957  * Reads on the given socket and returns an encoded response when received.
01958  * Properly formatted HTTP/1.0 response headers are expected to be read
01959  * from the socket, preceding a binary-encoded OCSP response.  Problems
01960  * with parsing cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be
01961  * set; any other problems are likely low-level i/o or memory allocation
01962  * errors.
01963  */
01964 static SECItem *
01965 ocsp_GetEncodedResponse(PRArenaPool *arena, PRFileDesc *sock)
01966 {
01967     /* first read HTTP status line and headers */
01968 
01969     char* inBuffer = NULL;
01970     PRInt32 offset = 0;
01971     PRInt32 inBufsize = 0;
01972     const PRInt32 bufSizeIncrement = OCSP_BUFSIZE; /* 1 KB at a time */
01973     const PRInt32 maxBufSize = 8 * bufSizeIncrement ; /* 8 KB max */
01974     const char* CRLF = "\r\n";
01975     const PRInt32 CRLFlen = strlen(CRLF);
01976     const char* headerEndMark = "\r\n\r\n";
01977     const PRInt32 markLen = strlen(headerEndMark);
01978     const PRIntervalTime ocsptimeout =
01979         PR_SecondsToInterval(30); /* hardcoded to 30s for now */
01980     char* headerEnd = NULL;
01981     PRBool EOS = PR_FALSE;
01982     const char* httpprotocol = "HTTP/";
01983     const PRInt32 httplen = strlen(httpprotocol);
01984     const char* httpcode = NULL;
01985     const char* contenttype = NULL;
01986     PRInt32 contentlength = 0;
01987     PRInt32 bytesRead = 0;
01988     char* statusLineEnd = NULL;
01989     char* space = NULL;
01990     char* nextHeader = NULL;
01991     SECItem* result = NULL;
01992 
01993     /* read up to at least the end of the HTTP headers */
01994     do
01995     {
01996         inBufsize += bufSizeIncrement;
01997         inBuffer = PORT_Realloc(inBuffer, inBufsize+1);
01998         if (NULL == inBuffer)
01999         {
02000             AbortHttpDecode(SEC_ERROR_NO_MEMORY);
02001         }
02002         bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
02003             ocsptimeout);
02004         if (bytesRead > 0)
02005         {
02006             PRInt32 searchOffset = (offset - markLen) >0 ? offset-markLen : 0;
02007             offset += bytesRead;
02008             *(inBuffer + offset) = '\0'; /* NULL termination */
02009             headerEnd = strstr((const char*)inBuffer + searchOffset, headerEndMark);
02010             if (bytesRead < bufSizeIncrement)
02011             {
02012                 /* we read less data than requested, therefore we are at
02013                    EOS or there was a read error */
02014                 EOS = PR_TRUE;
02015             }
02016         }
02017         else
02018         {
02019             /* recv error or EOS */
02020             EOS = PR_TRUE;
02021         }
02022     } while ( (!headerEnd) && (PR_FALSE == EOS) &&
02023               (inBufsize < maxBufSize) );
02024 
02025     if (!headerEnd)
02026     {
02027         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02028     }
02029 
02030     /* parse the HTTP status line  */
02031     statusLineEnd = strstr((const char*)inBuffer, CRLF);
02032     if (!statusLineEnd)
02033     {
02034         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02035     }
02036     *statusLineEnd = '\0';
02037 
02038     /* check for HTTP/ response */
02039     space = strchr((const char*)inBuffer, ' ');
02040     if (!space || PORT_Strncasecmp((const char*)inBuffer, httpprotocol, httplen) != 0 )
02041     {
02042         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02043     }
02044 
02045     /* check the HTTP status code of 200 */
02046     httpcode = space +1;
02047     space = strchr(httpcode, ' ');
02048     if (!space)
02049     {
02050         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02051     }
02052     *space = 0;
02053     if (0 != strcmp(httpcode, "200"))
02054     {
02055         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02056     }
02057 
02058     /* parse the HTTP headers in the buffer . We only care about
02059        content-type and content-length
02060     */
02061 
02062     nextHeader = statusLineEnd + CRLFlen;
02063     *headerEnd = '\0'; /* terminate */
02064     do
02065     {
02066         char* thisHeaderEnd = NULL;
02067         char* value = NULL;
02068         char* colon = strchr(nextHeader, ':');
02069         
02070         if (!colon)
02071         {
02072             AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02073         }
02074 
02075         *colon = '\0';
02076         value = colon + 1;
02077 
02078         /* jpierre - note : the following code will only handle the basic form
02079            of HTTP/1.0 response headers, of the form "name: value" . Headers
02080            split among multiple lines are not supported. This is not common
02081            and should not be an issue, but it could become one in the
02082            future */
02083 
02084         if (*value != ' ')
02085         {
02086             AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02087         }
02088 
02089         value++;
02090         thisHeaderEnd  = strstr(value, CRLF);
02091         if (thisHeaderEnd )
02092         {
02093             *thisHeaderEnd  = '\0';
02094         }
02095 
02096         if (0 == PORT_Strcasecmp(nextHeader, "content-type"))
02097         {
02098             contenttype = value;
02099         }
02100         else
02101         if (0 == PORT_Strcasecmp(nextHeader, "content-length"))
02102         {
02103             contentlength = atoi(value);
02104         }
02105 
02106         if (thisHeaderEnd )
02107         {
02108             nextHeader = thisHeaderEnd + CRLFlen;
02109         }
02110         else
02111         {
02112             nextHeader = NULL;
02113         }
02114 
02115     } while (nextHeader && (nextHeader < (headerEnd + CRLFlen) ) );
02116 
02117     /* check content-type */
02118     if (!contenttype ||
02119         (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response")) )
02120     {
02121         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02122     }
02123 
02124     /* read the body of the OCSP response */
02125     offset = offset - (PRInt32) (headerEnd - (const char*)inBuffer) - markLen;
02126     if (offset)
02127     {
02128         /* move all data to the beginning of the buffer */
02129         PORT_Memmove(inBuffer, headerEnd + markLen, offset);
02130     }
02131 
02132     /* resize buffer to only what's needed to hold the current response */
02133     inBufsize = (1 + (offset-1) / bufSizeIncrement ) * bufSizeIncrement ;
02134 
02135     while ( (PR_FALSE == EOS) &&
02136             ( (contentlength == 0) || (offset < contentlength) ) &&
02137             (inBufsize < maxBufSize)
02138             )
02139     {
02140         /* we still need to receive more body data */
02141         inBufsize += bufSizeIncrement;
02142         inBuffer = PORT_Realloc(inBuffer, inBufsize+1);
02143         if (NULL == inBuffer)
02144         {
02145             AbortHttpDecode(SEC_ERROR_NO_MEMORY);
02146         }
02147         bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
02148                               ocsptimeout);
02149         if (bytesRead > 0)
02150         {
02151             offset += bytesRead;
02152             if (bytesRead < bufSizeIncrement)
02153             {
02154                 /* we read less data than requested, therefore we are at
02155                    EOS or there was a read error */
02156                 EOS = PR_TRUE;
02157             }
02158         }
02159         else
02160         {
02161             /* recv error or EOS */
02162             EOS = PR_TRUE;
02163         }
02164     }
02165 
02166     if (0 == offset)
02167     {
02168         AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02169     }
02170 
02171     /*
02172      * Now allocate the item to hold the data.
02173      */
02174     result = SECITEM_AllocItem(arena, NULL, offset);
02175     if (NULL == result)
02176     {
02177         AbortHttpDecode(SEC_ERROR_NO_MEMORY);
02178     }
02179 
02180     /*
02181      * And copy the data left in the buffer.
02182     */
02183     PORT_Memcpy(result->data, inBuffer, offset);
02184 
02185     /* and free the temporary buffer */
02186     PORT_Free(inBuffer);
02187     return result;
02188 }
02189 
02190 /*
02191  * Limit the size of http responses we are willing to accept.
02192  */
02193 #define MAX_WANTED_OCSP_RESPONSE_LEN 64*1024
02194 
02195 static SECItem *
02196 fetchOcspHttpClientV1(PRArenaPool *arena, 
02197                       const SEC_HttpClientFcnV1 *hcv1, 
02198                       char *location, 
02199                       SECItem *encodedRequest)
02200 {
02201     char *hostname = NULL;
02202     char *path = NULL;
02203     PRUint16 port;
02204     SECItem *encodedResponse = NULL;
02205     SEC_HTTP_SERVER_SESSION pServerSession = NULL;
02206     SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
02207     PRUint16 myHttpResponseCode;
02208     const char *myHttpResponseData;
02209     PRUint32 myHttpResponseDataLen;
02210 
02211     if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) {
02212         PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
02213         goto loser;
02214     }
02215     
02216     PORT_Assert(hostname != NULL);
02217     PORT_Assert(path != NULL);
02218 
02219     if ((*hcv1->createSessionFcn)(
02220             hostname, 
02221             port, 
02222             &pServerSession) != SECSuccess) {
02223         PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
02224         goto loser;
02225     }
02226 
02227     /* We use a non-zero timeout, which means:
02228        - the client will use blocking I/O
02229        - TryFcn will not return WOULD_BLOCK nor a poll descriptor
02230        - it's sufficient to call TryFcn once
02231     */
02232 
02233     if ((*hcv1->createFcn)(
02234             pServerSession,
02235             "http",
02236             path,
02237             "POST",
02238             PR_TicksPerSecond() * 60,
02239             &pRequestSession) != SECSuccess) {
02240         PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
02241         goto loser;
02242     }
02243 
02244     if ((*hcv1->setPostDataFcn)(
02245             pRequestSession, 
02246             (char*)encodedRequest->data,
02247             encodedRequest->len,
02248             "application/ocsp-request") != SECSuccess) {
02249         PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
02250         goto loser;
02251     }
02252 
02253     /* we don't want result objects larger than this: */
02254     myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN;
02255 
02256     if ((*hcv1->trySendAndReceiveFcn)(
02257             pRequestSession, 
02258             NULL,
02259             &myHttpResponseCode,
02260             NULL,
02261             NULL,
02262             &myHttpResponseData,
02263             &myHttpResponseDataLen) != SECSuccess) {
02264         PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
02265         goto loser;
02266     }
02267 
02268     if (myHttpResponseCode != 200) {
02269         PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
02270         goto loser;
02271     }
02272 
02273     encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen);
02274 
02275     if (!encodedResponse) {
02276         PORT_SetError(SEC_ERROR_NO_MEMORY);
02277         goto loser;
02278     }
02279 
02280     PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen);
02281 
02282 loser:
02283     if (pRequestSession != NULL) 
02284         (*hcv1->freeFcn)(pRequestSession);
02285     if (pServerSession != NULL)
02286         (*hcv1->freeSessionFcn)(pServerSession);
02287     if (path != NULL)
02288        PORT_Free(path);
02289     if (hostname != NULL)
02290        PORT_Free(hostname);
02291     
02292     return encodedResponse;
02293 }
02294 
02295 /*
02296  * FUNCTION: CERT_GetEncodedOCSPResponse
02297  *   Creates and sends a request to an OCSP responder, then reads and
02298  *   returns the (encoded) response.
02299  * INPUTS:
02300  *   PRArenaPool *arena
02301  *     Pointer to arena from which return value will be allocated.
02302  *     If NULL, result will be allocated from the heap (and thus should
02303  *     be freed via SECITEM_FreeItem).
02304  *   CERTCertList *certList
02305  *     A list of certs for which status will be requested.
02306  *     Note that all of these certificates should have the same issuer,
02307  *     or it's expected the response will be signed by a trusted responder.
02308  *     If the certs need to be broken up into multiple requests, that
02309  *     must be handled by the caller (and thus by having multiple calls
02310  *     to this routine), who knows about where the request(s) are being
02311  *     sent and whether there are any trusted responders in place.
02312  *   char *location
02313  *     The location of the OCSP responder (a URL).
02314  *   int64 time
02315  *     Indicates the time for which the certificate status is to be 
02316  *     determined -- this may be used in the search for the cert's issuer
02317  *     but has no other bearing on the operation.
02318  *   PRBool addServiceLocator
02319  *     If true, the Service Locator extension should be added to the
02320  *     single request(s) for each cert.
02321  *   CERTCertificate *signerCert
02322  *     If non-NULL, means sign the request using this cert.  Otherwise,
02323  *     do not sign.
02324  *   void *pwArg
02325  *     Pointer to argument for password prompting, if needed.  (Definitely
02326  *     not needed if not signing.)
02327  * OUTPUTS:
02328  *   CERTOCSPRequest **pRequest
02329  *     Pointer in which to store the OCSP request created for the given
02330  *     list of certificates.  It is only filled in if the entire operation
02331  *     is successful and the pointer is not null -- and in that case the
02332  *     caller is then reponsible for destroying it.
02333  * RETURN:
02334  *   Returns a pointer to the SECItem holding the response.
02335  *   On error, returns null with error set describing the reason:
02336  *     SEC_ERROR_UNKNOWN_ISSUER
02337  *     SEC_ERROR_CERT_BAD_ACCESS_LOCATION
02338  *     SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
02339  *   Other errors are low-level problems (no memory, bad database, etc.).
02340  */
02341 SECItem *
02342 CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList,
02343                          char *location, int64 time,
02344                          PRBool addServiceLocator,
02345                          CERTCertificate *signerCert, void *pwArg,
02346                          CERTOCSPRequest **pRequest)
02347 {
02348     CERTOCSPRequest *request = NULL;
02349     SECItem *encodedRequest = NULL;
02350     SECItem *encodedResponse = NULL;
02351     PRFileDesc *sock = NULL;
02352     SECStatus rv;
02353     const SEC_HttpClientFcn *registeredHttpClient = NULL;
02354 
02355     request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
02356                                  signerCert);
02357     if (request == NULL)
02358        goto loser;
02359 
02360     rv = CERT_AddOCSPAcceptableResponses(request,
02361                                     SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
02362     if (rv != SECSuccess)
02363        goto loser;
02364 
02365     encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg);
02366     if (encodedRequest == NULL)
02367        goto loser;
02368 
02369     registeredHttpClient = GetRegisteredHttpClient();
02370 
02371     if (registeredHttpClient
02372             &&
02373             registeredHttpClient->version == 1) {
02374         encodedResponse = fetchOcspHttpClientV1(
02375                               arena,
02376                               &registeredHttpClient->fcnTable.ftable1,
02377                               location,
02378                               encodedRequest);
02379     }
02380     else {
02381       /* use internal http client */
02382     
02383       sock = ocsp_SendEncodedRequest(location, encodedRequest);
02384       if (sock == NULL)
02385          goto loser;
02386 
02387       encodedResponse = ocsp_GetEncodedResponse(arena, sock);
02388     }
02389 
02390     if (encodedResponse != NULL && pRequest != NULL) {
02391        *pRequest = request;
02392        request = NULL;                    /* avoid destroying below */
02393     }
02394 
02395 loser:
02396     if (request != NULL)
02397        CERT_DestroyOCSPRequest(request);
02398     if (encodedRequest != NULL)
02399        SECITEM_FreeItem(encodedRequest, PR_TRUE);
02400     if (sock != NULL)
02401        PR_Close(sock);
02402 
02403     return encodedResponse;
02404 }
02405 
02406 
02407 /* Checks a certificate for the key usage extension of OCSP signer. */
02408 static PRBool
02409 ocsp_CertIsOCSPSigner(CERTCertificate *cert)
02410 {
02411     SECStatus rv;
02412     SECItem extItem;
02413     SECItem **oids;
02414     SECItem *oid;
02415     SECOidTag oidTag;
02416     PRBool retval;
02417     CERTOidSequence *oidSeq = NULL;
02418 
02419 
02420     extItem.data = NULL;
02421     rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
02422     if ( rv != SECSuccess ) {
02423        goto loser;
02424     }
02425 
02426     oidSeq = CERT_DecodeOidSequence(&extItem);
02427     if ( oidSeq == NULL ) {
02428        goto loser;
02429     }
02430 
02431     oids = oidSeq->oids;
02432     while ( *oids != NULL ) {
02433        oid = *oids;
02434        
02435        oidTag = SECOID_FindOIDTag(oid);
02436        
02437        if ( oidTag == SEC_OID_OCSP_RESPONDER ) {
02438            goto success;
02439        }
02440        
02441        oids++;
02442     }
02443 
02444 loser:
02445     retval = PR_FALSE;
02446     PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
02447     goto done;
02448 success:
02449     retval = PR_TRUE;
02450 done:
02451     if ( extItem.data != NULL ) {
02452        PORT_Free(extItem.data);
02453     }
02454     if ( oidSeq != NULL ) {
02455        CERT_DestroyOidSequence(oidSeq);
02456     }
02457     
02458     return(retval);
02459 }
02460 
02461 
02462 #ifdef LATER  /*
02463                * XXX This function is not currently used, but will
02464                * be needed later when we do revocation checking of
02465                * the responder certificate.  Of course, it may need
02466                * revising then, if the cert extension interface has
02467                * changed.  (Hopefully it will!)
02468                */
02469 
02470 /* Checks a certificate to see if it has the OCSP no check extension. */
02471 static PRBool
02472 ocsp_CertHasNoCheckExtension(CERTCertificate *cert)
02473 {
02474     SECStatus rv;
02475     
02476     rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK, 
02477                             NULL);
02478     if (rv == SECSuccess) {
02479        return PR_TRUE;
02480     }
02481     return PR_FALSE;
02482 }
02483 #endif /* LATER */
02484 
02485 static PRBool
02486 ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert)
02487 {
02488     SECItem item;
02489     unsigned char buf[HASH_LENGTH_MAX];
02490 
02491     item.data = buf;
02492     item.len = SHA1_LENGTH;
02493 
02494     if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_SHA1, &item) == NULL) {
02495        return PR_FALSE;
02496     }
02497     if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
02498        return PR_TRUE;
02499     }
02500     if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD5, &item) == NULL) {
02501        return PR_FALSE;
02502     }
02503     if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
02504        return PR_TRUE;
02505     }
02506     if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD2, &item) == NULL) {
02507        return PR_FALSE;
02508     }
02509     if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
02510        return PR_TRUE;
02511     }
02512 
02513     return PR_FALSE;
02514 }
02515 
02516 static CERTCertificate *
02517 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID);
02518 
02519 /*
02520  * Check the signature on some OCSP data.  This is a helper function that
02521  * can be used to check either a request or a response.  The result is
02522  * saved in the signature structure itself for future reference (to avoid
02523  * repeating the expensive verification operation), as well as returned.
02524  * In addition to checking the signature, the certificate (and its chain)
02525  * are also checked for validity (at the specified time) and usage.
02526  *
02527  * The type of cert lookup to be performed is specified by "lookupByName":
02528  * if true, then "certIndex" is actually a CERTName; otherwise it is a
02529  * SECItem which contains a key hash.
02530  *
02531  * If the signature verifies okay, and the argument "pSignerCert" is not
02532  * null, that parameter will be filled-in with a pointer to the signer's
02533  * certificate.  The caller is then responsible for destroying the cert.
02534  *
02535  * A return of SECSuccess means the verification succeeded.  If not,
02536  * an error will be set with the reason.  Most likely are:
02537  *     SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
02538  *     SEC_ERROR_BAD_SIGNATURE - the signature did not verify
02539  * Other errors are any of the many possible failures in cert verification
02540  * (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
02541  * verifying the signer's cert, or low-level problems (no memory, etc.)
02542  */
02543 static SECStatus
02544 ocsp_CheckSignature(ocspSignature *signature, void *tbs,
02545                   const SEC_ASN1Template *encodeTemplate,
02546                   CERTCertDBHandle *handle, SECCertUsage certUsage,
02547                   int64 checkTime, PRBool lookupByName, void *certIndex,
02548                   void *pwArg, CERTCertificate **pSignerCert,
02549                   CERTCertificate *issuer)
02550 {
02551     SECItem rawSignature;
02552     SECItem *encodedTBS = NULL;
02553     CERTCertificate *responder = NULL;
02554     CERTCertificate *signerCert = NULL;
02555     SECKEYPublicKey *signerKey = NULL;
02556     CERTCertificate **certs = NULL;
02557     SECStatus rv = SECFailure;
02558     int certCount;
02559     int i;
02560 
02561     /*
02562      * If this signature has already gone through verification, just
02563      * return the cached result.
02564      */
02565     if (signature->wasChecked) {
02566        if (signature->status == SECSuccess) {
02567            if (pSignerCert != NULL)
02568               *pSignerCert = CERT_DupCertificate(signature->cert);
02569        } else {
02570            PORT_SetError(signature->failureReason);
02571        }
02572        return signature->status;
02573     }
02574 
02575     /*
02576      * If the signature contains some certificates as well, temporarily
02577      * import them in case they are needed for verification.
02578      *
02579      * Note that the result of this is that each cert in "certs" needs
02580      * to be destroyed.
02581      */
02582     certCount = 0;
02583     if (signature->derCerts != NULL) {
02584        for (; signature->derCerts[certCount] != NULL; certCount++) {
02585            /* just counting */
02586            /*IMPORT CERT TO SPKI TABLE */
02587        }
02588     }
02589     rv = CERT_ImportCerts(handle, certUsage, certCount,
02590                        signature->derCerts, &certs,
02591                        PR_FALSE, PR_FALSE, NULL);
02592     if (rv != SECSuccess)
02593        goto finish;
02594 
02595     /*
02596      * Now look up the certificate that did the signing.
02597      * The signer can be specified either by name or by key hash.
02598      */
02599     if (lookupByName) {
02600        SECItem *encodedName;
02601 
02602        encodedName = SEC_ASN1EncodeItem(NULL, NULL, certIndex,
02603                                     CERT_NameTemplate);
02604        if (encodedName == NULL)
02605            goto finish;
02606 
02607        signerCert = CERT_FindCertByName(handle, encodedName);
02608        SECITEM_FreeItem(encodedName, PR_TRUE);
02609     } else {
02610        /*
02611         * The signer is either 1) a known issuer CA we passed in,
02612         * 2) the default OCSP responder, or 3) an intermediate CA
02613         * passed in the cert list to use. Figure out which it is.
02614         */
02615        responder = ocsp_CertGetDefaultResponder(handle,NULL);
02616        if (responder && ocsp_matchcert(certIndex,responder)) {
02617            signerCert = CERT_DupCertificate(responder);
02618        } else if (issuer && ocsp_matchcert(certIndex,issuer)) {
02619            signerCert = CERT_DupCertificate(issuer);
02620        } 
02621        for (i=0; (signerCert == NULL) && (i < certCount); i++) {
02622            if (ocsp_matchcert(certIndex,certs[i])) {
02623               signerCert = CERT_DupCertificate(certs[i]);
02624            }
02625        }
02626     }
02627 
02628     if (signerCert == NULL) {
02629        rv = SECFailure;
02630        if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
02631            /* Make the error a little more specific. */
02632            PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
02633        }
02634        goto finish;
02635     }
02636 
02637     /*
02638      * We could mark this true at the top of this function, or always
02639      * below at "finish", but if the problem was just that we could not
02640      * find the signer's cert, leave that as if the signature hasn't
02641      * been checked in case a subsequent call might have better luck.
02642      */
02643     signature->wasChecked = PR_TRUE;
02644 
02645     /*
02646      * Just because we have a cert does not mean it is any good; check
02647      * it for validity, trust and usage.
02648      */
02649     rv = CERT_VerifyCert(handle, signerCert, PR_TRUE, certUsage, checkTime,
02650                       pwArg, NULL);
02651     if (rv != SECSuccess) {
02652         PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
02653        goto finish;
02654     }
02655 
02656     /*
02657      * Now get the public key from the signer's certificate; we need
02658      * it to perform the verification.
02659      */
02660     signerKey = CERT_ExtractPublicKey(signerCert);
02661     if (signerKey == NULL)
02662        goto finish;
02663 
02664     /*
02665      * Prepare the data to be verified; it needs to be DER encoded first.
02666      */
02667     encodedTBS = SEC_ASN1EncodeItem(NULL, NULL, tbs, encodeTemplate);
02668     if (encodedTBS == NULL)
02669        goto finish;
02670 
02671     /*
02672      * We copy the signature data *pointer* and length, so that we can
02673      * modify the length without damaging the original copy.  This is a
02674      * simple copy, not a dup, so no destroy/free is necessary.
02675      */
02676     rawSignature = signature->signature;
02677     /*
02678      * The raw signature is a bit string, but we need to represent its
02679      * length in bytes, because that is what the verify function expects.
02680      */
02681     DER_ConvertBitString(&rawSignature);
02682 
02683     rv = VFY_VerifyDataWithAlgorithmID(encodedTBS->data, encodedTBS->len, 
02684                      signerKey, &rawSignature,
02685                      &signature->signatureAlgorithm, NULL,
02686                      pwArg);
02687 
02688 finish:
02689     if (signature->wasChecked)
02690        signature->status = rv;
02691 
02692     if (rv != SECSuccess) {
02693        signature->failureReason = PORT_GetError();
02694        if (signerCert != NULL)
02695            CERT_DestroyCertificate(signerCert);
02696     } else {
02697        /*
02698         * Save signer's certificate in signature.
02699         */
02700        signature->cert = signerCert;
02701        if (pSignerCert != NULL) {
02702            /*
02703             * Pass pointer to signer's certificate back to our caller,
02704             * who is also now responsible for destroying it.
02705             */
02706            *pSignerCert = CERT_DupCertificate(signerCert);
02707        }
02708     }
02709 
02710     if (encodedTBS != NULL)
02711        SECITEM_FreeItem(encodedTBS, PR_TRUE);
02712 
02713     if (signerKey != NULL)
02714        SECKEY_DestroyPublicKey(signerKey);
02715 
02716     if (certs != NULL)
02717        CERT_DestroyCertArray(certs, certCount);
02718        /* Free CERTS from SPKDigest Table */
02719 
02720     return rv;
02721 }
02722 
02723 
02724 /*
02725  * FUNCTION: CERT_VerifyOCSPResponseSignature
02726  *   Check the signature on an OCSP Response.  Will also perform a
02727  *   verification of the signer's certificate.  Note, however, that a
02728  *   successful verification does not make any statement about the
02729  *   signer's *authority* to provide status for the certificate(s),
02730  *   that must be checked individually for each certificate.
02731  * INPUTS:
02732  *   CERTOCSPResponse *response
02733  *     Pointer to response structure with signature to be checked.
02734  *   CERTCertDBHandle *handle
02735  *     Pointer to CERTCertDBHandle for certificate DB to use for verification.
02736  *   void *pwArg
02737  *     Pointer to argument for password prompting, if needed.
02738  * OUTPUTS:
02739  *   CERTCertificate **pSignerCert
02740  *     Pointer in which to store signer's certificate; only filled-in if
02741  *     non-null.
02742  * RETURN:
02743  *   Returns SECSuccess when signature is valid, anything else means invalid.
02744  *   Possible errors set:
02745  *     SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
02746  *     SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
02747  *     SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
02748  *     SEC_ERROR_BAD_SIGNATURE - the signature did not verify
02749  *   Other errors are any of the many possible failures in cert verification
02750  *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
02751  *   verifying the signer's cert, or low-level problems (no memory, etc.)
02752  */
02753 SECStatus
02754 CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,   
02755                              CERTCertDBHandle *handle, void *pwArg,
02756                              CERTCertificate **pSignerCert,
02757                              CERTCertificate *issuer)
02758 {
02759     ocspResponseData *tbsData;            /* this is what is signed */
02760     PRBool byName;
02761     void *certIndex;
02762     int64 producedAt;
02763     SECStatus rv;
02764 
02765     tbsData = ocsp_GetResponseData(response);
02766 
02767     PORT_Assert(tbsData->responderID != NULL);
02768     switch (tbsData->responderID->responderIDType) {
02769       case ocspResponderID_byName:
02770        byName = PR_TRUE;
02771        certIndex = &tbsData->responderID->responderIDValue.name;
02772        break;
02773       case ocspResponderID_byKey:
02774        byName = PR_FALSE;
02775        certIndex = &tbsData->responderID->responderIDValue.keyHash;
02776        break;
02777       case ocspResponderID_other:
02778       default:
02779        PORT_Assert(0);
02780        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
02781        return SECFailure;
02782     }
02783 
02784     /*
02785      * ocsp_CheckSignature will also verify the signer certificate; we
02786      * need to tell it *when* that certificate must be valid -- for our
02787      * purposes we expect it to be valid when the response was signed.
02788      * The value of "producedAt" is the signing time.
02789      */
02790     rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
02791     if (rv != SECSuccess)
02792        return rv;
02793 
02794     return ocsp_CheckSignature(ocsp_GetResponseSignature(response),
02795                             tbsData, ocsp_ResponseDataTemplate,
02796                             handle, certUsageStatusResponder, producedAt,
02797                             byName, certIndex, pwArg, pSignerCert, issuer);
02798 }
02799 
02800 /*
02801  * See if two certIDs match.  This can be easy or difficult, depending
02802  * on whether the same hash algorithm was used.
02803  */
02804 static PRBool
02805 ocsp_CertIDsMatch(CERTCertDBHandle *handle,
02806                 CERTOCSPCertID *certID1, CERTOCSPCertID *certID2)
02807 {
02808     PRBool match = PR_FALSE;
02809     SECOidTag hashAlg;
02810     SECItem *keyHash = NULL;
02811     SECItem *nameHash = NULL;
02812 
02813     /*
02814      * In order to match, they must have the same issuer and the same
02815      * serial number.
02816      *
02817      * We just compare the easier things first.
02818      */
02819     if (SECITEM_CompareItem(&certID1->serialNumber,
02820                          &certID2->serialNumber) != SECEqual) {
02821        goto done;
02822     }
02823 
02824     if (SECOID_CompareAlgorithmID(&certID1->hashAlgorithm,
02825                               &certID2->hashAlgorithm) == SECEqual) {
02826        /*
02827         * If the hash algorithms match then we can do a simple compare
02828         * of the hash values themselves.
02829         */
02830        if ((SECITEM_CompareItem(&certID1->issuerNameHash,
02831                              &certID2->issuerNameHash) == SECEqual)
02832            && (SECITEM_CompareItem(&certID1->issuerKeyHash,
02833                                 &certID2->issuerKeyHash) == SECEqual)) {
02834            match = PR_TRUE;
02835        }
02836        goto done;
02837     }
02838 
02839     hashAlg = SECOID_FindOIDTag(&certID2->hashAlgorithm.algorithm);
02840     switch (hashAlg) {
02841     case SEC_OID_SHA1:
02842        keyHash = &certID1->issuerSHA1KeyHash;
02843        nameHash = &certID1->issuerSHA1NameHash;
02844        break;
02845     case SEC_OID_MD5:
02846        keyHash = &certID1->issuerMD5KeyHash;
02847        nameHash = &certID1->issuerMD5NameHash;
02848        break;
02849     case SEC_OID_MD2:
02850        keyHash = &certID1->issuerMD2KeyHash;
02851        nameHash = &certID1->issuerMD2NameHash;
02852        break;
02853     }
02854 
02855     if ((keyHash != NULL)
02856       && (SECITEM_CompareItem(nameHash, &certID2->issuerNameHash) == SECEqual)
02857       && (SECITEM_CompareItem(keyHash, &certID2->issuerKeyHash) == SECEqual)) {
02858        match = PR_TRUE;
02859     }
02860 
02861 done:
02862     return match;
02863 }
02864 
02865 /*
02866  * Find the single response for the cert specified by certID.
02867  * No copying is done; this just returns a pointer to the appropriate
02868  * response within responses, if it is found (and null otherwise).
02869  * This is fine, of course, since this function is internal-use only.
02870  */
02871 static CERTOCSPSingleResponse *
02872 ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses,
02873                             CERTCertDBHandle *handle,
02874                             CERTOCSPCertID *certID)
02875 {
02876     CERTOCSPSingleResponse *single;
02877     int i;
02878 
02879     if (responses == NULL)
02880        return NULL;
02881 
02882     for (i = 0; responses[i] != NULL; i++) {
02883        single = responses[i];
02884        if (ocsp_CertIDsMatch(handle, certID, single->certID) == PR_TRUE) {
02885            return single;
02886        }
02887     }
02888 
02889     /*
02890      * The OCSP server should have included a response even if it knew
02891      * nothing about the certificate in question.  Since it did not,
02892      * this will make it look as if it had.
02893      * 
02894      * XXX Should we make this a separate error to notice the server's
02895      * bad behavior?
02896      */
02897     PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
02898     return NULL;
02899 }
02900 
02901 static ocspCheckingContext *
02902 ocsp_GetCheckingContext(CERTCertDBHandle *handle)
02903 {
02904     CERTStatusConfig *statusConfig;
02905     ocspCheckingContext *ocspcx = NULL;
02906 
02907     statusConfig = CERT_GetStatusConfig(handle);
02908     if (statusConfig != NULL) {
02909        ocspcx = statusConfig->statusContext;
02910 
02911        /*
02912         * This is actually an internal error, because we should never
02913         * have a good statusConfig without a good statusContext, too.
02914         * For lack of anything better, though, we just assert and use
02915         * the same error as if there were no statusConfig (set below).
02916         */
02917        PORT_Assert(ocspcx != NULL);
02918     }
02919 
02920     if (ocspcx == NULL)
02921        PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
02922 
02923     return ocspcx;
02924 }
02925 /*
02926  * Return true if the given signerCert is the default responder for
02927  * the given certID.  If not, or if any error, return false.
02928  */
02929 static CERTCertificate *
02930 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID)
02931 {
02932     ocspCheckingContext *ocspcx;
02933 
02934     ocspcx = ocsp_GetCheckingContext(handle);
02935     if (ocspcx == NULL)
02936        goto loser;
02937 
02938    /*
02939     * Right now we have only one default responder.  It applies to
02940     * all certs when it is used, so the check is simple and certID
02941     * has no bearing on the answer.  Someday in the future we may
02942     * allow configuration of different responders for different
02943     * issuers, and then we would have to use the issuer specified
02944     * in certID to determine if signerCert is the right one.
02945     */
02946     if (ocspcx->useDefaultResponder) {
02947        PORT_Assert(ocspcx->defaultResponderCert != NULL);
02948        return ocspcx->defaultResponderCert;
02949     }
02950 
02951 loser:
02952     return NULL;
02953 }
02954 
02955 /*
02956  * Return true if the given signerCert is the default responder for
02957  * the given certID.  If not, or if any error, return false.
02958  */
02959 static PRBool
02960 ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle,
02961                                  CERTCertificate *signerCert,
02962                                  CERTOCSPCertID *certID)
02963 {
02964     CERTCertificate *defaultResponderCert;
02965 
02966     defaultResponderCert = ocsp_CertGetDefaultResponder(handle, certID);
02967     return (PRBool) (defaultResponderCert == signerCert);
02968 }
02969 
02970 /*
02971  * Check that the given signer certificate is authorized to sign status
02972  * information for the given certID.  Return true if it is, false if not
02973  * (or if there is any error along the way).  If false is returned because
02974  * the signer is not authorized, the following error will be set:
02975  *     SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
02976  * Other errors are low-level problems (no memory, bad database, etc.).
02977  *
02978  * There are three ways to be authorized.  In the order in which we check,
02979  * using the terms used in the OCSP spec, the signer must be one of:
02980  *  1.  A "trusted responder" -- it matches a local configuration
02981  *      of OCSP signing authority for the certificate in question.
02982  *  2.  The CA who issued the certificate in question.
02983  *  3.  A "CA designated responder", aka an "authorized responder" -- it
02984  *      must be represented by a special cert issued by the CA who issued
02985  *      the certificate in question.
02986  */
02987 static PRBool
02988 ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle,
02989                               CERTCertificate *signerCert,
02990                               CERTOCSPCertID *certID,
02991                               int64 thisUpdate)
02992 {
02993     CERTCertificate *issuerCert = NULL;
02994     SECItem *issuerKeyHash = NULL;
02995     SECOidTag hashAlg;
02996     PRBool okay = PR_FALSE;
02997 
02998     /*
02999      * Check first for a trusted responder, which overrides everything else.
03000      */
03001     if (ocsp_CertIsDefaultResponderForCertID(handle, signerCert, certID))
03002        return PR_TRUE;
03003 
03004     /*
03005      * In the other two cases, we need to do an issuer comparison.
03006      * How we do it depends on whether the signer certificate has the
03007      * special extension (for a designated responder) or not.
03008      */
03009 
03010     if (ocsp_CertIsOCSPSigner(signerCert)) {
03011        /*
03012         * The signer is a designated responder.  Its issuer must match
03013         * the issuer of the cert being checked.
03014         */
03015        issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
03016                                     certUsageAnyCA);
03017        if (issuerCert == NULL) {
03018            /*
03019             * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
03020             * but the following will give slightly more information.
03021             * Once we have an error stack, things will be much better.
03022             */
03023            PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
03024            goto loser;
03025        }
03026     } else {
03027        /*
03028         * The signer must *be* the issuer of the cert being checked.
03029         */
03030        issuerCert = signerCert;
03031     }
03032 
03033     hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);
03034     issuerKeyHash = CERT_SPKDigestValueForCert(NULL, issuerCert, hashAlg, NULL);
03035     if (issuerKeyHash == NULL)
03036        goto loser;
03037 
03038     if (SECITEM_CompareItem(issuerKeyHash,
03039                          &certID->issuerKeyHash) != SECEqual) {
03040        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
03041        goto loser;
03042     }
03043 
03044     okay = PR_TRUE;
03045 
03046 loser:
03047     if (issuerKeyHash != NULL)
03048        SECITEM_FreeItem(issuerKeyHash, PR_TRUE);
03049 
03050     if (issuerCert != NULL && issuerCert != signerCert)
03051        CERT_DestroyCertificate(issuerCert);
03052 
03053     return okay;
03054 }
03055 
03056 /*
03057  * We need to check that a responder gives us "recent" information.
03058  * Since a responder can pre-package responses, we need to pick an amount
03059  * of time that is acceptable to us, and reject any response that is
03060  * older than that.
03061  *
03062  * XXX This *should* be based on some configuration parameter, so that
03063  * different usages could specify exactly what constitutes "sufficiently
03064  * recent".  But that is not going to happen right away.  For now, we
03065  * want something from within the last 24 hours.  This macro defines that
03066  * number in seconds.
03067  */
03068 #define OCSP_ALLOWABLE_LAPSE_SECONDS      (24L * 60L * 60L)
03069 
03070 static PRBool
03071 ocsp_TimeIsRecent(int64 checkTime)
03072 {
03073     int64 now = PR_Now();
03074     int64 lapse, tmp;
03075 
03076     LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS);
03077     LL_I2L(tmp, PR_USEC_PER_SEC);
03078     LL_MUL(lapse, lapse, tmp);            /* allowable lapse in microseconds */
03079 
03080     LL_ADD(checkTime, checkTime, lapse);
03081     if (LL_CMP(now, >, checkTime))
03082        return PR_FALSE;
03083 
03084     return PR_TRUE;
03085 }
03086 
03087 #define OCSP_SLOP (5L*60L) /* OCSP responses are allowed to be 5 minutes
03088                               in the future by default */
03089 
03090 static PRUint32 ocspsloptime = OCSP_SLOP; /* seconds */
03091 
03092 /*
03093  * Check that this single response is okay.  A return of SECSuccess means:
03094  *   1. The signer (represented by "signerCert") is authorized to give status
03095  *     for the cert represented by the individual response in "single".
03096  *   2. The value of thisUpdate is earlier than now.
03097  *   3. The value of producedAt is later than or the same as thisUpdate.
03098  *   4. If nextUpdate is given:
03099  *     - The value of nextUpdate is later than now.
03100  *     - The value of producedAt is earlier than nextUpdate.
03101  *     Else if no nextUpdate:
03102  *     - The value of thisUpdate is fairly recent.
03103  *     - The value of producedAt is fairly recent.
03104  *     However we do not need to perform an explicit check for this last
03105  *     constraint because it is already guaranteed by checking that
03106  *     producedAt is later than thisUpdate and thisUpdate is recent.
03107  * Oh, and any responder is "authorized" to say that a cert is unknown to it.
03108  *
03109  * If any of those checks fail, SECFailure is returned and an error is set:
03110  *     SEC_ERROR_OCSP_FUTURE_RESPONSE
03111  *     SEC_ERROR_OCSP_OLD_RESPONSE
03112  *     SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
03113  * Other errors are low-level problems (no memory, bad database, etc.).
03114  */ 
03115 static SECStatus
03116 ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single,
03117                        CERTCertDBHandle *handle,
03118                        CERTCertificate *signerCert,
03119                        int64 producedAt)
03120 {
03121     CERTOCSPCertID *certID = single->certID;
03122     int64 now, thisUpdate, nextUpdate, tmstamp, tmp;
03123     SECStatus rv;
03124 
03125     /*
03126      * If all the responder said was that the given cert was unknown to it,
03127      * that is a valid response.  Not very interesting to us, of course,
03128      * but all this function is concerned with is validity of the response,
03129      * not the status of the cert.
03130      */
03131     PORT_Assert(single->certStatus != NULL);
03132     if (single->certStatus->certStatusType == ocspCertStatus_unknown)
03133        return SECSuccess;
03134 
03135     /*
03136      * We need to extract "thisUpdate" for use below and to pass along
03137      * to AuthorizedResponderForCertID in case it needs it for doing an
03138      * issuer look-up.
03139      */
03140     rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate);
03141     if (rv != SECSuccess)
03142        return rv;
03143 
03144     /*
03145      * First confirm that signerCert is authorized to give this status.
03146      */
03147     if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID,
03148                                      thisUpdate) != PR_TRUE)
03149        return SECFailure;
03150 
03151     /*
03152      * Now check the time stuff, as described above.
03153      */
03154     now = PR_Now();
03155     /* allow slop time for future response */
03156     LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */
03157     LL_UI2L(tmp, PR_USEC_PER_SEC);
03158     LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */
03159     LL_ADD(tmstamp, tmp, now); /* add current time to it */
03160 
03161     if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) {
03162        PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE);
03163        return SECFailure;
03164     }
03165     if (single->nextUpdate != NULL) {
03166        rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate);
03167        if (rv != SECSuccess)
03168            return rv;
03169 
03170        LL_ADD(tmp, tmp, nextUpdate);
03171        if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate)) {
03172            PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
03173            return SECFailure;
03174        }
03175     } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) {
03176        PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
03177        return SECFailure;
03178     }
03179 
03180     return SECSuccess;
03181 }
03182 
03183 
03184 /*
03185  * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation
03186  *   Get the value of the URI of the OCSP responder for the given cert.
03187  *   This is found in the (optional) Authority Information Access extension
03188  *   in the cert.
03189  * INPUTS:
03190  *   CERTCertificate *cert
03191  *     The certificate being examined.
03192  * RETURN:
03193  *   char *
03194  *     A copy of the URI for the OCSP method, if found.  If either the
03195  *     extension is not present or it does not contain an entry for OCSP,
03196  *     SEC_ERROR_CERT_BAD_ACCESS_LOCATION will be set and a NULL returned.
03197  *     Any other error will also result in a NULL being returned.
03198  *     
03199  *     This result should be freed (via PORT_Free) when no longer in use.
03200  */
03201 char *
03202 CERT_GetOCSPAuthorityInfoAccessLocation(CERTCertificate *cert)
03203 {
03204     CERTGeneralName *locname = NULL;
03205     SECItem *location = NULL;
03206     SECItem *encodedAuthInfoAccess = NULL;
03207     CERTAuthInfoAccess **authInfoAccess = NULL;
03208     char *locURI = NULL;
03209     PRArenaPool *arena = NULL;
03210     SECStatus rv;
03211     int i;
03212 
03213     /*
03214      * Allocate this one from the heap because it will get filled in
03215      * by CERT_FindCertExtension which will also allocate from the heap,
03216      * and we can free the entire thing on our way out.
03217      */
03218     encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
03219     if (encodedAuthInfoAccess == NULL)
03220        goto loser;
03221 
03222     rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
03223                             encodedAuthInfoAccess);
03224     if (rv == SECFailure) {
03225        PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
03226        goto loser;
03227     }
03228 
03229     /*
03230      * The rest of the things allocated in the routine will come out of
03231      * this arena, which is temporary just for us to decode and get at the
03232      * AIA extension.  The whole thing will be destroyed on our way out,
03233      * after we have copied the location string (url) itself (if found).
03234      */
03235     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
03236     if (arena == NULL)
03237        goto loser;
03238 
03239     authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena,
03240                                                  encodedAuthInfoAccess);
03241     if (authInfoAccess == NULL)
03242        goto loser;
03243 
03244     for (i = 0; authInfoAccess[i] != NULL; i++) {
03245        if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP)
03246            locname = authInfoAccess[i]->location;
03247     }
03248 
03249     /*
03250      * If we found an AIA extension, but it did not include an OCSP method,
03251      * that should look to our caller as if we did not find the extension
03252      * at all, because it is only an OCSP method that we care about.
03253      * So set the same error that would be set if the AIA extension was
03254      * not there at all.
03255      */
03256     if (locname == NULL) {
03257        PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
03258        goto loser;
03259     }
03260 
03261     /*
03262      * The following is just a pointer back into locname (i.e. not a copy);
03263      * thus it should not be freed.
03264      */
03265     location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
03266     if (location == NULL) {
03267        /*
03268         * XXX Appears that CERT_GetGeneralNameByType does not set an
03269         * error if there is no name by that type.  For lack of anything
03270         * better, act as if the extension was not found.  In the future
03271         * this should probably be something more like the extension was
03272         * badly formed.
03273         */
03274        PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
03275        goto loser;
03276     }
03277 
03278     /*
03279      * That location is really a string, but it has a specified length
03280      * without a null-terminator.  We need a real string that does have
03281      * a null-terminator, and we need a copy of it anyway to return to
03282      * our caller -- so allocate and copy.
03283      */
03284     locURI = PORT_Alloc(location->len + 1);
03285     if (locURI == NULL) {
03286        goto loser;
03287     }
03288     PORT_Memcpy(locURI, location->data, location->len);
03289     locURI[location->len] = '\0';
03290 
03291 loser:
03292     if (arena != NULL)
03293        PORT_FreeArena(arena, PR_FALSE);
03294 
03295     if (encodedAuthInfoAccess != NULL)
03296        SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);
03297 
03298     return locURI;
03299 }
03300 
03301 
03302 /*
03303  * Figure out where we should go to find out the status of the given cert
03304  * via OCSP.  If a default responder is set up, that is our answer.
03305  * If not, see if the certificate has an Authority Information Access (AIA)
03306  * extension for OCSP, and return the value of that.  Otherwise return NULL.
03307  * We also let our caller know whether or not the responder chosen was
03308  * a default responder or not through the output variable isDefault;
03309  * its value has no meaning unless a good (non-null) value is returned
03310  * for the location.
03311  *
03312  * The result needs to be freed (PORT_Free) when no longer in use.
03313  */
03314 static char *
03315 ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert,
03316                        PRBool *isDefault)
03317 {
03318     ocspCheckingContext *ocspcx;
03319 
03320     ocspcx = ocsp_GetCheckingContext(handle);
03321     if (ocspcx != NULL && ocspcx->useDefaultResponder) {
03322        /*
03323         * A default responder wins out, if specified.
03324         * XXX Someday this may be a more complicated determination based
03325         * on the cert's issuer.  (That is, we could have different default
03326         * responders configured for different issuers.)
03327         */
03328        PORT_Assert(ocspcx->defaultResponderURI != NULL);
03329        *isDefault = PR_TRUE;
03330        return (PORT_Strdup(ocspcx->defaultResponderURI));
03331     }
03332 
03333     /*
03334      * No default responder set up, so go see if we can find an AIA
03335      * extension that has a value for OCSP, and get the url from that.
03336      */
03337     *isDefault = PR_FALSE;
03338     return CERT_GetOCSPAuthorityInfoAccessLocation(cert);
03339 }
03340 
03341 /*
03342  * Return SECSuccess if the cert was revoked *after* "time",
03343  * SECFailure otherwise.
03344  */
03345 static SECStatus
03346 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, int64 time)
03347 {
03348     int64 revokedTime;
03349     SECStatus rv;
03350 
03351     rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime);
03352     if (rv != SECSuccess)
03353        return rv;
03354 
03355     /*
03356      * Set the error even if we will return success; someone might care.
03357      */
03358     PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
03359 
03360     if (LL_CMP(revokedTime, >, time))
03361        return SECSuccess;
03362 
03363     return SECFailure;
03364 }
03365 
03366 /*
03367  * See if the cert represented in the single response had a good status
03368  * at the specified time.
03369  */
03370 static SECStatus
03371 ocsp_CertHasGoodStatus(CERTOCSPSingleResponse *single, int64 time)
03372 {
03373     ocspCertStatus *status;
03374     SECStatus rv;
03375 
03376     status = single->certStatus;
03377 
03378     switch (status->certStatusType) {
03379       case ocspCertStatus_good:
03380        rv = SECSuccess;
03381        break;
03382       case ocspCertStatus_revoked:
03383        rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
03384        break;
03385       case ocspCertStatus_unknown:
03386        PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
03387        rv = SECFailure;
03388        break;
03389       case ocspCertStatus_other:
03390       default:
03391        PORT_Assert(0);
03392        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
03393        rv = SECFailure;
03394        break;
03395     }
03396 
03397     return rv;
03398 }
03399 
03400 
03401 /*
03402  * FUNCTION: CERT_CheckOCSPStatus
03403  *   Checks the status of a certificate via OCSP.  Will only check status for
03404  *   a certificate that has an AIA (Authority Information Access) extension
03405  *   for OCSP *or* when a "default responder" is specified and enabled.
03406  *   (If no AIA extension for OCSP and no default responder in place, the
03407  *   cert is considered to have a good status and SECSuccess is returned.)
03408  * INPUTS:
03409  *   CERTCertDBHandle *handle
03410  *     certificate DB of the cert that is being checked
03411  *   CERTCertificate *cert
03412  *     the certificate being checked
03413  *   XXX in the long term also need a boolean parameter that specifies
03414  *     whether to check the cert chain, as well; for now we check only
03415  *     the leaf (the specified certificate)
03416  *   int64 time
03417  *     time for which status is to be determined
03418  *   void *pwArg
03419  *     argument for password prompting, if needed
03420  * RETURN:
03421  *   Returns SECSuccess if an approved OCSP responder "knows" the cert
03422  *   *and* returns a non-revoked status for it; SECFailure otherwise,
03423  *   with an error set describing the reason:
03424  *
03425  *     SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
03426  *     SEC_ERROR_OCSP_FUTURE_RESPONSE
03427  *     SEC_ERROR_OCSP_MALFORMED_REQUEST
03428  *     SEC_ERROR_OCSP_MALFORMED_RESPONSE
03429  *     SEC_ERROR_OCSP_OLD_RESPONSE
03430  *     SEC_ERROR_OCSP_REQUEST_NEEDS_SIG
03431  *     SEC_ERROR_OCSP_SERVER_ERROR
03432  *     SEC_ERROR_OCSP_TRY_SERVER_LATER
03433  *     SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST
03434  *     SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
03435  *     SEC_ERROR_OCSP_UNKNOWN_CERT
03436  *     SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
03437  *     SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE
03438  *
03439  *     SEC_ERROR_BAD_SIGNATURE
03440  *     SEC_ERROR_CERT_BAD_ACCESS_LOCATION
03441  *     SEC_ERROR_INVALID_TIME
03442  *     SEC_ERROR_REVOKED_CERTIFICATE
03443  *     SEC_ERROR_UNKNOWN_ISSUER
03444  *     SEC_ERROR_UNKNOWN_SIGNER
03445  *
03446  *   Other errors are any of the many possible failures in cert verification
03447  *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
03448  *   verifying the signer's cert, or low-level problems (error allocating
03449  *   memory, error performing ASN.1 decoding, etc.).
03450  */    
03451 SECStatus 
03452 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
03453                    int64 time, void *pwArg)
03454 {
03455     char *location = NULL;
03456     PRBool locationIsDefault;
03457     CERTCertList *certList = NULL;
03458     SECItem *encodedResponse = NULL;
03459     CERTOCSPRequest *request = NULL;
03460     CERTOCSPResponse *response = NULL;
03461     CERTCertificate *signerCert = NULL;
03462     CERTCertificate *issuerCert = NULL;
03463     CERTOCSPCertID *certID;
03464     SECStatus rv = SECFailure;
03465 
03466 
03467     /*
03468      * The first thing we need to do is find the location of the responder.
03469      * This will be the value of the default responder (if enabled), else
03470      * it will come out of the AIA extension in the cert (if present).
03471      * If we have no such location, then this cert does not "deserve" to
03472      * be checked -- that is, we consider it a success and just return.
03473      * The way we tell that is by looking at the error number to see if
03474      * the problem was no AIA extension was found; any other error was
03475      * a true failure that we unfortunately have to treat as an overall
03476      * failure here.
03477      */
03478     location = ocsp_GetResponderLocation(handle, cert, &locationIsDefault);
03479     if (location == NULL) {
03480        int err = PORT_GetError();
03481        if (err == SEC_ERROR_EXTENSION_NOT_FOUND ||
03482            err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
03483            PORT_SetError(0);
03484            return SECSuccess;
03485        }
03486        return SECFailure;
03487     }
03488 
03489     /*
03490      * For now, create a cert-list of one.
03491      * XXX In the fullness of time, we will want/need to handle a
03492      * certificate chain.  This will be done either when a new parameter
03493      * tells us to, or some configuration variable tells us to.  In any
03494      * case, handling it is complicated because we may need to send as
03495      * many requests (and receive as many responses) as we have certs
03496      * in the chain.  If we are going to talk to a default responder,
03497      * and we only support one default responder, we can put all of the
03498      * certs together into one request.  Otherwise, we must break them up
03499      * into multiple requests.  (Even if all of the requests will go to
03500      * the same location, the signature on each response will be different,
03501      * because each issuer is different.  Carefully read the OCSP spec
03502      * if you do not understand this.)
03503      */
03504 
03505     certList = CERT_NewCertList();
03506     if (certList == NULL)
03507        goto loser;
03508 
03509     /* dup it because freeing the list will destroy the cert, too */
03510     cert = CERT_DupCertificate(cert);
03511     if (cert == NULL)
03512        goto loser;
03513 
03514     if (CERT_AddCertToListTail(certList, cert) != SECSuccess) {
03515        CERT_DestroyCertificate(cert);
03516        goto loser;
03517     }
03518 
03519     /*
03520      * XXX If/when signing of requests is supported, that second NULL
03521      * should be changed to be the signer certificate.  Not sure if that
03522      * should be passed into this function or retrieved via some operation
03523      * on the handle/context.
03524      */
03525     encodedResponse = CERT_GetEncodedOCSPResponse(NULL, certList, location,
03526                                             time, locationIsDefault,
03527                                             NULL, pwArg, &request);
03528     if (encodedResponse == NULL) {
03529        goto loser;
03530     }
03531 
03532     response = CERT_DecodeOCSPResponse(encodedResponse);
03533     if (response == NULL) {
03534        goto loser;
03535     }
03536 
03537     /*
03538      * Okay, we at least have a response that *looks* like a response!
03539      * Now see if the overall response status value is good or not.
03540      * If not, we set an error and give up.  (It means that either the
03541      * server had a problem, or it didn't like something about our
03542      * request.  Either way there is nothing to do but give up.)
03543      * Otherwise, we continue to find the actual per-cert status
03544      * in the response.
03545      */
03546     if (CERT_GetOCSPResponseStatus(response) != SECSuccess) {
03547        goto loser;
03548     }
03549 
03550     /*
03551      * If we've made it this far, we expect a response with a good signature.
03552      * So, check for that.
03553      */
03554     issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
03555     rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert,
03556                      issuerCert);
03557     if (rv != SECSuccess)
03558        goto loser;
03559 
03560     PORT_Assert(signerCert != NULL);      /* internal consistency check */
03561     /* XXX probably should set error, return failure if signerCert is null */
03562 
03563 
03564     /*
03565      * Again, we are only doing one request for one cert.
03566      * XXX When we handle cert chains, the following code will obviously
03567      * have to be modified, in coordation with the code above that will
03568      * have to determine how to make multiple requests, etc.  It will need
03569      * to loop, and for each certID in the request, find the matching
03570      * single response and check the status specified by it.
03571      *
03572      * We are helped here in that we know that the requests are made with
03573      * the request list in the same order as the order of the certs we hand
03574      * to it.  This is why I can directly access the first member of the
03575      * single request array for the one cert I care about.
03576      */
03577 
03578     certID = request->tbsRequest->requestList[0]->reqCert;
03579     rv = CERT_GetOCSPStatusForCertID(handle, response, certID, 
03580                                      signerCert, time);
03581 loser:
03582     if (issuerCert != NULL)
03583        CERT_DestroyCertificate(issuerCert);
03584     if (signerCert != NULL)
03585        CERT_DestroyCertificate(signerCert);
03586     if (response != NULL)
03587        CERT_DestroyOCSPResponse(response);
03588     if (request != NULL)
03589        CERT_DestroyOCSPRequest(request);
03590     if (encodedResponse != NULL)
03591        SECITEM_FreeItem(encodedResponse, PR_TRUE);
03592     if (certList != NULL)
03593        CERT_DestroyCertList(certList);
03594     if (location != NULL)
03595        PORT_Free(location);
03596     return rv;
03597 }
03598 
03599 SECStatus
03600 CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle, 
03601                             CERTOCSPResponse *response, 
03602                             CERTOCSPCertID   *certID,
03603                             CERTCertificate  *signerCert,
03604                             int64             time)
03605 {
03606     SECStatus rv;
03607     ocspResponseData *responseData;
03608     int64 producedAt;
03609     CERTOCSPSingleResponse *single;
03610 
03611     /*
03612      * The ResponseData part is the real guts of the response.
03613      */
03614     responseData = ocsp_GetResponseData(response);
03615     if (responseData == NULL) {
03616        rv = SECFailure;
03617        goto loser;
03618     }
03619 
03620     /*
03621      * There is one producedAt time for the entire response (and a separate
03622      * thisUpdate time for each individual single response).  We need to
03623      * compare them, so get the overall time to pass into the check of each
03624      * single response.
03625      */
03626     rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt);
03627     if (rv != SECSuccess)
03628        goto loser;
03629 
03630     single = ocsp_GetSingleResponseForCertID(responseData->responses,
03631                                         handle, certID);
03632     if (single == NULL) {
03633        rv = SECFailure;
03634        goto loser;
03635     }
03636 
03637     rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
03638     if (rv != SECSuccess)
03639        goto loser;
03640 
03641     /*
03642      * Okay, the last step is to check whether the status says revoked,
03643      * and if so how that compares to the time value passed into this routine.
03644      */
03645 
03646     rv = ocsp_CertHasGoodStatus(single, time);
03647 loser:
03648     return rv;
03649 }
03650 
03651 
03652 /*
03653  * Disable status checking and destroy related structures/data.
03654  */
03655 static SECStatus
03656 ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig)
03657 {
03658     ocspCheckingContext *statusContext;
03659 
03660     /*
03661      * Disable OCSP checking
03662      */
03663     statusConfig->statusChecker = NULL;
03664 
03665     statusContext = statusConfig->statusContext;
03666     PORT_Assert(statusContext != NULL);
03667     if (statusContext == NULL)
03668        return SECFailure;
03669 
03670     if (statusContext->defaultResponderURI != NULL)
03671        PORT_Free(statusContext->defaultResponderURI);
03672     if (statusContext->defaultResponderNickname != NULL)
03673        PORT_Free(statusContext->defaultResponderNickname);
03674 
03675     PORT_Free(statusContext);
03676     statusConfig->statusContext = NULL;
03677 
03678     PORT_Free(statusConfig);
03679 
03680     return SECSuccess;
03681 }
03682 
03683 
03684 /*
03685  * FUNCTION: CERT_DisableOCSPChecking
03686  *   Turns off OCSP checking for the given certificate database.
03687  *   This routine disables OCSP checking.  Though it will return
03688  *   SECFailure if OCSP checking is not enabled, it is "safe" to
03689  *   call it that way and just ignore the return value, if it is
03690  *   easier to just call it than to "remember" whether it is enabled.
03691  * INPUTS:
03692  *   CERTCertDBHandle *handle
03693  *     Certificate database for which OCSP checking will be disabled.
03694  * RETURN:
03695  *   Returns SECFailure if an error occurred (usually means that OCSP
03696  *   checking was not enabled or status contexts were not initialized --
03697  *   error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise.
03698  */
03699 SECStatus
03700 CERT_DisableOCSPChecking(CERTCertDBHandle *handle)
03701 {
03702     CERTStatusConfig *statusConfig;
03703     ocspCheckingContext *statusContext;
03704 
03705     if (handle == NULL) {
03706        PORT_SetError(SEC_ERROR_INVALID_ARGS);
03707        return SECFailure;
03708     }
03709 
03710     statusConfig = CERT_GetStatusConfig(handle);
03711     statusContext = ocsp_GetCheckingContext(handle);
03712     if (statusContext == NULL)
03713        return SECFailure;
03714 
03715     if (statusConfig->statusChecker != CERT_CheckOCSPStatus) {
03716        /*
03717         * Status configuration is present, but either not currently
03718         * enabled or not for OCSP.
03719         */
03720        PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
03721        return SECFailure;
03722     }
03723 
03724     /*
03725      * This is how we disable status checking.  Everything else remains
03726      * in place in case we are enabled again.
03727      */
03728     statusConfig->statusChecker = NULL;
03729 
03730     return SECSuccess;
03731 }
03732 
03733 /*
03734  * Allocate and initialize the informational structures for status checking.
03735  * This is done when some configuration of OCSP is being done or when OCSP
03736  * checking is being turned on, whichever comes first.
03737  */
03738 static SECStatus
03739 ocsp_InitStatusChecking(CERTCertDBHandle *handle)
03740 {
03741     CERTStatusConfig *statusConfig = NULL;
03742     ocspCheckingContext *statusContext = NULL;
03743 
03744     PORT_Assert(CERT_GetStatusConfig(handle) == NULL);
03745     if (CERT_GetStatusConfig(handle) != NULL) {
03746        /* XXX or call statusConfig->statusDestroy and continue? */
03747        return SECFailure;
03748     }
03749 
03750     statusConfig = PORT_ZNew(CERTStatusConfig);
03751     if (statusConfig == NULL)
03752        goto loser;
03753 
03754     statusContext = PORT_ZNew(ocspCheckingContext);
03755     if (statusContext == NULL)
03756        goto loser;
03757 
03758     statusConfig->statusDestroy = ocsp_DestroyStatusChecking;
03759     statusConfig->statusContext = statusContext;
03760 
03761     CERT_SetStatusConfig(handle, statusConfig);
03762 
03763     return SECSuccess;
03764 
03765 loser:
03766     if (statusConfig != NULL)
03767        PORT_Free(statusConfig);
03768     return SECFailure;
03769 }
03770 
03771 
03772 /*
03773  * FUNCTION: CERT_EnableOCSPChecking
03774  *   Turns on OCSP checking for the given certificate database.
03775  * INPUTS:
03776  *   CERTCertDBHandle *handle
03777  *     Certificate database for which OCSP checking will be enabled.
03778  * RETURN:
03779  *   Returns SECFailure if an error occurred (likely only problem
03780  *   allocating memory); SECSuccess otherwise.
03781  */
03782 SECStatus
03783 CERT_EnableOCSPChecking(CERTCertDBHandle *handle)
03784 {
03785     CERTStatusConfig *statusConfig;
03786     
03787     SECStatus rv;
03788 
03789     if (handle == NULL) {
03790        PORT_SetError(SEC_ERROR_INVALID_ARGS);
03791        return SECFailure;
03792     }
03793 
03794     statusConfig = CERT_GetStatusConfig(handle);
03795     if (statusConfig == NULL) {
03796        rv = ocsp_InitStatusChecking(handle);
03797        if (rv != SECSuccess)
03798            return rv;
03799 
03800        /* Get newly established value */
03801        statusConfig = CERT_GetStatusConfig(handle);
03802        PORT_Assert(statusConfig != NULL);
03803     }
03804 
03805     /*
03806      * Setting the checker function is what really enables the checking
03807      * when each cert verification is done.
03808      */
03809     statusConfig->statusChecker = CERT_CheckOCSPStatus;
03810 
03811     return SECSuccess;
03812 }
03813 
03814 
03815 /*
03816  * FUNCTION: CERT_SetOCSPDefaultResponder
03817  *   Specify the location and cert of the default responder.
03818  *   If OCSP checking is already enabled *and* use of a default responder
03819  *   is also already enabled, all OCSP checking from now on will go directly
03820  *   to the specified responder.  If OCSP checking is not enabled, or if
03821  *   it is but use of a default responder is not enabled, the information
03822  *   will be recorded and take effect whenever both are enabled.
03823  * INPUTS:
03824  *   CERTCertDBHandle *handle
03825  *     Cert database on which OCSP checking should use the default responder.
03826  *   char *url
03827  *     The location of the default responder (e.g. "http://foo.com:80/ocsp")
03828  *     Note that the location will not be tested until the first attempt
03829  *     to send a request there.
03830  *   char *name
03831  *     The nickname of the cert to trust (expected) to sign the OCSP responses.
03832  *     If the corresponding cert cannot be found, SECFailure is returned.
03833  * RETURN:
03834  *   Returns SECFailure if an error occurred; SECSuccess otherwise.
03835  *   The most likely error is that the cert for "name" could not be found
03836  *   (probably SEC_ERROR_UNKNOWN_CERT).  Other errors are low-level (no memory,
03837  *   bad database, etc.).
03838  */
03839 SECStatus
03840 CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle,
03841                           const char *url, const char *name)
03842 {
03843     CERTCertificate *cert;
03844     ocspCheckingContext *statusContext;
03845     char *url_copy = NULL;
03846     char *name_copy = NULL;
03847     SECStatus rv;
03848 
03849     if (handle == NULL || url == NULL || name == NULL) {
03850        /*
03851         * XXX When interface is exported, probably want better errors;
03852         * perhaps different one for each parameter.
03853         */
03854        PORT_SetError(SEC_ERROR_INVALID_ARGS);
03855        return SECFailure;
03856     }
03857 
03858     /*
03859      * Find the certificate for the specified nickname.  Do this first
03860      * because it seems the most likely to fail.
03861      *
03862      * XXX Shouldn't need that cast if the FindCertByNickname interface
03863      * used const to convey that it does not modify the name.  Maybe someday.
03864      */
03865     cert = CERT_FindCertByNickname(handle, (char *) name);
03866     if (cert == NULL) {
03867       /*
03868        * look for the cert on an external token.
03869        */
03870       cert = PK11_FindCertFromNickname((char *)name, NULL);
03871     }
03872     if (cert == NULL)
03873        return SECFailure;
03874 
03875     /*
03876      * Make a copy of the url and nickname.
03877      */
03878     url_copy = PORT_Strdup(url);
03879     name_copy = PORT_Strdup(name);
03880     if (url_copy == NULL || name_copy == NULL) {
03881        rv = SECFailure;
03882        goto loser;
03883     }
03884 
03885     statusContext = ocsp_GetCheckingContext(handle);
03886 
03887     /*
03888      * Allocate and init the context if it doesn't already exist.
03889      */
03890     if (statusContext == NULL) {
03891        rv = ocsp_InitStatusChecking(handle);
03892        if (rv != SECSuccess)
03893            goto loser;
03894 
03895        statusContext = ocsp_GetCheckingContext(handle);
03896        PORT_Assert(statusContext != NULL);       /* extreme paranoia */
03897     }
03898 
03899     /*
03900      * Note -- we do not touch the status context until after all of
03901      * the steps which could cause errors.  If something goes wrong,
03902      * we want to leave things as they were.
03903      */
03904 
03905     /*
03906      * Get rid of old url and name if there.
03907      */
03908     if (statusContext->defaultResponderNickname != NULL)
03909        PORT_Free(statusContext->defaultResponderNickname);
03910     if (statusContext->defaultResponderURI != NULL)
03911        PORT_Free(statusContext->defaultResponderURI);
03912 
03913     /*
03914      * And replace them with the new ones.
03915      */
03916     statusContext->defaultResponderURI = url_copy;
03917     statusContext->defaultResponderNickname = name_copy;
03918 
03919     /*
03920      * If there was already a cert in place, get rid of it and replace it.
03921      * Otherwise, we are not currently enabled, so we don't want to save it;
03922      * it will get re-found and set whenever use of a default responder is
03923      * enabled.
03924      */
03925     if (statusContext->defaultResponderCert != NULL) {
03926        CERT_DestroyCertificate(statusContext->defaultResponderCert);
03927        statusContext->defaultResponderCert = cert;
03928     } else {
03929        PORT_Assert(statusContext->useDefaultResponder == PR_FALSE);
03930        CERT_DestroyCertificate(cert);
03931     }
03932 
03933     return SECSuccess;
03934 
03935 loser:
03936     CERT_DestroyCertificate(cert);
03937     if (url_copy != NULL)
03938        PORT_Free(url_copy);
03939     if (name_copy != NULL)
03940        PORT_Free(name_copy);
03941     return rv;
03942 }
03943 
03944 
03945 /*
03946  * FUNCTION: CERT_EnableOCSPDefaultResponder
03947  *   Turns on use of a default responder when OCSP checking.
03948  *   If OCSP checking is already enabled, this will make subsequent checks
03949  *   go directly to the default responder.  (The location of the responder
03950  *   and the nickname of the responder cert must already be specified.)
03951  *   If OCSP checking is not enabled, this will be recorded and take effect
03952  *   whenever it is enabled.
03953  * INPUTS:
03954  *   CERTCertDBHandle *handle
03955  *     Cert database on which OCSP checking should use the default responder.
03956  * RETURN:
03957  *   Returns SECFailure if an error occurred; SECSuccess otherwise.
03958  *   No errors are especially likely unless the caller did not previously
03959  *   perform a successful call to SetOCSPDefaultResponder (in which case
03960  *   the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER).
03961  */
03962 SECStatus
03963 CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle)
03964 {
03965     ocspCheckingContext *statusContext;
03966     CERTCertificate *cert;
03967 
03968     if (handle == NULL) {
03969        PORT_SetError(SEC_ERROR_INVALID_ARGS);
03970        return SECFailure;
03971     }
03972 
03973     statusContext = ocsp_GetCheckingContext(handle);
03974 
03975     if (statusContext == NULL) {
03976        /*
03977         * Strictly speaking, the error already set is "correct",
03978         * but cover over it with one more helpful in this context.
03979         */
03980        PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
03981        return SECFailure;
03982     }
03983 
03984     if (statusContext->defaultResponderURI == NULL) {
03985        PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
03986        return SECFailure;
03987     }
03988 
03989     if (statusContext->defaultResponderNickname == NULL) {
03990        PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
03991        return SECFailure;
03992     }
03993 
03994     /*
03995      * Find the cert for the nickname.
03996      */
03997     cert = CERT_FindCertByNickname(handle,
03998                                statusContext->defaultResponderNickname);
03999     if (cert == NULL) {
04000         cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname,
04001                                          NULL);
04002     }
04003     /*
04004      * We should never have trouble finding the cert, because its
04005      * existence should have been proven by SetOCSPDefaultResponder.
04006      */
04007     PORT_Assert(cert != NULL);
04008     if (cert == NULL)
04009        return SECFailure;
04010 
04011     /*
04012      * And hang onto it.
04013      */
04014     statusContext->defaultResponderCert = cert;
04015 
04016     /*
04017      * Finally, record the fact that we now have a default responder enabled.
04018      */
04019     statusContext->useDefaultResponder = PR_TRUE;
04020     return SECSuccess;
04021 }
04022 
04023 
04024 /*
04025  * FUNCTION: CERT_DisableOCSPDefaultResponder
04026  *   Turns off use of a default responder when OCSP checking.
04027  *   (Does nothing if use of a default responder is not enabled.)
04028  * INPUTS:
04029  *   CERTCertDBHandle *handle
04030  *     Cert database on which OCSP checking should stop using a default
04031  *     responder.
04032  * RETURN:
04033  *   Returns SECFailure if an error occurred; SECSuccess otherwise.
04034  *   Errors very unlikely (like random memory corruption...).
04035  */
04036 SECStatus
04037 CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle)
04038 {
04039     CERTStatusConfig *statusConfig;
04040     ocspCheckingContext *statusContext;
04041 
04042     if (handle == NULL) {
04043        PORT_SetError(SEC_ERROR_INVALID_ARGS);
04044        return SECFailure;
04045     }
04046 
04047     statusConfig = CERT_GetStatusConfig(handle);
04048     if (statusConfig == NULL)
04049        return SECSuccess;
04050 
04051     statusContext = ocsp_GetCheckingContext(handle);
04052     PORT_Assert(statusContext != NULL);
04053     if (statusContext == NULL)
04054        return SECFailure;
04055 
04056     if (statusContext->defaultResponderCert != NULL) {
04057        CERT_DestroyCertificate(statusContext->defaultResponderCert);
04058        statusContext->defaultResponderCert = NULL;
04059     }
04060 
04061     /*
04062      * Finally, record the fact.
04063      */
04064     statusContext->useDefaultResponder = PR_FALSE;
04065     return SECSuccess;
04066 }
04067 
04068 /*
04069  * Digest the cert's subject public key using the specified algorithm.
04070  * The necessary storage for the digest data is allocated.  If "fill" is
04071  * non-null, the data is put there, otherwise a SECItem is allocated.
04072  * Allocation from "arena" if it is non-null, heap otherwise.  Any problem
04073  * results in a NULL being returned (and an appropriate error set).
04074  */
04075 SECItem *
04076 CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert,
04077                            SECOidTag digestAlg, SECItem *fill)
04078 {
04079     const SECHashObject *digestObject;
04080     void *digestContext;
04081     SECItem *result = NULL;
04082     void *mark = NULL;
04083     SECItem spk;
04084 
04085     if ( arena != NULL ) {
04086         mark = PORT_ArenaMark(arena);
04087     }
04088 
04089     digestObject = HASH_GetHashObjectByOidTag(digestAlg);
04090     if ( digestObject == NULL ) {
04091         goto loser;
04092     }
04093 
04094     if ((fill == NULL) || (fill->data == NULL)) {
04095        result = SECITEM_AllocItem(arena, fill, digestObject->length);
04096        if ( result == NULL ) {
04097           goto loser;
04098        }
04099        fill = result;
04100     }
04101 
04102     /*
04103      * Copy just the length and data pointer (nothing needs to be freed)
04104      * of the subject public key so we can convert the length from bits
04105      * to bytes, which is what the digest function expects.
04106      */
04107     spk = cert->subjectPublicKeyInfo.subjectPublicKey;
04108     DER_ConvertBitString(&spk);
04109 
04110     /*
04111      * Now digest the value, using the specified algorithm.
04112      */
04113     digestContext = digestObject->create();
04114     if ( digestContext == NULL ) {
04115         goto loser;
04116     }
04117     digestObject->begin(digestContext);
04118     digestObject->update(digestContext, spk.data, spk.len);
04119     digestObject->end(digestContext, fill->data, &(fill->len), fill->len);
04120     digestObject->destroy(digestContext, PR_TRUE);
04121 
04122     if ( arena != NULL ) {
04123         PORT_ArenaUnmark(arena, mark);
04124     }
04125     return(fill);
04126 
04127 loser:
04128     if ( arena != NULL ) {
04129         PORT_ArenaRelease(arena, mark);
04130     } else {
04131         if ( result != NULL ) {
04132             SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE);
04133         }
04134     }
04135     return(NULL);
04136 }
04137 
04138 SECStatus
04139 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response)
04140 {
04141     PORT_Assert(response);
04142     if (response->statusValue == ocspResponse_successful)
04143        return SECSuccess;
04144 
04145     switch (response->statusValue) {
04146       case ocspResponse_malformedRequest:
04147        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
04148        break;
04149       case ocspResponse_internalError:
04150        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
04151        break;
04152       case ocspResponse_tryLater:
04153        PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER);
04154        break;
04155       case ocspResponse_sigRequired:
04156        /* XXX We *should* retry with a signature, if possible. */
04157        PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
04158        break;
04159       case ocspResponse_unauthorized:
04160        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
04161        break;
04162       case ocspResponse_other:
04163       case ocspResponse_unused:
04164       default:
04165        PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
04166        break;
04167     }
04168     return SECFailure;
04169 }