Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Member Functions | Static Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes
Arc::Credential Class Reference

#include <Credential.h>

Collaboration diagram for Arc::Credential:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 Credential ()
 Default constructor, only acts as a container for inquiring certificate request, *is meaningless for any other use.
 Credential (int keybits)
 Constructor with user-defined keylength.
virtual ~Credential ()
 Credential (const std::string &CAfile, const std::string &CAkey, const std::string &CAserial, bool CAcreateserial, const std::string &extfile, const std::string &extsect, const std::string &passphrase4key="")
 Constructor, specific constructor for CA certificate *is meaningless for any other use.
 Credential (Time start, Period lifetime=Period("PT12H"), int keybits=1024, std::string proxyversion="rfc", std::string policylang="inheritAll", std::string policy="", int pathlength=-1)
 Constructor, specific constructor for proxy certificate, only acts as a container for constraining certificate signing and/or generating certificate request(only keybits is useful for creating certificate request), is meaningless for any other use.
 Credential (const std::string &cert, const std::string &key, const std::string &cadir, const std::string &cafile, const std::string &passphrase4key="", const bool is_file=true)
 Constructor, specific constructor for usual certificate, constructing from credential files.
void AddCertExtObj (std::string &sn, std::string &oid)
 General method for adding a new nid into openssl's global const.
void LogError (void)
 Log error information related with openssl.
bool GetVerification (void)
 Get the verification result about certificate chain checking.
EVP_PKEY * GetPrivKey (void)
 Get the private key attached to this object.
EVP_PKEY * GetPubKey (void)
 Get the public key attached to this object.
X509 * GetCert (void)
 Get the certificate attached to this object.
X509_REQ * GetCertReq (void)
 Get the certificate request, if there is any.
 STACK_OF (X509)*GetCertChain(void)
 Get the certificate chain attached to this object.
int GetCertNumofChain (void)
 Get the number of certificates in the certificate chain attached to this object.
Credformat getFormat (BIO *in, const bool is_file=true)
 Get the certificate format, PEM PKCS12 or DER BIO could be memory or file, they should be processed differently.
std::string GetDN (void)
 Get the DN of the certificate attached to this object.
std::string GetIdentityName (void)
 Get the Identity name of the certificate attached to this object, the result will not include proxy CN.
ArcCredential::certType GetType (void)
 Get type of the certificate attached to this object.
std::string GetProxyPolicy (void)
 Get the proxy policy attached to the "proxy certificate information" extension of the proxy certicate.
void SetProxyPolicy (const std::string &proxyversion, const std::string &policylang, const std::string &policy, int pathlength)
 Set the proxy policy attached to the "proxy certificate information" extension of the proxy certicate.
bool OutputPrivatekey (std::string &content, bool encryption=false, const std::string &passphrase="")
 Output the private key into string.
bool OutputPublickey (std::string &content)
 Output the public key into string.
bool OutputCertificate (std::string &content, bool is_der=false)
 Output the certificate into string.
bool OutputCertificateChain (std::string &content, bool is_der=false)
 Output the certificate chain into string.
Period GetLifeTime (void)
 Returns lifetime of certificate or proxy.
Time GetStartTime ()
 Returns validity start time of certificate or proxy.
Time GetEndTime ()
 Returns validity end time of certificate or proxy.
void SetLifeTime (const Period &period)
 Set lifetime of certificate or proxy.
void SetStartTime (const Time &start_time)
 Set start time of certificate or proxy.
bool AddExtension (std::string name, std::string data, bool crit=false)
 Add an extension to the extension part of the certificate.
bool AddExtension (std::string name, char **binary, bool crit=false)
 Add an extension to the extension part of the certificate.
bool GenerateEECRequest (BIO *reqbio, BIO *keybio, std::string dn="")
 Generate an EEC request, based on the keybits and signing algorithm information inside this object output the certificate request to output BIO.
bool GenerateEECRequest (std::string &reqcontent, std::string &keycontent, std::string dn="")
 Generate an EEC request, output the certificate request to a string.
bool GenerateEECRequest (const char *request_filename, const char *key_filename, std::string dn="")
 Generate an EEC request, output the certificate request and the key to a file.
bool GenerateRequest (BIO *bio, bool if_der=false)
 Generate a proxy request, base on the keybits and signing algorithm information inside this object output the certificate request to output BIO.
bool GenerateRequest (std::string &content, bool if_der=false)
 Generate a proxy request, output the certificate request to a string.
bool GenerateRequest (const char *filename, bool if_der=false)
 Generate a proxy request, output the certificate request to a file.
bool InquireRequest (BIO *reqbio, bool if_eec=false, bool if_der=false)
 Inquire the certificate request from BIO, and put the request information to X509_REQ inside this object, and parse the certificate type from the PROXYCERTINFO of request' extension.
bool InquireRequest (std::string &content, bool if_eec=false, bool if_der=false)
 Inquire the certificate request from a string.
bool InquireRequest (const char *filename, bool if_eec=false, bool if_der=false)
 Inquire the certificate request from a file.
bool SignRequest (Credential *proxy, BIO *outputbio, bool if_der=false)
 Sign request based on the information inside proxy, and output the signed certificate to output BIO.
bool SignRequest (Credential *proxy, std::string &content, bool if_der=false)
 Sign request and output the signed certificate to a string.
bool SignRequest (Credential *proxy, const char *filename, bool foamat=false)
 Sign request and output the signed certificate to a file.
bool SignEECRequest (Credential *eec, const std::string &DN, BIO *outputbio)
 Sign eec request, and output the signed certificate to output BIO.
bool SignEECRequest (Credential *eec, const std::string &DN, std::string &content)
 Sign request and output the signed certificate to a string.
bool SignEECRequest (Credential *eec, const std::string &DN, const char *filename)
 Sign request and output the signed certificate to a file.

Static Public Member Functions

static void InitProxyCertInfo (void)
 Initiate nid for proxy certificate extension.
static bool IsCredentialsValid (const UserConfig &usercfg)

Private Member Functions

void loadKeyString (const std::string &key, EVP_PKEY *&pkey, const std::string &passphrase="")
 load key from argument keybio, and put key information into argument pkey
void loadKeyFile (const std::string &keyfile, EVP_PKEY *&pkey, const std::string &passphrase="")
void loadKey (BIO *bio, EVP_PKEY *&pkey, const std::string &passphrase="", const std::string &prompt_info="", const bool is_file=true)
void loadCertificateString (const std::string &cert, X509 *&x509, STACK_OF(X509)**certchain)
 load certificate from argument certbio, and put certificate information into argument cert and certchain
void loadCertificateFile (const std::string &certfile, X509 *&x509, STACK_OF(X509)**certchain)
void loadCertificate (BIO *bio, X509 *&x509, STACK_OF(X509)**certchain, const bool is_file=true)
void InitVerification (void)
 Initiate cert_verify_context which will be used for certificate verification.
bool Verify (void)
 Verify whether the certificate is signed by trusted CAs *the verification is not needed for EEC, but needed for verifying a proxy certificate which *is generated by the others.
X509_EXTENSION * CreateExtension (std::string &name, std::string &data, bool crit=false)
 Create a certificate extension based on the arguments name and data.
bool SetProxyPeriod (X509 *tosign, X509 *issuer, Time &start, Period &lifetime)
 Set the start and end time for the proxy credential.
bool SignRequestAssistant (Credential *proxy, EVP_PKEY *req_pubkey, X509 **tosign)
 Assistant method for signing the proxy request, the method will duplicate some information (subject and extension) from signing certificate.
 STACK_OF (X509)*cert_chain_
 STACK_OF (X509_EXTENSION)*extensions_

Static Private Member Functions

static X509_NAME * parse_name (char *subject, long chtype, int multirdn)

Private Attributes

std::string cacertfile_
std::string cacertdir_
std::string certfile_
std::string keyfile_
ArcCredential::cert_verify_context verify_ctx_
bool verification_valid
X509 * cert_
ArcCredential::certType cert_type_
EVP_PKEY * pkey_
ArcCredential::PROXYCERTINFOproxy_cert_info_
Credformat format
Time start_
Period lifetime_
X509_REQ * req_
RSA * rsa_key_
EVP_MD * signing_alg_
int keybits_
std::string proxyversion_
std::string policy_
std::string policylang_
int proxyver_
int pathlength_
std::string CAserial_
bool CAcreateserial_
std::string extfile_
std::string extsect_

Detailed Description

Definition at line 54 of file Credential.h.


Constructor & Destructor Documentation

Default constructor, only acts as a container for inquiring certificate request, *is meaningless for any other use.

Definition at line 647 of file Credential.cpp.

                         : cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
        start_(Time()), lifetime_(Period("PT12H")),
        req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(1024),
        extensions_(NULL) {

    OpenSSLInit();
    //EVP_add_digest(EVP_sha1());

    InitVerification();

    extensions_ = sk_X509_EXTENSION_new_null();

    //Initiate the proxy certificate constant and  method which is required by openssl
    if(!proxy_init_) InitProxyCertInfo();
  }

Here is the call graph for this function:

Arc::Credential::Credential ( int  keybits)

Constructor with user-defined keylength.

Needed for creation of EE certs, since some applications will only support keys with a certain minimum length > 1024

Definition at line 663 of file Credential.cpp.

                                    : cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
    start_(Time()), lifetime_(Period("PT12H")),
    req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(keybits),
    extensions_(NULL) {

    OpenSSLInit();
    //EVP_add_digest(EVP_sha1());

    InitVerification();

    extensions_ = sk_X509_EXTENSION_new_null();

    //Initiate the proxy certificate constant and  method which is required by openssl
    if(!proxy_init_) InitProxyCertInfo();
  }

Here is the call graph for this function:

Definition at line 2721 of file Credential.cpp.

                          {
    if(cert_) X509_free(cert_);
    if(pkey_) EVP_PKEY_free(pkey_);
    if(cert_chain_) sk_X509_pop_free(cert_chain_, X509_free);
    if(proxy_cert_info_) PROXYCERTINFO_free(proxy_cert_info_);
    if(req_) X509_REQ_free(req_);
    if(rsa_key_) RSA_free(rsa_key_);
    if(extensions_) sk_X509_EXTENSION_pop_free(extensions_, X509_EXTENSION_free);
    if(verify_ctx_.cert_chain) sk_X509_pop_free(verify_ctx_.cert_chain, X509_free);
  }

Here is the call graph for this function:

Arc::Credential::Credential ( const std::string &  CAfile,
const std::string &  CAkey,
const std::string &  CAserial,
bool  CAcreateserial,
const std::string &  extfile,
const std::string &  extsect,
const std::string &  passphrase4key = "" 
)

Constructor, specific constructor for CA certificate *is meaningless for any other use.

Definition at line 2180 of file Credential.cpp.

                                                                  : certfile_(CAcertfile), keyfile_(CAkeyfile),
       CAserial_(CAserial), CAcreateserial_(CAcreateserial), extfile_(extfile), extsect_(extsect),
       cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
       req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(1024), extensions_(NULL) {
    OpenSSLInit();

    InitVerification();

    //Initiate the proxy certificate constant and  method which is required by openssl
    if(!proxy_init_) InitProxyCertInfo();

    extensions_ = sk_X509_EXTENSION_new_null();

    try {
      loadCertificateFile(CAcertfile, cert_, &cert_chain_);
      if(cert_) check_cert_type(cert_,cert_type_);
      loadKeyFile(CAkeyfile, pkey_, passphrase4key);
    } catch(std::exception& err){
      CredentialLogger.msg(ERROR, "ERROR:%s", err.what());
      LogError();
    }
  }

Here is the call graph for this function:

Arc::Credential::Credential ( Time  start,
Period  lifetime = Period("PT12H"),
int  keybits = 1024,
std::string  proxyversion = "rfc",
std::string  policylang = "inheritAll",
std::string  policy = "",
int  pathlength = -1 
)

Constructor, specific constructor for proxy certificate, only acts as a container for constraining certificate signing and/or generating certificate request(only keybits is useful for creating certificate request), is meaningless for any other use.

The proxyversion and policylang is for specifying the proxy certificate type and the policy language inside proxy. The definition of proxyversion and policy language is based on http://dev.globus.org/wiki/Security/ProxyCertTypes#RFC_3820_Proxy_Certificates The code is supposed to support proxy version: GSI2(legacy proxy), GSI3(Proxy draft) and RFC(RFC3820 proxy), and correspoding policy language. GSI2(GSI2, GSI2_LIMITED) GSI3 and RFC (IMPERSONATION_PROXY--1.3.6.1.5.5.7.21.1, INDEPENDENT_PROXY--1.3.6.1.5.5.7.21.2, LIMITED_PROXY--1.3.6.1.4.1.3536.1.1.1.9, RESTRICTED_PROXY--policy language undefined) In openssl>=098, there are three types of policy languages: id-ppl-inheritAll--1.3.6.1.5.5.7.21.1, id-ppl-independent--1.3.6.1.5.5.7.21.2, and id-ppl-anyLanguage-1.3.6.1.5.5.7.21.0

Parameters:
start,starttime of proxy certificate
lifetime,lifetimeof proxy certificate
keybits,modulussize for RSA key generation, *it should be greater than 1024 if 'this' class is *used for generating X509 request; it should be '0' if 'this' class is used for constraing certificate signing.

Definition at line 679 of file Credential.cpp.

                                                                :
        cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
        start_(start), lifetime_(lifetime), req_(NULL), rsa_key_(NULL),
        signing_alg_((EVP_MD*)EVP_sha1()), keybits_(keybits), extensions_(NULL) {

    OpenSSLInit();
    //EVP_add_digest(EVP_sha1());

    InitVerification();

    extensions_ = sk_X509_EXTENSION_new_null();

    //Initiate the proxy certificate constant and  method which is required by openssl
    if(!proxy_init_) InitProxyCertInfo();

    SetProxyPolicy(proxyversion, policylang, policy, pathlength);
  }

Here is the call graph for this function:

Arc::Credential::Credential ( const std::string &  cert,
const std::string &  key,
const std::string &  cadir,
const std::string &  cafile,
const std::string &  passphrase4key = "",
const bool  is_file = true 
)

Constructor, specific constructor for usual certificate, constructing from credential files.

only acts as a container for parsing the certificate and key files, is meaningless for any other use. this constructor will parse the credential information, and put them into "this" object

Parameters:
is_file,specifyif the cert/key are from file, otherwise they are supposed to be from string. default is from file

Definition at line 881 of file Credential.cpp.

                                                             :
        cacertfile_(cafile), cacertdir_(cadir), certfile_(certfile), keyfile_(keyfile),
        cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
        req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()),
        keybits_(1024), extensions_(NULL), verification_valid(false) {

    OpenSSLInit();
    //EVP_add_digest(EVP_sha1());

    InitVerification();

    extensions_ = sk_X509_EXTENSION_new_null();

    if(certfile.empty()) {
      CredentialLogger.msg(ERROR, "Certificate/Proxy path is empty");
      return;
    }

    //Initiate the proxy certificate constant and  method which is required by openssl
    if(!proxy_init_) InitProxyCertInfo();

    if(is_file) {
      try {
        loadCertificateFile(certfile, cert_, &cert_chain_);
        if(cert_) check_cert_type(cert_,cert_type_);
        //std::cout<<"Your identity: "<<GetDN() << std::endl;
        if(keyfile.empty()) {
          //Detect if the certificate file/string contains private key.
          //If the key file is absent, and the private key is not contained inside
          //certificate file/string, then the certificate file will not
          //be parsed for private key.
          //Note this detection only applies to PEM file
          std::string keystr;
          // Since the certfile file has been loaded in the call to
          // loadCertificateFile, it is redundant to check if it exist.
          // loadCertificateFile will throw an exception if the file does not
          // exist.
          std::ifstream in(certfile.c_str(), std::ios::in);
          std::getline<char>(in, keystr, 0);
          in.close();
          if(keystr.find("BEGIN RSA PRIVATE KEY") != std::string::npos)
            loadKeyFile(certfile, pkey_, passphrase4key);
        }
        else
          loadKeyFile(keyfile, pkey_, passphrase4key);
      } catch(std::exception& err){
        CredentialLogger.msg(ERROR, "%s", err.what());
        LogError(); return;
      }
    } else {
      try {
        loadCertificateString(certfile, cert_, &cert_chain_);
        if(cert_) check_cert_type(cert_,cert_type_);
        if(keyfile.empty()) {
          std::string keystr;
          keystr = certfile;
          if(keystr.find("BEGIN RSA PRIVATE KEY") != std::string::npos)
            loadKeyString(certfile, pkey_, passphrase4key);
        }
        else
          loadKeyString(keyfile, pkey_, passphrase4key);
      } catch(std::exception& err){
        CredentialLogger.msg(ERROR, "%s", err.what());
        LogError(); return;
      }
    }

    //Get the lifetime of the credential
    getLifetime(cert_chain_, cert_, start_, lifetime_);

    if(!cacertfile_.empty() || !cacertdir_.empty())
      Verify();
  }

Here is the call graph for this function:


Member Function Documentation

void Arc::Credential::AddCertExtObj ( std::string &  sn,
std::string &  oid 
)

General method for adding a new nid into openssl's global const.

Definition at line 622 of file Credential.cpp.

                                                              {
    OBJ_create(oid.c_str(), sn.c_str(), sn.c_str());
  }

Here is the caller graph for this function:

bool Arc::Credential::AddExtension ( std::string  name,
std::string  data,
bool  crit = false 
)

Add an extension to the extension part of the certificate.

Parameters:
name,thename of the extension, there OID related with the name *should be registered into openssl firstly
data,thedata which will be inserted into certificate extension

Definition at line 1780 of file Credential.cpp.

                                                                         {
    X509_EXTENSION* ext = NULL;
    ext = CreateExtension(name, data, crit);
    if(ext && sk_X509_EXTENSION_push(extensions_, ext)) return true;
    return false;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::AddExtension ( std::string  name,
char **  binary,
bool  crit = false 
)

Add an extension to the extension part of the certificate.

Parameters:
binary,thedata which will be inserted into certificate extension part as a specific extension there should be specific methods defined inside specific X509V3_EXT_METHOD structure to parse the specific extension format. For example, VOMS attribute certificate is a specific extension to proxy certificate. There is specific X509V3_EXT_METHOD defined in VOMSAttribute.h and VOMSAttribute.c for parsing attribute certificate. In openssl, the specific X509V3_EXT_METHOD can be got according to the extension name/id, see X509V3_EXT_get_nid(ext_nid)

Definition at line 1787 of file Credential.cpp.

                                                                   {
    X509_EXTENSION* ext = NULL;
    if(binary == NULL) return false;
    ext = X509V3_EXT_conf_nid(NULL, NULL, OBJ_txt2nid((char*)(name.c_str())), (char*)binary);
    if(ext && sk_X509_EXTENSION_push(extensions_, ext)) return true;
    return false;
  }
X509_EXTENSION * Arc::Credential::CreateExtension ( std::string &  name,
std::string &  data,
bool  crit = false 
) [private]

Create a certificate extension based on the arguments name and data.

argument crit will be used by X509_EXTENSION_create_by_OBJ which is called inside CreateExtension method.

Definition at line 979 of file Credential.cpp.

                                                                                         {
    X509_EXTENSION*   ext = NULL;
    ASN1_OBJECT*      ext_obj = NULL;
    ASN1_OCTET_STRING*  ext_oct = NULL;

    bool numberic = true;
    size_t pos1 = 0, pos2;
    do {
      pos2 = name.find(".", pos1);
      if(pos2 != std::string::npos) { //OID: 1.2.3.4.5
        std::string str = name.substr(pos1, pos2 - pos1);
        long int number = strtol(str.c_str(), NULL, 0);
        if(number == 0) { numberic = false; break; }
      }
      else { //The only one (without '.' as sperator, then the name is a single number or a string) or the last number
        std::string str = name.substr(pos1);
        long int number = strtol(str.c_str(), NULL, 0);
        if(number == 0) { numberic = false; break; }
        else break;
      }
      pos1 = pos2 + 1;
    } while(true);

    if(!numberic && !(ext_obj = OBJ_nid2obj(OBJ_txt2nid((char *)(name.c_str()))))) {
      //string format, the OID should have been registered before calling OBJ_nid2obj
      CredentialLogger.msg(ERROR, "Can not convert string into ASN1_OBJECT");
      LogError(); return NULL;
    }
    else if(numberic && !(ext_obj = OBJ_txt2obj(name.c_str(), 1))) {
      //numerical format, the OID will be registered here if it has not been registered before
      CredentialLogger.msg(ERROR, "Can not convert string into ASN1_OBJECT");
      LogError(); return NULL;
    }

    ext_oct = ASN1_OCTET_STRING_new();

    //ASN1_OCTET_STRING_set(ext_oct, data.c_str(), data.size());
    ext_oct->data = (unsigned char*) malloc(data.size());
    memcpy(ext_oct->data, data.c_str(), data.size());
    ext_oct->length = data.size();

    if (!(ext = X509_EXTENSION_create_by_OBJ(NULL, ext_obj, crit, ext_oct))) {
      CredentialLogger.msg(ERROR, "Can not create extension for proxy certificate");
      LogError();
      if(ext_oct) ASN1_OCTET_STRING_free(ext_oct);
      if(ext_obj) ASN1_OBJECT_free(ext_obj);
      return NULL;
    }

#ifndef WIN32

    // TODO: ASN1_OCTET_STRING_free is not working correctly
    //      on Windows Vista, bugreport: 1587

    if(ext_oct) ASN1_OCTET_STRING_free(ext_oct);

#endif
    if(ext_obj) ASN1_OBJECT_free(ext_obj);

    return ext;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::GenerateEECRequest ( BIO *  reqbio,
BIO *  keybio,
std::string  dn = "" 
)

Generate an EEC request, based on the keybits and signing algorithm information inside this object output the certificate request to output BIO.

The user will be asked for a private key password

Definition at line 1045 of file Credential.cpp.

                                                                       {
    bool res = false;
    RSA* rsa_key = NULL;
    const EVP_MD *digest = signing_alg_;
    EVP_PKEY* pkey;
    int keybits = keybits_;

#ifdef HAVE_OPENSSL_OLDRSA
    unsigned long prime = RSA_F4;
    rsa_key = RSA_generate_key(keybits, prime, keygen_cb, NULL);
    if(!rsa_key) {
      CredentialLogger.msg(ERROR, "RSA_generate_key failed");
      if(rsa_key) RSA_free(rsa_key);
      return false;
    }
#else
    BN_GENCB cb;
    BIGNUM *prime = BN_new();
    rsa_key = RSA_new();

    BN_GENCB_set(&cb,&keygen_cb,NULL);
    if(prime && rsa_key) {
      if(BN_set_word(prime,RSA_F4)) {
        if(!RSA_generate_key_ex(rsa_key, keybits, prime, &cb)) {
          CredentialLogger.msg(ERROR, "RSA_generate_key_ex failed");
          LogError();
          if(prime) BN_free(prime);
          return false;
        }
      }
      else{
        CredentialLogger.msg(ERROR, "BN_set_word failed");
        LogError();
        if(prime) BN_free(prime);
        if(rsa_key) RSA_free(rsa_key);
        return false;
      }
    }
    else {
      CredentialLogger.msg(ERROR, "BN_new || RSA_new failed");
      LogError();
      if(prime) BN_free(prime);
      if(rsa_key) RSA_free(rsa_key);
      return false;
    }
    if(prime) BN_free(prime);
#endif

    X509_REQ *req = NULL;
    CredentialLogger.msg(VERBOSE, "Created RSA key, proceeding with request");
    pkey = EVP_PKEY_new();

    if (pkey) {
      if (rsa_key) {
        CredentialLogger.msg(VERBOSE, "pkey and rsa_key exist!");
        if (EVP_PKEY_set1_RSA(pkey, rsa_key)) {
          req = X509_REQ_new();
          CredentialLogger.msg(VERBOSE, "Generate new X509 request!");
          if(req) {
            if (X509_REQ_set_version(req,3L)) {
              X509_NAME *name = NULL;
              unsigned long chtype = MBSTRING_ASC;  //TODO
              name = parse_name((char*)(dn.c_str()), chtype, 0);
              CredentialLogger.msg(VERBOSE, "Setting subject name!");

              X509_REQ_set_subject_name(req, name);
              X509_NAME_free(name);

              if(X509_REQ_set_pubkey(req,pkey)) {
                if(X509_REQ_sign(req,pkey,digest)) {
                  if(!(PEM_write_bio_X509_REQ(reqbio,req))){
                    CredentialLogger.msg(ERROR, "PEM_write_bio_X509_REQ failed");
                    LogError();
                    res = false;
                  }
                  else {
                    rsa_key_ = rsa_key;
                    rsa_key = NULL;
                    pkey_ = pkey;
                    pkey = NULL;
                    req_ = req;
                    res = true;
                  }
                }
              }
            }
          }
        }
      }
    }

    req_ = req;
    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::GenerateEECRequest ( std::string &  reqcontent,
std::string &  keycontent,
std::string  dn = "" 
)

Generate an EEC request, output the certificate request to a string.

Definition at line 1140 of file Credential.cpp.

                                                                                                  {
    BIO *req_out = BIO_new(BIO_s_mem());
    BIO *key_out = BIO_new(BIO_s_mem());
    if(!req_out || !key_out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for request");
      LogError(); return false;
    }

    if(GenerateEECRequest(req_out, key_out,dn)) {
      int l = 0;
      char s[256];

      while ((l = BIO_read(req_out,s,sizeof(s))) >= 0) {
        req_content.append(s,l);
      }

      l = 0;

      while ((l=BIO_read(key_out,s,sizeof(s))) >= 0) {
        key_content.append(s,l);
      }
    } else {
      CredentialLogger.msg(ERROR, "Failed to write request into string");
      BIO_free_all(req_out);
      BIO_free_all(key_out);
      return false;
    }

    BIO_free_all(req_out);
    BIO_free_all(key_out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::GenerateEECRequest ( const char *  request_filename,
const char *  key_filename,
std::string  dn = "" 
)

Generate an EEC request, output the certificate request and the key to a file.

Definition at line 1173 of file Credential.cpp.

                                                                                                      {
    BIO *req_out = BIO_new(BIO_s_file());
    BIO *key_out = BIO_new(BIO_s_file());
    if(!req_out || !key_out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for request");
      return false;
    }
    if (!(BIO_write_filename(req_out, (char*)req_filename))) {
      CredentialLogger.msg(ERROR, "Can not set writable file for request BIO");
      BIO_free_all(req_out); return false;
    }

    if (!(BIO_write_filename(key_out, (char*)key_filename))) {
      CredentialLogger.msg(ERROR, "Can not set writable file for request BIO");
      BIO_free_all(key_out);
      return false;
    }

    if(GenerateEECRequest(req_out,key_out, dn)) {
      CredentialLogger.msg(INFO, "Wrote request into a file");
    } else {
      CredentialLogger.msg(ERROR, "Failed to write request into a file");
      BIO_free_all(req_out);
      BIO_free_all(key_out);
      return false;
    }

    BIO_free_all(req_out);
    BIO_free_all(key_out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::GenerateRequest ( BIO *  bio,
bool  if_der = false 
)

Generate a proxy request, base on the keybits and signing algorithm information inside this object output the certificate request to output BIO.

Definition at line 1207 of file Credential.cpp.

                                                          {
    bool res = false;
    RSA* rsa_key = NULL;
    int keybits = keybits_;
    const EVP_MD *digest = signing_alg_;
    EVP_PKEY* pkey;

    if(pkey_) { CredentialLogger.msg(ERROR, "The credential's private key has already been initialized"); return false; };

#ifdef HAVE_OPENSSL_OLDRSA
    unsigned long prime = RSA_F4;
    rsa_key = RSA_generate_key(keybits, prime, keygen_cb, NULL);
    if(!rsa_key) {
      CredentialLogger.msg(ERROR, "RSA_generate_key failed");
      LogError();
      if(rsa_key) RSA_free(rsa_key);
      return false;
    }
#else
    BN_GENCB cb;
    BIGNUM *prime = BN_new();
    rsa_key = RSA_new();

    BN_GENCB_set(&cb,&keygen_cb,NULL);
    if(prime && rsa_key) {
      if(BN_set_word(prime,RSA_F4)) {
        if(RSA_generate_key_ex(rsa_key, keybits, prime, &cb) != 1) {
          CredentialLogger.msg(ERROR, "RSA_generate_key_ex failed");
          LogError();
          if(prime) BN_free(prime);
          return false;
        }
      }
      else{
        CredentialLogger.msg(ERROR, "BN_set_word failed");
        LogError();
        if(prime) BN_free(prime);
        if(rsa_key) RSA_free(rsa_key);
        return false; }
    }
    else {
      CredentialLogger.msg(ERROR, "BN_new || RSA_new failed");
      LogError();
      if(prime) BN_free(prime);
      if(rsa_key) RSA_free(rsa_key);
      return false;
    }
    if(prime) BN_free(prime);
#endif

    X509_REQ *req = NULL;
    pkey = EVP_PKEY_new();
    if(pkey){
      if(rsa_key) {
        if(EVP_PKEY_set1_RSA(pkey, rsa_key)) {
          req = X509_REQ_new();
          if(req) {
            if(X509_REQ_set_version(req,2L)) {
              //set the DN
              X509_NAME* name = NULL;
              X509_NAME_ENTRY* entry = NULL;
              if(cert_) { //self-sign, copy the X509_NAME
                if ((name = X509_NAME_dup(X509_get_subject_name(cert_))) == NULL) {
                  CredentialLogger.msg(ERROR, "Can not duplicate the subject name for the self-signing proxy certificate request");
                  LogError(); res = false;
                  if(pkey) EVP_PKEY_free(pkey);
                  if(rsa_key) RSA_free(rsa_key);
                  return res;
                }
              }
              else { name = X509_NAME_new();}
              if((entry = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, V_ASN1_APP_CHOOSE,
                          (unsigned char *) "NULL SUBJECT NAME ENTRY", -1)) == NULL) {
                CredentialLogger.msg(ERROR, "Can not create a new X509_NAME_ENTRY for the proxy certificate request");
                LogError(); res = false; X509_NAME_free(name);
                if(pkey) EVP_PKEY_free(pkey);
                if(rsa_key) RSA_free(rsa_key);
                return res;
              }
              X509_NAME_add_entry(name, entry, X509_NAME_entry_count(name), 0);
              X509_REQ_set_subject_name(req,name);
              X509_NAME_free(name); name = NULL;
              if(entry) { X509_NAME_ENTRY_free(entry); entry = NULL; }

              if(cert_type_ != CERT_TYPE_EEC) {

                // set the default PROXYCERTINFO extension
                std::string certinfo_sn;
                X509_EXTENSION* ext = NULL;
                if (CERT_IS_RFC_PROXY(cert_type_)) certinfo_sn = "PROXYCERTINFO_V4";
                else certinfo_sn = "PROXYCERTINFO_V3";
                //if(proxy_cert_info_->version == 3)

                if(!(certinfo_sn.empty())) {
                  const X509V3_EXT_METHOD*  ext_method = NULL;
                  unsigned char* data = NULL;
                  int length;
                  ext_method = X509V3_EXT_get_nid(OBJ_sn2nid(certinfo_sn.c_str()));
                  if(ext_method == NULL) {
                    CredentialLogger.msg(ERROR, "Can get X509V3_EXT_METHOD for %s",certinfo_sn.c_str());
                    LogError(); return false;
                  }
                  length = ext_method->i2d(proxy_cert_info_, NULL);
                  if(length < 0) {
                    CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
                    LogError();
                  }
                  else {
                    data = (unsigned char*) malloc(length);

                    unsigned char* derdata;
                    derdata = data;
                    length = ext_method->i2d(proxy_cert_info_,  &derdata);

                    if(length < 0) {
                      CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
                      free(data); data = NULL; LogError();
                    }
                  }
                  if(data) {
                    std::string ext_data((char*)data, length); free(data);
                    std::string certinfo_oid = PROXYCERTINFO_OPENSSL;
                    ext = CreateExtension(certinfo_oid, ext_data, 1);
                  }
                }

                if(ext) {
                  STACK_OF(X509_EXTENSION)* extensions;
                  extensions = sk_X509_EXTENSION_new_null();
                  sk_X509_EXTENSION_push(extensions, ext);
                  X509_REQ_add_extensions(req, extensions);
                  sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free);
                }

              }

              if(X509_REQ_set_pubkey(req,pkey)) {
                if(X509_REQ_sign(req,pkey,digest)  != 0) {
                  if(if_der == false) {
                    if(!(PEM_write_bio_X509_REQ(reqbio,req))){
                      CredentialLogger.msg(ERROR, "PEM_write_bio_X509_REQ failed");
                      LogError(); res = false;
                    }
                    else { rsa_key_ = rsa_key; rsa_key = NULL; pkey_ = pkey; pkey = NULL; res = true; }
                  }
                  else {
                    if(!(i2d_X509_REQ_bio(reqbio,req))){
                      CredentialLogger.msg(ERROR, "Can't convert X509 request from internal to DER encoded format");
                      LogError(); res = false;
                    }
                    else { rsa_key_ = rsa_key; rsa_key = NULL; pkey_ = pkey; pkey = NULL; res = true; }
                  }
                }
              }
            }
            //X509_REQ_free(req);
          }
          else { CredentialLogger.msg(ERROR, "Can not generate X509 request"); LogError(); res = false; }
        }
        else { CredentialLogger.msg(ERROR, "Can not set private key"); LogError(); res = false;}
      }
    }

    req_ = req;
    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::GenerateRequest ( std::string &  content,
bool  if_der = false 
)

Generate a proxy request, output the certificate request to a string.

Definition at line 1374 of file Credential.cpp.

                                                                  {
    BIO *out = BIO_new(BIO_s_mem());
    if(!out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for request");
      LogError(); return false;
    }

    if(GenerateRequest(out,if_der)) {
      for(;;) {
        char s[256];
        int l = BIO_read(out,s,sizeof(s));
        if(l <= 0) break;
        content.append(s,l);
      }
    }

    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::GenerateRequest ( const char *  filename,
bool  if_der = false 
)

Generate a proxy request, output the certificate request to a file.

Definition at line 1394 of file Credential.cpp.

                                                                    {
    BIO *out = BIO_new(BIO_s_file());
    if(!out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for request");
      LogError(); return false;
    }
    if (!(BIO_write_filename(out, (char*)filename))) {
      CredentialLogger.msg(ERROR, "Can not set writable file for request BIO");
      LogError(); BIO_free_all(out); return false;
    }

    if(GenerateRequest(out,if_der)) {
      CredentialLogger.msg(INFO, "Wrote request into a file");
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to write request into a file");
      BIO_free_all(out); return false;
    }

    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

X509 * Arc::Credential::GetCert ( void  )

Get the certificate attached to this object.

Definition at line 1757 of file Credential.cpp.

                                {
    X509* cert = NULL;
    if(cert_) cert = X509_dup(cert_);
    return cert;
  }

Here is the caller graph for this function:

Get the number of certificates in the certificate chain attached to this object.

Definition at line 1774 of file Credential.cpp.

                                        {
    //Return the number of certificates
    //in the issuer chain
    return sk_X509_num(cert_chain_) - 2;
  }

Here is the caller graph for this function:

X509_REQ * Arc::Credential::GetCertReq ( void  )

Get the certificate request, if there is any.

Definition at line 1041 of file Credential.cpp.

                                       {
    return req_;
  }

Here is the caller graph for this function:

std::string Arc::Credential::GetDN ( void  )

Get the DN of the certificate attached to this object.

Definition at line 274 of file Credential.cpp.

                                  {
    X509_NAME *subject = NULL;
    if(!cert_) return "";
    subject = X509_get_subject_name(cert_);
    std::string str;
    char buf[256];
    if(subject!=NULL)
      X509_NAME_oneline(subject,buf,sizeof(buf));
    str.append(buf);
    return str;
  }

Here is the caller graph for this function:

Returns validity end time of certificate or proxy.

Definition at line 347 of file Credential.cpp.

                              {
    return start_+lifetime_;
  }

Here is the caller graph for this function:

Credformat Arc::Credential::getFormat ( BIO *  in,
const bool  is_file = true 
)

Get the certificate format, PEM PKCS12 or DER BIO could be memory or file, they should be processed differently.

Definition at line 227 of file Credential.cpp.

                                                               {
    Credformat format = CRED_UNKNOWN;
    if(bio == NULL) return format;
    if(is_file) {
      char buf[1];
      char firstbyte;
      int position;
      if((position = BIO_tell(bio))<0 || BIO_read(bio, buf, 1)<=0 || BIO_seek(bio, position)<0) {
        LogError();
        CredentialLogger.msg(ERROR,"Can't get the first byte of input BIO to get its format");
        return format;
      }
      firstbyte = buf[0];
      // DER-encoded structure (including PKCS12) will start with ASCII 048.
      // Otherwise, it's PEM.
      if(firstbyte==48) {
        //DER-encoded, PKCS12 or DER? firstly parse it as PKCS12 ASN.1,
        //if can not parse it, then it is DER format
        PKCS12* pkcs12 = NULL;
        if((pkcs12 = d2i_PKCS12_bio(bio,NULL)) == NULL){ format=CRED_DER; PKCS12_free(pkcs12); }
        else { format = CRED_PKCS; PKCS12_free(pkcs12); }
        if( BIO_seek(bio, position) < 0 ) {
          LogError();
          CredentialLogger.msg(ERROR,"Can't reset the BIO");
          return format;
        }
      }
      else { format = CRED_PEM; }
    }
    else {
      unsigned char* bio_str;
      int len;
      len = BIO_get_mem_data(bio, (unsigned char *) &bio_str);
      char firstbyte;
      if(len>0) {
        firstbyte = bio_str[0];
        if(firstbyte==48)  {}
        else { format = CRED_PEM; }
      }
      else {
        CredentialLogger.msg(ERROR,"Can't get the first byte of input BIO to get its format");
        return format;
      }
    }
    return format;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

std::string Arc::Credential::GetIdentityName ( void  )

Get the Identity name of the certificate attached to this object, the result will not include proxy CN.

Definition at line 286 of file Credential.cpp.

                                            {
    X509_NAME *subject = NULL;
    X509_NAME_ENTRY *ne = NULL;
    if(!cert_) return "";
    subject = X509_NAME_dup(X509_get_subject_name(cert_));

#if 0
    int proxy_depth = verify_ctx_.proxy_depth;
    //std::cout<<"proxy depth: +++"<<verify_ctx_.proxy_depth<<std::endl;
    for(int i=0; i<proxy_depth; i++) {
      ne = X509_NAME_delete_entry(subject, X509_NAME_entry_count(subject)-1);
      if(ne)
        X509_NAME_ENTRY_free(ne);
    }
#endif

    ASN1_STRING* entry;
    std::string entry_str;
    for(;;) {
      ne = X509_NAME_get_entry(subject, X509_NAME_entry_count(subject)-1);
      if (!OBJ_cmp(ne->object,OBJ_nid2obj(NID_commonName))) {
        entry = X509_NAME_ENTRY_get_data(ne);
        entry_str.assign((const char*)(entry->data), (std::size_t)(entry->length));
        if(entry_str == "proxy" || entry_str == "limited proxy" ||
           entry_str.find_first_not_of("0123456789") == std::string::npos) {
          //Drop the name entry "proxy", "limited proxy", or the random digital(RFC)
          ne = X509_NAME_delete_entry(subject, X509_NAME_entry_count(subject)-1);
          X509_NAME_ENTRY_free(ne);
          ne = NULL;
        }
        else break;
      }
      else break;
    }

    std::string str;
    char buf[256];
    if(subject!=NULL) {
      X509_NAME_oneline(subject,buf,sizeof(buf));
      X509_NAME_free(subject);
    }
    str.append(buf);
    return str;
  }

Here is the caller graph for this function:

Returns lifetime of certificate or proxy.

Definition at line 339 of file Credential.cpp.

                                     {
    return lifetime_;
  }
EVP_PKEY * Arc::Credential::GetPrivKey ( void  )

Get the private key attached to this object.

Definition at line 1731 of file Credential.cpp.

                                      {
    EVP_PKEY* key = NULL;
    BIO*  bio = NULL;
    int length;
    bio = BIO_new(BIO_s_mem());
    if(pkey_ == NULL) {
      CredentialLogger.msg(ERROR, "Private key of the credential object is NULL");
      BIO_free(bio); return NULL;
    }
    length = i2d_PrivateKey_bio(bio, pkey_);
    if(length <= 0) {
      CredentialLogger.msg(ERROR, "Can not convert private key to DER format");
      LogError(); BIO_free(bio); return NULL;
    }
    key = d2i_PrivateKey_bio(bio, NULL);
    BIO_free(bio);

    return key;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

std::string Arc::Credential::GetProxyPolicy ( void  )

Get the proxy policy attached to the "proxy certificate information" extension of the proxy certicate.

Definition at line 335 of file Credential.cpp.

                                           {
    return (verify_ctx_.proxy_policy);
  }

Here is the caller graph for this function:

EVP_PKEY * Arc::Credential::GetPubKey ( void  )

Get the public key attached to this object.

Definition at line 1751 of file Credential.cpp.

                                     {
    EVP_PKEY* key = NULL;
    key = X509_get_pubkey(cert_);
    return key;
  }

Here is the caller graph for this function:

Returns validity start time of certificate or proxy.

Definition at line 343 of file Credential.cpp.

                                {
    return start_;
  }

Here is the caller graph for this function:

Get type of the certificate attached to this object.

Definition at line 331 of file Credential.cpp.

                                   {
    return cert_type_;
  }

Here is the caller graph for this function:

bool Arc::Credential::GetVerification ( void  ) [inline]

Get the verification result about certificate chain checking.

Definition at line 172 of file Credential.h.

{return verification_valid; };

Here is the caller graph for this function:

void Arc::Credential::InitProxyCertInfo ( void  ) [static]

Initiate nid for proxy certificate extension.

Definition at line 568 of file Credential.cpp.

                                         {
    static Glib::Mutex lock_;
    #define OBJC(c,n) OBJ_create(c,n,#c)
    X509V3_EXT_METHOD *pci_x509v3_ext_meth = NULL;

    // At least in some versions of OpenSSL functions manupulating
    // global lists seems to be not thread-safe despite locks
    // installed (tested for 0.9.7). Hence it is safer to protect
    // such calls.
    // It is also good idea to protect proxy_init_ too.

    Glib::Mutex::Lock lock(lock_);
    if(proxy_init_) return;

    /* Proxy Certificate Extension's related objects */
    if(OBJ_txt2nid(PROXYCERTINFO_V3) == NID_undef) {
      OBJC(PROXYCERTINFO_V3, "PROXYCERTINFO_V3");
      pci_x509v3_ext_meth = PROXYCERTINFO_v3_x509v3_ext_meth();
      if (pci_x509v3_ext_meth) {
        pci_x509v3_ext_meth->ext_nid = OBJ_txt2nid(PROXYCERTINFO_V3);
        X509V3_EXT_add(pci_x509v3_ext_meth);
      }
    }

    if(OBJ_txt2nid(PROXYCERTINFO_V4) == NID_undef) {
      OBJC(PROXYCERTINFO_V4, "PROXYCERTINFO_V4");
      pci_x509v3_ext_meth = PROXYCERTINFO_v4_x509v3_ext_meth();
      if (pci_x509v3_ext_meth) {
        pci_x509v3_ext_meth->ext_nid = OBJ_txt2nid(PROXYCERTINFO_V4);
        X509V3_EXT_add(pci_x509v3_ext_meth);
      }
    }

    if(OBJ_txt2nid(IMPERSONATION_PROXY_OID) == NID_undef) {
      OBJ_create(IMPERSONATION_PROXY_OID, IMPERSONATION_PROXY_SN, IMPERSONATION_PROXY_LN);
    }
    if(OBJ_txt2nid(INDEPENDENT_PROXY_OID) == NID_undef) {
      OBJ_create(INDEPENDENT_PROXY_OID, INDEPENDENT_PROXY_SN, INDEPENDENT_PROXY_LN);
    }
    if(OBJ_txt2nid(ANYLANGUAGE_PROXY_OID) == NID_undef) {
      OBJ_create(ANYLANGUAGE_PROXY_OID, ANYLANGUAGE_PROXY_SN, ANYLANGUAGE_PROXY_LN);
    }
    if(OBJ_txt2nid(LIMITED_PROXY_OID) == NID_undef) {
      OBJ_create(LIMITED_PROXY_OID, LIMITED_PROXY_SN, LIMITED_PROXY_LN);
    }
    // This library provides methods and objects which when registred in
    // global OpenSSL lists can't be unregistred anymore. Hence it must not
    // be allowed to unload.
    if(!PersistentLibraryInit("modcredential")) {
      CredentialLogger.msg(WARNING, "Failed to lock arccredential library in memory");
    };
    proxy_init_=true;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::InitVerification ( void  ) [private]

Initiate cert_verify_context which will be used for certificate verification.

Definition at line 626 of file Credential.cpp.

Here is the caller graph for this function:

bool Arc::Credential::InquireRequest ( BIO *  reqbio,
bool  if_eec = false,
bool  if_der = false 
)

Inquire the certificate request from BIO, and put the request information to X509_REQ inside this object, and parse the certificate type from the PROXYCERTINFO of request' extension.

Parameters:
if_derfalse for PEM; true for DER

Definition at line 1570 of file Credential.cpp.

                                                                      {
    bool res = false;
    if(reqbio == NULL) { CredentialLogger.msg(ERROR, "NULL BIO passed to InquireRequest"); return false; }
    if(req_) {X509_REQ_free(req_); req_ = NULL; }
    if((if_der == false) && (!(PEM_read_bio_X509_REQ(reqbio, &req_, NULL, NULL)))) {
      CredentialLogger.msg(ERROR, "PEM_read_bio_X509_REQ failed");
      LogError(); return false;
    }
    else if((if_der == true) && (!(d2i_X509_REQ_bio(reqbio, &req_)))) {
      CredentialLogger.msg(ERROR, "d2i_X509_REQ_bio failed");
      LogError(); return false;
    }

    STACK_OF(X509_EXTENSION)* req_extensions = NULL;
    X509_EXTENSION* ext;
    PROXYPOLICY*  policy = NULL;
    ASN1_OBJECT*  policy_lang = NULL;
    ASN1_OBJECT*  extension_oid = NULL;
    int certinfo_old_NID, certinfo_NID, nid = NID_undef;
    int i;

    //Get the PROXYCERTINFO from request' extension
    req_extensions = X509_REQ_get_extensions(req_);
    certinfo_old_NID = OBJ_txt2nid(PROXYCERTINFO_V3);
    certinfo_NID = OBJ_txt2nid(PROXYCERTINFO_V4);
    for(i=0;i<sk_X509_EXTENSION_num(req_extensions);i++) {
      ext = sk_X509_EXTENSION_value(req_extensions,i);
      extension_oid = X509_EXTENSION_get_object(ext);
      nid = OBJ_obj2nid(extension_oid);
      if((nid != 0) && (nid == certinfo_old_NID || nid == certinfo_NID)) {
        if(proxy_cert_info_) {
          PROXYCERTINFO_free(proxy_cert_info_);
          proxy_cert_info_ = NULL;
        }
        if((proxy_cert_info_ = (PROXYCERTINFO*)X509V3_EXT_d2i(ext)) == NULL) {
           CredentialLogger.msg(ERROR, "Can not convert DER encoded PROXYCERTINFO extension to internal format");
           LogError(); goto err;
        }
        break;
      }
    }

    if(proxy_cert_info_) {
      if((policy = PROXYCERTINFO_get_proxypolicy(proxy_cert_info_)) == NULL) {
        CredentialLogger.msg(ERROR, "Can not get policy from PROXYCERTINFO extension");
        LogError(); goto err;
      }
      if((policy_lang = PROXYPOLICY_get_policy_language(policy)) == NULL) {
        CredentialLogger.msg(ERROR, "Can not get policy language from PROXYCERTINFO extension");
        LogError(); goto err;
      }
      int policy_nid = OBJ_obj2nid(policy_lang);
      if((nid != 0) && (nid == certinfo_old_NID)) {
        if(policy_nid == OBJ_txt2nid(IMPERSONATION_PROXY_OID)) { cert_type_= CERT_TYPE_GSI_3_IMPERSONATION_PROXY; }
        else if(policy_nid == OBJ_txt2nid(INDEPENDENT_PROXY_OID)) { cert_type_ = CERT_TYPE_GSI_3_INDEPENDENT_PROXY; }
        else if(policy_nid == OBJ_txt2nid(LIMITED_PROXY_OID)) { cert_type_ = CERT_TYPE_GSI_3_LIMITED_PROXY; }
        else { cert_type_ = CERT_TYPE_GSI_3_RESTRICTED_PROXY; }
      }
      else {
        if(policy_nid == OBJ_txt2nid(IMPERSONATION_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_IMPERSONATION_PROXY; }
        else if(policy_nid == OBJ_txt2nid(INDEPENDENT_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_INDEPENDENT_PROXY; }
        else if(policy_nid == OBJ_txt2nid(ANYLANGUAGE_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_ANYLANGUAGE_PROXY; }
        else if(policy_nid == OBJ_txt2nid(LIMITED_PROXY_OID)) { cert_type_ = CERT_TYPE_RFC_LIMITED_PROXY; }
        else { cert_type_ = CERT_TYPE_RFC_RESTRICTED_PROXY; }
      }
    }
    //If can not find proxy_cert_info, depend on the parameters to distinguish the type: if
    //it is not eec request, then treat it as RFC proxy request
    else if(if_eec == false) { cert_type_ =  CERT_TYPE_RFC_INDEPENDENT_PROXY; } //CERT_TYPE_GSI_2_PROXY; }
    else { cert_type_ = CERT_TYPE_EEC; }

    CredentialLogger.msg(DEBUG,"Cert Type: %d",cert_type_);

    res = true;

err:
    if(req_extensions != NULL) { sk_X509_EXTENSION_pop_free(req_extensions, X509_EXTENSION_free); }

    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::InquireRequest ( std::string &  content,
bool  if_eec = false,
bool  if_der = false 
)

Inquire the certificate request from a string.

Definition at line 1651 of file Credential.cpp.

                                                                              {
    BIO *in;
    if(!(in = BIO_new_mem_buf((void*)(content.c_str()), content.length()))) {
      CredentialLogger.msg(ERROR, "Can not create BIO for parsing request");
      LogError(); return false;
    }

    if(InquireRequest(in,if_eec,if_der)) {
      CredentialLogger.msg(INFO, "Read request from a string");
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to read request from a string");
      BIO_free_all(in); return false;
    }

    BIO_free_all(in);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::InquireRequest ( const char *  filename,
bool  if_eec = false,
bool  if_der = false 
)

Inquire the certificate request from a file.

Definition at line 1670 of file Credential.cpp.

                                                                                {
    BIO *in = BIO_new(BIO_s_file());
    if(!in) {
      CredentialLogger.msg(ERROR, "Can not create BIO for parsing request");
      LogError(); return false;
    }
    if (!(BIO_read_filename(in, (char*)filename))) {
      CredentialLogger.msg(ERROR, "Can not set readable file for request BIO");
      LogError(); BIO_free_all(in); return false;
    }

    if(InquireRequest(in,if_eec,if_der)) {
      CredentialLogger.msg(INFO, "Read request from a file");
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to read request from a file");
      BIO_free_all(in); return false;
    }

    BIO_free_all(in);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::IsCredentialsValid ( const UserConfig usercfg) [static]

Definition at line 359 of file Credential.cpp.

                                                               {
    Credential cred(!usercfg.ProxyPath().empty() ? usercfg.ProxyPath() : usercfg.CertificatePath(),
                    !usercfg.ProxyPath().empty() ? ""                  : usercfg.KeyPath(),
                    usercfg.CACertificatesDirectory(), usercfg.CACertificatePath());
    Time t;
    return cred.verification_valid && cred.GetStartTime() < t && t < cred.GetEndTime();
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::loadCertificate ( BIO *  bio,
X509 *&  x509,
STACK_OF(X509)**  certchain,
const bool  is_file = true 
) [private]

Definition at line 403 of file Credential.cpp.

                                                                                                            {
    //Parse the certificate
    Credformat format = CRED_UNKNOWN;
    PKCS12* pkcs12 = NULL;
    STACK_OF(X509)* pkcs12_certs = NULL;

    if(certbio == NULL) return;
    format = getFormat(certbio, is_file);
    int n;
    if(*certchain) {
      sk_X509_pop_free(*certchain, X509_free);
      *certchain = NULL;
    }

    switch(format) {
      case CRED_PEM:
        CredentialLogger.msg(DEBUG,"Certificate format is PEM");
        //Get the certificte, By default, certificate is without passphrase
        //Read certificate
        if(!(PEM_read_bio_X509(certbio, &x509, NULL, NULL))) {
          throw CredentialError("Can not read cert information from BIO");
        }
        //Get the issuer chain
        *certchain = sk_X509_new_null();
        n = 0;
        while(!BIO_eof(certbio)){
          X509 * tmp = NULL;
          if(!(PEM_read_bio_X509(certbio, &tmp, NULL, NULL))){
            ERR_clear_error(); break;
          }
          if(!sk_X509_insert(*certchain, tmp, n)) {
            //std::string str(X509_NAME_oneline(X509_get_subject_name(tmp),0,0));
            X509_free(tmp);
            throw CredentialError("Can not insert cert into certificate's issuer chain");
          }
          ++n;
        }
        break;

      case CRED_DER:
        CredentialLogger.msg(DEBUG,"Certificate format is DER");
        x509=d2i_X509_bio(certbio,NULL);
        if(!x509){
          throw CredentialError("Unable to read DER credential from BIO");
        }
        //Get the issuer chain
        *certchain = sk_X509_new_null();
        n = 0;
        while(!BIO_eof(certbio)){
          X509 * tmp = NULL;
          if(!(d2i_X509_bio(certbio, &tmp))){
            ERR_clear_error(); break;
          }
          if(!sk_X509_insert(*certchain, tmp, n)) {
            //std::string str(X509_NAME_oneline(X509_get_subject_name(tmp),0,0));
            X509_free(tmp);
            throw CredentialError("Can not insert cert into certificate's issuer chain");
          }
          ++n;
        }
        break;

      case CRED_PKCS:
        CredentialLogger.msg(DEBUG,"Certificate format is PKCS");
        pkcs12 = d2i_PKCS12_bio(certbio, NULL);
        if(pkcs12){
          char password[100];
          EVP_read_pw_string(password, 100, "Enter Password for PKCS12 certificate:", 0);
          if(!PKCS12_parse(pkcs12, password, NULL, &x509, &pkcs12_certs)) {
            if(pkcs12) PKCS12_free(pkcs12);
            throw CredentialError("Can not parse PKCS12 file");
          }
        }
        else{
          throw CredentialError("Can not read PKCS12 credential from BIO");
        }
        if (pkcs12_certs && sk_X509_num(pkcs12_certs)){
          X509* tmp;
          for (n = 0; n < sk_X509_num(pkcs12_certs); n++) {
            tmp = X509_dup(sk_X509_value(pkcs12_certs, n));
            sk_X509_insert(*certchain, tmp, n);
          }
        }
        if(pkcs12) { PKCS12_free(pkcs12); }
        if(pkcs12_certs) { sk_X509_pop_free(pkcs12_certs, X509_free); }

        break;

      default:
        CredentialLogger.msg(DEBUG,"Certificate format is unknown");
        break;
     } // end switch
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::loadCertificateFile ( const std::string &  certfile,
X509 *&  x509,
STACK_OF(X509)**  certchain 
) [private]

Definition at line 389 of file Credential.cpp.

                                                                                                         {
    if(!Glib::file_test(certfile,Glib::FILE_TEST_IS_REGULAR)) {
        CredentialLogger.msg(ERROR,"Can not find certificate file: %s", certfile);
        throw CredentialError("Can not find certificate file");
    }
    AutoBIO certbio(BIO_new_file(certfile.c_str(), "r"));
    if(!certbio){
      CredentialLogger.msg(ERROR,"Can not read certificate file: %s", certfile);
      LogError();
      throw CredentialError("Can not read certificate file");
    }
    loadCertificate(certbio,x509,certchain, true);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::loadCertificateString ( const std::string &  cert,
X509 *&  x509,
STACK_OF(X509)**  certchain 
) [private]

load certificate from argument certbio, and put certificate information into argument cert and certchain

Definition at line 379 of file Credential.cpp.

                                                                                                       {
    AutoBIO certbio(BIO_new_mem_buf((void*)(cert.c_str()), cert.length()));
    if(!certbio){
      CredentialLogger.msg(ERROR,"Can not read certificate string");
      LogError();
      throw CredentialError("Can not read certificate string");
    }
    loadCertificate(certbio,x509,certchain, false);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::loadKey ( BIO *  bio,
EVP_PKEY *&  pkey,
const std::string &  passphrase = "",
const std::string &  prompt_info = "",
const bool  is_file = true 
) [private]

Definition at line 521 of file Credential.cpp.

                                                                                                                                      {
    //Read key
    Credformat format;
    PKCS12* pkcs12 = NULL;

    if(keybio == NULL) return;
    format = getFormat(keybio, is_file);
    std::string prompt;
    switch(format){
      case CRED_PEM:
        PW_CB_DATA cb_data;
        cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
        cb_data.prompt_info = prompt_info.empty() ? NULL : prompt_info.c_str();
        if(!(pkey = PEM_read_bio_PrivateKey(keybio, NULL, (pem_password_cb *)passwordcb, &cb_data))) {
          int reason = ERR_GET_REASON(ERR_peek_error());
          if(reason == PEM_R_BAD_BASE64_DECODE ||
            reason == PEM_R_BAD_DECRYPT ||
            reason == PEM_R_BAD_PASSWORD_READ ||
            reason == PEM_R_PROBLEMS_GETTING_PASSWORD)
            throw CredentialError("Can not read PEM private key: Bad password");
          else throw CredentialError("Can not read PEM private key");
        }
        break;

      case CRED_DER:
        pkey=d2i_PrivateKey_bio(keybio, NULL);
        break;

      case CRED_PKCS:
        pkcs12 = d2i_PKCS12_bio(keybio, NULL);
        if(pkcs12) {
          char password[100];
          EVP_read_pw_string(password, 100, "Enter Password for PKCS12 certificate:", 0);
          if(!PKCS12_parse(pkcs12, password, &pkey, NULL, NULL)) {
            throw CredentialError("Can not parse PKCS12");
          }
          PKCS12_free(pkcs12);
        }
        break;

      default:
        break;
    }
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::loadKeyFile ( const std::string &  keyfile,
EVP_PKEY *&  pkey,
const std::string &  passphrase = "" 
) [private]

Definition at line 507 of file Credential.cpp.

                                                                                                     {
    if(!Glib::file_test(keyfile,Glib::FILE_TEST_IS_REGULAR)) {
        CredentialLogger.msg(ERROR,"Can not find key file: %s", keyfile);
        throw CredentialError("Can not find key file");
    }
    AutoBIO keybio(BIO_new_file(keyfile.c_str(), "r"));
    if(!keybio){
      CredentialLogger.msg(ERROR,"Can not open key file %s", keyfile);
      LogError();
      throw CredentialError("Can not open key file " + keyfile);
    }
    loadKey(keybio,pkey,passphrase, keyfile, true);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::loadKeyString ( const std::string &  key,
EVP_PKEY *&  pkey,
const std::string &  passphrase = "" 
) [private]

load key from argument keybio, and put key information into argument pkey

Definition at line 497 of file Credential.cpp.

                                                                                                   {
    AutoBIO keybio(BIO_new_mem_buf((void*)(key.c_str()), key.length()));
    if(!keybio){
      CredentialLogger.msg(ERROR,"Can not read key string");
      LogError();
      throw CredentialError("Can not read key string");
    }
    loadKey(keybio,pkey,passphrase, "Load key from a string", false);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::LogError ( void  )

Log error information related with openssl.

Definition at line 172 of file Credential.cpp.

                                {
    ERR_print_errors_cb(&ssl_err_cb, &CredentialLogger);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::OutputCertificate ( std::string &  content,
bool  is_der = false 
)

Output the certificate into string.

Parameters:
is_derfalse for PEM, true for DER

Definition at line 1518 of file Credential.cpp.

                                                                    {
    BIO *out = BIO_new(BIO_s_mem());
    if(!out) return false;
    if(if_der == false) {
      if(!PEM_write_bio_X509(out,cert_)) { BIO_free_all(out); return false; };
    }
    else {
      if(!i2d_X509_bio(out,cert_)) { BIO_free_all(out); return false; };
    }

    for(;;) {
      char s[256];
      int l = BIO_read(out,s,sizeof(s));
      if(l <= 0) break;
      content.append(s,l);
    }
    BIO_free_all(out);
    return true;
  }

Here is the caller graph for this function:

bool Arc::Credential::OutputCertificateChain ( std::string &  content,
bool  is_der = false 
)

Output the certificate chain into string.

Parameters:
is_derfalse for PEM, true for DER

Definition at line 1538 of file Credential.cpp.

                                                                         {
    BIO *out = BIO_new(BIO_s_mem());
    if(!out) return false;
    X509 *cert;
    CredentialLogger.msg(DEBUG, "Certiticate chain number %d",sk_X509_num(cert_chain_));
    //std::cout<<"+++++ cert chain number: "<<sk_X509_num(cert_chain_)<<std::endl;

    //Out put the cert chain. After the verification the cert_chain_
    //will include the CA certificate and the certificate (which
    //need to be verified here) itself.
    //Those two certificates are excluded when outputing
    for (int n = 1; n < sk_X509_num(cert_chain_) - 1 ; n++) {
      cert = sk_X509_value(cert_chain_, n);
      if(if_der == false) {
        if(!PEM_write_bio_X509(out,cert)) { BIO_free_all(out); return false; };
      }
      else {
        if(!i2d_X509_bio(out,cert)) { BIO_free_all(out); return false; };
      }

      for(;;) {
        char s[256];
        int l = BIO_read(out,s,sizeof(s));
        if(l <= 0) break;
        content.append(s,l);
      }
    }
    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::OutputPrivatekey ( std::string &  content,
bool  encryption = false,
const std::string &  passphrase = "" 
)

Output the private key into string.

Parameters:
encryption,whetherencrypt the output private key or not
passphrase,thepassphrase to encrypt the output private key

Definition at line 1417 of file Credential.cpp.

                                                                                                    {
    BIO *out = BIO_new(BIO_s_mem());
    EVP_CIPHER *enc = NULL;
    if(!out) return false;
    if(rsa_key_ != NULL) {
      if(!encryption) {
        if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0,NULL,NULL)) {
          BIO_free_all(out); return false;
        }
      }
      else {
        enc = (EVP_CIPHER*)EVP_des_ede3_cbc();
#if 0
        std::string prompt;
        prompt = "Enter passphrase to encrypt the PEM key file: ";
        if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0,passwordcb,
          (passphrase.empty())?NULL:(void*)(passphrase.c_str()))) {
          BIO_free_all(out); return false;
        }
#endif
        PW_CB_DATA cb_data;
        cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
        cb_data.prompt_info = NULL;
        if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0, (pem_password_cb *)passwordcb,&cb_data)) {
          BIO_free_all(out); return false;
        }
      }
    }
    else if(pkey_ != NULL) {
      if(!encryption) {
        if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0,NULL,NULL)) {
          BIO_free_all(out); return false;
        }
      }
      else {
        enc = (EVP_CIPHER*)EVP_des_ede3_cbc();
#if 0
        std::string prompt;
        prompt = "Enter passphrase to encrypt the PEM key file: ";
        if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0,passwordcb,
          (passphrase.empty())?NULL:(void*)(passphrase.c_str()))) {
          BIO_free_all(out); return false;
        }
#endif
        PW_CB_DATA cb_data;
        cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
        cb_data.prompt_info = NULL;
        if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0, (pem_password_cb *)passwordcb,&cb_data)) {
          BIO_free_all(out); return false;
        }
      }
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to get private key");
      BIO_free_all(out); return false;
    }

    for(;;) {
      char s[256];
      int l = BIO_read(out,s,sizeof(s));
      if(l <= 0) break;
      content.append(s,l);
    }
    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::OutputPublickey ( std::string &  content)

Output the public key into string.

Definition at line 1484 of file Credential.cpp.

                                                     {
    BIO *out = BIO_new(BIO_s_mem());
    if(!out) return false;
    if(rsa_key_ != NULL) {
      if(!PEM_write_bio_RSAPublicKey(out,rsa_key_)) {
        CredentialLogger.msg(ERROR, "Failed to get public key from RSA object");
        BIO_free_all(out); return false;
      };
    }
    else if(cert_ != NULL) {
      EVP_PKEY *pkey = NULL;
      pkey = X509_get_pubkey(cert_);
      if(pkey == NULL) {
        CredentialLogger.msg(ERROR, "Failed to get public key from X509 object");
        BIO_free_all(out); return false;
      };
      PEM_write_bio_PUBKEY(out, pkey);
      EVP_PKEY_free(pkey);
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to get public key");
      BIO_free_all(out); return false;
    }

    for(;;) {
      char s[256];
      int l = BIO_read(out,s,sizeof(s));
      if(l <= 0) break;
      content.append(s,l);
    }
    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

X509_NAME * Arc::Credential::parse_name ( char *  subject,
long  chtype,
int  multirdn 
) [static, private]

Definition at line 2441 of file Credential.cpp.

                                                                             {
    size_t buflen = strlen(subject)+1;
    /* to copy the types and values into. due to escaping, the copy can only become shorter */
    char *buf = (char*)(OPENSSL_malloc(buflen));
    size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
    char **ne_types =  (char **)(OPENSSL_malloc(max_ne * sizeof (char *)));
    char **ne_values = (char **)(OPENSSL_malloc(max_ne * sizeof (char *)));
    int *mval = (int*)(OPENSSL_malloc (max_ne * sizeof (int)));

    char *sp = subject, *bp = buf;
    int i, ne_num = 0;

    X509_NAME *n = NULL;
    int nid;

    if (!buf || !ne_types || !ne_values) {
      CredentialLogger.msg(ERROR,"malloc error");
      goto error;
    }
    if (*subject != '/') {
      CredentialLogger.msg(ERROR,"Subject does not start with '/'");
      goto error;
    }
    sp++; /* skip leading / */

    /* no multivalued RDN by default */
    mval[ne_num] = 0;
    while (*sp) {
      /* collect type */
      ne_types[ne_num] = bp;
      while (*sp) {
        if (*sp == '\\') /* is there anything to escape in the type...? */
        {
          if (*++sp)
          *bp++ = *sp++;
          else {
            CredentialLogger.msg(ERROR,"escape character at end of string");
            goto error;
          }
        }
        else if (*sp == '=') {
          sp++;
          *bp++ = '\0';
          break;
        }
        else  *bp++ = *sp++;
      }
      if (!*sp) {
        CredentialLogger.msg(ERROR,"end of string encountered while processing type of subject name element #%d",ne_num);
        goto error;
      }
      ne_values[ne_num] = bp;
      while (*sp) {
        if (*sp == '\\') {
          if (*++sp)
            *bp++ = *sp++;
          else {
            CredentialLogger.msg(ERROR,"escape character at end of string");
            goto error;
          }
        }
        else if (*sp == '/') {
          sp++;
          /* no multivalued RDN by default */
          mval[ne_num+1] = 0;
          break;
        }
        else if (*sp == '+' && multirdn) {
          /* a not escaped + signals a mutlivalued RDN */
          sp++;
          mval[ne_num+1] = -1;
          break;
        }
        else
          *bp++ = *sp++;
      }
      *bp++ = '\0';
      ne_num++;
    }

    if (!(n = X509_NAME_new()))
      goto error;

    for (i = 0; i < ne_num; i++) {
      if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef) {
        CredentialLogger.msg(ERROR,"Subject Attribute %s has no known NID, skipped",ne_types[i]);
        continue;
      }
      if (!*ne_values[i]) {
        CredentialLogger.msg(ERROR,"No value provided for Subject Attribute %s skipped",ne_types[i]);
        continue;
      }

      if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
        goto error;
    }

    OPENSSL_free(mval);
    OPENSSL_free(ne_values);
    OPENSSL_free(ne_types);
    OPENSSL_free(buf);
    return n;

error:
    X509_NAME_free(n);
    if (ne_values)
      OPENSSL_free(ne_values);
    if (ne_types)
      OPENSSL_free(ne_types);
    if (buf)
      OPENSSL_free(buf);
    return NULL;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::SetLifeTime ( const Period period)

Set lifetime of certificate or proxy.

Definition at line 351 of file Credential.cpp.

                                                   {
    lifetime_ = period;
  }

Here is the caller graph for this function:

bool Arc::Credential::SetProxyPeriod ( X509 *  tosign,
X509 *  issuer,
Time start,
Period lifetime 
) [private]

Set the start and end time for the proxy credential.

After setting, the start time of proxy will not before the later value from issuer's start time and the "start" parameter, and the end time of proxy will not after the ealier value from issuer's end time and the "start" parameter plus "lifetime" paremeter

Definition at line 1693 of file Credential.cpp.

                                                                                           {
    ASN1_UTCTIME* notBefore = NULL;
    ASN1_UTCTIME* notAfter = NULL;
    time_t t1 = start.GetTime();
    Time tmp = start + lifetime;
    time_t t2 = tmp.GetTime();

    //Set "notBefore"
    if( X509_cmp_time(X509_get_notBefore(issuer), &t1) < 0) {
      X509_time_adj(X509_get_notBefore(tosign), 0L, &t1);
    }
    else {
      X509_set_notBefore(tosign, X509_get_notBefore(issuer));
    }

    //Set "not After"
#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
    ASN1_UTCTIME*  atime = X509_get_notAfter(issuer);
    Time end = asn1_to_utctime(atime);
    if(Time(t2) < end) {
      X509_time_adj(X509_get_notAfter(tosign), 0L, &t2);
    }
    else {
      t2 = end.GetTime();
      X509_time_adj(X509_get_notAfter(tosign), 0L, &t2);
    }
#else
    if( X509_cmp_time(X509_get_notAfter(issuer), &t2) > 0) {
      X509_time_adj(X509_get_notAfter(tosign), 0L, &t2);
    }
    else {
      X509_set_notAfter(tosign, X509_get_notAfter(issuer));
    }
#endif

    return true;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::SetProxyPolicy ( const std::string &  proxyversion,
const std::string &  policylang,
const std::string &  policy,
int  pathlength 
)

Set the proxy policy attached to the "proxy certificate information" extension of the proxy certicate.

here the definition about policy languange is redundant with above definition, but it could cover "restricted" language which has no explicit definition according to http://dev.globus.org/wiki/Security/ProxyCertTypes

Definition at line 698 of file Credential.cpp.

                                                 {

    proxyversion_ = proxyversion;
    policy_ = policy;
    policylang_ = policylang;
    pathlength_ = pathlength;

    //Get certType
    if(proxyversion_.compare("GSI2") == 0 || proxyversion_.compare("gsi2") == 0) {
      if(policylang_.compare("LIMITED") == 0 || policylang_.compare("limited") == 0) {
        cert_type_ = CERT_TYPE_GSI_2_LIMITED_PROXY;
      }
      else if (policylang_.compare("RESTRICTED") == 0 || policylang_.compare("restricted") == 0) {
        CredentialLogger.msg(ERROR,"Globus legacy proxies can not carry policy data or path length contraints");
      }
      else {
        cert_type_ = CERT_TYPE_GSI_2_PROXY;
      }
    }
    else if (proxyversion_.compare("RFC") == 0 || proxyversion_.compare("rfc") == 0) {
      //The "limited" and "restricted" are from the definition in
      //http://dev.globus.org/wiki/Security/ProxyCertTypes#RFC_3820_Proxy_Certificates
      if(policylang_.compare("LIMITED") == 0 || policylang_.compare("limited") == 0) {
        cert_type_ = CERT_TYPE_RFC_LIMITED_PROXY;
      }
      else if(policylang_.compare("RESTRICTED") == 0 || policylang_.compare("restricted") == 0) {
        cert_type_ = CERT_TYPE_RFC_RESTRICTED_PROXY;
      }
      else if(policylang_.compare("INDEPENDENT") == 0 || policylang_.compare("independent") == 0) {
        cert_type_ = CERT_TYPE_RFC_INDEPENDENT_PROXY;
      }
      else if(policylang_.compare("IMPERSONATION") == 0 || policylang_.compare("impersonation") == 0 ||
         policylang_.compare("INHERITALL") == 0 || policylang_.compare("inheritAll") == 0){
        cert_type_ = CERT_TYPE_RFC_IMPERSONATION_PROXY;
        //For RFC here, "impersonation" is the same as the "inheritAll" in openssl version>098
      }
      else if(policylang_.compare("ANYLANGUAGE") == 0 || policylang_.compare("anylanguage") == 0) {
        cert_type_ = CERT_TYPE_RFC_ANYLANGUAGE_PROXY;  //Defined in openssl version>098
      }
    }
    else if (proxyversion_.compare("EEC") == 0 || proxyversion_.compare("eec") == 0) {
      cert_type_ = CERT_TYPE_EEC;
    }
    else {
      if(policylang_.compare("LIMITED") == 0 || policylang_.compare("limited") == 0) {
        cert_type_ = CERT_TYPE_GSI_3_LIMITED_PROXY;
      }
      else if(policylang_.compare("RESTRICTED") == 0 || policylang_.compare("restricted") == 0) {
        cert_type_ = CERT_TYPE_GSI_3_RESTRICTED_PROXY;
      }
      else if(policylang_.compare("INDEPENDENT") == 0 || policylang_.compare("independent") == 0) {
        cert_type_ = CERT_TYPE_GSI_3_INDEPENDENT_PROXY;
      }
      else {
        cert_type_ = CERT_TYPE_GSI_3_IMPERSONATION_PROXY;
      }
    }

    if(cert_type_ != CERT_TYPE_EEC) {
      if(!policy_.empty() && policylang_.empty()) {
        CredentialLogger.msg(ERROR,"If you specify a policy you also need to specify a policy language");
        return;
      }

      if(proxy_cert_info_) {
        PROXYCERTINFO_free(proxy_cert_info_);
        proxy_cert_info_ = NULL;
      }

      proxy_cert_info_ = PROXYCERTINFO_new();
      PROXYPOLICY *   ppolicy =PROXYCERTINFO_get_proxypolicy(proxy_cert_info_);
      PROXYPOLICY_set_policy(ppolicy, NULL, 0);
      ASN1_OBJECT *   policy_object = NULL;

      //set policy language, see definiton in: http://dev.globus.org/wiki/Security/ProxyCertTypes
      switch(cert_type_)
      {
        case CERT_TYPE_GSI_3_IMPERSONATION_PROXY:
        case CERT_TYPE_RFC_IMPERSONATION_PROXY:
          if((policy_object = OBJ_nid2obj(OBJ_txt2nid(IMPERSONATION_PROXY_OID))) != NULL) {
            PROXYPOLICY_set_policy_language(ppolicy, policy_object);
          }
          break;

        case CERT_TYPE_GSI_3_INDEPENDENT_PROXY:
        case CERT_TYPE_RFC_INDEPENDENT_PROXY:
          if((policy_object = OBJ_nid2obj(OBJ_txt2nid(INDEPENDENT_PROXY_OID))) != NULL) {
            PROXYPOLICY_set_policy_language(ppolicy, policy_object);
          }
          break;

        case CERT_TYPE_GSI_3_LIMITED_PROXY:
        case CERT_TYPE_RFC_LIMITED_PROXY:
          if((policy_object = OBJ_nid2obj(OBJ_txt2nid(LIMITED_PROXY_OID))) != NULL) {
            PROXYPOLICY_set_policy_language(ppolicy, policy_object);
          }
          break;
        case CERT_TYPE_RFC_ANYLANGUAGE_PROXY:
          if((policy_object = OBJ_nid2obj(OBJ_txt2nid(ANYLANGUAGE_PROXY_OID))) != NULL) {
            PROXYPOLICY_set_policy_language(ppolicy, policy_object);
          }
          break;
        default:
          break;
      }

      //set path length constraint
      if(pathlength >= 0)
      PROXYCERTINFO_set_path_length(proxy_cert_info_, pathlength_);

      //set policy
      std::string policystring;
      if(!policy_.empty()) {
        if(Glib::file_test(policy_,Glib::FILE_TEST_EXISTS)) {
          //If the argument is a location which specifies a file that
          //includes the policy content
          if(Glib::file_test(policy_,Glib::FILE_TEST_IS_REGULAR)) {
            std::ifstream fp;
            fp.open(policy_.c_str());
            if(!fp) {
              CredentialLogger.msg(ERROR,"Error: can't open policy file: %s", policy_.c_str());
              if(proxy_cert_info_) {
                PROXYCERTINFO_free(proxy_cert_info_);
                proxy_cert_info_ = NULL;
              }
              return;
            }
            fp.unsetf(std::ios::skipws);
            char c;
            while(fp.get(c))
              policystring += c;
          }
          else {
            CredentialLogger.msg(ERROR,"Error: policy location: %s is not a regular file", policy_.c_str());
            if(proxy_cert_info_) {
              PROXYCERTINFO_free(proxy_cert_info_);
              proxy_cert_info_ = NULL;
            }
            return;
          }
        }
        else {
          //Otherwise the argument should include the policy content
          policystring = policy_;
        }
      }

      if(policylang_ == "LIMITED" || policylang_ == "limited")
        policylang_ = LIMITED_PROXY_OID;
      else if(policylang_ == "INDEPENDENT" || policylang_ == "independent")
        policylang_ = INDEPENDENT_PROXY_OID;
      else if(policylang_ == "IMPERSONATION" || policylang_ == "impersonation"
          || policylang_ == "inheritAll" || policylang_ == "INHERITALL")
        policylang_ = IMPERSONATION_PROXY_OID;
      else if(policylang_.empty()) {
        if(policy_.empty()) policylang_ = IMPERSONATION_PROXY_OID;
        else policylang_ = GLOBUS_GSI_PROXY_GENERIC_POLICY_OID;
      }

      //OBJ_create((char *)policylang_.c_str(), (char *)policylang_.c_str(), (char *)policylang_.c_str());

      //policy_object = OBJ_nid2obj(OBJ_sn2nid(policylang_.c_str()));

      ppolicy = PROXYCERTINFO_get_proxypolicy(proxy_cert_info_);
      //Here only consider the situation when there is policy specified
      if(policystring.size() > 0) {
        //PROXYPOLICY_set_policy_language(ppolicy, policy_object);
        PROXYPOLICY_set_policy(ppolicy, (unsigned char*)policystring.c_str(), policystring.size());
      }

      //set the version of PROXYCERTINFO
      if(proxyversion_ == "RFC" || proxyversion_ == "rfc")
        PROXYCERTINFO_set_version(proxy_cert_info_, 4);
      else
        PROXYCERTINFO_set_version(proxy_cert_info_, 3);
    }
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::Credential::SetStartTime ( const Time start_time)

Set start time of certificate or proxy.

Definition at line 355 of file Credential.cpp.

                                                      {
    start_ = start_time;
  }
bool Arc::Credential::SignEECRequest ( Credential eec,
const std::string &  DN,
BIO *  outputbio 
)

Sign eec request, and output the signed certificate to output BIO.

Definition at line 2555 of file Credential.cpp.

                                                                                      {
    if(pkey_ == NULL) { CredentialLogger.msg(ERROR, "The private key for signing is not initialized"); return false; }
    bool res = false;
    if(eec == NULL) { CredentialLogger.msg(ERROR, "The credential to be signed is NULL"); return false; }
    if(eec->req_ == NULL) { CredentialLogger.msg(ERROR, "The credential to be signed contains no request"); return false; }
    if(outputbio == NULL) { CredentialLogger.msg(ERROR, "The BIO for output is NULL"); return false; }

    X509*  eec_cert = NULL;
    EVP_PKEY* req_pubkey = NULL;
    req_pubkey = X509_REQ_get_pubkey(eec->req_);
    if(!req_pubkey) { CredentialLogger.msg(ERROR, "Error when extracting public key from request");
      LogError(); return false;
    }
    if(!X509_REQ_verify(eec->req_, req_pubkey)){
      CredentialLogger.msg(ERROR,"Failed to verify the request");
      LogError(); return false;
    }
    eec_cert = X509_new();
    X509_set_pubkey(eec_cert, req_pubkey);
    EVP_PKEY_free(req_pubkey);

    X509_set_issuer_name(eec_cert,eec->req_->req_info->subject);
    //X509_set_subject_name(eec_cert,eec->req_->req_info->subject);

    X509_NAME *subject = NULL;
    unsigned long chtype = MBSTRING_ASC;  //TODO
    subject = parse_name((char*)(dn.c_str()), chtype, 0);
    X509_set_subject_name(eec_cert, subject);
    X509_NAME_free(subject);

    const EVP_MD *digest=EVP_sha1();
#ifndef OPENSSL_NO_DSA
    if (pkey_->type == EVP_PKEY_DSA)
      digest=EVP_dss1();
#endif
/*
#ifndef OPENSSL_NO_ECDSA
    if (pkey_->type == EVP_PKEY_EC)
      digest = EVP_ecdsa();
#endif
*/
    X509_STORE *ctx=NULL;
    ctx=X509_STORE_new();
    //X509_STORE_set_verify_cb_func(ctx,callb);
    if (!X509_STORE_set_default_paths(ctx)) {
      LogError();
    }

    CONF *extconf = NULL;
    if (!extfile_.empty()) {
      long errorline = -1;
      X509V3_CTX ctx2;
      extconf = NCONF_new(NULL);
      //configuration file with X509V3 extensions to add
      if (!NCONF_load(extconf, extfile_.c_str(),&errorline)) {
        if (errorline <= 0) {
          CredentialLogger.msg(ERROR,"Error when loading the extension config file: %s", extfile_.c_str());
          return false;
        }
        else {
          CredentialLogger.msg(ERROR,"Error when loading the extension config file: %s on line: %d",
             extfile_.c_str(), errorline);
        }
      }
      //section from config file with X509V3 extensions to add
      if (extsect_.empty()) {
        extsect_.append(NCONF_get_string(extconf, "default", "extensions"));
        if (extsect_.empty()) {
          ERR_clear_error();
          extsect_ = "default";
        }
      }
      X509V3_set_ctx_test(&ctx2);
      X509V3_set_nconf(&ctx2, extconf);
      if (!X509V3_EXT_add_nconf(extconf, &ctx2, (char*)(extsect_.c_str()), NULL)) {
        CredentialLogger.msg(ERROR,"Error when loading the extension section: %s",
          extsect_.c_str());
        LogError();
      }
    }

    //Add extensions to certificate object
    X509_EXTENSION* ext = NULL;
    X509_CINF*  cert_info = NULL;
    cert_info = eec_cert->cert_info;
    if (cert_info->extensions != NULL) {
      sk_X509_EXTENSION_pop_free(cert_info->extensions, X509_EXTENSION_free);
    }
    if(sk_X509_EXTENSION_num(eec->extensions_)) {
      cert_info->extensions = sk_X509_EXTENSION_new_null();
    }
    for (int i=0; i<sk_X509_EXTENSION_num(eec->extensions_); i++) {
      ext = X509_EXTENSION_dup(sk_X509_EXTENSION_value(eec->extensions_, i));
      if (ext == NULL) {
        CredentialLogger.msg(ERROR,"Failed to duplicate extension"); LogError();
      }

      if (!sk_X509_EXTENSION_push(cert_info->extensions, ext)) {
        CredentialLogger.msg(ERROR,"Failed to add extension into EEC certificate"); LogError();
      }
    }

    long lifetime = 12*60*60; //Default lifetime 12 hours
    if (!x509_certify(ctx,(char*)(certfile_.c_str()), digest, eec_cert, cert_,
                      pkey_, (char*)(CAserial_.c_str()), CAcreateserial_, lifetime, 0,
                      extconf, (char*)(extsect_.c_str()), NULL)) {
      CredentialLogger.msg(ERROR,"Can not sign a EEC"); LogError();
    }

    if(PEM_write_bio_X509(outputbio, eec_cert)) {
      CredentialLogger.msg(INFO, "Output EEC certificate"); res = true;
    }
    else {
      CredentialLogger.msg(ERROR, "Can not convert signed EEC cert into DER format");
      LogError();
    }

    NCONF_free(extconf);
    X509_free(eec_cert);
    X509_STORE_free(ctx);

    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::SignEECRequest ( Credential eec,
const std::string &  DN,
std::string &  content 
)

Sign request and output the signed certificate to a string.

Definition at line 2679 of file Credential.cpp.

                                                                                          {
    BIO *out = BIO_new(BIO_s_mem());
    if(!out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for signed EEC certificate");
      LogError(); return false;
    }

    if(SignEECRequest(eec, dn, out)) {
      for(;;) {
        char s[256];
        int l = BIO_read(out,s,sizeof(s));
        if(l <= 0) break;
        content.append(s,l);
      }
    }
    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::SignEECRequest ( Credential eec,
const std::string &  DN,
const char *  filename 
)

Sign request and output the signed certificate to a file.

Definition at line 2698 of file Credential.cpp.

                                                                                            {
    BIO *out = BIO_new(BIO_s_file());
    if(!out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for signed EEC certificate");
      LogError(); return false;
    }
    if (!(BIO_write_filename(out, (char*)filename))) {
      CredentialLogger.msg(ERROR, "Can not set writable file for signed EEC certificate BIO");
      LogError(); BIO_free_all(out); return false;
    }

    if(SignEECRequest(eec, dn, out)) {
      CredentialLogger.msg(INFO, "Wrote signed EEC certificate into a file");
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to write signed EEC certificate into a file");
      BIO_free_all(out); return false;
    }
    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::SignRequest ( Credential proxy,
BIO *  outputbio,
bool  if_der = false 
)

Sign request based on the information inside proxy, and output the signed certificate to output BIO.

Parameters:
if_derfalse for PEM, true for DER

Definition at line 2014 of file Credential.cpp.

                                                                            {
    bool res = false;
    if(proxy == NULL) {CredentialLogger.msg(ERROR, "The credential to be signed is NULL"); return false; }
    if(proxy->req_ == NULL) {CredentialLogger.msg(ERROR, "The credential to be signed contains no request"); return false; }
    if(outputbio == NULL) { CredentialLogger.msg(ERROR, "The BIO for output is NULL"); return false; }

    EVP_PKEY* issuer_priv = NULL;
    EVP_PKEY* issuer_pub = NULL;
    X509*  proxy_cert = NULL;
    X509_CINF*  cert_info = NULL;
    X509_EXTENSION* ext = NULL;
    EVP_PKEY* req_pubkey = NULL;
    req_pubkey = X509_REQ_get_pubkey(proxy->req_);

    if(!req_pubkey) {
      CredentialLogger.msg(ERROR, "Error when extracting public key from request");
      LogError(); return false;
    }

    if(!X509_REQ_verify(proxy->req_, req_pubkey)){
      CredentialLogger.msg(ERROR,"Failed to verify the request"); LogError(); goto err;
    }

    if(!SignRequestAssistant(proxy, req_pubkey, &proxy_cert)) {
      CredentialLogger.msg(ERROR,"Failed to add issuer's extension into proxy");
      LogError(); goto err;
    }

    /*Add the extensions which has just been added by application,
     * into the proxy_cert which will be signed soon.
     * Note here we suppose it is the signer who will add the
     * extension to to-signed proxy and then sign it;
     * it also could be the request who add the extension and put
     * it inside X509 request' extension, but here the situation
     * has not been considered for now
     */
    cert_info = proxy_cert->cert_info;
    if (cert_info->extensions != NULL) {
      sk_X509_EXTENSION_pop_free(cert_info->extensions, X509_EXTENSION_free);
    }

    /*Set the serialNumber*/
    //cert_info->serialNumber = M_ASN1_INTEGER_dup(X509_get_serialNumber(proxy_cert));;

    /*Set the extension*/
    if(sk_X509_EXTENSION_num(proxy->extensions_)) {
      cert_info->extensions = sk_X509_EXTENSION_new_null();
    }

    for (int i=0; i<sk_X509_EXTENSION_num(proxy->extensions_); i++) {
      //ext = X509_EXTENSION_dup(sk_X509_EXTENSION_value(proxy->extensions_, i));
      ext = sk_X509_EXTENSION_value(proxy->extensions_, i);
      if (ext == NULL) {
        //CredentialLogger.msg(ERROR,"Failed to duplicate extension"); LogError(); goto err;
        CredentialLogger.msg(ERROR,"Failed to find extension"); LogError(); goto err;
      }

      if (!sk_X509_EXTENSION_push(cert_info->extensions, ext)) {
        CredentialLogger.msg(ERROR,"Failed to add extension into proxy"); LogError(); goto err;
      }
    }

    /*Clean extensions attached to "proxy" after it has been linked into
    to-signed certificate*/
    sk_X509_EXTENSION_zero(proxy->extensions_);

    /* Now sign the new certificate */
    if(!(issuer_priv = GetPrivKey())) {
      CredentialLogger.msg(ERROR, "Can not get the issuer's private key"); goto err;
    }

    /* Check whether SHA1 isn't requested as the signing algorithm in the request*/
    if(EVP_MD_type(proxy->signing_alg_) != NID_sha1) {
      CredentialLogger.msg(ERROR, "The signing algorithm %s is not allowed,it should be SHA1 to sign certificate requests",
      OBJ_nid2sn(EVP_MD_type(proxy->signing_alg_)));
      goto err;
    }

    if(!X509_sign(proxy_cert, issuer_priv, proxy->signing_alg_)) {
      CredentialLogger.msg(ERROR, "Failed to sign the proxy certificate"); LogError(); goto err;
    }
    else CredentialLogger.msg(INFO, "Succeeded to sign the proxy certificate");

    /*Verify the signature, not needed later*/
    issuer_pub = GetPubKey();
    if((X509_verify(proxy_cert, issuer_pub)) != 1) {
      CredentialLogger.msg(ERROR, "Failed to verify the signed certificate"); LogError(); goto err;
    }
    else CredentialLogger.msg(INFO, "Succeeded to verify the signed certificate");

    /*Output the signed certificate into BIO*/
    if(if_der == false) {
      if(PEM_write_bio_X509(outputbio, proxy_cert)) {
        CredentialLogger.msg(INFO, "Output the proxy certificate"); res = true;
      }
      else {
        CredentialLogger.msg(ERROR, "Can not convert signed proxy cert into PEM format");
        LogError();
      }
    }
    else {
      if(i2d_X509_bio(outputbio, proxy_cert)) {
        CredentialLogger.msg(INFO, "Output the proxy certificate"); res = true;
      }
      else {
        CredentialLogger.msg(ERROR, "Can not convert signed proxy cert into DER format");
        LogError();
      }
    }

err:
    if(issuer_priv) { EVP_PKEY_free(issuer_priv);}
    if(proxy_cert) { X509_free(proxy_cert);}
    if(req_pubkey) { EVP_PKEY_free(req_pubkey); }
    if(issuer_pub) { EVP_PKEY_free(issuer_pub); }
    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

bool Arc::Credential::SignRequest ( Credential proxy,
std::string &  content,
bool  if_der = false 
)

Sign request and output the signed certificate to a string.

Parameters:
if_derfalse for PEM, true for DER

Definition at line 2132 of file Credential.cpp.

                                                                                 {
    BIO *out = BIO_new(BIO_s_mem());
    if(!out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for signed proxy certificate");
      LogError(); return false;
    }

    if(SignRequest(proxy, out, if_der)) {
      for(;;) {
        char s[256];
        int l = BIO_read(out,s,sizeof(s));
        if(l <= 0) break;
        content.append(s,l);
      }
    } else {
      BIO_free_all(out);
      return false;
    }

    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::SignRequest ( Credential proxy,
const char *  filename,
bool  foamat = false 
)

Sign request and output the signed certificate to a file.

Parameters:
if_derfalse for PEM, true for DER

Definition at line 2155 of file Credential.cpp.

                                                                                   {
    BIO *out = BIO_new(BIO_s_file());
    if(!out) {
      CredentialLogger.msg(ERROR, "Can not create BIO for signed proxy certificate");
      LogError(); return false;
    }
    if (!(BIO_write_filename(out, (char*)filename))) {
      CredentialLogger.msg(ERROR, "Can not set writable file for signed proxy certificate BIO");
      LogError(); BIO_free_all(out); return false;
    }

    if(SignRequest(proxy, out, if_der)) {
      CredentialLogger.msg(INFO, "Wrote signed proxy certificate into a file");
    }
    else {
      CredentialLogger.msg(ERROR, "Failed to write signed proxy certificate into a file");
      BIO_free_all(out); return false;
    }

    BIO_free_all(out);
    return true;
  }

Here is the call graph for this function:

bool Arc::Credential::SignRequestAssistant ( Credential proxy,
EVP_PKEY *  req_pubkey,
X509 **  tosign 
) [private]

Assistant method for signing the proxy request, the method will duplicate some information (subject and extension) from signing certificate.

Definition at line 1795 of file Credential.cpp.

                                                                                             {

    bool res = false;
    X509* issuer = NULL;

    X509_NAME* subject_name = NULL;
    X509_NAME_ENTRY* name_entry = NULL;

    *tosign = NULL;
    char* CN_name = NULL;
    ASN1_INTEGER* serial_number = NULL;
    unsigned char* certinfo_data = NULL;
    X509_EXTENSION* certinfo_ext = NULL;
    X509_EXTENSION* ext = NULL;
    int certinfo_NID = NID_undef;

    if(cert_ == NULL) {
      CredentialLogger.msg(ERROR, "Credential is not initialized");
      goto err;
    }
    issuer = X509_dup(cert_);
    if((*tosign = X509_new()) == NULL) {
      CredentialLogger.msg(ERROR, "Failed to initialize X509 structure");
      LogError(); goto err;
    }

    //TODO: VOMS
    if(CERT_IS_GSI_3_PROXY(proxy->cert_type_)) { certinfo_NID = OBJ_txt2nid(PROXYCERTINFO_V3); }
    else if(CERT_IS_RFC_PROXY(proxy->cert_type_)) { certinfo_NID = OBJ_txt2nid(PROXYCERTINFO_V4); }

    if(proxy->cert_type_ == CERT_TYPE_GSI_2_LIMITED_PROXY){
      CN_name = const_cast<char*>("limited proxy");
      serial_number = M_ASN1_INTEGER_dup(X509_get_serialNumber(issuer));
    }
    else if(proxy->cert_type_ == CERT_TYPE_GSI_2_PROXY) {
      CN_name = const_cast<char*>("proxy");
      serial_number = M_ASN1_INTEGER_dup(X509_get_serialNumber(issuer));
    }
    else if (certinfo_NID != NID_undef) {
      unsigned char   md[SHA_DIGEST_LENGTH];
      long  sub_hash;
      unsigned int   len;
      const X509V3_EXT_METHOD* ext_method = NULL;
      ext_method = X509V3_EXT_get_nid(certinfo_NID);
      if(ext_method == NULL) {
        CredentialLogger.msg(ERROR, "Can't get X509V3_EXT_METHOD for %s",OBJ_nid2sn(certinfo_NID));
        LogError(); goto err;
      }

#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
      ASN1_digest((int (*)(void*, unsigned char**))i2d_PUBKEY, EVP_sha1(), (char*)req_pubkey,md,&len);
#else
      ASN1_digest((int(*)())i2d_PUBKEY, EVP_sha1(), (char*)req_pubkey,md,&len);
#endif

      sub_hash = md[0] + (md[1] + (md[2] + (md[3] >> 1) * 256) * 256) * 256;

      CN_name = (char*)malloc(sizeof(long)*4 + 1);
      snprintf(CN_name, sizeof(long)*4 + 1, "%ld", sub_hash);

      //serial_number = ASN1_INTEGER_new();
      //ASN1_INTEGER_set(serial_number, sub_hash);
      //Use the serial number in the certificate as the
      //serial number in the proxy certificate
      serial_number = M_ASN1_INTEGER_dup(X509_get_serialNumber(issuer));

      int length = ext_method->i2d(proxy->proxy_cert_info_, NULL);
      if(length < 0) {
        CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
        LogError();
      }
      else {certinfo_data = (unsigned char*)malloc(length); }

      unsigned char* derdata; derdata = certinfo_data;
      length = ext_method->i2d(proxy->proxy_cert_info_, &derdata);
      if(length < 0) {
        CredentialLogger.msg(ERROR, "Can not convert PROXYCERTINFO struct from internal to DER encoded format");
        free(certinfo_data); certinfo_data = NULL; LogError();
      }
      if(certinfo_data) {
        std::string certinfo_string((char*)certinfo_data, length); free(certinfo_data);
        certinfo_data = NULL;
        std::string NID_txt = PROXYCERTINFO_OPENSSL;
        certinfo_ext = CreateExtension(NID_txt, certinfo_string, 1);
      }
      if(certinfo_ext != NULL) {
        //if(!X509_add_ext(*tosign, certinfo_ext, 0)) {
        if(!sk_X509_EXTENSION_push(proxy->extensions_, certinfo_ext)) {
          CredentialLogger.msg(ERROR, "Can not add X509 extension to proxy cert");
          LogError(); goto err;
        }
      }
    }

    int position;

    /* Add any keyUsage and extendedKeyUsage extensions present in the issuer cert */
    if((position = X509_get_ext_by_NID(issuer, NID_key_usage, -1)) > -1) {
      ASN1_BIT_STRING*   usage;
      unsigned char *    ku_data = NULL;
      int ku_length;

      if(!(ext = X509_get_ext(issuer, position))) {
        CredentialLogger.msg(ERROR, "Can not get extension from issuer certificate");
        LogError(); goto err;
      }

      if(!(usage = (ASN1_BIT_STRING*)X509_get_ext_d2i(issuer, NID_key_usage, NULL, NULL))) {
        CredentialLogger.msg(ERROR, "Can not convert keyUsage struct from DER encoded format");
        LogError(); goto err;
      }

      /* clear bits specified in draft */
      ASN1_BIT_STRING_set_bit(usage, 1, 0); /* Non Repudiation */
      ASN1_BIT_STRING_set_bit(usage, 5, 0); /* Certificate Sign */

      ku_length = i2d_ASN1_BIT_STRING(usage, NULL);
      if(ku_length < 0) {
        CredentialLogger.msg(ERROR, "Can not convert keyUsage struct from internal to DER format");
        LogError(); ASN1_BIT_STRING_free(usage); goto err;
      }
      ku_data = (unsigned char*) malloc(ku_length);

      unsigned char* derdata; derdata = ku_data;
      ku_length = i2d_ASN1_BIT_STRING(usage, &derdata);
      if(ku_length < 0) {
        CredentialLogger.msg(ERROR, "Can not convert keyUsage struct from internal to DER format");
        LogError(); ASN1_BIT_STRING_free(usage); free(ku_data); goto err;
      }
      ASN1_BIT_STRING_free(usage);
      if(ku_data) {
        std::string ku_string((char*)ku_data, ku_length); free(ku_data); ku_data = NULL;
        std::string name = "keyUsage";
        ext = CreateExtension(name, ku_string, 1);
      }
      if(ext != NULL) {
        //if(!X509_add_ext(*tosign, ext, 0)) {
        if(!sk_X509_EXTENSION_push(proxy->extensions_, ext)) {
          CredentialLogger.msg(ERROR, "Can not add X509 extension to proxy cert");
          LogError(); X509_EXTENSION_free(ext); ext = NULL; goto err;
        }
      }
    }

    if((position = X509_get_ext_by_NID(issuer, NID_ext_key_usage, -1)) > -1) {
      if(!(ext = X509_get_ext(issuer, position))) {
        CredentialLogger.msg(ERROR, "Can not get extended KeyUsage extension from issuer certificate");
        LogError(); goto err;
      }

      ext = X509_EXTENSION_dup(ext);
      if(ext == NULL) {
        CredentialLogger.msg(ERROR, "Can not copy extended KeyUsage extension");
        LogError(); goto err;
      }

      //if(!X509_add_ext(*tosign, ext, 0)) {
      if(!sk_X509_EXTENSION_push(proxy->extensions_, ext)) {
        CredentialLogger.msg(ERROR, "Can not add X509 extended KeyUsage extension to new proxy certificate");
        LogError(); X509_EXTENSION_free(ext); ext = NULL; goto err;
      }
    }

    /* Create proxy subject name */
    if((subject_name = X509_NAME_dup(X509_get_subject_name(issuer))) == NULL) {
      CredentialLogger.msg(ERROR, "Can not copy the subject name from issuer for proxy certificate");
      goto err;
    }
    if((name_entry = X509_NAME_ENTRY_create_by_NID(&name_entry, NID_commonName, V_ASN1_APP_CHOOSE,
                                     (unsigned char *) CN_name, -1)) == NULL) {
      CredentialLogger.msg(ERROR, "Can not create name entry CN for proxy certificate");
      LogError(); X509_NAME_free(subject_name); goto err;
    }
    if(!X509_NAME_add_entry(subject_name, name_entry, X509_NAME_entry_count(subject_name), 0) ||
       !X509_set_subject_name(*tosign, subject_name)) {
      CredentialLogger.msg(ERROR, "Can not set CN in proxy certificate");
      LogError(); X509_NAME_ENTRY_free(name_entry); goto err;
    }

    X509_NAME_free(subject_name); subject_name = NULL;
    X509_NAME_ENTRY_free(name_entry);

    if(!X509_set_issuer_name(*tosign, X509_get_subject_name(issuer))) {
      CredentialLogger.msg(ERROR, "Can not set issuer's subject for proxy certificate");
      LogError(); goto err;
    }

    if(!X509_set_version(*tosign, 2L)) {
      CredentialLogger.msg(ERROR, "Can not set version number for proxy certificate");
      LogError(); goto err;
    }

    if(!X509_set_serialNumber(*tosign, serial_number)) {
      CredentialLogger.msg(ERROR, "Can not set serial number for proxy certificate");
      LogError(); goto err;
    }

    if(!SetProxyPeriod(*tosign, issuer, proxy->start_, proxy->lifetime_)) {
      CredentialLogger.msg(ERROR, "Can not set the lifetime for proxy certificate"); goto err;
    }

    if(!X509_set_pubkey(*tosign, req_pubkey)) {
      CredentialLogger.msg(ERROR, "Can not set pubkey for proxy certificate");
      LogError(); goto err;
    }

    res = true;

err:
    if(issuer) { X509_free(issuer); }
    if(res == false && *tosign) { X509_free(*tosign); *tosign = NULL;}
    if(certinfo_NID != NID_undef) {
      if(serial_number) { ASN1_INTEGER_free(serial_number);}
      if(CN_name) { free(CN_name); }
    }

    return res;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Get the certificate chain attached to this object.

Here is the caller graph for this function:

Arc::Credential::STACK_OF ( X509  ) [private]
Arc::Credential::STACK_OF ( X509_EXTENSION  ) [private]
bool Arc::Credential::Verify ( void  ) [private]

Verify whether the certificate is signed by trusted CAs *the verification is not needed for EEC, but needed for verifying a proxy certificate which *is generated by the others.

Definition at line 638 of file Credential.cpp.

                              {
    if(verify_cert_chain(cert_, &cert_chain_, &verify_ctx_)) {
      CredentialLogger.msg(VERBOSE, "Certificate verification succeeded");
      verification_valid = true;
      return true;
    }
    else {CredentialLogger.msg(INFO, "Certificate verification failed"); LogError(); return false;}
  }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

std::string Arc::Credential::cacertdir_ [private]

Definition at line 352 of file Credential.h.

std::string Arc::Credential::cacertfile_ [private]

Definition at line 351 of file Credential.h.

Definition at line 393 of file Credential.h.

std::string Arc::Credential::CAserial_ [private]

Definition at line 392 of file Credential.h.

X509* Arc::Credential::cert_ [private]

Definition at line 363 of file Credential.h.

Definition at line 364 of file Credential.h.

std::string Arc::Credential::certfile_ [private]

Definition at line 353 of file Credential.h.

std::string Arc::Credential::extfile_ [private]

Definition at line 394 of file Credential.h.

std::string Arc::Credential::extsect_ [private]

Definition at line 395 of file Credential.h.

Definition at line 371 of file Credential.h.

Definition at line 379 of file Credential.h.

std::string Arc::Credential::keyfile_ [private]

Definition at line 354 of file Credential.h.

Definition at line 373 of file Credential.h.

Definition at line 386 of file Credential.h.

EVP_PKEY* Arc::Credential::pkey_ [private]

Definition at line 365 of file Credential.h.

std::string Arc::Credential::policy_ [private]

Definition at line 383 of file Credential.h.

std::string Arc::Credential::policylang_ [private]

Definition at line 384 of file Credential.h.

Definition at line 370 of file Credential.h.

Definition at line 385 of file Credential.h.

std::string Arc::Credential::proxyversion_ [private]

Definition at line 382 of file Credential.h.

X509_REQ* Arc::Credential::req_ [private]

Definition at line 376 of file Credential.h.

RSA* Arc::Credential::rsa_key_ [private]

Definition at line 377 of file Credential.h.

EVP_MD* Arc::Credential::signing_alg_ [private]

Definition at line 378 of file Credential.h.

Definition at line 372 of file Credential.h.

Definition at line 360 of file Credential.h.

Definition at line 357 of file Credential.h.


The documentation for this class was generated from the following files: