Add authentication functions to libiperf (#713)
Fixes #712. A subsequent commit will add some information to the libiperf manual page.
Этот коммит содержится в:
родитель
efce01e1b5
Коммит
e28f12c788
17
src/iperf.h
17
src/iperf.h
@ -62,6 +62,11 @@
|
|||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "cjson.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;
|
typedef uint64_t iperf_size_t;
|
||||||
|
|
||||||
struct iperf_interval_results
|
struct iperf_interval_results
|
||||||
@ -141,7 +146,12 @@ struct iperf_settings
|
|||||||
iperf_size_t blocks; /* number of blocks (packets) to send */
|
iperf_size_t blocks; /* number of blocks (packets) to send */
|
||||||
char unit_format; /* -f */
|
char unit_format; /* -f */
|
||||||
int num_ostreams; /* SCTP initmsg settings */
|
int num_ostreams; /* SCTP initmsg settings */
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
char *authtoken; /* Authentication token */
|
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 */
|
int connect_timeout; /* socket connection timeout, in ms */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -257,8 +267,11 @@ struct iperf_test
|
|||||||
int prot_listener;
|
int prot_listener;
|
||||||
|
|
||||||
int ctrl_sck_mss; /* MSS for the control channel */
|
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 */
|
/* boolean variables for Options */
|
||||||
int daemon; /* -D option */
|
int daemon; /* -D option */
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
#include "iperf_locale.h"
|
#include "iperf_locale.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#if defined(HAVE_SSL)
|
#if defined(HAVE_SSL)
|
||||||
|
#include <openssl/bio.h>
|
||||||
#include "iperf_auth.h"
|
#include "iperf_auth.h"
|
||||||
#endif /* HAVE_SSL */
|
#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;
|
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
|
void
|
||||||
iperf_set_test_bind_address(struct iperf_test *ipt, char *bnd_address)
|
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;
|
blksize = 0;
|
||||||
server_flag = client_flag = rate_flag = duration_flag = 0;
|
server_flag = client_flag = rate_flag = duration_flag = 0;
|
||||||
#if defined(HAVE_SSL)
|
#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 */
|
#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) {
|
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);
|
client_rsa_public_key = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
case OPT_SERVER_RSA_PRIVATE_KEY:
|
case OPT_SERVER_RSA_PRIVATE_KEY:
|
||||||
test->server_rsa_private_key = strdup(optarg);
|
server_rsa_private_key = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
case OPT_SERVER_AUTHORIZED_USERS:
|
case OPT_SERVER_AUTHORIZED_USERS:
|
||||||
test->server_authorized_users = strdup(optarg);
|
test->server_authorized_users = strdup(optarg);
|
||||||
@ -1113,24 +1134,30 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
|||||||
return -1;
|
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;
|
i_errno = IESETCLIENTAUTH;
|
||||||
return -1;
|
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;
|
i_errno = IESERVERONLY;
|
||||||
return -1;
|
return -1;
|
||||||
} else if (test->role == 's' && (test->server_rsa_private_key || test->server_authorized_users) &&
|
} else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) &&
|
||||||
!(test->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' && 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;
|
i_errno = IESETSERVERAUTH;
|
||||||
return -1;
|
return -1;
|
||||||
|
} else {
|
||||||
|
test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //HAVE_SSL
|
#endif //HAVE_SSL
|
||||||
if (blksize == 0) {
|
if (blksize == 0) {
|
||||||
if (test->protocol->id == Pudp)
|
if (test->protocol->id == Pudp)
|
||||||
@ -1529,8 +1556,10 @@ send_parameters(struct iperf_test *test)
|
|||||||
if (test->udp_counters_64bit)
|
if (test->udp_counters_64bit)
|
||||||
cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
|
cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
|
||||||
#if defined(HAVE_SSL)
|
#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);
|
cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
|
||||||
|
}
|
||||||
#endif // HAVE_SSL
|
#endif // HAVE_SSL
|
||||||
cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
|
cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
|
||||||
|
|
||||||
@ -2328,10 +2357,26 @@ iperf_reset_test(struct iperf_test *test)
|
|||||||
test->settings->burst = 0;
|
test->settings->burst = 0;
|
||||||
test->settings->mss = 0;
|
test->settings->mss = 0;
|
||||||
test->settings->tos = 0;
|
test->settings->tos = 0;
|
||||||
|
|
||||||
|
#if defined(HAVE_SSL)
|
||||||
if (test->settings->authtoken) {
|
if (test->settings->authtoken) {
|
||||||
free(test->settings->authtoken);
|
free(test->settings->authtoken);
|
||||||
test->settings->authtoken = NULL;
|
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);
|
memset(test->cookie, 0, COOKIE_SIZE);
|
||||||
test->multisend = 10; /* arbitrary */
|
test->multisend = 10; /* arbitrary */
|
||||||
test->udp_counters_64bit = 0;
|
test->udp_counters_64bit = 0;
|
||||||
|
@ -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_one_off( struct iperf_test* ipt, int one_off );
|
||||||
void iperf_set_test_tos( struct iperf_test* ipt, int tos );
|
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
|
* exchange_parameters - handles the param_Exchange part for client
|
||||||
*
|
*
|
||||||
|
@ -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;
|
BIO *bio, *b64;
|
||||||
BUF_MEM *bufferPtr;
|
BUF_MEM *bufferPtr;
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ size_t calcDecodeLength(const char* b64input) { //Calculates the length of a dec
|
|||||||
return (len*3)/4 - padding;
|
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;
|
BIO *bio, *b64;
|
||||||
|
|
||||||
int decodeLen = calcDecodeLength(b64message);
|
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;
|
BIO *key = NULL;
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
|
|
||||||
@ -164,7 +164,18 @@ EVP_PKEY *load_pubkey(const char *file) {
|
|||||||
return (pkey);
|
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;
|
BIO *key = NULL;
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
|
|
||||||
@ -176,8 +187,8 @@ EVP_PKEY *load_key(const char *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int test_load_pubkey(const char *file){
|
int test_load_pubkey_from_file(const char *file){
|
||||||
EVP_PKEY *key = load_pubkey(file);
|
EVP_PKEY *key = load_pubkey_from_file(file);
|
||||||
if (key == NULL){
|
if (key == NULL){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -185,8 +196,8 @@ int test_load_pubkey(const char *file){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_load_private_key(const char *file){
|
int test_load_private_key_from_file(const char *file){
|
||||||
EVP_PKEY *key = load_key(file);
|
EVP_PKEY *key = load_privkey_from_file(file);
|
||||||
if (key == NULL){
|
if (key == NULL){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -194,17 +205,14 @@ int test_load_private_key(const char *file){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext) {
|
int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext) {
|
||||||
EVP_PKEY *public_key = NULL;
|
|
||||||
RSA *rsa = NULL;
|
RSA *rsa = NULL;
|
||||||
unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
||||||
int keysize, encryptedtext_len, rsa_buffer_len;
|
int keysize, encryptedtext_len, rsa_buffer_len;
|
||||||
|
|
||||||
public_key = load_pubkey(public_keyfile);
|
|
||||||
rsa = EVP_PKEY_get1_RSA(public_key);
|
rsa = EVP_PKEY_get1_RSA(public_key);
|
||||||
EVP_PKEY_free(public_key);
|
|
||||||
|
|
||||||
keysize = RSA_size(rsa);
|
keysize = RSA_size(rsa);
|
||||||
|
|
||||||
rsa_buffer = OPENSSL_malloc(keysize * 2);
|
rsa_buffer = OPENSSL_malloc(keysize * 2);
|
||||||
*encryptedtext = (unsigned char*)OPENSSL_malloc(keysize);
|
*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;
|
return encryptedtext_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext) {
|
int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext) {
|
||||||
EVP_PKEY *private_key = NULL;
|
|
||||||
RSA *rsa = NULL;
|
RSA *rsa = NULL;
|
||||||
unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING;
|
||||||
int plaintext_len, rsa_buffer_len, keysize;
|
int plaintext_len, rsa_buffer_len, keysize;
|
||||||
|
|
||||||
private_key = load_key(private_keyfile);
|
|
||||||
rsa = EVP_PKEY_get1_RSA(private_key);
|
rsa = EVP_PKEY_get1_RSA(private_key);
|
||||||
EVP_PKEY_free(private_key);
|
|
||||||
|
|
||||||
keysize = RSA_size(rsa);
|
keysize = RSA_size(rsa);
|
||||||
rsa_buffer = OPENSSL_malloc(keysize * 2);
|
rsa_buffer = OPENSSL_malloc(keysize * 2);
|
||||||
@ -244,26 +249,26 @@ int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedt
|
|||||||
return plaintext_len;
|
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 t = time(NULL);
|
||||||
time_t utc_seconds = mktime(localtime(&t));
|
time_t utc_seconds = mktime(localtime(&t));
|
||||||
char text[150];
|
char text[150];
|
||||||
sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds);
|
sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds);
|
||||||
unsigned char *encrypted = NULL;
|
unsigned char *encrypted = NULL;
|
||||||
int encrypted_len;
|
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);
|
Base64Encode(encrypted, encrypted_len, authtoken);
|
||||||
return (0); //success
|
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;
|
unsigned char *encrypted_b64 = NULL;
|
||||||
size_t encrypted_len_b64;
|
size_t encrypted_len_b64;
|
||||||
Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);
|
Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);
|
||||||
|
|
||||||
unsigned char *plaintext = NULL;
|
unsigned char *plaintext = NULL;
|
||||||
int plaintext_len;
|
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';
|
plaintext[plaintext_len] = '\0';
|
||||||
|
|
||||||
char s_username[20], s_password[20];
|
char s_username[20], s_password[20];
|
||||||
|
@ -27,10 +27,14 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
|
||||||
int test_load_pubkey(const char *public_keyfile);
|
int test_load_pubkey_from_file(const char *public_keyfile);
|
||||||
int test_load_private_key(const char *private_keyfile);
|
int test_load_private_key_from_file(const char *private_keyfile);
|
||||||
int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken);
|
EVP_PKEY *load_pubkey_from_file(const char *file);
|
||||||
int decode_auth_setting(int enable_debug, const char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts);
|
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);
|
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);
|
ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream);
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user