blob: 29a3b9641fa6aaacee8a0a764224180aa496baba [file] [log] [blame]
Constantin Kaplinskyde179d42006-04-16 06:53:44 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00003 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18//
19// SSecurityVncAuth
20//
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000021// XXX not thread-safe, because d3des isn't - do we need to worry about this?
22//
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000023
24#include <rfb/SSecurityVncAuth.h>
25#include <rdr/RandomStream.h>
26#include <rfb/SConnection.h>
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000027#include <rfb/Password.h>
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000028#include <rfb/Configuration.h>
29#include <rfb/LogWriter.h>
30#include <rfb/util.h>
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000031#include <rfb/Exception.h>
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000032#include <string.h>
33#include <stdio.h>
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000034extern "C" {
35#include <rfb/d3des.h>
36}
37
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000038
39using namespace rfb;
40
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000041static LogWriter vlog("SVncAuth");
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000042
43
44SSecurityVncAuth::SSecurityVncAuth(VncAuthPasswdGetter* pg_)
45 : sentChallenge(false), responsePos(0), pg(pg_)
46{
47}
48
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000049bool SSecurityVncAuth::processMsg(SConnection* sc)
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000050{
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000051 rdr::InStream* is = sc->getInStream();
52 rdr::OutStream* os = sc->getOutStream();
53
54 if (!sentChallenge) {
55 rdr::RandomStream rs;
56 rs.readBytes(challenge, vncAuthChallengeSize);
57 os->writeBytes(challenge, vncAuthChallengeSize);
58 os->flush();
59 sentChallenge = true;
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000060 return false;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000061 }
62
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000063 while (responsePos < vncAuthChallengeSize && is->checkNoWait(1))
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000064 response[responsePos++] = is->readU8();
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000065
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000066 if (responsePos < vncAuthChallengeSize) return false;
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000067
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000068 PlainPasswd passwd(pg->getVncAuthPasswd());
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000069
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000070 if (!passwd.buf)
71 throw AuthFailureException("No password configured for VNC Auth");
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000072
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000073 // Calculate the expected response
74 rdr::U8 key[8];
75 int pwdLen = strlen(passwd.buf);
76 for (int i=0; i<8; i++)
77 key[i] = i<pwdLen ? passwd.buf[i] : 0;
78 deskey(key, EN0);
79 for (int j = 0; j < vncAuthChallengeSize; j += 8)
80 des(challenge+j, challenge+j);
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000081
Constantin Kaplinskyde179d42006-04-16 06:53:44 +000082 // Check the actual response
83 if (memcmp(challenge, response, vncAuthChallengeSize) != 0)
84 throw AuthFailureException();
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +000085
86 return true;
87}