author | Michael Krelin <hacker@klever.net> | 2008-02-04 22:39:59 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2008-02-04 22:39:59 (UTC) |
commit | 9163a26ec8839a31df888920418280a62ebc5595 (patch) (unidiff) | |
tree | 55339b4ecf0a3f24817eb5cc1b0b24f831ac895b | |
parent | c0eeee1cfd41d0f5f6ff6ac3d6fe021421376a69 (diff) | |
download | libopkele-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>
-rw-r--r-- | include/opkele/basic_op.h | 3 | ||||
-rw-r--r-- | include/opkele/extension.h | 49 | ||||
-rw-r--r-- | include/opkele/extension_chain.h | 6 | ||||
-rw-r--r-- | include/opkele/sreg.h | 31 | ||||
-rw-r--r-- | lib/basic_op.cc | 5 | ||||
-rw-r--r-- | lib/basic_rp.cc | 4 | ||||
-rw-r--r-- | lib/extension.cc | 25 | ||||
-rw-r--r-- | lib/extension_chain.cc | 27 | ||||
-rw-r--r-- | lib/sreg.cc | 28 | ||||
-rw-r--r-- | test/OP.cc | 10 |
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 | |||
@@ -35,17 +35,18 @@ namespace opkele { | |||
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( |
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,62 +1,57 @@ | |||
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 | ||
11 | namespace opkele { | 12 | namespace 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 | }; |
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 | |||
@@ -23,16 +23,22 @@ namespace opkele { | |||
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 | |||
@@ -130,28 +130,27 @@ namespace opkele { | |||
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; } |
@@ -186,18 +185,20 @@ namespace opkele { | |||
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 | |||
@@ -188,19 +188,21 @@ namespace opkele { | |||
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_ |
@@ -219,16 +221,17 @@ namespace opkele { | |||
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"); |
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 | |||
@@ -124,17 +124,17 @@ namespace opkele { | |||
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 | ||
@@ -270,17 +270,17 @@ namespace opkele { | |||
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")) { |
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 | ||
4 | namespace opkele { | 4 | namespace 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 | ||
4 | namespace opkele { | 4 | namespace 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 | |||
@@ -23,17 +23,17 @@ namespace opkele { | |||
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+=","; |
@@ -41,17 +41,21 @@ namespace opkele { | |||
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) { |
@@ -62,16 +66,20 @@ namespace opkele { | |||
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) { |
@@ -100,41 +108,53 @@ namespace opkele { | |||
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 | } |
@@ -9,16 +9,17 @@ using namespace std; | |||
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 | ||
21 | static const string get_self_url(const kingate::cgi_gateway& gw) { | 22 | static 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"); |
@@ -264,28 +265,33 @@ int main(int argc,char *argv[]) { | |||
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); |