-rw-r--r-- | include/Makefile.am | 8 | ||||
-rw-r--r-- | include/opkele/.gitignore | 1 | ||||
-rw-r--r-- | include/opkele/consumer.h | 6 | ||||
-rw-r--r-- | include/opkele/curl.h | 24 | ||||
-rw-r--r-- | include/opkele/debug.h | 17 | ||||
-rw-r--r-- | include/opkele/discovery.h | 40 | ||||
-rw-r--r-- | include/opkele/exception.h | 95 | ||||
-rw-r--r-- | include/opkele/expat.h | 91 | ||||
-rw-r--r-- | include/opkele/server.h | 4 | ||||
-rw-r--r-- | include/opkele/tidy.h | 73 | ||||
-rw-r--r-- | include/opkele/tr1-mem.h.in | 10 | ||||
-rw-r--r-- | include/opkele/types.h | 92 | ||||
-rw-r--r-- | include/opkele/uris.h | 18 |
13 files changed, 456 insertions, 23 deletions
diff --git a/include/Makefile.am b/include/Makefile.am index b31786d..51dcea1 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -5,13 +5,17 @@ nobase_include_HEADERS = \ opkele/association.h \ opkele/exception.h \ opkele/server.h \ opkele/consumer.h \ opkele/extension.h \ opkele/sreg.h \ opkele/extension_chain.h \ opkele/xconsumer.h \ - opkele/xserver.h + opkele/xserver.h \ + opkele/discovery.h \ + opkele/uris.h \ + opkele/tr1-mem.h EXTRA_DIST = \ opkele/data.h \ + opkele/curl.h opkele/expat.h opkele/tidy.h \ opkele/util.h \ - opkele/curl.h + opkele/debug.h diff --git a/include/opkele/.gitignore b/include/opkele/.gitignore index ffa24dc..dfc2d2c 100644 --- a/include/opkele/.gitignore +++ b/include/opkele/.gitignore @@ -1,2 +1,3 @@ acconfig.h +tr1-mem.h stamp-h2 diff --git a/include/opkele/consumer.h b/include/opkele/consumer.h index c463787..3c1d318 100644 --- a/include/opkele/consumer.h +++ b/include/opkele/consumer.h @@ -26,17 +26,17 @@ namespace opkele { /** * 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 + * @return the assoc_t 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. * * @note @@ -68,17 +68,17 @@ namespace opkele { * association. * * @note * It may be a good idea to pre-expire associations shortly before * their time is really up to avoid association expiry in the * middle of negotiations. * * @param server the OpenID server - * @return the auto_ptr<> for the newly allocated association_t object + * @return the assoc_t 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. @@ -88,17 +88,17 @@ namespace opkele { * @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 + * @return the assoc_t 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 diff --git a/include/opkele/curl.h b/include/opkele/curl.h index 8020b63..5cf8e48 100644 --- a/include/opkele/curl.h +++ b/include/opkele/curl.h @@ -1,15 +1,19 @@ #ifndef __OPKELE_CURL_H #define __OPKELE_CURL_H #include <cassert> +#include <string> +#include <algorithm> #include <curl/curl.h> namespace opkele { + using std::min; + using std::string; namespace util { class curl_t { public: CURL *_c; curl_t() : _c(0) { } @@ -36,13 +40,33 @@ namespace opkele { virtual int progress(double /* dlt */,double /* dln*/ ,double /* ult */,double /* uln */) { return 0; } CURLcode set_progress(); virtual size_t header(void* /* p */,size_t s,size_t nm) { return s*nm; } CURLcode set_header(); }; + template<int lim> + class curl_fetch_string_t : public curl_t { + public: + curl_fetch_string_t(CURL *c) + : curl_t(c) { } + ~curl_fetch_string_t() throw() { } + + string response; + + size_t write(void *p,size_t size,size_t nmemb) { + size_t bytes = size*nmemb; + size_t get = min(lim-response.length(),bytes); + response.append((const char *)p,get); + return get; + } + }; + + typedef curl_fetch_string_t<16384> curl_pick_t; + + } } #endif /* __OPKELE_CURL_H */ diff --git a/include/opkele/debug.h b/include/opkele/debug.h new file mode 100644 index 0000000..a02f8d4 --- a/dev/null +++ b/include/opkele/debug.h @@ -0,0 +1,17 @@ +#ifndef __OPKELE_DEBUG_H +#define __OPKELE_DEBUG_H + +#ifdef NDEBUG + +#define D_(x) ((void)0) +#define DOUT_(x) ((void)0) + +#else /* NDEBUG */ + +#define D_(x) x +#include <iostream> +#define DOUT_(x) std::clog << x << std::endl + +#endif /* NDEBUG */ + +#endif /* __OPKELE_DEBUG_H */ diff --git a/include/opkele/discovery.h b/include/opkele/discovery.h new file mode 100644 index 0000000..af4aa29 --- a/dev/null +++ b/include/opkele/discovery.h @@ -0,0 +1,40 @@ +#ifndef __OPKELE_DISCOVERY_H +#define __OPKELE_DISCOVERY_H + +#include <string> +#include <opkele/types.h> + +namespace opkele { + using std::string; + + struct idiscovery_t; + + void idiscover(idiscovery_t& result,const string& identity); + + struct idiscovery_t { + bool xri_identity; + string normalized_id; + string canonicalized_id; + xrd::XRD_t xrd; + + idiscovery_t() { } + idiscovery_t(const string& i) { + idiscover(*this,i); + } + idiscovery_t(const char *i) { + idiscover(*this,i); + } + + void clear() { + normalized_id.clear(); canonicalized_id.clear(); + xrd.clear(); + } + + idiscovery_t& operator=(const string& i) { + idiscover(*this,i); return *this; } + idiscovery_t& operator=(const char *i) { + idiscover(*this,i); return *this; } + }; +} + +#endif /* __OPKELE_DISCOVERY_H */ diff --git a/include/opkele/exception.h b/include/opkele/exception.h index 2ff44b7..a8c3339 100644 --- a/include/opkele/exception.h +++ b/include/opkele/exception.h @@ -19,19 +19,23 @@ * the exception parameters list to pass to constructor */ # define OPKELE_E_CONS_ fi,fu,l, /** * the exception codepoint specification */ # define OPKELE_CP_ CODEPOINT, /** + * open function-try-block + */ +# define OPKELE_FUNC_TRY try +/** * the simple rethrow of konforka-based exception */ -# define OPKELE_RETHROW catch(konforka::exception& e) { e.see(CODEPOINT); throw } +# define OPKELE_RETHROW catch(konforka::exception& e) { e.see(CODEPOINT); throw; } #else /* OPKELE_HAVE_KONFORKA */ # include <exception> # include <string> /** * the exception parameter declaration */ # define OPKELE_E_PARS const string& w /** @@ -39,16 +43,20 @@ * konforka library */ # define OPKELE_E_CONS_ /** * the dummy placeholder for konforka exception codepoint specification */ # define OPKELE_CP_ /** + * the dummy define for the opening function-try-block + */ +# define OPKELE_FUNC_TRY +/** * 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 @@ -64,23 +72,20 @@ namespace opkele { 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) { } + exception(const string& fi,const string& fu,int l,const string& w); # else /* OPKELE_HAVE_KONFORKA */ string _what; - explicit - exception(const string& w) - : _what(w) { } + explicit exception(const string& w); virtual ~exception() throw(); virtual const char * what() const throw(); # endif /* OPKELE_HAVE_KONFORKA */ }; /** * thrown in case of failed conversion */ @@ -151,17 +156,17 @@ namespace opkele { : 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_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: @@ -174,16 +179,52 @@ namespace opkele { */ class id_res_expired_on_delivery : public id_res_failed { public: id_res_expired_on_delivery(OPKELE_E_PARS) : id_res_failed(OPKELE_E_CONS) { } }; /** + * thown when the user cancelled authentication process. + */ + class id_res_cancel : public id_res_failed { + public: + id_res_cancel(OPKELE_E_PARS) + : id_res_failed(OPKELE_E_CONS) { } + }; + + /** + * thrown in case of nonce reuse or otherwise imperfect nonce. + */ + class id_res_bad_nonce : public id_res_failed { + public: + id_res_bad_nonce(OPKELE_E_PARS) + : id_res_failed(OPKELE_E_CONS) { } + }; + + /** + * thrown if return_to didn't pass verification + */ + class id_res_bad_return_to : public id_res_failed { + public: + id_res_bad_return_to(OPKELE_E_PARS) + : id_res_failed(OPKELE_E_CONS) { } + }; + + /** + * thrown if OP isn't authorized to make an assertion + */ + class id_res_unauthorized : public id_res_failed { + public: + id_res_unauthorized(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() { } @@ -207,16 +248,46 @@ namespace opkele { CURLcode _error; string _curl_string; exception_curl(OPKELE_E_PARS); exception_curl(OPKELE_E_PARS,CURLcode e); ~exception_curl() throw() { } }; /** + * htmltidy related error occured + */ + class exception_tidy : public exception { + public: + int _rc; + exception_tidy(OPKELE_E_PARS); + exception_tidy(OPKELE_E_PARS,int r); + ~exception_tidy() throw() { } + }; + + /** + * exception thrown in case of failed discovery + */ + class failed_discovery : public exception { + public: + failed_discovery(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + + /** + * unsuccessfull xri resolution + */ + class failed_xri_resolution : public failed_discovery { + public: + long _code; + failed_xri_resolution(OPKELE_E_PARS,long _c=-1) + : failed_discovery(OPKELE_E_CONS), _code(_c) { } + }; + + /** * not implemented (think pure virtual) member function executed, signfies * programmer error */ class not_implemented : public exception { public: not_implemented(OPKELE_E_PARS) : exception(OPKELE_E_CONS) { } }; @@ -225,11 +296,21 @@ namespace opkele { * internal error, indicates internal libopkele problem */ class internal_error : public exception { public: internal_error(OPKELE_E_PARS) : exception(OPKELE_E_CONS) { } }; + /** + * thrown in case of unsupported parameter encountered (e.g. unsupported + * association type). + */ + class unsupported : public exception { + public: + unsupported(OPKELE_E_PARS) + : exception(OPKELE_E_CONS) { } + }; + } #endif /* __OPKELE_EXCEPTION_H */ diff --git a/include/opkele/expat.h b/include/opkele/expat.h new file mode 100644 index 0000000..60c41ac --- a/dev/null +++ b/include/opkele/expat.h @@ -0,0 +1,91 @@ +#ifndef __OPKELE_EXPAT_H +#define __OPKELE_EXPAT_H + +#include <cassert> +#include <expat.h> + +namespace opkele { + + namespace util { + + class expat_t { + public: + XML_Parser _x; + + expat_t() : _x(0) { } + expat_t(XML_Parser x) : _x(x) { } + virtual ~expat_t() throw(); + + expat_t& operator=(XML_Parser x); + + operator const XML_Parser(void) const { return _x; } + operator XML_Parser(void) { return _x; } + + inline bool parse(const char *s,int len,bool final=false) { + assert(_x); + return XML_Parse(_x,s,len,final); + } + + virtual void start_element(const XML_Char *n,const XML_Char **a) { } + virtual void end_element(const XML_Char *n) { } + void set_element_handler(); + + virtual void character_data(const XML_Char *s,int l) { } + void set_character_data_handler(); + + virtual void processing_instruction(const XML_Char *t,const XML_Char *d) { } + void set_processing_instruction_handler(); + + virtual void comment(const XML_Char *d) { } + void set_comment_handler(); + + virtual void start_cdata_section() { } + virtual void end_cdata_section() { } + void set_cdata_section_handler(); + + virtual void default_handler(const XML_Char *s,int l) { } + void set_default_handler(); + void set_default_handler_expand(); + + virtual void start_namespace_decl(const XML_Char *p,const XML_Char *u) { } + virtual void end_namespace_decl(const XML_Char *p) { } + void set_namespace_decl_handler(); + + inline enum XML_Error get_error_code() { + assert(_x); return XML_GetErrorCode(_x); } + static inline const XML_LChar *error_string(XML_Error c) { + return XML_ErrorString(c); } + + inline long get_current_byte_index() { + assert(_x); return XML_GetCurrentByteIndex(_x); } + inline int get_current_line_number() { + assert(_x); return XML_GetCurrentLineNumber(_x); } + inline int get_current_column_number() { + assert(_x); return XML_GetCurrentColumnNumber(_x); } + + inline void set_user_data() { + assert(_x); XML_SetUserData(_x,this); } + + inline bool set_base(const XML_Char *b) { + assert(_x); return XML_SetBase(_x,b); } + inline const XML_Char *get_base() { + assert(_x); return XML_GetBase(_x); } + + inline int get_specified_attribute_count() { + assert(_x); return XML_GetSpecifiedAttributeCount(_x); } + + inline bool set_param_entity_parsing(enum XML_ParamEntityParsing c) { + assert(_x); return XML_SetParamEntityParsing(_x,c); } + + inline static XML_Parser parser_create(const XML_Char *e=0) { + return XML_ParserCreate(e); } + inline static XML_Parser parser_create_ns(const XML_Char *e=0,XML_Char s='\t') { + return XML_ParserCreateNS(e,s); } + + }; + + } + +} + +#endif /* __OPKELE_EXPAT_H */ diff --git a/include/opkele/server.h b/include/opkele/server.h index dd7fc41..3c25646 100644 --- a/include/opkele/server.h +++ b/include/opkele/server.h @@ -20,25 +20,25 @@ namespace opkele { virtual ~server_t() { } /** * 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 + * @return the assoc_t 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 + * @return the assoc_t 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 diff --git a/include/opkele/tidy.h b/include/opkele/tidy.h new file mode 100644 index 0000000..888e7d4 --- a/dev/null +++ b/include/opkele/tidy.h @@ -0,0 +1,73 @@ +#ifndef __OPKELE_TIDY_H +#define __OPKELE_TIDY_H + +#include <cassert> +#include <tidy.h> +#include <buffio.h> + +namespace opkele { + namespace util { + + class tidy_buf_t { + public: + TidyBuffer _x; + + tidy_buf_t() { tidyBufInit(&_x); } + virtual ~tidy_buf_t() throw() { + tidyBufFree(&_x); } + + inline operator const TidyBuffer&(void) const { return _x; } + inline operator TidyBuffer&(void) { return _x; } + + inline operator const char*(void) const { return (const char*)_x.bp; } + inline operator char*(void) { return (char*)_x.bp; } + + inline const char *c_str() const { + return (const char*)_x.bp; } + inline size_t size() const { + return _x.size; } + }; + + class tidy_doc_t { + public: + TidyDoc _x; + + tidy_doc_t() : _x(0) { } + tidy_doc_t(TidyDoc x) : _x(x) { } + virtual ~tidy_doc_t() throw() { + if(_x) tidyRelease(_x); } + + tidy_doc_t& operator=(TidyDoc x) { + if(_x) tidyRelease(_x); + _x = x; + return *this; + } + + operator const TidyDoc(void) const { return _x; } + operator TidyDoc(void) { return _x; } + + inline bool opt_set(TidyOptionId o,bool v) { + assert(_x); + return tidyOptSetBool(_x,o,v?yes:no); } + inline bool opt_set(TidyOptionId o,int v) { + assert(_x); + return tidyOptSetInt(_x,o,v); } + + inline int parse_string(const string& s) { + assert(_x); + return tidyParseString(_x,s.c_str()); } + inline int clean_and_repair() { + assert(_x); + return tidyCleanAndRepair(_x); } + inline int save_buffer(TidyBuffer& ob) { + assert(_x); + return tidySaveBuffer(_x,&ob); } + + static inline TidyDoc create() { + return tidyCreate(); } + }; + + } +} + +#endif /* __OPKELE_TIDY_H */ diff --git a/include/opkele/tr1-mem.h.in b/include/opkele/tr1-mem.h.in new file mode 100644 index 0000000..e9ccf0b --- a/dev/null +++ b/include/opkele/tr1-mem.h.in @@ -0,0 +1,10 @@ +#ifndef __OPKELE_TR1_MEM_H +#define __OPKELE_TR1_MEM_H + +#include <@OPKELE_TR1_MEM_HEADER@> + +namespace opkele { + namespace tr1mem = @OPKELE_TR1_MEM_NS@; +} + +#endif /* __OPKELE_TR1_MEM_H */ diff --git a/include/opkele/types.h b/include/opkele/types.h index f732a1e..de44a5c 100644 --- a/include/opkele/types.h +++ b/include/opkele/types.h @@ -5,24 +5,26 @@ * @file * @brief various types declarations */ #include <ostream> #include <vector> #include <string> #include <map> -#include <memory> +#include <set> +#include <opkele/tr1-mem.h> namespace opkele { using std::vector; using std::string; using std::map; using std::ostream; - using std::auto_ptr; + using std::multimap; + using std::set; /** * the OpenID operation mode */ typedef enum _mode_t { mode_associate, mode_checkid_immediate, mode_checkid_setup, @@ -32,26 +34,26 @@ namespace opkele { /** * 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 key_d pointer to the message digest * @param rv reference to the return value */ - void enxor_to_base64(const unsigned char *key_sha1,string& rv) const; + void enxor_to_base64(const unsigned char *key_d,string& rv) const; /** - * decode base64-encoded secret and xor it with the sha1 digest - * @param key_sha1 pointer to the message digest + * decode base64-encoded secret and xor it with the message digest + * @param key_d pointer to the message digest * @param b64 base64-encoded secret value */ - void enxor_from_base64(const unsigned char *key_sha1,const string& b64); + void enxor_from_base64(const unsigned char *key_d,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 @@ -100,19 +102,19 @@ namespace opkele { /** * check whether the association is expired. * @return true if expired */ virtual bool is_expired() const = 0; }; /** - * the auto_ptr<> for association_t object type + * the shared_ptr<> for association_t object type */ - typedef auto_ptr<association_t> assoc_t; + typedef tr1mem::shared_ptr<association_t> assoc_t; /** * request/response parameters map */ class params_t : public map<string,string> { public: /** @@ -153,20 +155,92 @@ namespace opkele { /** * 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; + + /** + * make up a query string suitable for use in GET and POST + * requests. + * @param prefix string to prened to parameter names + * @return query string + */ + string query_string(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); + namespace xrd { + + struct priority_compare { + inline bool operator()(long a,long b) const { + return (a<0) ? false : (b<0) ? true : (a<b); + } + }; + + template <typename _DT> + class priority_map : public multimap<long,_DT,priority_compare> { + typedef multimap<long,_DT,priority_compare> map_type; + public: + + inline _DT& add(long priority,const _DT& d) { + return insert(typename map_type::value_type(priority,d))->second; + } + }; + + typedef priority_map<string> canonical_ids_t; + typedef priority_map<string> local_ids_t; + typedef set<string> types_t; + typedef priority_map<string> uris_t; + + class service_t { + public: + types_t types; + uris_t uris; + local_ids_t local_ids; + string provider_id; + + void clear() { + types.clear(); + uris.clear(); local_ids.clear(); + provider_id.clear(); + } + }; + typedef priority_map<service_t> services_t; + + class XRD_t { + public: + time_t expires; + + canonical_ids_t canonical_ids; + local_ids_t local_ids; + services_t services; + string provider_id; + + void clear() { + expires = 0; + canonical_ids.clear(); local_ids.clear(); + services.clear(); + provider_id.clear(); + } + bool empty() const { + return + canonical_ids.empty() + && local_ids.empty() + && services.empty(); + } + + }; + + } + } #endif /* __OPKELE_TYPES_H */ diff --git a/include/opkele/uris.h b/include/opkele/uris.h new file mode 100644 index 0000000..56c2d6d --- a/dev/null +++ b/include/opkele/uris.h @@ -0,0 +1,18 @@ +#ifndef __OPKELE_URIS_H +#define __OPKELE_URIS_H + +#define NSURI_XRDS "xri://$xrds" +#define NSURI_XRD "xri://$xrd*($v*2.0)" +#define NSURI_OPENID10 "http://openid.net/xmlns/1.0" + +#define OIURI_OPENID20 "http://specs.openid.net/auth/2.0" +#define OIURI_SREG11 "http://openid.net/extensions/sreg/1.1" + +#define STURI_OPENID10 "http://openid.net/signon/1.0" +#define STURI_OPENID11 "http://openid.net/signon/1.1" +#define STURI_OPENID20 "http://specs.openid.net/auth/2.0/signon" +#define STURI_OPENID20_OP "http://specs.openid.net/auth/2.0/server" + +#define IDURI_SELECT20 "http://specs.openid.net/auth/2.0/identifier_select" + +#endif /* __OPKELE_URIS_H */ |