25
25
using namespace ArcCredential;
29
#define DEFAULT_DIGEST ((EVP_MD*)EVP_sha1())
30
#define DEFAULT_KEYBITS (1024)
28
32
CredentialError::CredentialError(const std::string& what) : std::runtime_error(what) { }
30
34
Logger CredentialLogger(Logger::rootLogger, "Credential");
33
#define PASS_MIN_LENGTH 4
34
static int passwordcb(char* pwd, int len, int verify, void* passphrase) {
39
j=strlen((const char*)passphrase);
41
memcpy(pwd,passphrase,j);
44
prompt=EVP_get_pw_prompt();
46
prompt="Enter PEM pass phrase:";
50
// snprintf(prompt, sizeof(prompt), "Enter passphrase to decrypte the key file: ");
52
// snprintf(prompt, sizeof(prompt), "Enter passphrase to encrypte the key file: ");
53
r = EVP_read_pw_string(pwd, len, prompt, verify);
55
CredentialLogger.msg(ERROR,"Failed to read input passphrase");
56
memset(pwd,0,(unsigned int)len);
60
if(verify && (j < PASS_MIN_LENGTH)) {
61
CredentialLogger.msg(ERROR,"Input phrase is too short (at least %d char)",PASS_MIN_LENGTH);
68
36
static int ssl_err_cb(const char *str, size_t, void *u) {
69
37
Logger& logger = *((Logger*)u);
70
38
logger.msg(DEBUG, "OpenSSL error string: %s", str);
74
42
#define PASS_MIN_LENGTH (0)
75
43
typedef struct pw_cb_data {
77
const char *prompt_info;
44
PasswordSource *password;
80
47
static int passwordcb(char *buf, int bufsiz, int verify, void *cb_tmp) {
83
const char *prompt_info = NULL;
84
const char *password = NULL;
85
48
PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
87
if (bufsiz <= 1) return res;
50
if (bufsiz <= 1) return 0;
89
if (cb_data->password) password = (const char*)(cb_data->password);
90
if (cb_data->prompt_info) prompt_info = cb_data->prompt_info;
94
res = strlen(password);
95
if (res > (bufsiz-1)) res = bufsiz-1;
96
if(buf) memcpy(buf, password, res+1);
109
prompt = UI_construct_prompt(ui, "pass phrase", cb_data->prompt_info);
111
ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
112
// UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
116
if((buf1 = (char *)OPENSSL_malloc(bufsiz)) != NULL) {
117
memset(buf1,0,(unsigned int)bufsiz);
118
ok = UI_add_input_string(ui,prompt,ui_flags,buf1,PASS_MIN_LENGTH,bufsiz-1);
121
if (ok >= 0 && verify) {
123
if((buf2 = (char *)OPENSSL_malloc(bufsiz)) != NULL) {
124
memset(buf2,0,(unsigned int)bufsiz);
125
ok = UI_add_verify_string(ui,prompt,ui_flags,buf2,PASS_MIN_LENGTH,bufsiz-1,buf1);
130
if(ok == -2) break; // Abort request
131
if(ok == -1) { // Password error
132
unsigned long errcode = ERR_get_error();
133
const char* errstr = ERR_reason_error_string(errcode);
135
CredentialLogger.msg(Arc::ERROR, "Password input error - code %lu",errcode);
136
} else if(strstr(errstr,"result too small")) {
137
CredentialLogger.msg(Arc::ERROR, "Password is too short, need at least %u charcters", PASS_MIN_LENGTH);
138
} else if(strstr(errstr,"result too large")) {
139
CredentialLogger.msg(Arc::ERROR, "Password is too long, need at most %u characters", bufsiz-1);
141
CredentialLogger.msg(Arc::ERROR, "%s", errstr);
144
} while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
147
memset(buf2,0,(unsigned int)bufsiz);
155
if(buf) memcpy(buf,buf1,res+1);
160
memset(buf1,0,(unsigned int)bufsiz);
165
CredentialLogger.msg(Arc::ERROR, "User interface error");
166
ERR_print_errors_cb(&ssl_err_cb, &CredentialLogger);
167
if(buf) memset(buf,0,(unsigned int)bufsiz);
169
} else if (ok == -2) {
170
if(buf) memset(buf,0,(unsigned int)bufsiz);
174
OPENSSL_free(prompt);
52
if (cb_data->password) {
54
if(cb_data->password->Get(password,PASS_MIN_LENGTH,bufsiz) != PasswordSource::PASSWORD) {
55
// It was requested to have key encrypted and no password was provided
58
if(buf) strncpy(buf, password.c_str(), bufsiz);
59
int len = password.length();
60
if(len > bufsiz) len = bufsiz;
64
// Password is needed but no source defined for password
179
68
void Credential::LogError(void) const {
463
352
return start_+lifetime_;
355
Signalgorithm Credential::GetSigningAlgorithm(void) const {
356
Signalgorithm signing_algorithm = SIGN_DEFAULT;
357
if(!cert_) return signing_algorithm;
358
X509_ALGOR* alg = cert_->sig_alg;
359
if(!alg) return signing_algorithm;
360
int sig_nid = OBJ_obj2nid(alg->algorithm);
362
case NID_sha1WithRSAEncryption: signing_algorithm = SIGN_SHA1; break;
363
case NID_sha224WithRSAEncryption: signing_algorithm = SIGN_SHA224; break;
364
case NID_sha256WithRSAEncryption: signing_algorithm = SIGN_SHA256; break;
365
case NID_sha384WithRSAEncryption: signing_algorithm = SIGN_SHA384; break;
366
case NID_sha512WithRSAEncryption: signing_algorithm = SIGN_SHA512; break;
368
return signing_algorithm;
371
int Credential::GetKeybits(void) const {
373
if(!cert_) return keybits;
374
EVP_PKEY* pkey = X509_get_pubkey(cert_);
375
if(!pkey) return keybits;
376
keybits = EVP_PKEY_bits(pkey);
466
380
void Credential::SetLifeTime(const Period& period) {
467
381
lifetime_ = period;
471
385
start_ = start_time;
388
void Credential::SetSigningAlgorithm(Signalgorithm signing_algorithm) {
389
switch(signing_algorithm) {
390
case SIGN_SHA1: signing_alg_ = ((EVP_MD*)EVP_sha1()); break;
391
case SIGN_SHA224: signing_alg_ = ((EVP_MD*)EVP_sha224()); break;
392
case SIGN_SHA256: signing_alg_ = ((EVP_MD*)EVP_sha256()); break;
393
case SIGN_SHA384: signing_alg_ = ((EVP_MD*)EVP_sha384()); break;
394
case SIGN_SHA512: signing_alg_ = ((EVP_MD*)EVP_sha512()); break;
395
default: signing_alg_ = NULL; break;
399
void Credential::SetKeybits(int keybits) {
474
403
bool Credential::IsCredentialsValid(const UserConfig& usercfg) {
476
405
Credential(!usercfg.ProxyPath().empty() ? usercfg.ProxyPath() : usercfg.CertificatePath(),
812
739
Credential::Credential() : verification_valid(false), cert_(NULL), pkey_(NULL),
813
740
cert_chain_(NULL), proxy_cert_info_(NULL), format(CRED_UNKNOWN),
814
741
start_(Time()), lifetime_(Period("PT12H")),
815
req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(1024),
742
req_(NULL), rsa_key_(NULL), signing_alg_(NULL), keybits_(0),
816
743
proxyver_(0), pathlength_(0), extensions_(NULL) {
828
755
Credential::Credential(const int keybits) : cert_(NULL),
829
756
pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
830
757
start_(Time()), lifetime_(Period("PT12H")),
831
req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(keybits),
758
req_(NULL), rsa_key_(NULL), signing_alg_(NULL), keybits_(keybits),
832
759
extensions_(NULL) {
845
772
std::string policylang, std::string policy, int pathlength) :
846
773
cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
847
774
start_(start), lifetime_(lifetime), req_(NULL), rsa_key_(NULL),
848
signing_alg_((EVP_MD*)EVP_sha1()), keybits_(keybits), extensions_(NULL) {
775
signing_alg_(NULL), keybits_(keybits), extensions_(NULL) {
1045
972
Credential::Credential(const std::string& certfile, const std::string& keyfile,
1046
973
const std::string& cadir, const std::string& cafile,
1047
const std::string& passphrase4key, const bool is_file) {
974
PasswordSource& passphrase4key, const bool is_file) {
1048
975
InitCredential(certfile,keyfile,cadir,cafile,passphrase4key,is_file);
977
Credential::Credential(const std::string& certfile, const std::string& keyfile,
978
const std::string& cadir, const std::string& cafile,
979
const std::string& passphrase4key, const bool is_file) {
980
PasswordSource* pass = NULL;
981
if(passphrase4key.empty()) {
982
pass = new PasswordSourceInteractive("private key", false);
983
} else if(passphrase4key[0] == '\0') {
984
pass = new PasswordSourceString("");
986
pass = new PasswordSourceString(passphrase4key);
988
InitCredential(certfile,keyfile,cadir,cafile,*pass,is_file);
992
Credential::Credential(const UserConfig& usercfg, PasswordSource& passphrase4key) {
993
if (usercfg.CredentialString().empty()) {
994
InitCredential(!usercfg.ProxyPath().empty() ? usercfg.ProxyPath() : usercfg.CertificatePath(),
995
!usercfg.ProxyPath().empty() ? "" : usercfg.KeyPath(),
996
usercfg.CACertificatesDirectory(), usercfg.CACertificatePath(),
997
passphrase4key, true);
999
InitCredential(usercfg.CredentialString(), "",
1000
usercfg.CACertificatesDirectory(), usercfg.CACertificatePath(),
1001
passphrase4key, false);
1051
1005
Credential::Credential(const UserConfig& usercfg, const std::string& passphrase4key) {
1052
InitCredential(!usercfg.ProxyPath().empty() ? usercfg.ProxyPath() : usercfg.CertificatePath(),
1053
!usercfg.ProxyPath().empty() ? "" : usercfg.KeyPath(),
1054
usercfg.CACertificatesDirectory(), usercfg.CACertificatePath(),
1055
passphrase4key, true);
1006
PasswordSource* pass = NULL;
1007
if(passphrase4key.empty()) {
1008
pass = new PasswordSourceInteractive("private key", false);
1009
} else if(passphrase4key[0] == '\0') {
1010
pass = new PasswordSourceString("");
1012
pass = new PasswordSourceString(passphrase4key);
1014
if (usercfg.CredentialString().empty()) {
1015
InitCredential(!usercfg.ProxyPath().empty() ? usercfg.ProxyPath() : usercfg.CertificatePath(),
1016
!usercfg.ProxyPath().empty() ? "" : usercfg.KeyPath(),
1017
usercfg.CACertificatesDirectory(), usercfg.CACertificatePath(),
1020
InitCredential(usercfg.CredentialString(), "",
1021
usercfg.CACertificatesDirectory(), usercfg.CACertificatePath(),
1058
1027
void Credential::InitCredential(const std::string& certfile, const std::string& keyfile,
1059
1028
const std::string& cadir, const std::string& cafile,
1060
const std::string& passphrase4key, const bool is_file) {
1029
PasswordSource& passphrase4key, const bool is_file) {
1062
1031
cacertfile_ = cafile;
1063
1032
cacertdir_ = cadir;
1638
1608
bool Credential::OutputPrivatekey(std::string &content, bool encryption, const std::string& passphrase) {
1609
if(passphrase.empty()) {
1611
PasswordSourceInteractive pass("", true);
1612
return OutputPrivatekey(content, encryption, pass);
1614
PasswordSourceString pass(passphrase);
1615
return OutputPrivatekey(content, encryption, pass);
1618
bool Credential::OutputPrivatekey(std::string &content, bool encryption, PasswordSource& passphrase) {
1639
1619
BIO *out = BIO_new(BIO_s_mem());
1640
1620
EVP_CIPHER *enc = NULL;
1641
1621
if(!out) return false;
1649
1629
enc = (EVP_CIPHER*)EVP_des_ede3_cbc();
1652
prompt = "Enter passphrase to encrypt the PEM key file: ";
1653
if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0,passwordcb,
1654
(passphrase.empty())?NULL:(void*)(passphrase.c_str()))) {
1655
BIO_free_all(out); return false;
1658
1630
PW_CB_DATA cb_data;
1659
cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
1660
cb_data.prompt_info = NULL;
1661
if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0, (pem_password_cb *)passwordcb,&cb_data)) {
1631
cb_data.password = &passphrase;
1632
if(!PEM_write_bio_RSAPrivateKey(out,rsa_key_,enc,NULL,0, &passwordcb,&cb_data)) {
1662
1633
BIO_free_all(out); return false;
1673
1644
enc = (EVP_CIPHER*)EVP_des_ede3_cbc();
1676
prompt = "Enter passphrase to encrypt the PEM key file: ";
1677
if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0,passwordcb,
1678
(passphrase.empty())?NULL:(void*)(passphrase.c_str()))) {
1679
BIO_free_all(out); return false;
1682
1645
PW_CB_DATA cb_data;
1683
cb_data.password = (passphrase.empty()) ? NULL : (void*)(passphrase.c_str());
1684
cb_data.prompt_info = NULL;
1685
if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0, (pem_password_cb *)passwordcb,&cb_data)) {
1646
cb_data.password = &passphrase;
1647
if(!PEM_write_bio_PrivateKey(out,pkey_,enc,NULL,0, &passwordcb,&cb_data)) {
1686
1648
BIO_free_all(out); return false;
2354
2315
/* Use the signing algorithm in the signer's priv key */
2355
2316
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
2356
if(EVP_PKEY_get_default_digest_nid(issuer_priv, &md_nid) <= 0) {
2357
CredentialLogger.msg(INFO, "There is no digest in issuer's private key object");
2359
md_str = (char *)OBJ_nid2sn(md_nid);
2360
if((dgst_alg = EVP_get_digestbyname(md_str)) == NULL) {
2361
CredentialLogger.msg(INFO, "%s is an unsupported digest type", md_str);
2318
int dgst_err = EVP_PKEY_get_default_digest_nid(issuer_priv, &md_nid);
2320
CredentialLogger.msg(INFO, "There is no digest in issuer's private key object");
2321
} else if((dgst_err == 2) || (!proxy->signing_alg_)) { // mandatory or no digest specified
2322
char* md_str = (char *)OBJ_nid2sn(md_nid);
2324
if((dgst_alg = EVP_get_digestbyname(md_str)) == NULL) {
2325
CredentialLogger.msg(INFO, "%s is an unsupported digest type", md_str);
2326
// TODO: if disgest is mandatory then probably there must be error.
2364
if(dgst_alg == NULL) dgst_alg = proxy->signing_alg_;
2332
if(dgst_alg == NULL) dgst_alg = proxy->signing_alg_?proxy->signing_alg_:DEFAULT_DIGEST;
2366
2334
/* Check whether the digest algorithm is SHA1 or SHA2*/
2367
2335
md_nid = EVP_MD_type(dgst_alg);
2470
2438
Credential::Credential(const std::string& CAcertfile, const std::string& CAkeyfile,
2471
2439
const std::string& CAserial, const std::string& extfile,
2440
const std::string& extsect, PasswordSource& passphrase4key) :
2441
certfile_(CAcertfile), keyfile_(CAkeyfile), verification_valid(false),
2442
cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
2443
req_(NULL), rsa_key_(NULL), signing_alg_(NULL), keybits_(0),
2444
proxyver_(0), pathlength_(0), extensions_(NULL),
2445
CAserial_(CAserial), extfile_(extfile), extsect_(extsect) {
2450
//Initiate the proxy certificate constant and method which is required by openssl
2451
if(!proxy_init_) InitProxyCertInfo();
2453
extensions_ = sk_X509_EXTENSION_new_null();
2456
loadCertificateFile(CAcertfile, cert_, &cert_chain_);
2457
if(cert_) check_cert_type(cert_,cert_type_);
2458
loadKeyFile(CAkeyfile, pkey_, passphrase4key);
2459
} catch(std::exception& err){
2460
CredentialLogger.msg(ERROR, "ERROR:%s", err.what());
2465
Credential::Credential(const std::string& CAcertfile, const std::string& CAkeyfile,
2466
const std::string& CAserial, const std::string& extfile,
2472
2467
const std::string& extsect, const std::string& passphrase4key) :
2473
2468
certfile_(CAcertfile), keyfile_(CAkeyfile), verification_valid(false),
2474
2469
cert_(NULL), pkey_(NULL), cert_chain_(NULL), proxy_cert_info_(NULL),
2475
req_(NULL), rsa_key_(NULL), signing_alg_((EVP_MD*)EVP_sha1()), keybits_(1024),
2470
req_(NULL), rsa_key_(NULL), signing_alg_(NULL), keybits_(0),
2476
2471
proxyver_(0), pathlength_(0), extensions_(NULL),
2477
2472
CAserial_(CAserial), extfile_(extfile), extsect_(extsect) {
2485
2480
extensions_ = sk_X509_EXTENSION_new_null();
2483
PasswordSource* pass = NULL;
2484
if(passphrase4key.empty()) {
2485
pass = new PasswordSourceInteractive("private key", false);
2486
} else if(passphrase4key[0] == '\0') {
2487
pass = new PasswordSourceString("");
2489
pass = new PasswordSourceString(passphrase4key);
2488
2491
loadCertificateFile(CAcertfile, cert_, &cert_chain_);
2489
2492
if(cert_) check_cert_type(cert_,cert_type_);
2490
loadKeyFile(CAkeyfile, pkey_, passphrase4key);
2493
loadKeyFile(CAkeyfile, pkey_, *pass);
2491
2495
} catch(std::exception& err){
2492
2496
CredentialLogger.msg(ERROR, "ERROR:%s", err.what());