diff options
author | Phil <phil.buschmann@tum.de> | 2018-01-09 14:29:29 +0100 |
---|---|---|
committer | Phil <phil.buschmann@tum.de> | 2018-01-09 14:29:29 +0100 |
commit | f0a84723fae7454cdefbc1c0125da71732c5242d (patch) | |
tree | b6c218a84ccdea5339a36fd2510971a85f11c603 /src/identity-provider | |
parent | f2d31fb82a314dcf6819dd494ff4a11e4f871c4e (diff) | |
download | gnunet-f0a84723fae7454cdefbc1c0125da71732c5242d.tar.gz gnunet-f0a84723fae7454cdefbc1c0125da71732c5242d.zip |
-wip post authentication
Diffstat (limited to 'src/identity-provider')
-rw-r--r-- | src/identity-provider/logfile.txt | 73 | ||||
-rw-r--r-- | src/identity-provider/plugin_rest_identity_provider.c | 459 |
2 files changed, 415 insertions, 117 deletions
diff --git a/src/identity-provider/logfile.txt b/src/identity-provider/logfile.txt deleted file mode 100644 index a59f2478a..000000000 --- a/src/identity-provider/logfile.txt +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | *** Error in `/usr/local/lib//gnunet/libexec/gnunet-rest-server': free(): invalid pointer: 0x00007f9c415c9275 *** | ||
2 | *** Error in `/usr/local/lib//gnunet/libexec/gnunet-rest-server': free(): invalid pointer: 0x00007f0888c25275 *** | ||
3 | *** Error in `/usr/local/lib//gnunet/libexec/gnunet-rest-server': free(): invalid pointer: 0x00007f7dee65b275 *** | ||
4 | Nov 23 13:58:28-246065 gnunet-rest-server-26879 ERROR Error: (null) | ||
5 | Nov 23 13:58:46-677968 gnunet-rest-server-26879 ERROR Error: Missing openid scope | ||
6 | Nov 23 13:59:34-165447 gnunet-rest-server-26901 ERROR Error: Missing openid scope | ||
7 | Nov 23 14:04:07-545573 gnunet-rest-server-28097 ERROR Error: Response type is not code | ||
8 | Nov 23 14:53:06-102430 gnunet-rest-server-30299 ERROR Error: Missing openid scope | ||
9 | Nov 23 14:54:04-248567 gnunet-rest-server-30798 ERROR Error: Missing openid scope | ||
10 | Nov 23 14:56:12-809322 gnunet-rest-server-31914 ERROR Error: Missing openid scope | ||
11 | Nov 23 14:56:39-819194 gnunet-rest-server-31914 ERROR Error: Missing openid scope | ||
12 | Nov 23 14:58:38-889573 gnunet-rest-server-601 ERROR Error: Missing openid scope | ||
13 | Nov 30 11:59:42-727619 gnunet-rest-server-9307 ERROR (null)Nov 30 12:00:28-889186 gnunet-rest-server-9307 ERROR (null)Nov 30 12:01:56-950658 gnunet-rest-server-10445 ERROR con_handle: /idp/authorize | ||
14 | Nov 30 12:01:56-982304 gnunet-rest-server-10445 ERROR url: /idp/authorize | ||
15 | Nov 30 12:08:22-749785 gnunet-rest-server-11652 ERROR con_handle: /idp/authorize | ||
16 | Nov 30 12:08:22-782042 gnunet-rest-server-11652 ERROR url: /idp/authorize | ||
17 | Nov 30 12:39:51-816632 gnunet-rest-server-14500 ERROR url: /idp/authorize | ||
18 | Dec 04 09:51:02-313753 gnunet-rest-server-1974 ERROR No default ego configured in identity service | ||
19 | Dec 04 09:51:09-311601 gnunet-rest-server-1974 ERROR No default ego configured in identity service | ||
20 | Failed to send data in request for `/idp/attributes/testego'. | ||
21 | Dec 04 11:58:11-490711 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
22 | Failed to send data in request for `/idp/tickets/testego'. | ||
23 | Dec 04 11:58:11-508689 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
24 | Failed to send data in request for `/names/'. | ||
25 | Dec 04 11:58:11-511015 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
26 | Failed to send data in request for `/idp/tickets/testego'. | ||
27 | Dec 04 12:38:15-960444 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
28 | Failed to send data in request for `/names/'. | ||
29 | Dec 04 12:38:16-003695 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
30 | Failed to send data in request for `/idp/attributes/testego'. | ||
31 | Dec 04 12:38:16-021887 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
32 | Failed to send data in request for `/idp/tickets/testego'. | ||
33 | Dec 04 12:38:29-977580 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
34 | Failed to send data in request for `/names/'. | ||
35 | Dec 04 12:38:30-008002 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
36 | Failed to send data in request for `/idp/attributes/testego'. | ||
37 | Dec 04 12:38:30-036167 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
38 | Failed to send data in request for `/idp/attributes/testego'. | ||
39 | Dec 04 12:43:23-654462 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
40 | Failed to send data in request for `/idp/tickets/testego'. | ||
41 | Dec 04 12:43:23-655070 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
42 | Failed to send data in request for `/names/'. | ||
43 | Dec 04 12:43:23-665165 gnunet-rest-server-6760 ERROR MHD encountered error handling request: 1 | ||
44 | Failed to send data in request for `/idp/tickets/testego'. | ||
45 | Dec 04 13:06:56-306701 gnunet-rest-server-9599 ERROR MHD encountered error handling request: 1 | ||
46 | Failed to send data in request for `/idp/attributes/testego'. | ||
47 | Dec 04 13:06:56-326200 gnunet-rest-server-9599 ERROR MHD encountered error handling request: 1 | ||
48 | Failed to send data in request for `/names/'. | ||
49 | Dec 04 13:06:56-331741 gnunet-rest-server-9599 ERROR MHD encountered error handling request: 1 | ||
50 | Dec 04 13:09:56-080335 gnunet-rest-server-10794 ERROR URL (response_type=code) | ||
51 | Dec 04 13:12:49-565164 gnunet-rest-server-11931 ERROR URL (response_type=code) | ||
52 | Failed to send data in request for `/idp/tickets/testego'. | ||
53 | Dec 04 13:12:49-586734 gnunet-rest-server-11931 ERROR MHD encountered error handling request: 1 | ||
54 | Failed to send data in request for `/idp/attributes/testego'. | ||
55 | Dec 04 13:12:49-592627 gnunet-rest-server-11931 ERROR MHD encountered error handling request: 1 | ||
56 | Failed to send data in request for `/names/'. | ||
57 | Dec 04 13:12:49-601007 gnunet-rest-server-11931 ERROR MHD encountered error handling request: 1 | ||
58 | Dec 04 13:15:25-370395 gnunet-rest-server-13261 ERROR URL (acr_values=true) | ||
59 | Failed to send data in request for `/idp/tickets/testego'. | ||
60 | Dec 04 13:15:25-395382 gnunet-rest-server-13261 ERROR MHD encountered error handling request: 1 | ||
61 | Failed to send data in request for `/idp/attributes/testego'. | ||
62 | Dec 04 13:15:25-399622 gnunet-rest-server-13261 ERROR MHD encountered error handling request: 1 | ||
63 | Failed to send data in request for `/names/'. | ||
64 | Dec 04 13:15:25-408151 gnunet-rest-server-13261 ERROR MHD encountered error handling request: 1 | ||
65 | Dec 04 13:36:24-427812 gnunet-rest-server-15336 ERROR URL (?response_type=code&client_id=test&scope=openid email&redirect_uri=https://google.com&nonce=11111&ui_locales=test&) | ||
66 | Failed to send data in request for `/idp/tickets/testego'. | ||
67 | Dec 04 13:36:24-450636 gnunet-rest-server-15336 ERROR MHD encountered error handling request: 1 | ||
68 | Failed to send data in request for `/idp/attributes/testego'. | ||
69 | Dec 04 13:36:24-456164 gnunet-rest-server-15336 ERROR MHD encountered error handling request: 1 | ||
70 | Failed to send data in request for `/names/'. | ||
71 | Dec 04 13:36:24-461431 gnunet-rest-server-15336 ERROR MHD encountered error handling request: 1 | ||
72 | Dec 04 13:39:02-052691 gnunet-rest-server-16482 ERROR URL (?response_type=code&client_id=test&scope=openid email&redirect_uri=https://google.com&nonce=1111&ui_locales=test&acr_values=true) | ||
73 | Dec 04 15:27:43-226881 gnunet-rest-server-16482 ERROR URL (?response_type=code&client_id=test&scope=openid email&redirect_uri=https://google.com&nonce=11111&ui_locales=test&acr_values=true) | ||
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c index 1aa1f818d..9d61ac92b 100644 --- a/src/identity-provider/plugin_rest_identity_provider.c +++ b/src/identity-provider/plugin_rest_identity_provider.c | |||
@@ -150,8 +150,6 @@ | |||
150 | * OIDC expected scope part while authorizing | 150 | * OIDC expected scope part while authorizing |
151 | */ | 151 | */ |
152 | #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid" | 152 | #define OIDC_EXPECTED_AUTHORIZATION_SCOPE "openid" |
153 | |||
154 | |||
155 | /** | 153 | /** |
156 | * OIDC ignored parameter array | 154 | * OIDC ignored parameter array |
157 | */ | 155 | */ |
@@ -167,6 +165,8 @@ char* OIDC_ignored_parameter_array [] = | |||
167 | "acr_values" | 165 | "acr_values" |
168 | }; | 166 | }; |
169 | 167 | ||
168 | struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
169 | |||
170 | /** | 170 | /** |
171 | * OIDC authorized identities and times hashmap | 171 | * OIDC authorized identities and times hashmap |
172 | */ | 172 | */ |
@@ -366,6 +366,10 @@ cleanup_handle (struct RequestHandle *handle) | |||
366 | GNUNET_free (handle->url); | 366 | GNUNET_free (handle->url); |
367 | if (NULL != handle->emsg) | 367 | if (NULL != handle->emsg) |
368 | GNUNET_free (handle->emsg); | 368 | GNUNET_free (handle->emsg); |
369 | if (NULL != handle->edesc) | ||
370 | GNUNET_free (handle->edesc); | ||
371 | if (NULL != handle->eredirect) | ||
372 | GNUNET_free (handle->eredirect); | ||
369 | for (ego_entry = handle->ego_head; | 373 | for (ego_entry = handle->ego_head; |
370 | NULL != ego_entry;) | 374 | NULL != ego_entry;) |
371 | { | 375 | { |
@@ -1125,32 +1129,358 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1125 | } | 1129 | } |
1126 | 1130 | ||
1127 | /** | 1131 | /** |
1128 | * Respond to OPTIONS request | 1132 | * Function called if we had an error in zone-to-name mapping. |
1133 | */ | ||
1134 | static void | ||
1135 | zone_to_name_error (void *cls) | ||
1136 | { | ||
1137 | struct RequestHandle *handle = cls; | ||
1138 | |||
1139 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1140 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1141 | |||
1142 | GNUNET_NAMESTORE_disconnect (namestore_handle); | ||
1143 | namestore_handle = NULL; | ||
1144 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1145 | } | ||
1146 | |||
1147 | /** | ||
1148 | * Test if a name mapping was found, if so, continue, else, throw error | ||
1149 | * | ||
1150 | * @param cls closure | ||
1151 | * @param zone_key public key of the zone | ||
1152 | * @param name name that is being mapped (at most 255 characters long) | ||
1153 | * @param rd_count number of entries in @a rd array | ||
1154 | * @param rd array of records with data to store | ||
1155 | */ | ||
1156 | static void | ||
1157 | zone_to_name_cb (void *cls, | ||
1158 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | ||
1159 | const char *name, | ||
1160 | unsigned int rd_count, | ||
1161 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1162 | { | ||
1163 | struct RequestHandle *handle = cls; | ||
1164 | |||
1165 | |||
1166 | if (0 == rd_count) | ||
1167 | { | ||
1168 | handle->emsg = GNUNET_strdup("unauthorized_client"); | ||
1169 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1170 | |||
1171 | GNUNET_NAMESTORE_disconnect (namestore_handle); | ||
1172 | namestore_handle = NULL; | ||
1173 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1174 | return; | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | /** | ||
1179 | * Respond to authorization request | ||
1129 | * | 1180 | * |
1130 | * @param con_handle the connection handle | 1181 | * @param con_handle the connection handle |
1131 | * @param url the url | 1182 | * @param url the url |
1132 | * @param cls the RequestHandle | 1183 | * @param cls the RequestHandle |
1133 | */ | 1184 | */ |
1134 | static void | 1185 | static void |
1135 | authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | 1186 | authorize_get_cont (struct GNUNET_REST_RequestHandle *con_handle, |
1136 | const char* url, | 1187 | const char* url, |
1137 | void *cls) | 1188 | void *cls) |
1138 | { | 1189 | { |
1190 | /** The Authorization Server MUST validate all the OAuth 2.0 parameters | ||
1191 | * according to the OAuth 2.0 specification. | ||
1192 | */ | ||
1193 | /** | ||
1194 | * If the sub (subject) Claim is requested with a specific value for the | ||
1195 | * ID Token, the Authorization Server MUST only send a positive response | ||
1196 | * if the End-User identified by that sub value has an active session with | ||
1197 | * the Authorization Server or has been Authenticated as a result of the | ||
1198 | * request. The Authorization Server MUST NOT reply with an ID Token or | ||
1199 | * Access Token for a different user, even if they have an active session | ||
1200 | * with the Authorization Server. Such a request can be made either using | ||
1201 | * an id_token_hint parameter or by requesting a specific Claim Value as | ||
1202 | * described in Section 5.5.1, if the claims parameter is supported by | ||
1203 | * the implementation. | ||
1204 | */ | ||
1205 | |||
1139 | struct MHD_Response *resp; | 1206 | struct MHD_Response *resp; |
1140 | struct RequestHandle *handle = cls; | 1207 | struct RequestHandle *handle = cls; |
1141 | char *response_type; | 1208 | char *response_type; |
1142 | char *client_id; | 1209 | char *client_id; |
1143 | char *scope; | 1210 | char *scope; |
1144 | char *redirect_uri; | 1211 | char *redirect_uri; |
1212 | char *expected_redirect_uri; | ||
1145 | char *state = NULL; | 1213 | char *state = NULL; |
1146 | char *nonce = NULL; | 1214 | char *nonce = NULL; |
1147 | struct GNUNET_TIME_Absolute current_time, *relog_time; | 1215 | struct GNUNET_TIME_Absolute current_time, *relog_time; |
1148 | char *login_base_url, *new_redirect; | 1216 | char *login_base_url, *new_redirect; |
1149 | struct GNUNET_HashCode cache_key; | 1217 | struct GNUNET_HashCode cache_key; |
1218 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey; | ||
1219 | struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; | ||
1220 | int number_of_ignored_parameter, iterator; | ||
1221 | |||
1222 | // REQUIRED value: client_id | ||
1223 | GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), | ||
1224 | &cache_key); | ||
1225 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1226 | &cache_key)) | ||
1227 | { | ||
1228 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1229 | handle->edesc=GNUNET_strdup("Missing parameter: client_id"); | ||
1230 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1231 | return; | ||
1232 | } | ||
1233 | client_id = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1234 | &cache_key); | ||
1235 | if ( GNUNET_OK | ||
1236 | != GNUNET_CRYPTO_ecdsa_public_key_from_string (client_id, | ||
1237 | strlen (client_id), | ||
1238 | &pubkey) ) | ||
1239 | { | ||
1240 | handle->emsg=GNUNET_strdup("unauthorized_client"); | ||
1241 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1242 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1243 | } | ||
1244 | |||
1245 | // Checks if client_id is valid: | ||
1246 | namestore_handle = GNUNET_NAMESTORE_connect(cfg); | ||
1247 | zone_pkey = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | ||
1248 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, zone_pkey, &pubkey, | ||
1249 | zone_to_name_error, handle, zone_to_name_cb, | ||
1250 | handle); | ||
1251 | |||
1252 | // REQUIRED value: redirect_uri | ||
1253 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), | ||
1254 | &cache_key); | ||
1255 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1256 | &cache_key)) | ||
1257 | { | ||
1258 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1259 | handle->edesc=GNUNET_strdup("Missing parameter: redirect_uri"); | ||
1260 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1261 | return; | ||
1262 | } | ||
1263 | redirect_uri = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1264 | &cache_key); | ||
1265 | |||
1266 | GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", client_id); | ||
1267 | |||
1268 | // verify the redirect uri matches https://<client_id>.zkey[/xyz] | ||
1269 | if( 0 != strncmp( expected_redirect_uri, redirect_uri, strlen(expected_redirect_uri)) ) | ||
1270 | { | ||
1271 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1272 | handle->edesc=GNUNET_strdup("Invalid redirect_uri"); | ||
1273 | GNUNET_free(expected_redirect_uri); | ||
1274 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1275 | return; | ||
1276 | } | ||
1277 | handle->eredirect = GNUNET_strdup(redirect_uri); | ||
1278 | |||
1279 | // REQUIRED value: response_type | ||
1280 | GNUNET_CRYPTO_hash (OIDC_RESPONSE_TYPE_KEY, strlen (OIDC_RESPONSE_TYPE_KEY), | ||
1281 | &cache_key); | ||
1282 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1283 | &cache_key)) | ||
1284 | { | ||
1285 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1286 | handle->edesc=GNUNET_strdup("Missing parameter: response_type"); | ||
1287 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1288 | return; | ||
1289 | } | ||
1290 | response_type = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1291 | &cache_key); | ||
1292 | |||
1293 | // REQUIRED value: scope | ||
1294 | GNUNET_CRYPTO_hash (OIDC_SCOPE_KEY, strlen (OIDC_SCOPE_KEY), &cache_key); | ||
1295 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1296 | &cache_key)) | ||
1297 | { | ||
1298 | handle->emsg=GNUNET_strdup("invalid_request"); | ||
1299 | handle->edesc=GNUNET_strdup("Missing parameter: scope"); | ||
1300 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1301 | return; | ||
1302 | } | ||
1303 | scope = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1304 | &cache_key); | ||
1305 | |||
1306 | //RECOMMENDED value: state | ||
1307 | GNUNET_CRYPTO_hash (OIDC_STATE_KEY, strlen (OIDC_STATE_KEY), &cache_key); | ||
1308 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1309 | &cache_key)) | ||
1310 | { | ||
1311 | state = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1312 | &cache_key); | ||
1313 | } | ||
1314 | |||
1315 | //OPTIONAL value: nonce | ||
1316 | GNUNET_CRYPTO_hash (OIDC_NONCE_KEY, strlen (OIDC_NONCE_KEY), &cache_key); | ||
1317 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1318 | &cache_key)) | ||
1319 | { | ||
1320 | nonce = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | ||
1321 | &cache_key); | ||
1322 | } | ||
1323 | |||
1324 | number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); | ||
1325 | for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) | ||
1326 | { | ||
1327 | GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], | ||
1328 | strlen(OIDC_ignored_parameter_array[iterator]), | ||
1329 | &cache_key); | ||
1330 | if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(handle->rest_handle->url_param_map, | ||
1331 | &cache_key)) | ||
1332 | { | ||
1333 | handle->emsg=GNUNET_strdup("access_denied"); | ||
1334 | GNUNET_asprintf (*handle->edesc, "Server will not handle parameter: %s", | ||
1335 | OIDC_ignored_parameter_array[iterator]); | ||
1336 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1337 | return; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | // Checks if response_type is 'code' | ||
1342 | if( 0 != strcmp( response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) | ||
1343 | { | ||
1344 | handle->emsg=GNUNET_strdup("unsupported_response_type"); | ||
1345 | handle->edesc=GNUNET_strdup("The authorization server does not support " | ||
1346 | "obtaining this authorization code."); | ||
1347 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1348 | return; | ||
1349 | } | ||
1350 | // Checks if scope contains 'openid' | ||
1351 | if( NULL == strstr( scope, OIDC_EXPECTED_AUTHORIZATION_SCOPE ) ) | ||
1352 | { | ||
1353 | handle->emsg=GNUNET_strdup("invalid_scope"); | ||
1354 | handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " | ||
1355 | "malformed."); | ||
1356 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | ||
1357 | return; | ||
1358 | } | ||
1359 | |||
1360 | //TODO check other values and use them accordingly | ||
1361 | |||
1362 | GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), | ||
1363 | &cache_key); | ||
1364 | //No identity-cookie -> redirect to login | ||
1365 | if ( GNUNET_YES | ||
1366 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->header_param_map, | ||
1367 | &cache_key) ) | ||
1368 | { | ||
1369 | //split cookies and find 'Identity' cookie | ||
1370 | char* cookies = GNUNET_CONTAINER_multihashmap_get ( | ||
1371 | con_handle->header_param_map, &cache_key); | ||
1372 | char delimiter[] = "; "; | ||
1373 | char *identity_cookie; | ||
1374 | identity_cookie = strtok(cookies, delimiter); | ||
1375 | |||
1376 | while ( NULL != identity_cookie ) | ||
1377 | { | ||
1378 | if ( NULL != strstr (identity_cookie, OIDC_COOKIE_HEADER_INFORMATION_KEY) ) | ||
1379 | { | ||
1380 | break; | ||
1381 | } | ||
1382 | identity_cookie = strtok (NULL, delimiter); | ||
1383 | } | ||
1384 | GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); | ||
1150 | 1385 | ||
1151 | //TODO clean up method | 1386 | //No login time for identity -> redirect to login |
1387 | if ( GNUNET_YES | ||
1388 | == GNUNET_CONTAINER_multihashmap_contains (OIDC_authorized_identities, | ||
1389 | &cache_key) ) | ||
1390 | { | ||
1391 | relog_time = GNUNET_CONTAINER_multihashmap_get ( | ||
1392 | OIDC_authorized_identities, &cache_key); | ||
1152 | 1393 | ||
1153 | /** The Authorization Server MUST validate all the OAuth 2.0 parameters | 1394 | current_time = GNUNET_TIME_absolute_get(); |
1395 | |||
1396 | GNUNET_CONTAINER_multihashmap_remove_all(OIDC_authorized_identities, &cache_key); | ||
1397 | // 30 min after old login -> redirect to login | ||
1398 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) | ||
1399 | { | ||
1400 | resp = GNUNET_REST_create_response (""); | ||
1401 | |||
1402 | GNUNET_CRYPTO_ecdsa_public_key_from_string (identity_cookie, | ||
1403 | strlen (identity_cookie), | ||
1404 | &pubkey); | ||
1405 | |||
1406 | // iterate over egos and compare their public key | ||
1407 | // GNUNET_IDENTITY_PROVIDER_get_attributes_start | ||
1408 | // iterate over scope variables | ||
1409 | char delimiter[] = " "; | ||
1410 | char *scope_attribute; | ||
1411 | scope_attribute = strtok(scope, delimiter); | ||
1412 | |||
1413 | while ( NULL != scope_attribute ) | ||
1414 | { | ||
1415 | if ( NULL == strstr (scope_attribute, OIDC_EXPECTED_AUTHORIZATION_SCOPE) ) | ||
1416 | { | ||
1417 | // claim attribute from ego | ||
1418 | scope_attribute = strtok (NULL, delimiter); | ||
1419 | } | ||
1420 | } | ||
1421 | // create an authorization code | ||
1422 | |||
1423 | // GNUNET_IDENTITY_PROVIDER_t | ||
1424 | |||
1425 | MHD_add_response_header (resp, "Location", redirect_uri); | ||
1426 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
1427 | cleanup_handle (handle); | ||
1428 | GNUNET_free(relog_time); | ||
1429 | return; | ||
1430 | } | ||
1431 | GNUNET_free(relog_time); | ||
1432 | } | ||
1433 | } | ||
1434 | |||
1435 | |||
1436 | // login redirection | ||
1437 | if ( GNUNET_OK | ||
1438 | == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", | ||
1439 | "address", &login_base_url) ) | ||
1440 | { | ||
1441 | GNUNET_asprintf (&new_redirect, "%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s", | ||
1442 | login_base_url, | ||
1443 | OIDC_RESPONSE_TYPE_KEY, | ||
1444 | response_type, | ||
1445 | OIDC_CLIENT_ID_KEY, | ||
1446 | client_id, | ||
1447 | OIDC_REDIRECT_URI_KEY, | ||
1448 | redirect_uri, | ||
1449 | OIDC_SCOPE_KEY, | ||
1450 | scope, | ||
1451 | OIDC_STATE_KEY, | ||
1452 | (NULL == state) ? state : "", | ||
1453 | OIDC_NONCE_KEY, | ||
1454 | (NULL == nonce) ? nonce : ""); | ||
1455 | resp = GNUNET_REST_create_response (""); | ||
1456 | MHD_add_response_header (resp, "Location", new_redirect); | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | handle->emsg = GNUNET_strdup("No server configuration"); | ||
1461 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1462 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1463 | return; | ||
1464 | } | ||
1465 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | ||
1466 | cleanup_handle (handle); | ||
1467 | GNUNET_free(new_redirect); | ||
1468 | return; | ||
1469 | } | ||
1470 | |||
1471 | /** | ||
1472 | * Respond to authorization request | ||
1473 | * | ||
1474 | * @param con_handle the connection handle | ||
1475 | * @param url the url | ||
1476 | * @param cls the RequestHandle | ||
1477 | */ | ||
1478 | static void | ||
1479 | authorize_post_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
1480 | const char* url, | ||
1481 | void *cls) | ||
1482 | { | ||
1483 | /** The Authorization Server MUST validate all the OAuth 2.0 parameters | ||
1154 | * according to the OAuth 2.0 specification. | 1484 | * according to the OAuth 2.0 specification. |
1155 | */ | 1485 | */ |
1156 | /** | 1486 | /** |
@@ -1166,7 +1496,27 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1166 | * the implementation. | 1496 | * the implementation. |
1167 | */ | 1497 | */ |
1168 | 1498 | ||
1499 | struct MHD_Response *resp; | ||
1500 | struct RequestHandle *handle = cls; | ||
1501 | char *response_type; | ||
1502 | char *client_id; | ||
1503 | char *scope; | ||
1504 | char *redirect_uri; | ||
1505 | char *expected_redirect_uri; | ||
1506 | char *state = NULL; | ||
1507 | char *nonce = NULL; | ||
1508 | struct GNUNET_TIME_Absolute current_time, *relog_time; | ||
1509 | char *login_base_url, *new_redirect; | ||
1510 | struct GNUNET_HashCode cache_key; | ||
1511 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey; | ||
1512 | struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; | ||
1513 | int number_of_ignored_parameter, iterator; | ||
1169 | 1514 | ||
1515 | json_t *root; | ||
1516 | json_error_t error; | ||
1517 | json_t *identity; | ||
1518 | root = json_loads (handle->rest_handle->data, 0, &error); | ||
1519 | client_id = json_object_get (root, OIDC_CLIENT_ID_KEY); | ||
1170 | 1520 | ||
1171 | // REQUIRED value: client_id | 1521 | // REQUIRED value: client_id |
1172 | GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), | 1522 | GNUNET_CRYPTO_hash (OIDC_CLIENT_ID_KEY, strlen (OIDC_CLIENT_ID_KEY), |
@@ -1181,24 +1531,24 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1181 | } | 1531 | } |
1182 | client_id = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | 1532 | client_id = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, |
1183 | &cache_key); | 1533 | &cache_key); |
1184 | struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; | 1534 | if ( GNUNET_OK |
1185 | GNUNET_CRYPTO_ecdsa_public_key_from_string(client_id, | 1535 | != GNUNET_CRYPTO_ecdsa_public_key_from_string (client_id, |
1186 | strlen (client_id), | 1536 | strlen (client_id), |
1187 | &pubkey); | 1537 | &pubkey) ) |
1188 | // GNUNET_NAMESTORE_zone_to_name(); | 1538 | { |
1539 | handle->emsg=GNUNET_strdup("unauthorized_client"); | ||
1540 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1541 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1542 | } | ||
1543 | |||
1189 | // Checks if client_id is valid: | 1544 | // Checks if client_id is valid: |
1190 | // TODO use GNUNET_NAMESTORE_zone_to_name() function to verify that a delegation to the client_id exists | 1545 | namestore_handle = GNUNET_NAMESTORE_connect(cfg); |
1191 | // TODO change check (lookup trusted public_key?) | 1546 | zone_pkey = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); |
1192 | // if( strcmp( client_id, "localhost" ) != 0 ) | 1547 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, zone_pkey, &pubkey, |
1193 | // { | 1548 | zone_to_name_error, handle, zone_to_name_cb, |
1194 | // handle->emsg=GNUNET_strdup("unauthorized_client"); | 1549 | handle); |
1195 | // handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
1196 | // GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1197 | // return; | ||
1198 | // } | ||
1199 | 1550 | ||
1200 | // REQUIRED value: redirect_uri | 1551 | // REQUIRED value: redirect_uri |
1201 | // TODO verify the redirect uri matches https://<client_id>.zkey[/xyz] | ||
1202 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), | 1552 | GNUNET_CRYPTO_hash (OIDC_REDIRECT_URI_KEY, strlen (OIDC_REDIRECT_URI_KEY), |
1203 | &cache_key); | 1553 | &cache_key); |
1204 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | 1554 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, |
@@ -1212,15 +1562,17 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1212 | redirect_uri = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, | 1562 | redirect_uri = GNUNET_CONTAINER_multihashmap_get(handle->rest_handle->url_param_map, |
1213 | &cache_key); | 1563 | &cache_key); |
1214 | 1564 | ||
1565 | GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", client_id); | ||
1566 | |||
1215 | // verify the redirect uri matches https://<client_id>.zkey[/xyz] | 1567 | // verify the redirect uri matches https://<client_id>.zkey[/xyz] |
1216 | // TODO change check (check client_id->public key == address) | 1568 | if( 0 != strncmp( expected_redirect_uri, redirect_uri, strlen(expected_redirect_uri)) ) |
1217 | // if( strcmp( redirect_uri, "https://localhost:8000" ) != 0 ) | 1569 | { |
1218 | // { | 1570 | handle->emsg=GNUNET_strdup("invalid_request"); |
1219 | // handle->emsg=GNUNET_strdup("invalid_request"); | 1571 | handle->edesc=GNUNET_strdup("Invalid redirect_uri"); |
1220 | // handle->edesc=GNUNET_strdup("Invalid or mismatching redirect_uri"); | 1572 | GNUNET_free(expected_redirect_uri); |
1221 | // GNUNET_SCHEDULER_add_now (&do_error, handle); | 1573 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1222 | // return; | 1574 | return; |
1223 | // } | 1575 | } |
1224 | handle->eredirect = GNUNET_strdup(redirect_uri); | 1576 | handle->eredirect = GNUNET_strdup(redirect_uri); |
1225 | 1577 | ||
1226 | // REQUIRED value: response_type | 1578 | // REQUIRED value: response_type |
@@ -1268,8 +1620,7 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1268 | &cache_key); | 1620 | &cache_key); |
1269 | } | 1621 | } |
1270 | 1622 | ||
1271 | int number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); | 1623 | number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); |
1272 | int iterator; | ||
1273 | for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) | 1624 | for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) |
1274 | { | 1625 | { |
1275 | GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], | 1626 | GNUNET_CRYPTO_hash (OIDC_ignored_parameter_array[iterator], |
@@ -1279,15 +1630,15 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1279 | &cache_key)) | 1630 | &cache_key)) |
1280 | { | 1631 | { |
1281 | handle->emsg=GNUNET_strdup("access_denied"); | 1632 | handle->emsg=GNUNET_strdup("access_denied"); |
1282 | //TODO rewrite error description | 1633 | GNUNET_asprintf (*handle->edesc, "Server will not handle parameter: %s", |
1283 | handle->edesc=GNUNET_strdup("Server will not handle parameter"); | 1634 | OIDC_ignored_parameter_array[iterator]); |
1284 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); | 1635 | GNUNET_SCHEDULER_add_now (&do_redirect_error, handle); |
1285 | return; | 1636 | return; |
1286 | } | 1637 | } |
1287 | } | 1638 | } |
1288 | 1639 | ||
1289 | // Checks if response_type is 'code' | 1640 | // Checks if response_type is 'code' |
1290 | if( strcmp( response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) != 0 ) | 1641 | if( 0 != strcmp( response_type, OIDC_EXPECTED_AUTHORIZATION_RESPONSE_TYPE ) ) |
1291 | { | 1642 | { |
1292 | handle->emsg=GNUNET_strdup("unsupported_response_type"); | 1643 | handle->emsg=GNUNET_strdup("unsupported_response_type"); |
1293 | handle->edesc=GNUNET_strdup("The authorization server does not support " | 1644 | handle->edesc=GNUNET_strdup("The authorization server does not support " |
@@ -1296,7 +1647,7 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1296 | return; | 1647 | return; |
1297 | } | 1648 | } |
1298 | // Checks if scope contains 'openid' | 1649 | // Checks if scope contains 'openid' |
1299 | if( strstr( scope, OIDC_EXPECTED_AUTHORIZATION_SCOPE ) == NULL ) | 1650 | if( NULL == strstr( scope, OIDC_EXPECTED_AUTHORIZATION_SCOPE ) ) |
1300 | { | 1651 | { |
1301 | handle->emsg=GNUNET_strdup("invalid_scope"); | 1652 | handle->emsg=GNUNET_strdup("invalid_scope"); |
1302 | handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " | 1653 | handle->edesc=GNUNET_strdup("The requested scope is invalid, unknown, or " |
@@ -1305,10 +1656,8 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1305 | return; | 1656 | return; |
1306 | } | 1657 | } |
1307 | 1658 | ||
1308 | |||
1309 | //TODO check other values and use them accordingly | 1659 | //TODO check other values and use them accordingly |
1310 | 1660 | ||
1311 | |||
1312 | GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), | 1661 | GNUNET_CRYPTO_hash (OIDC_COOKIE_HEADER_KEY, strlen (OIDC_COOKIE_HEADER_KEY), |
1313 | &cache_key); | 1662 | &cache_key); |
1314 | //No identity-cookie -> redirect to login | 1663 | //No identity-cookie -> redirect to login |
@@ -1323,13 +1672,13 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1323 | char *identity_cookie; | 1672 | char *identity_cookie; |
1324 | identity_cookie = strtok(cookies, delimiter); | 1673 | identity_cookie = strtok(cookies, delimiter); |
1325 | 1674 | ||
1326 | while(identity_cookie != NULL) | 1675 | while ( NULL != identity_cookie ) |
1327 | { | 1676 | { |
1328 | if(strstr( identity_cookie, OIDC_COOKIE_HEADER_INFORMATION_KEY ) != NULL) | 1677 | if ( NULL != strstr (identity_cookie, OIDC_COOKIE_HEADER_INFORMATION_KEY) ) |
1329 | { | 1678 | { |
1330 | break; | 1679 | break; |
1331 | } | 1680 | } |
1332 | identity_cookie = strtok(NULL, delimiter); | 1681 | identity_cookie = strtok (NULL, delimiter); |
1333 | } | 1682 | } |
1334 | GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); | 1683 | GNUNET_CRYPTO_hash (identity_cookie, strlen (identity_cookie), &cache_key); |
1335 | 1684 | ||
@@ -1348,8 +1697,30 @@ authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
1348 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) | 1697 | if ( current_time.abs_value_us <= relog_time->abs_value_us ) |
1349 | { | 1698 | { |
1350 | resp = GNUNET_REST_create_response (""); | 1699 | resp = GNUNET_REST_create_response (""); |
1351 | // code = struct GNUNET_IDENTITY_PROVIDER_Ticket | 1700 | |
1352 | GNUNET_IDENTITY_PROVIDER_t | 1701 | GNUNET_CRYPTO_ecdsa_public_key_from_string (identity_cookie, |
1702 | strlen (identity_cookie), | ||
1703 | &pubkey); | ||
1704 | |||
1705 | // iterate over egos and compare their public key | ||
1706 | // GNUNET_IDENTITY_PROVIDER_get_attributes_start | ||
1707 | // iterate over scope variables | ||
1708 | char delimiter[] = " "; | ||
1709 | char *scope_attribute; | ||
1710 | scope_attribute = strtok(scope, delimiter); | ||
1711 | |||
1712 | while ( NULL != scope_attribute ) | ||
1713 | { | ||
1714 | if ( NULL == strstr (scope_attribute, OIDC_EXPECTED_AUTHORIZATION_SCOPE) ) | ||
1715 | { | ||
1716 | // claim attribute from ego | ||
1717 | scope_attribute = strtok (NULL, delimiter); | ||
1718 | } | ||
1719 | } | ||
1720 | // create an authorization code | ||
1721 | |||
1722 | // GNUNET_IDENTITY_PROVIDER_t | ||
1723 | |||
1353 | MHD_add_response_header (resp, "Location", redirect_uri); | 1724 | MHD_add_response_header (resp, "Location", redirect_uri); |
1354 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); | 1725 | handle->proc (handle->proc_cls, resp, MHD_HTTP_FOUND); |
1355 | cleanup_handle (handle); | 1726 | cleanup_handle (handle); |
@@ -1459,9 +1830,9 @@ init_cont (struct RequestHandle *handle) | |||
1459 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, | 1830 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, |
1460 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, | 1831 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, |
1461 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, | 1832 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, |
1462 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_cont}, | 1833 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_get_cont}, |
1463 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, | 1834 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, |
1464 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_cont}, | 1835 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_post_cont}, |
1465 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, | 1836 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, |
1466 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, | 1837 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, |
1467 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, | 1838 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, |