-rw-r--r-- | lib/util.cc | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/lib/util.cc b/lib/util.cc index a9b9bed..54d6535 100644 --- a/lib/util.cc +++ b/lib/util.cc @@ -1,29 +1,35 @@ #include <errno.h> #include <cassert> #include <cctype> #include <cstring> #include <vector> #include <string> #include <stack> #include <openssl/bio.h> #include <openssl/evp.h> +#include <openssl/hmac.h> #include <curl/curl.h> #include "opkele/util.h" #include "opkele/exception.h" +#include <config.h> +#ifdef HAVE_DEMANGLE +# include <cxxabi.h> +#endif + namespace opkele { using namespace std; namespace util { /* * base64 */ string encode_base64(const void *data,size_t length) { BIO *b64 = 0, *bmem = 0; try { b64 = BIO_new(BIO_f_base64()); if(!b64) throw exception_openssl(OPKELE_CP_ "failed to BIO_new() base64 encoder"); BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); bmem = BIO_new(BIO_s_mem()); @@ -192,34 +198,33 @@ namespace opkele { if(colon==string::npos) throw bad_input(OPKELE_CP_ "No scheme specified in URI"); transform( uri.begin()+ns, uri.begin()+colon+1, back_inserter(rv), ::tolower ); bool s; string::size_type ul = uri.find_last_not_of(whitespace)+1; if(ul <= (colon+3)) throw bad_input(OPKELE_CP_ "Unexpected end of URI being normalized encountered"); if(uri[colon+1]!='/' || uri[colon+2]!='/') throw bad_input(OPKELE_CP_ "Unexpected input in URI being normalized after scheme component"); if(rv=="http:") s = false; else if(rv=="https:") s = true; else{ - /* TODO: support more schemes. - * e.g. xri. How do we normalize + /* TODO: support more schemes. e.g. xri. How do we normalize * xri? */ rv.append(uri,colon+1,ul-colon-1); return rv; } rv += "//"; string::size_type interesting = uri.find_first_of(":/#?",colon+3); if(interesting==string::npos) { transform( uri.begin()+colon+3,uri.begin()+ul, back_inserter(rv), ::tolower ); rv += '/'; return rv; } transform( uri.begin()+colon+3,uri.begin()+interesting, back_inserter(rv), ::tolower ); @@ -298,19 +303,81 @@ namespace opkele { if(pseg.empty()) rv += c; qf = true; } pseg.clear(); }else{ pseg += c; } } if(!pseg.empty()) { if(!qf) rv += '/'; rv += pseg; } return rv; } + string& strip_uri_fragment_part(string& u) { + string::size_type q = u.find('?'), f = u.find('#'); + if(q==string::npos) { + if(f!=string::npos) + u.erase(f); + }else{ + if(f!=string::npos) { + if(f<q) + u.erase(f,q-f); + else + u.erase(f); + } + } + return u; + } + + string abi_demangle(const char *mn) { +#ifndef HAVE_DEMANGLE + return mn; +#else /* !HAVE_DEMANGLE */ + int dstat; + char *demangled = abi::__cxa_demangle(mn,0,0,&dstat); + if(dstat) + return mn; + string rv = demangled; + free(demangled); + return rv; +#endif /* !HAVE_DEMANGLE */ + } + + string base64_signature(const assoc_t& assoc,const basic_openid_message& om) { + const string& slist = om.get_field("signed"); + string kv; + string::size_type p=0; + while(true) { + string::size_type co = slist.find(',',p); + string f = (co==string::npos) + ?slist.substr(p):slist.substr(p,co-p); + kv += f; + kv += ':'; + kv += om.get_field(f); + kv += '\n'; + if(co==string::npos) break; + p = co+1; + } + const secret_t& secret = assoc->secret(); + const EVP_MD *evpmd; + const string& at = assoc->assoc_type(); + if(at=="HMAC-SHA256") + evpmd = EVP_sha256(); + else if(at=="HMAC-SHA1") + evpmd = EVP_sha1(); + else + throw unsupported(OPKELE_CP_ "unknown association type"); + unsigned int md_len = 0; + unsigned char *md = HMAC(evpmd, + &(secret.front()),secret.size(), + (const unsigned char*)kv.data(),kv.length(), + 0,&md_len); + return encode_base64(md,md_len); + } + } } |