1
1

fix: Fix off-by-one memory overwrite crash and memory leaks (#887)

The base64 decode will crash on musl c-library builds for OpenWRT
due to the write of the '\0' past the end of the allocated buffer.
Fix other various memory leaks on the authentication code paths.
Fix some memory-free library calls into OpenSSL.

Based heavily on PR #881 originally submitted by @acmay, 
with comments from @ralcini.
Этот коммит содержится в:
Bruce A. Mah 2019-06-18 15:11:32 -07:00 коммит произвёл GitHub
родитель 098dd3cc1b
Коммит c4bd56f373
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 68 добавлений и 21 удалений

Просмотреть файл

@ -1257,8 +1257,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
char *client_password = NULL; char *client_password = NULL;
size_t s; size_t s;
if ((client_password = getenv("IPERF3_PASSWORD")) == NULL && /* Need to copy env var, so we can do a common free */
iperf_getpass(&client_password, &s, stdin) < 0){ if ((client_password = getenv("IPERF3_PASSWORD")) != NULL)
client_password = strdup(client_password);
else if (iperf_getpass(&client_password, &s, stdin) < 0){
return -1; return -1;
} }
@ -1275,6 +1277,8 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->settings->client_username = client_username; test->settings->client_username = client_username;
test->settings->client_password = client_password; test->settings->client_password = client_password;
test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key); test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key);
free(client_rsa_public_key);
client_rsa_public_key = NULL;
} }
if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){ if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){
@ -1284,11 +1288,14 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
!(server_rsa_private_key && test->server_authorized_users)) { !(server_rsa_private_key && test->server_authorized_users)) {
i_errno = IESETSERVERAUTH; i_errno = IESETSERVERAUTH;
return -1; return -1;
} else if (test->role == 's' && server_rsa_private_key && test_load_private_key_from_file(server_rsa_private_key) < 0){ } else if (test->role == 's' && server_rsa_private_key) {
test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key);
if (test->server_rsa_private_key == NULL){
i_errno = IESETSERVERAUTH; i_errno = IESETSERVERAUTH;
return -1; return -1;
} else { }
test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key); free(server_rsa_private_key);
server_rsa_private_key = NULL;
} }
#endif //HAVE_SSL #endif //HAVE_SSL
@ -1556,9 +1563,13 @@ int test_is_authorized(struct iperf_test *test){
int ret = check_authentication(username, password, ts, test->server_authorized_users); int ret = check_authentication(username, password, ts, test->server_authorized_users);
if (ret == 0){ if (ret == 0){
iperf_printf(test, report_authetication_successed, username, ts); iperf_printf(test, report_authetication_successed, username, ts);
free(username);
free(password);
return 0; return 0;
} else { } else {
iperf_printf(test, report_authetication_failed, username, ts); iperf_printf(test, report_authetication_failed, username, ts);
free(username);
free(password);
return -1; return -1;
} }
} }
@ -1754,7 +1765,10 @@ get_parameters(struct iperf_test *test)
r = -1; r = -1;
} else { } else {
if (test->debug) { if (test->debug) {
printf("get_parameters:\n%s\n", cJSON_Print(j)); char *str;
str = cJSON_Print(j);
printf("get_parameters:\n%s\n", str );
free(str);
} }
if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL) if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
@ -1919,7 +1933,9 @@ send_results(struct iperf_test *test)
} }
} }
if (r == 0 && test->debug) { if (r == 0 && test->debug) {
printf("send_results\n%s\n", cJSON_Print(j)); char *str = cJSON_Print(j);
printf("send_results\n%s\n", str);
free(str);
} }
if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) { if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
i_errno = IESENDRESULTS; i_errno = IESENDRESULTS;
@ -1975,7 +1991,9 @@ get_results(struct iperf_test *test)
r = -1; r = -1;
} else { } else {
if (test->debug) { if (test->debug) {
printf("get_results\n%s\n", cJSON_Print(j)); char *str = cJSON_Print(j);
printf("get_results\n%s\n", str);
free(str);
} }
test->remote_cpu_util[0] = j_cpu_util_total->valuedouble; test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
@ -2392,7 +2410,6 @@ iperf_free_test(struct iperf_test *test)
SLIST_REMOVE_HEAD(&test->streams, streams); SLIST_REMOVE_HEAD(&test->streams, streams);
iperf_free_stream(sp); iperf_free_stream(sp);
} }
if (test->server_hostname) if (test->server_hostname)
free(test->server_hostname); free(test->server_hostname);
if (test->tmp_template) if (test->tmp_template)
@ -2411,6 +2428,26 @@ iperf_free_test(struct iperf_test *test)
free(xbe); free(xbe);
} }
} }
#if defined(HAVE_SSL)
if (test->server_rsa_private_key)
EVP_PKEY_free(test->server_rsa_private_key);
test->server_rsa_private_key = NULL;
free(test->settings->authtoken);
test->settings->authtoken = NULL;
free(test->settings->client_username);
test->settings->client_username = NULL;
free(test->settings->client_password);
test->settings->client_password = NULL;
if (test->settings->client_rsa_pubkey)
EVP_PKEY_free(test->settings->client_rsa_pubkey);
test->settings->client_rsa_pubkey = NULL;
#endif /* HAVE_SSL */
if (test->settings) if (test->settings)
free(test->settings); free(test->settings);
if (test->title) if (test->title)
@ -2509,6 +2546,9 @@ iperf_reset_test(struct iperf_test *test)
SLIST_INIT(&test->streams); SLIST_INIT(&test->streams);
if (test->remote_congestion_used)
free(test->remote_congestion_used);
test->remote_congestion_used = NULL;
test->role = 's'; test->role = 's';
test->mode = RECEIVER; test->mode = RECEIVER;
test->sender_has_retransmits = 0; test->sender_has_retransmits = 0;

Просмотреть файл

@ -95,6 +95,7 @@ int check_authentication(const char *username, const char *password, const time_
s_username = strtok(buf, ","); s_username = strtok(buf, ",");
s_password = strtok(NULL, ","); s_password = strtok(NULL, ",");
if (strcmp( username, s_username ) == 0 && strcmp( passwordHash, s_password ) == 0){ if (strcmp( username, s_username ) == 0 && strcmp( passwordHash, s_password ) == 0){
fclose(ptr_file);
return 0; return 0;
} }
} }
@ -115,11 +116,9 @@ int Base64Encode(const unsigned char* buffer, const size_t length, char** b64tex
BIO_write(bio, buffer, length); BIO_write(bio, buffer, length);
BIO_flush(bio); BIO_flush(bio);
BIO_get_mem_ptr(bio, &bufferPtr); BIO_get_mem_ptr(bio, &bufferPtr);
BIO_set_close(bio, BIO_NOCLOSE); *b64text = strndup( (*bufferPtr).data, (*bufferPtr).length );
BIO_free_all(bio); BIO_free_all(bio);
*b64text=(*bufferPtr).data;
(*b64text)[(*bufferPtr).length] = '\0';
return (0); //success return (0); //success
} }
@ -157,10 +156,12 @@ EVP_PKEY *load_pubkey_from_file(const char *file) {
BIO *key = NULL; BIO *key = NULL;
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
if (file) {
key = BIO_new_file(file, "r"); key = BIO_new_file(file, "r");
pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL);
BIO_free(key); BIO_free(key);
}
return (pkey); return (pkey);
} }
@ -179,10 +180,12 @@ EVP_PKEY *load_privkey_from_file(const char *file) {
BIO *key = NULL; BIO *key = NULL;
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
if (file) {
key = BIO_new_file(file, "r"); key = BIO_new_file(file, "r");
pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL);
BIO_free(key); BIO_free(key);
}
return (pkey); return (pkey);
} }
@ -222,7 +225,7 @@ int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned ch
RSA_free(rsa); RSA_free(rsa);
OPENSSL_free(rsa_buffer); OPENSSL_free(rsa_buffer);
OPENSSL_free(bioBuff); BIO_free(bioBuff);
return encryptedtext_len; return encryptedtext_len;
} }
@ -244,7 +247,7 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt
RSA_free(rsa); RSA_free(rsa);
OPENSSL_free(rsa_buffer); OPENSSL_free(rsa_buffer);
OPENSSL_free(bioBuff); BIO_free(bioBuff);
return plaintext_len; return plaintext_len;
} }
@ -258,6 +261,8 @@ int encode_auth_setting(const char *username, const char *password, EVP_PKEY *pu
int encrypted_len; int encrypted_len;
encrypted_len = encrypt_rsa_message(text, public_key, &encrypted); encrypted_len = encrypt_rsa_message(text, public_key, &encrypted);
Base64Encode(encrypted, encrypted_len, authtoken); Base64Encode(encrypted, encrypted_len, authtoken);
OPENSSL_free(encrypted);
return (0); //success return (0); //success
} }
@ -270,6 +275,7 @@ int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key
int plaintext_len; int plaintext_len;
plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext); plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext);
plaintext[plaintext_len] = '\0'; plaintext[plaintext_len] = '\0';
free(encrypted_b64);
char s_username[20], s_password[20]; char s_username[20], s_password[20];
sscanf ((char *)plaintext,"user: %s\npwd: %s\nts: %ld", s_username, s_password, ts); sscanf ((char *)plaintext,"user: %s\npwd: %s\nts: %ld", s_username, s_password, ts);
@ -281,6 +287,7 @@ int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key
*password = (char *) calloc(21, sizeof(char)); *password = (char *) calloc(21, sizeof(char));
strncpy(*username, s_username, 20); strncpy(*username, s_username, 20);
strncpy(*password, s_password, 20); strncpy(*password, s_password, 20);
OPENSSL_free(plaintext);
return (0); return (0);
} }