summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/opkele/curl.h3
-rw-r--r--lib/consumer.cc50
-rw-r--r--lib/curl.cc12
3 files changed, 43 insertions, 22 deletions
diff --git a/include/opkele/curl.h b/include/opkele/curl.h
index 6a7d084..1029b34 100644
--- a/include/opkele/curl.h
+++ b/include/opkele/curl.h
@@ -21,19 +21,22 @@ namespace opkele {
21 operator const CURL*(void) const { return _c; } 21 operator const CURL*(void) const { return _c; }
22 operator CURL*(void) { return _c; } 22 operator CURL*(void) { return _c; }
23 23
24 CURLcode misc_sets(); 24 CURLcode misc_sets();
25 25
26 template<typename PT> 26 template<typename PT>
27 inline CURLcode easy_setopt(CURLoption o,PT p) { assert(_c); return curl_easy_setopt(_c,o,p); } 27 inline CURLcode easy_setopt(CURLoption o,PT p) { assert(_c); return curl_easy_setopt(_c,o,p); }
28 CURLcode easy_perform() { assert(_c); return curl_easy_perform(_c); } 28 CURLcode easy_perform() { assert(_c); return curl_easy_perform(_c); }
29 template<typename IT> 29 template<typename IT>
30 inline CURLcode easy_getinfo(CURLINFO i,IT p) { assert(_c); return curl_easy_getinfo(_c,i,p); } 30 inline CURLcode easy_getinfo(CURLINFO i,IT p) { assert(_c); return curl_easy_getinfo(_c,i,p); }
31 31
32 static inline CURL *easy_init() { return curl_easy_init(); } 32 static inline CURL *easy_init() { return curl_easy_init(); }
33
34 virtual size_t write(void *p,size_t s,size_t nm) { return 0; }
35 CURLcode set_write();
33 }; 36 };
34 37
35 } 38 }
36 39
37} 40}
38 41
39#endif /* __OPKELE_CURL_H */ 42#endif /* __OPKELE_CURL_H */
diff --git a/lib/consumer.cc b/lib/consumer.cc
index c155157..62bec71 100644
--- a/lib/consumer.cc
+++ b/lib/consumer.cc
@@ -9,24 +9,43 @@
9#include <openssl/sha.h> 9#include <openssl/sha.h>
10#include <openssl/hmac.h> 10#include <openssl/hmac.h>
11#include <iostream> 11#include <iostream>
12 12
13#include "config.h" 13#include "config.h"
14 14
15#include <pcre.h> 15#include <pcre.h>
16 16
17namespace opkele { 17namespace opkele {
18 using namespace std; 18 using namespace std;
19 using util::curl_t; 19 using util::curl_t;
20 20
21 template<int lim>
22 class curl_fetch_string_t : public curl_t {
23 public:
24 curl_fetch_string_t(CURL *c)
25 : curl_t(c) { }
26 ~curl_fetch_string_t() throw() { }
27
28 string response;
29
30 size_t write(void *p,size_t size,size_t nmemb) {
31 size_t bytes = size*nmemb;
32 size_t get = min(lim-response.length(),bytes);
33 response.append((const char *)p,get);
34 return get;
35 }
36 };
37
38 typedef curl_fetch_string_t<16384> curl_pick_t;
39
21 class pcre_matches_t { 40 class pcre_matches_t {
22 public: 41 public:
23 int *_ov; 42 int *_ov;
24 int _s; 43 int _s;
25 44
26 pcre_matches_t() : _ov(0), _s(0) { } 45 pcre_matches_t() : _ov(0), _s(0) { }
27 pcre_matches_t(int s) : _ov(0), _s(s) { 46 pcre_matches_t(int s) : _ov(0), _s(s) {
28 if(_s&1) ++_s; 47 if(_s&1) ++_s;
29 _s += _s>>1; 48 _s += _s>>1;
30 _ov = new int[_s]; 49 _ov = new int[_s];
31 } 50 }
32 ~pcre_matches_t() throw() { if(_ov) delete[] _ov; } 51 ~pcre_matches_t() throw() { if(_ov) delete[] _ov; }
@@ -53,64 +72,54 @@ namespace opkele {
53 pcre_t& operator=(pcre *p) { if(_p) (*pcre_free)(_p); _p=p; return *this; } 72 pcre_t& operator=(pcre *p) { if(_p) (*pcre_free)(_p); _p=p; return *this; }
54 73
55 operator const pcre*(void) const { return _p; } 74 operator const pcre*(void) const { return _p; }
56 operator pcre*(void) { return _p; } 75 operator pcre*(void) { return _p; }
57 76
58 int exec(const string& s,pcre_matches_t& m) { 77 int exec(const string& s,pcre_matches_t& m) {
59 if(!_p) 78 if(!_p)
60 throw internal_error(OPKELE_CP_ "Trying to execute absent regexp"); 79 throw internal_error(OPKELE_CP_ "Trying to execute absent regexp");
61 return pcre_exec(_p,NULL,s.c_str(),s.length(),0,0,m._ov,m._s); 80 return pcre_exec(_p,NULL,s.c_str(),s.length(),0,0,m._ov,m._s);
62 } 81 }
63 }; 82 };
64 83
65 static size_t _curl_tostring(void *ptr,size_t size,size_t nmemb,void *stream) {
66 string *str = (string*)stream;
67 size_t bytes = size*nmemb;
68 size_t get = min(16384-str->length(),bytes);
69 str->append((const char*)ptr,get);
70 return get;
71 }
72
73 assoc_t consumer_t::associate(const string& server) { 84 assoc_t consumer_t::associate(const string& server) {
74 util::dh_t dh = DH_new(); 85 util::dh_t dh = DH_new();
75 if(!dh) 86 if(!dh)
76 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 87 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
77 dh->p = util::dec_to_bignum(data::_default_p); 88 dh->p = util::dec_to_bignum(data::_default_p);
78 dh->g = util::dec_to_bignum(data::_default_g); 89 dh->g = util::dec_to_bignum(data::_default_g);
79 if(!DH_generate_key(dh)) 90 if(!DH_generate_key(dh))
80 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 91 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
81 string request = 92 string request =
82 "openid.mode=associate" 93 "openid.mode=associate"
83 "&openid.assoc_type=HMAC-SHA1" 94 "&openid.assoc_type=HMAC-SHA1"
84 "&openid.session_type=DH-SHA1" 95 "&openid.session_type=DH-SHA1"
85 "&openid.dh_consumer_public="; 96 "&openid.dh_consumer_public=";
86 request += util::url_encode(util::bignum_to_base64(dh->pub_key)); 97 request += util::url_encode(util::bignum_to_base64(dh->pub_key));
87 curl_t curl = curl_t::easy_init(); 98 curl_pick_t curl = curl_pick_t::easy_init();
88 if(!curl) 99 if(!curl)
89 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 100 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
90 string response;
91 CURLcode r; 101 CURLcode r;
92 (r=curl.misc_sets()) 102 (r=curl.misc_sets())
93 || (r=curl.easy_setopt(CURLOPT_URL,server.c_str())) 103 || (r=curl.easy_setopt(CURLOPT_URL,server.c_str()))
94 || (r=curl.easy_setopt(CURLOPT_POST,1)) 104 || (r=curl.easy_setopt(CURLOPT_POST,1))
95 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 105 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
96 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 106 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
97 || (r=curl.easy_setopt(CURLOPT_WRITEFUNCTION,_curl_tostring)) 107 || (r=curl.set_write())
98 || (r=curl.easy_setopt(CURLOPT_WRITEDATA,&response))
99 ; 108 ;
100 if(r) 109 if(r)
101 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 110 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
102 if( (r=curl.easy_perform()) ) 111 if( (r=curl.easy_perform()) )
103 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 112 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
104 params_t p; p.parse_keyvalues(response); 113 params_t p; p.parse_keyvalues(curl.response);
105 if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1") 114 if(p.has_param("assoc_type") && p.get_param("assoc_type")!="HMAC-SHA1")
106 throw bad_input(OPKELE_CP_ "unsupported assoc_type"); 115 throw bad_input(OPKELE_CP_ "unsupported assoc_type");
107 string st; 116 string st;
108 if(p.has_param("session_type")) st = p.get_param("session_type"); 117 if(p.has_param("session_type")) st = p.get_param("session_type");
109 if((!st.empty()) && st!="DH-SHA1") 118 if((!st.empty()) && st!="DH-SHA1")
110 throw bad_input(OPKELE_CP_ "unsupported session_type"); 119 throw bad_input(OPKELE_CP_ "unsupported session_type");
111 secret_t secret; 120 secret_t secret;
112 if(st.empty()) { 121 if(st.empty()) {
113 secret.from_base64(p.get_param("mac_key")); 122 secret.from_base64(p.get_param("mac_key"));
114 }else{ 123 }else{
115 util::bignum_t s_pub = util::base64_to_bignum(p.get_param("dh_server_public")); 124 util::bignum_t s_pub = util::base64_to_bignum(p.get_param("dh_server_public"));
116 vector<unsigned char> ck(DH_size(dh)+1); 125 vector<unsigned char> ck(DH_size(dh)+1);
@@ -235,66 +244,63 @@ namespace opkele {
235 } 244 }
236 245
237 void consumer_t::check_authentication(const string& server,const params_t& p) { 246 void consumer_t::check_authentication(const string& server,const params_t& p) {
238 string request = "openid.mode=check_authentication"; 247 string request = "openid.mode=check_authentication";
239 for(params_t::const_iterator i=p.begin();i!=p.end();++i) { 248 for(params_t::const_iterator i=p.begin();i!=p.end();++i) {
240 if(i->first!="openid.mode") { 249 if(i->first!="openid.mode") {
241 request += '&'; 250 request += '&';
242 request += i->first; 251 request += i->first;
243 request += '='; 252 request += '=';
244 request += util::url_encode(i->second); 253 request += util::url_encode(i->second);
245 } 254 }
246 } 255 }
247 curl_t curl = curl_t::easy_init(); 256 curl_pick_t curl = curl_pick_t::easy_init();
248 if(!curl) 257 if(!curl)
249 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 258 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
250 string response;
251 CURLcode r; 259 CURLcode r;
252 (r=curl.misc_sets()) 260 (r=curl.misc_sets())
253 || (r=curl.easy_setopt(CURLOPT_URL,server.c_str())) 261 || (r=curl.easy_setopt(CURLOPT_URL,server.c_str()))
254 || (r=curl.easy_setopt(CURLOPT_POST,1)) 262 || (r=curl.easy_setopt(CURLOPT_POST,1))
255 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 263 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
256 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 264 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
257 || (r=curl.easy_setopt(CURLOPT_WRITEFUNCTION,_curl_tostring)) 265 || (r=curl.set_write())
258 || (r=curl.easy_setopt(CURLOPT_WRITEDATA,&response))
259 ; 266 ;
260 if(r) 267 if(r)
261 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 268 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
262 if( (r=curl.easy_perform()) ) 269 if( (r=curl.easy_perform()) )
263 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 270 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
264 params_t pp; pp.parse_keyvalues(response); 271 params_t pp; pp.parse_keyvalues(curl.response);
265 if(pp.has_param("invalidate_handle")) 272 if(pp.has_param("invalidate_handle"))
266 invalidate_assoc(server,pp.get_param("invalidate_handle")); 273 invalidate_assoc(server,pp.get_param("invalidate_handle"));
267 if(pp.has_param("is_valid")) { 274 if(pp.has_param("is_valid")) {
268 if(pp.get_param("is_valid")=="true") 275 if(pp.get_param("is_valid")=="true")
269 return; 276 return;
270 }else if(pp.has_param("lifetime")) { 277 }else if(pp.has_param("lifetime")) {
271 if(util::string_to_long(pp.get_param("lifetime"))) 278 if(util::string_to_long(pp.get_param("lifetime")))
272 return; 279 return;
273 } 280 }
274 throw failed_check_authentication(OPKELE_CP_ "failed to verify response"); 281 throw failed_check_authentication(OPKELE_CP_ "failed to verify response");
275 } 282 }
276 283
277 void consumer_t::retrieve_links(const string& url,string& server,string& delegate) { 284 void consumer_t::retrieve_links(const string& url,string& server,string& delegate) {
278 server.erase(); 285 server.erase();
279 delegate.erase(); 286 delegate.erase();
280 curl_t curl = curl_t::easy_init(); 287 curl_pick_t curl = curl_pick_t::easy_init();
281 if(!curl) 288 if(!curl)
282 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 289 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
283 string html; 290 string& html = curl.response;
284 CURLcode r; 291 CURLcode r;
285 (r=curl.misc_sets()) 292 (r=curl.misc_sets())
286 || (r=curl.easy_setopt(CURLOPT_URL,url.c_str())) 293 || (r=curl.easy_setopt(CURLOPT_URL,url.c_str()))
287 || (r=curl.easy_setopt(CURLOPT_WRITEFUNCTION,_curl_tostring)) 294 || (r=curl.set_write());
288 || (r=curl.easy_setopt(CURLOPT_WRITEDATA,&html))
289 ; 295 ;
290 if(r) 296 if(r)
291 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 297 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
292 r = curl.easy_perform(); 298 r = curl.easy_perform();
293 if(r && r!=CURLE_WRITE_ERROR) 299 if(r && r!=CURLE_WRITE_ERROR)
294 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 300 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
295 static const char *re_bre = "<\\s*body\\b", *re_hdre = "<\\s*head[^>]*>", 301 static const char *re_bre = "<\\s*body\\b", *re_hdre = "<\\s*head[^>]*>",
296 *re_lre = "<\\s*link\\b([^>]+)>", 302 *re_lre = "<\\s*link\\b([^>]+)>",
297 *re_rre = "\\brel\\s*=\\s*['\"]([^'\"]+)['\"]", 303 *re_rre = "\\brel\\s*=\\s*['\"]([^'\"]+)['\"]",
298 *re_hre = "\\bhref\\s*=\\s*['\"]\\s*([^'\"\\s]+)\\s*['\"]"; 304 *re_hre = "\\bhref\\s*=\\s*['\"]\\s*([^'\"\\s]+)\\s*['\"]";
299 pcre_matches_t m1(3), m2(3); 305 pcre_matches_t m1(3), m2(3);
300 pcre_t bre(re_bre,PCRE_CASELESS); 306 pcre_t bre(re_bre,PCRE_CASELESS);
diff --git a/lib/curl.cc b/lib/curl.cc
index 418aa79..3e69b47 100644
--- a/lib/curl.cc
+++ b/lib/curl.cc
@@ -28,15 +28,27 @@ namespace opkele {
28 || (r=easy_setopt(CURLOPT_USERAGENT,PACKAGE_NAME"/"PACKAGE_SRC_VERSION)) 28 || (r=easy_setopt(CURLOPT_USERAGENT,PACKAGE_NAME"/"PACKAGE_SRC_VERSION))
29 || (r=easy_setopt(CURLOPT_TIMEOUT,20)) 29 || (r=easy_setopt(CURLOPT_TIMEOUT,20))
30 #ifdefDISABLE_CURL_SSL_VERIFYHOST 30 #ifdefDISABLE_CURL_SSL_VERIFYHOST
31 || (r=easy_setopt(CURLOPT_SSL_VERIFYHOST,0)) 31 || (r=easy_setopt(CURLOPT_SSL_VERIFYHOST,0))
32#endif 32#endif
33 #ifdefDISABLE_CURL_SSL_VERIFYPEER 33 #ifdefDISABLE_CURL_SSL_VERIFYPEER
34 || (r=easy_setopt(CURLOPT_SSL_VERIFYPEER,0)) 34 || (r=easy_setopt(CURLOPT_SSL_VERIFYPEER,0))
35#endif 35#endif
36 ; 36 ;
37 return r; 37 return r;
38 } 38 }
39 39
40 static size_t _write(void *p,size_t s,size_t nm,void *stream) {
41 return ((curl_t*)stream)->write(p,s,nm);
42 }
43
44 CURLcode curl_t::set_write() {
45 assert(_c);
46 CURLcode r;
47 (r = easy_setopt(CURLOPT_WRITEDATA,this))
48 || (r = easy_setopt(CURLOPT_WRITEFUNCTION,_write));
49 return r;
50 }
51
40 } 52 }
41 53
42} 54}