summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVic Lee <llyzs@163.com>2009-10-07 11:01:55 +0800
committerJohannes Schindelin <johannes.schindelin@gmx.de>2009-11-02 16:10:59 +0100
commit29990f0090754c722653aafd3fc6800cebc1584c (patch)
tree891066286999828e6170cddde6bc8bdaaae98496
parent95ae56c83110c35bce9752d18975b6edcd8088b9 (diff)
downloadlibtdevnc-29990f0090754c722653aafd3fc6800cebc1584c.tar.gz
libtdevnc-29990f0090754c722653aafd3fc6800cebc1584c.zip
Add MSLogon security type
Signed-off-by: Vic Lee <llyzs@163.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
-rw-r--r--libvncclient/rfbproto.c124
-rw-r--r--libvncserver/vncauth.c15
-rw-r--r--rfb/rfbclient.h10
-rw-r--r--rfb/rfbproto.h1
4 files changed, 142 insertions, 8 deletions
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index 497facb..7b53722 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -414,6 +414,7 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
}
extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd);
+extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key);
rfbBool
rfbHandleAuthResult(rfbClient* client)
@@ -503,7 +504,7 @@ ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth)
if (!ReadFromRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE;
rfbClientLog("%d) Received security type %d\n", loop, tAuth[loop]);
if (flag) continue;
- if (tAuth[loop]==rfbVncAuth || tAuth[loop]==rfbNoAuth ||
+ if (tAuth[loop]==rfbVncAuth || tAuth[loop]==rfbNoAuth || tAuth[loop]==rfbMSLogon ||
(!subAuth && (tAuth[loop]==rfbTLS || tAuth[loop]==rfbVeNCrypt)))
{
flag++;
@@ -569,6 +570,14 @@ HandleVncAuth(rfbClient *client)
return TRUE;
}
+static void
+FreeUserCredential(rfbCredential *cred)
+{
+ if (cred->userCredential.username) free(cred->userCredential.username);
+ if (cred->userCredential.password) free(cred->userCredential.password);
+ free(cred);
+}
+
static rfbBool
HandlePlainAuth(rfbClient *client)
{
@@ -592,20 +601,114 @@ HandlePlainAuth(rfbClient *client)
ulensw = rfbClientSwap32IfLE(ulen);
plen = (cred->userCredential.password ? strlen(cred->userCredential.password) : 0);
plensw = rfbClientSwap32IfLE(plen);
- if (!WriteToRFBServer(client, (char *)&ulensw, 4)) return FALSE;
- if (!WriteToRFBServer(client, (char *)&plensw, 4)) return FALSE;
+ if (!WriteToRFBServer(client, (char *)&ulensw, 4) ||
+ !WriteToRFBServer(client, (char *)&plensw, 4))
+ {
+ FreeUserCredential(cred);
+ return FALSE;
+ }
if (ulen > 0)
{
- if (!WriteToRFBServer(client, cred->userCredential.username, ulen)) return FALSE;
+ if (!WriteToRFBServer(client, cred->userCredential.username, ulen))
+ {
+ FreeUserCredential(cred);
+ return FALSE;
+ }
}
if (plen > 0)
{
- if (!WriteToRFBServer(client, cred->userCredential.password, plen)) return FALSE;
+ if (!WriteToRFBServer(client, cred->userCredential.password, plen))
+ {
+ FreeUserCredential(cred);
+ return FALSE;
+ }
}
- if (cred->userCredential.username) free(cred->userCredential.username);
- if (cred->userCredential.password) free(cred->userCredential.password);
- free(cred);
+ FreeUserCredential(cred);
+
+ /* Handle the SecurityResult message */
+ if (!rfbHandleAuthResult(client)) return FALSE;
+
+ return TRUE;
+}
+
+/* Simple 64bit big integer arithmetic implementation */
+/* (x + y) % m, works even if (x + y) > 64bit */
+#define rfbAddM64(x,y,m) ((x+y)%m+(x+y<x?(((uint64_t)-1)%m+1)%m:0))
+/* (x * y) % m */
+static uint64_t
+rfbMulM64(uint64_t x, uint64_t y, uint64_t m)
+{
+ uint64_t r;
+ for(r=0;x>0;x>>=1)
+ {
+ if (x&1) r=rfbAddM64(r,y,m);
+ y=rfbAddM64(y,y,m);
+ }
+ return r;
+}
+/* (x ^ y) % m */
+static uint64_t
+rfbPowM64(uint64_t b, uint64_t e, uint64_t m)
+{
+ uint64_t r;
+ for(r=1;e>0;e>>=1)
+ {
+ if(e&1) r=rfbMulM64(r,b,m);
+ b=rfbMulM64(b,b,m);
+ }
+ return r;
+}
+
+static rfbBool
+HandleMSLogonAuth(rfbClient *client)
+{
+ uint64_t gen, mod, resp, priv, pub, key;
+ uint8_t username[256], password[64];
+ rfbCredential *cred;
+
+ if (!ReadFromRFBServer(client, (char *)&gen, 8)) return FALSE;
+ if (!ReadFromRFBServer(client, (char *)&mod, 8)) return FALSE;
+ if (!ReadFromRFBServer(client, (char *)&resp, 8)) return FALSE;
+ gen = rfbClientSwap64IfLE(gen);
+ mod = rfbClientSwap64IfLE(mod);
+ resp = rfbClientSwap64IfLE(resp);
+
+ if (!client->GetCredential)
+ {
+ rfbClientLog("GetCredential callback is not set.\n");
+ return FALSE;
+ }
+ rfbClientLog("WARNING! MSLogon security type has very low password encryption! "\
+ "Use it only with SSH tunnel or trusted network.\n");
+ cred = client->GetCredential(client, rfbCredentialTypeUser);
+ if (!cred)
+ {
+ rfbClientLog("Reading credential failed\n");
+ return FALSE;
+ }
+
+ memset(username, 0, sizeof(username));
+ strncpy((char *)username, cred->userCredential.username, sizeof(username));
+ memset(password, 0, sizeof(password));
+ strncpy((char *)password, cred->userCredential.password, sizeof(password));
+ FreeUserCredential(cred);
+
+ srand(time(NULL));
+ priv = ((uint64_t)rand())<<32;
+ priv |= (uint64_t)rand();
+
+ pub = rfbPowM64(gen, priv, mod);
+ key = rfbPowM64(resp, priv, mod);
+ pub = rfbClientSwap64IfLE(pub);
+ key = rfbClientSwap64IfLE(key);
+
+ rfbClientEncryptBytes2(username, sizeof(username), (unsigned char *)&key);
+ rfbClientEncryptBytes2(password, sizeof(password), (unsigned char *)&key);
+
+ if (!WriteToRFBServer(client, (char *)&pub, 8)) return FALSE;
+ if (!WriteToRFBServer(client, (char *)username, sizeof(username))) return FALSE;
+ if (!WriteToRFBServer(client, (char *)password, sizeof(password))) return FALSE;
/* Handle the SecurityResult message */
if (!rfbHandleAuthResult(client)) return FALSE;
@@ -713,6 +816,10 @@ InitialiseRFBConnection(rfbClient* client)
if (!HandleVncAuth(client)) return FALSE;
break;
+ case rfbMSLogon:
+ if (!HandleMSLogonAuth(client)) return FALSE;
+ break;
+
case rfbTLS:
if (!HandleAnonTLSAuth(client)) return FALSE;
/* After the TLS session is established, sub auth types are expected.
@@ -1889,6 +1996,7 @@ PrintPixelFormat(rfbPixelFormat *format)
/* avoid name clashes with LibVNCServer */
#define rfbEncryptBytes rfbClientEncryptBytes
+#define rfbEncryptBytes2 rfbClientEncryptBytes2
#define rfbDes rfbClientDes
#define rfbDesKey rfbClientDesKey
#define rfbUseKey rfbClientUseKey
diff --git a/libvncserver/vncauth.c b/libvncserver/vncauth.c
index b8ee288..0b73531 100644
--- a/libvncserver/vncauth.c
+++ b/libvncserver/vncauth.c
@@ -191,3 +191,18 @@ rfbEncryptBytes(unsigned char *bytes, char *passwd)
rfbDes(bytes+i, bytes+i);
}
}
+
+void
+rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) {
+ int i, j;
+ rfbDesKey(key, EN0);
+ for (i = 0; i< 8; i++)
+ where[i] ^= key[i];
+ rfbDes(where, where);
+ for (i = 8; i < length; i += 8) {
+ for (j = 0; j < 8; j++)
+ where[i + j] ^= where[i + j - 8];
+ rfbDes(where + i, where + i);
+ }
+}
+
diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h
index c32168c..6d38c8f 100644
--- a/rfb/rfbclient.h
+++ b/rfb/rfbclient.h
@@ -46,6 +46,16 @@
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
+#define rfbClientSwap64IfLE(l) \
+ (*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \
+ (((l) & 0x00ff000000000000ULL) >> 40) | \
+ (((l) & 0x0000ff0000000000ULL) >> 24) | \
+ (((l) & 0x000000ff00000000ULL) >> 8) | \
+ (((l) & 0x00000000ff000000ULL) << 8) | \
+ (((l) & 0x0000000000ff0000ULL) << 24) | \
+ (((l) & 0x000000000000ff00ULL) << 40) | \
+ (((l) & 0x00000000000000ffULL) << 56)) : (l))
+
#define FLASH_PORT_OFFSET 5400
#define LISTEN_PORT_OFFSET 5500
#define TUNNEL_PORT_OFFSET 5500
diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h
index 06ab579..b6f201c 100644
--- a/rfb/rfbproto.h
+++ b/rfb/rfbproto.h
@@ -265,6 +265,7 @@ typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
#define rfbUltra 17
#define rfbTLS 18
#define rfbVeNCrypt 19
+#define rfbMSLogon 0xfffffffa
#define rfbVeNCryptPlain 256
#define rfbVeNCryptTLSNone 257