aboutsummaryrefslogtreecommitdiff
path: root/src/reclaim/plugin_rest_openid_connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/reclaim/plugin_rest_openid_connect.c')
-rw-r--r--src/reclaim/plugin_rest_openid_connect.c531
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
826static int
827parse_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
935static char*
936build_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
997static void 826static void
998get_client_name_result (void *cls, 827get_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/** 1364static int
1536 * Responds to token url-encoded POST request 1365check_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 */
1542static void
1543token_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
1484static int
1485ego_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
1506static void
1507store_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 */
1542static void
1543token_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);