diff options
author | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-07-23 12:42:18 +0200 |
---|---|---|
committer | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-07-23 12:42:18 +0200 |
commit | 97b5905aac2954fd0ce618b86ae80d11671fa1ba (patch) | |
tree | 0ea14c61e4c0a7ef3deadd82be45280075a8864c /src/reclaim/plugin_rest_openid_connect.c | |
parent | 98defb69b11bc6ca89cd1b5419de5036004626c4 (diff) | |
download | gnunet-97b5905aac2954fd0ce618b86ae80d11671fa1ba.tar.gz gnunet-97b5905aac2954fd0ce618b86ae80d11671fa1ba.zip |
refactoring of OIDC plugin
Diffstat (limited to 'src/reclaim/plugin_rest_openid_connect.c')
-rw-r--r-- | src/reclaim/plugin_rest_openid_connect.c | 531 |
1 files changed, 186 insertions, 345 deletions
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 0f746f988..06815d9d1 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "gnunet_signatures.h" | 38 | #include "gnunet_signatures.h" |
39 | #include "gnunet_reclaim_attribute_lib.h" | 39 | #include "gnunet_reclaim_attribute_lib.h" |
40 | #include "gnunet_reclaim_service.h" | 40 | #include "gnunet_reclaim_service.h" |
41 | #include "jwt.h" | 41 | #include "oidc_helper.h" |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * REST root namespace | 44 | * REST root namespace |
@@ -823,177 +823,6 @@ oidc_iteration_error (void *cls) | |||
823 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 823 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
824 | } | 824 | } |
825 | 825 | ||
826 | static int | ||
827 | parse_authz_code (const struct GNUNET_CRYPTO_EcdsaPublicKey *audience, | ||
828 | const char* code, | ||
829 | struct GNUNET_RECLAIM_Ticket **ticket, | ||
830 | char **nonce) | ||
831 | { | ||
832 | json_error_t error; | ||
833 | json_t *code_json; | ||
834 | json_t *ticket_json; | ||
835 | json_t *nonce_json; | ||
836 | json_t *signature_json; | ||
837 | const char *ticket_str; | ||
838 | const char *signature_str; | ||
839 | const char *nonce_str; | ||
840 | char *code_output; | ||
841 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
842 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
843 | size_t signature_payload_len; | ||
844 | |||
845 | code_output = NULL; | ||
846 | GNUNET_STRINGS_base64_decode (code, | ||
847 | strlen(code), | ||
848 | (void**)&code_output); | ||
849 | code_json = json_loads (code_output, 0 , &error); | ||
850 | GNUNET_free (code_output); | ||
851 | ticket_json = json_object_get (code_json, "ticket"); | ||
852 | nonce_json = json_object_get (code_json, "nonce"); | ||
853 | signature_json = json_object_get (code_json, "signature"); | ||
854 | *ticket = NULL; | ||
855 | *nonce = NULL; | ||
856 | |||
857 | if ((NULL == ticket_json || !json_is_string (ticket_json)) || | ||
858 | (NULL == signature_json || !json_is_string (signature_json))) | ||
859 | { | ||
860 | json_decref (code_json); | ||
861 | return GNUNET_SYSERR; | ||
862 | } | ||
863 | ticket_str = json_string_value (ticket_json); | ||
864 | signature_str = json_string_value (signature_json); | ||
865 | nonce_str = NULL; | ||
866 | if (NULL != nonce_json) | ||
867 | nonce_str = json_string_value (nonce_json); | ||
868 | signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); | ||
869 | if (NULL != nonce_str) | ||
870 | signature_payload_len += strlen (nonce_str); | ||
871 | purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
872 | signature_payload_len); | ||
873 | purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); | ||
874 | purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); | ||
875 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str, | ||
876 | strlen (ticket_str), | ||
877 | &purpose[1], | ||
878 | sizeof (struct GNUNET_RECLAIM_Ticket))) | ||
879 | { | ||
880 | GNUNET_free (purpose); | ||
881 | json_decref (code_json); | ||
882 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
883 | "Cannot parse ticket!\n"); | ||
884 | return GNUNET_SYSERR; | ||
885 | } | ||
886 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str, | ||
887 | strlen (signature_str), | ||
888 | &signature, | ||
889 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) | ||
890 | { | ||
891 | GNUNET_free (purpose); | ||
892 | json_decref (code_json); | ||
893 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
894 | "Cannot parse signature!\n"); | ||
895 | return GNUNET_SYSERR; | ||
896 | } | ||
897 | *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket); | ||
898 | memcpy (*ticket, | ||
899 | &purpose[1], | ||
900 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
901 | if (0 != memcmp (audience, | ||
902 | &(*ticket)->audience, | ||
903 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
904 | { | ||
905 | GNUNET_free (purpose); | ||
906 | GNUNET_free (*ticket); | ||
907 | json_decref (code_json); | ||
908 | *ticket = NULL; | ||
909 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
910 | "Audience in ticket does not match client!\n"); | ||
911 | return GNUNET_SYSERR; | ||
912 | |||
913 | } | ||
914 | if (NULL != nonce_str) | ||
915 | memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), | ||
916 | nonce_str, | ||
917 | strlen (nonce_str)); | ||
918 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, | ||
919 | purpose, | ||
920 | &signature, | ||
921 | &(*ticket)->identity)) | ||
922 | { | ||
923 | GNUNET_free (purpose); | ||
924 | GNUNET_free (*ticket); | ||
925 | json_decref (code_json); | ||
926 | *ticket = NULL; | ||
927 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
928 | "Signature of authZ code invalid!\n"); | ||
929 | return GNUNET_SYSERR; | ||
930 | } | ||
931 | *nonce = GNUNET_strdup (nonce_str); | ||
932 | return GNUNET_OK; | ||
933 | } | ||
934 | |||
935 | static char* | ||
936 | build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | ||
937 | const struct GNUNET_RECLAIM_Ticket *ticket, | ||
938 | const char* nonce) | ||
939 | { | ||
940 | char *ticket_str; | ||
941 | json_t *code_json; | ||
942 | char *signature_payload; | ||
943 | char *signature_str; | ||
944 | char *authz_code; | ||
945 | size_t signature_payload_len; | ||
946 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
947 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
948 | |||
949 | signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); | ||
950 | if (NULL != nonce) | ||
951 | signature_payload_len += strlen (nonce); | ||
952 | |||
953 | signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); | ||
954 | purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; | ||
955 | purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); | ||
956 | purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); | ||
957 | memcpy (&purpose[1], | ||
958 | ticket, | ||
959 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
960 | if (NULL != nonce) | ||
961 | memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), | ||
962 | nonce, | ||
963 | strlen (nonce)); | ||
964 | if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, | ||
965 | purpose, | ||
966 | &signature)) | ||
967 | { | ||
968 | GNUNET_free (signature_payload); | ||
969 | return NULL; | ||
970 | } | ||
971 | signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, | ||
972 | sizeof (signature)); | ||
973 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, | ||
974 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
975 | |||
976 | code_json = json_object (); | ||
977 | json_object_set_new (code_json, | ||
978 | "ticket", | ||
979 | json_string (ticket_str)); | ||
980 | if (NULL != nonce) | ||
981 | json_object_set_new (code_json, | ||
982 | "nonce", | ||
983 | json_string (nonce)); | ||
984 | json_object_set_new (code_json, | ||
985 | "signature", | ||
986 | json_string (signature_str)); | ||
987 | authz_code = json_dumps (code_json, | ||
988 | JSON_INDENT(0) | JSON_COMPACT); | ||
989 | GNUNET_free (signature_payload); | ||
990 | GNUNET_free (signature_str); | ||
991 | GNUNET_free (ticket_str); | ||
992 | json_decref (code_json); | ||
993 | return authz_code; | ||
994 | } | ||
995 | |||
996 | |||
997 | static void | 826 | static void |
998 | get_client_name_result (void *cls, | 827 | get_client_name_result (void *cls, |
999 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 828 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, |
@@ -1011,9 +840,9 @@ get_client_name_result (void *cls, | |||
1011 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, | 840 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (&handle->ticket, |
1012 | sizeof (struct GNUNET_RECLAIM_Ticket)); | 841 | sizeof (struct GNUNET_RECLAIM_Ticket)); |
1013 | //TODO change if more attributes are needed (see max_age) | 842 | //TODO change if more attributes are needed (see max_age) |
1014 | code_json_string = build_authz_code (&handle->priv_key, | 843 | code_json_string = OIDC_build_authz_code (&handle->priv_key, |
1015 | &handle->ticket, | 844 | &handle->ticket, |
1016 | handle->oidc->nonce); | 845 | handle->oidc->nonce); |
1017 | code_base64_final_string = base_64_encode(code_json_string); | 846 | code_base64_final_string = base_64_encode(code_json_string); |
1018 | GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", | 847 | GNUNET_asprintf (&redirect_uri, "%s.%s/%s?%s=%s&state=%s", |
1019 | handle->redirect_prefix, | 848 | handle->redirect_prefix, |
@@ -1532,36 +1361,19 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1532 | return; | 1361 | return; |
1533 | } | 1362 | } |
1534 | 1363 | ||
1535 | /** | 1364 | static int |
1536 | * Responds to token url-encoded POST request | 1365 | check_authorization (struct RequestHandle *handle, |
1537 | * | 1366 | struct GNUNET_CRYPTO_EcdsaPublicKey *cid) |
1538 | * @param con_handle the connection handle | ||
1539 | * @param url the url | ||
1540 | * @param cls the RequestHandle | ||
1541 | */ | ||
1542 | static void | ||
1543 | token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | ||
1544 | const char* url, | ||
1545 | void *cls) | ||
1546 | { | 1367 | { |
1547 | //TODO static strings | ||
1548 | struct RequestHandle *handle = cls; | ||
1549 | struct GNUNET_HashCode cache_key; | 1368 | struct GNUNET_HashCode cache_key; |
1550 | char *authorization, *credentials; | 1369 | char *authorization; |
1551 | char delimiter[]=" "; | 1370 | char *credentials; |
1552 | char delimiter_user_psw[]=":"; | 1371 | char *basic_authorization; |
1553 | char *grant_type, *code; | 1372 | char *client_id; |
1554 | char *user_psw = NULL, *client_id, *psw; | 1373 | char *pass; |
1555 | char *expected_psw; | 1374 | char *expected_pass; |
1556 | int client_exists = GNUNET_NO; | 1375 | int client_exists = GNUNET_NO; |
1557 | struct MHD_Response *resp; | ||
1558 | char *json_response; | ||
1559 | char *jwt_secret; | ||
1560 | char *nonce; | ||
1561 | 1376 | ||
1562 | /* | ||
1563 | * Check Authorization | ||
1564 | */ | ||
1565 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, | 1377 | GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, |
1566 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), | 1378 | strlen (OIDC_AUTHORIZATION_HEADER_KEY), |
1567 | &cache_key); | 1379 | &cache_key); |
@@ -1571,80 +1383,75 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1571 | handle->emsg=GNUNET_strdup("invalid_client"); | 1383 | handle->emsg=GNUNET_strdup("invalid_client"); |
1572 | handle->edesc=GNUNET_strdup("missing authorization"); | 1384 | handle->edesc=GNUNET_strdup("missing authorization"); |
1573 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1385 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1574 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1386 | return GNUNET_SYSERR; |
1575 | return; | ||
1576 | } | 1387 | } |
1577 | authorization = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->header_param_map, &cache_key); | 1388 | authorization = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->header_param_map, |
1389 | &cache_key); | ||
1578 | 1390 | ||
1579 | //split header in "Basic" and [content] | 1391 | //split header in "Basic" and [content] |
1580 | credentials = strtok (authorization, delimiter); | 1392 | credentials = strtok (authorization, " "); |
1581 | if (0 != strcmp ("Basic",credentials)) | 1393 | if (0 != strcmp ("Basic", credentials)) |
1582 | { | 1394 | { |
1583 | handle->emsg=GNUNET_strdup("invalid_client"); | 1395 | handle->emsg=GNUNET_strdup("invalid_client"); |
1584 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1396 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1585 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1397 | return GNUNET_SYSERR; |
1586 | return; | ||
1587 | } | 1398 | } |
1588 | credentials = strtok(NULL, delimiter); | 1399 | credentials = strtok(NULL, " "); |
1589 | if (NULL == credentials) | 1400 | if (NULL == credentials) |
1590 | { | 1401 | { |
1591 | handle->emsg=GNUNET_strdup("invalid_client"); | 1402 | handle->emsg=GNUNET_strdup("invalid_client"); |
1592 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1403 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1593 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1404 | return GNUNET_SYSERR; |
1594 | return; | ||
1595 | } | 1405 | } |
1596 | GNUNET_STRINGS_base64_decode (credentials, strlen (credentials), (void**)&user_psw); | 1406 | GNUNET_STRINGS_base64_decode (credentials, |
1407 | strlen (credentials), | ||
1408 | (void**)&basic_authorization); | ||
1597 | 1409 | ||
1598 | if ( NULL == user_psw ) | 1410 | if ( NULL == basic_authorization ) |
1599 | { | 1411 | { |
1600 | handle->emsg=GNUNET_strdup("invalid_client"); | 1412 | handle->emsg=GNUNET_strdup("invalid_client"); |
1601 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1413 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1602 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1414 | return GNUNET_SYSERR; |
1603 | return; | ||
1604 | } | 1415 | } |
1605 | client_id = strtok (user_psw, delimiter_user_psw); | 1416 | client_id = strtok (basic_authorization, ":"); |
1606 | if ( NULL == client_id ) | 1417 | if ( NULL == client_id ) |
1607 | { | 1418 | { |
1608 | GNUNET_free_non_null(user_psw); | 1419 | GNUNET_free_non_null(basic_authorization); |
1609 | handle->emsg=GNUNET_strdup("invalid_client"); | 1420 | handle->emsg=GNUNET_strdup("invalid_client"); |
1610 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1421 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1611 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1422 | return GNUNET_SYSERR; |
1612 | return; | ||
1613 | } | 1423 | } |
1614 | psw = strtok (NULL, delimiter_user_psw); | 1424 | pass = strtok (NULL, ":"); |
1615 | if (NULL == psw) | 1425 | if (NULL == pass) |
1616 | { | 1426 | { |
1617 | GNUNET_free_non_null(user_psw); | 1427 | GNUNET_free_non_null(basic_authorization); |
1618 | handle->emsg=GNUNET_strdup("invalid_client"); | 1428 | handle->emsg=GNUNET_strdup("invalid_client"); |
1619 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1429 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1620 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1430 | return GNUNET_SYSERR; |
1621 | return; | ||
1622 | } | 1431 | } |
1623 | 1432 | ||
1624 | //check client password | 1433 | //check client password |
1625 | if ( GNUNET_OK | 1434 | if ( GNUNET_OK |
1626 | == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", | 1435 | == GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", |
1627 | "psw", &expected_psw) ) | 1436 | "psw", &expected_pass) ) |
1628 | { | 1437 | { |
1629 | if (0 != strcmp (expected_psw, psw)) | 1438 | if (0 != strcmp (expected_pass, pass)) |
1630 | { | 1439 | { |
1631 | GNUNET_free_non_null(user_psw); | 1440 | GNUNET_free_non_null(basic_authorization); |
1632 | GNUNET_free(expected_psw); | 1441 | GNUNET_free(expected_pass); |
1633 | handle->emsg=GNUNET_strdup("invalid_client"); | 1442 | handle->emsg=GNUNET_strdup("invalid_client"); |
1634 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1443 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1635 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1444 | return GNUNET_SYSERR; |
1636 | return; | ||
1637 | } | 1445 | } |
1638 | GNUNET_free(expected_psw); | 1446 | GNUNET_free(expected_pass); |
1639 | } | 1447 | } |
1640 | else | 1448 | else |
1641 | { | 1449 | { |
1642 | GNUNET_free_non_null(user_psw); | 1450 | GNUNET_free_non_null(basic_authorization); |
1643 | handle->emsg = GNUNET_strdup("server_error"); | 1451 | handle->emsg = GNUNET_strdup("server_error"); |
1644 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | 1452 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); |
1645 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | 1453 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; |
1646 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1454 | return GNUNET_SYSERR; |
1647 | return; | ||
1648 | } | 1455 | } |
1649 | 1456 | ||
1650 | //check client_id | 1457 | //check client_id |
@@ -1659,9 +1466,108 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1659 | } | 1466 | } |
1660 | if (GNUNET_NO == client_exists) | 1467 | if (GNUNET_NO == client_exists) |
1661 | { | 1468 | { |
1662 | GNUNET_free_non_null(user_psw); | 1469 | GNUNET_free_non_null(basic_authorization); |
1663 | handle->emsg=GNUNET_strdup("invalid_client"); | 1470 | handle->emsg=GNUNET_strdup("invalid_client"); |
1664 | handle->response_code = MHD_HTTP_UNAUTHORIZED; | 1471 | handle->response_code = MHD_HTTP_UNAUTHORIZED; |
1472 | return GNUNET_SYSERR; | ||
1473 | } | ||
1474 | GNUNET_STRINGS_string_to_data (client_id, | ||
1475 | strlen(client_id), | ||
1476 | cid, | ||
1477 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1478 | |||
1479 | GNUNET_free (client_id); | ||
1480 | GNUNET_free (basic_authorization); | ||
1481 | return GNUNET_OK; | ||
1482 | } | ||
1483 | |||
1484 | static int | ||
1485 | ego_exists (struct RequestHandle *handle, | ||
1486 | struct GNUNET_CRYPTO_EcdsaPublicKey *test_key) | ||
1487 | { | ||
1488 | struct EgoEntry *ego_entry; | ||
1489 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
1490 | |||
1491 | for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) | ||
1492 | { | ||
1493 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); | ||
1494 | if (0 == memcmp (&pub_key, | ||
1495 | test_key, | ||
1496 | sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1497 | { | ||
1498 | break; | ||
1499 | } | ||
1500 | } | ||
1501 | if (NULL == ego_entry) | ||
1502 | return GNUNET_NO; | ||
1503 | return GNUNET_YES; | ||
1504 | } | ||
1505 | |||
1506 | static void | ||
1507 | store_ticket_reference (const struct RequestHandle *handle, | ||
1508 | const char* access_token, | ||
1509 | const struct GNUNET_RECLAIM_Ticket *ticket, | ||
1510 | const struct GNUNET_CRYPTO_EcdsaPublicKey *cid) | ||
1511 | { | ||
1512 | struct GNUNET_HashCode cache_key; | ||
1513 | char *id_ticket_combination; | ||
1514 | char *ticket_string; | ||
1515 | char *client_id; | ||
1516 | |||
1517 | GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); | ||
1518 | client_id = GNUNET_STRINGS_data_to_string_alloc (cid, | ||
1519 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1520 | ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket, | ||
1521 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
1522 | GNUNET_asprintf(&id_ticket_combination, | ||
1523 | "%s;%s", | ||
1524 | client_id, | ||
1525 | ticket_string); | ||
1526 | GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, | ||
1527 | &cache_key, | ||
1528 | id_ticket_combination, | ||
1529 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
1530 | |||
1531 | GNUNET_free (client_id); | ||
1532 | GNUNET_free (ticket_string); | ||
1533 | } | ||
1534 | |||
1535 | /** | ||
1536 | * Responds to token url-encoded POST request | ||
1537 | * | ||
1538 | * @param con_handle the connection handle | ||
1539 | * @param url the url | ||
1540 | * @param cls the RequestHandle | ||
1541 | */ | ||
1542 | static void | ||
1543 | token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | ||
1544 | const char* url, | ||
1545 | void *cls) | ||
1546 | { | ||
1547 | struct RequestHandle *handle = cls; | ||
1548 | struct GNUNET_TIME_Relative expiration_time; | ||
1549 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl; | ||
1550 | struct GNUNET_RECLAIM_Ticket *ticket; | ||
1551 | struct GNUNET_CRYPTO_EcdsaPublicKey cid; | ||
1552 | struct GNUNET_HashCode cache_key; | ||
1553 | struct MHD_Response *resp; | ||
1554 | char *grant_type; | ||
1555 | char *code; | ||
1556 | char *json_response; | ||
1557 | char *id_token; | ||
1558 | char *access_token; | ||
1559 | char *jwt_secret; | ||
1560 | char *nonce; | ||
1561 | int i = 1; | ||
1562 | |||
1563 | /* | ||
1564 | * Check Authorization | ||
1565 | */ | ||
1566 | if (GNUNET_SYSERR == check_authorization (handle, | ||
1567 | &cid)) | ||
1568 | { | ||
1569 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1570 | "OIDC authorization for token endpoint failed\n"); | ||
1665 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1571 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1666 | return; | 1572 | return; |
1667 | } | 1573 | } |
@@ -1673,27 +1579,25 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1673 | //TODO Do not allow multiple equal parameter names | 1579 | //TODO Do not allow multiple equal parameter names |
1674 | //REQUIRED grant_type | 1580 | //REQUIRED grant_type |
1675 | GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); | 1581 | GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); |
1676 | if ( GNUNET_NO | 1582 | if (GNUNET_NO == |
1677 | == GNUNET_CONTAINER_multihashmap_contains ( | 1583 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, |
1678 | handle->rest_handle->url_param_map, &cache_key) ) | 1584 | &cache_key)) |
1679 | { | 1585 | { |
1680 | GNUNET_free_non_null(user_psw); | ||
1681 | handle->emsg = GNUNET_strdup("invalid_request"); | 1586 | handle->emsg = GNUNET_strdup("invalid_request"); |
1682 | handle->edesc = GNUNET_strdup("missing parameter grant_type"); | 1587 | handle->edesc = GNUNET_strdup("missing parameter grant_type"); |
1683 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1588 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
1684 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1589 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1685 | return; | 1590 | return; |
1686 | } | 1591 | } |
1687 | grant_type = GNUNET_CONTAINER_multihashmap_get ( | 1592 | grant_type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, |
1688 | handle->rest_handle->url_param_map, &cache_key); | 1593 | &cache_key); |
1689 | 1594 | ||
1690 | //REQUIRED code | 1595 | //REQUIRED code |
1691 | GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key); | 1596 | GNUNET_CRYPTO_hash (OIDC_CODE_KEY, strlen (OIDC_CODE_KEY), &cache_key); |
1692 | if ( GNUNET_NO | 1597 | if (GNUNET_NO == |
1693 | == GNUNET_CONTAINER_multihashmap_contains ( | 1598 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, |
1694 | handle->rest_handle->url_param_map, &cache_key) ) | 1599 | &cache_key)) |
1695 | { | 1600 | { |
1696 | GNUNET_free_non_null(user_psw); | ||
1697 | handle->emsg = GNUNET_strdup("invalid_request"); | 1601 | handle->emsg = GNUNET_strdup("invalid_request"); |
1698 | handle->edesc = GNUNET_strdup("missing parameter code"); | 1602 | handle->edesc = GNUNET_strdup("missing parameter code"); |
1699 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1603 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
@@ -1706,11 +1610,10 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1706 | //REQUIRED redirect_uri | 1610 | //REQUIRED redirect_uri |
1707 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), | 1611 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), |
1708 | &cache_key); | 1612 | &cache_key); |
1709 | if ( GNUNET_NO | 1613 | if (GNUNET_NO == |
1710 | == GNUNET_CONTAINER_multihashmap_contains ( | 1614 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, |
1711 | handle->rest_handle->url_param_map, &cache_key) ) | 1615 | &cache_key) ) |
1712 | { | 1616 | { |
1713 | GNUNET_free_non_null(user_psw); | ||
1714 | handle->emsg = GNUNET_strdup("invalid_request"); | 1617 | handle->emsg = GNUNET_strdup("invalid_request"); |
1715 | handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); | 1618 | handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); |
1716 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1619 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
@@ -1721,21 +1624,18 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1721 | //Check parameter grant_type == "authorization_code" | 1624 | //Check parameter grant_type == "authorization_code" |
1722 | if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) | 1625 | if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) |
1723 | { | 1626 | { |
1724 | GNUNET_free_non_null(user_psw); | ||
1725 | handle->emsg=GNUNET_strdup("unsupported_grant_type"); | 1627 | handle->emsg=GNUNET_strdup("unsupported_grant_type"); |
1726 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1628 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
1727 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1629 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1728 | return; | 1630 | return; |
1729 | } | 1631 | } |
1730 | GNUNET_CRYPTO_hash (code, strlen (code), &cache_key); | 1632 | GNUNET_CRYPTO_hash (code, strlen (code), &cache_key); |
1731 | int i = 1; | 1633 | if (GNUNET_SYSERR == |
1732 | if ( GNUNET_SYSERR | 1634 | GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, |
1733 | == GNUNET_CONTAINER_multihashmap_put (OIDC_ticket_once, | 1635 | &cache_key, |
1734 | &cache_key, | 1636 | &i, |
1735 | &i, | 1637 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) |
1736 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) ) | ||
1737 | { | 1638 | { |
1738 | GNUNET_free_non_null(user_psw); | ||
1739 | handle->emsg = GNUNET_strdup("invalid_request"); | 1639 | handle->emsg = GNUNET_strdup("invalid_request"); |
1740 | handle->edesc = GNUNET_strdup("Cannot use the same code more than once"); | 1640 | handle->edesc = GNUNET_strdup("Cannot use the same code more than once"); |
1741 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1641 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
@@ -1744,18 +1644,11 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1744 | } | 1644 | } |
1745 | 1645 | ||
1746 | //decode code | 1646 | //decode code |
1747 | struct GNUNET_CRYPTO_EcdsaPublicKey cid; | 1647 | if(GNUNET_OK != OIDC_parse_authz_code (&cid, |
1748 | GNUNET_STRINGS_string_to_data (client_id, | 1648 | code, |
1749 | strlen(client_id), | 1649 | &ticket, |
1750 | &cid, | 1650 | &nonce)) |
1751 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1752 | struct GNUNET_RECLAIM_Ticket *ticket; | ||
1753 | if(GNUNET_OK != parse_authz_code (&cid, | ||
1754 | code, | ||
1755 | &ticket, | ||
1756 | &nonce)) | ||
1757 | { | 1651 | { |
1758 | GNUNET_free_non_null(user_psw); | ||
1759 | handle->emsg = GNUNET_strdup("invalid_request"); | 1652 | handle->emsg = GNUNET_strdup("invalid_request"); |
1760 | handle->edesc = GNUNET_strdup("invalid code"); | 1653 | handle->edesc = GNUNET_strdup("invalid code"); |
1761 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1654 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
@@ -1763,27 +1656,13 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1763 | return; | 1656 | return; |
1764 | } | 1657 | } |
1765 | 1658 | ||
1766 | // this is the current client (relying party) | ||
1767 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
1768 | GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); | ||
1769 | if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1770 | { | ||
1771 | GNUNET_free_non_null(user_psw); | ||
1772 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1773 | handle->edesc = GNUNET_strdup("invalid code"); | ||
1774 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1775 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1776 | GNUNET_free(ticket); | ||
1777 | return; | ||
1778 | } | ||
1779 | |||
1780 | //create jwt | 1659 | //create jwt |
1781 | struct GNUNET_TIME_Relative expiration_time; | 1660 | if (GNUNET_OK != |
1782 | if ( GNUNET_OK | 1661 | GNUNET_CONFIGURATION_get_value_time(cfg, |
1783 | != GNUNET_CONFIGURATION_get_value_time(cfg, "reclaim-rest-plugin", | 1662 | "reclaim-rest-plugin", |
1784 | "expiration_time", &expiration_time) ) | 1663 | "expiration_time", |
1664 | &expiration_time)) | ||
1785 | { | 1665 | { |
1786 | GNUNET_free_non_null(user_psw); | ||
1787 | handle->emsg = GNUNET_strdup("server_error"); | 1666 | handle->emsg = GNUNET_strdup("server_error"); |
1788 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); | 1667 | handle->edesc = GNUNET_strdup ("gnunet configuration failed"); |
1789 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | 1668 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; |
@@ -1792,34 +1671,21 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1792 | return; | 1671 | return; |
1793 | } | 1672 | } |
1794 | 1673 | ||
1795 | struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); | ||
1796 | 1674 | ||
1797 | //TODO OPTIONAL acr,amr,azp | 1675 | //TODO OPTIONAL acr,amr,azp |
1798 | 1676 | if (GNUNET_NO == ego_exists (handle, | |
1799 | struct EgoEntry *ego_entry; | 1677 | &ticket->audience)) |
1800 | for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) | ||
1801 | { | ||
1802 | GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &pub_key); | ||
1803 | if (0 == memcmp (&pub_key, &ticket->audience, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
1804 | { | ||
1805 | break; | ||
1806 | } | ||
1807 | } | ||
1808 | if ( NULL == ego_entry ) | ||
1809 | { | 1678 | { |
1810 | GNUNET_free_non_null(user_psw); | ||
1811 | handle->emsg = GNUNET_strdup("invalid_request"); | 1679 | handle->emsg = GNUNET_strdup("invalid_request"); |
1812 | handle->edesc = GNUNET_strdup("invalid code..."); | 1680 | handle->edesc = GNUNET_strdup("invalid code..."); |
1813 | handle->response_code = MHD_HTTP_BAD_REQUEST; | 1681 | handle->response_code = MHD_HTTP_BAD_REQUEST; |
1814 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 1682 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1815 | GNUNET_free(ticket); | 1683 | GNUNET_free(ticket); |
1816 | return; | ||
1817 | } | 1684 | } |
1818 | if ( GNUNET_OK | 1685 | if ( GNUNET_OK |
1819 | != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", | 1686 | != GNUNET_CONFIGURATION_get_value_string (cfg, "reclaim-rest-plugin", |
1820 | "jwt_secret", &jwt_secret) ) | 1687 | "jwt_secret", &jwt_secret) ) |
1821 | { | 1688 | { |
1822 | GNUNET_free_non_null(user_psw); | ||
1823 | handle->emsg = GNUNET_strdup("invalid_request"); | 1689 | handle->emsg = GNUNET_strdup("invalid_request"); |
1824 | handle->edesc = GNUNET_strdup("No signing secret configured!"); | 1690 | handle->edesc = GNUNET_strdup("No signing secret configured!"); |
1825 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | 1691 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; |
@@ -1827,56 +1693,31 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1827 | GNUNET_free(ticket); | 1693 | GNUNET_free(ticket); |
1828 | return; | 1694 | return; |
1829 | } | 1695 | } |
1830 | char *id_token = jwt_create_from_list(&ticket->audience, | 1696 | //TODO We should collect the attributes here. cl always empty |
1831 | &ticket->identity, | 1697 | cl = GNUNET_new (struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList); |
1832 | cl, | 1698 | id_token = OIDC_id_token_new (&ticket->audience, |
1833 | &expiration_time, | 1699 | &ticket->identity, |
1834 | (NULL != nonce) ? nonce : NULL, | 1700 | cl, |
1835 | jwt_secret); | 1701 | &expiration_time, |
1836 | 1702 | (NULL != nonce) ? nonce : NULL, | |
1837 | //Create random access_token | 1703 | jwt_secret); |
1838 | char* access_token_number; | 1704 | access_token = OIDC_access_token_new (); |
1839 | char* access_token; | 1705 | OIDC_build_token_response (access_token, |
1840 | uint64_t random_number; | 1706 | id_token, |
1841 | random_number = GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); | 1707 | &expiration_time, |
1842 | GNUNET_asprintf(&access_token_number, "%" PRIu64, random_number); | 1708 | &json_response); |
1843 | GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); | 1709 | |
1844 | 1710 | store_ticket_reference (handle, | |
1845 | 1711 | access_token, | |
1846 | 1712 | ticket, | |
1847 | //TODO OPTIONAL add refresh_token and scope | 1713 | &cid); |
1848 | GNUNET_asprintf (&json_response, | ||
1849 | "{ \"access_token\" : \"%s\", " | ||
1850 | "\"token_type\" : \"Bearer\", " | ||
1851 | "\"expires_in\" : %d, " | ||
1852 | "\"id_token\" : \"%s\"}", | ||
1853 | access_token, | ||
1854 | expiration_time, | ||
1855 | id_token); | ||
1856 | GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); | ||
1857 | char *id_ticket_combination; | ||
1858 | char *ticket_string; | ||
1859 | ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket, | ||
1860 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
1861 | GNUNET_asprintf(&id_ticket_combination, | ||
1862 | "%s;%s", | ||
1863 | client_id, | ||
1864 | ticket_string); | ||
1865 | GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, | ||
1866 | &cache_key, | ||
1867 | id_ticket_combination, | ||
1868 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
1869 | |||
1870 | resp = GNUNET_REST_create_response (json_response); | 1714 | resp = GNUNET_REST_create_response (json_response); |
1871 | MHD_add_response_header (resp, "Cache-Control", "no-store"); | 1715 | MHD_add_response_header (resp, "Cache-Control", "no-store"); |
1872 | MHD_add_response_header (resp, "Pragma", "no-cache"); | 1716 | MHD_add_response_header (resp, "Pragma", "no-cache"); |
1873 | MHD_add_response_header (resp, "Content-Type", "application/json"); | 1717 | MHD_add_response_header (resp, "Content-Type", "application/json"); |
1874 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 1718 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
1875 | |||
1876 | GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl); | 1719 | GNUNET_RECLAIM_ATTRIBUTE_list_destroy(cl); |
1877 | GNUNET_free(access_token_number); | ||
1878 | GNUNET_free(access_token); | 1720 | GNUNET_free(access_token); |
1879 | GNUNET_free(user_psw); | ||
1880 | GNUNET_free(json_response); | 1721 | GNUNET_free(json_response); |
1881 | GNUNET_free(ticket); | 1722 | GNUNET_free(ticket); |
1882 | GNUNET_free(id_token); | 1723 | GNUNET_free(id_token); |