From d39156c0e5a6a90fb163cc3fa27d33dbacf6f20e Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 18 May 2025 20:17:12 +0200 Subject: [PATCH] Remove sha1. Server and client prefer sha256 in the authentication protocol since paraslash-0.7.0, while 0.6.x clients and servers only know about sha1. This patch drops the compatibility code which enabled old clients to connect to new servers and vice versa. Now the client code no longer checks whether the sha256 feature is supported, but requests and uses the feature unconditionally. The server still announces the sha256 feature and accepts the corresponding feature request, but uses sha256 unconditionally. With this approach older 0.7.x clients are still compatible to current server versions and current clients can still talk to servers running older 0.7.x versions. --- client_common.c | 41 ++++++++--------------------------------- command.c | 34 ++++++++-------------------------- crypt.h | 39 --------------------------------------- crypt_common.c | 25 ------------------------- gcrypt.c | 16 ---------------- openssl.c | 15 --------------- 6 files changed, 16 insertions(+), 154 deletions(-) diff --git a/client_common.c b/client_common.c index ae5326ec..8542a010 100644 --- a/client_common.c +++ b/client_common.c @@ -253,17 +253,6 @@ static int send_sb_command(struct client_task *ct) return send_sb(ct, 0, command, len, SBD_COMMAND, false); } -/* Find out if the given string is contained in the features vector. */ -static bool has_feature(const char *feature, struct client_task *ct) -{ - if (!ct->features) - return false; - for (int i = 0; ct->features[i]; i++) - if (strcmp(feature, ct->features[i]) == 0) - return true; - return false; -} - /* * This function reads or writes to the socket file descriptor which * corresponds to an established connection between the client and the server. @@ -298,16 +287,12 @@ static int client_post_monitor(struct sched *s, void *context) case CL_RECEIVED_WELCOME: /* send auth command */ { /* - * Use sha256 iff the server announced the feature. After 0.7.0 - * we may request and use the feature unconditionally. After - * 0.8.0 we no longer need to request the feature. + * Request and use the sha256 feature unconditionally. After + * 0.8.0 we no longer need to request it. */ - bool has_sha256; if (!sched_write_ok(ct->scc.fd, s)) return 0; - has_sha256 = has_feature("sha256", ct); - sprintf(buf, AUTH_REQUEST_MSG "%s%s", ct->user, has_sha256? - " sha256" : ""); + sprintf(buf, AUTH_REQUEST_MSG "%s sha256", ct->user); PARA_INFO_LOG("--> %s\n", buf); ret = write_buffer(ct->scc.fd, buf); if (ret < 0) @@ -346,15 +331,9 @@ static int client_post_monitor(struct sched *s, void *context) goto out; } ct->challenge_hash = alloc(HASH2_SIZE); - if (has_feature("sha256", ct)) { - hash2_function((char *)crypt_buf, APC_CHALLENGE_SIZE, - ct->challenge_hash); - hash2_to_asc(ct->challenge_hash, buf); - } else { - hash_function((char *)crypt_buf, APC_CHALLENGE_SIZE, - ct->challenge_hash); - hash_to_asc(ct->challenge_hash, buf); - } + hash2_function((char *)crypt_buf, APC_CHALLENGE_SIZE, + ct->challenge_hash); + hash2_to_asc(ct->challenge_hash, buf); ct->scc.send = sc_new(crypt_buf + APC_CHALLENGE_SIZE, SESSION_KEY_LEN); ct->scc.recv = sc_new(crypt_buf + APC_CHALLENGE_SIZE @@ -365,12 +344,8 @@ static int client_post_monitor(struct sched *s, void *context) return 0; } case CL_RECEIVED_CHALLENGE: - if (has_feature("sha256", ct)) - ret = send_sb(ct, 0, ct->challenge_hash, HASH2_SIZE, - SBD_CHALLENGE_RESPONSE, false); - else - ret = send_sb(ct, 0, ct->challenge_hash, HASH_SIZE, - SBD_CHALLENGE_RESPONSE, false); + ret = send_sb(ct, 0, ct->challenge_hash, HASH2_SIZE, + SBD_CHALLENGE_RESPONSE, false); if (ret != 0) ct->challenge_hash = NULL; if (ret <= 0) diff --git a/command.c b/command.c index af423202..4139c8cb 100644 --- a/command.c +++ b/command.c @@ -791,19 +791,13 @@ static void reset_signals(void) para_sigaction(SIGHUP, SIG_DFL); } -struct connection_features { - bool sha256_requested; /* can be removed after 0.7.0 */ -}; - -static int parse_auth_request(char *buf, int len, const struct user **u, - struct connection_features *cf) +static int parse_auth_request(char *buf, int len, const struct user **u) { int ret; char *p, *username, **features = NULL; size_t auth_rq_len = strlen(AUTH_REQUEST_MSG); *u = NULL; - memset(cf, 0, sizeof(*cf)); if (len < auth_rq_len + 2) return -E_AUTH_REQUEST; if (strncmp(buf, AUTH_REQUEST_MSG, auth_rq_len) != 0) @@ -819,13 +813,10 @@ static int parse_auth_request(char *buf, int len, const struct user **u, create_argv(p, ",", &features); for (i = 0; features[i]; i++) { /* - * ->sha256_requested can go away after 0.7.0 so that * sha256 is used unconditionally, but we need to * accept the feature request until 0.9.0. */ - if (strcmp(features[i], "sha256") == 0) - cf->sha256_requested = true; - else { + if (strcmp(features[i], "sha256")) { ret = -E_BAD_FEATURE; goto out; } @@ -928,7 +919,6 @@ int handle_connect(int fd) size_t numbytes; struct command_context cc_struct = {.u = NULL}, *cc = &cc_struct; struct iovec iov; - struct connection_features cf; cc->scc.fd = fd; reset_signals(); @@ -947,7 +937,7 @@ int handle_connect(int fd) ret = recv_buffer(fd, hsbuf, HANDSHAKE_BUFSIZE); if (ret < 0) goto net_err; - ret = parse_auth_request(hsbuf, ret, &cc->u, &cf); + ret = parse_auth_request(hsbuf, ret, &cc->u); if (ret < 0) goto net_err; if (cc->u) { @@ -987,19 +977,11 @@ int handle_connect(int fd) * of the random data. */ ret = -E_BAD_AUTH; - if (cf.sha256_requested) { - if (numbytes != HASH2_SIZE) - goto net_err; - hash2_function((char *)rand_buf, APC_CHALLENGE_SIZE, challenge_hash); - if (memcmp(challenge_hash, buf, HASH2_SIZE)) - goto net_err; - } else { /* old client. This can be removed after 0.7.0 */ - if (numbytes != HASH_SIZE) - goto net_err; - hash_function((char *)rand_buf, APC_CHALLENGE_SIZE, challenge_hash); - if (memcmp(challenge_hash, buf, HASH_SIZE)) - goto net_err; - } + if (numbytes != HASH2_SIZE) + goto net_err; + hash2_function((char *)rand_buf, APC_CHALLENGE_SIZE, challenge_hash); + if (memcmp(challenge_hash, buf, HASH2_SIZE)) + goto net_err; /* auth successful */ alarm(0); PARA_INFO_LOG("good auth for %s\n", cc->u->name); diff --git a/crypt.h b/crypt.h index 2e094ced..27da9aa3 100644 --- a/crypt.h +++ b/crypt.h @@ -162,45 +162,6 @@ _static_inline_ void sc_trafo(struct iovec *src, struct iovec *dst, */ void sc_free(struct stream_cipher *sc); -/** Size of the hash value in bytes. */ -#define HASH_SIZE 20 - -/** - * Compute the hash of the given input data. - * - * \param data Pointer to the data to compute the hash value from. - * \param len The length of \a data in bytes. - * \param hash Result pointer. - * - * \a hash must point to an area at least \p HASH_SIZE bytes large. - * - * \sa sha(3), openssl(1). - * */ -void hash_function(const char *data, unsigned long len, unsigned char *hash); - -/** - * Convert a hash value to ascii format. - * - * \param hash the hash value. - * \param asc Result pointer. - * - * \a asc must point to an area of at least 2 * \p HASH_SIZE + 1 bytes which - * will be filled by the function with the ascii representation of the hash - * value given by \a hash, and a terminating \p NULL byte. - */ -void hash_to_asc(const unsigned char *hash, char *asc); - -/** - * Compare two hashes. - * - * \param h1 Pointer to the first hash value. - * \param h2 Pointer to the second hash value. - * - * \return 1, -1, or zero, depending on whether \a h1 is greater than, - * less than or equal to h2, respectively. - */ -int hash_compare(const unsigned char *h1, const unsigned char *h2); - /** Size of the hash value in bytes. */ #define HASH2_SIZE 32 diff --git a/crypt_common.c b/crypt_common.c index 59c32ca8..dbd63b50 100644 --- a/crypt_common.c +++ b/crypt_common.c @@ -133,31 +133,6 @@ int check_private_key_file(const char *file) return 1; } -void hash_to_asc(const unsigned char *hash, char *asc) -{ - int i; - const char hexchar[] = "0123456789abcdef"; - - for (i = 0; i < HASH_SIZE; i++) { - asc[2 * i] = hexchar[hash[i] >> 4]; - asc[2 * i + 1] = hexchar[hash[i] & 0xf]; - } - asc[2 * HASH_SIZE] = '\0'; -} - -int hash_compare(const unsigned char *h1, const unsigned char *h2) -{ - int i; - - for (i = 0; i < HASH_SIZE; i++) { - if (h1[i] < h2[i]) - return -1; - if (h1[i] > h2[i]) - return 1; - } - return 0; -} - void hash2_to_asc(const unsigned char *hash, char *asc) { int i; diff --git a/gcrypt.c b/gcrypt.c index ce63c828..5eca71ef 100644 --- a/gcrypt.c +++ b/gcrypt.c @@ -29,22 +29,6 @@ static void dump_buffer(const char *msg, unsigned char *buf, int len) #define dump_buffer(a, b, c) #endif -void hash_function(const char *data, unsigned long len, unsigned char *hash) -{ - gcry_error_t gret; - gcry_md_hd_t handle; - unsigned char *md; - - gret = gcry_md_open(&handle, GCRY_MD_SHA1, 0); - assert(gret == 0); - gcry_md_write(handle, data, (size_t)len); - gcry_md_final(handle); - md = gcry_md_read(handle, GCRY_MD_SHA1); - assert(md); - memcpy(hash, md, HASH_SIZE); - gcry_md_close(handle); -} - void hash2_function(const char *data, unsigned long len, unsigned char *hash) { gcry_error_t gret; diff --git a/openssl.c b/openssl.c index ba07f043..34e42886 100644 --- a/openssl.c +++ b/openssl.c @@ -519,21 +519,6 @@ void sc_crypt(struct stream_cipher *sc, struct iovec *src, struct iovec *dst) return aes_ctr128_crypt(sc->aes, src, dst); } -void hash_function(const char *data, unsigned long len, unsigned char *hash) -{ - int ret; - EVP_MD_CTX *c; - - assert((c = EVP_MD_CTX_new())); - ret = EVP_DigestInit_ex(c, EVP_sha1(), NULL); - assert(ret != 0); - ret = EVP_DigestUpdate(c, data, len); - assert(ret != 0); - ret = EVP_DigestFinal_ex(c, hash, NULL); - assert(ret != 0); - EVP_MD_CTX_free(c); -} - void hash2_function(const char *data, unsigned long len, unsigned char *hash) { int ret; -- 2.39.5