LibVNCServer/LibVNCClient
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tls_openssl.c
Go to the documentation of this file.
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 
38  pthread_mutex_t mutex;
39 };
40 
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 
49 static unsigned long id_function(void)
50 {
51  return ((unsigned long) pthread_self());
52 }
53 
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 
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
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
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
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
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 
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 
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 *
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
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
294 SetTLSAnonCredential(rfbClient* client)
295 {
296  rfbClientLog("TLS anonymous credential created.\n");
297  return TRUE;
298 }
299 
300 static rfbBool
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
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 ||
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
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
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
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
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 
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