X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=Xserver%2Fprograms%2FXserver%2Fhw%2Fvnc%2Fauth.c;fp=Xserver%2Fprograms%2FXserver%2Fhw%2Fvnc%2Fauth.c;h=e9a79770f0237a6fb2d517503b1bfbf8d3c0d565;hp=0000000000000000000000000000000000000000;hb=b6e6afccf37f4ad0515ef2a698f714fdf1bf23b3;hpb=e3340a110a3b01756b8e67531395a33b40a17d37 diff --git a/Xserver/programs/Xserver/hw/vnc/auth.c b/Xserver/programs/Xserver/hw/vnc/auth.c new file mode 100644 index 0000000..e9a7977 --- /dev/null +++ b/Xserver/programs/Xserver/hw/vnc/auth.c @@ -0,0 +1,193 @@ +/* + * auth.c - deal with authentication. + * + * This file implements the VNC authentication protocol when setting up an RFB + * connection. + */ + +/* + * Copyright (C) 2002 RealVNC Ltd. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include "windowstr.h" +#include "rfb.h" + + +#define MAX_AUTH_TRIES 5 +#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000 /* in ms, doubles for each failure + over MAX_AUTH_TRIES */ + +static int rfbAuthFailure(); +static CARD32 rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg); + +char *rfbAuthPasswdFile = NULL; +int rfbAuthTries = 0; +Bool rfbAuthTooManyTries = FALSE; +static OsTimerPtr timer = NULL; + + +/* + * rfbAuthNewClient is called when we reach the point of authenticating + * a new client. If authentication isn't being used then we simply send + * rfbNoAuth. Otherwise we send rfbVncAuth plus the challenge. + */ + +void +rfbAuthNewClient(cl) + rfbClientPtr cl; +{ + char buf[4 + CHALLENGESIZE]; + int len; + + cl->state = RFB_AUTHENTICATION; + + if (rfbAuthPasswdFile && !cl->reverseConnection) { + + if (rfbAuthTooManyTries) { + rfbClientConnFailed(cl, "Too many authentication failures"); + return; + } + + *(CARD32 *)buf = Swap32IfLE(rfbVncAuth); + vncRandomBytes(cl->authChallenge); + memcpy(&buf[4], (char *)cl->authChallenge, CHALLENGESIZE); + len = 4 + CHALLENGESIZE; + + } else { + + *(CARD32 *)buf = Swap32IfLE(rfbNoAuth); + len = 4; + cl->state = RFB_INITIALISATION; + } + + if (WriteExact(cl->sock, buf, len) < 0) { + rfbLogPerror("rfbAuthNewClient: write"); + rfbCloseSock(cl->sock); + return; + } +} + + +/* + * rfbAuthProcessClientMessage is called when the client sends its + * authentication response. + */ + +void +rfbAuthProcessClientMessage(cl) + rfbClientPtr cl; +{ + char *passwd; + int i, n; + CARD8 response[CHALLENGESIZE]; + CARD32 authResult; + + n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE); + + if (n <= 0) { + if (n == 0) + rfbLog("rfbAuthProcessClientMessage: read failed\n"); + else + rfbLogPerror("rfbAuthProcessClientMessage: read"); + rfbAuthFailure(); + rfbCloseSock(cl->sock); + return; + } + + passwd = vncDecryptPasswdFromFile(rfbAuthPasswdFile); + + if (passwd == NULL) { + rfbLog("rfbAuthProcessClientMessage: could not get password from %s\n", + rfbAuthPasswdFile); + + authResult = Swap32IfLE(rfbVncAuthFailed); + + if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { + rfbLogPerror("rfbAuthProcessClientMessage: write"); + } + rfbCloseSock(cl->sock); + return; + } + + vncEncryptBytes(cl->authChallenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + + free((char *)passwd); + + if (memcmp(cl->authChallenge, response, CHALLENGESIZE) != 0) { + rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n", + cl->host); + + authResult = rfbAuthFailure(); + authResult = Swap32IfLE(authResult); + + if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { + rfbLogPerror("rfbAuthProcessClientMessage: write"); + } + rfbCloseSock(cl->sock); + return; + } + + rfbAuthTries = 0; + + authResult = Swap32IfLE(rfbVncAuthOK); + + if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { + rfbLogPerror("rfbAuthProcessClientMessage: write"); + rfbCloseSock(cl->sock); + return; + } + + cl->state = RFB_INITIALISATION; +} + + +static int rfbAuthFailure() +{ + int i; + + rfbAuthTries++; + + if (rfbAuthTries >= MAX_AUTH_TRIES) { + + CARD32 delay = AUTH_TOO_MANY_BASE_DELAY; + for (i = MAX_AUTH_TRIES; i < rfbAuthTries; i++) + delay *= 2; + timer = TimerSet(timer, 0, delay, rfbAuthReenable, NULL); + + rfbAuthTooManyTries = TRUE; + return rfbVncAuthTooMany; + } + + return rfbVncAuthFailed; +} + + +static CARD32 +rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rfbAuthTooManyTries = FALSE; + return 0; +}