diff options
Diffstat (limited to 'src/identity-provider')
21 files changed, 0 insertions, 10197 deletions
diff --git a/src/identity-provider/.gitignore b/src/identity-provider/.gitignore deleted file mode 100644 index ef77fccdc..000000000 --- a/src/identity-provider/.gitignore +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | gnunet-service-identity-provider | ||
2 | gnunet-identity-token | ||
diff --git a/src/identity-provider/Makefile.am b/src/identity-provider/Makefile.am deleted file mode 100644 index 2eb699542..000000000 --- a/src/identity-provider/Makefile.am +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | plugindir = $(libdir)/gnunet | ||
5 | |||
6 | if MINGW | ||
7 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
8 | endif | ||
9 | |||
10 | if USE_COVERAGE | ||
11 | AM_CFLAGS = --coverage -O0 | ||
12 | XLIB = -lgcov | ||
13 | endif | ||
14 | |||
15 | if HAVE_SQLITE | ||
16 | SQLITE_PLUGIN = libgnunet_plugin_identity_provider_sqlite.la | ||
17 | endif | ||
18 | |||
19 | EXTRA_DIST = \ | ||
20 | test_idp_defaults.conf \ | ||
21 | test_idp.conf \ | ||
22 | $(check_SCRIPTS) | ||
23 | |||
24 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
25 | |||
26 | libexecdir= $(pkglibdir)/libexec/ | ||
27 | |||
28 | pkgcfg_DATA = \ | ||
29 | identity-provider.conf | ||
30 | |||
31 | lib_LTLIBRARIES = \ | ||
32 | libgnunetidentityprovider.la | ||
33 | plugin_LTLIBRARIES = \ | ||
34 | libgnunet_plugin_rest_identity_provider.la \ | ||
35 | libgnunet_plugin_rest_openid_connect.la \ | ||
36 | libgnunet_plugin_gnsrecord_identity_provider.la \ | ||
37 | $(SQLITE_PLUGIN) | ||
38 | |||
39 | bin_PROGRAMS = \ | ||
40 | gnunet-idp | ||
41 | |||
42 | libexec_PROGRAMS = \ | ||
43 | gnunet-service-identity-provider | ||
44 | |||
45 | libgnunet_plugin_gnsrecord_identity_provider_la_SOURCES = \ | ||
46 | plugin_gnsrecord_identity_provider.c | ||
47 | libgnunet_plugin_gnsrecord_identity_provider_la_LIBADD = \ | ||
48 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
49 | $(LTLIBINTL) | ||
50 | libgnunet_plugin_gnsrecord_identity_provider_la_LDFLAGS = \ | ||
51 | $(GN_PLUGIN_LDFLAGS) | ||
52 | |||
53 | libgnunet_plugin_identity_provider_sqlite_la_SOURCES = \ | ||
54 | plugin_identity_provider_sqlite.c | ||
55 | libgnunet_plugin_identity_provider_sqlite_la_LIBADD = \ | ||
56 | libgnunetidentityprovider.la \ | ||
57 | $(top_builddir)/src/sq/libgnunetsq.la \ | ||
58 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
59 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ | ||
60 | $(LTLIBINTL) | ||
61 | libgnunet_plugin_identity_provider_sqlite_la_LDFLAGS = \ | ||
62 | $(GN_PLUGIN_LDFLAGS) | ||
63 | |||
64 | |||
65 | |||
66 | gnunet_service_identity_provider_SOURCES = \ | ||
67 | gnunet-service-identity-provider.c | ||
68 | gnunet_service_identity_provider_LDADD = \ | ||
69 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
70 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
71 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
72 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
73 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
74 | $(top_builddir)/src/abe/libgnunetabe.la \ | ||
75 | $(top_builddir)/src/credential/libgnunetcredential.la \ | ||
76 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
77 | libgnunetidentityprovider.la \ | ||
78 | $(top_builddir)/src/gns/libgnunetgns.la \ | ||
79 | $(GN_LIBINTL) | ||
80 | |||
81 | libgnunetidentityprovider_la_SOURCES = \ | ||
82 | identity_provider_api.c \ | ||
83 | identity_provider.h | ||
84 | libgnunetidentityprovider_la_LIBADD = \ | ||
85 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
86 | $(GN_LIBINTL) $(XLIB) | ||
87 | libgnunetidentityprovider_la_LDFLAGS = \ | ||
88 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
89 | -version-info 0:0:0 | ||
90 | |||
91 | libgnunet_plugin_rest_identity_provider_la_SOURCES = \ | ||
92 | plugin_rest_identity_provider.c \ | ||
93 | jwt.c | ||
94 | libgnunet_plugin_rest_identity_provider_la_LIBADD = \ | ||
95 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
96 | libgnunetidentityprovider.la \ | ||
97 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
98 | $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ | ||
99 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
100 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
101 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
102 | $(LTLIBINTL) -ljansson -lmicrohttpd | ||
103 | libgnunet_plugin_rest_identity_provider_la_LDFLAGS = \ | ||
104 | $(GN_PLUGIN_LDFLAGS) | ||
105 | |||
106 | libgnunet_plugin_rest_openid_connect_la_SOURCES = \ | ||
107 | plugin_rest_openid_connect.c \ | ||
108 | jwt.c | ||
109 | libgnunet_plugin_rest_openid_connect_la_LIBADD = \ | ||
110 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
111 | libgnunetidentityprovider.la \ | ||
112 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
113 | $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ | ||
114 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
115 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
116 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
117 | $(LTLIBINTL) -ljansson -lmicrohttpd | ||
118 | libgnunet_plugin_rest_openid_connect_la_LDFLAGS = \ | ||
119 | $(GN_PLUGIN_LDFLAGS) | ||
120 | |||
121 | gnunet_idp_SOURCES = \ | ||
122 | gnunet-idp.c | ||
123 | gnunet_idp_LDADD = \ | ||
124 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
125 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
126 | libgnunetidentityprovider.la \ | ||
127 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
128 | $(top_builddir)/src/identity-attribute/libgnunetidentityattribute.la \ | ||
129 | $(GN_LIBINTL) | ||
130 | |||
131 | check_SCRIPTS = \ | ||
132 | test_idp_attribute.sh \ | ||
133 | test_idp_issue.sh \ | ||
134 | test_idp_consume.sh \ | ||
135 | test_idp_revoke.sh | ||
136 | |||
137 | if ENABLE_TEST_RUN | ||
138 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
139 | TESTS = $(check_SCRIPTS) | ||
140 | endif | ||
diff --git a/src/identity-provider/gnunet-idp.c b/src/identity-provider/gnunet-idp.c deleted file mode 100644 index 79e4f8d27..000000000 --- a/src/identity-provider/gnunet-idp.c +++ /dev/null | |||
@@ -1,517 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @file src/identity-provider/gnunet-idp.c | ||
21 | * @brief Identity Provider utility | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_namestore_service.h" | ||
28 | #include "gnunet_identity_provider_service.h" | ||
29 | #include "gnunet_identity_service.h" | ||
30 | #include "gnunet_signatures.h" | ||
31 | |||
32 | /** | ||
33 | * return value | ||
34 | */ | ||
35 | static int ret; | ||
36 | |||
37 | /** | ||
38 | * List attribute flag | ||
39 | */ | ||
40 | static int list; | ||
41 | |||
42 | /** | ||
43 | * Relying party | ||
44 | */ | ||
45 | static char* rp; | ||
46 | |||
47 | /** | ||
48 | * The attribute | ||
49 | */ | ||
50 | static char* attr_name; | ||
51 | |||
52 | /** | ||
53 | * Attribute value | ||
54 | */ | ||
55 | static char* attr_value; | ||
56 | |||
57 | /** | ||
58 | * Attributes to issue | ||
59 | */ | ||
60 | static char* issue_attrs; | ||
61 | |||
62 | /** | ||
63 | * Ticket to consume | ||
64 | */ | ||
65 | static char* consume_ticket; | ||
66 | |||
67 | /** | ||
68 | * Attribute type | ||
69 | */ | ||
70 | static char* type_str; | ||
71 | |||
72 | /** | ||
73 | * Ticket to revoke | ||
74 | */ | ||
75 | static char* revoke_ticket; | ||
76 | |||
77 | /** | ||
78 | * Ego name | ||
79 | */ | ||
80 | static char* ego_name; | ||
81 | |||
82 | /** | ||
83 | * Identity handle | ||
84 | */ | ||
85 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
86 | |||
87 | /** | ||
88 | * IdP handle | ||
89 | */ | ||
90 | static struct GNUNET_IDENTITY_PROVIDER_Handle *idp_handle; | ||
91 | |||
92 | /** | ||
93 | * IdP operation | ||
94 | */ | ||
95 | static struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; | ||
96 | |||
97 | /** | ||
98 | * Attribute iterator | ||
99 | */ | ||
100 | static struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_iterator; | ||
101 | |||
102 | /** | ||
103 | * Master ABE key | ||
104 | */ | ||
105 | static struct GNUNET_CRYPTO_AbeMasterKey *abe_key; | ||
106 | |||
107 | /** | ||
108 | * ego private key | ||
109 | */ | ||
110 | static const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey; | ||
111 | |||
112 | /** | ||
113 | * rp public key | ||
114 | */ | ||
115 | static struct GNUNET_CRYPTO_EcdsaPublicKey rp_key; | ||
116 | |||
117 | /** | ||
118 | * Ticket to consume | ||
119 | */ | ||
120 | static struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
121 | |||
122 | /** | ||
123 | * Attribute list | ||
124 | */ | ||
125 | static struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; | ||
126 | |||
127 | /** | ||
128 | * Attribute expiration interval | ||
129 | */ | ||
130 | static struct GNUNET_TIME_Relative exp_interval; | ||
131 | |||
132 | /** | ||
133 | * Timeout task | ||
134 | */ | ||
135 | static struct GNUNET_SCHEDULER_Task *timeout; | ||
136 | |||
137 | static void | ||
138 | do_cleanup(void *cls) | ||
139 | { | ||
140 | if (NULL != timeout) | ||
141 | GNUNET_SCHEDULER_cancel (timeout); | ||
142 | if (NULL != idp_op) | ||
143 | GNUNET_IDENTITY_PROVIDER_cancel (idp_op); | ||
144 | if (NULL != attr_iterator) | ||
145 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (attr_iterator); | ||
146 | if (NULL != idp_handle) | ||
147 | GNUNET_IDENTITY_PROVIDER_disconnect (idp_handle); | ||
148 | if (NULL != identity_handle) | ||
149 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
150 | if (NULL != abe_key) | ||
151 | GNUNET_free (abe_key); | ||
152 | if (NULL != attr_list) | ||
153 | GNUNET_free (attr_list); | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | ticket_issue_cb (void* cls, | ||
158 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | ||
159 | { | ||
160 | char* ticket_str; | ||
161 | idp_op = NULL; | ||
162 | if (NULL != ticket) { | ||
163 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, | ||
164 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
165 | printf("%s\n", | ||
166 | ticket_str); | ||
167 | GNUNET_free (ticket_str); | ||
168 | } | ||
169 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
170 | } | ||
171 | |||
172 | static void | ||
173 | store_attr_cont (void *cls, | ||
174 | int32_t success, | ||
175 | const char*emsg) | ||
176 | { | ||
177 | idp_op = NULL; | ||
178 | if (GNUNET_SYSERR == success) { | ||
179 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
180 | "%s\n", emsg); | ||
181 | } | ||
182 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
183 | } | ||
184 | |||
185 | static void | ||
186 | process_attrs (void *cls, | ||
187 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
188 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
189 | { | ||
190 | char *value_str; | ||
191 | if (NULL == identity) | ||
192 | { | ||
193 | idp_op = NULL; | ||
194 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
195 | return; | ||
196 | } | ||
197 | if (NULL == attr) | ||
198 | { | ||
199 | ret = 1; | ||
200 | return; | ||
201 | } | ||
202 | value_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type, | ||
203 | attr->data, | ||
204 | attr->data_size); | ||
205 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
206 | "%s: %s\n", attr->name, value_str); | ||
207 | } | ||
208 | |||
209 | |||
210 | static void | ||
211 | iter_error (void *cls) | ||
212 | { | ||
213 | attr_iterator = NULL; | ||
214 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
215 | "Failed to iterate over attributes\n"); | ||
216 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
217 | } | ||
218 | |||
219 | static void | ||
220 | timeout_task (void *cls) | ||
221 | { | ||
222 | timeout = NULL; | ||
223 | ret = 1; | ||
224 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
225 | "Timeout\n"); | ||
226 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
227 | } | ||
228 | |||
229 | static void | ||
230 | process_rvk (void *cls, int success, const char* msg) | ||
231 | { | ||
232 | idp_op = NULL; | ||
233 | if (GNUNET_OK != success) | ||
234 | { | ||
235 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
236 | "Revocation failed.\n"); | ||
237 | ret = 1; | ||
238 | } | ||
239 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
240 | } | ||
241 | |||
242 | static void | ||
243 | iter_finished (void *cls) | ||
244 | { | ||
245 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim; | ||
246 | char *data; | ||
247 | size_t data_size; | ||
248 | int type; | ||
249 | |||
250 | attr_iterator = NULL; | ||
251 | if (list) | ||
252 | { | ||
253 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | if (issue_attrs) | ||
258 | { | ||
259 | idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (idp_handle, | ||
260 | pkey, | ||
261 | &rp_key, | ||
262 | attr_list, | ||
263 | &ticket_issue_cb, | ||
264 | NULL); | ||
265 | return; | ||
266 | } | ||
267 | if (consume_ticket) | ||
268 | { | ||
269 | idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (idp_handle, | ||
270 | pkey, | ||
271 | &ticket, | ||
272 | &process_attrs, | ||
273 | NULL); | ||
274 | timeout = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10), | ||
275 | &timeout_task, | ||
276 | NULL); | ||
277 | return; | ||
278 | } | ||
279 | if (revoke_ticket) | ||
280 | { | ||
281 | idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (idp_handle, | ||
282 | pkey, | ||
283 | &ticket, | ||
284 | &process_rvk, | ||
285 | NULL); | ||
286 | return; | ||
287 | } | ||
288 | if (attr_name) | ||
289 | { | ||
290 | if (NULL == type_str) | ||
291 | type = GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING; | ||
292 | else | ||
293 | type = GNUNET_IDENTITY_ATTRIBUTE_typename_to_number (type_str); | ||
294 | |||
295 | GNUNET_assert (GNUNET_SYSERR != GNUNET_IDENTITY_ATTRIBUTE_string_to_value (type, | ||
296 | attr_value, | ||
297 | (void**)&data, | ||
298 | &data_size)); | ||
299 | claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr_name, | ||
300 | type, | ||
301 | data, | ||
302 | data_size); | ||
303 | idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (idp_handle, | ||
304 | pkey, | ||
305 | claim, | ||
306 | &exp_interval, | ||
307 | &store_attr_cont, | ||
308 | NULL); | ||
309 | return; | ||
310 | } | ||
311 | GNUNET_SCHEDULER_add_now (&do_cleanup, NULL); | ||
312 | } | ||
313 | |||
314 | static void | ||
315 | iter_cb (void *cls, | ||
316 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
317 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
318 | { | ||
319 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
320 | char *attrs_tmp; | ||
321 | char *attr_str; | ||
322 | |||
323 | if (issue_attrs) | ||
324 | { | ||
325 | attrs_tmp = GNUNET_strdup (issue_attrs); | ||
326 | attr_str = strtok (attrs_tmp, ","); | ||
327 | while (NULL != attr_str) { | ||
328 | if (0 != strcmp (attr_str, attr->name)) { | ||
329 | attr_str = strtok (NULL, ","); | ||
330 | continue; | ||
331 | } | ||
332 | le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry); | ||
333 | le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name, | ||
334 | attr->type, | ||
335 | attr->data, | ||
336 | attr->data_size); | ||
337 | GNUNET_CONTAINER_DLL_insert (attr_list->list_head, | ||
338 | attr_list->list_tail, | ||
339 | le); | ||
340 | break; | ||
341 | } | ||
342 | GNUNET_free (attrs_tmp); | ||
343 | } else if (list) { | ||
344 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
345 | "%s: %s\n", attr->name, (char*)attr->data); | ||
346 | } | ||
347 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (attr_iterator); | ||
348 | } | ||
349 | |||
350 | static void | ||
351 | ego_iter_finished (void *cls) | ||
352 | { | ||
353 | if (NULL == pkey) | ||
354 | { | ||
355 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
356 | "Ego %s not found\n", ego_name); | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | if (NULL != rp) | ||
361 | GNUNET_CRYPTO_ecdsa_public_key_from_string (rp, | ||
362 | strlen (rp), | ||
363 | &rp_key); | ||
364 | if (NULL != consume_ticket) | ||
365 | GNUNET_STRINGS_string_to_data (consume_ticket, | ||
366 | strlen (consume_ticket), | ||
367 | &ticket, | ||
368 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
369 | if (NULL != revoke_ticket) | ||
370 | GNUNET_STRINGS_string_to_data (revoke_ticket, | ||
371 | strlen (revoke_ticket), | ||
372 | &ticket, | ||
373 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
374 | |||
375 | |||
376 | attr_list = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
377 | |||
378 | attr_iterator = GNUNET_IDENTITY_PROVIDER_get_attributes_start (idp_handle, | ||
379 | pkey, | ||
380 | &iter_error, | ||
381 | NULL, | ||
382 | &iter_cb, | ||
383 | NULL, | ||
384 | &iter_finished, | ||
385 | NULL); | ||
386 | |||
387 | |||
388 | } | ||
389 | |||
390 | static int init = GNUNET_YES; | ||
391 | |||
392 | static void | ||
393 | ego_cb (void *cls, | ||
394 | struct GNUNET_IDENTITY_Ego *ego, | ||
395 | void **ctx, | ||
396 | const char *name) | ||
397 | { | ||
398 | if (NULL == name) { | ||
399 | if (GNUNET_YES == init) { | ||
400 | init = GNUNET_NO; | ||
401 | GNUNET_SCHEDULER_add_now (&ego_iter_finished, NULL); | ||
402 | } | ||
403 | return; | ||
404 | } | ||
405 | if (0 != strcmp (name, ego_name)) | ||
406 | return; | ||
407 | pkey = GNUNET_IDENTITY_ego_get_private_key (ego); | ||
408 | } | ||
409 | |||
410 | |||
411 | static void | ||
412 | run (void *cls, | ||
413 | char *const *args, | ||
414 | const char *cfgfile, | ||
415 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
416 | { | ||
417 | ret = 0; | ||
418 | if (NULL == ego_name) | ||
419 | { | ||
420 | ret = 1; | ||
421 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
422 | _("Ego is required\n")); | ||
423 | return; | ||
424 | } | ||
425 | |||
426 | if ( (NULL == attr_value) && (NULL != attr_name) ) | ||
427 | { | ||
428 | ret = 1; | ||
429 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
430 | _("Attribute value missing!\n")); | ||
431 | return; | ||
432 | } | ||
433 | |||
434 | if ( (NULL == rp) && (NULL != issue_attrs) ) | ||
435 | { | ||
436 | ret = 1; | ||
437 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
438 | _("Requesting party key is required!\n")); | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | idp_handle = GNUNET_IDENTITY_PROVIDER_connect (c); | ||
443 | //Get Ego | ||
444 | identity_handle = GNUNET_IDENTITY_connect (c, | ||
445 | &ego_cb, | ||
446 | NULL); | ||
447 | |||
448 | |||
449 | } | ||
450 | |||
451 | |||
452 | int | ||
453 | main(int argc, char *const argv[]) | ||
454 | { | ||
455 | exp_interval = GNUNET_TIME_UNIT_HOURS; | ||
456 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
457 | |||
458 | GNUNET_GETOPT_option_string ('a', | ||
459 | "add", | ||
460 | NULL, | ||
461 | gettext_noop ("Add attribute"), | ||
462 | &attr_name), | ||
463 | |||
464 | GNUNET_GETOPT_option_string ('V', | ||
465 | "value", | ||
466 | NULL, | ||
467 | gettext_noop ("Attribute value"), | ||
468 | &attr_value), | ||
469 | GNUNET_GETOPT_option_string ('e', | ||
470 | "ego", | ||
471 | NULL, | ||
472 | gettext_noop ("Ego"), | ||
473 | &ego_name), | ||
474 | GNUNET_GETOPT_option_string ('r', | ||
475 | "rp", | ||
476 | NULL, | ||
477 | gettext_noop ("Audience (relying party)"), | ||
478 | &rp), | ||
479 | GNUNET_GETOPT_option_flag ('D', | ||
480 | "dump", | ||
481 | gettext_noop ("List attributes for Ego"), | ||
482 | &list), | ||
483 | GNUNET_GETOPT_option_string ('i', | ||
484 | "issue", | ||
485 | NULL, | ||
486 | gettext_noop ("Issue a ticket"), | ||
487 | &issue_attrs), | ||
488 | GNUNET_GETOPT_option_string ('C', | ||
489 | "consume", | ||
490 | NULL, | ||
491 | gettext_noop ("Consume a ticket"), | ||
492 | &consume_ticket), | ||
493 | GNUNET_GETOPT_option_string ('R', | ||
494 | "revoke", | ||
495 | NULL, | ||
496 | gettext_noop ("Revoke a ticket"), | ||
497 | &revoke_ticket), | ||
498 | GNUNET_GETOPT_option_string ('t', | ||
499 | "type", | ||
500 | NULL, | ||
501 | gettext_noop ("Type of attribute"), | ||
502 | &type_str), | ||
503 | GNUNET_GETOPT_option_relative_time ('E', | ||
504 | "expiration", | ||
505 | NULL, | ||
506 | gettext_noop ("Expiration interval of the attribute"), | ||
507 | &exp_interval), | ||
508 | |||
509 | GNUNET_GETOPT_OPTION_END | ||
510 | }; | ||
511 | if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "ct", | ||
512 | "ct", options, | ||
513 | &run, NULL)) | ||
514 | return 1; | ||
515 | else | ||
516 | return ret; | ||
517 | } | ||
diff --git a/src/identity-provider/gnunet-service-identity-provider.c b/src/identity-provider/gnunet-service-identity-provider.c deleted file mode 100644 index c53e72477..000000000 --- a/src/identity-provider/gnunet-service-identity-provider.c +++ /dev/null | |||
@@ -1,2786 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @file src/identity-provider/gnunet-service-identity-provider.c | ||
21 | * @brief Identity Token Service | ||
22 | * | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_constants.h" | ||
27 | #include "gnunet_protocols.h" | ||
28 | #include "gnunet_identity_service.h" | ||
29 | #include "gnunet_gnsrecord_lib.h" | ||
30 | #include "gnunet_namestore_service.h" | ||
31 | #include "gnunet_abe_lib.h" | ||
32 | #include "gnunet_credential_service.h" | ||
33 | #include "gnunet_statistics_service.h" | ||
34 | #include "gnunet_gns_service.h" | ||
35 | #include "gnunet_identity_provider_plugin.h" | ||
36 | #include "gnunet_identity_attribute_lib.h" | ||
37 | #include "gnunet_signatures.h" | ||
38 | #include "identity_provider.h" | ||
39 | |||
40 | /** | ||
41 | * First pass state | ||
42 | */ | ||
43 | #define STATE_INIT 0 | ||
44 | |||
45 | /** | ||
46 | * Normal operation state | ||
47 | */ | ||
48 | #define STATE_POST_INIT 1 | ||
49 | |||
50 | /** | ||
51 | * Minimum interval between updates | ||
52 | */ | ||
53 | #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES | ||
54 | |||
55 | /** | ||
56 | * Standard token expiration time | ||
57 | */ | ||
58 | #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS | ||
59 | |||
60 | /** | ||
61 | * Identity handle | ||
62 | */ | ||
63 | static struct GNUNET_IDENTITY_Handle *identity_handle; | ||
64 | |||
65 | /** | ||
66 | * Database handle | ||
67 | */ | ||
68 | static struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *TKT_database; | ||
69 | |||
70 | /** | ||
71 | * Name of DB plugin | ||
72 | */ | ||
73 | static char *db_lib_name; | ||
74 | |||
75 | /** | ||
76 | * Token expiration interval | ||
77 | */ | ||
78 | static struct GNUNET_TIME_Relative token_expiration_interval; | ||
79 | |||
80 | /** | ||
81 | * Namestore handle | ||
82 | */ | ||
83 | static struct GNUNET_NAMESTORE_Handle *ns_handle; | ||
84 | |||
85 | /** | ||
86 | * GNS handle | ||
87 | */ | ||
88 | static struct GNUNET_GNS_Handle *gns_handle; | ||
89 | |||
90 | /** | ||
91 | * Credential handle | ||
92 | */ | ||
93 | static struct GNUNET_CREDENTIAL_Handle *credential_handle; | ||
94 | |||
95 | /** | ||
96 | * Namestore qe | ||
97 | */ | ||
98 | static struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
99 | |||
100 | /** | ||
101 | * Namestore iterator | ||
102 | */ | ||
103 | static struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
104 | |||
105 | /** | ||
106 | * Timeout task | ||
107 | */ | ||
108 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
109 | |||
110 | /** | ||
111 | * Update task | ||
112 | */ | ||
113 | static struct GNUNET_SCHEDULER_Task *update_task; | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Currently processed token | ||
118 | */ | ||
119 | static struct IdentityToken *token; | ||
120 | |||
121 | /** | ||
122 | * Label for currently processed token | ||
123 | */ | ||
124 | static char* label; | ||
125 | |||
126 | /** | ||
127 | * Scopes for processed token | ||
128 | */ | ||
129 | static char* scopes; | ||
130 | |||
131 | /** | ||
132 | * Handle to the statistics service. | ||
133 | */ | ||
134 | static struct GNUNET_STATISTICS_Handle *stats; | ||
135 | |||
136 | /** | ||
137 | * Our configuration. | ||
138 | */ | ||
139 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
140 | |||
141 | /** | ||
142 | * An idp client | ||
143 | */ | ||
144 | struct IdpClient; | ||
145 | |||
146 | /** | ||
147 | * A ticket iteration operation. | ||
148 | */ | ||
149 | struct TicketIteration | ||
150 | { | ||
151 | /** | ||
152 | * DLL | ||
153 | */ | ||
154 | struct TicketIteration *next; | ||
155 | |||
156 | /** | ||
157 | * DLL | ||
158 | */ | ||
159 | struct TicketIteration *prev; | ||
160 | |||
161 | /** | ||
162 | * Client which intiated this zone iteration | ||
163 | */ | ||
164 | struct IdpClient *client; | ||
165 | |||
166 | /** | ||
167 | * Key of the identity we are iterating over. | ||
168 | */ | ||
169 | struct GNUNET_CRYPTO_EcdsaPublicKey identity; | ||
170 | |||
171 | /** | ||
172 | * Identity is audience | ||
173 | */ | ||
174 | uint32_t is_audience; | ||
175 | |||
176 | /** | ||
177 | * The operation id fot the iteration in the response for the client | ||
178 | */ | ||
179 | uint32_t r_id; | ||
180 | |||
181 | /** | ||
182 | * Offset of the iteration used to address next result of the | ||
183 | * iteration in the store | ||
184 | * | ||
185 | * Initialy set to 0 in handle_iteration_start | ||
186 | * Incremented with by every call to handle_iteration_next | ||
187 | */ | ||
188 | uint32_t offset; | ||
189 | |||
190 | }; | ||
191 | |||
192 | |||
193 | |||
194 | /** | ||
195 | * Callback after an ABE bootstrap | ||
196 | * | ||
197 | * @param cls closure | ||
198 | * @param abe_key the ABE key that exists or was created | ||
199 | */ | ||
200 | typedef void | ||
201 | (*AbeBootstrapResult) (void *cls, | ||
202 | struct GNUNET_ABE_AbeMasterKey *abe_key); | ||
203 | |||
204 | |||
205 | struct AbeBootstrapHandle | ||
206 | { | ||
207 | /** | ||
208 | * Function to call when finished | ||
209 | */ | ||
210 | AbeBootstrapResult proc; | ||
211 | |||
212 | /** | ||
213 | * Callback closure | ||
214 | */ | ||
215 | char *proc_cls; | ||
216 | |||
217 | /** | ||
218 | * Key of the zone we are iterating over. | ||
219 | */ | ||
220 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
221 | |||
222 | /** | ||
223 | * Namestore Queue Entry | ||
224 | */ | ||
225 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
226 | |||
227 | /** | ||
228 | * The issuer egos ABE master key | ||
229 | */ | ||
230 | struct GNUNET_ABE_AbeMasterKey *abe_key; | ||
231 | }; | ||
232 | |||
233 | /** | ||
234 | * An attribute iteration operation. | ||
235 | */ | ||
236 | struct AttributeIterator | ||
237 | { | ||
238 | /** | ||
239 | * Next element in the DLL | ||
240 | */ | ||
241 | struct AttributeIterator *next; | ||
242 | |||
243 | /** | ||
244 | * Previous element in the DLL | ||
245 | */ | ||
246 | struct AttributeIterator *prev; | ||
247 | |||
248 | /** | ||
249 | * IDP client which intiated this zone iteration | ||
250 | */ | ||
251 | struct IdpClient *client; | ||
252 | |||
253 | /** | ||
254 | * Key of the zone we are iterating over. | ||
255 | */ | ||
256 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
257 | |||
258 | /** | ||
259 | * The issuer egos ABE master key | ||
260 | */ | ||
261 | struct GNUNET_ABE_AbeMasterKey *abe_key; | ||
262 | |||
263 | /** | ||
264 | * Namestore iterator | ||
265 | */ | ||
266 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
267 | |||
268 | /** | ||
269 | * The operation id fot the zone iteration in the response for the client | ||
270 | */ | ||
271 | uint32_t request_id; | ||
272 | |||
273 | }; | ||
274 | |||
275 | |||
276 | |||
277 | /** | ||
278 | * An idp client | ||
279 | */ | ||
280 | struct IdpClient | ||
281 | { | ||
282 | |||
283 | /** | ||
284 | * The client | ||
285 | */ | ||
286 | struct GNUNET_SERVICE_Client *client; | ||
287 | |||
288 | /** | ||
289 | * Message queue for transmission to @e client | ||
290 | */ | ||
291 | struct GNUNET_MQ_Handle *mq; | ||
292 | |||
293 | /** | ||
294 | * Head of the DLL of | ||
295 | * Attribute iteration operations in | ||
296 | * progress initiated by this client | ||
297 | */ | ||
298 | struct AttributeIterator *attr_iter_head; | ||
299 | |||
300 | /** | ||
301 | * Tail of the DLL of | ||
302 | * Attribute iteration operations | ||
303 | * in progress initiated by this client | ||
304 | */ | ||
305 | struct AttributeIterator *attr_iter_tail; | ||
306 | |||
307 | /** | ||
308 | * Head of DLL of ticket iteration ops | ||
309 | */ | ||
310 | struct TicketIteration *ticket_iter_head; | ||
311 | |||
312 | /** | ||
313 | * Tail of DLL of ticket iteration ops | ||
314 | */ | ||
315 | struct TicketIteration *ticket_iter_tail; | ||
316 | |||
317 | /** | ||
318 | * Head of DLL of ticket revocation ops | ||
319 | */ | ||
320 | struct TicketRevocationHandle *revoke_op_head; | ||
321 | |||
322 | /** | ||
323 | * Tail of DLL of ticket revocation ops | ||
324 | */ | ||
325 | struct TicketRevocationHandle *revoke_op_tail; | ||
326 | |||
327 | /** | ||
328 | * Head of DLL of ticket issue ops | ||
329 | */ | ||
330 | struct TicketIssueHandle *issue_op_head; | ||
331 | |||
332 | /** | ||
333 | * Tail of DLL of ticket issue ops | ||
334 | */ | ||
335 | struct TicketIssueHandle *issue_op_tail; | ||
336 | |||
337 | /** | ||
338 | * Head of DLL of ticket consume ops | ||
339 | */ | ||
340 | struct ConsumeTicketHandle *consume_op_head; | ||
341 | |||
342 | /** | ||
343 | * Tail of DLL of ticket consume ops | ||
344 | */ | ||
345 | struct ConsumeTicketHandle *consume_op_tail; | ||
346 | |||
347 | /** | ||
348 | * Head of DLL of attribute store ops | ||
349 | */ | ||
350 | struct AttributeStoreHandle *store_op_head; | ||
351 | |||
352 | /** | ||
353 | * Tail of DLL of attribute store ops | ||
354 | */ | ||
355 | struct AttributeStoreHandle *store_op_tail; | ||
356 | |||
357 | }; | ||
358 | |||
359 | struct AttributeStoreHandle | ||
360 | { | ||
361 | /** | ||
362 | * DLL | ||
363 | */ | ||
364 | struct AttributeStoreHandle *next; | ||
365 | |||
366 | /** | ||
367 | * DLL | ||
368 | */ | ||
369 | struct AttributeStoreHandle *prev; | ||
370 | |||
371 | /** | ||
372 | * Client connection | ||
373 | */ | ||
374 | struct IdpClient *client; | ||
375 | |||
376 | /** | ||
377 | * Identity | ||
378 | */ | ||
379 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
380 | |||
381 | /** | ||
382 | * Identity pubkey | ||
383 | */ | ||
384 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey; | ||
385 | |||
386 | /** | ||
387 | * The issuer egos ABE master key | ||
388 | */ | ||
389 | struct GNUNET_ABE_AbeMasterKey *abe_key; | ||
390 | |||
391 | /** | ||
392 | * QueueEntry | ||
393 | */ | ||
394 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
395 | |||
396 | /** | ||
397 | * The attribute to store | ||
398 | */ | ||
399 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *claim; | ||
400 | |||
401 | /** | ||
402 | * The attribute expiration interval | ||
403 | */ | ||
404 | struct GNUNET_TIME_Relative exp; | ||
405 | |||
406 | /** | ||
407 | * request id | ||
408 | */ | ||
409 | uint32_t r_id; | ||
410 | }; | ||
411 | |||
412 | |||
413 | /* Prototype */ | ||
414 | struct ParallelLookup; | ||
415 | |||
416 | struct ConsumeTicketHandle | ||
417 | { | ||
418 | /** | ||
419 | * DLL | ||
420 | */ | ||
421 | struct ConsumeTicketHandle *next; | ||
422 | |||
423 | /** | ||
424 | * DLL | ||
425 | */ | ||
426 | struct ConsumeTicketHandle *prev; | ||
427 | |||
428 | /** | ||
429 | * Client connection | ||
430 | */ | ||
431 | struct IdpClient *client; | ||
432 | |||
433 | /** | ||
434 | * Ticket | ||
435 | */ | ||
436 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
437 | |||
438 | /** | ||
439 | * LookupRequest | ||
440 | */ | ||
441 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
442 | |||
443 | /** | ||
444 | * Audience Key | ||
445 | */ | ||
446 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
447 | |||
448 | /** | ||
449 | * Audience Key | ||
450 | */ | ||
451 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub; | ||
452 | |||
453 | /** | ||
454 | * Lookup DLL | ||
455 | */ | ||
456 | struct ParallelLookup *parallel_lookups_head; | ||
457 | |||
458 | /** | ||
459 | * Lookup DLL | ||
460 | */ | ||
461 | struct ParallelLookup *parallel_lookups_tail; | ||
462 | |||
463 | /** | ||
464 | * Kill task | ||
465 | */ | ||
466 | struct GNUNET_SCHEDULER_Task *kill_task; | ||
467 | |||
468 | /** | ||
469 | * The ABE key | ||
470 | */ | ||
471 | struct GNUNET_ABE_AbeKey *key; | ||
472 | |||
473 | /** | ||
474 | * Attributes | ||
475 | */ | ||
476 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
477 | |||
478 | /** | ||
479 | * Lookup time | ||
480 | */ | ||
481 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
482 | |||
483 | /** | ||
484 | * request id | ||
485 | */ | ||
486 | uint32_t r_id; | ||
487 | }; | ||
488 | |||
489 | /** | ||
490 | * Handle for a parallel GNS lookup job | ||
491 | */ | ||
492 | struct ParallelLookup | ||
493 | { | ||
494 | /* DLL */ | ||
495 | struct ParallelLookup *next; | ||
496 | |||
497 | /* DLL */ | ||
498 | struct ParallelLookup *prev; | ||
499 | |||
500 | /* The GNS request */ | ||
501 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
502 | |||
503 | /* The handle the return to */ | ||
504 | struct ConsumeTicketHandle *handle; | ||
505 | |||
506 | /** | ||
507 | * Lookup time | ||
508 | */ | ||
509 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
510 | |||
511 | /* The label to look up */ | ||
512 | char *label; | ||
513 | }; | ||
514 | |||
515 | /** | ||
516 | * Ticket revocation request handle | ||
517 | */ | ||
518 | struct TicketRevocationHandle | ||
519 | { | ||
520 | /** | ||
521 | * DLL | ||
522 | */ | ||
523 | struct TicketRevocationHandle *prev; | ||
524 | |||
525 | /** | ||
526 | * DLL | ||
527 | */ | ||
528 | struct TicketRevocationHandle *next; | ||
529 | |||
530 | /** | ||
531 | * Client connection | ||
532 | */ | ||
533 | struct IdpClient *client; | ||
534 | |||
535 | /** | ||
536 | * Attributes to reissue | ||
537 | */ | ||
538 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
539 | |||
540 | /** | ||
541 | * Attributes to revoke | ||
542 | */ | ||
543 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *rvk_attrs; | ||
544 | |||
545 | /** | ||
546 | * Issuer Key | ||
547 | */ | ||
548 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
549 | |||
550 | /** | ||
551 | * Ticket to issue | ||
552 | */ | ||
553 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
554 | |||
555 | /** | ||
556 | * QueueEntry | ||
557 | */ | ||
558 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
559 | |||
560 | /** | ||
561 | * Namestore iterator | ||
562 | */ | ||
563 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
564 | |||
565 | /** | ||
566 | * The ABE master key | ||
567 | */ | ||
568 | struct GNUNET_ABE_AbeMasterKey *abe_key; | ||
569 | |||
570 | /** | ||
571 | * Offset | ||
572 | */ | ||
573 | uint32_t offset; | ||
574 | |||
575 | /** | ||
576 | * request id | ||
577 | */ | ||
578 | uint32_t r_id; | ||
579 | }; | ||
580 | |||
581 | |||
582 | |||
583 | /** | ||
584 | * Ticket issue request handle | ||
585 | */ | ||
586 | struct TicketIssueHandle | ||
587 | { | ||
588 | /** | ||
589 | * DLL | ||
590 | */ | ||
591 | struct TicketIssueHandle *prev; | ||
592 | |||
593 | /** | ||
594 | * DLL | ||
595 | */ | ||
596 | struct TicketIssueHandle *next; | ||
597 | |||
598 | /** | ||
599 | * Client connection | ||
600 | */ | ||
601 | struct IdpClient *client; | ||
602 | |||
603 | /** | ||
604 | * Attributes to issue | ||
605 | */ | ||
606 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
607 | |||
608 | /** | ||
609 | * Issuer Key | ||
610 | */ | ||
611 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
612 | |||
613 | /** | ||
614 | * Ticket to issue | ||
615 | */ | ||
616 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
617 | |||
618 | /** | ||
619 | * QueueEntry | ||
620 | */ | ||
621 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
622 | |||
623 | /** | ||
624 | * request id | ||
625 | */ | ||
626 | uint32_t r_id; | ||
627 | }; | ||
628 | |||
629 | |||
630 | /** | ||
631 | * DLL for ego handles to egos containing the ID_ATTRS in a map in json_t format | ||
632 | * | ||
633 | */ | ||
634 | struct EgoEntry | ||
635 | { | ||
636 | /** | ||
637 | * DLL | ||
638 | */ | ||
639 | struct EgoEntry *next; | ||
640 | |||
641 | /** | ||
642 | * DLL | ||
643 | */ | ||
644 | struct EgoEntry *prev; | ||
645 | |||
646 | /** | ||
647 | * Ego handle | ||
648 | */ | ||
649 | struct GNUNET_IDENTITY_Ego *ego; | ||
650 | |||
651 | /** | ||
652 | * Attribute map. Contains the attributes as json_t | ||
653 | */ | ||
654 | struct GNUNET_CONTAINER_MultiHashMap *attr_map; | ||
655 | |||
656 | }; | ||
657 | |||
658 | /** | ||
659 | * Cleanup task | ||
660 | */ | ||
661 | static void | ||
662 | cleanup() | ||
663 | { | ||
664 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
665 | "Cleaning up\n"); | ||
666 | |||
667 | if (NULL != stats) | ||
668 | { | ||
669 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
670 | stats = NULL; | ||
671 | } | ||
672 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, | ||
673 | TKT_database)); | ||
674 | GNUNET_free (db_lib_name); | ||
675 | db_lib_name = NULL; | ||
676 | if (NULL != timeout_task) | ||
677 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
678 | if (NULL != update_task) | ||
679 | GNUNET_SCHEDULER_cancel (update_task); | ||
680 | if (NULL != identity_handle) | ||
681 | GNUNET_IDENTITY_disconnect (identity_handle); | ||
682 | if (NULL != gns_handle) | ||
683 | GNUNET_GNS_disconnect (gns_handle); | ||
684 | if (NULL != credential_handle) | ||
685 | GNUNET_CREDENTIAL_disconnect (credential_handle); | ||
686 | if (NULL != ns_it) | ||
687 | GNUNET_NAMESTORE_zone_iteration_stop (ns_it); | ||
688 | if (NULL != ns_qe) | ||
689 | GNUNET_NAMESTORE_cancel (ns_qe); | ||
690 | if (NULL != ns_handle) | ||
691 | GNUNET_NAMESTORE_disconnect (ns_handle); | ||
692 | GNUNET_free_non_null (token); | ||
693 | GNUNET_free_non_null (label); | ||
694 | |||
695 | } | ||
696 | |||
697 | /** | ||
698 | * Shutdown task | ||
699 | * | ||
700 | * @param cls NULL | ||
701 | */ | ||
702 | static void | ||
703 | do_shutdown (void *cls) | ||
704 | { | ||
705 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
706 | "Shutting down...\n"); | ||
707 | cleanup(); | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * Finished storing newly bootstrapped ABE key | ||
712 | */ | ||
713 | static void | ||
714 | bootstrap_store_cont (void *cls, | ||
715 | int32_t success, | ||
716 | const char *emsg) | ||
717 | { | ||
718 | struct AbeBootstrapHandle *abh = cls; | ||
719 | if (GNUNET_SYSERR == success) | ||
720 | { | ||
721 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
722 | "Failed to bootstrap ABE master %s\n", | ||
723 | emsg); | ||
724 | abh->proc (abh->proc_cls, NULL); | ||
725 | GNUNET_free (abh->abe_key); | ||
726 | GNUNET_free (abh); | ||
727 | return; | ||
728 | } | ||
729 | abh->proc (abh->proc_cls, abh->abe_key); | ||
730 | GNUNET_free (abh); | ||
731 | } | ||
732 | |||
733 | /** | ||
734 | * Generates and stores a new ABE key | ||
735 | */ | ||
736 | static void | ||
737 | bootstrap_store_task (void *cls) | ||
738 | { | ||
739 | struct AbeBootstrapHandle *abh = cls; | ||
740 | struct GNUNET_GNSRECORD_Data rd[1]; | ||
741 | char *key; | ||
742 | |||
743 | rd[0].data_size = GNUNET_ABE_cpabe_serialize_master_key (abh->abe_key, | ||
744 | (void**)&key); | ||
745 | rd[0].data = key; | ||
746 | rd[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_MASTER; | ||
747 | rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE; | ||
748 | rd[0].expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us; //TODO sane? | ||
749 | abh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
750 | &abh->identity, | ||
751 | "+", | ||
752 | 1, | ||
753 | rd, | ||
754 | &bootstrap_store_cont, | ||
755 | abh); | ||
756 | GNUNET_free (key); | ||
757 | } | ||
758 | |||
759 | /** | ||
760 | * Error checking for ABE master | ||
761 | */ | ||
762 | static void | ||
763 | bootstrap_abe_error (void *cls) | ||
764 | { | ||
765 | struct AbeBootstrapHandle *abh = cls; | ||
766 | abh->proc (abh->proc_cls, NULL); | ||
767 | GNUNET_free (abh); | ||
768 | } | ||
769 | |||
770 | |||
771 | /** | ||
772 | * Handle ABE lookup in namestore | ||
773 | */ | ||
774 | static void | ||
775 | bootstrap_abe_result (void *cls, | ||
776 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
777 | const char *label, | ||
778 | unsigned int rd_count, | ||
779 | const struct GNUNET_GNSRECORD_Data *rd) | ||
780 | { | ||
781 | struct AbeBootstrapHandle *abh = cls; | ||
782 | struct GNUNET_ABE_AbeMasterKey *abe_key; | ||
783 | |||
784 | for (uint32_t i=0;i<rd_count;i++) { | ||
785 | if (GNUNET_GNSRECORD_TYPE_ABE_MASTER != rd[i].record_type) | ||
786 | continue; | ||
787 | abe_key = GNUNET_ABE_cpabe_deserialize_master_key (rd[i].data, | ||
788 | rd[i].data_size); | ||
789 | abh->proc (abh->proc_cls, abe_key); | ||
790 | GNUNET_free (abh); | ||
791 | return; | ||
792 | } | ||
793 | |||
794 | //No ABE master found, bootstrapping... | ||
795 | abh->abe_key = GNUNET_ABE_cpabe_create_master_key (); | ||
796 | GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh); | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * Bootstrap ABE master if it does not yet exists. | ||
801 | * Will call the AbeBootstrapResult processor when done. | ||
802 | * will always recreate the ABE key of GNUNET_YES == recreate | ||
803 | */ | ||
804 | static void | ||
805 | bootstrap_abe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
806 | AbeBootstrapResult proc, | ||
807 | void* cls, | ||
808 | int recreate) | ||
809 | { | ||
810 | struct AbeBootstrapHandle *abh; | ||
811 | |||
812 | abh = GNUNET_new (struct AbeBootstrapHandle); | ||
813 | abh->proc = proc; | ||
814 | abh->proc_cls = cls; | ||
815 | abh->identity = *identity; | ||
816 | if (GNUNET_YES == recreate) | ||
817 | { | ||
818 | abh->abe_key = GNUNET_ABE_cpabe_create_master_key (); | ||
819 | GNUNET_SCHEDULER_add_now (&bootstrap_store_task, abh); | ||
820 | } else { | ||
821 | abh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, | ||
822 | identity, | ||
823 | "+", | ||
824 | &bootstrap_abe_error, | ||
825 | abh, | ||
826 | &bootstrap_abe_result, | ||
827 | abh); | ||
828 | } | ||
829 | } | ||
830 | |||
831 | |||
832 | |||
833 | static int | ||
834 | create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash, | ||
835 | struct GNUNET_CRYPTO_SymmetricSessionKey *skey, | ||
836 | struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) | ||
837 | { | ||
838 | struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str; | ||
839 | |||
840 | GNUNET_CRYPTO_hash_to_enc (new_key_hash, | ||
841 | &new_key_hash_str); | ||
842 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str); | ||
843 | static const char ctx_key[] = "gnuid-aes-ctx-key"; | ||
844 | GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), | ||
845 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
846 | ctx_key, strlen (ctx_key), | ||
847 | NULL, 0); | ||
848 | static const char ctx_iv[] = "gnuid-aes-ctx-iv"; | ||
849 | GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), | ||
850 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
851 | ctx_iv, strlen (ctx_iv), | ||
852 | NULL, 0); | ||
853 | return GNUNET_OK; | ||
854 | } | ||
855 | |||
856 | /** | ||
857 | * Cleanup ticket consume handle | ||
858 | * @param handle the handle to clean up | ||
859 | */ | ||
860 | static void | ||
861 | cleanup_ticket_issue_handle (struct TicketIssueHandle *handle) | ||
862 | { | ||
863 | if (NULL != handle->attrs) | ||
864 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs); | ||
865 | if (NULL != handle->ns_qe) | ||
866 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
867 | GNUNET_free (handle); | ||
868 | } | ||
869 | |||
870 | |||
871 | static void | ||
872 | send_ticket_result (struct IdpClient *client, | ||
873 | uint32_t r_id, | ||
874 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
875 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
876 | { | ||
877 | struct TicketResultMessage *irm; | ||
878 | struct GNUNET_MQ_Envelope *env; | ||
879 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket_buf; | ||
880 | |||
881 | /* store ticket in DB */ | ||
882 | if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls, | ||
883 | ticket, | ||
884 | attrs)) | ||
885 | { | ||
886 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
887 | "Unable to store ticket after issue\n"); | ||
888 | GNUNET_break (0); | ||
889 | } | ||
890 | |||
891 | env = GNUNET_MQ_msg_extra (irm, | ||
892 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
893 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT); | ||
894 | ticket_buf = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&irm[1]; | ||
895 | *ticket_buf = *ticket; | ||
896 | irm->id = htonl (r_id); | ||
897 | GNUNET_MQ_send (client->mq, | ||
898 | env); | ||
899 | } | ||
900 | |||
901 | static void | ||
902 | store_ticket_issue_cont (void *cls, | ||
903 | int32_t success, | ||
904 | const char *emsg) | ||
905 | { | ||
906 | struct TicketIssueHandle *handle = cls; | ||
907 | |||
908 | handle->ns_qe = NULL; | ||
909 | GNUNET_CONTAINER_DLL_remove (handle->client->issue_op_head, | ||
910 | handle->client->issue_op_tail, | ||
911 | handle); | ||
912 | if (GNUNET_SYSERR == success) | ||
913 | { | ||
914 | cleanup_ticket_issue_handle (handle); | ||
915 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
916 | "Unknown Error\n"); | ||
917 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
918 | return; | ||
919 | } | ||
920 | send_ticket_result (handle->client, | ||
921 | handle->r_id, | ||
922 | &handle->ticket, | ||
923 | handle->attrs); | ||
924 | cleanup_ticket_issue_handle (handle); | ||
925 | } | ||
926 | |||
927 | |||
928 | |||
929 | int | ||
930 | serialize_abe_keyinfo2 (const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
931 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
932 | const struct GNUNET_ABE_AbeKey *rp_key, | ||
933 | struct GNUNET_CRYPTO_EcdhePrivateKey **ecdh_privkey, | ||
934 | char **result) | ||
935 | { | ||
936 | struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey; | ||
937 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
938 | char *enc_keyinfo; | ||
939 | char *serialized_key; | ||
940 | char *buf; | ||
941 | char *write_ptr; | ||
942 | char attrs_str_len; | ||
943 | ssize_t size; | ||
944 | |||
945 | struct GNUNET_CRYPTO_SymmetricSessionKey skey; | ||
946 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
947 | struct GNUNET_HashCode new_key_hash; | ||
948 | ssize_t enc_size; | ||
949 | |||
950 | size = GNUNET_ABE_cpabe_serialize_key (rp_key, | ||
951 | (void**)&serialized_key); | ||
952 | attrs_str_len = 0; | ||
953 | for (le = attrs->list_head; NULL != le; le = le->next) { | ||
954 | attrs_str_len += strlen (le->claim->name) + 1; | ||
955 | } | ||
956 | buf = GNUNET_malloc (attrs_str_len + size); | ||
957 | write_ptr = buf; | ||
958 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
959 | "Writing attributes\n"); | ||
960 | for (le = attrs->list_head; NULL != le; le = le->next) { | ||
961 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
962 | "%s\n", le->claim->name); | ||
963 | |||
964 | |||
965 | GNUNET_memcpy (write_ptr, | ||
966 | le->claim->name, | ||
967 | strlen (le->claim->name)); | ||
968 | write_ptr[strlen (le->claim->name)] = ','; | ||
969 | write_ptr += strlen (le->claim->name) + 1; | ||
970 | } | ||
971 | write_ptr--; | ||
972 | write_ptr[0] = '\0'; //replace last , with a 0-terminator | ||
973 | write_ptr++; | ||
974 | GNUNET_memcpy (write_ptr, | ||
975 | serialized_key, | ||
976 | size); | ||
977 | GNUNET_free (serialized_key); | ||
978 | // ECDH keypair E = eG | ||
979 | *ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create(); | ||
980 | GNUNET_CRYPTO_ecdhe_key_get_public (*ecdh_privkey, | ||
981 | &ecdh_pubkey); | ||
982 | enc_keyinfo = GNUNET_malloc (size + attrs_str_len); | ||
983 | // Derived key K = H(eB) | ||
984 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (*ecdh_privkey, | ||
985 | &ticket->audience, | ||
986 | &new_key_hash)); | ||
987 | create_sym_key_from_ecdh(&new_key_hash, &skey, &iv); | ||
988 | enc_size = GNUNET_CRYPTO_symmetric_encrypt (buf, | ||
989 | size + attrs_str_len, | ||
990 | &skey, &iv, | ||
991 | enc_keyinfo); | ||
992 | *result = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+ | ||
993 | enc_size); | ||
994 | GNUNET_memcpy (*result, | ||
995 | &ecdh_pubkey, | ||
996 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
997 | GNUNET_memcpy (*result + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
998 | enc_keyinfo, | ||
999 | enc_size); | ||
1000 | GNUNET_free (enc_keyinfo); | ||
1001 | GNUNET_free (buf); | ||
1002 | return sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+enc_size; | ||
1003 | } | ||
1004 | |||
1005 | |||
1006 | |||
1007 | static void | ||
1008 | issue_ticket_after_abe_bootstrap (void *cls, | ||
1009 | struct GNUNET_ABE_AbeMasterKey *abe_key) | ||
1010 | { | ||
1011 | struct TicketIssueHandle *ih = cls; | ||
1012 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
1013 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; | ||
1014 | struct GNUNET_GNSRECORD_Data code_record[1]; | ||
1015 | struct GNUNET_ABE_AbeKey *rp_key; | ||
1016 | char *code_record_data; | ||
1017 | char **attrs; | ||
1018 | char *label; | ||
1019 | char *policy; | ||
1020 | int attrs_len; | ||
1021 | uint32_t i; | ||
1022 | size_t code_record_len; | ||
1023 | |||
1024 | //Create new ABE key for RP | ||
1025 | attrs_len = 0; | ||
1026 | for (le = ih->attrs->list_head; NULL != le; le = le->next) | ||
1027 | attrs_len++; | ||
1028 | attrs = GNUNET_malloc ((attrs_len + 1)*sizeof (char*)); | ||
1029 | i = 0; | ||
1030 | for (le = ih->attrs->list_head; NULL != le; le = le->next) { | ||
1031 | GNUNET_asprintf (&policy, "%s_%lu", | ||
1032 | le->claim->name, | ||
1033 | le->claim->version); | ||
1034 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1035 | "Adding attribute to key: %s\n", | ||
1036 | policy); | ||
1037 | attrs[i] = policy; | ||
1038 | i++; | ||
1039 | } | ||
1040 | attrs[i] = NULL; | ||
1041 | rp_key = GNUNET_ABE_cpabe_create_key (abe_key, | ||
1042 | attrs); | ||
1043 | |||
1044 | //TODO review this wireformat | ||
1045 | code_record_len = serialize_abe_keyinfo2 (&ih->ticket, | ||
1046 | ih->attrs, | ||
1047 | rp_key, | ||
1048 | &ecdhe_privkey, | ||
1049 | &code_record_data); | ||
1050 | code_record[0].data = code_record_data; | ||
1051 | code_record[0].data_size = code_record_len; | ||
1052 | code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us; | ||
1053 | code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY; | ||
1054 | code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1055 | |||
1056 | label = GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, | ||
1057 | sizeof (uint64_t)); | ||
1058 | //Publish record | ||
1059 | ih->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1060 | &ih->identity, | ||
1061 | label, | ||
1062 | 1, | ||
1063 | code_record, | ||
1064 | &store_ticket_issue_cont, | ||
1065 | ih); | ||
1066 | //for (; i > 0; i--) | ||
1067 | // GNUNET_free (attrs[i-1]); | ||
1068 | GNUNET_free (ecdhe_privkey); | ||
1069 | GNUNET_free (label); | ||
1070 | GNUNET_free (attrs); | ||
1071 | GNUNET_free (code_record_data); | ||
1072 | GNUNET_ABE_cpabe_delete_key (rp_key, | ||
1073 | GNUNET_YES); | ||
1074 | GNUNET_ABE_cpabe_delete_master_key (abe_key); | ||
1075 | } | ||
1076 | |||
1077 | |||
1078 | static int | ||
1079 | check_issue_ticket_message(void *cls, | ||
1080 | const struct IssueTicketMessage *im) | ||
1081 | { | ||
1082 | uint16_t size; | ||
1083 | |||
1084 | size = ntohs (im->header.size); | ||
1085 | if (size <= sizeof (struct IssueTicketMessage)) | ||
1086 | { | ||
1087 | GNUNET_break (0); | ||
1088 | return GNUNET_SYSERR; | ||
1089 | } | ||
1090 | return GNUNET_OK; | ||
1091 | } | ||
1092 | |||
1093 | |||
1094 | static void | ||
1095 | handle_issue_ticket_message (void *cls, | ||
1096 | const struct IssueTicketMessage *im) | ||
1097 | { | ||
1098 | struct TicketIssueHandle *ih; | ||
1099 | struct IdpClient *idp = cls; | ||
1100 | size_t attrs_len; | ||
1101 | |||
1102 | ih = GNUNET_new (struct TicketIssueHandle); | ||
1103 | attrs_len = ntohs (im->attr_len); | ||
1104 | ih->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&im[1], attrs_len); | ||
1105 | ih->r_id = ntohl (im->id); | ||
1106 | ih->client = idp; | ||
1107 | ih->identity = im->identity; | ||
1108 | GNUNET_CRYPTO_ecdsa_key_get_public (&ih->identity, | ||
1109 | &ih->ticket.identity); | ||
1110 | ih->ticket.audience = im->rp; | ||
1111 | ih->ticket.rnd = | ||
1112 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, | ||
1113 | UINT64_MAX); | ||
1114 | GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, | ||
1115 | idp->issue_op_tail, | ||
1116 | ih); | ||
1117 | bootstrap_abe (&ih->identity, &issue_ticket_after_abe_bootstrap, ih, GNUNET_NO); | ||
1118 | GNUNET_SERVICE_client_continue (idp->client); | ||
1119 | |||
1120 | } | ||
1121 | |||
1122 | /********************************************************** | ||
1123 | * Revocation | ||
1124 | **********************************************************/ | ||
1125 | |||
1126 | /** | ||
1127 | * Cleanup revoke handle | ||
1128 | * | ||
1129 | * @param rh the ticket revocation handle | ||
1130 | */ | ||
1131 | static void | ||
1132 | cleanup_revoke_ticket_handle (struct TicketRevocationHandle *rh) | ||
1133 | { | ||
1134 | if (NULL != rh->attrs) | ||
1135 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->attrs); | ||
1136 | if (NULL != rh->rvk_attrs) | ||
1137 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (rh->rvk_attrs); | ||
1138 | if (NULL != rh->abe_key) | ||
1139 | GNUNET_ABE_cpabe_delete_master_key (rh->abe_key); | ||
1140 | if (NULL != rh->ns_qe) | ||
1141 | GNUNET_NAMESTORE_cancel (rh->ns_qe); | ||
1142 | if (NULL != rh->ns_it) | ||
1143 | GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it); | ||
1144 | GNUNET_free (rh); | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | /** | ||
1149 | * Send revocation result | ||
1150 | * | ||
1151 | * @param rh ticket revocation handle | ||
1152 | * @param success GNUNET_OK if successful result | ||
1153 | */ | ||
1154 | static void | ||
1155 | send_revocation_finished (struct TicketRevocationHandle *rh, | ||
1156 | uint32_t success) | ||
1157 | { | ||
1158 | struct GNUNET_MQ_Envelope *env; | ||
1159 | struct RevokeTicketResultMessage *trm; | ||
1160 | |||
1161 | env = GNUNET_MQ_msg (trm, | ||
1162 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT); | ||
1163 | trm->id = htonl (rh->r_id); | ||
1164 | trm->success = htonl (success); | ||
1165 | GNUNET_MQ_send (rh->client->mq, | ||
1166 | env); | ||
1167 | GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, | ||
1168 | rh->client->revoke_op_tail, | ||
1169 | rh); | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | /** | ||
1174 | * Process ticket from database | ||
1175 | * | ||
1176 | * @param cls struct TicketIterationProcResult | ||
1177 | * @param ticket the ticket | ||
1178 | * @param attrs the attributes | ||
1179 | */ | ||
1180 | static void | ||
1181 | ticket_reissue_proc (void *cls, | ||
1182 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1183 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs); | ||
1184 | |||
1185 | static void | ||
1186 | revocation_reissue_tickets (struct TicketRevocationHandle *rh); | ||
1187 | |||
1188 | |||
1189 | static void reissue_next (void *cls) | ||
1190 | { | ||
1191 | struct TicketRevocationHandle *rh = cls; | ||
1192 | revocation_reissue_tickets (rh); | ||
1193 | } | ||
1194 | |||
1195 | |||
1196 | static void | ||
1197 | reissue_ticket_cont (void *cls, | ||
1198 | int32_t success, | ||
1199 | const char *emsg) | ||
1200 | { | ||
1201 | struct TicketRevocationHandle *rh = cls; | ||
1202 | |||
1203 | rh->ns_qe = NULL; | ||
1204 | if (GNUNET_SYSERR == success) | ||
1205 | { | ||
1206 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", | ||
1207 | "Unknown Error\n"); | ||
1208 | send_revocation_finished (rh, GNUNET_SYSERR); | ||
1209 | GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, | ||
1210 | rh->client->revoke_op_tail, | ||
1211 | rh); | ||
1212 | cleanup_revoke_ticket_handle (rh); | ||
1213 | return; | ||
1214 | } | ||
1215 | rh->offset++; | ||
1216 | GNUNET_SCHEDULER_add_now (&reissue_next, rh); | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | /** | ||
1221 | * Process ticket from database | ||
1222 | * | ||
1223 | * @param cls struct TicketIterationProcResult | ||
1224 | * @param ticket the ticket | ||
1225 | * @param attrs the attributes | ||
1226 | */ | ||
1227 | static void | ||
1228 | ticket_reissue_proc (void *cls, | ||
1229 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1230 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
1231 | { | ||
1232 | struct TicketRevocationHandle *rh = cls; | ||
1233 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
1234 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le_rollover; | ||
1235 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; | ||
1236 | struct GNUNET_GNSRECORD_Data code_record[1]; | ||
1237 | struct GNUNET_ABE_AbeKey *rp_key; | ||
1238 | char *code_record_data; | ||
1239 | char **attr_arr; | ||
1240 | char *label; | ||
1241 | char *policy; | ||
1242 | int attrs_len; | ||
1243 | uint32_t i; | ||
1244 | int reissue_ticket; | ||
1245 | size_t code_record_len; | ||
1246 | |||
1247 | |||
1248 | if (NULL == ticket) | ||
1249 | { | ||
1250 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1251 | "Iteration done\n"); | ||
1252 | return; | ||
1253 | } | ||
1254 | |||
1255 | if (0 == memcmp (&ticket->audience, | ||
1256 | &rh->ticket.audience, | ||
1257 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1258 | { | ||
1259 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1260 | "Do not reissue for this identity.!\n"); | ||
1261 | |||
1262 | rh->offset++; | ||
1263 | GNUNET_SCHEDULER_add_now (&reissue_next, rh); | ||
1264 | return; | ||
1265 | } | ||
1266 | |||
1267 | /* | ||
1268 | * Check if any attribute of this ticket intersects with a rollover attribute | ||
1269 | */ | ||
1270 | reissue_ticket = GNUNET_NO; | ||
1271 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
1272 | { | ||
1273 | for (le_rollover = rh->rvk_attrs->list_head; | ||
1274 | NULL != le_rollover; | ||
1275 | le_rollover = le_rollover->next) | ||
1276 | { | ||
1277 | if (0 == strcmp (le_rollover->claim->name, | ||
1278 | le->claim->name)) | ||
1279 | { | ||
1280 | reissue_ticket = GNUNET_YES; | ||
1281 | le->claim->version = le_rollover->claim->version; | ||
1282 | } | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | if (GNUNET_NO == reissue_ticket) | ||
1287 | { | ||
1288 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1289 | "Skipping ticket.\n"); | ||
1290 | |||
1291 | rh->offset++; | ||
1292 | GNUNET_SCHEDULER_add_now (&reissue_next, rh); | ||
1293 | |||
1294 | |||
1295 | return; | ||
1296 | } | ||
1297 | |||
1298 | //Create new ABE key for RP | ||
1299 | attrs_len = 0; | ||
1300 | |||
1301 | /* If this is the RP we want to revoke attributes of, the do so */ | ||
1302 | |||
1303 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
1304 | attrs_len++; | ||
1305 | attr_arr = GNUNET_malloc ((attrs_len + 1)*sizeof (char*)); | ||
1306 | i = 0; | ||
1307 | for (le = attrs->list_head; NULL != le; le = le->next) { | ||
1308 | GNUNET_asprintf (&policy, "%s_%lu", | ||
1309 | le->claim->name, | ||
1310 | le->claim->version); | ||
1311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1312 | "Recreating key with %s\n", policy); | ||
1313 | attr_arr[i] = policy; | ||
1314 | i++; | ||
1315 | } | ||
1316 | attr_arr[i] = NULL; | ||
1317 | rp_key = GNUNET_ABE_cpabe_create_key (rh->abe_key, | ||
1318 | attr_arr); | ||
1319 | |||
1320 | //TODO review this wireformat | ||
1321 | code_record_len = serialize_abe_keyinfo2 (ticket, | ||
1322 | attrs, | ||
1323 | rp_key, | ||
1324 | &ecdhe_privkey, | ||
1325 | &code_record_data); | ||
1326 | code_record[0].data = code_record_data; | ||
1327 | code_record[0].data_size = code_record_len; | ||
1328 | code_record[0].expiration_time = GNUNET_TIME_UNIT_DAYS.rel_value_us; | ||
1329 | code_record[0].record_type = GNUNET_GNSRECORD_TYPE_ABE_KEY; | ||
1330 | code_record[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1331 | |||
1332 | label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
1333 | sizeof (uint64_t)); | ||
1334 | //Publish record | ||
1335 | rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1336 | &rh->identity, | ||
1337 | label, | ||
1338 | 1, | ||
1339 | code_record, | ||
1340 | &reissue_ticket_cont, | ||
1341 | rh); | ||
1342 | //for (; i > 0; i--) | ||
1343 | // GNUNET_free (attr_arr[i-1]); | ||
1344 | GNUNET_free (ecdhe_privkey); | ||
1345 | GNUNET_free (label); | ||
1346 | GNUNET_free (attr_arr); | ||
1347 | GNUNET_free (code_record_data); | ||
1348 | GNUNET_ABE_cpabe_delete_key (rp_key, GNUNET_YES); | ||
1349 | } | ||
1350 | |||
1351 | |||
1352 | /* Prototype for below function */ | ||
1353 | static void | ||
1354 | attr_reenc_cont (void *cls, | ||
1355 | int32_t success, | ||
1356 | const char *emsg); | ||
1357 | |||
1358 | static void | ||
1359 | revocation_reissue_tickets (struct TicketRevocationHandle *rh) | ||
1360 | { | ||
1361 | int ret; | ||
1362 | /* Done, issue new keys */ | ||
1363 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1364 | "Revocation Phase III: Reissuing Tickets\n"); | ||
1365 | if (GNUNET_SYSERR == (ret = TKT_database->iterate_tickets (TKT_database->cls, | ||
1366 | &rh->ticket.identity, | ||
1367 | GNUNET_NO, | ||
1368 | rh->offset, | ||
1369 | &ticket_reissue_proc, | ||
1370 | rh))) | ||
1371 | { | ||
1372 | GNUNET_break (0); | ||
1373 | } | ||
1374 | if (GNUNET_NO == ret) | ||
1375 | { | ||
1376 | send_revocation_finished (rh, GNUNET_OK); | ||
1377 | GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, | ||
1378 | rh->client->revoke_op_tail, | ||
1379 | rh); | ||
1380 | cleanup_revoke_ticket_handle (rh); | ||
1381 | return; | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | /** | ||
1386 | * Failed to check for attribute | ||
1387 | */ | ||
1388 | static void | ||
1389 | check_attr_error (void *cls) | ||
1390 | { | ||
1391 | struct TicketRevocationHandle *rh = cls; | ||
1392 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1393 | "Unable to check for existing attribute\n"); | ||
1394 | send_revocation_finished (rh, GNUNET_SYSERR); | ||
1395 | GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, | ||
1396 | rh->client->revoke_op_tail, | ||
1397 | rh); | ||
1398 | cleanup_revoke_ticket_handle (rh); | ||
1399 | } | ||
1400 | |||
1401 | |||
1402 | /** | ||
1403 | * Revoke next attribte by reencryption with | ||
1404 | * new ABE master | ||
1405 | */ | ||
1406 | static void | ||
1407 | reenc_next_attribute (void *cls); | ||
1408 | |||
1409 | /** | ||
1410 | * Check for existing attribute and overwrite | ||
1411 | */ | ||
1412 | static void | ||
1413 | check_attr_cb (void *cls, | ||
1414 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
1415 | const char *label, | ||
1416 | unsigned int rd_count, | ||
1417 | const struct GNUNET_GNSRECORD_Data *rd_old) | ||
1418 | { | ||
1419 | struct TicketRevocationHandle *rh = cls; | ||
1420 | struct GNUNET_GNSRECORD_Data rd[1]; | ||
1421 | char* buf; | ||
1422 | char* enc_buf; | ||
1423 | size_t enc_size; | ||
1424 | char* rd_buf; | ||
1425 | size_t buf_size; | ||
1426 | char* policy; | ||
1427 | uint32_t attr_ver; | ||
1428 | |||
1429 | if (1 != rd_count) { | ||
1430 | GNUNET_SCHEDULER_add_now (&reenc_next_attribute, | ||
1431 | rh); | ||
1432 | return; | ||
1433 | } | ||
1434 | |||
1435 | buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (rh->attrs->list_head->claim); | ||
1436 | buf = GNUNET_malloc (buf_size); | ||
1437 | GNUNET_IDENTITY_ATTRIBUTE_serialize (rh->attrs->list_head->claim, | ||
1438 | buf); | ||
1439 | rh->attrs->list_head->claim->version++; | ||
1440 | GNUNET_asprintf (&policy, "%s_%lu", | ||
1441 | rh->attrs->list_head->claim->name, | ||
1442 | rh->attrs->list_head->claim->version); | ||
1443 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1444 | "Encrypting with policy %s\n", policy); | ||
1445 | /** | ||
1446 | * Encrypt the attribute value and store in namestore | ||
1447 | */ | ||
1448 | enc_size = GNUNET_ABE_cpabe_encrypt (buf, | ||
1449 | buf_size, | ||
1450 | policy, //Policy | ||
1451 | rh->abe_key, | ||
1452 | (void**)&enc_buf); | ||
1453 | GNUNET_free (buf); | ||
1454 | if (GNUNET_SYSERR == enc_size) | ||
1455 | { | ||
1456 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1457 | "Unable to re-encrypt with policy %s\n", | ||
1458 | policy); | ||
1459 | GNUNET_free (policy); | ||
1460 | send_revocation_finished (rh, GNUNET_SYSERR); | ||
1461 | GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, | ||
1462 | rh->client->revoke_op_tail, | ||
1463 | rh); | ||
1464 | cleanup_revoke_ticket_handle (rh); | ||
1465 | return; | ||
1466 | } | ||
1467 | GNUNET_free (policy); | ||
1468 | |||
1469 | rd[0].data_size = enc_size + sizeof (uint32_t); | ||
1470 | rd_buf = GNUNET_malloc (rd[0].data_size); | ||
1471 | attr_ver = htonl (rh->attrs->list_head->claim->version); | ||
1472 | GNUNET_memcpy (rd_buf, | ||
1473 | &attr_ver, | ||
1474 | sizeof (uint32_t)); | ||
1475 | GNUNET_memcpy (rd_buf+sizeof (uint32_t), | ||
1476 | enc_buf, | ||
1477 | enc_size); | ||
1478 | rd[0].data = rd_buf; | ||
1479 | rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR; | ||
1480 | rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1481 | rd[0].expiration_time = rd_old[0].expiration_time; | ||
1482 | rh->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
1483 | &rh->identity, | ||
1484 | rh->attrs->list_head->claim->name, | ||
1485 | 1, | ||
1486 | rd, | ||
1487 | &attr_reenc_cont, | ||
1488 | rh); | ||
1489 | GNUNET_free (enc_buf); | ||
1490 | GNUNET_free (rd_buf); | ||
1491 | } | ||
1492 | |||
1493 | |||
1494 | /** | ||
1495 | * Revoke next attribte by reencryption with | ||
1496 | * new ABE master | ||
1497 | */ | ||
1498 | static void | ||
1499 | reenc_next_attribute (void *cls) | ||
1500 | { | ||
1501 | struct TicketRevocationHandle *rh = cls; | ||
1502 | if (NULL == rh->attrs->list_head) | ||
1503 | { | ||
1504 | revocation_reissue_tickets (rh); | ||
1505 | return; | ||
1506 | } | ||
1507 | /* First check if attribute still exists */ | ||
1508 | rh->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, | ||
1509 | &rh->identity, | ||
1510 | rh->attrs->list_head->claim->name, | ||
1511 | &check_attr_error, | ||
1512 | rh, | ||
1513 | &check_attr_cb, | ||
1514 | rh); | ||
1515 | } | ||
1516 | |||
1517 | |||
1518 | /** | ||
1519 | * Namestore callback after revoked attribute | ||
1520 | * is stored | ||
1521 | */ | ||
1522 | static void | ||
1523 | attr_reenc_cont (void *cls, | ||
1524 | int32_t success, | ||
1525 | const char *emsg) | ||
1526 | { | ||
1527 | struct TicketRevocationHandle *rh = cls; | ||
1528 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
1529 | |||
1530 | if (GNUNET_SYSERR == success) | ||
1531 | { | ||
1532 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1533 | "Failed to reencrypt attribute %s\n", | ||
1534 | emsg); | ||
1535 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
1536 | return; | ||
1537 | } | ||
1538 | if (NULL == rh->attrs->list_head) | ||
1539 | { | ||
1540 | revocation_reissue_tickets (rh); | ||
1541 | return; | ||
1542 | } | ||
1543 | le = rh->attrs->list_head; | ||
1544 | GNUNET_CONTAINER_DLL_remove (rh->attrs->list_head, | ||
1545 | rh->attrs->list_tail, | ||
1546 | le); | ||
1547 | GNUNET_assert (NULL != rh->rvk_attrs); | ||
1548 | GNUNET_CONTAINER_DLL_insert (rh->rvk_attrs->list_head, | ||
1549 | rh->rvk_attrs->list_tail, | ||
1550 | le); | ||
1551 | |||
1552 | |||
1553 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1554 | "Re-encrypting next attribute\n"); | ||
1555 | reenc_next_attribute (rh); | ||
1556 | } | ||
1557 | |||
1558 | |||
1559 | static void | ||
1560 | process_attributes_to_update (void *cls, | ||
1561 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1562 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
1563 | { | ||
1564 | struct TicketRevocationHandle *rh = cls; | ||
1565 | |||
1566 | rh->attrs = GNUNET_IDENTITY_ATTRIBUTE_list_dup (attrs); | ||
1567 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1568 | "Revocation Phase I: Collecting attributes\n"); | ||
1569 | /* Reencrypt all attributes with new key */ | ||
1570 | if (NULL == rh->attrs->list_head) | ||
1571 | { | ||
1572 | /* No attributes to reencrypt */ | ||
1573 | send_revocation_finished (rh, GNUNET_OK); | ||
1574 | GNUNET_CONTAINER_DLL_remove (rh->client->revoke_op_head, | ||
1575 | rh->client->revoke_op_tail, | ||
1576 | rh); | ||
1577 | cleanup_revoke_ticket_handle (rh); | ||
1578 | return; | ||
1579 | } else { | ||
1580 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1581 | "Revocation Phase II: Re-encrypting attributes\n"); | ||
1582 | reenc_next_attribute (rh); | ||
1583 | } | ||
1584 | |||
1585 | } | ||
1586 | |||
1587 | |||
1588 | |||
1589 | static void | ||
1590 | get_ticket_after_abe_bootstrap (void *cls, | ||
1591 | struct GNUNET_ABE_AbeMasterKey *abe_key) | ||
1592 | { | ||
1593 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1594 | "Finished ABE bootstrap\n"); | ||
1595 | struct TicketRevocationHandle *rh = cls; | ||
1596 | rh->abe_key = abe_key; | ||
1597 | TKT_database->get_ticket_attributes (TKT_database->cls, | ||
1598 | &rh->ticket, | ||
1599 | &process_attributes_to_update, | ||
1600 | rh); | ||
1601 | } | ||
1602 | |||
1603 | static int | ||
1604 | check_revoke_ticket_message(void *cls, | ||
1605 | const struct RevokeTicketMessage *im) | ||
1606 | { | ||
1607 | uint16_t size; | ||
1608 | |||
1609 | size = ntohs (im->header.size); | ||
1610 | if (size <= sizeof (struct RevokeTicketMessage)) | ||
1611 | { | ||
1612 | GNUNET_break (0); | ||
1613 | return GNUNET_SYSERR; | ||
1614 | } | ||
1615 | return GNUNET_OK; | ||
1616 | } | ||
1617 | |||
1618 | static void | ||
1619 | handle_revoke_ticket_message (void *cls, | ||
1620 | const struct RevokeTicketMessage *rm) | ||
1621 | { | ||
1622 | struct TicketRevocationHandle *rh; | ||
1623 | struct IdpClient *idp = cls; | ||
1624 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; | ||
1625 | |||
1626 | rh = GNUNET_new (struct TicketRevocationHandle); | ||
1627 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket*)&rm[1]; | ||
1628 | rh->rvk_attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1629 | rh->ticket = *ticket; | ||
1630 | rh->r_id = ntohl (rm->id); | ||
1631 | rh->client = idp; | ||
1632 | rh->identity = rm->identity; | ||
1633 | GNUNET_CRYPTO_ecdsa_key_get_public (&rh->identity, | ||
1634 | &rh->ticket.identity); | ||
1635 | GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, | ||
1636 | idp->revoke_op_tail, | ||
1637 | rh); | ||
1638 | bootstrap_abe (&rh->identity, &get_ticket_after_abe_bootstrap, rh, GNUNET_NO); | ||
1639 | GNUNET_SERVICE_client_continue (idp->client); | ||
1640 | |||
1641 | } | ||
1642 | |||
1643 | /** | ||
1644 | * Cleanup ticket consume handle | ||
1645 | * @param handle the handle to clean up | ||
1646 | */ | ||
1647 | static void | ||
1648 | cleanup_consume_ticket_handle (struct ConsumeTicketHandle *handle) | ||
1649 | { | ||
1650 | struct ParallelLookup *lu; | ||
1651 | struct ParallelLookup *tmp; | ||
1652 | if (NULL != handle->lookup_request) | ||
1653 | GNUNET_GNS_lookup_cancel (handle->lookup_request); | ||
1654 | for (lu = handle->parallel_lookups_head; | ||
1655 | NULL != lu;) { | ||
1656 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
1657 | GNUNET_free (lu->label); | ||
1658 | tmp = lu->next; | ||
1659 | GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head, | ||
1660 | handle->parallel_lookups_tail, | ||
1661 | lu); | ||
1662 | GNUNET_free (lu); | ||
1663 | lu = tmp; | ||
1664 | } | ||
1665 | |||
1666 | if (NULL != handle->key) | ||
1667 | GNUNET_ABE_cpabe_delete_key (handle->key, | ||
1668 | GNUNET_YES); | ||
1669 | if (NULL != handle->attrs) | ||
1670 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (handle->attrs); | ||
1671 | GNUNET_free (handle); | ||
1672 | } | ||
1673 | |||
1674 | |||
1675 | |||
1676 | static int | ||
1677 | check_consume_ticket_message(void *cls, | ||
1678 | const struct ConsumeTicketMessage *cm) | ||
1679 | { | ||
1680 | uint16_t size; | ||
1681 | |||
1682 | size = ntohs (cm->header.size); | ||
1683 | if (size <= sizeof (struct ConsumeTicketMessage)) | ||
1684 | { | ||
1685 | GNUNET_break (0); | ||
1686 | return GNUNET_SYSERR; | ||
1687 | } | ||
1688 | return GNUNET_OK; | ||
1689 | } | ||
1690 | |||
1691 | static void | ||
1692 | process_parallel_lookup2 (void *cls, uint32_t rd_count, | ||
1693 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1694 | { | ||
1695 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1696 | "Parallel lookup finished (count=%u)\n", rd_count); | ||
1697 | struct ParallelLookup *parallel_lookup = cls; | ||
1698 | struct ConsumeTicketHandle *handle = parallel_lookup->handle; | ||
1699 | struct ConsumeTicketResultMessage *crm; | ||
1700 | struct GNUNET_MQ_Envelope *env; | ||
1701 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *attr_le; | ||
1702 | struct GNUNET_TIME_Absolute decrypt_duration; | ||
1703 | char *data; | ||
1704 | char *data_tmp; | ||
1705 | ssize_t attr_len; | ||
1706 | size_t attrs_len; | ||
1707 | |||
1708 | GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head, | ||
1709 | handle->parallel_lookups_tail, | ||
1710 | parallel_lookup); | ||
1711 | GNUNET_free (parallel_lookup->label); | ||
1712 | |||
1713 | GNUNET_STATISTICS_update (stats, | ||
1714 | "attribute_lookup_time_total", | ||
1715 | GNUNET_TIME_absolute_get_duration (parallel_lookup->lookup_start_time).rel_value_us, | ||
1716 | GNUNET_YES); | ||
1717 | GNUNET_STATISTICS_update (stats, | ||
1718 | "attribute_lookups_count", | ||
1719 | 1, | ||
1720 | GNUNET_YES); | ||
1721 | |||
1722 | |||
1723 | GNUNET_free (parallel_lookup); | ||
1724 | if (1 != rd_count) | ||
1725 | GNUNET_break(0);//TODO | ||
1726 | if (rd->record_type == GNUNET_GNSRECORD_TYPE_ID_ATTR) | ||
1727 | { | ||
1728 | decrypt_duration = GNUNET_TIME_absolute_get (); | ||
1729 | attr_len = GNUNET_ABE_cpabe_decrypt (rd->data + sizeof (uint32_t), | ||
1730 | rd->data_size - sizeof (uint32_t), | ||
1731 | handle->key, | ||
1732 | (void**)&data); | ||
1733 | if (GNUNET_SYSERR != attr_len) | ||
1734 | { | ||
1735 | GNUNET_STATISTICS_update (stats, | ||
1736 | "abe_decrypt_time_total", | ||
1737 | GNUNET_TIME_absolute_get_duration (decrypt_duration).rel_value_us, | ||
1738 | GNUNET_YES); | ||
1739 | GNUNET_STATISTICS_update (stats, | ||
1740 | "abe_decrypt_count", | ||
1741 | 1, | ||
1742 | GNUNET_YES); | ||
1743 | |||
1744 | attr_le = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry); | ||
1745 | attr_le->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize (data, | ||
1746 | attr_len); | ||
1747 | attr_le->claim->version = ntohl(*(uint32_t*)rd->data); | ||
1748 | GNUNET_CONTAINER_DLL_insert (handle->attrs->list_head, | ||
1749 | handle->attrs->list_tail, | ||
1750 | attr_le); | ||
1751 | GNUNET_free (data); | ||
1752 | } | ||
1753 | } | ||
1754 | if (NULL != handle->parallel_lookups_head) | ||
1755 | return; //Wait for more | ||
1756 | /* Else we are done */ | ||
1757 | |||
1758 | /* Store ticket in DB */ | ||
1759 | if (GNUNET_OK != TKT_database->store_ticket (TKT_database->cls, | ||
1760 | &handle->ticket, | ||
1761 | handle->attrs)) | ||
1762 | { | ||
1763 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1764 | "Unable to store ticket after consume\n"); | ||
1765 | GNUNET_break (0); | ||
1766 | } | ||
1767 | |||
1768 | GNUNET_SCHEDULER_cancel (handle->kill_task); | ||
1769 | attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (handle->attrs); | ||
1770 | env = GNUNET_MQ_msg_extra (crm, | ||
1771 | attrs_len, | ||
1772 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT); | ||
1773 | crm->id = htonl (handle->r_id); | ||
1774 | crm->attrs_len = htons (attrs_len); | ||
1775 | crm->identity = handle->ticket.identity; | ||
1776 | data_tmp = (char *) &crm[1]; | ||
1777 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (handle->attrs, | ||
1778 | data_tmp); | ||
1779 | GNUNET_MQ_send (handle->client->mq, env); | ||
1780 | GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head, | ||
1781 | handle->client->consume_op_tail, | ||
1782 | handle); | ||
1783 | cleanup_consume_ticket_handle (handle); | ||
1784 | } | ||
1785 | |||
1786 | void | ||
1787 | abort_parallel_lookups2 (void *cls) | ||
1788 | { | ||
1789 | struct ConsumeTicketHandle *handle = cls; | ||
1790 | struct ParallelLookup *lu; | ||
1791 | struct ParallelLookup *tmp; | ||
1792 | struct AttributeResultMessage *arm; | ||
1793 | struct GNUNET_MQ_Envelope *env; | ||
1794 | |||
1795 | handle->kill_task = NULL; | ||
1796 | for (lu = handle->parallel_lookups_head; | ||
1797 | NULL != lu;) { | ||
1798 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
1799 | GNUNET_free (lu->label); | ||
1800 | tmp = lu->next; | ||
1801 | GNUNET_CONTAINER_DLL_remove (handle->parallel_lookups_head, | ||
1802 | handle->parallel_lookups_tail, | ||
1803 | lu); | ||
1804 | GNUNET_free (lu); | ||
1805 | lu = tmp; | ||
1806 | } | ||
1807 | env = GNUNET_MQ_msg (arm, | ||
1808 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT); | ||
1809 | arm->id = htonl (handle->r_id); | ||
1810 | arm->attr_len = htons (0); | ||
1811 | GNUNET_MQ_send (handle->client->mq, env); | ||
1812 | |||
1813 | } | ||
1814 | |||
1815 | |||
1816 | static void | ||
1817 | process_consume_abe_key (void *cls, uint32_t rd_count, | ||
1818 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1819 | { | ||
1820 | struct ConsumeTicketHandle *handle = cls; | ||
1821 | struct GNUNET_HashCode new_key_hash; | ||
1822 | struct GNUNET_CRYPTO_SymmetricSessionKey enc_key; | ||
1823 | struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv; | ||
1824 | struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key; | ||
1825 | struct ParallelLookup *parallel_lookup; | ||
1826 | size_t size; | ||
1827 | char *buf; | ||
1828 | char *scope; | ||
1829 | |||
1830 | handle->lookup_request = NULL; | ||
1831 | if (1 != rd_count) | ||
1832 | { | ||
1833 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1834 | "Number of keys %d != 1.", | ||
1835 | rd_count); | ||
1836 | cleanup_consume_ticket_handle (handle); | ||
1837 | GNUNET_CONTAINER_DLL_remove (handle->client->consume_op_head, | ||
1838 | handle->client->consume_op_tail, | ||
1839 | handle); | ||
1840 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
1841 | return; | ||
1842 | } | ||
1843 | |||
1844 | //Decrypt | ||
1845 | ecdh_key = (struct GNUNET_CRYPTO_EcdhePublicKey *)rd->data; | ||
1846 | |||
1847 | buf = GNUNET_malloc (rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
1848 | |||
1849 | //Calculate symmetric key from ecdh parameters | ||
1850 | GNUNET_assert (GNUNET_OK == | ||
1851 | GNUNET_CRYPTO_ecdsa_ecdh (&handle->identity, | ||
1852 | ecdh_key, | ||
1853 | &new_key_hash)); | ||
1854 | create_sym_key_from_ecdh (&new_key_hash, | ||
1855 | &enc_key, | ||
1856 | &enc_iv); | ||
1857 | size = GNUNET_CRYPTO_symmetric_decrypt (rd->data + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
1858 | rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey), | ||
1859 | &enc_key, | ||
1860 | &enc_iv, | ||
1861 | buf); | ||
1862 | |||
1863 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1864 | "Decrypted bytes: %zd Expected bytes: %zd\n", | ||
1865 | size, rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
1866 | GNUNET_STATISTICS_update (stats, | ||
1867 | "abe_key_lookup_time_total", | ||
1868 | GNUNET_TIME_absolute_get_duration (handle->lookup_start_time).rel_value_us, | ||
1869 | GNUNET_YES); | ||
1870 | GNUNET_STATISTICS_update (stats, | ||
1871 | "abe_key_lookups_count", | ||
1872 | 1, | ||
1873 | GNUNET_YES); | ||
1874 | scopes = GNUNET_strdup (buf); | ||
1875 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1876 | "Scopes %s\n", scopes); | ||
1877 | handle->key = GNUNET_ABE_cpabe_deserialize_key ((void*)(buf + strlen (scopes) + 1), | ||
1878 | rd->data_size - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) | ||
1879 | - strlen (scopes) - 1); | ||
1880 | |||
1881 | for (scope = strtok (scopes, ","); NULL != scope; scope = strtok (NULL, ",")) | ||
1882 | { | ||
1883 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1884 | "Looking up %s\n", scope); | ||
1885 | parallel_lookup = GNUNET_new (struct ParallelLookup); | ||
1886 | parallel_lookup->handle = handle; | ||
1887 | parallel_lookup->label = GNUNET_strdup (scope); | ||
1888 | parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get(); | ||
1889 | parallel_lookup->lookup_request | ||
1890 | = GNUNET_GNS_lookup (gns_handle, | ||
1891 | scope, | ||
1892 | &handle->ticket.identity, | ||
1893 | GNUNET_GNSRECORD_TYPE_ID_ATTR, | ||
1894 | GNUNET_GNS_LO_DEFAULT, | ||
1895 | &process_parallel_lookup2, | ||
1896 | parallel_lookup); | ||
1897 | GNUNET_CONTAINER_DLL_insert (handle->parallel_lookups_head, | ||
1898 | handle->parallel_lookups_tail, | ||
1899 | parallel_lookup); | ||
1900 | } | ||
1901 | GNUNET_free (scopes); | ||
1902 | GNUNET_free (buf); | ||
1903 | handle->kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES,3), | ||
1904 | &abort_parallel_lookups2, | ||
1905 | handle); | ||
1906 | } | ||
1907 | |||
1908 | |||
1909 | static void | ||
1910 | handle_consume_ticket_message (void *cls, | ||
1911 | const struct ConsumeTicketMessage *cm) | ||
1912 | { | ||
1913 | struct ConsumeTicketHandle *ch; | ||
1914 | struct IdpClient *idp = cls; | ||
1915 | char* rnd_label; | ||
1916 | |||
1917 | ch = GNUNET_new (struct ConsumeTicketHandle); | ||
1918 | ch->r_id = ntohl (cm->id); | ||
1919 | ch->client = idp; | ||
1920 | ch->identity = cm->identity; | ||
1921 | ch->attrs = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1922 | GNUNET_CRYPTO_ecdsa_key_get_public (&ch->identity, | ||
1923 | &ch->identity_pub); | ||
1924 | ch->ticket = *((struct GNUNET_IDENTITY_PROVIDER_Ticket*)&cm[1]); | ||
1925 | rnd_label = GNUNET_STRINGS_data_to_string_alloc (&ch->ticket.rnd, | ||
1926 | sizeof (uint64_t)); | ||
1927 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1928 | "Looking for ABE key under %s\n", rnd_label); | ||
1929 | ch->lookup_start_time = GNUNET_TIME_absolute_get (); | ||
1930 | ch->lookup_request | ||
1931 | = GNUNET_GNS_lookup (gns_handle, | ||
1932 | rnd_label, | ||
1933 | &ch->ticket.identity, | ||
1934 | GNUNET_GNSRECORD_TYPE_ABE_KEY, | ||
1935 | GNUNET_GNS_LO_DEFAULT, | ||
1936 | &process_consume_abe_key, | ||
1937 | ch); | ||
1938 | GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, | ||
1939 | idp->consume_op_tail, | ||
1940 | ch); | ||
1941 | GNUNET_free (rnd_label); | ||
1942 | GNUNET_SERVICE_client_continue (idp->client); | ||
1943 | } | ||
1944 | |||
1945 | /** | ||
1946 | * Cleanup attribute store handle | ||
1947 | * | ||
1948 | * @param handle handle to clean up | ||
1949 | */ | ||
1950 | static void | ||
1951 | cleanup_as_handle (struct AttributeStoreHandle *handle) | ||
1952 | { | ||
1953 | if (NULL != handle->ns_qe) | ||
1954 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
1955 | if (NULL != handle->claim) | ||
1956 | GNUNET_free (handle->claim); | ||
1957 | if (NULL != handle->abe_key) | ||
1958 | GNUNET_ABE_cpabe_delete_master_key (handle->abe_key); | ||
1959 | GNUNET_free (handle); | ||
1960 | } | ||
1961 | |||
1962 | static void | ||
1963 | attr_store_cont (void *cls, | ||
1964 | int32_t success, | ||
1965 | const char *emsg) | ||
1966 | { | ||
1967 | struct AttributeStoreHandle *as_handle = cls; | ||
1968 | struct GNUNET_MQ_Envelope *env; | ||
1969 | struct AttributeStoreResultMessage *acr_msg; | ||
1970 | |||
1971 | as_handle->ns_qe = NULL; | ||
1972 | GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, | ||
1973 | as_handle->client->store_op_tail, | ||
1974 | as_handle); | ||
1975 | |||
1976 | if (GNUNET_SYSERR == success) | ||
1977 | { | ||
1978 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1979 | "Failed to store attribute %s\n", | ||
1980 | emsg); | ||
1981 | cleanup_as_handle (as_handle); | ||
1982 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
1983 | return; | ||
1984 | } | ||
1985 | |||
1986 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1987 | "Sending ATTRIBUTE_STORE_RESPONSE message\n"); | ||
1988 | env = GNUNET_MQ_msg (acr_msg, | ||
1989 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE); | ||
1990 | acr_msg->id = htonl (as_handle->r_id); | ||
1991 | acr_msg->op_result = htonl (GNUNET_OK); | ||
1992 | GNUNET_MQ_send (as_handle->client->mq, | ||
1993 | env); | ||
1994 | cleanup_as_handle (as_handle); | ||
1995 | } | ||
1996 | |||
1997 | static void | ||
1998 | attr_store_task (void *cls) | ||
1999 | { | ||
2000 | struct AttributeStoreHandle *as_handle = cls; | ||
2001 | struct GNUNET_GNSRECORD_Data rd[1]; | ||
2002 | char* buf; | ||
2003 | char* policy; | ||
2004 | char* enc_buf; | ||
2005 | char* rd_buf; | ||
2006 | size_t enc_size; | ||
2007 | size_t buf_size; | ||
2008 | uint32_t attr_ver; | ||
2009 | |||
2010 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2011 | "Storing attribute\n"); | ||
2012 | buf_size = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (as_handle->claim); | ||
2013 | buf = GNUNET_malloc (buf_size); | ||
2014 | |||
2015 | GNUNET_IDENTITY_ATTRIBUTE_serialize (as_handle->claim, | ||
2016 | buf); | ||
2017 | |||
2018 | GNUNET_asprintf (&policy, | ||
2019 | "%s_%lu", | ||
2020 | as_handle->claim->name, | ||
2021 | as_handle->claim->version); | ||
2022 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2023 | "Encrypting with policy %s\n", policy); | ||
2024 | /** | ||
2025 | * Encrypt the attribute value and store in namestore | ||
2026 | */ | ||
2027 | enc_size = GNUNET_ABE_cpabe_encrypt (buf, | ||
2028 | buf_size, | ||
2029 | policy, //Policy | ||
2030 | as_handle->abe_key, | ||
2031 | (void**)&enc_buf); | ||
2032 | if (GNUNET_SYSERR == enc_size) | ||
2033 | { | ||
2034 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2035 | "Failed to encrypt with policy %s\n", | ||
2036 | policy); | ||
2037 | GNUNET_CONTAINER_DLL_remove (as_handle->client->store_op_head, | ||
2038 | as_handle->client->store_op_tail, | ||
2039 | as_handle); | ||
2040 | |||
2041 | cleanup_as_handle (as_handle); | ||
2042 | GNUNET_free (buf); | ||
2043 | GNUNET_free (policy); | ||
2044 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
2045 | return; | ||
2046 | } | ||
2047 | GNUNET_free (buf); | ||
2048 | GNUNET_free (policy); | ||
2049 | rd[0].data_size = enc_size + sizeof (uint32_t); | ||
2050 | rd_buf = GNUNET_malloc (rd[0].data_size); | ||
2051 | attr_ver = htonl (as_handle->claim->version); | ||
2052 | GNUNET_memcpy (rd_buf, | ||
2053 | &attr_ver, | ||
2054 | sizeof (uint32_t)); | ||
2055 | GNUNET_memcpy (rd_buf+sizeof (uint32_t), | ||
2056 | enc_buf, | ||
2057 | enc_size); | ||
2058 | rd[0].data = rd_buf; | ||
2059 | rd[0].record_type = GNUNET_GNSRECORD_TYPE_ID_ATTR; | ||
2060 | rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
2061 | rd[0].expiration_time = as_handle->exp.rel_value_us; | ||
2062 | as_handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle, | ||
2063 | &as_handle->identity, | ||
2064 | as_handle->claim->name, | ||
2065 | 1, | ||
2066 | rd, | ||
2067 | &attr_store_cont, | ||
2068 | as_handle); | ||
2069 | GNUNET_free (enc_buf); | ||
2070 | GNUNET_free (rd_buf); | ||
2071 | } | ||
2072 | |||
2073 | |||
2074 | static void | ||
2075 | store_after_abe_bootstrap (void *cls, | ||
2076 | struct GNUNET_ABE_AbeMasterKey *abe_key) | ||
2077 | { | ||
2078 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2079 | "Finished ABE bootstrap\n"); | ||
2080 | struct AttributeStoreHandle *ash = cls; | ||
2081 | ash->abe_key = abe_key; | ||
2082 | GNUNET_SCHEDULER_add_now (&attr_store_task, ash); | ||
2083 | } | ||
2084 | |||
2085 | static int | ||
2086 | check_attribute_store_message(void *cls, | ||
2087 | const struct AttributeStoreMessage *sam) | ||
2088 | { | ||
2089 | uint16_t size; | ||
2090 | |||
2091 | size = ntohs (sam->header.size); | ||
2092 | if (size <= sizeof (struct AttributeStoreMessage)) | ||
2093 | { | ||
2094 | GNUNET_break (0); | ||
2095 | return GNUNET_SYSERR; | ||
2096 | } | ||
2097 | return GNUNET_OK; | ||
2098 | } | ||
2099 | |||
2100 | |||
2101 | static void | ||
2102 | handle_attribute_store_message (void *cls, | ||
2103 | const struct AttributeStoreMessage *sam) | ||
2104 | { | ||
2105 | struct AttributeStoreHandle *as_handle; | ||
2106 | struct IdpClient *idp = cls; | ||
2107 | size_t data_len; | ||
2108 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2109 | "Received ATTRIBUTE_STORE message\n"); | ||
2110 | |||
2111 | data_len = ntohs (sam->attr_len); | ||
2112 | |||
2113 | as_handle = GNUNET_new (struct AttributeStoreHandle); | ||
2114 | as_handle->claim = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&sam[1], | ||
2115 | data_len); | ||
2116 | |||
2117 | as_handle->r_id = ntohl (sam->id); | ||
2118 | as_handle->identity = sam->identity; | ||
2119 | as_handle->exp.rel_value_us = GNUNET_ntohll (sam->exp); | ||
2120 | GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, | ||
2121 | &as_handle->identity_pkey); | ||
2122 | |||
2123 | GNUNET_SERVICE_client_continue (idp->client); | ||
2124 | as_handle->client = idp; | ||
2125 | GNUNET_CONTAINER_DLL_insert (idp->store_op_head, | ||
2126 | idp->store_op_tail, | ||
2127 | as_handle); | ||
2128 | bootstrap_abe (&as_handle->identity, &store_after_abe_bootstrap, as_handle, GNUNET_NO); | ||
2129 | } | ||
2130 | |||
2131 | static void | ||
2132 | cleanup_attribute_iter_handle (struct AttributeIterator *ai) | ||
2133 | { | ||
2134 | if (NULL != ai->abe_key) | ||
2135 | GNUNET_ABE_cpabe_delete_master_key (ai->abe_key); | ||
2136 | GNUNET_free (ai); | ||
2137 | } | ||
2138 | |||
2139 | static void | ||
2140 | attr_iter_error (void *cls) | ||
2141 | { | ||
2142 | struct AttributeIterator *ai = cls; | ||
2143 | //TODO | ||
2144 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2145 | "Failed to iterate over attributes\n"); | ||
2146 | GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head, | ||
2147 | ai->client->attr_iter_tail, | ||
2148 | ai); | ||
2149 | cleanup_attribute_iter_handle (ai); | ||
2150 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | ||
2151 | } | ||
2152 | |||
2153 | static void | ||
2154 | attr_iter_finished (void *cls) | ||
2155 | { | ||
2156 | struct AttributeIterator *ai = cls; | ||
2157 | struct GNUNET_MQ_Envelope *env; | ||
2158 | struct AttributeResultMessage *arm; | ||
2159 | |||
2160 | env = GNUNET_MQ_msg (arm, | ||
2161 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT); | ||
2162 | arm->id = htonl (ai->request_id); | ||
2163 | arm->attr_len = htons (0); | ||
2164 | GNUNET_MQ_send (ai->client->mq, env); | ||
2165 | GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head, | ||
2166 | ai->client->attr_iter_tail, | ||
2167 | ai); | ||
2168 | cleanup_attribute_iter_handle (ai); | ||
2169 | } | ||
2170 | |||
2171 | static void | ||
2172 | attr_iter_cb (void *cls, | ||
2173 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
2174 | const char *label, | ||
2175 | unsigned int rd_count, | ||
2176 | const struct GNUNET_GNSRECORD_Data *rd) | ||
2177 | { | ||
2178 | struct AttributeIterator *ai = cls; | ||
2179 | struct AttributeResultMessage *arm; | ||
2180 | struct GNUNET_ABE_AbeKey *key; | ||
2181 | struct GNUNET_MQ_Envelope *env; | ||
2182 | ssize_t msg_extra_len; | ||
2183 | char* attr_ser; | ||
2184 | char* attrs[2]; | ||
2185 | char* data_tmp; | ||
2186 | char* policy; | ||
2187 | uint32_t attr_ver; | ||
2188 | |||
2189 | if (rd_count != 1) | ||
2190 | { | ||
2191 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, | ||
2192 | 1); | ||
2193 | return; | ||
2194 | } | ||
2195 | |||
2196 | if (GNUNET_GNSRECORD_TYPE_ID_ATTR != rd->record_type) | ||
2197 | { | ||
2198 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, | ||
2199 | 1); | ||
2200 | return; | ||
2201 | } | ||
2202 | attr_ver = ntohl(*((uint32_t*)rd->data)); | ||
2203 | GNUNET_asprintf (&policy, "%s_%lu", | ||
2204 | label, attr_ver); | ||
2205 | attrs[0] = policy; | ||
2206 | attrs[1] = 0; | ||
2207 | key = GNUNET_ABE_cpabe_create_key (ai->abe_key, | ||
2208 | attrs); | ||
2209 | msg_extra_len = GNUNET_ABE_cpabe_decrypt (rd->data+sizeof (uint32_t), | ||
2210 | rd->data_size-sizeof (uint32_t), | ||
2211 | key, | ||
2212 | (void**)&attr_ser); | ||
2213 | if (GNUNET_SYSERR == msg_extra_len) | ||
2214 | { | ||
2215 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, | ||
2216 | 1); | ||
2217 | return; | ||
2218 | } | ||
2219 | |||
2220 | GNUNET_ABE_cpabe_delete_key (key, | ||
2221 | GNUNET_YES); | ||
2222 | //GNUNET_free (policy); | ||
2223 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2224 | "Found attribute: %s\n", label); | ||
2225 | env = GNUNET_MQ_msg_extra (arm, | ||
2226 | msg_extra_len, | ||
2227 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT); | ||
2228 | arm->id = htonl (ai->request_id); | ||
2229 | arm->attr_len = htons (msg_extra_len); | ||
2230 | GNUNET_CRYPTO_ecdsa_key_get_public (zone, | ||
2231 | &arm->identity); | ||
2232 | data_tmp = (char *) &arm[1]; | ||
2233 | GNUNET_memcpy (data_tmp, | ||
2234 | attr_ser, | ||
2235 | msg_extra_len); | ||
2236 | GNUNET_MQ_send (ai->client->mq, env); | ||
2237 | GNUNET_free (attr_ser); | ||
2238 | GNUNET_ABE_cpabe_delete_master_key (ai->abe_key); | ||
2239 | ai->abe_key = NULL; | ||
2240 | } | ||
2241 | |||
2242 | |||
2243 | void | ||
2244 | iterate_after_abe_bootstrap (void *cls, | ||
2245 | struct GNUNET_ABE_AbeMasterKey *abe_key) | ||
2246 | { | ||
2247 | struct AttributeIterator *ai = cls; | ||
2248 | ai->abe_key = abe_key; | ||
2249 | ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (ns_handle, | ||
2250 | &ai->identity, | ||
2251 | &attr_iter_error, | ||
2252 | ai, | ||
2253 | &attr_iter_cb, | ||
2254 | ai, | ||
2255 | &attr_iter_finished, | ||
2256 | ai); | ||
2257 | } | ||
2258 | |||
2259 | |||
2260 | static void | ||
2261 | iterate_next_after_abe_bootstrap (void *cls, | ||
2262 | struct GNUNET_ABE_AbeMasterKey *abe_key) | ||
2263 | { | ||
2264 | struct AttributeIterator *ai = cls; | ||
2265 | ai->abe_key = abe_key; | ||
2266 | GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, | ||
2267 | 1); | ||
2268 | } | ||
2269 | |||
2270 | |||
2271 | |||
2272 | static void | ||
2273 | handle_iteration_start (void *cls, | ||
2274 | const struct AttributeIterationStartMessage *ais_msg) | ||
2275 | { | ||
2276 | struct IdpClient *idp = cls; | ||
2277 | struct AttributeIterator *ai; | ||
2278 | |||
2279 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2280 | "Received ATTRIBUTE_ITERATION_START message\n"); | ||
2281 | ai = GNUNET_new (struct AttributeIterator); | ||
2282 | ai->request_id = ntohl (ais_msg->id); | ||
2283 | ai->client = idp; | ||
2284 | ai->identity = ais_msg->identity; | ||
2285 | |||
2286 | GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, | ||
2287 | idp->attr_iter_tail, | ||
2288 | ai); | ||
2289 | bootstrap_abe (&ai->identity, &iterate_after_abe_bootstrap, ai, GNUNET_NO); | ||
2290 | GNUNET_SERVICE_client_continue (idp->client); | ||
2291 | } | ||
2292 | |||
2293 | |||
2294 | static void | ||
2295 | handle_iteration_stop (void *cls, | ||
2296 | const struct AttributeIterationStopMessage *ais_msg) | ||
2297 | { | ||
2298 | struct IdpClient *idp = cls; | ||
2299 | struct AttributeIterator *ai; | ||
2300 | uint32_t rid; | ||
2301 | |||
2302 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2303 | "Received `%s' message\n", | ||
2304 | "ATTRIBUTE_ITERATION_STOP"); | ||
2305 | rid = ntohl (ais_msg->id); | ||
2306 | for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next) | ||
2307 | if (ai->request_id == rid) | ||
2308 | break; | ||
2309 | if (NULL == ai) | ||
2310 | { | ||
2311 | GNUNET_break (0); | ||
2312 | GNUNET_SERVICE_client_drop (idp->client); | ||
2313 | return; | ||
2314 | } | ||
2315 | GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, | ||
2316 | idp->attr_iter_tail, | ||
2317 | ai); | ||
2318 | GNUNET_free (ai); | ||
2319 | GNUNET_SERVICE_client_continue (idp->client); | ||
2320 | } | ||
2321 | |||
2322 | |||
2323 | static void | ||
2324 | handle_iteration_next (void *cls, | ||
2325 | const struct AttributeIterationNextMessage *ais_msg) | ||
2326 | { | ||
2327 | struct IdpClient *idp = cls; | ||
2328 | struct AttributeIterator *ai; | ||
2329 | uint32_t rid; | ||
2330 | |||
2331 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2332 | "Received ATTRIBUTE_ITERATION_NEXT message\n"); | ||
2333 | rid = ntohl (ais_msg->id); | ||
2334 | for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next) | ||
2335 | if (ai->request_id == rid) | ||
2336 | break; | ||
2337 | if (NULL == ai) | ||
2338 | { | ||
2339 | GNUNET_break (0); | ||
2340 | GNUNET_SERVICE_client_drop (idp->client); | ||
2341 | return; | ||
2342 | } | ||
2343 | bootstrap_abe (&ai->identity, | ||
2344 | &iterate_next_after_abe_bootstrap, | ||
2345 | ai, | ||
2346 | GNUNET_NO); | ||
2347 | GNUNET_SERVICE_client_continue (idp->client); | ||
2348 | } | ||
2349 | |||
2350 | /** | ||
2351 | * Ticket iteration processor result | ||
2352 | */ | ||
2353 | enum ZoneIterationResult | ||
2354 | { | ||
2355 | /** | ||
2356 | * Iteration start. | ||
2357 | */ | ||
2358 | IT_START = 0, | ||
2359 | |||
2360 | /** | ||
2361 | * Found tickets, | ||
2362 | * Continue to iterate with next iteration_next call | ||
2363 | */ | ||
2364 | IT_SUCCESS_MORE_AVAILABLE = 1, | ||
2365 | |||
2366 | /** | ||
2367 | * Iteration complete | ||
2368 | */ | ||
2369 | IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2 | ||
2370 | }; | ||
2371 | |||
2372 | |||
2373 | /** | ||
2374 | * Context for ticket iteration | ||
2375 | */ | ||
2376 | struct TicketIterationProcResult | ||
2377 | { | ||
2378 | /** | ||
2379 | * The ticket iteration handle | ||
2380 | */ | ||
2381 | struct TicketIteration *ti; | ||
2382 | |||
2383 | /** | ||
2384 | * Iteration result: iteration done? | ||
2385 | * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but | ||
2386 | * we got one for now and have sent it to the client | ||
2387 | * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results, | ||
2388 | * #IT_START: if we are still trying to find a result. | ||
2389 | */ | ||
2390 | int res_iteration_finished; | ||
2391 | |||
2392 | }; | ||
2393 | |||
2394 | static void | ||
2395 | cleanup_ticket_iter_handle (struct TicketIteration *ti) | ||
2396 | { | ||
2397 | GNUNET_free (ti); | ||
2398 | } | ||
2399 | |||
2400 | /** | ||
2401 | * Process ticket from database | ||
2402 | * | ||
2403 | * @param cls struct TicketIterationProcResult | ||
2404 | * @param ticket the ticket | ||
2405 | * @param attrs the attributes | ||
2406 | */ | ||
2407 | static void | ||
2408 | ticket_iterate_proc (void *cls, | ||
2409 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
2410 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
2411 | { | ||
2412 | struct TicketIterationProcResult *proc = cls; | ||
2413 | |||
2414 | if (NULL == ticket) | ||
2415 | { | ||
2416 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2417 | "Iteration done\n"); | ||
2418 | proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; | ||
2419 | return; | ||
2420 | } | ||
2421 | proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE; | ||
2422 | send_ticket_result (proc->ti->client, | ||
2423 | proc->ti->r_id, | ||
2424 | ticket, | ||
2425 | attrs); | ||
2426 | |||
2427 | } | ||
2428 | |||
2429 | /** | ||
2430 | * Perform ticket iteration step | ||
2431 | * | ||
2432 | * @param ti ticket iterator to process | ||
2433 | */ | ||
2434 | static void | ||
2435 | run_ticket_iteration_round (struct TicketIteration *ti) | ||
2436 | { | ||
2437 | struct TicketIterationProcResult proc; | ||
2438 | struct GNUNET_MQ_Envelope *env; | ||
2439 | struct TicketResultMessage *trm; | ||
2440 | int ret; | ||
2441 | |||
2442 | memset (&proc, 0, sizeof (proc)); | ||
2443 | proc.ti = ti; | ||
2444 | proc.res_iteration_finished = IT_START; | ||
2445 | while (IT_START == proc.res_iteration_finished) | ||
2446 | { | ||
2447 | if (GNUNET_SYSERR == | ||
2448 | (ret = TKT_database->iterate_tickets (TKT_database->cls, | ||
2449 | &ti->identity, | ||
2450 | ti->is_audience, | ||
2451 | ti->offset, | ||
2452 | &ticket_iterate_proc, | ||
2453 | &proc))) | ||
2454 | { | ||
2455 | GNUNET_break (0); | ||
2456 | break; | ||
2457 | } | ||
2458 | if (GNUNET_NO == ret) | ||
2459 | proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; | ||
2460 | ti->offset++; | ||
2461 | } | ||
2462 | if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished) | ||
2463 | { | ||
2464 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2465 | "More results available\n"); | ||
2466 | return; /* more later */ | ||
2467 | } | ||
2468 | /* send empty response to indicate end of list */ | ||
2469 | env = GNUNET_MQ_msg (trm, | ||
2470 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT); | ||
2471 | trm->id = htonl (ti->r_id); | ||
2472 | GNUNET_MQ_send (ti->client->mq, | ||
2473 | env); | ||
2474 | GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head, | ||
2475 | ti->client->ticket_iter_tail, | ||
2476 | ti); | ||
2477 | cleanup_ticket_iter_handle (ti); | ||
2478 | } | ||
2479 | |||
2480 | static void | ||
2481 | handle_ticket_iteration_start (void *cls, | ||
2482 | const struct TicketIterationStartMessage *tis_msg) | ||
2483 | { | ||
2484 | struct IdpClient *client = cls; | ||
2485 | struct TicketIteration *ti; | ||
2486 | |||
2487 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2488 | "Received TICKET_ITERATION_START message\n"); | ||
2489 | ti = GNUNET_new (struct TicketIteration); | ||
2490 | ti->r_id = ntohl (tis_msg->id); | ||
2491 | ti->offset = 0; | ||
2492 | ti->client = client; | ||
2493 | ti->identity = tis_msg->identity; | ||
2494 | ti->is_audience = ntohl (tis_msg->is_audience); | ||
2495 | |||
2496 | GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head, | ||
2497 | client->ticket_iter_tail, | ||
2498 | ti); | ||
2499 | run_ticket_iteration_round (ti); | ||
2500 | GNUNET_SERVICE_client_continue (client->client); | ||
2501 | } | ||
2502 | |||
2503 | |||
2504 | static void | ||
2505 | handle_ticket_iteration_stop (void *cls, | ||
2506 | const struct TicketIterationStopMessage *tis_msg) | ||
2507 | { | ||
2508 | struct IdpClient *client = cls; | ||
2509 | struct TicketIteration *ti; | ||
2510 | uint32_t rid; | ||
2511 | |||
2512 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2513 | "Received `%s' message\n", | ||
2514 | "TICKET_ITERATION_STOP"); | ||
2515 | rid = ntohl (tis_msg->id); | ||
2516 | for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next) | ||
2517 | if (ti->r_id == rid) | ||
2518 | break; | ||
2519 | if (NULL == ti) | ||
2520 | { | ||
2521 | GNUNET_break (0); | ||
2522 | GNUNET_SERVICE_client_drop (client->client); | ||
2523 | return; | ||
2524 | } | ||
2525 | GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head, | ||
2526 | client->ticket_iter_tail, | ||
2527 | ti); | ||
2528 | cleanup_ticket_iter_handle (ti); | ||
2529 | GNUNET_SERVICE_client_continue (client->client); | ||
2530 | } | ||
2531 | |||
2532 | |||
2533 | static void | ||
2534 | handle_ticket_iteration_next (void *cls, | ||
2535 | const struct TicketIterationNextMessage *tis_msg) | ||
2536 | { | ||
2537 | struct IdpClient *client = cls; | ||
2538 | struct TicketIteration *ti; | ||
2539 | uint32_t rid; | ||
2540 | |||
2541 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2542 | "Received TICKET_ITERATION_NEXT message\n"); | ||
2543 | rid = ntohl (tis_msg->id); | ||
2544 | for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next) | ||
2545 | if (ti->r_id == rid) | ||
2546 | break; | ||
2547 | if (NULL == ti) | ||
2548 | { | ||
2549 | GNUNET_break (0); | ||
2550 | GNUNET_SERVICE_client_drop (client->client); | ||
2551 | return; | ||
2552 | } | ||
2553 | run_ticket_iteration_round (ti); | ||
2554 | GNUNET_SERVICE_client_continue (client->client); | ||
2555 | } | ||
2556 | |||
2557 | |||
2558 | |||
2559 | |||
2560 | /** | ||
2561 | * Main function that will be run | ||
2562 | * | ||
2563 | * @param cls closure | ||
2564 | * @param c the configuration used | ||
2565 | * @param server the service handle | ||
2566 | */ | ||
2567 | static void | ||
2568 | run (void *cls, | ||
2569 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
2570 | struct GNUNET_SERVICE_Handle *server) | ||
2571 | { | ||
2572 | char *database; | ||
2573 | cfg = c; | ||
2574 | |||
2575 | stats = GNUNET_STATISTICS_create ("identity-provider", cfg); | ||
2576 | |||
2577 | //Connect to identity and namestore services | ||
2578 | ns_handle = GNUNET_NAMESTORE_connect (cfg); | ||
2579 | if (NULL == ns_handle) | ||
2580 | { | ||
2581 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to namestore"); | ||
2582 | } | ||
2583 | |||
2584 | gns_handle = GNUNET_GNS_connect (cfg); | ||
2585 | if (NULL == gns_handle) | ||
2586 | { | ||
2587 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); | ||
2588 | } | ||
2589 | credential_handle = GNUNET_CREDENTIAL_connect (cfg); | ||
2590 | if (NULL == credential_handle) | ||
2591 | { | ||
2592 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to credential"); | ||
2593 | } | ||
2594 | identity_handle = GNUNET_IDENTITY_connect (cfg, | ||
2595 | NULL, | ||
2596 | NULL); | ||
2597 | /* Loading DB plugin */ | ||
2598 | if (GNUNET_OK != | ||
2599 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
2600 | "identity-provider", | ||
2601 | "database", | ||
2602 | &database)) | ||
2603 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2604 | "No database backend configured\n"); | ||
2605 | GNUNET_asprintf (&db_lib_name, | ||
2606 | "libgnunet_plugin_identity_provider_%s", | ||
2607 | database); | ||
2608 | TKT_database = GNUNET_PLUGIN_load (db_lib_name, | ||
2609 | (void *) cfg); | ||
2610 | GNUNET_free (database); | ||
2611 | if (NULL == TKT_database) | ||
2612 | { | ||
2613 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2614 | "Could not load database backend `%s'\n", | ||
2615 | db_lib_name); | ||
2616 | GNUNET_SCHEDULER_shutdown (); | ||
2617 | return; | ||
2618 | } | ||
2619 | |||
2620 | if (GNUNET_OK == | ||
2621 | GNUNET_CONFIGURATION_get_value_time (cfg, | ||
2622 | "identity-provider", | ||
2623 | "TOKEN_EXPIRATION_INTERVAL", | ||
2624 | &token_expiration_interval)) | ||
2625 | { | ||
2626 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2627 | "Time window for zone iteration: %s\n", | ||
2628 | GNUNET_STRINGS_relative_time_to_string (token_expiration_interval, | ||
2629 | GNUNET_YES)); | ||
2630 | } else { | ||
2631 | token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL; | ||
2632 | } | ||
2633 | |||
2634 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
2635 | } | ||
2636 | |||
2637 | /** | ||
2638 | * Called whenever a client is disconnected. | ||
2639 | * | ||
2640 | * @param cls closure | ||
2641 | * @param client identification of the client | ||
2642 | * @param app_ctx @a client | ||
2643 | */ | ||
2644 | static void | ||
2645 | client_disconnect_cb (void *cls, | ||
2646 | struct GNUNET_SERVICE_Client *client, | ||
2647 | void *app_ctx) | ||
2648 | { | ||
2649 | struct IdpClient *idp = app_ctx; | ||
2650 | struct AttributeIterator *ai; | ||
2651 | struct TicketIteration *ti; | ||
2652 | struct TicketRevocationHandle *rh; | ||
2653 | struct TicketIssueHandle *iss; | ||
2654 | struct ConsumeTicketHandle *ct; | ||
2655 | struct AttributeStoreHandle *as; | ||
2656 | |||
2657 | //TODO other operations | ||
2658 | |||
2659 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2660 | "Client %p disconnected\n", | ||
2661 | client); | ||
2662 | |||
2663 | while (NULL != (iss = idp->issue_op_head)) | ||
2664 | { | ||
2665 | GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, | ||
2666 | idp->issue_op_tail, | ||
2667 | iss); | ||
2668 | cleanup_ticket_issue_handle (iss); | ||
2669 | } | ||
2670 | while (NULL != (ct = idp->consume_op_head)) | ||
2671 | { | ||
2672 | GNUNET_CONTAINER_DLL_remove (idp->consume_op_head, | ||
2673 | idp->consume_op_tail, | ||
2674 | ct); | ||
2675 | cleanup_consume_ticket_handle (ct); | ||
2676 | } | ||
2677 | while (NULL != (as = idp->store_op_head)) | ||
2678 | { | ||
2679 | GNUNET_CONTAINER_DLL_remove (idp->store_op_head, | ||
2680 | idp->store_op_tail, | ||
2681 | as); | ||
2682 | cleanup_as_handle (as); | ||
2683 | } | ||
2684 | |||
2685 | while (NULL != (ai = idp->attr_iter_head)) | ||
2686 | { | ||
2687 | GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, | ||
2688 | idp->attr_iter_tail, | ||
2689 | ai); | ||
2690 | cleanup_attribute_iter_handle (ai); | ||
2691 | } | ||
2692 | while (NULL != (rh = idp->revoke_op_head)) | ||
2693 | { | ||
2694 | GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, | ||
2695 | idp->revoke_op_tail, | ||
2696 | rh); | ||
2697 | cleanup_revoke_ticket_handle (rh); | ||
2698 | } | ||
2699 | while (NULL != (ti = idp->ticket_iter_head)) | ||
2700 | { | ||
2701 | GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head, | ||
2702 | idp->ticket_iter_tail, | ||
2703 | ti); | ||
2704 | cleanup_ticket_iter_handle (ti); | ||
2705 | } | ||
2706 | GNUNET_free (idp); | ||
2707 | } | ||
2708 | |||
2709 | |||
2710 | /** | ||
2711 | * Add a client to our list of active clients. | ||
2712 | * | ||
2713 | * @param cls NULL | ||
2714 | * @param client client to add | ||
2715 | * @param mq message queue for @a client | ||
2716 | * @return internal namestore client structure for this client | ||
2717 | */ | ||
2718 | static void * | ||
2719 | client_connect_cb (void *cls, | ||
2720 | struct GNUNET_SERVICE_Client *client, | ||
2721 | struct GNUNET_MQ_Handle *mq) | ||
2722 | { | ||
2723 | struct IdpClient *idp; | ||
2724 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2725 | "Client %p connected\n", | ||
2726 | client); | ||
2727 | idp = GNUNET_new (struct IdpClient); | ||
2728 | idp->client = client; | ||
2729 | idp->mq = mq; | ||
2730 | return idp; | ||
2731 | } | ||
2732 | |||
2733 | |||
2734 | |||
2735 | /** | ||
2736 | * Define "main" method using service macro. | ||
2737 | */ | ||
2738 | GNUNET_SERVICE_MAIN | ||
2739 | ("identity-provider", | ||
2740 | GNUNET_SERVICE_OPTION_NONE, | ||
2741 | &run, | ||
2742 | &client_connect_cb, | ||
2743 | &client_disconnect_cb, | ||
2744 | NULL, | ||
2745 | GNUNET_MQ_hd_var_size (attribute_store_message, | ||
2746 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE, | ||
2747 | struct AttributeStoreMessage, | ||
2748 | NULL), | ||
2749 | GNUNET_MQ_hd_fixed_size (iteration_start, | ||
2750 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START, | ||
2751 | struct AttributeIterationStartMessage, | ||
2752 | NULL), | ||
2753 | GNUNET_MQ_hd_fixed_size (iteration_next, | ||
2754 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT, | ||
2755 | struct AttributeIterationNextMessage, | ||
2756 | NULL), | ||
2757 | GNUNET_MQ_hd_fixed_size (iteration_stop, | ||
2758 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP, | ||
2759 | struct AttributeIterationStopMessage, | ||
2760 | NULL), | ||
2761 | GNUNET_MQ_hd_var_size (issue_ticket_message, | ||
2762 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET, | ||
2763 | struct IssueTicketMessage, | ||
2764 | NULL), | ||
2765 | GNUNET_MQ_hd_var_size (consume_ticket_message, | ||
2766 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET, | ||
2767 | struct ConsumeTicketMessage, | ||
2768 | NULL), | ||
2769 | GNUNET_MQ_hd_fixed_size (ticket_iteration_start, | ||
2770 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START, | ||
2771 | struct TicketIterationStartMessage, | ||
2772 | NULL), | ||
2773 | GNUNET_MQ_hd_fixed_size (ticket_iteration_next, | ||
2774 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT, | ||
2775 | struct TicketIterationNextMessage, | ||
2776 | NULL), | ||
2777 | GNUNET_MQ_hd_fixed_size (ticket_iteration_stop, | ||
2778 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP, | ||
2779 | struct TicketIterationStopMessage, | ||
2780 | NULL), | ||
2781 | GNUNET_MQ_hd_var_size (revoke_ticket_message, | ||
2782 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET, | ||
2783 | struct RevokeTicketMessage, | ||
2784 | NULL), | ||
2785 | GNUNET_MQ_handler_end()); | ||
2786 | /* end of gnunet-service-identity-provider.c */ | ||
diff --git a/src/identity-provider/identity-provider.conf b/src/identity-provider/identity-provider.conf deleted file mode 100644 index cc50152a1..000000000 --- a/src/identity-provider/identity-provider.conf +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | [identity-provider] | ||
2 | START_ON_DEMAND = NO | ||
3 | RUN_PER_USER = YES | ||
4 | #PORT = 2108 | ||
5 | HOSTNAME = localhost | ||
6 | BINARY = gnunet-service-identity-provider | ||
7 | ACCEPT_FROM = 127.0.0.1; | ||
8 | ACCEPT_FROM6 = ::1; | ||
9 | UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity-provider.sock | ||
10 | UNIX_MATCH_UID = NO | ||
11 | UNIX_MATCH_GID = YES | ||
12 | TOKEN_EXPIRATION_INTERVAL = 30 m | ||
13 | DATABASE = sqlite | ||
14 | |||
15 | [identity-rest-plugin] | ||
16 | #ADDRESS = https://identity.gnu:8000#/login | ||
17 | ADDRESS = https://reclaim.ui/#/login | ||
18 | PSW = secret | ||
19 | EXPIRATION_TIME = 3600 | ||
20 | |||
21 | [identity-provider-sqlite] | ||
22 | FILENAME = $GNUNET_DATA_HOME/identity-provider/sqlite.db | ||
diff --git a/src/identity-provider/identity-token.conf b/src/identity-provider/identity-token.conf deleted file mode 100644 index f29f6cdf3..000000000 --- a/src/identity-provider/identity-token.conf +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | [identity-token] | ||
2 | BINARY=gnunet-service-identity-token | ||
diff --git a/src/identity-provider/identity_provider.h b/src/identity-provider/identity_provider.h deleted file mode 100644 index 6a4b7769f..000000000 --- a/src/identity-provider/identity_provider.h +++ /dev/null | |||
@@ -1,410 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @author Martin Schanzenbach | ||
21 | * @file identity-provider/identity_provider.h | ||
22 | * | ||
23 | * @brief Common type definitions for the identity provider | ||
24 | * service and API. | ||
25 | */ | ||
26 | #ifndef IDENTITY_PROVIDER_H | ||
27 | #define IDENTITY_PROVIDER_H | ||
28 | |||
29 | #include "gnunet_common.h" | ||
30 | |||
31 | |||
32 | GNUNET_NETWORK_STRUCT_BEGIN | ||
33 | |||
34 | /** | ||
35 | * Use to store an identity attribute | ||
36 | */ | ||
37 | struct AttributeStoreMessage | ||
38 | { | ||
39 | /** | ||
40 | * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT | ||
41 | */ | ||
42 | struct GNUNET_MessageHeader header; | ||
43 | |||
44 | /** | ||
45 | * Unique identifier for this request (for key collisions). | ||
46 | */ | ||
47 | uint32_t id GNUNET_PACKED; | ||
48 | |||
49 | /** | ||
50 | * The length of the attribute | ||
51 | */ | ||
52 | uint32_t attr_len GNUNET_PACKED; | ||
53 | |||
54 | /** | ||
55 | * The expiration interval of the attribute | ||
56 | */ | ||
57 | uint64_t exp GNUNET_PACKED; | ||
58 | |||
59 | /** | ||
60 | * Identity | ||
61 | */ | ||
62 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
63 | |||
64 | /* followed by the serialized attribute */ | ||
65 | |||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * Attribute store response message | ||
70 | */ | ||
71 | struct AttributeStoreResultMessage | ||
72 | { | ||
73 | /** | ||
74 | * Message header | ||
75 | */ | ||
76 | struct GNUNET_MessageHeader header; | ||
77 | |||
78 | /** | ||
79 | * Unique identifier for this request (for key collisions). | ||
80 | */ | ||
81 | uint32_t id GNUNET_PACKED; | ||
82 | |||
83 | /** | ||
84 | * #GNUNET_SYSERR on failure, #GNUNET_OK on success | ||
85 | */ | ||
86 | int32_t op_result GNUNET_PACKED; | ||
87 | |||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * Attribute is returned from the idp. | ||
92 | */ | ||
93 | struct AttributeResultMessage | ||
94 | { | ||
95 | /** | ||
96 | * Message header | ||
97 | */ | ||
98 | struct GNUNET_MessageHeader header; | ||
99 | |||
100 | /** | ||
101 | * Unique identifier for this request (for key collisions). | ||
102 | */ | ||
103 | uint32_t id GNUNET_PACKED; | ||
104 | |||
105 | /** | ||
106 | * Length of serialized attribute data | ||
107 | */ | ||
108 | uint16_t attr_len GNUNET_PACKED; | ||
109 | |||
110 | /** | ||
111 | * always zero (for alignment) | ||
112 | */ | ||
113 | uint16_t reserved GNUNET_PACKED; | ||
114 | |||
115 | /** | ||
116 | * The public key of the identity. | ||
117 | */ | ||
118 | struct GNUNET_CRYPTO_EcdsaPublicKey identity; | ||
119 | |||
120 | /* followed by: | ||
121 | * serialized attribute data | ||
122 | */ | ||
123 | }; | ||
124 | |||
125 | |||
126 | /** | ||
127 | * Start a attribute iteration for the given identity | ||
128 | */ | ||
129 | struct AttributeIterationStartMessage | ||
130 | { | ||
131 | /** | ||
132 | * Message | ||
133 | */ | ||
134 | struct GNUNET_MessageHeader header; | ||
135 | |||
136 | /** | ||
137 | * Unique identifier for this request (for key collisions). | ||
138 | */ | ||
139 | uint32_t id GNUNET_PACKED; | ||
140 | |||
141 | /** | ||
142 | * Identity. | ||
143 | */ | ||
144 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
145 | |||
146 | }; | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Ask for next result of attribute iteration for the given operation | ||
151 | */ | ||
152 | struct AttributeIterationNextMessage | ||
153 | { | ||
154 | /** | ||
155 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT | ||
156 | */ | ||
157 | struct GNUNET_MessageHeader header; | ||
158 | |||
159 | /** | ||
160 | * Unique identifier for this request (for key collisions). | ||
161 | */ | ||
162 | uint32_t id GNUNET_PACKED; | ||
163 | |||
164 | }; | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Stop attribute iteration for the given operation | ||
169 | */ | ||
170 | struct AttributeIterationStopMessage | ||
171 | { | ||
172 | /** | ||
173 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP | ||
174 | */ | ||
175 | struct GNUNET_MessageHeader header; | ||
176 | |||
177 | /** | ||
178 | * Unique identifier for this request (for key collisions). | ||
179 | */ | ||
180 | uint32_t id GNUNET_PACKED; | ||
181 | |||
182 | }; | ||
183 | |||
184 | /** | ||
185 | * Start a ticket iteration for the given identity | ||
186 | */ | ||
187 | struct TicketIterationStartMessage | ||
188 | { | ||
189 | /** | ||
190 | * Message | ||
191 | */ | ||
192 | struct GNUNET_MessageHeader header; | ||
193 | |||
194 | /** | ||
195 | * Unique identifier for this request (for key collisions). | ||
196 | */ | ||
197 | uint32_t id GNUNET_PACKED; | ||
198 | |||
199 | /** | ||
200 | * Identity. | ||
201 | */ | ||
202 | struct GNUNET_CRYPTO_EcdsaPublicKey identity; | ||
203 | |||
204 | /** | ||
205 | * Identity is audience or issuer | ||
206 | */ | ||
207 | uint32_t is_audience GNUNET_PACKED; | ||
208 | }; | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Ask for next result of ticket iteration for the given operation | ||
213 | */ | ||
214 | struct TicketIterationNextMessage | ||
215 | { | ||
216 | /** | ||
217 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT | ||
218 | */ | ||
219 | struct GNUNET_MessageHeader header; | ||
220 | |||
221 | /** | ||
222 | * Unique identifier for this request (for key collisions). | ||
223 | */ | ||
224 | uint32_t id GNUNET_PACKED; | ||
225 | |||
226 | }; | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Stop ticket iteration for the given operation | ||
231 | */ | ||
232 | struct TicketIterationStopMessage | ||
233 | { | ||
234 | /** | ||
235 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP | ||
236 | */ | ||
237 | struct GNUNET_MessageHeader header; | ||
238 | |||
239 | /** | ||
240 | * Unique identifier for this request (for key collisions). | ||
241 | */ | ||
242 | uint32_t id GNUNET_PACKED; | ||
243 | |||
244 | }; | ||
245 | |||
246 | |||
247 | |||
248 | /** | ||
249 | * Ticket issue message | ||
250 | */ | ||
251 | struct IssueTicketMessage | ||
252 | { | ||
253 | /** | ||
254 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET | ||
255 | */ | ||
256 | struct GNUNET_MessageHeader header; | ||
257 | |||
258 | /** | ||
259 | * Unique identifier for this request (for key collisions). | ||
260 | */ | ||
261 | uint32_t id GNUNET_PACKED; | ||
262 | |||
263 | /** | ||
264 | * Identity. | ||
265 | */ | ||
266 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
267 | |||
268 | /** | ||
269 | * Requesting party. | ||
270 | */ | ||
271 | struct GNUNET_CRYPTO_EcdsaPublicKey rp; | ||
272 | |||
273 | /** | ||
274 | * length of serialized attribute list | ||
275 | */ | ||
276 | uint32_t attr_len GNUNET_PACKED; | ||
277 | |||
278 | //Followed by a serialized attribute list | ||
279 | }; | ||
280 | |||
281 | /** | ||
282 | * Ticket revoke message | ||
283 | */ | ||
284 | struct RevokeTicketMessage | ||
285 | { | ||
286 | /** | ||
287 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET | ||
288 | */ | ||
289 | struct GNUNET_MessageHeader header; | ||
290 | |||
291 | /** | ||
292 | * Unique identifier for this request (for key collisions). | ||
293 | */ | ||
294 | uint32_t id GNUNET_PACKED; | ||
295 | |||
296 | /** | ||
297 | * Identity. | ||
298 | */ | ||
299 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
300 | |||
301 | /** | ||
302 | * length of serialized attribute list | ||
303 | */ | ||
304 | uint32_t attrs_len GNUNET_PACKED; | ||
305 | |||
306 | //Followed by a ticket and serialized attribute list | ||
307 | }; | ||
308 | |||
309 | /** | ||
310 | * Ticket revoke message | ||
311 | */ | ||
312 | struct RevokeTicketResultMessage | ||
313 | { | ||
314 | /** | ||
315 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT | ||
316 | */ | ||
317 | struct GNUNET_MessageHeader header; | ||
318 | |||
319 | /** | ||
320 | * Unique identifier for this request (for key collisions). | ||
321 | */ | ||
322 | uint32_t id GNUNET_PACKED; | ||
323 | |||
324 | /** | ||
325 | * Revocation result | ||
326 | */ | ||
327 | uint32_t success GNUNET_PACKED; | ||
328 | }; | ||
329 | |||
330 | |||
331 | /** | ||
332 | * Ticket result message | ||
333 | */ | ||
334 | struct TicketResultMessage | ||
335 | { | ||
336 | /** | ||
337 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
338 | */ | ||
339 | struct GNUNET_MessageHeader header; | ||
340 | |||
341 | /** | ||
342 | * Unique identifier for this request (for key collisions). | ||
343 | */ | ||
344 | uint32_t id GNUNET_PACKED; | ||
345 | |||
346 | }; | ||
347 | |||
348 | /** | ||
349 | * Ticket consume message | ||
350 | */ | ||
351 | struct ConsumeTicketMessage | ||
352 | { | ||
353 | /** | ||
354 | * Type will be #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET | ||
355 | */ | ||
356 | struct GNUNET_MessageHeader header; | ||
357 | |||
358 | /** | ||
359 | * Unique identifier for this request (for key collisions). | ||
360 | */ | ||
361 | uint32_t id GNUNET_PACKED; | ||
362 | |||
363 | /** | ||
364 | * Identity. | ||
365 | */ | ||
366 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
367 | |||
368 | //Followed by a serialized ticket | ||
369 | }; | ||
370 | |||
371 | /** | ||
372 | * Attribute list is returned from the idp. | ||
373 | */ | ||
374 | struct ConsumeTicketResultMessage | ||
375 | { | ||
376 | /** | ||
377 | * Message header | ||
378 | */ | ||
379 | struct GNUNET_MessageHeader header; | ||
380 | |||
381 | /** | ||
382 | * Unique identifier for this request (for key collisions). | ||
383 | */ | ||
384 | uint32_t id GNUNET_PACKED; | ||
385 | |||
386 | /** | ||
387 | * Length of serialized attribute data | ||
388 | */ | ||
389 | uint16_t attrs_len GNUNET_PACKED; | ||
390 | |||
391 | /** | ||
392 | * always zero (for alignment) | ||
393 | */ | ||
394 | uint16_t reserved GNUNET_PACKED; | ||
395 | |||
396 | /** | ||
397 | * The public key of the identity. | ||
398 | */ | ||
399 | struct GNUNET_CRYPTO_EcdsaPublicKey identity; | ||
400 | |||
401 | /* followed by: | ||
402 | * serialized attributes data | ||
403 | */ | ||
404 | }; | ||
405 | |||
406 | |||
407 | |||
408 | GNUNET_NETWORK_STRUCT_END | ||
409 | |||
410 | #endif | ||
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c deleted file mode 100644 index 772b4a244..000000000 --- a/src/identity-provider/identity_provider_api.c +++ /dev/null | |||
@@ -1,1384 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @file identity-provider/identity_provider_api.c | ||
21 | * @brief api to interact with the identity provider service | ||
22 | * @author Martin Schanzenbach | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_constants.h" | ||
27 | #include "gnunet_protocols.h" | ||
28 | #include "gnunet_mq_lib.h" | ||
29 | #include "gnunet_identity_provider_service.h" | ||
30 | #include "gnunet_identity_attribute_lib.h" | ||
31 | #include "identity_provider.h" | ||
32 | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Handle for an operation with the service. | ||
38 | */ | ||
39 | struct GNUNET_IDENTITY_PROVIDER_Operation | ||
40 | { | ||
41 | |||
42 | /** | ||
43 | * Main handle. | ||
44 | */ | ||
45 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
46 | |||
47 | /** | ||
48 | * We keep operations in a DLL. | ||
49 | */ | ||
50 | struct GNUNET_IDENTITY_PROVIDER_Operation *next; | ||
51 | |||
52 | /** | ||
53 | * We keep operations in a DLL. | ||
54 | */ | ||
55 | struct GNUNET_IDENTITY_PROVIDER_Operation *prev; | ||
56 | |||
57 | /** | ||
58 | * Message to send to the service. | ||
59 | * Allocated at the end of this struct. | ||
60 | */ | ||
61 | const struct GNUNET_MessageHeader *msg; | ||
62 | |||
63 | /** | ||
64 | * Continuation to invoke after attribute store call | ||
65 | */ | ||
66 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus as_cb; | ||
67 | |||
68 | /** | ||
69 | * Attribute result callback | ||
70 | */ | ||
71 | GNUNET_IDENTITY_PROVIDER_AttributeResult ar_cb; | ||
72 | |||
73 | /** | ||
74 | * Revocation result callback | ||
75 | */ | ||
76 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus rvk_cb; | ||
77 | |||
78 | /** | ||
79 | * Ticket result callback | ||
80 | */ | ||
81 | GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb; | ||
82 | |||
83 | /** | ||
84 | * Envelope with the message for this queue entry. | ||
85 | */ | ||
86 | struct GNUNET_MQ_Envelope *env; | ||
87 | |||
88 | /** | ||
89 | * request id | ||
90 | */ | ||
91 | uint32_t r_id; | ||
92 | |||
93 | /** | ||
94 | * Closure for @e cont or @e cb. | ||
95 | */ | ||
96 | void *cls; | ||
97 | |||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * Handle for a ticket iterator operation | ||
102 | */ | ||
103 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator | ||
104 | { | ||
105 | |||
106 | /** | ||
107 | * Kept in a DLL. | ||
108 | */ | ||
109 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *next; | ||
110 | |||
111 | /** | ||
112 | * Kept in a DLL. | ||
113 | */ | ||
114 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *prev; | ||
115 | |||
116 | /** | ||
117 | * Main handle to access the idp. | ||
118 | */ | ||
119 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
120 | |||
121 | /** | ||
122 | * Function to call on completion. | ||
123 | */ | ||
124 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
125 | |||
126 | /** | ||
127 | * Closure for @e error_cb. | ||
128 | */ | ||
129 | void *finish_cb_cls; | ||
130 | |||
131 | /** | ||
132 | * The continuation to call with the results | ||
133 | */ | ||
134 | GNUNET_IDENTITY_PROVIDER_TicketCallback tr_cb; | ||
135 | |||
136 | /** | ||
137 | * Closure for @e tr_cb. | ||
138 | */ | ||
139 | void *cls; | ||
140 | |||
141 | /** | ||
142 | * Function to call on errors. | ||
143 | */ | ||
144 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
145 | |||
146 | /** | ||
147 | * Closure for @e error_cb. | ||
148 | */ | ||
149 | void *error_cb_cls; | ||
150 | |||
151 | /** | ||
152 | * Envelope of the message to send to the service, if not yet | ||
153 | * sent. | ||
154 | */ | ||
155 | struct GNUNET_MQ_Envelope *env; | ||
156 | |||
157 | /** | ||
158 | * The operation id this zone iteration operation has | ||
159 | */ | ||
160 | uint32_t r_id; | ||
161 | |||
162 | }; | ||
163 | |||
164 | |||
165 | /** | ||
166 | * Handle for a attribute iterator operation | ||
167 | */ | ||
168 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator | ||
169 | { | ||
170 | |||
171 | /** | ||
172 | * Kept in a DLL. | ||
173 | */ | ||
174 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *next; | ||
175 | |||
176 | /** | ||
177 | * Kept in a DLL. | ||
178 | */ | ||
179 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *prev; | ||
180 | |||
181 | /** | ||
182 | * Main handle to access the idp. | ||
183 | */ | ||
184 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
185 | |||
186 | /** | ||
187 | * Function to call on completion. | ||
188 | */ | ||
189 | GNUNET_SCHEDULER_TaskCallback finish_cb; | ||
190 | |||
191 | /** | ||
192 | * Closure for @e error_cb. | ||
193 | */ | ||
194 | void *finish_cb_cls; | ||
195 | |||
196 | /** | ||
197 | * The continuation to call with the results | ||
198 | */ | ||
199 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc; | ||
200 | |||
201 | /** | ||
202 | * Closure for @e proc. | ||
203 | */ | ||
204 | void *proc_cls; | ||
205 | |||
206 | /** | ||
207 | * Function to call on errors. | ||
208 | */ | ||
209 | GNUNET_SCHEDULER_TaskCallback error_cb; | ||
210 | |||
211 | /** | ||
212 | * Closure for @e error_cb. | ||
213 | */ | ||
214 | void *error_cb_cls; | ||
215 | |||
216 | /** | ||
217 | * Envelope of the message to send to the service, if not yet | ||
218 | * sent. | ||
219 | */ | ||
220 | struct GNUNET_MQ_Envelope *env; | ||
221 | |||
222 | /** | ||
223 | * Private key of the zone. | ||
224 | */ | ||
225 | struct GNUNET_CRYPTO_EcdsaPrivateKey identity; | ||
226 | |||
227 | /** | ||
228 | * The operation id this zone iteration operation has | ||
229 | */ | ||
230 | uint32_t r_id; | ||
231 | |||
232 | }; | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Handle for the service. | ||
237 | */ | ||
238 | struct GNUNET_IDENTITY_PROVIDER_Handle | ||
239 | { | ||
240 | /** | ||
241 | * Configuration to use. | ||
242 | */ | ||
243 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
244 | |||
245 | /** | ||
246 | * Socket (if available). | ||
247 | */ | ||
248 | struct GNUNET_CLIENT_Connection *client; | ||
249 | |||
250 | /** | ||
251 | * Closure for 'cb'. | ||
252 | */ | ||
253 | void *cb_cls; | ||
254 | |||
255 | /** | ||
256 | * Head of active operations. | ||
257 | */ | ||
258 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_head; | ||
259 | |||
260 | /** | ||
261 | * Tail of active operations. | ||
262 | */ | ||
263 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; | ||
264 | |||
265 | /** | ||
266 | * Head of active iterations | ||
267 | */ | ||
268 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_head; | ||
269 | |||
270 | /** | ||
271 | * Tail of active iterations | ||
272 | */ | ||
273 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it_tail; | ||
274 | |||
275 | /** | ||
276 | * Head of active iterations | ||
277 | */ | ||
278 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_head; | ||
279 | |||
280 | /** | ||
281 | * Tail of active iterations | ||
282 | */ | ||
283 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it_tail; | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Currently pending transmission request, or NULL for none. | ||
288 | */ | ||
289 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
290 | |||
291 | /** | ||
292 | * Task doing exponential back-off trying to reconnect. | ||
293 | */ | ||
294 | struct GNUNET_SCHEDULER_Task * reconnect_task; | ||
295 | |||
296 | /** | ||
297 | * Time for next connect retry. | ||
298 | */ | ||
299 | struct GNUNET_TIME_Relative reconnect_backoff; | ||
300 | |||
301 | /** | ||
302 | * Connection to service (if available). | ||
303 | */ | ||
304 | struct GNUNET_MQ_Handle *mq; | ||
305 | |||
306 | /** | ||
307 | * Request Id generator. Incremented by one for each request. | ||
308 | */ | ||
309 | uint32_t r_id_gen; | ||
310 | |||
311 | /** | ||
312 | * Are we polling for incoming messages right now? | ||
313 | */ | ||
314 | int in_receive; | ||
315 | |||
316 | }; | ||
317 | |||
318 | /** | ||
319 | * Try again to connect to the service. | ||
320 | * | ||
321 | * @param h handle to the identity provider service. | ||
322 | */ | ||
323 | static void | ||
324 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h); | ||
325 | |||
326 | /** | ||
327 | * Reconnect | ||
328 | * | ||
329 | * @param cls the handle | ||
330 | */ | ||
331 | static void | ||
332 | reconnect_task (void *cls) | ||
333 | { | ||
334 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | ||
335 | |||
336 | handle->reconnect_task = NULL; | ||
337 | reconnect (handle); | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Disconnect from service and then reconnect. | ||
343 | * | ||
344 | * @param handle our service | ||
345 | */ | ||
346 | static void | ||
347 | force_reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *handle) | ||
348 | { | ||
349 | GNUNET_MQ_destroy (handle->mq); | ||
350 | handle->mq = NULL; | ||
351 | handle->reconnect_backoff | ||
352 | = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); | ||
353 | handle->reconnect_task | ||
354 | = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, | ||
355 | &reconnect_task, | ||
356 | handle); | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * Free @a it. | ||
361 | * | ||
362 | * @param it entry to free | ||
363 | */ | ||
364 | static void | ||
365 | free_it (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
366 | { | ||
367 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
368 | |||
369 | GNUNET_CONTAINER_DLL_remove (h->it_head, | ||
370 | h->it_tail, | ||
371 | it); | ||
372 | if (NULL != it->env) | ||
373 | GNUNET_MQ_discard (it->env); | ||
374 | GNUNET_free (it); | ||
375 | } | ||
376 | |||
377 | static void | ||
378 | free_op (struct GNUNET_IDENTITY_PROVIDER_Operation* op) | ||
379 | { | ||
380 | if (NULL == op) | ||
381 | return; | ||
382 | if (NULL != op->env) | ||
383 | GNUNET_MQ_discard (op->env); | ||
384 | GNUNET_free(op); | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Generic error handler, called with the appropriate error code and | ||
390 | * the same closure specified at the creation of the message queue. | ||
391 | * Not every message queue implementation supports an error handler. | ||
392 | * | ||
393 | * @param cls closure with the `struct GNUNET_GNS_Handle *` | ||
394 | * @param error error code | ||
395 | */ | ||
396 | static void | ||
397 | mq_error_handler (void *cls, | ||
398 | enum GNUNET_MQ_Error error) | ||
399 | { | ||
400 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | ||
401 | force_reconnect (handle); | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * Handle an incoming message of type | ||
406 | * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE | ||
407 | * | ||
408 | * @param cls | ||
409 | * @param msg the message we received | ||
410 | */ | ||
411 | static void | ||
412 | handle_attribute_store_response (void *cls, | ||
413 | const struct AttributeStoreResultMessage *msg) | ||
414 | { | ||
415 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
416 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
417 | uint32_t r_id = ntohl (msg->id); | ||
418 | int res; | ||
419 | const char *emsg; | ||
420 | |||
421 | for (op = h->op_head; NULL != op; op = op->next) | ||
422 | if (op->r_id == r_id) | ||
423 | break; | ||
424 | if (NULL == op) | ||
425 | return; | ||
426 | |||
427 | res = ntohl (msg->op_result); | ||
428 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
429 | "Received ATTRIBUTE_STORE_RESPONSE with result %d\n", | ||
430 | res); | ||
431 | |||
432 | /* TODO: add actual error message to response... */ | ||
433 | if (GNUNET_SYSERR == res) | ||
434 | emsg = _("failed to store record\n"); | ||
435 | else | ||
436 | emsg = NULL; | ||
437 | if (NULL != op->as_cb) | ||
438 | op->as_cb (op->cls, | ||
439 | res, | ||
440 | emsg); | ||
441 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
442 | h->op_tail, | ||
443 | op); | ||
444 | free_op (op); | ||
445 | |||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Handle an incoming message of type | ||
451 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT | ||
452 | * | ||
453 | * @param cls | ||
454 | * @param msg the message we received | ||
455 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
456 | */ | ||
457 | static int | ||
458 | check_consume_ticket_result (void *cls, | ||
459 | const struct ConsumeTicketResultMessage *msg) | ||
460 | { | ||
461 | size_t msg_len; | ||
462 | size_t attrs_len; | ||
463 | |||
464 | msg_len = ntohs (msg->header.size); | ||
465 | attrs_len = ntohs (msg->attrs_len); | ||
466 | if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len) | ||
467 | { | ||
468 | GNUNET_break (0); | ||
469 | return GNUNET_SYSERR; | ||
470 | } | ||
471 | return GNUNET_OK; | ||
472 | } | ||
473 | |||
474 | |||
475 | /** | ||
476 | * Handle an incoming message of type | ||
477 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT | ||
478 | * | ||
479 | * @param cls | ||
480 | * @param msg the message we received | ||
481 | */ | ||
482 | static void | ||
483 | handle_consume_ticket_result (void *cls, | ||
484 | const struct ConsumeTicketResultMessage *msg) | ||
485 | { | ||
486 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
487 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
488 | size_t attrs_len; | ||
489 | uint32_t r_id = ntohl (msg->id); | ||
490 | |||
491 | attrs_len = ntohs (msg->attrs_len); | ||
492 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
493 | "Processing attribute result.\n"); | ||
494 | |||
495 | |||
496 | for (op = h->op_head; NULL != op; op = op->next) | ||
497 | if (op->r_id == r_id) | ||
498 | break; | ||
499 | if (NULL == op) | ||
500 | return; | ||
501 | |||
502 | { | ||
503 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
504 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
505 | attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize ((char*)&msg[1], | ||
506 | attrs_len); | ||
507 | if (NULL != op->ar_cb) | ||
508 | { | ||
509 | if (NULL == attrs) | ||
510 | { | ||
511 | op->ar_cb (op->cls, | ||
512 | &msg->identity, | ||
513 | NULL); | ||
514 | } | ||
515 | else | ||
516 | { | ||
517 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
518 | op->ar_cb (op->cls, | ||
519 | &msg->identity, | ||
520 | le->claim); | ||
521 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs); | ||
522 | } | ||
523 | } | ||
524 | if (NULL != op) | ||
525 | { | ||
526 | op->ar_cb (op->cls, | ||
527 | NULL, | ||
528 | NULL); | ||
529 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
530 | h->op_tail, | ||
531 | op); | ||
532 | free_op (op); | ||
533 | } | ||
534 | return; | ||
535 | } | ||
536 | GNUNET_assert (0); | ||
537 | } | ||
538 | |||
539 | |||
540 | /** | ||
541 | * Handle an incoming message of type | ||
542 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT | ||
543 | * | ||
544 | * @param cls | ||
545 | * @param msg the message we received | ||
546 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
547 | */ | ||
548 | static int | ||
549 | check_attribute_result (void *cls, | ||
550 | const struct AttributeResultMessage *msg) | ||
551 | { | ||
552 | size_t msg_len; | ||
553 | size_t attr_len; | ||
554 | |||
555 | msg_len = ntohs (msg->header.size); | ||
556 | attr_len = ntohs (msg->attr_len); | ||
557 | if (msg_len != sizeof (struct AttributeResultMessage) + attr_len) | ||
558 | { | ||
559 | GNUNET_break (0); | ||
560 | return GNUNET_SYSERR; | ||
561 | } | ||
562 | return GNUNET_OK; | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * Handle an incoming message of type | ||
568 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT | ||
569 | * | ||
570 | * @param cls | ||
571 | * @param msg the message we received | ||
572 | */ | ||
573 | static void | ||
574 | handle_attribute_result (void *cls, | ||
575 | const struct AttributeResultMessage *msg) | ||
576 | { | ||
577 | static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy; | ||
578 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
579 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it; | ||
580 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
581 | size_t attr_len; | ||
582 | uint32_t r_id = ntohl (msg->id); | ||
583 | |||
584 | attr_len = ntohs (msg->attr_len); | ||
585 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
586 | "Processing attribute result.\n"); | ||
587 | |||
588 | |||
589 | for (it = h->it_head; NULL != it; it = it->next) | ||
590 | if (it->r_id == r_id) | ||
591 | break; | ||
592 | for (op = h->op_head; NULL != op; op = op->next) | ||
593 | if (op->r_id == r_id) | ||
594 | break; | ||
595 | if ((NULL == it) && (NULL == op)) | ||
596 | return; | ||
597 | |||
598 | if ( (0 == (memcmp (&msg->identity, | ||
599 | &identity_dummy, | ||
600 | sizeof (identity_dummy)))) ) | ||
601 | { | ||
602 | if ((NULL == it) && (NULL == op)) | ||
603 | { | ||
604 | GNUNET_break (0); | ||
605 | force_reconnect (h); | ||
606 | return; | ||
607 | } | ||
608 | if (NULL != it) | ||
609 | { | ||
610 | if (NULL != it->finish_cb) | ||
611 | it->finish_cb (it->finish_cb_cls); | ||
612 | free_it (it); | ||
613 | } | ||
614 | if (NULL != op) | ||
615 | { | ||
616 | if (NULL != op->ar_cb) | ||
617 | op->ar_cb (op->cls, | ||
618 | NULL, | ||
619 | NULL); | ||
620 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
621 | h->op_tail, | ||
622 | op); | ||
623 | free_op (op); | ||
624 | |||
625 | } | ||
626 | return; | ||
627 | } | ||
628 | |||
629 | { | ||
630 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr; | ||
631 | attr = GNUNET_IDENTITY_ATTRIBUTE_deserialize ((char*)&msg[1], | ||
632 | attr_len); | ||
633 | if (NULL != it) | ||
634 | { | ||
635 | if (NULL != it->proc) | ||
636 | it->proc (it->proc_cls, | ||
637 | &msg->identity, | ||
638 | attr); | ||
639 | } else if (NULL != op) | ||
640 | { | ||
641 | if (NULL != op->ar_cb) | ||
642 | op->ar_cb (op->cls, | ||
643 | &msg->identity, | ||
644 | attr); | ||
645 | |||
646 | } | ||
647 | GNUNET_free (attr); | ||
648 | return; | ||
649 | } | ||
650 | GNUNET_assert (0); | ||
651 | } | ||
652 | |||
653 | /** | ||
654 | * Handle an incoming message of type | ||
655 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
656 | * | ||
657 | * @param cls | ||
658 | * @param msg the message we received | ||
659 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
660 | */ | ||
661 | static int | ||
662 | check_ticket_result (void *cls, | ||
663 | const struct TicketResultMessage *msg) | ||
664 | { | ||
665 | size_t msg_len; | ||
666 | |||
667 | msg_len = ntohs (msg->header.size); | ||
668 | if (msg_len < sizeof (struct TicketResultMessage)) | ||
669 | { | ||
670 | GNUNET_break (0); | ||
671 | return GNUNET_SYSERR; | ||
672 | } | ||
673 | return GNUNET_OK; | ||
674 | } | ||
675 | |||
676 | |||
677 | |||
678 | /** | ||
679 | * Handle an incoming message of type | ||
680 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT | ||
681 | * | ||
682 | * @param cls | ||
683 | * @param msg the message we received | ||
684 | */ | ||
685 | static void | ||
686 | handle_ticket_result (void *cls, | ||
687 | const struct TicketResultMessage *msg) | ||
688 | { | ||
689 | struct GNUNET_IDENTITY_PROVIDER_Handle *handle = cls; | ||
690 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
691 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; | ||
692 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; | ||
693 | uint32_t r_id = ntohl (msg->id); | ||
694 | size_t msg_len; | ||
695 | |||
696 | for (op = handle->op_head; NULL != op; op = op->next) | ||
697 | if (op->r_id == r_id) | ||
698 | break; | ||
699 | for (it = handle->ticket_it_head; NULL != it; it = it->next) | ||
700 | if (it->r_id == r_id) | ||
701 | break; | ||
702 | if ((NULL == op) && (NULL == it)) | ||
703 | return; | ||
704 | msg_len = ntohs (msg->header.size); | ||
705 | if (NULL != op) | ||
706 | { | ||
707 | GNUNET_CONTAINER_DLL_remove (handle->op_head, | ||
708 | handle->op_tail, | ||
709 | op); | ||
710 | if (msg_len == sizeof (struct TicketResultMessage)) | ||
711 | { | ||
712 | if (NULL != op->tr_cb) | ||
713 | op->tr_cb (op->cls, NULL); | ||
714 | } else { | ||
715 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1]; | ||
716 | if (NULL != op->tr_cb) | ||
717 | op->tr_cb (op->cls, ticket); | ||
718 | } | ||
719 | free_op (op); | ||
720 | return; | ||
721 | } else if (NULL != it) { | ||
722 | if (msg_len == sizeof (struct TicketResultMessage)) | ||
723 | { | ||
724 | if (NULL != it->tr_cb) | ||
725 | GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head, | ||
726 | handle->ticket_it_tail, | ||
727 | it); | ||
728 | it->finish_cb (it->finish_cb_cls); | ||
729 | GNUNET_free (it); | ||
730 | } else { | ||
731 | ticket = (struct GNUNET_IDENTITY_PROVIDER_Ticket *)&msg[1]; | ||
732 | if (NULL != it->tr_cb) | ||
733 | it->tr_cb (it->cls, ticket); | ||
734 | } | ||
735 | return; | ||
736 | } | ||
737 | GNUNET_break (0); | ||
738 | } | ||
739 | |||
740 | |||
741 | /** | ||
742 | * Handle an incoming message of type | ||
743 | * #GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT | ||
744 | * | ||
745 | * @param cls | ||
746 | * @param msg the message we received | ||
747 | */ | ||
748 | static void | ||
749 | handle_revoke_ticket_result (void *cls, | ||
750 | const struct RevokeTicketResultMessage *msg) | ||
751 | { | ||
752 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
753 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
754 | uint32_t r_id = ntohl (msg->id); | ||
755 | int32_t success; | ||
756 | |||
757 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
758 | "Processing revocation result.\n"); | ||
759 | |||
760 | |||
761 | for (op = h->op_head; NULL != op; op = op->next) | ||
762 | if (op->r_id == r_id) | ||
763 | break; | ||
764 | if (NULL == op) | ||
765 | return; | ||
766 | success = ntohl (msg->success); | ||
767 | { | ||
768 | if (NULL != op->rvk_cb) | ||
769 | { | ||
770 | op->rvk_cb (op->cls, | ||
771 | success, | ||
772 | NULL); | ||
773 | } | ||
774 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
775 | h->op_tail, | ||
776 | op); | ||
777 | free_op (op); | ||
778 | return; | ||
779 | } | ||
780 | GNUNET_assert (0); | ||
781 | } | ||
782 | |||
783 | |||
784 | |||
785 | /** | ||
786 | * Try again to connect to the service. | ||
787 | * | ||
788 | * @param h handle to the identity provider service. | ||
789 | */ | ||
790 | static void | ||
791 | reconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | ||
792 | { | ||
793 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
794 | GNUNET_MQ_hd_fixed_size (attribute_store_response, | ||
795 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE_RESPONSE, | ||
796 | struct AttributeStoreResultMessage, | ||
797 | h), | ||
798 | GNUNET_MQ_hd_var_size (attribute_result, | ||
799 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_RESULT, | ||
800 | struct AttributeResultMessage, | ||
801 | h), | ||
802 | GNUNET_MQ_hd_var_size (ticket_result, | ||
803 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_RESULT, | ||
804 | struct TicketResultMessage, | ||
805 | h), | ||
806 | GNUNET_MQ_hd_var_size (consume_ticket_result, | ||
807 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET_RESULT, | ||
808 | struct ConsumeTicketResultMessage, | ||
809 | h), | ||
810 | GNUNET_MQ_hd_fixed_size (revoke_ticket_result, | ||
811 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET_RESULT, | ||
812 | struct RevokeTicketResultMessage, | ||
813 | h), | ||
814 | GNUNET_MQ_handler_end () | ||
815 | }; | ||
816 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
817 | |||
818 | GNUNET_assert (NULL == h->mq); | ||
819 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
820 | "Connecting to identity provider service.\n"); | ||
821 | |||
822 | h->mq = GNUNET_CLIENT_connect (h->cfg, | ||
823 | "identity-provider", | ||
824 | handlers, | ||
825 | &mq_error_handler, | ||
826 | h); | ||
827 | if (NULL == h->mq) | ||
828 | return; | ||
829 | for (op = h->op_head; NULL != op; op = op->next) | ||
830 | GNUNET_MQ_send_copy (h->mq, | ||
831 | op->env); | ||
832 | } | ||
833 | |||
834 | |||
835 | /** | ||
836 | * Connect to the identity provider service. | ||
837 | * | ||
838 | * @param cfg the configuration to use | ||
839 | * @return handle to use | ||
840 | */ | ||
841 | struct GNUNET_IDENTITY_PROVIDER_Handle * | ||
842 | GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
843 | { | ||
844 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
845 | |||
846 | h = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Handle); | ||
847 | h->cfg = cfg; | ||
848 | reconnect (h); | ||
849 | if (NULL == h->mq) | ||
850 | { | ||
851 | GNUNET_free (h); | ||
852 | return NULL; | ||
853 | } | ||
854 | return h; | ||
855 | } | ||
856 | |||
857 | |||
858 | /** | ||
859 | * Cancel an operation. Note that the operation MAY still | ||
860 | * be executed; this merely cancels the continuation; if the request | ||
861 | * was already transmitted, the service may still choose to complete | ||
862 | * the operation. | ||
863 | * | ||
864 | * @param op operation to cancel | ||
865 | */ | ||
866 | void | ||
867 | GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op) | ||
868 | { | ||
869 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = op->h; | ||
870 | |||
871 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
872 | h->op_tail, | ||
873 | op); | ||
874 | free_op (op); | ||
875 | } | ||
876 | |||
877 | |||
878 | /** | ||
879 | * Disconnect from service | ||
880 | * | ||
881 | * @param h handle to destroy | ||
882 | */ | ||
883 | void | ||
884 | GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | ||
885 | { | ||
886 | GNUNET_assert (NULL != h); | ||
887 | if (NULL != h->mq) | ||
888 | { | ||
889 | GNUNET_MQ_destroy (h->mq); | ||
890 | h->mq = NULL; | ||
891 | } | ||
892 | if (NULL != h->reconnect_task) | ||
893 | { | ||
894 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
895 | h->reconnect_task = NULL; | ||
896 | } | ||
897 | GNUNET_assert (NULL == h->op_head); | ||
898 | GNUNET_free (h); | ||
899 | } | ||
900 | |||
901 | /** | ||
902 | * Store an attribute. If the attribute is already present, | ||
903 | * it is replaced with the new attribute. | ||
904 | * | ||
905 | * @param h handle to the identity provider | ||
906 | * @param pkey private key of the identity | ||
907 | * @param attr the attribute value | ||
908 | * @param exp_interval the relative expiration interval for the attribute | ||
909 | * @param cont continuation to call when done | ||
910 | * @param cont_cls closure for @a cont | ||
911 | * @return handle to abort the request | ||
912 | */ | ||
913 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
914 | GNUNET_IDENTITY_PROVIDER_attribute_store (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
915 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, | ||
916 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr, | ||
917 | const struct GNUNET_TIME_Relative *exp_interval, | ||
918 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cont, | ||
919 | void *cont_cls) | ||
920 | { | ||
921 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
922 | struct AttributeStoreMessage *sam; | ||
923 | size_t attr_len; | ||
924 | |||
925 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
926 | op->h = h; | ||
927 | op->as_cb = cont; | ||
928 | op->cls = cont_cls; | ||
929 | op->r_id = h->r_id_gen++; | ||
930 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
931 | h->op_tail, | ||
932 | op); | ||
933 | attr_len = GNUNET_IDENTITY_ATTRIBUTE_serialize_get_size (attr); | ||
934 | op->env = GNUNET_MQ_msg_extra (sam, | ||
935 | attr_len, | ||
936 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_STORE); | ||
937 | sam->identity = *pkey; | ||
938 | sam->id = htonl (op->r_id); | ||
939 | sam->exp = GNUNET_htonll (exp_interval->rel_value_us); | ||
940 | |||
941 | GNUNET_IDENTITY_ATTRIBUTE_serialize (attr, | ||
942 | (char*)&sam[1]); | ||
943 | |||
944 | sam->attr_len = htons (attr_len); | ||
945 | if (NULL != h->mq) | ||
946 | GNUNET_MQ_send_copy (h->mq, | ||
947 | op->env); | ||
948 | return op; | ||
949 | |||
950 | } | ||
951 | |||
952 | |||
953 | /** | ||
954 | * List all attributes for a local identity. | ||
955 | * This MUST lock the `struct GNUNET_IDENTITY_PROVIDER_Handle` | ||
956 | * for any other calls than #GNUNET_IDENTITY_PROVIDER_get_attributes_next() and | ||
957 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_stop. @a proc will be called once | ||
958 | * immediately, and then again after | ||
959 | * #GNUNET_IDENTITY_PROVIDER_get_attributes_next() is invoked. | ||
960 | * | ||
961 | * On error (disconnect), @a error_cb will be invoked. | ||
962 | * On normal completion, @a finish_cb proc will be | ||
963 | * invoked. | ||
964 | * | ||
965 | * @param h handle to the idp | ||
966 | * @param identity identity to access | ||
967 | * @param error_cb function to call on error (i.e. disconnect), | ||
968 | * the handle is afterwards invalid | ||
969 | * @param error_cb_cls closure for @a error_cb | ||
970 | * @param proc function to call on each attribute; it | ||
971 | * will be called repeatedly with a value (if available) | ||
972 | * @param proc_cls closure for @a proc | ||
973 | * @param finish_cb function to call on completion | ||
974 | * the handle is afterwards invalid | ||
975 | * @param finish_cb_cls closure for @a finish_cb | ||
976 | * @return an iterator handle to use for iteration | ||
977 | */ | ||
978 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator * | ||
979 | GNUNET_IDENTITY_PROVIDER_get_attributes_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
980 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
981 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
982 | void *error_cb_cls, | ||
983 | GNUNET_IDENTITY_PROVIDER_AttributeResult proc, | ||
984 | void *proc_cls, | ||
985 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
986 | void *finish_cb_cls) | ||
987 | { | ||
988 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it; | ||
989 | struct GNUNET_MQ_Envelope *env; | ||
990 | struct AttributeIterationStartMessage *msg; | ||
991 | uint32_t rid; | ||
992 | |||
993 | rid = h->r_id_gen++; | ||
994 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator); | ||
995 | it->h = h; | ||
996 | it->error_cb = error_cb; | ||
997 | it->error_cb_cls = error_cb_cls; | ||
998 | it->finish_cb = finish_cb; | ||
999 | it->finish_cb_cls = finish_cb_cls; | ||
1000 | it->proc = proc; | ||
1001 | it->proc_cls = proc_cls; | ||
1002 | it->r_id = rid; | ||
1003 | it->identity = *identity; | ||
1004 | GNUNET_CONTAINER_DLL_insert_tail (h->it_head, | ||
1005 | h->it_tail, | ||
1006 | it); | ||
1007 | env = GNUNET_MQ_msg (msg, | ||
1008 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_START); | ||
1009 | msg->id = htonl (rid); | ||
1010 | msg->identity = *identity; | ||
1011 | if (NULL == h->mq) | ||
1012 | it->env = env; | ||
1013 | else | ||
1014 | GNUNET_MQ_send (h->mq, | ||
1015 | env); | ||
1016 | return it; | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | /** | ||
1021 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_get_attributes_start | ||
1022 | * for the next record. | ||
1023 | * | ||
1024 | * @param it the iterator | ||
1025 | */ | ||
1026 | void | ||
1027 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
1028 | { | ||
1029 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1030 | struct AttributeIterationNextMessage *msg; | ||
1031 | struct GNUNET_MQ_Envelope *env; | ||
1032 | |||
1033 | env = GNUNET_MQ_msg (msg, | ||
1034 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_NEXT); | ||
1035 | msg->id = htonl (it->r_id); | ||
1036 | GNUNET_MQ_send (h->mq, | ||
1037 | env); | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | /** | ||
1042 | * Stops iteration and releases the idp handle for further calls. Must | ||
1043 | * be called on any iteration that has not yet completed prior to calling | ||
1044 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
1045 | * | ||
1046 | * @param it the iterator | ||
1047 | */ | ||
1048 | void | ||
1049 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *it) | ||
1050 | { | ||
1051 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1052 | struct GNUNET_MQ_Envelope *env; | ||
1053 | struct AttributeIterationStopMessage *msg; | ||
1054 | |||
1055 | if (NULL != h->mq) | ||
1056 | { | ||
1057 | env = GNUNET_MQ_msg (msg, | ||
1058 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ATTRIBUTE_ITERATION_STOP); | ||
1059 | msg->id = htonl (it->r_id); | ||
1060 | GNUNET_MQ_send (h->mq, | ||
1061 | env); | ||
1062 | } | ||
1063 | free_it (it); | ||
1064 | } | ||
1065 | |||
1066 | |||
1067 | /** TODO | ||
1068 | * Issues a ticket to another identity. The identity may use | ||
1069 | * @GNUNET_IDENTITY_PROVIDER_authorization_ticket_consume to consume the ticket | ||
1070 | * and retrieve the attributes specified in the AttributeList. | ||
1071 | * | ||
1072 | * @param h the identity provider to use | ||
1073 | * @param iss the issuing identity | ||
1074 | * @param rp the subject of the ticket (the relying party) | ||
1075 | * @param attrs the attributes that the relying party is given access to | ||
1076 | * @param cb the callback | ||
1077 | * @param cb_cls the callback closure | ||
1078 | * @return handle to abort the operation | ||
1079 | */ | ||
1080 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1081 | GNUNET_IDENTITY_PROVIDER_ticket_issue (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1082 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss, | ||
1083 | const struct GNUNET_CRYPTO_EcdsaPublicKey *rp, | ||
1084 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
1085 | GNUNET_IDENTITY_PROVIDER_TicketCallback cb, | ||
1086 | void *cb_cls) | ||
1087 | { | ||
1088 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1089 | struct IssueTicketMessage *tim; | ||
1090 | size_t attr_len; | ||
1091 | |||
1092 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1093 | op->h = h; | ||
1094 | op->tr_cb = cb; | ||
1095 | op->cls = cb_cls; | ||
1096 | op->r_id = h->r_id_gen++; | ||
1097 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1098 | h->op_tail, | ||
1099 | op); | ||
1100 | attr_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs); | ||
1101 | op->env = GNUNET_MQ_msg_extra (tim, | ||
1102 | attr_len, | ||
1103 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_TICKET); | ||
1104 | tim->identity = *iss; | ||
1105 | tim->rp = *rp; | ||
1106 | tim->id = htonl (op->r_id); | ||
1107 | |||
1108 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs, | ||
1109 | (char*)&tim[1]); | ||
1110 | |||
1111 | tim->attr_len = htons (attr_len); | ||
1112 | if (NULL != h->mq) | ||
1113 | GNUNET_MQ_send_copy (h->mq, | ||
1114 | op->env); | ||
1115 | return op; | ||
1116 | } | ||
1117 | |||
1118 | /** | ||
1119 | * Consumes an issued ticket. The ticket is persisted | ||
1120 | * and used to retrieve identity information from the issuer | ||
1121 | * | ||
1122 | * @param h the identity provider to use | ||
1123 | * @param identity the identity that is the subject of the issued ticket (the relying party) | ||
1124 | * @param ticket the issued ticket to consume | ||
1125 | * @param cb the callback to call | ||
1126 | * @param cb_cls the callback closure | ||
1127 | * @return handle to abort the operation | ||
1128 | */ | ||
1129 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1130 | GNUNET_IDENTITY_PROVIDER_ticket_consume (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1131 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1132 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1133 | GNUNET_IDENTITY_PROVIDER_AttributeResult cb, | ||
1134 | void *cb_cls) | ||
1135 | { | ||
1136 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1137 | struct ConsumeTicketMessage *ctm; | ||
1138 | |||
1139 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1140 | op->h = h; | ||
1141 | op->ar_cb = cb; | ||
1142 | op->cls = cb_cls; | ||
1143 | op->r_id = h->r_id_gen++; | ||
1144 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1145 | h->op_tail, | ||
1146 | op); | ||
1147 | op->env = GNUNET_MQ_msg_extra (ctm, | ||
1148 | sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
1149 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_CONSUME_TICKET); | ||
1150 | ctm->identity = *identity; | ||
1151 | ctm->id = htonl (op->r_id); | ||
1152 | |||
1153 | GNUNET_memcpy ((char*)&ctm[1], | ||
1154 | ticket, | ||
1155 | sizeof (const struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1156 | |||
1157 | if (NULL != h->mq) | ||
1158 | GNUNET_MQ_send_copy (h->mq, | ||
1159 | op->env); | ||
1160 | return op; | ||
1161 | |||
1162 | } | ||
1163 | |||
1164 | |||
1165 | /** | ||
1166 | * Lists all tickets that have been issued to remote | ||
1167 | * identites (relying parties) | ||
1168 | * | ||
1169 | * @param h the identity provider to use | ||
1170 | * @param identity the issuing identity | ||
1171 | * @param error_cb function to call on error (i.e. disconnect), | ||
1172 | * the handle is afterwards invalid | ||
1173 | * @param error_cb_cls closure for @a error_cb | ||
1174 | * @param proc function to call on each ticket; it | ||
1175 | * will be called repeatedly with a value (if available) | ||
1176 | * @param proc_cls closure for @a proc | ||
1177 | * @param finish_cb function to call on completion | ||
1178 | * the handle is afterwards invalid | ||
1179 | * @param finish_cb_cls closure for @a finish_cb | ||
1180 | * @return an iterator handle to use for iteration | ||
1181 | */ | ||
1182 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * | ||
1183 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1184 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1185 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1186 | void *error_cb_cls, | ||
1187 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
1188 | void *proc_cls, | ||
1189 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1190 | void *finish_cb_cls) | ||
1191 | { | ||
1192 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; | ||
1193 | struct GNUNET_CRYPTO_EcdsaPublicKey identity_pub; | ||
1194 | struct GNUNET_MQ_Envelope *env; | ||
1195 | struct TicketIterationStartMessage *msg; | ||
1196 | uint32_t rid; | ||
1197 | |||
1198 | GNUNET_CRYPTO_ecdsa_key_get_public (identity, | ||
1199 | &identity_pub); | ||
1200 | rid = h->r_id_gen++; | ||
1201 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator); | ||
1202 | it->h = h; | ||
1203 | it->error_cb = error_cb; | ||
1204 | it->error_cb_cls = error_cb_cls; | ||
1205 | it->finish_cb = finish_cb; | ||
1206 | it->finish_cb_cls = finish_cb_cls; | ||
1207 | it->tr_cb = proc; | ||
1208 | it->cls = proc_cls; | ||
1209 | it->r_id = rid; | ||
1210 | GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, | ||
1211 | h->ticket_it_tail, | ||
1212 | it); | ||
1213 | env = GNUNET_MQ_msg (msg, | ||
1214 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START); | ||
1215 | msg->id = htonl (rid); | ||
1216 | msg->identity = identity_pub; | ||
1217 | msg->is_audience = htonl (GNUNET_NO); | ||
1218 | if (NULL == h->mq) | ||
1219 | it->env = env; | ||
1220 | else | ||
1221 | GNUNET_MQ_send (h->mq, | ||
1222 | env); | ||
1223 | return it; | ||
1224 | |||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * Lists all tickets that have been issued to remote | ||
1230 | * identites (relying parties) | ||
1231 | * | ||
1232 | * @param h the identity provider to use | ||
1233 | * @param identity the issuing identity | ||
1234 | * @param error_cb function to call on error (i.e. disconnect), | ||
1235 | * the handle is afterwards invalid | ||
1236 | * @param error_cb_cls closure for @a error_cb | ||
1237 | * @param proc function to call on each ticket; it | ||
1238 | * will be called repeatedly with a value (if available) | ||
1239 | * @param proc_cls closure for @a proc | ||
1240 | * @param finish_cb function to call on completion | ||
1241 | * the handle is afterwards invalid | ||
1242 | * @param finish_cb_cls closure for @a finish_cb | ||
1243 | * @return an iterator handle to use for iteration | ||
1244 | */ | ||
1245 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator * | ||
1246 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_start_rp (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1247 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1248 | GNUNET_SCHEDULER_TaskCallback error_cb, | ||
1249 | void *error_cb_cls, | ||
1250 | GNUNET_IDENTITY_PROVIDER_TicketCallback proc, | ||
1251 | void *proc_cls, | ||
1252 | GNUNET_SCHEDULER_TaskCallback finish_cb, | ||
1253 | void *finish_cb_cls) | ||
1254 | { | ||
1255 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it; | ||
1256 | struct GNUNET_MQ_Envelope *env; | ||
1257 | struct TicketIterationStartMessage *msg; | ||
1258 | uint32_t rid; | ||
1259 | |||
1260 | rid = h->r_id_gen++; | ||
1261 | it = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_TicketIterator); | ||
1262 | it->h = h; | ||
1263 | it->error_cb = error_cb; | ||
1264 | it->error_cb_cls = error_cb_cls; | ||
1265 | it->finish_cb = finish_cb; | ||
1266 | it->finish_cb_cls = finish_cb_cls; | ||
1267 | it->tr_cb = proc; | ||
1268 | it->cls = proc_cls; | ||
1269 | it->r_id = rid; | ||
1270 | GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, | ||
1271 | h->ticket_it_tail, | ||
1272 | it); | ||
1273 | env = GNUNET_MQ_msg (msg, | ||
1274 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_START); | ||
1275 | msg->id = htonl (rid); | ||
1276 | msg->identity = *identity; | ||
1277 | msg->is_audience = htonl (GNUNET_YES); | ||
1278 | if (NULL == h->mq) | ||
1279 | it->env = env; | ||
1280 | else | ||
1281 | GNUNET_MQ_send (h->mq, | ||
1282 | env); | ||
1283 | return it; | ||
1284 | |||
1285 | |||
1286 | } | ||
1287 | |||
1288 | /** | ||
1289 | * Calls the record processor specified in #GNUNET_IDENTITY_PROVIDER_ticket_iteration_start | ||
1290 | * for the next record. | ||
1291 | * | ||
1292 | * @param it the iterator | ||
1293 | */ | ||
1294 | void | ||
1295 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) | ||
1296 | { | ||
1297 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1298 | struct TicketIterationNextMessage *msg; | ||
1299 | struct GNUNET_MQ_Envelope *env; | ||
1300 | |||
1301 | env = GNUNET_MQ_msg (msg, | ||
1302 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_NEXT); | ||
1303 | msg->id = htonl (it->r_id); | ||
1304 | GNUNET_MQ_send (h->mq, | ||
1305 | env); | ||
1306 | } | ||
1307 | |||
1308 | |||
1309 | /** | ||
1310 | * Stops iteration and releases the idp handle for further calls. Must | ||
1311 | * be called on any iteration that has not yet completed prior to calling | ||
1312 | * #GNUNET_IDENTITY_PROVIDER_disconnect. | ||
1313 | * | ||
1314 | * @param it the iterator | ||
1315 | */ | ||
1316 | void | ||
1317 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (struct GNUNET_IDENTITY_PROVIDER_TicketIterator *it) | ||
1318 | { | ||
1319 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = it->h; | ||
1320 | struct GNUNET_MQ_Envelope *env; | ||
1321 | struct TicketIterationStopMessage *msg; | ||
1322 | |||
1323 | if (NULL != h->mq) | ||
1324 | { | ||
1325 | env = GNUNET_MQ_msg (msg, | ||
1326 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_TICKET_ITERATION_STOP); | ||
1327 | msg->id = htonl (it->r_id); | ||
1328 | GNUNET_MQ_send (h->mq, | ||
1329 | env); | ||
1330 | } | ||
1331 | GNUNET_free (it); | ||
1332 | } | ||
1333 | |||
1334 | /** | ||
1335 | * Revoked an issued ticket. The relying party will be unable to retrieve | ||
1336 | * updated attributes. | ||
1337 | * | ||
1338 | * @param h the identity provider to use | ||
1339 | * @param identity the issuing identity | ||
1340 | * @param ticket the ticket to revoke | ||
1341 | * @param cb the callback | ||
1342 | * @param cb_cls the callback closure | ||
1343 | * @return handle to abort the operation | ||
1344 | */ | ||
1345 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
1346 | GNUNET_IDENTITY_PROVIDER_ticket_revoke (struct GNUNET_IDENTITY_PROVIDER_Handle *h, | ||
1347 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity, | ||
1348 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
1349 | GNUNET_IDENTITY_PROVIDER_ContinuationWithStatus cb, | ||
1350 | void *cb_cls) | ||
1351 | { | ||
1352 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
1353 | struct GNUNET_MQ_Envelope *env; | ||
1354 | struct RevokeTicketMessage *msg; | ||
1355 | uint32_t rid; | ||
1356 | |||
1357 | rid = h->r_id_gen++; | ||
1358 | op = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Operation); | ||
1359 | op->h = h; | ||
1360 | op->rvk_cb = cb; | ||
1361 | op->cls = cb_cls; | ||
1362 | op->r_id = rid; | ||
1363 | GNUNET_CONTAINER_DLL_insert_tail (h->op_head, | ||
1364 | h->op_tail, | ||
1365 | op); | ||
1366 | env = GNUNET_MQ_msg_extra (msg, | ||
1367 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket), | ||
1368 | GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_REVOKE_TICKET); | ||
1369 | msg->id = htonl (rid); | ||
1370 | msg->identity = *identity; | ||
1371 | GNUNET_memcpy (&msg[1], | ||
1372 | ticket, | ||
1373 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1374 | if (NULL == h->mq) | ||
1375 | op->env = env; | ||
1376 | else | ||
1377 | GNUNET_MQ_send (h->mq, | ||
1378 | env); | ||
1379 | return op; | ||
1380 | } | ||
1381 | |||
1382 | |||
1383 | |||
1384 | /* end of identity_provider_api.c */ | ||
diff --git a/src/identity-provider/jwt.c b/src/identity-provider/jwt.c deleted file mode 100644 index 1a984f7b5..000000000 --- a/src/identity-provider/jwt.c +++ /dev/null | |||
@@ -1,189 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2010-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @file identity-provider/jwt.c | ||
21 | * @brief helper library for JSON-Web-Tokens | ||
22 | * @author Martin Schanzenbach | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_signatures.h" | ||
27 | #include "gnunet_identity_attribute_lib.h" | ||
28 | #include <jansson.h> | ||
29 | |||
30 | |||
31 | #define JWT_ALG "alg" | ||
32 | |||
33 | /*TODO is this the correct way to define new algs? */ | ||
34 | #define JWT_ALG_VALUE "urn:org:gnunet:jwt:alg:ecdsa:ed25519" | ||
35 | |||
36 | #define JWT_TYP "typ" | ||
37 | |||
38 | #define JWT_TYP_VALUE "jwt" | ||
39 | |||
40 | //TODO change server address | ||
41 | #define SERVER_ADDRESS "https://localhost" | ||
42 | |||
43 | static char* | ||
44 | create_jwt_header(void) | ||
45 | { | ||
46 | json_t *root; | ||
47 | char *json_str; | ||
48 | |||
49 | root = json_object (); | ||
50 | json_object_set_new (root, JWT_ALG, json_string (JWT_ALG_VALUE)); | ||
51 | json_object_set_new (root, JWT_TYP, json_string (JWT_TYP_VALUE)); | ||
52 | |||
53 | json_str = json_dumps (root, JSON_INDENT(1)); | ||
54 | json_decref (root); | ||
55 | return json_str; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * Create a JWT from attributes | ||
60 | * | ||
61 | * @param aud_key the public of the subject | ||
62 | * @param attrs the attribute list | ||
63 | * @param priv_key the key used to sign the JWT | ||
64 | * @return a new base64-encoded JWT string. | ||
65 | */ | ||
66 | char* | ||
67 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | ||
68 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
69 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key) | ||
70 | { | ||
71 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
72 | struct GNUNET_CRYPTO_EcdsaPublicKey sub_key; | ||
73 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
74 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
75 | char* audience; | ||
76 | char* subject; | ||
77 | char* header; | ||
78 | char* padding; | ||
79 | char* body_str; | ||
80 | char* result; | ||
81 | char* header_base64; | ||
82 | char* body_base64; | ||
83 | char* signature_target; | ||
84 | char* signature_base64; | ||
85 | char* attr_val_str; | ||
86 | json_t* body; | ||
87 | |||
88 | //exp REQUIRED time expired from config | ||
89 | //iat REQUIRED time now | ||
90 | //auth_time only if max_age | ||
91 | //nonce only if nonce | ||
92 | // OPTIONAL acr,amr,azp | ||
93 | GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, &sub_key); | ||
94 | /* TODO maybe we should use a local identity here */ | ||
95 | subject = GNUNET_STRINGS_data_to_string_alloc (&sub_key, | ||
96 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
97 | audience = GNUNET_STRINGS_data_to_string_alloc (aud_key, | ||
98 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
99 | header = create_jwt_header (); | ||
100 | body = json_object (); | ||
101 | /* TODO who is the issuer? local IdP or subject ? See self-issued tokens? */ | ||
102 | //iss REQUIRED case sensitive server uri with https | ||
103 | json_object_set_new (body, | ||
104 | "iss", json_string (SERVER_ADDRESS)); | ||
105 | //sub REQUIRED public key identity, not exceed 255 ASCII length | ||
106 | json_object_set_new (body, | ||
107 | "sub", json_string (subject)); | ||
108 | /* TODO what should be in here exactly? */ | ||
109 | //aud REQUIRED public key client_id must be there | ||
110 | json_object_set_new (body, | ||
111 | "aud", json_string (audience)); | ||
112 | for (le = attrs->list_head; NULL != le; le = le->next) | ||
113 | { | ||
114 | /** | ||
115 | * TODO here we should have a function that | ||
116 | * calls the Attribute plugins to create a | ||
117 | * json representation for its value | ||
118 | */ | ||
119 | attr_val_str = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (le->claim->type, | ||
120 | le->claim->data, | ||
121 | le->claim->data_size); | ||
122 | json_object_set_new (body, | ||
123 | le->claim->name, | ||
124 | json_string (attr_val_str)); | ||
125 | GNUNET_free (attr_val_str); | ||
126 | } | ||
127 | body_str = json_dumps (body, JSON_INDENT(0)); | ||
128 | json_decref (body); | ||
129 | |||
130 | GNUNET_STRINGS_base64_encode (header, | ||
131 | strlen (header), | ||
132 | &header_base64); | ||
133 | //Remove GNUNET padding of base64 | ||
134 | padding = strtok(header_base64, "="); | ||
135 | while (NULL != padding) | ||
136 | padding = strtok(NULL, "="); | ||
137 | |||
138 | GNUNET_STRINGS_base64_encode (body_str, | ||
139 | strlen (body_str), | ||
140 | &body_base64); | ||
141 | |||
142 | //Remove GNUNET padding of base64 | ||
143 | padding = strtok(body_base64, "="); | ||
144 | while (NULL != padding) | ||
145 | padding = strtok(NULL, "="); | ||
146 | |||
147 | GNUNET_free (subject); | ||
148 | GNUNET_free (audience); | ||
149 | |||
150 | /** | ||
151 | * TODO | ||
152 | * Creating the JWT signature. This might not be | ||
153 | * standards compliant, check. | ||
154 | */ | ||
155 | GNUNET_asprintf (&signature_target, "%s,%s", header_base64, body_base64); | ||
156 | |||
157 | purpose = | ||
158 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
159 | strlen (signature_target)); | ||
160 | purpose->size = | ||
161 | htonl (strlen (signature_target) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); | ||
162 | purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN); | ||
163 | GNUNET_memcpy (&purpose[1], signature_target, strlen (signature_target)); | ||
164 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, | ||
165 | purpose, | ||
166 | (struct GNUNET_CRYPTO_EcdsaSignature *)&signature)) | ||
167 | { | ||
168 | GNUNET_free (signature_target); | ||
169 | GNUNET_free (body_str); | ||
170 | GNUNET_free (body_base64); | ||
171 | GNUNET_free (header_base64); | ||
172 | GNUNET_free (purpose); | ||
173 | return NULL; | ||
174 | } | ||
175 | GNUNET_STRINGS_base64_encode ((const char*)&signature, | ||
176 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | ||
177 | &signature_base64); | ||
178 | GNUNET_asprintf (&result, "%s.%s.%s", | ||
179 | header_base64, body_base64, signature_base64); | ||
180 | |||
181 | GNUNET_free (signature_target); | ||
182 | GNUNET_free (header); | ||
183 | GNUNET_free (body_str); | ||
184 | GNUNET_free (signature_base64); | ||
185 | GNUNET_free (body_base64); | ||
186 | GNUNET_free (header_base64); | ||
187 | GNUNET_free (purpose); | ||
188 | return result; | ||
189 | } | ||
diff --git a/src/identity-provider/jwt.h b/src/identity-provider/jwt.h deleted file mode 100644 index 072958973..000000000 --- a/src/identity-provider/jwt.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | #ifndef JWT_H | ||
2 | #define JWT_H | ||
3 | |||
4 | char* | ||
5 | jwt_create_from_list (const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | ||
6 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs, | ||
7 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key); | ||
8 | |||
9 | #endif | ||
diff --git a/src/identity-provider/plugin_gnsrecord_identity_provider.c b/src/identity-provider/plugin_gnsrecord_identity_provider.c deleted file mode 100644 index f0dc563dc..000000000 --- a/src/identity-provider/plugin_gnsrecord_identity_provider.c +++ /dev/null | |||
@@ -1,265 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2013, 2014 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @file identity-provider/plugin_gnsrecord_identity_provider.c | ||
21 | * @brief gnsrecord plugin to provide the API for identity records | ||
22 | * @author Martin Schanzenbach | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_gnsrecord_lib.h" | ||
27 | #include "gnunet_gnsrecord_plugin.h" | ||
28 | |||
29 | |||
30 | /** | ||
31 | * Convert the 'value' of a record to a string. | ||
32 | * | ||
33 | * @param cls closure, unused | ||
34 | * @param type type of the record | ||
35 | * @param data value in binary encoding | ||
36 | * @param data_size number of bytes in @a data | ||
37 | * @return NULL on error, otherwise human-readable representation of the value | ||
38 | */ | ||
39 | static char * | ||
40 | value_to_string (void *cls, | ||
41 | uint32_t type, | ||
42 | const void *data, | ||
43 | size_t data_size) | ||
44 | { | ||
45 | const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe_privkey; | ||
46 | const struct GNUNET_CRYPTO_EcdsaPublicKey *audience_pubkey; | ||
47 | const char *scopes; | ||
48 | char *ecdhe_str; | ||
49 | char *aud_str; | ||
50 | char *result; | ||
51 | |||
52 | switch (type) | ||
53 | { | ||
54 | case GNUNET_GNSRECORD_TYPE_ID_ATTR: | ||
55 | return GNUNET_STRINGS_data_to_string_alloc (data, data_size); | ||
56 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN: //DEPRECATED | ||
57 | return GNUNET_strndup (data, data_size); | ||
58 | case GNUNET_GNSRECORD_TYPE_ABE_KEY: | ||
59 | case GNUNET_GNSRECORD_TYPE_ABE_MASTER: | ||
60 | return GNUNET_STRINGS_data_to_string_alloc (data, data_size); | ||
61 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: //DEPRECATED | ||
62 | ecdhe_privkey = data; | ||
63 | audience_pubkey = data+sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | ||
64 | scopes = (char*) audience_pubkey+(sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
65 | ecdhe_str = GNUNET_STRINGS_data_to_string_alloc (ecdhe_privkey, | ||
66 | sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); | ||
67 | aud_str = GNUNET_STRINGS_data_to_string_alloc (audience_pubkey, | ||
68 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
69 | GNUNET_asprintf (&result, | ||
70 | "%s;%s;%s", | ||
71 | ecdhe_str, aud_str, scopes); | ||
72 | GNUNET_free (aud_str); | ||
73 | GNUNET_free (ecdhe_str); | ||
74 | return result; | ||
75 | |||
76 | default: | ||
77 | return NULL; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | |||
82 | /** | ||
83 | * Convert human-readable version of a 'value' of a record to the binary | ||
84 | * representation. | ||
85 | * | ||
86 | * @param cls closure, unused | ||
87 | * @param type type of the record | ||
88 | * @param s human-readable string | ||
89 | * @param data set to value in binary encoding (will be allocated) | ||
90 | * @param data_size set to number of bytes in @a data | ||
91 | * @return #GNUNET_OK on success | ||
92 | */ | ||
93 | static int | ||
94 | string_to_value (void *cls, | ||
95 | uint32_t type, | ||
96 | const char *s, | ||
97 | void **data, | ||
98 | size_t *data_size) | ||
99 | { | ||
100 | char* ecdhe_str; | ||
101 | char* aud_keystr; | ||
102 | char* write_ptr; | ||
103 | char* tmp_tok; | ||
104 | char* str; | ||
105 | |||
106 | if (NULL == s) | ||
107 | return GNUNET_SYSERR; | ||
108 | switch (type) | ||
109 | { | ||
110 | case GNUNET_GNSRECORD_TYPE_ID_ATTR: | ||
111 | return GNUNET_STRINGS_string_to_data (s, | ||
112 | strlen (s), | ||
113 | *data, | ||
114 | *data_size); | ||
115 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN: | ||
116 | *data = GNUNET_strdup (s); | ||
117 | *data_size = strlen (s); | ||
118 | return GNUNET_OK; | ||
119 | case GNUNET_GNSRECORD_TYPE_ABE_KEY: | ||
120 | case GNUNET_GNSRECORD_TYPE_ABE_MASTER: | ||
121 | return GNUNET_STRINGS_string_to_data (s, | ||
122 | strlen (s), | ||
123 | *data, | ||
124 | *data_size); | ||
125 | case GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA: | ||
126 | tmp_tok = GNUNET_strdup (s); | ||
127 | ecdhe_str = strtok (tmp_tok, ";"); | ||
128 | if (NULL == ecdhe_str) | ||
129 | { | ||
130 | GNUNET_free (tmp_tok); | ||
131 | return GNUNET_SYSERR; | ||
132 | } | ||
133 | aud_keystr = strtok (NULL, ";"); | ||
134 | if (NULL == aud_keystr) | ||
135 | { | ||
136 | GNUNET_free (tmp_tok); | ||
137 | return GNUNET_SYSERR; | ||
138 | } | ||
139 | str = strtok (NULL, ";"); | ||
140 | if (NULL == str) | ||
141 | { | ||
142 | GNUNET_free (tmp_tok); | ||
143 | return GNUNET_SYSERR; | ||
144 | } | ||
145 | *data_size = strlen (str) + 1 | ||
146 | +sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) | ||
147 | +sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
148 | *data = GNUNET_malloc (*data_size); | ||
149 | |||
150 | write_ptr = *data; | ||
151 | GNUNET_STRINGS_string_to_data (ecdhe_str, | ||
152 | strlen (ecdhe_str), | ||
153 | write_ptr, | ||
154 | sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); | ||
155 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey); | ||
156 | GNUNET_STRINGS_string_to_data (aud_keystr, | ||
157 | strlen (aud_keystr), | ||
158 | write_ptr, | ||
159 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
160 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
161 | GNUNET_memcpy (write_ptr, str, strlen (str) + 1); //with 0-Terminator | ||
162 | GNUNET_free (tmp_tok); | ||
163 | return GNUNET_OK; | ||
164 | |||
165 | default: | ||
166 | return GNUNET_SYSERR; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | |||
171 | /** | ||
172 | * Mapping of record type numbers to human-readable | ||
173 | * record type names. | ||
174 | */ | ||
175 | static struct { | ||
176 | const char *name; | ||
177 | uint32_t number; | ||
178 | } name_map[] = { | ||
179 | { "ID_ATTR", GNUNET_GNSRECORD_TYPE_ID_ATTR }, | ||
180 | { "ID_TOKEN", GNUNET_GNSRECORD_TYPE_ID_TOKEN }, | ||
181 | { "ABE_KEY", GNUNET_GNSRECORD_TYPE_ABE_KEY }, | ||
182 | { "ABE_MASTER", GNUNET_GNSRECORD_TYPE_ABE_MASTER }, | ||
183 | { "ID_TOKEN_METADATA", GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA }, | ||
184 | { NULL, UINT32_MAX } | ||
185 | }; | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Convert a type name (i.e. "AAAA") to the corresponding number. | ||
190 | * | ||
191 | * @param cls closure, unused | ||
192 | * @param dns_typename name to convert | ||
193 | * @return corresponding number, UINT32_MAX on error | ||
194 | */ | ||
195 | static uint32_t | ||
196 | typename_to_number (void *cls, | ||
197 | const char *dns_typename) | ||
198 | { | ||
199 | unsigned int i; | ||
200 | |||
201 | i=0; | ||
202 | while ( (NULL != name_map[i].name) && | ||
203 | (0 != strcasecmp (dns_typename, name_map[i].name)) ) | ||
204 | i++; | ||
205 | return name_map[i].number; | ||
206 | } | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") | ||
211 | * | ||
212 | * @param cls closure, unused | ||
213 | * @param type number of a type to convert | ||
214 | * @return corresponding typestring, NULL on error | ||
215 | */ | ||
216 | static const char * | ||
217 | number_to_typename (void *cls, | ||
218 | uint32_t type) | ||
219 | { | ||
220 | unsigned int i; | ||
221 | |||
222 | i=0; | ||
223 | while ( (NULL != name_map[i].name) && | ||
224 | (type != name_map[i].number) ) | ||
225 | i++; | ||
226 | return name_map[i].name; | ||
227 | } | ||
228 | |||
229 | |||
230 | /** | ||
231 | * Entry point for the plugin. | ||
232 | * | ||
233 | * @param cls NULL | ||
234 | * @return the exported block API | ||
235 | */ | ||
236 | void * | ||
237 | libgnunet_plugin_gnsrecord_identity_provider_init (void *cls) | ||
238 | { | ||
239 | struct GNUNET_GNSRECORD_PluginFunctions *api; | ||
240 | |||
241 | api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); | ||
242 | api->value_to_string = &value_to_string; | ||
243 | api->string_to_value = &string_to_value; | ||
244 | api->typename_to_number = &typename_to_number; | ||
245 | api->number_to_typename = &number_to_typename; | ||
246 | return api; | ||
247 | } | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Exit point from the plugin. | ||
252 | * | ||
253 | * @param cls the return value from #libgnunet_plugin_block_test_init | ||
254 | * @return NULL | ||
255 | */ | ||
256 | void * | ||
257 | libgnunet_plugin_gnsrecord_identity_provider_done (void *cls) | ||
258 | { | ||
259 | struct GNUNET_GNSRECORD_PluginFunctions *api = cls; | ||
260 | |||
261 | GNUNET_free (api); | ||
262 | return NULL; | ||
263 | } | ||
264 | |||
265 | /* end of plugin_gnsrecord_dns.c */ | ||
diff --git a/src/identity-provider/plugin_identity_provider_sqlite.c b/src/identity-provider/plugin_identity_provider_sqlite.c deleted file mode 100644 index f2a8b7b54..000000000 --- a/src/identity-provider/plugin_identity_provider_sqlite.c +++ /dev/null | |||
@@ -1,734 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2009-2017 GNUnet e.V. | ||
4 | * | ||
5 | * GNUnet is free software: you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU Affero General Public License as published | ||
7 | * by the Free Software Foundation, either version 3 of the License, | ||
8 | * or (at your option) any later version. | ||
9 | * | ||
10 | * GNUnet is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Affero General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Affero General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @file identity-provider/plugin_identity_provider_sqlite.c | ||
21 | * @brief sqlite-based idp backend | ||
22 | * @author Martin Schanzenbach | ||
23 | */ | ||
24 | |||
25 | #include "platform.h" | ||
26 | #include "gnunet_identity_provider_service.h" | ||
27 | #include "gnunet_identity_provider_plugin.h" | ||
28 | #include "gnunet_identity_attribute_lib.h" | ||
29 | #include "gnunet_sq_lib.h" | ||
30 | #include <sqlite3.h> | ||
31 | |||
32 | /** | ||
33 | * After how many ms "busy" should a DB operation fail for good? A | ||
34 | * low value makes sure that we are more responsive to requests | ||
35 | * (especially PUTs). A high value guarantees a higher success rate | ||
36 | * (SELECTs in iterate can take several seconds despite LIMIT=1). | ||
37 | * | ||
38 | * The default value of 1s should ensure that users do not experience | ||
39 | * huge latencies while at the same time allowing operations to | ||
40 | * succeed with reasonable probability. | ||
41 | */ | ||
42 | #define BUSY_TIMEOUT_MS 1000 | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Log an error message at log-level 'level' that indicates | ||
47 | * a failure of the command 'cmd' on file 'filename' | ||
48 | * with the message given by strerror(errno). | ||
49 | */ | ||
50 | #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "identity-provider", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) | ||
51 | |||
52 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-provider-sqlite", __VA_ARGS__) | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Context for all functions in this plugin. | ||
57 | */ | ||
58 | struct Plugin | ||
59 | { | ||
60 | |||
61 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
62 | |||
63 | /** | ||
64 | * Database filename. | ||
65 | */ | ||
66 | char *fn; | ||
67 | |||
68 | /** | ||
69 | * Native SQLite database handle. | ||
70 | */ | ||
71 | sqlite3 *dbh; | ||
72 | |||
73 | /** | ||
74 | * Precompiled SQL to store ticket. | ||
75 | */ | ||
76 | sqlite3_stmt *store_ticket; | ||
77 | |||
78 | /** | ||
79 | * Precompiled SQL to delete existing ticket. | ||
80 | */ | ||
81 | sqlite3_stmt *delete_ticket; | ||
82 | |||
83 | /** | ||
84 | * Precompiled SQL to iterate tickets. | ||
85 | */ | ||
86 | sqlite3_stmt *iterate_tickets; | ||
87 | |||
88 | /** | ||
89 | * Precompiled SQL to get ticket attributes. | ||
90 | */ | ||
91 | sqlite3_stmt *get_ticket_attrs; | ||
92 | |||
93 | /** | ||
94 | * Precompiled SQL to iterate tickets by audience. | ||
95 | */ | ||
96 | sqlite3_stmt *iterate_tickets_by_audience; | ||
97 | }; | ||
98 | |||
99 | |||
100 | /** | ||
101 | * @brief Prepare a SQL statement | ||
102 | * | ||
103 | * @param dbh handle to the database | ||
104 | * @param zSql SQL statement, UTF-8 encoded | ||
105 | * @param ppStmt set to the prepared statement | ||
106 | * @return 0 on success | ||
107 | */ | ||
108 | static int | ||
109 | sq_prepare (sqlite3 *dbh, | ||
110 | const char *zSql, | ||
111 | sqlite3_stmt **ppStmt) | ||
112 | { | ||
113 | char *dummy; | ||
114 | int result; | ||
115 | |||
116 | result = | ||
117 | sqlite3_prepare_v2 (dbh, | ||
118 | zSql, | ||
119 | strlen (zSql), | ||
120 | ppStmt, | ||
121 | (const char **) &dummy); | ||
122 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
123 | "Prepared `%s' / %p: %d\n", | ||
124 | zSql, | ||
125 | *ppStmt, | ||
126 | result); | ||
127 | return result; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Create our database indices. | ||
132 | * | ||
133 | * @param dbh handle to the database | ||
134 | */ | ||
135 | static void | ||
136 | create_indices (sqlite3 * dbh) | ||
137 | { | ||
138 | /* create indices */ | ||
139 | if ( (SQLITE_OK != | ||
140 | sqlite3_exec (dbh, | ||
141 | "CREATE INDEX IF NOT EXISTS identity_reverse ON identity001tickets (identity,audience)", | ||
142 | NULL, NULL, NULL)) || | ||
143 | (SQLITE_OK != | ||
144 | sqlite3_exec (dbh, | ||
145 | "CREATE INDEX IF NOT EXISTS it_iter ON identity001tickets (rnd)", | ||
146 | NULL, NULL, NULL)) ) | ||
147 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
148 | "Failed to create indices: %s\n", | ||
149 | sqlite3_errmsg (dbh)); | ||
150 | } | ||
151 | |||
152 | |||
153 | |||
154 | #if 0 | ||
155 | #define CHECK(a) GNUNET_break(a) | ||
156 | #define ENULL NULL | ||
157 | #else | ||
158 | #define ENULL &e | ||
159 | #define ENULL_DEFINED 1 | ||
160 | #define CHECK(a) if (! (a)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); } | ||
161 | #endif | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Initialize the database connections and associated | ||
166 | * data structures (create tables and indices | ||
167 | * as needed as well). | ||
168 | * | ||
169 | * @param plugin the plugin context (state for this module) | ||
170 | * @return #GNUNET_OK on success | ||
171 | */ | ||
172 | static int | ||
173 | database_setup (struct Plugin *plugin) | ||
174 | { | ||
175 | sqlite3_stmt *stmt; | ||
176 | char *afsdir; | ||
177 | #if ENULL_DEFINED | ||
178 | char *e; | ||
179 | #endif | ||
180 | |||
181 | if (GNUNET_OK != | ||
182 | GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, | ||
183 | "identity-provider-sqlite", | ||
184 | "FILENAME", | ||
185 | &afsdir)) | ||
186 | { | ||
187 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
188 | "identity-provider-sqlite", | ||
189 | "FILENAME"); | ||
190 | return GNUNET_SYSERR; | ||
191 | } | ||
192 | if (GNUNET_OK != | ||
193 | GNUNET_DISK_file_test (afsdir)) | ||
194 | { | ||
195 | if (GNUNET_OK != | ||
196 | GNUNET_DISK_directory_create_for_file (afsdir)) | ||
197 | { | ||
198 | GNUNET_break (0); | ||
199 | GNUNET_free (afsdir); | ||
200 | return GNUNET_SYSERR; | ||
201 | } | ||
202 | } | ||
203 | /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ | ||
204 | plugin->fn = afsdir; | ||
205 | |||
206 | /* Open database and precompile statements */ | ||
207 | if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) | ||
208 | { | ||
209 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
210 | _("Unable to initialize SQLite: %s.\n"), | ||
211 | sqlite3_errmsg (plugin->dbh)); | ||
212 | return GNUNET_SYSERR; | ||
213 | } | ||
214 | CHECK (SQLITE_OK == | ||
215 | sqlite3_exec (plugin->dbh, | ||
216 | "PRAGMA temp_store=MEMORY", NULL, NULL, | ||
217 | ENULL)); | ||
218 | CHECK (SQLITE_OK == | ||
219 | sqlite3_exec (plugin->dbh, | ||
220 | "PRAGMA synchronous=NORMAL", NULL, NULL, | ||
221 | ENULL)); | ||
222 | CHECK (SQLITE_OK == | ||
223 | sqlite3_exec (plugin->dbh, | ||
224 | "PRAGMA legacy_file_format=OFF", NULL, NULL, | ||
225 | ENULL)); | ||
226 | CHECK (SQLITE_OK == | ||
227 | sqlite3_exec (plugin->dbh, | ||
228 | "PRAGMA auto_vacuum=INCREMENTAL", NULL, | ||
229 | NULL, ENULL)); | ||
230 | CHECK (SQLITE_OK == | ||
231 | sqlite3_exec (plugin->dbh, | ||
232 | "PRAGMA encoding=\"UTF-8\"", NULL, | ||
233 | NULL, ENULL)); | ||
234 | CHECK (SQLITE_OK == | ||
235 | sqlite3_exec (plugin->dbh, | ||
236 | "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, | ||
237 | ENULL)); | ||
238 | CHECK (SQLITE_OK == | ||
239 | sqlite3_exec (plugin->dbh, | ||
240 | "PRAGMA page_size=4092", NULL, NULL, | ||
241 | ENULL)); | ||
242 | |||
243 | CHECK (SQLITE_OK == | ||
244 | sqlite3_busy_timeout (plugin->dbh, | ||
245 | BUSY_TIMEOUT_MS)); | ||
246 | |||
247 | |||
248 | /* Create table */ | ||
249 | CHECK (SQLITE_OK == | ||
250 | sq_prepare (plugin->dbh, | ||
251 | "SELECT 1 FROM sqlite_master WHERE tbl_name = 'identity001tickets'", | ||
252 | &stmt)); | ||
253 | if ((sqlite3_step (stmt) == SQLITE_DONE) && | ||
254 | (sqlite3_exec | ||
255 | (plugin->dbh, | ||
256 | "CREATE TABLE identity001tickets (" | ||
257 | " identity BLOB NOT NULL DEFAULT ''," | ||
258 | " audience BLOB NOT NULL DEFAULT ''," | ||
259 | " rnd INT8 NOT NULL DEFAULT ''," | ||
260 | " attributes BLOB NOT NULL DEFAULT ''" | ||
261 | ")", | ||
262 | NULL, NULL, NULL) != SQLITE_OK)) | ||
263 | { | ||
264 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, | ||
265 | "sqlite3_exec"); | ||
266 | sqlite3_finalize (stmt); | ||
267 | return GNUNET_SYSERR; | ||
268 | } | ||
269 | sqlite3_finalize (stmt); | ||
270 | |||
271 | create_indices (plugin->dbh); | ||
272 | |||
273 | if ( (SQLITE_OK != | ||
274 | sq_prepare (plugin->dbh, | ||
275 | "INSERT INTO identity001tickets (identity, audience, rnd, attributes)" | ||
276 | " VALUES (?, ?, ?, ?)", | ||
277 | &plugin->store_ticket)) || | ||
278 | (SQLITE_OK != | ||
279 | sq_prepare (plugin->dbh, | ||
280 | "DELETE FROM identity001tickets WHERE identity=? AND rnd=?", | ||
281 | &plugin->delete_ticket)) || | ||
282 | (SQLITE_OK != | ||
283 | sq_prepare (plugin->dbh, | ||
284 | "SELECT identity,audience,rnd,attributes" | ||
285 | " FROM identity001tickets WHERE identity=? AND rnd=?", | ||
286 | &plugin->get_ticket_attrs)) || | ||
287 | (SQLITE_OK != | ||
288 | sq_prepare (plugin->dbh, | ||
289 | "SELECT identity,audience,rnd,attributes" | ||
290 | " FROM identity001tickets WHERE identity=?" | ||
291 | " ORDER BY rnd LIMIT 1 OFFSET ?", | ||
292 | &plugin->iterate_tickets)) || | ||
293 | (SQLITE_OK != | ||
294 | sq_prepare (plugin->dbh, | ||
295 | "SELECT identity,audience,rnd,attributes" | ||
296 | " FROM identity001tickets WHERE audience=?" | ||
297 | " ORDER BY rnd LIMIT 1 OFFSET ?", | ||
298 | &plugin->iterate_tickets_by_audience)) ) | ||
299 | { | ||
300 | LOG_SQLITE (plugin, | ||
301 | GNUNET_ERROR_TYPE_ERROR, | ||
302 | "precompiling"); | ||
303 | return GNUNET_SYSERR; | ||
304 | } | ||
305 | return GNUNET_OK; | ||
306 | } | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Shutdown database connection and associate data | ||
311 | * structures. | ||
312 | * @param plugin the plugin context (state for this module) | ||
313 | */ | ||
314 | static void | ||
315 | database_shutdown (struct Plugin *plugin) | ||
316 | { | ||
317 | int result; | ||
318 | sqlite3_stmt *stmt; | ||
319 | |||
320 | if (NULL != plugin->store_ticket) | ||
321 | sqlite3_finalize (plugin->store_ticket); | ||
322 | if (NULL != plugin->delete_ticket) | ||
323 | sqlite3_finalize (plugin->delete_ticket); | ||
324 | if (NULL != plugin->iterate_tickets) | ||
325 | sqlite3_finalize (plugin->iterate_tickets); | ||
326 | if (NULL != plugin->iterate_tickets_by_audience) | ||
327 | sqlite3_finalize (plugin->iterate_tickets_by_audience); | ||
328 | if (NULL != plugin->get_ticket_attrs) | ||
329 | sqlite3_finalize (plugin->get_ticket_attrs); | ||
330 | result = sqlite3_close (plugin->dbh); | ||
331 | if (result == SQLITE_BUSY) | ||
332 | { | ||
333 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
334 | _("Tried to close sqlite without finalizing all prepared statements.\n")); | ||
335 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
336 | NULL); | ||
337 | while (NULL != stmt) | ||
338 | { | ||
339 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
340 | "sqlite", | ||
341 | "Closing statement %p\n", | ||
342 | stmt); | ||
343 | result = sqlite3_finalize (stmt); | ||
344 | if (result != SQLITE_OK) | ||
345 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
346 | "sqlite", | ||
347 | "Failed to close statement %p: %d\n", | ||
348 | stmt, | ||
349 | result); | ||
350 | stmt = sqlite3_next_stmt (plugin->dbh, | ||
351 | NULL); | ||
352 | } | ||
353 | result = sqlite3_close (plugin->dbh); | ||
354 | } | ||
355 | if (SQLITE_OK != result) | ||
356 | LOG_SQLITE (plugin, | ||
357 | GNUNET_ERROR_TYPE_ERROR, | ||
358 | "sqlite3_close"); | ||
359 | |||
360 | GNUNET_free_non_null (plugin->fn); | ||
361 | } | ||
362 | |||
363 | |||
364 | /** | ||
365 | * Store a ticket in the database. | ||
366 | * | ||
367 | * @param cls closure (internal context for the plugin) | ||
368 | * @param ticket the ticket to persist | ||
369 | * @param attrs the attributes associated with the ticket | ||
370 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
371 | */ | ||
372 | static int | ||
373 | identity_provider_sqlite_store_ticket (void *cls, | ||
374 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
375 | const struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs) | ||
376 | { | ||
377 | struct Plugin *plugin = cls; | ||
378 | size_t attrs_len; | ||
379 | char *attrs_ser; | ||
380 | int n; | ||
381 | |||
382 | { | ||
383 | /* First delete duplicates */ | ||
384 | struct GNUNET_SQ_QueryParam dparams[] = { | ||
385 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
386 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
387 | GNUNET_SQ_query_param_end | ||
388 | }; | ||
389 | if (GNUNET_OK != | ||
390 | GNUNET_SQ_bind (plugin->delete_ticket, | ||
391 | dparams)) | ||
392 | { | ||
393 | LOG_SQLITE (plugin, | ||
394 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
395 | "sqlite3_bind_XXXX"); | ||
396 | GNUNET_SQ_reset (plugin->dbh, | ||
397 | plugin->delete_ticket); | ||
398 | return GNUNET_SYSERR; | ||
399 | } | ||
400 | n = sqlite3_step (plugin->delete_ticket); | ||
401 | GNUNET_SQ_reset (plugin->dbh, | ||
402 | plugin->delete_ticket); | ||
403 | |||
404 | attrs_len = GNUNET_IDENTITY_ATTRIBUTE_list_serialize_get_size (attrs); | ||
405 | attrs_ser = GNUNET_malloc (attrs_len); | ||
406 | GNUNET_IDENTITY_ATTRIBUTE_list_serialize (attrs, | ||
407 | attrs_ser); | ||
408 | struct GNUNET_SQ_QueryParam sparams[] = { | ||
409 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
410 | GNUNET_SQ_query_param_auto_from_type (&ticket->audience), | ||
411 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
412 | GNUNET_SQ_query_param_fixed_size (attrs_ser, attrs_len), | ||
413 | GNUNET_SQ_query_param_end | ||
414 | }; | ||
415 | |||
416 | if (GNUNET_OK != | ||
417 | GNUNET_SQ_bind (plugin->store_ticket, | ||
418 | sparams)) | ||
419 | { | ||
420 | LOG_SQLITE (plugin, | ||
421 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
422 | "sqlite3_bind_XXXX"); | ||
423 | GNUNET_SQ_reset (plugin->dbh, | ||
424 | plugin->store_ticket); | ||
425 | return GNUNET_SYSERR; | ||
426 | } | ||
427 | n = sqlite3_step (plugin->store_ticket); | ||
428 | GNUNET_SQ_reset (plugin->dbh, | ||
429 | plugin->store_ticket); | ||
430 | GNUNET_free (attrs_ser); | ||
431 | } | ||
432 | switch (n) | ||
433 | { | ||
434 | case SQLITE_DONE: | ||
435 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
436 | "sqlite", | ||
437 | "Ticket stored\n"); | ||
438 | return GNUNET_OK; | ||
439 | case SQLITE_BUSY: | ||
440 | LOG_SQLITE (plugin, | ||
441 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
442 | "sqlite3_step"); | ||
443 | return GNUNET_NO; | ||
444 | default: | ||
445 | LOG_SQLITE (plugin, | ||
446 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
447 | "sqlite3_step"); | ||
448 | return GNUNET_SYSERR; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | |||
453 | /** | ||
454 | * Store a ticket in the database. | ||
455 | * | ||
456 | * @param cls closure (internal context for the plugin) | ||
457 | * @param ticket the ticket to delete | ||
458 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
459 | */ | ||
460 | static int | ||
461 | identity_provider_sqlite_delete_ticket (void *cls, | ||
462 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | ||
463 | { | ||
464 | struct Plugin *plugin = cls; | ||
465 | int n; | ||
466 | |||
467 | { | ||
468 | struct GNUNET_SQ_QueryParam sparams[] = { | ||
469 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
470 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
471 | GNUNET_SQ_query_param_end | ||
472 | }; | ||
473 | |||
474 | if (GNUNET_OK != | ||
475 | GNUNET_SQ_bind (plugin->delete_ticket, | ||
476 | sparams)) | ||
477 | { | ||
478 | LOG_SQLITE (plugin, | ||
479 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
480 | "sqlite3_bind_XXXX"); | ||
481 | GNUNET_SQ_reset (plugin->dbh, | ||
482 | plugin->store_ticket); | ||
483 | return GNUNET_SYSERR; | ||
484 | } | ||
485 | n = sqlite3_step (plugin->delete_ticket); | ||
486 | GNUNET_SQ_reset (plugin->dbh, | ||
487 | plugin->delete_ticket); | ||
488 | } | ||
489 | switch (n) | ||
490 | { | ||
491 | case SQLITE_DONE: | ||
492 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
493 | "sqlite", | ||
494 | "Ticket deleted\n"); | ||
495 | return GNUNET_OK; | ||
496 | case SQLITE_BUSY: | ||
497 | LOG_SQLITE (plugin, | ||
498 | GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, | ||
499 | "sqlite3_step"); | ||
500 | return GNUNET_NO; | ||
501 | default: | ||
502 | LOG_SQLITE (plugin, | ||
503 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
504 | "sqlite3_step"); | ||
505 | return GNUNET_SYSERR; | ||
506 | } | ||
507 | } | ||
508 | |||
509 | |||
510 | /** | ||
511 | * The given 'sqlite' statement has been prepared to be run. | ||
512 | * It will return a record which should be given to the iterator. | ||
513 | * Runs the statement and parses the returned record. | ||
514 | * | ||
515 | * @param plugin plugin context | ||
516 | * @param stmt to run (and then clean up) | ||
517 | * @param iter iterator to call with the result | ||
518 | * @param iter_cls closure for @a iter | ||
519 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
520 | */ | ||
521 | static int | ||
522 | get_ticket_and_call_iterator (struct Plugin *plugin, | ||
523 | sqlite3_stmt *stmt, | ||
524 | GNUNET_IDENTITY_PROVIDER_TicketIterator iter, | ||
525 | void *iter_cls) | ||
526 | { | ||
527 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
528 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attrs; | ||
529 | int ret; | ||
530 | int sret; | ||
531 | size_t attrs_len; | ||
532 | char *attrs_ser; | ||
533 | |||
534 | ret = GNUNET_NO; | ||
535 | if (SQLITE_ROW == (sret = sqlite3_step (stmt))) | ||
536 | { | ||
537 | struct GNUNET_SQ_ResultSpec rs[] = { | ||
538 | GNUNET_SQ_result_spec_auto_from_type (&ticket.identity), | ||
539 | GNUNET_SQ_result_spec_auto_from_type (&ticket.audience), | ||
540 | GNUNET_SQ_result_spec_uint64 (&ticket.rnd), | ||
541 | GNUNET_SQ_result_spec_variable_size ((void**)&attrs_ser, | ||
542 | &attrs_len), | ||
543 | GNUNET_SQ_result_spec_end | ||
544 | |||
545 | }; | ||
546 | ret = GNUNET_SQ_extract_result (stmt, | ||
547 | rs); | ||
548 | if (GNUNET_OK != ret) | ||
549 | { | ||
550 | GNUNET_break (0); | ||
551 | ret = GNUNET_SYSERR; | ||
552 | } | ||
553 | else | ||
554 | { | ||
555 | attrs = GNUNET_IDENTITY_ATTRIBUTE_list_deserialize (attrs_ser, | ||
556 | attrs_len); | ||
557 | if (NULL != iter) | ||
558 | iter (iter_cls, | ||
559 | &ticket, | ||
560 | attrs); | ||
561 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy (attrs); | ||
562 | ret = GNUNET_YES; | ||
563 | } | ||
564 | GNUNET_SQ_cleanup_result (rs); | ||
565 | } | ||
566 | else | ||
567 | { | ||
568 | if (SQLITE_DONE != sret) | ||
569 | LOG_SQLITE (plugin, | ||
570 | GNUNET_ERROR_TYPE_ERROR, | ||
571 | "sqlite_step"); | ||
572 | } | ||
573 | GNUNET_SQ_reset (plugin->dbh, | ||
574 | stmt); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Lookup tickets in the datastore. | ||
581 | * | ||
582 | * @param cls closure (internal context for the plugin) | ||
583 | * @param ticket the ticket to retrieve attributes for | ||
584 | * @param iter function to call with the result | ||
585 | * @param iter_cls closure for @a iter | ||
586 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
587 | */ | ||
588 | static int | ||
589 | identity_provider_sqlite_ticket_get_attrs (void *cls, | ||
590 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket, | ||
591 | GNUNET_IDENTITY_PROVIDER_TicketIterator iter, | ||
592 | void *iter_cls) | ||
593 | { | ||
594 | struct Plugin *plugin = cls; | ||
595 | struct GNUNET_SQ_QueryParam params[] = { | ||
596 | GNUNET_SQ_query_param_auto_from_type (&ticket->identity), | ||
597 | GNUNET_SQ_query_param_uint64 (&ticket->rnd), | ||
598 | GNUNET_SQ_query_param_end | ||
599 | }; | ||
600 | |||
601 | if (GNUNET_OK != | ||
602 | GNUNET_SQ_bind (plugin->get_ticket_attrs, | ||
603 | params)) | ||
604 | { | ||
605 | LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
606 | "sqlite3_bind_XXXX"); | ||
607 | GNUNET_SQ_reset (plugin->dbh, | ||
608 | plugin->get_ticket_attrs); | ||
609 | return GNUNET_SYSERR; | ||
610 | } | ||
611 | return get_ticket_and_call_iterator (plugin, | ||
612 | plugin->get_ticket_attrs, | ||
613 | iter, | ||
614 | iter_cls); | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * Iterate over the results for a particular key and zone in the | ||
620 | * datastore. Will return at most one result to the iterator. | ||
621 | * | ||
622 | * @param cls closure (internal context for the plugin) | ||
623 | * @param identity the issuing identity or audience (depending on audience switch) | ||
624 | * @param audience GNUNET_YES if identity is audience | ||
625 | * @param offset offset in the list of all matching records | ||
626 | * @param iter function to call with the result | ||
627 | * @param iter_cls closure for @a iter | ||
628 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
629 | */ | ||
630 | static int | ||
631 | identity_provider_sqlite_iterate_tickets (void *cls, | ||
632 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
633 | int audience, | ||
634 | uint64_t offset, | ||
635 | GNUNET_IDENTITY_PROVIDER_TicketIterator iter, | ||
636 | void *iter_cls) | ||
637 | { | ||
638 | struct Plugin *plugin = cls; | ||
639 | sqlite3_stmt *stmt; | ||
640 | int err; | ||
641 | |||
642 | if (NULL == identity) | ||
643 | { | ||
644 | GNUNET_break (0); | ||
645 | return GNUNET_SYSERR; | ||
646 | } | ||
647 | struct GNUNET_SQ_QueryParam params[] = { | ||
648 | GNUNET_SQ_query_param_auto_from_type (identity), | ||
649 | GNUNET_SQ_query_param_uint64 (&offset), | ||
650 | GNUNET_SQ_query_param_end | ||
651 | }; | ||
652 | if (GNUNET_YES == audience) | ||
653 | { | ||
654 | stmt = plugin->iterate_tickets_by_audience; | ||
655 | err = GNUNET_SQ_bind (stmt, | ||
656 | params); | ||
657 | } | ||
658 | else | ||
659 | { | ||
660 | stmt = plugin->iterate_tickets; | ||
661 | err = GNUNET_SQ_bind (stmt, | ||
662 | params); | ||
663 | } | ||
664 | if (GNUNET_OK != err) | ||
665 | { | ||
666 | LOG_SQLITE (plugin, | ||
667 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
668 | "sqlite3_bind_XXXX"); | ||
669 | GNUNET_SQ_reset (plugin->dbh, | ||
670 | stmt); | ||
671 | return GNUNET_SYSERR; | ||
672 | } | ||
673 | return get_ticket_and_call_iterator (plugin, | ||
674 | stmt, | ||
675 | iter, | ||
676 | iter_cls); | ||
677 | } | ||
678 | |||
679 | |||
680 | /** | ||
681 | * Entry point for the plugin. | ||
682 | * | ||
683 | * @param cls the "struct GNUNET_IDENTITY_PROVIDER_PluginEnvironment*" | ||
684 | * @return NULL on error, otherwise the plugin context | ||
685 | */ | ||
686 | void * | ||
687 | libgnunet_plugin_identity_provider_sqlite_init (void *cls) | ||
688 | { | ||
689 | static struct Plugin plugin; | ||
690 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
691 | struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api; | ||
692 | |||
693 | if (NULL != plugin.cfg) | ||
694 | return NULL; /* can only initialize once! */ | ||
695 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
696 | plugin.cfg = cfg; | ||
697 | if (GNUNET_OK != database_setup (&plugin)) | ||
698 | { | ||
699 | database_shutdown (&plugin); | ||
700 | return NULL; | ||
701 | } | ||
702 | api = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_PluginFunctions); | ||
703 | api->cls = &plugin; | ||
704 | api->store_ticket = &identity_provider_sqlite_store_ticket; | ||
705 | api->delete_ticket = &identity_provider_sqlite_delete_ticket; | ||
706 | api->iterate_tickets = &identity_provider_sqlite_iterate_tickets; | ||
707 | api->get_ticket_attributes = &identity_provider_sqlite_ticket_get_attrs; | ||
708 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
709 | _("Sqlite database running\n")); | ||
710 | return api; | ||
711 | } | ||
712 | |||
713 | |||
714 | /** | ||
715 | * Exit point from the plugin. | ||
716 | * | ||
717 | * @param cls the plugin context (as returned by "init") | ||
718 | * @return always NULL | ||
719 | */ | ||
720 | void * | ||
721 | libgnunet_plugin_identity_provider_sqlite_done (void *cls) | ||
722 | { | ||
723 | struct GNUNET_IDENTITY_PROVIDER_PluginFunctions *api = cls; | ||
724 | struct Plugin *plugin = api->cls; | ||
725 | |||
726 | database_shutdown (plugin); | ||
727 | plugin->cfg = NULL; | ||
728 | GNUNET_free (api); | ||
729 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
730 | "sqlite plugin is finished\n"); | ||
731 | return NULL; | ||
732 | } | ||
733 | |||
734 | /* end of plugin_identity_provider_sqlite.c */ | ||
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c deleted file mode 100644 index a83163db2..000000000 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ /dev/null | |||
@@ -1,1253 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @author Philippe Buschmann | ||
21 | * @file identity/plugin_rest_identity.c | ||
22 | * @brief GNUnet Namestore REST plugin | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_rest_plugin.h" | ||
28 | #include "gnunet_identity_service.h" | ||
29 | #include "gnunet_gns_service.h" | ||
30 | #include "gnunet_gnsrecord_lib.h" | ||
31 | #include "gnunet_namestore_service.h" | ||
32 | #include "gnunet_rest_lib.h" | ||
33 | #include "gnunet_jsonapi_lib.h" | ||
34 | #include "gnunet_jsonapi_util.h" | ||
35 | #include "microhttpd.h" | ||
36 | #include <jansson.h> | ||
37 | #include <inttypes.h> | ||
38 | #include "gnunet_signatures.h" | ||
39 | #include "gnunet_identity_attribute_lib.h" | ||
40 | #include "gnunet_identity_provider_service.h" | ||
41 | |||
42 | /** | ||
43 | * REST root namespace | ||
44 | */ | ||
45 | #define GNUNET_REST_API_NS_IDENTITY_PROVIDER "/idp" | ||
46 | |||
47 | /** | ||
48 | * Attribute namespace | ||
49 | */ | ||
50 | #define GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES "/idp/attributes" | ||
51 | |||
52 | /** | ||
53 | * Ticket namespace | ||
54 | */ | ||
55 | #define GNUNET_REST_API_NS_IDENTITY_TICKETS "/idp/tickets" | ||
56 | |||
57 | /** | ||
58 | * Revoke namespace | ||
59 | */ | ||
60 | #define GNUNET_REST_API_NS_IDENTITY_REVOKE "/idp/revoke" | ||
61 | |||
62 | /** | ||
63 | * Revoke namespace | ||
64 | */ | ||
65 | #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" | ||
66 | |||
67 | /** | ||
68 | * Attribute key | ||
69 | */ | ||
70 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" | ||
71 | |||
72 | /** | ||
73 | * Ticket key | ||
74 | */ | ||
75 | #define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" | ||
76 | |||
77 | |||
78 | /** | ||
79 | * Value key | ||
80 | */ | ||
81 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value" | ||
82 | |||
83 | /** | ||
84 | * State while collecting all egos | ||
85 | */ | ||
86 | #define ID_REST_STATE_INIT 0 | ||
87 | |||
88 | /** | ||
89 | * Done collecting egos | ||
90 | */ | ||
91 | #define ID_REST_STATE_POST_INIT 1 | ||
92 | |||
93 | /** | ||
94 | * The configuration handle | ||
95 | */ | ||
96 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
97 | |||
98 | /** | ||
99 | * HTTP methods allows for this plugin | ||
100 | */ | ||
101 | static char* allow_methods; | ||
102 | |||
103 | /** | ||
104 | * @brief struct returned by the initialization function of the plugin | ||
105 | */ | ||
106 | struct Plugin | ||
107 | { | ||
108 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
109 | }; | ||
110 | |||
111 | /** | ||
112 | * The ego list | ||
113 | */ | ||
114 | struct EgoEntry | ||
115 | { | ||
116 | /** | ||
117 | * DLL | ||
118 | */ | ||
119 | struct EgoEntry *next; | ||
120 | |||
121 | /** | ||
122 | * DLL | ||
123 | */ | ||
124 | struct EgoEntry *prev; | ||
125 | |||
126 | /** | ||
127 | * Ego Identifier | ||
128 | */ | ||
129 | char *identifier; | ||
130 | |||
131 | /** | ||
132 | * Public key string | ||
133 | */ | ||
134 | char *keystring; | ||
135 | |||
136 | /** | ||
137 | * The Ego | ||
138 | */ | ||
139 | struct GNUNET_IDENTITY_Ego *ego; | ||
140 | }; | ||
141 | |||
142 | |||
143 | struct RequestHandle | ||
144 | { | ||
145 | /** | ||
146 | * Ego list | ||
147 | */ | ||
148 | struct EgoEntry *ego_head; | ||
149 | |||
150 | /** | ||
151 | * Ego list | ||
152 | */ | ||
153 | struct EgoEntry *ego_tail; | ||
154 | |||
155 | /** | ||
156 | * Selected ego | ||
157 | */ | ||
158 | struct EgoEntry *ego_entry; | ||
159 | |||
160 | /** | ||
161 | * Pointer to ego private key | ||
162 | */ | ||
163 | struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; | ||
164 | |||
165 | /** | ||
166 | * The processing state | ||
167 | */ | ||
168 | int state; | ||
169 | |||
170 | /** | ||
171 | * Handle to Identity service. | ||
172 | */ | ||
173 | struct GNUNET_IDENTITY_Handle *identity_handle; | ||
174 | |||
175 | /** | ||
176 | * Rest connection | ||
177 | */ | ||
178 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
179 | |||
180 | /** | ||
181 | * Handle to NAMESTORE | ||
182 | */ | ||
183 | struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
184 | |||
185 | /** | ||
186 | * Iterator for NAMESTORE | ||
187 | */ | ||
188 | struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; | ||
189 | |||
190 | /** | ||
191 | * Attribute claim list | ||
192 | */ | ||
193 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; | ||
194 | |||
195 | /** | ||
196 | * IDENTITY Operation | ||
197 | */ | ||
198 | struct GNUNET_IDENTITY_Operation *op; | ||
199 | |||
200 | /** | ||
201 | * Identity Provider | ||
202 | */ | ||
203 | struct GNUNET_IDENTITY_PROVIDER_Handle *idp; | ||
204 | |||
205 | /** | ||
206 | * Idp Operation | ||
207 | */ | ||
208 | struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; | ||
209 | |||
210 | /** | ||
211 | * Attribute iterator | ||
212 | */ | ||
213 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it; | ||
214 | |||
215 | /** | ||
216 | * Ticket iterator | ||
217 | */ | ||
218 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it; | ||
219 | |||
220 | /** | ||
221 | * A ticket | ||
222 | */ | ||
223 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
224 | |||
225 | /** | ||
226 | * Desired timeout for the lookup (default is no timeout). | ||
227 | */ | ||
228 | struct GNUNET_TIME_Relative timeout; | ||
229 | |||
230 | /** | ||
231 | * ID of a task associated with the resolution process. | ||
232 | */ | ||
233 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
234 | |||
235 | /** | ||
236 | * The plugin result processor | ||
237 | */ | ||
238 | GNUNET_REST_ResultProcessor proc; | ||
239 | |||
240 | /** | ||
241 | * The closure of the result processor | ||
242 | */ | ||
243 | void *proc_cls; | ||
244 | |||
245 | /** | ||
246 | * The url | ||
247 | */ | ||
248 | char *url; | ||
249 | |||
250 | /** | ||
251 | * Error response message | ||
252 | */ | ||
253 | char *emsg; | ||
254 | |||
255 | /** | ||
256 | * Reponse code | ||
257 | */ | ||
258 | int response_code; | ||
259 | |||
260 | /** | ||
261 | * Response object | ||
262 | */ | ||
263 | struct GNUNET_JSONAPI_Document *resp_object; | ||
264 | |||
265 | }; | ||
266 | |||
267 | /** | ||
268 | * Cleanup lookup handle | ||
269 | * @param handle Handle to clean up | ||
270 | */ | ||
271 | static void | ||
272 | cleanup_handle (struct RequestHandle *handle) | ||
273 | { | ||
274 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry; | ||
275 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp; | ||
276 | struct EgoEntry *ego_entry; | ||
277 | struct EgoEntry *ego_tmp; | ||
278 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
279 | "Cleaning up\n"); | ||
280 | if (NULL != handle->resp_object) | ||
281 | GNUNET_JSONAPI_document_delete (handle->resp_object); | ||
282 | if (NULL != handle->timeout_task) | ||
283 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
284 | if (NULL != handle->identity_handle) | ||
285 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | ||
286 | if (NULL != handle->attr_it) | ||
287 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it); | ||
288 | if (NULL != handle->ticket_it) | ||
289 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it); | ||
290 | if (NULL != handle->idp) | ||
291 | GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); | ||
292 | if (NULL != handle->url) | ||
293 | GNUNET_free (handle->url); | ||
294 | if (NULL != handle->emsg) | ||
295 | GNUNET_free (handle->emsg); | ||
296 | if (NULL != handle->namestore_handle) | ||
297 | GNUNET_NAMESTORE_disconnect (handle->namestore_handle); | ||
298 | if ( NULL != handle->attr_list ) | ||
299 | { | ||
300 | for (claim_entry = handle->attr_list->list_head; | ||
301 | NULL != claim_entry;) | ||
302 | { | ||
303 | claim_tmp = claim_entry; | ||
304 | claim_entry = claim_entry->next; | ||
305 | GNUNET_free(claim_tmp->claim); | ||
306 | GNUNET_free(claim_tmp); | ||
307 | } | ||
308 | GNUNET_free (handle->attr_list); | ||
309 | } | ||
310 | for (ego_entry = handle->ego_head; | ||
311 | NULL != ego_entry;) | ||
312 | { | ||
313 | ego_tmp = ego_entry; | ||
314 | ego_entry = ego_entry->next; | ||
315 | GNUNET_free (ego_tmp->identifier); | ||
316 | GNUNET_free (ego_tmp->keystring); | ||
317 | GNUNET_free (ego_tmp); | ||
318 | } | ||
319 | if (NULL != handle->attr_it) | ||
320 | { | ||
321 | GNUNET_free(handle->attr_it); | ||
322 | } | ||
323 | GNUNET_free (handle); | ||
324 | } | ||
325 | |||
326 | static void | ||
327 | cleanup_handle_delayed (void *cls) | ||
328 | { | ||
329 | cleanup_handle (cls); | ||
330 | } | ||
331 | |||
332 | |||
333 | /** | ||
334 | * Task run on error, sends error message. Cleans up everything. | ||
335 | * | ||
336 | * @param cls the `struct RequestHandle` | ||
337 | */ | ||
338 | static void | ||
339 | do_error (void *cls) | ||
340 | { | ||
341 | struct RequestHandle *handle = cls; | ||
342 | struct MHD_Response *resp; | ||
343 | char *json_error; | ||
344 | |||
345 | GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\" }", | ||
346 | handle->emsg); | ||
347 | if ( 0 == handle->response_code ) | ||
348 | { | ||
349 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
350 | } | ||
351 | resp = GNUNET_REST_create_response (json_error); | ||
352 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
353 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
354 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
355 | GNUNET_free (json_error); | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Task run on timeout, sends error message. Cleans up everything. | ||
361 | * | ||
362 | * @param cls the `struct RequestHandle` | ||
363 | */ | ||
364 | static void | ||
365 | do_timeout (void *cls) | ||
366 | { | ||
367 | struct RequestHandle *handle = cls; | ||
368 | |||
369 | handle->timeout_task = NULL; | ||
370 | do_error (handle); | ||
371 | } | ||
372 | |||
373 | |||
374 | static void | ||
375 | collect_error_cb (void *cls) | ||
376 | { | ||
377 | struct RequestHandle *handle = cls; | ||
378 | |||
379 | do_error (handle); | ||
380 | } | ||
381 | |||
382 | static void | ||
383 | finished_cont (void *cls, | ||
384 | int32_t success, | ||
385 | const char *emsg) | ||
386 | { | ||
387 | struct RequestHandle *handle = cls; | ||
388 | struct MHD_Response *resp; | ||
389 | |||
390 | resp = GNUNET_REST_create_response (emsg); | ||
391 | if (GNUNET_OK != success) | ||
392 | { | ||
393 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
394 | return; | ||
395 | } | ||
396 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
397 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Return attributes for identity | ||
403 | * | ||
404 | * @param cls the request handle | ||
405 | */ | ||
406 | static void | ||
407 | return_response (void *cls) | ||
408 | { | ||
409 | char* result_str; | ||
410 | struct RequestHandle *handle = cls; | ||
411 | struct MHD_Response *resp; | ||
412 | |||
413 | GNUNET_JSONAPI_document_serialize (handle->resp_object, &result_str); | ||
414 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
415 | resp = GNUNET_REST_create_response (result_str); | ||
416 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
417 | GNUNET_free (result_str); | ||
418 | cleanup_handle (handle); | ||
419 | } | ||
420 | |||
421 | static void | ||
422 | collect_finished_cb (void *cls) | ||
423 | { | ||
424 | struct RequestHandle *handle = cls; | ||
425 | //Done | ||
426 | handle->attr_it = NULL; | ||
427 | handle->ticket_it = NULL; | ||
428 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
429 | } | ||
430 | |||
431 | |||
432 | /** | ||
433 | * Collect all attributes for an ego | ||
434 | * | ||
435 | */ | ||
436 | static void | ||
437 | ticket_collect (void *cls, | ||
438 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | ||
439 | { | ||
440 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
441 | struct RequestHandle *handle = cls; | ||
442 | json_t *value; | ||
443 | char* tmp; | ||
444 | |||
445 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding ticket\n"); | ||
446 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
447 | sizeof (uint64_t)); | ||
448 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_TICKET, | ||
449 | tmp); | ||
450 | GNUNET_free (tmp); | ||
451 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | ||
452 | |||
453 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->identity, | ||
454 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
455 | value = json_string (tmp); | ||
456 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
457 | "issuer", | ||
458 | value); | ||
459 | GNUNET_free (tmp); | ||
460 | json_decref (value); | ||
461 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->audience, | ||
462 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
463 | value = json_string (tmp); | ||
464 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
465 | "audience", | ||
466 | value); | ||
467 | GNUNET_free (tmp); | ||
468 | json_decref (value); | ||
469 | tmp = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
470 | sizeof (uint64_t)); | ||
471 | value = json_string (tmp); | ||
472 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
473 | "rnd", | ||
474 | value); | ||
475 | GNUNET_free (tmp); | ||
476 | json_decref (value); | ||
477 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_next (handle->ticket_it); | ||
478 | } | ||
479 | |||
480 | |||
481 | |||
482 | /** | ||
483 | * List tickets for identity request | ||
484 | * | ||
485 | * @param con_handle the connection handle | ||
486 | * @param url the url | ||
487 | * @param cls the RequestHandle | ||
488 | */ | ||
489 | static void | ||
490 | list_tickets_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
491 | const char* url, | ||
492 | void *cls) | ||
493 | { | ||
494 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
495 | struct RequestHandle *handle = cls; | ||
496 | struct EgoEntry *ego_entry; | ||
497 | char *identity; | ||
498 | |||
499 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting tickets for %s.\n", | ||
500 | handle->url); | ||
501 | if ( strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) >= | ||
502 | strlen (handle->url)) | ||
503 | { | ||
504 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); | ||
505 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
506 | return; | ||
507 | } | ||
508 | identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_TICKETS) + 1; | ||
509 | |||
510 | for (ego_entry = handle->ego_head; | ||
511 | NULL != ego_entry; | ||
512 | ego_entry = ego_entry->next) | ||
513 | if (0 == strcmp (identity, ego_entry->identifier)) | ||
514 | break; | ||
515 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
516 | |||
517 | if (NULL == ego_entry) | ||
518 | { | ||
519 | //Done | ||
520 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", | ||
521 | identity); | ||
522 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
523 | return; | ||
524 | } | ||
525 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
526 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
527 | handle->ticket_it = GNUNET_IDENTITY_PROVIDER_ticket_iteration_start (handle->idp, | ||
528 | priv_key, | ||
529 | &collect_error_cb, | ||
530 | handle, | ||
531 | &ticket_collect, | ||
532 | handle, | ||
533 | &collect_finished_cb, | ||
534 | handle); | ||
535 | } | ||
536 | |||
537 | |||
538 | static void | ||
539 | add_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
540 | const char* url, | ||
541 | void *cls) | ||
542 | { | ||
543 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv; | ||
544 | const char* identity; | ||
545 | const char* name_str; | ||
546 | const char* value_str; | ||
547 | const char* exp_str; | ||
548 | |||
549 | struct RequestHandle *handle = cls; | ||
550 | struct EgoEntry *ego_entry; | ||
551 | struct MHD_Response *resp; | ||
552 | struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attribute; | ||
553 | struct GNUNET_JSONAPI_Document *json_obj; | ||
554 | struct GNUNET_JSONAPI_Resource *json_res; | ||
555 | struct GNUNET_TIME_Relative exp; | ||
556 | char term_data[handle->rest_handle->data_size+1]; | ||
557 | json_t *value_json; | ||
558 | json_t *data_json; | ||
559 | json_t *exp_json; | ||
560 | json_error_t err; | ||
561 | struct GNUNET_JSON_Specification docspec[] = { | ||
562 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
563 | GNUNET_JSON_spec_end() | ||
564 | }; | ||
565 | |||
566 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding an attribute for %s.\n", | ||
567 | handle->url); | ||
568 | if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >= | ||
569 | strlen (handle->url)) | ||
570 | { | ||
571 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); | ||
572 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
573 | return; | ||
574 | } | ||
575 | identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1; | ||
576 | |||
577 | for (ego_entry = handle->ego_head; | ||
578 | NULL != ego_entry; | ||
579 | ego_entry = ego_entry->next) | ||
580 | if (0 == strcmp (identity, ego_entry->identifier)) | ||
581 | break; | ||
582 | |||
583 | if (NULL == ego_entry) | ||
584 | { | ||
585 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
586 | "Identity unknown (%s)\n", identity); | ||
587 | GNUNET_JSONAPI_document_delete (json_obj); | ||
588 | return; | ||
589 | } | ||
590 | identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
591 | |||
592 | if (0 >= handle->rest_handle->data_size) | ||
593 | { | ||
594 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | term_data[handle->rest_handle->data_size] = '\0'; | ||
599 | GNUNET_memcpy (term_data, | ||
600 | handle->rest_handle->data, | ||
601 | handle->rest_handle->data_size); | ||
602 | data_json = json_loads (term_data, | ||
603 | JSON_DECODE_ANY, | ||
604 | &err); | ||
605 | GNUNET_assert (GNUNET_OK == | ||
606 | GNUNET_JSON_parse (data_json, docspec, | ||
607 | NULL, NULL)); | ||
608 | json_decref (data_json); | ||
609 | if (NULL == json_obj) | ||
610 | { | ||
611 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
612 | "Unable to parse JSONAPI Object from %s\n", | ||
613 | term_data); | ||
614 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
615 | return; | ||
616 | } | ||
617 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | ||
618 | { | ||
619 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
620 | "Cannot create more than 1 resource! (Got %d)\n", | ||
621 | GNUNET_JSONAPI_document_resource_count (json_obj)); | ||
622 | GNUNET_JSONAPI_document_delete (json_obj); | ||
623 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
624 | return; | ||
625 | } | ||
626 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | ||
627 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, | ||
628 | GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE)) | ||
629 | { | ||
630 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
631 | "Unsupported JSON data type\n"); | ||
632 | GNUNET_JSONAPI_document_delete (json_obj); | ||
633 | resp = GNUNET_REST_create_response (NULL); | ||
634 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
635 | cleanup_handle (handle); | ||
636 | return; | ||
637 | } | ||
638 | name_str = GNUNET_JSONAPI_resource_get_id (json_res); | ||
639 | exp_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
640 | "exp"); | ||
641 | exp_str = json_string_value (exp_json); | ||
642 | if (NULL == exp_str) { | ||
643 | exp = GNUNET_TIME_UNIT_HOURS; | ||
644 | } else { | ||
645 | if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (exp_str, | ||
646 | &exp)) { | ||
647 | exp = GNUNET_TIME_UNIT_HOURS; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | value_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
652 | "value"); | ||
653 | value_str = json_string_value (value_json); | ||
654 | attribute = GNUNET_IDENTITY_ATTRIBUTE_claim_new (name_str, | ||
655 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
656 | value_str, | ||
657 | strlen (value_str) + 1); | ||
658 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
659 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_attribute_store (handle->idp, | ||
660 | identity_priv, | ||
661 | attribute, | ||
662 | &exp, | ||
663 | &finished_cont, | ||
664 | handle); | ||
665 | GNUNET_free (attribute); | ||
666 | GNUNET_JSONAPI_document_delete (json_obj); | ||
667 | } | ||
668 | |||
669 | |||
670 | |||
671 | /** | ||
672 | * Collect all attributes for an ego | ||
673 | * | ||
674 | */ | ||
675 | static void | ||
676 | attr_collect (void *cls, | ||
677 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
678 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
679 | { | ||
680 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
681 | struct RequestHandle *handle = cls; | ||
682 | json_t *value; | ||
683 | char* tmp_value; | ||
684 | |||
685 | if ((NULL == attr->name) || (NULL == attr->data)) | ||
686 | { | ||
687 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
688 | return; | ||
689 | } | ||
690 | |||
691 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", | ||
692 | attr->name); | ||
693 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE, | ||
694 | attr->name); | ||
695 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | ||
696 | |||
697 | tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type, | ||
698 | attr->data, | ||
699 | attr->data_size); | ||
700 | |||
701 | value = json_string (tmp_value); | ||
702 | |||
703 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
704 | "value", | ||
705 | value); | ||
706 | json_decref (value); | ||
707 | GNUNET_free(tmp_value); | ||
708 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
709 | } | ||
710 | |||
711 | |||
712 | |||
713 | /** | ||
714 | * List attributes for identity request | ||
715 | * | ||
716 | * @param con_handle the connection handle | ||
717 | * @param url the url | ||
718 | * @param cls the RequestHandle | ||
719 | */ | ||
720 | static void | ||
721 | list_attribute_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
722 | const char* url, | ||
723 | void *cls) | ||
724 | { | ||
725 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
726 | struct RequestHandle *handle = cls; | ||
727 | struct EgoEntry *ego_entry; | ||
728 | char *identity; | ||
729 | |||
730 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Getting attributes for %s.\n", | ||
731 | handle->url); | ||
732 | if ( strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) >= | ||
733 | strlen (handle->url)) | ||
734 | { | ||
735 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No identity given.\n"); | ||
736 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
737 | return; | ||
738 | } | ||
739 | identity = handle->url + strlen (GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES) + 1; | ||
740 | |||
741 | for (ego_entry = handle->ego_head; | ||
742 | NULL != ego_entry; | ||
743 | ego_entry = ego_entry->next) | ||
744 | if (0 == strcmp (identity, ego_entry->identifier)) | ||
745 | break; | ||
746 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
747 | |||
748 | |||
749 | if (NULL == ego_entry) | ||
750 | { | ||
751 | //Done | ||
752 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego %s not found.\n", | ||
753 | identity); | ||
754 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
755 | return; | ||
756 | } | ||
757 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
758 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
759 | handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start (handle->idp, | ||
760 | priv_key, | ||
761 | &collect_error_cb, | ||
762 | handle, | ||
763 | &attr_collect, | ||
764 | handle, | ||
765 | &collect_finished_cb, | ||
766 | handle); | ||
767 | } | ||
768 | |||
769 | |||
770 | static void | ||
771 | revoke_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
772 | const char* url, | ||
773 | void *cls) | ||
774 | { | ||
775 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv; | ||
776 | const char* identity_str; | ||
777 | const char* audience_str; | ||
778 | const char* rnd_str; | ||
779 | |||
780 | struct RequestHandle *handle = cls; | ||
781 | struct EgoEntry *ego_entry; | ||
782 | struct MHD_Response *resp; | ||
783 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
784 | struct GNUNET_JSONAPI_Document *json_obj; | ||
785 | struct GNUNET_JSONAPI_Resource *json_res; | ||
786 | struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk; | ||
787 | char term_data[handle->rest_handle->data_size+1]; | ||
788 | json_t *rnd_json; | ||
789 | json_t *identity_json; | ||
790 | json_t *audience_json; | ||
791 | json_t *data_json; | ||
792 | json_error_t err; | ||
793 | struct GNUNET_JSON_Specification docspec[] = { | ||
794 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
795 | GNUNET_JSON_spec_end() | ||
796 | }; | ||
797 | |||
798 | if (0 >= handle->rest_handle->data_size) | ||
799 | { | ||
800 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
801 | return; | ||
802 | } | ||
803 | |||
804 | term_data[handle->rest_handle->data_size] = '\0'; | ||
805 | GNUNET_memcpy (term_data, | ||
806 | handle->rest_handle->data, | ||
807 | handle->rest_handle->data_size); | ||
808 | data_json = json_loads (term_data, | ||
809 | JSON_DECODE_ANY, | ||
810 | &err); | ||
811 | GNUNET_assert (GNUNET_OK == | ||
812 | GNUNET_JSON_parse (data_json, docspec, | ||
813 | NULL, NULL)); | ||
814 | json_decref (data_json); | ||
815 | if (NULL == json_obj) | ||
816 | { | ||
817 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
818 | "Unable to parse JSONAPI Object from %s\n", | ||
819 | term_data); | ||
820 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
821 | return; | ||
822 | } | ||
823 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | ||
824 | { | ||
825 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
826 | "Cannot create more than 1 resource! (Got %d)\n", | ||
827 | GNUNET_JSONAPI_document_resource_count (json_obj)); | ||
828 | GNUNET_JSONAPI_document_delete (json_obj); | ||
829 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
830 | return; | ||
831 | } | ||
832 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | ||
833 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, | ||
834 | GNUNET_REST_JSONAPI_IDENTITY_TICKET)) | ||
835 | { | ||
836 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
837 | "Unsupported JSON data type\n"); | ||
838 | GNUNET_JSONAPI_document_delete (json_obj); | ||
839 | resp = GNUNET_REST_create_response (NULL); | ||
840 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
841 | cleanup_handle (handle); | ||
842 | return; | ||
843 | } | ||
844 | rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
845 | "rnd"); | ||
846 | identity_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
847 | "identity"); | ||
848 | audience_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
849 | "audience"); | ||
850 | rnd_str = json_string_value (rnd_json); | ||
851 | identity_str = json_string_value (identity_json); | ||
852 | audience_str = json_string_value (audience_json); | ||
853 | |||
854 | GNUNET_STRINGS_string_to_data (rnd_str, | ||
855 | strlen (rnd_str), | ||
856 | &ticket.rnd, | ||
857 | sizeof (uint64_t)); | ||
858 | GNUNET_STRINGS_string_to_data (identity_str, | ||
859 | strlen (identity_str), | ||
860 | &ticket.identity, | ||
861 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
862 | GNUNET_STRINGS_string_to_data (audience_str, | ||
863 | strlen (audience_str), | ||
864 | &ticket.audience, | ||
865 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
866 | |||
867 | for (ego_entry = handle->ego_head; | ||
868 | NULL != ego_entry; | ||
869 | ego_entry = ego_entry->next) | ||
870 | { | ||
871 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, | ||
872 | &tmp_pk); | ||
873 | if (0 == memcmp (&ticket.identity, | ||
874 | &tmp_pk, | ||
875 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
876 | break; | ||
877 | } | ||
878 | if (NULL == ego_entry) | ||
879 | { | ||
880 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
881 | "Identity unknown (%s)\n", identity_str); | ||
882 | GNUNET_JSONAPI_document_delete (json_obj); | ||
883 | return; | ||
884 | } | ||
885 | identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
886 | |||
887 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
888 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_revoke (handle->idp, | ||
889 | identity_priv, | ||
890 | &ticket, | ||
891 | &finished_cont, | ||
892 | handle); | ||
893 | GNUNET_JSONAPI_document_delete (json_obj); | ||
894 | } | ||
895 | |||
896 | static void | ||
897 | consume_cont (void *cls, | ||
898 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
899 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
900 | { | ||
901 | struct RequestHandle *handle = cls; | ||
902 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
903 | json_t *value; | ||
904 | |||
905 | if (NULL == identity) | ||
906 | { | ||
907 | GNUNET_SCHEDULER_add_now (&return_response, handle); | ||
908 | return; | ||
909 | } | ||
910 | |||
911 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute: %s\n", | ||
912 | attr->name); | ||
913 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE, | ||
914 | attr->name); | ||
915 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | ||
916 | |||
917 | value = json_string (attr->data); | ||
918 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
919 | "value", | ||
920 | value); | ||
921 | json_decref (value); | ||
922 | } | ||
923 | |||
924 | static void | ||
925 | consume_ticket_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
926 | const char* url, | ||
927 | void *cls) | ||
928 | { | ||
929 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity_priv; | ||
930 | const char* identity_str; | ||
931 | const char* audience_str; | ||
932 | const char* rnd_str; | ||
933 | |||
934 | struct RequestHandle *handle = cls; | ||
935 | struct EgoEntry *ego_entry; | ||
936 | struct MHD_Response *resp; | ||
937 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
938 | struct GNUNET_JSONAPI_Document *json_obj; | ||
939 | struct GNUNET_JSONAPI_Resource *json_res; | ||
940 | struct GNUNET_CRYPTO_EcdsaPublicKey tmp_pk; | ||
941 | char term_data[handle->rest_handle->data_size+1]; | ||
942 | json_t *rnd_json; | ||
943 | json_t *identity_json; | ||
944 | json_t *audience_json; | ||
945 | json_t *data_json; | ||
946 | json_error_t err; | ||
947 | struct GNUNET_JSON_Specification docspec[] = { | ||
948 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
949 | GNUNET_JSON_spec_end() | ||
950 | }; | ||
951 | |||
952 | if (0 >= handle->rest_handle->data_size) | ||
953 | { | ||
954 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
955 | return; | ||
956 | } | ||
957 | |||
958 | term_data[handle->rest_handle->data_size] = '\0'; | ||
959 | GNUNET_memcpy (term_data, | ||
960 | handle->rest_handle->data, | ||
961 | handle->rest_handle->data_size); | ||
962 | data_json = json_loads (term_data, | ||
963 | JSON_DECODE_ANY, | ||
964 | &err); | ||
965 | GNUNET_assert (GNUNET_OK == | ||
966 | GNUNET_JSON_parse (data_json, docspec, | ||
967 | NULL, NULL)); | ||
968 | json_decref (data_json); | ||
969 | if (NULL == json_obj) | ||
970 | { | ||
971 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
972 | "Unable to parse JSONAPI Object from %s\n", | ||
973 | term_data); | ||
974 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
975 | return; | ||
976 | } | ||
977 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | ||
978 | { | ||
979 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
980 | "Cannot create more than 1 resource! (Got %d)\n", | ||
981 | GNUNET_JSONAPI_document_resource_count (json_obj)); | ||
982 | GNUNET_JSONAPI_document_delete (json_obj); | ||
983 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
984 | return; | ||
985 | } | ||
986 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | ||
987 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, | ||
988 | GNUNET_REST_JSONAPI_IDENTITY_TICKET)) | ||
989 | { | ||
990 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
991 | "Unsupported JSON data type\n"); | ||
992 | GNUNET_JSONAPI_document_delete (json_obj); | ||
993 | resp = GNUNET_REST_create_response (NULL); | ||
994 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
995 | cleanup_handle (handle); | ||
996 | return; | ||
997 | } | ||
998 | rnd_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
999 | "rnd"); | ||
1000 | identity_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
1001 | "identity"); | ||
1002 | audience_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
1003 | "audience"); | ||
1004 | rnd_str = json_string_value (rnd_json); | ||
1005 | identity_str = json_string_value (identity_json); | ||
1006 | audience_str = json_string_value (audience_json); | ||
1007 | |||
1008 | GNUNET_STRINGS_string_to_data (rnd_str, | ||
1009 | strlen (rnd_str), | ||
1010 | &ticket.rnd, | ||
1011 | sizeof (uint64_t)); | ||
1012 | GNUNET_STRINGS_string_to_data (identity_str, | ||
1013 | strlen (identity_str), | ||
1014 | &ticket.identity, | ||
1015 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1016 | GNUNET_STRINGS_string_to_data (audience_str, | ||
1017 | strlen (audience_str), | ||
1018 | &ticket.audience, | ||
1019 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1020 | |||
1021 | for (ego_entry = handle->ego_head; | ||
1022 | NULL != ego_entry; | ||
1023 | ego_entry = ego_entry->next) | ||
1024 | { | ||
1025 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, | ||
1026 | &tmp_pk); | ||
1027 | if (0 == memcmp (&ticket.audience, | ||
1028 | &tmp_pk, | ||
1029 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1030 | break; | ||
1031 | } | ||
1032 | if (NULL == ego_entry) | ||
1033 | { | ||
1034 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1035 | "Identity unknown (%s)\n", identity_str); | ||
1036 | GNUNET_JSONAPI_document_delete (json_obj); | ||
1037 | return; | ||
1038 | } | ||
1039 | identity_priv = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
1040 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
1041 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
1042 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp, | ||
1043 | identity_priv, | ||
1044 | &ticket, | ||
1045 | &consume_cont, | ||
1046 | handle); | ||
1047 | GNUNET_JSONAPI_document_delete (json_obj); | ||
1048 | } | ||
1049 | |||
1050 | |||
1051 | |||
1052 | /** | ||
1053 | * Respond to OPTIONS request | ||
1054 | * | ||
1055 | * @param con_handle the connection handle | ||
1056 | * @param url the url | ||
1057 | * @param cls the RequestHandle | ||
1058 | */ | ||
1059 | static void | ||
1060 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1061 | const char* url, | ||
1062 | void *cls) | ||
1063 | { | ||
1064 | struct MHD_Response *resp; | ||
1065 | struct RequestHandle *handle = cls; | ||
1066 | |||
1067 | //For now, independent of path return all options | ||
1068 | resp = GNUNET_REST_create_response (NULL); | ||
1069 | MHD_add_response_header (resp, | ||
1070 | "Access-Control-Allow-Methods", | ||
1071 | allow_methods); | ||
1072 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
1073 | cleanup_handle (handle); | ||
1074 | return; | ||
1075 | } | ||
1076 | |||
1077 | /** | ||
1078 | * Handle rest request | ||
1079 | * | ||
1080 | * @param handle the request handle | ||
1081 | */ | ||
1082 | static void | ||
1083 | init_cont (struct RequestHandle *handle) | ||
1084 | { | ||
1085 | struct GNUNET_REST_RequestHandlerError err; | ||
1086 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
1087 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, | ||
1088 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, | ||
1089 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, | ||
1090 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, | ||
1091 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, | ||
1092 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, | ||
1093 | &options_cont}, | ||
1094 | GNUNET_REST_HANDLER_END | ||
1095 | }; | ||
1096 | |||
1097 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, | ||
1098 | handlers, | ||
1099 | &err, | ||
1100 | handle)) | ||
1101 | { | ||
1102 | handle->response_code = err.error_code; | ||
1103 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | /** | ||
1108 | * If listing is enabled, prints information about the egos. | ||
1109 | * | ||
1110 | * This function is initially called for all egos and then again | ||
1111 | * whenever a ego's identifier changes or if it is deleted. At the | ||
1112 | * end of the initial pass over all egos, the function is once called | ||
1113 | * with 'NULL' for 'ego'. That does NOT mean that the callback won't | ||
1114 | * be invoked in the future or that there was an error. | ||
1115 | * | ||
1116 | * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', | ||
1117 | * this function is only called ONCE, and 'NULL' being passed in | ||
1118 | * 'ego' does indicate an error (i.e. name is taken or no default | ||
1119 | * value is known). If 'ego' is non-NULL and if '*ctx' | ||
1120 | * is set in those callbacks, the value WILL be passed to a subsequent | ||
1121 | * call to the identity callback of 'GNUNET_IDENTITY_connect' (if | ||
1122 | * that one was not NULL). | ||
1123 | * | ||
1124 | * When an identity is renamed, this function is called with the | ||
1125 | * (known) ego but the NEW identifier. | ||
1126 | * | ||
1127 | * When an identity is deleted, this function is called with the | ||
1128 | * (known) ego and "NULL" for the 'identifier'. In this case, | ||
1129 | * the 'ego' is henceforth invalid (and the 'ctx' should also be | ||
1130 | * cleaned up). | ||
1131 | * | ||
1132 | * @param cls closure | ||
1133 | * @param ego ego handle | ||
1134 | * @param ctx context for application to store data for this ego | ||
1135 | * (during the lifetime of this process, initially NULL) | ||
1136 | * @param identifier identifier assigned by the user for this ego, | ||
1137 | * NULL if the user just deleted the ego and it | ||
1138 | * must thus no longer be used | ||
1139 | */ | ||
1140 | static void | ||
1141 | list_ego (void *cls, | ||
1142 | struct GNUNET_IDENTITY_Ego *ego, | ||
1143 | void **ctx, | ||
1144 | const char *identifier) | ||
1145 | { | ||
1146 | struct RequestHandle *handle = cls; | ||
1147 | struct EgoEntry *ego_entry; | ||
1148 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | ||
1149 | |||
1150 | if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) | ||
1151 | { | ||
1152 | handle->state = ID_REST_STATE_POST_INIT; | ||
1153 | init_cont (handle); | ||
1154 | return; | ||
1155 | } | ||
1156 | if (ID_REST_STATE_INIT == handle->state) { | ||
1157 | ego_entry = GNUNET_new (struct EgoEntry); | ||
1158 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
1159 | ego_entry->keystring = | ||
1160 | GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | ||
1161 | ego_entry->ego = ego; | ||
1162 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
1163 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); | ||
1164 | } | ||
1165 | |||
1166 | } | ||
1167 | |||
1168 | static void | ||
1169 | rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | ||
1170 | GNUNET_REST_ResultProcessor proc, | ||
1171 | void *proc_cls) | ||
1172 | { | ||
1173 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
1174 | handle->response_code = 0; | ||
1175 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
1176 | handle->proc_cls = proc_cls; | ||
1177 | handle->proc = proc; | ||
1178 | handle->state = ID_REST_STATE_INIT; | ||
1179 | handle->rest_handle = rest_handle; | ||
1180 | |||
1181 | handle->url = GNUNET_strdup (rest_handle->url); | ||
1182 | if (handle->url[strlen (handle->url)-1] == '/') | ||
1183 | handle->url[strlen (handle->url)-1] = '\0'; | ||
1184 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1185 | "Connecting...\n"); | ||
1186 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, | ||
1187 | &list_ego, | ||
1188 | handle); | ||
1189 | handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); | ||
1190 | handle->timeout_task = | ||
1191 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
1192 | &do_timeout, | ||
1193 | handle); | ||
1194 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1195 | "Connected\n"); | ||
1196 | } | ||
1197 | |||
1198 | /** | ||
1199 | * Entry point for the plugin. | ||
1200 | * | ||
1201 | * @param cls Config info | ||
1202 | * @return NULL on error, otherwise the plugin context | ||
1203 | */ | ||
1204 | void * | ||
1205 | libgnunet_plugin_rest_identity_provider_init (void *cls) | ||
1206 | { | ||
1207 | static struct Plugin plugin; | ||
1208 | struct GNUNET_REST_Plugin *api; | ||
1209 | |||
1210 | cfg = cls; | ||
1211 | if (NULL != plugin.cfg) | ||
1212 | return NULL; /* can only initialize once! */ | ||
1213 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
1214 | plugin.cfg = cfg; | ||
1215 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
1216 | api->cls = &plugin; | ||
1217 | api->name = GNUNET_REST_API_NS_IDENTITY_PROVIDER; | ||
1218 | api->process_request = &rest_identity_process_request; | ||
1219 | GNUNET_asprintf (&allow_methods, | ||
1220 | "%s, %s, %s, %s, %s", | ||
1221 | MHD_HTTP_METHOD_GET, | ||
1222 | MHD_HTTP_METHOD_POST, | ||
1223 | MHD_HTTP_METHOD_PUT, | ||
1224 | MHD_HTTP_METHOD_DELETE, | ||
1225 | MHD_HTTP_METHOD_OPTIONS); | ||
1226 | |||
1227 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1228 | _("Identity Provider REST API initialized\n")); | ||
1229 | return api; | ||
1230 | } | ||
1231 | |||
1232 | |||
1233 | /** | ||
1234 | * Exit point from the plugin. | ||
1235 | * | ||
1236 | * @param cls the plugin context (as returned by "init") | ||
1237 | * @return always NULL | ||
1238 | */ | ||
1239 | void * | ||
1240 | libgnunet_plugin_rest_identity_provider_done (void *cls) | ||
1241 | { | ||
1242 | struct GNUNET_REST_Plugin *api = cls; | ||
1243 | struct Plugin *plugin = api->cls; | ||
1244 | plugin->cfg = NULL; | ||
1245 | |||
1246 | GNUNET_free_non_null (allow_methods); | ||
1247 | GNUNET_free (api); | ||
1248 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1249 | "Identity Provider REST plugin is finished\n"); | ||
1250 | return NULL; | ||
1251 | } | ||
1252 | |||
1253 | /* end of plugin_rest_identity_provider.c */ | ||
diff --git a/src/identity-provider/plugin_rest_openid_connect.c b/src/identity-provider/plugin_rest_openid_connect.c deleted file mode 100644 index d87a345cf..000000000 --- a/src/identity-provider/plugin_rest_openid_connect.c +++ /dev/null | |||
@@ -1,2206 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @author Philippe Buschmann | ||
21 | * @file identity/plugin_rest_openid_connect.c | ||
22 | * @brief GNUnet Namestore REST plugin | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_rest_plugin.h" | ||
28 | #include "gnunet_identity_service.h" | ||
29 | #include "gnunet_gns_service.h" | ||
30 | #include "gnunet_gnsrecord_lib.h" | ||
31 | #include "gnunet_namestore_service.h" | ||
32 | #include "gnunet_rest_lib.h" | ||
33 | #include "gnunet_jsonapi_lib.h" | ||
34 | #include "gnunet_jsonapi_util.h" | ||
35 | #include "microhttpd.h" | ||
36 | #include <jansson.h> | ||
37 | #include <inttypes.h> | ||
38 | #include "gnunet_signatures.h" | ||
39 | #include "gnunet_identity_attribute_lib.h" | ||
40 | #include "gnunet_identity_provider_service.h" | ||
41 | #include "jwt.h" | ||
42 | |||
43 | /** | ||
44 | * REST root namespace | ||
45 | */ | ||
46 | #define GNUNET_REST_API_NS_OIDC "/openid" | ||
47 | |||
48 | /** | ||
49 | * Authorize endpoint | ||
50 | */ | ||
51 | #define GNUNET_REST_API_NS_AUTHORIZE "/openid/authorize" | ||
52 | |||
53 | /** | ||
54 | * Token endpoint | ||
55 | */ | ||
56 | #define GNUNET_REST_API_NS_TOKEN "/openid/token" | ||
57 | |||
58 | /** | ||
59 | * UserInfo endpoint | ||
60 | */ | ||
61 | #define GNUNET_REST_API_NS_USERINFO "/openid/userinfo" | ||
62 | |||
63 | /** | ||
64 | * Login namespace | ||
65 | */ | ||
66 | #define GNUNET_REST_API_NS_LOGIN "/openid/login" | ||
67 | |||
68 | /** | ||
69 | * Attribute key | ||
70 | */ | ||
71 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" | ||
72 | |||
73 | /** | ||
74 | * Ticket key | ||
75 | */ | ||
76 | #define GNUNET_REST_JSONAPI_IDENTITY_TICKET "ticket" | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Value key | ||
81 | */ | ||
82 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE_VALUE "value" | ||
83 | |||
84 | /** | ||
85 | * State while collecting all egos | ||
86 | */ | ||
87 | #define ID_REST_STATE_INIT 0 | ||
88 | |||
89 | /** | ||
90 | * Done collecting egos | ||
91 | */ | ||
92 | #define ID_REST_STATE_POST_INIT 1 | ||
93 | |||
94 | /** | ||
95 | * OIDC grant_type key | ||
96 | */ | ||
97 | #define OIDC_GRANT_TYPE_KEY "grant_type" | ||
98 | |||
99 | /** | ||
100 | * OIDC grant_type key | ||
101 | */ | ||
102 | #define OIDC_GRANT_TYPE_VALUE "authorization_code" | ||
103 | |||
104 | /** | ||
105 | * OIDC code key | ||
106 | */ | ||
107 | #define OIDC_CODE_KEY "code" | ||
108 | |||
109 | /** | ||
110 | * OIDC response_type key | ||
111 | */ | ||
112 | #define OIDC_RESPONSE_TYPE_KEY "response_type" | ||
113 | |||
114 | /** | ||
115 | * OIDC client_id key | ||
116 | */ | ||
117 | #define OIDC_CLIENT_ID_KEY "client_id" | ||
118 | |||
119 | /** | ||
120 | * OIDC scope key | ||
121 | */ | ||
122 | #define OIDC_SCOPE_KEY "scope" | ||
123 | |||
124 | /** | ||
125 | * OIDC redirect_uri key | ||
126 | */ | ||
127 | #define OIDC_REDIRECT_URI_KEY "redirect_uri" | ||
128 | |||
129 | /** | ||
130 | * OIDC state key | ||
131 | */ | ||
132 | #define OIDC_STATE_KEY "state" | ||
133 | |||
134 | /** | ||
135 | * OIDC nonce key | ||
136 | */ | ||
137 | #define OIDC_NONCE_KEY "nonce" | ||
138 | |||
139 | /** | ||
140 | * OIDC cookie header key | ||
141 | */ | ||
142 | #define OIDC_COOKIE_HEADER_KEY "cookie" | ||
143 | |||
144 | /** | ||
145 | * OIDC cookie header information key | ||
146 | */ | ||
147 | #define OIDC_AUTHORIZATION_HEADER_KEY "authorization" | ||
148 | |||
149 | /** | ||
150 | * OIDC cookie header information key | ||
151 | */ | ||
152 | #define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity=" | ||
153 | |||
154 | /** | ||
155 | * OIDC expected response_type while authorizing | ||
156 | */ | ||
157 | #define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code" | ||
158 | |||
159 | /** | ||
160 | * OIDC expected scope part while authorizing | ||
161 | */ | ||
162 | #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid" | ||
163 | |||
164 | /** | ||
165 | * OIDC ignored parameter array | ||
166 | */ | ||
167 | static char* OIDC_ignored_parameter_array [] = | ||
168 | { | ||
169 | "display", | ||
170 | "prompt", | ||
171 | "max_age", | ||
172 | "ui_locales", | ||
173 | "response_mode", | ||
174 | "id_token_hint", | ||
175 | "login_hint", | ||
176 | "acr_values" | ||
177 | }; | ||
178 | |||
179 | /** | ||
180 | * OIDC authorized identities and times hashmap | ||
181 | */ | ||
182 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time; | ||
183 | |||
184 | /** | ||
185 | * OIDC authorized identities and times hashmap | ||
186 | */ | ||
187 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants; | ||
188 | |||
189 | /** | ||
190 | * OIDC ticket/code use only once | ||
191 | */ | ||
192 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once; | ||
193 | |||
194 | /** | ||
195 | * OIDC access_token to ticket and ego | ||
196 | */ | ||
197 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token; | ||
198 | |||
199 | /** | ||
200 | * The configuration handle | ||
201 | */ | ||
202 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
203 | |||
204 | /** | ||
205 | * HTTP methods allows for this plugin | ||
206 | */ | ||
207 | static char* allow_methods; | ||
208 | |||
209 | /** | ||
210 | * @brief struct returned by the initialization function of the plugin | ||
211 | */ | ||
212 | struct Plugin | ||
213 | { | ||
214 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
215 | }; | ||
216 | |||
217 | /** | ||
218 | * OIDC needed variables | ||
219 | */ | ||
220 | struct OIDC_Variables | ||
221 | { | ||
222 | /** | ||
223 | * The RP client public key | ||
224 | */ | ||
225 | struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey; | ||
226 | |||
227 | /** | ||
228 | * The OIDC client id of the RP | ||
229 | */ | ||
230 | char *client_id; | ||
231 | |||
232 | /** | ||
233 | * GNUNET_YES if there is a delegation to | ||
234 | * this RP or if it is a local identity | ||
235 | */ | ||
236 | int is_client_trusted; | ||
237 | |||
238 | /** | ||
239 | * The OIDC redirect uri | ||
240 | */ | ||
241 | char *redirect_uri; | ||
242 | |||
243 | /** | ||
244 | * The list of oidc scopes | ||
245 | */ | ||
246 | char *scope; | ||
247 | |||
248 | /** | ||
249 | * The OIDC state | ||
250 | */ | ||
251 | char *state; | ||
252 | |||
253 | /** | ||
254 | * The OIDC nonce | ||
255 | */ | ||
256 | char *nonce; | ||
257 | |||
258 | /** | ||
259 | * The OIDC response type | ||
260 | */ | ||
261 | char *response_type; | ||
262 | |||
263 | /** | ||
264 | * The identity chosen by the user to login | ||
265 | */ | ||
266 | char *login_identity; | ||
267 | |||
268 | /** | ||
269 | * The response JSON | ||
270 | */ | ||
271 | json_t *response; | ||
272 | |||
273 | }; | ||
274 | |||
275 | /** | ||
276 | * The ego list | ||
277 | */ | ||
278 | struct EgoEntry | ||
279 | { | ||
280 | /** | ||
281 | * DLL | ||
282 | */ | ||
283 | struct EgoEntry *next; | ||
284 | |||
285 | /** | ||
286 | * DLL | ||
287 | */ | ||
288 | struct EgoEntry *prev; | ||
289 | |||
290 | /** | ||
291 | * Ego Identifier | ||
292 | */ | ||
293 | char *identifier; | ||
294 | |||
295 | /** | ||
296 | * Public key string | ||
297 | */ | ||
298 | char *keystring; | ||
299 | |||
300 | /** | ||
301 | * The Ego | ||
302 | */ | ||
303 | struct GNUNET_IDENTITY_Ego *ego; | ||
304 | }; | ||
305 | |||
306 | |||
307 | struct RequestHandle | ||
308 | { | ||
309 | /** | ||
310 | * Ego list | ||
311 | */ | ||
312 | struct EgoEntry *ego_head; | ||
313 | |||
314 | /** | ||
315 | * Ego list | ||
316 | */ | ||
317 | struct EgoEntry *ego_tail; | ||
318 | |||
319 | /** | ||
320 | * Selected ego | ||
321 | */ | ||
322 | struct EgoEntry *ego_entry; | ||
323 | |||
324 | /** | ||
325 | * Pointer to ego private key | ||
326 | */ | ||
327 | struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; | ||
328 | |||
329 | /** | ||
330 | * OIDC variables | ||
331 | */ | ||
332 | struct OIDC_Variables *oidc; | ||
333 | |||
334 | /** | ||
335 | * The processing state | ||
336 | */ | ||
337 | int state; | ||
338 | |||
339 | /** | ||
340 | * Handle to Identity service. | ||
341 | */ | ||
342 | struct GNUNET_IDENTITY_Handle *identity_handle; | ||
343 | |||
344 | /** | ||
345 | * Rest connection | ||
346 | */ | ||
347 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
348 | |||
349 | /** | ||
350 | * Handle to NAMESTORE | ||
351 | */ | ||
352 | struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
353 | |||
354 | /** | ||
355 | * Iterator for NAMESTORE | ||
356 | */ | ||
357 | struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; | ||
358 | |||
359 | /** | ||
360 | * Attribute claim list | ||
361 | */ | ||
362 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; | ||
363 | |||
364 | /** | ||
365 | * IDENTITY Operation | ||
366 | */ | ||
367 | struct GNUNET_IDENTITY_Operation *op; | ||
368 | |||
369 | /** | ||
370 | * Identity Provider | ||
371 | */ | ||
372 | struct GNUNET_IDENTITY_PROVIDER_Handle *idp; | ||
373 | |||
374 | /** | ||
375 | * Idp Operation | ||
376 | */ | ||
377 | struct GNUNET_IDENTITY_PROVIDER_Operation *idp_op; | ||
378 | |||
379 | /** | ||
380 | * Attribute iterator | ||
381 | */ | ||
382 | struct GNUNET_IDENTITY_PROVIDER_AttributeIterator *attr_it; | ||
383 | |||
384 | /** | ||
385 | * Ticket iterator | ||
386 | */ | ||
387 | struct GNUNET_IDENTITY_PROVIDER_TicketIterator *ticket_it; | ||
388 | |||
389 | /** | ||
390 | * A ticket | ||
391 | */ | ||
392 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
393 | |||
394 | /** | ||
395 | * Desired timeout for the lookup (default is no timeout). | ||
396 | */ | ||
397 | struct GNUNET_TIME_Relative timeout; | ||
398 | |||
399 | /** | ||
400 | * ID of a task associated with the resolution process. | ||
401 | */ | ||
402 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
403 | |||
404 | /** | ||
405 | * The plugin result processor | ||
406 | */ | ||
407 | GNUNET_REST_ResultProcessor proc; | ||
408 | |||
409 | /** | ||
410 | * The closure of the result processor | ||
411 | */ | ||
412 | void *proc_cls; | ||
413 | |||
414 | /** | ||
415 | * The url | ||
416 | */ | ||
417 | char *url; | ||
418 | |||
419 | /** | ||
420 | * The tld for redirect | ||
421 | */ | ||
422 | char *tld; | ||
423 | |||
424 | /** | ||
425 | * Error response message | ||
426 | */ | ||
427 | char *emsg; | ||
428 | |||
429 | /** | ||
430 | * Error response description | ||
431 | */ | ||
432 | char *edesc; | ||
433 | |||
434 | /** | ||
435 | * Reponse code | ||
436 | */ | ||
437 | int response_code; | ||
438 | |||
439 | /** | ||
440 | * Response object | ||
441 | */ | ||
442 | struct GNUNET_JSONAPI_Document *resp_object; | ||
443 | |||
444 | }; | ||
445 | |||
446 | /** | ||
447 | * Cleanup lookup handle | ||
448 | * @param handle Handle to clean up | ||
449 | */ | ||
450 | static void | ||
451 | cleanup_handle (struct RequestHandle *handle) | ||
452 | { | ||
453 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry; | ||
454 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp; | ||
455 | struct EgoEntry *ego_entry; | ||
456 | struct EgoEntry *ego_tmp; | ||
457 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
458 | "Cleaning up\n"); | ||
459 | if (NULL != handle->resp_object) | ||
460 | GNUNET_JSONAPI_document_delete (handle->resp_object); | ||
461 | if (NULL != handle->timeout_task) | ||
462 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
463 | if (NULL != handle->identity_handle) | ||
464 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | ||
465 | if (NULL != handle->attr_it) | ||
466 | GNUNET_IDENTITY_PROVIDER_get_attributes_stop (handle->attr_it); | ||
467 | if (NULL != handle->ticket_it) | ||
468 | GNUNET_IDENTITY_PROVIDER_ticket_iteration_stop (handle->ticket_it); | ||
469 | if (NULL != handle->idp) | ||
470 | GNUNET_IDENTITY_PROVIDER_disconnect (handle->idp); | ||
471 | if (NULL != handle->url) | ||
472 | GNUNET_free (handle->url); | ||
473 | if (NULL != handle->tld) | ||
474 | GNUNET_free (handle->tld); | ||
475 | if (NULL != handle->emsg) | ||
476 | GNUNET_free (handle->emsg); | ||
477 | if (NULL != handle->edesc) | ||
478 | GNUNET_free (handle->edesc); | ||
479 | if (NULL != handle->namestore_handle) | ||
480 | GNUNET_NAMESTORE_disconnect (handle->namestore_handle); | ||
481 | if (NULL != handle->oidc) | ||
482 | { | ||
483 | if (NULL != handle->oidc->client_id) | ||
484 | GNUNET_free(handle->oidc->client_id); | ||
485 | if (NULL != handle->oidc->login_identity) | ||
486 | GNUNET_free(handle->oidc->login_identity); | ||
487 | if (NULL != handle->oidc->nonce) | ||
488 | GNUNET_free(handle->oidc->nonce); | ||
489 | if (NULL != handle->oidc->redirect_uri) | ||
490 | GNUNET_free(handle->oidc->redirect_uri); | ||
491 | if (NULL != handle->oidc->response_type) | ||
492 | GNUNET_free(handle->oidc->response_type); | ||
493 | if (NULL != handle->oidc->scope) | ||
494 | GNUNET_free(handle->oidc->scope); | ||
495 | if (NULL != handle->oidc->state) | ||
496 | GNUNET_free(handle->oidc->state); | ||
497 | if (NULL != handle->oidc->response) | ||
498 | json_decref(handle->oidc->response); | ||
499 | GNUNET_free(handle->oidc); | ||
500 | } | ||
501 | if ( NULL != handle->attr_list ) | ||
502 | { | ||
503 | for (claim_entry = handle->attr_list->list_head; | ||
504 | NULL != claim_entry;) | ||
505 | { | ||
506 | claim_tmp = claim_entry; | ||
507 | claim_entry = claim_entry->next; | ||
508 | GNUNET_free(claim_tmp->claim); | ||
509 | GNUNET_free(claim_tmp); | ||
510 | } | ||
511 | GNUNET_free (handle->attr_list); | ||
512 | } | ||
513 | for (ego_entry = handle->ego_head; | ||
514 | NULL != ego_entry;) | ||
515 | { | ||
516 | ego_tmp = ego_entry; | ||
517 | ego_entry = ego_entry->next; | ||
518 | GNUNET_free (ego_tmp->identifier); | ||
519 | GNUNET_free (ego_tmp->keystring); | ||
520 | GNUNET_free (ego_tmp); | ||
521 | } | ||
522 | if (NULL != handle->attr_it) | ||
523 | { | ||
524 | GNUNET_free(handle->attr_it); | ||
525 | } | ||
526 | GNUNET_free (handle); | ||
527 | } | ||
528 | |||
529 | static void | ||
530 | cleanup_handle_delayed (void *cls) | ||
531 | { | ||
532 | cleanup_handle (cls); | ||
533 | } | ||
534 | |||
535 | |||
536 | /** | ||
537 | * Task run on error, sends error message. Cleans up everything. | ||
538 | * | ||
539 | * @param cls the `struct RequestHandle` | ||
540 | */ | ||
541 | static void | ||
542 | do_error (void *cls) | ||
543 | { | ||
544 | struct RequestHandle *handle = cls; | ||
545 | struct MHD_Response *resp; | ||
546 | char *json_error; | ||
547 | |||
548 | GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}", | ||
549 | handle->emsg, | ||
550 | (NULL != handle->edesc) ? handle->edesc : "", | ||
551 | (NULL != handle->oidc->state) ? ", \"state\":\"" : "", | ||
552 | (NULL != handle->oidc->state) ? handle->oidc->state : "", | ||
553 | (NULL != handle->oidc->state) ? "\"" : ""); | ||
554 | if ( 0 == handle->response_code ) | ||
555 | { | ||
556 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
557 | } | ||
558 | resp = GNUNET_REST_create_response (json_error); | ||
559 | if (MHD_HTTP_UNAUTHORIZED == handle->response_code) | ||
560 | { | ||
561 | MHD_add_response_header(resp, "WWW-Authenticate", "Basic"); | ||
562 | } | ||
563 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
564 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
565 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
566 | GNUNET_free (json_error); | ||
567 | } | ||
568 | |||
569 | |||
570 | /** | ||
571 | * Task run on error in userinfo endpoint, sends error header. Cleans up | ||
572 | * everything | ||
573 | * | ||
574 | * @param cls the `struct RequestHandle` | ||
575 | */ | ||
576 | static void | ||
577 | do_userinfo_error (void *cls) | ||
578 | { | ||
579 | struct RequestHandle *handle = cls; | ||
580 | struct MHD_Response *resp; | ||
581 | char *error; | ||
582 | |||
583 | GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"", | ||
584 | handle->emsg, | ||
585 | (NULL != handle->edesc) ? handle->edesc : ""); | ||
586 | resp = GNUNET_REST_create_response (""); | ||
587 | MHD_add_response_header(resp, "WWW-Authenticate", error); | ||
588 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
589 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
590 | GNUNET_free (error); | ||
591 | } | ||
592 | |||
593 | |||
594 | /** | ||
595 | * Task run on error, sends error message and redirects. Cleans up everything. | ||
596 | * | ||
597 | * @param cls the `struct RequestHandle` | ||
598 | */ | ||
599 | static void | ||
600 | do_redirect_error (void *cls) | ||
601 | { | ||
602 | struct RequestHandle *handle = cls; | ||
603 | struct MHD_Response *resp; | ||
604 | char* redirect; | ||
605 | GNUNET_asprintf (&redirect, | ||
606 | "%s?error=%s&error_description=%s%s%s", | ||
607 | handle->oidc->redirect_uri, handle->emsg, handle->edesc, | ||
608 | (NULL != handle->oidc->state) ? "&state=" : "", | ||
609 | (NULL != handle->oidc->state) ? handle->oidc->state : ""); | ||
610 | resp = GNUNET_REST_create_response (""); | ||
611 | MHD_add_response_header (resp, "Location", redirect); | ||
612 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
613 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
614 | GNUNET_free (redirect); | ||
615 | } | ||
616 | |||
617 | /** | ||
618 | * Task run on timeout, sends error message. Cleans up everything. | ||
619 | * | ||
620 | * @param cls the `struct RequestHandle` | ||
621 | */ | ||
622 | static void | ||
623 | do_timeout (void *cls) | ||
624 | { | ||
625 | struct RequestHandle *handle = cls; | ||
626 | |||
627 | handle->timeout_task = NULL; | ||
628 | do_error (handle); | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * Return attributes for claim | ||
633 | * | ||
634 | * @param cls the request handle | ||
635 | */ | ||
636 | static void | ||
637 | return_userinfo_response (void *cls) | ||
638 | { | ||
639 | char* result_str; | ||
640 | struct RequestHandle *handle = cls; | ||
641 | struct MHD_Response *resp; | ||
642 | |||
643 | result_str = json_dumps (handle->oidc->response, 0); | ||
644 | |||
645 | resp = GNUNET_REST_create_response (result_str); | ||
646 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
647 | GNUNET_free (result_str); | ||
648 | cleanup_handle (handle); | ||
649 | } | ||
650 | |||
651 | /** | ||
652 | * Returns base64 encoded string without padding | ||
653 | * | ||
654 | * @param string the string to encode | ||
655 | * @return base64 encoded string | ||
656 | */ | ||
657 | static char* | ||
658 | base_64_encode(const char *s) | ||
659 | { | ||
660 | char *enc; | ||
661 | char *tmp; | ||
662 | |||
663 | GNUNET_STRINGS_base64_encode(s, strlen(s), &enc); | ||
664 | tmp = strrchr (enc, '='); | ||
665 | *tmp = '\0'; | ||
666 | return enc; | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * Respond to OPTIONS request | ||
671 | * | ||
672 | * @param con_handle the connection handle | ||
673 | * @param url the url | ||
674 | * @param cls the RequestHandle | ||
675 | */ | ||
676 | static void | ||
677 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
678 | const char* url, | ||
679 | void *cls) | ||
680 | { | ||
681 | struct MHD_Response *resp; | ||
682 | struct RequestHandle *handle = cls; | ||
683 | |||
684 | //For now, independent of path return all options | ||
685 | resp = GNUNET_REST_create_response (NULL); | ||
686 | MHD_add_response_header (resp, | ||
687 | "Access-Control-Allow-Methods", | ||
688 | allow_methods); | ||
689 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
690 | cleanup_handle (handle); | ||
691 | return; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * Interprets cookie header and pass its identity keystring to handle | ||
696 | */ | ||
697 | static void | ||
698 | cookie_identity_interpretation (struct RequestHandle *handle) | ||
699 | { | ||
700 | struct GNUNET_HashCode cache_key; | ||
701 | char *cookies; | ||
702 | struct GNUNET_TIME_Absolute current_time, *relog_time; | ||
703 | char delimiter[] = "; "; | ||
704 | |||
705 | //gets identity of login try with cookie | ||
706 | GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), | ||
707 | &cache_key); | ||
708 | if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, | ||
709 | &cache_key) ) | ||
710 | { | ||
711 | //splits cookies and find 'Identity' cookie | ||
712 | cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); | ||
713 | handle->oidc->login_identity = strtok(cookies, delimiter); | ||
714 | |||
715 | while ( NULL != handle->oidc->login_identity ) | ||
716 | { | ||
717 | if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) ) | ||
718 | { | ||
719 | break; | ||
720 | } | ||
721 | handle->oidc->login_identity = strtok (NULL, delimiter); | ||
722 | } | ||
723 | GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity), | ||
724 | &cache_key); | ||
725 | if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) ) | ||
726 | { | ||
727 | relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, | ||
728 | &cache_key); | ||
729 | current_time = GNUNET_TIME_absolute_get (); | ||
730 | // 30 min after old login -> redirect to login | ||
731 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) | ||
732 | { | ||
733 | handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY); | ||
734 | handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity); | ||
735 | } | ||
736 | } | ||
737 | else | ||
738 | { | ||
739 | handle->oidc->login_identity = NULL; | ||
740 | } | ||
741 | } | ||
742 | } | ||
743 | |||
744 | /** | ||
745 | * Redirects to login page stored in configuration file | ||
746 | */ | ||
747 | static void | ||
748 | login_redirection(void *cls) | ||
749 | { | ||
750 | char *login_base_url; | ||
751 | char *new_redirect; | ||
752 | struct MHD_Response *resp; | ||
753 | struct RequestHandle *handle = cls; | ||
754 | |||
755 | if ( GNUNET_OK | ||
756 | == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", | ||
757 | "address", &login_base_url) ) | ||
758 | { | ||
759 | GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", | ||
760 | login_base_url, | ||
761 | OIDC_RESPONSE_TYPE_KEY, | ||
762 | handle->oidc->response_type, | ||
763 | OIDC_CLIENT_ID_KEY, | ||
764 | handle->oidc->client_id, | ||
765 | OIDC_REDIRECT_URI_KEY, | ||
766 | handle->oidc->redirect_uri, | ||
767 | OIDC_SCOPE_KEY, | ||
768 | handle->oidc->scope, | ||
769 | OIDC_STATE_KEY, | ||
770 | (NULL != handle->oidc->state) ? handle->oidc->state : "", | ||
771 | OIDC_NONCE_KEY, | ||
772 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); | ||
773 | resp = GNUNET_REST_create_response (""); | ||
774 | MHD_add_response_header (resp, "Location", new_redirect); | ||
775 | GNUNET_free(login_base_url); | ||
776 | } | ||
777 | else | ||
778 | { | ||
779 | handle->emsg = GNUNET_strdup("server_error"); | ||
780 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | ||
781 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
782 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
783 | return; | ||
784 | } | ||
785 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
786 | GNUNET_free(new_redirect); | ||
787 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
788 | } | ||
789 | |||
790 | /** | ||
791 | * Does internal server error when iteration failed. | ||
792 | */ | ||
793 | static void | ||
794 | oidc_iteration_error (void *cls) | ||
795 | { | ||
796 | struct RequestHandle *handle = cls; | ||
797 | handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR"); | ||
798 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
799 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
800 | } | ||
801 | |||
802 | static void get_client_name_result (void *cls, | ||
803 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
804 | const char *label, | ||
805 | unsigned int rd_count, | ||
806 | const struct GNUNET_GNSRECORD_Data *rd) | ||
807 | { | ||
808 | struct RequestHandle *handle = cls; | ||
809 | struct MHD_Response *resp; | ||
810 | char *ticket_str; | ||
811 | char *redirect_uri; | ||
812 | char *code_json_string; | ||
813 | char *code_base64_final_string; | ||
814 | char *redirect_path; | ||
815 | char *tmp; | ||
816 | char *tmp_prefix; | ||
817 | char *prefix; | ||
818 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, | ||
819 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
820 | //TODO change if more attributes are needed (see max_age) | ||
821 | GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", | ||
822 | ticket_str, | ||
823 | (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", | ||
824 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", | ||
825 | (NULL != handle->oidc->nonce) ? "\"" : ""); | ||
826 | code_base64_final_string = base_64_encode(code_json_string); | ||
827 | tmp = GNUNET_strdup (handle->oidc->redirect_uri); | ||
828 | redirect_path = strtok (tmp, "/"); | ||
829 | redirect_path = strtok (NULL, "/"); | ||
830 | redirect_path = strtok (NULL, "/"); | ||
831 | tmp_prefix = GNUNET_strdup (handle->oidc->redirect_uri); | ||
832 | prefix = strrchr (tmp_prefix, | ||
833 | (unsigned char) '.'); | ||
834 | *prefix = '\0'; | ||
835 | GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", | ||
836 | tmp_prefix, | ||
837 | handle->tld, | ||
838 | redirect_path, | ||
839 | handle->oidc->response_type, | ||
840 | code_base64_final_string, handle->oidc->state); | ||
841 | resp = GNUNET_REST_create_response (""); | ||
842 | MHD_add_response_header (resp, "Location", redirect_uri); | ||
843 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
844 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
845 | GNUNET_free (tmp); | ||
846 | GNUNET_free (tmp_prefix); | ||
847 | GNUNET_free (redirect_uri); | ||
848 | GNUNET_free (ticket_str); | ||
849 | GNUNET_free (code_json_string); | ||
850 | GNUNET_free (code_base64_final_string); | ||
851 | return; | ||
852 | } | ||
853 | |||
854 | static void | ||
855 | get_client_name_error (void *cls) | ||
856 | { | ||
857 | struct RequestHandle *handle = cls; | ||
858 | |||
859 | handle->emsg = GNUNET_strdup("server_error"); | ||
860 | handle->edesc = GNUNET_strdup("Server cannot generate ticket, no name found for client."); | ||
861 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
862 | } | ||
863 | |||
864 | /** | ||
865 | * Issues ticket and redirects to relying party with the authorization code as | ||
866 | * parameter. Otherwise redirects with error | ||
867 | */ | ||
868 | static void | ||
869 | oidc_ticket_issue_cb (void* cls, | ||
870 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | ||
871 | { | ||
872 | struct RequestHandle *handle = cls; | ||
873 | handle->idp_op = NULL; | ||
874 | handle->ticket = *ticket; | ||
875 | if (NULL != ticket) { | ||
876 | GNUNET_NAMESTORE_zone_to_name (handle->namestore_handle, | ||
877 | &handle->priv_key, | ||
878 | &handle->oidc->client_pkey, | ||
879 | &get_client_name_error, | ||
880 | handle, | ||
881 | &get_client_name_result, | ||
882 | handle); | ||
883 | return; | ||
884 | } | ||
885 | handle->emsg = GNUNET_strdup("server_error"); | ||
886 | handle->edesc = GNUNET_strdup("Server cannot generate ticket."); | ||
887 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
888 | } | ||
889 | |||
890 | static void | ||
891 | oidc_collect_finished_cb (void *cls) | ||
892 | { | ||
893 | struct RequestHandle *handle = cls; | ||
894 | handle->attr_it = NULL; | ||
895 | handle->ticket_it = NULL; | ||
896 | if (NULL == handle->attr_list->list_head) | ||
897 | { | ||
898 | handle->emsg = GNUNET_strdup("invalid_scope"); | ||
899 | handle->edesc = GNUNET_strdup("The requested scope is not available."); | ||
900 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
901 | return; | ||
902 | } | ||
903 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (handle->idp, | ||
904 | &handle->priv_key, | ||
905 | &handle->oidc->client_pkey, | ||
906 | handle->attr_list, | ||
907 | &oidc_ticket_issue_cb, | ||
908 | handle); | ||
909 | } | ||
910 | |||
911 | |||
912 | /** | ||
913 | * Collects all attributes for an ego if in scope parameter | ||
914 | */ | ||
915 | static void | ||
916 | oidc_attr_collect (void *cls, | ||
917 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
918 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
919 | { | ||
920 | struct RequestHandle *handle = cls; | ||
921 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
922 | char* scope_variables; | ||
923 | char* scope_variable; | ||
924 | char delimiter[]=" "; | ||
925 | |||
926 | if ( (NULL == attr->name) || (NULL == attr->data) ) | ||
927 | { | ||
928 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
929 | return; | ||
930 | } | ||
931 | |||
932 | scope_variables = GNUNET_strdup(handle->oidc->scope); | ||
933 | scope_variable = strtok (scope_variables, delimiter); | ||
934 | while (NULL != scope_variable) | ||
935 | { | ||
936 | if ( 0 == strcmp (attr->name, scope_variable) ) | ||
937 | { | ||
938 | break; | ||
939 | } | ||
940 | scope_variable = strtok (NULL, delimiter); | ||
941 | } | ||
942 | if ( NULL == scope_variable ) | ||
943 | { | ||
944 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
945 | GNUNET_free(scope_variables); | ||
946 | return; | ||
947 | } | ||
948 | GNUNET_free(scope_variables); | ||
949 | |||
950 | le = GNUNET_new(struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry); | ||
951 | le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name, attr->type, | ||
952 | attr->data, attr->data_size); | ||
953 | GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head, | ||
954 | handle->attr_list->list_tail, le); | ||
955 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
956 | } | ||
957 | |||
958 | |||
959 | /** | ||
960 | * Checks time and cookie and redirects accordingly | ||
961 | */ | ||
962 | static void | ||
963 | login_check (void *cls) | ||
964 | { | ||
965 | struct RequestHandle *handle = cls; | ||
966 | struct GNUNET_TIME_Absolute current_time, *relog_time; | ||
967 | struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey; | ||
968 | struct GNUNET_HashCode cache_key; | ||
969 | char *identity_cookie; | ||
970 | |||
971 | GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity); | ||
972 | GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); | ||
973 | GNUNET_free(identity_cookie); | ||
974 | //No login time for identity -> redirect to login | ||
975 | if ( GNUNET_YES | ||
976 | == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, | ||
977 | &cache_key) ) | ||
978 | { | ||
979 | relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, | ||
980 | &cache_key); | ||
981 | current_time = GNUNET_TIME_absolute_get (); | ||
982 | // 30 min after old login -> redirect to login | ||
983 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) | ||
984 | { | ||
985 | if ( GNUNET_OK | ||
986 | != GNUNET_CRYPTO_ecdsa_public_key_from_string ( | ||
987 | handle->oidc->login_identity, | ||
988 | strlen (handle->oidc->login_identity), &pubkey) ) | ||
989 | { | ||
990 | handle->emsg = GNUNET_strdup("invalid_cookie"); | ||
991 | handle->edesc = GNUNET_strdup( | ||
992 | "The cookie of a login identity is not valid"); | ||
993 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
994 | return; | ||
995 | } | ||
996 | // iterate over egos and compare their public key | ||
997 | for (handle->ego_entry = handle->ego_head; | ||
998 | NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) | ||
999 | { | ||
1000 | GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); | ||
1001 | if ( 0 | ||
1002 | == memcmp (&ego_pkey, &pubkey, | ||
1003 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1004 | { | ||
1005 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key ( | ||
1006 | handle->ego_entry->ego); | ||
1007 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
1008 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
1009 | handle->attr_list = GNUNET_new( | ||
1010 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1011 | handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start ( | ||
1012 | handle->idp, &handle->priv_key, &oidc_iteration_error, handle, | ||
1013 | &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle); | ||
1014 | return; | ||
1015 | } | ||
1016 | } | ||
1017 | handle->emsg = GNUNET_strdup("invalid_cookie"); | ||
1018 | handle->edesc = GNUNET_strdup( | ||
1019 | "The cookie of the login identity is not valid"); | ||
1020 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1021 | return; | ||
1022 | } | ||
1023 | } | ||
1024 | } | ||
1025 | |||
1026 | /** | ||
1027 | * Searches for client_id in namestore. If found trust status stored in handle | ||
1028 | * Else continues to search | ||
1029 | * | ||
1030 | * @param handle the RequestHandle | ||
1031 | */ | ||
1032 | static void | ||
1033 | namestore_iteration_callback ( | ||
1034 | void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | ||
1035 | const char *rname, unsigned int rd_len, | ||
1036 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1037 | { | ||
1038 | struct RequestHandle *handle = cls; | ||
1039 | struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey; | ||
1040 | struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey; | ||
1041 | int i; | ||
1042 | |||
1043 | for (i = 0; i < rd_len; i++) | ||
1044 | { | ||
1045 | if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type ) | ||
1046 | continue; | ||
1047 | |||
1048 | if ( NULL != handle->oidc->login_identity ) | ||
1049 | { | ||
1050 | GNUNET_CRYPTO_ecdsa_public_key_from_string ( | ||
1051 | handle->oidc->login_identity, | ||
1052 | strlen (handle->oidc->login_identity), | ||
1053 | &login_identity_pkey); | ||
1054 | GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, | ||
1055 | ¤t_zone_pkey); | ||
1056 | |||
1057 | if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, | ||
1058 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1059 | { | ||
1060 | if ( 0 == memcmp (&login_identity_pkey, ¤t_zone_pkey, | ||
1061 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1062 | { | ||
1063 | handle->oidc->is_client_trusted = GNUNET_YES; | ||
1064 | } | ||
1065 | } | ||
1066 | } | ||
1067 | else | ||
1068 | { | ||
1069 | if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, | ||
1070 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1071 | { | ||
1072 | handle->oidc->is_client_trusted = GNUNET_YES; | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it, | ||
1078 | 1); | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | /** | ||
1083 | * Iteration over all results finished, build final | ||
1084 | * response. | ||
1085 | * | ||
1086 | * @param cls the `struct RequestHandle` | ||
1087 | */ | ||
1088 | static void | ||
1089 | namestore_iteration_finished (void *cls) | ||
1090 | { | ||
1091 | struct RequestHandle *handle = cls; | ||
1092 | struct GNUNET_HashCode cache_key; | ||
1093 | |||
1094 | char *expected_scope; | ||
1095 | char delimiter[]=" "; | ||
1096 | int number_of_ignored_parameter, iterator; | ||
1097 | |||
1098 | |||
1099 | handle->ego_entry = handle->ego_entry->next; | ||
1100 | |||
1101 | if(NULL != handle->ego_entry) | ||
1102 | { | ||
1103 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | ||
1104 | handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key, | ||
1105 | &oidc_iteration_error, handle, &namestore_iteration_callback, handle, | ||
1106 | &namestore_iteration_finished, handle); | ||
1107 | return; | ||
1108 | } | ||
1109 | if (GNUNET_NO == handle->oidc->is_client_trusted) | ||
1110 | { | ||
1111 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1112 | handle->edesc = GNUNET_strdup("The client is not authorized to request an " | ||
1113 | "authorization code using this method."); | ||
1114 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1115 | return; | ||
1116 | } | ||
1117 | |||
1118 | // REQUIRED value: redirect_uri | ||
1119 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), | ||
1120 | &cache_key); | ||
1121 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1122 | &cache_key)) | ||
1123 | { | ||
1124 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1125 | handle->edesc=GNUNET_strdup("missing parameter redirect_uri"); | ||
1126 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1127 | return; | ||
1128 | } | ||
1129 | handle->oidc->redirect_uri = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1130 | &cache_key)); | ||
1131 | |||
1132 | // REQUIRED value: response_type | ||
1133 | GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY), | ||
1134 | &cache_key); | ||
1135 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1136 | &cache_key)) | ||
1137 | { | ||
1138 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1139 | handle->edesc=GNUNET_strdup("missing parameter response_type"); | ||
1140 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1141 | return; | ||
1142 | } | ||
1143 | handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1144 | &cache_key); | ||
1145 | handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type); | ||
1146 | |||
1147 | // REQUIRED value: scope | ||
1148 | GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key); | ||
1149 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1150 | &cache_key)) | ||
1151 | { | ||
1152 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1153 | handle->edesc=GNUNET_strdup("missing parameter scope"); | ||
1154 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1155 | return; | ||
1156 | } | ||
1157 | handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1158 | &cache_key); | ||
1159 | handle->oidc->scope = GNUNET_strdup(handle->oidc->scope); | ||
1160 | |||
1161 | //OPTIONAL value: nonce | ||
1162 | GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key); | ||
1163 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1164 | &cache_key)) | ||
1165 | { | ||
1166 | handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1167 | &cache_key); | ||
1168 | handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce); | ||
1169 | } | ||
1170 | |||
1171 | //TODO check other values if needed | ||
1172 | number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); | ||
1173 | for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) | ||
1174 | { | ||
1175 | GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], | ||
1176 | strlen(OIDC_ignored_parameter_array[iterator]), | ||
1177 | &cache_key); | ||
1178 | if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map, | ||
1179 | &cache_key)) | ||
1180 | { | ||
1181 | handle->emsg=GNUNET_strdup("access_denied"); | ||
1182 | GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s", | ||
1183 | OIDC_ignored_parameter_array[iterator]); | ||
1184 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1185 | return; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | // Checks if response_type is 'code' | ||
1190 | if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) | ||
1191 | { | ||
1192 | handle->emsg=GNUNET_strdup("unsupported_response_type"); | ||
1193 | handle->edesc=GNUNET_strdup("The authorization server does not support " | ||
1194 | "obtaining this authorization code."); | ||
1195 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1196 | return; | ||
1197 | } | ||
1198 | |||
1199 | // Checks if scope contains 'openid' | ||
1200 | expected_scope = GNUNET_strdup(handle->oidc->scope); | ||
1201 | char* test; | ||
1202 | test = strtok (expected_scope, delimiter); | ||
1203 | while (NULL != test) | ||
1204 | { | ||
1205 | if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) ) | ||
1206 | { | ||
1207 | break; | ||
1208 | } | ||
1209 | test = strtok (NULL, delimiter); | ||
1210 | } | ||
1211 | if (NULL == test) | ||
1212 | { | ||
1213 | handle->emsg = GNUNET_strdup("invalid_scope"); | ||
1214 | handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " | ||
1215 | "malformed."); | ||
1216 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1217 | GNUNET_free(expected_scope); | ||
1218 | return; | ||
1219 | } | ||
1220 | |||
1221 | GNUNET_free(expected_scope); | ||
1222 | |||
1223 | if( NULL != handle->oidc->login_identity ) | ||
1224 | { | ||
1225 | GNUNET_SCHEDULER_add_now(&login_check,handle); | ||
1226 | return; | ||
1227 | } | ||
1228 | |||
1229 | GNUNET_SCHEDULER_add_now(&login_redirection,handle); | ||
1230 | } | ||
1231 | |||
1232 | /** | ||
1233 | * Responds to authorization GET and url-encoded POST request | ||
1234 | * | ||
1235 | * @param con_handle the connection handle | ||
1236 | * @param url the url | ||
1237 | * @param cls the RequestHandle | ||
1238 | */ | ||
1239 | static void | ||
1240 | authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | ||
1241 | const char* url, | ||
1242 | void *cls) | ||
1243 | { | ||
1244 | struct RequestHandle *handle = cls; | ||
1245 | struct GNUNET_HashCode cache_key; | ||
1246 | struct EgoEntry *tmp_ego; | ||
1247 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | ||
1248 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
1249 | |||
1250 | cookie_identity_interpretation(handle); | ||
1251 | |||
1252 | //RECOMMENDED value: state - REQUIRED for answers | ||
1253 | GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key); | ||
1254 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1255 | &cache_key)) | ||
1256 | { | ||
1257 | handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1258 | &cache_key); | ||
1259 | handle->oidc->state = GNUNET_strdup (handle->oidc->state); | ||
1260 | } | ||
1261 | |||
1262 | // REQUIRED value: client_id | ||
1263 | GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), | ||
1264 | &cache_key); | ||
1265 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1266 | &cache_key)) | ||
1267 | { | ||
1268 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1269 | handle->edesc=GNUNET_strdup("missing parameter client_id"); | ||
1270 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1271 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1272 | return; | ||
1273 | } | ||
1274 | handle->oidc->client_id = GNUNET_strdup (GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1275 | &cache_key)); | ||
1276 | |||
1277 | if ( GNUNET_OK | ||
1278 | != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id, | ||
1279 | strlen (handle->oidc->client_id), | ||
1280 | &handle->oidc->client_pkey) ) | ||
1281 | { | ||
1282 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1283 | handle->edesc = GNUNET_strdup("The client is not authorized to request an " | ||
1284 | "authorization code using this method."); | ||
1285 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1286 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1287 | return; | ||
1288 | } | ||
1289 | |||
1290 | |||
1291 | if ( NULL == handle->ego_head ) | ||
1292 | { | ||
1293 | handle->emsg = GNUNET_strdup("server_error"); | ||
1294 | handle->edesc = GNUNET_strdup ("Egos are missing"); | ||
1295 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1296 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1297 | return; | ||
1298 | } | ||
1299 | |||
1300 | handle->ego_entry = handle->ego_head; | ||
1301 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); | ||
1302 | handle->oidc->is_client_trusted = GNUNET_NO; | ||
1303 | |||
1304 | //First check if client_id is one of our egos; TODO: handle other TLD cases: Delegation, from config | ||
1305 | for (tmp_ego = handle->ego_head; NULL != tmp_ego; tmp_ego = tmp_ego->next) | ||
1306 | { | ||
1307 | priv_key = GNUNET_IDENTITY_ego_get_private_key (tmp_ego->ego); | ||
1308 | GNUNET_CRYPTO_ecdsa_key_get_public (priv_key, | ||
1309 | &pkey); | ||
1310 | if ( 0 == memcmp (&pkey, &handle->oidc->client_pkey, | ||
1311 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1312 | { | ||
1313 | handle->tld = GNUNET_strdup (tmp_ego->identifier); | ||
1314 | handle->oidc->is_client_trusted = GNUNET_YES; | ||
1315 | handle->ego_entry = handle->ego_tail; | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | |||
1320 | // Checks if client_id is valid: | ||
1321 | handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start ( | ||
1322 | handle->namestore_handle, &handle->priv_key, &oidc_iteration_error, | ||
1323 | handle, &namestore_iteration_callback, handle, | ||
1324 | &namestore_iteration_finished, handle); | ||
1325 | } | ||
1326 | |||
1327 | /** | ||
1328 | * Combines an identity with a login time and responds OK to login request | ||
1329 | * | ||
1330 | * @param con_handle the connection handle | ||
1331 | * @param url the url | ||
1332 | * @param cls the RequestHandle | ||
1333 | */ | ||
1334 | static void | ||
1335 | login_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1336 | const char* url, | ||
1337 | void *cls) | ||
1338 | { | ||
1339 | struct MHD_Response *resp = GNUNET_REST_create_response (""); | ||
1340 | struct RequestHandle *handle = cls; | ||
1341 | struct GNUNET_HashCode cache_key; | ||
1342 | struct GNUNET_TIME_Absolute *current_time; | ||
1343 | struct GNUNET_TIME_Absolute *last_time; | ||
1344 | char* cookie; | ||
1345 | json_t *root; | ||
1346 | json_error_t error; | ||
1347 | json_t *identity; | ||
1348 | char term_data[handle->rest_handle->data_size+1]; | ||
1349 | term_data[handle->rest_handle->data_size] = '\0'; | ||
1350 | GNUNET_memcpy (term_data, handle->rest_handle->data, handle->rest_handle->data_size); | ||
1351 | root = json_loads (term_data, JSON_DECODE_ANY, &error); | ||
1352 | identity = json_object_get (root, "identity"); | ||
1353 | if ( json_is_string(identity) ) | ||
1354 | { | ||
1355 | GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity)); | ||
1356 | MHD_add_response_header (resp, "Set-Cookie", cookie); | ||
1357 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", "POST"); | ||
1358 | GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key); | ||
1359 | |||
1360 | current_time = GNUNET_new(struct GNUNET_TIME_Absolute); | ||
1361 | *current_time = GNUNET_TIME_relative_to_absolute ( | ||
1362 | GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_minute_ (), | ||
1363 | 30)); | ||
1364 | last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key); | ||
1365 | if (NULL != last_time) | ||
1366 | { | ||
1367 | GNUNET_free(last_time); | ||
1368 | } | ||
1369 | GNUNET_CONTAINER_multihashmap_put ( | ||
1370 | OIDC_identity_login_time, &cache_key, current_time, | ||
1371 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
1372 | |||
1373 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
1374 | GNUNET_free(cookie); | ||
1375 | } | ||
1376 | else | ||
1377 | { | ||
1378 | handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); | ||
1379 | } | ||
1380 | json_decref (root); | ||
1381 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
1382 | return; | ||
1383 | } | ||
1384 | |||
1385 | /** | ||
1386 | * Responds to token url-encoded POST request | ||
1387 | * | ||
1388 | * @param con_handle the connection handle | ||
1389 | * @param url the url | ||
1390 | * @param cls the RequestHandle | ||
1391 | */ | ||
1392 | static void | ||
1393 | token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | ||
1394 | const char* url, | ||
1395 | void *cls) | ||
1396 | { | ||
1397 | //TODO static strings | ||
1398 | struct RequestHandle *handle = cls; | ||
1399 | struct GNUNET_HashCode cache_key; | ||
1400 | char *authorization, *credentials; | ||
1401 | char delimiter[]=" "; | ||
1402 | char delimiter_user_psw[]=":"; | ||
1403 | char *grant_type, *code; | ||
1404 | char *user_psw = NULL, *client_id, *psw; | ||
1405 | char *expected_psw; | ||
1406 | int client_exists = GNUNET_NO; | ||
1407 | struct MHD_Response *resp; | ||
1408 | char* code_output; | ||
1409 | json_t *root, *ticket_string, *nonce, *max_age; | ||
1410 | json_error_t error; | ||
1411 | char *json_response; | ||
1412 | |||
1413 | /* | ||
1414 | * Check Authorization | ||
1415 | */ | ||
1416 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, | ||
1417 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), | ||
1418 | &cache_key); | ||
1419 | if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, | ||
1420 | &cache_key) ) | ||
1421 | { | ||
1422 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1423 | handle->edesc=GNUNET_strdup("missing authorization"); | ||
1424 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1425 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1426 | return; | ||
1427 | } | ||
1428 | authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); | ||
1429 | |||
1430 | //split header in "Basic" and [content] | ||
1431 | credentials = strtok (authorization, delimiter); | ||
1432 | if (0 != strcmp ("Basic",credentials)) | ||
1433 | { | ||
1434 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1435 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1436 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1437 | return; | ||
1438 | } | ||
1439 | credentials = strtok(NULL, delimiter); | ||
1440 | if (NULL == credentials) | ||
1441 | { | ||
1442 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1443 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1444 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1445 | return; | ||
1446 | } | ||
1447 | GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), &user_psw); | ||
1448 | |||
1449 | if ( NULL == user_psw ) | ||
1450 | { | ||
1451 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1452 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1453 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1454 | return; | ||
1455 | } | ||
1456 | client_id = strtok (user_psw, delimiter_user_psw); | ||
1457 | if ( NULL == client_id ) | ||
1458 | { | ||
1459 | GNUNET_free_non_null(user_psw); | ||
1460 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1461 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1462 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1463 | return; | ||
1464 | } | ||
1465 | psw = strtok (NULL, delimiter_user_psw); | ||
1466 | if (NULL == psw) | ||
1467 | { | ||
1468 | GNUNET_free_non_null(user_psw); | ||
1469 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1470 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1471 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1472 | return; | ||
1473 | } | ||
1474 | |||
1475 | //check client password | ||
1476 | if ( GNUNET_OK | ||
1477 | == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", | ||
1478 | "psw", &expected_psw) ) | ||
1479 | { | ||
1480 | if (0 != strcmp (expected_psw, psw)) | ||
1481 | { | ||
1482 | GNUNET_free_non_null(user_psw); | ||
1483 | GNUNET_free(expected_psw); | ||
1484 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1485 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1486 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1487 | return; | ||
1488 | } | ||
1489 | GNUNET_free(expected_psw); | ||
1490 | } | ||
1491 | else | ||
1492 | { | ||
1493 | GNUNET_free_non_null(user_psw); | ||
1494 | handle->emsg = GNUNET_strdup("server_error"); | ||
1495 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | ||
1496 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1497 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1498 | return; | ||
1499 | } | ||
1500 | |||
1501 | //check client_id | ||
1502 | for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; ) | ||
1503 | { | ||
1504 | if ( 0 == strcmp(handle->ego_entry->keystring, client_id)) | ||
1505 | { | ||
1506 | client_exists = GNUNET_YES; | ||
1507 | break; | ||
1508 | } | ||
1509 | handle->ego_entry = handle->ego_entry->next; | ||
1510 | } | ||
1511 | if (GNUNET_NO == client_exists) | ||
1512 | { | ||
1513 | GNUNET_free_non_null(user_psw); | ||
1514 | handle->emsg=GNUNET_strdup("invalid_client"); | ||
1515 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1516 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1517 | return; | ||
1518 | } | ||
1519 | |||
1520 | /* | ||
1521 | * Check parameter | ||
1522 | */ | ||
1523 | |||
1524 | //TODO Do not allow multiple equal parameter names | ||
1525 | //REQUIRED grant_type | ||
1526 | GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); | ||
1527 | if ( GNUNET_NO | ||
1528 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
1529 | handle->rest_handle->url_param_map, &cache_key) ) | ||
1530 | { | ||
1531 | GNUNET_free_non_null(user_psw); | ||
1532 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1533 | handle->edesc = GNUNET_strdup("missing parameter grant_type"); | ||
1534 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1535 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1536 | return; | ||
1537 | } | ||
1538 | grant_type = GNUNET_CONTAINER_multihashmap_get ( | ||
1539 | handle->rest_handle->url_param_map, &cache_key); | ||
1540 | |||
1541 | //REQUIRED code | ||
1542 | GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key); | ||
1543 | if ( GNUNET_NO | ||
1544 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
1545 | handle->rest_handle->url_param_map, &cache_key) ) | ||
1546 | { | ||
1547 | GNUNET_free_non_null(user_psw); | ||
1548 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1549 | handle->edesc = GNUNET_strdup("missing parameter code"); | ||
1550 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1551 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1552 | return; | ||
1553 | } | ||
1554 | code = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
1555 | &cache_key); | ||
1556 | |||
1557 | //REQUIRED redirect_uri | ||
1558 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), | ||
1559 | &cache_key); | ||
1560 | if ( GNUNET_NO | ||
1561 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
1562 | handle->rest_handle->url_param_map, &cache_key) ) | ||
1563 | { | ||
1564 | GNUNET_free_non_null(user_psw); | ||
1565 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1566 | handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); | ||
1567 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1568 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1569 | return; | ||
1570 | } | ||
1571 | |||
1572 | //Check parameter grant_type == "authorization_code" | ||
1573 | if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) | ||
1574 | { | ||
1575 | GNUNET_free_non_null(user_psw); | ||
1576 | handle->emsg=GNUNET_strdup("unsupported_grant_type"); | ||
1577 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1578 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1579 | return; | ||
1580 | } | ||
1581 | GNUNET_CRYPTO_hash (code, strlen (code), &cache_key); | ||
1582 | int i = 1; | ||
1583 | if ( GNUNET_SYSERR | ||
1584 | == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, | ||
1585 | &cache_key, | ||
1586 | &i, | ||
1587 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) | ||
1588 | { | ||
1589 | GNUNET_free_non_null(user_psw); | ||
1590 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1591 | handle->edesc = GNUNET_strdup("Cannot use the same code more than once"); | ||
1592 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1593 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1594 | return; | ||
1595 | } | ||
1596 | |||
1597 | //decode code | ||
1598 | GNUNET_STRINGS_base64_decode(code,strlen(code),&code_output); | ||
1599 | root = json_loads (code_output, 0, &error); | ||
1600 | GNUNET_free(code_output); | ||
1601 | ticket_string = json_object_get (root, "ticket"); | ||
1602 | nonce = json_object_get (root, "nonce"); | ||
1603 | max_age = json_object_get (root, "max_age"); | ||
1604 | |||
1605 | if(ticket_string == NULL && !json_is_string(ticket_string)) | ||
1606 | { | ||
1607 | GNUNET_free_non_null(user_psw); | ||
1608 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1609 | handle->edesc = GNUNET_strdup("invalid code"); | ||
1610 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1611 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1612 | return; | ||
1613 | } | ||
1614 | |||
1615 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket); | ||
1616 | if ( GNUNET_OK | ||
1617 | != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string), | ||
1618 | strlen (json_string_value(ticket_string)), | ||
1619 | ticket, | ||
1620 | sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket))) | ||
1621 | { | ||
1622 | GNUNET_free_non_null(user_psw); | ||
1623 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1624 | handle->edesc = GNUNET_strdup("invalid code"); | ||
1625 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1626 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1627 | GNUNET_free(ticket); | ||
1628 | return; | ||
1629 | } | ||
1630 | // this is the current client (relying party) | ||
1631 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
1632 | GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); | ||
1633 | if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1634 | { | ||
1635 | GNUNET_free_non_null(user_psw); | ||
1636 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1637 | handle->edesc = GNUNET_strdup("invalid code"); | ||
1638 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1639 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1640 | GNUNET_free(ticket); | ||
1641 | return; | ||
1642 | } | ||
1643 | |||
1644 | //create jwt | ||
1645 | unsigned long long int expiration_time; | ||
1646 | if ( GNUNET_OK | ||
1647 | != GNUNET_CONFIGURATION_get_value_number(cfg, "identity-rest-plugin", | ||
1648 | "expiration_time", &expiration_time) ) | ||
1649 | { | ||
1650 | GNUNET_free_non_null(user_psw); | ||
1651 | handle->emsg = GNUNET_strdup("server_error"); | ||
1652 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | ||
1653 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1654 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1655 | GNUNET_free(ticket); | ||
1656 | return; | ||
1657 | } | ||
1658 | |||
1659 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1660 | //aud REQUIRED public key client_id must be there | ||
1661 | GNUNET_IDENTITY_ATTRIBUTE_list_add(cl, | ||
1662 | "aud", | ||
1663 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
1664 | client_id, | ||
1665 | strlen(client_id)); | ||
1666 | //exp REQUIRED time expired from config | ||
1667 | struct GNUNET_TIME_Absolute exp_time = GNUNET_TIME_relative_to_absolute ( | ||
1668 | GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_second_ (), | ||
1669 | expiration_time)); | ||
1670 | const char* exp_time_string = GNUNET_STRINGS_absolute_time_to_string(exp_time); | ||
1671 | GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, | ||
1672 | "exp", | ||
1673 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
1674 | exp_time_string, | ||
1675 | strlen(exp_time_string)); | ||
1676 | //iat REQUIRED time now | ||
1677 | struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get(); | ||
1678 | const char* time_now_string = GNUNET_STRINGS_absolute_time_to_string(time_now); | ||
1679 | GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, | ||
1680 | "iat", | ||
1681 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
1682 | time_now_string, | ||
1683 | strlen(time_now_string)); | ||
1684 | //nonce only if nonce is provided | ||
1685 | if ( NULL != nonce && json_is_string(nonce) ) | ||
1686 | { | ||
1687 | GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, | ||
1688 | "nonce", | ||
1689 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
1690 | json_string_value(nonce), | ||
1691 | strlen(json_string_value(nonce))); | ||
1692 | } | ||
1693 | //auth_time only if max_age is provided | ||
1694 | if ( NULL != max_age && json_is_string(max_age) ) | ||
1695 | { | ||
1696 | GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, | ||
1697 | "auth_time", | ||
1698 | GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, | ||
1699 | json_string_value(max_age), | ||
1700 | strlen(json_string_value(max_age))); | ||
1701 | } | ||
1702 | //TODO OPTIONAL acr,amr,azp | ||
1703 | |||
1704 | struct EgoEntry *ego_entry; | ||
1705 | for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) | ||
1706 | { | ||
1707 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); | ||
1708 | if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1709 | { | ||
1710 | break; | ||
1711 | } | ||
1712 | } | ||
1713 | if ( NULL == ego_entry ) | ||
1714 | { | ||
1715 | GNUNET_free_non_null(user_psw); | ||
1716 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1717 | handle->edesc = GNUNET_strdup("invalid code...."); | ||
1718 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1719 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1720 | GNUNET_free(ticket); | ||
1721 | return; | ||
1722 | } | ||
1723 | char *id_token = jwt_create_from_list(&ticket->audience, | ||
1724 | cl, | ||
1725 | GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego)); | ||
1726 | |||
1727 | //Create random access_token | ||
1728 | char* access_token_number; | ||
1729 | char* access_token; | ||
1730 | uint64_t random_number; | ||
1731 | random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); | ||
1732 | GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number); | ||
1733 | GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); | ||
1734 | |||
1735 | |||
1736 | |||
1737 | //TODO OPTIONAL add refresh_token and scope | ||
1738 | GNUNET_asprintf (&json_response, | ||
1739 | "{ \"access_token\" : \"%s\", " | ||
1740 | "\"token_type\" : \"Bearer\", " | ||
1741 | "\"expires_in\" : %d, " | ||
1742 | "\"id_token\" : \"%s\"}", | ||
1743 | access_token, | ||
1744 | expiration_time, | ||
1745 | id_token); | ||
1746 | GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); | ||
1747 | char *id_ticket_combination; | ||
1748 | GNUNET_asprintf(&id_ticket_combination, | ||
1749 | "%s;%s", | ||
1750 | client_id, | ||
1751 | json_string_value(ticket_string)); | ||
1752 | GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, | ||
1753 | &cache_key, | ||
1754 | id_ticket_combination, | ||
1755 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
1756 | |||
1757 | resp = GNUNET_REST_create_response (json_response); | ||
1758 | MHD_add_response_header (resp, "Cache-Control", "no-store"); | ||
1759 | MHD_add_response_header (resp, "Pragma", "no-cache"); | ||
1760 | MHD_add_response_header (resp, "Content-Type", "application/json"); | ||
1761 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
1762 | |||
1763 | GNUNET_IDENTITY_ATTRIBUTE_list_destroy(cl); | ||
1764 | GNUNET_free(access_token_number); | ||
1765 | GNUNET_free(access_token); | ||
1766 | GNUNET_free(user_psw); | ||
1767 | GNUNET_free(json_response); | ||
1768 | GNUNET_free(ticket); | ||
1769 | GNUNET_free(id_token); | ||
1770 | json_decref (root); | ||
1771 | GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle); | ||
1772 | } | ||
1773 | |||
1774 | /** | ||
1775 | * Collects claims and stores them in handle | ||
1776 | */ | ||
1777 | static void | ||
1778 | consume_ticket (void *cls, | ||
1779 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1780 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
1781 | { | ||
1782 | struct RequestHandle *handle = cls; | ||
1783 | char *tmp_value; | ||
1784 | json_t *value; | ||
1785 | |||
1786 | if (NULL == identity) | ||
1787 | { | ||
1788 | GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle); | ||
1789 | return; | ||
1790 | } | ||
1791 | |||
1792 | tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type, | ||
1793 | attr->data, | ||
1794 | attr->data_size); | ||
1795 | |||
1796 | value = json_string (tmp_value); | ||
1797 | |||
1798 | |||
1799 | json_object_set_new (handle->oidc->response, | ||
1800 | attr->name, | ||
1801 | value); | ||
1802 | GNUNET_free (tmp_value); | ||
1803 | } | ||
1804 | |||
1805 | /** | ||
1806 | * Responds to userinfo GET and url-encoded POST request | ||
1807 | * | ||
1808 | * @param con_handle the connection handle | ||
1809 | * @param url the url | ||
1810 | * @param cls the RequestHandle | ||
1811 | */ | ||
1812 | static void | ||
1813 | userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | ||
1814 | const char* url, void *cls) | ||
1815 | { | ||
1816 | //TODO expiration time | ||
1817 | struct RequestHandle *handle = cls; | ||
1818 | char delimiter[] = " "; | ||
1819 | char delimiter_db[] = ";"; | ||
1820 | struct GNUNET_HashCode cache_key; | ||
1821 | char *authorization, *authorization_type, *authorization_access_token; | ||
1822 | char *client_ticket, *client, *ticket_str; | ||
1823 | struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket; | ||
1824 | |||
1825 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, | ||
1826 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), | ||
1827 | &cache_key); | ||
1828 | if ( GNUNET_NO | ||
1829 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
1830 | handle->rest_handle->header_param_map, &cache_key) ) | ||
1831 | { | ||
1832 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1833 | handle->edesc = GNUNET_strdup("No Access Token"); | ||
1834 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1835 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1836 | return; | ||
1837 | } | ||
1838 | authorization = GNUNET_CONTAINER_multihashmap_get ( | ||
1839 | handle->rest_handle->header_param_map, &cache_key); | ||
1840 | |||
1841 | //split header in "Bearer" and access_token | ||
1842 | authorization = GNUNET_strdup(authorization); | ||
1843 | authorization_type = strtok (authorization, delimiter); | ||
1844 | if ( 0 != strcmp ("Bearer", authorization_type) ) | ||
1845 | { | ||
1846 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1847 | handle->edesc = GNUNET_strdup("No Access Token"); | ||
1848 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1849 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1850 | GNUNET_free(authorization); | ||
1851 | return; | ||
1852 | } | ||
1853 | authorization_access_token = strtok (NULL, delimiter); | ||
1854 | if ( NULL == authorization_access_token ) | ||
1855 | { | ||
1856 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1857 | handle->edesc = GNUNET_strdup("No Access Token"); | ||
1858 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1859 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1860 | GNUNET_free(authorization); | ||
1861 | return; | ||
1862 | } | ||
1863 | |||
1864 | GNUNET_CRYPTO_hash (authorization_access_token, | ||
1865 | strlen (authorization_access_token), | ||
1866 | &cache_key); | ||
1867 | if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token, | ||
1868 | &cache_key) ) | ||
1869 | { | ||
1870 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1871 | handle->edesc = GNUNET_strdup("The Access Token expired"); | ||
1872 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1873 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1874 | GNUNET_free(authorization); | ||
1875 | return; | ||
1876 | } | ||
1877 | |||
1878 | client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token, | ||
1879 | &cache_key); | ||
1880 | client_ticket = GNUNET_strdup(client_ticket); | ||
1881 | client = strtok(client_ticket,delimiter_db); | ||
1882 | if (NULL == client) | ||
1883 | { | ||
1884 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1885 | handle->edesc = GNUNET_strdup("The Access Token expired"); | ||
1886 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1887 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1888 | GNUNET_free(authorization); | ||
1889 | GNUNET_free(client_ticket); | ||
1890 | return; | ||
1891 | } | ||
1892 | handle->ego_entry = handle->ego_head; | ||
1893 | for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) | ||
1894 | { | ||
1895 | if (0 == strcmp(handle->ego_entry->keystring,client)) | ||
1896 | { | ||
1897 | break; | ||
1898 | } | ||
1899 | } | ||
1900 | if (NULL == handle->ego_entry) | ||
1901 | { | ||
1902 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1903 | handle->edesc = GNUNET_strdup("The Access Token expired"); | ||
1904 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1905 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1906 | GNUNET_free(authorization); | ||
1907 | GNUNET_free(client_ticket); | ||
1908 | return; | ||
1909 | } | ||
1910 | ticket_str = strtok(NULL, delimiter_db); | ||
1911 | if (NULL == ticket_str) | ||
1912 | { | ||
1913 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1914 | handle->edesc = GNUNET_strdup("The Access Token expired"); | ||
1915 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1916 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1917 | GNUNET_free(authorization); | ||
1918 | GNUNET_free(client_ticket); | ||
1919 | return; | ||
1920 | } | ||
1921 | ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket); | ||
1922 | if ( GNUNET_OK | ||
1923 | != GNUNET_STRINGS_string_to_data (ticket_str, | ||
1924 | strlen (ticket_str), | ||
1925 | ticket, | ||
1926 | sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket))) | ||
1927 | { | ||
1928 | handle->emsg = GNUNET_strdup("invalid_token"); | ||
1929 | handle->edesc = GNUNET_strdup("The Access Token expired"); | ||
1930 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | ||
1931 | GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle); | ||
1932 | GNUNET_free(ticket); | ||
1933 | GNUNET_free(authorization); | ||
1934 | GNUNET_free(client_ticket); | ||
1935 | return; | ||
1936 | } | ||
1937 | |||
1938 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
1939 | handle->oidc->response = json_object(); | ||
1940 | json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring)); | ||
1941 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume ( | ||
1942 | handle->idp, | ||
1943 | GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego), | ||
1944 | ticket, | ||
1945 | consume_ticket, | ||
1946 | handle); | ||
1947 | GNUNET_free(ticket); | ||
1948 | GNUNET_free(authorization); | ||
1949 | GNUNET_free(client_ticket); | ||
1950 | |||
1951 | } | ||
1952 | |||
1953 | |||
1954 | /** | ||
1955 | * Handle rest request | ||
1956 | * | ||
1957 | * @param handle the request handle | ||
1958 | */ | ||
1959 | static void | ||
1960 | init_cont (struct RequestHandle *handle) | ||
1961 | { | ||
1962 | struct GNUNET_REST_RequestHandlerError err; | ||
1963 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
1964 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, | ||
1965 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded | ||
1966 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, | ||
1967 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint }, | ||
1968 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, | ||
1969 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint }, | ||
1970 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_OIDC, | ||
1971 | &options_cont}, | ||
1972 | GNUNET_REST_HANDLER_END | ||
1973 | }; | ||
1974 | |||
1975 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, | ||
1976 | handlers, | ||
1977 | &err, | ||
1978 | handle)) | ||
1979 | { | ||
1980 | handle->response_code = err.error_code; | ||
1981 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1982 | } | ||
1983 | } | ||
1984 | |||
1985 | /** | ||
1986 | * If listing is enabled, prints information about the egos. | ||
1987 | * | ||
1988 | * This function is initially called for all egos and then again | ||
1989 | * whenever a ego's identifier changes or if it is deleted. At the | ||
1990 | * end of the initial pass over all egos, the function is once called | ||
1991 | * with 'NULL' for 'ego'. That does NOT mean that the callback won't | ||
1992 | * be invoked in the future or that there was an error. | ||
1993 | * | ||
1994 | * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', | ||
1995 | * this function is only called ONCE, and 'NULL' being passed in | ||
1996 | * 'ego' does indicate an error (i.e. name is taken or no default | ||
1997 | * value is known). If 'ego' is non-NULL and if '*ctx' | ||
1998 | * is set in those callbacks, the value WILL be passed to a subsequent | ||
1999 | * call to the identity callback of 'GNUNET_IDENTITY_connect' (if | ||
2000 | * that one was not NULL). | ||
2001 | * | ||
2002 | * When an identity is renamed, this function is called with the | ||
2003 | * (known) ego but the NEW identifier. | ||
2004 | * | ||
2005 | * When an identity is deleted, this function is called with the | ||
2006 | * (known) ego and "NULL" for the 'identifier'. In this case, | ||
2007 | * the 'ego' is henceforth invalid (and the 'ctx' should also be | ||
2008 | * cleaned up). | ||
2009 | * | ||
2010 | * @param cls closure | ||
2011 | * @param ego ego handle | ||
2012 | * @param ctx context for application to store data for this ego | ||
2013 | * (during the lifetime of this process, initially NULL) | ||
2014 | * @param identifier identifier assigned by the user for this ego, | ||
2015 | * NULL if the user just deleted the ego and it | ||
2016 | * must thus no longer be used | ||
2017 | */ | ||
2018 | static void | ||
2019 | list_ego (void *cls, | ||
2020 | struct GNUNET_IDENTITY_Ego *ego, | ||
2021 | void **ctx, | ||
2022 | const char *identifier) | ||
2023 | { | ||
2024 | struct RequestHandle *handle = cls; | ||
2025 | struct EgoEntry *ego_entry; | ||
2026 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | ||
2027 | |||
2028 | if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) | ||
2029 | { | ||
2030 | handle->state = ID_REST_STATE_POST_INIT; | ||
2031 | init_cont (handle); | ||
2032 | return; | ||
2033 | } | ||
2034 | if (ID_REST_STATE_INIT == handle->state) { | ||
2035 | ego_entry = GNUNET_new (struct EgoEntry); | ||
2036 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
2037 | ego_entry->keystring = | ||
2038 | GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | ||
2039 | ego_entry->ego = ego; | ||
2040 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
2041 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); | ||
2042 | return; | ||
2043 | } | ||
2044 | /* Ego renamed or added */ | ||
2045 | if (identifier != NULL) { | ||
2046 | for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { | ||
2047 | if (ego_entry->ego == ego) { | ||
2048 | /* Rename */ | ||
2049 | GNUNET_free (ego_entry->identifier); | ||
2050 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
2051 | break; | ||
2052 | } | ||
2053 | } | ||
2054 | if (NULL == ego_entry) { | ||
2055 | /* Add */ | ||
2056 | ego_entry = GNUNET_new (struct EgoEntry); | ||
2057 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
2058 | ego_entry->keystring = | ||
2059 | GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | ||
2060 | ego_entry->ego = ego; | ||
2061 | ego_entry->identifier = GNUNET_strdup (identifier); | ||
2062 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); | ||
2063 | } | ||
2064 | } else { | ||
2065 | /* Delete */ | ||
2066 | for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { | ||
2067 | if (ego_entry->ego == ego) | ||
2068 | break; | ||
2069 | } | ||
2070 | if (NULL != ego_entry) | ||
2071 | GNUNET_CONTAINER_DLL_remove(handle->ego_head,handle->ego_tail, ego_entry); | ||
2072 | } | ||
2073 | |||
2074 | } | ||
2075 | |||
2076 | static void | ||
2077 | rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | ||
2078 | GNUNET_REST_ResultProcessor proc, | ||
2079 | void *proc_cls) | ||
2080 | { | ||
2081 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
2082 | handle->oidc = GNUNET_new (struct OIDC_Variables); | ||
2083 | if ( NULL == OIDC_identity_login_time ) | ||
2084 | OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2085 | if ( NULL == OIDC_identity_grants ) | ||
2086 | OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2087 | if ( NULL == OIDC_ticket_once ) | ||
2088 | OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2089 | if ( NULL == OIDC_interpret_access_token ) | ||
2090 | OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2091 | handle->response_code = 0; | ||
2092 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
2093 | handle->proc_cls = proc_cls; | ||
2094 | handle->proc = proc; | ||
2095 | handle->state = ID_REST_STATE_INIT; | ||
2096 | handle->rest_handle = rest_handle; | ||
2097 | |||
2098 | handle->url = GNUNET_strdup (rest_handle->url); | ||
2099 | if (handle->url[strlen (handle->url)-1] == '/') | ||
2100 | handle->url[strlen (handle->url)-1] = '\0'; | ||
2101 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2102 | "Connecting...\n"); | ||
2103 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, | ||
2104 | &list_ego, | ||
2105 | handle); | ||
2106 | handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); | ||
2107 | handle->timeout_task = | ||
2108 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
2109 | &do_timeout, | ||
2110 | handle); | ||
2111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2112 | "Connected\n"); | ||
2113 | } | ||
2114 | |||
2115 | /** | ||
2116 | * Entry point for the plugin. | ||
2117 | * | ||
2118 | * @param cls Config info | ||
2119 | * @return NULL on error, otherwise the plugin context | ||
2120 | */ | ||
2121 | void * | ||
2122 | libgnunet_plugin_rest_openid_connect_init (void *cls) | ||
2123 | { | ||
2124 | static struct Plugin plugin; | ||
2125 | struct GNUNET_REST_Plugin *api; | ||
2126 | |||
2127 | cfg = cls; | ||
2128 | if (NULL != plugin.cfg) | ||
2129 | return NULL; /* can only initialize once! */ | ||
2130 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
2131 | plugin.cfg = cfg; | ||
2132 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
2133 | api->cls = &plugin; | ||
2134 | api->name = GNUNET_REST_API_NS_OIDC; | ||
2135 | api->process_request = &rest_identity_process_request; | ||
2136 | GNUNET_asprintf (&allow_methods, | ||
2137 | "%s, %s, %s, %s, %s", | ||
2138 | MHD_HTTP_METHOD_GET, | ||
2139 | MHD_HTTP_METHOD_POST, | ||
2140 | MHD_HTTP_METHOD_PUT, | ||
2141 | MHD_HTTP_METHOD_DELETE, | ||
2142 | MHD_HTTP_METHOD_OPTIONS); | ||
2143 | |||
2144 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2145 | _("Identity Provider REST API initialized\n")); | ||
2146 | return api; | ||
2147 | } | ||
2148 | |||
2149 | |||
2150 | /** | ||
2151 | * Exit point from the plugin. | ||
2152 | * | ||
2153 | * @param cls the plugin context (as returned by "init") | ||
2154 | * @return always NULL | ||
2155 | */ | ||
2156 | void * | ||
2157 | libgnunet_plugin_rest_openid_connect_done (void *cls) | ||
2158 | { | ||
2159 | struct GNUNET_REST_Plugin *api = cls; | ||
2160 | struct Plugin *plugin = api->cls; | ||
2161 | plugin->cfg = NULL; | ||
2162 | |||
2163 | struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it; | ||
2164 | void *value = NULL; | ||
2165 | hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create ( | ||
2166 | OIDC_identity_login_time); | ||
2167 | while (GNUNET_YES == | ||
2168 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) | ||
2169 | { | ||
2170 | if (NULL != value) | ||
2171 | GNUNET_free(value); | ||
2172 | } | ||
2173 | GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time); | ||
2174 | hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants); | ||
2175 | while (GNUNET_YES == | ||
2176 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) | ||
2177 | { | ||
2178 | if (NULL != value) | ||
2179 | GNUNET_free(value); | ||
2180 | } | ||
2181 | GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants); | ||
2182 | hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once); | ||
2183 | while (GNUNET_YES == | ||
2184 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) | ||
2185 | { | ||
2186 | if (NULL != value) | ||
2187 | GNUNET_free(value); | ||
2188 | } | ||
2189 | GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once); | ||
2190 | hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token); | ||
2191 | while (GNUNET_YES == | ||
2192 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) | ||
2193 | { | ||
2194 | if (NULL != value) | ||
2195 | GNUNET_free(value); | ||
2196 | } | ||
2197 | GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token); | ||
2198 | GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it); | ||
2199 | GNUNET_free_non_null (allow_methods); | ||
2200 | GNUNET_free (api); | ||
2201 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2202 | "Identity Provider REST plugin is finished\n"); | ||
2203 | return NULL; | ||
2204 | } | ||
2205 | |||
2206 | /* end of plugin_rest_identity_provider.c */ | ||
diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf deleted file mode 100644 index 3e4df561a..000000000 --- a/src/identity-provider/test_idp.conf +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | @INLINE@ test_idp_defaults.conf | ||
2 | |||
3 | [PATHS] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-peer-1/ | ||
5 | |||
6 | [dht] | ||
7 | START_ON_DEMAND = YES | ||
8 | |||
9 | [rest] | ||
10 | START_ON_DEMAND = YES | ||
11 | PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=$GNUNET_TMP/restlog | ||
12 | |||
13 | [transport] | ||
14 | PLUGINS = | ||
15 | |||
16 | [identity-provider] | ||
17 | START_ON_DEMAND = YES | ||
18 | #PREFIX = valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=$GNUNET_TMP/idplog | ||
19 | |||
20 | [gns] | ||
21 | #PREFIX = valgrind --leak-check=full --track-origins=yes | ||
22 | START_ON_DEMAND = YES | ||
23 | AUTO_IMPORT_PKEY = YES | ||
24 | MAX_PARALLEL_BACKGROUND_QUERIES = 10 | ||
25 | DEFAULT_LOOKUP_TIMEOUT = 15 s | ||
26 | RECORD_PUT_INTERVAL = 1 h | ||
27 | ZONE_PUBLISH_TIME_WINDOW = 1 h | ||
28 | DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 | ||
29 | |||
30 | [identity-rest-plugin] | ||
31 | address = http://localhost:8000/#/login | ||
32 | psw = mysupersecretpassword | ||
33 | expiration_time = 3600 | ||
diff --git a/src/identity-provider/test_idp.sh b/src/identity-provider/test_idp.sh deleted file mode 100755 index 598d1008c..000000000 --- a/src/identity-provider/test_idp.sh +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | #trap "gnunet-arm -e -c test_idp_lookup.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f` | ||
17 | |||
18 | # (1) PKEY1.user -> PKEY2.resu.user | ||
19 | # (2) PKEY2.resu -> PKEY3 | ||
20 | # (3) PKEY3.user -> PKEY4 | ||
21 | |||
22 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | gnunet-identity -C testego -c test_idp.conf | ||
28 | valgrind gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf | ||
29 | gnunet-idp -e testego -a name -V John -c test_idp.conf | ||
30 | gnunet-idp -e testego -D -c test_idp.conf | ||
31 | gnunet-arm -e -c test_idp.conf | ||
diff --git a/src/identity-provider/test_idp_attribute.sh b/src/identity-provider/test_idp_attribute.sh deleted file mode 100755 index 7f0f06dac..000000000 --- a/src/identity-provider/test_idp_attribute.sh +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f` | ||
17 | |||
18 | # (1) PKEY1.user -> PKEY2.resu.user | ||
19 | # (2) PKEY2.resu -> PKEY3 | ||
20 | # (3) PKEY3.user -> PKEY4 | ||
21 | |||
22 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | #gnunet-arm -i rest -c test_idp.conf | ||
28 | gnunet-identity -C testego -c test_idp.conf | ||
29 | gnunet-identity -C rpego -c test_idp.conf | ||
30 | TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}') | ||
31 | gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf | ||
32 | gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1 | ||
33 | if test $? != 0 | ||
34 | then | ||
35 | echo "Failed." | ||
36 | exit 1 | ||
37 | fi | ||
38 | |||
39 | #curl localhost:7776/idp/attributes/testego | ||
40 | gnunet-arm -e -c test_idp.conf | ||
diff --git a/src/identity-provider/test_idp_consume.sh b/src/identity-provider/test_idp_consume.sh deleted file mode 100755 index 11f6865a4..000000000 --- a/src/identity-provider/test_idp_consume.sh +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f` | ||
17 | |||
18 | # (1) PKEY1.user -> PKEY2.resu.user | ||
19 | # (2) PKEY2.resu -> PKEY3 | ||
20 | # (3) PKEY3.user -> PKEY4 | ||
21 | |||
22 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | #gnunet-arm -i rest -c test_idp.conf | ||
28 | gnunet-identity -C testego -c test_idp.conf | ||
29 | gnunet-identity -C rpego -c test_idp.conf | ||
30 | SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}') | ||
31 | TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}') | ||
32 | gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf | ||
33 | gnunet-idp -e testego -a name -V John -c test_idp.conf | ||
34 | TICKET=$(gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf | awk '{print $1}') | ||
35 | gnunet-idp -e rpego -C $TICKET -c test_idp.conf > /dev/null 2>&1 | ||
36 | |||
37 | if test $? != 0 | ||
38 | then | ||
39 | "Failed." | ||
40 | exit 1 | ||
41 | fi | ||
42 | #curl http://localhost:7776/idp/tickets/testego | ||
43 | gnunet-arm -e -c test_idp.conf | ||
diff --git a/src/identity-provider/test_idp_defaults.conf b/src/identity-provider/test_idp_defaults.conf deleted file mode 100644 index a9a197dea..000000000 --- a/src/identity-provider/test_idp_defaults.conf +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | @INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf | ||
2 | |||
3 | [PATHS] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-idp-testing/ | ||
5 | |||
6 | [namestore-sqlite] | ||
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | ||
8 | |||
9 | [namecache-sqlite] | ||
10 | FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db | ||
11 | |||
12 | [identity] | ||
13 | # Directory where we store information about our egos | ||
14 | EGODIR = $GNUNET_TEST_HOME/identity/egos/ | ||
15 | |||
16 | [dhtcache] | ||
17 | DATABASE = heap | ||
18 | |||
19 | [transport] | ||
20 | PLUGINS = tcp | ||
21 | |||
22 | [transport-tcp] | ||
23 | BINDTO = 127.0.0.1 | ||
24 | |||
diff --git a/src/identity-provider/test_idp_issue.sh b/src/identity-provider/test_idp_issue.sh deleted file mode 100755 index 90487ee73..000000000 --- a/src/identity-provider/test_idp_issue.sh +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f` | ||
17 | |||
18 | # (1) PKEY1.user -> PKEY2.resu.user | ||
19 | # (2) PKEY2.resu -> PKEY3 | ||
20 | # (3) PKEY3.user -> PKEY4 | ||
21 | |||
22 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf | ||
27 | #gnunet-arm -i rest -c test_idp.conf | ||
28 | gnunet-identity -C testego -c test_idp.conf | ||
29 | gnunet-identity -C rpego -c test_idp.conf | ||
30 | SUBJECT_KEY=$(gnunet-identity -d -c test_idp.conf | grep rpego | awk '{print $3}') | ||
31 | TEST_KEY=$(gnunet-identity -d -c test_idp.conf | grep testego | awk '{print $3}') | ||
32 | gnunet-idp -e testego -a email -V john@doe.gnu -c test_idp.conf > /dev/null 2>&1 | ||
33 | gnunet-idp -e testego -a name -V John -c test_idp.conf > /dev/null 2>&1 | ||
34 | #gnunet-idp -e testego -D -c test_idp.conf | ||
35 | gnunet-idp -e testego -i "email,name" -r $SUBJECT_KEY -c test_idp.conf > /dev/null 2>&1 | ||
36 | if test $? != 0 | ||
37 | then | ||
38 | echo "Failed." | ||
39 | exit 1 | ||
40 | fi | ||
41 | #curl http://localhost:7776/idp/attributes/testego | ||
42 | gnunet-arm -e -c test_idp.conf | ||
diff --git a/src/identity-provider/test_idp_revoke.sh b/src/identity-provider/test_idp_revoke.sh deleted file mode 100755 index 7a3f5d030..000000000 --- a/src/identity-provider/test_idp_revoke.sh +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | trap "gnunet-arm -e -c test_idp.conf" SIGINT | ||
3 | |||
4 | LOCATION=$(which gnunet-config) | ||
5 | if [ -z $LOCATION ] | ||
6 | then | ||
7 | LOCATION="gnunet-config" | ||
8 | fi | ||
9 | $LOCATION --version 1> /dev/null | ||
10 | if test $? != 0 | ||
11 | then | ||
12 | echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" | ||
13 | exit 77 | ||
14 | fi | ||
15 | |||
16 | rm -rf `gnunet-config -c test_idp.conf -s PATHS -o GNUNET_HOME -f` | ||
17 | |||
18 | # (1) PKEY1.user -> PKEY2.resu.user | ||
19 | # (2) PKEY2.resu -> PKEY3 | ||
20 | # (3) PKEY3.user -> PKEY4 | ||
21 | |||
22 | |||
23 | which timeout &> /dev/null && DO_TIMEOUT="timeout 30" | ||
24 | |||
25 | TEST_ATTR="test" | ||
26 | gnunet-arm -s -c test_idp.conf 2&>1 > /dev/null | ||
27 | gnunet-identity -C alice -c test_idp.conf | ||
28 | gnunet-identity -C bob -c test_idp.conf | ||
29 | gnunet-identity -C eve -c test_idp.conf | ||
30 | ALICE_KEY=$(gnunet-identity -d -c test_idp.conf | grep alice | awk '{print $3}') | ||
31 | BOB_KEY=$(gnunet-identity -d -c test_idp.conf | grep bob | awk '{print $3}') | ||
32 | EVE_KEY=$(gnunet-identity -d -c test_idp.conf | grep eve | awk '{print $3}') | ||
33 | |||
34 | gnunet-idp -e alice -E 15s -a email -V john@doe.gnu -c test_idp.conf | ||
35 | gnunet-idp -e alice -E 15s -a name -V John -c test_idp.conf | ||
36 | TICKET_BOB=$(gnunet-idp -e alice -i "email,name" -r $BOB_KEY -c test_idp.conf | awk '{print $1}') | ||
37 | #gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf | ||
38 | TICKET_EVE=$(gnunet-idp -e alice -i "email" -r $EVE_KEY -c test_idp.conf | awk '{print $1}') | ||
39 | |||
40 | #echo "Consuming $TICKET" | ||
41 | #gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf | ||
42 | gnunet-idp -e alice -R $TICKET_EVE -c test_idp.conf | ||
43 | |||
44 | #sleep 6 | ||
45 | |||
46 | gnunet-idp -e eve -C $TICKET_EVE -c test_idp.conf 2&>1 >/dev/null | ||
47 | if test $? == 0 | ||
48 | then | ||
49 | echo "Eve can still resolve attributes..." | ||
50 | gnunet-arm -e -c test_idp.conf | ||
51 | exit 1 | ||
52 | fi | ||
53 | |||
54 | gnunet-arm -e -c test_idp.conf | ||
55 | gnunet-arm -s -c test_idp.conf 2&>1 > /dev/null | ||
56 | |||
57 | gnunet-idp -e bob -C $TICKET_BOB -c test_idp.conf 2&>1 >/dev/null | ||
58 | if test $? != 0 | ||
59 | then | ||
60 | echo "Bob cannot resolve attributes..." | ||
61 | gnunet-arm -e -c test_idp.conf | ||
62 | exit 1 | ||
63 | fi | ||
64 | |||
65 | gnunet-arm -e -c test_idp.conf | ||