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