Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "vnc.h"
2
#include <libsec.h>
3
#include <auth.h>
4
 
5
char *serveraddr;
6
 
7
/*
8
 * Encrypt n bytes using the password
9
 * as key, padded with zeros to 8 bytes.
10
 */
11
enum
12
{
13
	VerLen	= 12
14
};
15
 
16
static char version[VerLen+1] = "RFB 003.003\n";
17
 
18
static uchar tab[256];
19
 
20
/* VNC reverses the bits of each byte before using as a des key */
21
static void
22
mktab(void)
23
{
24
	int i, j, k;
25
	static int once;
26
 
27
	if(once)
28
		return;
29
	once = 1;
30
 
31
	for(i=0; i<256; i++){
32
		j=i;
33
		tab[i] = 0;
34
		for(k=0; k<8; k++){
35
			tab[i] = (tab[i]<<1) | (j&1);
36
			j >>= 1;
37
		}
38
	}
39
}
40
 
41
static void
42
vncencrypt(uchar *buf, int n, char *pw)
43
{
44
	uchar *p;
45
	uchar key[9];
46
	DESstate s;
47
 
48
	mktab();
49
	memset(key, 0, sizeof key);
50
	strncpy((char*)key, pw, 8);
51
	for(p=key; *p; p++)
52
		*p = tab[*p];
53
 
54
	setupDESstate(&s, key, nil);
55
	desECBencrypt(buf, n, &s);
56
}
57
 
58
static int
59
readln(char *prompt, char *line, int len)
60
{
61
	char *p;
62
	int fd, ctl, n, nr;
63
 
64
	fd = open("/dev/cons", ORDWR);
65
	if(fd < 0)
66
		sysfatal("couldn't open cons");
67
	ctl = open("/dev/consctl", OWRITE);
68
	if(ctl < 0)
69
		sysfatal("couldn't open consctl");
70
	write(ctl, "rawon", 5);
71
	fprint(fd, "%s", prompt);
72
	nr = 0;
73
	p = line;
74
	for(;;){
75
		n = read(fd, p, 1);
76
		if(n < 0){
77
			close(fd);
78
			close(ctl);
79
			return -1;
80
		}
81
		if(n == 0 || *p == '\n' || *p == '\r'){
82
			*p = '\0';
83
			write(fd, "\n", 1);
84
			close(fd);
85
			close(ctl);
86
			return nr;
87
		}
88
		if(*p == '\b'){
89
			if(nr > 0){
90
				nr--;
91
				p--;
92
			}
93
		}else if(*p == 21){		/* cntrl-u */
94
			fprint(fd, "\n%s", prompt);
95
			nr = 0;
96
			p = line;
97
		}else{
98
			nr++;
99
			p++;
100
		}
101
		if(nr == len){
102
			fprint(fd, "line too long; try again\n%s", prompt);
103
			nr = 0;
104
			p = line;
105
		}
106
	}
107
}
108
 
109
int
110
vncsrvhandshake(Vnc *v)
111
{
112
	char msg[VerLen+1];
113
 
114
	strecpy(msg, msg+sizeof msg, version);
115
	if(verbose)
116
		fprint(2, "server version: %s", msg);
117
	vncwrbytes(v, msg, VerLen);
118
	vncflush(v);
119
 
120
	vncrdbytes(v, msg, VerLen);
121
	if(verbose)
122
		fprint(2, "client version: %s", msg);
123
	return 0;
124
}
125
 
126
int
127
vnchandshake(Vnc *v)
128
{
129
	char msg[VerLen+1];
130
 
131
	msg[VerLen] = 0;
132
	vncrdbytes(v, msg, VerLen);
133
	if(strncmp(msg, "RFB ", 4) != 0){
134
		werrstr("bad rfb version \"%s\"", msg);
135
		return -1;
136
	}
137
	if(verbose)
138
		fprint(2, "server version: %s", msg);
139
	strcpy(msg, version);
140
	vncwrbytes(v, msg, VerLen);
141
	vncflush(v);
142
	return 0;
143
}
144
 
145
int
146
vncauth(Vnc *v, char *keypattern)
147
{
148
	char pw[128], *reason;
149
	uchar chal[VncChalLen];
150
	ulong auth;
151
	char *p, *server;
152
 
153
	if(keypattern == nil)
154
		keypattern = "";
155
	auth = vncrdlong(v);
156
	switch(auth){
157
	default:
158
		werrstr("unknown auth type 0x%lux", auth);
159
		if(verbose)
160
			fprint(2, "unknown auth type 0x%lux", auth);
161
		return -1;
162
 
163
	case AFailed:
164
		reason = vncrdstring(v);
165
		werrstr("%s", reason);
166
		if(verbose)
167
			fprint(2, "auth failed: %s\n", reason);
168
		return -1;
169
 
170
	case ANoAuth:
171
		if(verbose)
172
			fprint(2, "no auth needed");
173
		break;
174
 
175
	case AVncAuth:
176
		vncrdbytes(v, chal, VncChalLen);
177
		server = strdup(serveraddr);
178
		p = strrchr(server, ':');
179
		if(p)
180
			*p = 0;
181
		if(auth_respond(chal, VncChalLen, nil, 0, chal, VncChalLen, auth_getkey,
182
			"proto=vnc role=client server=%s %s", server, keypattern) != VncChalLen){
183
			/* BUG This is for drawterm users who don't start their own factotums */
184
			readln("password: ", pw, sizeof(pw));
185
			vncencrypt(chal, VncChalLen, pw);
186
			memset(pw, 0, sizeof pw);
187
		}
188
		free(server);
189
		vncwrbytes(v, chal, VncChalLen);
190
		vncflush(v);
191
 
192
		auth = vncrdlong(v);
193
		switch(auth){
194
		default:
195
			werrstr("unknown server response 0x%lux", auth);
196
			return -1;
197
		case VncAuthFailed:
198
			werrstr("server says authentication failed");
199
			return -1;
200
		case VncAuthTooMany:
201
			werrstr("server says too many tries");
202
			return -1;
203
		case VncAuthOK:
204
			break;
205
		}
206
		break;
207
	}
208
	return 0;
209
}
210
 
211
int
212
vncsrvauth(Vnc *v)
213
{
214
	Chalstate *c;
215
	AuthInfo *ai;
216
 
217
	if((c = auth_challenge("proto=vnc role=server user=%q", getuser()))==nil)
218
		sysfatal("vncchal: %r");
219
	if(c->nchal != VncChalLen)
220
		sysfatal("vncchal got %d bytes wanted %d", c->nchal, VncChalLen);
221
	vncwrlong(v, AVncAuth);
222
	vncwrbytes(v, c->chal, VncChalLen);
223
	vncflush(v);
224
 
225
	vncrdbytes(v, c->chal, VncChalLen);
226
	c->resp = c->chal;
227
	c->nresp = VncChalLen;
228
	ai = auth_response(c);
229
	auth_freechal(c);
230
	if(ai == nil){
231
		fprint(2, "vnc auth failed: server factotum: %r\n");
232
		vncwrlong(v, VncAuthFailed);
233
		vncflush(v);
234
		return -1;
235
	}
236
	auth_freeAI(ai);
237
	vncwrlong(v, VncAuthOK);
238
	vncflush(v);
239
 
240
	return 0;
241
}
242