From 29990f0090754c722653aafd3fc6800cebc1584c Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Wed, 7 Oct 2009 11:01:55 +0800 Subject: Add MSLogon security type Signed-off-by: Vic Lee Signed-off-by: Johannes Schindelin --- libvncclient/rfbproto.c | 124 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 8 deletions(-) (limited to 'libvncclient') 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+y0;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 -- cgit v1.2.1