summaryrefslogtreecommitdiffabout
authorMichael Krelin <hacker@klever.net>2008-02-04 22:39:59 (UTC)
committer Michael Krelin <hacker@klever.net>2008-02-04 22:39:59 (UTC)
commit9163a26ec8839a31df888920418280a62ebc5595 (patch) (unidiff)
tree55339b4ecf0a3f24817eb5cc1b0b24f831ac895b
parentc0eeee1cfd41d0f5f6ff6ac3d6fe021421376a69 (diff)
downloadlibopkele-9163a26ec8839a31df888920418280a62ebc5595.zip
libopkele-9163a26ec8839a31df888920418280a62ebc5595.tar.gz
libopkele-9163a26ec8839a31df888920418280a62ebc5595.tar.bz2
reworked extensions framework
* changed {checkid,id_res}_hook to {rp,op}_{checkid,id_res}_hook * deprecated older hooks, although implemented it in sreg and chain extensions * added extension processing to basic_op * added sreg to test OP Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--include/opkele/basic_op.h3
-rw-r--r--include/opkele/extension.h49
-rw-r--r--include/opkele/extension_chain.h6
-rw-r--r--include/opkele/sreg.h31
-rw-r--r--lib/basic_op.cc5
-rw-r--r--lib/basic_rp.cc4
-rw-r--r--lib/extension.cc25
-rw-r--r--lib/extension_chain.cc27
-rw-r--r--lib/sreg.cc28
-rw-r--r--test/OP.cc10
10 files changed, 121 insertions, 67 deletions
diff --git a/include/opkele/basic_op.h b/include/opkele/basic_op.h
index 7f4e481..5bba1bf 100644
--- a/include/opkele/basic_op.h
+++ b/include/opkele/basic_op.h
@@ -31,25 +31,26 @@ namespace opkele {
31 const string& get_identity() const; 31 const string& get_identity() const;
32 32
33 bool is_id_select() const; 33 bool is_id_select() const;
34 34
35 void select_identity(const string& c,const string& i); 35 void select_identity(const string& c,const string& i);
36 void set_claimed_id(const string& c); 36 void set_claimed_id(const string& c);
37 37
38 basic_openid_message& associate( 38 basic_openid_message& associate(
39 basic_openid_message& oum, 39 basic_openid_message& oum,
40 const basic_openid_message& inm); 40 const basic_openid_message& inm);
41 41
42 void checkid_(const basic_openid_message& inm,extension_t *ext=0); 42 void checkid_(const basic_openid_message& inm,extension_t *ext=0);
43 basic_openid_message& id_res(basic_openid_message& om); 43 basic_openid_message& id_res(basic_openid_message& om,
44 extension_t *ext=0);
44 basic_openid_message& cancel(basic_openid_message& om); 45 basic_openid_message& cancel(basic_openid_message& om);
45 basic_openid_message& error(basic_openid_message& om, 46 basic_openid_message& error(basic_openid_message& om,
46 const string& error,const string& contact, 47 const string& error,const string& contact,
47 const string& reference ); 48 const string& reference );
48 basic_openid_message& setup_needed( 49 basic_openid_message& setup_needed(
49 basic_openid_message& oum,const basic_openid_message& inm); 50 basic_openid_message& oum,const basic_openid_message& inm);
50 51
51 basic_openid_message& check_authentication( 52 basic_openid_message& check_authentication(
52 basic_openid_message& oum,const basic_openid_message& inm); 53 basic_openid_message& oum,const basic_openid_message& inm);
53 54
54 virtual void verify_return_to(); 55 virtual void verify_return_to();
55 56
diff --git a/include/opkele/extension.h b/include/opkele/extension.h
index 3ee25ee..37bcb90 100644
--- a/include/opkele/extension.h
+++ b/include/opkele/extension.h
@@ -1,66 +1,61 @@
1#ifndef __OPKELE_EXTENSION_H 1#ifndef __OPKELE_EXTENSION_H
2#define __OPKELE_EXTENSION_H 2#define __OPKELE_EXTENSION_H
3 3
4/** 4/**
5 * @file 5 * @file
6 * @brief extensions framework basics 6 * @brief extensions framework basics
7 */ 7 */
8 8
9#include <opkele/opkele-config.h>
9#include <opkele/types.h> 10#include <opkele/types.h>
10 11
11namespace opkele { 12namespace opkele {
12 13
13 /** 14 /**
14 * OpenID extension hooks base class 15 * OpenID extension hooks base class
15 */ 16 */
16 class extension_t { 17 class extension_t {
17 public: 18 public:
18 19
19 virtual ~extension_t() { } 20 virtual ~extension_t() { }
20 21
21 /** 22 /**
22 * hook called by consumer before submitting data to OpenID server. 23 * hook called by RP before submitting the message to OP.
23 * It is supposed to manipulate parameters list. 24 * @param om openid message to be submit
24 * @param p parameters about to be submitted to server
25 * @param identity identity being verified. It may differ from the
26 * one available in parameters list in case of delegation
27 * @see consumer_t::checkid_
28 * @see consumer_t::checkid_immediate
29 * @see consumer_t::checkid_setup
30 */ 25 */
31 virtual void checkid_hook(basic_openid_message& om); 26 virtual void rp_checkid_hook(basic_openid_message& om);
27
32 /** 28 /**
33 * hook called by consumer after identity information received from 29 * hook called by RP after verifying information received from OP.
34 * OpenID server is verified. 30 * @param om openid message received
35 * @param p parameters received from server 31 * @param sp signed part of the message
36 * @param sp signed parameters received from server with 'openid.'
37 * leader stripped
38 * @param identity identity confirmed. May differ from the one
39 * available in parameters list in case of delegation. May also be
40 * empty which means - extract one from parameters
41 * @see consumer_t::id_res
42 */ 32 */
43 virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp); 33 virtual void rp_id_res_hook(const basic_openid_message& om,
34 const basic_openid_message& sp);
44 35
45 /** 36 /**
46 * hook called by server before returning information to consumer. 37 * hook called by OP after parsing incoming message
47 * The hook may manipulate output parameters. It is important to 38 * @param inm message received from RP
48 * note that modified pout["signed"] is used for signing response. 39 */
49 * @param pin request parameters list with "openid." prefix 40 virtual void op_checkid_hook(const basic_openid_message& inm);
50 * @param pout response parameters list without "openid." prefix 41 /**
51 * @see server_t::checkid_ 42 * hook called by OP before signing the reply to RP
52 * @see server_t::checkid_immediate 43 * @param oum message to be sent to RP
53 * @see server_t::checkid_setup
54 */ 44 */
45 virtual void op_id_res_hook(basic_openid_message& oum);
46
47 virtual void checkid_hook(basic_openid_message& om) OPKELE_DEPRECATE;
48 virtual void id_res_hook(const basic_openid_message& om,
49 const basic_openid_message& sp) OPKELE_DEPRECATE;
55 virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum); 50 virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
56 51
57 /** 52 /**
58 * Casts the object to pointer to itself. For convenient passing 53 * Casts the object to pointer to itself. For convenient passing
59 * of pointer. 54 * of pointer.
60 */ 55 */
61 operator extension_t*(void) { return this; } 56 operator extension_t*(void) { return this; }
62 }; 57 };
63 58
64} 59}
65 60
66#endif /* __OPKELE_EXTENSION_H */ 61#endif /* __OPKELE_EXTENSION_H */
diff --git a/include/opkele/extension_chain.h b/include/opkele/extension_chain.h
index fb9bc84..9692934 100644
--- a/include/opkele/extension_chain.h
+++ b/include/opkele/extension_chain.h
@@ -19,20 +19,26 @@ namespace opkele {
19 class extension_chain_t : public extension_t, public list<extension_t*> { 19 class extension_chain_t : public extension_t, public list<extension_t*> {
20 public: 20 public:
21 21
22 /** 22 /**
23 * Default constructor creates an empty chain 23 * Default constructor creates an empty chain
24 */ 24 */
25 extension_chain_t() { } 25 extension_chain_t() { }
26 /** 26 /**
27 * Create extension chain with a single extension in it 27 * Create extension chain with a single extension in it
28 */ 28 */
29 extension_chain_t(extension_t *e) { push_back(e); } 29 extension_chain_t(extension_t *e) { push_back(e); }
30 30
31 virtual void rp_checkid_hook(basic_openid_message& om);
32 virtual void rp_id_res_hook(const basic_openid_message& om,
33 const basic_openid_message& sp);
34 virtual void op_checkid_hook(const basic_openid_message& inm);
35 virtual void op_id_res_hook(basic_openid_message& oum);
36
31 virtual void checkid_hook(basic_openid_message& om); 37 virtual void checkid_hook(basic_openid_message& om);
32 virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp); 38 virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp);
33 virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum); 39 virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
34 }; 40 };
35 41
36} 42}
37 43
38#endif /* __OPKELE_EXTENSION_CHAIN_H */ 44#endif /* __OPKELE_EXTENSION_CHAIN_H */
diff --git a/include/opkele/sreg.h b/include/opkele/sreg.h
index 24cb315..513e221 100644
--- a/include/opkele/sreg.h
+++ b/include/opkele/sreg.h
@@ -126,36 +126,35 @@ namespace opkele {
126 /** 126 /**
127 * Consumer constructor. 127 * Consumer constructor.
128 * @param fr required fields 128 * @param fr required fields
129 * @see fields_required 129 * @see fields_required
130 * @param fo optional fields 130 * @param fo optional fields
131 * @see fields_optional 131 * @see fields_optional
132 * @param pu policy url 132 * @param pu policy url
133 * @see policy_url 133 * @see policy_url
134 */ 134 */
135 sreg_t(long fr=fields_NONE,long fo=fields_NONE,const string& pu="") 135 sreg_t(long fr=fields_NONE,long fo=fields_NONE,const string& pu="")
136 : fields_required(fr), fields_optional(fo), policy_url(pu), has_fields(0) { } 136 : fields_required(fr), fields_optional(fo), policy_url(pu), has_fields(0) { }
137 137
138 /** 138 virtual void rp_checkid_hook(basic_openid_message& om);
139 * Implementation of consumer's checkid hook 139 virtual void rp_id_res_hook(const basic_openid_message& om,
140 */ 140 const basic_openid_message& sp);
141 virtual void op_checkid_hook(const basic_openid_message& inm);
142 virtual void op_id_res_hook(basic_openid_message& oum);
143
141 virtual void checkid_hook(basic_openid_message& om); 144 virtual void checkid_hook(basic_openid_message& om);
142 /** 145 virtual void id_res_hook(const basic_openid_message& om,
143 * Implementation of consumer's id_res hook 146 const basic_openid_message& sp);
144 */ 147 virtual void checkid_hook(const basic_openid_message& inm,
145 virtual void id_res_hook(const basic_openid_message& om,const basic_openid_message& sp); 148 basic_openid_message& oum);
146 /**
147 * Implementation of server's checkid_hook
148 */
149 virtual void checkid_hook(const basic_openid_message& inm,basic_openid_message& oum);
150 149
151 /** 150 /**
152 * Check and see if we have value for some particular field. 151 * Check and see if we have value for some particular field.
153 * @param fb field in question 152 * @param fb field in question
154 * @see fieldbit_t 153 * @see fieldbit_t
155 * @return true if the value is available 154 * @return true if the value is available
156 */ 155 */
157 bool has_field(fieldbit_t fb) const { return has_fields&fb; } 156 bool has_field(fieldbit_t fb) const { return has_fields&fb; }
158 157
159 /** 158 /**
160 * Retrieve the value for a field. 159 * Retrieve the value for a field.
161 * @param fb field in question 160 * @param fb field in question
@@ -182,22 +181,24 @@ namespace opkele {
182 181
183 /** 182 /**
184 * Reset field data 183 * Reset field data
185 */ 184 */
186 void clear(); 185 void clear();
187 186
188 /** 187 /**
189 * Function called after parsing sreg request to set up response 188 * Function called after parsing sreg request to set up response
190 * fields. The default implementation tries to send as much fields 189 * fields. The default implementation tries to send as much fields
191 * as we have. The function is supposed to set the data and 190 * as we have. The function is supposed to set the data and
192 * fields_response. 191 * fields_response.
193 * @see fields_response 192 * @see fields_response
194 * @param pin input request parameters with "openid." prefix 193 * @param inm incoming openid message
195 * @param pout output request parameters without "openid." prefix. 194 * @param oum outgoing openid message
196 * @see checkid_hook(const params_t&,params_t&)
197 */ 195 */
198 virtual void setup_response(const basic_openid_message& inm,basic_openid_message& oum); 196 virtual void setup_response(const basic_openid_message& inm,
197 basic_openid_message& oum);
198
199 virtual void setup_response();
199 200
200 }; 201 };
201} 202}
202 203
203#endif /* __OPKELE_SREG_H */ 204#endif /* __OPKELE_SREG_H */
diff --git a/lib/basic_op.cc b/lib/basic_op.cc
index c89d1d7..9e2ea5a 100644
--- a/lib/basic_op.cc
+++ b/lib/basic_op.cc
@@ -184,27 +184,29 @@ namespace opkele {
184 }catch(failed_lookup&) { 184 }catch(failed_lookup&) {
185 if(openid2) 185 if(openid2)
186 throw bad_input(OPKELE_CP_ 186 throw bad_input(OPKELE_CP_
187 "claimed_id and identity must be either both present or both absent"); 187 "claimed_id and identity must be either both present or both absent");
188 claimed_id = identity; 188 claimed_id = identity;
189 } 189 }
190 }catch(failed_lookup&) { 190 }catch(failed_lookup&) {
191 if(openid2 && inm.has_field("claimed_id")) 191 if(openid2 && inm.has_field("claimed_id"))
192 throw bad_input(OPKELE_CP_ 192 throw bad_input(OPKELE_CP_
193 "claimed_id and identity must be either both present or both absent"); 193 "claimed_id and identity must be either both present or both absent");
194 } 194 }
195 verify_return_to(); 195 verify_return_to();
196 if(ext) ext->op_checkid_hook(inm);
196 } 197 }
197 198
198 basic_openid_message& basic_op::id_res(basic_openid_message& om) { 199 basic_openid_message& basic_op::id_res(basic_openid_message& om,
200 extension_t *ext) {
199 assert(assoc); 201 assert(assoc);
200 assert(!return_to.empty()); 202 assert(!return_to.empty());
201 assert(!is_id_select()); 203 assert(!is_id_select());
202 time_t now = time(0); 204 time_t now = time(0);
203 struct tm gmt; gmtime_r(&now,&gmt); 205 struct tm gmt; gmtime_r(&now,&gmt);
204 char w3timestr[24]; 206 char w3timestr[24];
205 if(!strftime(w3timestr,sizeof(w3timestr),"%Y-%m-%dT%H:%M:%SZ",&gmt)) 207 if(!strftime(w3timestr,sizeof(w3timestr),"%Y-%m-%dT%H:%M:%SZ",&gmt))
206 throw failed_conversion(OPKELE_CP_ 208 throw failed_conversion(OPKELE_CP_
207 "Failed to build time string for nonce" ); 209 "Failed to build time string for nonce" );
208 om.set_field("ns",OIURI_OPENID20); 210 om.set_field("ns",OIURI_OPENID20);
209 om.set_field("mode","id_res"); 211 om.set_field("mode","id_res");
210 om.set_field("op_endpoint",get_op_endpoint()); 212 om.set_field("op_endpoint",get_op_endpoint());
@@ -215,24 +217,25 @@ namespace opkele {
215 om.set_field("claimed_id",claimed_id); 217 om.set_field("claimed_id",claimed_id);
216 ats += ",identity,claimed_id"; 218 ats += ",identity,claimed_id";
217 } 219 }
218 om.set_field("return_to",return_to); 220 om.set_field("return_to",return_to);
219 string nonce = w3timestr; 221 string nonce = w3timestr;
220 om.set_field("response_nonce",alloc_nonce(nonce,assoc->stateless())); 222 om.set_field("response_nonce",alloc_nonce(nonce,assoc->stateless()));
221 if(!invalidate_handle.empty()) { 223 if(!invalidate_handle.empty()) {
222 om.set_field("invalidate_handle",invalidate_handle); 224 om.set_field("invalidate_handle",invalidate_handle);
223 ats += ",invalidate_handle"; 225 ats += ",invalidate_handle";
224 } 226 }
225 om.set_field("assoc_handle",assoc->handle()); 227 om.set_field("assoc_handle",assoc->handle());
226 om.add_to_signed(ats); 228 om.add_to_signed(ats);
229 if(ext) ext->op_id_res_hook(om);
227 om.set_field("sig",util::base64_signature(assoc,om)); 230 om.set_field("sig",util::base64_signature(assoc,om));
228 return om; 231 return om;
229 } 232 }
230 233
231 basic_openid_message& basic_op::cancel(basic_openid_message& om) { 234 basic_openid_message& basic_op::cancel(basic_openid_message& om) {
232 assert(!return_to.empty()); 235 assert(!return_to.empty());
233 om.set_field("ns",OIURI_OPENID20); 236 om.set_field("ns",OIURI_OPENID20);
234 om.set_field("mode","cancel"); 237 om.set_field("mode","cancel");
235 return om; 238 return om;
236 } 239 }
237 240
238 basic_openid_message& basic_op::error(basic_openid_message& om, 241 basic_openid_message& basic_op::error(basic_openid_message& om,
diff --git a/lib/basic_rp.cc b/lib/basic_rp.cc
index a884583..bd45d99 100644
--- a/lib/basic_rp.cc
+++ b/lib/basic_rp.cc
@@ -120,25 +120,25 @@ namespace opkele {
120 rv.set_field("return_to",return_to); 120 rv.set_field("return_to",return_to);
121 const openid_endpoint_t& ep = get_endpoint(); 121 const openid_endpoint_t& ep = get_endpoint();
122 rv.set_field("claimed_id",ep.claimed_id); 122 rv.set_field("claimed_id",ep.claimed_id);
123 rv.set_field("identity",ep.local_id); 123 rv.set_field("identity",ep.local_id);
124 try { 124 try {
125 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle()); 125 rv.set_field("assoc_handle",find_assoc(ep.uri)->handle());
126 }catch(dumb_RP& drp) { 126 }catch(dumb_RP& drp) {
127 }catch(failed_lookup& fl) { 127 }catch(failed_lookup& fl) {
128 try { 128 try {
129 rv.set_field("assoc_handle",associate(ep.uri)->handle()); 129 rv.set_field("assoc_handle",associate(ep.uri)->handle());
130 }catch(dumb_RP& drp) { } 130 }catch(dumb_RP& drp) { }
131 } OPKELE_RETHROW 131 } OPKELE_RETHROW
132 if(ext) ext->checkid_hook(rv); 132 if(ext) ext->rp_checkid_hook(rv);
133 return rv; 133 return rv;
134 } 134 }
135 135
136 class signed_part_message_proxy : public basic_openid_message { 136 class signed_part_message_proxy : public basic_openid_message {
137 public: 137 public:
138 const basic_openid_message& x; 138 const basic_openid_message& x;
139 set<string> signeds; 139 set<string> signeds;
140 140
141 signed_part_message_proxy(const basic_openid_message& xx) : x(xx) { 141 signed_part_message_proxy(const basic_openid_message& xx) : x(xx) {
142 const string& slist = x.get_field("signed"); 142 const string& slist = x.get_field("signed");
143 string::size_type p = 0; 143 string::size_type p = 0;
144 while(true) { 144 while(true) {
@@ -266,25 +266,25 @@ namespace opkele {
266 if(tpi->second!=rpi->second) 266 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"); 267 throw id_res_bad_return_to(OPKELE_CP_ string("Parameter '")+rpi->first+"' from return_to doesn't matche the request");
268 } 268 }
269 269
270 if(om.has_field("claimed_id")) { 270 if(om.has_field("claimed_id")) {
271 verify_OP( 271 verify_OP(
272 om.get_field("op_endpoint"), 272 om.get_field("op_endpoint"),
273 om.get_field("claimed_id"), 273 om.get_field("claimed_id"),
274 om.get_field("identity") ); 274 om.get_field("identity") );
275 } 275 }
276 276
277 } 277 }
278 if(ext) ext->id_res_hook(om,signeds); 278 if(ext) ext->rp_id_res_hook(om,signeds);
279 } 279 }
280 280
281 void basic_RP::check_authentication(const string& OP, 281 void basic_RP::check_authentication(const string& OP,
282 const basic_openid_message& om){ 282 const basic_openid_message& om){
283 openid_message_t res; 283 openid_message_t res;
284 static const string checkauthmode = "check_authentication"; 284 static const string checkauthmode = "check_authentication";
285 direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP); 285 direct_request(res,util::change_mode_message_proxy(om,checkauthmode),OP);
286 if(res.has_field("is_valid")) { 286 if(res.has_field("is_valid")) {
287 if(res.get_field("is_valid")=="true") { 287 if(res.get_field("is_valid")=="true") {
288 if(res.has_field("invalidate_handle")) 288 if(res.has_field("invalidate_handle"))
289 invalidate_assoc(OP,res.get_field("invalidate_handle")); 289 invalidate_assoc(OP,res.get_field("invalidate_handle"));
290 return; 290 return;
diff --git a/lib/extension.cc b/lib/extension.cc
index 6451249..f7aaea5 100644
--- a/lib/extension.cc
+++ b/lib/extension.cc
@@ -1,15 +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&) {
7 throw not_implemented(OPKELE_CP_ "RP checkid_* hook not implemented"); }
8 void extension_t::rp_id_res_hook(const basic_openid_message&,
9 const basic_openid_message&) {
10 throw not_implemented(OPKELE_CP_ "RP id_res hook not implemented"); }
11
12 void extension_t::op_checkid_hook(const basic_openid_message&) {
13 throw not_implemented(OPKELE_CP_ "OP checkid_* hook not implemented"); }
14 void extension_t::op_id_res_hook(basic_openid_message& om) {
15 throw not_implemented(OPKELE_CP_ "OP id_res hook not implemented"); }
16
17
6 void extension_t::checkid_hook(basic_openid_message&) { 18 void extension_t::checkid_hook(basic_openid_message&) {
7 throw not_implemented(OPKELE_CP_ "Consumer checkid_hook not implemented"); 19 throw not_implemented(OPKELE_CP_ "deprecated consumer checkid_* hook not implemented"); }
8 } 20 void extension_t::id_res_hook(const basic_openid_message&,
9 void extension_t::id_res_hook(const basic_openid_message&,const basic_openid_message&) { 21 const basic_openid_message&) {
10 throw not_implemented(OPKELE_CP_ "Consumer id_res_hook not implemented"); 22 throw not_implemented(OPKELE_CP_ "deprecated consumer id_res hook not implemented"); }
11 } 23
12 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&) {
13 throw not_implemented(OPKELE_CP_ "Server checkid_hook not implemented"); 25 throw not_implemented(OPKELE_CP_ "deprecated server checkid hook not implemented"); }
14 }
15} 26}
diff --git a/lib/extension_chain.cc b/lib/extension_chain.cc
index 5c2afd9..5483740 100644
--- a/lib/extension_chain.cc
+++ b/lib/extension_chain.cc
@@ -1,16 +1,27 @@
1#include <cstdarg> 1#include <cstdarg>
2#include <opkele/extension_chain.h> 2#include <opkele/extension_chain.h>
3 3
4namespace opkele { 4namespace opkele {
5 5
6 void extension_chain_t::rp_checkid_hook(basic_openid_message& om) {
7 for(iterator i=begin();i!=end();++i) (*i)->rp_checkid_hook(om); }
8 void extension_chain_t::rp_id_res_hook(const basic_openid_message& om,
9 const basic_openid_message& sp) {
10 for(iterator i=begin();i!=end();++i) (*i)->rp_id_res_hook(om,sp); }
11
12 void extension_chain_t::op_checkid_hook(const basic_openid_message& inm) {
13 for(iterator i=begin();i!=end();++i) (*i)->op_checkid_hook(inm); }
14 void extension_chain_t::op_id_res_hook(basic_openid_message& oum) {
15 for(iterator i=begin();i!=end();++i) (*i)->op_id_res_hook(oum); }
16
17
6 void extension_chain_t::checkid_hook(basic_openid_message& om){ 18 void extension_chain_t::checkid_hook(basic_openid_message& om){
7 for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(om); 19 for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(om); }
8 } 20 void extension_chain_t::id_res_hook(const basic_openid_message& om,
9 void extension_chain_t::id_res_hook(const basic_openid_message& om,const basic_openid_message& sp) { 21 const basic_openid_message& sp) {
10 for(iterator i=begin();i!=end();++i) (*i)->id_res_hook(om,sp); 22 for(iterator i=begin();i!=end();++i) (*i)->id_res_hook(om,sp); }
11 } 23 void extension_chain_t::checkid_hook(const basic_openid_message& inm,
12 void extension_chain_t::checkid_hook(const basic_openid_message& inm,basic_openid_message& oum) { 24 basic_openid_message& oum) {
13 for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(inm,oum); 25 for(iterator i=begin();i!=end();++i) (*i)->checkid_hook(inm,oum); }
14 }
15 26
16} 27}
diff --git a/lib/sreg.cc b/lib/sreg.cc
index 7e2d588..b40cd45 100644
--- a/lib/sreg.cc
+++ b/lib/sreg.cc
@@ -19,63 +19,71 @@ namespace opkele {
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::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::id_res_hook(const basic_openid_message& om,const basic_openid_message& sp) { 49 void sreg_t::checkid_hook(basic_openid_message& om) {
50 rp_checkid_hook(om); }
51
52 void sreg_t::rp_id_res_hook(const basic_openid_message& om,
53 const basic_openid_message& sp) {
50 clear(); 54 clear();
51 string pfx; 55 string pfx;
52 try { 56 try {
53 pfx = om.find_ns(OIURI_SREG11,"sreg"); 57 pfx = om.find_ns(OIURI_SREG11,"sreg");
54 }catch(failed_lookup& fl) { 58 }catch(failed_lookup& fl) {
55 try { 59 try {
56 pfx = om.find_ns(OIURI_SREG10,"sreg"); 60 pfx = om.find_ns(OIURI_SREG10,"sreg");
57 }catch(failed_lookup& fl) { 61 }catch(failed_lookup& fl) {
58 return; 62 return;
59 } 63 }
60 } 64 }
61 pfx += '.'; 65 pfx += '.';
62 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) { 66 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) {
63 string fn = pfx; fn+=f->fieldname; 67 string fn = pfx; fn+=f->fieldname;
64 if(!sp.has_field(fn)) continue; 68 if(!sp.has_field(fn)) continue;
65 has_fields |= f->fieldbit; 69 has_fields |= f->fieldbit;
66 response[f->fieldbit]=sp.get_field(fn); 70 response[f->fieldbit]=sp.get_field(fn);
67 } 71 }
68 } 72 }
69 73
74 void sreg_t::id_res_hook(const basic_openid_message& om,
75 const basic_openid_message& sp) {
76 rp_id_res_hook(om,sp); }
77
70 const string& sreg_t::get_field(fieldbit_t fb) const { 78 const string& sreg_t::get_field(fieldbit_t fb) const {
71 response_t::const_iterator i = response.find(fb); 79 response_t::const_iterator i = response.find(fb);
72 if(i==response.end()) 80 if(i==response.end())
73 throw failed_lookup(OPKELE_CP_ "no field data available"); 81 throw failed_lookup(OPKELE_CP_ "no field data available");
74 return i->second; 82 return i->second;
75 } 83 }
76 84
77 void sreg_t::set_field(fieldbit_t fb,const string& fv) { 85 void sreg_t::set_field(fieldbit_t fb,const string& fv) {
78 response[fb] = fv; 86 response[fb] = fv;
79 has_fields |= fb; 87 has_fields |= fb;
80 } 88 }
81 89
@@ -96,45 +104,57 @@ namespace opkele {
96 if(co==string::npos) { 104 if(co==string::npos) {
97 fn = fl; fl.erase(); 105 fn = fl; fl.erase();
98 }else{ 106 }else{
99 fn = fl.substr(0,co); fl.erase(0,co+1); 107 fn = fl.substr(0,co); fl.erase(0,co+1);
100 } 108 }
101 fields_iterator f = find(fields_BEGIN,fields_END,fn); 109 fields_iterator f = find(fields_BEGIN,fields_END,fn);
102 if(f!=fields_END) 110 if(f!=fields_END)
103 rv |= f->fieldbit; 111 rv |= f->fieldbit;
104 } 112 }
105 return rv; 113 return rv;
106 } 114 }
107 115
108 void sreg_t::checkid_hook(const basic_openid_message& inm,basic_openid_message& oum) { 116 void sreg_t::op_checkid_hook(const basic_openid_message& inm) {
109 string ins = inm.find_ns(OIURI_SREG11,"sreg"); 117 string ins = inm.find_ns(OIURI_SREG11,"sreg");
110 fields_optional = 0; fields_required = 0; policy_url.erase(); 118 fields_optional = 0; fields_required = 0; policy_url.erase();
111 fields_response = 0; 119 fields_response = 0;
112 try { 120 try {
113 string fl = inm.get_field(ins+".required"); 121 string fl = inm.get_field(ins+".required");
114 fields_required = fields_list_to_bitmask(fl); 122 fields_required = fields_list_to_bitmask(fl);
115 }catch(failed_lookup&) { } 123 }catch(failed_lookup&) { }
116 try { 124 try {
117 string fl = inm.get_field(ins+".optional"); 125 string fl = inm.get_field(ins+".optional");
118 fields_optional = fields_list_to_bitmask(fl); 126 fields_optional = fields_list_to_bitmask(fl);
119 }catch(failed_lookup&) { } 127 }catch(failed_lookup&) { }
120 try { 128 try {
121 policy_url = inm.get_field(ins+".policy_url"); 129 policy_url = inm.get_field(ins+".policy_url");
122 }catch(failed_lookup&) { } 130 }catch(failed_lookup&) { }
123 setup_response(inm,oum); 131 }
132
133 void sreg_t::op_id_res_hook(basic_openid_message& oum) {
124 string ons = oum.allocate_ns(OIURI_SREG11,"sreg"); 134 string ons = oum.allocate_ns(OIURI_SREG11,"sreg");
125 fields_response &= has_fields; 135 fields_response &= has_fields;
126 string signeds = "ns."+ons; 136 string signeds = "ns."+ons;
127 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) { 137 for(fields_iterator f=fields_BEGIN;f<fields_END;++f) {
128 if(!(f->fieldbit&fields_response)) continue; 138 if(!(f->fieldbit&fields_response)) continue;
129 signeds +=','; 139 signeds +=',';
130 string pn = ons; pn += '.'; pn += f->fieldname; 140 string pn = ons; pn += '.'; pn += f->fieldname;
131 signeds += pn; 141 signeds += pn;
132 oum.set_field(pn,get_field(f->fieldbit)); 142 oum.set_field(pn,get_field(f->fieldbit));
133 } 143 }
134 oum.add_to_signed(signeds); 144 oum.add_to_signed(signeds);
135 } 145 }
136 146
147 void sreg_t::checkid_hook(const basic_openid_message& inm,
148 basic_openid_message& oum) {
149 op_checkid_hook(inm);
150 setup_response(inm,oum);
151 op_id_res_hook(oum);
152 }
153
137 void sreg_t::setup_response(const basic_openid_message& /* inm */,basic_openid_message& /* oum */) { 154 void sreg_t::setup_response(const basic_openid_message& /* inm */,basic_openid_message& /* oum */) {
155 setup_response();
156 }
157 void sreg_t::setup_response() {
138 fields_response = (fields_required|fields_optional)&has_fields; 158 fields_response = (fields_required|fields_optional)&has_fields;
139 } 159 }
140} 160}
diff --git a/test/OP.cc b/test/OP.cc
index 1196c0c..c919d7f 100644
--- a/test/OP.cc
+++ b/test/OP.cc
@@ -5,24 +5,25 @@
5#include <ext/algorithm> 5#include <ext/algorithm>
6using namespace std; 6using namespace std;
7#include <kingate/exception.h> 7#include <kingate/exception.h>
8#include <kingate/plaincgi.h> 8#include <kingate/plaincgi.h>
9#include <kingate/cgi_gateway.h> 9#include <kingate/cgi_gateway.h>
10#include <opkele/exception.h> 10#include <opkele/exception.h>
11#include <opkele/util.h> 11#include <opkele/util.h>
12#include <opkele/uris.h> 12#include <opkele/uris.h>
13#include <opkele/extension.h> 13#include <opkele/extension.h>
14#include <opkele/association.h> 14#include <opkele/association.h>
15#include <opkele/debug.h> 15#include <opkele/debug.h>
16#include <opkele/verify_op.h> 16#include <opkele/verify_op.h>
17#include <opkele/sreg.h>
17 18
18#include "sqlite.h" 19#include "sqlite.h"
19#include "kingate_openid_message.h" 20#include "kingate_openid_message.h"
20 21
21static const string get_self_url(const kingate::cgi_gateway& gw) { 22static const string get_self_url(const kingate::cgi_gateway& gw) {
22 bool s = gw.has_meta("SSL_PROTOCOL_VERSION"); 23 bool s = gw.has_meta("SSL_PROTOCOL_VERSION");
23 string rv = s?"https://":"http://"; 24 string rv = s?"https://":"http://";
24 rv += gw.http_request_header("Host"); 25 rv += gw.http_request_header("Host");
25 const string& port = gw.get_meta("SERVER_PORT"); 26 const string& port = gw.get_meta("SERVER_PORT");
26 if( port!=(s?"443":"80") ) { 27 if( port!=(s?"443":"80") ) {
27 rv += ':'; rv += port; 28 rv += ':'; rv += port;
28 } 29 }
@@ -260,36 +261,41 @@ int main(int argc,char *argv[]) {
260 "<Service>" 261 "<Service>"
261 "<Type>" STURI_OPENID20_OP "</Type>" 262 "<Type>" STURI_OPENID20_OP "</Type>"
262 "<URI>" << get_self_url(gw) << "</URI>"; 263 "<URI>" << get_self_url(gw) << "</URI>";
263 } 264 }
264 cout << 265 cout <<
265 "</XRD>" 266 "</XRD>"
266 "</xrds:XRDS>"; 267 "</xrds:XRDS>";
267 }else if(op=="id_res" || op=="cancel") { 268 }else if(op=="id_res" || op=="cancel") {
268 kingate_openid_message_t inm(gw); 269 kingate_openid_message_t inm(gw);
269 example_op_t OP(gw); 270 example_op_t OP(gw);
270 if(gw.get_param("hts_id")!=OP.htc.get_value()) 271 if(gw.get_param("hts_id")!=OP.htc.get_value())
271 throw opkele::exception(OPKELE_CP_ "toying around, huh?"); 272 throw opkele::exception(OPKELE_CP_ "toying around, huh?");
272 OP.checkid_(inm,0); 273 opkele::sreg_t sreg;
274 OP.checkid_(inm,sreg);
273 OP.cookie_header(cout); 275 OP.cookie_header(cout);
274 opkele::openid_message_t om; 276 opkele::openid_message_t om;
275 if(op=="id_res") { 277 if(op=="id_res") {
276 if(!OP.get_authorized()) 278 if(!OP.get_authorized())
277 throw opkele::exception(OPKELE_CP_ "not logged in"); 279 throw opkele::exception(OPKELE_CP_ "not logged in");
278 if(OP.is_id_select()) { 280 if(OP.is_id_select()) {
279 OP.select_identity( get_self_url(gw), get_self_url(gw) ); 281 OP.select_identity( get_self_url(gw), get_self_url(gw) );
280 } 282 }
283 sreg.set_field(opkele::sreg_t::field_nickname,"anonymous");
284 sreg.set_field(opkele::sreg_t::field_fullname,"Ann O'Nymus");
285 sreg.set_field(opkele::sreg_t::field_gender,"F");
286 sreg.setup_response();
281 cout << 287 cout <<
282 "Status: 302 Going back to RP with id_res\n" 288 "Status: 302 Going back to RP with id_res\n"
283 "Location: " << OP.id_res(om).append_query(OP.get_return_to()) 289 "Location: " << OP.id_res(om,sreg).append_query(OP.get_return_to())
284 << "\n\n"; 290 << "\n\n";
285 }else{ 291 }else{
286 cout << 292 cout <<
287 "Status: 302 Going back to RP with cancel\n" 293 "Status: 302 Going back to RP with cancel\n"
288 "Location: " << OP.cancel(om).append_query(OP.get_return_to()) 294 "Location: " << OP.cancel(om).append_query(OP.get_return_to())
289 << "\n\n"; 295 << "\n\n";
290 } 296 }
291 om.to_keyvalues(clog); 297 om.to_keyvalues(clog);
292 }else if(om=="associate") { 298 }else if(om=="associate") {
293 kingate_openid_message_t inm(gw); 299 kingate_openid_message_t inm(gw);
294 opkele::openid_message_t oum; 300 opkele::openid_message_t oum;
295 example_op_t OP(gw); 301 example_op_t OP(gw);