Back to index

nordugrid-arc-nox  1.1.0~rc6
Functions | Variables
arcslcs.cpp File Reference
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/bio.h>
#include <arc/ArcLocation.h>
#include <arc/Logger.h>
#include <arc/credential/Credential.h>
#include <arc/client/ClientSAML2SSO.h>
#include <arc/message/MCC.h>
#include <arc/OptionParser.h>
#include <arc/StringConv.h>
#include <arc/User.h>
#include <arc/Utils.h>
#include <arc/URL.h>
#include <arc/UserConfig.h>
#include <arc/xmlsec/XmlSecUtils.h>

Go to the source code of this file.


static void tls_process_error (void)
void handleSLCS ()
int main (int argc, char *argv[])


static Arc::Loggerlogger = Arc::Logger::rootLogger
std::string slcs_url
std::string idp_name
std::string username
std::string password
int keysize = 0
std::string keypass
std::string storedir
int lifetime
std::string key_path
std::string cert_path
std::string cert_req_path
std::string trusted_ca_path
std::string trusted_ca_dir
Arc::MCCConfig mcc_cfg

Function Documentation

void handleSLCS ( )

Definition at line 68 of file arcslcs.cpp.

    //Generate certificate request
    Arc::Time t;
    Arc::User user;
    Arc::Credential request(t, Arc::Period(lifetime * 3600), keysize, "EEC");
    std::string cert_req_str;
    if (!request.GenerateRequest(cert_req_str))
      throw std::runtime_error("Failed to generate certificate request");

    std::ofstream out_cert_req(cert_req_path.c_str(), std::ofstream::out);
    out_cert_req.write(cert_req_str.c_str(), cert_req_str.size());
    std::string private_key;
    //If the passphrase for protecting private key has not been set,
    // the private key will not be protected by passphrase.
    if (keypass.empty())
      request.OutputPrivatekey(private_key, true, keypass);
    std::ofstream out_key(key_path.c_str(), std::ofstream::out);
    out_key.write(private_key.c_str(), private_key.size());

    //Send soap message to service, implicitly including the SAML2SSO profile

    Arc::URL url(slcs_url);

    Arc::ClientSOAPwithSAML2SSO *client_soap = NULL;
    client_soap = new Arc::ClientSOAPwithSAML2SSO(mcc_cfg, url);
    logger.msg(Arc::INFO, "Creating and sending soap request");

    Arc::NS slcs_ns;
    slcs_ns["slcs"] = "";
    Arc::PayloadSOAP req_soap(slcs_ns);
    req_soap.NewChild("GetSLCSCertificateRequest").NewChild("X509Request") = cert_req_str;

    Arc::PayloadSOAP *resp_soap = NULL;
    if (client_soap) {
      Arc::MCC_Status status = client_soap->process(&req_soap, &resp_soap, idp_name, username, password);
      if (!status) {
        logger.msg(Arc::ERROR, "SOAP with SAML2SSO invokation failed");
        delete client_soap;
        throw std::runtime_error("SOAP with SAML2SSO invokation failed");
      if (resp_soap == NULL) {
        logger.msg(Arc::ERROR, "There was no SOAP response");
        delete client_soap;
        throw std::runtime_error("There was no SOAP response");

    std::string cert_str = (std::string)((*resp_soap)["GetSLCSCertificateResponse"]["X509Certificate"]);
    std::string ca_str = (std::string)((*resp_soap)["GetSLCSCertificateResponse"]["CACertificate"]);
    if (resp_soap)
      delete resp_soap;
    if (client_soap)
      delete client_soap;

    //Output the responded slcs certificate and CA certificate
    std::ofstream out_cert(cert_path.c_str(), std::ofstream::out);
    out_cert.write(cert_str.c_str(), cert_str.size());

    char ca_name[20];
    if (!ca_str.empty()) {
      BIO *ca_bio = BIO_new_mem_buf((void*)(ca_str.c_str()), ca_str.length());
      X509 *ca_cert = PEM_read_bio_X509(ca_bio, NULL, NULL, NULL);
      unsigned long ca_hash;
      ca_hash = X509_subject_name_hash(ca_cert);
      snprintf(ca_name, 20, "%08lx.0", ca_hash);
    std::string ca_path = cert_path.substr(0, (cert_path.size() - 13)) + "/certificates/" + ca_name;
    std::ofstream out_ca(ca_path.c_str(), std::ofstream::out);
    out_ca.write(ca_str.c_str(), ca_str.size());


Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char *  argv[] 

Definition at line 149 of file arcslcs.cpp.


  setlocale(LC_ALL, "");

  Arc::LogStream logcerr(std::cerr);

  Arc::User user;


  Arc::OptionParser options("", "", "");


  options.AddOption('S', "url", istring("URL of SLCS service"),
                    istring("url"), slcs_url);

  options.AddOption('I', "idp", istring("IdP name"),
                    istring("string"), idp_name);

  options.AddOption('U', "user", istring("User account to IdP"),
                    istring("string"), username);

  options.AddOption('P', "password", istring("Password for user account to IdP"),
                    istring("string"), password);

  options.AddOption('Z', "keysize", istring("Key size of the private key (512, 1024, 2048)"),
                    istring("number"), keysize);

  options.AddOption('K', "keypass", istring("Private key passphrase"),
                    istring("passphrase"), keypass);

  int lifetime = 0;
  options.AddOption('L', "lifetime", istring("Lifetime of the certificate, start with current time, hour as unit"),
                    istring("period"), lifetime);

  options.AddOption('D', "storedir", istring("Store directory for key and signed certificate"),
                    istring("directory"), storedir);

  std::string conffile;
  options.AddOption('z', "conffile",
                    istring("configuration file (default ~/.arc/client.conf)"),
                    istring("filename"), conffile);

  std::string debug;
  options.AddOption('d', "debug",
                    istring("FATAL, ERROR, WARNING, INFO, VERBOSE or DEBUG"),
                    istring("debuglevel"), debug);

  bool version = false;
  options.AddOption('v', "version", istring("print version information"),

  std::list<std::string> params = options.Parse(argc, argv);

  // If debug is specified as argument, it should be set before loading the configuration.
  if (!debug.empty())

  Arc::UserConfig usercfg(conffile,  Arc::initializeCredentialsType(Arc::initializeCredentialsType::SkipCredentials));
  if (!usercfg) {
    logger.msg(Arc::ERROR, "Failed configuration initialization");
    return 1;

  if (debug.empty() && !usercfg.Verbosity().empty())

  if (slcs_url.empty() && usercfg.SLCS())
    slcs_url = usercfg.SLCS().str();

  if (idp_name.empty() && usercfg.IdPName().empty())
    idp_name = usercfg.IdPName();

  if (username.empty() && !usercfg.UserName().empty())
    username = usercfg.UserName();

  if (password.empty() && !usercfg.Password().empty())
    password = usercfg.Password();

  if (keysize == 0 && usercfg.KeySize() > 0)
    keysize = usercfg.KeySize();
  else if (keysize == 0)
    keysize = 1024;

  if (keypass.empty() && !usercfg.KeyPassword().empty())
    keypass = usercfg.KeyPassword();

  if (lifetime == 0 && usercfg.CertificateLifeTime() > 0) {
    lifetime = usercfg.CertificateLifeTime().GetPeriod();
  if (lifetime == 0)
    lifetime = 12;

  if (storedir.empty() && !usercfg.StoreDirectory().empty())
    storedir = usercfg.StoreDirectory();

  trusted_ca_path = usercfg.CACertificatePath();
  trusted_ca_dir = usercfg.CACertificatesDirectory();

  if (version) {
    std::cout << Arc::IString("%s version %s", "arcslcs", VERSION) << std::endl;
    return 0;

  try {
    if (params.size() != 0)
      throw std::invalid_argument("Wrong number of arguments!");

    if (storedir.empty()) {
      key_path = Arc::GetEnv("X509_USER_KEY");
      if (key_path.empty())
        key_path = /*user.get_uid() == 0 ? "/etc/grid-security/hostkey.pem" :*/
                   user.Home() + "/.globus/userkey.pem";
      key_path = storedir + "/userkey.pem";

    if (storedir.empty()) {
      cert_path = Arc::GetEnv("X509_USER_CERT");
      if (cert_path.empty())
        cert_path = /*user.get_uid() == 0 ? "/etc/grid-security/hostcert.pem" :*/
                    user.Home() + "/.globus/usercert.pem";
    else {
      cert_path = storedir + "/usercert.pem";
      cert_req_path = cert_path.substr(0, (cert_path.size() - 13)) + "/usercert_request.pem";

  if (!trusted_ca_path.empty())

  if (trusted_ca_dir.empty())
     trusted_ca_dir = user.get_uid() == 0 ? "/etc/grid-security/certificates" :
            user.Home() + "/.globus/certificates";
  if (!trusted_ca_dir.empty())


    return EXIT_SUCCESS;
  } catch (std::exception& err) {
    std::cerr << "ERROR: " << err.what() << std::endl;
    return EXIT_FAILURE;

Here is the call graph for this function:

static void tls_process_error ( void  ) [static]

Definition at line 37 of file arcslcs.cpp.

  unsigned long err;
  err = ERR_get_error();
  if (err != 0) {
    logger.msg(Arc::ERROR, "OpenSSL Error -- %s", ERR_error_string(err, NULL));
    logger.msg(Arc::ERROR, "Library  : %s", ERR_lib_error_string(err));
    logger.msg(Arc::ERROR, "Function : %s", ERR_func_error_string(err));
    logger.msg(Arc::ERROR, "Reason   : %s", ERR_reason_error_string(err));

Here is the call graph for this function:

Here is the caller graph for this function:

Variable Documentation

std::string cert_path

Definition at line 59 of file arcslcs.cpp.

std::string cert_req_path

Definition at line 60 of file arcslcs.cpp.

std::string idp_name

Definition at line 50 of file arcslcs.cpp.

std::string key_path

Definition at line 59 of file arcslcs.cpp.

std::string keypass

Definition at line 54 of file arcslcs.cpp.

int keysize = 0

Definition at line 53 of file arcslcs.cpp.

int lifetime

Definition at line 56 of file arcslcs.cpp.

Definition at line 35 of file arcslcs.cpp.

Definition at line 65 of file arcslcs.cpp.

std::string password

Definition at line 52 of file arcslcs.cpp.

std::string slcs_url

Definition at line 49 of file arcslcs.cpp.

std::string storedir

Definition at line 55 of file arcslcs.cpp.

std::string trusted_ca_dir

Definition at line 64 of file arcslcs.cpp.

std::string trusted_ca_path

Definition at line 64 of file arcslcs.cpp.

std::string username

Definition at line 51 of file arcslcs.cpp.