summaryrefslogtreecommitdiffabout
path: root/lib/basic_rp.cc
Unidiff
Diffstat (limited to 'lib/basic_rp.cc') (more/less context) (ignore 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,300 +1,325 @@
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
38 57
39 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) { 58 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) {
40 util::curl_pick_t curl = util::curl_pick_t::easy_init(); 59 util::curl_pick_t curl = util::curl_pick_t::easy_init();
41 if(!curl) 60 if(!curl)
42 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 61 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
43 string request = inm.query_string(); 62 string request = inm.query_string();
44 CURLcode r; 63 CURLcode r;
45 (r=curl.misc_sets()) 64 (r=curl.misc_sets())
46 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str())) 65 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str()))
47 || (r=curl.easy_setopt(CURLOPT_POST,1)) 66 || (r=curl.easy_setopt(CURLOPT_POST,1))
48 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 67 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
49 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 68 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
50 || (r=curl.set_write()); 69 || (r=curl.set_write());
51 if(r) 70 if(r)
52 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 71 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
53 if( (r=curl.easy_perform()) ) 72 if( (r=curl.easy_perform()) )
54 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 73 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
55 oum.from_keyvalues(curl.response); 74 oum.from_keyvalues(curl.response);
56 } 75 }
57 76
58 77
59 assoc_t basic_RP::associate(const string& OP) { 78 assoc_t basic_RP::associate(const string& OP) {
60 util::dh_t dh = DH_new(); 79 util::dh_t dh = DH_new();
61 if(!dh) 80 if(!dh)
62 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 81 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
63 dh->p = util::dec_to_bignum(data::_default_p); 82 dh->p = util::dec_to_bignum(data::_default_p);
64 dh->g = util::dec_to_bignum(data::_default_g); 83 dh->g = util::dec_to_bignum(data::_default_g);
65 if(!DH_generate_key(dh)) 84 if(!DH_generate_key(dh))
66 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 85 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
67 openid_message_t req; 86 openid_message_t req;
68 req.set_field("ns",OIURI_OPENID20); 87 req.set_field("ns",OIURI_OPENID20);
69 req.set_field("mode","associate"); 88 req.set_field("mode","associate");
70 req.set_field("dh_modulus",util::bignum_to_base64(dh->p)); 89 req.set_field("dh_modulus",util::bignum_to_base64(dh->p));
71 req.set_field("dh_gen",util::bignum_to_base64(dh->g)); 90 req.set_field("dh_gen",util::bignum_to_base64(dh->g));
72 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key)); 91 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key));
73 openid_message_t res; 92 openid_message_t res;
74 req.set_field("assoc_type","HMAC-SHA256"); 93 req.set_field("assoc_type","HMAC-SHA256");
75 req.set_field("session_type","DH-SHA256"); 94 req.set_field("session_type","DH-SHA256");
76 secret_t secret; 95 secret_t secret;
77 int expires_in; 96 int expires_in;
78 try { 97 try {
79 direct_request(res,req,OP); 98 direct_request(res,req,OP);
80 dh_get_secret( secret, res, 99 dh_get_secret( secret, res,
81 "HMAC-SHA256", "DH-SHA256", 100 "HMAC-SHA256", "DH-SHA256",
82 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH ); 101 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH );
83 expires_in = util::string_to_long(res.get_field("expires_in")); 102 expires_in = util::string_to_long(res.get_field("expires_in"));
84 }catch(exception&) { 103 }catch(exception&) {
85 try { 104 try {
86 req.set_field("assoc_type","HMAC-SHA1"); 105 req.set_field("assoc_type","HMAC-SHA1");
87 req.set_field("session_type","DH-SHA1"); 106 req.set_field("session_type","DH-SHA1");
88 direct_request(res,req,OP); 107 direct_request(res,req,OP);
89 dh_get_secret( secret, res, 108 dh_get_secret( secret, res,
90 "HMAC-SHA1", "DH-SHA1", 109 "HMAC-SHA1", "DH-SHA1",
91 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH ); 110 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH );
92 expires_in = util::string_to_long(res.get_field("expires_in")); 111 expires_in = util::string_to_long(res.get_field("expires_in"));
93 }catch(bad_input&) { 112 }catch(bad_input&) {
94 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association"); 113 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association");
95 } 114 }
96 } 115 }
97 return store_assoc( 116 return store_assoc(
98 OP, res.get_field("assoc_handle"), 117 OP, res.get_field("assoc_handle"),
99 res.get_field("assoc_type"), secret, 118 res.get_field("assoc_type"), secret,
100 expires_in ); 119 expires_in );
101 } 120 }
102 121
103 basic_openid_message& basic_RP::checkid_( 122 basic_openid_message& basic_RP::checkid_(
104 basic_openid_message& rv, 123 basic_openid_message& rv,
105 mode_t mode, 124 mode_t mode,
106 const string& return_to,const string& realm, 125 const string& return_to,const string& realm,
107 extension_t *ext) { 126 extension_t *ext) {
108 rv.reset_fields(); 127 rv.reset_fields();
109 rv.set_field("ns",OIURI_OPENID20); 128 rv.set_field("ns",OIURI_OPENID20);
110 if(mode==mode_checkid_immediate) 129 if(mode==mode_checkid_immediate)
111 rv.set_field("mode","checkid_immediate"); 130 rv.set_field("mode","checkid_immediate");
112 else if(mode==mode_checkid_setup) 131 else if(mode==mode_checkid_setup)
113 rv.set_field("mode","checkid_setup"); 132 rv.set_field("mode","checkid_setup");
114 else 133 else
115 throw bad_input(OPKELE_CP_ "unknown checkid_* mode"); 134 throw bad_input(OPKELE_CP_ "unknown checkid_* mode");
116 if(realm.empty() && return_to.empty()) 135 if(realm.empty() && return_to.empty())
117 throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty"); 136 throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty");
118 if(!realm.empty()) { 137 if(!realm.empty()) {
119 rv.set_field("realm",realm); 138 rv.set_field("realm",realm);
120 rv.set_field("trust_root",realm); 139 rv.set_field("trust_root",realm);
121 } 140 }
122 if(!return_to.empty()) 141 if(!return_to.empty())
123 rv.set_field("return_to",return_to); 142 rv.set_field("return_to",return_to);
124 const openid_endpoint_t& ep = get_endpoint(); 143 const openid_endpoint_t& ep = get_endpoint();
125 rv.set_field("claimed_id",ep.claimed_id); 144 rv.set_field("claimed_id",ep.claimed_id);
126 rv.set_field("identity",ep.local_id); 145 rv.set_field("identity",ep.local_id);
127 try { 146 try {
128 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle()); 147 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle());
129 }catch(dumb_RP& drp) { 148 }catch(dumb_RP& drp) {
130 }catch(failed_lookup& fl) { 149 }catch(failed_lookup& fl) {
131 try { 150 try {
132 rv.set_field("assoc_handle",associate(ep.uri)->handle()); 151 rv.set_field("assoc_handle",associate(ep.uri)->handle());
133 }catch(dumb_RP& drp) { } 152 }catch(dumb_RP& drp) { }
134 } OPKELE_RETHROW 153 } OPKELE_RETHROW
135 if(ext) ext->rp_checkid_hook(rv); 154 if(ext) ext->rp_checkid_hook(rv);
136 return rv; 155 return rv;
137 } 156 }
138 157
139 class signed_part_message_proxy : public basic_openid_message { 158 class signed_part_message_proxy : public basic_openid_message {
140 public: 159 public:
141 const basic_openid_message& x; 160 const basic_openid_message& x;
142 set<string> signeds; 161 set<string> signeds;
143 162
144 signed_part_message_proxy(const basic_openid_message& xx) : x(xx) { 163 signed_part_message_proxy(const basic_openid_message& xx) : x(xx) {
145 const string& slist = x.get_field("signed"); 164 const string& slist = x.get_field("signed");
146 string::size_type p = 0; 165 string::size_type p = 0;
147 while(true) { 166 while(true) {
148 string::size_type co = slist.find(',',p); 167 string::size_type co = slist.find(',',p);
149 string f = (co==string::npos) 168 string f = (co==string::npos)
150 ?slist.substr(p):slist.substr(p,co-p); 169 ?slist.substr(p):slist.substr(p,co-p);
151 signeds.insert(f); 170 signeds.insert(f);
152 if(co==string::npos) break; 171 if(co==string::npos) break;
153 p = co+1; 172 p = co+1;
154 } 173 }
155 } 174 }
156 175
157 bool has_field(const string& n) const { 176 bool has_field(const string& n) const {
158 return signeds.find(n)!=signeds.end() && x.has_field(n); } 177 return signeds.find(n)!=signeds.end() && x.has_field(n); }
159 const string& get_field(const string& n) const { 178 const string& get_field(const string& n) const {
160 if(signeds.find(n)==signeds.end()) 179 if(signeds.find(n)==signeds.end())
161 throw failed_lookup(OPKELE_CP_ "The field isn't known to be signed"); 180 throw failed_lookup(OPKELE_CP_ "The field isn't known to be signed");
162 return x.get_field(n); } 181 return x.get_field(n); }
163 182
164 fields_iterator fields_begin() const { 183 fields_iterator fields_begin() const {
165 return signeds.begin(); } 184 return signeds.begin(); }
166 fields_iterator fields_end() const { 185 fields_iterator fields_end() const {
167 return signeds.end(); } 186 return signeds.end(); }
168 }; 187 };
169 188
170 static void parse_query(const string& u,string::size_type q, 189 static void parse_query(const string& u,string::size_type q,
171 map<string,string>& p) { 190 map<string,string>& p) {
172 if(q==string::npos) 191 if(q==string::npos)
173 return; 192 return;
174 assert(u[q]=='?'); 193 assert(u[q]=='?');
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
223 if(go_dumb) { 243 if(go_dumb) {
224 try { 244 try {
225 string OP = o2 245 string OP = o2
226 ?om.get_field("op_endpoint") 246 ?om.get_field("op_endpoint")
227 :get_endpoint().uri; 247 :get_endpoint().uri;
228 check_authentication(OP,om); 248 check_authentication(OP,om);
229 }catch(failed_check_authentication& fca) { 249 }catch(failed_check_authentication& fca) {
230 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()"); 250 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()");
231 } OPKELE_RETHROW 251 } OPKELE_RETHROW
232 } 252 }
233 signed_part_message_proxy signeds(om); 253 signed_part_message_proxy signeds(om);
234 if(o2) { 254 if(o2) {
235 check_nonce(om.get_field("op_endpoint"), 255 check_nonce(om.get_field("op_endpoint"),
236 om.get_field("response_nonce")); 256 om.get_field("response_nonce"));
237 static const char *mustsign[] = { 257 static const char *mustsign[] = {
238 "op_endpoint", "return_to", "response_nonce", "assoc_handle", 258 "op_endpoint", "return_to", "response_nonce", "assoc_handle",
239 "claimed_id", "identity" }; 259 "claimed_id", "identity" };
240 for(size_t ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) { 260 for(size_t ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) {
241 if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms])) 261 if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms]))
242 throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs"); 262 throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs");
243 } 263 }
244 if( ( 264 if( (
245 (om.has_field("claimed_id")?1:0) 265 (om.has_field("claimed_id")?1:0)
246 ^ 266 ^
247 (om.has_field("identity")?1:0) 267 (om.has_field("identity")?1:0)
248 )&1 ) 268 )&1 )
249 throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent"); 269 throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent");
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}