1 /* 2 * iperf, Copyright (c) 2014-2018, 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 TTD@lbl.gov. 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 /* FreeBSD needs _WITH_GETLINE to enable the getline() declaration */ 35 #define _WITH_GETLINE 36 #include <stdio.h> 37 #include <termios.h> 38 39 #if defined(HAVE_SSL) 40 41 #include <openssl/rsa.h> 42 #include <openssl/bio.h> 43 #include <openssl/pem.h> 44 #include <openssl/sha.h> 45 #include <openssl/buffer.h> 46 47 void sha256(const char *string, char outputBuffer[65]) 48 { 49 unsigned char hash[SHA256_DIGEST_LENGTH]; 50 SHA256_CTX sha256; 51 SHA256_Init(&sha256); 52 SHA256_Update(&sha256, string, strlen(string)); 53 SHA256_Final(hash, &sha256); 54 int i = 0; 55 for(i = 0; i < SHA256_DIGEST_LENGTH; i++) 56 { 57 sprintf(outputBuffer + (i * 2), "%02x", hash[i]); 58 } 59 outputBuffer[64] = 0; 60 } 61 62 int check_authentication(const char *username, const char *password, const time_t ts, const char *filename){ 63 time_t t = time(NULL); 64 time_t utc_seconds = mktime(localtime(&t)); 65 if ( (utc_seconds - ts) > 10 || (utc_seconds - ts) < -10 ) { 66 return 1; 67 } 68 69 char passwordHash[65]; 70 char salted[strlen(username) + strlen(password) + 3]; 71 sprintf(salted, "{%s}%s", username, password); 72 sha256(&salted[0], passwordHash); 73 74 char *s_username, *s_password; 75 int i; 76 FILE *ptr_file; 77 char buf[1024]; 78 79 ptr_file =fopen(filename,"r"); 80 if (!ptr_file) 81 return 2; 82 83 while (fgets(buf,1024, ptr_file)){ 84 //strip the \n or \r\n chars 85 for (i = 0; buf[i] != '\0'; i++){ 86 if (buf[i] == '\n' || buf[i] == '\r'){ 87 buf[i] = '\0'; 88 break; 89 } 90 } 91 //skip empty / not completed / comment lines 92 if (strlen(buf) == 0 || strchr(buf, ',') == NULL || buf[0] == '#'){ 93 continue; 94 } 95 s_username = strtok(buf, ","); 96 s_password = strtok(NULL, ","); 97 if (strcmp( username, s_username ) == 0 && strcmp( passwordHash, s_password ) == 0){ 98 fclose(ptr_file); 99 return 0; 100 } 101 } 102 fclose(ptr_file); 103 return 3; 104 } 105 106 107 int Base64Encode(const unsigned char* buffer, const size_t length, char** b64text) { //Encodes a binary safe base 64 string 108 BIO *bio, *b64; 109 BUF_MEM *bufferPtr; 110 111 b64 = BIO_new(BIO_f_base64()); 112 bio = BIO_new(BIO_s_mem()); 113 bio = BIO_push(b64, bio); 114 115 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line 116 BIO_write(bio, buffer, length); 117 BIO_flush(bio); 118 BIO_get_mem_ptr(bio, &bufferPtr); 119 *b64text = strndup( (*bufferPtr).data, (*bufferPtr).length ); 120 BIO_free_all(bio); 121 122 return (0); //success 123 } 124 125 size_t calcDecodeLength(const char* b64input) { //Calculates the length of a decoded string 126 size_t len = strlen(b64input), padding = 0; 127 if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are = 128 padding = 2; 129 else if (b64input[len-1] == '=') //last char is = 130 padding = 1; 131 132 return (len*3)/4 - padding; 133 } 134 135 int Base64Decode(const char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string 136 BIO *bio, *b64; 137 138 int decodeLen = calcDecodeLength(b64message); 139 *buffer = (unsigned char*)malloc(decodeLen + 1); 140 (*buffer)[decodeLen] = '\0'; 141 142 bio = BIO_new_mem_buf(b64message, -1); 143 b64 = BIO_new(BIO_f_base64()); 144 bio = BIO_push(b64, bio); 145 146 BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer 147 *length = BIO_read(bio, *buffer, strlen(b64message)); 148 assert(*length == decodeLen); //length should equal decodeLen, else something went horribly wrong 149 BIO_free_all(bio); 150 151 return (0); //success 152 } 153 154 155 EVP_PKEY *load_pubkey_from_file(const char *file) { 156 BIO *key = NULL; 157 EVP_PKEY *pkey = NULL; 158 159 if (file) { 160 key = BIO_new_file(file, "r"); 161 pkey = PEM_read_bio_PUBKEY(key, NULL, NULL, NULL); 162 163 BIO_free(key); 164 } 165 return (pkey); 166 } 167 168 EVP_PKEY *load_pubkey_from_base64(const char *buffer) { 169 unsigned char *key = NULL; 170 size_t key_len; 171 Base64Decode(buffer, &key, &key_len); 172 173 BIO* bio = BIO_new(BIO_s_mem()); 174 BIO_write(bio, key, key_len); 175 EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); 176 return (pkey); 177 } 178 179 EVP_PKEY *load_privkey_from_file(const char *file) { 180 BIO *key = NULL; 181 EVP_PKEY *pkey = NULL; 182 183 if (file) { 184 key = BIO_new_file(file, "r"); 185 pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); 186 187 BIO_free(key); 188 } 189 return (pkey); 190 } 191 192 193 int test_load_pubkey_from_file(const char *file){ 194 EVP_PKEY *key = load_pubkey_from_file(file); 195 if (key == NULL){ 196 return -1; 197 } 198 EVP_PKEY_free(key); 199 return 0; 200 } 201 202 int test_load_private_key_from_file(const char *file){ 203 EVP_PKEY *key = load_privkey_from_file(file); 204 if (key == NULL){ 205 return -1; 206 } 207 EVP_PKEY_free(key); 208 return 0; 209 } 210 211 int encrypt_rsa_message(const char *plaintext, EVP_PKEY *public_key, unsigned char **encryptedtext) { 212 RSA *rsa = NULL; 213 unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; 214 int keysize, encryptedtext_len, rsa_buffer_len; 215 216 rsa = EVP_PKEY_get1_RSA(public_key); 217 keysize = RSA_size(rsa); 218 219 rsa_buffer = OPENSSL_malloc(keysize * 2); 220 *encryptedtext = (unsigned char*)OPENSSL_malloc(keysize); 221 222 BIO *bioBuff = BIO_new_mem_buf((void*)plaintext, (int)strlen(plaintext)); 223 rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2); 224 encryptedtext_len = RSA_public_encrypt(rsa_buffer_len, rsa_buffer, *encryptedtext, rsa, pad); 225 226 RSA_free(rsa); 227 OPENSSL_free(rsa_buffer); 228 BIO_free(bioBuff); 229 230 return encryptedtext_len; 231 } 232 233 int decrypt_rsa_message(const unsigned char *encryptedtext, const int encryptedtext_len, EVP_PKEY *private_key, unsigned char **plaintext) { 234 RSA *rsa = NULL; 235 unsigned char *rsa_buffer = NULL, pad = RSA_PKCS1_PADDING; 236 int plaintext_len, rsa_buffer_len, keysize; 237 238 rsa = EVP_PKEY_get1_RSA(private_key); 239 240 keysize = RSA_size(rsa); 241 rsa_buffer = OPENSSL_malloc(keysize * 2); 242 *plaintext = (unsigned char*)OPENSSL_malloc(keysize); 243 244 BIO *bioBuff = BIO_new_mem_buf((void*)encryptedtext, encryptedtext_len); 245 rsa_buffer_len = BIO_read(bioBuff, rsa_buffer, keysize * 2); 246 plaintext_len = RSA_private_decrypt(rsa_buffer_len, rsa_buffer, *plaintext, rsa, pad); 247 248 RSA_free(rsa); 249 OPENSSL_free(rsa_buffer); 250 BIO_free(bioBuff); 251 252 return plaintext_len; 253 } 254 255 int encode_auth_setting(const char *username, const char *password, EVP_PKEY *public_key, char **authtoken){ 256 time_t t = time(NULL); 257 time_t utc_seconds = mktime(localtime(&t)); 258 char text[150]; 259 sprintf (text, "user: %s\npwd: %s\nts: %ld", username, password, utc_seconds); 260 unsigned char *encrypted = NULL; 261 int encrypted_len; 262 encrypted_len = encrypt_rsa_message(text, public_key, &encrypted); 263 Base64Encode(encrypted, encrypted_len, authtoken); 264 OPENSSL_free(encrypted); 265 266 return (0); //success 267 } 268 269 int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){ 270 unsigned char *encrypted_b64 = NULL; 271 size_t encrypted_len_b64; 272 Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64); 273 274 unsigned char *plaintext = NULL; 275 int plaintext_len; 276 plaintext_len = decrypt_rsa_message(encrypted_b64, encrypted_len_b64, private_key, &plaintext); 277 plaintext[plaintext_len] = '\0'; 278 free(encrypted_b64); 279 280 char s_username[20], s_password[20]; 281 sscanf ((char *)plaintext,"user: %s\npwd: %s\nts: %ld", s_username, s_password, ts); 282 if (enable_debug) { 283 printf("Auth Token Content:\n%s\n", plaintext); 284 printf("Auth Token Credentials:\n--> %s %s\n", s_username, s_password); 285 } 286 *username = (char *) calloc(21, sizeof(char)); 287 *password = (char *) calloc(21, sizeof(char)); 288 strncpy(*username, s_username, 20); 289 strncpy(*password, s_password, 20); 290 OPENSSL_free(plaintext); 291 return (0); 292 } 293 294 #endif //HAVE_SSL 295 296 ssize_t iperf_getpass (char **lineptr, size_t *n, FILE *stream) { 297 struct termios old, new; 298 ssize_t nread; 299 300 /* Turn echoing off and fail if we can't. */ 301 if (tcgetattr (fileno (stream), &old) != 0) 302 return -1; 303 new = old; 304 new.c_lflag &= ~ECHO; 305 if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0) 306 return -1; 307 308 /* Read the password. */ 309 printf("Password: "); 310 nread = getline (lineptr, n, stream); 311 312 /* Restore terminal. */ 313 (void) tcsetattr (fileno (stream), TCSAFLUSH, &old); 314 315 //strip the \n or \r\n chars 316 char *buf = *lineptr; 317 int i; 318 for (i = 0; buf[i] != '\0'; i++){ 319 if (buf[i] == '\n' || buf[i] == '\r'){ 320 buf[i] = '\0'; 321 break; 322 } 323 } 324 325 return nread; 326 } 327 328 329