summaryrefslogtreecommitdiffabout
path: root/lib/basic_rp.cc
Unidiff
Diffstat (limited to 'lib/basic_rp.cc') (more/less context) (show whitespace changes)
-rw-r--r--lib/basic_rp.cc29
1 files changed, 27 insertions, 2 deletions
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc
index e65d9fb..3357d0b 100644
--- a/lib/basic_rp.cc
+++ b/lib/basic_rp.cc
@@ -1,37 +1,56 @@
1#include <cassert> 1#include <cassert>
2#include <openssl/sha.h> 2#include <openssl/sha.h>
3#include <openssl/hmac.h> 3#include <openssl/hmac.h>
4#include <opkele/basic_rp.h> 4#include <opkele/basic_rp.h>
5#include <opkele/exception.h> 5#include <opkele/exception.h>
6#include <opkele/uris.h> 6#include <opkele/uris.h>
7#include <opkele/data.h> 7#include <opkele/data.h>
8#include <opkele/util.h> 8#include <opkele/util.h>
9#include <opkele/util-internal.h> 9#include <opkele/util-internal.h>
10#include <opkele/curl.h> 10#include <opkele/curl.h>
11#include <opkele/debug.h>
11 12
12namespace opkele { 13namespace opkele {
13 14
15 void basic_RP::reset_vars() {
16 claimed_id.clear(); identity.clear();
17 }
18
19 const string& basic_RP::get_claimed_id() const {
20 if(claimed_id.empty())
21 throw non_identity(OPKELE_CP_ "attempting to retreive claimed_id of non-identity assertion");
22 assert(!identity.empty());
23 return claimed_id;
24 }
25
26 const string& basic_RP::get_identity() const {
27 if(identity.empty())
28 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related assertion");
29 assert(!claimed_id.empty());
30 return identity;
31 }
32
14 static void dh_get_secret( 33 static void dh_get_secret(
15 secret_t& secret, const basic_openid_message& om, 34 secret_t& secret, const basic_openid_message& om,
16 const char *exp_assoc, const char *exp_sess, 35 const char *exp_assoc, const char *exp_sess,
17 util::dh_t& dh, 36 util::dh_t& dh,
18 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*), 37 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*),
19 size_t exp_s_len) try { 38 size_t exp_s_len) try {
20 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess) 39 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess)
21 throw bad_input(OPKELE_CP_ "Unexpected associate response"); 40 throw bad_input(OPKELE_CP_ "Unexpected associate response");
22 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public")); 41 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public"));
23 vector<unsigned char> ck(DH_size(dh)+1); 42 vector<unsigned char> ck(DH_size(dh)+1);
24 unsigned char *ckptr = &(ck.front())+1; 43 unsigned char *ckptr = &(ck.front())+1;
25 int cklen = DH_compute_key(ckptr,s_pub,dh); 44 int cklen = DH_compute_key(ckptr,s_pub,dh);
26 if(cklen<0) 45 if(cklen<0)
27 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 46 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
28 if(cklen && (*ckptr)&0x80) { 47 if(cklen && (*ckptr)&0x80) {
29 (*(--ckptr))=0; ++cklen; } 48 (*(--ckptr))=0; ++cklen; }
30 assert(d_len<=SHA256_DIGEST_LENGTH); 49 assert(d_len<=SHA256_DIGEST_LENGTH);
31 unsigned char key_digest[SHA256_DIGEST_LENGTH]; 50 unsigned char key_digest[SHA256_DIGEST_LENGTH];
32 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key")); 51 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key"));
33 if(secret.size()!=exp_s_len) 52 if(secret.size()!=exp_s_len)
34 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type"); 53 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type");
35 }catch(opkele::failed_lookup& ofl) { 54 }catch(opkele::failed_lookup& ofl) {
36 throw bad_input(OPKELE_CP_ "Incoherent response from OP"); 55 throw bad_input(OPKELE_CP_ "Incoherent response from OP");
37 } OPKELE_RETHROW 56 } OPKELE_RETHROW
@@ -175,48 +194,49 @@ namespace opkele {
175 ++q; 194 ++q;
176 string::size_type l = u.size(); 195 string::size_type l = u.size();
177 while(q<l) { 196 while(q<l) {
178 string::size_type eq = u.find('=',q); 197 string::size_type eq = u.find('=',q);
179 string::size_type am = u.find('&',q); 198 string::size_type am = u.find('&',q);
180 if(am==string::npos) { 199 if(am==string::npos) {
181 if(eq==string::npos) { 200 if(eq==string::npos) {
182 p[""] = u.substr(q); 201 p[""] = u.substr(q);
183 }else{ 202 }else{
184 p[u.substr(q,eq-q)] = u.substr(eq+1); 203 p[u.substr(q,eq-q)] = u.substr(eq+1);
185 } 204 }
186 break; 205 break;
187 }else{ 206 }else{
188 if(eq==string::npos || eq>am) { 207 if(eq==string::npos || eq>am) {
189 p[""] = u.substr(q,eq-q); 208 p[""] = u.substr(q,eq-q);
190 }else{ 209 }else{
191 p[u.substr(q,eq-q)] = u.substr(eq+1,am-eq-1); 210 p[u.substr(q,eq-q)] = u.substr(eq+1,am-eq-1);
192 } 211 }
193 q = ++am; 212 q = ++am;
194 } 213 }
195 } 214 }
196 } 215 }
197 216
198 void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) { 217 void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) {
218 reset_vars();
199 bool o2 = om.has_field("ns") 219 bool o2 = om.has_field("ns")
200 && om.get_field("ns")==OIURI_OPENID20; 220 && om.get_field("ns")==OIURI_OPENID20;
201 if( (!o2) && om.has_field("user_setup_url")) 221 if( (!o2) && om.has_field("user_setup_url"))
202 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided", 222 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided",
203 om.get_field("user_setup_url")); 223 om.get_field("user_setup_url"));
204 string m = om.get_field("mode"); 224 string m = om.get_field("mode");
205 if(o2 && m=="setup_needed") 225 if(o2 && m=="setup_needed")
206 throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided"); 226 throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided");
207 if(m=="cancel") 227 if(m=="cancel")
208 throw id_res_cancel(OPKELE_CP_ "authentication cancelled"); 228 throw id_res_cancel(OPKELE_CP_ "authentication cancelled");
209 bool go_dumb=false; 229 bool go_dumb=false;
210 try { 230 try {
211 string OP = o2 231 string OP = o2
212 ?om.get_field("op_endpoint") 232 ?om.get_field("op_endpoint")
213 :get_endpoint().uri; 233 :get_endpoint().uri;
214 assoc_t assoc = retrieve_assoc( 234 assoc_t assoc = retrieve_assoc(
215 OP,om.get_field("assoc_handle")); 235 OP,om.get_field("assoc_handle"));
216 if(om.get_field("sig")!=util::base64_signature(assoc,om)) 236 if(om.get_field("sig")!=util::base64_signature(assoc,om))
217 throw id_res_mismatch(OPKELE_CP_ "signature mismatch"); 237 throw id_res_mismatch(OPKELE_CP_ "signature mismatch");
218 }catch(dumb_RP& drp) { 238 }catch(dumb_RP& drp) {
219 go_dumb=true; 239 go_dumb=true;
220 }catch(failed_lookup& e) { 240 }catch(failed_lookup& e) {
221 go_dumb=true; 241 go_dumb=true;
222 } OPKELE_RETHROW 242 } OPKELE_RETHROW
@@ -250,51 +270,56 @@ namespace opkele {
250 270
251 string turl = util::rfc_3986_normalize_uri(get_this_url()); 271 string turl = util::rfc_3986_normalize_uri(get_this_url());
252 util::strip_uri_fragment_part(turl); 272 util::strip_uri_fragment_part(turl);
253 string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to")); 273 string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to"));
254 util::strip_uri_fragment_part(rurl); 274 util::strip_uri_fragment_part(rurl);
255 string::size_type 275 string::size_type
256 tq = turl.find('?'), rq = rurl.find('?'); 276 tq = turl.find('?'), rq = rurl.find('?');
257 if( 277 if(
258 ((tq==string::npos)?turl:turl.substr(0,tq)) 278 ((tq==string::npos)?turl:turl.substr(0,tq))
259 != 279 !=
260 ((rq==string::npos)?rurl:rurl.substr(0,rq)) 280 ((rq==string::npos)?rurl:rurl.substr(0,rq))
261 ) 281 )
262 throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url"); 282 throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url");
263 map<string,string> tp; parse_query(turl,tq,tp); 283 map<string,string> tp; parse_query(turl,tq,tp);
264 map<string,string> rp; parse_query(rurl,rq,rp); 284 map<string,string> rp; parse_query(rurl,rq,rp);
265 for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) { 285 for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) {
266 map<string,string>::const_iterator tpi = tp.find(rpi->first); 286 map<string,string>::const_iterator tpi = tp.find(rpi->first);
267 if(tpi==tp.end()) 287 if(tpi==tp.end())
268 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request"); 288 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request");
269 if(tpi->second!=rpi->second) 289 if(tpi->second!=rpi->second)
270 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request"); 290 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request");
271 } 291 }
272 292
273 if(om.has_field("claimed_id")) { 293 if(om.has_field("claimed_id")) {
294 claimed_id = om.get_field("claimed_id");
295 identity = om.get_field("identity");
274 verify_OP( 296 verify_OP(
275 om.get_field("op_endpoint"), 297 om.get_field("op_endpoint"),
276 om.get_field("claimed_id"), 298 claimed_id, identity );
277 om.get_field("identity") );
278 } 299 }
279 300
301 }else{
302 claimed_id = get_endpoint().claimed_id;
303 /* TODO: check if this is the identity we asked for */
304 identity = om.get_field("identity");
280 } 305 }
281 if(ext) ext->rp_id_res_hook(om,signeds); 306 if(ext) ext->rp_id_res_hook(om,signeds);
282 } 307 }
283 308
284 void basic_RP::check_authentication(const string& OP, 309 void basic_RP::check_authentication(const string& OP,
285 const basic_openid_message& om){ 310 const basic_openid_message& om){
286 openid_message_t res; 311 openid_message_t res;
287 static const string checkauthmode = "check_authentication"; 312 static const string checkauthmode = "check_authentication";
288 direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP); 313 direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP);
289 if(res.has_field("is_valid")) { 314 if(res.has_field("is_valid")) {
290 if(res.get_field("is_valid")=="true") { 315 if(res.get_field("is_valid")=="true") {
291 if(res.has_field("invalidate_handle")) 316 if(res.has_field("invalidate_handle"))
292 invalidate_assoc(OP,res.get_field("invalidate_handle")); 317 invalidate_assoc(OP,res.get_field("invalidate_handle"));
293 return; 318 return;
294 } 319 }
295 } 320 }
296 throw failed_check_authentication( 321 throw failed_check_authentication(
297 OPKELE_CP_ "failed to verify response"); 322 OPKELE_CP_ "failed to verify response");
298 } 323 }
299 324
300} 325}