diff options
author | ralcini <roberto.alcini@gmail.com> | 2018-04-27 22:39:28 +0200 |
---|---|---|
committer | Bruce A. Mah <bmah@kitchenlab.org> | 2018-04-27 13:39:28 -0700 |
commit | e28f12c788fe238a02f4b7ff2410cc563b27d2b6 (patch) | |
tree | 2f43e1df54820099f3d5a04b33dfadcb8ba19b6c /src | |
parent | efce01e1b5199ec36dcd823e684e5af5c1268525 (diff) | |
download | iperf3-e28f12c788fe238a02f4b7ff2410cc563b27d2b6.tar.gz |
Add authentication functions to libiperf (#713)
Fixes #712. A subsequent commit will add some information to the libiperf manual page.
Diffstat (limited to 'src')
-rwxr-xr-x | src/iperf.h | 17 | ||||
-rwxr-xr-x | src/iperf_api.c | 67 | ||||
-rwxr-xr-x | src/iperf_api.h | 6 | ||||
-rw-r--r-- | src/iperf_auth.c | 47 | ||||
-rw-r--r-- | src/iperf_auth.h | 12 |
5 files changed, 111 insertions, 38 deletions
diff --git a/src/iperf.h b/src/iperf.h index 8469083..b33ba37 100755 --- a/src/iperf.h +++ b/src/iperf.h @@ -62,6 +62,11 @@ #include "queue.h" #include "cjson.h" +#if defined(HAVE_SSL) +#include <openssl/bio.h> +#include <openssl/evp.h> +#endif // HAVE_SSL + typedef uint64_t iperf_size_t; struct iperf_interval_results @@ -141,7 +146,12 @@ struct iperf_settings iperf_size_t blocks; /* number of blocks (packets) to send */ char unit_format; /* -f */ int num_ostreams; /* SCTP initmsg settings */ +#if defined(HAVE_SSL) char *authtoken; /* Authentication token */ + char *client_username; + char *client_password; + EVP_PKEY *client_rsa_pubkey; +#endif // HAVE_SSL int connect_timeout; /* socket connection timeout, in ms */ }; @@ -257,8 +267,11 @@ struct iperf_test int prot_listener; int ctrl_sck_mss; /* MSS for the control channel */ - char *server_rsa_private_key; - char *server_authorized_users; + +#if defined(HAVE_SSL) + char *server_authorized_users; + EVP_PKEY *server_rsa_private_key; +#endif // HAVE_SSL /* boolean variables for Options */ int daemon; /* -D option */ diff --git a/src/iperf_api.c b/src/iperf_api.c index 92252e6..8d3608b 100755 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -83,6 +83,7 @@ #include "iperf_locale.h" #include "version.h" #if defined(HAVE_SSL) +#include <openssl/bio.h> #include "iperf_auth.h" #endif /* HAVE_SSL */ @@ -455,6 +456,26 @@ iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format) ipt->settings->unit_format = unit_format; } +#if defined(HAVE_SSL) +void +iperf_set_test_client_username(struct iperf_test *ipt, char *client_username) +{ + ipt->settings->client_username = client_username; +} + +void +iperf_set_test_client_password(struct iperf_test *ipt, char *client_password) +{ + ipt->settings->client_password = client_password; +} + +void +iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64) +{ + ipt->settings->client_rsa_pubkey = load_pubkey_from_base64(client_rsa_pubkey_base64); +} +#endif // HAVE_SSL + void iperf_set_test_bind_address(struct iperf_test *ipt, char *bnd_address) { @@ -720,7 +741,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) blksize = 0; server_flag = client_flag = rate_flag = duration_flag = 0; #if defined(HAVE_SSL) - char *client_username = NULL, *client_rsa_public_key = NULL; + char *client_username = NULL, *client_rsa_public_key = NULL, *server_rsa_private_key = NULL; #endif /* HAVE_SSL */ while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) { @@ -1049,7 +1070,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) client_rsa_public_key = strdup(optarg); break; case OPT_SERVER_RSA_PRIVATE_KEY: - test->server_rsa_private_key = strdup(optarg); + server_rsa_private_key = strdup(optarg); break; case OPT_SERVER_AUTHORIZED_USERS: test->server_authorized_users = strdup(optarg); @@ -1113,24 +1134,30 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) return -1; } - if (test_load_pubkey(client_rsa_public_key) < 0){ + if (test_load_pubkey_from_file(client_rsa_public_key) < 0){ i_errno = IESETCLIENTAUTH; return -1; } - encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken); + + test->settings->client_username = client_username; + test->settings->client_password = client_password; + test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key); } - if (test->role == 'c' && (test->server_rsa_private_key || test->server_authorized_users)){ + if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){ i_errno = IESERVERONLY; return -1; - } else if (test->role == 's' && (test->server_rsa_private_key || test->server_authorized_users) && - !(test->server_rsa_private_key && test->server_authorized_users)) { + } else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) && + !(server_rsa_private_key && test->server_authorized_users)) { i_errno = IESETSERVERAUTH; return -1; - } else if (test->role == 's' && test->server_rsa_private_key && test_load_private_key(test->server_rsa_private_key) < 0){ + } else if (test->role == 's' && server_rsa_private_key && test_load_private_key_from_file(server_rsa_private_key) < 0){ i_errno = IESETSERVERAUTH; return -1; + } else { + test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key); } + #endif //HAVE_SSL if (blksize == 0) { if (test->protocol->id == Pudp) @@ -1529,8 +1556,10 @@ send_parameters(struct iperf_test *test) if (test->udp_counters_64bit) cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test)); #if defined(HAVE_SSL) - if (test->settings->authtoken) + if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){ + encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken); cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken); + } #endif // HAVE_SSL cJSON_AddStringToObject(j, "client_version", IPERF_VERSION); @@ -2328,10 +2357,26 @@ iperf_reset_test(struct iperf_test *test) test->settings->burst = 0; test->settings->mss = 0; test->settings->tos = 0; + +#if defined(HAVE_SSL) if (test->settings->authtoken) { - free(test->settings->authtoken); - test->settings->authtoken = NULL; + free(test->settings->authtoken); + test->settings->authtoken = NULL; + } + if (test->settings->client_username) { + free(test->settings->client_username); + test->settings->client_username = NULL; + } + if (test->settings->client_password) { + 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 */ + memset(test->cookie, 0, COOKIE_SIZE); test->multisend = 10; /* arbitrary */ test->udp_counters_64bit = 0; diff --git a/src/iperf_api.h b/src/iperf_api.h index 7ebeb3c..7e8346b 100755 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -145,6 +145,12 @@ void iperf_set_test_udp_counters_64bit( struct iperf_test* ipt, int udp_counters void iperf_set_test_one_off( struct iperf_test* ipt, int one_off ); void iperf_set_test_tos( struct iperf_test* ipt, int tos ); +#if defined(HAVE_SSL) +void iperf_set_test_client_username(struct iperf_test *ipt, char *client_username); +void iperf_set_test_client_password(struct iperf_test *ipt, char *client_password); +void iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64); +#endif // HAVE_SSL + /** * exchange_parameters - handles the param_Exchange part for client * diff --git a/src/iperf_auth.c b/src/iperf_auth.c index f8d2b0a..b9cd98a 100644 --- a/src/iperf_auth.c +++ b/src/iperf_auth.c @@ -103,7 +103,7 @@ int check_authentication(const char *username, const char *password, const time_ } -int Base64Encode(unsigned char* buffer, const size_t length, char** b64text) { //Encodes a binary safe base 64 string +int Base64Encode(const unsigned char* buffer, const size_t length, char** b64text) { //Encodes a binary safe base 64 string BIO *bio, *b64; BUF_MEM *bufferPtr; @@ -133,7 +133,7 @@ size_t calcDecodeLength(const char* b64input) { //Calculates the length of a dec return (len*3)/4 - padding; } -int Base64Decode(char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string +int Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string BIO *bio, *b64; int decodeLen = calcDecodeLength(b64message); @@ -153,7 +153,7 @@ int Base64Decode(char* b64message, unsigned char** buffer, size_t* length) { //D } -EVP_PKEY *load_pubkey(const char *file) { +EVP_PKEY *load_pubkey_from_file(const char *file) { BIO *key = NULL; EVP_PKEY *pkey = NULL; @@ -164,7 +164,18 @@ EVP_PKEY *load_pubkey(const char *file) { return (pkey); } -EVP_PKEY *load_key(const char *file) { +EVP_PKEY *load_pubkey_from_base64(const char *buffer) { + unsigned char *key = NULL; + size_t key_len; + Base64Decode(buffer, &key, &key_len); + + BIO* bio = BIO_new(BIO_s_mem()); + BIO_write(bio, key, key_len); + EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + return (pkey); +} + +EVP_PKEY *load_privkey_from_file(const char *file) { BIO *key = NULL; EVP_PKEY *pkey = NULL; @@ -176,8 +187,8 @@ EVP_PKEY *load_key(const char *file) { } -int test_load_pubkey(const char *file){ - EVP_PKEY *key = load_pubkey(file); +int test_load_pubkey_from_file(const char *file){ + EVP_PKEY *key = load_pubkey_from_file(file); if (key == NULL){ return -1; } @@ -185,8 +196,8 @@ int test_load_pubkey(const char *file){ return 0; } -int test_load_private_key(const char *file){ - EVP_PKEY *key = load_key(file); +int test_load_private_key_from_file(const char *file){ + EVP_PKEY *key = load_privkey_from_file(file); if (key == NULL){ return -1; } @@ -194,17 +205,14 @@ int test_load_private_key(const char *file){ return 0; } -int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext) { - EVP_PKEY *public_key = NULL; +int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext) { RSA *rsa = NULL; unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; int keysize, encryptedtext_len, rsa_buffer_len; - public_key = load_pubkey(public_keyfile); rsa = EVP_PKEY_get1_RSA(public_key); - EVP_PKEY_free(public_key); - keysize = RSA_size(rsa); + rsa_buffer = OPENSSL_malloc(keysize * 2); *encryptedtext = (unsigned char*)OPENSSL_malloc(keysize); @@ -219,15 +227,12 @@ int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsig return encryptedtext_len; } -int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext) { - EVP_PKEY *private_key = NULL; +int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext) { RSA *rsa = NULL; unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; int plaintext_len, rsa_buffer_len, keysize; - private_key = load_key(private_keyfile); rsa = EVP_PKEY_get1_RSA(private_key); - EVP_PKEY_free(private_key); keysize = RSA_size(rsa); rsa_buffer = OPENSSL_malloc(keysize * 2); @@ -244,26 +249,26 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt return plaintext_len; } -int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken){ +int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken){ time_t t = time(NULL); time_t utc_seconds = mktime(localtime(&t)); char text[150]; sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds); unsigned char *encrypted = NULL; int encrypted_len; - encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted); + encrypted_len = encrypt_rsa_message(text, public_key, &encrypted); Base64Encode(encrypted, encrypted_len, authtoken); return (0); //success } -int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts){ +int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){ unsigned char *encrypted_b64 = NULL; size_t encrypted_len_b64; Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64); unsigned char *plaintext = NULL; int plaintext_len; - plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext); + plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext); plaintext[plaintext_len] = '\0'; char s_username[20], s_password[20]; diff --git a/src/iperf_auth.h b/src/iperf_auth.h index 38971d8..0c6fb0f 100644 --- a/src/iperf_auth.h +++ b/src/iperf_auth.h @@ -27,10 +27,14 @@ #include <time.h> #include <sys/types.h> +#include <openssl/bio.h> -int test_load_pubkey(const char *public_keyfile); -int test_load_private_key(const char *private_keyfile); -int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken); -int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts); +int test_load_pubkey_from_file(const char *public_keyfile); +int test_load_private_key_from_file(const char *private_keyfile); +EVP_PKEY *load_pubkey_from_file(const char *file); +EVP_PKEY *load_pubkey_from_base64(const char *buffer); +EVP_PKEY *load_privkey_from_file(const char *file); +int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken); +int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts); int check_authentication(const char *username, const char *password, const time_t ts, const char *filename); ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream); |