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/feature_posix/sys/src/cmd/ssh1/smsg.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
#include <bio.h>
3
 
4
static void
5
send_ssh_smsg_public_key(Conn *c)
6
{
7
	int i;
8
	Msg *m;
9
 
10
	m = allocmsg(c, SSH_SMSG_PUBLIC_KEY, 2048);
11
	putbytes(m, c->cookie, COOKIELEN);
12
	putRSApub(m, c->serverkey);
13
	putRSApub(m, c->hostkey);
14
	putlong(m, c->flags);
15
 
16
	for(i=0; i<c->nokcipher; i++)
17
		c->ciphermask |= 1<<c->okcipher[i]->id;
18
	putlong(m, c->ciphermask);
19
	for(i=0; i<c->nokauthsrv; i++)
20
		c->authmask |= 1<<c->okauthsrv[i]->id;
21
	putlong(m, c->authmask);
22
 
23
	sendmsg(m);
24
}
25
 
26
static mpint*
27
rpcdecrypt(AuthRpc *rpc, mpint *b)
28
{
29
	mpint *a;
30
	char *p;
31
 
32
	p = mptoa(b, 16, nil, 0);
33
	if(auth_rpc(rpc, "write", p, strlen(p)) != ARok)
34
		sysfatal("factotum rsa write: %r");
35
	free(p);
36
	if(auth_rpc(rpc, "read", nil, 0) != ARok)
37
		sysfatal("factotum rsa read: %r");
38
	a = strtomp(rpc->arg, nil, 16, nil);
39
	mpfree(b);
40
	return a;
41
}
42
 
43
static void
44
recv_ssh_cmsg_session_key(Conn *c, AuthRpc *rpc)
45
{
46
	int i, id, n, serverkeylen, hostkeylen;
47
	mpint *a, *b;
48
	uchar *buf;
49
	Msg *m;
50
	RSApriv *ksmall, *kbig;
51
 
52
	m = recvmsg(c, SSH_CMSG_SESSION_KEY);
53
	id = getbyte(m);
54
	c->cipher = nil;
55
	for(i=0; i<c->nokcipher; i++)
56
		if(c->okcipher[i]->id == id)
57
			c->cipher = c->okcipher[i];
58
	if(c->cipher == nil)
59
		sysfatal("invalid cipher selected");
60
 
61
	if(memcmp(getbytes(m, COOKIELEN), c->cookie, COOKIELEN) != 0)
62
		sysfatal("bad cookie");
63
 
64
	serverkeylen = mpsignif(c->serverkey->n);
65
	hostkeylen = mpsignif(c->hostkey->n);
66
	ksmall = kbig = nil;
67
	if(serverkeylen+128 <= hostkeylen){
68
		ksmall = c->serverpriv;
69
		kbig = nil;
70
	}else if(hostkeylen+128 <= serverkeylen){
71
		ksmall = nil;
72
		kbig = c->serverpriv;
73
	}else
74
		sysfatal("server session and host keys do not differ by at least 128 bits");
75
 
76
	b = getmpint(m);
77
 
78
	debug(DBG_CRYPTO, "encrypted with kbig is %B\n", b);
79
	if(kbig){
80
		a = rsadecrypt(kbig, b, nil);
81
		mpfree(b);
82
		b = a;
83
	}else
84
		b = rpcdecrypt(rpc, b);
85
	a = rsaunpad(b);
86
	mpfree(b);
87
	b = a;
88
 
89
	debug(DBG_CRYPTO, "encrypted with ksmall is %B\n", b);
90
	if(ksmall){
91
		a = rsadecrypt(ksmall, b, nil);
92
		mpfree(b);
93
		b = a;
94
	}else
95
		b = rpcdecrypt(rpc, b);
96
	a = rsaunpad(b);
97
	mpfree(b);
98
	b = a;
99
 
100
	debug(DBG_CRYPTO, "munged is %B\n", b);
101
 
102
	n = (mpsignif(b)+7)/8;
103
	if(n > SESSKEYLEN)
104
		sysfatal("client sent short session key");
105
 
106
	buf = emalloc(SESSKEYLEN);
107
	mptoberjust(b, buf, SESSKEYLEN);
108
	mpfree(b);
109
 
110
	for(i=0; i<SESSIDLEN; i++)
111
		buf[i] ^= c->sessid[i];
112
 
113
	memmove(c->sesskey, buf, SESSKEYLEN);
114
 
115
	debug(DBG_CRYPTO, "unmunged is %.*H\n", SESSKEYLEN, buf);
116
 
117
	c->flags = getlong(m);
118
	free(m);
119
}
120
 
121
static AuthInfo*
122
responselogin(char *user, char *resp)
123
{
124
	Chalstate *c;
125
	AuthInfo *ai;
126
 
127
	if((c = auth_challenge("proto=p9cr user=%q role=server", user)) == nil){
128
		sshlog("auth_challenge failed for %s", user);
129
		return nil;
130
	}
131
	c->resp = resp;
132
	c->nresp = strlen(resp);
133
	ai = auth_response(c);
134
	auth_freechal(c);
135
	return ai;
136
}
137
 
138
static AuthInfo*
139
authusername(Conn *c)
140
{
141
	char *p;
142
	AuthInfo *ai;
143
 
144
	/*
145
	 * hack for sam users: 'name numbers' gets tried as securid login.
146
	 */
147
	if(p = strchr(c->user, ' ')){
148
		*p++ = '\0';
149
		if((ai=responselogin(c->user, p)) != nil)
150
			return ai;
151
		*--p = ' ';
152
		sshlog("bad response: %s", c->user);
153
	}
154
	return nil;
155
}
156
 
157
static void
158
authsrvuser(Conn *c)
159
{
160
	int i;
161
	char *ns, *user;
162
	AuthInfo *ai;
163
	Msg *m;
164
 
165
	m = recvmsg(c, SSH_CMSG_USER);
166
	user = getstring(m);
167
	c->user = emalloc(strlen(user)+1);
168
	strcpy(c->user, user);
169
	free(m);
170
 
171
	ai = authusername(c);
172
	while(ai == nil){
173
		/*
174
		 * clumsy: if the client aborted the auth_tis early
175
		 * we don't send a new failure.  we check this by
176
		 * looking at c->unget, which is only used in that
177
		 * case.
178
		 */
179
		if(c->unget != nil)
180
			goto skipfailure;
181
		sendmsg(allocmsg(c, SSH_SMSG_FAILURE, 0));
182
	skipfailure:
183
		m = recvmsg(c, -1);
184
		for(i=0; i<c->nokauthsrv; i++)
185
			if(c->okauthsrv[i]->firstmsg == m->type){
186
				ai = (*c->okauthsrv[i]->fn)(c, m);
187
				break;
188
			}
189
		if(i==c->nokauthsrv)
190
			badmsg(m, 0);
191
	}
192
	sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
193
 
194
	if(noworld(ai->cuid))
195
		ns = "/lib/namespace.noworld";
196
	else
197
		ns = nil;
198
	if(auth_chuid(ai, ns) < 0){
199
		sshlog("auth_chuid to %s: %r", ai->cuid);
200
		sysfatal("auth_chuid: %r");
201
	}
202
	sshlog("logged in as %s", ai->cuid);
203
	auth_freeAI(ai);
204
}
205
 
206
void
207
sshserverhandshake(Conn *c)
208
{
209
	char *p, buf[128];
210
	Biobuf *b;
211
	Attr *a;
212
	int i, afd;
213
	mpint *m;
214
	AuthRpc *rpc;
215
	RSApub *key;
216
 
217
	/*
218
	 * BUG: should use `attr' to get the key attributes
219
	 * after the read, but that's not implemented yet.
220
	 */
221
	if((b = Bopen("/mnt/factotum/ctl", OREAD)) == nil)
222
		sysfatal("open /mnt/factotum/ctl: %r");
223
	while((p = Brdline(b, '\n')) != nil){
224
		p[Blinelen(b)-1] = '\0';
225
		if(strstr(p, " proto=rsa ") && strstr(p, " service=sshserve "))
226
			break;
227
	}
228
	if(p == nil)
229
		sysfatal("no sshserve keys found in /mnt/factotum/ctl");
230
	a = _parseattr(p);
231
	Bterm(b);
232
	key = emalloc(sizeof(*key));
233
	if((p = _strfindattr(a, "n")) == nil)
234
		sysfatal("no n in sshserve key");
235
	if((key->n = strtomp(p, &p, 16, nil)) == nil || *p != 0)
236
		sysfatal("bad n in sshserve key");
237
	if((p = _strfindattr(a, "ek")) == nil)
238
		sysfatal("no ek in sshserve key");
239
	if((key->ek = strtomp(p, &p, 16, nil)) == nil || *p != 0)
240
		sysfatal("bad ek in sshserve key");
241
	_freeattr(a);
242
 
243
	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
244
		sysfatal("open /mnt/factotum/rpc: %r");
245
	if((rpc = auth_allocrpc(afd)) == nil)
246
		sysfatal("auth_allocrpc: %r");
247
	p = "proto=rsa role=client service=sshserve";
248
	if(auth_rpc(rpc, "start", p, strlen(p)) != ARok)
249
		sysfatal("auth_rpc start %s: %r", p);
250
	if(auth_rpc(rpc, "read", nil, 0) != ARok)
251
		sysfatal("auth_rpc read: %r");
252
	m = strtomp(rpc->arg, nil, 16, nil);
253
	if(mpcmp(m, key->n) != 0)
254
		sysfatal("key in /mnt/factotum/ctl does not match rpc key");
255
	mpfree(m);
256
	c->hostkey = key;
257
 
258
	/* send id string */
259
	fprint(c->fd[0], "SSH-1.5-Plan9\n");
260
 
261
	/* receive id string */
262
	if(readstrnl(c->fd[0], buf, sizeof buf) < 0)
263
		sysfatal("reading server version: %r");
264
 
265
	/* id string is "SSH-m.n-comment".  We need m=1, n>=5. */
266
	if(strncmp(buf, "SSH-", 4) != 0
267
	|| strtol(buf+4, &p, 10) != 1
268
	|| *p != '.'
269
	|| strtol(p+1, &p, 10) < 5
270
	|| *p != '-')
271
		sysfatal("protocol mismatch; got %s, need SSH-1.x for x>=5", buf);
272
 
273
	for(i=0; i<COOKIELEN; i++)
274
		c->cookie[i] = fastrand();
275
	calcsessid(c);
276
	send_ssh_smsg_public_key(c);
277
	recv_ssh_cmsg_session_key(c, rpc);
278
	auth_freerpc(rpc);
279
	close(afd);
280
 
281
	c->cstate = (*c->cipher->init)(c, 1);		/* turns on encryption */
282
	sendmsg(allocmsg(c, SSH_SMSG_SUCCESS, 0));
283
 
284
	authsrvuser(c);
285
}