1 /* 2 * iperf, Copyright (c) 2014-2017, The Regents of the University of 3 * California, through Lawrence Berkeley National Laboratory (subject 4 * to receipt of any required approvals from the U.S. Dept. of 5 * Energy). All rights reserved. 6 * 7 * If you have questions about your rights to use or distribute this 8 * software, please contact Berkeley Lab's Technology Transfer 9 * Department at [email protected]. 10 * 11 * NOTICE. This software is owned by the U.S. Department of Energy. 12 * As such, the U.S. Government has been granted for itself and others 13 * acting on its behalf a paid-up, nonexclusive, irrevocable, 14 * worldwide license in the Software to reproduce, prepare derivative 15 * works, and perform publicly and display publicly. Beginning five 16 * (5) years after the date permission to assert copyright is obtained 17 * from the U.S. Department of Energy, and subject to any subsequent 18 * five (5) year renewals, the U.S. Government is granted for itself 19 * and others acting on its behalf a paid-up, nonexclusive, 20 * irrevocable, worldwide license in the Software to reproduce, 21 * prepare derivative works, distribute copies to the public, perform 22 * publicly and display publicly, and to permit others to do so. 23 * 24 * This code is distributed under a BSD style license, see the LICENSE file 25 * for complete information. 26 */ 27 28 #include "iperf_config.h" 29 30 #include <string.h> 31 #include <assert.h> 32 #include <time.h> 33 #include <sys/types.h> 34 #include <stdio.h> 35 #include <termios.h> 36 37 #if defined(HAVE_SSL) 38 39 #include <openssl/bio.h> 40 #include <openssl/pem.h> 41 #include <openssl/sha.h> 42 #include <openssl/buffer.h> 43 44 void sha256(const char *string, char outputBuffer[65]) 45 { 46 unsigned char hash[SHA256_DIGEST_LENGTH]; 47 SHA256_CTX sha256; 48 SHA256_Init(&sha256); 49 SHA256_Update(&sha256, string, strlen(string)); 50 SHA256_Final(hash, &sha256); 51 int i = 0; 52 for(i = 0; i < SHA256_DIGEST_LENGTH; i++) 53 { 54 sprintf(outputBuffer + (i * 2), "%02x", hash[i]); 55 } 56 outputBuffer[64] = 0; 57 } 58 59 int check_authentication(const char *username, const char *password, const time_t ts, const char *filename){ 60 time_t t = time(NULL); 61 time_t utc_seconds = mktime(localtime(&t)); 62 if ( (utc_seconds - ts) < 10 && (utc_seconds - ts) > 0 ){ 63 return 1; 64 } 65 66 char passwordHash[65]; 67 char salted[strlen(username) + strlen(password) + 3]; 68 sprintf(salted, "{%s}%s", username, password); 69 sha256(&salted[0], passwordHash); 70 71 char *s_username, *s_password; 72 int i; 73 FILE *ptr_file; 74 char buf[1024]; 75 76 ptr_file =fopen(filename,"r"); 77 if (!ptr_file) 78 return 2; 79 80 while (fgets(buf,1024, ptr_file)){ 81 //strip the \n or \r\n chars 82 for (i = 0; buf[i] != '\0'; i++){ 83 if (buf[i] == '\n' || buf[i] == '\r'){ 84 buf[i] = '\0'; 85 break; 86 } 87 } 88 //skip empty / not completed / comment lines 89 if (strlen(buf) == 0 || strchr(buf, ',') == NULL || buf[0] == '#'){ 90 continue; 91 } 92 s_username = strtok(buf, ","); 93 s_password = strtok(NULL, ","); 94 if (strcmp( username, s_username ) == 0 && strcmp( passwordHash, s_password ) == 0){ 95 return 0; 96 } 97 } 98 return 3; 99 } 100 101 102 int Base64Encode(unsigned char* buffer, const size_t length, char** b64text) { //Encodes a binary safe base 64 string 103 BIO *bio, *b64; 104 BUF_MEM *bufferPtr; 105 106 b64 = BIO_new(BIO_f_base64()); 107 bio = BIO_new(BIO_s_mem()); 108 bio = BIO_push(b64, bio); 109 110 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line 111 BIO_write(bio, buffer, length); 112 BIO_flush(bio); 113 BIO_get_mem_ptr(bio, &bufferPtr); 114 BIO_set_close(bio, BIO_NOCLOSE); 115 BIO_free_all(bio); 116 117 *b64text=(*bufferPtr).data; 118 (*b64text)[(*bufferPtr).length] = '\0'; 119 return (0); //success 120 } 121 122 size_t calcDecodeLength(const char* b64input) { //Calculates the length of a decoded string 123 size_t len = strlen(b64input), padding = 0; 124 if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are = 125 padding = 2; 126 else if (b64input[len-1] == '=') //last char is = 127 padding = 1; 128 129 return (len*3)/4 - padding; 130 } 131 132 int Base64Decode(char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string 133 BIO *bio, *b64; 134 135 int decodeLen = calcDecodeLength(b64message); 136 *buffer = (unsigned char*)malloc(decodeLen + 1); 137 (*buffer)[decodeLen] = '\0'; 138 139 bio = BIO_new_mem_buf(b64message, -1); 140 b64 = BIO_new(BIO_f_base64()); 141 bio = BIO_push(b64, bio); 142 143 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer 144 *length = BIO_read(bio, *buffer, strlen(b64message)); 145 assert(*length == decodeLen); //length should equal decodeLen, else something went horribly wrong 146 BIO_free_all(bio); 147 148 return (0); //success 149 } 150 151 152 EVP_PKEY *load_pubkey(const char *file) { 153 BIO *key = NULL; 154 EVP_PKEY *pkey = NULL; 155 156 key = BIO_new_file(file, "r"); 157 pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); 158 159 BIO_free(key); 160 return (pkey); 161 } 162 163 EVP_PKEY *load_key(const char *file) { 164 BIO *key = NULL; 165 EVP_PKEY *pkey = NULL; 166 167 key = BIO_new_file(file, "r"); 168 pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); 169 170 BIO_free(key); 171 return (pkey); 172 } 173 174 175 int test_load_pubkey(const char *file){ 176 EVP_PKEY *key = load_pubkey(file); 177 if (key == NULL){ 178 return -1; 179 } 180 EVP_PKEY_free(key); 181 return 0; 182 } 183 184 int test_load_private_key(const char *file){ 185 EVP_PKEY *key = load_key(file); 186 if (key == NULL){ 187 return -1; 188 } 189 EVP_PKEY_free(key); 190 return 0; 191 } 192 193 int encrypt_rsa_message(const char *plaintext, const char *public_keyfile, unsigned char **encryptedtext) { 194 EVP_PKEY *public_key = NULL; 195 RSA *rsa = NULL; 196 unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; 197 int keysize, encryptedtext_len, rsa_buffer_len; 198 199 public_key = load_pubkey(public_keyfile); 200 rsa = EVP_PKEY_get1_RSA(public_key); 201 EVP_PKEY_free(public_key); 202 203 keysize = RSA_size(rsa); 204 rsa_buffer = OPENSSL_malloc(keysize * 2); 205 *encryptedtext = (unsigned char*)OPENSSL_malloc(keysize); 206 207 BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext)); 208 rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2); 209 encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, pad); 210 211 RSA_free(rsa); 212 OPENSSL_free(rsa_buffer); 213 OPENSSL_free(bioBuff); 214 215 return encryptedtext_len; 216 } 217 218 int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, const char *private_keyfile, unsigned char **plaintext) { 219 EVP_PKEY *private_key = NULL; 220 RSA *rsa = NULL; 221 unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; 222 int plaintext_len, rsa_buffer_len, keysize; 223 224 private_key = load_key(private_keyfile); 225 rsa = EVP_PKEY_get1_RSA(private_key); 226 EVP_PKEY_free(private_key); 227 228 keysize = RSA_size(rsa); 229 rsa_buffer = OPENSSL_malloc(keysize * 2); 230 *plaintext = (unsigned char*)OPENSSL_malloc(keysize); 231 232 BIO *bioBuff = BIO_new_mem_buf((void*)encryptedtext, encryptedtext_len); 233 rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2); 234 plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, pad); 235 236 RSA_free(rsa); 237 OPENSSL_free(rsa_buffer); 238 OPENSSL_free(bioBuff); 239 240 return plaintext_len; 241 } 242 243 int encode_auth_setting(const char *username, const char *password, const char *public_keyfile, char **authtoken){ 244 time_t t = time(NULL); 245 time_t utc_seconds = mktime(localtime(&t)); 246 char text[150]; 247 sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds); 248 unsigned char *encrypted = NULL; 249 int encrypted_len; 250 encrypted_len = encrypt_rsa_message(text, public_keyfile, &encrypted); 251 Base64Encode(encrypted, encrypted_len, authtoken); 252 return (0); //success 253 } 254 255 int decode_auth_setting(int enable_debug, char *authtoken, const char *private_keyfile, char **username, char **password, time_t *ts){ 256 unsigned char *encrypted_b64 = NULL; 257 size_t encrypted_len_b64; 258 Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64); 259 260 unsigned char *plaintext = NULL; 261 int plaintext_len; 262 plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_keyfile, &plaintext); 263 plaintext[plaintext_len] = '\0'; 264 265 char s_username[20], s_password[20]; 266 sscanf ((char *)plaintext,"user: %s\npwd: %s\nts: %ld", s_username, s_password, ts); 267 if (enable_debug) { 268 printf("Auth Token Content:\n%s\n", plaintext); 269 printf("Auth Token Credentials:\n--> %s %s\n", s_username, s_password); 270 } 271 *username = (char *) calloc(21, sizeof(char *)); 272 *password = (char *) calloc(21, sizeof(char *)); 273 strncpy(*username, s_username, 20); 274 strncpy(*password, s_password, 20); 275 return (0); 276 } 277 278 #endif //HAVE_SSL 279 280 ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream) { 281 struct termios old, new; 282 ssize_t nread; 283 284 /* Turn echoing off and fail if we can't. */ 285 if (tcgetattr (fileno (stream), &old) != 0) 286 return -1; 287 new = old; 288 new.c_lflag &= ~ECHO; 289 if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0) 290 return -1; 291 292 /* Read the password. */ 293 printf("Password: "); 294 nread = getline (lineptr, n, stream); 295 296 /* Restore terminal. */ 297 (void) tcsetattr (fileno (stream), TCSAFLUSH, &old); 298 299 //strip the \n or \r\n chars 300 char *buf = *lineptr; 301 int i; 302 for (i = 0; buf[i] != '\0'; i++){ 303 if (buf[i] == '\n' || buf[i] == '\r'){ 304 buf[i] = '\0'; 305 break; 306 } 307 } 308 309 return nread; 310 } 311 312 313