#include <u.h>#include <libc.h>#include <mp.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include <libsec.h>#include <ip.h>#include "sshtun.h" extern Cipher *cryptos[]; Packet *new_packet(Conn *c){ Packet *p; p = emalloc9p(sizeof(Packet)); init_packet(p); p->c = c; return p;} voidinit_packet(Packet *p){ memset(p, 0, sizeof(Packet)); p->rlength = 1;} voidadd_byte(Packet *p, char c){ p->payload[p->rlength-1] = c; p->rlength++;} voidadd_uint32(Packet *p, ulong l){ hnputl(p->payload+p->rlength-1, l); p->rlength += 4;} ulongget_uint32(Packet *, uchar **data){ ulong x; x = nhgetl(*data); *data += 4; return x;} intadd_packet(Packet *p, void *data, int len){ if(p->rlength + len > 32768) return -1; memmove(p->payload + p->rlength - 1, data, len); p->rlength += len; return 0;} voidadd_block(Packet *p, void *data, int len){ hnputl(p->payload + p->rlength - 1, len); p->rlength += 4; add_packet(p, data, len);} void add_string(Packet *p, char *s){ uchar *q; int n; uchar nn[4]; n = strlen(s); hnputl(nn, n); q = p->payload + p->rlength - 1; memmove(q, nn, 4); memmove(q+4, s, n); p->rlength += n + 4;} uchar *get_string(Packet *p, uchar *q, char *s, int lim, int *len){ int n, m; if (p && q > p->payload + p->rlength) s[0] = '\0'; m = nhgetl(q); q += 4; if(m < lim) n = m; else n = lim - 1; memmove(s, q, n); s[n] = '\0'; q += m; if(len) *len = n; return q;} voidadd_mp(Packet *p, mpint *x){ uchar *q; int n; q = p->payload + p->rlength - 1; n = mptobe(x, q + 4, 35000 - p->rlength + 1 - 4, nil); if(q[4] & 0x80){ memmove(q + 5, q + 4, n); q[4] = 0; n++; } hnputl(q, n); p->rlength += n + 4;} mpint *get_mp(uchar *q){ int n; n = nhgetl(q); q += 4; return betomp(q, n, nil);} intfinish_packet(Packet *p){ Conn *c; uchar *q, *buf; int blklen, i, n2, n1, maclen; c = p->c; blklen = 8; if(debug > 1) fprint(2, "In finish packet: enc:%d outmac:%d len:%ld\n", c->encrypt, c->outmac, p->rlength); if(c && c->encrypt != -1){ blklen = cryptos[c->encrypt]->blklen; if(blklen < 8) blklen = 8; } n1 = p->rlength - 1; n2 = blklen - ((n1 + 5) % blklen); if(n2 < 4) n2 += blklen; p->pad_len = n2; for(i = 0, q = p->payload + n1; i < n2; ++i, ++q) *q = fastrand(); p->rlength = n1 + n2 + 1; hnputl(p->nlength, p->rlength); maclen = 0; if(c && c->outmac != -1){ maclen = SHA1dlen; buf = emalloc9p(35000); hnputl(buf, c->outseq); memmove(buf + 4, p->nlength, p->rlength + 4); hmac_sha1(buf, p->rlength + 8, c->outik, maclen, q, nil); free(buf); } if(c && c->encrypt != -1) cryptos[c->encrypt]->encrypt(c->enccs, p->nlength, p->rlength + 4); c->outseq++; if(debug > 1) fprint(2, "leaving finish packet: len:%ld n1:%d n2:%d maclen:%d\n", p->rlength, n1, n2, maclen); return p->rlength + 4 + maclen;} /* * The first blklen bytes are already decrypted so we could find the * length. */intundo_packet(Packet *p){ Conn *c; long nlength; int nb; uchar rmac[SHA1dlen], *buf; c = p->c; nb = 4; if(c->decrypt != -1) nb = cryptos[c->decrypt]->blklen; if(c->inmac != -1) p->rlength -= 20; nlength = nhgetl(p->nlength); if(c->decrypt != -1) cryptos[c->decrypt]->decrypt(c->deccs, p->nlength + nb, p->rlength + 4 - nb); if(c->inmac != -1){ buf = emalloc9p(35000); hnputl(buf, c->inseq); memmove(buf + 4, p->nlength, nlength + 4); hmac_sha1(buf, nlength + 8, c->inik, SHA1dlen, rmac, nil); free(buf); if(memcmp(rmac, p->payload + nlength - 1, SHA1dlen) != 0){ fprint(2, "Received MAC verification failed: seq=%d\n", c->inseq); return -1; } } c->inseq++; p->rlength -= p->pad_len; p->pad_len = 0; return p->rlength - 1;} voiddump_packet(Packet *p){ int i; char *buf, *q, *e; fprint(2, "Length: %ld, Padding length: %d\n", p->rlength, p->pad_len); buf = emalloc9p(4096); e = buf + 4096; q = buf; for(i = 0; i < p->rlength - 1; ++i){ q = seprint(q, e, " %02x", p->payload[i]); if(i % 16 == 15) q = seprint(q, e, "\n"); if((q - buf) > 4092){ fprint(2, "%s", buf); q = buf; } } fprint(2, "%s\n", buf); free(buf);}
#include <u.h>
#include <libc.h>
#include <mp.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <libsec.h>
#include <ip.h>
#include "sshtun.h"
extern Cipher *cryptos[];
Packet *
new_packet(Conn *c)
{
Packet *p;
p = emalloc9p(sizeof(Packet));
init_packet(p);
p->c = c;
return p;
}
void
init_packet(Packet *p)
{
memset(p, 0, sizeof(Packet));
p->rlength = 1;
}
void
add_byte(Packet *p, char c)
{
p->payload[p->rlength-1] = c;
p->rlength++;
}
void
add_uint32(Packet *p, ulong l)
{
hnputl(p->payload+p->rlength-1, l);
p->rlength += 4;
}
ulong
get_uint32(Packet *, uchar **data)
{
ulong x;
x = nhgetl(*data);
*data += 4;
return x;
}
int
add_packet(Packet *p, void *data, int len)
{
if(p->rlength + len > 32768)
return -1;
memmove(p->payload + p->rlength - 1, data, len);
p->rlength += len;
return 0;
}
void
add_block(Packet *p, void *data, int len)
{
hnputl(p->payload + p->rlength - 1, len);
p->rlength += 4;
add_packet(p, data, len);
}
void
add_string(Packet *p, char *s)
{
uchar *q;
int n;
uchar nn[4];
n = strlen(s);
hnputl(nn, n);
q = p->payload + p->rlength - 1;
memmove(q, nn, 4);
memmove(q+4, s, n);
p->rlength += n + 4;
}
uchar *
get_string(Packet *p, uchar *q, char *s, int lim, int *len)
{
int n, m;
if (p && q > p->payload + p->rlength)
s[0] = '\0';
m = nhgetl(q);
q += 4;
if(m < lim)
n = m;
else
n = lim - 1;
memmove(s, q, n);
s[n] = '\0';
q += m;
if(len)
*len = n;
return q;
}
void
add_mp(Packet *p, mpint *x)
{
uchar *q;
int n;
q = p->payload + p->rlength - 1;
n = mptobe(x, q + 4, 35000 - p->rlength + 1 - 4, nil);
if(q[4] & 0x80){
memmove(q + 5, q + 4, n);
q[4] = 0;
n++;
}
hnputl(q, n);
p->rlength += n + 4;
}
mpint *
get_mp(uchar *q)
{
int n;
n = nhgetl(q);
q += 4;
return betomp(q, n, nil);
}
int
finish_packet(Packet *p)
{
Conn *c;
uchar *q, *buf;
int blklen, i, n2, n1, maclen;
c = p->c;
blklen = 8;
if(debug > 1)
fprint(2, "In finish packet: enc:%d outmac:%d len:%ld\n", c->encrypt, c->outmac, p->rlength);
if(c && c->encrypt != -1){
blklen = cryptos[c->encrypt]->blklen;
if(blklen < 8)
blklen = 8;
}
n1 = p->rlength - 1;
n2 = blklen - ((n1 + 5) % blklen);
if(n2 < 4)
n2 += blklen;
p->pad_len = n2;
for(i = 0, q = p->payload + n1; i < n2; ++i, ++q)
*q = fastrand();
p->rlength = n1 + n2 + 1;
hnputl(p->nlength, p->rlength);
maclen = 0;
if(c && c->outmac != -1){
maclen = SHA1dlen;
buf = emalloc9p(35000);
hnputl(buf, c->outseq);
memmove(buf + 4, p->nlength, p->rlength + 4);
hmac_sha1(buf, p->rlength + 8, c->outik, maclen, q, nil);
free(buf);
}
if(c && c->encrypt != -1)
cryptos[c->encrypt]->encrypt(c->enccs, p->nlength, p->rlength + 4);
c->outseq++;
if(debug > 1)
fprint(2, "leaving finish packet: len:%ld n1:%d n2:%d maclen:%d\n", p->rlength, n1, n2, maclen);
return p->rlength + 4 + maclen;
}
/*
* The first blklen bytes are already decrypted so we could find the
* length.
*/
int
undo_packet(Packet *p)
{
Conn *c;
long nlength;
int nb;
uchar rmac[SHA1dlen], *buf;
c = p->c;
nb = 4;
if(c->decrypt != -1)
nb = cryptos[c->decrypt]->blklen;
if(c->inmac != -1)
p->rlength -= 20;
nlength = nhgetl(p->nlength);
if(c->decrypt != -1)
cryptos[c->decrypt]->decrypt(c->deccs, p->nlength + nb, p->rlength + 4 - nb);
if(c->inmac != -1){
buf = emalloc9p(35000);
hnputl(buf, c->inseq);
memmove(buf + 4, p->nlength, nlength + 4);
hmac_sha1(buf, nlength + 8, c->inik, SHA1dlen, rmac, nil);
free(buf);
if(memcmp(rmac, p->payload + nlength - 1, SHA1dlen) != 0){
fprint(2, "Received MAC verification failed: seq=%d\n", c->inseq);
return -1;
}
}
c->inseq++;
p->rlength -= p->pad_len;
p->pad_len = 0;
return p->rlength - 1;
}
void
dump_packet(Packet *p)
{
int i;
char *buf, *q, *e;
fprint(2, "Length: %ld, Padding length: %d\n", p->rlength, p->pad_len);
buf = emalloc9p(4096);
e = buf + 4096;
q = buf;
for(i = 0; i < p->rlength - 1; ++i){
q = seprint(q, e, " %02x", p->payload[i]);
if(i % 16 == 15)
q = seprint(q, e, "\n");
if((q - buf) > 4092){
fprint(2, "%s", buf);
q = buf;
}
}
fprint(2, "%s\n", buf);
free(buf);
}