summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2008-01-23 21:13:27 (UTC)
committer Michael Krelin <hacker@klever.net>2008-01-23 21:13:27 (UTC)
commitdc5dad0709ae8dd0a4be74248a22a78e47ba90e2 (patch) (unidiff)
treeeebd2a18bec33c4250036e1fd92d38cd4268777e
parent2a116bce75236e46946bb9564790c26c6a59b9a4 (diff)
downloadlibopkele-dc5dad0709ae8dd0a4be74248a22a78e47ba90e2.zip
libopkele-dc5dad0709ae8dd0a4be74248a22a78e47ba90e2.tar.gz
libopkele-dc5dad0709ae8dd0a4be74248a22a78e47ba90e2.tar.bz2
check associate reply for consistency
Reject associate replies returning secret of inconsistent with association type length. This way severely broken OPs which return SHA1 association as SHA256 will still work in dumb mode. Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--lib/basic_rp.cc9
1 files changed, 6 insertions, 3 deletions
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc
index 763a391..2da8416 100644
--- a/lib/basic_rp.cc
+++ b/lib/basic_rp.cc
@@ -1,311 +1,314 @@
1#include <openssl/sha.h> 1#include <openssl/sha.h>
2#include <openssl/hmac.h> 2#include <openssl/hmac.h>
3#include <opkele/basic_rp.h> 3#include <opkele/basic_rp.h>
4#include <opkele/exception.h> 4#include <opkele/exception.h>
5#include <opkele/uris.h> 5#include <opkele/uris.h>
6#include <opkele/data.h> 6#include <opkele/data.h>
7#include <opkele/util.h> 7#include <opkele/util.h>
8#include <opkele/curl.h> 8#include <opkele/curl.h>
9 9
10namespace opkele { 10namespace opkele {
11 11
12 static void dh_get_secret( 12 static void dh_get_secret(
13 secret_t& secret, const basic_openid_message& om, 13 secret_t& secret, const basic_openid_message& om,
14 const char *exp_assoc, const char *exp_sess, 14 const char *exp_assoc, const char *exp_sess,
15 util::dh_t& dh, 15 util::dh_t& dh,
16 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*) ) try { 16 size_t d_len, unsigned char *(*d_fun)(const unsigned char*,size_t,unsigned char*),
17 size_t exp_s_len) try {
17 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess) 18 if(om.get_field("assoc_type")!=exp_assoc || om.get_field("session_type")!=exp_sess)
18 throw bad_input(OPKELE_CP_ "Unexpected associate response"); 19 throw bad_input(OPKELE_CP_ "Unexpected associate response");
19 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public")); 20 util::bignum_t s_pub = util::base64_to_bignum(om.get_field("dh_server_public"));
20 vector<unsigned char> ck(DH_size(dh)+1); 21 vector<unsigned char> ck(DH_size(dh)+1);
21 unsigned char *ckptr = &(ck.front())+1; 22 unsigned char *ckptr = &(ck.front())+1;
22 int cklen = DH_compute_key(ckptr,s_pub,dh); 23 int cklen = DH_compute_key(ckptr,s_pub,dh);
23 if(cklen<0) 24 if(cklen<0)
24 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 25 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
25 if(cklen && (*ckptr)&0x80) { 26 if(cklen && (*ckptr)&0x80) {
26 (*(--ckptr))=0; ++cklen; } 27 (*(--ckptr))=0; ++cklen; }
27 unsigned char key_digest[d_len]; 28 unsigned char key_digest[d_len];
28 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key")); 29 secret.enxor_from_base64((*d_fun)(ckptr,cklen,key_digest),om.get_field("enc_mac_key"));
30 if(secret.size()!=exp_s_len)
31 throw bad_input(OPKELE_CP_ "Secret length isn't consistent with association type");
29 }catch(opkele::failed_lookup& ofl) { 32 }catch(opkele::failed_lookup& ofl) {
30 throw bad_input(OPKELE_CP_ "Incoherent response from OP"); 33 throw bad_input(OPKELE_CP_ "Incoherent response from OP");
31 } OPKELE_RETHROW 34 } OPKELE_RETHROW
32 35
33 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) { 36 static void direct_request(basic_openid_message& oum,const basic_openid_message& inm,const string& OP) {
34 util::curl_pick_t curl = util::curl_pick_t::easy_init(); 37 util::curl_pick_t curl = util::curl_pick_t::easy_init();
35 if(!curl) 38 if(!curl)
36 throw exception_curl(OPKELE_CP_ "failed to initialize curl"); 39 throw exception_curl(OPKELE_CP_ "failed to initialize curl");
37 string request = inm.query_string(); 40 string request = inm.query_string();
38 CURLcode r; 41 CURLcode r;
39 (r=curl.misc_sets()) 42 (r=curl.misc_sets())
40 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str())) 43 || (r=curl.easy_setopt(CURLOPT_URL,OP.c_str()))
41 || (r=curl.easy_setopt(CURLOPT_POST,1)) 44 || (r=curl.easy_setopt(CURLOPT_POST,1))
42 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data())) 45 || (r=curl.easy_setopt(CURLOPT_POSTFIELDS,request.data()))
43 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length())) 46 || (r=curl.easy_setopt(CURLOPT_POSTFIELDSIZE,request.length()))
44 || (r=curl.set_write()); 47 || (r=curl.set_write());
45 if(r) 48 if(r)
46 throw exception_curl(OPKELE_CP_ "failed to set curly options",r); 49 throw exception_curl(OPKELE_CP_ "failed to set curly options",r);
47 if( (r=curl.easy_perform()) ) 50 if( (r=curl.easy_perform()) )
48 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r); 51 throw exception_curl(OPKELE_CP_ "failed to perform curly request",r);
49 oum.from_keyvalues(curl.response); 52 oum.from_keyvalues(curl.response);
50 } 53 }
51 54
52 55
53 assoc_t basic_RP::associate(const string& OP) { 56 assoc_t basic_RP::associate(const string& OP) {
54 util::dh_t dh = DH_new(); 57 util::dh_t dh = DH_new();
55 if(!dh) 58 if(!dh)
56 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 59 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
57 dh->p = util::dec_to_bignum(data::_default_p); 60 dh->p = util::dec_to_bignum(data::_default_p);
58 dh->g = util::dec_to_bignum(data::_default_g); 61 dh->g = util::dec_to_bignum(data::_default_g);
59 if(!DH_generate_key(dh)) 62 if(!DH_generate_key(dh))
60 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 63 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
61 openid_message_t req; 64 openid_message_t req;
62 req.set_field("ns",OIURI_OPENID20); 65 req.set_field("ns",OIURI_OPENID20);
63 req.set_field("mode","associate"); 66 req.set_field("mode","associate");
64 req.set_field("dh_modulus",util::bignum_to_base64(dh->p)); 67 req.set_field("dh_modulus",util::bignum_to_base64(dh->p));
65 req.set_field("dh_gen",util::bignum_to_base64(dh->g)); 68 req.set_field("dh_gen",util::bignum_to_base64(dh->g));
66 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key)); 69 req.set_field("dh_consumer_public",util::bignum_to_base64(dh->pub_key));
67 openid_message_t res; 70 openid_message_t res;
68 req.set_field("assoc_type","HMAC-SHA256"); 71 req.set_field("assoc_type","HMAC-SHA256");
69 req.set_field("session_type","DH-SHA256"); 72 req.set_field("session_type","DH-SHA256");
70 secret_t secret; 73 secret_t secret;
71 int expires_in; 74 int expires_in;
72 try { 75 try {
73 direct_request(res,req,OP); 76 direct_request(res,req,OP);
74 dh_get_secret( secret, res, 77 dh_get_secret( secret, res,
75 "HMAC-SHA256", "DH-SHA256", 78 "HMAC-SHA256", "DH-SHA256",
76 dh, SHA256_DIGEST_LENGTH, SHA256 ); 79 dh, SHA256_DIGEST_LENGTH, SHA256, SHA256_DIGEST_LENGTH );
77 expires_in = util::string_to_long(res.get_field("expires_in")); 80 expires_in = util::string_to_long(res.get_field("expires_in"));
78 }catch(exception& e) { 81 }catch(exception& e) {
79 try { 82 try {
80 req.set_field("assoc_type","HMAC-SHA1"); 83 req.set_field("assoc_type","HMAC-SHA1");
81 req.set_field("session_type","DH-SHA1"); 84 req.set_field("session_type","DH-SHA1");
82 direct_request(res,req,OP); 85 direct_request(res,req,OP);
83 dh_get_secret( secret, res, 86 dh_get_secret( secret, res,
84 "HMAC-SHA1", "DH-SHA1", 87 "HMAC-SHA1", "DH-SHA1",
85 dh, SHA_DIGEST_LENGTH, SHA1 ); 88 dh, SHA_DIGEST_LENGTH, SHA1, SHA_DIGEST_LENGTH );
86 expires_in = util::string_to_long(res.get_field("expires_in")); 89 expires_in = util::string_to_long(res.get_field("expires_in"));
87 }catch(bad_input& e) { 90 }catch(bad_input& e) {
88 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association"); 91 throw dumb_RP(OPKELE_CP_ "OP failed to supply an association");
89 } 92 }
90 } 93 }
91 return store_assoc( 94 return store_assoc(
92 OP, res.get_field("assoc_handle"), 95 OP, res.get_field("assoc_handle"),
93 res.get_field("assoc_type"), secret, 96 res.get_field("assoc_type"), secret,
94 expires_in ); 97 expires_in );
95 } 98 }
96 99
97 basic_openid_message& basic_RP::checkid_( 100 basic_openid_message& basic_RP::checkid_(
98 basic_openid_message& rv, 101 basic_openid_message& rv,
99 mode_t mode, 102 mode_t mode,
100 const string& return_to,const string& realm, 103 const string& return_to,const string& realm,
101 extension_t *ext) { 104 extension_t *ext) {
102 rv.reset_fields(); 105 rv.reset_fields();
103 rv.set_field("ns",OIURI_OPENID20); 106 rv.set_field("ns",OIURI_OPENID20);
104 if(mode==mode_checkid_immediate) 107 if(mode==mode_checkid_immediate)
105 rv.set_field("mode","checkid_immediate"); 108 rv.set_field("mode","checkid_immediate");
106 else if(mode==mode_checkid_setup) 109 else if(mode==mode_checkid_setup)
107 rv.set_field("mode","checkid_setup"); 110 rv.set_field("mode","checkid_setup");
108 else 111 else
109 throw bad_input(OPKELE_CP_ "unknown checkid_* mode"); 112 throw bad_input(OPKELE_CP_ "unknown checkid_* mode");
110 if(realm.empty() && return_to.empty()) 113 if(realm.empty() && return_to.empty())
111 throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty"); 114 throw bad_input(OPKELE_CP_ "At least one of realm and return_to must be non-empty");
112 if(!realm.empty()) { 115 if(!realm.empty()) {
113 rv.set_field("realm",realm); 116 rv.set_field("realm",realm);
114 rv.set_field("trust_root",realm); 117 rv.set_field("trust_root",realm);
115 } 118 }
116 if(!return_to.empty()) 119 if(!return_to.empty())
117 rv.set_field("return_to",return_to); 120 rv.set_field("return_to",return_to);
118 const openid_endpoint_t& ep = get_endpoint(); 121 const openid_endpoint_t& ep = get_endpoint();
119 rv.set_field("claimed_id",ep.claimed_id); 122 rv.set_field("claimed_id",ep.claimed_id);
120 rv.set_field("identity",ep.local_id); 123 rv.set_field("identity",ep.local_id);
121 try { 124 try {
122 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle()); 125 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle());
123 }catch(dumb_RP& drp) { 126 }catch(dumb_RP& drp) {
124 }catch(failed_lookup& fl) { 127 }catch(failed_lookup& fl) {
125 try { 128 try {
126 rv.set_field("assoc_handle",associate(ep.uri)->handle()); 129 rv.set_field("assoc_handle",associate(ep.uri)->handle());
127 }catch(dumb_RP& drp) { } 130 }catch(dumb_RP& drp) { }
128 } OPKELE_RETHROW 131 } OPKELE_RETHROW
129 if(ext) ext->checkid_hook(rv); 132 if(ext) ext->checkid_hook(rv);
130 return rv; 133 return rv;
131 } 134 }
132 135
133 class signed_part_message_proxy : public basic_openid_message { 136 class signed_part_message_proxy : public basic_openid_message {
134 public: 137 public:
135 const basic_openid_message& x; 138 const basic_openid_message& x;
136 set<string> signeds; 139 set<string> signeds;
137 140
138 signed_part_message_proxy(const basic_openid_message& xx) : x(xx) { 141 signed_part_message_proxy(const basic_openid_message& xx) : x(xx) {
139 const string& slist = x.get_field("signed"); 142 const string& slist = x.get_field("signed");
140 string::size_type p = 0; 143 string::size_type p = 0;
141 while(true) { 144 while(true) {
142 string::size_type co = slist.find(',',p); 145 string::size_type co = slist.find(',',p);
143 string f = (co==string::npos) 146 string f = (co==string::npos)
144 ?slist.substr(p):slist.substr(p,co-p); 147 ?slist.substr(p):slist.substr(p,co-p);
145 signeds.insert(f); 148 signeds.insert(f);
146 if(co==string::npos) break; 149 if(co==string::npos) break;
147 p = co+1; 150 p = co+1;
148 } 151 }
149 } 152 }
150 153
151 bool has_field(const string& n) const { 154 bool has_field(const string& n) const {
152 return signeds.find(n)!=signeds.end() && x.has_field(n); } 155 return signeds.find(n)!=signeds.end() && x.has_field(n); }
153 const string& get_field(const string& n) const { 156 const string& get_field(const string& n) const {
154 if(signeds.find(n)==signeds.end()) 157 if(signeds.find(n)==signeds.end())
155 throw failed_lookup(OPKELE_CP_ "The field isn't known to be signed"); 158 throw failed_lookup(OPKELE_CP_ "The field isn't known to be signed");
156 return x.get_field(n); } 159 return x.get_field(n); }
157 160
158 fields_iterator fields_begin() const { 161 fields_iterator fields_begin() const {
159 return signeds.begin(); } 162 return signeds.begin(); }
160 fields_iterator fields_end() const { 163 fields_iterator fields_end() const {
161 return signeds.end(); } 164 return signeds.end(); }
162 }; 165 };
163 166
164 static void parse_query(const string& u,string::size_type q, 167 static void parse_query(const string& u,string::size_type q,
165 map<string,string>& p) { 168 map<string,string>& p) {
166 if(q==string::npos) 169 if(q==string::npos)
167 return; 170 return;
168 assert(u[q]=='?'); 171 assert(u[q]=='?');
169 ++q; 172 ++q;
170 string::size_type l = u.size(); 173 string::size_type l = u.size();
171 while(q<l) { 174 while(q<l) {
172 string::size_type eq = u.find('=',q); 175 string::size_type eq = u.find('=',q);
173 string::size_type am = u.find('&',q); 176 string::size_type am = u.find('&',q);
174 if(am==string::npos) { 177 if(am==string::npos) {
175 if(eq==string::npos) { 178 if(eq==string::npos) {
176 p[""] = u.substr(q); 179 p[""] = u.substr(q);
177 }else{ 180 }else{
178 p[u.substr(q,eq-q)] = u.substr(eq+1); 181 p[u.substr(q,eq-q)] = u.substr(eq+1);
179 } 182 }
180 break; 183 break;
181 }else{ 184 }else{
182 if(eq==string::npos || eq>am) { 185 if(eq==string::npos || eq>am) {
183 p[""] = u.substr(q,eq-q); 186 p[""] = u.substr(q,eq-q);
184 }else{ 187 }else{
185 p[u.substr(q,eq-q)] = u.substr(eq+1,am-eq-1); 188 p[u.substr(q,eq-q)] = u.substr(eq+1,am-eq-1);
186 } 189 }
187 q = ++am; 190 q = ++am;
188 } 191 }
189 } 192 }
190 } 193 }
191 194
192 void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) { 195 void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) {
193 bool o2 = om.has_field("ns") 196 bool o2 = om.has_field("ns")
194 && om.get_field("ns")==OIURI_OPENID20; 197 && om.get_field("ns")==OIURI_OPENID20;
195 if( (!o2) && om.has_field("user_setup_url")) 198 if( (!o2) && om.has_field("user_setup_url"))
196 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided", 199 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided",
197 om.get_field("user_setup_url")); 200 om.get_field("user_setup_url"));
198 string m = om.get_field("mode"); 201 string m = om.get_field("mode");
199 if(o2 && m=="setup_needed") 202 if(o2 && m=="setup_needed")
200 throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided"); 203 throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided");
201 if(m=="cancel") 204 if(m=="cancel")
202 throw id_res_cancel(OPKELE_CP_ "authentication cancelled"); 205 throw id_res_cancel(OPKELE_CP_ "authentication cancelled");
203 bool go_dumb=false; 206 bool go_dumb=false;
204 try { 207 try {
205 string OP = o2 208 string OP = o2
206 ?om.get_field("op_endpoint") 209 ?om.get_field("op_endpoint")
207 :get_endpoint().uri; 210 :get_endpoint().uri;
208 assoc_t assoc = retrieve_assoc( 211 assoc_t assoc = retrieve_assoc(
209 OP,om.get_field("assoc_handle")); 212 OP,om.get_field("assoc_handle"));
210 if(om.get_field("sig")!=util::base64_signature(assoc,om)) 213 if(om.get_field("sig")!=util::base64_signature(assoc,om))
211 throw id_res_mismatch(OPKELE_CP_ "signature mismatch"); 214 throw id_res_mismatch(OPKELE_CP_ "signature mismatch");
212 }catch(dumb_RP& drp) { 215 }catch(dumb_RP& drp) {
213 go_dumb=true; 216 go_dumb=true;
214 }catch(failed_lookup& e) { 217 }catch(failed_lookup& e) {
215 go_dumb=true; 218 go_dumb=true;
216 } OPKELE_RETHROW 219 } OPKELE_RETHROW
217 if(go_dumb) { 220 if(go_dumb) {
218 try { 221 try {
219 string OP = o2 222 string OP = o2
220 ?om.get_field("op_endpoint") 223 ?om.get_field("op_endpoint")
221 :get_endpoint().uri; 224 :get_endpoint().uri;
222 check_authentication(OP,om); 225 check_authentication(OP,om);
223 }catch(failed_check_authentication& fca) { 226 }catch(failed_check_authentication& fca) {
224 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()"); 227 throw id_res_failed(OPKELE_CP_ "failed to check_authentication()");
225 } OPKELE_RETHROW 228 } OPKELE_RETHROW
226 } 229 }
227 signed_part_message_proxy signeds(om); 230 signed_part_message_proxy signeds(om);
228 if(o2) { 231 if(o2) {
229 check_nonce(om.get_field("op_endpoint"), 232 check_nonce(om.get_field("op_endpoint"),
230 om.get_field("response_nonce")); 233 om.get_field("response_nonce"));
231 static const char *mustsign[] = { 234 static const char *mustsign[] = {
232 "op_endpoint", "return_to", "response_nonce", "assoc_handle", 235 "op_endpoint", "return_to", "response_nonce", "assoc_handle",
233 "claimed_id", "identity" }; 236 "claimed_id", "identity" };
234 for(int ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) { 237 for(int ms=0;ms<(sizeof(mustsign)/sizeof(*mustsign));++ms) {
235 if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms])) 238 if(om.has_field(mustsign[ms]) && !signeds.has_field(mustsign[ms]))
236 throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs"); 239 throw bad_input(OPKELE_CP_ string("Field '")+mustsign[ms]+"' is not signed against the specs");
237 } 240 }
238 if( ( 241 if( (
239 (om.has_field("claimed_id")?1:0) 242 (om.has_field("claimed_id")?1:0)
240 ^ 243 ^
241 (om.has_field("identity")?1:0) 244 (om.has_field("identity")?1:0)
242 )&1 ) 245 )&1 )
243 throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent"); 246 throw bad_input(OPKELE_CP_ "claimed_id and identity must be either both present or both absent");
244 247
245 string turl = util::rfc_3986_normalize_uri(get_this_url()); 248 string turl = util::rfc_3986_normalize_uri(get_this_url());
246 util::strip_uri_fragment_part(turl); 249 util::strip_uri_fragment_part(turl);
247 string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to")); 250 string rurl = util::rfc_3986_normalize_uri(om.get_field("return_to"));
248 util::strip_uri_fragment_part(rurl); 251 util::strip_uri_fragment_part(rurl);
249 string::size_type 252 string::size_type
250 tq = turl.find('?'), rq = rurl.find('?'); 253 tq = turl.find('?'), rq = rurl.find('?');
251 if( 254 if(
252 ((tq==string::npos)?turl:turl.substr(0,tq)) 255 ((tq==string::npos)?turl:turl.substr(0,tq))
253 != 256 !=
254 ((rq==string::npos)?rurl:rurl.substr(0,rq)) 257 ((rq==string::npos)?rurl:rurl.substr(0,rq))
255 ) 258 )
256 throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url"); 259 throw id_res_bad_return_to(OPKELE_CP_ "return_to url doesn't match request url");
257 map<string,string> tp; parse_query(turl,tq,tp); 260 map<string,string> tp; parse_query(turl,tq,tp);
258 map<string,string> rp; parse_query(rurl,rq,rp); 261 map<string,string> rp; parse_query(rurl,rq,rp);
259 for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) { 262 for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) {
260 map<string,string>::const_iterator tpi = tp.find(rpi->first); 263 map<string,string>::const_iterator tpi = tp.find(rpi->first);
261 if(tpi==tp.end()) 264 if(tpi==tp.end())
262 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request"); 265 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request");
263 if(tpi->second!=rpi->second) 266 if(tpi->second!=rpi->second)
264 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request"); 267 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request");
265 } 268 }
266 269
267 if(om.has_field("claimed_id")) { 270 if(om.has_field("claimed_id")) {
268 verify_OP( 271 verify_OP(
269 om.get_field("op_endpoint"), 272 om.get_field("op_endpoint"),
270 om.get_field("claimed_id"), 273 om.get_field("claimed_id"),
271 om.get_field("identity") ); 274 om.get_field("identity") );
272 } 275 }
273 276
274 } 277 }
275 if(ext) ext->id_res_hook(om,signeds); 278 if(ext) ext->id_res_hook(om,signeds);
276 } 279 }
277 280
278 class check_auth_message_proxy : public basic_openid_message { 281 class check_auth_message_proxy : public basic_openid_message {
279 public: 282 public:
280 const basic_openid_message& x; 283 const basic_openid_message& x;
281 284
282 check_auth_message_proxy(const basic_openid_message& xx) : x(xx) { } 285 check_auth_message_proxy(const basic_openid_message& xx) : x(xx) { }
283 286
284 bool has_field(const string& n) const { return x.has_field(n); } 287 bool has_field(const string& n) const { return x.has_field(n); }
285 const string& get_field(const string& n) const { 288 const string& get_field(const string& n) const {
286 static const string checkauthmode="check_authentication"; 289 static const string checkauthmode="check_authentication";
287 return (n=="mode")?checkauthmode:x.get_field(n); } 290 return (n=="mode")?checkauthmode:x.get_field(n); }
288 bool has_ns(const string& uri) const {return x.has_ns(uri); } 291 bool has_ns(const string& uri) const {return x.has_ns(uri); }
289 string get_ns(const string& uri) const { return x.get_ns(uri); } 292 string get_ns(const string& uri) const { return x.get_ns(uri); }
290 fields_iterator fields_begin() const { 293 fields_iterator fields_begin() const {
291 return x.fields_begin(); } 294 return x.fields_begin(); }
292 fields_iterator fields_end() const { 295 fields_iterator fields_end() const {
293 return x.fields_end(); } 296 return x.fields_end(); }
294 }; 297 };
295 298
296 void basic_RP::check_authentication(const string& OP, 299 void basic_RP::check_authentication(const string& OP,
297 const basic_openid_message& om){ 300 const basic_openid_message& om){
298 openid_message_t res; 301 openid_message_t res;
299 direct_request(res,check_auth_message_proxy(om),OP); 302 direct_request(res,check_auth_message_proxy(om),OP);
300 if(res.has_field("is_valid")) { 303 if(res.has_field("is_valid")) {
301 if(res.get_field("is_valid")=="true") { 304 if(res.get_field("is_valid")=="true") {
302 if(res.has_field("invalidate_handle")) 305 if(res.has_field("invalidate_handle"))
303 invalidate_assoc(OP,res.get_field("invalidate_handle")); 306 invalidate_assoc(OP,res.get_field("invalidate_handle"));
304 return; 307 return;
305 } 308 }
306 } 309 }
307 throw failed_check_authentication( 310 throw failed_check_authentication(
308 OPKELE_CP_ "failed to verify response"); 311 OPKELE_CP_ "failed to verify response");
309 } 312 }
310 313
311} 314}