|
|
|
@@ -1,64 +1,65 @@ |
1 | #include <uuid/uuid.h> |
1 | #include <uuid/uuid.h> |
2 | #include <iostream> |
2 | #include <iostream> |
3 | #include <cassert> |
3 | #include <cassert> |
4 | #include <string> |
4 | #include <string> |
5 | #include <ext/algorithm> |
5 | #include <ext/algorithm> |
6 | using namespace std; |
6 | using 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 | |
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"); |
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 | } |
29 | rv += gw.get_meta("REQUEST_URI"); |
30 | rv += gw.get_meta("REQUEST_URI"); |
30 | string::size_type q = rv.find('?'); |
31 | string::size_type q = rv.find('?'); |
31 | if(q!=string::npos) |
32 | if(q!=string::npos) |
32 | rv.erase(q); |
33 | rv.erase(q); |
33 | return rv; |
34 | return rv; |
34 | } |
35 | } |
35 | |
36 | |
36 | class opdb_t : public sqlite3_t { |
37 | class opdb_t : public sqlite3_t { |
37 | public: |
38 | public: |
38 | opdb_t() |
39 | opdb_t() |
39 | : sqlite3_t("/tmp/OP.db") { |
40 | : sqlite3_t("/tmp/OP.db") { |
40 | assert(_D); |
41 | assert(_D); |
41 | char **resp; int nr,nc; char *errm; |
42 | char **resp; int nr,nc; char *errm; |
42 | if(sqlite3_get_table( |
43 | if(sqlite3_get_table( |
43 | _D, "SELECT a_op FROM assoc LIMIT 0", |
44 | _D, "SELECT a_op FROM assoc LIMIT 0", |
44 | &resp,&nr,&nc,&errm)!=SQLITE_OK) { |
45 | &resp,&nr,&nc,&errm)!=SQLITE_OK) { |
45 | extern const char *__OP_db_bootstrap; |
46 | extern const char *__OP_db_bootstrap; |
46 | DOUT_("Bootstrapping DB"); |
47 | DOUT_("Bootstrapping DB"); |
47 | if(sqlite3_exec(_D,__OP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) |
48 | if(sqlite3_exec(_D,__OP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) |
48 | throw opkele::exception(OPKELE_CP_ string("Failed to boostrap SQLite database: ")+errm); |
49 | throw opkele::exception(OPKELE_CP_ string("Failed to boostrap SQLite database: ")+errm); |
49 | }else |
50 | }else |
50 | sqlite3_free_table(resp); |
51 | sqlite3_free_table(resp); |
51 | } |
52 | } |
52 | }; |
53 | }; |
53 | |
54 | |
54 | class example_op_t : public opkele::verify_op { |
55 | class example_op_t : public opkele::verify_op { |
55 | public: |
56 | public: |
56 | kingate::cgi_gateway& gw; |
57 | kingate::cgi_gateway& gw; |
57 | opdb_t db; |
58 | opdb_t db; |
58 | kingate::cookie htc; |
59 | kingate::cookie htc; |
59 | |
60 | |
60 | |
61 | |
61 | example_op_t(kingate::cgi_gateway& gw) |
62 | example_op_t(kingate::cgi_gateway& gw) |
62 | : gw(gw) { |
63 | : gw(gw) { |
63 | try { |
64 | try { |
64 | htc = gw.cookies.get_cookie("htop_session"); |
65 | htc = gw.cookies.get_cookie("htop_session"); |
@@ -224,108 +225,113 @@ int main(int argc,char *argv[]) { |
224 | message = "password set"; |
225 | message = "password set"; |
225 | }else if(op=="login") { |
226 | }else if(op=="login") { |
226 | example_op_t OP(gw); |
227 | example_op_t OP(gw); |
227 | string password = gw.get_param("password"); |
228 | string password = gw.get_param("password"); |
228 | sqlite3_mem_t<char*> |
229 | sqlite3_mem_t<char*> |
229 | Sget = sqlite3_mprintf("SELECT s_password FROM setup LIMIT 1"); |
230 | Sget = sqlite3_mprintf("SELECT s_password FROM setup LIMIT 1"); |
230 | sqlite3_table_t T; int nr,nc; |
231 | sqlite3_table_t T; int nr,nc; |
231 | OP.db.get_table(Sget,T,&nr,&nc); |
232 | OP.db.get_table(Sget,T,&nr,&nc); |
232 | if(nr<1) |
233 | if(nr<1) |
233 | throw opkele::exception(OPKELE_CP_ "no password set"); |
234 | throw opkele::exception(OPKELE_CP_ "no password set"); |
234 | if(password!=T.get(1,0,nc)) |
235 | if(password!=T.get(1,0,nc)) |
235 | throw opkele::exception(OPKELE_CP_ "wrong password"); |
236 | throw opkele::exception(OPKELE_CP_ "wrong password"); |
236 | OP.set_authorized(true); |
237 | OP.set_authorized(true); |
237 | op.clear(); |
238 | op.clear(); |
238 | message = "logged in"; |
239 | message = "logged in"; |
239 | OP.cookie_header(cout); |
240 | OP.cookie_header(cout); |
240 | }else if(op=="logout") { |
241 | }else if(op=="logout") { |
241 | example_op_t OP(gw); |
242 | example_op_t OP(gw); |
242 | OP.set_authorized(false); |
243 | OP.set_authorized(false); |
243 | op.clear(); |
244 | op.clear(); |
244 | message = "logged out"; |
245 | message = "logged out"; |
245 | } |
246 | } |
246 | string om; |
247 | string om; |
247 | try { om = gw.get_param("openid.mode"); }catch(kingate::exception_notfound&) { } |
248 | try { om = gw.get_param("openid.mode"); }catch(kingate::exception_notfound&) { } |
248 | if(op=="xrds") { |
249 | if(op=="xrds") { |
249 | cout << |
250 | cout << |
250 | "Content-type: application/xrds+xml\n\n" |
251 | "Content-type: application/xrds+xml\n\n" |
251 | "<?xml version='1.0' encoding='utf-8'?>" |
252 | "<?xml version='1.0' encoding='utf-8'?>" |
252 | "<xrds:XRDS xmlns:xrds='xri://$xrds' xmlns='xri://$xrd*($v*2.0)'>" |
253 | "<xrds:XRDS xmlns:xrds='xri://$xrds' xmlns='xri://$xrd*($v*2.0)'>" |
253 | "<XRD>" |
254 | "<XRD>" |
254 | "<Service>" |
255 | "<Service>" |
255 | "<Type>" STURI_OPENID20 "</Type>" |
256 | "<Type>" STURI_OPENID20 "</Type>" |
256 | "<URI>" << get_self_url(gw) << "</URI>" |
257 | "<URI>" << get_self_url(gw) << "</URI>" |
257 | "</Service>"; |
258 | "</Service>"; |
258 | if(gw.has_param("idsel")){ |
259 | if(gw.has_param("idsel")){ |
259 | cout << |
260 | cout << |
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); |
296 | OP.associate(oum,inm); |
302 | OP.associate(oum,inm); |
297 | cout << "Content-type: text/plain\n\n"; |
303 | cout << "Content-type: text/plain\n\n"; |
298 | oum.to_keyvalues(cout); |
304 | oum.to_keyvalues(cout); |
299 | }else if(om=="checkid_setup") { |
305 | }else if(om=="checkid_setup") { |
300 | kingate_openid_message_t inm(gw); |
306 | kingate_openid_message_t inm(gw); |
301 | example_op_t OP(gw); |
307 | example_op_t OP(gw); |
302 | OP.checkid_(inm,0); |
308 | OP.checkid_(inm,0); |
303 | OP.cookie_header(cout) << |
309 | OP.cookie_header(cout) << |
304 | "Content-type: text/html\n" |
310 | "Content-type: text/html\n" |
305 | "\n" |
311 | "\n" |
306 | |
312 | |
307 | "<html>" |
313 | "<html>" |
308 | "<head>" |
314 | "<head>" |
309 | "<title>test OP: confirm authentication</title>" |
315 | "<title>test OP: confirm authentication</title>" |
310 | "</head>" |
316 | "</head>" |
311 | "<body>" |
317 | "<body>" |
312 | "realm: " << OP.get_realm() << "<br/>" |
318 | "realm: " << OP.get_realm() << "<br/>" |
313 | "return_to: " << OP.get_return_to() << "<br/>" |
319 | "return_to: " << OP.get_return_to() << "<br/>" |
314 | "claimed_id: " << OP.get_claimed_id() << "<br/>" |
320 | "claimed_id: " << OP.get_claimed_id() << "<br/>" |
315 | "identity: " << OP.get_identity() << "<br/>"; |
321 | "identity: " << OP.get_identity() << "<br/>"; |
316 | if(OP.is_id_select()) { |
322 | if(OP.is_id_select()) { |
317 | OP.select_identity( get_self_url(gw), get_self_url(gw) ); |
323 | OP.select_identity( get_self_url(gw), get_self_url(gw) ); |
318 | cout << |
324 | cout << |
319 | "selected claimed_id: " << OP.get_claimed_id() << "<br/>" |
325 | "selected claimed_id: " << OP.get_claimed_id() << "<br/>" |
320 | "selected identity: " << OP.get_identity() << "<br/>"; |
326 | "selected identity: " << OP.get_identity() << "<br/>"; |
321 | } |
327 | } |
322 | cout << |
328 | cout << |
323 | "<form method='post'>"; |
329 | "<form method='post'>"; |
324 | inm.to_htmlhiddens(cout); |
330 | inm.to_htmlhiddens(cout); |
325 | cout << |
331 | cout << |
326 | "<input type='hidden' name='hts_id'" |
332 | "<input type='hidden' name='hts_id'" |
327 | " value='" << opkele::util::attr_escape(OP.htc.get_value()) << "'/>" |
333 | " value='" << opkele::util::attr_escape(OP.htc.get_value()) << "'/>" |
328 | "<input type='submit' name='op' value='id_res'/>" |
334 | "<input type='submit' name='op' value='id_res'/>" |
329 | "<input type='submit' name='op' value='cancel'/>" |
335 | "<input type='submit' name='op' value='cancel'/>" |
330 | "</form>" |
336 | "</form>" |
331 | "</body>" |
337 | "</body>" |
|