Home | History | Annotate | Download | only in libvncserver
      1 /*
      2  * auth.c - deal with authentication.
      3  *
      4  * This file implements the VNC authentication protocol when setting up an RFB
      5  * connection.
      6  */
      7 
      8 /*
      9  *  Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
     10  *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk (at) incompleteness.net>.
     11  *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
     12  *  All Rights Reserved.
     13  *
     14  *  This is free software; you can redistribute it and/or modify
     15  *  it under the terms of the GNU General Public License as published by
     16  *  the Free Software Foundation; either version 2 of the License, or
     17  *  (at your option) any later version.
     18  *
     19  *  This software is distributed in the hope that it will be useful,
     20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     22  *  GNU General Public License for more details.
     23  *
     24  *  You should have received a copy of the GNU General Public License
     25  *  along with this software; if not, write to the Free Software
     26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
     27  *  USA.
     28  */
     29 
     30 #include <rfb/rfb.h>
     31 
     32 /* RFB 3.8 clients are well informed */
     33 void rfbClientSendString(rfbClientPtr cl, const char *reason);
     34 
     35 
     36 /*
     37  * Handle security types
     38  */
     39 
     40 static rfbSecurityHandler* securityHandlers = NULL;
     41 
     42 /*
     43  * This method registers a list of new security types.
     44  * It avoids same security type getting registered multiple times.
     45  * The order is not preserved if multiple security types are
     46  * registered at one-go.
     47  */
     48 void
     49 rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
     50 {
     51 	rfbSecurityHandler *head = securityHandlers, *next = NULL;
     52 
     53 	if(handler == NULL)
     54 		return;
     55 
     56 	next = handler->next;
     57 
     58 	while(head != NULL) {
     59 		if(head == handler) {
     60 			rfbRegisterSecurityHandler(next);
     61 			return;
     62 		}
     63 
     64 		head = head->next;
     65 	}
     66 
     67 	handler->next = securityHandlers;
     68 	securityHandlers = handler;
     69 
     70 	rfbRegisterSecurityHandler(next);
     71 }
     72 
     73 /*
     74  * This method unregisters a list of security types.
     75  * These security types won't be available for any new
     76  * client connection.
     77  */
     78 void
     79 rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
     80 {
     81 	rfbSecurityHandler *cur = NULL, *pre = NULL;
     82 
     83 	if(handler == NULL)
     84 		return;
     85 
     86 	if(securityHandlers == handler) {
     87 		securityHandlers = securityHandlers->next;
     88 		rfbUnregisterSecurityHandler(handler->next);
     89 		return;
     90 	}
     91 
     92 	cur = pre = securityHandlers;
     93 
     94 	while(cur) {
     95 		if(cur == handler) {
     96 			pre->next = cur->next;
     97 			break;
     98 		}
     99 		pre = cur;
    100 		cur = cur->next;
    101 	}
    102 	rfbUnregisterSecurityHandler(handler->next);
    103 }
    104 
    105 /*
    106  * Send the authentication challenge.
    107  */
    108 
    109 static void
    110 rfbVncAuthSendChallenge(rfbClientPtr cl)
    111 {
    112 
    113     /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth
    114        (same as rfbVncAuth). Just send the challenge. */
    115     rfbRandomBytes(cl->authChallenge);
    116     if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
    117         rfbLogPerror("rfbAuthNewClient: write");
    118         rfbCloseClient(cl);
    119         return;
    120     }
    121 
    122     /* Dispatch client input to rfbVncAuthProcessResponse. */
    123     cl->state = RFB_AUTHENTICATION;
    124 }
    125 
    126 /*
    127  * Send the NO AUTHENTICATION. SCARR
    128  */
    129 
    130 /*
    131  * The rfbVncAuthNone function is currently the only function that contains
    132  * special logic for the built-in Mac OS X VNC client which is activated by
    133  * a protocolMinorVersion == 889 coming from the Mac OS X VNC client.
    134  * The rfbProcessClientInitMessage function does understand how to handle the
    135  * RFB_INITIALISATION_SHARED state which was introduced to support the built-in
    136  * Mac OS X VNC client, but rfbProcessClientInitMessage does not examine the
    137  * protocolMinorVersion version field and so its support for the
    138  * RFB_INITIALISATION_SHARED state is not restricted to just the OS X client.
    139  */
    140 
    141 static void
    142 rfbVncAuthNone(rfbClientPtr cl)
    143 {
    144     /* The built-in Mac OS X VNC client behaves in a non-conforming fashion
    145      * when the server version is 3.7 or later AND the list of security types
    146      * sent to the OS X client contains the 'None' authentication type AND
    147      * the OS X client sends back the 'None' type as its choice.  In this case,
    148      * and this case ONLY, the built-in Mac OS X VNC client will NOT send the
    149      * ClientInit message and instead will behave as though an implicit
    150      * ClientInit message containing a shared-flag of true has been sent.
    151      * The special state RFB_INITIALISATION_SHARED represents this case.
    152      * The Mac OS X VNC client can be detected by checking protocolMinorVersion
    153      * for a value of 889.  No other VNC client is known to use this value
    154      * for protocolMinorVersion. */
    155     uint32_t authResult;
    156 
    157     /* The built-in Mac OS X VNC client expects to NOT receive a SecurityResult
    158      * message for authentication type 'None'.  Since its protocolMinorVersion
    159      * is greater than 7 (it is 889) this case must be tested for specially. */
    160     if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7 && cl->protocolMinorVersion != 889) {
    161         rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
    162         authResult = Swap32IfLE(rfbVncAuthOK);
    163         if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
    164             rfbLogPerror("rfbAuthProcessClientMessage: write");
    165             rfbCloseClient(cl);
    166             return;
    167         }
    168     }
    169     cl->state = cl->protocolMinorVersion == 889 ? RFB_INITIALISATION_SHARED : RFB_INITIALISATION;
    170     if (cl->state == RFB_INITIALISATION_SHARED)
    171         /* In this case we must call rfbProcessClientMessage now because
    172          * otherwise we would hang waiting for data to be received from the
    173          * client (the ClientInit message which will never come). */
    174         rfbProcessClientMessage(cl);
    175     return;
    176 }
    177 
    178 
    179 /*
    180  * Advertise the supported security types (protocol 3.7). Here before sending
    181  * the list of security types to the client one more security type is added
    182  * to the list if primaryType is not set to rfbSecTypeInvalid. This security
    183  * type is the standard vnc security type which does the vnc authentication
    184  * or it will be security type for no authentication.
    185  * Different security types will be added by applications using this library.
    186  */
    187 
    188 static rfbSecurityHandler VncSecurityHandlerVncAuth = {
    189     rfbSecTypeVncAuth,
    190     rfbVncAuthSendChallenge,
    191     NULL
    192 };
    193 
    194 static rfbSecurityHandler VncSecurityHandlerNone = {
    195     rfbSecTypeNone,
    196     rfbVncAuthNone,
    197     NULL
    198 };
    199 
    200 
    201 static void
    202 rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
    203 {
    204     /* The size of the message is the count of security types +1,
    205      * since the first byte is the number of types. */
    206     int size = 1;
    207     rfbSecurityHandler* handler;
    208 #define MAX_SECURITY_TYPES 255
    209     uint8_t buffer[MAX_SECURITY_TYPES+1];
    210 
    211 
    212     /* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
    213     switch (primaryType) {
    214     case rfbSecTypeNone:
    215         rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
    216         break;
    217     case rfbSecTypeVncAuth:
    218         rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
    219         break;
    220     }
    221 
    222     for (handler = securityHandlers;
    223 	    handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
    224 	buffer[size] = handler->type;
    225 	size++;
    226     }
    227     buffer[0] = (unsigned char)size-1;
    228 
    229     /* Send the list. */
    230     if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
    231 	rfbLogPerror("rfbSendSecurityTypeList: write");
    232 	rfbCloseClient(cl);
    233 	return;
    234     }
    235 
    236     /*
    237       * if count is 0, we need to send the reason and close the connection.
    238       */
    239     if(size <= 1) {
    240 	/* This means total count is Zero and so reason msg should be sent */
    241 	/* The execution should never reach here */
    242 	char* reason = "No authentication mode is registered!";
    243 
    244 	rfbClientSendString(cl, reason);
    245 	return;
    246     }
    247 
    248     /* Dispatch client input to rfbProcessClientSecurityType. */
    249     cl->state = RFB_SECURITY_TYPE;
    250 }
    251 
    252 
    253 
    254 
    255 /*
    256  * Tell the client what security type will be used (protocol 3.3).
    257  */
    258 static void
    259 rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
    260 {
    261     uint32_t value32;
    262 
    263     /* Send the value. */
    264     value32 = Swap32IfLE(securityType);
    265     if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
    266 	rfbLogPerror("rfbSendSecurityType: write");
    267 	rfbCloseClient(cl);
    268 	return;
    269     }
    270 
    271     /* Decide what to do next. */
    272     switch (securityType) {
    273     case rfbSecTypeNone:
    274 	/* Dispatch client input to rfbProcessClientInitMessage. */
    275 	cl->state = RFB_INITIALISATION;
    276 	break;
    277     case rfbSecTypeVncAuth:
    278 	/* Begin the standard VNC authentication procedure. */
    279 	rfbVncAuthSendChallenge(cl);
    280 	break;
    281     default:
    282 	/* Impossible case (hopefully). */
    283 	rfbLogPerror("rfbSendSecurityType: assertion failed");
    284 	rfbCloseClient(cl);
    285     }
    286 }
    287 
    288 
    289 
    290 /*
    291  * rfbAuthNewClient is called right after negotiating the protocol
    292  * version. Depending on the protocol version, we send either a code
    293  * for authentication scheme to be used (protocol 3.3), or a list of
    294  * possible "security types" (protocol 3.7).
    295  */
    296 
    297 void
    298 rfbAuthNewClient(rfbClientPtr cl)
    299 {
    300     int32_t securityType = rfbSecTypeInvalid;
    301 
    302     if (!cl->screen->authPasswdData || cl->reverseConnection) {
    303 	/* chk if this condition is valid or not. */
    304 	securityType = rfbSecTypeNone;
    305     } else if (cl->screen->authPasswdData) {
    306  	    securityType = rfbSecTypeVncAuth;
    307     }
    308 
    309     if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
    310     {
    311 	/* Make sure we use only RFB 3.3 compatible security types. */
    312 	if (securityType == rfbSecTypeInvalid) {
    313 	    rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
    314 	    rfbClientConnFailed(cl, "Your viewer cannot handle required "
    315 				"authentication methods");
    316 	    return;
    317 	}
    318 	rfbSendSecurityType(cl, securityType);
    319     } else {
    320 	/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
    321 	rfbSendSecurityTypeList(cl, securityType);
    322     }
    323 }
    324 
    325 /*
    326  * Read the security type chosen by the client (protocol 3.7).
    327  */
    328 
    329 void
    330 rfbProcessClientSecurityType(rfbClientPtr cl)
    331 {
    332     int n;
    333     uint8_t chosenType;
    334     rfbSecurityHandler* handler;
    335 
    336     /* Read the security type. */
    337     n = rfbReadExact(cl, (char *)&chosenType, 1);
    338     if (n <= 0) {
    339 	if (n == 0)
    340 	    rfbLog("rfbProcessClientSecurityType: client gone\n");
    341 	else
    342 	    rfbLogPerror("rfbProcessClientSecurityType: read");
    343 	rfbCloseClient(cl);
    344 	return;
    345     }
    346 
    347     /* Make sure it was present in the list sent by the server. */
    348     for (handler = securityHandlers; handler; handler = handler->next) {
    349 	if (chosenType == handler->type) {
    350 	      rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
    351 	      handler->handler(cl);
    352 	      return;
    353 	}
    354     }
    355 
    356     rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
    357     rfbCloseClient(cl);
    358 }
    359 
    360 
    361 
    362 /*
    363  * rfbAuthProcessClientMessage is called when the client sends its
    364  * authentication response.
    365  */
    366 
    367 void
    368 rfbAuthProcessClientMessage(rfbClientPtr cl)
    369 {
    370     int n;
    371     uint8_t response[CHALLENGESIZE];
    372     uint32_t authResult;
    373 
    374     if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
    375         if (n != 0)
    376             rfbLogPerror("rfbAuthProcessClientMessage: read");
    377         rfbCloseClient(cl);
    378         return;
    379     }
    380 
    381     if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
    382         rfbErr("rfbAuthProcessClientMessage: password check failed\n");
    383         authResult = Swap32IfLE(rfbVncAuthFailed);
    384         if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
    385             rfbLogPerror("rfbAuthProcessClientMessage: write");
    386         }
    387 	/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
    388         if (cl->protocolMinorVersion > 7) {
    389             rfbClientSendString(cl, "password check failed!");
    390 	}
    391 	else
    392             rfbCloseClient(cl);
    393         return;
    394     }
    395 
    396     authResult = Swap32IfLE(rfbVncAuthOK);
    397 
    398     if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
    399         rfbLogPerror("rfbAuthProcessClientMessage: write");
    400         rfbCloseClient(cl);
    401         return;
    402     }
    403 
    404     cl->state = RFB_INITIALISATION;
    405 }
    406