Commit f75486ec authored by Aleksandr Konstantinov's avatar Aleksandr Konstantinov

Merge branch 'scitokens' into 'master'

Technology preview of OIDC tokens support.

See merge request !956
parents c1fd89e7 734aa630
Pipeline #7525 passed with stages
in 94 minutes and 33 seconds
=====================
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
src/hed/libs/delegation/test/Makefile
src/hed/libs/xmlsec/Makefile
src/hed/libs/globusutils/Makefile
src/hed/libs/scitokens/Makefile
src/hed/libs/otokens/Makefile
src/hed/daemon/Makefile
src/hed/daemon/scripts/Makefile
src/hed/daemon/schema/Makefile
......@@ -2262,6 +2262,7 @@ AC_CONFIG_FILES([Makefile
src/hed/shc/delegationsh/schema/Makefile
src/hed/shc/legacy/Makefile
src/hed/shc/legacy/schema/Makefile
src/hed/shc/otokens/Makefile
src/hed/identitymap/Makefile
src/hed/identitymap/schema/Makefile
src/libs/Makefile
......
......@@ -9,7 +9,7 @@ debian/tmp/usr/lib/libarcdatastaging.so.*
debian/tmp/usr/lib/libarcloader.so.*
debian/tmp/usr/lib/libarcmessage.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/libarcwsaddressing.so.*
debian/tmp/usr/lib/libarcwssecurity.so.*
......
......@@ -5,6 +5,7 @@ debian/tmp/usr/lib/arc/libaccARCHERY.so
debian/tmp/usr/lib/arc/libaccLDAP.so
debian/tmp/usr/lib/arc/test/libaccTEST.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/libdmcfile.so
debian/tmp/usr/lib/arc/libdmchttp.so
......@@ -26,6 +27,7 @@ debian/tmp/usr/lib/arc/libaccARCHERY.apd
debian/tmp/usr/lib/arc/libaccLDAP.apd
debian/tmp/usr/lib/arc/test/libaccTEST.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/libdmcfile.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'
AC_SUBST(ARCSECURITY_LIBS)
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_CFLAGS='-I$(top_srcdir)/include'
AC_SUBST(ARCINFOSYS_LIBS)
......
......@@ -1187,7 +1187,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || :
%{_libdir}/libarcloader.so.*
%{_libdir}/libarcmessage.so.*
%{_libdir}/libarcsecurity.so.*
%{_libdir}/libarcscitokens.so.*
%{_libdir}/libarcotokens.so.*
%{_libdir}/libarcinfosys.so.*
%{_libdir}/libarcwsaddressing.so.*
%{_libdir}/libarcwssecurity.so.*
......@@ -1552,6 +1552,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || :
%{_libdir}/%{pkgdir}/libaccLDAP.so
%{_libdir}/%{pkgdir}/libarcshc.so
%{_libdir}/%{pkgdir}/libarcshclegacy.so
%{_libdir}/%{pkgdir}/libarcshcotokens.so
%{_libdir}/%{pkgdir}/libdmcfile.so
%{_libdir}/%{pkgdir}/libdmchttp.so
%{_libdir}/%{pkgdir}/libdmcldap.so
......@@ -1575,6 +1576,7 @@ service arc-infosys-ldap condrestart > /dev/null 2>&1 || :
%{_libdir}/%{pkgdir}/libaccLDAP.apd
%{_libdir}/%{pkgdir}/libarcshc.apd
%{_libdir}/%{pkgdir}/libarcshclegacy.apd
%{_libdir}/%{pkgdir}/libarcshcotokens.apd
%{_libdir}/%{pkgdir}/libdmcfile.apd
%{_libdir}/%{pkgdir}/libdmchttp.apd
%{_libdir}/%{pkgdir}/libdmcldap.apd
......
......@@ -10,8 +10,12 @@
#include <arc/delegation/DelegationInterface.h>
#include <arc/compute/Job.h>
#include <arc/StringConv.h>
#include <arc/otokens/otokens.h>
#include <arc/credential/Credential.h>
#include "JobStateEMIES.h"
#define USE_OTOKENS 1
#include "EMIESClient.h"
#ifdef CPPUNITTEST
......@@ -77,7 +81,25 @@ namespace Arc {
soapfault(false) {
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);
#endif
if (!client)
logger.msg(VERBOSE, "Unable to create SOAP client used by EMIESClient.");
set_namespaces(ns);
......@@ -98,7 +120,7 @@ namespace Arc {
}
std::string EMIESClient::dodelegation(const std::string& renew_id) {
DelegationProviderSOAP* deleg;
DelegationProviderSOAP* deleg(NULL);
if (!cfg.credential.empty()) {
deleg = new DelegationProviderSOAP(cfg.credential);
}
......@@ -131,6 +153,9 @@ namespace Arc {
MessageAttributes attrout;
MessageAttributes attrin;
attrout.set("SOAP:ENDPOINT",rurl.str());
if(!otoken.empty())
attrout.set("HTTP:authorization", "bearer "+otoken);
if (!deleg->DelegateCredentialsInit(*entry,&attrout,&attrin,&(client->GetContext()),
(renew_id.empty()?DelegationProviderSOAP::EMIDS:DelegationProviderSOAP::EMIDSRENEW))) {
lfailure = "Failed to initiate delegation credentials";
......@@ -176,7 +201,12 @@ namespace Arc {
std::string action = req.Child(0).Name();
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());
lfailure = "Failed processing request";
delete client; client = NULL;
......
......@@ -329,6 +329,8 @@ namespace Arc {
const MCCConfig cfg;
std::string otoken;
int timeout;
std::string lfailure;
......
......@@ -14,6 +14,7 @@ libaccEMIES_la_SOURCES = EMIESClient.cpp EMIESClient.h \
libaccEMIES_la_CXXFLAGS = -I$(top_srcdir)/include \
$(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS) $(AM_CXXFLAGS)
libaccEMIES_la_LIBADD = \
$(top_builddir)/src/hed/libs/otokens/libarcotokens.la \
$(top_builddir)/src/hed/libs/delegation/libarcdelegation.la \
$(top_builddir)/src/hed/libs/compute/libarccompute.la \
$(top_builddir)/src/hed/libs/communication/libarccommunication.la \
......@@ -31,6 +32,7 @@ libaccEMIES_la_LDFLAGS = -no-undefined -avoid-version -module
arcemiestest_SOURCES = TestEMIESClient.cpp EMIESClient.cpp JobStateEMIES.cpp
arcemiestest_CXXFLAGS = -I$(top_srcdir)/include $(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS)
arcemiestest_LDADD = \
$(top_builddir)/src/hed/libs/otokens/libarcotokens.la \
$(top_builddir)/src/hed/libs/delegation/libarcdelegation.la \
$(top_builddir)/src/hed/libs/communication/libarccommunication.la \
$(top_builddir)/src/hed/libs/compute/libarccompute.la \
......
......@@ -15,9 +15,9 @@ SUBDIRS = common loader message crypto cryptomod \
credential credentialmod data security \
ws-addressing $(XMLSEC_DIR) ws-security delegation \
communication compute infosys $(GLOBUSUTILS_DIR) \
credentialstore scitokens
credentialstore otokens
DIST_SUBDIRS = common loader message crypto cryptomod \
credential credentialmod data security \
ws-addressing xmlsec ws-security delegation \
communication compute infosys globusutils \
credentialstore scitokens
credentialstore otokens
......@@ -18,15 +18,15 @@ namespace Arc {
// Implemented according to RFC4648, MSB first approach and assuming ASCII codes.
// 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);
in -= 26;
if(((unsigned char)in) < (unsigned char)26) return ('a' + in);
in -= 26;
if(((unsigned char)in) < (unsigned char)10) return ('0' + in);
in -= 10;
if(in == (char)0) return '+';
if(in == (char)1) return '/';
if(in == (char)0) return urlSafe ? '-' : '+';
if(in == (char)1) return urlSafe ? '_' : '/';
return '?';
}
......@@ -46,19 +46,19 @@ namespace Arc {
static int base64_quantum_encode(const char in[3], int size, char out[4], bool urlSafe) {
if(size == 3) {
out[0] = base64_character_encode((in[0]>>2) & 0x3f);
out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f));
out[2] = base64_character_encode(((in[1]<<2) & 0x3c) | ((in[2]>>6) & 0x03));
out[3] = base64_character_encode(in[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), urlSafe);
out[2] = base64_character_encode(((in[1]<<2) & 0x3c) | ((in[2]>>6) & 0x03), urlSafe);
out[3] = base64_character_encode(in[2] & 0x3f, urlSafe);
} else if(size == 2) {
out[0] = base64_character_encode((in[0]>>2) & 0x3f);
out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f));
out[2] = base64_character_encode((in[1]<<2) & 0x3c);
out[0] = base64_character_encode((in[0]>>2) & 0x3f, urlSafe);
out[1] = base64_character_encode(((in[0]<<4) & 0x30) | ((in[1]>>4) & 0x0f), urlSafe);
out[2] = base64_character_encode((in[1]<<2) & 0x3c, urlSafe);
out[3] = '=';
if(urlSafe) return 3;
} else if(size == 1) {
out[0] = base64_character_encode((in[0]>>2) & 0x3f);
out[1] = base64_character_encode((in[0]<<4) & 0x30);
out[0] = base64_character_encode((in[0]>>2) & 0x3f, urlSafe);
out[1] = base64_character_encode((in[0]<<4) & 0x30, urlSafe);
out[2] = '=';
out[3] = '=';
if(urlSafe) return 2;
......
......@@ -95,9 +95,19 @@ namespace Arc {
private:
T *object;
void (*deleter)(T*);
void operator=(const AutoPointer<T>&);
AutoPointer(const AutoPointer&);
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:
/// NULL pointer constructor
AutoPointer(void (*d)(T*) = &DefaultDeleter)
......@@ -105,13 +115,24 @@ namespace Arc {
/// Constructor which wraps pointer and optionally defines deletion function
AutoPointer(T *o, void (*d)(T*) = &DefaultDeleter)
: object(o), deleter(d) {}
/// Moving constructor
AutoPointer(AutoPointer<T>& o)
: object(o.Release()), deleter(o.deleter) {}
/// Destructor destroys wrapped object using assigned deleter
~AutoPointer(void) {
if (object) if(deleter) (*deleter)(object);
object = NULL;
}
void operator=(T* o) {
AutoPointer<T>& operator=(T* o) {
if (object) if(deleter) (*deleter)(object);
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
T& operator*(void) const {
......@@ -254,4 +275,4 @@ namespace Arc {
} // namespace Arc
# endif // __ARC_UTILS_H__
#endif // __ARC_UTILS_H__
......@@ -77,8 +77,8 @@ namespace Arc {
const char *id) {
XMLNode comp = chain["Component"];
for (; (bool)comp; ++comp)
if ((comp.Attribute("name") == name) &&
(comp.Attribute("id") == id))
if ((!name || (comp.Attribute("name") == name)) &&
(!id || (comp.Attribute("id") == id)))
return comp;
return XMLNode();
}
......@@ -397,6 +397,12 @@ namespace Arc {
comp.NewAttribute("entry") = "http";
comp.NewChild("Method") = "POST"; // 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() {}
......@@ -476,6 +482,16 @@ namespace Arc {
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,
const std::string& path,
std::multimap<std::string, std::string>& attributes,
......@@ -525,12 +541,8 @@ namespace Arc {
reqmsg.Attributes()->set("HTTP:Range", "bytes=" +
tostring(range_start) + "-");
}
std::map<std::string, std::string>::iterator it;
for (it = attributes.begin(); it != attributes.end(); it++) {
std::string key("HTTP:");
key.append((*it).first);
reqmsg.Attributes()->add(key, (*it).second);
}
HTTPAttributesToMessage(attributes, reqmsg);
r = http_entry->process(reqmsg, repmsg);
if(!r) {
if (repmsg.Payload() != NULL) delete repmsg.Payload();
......@@ -705,6 +717,12 @@ namespace Arc {
MCC_Status ClientSOAP::process(PayloadSOAP *request,
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;
MCC_Status r;
if(!(r=Load())) return r;
......@@ -718,6 +736,7 @@ namespace Arc {
reqmsg.Payload(request);
repmsg.Attributes(&attributes_rep);
repmsg.Context(&context);
HTTPAttributesToMessage(http_attr, reqmsg);
r = soap_entry->process(reqmsg, repmsg);
if (repmsg.Payload() != NULL) {
try {
......@@ -733,6 +752,13 @@ namespace Arc {
MCC_Status ClientSOAP::process(const std::string& action,
PayloadSOAP *request,
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;
MCC_Status r;
if(!(r=Load())) return r;
......@@ -747,6 +773,7 @@ namespace Arc {
repmsg.Attributes(&attributes_rep);
repmsg.Context(&context);
attributes_req.set("SOAP:ACTION", action);
HTTPAttributesToMessage(http_attr, reqmsg);
r = soap_entry->process(reqmsg, repmsg);
if (repmsg.Payload() != NULL) {
try {
......
......@@ -114,7 +114,7 @@ namespace Arc {
return tls_entry ? tls_entry : tcp_entry;
}
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:
MCC *tcp_entry;
MCC *tls_entry;
......@@ -215,7 +215,7 @@ namespace Arc {
MCC* GetEntry() {
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();
void RelativeURI(bool val) { relative_uri=val; };
const URL& GetURL() const { return default_url; };
......@@ -246,16 +246,21 @@ namespace Arc {
virtual ~ClientSOAP();
/** Send SOAP request and receive response. */
MCC_Status process(PayloadSOAP *request, PayloadSOAP **response);
/** Send SOAP request + additional HTTP header attributes and receive response. */
MCC_Status process(const std::multimap<std::string, std::string> &http_attr, PayloadSOAP *request, PayloadSOAP **response);
/** Send SOAP request with specified SOAP action and receive response. */
MCC_Status process(const std::string& action, PayloadSOAP *request,
PayloadSOAP **response);
/** Send SOAP request with specified SOAP action + additional HTTP header attributes and receive response. */
MCC_Status process(const std::multimap<std::string, std::string> &http_attr, const std::string& action, PayloadSOAP *request,
PayloadSOAP **response);
/** Returns entry point to SOAP MCC in configured chain.
To initialize entry point Load() method must be called. */
MCC* GetEntry() {
return soap_entry;
}
/** Adds security handler to configuration of SOAP MCC */
void AddSecHandler(XMLNode handlercfg, const std::string& libanme = "", const std::string& libpath = "");
void AddSecHandler(XMLNode handlercfg, const std::string& libname = "", const std::string& libpath = "");
/** Instantiates pluggable elements according to generated configuration */
virtual MCC_Status Load();
protected:
......
#DIST_SUBDIRS = test
#SUBDIRS = $(TEST_DIR)
lib_LTLIBRARIES = libarcotokens.la
pgmpkglibdir = $(pkglibdir)
pgmpkglib_PROGRAMS =
libarcotokens_ladir = $(pkgincludedir)
libarcotokens_la_HEADERS = otokens.h openid_metadata.h
libarcotokens_la_SOURCES = jwse.cpp jwse_hmac.cpp jwse_ecdsa.cpp jwse_rsassapkcs1.cpp jwse_rsassapss.cpp jwse_keys.cpp openid_metadata.cpp jwse_private.h
libarcotokens_la_CXXFLAGS = -I$(top_srcdir)/include $(OPENSSL_CFLAGS) $(LIBXML2_CFLAGS) $(GLIBMM_CFLAGS) $(AM_CXXFLAGS)
libarcotokens_la_LIBADD = \
$(top_builddir)/src/external/cJSON/libcjson.la \
$(top_builddir)/src/hed/libs/common/libarccommon.la \
$(top_builddir)/src/hed/libs/message/libarcmessage.la \
$(top_builddir)/src/hed/libs/crypto/libarccrypto.la \
$(top_builddir)/src/hed/libs/communication/libarccommunication.la \
$(OPENSSL_LIBS) $(GLIBMM_LIBS) $(LIBINTL)
libarcotokens_la_LDFLAGS = -version-info 3:0:0
This diff is collapsed.
......@@ -6,7 +6,8 @@
#include <arc/external/cJSON/cJSON.h>
#include <openssl/evp.h>
#include "jwse.h"
#include "otokens.h"
#include "jwse_private.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define EVP_MD_CTX_new EVP_MD_CTX_create
......@@ -19,13 +20,12 @@ namespace Arc {
bool JWSE::VerifyECDSA(char const* digestName, void const* message, unsigned int messageSize,
void const* signature, unsigned int signatureSize) {
AutoPointer<EVP_PKEY> pkey(GetPublicKey(), &EVP_PKEY_free);
if(!pkey) return false;
if(!key_) return false;
AutoPointer<EVP_MD_CTX> ctx(EVP_MD_CTX_new(),&EVP_MD_CTX_free);
if(!ctx) return false;
const EVP_MD* md = EVP_get_digestbyname(digestName);
if(!md) return false;
int rc = EVP_DigestVerifyInit(ctx.Ptr(), NULL, md, NULL, pkey.Ptr());
int rc = EVP_DigestVerifyInit(ctx.Ptr(), NULL, md, NULL, const_cast<EVP_PKEY*>(key_->PublicKey()));
if(rc != 1) return false;
rc = EVP_DigestVerifyUpdate(ctx.Ptr(), message, messageSize);
if(rc != 1) return false;
......@@ -35,4 +35,23 @@ namespace Arc {
return true;
}
bool JWSE::SignECDSA(char const* digestName, void const* message, unsigned int messageSize, std::string& signature) const {
if(!key_) return false;
AutoPointer<EVP_MD_CTX> ctx(EVP_MD_CTX_new(),&EVP_MD_CTX_free);
if(!ctx) return false;
const EVP_MD* md = EVP_get_digestbyname(digestName);
if(!md) return false;
int rc = EVP_DigestSignInit(ctx.Ptr(), NULL, md, NULL, const_cast<EVP_PKEY*>(key_->PrivateKey()));
if(rc != 1) return false;
rc = EVP_DigestSignUpdate(ctx.Ptr(), message, messageSize);
if(rc != 1) return false;
size_t signatureSize = 0;
rc = EVP_DigestSignFinal(ctx.Ptr(), NULL, &signatureSize);
if((rc != 1) || (signatureSize <= 0)) return false;
signature.resize(signatureSize);
rc = EVP_DigestSignFinal(ctx.Ptr(), const_cast<unsigned char*>(reinterpret_cast<unsigned char const*>(signature.c_str())), &signatureSize);
if((rc != 1) || (signatureSize <= 0)) return false;
return true;
}
} // namespace Arc
......@@ -6,7 +6,8 @@
#include <arc/external/cJSON/cJSON.h>
#include <openssl/evp.h>
#include "jwse.h"
#include "otokens.h"
#include "jwse_private.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define EVP_MD_CTX_new EVP_MD_CTX_create
......@@ -37,7 +38,7 @@ namespace Arc {
return false;
}
rc = 0;
for(int n = 0; n < signatureSize; ++n) rc |= (reinterpret_cast<unsigned char const*>(signature))[n] ^ buffer.Ptr()[n];
for(unsigned int n = 0; n < signatureSize; ++n) rc |= (reinterpret_cast<unsigned char const*>(signature))[n] ^ buffer.Ptr()[n];
std::memset(buffer.Ptr(), 0, signatureSize);
if(rc != 1) return false;
return true;
......
This diff is collapsed.
#include <openssl/x509.h>
#include <arc/URL.h>
#include <arc/communication/ClientInterface.h>
namespace Arc {
class JWSEKeyHolder {
public:
JWSEKeyHolder();
JWSEKeyHolder(char const* certificate);
~JWSEKeyHolder();
operator bool() const;
bool operator!() const;
char const* Id() const;
void Id(char const* keyId);