From ee1fbffa1c42f7ac3fc897e73e90c525037dd915 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 16 Jul 2020 17:40:14 +0200 Subject: support context-wide client authentication --- contrib/build-common | 2 +- src/curl/curl.c | 114 ++++++++++++++++++++++++++++++++++++++++++ src/gnsrecord/gnsrecord.c | 8 +-- src/include/gnunet_curl_lib.h | 36 +++++++++++++ src/util/crypto_kdf.c | 4 +- 5 files changed, 157 insertions(+), 7 deletions(-) diff --git a/contrib/build-common b/contrib/build-common index 1915a74bb..d81bbfabc 160000 --- a/contrib/build-common +++ b/contrib/build-common @@ -1 +1 @@ -Subproject commit 1915a74bbb4cd2ae9bc541a382dfebc37064a2fd +Subproject commit d81bbfabc2538932f631d3946bd6a9b95182b4f2 diff --git a/src/curl/curl.c b/src/curl/curl.c index a63a10f3b..f43670944 100644 --- a/src/curl/curl.c +++ b/src/curl/curl.c @@ -170,9 +170,92 @@ struct GNUNET_CURL_Context * Closure for @e cb. */ void *cb_cls; + + /** + * USERNAME:PASSWORD to use for client-authentication + * with all requests of this context, or NULL. + */ + char *userpass; + + /** + * Type of the TLS client certificate used, or NULL. + */ + char *certtype; + + /** + * File with the TLS client certificate, or NULL. + */ + char *certfile; + + /** + * File with the private key to authenticate the + * TLS client, or NULL. + */ + char *keyfile; + + /** + * Passphrase to decrypt @e keyfile, or NULL. + */ + char *keypass; + }; +/** + * Force use of the provided username and password + * for client authentication for all operations performed + * with @a ctx. + * + * @param ctx context to set authentication data for + * @param userpass string with "$USERNAME:$PASSWORD" + */ +void +GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx, + const char *userpass) +{ + GNUNET_free (ctx->userpass); + if (NULL != userpass) + ctx->userpass = GNUNET_strdup (userpass); +} + + +/** + * Force use of the provided TLS client certificate + * for client authentication for all operations performed + * with @a ctx. + * + * Note that if the provided information is incorrect, + * the earliest operation that could fail is + * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()! + * + * @param ctx context to set authentication data for + * @param certtype type of the certificate + * @param certfile file with the certificate + * @param keyfile file with the private key + * @param keypass passphrase to decrypt @a keyfile (or NULL) + */ +void +GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx, + const char *certtype, + const char *certfile, + const char *keyfile, + const char *keypass) +{ + GNUNET_free (ctx->certtype); + GNUNET_free (ctx->certfile); + GNUNET_free (ctx->keyfile); + GNUNET_free (ctx->keypass); + if (NULL != certtype) + ctx->certtype = GNUNET_strdup (certtype); + if (NULL != certfile) + ctx->certfile = GNUNET_strdup (certfile); + if (NULL != keyfile) + ctx->certtype = GNUNET_strdup (keyfile); + if (NULL != keypass) + ctx->certtype = GNUNET_strdup (keypass); +} + + /** * Initialise this library. This function should be called before using any of * the following functions. @@ -457,6 +540,32 @@ GNUNET_CURL_job_add2 (struct GNUNET_CURL_Context *ctx, struct curl_slist *all_headers; GNUNET_assert (NULL != jcc); + if ( (NULL != ctx->userpass) && + (0 != curl_easy_setopt (eh, + CURLOPT_USERPWD, + ctx->userpass)) ) + return NULL; + if ( (NULL != ctx->certfile) && + (0 != curl_easy_setopt (eh, + CURLOPT_SSLCERT, + ctx->certfile)) ) + return NULL; + if ( (NULL != ctx->certtype) && + (0 != curl_easy_setopt (eh, + CURLOPT_SSLCERTTYPE, + ctx->certtype)) ) + return NULL; + if ( (NULL != ctx->keyfile) && + (0 != curl_easy_setopt (eh, + CURLOPT_SSLKEY, + ctx->keyfile)) ) + return NULL; + if ( (NULL != ctx->keypass) && + (0 != curl_easy_setopt (eh, + CURLOPT_KEYPASSWD, + ctx->keypass)) ) + return NULL; + all_headers = setup_job_headers (ctx, job_headers); if (NULL == (job = setup_job (eh, @@ -899,6 +1008,11 @@ GNUNET_CURL_fini (struct GNUNET_CURL_Context *ctx) curl_share_cleanup (ctx->share); curl_multi_cleanup (ctx->multi); curl_slist_free_all (ctx->common_headers); + GNUNET_free (ctx->userpass); + GNUNET_free (ctx->certtype); + GNUNET_free (ctx->certfile); + GNUNET_free (ctx->keyfile); + GNUNET_free (ctx->keypass); GNUNET_free (ctx); } diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index a59997934..3cbf5fc8d 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -102,8 +102,8 @@ init () if (1 == once) return; once = 1; - struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); - struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default (); + const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); + const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default (); if (pd != dpd) GNUNET_OS_init(dpd); @@ -121,8 +121,8 @@ void __attribute__ ((destructor)) GNSRECORD_fini () { struct Plugin *plugin; - struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); - struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default (); + const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get (); + const struct GNUNET_OS_ProjectData *dpd = GNUNET_OS_project_data_default (); if (pd != dpd) GNUNET_OS_init(dpd); diff --git a/src/include/gnunet_curl_lib.h b/src/include/gnunet_curl_lib.h index 875cfa3bd..0bb337ee7 100644 --- a/src/include/gnunet_curl_lib.h +++ b/src/include/gnunet_curl_lib.h @@ -244,6 +244,42 @@ GNUNET_CURL_job_add (struct GNUNET_CURL_Context *ctx, void *jcc_cls); +/** + * Force use of the provided username and password + * for client authentication for all operations performed + * with @a ctx. + * + * @param ctx context to set authentication data for + * @param userpass string with "$USERNAME:$PASSWORD" + */ +void +GNUNET_CURL_set_userpass (struct GNUNET_CURL_Context *ctx, + const char *userpass); + + +/** + * Force use of the provided TLS client certificate + * for client authentication for all operations performed + * with @a ctx. + * + * Note that if the provided information is incorrect, + * the earliest operation that could fail is + * #GNUNET_CURL_job_add() or #GNUNET_CURL_job_add2()! + * + * @param ctx context to set authentication data for + * @param certtype type of the certificate + * @param certfile file with the certificate + * @param keyfile file with the private key + * @param keypass passphrase to decrypt @a keyfile (or NULL) + */ +void +GNUNET_CURL_set_tlscert (struct GNUNET_CURL_Context *ctx, + const char *certtype, + const char *certfile, + const char *keyfile, + const char *keypass); + + /** * Schedule a CURL request to be executed and call the given @a jcc * upon its completion. Note that the context will make use of the diff --git a/src/util/crypto_kdf.c b/src/util/crypto_kdf.c index 1b3bd686f..4f3830308 100644 --- a/src/util/crypto_kdf.c +++ b/src/util/crypto_kdf.c @@ -62,7 +62,8 @@ GNUNET_CRYPTO_kdf_v (void *result, * hash function." * * http://eprint.iacr.org/2010/264 - */return GNUNET_CRYPTO_hkdf_v (result, + */// + return GNUNET_CRYPTO_hkdf_v (result, out_len, GCRY_MD_SHA512, GCRY_MD_SHA256, @@ -142,7 +143,6 @@ GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r, { /* Ain't clear if n is always divisible by 8 */ uint8_t buf[ (nbits - 1) / 8 + 1 ]; - uint16_t ctr_nbo = htons (ctr); rc = GNUNET_CRYPTO_kdf (buf, -- cgit v1.2.3