-rw-r--r-- | include/opkele/.gitignore | 2 | ||||
-rw-r--r-- | include/opkele/acconfig.h.in | 3 | ||||
-rw-r--r-- | include/opkele/association.h | 89 | ||||
-rw-r--r-- | include/opkele/consumer.h | 135 | ||||
-rw-r--r-- | include/opkele/data.h | 12 | ||||
-rw-r--r-- | include/opkele/exception.h | 206 | ||||
-rw-r--r-- | include/opkele/opkele-config.h | 6 | ||||
-rw-r--r-- | include/opkele/server.h | 95 | ||||
-rw-r--r-- | include/opkele/types.h | 168 | ||||
-rw-r--r-- | include/opkele/util.h | 60 |
10 files changed, 776 insertions, 0 deletions
diff --git a/include/opkele/.gitignore b/include/opkele/.gitignore new file mode 100644 index 0000000..ffa24dc --- a/dev/null +++ b/include/opkele/.gitignore @@ -0,0 +1,2 @@ +acconfig.h +stamp-h2 diff --git a/include/opkele/acconfig.h.in b/include/opkele/acconfig.h.in new file mode 100644 index 0000000..d56a1cd --- a/dev/null +++ b/include/opkele/acconfig.h.in @@ -0,0 +1,3 @@ + +/* defined in presence of konforka library */ +#undef OPKELE_HAVE_KONFORKA diff --git a/include/opkele/association.h b/include/opkele/association.h new file mode 100644 index 0000000..5eb1cc3 --- a/dev/null +++ b/include/opkele/association.h @@ -0,0 +1,89 @@ +#ifndef __OPKELE_ASSOCIATION_H +#define __OPKELE_ASSOCIATION_H + +#include <time.h> +#include <opkele/types.h> + +/** + * @file + * @brief reference implementation of association_t + */ + +/** + * @brief the main opkele namespace + */ +namespace opkele { + + /** + * reference implementation of association_t class. + */ + class association : public association_t { + public: + /** + * OpenID server name + */ + string _server; + /** + * association handle + */ + string _handle; + /** + * association type + */ + string _assoc_type; + /** + * the secret + */ + secret_t _secret; + /** + * expiration time + */ + time_t _expires; + /** + * statelessness of the assoc_handle + */ + bool _stateless; + + /** + * @param __server the server name + * @param __handle association handle + * @param __assoc_type association type + * @param __secret the secret + * @param __expires expiration time + * @param __stateless statelessness of the assoc_handle + */ + association(const string& __server, const string& __handle, + const string& __assoc_type, const secret_t& __secret, + time_t __expires, bool __stateless) + : _server(__server), _handle(__handle), _assoc_type(__assoc_type), + _secret(__secret), _expires(__expires), _stateless(__stateless) { } + + /** + * @overload association_t::server() + */ + virtual string server() const { return _server; } + /** + * @overload association_t::handle() + */ + virtual string handle() const { return _handle; } + /** + * @overload association_t::assoc_type() + */ + virtual string assoc_type() const { return _assoc_type; } + /** + * @overload association_t::secret() + */ + virtual secret_t secret() const { return _secret; } + /** + * @overload association_t::expires_in() + */ + virtual int expires_in() const { return _expires-time(0); } + /** + * @overload associationn_t::stateless() + */ + virtual bool stateless() const { return _stateless; } + }; + +} + +#endif /* __OPKELE_ASSOCIATION_H */ diff --git a/include/opkele/consumer.h b/include/opkele/consumer.h new file mode 100644 index 0000000..b9c29bd --- a/dev/null +++ b/include/opkele/consumer.h @@ -0,0 +1,135 @@ +#ifndef __OPKELE_CONSUMER_H +#define __OPKELE_CONSUMER_H + +#include <opkele/types.h> + +/** + * @file + * @brief OpenID consumer-side functionality + */ + +/** + * @brief the main opkele namespace + */ +namespace opkele { + + /** + * implementation of basic consumer functionality + */ + class consumer_t { + public: + + /** + * store association. The function should be overridden in the real + * implementation to provide persistent associations store. + * @param server the OpenID server + * @param handle association handle + * @param secret the secret associated with the server and handle + * @param expires_in the number of seconds until the handle is expired + * @return the auto_ptr<> for the newly allocated association_t object + */ + virtual assoc_t store_assoc(const string& server,const string& handle,const secret_t& secret,int expires_in) = 0; + /** + * retrieve stored association. The function should be overridden + * in the real implementation to provide persistent assocations + * store. + * @param server the OpenID server + * @param handle association handle + * @return the autho_ptr<> for the newly allocated association_t object + * @throw failed_lookup in case of error + */ + virtual assoc_t retrieve_assoc(const string& server,const string& handle) = 0; + /** + * invalidate stored association. The function should be overridden + * in the real implementation of the consumer. + * @param server the OpenID server + * @param handle association handle + */ + virtual void invalidate_assoc(const string& server,const string& handle) = 0; + /** + * retrieve any unexpired association for the server. If the + * function is not overridden in the real implementation, the new + * association will be established for each request. + * @param server the OpenID server + * @return the auto_ptr<> for the newly allocated association_t object + * @throw failed_lookup in case of absence of the handle + */ + virtual assoc_t find_assoc(const string& server); + + /** + * retrieve the metainformation contained in link tags from the + * page pointed by url. the function may implement caching of the + * information. + * @param url url to harvest for link tags + * @param server reference to the string object where to put + * openid.server value + * @param delegate reference to the string object where to put the + * openid.delegate value (if any) + */ + virtual void retrieve_links(const string& url,string& server,string& delegate); + + /** + * perform the associate request to OpenID server. + * @param server the OpenID server + * @return the auto_ptr<> for the newly allocated association_t + * object, representing established association + * @throw exception in case of error + */ + assoc_t associate(const string& server); + /** + * prepare the parameters for the checkid_immediate + * request. + * @param identity the identity to verify + * @param return_to the return_to url to pass with the request + * @param trust_root the trust root to advertise with the request + * @return the location string + * @throw exception in case of error + */ + string checkid_immediate(const string& identity,const string& return_to,const string& trust_root=""); + /** + * prepare the parameters for the checkid_setup + * request. + * @param identity the identity to verify + * @param return_to the return_to url to pass with the request + * @param trust_root the trust root to advertise with the request + * @return the location string + * @throw exception in case of error + */ + string checkid_setup(const string& identity,const string& return_to,const string& trust_root=""); + /** + * the actual implementation behind checkid_immediate() and + * checkid_setup() functions. + * @param mode checkid_* mode - either mode_checkid_immediate or mode_checkid_setup + * @param identity the identity to verify + * @param return_to the return_to url to pass with the request + * @param trust_root the trust root to advertise with the request + * @return the location string + * @throw exception in case of error + */ + string checkid_(mode_t mode,const string& identity,const string& return_to,const string& trust_root=""); + /** + * verify the id_res response + * @param pin the response parameters + * @param identity the identity being checked (if not specified, extracted + * from the openid.identity parameter + * @throw id_res_mismatch in case of signature + * mismatch + * @throw id_res_setup in case of + * openid.user_setup_url failure (supposedly + * checkid_immediate only) + * @throw id_res_failed in case of failure + * @throw exception in case of other failures + */ + void id_res(const params_t& pin,const string& identity=""); + /** + * perform a check_authentication request. + * @param server the OpenID server + * @param p request parameters + */ + void check_authentication(const string& server,const params_t& p); + + }; + +} + +#endif /* __OPKELE_CONSUMER_H */ diff --git a/include/opkele/data.h b/include/opkele/data.h new file mode 100644 index 0000000..7fc635b --- a/dev/null +++ b/include/opkele/data.h @@ -0,0 +1,12 @@ +#ifndef __OPKELE_DATA_H +#define __OPKELE_DATA_H + +namespace opkele { + + namespace data { + extern const char *_default_p; + extern const char *_default_g; + } +} + +#endif /* __OPKELE_DATA_H */ diff --git a/include/opkele/exception.h b/include/opkele/exception.h new file mode 100644 index 0000000..2ac0661 --- a/dev/null +++ b/include/opkele/exception.h @@ -0,0 +1,206 @@ +#ifndef __OPKELE_EXCEPTION_H +#define __OPKELE_EXCEPTION_H + +/** + * @file + * @brief opkele exceptions + */ + +#include <curl/curl.h> + +#include <opkele/opkele-config.h> +#ifdef OPKELE_HAVE_KONFORKA +# include <konforka/exception.h> +/** + * the exception parameters declaration + */ +# define OPKELE_E_PARS const string& fi,const string&fu,int l,const string& w +/** + * the exception parameters list to pass to constructor + */ +# define OPKELE_E_CONS_ fi,fu,l, +/** + * the exception codepoint specification + */ +# define OPKELE_CP_ CODEPOINT, +/** + * the simple rethrow of konforka-based exception + */ +# define OPKELE_RETHROW catch(konforka::exception& e) { e.see(CODEPOINT); throw } +#else /* OPKELE_HAVE_KONFORKA */ +# include <stdexcept> +/** + * the exception parameter declaration + */ +# define OPKELE_E_PARS const string& w +/** + * the dummy prefix for exception parameters list to prepend in the absence of + * konforka library + */ +# define OPKELE_E_CONS_ +/** + * the dummy placeholder for konforka exception codepoint specification + */ +# define OPKELE_CP_ +/** + * the dummy define for the konforka-based rethrow of exception + */ +# define OPKELE_RETHROW +#endif /* OPKELE_HAVE_KONFORKA */ +/** + * the exception parameters list to pass to constructor + */ +# define OPKELE_E_CONS OPKELE_E_CONS_ w + +/* + * @brief the main opkele namespace + */ +namespace opkele { + using std::string; + + /** + * the base opkele exception class + */ + class exception : public +# ifdef OPKELE_HAVE_KONFORKA + konforka::exception +# else + std::exception +# endif + { + public: +# ifdef OPKELE_HAVE_KONFORKA + explicit + exception(const string& fi,const string& fu,int l,const string& w) + : konforka::exception(fi,fu,l,w) { } +# else /* OPKELE_HAVE_KONFORKA */ + explicit + exception(const string& w) + : std::exception(w) { } +# endif /* OPKELE_HAVE_KONFORKA */ + }; + + /** + * thrown in case of failed conversion + */ + class failed_conversion : public exception { + public: + failed_conversion(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + /** + * thrown in case of failed lookup (either parameter or persistent store) + */ + class failed_lookup : public exception { + public: + failed_lookup(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + /** + * thrown in case of bad input (either local or network) + */ + class bad_input : public exception { + public: + bad_input(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + + /** + * thrown on failed assertion + */ + class failed_assertion : public exception { + public: + failed_assertion(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + + /** + * thrown if the handle being retrieved is invalid + */ + class invalid_handle : public exception { + public: + invalid_handle(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + /** + * thrown if the handle passed to check_authentication request is not + * stateless + */ + class stateful_handle : public exception { + public: + stateful_handle(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + + /** + * thrown if check_authentication request fails + */ + class failed_check_authentication : public exception { + public: + failed_check_authentication(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + + /** + * thrown if the id_res request result is negative + */ + class id_res_failed : public exception { + public: + id_res_failed(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + /** + * thrown if the user_setup_url is provided with negative response + */ + class id_res_setup : public id_res_failed { + public: + string setup_url; + id_res_setup(OPKELE_E_PARS,const string& su) + : id_res_failed(OPKELE_E_CONS), setup_url(su) { } + ~id_res_setup() throw() { } + }; + /** + * thrown in case of signature mismatch + */ + class id_res_mismatch : public id_res_failed { + public: + id_res_mismatch(OPKELE_E_PARS) + : id_res_failed(OPKELE_E_CONS) { } + }; + + /** + * openssl malfunction occured + */ + class exception_openssl : public exception { + public: + unsigned long _error; + string _ssl_string; + exception_openssl(OPKELE_E_PARS); + ~exception_openssl() throw() { } + }; + + /** + * network operation related error occured + */ + class exception_network : public exception { + public: + exception_network(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + + /** + * network operation related error occured, specifically, related to + * libcurl + */ + class exception_curl : public exception_network { + public: + CURLcode _error; + string _curl_string; + exception_curl(OPKELE_E_PARS); + exception_curl(OPKELE_E_PARS,CURLcode e); + ~exception_curl() throw() { } + }; + +} + +#endif /* __OPKELE_EXCEPTION_H */ diff --git a/include/opkele/opkele-config.h b/include/opkele/opkele-config.h new file mode 100644 index 0000000..70c2d26 --- a/dev/null +++ b/include/opkele/opkele-config.h @@ -0,0 +1,6 @@ +#ifndef __OPKELE_OPKELE_CONFIG_H +#define __OPKELE_OPKELE_CONFIG_H + +#include "opkele/acconfig.h" + +#endif /* __OPKELE_OPKELE_CONFIG_H */ diff --git a/include/opkele/server.h b/include/opkele/server.h new file mode 100644 index 0000000..fe07448 --- a/dev/null +++ b/include/opkele/server.h @@ -0,0 +1,95 @@ +#ifndef __OPKELE_SERVER_H +#define __OPKELE_SERVER_H + +/** + * @file + * @brief OpenID server-side functionality + */ + +#include <opkele/types.h> + +/** + * @brief the main opkele namespace + */ +namespace opkele { + + /** + * implementation of basic server functionality + */ + class server_t { + public: + + /** + * allocate the new association. The function should be overridden + * in the real implementation to provide persistent assocations + * store. + * @param mode the mode of request being processed to base the + * statelessness of the association upon + * @return the auto_ptr<> for the newly allocated association_t object + */ + virtual assoc_t alloc_assoc(mode_t mode) = 0; + /** + * retrieve the association. The function should be overridden in + * the reqal implementation to provide persistent assocations + * store. + * @param h association handle + * @return the auto_ptr<> for the newly allocated association_t object + * @throw failed_lookup in case of failure + */ + virtual assoc_t retrieve_assoc(const string& h) = 0; + + /** + * validate the identity. + * @param assoc association object + * @param pin incoming request parameters + * @param identity being verified + * @param trust_root presented in the request + * @throw exception if identity can not be confirmed + */ + virtual void validate(const association_t& assoc,const params_t& pin,const string& identity,const string& trust_root) = 0; + + + /** + * process the associate request. + * @param pin the incoming request parameters + * @param pout the store for the response parameters + */ + void associate(const params_t& pin,params_t& pout); + /** + * process the checkid_immediate request. + * @param pin the incoming request parameters + * @param return_to reference to the object to store return_to url to + * @param pout the response parameters + * @throw exception in case of errors or negative reply + */ + void checkid_immediate(const params_t& pin,string& return_to,params_t& pout); + /** + * process the checkid_setup request. + * @param pin the incoming request parameters + * @param return_to reference to the object to store return_to url to + * @param pout the response parameters + * @throw exception in case of errors or negative reply + */ + void checkid_setup(const params_t& pin,string& return_to,params_t& pout); + /** + * the actual functionality behind checkid_immediate() and + * checkid_setup() + * @param mode the request being processed (either + * mode_checkid_immediate or mode_checkid_setup) + * @param pin the incoming request parameters + * @param return_to reference to the object to store return_to url to + * @param pout the response parameters + * @throw exception in case of errors or negative reply + */ + void checkid_(mode_t mode,const params_t& pin,string& return_to,params_t& pout); + /** + * process the check_authentication request. + * @param pin incoming request parameters + * @param pout response parameters + */ + void check_authentication(const params_t& pin,params_t& pout); + }; + +} + +#endif /* __OPKELE_SERVER_H */ diff --git a/include/opkele/types.h b/include/opkele/types.h new file mode 100644 index 0000000..ba06776 --- a/dev/null +++ b/include/opkele/types.h @@ -0,0 +1,168 @@ +#ifndef __OPKELE_TYPES_H +#define __OPKELE_TYPES_H + +/** + * @file + * @brief various types declarations + */ + +#include <ostream> +#include <vector> +#include <string> +#include <map> +#include <memory> + +/** + * @brief the main opkele namespace + */ +namespace opkele { + using std::vector; + using std::string; + using std::map; + using std::ostream; + using std::auto_ptr; + + /** + * the OpenID operation mode + */ + typedef enum _mode_t { + mode_associate, + mode_checkid_immediate, + mode_checkid_setup, + mode_check_association + } mode_t; + + /** + * the association secret container + */ + class secret_t : public vector<unsigned char> { + public: + + /** + * xor the secret and hmac together and encode, using base64 + * @param key_sha1 pointer to the sha1 digest + * @param rv reference to the return value + */ + void enxor_to_base64(const unsigned char *key_sha1,string& rv) const; + /** + * decode base64-encoded secret and xor it with the sha1 digest + * @param key_sha1 pointer to the message digest + * @param b64 base64-encoded secret value + */ + void enxor_from_base64(const unsigned char *key_sha1,const string& b64); + /** + * plainly encode to base64 representation + * @param rv reference to the return value + */ + void to_base64(string& rv) const; + /** + * decode cleartext secret from base64 + * @param b64 base64-encoded representation of the secret value + */ + void from_base64(const string& b64); + }; + + /** + * Interface to the association. + */ + class association_t { + public: + + /** + * retrieve the server with which association was established. + * @return server name + */ + virtual string server() const = 0; + /** + * retrieve the association handle. + * @return handle + */ + virtual string handle() const = 0; + /** + * retrieve the association type. + * @return association type + */ + virtual string assoc_type() const = 0; + /** + * retrieve the association secret. + * @return association secret + */ + virtual secret_t secret() const = 0; + /** + * retrieve the number of seconds the association expires in. + * @return seconds till expiration + */ + virtual int expires_in() const = 0; + /** + * check whether the association is stateless. + * @return true if stateless + */ + virtual bool stateless() const = 0; + }; + + /** + * the auto_ptr<> for association_t object type + */ + typedef auto_ptr<association_t> assoc_t; + + /** + * request/response parameters map + */ + class params_t : public map<string,string> { + public: + + /** + * check whether the parameter is present. + * @param n the parameter name + * @return true if yes + */ + bool has_param(const string& n) const; + /** + * retrieve the parameter (const version) + * @param n the parameter name + * @return the parameter value + * @throw failed_lookup if there is no such parameter + */ + const string& get_param(const string& n) const; + /** + * retrieve the parameter. + * @param n the parameter name + * @return the parameter value + * @throw failed_lookup if there is no such parameter + */ + string& get_param(const string& n); + + /** + * parse the OpenID key/value data. + * @param kv the OpenID key/value data + */ + void parse_keyvalues(const string& kv); + /** + * sign the fields. + * @param secret the secret used for signing + * @param sig reference to the string, containing base64-encoded + * result + * @param slist the comma-separated list of fields to sign + * @param prefix the string to prepend to parameter names + */ + void sign(secret_t secret,string& sig,const string& slist,const char *prefix=0) const; + + /** + * append parameters to the URL as a GET-request parameters. + * @param url the base URL + * @param prefix the string to prepend to parameter names + * @return the ready-to-use location + */ + string append_query(const string& url,const char *prefix = "openid.") const; + }; + + /** + * dump the key/value pairs for the parameters to the stream. + * @param o output stream + * @param p the parameters + */ + ostream& operator << (ostream& o,const params_t& p); + +} + +#endif /* __OPKELE_TYPES_H */ diff --git a/include/opkele/util.h b/include/opkele/util.h new file mode 100644 index 0000000..fbbef93 --- a/dev/null +++ b/include/opkele/util.h @@ -0,0 +1,60 @@ +#ifndef __OPKELE_UTIL_H +#define __OPKELE_UTIL_H + +#include <time.h> +#include <string> +#include <openssl/bn.h> +#include <openssl/dh.h> + +namespace opkele { + using std::string; + + namespace util { + + class bignum_t { + public: + BIGNUM *_bn; + + bignum_t() : _bn(0) { } + bignum_t(BIGNUM *bn) : _bn(bn) { } + ~bignum_t() throw() { if(_bn) BN_free(_bn); } + + bignum_t& operator=(BIGNUM *bn) { if(_bn) BN_free(_bn); _bn = bn; return *this; } + + operator const BIGNUM*(void) const { return _bn; } + operator BIGNUM*(void) { return _bn; } + }; + class dh_t { + public: + DH *_dh; + + dh_t() : _dh(0) { } + dh_t(DH *dh) : _dh(dh) { } + ~dh_t() throw() { if(_dh) DH_free(_dh); } + + dh_t& operator=(DH *dh) { if(_dh) DH_free(_dh); _dh = dh; return *this; } + + operator const DH*(void) const { return _dh; } + operator DH*(void) { return _dh; } + + DH* operator->() { return _dh; } + const DH* operator->() const { return _dh; } + }; + + BIGNUM *base64_to_bignum(const string& b64); + BIGNUM *dec_to_bignum(const string& dec); + string bignum_to_base64(const BIGNUM *bn); + + string time_to_w3c(time_t t); + time_t w3c_to_time(const string& w); + + string canonicalize_url(const string& url); + string url_encode(const string& str); + + string long_to_string(long l); + long string_to_long(const string& s); + } + +} + +#endif /* __OPKELE_UTIL_H */ |