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 #define _XOPEN_SOURCE 600
28 #endif
29 #ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H
30 #include <sys/types.h>
31 #endif
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <rfb/rfbproto.h>
36 #include "d3des.h"
37 
38 #include <string.h>
39 #include <math.h>
40 
41 #ifdef LIBVNCSERVER_HAVE_SYS_STAT_H
42 #include <sys/stat.h>
43 #endif
44 
45 #include <time.h>
46 
47 #ifdef WIN32
48 #define srandom srand
49 #define random rand
50 #else
51 #include <sys/time.h>
52 #endif
53 
54 
55 /* libvncclient does not need this */
56 #ifndef rfbEncryptBytes
57 
58 /*
59  * We use a fixed key to store passwords, since we assume that our local
60  * file system is secure but nonetheless don't want to store passwords
61  * as plaintext.
62  */
63 
64 static unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7};
65 
66 
67 /*
68  * Encrypt a password and store it in a file.  Returns 0 if successful,
69  * 1 if the file could not be written.
70  */
71 
72 int
rfbEncryptAndStorePasswd(char * passwd,char * fname)73 rfbEncryptAndStorePasswd(char *passwd, char *fname)
74 {
75     FILE *fp;
76     unsigned int i;
77     unsigned char encryptedPasswd[8];
78 
79     if ((fp = fopen(fname,"w")) == NULL) return 1;
80 
81 	/* windows security sux */
82 #ifndef WIN32
83     fchmod(fileno(fp), S_IRUSR|S_IWUSR);
84 #endif
85 
86     /* pad password with nulls */
87 
88     for (i = 0; i < 8; i++) {
89 	if (i < strlen(passwd)) {
90 	    encryptedPasswd[i] = passwd[i];
91 	} else {
92 	    encryptedPasswd[i] = 0;
93 	}
94     }
95 
96     /* Do encryption in-place - this way we overwrite our copy of the plaintext
97        password */
98 
99     rfbDesKey(fixedkey, EN0);
100     rfbDes(encryptedPasswd, encryptedPasswd);
101 
102     for (i = 0; i < 8; i++) {
103 	putc(encryptedPasswd[i], fp);
104     }
105 
106     fclose(fp);
107     return 0;
108 }
109 
110 
111 /*
112  * Decrypt a password from a file.  Returns a pointer to a newly allocated
113  * string containing the password or a null pointer if the password could
114  * not be retrieved for some reason.
115  */
116 
117 char *
rfbDecryptPasswdFromFile(char * fname)118 rfbDecryptPasswdFromFile(char *fname)
119 {
120     FILE *fp;
121     int i, ch;
122     unsigned char *passwd = (unsigned char *)malloc(9);
123 
124     if ((fp = fopen(fname,"r")) == NULL) {
125 	free(passwd);
126 	return NULL;
127     }
128 
129     for (i = 0; i < 8; i++) {
130 	ch = getc(fp);
131 	if (ch == EOF) {
132 	    fclose(fp);
133 	    free(passwd);
134 	    return NULL;
135 	}
136 	passwd[i] = ch;
137     }
138 
139     fclose(fp);
140 
141     rfbDesKey(fixedkey, DE1);
142     rfbDes(passwd, passwd);
143 
144     passwd[8] = 0;
145 
146     return (char *)passwd;
147 }
148 
149 
150 /*
151  * Generate CHALLENGESIZE random bytes for use in challenge-response
152  * authentication.
153  */
154 
155 void
rfbRandomBytes(unsigned char * bytes)156 rfbRandomBytes(unsigned char *bytes)
157 {
158     int i;
159     static rfbBool s_srandom_called = FALSE;
160 
161     if (!s_srandom_called) {
162 	srandom((unsigned int)time(NULL) ^ (unsigned int)getpid());
163 	s_srandom_called = TRUE;
164     }
165 
166     for (i = 0; i < CHALLENGESIZE; i++) {
167 	bytes[i] = (unsigned char)(random() & 255);
168     }
169 }
170 
171 #endif
172 
173 /*
174  * Encrypt CHALLENGESIZE bytes in memory using a password.
175  */
176 
177 void
rfbEncryptBytes(unsigned char * bytes,char * passwd)178 rfbEncryptBytes(unsigned char *bytes, char *passwd)
179 {
180     unsigned char key[8];
181     unsigned int i;
182 
183     /* key is simply password padded with nulls */
184 
185     for (i = 0; i < 8; i++) {
186 	if (i < strlen(passwd)) {
187 	    key[i] = passwd[i];
188 	} else {
189 	    key[i] = 0;
190 	}
191     }
192 
193     rfbDesKey(key, EN0);
194 
195     for (i = 0; i < CHALLENGESIZE; i += 8) {
196 	rfbDes(bytes+i, bytes+i);
197     }
198 }
199 
200 void
rfbEncryptBytes2(unsigned char * where,const int length,unsigned char * key)201 rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) {
202   int i, j;
203   rfbDesKey(key, EN0);
204   for (i = 0; i< 8; i++)
205     where[i] ^= key[i];
206   rfbDes(where, where);
207   for (i = 8; i < length; i += 8) {
208     for (j = 0; j < 8; j++)
209       where[i + j] ^= where[i + j - 8];
210       rfbDes(where + i, where + i);
211   }
212 }
213