Home | History | Annotate | Download | only in libvncclient
      1 /*
      2  *  Copyright (C) 2012 Philip Van Hoof <philip (at) 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 
     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 
     78 static unsigned long id_function(void)
     79 {
     80 	return ((unsigned long) CURRENT_THREAD_ID);
     81 }
     82 
     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 
     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
    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
    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
    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
    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 
    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 
    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 *
    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
    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
    317 SetTLSAnonCredential(rfbClient* client)
    318 {
    319   rfbClientLog("TLS anonymous credential created.\n");
    320   return TRUE;
    321 }
    322 
    323 static rfbBool
    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
    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
    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
    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
    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
    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 
    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