From a60ee2ee9f73d21c4407136d7a2878a34be2f7ed Mon Sep 17 00:00:00 2001 From: steven_carr Date: Mon, 5 Jun 2006 18:50:45 +0000 Subject: [PATCH] RFB 3.8 clients are well informed --- libvncclient/rfbproto.c | 92 ++++++++++++++++++++++++---------------- libvncserver/auth.c | 8 +++- libvncserver/rfbserver.c | 31 +++++++++++--- 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 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); }