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
sha256(const char * string,char outputBuffer[65])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
check_authentication(const char * username,const char * password,const time_t ts,const char * filename)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
Base64Encode(const unsigned char * buffer,const size_t length,char ** b64text)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
calcDecodeLength(const char * b64input)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
Base64Decode(const char * b64message,unsigned char ** buffer,size_t * length)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
load_pubkey_from_file(const char * file)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
load_pubkey_from_base64(const char * buffer)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
load_privkey_from_file(const char * file)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
test_load_pubkey_from_file(const char * file)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
test_load_private_key_from_file(const char * file)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
encrypt_rsa_message(const char * plaintext,EVP_PKEY * public_key,unsigned char ** encryptedtext)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
decrypt_rsa_message(const unsigned char * encryptedtext,const int encryptedtext_len,EVP_PKEY * private_key,unsigned char ** plaintext)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
encode_auth_setting(const char * username,const char * password,EVP_PKEY * public_key,char ** authtoken)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
decode_auth_setting(int enable_debug,char * authtoken,EVP_PKEY * private_key,char ** username,char ** password,time_t * ts)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
iperf_getpass(char ** lineptr,size_t * n,FILE * stream)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