[pve-devel] r5407 - vncterm/pve2/vncpatches

svn-commits at proxmox.com svn-commits at proxmox.com
Fri Jan 21 08:31:10 CET 2011


Author: dietmar
Date: 2011-01-21 08:31:10 +0100 (Fri, 21 Jan 2011)
New Revision: 5407

Modified:
   vncterm/pve2/vncpatches/patch2.diff
Log:


Modified: vncterm/pve2/vncpatches/patch2.diff
===================================================================
--- vncterm/pve2/vncpatches/patch2.diff	2011-01-20 16:05:50 UTC (rev 5406)
+++ vncterm/pve2/vncpatches/patch2.diff	2011-01-21 07:31:10 UTC (rev 5407)
@@ -32,14 +32,75 @@
 Index: vnc/newterm/vncterm.c
 ===================================================================
 --- vnc.orig/newterm/vncterm.c	2011-01-20 13:41:18.000000000 +0100
-+++ vnc/newterm/vncterm.c	2011-01-20 17:05:31.000000000 +0100
-@@ -37,6 +37,94 @@
++++ vnc/newterm/vncterm.c	2011-01-21 08:29:20.000000000 +0100
+@@ -37,6 +37,170 @@
  #include "vncterm.h"
  #include "glyphs.h"
  
 +#include <gnutls/gnutls.h>
 +#include <gnutls/x509.h>
 +
++char *auth_path = "/";
++
++/* launch expernal script to verify credential */
++int 
++pve_auth_verify(const char *username, const char *passwd)
++{
++	sigset_t oldmask, mask;
++	int pid, status;
++	char *args[4];
++	char **parg;
++	char *env[2];
++	char **penv;
++
++	char pwenv[1024];
++
++	sprintf(pwenv, "PVE_PW_TICKET=%s", passwd);
++
++	const char *script ="/usr/bin/pve-authhelper";
++
++	sigemptyset(&mask);
++	sigaddset(&mask, SIGCHLD);
++	sigprocmask(SIG_BLOCK, &mask, &oldmask);
++
++	/* try to launch pve authentification helper */
++	pid = fork();
++	if (pid == 0) {
++		int open_max = sysconf(_SC_OPEN_MAX), i;
++
++		for (i = 0; i < open_max; i++) {
++			if (i != STDIN_FILENO &&
++			    i != STDOUT_FILENO &&
++			    i != STDERR_FILENO) {
++				close(i);
++			}
++		}
++		parg = args;
++		*parg++ = (char *)script;
++		*parg++ = (char *)auth_path;
++		*parg++ = (char *)username;
++		*parg = NULL;
++		penv = env;
++		*penv++ = (char *)pwenv;
++		*penv = NULL;
++		execve(script, args, env);
++		_exit(1);
++	} else if (pid > 0) {
++		while (waitpid(pid, &status, 0) != pid) {
++			/* loop */
++		}
++		sigprocmask(SIG_SETMASK, &oldmask, NULL);
++
++		if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
++			return 0;
++		}
++	}
++
++	rfbLog("could not launch auth script %s\n", script);
++
++	return -1;
++}
++
 +#ifdef DEBUG
 +static void vnc_debug_gnutls_log(int level, const char* str) {
 +	fprintf(stderr, "%d %s", level, str);
@@ -64,7 +125,6 @@
 +
 +retry:
 +	n = send(cl->sock, data, len, 0);
-+	//fixme: is that safe?
 +	if (n < 0) {
 +		if (errno == EINTR)
 +			goto retry;
@@ -92,7 +152,7 @@
 +	return n;
 +}
 +
-+ssize_t my_tls_read(rfbClientPtr cl, void *buf, size_t count)
++ssize_t vnc_tls_read(rfbClientPtr cl, void *buf, size_t count)
 +{
 +	rfbLog("my_tls_read\n");
 +	tls_client_t *sd = (tls_client_t *)cl->clientData;
@@ -108,7 +168,23 @@
 +
 +	return ret;
 +}
++ssize_t vnc_tls_write(rfbClientPtr cl, void *buf, size_t count)
++{
++	rfbLog("my_tls_write\n");
++	tls_client_t *sd = (tls_client_t *)cl->clientData;
 +
++        int ret = gnutls_write(sd->session, buf, count);
++        if (ret < 0) {
++		if (ret == GNUTLS_E_AGAIN)
++			errno = EAGAIN;
++		else
++			errno = EIO;
++		ret = -1;
++        }
++
++	return ret;
++}
++
 +static gnutls_anon_server_credentials
 +tls_initialize_anon_cred(void)
 +{
@@ -128,7 +204,7 @@
  /* define this for debugging */
  //#define DEBUG
  
-@@ -45,10 +133,183 @@
+@@ -45,10 +209,275 @@
  #define rfbSecTypeVencrypt  19
  #define rfbVencryptTlsPlain 259
  
@@ -146,6 +222,77 @@
 +		(data[offset + 2] << 8) | data[offset + 3]);
 +}
 +
++static void
++vencrypt_subauth_plain(rfbClientPtr cl)
++{
++	const char *err = NULL;
++	char buf[4096];
++	int n;
++
++	if ((n = rfbReadExact(cl, buf, 8)) <= 0) {
++		err = n ? "read failed" : "client gone";
++		goto err;
++	}
++
++	uint32_t ulen = rfbDecodeU32(buf, 0);
++	uint32_t pwlen = rfbDecodeU32(buf, 4);
++
++	if (!ulen) {
++		err = "No User name.";
++		goto err;
++	}
++	if (ulen >= 255) {
++		err = "User name too long.";
++		goto err;
++	}
++	if (!pwlen) {
++		err = "Password too short";
++		goto err;
++	}
++	if (pwlen >= 511) {
++		err = "Password too long.";
++		goto err;
++	}
++
++	if ((n = rfbReadExact(cl, buf, ulen)) <= 0) {
++		err = n ? "read failed" : "client gone";
++		goto err;
++	}
++	buf[ulen] = 0;
++	char *username = buf;
++	char *passwd = buf + ulen + 1;
++	if ((n = rfbReadExact(cl, passwd, pwlen)) <= 0) {
++		err = n ? "read failed" : "client gone";
++		goto err;
++	}
++	passwd[pwlen] = 0;
++
++	rfbLog("VencryptPlain: username: %s pw: %s\n", username, passwd);
++
++	if (pve_auth_verify(username, passwd) == 0) {
++		rfbEncodeU32(buf, 0); /* Accept auth completion */
++		rfbWriteExact(cl, buf, 4);
++		cl->state = RFB_INITIALISATION;
++		return;
++	}
++
++	err = "Authentication failed";
++err:
++	rfbLog("VencryptPlain: %s\n", err ? err : "no reason specified");
++	if (err) {
++		rfbEncodeU32(buf, 1); /* Reject auth */
++		rfbWriteExact(cl, buf, 4);
++		if (cl->protocolMinorVersion >= 8) {
++			int elen = strlen(err);
++			rfbEncodeU32(buf, elen); 
++			rfbWriteExact(cl, buf, 4);
++			rfbWriteExact(cl, err, elen);
++		}
++	}
++	rfbCloseClient(cl);
++	return;
++}
++
  static void
  rfbVncAuthVencrypt(rfbClientPtr cl)
  {
@@ -163,7 +310,7 @@
 +            rfbCloseClient(cl);
 +            return;
 +	}
- 
++
 +	printf("TEST2\n");
 +	int n = rfbReadExact(cl, buf, 2);
 +	if (n <= 0) {
@@ -197,7 +344,7 @@
 +		rfbCloseClient(cl);
 +		return;
 +	}
-+
+ 
 +	printf("TEST5\n");
 +	n = rfbReadExact(cl, buf, 4);
 +	if (n <= 0) {
@@ -230,47 +377,76 @@
 +
 +
 +	tls_client_t *sd = calloc(1, sizeof(tls_client_t));
-+	cl->clientData = sd;
 +
 +	if (sd->session == NULL) {
 +		if (gnutls_init(&sd->session, GNUTLS_SERVER) < 0) {
-+			fprintf(stderr, "gnutls_init FAILED");
-+			exit(-1); //fixme
++			rfbLog("gnutls_init failed\n");
++			rfbCloseClient(cl);
++			return;
++			
 +		}
 +
-+		if (gnutls_set_default_priority(sd->session) < 0) {
-+			fprintf(stderr, "gnutls_set_default_priority FAILED");
-+			exit(-1); //fixme
++		if ((ret = gnutls_set_default_priority(sd->session)) < 0) {
++			rfbLog("gnutls_set_default_priority failed: %s\n", gnutls_strerror(ret));
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;
 +		}
 +
++		/* optimize for speed */
++		static const int cipher_priority_performance[] = { 
++			GNUTLS_CIPHER_ARCFOUR_128, 
++			GNUTLS_CIPHER_AES_128_CBC, 
++			GNUTLS_CIPHER_3DES_CBC, 0 
++		};
++
++		if ((ret = gnutls_cipher_set_priority(sd->session, cipher_priority_performance)) < 0) {
++			rfbLog("gnutls_cipher_set_priority failed: %s\n", gnutls_strerror(ret));
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;			
++		}
++
 +		static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
-+		if (gnutls_kx_set_priority(sd->session, kx_anon) < 0) {
-+			fprintf(stderr, "gnutls_kx_set_priority FAILED");
-+			exit(-1); //fixme
++		if ((ret = gnutls_kx_set_priority(sd->session, kx_anon)) < 0) {
++			rfbLog("gnutls_kx_set_priority failed: %s\n", gnutls_strerror(ret));
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;			
 +		}
 +
 +		static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
-+		if (gnutls_certificate_type_set_priority(sd->session, cert_type_priority) < 0) {
-+			fprintf(stderr, "gnutls_certificate_type_set_priority FAILED");
-+			exit(-1); //fixme
++		if ((ret = gnutls_certificate_type_set_priority(sd->session, cert_type_priority)) < 0) {
++			rfbLog("gnutls_certificate_type_set_priority failed: %s\n", 
++			       gnutls_strerror(ret));
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;			
 +		}
 +
 +		static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
-+		if (gnutls_protocol_set_priority(sd->session, protocol_priority) < 0) {
-+			fprintf(stderr, "gnutls_protocol_set_priority FAILED");
-+			exit(-1); //fixme
++		if ((ret = gnutls_protocol_set_priority(sd->session, protocol_priority)) < 0) {
++			rfbLog("gnutls_protocol_set_priority failed: %s\n",
++			       gnutls_strerror(ret));
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;			
 +		}
 +
 +		gnutls_anon_server_credentials anon_cred;
 +
 +		if (!(anon_cred = tls_initialize_anon_cred())) {
-+			exit(-1); //fixme
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;			
 +		}
 +
-+		if (gnutls_credentials_set(sd->session, GNUTLS_CRD_ANON, anon_cred) < 0) {
-+			fprintf(stderr, "gnutls_credentials_set FAILED");
++		if ((ret = gnutls_credentials_set(sd->session, GNUTLS_CRD_ANON, anon_cred)) < 0) {
++			rfbLog("gnutls_credentials_set failed: %s\n", gnutls_strerror(ret));
 +			gnutls_anon_free_server_credentials(anon_cred);
-+			exit(-1); //fixme
++			sd->session = NULL;
++			rfbCloseClient(cl);
++			return;			
 +		}
 +
 +		gnutls_transport_set_ptr(sd->session, (gnutls_transport_ptr_t)cl);
@@ -285,7 +461,7 @@
 +
 +	if ((ret = gnutls_handshake(sd->session)) < 0) {
 +		if (!gnutls_error_is_fatal(ret)) {
-+			usleep(10000);
++			usleep(100000);
 +			goto retry;
 +		}
 +		rfbLog("rfbVncAuthVencrypt: handshake failed\n");
@@ -293,26 +469,18 @@
 +		return;
 +	}
 +
-+	cl->sock_read_fn = &my_tls_read;
-+	
-+	/* start subauth - read plain password */
-+	n = rfbReadExact(cl, buf, 8);
-+	if (n <= 0) {
-+		if (n == 0)
-+			rfbLog("rfbVncAuthVencrypt: client gone\n");
-+		else
-+			rfbLogPerror("rfbVncAuthVencrypt: read");
-+		rfbCloseClient(cl);
-+		return;
-+	}
++	/* set up TLS read/write hooks */
++	cl->clientData = sd;
++	cl->sock_read_fn = &vnc_tls_read;
++	cl->sock_write_fn = &vnc_tls_write;
 +
-+	//fixme: read len, lew, id, pw
++	vencrypt_subauth_plain(cl);
 +
 +	printf("TEST end\n");
  }
  
  static rfbSecurityHandler VncSecurityHandlerVencrypt = {
-@@ -1759,6 +2020,21 @@
+@@ -1759,6 +2188,21 @@
    time_t elapsed, cur_time;
    struct winsize dimensions;
  
@@ -334,7 +502,7 @@
    for (i = 1; i < argc; i++) {
      if (!strcmp (argv[i], "-c")) {
        command = argv[i+1];
-@@ -1784,6 +2060,8 @@
+@@ -1784,6 +2228,8 @@
  
  #ifdef DEBUG
    rfbLogEnable (1);
@@ -346,7 +514,7 @@
 Index: vnc/libvncserver/sockets.c
 ===================================================================
 --- vnc.orig/libvncserver/sockets.c	2011-01-20 16:42:41.000000000 +0100
-+++ vnc/libvncserver/sockets.c	2011-01-20 16:47:59.000000000 +0100
++++ vnc/libvncserver/sockets.c	2011-01-21 06:32:42.000000000 +0100
 @@ -454,8 +454,12 @@
      fd_set fds;
      struct timeval tv;
@@ -361,24 +529,40 @@
  
          if (n > 0) {
  
+@@ -538,7 +542,10 @@
+ 
+     LOCK(cl->outputMutex);
+     while (len > 0) {
+-        n = write(sock, buf, len);
++	if (cl->sock_write_fn)
++	    n = cl->sock_write_fn(cl, buf, len);
++	else
++	    n = write(sock, buf, len);
+ 
+         if (n > 0) {
+ 
 Index: vnc/rfb/rfb.h
 ===================================================================
 --- vnc.orig/rfb/rfb.h	2011-01-20 16:36:06.000000000 +0100
-+++ vnc/rfb/rfb.h	2011-01-20 16:51:22.000000000 +0100
-@@ -397,6 +397,8 @@
++++ vnc/rfb/rfb.h	2011-01-21 06:44:22.000000000 +0100
+@@ -397,6 +397,9 @@
      struct _rfbStatList *Next;
  } rfbStatList;
  
 +typedef ssize_t (*sock_read_fn_t)(struct _rfbClientRec *cl, void *buf, size_t count);
++typedef ssize_t (*sock_write_fn_t)(struct _rfbClientRec *cl, const void *buf, size_t count);
 +
  typedef struct _rfbClientRec {
    
      /* back pointer to the screen */
-@@ -417,6 +419,7 @@
+@@ -417,6 +420,10 @@
      void* clientData;
      ClientGoneHookPtr clientGoneHook;
  
++    /* use to hook up TLS read/write */
 +    sock_read_fn_t sock_read_fn;
++    sock_read_fn_t sock_write_fn;
++
      SOCKET sock;
      char *host;
  



More information about the pve-devel mailing list