1 /*
2 * Copyright (C) 2012 Philip Van Hoof <philip@codeminded.be>
3 * Copyright (C) 2009 Vic Lee.
4 *
5 * This is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this software; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 * USA.
19 */
20
21 #include <rfb/rfbclient.h>
22 #include <errno.h>
23
24 #include <openssl/err.h>
25 #include <openssl/ssl.h>
26 #include <openssl/x509.h>
27 #include <openssl/rand.h>
28 #include <openssl/x509.h>
29
30 #include <pthread.h>
31
32 #include "tls.h"
33
34 static rfbBool rfbTLSInitialized = FALSE;
35 static pthread_mutex_t *mutex_buf = NULL;
36
37 struct CRYPTO_dynlock_value {
38 pthread_mutex_t mutex;
39 };
40
locking_function(int mode,int n,const char * file,int line)41 static void locking_function(int mode, int n, const char *file, int line)
42 {
43 if (mode & CRYPTO_LOCK)
44 pthread_mutex_lock(&mutex_buf[n]);
45 else
46 pthread_mutex_unlock(&mutex_buf[n]);
47 }
48
id_function(void)49 static unsigned long id_function(void)
50 {
51 return ((unsigned long) pthread_self());
52 }
53
dyn_create_function(const char * file,int line)54 static struct CRYPTO_dynlock_value *dyn_create_function(const char *file, int line)
55 {
56 struct CRYPTO_dynlock_value *value;
57
58 value = (struct CRYPTO_dynlock_value *)
59 malloc(sizeof(struct CRYPTO_dynlock_value));
60 if (!value)
61 goto err;
62 pthread_mutex_init(&value->mutex, NULL);
63
64 return value;
65
66 err:
67 return (NULL);
68 }
69
dyn_lock_function(int mode,struct CRYPTO_dynlock_value * l,const char * file,int line)70 static void dyn_lock_function (int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
71 {
72 if (mode & CRYPTO_LOCK)
73 pthread_mutex_lock(&l->mutex);
74 else
75 pthread_mutex_unlock(&l->mutex);
76 }
77
78
79 static void
dyn_destroy_function(struct CRYPTO_dynlock_value * l,const char * file,int line)80 dyn_destroy_function(struct CRYPTO_dynlock_value *l, const char *file, int line)
81 {
82 pthread_mutex_destroy(&l->mutex);
83 free(l);
84 }
85
86
87 static int
ssl_errno(SSL * ssl,int ret)88 ssl_errno (SSL *ssl, int ret)
89 {
90 switch (SSL_get_error (ssl, ret)) {
91 case SSL_ERROR_NONE:
92 return 0;
93 case SSL_ERROR_ZERO_RETURN:
94 /* this one does not map well at all */
95 //d(printf ("ssl_errno: SSL_ERROR_ZERO_RETURN\n"));
96 return EINVAL;
97 case SSL_ERROR_WANT_READ: /* non-fatal; retry */
98 case SSL_ERROR_WANT_WRITE: /* non-fatal; retry */
99 //d(printf ("ssl_errno: SSL_ERROR_WANT_[READ,WRITE]\n"));
100 return EAGAIN;
101 case SSL_ERROR_SYSCALL:
102 //d(printf ("ssl_errno: SSL_ERROR_SYSCALL\n"));
103 return EINTR;
104 case SSL_ERROR_SSL:
105 //d(printf ("ssl_errno: SSL_ERROR_SSL <-- very useful error...riiiiight\n"));
106 return EINTR;
107 default:
108 //d(printf ("ssl_errno: default error\n"));
109 return EINTR;
110 }
111 }
112
113 static rfbBool
InitializeTLS(void)114 InitializeTLS(void)
115 {
116 int i;
117
118 if (rfbTLSInitialized) return TRUE;
119
120 mutex_buf = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
121 if (mutex_buf == NULL) {
122 rfbClientLog("Failed to initialized OpenSSL: memory.\n");
123 return (-1);
124 }
125
126 for (i = 0; i < CRYPTO_num_locks(); i++)
127 pthread_mutex_init(&mutex_buf[i], NULL);
128
129 CRYPTO_set_locking_callback(locking_function);
130 CRYPTO_set_id_callback(id_function);
131 CRYPTO_set_dynlock_create_callback(dyn_create_function);
132 CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
133 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
134 SSL_load_error_strings();
135 SSLeay_add_ssl_algorithms();
136 RAND_load_file("/dev/urandom", 1024);
137
138 rfbClientLog("OpenSSL initialized.\n");
139 rfbTLSInitialized = TRUE;
140 return TRUE;
141 }
142
143 static int
ssl_verify(int ok,X509_STORE_CTX * ctx)144 ssl_verify (int ok, X509_STORE_CTX *ctx)
145 {
146 unsigned char md5sum[16], fingerprint[40], *f;
147 rfbClient *client;
148 char *prompt, *cert_str;
149 int err, i;
150 unsigned int md5len;
151 //char buf[257];
152 X509 *cert;
153 SSL *ssl;
154
155 if (ok)
156 return TRUE;
157
158 ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ());
159
160 client = SSL_CTX_get_app_data (ssl->ctx);
161
162 cert = X509_STORE_CTX_get_current_cert (ctx);
163 err = X509_STORE_CTX_get_error (ctx);
164
165 /* calculate the MD5 hash of the raw certificate */
166 md5len = sizeof (md5sum);
167 X509_digest (cert, EVP_md5 (), md5sum, &md5len);
168 for (i = 0, f = fingerprint; i < 16; i++, f += 3)
169 sprintf ((char *) f, "%.2x%c", md5sum[i], i != 15 ? ':' : '\0');
170
171 #define GET_STRING(name) X509_NAME_oneline (name, buf, 256)
172
173 /* TODO: Don't just ignore certificate checks
174
175 fingerprint = key to check in db
176
177 GET_STRING (X509_get_issuer_name (cert));
178 GET_STRING (X509_get_subject_name (cert));
179 cert->valid (bool: GOOD or BAD) */
180
181 ok = TRUE;
182
183 return ok;
184 }
185
sock_read_ready(SSL * ssl,uint32_t ms)186 static int sock_read_ready(SSL *ssl, uint32_t ms)
187 {
188 int r = 0;
189 fd_set fds;
190 struct timeval tv;
191
192 FD_ZERO(&fds);
193
194 FD_SET(SSL_get_fd(ssl), &fds);
195
196 tv.tv_sec = ms / 1000;
197 tv.tv_usec = (ms % 1000) * ms;
198
199 r = select (SSL_get_fd(ssl) + 1, &fds, NULL, NULL, &tv);
200
201 return r;
202 }
203
wait_for_data(SSL * ssl,int ret,int timeout)204 static int wait_for_data(SSL *ssl, int ret, int timeout)
205 {
206 struct timeval tv;
207 fd_set fds;
208 int err;
209 int retval = 1;
210
211 err = SSL_get_error(ssl, ret);
212
213 switch(err)
214 {
215 case SSL_ERROR_WANT_READ:
216 case SSL_ERROR_WANT_WRITE:
217 ret = sock_read_ready(ssl, timeout*1000);
218
219 if (ret == -1) {
220 retval = 2;
221 }
222
223 break;
224 default:
225 retval = 3;
226 break;
227 }
228
229 ERR_clear_error();
230
231 return retval;
232 }
233
234 static SSL *
open_ssl_connection(rfbClient * client,int sockfd,rfbBool anonTLS)235 open_ssl_connection (rfbClient *client, int sockfd, rfbBool anonTLS)
236 {
237 SSL_CTX *ssl_ctx = NULL;
238 SSL *ssl = NULL;
239 int n, finished = 0;
240 BIO *sbio;
241
242 ssl_ctx = SSL_CTX_new (SSLv23_client_method ());
243 SSL_CTX_set_default_verify_paths (ssl_ctx);
244 SSL_CTX_set_verify (ssl_ctx, SSL_VERIFY_NONE, &ssl_verify);
245 ssl = SSL_new (ssl_ctx);
246
247 /* TODO: finetune this list, take into account anonTLS bool */
248 SSL_set_cipher_list(ssl, "ALL");
249
250 SSL_set_fd (ssl, sockfd);
251 SSL_CTX_set_app_data (ssl_ctx, client);
252
253 do
254 {
255 n = SSL_connect(ssl);
256
257 if (n != 1)
258 {
259 if (wait_for_data(ssl, n, 1) != 1)
260 {
261 finished = 1;
262 if (ssl->ctx)
263 SSL_CTX_free (ssl->ctx);
264 SSL_free(ssl);
265 SSL_shutdown (ssl);
266
267 return NULL;
268 }
269 }
270 } while( n != 1 && finished != 1 );
271
272 return ssl;
273 }
274
275
276 static rfbBool
InitializeTLSSession(rfbClient * client,rfbBool anonTLS)277 InitializeTLSSession(rfbClient* client, rfbBool anonTLS)
278 {
279 int ret;
280
281 if (client->tlsSession) return TRUE;
282
283 client->tlsSession = open_ssl_connection (client, client->sock, anonTLS);
284
285 if (!client->tlsSession)
286 return FALSE;
287
288 rfbClientLog("TLS session initialized.\n");
289
290 return TRUE;
291 }
292
293 static rfbBool
SetTLSAnonCredential(rfbClient * client)294 SetTLSAnonCredential(rfbClient* client)
295 {
296 rfbClientLog("TLS anonymous credential created.\n");
297 return TRUE;
298 }
299
300 static rfbBool
HandshakeTLS(rfbClient * client)301 HandshakeTLS(rfbClient* client)
302 {
303 int timeout = 15;
304 int ret;
305
306 return TRUE;
307
308 while (timeout > 0 && (ret = SSL_do_handshake(client->tlsSession)) < 0)
309 {
310 if (ret != -1)
311 {
312 rfbClientLog("TLS handshake blocking.\n");
313 sleep(1);
314 timeout--;
315 continue;
316 }
317 rfbClientLog("TLS handshake failed: -.\n");
318 FreeTLS(client);
319 return FALSE;
320 }
321
322 if (timeout <= 0)
323 {
324 rfbClientLog("TLS handshake timeout.\n");
325 FreeTLS(client);
326 return FALSE;
327 }
328
329 rfbClientLog("TLS handshake done.\n");
330 return TRUE;
331 }
332
333 /* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */
334 static rfbBool
ReadVeNCryptSecurityType(rfbClient * client,uint32_t * result)335 ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result)
336 {
337 uint8_t count=0;
338 uint8_t loop=0;
339 uint8_t flag=0;
340 uint32_t tAuth[256], t;
341 char buf1[500],buf2[10];
342 uint32_t authScheme;
343
344 if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE;
345
346 if (count==0)
347 {
348 rfbClientLog("List of security types is ZERO. Giving up.\n");
349 return FALSE;
350 }
351
352 if (count>sizeof(tAuth))
353 {
354 rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth));
355 return FALSE;
356 }
357
358 rfbClientLog("We have %d security types to read\n", count);
359 authScheme=0;
360 /* now, we have a list of available security types to read ( uint8_t[] ) */
361 for (loop=0;loop<count;loop++)
362 {
363 if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 4)) return FALSE;
364 t=rfbClientSwap32IfLE(tAuth[loop]);
365 rfbClientLog("%d) Received security type %d\n", loop, t);
366 if (flag) continue;
367 if (t==rfbVeNCryptTLSNone ||
368 t==rfbVeNCryptTLSVNC ||
369 t==rfbVeNCryptTLSPlain ||
370 t==rfbVeNCryptX509None ||
371 t==rfbVeNCryptX509VNC ||
372 t==rfbVeNCryptX509Plain)
373 {
374 flag++;
375 authScheme=t;
376 rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
377 /* send back 4 bytes (in original byte order!) indicating which security type to use */
378 if (!WriteToRFBServer(client, (char *)&tAuth[loop], 4)) return FALSE;
379 }
380 tAuth[loop]=t;
381 }
382 if (authScheme==0)
383 {
384 memset(buf1, 0, sizeof(buf1));
385 for (loop=0;loop<count;loop++)
386 {
387 if (strlen(buf1)>=sizeof(buf1)-1) break;
388 snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]);
389 strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1);
390 }
391 rfbClientLog("Unknown VeNCrypt authentication scheme from VNC server: %s\n",
392 buf1);
393 return FALSE;
394 }
395 *result = authScheme;
396 return TRUE;
397 }
398
399 rfbBool
HandleAnonTLSAuth(rfbClient * client)400 HandleAnonTLSAuth(rfbClient* client)
401 {
402 if (!InitializeTLS() || !InitializeTLSSession(client, TRUE)) return FALSE;
403
404 if (!SetTLSAnonCredential(client)) return FALSE;
405
406 if (!HandshakeTLS(client)) return FALSE;
407
408 return TRUE;
409 }
410
411 rfbBool
HandleVeNCryptAuth(rfbClient * client)412 HandleVeNCryptAuth(rfbClient* client)
413 {
414 uint8_t major, minor, status;
415 uint32_t authScheme;
416 rfbBool anonTLS;
417 // gnutls_certificate_credentials_t x509_cred = NULL;
418 int ret;
419
420 if (!InitializeTLS()) return FALSE;
421
422 /* Read VeNCrypt version */
423 if (!ReadFromRFBServer(client, (char *)&major, 1) ||
424 !ReadFromRFBServer(client, (char *)&minor, 1))
425 {
426 return FALSE;
427 }
428 rfbClientLog("Got VeNCrypt version %d.%d from server.\n", (int)major, (int)minor);
429
430 if (major != 0 && minor != 2)
431 {
432 rfbClientLog("Unsupported VeNCrypt version.\n");
433 return FALSE;
434 }
435
436 if (!WriteToRFBServer(client, (char *)&major, 1) ||
437 !WriteToRFBServer(client, (char *)&minor, 1) ||
438 !ReadFromRFBServer(client, (char *)&status, 1))
439 {
440 return FALSE;
441 }
442
443 if (status != 0)
444 {
445 rfbClientLog("Server refused VeNCrypt version %d.%d.\n", (int)major, (int)minor);
446 return FALSE;
447 }
448
449 if (!ReadVeNCryptSecurityType(client, &authScheme)) return FALSE;
450 if (!ReadFromRFBServer(client, (char *)&status, 1) || status != 1)
451 {
452 rfbClientLog("Server refused VeNCrypt authentication %d (%d).\n", authScheme, (int)status);
453 return FALSE;
454 }
455 client->subAuthScheme = authScheme;
456
457 /* Some VeNCrypt security types are anonymous TLS, others are X509 */
458 switch (authScheme)
459 {
460 case rfbVeNCryptTLSNone:
461 case rfbVeNCryptTLSVNC:
462 case rfbVeNCryptTLSPlain:
463 anonTLS = TRUE;
464 break;
465 default:
466 anonTLS = FALSE;
467 break;
468 }
469
470 /* Get X509 Credentials if it's not anonymous */
471 if (!anonTLS)
472 {
473 rfbCredential *cred;
474
475 if (!client->GetCredential)
476 {
477 rfbClientLog("GetCredential callback is not set.\n");
478 return FALSE;
479 }
480 cred = client->GetCredential(client, rfbCredentialTypeX509);
481 if (!cred)
482 {
483 rfbClientLog("Reading credential failed\n");
484 return FALSE;
485 }
486
487 /* TODO: don't just ignore this
488 x509_cred = CreateX509CertCredential(cred);
489 FreeX509Credential(cred);
490 if (!x509_cred) return FALSE; */
491 }
492
493 /* Start up the TLS session */
494 if (!InitializeTLSSession(client, anonTLS)) return FALSE;
495
496 if (anonTLS)
497 {
498 if (!SetTLSAnonCredential(client)) return FALSE;
499 }
500 else
501 {
502 /* TODO: don't just ignore this
503 if ((ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0)
504 {
505 rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret));
506 FreeTLS(client); */
507 return FALSE;
508 // }
509 }
510
511 if (!HandshakeTLS(client)) return FALSE;
512
513 /* TODO: validate certificate */
514
515 /* We are done here. The caller should continue with client->subAuthScheme
516 * to do actual sub authentication.
517 */
518 return TRUE;
519 }
520
521 int
ReadFromTLS(rfbClient * client,char * out,unsigned int n)522 ReadFromTLS(rfbClient* client, char *out, unsigned int n)
523 {
524 ssize_t ret;
525
526 ret = SSL_read (client->tlsSession, out, n);
527
528 if (ret >= 0)
529 return ret;
530 else {
531 errno = ssl_errno (client->tlsSession, ret);
532
533 if (errno != EAGAIN) {
534 rfbClientLog("Error reading from TLS: -.\n");
535 }
536 }
537
538 return -1;
539 }
540
541 int
WriteToTLS(rfbClient * client,char * buf,unsigned int n)542 WriteToTLS(rfbClient* client, char *buf, unsigned int n)
543 {
544 unsigned int offset = 0;
545 ssize_t ret;
546
547 while (offset < n)
548 {
549
550 ret = SSL_write (client->tlsSession, buf + offset, (size_t)(n-offset));
551
552 if (ret < 0)
553 errno = ssl_errno (client->tlsSession, ret);
554
555 if (ret == 0) continue;
556 if (ret < 0)
557 {
558 if (errno == EAGAIN || errno == EWOULDBLOCK) continue;
559 rfbClientLog("Error writing to TLS: -\n");
560 return -1;
561 }
562 offset += (unsigned int)ret;
563 }
564 return offset;
565 }
566
FreeTLS(rfbClient * client)567 void FreeTLS(rfbClient* client)
568 {
569 int i;
570
571 if (mutex_buf != NULL) {
572 CRYPTO_set_dynlock_create_callback(NULL);
573 CRYPTO_set_dynlock_lock_callback(NULL);
574 CRYPTO_set_dynlock_destroy_callback(NULL);
575
576 CRYPTO_set_locking_callback(NULL);
577 CRYPTO_set_id_callback(NULL);
578
579 for (i = 0; i < CRYPTO_num_locks(); i++)
580 pthread_mutex_destroy(&mutex_buf[i]);
581 free(mutex_buf);
582 mutex_buf = NULL;
583 }
584
585 SSL_free(client->tlsSession);
586 }
587
588