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