XrdCryptosslgsiX509Chain.cc

Go to the documentation of this file.
00001 // $Id: XrdCryptosslgsiX509Chain.cc 30949 2009-11-02 16:37:58Z ganis $
00002 
00003 const char *XrdCryptosslgsiX509ChainCVSID = "$Id: XrdCryptosslgsiX509Chain.cc 30949 2009-11-02 16:37:58Z ganis $";
00004 /******************************************************************************/
00005 /*                                                                            */
00006 /*           X r d C r y p t o s s l g s i X 5 0 9 C h a i n . h h            */
00007 /*                                                                            */
00008 /* (c) 2005  G. Ganis, CERN                                                   */
00009 /*                                                                            */
00010 /******************************************************************************/
00011 #include <string.h>
00012 #include <time.h>
00013 
00014 #include <XrdCrypto/XrdCryptosslgsiAux.hh>
00015 #include <XrdCrypto/XrdCryptosslgsiX509Chain.hh>
00016 #include <XrdCrypto/XrdCryptoTrace.hh>
00017 
00018 // ---------------------------------------------------------------------------//
00019 //                                                                            //
00020 // XrdCryptosslgsiX509Chain                                                   //
00021 //                                                                            //
00022 // Enforce GSI policies on X509 certificate chains                            //
00023 //                                                                            //
00024 // ---------------------------------------------------------------------------//
00025 
00026 //___________________________________________________________________________
00027 bool XrdCryptosslgsiX509Chain::Verify(EX509ChainErr &errcode, x509ChainVerifyOpt_t *vopt)
00028 {
00029    // Verify the chain
00030    EPNAME("X509Chain::Verify");
00031    errcode = kNone; 
00032 
00033    // There must be at least a CA and a EEC. 
00034    if (size < 2) {
00035       DEBUG("Nothing to verify (size: "<<size<<")");
00036       return 0;
00037    }
00038    if (QTRACE(Dump)) { Dump(); }
00039 
00040    //
00041    // Reorder if needed
00042    if (Reorder() != 0) {
00043       errcode = kInconsistent;
00044       lastError = ":";
00045       lastError += X509ChainError(errcode);
00046       return 0;
00047    }
00048 
00049    //
00050    // Verification options
00051    int opt  = (vopt) ? vopt->opt : 0;
00052    int when = (vopt) ? vopt->when : (int)time(0);
00053    int plen = (vopt) ? vopt->pathlen : -1;
00054    XrdCryptoX509Crl *crl = (vopt) ? vopt->crl : 0;
00055 
00056    //
00057    // Global path depth length consistency check
00058    if (plen > -1 && plen < size) {
00059       errcode = kTooMany;
00060       lastError = "checking path depth: ";
00061       lastError += X509ChainError(errcode);
00062    }
00063 
00064    //
00065    // Check the first certificate: it MUST be of CA type, valid,
00066    // self-signed
00067    XrdCryptoX509ChainNode *node = begin;
00068    XrdCryptoX509 *xcer = node->Cert();      // Certificate under exam
00069    XrdCryptoX509 *xsig = xcer;              // Signing certificate
00070    if (statusCA == kUnknown) {
00071       if (!XrdCryptoX509Chain::Verify(errcode, "CA: ",
00072                                       XrdCryptoX509::kCA, when, xcer, xsig))
00073          return 0;
00074       statusCA = kValid;
00075    } else if (statusCA == kAbsent || statusCA == kInvalid) {
00076       errcode = kNoCA;
00077       lastError = X509ChainError(errcode);
00078       return 0;
00079    }
00080 
00081    //
00082    // Update the max path depth len
00083    if (plen > -1)
00084       plen -= 1;
00085    //
00086    // Check the end-point entity (or sub-CA) certificate
00087    while (node->Next() && strcmp(node->Next()->Cert()->Type(), "Proxy")) {
00088       xsig = xcer;
00089       node = node->Next();
00090       xcer = node->Cert();
00091       if (!XrdCryptoX509Chain::Verify(errcode, "EEC or sub-CA: ",
00092                                       XrdCryptoX509::kUnknown,
00093                                       when, xcer, xsig, crl))
00094          return 0;
00095       //
00096       // Update the max path depth len
00097       if (plen > -1)
00098          plen -= 1;
00099    }
00100 
00101    //
00102    // There are proxy certificates
00103    xsig = xcer;
00104    node = node->Next();
00105    while (node && (plen == -1 || plen > 0)) {
00106 
00107       // Attache to certificate
00108       xcer = node->Cert();
00109 
00110       // Proxy subject name must follow some rules
00111       if (!SubjectOK(errcode, xcer))
00112          return 0;
00113 
00114       // Check if ProxyCertInfo extension is there (required by RFC3820)
00115       int pxplen = -1;
00116       if (opt & kOptsRfc3820) {
00117          const void *extdata = xcer->GetExtension(gsiProxyCertInfo_OID);
00118          if (!extdata || !XrdSslgsiProxyCertInfo(extdata, pxplen)) {
00119             errcode = kMissingExtension;
00120             lastError = "rfc3820: ";
00121             lastError += X509ChainError(errcode);
00122             return 0;
00123          }
00124       }
00125       // Update plen, if needed
00126       if (plen == -1) {
00127          plen = (pxplen > -1) ? pxplen : plen;
00128       } else {
00129          plen--;
00130          // Aply stricter rules if required
00131          plen = (pxplen > -1 && pxplen < plen) ? pxplen : plen;
00132       }
00133 
00134       // Standard verification
00135       if (!XrdCryptoX509Chain::Verify(errcode, "Proxy: ",
00136                                       XrdCryptoX509::kProxy, when, xcer, xsig))
00137          return 0;
00138 
00139       // Get next
00140       xsig = xcer;
00141       node = node->Next();
00142    }
00143 
00144    // We are done (successfully!)
00145    return 1;
00146 }
00147 
00148 
00149 //___________________________________________________________________________
00150 bool XrdCryptosslgsiX509Chain::SubjectOK(EX509ChainErr &errcode, XrdCryptoX509 *xcer)
00151 {
00152    // Apply GSI rules for proxy subject names
00153 
00154    // Check inputs
00155    if (!xcer) {
00156       errcode = kNoCertificate;
00157       lastError = "subject check:";
00158       lastError += X509ChainError(errcode);
00159       return 0;
00160    }
00161 
00162    // This applies only to proxies
00163    if (xcer->type != XrdCryptoX509::kProxy)
00164       return 1;
00165 
00166    // Pointers to names
00167    if (!(xcer->Subject()) || !(xcer->Issuer())) {
00168       errcode = kInvalidNames;
00169       lastError = "subject check:";
00170       lastError += X509ChainError(errcode);
00171       return 0;
00172    }
00173 
00174    // Subject name must start with issuer name.
00175    // We need the length of the common part between issuer and subject.
00176    // We allow proxies issued by other proxies. In such cases we must
00177    // ignore the last '/CN=' in the issuer name; this explains the need
00178    // for the following gymnastic.
00179 
00180    int ilen = strlen(xcer->Issuer());
00181    if (strncmp(xcer->Subject(), xcer->Issuer(), ilen)) {
00182       // Check if the issuer is a proxy: ignore the last 'CN='
00183       char *pcn = (char *) strstr(xcer->Issuer(), "/CN=");
00184       if (pcn) {
00185          char *pcnn = 0;
00186          while ((pcnn = (char *) strstr(pcn+1,"/CN=")))
00187             pcn = pcnn;
00188          ilen = (int)(pcn - xcer->Issuer());
00189       }
00190       if (strncmp(xcer->Subject() + ilen,"/CN=",4)) {
00191          errcode = kInvalidNames;
00192          lastError = "proxy subject check: found additional chars :";
00193          lastError += X509ChainError(errcode);
00194          return 0;
00195       }
00196       if (strncmp(xcer->Subject(), xcer->Issuer(), ilen)) {
00197          errcode = kInvalidNames;
00198          lastError = "proxy issuer check: issuer not found in subject :";
00199          lastError += X509ChainError(errcode);
00200          return 0;
00201       }
00202    }
00203 
00204    // A common name must be appendend
00205    char *pp = (char *)strstr(xcer->Subject()+ilen, "CN=");
00206    if (!pp) {
00207       errcode = kInvalidNames;
00208       lastError = "proxy subject check: no appended 'CN='";
00209       lastError += X509ChainError(errcode);
00210       return 0;
00211    }
00212 
00213    // But only one
00214    pp = strstr(pp+strlen("CN="), "CN=");
00215    if (pp) {
00216       errcode = kInvalidNames;
00217       lastError = "proxy subject check: too many appended 'CN='s";
00218       lastError += X509ChainError(errcode);
00219       return 0;
00220    }
00221 
00222    // We are done
00223    return 1;
00224 }
00225 
00226 

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