60
60
static void create_proxy(std::string& proxy_cert, Arc::Credential& signer,
61
61
const std::string& proxy_policy, Arc::Time& proxy_start, Arc::Period& proxy_period,
62
const std::string& vomsacseq, bool use_gsi_proxy, int keybits);
62
const std::string& vomsacseq, bool use_gsi_proxy, int keybits,
63
const std::string& signing_algorithm);
64
65
static std::string get_proxypolicy(const std::string& policy_source);
123
#define PASS_MIN_LENGTH (4)
124
static int input_password(char *password, int passwdsz, bool verify,
125
const std::string& prompt_info,
126
const std::string& prompt_verify_info,
127
Arc::Logger& logger) {
133
char* buf = new char[passwdsz];
134
memset(buf, 0, passwdsz);
136
char *prompt1 = NULL;
137
char *prompt2 = NULL;
138
prompt1 = UI_construct_prompt(ui, "passphrase", prompt_info.c_str());
139
ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
140
UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
141
ok = UI_add_input_string(ui, prompt1, ui_flags, password,
146
} while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
149
if (ok >= 0) res = strlen(password);
151
if (ok >= 0 && verify) {
157
// TODO: use some generic password strength evaluation
158
if(res < PASS_MIN_LENGTH) {
159
UI_add_info_string(ui, "WARNING: Your password is too weak (too short)!\n"
160
"Make sure this is really what You wanted to enter.\n");
162
prompt2 = UI_construct_prompt(ui, "passphrase", prompt_verify_info.c_str());
163
ok = UI_add_verify_string(ui, prompt2, ui_flags, buf,
164
0, passwdsz - 1, password);
168
} while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
174
logger.msg(Arc::ERROR, "User interface error");
175
tls_process_error(logger);
176
memset(password, 0, (unsigned int)passwdsz);
180
logger.msg(Arc::ERROR, "Aborted!");
181
memset(password, 0, (unsigned int)passwdsz);
186
if(prompt1) OPENSSL_free(prompt1);
187
if(prompt2) OPENSSL_free(prompt2);
192
124
static bool is_file(std::string path) {
193
125
if (Glib::file_test(path, Glib::FILE_TEST_IS_REGULAR))
373
static std::string signTypeToString(Arc::Signalgorithm alg) {
375
case Arc::SIGN_SHA1: return "sha1";
376
case Arc::SIGN_SHA224: return "sha224";
377
case Arc::SIGN_SHA256: return "sha256";
378
case Arc::SIGN_SHA384: return "sha384";
379
case Arc::SIGN_SHA512: return "sha512";
391
} pass_destination_type;
393
std::map<pass_destination_type, Arc::PasswordSource*> passsources;
395
class PasswordSourceFile: public Arc::PasswordSource {
399
PasswordSourceFile(const std::string& filename):file_(filename.c_str()) {
401
virtual Result Get(std::string& password, int minsize, int maxsize) {
402
if(!file_) return Arc::PasswordSource::NO_PASSWORD;
403
std::getline(file_, password);
404
return Arc::PasswordSource::PASSWORD;
441
408
int main(int argc, char *argv[]) {
443
410
setlocale(LC_ALL, "");
465
432
" e.g. 43200 or 12h or 12H; if not specified, the default is the minimum value of\n"
466
433
" 12 hours and validityPeriod (which is lifetime of the delegated proxy on myproxy server))\n"
467
434
" proxyPolicy=policy content\n"
468
" proxyPolicyFile=policy file"));
435
" proxyPolicyFile=policy file\n"
436
" keybits=number - length of the key to generate. Default is 1024 bits.\n"
437
" Special value 'inherit' is to use key length of signing certificate.\n"
438
" signingAlgorithm=name - signing algorithm to use for signing public key of proxy.\n"
439
" Possible values are sha1, sha2 (alias for sha256), sha224, sha256, sha384, sha512\n"
440
" and inherit (use algorithm of signing certificate). Default is inherit.\n"
442
"Supported information item names are:\n"
443
" subject - subject name of proxy certificate.\n"
444
" identity - identity subject name of proxy certificate.\n"
445
" issuer - issuer subject name of proxy certificate.\n"
446
" ca - subject name of CA ehich issued initial certificate\n"
447
" path - file system path to file containing proxy.\n"
448
" type - type of proxy certificate.\n"
449
" validityStart - timestamp when proxy validity starts.\n"
450
" validityEnd - timestamp when proxy validity ends.\n"
451
" validityPeriod - duration of proxy validity in seconds.\n"
452
" validityLeft - duration of proxy validity left in seconds.\n"
453
" vomsVO - VO name represented by VOMS attribute\n"
454
" vomsSubject - subject of certificate for which VOMS attribute is issued\n"
455
" vomsIssuer - subject of service which issued VOMS certificate\n"
456
" vomsACvalidityStart - timestamp when VOMS attribute validity starts.\n"
457
" vomsACvalidityEnd - timestamp when VOMS attribute validity ends.\n"
458
" vomsACvalidityPeriod - duration of VOMS attribute validity in seconds.\n"
459
" vomsACvalidityLeft - duration of VOMS attribute validity left in seconds.\n"
461
" keybits - size of proxy certificate key in bits.\n"
462
" signingAlgorithm - algorith used to sign proxy certificate.\n"
463
"Items are printed in requested order and are separated by newline.\n"
464
"If item has multiple values they are printed in same line separated by |."
470
467
std::string proxy_path;
471
468
options.AddOption('P', "proxy", istring("path to the proxy file"),
525
522
options.AddOption('O', "old", istring("use GSI proxy (RFC 3820 compliant proxy is default)"), use_gsi_proxy);
527
524
bool info = false;
528
options.AddOption('I', "info", istring("print all information about this proxy. \n"
529
" In order to show the Identity (DN without CN as suffix for proxy) \n"
530
" of the certificate, the 'trusted certdir' is needed."
525
options.AddOption('I', "info", istring("print all information about this proxy."), info);
527
std::list<std::string> infoitemlist;
528
options.AddOption('i', "infoitem", istring("print selected information about this proxy."), istring("string"), infoitemlist);
534
530
bool remove_proxy = false;
535
531
options.AddOption('r', "remove", istring("remove proxy"), remove_proxy);
561
557
std::string myproxy_command; //command to myproxy server
562
558
options.AddOption('M', "myproxycmd", istring("command to MyProxy server. The command can be PUT or GET.\n"
563
" PUT/put/Put -- put a delegated credential to the MyProxy server; \n"
564
" GET/get/Get -- get a delegated credential from the MyProxy server, \n"
559
" PUT -- put a delegated credential to the MyProxy server; \n"
560
" GET -- get a delegated credential from the MyProxy server, \n"
565
561
" credential (certificate and key) is not needed in this case. \n"
566
562
" MyProxy functionality can be used together with VOMS\n"
567
563
" functionality.\n"
580
576
options.AddOption('c', "constraint", istring("proxy constraints"),
581
577
istring("string"), constraintlist);
579
std::list<std::string> passsourcelist;
580
options.AddOption('p', "passwordsource", istring("password sources"),
581
istring("string"), passsourcelist);
583
583
int timeout = -1;
584
584
options.AddOption('t', "timeout", istring("timeout in seconds (default 20)"),
585
585
istring("seconds"), timeout);
632
632
// Check for needed credentials objects
633
633
// Can proxy be used for? Could not find it in documentation.
634
634
// Key and certificate not needed if only printing proxy information
635
if (!(myproxy_command == "get" || myproxy_command == "GET" || myproxy_command == "Get")) {
635
if (!(Arc::lower(myproxy_command) == "get")) {
636
636
if((usercfg.CertificatePath().empty() ||
638
638
usercfg.KeyPath().empty() &&
639
639
(usercfg.CertificatePath().find(".p12") == std::string::npos)
641
) && !(info || remove_proxy)) {
641
) && !(info || (infoitemlist.size() > 0) || remove_proxy)) {
642
642
logger.msg(Arc::ERROR, "Failed to find certificate and/or private key or files have improper permissions or ownership.");
643
643
logger.msg(Arc::ERROR, "You may try to increase verbosity to get more information.");
644
644
return EXIT_FAILURE;
829
831
return EXIT_SUCCESS;
833
if(infoitemlist.size() > 0) {
834
std::vector<Arc::VOMSACInfo> voms_attributes;
835
Arc::Credential holder(proxy_path, "", "", "");
836
Arc::VOMSTrustList voms_trust_dn;
837
voms_trust_dn.AddRegex(".*");
838
parseVOMSAC(holder, ca_dir, "", voms_dir, voms_trust_dn, voms_attributes, true, true);
839
for(std::list<std::string>::iterator ii = infoitemlist.begin();
840
ii != infoitemlist.end(); ++ii) {
841
if(*ii == "subject") {
842
std::cout << holder.GetDN() << std::endl;
843
} else if(*ii == "identity") {
844
std::cout << holder.GetIdentityName() << std::endl;
845
} else if(*ii == "issuer") {
846
std::cout << holder.GetIssuerName() << std::endl;
847
} else if(*ii == "ca") {
848
std::cout << holder.GetCAName() << std::endl;
849
} else if(*ii == "path") {
850
std::cout << proxy_path << std::endl;
851
} else if(*ii == "type") {
852
std::cout << certTypeToString(holder.GetType()) << std::endl; // todo:less human readable
853
} else if(*ii == "validityStart") {
854
std::cout << holder.GetStartTime().GetTime() << std::endl;
855
} else if(*ii == "validityEnd") {
856
std::cout << holder.GetEndTime().GetTime() << std::endl;
857
} else if(*ii == "validityPeriod") {
858
std::cout << (holder.GetEndTime() - holder.GetStartTime()).GetPeriod() << std::endl;
859
} else if(*ii == "validityLeft") {
860
std::cout << ((now<holder.GetEndTime())?(holder.GetEndTime()-now):Arc::Period(0)).GetPeriod() << std::endl;
861
} else if(*ii == "vomsVO") {
862
for(int n = 0; n<voms_attributes.size(); ++n) {
863
if(n) std::cout << "|";
864
std::cout << voms_attributes[n].voname;
866
std::cout << std::endl;
867
} else if(*ii == "vomsSubject") {
868
for(int n = 0; n<voms_attributes.size(); ++n) {
869
if(n) std::cout << "|";
870
std::cout << voms_attributes[n].holder;
872
std::cout << std::endl;
873
} else if(*ii == "vomsIssuer") {
874
for(int n = 0; n<voms_attributes.size(); ++n) {
875
if(n) std::cout << "|";
876
std::cout << voms_attributes[n].issuer;
878
std::cout << std::endl;
879
} else if(*ii == "vomsACvalidityStart") {
880
for(int n = 0; n<voms_attributes.size(); ++n) {
881
if(n) std::cout << "|";
882
std::cout << voms_attributes[n].from.GetTime();
884
std::cout << std::endl;
885
} else if(*ii == "vomsACvalidityEnd") {
886
for(int n = 0; n<voms_attributes.size(); ++n) {
887
if(n) std::cout << "|";
888
std::cout << voms_attributes[n].till.GetTime();
890
std::cout << std::endl;
891
} else if(*ii == "vomsACvalidityPeriod") {
892
for(int n = 0; n<voms_attributes.size(); ++n) {
893
if(n) std::cout << "|";
894
std::cout << (voms_attributes[n].till-voms_attributes[n].from).GetPeriod();
896
std::cout << std::endl;
897
} else if(*ii == "vomsACvalidityLeft") {
898
for(int n = 0; n<voms_attributes.size(); ++n) {
899
if(n) std::cout << "|";
900
std::cout << ((voms_attributes[n].till>now)?(voms_attributes[n].till-now):Arc::Period(0)).GetPeriod();
902
std::cout << std::endl;
903
} else if(*ii == "proxyPolicy") {
904
std::cout << holder.GetProxyPolicy() << std::endl;
905
} else if(*ii == "keybits") {
906
std::cout << holder.GetKeybits() << std::endl;
907
} else if(*ii == "signingAlgorithm") {
908
std::cout << signTypeToString(holder.GetSigningAlgorithm()) << std::endl;
910
logger.msg(Arc::ERROR, "Information item '%s' is not known",*ii);
832
916
if ((cert_path.empty() || key_path.empty()) &&
833
((myproxy_command == "PUT") || (myproxy_command == "put") || (myproxy_command == "Put"))) {
917
(Arc::lower(myproxy_command) == "put")) {
834
918
if (cert_path.empty())
835
919
logger.msg(Arc::ERROR, "Cannot find the user certificate path, "
836
920
"please setup environment X509_USER_CERT, "
852
936
constraints[*it] = "";
939
std::map<pass_destination_type, std::pair<std::string,bool> > passprompts;
940
passprompts[pass_private_key] = std::pair<std::string,bool>("private key",false);
941
passprompts[pass_myproxy] = std::pair<std::string,bool>("MyProxy server",false);
942
passprompts[pass_myproxy_new] = std::pair<std::string,bool>("MyProxy server (new)",true);
943
for (std::list<std::string>::iterator it = passsourcelist.begin();
944
it != passsourcelist.end(); it++) {
945
std::string::size_type pos = it->find('=');
946
if (pos == std::string::npos) {
947
logger.msg(Arc::ERROR, "Cannot parse password source expression %s "
948
"it must be of type=source format", *it);
951
std::string dest = it->substr(0, pos);
952
pass_destination_type pass_dest;
954
pass_dest = pass_private_key;
956
logger.msg(Arc::ERROR, "Cannot parse password type %s. "
957
"Currently supported value is 'key'.", dest);
960
std::string pass = it->substr(pos + 1);
961
if((pass[0] == '"') && (pass[pass.length()-1] == '"')) {
962
passsources[pass_dest] = new Arc::PasswordSourceString(pass.substr(1,pass.length()-2));
963
} else if(pass == "int") {
964
passsources[pass_dest] = new Arc::PasswordSourceInteractive(passprompts[pass_private_key].first,passprompts[pass_private_key].second);
965
} else if(pass == "stdin") {
966
passsources[pass_dest] = new Arc::PasswordSourceStream(&std::cin);
968
pos = pass.find(':');
969
if(pos == std::string::npos) {
970
logger.msg(Arc::ERROR, "Cannot parse password source %s "
971
"it must be of source_type or source_type:data format. "
972
"Supported source types are int,stdin,stream,file.", pass);
975
std::string data = pass.substr(pos + 1);
978
passsources[pass_dest] = new PasswordSourceFile(data);
979
// TODO: combine same files
980
} else if(pass == "stream") {
982
passsources[pass_dest] = new Arc::PasswordSourceStream(&std::cin);
984
logger.msg(Arc::ERROR, "Only standard input is currently supported "
985
"for password source.");
989
logger.msg(Arc::ERROR, "Cannot parse password source type %s. "
990
"Supported source types are int,stdin,stream,file.", pass);
995
for(std::map<pass_destination_type, std::pair<std::string,bool> >::iterator p = passprompts.begin();
996
p != passprompts.end();++p) {
997
if(passsources.find(p->first) == passsources.end()) {
998
passsources[p->first] = new Arc::PasswordSourceInteractive(p->second.first,p->second.second);
855
1002
//proxy validity period
856
1003
//Set the default proxy validity lifetime to 12 hours if there is
857
1004
//no validity lifetime provided by command caller
1133
1289
Arc::Credential signer(proxy_path, proxy_path, "", "");
1134
1290
std::string proxy_cert;
1135
1291
create_proxy(proxy_cert, signer, policy, proxy_start, proxy_period,
1136
vomsacseq, use_gsi_proxy, 1024);
1292
vomsacseq, use_gsi_proxy, keybits, signing_algorithm);
1137
1293
write_proxy_file(proxy_path, proxy_cert);
1182
1338
std::string proxy_cert;
1183
1339
create_proxy(proxy_cert, signer, policy, proxy_start, proxy_period,
1184
vomsacseq, use_gsi_proxy, 1024);
1340
vomsacseq, use_gsi_proxy, keybits, signing_algorithm);
1186
1342
//If myproxy command is "Put", then the proxy path is set to /tmp/myproxy-proxy.uid.pid
1187
1343
if (myproxy_command == "put" || myproxy_command == "PUT" || myproxy_command == "Put")
1237
1393
static void create_proxy(std::string& proxy_cert, Arc::Credential& signer,
1238
1394
const std::string& proxy_policy, Arc::Time& proxy_start, Arc::Period& proxy_period,
1239
const std::string& vomsacseq, bool use_gsi_proxy, int keybits) {
1395
const std::string& vomsacseq, bool use_gsi_proxy, int keybits,
1396
const std::string& signing_algorithm) {
1241
1398
std::string private_key, signing_cert, signing_cert_chain;
1242
1399
std::string req_str;
1400
if(keybits < 0) keybits = signer.GetKeybits();
1244
1402
Arc::Credential cred_request(proxy_start, proxy_period, keybits);
1403
cred_request.SetSigningAlgorithm(signer.GetSigningAlgorithm());
1405
if(!signing_algorithm.empty() && signing_algorithm != "inherit") {
1406
if(signing_algorithm == "sha1") {
1407
cred_request.SetSigningAlgorithm(Arc::SIGN_SHA1);
1408
} else if(signing_algorithm == "sha2") {
1409
cred_request.SetSigningAlgorithm(Arc::SIGN_SHA256);
1410
} else if(signing_algorithm == "sha224") {
1411
cred_request.SetSigningAlgorithm(Arc::SIGN_SHA224);
1412
} else if(signing_algorithm == "sha256") {
1413
cred_request.SetSigningAlgorithm(Arc::SIGN_SHA256);
1414
} else if(signing_algorithm == "sha384") {
1415
cred_request.SetSigningAlgorithm(Arc::SIGN_SHA384);
1416
} else if(signing_algorithm == "sha512") {
1417
cred_request.SetSigningAlgorithm(Arc::SIGN_SHA512);
1419
throw std::runtime_error("Unknown signing algorithm specified: "+signing_algorithm);
1245
1422
cred_request.GenerateRequest(req_str);
1246
1423
cred_request.OutputPrivatekey(private_key);
1247
1424
signer.OutputCertificate(signing_cert);
1587
1764
if (user_name.empty())
1588
1765
throw std::invalid_argument("Username to MyProxy server is missing");
1590
std::string prompt1 = "MyProxy server";
1592
1767
std::string passphrase;
1593
int res = input_password(password, 256, false, prompt1, "", logger);
1768
if(passsources[pass_myproxy]->Get(passphrase, 4, 256) != Arc::PasswordSource::PASSWORD)
1595
1769
throw std::invalid_argument("Error entering passphrase");
1596
passphrase = password;
1598
std::string prompt2 = "MyProxy server";
1599
char newpassword[256];
1600
1771
std::string newpassphrase;
1601
res = input_password(newpassword, 256, true, prompt1, prompt2, logger);
1772
if(passsources[pass_myproxy_new]->Get(newpassphrase, 4, 256) != Arc::PasswordSource::PASSWORD)
1603
1773
throw std::invalid_argument("Error entering passphrase");
1604
newpassphrase = newpassword;
1606
1775
if(usercfg.ProxyPath().empty() && !proxy_path.empty()) usercfg.ProxyPath(proxy_path);
1692
1857
if (user_name.empty())
1693
1858
throw std::invalid_argument("Username to MyProxy server is missing");
1695
std::string prompt1 = "MyProxy server";
1698
std::string passphrase = password;
1860
std::string passphrase;
1699
1861
if(!use_empty_passphrase) {
1700
int res = input_password(password, 256, false, prompt1, "", logger);
1862
if(passsources[pass_myproxy]->Get(passphrase, 4, 256) != Arc::PasswordSource::PASSWORD)
1702
1863
throw std::invalid_argument("Error entering passphrase");
1703
passphrase = password;
1706
1866
std::string proxy_cred_str_pem;
1780
1940
throw std::invalid_argument("Username to MyProxy server is missing");
1782
1942
std::string prompt1 = "MyProxy server";
1783
std::string prompt2 = "MyProxy server";
1785
1943
std::string passphrase;
1786
1944
if(retrievable_by_cert.empty()) {
1787
int res = input_password(password, 256, true, prompt1, prompt2, logger);
1945
if(passsources[pass_myproxy_new]->Get(passphrase, 4, 256) != Arc::PasswordSource::PASSWORD)
1789
1946
throw std::invalid_argument("Error entering passphrase");
1790
passphrase = password;
1793
1949
std::string proxy_cred_str_pem;