summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libvncclient/rfbproto.c92
-rwxr-xr-xlibvncserver/auth.c8
-rw-r--r--libvncserver/rfbserver.c31
3 files changed, 86 insertions, 45 deletions
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index a7aab60..7572fd7 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -369,6 +369,47 @@ ConnectToRFBServer(rfbClient* client,const char *hostname, int port)
extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd);
+rfbBool
+rfbHandleAuthResult(rfbClient* client)
+{
+ uint32_t authResult=0, reasonLen=0;
+ char *reason=NULL;
+
+ if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE;
+
+ authResult = rfbClientSwap32IfLE(authResult);
+
+ switch (authResult) {
+ case rfbVncAuthOK:
+ rfbClientLog("VNC authentication succeeded\n");
+ return TRUE;
+ break;
+ case rfbVncAuthFailed:
+ if (client->major==3 && client->minor>7)
+ {
+ /* we have an error following */
+ if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
+ reasonLen = rfbClientSwap32IfLE(reasonLen);
+ reason = malloc(reasonLen+1);
+ if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
+ reason[reasonLen]=0;
+ rfbClientLog("VNC connection failed: %s\n",reason);
+ free(reason);
+ return FALSE;
+ }
+ rfbClientLog("VNC authentication failed\n");
+ return FALSE;
+ case rfbVncAuthTooMany:
+ rfbClientLog("VNC authentication failed - too many tries\n");
+ return FALSE;
+ }
+
+ rfbClientLog("Unknown VNC authentication result: %d\n",
+ (int)authResult);
+ return FALSE;
+}
+
+
/*
* InitialiseRFBConnection.
*/
@@ -378,7 +419,7 @@ InitialiseRFBConnection(rfbClient* client)
{
rfbProtocolVersionMsg pv;
int major,minor;
- uint32_t authScheme, reasonLen, authResult;
+ uint32_t authScheme, reasonLen;
char *reason;
uint8_t challenge[CHALLENGESIZE];
char *passwd=NULL;
@@ -453,9 +494,10 @@ InitialiseRFBConnection(rfbClient* client)
/* we have an error following */
if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
reasonLen = rfbClientSwap32IfLE(reasonLen);
- reason = malloc(reasonLen);
+ reason = malloc(reasonLen+1);
if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
- rfbClientLog("VNC connection failed: %.*s\n",(int)reasonLen, reason);
+ reason[reasonLen]=0;
+ rfbClientLog("VNC connection failed: %s\n",reason);
free(reason);
return FALSE;
}
@@ -473,6 +515,7 @@ InitialiseRFBConnection(rfbClient* client)
rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count);
/* send back a single byte indicating which security type to use */
if (!WriteToRFBServer(client, (char *)&tAuth, 1)) return FALSE;
+
}
}
}
@@ -490,16 +533,21 @@ InitialiseRFBConnection(rfbClient* client)
if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
reasonLen = rfbClientSwap32IfLE(reasonLen);
- reason = malloc(reasonLen);
+ reason = malloc(reasonLen+1);
if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
-
- rfbClientLog("VNC connection failed: %.*s\n",(int)reasonLen, reason);
+ reason[reasonLen]=0;
+ rfbClientLog("VNC connection failed: %s\n", reason);
free(reason);
return FALSE;
case rfbNoAuth:
rfbClientLog("No authentication needed\n");
+
+ /* 3.8 and upwards sends a Security Result for rfbNoAuth */
+ if (client->major==3 && client->minor > 7)
+ if (!rfbHandleAuthResult(client)) return FALSE;
+
break;
case rfbVncAuth:
@@ -528,36 +576,8 @@ InitialiseRFBConnection(rfbClient* client)
if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE;
}
- if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE;
-
- authResult = rfbClientSwap32IfLE(authResult);
-
- switch (authResult) {
- case rfbVncAuthOK:
- rfbClientLog("VNC authentication succeeded\n");
- break;
- case rfbVncAuthFailed:
- if (client->major==3 && client->minor>7)
- {
- /* we have an error following */
- if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE;
- reasonLen = rfbClientSwap32IfLE(reasonLen);
- reason = malloc(reasonLen);
- if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; }
- rfbClientLog("VNC connection failed: %.*s\n",(int)reasonLen, reason);
- free(reason);
- return FALSE;
- }
- rfbClientLog("VNC authentication failed\n");
- return FALSE;
- case rfbVncAuthTooMany:
- rfbClientLog("VNC authentication failed - too many tries\n");
- return FALSE;
- default:
- rfbClientLog("Unknown VNC authentication result: %d\n",
- (int)authResult);
- return FALSE;
- }
+ /* Handle the SecurityResult message */
+ if (!rfbHandleAuthResult(client)) return FALSE;
break;
default:
diff --git a/libvncserver/auth.c b/libvncserver/auth.c
index 642cca6..b8fbad6 100755
--- a/libvncserver/auth.c
+++ b/libvncserver/auth.c
@@ -29,6 +29,10 @@
#include <rfb/rfb.h>
+/* RFB 3.8 clients are well informed */
+void rfbClientSendString(rfbClientPtr cl, char *reason);
+
+
/*
* Handle security types
*/
@@ -207,7 +211,7 @@ rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
/* The execution should never reach here */
char* reason = "No authentication mode is registered!";
- rfbClientConnFailed(cl, reason);
+ rfbClientSendString(cl, reason);
return;
}
@@ -352,7 +356,7 @@ rfbAuthProcessClientMessage(rfbClientPtr cl)
}
/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
if (cl->protocolMinorVersion > 7) {
- rfbClientConnFailed(cl, "password check failed!");
+ rfbClientSendString(cl, "password check failed!");
}
else
rfbCloseClient(cl);
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index 57ba5d9..ae4877b 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -587,7 +587,6 @@ rfbProcessClientProtocolVersion(rfbClientPtr cl)
{
rfbProtocolVersionMsg pv;
int n, major_, minor_;
- char failureReason[256];
if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) {
if (n == 0)
@@ -612,14 +611,10 @@ rfbProcessClientProtocolVersion(rfbClientPtr cl)
rfbLog("Client Protocol Version %d.%d\n", major_, minor_);
if (major_ != rfbProtocolMajorVersion) {
- /* Major version mismatch - send a ConnFailed message */
-
- rfbErr("Major version mismatch\n");
- sprintf(failureReason,
- "RFB protocol version mismatch - server %d.%d, client %d.%d",
+ rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d",
cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion,
major_,minor_);
- rfbClientConnFailed(cl, failureReason);
+ rfbCloseClient(cl);
return;
}
@@ -641,6 +636,25 @@ rfbProcessClientProtocolVersion(rfbClientPtr cl)
}
+void
+rfbClientSendString(rfbClientPtr cl, char *reason)
+{
+ char *buf;
+ int len = strlen(reason);
+
+ rfbLog("rfbClientSendString(\"%s\")\n", reason);
+
+ buf = (char *)malloc(4 + len);
+ ((uint32_t *)buf)[0] = Swap32IfLE(len);
+ memcpy(buf + 4, reason, len);
+
+ if (rfbWriteExact(cl, buf, 4 + len) < 0)
+ rfbLogPerror("rfbClientSendString: write");
+ free(buf);
+
+ rfbCloseClient(cl);
+}
+
/*
* rfbClientConnFailed is called when a client connection has failed either
* because it talks the wrong protocol or it has failed authentication.
@@ -653,6 +667,8 @@ rfbClientConnFailed(rfbClientPtr cl,
char *buf;
int len = strlen(reason);
+ rfbLog("rfbClientConnFailed(\"%s\")\n", reason);
+
buf = (char *)malloc(8 + len);
((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed);
((uint32_t *)buf)[1] = Swap32IfLE(len);
@@ -661,6 +677,7 @@ rfbClientConnFailed(rfbClientPtr cl,
if (rfbWriteExact(cl, buf, 8 + len) < 0)
rfbLogPerror("rfbClientConnFailed: write");
free(buf);
+
rfbCloseClient(cl);
}