From 380c16a82b96dfde2700c60938a2ffc021b33bf2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 9 Apr 2024 14:52:38 +0200 Subject: [PATCH 1/3] configure: add --with-libgcrypt option libgcrypt is a relatively large dependency that is used only for the sake of computing MD5 in the CHAP authentication protocol. Allow distributions to disable it forcibly and rely on the embedded MD5 implementation. Signed-off-by: Paolo Bonzini --- configure.ac | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index c81b916..b7d214f 100644 --- a/configure.ac +++ b/configure.ac @@ -78,8 +78,21 @@ AM_CONDITIONAL([BUILD_EXAMPLES], AC_CONFIG_HEADERS([config.h]) -AC_CHECK_LIB([gcrypt], [gcry_control]) -AM_CONDITIONAL([HAVE_LIBGCRYPT], [test $ac_cv_lib_gcrypt_gcry_control = yes]) +AC_ARG_WITH([libgcrypt], + [AS_HELP_STRING([--with-libgcrypt], + [Use libgcrypt to compute MD5])], + [WITH_LIBGCRYPT=$withval], + [WITH_LIBGCRYPT=auto]) +if test "$WITH_LIBGCRYPT" != no; then + AC_CHECK_LIB([gcrypt], [gcry_control]) + if test "$WITH_LIBGCRYPT" = yes && test "$ac_cv_lib_gcrypt_gcry_control" != yes; then + AC_MSG_ERROR([libgcrypt not found]) + fi + WITH_LIBGCRYPT=$ac_cv_lib_gcrypt_gcry_control +fi + +AM_CONDITIONAL([HAVE_LIBGCRYPT], + [expr "$WITH_LIBGCRYPT" : yes > /dev/null 2>&1]) # For MinGW. AC_CHECK_LIB([ws2_32], [gethostbyname]) From e07472a3370edf59e7293f7bd5b273187b3f84d5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 9 Apr 2024 15:24:57 +0200 Subject: [PATCH 2/3] login: do not try to "emulate" the libgcrypt API Implement a more generic wrapper API for message digests, so that it is easier to also include gnutls as an option. Signed-off-by: Paolo Bonzini --- lib/login.c | 64 +++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/lib/login.c b/lib/login.c index 8251d16..03c4a7d 100644 --- a/lib/login.c +++ b/lib/login.c @@ -681,41 +681,48 @@ i2h(int i) return i + '0'; } -#ifndef HAVE_LIBGCRYPT -typedef struct MD5Context *gcry_md_hd_t; -#define gcry_md_write MD5Update -#define GCRY_MD_MD5 1 +#ifdef HAVE_LIBGCRYPT +typedef gcry_md_hd_t md5_context_t; +#define md5_open(hd) gcry_md_open(hd, GCRY_MD_MD5, 0) +#define md5_write gcry_md_write +#define md5_close gcry_md_close -static void gcry_md_open(gcry_md_hd_t *hd, int algo, unsigned int flags) +static void md5_read(md5_context_t h, uint8_t *result) +{ + memcpy(result, gcry_md_read(h, 0), 16); +} +#else +typedef struct MD5Context *md5_context_t; +#define md5_write MD5Update + +static void md5_open(md5_context_t *hd) { - assert(algo == GCRY_MD_MD5 && flags == 0); *hd = malloc(sizeof(struct MD5Context)); if (*hd) { MD5Init(*hd); } } -static void gcry_md_putc(gcry_md_hd_t h, unsigned char c) -{ - MD5Update(h, &c, 1); -} - -static char *gcry_md_read(gcry_md_hd_t h, int algo) +static void md5_read(md5_context_t h, uint8_t *result) { unsigned char digest[16]; - assert(algo == 0 || algo == GCRY_MD_MD5); MD5Final(digest, h); - return memcpy(h->buf, digest, sizeof(digest)); + memcpy(result, digest, sizeof(digest)); } -static void gcry_md_close(gcry_md_hd_t h) +static void md5_close(md5_context_t h) { memset(h, 0, sizeof(*h)); free(h); } #endif +static inline void md5_putc(md5_context_t h, unsigned char c) +{ + md5_write(h, &c, 1); +} + /* size of the challenge used for bidirectional chap */ #define TARGET_CHAP_C_SIZE 32 @@ -726,7 +733,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu char * strp; unsigned char c, cc[2]; unsigned char digest[CHAP_R_SIZE]; - gcry_md_hd_t ctx; + md5_context_t ctx; int i; if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG @@ -739,22 +746,22 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu return -1; } - gcry_md_open(&ctx, GCRY_MD_MD5, 0); + md5_open(&ctx); if (ctx == NULL) { iscsi_set_error(iscsi, "Cannot create MD5 algorithm"); return -1; } - gcry_md_putc(ctx, iscsi->chap_i); - gcry_md_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd)); + md5_putc(ctx, iscsi->chap_i); + md5_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd)); strp = iscsi->chap_c; while (*strp != 0) { c = (h2i(strp[0]) << 4) | h2i(strp[1]); strp += 2; - gcry_md_putc(ctx, c); + md5_putc(ctx, c); } - memcpy(digest, gcry_md_read(ctx, 0), sizeof(digest)); - gcry_md_close(ctx); + md5_read(ctx, digest); + md5_close(ctx); strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE); if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)) @@ -822,20 +829,19 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu return -1; } - gcry_md_open(&ctx, GCRY_MD_MD5, 0); + md5_open(&ctx); if (ctx == NULL) { iscsi_set_error(iscsi, "Cannot create MD5 algorithm"); return -1; } - gcry_md_putc(ctx, iscsi->target_chap_i); - gcry_md_write(ctx, (unsigned char *)iscsi->target_passwd, + md5_putc(ctx, iscsi->target_chap_i); + md5_write(ctx, (unsigned char *)iscsi->target_passwd, strlen(iscsi->target_passwd)); - gcry_md_write(ctx, (unsigned char *)target_chap_c, + md5_write(ctx, (unsigned char *)target_chap_c, TARGET_CHAP_C_SIZE); - memcpy(iscsi->target_chap_r, gcry_md_read(ctx, 0), - sizeof(iscsi->target_chap_r)); - gcry_md_close(ctx); + md5_read(ctx, iscsi->target_chap_r); + md5_close(ctx); } return 0; From 35fec3ea0ef5c3c068f698e1b2a94695522f8e47 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 9 Apr 2024 15:43:02 +0200 Subject: [PATCH 3/3] login: add support for gnutls Signed-off-by: Paolo Bonzini --- configure.ac | 26 ++++++++++++++++++++++++-- lib/Makefile.am | 2 +- lib/login.c | 19 ++++++++++++++++++- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index b7d214f..13ae3bb 100644 --- a/configure.ac +++ b/configure.ac @@ -78,11 +78,29 @@ AM_CONDITIONAL([BUILD_EXAMPLES], AC_CONFIG_HEADERS([config.h]) +AC_ARG_WITH([gnutls], + [AS_HELP_STRING([--with-gnutls], + [Use gnutls to compute MD5])], + [WITH_GNUTLS=$withval], + [WITH_GNUTLS=auto]) + AC_ARG_WITH([libgcrypt], [AS_HELP_STRING([--with-libgcrypt], [Use libgcrypt to compute MD5])], [WITH_LIBGCRYPT=$withval], [WITH_LIBGCRYPT=auto]) + +if test "$WITH_GNUTLS" != no; then + AC_CHECK_LIB([gnutls], [gnutls_hash_init]) + if test "$WITH_GNUTLS" = yes && test "$ac_cv_lib_gnutls_gnutls_hash_init" != yes; then + AC_MSG_ERROR([gnutls not found]) + fi + WITH_GNUTLS=$ac_cv_lib_gnutls_gnutls_hash_init +fi +if test "$WITH_GNUTLS" = yes; then + WITH_LIBGCRYPT=no +fi + if test "$WITH_LIBGCRYPT" != no; then AC_CHECK_LIB([gcrypt], [gcry_control]) if test "$WITH_LIBGCRYPT" = yes && test "$ac_cv_lib_gcrypt_gcry_control" != yes; then @@ -91,8 +109,12 @@ if test "$WITH_LIBGCRYPT" != no; then WITH_LIBGCRYPT=$ac_cv_lib_gcrypt_gcry_control fi -AM_CONDITIONAL([HAVE_LIBGCRYPT], - [expr "$WITH_LIBGCRYPT" : yes > /dev/null 2>&1]) +NEED_MD5=no +if test "$WITH_GNUTLS" = no && test "$WITH_LIBGCRYPT" = no; then + NEED_MD5=yes +fi +AM_CONDITIONAL([NEED_MD5], + [expr "$NEED_MD5" : yes > /dev/null 2>&1]) # For MinGW. AC_CHECK_LIB([ws2_32], [gethostbyname]) diff --git a/lib/Makefile.am b/lib/Makefile.am index 4cc03a9..ba6aaee 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -12,7 +12,7 @@ if TARGET_OS_IS_WIN32 libiscsipriv_la_SOURCES += ../win32/win32_compat.c endif -if !HAVE_LIBGCRYPT +if NEED_MD5 libiscsipriv_la_SOURCES += md5.c endif diff --git a/lib/login.c b/lib/login.c index 03c4a7d..5177201 100644 --- a/lib/login.c +++ b/lib/login.c @@ -44,6 +44,10 @@ #include "iscsi-private.h" #include "scsi-lowlevel.h" #include "md5.h" + +#ifdef HAVE_LIBGNUTLS +#include +#endif #ifdef HAVE_LIBGCRYPT #include #endif @@ -681,7 +685,20 @@ i2h(int i) return i + '0'; } -#ifdef HAVE_LIBGCRYPT +#if defined HAVE_LIBGNUTLS +#define md5_context_t gnutls_hash_hd_t +#define md5_open(hd) gnutls_hash_init(hd, GNUTLS_DIG_MD5) +#define md5_write gnutls_hash +#define md5_read gnutls_hash_output + +static void md5_close(md5_context_t h) +{ + unsigned char digest[16]; + + gnutls_hash_deinit(h, digest); +} + +#elif defined HAVE_LIBGCRYPT typedef gcry_md_hd_t md5_context_t; #define md5_open(hd) gcry_md_open(hd, GCRY_MD_MD5, 0) #define md5_write gcry_md_write