From 6bf86c7504c60cb089eca80ca2a5a0940d057b12 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 16 Sep 2025 09:49:54 +0200 Subject: [PATCH] krb5: add buffer size precaution in Curl_sec_read_msg To make sure the copy never overwrites the buffer, as this function decodes "in place". Inspired-by: Ryan Lefkowitz --- lib/curl_krb5.h | 3 ++- lib/ftp.c | 7 ++++--- lib/krb5.c | 24 +++++++++++++----------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/curl_krb5.h b/lib/curl_krb5.h index 574340fd3c..4e2fbd1093 100644 --- a/lib/curl_krb5.h +++ b/lib/curl_krb5.h @@ -42,7 +42,8 @@ struct Curl_sec_client_mech { #if defined(HAVE_GSSAPI) && !defined(CURL_DISABLE_FTP) void Curl_sec_conn_init(struct connectdata *); void Curl_sec_conn_destroy(struct connectdata *); -int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *, +int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, + char *buffer, const size_t buflen, enum protection_level); CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *); int Curl_sec_request_prot(struct connectdata *conn, const char *level); diff --git a/lib/ftp.c b/lib/ftp.c index 6c710dceb9..070c4bfc8f 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -582,17 +582,18 @@ static CURLcode ftp_readresp(struct Curl_easy *data, { struct connectdata *conn = data->conn; char * const buf = curlx_dyn_ptr(&ftpc->pp.recvbuf); + size_t buflen = curlx_dyn_len(&ftpc->pp.recvbuf); /* handle the security-oriented responses 6xx ***/ switch(code) { case 631: - code = Curl_sec_read_msg(data, conn, buf, PROT_SAFE); + code = Curl_sec_read_msg(data, conn, buf, buflen, PROT_SAFE); break; case 632: - code = Curl_sec_read_msg(data, conn, buf, PROT_PRIVATE); + code = Curl_sec_read_msg(data, conn, buf, buflen, PROT_PRIVATE); break; case 633: - code = Curl_sec_read_msg(data, conn, buf, PROT_CONFIDENTIAL); + code = Curl_sec_read_msg(data, conn, buf, buflen, PROT_CONFIDENTIAL); break; default: /* normal ftp stuff we pass through! */ diff --git a/lib/krb5.c b/lib/krb5.c index b041d2f227..b3105f6757 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -713,7 +713,8 @@ static CURLcode sec_send(struct Curl_easy *data, int sockindex, } int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, - char *buffer, enum protection_level level) + char *buffer, const size_t buflen, + enum protection_level level) { /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an int */ @@ -723,8 +724,6 @@ int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, size_t decoded_sz = 0; CURLcode error; - (void)data; - if(!conn->mech) /* not initialized, return error */ return -1; @@ -748,22 +747,25 @@ int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, return -1; } - { - buf[decoded_len] = '\n'; - Curl_debug(data, CURLINFO_HEADER_IN, buf, decoded_len + 1); - } - + buf[decoded_len] = '\n'; + Curl_debug(data, CURLINFO_HEADER_IN, buf, decoded_len + 1); buf[decoded_len] = '\0'; + if(decoded_len <= 3) /* suspiciously short */ - return 0; + return -1; if(buf[3] != '-') ret_code = atoi(buf); if(buf[decoded_len - 1] == '\n') - buf[decoded_len - 1] = '\0'; - strcpy(buffer, buf); + buf[--decoded_len] = '\0'; + + if((size_t)decoded_len > buflen) + /* too big */ + ret_code = -1; + else + memcpy(buffer, buf, decoded_len + 1); free(buf); return ret_code; }