aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhil <phil.buschmann@tum.de>2018-02-21 15:57:00 +0100
committerPhil <phil.buschmann@tum.de>2018-02-21 15:57:00 +0100
commitbbe8e9a4e5bc9b60a5cc5f54385e6252a0487aea (patch)
treeb5ce8a4a9abb1e9858aa5e92f643311d9f3a8e04 /src
parentfaf1fef1ed824ca5f7692ac8a6a50f5f35352b0e (diff)
downloadgnunet-bbe8e9a4e5bc9b60a5cc5f54385e6252a0487aea.tar.gz
gnunet-bbe8e9a4e5bc9b60a5cc5f54385e6252a0487aea.zip
-wip UserInfo Endpoint
Diffstat (limited to 'src')
-rw-r--r--src/identity-provider/plugin_rest_identity_provider.c465
-rw-r--r--src/rest/gnunet-rest-server.c1
2 files changed, 354 insertions, 112 deletions
diff --git a/src/identity-provider/plugin_rest_identity_provider.c b/src/identity-provider/plugin_rest_identity_provider.c
index 326313a13..033c6e4ba 100644
--- a/src/identity-provider/plugin_rest_identity_provider.c
+++ b/src/identity-provider/plugin_rest_identity_provider.c
@@ -77,6 +77,11 @@
77#define GNUNET_REST_API_NS_TOKEN "/idp/token" 77#define GNUNET_REST_API_NS_TOKEN "/idp/token"
78 78
79/** 79/**
80 * UserInfo endpoint
81 */
82#define GNUNET_REST_API_NS_USERINFO "/idp/userinfo"
83
84/**
80 * Login namespace 85 * Login namespace
81 */ 86 */
82#define GNUNET_REST_API_NS_LOGIN "/idp/login" 87#define GNUNET_REST_API_NS_LOGIN "/idp/login"
@@ -162,7 +167,6 @@
162 */ 167 */
163#define OIDC_AUTHORIZATION_HEADER_KEY "Authorization" 168#define OIDC_AUTHORIZATION_HEADER_KEY "Authorization"
164 169
165
166/** 170/**
167 * OIDC cookie header information key 171 * OIDC cookie header information key
168 */ 172 */
@@ -204,6 +208,16 @@ struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_login_time;
204struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants; 208struct GNUNET_CONTAINER_MultiHashMap *OIDC_identity_grants;
205 209
206/** 210/**
211 * OIDC ticket/code use only once
212 */
213struct GNUNET_CONTAINER_MultiHashMap *OIDC_ticket_once;
214
215/**
216 * OIDC access_token to ticket and ego
217 */
218struct GNUNET_CONTAINER_MultiHashMap *OIDC_interpret_access_token;
219
220/**
207 * The configuration handle 221 * The configuration handle
208 */ 222 */
209const struct GNUNET_CONFIGURATION_Handle *cfg; 223const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -244,6 +258,8 @@ struct OIDC_Variables
244 258
245 char *login_identity; 259 char *login_identity;
246 260
261 json_t *response;
262
247}; 263};
248 264
249/** 265/**
@@ -456,6 +472,8 @@ cleanup_handle (struct RequestHandle *handle)
456 GNUNET_free(handle->oidc->scope); 472 GNUNET_free(handle->oidc->scope);
457 if (NULL != handle->oidc->state) 473 if (NULL != handle->oidc->state)
458 GNUNET_free(handle->oidc->state); 474 GNUNET_free(handle->oidc->state);
475 if (NULL != handle->oidc->response)
476 json_decref(handle->oidc->response);
459 GNUNET_free(handle->oidc); 477 GNUNET_free(handle->oidc);
460 } 478 }
461 if ( NULL != handle->attr_list ) 479 if ( NULL != handle->attr_list )
@@ -516,12 +534,40 @@ do_error (void *cls)
516 handle->response_code = MHD_HTTP_BAD_REQUEST; 534 handle->response_code = MHD_HTTP_BAD_REQUEST;
517 } 535 }
518 resp = GNUNET_REST_create_response (json_error); 536 resp = GNUNET_REST_create_response (json_error);
537 if (MHD_HTTP_UNAUTHORIZED == handle->response_code)
538 {
539 MHD_add_response_header(resp, "WWW-Authenticate", "Basic");
540 }
519 MHD_add_response_header (resp, "Content-Type", "application/json"); 541 MHD_add_response_header (resp, "Content-Type", "application/json");
520 handle->proc (handle->proc_cls, resp, handle->response_code); 542 handle->proc (handle->proc_cls, resp, handle->response_code);
521 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); 543 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
522 GNUNET_free (json_error); 544 GNUNET_free (json_error);
523} 545}
524 546
547
548/**
549 * Task run on error, sends error message. Cleans up everything.
550 *
551 * @param cls the `struct RequestHandle`
552 */
553static void
554do_userinfo_error (void *cls)
555{
556 struct RequestHandle *handle = cls;
557 struct MHD_Response *resp;
558 char *error;
559
560 GNUNET_asprintf (&error, "error=\"%s\", error_description=\"%s\"",
561 handle->emsg,
562 (NULL != handle->edesc) ? handle->edesc : "");
563 resp = GNUNET_REST_create_response ("");
564 MHD_add_response_header(resp, "WWW-Authenticate", error);
565 handle->proc (handle->proc_cls, resp, handle->response_code);
566 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
567 GNUNET_free (error);
568}
569
570
525/** 571/**
526 * Task run on error, sends error message. Cleans up everything. 572 * Task run on error, sends error message. Cleans up everything.
527 * 573 *
@@ -607,16 +653,38 @@ return_response (void *cls)
607 cleanup_handle (handle); 653 cleanup_handle (handle);
608} 654}
609 655
656/**
657 * Return attributes for claim
658 *
659 * @param cls the request handle
660 */
610static void 661static void
611base_64_encode(char *string, char *output) 662return_userinfo_response (void *cls)
663{
664 char* result_str;
665 struct RequestHandle *handle = cls;
666 struct MHD_Response *resp;
667
668 result_str = json_dumps (handle->oidc->response, 0);
669
670 resp = GNUNET_REST_create_response (result_str);
671 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
672 GNUNET_free (result_str);
673 cleanup_handle (handle);
674}
675
676static char*
677base_64_encode(char *string)
612{ 678{
679 char *output;
613 GNUNET_STRINGS_base64_encode(string,strlen(string),&output); 680 GNUNET_STRINGS_base64_encode(string,strlen(string),&output);
614 char delimiter[] = "="; 681 int index = strlen(output)-1;
615 output = strtok (output, delimiter); 682 while ('=' == output[index])
616 while (NULL != output)
617 { 683 {
618 output = strtok (NULL, delimiter); 684 output[index] = '\0';
685 index--;
619 } 686 }
687 return output;
620} 688}
621 689
622static void 690static void
@@ -1382,23 +1450,13 @@ oidc_ticket_issue_cb (void* cls,
1382 if (NULL != ticket) { 1450 if (NULL != ticket) {
1383 ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket, 1451 ticket_str = GNUNET_STRINGS_data_to_string_alloc (ticket,
1384 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket)); 1452 sizeof (struct GNUNET_IDENTITY_PROVIDER_Ticket));
1385 1453 //TODO change if more attributes are needed (see max_age)
1386// json_t *object=json_object();
1387// json_object_set_new(object,"ticket",json_string(ticket_str));
1388// if(NULL != handle->oidc->nonce)
1389// {
1390// json_object_set_new(object,"nonce",json_string(handle->oidc->nonce));
1391// }
1392 //TODO change
1393 GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}", 1454 GNUNET_asprintf (&code_json_string, "{\"ticket\":\"%s\"%s%s%s}",
1394 ticket_str, 1455 ticket_str,
1395 (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "", 1456 (NULL != handle->oidc->nonce) ? ", \"nonce\":\"" : "",
1396 (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "", 1457 (NULL != handle->oidc->nonce) ? handle->oidc->nonce : "",
1397 (NULL != handle->oidc->nonce) ? "\"" : ""); 1458 (NULL != handle->oidc->nonce) ? "\"" : "");
1398 GNUNET_STRINGS_base64_encode(code_json_string,strlen(code_json_string),&code_base64_final_string); 1459 code_base64_final_string = base_64_encode(code_json_string);
1399 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", code_base64_final_string);
1400 base_64_encode(code_json_string, code_base64_final_string);
1401 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", code_base64_final_string);
1402 GNUNET_asprintf (&redirect_uri, "%s?%s=%s&state=%s", 1460 GNUNET_asprintf (&redirect_uri, "%s?%s=%s&state=%s",
1403 handle->oidc->redirect_uri, 1461 handle->oidc->redirect_uri,
1404 handle->oidc->response_type, 1462 handle->oidc->response_type,
@@ -1707,7 +1765,7 @@ static void namestore_iteration_finished (void *cls)
1707 handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce); 1765 handle->oidc->nonce = GNUNET_strdup (handle->oidc->nonce);
1708 } 1766 }
1709 1767
1710 //TODO check other values and use them accordingly 1768 //TODO check other values if needed
1711 number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *); 1769 number_of_ignored_parameter = sizeof(OIDC_ignored_parameter_array) / sizeof(char *);
1712 for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ ) 1770 for( iterator = 0; iterator < number_of_ignored_parameter; iterator++ )
1713 { 1771 {
@@ -1774,7 +1832,7 @@ static void namestore_iteration_finished (void *cls)
1774 * @param cls the RequestHandle 1832 * @param cls the RequestHandle
1775 */ 1833 */
1776static void 1834static void
1777authorize_cont (struct GNUNET_REST_RequestHandle *con_handle, 1835authorize_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1778 const char* url, 1836 const char* url,
1779 void *cls) 1837 void *cls)
1780{ 1838{
@@ -1898,43 +1956,11 @@ login_cont (struct GNUNET_REST_RequestHandle *con_handle,
1898} 1956}
1899 1957
1900static void 1958static void
1901consume_ticket (void *cls, 1959token_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
1902 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
1903 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
1904{
1905 struct RequestHandle *handle = cls;
1906 struct GNUNET_JSONAPI_Resource *json_resource;
1907 json_t *value;
1908
1909 if (NULL == identity)
1910 {
1911 GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle);
1912// GNUNET_SCHEDULER_add_now (&return_response, handle);
1913 return;
1914 }
1915
1916 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding attribute: %s\n",
1917 attr->name);
1918// json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_ATTRIBUTE,
1919// attr->name);
1920// GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
1921//
1922// value = json_string (attr->data);
1923// GNUNET_JSONAPI_resource_add_attr (json_resource,
1924// "value",
1925// value);
1926// json_decref (value);
1927}
1928
1929static void
1930token_cont(struct GNUNET_REST_RequestHandle *con_handle,
1931 const char* url, 1960 const char* url,
1932 void *cls) 1961 void *cls)
1933{ 1962{
1934 //TODO static strings 1963 //TODO static strings
1935 //TODO Unauthorized with Header Field
1936 //TODO Do not allow multiple equal parameter names
1937 //TODO free
1938 1964
1939 struct RequestHandle *handle = cls; 1965 struct RequestHandle *handle = cls;
1940 struct GNUNET_HashCode cache_key; 1966 struct GNUNET_HashCode cache_key;
@@ -1946,16 +1972,23 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
1946 char *expected_psw; 1972 char *expected_psw;
1947 int client_exists = GNUNET_NO; 1973 int client_exists = GNUNET_NO;
1948 struct MHD_Response *resp; 1974 struct MHD_Response *resp;
1975 char* code_output;
1976 json_t *root, *ticket_string, *nonce, *max_age;
1977 json_error_t error;
1978 char *json_response;
1949 1979
1950 //Check Authorization Header 1980 /*
1981 * Check Authorization
1982 */
1951 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY, 1983 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
1952 strlen (OIDC_AUTHORIZATION_HEADER_KEY), 1984 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
1953 &cache_key); 1985 &cache_key);
1954 if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map, 1986 if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->header_param_map,
1955 &cache_key) ) 1987 &cache_key) )
1956 { 1988 {
1957 handle->emsg=GNUNET_strdup("invalid_request"); 1989 handle->emsg=GNUNET_strdup("invalid_client");
1958 handle->edesc=GNUNET_strdup("missing authorization"); 1990 handle->edesc=GNUNET_strdup("missing authorization");
1991 handle->response_code = MHD_HTTP_UNAUTHORIZED;
1959 GNUNET_SCHEDULER_add_now (&do_error, handle); 1992 GNUNET_SCHEDULER_add_now (&do_error, handle);
1960 return; 1993 return;
1961 } 1994 }
@@ -1964,10 +1997,14 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
1964 //TODO authorization pointer will be moved as well 1997 //TODO authorization pointer will be moved as well
1965 //split header in "Basic" and [content] 1998 //split header in "Basic" and [content]
1966 credentials = strtok (authorization, delimiter); 1999 credentials = strtok (authorization, delimiter);
1967 if( NULL != credentials) 2000 if (0 != strcmp ("Basic",credentials))
1968 { 2001 {
1969 credentials = strtok(NULL, delimiter); 2002 handle->emsg=GNUNET_strdup("invalid_client");
2003 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2004 GNUNET_SCHEDULER_add_now (&do_error, handle);
2005 return;
1970 } 2006 }
2007 credentials = strtok(NULL, delimiter);
1971 if (NULL == credentials) 2008 if (NULL == credentials)
1972 { 2009 {
1973 handle->emsg=GNUNET_strdup("invalid_client"); 2010 handle->emsg=GNUNET_strdup("invalid_client");
@@ -2002,7 +2039,6 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2002 GNUNET_SCHEDULER_add_now (&do_error, handle); 2039 GNUNET_SCHEDULER_add_now (&do_error, handle);
2003 return; 2040 return;
2004 } 2041 }
2005
2006 //check client password 2042 //check client password
2007 if ( GNUNET_OK 2043 if ( GNUNET_OK
2008 == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin", 2044 == GNUNET_CONFIGURATION_get_value_string (cfg, "identity-rest-plugin",
@@ -2025,7 +2061,29 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2025 GNUNET_SCHEDULER_add_now (&do_error, handle); 2061 GNUNET_SCHEDULER_add_now (&do_error, handle);
2026 return; 2062 return;
2027 } 2063 }
2064 //check client_id
2065 for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; )
2066 {
2067 if ( 0 == strcmp(handle->ego_entry->keystring, client_id))
2068 {
2069 client_exists = GNUNET_YES;
2070 break;
2071 }
2072 handle->ego_entry = handle->ego_entry->next;
2073 }
2074 if (GNUNET_NO == client_exists)
2075 {
2076 handle->emsg=GNUNET_strdup("invalid_client");
2077 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2078 GNUNET_SCHEDULER_add_now (&do_error, handle);
2079 return;
2080 }
2081
2082 /*
2083 * Check parameter
2084 */
2028 2085
2086 //TODO Do not allow multiple equal parameter names
2029 //REQUIRED grant_type 2087 //REQUIRED grant_type
2030 GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key); 2088 GNUNET_CRYPTO_hash (OIDC_GRANT_TYPE_KEY, strlen (OIDC_GRANT_TYPE_KEY), &cache_key);
2031 if ( GNUNET_NO 2089 if ( GNUNET_NO
@@ -2034,6 +2092,7 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2034 { 2092 {
2035 handle->emsg = GNUNET_strdup("invalid_request"); 2093 handle->emsg = GNUNET_strdup("invalid_request");
2036 handle->edesc = GNUNET_strdup("missing parameter grant_type"); 2094 handle->edesc = GNUNET_strdup("missing parameter grant_type");
2095 handle->response_code = MHD_HTTP_BAD_REQUEST;
2037 GNUNET_SCHEDULER_add_now (&do_error, handle); 2096 GNUNET_SCHEDULER_add_now (&do_error, handle);
2038 return; 2097 return;
2039 } 2098 }
@@ -2048,6 +2107,7 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2048 { 2107 {
2049 handle->emsg = GNUNET_strdup("invalid_request"); 2108 handle->emsg = GNUNET_strdup("invalid_request");
2050 handle->edesc = GNUNET_strdup("missing parameter code"); 2109 handle->edesc = GNUNET_strdup("missing parameter code");
2110 handle->response_code = MHD_HTTP_BAD_REQUEST;
2051 GNUNET_SCHEDULER_add_now (&do_error, handle); 2111 GNUNET_SCHEDULER_add_now (&do_error, handle);
2052 return; 2112 return;
2053 } 2113 }
@@ -2063,29 +2123,13 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2063 { 2123 {
2064 handle->emsg = GNUNET_strdup("invalid_request"); 2124 handle->emsg = GNUNET_strdup("invalid_request");
2065 handle->edesc = GNUNET_strdup("missing parameter redirect_uri"); 2125 handle->edesc = GNUNET_strdup("missing parameter redirect_uri");
2126 handle->response_code = MHD_HTTP_BAD_REQUEST;
2066 GNUNET_SCHEDULER_add_now (&do_error, handle); 2127 GNUNET_SCHEDULER_add_now (&do_error, handle);
2067 return; 2128 return;
2068 } 2129 }
2069 redirect_uri = GNUNET_CONTAINER_multihashmap_get ( 2130 redirect_uri = GNUNET_CONTAINER_multihashmap_get (
2070 handle->rest_handle->url_param_map, &cache_key); 2131 handle->rest_handle->url_param_map, &cache_key);
2071 2132
2072 //check client_id
2073 for (handle->ego_entry = handle->ego_head; NULL != handle->ego_entry->next; )
2074 {
2075 if ( 0 == strcmp(handle->ego_entry->keystring, client_id))
2076 {
2077 client_exists = GNUNET_YES;
2078 break;
2079 }
2080 handle->ego_entry = handle->ego_entry->next;
2081 }
2082 if (GNUNET_NO == client_exists)
2083 {
2084 handle->emsg=GNUNET_strdup("unauthorized_client");
2085 handle->response_code = MHD_HTTP_BAD_REQUEST;
2086 GNUNET_SCHEDULER_add_now (&do_error, handle);
2087 return;
2088 }
2089 2133
2090 //Check parameter grant_type == "authorization_code" 2134 //Check parameter grant_type == "authorization_code"
2091 if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type)) 2135 if (0 != strcmp(OIDC_GRANT_TYPE_VALUE, grant_type))
@@ -2095,7 +2139,6 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2095 GNUNET_SCHEDULER_add_now (&do_error, handle); 2139 GNUNET_SCHEDULER_add_now (&do_error, handle);
2096 return; 2140 return;
2097 } 2141 }
2098
2099 // check redirect_uri 2142 // check redirect_uri
2100 GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", client_id); 2143 GNUNET_asprintf (&expected_redirect_uri, "https://%s.zkey", client_id);
2101 // verify the redirect uri matches https://<client_id>.zkey[/xyz] 2144 // verify the redirect uri matches https://<client_id>.zkey[/xyz]
@@ -2103,32 +2146,42 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2103 { 2146 {
2104 handle->emsg=GNUNET_strdup("invalid_request"); 2147 handle->emsg=GNUNET_strdup("invalid_request");
2105 handle->edesc=GNUNET_strdup("Invalid redirect_uri"); 2148 handle->edesc=GNUNET_strdup("Invalid redirect_uri");
2149 handle->response_code = MHD_HTTP_BAD_REQUEST;
2106 GNUNET_SCHEDULER_add_now (&do_error, handle); 2150 GNUNET_SCHEDULER_add_now (&do_error, handle);
2107 GNUNET_free(expected_redirect_uri); 2151 GNUNET_free(expected_redirect_uri);
2108 return; 2152 return;
2109 } 2153 }
2110 GNUNET_free(expected_redirect_uri); 2154 GNUNET_free(expected_redirect_uri);
2155 GNUNET_CRYPTO_hash(code, strlen(code), &cache_key);
2156 if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(OIDC_ticket_once,&cache_key))
2157 {
2158 handle->emsg = GNUNET_strdup("invalid_request");
2159 handle->edesc = GNUNET_strdup("Cannot use the same code more than once");
2160 handle->response_code = MHD_HTTP_BAD_REQUEST;
2161 GNUNET_SCHEDULER_add_now (&do_error, handle);
2162 return;
2163 }
2164 int i=1;
2165 GNUNET_CONTAINER_multihashmap_put(OIDC_ticket_once,&cache_key,&i,GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
2111 2166
2112 char* output; 2167 //decode code
2113 GNUNET_STRINGS_base64_decode(code,strlen(code),&output); 2168 GNUNET_STRINGS_base64_decode(code,strlen(code),&code_output);
2114 2169 root = json_loads (code_output, 0, &error);
2115 json_t *root; 2170 GNUNET_free(code_output);
2116 json_error_t error;
2117 json_t *ticket_string;
2118 json_t *nonce;
2119 root = json_loads (output, 0, &error);
2120 ticket_string = json_object_get (root, "ticket"); 2171 ticket_string = json_object_get (root, "ticket");
2121 nonce = json_object_get (root, "nonce"); 2172 nonce = json_object_get (root, "nonce");
2173 max_age = json_object_get (root, "max_age");
2122 2174
2123
2124 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket);
2125 if(ticket_string == NULL && !json_is_string(ticket_string)) 2175 if(ticket_string == NULL && !json_is_string(ticket_string))
2126 { 2176 {
2127 handle->emsg = GNUNET_strdup("invalid_request"); 2177 handle->emsg = GNUNET_strdup("invalid_request");
2128 handle->edesc = GNUNET_strdup("invalid code."); 2178 handle->edesc = GNUNET_strdup("invalid code");
2179 handle->response_code = MHD_HTTP_BAD_REQUEST;
2129 GNUNET_SCHEDULER_add_now (&do_error, handle); 2180 GNUNET_SCHEDULER_add_now (&do_error, handle);
2130 return; 2181 return;
2131 } 2182 }
2183
2184 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket);
2132 if ( GNUNET_OK 2185 if ( GNUNET_OK
2133 != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string), 2186 != GNUNET_STRINGS_string_to_data (json_string_value(ticket_string),
2134 strlen (json_string_value(ticket_string)), 2187 strlen (json_string_value(ticket_string)),
@@ -2136,19 +2189,22 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2136 sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket))) 2189 sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket)))
2137 { 2190 {
2138 handle->emsg = GNUNET_strdup("invalid_request"); 2191 handle->emsg = GNUNET_strdup("invalid_request");
2139 handle->edesc = GNUNET_strdup("invalid code.."); 2192 handle->edesc = GNUNET_strdup("invalid code");
2193 handle->response_code = MHD_HTTP_BAD_REQUEST;
2140 GNUNET_SCHEDULER_add_now (&do_error, handle); 2194 GNUNET_SCHEDULER_add_now (&do_error, handle);
2195 GNUNET_free(ticket);
2141 return; 2196 return;
2142 } 2197 }
2143 // this is the current client (relying party) 2198 // this is the current client (relying party)
2144 //TODO change
2145 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; 2199 struct GNUNET_CRYPTO_EcdsaPublicKey pub_key;
2146 GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key); 2200 GNUNET_IDENTITY_ego_get_public_key(handle->ego_entry->ego,&pub_key);
2147 if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey))) 2201 if (0 != memcmp(&pub_key,&ticket->audience,sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)))
2148 { 2202 {
2149 handle->emsg = GNUNET_strdup("invalid_request"); 2203 handle->emsg = GNUNET_strdup("invalid_request");
2150 handle->edesc = GNUNET_strdup("invalid code..."); 2204 handle->edesc = GNUNET_strdup("invalid code");
2205 handle->response_code = MHD_HTTP_BAD_REQUEST;
2151 GNUNET_SCHEDULER_add_now (&do_error, handle); 2206 GNUNET_SCHEDULER_add_now (&do_error, handle);
2207 GNUNET_free(ticket);
2152 return; 2208 return;
2153 } 2209 }
2154 2210
@@ -2162,6 +2218,7 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2162 handle->edesc = GNUNET_strdup ("gnunet configuration failed"); 2218 handle->edesc = GNUNET_strdup ("gnunet configuration failed");
2163 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; 2219 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
2164 GNUNET_SCHEDULER_add_now (&do_error, handle); 2220 GNUNET_SCHEDULER_add_now (&do_error, handle);
2221 GNUNET_free(ticket);
2165 return; 2222 return;
2166 } 2223 }
2167 2224
@@ -2192,7 +2249,7 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2192 GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING, 2249 GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
2193 time_now_string, 2250 time_now_string,
2194 strlen(time_now_string)); 2251 strlen(time_now_string));
2195 //nonce only if nonce 2252 //nonce only if nonce is provided
2196 if ( NULL != nonce && json_is_string(nonce) ) 2253 if ( NULL != nonce && json_is_string(nonce) )
2197 { 2254 {
2198 GNUNET_IDENTITY_ATTRIBUTE_list_add (cl, 2255 GNUNET_IDENTITY_ATTRIBUTE_list_add (cl,
@@ -2201,8 +2258,15 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2201 json_string_value(nonce), 2258 json_string_value(nonce),
2202 strlen(json_string_value(nonce))); 2259 strlen(json_string_value(nonce)));
2203 } 2260 }
2204 2261 //auth_time only if max_age is provided
2205 //TODO auth_time only if max_age 2262 if ( NULL != max_age && json_is_string(max_age) )
2263 {
2264 GNUNET_IDENTITY_ATTRIBUTE_list_add (cl,
2265 "auth_time",
2266 GNUNET_IDENTITY_ATTRIBUTE_TYPE_STRING,
2267 json_string_value(max_age),
2268 strlen(json_string_value(max_age)));
2269 }
2206 //TODO OPTIONAL acr,amr,azp 2270 //TODO OPTIONAL acr,amr,azp
2207 2271
2208 //TODO lookup client for client == audience of ticket 2272 //TODO lookup client for client == audience of ticket
@@ -2219,14 +2283,16 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2219 { 2283 {
2220 handle->emsg = GNUNET_strdup("invalid_request"); 2284 handle->emsg = GNUNET_strdup("invalid_request");
2221 handle->edesc = GNUNET_strdup("invalid code...."); 2285 handle->edesc = GNUNET_strdup("invalid code....");
2286 handle->response_code = MHD_HTTP_BAD_REQUEST;
2222 GNUNET_SCHEDULER_add_now (&do_error, handle); 2287 GNUNET_SCHEDULER_add_now (&do_error, handle);
2288 GNUNET_free(ticket);
2223 return; 2289 return;
2224 } 2290 }
2225 char *id_token = jwt_create_from_list(&ticket->audience, 2291 char *id_token = jwt_create_from_list(&ticket->audience,
2226 cl, 2292 cl,
2227 GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego)); 2293 GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego));
2228 2294
2229 // random access_token 2295 //Create random access_token
2230 char* access_token_number; 2296 char* access_token_number;
2231 char* access_token; 2297 char* access_token;
2232 uint64_t random_number; 2298 uint64_t random_number;
@@ -2235,9 +2301,9 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2235 GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token); 2301 GNUNET_STRINGS_base64_encode(access_token_number,strlen(access_token_number),&access_token);
2236 2302
2237 2303
2238 char *json_error; 2304
2239 //TODO optional refresh_token and scope 2305 //TODO OPTIONAL add refresh_token and scope
2240 GNUNET_asprintf (&json_error, 2306 GNUNET_asprintf (&json_response,
2241 "{ \"access_token\" : \"%s\", " 2307 "{ \"access_token\" : \"%s\", "
2242 "\"token_type\" : \"Bearer\", " 2308 "\"token_type\" : \"Bearer\", "
2243 "\"expires_in\" : %d, " 2309 "\"expires_in\" : %d, "
@@ -2245,31 +2311,184 @@ token_cont(struct GNUNET_REST_RequestHandle *con_handle,
2245 access_token, 2311 access_token,
2246 expiration_time, 2312 expiration_time,
2247 id_token); 2313 id_token);
2248 2314 GNUNET_CRYPTO_hash(access_token, strlen(access_token), &cache_key);
2249 resp = GNUNET_REST_create_response (json_error); 2315 char *id_ticket_combination;
2316 GNUNET_asprintf(&id_ticket_combination,
2317 "%s;%s",
2318 client_id,
2319 json_string_value(ticket_string));
2320 GNUNET_CONTAINER_multihashmap_put(OIDC_interpret_access_token,
2321 &cache_key,
2322 id_ticket_combination,
2323 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
2324
2325 resp = GNUNET_REST_create_response (json_response);
2250 MHD_add_response_header (resp, "Cache-Control", "no-store"); 2326 MHD_add_response_header (resp, "Cache-Control", "no-store");
2251 MHD_add_response_header (resp, "Pragma", "no-cache"); 2327 MHD_add_response_header (resp, "Pragma", "no-cache");
2252 MHD_add_response_header (resp, "Content-Type", "application/json"); 2328 MHD_add_response_header (resp, "Content-Type", "application/json");
2253 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 2329 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
2254 2330
2331 //TODO one time ticket/code
2332
2333 //TODO free
2255 GNUNET_IDENTITY_ATTRIBUTE_list_destroy(cl); 2334 GNUNET_IDENTITY_ATTRIBUTE_list_destroy(cl);
2256 //TODO write method
2257 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
2258 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (handle->idp,
2259 GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego),
2260 ticket,
2261 consume_ticket,
2262 handle);
2263 GNUNET_free(access_token_number); 2335 GNUNET_free(access_token_number);
2264 GNUNET_free(access_token); 2336 GNUNET_free(access_token);
2265 GNUNET_free(user_psw); 2337 GNUNET_free(user_psw);
2266 GNUNET_free(json_error); 2338 GNUNET_free(json_response);
2267 GNUNET_free(ticket); 2339 GNUNET_free(ticket);
2268 GNUNET_free(output);
2269 GNUNET_free(id_token); 2340 GNUNET_free(id_token);
2270 json_decref(root); 2341 json_decref (root);
2342 GNUNET_SCHEDULER_add_now(&cleanup_handle_delayed, handle);
2343}
2344
2345
2346static void
2347consume_ticket (void *cls,
2348 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
2349 const struct GNUNET_IDENTITY_ATTRIBUTE_Claim *attr)
2350{
2351 struct RequestHandle *handle = cls;
2352
2353 if (NULL == identity)
2354 {
2355 GNUNET_SCHEDULER_add_now (&return_userinfo_response, handle);
2356 return;
2357 }
2358
2359 json_object_set_new (handle->oidc->response,
2360 attr->name,
2361 json_string(attr->data));
2362}
2363
2364static void
2365userinfo_endpoint (struct GNUNET_REST_RequestHandle *con_handle,
2366 const char* url, void *cls)
2367{
2368 struct RequestHandle *handle = cls;
2369 char delimiter[] = " ";
2370 char delimiter_db[] = ";";
2371 struct GNUNET_HashCode cache_key;
2372 char *authorization, *authorization_type, *authorization_access_token;
2373 char *client_ticket;
2374 struct GNUNET_IDENTITY_PROVIDER_Ticket *ticket;
2375
2376 GNUNET_CRYPTO_hash (OIDC_AUTHORIZATION_HEADER_KEY,
2377 strlen (OIDC_AUTHORIZATION_HEADER_KEY),
2378 &cache_key);
2379 if ( GNUNET_NO
2380 == GNUNET_CONTAINER_multihashmap_contains (
2381 handle->rest_handle->header_param_map, &cache_key) )
2382 {
2383 handle->emsg = GNUNET_strdup("invalid_token");
2384 handle->edesc = GNUNET_strdup("No Access Token");
2385 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2386 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2387 return;
2388 }
2389 authorization = GNUNET_CONTAINER_multihashmap_get (
2390 handle->rest_handle->header_param_map, &cache_key);
2391
2392 //TODO authorization pointer will be moved as well
2393 //split header in "Bearer" and access_token
2394 authorization_type = strtok (authorization, delimiter);
2395 if ( 0 != strcmp ("Bearer", authorization_type) )
2396 {
2397 handle->emsg = GNUNET_strdup("invalid_token");
2398 handle->edesc = GNUNET_strdup("No Access Token");
2399 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2400 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2401 return;
2402 }
2403 authorization_access_token = strtok (NULL, delimiter);
2404 if ( NULL == authorization_access_token )
2405 {
2406 handle->emsg = GNUNET_strdup("invalid_token");
2407 handle->edesc = GNUNET_strdup("No Access Token");
2408 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2409 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2410 return;
2411 }
2412
2413 GNUNET_CRYPTO_hash (authorization_access_token,
2414 strlen (authorization_access_token),
2415 &cache_key);
2416 if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (OIDC_interpret_access_token,
2417 &cache_key) )
2418 {
2419 handle->emsg = GNUNET_strdup("invalid_token");
2420 handle->edesc = GNUNET_strdup("The Access Token expired");
2421 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2422 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2423 return;
2424 }
2425
2426 client_ticket = GNUNET_CONTAINER_multihashmap_get(OIDC_interpret_access_token,
2427 &cache_key);
2428
2429 client_ticket = strtok(client_ticket,delimiter_db);
2430 if (NULL == client_ticket)
2431 {
2432 handle->emsg = GNUNET_strdup("invalid_token");
2433 handle->edesc = GNUNET_strdup("The Access Token expired");
2434 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2435 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2436 return;
2437 }
2438 handle->ego_entry = handle->ego_head;
2439 for(; NULL != handle->ego_entry; handle->ego_entry = handle->ego_entry->next)
2440 {
2441 if (0 == strcmp(handle->ego_entry->keystring,client_ticket))
2442 {
2443 break;
2444 }
2445 }
2446 if (NULL == handle->ego_entry)
2447 {
2448 handle->emsg = GNUNET_strdup("invalid_token");
2449 handle->edesc = GNUNET_strdup("The Access Token expired");
2450 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2451 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2452 return;
2453 }
2454 client_ticket = strtok(NULL, delimiter_db);
2455 if (NULL == client_ticket)
2456 {
2457 handle->emsg = GNUNET_strdup("invalid_token");
2458 handle->edesc = GNUNET_strdup("The Access Token expired");
2459 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2460 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2461 return;
2462 }
2463 ticket = GNUNET_new(struct GNUNET_IDENTITY_PROVIDER_Ticket);
2464 if ( GNUNET_OK
2465 != GNUNET_STRINGS_string_to_data (client_ticket,
2466 strlen (client_ticket),
2467 ticket,
2468 sizeof(struct GNUNET_IDENTITY_PROVIDER_Ticket)))
2469 {
2470 handle->emsg = GNUNET_strdup("invalid_token");
2471 handle->edesc = GNUNET_strdup("The Access Token expired");
2472 handle->response_code = MHD_HTTP_UNAUTHORIZED;
2473 GNUNET_SCHEDULER_add_now (&do_userinfo_error, handle);
2474 GNUNET_free(ticket);
2475 return;
2476 }
2477
2478 handle->idp = GNUNET_IDENTITY_PROVIDER_connect (cfg);
2479 handle->oidc->response = json_object();
2480 json_object_set_new( handle->oidc->response, "sub", json_string( handle->ego_entry->keystring));
2481 handle->idp_op = GNUNET_IDENTITY_PROVIDER_ticket_consume (
2482 handle->idp,
2483 GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego),
2484 ticket,
2485 consume_ticket,
2486 handle);
2487 GNUNET_free(ticket);
2488
2271} 2489}
2272 2490
2491
2273/** 2492/**
2274 * Handle rest request 2493 * Handle rest request
2275 * 2494 *
@@ -2283,10 +2502,12 @@ init_cont (struct RequestHandle *handle)
2283 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont}, 2502 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &list_attribute_cont},
2284 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont}, 2503 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_ATTRIBUTES, &add_attribute_cont},
2285 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont}, 2504 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TICKETS, &list_tickets_cont},
2286 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_cont}, 2505 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint},
2287 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_cont}, //url-encoded 2506 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_AUTHORIZE, &authorize_endpoint}, //url-encoded
2288 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont}, 2507 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_LOGIN, &login_cont},
2289 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_cont}, 2508 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_TOKEN, &token_endpoint },
2509 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2510 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_USERINFO, &userinfo_endpoint },
2290 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont}, 2511 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_REVOKE, &revoke_ticket_cont},
2291 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont}, 2512 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_CONSUME, &consume_ticket_cont},
2292 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER, 2513 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_PROVIDER,
@@ -2376,6 +2597,10 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
2376 OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); 2597 OIDC_identity_login_time = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
2377 if ( NULL == OIDC_identity_grants ) 2598 if ( NULL == OIDC_identity_grants )
2378 OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); 2599 OIDC_identity_grants = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
2600 if ( NULL == OIDC_ticket_once )
2601 OIDC_ticket_once = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
2602 if ( NULL == OIDC_interpret_access_token )
2603 OIDC_interpret_access_token = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
2379 handle->response_code = 0; 2604 handle->response_code = 0;
2380 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 2605 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
2381 handle->proc_cls = proc_cls; 2606 handle->proc_cls = proc_cls;
@@ -2467,6 +2692,22 @@ libgnunet_plugin_rest_identity_provider_done (void *cls)
2467 GNUNET_free(value); 2692 GNUNET_free(value);
2468 } 2693 }
2469 GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants); 2694 GNUNET_CONTAINER_multihashmap_destroy(OIDC_identity_grants);
2695 hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_ticket_once);
2696 while (GNUNET_YES ==
2697 GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
2698 {
2699 if (NULL != value)
2700 GNUNET_free(value);
2701 }
2702 GNUNET_CONTAINER_multihashmap_destroy(OIDC_ticket_once);
2703 hashmap_it = GNUNET_CONTAINER_multihashmap_iterator_create (OIDC_interpret_access_token);
2704 while (GNUNET_YES ==
2705 GNUNET_CONTAINER_multihashmap_iterator_next (hashmap_it, NULL, value))
2706 {
2707 if (NULL != value)
2708 GNUNET_free(value);
2709 }
2710 GNUNET_CONTAINER_multihashmap_destroy(OIDC_interpret_access_token);
2470 GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it); 2711 GNUNET_CONTAINER_multihashmap_iterator_destroy(hashmap_it);
2471 GNUNET_free_non_null (allow_methods); 2712 GNUNET_free_non_null (allow_methods);
2472 GNUNET_free (api); 2713 GNUNET_free (api);
diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c
index 4313f07a2..fdcd4f9c5 100644
--- a/src/rest/gnunet-rest-server.c
+++ b/src/rest/gnunet-rest-server.c
@@ -303,6 +303,7 @@ post_data_iter (void *cls,
303 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 303 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
304 "Could not load add url param `%s'=%s\n", 304 "Could not load add url param `%s'=%s\n",
305 key, data); 305 key, data);
306 GNUNET_free(val);
306 } 307 }
307 return MHD_YES; 308 return MHD_YES;
308 309