Back to index

nordugrid-arc-nox  1.1.0~rc6
Credential.cpp
Go to the documentation of this file.
00001 
00002 #ifdef HAVE_CONFIG_H
00003 #include <config.h>
00004 #endif
00005 
00006 #include <vector>
00007 
00008 #include <fstream>
00009 #include <fcntl.h>
00010 #include <openssl/ui.h>
00011 
00012 #include <glibmm/fileutils.h>
00013 
00014 #include <arc/crypto/OpenSSL.h>
00015 #include <arc/Utils.h>
00016 
00017 #include <arc/credential/VOMSUtil.h>
00018 
00019 #include "Credential.h"
00020 
00021 using namespace ArcCredential;
00022 
00023 namespace Arc {
00024   CredentialError::CredentialError(const std::string& what) : std::runtime_error(what) { }
00025 
00026   Logger CredentialLogger(Logger::rootLogger, "Credential");
00027 
00028 #if 0
00029 #define PASS_MIN_LENGTH 4
00030   static int passwordcb(char* pwd, int len, int verify, void* passphrase) {
00031     int j, r;
00032     //char prompt[128];
00033     const char* prompt;
00034     if(passphrase) {
00035       j=strlen((const char*)passphrase);
00036       j=(j > len)?len:j;
00037       memcpy(pwd,passphrase,j);
00038       return(j);
00039     }
00040     prompt=EVP_get_pw_prompt();
00041     if (prompt == NULL)
00042       prompt="Enter PEM pass phrase:";
00043 
00044     for(;;) {
00045       //if(!verify)
00046       //  snprintf(prompt, sizeof(prompt), "Enter passphrase to decrypte the key file: ");
00047       //else
00048       //  snprintf(prompt, sizeof(prompt), "Enter passphrase to encrypte the key file: ");
00049       r = EVP_read_pw_string(pwd, len, prompt, verify);
00050       if(r != 0) {
00051         CredentialLogger.msg(ERROR,"Failed to read input passphrase");
00052         memset(pwd,0,(unsigned int)len);
00053         return(-1);
00054       }
00055       j = strlen(pwd);
00056       if(verify && (j < PASS_MIN_LENGTH)) {
00057         CredentialLogger.msg(ERROR,"Input phrase is too short (at least %d char",PASS_MIN_LENGTH);
00058       }
00059       else { return j; }
00060     }
00061   }
00062 #endif
00063 
00064   static int ssl_err_cb(const char *str, size_t, void *u) {
00065     Logger& logger = *((Logger*)u);
00066     logger.msg(DEBUG, "OpenSSL error string: %s", str);
00067     return 1;
00068   }
00069 
00070 #define PASS_MIN_LENGTH 4
00071 #define PASS_MAX_LENGTH 20
00072   typedef struct pw_cb_data {
00073     const void *password;
00074     const char *prompt_info;
00075   } PW_CB_DATA;
00076 
00077   static int passwordcb(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) {
00078     UI *ui = NULL;
00079     int res = 0;
00080     const char *prompt_info = NULL;
00081     const char *password = NULL;
00082     PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
00083 
00084     if (bufsiz < 1) return res;
00085     if (cb_data) {
00086       if (cb_data->password)
00087       password = (const char*)(cb_data->password);
00088       if (cb_data->prompt_info)
00089         prompt_info = cb_data->prompt_info;
00090     }
00091 
00092     if (password) {
00093       res = strlen(password);
00094       if (res > (bufsiz-1))
00095         res = bufsiz-1;
00096       if(buf) {
00097         memcpy(buf, password, res);
00098         buf[res] = 0;
00099       }
00100       return res;
00101     }
00102 
00103     //ui = UI_new_method(ui_method);
00104     ui = UI_new();
00105     if (ui) {
00106       int ok = 0;
00107       char *buf1 = NULL;
00108       char *buf2 = NULL;
00109       int ui_flags = 0;
00110       char *prompt = NULL;
00111 
00112       prompt = UI_construct_prompt(ui, "pass phrase", cb_data->prompt_info);
00113 
00114       ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
00115       UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
00116 
00117       if (ok >= 0) {
00118         ok = -1;
00119         if((buf1 = (char *)OPENSSL_malloc(bufsiz)) != NULL) {
00120           memset(buf1,0,(unsigned int)bufsiz);
00121           ok = UI_add_input_string(ui,prompt,ui_flags,buf1,PASS_MIN_LENGTH,PASS_MAX_LENGTH);
00122         }
00123       }
00124       if (ok >= 0 && verify) {
00125         ok = -1;
00126         if((buf2 = (char *)OPENSSL_malloc(bufsiz)) != NULL) {
00127           memset(buf2,0,(unsigned int)bufsiz);
00128           ok = UI_add_verify_string(ui,prompt,ui_flags,buf2,PASS_MIN_LENGTH,PASS_MAX_LENGTH, buf);
00129         }
00130       }
00131       if (ok >= 0)
00132         do{
00133           ok = UI_process(ui);
00134         }while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
00135 
00136       if (buf2){
00137         memset(buf2,0,(unsigned int)bufsiz);
00138         OPENSSL_free(buf2);
00139       }
00140 
00141       if (ok >= 0) {
00142         if(buf1) {
00143           buf1[bufsiz-1] = 0;
00144           res = strlen(buf1);
00145           if(buf) memcpy(buf,buf1,res+1);
00146         }
00147       }
00148 
00149       if (buf1){
00150         memset(buf1,0,(unsigned int)bufsiz);
00151         OPENSSL_free(buf1);
00152       }
00153 
00154       if (ok == -1){
00155         std::cerr<<"User interface error\n"<<std::endl;
00156         ERR_print_errors_cb(&ssl_err_cb, &CredentialLogger);
00157         if(buf) memset(buf,0,(unsigned int)bufsiz);
00158         res = 0;
00159       }
00160       if (ok == -2) {
00161         std::cerr<<"Aborted!\n"<<std::endl;
00162         if(buf) memset(buf,0,(unsigned int)bufsiz);
00163         res = 0;
00164       }
00165       UI_free(ui);
00166       OPENSSL_free(prompt);
00167     }
00168 
00169     return res;
00170   }
00171 
00172   void Credential::LogError(void) {
00173     ERR_print_errors_cb(&ssl_err_cb, &CredentialLogger);
00174   }
00175 
00176   Time asn1_to_utctime(const ASN1_UTCTIME *s) {
00177     if(s == NULL) return Time();
00178     std::string t_str;
00179     if(s->type == V_ASN1_UTCTIME) {
00180       t_str.append("20");
00181       t_str.append((char*)(s->data));
00182     }
00183     else {//V_ASN1_GENERALIZEDTIME
00184       t_str.append((char*)(s->data));
00185     }
00186     return Time(t_str);
00187   }
00188 
00189   //Get the life time of the credential
00190   static void getLifetime(STACK_OF(X509)* certchain, X509* cert, Time& start, Period &lifetime) {
00191     X509* tmp_cert = NULL;
00192     Time start_time(-1), end_time(-1);
00193     int n;
00194     ASN1_UTCTIME* atime = NULL;
00195 
00196     if((cert == NULL) || (certchain == NULL)) {
00197       start = Time();
00198       lifetime = Period();
00199       return;
00200     }
00201 
00202     for (n = 0; n < sk_X509_num(certchain); n++) {
00203       tmp_cert = sk_X509_value(certchain, n);
00204 
00205       atime = X509_get_notAfter(tmp_cert);
00206       Time end = asn1_to_utctime(atime);
00207       if (end_time == Time(-1) || end < end_time) { end_time = end; }
00208 
00209       atime = X509_get_notBefore(tmp_cert);
00210       Time start = asn1_to_utctime(atime);
00211       if (start_time == Time(-1) || start > start_time) { start_time = start; }
00212     }
00213 
00214     atime = X509_get_notAfter(cert);
00215     Time e = asn1_to_utctime(atime);
00216     if (end_time == Time(-1) || e < end_time) { end_time = e; }
00217 
00218     atime = X509_get_notBefore(cert);
00219     Time s = asn1_to_utctime(atime);
00220     if (start_time == Time(-1) || s > start_time) { start_time = s; }
00221 
00222     start = start_time;
00223     lifetime = end_time - start_time;
00224   }
00225 
00226   //Parse the BIO for certificate and get the format of it
00227   Credformat Credential::getFormat(BIO* bio, const bool is_file) {
00228     Credformat format = CRED_UNKNOWN;
00229     if(bio == NULL) return format;
00230     if(is_file) {
00231       char buf[1];
00232       char firstbyte;
00233       int position;
00234       if((position = BIO_tell(bio))<0 || BIO_read(bio, buf, 1)<=0 || BIO_seek(bio, position)<0) {
00235         LogError();
00236         CredentialLogger.msg(ERROR,"Can't get the first byte of input BIO to get its format");
00237         return format;
00238       }
00239       firstbyte = buf[0];
00240       // DER-encoded structure (including PKCS12) will start with ASCII 048.
00241       // Otherwise, it's PEM.
00242       if(firstbyte==48) {
00243         //DER-encoded, PKCS12 or DER? firstly parse it as PKCS12 ASN.1,
00244         //if can not parse it, then it is DER format
00245         PKCS12* pkcs12 = NULL;
00246         if((pkcs12 = d2i_PKCS12_bio(bio,NULL)) == NULL){ format=CRED_DER; PKCS12_free(pkcs12); }
00247         else { format = CRED_PKCS; PKCS12_free(pkcs12); }
00248         if( BIO_seek(bio, position) < 0 ) {
00249           LogError();
00250           CredentialLogger.msg(ERROR,"Can't reset the BIO");
00251           return format;
00252         }
00253       }
00254       else { format = CRED_PEM; }
00255     }
00256     else {
00257       unsigned char* bio_str;
00258       int len;
00259       len = BIO_get_mem_data(bio, (unsigned char *) &bio_str);
00260       char firstbyte;
00261       if(len>0) {
00262         firstbyte = bio_str[0];
00263         if(firstbyte==48)  {}
00264         else { format = CRED_PEM; }
00265       }
00266       else {
00267         CredentialLogger.msg(ERROR,"Can't get the first byte of input BIO to get its format");
00268         return format;
00269       }
00270     }
00271     return format;
00272   }
00273 
00274   std::string Credential::GetDN(void) {
00275     X509_NAME *subject = NULL;
00276     if(!cert_) return "";
00277     subject = X509_get_subject_name(cert_);
00278     std::string str;
00279     char buf[256];
00280     if(subject!=NULL)
00281       X509_NAME_oneline(subject,buf,sizeof(buf));
00282     str.append(buf);
00283     return str;
00284   }
00285 
00286   std::string Credential::GetIdentityName(void) {
00287     X509_NAME *subject = NULL;
00288     X509_NAME_ENTRY *ne = NULL;
00289     if(!cert_) return "";
00290     subject = X509_NAME_dup(X509_get_subject_name(cert_));
00291 
00292 #if 0
00293     int proxy_depth = verify_ctx_.proxy_depth;
00294     //std::cout<<"proxy depth: +++"<<verify_ctx_.proxy_depth<<std::endl;
00295     for(int i=0; i<proxy_depth; i++) {
00296       ne = X509_NAME_delete_entry(subject, X509_NAME_entry_count(subject)-1);
00297       if(ne)
00298         X509_NAME_ENTRY_free(ne);
00299     }
00300 #endif
00301 
00302     ASN1_STRING* entry;
00303     std::string entry_str;
00304     for(;;) {
00305       ne = X509_NAME_get_entry(subject, X509_NAME_entry_count(subject)-1);
00306       if (!OBJ_cmp(ne->object,OBJ_nid2obj(NID_commonName))) {
00307         entry = X509_NAME_ENTRY_get_data(ne);
00308         entry_str.assign((const char*)(entry->data), (std::size_t)(entry->length));
00309         if(entry_str == "proxy" || entry_str == "limited proxy" ||
00310            entry_str.find_first_not_of("0123456789") == std::string::npos) {
00311           //Drop the name entry "proxy", "limited proxy", or the random digital(RFC)
00312           ne = X509_NAME_delete_entry(subject, X509_NAME_entry_count(subject)-1);
00313           X509_NAME_ENTRY_free(ne);
00314           ne = NULL;
00315         }
00316         else break;
00317       }
00318       else break;
00319     }
00320 
00321     std::string str;
00322     char buf[256];
00323     if(subject!=NULL) {
00324       X509_NAME_oneline(subject,buf,sizeof(buf));
00325       X509_NAME_free(subject);
00326     }
00327     str.append(buf);
00328     return str;
00329   }
00330 
00331   certType Credential::GetType(void) {
00332     return cert_type_;
00333   }
00334 
00335   std::string Credential::GetProxyPolicy(void) {
00336     return (verify_ctx_.proxy_policy);
00337   }
00338 
00339   Period Credential::GetLifeTime(void) {
00340     return lifetime_;
00341   }
00342 
00343   Time Credential::GetStartTime() {
00344     return start_;
00345   }
00346 
00347   Time Credential::GetEndTime() {
00348     return start_+lifetime_;
00349   }
00350 
00351   void Credential::SetLifeTime(const Period& period) {
00352     lifetime_ = period;
00353   }
00354 
00355   void Credential::SetStartTime(const Time& start_time) {
00356     start_ = start_time;
00357   }
00358 
00359   bool Credential::IsCredentialsValid(const UserConfig& usercfg) {
00360     Credential cred(!usercfg.ProxyPath().empty() ? usercfg.ProxyPath() : usercfg.CertificatePath(),
00361                     !usercfg.ProxyPath().empty() ? ""                  : usercfg.KeyPath(),
00362                     usercfg.CACertificatesDirectory(), usercfg.CACertificatePath());
00363     Time t;
00364     return cred.verification_valid && cred.GetStartTime() < t && t < cred.GetEndTime();
00365   }
00366 
00367   class AutoBIO {
00368    private:
00369     BIO* bio_;
00370    public:
00371     AutoBIO(BIO* bio):bio_(bio) { };
00372     ~AutoBIO(void) { if(bio_) { BIO_set_close(bio_,BIO_CLOSE); BIO_free_all(bio_); } };
00373     operator bool(void) { return (bio_ != NULL); };
00374     operator BIO*(void) { return bio_; };
00375     BIO& operator*(void) const { return *bio_; };
00376     BIO* operator->(void) const { return bio_; };
00377   };
00378 
00379   void Credential::loadCertificateString(const std::string& cert, X509* &x509, STACK_OF(X509) **certchain) {
00380     AutoBIO certbio(BIO_new_mem_buf((void*)(cert.c_str()), cert.length()));
00381     if(!certbio){
00382       CredentialLogger.msg(ERROR,"Can not read certificate string");
00383       LogError();
00384       throw CredentialError("Can not read certificate string");
00385     }
00386     loadCertificate(certbio,x509,certchain, false);
00387   }
00388 
00389   void Credential::loadCertificateFile(const std::string& certfile, X509* &x509, STACK_OF(X509) **certchain) {
00390     if(!Glib::file_test(certfile,Glib::FILE_TEST_IS_REGULAR)) {
00391         CredentialLogger.msg(ERROR,"Can not find certificate file: %s", certfile);
00392         throw CredentialError("Can not find certificate file");
00393     }
00394     AutoBIO certbio(BIO_new_file(certfile.c_str(), "r"));
00395     if(!certbio){
00396       CredentialLogger.msg(ERROR,"Can not read certificate file: %s", certfile);
00397       LogError();
00398       throw CredentialError("Can not read certificate file");
00399     }
00400     loadCertificate(certbio,x509,certchain, true);
00401   }
00402 
00403   void Credential::loadCertificate(BIO* certbio, X509* &x509, STACK_OF(X509) **certchain, const bool is_file) {
00404     //Parse the certificate
00405     Credformat format = CRED_UNKNOWN;
00406     PKCS12* pkcs12 = NULL;
00407     STACK_OF(X509)* pkcs12_certs = NULL;
00408 
00409     if(certbio == NULL) return;
00410     format = getFormat(certbio, is_file);
00411     int n;
00412     if(*certchain) {
00413       sk_X509_pop_free(*certchain, X509_free);
00414       *certchain = NULL;
00415     }
00416 
00417     switch(format) {
00418       case CRED_PEM:
00419         CredentialLogger.msg(DEBUG,"Certificate format is PEM");
00420         //Get the certificte, By default, certificate is without passphrase
00421         //Read certificate
00422         if(!(PEM_read_bio_X509(certbio, &x509, NULL, NULL))) {
00423           throw CredentialError("Can not read cert information from BIO");
00424         }
00425         //Get the issuer chain
00426         *certchain = sk_X509_new_null();
00427         n = 0;
00428         while(!BIO_eof(certbio)){
00429           X509 * tmp = NULL;
00430           if(!(PEM_read_bio_X509(certbio, &tmp, NULL, NULL))){
00431             ERR_clear_error(); break;
00432           }
00433           if(!sk_X509_insert(*certchain, tmp, n)) {
00434             //std::string str(X509_NAME_oneline(X509_get_subject_name(tmp),0,0));
00435             X509_free(tmp);
00436             throw CredentialError("Can not insert cert into certificate's issuer chain");
00437           }
00438           ++n;
00439         }
00440         break;
00441 
00442       case CRED_DER:
00443         CredentialLogger.msg(DEBUG,"Certificate format is DER");
00444         x509=d2i_X509_bio(certbio,NULL);
00445         if(!x509){
00446           throw CredentialError("Unable to read DER credential from BIO");
00447         }
00448         //Get the issuer chain
00449         *certchain = sk_X509_new_null();
00450         n = 0;
00451         while(!BIO_eof(certbio)){
00452           X509 * tmp = NULL;
00453           if(!(d2i_X509_bio(certbio, &tmp))){
00454             ERR_clear_error(); break;
00455           }
00456           if(!sk_X509_insert(*certchain, tmp, n)) {
00457             //std::string str(X509_NAME_oneline(X509_get_subject_name(tmp),0,0));
00458             X509_free(tmp);
00459             throw CredentialError("Can not insert cert into certificate's issuer chain");
00460           }
00461           ++n;
00462         }
00463         break;
00464 
00465       case CRED_PKCS:
00466         CredentialLogger.msg(DEBUG,"Certificate format is PKCS");
00467         pkcs12 = d2i_PKCS12_bio(certbio, NULL);
00468         if(pkcs12){
00469           char password[100];
00470           EVP_read_pw_string(password, 100, "Enter Password for PKCS12 certificate:", 0);
00471           if(!PKCS12_parse(pkcs12, password, NULL, &x509, &pkcs12_certs)) {
00472             if(pkcs12) PKCS12_free(pkcs12);
00473             throw CredentialError("Can not parse PKCS12 file");
00474           }
00475         }
00476         else{
00477           throw CredentialError("Can not read PKCS12 credential from BIO");
00478         }
00479         if (pkcs12_certs && sk_X509_num(pkcs12_certs)){
00480           X509* tmp;
00481           for (n = 0; n < sk_X509_num(pkcs12_certs); n++) {
00482             tmp = X509_dup(sk_X509_value(pkcs12_certs, n));
00483             sk_X509_insert(*certchain, tmp, n);
00484           }
00485         }
00486         if(pkcs12) { PKCS12_free(pkcs12); }
00487         if(pkcs12_certs) { sk_X509_pop_free(pkcs12_certs, X509_free); }
00488 
00489         break;
00490 
00491       default:
00492         CredentialLogger.msg(DEBUG,"Certificate format is unknown");
00493         break;
00494      } // end switch
00495   }
00496 
00497   void Credential::loadKeyString(const std::string& key, EVP_PKEY* &pkey, const std::string& passphrase) {
00498     AutoBIO keybio(BIO_new_mem_buf((void*)(key.c_str()), key.length()));
00499     if(!keybio){
00500       CredentialLogger.msg(ERROR,"Can not read key string");
00501       LogError();
00502       throw CredentialError("Can not read key string");
00503     }
00504     loadKey(keybio,pkey,passphrase, "Load key from a string", false);
00505   }
00506 
00507   void Credential::loadKeyFile(const std::string& keyfile, EVP_PKEY* &pkey, const std::string& passphrase) {
00508     if(!Glib::file_test(keyfile,Glib::FILE_TEST_IS_REGULAR)) {
00509         CredentialLogger.msg(ERROR,"Can not find key file: %s", keyfile);
00510         throw CredentialError("Can not find key file");
00511     }
00512     AutoBIO keybio(BIO_new_file(keyfile.c_str(), "r"));
00513     if(!keybio){
00514       CredentialLogger.msg(ERROR,"Can not open key file %s", keyfile);
00515       LogError();
00516       throw CredentialError("Can not open key file " + keyfile);
00517     }
00518     loadKey(keybio,pkey,passphrase, keyfile, true);
00519   }
00520 
00521   void Credential::loadKey(BIO* keybio, EVP_PKEY* &pkey, const std::string& passphrase, const std::string& prompt_info, const bool is_file) {
00522     //Read key
00523     Credformat format;
00524     PKCS12* pkcs12 = NULL;
00525 
00526     if(keybio == NULL) return;
00527     format = getFormat(keybio, is_file);
00528     std::string prompt;
00529     switch(format){
00530       case CRED_PEM:
00531         PW_CB_DATA cb_data;
00532         cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
00533         cb_data.prompt_info = prompt_info.empty() ? NULL : prompt_info.c_str();
00534         if(!(pkey = PEM_read_bio_PrivateKey(keybio, NULL, (pem_password_cb *)passwordcb, &cb_data))) {
00535           int reason = ERR_GET_REASON(ERR_peek_error());
00536           if(reason == PEM_R_BAD_BASE64_DECODE ||
00537             reason == PEM_R_BAD_DECRYPT ||
00538             reason == PEM_R_BAD_PASSWORD_READ ||
00539             reason == PEM_R_PROBLEMS_GETTING_PASSWORD)
00540             throw CredentialError("Can not read PEM private key: Bad password");
00541           else throw CredentialError("Can not read PEM private key");
00542         }
00543         break;
00544 
00545       case CRED_DER:
00546         pkey=d2i_PrivateKey_bio(keybio, NULL);
00547         break;
00548 
00549       case CRED_PKCS:
00550         pkcs12 = d2i_PKCS12_bio(keybio, NULL);
00551         if(pkcs12) {
00552           char password[100];
00553           EVP_read_pw_string(password, 100, "Enter Password for PKCS12 certificate:", 0);
00554           if(!PKCS12_parse(pkcs12, password, &pkey, NULL, NULL)) {
00555             throw CredentialError("Can not parse PKCS12");
00556           }
00557           PKCS12_free(pkcs12);
00558         }
00559         break;
00560 
00561       default:
00562         break;
00563     }
00564   }
00565 
00566   static bool proxy_init_ = false;
00567 
00568   void Credential::InitProxyCertInfo(void) {
00569     static Glib::Mutex lock_;
00570     #define OBJC(c,n) OBJ_create(c,n,#c)
00571     X509V3_EXT_METHOD *pci_x509v3_ext_meth = NULL;
00572 
00573     // At least in some versions of OpenSSL functions manupulating
00574     // global lists seems to be not thread-safe despite locks
00575     // installed (tested for 0.9.7). Hence it is safer to protect
00576     // such calls.
00577     // It is also good idea to protect proxy_init_ too.
00578 
00579     Glib::Mutex::Lock lock(lock_);
00580     if(proxy_init_) return;
00581 
00582     /* Proxy Certificate Extension's related objects */
00583     if(OBJ_txt2nid(PROXYCERTINFO_V3) == NID_undef) {
00584       OBJC(PROXYCERTINFO_V3, "PROXYCERTINFO_V3");
00585       pci_x509v3_ext_meth = PROXYCERTINFO_v3_x509v3_ext_meth();
00586       if (pci_x509v3_ext_meth) {
00587         pci_x509v3_ext_meth->ext_nid = OBJ_txt2nid(PROXYCERTINFO_V3);
00588         X509V3_EXT_add(pci_x509v3_ext_meth);
00589       }
00590     }
00591 
00592     if(OBJ_txt2nid(PROXYCERTINFO_V4) == NID_undef) {
00593       OBJC(PROXYCERTINFO_V4, "PROXYCERTINFO_V4");
00594       pci_x509v3_ext_meth = PROXYCERTINFO_v4_x509v3_ext_meth();
00595       if (pci_x509v3_ext_meth) {
00596         pci_x509v3_ext_meth->ext_nid = OBJ_txt2nid(PROXYCERTINFO_V4);
00597         X509V3_EXT_add(pci_x509v3_ext_meth);
00598       }
00599     }
00600 
00601     if(OBJ_txt2nid(IMPERSONATION_PROXY_OID) == NID_undef) {
00602       OBJ_create(IMPERSONATION_PROXY_OID, IMPERSONATION_PROXY_SN, IMPERSONATION_PROXY_LN);
00603     }
00604     if(OBJ_txt2nid(INDEPENDENT_PROXY_OID) == NID_undef) {
00605       OBJ_create(INDEPENDENT_PROXY_OID, INDEPENDENT_PROXY_SN, INDEPENDENT_PROXY_LN);
00606     }
00607     if(OBJ_txt2nid(ANYLANGUAGE_PROXY_OID) == NID_undef) {
00608       OBJ_create(ANYLANGUAGE_PROXY_OID, ANYLANGUAGE_PROXY_SN, ANYLANGUAGE_PROXY_LN);
00609     }
00610     if(OBJ_txt2nid(LIMITED_PROXY_OID) == NID_undef) {
00611       OBJ_create(LIMITED_PROXY_OID, LIMITED_PROXY_SN, LIMITED_PROXY_LN);
00612     }
00613     // This library provides methods and objects which when registred in
00614     // global OpenSSL lists can't be unregistred anymore. Hence it must not
00615     // be allowed to unload.
00616     if(!PersistentLibraryInit("modcredential")) {
00617       CredentialLogger.msg(WARNING, "Failed to lock arccredential library in memory");
00618     };
00619     proxy_init_=true;
00620   }
00621 
00622   void Credential::AddCertExtObj(std::string& sn, std::string& oid) {
00623     OBJ_create(oid.c_str(), sn.c_str(), sn.c_str());
00624   }
00625 
00626   void Credential::InitVerification(void) {
00627     verify_ctx_.cert_store = NULL;
00628     verify_ctx_.cert_depth = 0;
00629     verify_ctx_.proxy_depth = 0;
00630     verify_ctx_.max_proxy_depth = -1;
00631     verify_ctx_.limited_proxy = 0;
00632     verify_ctx_.cert_type = CERT_TYPE_EEC;
00633     verify_ctx_.cert_chain = sk_X509_new_null();
00634     verify_ctx_.ca_dir = cacertdir_;
00635     verify_ctx_.ca_file = cacertfile_;
00636   }
00637 
00638   bool Credential::Verify(void) {
00639     if(verify_cert_chain(cert_, &cert_chain_, &verify_ctx_)) {
00640       CredentialLogger.msg(VERBOSE, "Certificate verification succeeded");
00641       verification_valid = true;
00642       return true;
00643     }
00644     else {CredentialLogger.msg(INFO, "Certificate verification failed"); LogError(); return false;}
00645   }
00646 
00647   Credential::Credential() : cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
00648         start_(Time()), lifetime_(Period("PT12H")),
00649         req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(1024),
00650         extensions_(NULL) {
00651 
00652     OpenSSLInit();
00653     //EVP_add_digest(EVP_sha1());
00654 
00655     InitVerification();
00656 
00657     extensions_ = sk_X509_EXTENSION_new_null();
00658 
00659     //Initiate the proxy certificate constant and  method which is required by openssl
00660     if(!proxy_init_) InitProxyCertInfo();
00661   }
00662 
00663   Credential::Credential(int keybits) : cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
00664     start_(Time()), lifetime_(Period("PT12H")),
00665     req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(keybits),
00666     extensions_(NULL) {
00667 
00668     OpenSSLInit();
00669     //EVP_add_digest(EVP_sha1());
00670 
00671     InitVerification();
00672 
00673     extensions_ = sk_X509_EXTENSION_new_null();
00674 
00675     //Initiate the proxy certificate constant and  method which is required by openssl
00676     if(!proxy_init_) InitProxyCertInfo();
00677   }
00678 
00679   Credential::Credential(Time start, Period lifetime, int keybits, std::string proxyversion,
00680         std::string policylang, std::string policy, int pathlength) :
00681         cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
00682         start_(start), lifetime_(lifetime), req_(NULL), rsa_key_(NULL),
00683         signing_alg_((EVP_MD*)EVP_sha1()), keybits_(keybits), extensions_(NULL) {
00684 
00685     OpenSSLInit();
00686     //EVP_add_digest(EVP_sha1());
00687 
00688     InitVerification();
00689 
00690     extensions_ = sk_X509_EXTENSION_new_null();
00691 
00692     //Initiate the proxy certificate constant and  method which is required by openssl
00693     if(!proxy_init_) InitProxyCertInfo();
00694 
00695     SetProxyPolicy(proxyversion, policylang, policy, pathlength);
00696   }
00697 
00698   void Credential::SetProxyPolicy(const std::string& proxyversion, const std::string& policylang,
00699         const std::string& policy, int pathlength) {
00700 
00701     proxyversion_ = proxyversion;
00702     policy_ = policy;
00703     policylang_ = policylang;
00704     pathlength_ = pathlength;
00705 
00706     //Get certType
00707     if(proxyversion_.compare("GSI2") == 0 || proxyversion_.compare("gsi2") == 0) {
00708       if(policylang_.compare("LIMITED") == 0 || policylang_.compare("limited") == 0) {
00709         cert_type_ = CERT_TYPE_GSI_2_LIMITED_PROXY;
00710       }
00711       else if (policylang_.compare("RESTRICTED") == 0 || policylang_.compare("restricted") == 0) {
00712         CredentialLogger.msg(ERROR,"Globus legacy proxies can not carry policy data or path length contraints");
00713       }
00714       else {
00715         cert_type_ = CERT_TYPE_GSI_2_PROXY;
00716       }
00717     }
00718     else if (proxyversion_.compare("RFC") == 0 || proxyversion_.compare("rfc") == 0) {
00719       //The "limited" and "restricted" are from the definition in
00720       //http://dev.globus.org/wiki/Security/ProxyCertTypes#RFC_3820_Proxy_Certificates
00721       if(policylang_.compare("LIMITED") == 0 || policylang_.compare("limited") == 0) {
00722         cert_type_ = CERT_TYPE_RFC_LIMITED_PROXY;
00723       }
00724       else if(policylang_.compare("RESTRICTED") == 0 || policylang_.compare("restricted") == 0) {
00725         cert_type_ = CERT_TYPE_RFC_RESTRICTED_PROXY;
00726       }
00727       else if(policylang_.compare("INDEPENDENT") == 0 || policylang_.compare("independent") == 0) {
00728         cert_type_ = CERT_TYPE_RFC_INDEPENDENT_PROXY;
00729       }
00730       else if(policylang_.compare("IMPERSONATION") == 0 || policylang_.compare("impersonation") == 0 ||
00731          policylang_.compare("INHERITALL") == 0 || policylang_.compare("inheritAll") == 0){
00732         cert_type_ = CERT_TYPE_RFC_IMPERSONATION_PROXY;
00733         //For RFC here, "impersonation" is the same as the "inheritAll" in openssl version>098
00734       }
00735       else if(policylang_.compare("ANYLANGUAGE") == 0 || policylang_.compare("anylanguage") == 0) {
00736         cert_type_ = CERT_TYPE_RFC_ANYLANGUAGE_PROXY;  //Defined in openssl version>098
00737       }
00738     }
00739     else if (proxyversion_.compare("EEC") == 0 || proxyversion_.compare("eec") == 0) {
00740       cert_type_ = CERT_TYPE_EEC;
00741     }
00742     else {
00743       if(policylang_.compare("LIMITED") == 0 || policylang_.compare("limited") == 0) {
00744         cert_type_ = CERT_TYPE_GSI_3_LIMITED_PROXY;
00745       }
00746       else if(policylang_.compare("RESTRICTED") == 0 || policylang_.compare("restricted") == 0) {
00747         cert_type_ = CERT_TYPE_GSI_3_RESTRICTED_PROXY;
00748       }
00749       else if(policylang_.compare("INDEPENDENT") == 0 || policylang_.compare("independent") == 0) {
00750         cert_type_ = CERT_TYPE_GSI_3_INDEPENDENT_PROXY;
00751       }
00752       else {
00753         cert_type_ = CERT_TYPE_GSI_3_IMPERSONATION_PROXY;
00754       }
00755     }
00756 
00757     if(cert_type_ != CERT_TYPE_EEC) {
00758       if(!policy_.empty() && policylang_.empty()) {
00759         CredentialLogger.msg(ERROR,"If you specify a policy you also need to specify a policy language");
00760         return;
00761       }
00762 
00763       if(proxy_cert_info_) {
00764         PROXYCERTINFO_free(proxy_cert_info_);
00765         proxy_cert_info_ = NULL;
00766       }
00767 
00768       proxy_cert_info_ = PROXYCERTINFO_new();
00769       PROXYPOLICY *   ppolicy =PROXYCERTINFO_get_proxypolicy(proxy_cert_info_);
00770       PROXYPOLICY_set_policy(ppolicy, NULL, 0);
00771       ASN1_OBJECT *   policy_object = NULL;
00772 
00773       //set policy language, see definiton in: http://dev.globus.org/wiki/Security/ProxyCertTypes
00774       switch(cert_type_)
00775       {
00776         case CERT_TYPE_GSI_3_IMPERSONATION_PROXY:
00777         case CERT_TYPE_RFC_IMPERSONATION_PROXY:
00778           if((policy_object = OBJ_nid2obj(OBJ_txt2nid(IMPERSONATION_PROXY_OID))) != NULL) {
00779             PROXYPOLICY_set_policy_language(ppolicy, policy_object);
00780           }
00781           break;
00782 
00783         case CERT_TYPE_GSI_3_INDEPENDENT_PROXY:
00784         case CERT_TYPE_RFC_INDEPENDENT_PROXY:
00785           if((policy_object = OBJ_nid2obj(OBJ_txt2nid(INDEPENDENT_PROXY_OID))) != NULL) {
00786             PROXYPOLICY_set_policy_language(ppolicy, policy_object);
00787           }
00788           break;
00789 
00790         case CERT_TYPE_GSI_3_LIMITED_PROXY:
00791         case CERT_TYPE_RFC_LIMITED_PROXY:
00792           if((policy_object = OBJ_nid2obj(OBJ_txt2nid(LIMITED_PROXY_OID))) != NULL) {
00793             PROXYPOLICY_set_policy_language(ppolicy, policy_object);
00794           }
00795           break;
00796         case CERT_TYPE_RFC_ANYLANGUAGE_PROXY:
00797           if((policy_object = OBJ_nid2obj(OBJ_txt2nid(ANYLANGUAGE_PROXY_OID))) != NULL) {
00798             PROXYPOLICY_set_policy_language(ppolicy, policy_object);
00799           }
00800           break;
00801         default:
00802           break;
00803       }
00804 
00805       //set path length constraint
00806       if(pathlength >= 0)
00807       PROXYCERTINFO_set_path_length(proxy_cert_info_, pathlength_);
00808 
00809       //set policy
00810       std::string policystring;
00811       if(!policy_.empty()) {
00812         if(Glib::file_test(policy_,Glib::FILE_TEST_EXISTS)) {
00813           //If the argument is a location which specifies a file that
00814           //includes the policy content
00815           if(Glib::file_test(policy_,Glib::FILE_TEST_IS_REGULAR)) {
00816             std::ifstream fp;
00817             fp.open(policy_.c_str());
00818             if(!fp) {
00819               CredentialLogger.msg(ERROR,"Error: can't open policy file: %s", policy_.c_str());
00820               if(proxy_cert_info_) {
00821                 PROXYCERTINFO_free(proxy_cert_info_);
00822                 proxy_cert_info_ = NULL;
00823               }
00824               return;
00825             }
00826             fp.unsetf(std::ios::skipws);
00827             char c;
00828             while(fp.get(c))
00829               policystring += c;
00830           }
00831           else {
00832             CredentialLogger.msg(ERROR,"Error: policy location: %s is not a regular file", policy_.c_str());
00833             if(proxy_cert_info_) {
00834               PROXYCERTINFO_free(proxy_cert_info_);
00835               proxy_cert_info_ = NULL;
00836             }
00837             return;
00838           }
00839         }
00840         else {
00841           //Otherwise the argument should include the policy content
00842           policystring = policy_;
00843         }
00844       }
00845 
00846       if(policylang_ == "LIMITED" || policylang_ == "limited")
00847         policylang_ = LIMITED_PROXY_OID;
00848       else if(policylang_ == "INDEPENDENT" || policylang_ == "independent")
00849         policylang_ = INDEPENDENT_PROXY_OID;
00850       else if(policylang_ == "IMPERSONATION" || policylang_ == "impersonation"
00851           || policylang_ == "inheritAll" || policylang_ == "INHERITALL")
00852         policylang_ = IMPERSONATION_PROXY_OID;
00853       else if(policylang_.empty()) {
00854         if(policy_.empty()) policylang_ = IMPERSONATION_PROXY_OID;
00855         else policylang_ = GLOBUS_GSI_PROXY_GENERIC_POLICY_OID;
00856       }
00857 
00862       //OBJ_create((char *)policylang_.c_str(), (char *)policylang_.c_str(), (char *)policylang_.c_str());
00863 
00864       //policy_object = OBJ_nid2obj(OBJ_sn2nid(policylang_.c_str()));
00865 
00866       ppolicy = PROXYCERTINFO_get_proxypolicy(proxy_cert_info_);
00867       //Here only consider the situation when there is policy specified
00868       if(policystring.size() > 0) {
00869         //PROXYPOLICY_set_policy_language(ppolicy, policy_object);
00870         PROXYPOLICY_set_policy(ppolicy, (unsigned char*)policystring.c_str(), policystring.size());
00871       }
00872 
00873       //set the version of PROXYCERTINFO
00874       if(proxyversion_ == "RFC" || proxyversion_ == "rfc")
00875         PROXYCERTINFO_set_version(proxy_cert_info_, 4);
00876       else
00877         PROXYCERTINFO_set_version(proxy_cert_info_, 3);
00878     }
00879   }
00880 
00881   Credential::Credential(const std::string& certfile, const std::string& keyfile,
00882         const std::string& cadir, const std::string& cafile,
00883         const std::string& passphrase4key, const bool is_file) :
00884         cacertfile_(cafile), cacertdir_(cadir), certfile_(certfile), keyfile_(keyfile),
00885         cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
00886         req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()),
00887         keybits_(1024), extensions_(NULL), verification_valid(false) {
00888 
00889     OpenSSLInit();
00890     //EVP_add_digest(EVP_sha1());
00891 
00892     InitVerification();
00893 
00894     extensions_ = sk_X509_EXTENSION_new_null();
00895 
00896     if(certfile.empty()) {
00897       CredentialLogger.msg(ERROR, "Certificate/Proxy path is empty");
00898       return;
00899     }
00900 
00901     //Initiate the proxy certificate constant and  method which is required by openssl
00902     if(!proxy_init_) InitProxyCertInfo();
00903 
00904     if(is_file) {
00905       try {
00906         loadCertificateFile(certfile, cert_, &cert_chain_);
00907         if(cert_) check_cert_type(cert_,cert_type_);
00908         //std::cout<<"Your identity: "<<GetDN() << std::endl;
00909         if(keyfile.empty()) {
00910           //Detect if the certificate file/string contains private key.
00911           //If the key file is absent, and the private key is not contained inside
00912           //certificate file/string, then the certificate file will not
00913           //be parsed for private key.
00914           //Note this detection only applies to PEM file
00915           std::string keystr;
00916           // Since the certfile file has been loaded in the call to
00917           // loadCertificateFile, it is redundant to check if it exist.
00918           // loadCertificateFile will throw an exception if the file does not
00919           // exist.
00920           std::ifstream in(certfile.c_str(), std::ios::in);
00921           std::getline<char>(in, keystr, 0);
00922           in.close();
00923           if(keystr.find("BEGIN RSA PRIVATE KEY") != std::string::npos)
00924             loadKeyFile(certfile, pkey_, passphrase4key);
00925         }
00926         else
00927           loadKeyFile(keyfile, pkey_, passphrase4key);
00928       } catch(std::exception& err){
00929         CredentialLogger.msg(ERROR, "%s", err.what());
00930         LogError(); return;
00931       }
00932     } else {
00933       try {
00934         loadCertificateString(certfile, cert_, &cert_chain_);
00935         if(cert_) check_cert_type(cert_,cert_type_);
00936         if(keyfile.empty()) {
00937           std::string keystr;
00938           keystr = certfile;
00939           if(keystr.find("BEGIN RSA PRIVATE KEY") != std::string::npos)
00940             loadKeyString(certfile, pkey_, passphrase4key);
00941         }
00942         else
00943           loadKeyString(keyfile, pkey_, passphrase4key);
00944       } catch(std::exception& err){
00945         CredentialLogger.msg(ERROR, "%s", err.what());
00946         LogError(); return;
00947       }
00948     }
00949 
00950     //Get the lifetime of the credential
00951     getLifetime(cert_chain_, cert_, start_, lifetime_);
00952 
00953     if(!cacertfile_.empty() || !cacertdir_.empty())
00954       Verify();
00955   }
00956 
00957   #ifdef HAVE_OPENSSL_OLDRSA
00958   static void keygen_cb(int p, int, void*) {
00959     char c='*';
00960     if (p == 0) c='.';
00961     if (p == 1) c='+';
00962     if (p == 2) c='*';
00963     if (p == 3) c='\n';
00964     std::cerr<<c;
00965   }
00966   #else
00967   static int keygen_cb(int p, int, BN_GENCB*) {
00968     char c='*';
00969     if (p == 0) c='.';
00970     if (p == 1) c='+';
00971     if (p == 2) c='*';
00972     if (p == 3) c='\n';
00973     std::cerr<<c;
00974     return 1;
00975   }
00976   #endif
00977 
00978 
00979   X509_EXTENSION* Credential::CreateExtension(std::string& name, std::string& data, bool crit) {
00980     X509_EXTENSION*   ext = NULL;
00981     ASN1_OBJECT*      ext_obj = NULL;
00982     ASN1_OCTET_STRING*  ext_oct = NULL;
00983 
00984     bool numberic = true;
00985     size_t pos1 = 0, pos2;
00986     do {
00987       pos2 = name.find(".", pos1);
00988       if(pos2 != std::string::npos) { //OID: 1.2.3.4.5
00989         std::string str = name.substr(pos1, pos2 - pos1);
00990         long int number = strtol(str.c_str(), NULL, 0);
00991         if(number == 0) { numberic = false; break; }
00992       }
00993       else { //The only one (without '.' as sperator, then the name is a single number or a string) or the last number
00994         std::string str = name.substr(pos1);
00995         long int number = strtol(str.c_str(), NULL, 0);
00996         if(number == 0) { numberic = false; break; }
00997         else break;
00998       }
00999       pos1 = pos2 + 1;
01000     } while(true);
01001 
01002     if(!numberic && !(ext_obj = OBJ_nid2obj(OBJ_txt2nid((char *)(name.c_str()))))) {
01003       //string format, the OID should have been registered before calling OBJ_nid2obj
01004       CredentialLogger.msg(ERROR, "Can not convert string into ASN1_OBJECT");
01005       LogError(); return NULL;
01006     }
01007     else if(numberic && !(ext_obj = OBJ_txt2obj(name.c_str(), 1))) {
01008       //numerical format, the OID will be registered here if it has not been registered before
01009       CredentialLogger.msg(ERROR, "Can not convert string into ASN1_OBJECT");
01010       LogError(); return NULL;
01011     }
01012 
01013     ext_oct = ASN1_OCTET_STRING_new();
01014 
01015     //ASN1_OCTET_STRING_set(ext_oct, data.c_str(), data.size());
01016     ext_oct->data = (unsigned char*) malloc(data.size());
01017     memcpy(ext_oct->data, data.c_str(), data.size());
01018     ext_oct->length = data.size();
01019 
01020     if (!(ext = X509_EXTENSION_create_by_OBJ(NULL, ext_obj, crit, ext_oct))) {
01021       CredentialLogger.msg(ERROR, "Can not create extension for proxy certificate");
01022       LogError();
01023       if(ext_oct) ASN1_OCTET_STRING_free(ext_oct);
01024       if(ext_obj) ASN1_OBJECT_free(ext_obj);
01025       return NULL;
01026     }
01027 
01028 #ifndef WIN32
01029 
01030     // TODO: ASN1_OCTET_STRING_free is not working correctly
01031     //      on Windows Vista, bugreport: 1587
01032 
01033     if(ext_oct) ASN1_OCTET_STRING_free(ext_oct);
01034 
01035 #endif
01036     if(ext_obj) ASN1_OBJECT_free(ext_obj);
01037 
01038     return ext;
01039   }
01040 
01041   X509_REQ* Credential::GetCertReq(void) {
01042     return req_;
01043   }
01044 
01045   bool Credential::GenerateEECRequest(BIO* reqbio, BIO* /*keybio*/, std::string dn) {
01046     bool res = false;
01047     RSA* rsa_key = NULL;
01048     const EVP_MD *digest = signing_alg_;
01049     EVP_PKEY* pkey;
01050     int keybits = keybits_;
01051 
01052 #ifdef HAVE_OPENSSL_OLDRSA
01053     unsigned long prime = RSA_F4;
01054     rsa_key = RSA_generate_key(keybits, prime, keygen_cb, NULL);
01055     if(!rsa_key) {
01056       CredentialLogger.msg(ERROR, "RSA_generate_key failed");
01057       if(rsa_key) RSA_free(rsa_key);
01058       return false;
01059     }
01060 #else
01061     BN_GENCB cb;
01062     BIGNUM *prime = BN_new();
01063     rsa_key = RSA_new();
01064 
01065     BN_GENCB_set(&cb,&keygen_cb,NULL);
01066     if(prime && rsa_key) {
01067       if(BN_set_word(prime,RSA_F4)) {
01068         if(!RSA_generate_key_ex(rsa_key, keybits, prime, &cb)) {
01069           CredentialLogger.msg(ERROR, "RSA_generate_key_ex failed");
01070           LogError();
01071           if(prime) BN_free(prime);
01072           return false;
01073         }
01074       }
01075       else{
01076         CredentialLogger.msg(ERROR, "BN_set_word failed");
01077         LogError();
01078         if(prime) BN_free(prime);
01079         if(rsa_key) RSA_free(rsa_key);
01080         return false;
01081       }
01082     }
01083     else {
01084       CredentialLogger.msg(ERROR, "BN_new || RSA_new failed");
01085       LogError();
01086       if(prime) BN_free(prime);
01087       if(rsa_key) RSA_free(rsa_key);
01088       return false;
01089     }
01090     if(prime) BN_free(prime);
01091 #endif
01092 
01093     X509_REQ *req = NULL;
01094     CredentialLogger.msg(VERBOSE, "Created RSA key, proceeding with request");
01095     pkey = EVP_PKEY_new();
01096 
01097     if (pkey) {
01098       if (rsa_key) {
01099         CredentialLogger.msg(VERBOSE, "pkey and rsa_key exist!");
01100         if (EVP_PKEY_set1_RSA(pkey, rsa_key)) {
01101           req = X509_REQ_new();
01102           CredentialLogger.msg(VERBOSE, "Generate new X509 request!");
01103           if(req) {
01104             if (X509_REQ_set_version(req,3L)) {
01105               X509_NAME *name = NULL;
01106               unsigned long chtype = MBSTRING_ASC;  //TODO
01107               name = parse_name((char*)(dn.c_str()), chtype, 0);
01108               CredentialLogger.msg(VERBOSE, "Setting subject name!");
01109 
01110               X509_REQ_set_subject_name(req, name);
01111               X509_NAME_free(name);
01112 
01113               if(X509_REQ_set_pubkey(req,pkey)) {
01114                 if(X509_REQ_sign(req,pkey,digest)) {
01115                   if(!(PEM_write_bio_X509_REQ(reqbio,req))){
01116                     CredentialLogger.msg(ERROR, "PEM_write_bio_X509_REQ failed");
01117                     LogError();
01118                     res = false;
01119                   }
01120                   else {
01121                     rsa_key_ = rsa_key;
01122                     rsa_key = NULL;
01123                     pkey_ = pkey;
01124                     pkey = NULL;
01125                     req_ = req;
01126                     res = true;
01127                   }
01128                 }
01129               }
01130             }
01131           }
01132         }
01133       }
01134     }
01135 
01136     req_ = req;
01137     return res;
01138   }
01139 
01140   bool Credential::GenerateEECRequest(std::string &req_content, std::string &key_content, std::string dn) {
01141     BIO *req_out = BIO_new(BIO_s_mem());
01142     BIO *key_out = BIO_new(BIO_s_mem());
01143     if(!req_out || !key_out) {
01144       CredentialLogger.msg(ERROR, "Can not create BIO for request");
01145       LogError(); return false;
01146     }
01147 
01148     if(GenerateEECRequest(req_out, key_out,dn)) {
01149       int l = 0;
01150       char s[256];
01151 
01152       while ((l = BIO_read(req_out,s,sizeof(s))) >= 0) {
01153         req_content.append(s,l);
01154       }
01155 
01156       l = 0;
01157 
01158       while ((l=BIO_read(key_out,s,sizeof(s))) >= 0) {
01159         key_content.append(s,l);
01160       }
01161     } else {
01162       CredentialLogger.msg(ERROR, "Failed to write request into string");
01163       BIO_free_all(req_out);
01164       BIO_free_all(key_out);
01165       return false;
01166     }
01167 
01168     BIO_free_all(req_out);
01169     BIO_free_all(key_out);
01170     return true;
01171   }
01172 
01173   bool Credential::GenerateEECRequest(const char* req_filename, const char* key_filename, std::string dn) {
01174     BIO *req_out = BIO_new(BIO_s_file());
01175     BIO *key_out = BIO_new(BIO_s_file());
01176     if(!req_out || !key_out) {
01177       CredentialLogger.msg(ERROR, "Can not create BIO for request");
01178       return false;
01179     }
01180     if (!(BIO_write_filename(req_out, (char*)req_filename))) {
01181       CredentialLogger.msg(ERROR, "Can not set writable file for request BIO");
01182       BIO_free_all(req_out); return false;
01183     }
01184 
01185     if (!(BIO_write_filename(key_out, (char*)key_filename))) {
01186       CredentialLogger.msg(ERROR, "Can not set writable file for request BIO");
01187       BIO_free_all(key_out);
01188       return false;
01189     }
01190 
01191     if(GenerateEECRequest(req_out,key_out, dn)) {
01192       CredentialLogger.msg(INFO, "Wrote request into a file");
01193     } else {
01194       CredentialLogger.msg(ERROR, "Failed to write request into a file");
01195       BIO_free_all(req_out);
01196       BIO_free_all(key_out);
01197       return false;
01198     }
01199 
01200     BIO_free_all(req_out);
01201     BIO_free_all(key_out);
01202     return true;
01203   }
01204 
01205   //TODO: self request/sign proxy
01206 
01207   bool Credential::GenerateRequest(BIO* reqbio, bool if_der){
01208     bool res = false;
01209     RSA* rsa_key = NULL;
01210     int keybits = keybits_;
01211     const EVP_MD *digest = signing_alg_;
01212     EVP_PKEY* pkey;
01213 
01214     if(pkey_) { CredentialLogger.msg(ERROR, "The credential's private key has already been initialized"); return false; };
01215 
01216 #ifdef HAVE_OPENSSL_OLDRSA
01217     unsigned long prime = RSA_F4;
01218     rsa_key = RSA_generate_key(keybits, prime, keygen_cb, NULL);
01219     if(!rsa_key) {
01220       CredentialLogger.msg(ERROR, "RSA_generate_key failed");
01221       LogError();
01222       if(rsa_key) RSA_free(rsa_key);
01223       return false;
01224     }
01225 #else
01226     BN_GENCB cb;
01227     BIGNUM *prime = BN_new();
01228     rsa_key = RSA_new();
01229 
01230     BN_GENCB_set(&cb,&keygen_cb,NULL);
01231     if(prime && rsa_key) {
01232       if(BN_set_word(prime,RSA_F4)) {
01233         if(RSA_generate_key_ex(rsa_key, keybits, prime, &cb) != 1) {
01234           CredentialLogger.msg(ERROR, "RSA_generate_key_ex failed");
01235           LogError();
01236           if(prime) BN_free(prime);
01237           return false;
01238         }
01239       }
01240       else{
01241         CredentialLogger.msg(ERROR, "BN_set_word failed");
01242         LogError();
01243         if(prime) BN_free(prime);
01244         if(rsa_key) RSA_free(rsa_key);
01245         return false; }
01246     }
01247     else {
01248       CredentialLogger.msg(ERROR, "BN_new || RSA_new failed");
01249       LogError();
01250       if(prime) BN_free(prime);
01251       if(rsa_key) RSA_free(rsa_key);
01252       return false;
01253     }
01254     if(prime) BN_free(prime);
01255 #endif
01256 
01257     X509_REQ *req = NULL;
01258     pkey = EVP_PKEY_new();
01259     if(pkey){
01260       if(rsa_key) {
01261         if(EVP_PKEY_set1_RSA(pkey, rsa_key)) {
01262           req = X509_REQ_new();
01263           if(req) {
01264             if(X509_REQ_set_version(req,2L)) {
01265               //set the DN
01266               X509_NAME* name = NULL;
01267               X509_NAME_ENTRY* entry = NULL;
01268               if(cert_) { //self-sign, copy the X509_NAME
01269                 if ((name = X509_NAME_dup(X509_get_subject_name(cert_))) == NULL) {
01270                   CredentialLogger.msg(ERROR, "Can not duplicate the subject name for the self-signing proxy certificate request");
01271                   LogError(); res = false;
01272                   if(pkey) EVP_PKEY_free(pkey);
01273                   if(rsa_key) RSA_free(rsa_key);
01274                   return res;
01275                 }
01276               }
01277               else { name = X509_NAME_new();}
01278               if((entry = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, V_ASN1_APP_CHOOSE,
01279                           (unsigned char *) "NULL SUBJECT NAME ENTRY", -1)) == NULL) {
01280                 CredentialLogger.msg(ERROR, "Can not create a new X509_NAME_ENTRY for the proxy certificate request");
01281                 LogError(); res = false; X509_NAME_free(name);
01282                 if(pkey) EVP_PKEY_free(pkey);
01283                 if(rsa_key) RSA_free(rsa_key);
01284                 return res;
01285               }
01286               X509_NAME_add_entry(name, entry, X509_NAME_entry_count(name), 0);
01287               X509_REQ_set_subject_name(req,name);
01288               X509_NAME_free(name); name = NULL;
01289               if(entry) { X509_NAME_ENTRY_free(entry); entry = NULL; }
01290 
01291               if(cert_type_ != CERT_TYPE_EEC) {
01292 
01293                 // set the default PROXYCERTINFO extension
01294                 std::string certinfo_sn;
01295                 X509_EXTENSION* ext = NULL;
01296                 if (CERT_IS_RFC_PROXY(cert_type_)) certinfo_sn = "PROXYCERTINFO_V4";
01297                 else certinfo_sn = "PROXYCERTINFO_V3";
01298                 //if(proxy_cert_info_->version == 3)
01299 
01300                 if(!(certinfo_sn.empty())) {
01301                   const X509V3_EXT_METHOD*  ext_method = NULL;
01302                   unsigned char* data = NULL;
01303                   int length;
01304                   ext_method = X509V3_EXT_get_nid(OBJ_sn2nid(certinfo_sn.c_str()));
01305                   if(ext_method == NULL) {
01306                     CredentialLogger.msg(ERROR, "Can get X509V3_EXT_METHOD for %s",certinfo_sn.c_str());
01307                     LogError(); return false;
01308                   }
01309                   length = ext_method->i2d(proxy_cert_info_, NULL);
01310                   if(length < 0) {
01311                     CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
01312                     LogError();
01313                   }
01314                   else {
01315                     data = (unsigned char*) malloc(length);
01316 
01317                     unsigned char* derdata;
01318                     derdata = data;
01319                     length = ext_method->i2d(proxy_cert_info_,  &derdata);
01320 
01321                     if(length < 0) {
01322                       CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
01323                       free(data); data = NULL; LogError();
01324                     }
01325                   }
01326                   if(data) {
01327                     std::string ext_data((char*)data, length); free(data);
01328                     std::string certinfo_oid = PROXYCERTINFO_OPENSSL;
01329                     ext = CreateExtension(certinfo_oid, ext_data, 1);
01330                   }
01331                 }
01332 
01333                 if(ext) {
01334                   STACK_OF(X509_EXTENSION)* extensions;
01335                   extensions = sk_X509_EXTENSION_new_null();
01336                   sk_X509_EXTENSION_push(extensions, ext);
01337                   X509_REQ_add_extensions(req, extensions);
01338                   sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free);
01339                 }
01340 
01341               }
01342 
01343               if(X509_REQ_set_pubkey(req,pkey)) {
01344                 if(X509_REQ_sign(req,pkey,digest)  != 0) {
01345                   if(if_der == false) {
01346                     if(!(PEM_write_bio_X509_REQ(reqbio,req))){
01347                       CredentialLogger.msg(ERROR, "PEM_write_bio_X509_REQ failed");
01348                       LogError(); res = false;
01349                     }
01350                     else { rsa_key_ = rsa_key; rsa_key = NULL; pkey_ = pkey; pkey = NULL; res = true; }
01351                   }
01352                   else {
01353                     if(!(i2d_X509_REQ_bio(reqbio,req))){
01354                       CredentialLogger.msg(ERROR, "Can't convert X509 request from internal to DER encoded format");
01355                       LogError(); res = false;
01356                     }
01357                     else { rsa_key_ = rsa_key; rsa_key = NULL; pkey_ = pkey; pkey = NULL; res = true; }
01358                   }
01359                 }
01360               }
01361             }
01362             //X509_REQ_free(req);
01363           }
01364           else { CredentialLogger.msg(ERROR, "Can not generate X509 request"); LogError(); res = false; }
01365         }
01366         else { CredentialLogger.msg(ERROR, "Can not set private key"); LogError(); res = false;}
01367       }
01368     }
01369 
01370     req_ = req;
01371     return res;
01372   }
01373 
01374   bool Credential::GenerateRequest(std::string &content, bool if_der) {
01375     BIO *out = BIO_new(BIO_s_mem());
01376     if(!out) {
01377       CredentialLogger.msg(ERROR, "Can not create BIO for request");
01378       LogError(); return false;
01379     }
01380 
01381     if(GenerateRequest(out,if_der)) {
01382       for(;;) {
01383         char s[256];
01384         int l = BIO_read(out,s,sizeof(s));
01385         if(l <= 0) break;
01386         content.append(s,l);
01387       }
01388     }
01389 
01390     BIO_free_all(out);
01391     return true;
01392   }
01393 
01394   bool Credential::GenerateRequest(const char* filename, bool if_der) {
01395     BIO *out = BIO_new(BIO_s_file());
01396     if(!out) {
01397       CredentialLogger.msg(ERROR, "Can not create BIO for request");
01398       LogError(); return false;
01399     }
01400     if (!(BIO_write_filename(out, (char*)filename))) {
01401       CredentialLogger.msg(ERROR, "Can not set writable file for request BIO");
01402       LogError(); BIO_free_all(out); return false;
01403     }
01404 
01405     if(GenerateRequest(out,if_der)) {
01406       CredentialLogger.msg(INFO, "Wrote request into a file");
01407     }
01408     else {
01409       CredentialLogger.msg(ERROR, "Failed to write request into a file");
01410       BIO_free_all(out); return false;
01411     }
01412 
01413     BIO_free_all(out);
01414     return true;
01415   }
01416 
01417   bool Credential::OutputPrivatekey(std::string &content, bool encryption, const std::string& passphrase) {
01418     BIO *out = BIO_new(BIO_s_mem());
01419     EVP_CIPHER *enc = NULL;
01420     if(!out) return false;
01421     if(rsa_key_ != NULL) {
01422       if(!encryption) {
01423         if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0,NULL,NULL)) {
01424           BIO_free_all(out); return false;
01425         }
01426       }
01427       else {
01428         enc = (EVP_CIPHER*)EVP_des_ede3_cbc();
01429 #if 0
01430         std::string prompt;
01431         prompt = "Enter passphrase to encrypt the PEM key file: ";
01432         if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0,passwordcb,
01433           (passphrase.empty())?NULL:(void*)(passphrase.c_str()))) {
01434           BIO_free_all(out); return false;
01435         }
01436 #endif
01437         PW_CB_DATA cb_data;
01438         cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
01439         cb_data.prompt_info = NULL;
01440         if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0, (pem_password_cb *)passwordcb,&cb_data)) {
01441           BIO_free_all(out); return false;
01442         }
01443       }
01444     }
01445     else if(pkey_ != NULL) {
01446       if(!encryption) {
01447         if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0,NULL,NULL)) {
01448           BIO_free_all(out); return false;
01449         }
01450       }
01451       else {
01452         enc = (EVP_CIPHER*)EVP_des_ede3_cbc();
01453 #if 0
01454         std::string prompt;
01455         prompt = "Enter passphrase to encrypt the PEM key file: ";
01456         if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0,passwordcb,
01457           (passphrase.empty())?NULL:(void*)(passphrase.c_str()))) {
01458           BIO_free_all(out); return false;
01459         }
01460 #endif
01461         PW_CB_DATA cb_data;
01462         cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
01463         cb_data.prompt_info = NULL;
01464         if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0, (pem_password_cb *)passwordcb,&cb_data)) {
01465           BIO_free_all(out); return false;
01466         }
01467       }
01468     }
01469     else {
01470       CredentialLogger.msg(ERROR, "Failed to get private key");
01471       BIO_free_all(out); return false;
01472     }
01473 
01474     for(;;) {
01475       char s[256];
01476       int l = BIO_read(out,s,sizeof(s));
01477       if(l <= 0) break;
01478       content.append(s,l);
01479     }
01480     BIO_free_all(out);
01481     return true;
01482   }
01483 
01484   bool Credential::OutputPublickey(std::string &content) {
01485     BIO *out = BIO_new(BIO_s_mem());
01486     if(!out) return false;
01487     if(rsa_key_ != NULL) {
01488       if(!PEM_write_bio_RSAPublicKey(out,rsa_key_)) {
01489         CredentialLogger.msg(ERROR, "Failed to get public key from RSA object");
01490         BIO_free_all(out); return false;
01491       };
01492     }
01493     else if(cert_ != NULL) {
01494       EVP_PKEY *pkey = NULL;
01495       pkey = X509_get_pubkey(cert_);
01496       if(pkey == NULL) {
01497         CredentialLogger.msg(ERROR, "Failed to get public key from X509 object");
01498         BIO_free_all(out); return false;
01499       };
01500       PEM_write_bio_PUBKEY(out, pkey);
01501       EVP_PKEY_free(pkey);
01502     }
01503     else {
01504       CredentialLogger.msg(ERROR, "Failed to get public key");
01505       BIO_free_all(out); return false;
01506     }
01507 
01508     for(;;) {
01509       char s[256];
01510       int l = BIO_read(out,s,sizeof(s));
01511       if(l <= 0) break;
01512       content.append(s,l);
01513     }
01514     BIO_free_all(out);
01515     return true;
01516   }
01517 
01518   bool Credential::OutputCertificate(std::string &content, bool if_der) {
01519     BIO *out = BIO_new(BIO_s_mem());
01520     if(!out) return false;
01521     if(if_der == false) {
01522       if(!PEM_write_bio_X509(out,cert_)) { BIO_free_all(out); return false; };
01523     }
01524     else {
01525       if(!i2d_X509_bio(out,cert_)) { BIO_free_all(out); return false; };
01526     }
01527 
01528     for(;;) {
01529       char s[256];
01530       int l = BIO_read(out,s,sizeof(s));
01531       if(l <= 0) break;
01532       content.append(s,l);
01533     }
01534     BIO_free_all(out);
01535     return true;
01536   }
01537 
01538   bool Credential::OutputCertificateChain(std::string &content, bool if_der) {
01539     BIO *out = BIO_new(BIO_s_mem());
01540     if(!out) return false;
01541     X509 *cert;
01542     CredentialLogger.msg(DEBUG, "Certiticate chain number %d",sk_X509_num(cert_chain_));
01543     //std::cout<<"+++++ cert chain number: "<<sk_X509_num(cert_chain_)<<std::endl;
01544 
01545     //Out put the cert chain. After the verification the cert_chain_
01546     //will include the CA certificate and the certificate (which
01547     //need to be verified here) itself.
01548     //Those two certificates are excluded when outputing
01549     for (int n = 1; n < sk_X509_num(cert_chain_) - 1 ; n++) {
01550       cert = sk_X509_value(cert_chain_, n);
01551       if(if_der == false) {
01552         if(!PEM_write_bio_X509(out,cert)) { BIO_free_all(out); return false; };
01553       }
01554       else {
01555         if(!i2d_X509_bio(out,cert)) { BIO_free_all(out); return false; };
01556       }
01557 
01558       for(;;) {
01559         char s[256];
01560         int l = BIO_read(out,s,sizeof(s));
01561         if(l <= 0) break;
01562         content.append(s,l);
01563       }
01564     }
01565     BIO_free_all(out);
01566     return true;
01567   }
01568 
01569   //Inquire the input request bio to get PROXYCERTINFO, certType
01570   bool Credential::InquireRequest(BIO* reqbio, bool if_eec, bool if_der){
01571     bool res = false;
01572     if(reqbio == NULL) { CredentialLogger.msg(ERROR, "NULL BIO passed to InquireRequest"); return false; }
01573     if(req_) {X509_REQ_free(req_); req_ = NULL; }
01574     if((if_der == false) && (!(PEM_read_bio_X509_REQ(reqbio, &req_, NULL, NULL)))) {
01575       CredentialLogger.msg(ERROR, "PEM_read_bio_X509_REQ failed");
01576       LogError(); return false;
01577     }
01578     else if((if_der == true) && (!(d2i_X509_REQ_bio(reqbio, &req_)))) {
01579       CredentialLogger.msg(ERROR, "d2i_X509_REQ_bio failed");
01580       LogError(); return false;
01581     }
01582 
01583     STACK_OF(X509_EXTENSION)* req_extensions = NULL;
01584     X509_EXTENSION* ext;
01585     PROXYPOLICY*  policy = NULL;
01586     ASN1_OBJECT*  policy_lang = NULL;
01587     ASN1_OBJECT*  extension_oid = NULL;
01588     int certinfo_old_NID, certinfo_NID, nid = NID_undef;
01589     int i;
01590 
01591     //Get the PROXYCERTINFO from request' extension
01592     req_extensions = X509_REQ_get_extensions(req_);
01593     certinfo_old_NID = OBJ_txt2nid(PROXYCERTINFO_V3);
01594     certinfo_NID = OBJ_txt2nid(PROXYCERTINFO_V4);
01595     for(i=0;i<sk_X509_EXTENSION_num(req_extensions);i++) {
01596       ext = sk_X509_EXTENSION_value(req_extensions,i);
01597       extension_oid = X509_EXTENSION_get_object(ext);
01598       nid = OBJ_obj2nid(extension_oid);
01599       if((nid != 0) && (nid == certinfo_old_NID || nid == certinfo_NID)) {
01600         if(proxy_cert_info_) {
01601           PROXYCERTINFO_free(proxy_cert_info_);
01602           proxy_cert_info_ = NULL;
01603         }
01604         if((proxy_cert_info_ = (PROXYCERTINFO*)X509V3_EXT_d2i(ext)) == NULL) {
01605            CredentialLogger.msg(ERROR, "Can not convert DER encoded PROXYCERTINFO extension to internal format");
01606            LogError(); goto err;
01607         }
01608         break;
01609       }
01610     }
01611 
01612     if(proxy_cert_info_) {
01613       if((policy = PROXYCERTINFO_get_proxypolicy(proxy_cert_info_)) == NULL) {
01614         CredentialLogger.msg(ERROR, "Can not get policy from PROXYCERTINFO extension");
01615         LogError(); goto err;
01616       }
01617       if((policy_lang = PROXYPOLICY_get_policy_language(policy)) == NULL) {
01618         CredentialLogger.msg(ERROR, "Can not get policy language from PROXYCERTINFO extension");
01619         LogError(); goto err;
01620       }
01621       int policy_nid = OBJ_obj2nid(policy_lang);
01622       if((nid != 0) && (nid == certinfo_old_NID)) {
01623         if(policy_nid == OBJ_txt2nid(IMPERSONATION_PROXY_OID)) { cert_type_= CERT_TYPE_GSI_3_IMPERSONATION_PROXY; }
01624         else if(policy_nid == OBJ_txt2nid(INDEPENDENT_PROXY_OID)) { cert_type_ = CERT_TYPE_GSI_3_INDEPENDENT_PROXY; }
01625         else if(policy_nid == OBJ_txt2nid(LIMITED_PROXY_OID)) { cert_type_ = CERT_TYPE_GSI_3_LIMITED_PROXY; }
01626         else { cert_type_ = CERT_TYPE_GSI_3_RESTRICTED_PROXY; }
01627       }
01628       else {
01629         if(policy_nid == OBJ_txt2nid(IMPERSONATION_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_IMPERSONATION_PROXY; }
01630         else if(policy_nid == OBJ_txt2nid(INDEPENDENT_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_INDEPENDENT_PROXY; }
01631         else if(policy_nid == OBJ_txt2nid(ANYLANGUAGE_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_ANYLANGUAGE_PROXY; }
01632         else if(policy_nid == OBJ_txt2nid(LIMITED_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_LIMITED_PROXY; }
01633         else { cert_type_ = CERT_TYPE_RFC_RESTRICTED_PROXY; }
01634       }
01635     }
01636     //If can not find proxy_cert_info, depend on the parameters to distinguish the type: if
01637     //it is not eec request, then treat it as RFC proxy request
01638     else if(if_eec == false) { cert_type_ =  CERT_TYPE_RFC_INDEPENDENT_PROXY; } //CERT_TYPE_GSI_2_PROXY; }
01639     else { cert_type_ = CERT_TYPE_EEC; }
01640 
01641     CredentialLogger.msg(DEBUG,"Cert Type: %d",cert_type_);
01642 
01643     res = true;
01644 
01645 err:
01646     if(req_extensions != NULL) { sk_X509_EXTENSION_pop_free(req_extensions, X509_EXTENSION_free); }
01647 
01648     return res;
01649   }
01650 
01651   bool Credential::InquireRequest(std::string &content, bool if_eec, bool if_der) {
01652     BIO *in;
01653     if(!(in = BIO_new_mem_buf((void*)(content.c_str()), content.length()))) {
01654       CredentialLogger.msg(ERROR, "Can not create BIO for parsing request");
01655       LogError(); return false;
01656     }
01657 
01658     if(InquireRequest(in,if_eec,if_der)) {
01659       CredentialLogger.msg(INFO, "Read request from a string");
01660     }
01661     else {
01662       CredentialLogger.msg(ERROR, "Failed to read request from a string");
01663       BIO_free_all(in); return false;
01664     }
01665 
01666     BIO_free_all(in);
01667     return true;
01668   }
01669 
01670   bool Credential::InquireRequest(const char* filename, bool if_eec, bool if_der) {
01671     BIO *in = BIO_new(BIO_s_file());
01672     if(!in) {
01673       CredentialLogger.msg(ERROR, "Can not create BIO for parsing request");
01674       LogError(); return false;
01675     }
01676     if (!(BIO_read_filename(in, (char*)filename))) {
01677       CredentialLogger.msg(ERROR, "Can not set readable file for request BIO");
01678       LogError(); BIO_free_all(in); return false;
01679     }
01680 
01681     if(InquireRequest(in,if_eec,if_der)) {
01682       CredentialLogger.msg(INFO, "Read request from a file");
01683     }
01684     else {
01685       CredentialLogger.msg(ERROR, "Failed to read request from a file");
01686       BIO_free_all(in); return false;
01687     }
01688 
01689     BIO_free_all(in);
01690     return true;
01691   }
01692 
01693   bool Credential::SetProxyPeriod(X509* tosign, X509* issuer, Time& start, Period& lifetime) {
01694     ASN1_UTCTIME* notBefore = NULL;
01695     ASN1_UTCTIME* notAfter = NULL;
01696     time_t t1 = start.GetTime();
01697     Time tmp = start + lifetime;
01698     time_t t2 = tmp.GetTime();
01699 
01700     //Set "notBefore"
01701     if( X509_cmp_time(X509_get_notBefore(issuer), &t1) < 0) {
01702       X509_time_adj(X509_get_notBefore(tosign), 0L, &t1);
01703     }
01704     else {
01705       X509_set_notBefore(tosign, X509_get_notBefore(issuer));
01706     }
01707 
01708     //Set "not After"
01709 #ifdef WIN32  //Different process here for Win, because X509_cmp_time always return 0 on Win when the second calling, which is not as expected
01710     ASN1_UTCTIME*  atime = X509_get_notAfter(issuer);
01711     Time end = asn1_to_utctime(atime);
01712     if(Time(t2) < end) {
01713       X509_time_adj(X509_get_notAfter(tosign), 0L, &t2);
01714     }
01715     else {
01716       t2 = end.GetTime();
01717       X509_time_adj(X509_get_notAfter(tosign), 0L, &t2);
01718     }
01719 #else
01720     if( X509_cmp_time(X509_get_notAfter(issuer), &t2) > 0) {
01721       X509_time_adj(X509_get_notAfter(tosign), 0L, &t2);
01722     }
01723     else {
01724       X509_set_notAfter(tosign, X509_get_notAfter(issuer));
01725     }
01726 #endif
01727 
01728     return true;
01729   }
01730 
01731   EVP_PKEY* Credential::GetPrivKey(void){
01732     EVP_PKEY* key = NULL;
01733     BIO*  bio = NULL;
01734     int length;
01735     bio = BIO_new(BIO_s_mem());
01736     if(pkey_ == NULL) {
01737       CredentialLogger.msg(ERROR, "Private key of the credential object is NULL");
01738       BIO_free(bio); return NULL;
01739     }
01740     length = i2d_PrivateKey_bio(bio, pkey_);
01741     if(length <= 0) {
01742       CredentialLogger.msg(ERROR, "Can not convert private key to DER format");
01743       LogError(); BIO_free(bio); return NULL;
01744     }
01745     key = d2i_PrivateKey_bio(bio, NULL);
01746     BIO_free(bio);
01747 
01748     return key;
01749   }
01750 
01751   EVP_PKEY* Credential::GetPubKey(void){
01752     EVP_PKEY* key = NULL;
01753     key = X509_get_pubkey(cert_);
01754     return key;
01755   }
01756 
01757   X509* Credential::GetCert(void) {
01758     X509* cert = NULL;
01759     if(cert_) cert = X509_dup(cert_);
01760     return cert;
01761   }
01762 
01763   STACK_OF(X509)* Credential::GetCertChain(void) {
01764     STACK_OF(X509)* chain = NULL;
01765     chain = sk_X509_new_null();
01766     //Return the cert chain (not including this certificate itself)
01767     for (int i=1; i < sk_X509_num(cert_chain_)-1; i++) {
01768       X509* tmp = X509_dup(sk_X509_value(cert_chain_,i));
01769       sk_X509_insert(chain, tmp, i);
01770     }
01771     return chain;
01772   }
01773 
01774   int Credential::GetCertNumofChain(void) {
01775     //Return the number of certificates
01776     //in the issuer chain
01777     return sk_X509_num(cert_chain_) - 2;
01778   }
01779 
01780   bool Credential::AddExtension(std::string name, std::string data, bool crit) {
01781     X509_EXTENSION* ext = NULL;
01782     ext = CreateExtension(name, data, crit);
01783     if(ext && sk_X509_EXTENSION_push(extensions_, ext)) return true;
01784     return false;
01785   }
01786 
01787   bool Credential::AddExtension(std::string name, char** binary, bool) {
01788     X509_EXTENSION* ext = NULL;
01789     if(binary == NULL) return false;
01790     ext = X509V3_EXT_conf_nid(NULL, NULL, OBJ_txt2nid((char*)(name.c_str())), (char*)binary);
01791     if(ext && sk_X509_EXTENSION_push(extensions_, ext)) return true;
01792     return false;
01793   }
01794 
01795   bool Credential::SignRequestAssistant(Credential* proxy, EVP_PKEY* req_pubkey, X509** tosign){
01796 
01797     bool res = false;
01798     X509* issuer = NULL;
01799 
01800     X509_NAME* subject_name = NULL;
01801     X509_NAME_ENTRY* name_entry = NULL;
01802 
01803     *tosign = NULL;
01804     char* CN_name = NULL;
01805     ASN1_INTEGER* serial_number = NULL;
01806     unsigned char* certinfo_data = NULL;
01807     X509_EXTENSION* certinfo_ext = NULL;
01808     X509_EXTENSION* ext = NULL;
01809     int certinfo_NID = NID_undef;
01810 
01811     if(cert_ == NULL) {
01812       CredentialLogger.msg(ERROR, "Credential is not initialized");
01813       goto err;
01814     }
01815     issuer = X509_dup(cert_);
01816     if((*tosign = X509_new()) == NULL) {
01817       CredentialLogger.msg(ERROR, "Failed to initialize X509 structure");
01818       LogError(); goto err;
01819     }
01820 
01821     //TODO: VOMS
01822     if(CERT_IS_GSI_3_PROXY(proxy->cert_type_)) { certinfo_NID = OBJ_txt2nid(PROXYCERTINFO_V3); }
01823     else if(CERT_IS_RFC_PROXY(proxy->cert_type_)) { certinfo_NID = OBJ_txt2nid(PROXYCERTINFO_V4); }
01824 
01825     if(proxy->cert_type_ == CERT_TYPE_GSI_2_LIMITED_PROXY){
01826       CN_name = const_cast<char*>("limited proxy");
01827       serial_number = M_ASN1_INTEGER_dup(X509_get_serialNumber(issuer));
01828     }
01829     else if(proxy->cert_type_ == CERT_TYPE_GSI_2_PROXY) {
01830       CN_name = const_cast<char*>("proxy");
01831       serial_number = M_ASN1_INTEGER_dup(X509_get_serialNumber(issuer));
01832     }
01833     else if (certinfo_NID != NID_undef) {
01834       unsigned char   md[SHA_DIGEST_LENGTH];
01835       long  sub_hash;
01836       unsigned int   len;
01837       const X509V3_EXT_METHOD* ext_method = NULL;
01838       ext_method = X509V3_EXT_get_nid(certinfo_NID);
01839       if(ext_method == NULL) {
01840         CredentialLogger.msg(ERROR, "Can't get X509V3_EXT_METHOD for %s",OBJ_nid2sn(certinfo_NID));
01841         LogError(); goto err;
01842       }
01843 
01844 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
01845       ASN1_digest((int (*)(void*, unsigned char**))i2d_PUBKEY, EVP_sha1(), (char*)req_pubkey,md,&len);
01846 #else
01847       ASN1_digest((int(*)())i2d_PUBKEY, EVP_sha1(), (char*)req_pubkey,md,&len);
01848 #endif
01849 
01850       sub_hash = md[0] + (md[1] + (md[2] + (md[3] >> 1) * 256) * 256) * 256;
01851 
01852       CN_name = (char*)malloc(sizeof(long)*4 + 1);
01853       snprintf(CN_name, sizeof(long)*4 + 1, "%ld", sub_hash);
01854 
01855       //serial_number = ASN1_INTEGER_new();
01856       //ASN1_INTEGER_set(serial_number, sub_hash);
01857       //Use the serial number in the certificate as the
01858       //serial number in the proxy certificate
01859       serial_number = M_ASN1_INTEGER_dup(X509_get_serialNumber(issuer));
01860 
01861       int length = ext_method->i2d(proxy->proxy_cert_info_, NULL);
01862       if(length < 0) {
01863         CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
01864         LogError();
01865       }
01866       else {certinfo_data = (unsigned char*)malloc(length); }
01867 
01868       unsigned char* derdata; derdata = certinfo_data;
01869       length = ext_method->i2d(proxy->proxy_cert_info_, &derdata);
01870       if(length < 0) {
01871         CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
01872         free(certinfo_data); certinfo_data = NULL; LogError();
01873       }
01874       if(certinfo_data) {
01875         std::string certinfo_string((char*)certinfo_data, length); free(certinfo_data);
01876         certinfo_data = NULL;
01877         std::string NID_txt = PROXYCERTINFO_OPENSSL;
01878         certinfo_ext = CreateExtension(NID_txt, certinfo_string, 1);
01879       }
01880       if(certinfo_ext != NULL) {
01881         //if(!X509_add_ext(*tosign, certinfo_ext, 0)) {
01882         if(!sk_X509_EXTENSION_push(proxy->extensions_, certinfo_ext)) {
01883           CredentialLogger.msg(ERROR, "Can not add X509 extension to proxy cert");
01884           LogError(); goto err;
01885         }
01886       }
01887     }
01888 
01889     int position;
01890 
01891     /* Add any keyUsage and extendedKeyUsage extensions present in the issuer cert */
01892     if((position = X509_get_ext_by_NID(issuer, NID_key_usage, -1)) > -1) {
01893       ASN1_BIT_STRING*   usage;
01894       unsigned char *    ku_data = NULL;
01895       int ku_length;
01896 
01897       if(!(ext = X509_get_ext(issuer, position))) {
01898         CredentialLogger.msg(ERROR, "Can not get extension from issuer certificate");
01899         LogError(); goto err;
01900       }
01901 
01902       if(!(usage = (ASN1_BIT_STRING*)X509_get_ext_d2i(issuer, NID_key_usage, NULL, NULL))) {
01903         CredentialLogger.msg(ERROR, "Can not convert keyUsage struct from DER encoded format");
01904         LogError(); goto err;
01905       }
01906 
01907       /* clear bits specified in draft */
01908       ASN1_BIT_STRING_set_bit(usage, 1, 0); /* Non Repudiation */
01909       ASN1_BIT_STRING_set_bit(usage, 5, 0); /* Certificate Sign */
01910 
01911       ku_length = i2d_ASN1_BIT_STRING(usage, NULL);
01912       if(ku_length < 0) {
01913         CredentialLogger.msg(ERROR, "Can not convert keyUsage struct from internal to DER format");
01914         LogError(); ASN1_BIT_STRING_free(usage); goto err;
01915       }
01916       ku_data = (unsigned char*) malloc(ku_length);
01917 
01918       unsigned char* derdata; derdata = ku_data;
01919       ku_length = i2d_ASN1_BIT_STRING(usage, &derdata);
01920       if(ku_length < 0) {
01921         CredentialLogger.msg(ERROR, "Can not convert keyUsage struct from internal to DER format");
01922         LogError(); ASN1_BIT_STRING_free(usage); free(ku_data); goto err;
01923       }
01924       ASN1_BIT_STRING_free(usage);
01925       if(ku_data) {
01926         std::string ku_string((char*)ku_data, ku_length); free(ku_data); ku_data = NULL;
01927         std::string name = "keyUsage";
01928         ext = CreateExtension(name, ku_string, 1);
01929       }
01930       if(ext != NULL) {
01931         //if(!X509_add_ext(*tosign, ext, 0)) {
01932         if(!sk_X509_EXTENSION_push(proxy->extensions_, ext)) {
01933           CredentialLogger.msg(ERROR, "Can not add X509 extension to proxy cert");
01934           LogError(); X509_EXTENSION_free(ext); ext = NULL; goto err;
01935         }
01936       }
01937     }
01938 
01939     if((position = X509_get_ext_by_NID(issuer, NID_ext_key_usage, -1)) > -1) {
01940       if(!(ext = X509_get_ext(issuer, position))) {
01941         CredentialLogger.msg(ERROR, "Can not get extended KeyUsage extension from issuer certificate");
01942         LogError(); goto err;
01943       }
01944 
01945       ext = X509_EXTENSION_dup(ext);
01946       if(ext == NULL) {
01947         CredentialLogger.msg(ERROR, "Can not copy extended KeyUsage extension");
01948         LogError(); goto err;
01949       }
01950 
01951       //if(!X509_add_ext(*tosign, ext, 0)) {
01952       if(!sk_X509_EXTENSION_push(proxy->extensions_, ext)) {
01953         CredentialLogger.msg(ERROR, "Can not add X509 extended KeyUsage extension to new proxy certificate");
01954         LogError(); X509_EXTENSION_free(ext); ext = NULL; goto err;
01955       }
01956     }
01957 
01958     /* Create proxy subject name */
01959     if((subject_name = X509_NAME_dup(X509_get_subject_name(issuer))) == NULL) {
01960       CredentialLogger.msg(ERROR, "Can not copy the subject name from issuer for proxy certificate");
01961       goto err;
01962     }
01963     if((name_entry = X509_NAME_ENTRY_create_by_NID(&name_entry, NID_commonName, V_ASN1_APP_CHOOSE,
01964                                      (unsigned char *) CN_name, -1)) == NULL) {
01965       CredentialLogger.msg(ERROR, "Can not create name entry CN for proxy certificate");
01966       LogError(); X509_NAME_free(subject_name); goto err;
01967     }
01968     if(!X509_NAME_add_entry(subject_name, name_entry, X509_NAME_entry_count(subject_name), 0) ||
01969        !X509_set_subject_name(*tosign, subject_name)) {
01970       CredentialLogger.msg(ERROR, "Can not set CN in proxy certificate");
01971       LogError(); X509_NAME_ENTRY_free(name_entry); goto err;
01972     }
01973 
01974     X509_NAME_free(subject_name); subject_name = NULL;
01975     X509_NAME_ENTRY_free(name_entry);
01976 
01977     if(!X509_set_issuer_name(*tosign, X509_get_subject_name(issuer))) {
01978       CredentialLogger.msg(ERROR, "Can not set issuer's subject for proxy certificate");
01979       LogError(); goto err;
01980     }
01981 
01982     if(!X509_set_version(*tosign, 2L)) {
01983       CredentialLogger.msg(ERROR, "Can not set version number for proxy certificate");
01984       LogError(); goto err;
01985     }
01986 
01987     if(!X509_set_serialNumber(*tosign, serial_number)) {
01988       CredentialLogger.msg(ERROR, "Can not set serial number for proxy certificate");
01989       LogError(); goto err;
01990     }
01991 
01992     if(!SetProxyPeriod(*tosign, issuer, proxy->start_, proxy->lifetime_)) {
01993       CredentialLogger.msg(ERROR, "Can not set the lifetime for proxy certificate"); goto err;
01994     }
01995 
01996     if(!X509_set_pubkey(*tosign, req_pubkey)) {
01997       CredentialLogger.msg(ERROR, "Can not set pubkey for proxy certificate");
01998       LogError(); goto err;
01999     }
02000 
02001     res = true;
02002 
02003 err:
02004     if(issuer) { X509_free(issuer); }
02005     if(res == false && *tosign) { X509_free(*tosign); *tosign = NULL;}
02006     if(certinfo_NID != NID_undef) {
02007       if(serial_number) { ASN1_INTEGER_free(serial_number);}
02008       if(CN_name) { free(CN_name); }
02009     }
02010 
02011     return res;
02012   }
02013 
02014   bool Credential::SignRequest(Credential* proxy, BIO* outputbio, bool if_der){
02015     bool res = false;
02016     if(proxy == NULL) {CredentialLogger.msg(ERROR, "The credential to be signed is NULL"); return false; }
02017     if(proxy->req_ == NULL) {CredentialLogger.msg(ERROR, "The credential to be signed contains no request"); return false; }
02018     if(outputbio == NULL) { CredentialLogger.msg(ERROR, "The BIO for output is NULL"); return false; }
02019 
02020     EVP_PKEY* issuer_priv = NULL;
02021     EVP_PKEY* issuer_pub = NULL;
02022     X509*  proxy_cert = NULL;
02023     X509_CINF*  cert_info = NULL;
02024     X509_EXTENSION* ext = NULL;
02025     EVP_PKEY* req_pubkey = NULL;
02026     req_pubkey = X509_REQ_get_pubkey(proxy->req_);
02027 
02028     if(!req_pubkey) {
02029       CredentialLogger.msg(ERROR, "Error when extracting public key from request");
02030       LogError(); return false;
02031     }
02032 
02033     if(!X509_REQ_verify(proxy->req_, req_pubkey)){
02034       CredentialLogger.msg(ERROR,"Failed to verify the request"); LogError(); goto err;
02035     }
02036 
02037     if(!SignRequestAssistant(proxy, req_pubkey, &proxy_cert)) {
02038       CredentialLogger.msg(ERROR,"Failed to add issuer's extension into proxy");
02039       LogError(); goto err;
02040     }
02041 
02042     /*Add the extensions which has just been added by application,
02043      * into the proxy_cert which will be signed soon.
02044      * Note here we suppose it is the signer who will add the
02045      * extension to to-signed proxy and then sign it;
02046      * it also could be the request who add the extension and put
02047      * it inside X509 request' extension, but here the situation
02048      * has not been considered for now
02049      */
02050     cert_info = proxy_cert->cert_info;
02051     if (cert_info->extensions != NULL) {
02052       sk_X509_EXTENSION_pop_free(cert_info->extensions, X509_EXTENSION_free);
02053     }
02054 
02055     /*Set the serialNumber*/
02056     //cert_info->serialNumber = M_ASN1_INTEGER_dup(X509_get_serialNumber(proxy_cert));;
02057 
02058     /*Set the extension*/
02059     if(sk_X509_EXTENSION_num(proxy->extensions_)) {
02060       cert_info->extensions = sk_X509_EXTENSION_new_null();
02061     }
02062 
02063     for (int i=0; i<sk_X509_EXTENSION_num(proxy->extensions_); i++) {
02064       //ext = X509_EXTENSION_dup(sk_X509_EXTENSION_value(proxy->extensions_, i));
02065       ext = sk_X509_EXTENSION_value(proxy->extensions_, i);
02066       if (ext == NULL) {
02067         //CredentialLogger.msg(ERROR,"Failed to duplicate extension"); LogError(); goto err;
02068         CredentialLogger.msg(ERROR,"Failed to find extension"); LogError(); goto err;
02069       }
02070 
02071       if (!sk_X509_EXTENSION_push(cert_info->extensions, ext)) {
02072         CredentialLogger.msg(ERROR,"Failed to add extension into proxy"); LogError(); goto err;
02073       }
02074     }
02075 
02076     /*Clean extensions attached to "proxy" after it has been linked into
02077     to-signed certificate*/
02078     sk_X509_EXTENSION_zero(proxy->extensions_);
02079 
02080     /* Now sign the new certificate */
02081     if(!(issuer_priv = GetPrivKey())) {
02082       CredentialLogger.msg(ERROR, "Can not get the issuer's private key"); goto err;
02083     }
02084 
02085     /* Check whether SHA1 isn't requested as the signing algorithm in the request*/
02086     if(EVP_MD_type(proxy->signing_alg_) != NID_sha1) {
02087       CredentialLogger.msg(ERROR, "The signing algorithm %s is not allowed,it should be SHA1 to sign certificate requests",
02088       OBJ_nid2sn(EVP_MD_type(proxy->signing_alg_)));
02089       goto err;
02090     }
02091 
02092     if(!X509_sign(proxy_cert, issuer_priv, proxy->signing_alg_)) {
02093       CredentialLogger.msg(ERROR, "Failed to sign the proxy certificate"); LogError(); goto err;
02094     }
02095     else CredentialLogger.msg(INFO, "Succeeded to sign the proxy certificate");
02096 
02097     /*Verify the signature, not needed later*/
02098     issuer_pub = GetPubKey();
02099     if((X509_verify(proxy_cert, issuer_pub)) != 1) {
02100       CredentialLogger.msg(ERROR, "Failed to verify the signed certificate"); LogError(); goto err;
02101     }
02102     else CredentialLogger.msg(INFO, "Succeeded to verify the signed certificate");
02103 
02104     /*Output the signed certificate into BIO*/
02105     if(if_der == false) {
02106       if(PEM_write_bio_X509(outputbio, proxy_cert)) {
02107         CredentialLogger.msg(INFO, "Output the proxy certificate"); res = true;
02108       }
02109       else {
02110         CredentialLogger.msg(ERROR, "Can not convert signed proxy cert into PEM format");
02111         LogError();
02112       }
02113     }
02114     else {
02115       if(i2d_X509_bio(outputbio, proxy_cert)) {
02116         CredentialLogger.msg(INFO, "Output the proxy certificate"); res = true;
02117       }
02118       else {
02119         CredentialLogger.msg(ERROR, "Can not convert signed proxy cert into DER format");
02120         LogError();
02121       }
02122     }
02123 
02124 err:
02125     if(issuer_priv) { EVP_PKEY_free(issuer_priv);}
02126     if(proxy_cert) { X509_free(proxy_cert);}
02127     if(req_pubkey) { EVP_PKEY_free(req_pubkey); }
02128     if(issuer_pub) { EVP_PKEY_free(issuer_pub); }
02129     return res;
02130   }
02131 
02132   bool Credential::SignRequest(Credential* proxy, std::string &content, bool if_der) {
02133     BIO *out = BIO_new(BIO_s_mem());
02134     if(!out) {
02135       CredentialLogger.msg(ERROR, "Can not create BIO for signed proxy certificate");
02136       LogError(); return false;
02137     }
02138 
02139     if(SignRequest(proxy, out, if_der)) {
02140       for(;;) {
02141         char s[256];
02142         int l = BIO_read(out,s,sizeof(s));
02143         if(l <= 0) break;
02144         content.append(s,l);
02145       }
02146     } else {
02147       BIO_free_all(out);
02148       return false;
02149     }
02150 
02151     BIO_free_all(out);
02152     return true;
02153   }
02154 
02155   bool Credential::SignRequest(Credential* proxy, const char* filename, bool if_der) {
02156     BIO *out = BIO_new(BIO_s_file());
02157     if(!out) {
02158       CredentialLogger.msg(ERROR, "Can not create BIO for signed proxy certificate");
02159       LogError(); return false;
02160     }
02161     if (!(BIO_write_filename(out, (char*)filename))) {
02162       CredentialLogger.msg(ERROR, "Can not set writable file for signed proxy certificate BIO");
02163       LogError(); BIO_free_all(out); return false;
02164     }
02165 
02166     if(SignRequest(proxy, out, if_der)) {
02167       CredentialLogger.msg(INFO, "Wrote signed proxy certificate into a file");
02168     }
02169     else {
02170       CredentialLogger.msg(ERROR, "Failed to write signed proxy certificate into a file");
02171       BIO_free_all(out); return false;
02172     }
02173 
02174     BIO_free_all(out);
02175     return true;
02176   }
02177 
02178  //The following is the methods about how to use a CA credential to sign an EEC
02179 
02180   Credential::Credential(const std::string& CAcertfile, const std::string& CAkeyfile,
02181        const std::string& CAserial, bool CAcreateserial, const std::string& extfile,
02182        const std::string& extsect, const std::string& passphrase4key) : certfile_(CAcertfile), keyfile_(CAkeyfile),
02183        CAserial_(CAserial), CAcreateserial_(CAcreateserial), extfile_(extfile), extsect_(extsect),
02184        cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
02185        req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(1024), extensions_(NULL) {
02186     OpenSSLInit();
02187 
02188     InitVerification();
02189 
02190     //Initiate the proxy certificate constant and  method which is required by openssl
02191     if(!proxy_init_) InitProxyCertInfo();
02192 
02193     extensions_ = sk_X509_EXTENSION_new_null();
02194 
02195     try {
02196       loadCertificateFile(CAcertfile, cert_, &cert_chain_);
02197       if(cert_) check_cert_type(cert_,cert_type_);
02198       loadKeyFile(CAkeyfile, pkey_, passphrase4key);
02199     } catch(std::exception& err){
02200       CredentialLogger.msg(ERROR, "ERROR:%s", err.what());
02201       LogError();
02202     }
02203   }
02204 
02205   static void print_ssl_errors() {
02206     unsigned long err;
02207     while(err = ERR_get_error()) {
02208       CredentialLogger.msg(ERROR,"SSL error: %s, libs: %s, func: %s, reason: %s",
02209         ERR_error_string(err, NULL),ERR_lib_error_string(err),
02210         ERR_func_error_string(err),ERR_reason_error_string(err));
02211     }
02212   }
02213 
02214 #define SERIAL_RAND_BITS        64
02215   int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) {
02216     BIGNUM *btmp;
02217     int ret = 0;
02218     if (b)
02219       btmp = b;
02220     else
02221       btmp = BN_new();
02222     if (!btmp)
02223       return 0;
02224     if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
02225       goto error;
02226     if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
02227       goto error;
02228     ret = 1;
02229 error:
02230     if (!b)
02231       BN_free(btmp);
02232     return ret;
02233   }
02234 
02235 #undef BSIZE
02236 #define BSIZE 256
02237   BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai) {
02238     BIO *in=NULL;
02239     BIGNUM *ret=NULL;
02240     char buf[1024];
02241     ASN1_INTEGER *ai=NULL;
02242 
02243     ai=ASN1_INTEGER_new();
02244     if (ai == NULL) goto err;
02245 
02246     if ((in=BIO_new(BIO_s_file())) == NULL) {
02247       print_ssl_errors();
02248       goto err;
02249     }
02250 
02251     if (BIO_read_filename(in,serialfile) <= 0) {
02252       if (!create) {
02253         perror(serialfile);
02254         goto err;
02255       }
02256       else {
02257         ret=BN_new();
02258         if (ret == NULL || !rand_serial(ret, ai))
02259           CredentialLogger.msg(ERROR,"Out of memory");
02260       }
02261     }
02262     else {
02263       if (!a2i_ASN1_INTEGER(in,ai,buf,1024)) {
02264         CredentialLogger.msg(ERROR,"unable to load number from: %s",serialfile);
02265         goto err;
02266       }
02267       ret=ASN1_INTEGER_to_BN(ai,NULL);
02268       if (ret == NULL) {
02269         CredentialLogger.msg(ERROR, "error converting number from bin to BIGNUM");
02270         goto err;
02271       }
02272     }
02273 
02274     if (ret && retai) {
02275       *retai = ai;
02276       ai = NULL;
02277     }
02278 err:
02279     if (in != NULL) BIO_free(in);
02280     if (ai != NULL) ASN1_INTEGER_free(ai);
02281       return(ret);
02282   }
02283 
02284   int save_serial(char *serialfile, char *suffix, BIGNUM *serial, ASN1_INTEGER **retai) {
02285     char buf[1][BSIZE];
02286     BIO *out = NULL;
02287     int ret=0;
02288     ASN1_INTEGER *ai=NULL;
02289     int j;
02290 
02291     if (suffix == NULL)
02292       j = strlen(serialfile);
02293     else
02294       j = strlen(serialfile) + strlen(suffix) + 1;
02295     if (j >= BSIZE) {
02296       CredentialLogger.msg(ERROR,"file name too long");
02297       goto err;
02298     }
02299 
02300     if (suffix == NULL)
02301       BUF_strlcpy(buf[0], serialfile, BSIZE);
02302     else {
02303 #ifndef OPENSSL_SYS_VMS
02304       j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
02305 #else
02306       j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
02307 #endif
02308     }
02309     out=BIO_new(BIO_s_file());
02310     if (out == NULL) {
02311       print_ssl_errors();
02312       goto err;
02313     }
02314     if (BIO_write_filename(out,buf[0]) <= 0) {
02315       perror(serialfile);
02316       goto err;
02317     }
02318     if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL) {
02319       CredentialLogger.msg(ERROR,"error converting serial to ASN.1 format");
02320       goto err;
02321     }
02322     i2a_ASN1_INTEGER(out,ai);
02323     BIO_puts(out,"\n");
02324     ret=1;
02325     if (retai) {
02326       *retai = ai;
02327       ai = NULL;
02328     }
02329 err:
02330     if (out != NULL) BIO_free_all(out);
02331     if (ai != NULL) ASN1_INTEGER_free(ai);
02332     return(ret);
02333   }
02334 
02335 #undef POSTFIX
02336 #define POSTFIX ".srl"
02337   static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create) {
02338     char *buf = NULL, *p;
02339     ASN1_INTEGER *bs = NULL;
02340     BIGNUM *serial = NULL;
02341     size_t len;
02342 
02343     len = ((serialfile == NULL)
02344             ?(strlen(CAfile)+strlen(POSTFIX)+1)
02345             :(strlen(serialfile)))+1;
02346     buf=(char*)(OPENSSL_malloc(len));
02347     if (buf == NULL) { CredentialLogger.msg(ERROR,"out of memory"); goto end; }
02348     if (serialfile == NULL) {
02349       BUF_strlcpy(buf,CAfile,len);
02350       for (p=buf; *p; p++)
02351         if (*p == '.') {
02352           *p='\0';
02353           break;
02354         }
02355       BUF_strlcat(buf,POSTFIX,len);
02356     }
02357     else
02358       BUF_strlcpy(buf,serialfile,len);
02359 
02360     serial = load_serial(buf, create, NULL);
02361     if (serial == NULL) goto end;
02362 
02363     if (!BN_add_word(serial,1)) {
02364       CredentialLogger.msg(ERROR,"add_word failure"); goto end;
02365     }
02366 
02367     if (!save_serial(buf, NULL, serial, &bs)) goto end;
02368 
02369  end:
02370     if (buf) OPENSSL_free(buf);
02371     BN_free(serial);
02372     return bs;
02373   }
02374 
02375   static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
02376              X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
02377              long lifetime, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno) {
02378     int ret=0;
02379     ASN1_INTEGER *bs=NULL;
02380     X509_STORE_CTX xsc;
02381     EVP_PKEY *upkey;
02382 
02383     upkey = X509_get_pubkey(xca);
02384     EVP_PKEY_copy_parameters(upkey,pkey);
02385     EVP_PKEY_free(upkey);
02386 
02387     if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL)) {
02388       CredentialLogger.msg(ERROR,"Error initialising X509 store");
02389       goto end;
02390     }
02391     if (sno) bs = sno;
02392     else if (!(bs = x509_load_serial(CAfile, serialfile, create)))
02393       goto end;
02394 
02395     X509_STORE_CTX_set_cert(&xsc,x);
02396     //if (!X509_verify_cert(&xsc))
02397     //  goto end;
02398 
02399     if (!X509_check_private_key(xca,pkey)) {
02400       CredentialLogger.msg(ERROR,"CA certificate and CA private key do not match");
02401       goto end;
02402     }
02403 
02404     if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end;
02405     if (!X509_set_serialNumber(x,bs)) goto end;
02406 
02407     if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL)
02408       goto end;
02409 
02410     /* hardwired expired */
02411     if (X509_gmtime_adj(X509_get_notAfter(x), lifetime) == NULL)
02412       goto end;
02413 
02414     if (clrext) {
02415       while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0);
02416     }
02417 
02418     if (conf) {
02419       X509V3_CTX ctx2;
02420       X509_set_version(x,2); /* version 3 certificate */
02421       X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
02422       X509V3_set_nconf(&ctx2, conf);
02423       if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
02424     }
02425 
02426     if (!X509_sign(x,pkey,digest)) goto end;
02427       ret=1;
02428 end:
02429     X509_STORE_CTX_cleanup(&xsc);
02430     if (!ret)
02431       ERR_clear_error();
02432     if (!sno) ASN1_INTEGER_free(bs);
02433 
02434     return ret;
02435   }
02436 
02437 
02438  /*subject is expected to be in the format /type0=value0/type1=value1/type2=...
02439  * where characters may be escaped by \
02440  */
02441   X509_NAME * Credential::parse_name(char *subject, long chtype, int multirdn) {
02442     size_t buflen = strlen(subject)+1;
02443     /* to copy the types and values into. due to escaping, the copy can only become shorter */
02444     char *buf = (char*)(OPENSSL_malloc(buflen));
02445     size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
02446     char **ne_types =  (char **)(OPENSSL_malloc(max_ne * sizeof (char *)));
02447     char **ne_values = (char **)(OPENSSL_malloc(max_ne * sizeof (char *)));
02448     int *mval = (int*)(OPENSSL_malloc (max_ne * sizeof (int)));
02449 
02450     char *sp = subject, *bp = buf;
02451     int i, ne_num = 0;
02452 
02453     X509_NAME *n = NULL;
02454     int nid;
02455 
02456     if (!buf || !ne_types || !ne_values) {
02457       CredentialLogger.msg(ERROR,"malloc error");
02458       goto error;
02459     }
02460     if (*subject != '/') {
02461       CredentialLogger.msg(ERROR,"Subject does not start with '/'");
02462       goto error;
02463     }
02464     sp++; /* skip leading / */
02465 
02466     /* no multivalued RDN by default */
02467     mval[ne_num] = 0;
02468     while (*sp) {
02469       /* collect type */
02470       ne_types[ne_num] = bp;
02471       while (*sp) {
02472         if (*sp == '\\') /* is there anything to escape in the type...? */
02473         {
02474           if (*++sp)
02475           *bp++ = *sp++;
02476           else {
02477             CredentialLogger.msg(ERROR,"escape character at end of string");
02478             goto error;
02479           }
02480         }
02481         else if (*sp == '=') {
02482           sp++;
02483           *bp++ = '\0';
02484           break;
02485         }
02486         else  *bp++ = *sp++;
02487       }
02488       if (!*sp) {
02489         CredentialLogger.msg(ERROR,"end of string encountered while processing type of subject name element #%d",ne_num);
02490         goto error;
02491       }
02492       ne_values[ne_num] = bp;
02493       while (*sp) {
02494         if (*sp == '\\') {
02495           if (*++sp)
02496             *bp++ = *sp++;
02497           else {
02498             CredentialLogger.msg(ERROR,"escape character at end of string");
02499             goto error;
02500           }
02501         }
02502         else if (*sp == '/') {
02503           sp++;
02504           /* no multivalued RDN by default */
02505           mval[ne_num+1] = 0;
02506           break;
02507         }
02508         else if (*sp == '+' && multirdn) {
02509           /* a not escaped + signals a mutlivalued RDN */
02510           sp++;
02511           mval[ne_num+1] = -1;
02512           break;
02513         }
02514         else
02515           *bp++ = *sp++;
02516       }
02517       *bp++ = '\0';
02518       ne_num++;
02519     }
02520 
02521     if (!(n = X509_NAME_new()))
02522       goto error;
02523 
02524     for (i = 0; i < ne_num; i++) {
02525       if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) {
02526         CredentialLogger.msg(ERROR,"Subject Attribute %s has no known NID, skipped",ne_types[i]);
02527         continue;
02528       }
02529       if (!*ne_values[i]) {
02530         CredentialLogger.msg(ERROR,"No value provided for Subject Attribute %s skipped",ne_types[i]);
02531         continue;
02532       }
02533 
02534       if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
02535         goto error;
02536     }
02537 
02538     OPENSSL_free(mval);
02539     OPENSSL_free(ne_values);
02540     OPENSSL_free(ne_types);
02541     OPENSSL_free(buf);
02542     return n;
02543 
02544 error:
02545     X509_NAME_free(n);
02546     if (ne_values)
02547       OPENSSL_free(ne_values);
02548     if (ne_types)
02549       OPENSSL_free(ne_types);
02550     if (buf)
02551       OPENSSL_free(buf);
02552     return NULL;
02553   }
02554 
02555   bool Credential::SignEECRequest(Credential* eec, const std::string& dn, BIO* outputbio) {
02556     if(pkey_ == NULL) { CredentialLogger.msg(ERROR, "The private key for signing is not initialized"); return false; }
02557     bool res = false;
02558     if(eec == NULL) { CredentialLogger.msg(ERROR, "The credential to be signed is NULL"); return false; }
02559     if(eec->req_ == NULL) { CredentialLogger.msg(ERROR, "The credential to be signed contains no request"); return false; }
02560     if(outputbio == NULL) { CredentialLogger.msg(ERROR, "The BIO for output is NULL"); return false; }
02561 
02562     X509*  eec_cert = NULL;
02563     EVP_PKEY* req_pubkey = NULL;
02564     req_pubkey = X509_REQ_get_pubkey(eec->req_);
02565     if(!req_pubkey) { CredentialLogger.msg(ERROR, "Error when extracting public key from request");
02566       LogError(); return false;
02567     }
02568     if(!X509_REQ_verify(eec->req_, req_pubkey)){
02569       CredentialLogger.msg(ERROR,"Failed to verify the request");
02570       LogError(); return false;
02571     }
02572     eec_cert = X509_new();
02573     X509_set_pubkey(eec_cert, req_pubkey);
02574     EVP_PKEY_free(req_pubkey);
02575 
02576     X509_set_issuer_name(eec_cert,eec->req_->req_info->subject);
02577     //X509_set_subject_name(eec_cert,eec->req_->req_info->subject);
02578 
02579     X509_NAME *subject = NULL;
02580     unsigned long chtype = MBSTRING_ASC;  //TODO
02581     subject = parse_name((char*)(dn.c_str()), chtype, 0);
02582     X509_set_subject_name(eec_cert, subject);
02583     X509_NAME_free(subject);
02584 
02585     const EVP_MD *digest=EVP_sha1();
02586 #ifndef OPENSSL_NO_DSA
02587     if (pkey_->type == EVP_PKEY_DSA)
02588       digest=EVP_dss1();
02589 #endif
02590 /*
02591 #ifndef OPENSSL_NO_ECDSA
02592     if (pkey_->type == EVP_PKEY_EC)
02593       digest = EVP_ecdsa();
02594 #endif
02595 */
02596     X509_STORE *ctx=NULL;
02597     ctx=X509_STORE_new();
02598     //X509_STORE_set_verify_cb_func(ctx,callb);
02599     if (!X509_STORE_set_default_paths(ctx)) {
02600       LogError();
02601     }
02602 
02603     CONF *extconf = NULL;
02604     if (!extfile_.empty()) {
02605       long errorline = -1;
02606       X509V3_CTX ctx2;
02607       extconf = NCONF_new(NULL);
02608       //configuration file with X509V3 extensions to add
02609       if (!NCONF_load(extconf, extfile_.c_str(),&errorline)) {
02610         if (errorline <= 0) {
02611           CredentialLogger.msg(ERROR,"Error when loading the extension config file: %s", extfile_.c_str());
02612           return false;
02613         }
02614         else {
02615           CredentialLogger.msg(ERROR,"Error when loading the extension config file: %s on line: %d",
02616              extfile_.c_str(), errorline);
02617         }
02618       }
02619       //section from config file with X509V3 extensions to add
02620       if (extsect_.empty()) {
02621         extsect_.append(NCONF_get_string(extconf, "default", "extensions"));
02622         if (extsect_.empty()) {
02623           ERR_clear_error();
02624           extsect_ = "default";
02625         }
02626       }
02627       X509V3_set_ctx_test(&ctx2);
02628       X509V3_set_nconf(&ctx2, extconf);
02629       if (!X509V3_EXT_add_nconf(extconf, &ctx2, (char*)(extsect_.c_str()), NULL)) {
02630         CredentialLogger.msg(ERROR,"Error when loading the extension section: %s",
02631           extsect_.c_str());
02632         LogError();
02633       }
02634     }
02635 
02636     //Add extensions to certificate object
02637     X509_EXTENSION* ext = NULL;
02638     X509_CINF*  cert_info = NULL;
02639     cert_info = eec_cert->cert_info;
02640     if (cert_info->extensions != NULL) {
02641       sk_X509_EXTENSION_pop_free(cert_info->extensions, X509_EXTENSION_free);
02642     }
02643     if(sk_X509_EXTENSION_num(eec->extensions_)) {
02644       cert_info->extensions = sk_X509_EXTENSION_new_null();
02645     }
02646     for (int i=0; i<sk_X509_EXTENSION_num(eec->extensions_); i++) {
02647       ext = X509_EXTENSION_dup(sk_X509_EXTENSION_value(eec->extensions_, i));
02648       if (ext == NULL) {
02649         CredentialLogger.msg(ERROR,"Failed to duplicate extension"); LogError();
02650       }
02651 
02652       if (!sk_X509_EXTENSION_push(cert_info->extensions, ext)) {
02653         CredentialLogger.msg(ERROR,"Failed to add extension into EEC certificate"); LogError();
02654       }
02655     }
02656 
02657     long lifetime = 12*60*60; //Default lifetime 12 hours
02658     if (!x509_certify(ctx,(char*)(certfile_.c_str()), digest, eec_cert, cert_,
02659                       pkey_, (char*)(CAserial_.c_str()), CAcreateserial_, lifetime, 0,
02660                       extconf, (char*)(extsect_.c_str()), NULL)) {
02661       CredentialLogger.msg(ERROR,"Can not sign a EEC"); LogError();
02662     }
02663 
02664     if(PEM_write_bio_X509(outputbio, eec_cert)) {
02665       CredentialLogger.msg(INFO, "Output EEC certificate"); res = true;
02666     }
02667     else {
02668       CredentialLogger.msg(ERROR, "Can not convert signed EEC cert into DER format");
02669       LogError();
02670     }
02671 
02672     NCONF_free(extconf);
02673     X509_free(eec_cert);
02674     X509_STORE_free(ctx);
02675 
02676     return res;
02677   }
02678 
02679   bool Credential::SignEECRequest(Credential* eec, const std::string& dn, std::string &content) {
02680     BIO *out = BIO_new(BIO_s_mem());
02681     if(!out) {
02682       CredentialLogger.msg(ERROR, "Can not create BIO for signed EEC certificate");
02683       LogError(); return false;
02684     }
02685 
02686     if(SignEECRequest(eec, dn, out)) {
02687       for(;;) {
02688         char s[256];
02689         int l = BIO_read(out,s,sizeof(s));
02690         if(l <= 0) break;
02691         content.append(s,l);
02692       }
02693     }
02694     BIO_free_all(out);
02695     return true;
02696   }
02697 
02698   bool Credential::SignEECRequest(Credential* eec, const std::string& dn, const char* filename) {
02699     BIO *out = BIO_new(BIO_s_file());
02700     if(!out) {
02701       CredentialLogger.msg(ERROR, "Can not create BIO for signed EEC certificate");
02702       LogError(); return false;
02703     }
02704     if (!(BIO_write_filename(out, (char*)filename))) {
02705       CredentialLogger.msg(ERROR, "Can not set writable file for signed EEC certificate BIO");
02706       LogError(); BIO_free_all(out); return false;
02707     }
02708 
02709     if(SignEECRequest(eec, dn, out)) {
02710       CredentialLogger.msg(INFO, "Wrote signed EEC certificate into a file");
02711     }
02712     else {
02713       CredentialLogger.msg(ERROR, "Failed to write signed EEC certificate into a file");
02714       BIO_free_all(out); return false;
02715     }
02716     BIO_free_all(out);
02717     return true;
02718   }
02719 
02720 
02721   Credential::~Credential() {
02722     if(cert_) X509_free(cert_);
02723     if(pkey_) EVP_PKEY_free(pkey_);
02724     if(cert_chain_) sk_X509_pop_free(cert_chain_, X509_free);
02725     if(proxy_cert_info_) PROXYCERTINFO_free(proxy_cert_info_);
02726     if(req_) X509_REQ_free(req_);
02727     if(rsa_key_) RSA_free(rsa_key_);
02728     if(extensions_) sk_X509_EXTENSION_pop_free(extensions_, X509_EXTENSION_free);
02729     if(verify_ctx_.cert_chain) sk_X509_pop_free(verify_ctx_.cert_chain, X509_free);
02730   }
02731 
02732 }
02733