Re: [gtk-vnc-devel] Time for new release ...
- From: "Daniel P. Berrange" <berrange redhat com>
- To: Jonh Wendell <jwendell gnome org>
- Cc: gtk-vnc-devel <gtk-vnc-devel lists sourceforge net>
- Subject: Re: [gtk-vnc-devel] Time for new release ...
- Date: Fri, 28 Nov 2008 14:59:34 +0000
On Thu, Nov 27, 2008 at 12:46:52PM -0300, Jonh Wendell wrote:
> Em Qui, 2008-11-27 às 11:12 +0000, Daniel P. Berrange escreveu:
> > Jonh and I were talking on IRC the other day and think its time for a new
> > release so we can get people using the new Cairo based rendering code,
> > Windows portability, and (hopefully) fixed keyboard handling. Any
> > objections....
> >
> > Daniel
>
> How about the ms-logon patch? It could be added into this release.
I'm not entirely happy with the code license pedigree of the diffie-hellman
stuff in that patch. So here's a version that is re-written to be clean.
This is basically written based off the gnutls internal DH impl, in
lib/gnutls_dh.c which is explicitly LGPLv2+ licensed. It uses gcrypt
for its core functions.
NB, I don't have a windows server against which to test this code, so it
is quite possible I broke it when re-writing ....
Daniel
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,6 +20,7 @@ libgtk_vnc_1_0_la_SOURCES = blt.h blt1.h
libgtk_vnc_1_0_la_SOURCES = blt.h blt1.h \
coroutine.h \
d3des.h d3des.c \
+ dh.h dh.c \
gvnc.h gvnc.c \
vncdisplay.h vncdisplay.c \
vncmarshal.h vncmarshal.c \
diff --git a/src/dh.c b/src/dh.c
new file mode 100644
--- /dev/null
+++ b/src/dh.c
@@ -0,0 +1,135 @@
+/*
+ * GTK VNC Widget, Diffie Hellman
+ *
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * Derived from gnutls_dh.c, also under:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "dh.h"
+
+
+/*
+ * General plan, as per gnutls_dh.c
+ *
+ *
+ * VNC server: X = g ^ x mod p;
+ * VNC client: Y = g ^ y mod p;
+ *
+ * Server key = Y ^ x mod p;
+ * Client key = X ^ y mod p;
+ *
+ * Where
+ * g == gen
+ * p == mod
+ *
+ * y == priv
+ * Y == pub
+ * Client key == key
+ *
+ *
+ */
+
+struct gvnc_dh {
+ gcry_mpi_t gen; /* g */
+ gcry_mpi_t mod; /* p */
+
+ gcry_mpi_t priv; /* y */
+ gcry_mpi_t pub; /* Y = g ^ y mod p */
+
+ gcry_mpi_t key; /* X ^ y mod p */
+};
+
+#define GVNC_DH_MAX_BITS 31
+
+struct gvnc_dh *gvnc_dh_new(gcry_mpi_t gen, gcry_mpi_t mod)
+{
+ struct gvnc_dh *ret = g_new0(struct gvnc_dh, 1);
+
+ ret->gen = gcry_mpi_copy(gen);
+ ret->mod = gcry_mpi_copy(mod);
+
+ return ret;
+}
+
+
+gcry_mpi_t gvnc_dh_gen_secret(struct gvnc_dh *dh)
+{
+ if (!(dh->priv = gcry_mpi_new(GVNC_DH_MAX_BITS)))
+ abort();
+
+ do {
+ gcry_mpi_randomize (dh->priv, (GVNC_DH_MAX_BITS / 8) * 8, GCRY_STRONG_RANDOM);
+ } while (gcry_mpi_cmp_ui (dh->priv, 0) == 0);
+
+ if (!(dh->pub = gcry_mpi_new(GVNC_DH_MAX_BITS)))
+ abort();
+
+ gcry_mpi_powm(dh->pub, dh->gen, dh->priv, dh->mod);
+
+ return dh->pub;
+}
+
+gcry_mpi_t gvnc_dh_gen_key(struct gvnc_dh *dh, gcry_mpi_t inter)
+{
+ if (!(dh->key = gcry_mpi_new(GVNC_DH_MAX_BITS)))
+ abort();
+
+ gcry_mpi_powm(dh->key, inter, dh->priv, dh->mod);
+
+ return dh->key;
+}
+
+void gvnc_dh_free(struct gvnc_dh *dh)
+{
+ if (dh->key)
+ gcry_mpi_release(dh->key);
+ if (dh->pub)
+ gcry_mpi_release(dh->pub);
+ if (dh->priv)
+ gcry_mpi_release(dh->priv);
+ if (dh->mod)
+ gcry_mpi_release(dh->mod);
+ if (dh->gen)
+ gcry_mpi_release(dh->gen);
+ g_free(dh);
+}
+
+void gvnc_mpi_to_bytes(const gcry_mpi_t value, guchar* const bytes)
+{
+ gcry_mpi_print(GCRYMPI_FMT_STD, bytes, sizeof(gint64), NULL, value);
+}
+
+gcry_mpi_t gvnc_bytes_to_mpi(const guchar* const bytes)
+{
+ gcry_mpi_t ret;
+
+ gcry_mpi_scan(&ret, GCRYMPI_FMT_STD, bytes, sizeof(gint64), NULL);
+
+ return NULL;
+}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/dh.h b/src/dh.h
new file mode 100644
--- /dev/null
+++ b/src/dh.h
@@ -0,0 +1,38 @@
+/*
+ * GTK VNC Widget, Diffie Hellman
+ *
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.0 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef GTK_VNC_DH_H__
+#define GTK_VNC_DH_H__
+
+#include <glib.h>
+#include <gcrypt.h>
+
+struct gvnc_dh;
+
+struct gvnc_dh *gvnc_dh_new(gcry_mpi_t prime, gcry_mpi_t generator);
+
+gcry_mpi_t gvnc_dh_gen_secret(struct gvnc_dh *dh);
+gcry_mpi_t gvnc_dh_gen_key(struct gvnc_dh *dh, gcry_mpi_t inter);
+void gvnc_dh_free(struct gvnc_dh *dh);
+
+void gvnc_mpi_to_bytes(const gcry_mpi_t value, guchar* const bytes);
+gcry_mpi_t gvnc_bytes_to_mpi(const guchar* const bytes);
+
+#endif
diff --git a/src/gvnc.c b/src/gvnc.c
--- a/src/gvnc.c
+++ b/src/gvnc.c
@@ -36,6 +36,10 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <zlib.h>
+#include <gdk/gdkkeysyms.h>
#include "coroutine.h"
#include "d3des.h"
@@ -43,13 +47,7 @@
#include "x_keymap.h"
#include "utils.h"
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
-
-#include <zlib.h>
-
-#include <gdk/gdkkeysyms.h>
-
+#include "dh.h"
#include "getaddrinfo.h"
/* AI_ADDRCONFIG is missing on some systems and gnulib won't provide it
@@ -2173,6 +2171,84 @@ static gboolean gvnc_perform_auth_vnc(st
}
+/*
+ * marscha 2006 - Martin Scharpf
+ * Encrypt bytes[length] in memory using key.
+ * Key has to be 8 bytes, length a multiple of 8 bytes.
+ */
+static void
+vncEncryptBytes2(unsigned char *where, const int length, unsigned char *key) {
+ int i, j;
+ deskey(key, EN0);
+ for (i = 0; i< 8; i++)
+ where[i] ^= key[i];
+ des(where, where);
+ for (i = 8; i < length; i += 8) {
+ for (j = 0; j < 8; j++)
+ where[i + j] ^= where[i + j - 8];
+ des(where + i, where + i);
+ }
+}
+
+static gboolean gvnc_perform_auth_mslogon(struct gvnc *gvnc)
+{
+ struct gvnc_dh *dh;
+ guchar gen[8], mod[8], resp[8], pub[8], key[8];
+ gcry_mpi_t genmpi, modmpi, respmpi, pubmpi, keympi;
+
+ guchar username[256], password[64];
+ guint passwordLen, usernameLen;
+
+ GVNC_DEBUG("Do Challenge\n");
+ if (!gvnc->cred_username)
+ return FALSE;
+ if (!gvnc->cred_password)
+ return FALSE;
+
+ gvnc_read(gvnc, gen, sizeof(gen));
+ gvnc_read(gvnc, mod, sizeof(mod));
+ gvnc_read(gvnc, resp, sizeof(resp));
+
+ genmpi = gvnc_bytes_to_mpi(gen);
+ modmpi = gvnc_bytes_to_mpi(mod);
+ respmpi = gvnc_bytes_to_mpi(resp);
+
+ dh = gvnc_dh_new(genmpi, modmpi);
+
+ pubmpi = gvnc_dh_gen_secret(dh);
+ gvnc_mpi_to_bytes(pubmpi, pub);
+ gvnc_write(gvnc, pub, sizeof(pub));
+
+ keympi = gvnc_dh_gen_key(dh, respmpi);
+ gvnc_mpi_to_bytes(keympi, key);
+
+ passwordLen = strlen(gvnc->cred_password);
+ usernameLen = strlen(gvnc->cred_username);
+ if (passwordLen > sizeof(password))
+ passwordLen = sizeof(password);
+ if (usernameLen > sizeof(username))
+ usernameLen = sizeof(username);
+
+ memset(password, 0, sizeof password);
+ memset(username, 0, sizeof username);
+ memcpy(password, gvnc->cred_password, passwordLen);
+ memcpy(username, gvnc->cred_username, usernameLen);
+
+ vncEncryptBytes2(username, sizeof(username), key);
+ vncEncryptBytes2(password, sizeof(password), key);
+
+ gvnc_write(gvnc, username, sizeof(username));
+ gvnc_write(gvnc, password, sizeof(password));
+ gvnc_flush(gvnc);
+
+ gcry_mpi_release(genmpi);
+ gcry_mpi_release(modmpi);
+ gcry_mpi_release(respmpi);
+ gvnc_dh_free (dh);
+
+ return gvnc_check_auth_result(gvnc);
+}
+
static gboolean gvnc_start_tls(struct gvnc *gvnc, int anonTLS)
{
static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
@@ -2297,6 +2373,9 @@ gboolean gvnc_wants_credential_password(
return TRUE;
}
+ if (gvnc->auth_type == GVNC_AUTH_MSLOGON)
+ return TRUE;
+
return FALSE;
}
@@ -2308,6 +2387,9 @@ gboolean gvnc_wants_credential_username(
gvnc->auth_subtype == GVNC_AUTH_VENCRYPT_X509PLAIN)
return TRUE;
}
+
+ if (gvnc->auth_type == GVNC_AUTH_MSLOGON)
+ return TRUE;
return FALSE;
}
@@ -2626,6 +2708,9 @@ static gboolean gvnc_perform_auth(struct
case GVNC_AUTH_VENCRYPT:
return gvnc_perform_auth_vencrypt(gvnc);
+ case GVNC_AUTH_MSLOGON:
+ return gvnc_perform_auth_mslogon(gvnc);
+
default:
if (gvnc->ops.auth_unsupported)
gvnc->ops.auth_unsupported (gvnc->ops_data, gvnc->auth_type);
@@ -2994,6 +3079,7 @@ gboolean gvnc_set_auth_type(struct gvnc
}
if (type != GVNC_AUTH_NONE &&
type != GVNC_AUTH_VNC &&
+ type != GVNC_AUTH_MSLOGON &&
type != GVNC_AUTH_TLS &&
type != GVNC_AUTH_VENCRYPT) {
if (gvnc->ops.auth_unsupported)
diff --git a/src/gvnc.h b/src/gvnc.h
--- a/src/gvnc.h
+++ b/src/gvnc.h
@@ -128,7 +128,8 @@ typedef enum {
GVNC_AUTH_TIGHT = 16,
GVNC_AUTH_ULTRA = 17,
GVNC_AUTH_TLS = 18, /* Used by VINO */
- GVNC_AUTH_VENCRYPT = 19 /* Used by VeNCrypt and QEMU */
+ GVNC_AUTH_VENCRYPT = 19, /* Used by VeNCrypt and QEMU */
+ GVNC_AUTH_MSLOGON = 0xfffffffa, /* Used by UltraVNC */
} gvnc_auth;
typedef enum {
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -1861,6 +1861,7 @@ static void vnc_display_init(VncDisplay
priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_VENCRYPT));
priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_TLS));
+ priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_MSLOGON));
priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_VNC));
priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_NONE));
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
[
Date Prev][Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]