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 <u.h>
2
#include <libc.h>
3
#include <mp.h>
4
#include <fcall.h>
5
#include <thread.h>
6
#include <9p.h>
7
#include <libsec.h>
8
#include <ip.h>
9
#include "netssh.h"
10
 
11
extern Cipher *cryptos[];
12
 
13
Packet *
14
new_packet(Conn *c)
15
{
16
	Packet *p;
17
 
18
	p = emalloc9p(sizeof(Packet));
19
	init_packet(p);
20
	p->c = c;
21
	return p;
22
}
23
 
24
void
25
init_packet(Packet *p)
26
{
27
	memset(p, 0, sizeof(Packet));
28
	p->rlength = 1;
29
}
30
 
31
void
32
add_byte(Packet *p, char c)
33
{
34
	p->payload[p->rlength-1] = c;
35
	p->rlength++;
36
}
37
 
38
void
39
add_uint32(Packet *p, ulong l)
40
{
41
	hnputl(p->payload+p->rlength-1, l);
42
	p->rlength += 4;
43
}
44
 
45
ulong
46
get_uint32(Packet *, uchar **data)
47
{
48
	ulong x;
49
	x = nhgetl(*data);
50
	*data += 4;
51
	return x;
52
}
53
 
54
int
55
add_packet(Packet *p, void *data, int len)
56
{
57
	if(p->rlength + len > Maxpayload)
58
		return -1;
59
	memmove(p->payload + p->rlength - 1, data, len);
60
	p->rlength += len;
61
	return 0;
62
}
63
 
64
void
65
add_block(Packet *p, void *data, int len)
66
{
67
	hnputl(p->payload + p->rlength - 1, len);
68
	p->rlength += 4;
69
	add_packet(p, data, len);
70
}
71
 
72
void 
73
add_string(Packet *p, char *s)
74
{
75
	uchar *q;
76
	int n;
77
	uchar nn[4];
78
 
79
	n = strlen(s);
80
	hnputl(nn, n);
81
	q = p->payload + p->rlength - 1;
82
	memmove(q, nn, 4);
83
	memmove(q+4, s, n);
84
	p->rlength += n + 4;
85
}
86
 
87
uchar *
88
get_string(Packet *p, uchar *q, char *s, int lim, int *len)
89
{
90
	int n, m;
91
 
92
	if (p && q > p->payload + p->rlength)
93
		s[0] = '\0';
94
	m = nhgetl(q);
95
	q += 4;
96
	if(m < lim)
97
		n = m;
98
	else
99
		n = lim - 1;
100
	memmove(s, q, n);
101
	s[n] = '\0';
102
	q += m;
103
	if(len)
104
		*len = n;
105
	return q;
106
}
107
 
108
void
109
add_mp(Packet *p, mpint *x)
110
{
111
	uchar *q;
112
	int n;
113
 
114
	q = p->payload + p->rlength - 1;
115
	n = mptobe(x, q + 4, Maxpktpay - p->rlength + 1 - 4, nil);
116
	if(q[4] & 0x80){
117
		memmove(q + 5, q + 4, n);
118
		q[4] = 0;
119
		n++;
120
	}
121
	hnputl(q, n);
122
	p->rlength += n + 4;
123
}
124
 
125
mpint *
126
get_mp(uchar *q)
127
{
128
	return betomp(q + 4, nhgetl(q), nil);
129
}
130
 
131
int
132
finish_packet(Packet *p)
133
{
134
	Conn *c;
135
	uchar *q, *buf;
136
	int blklen, i, n2, n1, maclen;
137
 
138
	c = p->c;
139
	blklen = 8;
140
	if(c && debug > 1)
141
		fprint(2, "%s: in finish_packet: enc %d outmac %d len %ld\n",
142
			argv0, c->encrypt, c->outmac, p->rlength);
143
	if(c && c->encrypt != -1){
144
		blklen = cryptos[c->encrypt]->blklen;
145
		if(blklen < 8)
146
			blklen = 8;
147
	}
148
	n1 = p->rlength - 1;
149
	n2 = blklen - (n1 + 5) % blklen;
150
	if(n2 < 4)
151
		n2 += blklen;
152
	p->pad_len = n2;
153
	for(i = 0, q = p->payload + n1; i < n2; ++i, ++q)
154
		*q = fastrand();
155
	p->rlength = n1 + n2 + 1;
156
	hnputl(p->nlength, p->rlength);
157
	maclen = 0;
158
	if(c && c->outmac != -1){
159
		maclen = SHA1dlen;
160
		buf = emalloc9p(Maxpktpay);
161
		hnputl(buf, c->outseq);
162
		memmove(buf + 4, p->nlength, p->rlength + 4);
163
		hmac_sha1(buf, p->rlength + 8, c->outik, maclen, q, nil);
164
		free(buf);
165
	}
166
	if(c && c->encrypt != -1)
167
		cryptos[c->encrypt]->encrypt(c->enccs, p->nlength, p->rlength + 4);
168
	if (c)
169
		c->outseq++;
170
	if(debug > 1)
171
		fprint(2, "%s: leaving finish packet: len %ld n1 %d n2 %d maclen %d\n",
172
			argv0, p->rlength, n1, n2, maclen);
173
	return p->rlength + 4 + maclen;
174
}
175
 
176
/*
177
 * The first blklen bytes are already decrypted so we could find the
178
 * length.
179
 */
180
int
181
undo_packet(Packet *p)
182
{
183
	Conn *c;
184
	long nlength;
185
	int nb;
186
	uchar rmac[SHA1dlen], *buf;
187
 
188
	c = p->c;
189
	nb = 4;
190
	if(c->decrypt != -1)
191
		nb = cryptos[c->decrypt]->blklen;
192
	if(c->inmac != -1)
193
		p->rlength -= SHA1dlen;			/* was magic 20 */
194
	nlength = nhgetl(p->nlength);
195
	if(c->decrypt != -1)
196
		cryptos[c->decrypt]->decrypt(c->deccs, p->nlength + nb,
197
			p->rlength + 4 - nb);
198
	if(c->inmac != -1){
199
		buf = emalloc9p(Maxpktpay);
200
		hnputl(buf, c->inseq);
201
		memmove(buf + 4, p->nlength, nlength + 4);
202
		hmac_sha1(buf, nlength + 8, c->inik, SHA1dlen, rmac, nil);
203
		free(buf);
204
		if(memcmp(rmac, p->payload + nlength - 1, SHA1dlen) != 0){
205
			fprint(2, "%s: received MAC verification failed: seq=%d\n",
206
				argv0, c->inseq);
207
			return -1;
208
		}
209
	}
210
	c->inseq++;
211
	p->rlength -= p->pad_len;
212
	p->pad_len = 0;
213
	return p->rlength - 1;
214
}
215
 
216
void
217
dump_packet(Packet *p)
218
{
219
	int i;
220
	char *buf, *q, *e;
221
 
222
	fprint(2, "Length: %ld, Padding length: %d\n", p->rlength, p->pad_len);
223
	q = buf = emalloc9p(Copybufsz);
224
	e = buf + Copybufsz;
225
	for(i = 0; i < p->rlength - 1; ++i){
226
		q = seprint(q, e, " %02x", p->payload[i]);
227
		if(i % 16 == 15)
228
			q = seprint(q, e, "\n");
229
		if(q - buf > Copybufsz - 4){
230
			fprint(2, "%s", buf);
231
			q = buf;
232
		}
233
	}
234
	fprint(2, "%s\n", buf);
235
	free(buf);
236
}