summaryrefslogtreecommitdiffabout
path: root/lib/basic_op.cc
Unidiff
Diffstat (limited to 'lib/basic_op.cc') (more/less context) (show whitespace changes)
-rw-r--r--lib/basic_op.cc36
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/basic_op.cc b/lib/basic_op.cc
index 22012bc..f7573aa 100644
--- a/lib/basic_op.cc
+++ b/lib/basic_op.cc
@@ -1,59 +1,62 @@
1#include <time.h> 1#include <time.h>
2#include <cassert> 2#include <cassert>
3#include <algorithm>
3#include <openssl/sha.h> 4#include <openssl/sha.h>
4#include <openssl/hmac.h> 5#include <openssl/hmac.h>
5#include <opkele/data.h> 6#include <opkele/data.h>
6#include <opkele/basic_op.h> 7#include <opkele/basic_op.h>
7#include <opkele/exception.h> 8#include <opkele/exception.h>
8#include <opkele/util.h> 9#include <opkele/util.h>
9#include <opkele/uris.h> 10#include <opkele/uris.h>
10 11
11namespace opkele { 12namespace opkele {
13 using std::pair;
14 using std::mismatch;
12 15
13 void basic_op::reset_vars() { 16 void basic_op::reset_vars() {
14 assoc.reset(); 17 assoc.reset();
15 return_to.clear(); realm.clear(); 18 return_to.clear(); realm.clear();
16 claimed_id.clear(); identity.clear(); 19 claimed_id.clear(); identity.clear();
17 invalidate_handle.clear(); 20 invalidate_handle.clear();
18 } 21 }
19 22
20 bool basic_op::has_return_to() const { 23 bool basic_op::has_return_to() const {
21 return !return_to.empty(); 24 return !return_to.empty();
22 } 25 }
23 const string& basic_op::get_return_to() const { 26 const string& basic_op::get_return_to() const {
24 if(return_to.empty()) 27 if(return_to.empty())
25 throw no_return_to(OPKELE_CP_ "No return_to URL provided with request"); 28 throw no_return_to(OPKELE_CP_ "No return_to URL provided with request");
26 return return_to; 29 return return_to;
27 } 30 }
28 31
29 const string& basic_op::get_realm() const { 32 const string& basic_op::get_realm() const {
30 assert(!realm.empty()); 33 assert(!realm.empty());
31 return realm; 34 return realm;
32 } 35 }
33 36
34 bool basic_op::has_identity() const { 37 bool basic_op::has_identity() const {
35 return !identity.empty(); 38 return !identity.empty();
36 } 39 }
37 const string& basic_op::get_claimed_id() const { 40 const string& basic_op::get_claimed_id() const {
38 if(claimed_id.empty()) 41 if(claimed_id.empty())
39 throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request"); 42 throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request");
40 assert(!identity.empty()); 43 assert(!identity.empty());
41 return claimed_id; 44 return claimed_id;
42 } 45 }
43 const string& basic_op::get_identity() const { 46 const string& basic_op::get_identity() const {
44 if(identity.empty()) 47 if(identity.empty())
45 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request"); 48 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request");
46 assert(!claimed_id.empty()); 49 assert(!claimed_id.empty());
47 return identity; 50 return identity;
48 } 51 }
49 52
50 bool basic_op::is_id_select() const { 53 bool basic_op::is_id_select() const {
51 return identity==IDURI_SELECT20; 54 return identity==IDURI_SELECT20;
52 } 55 }
53 56
54 void basic_op::select_identity(const string& c,const string& i) { 57 void basic_op::select_identity(const string& c,const string& i) {
55 claimed_id = c; identity = i; 58 claimed_id = c; identity = i;
56 } 59 }
57 void basic_op::set_claimed_id(const string& c) { 60 void basic_op::set_claimed_id(const string& c) {
58 claimed_id = c; 61 claimed_id = c;
59 } 62 }
@@ -272,49 +275,82 @@ namespace opkele {
272 bool o2; 275 bool o2;
273 try { 276 try {
274 o2 = (inm.get_field("ns")==OIURI_OPENID20); 277 o2 = (inm.get_field("ns")==OIURI_OPENID20);
275 }catch(failed_lookup&) { o2 = false; } 278 }catch(failed_lookup&) { o2 = false; }
276 string nonce; 279 string nonce;
277 if(o2) { 280 if(o2) {
278 try { 281 try {
279 if(!check_nonce(nonce = inm.get_field("response_nonce"))) 282 if(!check_nonce(nonce = inm.get_field("response_nonce")))
280 throw failed_check_authentication(OPKELE_CP_ "Invalid nonce"); 283 throw failed_check_authentication(OPKELE_CP_ "Invalid nonce");
281 }catch(failed_lookup&) { 284 }catch(failed_lookup&) {
282 throw failed_check_authentication(OPKELE_CP_ "No nonce provided with check_authentication request"); 285 throw failed_check_authentication(OPKELE_CP_ "No nonce provided with check_authentication request");
283 } 286 }
284 } 287 }
285 try { 288 try {
286 assoc = retrieve_assoc(inm.get_field("assoc_handle")); 289 assoc = retrieve_assoc(inm.get_field("assoc_handle"));
287 if(!assoc->stateless()) 290 if(!assoc->stateless())
288 throw failed_check_authentication(OPKELE_CP_ "Will not do check_authentication on a stateful handle"); 291 throw failed_check_authentication(OPKELE_CP_ "Will not do check_authentication on a stateful handle");
289 }catch(failed_lookup&) { 292 }catch(failed_lookup&) {
290 throw failed_check_authentication(OPKELE_CP_ "No assoc_handle or invalid assoc_handle specified with check_authentication request"); 293 throw failed_check_authentication(OPKELE_CP_ "No assoc_handle or invalid assoc_handle specified with check_authentication request");
291 } 294 }
292 static const string idresmode = "id_res"; 295 static const string idresmode = "id_res";
293 try { 296 try {
294 if(util::base64_signature(assoc,util::change_mode_message_proxy(inm,idresmode))!=inm.get_field("sig")) 297 if(util::base64_signature(assoc,util::change_mode_message_proxy(inm,idresmode))!=inm.get_field("sig"))
295 throw failed_check_authentication(OPKELE_CP_ "Signature mismatch"); 298 throw failed_check_authentication(OPKELE_CP_ "Signature mismatch");
296 }catch(failed_lookup&) { 299 }catch(failed_lookup&) {
297 throw failed_check_authentication(OPKELE_CP_ "failed to calculate signature"); 300 throw failed_check_authentication(OPKELE_CP_ "failed to calculate signature");
298 } 301 }
299 oum.set_field("is_valid","true"); 302 oum.set_field("is_valid","true");
300 try { 303 try {
301 string h = inm.get_field("invalidate_handle"); 304 string h = inm.get_field("invalidate_handle");
302 try { 305 try {
303 assoc_t ih = retrieve_assoc(h); 306 assoc_t ih = retrieve_assoc(h);
304 }catch(invalid_handle& ih) { 307 }catch(invalid_handle& ih) {
305 oum.set_field("invalidate_handle",h); 308 oum.set_field("invalidate_handle",h);
306 }catch(failed_lookup& ih) { 309 }catch(failed_lookup& ih) {
307 oum.set_field("invalidate_handle",h); 310 oum.set_field("invalidate_handle",h);
308 } 311 }
309 }catch(failed_lookup&) { } 312 }catch(failed_lookup&) { }
310 if(o2) { 313 if(o2) {
311 assert(!nonce.empty()); 314 assert(!nonce.empty());
312 invalidate_nonce(nonce); 315 invalidate_nonce(nonce);
313 } 316 }
314 return oum; 317 return oum;
315 }catch(failed_check_authentication& ) { 318 }catch(failed_check_authentication& ) {
316 oum.set_field("is_valid","false"); 319 oum.set_field("is_valid","false");
317 return oum; 320 return oum;
318 } 321 }
319 322
323 void basic_op::verify_return_to() {
324 string nrealm = opkele::util::rfc_3986_normalize_uri(realm);
325 if(nrealm.find('#')!=string::npos)
326 throw opkele::bad_realm(OPKELE_CP_ "authentication realm contains URI fragment");
327 string nrt = opkele::util::rfc_3986_normalize_uri(return_to);
328 string::size_type pr = nrealm.find("://");
329 string::size_type prt = nrt.find("://");
330 assert(!(pr==string::npos || prt==string::npos));
331 pr += sizeof("://")-1;
332 prt += sizeof("://")-1;
333 if(!strncmp(nrealm.c_str()+pr,"*.",2)) {
334 pr = nrealm.find('.',pr);
335 prt = nrt.find('.',prt);
336 assert(pr!=string::npos);
337 if(prt==string::npos)
338 throw bad_return_to(
339 OPKELE_CP_ "return_to URL doesn't match realm");
340 // TODO: check for overgeneralized realm
341 }
342 string::size_type lr = nrealm.length();
343 string::size_type lrt = nrt.length();
344 if( (lrt-prt) < (lr-pr) )
345 throw bad_return_to(
346 OPKELE_CP_ "return_to URL doesn't match realm");
347 pair<const char*,const char*> mp = mismatch(
348 nrealm.c_str()+pr,nrealm.c_str()+lr,
349 nrt.c_str()+prt);
350 if( (*(mp.first-1))!='/'
351 && !strchr("/?#",*mp.second) )
352 throw bad_return_to(
353 OPKELE_CP_ "return_to URL doesn't match realm");
354 }
355
320} 356}