Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/ssh1/sshserve.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "ssh.h"
2
 
3
char *cipherlist = "blowfish rc4 3des";
4
char *authlist = "tis";
5
 
6
void fromnet(Conn*);
7
void startcmd(Conn*, char*, int*, int*);
8
int maxmsg = 256*1024;
9
 
10
Cipher *allcipher[] = {
11
	&cipherrc4,
12
	&cipherblowfish,
13
	&cipher3des,
14
	&cipherdes,
15
	&ciphernone,
16
	&ciphertwiddle,
17
};
18
 
19
Authsrv *allauthsrv[] = {
20
	&authsrvpassword,
21
	&authsrvtis,
22
};
23
 
24
Cipher*
25
findcipher(char *name, Cipher **list, int nlist)
26
{
27
	int i;
28
 
29
	for(i=0; i<nlist; i++)
30
		if(strcmp(name, list[i]->name) == 0)
31
			return list[i];
32
	error("unknown cipher %s", name);
33
	return nil;
34
}
35
 
36
Authsrv*
37
findauthsrv(char *name, Authsrv **list, int nlist)
38
{
39
	int i;
40
 
41
	for(i=0; i<nlist; i++)
42
		if(strcmp(name, list[i]->name) == 0)
43
			return list[i];
44
	error("unknown authsrv %s", name);
45
	return nil;
46
}
47
 
48
void
49
usage(void)
50
{
51
	fprint(2, "usage: sshserve [-A authlist] [-c cipherlist] client-ip-address\n");
52
	exits("usage");
53
}
54
 
55
void
56
main(int argc, char **argv)
57
{
58
	char *f[16];
59
	int i;
60
	Conn c;
61
 
62
	fmtinstall('B', mpfmt);
63
	fmtinstall('H', encodefmt);
64
	atexit(atexitkiller);
65
	atexitkill(getpid());
66
 
67
	memset(&c, 0, sizeof c);
68
 
69
	ARGBEGIN{
70
	case 'D':
71
		debuglevel = atoi(EARGF(usage()));
72
		break;
73
	case 'A':
74
		authlist = EARGF(usage());
75
		break;
76
	case 'c':
77
		cipherlist = EARGF(usage());
78
		break;
79
	default:
80
		usage();
81
	}ARGEND
82
 
83
	if(argc != 1)
84
		usage();
85
	c.host = argv[0];
86
 
87
	sshlog("connect from %s", c.host);
88
 
89
	/* limit of 768 bits in remote host key? */
90
	c.serverpriv = rsagen(768, 6, 0);
91
	if(c.serverpriv == nil)
92
		sysfatal("rsagen failed: %r");
93
	c.serverkey = &c.serverpriv->pub;
94
 
95
	c.nokcipher = getfields(cipherlist, f, nelem(f), 1, ", ");
96
	c.okcipher = emalloc(sizeof(Cipher*)*c.nokcipher);
97
	for(i=0; i<c.nokcipher; i++)
98
		c.okcipher[i] = findcipher(f[i], allcipher, nelem(allcipher));
99
 
100
	c.nokauthsrv = getfields(authlist, f, nelem(f), 1, ", ");
101
	c.okauthsrv = emalloc(sizeof(Authsrv*)*c.nokauthsrv);
102
	for(i=0; i<c.nokauthsrv; i++)
103
		c.okauthsrv[i] = findauthsrv(f[i], allauthsrv, nelem(allauthsrv));
104
 
105
	sshserverhandshake(&c);
106
 
107
	fromnet(&c);
108
}
109
 
110
void
111
fromnet(Conn *c)
112
{
113
	int infd, kidpid, n;
114
	char *cmd;
115
	Msg *m;
116
 
117
	infd = kidpid = -1;
118
	for(;;){
119
		m = recvmsg(c, -1);
120
		if(m == nil)
121
			exits(nil);
122
		switch(m->type){
123
		default:
124
			//badmsg(m, 0);
125
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
126
			break;
127
 
128
		case SSH_MSG_DISCONNECT:
129
			sysfatal("client disconnected");
130
 
131
		case SSH_CMSG_REQUEST_PTY:
132
			sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
133
			break;
134
 
135
		case SSH_CMSG_X11_REQUEST_FORWARDING:
136
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
137
			break;
138
 
139
		case SSH_CMSG_MAX_PACKET_SIZE:
140
			maxmsg = getlong(m);
141
			sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
142
			break;
143
 
144
		case SSH_CMSG_REQUEST_COMPRESSION:
145
			sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
146
			break;
147
 
148
		case SSH_CMSG_EXEC_SHELL:
149
			startcmd(c, nil, &kidpid, &infd);
150
			goto InteractiveMode;
151
 
152
		case SSH_CMSG_EXEC_CMD:
153
			cmd = getstring(m);
154
			startcmd(c, cmd, &kidpid, &infd);
155
			goto InteractiveMode;
156
		}
157
		free(m);
158
	}
159
 
160
InteractiveMode:
161
	for(;;){
162
		free(m);
163
		m = recvmsg(c, -1);
164
		if(m == nil)
165
			exits(nil);
166
		switch(m->type){
167
		default:
168
			badmsg(m, 0);
169
 
170
		case SSH_MSG_DISCONNECT:
171
			postnote(PNGROUP, kidpid, "hangup");
172
			sysfatal("client disconnected");
173
 
174
		case SSH_CMSG_STDIN_DATA:
175
			if(infd != 0){
176
				n = getlong(m);
177
				write(infd, getbytes(m, n), n);
178
			}
179
			break;
180
 
181
		case SSH_CMSG_EOF:
182
			close(infd);
183
			infd = -1;
184
			break;
185
 
186
		case SSH_CMSG_EXIT_CONFIRMATION:
187
			/* sent by some clients as dying breath */
188
			exits(nil);
189
 
190
		case SSH_CMSG_WINDOW_SIZE:
191
			/* we don't care */
192
			break;
193
		}
194
	}
195
}
196
 
197
void
198
copyout(Conn *c, int fd, int mtype)
199
{
200
	char buf[8192];
201
	int n, max, pid;
202
	Msg *m;
203
 
204
	max = sizeof buf;
205
	if(max > maxmsg - 32)	/* 32 is an overestimate of packet overhead */
206
		max = maxmsg - 32;
207
	if(max <= 0)
208
		sysfatal("maximum message size too small");
209
 
210
	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
211
	case -1:
212
		sysfatal("fork: %r");
213
	case 0:
214
		break;
215
	default:
216
		atexitkill(pid);
217
		return;
218
	}
219
 
220
	while((n = read(fd, buf, max)) > 0){
221
		m = allocmsg(c, mtype, 4+n);
222
		putlong(m, n);
223
		putbytes(m, buf, n);
224
		sendmsg(m);
225
	}
226
	exits(nil);
227
}
228
 
229
void
230
startcmd(Conn *c, char *cmd, int *kidpid, int *kidin)
231
{
232
	int i, pid, kpid;
233
	int pfd[3][2];
234
	char *dir;
235
	char *sysname, *tz;
236
	Msg *m;
237
	Waitmsg *w;
238
 
239
	for(i=0; i<3; i++)
240
		if(pipe(pfd[i]) < 0)
241
			sysfatal("pipe: %r");
242
 
243
	sysname = getenv("sysname");
244
	tz = getenv("timezone");
245
 
246
	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
247
	case -1:
248
		sysfatal("fork: %r");
249
	case 0:
250
		switch(kpid = rfork(RFPROC|RFNOTEG|RFENVG|RFFDG)){
251
		case -1:
252
			sysfatal("fork: %r");
253
		case 0:
254
			for(i=0; i<3; i++){
255
				if(dup(pfd[i][1], i) < 0)
256
					sysfatal("dup: %r");
257
				close(pfd[i][0]);
258
				close(pfd[i][1]);
259
			}
260
			putenv("user", c->user);
261
			if(sysname)
262
				putenv("sysname", sysname);
263
			if(tz)
264
				putenv("tz", tz);
265
 
266
			dir = smprint("/usr/%s", c->user);
267
			if(dir == nil || chdir(dir) < 0)
268
				chdir("/");
269
			if(cmd){
270
				putenv("service", "rx");
271
				execl("/bin/rc", "rc", "-lc", cmd, nil);
272
				sysfatal("cannot exec /bin/rc: %r");
273
			}else{
274
				putenv("service", "con");
275
				execl("/bin/ip/telnetd", "telnetd", "-tn", nil);
276
				sysfatal("cannot exec /bin/ip/telnetd: %r");
277
			}
278
		default:
279
			*kidpid = kpid;
280
			rendezvous(kidpid, 0);
281
			for(;;){
282
				if((w = wait()) == nil)
283
					sysfatal("wait: %r");
284
				if(w->pid == kpid)
285
					break;
286
				free(w);
287
			}
288
			if(w->msg[0]){
289
				m = allocmsg(c, SSH_MSG_DISCONNECT, 4+strlen(w->msg));
290
				putstring(m, w->msg);
291
				sendmsg(m);
292
			}else{
293
				m = allocmsg(c, SSH_SMSG_EXITSTATUS, 4);
294
				putlong(m, 0);
295
				sendmsg(m);
296
			}
297
			for(i=0; i<3; i++)
298
				close(pfd[i][0]);
299
			free(w);
300
			exits(nil);	
301
			break;
302
		}
303
	default:
304
		atexitkill(pid);
305
		rendezvous(kidpid, 0);
306
		break;
307
	}
308
 
309
	for(i=0; i<3; i++)
310
		close(pfd[i][1]);
311
 
312
	copyout(c, pfd[1][0], SSH_SMSG_STDOUT_DATA);
313
	copyout(c, pfd[2][0], SSH_SMSG_STDERR_DATA);
314
	*kidin = pfd[0][0];
315
}