grst_verifycallback.c

Go to the documentation of this file.
00001 /* This code is extracted from mod_gridsite removing references to apache methods */
00002 
00003 /*
00004    Copyright (c) 2003-7, Andrew McNab, Shiv Kaushal, Joseph Dada,
00005    and Yibiao Li, University of Manchester. All rights reserved.
00006 
00007    Redistribution and use in source and binary forms, with or
00008    without modification, are permitted provided that the following
00009    conditions are met:
00010 
00011      o Redistributions of source code must retain the above
00012        copyright notice, this list of conditions and the following
00013        disclaimer. 
00014      o Redistributions in binary form must reproduce the above
00015        copyright notice, this list of conditions and the following
00016        disclaimer in the documentation and/or other materials
00017        provided with the distribution. 
00018 
00019    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
00020    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
00021    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00022    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00023    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
00024    BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00026    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00027    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00028    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031    POSSIBILITY OF SUCH DAMAGE.
00032 
00033 
00034    This program includes code from dav_parse_range() from Apache mod_dav.c,
00035    and associated code contributed by  David O Callaghan
00036    
00037    Copyright 2000-2005 The Apache Software Foundation or its licensors, as
00038    applicable.
00039    
00040    Licensed under the Apache License, Version 2.0 (the "License");
00041    you may not use this file except in compliance with the License.
00042    You may obtain a copy of the License at
00043 
00044         http://www.apache.org/licenses/LICENSE-2.0
00045    
00046    Unless required by applicable law or agreed to in writing, software
00047    distributed under the License is distributed on an "AS IS" BASIS,
00048    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00049    See the License for the specific language governing permissions and
00050    limitations under the License.
00051 */
00052 
00053 #include "grst_verifycallback.h"
00054 #include "gridsite.h"
00055 #include <openssl/x509v3.h>
00056 #include <string.h>
00057 
00058 X509_STORE* grst_store=NULL;
00059 int grst_verify=0;
00060 int grst_depth=0;
00061 char* grst_cadir   = "/etc/grid-certificates/certificates";
00062 char* grst_vomsdir = "/etc/grid-certificates/vomsdir";
00063 
00064 // APACHE mod_ssl functions
00065 int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx);
00066 int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx);
00067 
00068 // GRIDSITE functions
00069 int GRST_X509_check_issued_wrapper(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
00070 /* We change the default callback to use our wrapper and discard errors
00071    due to GSI proxy chains (ie where users certs act as CAs) */
00072 {
00073     int ret;
00074     ret = X509_check_issued(issuer, x);
00075     if (ret == X509_V_OK)
00076                 return 1;
00077          
00078     /* Non self-signed certs without signing are ok if they passed
00079            the other checks inside X509_check_issued. Is this enough? */
00080     if ((ret == X509_V_ERR_KEYUSAGE_NO_CERTSIGN) &&
00081         (X509_NAME_cmp(X509_get_subject_name(issuer),
00082                            X509_get_subject_name(x)) != 0)) return 1;
00083  
00084     /* If we haven't asked for issuer errors don't set ctx */
00085 #if OPENSSL_VERSION_NUMBER < 0x00908000
00086     if (!(ctx->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0;
00087 #else
00088     if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) return 0;
00089 #endif 
00090   
00091     ctx->error = ret;
00092     ctx->current_cert = x;
00093     ctx->current_issuer = issuer;
00094     return ctx->verify_cb(0, ctx);
00095 }
00096 
00097 /* Later OpenSSL versions add a second pointer ... */
00098 int GRST_verify_cert_wrapper(X509_STORE_CTX *ctx, void *p)
00099 
00100 /* Earlier ones have a single argument ... */
00101 // int GRST_verify_cert_wrapper(X509_STORE_CTX *ctx)
00102 
00103 /* Before 0.9.7 we cannot change the check_issued callback directly in
00104    the X509_STORE, so we must insert it in another callback that gets
00105    called early enough */
00106 {
00107    ctx->check_issued = GRST_X509_check_issued_wrapper;
00108 #ifdef R__SSL_GE_098
00109    X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_ALLOW_PROXY_CERTS);
00110 #endif
00111    return X509_verify_cert(ctx);
00112 }
00113 
00114 int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
00115 {
00116    SSL *ssl            = (SSL *) X509_STORE_CTX_get_app_data(ctx);
00117    int errnum          = X509_STORE_CTX_get_error(ctx);
00118    int errdepth        = X509_STORE_CTX_get_error_depth(ctx);
00119    int returned_ok;
00120    STACK_OF(X509) *certstack;
00121    GRSTx509Chain *grst_chain;
00122    GRSTx509Chain *grst_old_chain;
00123 
00124    /*
00125     * GSI Proxy user-cert-as-CA handling:
00126     * we skip Invalid CA errors at this stage, since we will check this
00127     * again at errdepth=0 for the full chain using GRSTx509ChainLoadCheck
00128     */
00129    if (errnum == X509_V_ERR_INVALID_CA)
00130      {
00131        GRSTerrorLog(GRST_LOG_DEBUG,"Skip invalid CA error, since we will check again at errdepth=0");
00132        ok = TRUE;
00133        errnum = X509_V_OK;
00134         X509_STORE_CTX_set_error(ctx, errnum);
00135      }
00136 
00137    /*
00138     * New style GSI Proxy handling, with critical ProxyCertInfo
00139     * extension: we use GRSTx509KnownCriticalExts() to check this
00140     */
00141 #ifndef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION
00142 #define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
00143 #endif
00144    if (errnum == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)
00145      {
00146        if (GRSTx509KnownCriticalExts(X509_STORE_CTX_get_current_cert(ctx))
00147                                                               == GRST_RET_OK)
00148          {
00149            GRSTerrorLog(GRST_LOG_DEBUG,"GRSTx509KnownCriticalExts() accepts previously unhandled Critical Extension(GSI Proxy?)");
00150            ok = TRUE;
00151            errnum = X509_V_OK;
00152            X509_STORE_CTX_set_error(ctx, errnum);
00153          }
00154      }
00155 
00156    if (errnum == X509_V_ERR_INVALID_PURPOSE ) {
00157      GRSTerrorLog(GRST_LOG_DEBUG,"GRSTx509 invalid purpose error ignored ");
00158      ok =  TRUE;
00159      errnum = X509_V_OK;
00160      X509_STORE_CTX_set_error(ctx, errnum);
00161    }
00162 
00163    returned_ok = ssl_callback_SSLVerify(ok, ctx);
00164 
00165    /* in case ssl_callback_SSLVerify changed it */
00166    errnum = X509_STORE_CTX_get_error(ctx); 
00167 
00168    if ((errdepth == 0) && (errnum == X509_V_OK))
00169    /*
00170     * We've now got the last certificate - the identity being used for
00171     * this connection. At this point we check the whole chain for valid
00172     * CAs or, failing that, GSI-proxy validity using GRSTx509CheckChain.
00173     */
00174      {
00175         certstack = (STACK_OF(X509) *) X509_STORE_CTX_get_chain(ctx);
00176 
00177         errnum = GRSTx509ChainLoadCheck(&grst_chain, certstack, NULL,
00178                                         grst_cadir, 
00179                                         grst_vomsdir);
00180 
00181         if (errnum != X509_V_OK)
00182           {
00183             GRSTerrorLog(GRST_LOG_ERR,"Invalid certificate chain reported by GRSTx509CheckChain() %s\n", X509_verify_cert_error_string(errnum));
00184             ok = FALSE;
00185           }
00186         else 
00187           {
00188             GRSTerrorLog(GRST_LOG_DEBUG,"Valid certificate chain reported by GRSTx509ChainLoadCheck()\n");
00189           }
00190 
00191         // we don't free it but rather put it into the SSL context application data
00192         if ((grst_old_chain = SSL_get_app_data(ssl))) {
00193           SSL_set_app_data(ssl,grst_chain);
00194           GRSTerrorLog(GRST_LOG_INFO,"Free Chain %llx", grst_old_chain);
00195           GRSTx509ChainFree(grst_old_chain);
00196         } else {
00197           SSL_set_app_data(ssl,grst_chain);
00198         }
00199      }
00200 
00201    return returned_ok;
00202 }
00203 
00204 /*
00205     Save result validity info from chain into connection notes,
00206     and write out in an SSL session creds file.
00207 */
00208 
00209 void GRST_print_ssl_creds(void *in_chain)
00210 {
00211    int                       i= 0;
00212    int lowest_voms_delegation = 65535;
00213    GRSTx509Chain *grst_chain = (GRSTx509Chain*) in_chain;
00214    GRSTx509Cert  *grst_cert = NULL;
00215 
00216    /* check if already done */
00217 
00218    for (grst_cert = grst_chain->firstcert;
00219         grst_cert != NULL; grst_cert = grst_cert->next)
00220       {
00221         if (grst_cert->type == GRST_CERT_TYPE_VOMS)
00222           {
00223             /* want to record the delegation level 
00224                of the last proxy with VOMS attributes */
00225             GRSTerrorLog(GRST_LOG_DEBUG,"Recording VOMS delegation %d\n",grst_cert->delegation);
00226             lowest_voms_delegation = grst_cert->delegation;
00227           }
00228         else if ((grst_cert->type == GRST_CERT_TYPE_EEC) ||
00229                  (grst_cert->type == GRST_CERT_TYPE_PROXY))
00230           {
00231             GRSTerrorLog(GRST_LOG_INFO,"(%d) dn: %s\n",i,grst_cert->dn);
00232             GRSTerrorLog(GRST_LOG_INFO,"notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",grst_cert->notbefore,grst_cert->notafter,grst_cert->delegation);
00233             ++i;
00234           }
00235       }
00236    
00237    for (grst_cert = grst_chain->firstcert; 
00238         grst_cert != NULL; grst_cert = grst_cert->next)
00239       {
00240         if ((grst_cert->type == GRST_CERT_TYPE_VOMS) &&
00241             (grst_cert->delegation == lowest_voms_delegation))
00242           {
00243             /* only export attributes from the last proxy to contain them */
00244             GRSTerrorLog(GRST_LOG_INFO,"fqan:%s\n",grst_cert->value);
00245             GRSTerrorLog(GRST_LOG_INFO,"notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",grst_cert->notbefore,grst_cert->notafter,grst_cert->delegation);
00246             ++i;
00247           }
00248       }
00249 }
00250 
00251 
00252 char* GRST_get_voms_roles_and_free(void* in_chain)
00253 {
00254   int          i, lowest_voms_delegation = 65535;
00255   GRSTx509Chain *grst_chain = (GRSTx509Chain*) in_chain;
00256   GRSTx509Cert  *grst_cert = NULL;
00257 
00258   char* voms_roles = (char*) malloc(16384);
00259   voms_roles[0] =0;
00260 
00261   if (!voms_roles) {
00262     return NULL;
00263   }
00264 
00265   /* check if already done */
00266   
00267   for (grst_cert = grst_chain->firstcert;
00268        grst_cert != NULL; grst_cert = grst_cert->next)
00269     {
00270       if (grst_cert->type == GRST_CERT_TYPE_VOMS)
00271         {
00272           /* want to record the delegation level 
00273              of the last proxy with VOMS attributes */
00274           lowest_voms_delegation = grst_cert->delegation;
00275         }
00276       else if ((grst_cert->type == GRST_CERT_TYPE_EEC) ||
00277                (grst_cert->type == GRST_CERT_TYPE_PROXY))
00278         {
00279           ++i;
00280         }
00281     }
00282   
00283   for (grst_cert = grst_chain->firstcert; 
00284        grst_cert != NULL; grst_cert = grst_cert->next)
00285     {
00286       if ((grst_cert->type == GRST_CERT_TYPE_VOMS) &&
00287           (grst_cert->delegation == lowest_voms_delegation))
00288         {
00289           /* only export attributes from the last proxy to contain them */
00290           GRSTerrorLog(GRST_LOG_DEBUG,"fqan:%s\n",grst_cert->value);
00291 
00292           // filter the faulty roles out
00293           //      if (((strstr(grst_cert->value,"Role=NULL")))) {
00294           //            //|| (strstr(grst_cert->value,"Capability=NULL"))))) {
00295           // filter out - don't concatenate
00296           //      } else {
00297           
00298           // don't filter, but leave it to the application to interpret the FQANs
00299           strcat(voms_roles,grst_cert->value);
00300           strcat(voms_roles,":");
00301           //      }
00302           GRSTerrorLog(GRST_LOG_DEBUG,"notbefore=%ld notafter=%ld delegation=%d nist-loa=%d\n",grst_cert->notbefore,grst_cert->notafter,grst_cert->delegation);
00303           ++i;
00304         }
00305     }
00306   
00307   if (strlen(voms_roles)) {
00308     // remove last :
00309     voms_roles[strlen(voms_roles)-1] = 0;
00310   }
00311 
00312 
00313   if (grst_chain) {
00314     GRSTerrorLog(GRST_LOG_INFO,"Free Chain %llx", grst_chain);
00315     GRSTx509ChainFree(grst_chain);
00316   }
00317   return voms_roles;
00318 }
00319 
00320 void GRST_free_chain(void* in_chain) {
00321   GRSTx509Chain *grst_chain = (GRSTx509Chain*) in_chain;
00322   if (grst_chain) 
00323     GRSTx509ChainFree(grst_chain);
00324 }
00325 
00326 
00327 /*                      _             _
00328 **  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
00329 ** | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
00330 ** | | | | | | (_) | (_| |   \__ \__ \ |  www.modssl.org
00331 ** |_| |_| |_|\___/ \__,_|___|___/___/_|  ftp.modssl.org
00332 **                      |_____|
00333 **  ssl_engine_kernel.c
00334 **  The SSL engine kernel
00335 */
00336 
00337 /*
00338  * This OpenSSL callback function is called when OpenSSL
00339  * does client authentication and verifies the certificate chain.
00340  */
00341 int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
00342 {
00343   X509 *xs;
00344   int errnum;
00345   int errdepth;
00346   char *cp;
00347   char *cp2;
00348   int depth;
00349 
00350   /*
00351    * Get context back through OpenSSL context
00352    */
00353   SSL *ssl            = (SSL *) X509_STORE_CTX_get_app_data(ctx);
00354   
00355   /*
00356    * Get verify ingredients
00357    */
00358   xs       = X509_STORE_CTX_get_current_cert(ctx);
00359   errnum   = X509_STORE_CTX_get_error(ctx);
00360   errdepth = X509_STORE_CTX_get_error_depth(ctx);
00361   
00362   /*
00363    * Log verification information
00364    */
00365   cp  = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
00366   cp2 = X509_NAME_oneline(X509_get_issuer_name(xs),  NULL, 0);
00367   
00368   GRSTerrorLog(GRST_LOG_DEBUG,
00369           "Certificate Verification: depth: %d, subject: %s, issuer: %s\n",
00370           errdepth, cp != NULL ? cp : "-unknown-",
00371           cp2 != NULL ? cp2 : "-unknown");
00372   
00373 
00374   if (cp)
00375     OPENSSL_free(cp);
00376   if (cp2)
00377     OPENSSL_free(cp2);
00378   
00379   /*
00380    * Check for optionally acceptable non-verifiable issuer situation
00381    */
00382   
00383   if (   (   errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
00384              || errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
00385              || errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
00386 #if SSL_LIBRARY_VERSION >= 0x00905000
00387              || errnum == X509_V_ERR_CERT_UNTRUSTED
00388 #endif
00389              || errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE  )
00390          && grst_verify == GRST_VERIFY_OPTIONAL_NO_CA ) {
00391     GRSTerrorLog(GRST_LOG_ERR,
00392                  "Certificate Verification: Verifiable Issuer is configured as "
00393                  "optional, therefore we're accepting the certificate\n");
00394     SSL_set_verify_result(ssl, X509_V_OK);
00395     ok = TRUE;
00396   }
00397 
00398   /*
00399    * Additionally perform CRL-based revocation checks
00400    */
00401   
00402   if (ok) {
00403     ok = ssl_callback_SSLVerify_CRL(ok, ctx);
00404     if (!ok)
00405       errnum = X509_STORE_CTX_get_error(ctx);
00406   }
00407   
00408     /*
00409      * If we already know it's not ok, log the real reason
00410      */
00411   if (!ok) {
00412     GRSTerrorLog(GRST_LOG_ERR,"Certificate Verification: Error (%d): %s\n",
00413                  errnum, X509_verify_cert_error_string(errnum));
00414   }
00415   
00416   /*
00417    * Finally check the depth of the certificate verification
00418    */
00419   
00420   depth = grst_depth;
00421   
00422   if (errdepth > depth) {
00423     GRSTerrorLog(GRST_LOG_ERR,
00424                  "Certificate Verification: Certificate Chain too long "
00425                  "(chain has %d certificates, but maximum allowed are only %d)\n",
00426                  errdepth, depth);
00427     ok = FALSE;
00428   }
00429   
00430   /*
00431    * And finally signal OpenSSL the (perhaps changed) state
00432    */
00433   return (ok);
00434 }
00435 
00436 int ssl_callback_SSLVerify_CRL(
00437                                int ok, X509_STORE_CTX *ctx)
00438 {
00439   X509_OBJECT obj;
00440   X509_NAME *subject;
00441   X509_NAME *issuer;
00442   X509 *xs;
00443   X509_CRL *crl;
00444   X509_REVOKED *revoked;
00445   EVP_PKEY *pubkey;
00446   long serial;
00447   int i, n, rc;
00448   char *cp;
00449   ASN1_TIME *t;
00450   
00451   /*
00452    * Determine certificate ingredients in advance
00453    */
00454 
00455   GRSTerrorLog(GRST_LOG_DEBUG,"Checking certificate revocation lists\n");
00456 
00457 
00458   xs      = X509_STORE_CTX_get_current_cert(ctx);
00459   subject = X509_get_subject_name(xs);
00460   issuer  = X509_get_issuer_name(xs);
00461   
00462 
00463   /*
00464    * OpenSSL provides the general mechanism to deal with CRLs but does not
00465    * use them automatically when verifying certificates, so we do it
00466    * explicitly here. We will check the CRL for the currently checked
00467    * certificate, if there is such a CRL in the store.
00468    *
00469    * We come through this procedure for each certificate in the certificate
00470    * chain, starting with the root-CA's certificate. At each step we've to
00471    * both verify the signature on the CRL (to make sure it's a valid CRL)
00472    * and it's revocation list (to make sure the current certificate isn't
00473    * revoked).  But because to check the signature on the CRL we need the
00474    * public key of the issuing CA certificate (which was already processed
00475    * one round before), we've a little problem. But we can both solve it and
00476    * at the same time optimize the processing by using the following
00477    * verification scheme (idea and code snippets borrowed from the GLOBUS
00478    * project):
00479    *
00480    * 1. We'll check the signature of a CRL in each step when we find a CRL
00481    *    through the _subject_ name of the current certificate. This CRL
00482    *    itself will be needed the first time in the next round, of course.
00483    *    But we do the signature processing one round before this where the
00484    * public key of the issuing CA certificate (which was already processed
00485    * one round before), we've a little problem. But we can both solve it and
00486    * at the same time optimize the processing by using the following
00487    * verification scheme (idea and code snippets borrowed from the GLOBUS
00488    * project):
00489    *
00490    * 1. We'll check the signature of a CRL in each step when we find a CRL
00491    *    through the _subject_ name of the current certificate. This CRL
00492    *    itself will be needed the first time in the next round, of course.
00493    *    But we do the signature processing one round before this where the
00494    *    public key of the CA is available.
00495    *
00496    * 2. We'll check the revocation list of a CRL in each step when
00497    *    we find a CRL through the _issuer_ name of the current certificate.
00498    *    This CRLs signature was then already verified one round before.
00499    *
00500    * This verification scheme allows a CA to revoke its own certificate as
00501    * well, of course.
00502 
00503    */
00504 
00505   if (!grst_store) {
00506     return 1;
00507   }
00508 
00509 
00510   /*
00511    * Try to retrieve a CRL corresponding to the _subject_ of
00512    * the current certificate in order to verify it's integrity.
00513    */
00514   memset((char *)&obj, 0, sizeof(obj));
00515   
00516   rc = SSL_X509_STORE_lookup(grst_store,X509_LU_CRL, subject, &obj);
00517 
00518   crl = obj.data.crl;
00519   if (rc > 0 && crl != NULL) {
00520     GRSTerrorLog(GRST_LOG_DEBUG,"CRL lookup ...");
00521     /*
00522      * Verify the signature on this CRL
00523      */
00524     pubkey = X509_get_pubkey(xs);
00525     if (X509_CRL_verify(crl, pubkey) <= 0) {
00526     GRSTerrorLog(GRST_LOG_ERR,"Invalid signature on CRL\n");
00527     X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
00528     X509_OBJECT_free_contents(&obj);
00529     if (pubkey != NULL)
00530       EVP_PKEY_free(pubkey);
00531     return 0;
00532     }
00533     
00534     if (pubkey != NULL)
00535       EVP_PKEY_free(pubkey);
00536     
00537     /*
00538      * Check date of CRL to make sure it's not expired
00539      */
00540     if ((t = X509_CRL_get_nextUpdate(crl)) == NULL) {
00541       GRSTerrorLog(GRST_LOG_ERR,"Found CRL has invalid enxtUpdate field\n");
00542       X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
00543       X509_OBJECT_free_contents(&obj);
00544       return 0;
00545     }
00546     if (X509_cmp_current_time(t) < 0) {
00547       GRSTerrorLog(GRST_LOG_ERR,"Found CRL is expired - "
00548                    "revoking all certificates until you get updated CRL\n");
00549       X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
00550       X509_OBJECT_free_contents(&obj);
00551       return 0;
00552     }
00553     X509_OBJECT_free_contents(&obj);
00554   }
00555   
00556   /*
00557    * Try to retrieve a CRL corresponding to the _issuer_ of
00558    * the current certificate in order to check for revocation.
00559    */
00560   
00561   memset((char *)&obj, 0, sizeof(obj));
00562   rc = SSL_X509_STORE_lookup(grst_store,X509_LU_CRL, issuer, &obj);
00563   crl = obj.data.crl;
00564   if (rc > 0 && crl != NULL) {
00565     /*
00566      * Check if the current certificate is revoked by this CRL
00567      */
00568 #if SSL_LIBRARY_VERSION < 0x00904000
00569     n = sk_num(X509_CRL_get_REVOKED(crl));
00570 #else
00571     n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
00572 #endif
00573     for (i = 0; i < n; i++) {
00574 #if SSL_LIBRARY_VERSION < 0x00904000
00575       revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
00576 #else
00577       revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
00578 #endif
00579       if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(xs)) == 0) {
00580         serial = ASN1_INTEGER_get(revoked->serialNumber);
00581         cp = X509_NAME_oneline(issuer, NULL, 0);
00582         GRSTerrorLog(GRST_LOG_ERR,
00583                      "Certificate with serial %ld (0x%lX) "
00584                      "revoked per CRL from issuer %s\n",
00585                      serial, serial, cp);
00586         OPENSSL_free(cp);
00587         
00588         X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
00589         X509_OBJECT_free_contents(&obj);
00590         return 0;
00591       }
00592     }
00593     X509_OBJECT_free_contents(&obj);
00594   }
00595   return 1;
00596 }
00597 
00598 /*  _________________________________________________________________
00599 **
00600 **  Certificate Revocation List (CRL) Storage
00601 **  _________________________________________________________________
00602 */
00603 
00604 X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath)
00605 {
00606   X509_STORE *pStore;
00607   X509_LOOKUP *pLookup;
00608   
00609   if (cpFile == NULL && cpPath == NULL)
00610     return NULL;
00611   if ((pStore = X509_STORE_new()) == NULL)
00612     return NULL;
00613   if (cpFile != NULL) {
00614     if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file())) == NULL) {
00615       X509_STORE_free(pStore);
00616       return NULL;
00617     }
00618     X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
00619   }
00620   if (cpPath != NULL) {
00621     if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir())) == NULL) {
00622       X509_STORE_free(pStore);
00623       return NULL;
00624     }
00625     X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
00626   }
00627   return pStore;
00628 }
00629 
00630 int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
00631                           X509_NAME *pName, X509_OBJECT *pObj)
00632 {
00633   X509_STORE_CTX pStoreCtx;
00634   int rc;
00635   
00636   X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
00637   rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
00638   X509_STORE_CTX_cleanup(&pStoreCtx);
00639   return rc;
00640 }

Generated on Tue Jul 5 14:47:01 2011 for ROOT_528-00b_version by  doxygen 1.5.1