summaryrefslogtreecommitdiffabout
path: root/lib/basic_rp.cc
authorMichael Krelin <hacker@klever.net>2008-02-08 22:16:15 (UTC)
committer Michael Krelin <hacker@klever.net>2008-02-08 22:16:15 (UTC)
commit16667a21c3052c89218d3e56098f0fc29dca2f1a (patch) (unidiff)
tree7154633a771b96da02cc4c980167b7ad92b6d27e /lib/basic_rp.cc
parentf2ba7be73a62d115f293f5d690efabcafd5fcf4f (diff)
downloadlibopkele-16667a21c3052c89218d3e56098f0fc29dca2f1a.zip
libopkele-16667a21c3052c89218d3e56098f0fc29dca2f1a.tar.gz
libopkele-16667a21c3052c89218d3e56098f0fc29dca2f1a.tar.bz2
minor fixes and making compiler a bit happier
Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (limited to 'lib/basic_rp.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/basic_rp.cc10
1 files changed, 6 insertions, 4 deletions
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc
index bd45d99..a0ad130 100644
--- a/lib/basic_rp.cc
+++ b/lib/basic_rp.cc
@@ -1,52 +1,54 @@
1#include <cassert>
1#include <openssl/sha.h> 2#include <openssl/sha.h>
2#include <openssl/hmac.h> 3#include <openssl/hmac.h>
3#include <opkele/basic_rp.h> 4#include <opkele/basic_rp.h>
4#include <opkele/exception.h> 5#include <opkele/exception.h>
5#include <opkele/uris.h> 6#include <opkele/uris.h>
6#include <opkele/data.h> 7#include <opkele/data.h>
7#include <opkele/util.h> 8#include <opkele/util.h>
8#include <opkele/curl.h> 9#include <opkele/curl.h>
9 10
10namespace opkele { 11namespace opkele {
11 12
12 static void dh_get_secret( 13 static void dh_get_secret(
13 secret_t& secret, const basic_openid_message& om, 14 secret_t& secret, const basic_openid_message& om,
14 const char *exp_assoc, const char *exp_sess, 15 const char *exp_assoc, const char *exp_sess,
15 util::dh_t& dh, 16 util::dh_t& dh,
16 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*), 17 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*),
17 size_t exp_s_len) try { 18 size_t exp_s_len) try {
18 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess) 19 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess)
19 throw bad_input(OPKELE_CP_ "Unexpected associate response"); 20 throw bad_input(OPKELE_CP_ "Unexpected associate response");
20 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public")); 21 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public"));
21 vector<unsigned char> ck(DH_size(dh)+1); 22 vector<unsigned char> ck(DH_size(dh)+1);
22 unsigned char *ckptr = &(ck.front())+1; 23 unsigned char *ckptr = &(ck.front())+1;
23 int cklen = DH_compute_key(ckptr,s_pub,dh); 24 int cklen = DH_compute_key(ckptr,s_pub,dh);
24 if(cklen<0) 25 if(cklen<0)
25 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 26 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
26 if(cklen && (*ckptr)&0x80) { 27 if(cklen && (*ckptr)&0x80) {
27 (*(--ckptr))=0; ++cklen; } 28 (*(--ckptr))=0; ++cklen; }
28 unsigned char key_digest[d_len]; 29 assert(d_len<=SHA256_DIGEST_LENGTH);
30 unsigned char key_digest[SHA256_DIGEST_LENGTH];
29 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key")); 31 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key"));
30 if(secret.size()!=exp_s_len) 32 if(secret.size()!=exp_s_len)
31 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type"); 33 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type");
32 }catch(opkele::failed_lookup& ofl) { 34 }catch(opkele::failed_lookup& ofl) {
33 throw bad_input(OPKELE_CP_ "Incoherent response from OP"); 35 throw bad_input(OPKELE_CP_ "Incoherent response from OP");
34 } OPKELE_RETHROW 36 } OPKELE_RETHROW
35 37
36 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) { 38 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) {
37 util::curl_pick_t curl = util::curl_pick_t::easy_init(); 39 util::curl_pick_t curl = util::curl_pick_t::easy_init();
38 if(!curl) 40 if(!curl)
39 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 41 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
40 string request = inm.query_string(); 42 string request = inm.query_string();
41 CURLcode r; 43 CURLcode r;
42 (r=curl.misc_sets()) 44 (r=curl.misc_sets())
43 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str())) 45 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str()))
44 || (r=curl.easy_setopt(CURLOPT_POST,1)) 46 || (r=curl.easy_setopt(CURLOPT_POST,1))
45 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 47 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
46 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 48 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
47 || (r=curl.set_write()); 49 || (r=curl.set_write());
48 if(r) 50 if(r)
49 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 51 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
50 if( (r=curl.easy_perform()) ) 52 if( (r=curl.easy_perform()) )
51 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 53 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
52 oum.from_keyvalues(curl.response); 54 oum.from_keyvalues(curl.response);
@@ -57,58 +59,58 @@ namespace opkele {
57 util::dh_t dh = DH_new(); 59 util::dh_t dh = DH_new();
58 if(!dh) 60 if(!dh)
59 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 61 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
60 dh->p = util::dec_to_bignum(data::_default_p); 62 dh->p = util::dec_to_bignum(data::_default_p);
61 dh->g = util::dec_to_bignum(data::_default_g); 63 dh->g = util::dec_to_bignum(data::_default_g);
62 if(!DH_generate_key(dh)) 64 if(!DH_generate_key(dh))
63 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 65 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
64 openid_message_t req; 66 openid_message_t req;
65 req.set_field("ns",OIURI_OPENID20); 67 req.set_field("ns",OIURI_OPENID20);
66 req.set_field("mode","associate"); 68 req.set_field("mode","associate");
67 req.set_field("dh_modulus",util::bignum_to_base64(dh->p)); 69 req.set_field("dh_modulus",util::bignum_to_base64(dh->p));
68 req.set_field("dh_gen",util::bignum_to_base64(dh->g)); 70 req.set_field("dh_gen",util::bignum_to_base64(dh->g));
69 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key)); 71 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key));
70 openid_message_t res; 72 openid_message_t res;
71 req.set_field("assoc_type","HMAC-SHA256"); 73 req.set_field("assoc_type","HMAC-SHA256");
72 req.set_field("session_type","DH-SHA256"); 74 req.set_field("session_type","DH-SHA256");
73 secret_t secret; 75 secret_t secret;
74 int expires_in; 76 int expires_in;
75 try { 77 try {
76 direct_request(res,req,OP); 78 direct_request(res,req,OP);
77 dh_get_secret( secret, res, 79 dh_get_secret( secret, res,
78 "HMAC-SHA256", "DH-SHA256", 80 "HMAC-SHA256", "DH-SHA256",
79 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH ); 81 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH );
80 expires_in = util::string_to_long(res.get_field("expires_in")); 82 expires_in = util::string_to_long(res.get_field("expires_in"));
81 }catch(exception& e) { 83 }catch(exception&) {
82 try { 84 try {
83 req.set_field("assoc_type","HMAC-SHA1"); 85 req.set_field("assoc_type","HMAC-SHA1");
84 req.set_field("session_type","DH-SHA1"); 86 req.set_field("session_type","DH-SHA1");
85 direct_request(res,req,OP); 87 direct_request(res,req,OP);
86 dh_get_secret( secret, res, 88 dh_get_secret( secret, res,
87 "HMAC-SHA1", "DH-SHA1", 89 "HMAC-SHA1", "DH-SHA1",
88 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH ); 90 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH );
89 expires_in = util::string_to_long(res.get_field("expires_in")); 91 expires_in = util::string_to_long(res.get_field("expires_in"));
90 }catch(bad_input& e) { 92 }catch(bad_input&) {
91 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association"); 93 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association");
92 } 94 }
93 } 95 }
94 return store_assoc( 96 return store_assoc(
95 OP, res.get_field("assoc_handle"), 97 OP, res.get_field("assoc_handle"),
96 res.get_field("assoc_type"), secret, 98 res.get_field("assoc_type"), secret,
97 expires_in ); 99 expires_in );
98 } 100 }
99 101
100 basic_openid_message& basic_RP::checkid_( 102 basic_openid_message& basic_RP::checkid_(
101 basic_openid_message& rv, 103 basic_openid_message& rv,
102 mode_t mode, 104 mode_t mode,
103 const string& return_to,const string& realm, 105 const string& return_to,const string& realm,
104 extension_t *ext) { 106 extension_t *ext) {
105 rv.reset_fields(); 107 rv.reset_fields();
106 rv.set_field("ns",OIURI_OPENID20); 108 rv.set_field("ns",OIURI_OPENID20);
107 if(mode==mode_checkid_immediate) 109 if(mode==mode_checkid_immediate)
108 rv.set_field("mode","checkid_immediate"); 110 rv.set_field("mode","checkid_immediate");
109 else if(mode==mode_checkid_setup) 111 else if(mode==mode_checkid_setup)
110 rv.set_field("mode","checkid_setup"); 112 rv.set_field("mode","checkid_setup");
111 else 113 else
112 throw bad_input(OPKELE_CP_ "unknown checkid_* mode"); 114 throw bad_input(OPKELE_CP_ "unknown checkid_* mode");
113 if(realm.empty() && return_to.empty()) 115 if(realm.empty() && return_to.empty())
114 throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty"); 116 throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty");
@@ -213,49 +215,49 @@ namespace opkele {
213 if(om.get_field("sig")!=util::base64_signature(assoc,om)) 215 if(om.get_field("sig")!=util::base64_signature(assoc,om))
214 throw id_res_mismatch(OPKELE_CP_ "signature mismatch"); 216 throw id_res_mismatch(OPKELE_CP_ "signature mismatch");
215 }catch(dumb_RP& drp) { 217 }catch(dumb_RP& drp) {
216 go_dumb=true; 218 go_dumb=true;
217 }catch(failed_lookup& e) { 219 }catch(failed_lookup& e) {
218 go_dumb=true; 220 go_dumb=true;
219 } OPKELE_RETHROW 221 } OPKELE_RETHROW
220 if(go_dumb) { 222 if(go_dumb) {
221 try { 223 try {
222 string OP = o2 224 string OP = o2
223 ?om.get_field("op_endpoint") 225 ?om.get_field("op_endpoint")
224 :get_endpoint().uri; 226 :get_endpoint().uri;
225 check_authentication(OP,om); 227 check_authentication(OP,om);
226 }catch(failed_check_authentication& fca) { 228 }catch(failed_check_authentication& fca) {
227 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()"); 229 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()");
228 } OPKELE_RETHROW 230 } OPKELE_RETHROW
229 } 231 }
230 signed_part_message_proxy signeds(om); 232 signed_part_message_proxy signeds(om);
231 if(o2) { 233 if(o2) {
232 check_nonce(om.get_field("op_endpoint"), 234 check_nonce(om.get_field("op_endpoint"),
233 om.get_field("response_nonce")); 235 om.get_field("response_nonce"));
234 static const char *mustsign[] = { 236 static const char *mustsign[] = {
235 "op_endpoint", "return_to", "response_nonce", "assoc_handle", 237 "op_endpoint", "return_to", "response_nonce", "assoc_handle",
236 "claimed_id", "identity" }; 238 "claimed_id", "identity" };
237 for(int ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) { 239 for(size_t ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) {
238 if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms])) 240 if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms]))
239 throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs"); 241 throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs");
240 } 242 }
241 if( ( 243 if( (
242 (om.has_field("claimed_id")?1:0) 244 (om.has_field("claimed_id")?1:0)
243 ^ 245 ^
244 (om.has_field("identity")?1:0) 246 (om.has_field("identity")?1:0)
245 )&1 ) 247 )&1 )
246 throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent"); 248 throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent");
247 249
248 string turl = util::rfc_3986_normalize_uri(get_this_url()); 250 string turl = util::rfc_3986_normalize_uri(get_this_url());
249 util::strip_uri_fragment_part(turl); 251 util::strip_uri_fragment_part(turl);
250 string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to")); 252 string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to"));
251 util::strip_uri_fragment_part(rurl); 253 util::strip_uri_fragment_part(rurl);
252 string::size_type 254 string::size_type
253 tq = turl.find('?'), rq = rurl.find('?'); 255 tq = turl.find('?'), rq = rurl.find('?');
254 if( 256 if(
255 ((tq==string::npos)?turl:turl.substr(0,tq)) 257 ((tq==string::npos)?turl:turl.substr(0,tq))
256 != 258 !=
257 ((rq==string::npos)?rurl:rurl.substr(0,rq)) 259 ((rq==string::npos)?rurl:rurl.substr(0,rq))
258 ) 260 )
259 throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url"); 261 throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url");
260 map<string,string> tp; parse_query(turl,tq,tp); 262 map<string,string> tp; parse_query(turl,tq,tp);
261 map<string,string> rp; parse_query(rurl,rq,rp); 263 map<string,string> rp; parse_query(rurl,rq,rp);