1 /*
2 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
3 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19
20 /*
21 * vncauth.c - Functions for VNC password management and authentication.
22 */
23
24 #ifdef __STRICT_ANSI__
25 #define _BSD_SOURCE
26 #define _POSIX_SOURCE
27 #endif
28 #ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <rfb/rfbproto.h>
35 #include "d3des.h"
36
37 #include <string.h>
38 #include <math.h>
39
40 #ifdef LIBVNCSERVER_HAVE_SYS_STAT_H
41 #include <sys/stat.h>
42 #endif
43
44 #include <time.h>
45
46 #ifdef WIN32
47 #define srandom srand
48 #define random rand
49 #else
50 #include <sys/time.h>
51 #endif
52
53
54 /* libvncclient does not need this */
55 #ifndef rfbEncryptBytes
56
57 /*
58 * We use a fixed key to store passwords, since we assume that our local
59 * file system is secure but nonetheless don't want to store passwords
60 * as plaintext.
61 */
62
63 static unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7};
64
65
66 /*
67 * Encrypt a password and store it in a file. Returns 0 if successful,
68 * 1 if the file could not be written.
69 */
70
71 int
rfbEncryptAndStorePasswd(char * passwd,char * fname)72 rfbEncryptAndStorePasswd(char *passwd, char *fname)
73 {
74 FILE *fp;
75 unsigned int i;
76 unsigned char encryptedPasswd[8];
77
78 if ((fp = fopen(fname,"w")) == NULL) return 1;
79
80 /* windows security sux */
81 #ifndef WIN32
82 fchmod(fileno(fp), S_IRUSR|S_IWUSR);
83 #endif
84
85 /* pad password with nulls */
86
87 for (i = 0; i < 8; i++) {
88 if (i < strlen(passwd)) {
89 encryptedPasswd[i] = passwd[i];
90 } else {
91 encryptedPasswd[i] = 0;
92 }
93 }
94
95 /* Do encryption in-place - this way we overwrite our copy of the plaintext
96 password */
97
98 rfbDesKey(fixedkey, EN0);
99 rfbDes(encryptedPasswd, encryptedPasswd);
100
101 for (i = 0; i < 8; i++) {
102 putc(encryptedPasswd[i], fp);
103 }
104
105 fclose(fp);
106 return 0;
107 }
108
109
110 /*
111 * Decrypt a password from a file. Returns a pointer to a newly allocated
112 * string containing the password or a null pointer if the password could
113 * not be retrieved for some reason.
114 */
115
116 char *
rfbDecryptPasswdFromFile(char * fname)117 rfbDecryptPasswdFromFile(char *fname)
118 {
119 FILE *fp;
120 int i, ch;
121 unsigned char *passwd = (unsigned char *)malloc(9);
122
123 if ((fp = fopen(fname,"r")) == NULL) {
124 free(passwd);
125 return NULL;
126 }
127
128 for (i = 0; i < 8; i++) {
129 ch = getc(fp);
130 if (ch == EOF) {
131 fclose(fp);
132 free(passwd);
133 return NULL;
134 }
135 passwd[i] = ch;
136 }
137
138 fclose(fp);
139
140 rfbDesKey(fixedkey, DE1);
141 rfbDes(passwd, passwd);
142
143 passwd[8] = 0;
144
145 return (char *)passwd;
146 }
147
148
149 /*
150 * Generate CHALLENGESIZE random bytes for use in challenge-response
151 * authentication.
152 */
153
154 void
rfbRandomBytes(unsigned char * bytes)155 rfbRandomBytes(unsigned char *bytes)
156 {
157 int i;
158 static rfbBool s_srandom_called = FALSE;
159
160 if (!s_srandom_called) {
161 srandom((unsigned int)time(NULL) ^ (unsigned int)getpid());
162 s_srandom_called = TRUE;
163 }
164
165 for (i = 0; i < CHALLENGESIZE; i++) {
166 bytes[i] = (unsigned char)(random() & 255);
167 }
168 }
169
170 #endif
171
172 /*
173 * Encrypt CHALLENGESIZE bytes in memory using a password.
174 */
175
176 void
rfbEncryptBytes(unsigned char * bytes,char * passwd)177 rfbEncryptBytes(unsigned char *bytes, char *passwd)
178 {
179 unsigned char key[8];
180 unsigned int i;
181
182 /* key is simply password padded with nulls */
183
184 for (i = 0; i < 8; i++) {
185 if (i < strlen(passwd)) {
186 key[i] = passwd[i];
187 } else {
188 key[i] = 0;
189 }
190 }
191
192 rfbDesKey(key, EN0);
193
194 for (i = 0; i < CHALLENGESIZE; i += 8) {
195 rfbDes(bytes+i, bytes+i);
196 }
197 }
198
199 void
rfbEncryptBytes2(unsigned char * where,const int length,unsigned char * key)200 rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) {
201 int i, j;
202 rfbDesKey(key, EN0);
203 for (i = 0; i< 8; i++)
204 where[i] ^= key[i];
205 rfbDes(where, where);
206 for (i = 8; i < length; i += 8) {
207 for (j = 0; j < 8; j++)
208 where[i + j] ^= where[i + j - 8];
209 rfbDes(where + i, where + i);
210 }
211 }
212