summaryrefslogtreecommitdiffstats
path: root/libvncclient/rfbproto.c
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 /libvncclient/rfbproto.c
parent95ae56c83110c35bce9752d18975b6edcd8088b9 (diff)
downloadlibvncserver-29990f0090754c722653aafd3fc6800cebc1584c.zip
libvncserver-29990f0090754c722653aafd3fc6800cebc1584c.tar.gz
Add MSLogon security type
Signed-off-by: Vic Lee <llyzs@163.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Diffstat (limited to 'libvncclient/rfbproto.c')
-rw-r--r--libvncclient/rfbproto.c124
1 files changed, 116 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
OpenPOWER on IntegriCloud