Commit d00c388c authored by Andrii Salnikov's avatar Andrii Salnikov

Merge branch 'master' into voms-deploy-bug-3911

parents d40c1d64 f75486ec
=====================
ARC support for OIDC
=====================
Support level
==============
Currently support for OIDC tokens in ARC is at technology preview level.
Only tokens conforming to WLCG profile are supported.
Currently validation is not strict. Token is parsed and signature is
checked if present. But no additional requirements are imposed.
Tokens are only accepted for client authentication for job submission
through EMIES interface.
Obtaining and using tokens
===========================
Suggested way for obtaining token is through oidc-agent utility -
https://indigo-dc.gitbook.io/oidc-agent/. Install it following
instructions for your distribution.
Point your browser at https://wlcg.cloud.cnaf.infn.it/ and create
account.
Start oidc-agent. It will print few lines of shell commands. Copy
then at command line and execute. They will set up environment
variables for other oidc-* commands.
Start oidc-gen. It will guide You through steps to register OIDC
client and crete profile for oidc-agent. When asked about scope
write 'openid profile wlcg'. You need to run oidc-gen only once.
Next time You use oidc-agent You cam load already creted profile
with 'oidc-add NAME_YOU_CHOSE'.
Obtain token and store it into ARC_OTOKEN variable.
export ARC_OTKEN=`oidc-token NAME_YOU_CHOSE`
Now submit job to ARC CE with arcsub through EMIES interface. For that
use option '-S org.ogf.glue.emies.activitycreation'. The token stored
in ARC_TOKEN variable will be used instead of X.509 certificate for
authenticating user to ARC CE server.
Note: You can use any other method for obtaining WLCG compliant OIDC
token. Just store it into ARC_OTOKEN variable before calling arcsub.
Configuring authorization on server
====================================
User can be authorized on server by adding dedicated command to authgroup block:
otokens=subject issuer audience scope
Specified parameters must match those in provided token. Parameters
can be '*' to match any value. For example
otokens=e83eec5a-e2e3-43c6-bb67-df8f5ec3e8d0 https://wlcg.cloud.cnaf.infn.it/ * *
matches user with subject e83eec5a-e2e3-43c6-bb67-df8f5ec3e8d0 in token issued by
https://wlcg.cloud.cnaf.infn.it/ .
User mapping to local account is implemented using simulated X.509 user subject.
Because subjects obtained from OIDC tokens are not limited to domains/namespaces
the generated identifier suitable for mapping is composed of issuer and original
subject by catenating them like "issuer/subject". For example user with subject
e83eec5a-e2e3-43c6-bb67-df8f5ec3e8d0 in token issued by https://wlcg.cloud.cnaf.infn.it/
is represented by simulated identifier
https://wlcg.cloud.cnaf.infn.it//e83eec5a-e2e3-43c6-bb67-df8f5ec3e8d0
...@@ -2192,7 +2192,7 @@ AC_CONFIG_FILES([Makefile ...@@ -2192,7 +2192,7 @@ AC_CONFIG_FILES([Makefile
src/hed/libs/delegation/test/Makefile src/hed/libs/delegation/test/Makefile
src/hed/libs/xmlsec/Makefile src/hed/libs/xmlsec/Makefile
src/hed/libs/globusutils/Makefile src/hed/libs/globusutils/Makefile
src/hed/libs/scitokens/Makefile src/hed/libs/otokens/Makefile
src/hed/daemon/Makefile src/hed/daemon/Makefile
src/hed/daemon/scripts/Makefile src/hed/daemon/scripts/Makefile
src/hed/daemon/schema/Makefile src/hed/daemon/schema/Makefile
...@@ -2262,6 +2262,7 @@ AC_CONFIG_FILES([Makefile ...@@ -2262,6 +2262,7 @@ AC_CONFIG_FILES([Makefile
src/hed/shc/delegationsh/schema/Makefile src/hed/shc/delegationsh/schema/Makefile
src/hed/shc/legacy/Makefile src/hed/shc/legacy/Makefile
src/hed/shc/legacy/schema/Makefile src/hed/shc/legacy/schema/Makefile
src/hed/shc/otokens/Makefile
src/hed/identitymap/Makefile src/hed/identitymap/Makefile
src/hed/identitymap/schema/Makefile src/hed/identitymap/schema/Makefile
src/libs/Makefile src/libs/Makefile
......
...@@ -9,7 +9,7 @@ debian/tmp/usr/lib/libarcdatastaging.so.* ...@@ -9,7 +9,7 @@ debian/tmp/usr/lib/libarcdatastaging.so.*
debian/tmp/usr/lib/libarcloader.so.* debian/tmp/usr/lib/libarcloader.so.*
debian/tmp/usr/lib/libarcmessage.so.* debian/tmp/usr/lib/libarcmessage.so.*
debian/tmp/usr/lib/libarcsecurity.so.* debian/tmp/usr/lib/libarcsecurity.so.*
debian/tmp/usr/lib/libarcscitokens.so.* debian/tmp/usr/lib/libarcotokens.so.*
debian/tmp/usr/lib/libarcinfosys.so.* debian/tmp/usr/lib/libarcinfosys.so.*
debian/tmp/usr/lib/libarcwsaddressing.so.* debian/tmp/usr/lib/libarcwsaddressing.so.*
debian/tmp/usr/lib/libarcwssecurity.so.* debian/tmp/usr/lib/libarcwssecurity.so.*
......
...@@ -5,6 +5,7 @@ debian/tmp/usr/lib/arc/libaccARCHERY.so ...@@ -5,6 +5,7 @@ debian/tmp/usr/lib/arc/libaccARCHERY.so
debian/tmp/usr/lib/arc/libaccLDAP.so debian/tmp/usr/lib/arc/libaccLDAP.so
debian/tmp/usr/lib/arc/test/libaccTEST.so debian/tmp/usr/lib/arc/test/libaccTEST.so
debian/tmp/usr/lib/arc/libarcshclegacy.so debian/tmp/usr/lib/arc/libarcshclegacy.so
debian/tmp/usr/lib/arc/libarcshcotokens.so
debian/tmp/usr/lib/arc/libarcshc.so debian/tmp/usr/lib/arc/libarcshc.so
debian/tmp/usr/lib/arc/libdmcfile.so debian/tmp/usr/lib/arc/libdmcfile.so
debian/tmp/usr/lib/arc/libdmchttp.so debian/tmp/usr/lib/arc/libdmchttp.so
...@@ -26,6 +27,7 @@ debian/tmp/usr/lib/arc/libaccARCHERY.apd ...@@ -26,6 +27,7 @@ debian/tmp/usr/lib/arc/libaccARCHERY.apd
debian/tmp/usr/lib/arc/libaccLDAP.apd debian/tmp/usr/lib/arc/libaccLDAP.apd
debian/tmp/usr/lib/arc/test/libaccTEST.apd debian/tmp/usr/lib/arc/test/libaccTEST.apd
debian/tmp/usr/lib/arc/libarcshclegacy.apd debian/tmp/usr/lib/arc/libarcshclegacy.apd
debian/tmp/usr/lib/arc/libarcshcotokens.apd
debian/tmp/usr/lib/arc/libarcshc.apd debian/tmp/usr/lib/arc/libarcshc.apd
debian/tmp/usr/lib/arc/libdmcfile.apd debian/tmp/usr/lib/arc/libdmcfile.apd
debian/tmp/usr/lib/arc/libdmchttp.apd debian/tmp/usr/lib/arc/libdmchttp.apd
......
#include "../../../src/hed/libs/otokens/otokens.h"
...@@ -44,6 +44,11 @@ ARCSECURITY_CFLAGS='-I$(top_srcdir)/include' ...@@ -44,6 +44,11 @@ ARCSECURITY_CFLAGS='-I$(top_srcdir)/include'
AC_SUBST(ARCSECURITY_LIBS) AC_SUBST(ARCSECURITY_LIBS)
AC_SUBST(ARCSECURITY_CFLAGS) AC_SUBST(ARCSECURITY_CFLAGS)
ARCOTOKENS_LIBS='$(top_builddir)/src/hed/libs/security/libarcotokens.la'
ARCOTOKENS_CFLAGS='-I$(top_srcdir)/include'
AC_SUBST(ARCOTOKENS_LIBS)
AC_SUBST(ARCOTOKENS_CFLAGS)
ARCINFOSYS_LIBS='$(top_builddir)/src/hed/libs/infosys/libarcinfosys.la' ARCINFOSYS_LIBS='$(top_builddir)/src/hed/libs/infosys/libarcinfosys.la'
ARCINFOSYS_CFLAGS='-I$(top_srcdir)/include' ARCINFOSYS_CFLAGS='-I$(top_srcdir)/include'
AC_SUBST(ARCINFOSYS_LIBS) AC_SUBST(ARCINFOSYS_LIBS)
......
...@@ -1187,7 +1187,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || : ...@@ -1187,7 +1187,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || :
%{_libdir}/libarcloader.so.* %{_libdir}/libarcloader.so.*
%{_libdir}/libarcmessage.so.* %{_libdir}/libarcmessage.so.*
%{_libdir}/libarcsecurity.so.* %{_libdir}/libarcsecurity.so.*
%{_libdir}/libarcscitokens.so.* %{_libdir}/libarcotokens.so.*
%{_libdir}/libarcinfosys.so.* %{_libdir}/libarcinfosys.so.*
%{_libdir}/libarcwsaddressing.so.* %{_libdir}/libarcwsaddressing.so.*
%{_libdir}/libarcwssecurity.so.* %{_libdir}/libarcwssecurity.so.*
...@@ -1552,6 +1552,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || : ...@@ -1552,6 +1552,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || :
%{_libdir}/%{pkgdir}/libaccLDAP.so %{_libdir}/%{pkgdir}/libaccLDAP.so
%{_libdir}/%{pkgdir}/libarcshc.so %{_libdir}/%{pkgdir}/libarcshc.so
%{_libdir}/%{pkgdir}/libarcshclegacy.so %{_libdir}/%{pkgdir}/libarcshclegacy.so
%{_libdir}/%{pkgdir}/libarcshcotokens.so
%{_libdir}/%{pkgdir}/libdmcfile.so %{_libdir}/%{pkgdir}/libdmcfile.so
%{_libdir}/%{pkgdir}/libdmchttp.so %{_libdir}/%{pkgdir}/libdmchttp.so
%{_libdir}/%{pkgdir}/libdmcldap.so %{_libdir}/%{pkgdir}/libdmcldap.so
...@@ -1575,6 +1576,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || : ...@@ -1575,6 +1576,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || :
%{_libdir}/%{pkgdir}/libaccLDAP.apd %{_libdir}/%{pkgdir}/libaccLDAP.apd
%{_libdir}/%{pkgdir}/libarcshc.apd %{_libdir}/%{pkgdir}/libarcshc.apd
%{_libdir}/%{pkgdir}/libarcshclegacy.apd %{_libdir}/%{pkgdir}/libarcshclegacy.apd
%{_libdir}/%{pkgdir}/libarcshcotokens.apd
%{_libdir}/%{pkgdir}/libdmcfile.apd %{_libdir}/%{pkgdir}/libdmcfile.apd
%{_libdir}/%{pkgdir}/libdmchttp.apd %{_libdir}/%{pkgdir}/libdmchttp.apd
%{_libdir}/%{pkgdir}/libdmcldap.apd %{_libdir}/%{pkgdir}/libdmcldap.apd
......
...@@ -10,8 +10,12 @@ ...@@ -10,8 +10,12 @@
#include <arc/delegation/DelegationInterface.h> #include <arc/delegation/DelegationInterface.h>
#include <arc/compute/Job.h> #include <arc/compute/Job.h>
#include <arc/StringConv.h> #include <arc/StringConv.h>
#include <arc/otokens/otokens.h>
#include <arc/credential/Credential.h>
#include "JobStateEMIES.h" #include "JobStateEMIES.h"
#define USE_OTOKENS 1
#include "EMIESClient.h" #include "EMIESClient.h"
#ifdef CPPUNITTEST #ifdef CPPUNITTEST
...@@ -77,7 +81,25 @@ namespace Arc { ...@@ -77,7 +81,25 @@ namespace Arc {
soapfault(false) { soapfault(false) {
logger.msg(DEBUG, "Creating an EMI ES client"); logger.msg(DEBUG, "Creating an EMI ES client");
#ifdef USE_OTOKENS
otoken = Arc::GetEnv("ARC_OTOKEN");
std::cerr<<"OTOKEN: "<<otoken<<std::endl;
if(!otoken.empty()) {
// removing credentials from HTTPS layer
MCCConfig temp_cfg(cfg);
temp_cfg.proxy.clear();
temp_cfg.cert.clear();
temp_cfg.key.clear();
temp_cfg.credential.clear();
client = new ClientSOAP(temp_cfg, url, timeout);
} else {
client = new ClientSOAP(cfg, url, timeout);
}
#else
client = new ClientSOAP(cfg, url, timeout); client = new ClientSOAP(cfg, url, timeout);
#endif
if (!client) if (!client)
logger.msg(VERBOSE, "Unable to create SOAP client used by EMIESClient."); logger.msg(VERBOSE, "Unable to create SOAP client used by EMIESClient.");
set_namespaces(ns); set_namespaces(ns);
...@@ -98,7 +120,7 @@ namespace Arc { ...@@ -98,7 +120,7 @@ namespace Arc {
} }
std::string EMIESClient::dodelegation(const std::string& renew_id) { std::string EMIESClient::dodelegation(const std::string& renew_id) {
DelegationProviderSOAP* deleg; DelegationProviderSOAP* deleg(NULL);
if (!cfg.credential.empty()) { if (!cfg.credential.empty()) {
deleg = new DelegationProviderSOAP(cfg.credential); deleg = new DelegationProviderSOAP(cfg.credential);
} }
...@@ -131,6 +153,9 @@ namespace Arc { ...@@ -131,6 +153,9 @@ namespace Arc {
MessageAttributes attrout; MessageAttributes attrout;
MessageAttributes attrin; MessageAttributes attrin;
attrout.set("SOAP:ENDPOINT",rurl.str()); attrout.set("SOAP:ENDPOINT",rurl.str());
if(!otoken.empty())
attrout.set("HTTP:authorization", "bearer "+otoken);
if (!deleg->DelegateCredentialsInit(*entry,&attrout,&attrin,&(client->GetContext()), if (!deleg->DelegateCredentialsInit(*entry,&attrout,&attrin,&(client->GetContext()),
(renew_id.empty()?DelegationProviderSOAP::EMIDS:DelegationProviderSOAP::EMIDSRENEW))) { (renew_id.empty()?DelegationProviderSOAP::EMIDS:DelegationProviderSOAP::EMIDSRENEW))) {
lfailure = "Failed to initiate delegation credentials"; lfailure = "Failed to initiate delegation credentials";
...@@ -176,7 +201,12 @@ namespace Arc { ...@@ -176,7 +201,12 @@ namespace Arc {
std::string action = req.Child(0).Name(); std::string action = req.Child(0).Name();
PayloadSOAP* resp = NULL; PayloadSOAP* resp = NULL;
if (!client->process(&req, &resp)) {
std::multimap<std::string,std::string> http_attr;
if(!otoken.empty())
http_attr.insert(std::pair<std::string,std::string>("authorization","bearer "+otoken));
if (!client->process(http_attr, &req, &resp)) {
logger.msg(VERBOSE, "%s request failed", req.Child(0).FullName()); logger.msg(VERBOSE, "%s request failed", req.Child(0).FullName());
lfailure = "Failed processing request"; lfailure = "Failed processing request";
delete client; client = NULL; delete client; client = NULL;
......
...@@ -329,6 +329,8 @@ namespace Arc { ...@@ -329,6 +329,8 @@ namespace Arc {
const MCCConfig cfg; const MCCConfig cfg;
std::string otoken;
int timeout; int timeout;
std::string lfailure; std::string lfailure;
......
...@@ -14,6 +14,7 @@ libaccEMIES_la_SOURCES = EMIESClient.cpp EMIESClient.h \ ...@@ -14,6 +14,7 @@ libaccEMIES_la_SOURCES = EMIESClient.cpp EMIESClient.h \
libaccEMIES_la_CXXFLAGS = -I$(top_srcdir)/include \ libaccEMIES_la_CXXFLAGS = -I$(top_srcdir)/include \
$(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS) $(AM_CXXFLAGS) $(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS) $(AM_CXXFLAGS)
libaccEMIES_la_LIBADD = \ libaccEMIES_la_LIBADD = \
$(top_builddir)/src/hed/libs/otokens/libarcotokens.la \
$(top_builddir)/src/hed/libs/delegation/libarcdelegation.la \ $(top_builddir)/src/hed/libs/delegation/libarcdelegation.la \
$(top_builddir)/src/hed/libs/compute/libarccompute.la \ $(top_builddir)/src/hed/libs/compute/libarccompute.la \
$(top_builddir)/src/hed/libs/communication/libarccommunication.la \ $(top_builddir)/src/hed/libs/communication/libarccommunication.la \
...@@ -31,6 +32,7 @@ libaccEMIES_la_LDFLAGS = -no-undefined -avoid-version -module ...@@ -31,6 +32,7 @@ libaccEMIES_la_LDFLAGS = -no-undefined -avoid-version -module
arcemiestest_SOURCES = TestEMIESClient.cpp EMIESClient.cpp JobStateEMIES.cpp arcemiestest_SOURCES = TestEMIESClient.cpp EMIESClient.cpp JobStateEMIES.cpp
arcemiestest_CXXFLAGS = -I$(top_srcdir)/include $(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS) arcemiestest_CXXFLAGS = -I$(top_srcdir)/include $(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS)
arcemiestest_LDADD = \ arcemiestest_LDADD = \
$(top_builddir)/src/hed/libs/otokens/libarcotokens.la \
$(top_builddir)/src/hed/libs/delegation/libarcdelegation.la \ $(top_builddir)/src/hed/libs/delegation/libarcdelegation.la \
$(top_builddir)/src/hed/libs/communication/libarccommunication.la \ $(top_builddir)/src/hed/libs/communication/libarccommunication.la \
$(top_builddir)/src/hed/libs/compute/libarccompute.la \ $(top_builddir)/src/hed/libs/compute/libarccompute.la \
......
...@@ -15,9 +15,9 @@ SUBDIRS = common loader message crypto cryptomod \ ...@@ -15,9 +15,9 @@ SUBDIRS = common loader message crypto cryptomod \
credential credentialmod data security \ credential credentialmod data security \
ws-addressing $(XMLSEC_DIR) ws-security delegation \ ws-addressing $(XMLSEC_DIR) ws-security delegation \
communication compute infosys $(GLOBUSUTILS_DIR) \ communication compute infosys $(GLOBUSUTILS_DIR) \
credentialstore scitokens credentialstore otokens
DIST_SUBDIRS = common loader message crypto cryptomod \ DIST_SUBDIRS = common loader message crypto cryptomod \
credential credentialmod data security \ credential credentialmod data security \
ws-addressing xmlsec ws-security delegation \ ws-addressing xmlsec ws-security delegation \
communication compute infosys globusutils \ communication compute infosys globusutils \
credentialstore scitokens credentialstore otokens
...@@ -18,15 +18,15 @@ namespace Arc { ...@@ -18,15 +18,15 @@ namespace Arc {
// Implemented according to RFC4648, MSB first approach and assuming ASCII codes. // Implemented according to RFC4648, MSB first approach and assuming ASCII codes.
// There are no checks for bad characters. // There are no checks for bad characters.
static char base64_character_encode(char in) { static char base64_character_encode(char in, bool urlSafe) {
if(((unsigned char)in) < (unsigned char)26) return ('A' + in); if(((unsigned char)in) < (unsigned char)26) return ('A' + in);
in -= 26; in -= 26;
if(((unsigned char)in) < (unsigned char)26) return ('a' + in); if(((unsigned char)in) < (unsigned char)26) return ('a' + in);
in -= 26; in -= 26;
if(((unsigned char)in) < (unsigned char)10) return ('0' + in); if(((unsigned char)in) < (unsigned char)10) return ('0' + in);
in -= 10; in -= 10;
if(in == (char)0) return '+'; if(in == (char)0) return urlSafe ? '-' : '+';
if(in == (char)1) return '/'; if(in == (char)1) return urlSafe ? '_' : '/';
return '?'; return '?';
} }
...@@ -46,19 +46,19 @@ namespace Arc { ...@@ -46,19 +46,19 @@ namespace Arc {
static int base64_quantum_encode(const char in[3], int size, char out[4], bool urlSafe) { static int base64_quantum_encode(const char in[3], int size, char out[4], bool urlSafe) {
if(size == 3) { if(size == 3) {
out[0] = base64_character_encode((in[0]>>2) & 0x3f); out[0] = base64_character_encode((in[0]>>2) & 0x3f, urlSafe);
out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f)); out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f), urlSafe);
out[2] = base64_character_encode(((in[1]<<2) & 0x3c) | ((in[2]>>6) & 0x03)); out[2] = base64_character_encode(((in[1]<<2) & 0x3c) | ((in[2]>>6) & 0x03), urlSafe);
out[3] = base64_character_encode(in[2] & 0x3f); out[3] = base64_character_encode(in[2] & 0x3f, urlSafe);
} else if(size == 2) { } else if(size == 2) {
out[0] = base64_character_encode((in[0]>>2) & 0x3f); out[0] = base64_character_encode((in[0]>>2) & 0x3f, urlSafe);
out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f)); out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f), urlSafe);
out[2] = base64_character_encode((in[1]<<2) & 0x3c); out[2] = base64_character_encode((in[1]<<2) & 0x3c, urlSafe);
out[3] = '='; out[3] = '=';
if(urlSafe) return 3; if(urlSafe) return 3;
} else if(size == 1) { } else if(size == 1) {
out[0] = base64_character_encode((in[0]>>2) & 0x3f); out[0] = base64_character_encode((in[0]>>2) & 0x3f, urlSafe);
out[1] = base64_character_encode((in[0]<<4) & 0x30); out[1] = base64_character_encode((in[0]<<4) & 0x30, urlSafe);
out[2] = '='; out[2] = '=';
out[3] = '='; out[3] = '=';
if(urlSafe) return 2; if(urlSafe) return 2;
......
...@@ -95,9 +95,19 @@ namespace Arc { ...@@ -95,9 +95,19 @@ namespace Arc {
private: private:
T *object; T *object;
void (*deleter)(T*); void (*deleter)(T*);
void operator=(const AutoPointer<T>&);
AutoPointer(const AutoPointer&);
static void DefaultDeleter(T* o) { delete o; } static void DefaultDeleter(T* o) { delete o; }
void operator=(const AutoPointer<T>&);
#if __cplusplus >= 201103L
private:
AutoPointer(AutoPointer<T> const&);
#else
// Workaround for older gcc which does not implement construction
// of new elements in std::list according to specification.
public:
AutoPointer(AutoPointer<T> const& o) {
operator=(const_cast<AutoPointer<T>&>(o));
}
#endif
public: public:
/// NULL pointer constructor /// NULL pointer constructor
AutoPointer(void (*d)(T*) = &DefaultDeleter) AutoPointer(void (*d)(T*) = &DefaultDeleter)
...@@ -105,13 +115,24 @@ namespace Arc { ...@@ -105,13 +115,24 @@ namespace Arc {
/// Constructor which wraps pointer and optionally defines deletion function /// Constructor which wraps pointer and optionally defines deletion function
AutoPointer(T *o, void (*d)(T*) = &DefaultDeleter) AutoPointer(T *o, void (*d)(T*) = &DefaultDeleter)
: object(o), deleter(d) {} : object(o), deleter(d) {}
/// Moving constructor
AutoPointer(AutoPointer<T>& o)
: object(o.Release()), deleter(o.deleter) {}
/// Destructor destroys wrapped object using assigned deleter /// Destructor destroys wrapped object using assigned deleter
~AutoPointer(void) { ~AutoPointer(void) {
if (object) if(deleter) (*deleter)(object); if (object) if(deleter) (*deleter)(object);
object = NULL;
} }
void operator=(T* o) { AutoPointer<T>& operator=(T* o) {
if (object) if(deleter) (*deleter)(object); if (object) if(deleter) (*deleter)(object);
object = o; object = o;
return *this;
}
AutoPointer<T>& operator=(AutoPointer<T>& o) {
if (object) if(deleter) (*deleter)(object);
object = o.object;
o.object = NULL;
return *this;
} }
/// For referring wrapped object /// For referring wrapped object
T& operator*(void) const { T& operator*(void) const {
...@@ -254,4 +275,4 @@ namespace Arc { ...@@ -254,4 +275,4 @@ namespace Arc {
} // namespace Arc } // namespace Arc
# endif // __ARC_UTILS_H__ #endif // __ARC_UTILS_H__
...@@ -77,8 +77,8 @@ namespace Arc { ...@@ -77,8 +77,8 @@ namespace Arc {
const char *id) { const char *id) {
XMLNode comp = chain["Component"]; XMLNode comp = chain["Component"];
for (; (bool)comp; ++comp) for (; (bool)comp; ++comp)
if ((comp.Attribute("name") == name) && if ((!name || (comp.Attribute("name") == name)) &&
(comp.Attribute("id") == id)) (!id || (comp.Attribute("id") == id)))
return comp; return comp;
return XMLNode(); return XMLNode();
} }
...@@ -397,6 +397,12 @@ namespace Arc { ...@@ -397,6 +397,12 @@ namespace Arc {
comp.NewAttribute("entry") = "http"; comp.NewAttribute("entry") = "http";
comp.NewChild("Method") = "POST"; // Override using attributes if needed comp.NewChild("Method") = "POST"; // Override using attributes if needed
comp.NewChild("Endpoint") = url.str(true); // Override using attributes if needed comp.NewChild("Endpoint") = url.str(true); // Override using attributes if needed
// Pass information about protocol and hostname to TLS level
XMLNode compTLS = ConfigFindComponent(xmlcfg["Chain"], "tls.client", NULL);
if(compTLS) {
compTLS.NewChild("Hostname") = url.Host();
compTLS.NewChild("Protocol") = "http/1.1"; // educated guess
}
} }
ClientHTTP::~ClientHTTP() {} ClientHTTP::~ClientHTTP() {}
...@@ -476,6 +482,16 @@ namespace Arc { ...@@ -476,6 +482,16 @@ namespace Arc {
return r; return r;
} }
static void HTTPAttributesToMessage(std::multimap<std::string, std::string> const& attributes, Message& msg) {
std::multimap<std::string, std::string>::const_iterator it;
for (it = attributes.begin(); it != attributes.end(); it++) {
std::string key("HTTP:");
key.append((*it).first);
msg.Attributes()->add(key, (*it).second);
}
}
MCC_Status ClientHTTP::process(const std::string& method, MCC_Status ClientHTTP::process(const std::string& method,
const std::string& path, const std::string& path,
std::multimap<std::string, std::string>& attributes, std::multimap<std::string, std::string>& attributes,
...@@ -525,12 +541,8 @@ namespace Arc { ...@@ -525,12 +541,8 @@ namespace Arc {
reqmsg.Attributes()->set("HTTP:Range", "bytes=" + reqmsg.Attributes()->set("HTTP:Range", "bytes=" +
tostring(range_start) + "-"); tostring(range_start) + "-");
} }
std::map<std::string, std::string>::iterator it; HTTPAttributesToMessage(attributes, reqmsg);
for (it = attributes.begin(); it != attributes.end(); it++) {
std::string key("HTTP:");
key.append((*it).first);
reqmsg.Attributes()->add(key, (*it).second);
}
r = http_entry->process(reqmsg, repmsg); r = http_entry->process(reqmsg, repmsg);
if(!r) { if(!r) {
if (repmsg.Payload() != NULL) delete repmsg.Payload(); if (repmsg.Payload() != NULL) delete repmsg.Payload();
...@@ -705,6 +717,12 @@ namespace Arc { ...@@ -705,6 +717,12 @@ namespace Arc {
MCC_Status ClientSOAP::process(PayloadSOAP *request, MCC_Status ClientSOAP::process(PayloadSOAP *request,
PayloadSOAP **response) { PayloadSOAP **response) {
return process(std::multimap<std::string, std::string>(), request, response);
}
MCC_Status ClientSOAP::process(const std::multimap<std::string, std::string> &http_attr,
PayloadSOAP *request,
PayloadSOAP **response) {
*response = NULL; *response = NULL;
MCC_Status r; MCC_Status r;
if(!(r=Load())) return r; if(!(r=Load())) return r;
...@@ -718,6 +736,7 @@ namespace Arc { ...@@ -718,6 +736,7 @@ namespace Arc {
reqmsg.Payload(request); reqmsg.Payload(request);
repmsg.Attributes(&attributes_rep); repmsg.Attributes(&attributes_rep);
repmsg.Context(&context); repmsg.Context(&context);
HTTPAttributesToMessage(http_attr, reqmsg);
r = soap_entry->process(reqmsg, repmsg); r = soap_entry->process(reqmsg, repmsg);
if (repmsg.Payload() != NULL) { if (repmsg.Payload() != NULL) {
try { try {
...@@ -733,6 +752,13 @@ namespace Arc { ...@@ -733,6 +752,13 @@ namespace Arc {
MCC_Status ClientSOAP::process(const std::string& action, MCC_Status ClientSOAP::process(const std::string& action,
PayloadSOAP *request, PayloadSOAP *request,
PayloadSOAP **response) { PayloadSOAP **response) {
return process(std::multimap<std::string, std::string>(), action, request, response);
}
MCC_Status ClientSOAP::process(const std::multimap<std::string, std::string> &http_attr,
const std::string& action,
PayloadSOAP *request,
PayloadSOAP **response) {
*response = NULL; *response = NULL;
MCC_Status r; MCC_Status r;
if(!(r=Load())) return r; if(!(r=Load())) return r;
...@@ -747,6 +773,7 @@ namespace Arc { ...@@ -747,6 +773,7 @@ namespace Arc {
repmsg.Attributes(&attributes_rep); repmsg.Attributes(&attributes_rep);
repmsg.Context(&context); repmsg.Context(&context);
attributes_req.set("SOAP:ACTION", action); attributes_req.set("SOAP:ACTION", action);
HTTPAttributesToMessage(http_attr, reqmsg);
r = soap_entry->process(reqmsg, repmsg); r = soap_entry->process(reqmsg, repmsg);
if (repmsg.Payload() != NULL) { if (repmsg.Payload() != NULL) {
try { try {
......
...@@ -114,7 +114,7 @@ namespace Arc { ...@@ -114,7 +114,7 @@ namespace Arc {
return tls_entry ? tls_entry : tcp_entry; return tls_entry ? tls_entry : tcp_entry;
} }
virtual MCC_Status Load(); virtual MCC_Status Load();
void AddSecHandler(XMLNode handlercfg, TCPSec sec, const std::string& libanme = "", const std::string& libpath = ""); void AddSecHandler(XMLNode handlercfg, TCPSec sec, const std::string& libname = "", const std::string& libpath = "");
protected: protected:
MCC *tcp_entry; MCC *tcp_entry;
MCC *tls_entry; MCC *tls_entry;
...@@ -215,7 +215,7 @@ namespace Arc { ...@@ -215,7 +215,7 @@ namespace Arc {
MCC* GetEntry() { MCC* GetEntry() {
return http_entry; return http_entry;
} }
void AddSecHandler(XMLNode handlercfg, const std::string& libanme = "", const std::string& libpath = ""); void AddSecHandler(XMLNode handlercfg, const std::string& libname = "", const std::string& libpath = "");
virtual MCC_Status Load(); virtual MCC_Status Load();
void RelativeURI(bool val) { relative_uri=val; }; void RelativeURI(bool val) { relative_uri=val; };
const URL& GetURL() const { return default_url; }; const URL& GetURL() const { return default_url; };
...@@ -246,16 +246,21 @@ namespace Arc { ...@@ -246,16 +246,21 @@ namespace Arc {
virtual ~ClientSOAP(); virtual ~ClientSOAP();
/** Send SOAP request and receive response. */