-void ssh2_pkt_adddata(void *data, int len) {
- pktout.length += len;
- if (pktout.maxlen < pktout.length) {
- pktout.maxlen = pktout.length + 256;
- pktout.data = (pktout.data == NULL ? malloc(pktout.maxlen+APIEXTRA) :
- realloc(pktout.data, pktout.maxlen+APIEXTRA));
- if (!pktout.data)
- fatalbox("Out of memory");
- }
- memcpy(pktout.data+pktout.length-len, data, len);
-}
-void ssh2_pkt_addbyte(unsigned char byte) {
- ssh2_pkt_adddata(&byte, 1);
-}
-void ssh2_pkt_init(int pkt_type) {
- pktout.length = 5;
- ssh2_pkt_addbyte((unsigned char)pkt_type);
-}
-void ssh2_pkt_addbool(unsigned char value) {
- ssh2_pkt_adddata(&value, 1);
-}
-void ssh2_pkt_adduint32(unsigned long value) {
- unsigned char x[4];
- PUT_32BIT(x, value);
- ssh2_pkt_adddata(x, 4);
-}
-void ssh2_pkt_addstring_start(void) {
- ssh2_pkt_adduint32(0);
- pktout.savedpos = pktout.length;
-}
-void ssh2_pkt_addstring_str(char *data) {
- ssh2_pkt_adddata(data, strlen(data));
- PUT_32BIT(pktout.data + pktout.savedpos - 4,
- pktout.length - pktout.savedpos);
-}
-void ssh2_pkt_addstring_data(char *data, int len) {
- ssh2_pkt_adddata(data, len);
- PUT_32BIT(pktout.data + pktout.savedpos - 4,
- pktout.length - pktout.savedpos);
-}
-void ssh2_pkt_addstring(char *data) {
- ssh2_pkt_addstring_start();
- ssh2_pkt_addstring_str(data);
-}
-char *ssh2_mpint_fmt(Bignum b, int *len) {
- unsigned char *p;
- int i, n = b[0];
- p = malloc(n * 2 + 1);
- if (!p)
- fatalbox("out of memory");
- p[0] = 0;
- for (i = 0; i < n; i++) {
- p[i*2+1] = (b[n-i] >> 8) & 0xFF;
- p[i*2+2] = (b[n-i] ) & 0xFF;
- }
- i = 0;
- while (p[i] == 0 && (p[i+1] & 0x80) == 0)
- i++;
- memmove(p, p+i, n*2+1-i);
- *len = n*2+1-i;
- return p;
-}
-void ssh2_pkt_addmp(Bignum b) {
- unsigned char *p;
- int len;
- p = ssh2_mpint_fmt(b, &len);
- ssh2_pkt_addstring_start();
- ssh2_pkt_addstring_data(p, len);
- free(p);
-}
-void ssh2_pkt_send(void) {
- int cipherblk, maclen, padding, i;
- unsigned long outgoing_sequence = 0;
-
- /*
- * Add padding. At least four bytes, and must also bring total
- * length (minus MAC) up to a multiple of the block size.
- */
- cipherblk = cipher ? cipher->blksize : 8; /* block size */
- cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */
- padding = 4;
- padding += (cipherblk - (pktout.length + padding) % cipherblk) % cipherblk;
- pktout.data[4] = padding;
- for (i = 0; i < padding; i++)
- pktout.data[pktout.length + i] = random_byte();
- PUT_32BIT(pktout.data, pktout.length + padding - 4);
- if (csmac)
- csmac->generate(pktout.data, outgoing_sequence++,
- pktout.length + padding);
- if (cscipher)
- cscipher->encrypt(pktout.data, pktout.length + padding);
- maclen = csmac ? csmac->len : 0;
-#if 0
- debug(("Sending packet len=%d\r\n", pktout.length+padding+maclen));
- for (i = 0; i < pktout.length+padding+maclen; i++)
- debug((" %02x", (unsigned char)pktout.data[i]));
- debug(("\r\n"));
-#endif
- s_write(pktout.data, pktout.length + padding + maclen);
-}
-
-void sha_mpint(SHA_State *s, Bignum b) {
- unsigned char *p;
- int len;
- p = ssh2_mpint_fmt(b, &len);
- sha_string(s, p, len);
- free(p);
-}
-
-/*
- * SSH2 packet decode functions.
- */
-void ssh2_pkt_getstring(char **p, int *length) {
- *p = NULL;
- if (pktin.length - pktin.savedpos < 4)
- return;
- *length = GET_32BIT(pktin.data+pktin.savedpos);
- pktin.savedpos += 4;
- if (pktin.length - pktin.savedpos < *length)
- return;
- *p = pktin.data+pktin.savedpos;
- pktin.savedpos += *length;
-}
-Bignum ssh2_pkt_getmp(void) {
- char *p;
- int i, j, length;
- Bignum b;
-
- ssh2_pkt_getstring(&p, &length);
- if (!p)
- return NULL;
- if (p[0] & 0x80)
- fatalbox("internal error: Can't handle negative mpints");
- b = newbn((length+1)/2);
- for (i = 0; i < length; i++) {
- j = length - 1 - i;
- if (j & 1)
- b[j/2+1] |= ((unsigned char)p[i]) << 8;
- else
- b[j/2+1] |= ((unsigned char)p[i]);
- }
- return b;
-}
-
-void bndebug(char *string, Bignum b) {
- unsigned char *p;
- int i, len;
- p = ssh2_mpint_fmt(b, &len);
- debug(("%s", string));
- for (i = 0; i < len; i++)
- debug((" %02x", p[i]));
- debug(("\r\n"));
- free(p);
-}
-
-/*
- * Utility routine for decoding comma-separated strings in KEXINIT.
- */
-int in_commasep_string(char *needle, char *haystack, int haylen) {
- int needlen = strlen(needle);
- while (1) {
- /*
- * Is it at the start of the string?
- */
- if (haylen >= needlen && /* haystack is long enough */
- !memcmp(needle, haystack, needlen) && /* initial match */
- (haylen == needlen || haystack[needlen] == ',')
- /* either , or EOS follows */
- )
- return 1;
- /*
- * If not, search for the next comma and resume after that.
- * If no comma found, terminate.
- */
- while (haylen > 0 && *haystack != ',')
- haylen--, haystack++;
- if (haylen == 0)
- return 0;
- haylen--, haystack++; /* skip over comma itself */