XrdCryptosslgsiAux.cc

Go to the documentation of this file.
00001 // $Id: XrdCryptosslgsiAux.cc 31508 2009-12-02 19:11:01Z brun $
00002 
00003 const char *XrdCryptosslgsiAuxCVSID = "$Id: XrdCryptosslgsiAux.cc 31508 2009-12-02 19:11:01Z brun $";
00004 /******************************************************************************/
00005 /*                                                                            */
00006 /*                  X r d C r y p t o s s l g s i A u x . h h                 */
00007 /*                                                                            */
00008 /* (c) 2005, G. Ganis / CERN                                                  */
00009 /*                                                                            */
00010 /******************************************************************************/
00011 
00012 /* ************************************************************************** */
00013 /*                                                                            */
00014 /* GSI utility functions                                                      */
00015 /*                                                                            */
00016 /* ************************************************************************** */
00017 #include <string.h>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 
00021 #include <openssl/asn1.h>
00022 #include <openssl/asn1_mac.h>
00023 #include <openssl/err.h>
00024 #include <openssl/evp.h>
00025 #include <openssl/pem.h>
00026 #include <openssl/rsa.h>
00027 #include <openssl/x509v3.h>
00028 
00029 #include <XrdSut/XrdSutRndm.hh>
00030 #include <XrdCrypto/XrdCryptosslgsiAux.hh>
00031 #include <XrdCrypto/XrdCryptoTrace.hh>
00032 #include <XrdCrypto/XrdCryptosslAux.hh>
00033 #include <XrdCrypto/XrdCryptosslRSA.hh>
00034 #include <XrdCrypto/XrdCryptosslX509.hh>
00035 #include <XrdCrypto/XrdCryptosslX509Req.hh>
00036 
00037 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
00038 //                                                                           //
00039 // Handlers of the ProxyCertInfo extension following RFC3820                 //
00040 //                                                                           //
00041 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
00042 
00043 //
00044 // Types describing the ProxyCertInfo extension
00045 typedef struct {
00046    ASN1_OBJECT       *policyLanguage;
00047    ASN1_OCTET_STRING *policy;
00048 } gsiProxyPolicy_t;
00049 //
00050 typedef struct {
00051    ASN1_INTEGER      *proxyCertPathLengthConstraint;
00052    gsiProxyPolicy_t  *proxyPolicy;
00053 } gsiProxyCertInfo_t;
00054 //
00055 // Some function ID codes as in asn1.h: the ASN1 macros require something
00056 // though not sure we really need them.
00057 // (not yet used above 299: keep some margin)
00058 #define ASN1_F_GSIPROXYCERTINFO_NEW     500
00059 #define ASN1_F_D2I_GSIPROXYCERTINFO     501
00060 #define ASN1_F_GSIPROXYPOLICY_NEW       510
00061 #define ASN1_F_D2I_GSIPROXYPOLICY       511
00062 
00063 // -------------------------------------------------------------------------
00064 //
00065 // Version of OBJ_txt2obj with a bug fix introduced starting
00066 // with some 0.9.6 versions
00067 static ASN1_OBJECT *OBJ_txt2obj_fix(const char *s, int no_name)
00068         {
00069         int nid = NID_undef;
00070         ASN1_OBJECT *op=NULL;
00071         unsigned char *buf,*p;
00072         int i, j;
00073 
00074         if(!no_name) {
00075                 if( ((nid = OBJ_sn2nid(s)) != NID_undef) ||
00076                         ((nid = OBJ_ln2nid(s)) != NID_undef) ) 
00077                                         return OBJ_nid2obj(nid);
00078         }
00079 
00080         /* Work out size of content octets */
00081         i=a2d_ASN1_OBJECT(NULL,0,s,-1);
00082         if (i <= 0) {
00083                 /* Clear the error */
00084                 ERR_get_error();
00085                 return NULL;
00086         }
00087         /* Work out total size */
00088         j = ASN1_object_size(0,i,V_ASN1_OBJECT);
00089 
00090         if((buf=(unsigned char *)OPENSSL_malloc(j)) == NULL) return NULL;
00091 
00092         p = buf;
00093         /* Write out tag+length */
00094         ASN1_put_object(&p,0,i,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
00095         /* Write out contents */
00096         a2d_ASN1_OBJECT(p,i,s,-1);
00097         
00098         p=buf;
00099 #ifdef R__SSL_GE_098
00100         // not op=d2i_ASN1_OBJECT(0, &p, i) (C.H. Christensen, Oct 12, 2005)
00101         op = d2i_ASN1_OBJECT(0, const_cast<const unsigned char**>(&p), j);
00102 #else
00103         op=d2i_ASN1_OBJECT(0, &p, i);
00104 #endif
00105         OPENSSL_free(buf);
00106         return op;
00107         }
00108 // -------------------------------------------------------------------------
00109 
00110 //
00111 // Functions to create and destroy a gsiProxyPolicy_t
00112 // (NB: the names of the internal variables a fixed by the ASN1 macros)
00113 //
00114 //___________________________________________________________________________
00115 gsiProxyPolicy_t *gsiProxyPolicy_new()
00116 {
00117    // Create a new gsiProxyPolicy_t object
00118    ASN1_CTX          c;
00119    gsiProxyPolicy_t *ret;
00120 
00121    // Init object
00122    ret = 0;
00123    M_ASN1_New_Malloc(ret, gsiProxyPolicy_t);
00124    // Fill default policy
00125    ret->policyLanguage = OBJ_txt2obj_fix("1.3.6.1.5.5.7.21.1", 1);
00126    ret->policy = 0;
00127    // Return ok
00128    return (ret);
00129    // Error: flag it 
00130    M_ASN1_New_Error(ASN1_F_GSIPROXYPOLICY_NEW);
00131 }
00132 
00133 //___________________________________________________________________________
00134 void gsiProxyPolicy_free(gsiProxyPolicy_t *pol)
00135 {
00136    // Free a gsiProxyPolicy_t object
00137 
00138    // Make sure there is something to free
00139    if (!pol)
00140       return;
00141    //
00142    // Free language object
00143    if (pol->policyLanguage)
00144       ASN1_OBJECT_free(pol->policyLanguage);
00145    //
00146    // Free policy octet string
00147    if (pol->policy)
00148       M_ASN1_OCTET_STRING_free(pol->policy);
00149    //
00150    // Free the container
00151    OPENSSL_free(pol);
00152 }
00153 
00154 //
00155 // This function allows to convert the internal representation to a 
00156 // gsiProxyPolicy_t object. We need this for correct parsing of a
00157 // ProxyCertInfo object, even if we are not presently interested
00158 // in the policy.
00159 //___________________________________________________________________________
00160 #ifdef R__SSL_GE_098
00161 gsiProxyPolicy_t *d2i_gsiProxyPolicy(gsiProxyPolicy_t **pol,
00162                                      const unsigned char **pp, long length)
00163 #else
00164 gsiProxyPolicy_t *d2i_gsiProxyPolicy(gsiProxyPolicy_t **pol,
00165                                      unsigned char **pp, long length)
00166 #endif
00167 {
00168    // Get the policy object from buffer at pp, of length bytes.
00169 
00170    // Define vars
00171    M_ASN1_D2I_vars(pol, gsiProxyPolicy_t *, gsiProxyPolicy_new);
00172    //
00173    // Init sequence
00174    M_ASN1_D2I_Init();
00175    M_ASN1_D2I_start_sequence();
00176    //
00177    // Retrieve language
00178    M_ASN1_D2I_get(ret->policyLanguage, d2i_ASN1_OBJECT);
00179    //
00180    // Retrieve content
00181    M_ASN1_D2I_get_IMP_opt(ret->policy, d2i_ASN1_OCTET_STRING,
00182                                      0, V_ASN1_OCTET_STRING);
00183    //
00184    // Finalize
00185    M_ASN1_D2I_Finish(pol, gsiProxyPolicy_free, ASN1_F_D2I_GSIPROXYPOLICY);
00186 }
00187 
00188 //
00189 // This function allows to convert a gsiProxyPolicy_t object to 
00190 // internal representation. We need this for correct updating of
00191 // the path length in a ProxyCertInfo object, even if we are not
00192 // presently interested in the policy.
00193 //___________________________________________________________________________
00194 int i2d_gsiProxyPolicy(gsiProxyPolicy_t *pol, unsigned char **pp)
00195 {
00196    // Set the policy object from pol to buffer at pp.
00197    // Return number of meningful bytes 
00198 
00199    // Define vars
00200    M_ASN1_I2D_vars(pol);
00201    //
00202    // Set language length
00203    M_ASN1_I2D_len(pol->policyLanguage, i2d_ASN1_OBJECT);
00204    //
00205    // Set content length
00206    if (pol->policy) {
00207       M_ASN1_I2D_len(pol->policy, i2d_ASN1_OCTET_STRING);
00208    }
00209    //
00210    // Sequence
00211    M_ASN1_I2D_seq_total();
00212    //
00213    // Set language
00214    M_ASN1_I2D_put(pol->policyLanguage, i2d_ASN1_OBJECT);
00215    //
00216    // Set content
00217    if (pol->policy) {
00218       M_ASN1_I2D_put(pol->policy, i2d_ASN1_OCTET_STRING);
00219    }
00220    //
00221    // Finalize
00222    M_ASN1_I2D_finish();
00223 }
00224 //
00225 // Functions to create and destroy a gsiProxyCertInfo_t
00226 //
00227 //___________________________________________________________________________
00228 gsiProxyCertInfo_t *gsiProxyCertInfo_new()
00229 {
00230    // Create a new gsiProxyCertInfo_t object
00231    ASN1_CTX            c;
00232    gsiProxyCertInfo_t *ret;
00233    //
00234    // Init object
00235    ret = 0;
00236    M_ASN1_New_Malloc(ret, gsiProxyCertInfo_t);
00237    memset(ret, 0, sizeof(gsiProxyCertInfo_t));
00238    //
00239    // Default values
00240    ret->proxyCertPathLengthConstraint = 0;
00241    ret->proxyPolicy = gsiProxyPolicy_new();
00242    //
00243    // Return OK
00244    return (ret);
00245    //
00246    // Error: flag it
00247    M_ASN1_New_Error(ASN1_F_GSIPROXYCERTINFO_NEW);
00248 }
00249 
00250 //___________________________________________________________________________
00251 void gsiProxyCertInfo_free(gsiProxyCertInfo_t *pci)
00252 {
00253    // Free a gsiProxyPolicy_t object
00254 
00255    // Make sure there is something to free
00256    if (!pci)
00257       return;
00258    // Free path len constraint object
00259    if (pci->proxyCertPathLengthConstraint)
00260       ASN1_INTEGER_free(pci->proxyCertPathLengthConstraint);
00261    // Free the container
00262    OPENSSL_free(pci);
00263 }
00264 
00265 //
00266 // This function allow to convert the internal representation to a 
00267 // gsiProxyCertInfo_t object.
00268 //___________________________________________________________________________
00269 #ifdef R__SSL_GE_098
00270 gsiProxyCertInfo_t *d2i_gsiProxyCertInfo(gsiProxyCertInfo_t **pci,
00271                                          const unsigned char **pp, long length)
00272 #else
00273 gsiProxyCertInfo_t *d2i_gsiProxyCertInfo(gsiProxyCertInfo_t **pci,
00274                                          unsigned char **pp, long length)
00275 #endif
00276 {
00277    // Get the proxy certificate info object from length bytes at pp.
00278 
00279    // Define vars
00280    M_ASN1_D2I_vars(pci, gsiProxyCertInfo_t *, gsiProxyCertInfo_new);
00281    //
00282    // Init sequence
00283    M_ASN1_D2I_Init();
00284    M_ASN1_D2I_start_sequence();
00285    //
00286    // Retrieve the policy (wee need to do this to avoid screwing
00287    // up the sequence pointers)
00288    M_ASN1_D2I_get(ret->proxyPolicy, d2i_gsiProxyPolicy);
00289    //
00290    // Retrieve the path length constraint
00291    M_ASN1_D2I_get_EXP_opt(ret->proxyCertPathLengthConstraint, d2i_ASN1_INTEGER, 1);
00292    M_ASN1_D2I_get_opt(ret->proxyCertPathLengthConstraint, d2i_ASN1_INTEGER,
00293                                                           V_ASN1_INTEGER);
00294    //
00295    // Finalize
00296    M_ASN1_D2I_Finish(pci, gsiProxyCertInfo_free, ASN1_F_D2I_GSIPROXYCERTINFO);
00297 }
00298 //
00299 // This function allows to convert a gsiProxyCertInfo_t object to 
00300 // internal representation.
00301 //___________________________________________________________________________
00302 int i2d_gsiProxyCertInfo(gsiProxyCertInfo_t *pci, unsigned char **pp)
00303 {
00304    // Set the proxy certificate info object from pol to buffer at pp.
00305    // Return number of meningful bytes 
00306    int v1 = 0;
00307 
00308    // Define vars
00309    M_ASN1_I2D_vars(pci);
00310    v1 = 0;
00311    //
00312    // Set length of proxyPolicy
00313    M_ASN1_I2D_len(pci->proxyPolicy, i2d_gsiProxyPolicy);
00314    //
00315    // Set len of the path length constraint field
00316    if (pci->proxyCertPathLengthConstraint) {
00317       M_ASN1_I2D_len_EXP_opt(pci->proxyCertPathLengthConstraint,      
00318                              i2d_ASN1_INTEGER, 1, v1);
00319    }
00320    //
00321    // Sequence
00322    M_ASN1_I2D_seq_total();
00323    //
00324    // Set policy
00325    M_ASN1_I2D_put(pci->proxyPolicy, i2d_gsiProxyPolicy);
00326    //
00327    // Set path length constraint
00328    if (pci->proxyCertPathLengthConstraint) {
00329       M_ASN1_I2D_put_EXP_opt(pci->proxyCertPathLengthConstraint, i2d_ASN1_INTEGER, 1, v1);
00330    }
00331    //
00332    // Finalize
00333    M_ASN1_I2D_finish();
00334 }
00335 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
00336 
00337 //___________________________________________________________________________
00338 bool XrdSslgsiProxyCertInfo(const void *extdata, int &pathlen, bool *haspolicy)
00339 {
00340    //
00341    // Check presence of a proxyCertInfo and retrieve the path length constraint.
00342    // Written following RFC3820, examples in openssl-<vers>/crypto source code.
00343    // in gridsite code and Globus proxycertinfo.h / .c.
00344    // if 'haspolicy' is defined, the existence of a policy field is checked;
00345    // the content ignored for the time being.
00346 
00347    // Make sure we got an extension
00348    if (!extdata) {
00349       return 0;
00350    }
00351    // Structure the buffer
00352    X509_EXTENSION *ext = (X509_EXTENSION *)extdata;
00353 
00354    // Check ProxyCertInfo OID
00355    char s[80] = {0};
00356    OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ext), 1);
00357    if (strcmp(s, gsiProxyCertInfo_OID)) {
00358       return 0;
00359    }
00360 
00361    // Now extract the path length constraint, if any
00362    unsigned char *p = ext->value->data;
00363 #ifdef R__SSL_GE_098
00364    gsiProxyCertInfo_t *pci =
00365       d2i_gsiProxyCertInfo(0, (const unsigned char **)(&p), ext->value->length);
00366 #else
00367    gsiProxyCertInfo_t *pci = d2i_gsiProxyCertInfo(0, &p, ext->value->length);
00368 #endif
00369    if (!pci) {
00370       return 0;
00371    }
00372 
00373    // Default length is -1, i.e. check disabled
00374    pathlen = -1;
00375    if (pci->proxyCertPathLengthConstraint) {
00376       pathlen = ASN1_INTEGER_get(pci->proxyCertPathLengthConstraint);
00377    }
00378 
00379    // If required, check te existence of a policy field
00380    if (haspolicy) {
00381       *haspolicy = (pci->proxyPolicy) ? 1 : 0;
00382    }
00383 
00384    // We are done
00385    return 1;
00386 }
00387 
00388 //___________________________________________________________________________
00389 void XrdSslgsiSetPathLenConstraint(void *extdata, int pathlen)
00390 {
00391    //
00392    // Set the patch length constraint valur in proxyCertInfo extension ext
00393    // to 'pathlen'.
00394 
00395    // Make sure we got an extension
00396    if (!extdata)
00397       return;
00398    // Structure the buffer
00399    X509_EXTENSION *ext = (X509_EXTENSION *)extdata;
00400 
00401    // Check ProxyCertInfo OID
00402    char s[80] = {0};
00403    OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(ext), 1);
00404    if (strcmp(s, gsiProxyCertInfo_OID))
00405       return;
00406 
00407    // Now extract the path length constraint, if any
00408    unsigned char *p = ext->value->data;
00409 #ifdef R__SSL_GE_098
00410    gsiProxyCertInfo_t *pci =
00411       d2i_gsiProxyCertInfo(0, (const unsigned char **)(&p), ext->value->length);
00412 #else
00413    gsiProxyCertInfo_t *pci = d2i_gsiProxyCertInfo(0, &p, ext->value->length);
00414 #endif
00415    if (!pci)
00416       return;
00417 
00418    // Set the new length
00419    if (pci->proxyCertPathLengthConstraint) {
00420       ASN1_INTEGER_set(pci->proxyCertPathLengthConstraint, pathlen);
00421    }
00422 
00423    // We are done
00424    return;
00425 }
00426 
00427 //____________________________________________________________________________
00428 int XrdSslgsiX509CreateProxy(const char *fnc, const char *fnk, 
00429                              XrdProxyOpt_t *pxopt,
00430                              XrdCryptosslgsiX509Chain *xp, XrdCryptoRSA **kp,
00431                              const char *fnp)
00432 {
00433    // Create a proxy certificate following the GSI specification (RFC 3820)
00434    // for the EEC certificate in file 'fnc', private key in 'fnk'.
00435    // A chain containing the proxy certificate and the EEC is returned in 'xp'
00436    // and its full RSA key in 'kp'.
00437    // The structure pxopt can be used to change the default options about
00438    // number of bits for teh key, duration validity and max path signature depth.
00439    // If 'fpn' is defined, a PEM file is created with, in order, the proxy
00440    // certificate, the related private key and the EEC certificate (standard
00441    // GSI format).
00442    // Policy fields in the CertProxyExtension not yet included.
00443    // Return 0 in case of success, < 0 otherwise
00444    EPNAME("X509CreateProxy");
00445 
00446    // Make sure the files are specified
00447    if (!fnc || !fnk || !xp || !kp) {
00448       PRINT("invalid inputs ");
00449       return -1;
00450    }
00451 
00452    //
00453    // Init OpenSSL
00454    OpenSSL_add_all_ciphers();
00455    OpenSSL_add_all_digests();
00456    ERR_load_crypto_strings();
00457 
00458    // Use default options, if not specified
00459    int bits = (pxopt && pxopt->bits >= 512) ? pxopt->bits : 512;
00460    int valid = (pxopt) ? pxopt->valid : 43200;  // 12 hours
00461    int depthlen = (pxopt) ? pxopt->depthlen : -1; // unlimited
00462 
00463    //
00464    // Get EEC certificate from fnc
00465    X509 *xEEC = 0;
00466    FILE *fc = fopen(fnc, "r");
00467    if (fc) {
00468       // Read out the certificate
00469       if (PEM_read_X509(fc, &xEEC, 0, 0)) {
00470          DEBUG("EEC certificate loaded from file: "<<fnc);
00471       } else {
00472          PRINT("unable to load EEC certificate from file: "<<fnc);
00473          fclose(fc);
00474          return -kErrPX_BadEECfile;
00475       }
00476    } else {
00477       PRINT("EEC certificate cannot be opened (file: "<<fnc<<")"); 
00478       return -kErrPX_BadEECfile;
00479    }
00480    fclose(fc);
00481    // Make sure the certificate is not expired
00482    int now = (int)time(0);
00483    if (now > XrdCryptosslASN1toUTC(X509_get_notAfter(xEEC))) {
00484       PRINT("EEC certificate has expired"); 
00485       return -kErrPX_ExpiredEEC;
00486    }
00487 
00488    //
00489    // Get EEC private key from fnk
00490    EVP_PKEY *ekEEC;
00491    FILE *fk = fopen(fnk, "r");
00492    if (fk) {
00493       // Read out the private key
00494       ekEEC = X509_get_pubkey(xEEC);
00495       PRINT("Your identity: "<<X509_NAME_oneline(X509_get_subject_name(xEEC),0,0));
00496       if (PEM_read_PrivateKey(fk, &ekEEC, 0, 0)) {
00497          DEBUG("EEC private key loaded from file: "<<fnk);
00498       } else {
00499          PRINT("unable to load EEC private key from file: "<<fnk);
00500          fclose(fk);
00501          return -kErrPX_BadEECfile;
00502       }
00503    } else {
00504       PRINT("EEC private key file cannot be opened (file: "<<fnk<<")"); 
00505       return -kErrPX_BadEECfile;
00506    }
00507    fclose(fk);
00508    // Check key consistency
00509    if (RSA_check_key(ekEEC->pkey.rsa) == 0) {
00510       PRINT("inconsistent key loaded");
00511       return -kErrPX_BadEECkey;
00512    }
00513    //
00514    // Create a new request
00515    X509_REQ *preq = X509_REQ_new();
00516    if (!preq) {
00517       PRINT("cannot to create cert request");
00518       return -kErrPX_NoResources;
00519    }
00520    //
00521    // Create the new PKI for the proxy (exponent 65537)
00522    RSA *kPX = RSA_generate_key(bits, 0x10001, 0, 0);
00523    if (!kPX) {
00524       PRINT("proxy key could not be generated - return"); 
00525       return -kErrPX_GenerateKey;
00526    }
00527    //
00528    // Set the key into the request
00529    EVP_PKEY *ekPX = EVP_PKEY_new();
00530    if (!ekPX) {
00531       PRINT("could not create a EVP_PKEY * instance - return"); 
00532       return -kErrPX_NoResources;
00533    }
00534    EVP_PKEY_set1_RSA(ekPX, kPX);
00535    X509_REQ_set_pubkey(preq, ekPX);
00536    // 
00537    // Generate a serial number. Specification says that this *should*
00538    // unique, so we just draw an unsigned random integer
00539    unsigned int serial = XrdSutRndm::GetUInt();
00540    //
00541    // The subject name is the certificate subject + /CN=<rand_uint>
00542    // with <rand_uint> is a random unsigned int used also as serial
00543    // number.
00544    // Duplicate user subject name
00545    X509_NAME *psubj = X509_NAME_dup(X509_get_subject_name(xEEC)); 
00546    // Create an entry with the common name
00547    unsigned char sn[20] = {0};
00548    sprintf((char *)sn, "%d", serial);
00549    if (!X509_NAME_add_entry_by_txt(psubj, (char *)"CN", MBSTRING_ASC,
00550                                    sn, -1, -1, 0)) {
00551       PRINT("could not add CN - (serial: "<<serial<<", sn: "<<sn<<")"); 
00552       return -kErrPX_SetAttribute;
00553    }
00554    //
00555    // Set the name
00556    if (X509_REQ_set_subject_name(preq, psubj) != 1) {
00557       PRINT("could not set subject name - return"); 
00558       return -kErrPX_SetAttribute;
00559    }
00560    //
00561    // Create the extension CertProxyInfo
00562    gsiProxyCertInfo_t *pci = gsiProxyCertInfo_new();
00563    if (!pci) {
00564       PRINT("could not create structure for extension - return"); 
00565       return -kErrPX_NoResources;
00566    }
00567    // Set the new length
00568    if (depthlen > -1) {
00569       if ((pci->proxyCertPathLengthConstraint = ASN1_INTEGER_new())) {
00570          ASN1_INTEGER_set(pci->proxyCertPathLengthConstraint, depthlen);
00571       } else {
00572          PRINT("could not set the path length contrain"); 
00573          return -kErrPX_SetPathDepth;
00574       }
00575    }
00576    //
00577    // create extension
00578    X509_EXTENSION *ext = X509_EXTENSION_new();
00579    if (!ext) {
00580       PRINT("could not create extension object"); 
00581       return -kErrPX_NoResources;
00582    }
00583    // Set extension name.
00584 #ifndef R__SSL_096
00585    // We do not use directly OBJ_txt2obj because that is not working
00586    // with all OpenSSL 0.9.6 versions
00587    ASN1_OBJECT *obj = OBJ_nid2obj(OBJ_create(gsiProxyCertInfo_OID,
00588                             "gsiProxyCertInfo_OID","GSI ProxyCertInfo OID"));
00589 #else
00590    // This version of OBJ_txt2obj fixes a bug affecting some 
00591    // OpenSSL 0.9.6 versions
00592    ASN1_OBJECT *obj = OBJ_txt2obj_fix(gsiProxyCertInfo_OID, 1);
00593 #endif
00594    if (!obj || X509_EXTENSION_set_object(ext, obj) != 1) {
00595       PRINT("could not set extension name"); 
00596       return -kErrPX_SetAttribute;
00597    }
00598    // flag as critical
00599    if (X509_EXTENSION_set_critical(ext, 1) != 1) {
00600       PRINT("could not set extension critical flag"); 
00601       return -kErrPX_SetAttribute;
00602    }
00603    // Extract data in format for extension
00604    ext->value->length = i2d_gsiProxyCertInfo(pci, 0);
00605    if (!(ext->value->data = (unsigned char *)malloc(ext->value->length+1))) {
00606       PRINT("could not allocate data field for extension"); 
00607       return -kErrPX_NoResources;
00608    }
00609    unsigned char *pp = ext->value->data;
00610    if ((i2d_gsiProxyCertInfo(pci, &pp)) <= 0) {
00611       PRINT("problem converting data for extension"); 
00612       return -kErrPX_Error;
00613    }
00614    // Create a stack
00615    STACK_OF(X509_EXTENSION) *esk = sk_X509_EXTENSION_new_null();
00616    if (!esk) {
00617       PRINT("could not create stack for extensions"); 
00618       return -kErrPX_NoResources;
00619    }
00620    if (sk_X509_EXTENSION_push(esk, ext) != 1) {
00621       PRINT("could not push the extension in the stack"); 
00622       return -kErrPX_Error;
00623    }
00624    // Add extension
00625    if (!(X509_REQ_add_extensions(preq, esk))) {
00626       PRINT("problem adding extension"); 
00627       return -kErrPX_SetAttribute;
00628    }
00629    //
00630    // Sign the request
00631    if (!(X509_REQ_sign(preq, ekPX, EVP_md5()))) {
00632       PRINT("problems signing the request"); 
00633       return -kErrPX_Signing;
00634    }
00635    //
00636    // Create new proxy cert
00637    X509 *xPX = X509_new();
00638    if (!xPX) {
00639       PRINT("could not create certificate object for proxies"); 
00640       return -kErrPX_NoResources;
00641    }
00642 
00643    // Set version number
00644    if (X509_set_version(xPX, 2L) != 1) {
00645       PRINT("could not set version"); 
00646       return -kErrPX_SetAttribute;
00647    }
00648 
00649    // Set serial number
00650    if (ASN1_INTEGER_set(X509_get_serialNumber(xPX), serial) != 1) {
00651       PRINT("could not set serial number"); 
00652       return -kErrPX_SetAttribute;
00653    }
00654 
00655    // Set subject name
00656    if (X509_set_subject_name(xPX, psubj) != 1) {
00657       PRINT("could not set subject name"); 
00658       return -kErrPX_SetAttribute;
00659    }
00660    
00661    // Set issuer name
00662    if (X509_set_issuer_name(xPX, X509_get_subject_name(xEEC)) != 1) {
00663       PRINT("could not set issuer name"); 
00664       return -kErrPX_SetAttribute;
00665    }
00666 
00667    // Set public key
00668    if (X509_set_pubkey(xPX, ekPX) != 1) {
00669       PRINT("could not set issuer name"); 
00670       return -kErrPX_SetAttribute;
00671    }
00672 
00673    // Set proxy validity: notBefore now
00674    if (!X509_gmtime_adj(X509_get_notBefore(xPX), 0)) {
00675       PRINT("could not set notBefore"); 
00676       return -kErrPX_SetAttribute;
00677    }
00678 
00679    // Set proxy validity: notAfter expire_secs from now
00680    if (!X509_gmtime_adj(X509_get_notAfter(xPX), valid)) {
00681       PRINT("could not set notAfter"); 
00682       return -kErrPX_SetAttribute;
00683    }
00684 
00685    // Add the extension
00686    if (X509_add_ext(xPX, ext, -1) != 1) {
00687       PRINT("could not add extension"); 
00688       return -kErrPX_SetAttribute;
00689    }
00690 
00691    //
00692    // Sign the certificate
00693    if (!(X509_sign(xPX, ekEEC, EVP_md5()))) {
00694       PRINT("problems signing the certificate"); 
00695       return -kErrPX_Signing;
00696    }
00697 
00698    // Fill outputs
00699    XrdCryptoX509 *xcPX = new XrdCryptosslX509(xPX);
00700    if (!xcPX) {
00701       PRINT("could not create container for proxy certificate"); 
00702       return -kErrPX_NoResources;
00703    }
00704    // We need the full key
00705    ((XrdCryptosslX509 *)xcPX)->SetPKI((XrdCryptoX509data)ekPX);
00706    xp->PushBack(xcPX);
00707    XrdCryptoX509 *xcEEC = new XrdCryptosslX509(xEEC);
00708    if (!xcEEC) {
00709       PRINT("could not create container for EEC certificate"); 
00710       return -kErrPX_NoResources;
00711    }
00712    xp->PushBack(xcEEC);
00713    *kp = new XrdCryptosslRSA(ekPX);
00714    if (!(*kp)) {
00715       PRINT("could not creatr out PKI"); 
00716       return -kErrPX_NoResources;
00717    }
00718    
00719    //
00720    // Write to a file if requested
00721    int rc = 0;
00722    if (fnp) {
00723       // Open the file in write mode
00724       FILE *fp = fopen(fnp,"w");
00725       if (!fp) {
00726          PRINT("cannot open file to save the proxy certificate (file: "<<fnp<<")"); 
00727          fclose(fp);
00728          rc = -kErrPX_ProxyFile;
00729       }
00730       int ifp = fileno(fp);
00731       if (ifp == -1) {
00732          PRINT("got invalid file descriptor for the proxy certificate (file: "<<
00733                 fnp<<")"); 
00734          fclose(fp);
00735          rc = -kErrPX_ProxyFile;
00736       }
00737       // Set permissions to 0600
00738       if (fchmod(ifp, 0600) == -1) {
00739          PRINT("cannot set permissions on file: "<<fnp<<" (errno: "<<errno<<")"); 
00740          fclose(fp);
00741          rc = -kErrPX_ProxyFile;
00742       } 
00743 
00744       if (!rc && PEM_write_X509(fp, xPX) != 1) {
00745          PRINT("error while writing proxy certificate"); 
00746          fclose(fp);
00747          rc = -kErrPX_ProxyFile;
00748       }   
00749       if (!rc && PEM_write_RSAPrivateKey(fp, kPX, 0, 0, 0, 0, 0) != 1) {
00750          PRINT("error while writing proxy private key"); 
00751          fclose(fp);
00752          rc = -kErrPX_ProxyFile;
00753       }   
00754       if (!rc && PEM_write_X509(fp, xEEC) != 1) {
00755          PRINT("error while writing EEC certificate"); 
00756          fclose(fp);
00757          rc = -kErrPX_ProxyFile;
00758       }   
00759       fclose(fp);
00760       // Change
00761    }
00762 
00763    // Cleanup
00764    EVP_PKEY_free(ekEEC);
00765    X509_REQ_free(preq);
00766 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00767    sk_X509_EXTENSION_free(esk);
00768 #else /* OPENSSL */
00769    sk_free(esk);
00770 #endif /* OPENSSL */
00771 
00772    // We are done
00773    return rc;
00774 }
00775 
00776 //____________________________________________________________________________
00777 int XrdSslgsiX509CreateProxyReq(XrdCryptoX509 *xcpi,
00778                                 XrdCryptoX509Req **xcro, XrdCryptoRSA **kcro)
00779 {
00780    // Create a proxy certificate request following the GSI specification
00781    // (RFC 3820) for the proxy certificate 'xpi'.
00782    // The proxy certificate is returned in 'xpo' and its full RSA key in 'kpo'.
00783    // Policy fields in the CertProxyExtension not yet included.
00784    // Return 0 in case of success, < 0 otherwise
00785    EPNAME("X509CreateProxyReq");
00786 
00787    // Make sure we got an proxy certificate as input 
00788    if (!xcpi || !(xcpi->Opaque())) {
00789       PRINT("input proxy certificate not specified");
00790       return -1;
00791    }
00792 
00793    // Point to the cerificate
00794    X509 *xpi = (X509 *)(xcpi->Opaque());
00795 
00796    // Make sure the certificate is not expired
00797    if (!(xcpi->IsValid())) {
00798       PRINT("EEC certificate has expired"); 
00799       return -kErrPX_ExpiredEEC;
00800    }
00801    //
00802    // Create a new request
00803    X509_REQ *xro = X509_REQ_new();
00804    if (!xro) {
00805       PRINT("cannot to create cert request");
00806       return -kErrPX_NoResources;
00807    }
00808    //
00809    // Use same num of bits as the signing certificate, but
00810    // less than 512
00811    int bits = EVP_PKEY_bits(X509_get_pubkey(xpi));
00812    bits = (bits < 512) ? 512 : bits;
00813    //
00814    // Create the new PKI for the proxy (exponent 65537)
00815    RSA *kro = RSA_generate_key(bits, 0x10001, 0, 0);
00816    if (!kro) {
00817       PRINT("proxy key could not be generated - return"); 
00818       return -kErrPX_GenerateKey;
00819    }
00820    //
00821    // Set the key into the request
00822    EVP_PKEY *ekro = EVP_PKEY_new();
00823    if (!ekro) {
00824       PRINT("could not create a EVP_PKEY * instance - return"); 
00825       return -kErrPX_NoResources;
00826    }
00827    EVP_PKEY_set1_RSA(ekro, kro);
00828    X509_REQ_set_pubkey(xro, ekro);
00829    // 
00830    // Generate a serial number. Specification says that this *should*
00831    // unique, so we just draw an unsigned random integer
00832    unsigned int serial = XrdSutRndm::GetUInt();
00833    //
00834    // The subject name is the certificate subject + /CN=<rand_uint>
00835    // with <rand_uint> is a random unsigned int used also as serial
00836    // number.
00837    // Duplicate user subject name
00838    X509_NAME *psubj = X509_NAME_dup(X509_get_subject_name(xpi)); 
00839    if (xcro && *xcro && *((int *)(*xcro)) <= 10100) {
00840       // Delete existing proxy CN addition; for backward compatibility
00841 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00842       int ne = sk_X509_NAME_ENTRY_num(psubj->entries);
00843 #else /* OPENSSL */
00844       int ne = psubj->entries->num;
00845 #endif /* OPENSSL */
00846       if (ne >= 0) {
00847          X509_NAME_ENTRY *cne = X509_NAME_delete_entry(psubj, ne-1);
00848          if (cne) {
00849             X509_NAME_ENTRY_free(cne);
00850          } else {
00851             DEBUG("problems modifying subject name");
00852          }
00853       }
00854       *xcro = 0;
00855    }
00856    // Create an entry with the common name
00857    unsigned char sn[20] = {0};
00858    sprintf((char *)sn, "%d", serial);
00859    if (!X509_NAME_add_entry_by_txt(psubj, (char *)"CN", MBSTRING_ASC,
00860                                    sn, -1, -1, 0)) {
00861       PRINT("could not add CN - (serial: "<<serial<<", sn: "<<sn<<")"); 
00862       return -kErrPX_SetAttribute;
00863    }
00864    //
00865    // Set the name
00866    if (X509_REQ_set_subject_name(xro, psubj) != 1) {
00867       PRINT("could not set subject name - return"); 
00868       return -kErrPX_SetAttribute;
00869    }
00870    //
00871    // Create the extension CertProxyInfo
00872    gsiProxyCertInfo_t *pci = gsiProxyCertInfo_new();
00873    if (!pci) {
00874       PRINT("could not create structure for extension - return"); 
00875       return -kErrPX_NoResources;
00876    }
00877    //
00878    // Get signature path depth from present proxy
00879    X509_EXTENSION *xpiext = 0;
00880    int npiext = X509_get_ext_count(xpi);
00881    int i = 0;
00882    int indepthlen = -1;
00883    for (i = 0; i< npiext; i++) {
00884       xpiext = X509_get_ext(xpi, i);
00885       char s[256];
00886       OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(xpiext), 1);
00887       if (!strcmp(s, gsiProxyCertInfo_OID)) {
00888          unsigned char *p = xpiext->value->data;
00889 #ifdef R__SSL_GE_098
00890          gsiProxyCertInfo_t *inpci =
00891             d2i_gsiProxyCertInfo(0, (const unsigned char **)(&p), xpiext->value->length);
00892 #else
00893          gsiProxyCertInfo_t *inpci = d2i_gsiProxyCertInfo(0, &p, xpiext->value->length);
00894 #endif
00895          if (inpci && 
00896              inpci->proxyCertPathLengthConstraint)
00897             indepthlen = ASN1_INTEGER_get(inpci->proxyCertPathLengthConstraint);
00898          DEBUG("IN depth length: "<<indepthlen);
00899       }
00900       // Do not free the extension: its owned by the certificate
00901       xpiext = 0;
00902    }
00903 
00904    // Set the new length
00905    if (indepthlen > -1) {
00906       if ((pci->proxyCertPathLengthConstraint = ASN1_INTEGER_new())) {
00907          int depthlen = (indepthlen > 0) ? (indepthlen-1) : 0;
00908          ASN1_INTEGER_set(pci->proxyCertPathLengthConstraint, depthlen);
00909       } else {
00910          PRINT("could not set the path length contrain"); 
00911          return -kErrPX_SetPathDepth;
00912       }
00913    }
00914    //
00915    // create extension
00916    X509_EXTENSION *ext = X509_EXTENSION_new();
00917    if (!ext) {
00918       PRINT("could not create extension object"); 
00919       return -kErrPX_NoResources;
00920    }
00921    // Extract data in format for extension
00922    ext->value->length = i2d_gsiProxyCertInfo(pci, 0);
00923    if (!(ext->value->data = (unsigned char *)malloc(ext->value->length+1))) {
00924       PRINT("could not allocate data field for extension"); 
00925       return -kErrPX_NoResources;
00926    }
00927    unsigned char *pp = ext->value->data;
00928    if ((i2d_gsiProxyCertInfo(pci, &pp)) <= 0) {
00929       PRINT("problem converting data for extension"); 
00930       return -kErrPX_Error;
00931    }
00932    // Set extension name.
00933 #ifndef R__SSL_096
00934    // We do not use directly OBJ_txt2obj because that is not working
00935    // with all OpenSSL 0.9.6 versions
00936    ASN1_OBJECT *obj = OBJ_nid2obj(OBJ_create(gsiProxyCertInfo_OID,
00937                             "gsiProxyCertInfo_OID","GSI ProxyCertInfo OID"));
00938 #else
00939    // This version of OBJ_txt2obj fixes a bug affecting some 
00940    // OpenSSL 0.9.6 versions
00941    ASN1_OBJECT *obj = OBJ_txt2obj_fix(gsiProxyCertInfo_OID, 1);
00942 #endif
00943    if (!obj || X509_EXTENSION_set_object(ext, obj) != 1) {
00944       PRINT("could not set extension name"); 
00945       return -kErrPX_SetAttribute;
00946    }
00947    // flag as critical
00948    if (X509_EXTENSION_set_critical(ext, 1) != 1) {
00949       PRINT("could not set extension critical flag"); 
00950       return -kErrPX_SetAttribute;
00951    }
00952    // Create a stack
00953    STACK_OF(X509_EXTENSION) *esk = sk_X509_EXTENSION_new_null();
00954    if (!esk) {
00955       PRINT("could not create stack for extensions"); 
00956       return -kErrPX_NoResources;
00957    }
00958    if (sk_X509_EXTENSION_push(esk, ext) != 1) {
00959       PRINT("could not push the extension in the stack"); 
00960       return -kErrPX_Error;
00961    }
00962    // Add extension
00963    if (!(X509_REQ_add_extensions(xro, esk))) {
00964       PRINT("problem adding extension"); 
00965       return -kErrPX_SetAttribute;
00966    }
00967    //
00968    // Sign the request
00969    if (!(X509_REQ_sign(xro, ekro, EVP_md5()))) {
00970       PRINT("problems signing the request"); 
00971       return -kErrPX_Signing;
00972    }
00973 
00974    // Prepare output
00975    *xcro = new XrdCryptosslX509Req(xro);
00976    *kcro = new XrdCryptosslRSA(ekro);
00977 
00978    // Cleanup
00979 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
00980    sk_X509_EXTENSION_free(esk);
00981 #else /* OPENSSL */
00982    sk_free(esk);
00983 #endif /* OPENSSL */
00984 
00985    // We are done
00986    return 0;
00987 }
00988 
00989 
00990 //____________________________________________________________________________
00991 int XrdSslgsiX509SignProxyReq(XrdCryptoX509 *xcpi, XrdCryptoRSA *kcpi,
00992                               XrdCryptoX509Req *xcri, XrdCryptoX509 **xcpo)
00993 {
00994    // Sign a proxy certificate request.
00995    // Return 0 in case of success, < 0 otherwise
00996    EPNAME("X509SignProxyReq");
00997 
00998    // Make sure we got the right inputs
00999    if (!xcpi || !kcpi || !xcri || !xcpo) {
01000       PRINT("invalid inputs");
01001       return -1;
01002    }
01003 
01004    // Make sure the certificate is not expired
01005    int timeleft = xcpi->NotAfter() - (int)time(0);
01006    if (timeleft < 0) {
01007       PRINT("EEC certificate has expired"); 
01008       return -kErrPX_ExpiredEEC;
01009    }
01010    // Point to the cerificate
01011    X509 *xpi = (X509 *)(xcpi->Opaque());
01012 
01013    // Check key consistency
01014    if (kcpi->status != XrdCryptoRSA::kComplete) {
01015       PRINT("inconsistent key loaded");
01016       return -kErrPX_BadEECkey;
01017    }
01018    // Point to the cerificate
01019    RSA *kpi = ((EVP_PKEY *)(kcpi->Opaque()))->pkey.rsa;
01020    //
01021    // Set the key into the request
01022    EVP_PKEY *ekpi = EVP_PKEY_new();
01023    if (!ekpi) {
01024       PRINT("could not create a EVP_PKEY * instance - return"); 
01025       return -kErrPX_NoResources;
01026    }
01027    EVP_PKEY_set1_RSA(ekpi, kpi);
01028 
01029    // Get request in raw form
01030    X509_REQ *xri = (X509_REQ *)(xcri->Opaque());
01031 
01032    // Extract subject names
01033    XrdOucString psbj = X509_NAME_oneline(X509_get_subject_name(xpi), 0, 0);
01034    XrdOucString rsbj = X509_NAME_oneline(X509_REQ_get_subject_name(xri), 0, 0);
01035    if (psbj.length() <= 0 || rsbj.length() <= 0) {
01036       PRINT("names undefined");
01037       return -kErrPX_BadNames;
01038    }
01039 
01040    // Check the subject name: the new proxy one must be in the form
01041    // '<issuer subject> + /CN=<serial>'
01042    XrdOucString neecp(psbj);
01043    XrdOucString neecr(rsbj,0,rsbj.rfind("/CN=")-1);
01044    if (neecr.length() <= 0 || neecr.length() <= 0 || neecp != neecr) {
01045       if (xcri->Version() <= 10100) {
01046          // Support previous format
01047          neecp.erase(psbj.rfind("/CN="));
01048          if (neecr.length() <= 0 || neecr.length() <= 0 || neecp != neecr) {
01049             PRINT("Request subject not in the form '<EEC subject> + /CN=<serial>'");
01050             PRINT("   Versn: "<<xcri->Version());
01051             PRINT("   Proxy: "<<neecp);
01052             PRINT("   SubRq: "<<neecr);
01053             return -kErrPX_BadNames;
01054          }
01055       } else {
01056          PRINT("Request subject not in the form '<issuer subject> + /CN=<serial>'");
01057          PRINT("   Versn: "<<xcri->Version());
01058          PRINT("   Proxy: "<<neecp);
01059          PRINT("   SubRq: "<<neecr);
01060          return -kErrPX_BadNames;
01061       }
01062    }
01063 
01064    // Extract serial number
01065    XrdOucString sserial(rsbj,rsbj.rfind("/CN=")+4);
01066    unsigned int serial = (unsigned int)(strtol(sserial.c_str(), 0, 10));
01067    //
01068    // Create new proxy cert
01069    X509 *xpo = X509_new();
01070    if (!xpo) {
01071       PRINT("could not create certificate object for proxies"); 
01072       return -kErrPX_NoResources;
01073    }
01074 
01075    // Set version number
01076    if (X509_set_version(xpo, 2L) != 1) {
01077       PRINT("could not set version"); 
01078       return -kErrPX_SetAttribute;
01079    }
01080 
01081    // Set serial number
01082    if (ASN1_INTEGER_set(X509_get_serialNumber(xpo), serial) != 1) {
01083       PRINT("could not set serial number"); 
01084       return -kErrPX_SetAttribute;
01085    }
01086 
01087    // Set subject name
01088    if (X509_set_subject_name(xpo, X509_REQ_get_subject_name(xri)) != 1) {
01089       PRINT("could not set subject name"); 
01090       return -kErrPX_SetAttribute;
01091    }
01092    
01093    // Set issuer name
01094    if (X509_set_issuer_name(xpo, X509_get_subject_name(xpi)) != 1) {
01095       PRINT("could not set issuer name"); 
01096       return -kErrPX_SetAttribute;
01097    }
01098 
01099    // Set public key
01100    if (X509_set_pubkey(xpo, X509_REQ_get_pubkey(xri)) != 1) {
01101       PRINT("could not set public key"); 
01102       return -kErrPX_SetAttribute;
01103    }
01104 
01105    // Set proxy validity: notBefore now
01106    if (!X509_gmtime_adj(X509_get_notBefore(xpo), 0)) {
01107       PRINT("could not set notBefore"); 
01108       return -kErrPX_SetAttribute;
01109    }
01110 
01111    // Set proxy validity: notAfter timeleft from now
01112    if (!X509_gmtime_adj(X509_get_notAfter(xpo), timeleft)) {
01113       PRINT("could not set notAfter"); 
01114       return -kErrPX_SetAttribute;
01115    }
01116 
01117    //
01118    // Get signature path depth from input proxy
01119    X509_EXTENSION *xpiext = 0;
01120    int npiext = X509_get_ext_count(xpi);
01121    int i = 0;
01122    int indepthlen = -1;
01123    for (i = 0; i< npiext; i++) {
01124       xpiext = X509_get_ext(xpi, i);
01125       char s[256] = {0};
01126       ASN1_OBJECT *obj = X509_EXTENSION_get_object(xpiext);
01127       if (obj) 
01128          OBJ_obj2txt(s, sizeof(s), obj, 1);
01129       if (!strcmp(s, gsiProxyCertInfo_OID)) {
01130          unsigned char *p = xpiext->value->data;
01131 #ifdef R__SSL_GE_098
01132          gsiProxyCertInfo_t *inpci =
01133             d2i_gsiProxyCertInfo(0, (const unsigned char **)(&p), xpiext->value->length);
01134 #else
01135          gsiProxyCertInfo_t *inpci = d2i_gsiProxyCertInfo(0, &p, xpiext->value->length);
01136 #endif
01137          if (inpci && 
01138              inpci->proxyCertPathLengthConstraint)
01139             indepthlen = ASN1_INTEGER_get(inpci->proxyCertPathLengthConstraint);
01140          DEBUG("IN depth length: "<<indepthlen);
01141       }
01142       // Do not free the extension: its owned by the certificate
01143       xpiext = 0;
01144    }
01145 
01146    //
01147    // Get signature path depth from the request
01148    STACK_OF(X509_EXTENSION) *xrisk = X509_REQ_get_extensions(xri);
01149    //
01150    // There must be at most one extension
01151 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
01152    int nriext = sk_X509_EXTENSION_num(xrisk);
01153 #else /* OPENSSL */
01154    int nriext = sk_num(xrisk);
01155 #endif /* OPENSSL */
01156    if (nriext != 1) {
01157       PRINT("missing or too many extensions in request"); 
01158       return -kErrPX_BadExtension;
01159    }
01160    // Get it
01161 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
01162    X509_EXTENSION *xriext = sk_X509_EXTENSION_value(xrisk, 0);
01163 #else /* OPENSSL */
01164    X509_EXTENSION *xriext = (X509_EXTENSION *)sk_value(xrisk, 0);
01165 #endif /* OPENSSL */
01166    if (!xriext) {
01167       PRINT("could not get extensions from request"); 
01168       return -kErrPX_BadExtension;
01169    }
01170    // Check the extension type
01171    char s[256];
01172    OBJ_obj2txt(s, sizeof(s), X509_EXTENSION_get_object(xriext), 1);
01173    if (strcmp(s, gsiProxyCertInfo_OID)) {
01174       PRINT("wrong extension found"); 
01175       return -kErrPX_BadExtension;
01176    }
01177    // Get the content
01178    int reqdepthlen = -1;
01179    unsigned char *p = xriext->value->data;
01180 #ifdef R__SSL_GE_098
01181    gsiProxyCertInfo_t *reqpci =
01182       d2i_gsiProxyCertInfo(0, (const unsigned char **)(&p), xriext->value->length);
01183 #else
01184    gsiProxyCertInfo_t *reqpci = d2i_gsiProxyCertInfo(0, &p, xriext->value->length);
01185 #endif
01186    if (reqpci &&
01187        reqpci->proxyCertPathLengthConstraint)
01188       reqdepthlen = ASN1_INTEGER_get(reqpci->proxyCertPathLengthConstraint);
01189    DEBUG("REQ depth length: "<<reqdepthlen);
01190    
01191    // We allow max indepthlen-1
01192    int outdepthlen = (reqdepthlen < indepthlen) ? reqdepthlen :
01193                                                  (indepthlen - 1); 
01194    //
01195    // Create the extension CertProxyInfo
01196    gsiProxyCertInfo_t *pci = gsiProxyCertInfo_new();
01197    if (!pci) {
01198       PRINT("could not create structure for extension - return"); 
01199       return -kErrPX_NoResources;
01200    }
01201 
01202    // Set the new length
01203    if (outdepthlen > -1) {
01204       if ((pci->proxyCertPathLengthConstraint = ASN1_INTEGER_new())) {
01205          int depthlen = (outdepthlen > 0) ? (outdepthlen-1) : 0;
01206          ASN1_INTEGER_set(pci->proxyCertPathLengthConstraint, depthlen);
01207       } else {
01208          PRINT("could not set the path length contrain"); 
01209          return -kErrPX_SetPathDepth;
01210       }
01211    }
01212    // create extension
01213    X509_EXTENSION *ext = X509_EXTENSION_new();
01214    if (!ext) {
01215       PRINT("could not create extension object"); 
01216       return -kErrPX_NoResources;
01217    }
01218    // Extract data in format for extension
01219    ext->value->length = i2d_gsiProxyCertInfo(pci, 0);
01220    if (!(ext->value->data = (unsigned char *)malloc(ext->value->length+1))) {
01221       PRINT("could not allocate data field for extension"); 
01222       return -kErrPX_NoResources;
01223    }
01224    unsigned char *pp = ext->value->data;
01225    if ((i2d_gsiProxyCertInfo(pci, &pp)) <= 0) {
01226       PRINT("problem converting data for extension"); 
01227       return -kErrPX_Error;
01228    }
01229    // Set extension name.
01230 #ifndef R__SSL_096
01231    // We do not use directly OBJ_txt2obj because that is not working
01232    // with all OpenSSL 0.9.6 versions
01233    ASN1_OBJECT *obj = OBJ_nid2obj(OBJ_create(gsiProxyCertInfo_OID,
01234                             "gsiProxyCertInfo_OID","GSI ProxyCertInfo OID"));
01235 #else
01236    // This version of OBJ_txt2obj fixes a bug affecting some 
01237    // OpenSSL 0.9.6 versions
01238    ASN1_OBJECT *obj = OBJ_txt2obj_fix(gsiProxyCertInfo_OID, 1);
01239 #endif
01240    if (!obj || X509_EXTENSION_set_object(ext, obj) != 1) {
01241       PRINT("could not set extension name"); 
01242       return -kErrPX_SetAttribute;
01243    }
01244    // flag as critical
01245    if (X509_EXTENSION_set_critical(ext, 1) != 1) {
01246       PRINT("could not set extension critical flag"); 
01247       return -kErrPX_SetAttribute;
01248    }
01249 
01250    // Add the extension
01251    if (X509_add_ext(xpo, ext, -1) != 1) {
01252       PRINT("could not add extension"); 
01253       return -kErrPX_SetAttribute;
01254    }
01255 
01256    //
01257    // Sign the certificate
01258    if (!(X509_sign(xpo, ekpi, EVP_md5()))) {
01259       PRINT("problems signing the certificate"); 
01260       return -kErrPX_Signing;
01261    }
01262 
01263    // Prepare outputs
01264    *xcpo = new XrdCryptosslX509(xpo);
01265 
01266    // Cleanup
01267 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
01268    sk_X509_EXTENSION_free(xrisk);
01269 #else /* OPENSSL */
01270    sk_free(xrisk);
01271 #endif /* OPENSSL */
01272 
01273    // We are done
01274    return 0;
01275 }

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