diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-09-08 22:17:34 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-09-08 22:17:34 +0200 |
commit | 9ee1ef3d55721c37bac0978c0e7ead0c9c49eef1 (patch) | |
tree | 2241b071bcde8a6cd24aca3d1e8f93f66cb54f6a /src/rest/gnunet-rest-server.c | |
parent | 0b07a5569648e37633fedd3abd06592d19d41dee (diff) | |
download | gnunet-9ee1ef3d55721c37bac0978c0e7ead0c9c49eef1.tar.gz gnunet-9ee1ef3d55721c37bac0978c0e7ead0c9c49eef1.zip |
REST: Implement basic authentication for per user service. Fixes #5669
Diffstat (limited to 'src/rest/gnunet-rest-server.c')
-rw-r--r-- | src/rest/gnunet-rest-server.c | 112 |
1 files changed, 106 insertions, 6 deletions
diff --git a/src/rest/gnunet-rest-server.c b/src/rest/gnunet-rest-server.c index 63847587b..9984478ce 100644 --- a/src/rest/gnunet-rest-server.c +++ b/src/rest/gnunet-rest-server.c | |||
@@ -120,6 +120,21 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; | |||
120 | static int echo_origin; | 120 | static int echo_origin; |
121 | 121 | ||
122 | /** | 122 | /** |
123 | * Do basic auth of user | ||
124 | */ | ||
125 | static int basic_auth_enabled; | ||
126 | |||
127 | /** | ||
128 | * Basic auth secret | ||
129 | */ | ||
130 | static char *basic_auth_secret; | ||
131 | |||
132 | /** | ||
133 | * User of the service | ||
134 | */ | ||
135 | char cuser[LOGIN_NAME_MAX]; | ||
136 | |||
137 | /** | ||
123 | * Allowed Origins (CORS) | 138 | * Allowed Origins (CORS) |
124 | */ | 139 | */ |
125 | static char *allow_origins; | 140 | static char *allow_origins; |
@@ -318,7 +333,8 @@ cleanup_ar (struct AcceptedRequest *ar) | |||
318 | if (GNUNET_YES == ar->socket_with_mhd) | 333 | if (GNUNET_YES == ar->socket_with_mhd) |
319 | { | 334 | { |
320 | GNUNET_NETWORK_socket_free_memory_only_ (ar->sock); | 335 | GNUNET_NETWORK_socket_free_memory_only_ (ar->sock); |
321 | } else { | 336 | } |
337 | else { | ||
322 | GNUNET_NETWORK_socket_close (ar->sock); | 338 | GNUNET_NETWORK_socket_close (ar->sock); |
323 | } | 339 | } |
324 | ar->sock = NULL; | 340 | ar->sock = NULL; |
@@ -463,6 +479,8 @@ create_response (void *cls, | |||
463 | void **con_cls) | 479 | void **con_cls) |
464 | { | 480 | { |
465 | char *origin; | 481 | char *origin; |
482 | char *pw; | ||
483 | char *user; | ||
466 | struct AcceptedRequest *ar; | 484 | struct AcceptedRequest *ar; |
467 | struct GNUNET_HashCode key; | 485 | struct GNUNET_HashCode key; |
468 | struct MhdConnectionHandle *con_handle; | 486 | struct MhdConnectionHandle *con_handle; |
@@ -506,6 +524,29 @@ create_response (void *cls, | |||
506 | MHD_HEADER_KIND, | 524 | MHD_HEADER_KIND, |
507 | (MHD_KeyValueIterator) & header_iterator, | 525 | (MHD_KeyValueIterator) & header_iterator, |
508 | rest_conndata_handle); | 526 | rest_conndata_handle); |
527 | if (GNUNET_YES == basic_auth_enabled) | ||
528 | { | ||
529 | pw = NULL; | ||
530 | user = MHD_basic_auth_get_username_password (con, &pw); | ||
531 | if ((NULL == user) || | ||
532 | (0 != strcmp (user, cuser))) | ||
533 | { | ||
534 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
535 | "Unknown user %s\n", user); | ||
536 | MHD_queue_basic_auth_fail_response (con, "gnunet", failure_response); | ||
537 | return MHD_YES; | ||
538 | } | ||
539 | if ((NULL == pw) || | ||
540 | (0 != strcmp (pw, basic_auth_secret))) | ||
541 | { | ||
542 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
543 | "Password incorrect\n"); | ||
544 | MHD_queue_basic_auth_fail_response (con, "gnunet", failure_response); | ||
545 | GNUNET_free (pw); | ||
546 | return MHD_YES; | ||
547 | } | ||
548 | GNUNET_free (pw); | ||
549 | } | ||
509 | 550 | ||
510 | con_handle->pp = MHD_create_post_processor (con, | 551 | con_handle->pp = MHD_create_post_processor (con, |
511 | 65536, | 552 | 65536, |
@@ -540,7 +581,7 @@ create_response (void *cls, | |||
540 | MHD_suspend_connection (con_handle->con); | 581 | MHD_suspend_connection (con_handle->con); |
541 | return MHD_YES; | 582 | return MHD_YES; |
542 | } | 583 | } |
543 | //MHD_resume_connection (con_handle->con); | 584 | // MHD_resume_connection (con_handle->con); |
544 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 585 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
545 | "Queueing response from plugin with MHD\n"); | 586 | "Queueing response from plugin with MHD\n"); |
546 | // Handle Preflights for extensions | 587 | // Handle Preflights for extensions |
@@ -601,7 +642,7 @@ create_response (void *cls, | |||
601 | MHD_RESULT ret = MHD_queue_response (con, | 642 | MHD_RESULT ret = MHD_queue_response (con, |
602 | con_handle->status, | 643 | con_handle->status, |
603 | con_handle->response); | 644 | con_handle->response); |
604 | //cleanup_handle (con_handle); | 645 | // cleanup_handle (con_handle); |
605 | return ret; | 646 | return ret; |
606 | } | 647 | } |
607 | } | 648 | } |
@@ -1065,6 +1106,8 @@ run (void *cls, | |||
1065 | const struct GNUNET_CONFIGURATION_Handle *c) | 1106 | const struct GNUNET_CONFIGURATION_Handle *c) |
1066 | { | 1107 | { |
1067 | char *addr_str; | 1108 | char *addr_str; |
1109 | char *basic_auth_file; | ||
1110 | uint64_t secret; | ||
1068 | 1111 | ||
1069 | cfg = c; | 1112 | cfg = c; |
1070 | plugins_head = NULL; | 1113 | plugins_head = NULL; |
@@ -1119,6 +1162,62 @@ run (void *cls, | |||
1119 | } | 1162 | } |
1120 | GNUNET_free (addr_str); | 1163 | GNUNET_free (addr_str); |
1121 | 1164 | ||
1165 | basic_auth_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, | ||
1166 | "rest", | ||
1167 | "BASIC_AUTH_ENABLED"); | ||
1168 | if (basic_auth_enabled) | ||
1169 | { | ||
1170 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
1171 | "rest", | ||
1172 | "BASIC_AUTH_SECRET_FILE", | ||
1173 | &basic_auth_file)) | ||
1174 | { | ||
1175 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1176 | "No basic auth secret file location set...\n"); | ||
1177 | GNUNET_SCHEDULER_shutdown (); | ||
1178 | return; | ||
1179 | } | ||
1180 | if (GNUNET_YES != GNUNET_DISK_file_test (basic_auth_file)) | ||
1181 | { | ||
1182 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1183 | "No basic auth secret found... generating\n"); | ||
1184 | secret = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1185 | UINT64_MAX); | ||
1186 | basic_auth_secret = GNUNET_STRINGS_data_to_string_alloc (&secret, | ||
1187 | sizeof(secret)); | ||
1188 | if (GNUNET_OK != | ||
1189 | GNUNET_DISK_fn_write (basic_auth_file, | ||
1190 | basic_auth_secret, | ||
1191 | strlen (basic_auth_secret), | ||
1192 | GNUNET_DISK_PERM_USER_READ | ||
1193 | | GNUNET_DISK_PERM_USER_WRITE)) | ||
1194 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
1195 | "write", | ||
1196 | basic_auth_file); | ||
1197 | } | ||
1198 | else | ||
1199 | { | ||
1200 | char basic_auth_secret_tmp[16]; // Should be more than enough | ||
1201 | memset (basic_auth_secret_tmp, 0, 16); | ||
1202 | if (GNUNET_SYSERR == GNUNET_DISK_fn_read (basic_auth_file, | ||
1203 | basic_auth_secret_tmp, | ||
1204 | sizeof (basic_auth_secret_tmp))) | ||
1205 | { | ||
1206 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1207 | "Unable to read basic auth secret file.\n"); | ||
1208 | GNUNET_SCHEDULER_shutdown (); | ||
1209 | return; | ||
1210 | } | ||
1211 | if (0 != getlogin_r (cuser, LOGIN_NAME_MAX)) | ||
1212 | { | ||
1213 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1214 | "Unable to get user.\n"); | ||
1215 | GNUNET_SCHEDULER_shutdown (); | ||
1216 | return; | ||
1217 | } | ||
1218 | basic_auth_secret = GNUNET_strdup (basic_auth_secret_tmp); | ||
1219 | } | ||
1220 | } | ||
1122 | 1221 | ||
1123 | /* Get CORS data from cfg */ | 1222 | /* Get CORS data from cfg */ |
1124 | echo_origin = | 1223 | echo_origin = |
@@ -1155,7 +1254,7 @@ run (void *cls, | |||
1155 | "No CORS Access-Control-Allow-Headers Header will be sent...\n"); | 1254 | "No CORS Access-Control-Allow-Headers Header will be sent...\n"); |
1156 | } | 1255 | } |
1157 | 1256 | ||
1158 | /* Open listen socket proxy */ | 1257 | /* Open listen socket proxy */ |
1159 | lsock6 = bind_v6 (); | 1258 | lsock6 = bind_v6 (); |
1160 | if (NULL == lsock6) | 1259 | if (NULL == lsock6) |
1161 | { | 1260 | { |
@@ -1203,7 +1302,8 @@ run (void *cls, | |||
1203 | GNUNET_SCHEDULER_shutdown (); | 1302 | GNUNET_SCHEDULER_shutdown (); |
1204 | return; | 1303 | return; |
1205 | } | 1304 | } |
1206 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service listens on port %llu\n", port); | 1305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service listens on port %llu\n", |
1306 | port); | ||
1207 | httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET | 1307 | httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET |
1208 | | MHD_ALLOW_SUSPEND_RESUME, | 1308 | | MHD_ALLOW_SUSPEND_RESUME, |
1209 | 0, | 1309 | 0, |
@@ -1228,7 +1328,7 @@ run (void *cls, | |||
1228 | GNUNET_SCHEDULER_shutdown (); | 1328 | GNUNET_SCHEDULER_shutdown (); |
1229 | return; | 1329 | return; |
1230 | } | 1330 | } |
1231 | /* Load plugins */ | 1331 | /* Load plugins */ |
1232 | GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (), | 1332 | GNUNET_PLUGIN_load_all_in_context (GNUNET_OS_project_data_default (), |
1233 | "libgnunet_plugin_rest", | 1333 | "libgnunet_plugin_rest", |
1234 | (void *) cfg, | 1334 | (void *) cfg, |