XrdCryptosslX509Req.cc

Go to the documentation of this file.
00001 // $Id: XrdCryptosslX509Req.cc 31508 2009-12-02 19:11:01Z brun $
00002 
00003 const char *XrdCryptosslX509ReqCVSID = "$Id: XrdCryptosslX509Req.cc 31508 2009-12-02 19:11:01Z brun $";
00004 /******************************************************************************/
00005 /*                                                                            */
00006 /*                 X r d C r y p t o s s l X 5 0 9 R e q. c c                 */
00007 /*                                                                            */
00008 /* (c) 2005 G. Ganis , CERN                                                   */
00009 /*                                                                            */
00010 /******************************************************************************/
00011 
00012 
00013 /* ************************************************************************** */
00014 /*                                                                            */
00015 /* OpenSSL implementation of XrdCryptoX509Req                                 */
00016 /*                                                                            */
00017 /* ************************************************************************** */
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <unistd.h>
00021 #include <errno.h>
00022 
00023 #include <XrdCrypto/XrdCryptosslRSA.hh>
00024 #include <XrdCrypto/XrdCryptosslX509Req.hh>
00025 #include <XrdCrypto/XrdCryptosslAux.hh>
00026 #include <XrdCrypto/XrdCryptosslTrace.hh>
00027 
00028 #include <openssl/pem.h>
00029 
00030 //_____________________________________________________________________________
00031 XrdCryptosslX509Req::XrdCryptosslX509Req(XrdSutBucket *buck) : XrdCryptoX509Req()
00032 {
00033    // Constructor certificate from BIO 'bcer'
00034    EPNAME("X509Req::XrdCryptosslX509Req_bio");
00035 
00036    // Init private members
00037    creq = 0;        // The certificate object
00038    subject = "";    // subject;
00039    subjecthash = ""; // hash of subject;
00040    bucket = 0;      // bucket for serialization
00041    pki = 0;         // PKI of the certificate
00042 
00043    // Make sure we got something;
00044    if (!buck) {
00045       DEBUG("got undefined opaque buffer");
00046       return;
00047    }
00048 
00049    //
00050    // Create a bio_mem to store the certificates
00051    BIO *bmem = BIO_new(BIO_s_mem());
00052    if (!bmem) {
00053       DEBUG("unable to create BIO for memory operations");
00054       return; 
00055    }
00056 
00057    // Write data to BIO
00058    int nw = BIO_write(bmem,(const void *)(buck->buffer),buck->size);
00059    if (nw != buck->size) {
00060       DEBUG("problems writing data to memory BIO (nw: "<<nw<<")");
00061       return; 
00062    }
00063 
00064    // Get certificate request from BIO
00065    if (!PEM_read_bio_X509_REQ(bmem,&creq,0,0)) {
00066       DEBUG("unable to read certificate request to memory BIO");
00067       return;
00068    }
00069    //
00070    // Free BIO
00071    BIO_free(bmem);
00072    //
00073    // Init some of the private members (the others upon need)
00074    Subject();
00075    //
00076    // Get the public key
00077    EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
00078    //
00079    if (evpp) {
00080       // init pki with the partial key
00081       if (!pki)
00082          pki = new XrdCryptosslRSA(evpp, 0);
00083    } else {
00084       DEBUG("could not access the public key");
00085    }
00086 }
00087 
00088 //_____________________________________________________________________________
00089 XrdCryptosslX509Req::XrdCryptosslX509Req(X509_REQ *xc) : XrdCryptoX509Req()
00090 {
00091    // Constructor: import X509_REQ object
00092    EPNAME("X509Req::XrdCryptosslX509Req_x509");
00093 
00094    // Init private members
00095    creq = 0;        // The certificate object
00096    subject = "";    // subject;
00097    subjecthash = ""; // hash of subject;
00098    bucket = 0;      // bucket for serialization
00099    pki = 0;         // PKI of the certificate
00100 
00101    // Make sure we got something;
00102    if (!xc) {
00103       DEBUG("got undefined X509 object");
00104       return;
00105    }
00106 
00107    // Set certificate
00108    creq = xc;
00109    //
00110    // Init some of the private members (the others upon need)
00111    Subject();
00112    //
00113    // Get the public key
00114    EVP_PKEY *evpp = X509_REQ_get_pubkey(creq);
00115    //
00116    if (evpp) {
00117       // init pki with the partial key
00118       if (!pki)
00119          pki = new XrdCryptosslRSA(evpp, 0);
00120    } else {
00121       DEBUG("could not access the public key");
00122    }
00123 }
00124 
00125 //_____________________________________________________________________________
00126 XrdCryptosslX509Req::~XrdCryptosslX509Req()
00127 {
00128    // Destructor
00129 
00130    // Cleanup certificate
00131    if (creq) X509_REQ_free(creq);
00132    // Cleanup key
00133    if (pki) delete pki;
00134 }
00135 
00136 //_____________________________________________________________________________
00137 const char *XrdCryptosslX509Req::Subject()
00138 {
00139    // Return subject name
00140    EPNAME("X509Req::Subject");
00141 
00142    // If we do not have it already, try extraction
00143    if (subject.length() <= 0) {
00144 
00145       // Make sure we have a certificate
00146       if (!creq) {
00147          DEBUG("WARNING: no certificate available - cannot extract subject name");
00148          return (const char *)0;
00149       }
00150       
00151       // Extract subject name
00152       subject = X509_NAME_oneline(X509_REQ_get_subject_name(creq), 0, 0);
00153    }
00154 
00155    // return what we have
00156    return (subject.length() > 0) ? subject.c_str() : (const char *)0;
00157 }
00158 
00159 //_____________________________________________________________________________
00160 const char *XrdCryptosslX509Req::SubjectHash()
00161 {
00162    // Return issuer name
00163    EPNAME("X509Req::SubjectHash");
00164 
00165    // If we do not have it already, try extraction
00166    if (subjecthash.length() <= 0) {
00167 
00168       // Make sure we have a certificate
00169       if (creq) {
00170          char chash[15];
00171 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00172          sprintf(chash,"%08lx.0",X509_NAME_hash_old(creq->req_info->subject));
00173 #else
00174          sprintf(chash,"%08lx.0",X509_NAME_hash(creq->req_info->subject));
00175 #endif
00176          subjecthash = chash;
00177       } else {
00178          DEBUG("WARNING: no certificate available - cannot extract subject hash");
00179       }
00180    }
00181 
00182    // return what we have
00183    return (subjecthash.length() > 0) ? subjecthash.c_str() : (const char *)0;
00184 }
00185 
00186 //_____________________________________________________________________________
00187 XrdCryptoX509Reqdata XrdCryptosslX509Req::GetExtension(const char *oid)
00188 {
00189    // Return issuer name
00190    EPNAME("X509Req::GetExtension");
00191    XrdCryptoX509Reqdata ext = 0;
00192 
00193    // Make sure we got something to look for
00194    if (!oid) {
00195       DEBUG("OID string not defined");
00196       return ext;
00197    }
00198  
00199    // Make sure we got something to look for
00200    if (!creq) {
00201       DEBUG("certificate is not initialized");
00202       return ext;
00203    }
00204 
00205    // Are there any extension?
00206    STACK_OF(X509_EXTENSION) *esk = X509_REQ_get_extensions(creq);
00207    //
00208 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00209    int numext = sk_X509_EXTENSION_num(esk);
00210 #else /* OPENSSL */
00211    int numext = sk_num(esk);
00212 #endif /* OPENSSL */
00213    if (numext <= 0) {
00214       DEBUG("certificate has got no extensions");
00215       return ext;
00216    }
00217    DEBUG("certificate request has "<<numext<<" extensions");
00218 
00219    // If the string is the Standard Name of a known extension check
00220    // searche the corresponding NID
00221    int nid = OBJ_sn2nid(oid);
00222    bool usenid = (nid > 0);
00223 
00224    // Loop to identify the one we would like
00225    int i = 0;
00226    X509_EXTENSION *wext = 0;
00227    for (i = 0; i< numext; i++) {
00228 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00229       wext = sk_X509_EXTENSION_value(esk, i);
00230 #else /* OPENSSL */
00231       wext = (X509_EXTENSION *)sk_value(esk, i);
00232 #endif /* OPENSSL */
00233       if (usenid) {
00234          int enid = OBJ_obj2nid(X509_EXTENSION_get_object(wext));
00235          if (enid == nid)
00236             break;
00237       } else {
00238          // Try matching of the text
00239          char s[256];
00240          OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(wext), 1);
00241          if (!strcmp(s, oid)) 
00242             break;
00243       }
00244       wext = 0;
00245    }
00246 
00247    // We are done if nothing was found
00248    if (!wext) {
00249       DEBUG("Extension "<<oid<<" not found"); 
00250       return ext;
00251    }
00252 
00253    // We are done
00254    return (XrdCryptoX509Reqdata)wext;
00255 }
00256 
00257 //_____________________________________________________________________________
00258 XrdSutBucket *XrdCryptosslX509Req::Export()
00259 {
00260    // Export in form of bucket
00261    EPNAME("X509Req::Export");
00262 
00263    // If we have already done it, return the previous result
00264    if (bucket) {
00265       DEBUG("serialization already performed:"
00266             " return previous result ("<<bucket->size<<" bytes)");
00267       return bucket;
00268    }
00269 
00270    // Make sure we got something to export
00271    if (!creq) {
00272       DEBUG("certificate is not initialized");
00273       return 0;
00274    }
00275 
00276    //
00277    // Now we create a bio_mem to serialize the certificate
00278    BIO *bmem = BIO_new(BIO_s_mem());
00279    if (!bmem) {
00280       DEBUG("unable to create BIO for memory operations");
00281       return 0;
00282    }
00283    
00284    // Write certificate to BIO
00285    if (!PEM_write_bio_X509_REQ(bmem, creq)) {
00286       DEBUG("unable to write certificate request to memory BIO");
00287       return 0;
00288    }
00289 
00290    // Extract pointer to BIO data and length of segment
00291    char *bdata = 0;  
00292    int blen = BIO_get_mem_data(bmem, &bdata);
00293    DEBUG("BIO data: "<<blen<<" bytes at 0x"<<(int *)bdata);
00294 
00295    // create the bucket now
00296    bucket = new XrdSutBucket(0,0,kXRS_x509_req);
00297    if (bucket) {
00298       // Fill bucket
00299       bucket->SetBuf(bdata, blen);
00300       DEBUG("result of serialization: "<<bucket->size<<" bytes");
00301    } else {
00302       DEBUG("unable to create bucket for serialized format");
00303       BIO_free(bmem);
00304       return 0;
00305    }
00306    //
00307    // Free BIO
00308    BIO_free(bmem);
00309    //
00310    // We are done
00311    return bucket;
00312 }
00313 
00314 //_____________________________________________________________________________
00315 bool XrdCryptosslX509Req::Verify()
00316 {
00317    // Verify signature of the request 
00318    EPNAME("X509Req::Verify");
00319 
00320    // We must have been initialized
00321    if (!creq)
00322       return 0;
00323 
00324    // Ok: we can verify
00325    int rc = X509_REQ_verify(creq,X509_REQ_get_pubkey(creq));
00326    if (rc <= 0) {
00327      // Failure
00328      if (rc == 0) {
00329        // Signatures are not OK
00330        DEBUG("signature not OK");
00331      } else {
00332        // General failure
00333        DEBUG("could not verify signature");
00334      }
00335      return 0;
00336    }
00337    // OK
00338    return 1;
00339 }

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