summaryrefslogtreecommitdiffabout
path: root/lib
Unidiff
Diffstat (limited to 'lib') (more/less context) (show whitespace changes)
-rw-r--r--lib/basic_op.cc29
-rw-r--r--lib/basic_rp.cc10
-rw-r--r--lib/discovery.cc2
-rw-r--r--lib/expat.cc1
-rw-r--r--lib/extension.cc2
-rw-r--r--lib/openid_message.cc32
-rw-r--r--lib/prequeue_rp.cc4
-rw-r--r--lib/sreg.cc6
-rw-r--r--lib/verify_op.cc4
9 files changed, 44 insertions, 46 deletions
diff --git a/lib/basic_op.cc b/lib/basic_op.cc
index 18446dc..2d82147 100644
--- a/lib/basic_op.cc
+++ b/lib/basic_op.cc
@@ -21,168 +21,165 @@ namespace opkele {
21 return !return_to.empty(); 21 return !return_to.empty();
22 } 22 }
23 const string& basic_OP::get_return_to() const { 23 const string& basic_OP::get_return_to() const {
24 if(return_to.empty()) 24 if(return_to.empty())
25 throw no_return_to(OPKELE_CP_ "No return_to URL provided with request"); 25 throw no_return_to(OPKELE_CP_ "No return_to URL provided with request");
26 return return_to; 26 return return_to;
27 } 27 }
28 28
29 const string& basic_OP::get_realm() const { 29 const string& basic_OP::get_realm() const {
30 assert(!realm.empty()); 30 assert(!realm.empty());
31 return realm; 31 return realm;
32 } 32 }
33 33
34 bool basic_OP::has_identity() const { 34 bool basic_OP::has_identity() const {
35 return !identity.empty(); 35 return !identity.empty();
36 } 36 }
37 const string& basic_OP::get_claimed_id() const { 37 const string& basic_OP::get_claimed_id() const {
38 if(claimed_id.empty()) 38 if(claimed_id.empty())
39 throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request"); 39 throw non_identity(OPKELE_CP_ "attempting to retrieve claimed_id of non-identity related request");
40 assert(!identity.empty()); 40 assert(!identity.empty());
41 return claimed_id; 41 return claimed_id;
42 } 42 }
43 const string& basic_OP::get_identity() const { 43 const string& basic_OP::get_identity() const {
44 if(identity.empty()) 44 if(identity.empty())
45 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request"); 45 throw non_identity(OPKELE_CP_ "attempting to retrieve identity of non-identity related request");
46 assert(!claimed_id.empty()); 46 assert(!claimed_id.empty());
47 return identity; 47 return identity;
48 } 48 }
49 49
50 bool basic_OP::is_id_select() const { 50 bool basic_OP::is_id_select() const {
51 return identity==IDURI_SELECT20; 51 return identity==IDURI_SELECT20;
52 } 52 }
53 53
54 void basic_OP::select_identity(const string& c,const string& i) { 54 void basic_OP::select_identity(const string& c,const string& i) {
55 claimed_id = c; identity = i; 55 claimed_id = c; identity = i;
56 } 56 }
57 void basic_OP::set_claimed_id(const string& c) { 57 void basic_OP::set_claimed_id(const string& c) {
58 claimed_id = c; 58 claimed_id = c;
59 } 59 }
60 60
61 basic_openid_message& basic_OP::associate( 61 basic_openid_message& basic_OP::associate(
62 basic_openid_message& oum, 62 basic_openid_message& oum,
63 const basic_openid_message& inm) try { 63 const basic_openid_message& inm) try {
64 assert(inm.get_field("mode")=="associate"); 64 assert(inm.get_field("mode")=="associate");
65 util::dh_t dh; 65 util::dh_t dh;
66 util::bignum_t c_pub; 66 util::bignum_t c_pub;
67 unsigned char key_digest[SHA256_DIGEST_LENGTH]; 67 unsigned char key_digest[SHA256_DIGEST_LENGTH];
68 size_t d_len = 0; 68 size_t d_len = 0;
69 enum {
70 sess_cleartext, sess_dh_sha1, sess_dh_sha256
71 } st = sess_cleartext;
72 string sts = inm.get_field("session_type"); 69 string sts = inm.get_field("session_type");
73 string ats = inm.get_field("assoc_type"); 70 string ats = inm.get_field("assoc_type");
74 if(sts=="DH-SHA1" || sts=="DH-SHA256") { 71 if(sts=="DH-SHA1" || sts=="DH-SHA256") {
75 if(!(dh = DH_new())) 72 if(!(dh = DH_new()))
76 throw exception_openssl(OPKELE_CP_ "failed to DH_new()"); 73 throw exception_openssl(OPKELE_CP_ "failed to DH_new()");
77 c_pub = util::base64_to_bignum(inm.get_field("dh_consumer_public")); 74 c_pub = util::base64_to_bignum(inm.get_field("dh_consumer_public"));
78 try { dh->p = util::base64_to_bignum(inm.get_field("dh_modulus")); 75 try { dh->p = util::base64_to_bignum(inm.get_field("dh_modulus"));
79 }catch(failed_lookup&) { 76 }catch(failed_lookup&) {
80 dh->p = util::dec_to_bignum(data::_default_p); } 77 dh->p = util::dec_to_bignum(data::_default_p); }
81 try { dh->g = util::base64_to_bignum(inm.get_field("dh_gen")); 78 try { dh->g = util::base64_to_bignum(inm.get_field("dh_gen"));
82 }catch(failed_lookup&) { 79 }catch(failed_lookup&) {
83 dh->g = util::dec_to_bignum(data::_default_g); } 80 dh->g = util::dec_to_bignum(data::_default_g); }
84 if(!DH_generate_key(dh)) 81 if(!DH_generate_key(dh))
85 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()"); 82 throw exception_openssl(OPKELE_CP_ "failed to DH_generate_key()");
86 vector<unsigned char> ck(DH_size(dh)+1); 83 vector<unsigned char> ck(DH_size(dh)+1);
87 unsigned char *ckptr = &(ck.front())+1; 84 unsigned char *ckptr = &(ck.front())+1;
88 int cklen = DH_compute_key(ckptr,c_pub,dh); 85 int cklen = DH_compute_key(ckptr,c_pub,dh);
89 if(cklen<0) 86 if(cklen<0)
90 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()"); 87 throw exception_openssl(OPKELE_CP_ "failed to DH_compute_key()");
91 if(cklen && (*ckptr)&0x80) { 88 if(cklen && (*ckptr)&0x80) {
92 (*(--ckptr)) = 0; ++cklen; } 89 (*(--ckptr)) = 0; ++cklen; }
93 if(sts=="DH-SHA1") { 90 if(sts=="DH-SHA1") {
94 SHA1(ckptr,cklen,key_digest); d_len = SHA_DIGEST_LENGTH; 91 SHA1(ckptr,cklen,key_digest); d_len = SHA_DIGEST_LENGTH;
95 }else if(sts=="DH-SHA256") { 92 }else if(sts=="DH-SHA256") {
96 SHA256(ckptr,cklen,key_digest); d_len = SHA256_DIGEST_LENGTH; 93 SHA256(ckptr,cklen,key_digest); d_len = SHA256_DIGEST_LENGTH;
97 }else 94 }else
98 throw internal_error(OPKELE_CP_ "I thought I knew the session type"); 95 throw internal_error(OPKELE_CP_ "I thought I knew the session type");
99 }else 96 }else
100 throw unsupported(OPKELE_CP_ "Unsupported session_type"); 97 throw unsupported(OPKELE_CP_ "Unsupported session_type");
101 assoc_t assoc; 98 assoc_t a;
102 if(ats=="HMAC-SHA1") 99 if(ats=="HMAC-SHA1")
103 assoc = alloc_assoc(ats,SHA_DIGEST_LENGTH,true); 100 a = alloc_assoc(ats,SHA_DIGEST_LENGTH,true);
104 else if(ats=="HMAC-SHA256") 101 else if(ats=="HMAC-SHA256")
105 assoc = alloc_assoc(ats,SHA256_DIGEST_LENGTH,true); 102 a = alloc_assoc(ats,SHA256_DIGEST_LENGTH,true);
106 else 103 else
107 throw unsupported(OPKELE_CP_ "Unsupported assoc_type"); 104 throw unsupported(OPKELE_CP_ "Unsupported assoc_type");
108 oum.reset_fields(); 105 oum.reset_fields();
109 oum.set_field("ns",OIURI_OPENID20); 106 oum.set_field("ns",OIURI_OPENID20);
110 oum.set_field("assoc_type",assoc->assoc_type()); 107 oum.set_field("assoc_type",a->assoc_type());
111 oum.set_field("assoc_handle",assoc->handle()); 108 oum.set_field("assoc_handle",a->handle());
112 oum.set_field("expires_in",util::long_to_string(assoc->expires_in())); 109 oum.set_field("expires_in",util::long_to_string(assoc->expires_in()));
113 secret_t secret = assoc->secret(); 110 secret_t secret = a->secret();
114 if(sts=="DH-SHA1" || sts=="DH-SHA256") { 111 if(sts=="DH-SHA1" || sts=="DH-SHA256") {
115 if(d_len != secret.size()) 112 if(d_len != secret.size())
116 throw bad_input(OPKELE_CP_ "Association secret and session MAC are not of the same size"); 113 throw bad_input(OPKELE_CP_ "Association secret and session MAC are not of the same size");
117 oum.set_field("session_type",sts); 114 oum.set_field("session_type",sts);
118 oum.set_field("dh_server_public",util::bignum_to_base64(dh->pub_key)); 115 oum.set_field("dh_server_public",util::bignum_to_base64(dh->pub_key));
119 string b64; secret.enxor_to_base64(key_digest,b64); 116 string b64; secret.enxor_to_base64(key_digest,b64);
120 oum.set_field("enc_mac_key",b64); 117 oum.set_field("enc_mac_key",b64);
121 }else /* TODO: support cleartext over encrypted connection */ 118 }else /* TODO: support cleartext over encrypted connection */
122 throw unsupported(OPKELE_CP_ "Unsupported session type"); 119 throw unsupported(OPKELE_CP_ "Unsupported session type");
123 return oum; 120 return oum;
124 } catch(unsupported& u) { 121 } catch(unsupported& u) {
125 oum.reset_fields(); 122 oum.reset_fields();
126 oum.set_field("ns",OIURI_OPENID20); 123 oum.set_field("ns",OIURI_OPENID20);
127 oum.set_field("error",u.what()); 124 oum.set_field("error",u.what());
128 oum.set_field("error_code","unsupported-type"); 125 oum.set_field("error_code","unsupported-type");
129 oum.set_field("session_type","DH-SHA256"); 126 oum.set_field("session_type","DH-SHA256");
130 oum.set_field("assoc_type","HMAC-SHA256"); 127 oum.set_field("assoc_type","HMAC-SHA256");
131 return oum; 128 return oum;
132 } 129 }
133 130
134 void basic_OP::checkid_(const basic_openid_message& inm, 131 void basic_OP::checkid_(const basic_openid_message& inm,
135 extension_t *ext) { 132 extension_t *ext) {
136 reset_vars(); 133 reset_vars();
137 string mode = inm.get_field("mode"); 134 string modestr = inm.get_field("mode");
138 if(mode=="checkid_setup") 135 if(modestr=="checkid_setup")
139 mode = mode_checkid_setup; 136 mode = mode_checkid_setup;
140 else if(mode=="checkid_immediate") 137 else if(modestr=="checkid_immediate")
141 mode = mode_checkid_immediate; 138 mode = mode_checkid_immediate;
142 else 139 else
143 throw bad_input(OPKELE_CP_ "Invalid checkid_* mode"); 140 throw bad_input(OPKELE_CP_ "Invalid checkid_* mode");
144 try { 141 try {
145 assoc = retrieve_assoc(invalidate_handle=inm.get_field("assoc_handle")); 142 assoc = retrieve_assoc(invalidate_handle=inm.get_field("assoc_handle"));
146 invalidate_handle.clear(); 143 invalidate_handle.clear();
147 }catch(failed_lookup&) { } 144 }catch(failed_lookup&) { }
148 try { 145 try {
149 openid2 = (inm.get_field("ns")==OIURI_OPENID20); 146 openid2 = (inm.get_field("ns")==OIURI_OPENID20);
150 }catch(failed_lookup&) { openid2 = false; } 147 }catch(failed_lookup&) { openid2 = false; }
151 try { 148 try {
152 return_to = inm.get_field("return_to"); 149 return_to = inm.get_field("return_to");
153 }catch(failed_lookup&) { } 150 }catch(failed_lookup&) { }
154 if(openid2) { 151 if(openid2) {
155 try { 152 try {
156 realm = inm.get_field("realm"); 153 realm = inm.get_field("realm");
157 }catch(failed_lookup&) { 154 }catch(failed_lookup&) {
158 try { 155 try {
159 realm = inm.get_field("trust_root"); 156 realm = inm.get_field("trust_root");
160 }catch(failed_lookup&) { 157 }catch(failed_lookup&) {
161 if(return_to.empty()) 158 if(return_to.empty())
162 throw bad_input(OPKELE_CP_ 159 throw bad_input(OPKELE_CP_
163 "Both realm and return_to are unset"); 160 "Both realm and return_to are unset");
164 realm = return_to; 161 realm = return_to;
165 } 162 }
166 } 163 }
167 }else{ 164 }else{
168 try { 165 try {
169 realm = inm.get_field("trust_root"); 166 realm = inm.get_field("trust_root");
170 }catch(failed_lookup&) { 167 }catch(failed_lookup&) {
171 if(return_to.empty()) 168 if(return_to.empty())
172 throw bad_input(OPKELE_CP_ 169 throw bad_input(OPKELE_CP_
173 "Both realm and return_to are unset"); 170 "Both realm and return_to are unset");
174 realm = return_to; 171 realm = return_to;
175 } 172 }
176 } 173 }
177 try { 174 try {
178 identity = inm.get_field("identity"); 175 identity = inm.get_field("identity");
179 try { 176 try {
180 claimed_id = inm.get_field("claimed_id"); 177 claimed_id = inm.get_field("claimed_id");
181 }catch(failed_lookup&) { 178 }catch(failed_lookup&) {
182 if(openid2) 179 if(openid2)
183 throw bad_input(OPKELE_CP_ 180 throw bad_input(OPKELE_CP_
184 "claimed_id and identity must be either both present or both absent"); 181 "claimed_id and identity must be either both present or both absent");
185 claimed_id = identity; 182 claimed_id = identity;
186 } 183 }
187 }catch(failed_lookup&) { 184 }catch(failed_lookup&) {
188 if(openid2 && inm.has_field("claimed_id")) 185 if(openid2 && inm.has_field("claimed_id"))
@@ -193,104 +190,104 @@ namespace opkele {
193 if(ext) ext->op_checkid_hook(inm); 190 if(ext) ext->op_checkid_hook(inm);
194 } 191 }
195 192
196 basic_openid_message& basic_OP::id_res(basic_openid_message& om, 193 basic_openid_message& basic_OP::id_res(basic_openid_message& om,
197 extension_t *ext) { 194 extension_t *ext) {
198 assert(!return_to.empty()); 195 assert(!return_to.empty());
199 assert(!is_id_select()); 196 assert(!is_id_select());
200 if(!assoc) { 197 if(!assoc) {
201 assoc = alloc_assoc("HMAC-SHA256",SHA256_DIGEST_LENGTH,true); 198 assoc = alloc_assoc("HMAC-SHA256",SHA256_DIGEST_LENGTH,true);
202 } 199 }
203 time_t now = time(0); 200 time_t now = time(0);
204 struct tm gmt; gmtime_r(&now,&gmt); 201 struct tm gmt; gmtime_r(&now,&gmt);
205 char w3timestr[24]; 202 char w3timestr[24];
206 if(!strftime(w3timestr,sizeof(w3timestr),"%Y-%m-%dT%H:%M:%SZ",&gmt)) 203 if(!strftime(w3timestr,sizeof(w3timestr),"%Y-%m-%dT%H:%M:%SZ",&gmt))
207 throw failed_conversion(OPKELE_CP_ 204 throw failed_conversion(OPKELE_CP_
208 "Failed to build time string for nonce" ); 205 "Failed to build time string for nonce" );
209 om.set_field("ns",OIURI_OPENID20); 206 om.set_field("ns",OIURI_OPENID20);
210 om.set_field("mode","id_res"); 207 om.set_field("mode","id_res");
211 om.set_field("op_endpoint",get_op_endpoint()); 208 om.set_field("op_endpoint",get_op_endpoint());
212 string ats = "ns,mode,op_endpoint,return_to,response_nonce," 209 string ats = "ns,mode,op_endpoint,return_to,response_nonce,"
213 "assoc_handle,signed"; 210 "assoc_handle,signed";
214 if(!identity.empty()) { 211 if(!identity.empty()) {
215 om.set_field("identity",identity); 212 om.set_field("identity",identity);
216 om.set_field("claimed_id",claimed_id); 213 om.set_field("claimed_id",claimed_id);
217 ats += ",identity,claimed_id"; 214 ats += ",identity,claimed_id";
218 } 215 }
219 om.set_field("return_to",return_to); 216 om.set_field("return_to",return_to);
220 string nonce = w3timestr; 217 string nonce = w3timestr;
221 om.set_field("response_nonce",alloc_nonce(nonce)); 218 om.set_field("response_nonce",alloc_nonce(nonce));
222 if(!invalidate_handle.empty()) { 219 if(!invalidate_handle.empty()) {
223 om.set_field("invalidate_handle",invalidate_handle); 220 om.set_field("invalidate_handle",invalidate_handle);
224 ats += ",invalidate_handle"; 221 ats += ",invalidate_handle";
225 } 222 }
226 om.set_field("assoc_handle",assoc->handle()); 223 om.set_field("assoc_handle",assoc->handle());
227 om.add_to_signed(ats); 224 om.add_to_signed(ats);
228 if(ext) ext->op_id_res_hook(om); 225 if(ext) ext->op_id_res_hook(om);
229 om.set_field("sig",util::base64_signature(assoc,om)); 226 om.set_field("sig",util::base64_signature(assoc,om));
230 return om; 227 return om;
231 } 228 }
232 229
233 basic_openid_message& basic_OP::cancel(basic_openid_message& om) { 230 basic_openid_message& basic_OP::cancel(basic_openid_message& om) {
234 assert(!return_to.empty()); 231 assert(!return_to.empty());
235 om.set_field("ns",OIURI_OPENID20); 232 om.set_field("ns",OIURI_OPENID20);
236 om.set_field("mode","cancel"); 233 om.set_field("mode","cancel");
237 return om; 234 return om;
238 } 235 }
239 236
240 basic_openid_message& basic_OP::error(basic_openid_message& om, 237 basic_openid_message& basic_OP::error(basic_openid_message& om,
241 const string& error,const string& contact, 238 const string& err,const string& contact,
242 const string& reference ) { 239 const string& reference ) {
243 assert(!return_to.empty()); 240 assert(!return_to.empty());
244 om.set_field("ns",OIURI_OPENID20); 241 om.set_field("ns",OIURI_OPENID20);
245 om.set_field("mode","error"); 242 om.set_field("mode","error");
246 om.set_field("error",error); 243 om.set_field("error",err);
247 om.set_field("contact",contact); 244 if(!contact.empty()) om.set_field("contact",contact);
248 om.set_field("reference",reference); 245 if(!reference.empty()) om.set_field("reference",reference);
249 return om; 246 return om;
250 } 247 }
251 248
252 basic_openid_message& basic_OP::setup_needed( 249 basic_openid_message& basic_OP::setup_needed(
253 basic_openid_message& oum,const basic_openid_message& inm) { 250 basic_openid_message& oum,const basic_openid_message& inm) {
254 assert(mode==mode_checkid_immediate); 251 assert(mode==mode_checkid_immediate);
255 assert(!return_to.empty()); 252 assert(!return_to.empty());
256 if(openid2) { 253 if(openid2) {
257 oum.set_field("ns",OIURI_OPENID20); 254 oum.set_field("ns",OIURI_OPENID20);
258 oum.set_field("mode","setup_needed"); 255 oum.set_field("mode","setup_needed");
259 }else{ 256 }else{
260 oum.set_field("mode","id_res"); 257 oum.set_field("mode","id_res");
261 static const string setupmode = "checkid_setup"; 258 static const string setupmode = "checkid_setup";
262 oum.set_field("user_setup_url", 259 oum.set_field("user_setup_url",
263 util::change_mode_message_proxy(inm,setupmode) 260 util::change_mode_message_proxy(inm,setupmode)
264 .append_query(get_op_endpoint())); 261 .append_query(get_op_endpoint()));
265 } 262 }
266 return oum; 263 return oum;
267 } 264 }
268 265
269 basic_openid_message& basic_OP::check_authentication( 266 basic_openid_message& basic_OP::check_authentication(
270 basic_openid_message& oum, 267 basic_openid_message& oum,
271 const basic_openid_message& inm) try { 268 const basic_openid_message& inm) try {
272 assert(inm.get_field("mode")=="check_authentication"); 269 assert(inm.get_field("mode")=="check_authentication");
273 oum.reset_fields(); 270 oum.reset_fields();
274 oum.set_field("ns",OIURI_OPENID20); 271 oum.set_field("ns",OIURI_OPENID20);
275 bool o2; 272 bool o2;
276 try { 273 try {
277 o2 = (inm.get_field("ns")==OIURI_OPENID20); 274 o2 = (inm.get_field("ns")==OIURI_OPENID20);
278 }catch(failed_lookup&) { o2 = false; } 275 }catch(failed_lookup&) { o2 = false; }
279 string nonce; 276 string nonce;
280 if(o2) { 277 if(o2) {
281 try { 278 try {
282 if(!check_nonce(nonce = inm.get_field("response_nonce"))) 279 if(!check_nonce(nonce = inm.get_field("response_nonce")))
283 throw failed_check_authentication(OPKELE_CP_ "Invalid nonce"); 280 throw failed_check_authentication(OPKELE_CP_ "Invalid nonce");
284 }catch(failed_lookup&) { 281 }catch(failed_lookup&) {
285 throw failed_check_authentication(OPKELE_CP_ "No nonce provided with check_authentication request"); 282 throw failed_check_authentication(OPKELE_CP_ "No nonce provided with check_authentication request");
286 } 283 }
287 } 284 }
288 try { 285 try {
289 assoc = retrieve_assoc(inm.get_field("assoc_handle")); 286 assoc = retrieve_assoc(inm.get_field("assoc_handle"));
290 if(!assoc->stateless()) 287 if(!assoc->stateless())
291 throw failed_check_authentication(OPKELE_CP_ "Will not do check_authentication on a stateful handle"); 288 throw failed_check_authentication(OPKELE_CP_ "Will not do check_authentication on a stateful handle");
292 }catch(failed_lookup&) { 289 }catch(failed_lookup&) {
293 throw failed_check_authentication(OPKELE_CP_ "No assoc_handle or invalid assoc_handle specified with check_authentication request"); 290 throw failed_check_authentication(OPKELE_CP_ "No assoc_handle or invalid assoc_handle specified with check_authentication request");
294 } 291 }
295 static const string idresmode = "id_res"; 292 static const string idresmode = "id_res";
296 try { 293 try {
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,138 +1,140 @@
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);
53 } 55 }
54 56
55 57
56 assoc_t basic_RP::associate(const string& OP) { 58 assoc_t basic_RP::associate(const string& OP) {
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");
115 if(!realm.empty()) { 117 if(!realm.empty()) {
116 rv.set_field("realm",realm); 118 rv.set_field("realm",realm);
117 rv.set_field("trust_root",realm); 119 rv.set_field("trust_root",realm);
118 } 120 }
119 if(!return_to.empty()) 121 if(!return_to.empty())
120 rv.set_field("return_to",return_to); 122 rv.set_field("return_to",return_to);
121 const openid_endpoint_t& ep = get_endpoint(); 123 const openid_endpoint_t& ep = get_endpoint();
122 rv.set_field("claimed_id",ep.claimed_id); 124 rv.set_field("claimed_id",ep.claimed_id);
123 rv.set_field("identity",ep.local_id); 125 rv.set_field("identity",ep.local_id);
124 try { 126 try {
125 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle()); 127 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle());
126 }catch(dumb_RP& drp) { 128 }catch(dumb_RP& drp) {
127 }catch(failed_lookup& fl) { 129 }catch(failed_lookup& fl) {
128 try { 130 try {
129 rv.set_field("assoc_handle",associate(ep.uri)->handle()); 131 rv.set_field("assoc_handle",associate(ep.uri)->handle());
130 }catch(dumb_RP& drp) { } 132 }catch(dumb_RP& drp) { }
131 } OPKELE_RETHROW 133 } OPKELE_RETHROW
132 if(ext) ext->rp_checkid_hook(rv); 134 if(ext) ext->rp_checkid_hook(rv);
133 return rv; 135 return rv;
134 } 136 }
135 137
136 class signed_part_message_proxy : public basic_openid_message { 138 class signed_part_message_proxy : public basic_openid_message {
137 public: 139 public:
138 const basic_openid_message& x; 140 const basic_openid_message& x;
@@ -189,97 +191,97 @@ namespace opkele {
189 } 191 }
190 q = ++am; 192 q = ++am;
191 } 193 }
192 } 194 }
193 } 195 }
194 196
195 void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) { 197 void basic_RP::id_res(const basic_openid_message& om,extension_t *ext) {
196 bool o2 = om.has_field("ns") 198 bool o2 = om.has_field("ns")
197 && om.get_field("ns")==OIURI_OPENID20; 199 && om.get_field("ns")==OIURI_OPENID20;
198 if( (!o2) && om.has_field("user_setup_url")) 200 if( (!o2) && om.has_field("user_setup_url"))
199 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided", 201 throw id_res_setup(OPKELE_CP_ "assertion failed, setup url provided",
200 om.get_field("user_setup_url")); 202 om.get_field("user_setup_url"));
201 string m = om.get_field("mode"); 203 string m = om.get_field("mode");
202 if(o2 && m=="setup_needed") 204 if(o2 && m=="setup_needed")
203 throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided"); 205 throw id_res_setup(OPKELE_CP_ "setup needed, no setup url provided");
204 if(m=="cancel") 206 if(m=="cancel")
205 throw id_res_cancel(OPKELE_CP_ "authentication cancelled"); 207 throw id_res_cancel(OPKELE_CP_ "authentication cancelled");
206 bool go_dumb=false; 208 bool go_dumb=false;
207 try { 209 try {
208 string OP = o2 210 string OP = o2
209 ?om.get_field("op_endpoint") 211 ?om.get_field("op_endpoint")
210 :get_endpoint().uri; 212 :get_endpoint().uri;
211 assoc_t assoc = retrieve_assoc( 213 assoc_t assoc = retrieve_assoc(
212 OP,om.get_field("assoc_handle")); 214 OP,om.get_field("assoc_handle"));
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);
262 for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) { 264 for(map<string,string>::const_iterator rpi=rp.begin();rpi!=rp.end();++rpi) {
263 map<string,string>::const_iterator tpi = tp.find(rpi->first); 265 map<string,string>::const_iterator tpi = tp.find(rpi->first);
264 if(tpi==tp.end()) 266 if(tpi==tp.end())
265 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request"); 267 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to is missing from the request");
266 if(tpi->second!=rpi->second) 268 if(tpi->second!=rpi->second)
267 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request"); 269 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request");
268 } 270 }
269 271
270 if(om.has_field("claimed_id")) { 272 if(om.has_field("claimed_id")) {
271 verify_OP( 273 verify_OP(
272 om.get_field("op_endpoint"), 274 om.get_field("op_endpoint"),
273 om.get_field("claimed_id"), 275 om.get_field("claimed_id"),
274 om.get_field("identity") ); 276 om.get_field("identity") );
275 } 277 }
276 278
277 } 279 }
278 if(ext) ext->rp_id_res_hook(om,signeds); 280 if(ext) ext->rp_id_res_hook(om,signeds);
279 } 281 }
280 282
281 void basic_RP::check_authentication(const string& OP, 283 void basic_RP::check_authentication(const string& OP,
282 const basic_openid_message& om){ 284 const basic_openid_message& om){
283 openid_message_t res; 285 openid_message_t res;
284 static const string checkauthmode = "check_authentication"; 286 static const string checkauthmode = "check_authentication";
285 direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP); 287 direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP);
diff --git a/lib/discovery.cc b/lib/discovery.cc
index 6f58339..6f9926c 100644
--- a/lib/discovery.cc
+++ b/lib/discovery.cc
@@ -285,97 +285,97 @@ namespace opkele {
285 } 285 }
286 286
287 void html2xrd(endpoint_discovery_iterator& oi,idiscovery_t& id) { 287 void html2xrd(endpoint_discovery_iterator& oi,idiscovery_t& id) {
288 XRD_t& x = id.xrd; 288 XRD_t& x = id.xrd;
289 if(!html_openid2.uris.empty()) { 289 if(!html_openid2.uris.empty()) {
290 html_openid2.types.insert(STURI_OPENID20); 290 html_openid2.types.insert(STURI_OPENID20);
291 x.services.add(-1,html_openid2); 291 x.services.add(-1,html_openid2);
292 queue_endpoints(oi,id,&op_service_types[st_index_2]); 292 queue_endpoints(oi,id,&op_service_types[st_index_2]);
293 } 293 }
294 if(!html_openid1.uris.empty()) { 294 if(!html_openid1.uris.empty()) {
295 html_openid1.types.insert(STURI_OPENID11); 295 html_openid1.types.insert(STURI_OPENID11);
296 x.services.add(-1,html_openid1); 296 x.services.add(-1,html_openid1);
297 queue_endpoints(oi,id,&op_service_types[st_index_1]); 297 queue_endpoints(oi,id,&op_service_types[st_index_1]);
298 } 298 }
299 } 299 }
300 300
301 size_t write(void *p,size_t s,size_t nm) { 301 size_t write(void *p,size_t s,size_t nm) {
302 /* TODO: limit total size */ 302 /* TODO: limit total size */
303 size_t bytes = s*nm; 303 size_t bytes = s*nm;
304 const char *inbuf = (const char*)p; 304 const char *inbuf = (const char*)p;
305 if(xmode&xmode_html) { 305 if(xmode&xmode_html) {
306 size_t mbts = save_html.capacity()-save_html.size(); 306 size_t mbts = save_html.capacity()-save_html.size();
307 size_t bts = 0; 307 size_t bts = 0;
308 if(mbts>0) { 308 if(mbts>0) {
309 bts = (bytes>mbts)?mbts:bytes; 309 bts = (bytes>mbts)?mbts:bytes;
310 save_html.append(inbuf,bts); 310 save_html.append(inbuf,bts);
311 } 311 }
312 if(skipping<0) return bts; 312 if(skipping<0) return bts;
313 } 313 }
314 if(skipping<0) return 0; 314 if(skipping<0) return 0;
315 bool rp = parse(inbuf,bytes,false); 315 bool rp = parse(inbuf,bytes,false);
316 if(!rp) { 316 if(!rp) {
317 parser_choked = true; 317 parser_choked = true;
318 skipping = -1; 318 skipping = -1;
319 if(!(xmode&xmode_html)) 319 if(!(xmode&xmode_html))
320 bytes = 0; 320 bytes = 0;
321 } 321 }
322 return bytes; 322 return bytes;
323 } 323 }
324 size_t header(void *p,size_t s,size_t nm) { 324 size_t header(void *p,size_t s,size_t nm) {
325 size_t bytes = s*nm; 325 size_t bytes = s*nm;
326 const char *h = (const char*)p; 326 const char *h = (const char*)p;
327 const char *colon = (const char*)memchr(p,':',bytes); 327 const char *colon = (const char*)memchr(p,':',bytes);
328 const char *space = (const char*)memchr(p,' ',bytes); 328 const char *space = (const char*)memchr(p,' ',bytes);
329 if(space && ( (!colon) || space<colon ) ) { 329 if(space && ( (!colon) || space<colon ) ) {
330 xrds_location.clear(); http_content_type.clear(); 330 xrds_location.clear(); http_content_type.clear();
331 }else if(colon) { 331 }else if(colon) {
332 const char *hv = ++colon; 332 const char *hv = ++colon;
333 int hnl = colon-h; 333 size_t hnl = colon-h;
334 int rb; 334 int rb;
335 for(rb = bytes-hnl-1;rb>0 && isspace(*hv);++hv,--rb); 335 for(rb = bytes-hnl-1;rb>0 && isspace(*hv);++hv,--rb);
336 while(rb>0 && isspace(hv[rb-1])) --rb; 336 while(rb>0 && isspace(hv[rb-1])) --rb;
337 if(rb) { 337 if(rb) {
338 if( (hnl>=sizeof(XRDS_HEADER)) 338 if( (hnl>=sizeof(XRDS_HEADER))
339 && !strncasecmp(h,XRDS_HEADER":", 339 && !strncasecmp(h,XRDS_HEADER":",
340 sizeof(XRDS_HEADER)) ) { 340 sizeof(XRDS_HEADER)) ) {
341 xrds_location.assign(hv,rb); 341 xrds_location.assign(hv,rb);
342 }else if( (hnl>=sizeof(CT_HEADER)) 342 }else if( (hnl>=sizeof(CT_HEADER))
343 && !strncasecmp(h,CT_HEADER":", 343 && !strncasecmp(h,CT_HEADER":",
344 sizeof(CT_HEADER)) ) { 344 sizeof(CT_HEADER)) ) {
345 const char *sc = (const char*)memchr( 345 const char *sc = (const char*)memchr(
346 hv,';',rb); 346 hv,';',rb);
347 http_content_type.assign(hv,sc?(sc-hv):rb); 347 http_content_type.assign(hv,sc?(sc-hv):rb);
348 } 348 }
349 } 349 }
350 } 350 }
351 return curl_t::header(p,s,nm); 351 return curl_t::header(p,s,nm);
352 } 352 }
353 353
354 void start_element(const XML_Char *n,const XML_Char **a) { 354 void start_element(const XML_Char *n,const XML_Char **a) {
355 if(skipping<0) return; 355 if(skipping<0) return;
356 if(skipping) { 356 if(skipping) {
357 if(xmode&xmode_html) 357 if(xmode&xmode_html)
358 html_start_element(n,a); 358 html_start_element(n,a);
359 ++skipping; return; 359 ++skipping; return;
360 } 360 }
361 if(pt_stack.empty()) { 361 if(pt_stack.empty()) {
362 if(is_qelement(n,NSURI_XRDS "\tXRDS")) 362 if(is_qelement(n,NSURI_XRDS "\tXRDS"))
363 return; 363 return;
364 if(is_qelement(n,NSURI_XRD "\tXRD")) { 364 if(is_qelement(n,NSURI_XRD "\tXRD")) {
365 assert(xrd); 365 assert(xrd);
366 xrd->clear(); 366 xrd->clear();
367 pt_stack.push_back(n); 367 pt_stack.push_back(n);
368 }else if(xmode&xmode_html) { 368 }else if(xmode&xmode_html) {
369 html_start_element(n,a); 369 html_start_element(n,a);
370 }else{ 370 }else{
371 skipping = -1; 371 skipping = -1;
372 } 372 }
373 }else{ 373 }else{
374 int pt_s = pt_stack.size(); 374 int pt_s = pt_stack.size();
375 if(pt_s==1) { 375 if(pt_s==1) {
376 if(is_qelement(n,NSURI_XRD "\tCanonicalID")) { 376 if(is_qelement(n,NSURI_XRD "\tCanonicalID")) {
377 assert(xrd); 377 assert(xrd);
378 cdata = &(xrd->canonical_ids.add(element_priority(a),string())); 378 cdata = &(xrd->canonical_ids.add(element_priority(a),string()));
379 }else if(is_qelement(n,NSURI_XRD "\tLocalID")) { 379 }else if(is_qelement(n,NSURI_XRD "\tLocalID")) {
380 assert(xrd); 380 assert(xrd);
381 cdata = &(xrd->local_ids.add(element_priority(a),string())); 381 cdata = &(xrd->local_ids.add(element_priority(a),string()));
diff --git a/lib/expat.cc b/lib/expat.cc
index fa6fdde..c4dab7e 100644
--- a/lib/expat.cc
+++ b/lib/expat.cc
@@ -1,63 +1,64 @@
1#include <opkele/expat.h> 1#include <opkele/expat.h>
2 2
3namespace opkele { 3namespace opkele {
4 4
5 namespace util { 5 namespace util {
6 6
7 expat_t::~expat_t() throw() { 7 expat_t::~expat_t() throw() {
8 if(_x) 8 if(_x)
9 XML_ParserFree(_x); 9 XML_ParserFree(_x);
10 } 10 }
11 11
12 expat_t& expat_t::operator=(XML_Parser x) { 12 expat_t& expat_t::operator=(XML_Parser x) {
13 if(_x) 13 if(_x)
14 XML_ParserFree(_x); 14 XML_ParserFree(_x);
15 _x = x; 15 _x = x;
16 return *this;
16 } 17 }
17 18
18 static void _start_element(void* ud,const XML_Char *n,const XML_Char **a) { 19 static void _start_element(void* ud,const XML_Char *n,const XML_Char **a) {
19 ((expat_t*)ud)->start_element(n,a); 20 ((expat_t*)ud)->start_element(n,a);
20 } 21 }
21 static void _end_element(void *ud,const XML_Char *n) { 22 static void _end_element(void *ud,const XML_Char *n) {
22 ((expat_t*)ud)->end_element(n); 23 ((expat_t*)ud)->end_element(n);
23 } 24 }
24 25
25 void expat_t::set_element_handler() { 26 void expat_t::set_element_handler() {
26 assert(_x); 27 assert(_x);
27 XML_SetElementHandler(_x,_start_element,_end_element); 28 XML_SetElementHandler(_x,_start_element,_end_element);
28 } 29 }
29 30
30 static void _character_data(void *ud,const XML_Char *s,int l) { 31 static void _character_data(void *ud,const XML_Char *s,int l) {
31 ((expat_t*)ud)->character_data(s,l); 32 ((expat_t*)ud)->character_data(s,l);
32 } 33 }
33 34
34 void expat_t::set_character_data_handler() { 35 void expat_t::set_character_data_handler() {
35 assert(_x); 36 assert(_x);
36 XML_SetCharacterDataHandler(_x,_character_data); 37 XML_SetCharacterDataHandler(_x,_character_data);
37 } 38 }
38 39
39 static void _processing_instruction(void *ud,const XML_Char *t,const XML_Char *d) { 40 static void _processing_instruction(void *ud,const XML_Char *t,const XML_Char *d) {
40 ((expat_t*)ud)->processing_instruction(t,d); 41 ((expat_t*)ud)->processing_instruction(t,d);
41 } 42 }
42 43
43 void expat_t::set_processing_instruction_handler() { 44 void expat_t::set_processing_instruction_handler() {
44 assert(_x); 45 assert(_x);
45 XML_SetProcessingInstructionHandler(_x,_processing_instruction); 46 XML_SetProcessingInstructionHandler(_x,_processing_instruction);
46 } 47 }
47 48
48 static void _comment(void *ud,const XML_Char *d) { 49 static void _comment(void *ud,const XML_Char *d) {
49 ((expat_t*)ud)->comment(d); 50 ((expat_t*)ud)->comment(d);
50 } 51 }
51 52
52 void expat_t::set_comment_handler() { 53 void expat_t::set_comment_handler() {
53 assert(_x); 54 assert(_x);
54 XML_SetCommentHandler(_x,_comment); 55 XML_SetCommentHandler(_x,_comment);
55 } 56 }
56 57
57 static void _start_cdata_section(void *ud) { 58 static void _start_cdata_section(void *ud) {
58 ((expat_t*)ud)->start_cdata_section(); 59 ((expat_t*)ud)->start_cdata_section();
59 } 60 }
60 static void _end_cdata_section(void *ud) { 61 static void _end_cdata_section(void *ud) {
61 ((expat_t*)ud)->end_cdata_section(); 62 ((expat_t*)ud)->end_cdata_section();
62 } 63 }
63 64
diff --git a/lib/extension.cc b/lib/extension.cc
index f7aaea5..0f121ca 100644
--- a/lib/extension.cc
+++ b/lib/extension.cc
@@ -1,26 +1,26 @@
1#include <opkele/exception.h> 1#include <opkele/exception.h>
2#include <opkele/extension.h> 2#include <opkele/extension.h>
3 3
4namespace opkele { 4namespace opkele {
5 5
6 void extension_t::rp_checkid_hook(basic_openid_message&) { 6 void extension_t::rp_checkid_hook(basic_openid_message&) {
7 throw not_implemented(OPKELE_CP_ "RP checkid_* hook not implemented"); } 7 throw not_implemented(OPKELE_CP_ "RP checkid_* hook not implemented"); }
8 void extension_t::rp_id_res_hook(const basic_openid_message&, 8 void extension_t::rp_id_res_hook(const basic_openid_message&,
9 const basic_openid_message&) { 9 const basic_openid_message&) {
10 throw not_implemented(OPKELE_CP_ "RP id_res hook not implemented"); } 10 throw not_implemented(OPKELE_CP_ "RP id_res hook not implemented"); }
11 11
12 void extension_t::op_checkid_hook(const basic_openid_message&) { 12 void extension_t::op_checkid_hook(const basic_openid_message&) {
13 throw not_implemented(OPKELE_CP_ "OP checkid_* hook not implemented"); } 13 throw not_implemented(OPKELE_CP_ "OP checkid_* hook not implemented"); }
14 void extension_t::op_id_res_hook(basic_openid_message& om) { 14 void extension_t::op_id_res_hook(basic_openid_message&) {
15 throw not_implemented(OPKELE_CP_ "OP id_res hook not implemented"); } 15 throw not_implemented(OPKELE_CP_ "OP id_res hook not implemented"); }
16 16
17 17
18 void extension_t::checkid_hook(basic_openid_message&) { 18 void extension_t::checkid_hook(basic_openid_message&) {
19 throw not_implemented(OPKELE_CP_ "deprecated consumer checkid_* hook not implemented"); } 19 throw not_implemented(OPKELE_CP_ "deprecated consumer checkid_* hook not implemented"); }
20 void extension_t::id_res_hook(const basic_openid_message&, 20 void extension_t::id_res_hook(const basic_openid_message&,
21 const basic_openid_message&) { 21 const basic_openid_message&) {
22 throw not_implemented(OPKELE_CP_ "deprecated consumer id_res hook not implemented"); } 22 throw not_implemented(OPKELE_CP_ "deprecated consumer id_res hook not implemented"); }
23 23
24 void extension_t::checkid_hook(const basic_openid_message&,basic_openid_message&) { 24 void extension_t::checkid_hook(const basic_openid_message&,basic_openid_message&) {
25 throw not_implemented(OPKELE_CP_ "deprecated server checkid hook not implemented"); } 25 throw not_implemented(OPKELE_CP_ "deprecated server checkid hook not implemented"); }
26} 26}
diff --git a/lib/openid_message.cc b/lib/openid_message.cc
index fdb4b04..521ea85 100644
--- a/lib/openid_message.cc
+++ b/lib/openid_message.cc
@@ -1,216 +1,216 @@
1#include <cassert> 1#include <cassert>
2#include <opkele/types.h> 2#include <opkele/types.h>
3#include <opkele/exception.h> 3#include <opkele/exception.h>
4#include <opkele/util.h> 4#include <opkele/util.h>
5#include <opkele/debug.h> 5#include <opkele/debug.h>
6 6
7#include "config.h" 7#include "config.h"
8 8
9namespace opkele { 9namespace opkele {
10 using std::input_iterator_tag; 10 using std::input_iterator_tag;
11 using std::unary_function; 11 using std::unary_function;
12 12
13 struct __om_copier : public unary_function<const string&,void> { 13 struct __om_copier : public unary_function<const string&,void> {
14 public: 14 public:
15 const basic_openid_message& from; 15 const basic_openid_message& from;
16 basic_openid_message& to; 16 basic_openid_message& to;
17 17
18 __om_copier(basic_openid_message& to,const basic_openid_message& from) 18 __om_copier(basic_openid_message& t,const basic_openid_message& f)
19 : from(from), to(to) { 19 : from(f), to(t) {
20 to.reset_fields(); 20 to.reset_fields();
21 } 21 }
22 22
23 result_type operator()(argument_type f) { 23 result_type operator()(argument_type f) {
24 to.set_field(f,from.get_field(f)); } 24 to.set_field(f,from.get_field(f)); }
25 }; 25 };
26 26
27 basic_openid_message::basic_openid_message(const basic_openid_message& x) { 27 basic_openid_message::basic_openid_message(const basic_openid_message& x) {
28 x.copy_to(*this); 28 x.copy_to(*this);
29 } 29 }
30 void basic_openid_message::copy_to(basic_openid_message& x) const { 30 void basic_openid_message::copy_to(basic_openid_message& x) const {
31 for_each(fields_begin(),fields_end(), 31 for_each(fields_begin(),fields_end(),
32 __om_copier(x,*this) ); 32 __om_copier(x,*this) );
33 } 33 }
34 34
35 struct __om_ns_finder : public unary_function<const string&,bool> { 35 struct __om_ns_finder : public unary_function<const string&,bool> {
36 public: 36 public:
37 const basic_openid_message& om; 37 const basic_openid_message& om;
38 const string& uri; 38 const string& uri;
39 39
40 __om_ns_finder(const basic_openid_message& om, 40 __om_ns_finder(const basic_openid_message& m,
41 const string& uri) : om(om), uri(uri) { } 41 const string& u) : om(m), uri(u) { }
42 42
43 result_type operator()(argument_type f) { 43 result_type operator()(argument_type f) {
44 return 44 return
45 (!strncmp(f.c_str(),"ns.",sizeof("ns.")-1)) 45 (!strncmp(f.c_str(),"ns.",sizeof("ns.")-1))
46 && om.get_field(f)==uri ; 46 && om.get_field(f)==uri ;
47 } 47 }
48 }; 48 };
49 49
50 bool basic_openid_message::has_ns(const string& uri) const { 50 bool basic_openid_message::has_ns(const string& uri) const {
51 fields_iterator ei = fields_end(); 51 fields_iterator ei = fields_end();
52 fields_iterator i = find_if(fields_begin(),fields_end(), 52 fields_iterator i = find_if(fields_begin(),fields_end(),
53 __om_ns_finder(*this,uri)); 53 __om_ns_finder(*this,uri));
54 return !(i==ei); 54 return !(i==ei);
55 } 55 }
56 string basic_openid_message::get_ns(const string& uri) const { 56 string basic_openid_message::get_ns(const string& uri) const {
57 fields_iterator ei = fields_end(); 57 fields_iterator ei = fields_end();
58 fields_iterator i = find_if(fields_begin(),fields_end(), 58 fields_iterator i = find_if(fields_begin(),fields_end(),
59 __om_ns_finder(*this,uri)); 59 __om_ns_finder(*this,uri));
60 if(i==ei) 60 if(i==ei)
61 throw failed_lookup(OPKELE_CP_ string("failed to find namespace ")+uri); 61 throw failed_lookup(OPKELE_CP_ string("failed to find namespace ")+uri);
62 return i->substr(3); 62 return i->substr(3);
63 } 63 }
64 64
65 struct __om_query_builder : public unary_function<const string&,void> { 65 struct __om_query_builder : public unary_function<const string&,void> {
66 public: 66 public:
67 const basic_openid_message& om; 67 const basic_openid_message& om;
68 string& rv;
69 bool first; 68 bool first;
69 string& rv;
70 70
71 __om_query_builder(string& rv,const basic_openid_message& om) 71 __om_query_builder(string& r,const basic_openid_message& m)
72 : om(om), first(true), rv(rv) { 72 : om(m), first(true), rv(r) {
73 for_each(om.fields_begin(),om.fields_end(),*this); 73 for_each(om.fields_begin(),om.fields_end(),*this);
74 } 74 }
75 __om_query_builder(string& rv,const basic_openid_message& om,const string& url) 75 __om_query_builder(string& r,const basic_openid_message& m,const string& u)
76 : om(om), first(true), rv(rv) { 76 : om(m), first(true), rv(r) {
77 rv = url; 77 rv = u;
78 if(rv.find('?')==string::npos) 78 if(rv.find('?')==string::npos)
79 rv += '?'; 79 rv += '?';
80 else 80 else
81 first = false; 81 first = false;
82 for_each(om.fields_begin(),om.fields_end(),*this); 82 for_each(om.fields_begin(),om.fields_end(),*this);
83 } 83 }
84 84
85 result_type operator()(argument_type f) { 85 result_type operator()(argument_type f) {
86 if(first) 86 if(first)
87 first = false; 87 first = false;
88 else 88 else
89 rv += '&'; 89 rv += '&';
90 rv += "openid."; rv+= f; 90 rv += "openid."; rv+= f;
91 rv += '='; 91 rv += '=';
92 rv += util::url_encode(om.get_field(f)); 92 rv += util::url_encode(om.get_field(f));
93 } 93 }
94 }; 94 };
95 95
96 string basic_openid_message::append_query(const string& url) const { 96 string basic_openid_message::append_query(const string& url) const {
97 string rv; 97 string rv;
98 return __om_query_builder(rv,*this,url).rv; 98 return __om_query_builder(rv,*this,url).rv;
99 } 99 }
100 string basic_openid_message::query_string() const { 100 string basic_openid_message::query_string() const {
101 string rv; 101 string rv;
102 return __om_query_builder(rv,*this).rv; 102 return __om_query_builder(rv,*this).rv;
103 } 103 }
104 104
105 void basic_openid_message::reset_fields() { 105 void basic_openid_message::reset_fields() {
106 throw not_implemented(OPKELE_CP_ "reset_fields() not implemented"); 106 throw not_implemented(OPKELE_CP_ "reset_fields() not implemented");
107 } 107 }
108 void basic_openid_message::set_field(const string& n,const string& v) { 108 void basic_openid_message::set_field(const string&,const string&) {
109 throw not_implemented(OPKELE_CP_ "set_field() not implemented"); 109 throw not_implemented(OPKELE_CP_ "set_field() not implemented");
110 } 110 }
111 void basic_openid_message::reset_field(const string& n) { 111 void basic_openid_message::reset_field(const string&) {
112 throw not_implemented(OPKELE_CP_ "reset_field() not implemented"); 112 throw not_implemented(OPKELE_CP_ "reset_field() not implemented");
113 } 113 }
114 114
115 void basic_openid_message::from_keyvalues(const string& kv) { 115 void basic_openid_message::from_keyvalues(const string& kv) {
116 reset_fields(); 116 reset_fields();
117 string::size_type p = 0; 117 string::size_type p = 0;
118 while(true) { 118 while(true) {
119 string::size_type co = kv.find(':',p); 119 string::size_type co = kv.find(':',p);
120 if(co==string::npos) 120 if(co==string::npos)
121 break; 121 break;
122#ifndef POSTELS_LAW 122#ifndef POSTELS_LAW
123 string::size_type nl = kv.find('\n',co+1); 123 string::size_type nl = kv.find('\n',co+1);
124 if(nl==string::npos) 124 if(nl==string::npos)
125 throw bad_input(OPKELE_CP_ "malformed input"); 125 throw bad_input(OPKELE_CP_ "malformed input");
126 if(nl>co) 126 if(nl>co)
127 insert(value_type(kv.substr(p,co-p),kv.substr(co+1,nl-co-1))); 127 insert(value_type(kv.substr(p,co-p),kv.substr(co+1,nl-co-1)));
128 p = nl+1; 128 p = nl+1;
129#else /* POSTELS_LAW */ 129#else /* POSTELS_LAW */
130 string::size_type lb = kv.find_first_of("\r\n",co+1); 130 string::size_type lb = kv.find_first_of("\r\n",co+1);
131 if(lb==string::npos) { 131 if(lb==string::npos) {
132 set_field(kv.substr(p,co-p),kv.substr(co+1)); 132 set_field(kv.substr(p,co-p),kv.substr(co+1));
133 break; 133 break;
134 } 134 }
135 if(lb>co) 135 if(lb>co)
136 set_field(kv.substr(p,co-p),kv.substr(co+1,lb-co-1)); 136 set_field(kv.substr(p,co-p),kv.substr(co+1,lb-co-1));
137 string::size_type nolb = kv.find_first_not_of("\r\n",lb); 137 string::size_type nolb = kv.find_first_not_of("\r\n",lb);
138 if(nolb==string::npos) 138 if(nolb==string::npos)
139 break; 139 break;
140 p = nolb; 140 p = nolb;
141#endif /* POSTELS_LAW */ 141#endif /* POSTELS_LAW */
142 } 142 }
143 } 143 }
144 144
145 struct __om_kv_outputter : public unary_function<const string&,void> { 145 struct __om_kv_outputter : public unary_function<const string&,void> {
146 public: 146 public:
147 const basic_openid_message& om; 147 const basic_openid_message& om;
148 ostream& os; 148 ostream& os;
149 149
150 __om_kv_outputter(const basic_openid_message& om,ostream& os) 150 __om_kv_outputter(const basic_openid_message& m,ostream& s)
151 : om(om), os(os) { } 151 : om(m), os(s) { }
152 152
153 result_type operator()(argument_type f) { 153 result_type operator()(argument_type f) {
154 os << f << ':' << om.get_field(f) << '\n'; 154 os << f << ':' << om.get_field(f) << '\n';
155 } 155 }
156 }; 156 };
157 157
158 void basic_openid_message::to_keyvalues(ostream& o) const { 158 void basic_openid_message::to_keyvalues(ostream& o) const {
159 for_each(fields_begin(),fields_end(),__om_kv_outputter(*this,o)); 159 for_each(fields_begin(),fields_end(),__om_kv_outputter(*this,o));
160 } 160 }
161 161
162 struct __om_html_outputter : public unary_function<const string&,void> { 162 struct __om_html_outputter : public unary_function<const string&,void> {
163 public: 163 public:
164 const basic_openid_message& om; 164 const basic_openid_message& om;
165 ostream& os; 165 ostream& os;
166 166
167 __om_html_outputter(const basic_openid_message& om,ostream& os) 167 __om_html_outputter(const basic_openid_message& m,ostream& s)
168 : om(om), os(os) { } 168 : om(m), os(s) { }
169 169
170 result_type operator()(argument_type f) { 170 result_type operator()(argument_type f) {
171 os << 171 os <<
172 "<input type=\"hidden\"" 172 "<input type=\"hidden\""
173 " name=\"" << util::attr_escape(f) << "\"" 173 " name=\"" << util::attr_escape(f) << "\""
174 " value=\"" << util::attr_escape(om.get_field(f)) << "\" />"; 174 " value=\"" << util::attr_escape(om.get_field(f)) << "\" />";
175 } 175 }
176 }; 176 };
177 177
178 void basic_openid_message::to_htmlhiddens(ostream& o) const { 178 void basic_openid_message::to_htmlhiddens(ostream& o) const {
179 for_each(fields_begin(),fields_end(),__om_html_outputter(*this,o)); 179 for_each(fields_begin(),fields_end(),__om_html_outputter(*this,o));
180 } 180 }
181 181
182 void basic_openid_message::add_to_signed(const string& fields) { 182 void basic_openid_message::add_to_signed(const string& fields) {
183 string::size_type fnc = fields.find_first_not_of(","); 183 string::size_type fnc = fields.find_first_not_of(",");
184 if(fnc==string::npos) 184 if(fnc==string::npos)
185 throw bad_input(OPKELE_CP_ "Trying to add nothing in particular to the list of signed fields"); 185 throw bad_input(OPKELE_CP_ "Trying to add nothing in particular to the list of signed fields");
186 string signeds; 186 string signeds;
187 try { 187 try {
188 signeds = get_field("signed"); 188 signeds = get_field("signed");
189 string::size_type lnc = signeds.find_last_not_of(","); 189 string::size_type lnc = signeds.find_last_not_of(",");
190 if(lnc==string::npos) 190 if(lnc==string::npos)
191 signeds.assign(fields,fnc,fields.size()-fnc); 191 signeds.assign(fields,fnc,fields.size()-fnc);
192 else{ 192 else{
193 string::size_type ss = signeds.size(); 193 string::size_type ss = signeds.size();
194 if(lnc==(ss-1)) { 194 if(lnc==(ss-1)) {
195 signeds+= ','; 195 signeds+= ',';
196 signeds.append(fields,fnc,fields.size()-fnc); 196 signeds.append(fields,fnc,fields.size()-fnc);
197 }else{ 197 }else{
198 if(lnc<(ss-2)) 198 if(lnc<(ss-2))
199 signeds.replace(lnc+2,ss-lnc-2, 199 signeds.replace(lnc+2,ss-lnc-2,
200 fields,fnc,fields.size()-fnc); 200 fields,fnc,fields.size()-fnc);
201 else 201 else
202 signeds.append(fields,fnc,fields.size()-fnc); 202 signeds.append(fields,fnc,fields.size()-fnc);
203 } 203 }
204 } 204 }
205 }catch(failed_lookup&) { 205 }catch(failed_lookup&) {
206 signeds.assign(fields,fnc,fields.size()-fnc); 206 signeds.assign(fields,fnc,fields.size()-fnc);
207 } 207 }
208 set_field("signed",signeds); 208 set_field("signed",signeds);
209 } 209 }
210 210
211 string basic_openid_message::find_ns(const string& uri,const char *pfx) const { 211 string basic_openid_message::find_ns(const string& uri,const char *pfx) const {
212 if(has_field("ns")) 212 if(has_field("ns"))
213 return get_ns(uri); 213 return get_ns(uri);
214 return pfx; 214 return pfx;
215 } 215 }
216 string basic_openid_message::allocate_ns(const string& uri,const char *pfx) { 216 string basic_openid_message::allocate_ns(const string& uri,const char *pfx) {
diff --git a/lib/prequeue_rp.cc b/lib/prequeue_rp.cc
index e242f87..3aa960f 100644
--- a/lib/prequeue_rp.cc
+++ b/lib/prequeue_rp.cc
@@ -10,72 +10,72 @@
10#include <opkele/curl.h> 10#include <opkele/curl.h>
11#include <opkele/debug.h> 11#include <opkele/debug.h>
12 12
13namespace opkele { 13namespace opkele {
14 14
15 class __OP_verifier_good_input : public exception { 15 class __OP_verifier_good_input : public exception {
16 public: 16 public:
17 __OP_verifier_good_input(OPKELE_E_PARS) 17 __OP_verifier_good_input(OPKELE_E_PARS)
18 : exception(OPKELE_E_CONS) { } 18 : exception(OPKELE_E_CONS) { }
19 }; 19 };
20 20
21 class OP_verifier : public iterator<output_iterator_tag,openid_endpoint_t,void> { 21 class OP_verifier : public iterator<output_iterator_tag,openid_endpoint_t,void> {
22 public: 22 public:
23 const string& OP; 23 const string& OP;
24 const string& id; 24 const string& id;
25 25
26 OP_verifier(const string& o,const string& i) 26 OP_verifier(const string& o,const string& i)
27 : OP(o), id(i) { } 27 : OP(o), id(i) { }
28 28
29 OP_verifier& operator*() { return *this; } 29 OP_verifier& operator*() { return *this; }
30 OP_verifier& operator=(const openid_endpoint_t& oep) { 30 OP_verifier& operator=(const openid_endpoint_t& oep) {
31 if(oep.uri==OP) { 31 if(oep.uri==OP) {
32 if(oep.claimed_id==IDURI_SELECT20 32 if(oep.claimed_id==IDURI_SELECT20
33 || oep.local_id==IDURI_SELECT20 ) 33 || oep.local_id==IDURI_SELECT20 )
34 throw bad_input(OPKELE_CP_ "claimed_id is an OP-Id"); 34 throw bad_input(OPKELE_CP_ "claimed_id is an OP-Id");
35 if(oep.local_id==id) 35 if(oep.local_id==id)
36 throw __OP_verifier_good_input(OPKELE_CP_ "Found corresponding endpoint"); 36 throw __OP_verifier_good_input(OPKELE_CP_ "Found corresponding endpoint");
37 } 37 }
38 return *this; 38 return *this;
39 } 39 }
40 40
41 OP_verifier& operator++() { return *this; } 41 OP_verifier& operator++() { return *this; }
42 OP_verifier& operator++(int) { return *this; } 42 OP_verifier& operator++(int) { return *this; }
43 }; 43 };
44 44
45 void prequeue_RP::verify_OP(const string& OP,const string& claimed_id,const string& identity) const { 45 void prequeue_RP::verify_OP(const string& OP,const string& claimed_id,const string& identity) const {
46 try { 46 try {
47 idiscover(OP_verifier(OP,identity),claimed_id); 47 idiscover(OP_verifier(OP,identity),claimed_id);
48 throw id_res_unauthorized(OPKELE_CP_ 48 throw id_res_unauthorized(OPKELE_CP_
49 "OP is not authorized to make an assertion regarding the identity"); 49 "OP is not authorized to make an assertion regarding the identity");
50 }catch(__OP_verifier_good_input& ovgi) { 50 }catch(__OP_verifier_good_input& ovgi) {
51 } 51 }
52 } 52 }
53 53
54 class endpoint_queuer : public iterator<output_iterator_tag,openid_endpoint_t,void> { 54 class endpoint_queuer : public iterator<output_iterator_tag,openid_endpoint_t,void> {
55 public: 55 public:
56 prequeue_RP& rp; 56 prequeue_RP& rp;
57 57
58 endpoint_queuer(prequeue_RP& rp) : rp(rp) { } 58 endpoint_queuer(prequeue_RP& r) : rp(r) { }
59 59
60 endpoint_queuer& operator*() { return *this; } 60 endpoint_queuer& operator*() { return *this; }
61 endpoint_queuer& operator=(const openid_endpoint_t& oep) { 61 endpoint_queuer& operator=(const openid_endpoint_t& oep) {
62 rp.queue_endpoint(oep); return *this; } 62 rp.queue_endpoint(oep); return *this; }
63 63
64 endpoint_queuer& operator++() { return *this; } 64 endpoint_queuer& operator++() { return *this; }
65 endpoint_queuer& operator++(int) { return *this; } 65 endpoint_queuer& operator++(int) { return *this; }
66 }; 66 };
67 67
68 void prequeue_RP::initiate(const string& usi) { 68 void prequeue_RP::initiate(const string& usi) {
69 begin_queueing(); 69 begin_queueing();
70 set_normalized_id( idiscover(endpoint_queuer(*this),usi) ); 70 set_normalized_id( idiscover(endpoint_queuer(*this),usi) );
71 end_queueing(); 71 end_queueing();
72 } 72 }
73 73
74 void prequeue_RP::set_normalized_id(const string& nid) { 74 void prequeue_RP::set_normalized_id(const string&) {
75 } 75 }
76 76
77 const string prequeue_RP::get_normalized_id() const { 77 const string prequeue_RP::get_normalized_id() const {
78 throw not_implemented(OPKELE_CP_ "get_normalized_id() is not implemented"); 78 throw not_implemented(OPKELE_CP_ "get_normalized_id() is not implemented");
79 } 79 }
80 80
81} 81}
diff --git a/lib/sreg.cc b/lib/sreg.cc
index b40cd45..0bd4d2e 100644
--- a/lib/sreg.cc
+++ b/lib/sreg.cc
@@ -10,102 +10,100 @@ namespace opkele {
10 const char *fieldname; 10 const char *fieldname;
11 sreg_t::fieldbit_t fieldbit; 11 sreg_t::fieldbit_t fieldbit;
12 }fields[] = { 12 }fields[] = {
13 { "nickname", sreg_t::field_nickname }, 13 { "nickname", sreg_t::field_nickname },
14 { "email", sreg_t::field_email }, 14 { "email", sreg_t::field_email },
15 { "fullname", sreg_t::field_fullname }, 15 { "fullname", sreg_t::field_fullname },
16 { "dob", sreg_t::field_dob }, 16 { "dob", sreg_t::field_dob },
17 { "gender", sreg_t::field_gender }, 17 { "gender", sreg_t::field_gender },
18 { "postcode", sreg_t::field_postcode }, 18 { "postcode", sreg_t::field_postcode },
19 { "country", sreg_t::field_country }, 19 { "country", sreg_t::field_country },
20 { "language", sreg_t::field_language }, 20 { "language", sreg_t::field_language },
21 { "timezone", sreg_t::field_timezone } 21 { "timezone", sreg_t::field_timezone }
22 }; 22 };
23 # define fields_BEGINfields 23 # define fields_BEGINfields
24# define fields_END &fields[sizeof(fields)/sizeof(*fields)] 24# define fields_END &fields[sizeof(fields)/sizeof(*fields)]
25 typedef const struct _sreg_field *fields_iterator; 25 typedef const struct _sreg_field *fields_iterator;
26 26
27 bool operator==(const struct _sreg_field& fd,const string& fn) { 27 bool operator==(const struct _sreg_field& fd,const string& fn) {
28 return fd.fieldname==fn; 28 return fd.fieldname==fn;
29 } 29 }
30 30
31 void sreg_t::rp_checkid_hook(basic_openid_message& om) { 31 void sreg_t::rp_checkid_hook(basic_openid_message& om) {
32 string fr, fo; 32 string fr, fo;
33 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) { 33 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) {
34 if(f->fieldbit&fields_required) { 34 if(f->fieldbit&fields_required) {
35 if(!fr.empty()) fr+=","; 35 if(!fr.empty()) fr+=",";
36 fr += f->fieldname; 36 fr += f->fieldname;
37 } 37 }
38 if(f->fieldbit&fields_optional) { 38 if(f->fieldbit&fields_optional) {
39 if(!fo.empty()) fo+=","; 39 if(!fo.empty()) fo+=",";
40 fo += f->fieldname; 40 fo += f->fieldname;
41 } 41 }
42 } 42 }
43 string pfx = om.allocate_ns(OIURI_SREG11,"sreg"); 43 string pfx = om.allocate_ns(OIURI_SREG11,"sreg");
44 if(!fr.empty()) om.set_field(pfx+".required",fr); 44 if(!fr.empty()) om.set_field(pfx+".required",fr);
45 if(!fo.empty()) om.set_field(pfx+".optional",fo); 45 if(!fo.empty()) om.set_field(pfx+".optional",fo);
46 if(!policy_url.empty()) om.set_field(pfx+".policy_url",policy_url); 46 if(!policy_url.empty()) om.set_field(pfx+".policy_url",policy_url);
47 } 47 }
48 48
49 void sreg_t::checkid_hook(basic_openid_message& om) { 49 void sreg_t::checkid_hook(basic_openid_message& om) {
50 rp_checkid_hook(om); } 50 rp_checkid_hook(om); }
51 51
52 void sreg_t::rp_id_res_hook(const basic_openid_message& om, 52 void sreg_t::rp_id_res_hook(const basic_openid_message& om,
53 const basic_openid_message& sp) { 53 const basic_openid_message& sp) {
54 clear(); 54 clear();
55 string pfx; 55 string pfx;
56 try { 56 try {
57 pfx = om.find_ns(OIURI_SREG11,"sreg"); 57 pfx = om.find_ns(OIURI_SREG11,"sreg");
58 }catch(failed_lookup& fl) { 58 }catch(failed_lookup&) {
59 try { 59 try {
60 pfx = om.find_ns(OIURI_SREG10,"sreg"); 60 pfx = om.find_ns(OIURI_SREG10,"sreg");
61 }catch(failed_lookup& fl) { 61 }catch(failed_lookup&) { return; }
62 return;
63 }
64 } 62 }
65 pfx += '.'; 63 pfx += '.';
66 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) { 64 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) {
67 string fn = pfx; fn+=f->fieldname; 65 string fn = pfx; fn+=f->fieldname;
68 if(!sp.has_field(fn)) continue; 66 if(!sp.has_field(fn)) continue;
69 has_fields |= f->fieldbit; 67 has_fields |= f->fieldbit;
70 response[f->fieldbit]=sp.get_field(fn); 68 response[f->fieldbit]=sp.get_field(fn);
71 } 69 }
72 } 70 }
73 71
74 void sreg_t::id_res_hook(const basic_openid_message& om, 72 void sreg_t::id_res_hook(const basic_openid_message& om,
75 const basic_openid_message& sp) { 73 const basic_openid_message& sp) {
76 rp_id_res_hook(om,sp); } 74 rp_id_res_hook(om,sp); }
77 75
78 const string& sreg_t::get_field(fieldbit_t fb) const { 76 const string& sreg_t::get_field(fieldbit_t fb) const {
79 response_t::const_iterator i = response.find(fb); 77 response_t::const_iterator i = response.find(fb);
80 if(i==response.end()) 78 if(i==response.end())
81 throw failed_lookup(OPKELE_CP_ "no field data available"); 79 throw failed_lookup(OPKELE_CP_ "no field data available");
82 return i->second; 80 return i->second;
83 } 81 }
84 82
85 void sreg_t::set_field(fieldbit_t fb,const string& fv) { 83 void sreg_t::set_field(fieldbit_t fb,const string& fv) {
86 response[fb] = fv; 84 response[fb] = fv;
87 has_fields |= fb; 85 has_fields |= fb;
88 } 86 }
89 87
90 void sreg_t::reset_field(fieldbit_t fb) { 88 void sreg_t::reset_field(fieldbit_t fb) {
91 has_fields &= ~fb; 89 has_fields &= ~fb;
92 response.erase(fb); 90 response.erase(fb);
93 } 91 }
94 92
95 void sreg_t::clear() { 93 void sreg_t::clear() {
96 has_fields = 0; response.clear(); 94 has_fields = 0; response.clear();
97 } 95 }
98 96
99 static long fields_list_to_bitmask(string& fl) { 97 static long fields_list_to_bitmask(string& fl) {
100 long rv = 0; 98 long rv = 0;
101 while(!fl.empty()) { 99 while(!fl.empty()) {
102 string::size_type co = fl.find(','); 100 string::size_type co = fl.find(',');
103 string fn; 101 string fn;
104 if(co==string::npos) { 102 if(co==string::npos) {
105 fn = fl; fl.erase(); 103 fn = fl; fl.erase();
106 }else{ 104 }else{
107 fn = fl.substr(0,co); fl.erase(0,co+1); 105 fn = fl.substr(0,co); fl.erase(0,co+1);
108 } 106 }
109 fields_iterator f = find(fields_BEGIN,fields_END,fn); 107 fields_iterator f = find(fields_BEGIN,fields_END,fn);
110 if(f!=fields_END) 108 if(f!=fields_END)
111 rv |= f->fieldbit; 109 rv |= f->fieldbit;
diff --git a/lib/verify_op.cc b/lib/verify_op.cc
index ab21b4f..c493c12 100644
--- a/lib/verify_op.cc
+++ b/lib/verify_op.cc
@@ -1,53 +1,53 @@
1#include <opkele/verify_op.h> 1#include <opkele/verify_op.h>
2#include <opkele/discovery.h> 2#include <opkele/discovery.h>
3#include <opkele/exception.h> 3#include <opkele/exception.h>
4#include <opkele/util.h> 4#include <opkele/util.h>
5#include <opkele/uris.h> 5#include <opkele/uris.h>
6 6
7namespace opkele { 7namespace opkele {
8 using std::output_iterator_tag; 8 using std::output_iterator_tag;
9 9
10 class __RP_verifier_good_input : public exception { 10 class __RP_verifier_good_input : public exception {
11 public: 11 public:
12 __RP_verifier_good_input(OPKELE_E_PARS) 12 __RP_verifier_good_input(OPKELE_E_PARS)
13 : exception(OPKELE_E_CONS) { } 13 : exception(OPKELE_E_CONS) { }
14 }; 14 };
15 15
16 class RP_verifier : public iterator<output_iterator_tag,openid_endpoint_t,void> { 16 class RP_verifier : public iterator<output_iterator_tag,openid_endpoint_t,void> {
17 public: 17 public:
18 int seen;
19 const string& return_to; 18 const string& return_to;
19 int seen;
20 20
21 RP_verifier(const string& rt) 21 RP_verifier(const string& rt)
22 : return_to(rt), seen(0) { } 22 : return_to(rt), seen(0) { }
23 23
24 RP_verifier& operator*() { return *this; } 24 RP_verifier& operator*() { return *this; }
25 RP_verifier& operator=(const openid_endpoint_t& oep) { 25 RP_verifier& operator=(const openid_endpoint_t& oep) {
26 if(util::uri_matches_realm(return_to,oep.uri)) 26 if(util::uri_matches_realm(return_to,oep.uri))
27 throw __RP_verifier_good_input(OPKELE_CP_ "Found matching realm"); 27 throw __RP_verifier_good_input(OPKELE_CP_ "Found matching realm");
28 return *this; 28 return *this;
29 } 29 }
30 30
31 RP_verifier& operator++() { ++seen; return *this; } 31 RP_verifier& operator++() { ++seen; return *this; }
32 RP_verifier& operator++(int) { +seen; return *this; } 32 RP_verifier& operator++(int) { ++seen; return *this; }
33 }; 33 };
34 34
35 void verify_OP::verify_return_to() { 35 void verify_OP::verify_return_to() {
36 basic_OP::verify_return_to(); 36 basic_OP::verify_return_to();
37 try { 37 try {
38 RP_verifier rpv(return_to); 38 RP_verifier rpv(return_to);
39 string drealm = realm; 39 string drealm = realm;
40 string::size_type csss = drealm.find("://*."); 40 string::size_type csss = drealm.find("://*.");
41 if(csss==4 || csss==5) 41 if(csss==4 || csss==5)
42 drealm.replace(csss+3,1,"www"); 42 drealm.replace(csss+3,1,"www");
43 const char *rtt[] = { STURI_OPENID20_RT, 0 }; 43 const char *rtt[] = { STURI_OPENID20_RT, 0 };
44 yadiscover(rpv,drealm,rtt,false); 44 yadiscover(rpv,drealm,rtt,false);
45 if(rpv.seen) 45 if(rpv.seen)
46 throw bad_return_to(OPKELE_CP_ "return_to URL doesn't match any found while doing discovery on RP"); 46 throw bad_return_to(OPKELE_CP_ "return_to URL doesn't match any found while doing discovery on RP");
47 }catch(__RP_verifier_good_input&) { 47 }catch(__RP_verifier_good_input&) {
48 }catch(bad_return_to& brt) { 48 }catch(bad_return_to& brt) {
49 throw; 49 throw;
50 }catch(exception_network&) { } 50 }catch(exception_network&) { }
51 } 51 }
52 52
53} 53}