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