Back to index

nordugrid-arc-nox  1.1.0~rc6
ConfigTLSMCC.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <glibmm/miscutils.h>
00006 
00007 #include "PayloadTLSStream.h"
00008 
00009 #include "ConfigTLSMCC.h"
00010 
00011 namespace Arc {
00012 
00013 static void config_VOMS_add(XMLNode cfg,std::vector<std::string>& vomscert_trust_dn) {
00014   XMLNode nd = cfg["VOMSCertTrustDNChain"];
00015   for(;(bool)nd;++nd) {
00016     XMLNode cnd = nd["VOMSCertTrustDN"];
00017     if((bool)cnd) {
00018       for(;(bool)cnd;++cnd) {
00019         vomscert_trust_dn.push_back((std::string)cnd);
00020       }
00021       vomscert_trust_dn.push_back("----NEXT CHAIN----");
00022     } else {
00023       XMLNode rnd = nd["VOMSCertTrustRegex"];
00024       if(rnd) {
00025         std::string rgx = (std::string)rnd;
00026         if(rgx[0] != '^') rgx.insert(0,"^");
00027         if(rgx[rgx.length()-1] != '$') rgx+="$";
00028         vomscert_trust_dn.push_back(rgx);
00029         vomscert_trust_dn.push_back("----NEXT CHAIN----");
00030       }
00031     }
00032   }
00033 }
00034 
00035 // This class is collection of configuration information
00036 
00037 ConfigTLSMCC::ConfigTLSMCC(XMLNode cfg,Logger& logger,bool client) {
00038   client_authn_ = true;
00039   cert_file_ = (std::string)(cfg["CertificatePath"]);
00040   key_file_ = (std::string)(cfg["KeyPath"]);
00041   ca_file_ = (std::string)(cfg["CACertificatePath"]);
00042   ca_dir_ = (std::string)(cfg["CACertificatesDir"]);
00043   globus_policy_ = (((std::string)(cfg["CACertificatesDir"].Attribute("PolicyGlobus"))) == "true");
00044   handshake_ = (cfg["Handshake"] == "SSLv3")?ssl3_handshake:tls_handshake;
00045   proxy_file_ = (std::string)(cfg["ProxyPath"]);
00046   
00047   std::vector<std::string> gridSecDir (2);
00048   gridSecDir[0] = G_DIR_SEPARATOR_S + std::string("etc");
00049   gridSecDir[1] = "grid-security";
00050   std::string gridSecurityDir = Glib::build_path(G_DIR_SEPARATOR_S, gridSecDir);
00051 
00052   if(!client) {
00053     
00054     if(cert_file_.empty()) cert_file_= Glib::build_filename(gridSecurityDir, "hostcert.pem");
00055     if(key_file_.empty()) key_file_= Glib::build_filename(gridSecurityDir, "hostkey.pem");
00056     // Use VOMS trust DN of server certificates specified in configuration
00057     config_VOMS_add(cfg,vomscert_trust_dn_);
00058     // Look for those configured in separate files
00059     // TODO: should those file be reread on every connection
00060     XMLNode locnd = cfg["VOMSCertTrustDNChainsLocation"];
00061     for(;(bool)locnd;++locnd) {
00062       std::string filename = (std::string)locnd;
00063       std::ifstream file(filename.c_str());
00064       if (!file) {
00065         logger.msg(ERROR, "Can not read file %s with list of trusted VOMS DNs", filename);
00066         continue;
00067       };
00068       XMLNode node;
00069       file >> node;
00070       config_VOMS_add(node,vomscert_trust_dn_);
00071     };
00072     //If ClientAuthn is explicitly set to be "false" in configuration,
00073     //then client/authentication is not required, which means client 
00074     //side does not need to provide certificate and key in its configuration.
00075     //The default value of ClientAuthn is "true"
00076     if (((std::string)((cfg)["ClientAuthn"])) == "false") client_authn_ = false;
00077   } else {
00078     //If both CertificatePath and ProxyPath have not beed configured, 
00079     //client side can not provide certificate for server side. Then server 
00080     //side should not require client authentication
00081     if(cert_file_.empty() && proxy_file_.empty()) client_authn_ = false;
00082   };
00083   if(ca_dir_.empty() && ca_file_.empty()) ca_dir_= gridSecurityDir + G_DIR_SEPARATOR_S + "certificates";
00084   if(!proxy_file_.empty()) { key_file_=proxy_file_; cert_file_=proxy_file_; };
00085 }
00086 
00087 bool ConfigTLSMCC::Set(SSL_CTX* sslctx,Logger& logger) {
00088   int r;
00089   if((!ca_file_.empty()) || (!ca_dir_.empty())) {
00090     if(!SSL_CTX_load_verify_locations(sslctx, ca_file_.empty()?NULL:ca_file_.c_str(), ca_dir_.empty()?NULL:ca_dir_.c_str())) {
00091       logger.msg(ERROR, "Can not assign CA location - %s",ca_dir_.empty()?ca_file_:ca_dir_);
00092       PayloadTLSStream::HandleError(logger);
00093       return false;
00094     };
00095   };
00096   if(!cert_file_.empty()) {
00097     // Try to load proxy then PEM and then ASN1 certificate
00098     if((SSL_CTX_use_certificate_chain_file(sslctx,cert_file_.c_str()) != 1) &&
00099        (SSL_CTX_use_certificate_file(sslctx,cert_file_.c_str(),SSL_FILETYPE_PEM) != 1) &&
00100        (SSL_CTX_use_certificate_file(sslctx,cert_file_.c_str(),SSL_FILETYPE_ASN1) != 1)) {
00101       logger.msg(ERROR, "Can not load certificate file - %s",cert_file_);
00102       PayloadTLSStream::HandleError(logger);
00103       return false;
00104     };
00105   };
00106   if(!key_file_.empty()) {
00107     if((SSL_CTX_use_PrivateKey_file(sslctx,key_file_.c_str(),SSL_FILETYPE_PEM) != 1) &&
00108        (SSL_CTX_use_PrivateKey_file(sslctx,key_file_.c_str(),SSL_FILETYPE_ASN1) != 1)) {
00109       logger.msg(ERROR, "Can not load key file - %s",key_file_);
00110       PayloadTLSStream::HandleError(logger);
00111       return false;
00112     };
00113   };
00114   if((!key_file_.empty()) && (!cert_file_.empty()))
00115     if(!(SSL_CTX_check_private_key(sslctx))) {
00116       logger.msg(ERROR, "Private key %s does not match certificate %s",key_file_,cert_file_);
00117       PayloadTLSStream::HandleError(logger);
00118       return false;
00119     };
00120   return true;
00121 }
00122 
00123 } // namespace Arc
00124