Back to index

nordugrid-arc-nox  1.1.0~rc6
arcproxy.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #include <iostream>
00008 #include <fstream>
00009 #include <string>
00010 #include <stdexcept>
00011 #include <unistd.h>
00012 #include <stdlib.h>
00013 #include <sys/types.h>
00014 #include <sys/stat.h>
00015 #include <fcntl.h>
00016 #include <glibmm/stringutils.h>
00017 #include <glibmm/fileutils.h>
00018 #include <glibmm.h>
00019 #include <unistd.h>
00020 
00021 #include <arc/ArcLocation.h>
00022 #include <arc/Logger.h>
00023 #include <arc/DateTime.h>
00024 #include <arc/delegation/DelegationInterface.h>
00025 #include <arc/OptionParser.h>
00026 #include <arc/StringConv.h>
00027 #include <arc/User.h>
00028 #include <arc/Utils.h>
00029 #include <arc/UserConfig.h>
00030 #include <arc/client/ClientInterface.h>
00031 #include <arc/credential/VOMSAttribute.h>
00032 #include <arc/credential/VOMSUtil.h>
00033 #include <arc/credential/Credential.h>
00034 #include <arc/crypto/OpenSSL.h>
00035 
00036 #include <openssl/ui.h>
00037 
00038 static void tls_process_error(Arc::Logger& logger) {
00039   unsigned long err;
00040   err = ERR_get_error();
00041   if (err != 0) {
00042     logger.msg(Arc::ERROR, "OpenSSL Error -- %s", ERR_error_string(err, NULL));
00043     logger.msg(Arc::ERROR, "Library  : %s", ERR_lib_error_string(err));
00044     logger.msg(Arc::ERROR, "Function : %s", ERR_func_error_string(err));
00045     logger.msg(Arc::ERROR, "Reason   : %s", ERR_reason_error_string(err));
00046   }
00047   return;
00048 }
00049 
00050 #define PASS_MIN_LENGTH 6
00051 static int input_password(char *password, int passwdsz, bool verify,
00052                           const std::string prompt_info,
00053                           const std::string prompt_verify_info,
00054                           Arc::Logger& logger) {
00055   UI *ui = NULL;
00056   int res = 0;
00057   ui = UI_new();
00058   if (ui) {
00059     int ok = 0;
00060     char buf[256];
00061     memset(buf, 0, 256);
00062     int ui_flags = 0;
00063     char *prompt1 = NULL;
00064     char *prompt2 = NULL;
00065     prompt1 = UI_construct_prompt(ui, "passphrase", prompt_info.c_str());
00066     prompt2 = UI_construct_prompt(ui, "passphrase", prompt_verify_info.c_str());
00067     ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
00068     UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
00069     ok = UI_add_input_string(ui, prompt1, ui_flags, password,
00070                              PASS_MIN_LENGTH, BUFSIZ - 1);
00071     if (ok >= 0 && verify)
00072       ok = UI_add_verify_string(ui, prompt2, ui_flags, buf,
00073                                 PASS_MIN_LENGTH, BUFSIZ - 1, password);
00074     if (ok >= 0)
00075       do
00076         ok = UI_process(ui);
00077       while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
00078 
00079     if (ok >= 0)
00080       res = strlen(password);
00081     if (ok == -1) {
00082       logger.msg(Arc::ERROR, "User interface error");
00083       tls_process_error(logger);
00084       memset(password, 0, (unsigned int)passwdsz);
00085       res = 0;
00086     }
00087     if (ok == -2) {
00088       logger.msg(Arc::ERROR, "Aborted!");
00089       memset(password, 0, (unsigned int)passwdsz);
00090       res = 0;
00091     }
00092     UI_free(ui);
00093     OPENSSL_free(prompt1);
00094     OPENSSL_free(prompt2);
00095   }
00096   return res;
00097 }
00098 
00099 int main(int argc, char *argv[]) {
00100 
00101   setlocale(LC_ALL, "");
00102 
00103   Arc::Logger logger(Arc::Logger::getRootLogger(), "arcproxy");
00104   Arc::LogStream logcerr(std::cerr);
00105   logcerr.setFormat(Arc::ShortFormat);
00106   Arc::Logger::getRootLogger().addDestination(logcerr);
00107   Arc::Logger::getRootLogger().setThreshold(Arc::WARNING);
00108 
00109   Arc::ArcLocation::Init(argv[0]);
00110 
00111   Arc::OptionParser options(" ",
00112                             istring("The arcproxy command creates a proxy from a key/certificate pair for use in\n"
00113                                     "the ARC middleware"),
00114                             istring("Supported constraints are:\n"
00115                                     "  validityStart=time (e.g. 2008-05-29T10:20:30Z; if not specified, start from now)\n"
00116                                     "  validityEnd=time\n"
00117                                     "  validityPeriod=time (e.g. 43200 or 12h or 12H; if both validityPeriod and validityEnd not specified, the default is 12 hours)\n"
00118                                     "  vomsACvalidityPeriod=time (e.g. 43200 or 12h or 12H; if not specified, validityPeriod is used\n"
00119                                     "  proxyPolicy=policy content\n"
00120                                     "  proxyPolicyFile=policy file"));
00121 
00122   std::string proxy_path;
00123   options.AddOption('P', "proxy", istring("path to proxy file"),
00124                     istring("path"), proxy_path);
00125 
00126   std::string cert_path;
00127   options.AddOption('C', "cert", istring("path to certificate file"),
00128                     istring("path"), cert_path);
00129 
00130   std::string key_path;
00131   options.AddOption('K', "key", istring("path to private key file"),
00132                     istring("path"), key_path);
00133 
00134   std::string ca_dir;
00135   options.AddOption('T', "cadir", istring("path to trusted certificate directory, only needed for voms client functionality"),
00136                     istring("path"), ca_dir);
00137 
00138   std::string vomses_path;
00139   options.AddOption('V', "vomses", istring("path to voms server configuration file"),
00140                     istring("path"), vomses_path);
00141 
00142   std::list<std::string> vomslist;
00143   options.AddOption('S', "voms", istring("voms<:command>. Specify voms server (More than one voms server \n"
00144                                          "              can be specified like this: --voms VOa:command1 --voms VOb:command2). \n"
00145                                          "              :command is optional, and is used to ask for specific attributes(e.g: roles)\n"
00146                                          "              command option is:\n"
00147                                          "              all --- put all of this DN's attributes into AC; \n"
00148                                          "              list ---list all of the DN's attribute,will not create AC extension; \n"
00149                                          "              /Role=yourRole --- specify the role, if this DN \n"
00150                                          "                               has such a role, the role will be put into AC \n"
00151                                          "              /voname/groupname/Role=yourRole --- specify the vo,group and role if this DN \n"
00152                                          "                               has such a role, the role will be put into AC \n"
00153                                          ),
00154                     istring("string"), vomslist);
00155 
00156   std::list<std::string> orderlist;
00157   options.AddOption('o', "order", istring("group<:role>. Specify ordering of attributes \n"
00158                     "              Example: --order /knowarc.eu/coredev:Developer,/knowarc.eu/testers:Tester \n"
00159                     "              or: --order /knowarc.eu/coredev:Developer --order /knowarc.eu/testers:Tester \n"
00160                     " Note that it does not make sense to specify the order if you have two or more different voms server specified"),
00161                     istring("string"), orderlist);
00162 
00163   bool use_gsi_comm = false;
00164   options.AddOption('G', "gsicom", istring("use GSI communication protocol for contacting VOMS services"), use_gsi_comm);
00165 
00166   bool use_gsi_proxy = false;
00167   options.AddOption('O', "old", istring("use GSI proxy (RFC 3820 compliant proxy is default)"), use_gsi_proxy);
00168 
00169   bool info = false;
00170   options.AddOption('I', "info", istring("print all information about this proxy. \n"
00171                                          "              In order to show the Identity (DN without CN as subfix for proxy) \n"
00172                                          "              of the certificate, the 'trusted certdir' is needed."
00173                                          ),
00174                     info);
00175 
00176   std::string user_name; //user name to myproxy server
00177   options.AddOption('U', "user", istring("username to myproxy server"),
00178                     istring("string"), user_name);
00179 
00180   std::string passphrase; //passphrase to myproxy server
00181 //  options.AddOption('R', "pass", istring("passphrase to myproxy server"),
00182 //                    istring("string"), passphrase);
00183 
00184   std::string myproxy_server; //url of myproxy server
00185   options.AddOption('L', "myproxysrv", istring("url of myproxy server"),
00186                     istring("string"), myproxy_server);
00187 
00188   std::string myproxy_command; //command to myproxy server
00189   options.AddOption('M', "myproxycmd", istring("command to myproxy server. The command can be PUT and GET.\n"
00190                                                "              PUT/put -- put a delegated credential to myproxy server; \n"
00191                                                "              GET/get -- get a delegated credential from myproxy server, \n"
00192                                                "              credential (certificate and key) is not needed in this case. \n"
00193                                                "              myproxy functionality can be used together with voms\n"
00194                                                "              functionality.\n"
00195                                                ),
00196                     istring("string"), myproxy_command);
00197 
00198   std::list<std::string> constraintlist;
00199   options.AddOption('c', "constraint", istring("proxy constraints"),
00200                     istring("string"), constraintlist);
00201 
00202   int timeout = -1;
00203   options.AddOption('t', "timeout", istring("timeout in seconds (default 20)"),
00204                     istring("seconds"), timeout);
00205 
00206   std::string conffile;
00207   options.AddOption('z', "conffile",
00208                     istring("configuration file (default ~/.arc/client.conf)"),
00209                     istring("filename"), conffile);
00210 
00211   std::string debug;
00212   options.AddOption('d', "debug",
00213                     istring("FATAL, ERROR, WARNING, INFO, VERBOSE or DEBUG"),
00214                     istring("debuglevel"), debug);
00215 
00216   bool version = false;
00217   options.AddOption('v', "version", istring("print version information"),
00218                     version);
00219 
00220   std::list<std::string> params = options.Parse(argc, argv);
00221 
00222   // If debug is specified as argument, it should be set before loading the configuration.
00223   if (!debug.empty())
00224     Arc::Logger::getRootLogger().setThreshold(Arc::string_to_level(debug));
00225 
00226   Arc::UserConfig usercfg(conffile, Arc::initializeCredentialsType(Arc::initializeCredentialsType::SkipCredentials));
00227   if (!usercfg) {
00228     logger.msg(Arc::ERROR, "Failed configuration initialization");
00229     return EXIT_FAILURE;
00230   }
00231 
00232   if (debug.empty() && !usercfg.Verbosity().empty())
00233     Arc::Logger::getRootLogger().setThreshold(Arc::string_to_level(usercfg.Verbosity()));
00234 
00235   if (timeout > 0)
00236     usercfg.Timeout(timeout);
00237 
00238   if (version) {
00239     std::cout << Arc::IString("%s version %s", "arcproxy", VERSION) << std::endl;
00240     return EXIT_SUCCESS;
00241   }
00242 
00243   Arc::User user;
00244 
00245   try {
00246     if (params.size() != 0)
00247       throw std::invalid_argument("Wrong number of arguments!");
00248 
00249     // TODO: Conver to UserConfig. But only after UserConfig is extended.
00250     if (key_path.empty())
00251       key_path = Arc::GetEnv("X509_USER_KEY");
00252     if (key_path.empty())
00253       key_path = usercfg.KeyPath();
00254     if (key_path.empty())
00255 #ifndef WIN32
00256       key_path = user.Home() + G_DIR_SEPARATOR_S + ".globus" + G_DIR_SEPARATOR_S + "userkey.pem";
00257 #else
00258       key_path = std::string(g_get_home_dir()) + G_DIR_SEPARATOR_S + ".globus" + G_DIR_SEPARATOR_S + "userkey.pem";
00259 #endif
00260     if (!Glib::file_test(key_path, Glib::FILE_TEST_IS_REGULAR))
00261       key_path = "";
00262 
00263     if (cert_path.empty())
00264       cert_path = Arc::GetEnv("X509_USER_CERT");
00265     if (cert_path.empty())
00266       cert_path = usercfg.CertificatePath();
00267     if (cert_path.empty())
00268 #ifndef WIN32
00269       cert_path = user.Home() + G_DIR_SEPARATOR_S + ".globus" + G_DIR_SEPARATOR_S + "usercert.pem";
00270 #else
00271       cert_path = std::string(g_get_home_dir()) + G_DIR_SEPARATOR_S + ".globus" + G_DIR_SEPARATOR_S + "usercert.pem";
00272 #endif
00273     if (!Glib::file_test(cert_path, Glib::FILE_TEST_IS_REGULAR))
00274       cert_path = "";
00275 
00276     if (proxy_path.empty())
00277       proxy_path = Arc::GetEnv("X509_USER_PROXY");
00278     if (proxy_path.empty())
00279       proxy_path = usercfg.ProxyPath();
00280     if (proxy_path.empty())
00281       proxy_path = Glib::build_filename(Glib::get_tmp_dir(), "x509up_u" + Arc::tostring(user.get_uid()));
00282 
00283     if (ca_dir.empty())
00284       ca_dir = Arc::GetEnv("X509_CERT_DIR");
00285     if (ca_dir.empty())
00286       ca_dir = usercfg.CACertificatesDirectory();
00287     if (ca_dir.empty()) {
00288       ca_dir = std::string(g_get_home_dir()) + G_DIR_SEPARATOR_S + ".globus" + G_DIR_SEPARATOR_S + "certificates";
00289       if (!Glib::file_test(ca_dir, Glib::FILE_TEST_IS_DIR))
00290         ca_dir = "";
00291     }
00292     if (ca_dir.empty()) {
00293       ca_dir = user.Home() + G_DIR_SEPARATOR_S + ".globus" + G_DIR_SEPARATOR_S + "certificates";
00294       if (!Glib::file_test(ca_dir, Glib::FILE_TEST_IS_DIR))
00295         ca_dir = "";
00296     }
00297 #ifndef WIN32
00298     if (ca_dir.empty()) {
00299       ca_dir = "/etc/grid-security/certificates";
00300       if (!Glib::file_test(ca_dir, Glib::FILE_TEST_IS_DIR))
00301         ca_dir = "";
00302     }
00303 #endif
00304     if (ca_dir.empty()) {
00305       ca_dir = Arc::ArcLocation::Get() + G_DIR_SEPARATOR_S + "etc" + G_DIR_SEPARATOR_S + "grid-security" + G_DIR_SEPARATOR_S + "certificates";
00306       if (!Glib::file_test(ca_dir, Glib::FILE_TEST_IS_DIR))
00307         ca_dir = "";
00308     }
00309     if (ca_dir.empty()) {
00310       ca_dir = Arc::ArcLocation::Get() + G_DIR_SEPARATOR_S + "etc" + G_DIR_SEPARATOR_S + "certificates";
00311       if (!Glib::file_test(ca_dir, Glib::FILE_TEST_IS_DIR))
00312         ca_dir = "";
00313     }
00314     if (ca_dir.empty()) {
00315       ca_dir = Arc::ArcLocation::Get() + G_DIR_SEPARATOR_S + "share" + G_DIR_SEPARATOR_S + "certificates";
00316       if (!Glib::file_test(ca_dir, Glib::FILE_TEST_IS_DIR))
00317         ca_dir = "";
00318     }
00319   } catch (std::exception& err) {
00320     logger.msg(Arc::ERROR, err.what());
00321     tls_process_error(logger);
00322     return EXIT_FAILURE;
00323   }
00324 
00325   if (ca_dir.empty()) {
00326     logger.msg(Arc::ERROR, "Cannot find the CA Certificate Directory path, "
00327                "please setup environment X509_CERT_DIR, "
00328                "or cacertificatesdirectory in configuration file");
00329     return EXIT_FAILURE;
00330   }
00331 
00332   const Arc::Time now;
00333 
00334   if (info) {
00335     std::vector<std::string> voms_attributes;
00336     bool res = false;
00337 
00338     if (proxy_path.empty()) {
00339       logger.msg(Arc::ERROR, "Cannot find the path of the proxy file, "
00340                  "please setup environment X509_USER_PROXY, "
00341                  "or proxypath in configuration file");
00342       return EXIT_FAILURE;
00343     }
00344     else if (!(Glib::file_test(proxy_path, Glib::FILE_TEST_EXISTS))) {
00345       logger.msg(Arc::ERROR, "Cannot find file at %s for getting the proxy. "
00346                  "Please make sure this file exists.", proxy_path);
00347       return EXIT_FAILURE;
00348     }
00349 
00350     Arc::Credential holder(proxy_path, "", ca_dir, "");
00351     std::cout << Arc::IString("Subject: %s", holder.GetDN()) << std::endl;
00352     std::cout << Arc::IString("Identity: %s", holder.GetIdentityName()) << std::endl;
00353     if (holder.GetEndTime() < now)
00354       std::cout << Arc::IString("Time left for proxy: Proxy expired") << std::endl;
00355     else if (holder.GetVerification())
00356       std::cout << Arc::IString("Time left for proxy: %s", (holder.GetEndTime() - now).istr()) << std::endl;
00357     else
00358       std::cout << Arc::IString("Time left for proxy: Proxy not valid") << std::endl;
00359     std::cout << Arc::IString("Proxy path: %s", proxy_path) << std::endl;
00360     std::cout << Arc::IString("Proxy type: %s", certTypeToString(holder.GetType())) << std::endl;
00361 
00362     std::vector<std::string> voms_trust_dn;
00363     res = parseVOMSAC(holder, "", "", voms_trust_dn, voms_attributes, false);
00364     if (!res)
00365       logger.msg(Arc::ERROR, "VOMS attribute parsing failed");
00366 
00367     return EXIT_SUCCESS;
00368   }
00369 
00370   if (cert_path.empty() || key_path.empty()) {
00371     if (cert_path.empty())
00372       logger.msg(Arc::ERROR, "Cannot find the user certificate path, "
00373                  "please setup environment X509_USER_CERT, "
00374                  "or certificatepath in configuration file");
00375     if (key_path.empty())
00376       logger.msg(Arc::ERROR, "Cannot find the user private key path, "
00377                  "please setup environment X509_USER_KEY, "
00378                  "or keypath in configuration file");
00379     return EXIT_FAILURE;
00380   }
00381 
00382   std::map<std::string, std::string> constraints;
00383   for (std::list<std::string>::iterator it = constraintlist.begin();
00384        it != constraintlist.end(); it++) {
00385     std::string::size_type pos = it->find('=');
00386     if (pos != std::string::npos)
00387       constraints[it->substr(0, pos)] = it->substr(pos + 1);
00388     else
00389       constraints[*it] = "";
00390   }
00391 
00392   //Set the default proxy validity lifetime to 12 hours if there is
00393   //no validity lifetime provided by command caller
00394   if ((constraints["validityEnd"].empty()) &&
00395       (constraints["validityPeriod"].empty()))
00396     constraints["validityPeriod"] = "43200";
00397 
00398   //If the period is formated with hours, e.g., 12h, then change
00399   //it into seconds
00400   if (!(constraints["validityPeriod"].empty()) &&
00401       ((constraints["validityPeriod"].rfind("h") != std::string::npos) ||
00402        (constraints["validityPeriod"].rfind("H") != std::string::npos))) {
00403     unsigned long tmp;
00404     tmp = strtoll(constraints["validityPeriod"].c_str(), NULL, 0);
00405     tmp = tmp * 3600;
00406     std::string strtmp = Arc::tostring(tmp);
00407     constraints["validityPeriod"] = strtmp;
00408   }
00409 
00410   if (!(constraints["vomsACvalidityPeriod"].empty()) &&
00411       ((constraints["vomsACvalidityPeriod"].rfind("h") != std::string::npos) ||
00412        (constraints["vomsACvalidityPeriod"].rfind("H") != std::string::npos))) {
00413     unsigned long tmp;
00414     tmp = strtoll(constraints["vomsACvalidityPeriod"].c_str(), NULL, 0);
00415     tmp = tmp * 3600;
00416     std::string strtmp = Arc::tostring(tmp);
00417     constraints["vomsACvalidityPeriod"] = strtmp;
00418   }
00419 
00420   //Set the default proxy validity lifetime to 12 hours if there is
00421   //no validity lifetime provided by command caller
00422   if (constraints["vomsACvalidityPeriod"].empty()) {
00423     if ((constraints["validityEnd"].empty()) &&
00424         (constraints["validityPeriod"].empty()))
00425       constraints["vomsACvalidityPeriod"] = "43200";
00426     else if ((constraints["validityEnd"].empty()) &&
00427              (!(constraints["validityPeriod"].empty())))
00428       constraints["vomsACvalidityPeriod"] = constraints["validityPeriod"];
00429     else
00430       constraints["vomsACvalidityPeriod"] = constraints["validityStart"].empty() ? (Arc::Time(constraints["validityEnd"]) - now) : (Arc::Time(constraints["validityEnd"]) - Arc::Time(constraints["validityStart"]));
00431   }
00432 
00433   std::string voms_period = Arc::tostring(Arc::Period(constraints["vomsACvalidityPeriod"]).GetPeriod());
00434 
00435   Arc::OpenSSLInit();
00436 
00437   //If the "GET" myproxy command is given, try to get a delegated
00438   //certificate from the myproxy server.
00439   //For "GET" command, certificate and key are not needed, and
00440   //anonymous GSSAPI is used (GSS_C_ANON_FLAG)
00441   try {
00442     if (myproxy_command == "get" || myproxy_command == "GET") {
00443       std::string send_msg("VERSION=MYPROXYv2\n COMMAND=0\n ");
00444       if (user_name.empty())
00445         throw std::invalid_argument("Username to myproxy server is missing");
00446       send_msg.append("USERNAME=").append(user_name).append("\n ");
00447 
00448 //      if (passphrase.empty())
00449 //        throw std::invalid_argument("Passphrase to myproxy server is missing");
00450 
00451       std::string prompt1 = "MyProxy server";
00452       char password[256];
00453       int res = input_password(password, 256, false, prompt1, "", logger);
00454       if (!res)
00455         throw std::invalid_argument("Error entering passphrase");
00456 
00457       passphrase = password;
00458 
00459       send_msg.append("PASSPHRASE=").append(passphrase).append("\n ");
00460       send_msg.append("LIFETIME=43200\n");
00461 
00462       if (myproxy_server.empty())
00463         throw std::invalid_argument("URL of myproxy server is missing");
00464       std::string host;
00465       int port;
00466       std::string::size_type pos = myproxy_server.find(":");
00467       if (pos == std::string::npos) {
00468         host = myproxy_server;
00469         port = 7512;
00470       }
00471       else {
00472         host = myproxy_server.substr(0, pos);
00473         Arc::stringto(myproxy_server.substr(pos), port);
00474       }
00475       Arc::MCCConfig cfg;
00476       //if(!proxy_path.empty())
00477       //  cfg.AddProxy(proxy_path);
00478       cfg.AddCADir(ca_dir);
00479       //TODO: for "GET" command, client authentication is optional
00480       Arc::ClientTCP client(cfg, host, port, Arc::GSISec, usercfg.Timeout());
00481 
00482       //Send the message to myproxy server
00483       Arc::PayloadRaw request;
00484       request.Insert(send_msg.c_str(), 0, send_msg.length());
00485       Arc::PayloadStreamInterface *response = NULL;
00486       Arc::MCC_Status status = client.process(&request, &response, true);
00487       if (!status) {
00488         logger.msg(Arc::ERROR, (std::string)status);
00489         if (response)
00490           delete response;
00491         return EXIT_FAILURE;
00492       }
00493       if (!response) {
00494         logger.msg(Arc::ERROR, "No stream response");
00495         return EXIT_FAILURE;
00496       }
00497 
00498       //Parse the response message from myproxy server
00499       std::string ret_str;
00500       char ret_buf[1024];
00501       memset(ret_buf, 0, 1024);
00502       int len;
00503       do {
00504         len = 1024;
00505         response->Get(&ret_buf[0], len);
00506         ret_str.append(ret_buf, len);
00507         memset(ret_buf, 0, 1024);
00508       } while (len == 1024);
00509       logger.msg(Arc::DEBUG, "Returned msg from myproxy server: %s", ret_str.c_str());
00510       if (ret_str.find("RESPONSE=0") == std::string::npos) {
00511         //TODO: process "RESPONSE=2"
00512         logger.msg(Arc::ERROR, "Myproxy server return failure msg");
00513         return EXIT_FAILURE;
00514       }
00515       if (response) {
00516         delete response;
00517         response = NULL;
00518       }
00519 
00520       //Generate a certificate request,
00521       //and send it to myproxy server
00522       std::string x509_req_str;
00523       Arc::Time start;
00524       Arc::Credential x509_request(start, Arc::Period(), 1024);
00525       x509_request.GenerateRequest(x509_req_str, true);
00526       std::string proxy_key_str;
00527       x509_request.OutputPrivatekey(proxy_key_str);
00528 
00529       Arc::PayloadRaw request1;
00530       request1.Insert(x509_req_str.c_str(), 0, x509_req_str.length());
00531       status = client.process(&request1, &response, true);
00532       if (!status) {
00533         logger.msg(Arc::ERROR, (std::string)status);
00534         if (response)
00535           delete response;
00536         return EXIT_FAILURE;
00537       }
00538       if (!response) {
00539         logger.msg(Arc::ERROR, "No stream response");
00540         return EXIT_FAILURE;
00541       }
00542 
00543       std::string ret_str1;
00544       memset(ret_buf, 0, 1024);
00545       do {
00546         len = 1024;
00547         response->Get(&ret_buf[0], len);
00548         ret_str1.append(ret_buf, len);
00549         memset(ret_buf, 0, 1024);
00550       } while (len == 1024);
00551       logger.msg(Arc::DEBUG, "Returned msg from myproxy server: %s", ret_str1.c_str());
00552 
00553       //The response includes a signed certificate
00554       BIO *bio = BIO_new(BIO_s_mem());
00555       BIO_write(bio, (unsigned char*)(ret_str1.c_str()), ret_str1.length());
00556       unsigned char number_of_certs;
00557       BIO_read(bio, &number_of_certs, sizeof(number_of_certs));
00558       logger.msg(Arc::DEBUG, "There are %d certificates in the returned msg", number_of_certs);
00559       std::string proxy_cert_str;
00560       for (;;) {
00561         char s[256];
00562         int l = BIO_read(bio, s, sizeof(s));
00563         if (l <= 0)
00564           break;
00565         proxy_cert_str.append(s, l);
00566       }
00567       BIO_free_all(bio);
00568 
00569       //Output the PEM formated proxy certificate
00570       std::string tmpcert_file;
00571       tmpcert_file = Glib::build_filename(Glib::get_tmp_dir(), "tmpcert.pem");
00572       std::ofstream tmpcert_f(tmpcert_file.c_str(), std::ofstream::binary);
00573       std::string tmpkey_file;
00574       tmpkey_file = Glib::build_filename(Glib::get_tmp_dir(), "tmpkey.pem");
00575       std::ofstream tmpkey_f(tmpkey_file.c_str(), std::ofstream::binary);
00576       tmpcert_f.write(proxy_cert_str.c_str(), proxy_cert_str.size());
00577       tmpkey_f.write(proxy_key_str.c_str(), proxy_key_str.size());
00578       tmpcert_f.close();
00579       tmpkey_f.close();
00580 
00581       Arc::Credential proxy_cred(tmpcert_file, tmpkey_file, ca_dir, "");
00582       std::string proxy_cred_str_pem;
00583       proxy_cred.OutputCertificate(proxy_cred_str_pem);
00584       proxy_cred.OutputPrivatekey(proxy_cred_str_pem);
00585       proxy_cred.OutputCertificateChain(proxy_cred_str_pem);
00586 
00587       int f = ::open(proxy_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
00588       if (f == -1)
00589         throw std::runtime_error("Failed to open proxy file " + proxy_path);
00590       if (::write(f, proxy_cred_str_pem.c_str(), proxy_cred_str_pem.length()) != proxy_cred_str_pem.length())
00591         throw std::runtime_error("Failed to write into proxy file " + proxy_path);
00592       ::close(f);
00593 
00594       //Myproxy server will then return a standard response message
00595       std::string ret_str2;
00596       memset(ret_buf, 0, 1024);
00597       do {
00598         len = 1024;
00599         response->Get(&ret_buf[0], len);
00600         ret_str2.append(ret_buf, len);
00601         memset(ret_buf, 0, 1024);
00602       } while (len == 1024);
00603       logger.msg(Arc::DEBUG, "Returned msg from myproxy server: %s", ret_str2.c_str());
00604       if (ret_str.find("RESPONSE=0") == std::string::npos) {
00605         //TODO: process "RESPONSE=2"
00606         logger.msg(Arc::ERROR, "Myproxy server return failure msg");
00607         return EXIT_FAILURE;
00608       }
00609 
00610       if (response) {
00611         delete response;
00612         response = NULL;
00613       }
00614       //return EXIT_SUCCESS;
00615       //Assign proxy_path to cert_path and key_path,
00616       //so the later voms functionality can use the proxy_path
00617       //to create proxy with voms AC extension. In this
00618       //case, "--cert" and "--key" is not needed.
00619       cert_path = proxy_path;
00620       key_path = proxy_path;
00621     }
00622 
00623   } catch (std::exception& err) {
00624     logger.msg(Arc::ERROR, err.what());
00625     tls_process_error(logger);
00626     return EXIT_FAILURE;
00627   }
00628 
00629   //Create proxy or voms proxy
00630   try {
00631     std::cout << Arc::IString("Your identity: %s", Arc::Credential(cert_path, "", "", "").GetDN()) << std::endl;
00632 
00633     Arc::Credential signer(cert_path, key_path, ca_dir, "");
00634     if((signer.GetVerification()) == false) {
00635       if (now > signer.GetEndTime())
00636         std::cerr << "Proxy generation failed: Certificate has expired." << std::endl;
00637       else if (now < signer.GetStartTime())
00638         std::cerr << "Proxy generation failed: Certificate is not valid yet." << std::endl;
00639       //else In the other cases a error message should already have been printed.
00640       return EXIT_FAILURE;
00641     }
00642 
00643     std::string private_key, signing_cert, signing_cert_chain;
00644 
00645     Arc::Time start = constraints["validityStart"].empty() ? Arc::Time() : Arc::Time(constraints["validityStart"]);
00646     Arc::Period period1 = constraints["validityEnd"].empty() ? Arc::Period(std::string("43200")) : (Arc::Time(constraints["validityEnd"]) - start);
00647     Arc::Period period = constraints["validityPeriod"].empty() ? period1 : (Arc::Period(constraints["validityPeriod"]));
00648     int keybits = 1024;
00649     std::string req_str;
00650     std::string policy;
00651     policy = constraints["proxyPolicy"].empty() ? constraints["proxyPolicyFile"] : constraints["proxyPolicy"];
00652     //Arc::Credential cred_request(start, period, keybits, "rfc", policy.empty() ? "inheritAll" : "anylanguage", policy, -1);
00653     Arc::Credential cred_request(start - Arc::Period(300), period, keybits);
00654     cred_request.GenerateRequest(req_str);
00655     cred_request.OutputPrivatekey(private_key);
00656     signer.OutputCertificate(signing_cert);
00657     signer.OutputCertificateChain(signing_cert_chain);
00658 
00659     if (!vomslist.empty()) { //If we need to generate voms proxy
00660 
00661       //Generate a temporary self-signed proxy certificate
00662       //to contact the voms server
00663       signer.SignRequest(&cred_request, proxy_path.c_str());
00664       std::ofstream out_f(proxy_path.c_str(), std::ofstream::app);
00665       out_f.write(private_key.c_str(), private_key.size());
00666       out_f.write(signing_cert.c_str(), signing_cert.size());
00667       out_f.write(signing_cert_chain.c_str(), signing_cert_chain.size());
00668       out_f.close();
00669 
00670       //Parse the voms server and command from command line
00671       std::multimap<std::string, std::string> server_command_map;
00672       for (std::list<std::string>::iterator it = vomslist.begin();
00673            it != vomslist.end(); it++) {
00674         size_t p;
00675         std::string voms_server;
00676         std::string command;
00677         p = (*it).find(":");
00678         voms_server = (p == std::string::npos) ? (*it) : (*it).substr(0, p);
00679         command = (p == std::string::npos) ? "" : (*it).substr(p + 1);
00680         server_command_map.insert(std::pair<std::string, std::string>(voms_server, command));
00681       }
00682 
00683       //Parse the 'vomses' file to find configure lines corresponding to
00684       //the information from the command line
00685       if (vomses_path.empty())
00686         vomses_path = Arc::GetEnv("X509_VOMS_DIR");
00687       if (vomses_path.empty())
00688         vomses_path = usercfg.VOMSServerPath();
00689 
00690       if (vomses_path.empty()) {
00691         vomses_path = "/etc/grid-security/vomses";
00692         if (!Glib::file_test(vomses_path, Glib::FILE_TEST_IS_REGULAR)) {
00693           vomses_path = Arc::ArcLocation::Get() + G_DIR_SEPARATOR_S + "etc" + G_DIR_SEPARATOR_S + "grid-security" + G_DIR_SEPARATOR_S + "vomses";
00694           if (!Glib::file_test(vomses_path, Glib::FILE_TEST_IS_REGULAR)) {
00695             vomses_path = user.Home() + G_DIR_SEPARATOR_S + ".vomses";
00696             if (!Glib::file_test(vomses_path, Glib::FILE_TEST_IS_REGULAR)) {
00697               vomses_path = G_DIR_SEPARATOR_S;
00698               vomses_path.append("etc").append(G_DIR_SEPARATOR_S).append("grid-security").append(G_DIR_SEPARATOR_S).append("vomses");
00699               if (!Glib::file_test(vomses_path, Glib::FILE_TEST_IS_REGULAR)) {
00700                 vomses_path = G_DIR_SEPARATOR_S;
00701                 vomses_path.append("etc").append(G_DIR_SEPARATOR_S).append("vomses");
00702                 if (!Glib::file_test(vomses_path, Glib::FILE_TEST_IS_REGULAR)) {
00703                   vomses_path = user.Home() + G_DIR_SEPARATOR_S + ".voms" + G_DIR_SEPARATOR_S + "vomses";
00704                   if (!Glib::file_test(vomses_path, Glib::FILE_TEST_IS_REGULAR)) {
00705                     std::string tmp1 = Arc::ArcLocation::Get() + G_DIR_SEPARATOR_S + "etc" + G_DIR_SEPARATOR_S + "grid-security" + G_DIR_SEPARATOR_S + "vomses";
00706                     std::string tmp2 = user.Home() + G_DIR_SEPARATOR_S + ".vomses";
00707                     std::string tmp3 = G_DIR_SEPARATOR_S;
00708                     tmp3.append("etc").append(G_DIR_SEPARATOR_S).append("grid-security").append(G_DIR_SEPARATOR_S).append("vomses");
00709                     std::string tmp4 = G_DIR_SEPARATOR_S;
00710                     tmp4.append("etc").append(G_DIR_SEPARATOR_S).append("vomses");
00711                     std::string tmp5 = user.Home() + G_DIR_SEPARATOR_S + ".voms" + G_DIR_SEPARATOR_S + "vomses";
00712                     logger.msg(Arc::ERROR, "Cannot find vomses at %s, %s, %s, %s and %s",
00713                                tmp1.c_str(), tmp2.c_str(), tmp3.c_str(), tmp4.c_str(), tmp5.c_str());
00714                     return EXIT_FAILURE;
00715                   }
00716                 }
00717               }
00718             }
00719           }
00720         }
00721       }
00722 
00723       std::ifstream in_f(vomses_path.c_str());
00724       std::map<std::string, std::string> matched_voms_line;
00725       std::string voms_line;
00726       while (true) {
00727         voms_line.clear();
00728         std::getline<char>(in_f, voms_line, '\n');
00729         if (voms_line.empty())
00730           break;
00731         if((voms_line.size() >= 1) && (voms_line[0] == '#')) continue;
00732 
00733         size_t pos = voms_line.rfind("\"");
00734         std::string str;
00735         if (pos != std::string::npos) {
00736           voms_line.erase(pos);
00737           pos = voms_line.rfind("\"");
00738           if (pos != std::string::npos) {
00739             str = voms_line.substr(pos + 1);
00740             for (std::multimap<std::string, std::string>::iterator it = server_command_map.begin();
00741                  it != server_command_map.end(); it++) {
00742               std::string voms_server = (*it).first;
00743               if (str == voms_server) {
00744                 matched_voms_line[voms_server] = voms_line;
00745                 break;
00746               };
00747             };
00748           };
00749         };
00750 
00751         //you can also use the acronym name of the voms server
00752         size_t pos1 = voms_line.find("\"");
00753         if (pos1 != std::string::npos) {
00754           size_t pos2 = voms_line.find("\"", pos1+1);
00755           if (pos2 != std::string::npos) {
00756             std::string str1 = voms_line.substr(pos1+1, pos2-pos1-1);
00757             for (std::multimap<std::string, std::string>::iterator it = server_command_map.begin();
00758                  it != server_command_map.end(); it++) {
00759               std::string voms_server = (*it).first;
00760               if (str1 == voms_server) {
00761                 matched_voms_line[str] = voms_line;
00762                 break;
00763               };
00764             };
00765           };
00766         };
00767 
00768       }
00769       //Judge if we can not find any of the voms server in the command line from 'vomses' file
00770       //if(matched_voms_line.empty()) {
00771       //  logger.msg(Arc::ERROR, "Cannot get voms server information from file: %s ", vomses_path.c_str());
00772       // throw std::runtime_error("Cannot get voms server information from file: " + vomses_path);
00773       //}
00774       if (matched_voms_line.size() != server_command_map.size())
00775         for (std::multimap<std::string, std::string>::iterator it = server_command_map.begin();
00776              it != server_command_map.end(); it++)
00777           if (matched_voms_line.find((*it).first) == matched_voms_line.end())
00778             logger.msg(Arc::ERROR, "Cannot get voms server %s information from file: %s ",
00779                        (*it).first, vomses_path.c_str());
00780 
00781       //Contact the voms server to retrieve attribute certificate
00782       std::string voms_server;
00783       std::list<std::string> command_list;
00784       ArcCredential::AC **aclist = NULL;
00785       std::string acorder;
00786       Arc::MCCConfig cfg;
00787       cfg.AddProxy(proxy_path);
00788       cfg.AddCADir(ca_dir);
00789 
00790       for (std::map<std::string, std::string>::iterator it = matched_voms_line.begin();
00791            it != matched_voms_line.end(); it++) {
00792         std::map<std::string, std::string>::iterator it = matched_voms_line.begin();
00793         voms_server = (*it).first;
00794         voms_line = (*it).second;
00795         int count = server_command_map.count(voms_server);
00796         logger.msg(Arc::DEBUG, "There are %d commands to the same voms server %s\n", count, voms_server.c_str());
00797 
00798         std::multimap<std::string, std::string>::iterator command_it;
00799         for(command_it = server_command_map.equal_range(voms_server).first; command_it!=server_command_map.equal_range(voms_server).second; ++command_it) {
00800           command_list.push_back((*command_it).second);
00801         }
00802 
00803         size_t p = 0;
00804         for (int i = 0; i < 3; i++) {
00805           p = voms_line.find("\"", p);
00806           if (p == std::string::npos) {
00807             logger.msg(Arc::ERROR, "Cannot get voms server address information from voms line: %s\"", voms_line.c_str());
00808             throw std::runtime_error("Cannot get voms server address information from voms line:" + voms_line + "\"");
00809           }
00810           p = p + 1;
00811         }
00812 
00813         size_t p1 = voms_line.find("\"", p + 1);
00814         std::string address = voms_line.substr(p, p1 - p);
00815         p = voms_line.find("\"", p1 + 1);
00816         p1 = voms_line.find("\"", p + 1);
00817         std::string port = voms_line.substr(p + 1, p1 - p - 1);
00818         logger.msg(Arc::INFO, "Contacting VOMS server (named %s): %s on port: %s",
00819                    voms_server.c_str(), address.c_str(), port.c_str());
00820         std::cout << Arc::IString("Contacting VOMS server (named %s): %s on port: %s", voms_server, address, port) << std::endl;
00821 
00822         std::string send_msg;
00823         send_msg.append("<?xml version=\"1.0\" encoding = \"US-ASCII\"?><voms>");
00824         std::string command;
00825 
00826         for(std::list<std::string>::iterator c_it = command_list.begin(); c_it != command_list.end(); c_it++) {
00827           std::string command_2server;
00828           command = *c_it;
00829           if (command.empty())
00830             command_2server.append("G/").append(voms_server);
00831           else if (command == "all" || command == "ALL")
00832             command_2server.append("A");
00833           else if (command == "list")
00834             command_2server.append("N");
00835           else {
00836             std::string::size_type pos = command.find("/Role=");
00837             if (pos == 0)
00838               command_2server.append("R").append(command.substr(pos + 6));
00839             else if (pos != std::string::npos && pos > 0)
00840               command_2server.append("B").append(command.substr(0, pos)).append(":").append(command.substr(pos + 6));
00841             else if(command[0] == '/')
00842               command_2server.append("G").append(command);
00843           }
00844           send_msg.append("<command>").append(command_2server).append("</command>");
00845         }
00846 
00847         std::string ordering;
00848         for(std::list<std::string>::iterator o_it = orderlist.begin(); o_it != orderlist.end(); o_it++) {
00849           ordering.append(o_it == orderlist.begin() ? "" : ",").append(*o_it);
00850         }
00851         logger.msg(Arc::VERBOSE, "Try to get attribute from voms server with order: %s ", ordering.c_str());
00852         send_msg.append("<order>").append(ordering).append("</order>");
00853 
00854         send_msg.append("<lifetime>").append(voms_period).append("</lifetime></voms>");
00855         Arc::ClientTCP client(cfg, address, atoi(port.c_str()), use_gsi_comm ? Arc::GSISec : Arc::SSL3Sec, usercfg.Timeout());
00856         Arc::PayloadRaw request;
00857         request.Insert(send_msg.c_str(), 0, send_msg.length());
00858         Arc::PayloadStreamInterface *response = NULL;
00859         Arc::MCC_Status status = client.process(&request, &response, true);
00860         if (!status) {
00861           logger.msg(Arc::ERROR, (std::string)status);
00862           if (response)
00863             delete response;
00864           return EXIT_FAILURE;
00865         }
00866         if (!response) {
00867           logger.msg(Arc::ERROR, "No stream response from voms server");
00868           return EXIT_FAILURE;
00869         }
00870         std::string ret_str;
00871         char ret_buf[1024];
00872         memset(ret_buf, 0, 1024);
00873         int len;
00874         do {
00875           len = 1024;
00876           response->Get(&ret_buf[0], len);
00877           ret_str.append(ret_buf, len);
00878           memset(ret_buf, 0, 1024);
00879         } while (len == 1024);
00880         logger.msg(Arc::VERBOSE, "Returned msg from voms server: %s ", ret_str.c_str());
00881         Arc::XMLNode node(ret_str);
00882 
00883         if (ret_str.find("error") != std::string::npos) {
00884           std::string str = node["error"]["item"]["message"];
00885           throw std::runtime_error("Cannot get any AC or attributes info from voms server: " + voms_server + ";\n       Returned msg from voms server: " + str);
00886         }
00887 
00888         //Put the return attribute certificate into proxy certificate as the extension part
00889         std::string codedac;
00890         if (command == "list")
00891           codedac = (std::string)(node["bitstr"]);
00892         else
00893           codedac = (std::string)(node["ac"]);
00894         std::string decodedac;
00895         int size;
00896         char *dec = NULL;
00897         dec = Arc::VOMSDecode((char*)(codedac.c_str()), codedac.length(), &size);
00898         decodedac.append(dec, size);
00899         if (dec != NULL) {
00900           free(dec);
00901           dec = NULL;
00902         }
00903 
00904         if (command == "list") {
00905           //logger.msg(Arc::INFO, "The attribute information from voms server: %s is list as following:\n%s",
00906           //           voms_server.c_str(), decodedac.c_str());
00907           std::cout << Arc::IString("The attribute information from voms server: %s is list as following", voms_server) << std::endl << decodedac;
00908           if (response)
00909             delete response;
00910           return EXIT_SUCCESS;
00911         }
00912 
00913         if (response)
00914           delete response;
00915 
00916         Arc::addVOMSAC(aclist, acorder, decodedac);
00917       }
00918 
00919       //Put the returned attribute certificate into proxy certificate
00920       if (aclist != NULL)
00921         cred_request.AddExtension("acseq", (char**)aclist);
00922       if (!acorder.empty())
00923         cred_request.AddExtension("order", acorder);
00924     }
00925 
00926     if (!use_gsi_proxy)
00927       cred_request.SetProxyPolicy("rfc", policy.empty() ? "inheritAll" : "anylanguage", policy, -1);
00928     else
00929       cred_request.SetProxyPolicy("gsi2", "", "", -1);
00930 
00931     std::string proxy_cert;
00932     if (!signer.SignRequest(&cred_request, proxy_cert))
00933       throw std::runtime_error("Failed to sign proxy");
00934 
00935     proxy_cert.append(private_key).append(signing_cert).append(signing_cert_chain);
00936 
00937     int f = ::open(proxy_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
00938     if (f == -1)
00939       throw std::runtime_error("Failed to open proxy file " + proxy_path);
00940     if (::write(f, proxy_cert.c_str(), proxy_cert.length()) != proxy_cert.length())
00941       throw std::runtime_error("Failed to write into proxy file " + proxy_path);
00942     ::close(f);
00943 
00944     Arc::Credential proxy_cred(proxy_path, proxy_path, ca_dir, "");
00945     Arc::Time left = proxy_cred.GetEndTime();
00946     std::cout << Arc::IString("Proxy generation succeeded") << std::endl;
00947     std::cout << Arc::IString("Your proxy is valid until: %s", left.str(Arc::UserTime)) << std::endl;
00948 
00949     //return EXIT_SUCCESS;
00950   } catch (std::exception& err) {
00951     logger.msg(Arc::ERROR, err.what());
00952     tls_process_error(logger);
00953     return EXIT_FAILURE;
00954   }
00955 
00956   //Delegate the former self-delegated credential to
00957   //myproxy server
00958   try {
00959     if (myproxy_command == "put" || myproxy_command == "PUT") {
00960       //Create the message that will be
00961       //sent to myproxy server
00962       std::string send_msg("VERSION=MYPROXYv2\n COMMAND=1\n ");
00963       if (user_name.empty())
00964         throw std::invalid_argument("Username to myproxy server is missing");
00965       send_msg.append("USERNAME=").append(user_name).append("\n ");
00966 //      if (passphrase.empty())
00967 //        throw std::invalid_argument("Passphrase to myproxy server is missing");
00968 
00969       std::string prompt1 = "MyProxy server";
00970       std::string prompt2 = "MyProxy server";
00971       char password[256];
00972       int res = input_password(password, 256, true, prompt1, prompt2, logger);
00973       if (!res)
00974         throw std::invalid_argument("Error entering passphrase");
00975 
00976       passphrase = password;
00977 
00978       send_msg.append("PASSPHRASE=").append(passphrase).append("\n ");
00979       send_msg.append("LIFETIME=43200\n");
00980 
00981       if (myproxy_server.empty())
00982         throw std::invalid_argument("URL of myproxy server is missing");
00983       std::string host;
00984       int port;
00985       std::string::size_type pos = myproxy_server.find(":");
00986       if (pos == std::string::npos) {
00987         host = myproxy_server;
00988         port = 7512;
00989       }
00990       else {
00991         host = myproxy_server.substr(0, pos);
00992         Arc::stringto(myproxy_server.substr(pos), port);
00993       }
00994       Arc::MCCConfig cfg;
00995       cfg.AddProxy(proxy_path);
00996       cfg.AddCADir(ca_dir);
00997       Arc::ClientTCP client(cfg, host, port, Arc::GSISec, usercfg.Timeout());
00998 
00999       //Send the message to myproxy server
01000       Arc::PayloadRaw request;
01001       request.Insert(send_msg.c_str(), 0, send_msg.length());
01002       Arc::PayloadStreamInterface *response = NULL;
01003       Arc::MCC_Status status = client.process(&request, &response, true);
01004       if (!status) {
01005         logger.msg(Arc::ERROR, (std::string)status);
01006         if (response)
01007           delete response;
01008         return EXIT_FAILURE;
01009       }
01010       if (!response) {
01011         logger.msg(Arc::ERROR, "No stream response");
01012         return EXIT_FAILURE;
01013       }
01014 
01015       //Parse the response message from myproxy server
01016       std::string ret_str;
01017       char ret_buf[1024];
01018       memset(ret_buf, 0, 1024);
01019       int len;
01020       do {
01021         len = 1024;
01022         response->Get(&ret_buf[0], len);
01023         ret_str.append(ret_buf, len);
01024         memset(ret_buf, 0, 1024);
01025       } while (len == 1024);
01026       logger.msg(Arc::DEBUG, "Returned msg from myproxy server: %s", ret_str.c_str());
01027       if (ret_str.find("RESPONSE=0") == std::string::npos) {
01028         //TODO: process "RESPONSE=2"
01029         logger.msg(Arc::ERROR, "Myproxy server return failure msg");
01030         return EXIT_FAILURE;
01031       }
01032 
01033       //Myproxy server will then send back another message which includes
01034       //the x509 certificate request in DER format
01035       std::string x509ret_str;
01036       memset(ret_buf, 0, 1024);
01037       do {
01038         len = 1024;
01039         response->Get(&ret_buf[0], len);
01040         x509ret_str.append(ret_buf, len);
01041         memset(ret_buf, 0, 1024);
01042       } while (len == 1024);
01043       logger.msg(Arc::DEBUG, "Returned msg from myproxy server: %s", x509ret_str.c_str());
01044       if (ret_str.find("RESPONSE=1") != std::string::npos) {
01045         logger.msg(Arc::ERROR, "Myproxy server return failure msg");
01046         return EXIT_FAILURE;
01047       }
01048 
01049       if (response) {
01050         delete response;
01051         response = NULL;
01052       }
01053 
01054       //Sign the x509 certificate request
01055       Arc::Credential signer(proxy_path, "", ca_dir, "");
01056       Arc::Credential proxy;
01057       std::string signedcert, signing_cert, signing_cert_chain;
01058       proxy.InquireRequest(x509ret_str, false, true);
01059       proxy.SetProxyPolicy("rfc", "inheritAll", "", -1);
01060       if (!(signer.SignRequest(&proxy, signedcert, true))) {
01061         logger.msg(Arc::ERROR, "Delegate proxy to myproxy server failed");
01062         return EXIT_FAILURE;
01063       }
01064       signer.OutputCertificate(signing_cert, true);
01065       signer.OutputCertificateChain(signing_cert_chain, true);
01066       signedcert.append(signing_cert).append(signing_cert_chain);
01067 
01068       //Send back the proxy certificate to myproxy server
01069       //Caculate the numbers of certifictes as the beginning of the message
01070       unsigned char number_of_certs;
01071       number_of_certs = signer.GetCertNumofChain() + 2;
01072       BIO *bio = BIO_new(BIO_s_mem());
01073       BIO_write(bio, &number_of_certs, sizeof(number_of_certs));
01074       std::string start;
01075       for (;;) {
01076         char s[256];
01077         int l = BIO_read(bio, s, sizeof(s));
01078         if (l <= 0)
01079           break;
01080         start.append(s, l);
01081       }
01082       BIO_free_all(bio);
01083       signedcert.insert(0, start);
01084 
01085       Arc::PayloadRaw request1;
01086       request1.Insert(signedcert.c_str(), 0, signedcert.length());
01087       status = client.process(&request1, &response, true);
01088       if (!status) {
01089         logger.msg(Arc::ERROR, (std::string)status);
01090         if (response)
01091           delete response;
01092         return EXIT_FAILURE;
01093       }
01094       if (!response) {
01095         logger.msg(Arc::ERROR, "No stream response");
01096         return EXIT_FAILURE;
01097       }
01098       std::string ret_str1;
01099       memset(ret_buf, 0, 1024);
01100       do {
01101         len = 1024;
01102         response->Get(&ret_buf[0], len);
01103         ret_str1.append(ret_buf, len);
01104         memset(ret_buf, 0, 1024);
01105       } while (len == 1024);
01106       logger.msg(Arc::DEBUG, "Returned msg from myproxy server: %s", ret_str1.c_str());
01107       if (ret_str.find("RESPONSE=0") == std::string::npos) {
01108         //TODO: process "RESPONSE=2"
01109         logger.msg(Arc::ERROR, "Myproxy server return failure msg");
01110         return EXIT_FAILURE;
01111       }
01112 
01113       if (response) {
01114         delete response;
01115         response = NULL;
01116       }
01117 
01118       return EXIT_SUCCESS;
01119     }
01120   } catch (std::exception& err) {
01121     logger.msg(Arc::ERROR, err.what());
01122     tls_process_error(logger);
01123     return EXIT_FAILURE;
01124   }
01125 
01126   return EXIT_SUCCESS;
01127 
01128 }