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.
Этот коммит содержится в:
родитель
098dd3cc1b
Коммит
c4bd56f373
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user