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 } 237