diff options
author | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-07-22 16:37:49 +0200 |
---|---|---|
committer | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-07-22 16:37:49 +0200 |
commit | b68e69365b355f3ef5104f3b682457b0844a70df (patch) | |
tree | a9ba9e95d105af07f59401991188b6a2693a1837 /src/reclaim/plugin_rest_openid_connect.c | |
parent | 214f2e90aff373771838d4504d77444c43194e49 (diff) | |
download | gnunet-b68e69365b355f3ef5104f3b682457b0844a70df.tar.gz gnunet-b68e69365b355f3ef5104f3b682457b0844a70df.zip |
add signature check to token endpoint
Diffstat (limited to 'src/reclaim/plugin_rest_openid_connect.c')
-rw-r--r-- | src/reclaim/plugin_rest_openid_connect.c | 250 |
1 files changed, 162 insertions, 88 deletions
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index 0a6dd2b61..a2d32e126 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c | |||
@@ -794,66 +794,160 @@ oidc_iteration_error (void *cls) | |||
794 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 794 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
795 | } | 795 | } |
796 | 796 | ||
797 | static int | ||
798 | parse_authz_code (const char* code, | ||
799 | struct GNUNET_RECLAIM_Ticket **ticket, | ||
800 | char **nonce) | ||
801 | { | ||
802 | json_error_t error; | ||
803 | json_t *code_json; | ||
804 | json_t *ticket_json; | ||
805 | json_t *nonce_json; | ||
806 | json_t *signature_json; | ||
807 | const char *ticket_str; | ||
808 | const char *signature_str; | ||
809 | const char *nonce_str; | ||
810 | char *code_output; | ||
811 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
812 | struct GNUNET_CRYPTO_EcdsaSignature signature; | ||
813 | size_t signature_payload_len; | ||
814 | |||
815 | code_output = NULL; | ||
816 | GNUNET_STRINGS_base64_decode (code, | ||
817 | strlen(code), | ||
818 | (void**)&code_output); | ||
819 | code_json = json_loads (code_output, 0 , &error); | ||
820 | GNUNET_free (code_output); | ||
821 | ticket_json = json_object_get (code_json, "ticket"); | ||
822 | nonce_json = json_object_get (code_json, "nonce"); | ||
823 | signature_json = json_object_get (code_json, "signature"); | ||
824 | *ticket = NULL; | ||
825 | *nonce = NULL; | ||
826 | |||
827 | if ((NULL == ticket_json || !json_is_string (ticket_json)) || | ||
828 | (NULL == signature_json || !json_is_string (signature_json))) | ||
829 | { | ||
830 | json_decref (code_json); | ||
831 | return GNUNET_SYSERR; | ||
832 | } | ||
833 | ticket_str = json_string_value (ticket_json); | ||
834 | signature_str = json_string_value (signature_json); | ||
835 | nonce_str = NULL; | ||
836 | if (NULL != nonce_json) | ||
837 | nonce_str = json_string_value (nonce_json); | ||
838 | signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); | ||
839 | if (NULL != nonce_str) | ||
840 | signature_payload_len += strlen (nonce_str); | ||
841 | purpose = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
842 | signature_payload_len); | ||
843 | purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); | ||
844 | purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); | ||
845 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ticket_str, | ||
846 | strlen (ticket_str), | ||
847 | &purpose[1], | ||
848 | sizeof (struct GNUNET_RECLAIM_Ticket))) | ||
849 | { | ||
850 | GNUNET_free (purpose); | ||
851 | json_decref (code_json); | ||
852 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
853 | "Cannot parse ticket!\n"); | ||
854 | return GNUNET_SYSERR; | ||
855 | } | ||
856 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_str, | ||
857 | strlen (signature_str), | ||
858 | &signature, | ||
859 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) | ||
860 | { | ||
861 | GNUNET_free (purpose); | ||
862 | json_decref (code_json); | ||
863 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
864 | "Cannot parse signature!\n"); | ||
865 | return GNUNET_SYSERR; | ||
866 | } | ||
867 | *ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket); | ||
868 | memcpy (*ticket, | ||
869 | &purpose[1], | ||
870 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
871 | if (NULL != nonce_str) | ||
872 | memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), | ||
873 | nonce_str, | ||
874 | strlen (nonce_str)); | ||
875 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN, | ||
876 | purpose, | ||
877 | &signature, | ||
878 | &(*ticket)->identity)) | ||
879 | { | ||
880 | GNUNET_free (purpose); | ||
881 | GNUNET_free (*ticket); | ||
882 | json_decref (code_json); | ||
883 | *ticket = NULL; | ||
884 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
885 | "Signature of authZ code invalid!\n"); | ||
886 | return GNUNET_SYSERR; | ||
887 | } | ||
888 | *nonce = GNUNET_strdup (nonce_str); | ||
889 | return GNUNET_OK; | ||
890 | } | ||
797 | 891 | ||
798 | static char* | 892 | static char* |
799 | build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, | 893 | build_authz_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *issuer, |
800 | const struct GNUNET_RECLAIM_Ticket *ticket, | 894 | const struct GNUNET_RECLAIM_Ticket *ticket, |
801 | const char* nonce) | 895 | const char* nonce) |
802 | { | 896 | { |
803 | char *ticket_str; | 897 | char *ticket_str; |
804 | json_t *code_json; | 898 | json_t *code_json; |
805 | char *signature_payload; | 899 | char *signature_payload; |
806 | char *signature_str; | 900 | char *signature_str; |
807 | char *authz_code; | 901 | char *authz_code; |
808 | size_t signature_payload_len; | 902 | size_t signature_payload_len; |
809 | struct GNUNET_CRYPTO_EcdsaSignature signature; | 903 | struct GNUNET_CRYPTO_EcdsaSignature signature; |
810 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | 904 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; |
811 | 905 | ||
812 | signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); | 906 | signature_payload_len = sizeof (struct GNUNET_RECLAIM_Ticket); |
813 | if (NULL != nonce) | 907 | if (NULL != nonce) |
814 | signature_payload_len += strlen (nonce); | 908 | signature_payload_len += strlen (nonce); |
815 | 909 | ||
816 | signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); | 910 | signature_payload = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); |
817 | purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; | 911 | purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *)signature_payload; |
818 | purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); | 912 | purpose->size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + signature_payload_len); |
819 | purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); | 913 | purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_RECLAIM_CODE_SIGN); |
820 | memcpy (&purpose[1], | 914 | memcpy (&purpose[1], |
821 | ticket, | 915 | ticket, |
822 | sizeof (struct GNUNET_RECLAIM_Ticket)); | 916 | sizeof (struct GNUNET_RECLAIM_Ticket)); |
823 | if (NULL != nonce) | 917 | if (NULL != nonce) |
824 | memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), | 918 | memcpy (&purpose[1] + sizeof (struct GNUNET_RECLAIM_Ticket), |
825 | nonce, | 919 | nonce, |
826 | strlen (nonce)); | 920 | strlen (nonce)); |
827 | if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, | 921 | if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (issuer, |
828 | purpose, | 922 | purpose, |
829 | &signature)) | 923 | &signature)) |
830 | { | 924 | { |
831 | GNUNET_free (signature_payload); | 925 | GNUNET_free (signature_payload); |
832 | return NULL; | 926 | return NULL; |
833 | } | 927 | } |
834 | signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, | 928 | signature_str = GNUNET_STRINGS_data_to_string_alloc (&signature, |
835 | sizeof (signature)); | 929 | sizeof (signature)); |
836 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, | 930 | ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, |
837 | sizeof (struct GNUNET_RECLAIM_Ticket)); | 931 | sizeof (struct GNUNET_RECLAIM_Ticket)); |
838 | 932 | ||
839 | code_json = json_object (); | 933 | code_json = json_object (); |
840 | json_object_set_new (code_json, | 934 | json_object_set_new (code_json, |
841 | "ticket", | 935 | "ticket", |
842 | json_string (ticket_str)); | 936 | json_string (ticket_str)); |
843 | if (NULL != nonce) | 937 | if (NULL != nonce) |
844 | json_object_set_new (code_json, | 938 | json_object_set_new (code_json, |
845 | "nonce", | 939 | "nonce", |
846 | json_string (nonce)); | 940 | json_string (nonce)); |
847 | json_object_set_new (code_json, | 941 | json_object_set_new (code_json, |
848 | "signature", | 942 | "signature", |
849 | json_string (signature_str)); | 943 | json_string (signature_str)); |
850 | authz_code = json_dumps (code_json, | 944 | authz_code = json_dumps (code_json, |
851 | JSON_INDENT(0) | JSON_COMPACT); | 945 | JSON_INDENT(0) | JSON_COMPACT); |
852 | GNUNET_free (signature_payload); | 946 | GNUNET_free (signature_payload); |
853 | GNUNET_free (signature_str); | 947 | GNUNET_free (signature_str); |
854 | GNUNET_free (ticket_str); | 948 | GNUNET_free (ticket_str); |
855 | json_decref (code_json); | 949 | json_decref (code_json); |
856 | return authz_code; | 950 | return authz_code; |
857 | } | 951 | } |
858 | 952 | ||
859 | 953 | ||
@@ -882,10 +976,10 @@ get_client_name_result (void *cls, | |||
882 | &handle->ticket, | 976 | &handle->ticket, |
883 | handle->oidc->nonce); | 977 | handle->oidc->nonce); |
884 | /*GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", | 978 | /*GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", |
885 | ticket_str, | 979 | ticket_str, |
886 | (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", | 980 | (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", |
887 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", | 981 | (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", |
888 | (NULL != handle->oidc->nonce) ? "\"" : "");*/ | 982 | (NULL != handle->oidc->nonce) ? "\"" : "");*/ |
889 | code_base64_final_string = base_64_encode(code_json_string); | 983 | code_base64_final_string = base_64_encode(code_json_string); |
890 | tmp = GNUNET_strdup (handle->oidc->redirect_uri); | 984 | tmp = GNUNET_strdup (handle->oidc->redirect_uri); |
891 | redirect_path = strtok (tmp, "/"); | 985 | redirect_path = strtok (tmp, "/"); |
@@ -1386,13 +1480,9 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1386 | char *expected_psw; | 1480 | char *expected_psw; |
1387 | int client_exists = GNUNET_NO; | 1481 | int client_exists = GNUNET_NO; |
1388 | struct MHD_Response *resp; | 1482 | struct MHD_Response *resp; |
1389 | char* code_output; | ||
1390 | json_t *root; | ||
1391 | json_t *ticket_string; | ||
1392 | json_t *nonce; | ||
1393 | json_error_t error; | ||
1394 | char *json_response; | 1483 | char *json_response; |
1395 | char *jwt_secret; | 1484 | char *jwt_secret; |
1485 | char *nonce; | ||
1396 | 1486 | ||
1397 | /* | 1487 | /* |
1398 | * Check Authorization | 1488 | * Check Authorization |
@@ -1579,13 +1669,10 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1579 | } | 1669 | } |
1580 | 1670 | ||
1581 | //decode code | 1671 | //decode code |
1582 | GNUNET_STRINGS_base64_decode(code,strlen(code), (void**)&code_output); | 1672 | struct GNUNET_RECLAIM_Ticket *ticket; |
1583 | root = json_loads (code_output, 0, &error); | 1673 | if(GNUNET_OK != parse_authz_code (code, |
1584 | GNUNET_free(code_output); | 1674 | &ticket, |
1585 | ticket_string = json_object_get (root, "ticket"); | 1675 | &nonce)) |
1586 | nonce = json_object_get (root, "nonce"); | ||
1587 | |||
1588 | if(ticket_string == NULL && !json_is_string(ticket_string)) | ||
1589 | { | 1676 | { |
1590 | GNUNET_free_non_null(user_psw); | 1677 | GNUNET_free_non_null(user_psw); |
1591 | handle->emsg = GNUNET_strdup("invalid_request"); | 1678 | handle->emsg = GNUNET_strdup("invalid_request"); |
@@ -1595,21 +1682,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1595 | return; | 1682 | return; |
1596 | } | 1683 | } |
1597 | 1684 | ||
1598 | struct GNUNET_RECLAIM_Ticket *ticket = GNUNET_new(struct GNUNET_RECLAIM_Ticket); | ||
1599 | if ( GNUNET_OK | ||
1600 | != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string), | ||
1601 | strlen (json_string_value(ticket_string)), | ||
1602 | ticket, | ||
1603 | sizeof(struct GNUNET_RECLAIM_Ticket))) | ||
1604 | { | ||
1605 | GNUNET_free_non_null(user_psw); | ||
1606 | handle->emsg = GNUNET_strdup("invalid_request"); | ||
1607 | handle->edesc = GNUNET_strdup("invalid code"); | ||
1608 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
1609 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1610 | GNUNET_free(ticket); | ||
1611 | return; | ||
1612 | } | ||
1613 | // this is the current client (relying party) | 1685 | // this is the current client (relying party) |
1614 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | 1686 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; |
1615 | GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); | 1687 | GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); |
@@ -1678,7 +1750,7 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1678 | &ticket->identity, | 1750 | &ticket->identity, |
1679 | cl, | 1751 | cl, |
1680 | &expiration_time, | 1752 | &expiration_time, |
1681 | (NULL != nonce && json_is_string(nonce)) ? json_string_value (nonce) : NULL, | 1753 | (NULL != nonce) ? nonce : NULL, |
1682 | jwt_secret); | 1754 | jwt_secret); |
1683 | 1755 | ||
1684 | //Create random access_token | 1756 | //Create random access_token |
@@ -1702,10 +1774,13 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1702 | id_token); | 1774 | id_token); |
1703 | GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); | 1775 | GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key); |
1704 | char *id_ticket_combination; | 1776 | char *id_ticket_combination; |
1777 | char *ticket_string; | ||
1778 | ticket_string = GNUNET_STRINGS_data_to_string_alloc (ticket, | ||
1779 | sizeof (struct GNUNET_RECLAIM_Ticket)); | ||
1705 | GNUNET_asprintf(&id_ticket_combination, | 1780 | GNUNET_asprintf(&id_ticket_combination, |
1706 | "%s;%s", | 1781 | "%s;%s", |
1707 | client_id, | 1782 | client_id, |
1708 | json_string_value(ticket_string)); | 1783 | ticket_string); |
1709 | GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, | 1784 | GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token, |
1710 | &cache_key, | 1785 | &cache_key, |
1711 | id_ticket_combination, | 1786 | id_ticket_combination, |
@@ -1724,7 +1799,6 @@ token_endpoint (struct GNUNET_REST_RequestHandle *con_handle, | |||
1724 | GNUNET_free(json_response); | 1799 | GNUNET_free(json_response); |
1725 | GNUNET_free(ticket); | 1800 | GNUNET_free(ticket); |
1726 | GNUNET_free(id_token); | 1801 | GNUNET_free(id_token); |
1727 | json_decref (root); | ||
1728 | GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle); | 1802 | GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle); |
1729 | } | 1803 | } |
1730 | 1804 | ||