2 * auth.c - deal with authentication.
4 * This file implements the VNC authentication protocol when setting up an RFB
9 * Copyright (C) 2002 RealVNC Ltd.
10 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
12 * This is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This software is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this software; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
30 #include "windowstr.h"
34 #define MAX_AUTH_TRIES 5
35 #define AUTH_TOO_MANY_BASE_DELAY 10 * 1000 /* in ms, doubles for each failure
36 over MAX_AUTH_TRIES */
38 static int rfbAuthFailure();
39 static CARD32 rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg);
41 char *rfbAuthPasswdFile = NULL;
43 Bool rfbAuthTooManyTries = FALSE;
44 static OsTimerPtr timer = NULL;
48 * rfbAuthNewClient is called when we reach the point of authenticating
49 * a new client. If authentication isn't being used then we simply send
50 * rfbNoAuth. Otherwise we send rfbVncAuth plus the challenge.
57 char buf[4 + CHALLENGESIZE];
60 cl->state = RFB_AUTHENTICATION;
62 if (rfbAuthPasswdFile && !cl->reverseConnection) {
64 if (rfbAuthTooManyTries) {
65 rfbClientConnFailed(cl, "Too many authentication failures");
69 *(CARD32 *)buf = Swap32IfLE(rfbVncAuth);
70 vncRandomBytes(cl->authChallenge);
71 memcpy(&buf[4], (char *)cl->authChallenge, CHALLENGESIZE);
72 len = 4 + CHALLENGESIZE;
76 *(CARD32 *)buf = Swap32IfLE(rfbNoAuth);
78 cl->state = RFB_INITIALISATION;
81 if (WriteExact(cl->sock, buf, len) < 0) {
82 rfbLogPerror("rfbAuthNewClient: write");
83 rfbCloseSock(cl->sock);
90 * rfbAuthProcessClientMessage is called when the client sends its
91 * authentication response.
95 rfbAuthProcessClientMessage(cl)
100 CARD8 response[CHALLENGESIZE];
103 n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE);
107 rfbLog("rfbAuthProcessClientMessage: read failed\n");
109 rfbLogPerror("rfbAuthProcessClientMessage: read");
111 rfbCloseSock(cl->sock);
115 passwd = vncDecryptPasswdFromFile(rfbAuthPasswdFile);
117 if (passwd == NULL) {
118 rfbLog("rfbAuthProcessClientMessage: could not get password from %s\n",
121 authResult = Swap32IfLE(rfbVncAuthFailed);
123 if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) {
124 rfbLogPerror("rfbAuthProcessClientMessage: write");
126 rfbCloseSock(cl->sock);
130 vncEncryptBytes(cl->authChallenge, passwd);
132 /* Lose the password from memory */
133 for (i = strlen(passwd); i >= 0; i--) {
137 free((char *)passwd);
139 if (memcmp(cl->authChallenge, response, CHALLENGESIZE) != 0) {
140 rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
143 authResult = rfbAuthFailure();
144 authResult = Swap32IfLE(authResult);
146 if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) {
147 rfbLogPerror("rfbAuthProcessClientMessage: write");
149 rfbCloseSock(cl->sock);
155 authResult = Swap32IfLE(rfbVncAuthOK);
157 if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) {
158 rfbLogPerror("rfbAuthProcessClientMessage: write");
159 rfbCloseSock(cl->sock);
163 cl->state = RFB_INITIALISATION;
167 static int rfbAuthFailure()
173 if (rfbAuthTries >= MAX_AUTH_TRIES) {
175 CARD32 delay = AUTH_TOO_MANY_BASE_DELAY;
176 for (i = MAX_AUTH_TRIES; i < rfbAuthTries; i++)
178 timer = TimerSet(timer, 0, delay, rfbAuthReenable, NULL);
180 rfbAuthTooManyTries = TRUE;
181 return rfbVncAuthTooMany;
184 return rfbVncAuthFailed;
189 rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg)
191 rfbAuthTooManyTries = FALSE;