diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-07-14 11:44:01 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-07-14 13:27:45 +0200 |
commit | 2c47a23dec110fb77e1cda36d6bdb83fc4d5e252 (patch) | |
tree | 37e41d6e5c477105788c74ef7243ec83e92c70d4 | |
parent | 2ed04522e24b801251d7fd1768b7fccfd7b8deac (diff) | |
download | libmicrohttpd-2c47a23dec110fb77e1cda36d6bdb83fc4d5e252.tar.gz libmicrohttpd-2c47a23dec110fb77e1cda36d6bdb83fc4d5e252.zip |
integrate TLS PSK patch from Tal Moaz (plus documentation, plus style and bugfixes
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | doc/libmicrohttpd.texi | 10 | ||||
-rw-r--r-- | src/include/microhttpd.h | 38 | ||||
-rw-r--r-- | src/include/microhttpd2.h | 35 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 94 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 15 |
7 files changed, 187 insertions, 10 deletions
@@ -58,6 +58,7 @@ Louis Benoit <louisbenoit@videotron.ca> | |||
58 | Flavio Coelin <flavio.ceolin@intel.com> | 58 | Flavio Coelin <flavio.ceolin@intel.com> |
59 | Silvio Clecio <silvioprog@gmail.com> | 59 | Silvio Clecio <silvioprog@gmail.com> |
60 | Robert D Kosisko <rkocisko@gmail.com> | 60 | Robert D Kosisko <rkocisko@gmail.com> |
61 | Tal Moaz <tmoaz@cisco.com> | ||
61 | 62 | ||
62 | Documentation contributions also came from: | 63 | Documentation contributions also came from: |
63 | Marco Maggi <marco.maggi-ipsu@poste.it> | 64 | Marco Maggi <marco.maggi-ipsu@poste.it> |
@@ -1,3 +1,7 @@ | |||
1 | Sat Jul 14 11:42:15 CEST 2018 | ||
2 | Add MHD_OPTION_GNUTLS_PSK_CRED_HANDLER to allow use of PSK with | ||
3 | TLS connections. -CG/TM | ||
4 | |||
1 | Sat Jul 14 11:03:37 CEST 2018 | 5 | Sat Jul 14 11:03:37 CEST 2018 |
2 | Integrate patch for checking digest authentication based on | 6 | Integrate patch for checking digest authentication based on |
3 | a digest, allowing servers to store passwords only hashed. | 7 | a digest, allowing servers to store passwords only hashed. |
diff --git a/doc/libmicrohttpd.texi b/doc/libmicrohttpd.texi index e4437441..d2886a25 100644 --- a/doc/libmicrohttpd.texi +++ b/doc/libmicrohttpd.texi | |||
@@ -869,6 +869,16 @@ information provided. The callback is expected to access the SNI data | |||
869 | using gnutls_server_name_get(). Using this option requires GnuTLS 3.0 | 869 | using gnutls_server_name_get(). Using this option requires GnuTLS 3.0 |
870 | or higher. | 870 | or higher. |
871 | 871 | ||
872 | @item MHD_OPTION_GNUTLS_PSK_CRED_HANDLER | ||
873 | @cindex SSL | ||
874 | @cindex TLS | ||
875 | @cindex PSK | ||
876 | Use pre-shared key for TLS credentials. | ||
877 | Pass a pointer to callback of type | ||
878 | @code{MHD_PskServerCredentialsCallback} and a closure. | ||
879 | The function will be called to | ||
880 | retrieve the shared key for a given username. | ||
881 | |||
872 | @item MHD_OPTION_DIGEST_AUTH_RANDOM | 882 | @item MHD_OPTION_DIGEST_AUTH_RANDOM |
873 | @cindex digest auth | 883 | @cindex digest auth |
874 | @cindex random | 884 | @cindex random |
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index cdbde609..f43935c7 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -1167,6 +1167,25 @@ typedef void | |||
1167 | 1167 | ||
1168 | 1168 | ||
1169 | /** | 1169 | /** |
1170 | * Function called to lookup the pre shared key (@a psk) for a given | ||
1171 | * HTTP connection based on the @a username. | ||
1172 | * | ||
1173 | * @param cls closure | ||
1174 | * @param connection the HTTPS connection | ||
1175 | * @param username the user name claimed by the other side | ||
1176 | * @param psk[out] to be set to the pre-shared-key; should be allocated with malloc(), | ||
1177 | * will be freed by MHD | ||
1178 | * @param psk_size[out] to be set to the number of bytes in @a psk | ||
1179 | * @return 0 on success, -1 on errors | ||
1180 | */ | ||
1181 | typedef int | ||
1182 | (*MHD_PskServerCredentialsCallback)(void *cls, | ||
1183 | const struct MHD_Connection *connection, | ||
1184 | const char *username, | ||
1185 | void **psk, | ||
1186 | size_t *psk_size); | ||
1187 | |||
1188 | /** | ||
1170 | * @brief MHD options. | 1189 | * @brief MHD options. |
1171 | * | 1190 | * |
1172 | * Passed in the varargs portion of #MHD_start_daemon. | 1191 | * Passed in the varargs portion of #MHD_start_daemon. |
@@ -1489,7 +1508,15 @@ enum MHD_OPTION | |||
1489 | * testing clients against MHD, and 0 in production. This option | 1508 | * testing clients against MHD, and 0 in production. This option |
1490 | * should be followed by an `int` argument. | 1509 | * should be followed by an `int` argument. |
1491 | */ | 1510 | */ |
1492 | MHD_OPTION_STRICT_FOR_CLIENT = 29 | 1511 | MHD_OPTION_STRICT_FOR_CLIENT = 29, |
1512 | |||
1513 | /** | ||
1514 | * This should be a pointer to callback of type | ||
1515 | * gnutls_psk_server_credentials_function that will be given to | ||
1516 | * gnutls_psk_set_server_credentials_function. It is used to | ||
1517 | * retrieve the shared key for a given username. | ||
1518 | */ | ||
1519 | MHD_OPTION_GNUTLS_PSK_CRED_HANDLER = 30 | ||
1493 | }; | 1520 | }; |
1494 | 1521 | ||
1495 | 1522 | ||
@@ -3150,10 +3177,11 @@ MHD_free (void *ptr); | |||
3150 | */ | 3177 | */ |
3151 | _MHD_EXTERN int | 3178 | _MHD_EXTERN int |
3152 | MHD_digest_auth_check (struct MHD_Connection *connection, | 3179 | MHD_digest_auth_check (struct MHD_Connection *connection, |
3153 | const char *realm, | 3180 | const char *realm, |
3154 | const char *username, | 3181 | const char *username, |
3155 | const char *password, | 3182 | const char *password, |
3156 | unsigned int nonce_timeout); | 3183 | unsigned int nonce_timeout); |
3184 | |||
3157 | 3185 | ||
3158 | /** | 3186 | /** |
3159 | * Authenticates the authorization header sent by the client | 3187 | * Authenticates the authorization header sent by the client |
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h index 063b2d98..e8671825 100644 --- a/src/include/microhttpd2.h +++ b/src/include/microhttpd2.h | |||
@@ -2181,6 +2181,41 @@ MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon, | |||
2181 | 2181 | ||
2182 | 2182 | ||
2183 | /** | 2183 | /** |
2184 | * Function called to lookup the pre shared key (@a psk) for a given | ||
2185 | * HTTP connection based on the @a username. | ||
2186 | * | ||
2187 | * @param cls closure | ||
2188 | * @param connection the HTTPS connection | ||
2189 | * @param username the user name claimed by the other side | ||
2190 | * @param psk[out] to be set to the pre-shared-key; should be allocated with malloc(), | ||
2191 | * will be freed by MHD | ||
2192 | * @param psk_size[out] to be set to the number of bytes in @a psk | ||
2193 | * @return 0 on success, -1 on errors | ||
2194 | */ | ||
2195 | typedef int | ||
2196 | (*MHD_PskServerCredentialsCallback)(void *cls, | ||
2197 | const struct MHD_Connection *connection, | ||
2198 | const char *username, | ||
2199 | void **psk, | ||
2200 | size_t *psk_size); | ||
2201 | |||
2202 | |||
2203 | /** | ||
2204 | * Configure PSK to use for the TLS key exchange. | ||
2205 | * | ||
2206 | * @param daemon daemon to configure tls for | ||
2207 | * @param psk_cb function to call to obtain pre-shared key | ||
2208 | * @param psk_cb_cls closure for @a psk_cb | ||
2209 | * @return #MHD_SC_OK upon success; TODO: define failure modes | ||
2210 | */ | ||
2211 | _MHD_EXTERN enum MHD_StatusCode | ||
2212 | MHD_daemon_set_tls_psk_callback (struct MHD_Daemon *daemon, | ||
2213 | MHD_PskServerCredentialsCallback psk_cb, | ||
2214 | void *psk_cb_cls) | ||
2215 | MHD_NONNULL(1); | ||
2216 | |||
2217 | |||
2218 | /** | ||
2184 | * Memory pointer for the certificate (ca.pem) to be used by the | 2219 | * Memory pointer for the certificate (ca.pem) to be used by the |
2185 | * HTTPS daemon for client authentification. | 2220 | * HTTPS daemon for client authentification. |
2186 | * | 2221 | * |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 0b85764b..31ed1574 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -565,7 +565,6 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) | |||
565 | return -1; | 565 | return -1; |
566 | } | 566 | } |
567 | 567 | ||
568 | |||
569 | /** | 568 | /** |
570 | * Initialize security aspects of the HTTPS daemon | 569 | * Initialize security aspects of the HTTPS daemon |
571 | * | 570 | * |
@@ -582,6 +581,11 @@ MHD_TLS_init (struct MHD_Daemon *daemon) | |||
582 | gnutls_certificate_allocate_credentials (&daemon->x509_cred)) | 581 | gnutls_certificate_allocate_credentials (&daemon->x509_cred)) |
583 | return GNUTLS_E_MEMORY_ERROR; | 582 | return GNUTLS_E_MEMORY_ERROR; |
584 | return MHD_init_daemon_certificate (daemon); | 583 | return MHD_init_daemon_certificate (daemon); |
584 | case GNUTLS_CRD_PSK: | ||
585 | if (0 != | ||
586 | gnutls_psk_allocate_server_credentials (&daemon->psk_cred)) | ||
587 | return GNUTLS_E_MEMORY_ERROR; | ||
588 | return 0; | ||
585 | default: | 589 | default: |
586 | #ifdef HAVE_MESSAGES | 590 | #ifdef HAVE_MESSAGES |
587 | MHD_DLOG (daemon, | 591 | MHD_DLOG (daemon, |
@@ -2137,6 +2141,67 @@ MHD_tls_push_func_(gnutls_transport_ptr_t trnsp, | |||
2137 | #endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */ | 2141 | #endif /* MHD_TLSLIB_DONT_SUPPRESS_SIGPIPE */ |
2138 | #endif /* HTTPS_SUPPORT */ | 2142 | #endif /* HTTPS_SUPPORT */ |
2139 | 2143 | ||
2144 | |||
2145 | /** | ||
2146 | * Function called by GNUtls to obtain the PSK for a given session. | ||
2147 | * | ||
2148 | * @param session the session to lookup PSK for | ||
2149 | * @param username username to lookup PSK for | ||
2150 | * @param key[out] where to write PSK | ||
2151 | * @return 0 on success, -1 on error | ||
2152 | */ | ||
2153 | static int | ||
2154 | psk_gnutls_adapter (gnutls_session_t session, | ||
2155 | const char *username, | ||
2156 | gnutls_datum_t *key) | ||
2157 | { | ||
2158 | struct MHD_Connection *connection; | ||
2159 | struct MHD_Daemon *daemon; | ||
2160 | void *app_psk; | ||
2161 | size_t app_psk_size; | ||
2162 | |||
2163 | connection = gnutls_session_get_ptr (session); | ||
2164 | if (NULL == connection) | ||
2165 | { | ||
2166 | #ifdef HAVE_MESSAGES | ||
2167 | MHD_DLOG (daemon, | ||
2168 | _("Internal server error. This should be impossible.\n")); | ||
2169 | #endif | ||
2170 | return -1; | ||
2171 | } | ||
2172 | daemon = connection->daemon; | ||
2173 | if (NULL == daemon->cred_callback) | ||
2174 | { | ||
2175 | #ifdef HAVE_MESSAGES | ||
2176 | MHD_DLOG (daemon, | ||
2177 | _("PSK not supported by this server.\n")); | ||
2178 | #endif | ||
2179 | return -1; | ||
2180 | } | ||
2181 | if (0 != daemon->cred_callback (daemon->cred_callback_cls, | ||
2182 | connection, | ||
2183 | username, | ||
2184 | &app_psk, | ||
2185 | &app_psk_size)) | ||
2186 | return -1; | ||
2187 | if (NULL == (key->data = gnutls_malloc (app_psk_size))) | ||
2188 | { | ||
2189 | #ifdef HAVE_MESSAGES | ||
2190 | MHD_DLOG (daemon, | ||
2191 | _("PSK authentication failed: gnutls_malloc failed to allocate memory\n")); | ||
2192 | #endif | ||
2193 | free (app_psk); | ||
2194 | return -1; | ||
2195 | } | ||
2196 | key->size = app_psk_size; | ||
2197 | memcpy (key->data, | ||
2198 | app_psk, | ||
2199 | app_psk_size); | ||
2200 | free (app_psk); | ||
2201 | return 0; | ||
2202 | } | ||
2203 | |||
2204 | |||
2140 | /** | 2205 | /** |
2141 | * Add another client connection to the set of connections | 2206 | * Add another client connection to the set of connections |
2142 | * managed by MHD. This API is usually not needed (since | 2207 | * managed by MHD. This API is usually not needed (since |
@@ -2372,6 +2437,12 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
2372 | gnutls_credentials_set (connection->tls_session, | 2437 | gnutls_credentials_set (connection->tls_session, |
2373 | GNUTLS_CRD_CERTIFICATE, | 2438 | GNUTLS_CRD_CERTIFICATE, |
2374 | daemon->x509_cred); | 2439 | daemon->x509_cred); |
2440 | case GNUTLS_CRD_PSK: | ||
2441 | gnutls_credentials_set (connection->tls_session, | ||
2442 | GNUTLS_CRD_PSK, | ||
2443 | daemon->psk_cred); | ||
2444 | gnutls_psk_set_server_credentials_function (daemon->psk_cred, | ||
2445 | &psk_gnutls_adapter); | ||
2375 | break; | 2446 | break; |
2376 | default: | 2447 | default: |
2377 | #ifdef HAVE_MESSAGES | 2448 | #ifdef HAVE_MESSAGES |
@@ -2392,12 +2463,15 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
2392 | return MHD_NO; | 2463 | return MHD_NO; |
2393 | } | 2464 | } |
2394 | #if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64) | 2465 | #if (GNUTLS_VERSION_NUMBER+0 >= 0x030109) && !defined(_WIN64) |
2395 | gnutls_transport_set_int (connection->tls_session, (int)(client_socket)); | 2466 | gnutls_transport_set_int (connection->tls_session, |
2467 | (int)(client_socket)); | ||
2396 | #else /* GnuTLS before 3.1.9 or Win x64 */ | 2468 | #else /* GnuTLS before 3.1.9 or Win x64 */ |
2397 | gnutls_transport_set_ptr (connection->tls_session, (gnutls_transport_ptr_t)(intptr_t)(client_socket)); | 2469 | gnutls_transport_set_ptr (connection->tls_session, |
2470 | (gnutls_transport_ptr_t)(intptr_t)(client_socket)); | ||
2398 | #endif /* GnuTLS before 3.1.9 */ | 2471 | #endif /* GnuTLS before 3.1.9 */ |
2399 | #ifdef MHD_TLSLIB_NEED_PUSH_FUNC | 2472 | #ifdef MHD_TLSLIB_NEED_PUSH_FUNC |
2400 | gnutls_transport_set_push_function (connection->tls_session, MHD_tls_push_func_); | 2473 | gnutls_transport_set_push_function (connection->tls_session, |
2474 | MHD_tls_push_func_); | ||
2401 | #endif /* MHD_TLSLIB_NEED_PUSH_FUNC */ | 2475 | #endif /* MHD_TLSLIB_NEED_PUSH_FUNC */ |
2402 | if (daemon->https_mem_trust) | 2476 | if (daemon->https_mem_trust) |
2403 | gnutls_certificate_server_set_request (connection->tls_session, | 2477 | gnutls_certificate_server_set_request (connection->tls_session, |
@@ -2407,7 +2481,8 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
2407 | goto cleanup; | 2481 | goto cleanup; |
2408 | #endif /* ! HTTPS_SUPPORT */ | 2482 | #endif /* ! HTTPS_SUPPORT */ |
2409 | } | 2483 | } |
2410 | 2484 | gnutls_session_set_ptr (connection->tls_session, | |
2485 | connection); | ||
2411 | 2486 | ||
2412 | MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); | 2487 | MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); |
2413 | /* Firm check under lock. */ | 2488 | /* Firm check under lock. */ |
@@ -5070,6 +5145,7 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
5070 | case MHD_OPTION_URI_LOG_CALLBACK: | 5145 | case MHD_OPTION_URI_LOG_CALLBACK: |
5071 | case MHD_OPTION_EXTERNAL_LOGGER: | 5146 | case MHD_OPTION_EXTERNAL_LOGGER: |
5072 | case MHD_OPTION_UNESCAPE_CALLBACK: | 5147 | case MHD_OPTION_UNESCAPE_CALLBACK: |
5148 | case MHD_OPTION_GNUTLS_PSK_CRED_HANDLER: | ||
5073 | if (MHD_YES != parse_options (daemon, | 5149 | if (MHD_YES != parse_options (daemon, |
5074 | servaddr, | 5150 | servaddr, |
5075 | opt, | 5151 | opt, |
@@ -5100,6 +5176,12 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
5100 | daemon->unescape_callback_cls = va_arg (ap, | 5176 | daemon->unescape_callback_cls = va_arg (ap, |
5101 | void *); | 5177 | void *); |
5102 | break; | 5178 | break; |
5179 | case MHD_OPTION_GNUTLS_PSK_CRED_HANDLER: | ||
5180 | daemon->cred_callback = va_arg (ap, | ||
5181 | MHD_PskServerCredentialsCallback); | ||
5182 | daemon->cred_callback_cls = va_arg (ap, | ||
5183 | void *); | ||
5184 | break; | ||
5103 | default: | 5185 | default: |
5104 | #ifdef HAVE_MESSAGES | 5186 | #ifdef HAVE_MESSAGES |
5105 | if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) && | 5187 | if ( ( (opt >= MHD_OPTION_HTTPS_MEM_KEY) && |
@@ -6419,6 +6501,8 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
6419 | gnutls_priority_deinit (daemon->priority_cache); | 6501 | gnutls_priority_deinit (daemon->priority_cache); |
6420 | if (daemon->x509_cred) | 6502 | if (daemon->x509_cred) |
6421 | gnutls_certificate_free_credentials (daemon->x509_cred); | 6503 | gnutls_certificate_free_credentials (daemon->x509_cred); |
6504 | if (daemon->psk_cred) | ||
6505 | gnutls_psk_free_server_credentials (daemon->psk_cred); | ||
6422 | } | 6506 | } |
6423 | #endif /* HTTPS_SUPPORT */ | 6507 | #endif /* HTTPS_SUPPORT */ |
6424 | 6508 | ||
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index 01f2dbea..d1835ea0 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1611,12 +1611,27 @@ struct MHD_Daemon | |||
1611 | */ | 1611 | */ |
1612 | gnutls_dh_params_t dh_params; | 1612 | gnutls_dh_params_t dh_params; |
1613 | 1613 | ||
1614 | /** | ||
1615 | * Server PSK credentials | ||
1616 | */ | ||
1617 | gnutls_psk_server_credentials_t psk_cred; | ||
1618 | |||
1614 | #if GNUTLS_VERSION_MAJOR >= 3 | 1619 | #if GNUTLS_VERSION_MAJOR >= 3 |
1615 | /** | 1620 | /** |
1616 | * Function that can be used to obtain the certificate. Needed | 1621 | * Function that can be used to obtain the certificate. Needed |
1617 | * for SNI support. See #MHD_OPTION_HTTPS_CERT_CALLBACK. | 1622 | * for SNI support. See #MHD_OPTION_HTTPS_CERT_CALLBACK. |
1618 | */ | 1623 | */ |
1619 | gnutls_certificate_retrieve_function2 *cert_callback; | 1624 | gnutls_certificate_retrieve_function2 *cert_callback; |
1625 | |||
1626 | /** | ||
1627 | * Function that can be used to obtain the shared key. | ||
1628 | */ | ||
1629 | MHD_PskServerCredentialsCallback cred_callback; | ||
1630 | |||
1631 | /** | ||
1632 | * Closure for @e cred_callback. | ||
1633 | */ | ||
1634 | void *cred_callback_cls; | ||
1620 | #endif | 1635 | #endif |
1621 | 1636 | ||
1622 | /** | 1637 | /** |