diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2020-05-10 11:28:00 +0200 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2020-05-10 11:28:00 +0200 |
commit | 63c371cfbd8c6297a17dab9190ad650e93ad9053 (patch) | |
tree | db3c57f53788aa55d36991a200a2688edf664eee | |
parent | 9a323e17b449ff2ac09336e11263c6cca00a45ea (diff) | |
download | gnunet-63c371cfbd8c6297a17dab9190ad650e93ad9053.tar.gz gnunet-63c371cfbd8c6297a17dab9190ad650e93ad9053.zip |
separate id_token and userinfo claims requests
-rw-r--r-- | src/reclaim/plugin_rest_openid_connect.c | 238 |
1 files changed, 190 insertions, 48 deletions
diff --git a/src/reclaim/plugin_rest_openid_connect.c b/src/reclaim/plugin_rest_openid_connect.c index ad8e373fe..563bdd749 100644 --- a/src/reclaim/plugin_rest_openid_connect.c +++ b/src/reclaim/plugin_rest_openid_connect.c | |||
@@ -426,9 +426,14 @@ struct RequestHandle | |||
426 | struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; | 426 | struct GNUNET_NAMESTORE_ZoneIterator *namestore_handle_it; |
427 | 427 | ||
428 | /** | 428 | /** |
429 | * Attribute claim list | 429 | * Attribute claim list for id_token |
430 | */ | 430 | */ |
431 | struct GNUNET_RECLAIM_AttributeList *attr_list; | 431 | struct GNUNET_RECLAIM_AttributeList *attr_idtoken_list; |
432 | |||
433 | /** | ||
434 | * Attribute claim list for userinfo | ||
435 | */ | ||
436 | struct GNUNET_RECLAIM_AttributeList *attr_userinfo_list; | ||
432 | 437 | ||
433 | /** | 438 | /** |
434 | * Attestation list | 439 | * Attestation list |
@@ -577,8 +582,10 @@ cleanup_handle (struct RequestHandle *handle) | |||
577 | json_decref (handle->oidc->response); | 582 | json_decref (handle->oidc->response); |
578 | GNUNET_free (handle->oidc); | 583 | GNUNET_free (handle->oidc); |
579 | } | 584 | } |
580 | if (NULL!=handle->attr_list) | 585 | if (NULL!=handle->attr_idtoken_list) |
581 | GNUNET_RECLAIM_attribute_list_destroy (handle->attr_list); | 586 | GNUNET_RECLAIM_attribute_list_destroy (handle->attr_idtoken_list); |
587 | if (NULL!=handle->attr_userinfo_list) | ||
588 | GNUNET_RECLAIM_attribute_list_destroy (handle->attr_userinfo_list); | ||
582 | if (NULL!=handle->attests_list) | 589 | if (NULL!=handle->attests_list) |
583 | GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); | 590 | GNUNET_RECLAIM_attestation_list_destroy (handle->attests_list); |
584 | 591 | ||
@@ -935,7 +942,7 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | |||
935 | sizeof(struct GNUNET_RECLAIM_Ticket)); | 942 | sizeof(struct GNUNET_RECLAIM_Ticket)); |
936 | code_string = OIDC_build_authz_code (&handle->priv_key, | 943 | code_string = OIDC_build_authz_code (&handle->priv_key, |
937 | &handle->ticket, | 944 | &handle->ticket, |
938 | handle->attr_list, | 945 | handle->attr_idtoken_list, |
939 | handle->attests_list, | 946 | handle->attests_list, |
940 | handle->oidc->nonce, | 947 | handle->oidc->nonce, |
941 | handle->oidc->code_challenge); | 948 | handle->oidc->code_challenge); |
@@ -970,18 +977,77 @@ oidc_ticket_issue_cb (void *cls, const struct GNUNET_RECLAIM_Ticket *ticket) | |||
970 | } | 977 | } |
971 | 978 | ||
972 | 979 | ||
980 | static struct GNUNET_RECLAIM_AttributeList* | ||
981 | attribute_list_merge (struct GNUNET_RECLAIM_AttributeList *list_a, | ||
982 | struct GNUNET_RECLAIM_AttributeList *list_b) | ||
983 | { | ||
984 | struct GNUNET_RECLAIM_AttributeList *merged_list; | ||
985 | struct GNUNET_RECLAIM_AttributeListEntry *le_a; | ||
986 | struct GNUNET_RECLAIM_AttributeListEntry *le_b; | ||
987 | struct GNUNET_RECLAIM_AttributeListEntry *le_m; | ||
988 | |||
989 | merged_list = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | ||
990 | for (le_a = list_a->list_head; NULL != le_a; le_a = le_a->next) | ||
991 | { | ||
992 | le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | ||
993 | le_m->attribute = GNUNET_RECLAIM_attribute_new (le_a->attribute->name, | ||
994 | &le_a->attribute-> | ||
995 | attestation, | ||
996 | le_a->attribute->type, | ||
997 | le_a->attribute->data, | ||
998 | le_a->attribute->data_size); | ||
999 | le_m->attribute->id = le_a->attribute->id; | ||
1000 | le_m->attribute->flag = le_a->attribute->flag; | ||
1001 | le_m->attribute->attestation = le_a->attribute->attestation; | ||
1002 | GNUNET_CONTAINER_DLL_insert (merged_list->list_head, | ||
1003 | merged_list->list_tail, | ||
1004 | le_m); | ||
1005 | } | ||
1006 | le_m = NULL; | ||
1007 | for (le_b = list_b->list_head; NULL != le_b; le_b = le_b->next) | ||
1008 | { | ||
1009 | for (le_m = merged_list->list_head; NULL != le_m; le_m = le_m->next) | ||
1010 | { | ||
1011 | if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (&le_m->attribute->id, | ||
1012 | &le_b->attribute->id)) | ||
1013 | break; /** Attribute already in list **/ | ||
1014 | } | ||
1015 | if (NULL != le_m) | ||
1016 | continue; /** Attribute already in list **/ | ||
1017 | le_m = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | ||
1018 | le_m->attribute = GNUNET_RECLAIM_attribute_new (le_b->attribute->name, | ||
1019 | &le_b->attribute-> | ||
1020 | attestation, | ||
1021 | le_b->attribute->type, | ||
1022 | le_b->attribute->data, | ||
1023 | le_b->attribute->data_size); | ||
1024 | le_m->attribute->id = le_b->attribute->id; | ||
1025 | le_m->attribute->flag = le_b->attribute->flag; | ||
1026 | le_m->attribute->attestation = le_b->attribute->attestation; | ||
1027 | GNUNET_CONTAINER_DLL_insert (merged_list->list_head, | ||
1028 | merged_list->list_tail, | ||
1029 | le_m); | ||
1030 | } | ||
1031 | return merged_list; | ||
1032 | } | ||
1033 | |||
1034 | |||
973 | static void | 1035 | static void |
974 | oidc_attest_collect_finished_cb (void *cls) | 1036 | oidc_attest_collect_finished_cb (void *cls) |
975 | { | 1037 | { |
976 | struct RequestHandle *handle = cls; | 1038 | struct RequestHandle *handle = cls; |
1039 | struct GNUNET_RECLAIM_AttributeList *merged_list; | ||
977 | 1040 | ||
978 | handle->attest_it = NULL; | 1041 | handle->attest_it = NULL; |
1042 | merged_list = attribute_list_merge (handle->attr_idtoken_list, | ||
1043 | handle->attr_userinfo_list); | ||
979 | handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, | 1044 | handle->idp_op = GNUNET_RECLAIM_ticket_issue (handle->idp, |
980 | &handle->priv_key, | 1045 | &handle->priv_key, |
981 | &handle->oidc->client_pkey, | 1046 | &handle->oidc->client_pkey, |
982 | handle->attr_list, | 1047 | merged_list, |
983 | &oidc_ticket_issue_cb, | 1048 | &oidc_ticket_issue_cb, |
984 | handle); | 1049 | handle); |
1050 | GNUNET_RECLAIM_attribute_list_destroy (merged_list); | ||
985 | } | 1051 | } |
986 | 1052 | ||
987 | 1053 | ||
@@ -995,22 +1061,32 @@ oidc_attest_collect (void *cls, | |||
995 | { | 1061 | { |
996 | struct RequestHandle *handle = cls; | 1062 | struct RequestHandle *handle = cls; |
997 | struct GNUNET_RECLAIM_AttributeListEntry *le; | 1063 | struct GNUNET_RECLAIM_AttributeListEntry *le; |
1064 | struct GNUNET_RECLAIM_AttestationListEntry *ale; | ||
998 | 1065 | ||
999 | for (le = handle->attr_list->list_head; NULL != le; le = le->next) | 1066 | for (ale = handle->attests_list->list_head; NULL != ale; ale = ale->next) |
1067 | { | ||
1068 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&ale->attestation->id, | ||
1069 | &attest->id)) | ||
1070 | continue; | ||
1071 | /** Attestation already in list **/ | ||
1072 | GNUNET_RECLAIM_get_attestations_next (handle->attest_it); | ||
1073 | return; | ||
1074 | } | ||
1075 | |||
1076 | for (le = handle->attr_idtoken_list->list_head; NULL != le; le = le->next) | ||
1000 | { | 1077 | { |
1001 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation, | 1078 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_equal (&le->attribute->attestation, |
1002 | &attest->id)) | 1079 | &attest->id)) |
1003 | { | 1080 | continue; |
1004 | struct GNUNET_RECLAIM_AttestationListEntry *ale; | 1081 | /** Attestation matches for attribute, add **/ |
1005 | ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); | 1082 | ale = GNUNET_new (struct GNUNET_RECLAIM_AttestationListEntry); |
1006 | ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name, | 1083 | ale->attestation = GNUNET_RECLAIM_attestation_new (attest->name, |
1007 | attest->type, | 1084 | attest->type, |
1008 | attest->data, | 1085 | attest->data, |
1009 | attest->data_size); | 1086 | attest->data_size); |
1010 | GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, | 1087 | GNUNET_CONTAINER_DLL_insert (handle->attests_list->list_head, |
1011 | handle->attests_list->list_tail, | 1088 | handle->attests_list->list_tail, |
1012 | ale); | 1089 | ale); |
1013 | } | ||
1014 | } | 1090 | } |
1015 | GNUNET_RECLAIM_get_attestations_next (handle->attest_it); | 1091 | GNUNET_RECLAIM_get_attestations_next (handle->attest_it); |
1016 | } | 1092 | } |
@@ -1023,7 +1099,7 @@ oidc_attr_collect_finished_cb (void *cls) | |||
1023 | 1099 | ||
1024 | handle->attr_it = NULL; | 1100 | handle->attr_it = NULL; |
1025 | handle->ticket_it = NULL; | 1101 | handle->ticket_it = NULL; |
1026 | if (NULL == handle->attr_list->list_head) | 1102 | if (NULL == handle->attr_idtoken_list->list_head) |
1027 | { | 1103 | { |
1028 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE); | 1104 | handle->emsg = GNUNET_strdup (OIDC_ERROR_KEY_INVALID_SCOPE); |
1029 | handle->edesc = GNUNET_strdup ("The requested scope is not available."); | 1105 | handle->edesc = GNUNET_strdup ("The requested scope is not available."); |
@@ -1044,48 +1120,112 @@ oidc_attr_collect_finished_cb (void *cls) | |||
1044 | } | 1120 | } |
1045 | 1121 | ||
1046 | 1122 | ||
1047 | /** | 1123 | static int |
1048 | * Collects all attributes for an ego if in scope parameter | 1124 | attr_in_claims_request (struct RequestHandle *handle, |
1049 | */ | 1125 | const char *attr_name, |
1050 | static void | 1126 | const char *claims_parameter) |
1051 | oidc_attr_collect (void *cls, | ||
1052 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1053 | const struct GNUNET_RECLAIM_Attribute *attr) | ||
1054 | { | 1127 | { |
1055 | struct RequestHandle *handle = cls; | ||
1056 | struct GNUNET_RECLAIM_AttributeListEntry *le; | ||
1057 | char *scope_variables; | 1128 | char *scope_variables; |
1058 | char *scope_variable; | 1129 | char *scope_variable; |
1059 | char delimiter[] = " "; | 1130 | char delimiter[] = " "; |
1131 | int ret = GNUNET_NO; | ||
1132 | json_t *root; | ||
1133 | json_error_t error; | ||
1134 | json_t *claims_j; | ||
1135 | const char *key; | ||
1136 | json_t *value; | ||
1060 | 1137 | ||
1061 | scope_variables = GNUNET_strdup (handle->oidc->scope); | 1138 | scope_variables = GNUNET_strdup (handle->oidc->scope); |
1062 | scope_variable = strtok (scope_variables, delimiter); | 1139 | scope_variable = strtok (scope_variables, delimiter); |
1063 | while (NULL != scope_variable) | 1140 | while (NULL != scope_variable) |
1064 | { | 1141 | { |
1065 | if (0 == strcmp (attr->name, scope_variable)) | 1142 | if (0 == strcmp (attr_name, scope_variable)) |
1066 | break; | 1143 | break; |
1067 | scope_variable = strtok (NULL, delimiter); | 1144 | scope_variable = strtok (NULL, delimiter); |
1068 | } | 1145 | } |
1069 | if (NULL == scope_variable) | 1146 | if (NULL != scope_variable) |
1147 | ret = GNUNET_YES; | ||
1148 | GNUNET_free (scope_variables); | ||
1149 | |||
1150 | /** Try claims parameter if no in scope */ | ||
1151 | if ((NULL != handle->oidc->claims) && | ||
1152 | (GNUNET_YES != ret)) | ||
1070 | { | 1153 | { |
1071 | GNUNET_RECLAIM_get_attributes_next (handle->attr_it); | 1154 | root = json_loads (handle->oidc->claims, JSON_DECODE_ANY, &error); |
1072 | GNUNET_free (scope_variables); | 1155 | claims_j = json_object_get (root, claims_parameter); |
1073 | // We can ignore this | 1156 | /* obj is a JSON object */ |
1074 | return; | 1157 | if (NULL != claims_j) |
1158 | { | ||
1159 | json_object_foreach (claims_j, key, value) { | ||
1160 | if (0 != strcmp (attr_name, key)) | ||
1161 | continue; | ||
1162 | ret = GNUNET_YES; | ||
1163 | break; | ||
1164 | } | ||
1165 | } | ||
1166 | json_decref (root); | ||
1075 | } | 1167 | } |
1076 | GNUNET_free (scope_variables); | 1168 | return ret; |
1077 | le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | 1169 | } |
1078 | le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, | 1170 | |
1079 | &attr->attestation, | 1171 | |
1080 | attr->type, | 1172 | static int |
1081 | attr->data, | 1173 | attr_in_idtoken_request (struct RequestHandle *handle, |
1082 | attr->data_size); | 1174 | const char *attr_name) |
1083 | le->attribute->id = attr->id; | 1175 | { |
1084 | le->attribute->flag = attr->flag; | 1176 | return attr_in_claims_request (handle, attr_name, "id_token"); |
1085 | le->attribute->attestation = attr->attestation; | 1177 | } |
1086 | GNUNET_CONTAINER_DLL_insert (handle->attr_list->list_head, | 1178 | |
1087 | handle->attr_list->list_tail, | 1179 | |
1088 | le); | 1180 | static int |
1181 | attr_in_userinfo_request (struct RequestHandle *handle, | ||
1182 | const char *attr_name) | ||
1183 | { | ||
1184 | return attr_in_claims_request (handle, attr_name, "userinfo"); | ||
1185 | } | ||
1186 | |||
1187 | |||
1188 | /** | ||
1189 | * Collects all attributes for an ego if in scope parameter | ||
1190 | */ | ||
1191 | static void | ||
1192 | oidc_attr_collect (void *cls, | ||
1193 | const struct GNUNET_CRYPTO_EcdsaPublicKey *identity, | ||
1194 | const struct GNUNET_RECLAIM_Attribute *attr) | ||
1195 | { | ||
1196 | struct RequestHandle *handle = cls; | ||
1197 | struct GNUNET_RECLAIM_AttributeListEntry *le; | ||
1198 | if (GNUNET_YES == attr_in_idtoken_request (handle, attr->name)) | ||
1199 | { | ||
1200 | le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | ||
1201 | le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, | ||
1202 | &attr->attestation, | ||
1203 | attr->type, | ||
1204 | attr->data, | ||
1205 | attr->data_size); | ||
1206 | le->attribute->id = attr->id; | ||
1207 | le->attribute->flag = attr->flag; | ||
1208 | le->attribute->attestation = attr->attestation; | ||
1209 | GNUNET_CONTAINER_DLL_insert (handle->attr_idtoken_list->list_head, | ||
1210 | handle->attr_idtoken_list->list_tail, | ||
1211 | le); | ||
1212 | } | ||
1213 | if (GNUNET_YES == attr_in_userinfo_request (handle, attr->name)) | ||
1214 | { | ||
1215 | le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | ||
1216 | le->attribute = GNUNET_RECLAIM_attribute_new (attr->name, | ||
1217 | &attr->attestation, | ||
1218 | attr->type, | ||
1219 | attr->data, | ||
1220 | attr->data_size); | ||
1221 | le->attribute->id = attr->id; | ||
1222 | le->attribute->flag = attr->flag; | ||
1223 | le->attribute->attestation = attr->attestation; | ||
1224 | GNUNET_CONTAINER_DLL_insert (handle->attr_userinfo_list->list_head, | ||
1225 | handle->attr_userinfo_list->list_tail, | ||
1226 | le); | ||
1227 | } | ||
1228 | |||
1089 | GNUNET_RECLAIM_get_attributes_next (handle->attr_it); | 1229 | GNUNET_RECLAIM_get_attributes_next (handle->attr_it); |
1090 | } | 1230 | } |
1091 | 1231 | ||
@@ -1143,7 +1283,9 @@ code_redirect (void *cls) | |||
1143 | handle->priv_key = | 1283 | handle->priv_key = |
1144 | *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | 1284 | *GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); |
1145 | handle->idp = GNUNET_RECLAIM_connect (cfg); | 1285 | handle->idp = GNUNET_RECLAIM_connect (cfg); |
1146 | handle->attr_list = | 1286 | handle->attr_idtoken_list = |
1287 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | ||
1288 | handle->attr_userinfo_list = | ||
1147 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | 1289 | GNUNET_new (struct GNUNET_RECLAIM_AttributeList); |
1148 | handle->attr_it = | 1290 | handle->attr_it = |
1149 | GNUNET_RECLAIM_get_attributes_start (handle->idp, | 1291 | GNUNET_RECLAIM_get_attributes_start (handle->idp, |