author | Michael Krelin <hacker@klever.net> | 2008-01-20 21:10:23 (UTC) |
---|---|---|
committer | Michael Krelin <hacker@klever.net> | 2008-01-20 21:10:23 (UTC) |
commit | d16e79b1c792352eade736e7080c401a6c7ace03 (patch) (unidiff) | |
tree | 545a905ab8ef5c2a2135c17d2f949556b354b842 | |
parent | 9bfb6fadf71c46bf4cb5adabba0c96c32e84c1bc (diff) | |
download | libopkele-d16e79b1c792352eade736e7080c401a6c7ace03.zip libopkele-d16e79b1c792352eade736e7080c401a6c7ace03.tar.gz libopkele-d16e79b1c792352eade736e7080c401a6c7ace03.tar.bz2 |
test part rewritten
* cut down test.cc to only test rfc uri normalization
* redone idiscover to only list discovered endpoints
* added test RP cgi
Signed-off-by: Michael Krelin <hacker@klever.net>
-rw-r--r-- | test/.gitignore | 2 | ||||
-rw-r--r-- | test/Makefile.am | 35 | ||||
-rw-r--r-- | test/RP-db.sql | 37 | ||||
-rw-r--r-- | test/RP.cc | 538 | ||||
-rw-r--r-- | test/html/2rels.html | 7 | ||||
-rw-r--r-- | test/html/empty.html | 0 | ||||
-rw-r--r-- | test/html/head-in-body.html | 10 | ||||
-rw-r--r-- | test/html/hkn-delegate.html | 7 | ||||
-rw-r--r-- | test/html/hkn-server.html | 7 | ||||
-rw-r--r-- | test/html/hkn.html | 8 | ||||
-rw-r--r-- | test/html/in-body.html | 8 | ||||
-rw-r--r-- | test/html/spaced-link-attrs.html | 8 | ||||
-rw-r--r-- | test/html/spaced-links.html | 8 | ||||
-rw-r--r-- | test/html/unclosed-head.html | 7 | ||||
-rw-r--r-- | test/idiscover.cc | 46 | ||||
-rw-r--r-- | test/sqlite.h | 71 | ||||
-rw-r--r-- | test/test.cc | 49 |
17 files changed, 693 insertions, 155 deletions
diff --git a/test/.gitignore b/test/.gitignore index 31ae686..d07884c 100644 --- a/test/.gitignore +++ b/test/.gitignore | |||
@@ -5 +5,3 @@ | |||
5 | /idiscover | 5 | /idiscover |
6 | /RP.cgi | ||
7 | /RP-db.cc | ||
diff --git a/test/Makefile.am b/test/Makefile.am index b573d55..61e3787 100644 --- a/test/Makefile.am +++ b/test/Makefile.am | |||
@@ -1,2 +1,2 @@ | |||
1 | noinst_PROGRAMS = test idiscover | 1 | noinst_PROGRAMS = test idiscover RP.cgi |
2 | 2 | ||
@@ -4,3 +4,3 @@ AM_CPPFLAGS=${CPPFLAGS_DEBUG} | |||
4 | DEFAULT_INCLUDES = -I${top_builddir} | 4 | DEFAULT_INCLUDES = -I${top_builddir} |
5 | INCLUDES = -I${top_srcdir}/include/ ${KONFORKA_CFLAGS} ${LIBCURL_CPPFLAGS} | 5 | INCLUDES = -I${top_srcdir}/test/ -I${top_builddir}/include/ -I${top_srcdir}/include/ ${KONFORKA_CFLAGS} ${LIBCURL_CPPFLAGS} |
6 | 6 | ||
@@ -9,6 +9,5 @@ test_LDADD = ${top_builddir}/lib/libopkele.la | |||
9 | 9 | ||
10 | EXTRA_DIST=$(addsuffix .html,$(addprefix html/, \ | 10 | EXTRA_DIST= \ |
11 | empty head-in-body hkn-delegate hkn-server hkn in-body \ | 11 | sqlite.h \ |
12 | unclosed-head spaced-links spaced-link-attrs 2rels \ | 12 | RP-db.sql |
13 | )) | ||
14 | 13 | ||
@@ -16 +15,25 @@ idiscover_SOURCES = idiscover.cc | |||
16 | idiscover_LDADD = ${top_builddir}/lib/libopkele.la | 15 | idiscover_LDADD = ${top_builddir}/lib/libopkele.la |
16 | |||
17 | if HAVE_SQLITE3 | ||
18 | if HAVE_KINGATE | ||
19 | if HAVE_UUID | ||
20 | |||
21 | RP_cgi_SOURCES = RP.cc | ||
22 | nodist_RP_cgi_SOURCES = RP-db.cc | ||
23 | RP_cgi_LDADD = ${top_builddir}/lib/libopkele.la \ | ||
24 | ${SQLITE3_LIBS} ${KINGATE_LIBS} ${UUID_LIBS} | ||
25 | RP_cgi_CFLAGS = ${SQLITE3_CFLAGS} ${KINGATE_CFLAGS} ${UUID_CFLAGS} | ||
26 | |||
27 | RP-db.cc: RP-db.sql | ||
28 | ( \ | ||
29 | echo 'const char * __RP_db_bootstrap = ' && \ | ||
30 | sed -e 's/^/"/' -e 's/$$/"/' $< && \ | ||
31 | echo ';' \ | ||
32 | ) >$@ | ||
33 | |||
34 | clean-local: | ||
35 | rm -f RP-db.cc | ||
36 | |||
37 | endif #HAVE_UUID | ||
38 | endif #HAVE_KINGATE | ||
39 | endif #HAVE_SQLITE3 | ||
diff --git a/test/RP-db.sql b/test/RP-db.sql new file mode 100644 index 0000000..71a82d4 --- a/dev/null +++ b/test/RP-db.sql | |||
@@ -0,0 +1,37 @@ | |||
1 | CREATE TABLE assoc ( | ||
2 | a_op text, | ||
3 | a_handle text NOT NULL, | ||
4 | a_type text DEFAULT 'HMAC-SHA1', | ||
5 | a_ctime text NOT NULL, | ||
6 | a_etime text NOT NULL, | ||
7 | a_secret text NOT NULL, | ||
8 | a_stateless integer NOT NULL DEFAULT 0, | ||
9 | a_itime integer, | ||
10 | UNIQUE(a_op,a_handle) | ||
11 | ); | ||
12 | |||
13 | CREATE TABLE nonces ( | ||
14 | n_op text NOT NULL, | ||
15 | n_once text NOT NULL, | ||
16 | PRIMARY KEY (n_op,n_once) | ||
17 | ); | ||
18 | |||
19 | CREATE TABLE ht_sessions ( | ||
20 | hts_id text NOT NULL PRIMARY KEY | ||
21 | ); | ||
22 | |||
23 | CREATE TABLE auth_sessions ( | ||
24 | as_id integer PRIMARY KEY AUTOINCREMENT, | ||
25 | hts_id text NOT NULL REFERENCES ht_sessions(hts_id), | ||
26 | as_normalized_id text, | ||
27 | UNIQUE (hts_id,as_id) | ||
28 | ); | ||
29 | |||
30 | CREATE TABLE endpoints_queue ( | ||
31 | as_id integer NOT NULL REFERENCES auth_sessions (as_id), | ||
32 | eq_ctime integer NOT NULL, | ||
33 | eq_ordinal integer NOT NULL, | ||
34 | eq_uri text, | ||
35 | eq_claimed_id text, | ||
36 | eq_local_id text | ||
37 | ); | ||
diff --git a/test/RP.cc b/test/RP.cc new file mode 100644 index 0000000..f2f8851 --- a/dev/null +++ b/test/RP.cc | |||
@@ -0,0 +1,538 @@ | |||
1 | #include <uuid/uuid.h> | ||
2 | #include <iostream> | ||
3 | #include <cassert> | ||
4 | #include <stdexcept> | ||
5 | #include <string> | ||
6 | #include <set> | ||
7 | #include <iterator> | ||
8 | using namespace std; | ||
9 | #include <kingate/exception.h> | ||
10 | #include <kingate/plaincgi.h> | ||
11 | #include <kingate/cgi_gateway.h> | ||
12 | #include <opkele/exception.h> | ||
13 | #include <opkele/types.h> | ||
14 | #include <opkele/util.h> | ||
15 | #include <opkele/uris.h> | ||
16 | #include <opkele/discovery.h> | ||
17 | #include <opkele/association.h> | ||
18 | #include <opkele/sreg.h> | ||
19 | using namespace opkele; | ||
20 | #include <opkele/prequeue_rp.h> | ||
21 | #include <opkele/debug.h> | ||
22 | |||
23 | #include "sqlite.h" | ||
24 | |||
25 | #undef DUMB_RP | ||
26 | |||
27 | #ifdef DUMB_RP | ||
28 | # define DUMBTHROW throw opkele::dumb_RP(OPKELE_CP_ "This RP is dumb") | ||
29 | #else | ||
30 | # define DUMBTHROW (void)0 | ||
31 | #endif | ||
32 | |||
33 | template<typename IT> | ||
34 | class join_iterator : public iterator< | ||
35 | input_iterator_tag,typename IT::value_type, | ||
36 | void,typename IT::pointer,typename IT::reference> { | ||
37 | public: | ||
38 | typedef pair<IT,IT> range_t; | ||
39 | typedef list<range_t> ranges_t; | ||
40 | ranges_t ranges; | ||
41 | |||
42 | join_iterator() { } | ||
43 | |||
44 | bool cleanup() { | ||
45 | bool rv = false; | ||
46 | while(!(ranges.empty() || ranges.front().first!=ranges.front().second)) { | ||
47 | ranges.pop_front(); rv = true; | ||
48 | } | ||
49 | return rv; | ||
50 | } | ||
51 | |||
52 | join_iterator<IT>& add_range(const IT& b,const IT& e) { | ||
53 | ranges.push_back(typename ranges_t::value_type(b,e)); | ||
54 | cleanup(); | ||
55 | return *this; | ||
56 | } | ||
57 | |||
58 | bool operator==(const join_iterator<IT>& x) const { | ||
59 | return ranges==x.ranges; } | ||
60 | bool operator!=(const join_iterator<IT>& x) const { | ||
61 | return ranges!=x.ranges; } | ||
62 | |||
63 | typename IT::reference operator*() const { | ||
64 | assert(!ranges.empty()); | ||
65 | assert(ranges.front().first!=ranges.front().second); | ||
66 | return *ranges.front().first; } | ||
67 | typename IT::pointer operator->() const { | ||
68 | assert(!ranges.empty()); | ||
69 | assert(ranges.front().first!=ranges.front().second); | ||
70 | return ranges.front().first.operator->(); } | ||
71 | |||
72 | join_iterator<IT>& operator++() { | ||
73 | cleanup(); | ||
74 | if(ranges.empty()) return *this; | ||
75 | do { | ||
76 | ++ranges.front().first; | ||
77 | }while(cleanup() && !ranges.empty()); | ||
78 | return *this; | ||
79 | } | ||
80 | join_iterator<IT> operator++(int) { | ||
81 | join_iterator<IT> rv(*this); | ||
82 | ++(*this); return rv; } | ||
83 | }; | ||
84 | |||
85 | template<typename IT> | ||
86 | class cut_prefix_filterator : public opkele::util::basic_filterator<IT> { | ||
87 | public: | ||
88 | string pfx; | ||
89 | mutable string tmp; | ||
90 | |||
91 | cut_prefix_filterator() { } | ||
92 | cut_prefix_filterator(const IT& bi,const IT&ei,const string& pfx) | ||
93 | : opkele::util::basic_filterator<IT>(bi,ei), pfx(pfx) { | ||
94 | this->prepare(); | ||
95 | } | ||
96 | |||
97 | bool is_interesting() const { | ||
98 | return pfx.length()==0 || !strncmp(this->it->c_str(),pfx.c_str(),pfx.length()); | ||
99 | } | ||
100 | |||
101 | typename IT::reference operator*() const { | ||
102 | assert(!this->empty); | ||
103 | tmp = *this->it; tmp.erase(0,pfx.length()); | ||
104 | return tmp; } | ||
105 | typename IT::pointer operator->() const { | ||
106 | assert(!this->empty); | ||
107 | return &this->operator*(); } | ||
108 | }; | ||
109 | |||
110 | class kingate_openid_message_t : public opkele::basic_openid_message { | ||
111 | typedef join_iterator<kingate::cgi_gateway::params_t::const_iterator> jitterator; | ||
112 | typedef opkele::util::map_keys_iterator< | ||
113 | jitterator, | ||
114 | fields_iterator::value_type, | ||
115 | fields_iterator::reference, | ||
116 | fields_iterator::pointer> keys_iterator; | ||
117 | typedef cut_prefix_filterator<keys_iterator> pfilterator; | ||
118 | public: | ||
119 | const kingate::cgi_gateway& gw; | ||
120 | |||
121 | kingate_openid_message_t(const kingate::cgi_gateway& g) : gw(g) { } | ||
122 | |||
123 | bool has_field(const string& n) const { | ||
124 | return gw.has_param("openid."+n); } | ||
125 | const string& get_field(const string& n) const { | ||
126 | return gw.get_param("openid."+n); } | ||
127 | |||
128 | fields_iterator fields_begin() const { | ||
129 | return | ||
130 | pfilterator( keys_iterator( | ||
131 | jitterator() | ||
132 | .add_range( gw.get.begin(), gw.get.end() ) | ||
133 | .add_range( gw.post.begin(), gw.post.end() ), | ||
134 | jitterator() | ||
135 | ), keys_iterator(), "openid." ); | ||
136 | } | ||
137 | fields_iterator fields_end() const { | ||
138 | return pfilterator(); | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | class rpdb_t : public sqlite3_t { | ||
143 | public: | ||
144 | rpdb_t() | ||
145 | : sqlite3_t("/tmp/RP.db") { | ||
146 | assert(_D); | ||
147 | char **resp; int nrow,ncol; char *errm; | ||
148 | if(sqlite3_get_table( | ||
149 | _D,"SELECT a_op FROM assoc LIMIT 0", | ||
150 | &resp,&nrow,&ncol,&errm)!=SQLITE_OK) { | ||
151 | extern const char *__RP_db_bootstrap; | ||
152 | DOUT_("Bootstrapping DB"); | ||
153 | if(sqlite3_exec(_D,__RP_db_bootstrap,NULL,NULL,&errm)!=SQLITE_OK) | ||
154 | throw opkele::exception(OPKELE_CP_ string("Failed to bootstrap SQLite database: ")+errm); | ||
155 | }else | ||
156 | sqlite3_free_table(resp); | ||
157 | |||
158 | } | ||
159 | }; | ||
160 | |||
161 | class example_rp_t : public opkele::prequeue_RP { | ||
162 | public: | ||
163 | mutable rpdb_t db; | ||
164 | kingate::cookie htc; | ||
165 | long as_id; | ||
166 | int ordinal; | ||
167 | kingate::cgi_gateway& gw; | ||
168 | |||
169 | example_rp_t(kingate::cgi_gateway& gw) | ||
170 | : ordinal(0), have_eqtop(false), gw(gw), as_id(-1) { | ||
171 | try { | ||
172 | htc = gw.cookies.get_cookie("ht_session"); | ||
173 | as_id = opkele::util::string_to_long(gw.get_param("asid")); | ||
174 | }catch(kingate::exception_notfound& kenf) { | ||
175 | uuid_t uuid; uuid_generate(uuid); | ||
176 | htc = kingate::cookie("ht_session",util::encode_base64(uuid,sizeof(uuid))); | ||
177 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
178 | "INSERT INTO ht_sessions (hts_id) VALUES (%Q)", | ||
179 | htc.get_value().c_str()); | ||
180 | db.exec(S); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /* Global persistent store */ | ||
185 | |||
186 | opkele::assoc_t store_assoc( | ||
187 | const string& OP,const string& handle, | ||
188 | const string& type,const secret_t& secret, | ||
189 | int expires_in) { | ||
190 | DUMBTHROW; | ||
191 | DOUT_("Storing '" << handle << "' assoc with '" << OP << "'"); | ||
192 | time_t exp = time(0)+expires_in; | ||
193 | sqlite3_mem_t<char*> | ||
194 | S = sqlite3_mprintf( | ||
195 | "INSERT INTO assoc" | ||
196 | " (a_op,a_handle,a_type,a_ctime,a_etime,a_secret)" | ||
197 | " VALUES (" | ||
198 | " %Q,%Q,%Q," | ||
199 | " datetime('now'), datetime('now','+%d seconds')," | ||
200 | " %Q" | ||
201 | " );", OP.c_str(), handle.c_str(), type.c_str(), | ||
202 | expires_in, | ||
203 | util::encode_base64(&(secret.front()),secret.size()).c_str() ); | ||
204 | db.exec(S); | ||
205 | return opkele::assoc_t(new opkele::association( | ||
206 | OP, handle, type, secret, exp, false )); | ||
207 | } | ||
208 | |||
209 | opkele::assoc_t find_assoc( | ||
210 | const string& OP) { | ||
211 | DUMBTHROW; | ||
212 | DOUT_("Looking for an assoc with '" << OP << '\''); | ||
213 | sqlite3_mem_t<char*> | ||
214 | S = sqlite3_mprintf( | ||
215 | "SELECT" | ||
216 | " a_op,a_handle,a_type,a_secret," | ||
217 | " strftime('%%s',a_etime) AS a_etime" | ||
218 | " FROM assoc" | ||
219 | " WHERE a_op=%Q AND a_itime IS NULL AND NOT a_stateless" | ||
220 | " AND ( a_etime > datetime('now','-30 seconds') )" | ||
221 | " LIMIT 1", | ||
222 | OP.c_str()); | ||
223 | sqlite3_table_t T; | ||
224 | int nr,nc; | ||
225 | db.get_table(S,T,&nr,&nc); | ||
226 | if(nr<1) | ||
227 | throw opkele::failed_lookup(OPKELE_CP_ "Couldn't find unexpired handle"); | ||
228 | assert(nr==1); | ||
229 | assert(nc==5); | ||
230 | secret_t secret; | ||
231 | util::decode_base64(T.get(1,3,nc),secret); | ||
232 | DOUT_(" found '" << T.get(1,1,nc) << '\''); | ||
233 | return opkele::assoc_t(new opkele::association( | ||
234 | T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), | ||
235 | secret, strtol(T.get(1,4,nc),0,0), false )); | ||
236 | } | ||
237 | |||
238 | opkele::assoc_t retrieve_assoc( | ||
239 | const string& OP,const string& handle) { | ||
240 | DUMBTHROW; | ||
241 | DOUT_("Retrieving assoc '" << handle << "' with '" << OP << '\''); | ||
242 | sqlite3_mem_t<char*> | ||
243 | S = sqlite3_mprintf( | ||
244 | "SELECT" | ||
245 | " a_op,a_handle,a_type,a_secret," | ||
246 | " strftime('%%s',a_etime) AS a_etime" | ||
247 | " FROM assoc" | ||
248 | " WHERE a_op=%Q AND a_handle=%Q" | ||
249 | " AND a_itime IS NULL AND NOT a_stateless" | ||
250 | " LIMIT 1", | ||
251 | OP.c_str(),handle.c_str()); | ||
252 | sqlite3_table_t T; | ||
253 | int nr,nc; | ||
254 | db.get_table(S,T,&nr,&nc); | ||
255 | if(nr<1) | ||
256 | throw opkele::failed_lookup(OPKELE_CP_ "couldn't retrieve valid association"); | ||
257 | assert(nr==1); assert(nc==5); | ||
258 | secret_t secret; util::decode_base64(T.get(1,3,nc),secret); | ||
259 | DOUT_(" found. type=" << T.get(1,2,nc) << '\''); | ||
260 | return opkele::assoc_t(new opkele::association( | ||
261 | T.get(1,0,nc), T.get(1,1,nc), T.get(1,2,nc), | ||
262 | secret, strtol(T.get(1,4,nc),0,0), false )); | ||
263 | } | ||
264 | |||
265 | void invalidate_assoc( | ||
266 | const string& OP,const string& handle) { | ||
267 | DUMBTHROW; | ||
268 | DOUT_("Invalidating assoc '" << handle << "' with '" << OP << '\''); | ||
269 | sqlite3_mem_t<char*> | ||
270 | S = sqlite3_mprintf( | ||
271 | "UPDATE assoc SET a_itime=datetime('now')" | ||
272 | " WHERE a_op=%Q AND a_handle=%Q", | ||
273 | OP.c_str(), handle.c_str() ); | ||
274 | db.exec(S); | ||
275 | } | ||
276 | |||
277 | void check_nonce(const string& OP,const string& nonce) { | ||
278 | DOUT_("Checking nonce '" << nonce << "' from '" << OP << '\''); | ||
279 | sqlite3_mem_t<char*> | ||
280 | S = sqlite3_mprintf( | ||
281 | "SELECT 1 FROM nonces WHERE n_op=%Q AND n_once=%Q", | ||
282 | OP.c_str(), nonce.c_str()); | ||
283 | sqlite3_table_t T; | ||
284 | int nr,nc; | ||
285 | db.get_table(S,T,&nr,&nc); | ||
286 | if(nr) | ||
287 | throw opkele::id_res_bad_nonce(OPKELE_CP_ "already seen that nonce"); | ||
288 | sqlite3_mem_t<char*> | ||
289 | SS = sqlite3_mprintf( | ||
290 | "INSERT INTO nonces (n_op,n_once) VALUES (%Q,%Q)", | ||
291 | OP.c_str(), nonce.c_str()); | ||
292 | db.exec(SS); | ||
293 | } | ||
294 | |||
295 | /* Session perisistent store */ | ||
296 | |||
297 | void begin_queueing() { | ||
298 | assert(as_id>=0); | ||
299 | DOUT_("Resetting queue for session '" << htc.get_value() << "'/" << as_id); | ||
300 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
301 | "DELETE FROM endpoints_queue" | ||
302 | " WHERE as_id=%ld", | ||
303 | as_id); | ||
304 | db.exec(S); | ||
305 | } | ||
306 | |||
307 | void queue_endpoint(const opkele::openid_endpoint_t& ep) { | ||
308 | assert(as_id>=0); | ||
309 | DOUT_("Queueing endpoint " << ep.claimed_id << " : " << ep.local_id << " @ " << ep.uri); | ||
310 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
311 | "INSERT INTO endpoints_queue" | ||
312 | " (as_id,eq_ctime,eq_ordinal,eq_uri,eq_claimed_id,eq_local_id)" | ||
313 | " VALUES (%ld,strftime('%%s','now'),%d,%Q,%Q,%Q)", | ||
314 | as_id,ordinal++, | ||
315 | ep.uri.c_str(),ep.claimed_id.c_str(),ep.local_id.c_str()); | ||
316 | db.exec(S); | ||
317 | } | ||
318 | |||
319 | mutable openid_endpoint_t eqtop; | ||
320 | mutable bool have_eqtop; | ||
321 | |||
322 | const openid_endpoint_t& get_endpoint() const { | ||
323 | assert(as_id>=0); | ||
324 | if(!have_eqtop) { | ||
325 | sqlite3_mem_t<char*> | ||
326 | S = sqlite3_mprintf( | ||
327 | "SELECT" | ||
328 | " eq_uri, eq_claimed_id, eq_local_id" | ||
329 | " FROM endpoints_queue" | ||
330 | " JOIN auth_sessions USING(as_id)" | ||
331 | " WHERE hts_id=%Q AND as_id=%ld" | ||
332 | " ORDER BY eq_ctime,eq_ordinal" | ||
333 | " LIMIT 1",htc.get_value().c_str(),as_id); | ||
334 | sqlite3_table_t T; int nr,nc; | ||
335 | db.get_table(S,T,&nr,&nc); | ||
336 | if(nr<1) | ||
337 | throw opkele::exception(OPKELE_CP_ "No more endpoints queued"); | ||
338 | assert(nr==1); assert(nc==3); | ||
339 | eqtop.uri = T.get(1,0,nc); | ||
340 | eqtop.claimed_id = T.get(1,1,nc); | ||
341 | eqtop.local_id = T.get(1,2,nc); | ||
342 | have_eqtop = true; | ||
343 | } | ||
344 | return eqtop; | ||
345 | } | ||
346 | |||
347 | void next_endpoint() { | ||
348 | assert(as_id>=0); | ||
349 | get_endpoint(); | ||
350 | have_eqtop = false; | ||
351 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
352 | "DELETE FROM endpoints_queue" | ||
353 | " WHERE as_id=%ld AND eq_uri=%Q AND eq_local_id=%Q", | ||
354 | htc.get_value().c_str(),as_id, | ||
355 | eqtop.uri.c_str()); | ||
356 | db.exec(S); | ||
357 | } | ||
358 | |||
359 | mutable string _cid; | ||
360 | mutable string _nid; | ||
361 | |||
362 | void set_claimed_id(const string& cid) { | ||
363 | assert(as_id>=0); | ||
364 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
365 | "UPDATE auth_sessions" | ||
366 | " SET as_claimed_id=%Q" | ||
367 | " WHERE hts_id=%Q and as_id=%ld", | ||
368 | cid.c_str(), | ||
369 | htc.get_value().c_str(),as_id); | ||
370 | db.exec(S); | ||
371 | _cid = cid; | ||
372 | } | ||
373 | const string get_claimed_id() const { | ||
374 | assert(as_id>=0); | ||
375 | if(_cid.empty()) { | ||
376 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
377 | "SELECT as_claimed_id" | ||
378 | " FROM" | ||
379 | " auth_sessions" | ||
380 | " WHERE" | ||
381 | " hts_id=%Q AND as_id=%ld", | ||
382 | htc.get_value().c_str(),as_id); | ||
383 | sqlite3_table_t T; int nr,nc; | ||
384 | db.get_table(S,T,&nr,&nc); | ||
385 | assert(nr==1); assert(nc==1); | ||
386 | _cid = T.get(1,0,nc); | ||
387 | } | ||
388 | return _cid; | ||
389 | } | ||
390 | void set_normalized_id(const string& nid) { | ||
391 | assert(as_id>=0); | ||
392 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
393 | "UPDATE auth_sessions" | ||
394 | " SET as_normalized_id=%Q" | ||
395 | " WHERE hts_id=%Q and as_id=%ld", | ||
396 | nid.c_str(), | ||
397 | htc.get_value().c_str(),as_id); | ||
398 | db.exec(S); | ||
399 | _nid = nid; | ||
400 | } | ||
401 | const string get_normalized_id() const { | ||
402 | assert(as_id>=0); | ||
403 | if(_nid.empty()) { | ||
404 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
405 | "SELECT as_normalized_id" | ||
406 | " FROM" | ||
407 | " auth_sessions" | ||
408 | " WHERE" | ||
409 | " hts_id=%Q AND as_id=%ld", | ||
410 | htc.get_value().c_str(),as_id); | ||
411 | sqlite3_table_t T; int nr,nc; | ||
412 | db.get_table(S,T,&nr,&nc); | ||
413 | assert(nr==1); assert(nc==1); | ||
414 | _nid = T.get(1,0,nc); | ||
415 | } | ||
416 | return _nid; | ||
417 | } | ||
418 | |||
419 | const string get_this_url() const { | ||
420 | bool s = gw.has_meta("SSL_PROTOCOL_VERSION"); | ||
421 | string rv = s?"https://":"http://"; | ||
422 | rv += gw.http_request_header("Host"); | ||
423 | const string& port = gw.get_meta("SERVER_PORT"); | ||
424 | if( port!=(s?"443":"80") ) { | ||
425 | rv += ':'; rv += port; | ||
426 | } | ||
427 | rv += gw.get_meta("REQUEST_URI"); | ||
428 | return rv; | ||
429 | } | ||
430 | |||
431 | void initiate(const string& usi) { | ||
432 | allocate_asid(); | ||
433 | prequeue_RP::initiate(usi); | ||
434 | } | ||
435 | |||
436 | string get_self_url() const { | ||
437 | string rv = get_this_url(); | ||
438 | string::size_type q = rv.find('?'); | ||
439 | if(q!=string::npos) | ||
440 | rv.erase(q); | ||
441 | return rv; | ||
442 | } | ||
443 | |||
444 | void allocate_asid() { | ||
445 | sqlite3_mem_t<char*> S = sqlite3_mprintf( | ||
446 | "INSERT INTO auth_sessions (hts_id)" | ||
447 | " VALUES (%Q)", | ||
448 | htc.get_value().c_str()); | ||
449 | db.exec(S); | ||
450 | as_id = sqlite3_last_insert_rowid(db); | ||
451 | DOUT_("Allocated authentication session id "<<as_id); | ||
452 | assert(as_id>=0); | ||
453 | } | ||
454 | |||
455 | #ifdef DUMB_RP | ||
456 | virtual assoc_t associate(const string& OP) { | ||
457 | DUMBTHROW; | ||
458 | } | ||
459 | #endif | ||
460 | }; | ||
461 | |||
462 | int main(int argc,char *argv[]) { | ||
463 | try { | ||
464 | kingate::plaincgi_interface ci; | ||
465 | kingate::cgi_gateway gw(ci); | ||
466 | string op; | ||
467 | try { op = gw.get_param("op"); }catch(kingate::exception_notfound&) { } | ||
468 | if(op=="initiate") { | ||
469 | example_rp_t rp(gw); | ||
470 | string usi = gw.get_param("openid_identity"); | ||
471 | rp.initiate(usi); | ||
472 | opkele::sreg_t sreg(opkele::sreg_t::fields_NONE,opkele::sreg_t::fields_ALL); | ||
473 | opkele::openid_message_t cm; | ||
474 | string loc; | ||
475 | cout << | ||
476 | "Set-Cookie: " << rp.htc.set_cookie_header() << "\n" | ||
477 | "Status: 302 Going to OP\n" | ||
478 | "Location: " << ( | ||
479 | loc = rp.checkid_(cm,opkele::mode_checkid_setup, | ||
480 | rp.get_self_url()+ | ||
481 | "?op=confirm&asid="+opkele::util::long_to_string(rp.as_id), | ||
482 | rp.get_self_url(),&sreg).append_query(rp.get_endpoint().uri) | ||
483 | ) | ||
484 | << "\n\n"; | ||
485 | DOUT_("Going to " << loc); | ||
486 | }else if(op=="confirm") { | ||
487 | kingate_openid_message_t om(gw); | ||
488 | example_rp_t rp(gw); | ||
489 | opkele::sreg_t sreg(opkele::sreg_t::fields_NONE,opkele::sreg_t::fields_ALL); | ||
490 | rp.id_res(om,&sreg); | ||
491 | cout << | ||
492 | "Content-Type: text/plain\n\n"; | ||
493 | for(opkele::basic_openid_message::fields_iterator i=om.fields_begin(); | ||
494 | i!=om.fields_end();++i) { | ||
495 | cout << *i << '=' << om.get_field(*i) << endl; | ||
496 | } | ||
497 | cout << endl | ||
498 | << "SREG fields: " << sreg.has_fields << endl; | ||
499 | }else{ | ||
500 | cout << | ||
501 | "Content-type: text/html\n\n" | ||
502 | |||
503 | "<html>" | ||
504 | "<head><title>test RP</title></head>" | ||
505 | "<body>" | ||
506 | "<form action='' method='post'>" | ||
507 | "<input type='hidden' name='op' value='initiate' />" | ||
508 | "<input type='text' name='openid_identity'/>" | ||
509 | "<input type='submit' name='submit' value='submit' />" | ||
510 | "</form>" | ||
511 | "<br/><br/>" | ||
512 | "<a href='?op=initiate&openid_identity=www.myopenid.com&dummy=" << time(0) << "'>login with myopenid.com account</a>" | ||
513 | "<br/>" | ||
514 | "</body" | ||
515 | "</html>" | ||
516 | ; | ||
517 | } | ||
518 | #ifdef OPKELE_HAVE_KONFORKA | ||
519 | }catch(konforka::exception& e) { | ||
520 | #else | ||
521 | }catch(std::exception& e){ | ||
522 | #endif | ||
523 | DOUT_("Oops: " << e.what()); | ||
524 | cout << "Content-Type: text/plain\n\n" | ||
525 | "Exception:\n" | ||
526 | " what: " << e.what() << endl; | ||
527 | #ifdef OPKELE_HAVE_KONFORKA | ||
528 | cout << " where: " << e.where() << endl; | ||
529 | if(!e._seen.empty()) { | ||
530 | cout << " seen:" << endl; | ||
531 | for(list<konforka::code_point>::const_iterator | ||
532 | i=e._seen.begin();i!=e._seen.end();++i) { | ||
533 | cout << " " << i->c_str() << endl; | ||
534 | } | ||
535 | } | ||
536 | #endif | ||
537 | } | ||
538 | } | ||
diff --git a/test/html/2rels.html b/test/html/2rels.html deleted file mode 100644 index 8773c55..0000000 --- a/test/html/2rels.html +++ b/dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <link rel="openid.server openid.delegate" href="http://www.klever.net/openid.server" /> | ||
4 | </head> | ||
5 | <body> | ||
6 | </body> | ||
7 | </html> | ||
diff --git a/test/html/empty.html b/test/html/empty.html deleted file mode 100644 index e69de29..0000000 --- a/test/html/empty.html +++ b/dev/null | |||
diff --git a/test/html/head-in-body.html b/test/html/head-in-body.html deleted file mode 100644 index 0f778f3..0000000 --- a/test/html/head-in-body.html +++ b/dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | </head> | ||
4 | <body> | ||
5 | <head> | ||
6 | <link rel="openid.server" href="http://www.klever.net/openid.server" /> | ||
7 | <link rel="openid.delegate" href="http://hacker.klever.net/" /> | ||
8 | </head> | ||
9 | </body> | ||
10 | </html> | ||
diff --git a/test/html/hkn-delegate.html b/test/html/hkn-delegate.html deleted file mode 100644 index 62e25a3..0000000 --- a/test/html/hkn-delegate.html +++ b/dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <link rel="openid.delegate" href="http://hacker.klever.net/" /> | ||
4 | </head> | ||
5 | <body> | ||
6 | </body> | ||
7 | </html> | ||
diff --git a/test/html/hkn-server.html b/test/html/hkn-server.html deleted file mode 100644 index e6b64e8..0000000 --- a/test/html/hkn-server.html +++ b/dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <link rel="openid.server" href="http://www.klever.net/openid.server" /> | ||
4 | </head> | ||
5 | <body> | ||
6 | </body> | ||
7 | </html> | ||
diff --git a/test/html/hkn.html b/test/html/hkn.html deleted file mode 100644 index 8d6e409..0000000 --- a/test/html/hkn.html +++ b/dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <link rel="openid.server" href="http://www.klever.net/openid.server" /> | ||
4 | <link rel="openid.delegate" href="http://hacker.klever.net/" /> | ||
5 | </head> | ||
6 | <body> | ||
7 | </body> | ||
8 | </html> | ||
diff --git a/test/html/in-body.html b/test/html/in-body.html deleted file mode 100644 index 53bc06d..0000000 --- a/test/html/in-body.html +++ b/dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | </head> | ||
4 | <body> | ||
5 | <link rel="openid.server" href="http://www.klever.net/openid.server" /> | ||
6 | <link rel="openid.delegate" href="http://hacker.klever.net/" /> | ||
7 | </body> | ||
8 | </html> | ||
diff --git a/test/html/spaced-link-attrs.html b/test/html/spaced-link-attrs.html deleted file mode 100644 index 33905c0..0000000 --- a/test/html/spaced-link-attrs.html +++ b/dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <link rel=" openid.server " href=" http://www.klever.net/openid.server" /> | ||
4 | <link rel=" openid.delegate" href="http://hacker.klever.net/ " /> | ||
5 | </head> | ||
6 | <body> | ||
7 | </body> | ||
8 | </html> | ||
diff --git a/test/html/spaced-links.html b/test/html/spaced-links.html deleted file mode 100644 index a958907..0000000 --- a/test/html/spaced-links.html +++ b/dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | < link rel = "openid.server" href = "http://www.klever.net/openid.server" /> | ||
4 | <link rel="openid.delegate" href='http://hacker.klever.net/' /> | ||
5 | </head> | ||
6 | <body> | ||
7 | </body> | ||
8 | </html> | ||
diff --git a/test/html/unclosed-head.html b/test/html/unclosed-head.html deleted file mode 100644 index 9c6f2ea..0000000 --- a/test/html/unclosed-head.html +++ b/dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | <html> | ||
2 | <head> | ||
3 | <link rel="openid.server" href="http://www.klever.net/openid.server" /> | ||
4 | <link rel="openid.delegate" href="http://hacker.klever.net/" /> | ||
5 | <body> | ||
6 | </body> | ||
7 | </html> | ||
diff --git a/test/idiscover.cc b/test/idiscover.cc index d9a7c62..44df9ce 100644 --- a/test/idiscover.cc +++ b/test/idiscover.cc | |||
@@ -7,21 +7,12 @@ using namespace std; | |||
7 | #include <opkele/discovery.h> | 7 | #include <opkele/discovery.h> |
8 | #include <opkele/util.h> | ||
8 | 9 | ||
9 | template<typename _PDT> | 10 | namespace opkele { |
10 | ostream& operator<<(ostream& o,const opkele::xrd::priority_map<_PDT>& pm) { | 11 | ostream& operator<<(ostream& o,const opkele::openid_endpoint_t& oep) { |
11 | for(typename opkele::xrd::priority_map<_PDT>::const_iterator i=pm.begin(); | 12 | o |
12 | i!=pm.end();++i) | 13 | << " URI: " << oep.uri << endl |
13 | o << ' ' << i->second << '[' << i->first << ']'; | 14 | << " Claimed ID: " << oep.claimed_id << endl |
15 | << " Local ID: " << oep.local_id << endl; | ||
14 | return o; | 16 | return o; |
15 | } | 17 | } |
16 | |||
17 | ostream& operator<<(ostream& o,const opkele::xrd::service_t s) { | ||
18 | o << "{" << endl | ||
19 | << " Type: "; | ||
20 | copy(s.types.begin(),s.types.end(), | ||
21 | ostream_iterator<string>(o," ")); | ||
22 | o << endl | ||
23 | << " URI: " << s.uris << endl | ||
24 | << " LocalID: " << s.local_ids << endl | ||
25 | << " ProviderID: " << s.provider_id << endl; | ||
26 | o << "}"; | ||
27 | } | 18 | } |
@@ -33,19 +24,14 @@ int main(int argc,char **argv) { | |||
33 | for(int a=1;a<argc;++a) { | 24 | for(int a=1;a<argc;++a) { |
34 | opkele::idiscovery_t discovery(argv[a]); | 25 | cout << "==============================================================" << endl |
35 | clog | ||
36 | << "===============================================================" << endl | ||
37 | << "User-supplied ID: " << argv[a] << endl | 26 | << "User-supplied ID: " << argv[a] << endl |
38 | << "Normalized ID: " << discovery.normalized_id << endl | 27 | << "Endpoints:" << endl |
39 | << "Canonicalized ID: " << discovery.canonicalized_id << endl | 28 | << " --" << endl; |
40 | << "The identity is " << (discovery.xri_identity?"":"not ") << "an i-name" << endl; | 29 | string normalized = opkele::idiscover( |
41 | if(discovery.xrd.expires) | 30 | ostream_iterator<opkele::openid_endpoint_t>(cout," --\n") |
42 | clog << "Information expires in " << discovery.xrd.expires-time(0) << " seconds" << endl; | 31 | ,argv[a]); |
43 | clog << endl | 32 | cout << "Normalized ID: " << normalized << endl; |
44 | << "CanonicalID: " << discovery.xrd.canonical_ids << endl | ||
45 | << "LocalID: " << discovery.xrd.local_ids << endl | ||
46 | << "ProviderID: " << discovery.xrd.provider_id << endl | ||
47 | << "Services: " << discovery.xrd.services << endl; | ||
48 | } | 33 | } |
49 | }catch(exception& e) { | 34 | }catch(exception& e) { |
50 | cerr << "oops: " << e.what() << endl; | 35 | cerr << "oops, caught " << opkele::util::abi_demangle(typeid(e).name()) << endl |
36 | << " .what(): " << e.what() << endl; | ||
51 | _exit(1); | 37 | _exit(1); |
diff --git a/test/sqlite.h b/test/sqlite.h new file mode 100644 index 0000000..883a2c0 --- a/dev/null +++ b/test/sqlite.h | |||
@@ -0,0 +1,71 @@ | |||
1 | #include <sqlite3.h> | ||
2 | |||
3 | class sqlite3_t { | ||
4 | public: | ||
5 | sqlite3 *_D; | ||
6 | |||
7 | sqlite3_t(const char *f) | ||
8 | : _D(0) { | ||
9 | int r = sqlite3_open(f,&_D); | ||
10 | if(r!=SQLITE_OK) { | ||
11 | string msg = sqlite3_errmsg(_D); sqlite3_close(_D); | ||
12 | throw opkele::exception(OPKELE_CP_ "Failed to open SQLite database: "+msg); | ||
13 | } | ||
14 | } | ||
15 | ~sqlite3_t() { | ||
16 | if(_D) sqlite3_close(_D); | ||
17 | } | ||
18 | |||
19 | operator const sqlite3*(void) const { return _D; } | ||
20 | operator sqlite3*(void) { return _D; } | ||
21 | |||
22 | void exec(const char *sql) { | ||
23 | assert(_D); | ||
24 | char *errm; | ||
25 | if(sqlite3_exec(_D,sql,NULL,NULL,&errm)!=SQLITE_OK) | ||
26 | throw opkele::exception(OPKELE_CP_ string("Failed to sqlite3_exec():")+errm); | ||
27 | } | ||
28 | void get_table(const char *sql,char ***resp,int *nr,int *nc) { | ||
29 | assert(_D); | ||
30 | char *errm; | ||
31 | if(sqlite3_get_table(_D,sql,resp,nr,nc,&errm)!=SQLITE_OK) | ||
32 | throw opkele::exception(OPKELE_CP_ string("Failed to sqlite3_get_table():")+errm); | ||
33 | } | ||
34 | }; | ||
35 | |||
36 | template<typename T> | ||
37 | class sqlite3_mem_t { | ||
38 | public: | ||
39 | T _M; | ||
40 | |||
41 | sqlite3_mem_t(T M) :_M(M) { } | ||
42 | ~sqlite3_mem_t() { if(_M) sqlite3_free(_M); } | ||
43 | |||
44 | operator const T&(void) const { return _M; } | ||
45 | operator T&(void) { return _M; } | ||
46 | |||
47 | sqlite3_mem_t operator=(T M) { | ||
48 | if(_M) sqlite3_free(_M); | ||
49 | _M = M; | ||
50 | } | ||
51 | }; | ||
52 | |||
53 | class sqlite3_table_t { | ||
54 | public: | ||
55 | char **_T; | ||
56 | |||
57 | sqlite3_table_t() : _T(0) { } | ||
58 | sqlite3_table_t(char **T) : _T(T) { } | ||
59 | ~sqlite3_table_t() { if(_T) sqlite3_free_table(_T); } | ||
60 | |||
61 | operator char**&(void) { return _T; } | ||
62 | |||
63 | operator char ***(void) { | ||
64 | if(_T) sqlite3_free_table(_T); | ||
65 | return &_T; } | ||
66 | |||
67 | const char *get(int r,int c,int nc) { | ||
68 | assert(_T); | ||
69 | return _T[r*nc+c]; | ||
70 | } | ||
71 | }; | ||
diff --git a/test/test.cc b/test/test.cc index 1a012b5..35f58ab 100644 --- a/test/test.cc +++ b/test/test.cc | |||
@@ -4,3 +4,2 @@ using namespace std; | |||
4 | #include <opkele/exception.h> | 4 | #include <opkele/exception.h> |
5 | #include <opkele/consumer.h> | ||
6 | #include <opkele/util.h> | 5 | #include <opkele/util.h> |
@@ -15,49 +14,2 @@ class failed_test : public opkele::exception { | |||
15 | 14 | ||
16 | class dummy_consumer_t : public opkele::consumer_t { | ||
17 | public: | ||
18 | virtual opkele::assoc_t store_assoc(const string& /* server */,const string& /* handle */,const opkele::secret_t& /* secret */,int /* expires_in */) { | ||
19 | throw opkele::not_implemented(OPKELE_CP_ "Not implemented"); | ||
20 | } | ||
21 | virtual opkele::assoc_t retrieve_assoc(const string& /* server */ ,const string& /* handle */) { | ||
22 | throw opkele::not_implemented(OPKELE_CP_ "Not implemented"); | ||
23 | } | ||
24 | virtual void invalidate_assoc(const string& /* server */,const string& /* handle */) { | ||
25 | throw opkele::not_implemented(OPKELE_CP_ "Not implemented"); | ||
26 | } | ||
27 | }; | ||
28 | |||
29 | |||
30 | void test_retrieve_links(const string& f,bool success,const string& s="",const string& d="") { | ||
31 | dummy_consumer_t dc; | ||
32 | string server, delegate; | ||
33 | try { | ||
34 | dc.retrieve_links("file://" OPKELE_SRC_DIR "/test/html/"+f,server,delegate); | ||
35 | if(!success) | ||
36 | throw failed_test(OPKELE_CP_ "Retrieved links when it shouldn't"); | ||
37 | if(server!=s) | ||
38 | throw failed_test(OPKELE_CP_ "retrieve_links test failed, expected server '"+s+"', got '"+server+"'"); | ||
39 | if(delegate!=d) | ||
40 | throw failed_test(OPKELE_CP_ "retrieve_links test failed, expected delegate '"+d+"', got '"+delegate+"'"); | ||
41 | }catch(opkele::bad_input& obi) { | ||
42 | if(success) | ||
43 | throw failed_test(OPKELE_CP_ "Test '"+f+"' failed due to 'bad_input'["+obi.what()+"]"); | ||
44 | }catch(opkele::failed_assertion& ofa) { | ||
45 | if(success) | ||
46 | throw failed_test(OPKELE_CP_ "Test '"+f+"' failed due to 'failed_assertion'["+ofa.what()+"]"); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | void test_retrieve_links() { | ||
51 | test_retrieve_links("empty.html",false); | ||
52 | test_retrieve_links("in-body.html",false); | ||
53 | test_retrieve_links("head-in-body.html",false); | ||
54 | test_retrieve_links("hkn.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/"); | ||
55 | test_retrieve_links("hkn-server.html",true,"http://www.klever.net/openid.server"); | ||
56 | test_retrieve_links("hkn-delegate.html",false); | ||
57 | test_retrieve_links("unclosed-head.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/"); | ||
58 | test_retrieve_links("spaced-links.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/"); | ||
59 | test_retrieve_links("spaced-link-attrs.html",true,"http://www.klever.net/openid.server","http://hacker.klever.net/"); | ||
60 | test_retrieve_links("2rels.html",true,"http://www.klever.net/openid.server","http://www.klever.net/openid.server"); | ||
61 | } | ||
62 | |||
63 | void test_rfc_3986_normalize_uri(const string &ouri,bool success,const string& nuri="") { | 15 | void test_rfc_3986_normalize_uri(const string &ouri,bool success,const string& nuri="") { |
@@ -130,3 +82,2 @@ int main() { | |||
130 | test_rfc_3986_normalize_uri(); | 82 | test_rfc_3986_normalize_uri(); |
131 | test_retrieve_links(); | ||
132 | }catch(failed_test& ft) { | 83 | }catch(failed_test& ft) { |