Back to index

nordugrid-arc-nox  1.1.0~rc6
DelegationInterface.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <openssl/rsa.h>
00006 #include <openssl/bn.h>
00007 #include <openssl/bio.h>
00008 #include <openssl/pem.h>
00009 #include <openssl/err.h>
00010 #include <openssl/x509v3.h>
00011 
00012 #include <string>
00013 #include <iostream>
00014 #include <fstream>
00015 
00016 #include <arc/GUID.h>
00017 #include <arc/StringConv.h>
00018 #include <arc/DateTime.h>
00019 #include <arc/message/PayloadSOAP.h>
00020 #include <arc/crypto/OpenSSL.h>
00021 
00022 #include "DelegationInterface.h"
00023 
00024 namespace Arc {
00025 
00026 #define DELEGATION_NAMESPACE "http://www.nordugrid.org/schemas/delegation"
00027 //#define SERIAL_RAND_BITS 64
00028 #define SERIAL_RAND_BITS 31
00029 
00030 static int rand_serial(ASN1_INTEGER *ai) {
00031   int ret = 0;
00032   BIGNUM *btmp = BN_new();
00033   if(!btmp) goto error;
00034   if(!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) goto error;
00035   if(ai && !BN_to_ASN1_INTEGER(btmp, ai)) goto error;
00036   ret = 1;
00037 error:
00038   if(btmp) BN_free(btmp);
00039   return ret;
00040 }
00041 
00042 static bool x509_to_string(X509* cert,std::string& str) {
00043   BIO *out = BIO_new(BIO_s_mem());
00044   if(!out) return false;
00045   if(!PEM_write_bio_X509(out,cert)) { BIO_free_all(out); return false; };
00046   for(;;) {
00047     char s[256];
00048     int l = BIO_read(out,s,sizeof(s));
00049     if(l <= 0) break;
00050     str.append(s,l);;
00051   };
00052   BIO_free_all(out);
00053   return true;
00054 }
00055 
00056 /*
00057 static bool x509_to_string(EVP_PKEY* key,std::string& str) {
00058   BIO *out = BIO_new(BIO_s_mem());
00059   if(!out) return false;
00060   EVP_CIPHER *enc = NULL;
00061   if(!PEM_write_bio_PrivateKey(out,key,enc,NULL,0,NULL,NULL)) { BIO_free_all(out); return false; };
00062   for(;;) {
00063     char s[256];
00064     int l = BIO_read(out,s,sizeof(s));
00065     if(l <= 0) break;
00066     str.append(s,l);;
00067   };
00068   BIO_free_all(out);
00069   return true;
00070 }
00071 */
00072 
00073 static bool x509_to_string(RSA* key,std::string& str) {
00074   BIO *out = BIO_new(BIO_s_mem());
00075   if(!out) return false;
00076   EVP_CIPHER *enc = NULL;
00077   if(!PEM_write_bio_RSAPrivateKey(out,key,enc,NULL,0,NULL,NULL)) { BIO_free_all(out); return false; };
00078   for(;;) {
00079     char s[256];
00080     int l = BIO_read(out,s,sizeof(s));
00081     if(l <= 0) break;
00082     str.append(s,l);;
00083   };
00084   BIO_free_all(out);
00085   return true;
00086 }
00087 
00088 static int passphrase_callback(char* buf, int size, int, void *arg) {
00089    std::istream* in = (std::istream*)arg;
00090    if(in == &std::cin) std::cout<<"Enter passphrase for your private key: ";
00091    buf[0]=0;
00092    in->getline(buf,size);
00093    //if(!(*in)) {
00094    //  if(in == &std::cin) std::cerr<< "Failed to read passphrase from stdin"<<std::endl;
00095    //  return -1;
00096    //};
00097    return strlen(buf);
00098 }
00099 
00100 static bool string_to_x509(const std::string& str,X509* &cert,EVP_PKEY* &pkey,STACK_OF(X509)* &cert_sk) {
00101   BIO *in = NULL;
00102   cert=NULL; pkey=NULL; cert_sk=NULL;
00103   if(str.empty()) return false;
00104   if(!(in=BIO_new_mem_buf((void*)(str.c_str()),str.length()))) return false;
00105   if((!PEM_read_bio_X509(in,&cert,NULL,NULL)) || (!cert)) { BIO_free_all(in); return false; };
00106   if((!PEM_read_bio_PrivateKey(in,&pkey,NULL,NULL)) || (!pkey)) { BIO_free_all(in); return false; };
00107   if(!(cert_sk=sk_X509_new_null())) { BIO_free_all(in); return false; };
00108   for(;;) {
00109     X509* c = NULL;
00110     if((!PEM_read_bio_X509(in,&c,NULL,NULL)) || (!c)) break;
00111     sk_X509_push(cert_sk,c);
00112   };
00113   BIO_free_all(in);
00114   return true;
00115 }
00116 
00117 static bool string_to_x509(const std::string& cert_file,const std::string& key_file,std::istream* inpwd,X509* &cert,EVP_PKEY* &pkey,STACK_OF(X509)* &cert_sk) {
00118   BIO *in = NULL;
00119   cert=NULL; pkey=NULL; cert_sk=NULL;
00120   if(cert_file.empty()) return false;
00121   if(!(in=BIO_new_file(cert_file.c_str(),"r"))) return false;
00122   if((!PEM_read_bio_X509(in,&cert,NULL,NULL)) || (!cert)) { BIO_free_all(in); return false; };
00123   if(key_file.empty()) {
00124     if((!PEM_read_bio_PrivateKey(in,&pkey,inpwd?&passphrase_callback:NULL,inpwd)) || (!pkey)) { BIO_free_all(in); return false; };
00125   };
00126   if(!(cert_sk=sk_X509_new_null())) { BIO_free_all(in); return false; };
00127   for(;;) {
00128     X509* c = NULL;
00129     if((!PEM_read_bio_X509(in,&c,NULL,NULL)) || (!c)) break;
00130     sk_X509_push(cert_sk,c);
00131   };
00132   ERR_get_error();
00133   if(!pkey) {
00134     BIO_free_all(in); in=NULL;
00135     if(!(in=BIO_new_file(key_file.c_str(),"r"))) return false;
00136     if((!PEM_read_bio_PrivateKey(in,&pkey,inpwd?&passphrase_callback:NULL,inpwd)) || (!pkey)) { BIO_free_all(in); return false; };
00137   };
00138   BIO_free_all(in);
00139   return true;
00140 }
00141 
00142 static bool string_to_x509(const std::string& str,X509* &cert,STACK_OF(X509)* &cert_sk) {
00143   BIO *in = NULL;
00144   if(str.empty()) return false;
00145   if(!(in=BIO_new_mem_buf((void*)(str.c_str()),str.length()))) return false;
00146   if((!PEM_read_bio_X509(in,&cert,NULL,NULL)) || (!cert)) { BIO_free_all(in); return false; };
00147   if(!(cert_sk=sk_X509_new_null())) { BIO_free_all(in); return false; };
00148   for(;;) {
00149     X509* c = NULL;
00150     if((!PEM_read_bio_X509(in,&c,NULL,NULL)) || (!c)) break;
00151     sk_X509_push(cert_sk,c);
00152   };
00153   ERR_get_error();
00154   BIO_free_all(in);
00155   return true;
00156 }
00157 
00158 /*
00159 static unsigned char* ASN1_BIT_STRING_to_data(ASN1_BIT_STRING* str,int* l) {
00160   *l=0;
00161   int length = i2d_ASN1_BIT_STRING(str, NULL);
00162   if(length < 0) return NULL;
00163   unsigned char* data = (unsigned char*)malloc(length);
00164   if(!data) return NULL;
00165   length = i2d_ASN1_BIT_STRING(str,&data);
00166   if(length < 0) {
00167     free(data);
00168     return NULL;
00169   };
00170   if(l) *l=length;
00171   return data;
00172 }
00173 
00174 static X509_EXTENSION* data_to_X509_EXTENSION(const char* name,unsigned char* data,int length,bool critical) {
00175   ASN1_OBJECT* ext_obj = NULL;
00176   ASN1_OCTET_STRING* ext_oct = NULL;
00177   X509_EXTENSION* ext = NULL;
00178 
00179   ext_obj=OBJ_nid2obj(OBJ_txt2nid(name));
00180   if(!ext_obj) goto err;
00181   ext_oct=ASN1_OCTET_STRING_new();
00182   if(!ext_oct) goto err;
00183   ASN1_OCTET_STRING_set(ext_oct,data,length);
00184   ext=X509_EXTENSION_create_by_OBJ(NULL,ext_obj,critical?1:0,ext_oct);
00185 err:
00186   if(ext_oct) ASN1_OCTET_STRING_free(ext_oct);
00187   if(ext_obj) ASN1_OBJECT_free(ext_obj);
00188   return ext;
00189 }
00190 
00191 static X509_EXTENSION* ASN1_OCTET_STRING_to_X509_EXTENSION(const char* name,ASN1_OCTET_STRING* oct,bool critical) {
00192   ASN1_OBJECT* ext_obj = NULL;
00193   X509_EXTENSION* ext = NULL;
00194 
00195   ext_obj=OBJ_nid2obj(OBJ_txt2nid(name));
00196   if(!ext_obj) goto err;
00197   ext=X509_EXTENSION_create_by_OBJ(NULL,ext_obj,critical?1:0,oct);
00198 err:
00199   if(ext_obj) ASN1_OBJECT_free(ext_obj);
00200   return ext;
00201 }
00202 */
00203 
00204 static bool X509_add_ext_by_nid(X509 *cert,int nid,char *value,int pos) {
00205   X509_EXTENSION* ext = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
00206   if(!ext) return false;
00207   X509_add_ext(cert,ext,pos);
00208   X509_EXTENSION_free(ext);
00209   return true;
00210 }
00211 
00212 
00213 DelegationConsumer::DelegationConsumer(void):key_(NULL) {
00214   Generate();
00215 }
00216 
00217 DelegationConsumer::DelegationConsumer(const std::string& content):key_(NULL) {
00218   Restore(content);
00219 }
00220 
00221 DelegationConsumer::~DelegationConsumer(void) {
00222   if(key_) RSA_free((RSA*)key_);
00223 }
00224 
00225 const std::string& DelegationConsumer::ID(void) {
00226   static std::string s;
00227   return s;
00228 }
00229 
00230 #ifdef HAVE_OPENSSL_OLDRSA
00231 static void progress_cb(int p, int, void*) {
00232   char c='*';
00233   if (p == 0) c='.';
00234   if (p == 1) c='+';
00235   if (p == 2) c='*';
00236   if (p == 3) c='\n';
00237   std::cerr<<c;
00238 }
00239 #else
00240 static int progress_cb(int p, int, BN_GENCB*) {
00241   char c='*';
00242   if (p == 0) c='.';
00243   if (p == 1) c='+';
00244   if (p == 2) c='*';
00245   if (p == 3) c='\n';
00246   std::cerr<<c;
00247   return 1;
00248 }
00249 #endif
00250 
00251 static int ssl_err_cb(const char *str, size_t len, void *u) {
00252   std::string& ssl_err = *((std::string*)u);
00253   ssl_err.append(str,len);
00254   return 1;
00255 }
00256 
00257 void DelegationConsumer::LogError(void) {
00258   std::string ssl_err;
00259   ERR_print_errors_cb(&ssl_err_cb,&ssl_err);
00260 }
00261 
00262 bool DelegationConsumer::Backup(std::string& content) {
00263   bool res = false;
00264   content.resize(0);
00265   RSA *rsa = (RSA*)key_;
00266   if(rsa) {
00267     BIO *out = BIO_new(BIO_s_mem());
00268     if(out) {
00269       EVP_CIPHER *enc = NULL;
00270       if(PEM_write_bio_RSAPrivateKey(out,rsa,enc,NULL,0,NULL,NULL)) {
00271         res=true;
00272         for(;;) {
00273           char s[256];
00274           int l = BIO_read(out,s,sizeof(s));
00275           if(l <= 0) break;
00276           content.append(s,l);;
00277         };
00278       } else {
00279         LogError();
00280         std::cerr<<"PEM_write_bio_RSAPrivateKey failed"<<std::endl;
00281       };
00282       BIO_free_all(out);
00283     };
00284   };
00285   return res;
00286 }
00287 
00288 bool DelegationConsumer::Restore(const std::string& content) {
00289   bool res = false;
00290   RSA *rsa = NULL;
00291   BIO *in = BIO_new_mem_buf((void*)(content.c_str()),content.length());
00292   if(in) {
00293     if(PEM_read_bio_RSAPrivateKey(in,&rsa,NULL,NULL)) {
00294       if(rsa) {
00295         if(key_) RSA_free((RSA*)key_);
00296         key_=rsa; res=true;
00297       };
00298     };
00299     BIO_free_all(in);
00300   };
00301   return rsa;
00302 }
00303 
00304 bool DelegationConsumer::Generate(void) {
00305   bool res = false;
00306   int num = 1024;
00307 #ifdef HAVE_OPENSSL_OLDRSA
00308   unsigned long bn = RSA_F4;
00309   RSA *rsa=RSA_generate_key(num,bn,&progress_cb,NULL);
00310   if(rsa) {
00311     if(key_) RSA_free((RSA*)key_);
00312     key_=rsa; rsa=NULL; res=true;
00313   } else {
00314     LogError();
00315     std::cerr<<"RSA_generate_key failed"<<std::endl;
00316   };
00317   if(rsa) RSA_free(rsa);
00318 #else
00319   BN_GENCB cb;
00320   BIGNUM *bn = BN_new();
00321   RSA *rsa = RSA_new();
00322 
00323   BN_GENCB_set(&cb,&progress_cb,NULL);
00324   if(bn && rsa) {
00325     if(BN_set_word(bn,RSA_F4)) {
00326       if(RSA_generate_key_ex(rsa,num,bn,&cb)) {
00327         if(key_) RSA_free((RSA*)key_);
00328         key_=rsa; rsa=NULL; res=true;
00329       } else {
00330         LogError();
00331         std::cerr<<"RSA_generate_key_ex failed"<<std::endl;
00332       };
00333     } else {
00334       LogError();
00335       std::cerr<<"BN_set_word failed"<<std::endl;
00336     };
00337   } else {
00338     LogError();
00339     std::cerr<<"BN_new || RSA_new failed"<<std::endl;
00340   };
00341   if(bn) BN_free(bn);
00342   if(rsa) RSA_free(rsa);
00343 #endif
00344   return res;
00345 }
00346 
00347 bool DelegationConsumer::Request(std::string& content) {
00348   bool res = false;
00349   content.resize(0);
00350   EVP_PKEY *pkey = EVP_PKEY_new();
00351   const EVP_MD *digest = EVP_sha1();
00352   if(pkey) {
00353     RSA *rsa = (RSA*)key_;
00354     if(rsa) {
00355       if(EVP_PKEY_set1_RSA(pkey, rsa)) {
00356         X509_REQ *req = X509_REQ_new();
00357         if(req) {
00358           //if(X509_REQ_set_version(req,0L)) {
00359           if(X509_REQ_set_version(req,2L)) {
00360             if(X509_REQ_set_pubkey(req,pkey)) {
00361               if(X509_REQ_sign(req,pkey,digest)) {
00362                 BIO *out = BIO_new(BIO_s_mem());
00363                 if(out) {
00364                   if(PEM_write_bio_X509_REQ(out,req)) {
00365                     res=true;
00366                     for(;;) {
00367                       char s[256];
00368                       int l = BIO_read(out,s,sizeof(s));
00369                       if(l <= 0) break;
00370                       content.append(s,l);;
00371                     };
00372                   } else {
00373                     LogError();
00374                     std::cerr<<"PEM_write_bio_X509_REQ failed"<<std::endl;
00375                   };
00376                   BIO_free_all(out);
00377                 };
00378               };
00379             };
00380           };
00381           X509_REQ_free(req);
00382         };
00383       };
00384     };
00385     EVP_PKEY_free(pkey);
00386   };
00387   return res;
00388 }
00389 
00390 bool DelegationConsumer::Acquire(std::string& content) {
00391   std::string identity;
00392   return Acquire(content,identity);
00393 }
00394 
00395 bool DelegationConsumer::Acquire(std::string& content, std::string& identity) {
00396   X509 *cert = NULL;
00397   STACK_OF(X509) *cert_sk = NULL;
00398   bool res = false;
00399   char buf[100];
00400   std::string subject;
00401 
00402   if(!key_) return false;
00403 
00404   if(!string_to_x509(content,cert,cert_sk)) goto err;
00405 
00406   content.resize(0);
00407   if(!x509_to_string(cert,content)) goto err;
00408 
00409   X509_NAME_oneline(X509_get_subject_name(cert),buf,sizeof(buf));
00410   subject=buf;
00411 #ifdef HAVE_OPENSSL_PROXY
00412   if(X509_get_ext_by_NID(cert,NID_proxyCertInfo,-1) < 0) {
00413     identity=subject;
00414   };
00415 #endif
00416 
00417   if(!x509_to_string((RSA*)key_,content)) goto err;
00418   if(cert_sk) {
00419     for(int n=0;n<sk_X509_num((STACK_OF(X509) *)cert_sk);++n) {
00420       X509* v = sk_X509_value((STACK_OF(X509) *)cert_sk,n);
00421       if(!v) goto err;
00422       if(!x509_to_string(v,content)) goto err;
00423       if(identity.empty()) {
00424         memset(buf,0,100);
00425         X509_NAME_oneline(X509_get_subject_name(v),buf,sizeof(buf));
00426 #ifdef HAVE_OPENSSL_PROXY
00427         if(X509_get_ext_by_NID(v,NID_proxyCertInfo,-1) < 0) {
00428           identity=buf;
00429         };
00430 #endif
00431       };
00432     };
00433   };
00434   if(identity.empty()) identity = subject;
00435 
00436   res=true;
00437 err:
00438   if(!res) LogError();
00439   if(cert) X509_free(cert);
00440   if(cert_sk) {
00441     for(int i = 0;i<sk_X509_num(cert_sk);++i) {
00442       X509* v = sk_X509_value(cert_sk,i);
00443       if(v) X509_free(v);
00444     };
00445     sk_X509_free(cert_sk);
00446   };
00447   return res;
00448 }
00449 
00450 // ---------------------------------------------------------------------------------
00451 
00452 DelegationProvider::DelegationProvider(const std::string& credentials):key_(NULL),cert_(NULL),chain_(NULL) {
00453   EVP_PKEY *pkey = NULL;
00454   X509 *cert = NULL;
00455   STACK_OF(X509) *cert_sk = NULL;
00456   bool res = false;
00457 
00458   OpenSSLInit();
00459   EVP_add_digest(EVP_sha1());
00460 
00461   if(!string_to_x509(credentials,cert,pkey,cert_sk)) goto err;
00462   cert_=cert; cert=NULL;
00463   key_=pkey; pkey=NULL;
00464   chain_=cert_sk; cert_sk=NULL;
00465   res=true;
00466 err:
00467   if(!res) LogError();
00468   if(pkey) EVP_PKEY_free(pkey);
00469   if(cert) X509_free(cert);
00470   if(cert_sk) {
00471     for(int i = 0;i<sk_X509_num(cert_sk);++i) {
00472       X509* v = sk_X509_value(cert_sk,i);
00473       if(v) X509_free(v);
00474     };
00475     sk_X509_free(cert_sk);
00476   };
00477 }
00478 
00479 DelegationProvider::DelegationProvider(const std::string& cert_file,const std::string& key_file,std::istream* inpwd):key_(NULL),cert_(NULL),chain_(NULL) {
00480   EVP_PKEY *pkey = NULL;
00481   X509 *cert = NULL;
00482   STACK_OF(X509) *cert_sk = NULL;
00483   bool res = false;
00484 
00485   
00486   OpenSSLInit();
00487   EVP_add_digest(EVP_sha1());
00488 
00489   if(!string_to_x509(cert_file,key_file,inpwd,cert,pkey,cert_sk)) goto err;
00490   cert_=cert; cert=NULL;
00491   key_=pkey; pkey=NULL;
00492   chain_=cert_sk; cert_sk=NULL;
00493   res=true;
00494 err:
00495   if(!res) LogError();
00496   if(pkey) EVP_PKEY_free(pkey);
00497   if(cert) X509_free(cert);
00498   if(cert_sk) {
00499     for(int i = 0;i<sk_X509_num(cert_sk);++i) {
00500       X509* v = sk_X509_value(cert_sk,i);
00501       if(v) X509_free(v);
00502     };
00503     sk_X509_free(cert_sk);
00504   };
00505 }
00506 
00507 DelegationProvider::~DelegationProvider(void) {
00508   if(key_) EVP_PKEY_free((EVP_PKEY*)key_);
00509   if(cert_) X509_free((X509*)cert_);
00510   if(chain_) {
00511     for(;;) {
00512       X509* v = sk_X509_pop((STACK_OF(X509) *)chain_);
00513       if(!v) break;
00514       X509_free(v);
00515     };
00516     sk_X509_free((STACK_OF(X509) *)chain_);
00517   };
00518 }
00519 
00520 std::string DelegationProvider::Delegate(const std::string& request,const DelegationRestrictions& restrictions) {
00521 #ifdef HAVE_OPENSSL_PROXY
00522   X509 *cert = NULL;
00523   X509_REQ *req = NULL;
00524   BIO* in = NULL;
00525   EVP_PKEY *pkey = NULL;
00526   ASN1_INTEGER *sno = NULL;
00527   ASN1_OBJECT *obj= NULL;
00528   ASN1_OCTET_STRING* policy_string = NULL;
00529   X509_EXTENSION *ex = NULL;
00530   PROXY_CERT_INFO_EXTENSION proxy_info;
00531   PROXY_POLICY proxy_policy;
00532   const EVP_MD *digest = EVP_sha1();
00533   X509_NAME *subject = NULL;
00534   const char* need_ext = "critical,digitalSignature,keyEncipherment";
00535   std::string proxy_cn;
00536   std::string res;
00537   time_t validity_start = time(NULL);
00538   time_t validity_end = (time_t)(-1);
00539   DelegationRestrictions& restrictions_ = (DelegationRestrictions&)restrictions;
00540   std::string proxyPolicy;
00541   std::string proxyPolicyFile;
00542 
00543   if(!cert_) {
00544     std::cerr<<"Missing certificate chain"<<std::endl;
00545     return "";
00546   };
00547   if(!key_) {
00548     std::cerr<<"Missing private key"<<std::endl;
00549     return "";
00550   };
00551 
00552   in = BIO_new_mem_buf((void*)(request.c_str()),request.length());
00553   if(!in) goto err;
00554 
00555   if((!PEM_read_bio_X509_REQ(in,&req,NULL,NULL)) || (!req)) goto err;
00556   BIO_free_all(in); in=NULL;
00557 
00558  
00559   //subject=X509_REQ_get_subject_name(req);
00560   //char* buf = X509_NAME_oneline(subject, 0, 0);
00561   //std::cerr<<"subject="<<buf<<std::endl;
00562   //OPENSSL_free(buf);
00563 
00564   if((pkey=X509_REQ_get_pubkey(req)) == NULL) goto err;
00565   if(X509_REQ_verify(req,pkey) <= 0) goto err;
00566 
00567   cert=X509_new();
00568   if(!cert) goto err;
00569   //ci=x->cert_info;
00570   sno = ASN1_INTEGER_new();
00571   if(!sno) goto err;
00572   // TODO - serial number must be unique among generated by proxy issuer
00573   if(!rand_serial(sno)) goto err;
00574   if (!X509_set_serialNumber(cert,sno)) goto err;
00575   proxy_cn=tostring(ASN1_INTEGER_get(sno));
00576   ASN1_INTEGER_free(sno); sno=NULL;
00577   X509_set_version(cert,2L);
00578 
00579   /*
00580    Proxy certificates do not need KeyUsage extension. But
00581    some old software still expects it to be present.
00582 
00583    From RFC3820:
00584 
00585    If the Proxy Issuer certificate has the KeyUsage extension, the
00586    Digital Signature bit MUST be asserted.
00587   */
00588 
00589   X509_add_ext_by_nid(cert,NID_key_usage,(char*)need_ext,-1);
00590 
00591   /*
00592    From RFC3820:
00593 
00594    If a certificate is a Proxy Certificate, then the proxyCertInfo
00595    extension MUST be present, and this extension MUST be marked as
00596    critical.
00597   
00598    The pCPathLenConstraint field, if present, specifies the maximum
00599    depth of the path of Proxy Certificates that can be signed by this
00600    Proxy Certificate. 
00601 
00602    The proxyPolicy field specifies a policy on the use of this
00603    certificate for the purposes of authorization.  Within the
00604    proxyPolicy, the policy field is an expression of policy, and the
00605    policyLanguage field indicates the language in which the policy is
00606    expressed.
00607 
00608    *  id-ppl-inheritAll indicates that this is an unrestricted proxy
00609       that inherits all rights from the issuing PI.  An unrestricted
00610       proxy is a statement that the Proxy Issuer wishes to delegate all
00611       of its authority to the bearer (i.e., to anyone who has that proxy
00612       certificate and can prove possession of the associated private
00613       key).  For purposes of authorization, this an unrestricted proxy
00614       effectively impersonates the issuing PI.
00615 
00616    *  id-ppl-independent indicates that this is an independent proxy
00617       that inherits no rights from the issuing PI.  This PC MUST be
00618       treated as an independent identity by relying parties.  The only
00619       rights this PC has are those granted explicitly to it.
00620   */
00621   /*
00622   ex=X509V3_EXT_conf_nid(NULL,NULL,NID_proxyCertInfo,"critical,CA:FALSE");
00623   if(!ex) goto err;
00624   if(!X509_add_ext(cert,ex,-1)) goto err;
00625   X509_EXTENSION_free(ex); ex=NULL;
00626   */
00627   memset(&proxy_info,0,sizeof(proxy_info));
00628   memset(&proxy_policy,0,sizeof(proxy_policy));
00629   proxy_info.pcPathLengthConstraint=NULL;
00630   proxy_info.proxyPolicy=&proxy_policy;
00631   proxy_policy.policyLanguage=NULL;
00632   proxy_policy.policy=NULL;
00633   proxyPolicy=restrictions_["proxyPolicy"];
00634   proxyPolicyFile=restrictions_["proxyPolicyFile"];
00635   if(!proxyPolicyFile.empty()) {
00636     if(!proxyPolicy.empty()) goto err; // Two policies supplied
00637     std::ifstream is(proxyPolicyFile.c_str());
00638     std::getline(is,proxyPolicy,(char)0);
00639     if(proxyPolicy.empty()) goto err;
00640   };
00641   if(!proxyPolicy.empty()) {
00642     obj=OBJ_nid2obj(NID_id_ppl_anyLanguage);  // Proxy with policy
00643     if(!obj) goto err;
00644     policy_string=ASN1_OCTET_STRING_new();
00645     if(!policy_string) goto err;
00646     ASN1_OCTET_STRING_set(policy_string,(const unsigned char*)(proxyPolicy.c_str()),proxyPolicy.length());
00647     proxy_policy.policyLanguage=obj;
00648     proxy_policy.policy=policy_string;
00649   } else {
00650     obj=OBJ_nid2obj(NID_id_ppl_inheritAll);  // Unrestricted proxy
00651     if(!obj) goto err;
00652     proxy_policy.policyLanguage=obj;
00653   };
00654   if(X509_add1_ext_i2d(cert,NID_proxyCertInfo,&proxy_info,1,X509V3_ADD_REPLACE) != 1) goto err;
00655   if(policy_string) ASN1_OCTET_STRING_free(policy_string); policy_string=NULL;
00656   ASN1_OBJECT_free(obj); obj=NULL;
00657   /*
00658   PROXY_CERT_INFO_EXTENSION *pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL);
00659   typedef struct PROXY_CERT_INFO_EXTENSION_st {
00660         ASN1_INTEGER *pcPathLengthConstraint;
00661         PROXY_POLICY *proxyPolicy;
00662         } PROXY_CERT_INFO_EXTENSION;
00663   typedef struct PROXY_POLICY_st {
00664         ASN1_OBJECT *policyLanguage;
00665         ASN1_OCTET_STRING *policy;
00666         } PROXY_POLICY;
00667   */
00668 
00669   subject=X509_get_subject_name((X509*)cert_);
00670   if(!subject) goto err;
00671   subject=X509_NAME_dup(subject);
00672   if(!subject) goto err;
00673   if(!X509_set_issuer_name(cert,subject)) goto err;
00674   if(!X509_NAME_add_entry_by_NID(subject,NID_commonName,MBSTRING_ASC,(unsigned char*)(proxy_cn.c_str()),proxy_cn.length(),-1,0)) goto err;
00675   if(!X509_set_subject_name(cert,subject)) goto err;
00676   X509_NAME_free(subject); subject=NULL;
00677   if(!(restrictions_["validityStart"].empty())) {
00678     validity_start=Time(restrictions_["validityStart"]).GetTime();
00679   };
00680   if(!(restrictions_["validityEnd"].empty())) {
00681     validity_end=Time(restrictions_["validityEnd"]).GetTime();
00682   } else if(!(restrictions_["validityPeriod"].empty())) {
00683     validity_end=validity_start+Period(restrictions_["validityPeriod"]).GetPeriod();
00684   };
00685   //Set "notBefore"
00686   if( X509_cmp_time(X509_get_notBefore((X509*)cert_), &validity_start) < 0) {
00687     X509_time_adj(X509_get_notBefore(cert), 0L, &validity_start);
00688   }
00689   else {
00690     X509_set_notBefore(cert, X509_get_notBefore((X509*)cert_));
00691   }
00692   //Set "not After"
00693   if(validity_end == (time_t)(-1)) {
00694     X509_set_notAfter(cert,X509_get_notAfter((X509*)cert_));
00695   } else {
00696     X509_gmtime_adj(X509_get_notAfter(cert), (validity_end-validity_start));
00697   };
00698   X509_set_pubkey(cert,pkey);
00699   EVP_PKEY_free(pkey); pkey=NULL;
00700 
00701   if(!X509_sign(cert,(EVP_PKEY*)key_,digest)) goto err;
00702   /*
00703   {
00704     int pci_NID = NID_undef;
00705     ASN1_OBJECT * extension_oid = NULL;
00706     int nid;
00707     PROXY_CERT_INFO_EXTENSION* proxy_cert_info;
00708     X509_EXTENSION *                    extension;
00709 
00710     pci_NID = OBJ_sn2nid(SN_proxyCertInfo);
00711     for(i=0;i<X509_get_ext_count(cert);i++) {
00712         extension = X509_get_ext(cert,i);
00713         extension_oid = X509_EXTENSION_get_object(extension);
00714         nid = OBJ_obj2nid(extension_oid);
00715         if(nid == pci_NID) {
00716             CleanError();
00717             if((proxy_cert_info = (PROXY_CERT_INFO_EXTENSION*)(X509V3_EXT_d2i(extension))) == NULL) {
00718               goto err;
00719               std::cerr<<"X509V3_EXT_d2i failed"<<std::endl;
00720             }
00721             break;
00722         }
00723     }
00724   }
00725   */
00726 
00727   if(!x509_to_string(cert,res)) { res=""; goto err; };
00728   // Append chain of certificates
00729   if(!x509_to_string((X509*)cert_,res)) { res=""; goto err; };
00730   if(chain_) {
00731     for(int n=0;n<sk_X509_num((STACK_OF(X509) *)chain_);++n) {
00732       X509* v = sk_X509_value((STACK_OF(X509) *)chain_,n);
00733       if(!v) { res=""; goto err; };
00734       if(!x509_to_string(v,res)) { res=""; goto err; };
00735     };
00736   };
00737 
00738 err:
00739   if(res.empty()) LogError();
00740   if(in) BIO_free_all(in);
00741   if(req) X509_REQ_free(req);
00742   if(pkey) EVP_PKEY_free(pkey);
00743   if(cert) X509_free(cert);
00744   if(sno) ASN1_INTEGER_free(sno);
00745   if(ex) X509_EXTENSION_free(ex);
00746   if(obj) ASN1_OBJECT_free(obj);
00747   if(subject) X509_NAME_free(subject);
00748   if(policy_string) ASN1_OCTET_STRING_free(policy_string);
00749   return res;
00750 #else
00751   return "";
00752 #endif
00753 }
00754 
00755 void DelegationProvider::LogError(void) {
00756   std::string ssl_err;
00757   ERR_print_errors_cb(&ssl_err_cb,&ssl_err);
00758 }
00759 
00760 void DelegationProvider::CleanError(void) {
00761   std::string ssl_err;
00762   ERR_print_errors_cb(&ssl_err_cb,&ssl_err);
00763 }
00764 
00765 // ---------------------------------------------------------------------------------
00766 
00767 DelegationConsumerSOAP::DelegationConsumerSOAP(void):DelegationConsumer() {
00768 }
00769 
00770 DelegationConsumerSOAP::DelegationConsumerSOAP(const std::string& content):DelegationConsumer(content) {
00771 }
00772 
00773 DelegationConsumerSOAP::~DelegationConsumerSOAP(void) {
00774 }
00775 
00776 bool DelegationConsumerSOAP::DelegateCredentialsInit(const std::string& id,const SOAPEnvelope& in,SOAPEnvelope& out) {
00777 /*
00778   DelegateCredentialsInit
00779 
00780   DelegateCredentialsInitResponse
00781     TokenRequest - Format (=x509)
00782       Id (string)
00783       Value (string)
00784 */
00785   if(!in["DelegateCredentialsInit"]) return false;
00786   std::string x509_request;
00787   Request(x509_request);
00788   NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
00789   out.Namespaces(ns);
00790   XMLNode resp = out.NewChild("deleg:DelegateCredentialsInitResponse");
00791   XMLNode token = resp.NewChild("deleg:TokenRequest");
00792   token.NewAttribute("deleg:Format")="x509";
00793   token.NewChild("deleg:Id")=id;
00794   token.NewChild("deleg:Value")=x509_request;
00795   return true;
00796 }
00797 
00798 bool DelegationConsumerSOAP::UpdateCredentials(std::string& credentials,const SOAPEnvelope& in,SOAPEnvelope& out) {
00799   std::string identity;
00800   return UpdateCredentials(credentials,identity,in,out);
00801 }
00802 
00803 bool DelegationConsumerSOAP::UpdateCredentials(std::string& credentials,std::string& identity,const SOAPEnvelope& in,SOAPEnvelope& out) {
00804 /*
00805   UpdateCredentials
00806     DelegatedToken - Format (=x509)
00807       Id (string)
00808       Value (string)
00809       Reference (any, optional)
00810 
00811   UpdateCredentialsResponse
00812 */
00813   XMLNode req = in["UpdateCredentials"];
00814   if(!req) return false;
00815   credentials = (std::string)(req["DelegatedToken"]["Value"]);
00816   if(credentials.empty()) {
00817     // TODO: Fault
00818     return false;
00819   };
00820   if(((std::string)(req["DelegatedToken"].Attribute("Format"))) != "x509") {
00821     // TODO: Fault
00822     return false;
00823   };
00824   if(!Acquire(credentials,identity)) return false;
00825   NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
00826   out.Namespaces(ns);
00827   out.NewChild("deleg:UpdateCredentialsResponse");
00828   return true;
00829 }
00830 
00831 bool DelegationConsumerSOAP::DelegatedToken(std::string& credentials,XMLNode token) {
00832   std::string identity;
00833   return DelegatedToken(credentials,identity,token);
00834 }
00835 
00836 bool DelegationConsumerSOAP::DelegatedToken(std::string& credentials,std::string& identity,XMLNode token) {
00837   credentials = (std::string)(token["Value"]);
00838   if(credentials.empty()) return false;
00839   if(((std::string)(token.Attribute("Format"))) != "x509") return false;
00840   if(!Acquire(credentials,identity)) return false;
00841   return true;
00842 }
00843 
00844 // ---------------------------------------------------------------------------------
00845 
00846 DelegationProviderSOAP::DelegationProviderSOAP(const std::string& credentials):DelegationProvider(credentials) {
00847 }
00848 
00849 DelegationProviderSOAP::DelegationProviderSOAP(const std::string& cert_file,const std::string& key_file, std::istream* inpwd):DelegationProvider(cert_file,key_file, inpwd) {
00850 }
00851 
00852 DelegationProviderSOAP::~DelegationProviderSOAP(void) {
00853 }
00854 
00855 bool DelegationProviderSOAP::DelegateCredentialsInit(MCCInterface& interface,MessageContext* context) {
00856   MessageAttributes attributes_in;
00857   MessageAttributes attributes_out;
00858   return DelegateCredentialsInit(interface,&attributes_in,&attributes_out,context);
00859 }
00860 
00861 bool DelegationProviderSOAP::DelegateCredentialsInit(MCCInterface& interface,MessageAttributes* attributes_in,MessageAttributes* attributes_out,MessageContext* context) {
00862   NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
00863   PayloadSOAP req_soap(ns);
00864   req_soap.NewChild("deleg:DelegateCredentialsInit");
00865   Message req;
00866   Message resp;
00867   req.Attributes(attributes_in);
00868   req.Context(context);
00869   req.Payload(&req_soap);
00870   resp.Attributes(attributes_out);
00871   resp.Context(context);
00872   MCC_Status r = interface.process(req,resp);
00873   if(r != STATUS_OK) return false;
00874   if(!resp.Payload()) return false;
00875   PayloadSOAP* resp_soap = NULL;
00876   try {
00877     resp_soap=dynamic_cast<PayloadSOAP*>(resp.Payload());
00878   } catch(std::exception& e) { };
00879   if(!resp_soap) { delete resp.Payload(); return false; };
00880   XMLNode token = (*resp_soap)["DelegateCredentialsInitResponse"]["TokenRequest"];
00881   if(!token) { delete resp_soap; return false; };
00882   if(((std::string)(token.Attribute("Format"))) != "x509") { delete resp_soap; return false; };
00883   id_=(std::string)(token["Id"]);
00884   request_=(std::string)(token["Value"]);
00885   delete resp_soap;
00886   if(id_.empty() || request_.empty()) return false;
00887   return true;
00888 }
00889 
00890 bool DelegationProviderSOAP::UpdateCredentials(MCCInterface& interface,MessageContext* context,const DelegationRestrictions& restrictions) {
00891   MessageAttributes attributes_in;
00892   MessageAttributes attributes_out;
00893   return UpdateCredentials(interface,&attributes_in,&attributes_out,context);
00894 }
00895 
00896 bool DelegationProviderSOAP::UpdateCredentials(MCCInterface& interface,MessageAttributes* attributes_in,MessageAttributes* attributes_out,MessageContext* context,const DelegationRestrictions& restrictions) {
00897   if(id_.empty()) return false;
00898   if(request_.empty()) return false;
00899   std::string delegation = Delegate(request_,restrictions);
00900   if(delegation.empty()) return false;
00901   NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
00902   PayloadSOAP req_soap(ns);
00903   XMLNode token = req_soap.NewChild("deleg:UpdateCredentials").NewChild("deleg:DelegatedToken");
00904   token.NewAttribute("deleg:Format")="x509";
00905   token.NewChild("deleg:Id")=id_;
00906   token.NewChild("deleg:Value")=delegation;
00907   Message req;
00908   Message resp;
00909   req.Attributes(attributes_in);
00910   req.Context(context);
00911   req.Payload(&req_soap);
00912   resp.Attributes(attributes_out);
00913   resp.Context(context);
00914   MCC_Status r = interface.process(req,resp);
00915   if(r != STATUS_OK) return false;
00916   if(!resp.Payload()) return false;
00917   PayloadSOAP* resp_soap = NULL;
00918   try {
00919     resp_soap=dynamic_cast<PayloadSOAP*>(resp.Payload());
00920   } catch(std::exception& e) { };
00921   if(!resp_soap) { delete resp.Payload(); return false; };
00922   if(!(*resp_soap)["UpdateCredentialsResponse"]) 
00923   delete resp_soap;
00924   return true;
00925 }
00926 
00927 bool DelegationProviderSOAP::DelegatedToken(XMLNode parent) {
00928   if(id_.empty()) return false;
00929   if(request_.empty()) return false;
00930   std::string delegation = Delegate(request_);
00931   if(delegation.empty()) return false;
00932   NS ns; ns["deleg"]=DELEGATION_NAMESPACE;
00933   parent.Namespaces(ns);
00934   XMLNode token = parent.NewChild("deleg:DelegatedToken");
00935   token.NewAttribute("deleg:Format")="x509";
00936   token.NewChild("deleg:Id")=id_;
00937   token.NewChild("deleg:Value")=delegation;
00938   return true;
00939 }
00940 
00941 // ---------------------------------------------------------------------------------
00942 // TODO:
00943 // 1. Add access control by assigning user's DN to id.
00944 
00945 class DelegationContainerSOAP::Consumer {
00946  public:
00947   DelegationConsumerSOAP* deleg;
00948   int usage_count;
00949   time_t last_used;
00950   std::string dn;
00951   DelegationContainerSOAP::ConsumerIterator previous;
00952   DelegationContainerSOAP::ConsumerIterator next;
00953   Consumer(void):deleg(NULL),usage_count(0),last_used(time(NULL)) {
00954   };
00955   Consumer(DelegationConsumerSOAP* d):deleg(d),usage_count(0),last_used(time(NULL)) {
00956   };
00957   Consumer& operator=(DelegationConsumerSOAP* d) {
00958     deleg=d; usage_count=0; last_used=time(NULL); return *this;
00959   };
00960 };
00961 
00962 DelegationContainerSOAP::DelegationContainerSOAP(void) {
00963   max_size_=0;         // unlimited size of container
00964   max_duration_=30;    // 30 seconds for delegation
00965   max_usage_=2;        // allow 1 failure
00966   context_lock_=false;
00967   restricted_=true;
00968   consumers_first_=consumers_.end();
00969   consumers_last_=consumers_.end();
00970 }
00971 
00972 DelegationContainerSOAP::~DelegationContainerSOAP(void) {
00973   lock_.lock();
00974   ConsumerIterator i = consumers_.begin();
00975   for(;i!=consumers_.end();++i) {
00976     if(i->second.deleg) delete i->second.deleg;
00977   };
00978   lock_.unlock();
00979 }
00980 
00981 void DelegationContainerSOAP::AddConsumer(const std::string& id,DelegationConsumerSOAP* consumer) {
00982   Consumer c;
00983   c.deleg=consumer; 
00984   c.previous=consumers_.end();
00985   c.next=consumers_first_;
00986   ConsumerIterator i = consumers_.insert(consumers_.begin(),make_pair(id,c)); 
00987   if(consumers_first_ != consumers_.end()) consumers_first_->second.previous=i;
00988   consumers_first_=i;
00989   if(consumers_last_ == consumers_.end()) consumers_last_=i;
00990 }
00991 
00992 void DelegationContainerSOAP::TouchConsumer(ConsumerIterator i) {
00993   i->second.last_used=time(NULL);
00994   if(i == consumers_first_) return;
00995   ConsumerIterator previous = i->second.previous;
00996   ConsumerIterator next = i->second.next;
00997   if(previous != consumers_.end()) previous->second.next=next;
00998   if(next != consumers_.end()) next->second.previous=previous;
00999   i->second.previous=consumers_.end();
01000   i->second.next=consumers_first_;
01001   if(consumers_first_ != consumers_.end()) consumers_first_->second.previous=i;
01002   consumers_first_=i;
01003 }
01004 
01005 DelegationContainerSOAP::ConsumerIterator DelegationContainerSOAP::RemoveConsumer(ConsumerIterator i) {
01006   ConsumerIterator previous = i->second.previous;
01007   ConsumerIterator next = i->second.next;
01008   if(previous != consumers_.end()) previous->second.next=next;
01009   if(next != consumers_.end()) next->second.previous=previous;
01010   if(consumers_first_ == i) consumers_first_=next; 
01011   if(consumers_last_ == i) consumers_last_=previous; 
01012   if(i->second.deleg) delete i->second.deleg;
01013   consumers_.erase(i);
01014   return next;
01015 }
01016 
01017 void DelegationContainerSOAP::CheckConsumers(void) {
01018   if(max_size_ > 0) {
01019     while(consumers_.size() > max_size_) {
01020       RemoveConsumer(consumers_last_);
01021     };
01022   };
01023   if(max_duration_ > 0) {
01024     time_t t = time(NULL);
01025     for(ConsumerIterator i = consumers_last_;i!=consumers_.end();) {
01026       if(((unsigned int)(t - i->second.last_used)) > max_duration_) {
01027         i=RemoveConsumer(i);
01028       } else {
01029         break;
01030       };
01031     };
01032   };
01033 }
01034 
01035 bool DelegationContainerSOAP::DelegateCredentialsInit(const SOAPEnvelope& in,SOAPEnvelope& out) {
01036   lock_.lock();
01037   std::string id;
01038   for(int tries = 0;tries<1000;++tries) {
01039     GUID(id);
01040     ConsumerIterator i = consumers_.find(id);
01041     if(i == consumers_.end()) break;
01042     id.resize(0);
01043   };
01044   if(id.empty()) { lock_.unlock(); return false; };
01045   DelegationConsumerSOAP* consumer = new DelegationConsumerSOAP();
01046   if(!(consumer->DelegateCredentialsInit(id,in,out))) { lock_.unlock(); delete consumer; return false; };
01047   AddConsumer(id,consumer);
01048   CheckConsumers();
01049   lock_.unlock();
01050   return true;
01051 }
01052 
01053 bool DelegationContainerSOAP::UpdateCredentials(std::string& credentials,const SOAPEnvelope& in,SOAPEnvelope& out) {
01054   std::string identity;
01055   return UpdateCredentials(credentials,identity,in,out);
01056 }
01057 
01058 bool DelegationContainerSOAP::UpdateCredentials(std::string& credentials,std::string& identity, const SOAPEnvelope& in,SOAPEnvelope& out) {
01059   lock_.lock();
01060   std::string id = (std::string)(const_cast<SOAPEnvelope&>(in)["UpdateCredentials"]["DelegatedToken"]["Id"]);
01061   ConsumerIterator i = consumers_.find(id);
01062   if(i == consumers_.end()) { lock_.unlock(); return false; };
01063   if(!(i->second.deleg)) { lock_.unlock(); return false; };
01064   if(restricted_) {
01065 
01066 
01067   };
01068   bool r = i->second.deleg->UpdateCredentials(credentials,identity,in,out);
01069   if(((++(i->second.usage_count)) > max_usage_) && (max_usage_ > 0)) {
01070     RemoveConsumer(i);
01071   } else {
01072     TouchConsumer(i);
01073   };
01074   lock_.unlock();
01075   return r;
01076 }
01077 
01078 bool DelegationContainerSOAP::DelegatedToken(std::string& credentials,XMLNode token) {
01079   std::string identity;
01080   return DelegatedToken(credentials,identity,token);
01081 }
01082 
01083 bool DelegationContainerSOAP::DelegatedToken(std::string& credentials,std::string& identity,XMLNode token) {
01084   lock_.lock();
01085   std::string id = (std::string)(token["Id"]);
01086   ConsumerIterator i = consumers_.find(id);
01087   if(i == consumers_.end()) { lock_.unlock(); return false; };
01088   if(!(i->second.deleg)) { lock_.unlock(); return false; };
01089   bool r = i->second.deleg->DelegatedToken(credentials,identity,token);
01090   if(((++(i->second.usage_count)) > max_usage_) && (max_usage_ > 0)) {
01091     RemoveConsumer(i);
01092   } else {
01093     TouchConsumer(i);
01094   };
01095   lock_.unlock();
01096   return r;
01097 }
01098 
01099 } // namespace Arc
01100