diff options
Diffstat (limited to 'src/identity-provider')
-rw-r--r-- | src/identity-provider/plugin_rest_identity_provider.c | 1235 | ||||
-rw-r--r-- | src/identity-provider/test_idp.conf | 5 |
2 files changed, 1228 insertions, 12 deletions
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index 6eb856435..ca42cc50c 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c | |||
@@ -66,6 +66,21 @@ | |||
66 | #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" | 66 | #define GNUNET_REST_API_NS_IDENTITY_CONSUME "/idp/consume" |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * Authorize endpoint | ||
70 | */ | ||
71 | #define GNUNET_REST_API_NS_AUTHORIZE "/idp/authorize" | ||
72 | |||
73 | /** | ||
74 | * Token endpoint | ||
75 | */ | ||
76 | #define GNUNET_REST_API_NS_TOKEN "/idp/token" | ||
77 | |||
78 | /** | ||
79 | * Login namespace | ||
80 | */ | ||
81 | #define GNUNET_REST_API_NS_LOGIN "/idp/login" | ||
82 | |||
83 | /** | ||
69 | * Attribute key | 84 | * Attribute key |
70 | */ | 85 | */ |
71 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" | 86 | #define GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE "attribute" |
@@ -91,6 +106,86 @@ | |||
91 | */ | 106 | */ |
92 | #define ID_REST_STATE_POST_INIT 1 | 107 | #define ID_REST_STATE_POST_INIT 1 |
93 | 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 | /** | ||
151 | * OIDC cookie header information key | ||
152 | */ | ||
153 | #define OIDC_COOKIE_HEADER_INFORMATION_KEY "Identity=" | ||
154 | |||
155 | /** | ||
156 | * OIDC expected response_type while authorizing | ||
157 | */ | ||
158 | #define OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE "code" | ||
159 | |||
160 | /** | ||
161 | * OIDC expected scope part while authorizing | ||
162 | */ | ||
163 | #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid" | ||
164 | |||
165 | /** | ||
166 | * OIDC ignored parameter array | ||
167 | */ | ||
168 | char* OIDC_ignored_parameter_array [] = | ||
169 | { | ||
170 | "display", | ||
171 | "prompt", | ||
172 | "max_age", | ||
173 | "ui_locales", | ||
174 | "response_mode", | ||
175 | "id_token_hint", | ||
176 | "login_hint", | ||
177 | "acr_values" | ||
178 | }; | ||
179 | |||
180 | /** | ||
181 | * OIDC authorized identities and times hashmap | ||
182 | */ | ||
183 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time; | ||
184 | |||
185 | /** | ||
186 | * OIDC authorized identities and times hashmap | ||
187 | */ | ||
188 | struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants; | ||
94 | 189 | ||
95 | /** | 190 | /** |
96 | * The configuration handle | 191 | * The configuration handle |
@@ -110,6 +205,30 @@ struct Plugin | |||
110 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 205 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
111 | }; | 206 | }; |
112 | 207 | ||
208 | struct OIDC_Variables | ||
209 | { | ||
210 | |||
211 | struct GNUNET_CRYPTO_EcdsaPublicKey client_pkey; | ||
212 | |||
213 | char *client_id; | ||
214 | |||
215 | int is_client_trusted; | ||
216 | |||
217 | char *redirect_uri; | ||
218 | |||
219 | char *scope; | ||
220 | |||
221 | char *state; | ||
222 | |||
223 | char *nonce; | ||
224 | |||
225 | char *response_type; | ||
226 | |||
227 | char *login_identity; | ||
228 | |||
229 | json_t *post_object; | ||
230 | }; | ||
231 | |||
113 | /** | 232 | /** |
114 | * The ego list | 233 | * The ego list |
115 | */ | 234 | */ |
@@ -160,9 +279,14 @@ struct RequestHandle | |||
160 | struct EgoEntry *ego_entry; | 279 | struct EgoEntry *ego_entry; |
161 | 280 | ||
162 | /** | 281 | /** |
163 | * Ptr to current ego private key | 282 | * Pointer to ego private key |
164 | */ | 283 | */ |
165 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 284 | struct GNUNET_CRYPTO_EcdsaPrivateKey priv_key; |
285 | |||
286 | /** | ||
287 | * OIDC variables | ||
288 | */ | ||
289 | struct OIDC_Variables *oidc; | ||
166 | 290 | ||
167 | /** | 291 | /** |
168 | * The processing state | 292 | * The processing state |
@@ -179,6 +303,20 @@ struct RequestHandle | |||
179 | */ | 303 | */ |
180 | struct GNUNET_REST_RequestHandle *rest_handle; | 304 | struct GNUNET_REST_RequestHandle *rest_handle; |
181 | 305 | ||
306 | /** | ||
307 | * Handle to NAMESTORE | ||
308 | */ | ||
309 | struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
310 | |||
311 | /** | ||
312 | * Iterator for NAMESTORE | ||
313 | */ | ||
314 | struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; | ||
315 | |||
316 | /** | ||
317 | * Attribute claim list | ||
318 | */ | ||
319 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList *attr_list; | ||
182 | 320 | ||
183 | /** | 321 | /** |
184 | * IDENTITY Operation | 322 | * IDENTITY Operation |
@@ -236,6 +374,11 @@ struct RequestHandle | |||
236 | char *emsg; | 374 | char *emsg; |
237 | 375 | ||
238 | /** | 376 | /** |
377 | * Error response description | ||
378 | */ | ||
379 | char *edesc; | ||
380 | |||
381 | /** | ||
239 | * Reponse code | 382 | * Reponse code |
240 | */ | 383 | */ |
241 | int response_code; | 384 | int response_code; |
@@ -247,8 +390,6 @@ struct RequestHandle | |||
247 | 390 | ||
248 | }; | 391 | }; |
249 | 392 | ||
250 | |||
251 | |||
252 | /** | 393 | /** |
253 | * Cleanup lookup handle | 394 | * Cleanup lookup handle |
254 | * @param handle Handle to clean up | 395 | * @param handle Handle to clean up |
@@ -256,6 +397,8 @@ struct RequestHandle | |||
256 | static void | 397 | static void |
257 | cleanup_handle (struct RequestHandle *handle) | 398 | cleanup_handle (struct RequestHandle *handle) |
258 | { | 399 | { |
400 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_entry; | ||
401 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *claim_tmp; | ||
259 | struct EgoEntry *ego_entry; | 402 | struct EgoEntry *ego_entry; |
260 | struct EgoEntry *ego_tmp; | 403 | struct EgoEntry *ego_tmp; |
261 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 404 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -276,6 +419,42 @@ cleanup_handle (struct RequestHandle *handle) | |||
276 | GNUNET_free (handle->url); | 419 | GNUNET_free (handle->url); |
277 | if (NULL != handle->emsg) | 420 | if (NULL != handle->emsg) |
278 | GNUNET_free (handle->emsg); | 421 | GNUNET_free (handle->emsg); |
422 | if (NULL != handle->edesc) | ||
423 | GNUNET_free (handle->edesc); | ||
424 | if (NULL != handle->namestore_handle) | ||
425 | GNUNET_NAMESTORE_disconnect (handle->namestore_handle); | ||
426 | if (NULL != handle->oidc) | ||
427 | { | ||
428 | if (NULL != handle->oidc->client_id) | ||
429 | GNUNET_free(handle->oidc->client_id); | ||
430 | if (NULL != handle->oidc->login_identity) | ||
431 | GNUNET_free(handle->oidc->login_identity); | ||
432 | if (NULL != handle->oidc->nonce) | ||
433 | GNUNET_free(handle->oidc->nonce); | ||
434 | if (NULL != handle->oidc->redirect_uri) | ||
435 | GNUNET_free(handle->oidc->redirect_uri); | ||
436 | if (NULL != handle->oidc->response_type) | ||
437 | GNUNET_free(handle->oidc->response_type); | ||
438 | if (NULL != handle->oidc->scope) | ||
439 | GNUNET_free(handle->oidc->scope); | ||
440 | if (NULL != handle->oidc->state) | ||
441 | GNUNET_free(handle->oidc->state); | ||
442 | if (NULL != handle->oidc->post_object) | ||
443 | json_decref(handle->oidc->post_object); | ||
444 | GNUNET_free(handle->oidc); | ||
445 | } | ||
446 | if ( NULL != handle->attr_list ) | ||
447 | { | ||
448 | for (claim_entry = handle->attr_list->list_head; | ||
449 | NULL != claim_entry;) | ||
450 | { | ||
451 | claim_tmp = claim_entry; | ||
452 | claim_entry = claim_entry->next; | ||
453 | GNUNET_free(claim_tmp->claim); | ||
454 | GNUNET_free(claim_tmp); | ||
455 | } | ||
456 | GNUNET_free (handle->attr_list); | ||
457 | } | ||
279 | for (ego_entry = handle->ego_head; | 458 | for (ego_entry = handle->ego_head; |
280 | NULL != ego_entry;) | 459 | NULL != ego_entry;) |
281 | { | 460 | { |
@@ -285,6 +464,10 @@ cleanup_handle (struct RequestHandle *handle) | |||
285 | GNUNET_free (ego_tmp->keystring); | 464 | GNUNET_free (ego_tmp->keystring); |
286 | GNUNET_free (ego_tmp); | 465 | GNUNET_free (ego_tmp); |
287 | } | 466 | } |
467 | if (NULL != handle->attr_it) | ||
468 | { | ||
469 | GNUNET_free(handle->attr_it); | ||
470 | } | ||
288 | GNUNET_free (handle); | 471 | GNUNET_free (handle); |
289 | } | 472 | } |
290 | 473 | ||
@@ -307,16 +490,46 @@ do_error (void *cls) | |||
307 | struct MHD_Response *resp; | 490 | struct MHD_Response *resp; |
308 | char *json_error; | 491 | char *json_error; |
309 | 492 | ||
310 | GNUNET_asprintf (&json_error, | 493 | GNUNET_asprintf (&json_error, "{ \"error\" : \"%s\", \"error_description\" : \"%s\"%s%s%s}", |
311 | "{Error while processing request: %s}", | 494 | handle->emsg, |
312 | handle->emsg); | 495 | (NULL != handle->edesc) ? handle->edesc : "", |
496 | (NULL != handle->oidc->state) ? ", \"state\":\"" : "", | ||
497 | (NULL != handle->oidc->state) ? handle->oidc->state : "", | ||
498 | (NULL != handle->oidc->state) ? "\"" : ""); | ||
499 | if ( 0 == handle->response_code ) | ||
500 | { | ||
501 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
502 | } | ||
313 | resp = GNUNET_REST_create_response (json_error); | 503 | resp = GNUNET_REST_create_response (json_error); |
314 | handle->proc (handle->proc_cls, resp, handle->response_code); | 504 | handle->proc (handle->proc_cls, resp, handle->response_code); |
315 | cleanup_handle (handle); | 505 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); |
316 | GNUNET_free (json_error); | 506 | GNUNET_free (json_error); |
317 | } | 507 | } |
318 | 508 | ||
319 | /** | 509 | /** |
510 | * Task run on error, sends error message. Cleans up everything. | ||
511 | * | ||
512 | * @param cls the `struct RequestHandle` | ||
513 | */ | ||
514 | static void | ||
515 | do_redirect_error (void *cls) | ||
516 | { | ||
517 | struct RequestHandle *handle = cls; | ||
518 | struct MHD_Response *resp; | ||
519 | char* redirect; | ||
520 | GNUNET_asprintf (&redirect, | ||
521 | "%s?error=%s&error_description=%s%s%s", | ||
522 | handle->oidc->redirect_uri, handle->emsg, handle->edesc, | ||
523 | (NULL != handle->oidc->state) ? "&state=" : "", | ||
524 | (NULL != handle->oidc->state) ? handle->oidc->state : ""); | ||
525 | resp = GNUNET_REST_create_response (""); | ||
526 | MHD_add_response_header (resp, "Location", redirect); | ||
527 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
528 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
529 | GNUNET_free (redirect); | ||
530 | } | ||
531 | |||
532 | /** | ||
320 | * Task run on timeout, sends error message. Cleans up everything. | 533 | * Task run on timeout, sends error message. Cleans up everything. |
321 | * | 534 | * |
322 | * @param cls the `struct RequestHandle` | 535 | * @param cls the `struct RequestHandle` |
@@ -625,6 +838,7 @@ attr_collect (void *cls, | |||
625 | struct GNUNET_JSONAPI_Resource *json_resource; | 838 | struct GNUNET_JSONAPI_Resource *json_resource; |
626 | struct RequestHandle *handle = cls; | 839 | struct RequestHandle *handle = cls; |
627 | json_t *value; | 840 | json_t *value; |
841 | char* tmp_value; | ||
628 | 842 | ||
629 | if ((NULL == attr->name) || (NULL == attr->data)) | 843 | if ((NULL == attr->name) || (NULL == attr->data)) |
630 | { | 844 | { |
@@ -638,11 +852,17 @@ attr_collect (void *cls, | |||
638 | attr->name); | 852 | attr->name); |
639 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | 853 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); |
640 | 854 | ||
641 | value = json_string (attr->data); | 855 | tmp_value = GNUNET_IDENTITY_ATTRIBUTE_value_to_string (attr->type, |
856 | attr->data, | ||
857 | attr->data_size); | ||
858 | |||
859 | value = json_string (tmp_value); | ||
860 | |||
642 | GNUNET_JSONAPI_resource_add_attr (json_resource, | 861 | GNUNET_JSONAPI_resource_add_attr (json_resource, |
643 | "value", | 862 | "value", |
644 | value); | 863 | value); |
645 | json_decref (value); | 864 | json_decref (value); |
865 | GNUNET_free(tmp_value); | ||
646 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | 866 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); |
647 | } | 867 | } |
648 | 868 | ||
@@ -1013,6 +1233,970 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1013 | } | 1233 | } |
1014 | 1234 | ||
1015 | /** | 1235 | /** |
1236 | * Cookie interpretation | ||
1237 | */ | ||
1238 | static void | ||
1239 | cookie_identity_interpretation (struct RequestHandle *handle) | ||
1240 | { | ||
1241 | struct GNUNET_HashCode cache_key; | ||
1242 | char* cookies; | ||
1243 | struct GNUNET_TIME_Absolute current_time, *relog_time; | ||
1244 | char delimiter[] = "; "; | ||
1245 | |||
1246 | //gets identity of login try with cookie | ||
1247 | GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), | ||
1248 | &cache_key); | ||
1249 | if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, | ||
1250 | &cache_key) ) | ||
1251 | { | ||
1252 | //splits cookies and find 'Identity' cookie | ||
1253 | cookies = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); | ||
1254 | handle->oidc->login_identity = strtok(cookies, delimiter); | ||
1255 | |||
1256 | while ( NULL != handle->oidc->login_identity ) | ||
1257 | { | ||
1258 | if ( NULL != strstr (handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY) ) | ||
1259 | { | ||
1260 | break; | ||
1261 | } | ||
1262 | handle->oidc->login_identity = strtok (NULL, delimiter); | ||
1263 | } | ||
1264 | GNUNET_CRYPTO_hash (handle->oidc->login_identity, strlen (handle->oidc->login_identity), | ||
1265 | &cache_key); | ||
1266 | if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, &cache_key) ) | ||
1267 | { | ||
1268 | relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, | ||
1269 | &cache_key); | ||
1270 | current_time = GNUNET_TIME_absolute_get (); | ||
1271 | // 30 min after old login -> redirect to login | ||
1272 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) | ||
1273 | { | ||
1274 | handle->oidc->login_identity = strtok(handle->oidc->login_identity, OIDC_COOKIE_HEADER_INFORMATION_KEY); | ||
1275 | handle->oidc->login_identity = GNUNET_strdup(handle->oidc->login_identity); | ||
1276 | } | ||
1277 | } | ||
1278 | else | ||
1279 | { | ||
1280 | handle->oidc->login_identity = NULL; | ||
1281 | } | ||
1282 | } | ||
1283 | } | ||
1284 | |||
1285 | /** | ||
1286 | * Login redirection | ||
1287 | */ | ||
1288 | static void | ||
1289 | login_redirection(void *cls) | ||
1290 | { | ||
1291 | char *login_base_url; | ||
1292 | char *new_redirect; | ||
1293 | struct MHD_Response *resp; | ||
1294 | struct RequestHandle *handle = cls; | ||
1295 | |||
1296 | if ( GNUNET_OK | ||
1297 | == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", | ||
1298 | "address", &login_base_url) ) | ||
1299 | { | ||
1300 | GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", | ||
1301 | login_base_url, | ||
1302 | OIDC_RESPONSE_TYPE_KEY, | ||
1303 | handle->oidc->response_type, | ||
1304 | OIDC_CLIENT_ID_KEY, | ||
1305 | handle->oidc->client_id, | ||
1306 | OIDC_REDIRECT_URI_KEY, | ||
1307 | handle->oidc->redirect_uri, | ||
1308 | OIDC_SCOPE_KEY, | ||
1309 | handle->oidc->scope, | ||
1310 | OIDC_STATE_KEY, | ||
1311 | (NULL != handle->oidc->state) ? handle->oidc->state : "", | ||
1312 | OIDC_NONCE_KEY, | ||
1313 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : ""); | ||
1314 | resp = GNUNET_REST_create_response (""); | ||
1315 | MHD_add_response_header (resp, "Location", new_redirect); | ||
1316 | GNUNET_free(login_base_url); | ||
1317 | } | ||
1318 | else | ||
1319 | { | ||
1320 | handle->emsg = GNUNET_strdup("server_error"); | ||
1321 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | ||
1322 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1323 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1324 | return; | ||
1325 | } | ||
1326 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
1327 | GNUNET_free(new_redirect); | ||
1328 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
1329 | } | ||
1330 | |||
1331 | /** | ||
1332 | * Function called if we had an error in zone-to-name mapping. | ||
1333 | */ | ||
1334 | static void | ||
1335 | oidc_iteration_error (void *cls) | ||
1336 | { | ||
1337 | struct RequestHandle *handle = cls; | ||
1338 | handle->emsg = GNUNET_strdup("INTERNAL_SERVER_ERROR"); | ||
1339 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1340 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1341 | } | ||
1342 | |||
1343 | static void | ||
1344 | oidc_ticket_issue_cb (void* cls, | ||
1345 | const struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket) | ||
1346 | { | ||
1347 | struct RequestHandle *handle = cls; | ||
1348 | struct MHD_Response *resp; | ||
1349 | struct GNUNET_HashCode cache_key; | ||
1350 | char* ticket_str; | ||
1351 | char* redirect_uri; | ||
1352 | char* jwt; | ||
1353 | handle->idp_op = NULL; | ||
1354 | resp = GNUNET_REST_create_response (""); | ||
1355 | if (NULL != ticket) { | ||
1356 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, | ||
1357 | sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); | ||
1358 | |||
1359 | |||
1360 | //TODO Check if this is right: | ||
1361 | // GNUNET_CRYPTO_hash (ticket_str, strlen (ticket_str), &cache_key); | ||
1362 | // jwt = jwt_create_from_list (handle->oidc->client_pkey, | ||
1363 | // handle->attr_list, | ||
1364 | // handle->priv_key); | ||
1365 | // //TODO Check success of function | ||
1366 | // GNUNET_CONTAINER_multihashmap_put ( | ||
1367 | // OIDC_identity_grants, &cache_key, jwt, | ||
1368 | // GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
1369 | |||
1370 | |||
1371 | GNUNET_asprintf (&redirect_uri, "%s?%s=%s&state=%s", | ||
1372 | handle->oidc->redirect_uri, | ||
1373 | handle->oidc->response_type, | ||
1374 | ticket_str, handle->oidc->state); | ||
1375 | MHD_add_response_header (resp, "Location", redirect_uri); | ||
1376 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
1377 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
1378 | GNUNET_free (redirect_uri); | ||
1379 | GNUNET_free (ticket_str); | ||
1380 | return; | ||
1381 | } | ||
1382 | handle->emsg = GNUNET_strdup("server_error"); | ||
1383 | handle->edesc = GNUNET_strdup("Server cannot generate ticket."); | ||
1384 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1385 | } | ||
1386 | |||
1387 | static void | ||
1388 | oidc_collect_finished_cb (void *cls) | ||
1389 | { | ||
1390 | struct RequestHandle *handle = cls; | ||
1391 | handle->attr_it = NULL; | ||
1392 | handle->ticket_it = NULL; | ||
1393 | if (NULL == handle->attr_list->list_head) | ||
1394 | { | ||
1395 | handle->emsg = GNUNET_strdup("invalid_scope"); | ||
1396 | handle->edesc = GNUNET_strdup("The requested scope is not available."); | ||
1397 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1398 | return; | ||
1399 | } | ||
1400 | handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_issue (handle->idp, | ||
1401 | &handle->priv_key, | ||
1402 | &handle->oidc->client_pkey, | ||
1403 | handle->attr_list, | ||
1404 | &oidc_ticket_issue_cb, | ||
1405 | handle); | ||
1406 | } | ||
1407 | |||
1408 | |||
1409 | /** | ||
1410 | * Collect all attributes for an ego | ||
1411 | */ | ||
1412 | static void | ||
1413 | oidc_attr_collect (void *cls, | ||
1414 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1415 | const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr) | ||
1416 | { | ||
1417 | struct RequestHandle *handle = cls; | ||
1418 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry *le; | ||
1419 | char* scope_variables; | ||
1420 | char* scope_variable; | ||
1421 | char delimiter[]=" "; | ||
1422 | |||
1423 | if ( (NULL == attr->name) || (NULL == attr->data) ) | ||
1424 | { | ||
1425 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
1426 | return; | ||
1427 | } | ||
1428 | |||
1429 | scope_variables = GNUNET_strdup(handle->oidc->scope); | ||
1430 | scope_variable = strtok (scope_variables, delimiter); | ||
1431 | while (NULL != scope_variable) | ||
1432 | { | ||
1433 | if ( 0 == strcmp (attr->name, scope_variable) ) | ||
1434 | { | ||
1435 | break; | ||
1436 | } | ||
1437 | scope_variable = strtok (NULL, delimiter); | ||
1438 | } | ||
1439 | if ( NULL == scope_variable ) | ||
1440 | { | ||
1441 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
1442 | return; | ||
1443 | } | ||
1444 | GNUNET_free(scope_variables); | ||
1445 | |||
1446 | le = GNUNET_new(struct GNUNET_IDENTITY_ATTRIBUTE_ClaimListEntry); | ||
1447 | le->claim = GNUNET_IDENTITY_ATTRIBUTE_claim_new (attr->name, attr->type, | ||
1448 | attr->data, attr->data_size); | ||
1449 | GNUNET_CONTAINER_DLL_insert(handle->attr_list->list_head, | ||
1450 | handle->attr_list->list_tail, le); | ||
1451 | GNUNET_IDENTITY_PROVIDER_get_attributes_next (handle->attr_it); | ||
1452 | } | ||
1453 | |||
1454 | |||
1455 | /** | ||
1456 | * Cookie and Time check | ||
1457 | */ | ||
1458 | static void | ||
1459 | login_check (void *cls) | ||
1460 | { | ||
1461 | struct RequestHandle *handle = cls; | ||
1462 | struct GNUNET_TIME_Absolute current_time, *relog_time; | ||
1463 | struct GNUNET_CRYPTO_EcdsaPublicKey pubkey, ego_pkey; | ||
1464 | struct GNUNET_HashCode cache_key; | ||
1465 | char *identity_cookie; | ||
1466 | |||
1467 | GNUNET_asprintf (&identity_cookie, "Identity=%s", handle->oidc->login_identity); | ||
1468 | GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); | ||
1469 | GNUNET_free(identity_cookie); | ||
1470 | //No login time for identity -> redirect to login | ||
1471 | if ( GNUNET_YES | ||
1472 | == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_login_time, | ||
1473 | &cache_key) ) | ||
1474 | { | ||
1475 | relog_time = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_login_time, | ||
1476 | &cache_key); | ||
1477 | current_time = GNUNET_TIME_absolute_get (); | ||
1478 | // 30 min after old login -> redirect to login | ||
1479 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) | ||
1480 | { | ||
1481 | if ( GNUNET_OK | ||
1482 | != GNUNET_CRYPTO_ecdsa_public_key_from_string ( | ||
1483 | handle->oidc->login_identity, | ||
1484 | strlen (handle->oidc->login_identity), &pubkey) ) | ||
1485 | { | ||
1486 | handle->emsg = GNUNET_strdup("invalid_cookie"); | ||
1487 | handle->edesc = GNUNET_strdup( | ||
1488 | "The cookie of a login identity is not valid"); | ||
1489 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1490 | return; | ||
1491 | } | ||
1492 | // iterate over egos and compare their public key | ||
1493 | for (handle->ego_entry = handle->ego_head; | ||
1494 | NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next) | ||
1495 | { | ||
1496 | GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, &ego_pkey); | ||
1497 | if ( 0 | ||
1498 | == memcmp (&ego_pkey, &pubkey, | ||
1499 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1500 | { | ||
1501 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key ( | ||
1502 | handle->ego_entry->ego); | ||
1503 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
1504 | handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg); | ||
1505 | handle->attr_list = GNUNET_new( | ||
1506 | struct GNUNET_IDENTITY_ATTRIBUTE_ClaimList); | ||
1507 | handle->attr_it = GNUNET_IDENTITY_PROVIDER_get_attributes_start ( | ||
1508 | handle->idp, &handle->priv_key, &oidc_iteration_error, handle, | ||
1509 | &oidc_attr_collect, handle, &oidc_collect_finished_cb, handle); | ||
1510 | return; | ||
1511 | } | ||
1512 | } | ||
1513 | handle->emsg = GNUNET_strdup("invalid_cookie"); | ||
1514 | handle->edesc = GNUNET_strdup( | ||
1515 | "The cookie of the login identity is not valid"); | ||
1516 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1517 | return; | ||
1518 | } | ||
1519 | //GNUNET_free(relog_time); | ||
1520 | } | ||
1521 | } | ||
1522 | |||
1523 | /** | ||
1524 | * Create a response with requested records | ||
1525 | * | ||
1526 | * @param handle the RequestHandle | ||
1527 | */ | ||
1528 | static void | ||
1529 | namestore_iteration_callback ( | ||
1530 | void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | ||
1531 | const char *rname, unsigned int rd_len, | ||
1532 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1533 | { | ||
1534 | struct RequestHandle *handle = cls; | ||
1535 | struct GNUNET_CRYPTO_EcdsaPublicKey login_identity_pkey; | ||
1536 | struct GNUNET_CRYPTO_EcdsaPublicKey current_zone_pkey; | ||
1537 | int i; | ||
1538 | |||
1539 | for (i = 0; i < rd_len; i++) | ||
1540 | { | ||
1541 | if ( GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type ) | ||
1542 | continue; | ||
1543 | |||
1544 | if ( NULL != handle->oidc->login_identity ) | ||
1545 | { | ||
1546 | GNUNET_CRYPTO_ecdsa_public_key_from_string ( | ||
1547 | handle->oidc->login_identity, | ||
1548 | strlen (handle->oidc->login_identity), | ||
1549 | &login_identity_pkey); | ||
1550 | GNUNET_IDENTITY_ego_get_public_key (handle->ego_entry->ego, | ||
1551 | ¤t_zone_pkey); | ||
1552 | |||
1553 | if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, | ||
1554 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1555 | { | ||
1556 | if ( 0 == memcmp (&login_identity_pkey, ¤t_zone_pkey, | ||
1557 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1558 | { | ||
1559 | handle->oidc->is_client_trusted = GNUNET_YES; | ||
1560 | } | ||
1561 | } | ||
1562 | } | ||
1563 | else | ||
1564 | { | ||
1565 | if ( 0 == memcmp (rd[i].data, &handle->oidc->client_pkey, | ||
1566 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) ) | ||
1567 | { | ||
1568 | handle->oidc->is_client_trusted = GNUNET_YES; | ||
1569 | } | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | GNUNET_NAMESTORE_zone_iterator_next (handle->namestore_handle_it); | ||
1574 | } | ||
1575 | |||
1576 | /** | ||
1577 | * Iteration over all results finished, build final | ||
1578 | * response. | ||
1579 | * | ||
1580 | * @param cls the `struct RequestHandle` | ||
1581 | */ | ||
1582 | static void namestore_iteration_finished_GET (void *cls) | ||
1583 | { | ||
1584 | struct RequestHandle *handle = cls; | ||
1585 | struct GNUNET_HashCode cache_key; | ||
1586 | |||
1587 | char *expected_redirect_uri; | ||
1588 | char *expected_scope; | ||
1589 | char delimiter[]=" "; | ||
1590 | int number_of_ignored_parameter, iterator; | ||
1591 | |||
1592 | |||
1593 | handle->ego_entry = handle->ego_entry->next; | ||
1594 | |||
1595 | if(NULL != handle->ego_entry) | ||
1596 | { | ||
1597 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | ||
1598 | handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key, | ||
1599 | &oidc_iteration_error, handle, &namestore_iteration_callback, handle, | ||
1600 | &namestore_iteration_finished_GET, handle); | ||
1601 | return; | ||
1602 | } | ||
1603 | if (GNUNET_NO == handle->oidc->is_client_trusted) | ||
1604 | { | ||
1605 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1606 | handle->edesc = GNUNET_strdup("The client is not authorized to request an " | ||
1607 | "authorization code using this method."); | ||
1608 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1609 | return; | ||
1610 | } | ||
1611 | |||
1612 | // REQUIRED value: redirect_uri | ||
1613 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), | ||
1614 | &cache_key); | ||
1615 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1616 | &cache_key)) | ||
1617 | { | ||
1618 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1619 | handle->edesc=GNUNET_strdup("missing parameter redirect_uri"); | ||
1620 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1621 | return; | ||
1622 | } | ||
1623 | handle->oidc->redirect_uri = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1624 | &cache_key); | ||
1625 | |||
1626 | GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", handle->oidc->client_id); | ||
1627 | // verify the redirect uri matches https://<client_id>.zkey[/xyz] | ||
1628 | if( 0 != strncmp( expected_redirect_uri, handle->oidc->redirect_uri, strlen(expected_redirect_uri)) ) | ||
1629 | { | ||
1630 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1631 | handle->edesc=GNUNET_strdup("Invalid redirect_uri"); | ||
1632 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1633 | GNUNET_free(expected_redirect_uri); | ||
1634 | return; | ||
1635 | } | ||
1636 | handle->oidc->redirect_uri = GNUNET_strdup(handle->oidc->redirect_uri); | ||
1637 | |||
1638 | GNUNET_free(expected_redirect_uri); | ||
1639 | // REQUIRED value: response_type | ||
1640 | GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY), | ||
1641 | &cache_key); | ||
1642 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1643 | &cache_key)) | ||
1644 | { | ||
1645 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1646 | handle->edesc=GNUNET_strdup("missing parameter response_type"); | ||
1647 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1648 | return; | ||
1649 | } | ||
1650 | handle->oidc->response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1651 | &cache_key); | ||
1652 | handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type); | ||
1653 | |||
1654 | // REQUIRED value: scope | ||
1655 | GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key); | ||
1656 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1657 | &cache_key)) | ||
1658 | { | ||
1659 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1660 | handle->edesc=GNUNET_strdup("missing parameter scope"); | ||
1661 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1662 | return; | ||
1663 | } | ||
1664 | handle->oidc->scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1665 | &cache_key); | ||
1666 | handle->oidc->scope = GNUNET_strdup(handle->oidc->scope); | ||
1667 | |||
1668 | //OPTIONAL value: nonce | ||
1669 | GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key); | ||
1670 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1671 | &cache_key)) | ||
1672 | { | ||
1673 | handle->oidc->nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1674 | &cache_key); | ||
1675 | //TODO: what do we do with the nonce? | ||
1676 | handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce); | ||
1677 | } | ||
1678 | |||
1679 | //TODO check other values and use them accordingly | ||
1680 | number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); | ||
1681 | for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) | ||
1682 | { | ||
1683 | GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], | ||
1684 | strlen(OIDC_ignored_parameter_array[iterator]), | ||
1685 | &cache_key); | ||
1686 | if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map, | ||
1687 | &cache_key)) | ||
1688 | { | ||
1689 | handle->emsg=GNUNET_strdup("access_denied"); | ||
1690 | GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s", | ||
1691 | OIDC_ignored_parameter_array[iterator]); | ||
1692 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1693 | return; | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | // Checks if response_type is 'code' | ||
1698 | if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) | ||
1699 | { | ||
1700 | handle->emsg=GNUNET_strdup("unsupported_response_type"); | ||
1701 | handle->edesc=GNUNET_strdup("The authorization server does not support " | ||
1702 | "obtaining this authorization code."); | ||
1703 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1704 | return; | ||
1705 | } | ||
1706 | |||
1707 | // Checks if scope contains 'openid' | ||
1708 | expected_scope = GNUNET_strdup(handle->oidc->scope); | ||
1709 | expected_scope = strtok (expected_scope, delimiter); | ||
1710 | while (NULL != expected_scope) | ||
1711 | { | ||
1712 | if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) ) | ||
1713 | { | ||
1714 | break; | ||
1715 | } | ||
1716 | expected_scope = strtok (NULL, delimiter); | ||
1717 | } | ||
1718 | if (NULL == expected_scope) | ||
1719 | { | ||
1720 | handle->emsg = GNUNET_strdup("invalid_scope"); | ||
1721 | handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " | ||
1722 | "malformed."); | ||
1723 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1724 | return; | ||
1725 | } | ||
1726 | |||
1727 | GNUNET_free(expected_scope); | ||
1728 | |||
1729 | if( NULL != handle->oidc->login_identity ) | ||
1730 | { | ||
1731 | GNUNET_SCHEDULER_add_now(&login_check,handle); | ||
1732 | return; | ||
1733 | } | ||
1734 | |||
1735 | GNUNET_SCHEDULER_add_now(&login_redirection,handle); | ||
1736 | } | ||
1737 | |||
1738 | /** | ||
1739 | * Responds to authorization GET request | ||
1740 | * | ||
1741 | * @param con_handle the connection handle | ||
1742 | * @param url the url | ||
1743 | * @param cls the RequestHandle | ||
1744 | */ | ||
1745 | static void | ||
1746 | authorize_GET_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1747 | const char* url, | ||
1748 | void *cls) | ||
1749 | { | ||
1750 | struct RequestHandle *handle = cls; | ||
1751 | struct GNUNET_HashCode cache_key; | ||
1752 | |||
1753 | cookie_identity_interpretation(handle); | ||
1754 | |||
1755 | //RECOMMENDED value: state - REQUIRED for answers | ||
1756 | GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key); | ||
1757 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1758 | &cache_key)) | ||
1759 | { | ||
1760 | handle->oidc->state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1761 | &cache_key); | ||
1762 | handle->oidc->state = GNUNET_strdup (handle->oidc->state); | ||
1763 | } | ||
1764 | |||
1765 | // REQUIRED value: client_id | ||
1766 | GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), | ||
1767 | &cache_key); | ||
1768 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1769 | &cache_key)) | ||
1770 | { | ||
1771 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1772 | handle->edesc=GNUNET_strdup("missing parameter client_id"); | ||
1773 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1774 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1775 | return; | ||
1776 | } | ||
1777 | handle->oidc->client_id = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1778 | &cache_key); | ||
1779 | handle->oidc->client_id = GNUNET_strdup (handle->oidc->client_id); | ||
1780 | |||
1781 | if ( GNUNET_OK | ||
1782 | != GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->oidc->client_id, | ||
1783 | strlen (handle->oidc->client_id), | ||
1784 | &handle->oidc->client_pkey) ) | ||
1785 | { | ||
1786 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1787 | handle->edesc = GNUNET_strdup("The client is not authorized to request an " | ||
1788 | "authorization code using this method."); | ||
1789 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1790 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1791 | return; | ||
1792 | } | ||
1793 | |||
1794 | |||
1795 | if ( NULL == handle->ego_head ) | ||
1796 | { | ||
1797 | //TODO throw error or ignore if egos are missing? | ||
1798 | handle->emsg = GNUNET_strdup("server_error"); | ||
1799 | handle->edesc = GNUNET_strdup ("Egos are missing"); | ||
1800 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1801 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1802 | return; | ||
1803 | } | ||
1804 | |||
1805 | handle->ego_entry = handle->ego_head; | ||
1806 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); | ||
1807 | handle->oidc->is_client_trusted = GNUNET_NO; | ||
1808 | |||
1809 | // Checks if client_id is valid: | ||
1810 | handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start ( | ||
1811 | handle->namestore_handle, &handle->priv_key, &oidc_iteration_error, | ||
1812 | handle, &namestore_iteration_callback, handle, | ||
1813 | &namestore_iteration_finished_GET, handle); | ||
1814 | } | ||
1815 | |||
1816 | /** | ||
1817 | * Iteration over all results finished, build final | ||
1818 | * response. | ||
1819 | * | ||
1820 | * @param cls the `struct RequestHandle` | ||
1821 | */ | ||
1822 | static void namestore_iteration_finished_POST (void *cls) | ||
1823 | { | ||
1824 | struct RequestHandle *handle = cls; | ||
1825 | json_t *cache_object; | ||
1826 | char *expected_redirect_uri; | ||
1827 | char *expected_scope; | ||
1828 | char delimiter[]=" "; | ||
1829 | int number_of_ignored_parameter, iterator; | ||
1830 | |||
1831 | |||
1832 | handle->ego_entry = handle->ego_entry->next; | ||
1833 | |||
1834 | if(NULL != handle->ego_entry){ | ||
1835 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | ||
1836 | handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start (handle->namestore_handle, &handle->priv_key, | ||
1837 | &oidc_iteration_error, handle, &namestore_iteration_callback, handle, | ||
1838 | &namestore_iteration_finished_POST, handle); | ||
1839 | return; | ||
1840 | } | ||
1841 | if (GNUNET_YES != handle->oidc->is_client_trusted) | ||
1842 | { | ||
1843 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1844 | handle->edesc = GNUNET_strdup("The client is not authorized to request an " | ||
1845 | "authorization code using this method."); | ||
1846 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1847 | return; | ||
1848 | } | ||
1849 | |||
1850 | // REQUIRED value: redirect_uri | ||
1851 | cache_object = json_object_get (handle->oidc->post_object, OIDC_REDIRECT_URI_KEY); | ||
1852 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
1853 | { | ||
1854 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1855 | handle->edesc=GNUNET_strdup("missing parameter redirect_uri"); | ||
1856 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1857 | return; | ||
1858 | } | ||
1859 | handle->oidc->redirect_uri = json_string_value (cache_object); | ||
1860 | |||
1861 | GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", handle->oidc->client_id); | ||
1862 | // verify the redirect uri matches https://<client_id>.zkey[/xyz] | ||
1863 | if( 0 != strncmp( expected_redirect_uri, handle->oidc->redirect_uri, strlen(expected_redirect_uri)) ) | ||
1864 | { | ||
1865 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1866 | handle->edesc=GNUNET_strdup("Invalid redirect_uri"); | ||
1867 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1868 | GNUNET_free(expected_redirect_uri); | ||
1869 | return; | ||
1870 | } | ||
1871 | handle->oidc->redirect_uri = GNUNET_strdup(handle->oidc->redirect_uri); | ||
1872 | GNUNET_free(expected_redirect_uri); | ||
1873 | |||
1874 | // REQUIRED value: response_type | ||
1875 | cache_object = json_object_get (handle->oidc->post_object, OIDC_RESPONSE_TYPE_KEY); | ||
1876 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
1877 | { | ||
1878 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1879 | handle->edesc=GNUNET_strdup("missing parameter response_type"); | ||
1880 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1881 | return; | ||
1882 | } | ||
1883 | handle->oidc->response_type = json_string_value (cache_object); | ||
1884 | handle->oidc->response_type = GNUNET_strdup (handle->oidc->response_type); | ||
1885 | |||
1886 | // REQUIRED value: scope | ||
1887 | cache_object = json_object_get (handle->oidc->post_object, OIDC_SCOPE_KEY); | ||
1888 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
1889 | { | ||
1890 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1891 | handle->edesc=GNUNET_strdup("missing parameter scope"); | ||
1892 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1893 | return; | ||
1894 | } | ||
1895 | handle->oidc->scope = json_string_value (cache_object); | ||
1896 | handle->oidc->scope = GNUNET_strdup(handle->oidc->scope); | ||
1897 | |||
1898 | //OPTIONAL value: nonce | ||
1899 | cache_object = json_object_get (handle->oidc->post_object, OIDC_NONCE_KEY); | ||
1900 | if ( NULL != cache_object && json_is_string(cache_object) ) | ||
1901 | { | ||
1902 | handle->oidc->nonce = json_string_value (cache_object); | ||
1903 | //TODO: what do we do with the nonce? | ||
1904 | handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce); | ||
1905 | } | ||
1906 | |||
1907 | //TODO check other values and use them accordingly | ||
1908 | number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); | ||
1909 | for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) | ||
1910 | { | ||
1911 | cache_object = json_object_get (handle->oidc->post_object, OIDC_ignored_parameter_array[iterator]); | ||
1912 | if( NULL != cache_object && json_is_string(cache_object) ) | ||
1913 | { | ||
1914 | handle->emsg=GNUNET_strdup("access_denied"); | ||
1915 | GNUNET_asprintf (&handle->edesc, "Server will not handle parameter: %s", | ||
1916 | OIDC_ignored_parameter_array[iterator]); | ||
1917 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1918 | return; | ||
1919 | } | ||
1920 | } | ||
1921 | |||
1922 | // Checks if response_type is 'code' | ||
1923 | if( 0 != strcmp( handle->oidc->response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) | ||
1924 | { | ||
1925 | handle->emsg=GNUNET_strdup("unsupported_response_type"); | ||
1926 | handle->edesc=GNUNET_strdup("The authorization server does not support " | ||
1927 | "obtaining this authorization code."); | ||
1928 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1929 | return; | ||
1930 | } | ||
1931 | |||
1932 | // Checks if scope contains 'openid' | ||
1933 | expected_scope = GNUNET_strdup(handle->oidc->scope); | ||
1934 | expected_scope = strtok (expected_scope, delimiter); | ||
1935 | while (NULL != expected_scope) | ||
1936 | { | ||
1937 | if ( 0 == strcmp (OIDC_EXPECTED_AUTHORIZATION_SCOPE, expected_scope) ) | ||
1938 | { | ||
1939 | break; | ||
1940 | } | ||
1941 | expected_scope = strtok (NULL, delimiter); | ||
1942 | } | ||
1943 | if (NULL == expected_scope) | ||
1944 | { | ||
1945 | handle->emsg = GNUNET_strdup("invalid_scope"); | ||
1946 | handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " | ||
1947 | "malformed."); | ||
1948 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1949 | return; | ||
1950 | } | ||
1951 | |||
1952 | GNUNET_free(expected_scope); | ||
1953 | |||
1954 | if( NULL != handle->oidc->login_identity ) | ||
1955 | { | ||
1956 | GNUNET_SCHEDULER_add_now(&login_check,handle); | ||
1957 | return; | ||
1958 | } | ||
1959 | |||
1960 | GNUNET_SCHEDULER_add_now(&login_redirection,handle); | ||
1961 | } | ||
1962 | |||
1963 | |||
1964 | /** | ||
1965 | * Responds to authorization POST request | ||
1966 | * | ||
1967 | * @param con_handle the connection handle | ||
1968 | * @param url the url | ||
1969 | * @param cls the RequestHandle | ||
1970 | */ | ||
1971 | static void | ||
1972 | authorize_POST_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1973 | const char* url, | ||
1974 | void *cls) | ||
1975 | { | ||
1976 | struct RequestHandle *handle = cls; | ||
1977 | json_t *cache_object; | ||
1978 | json_error_t error; | ||
1979 | handle->oidc->post_object = json_loads (handle->rest_handle->data, 0, &error); | ||
1980 | |||
1981 | //gets identity of login try with cookie | ||
1982 | cookie_identity_interpretation(handle); | ||
1983 | |||
1984 | //RECOMMENDED value: state - REQUIRED for answers | ||
1985 | cache_object = json_object_get (handle->oidc->post_object, OIDC_STATE_KEY); | ||
1986 | if ( NULL != cache_object && json_is_string(cache_object) ) | ||
1987 | { | ||
1988 | handle->oidc->state = json_string_value (cache_object); | ||
1989 | handle->oidc->state = GNUNET_strdup(handle->oidc->state); | ||
1990 | } | ||
1991 | |||
1992 | // REQUIRED value: client_id | ||
1993 | cache_object = json_object_get (handle->oidc->post_object, | ||
1994 | OIDC_CLIENT_ID_KEY); | ||
1995 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
1996 | { | ||
1997 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1998 | handle->edesc = GNUNET_strdup("missing parameter client_id"); | ||
1999 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
2000 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2001 | return; | ||
2002 | } | ||
2003 | handle->oidc->client_id = json_string_value (cache_object); | ||
2004 | handle->oidc->client_id = GNUNET_strdup(handle->oidc->client_id); | ||
2005 | |||
2006 | if ( GNUNET_OK | ||
2007 | != GNUNET_CRYPTO_ecdsa_public_key_from_string ( | ||
2008 | handle->oidc->client_id, strlen (handle->oidc->client_id), | ||
2009 | &handle->oidc->client_pkey) ) | ||
2010 | { | ||
2011 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
2012 | handle->edesc = GNUNET_strdup("The client is not authorized to request an " | ||
2013 | "authorization code using this method."); | ||
2014 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
2015 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2016 | return; | ||
2017 | } | ||
2018 | |||
2019 | if ( NULL == handle->ego_head ) | ||
2020 | { | ||
2021 | //TODO throw error or ignore if egos are missing? | ||
2022 | handle->emsg = GNUNET_strdup("server_error"); | ||
2023 | handle->edesc = GNUNET_strdup ("Egos are missing"); | ||
2024 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
2025 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2026 | return; | ||
2027 | } | ||
2028 | |||
2029 | handle->ego_entry = handle->ego_head; | ||
2030 | handle->priv_key = *GNUNET_IDENTITY_ego_get_private_key (handle->ego_head->ego); | ||
2031 | handle->oidc->is_client_trusted = GNUNET_NO; | ||
2032 | |||
2033 | // Checks if client_id is valid: | ||
2034 | handle->namestore_handle_it = GNUNET_NAMESTORE_zone_iteration_start ( | ||
2035 | handle->namestore_handle, &handle->priv_key, &oidc_iteration_error, | ||
2036 | handle, &namestore_iteration_callback, handle, | ||
2037 | &namestore_iteration_finished_POST, handle); | ||
2038 | } | ||
2039 | |||
2040 | /** | ||
2041 | * Combines an identity with a login time and responds OK to login request | ||
2042 | * | ||
2043 | * @param con_handle the connection handle | ||
2044 | * @param url the url | ||
2045 | * @param cls the RequestHandle | ||
2046 | */ | ||
2047 | static void | ||
2048 | login_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
2049 | const char* url, | ||
2050 | void *cls) | ||
2051 | { | ||
2052 | struct MHD_Response *resp = GNUNET_REST_create_response (""); | ||
2053 | struct RequestHandle *handle = cls; | ||
2054 | struct GNUNET_HashCode cache_key; | ||
2055 | struct GNUNET_TIME_Absolute *current_time; | ||
2056 | struct GNUNET_TIME_Absolute *last_time; | ||
2057 | char* cookie; | ||
2058 | json_t *root; | ||
2059 | json_error_t error; | ||
2060 | json_t *identity; | ||
2061 | root = json_loads (handle->rest_handle->data, 0, &error); | ||
2062 | identity = json_object_get (root, "identity"); | ||
2063 | if ( json_is_string(identity) ) | ||
2064 | { | ||
2065 | GNUNET_asprintf (&cookie, "Identity=%s", json_string_value (identity)); | ||
2066 | |||
2067 | GNUNET_CRYPTO_hash (cookie, strlen (cookie), &cache_key); | ||
2068 | |||
2069 | current_time = GNUNET_new(struct GNUNET_TIME_Absolute); | ||
2070 | *current_time = GNUNET_TIME_relative_to_absolute ( | ||
2071 | GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_minute_ (), | ||
2072 | 30)); | ||
2073 | last_time = GNUNET_CONTAINER_multihashmap_get(OIDC_identity_login_time, &cache_key); | ||
2074 | if (NULL != last_time) | ||
2075 | { | ||
2076 | GNUNET_free(last_time); | ||
2077 | } | ||
2078 | GNUNET_CONTAINER_multihashmap_put ( | ||
2079 | OIDC_identity_login_time, &cache_key, current_time, | ||
2080 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
2081 | |||
2082 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
2083 | } | ||
2084 | else | ||
2085 | { | ||
2086 | handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); | ||
2087 | } | ||
2088 | GNUNET_free(cookie); | ||
2089 | json_decref (root); | ||
2090 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
2091 | return; | ||
2092 | } | ||
2093 | |||
2094 | static void | ||
2095 | token_cont(struct GNUNET_REST_RequestHandle *con_handle, | ||
2096 | const char* url, | ||
2097 | void *cls) | ||
2098 | { | ||
2099 | //TODO static strings | ||
2100 | struct RequestHandle *handle = cls; | ||
2101 | struct GNUNET_HashCode cache_key; | ||
2102 | char *authorization, *cache_authorization, *jwt; | ||
2103 | char delimiter[]=" "; | ||
2104 | json_t *cache_object; | ||
2105 | json_error_t error; | ||
2106 | char *grant_type, *code, *expected_jwt, *redirect_uri, *expected_redirect_uri; | ||
2107 | |||
2108 | handle->oidc->post_object = json_loads (handle->rest_handle->data, 0, &error); | ||
2109 | //Check Authorization Header | ||
2110 | GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), | ||
2111 | &cache_key); | ||
2112 | if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, | ||
2113 | &cache_key) ) | ||
2114 | { | ||
2115 | //error | ||
2116 | } | ||
2117 | authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); | ||
2118 | //split JWT in "Base" and [content] | ||
2119 | cache_authorization = GNUNET_strdup (authorization); | ||
2120 | jwt = strtok(cache_authorization,delimiter); | ||
2121 | if( NULL != jwt) | ||
2122 | { | ||
2123 | jwt = strtok(jwt, delimiter); | ||
2124 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Test:%s\n", jwt); | ||
2125 | } | ||
2126 | |||
2127 | cache_object = json_object_get (handle->oidc->post_object, "grant_type"); | ||
2128 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
2129 | { | ||
2130 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
2131 | handle->edesc=GNUNET_strdup("missing parameter grant_type"); | ||
2132 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2133 | return; | ||
2134 | } | ||
2135 | grant_type = json_string_value (cache_object); | ||
2136 | |||
2137 | //Check parameter grant_type == "authorization_code" | ||
2138 | if (0 != strcmp("authorization_code", grant_type)) | ||
2139 | { | ||
2140 | //error | ||
2141 | } | ||
2142 | |||
2143 | cache_object = json_object_get (handle->oidc->post_object, "code"); | ||
2144 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
2145 | { | ||
2146 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
2147 | handle->edesc=GNUNET_strdup("missing parameter code"); | ||
2148 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2149 | return; | ||
2150 | } | ||
2151 | code = json_string_value (cache_object); | ||
2152 | |||
2153 | // lookup code in grants_hashmap and check if [content] is same | ||
2154 | GNUNET_CRYPTO_hash(code, strlen(code), &cache_key); | ||
2155 | if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_identity_grants, &cache_key) ) | ||
2156 | { | ||
2157 | //error | ||
2158 | } | ||
2159 | expected_jwt = GNUNET_CONTAINER_multihashmap_get (OIDC_identity_grants, &cache_key); | ||
2160 | |||
2161 | if (0 != strcmp(expected_jwt,jwt)) | ||
2162 | { | ||
2163 | //error | ||
2164 | } | ||
2165 | |||
2166 | cache_object = json_object_get (handle->oidc->post_object, "redirect_uri"); | ||
2167 | if ( NULL == cache_object || !json_is_string(cache_object) ) | ||
2168 | { | ||
2169 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
2170 | handle->edesc=GNUNET_strdup("missing parameter code"); | ||
2171 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2172 | return; | ||
2173 | } | ||
2174 | redirect_uri = json_string_value (cache_object); | ||
2175 | |||
2176 | // check redirect_uri | ||
2177 | // jwt breakdown to iss or sub | ||
2178 | |||
2179 | // GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", iss); | ||
2180 | // // verify the redirect uri matches https://<client_id>.zkey[/xyz] | ||
2181 | // if( 0 != strncmp( expected_redirect_uri, redirect_uri, strlen(expected_redirect_uri)) ) | ||
2182 | // { | ||
2183 | // handle->emsg=GNUNET_strdup("invalid_request"); | ||
2184 | // handle->edesc=GNUNET_strdup("Invalid redirect_uri"); | ||
2185 | // GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
2186 | // GNUNET_free(expected_redirect_uri); | ||
2187 | // return; | ||
2188 | // } | ||
2189 | // handle->oidc->redirect_uri = GNUNET_strdup(handle->oidc->redirect_uri); | ||
2190 | // GNUNET_free(expected_redirect_uri); | ||
2191 | |||
2192 | |||
2193 | //do we need the client_id? | ||
2194 | |||
2195 | GNUNET_free(cache_authorization); | ||
2196 | decref(handle->oidc->post_object); | ||
2197 | } | ||
2198 | |||
2199 | /** | ||
1016 | * Handle rest request | 2200 | * Handle rest request |
1017 | * | 2201 | * |
1018 | * @param handle the request handle | 2202 | * @param handle the request handle |
@@ -1025,6 +2209,10 @@ init_cont (struct RequestHandle *handle) | |||
1025 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, | 2209 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, |
1026 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, | 2210 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, |
1027 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, | 2211 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, |
2212 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_GET_cont}, | ||
2213 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_POST_cont}, | ||
2214 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, | ||
2215 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_cont}, | ||
1028 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, | 2216 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, |
1029 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, | 2217 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, |
1030 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, | 2218 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, |
@@ -1109,7 +2297,12 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | |||
1109 | void *proc_cls) | 2297 | void *proc_cls) |
1110 | { | 2298 | { |
1111 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | 2299 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); |
1112 | 2300 | handle->oidc = GNUNET_new (struct OIDC_Variables); | |
2301 | if ( NULL == OIDC_identity_login_time ) | ||
2302 | OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2303 | if ( NULL == OIDC_identity_grants ) | ||
2304 | OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); | ||
2305 | handle->response_code = 0; | ||
1113 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | 2306 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; |
1114 | handle->proc_cls = proc_cls; | 2307 | handle->proc_cls = proc_cls; |
1115 | handle->proc = proc; | 2308 | handle->proc = proc; |
@@ -1124,6 +2317,7 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | |||
1124 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, | 2317 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, |
1125 | &list_ego, | 2318 | &list_ego, |
1126 | handle); | 2319 | handle); |
2320 | handle->namestore_handle = GNUNET_NAMESTORE_connect (cfg); | ||
1127 | handle->timeout_task = | 2321 | handle->timeout_task = |
1128 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | 2322 | GNUNET_SCHEDULER_add_delayed (handle->timeout, |
1129 | &do_timeout, | 2323 | &do_timeout, |
@@ -1178,8 +2372,27 @@ libgnunet_plugin_rest_identity_provider_done (void *cls) | |||
1178 | { | 2372 | { |
1179 | struct GNUNET_REST_Plugin *api = cls; | 2373 | struct GNUNET_REST_Plugin *api = cls; |
1180 | struct Plugin *plugin = api->cls; | 2374 | struct Plugin *plugin = api->cls; |
1181 | |||
1182 | plugin->cfg = NULL; | 2375 | plugin->cfg = NULL; |
2376 | |||
2377 | struct GNUNET_CONTAINER_MultiHashMapIterator *hashmap_it; | ||
2378 | void *value = NULL; | ||
2379 | hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create ( | ||
2380 | OIDC_identity_login_time); | ||
2381 | while (GNUNET_YES == | ||
2382 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) | ||
2383 | { | ||
2384 | if (NULL != value) | ||
2385 | GNUNET_free(value); | ||
2386 | } | ||
2387 | GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_login_time); | ||
2388 | hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_identity_grants); | ||
2389 | while (GNUNET_YES == | ||
2390 | GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value)) | ||
2391 | { | ||
2392 | if (NULL != value) | ||
2393 | GNUNET_free(value); | ||
2394 | } | ||
2395 | GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants); | ||
1183 | GNUNET_free_non_null (allow_methods); | 2396 | GNUNET_free_non_null (allow_methods); |
1184 | GNUNET_free (api); | 2397 | GNUNET_free (api); |
1185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2398 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
diff --git a/src/identity-provider/test_idp.conf b/src/identity-provider/test_idp.conf index 2b76c7bf2..95111df3e 100644 --- a/src/identity-provider/test_idp.conf +++ b/src/identity-provider/test_idp.conf | |||
@@ -8,7 +8,7 @@ AUTOSTART = YES | |||
8 | 8 | ||
9 | [rest] | 9 | [rest] |
10 | AUTOSTART = YES | 10 | AUTOSTART = YES |
11 | #PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog | 11 | PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/restlog |
12 | 12 | ||
13 | [transport] | 13 | [transport] |
14 | PLUGINS = | 14 | PLUGINS = |
@@ -26,3 +26,6 @@ DEFAULT_LOOKUP_TIMEOUT = 15 s | |||
26 | RECORD_PUT_INTERVAL = 1 h | 26 | RECORD_PUT_INTERVAL = 1 h |
27 | ZONE_PUBLISH_TIME_WINDOW = 1 h | 27 | ZONE_PUBLISH_TIME_WINDOW = 1 h |
28 | DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 | 28 | DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 |
29 | |||
30 | [identity-rest-plugin] | ||
31 | address = http://localhost:8000/#/identities \ No newline at end of file | ||