Update kumina with HyBi-10+ support.
Pull 63aa9ce07 from https://github.com/kumina/wsproxy
This commit is contained in:
parent
40868636da
commit
545b6c80de
|
|
@ -98,7 +98,7 @@ implementations:
|
||||||
<td>yes</td>
|
<td>yes</td>
|
||||||
<td>yes</td>
|
<td>yes</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
<td>no</td>
|
<td>via inetd</td>
|
||||||
<td>yes</td>
|
<td>yes</td>
|
||||||
</tr> <tr>
|
</tr> <tr>
|
||||||
<th>Daemon</th>
|
<th>Daemon</th>
|
||||||
|
|
@ -106,7 +106,7 @@ implementations:
|
||||||
<td>yes</td>
|
<td>yes</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
<td>no</td>
|
<td>via inetd</td>
|
||||||
<td>yes</td>
|
<td>yes</td>
|
||||||
</tr> <tr>
|
</tr> <tr>
|
||||||
<th>SSL wss</th>
|
<th>SSL wss</th>
|
||||||
|
|
@ -178,7 +178,7 @@ implementations:
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
<td>no</td>
|
<td>no</td>
|
||||||
<td>no</td>
|
<td>yes</td>
|
||||||
<td>yes</td>
|
<td>yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
448
other/kumina.c
448
other/kumina.c
|
|
@ -32,19 +32,32 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
static pid_t other;
|
#define MAXOFRAME UINT16_MAX
|
||||||
|
#define HYBI10_ACCEPTHDRLEN 29
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define DPRINTF(fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DPRINTF(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static pid_t other = -1;
|
||||||
|
static int hybi10 = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
die(int exitcode)
|
die(int exitcode)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (other != -1)
|
||||||
kill(other, SIGTERM);
|
kill(other, SIGTERM);
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
}
|
}
|
||||||
|
|
@ -53,11 +66,11 @@ static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
fprintf(stderr, "usage: kumina minport maxport\n");
|
fprintf(stderr, "usage: wsproxy minport maxport\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static unsigned char
|
||||||
pgetc(FILE *fp)
|
pgetc(FILE *fp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -68,113 +81,8 @@ pgetc(FILE *fp)
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* UTF-8 */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pputc(FILE *fp, unsigned char ch)
|
putb64(FILE *out, const char *inb, size_t *inblen)
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = fputc(ch, fp);
|
|
||||||
if (ret == EOF)
|
|
||||||
die(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
decode(FILE *in, int outfd)
|
|
||||||
{
|
|
||||||
FILE *out;
|
|
||||||
int ch;
|
|
||||||
unsigned char och;
|
|
||||||
|
|
||||||
out = fdopen(outfd, "w");
|
|
||||||
if (out == NULL) {
|
|
||||||
perror("fdopen");
|
|
||||||
die(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
/* Frame header. */
|
|
||||||
ch = pgetc(in);
|
|
||||||
if (ch != 0x00) {
|
|
||||||
fprintf(stderr, "malformed frame header received\n");
|
|
||||||
die(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
/* Frame trailer. */
|
|
||||||
ch = pgetc(in);
|
|
||||||
if (ch == EOF)
|
|
||||||
die(0);
|
|
||||||
if (ch == 0xff) {
|
|
||||||
fflush(out);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UTF-8 character, only allowing points 0 to 255. */
|
|
||||||
if (ch < 0x80)
|
|
||||||
och = ch;
|
|
||||||
else if ((ch & 0xf3) == 0xc0) {
|
|
||||||
och = ch << 6;
|
|
||||||
ch = pgetc(in);
|
|
||||||
if ((ch & 0xc0) != 0x80)
|
|
||||||
goto malformed;
|
|
||||||
och |= ch & 0x3f;
|
|
||||||
} else
|
|
||||||
goto malformed;
|
|
||||||
pputc(out, och);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
malformed:
|
|
||||||
fprintf(stderr, "malformed UTF-8 sequence received\n");
|
|
||||||
die(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
encode(int in, int out)
|
|
||||||
{
|
|
||||||
unsigned char inbuf[512];
|
|
||||||
unsigned char outbuf[sizeof inbuf * 2 + 2];
|
|
||||||
unsigned char *op;
|
|
||||||
ssize_t len, i;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
len = read(in, inbuf, sizeof inbuf);
|
|
||||||
if (len == -1) {
|
|
||||||
perror("read");
|
|
||||||
die(1);
|
|
||||||
} else if (len == 0)
|
|
||||||
die(0);
|
|
||||||
|
|
||||||
op = outbuf;
|
|
||||||
/* Frame header. */
|
|
||||||
*op++ = 0x00;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
/* Encode data as UTF-8. */
|
|
||||||
if (inbuf[i] < 0x80)
|
|
||||||
*op++ = inbuf[i];
|
|
||||||
else {
|
|
||||||
*op++ = 0xc0 | (inbuf[i] >> 6);
|
|
||||||
*op++ = 0x80 | (inbuf[i] & 0x3f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Frame trailer. */
|
|
||||||
*op++ = 0xff;
|
|
||||||
assert(op <= outbuf + sizeof outbuf);
|
|
||||||
len = write(out, outbuf, op - outbuf);
|
|
||||||
if (len == -1) {
|
|
||||||
perror("write");
|
|
||||||
die(1);
|
|
||||||
} else if (len != op - outbuf)
|
|
||||||
die(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* base64 */
|
|
||||||
|
|
||||||
static void
|
|
||||||
putb64(FILE *out, char *inb, size_t *inblen)
|
|
||||||
{
|
{
|
||||||
char inbuf[5] = { 0 };
|
char inbuf[5] = { 0 };
|
||||||
unsigned char outbuf[3];
|
unsigned char outbuf[3];
|
||||||
|
|
@ -187,7 +95,7 @@ putb64(FILE *out, char *inb, size_t *inblen)
|
||||||
memcpy(inbuf, inb, *inblen);
|
memcpy(inbuf, inb, *inblen);
|
||||||
outbuflen = b64_pton(inbuf, outbuf, sizeof outbuf);
|
outbuflen = b64_pton(inbuf, outbuf, sizeof outbuf);
|
||||||
if (outbuflen <= 0) {
|
if (outbuflen <= 0) {
|
||||||
fprintf(stderr, "invalid Base64 data\n");
|
DPRINTF("invalid Base64 data");
|
||||||
die(1);
|
die(1);
|
||||||
}
|
}
|
||||||
if (fwrite(outbuf, outbuflen, 1, out) != 1) {
|
if (fwrite(outbuf, outbuflen, 1, out) != 1) {
|
||||||
|
|
@ -197,11 +105,178 @@ putb64(FILE *out, char *inb, size_t *inblen)
|
||||||
*inblen = 0;
|
*inblen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for HyBi10.
|
||||||
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
decode(FILE *in, int outfd)
|
hybi10_calcaccepthdr(const char *key, char *out)
|
||||||
|
{
|
||||||
|
SHA_CTX c;
|
||||||
|
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
SHA1_Init(&c);
|
||||||
|
SHA1_Update(&c, key, strlen(key));
|
||||||
|
SHA1_Update(&c, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36);
|
||||||
|
SHA1_Final(hash, &c);
|
||||||
|
|
||||||
|
r = b64_ntop(hash, sizeof hash, out, HYBI10_ACCEPTHDRLEN);
|
||||||
|
assert(r == HYBI10_ACCEPTHDRLEN - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
hybi10_getlength(FILE *in)
|
||||||
|
{
|
||||||
|
uint64_t len;
|
||||||
|
int lenlen;
|
||||||
|
unsigned char ch;
|
||||||
|
|
||||||
|
ch = pgetc(in);
|
||||||
|
if (!(ch & 0x80)) {
|
||||||
|
DPRINTF("mask bit not set");
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
ch &= ~0x80;
|
||||||
|
|
||||||
|
/* Two or eight bytes of input length? */
|
||||||
|
switch (ch) {
|
||||||
|
case 126:
|
||||||
|
lenlen = 2;
|
||||||
|
break;
|
||||||
|
case 127:
|
||||||
|
lenlen = 8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Small packet, length encoded directly. */
|
||||||
|
return (ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
while (lenlen-- > 0)
|
||||||
|
len = len << 8 | pgetc(in);
|
||||||
|
return (len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hybi10_getmasks(FILE *in, unsigned char masks[4])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
masks[i] = pgetc(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hybi10_decode(FILE *in, int outfd)
|
||||||
{
|
{
|
||||||
FILE *out;
|
FILE *out;
|
||||||
int ch;
|
unsigned char ch, masks[4];
|
||||||
|
char inb[4];
|
||||||
|
size_t inblen = 0;
|
||||||
|
uint64_t i, framelen;
|
||||||
|
|
||||||
|
out = fdopen(outfd, "w");
|
||||||
|
if (out == NULL) {
|
||||||
|
perror("fdopen");
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
/* Frame header. */
|
||||||
|
ch = pgetc(in);
|
||||||
|
if (ch != 0x81) {
|
||||||
|
DPRINTF("unsupported packet received: %#hhx", ch);
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Payload length. */
|
||||||
|
framelen = hybi10_getlength(in);
|
||||||
|
hybi10_getmasks(in, masks);
|
||||||
|
for (i = 0; i < framelen; i++) {
|
||||||
|
ch = pgetc(in) ^ masks[i % 4];
|
||||||
|
if (!((ch >= 'A' && ch <= 'Z') ||
|
||||||
|
(ch >= 'a' && ch <= 'z') ||
|
||||||
|
(ch >= '0' && ch <= '9') ||
|
||||||
|
ch == '+' || ch == '/' || ch == '=')) {
|
||||||
|
DPRINTF("non-Base64 character received");
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base64 character. */
|
||||||
|
inb[inblen++] = ch;
|
||||||
|
if (inblen == sizeof inb)
|
||||||
|
putb64(out, inb, &inblen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frame trailer. */
|
||||||
|
putb64(out, inb, &inblen);
|
||||||
|
if (fflush(out) == -1) {
|
||||||
|
perror("fflush");
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hybi10_encode(int in, int out)
|
||||||
|
{
|
||||||
|
unsigned char inbuf[MAXOFRAME / 4 * 3];
|
||||||
|
char outbuf[MAXOFRAME + 5]; /* Four-byte header + nul. */
|
||||||
|
ssize_t len, wlen;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
len = read(in, inbuf, sizeof inbuf);
|
||||||
|
if (len == -1) {
|
||||||
|
perror("read");
|
||||||
|
die(1);
|
||||||
|
} else if (len == 0)
|
||||||
|
die(0);
|
||||||
|
|
||||||
|
/* Encode data as Base64. */
|
||||||
|
len = b64_ntop(inbuf, len, outbuf + 4, sizeof outbuf - 4);
|
||||||
|
assert(len > 0 && len <= MAXOFRAME);
|
||||||
|
/* Frame header. */
|
||||||
|
outbuf[0] = 0x81;
|
||||||
|
outbuf[1] = 126;
|
||||||
|
outbuf[2] = len >> 8;
|
||||||
|
outbuf[3] = len;
|
||||||
|
len += 4;
|
||||||
|
|
||||||
|
wlen = write(out, outbuf, len);
|
||||||
|
if (wlen == -1) {
|
||||||
|
perror("write");
|
||||||
|
die(1);
|
||||||
|
} else if (wlen != len)
|
||||||
|
die(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for Hixie 76.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
hixie76_calcresponse(uint32_t key1, uint32_t key2, const char *key3, char *out)
|
||||||
|
{
|
||||||
|
MD5_CTX c;
|
||||||
|
char in[16] = {
|
||||||
|
key1 >> 24, key1 >> 16, key1 >> 8, key1,
|
||||||
|
key2 >> 24, key2 >> 16, key2 >> 8, key2,
|
||||||
|
key3[0], key3[1], key3[2], key3[3],
|
||||||
|
key3[4], key3[5], key3[6], key3[7]
|
||||||
|
};
|
||||||
|
|
||||||
|
MD5_Init(&c);
|
||||||
|
MD5_Update(&c, (void *)in, sizeof in);
|
||||||
|
MD5_Final((void *)out, &c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hixie76_decode(FILE *in, int outfd)
|
||||||
|
{
|
||||||
|
FILE *out;
|
||||||
|
unsigned char ch;
|
||||||
char inb[4];
|
char inb[4];
|
||||||
size_t inblen = 0;
|
size_t inblen = 0;
|
||||||
|
|
||||||
|
|
@ -215,32 +290,16 @@ decode(FILE *in, int outfd)
|
||||||
/* Frame header. */
|
/* Frame header. */
|
||||||
ch = pgetc(in);
|
ch = pgetc(in);
|
||||||
if (ch != 0x00) {
|
if (ch != 0x00) {
|
||||||
fprintf(stderr, "malformed frame header received\n");
|
DPRINTF("unsupported packet received: %#hhx", ch);
|
||||||
die(1);
|
die(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
while ((ch = pgetc(in)) != 0xff) {
|
||||||
ch = pgetc(in);
|
|
||||||
if (ch == EOF) {
|
|
||||||
putb64(out, inb, &inblen);
|
|
||||||
die(0);
|
|
||||||
}
|
|
||||||
/* Frame trailer. */
|
|
||||||
if (ch == 0xff) {
|
|
||||||
putb64(out, inb, &inblen);
|
|
||||||
if (fflush(out) == -1) {
|
|
||||||
perror("fflush");
|
|
||||||
die(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!((ch >= 'A' && ch <= 'Z') ||
|
if (!((ch >= 'A' && ch <= 'Z') ||
|
||||||
(ch >= 'a' && ch <= 'z') ||
|
(ch >= 'a' && ch <= 'z') ||
|
||||||
(ch >= '0' && ch <= '9') ||
|
(ch >= '0' && ch <= '9') ||
|
||||||
ch == '+' || ch == '/' || ch == '=')) {
|
ch == '+' || ch == '/' || ch == '=')) {
|
||||||
fprintf(stderr,
|
DPRINTF("non-Base64 character received");
|
||||||
"non-Base64 character received\n");
|
|
||||||
die(1);
|
die(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,14 +308,21 @@ decode(FILE *in, int outfd)
|
||||||
if (inblen == sizeof inb)
|
if (inblen == sizeof inb)
|
||||||
putb64(out, inb, &inblen);
|
putb64(out, inb, &inblen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Frame trailer. */
|
||||||
|
putb64(out, inb, &inblen);
|
||||||
|
if (fflush(out) == -1) {
|
||||||
|
perror("fflush");
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
encode(int in, int out)
|
hixie76_encode(int in, int out)
|
||||||
{
|
{
|
||||||
unsigned char inbuf[512];
|
unsigned char inbuf[MAXOFRAME / 4 * 3];
|
||||||
char outbuf[sizeof inbuf * 2 + 2];
|
char outbuf[MAXOFRAME + 2];
|
||||||
ssize_t len, wlen;
|
ssize_t len, wlen;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
@ -270,22 +336,20 @@ encode(int in, int out)
|
||||||
/* Frame header. */
|
/* Frame header. */
|
||||||
outbuf[0] = 0x00;
|
outbuf[0] = 0x00;
|
||||||
/* Encode data as Base64. */
|
/* Encode data as Base64. */
|
||||||
len = b64_ntop(inbuf, len, outbuf + 1, sizeof outbuf - 1) + 1;
|
len = b64_ntop(inbuf, len, outbuf + 1, sizeof outbuf - 1);
|
||||||
assert(len >= 1);
|
assert(len > 0 && len <= MAXOFRAME);
|
||||||
/* Frame footer. */
|
/* Frame trailer. */
|
||||||
outbuf[len++] = 0xff;
|
outbuf[len + 1] = 0xff;
|
||||||
|
|
||||||
wlen = write(out, outbuf, len);
|
wlen = write(out, outbuf, len + 2);
|
||||||
if (wlen == -1) {
|
if (wlen == -1) {
|
||||||
perror("write");
|
perror("write");
|
||||||
die(1);
|
die(1);
|
||||||
} else if (wlen != len)
|
} else if (wlen != len + 2)
|
||||||
die(0);
|
die(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
do_strndup(const char *str, size_t n)
|
do_strndup(const char *str, size_t n)
|
||||||
{
|
{
|
||||||
|
|
@ -331,44 +395,19 @@ parsehdrkey(const char *key)
|
||||||
return (spaces == 0 ? 0 : sum / spaces);
|
return (spaces == 0 ? 0 : sum / spaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
calcresponse(uint32_t key1, uint32_t key2, const char *key3, char *out)
|
|
||||||
{
|
|
||||||
MD5_CTX c;
|
|
||||||
char in[16];
|
|
||||||
|
|
||||||
in[0] = key1 >> 24;
|
|
||||||
in[1] = key1 >> 16;
|
|
||||||
in[2] = key1 >> 8;
|
|
||||||
in[3] = key1;
|
|
||||||
in[4] = key2 >> 24;
|
|
||||||
in[5] = key2 >> 16;
|
|
||||||
in[6] = key2 >> 8;
|
|
||||||
in[7] = key2;
|
|
||||||
memcpy(in + 8, key3, 8);
|
|
||||||
|
|
||||||
MD5_Init(&c);
|
|
||||||
MD5_Update(&c, (void *)in, sizeof in);
|
|
||||||
MD5_Final((void *)out, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
eat_flash_magic(void)
|
eat_flash_magic(void)
|
||||||
{
|
{
|
||||||
static const char flash_magic[] = "<policy-file-request/>";
|
static const char flash_magic[] = "<policy-file-request/>";
|
||||||
ssize_t i;
|
size_t i;
|
||||||
int ch;
|
char ch;
|
||||||
|
|
||||||
for (i = 0; i < sizeof flash_magic - 1; i++) {
|
for (i = 0; i < sizeof flash_magic - 1; i++) {
|
||||||
ch = getchar();
|
ch = pgetc(stdin);
|
||||||
if (ch == EOF) {
|
|
||||||
perror("getc");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* Not a Flash applet. Roll back. */
|
/* Not a Flash applet. Roll back. */
|
||||||
if (ch != flash_magic[i]) {
|
if (ch != flash_magic[i]) {
|
||||||
ungetc(ch, stdin);
|
ungetc(ch, stdin);
|
||||||
while (--i >= 0)
|
while (i-- > 0)
|
||||||
ungetc(flash_magic[i], stdin);
|
ungetc(flash_magic[i], stdin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -388,7 +427,8 @@ main(int argc, char *argv[])
|
||||||
struct sockaddr_in sa_in;
|
struct sockaddr_in sa_in;
|
||||||
struct sockaddr_in6 sa_in6;
|
struct sockaddr_in6 sa_in6;
|
||||||
} sa;
|
} sa;
|
||||||
char line[512], key3[8], response[16], *host = NULL, *origin = NULL;
|
char line[512], key3[8], *host = NULL,
|
||||||
|
*origin = NULL, *key = NULL, *protocol;
|
||||||
unsigned long minport, maxport, port;
|
unsigned long minport, maxport, port;
|
||||||
uint32_t key1 = 0, key2 = 0;
|
uint32_t key1 = 0, key2 = 0;
|
||||||
socklen_t salen;
|
socklen_t salen;
|
||||||
|
|
@ -423,31 +463,48 @@ main(int argc, char *argv[])
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (strncmp(line, "GET /", 5) != 0) {
|
if (strncmp(line, "GET /", 5) != 0) {
|
||||||
fprintf(stderr, "malformed HTTP header received\n");
|
DPRINTF("malformed HTTP header received");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (strncmp(line, "GET /kumina-monitoring/ ", 25) == 0)
|
if (strncmp(line, "GET /wsproxy-monitoring/ ", 25) == 0) {
|
||||||
monitoring = 1;
|
monitoring = 1;
|
||||||
|
port = 0; /* Keep compiler happy. */
|
||||||
|
} else if (minport == maxport) {
|
||||||
|
/* Simply ignore URL and connect to a single host. */
|
||||||
|
port = minport;
|
||||||
|
} else {
|
||||||
|
/* Multiplexing mode. Use port number in URL. */
|
||||||
port = strtoul(line + 5, NULL, 10);
|
port = strtoul(line + 5, NULL, 10);
|
||||||
if (!monitoring && (port < minport || port > maxport)) {
|
if (port < minport || port > maxport) {
|
||||||
fprintf(stderr, "port not allowed\n");
|
DPRINTF("port not allowed");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse HTTP headers. */
|
/* Parse HTTP headers. */
|
||||||
do {
|
do {
|
||||||
if (fgets(line, sizeof line, stdin) == NULL) {
|
if (fgets(line, sizeof line, stdin) == NULL) {
|
||||||
fprintf(stderr, "partial HTTP header received\n");
|
DPRINTF("partial HTTP header received");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (strncasecmp(line, "Host: ", 6) == 0) {
|
if (strncasecmp(line, "Host: ", 6) == 0) {
|
||||||
host = parsestring(line + 6);
|
host = parsestring(line + 6);
|
||||||
} else if (strncasecmp(line, "Origin: ", 8) == 0) {
|
} else if (strncasecmp(line, "Origin: ", 8) == 0) {
|
||||||
origin = parsestring(line + 8);
|
origin = parsestring(line + 8);
|
||||||
|
} else if (strncasecmp(line, "Sec-WebSocket-Key: ", 19) == 0) {
|
||||||
|
hybi10 = 1;
|
||||||
|
key = parsestring(line + 19);
|
||||||
} else if (strncasecmp(line, "Sec-WebSocket-Key1: ", 20) == 0) {
|
} else if (strncasecmp(line, "Sec-WebSocket-Key1: ", 20) == 0) {
|
||||||
key1 = parsehdrkey(line + 20);
|
key1 = parsehdrkey(line + 20);
|
||||||
} else if (strncasecmp(line, "Sec-WebSocket-Key2: ", 20) == 0) {
|
} else if (strncasecmp(line, "Sec-WebSocket-Key2: ", 20) == 0) {
|
||||||
key2 = parsehdrkey(line + 20);
|
key2 = parsehdrkey(line + 20);
|
||||||
|
} else if (strncasecmp(line, "Sec-WebSocket-Protocol: ",
|
||||||
|
24) == 0) {
|
||||||
|
protocol = parsestring(line + 24);
|
||||||
|
if (strcmp(protocol, "base64") != 0) {
|
||||||
|
DPRINTF("Unsupported protocol: %s", protocol);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (strcmp(line, "\n") != 0 && strcmp(line, "\r\n") != 0);
|
} while (strcmp(line, "\n") != 0 && strcmp(line, "\r\n") != 0);
|
||||||
|
|
||||||
|
|
@ -461,8 +518,9 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Eight byte payload. */
|
/* Eight byte payload. */
|
||||||
|
if (!hybi10)
|
||||||
if (fread(key3, sizeof key3, 1, stdin) != 1) {
|
if (fread(key3, sizeof key3, 1, stdin) != 1) {
|
||||||
fprintf(stderr, "key data missing\n");
|
DPRINTF("key data missing");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,7 +541,7 @@ main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown protocol. */
|
/* Unknown protocol. */
|
||||||
fprintf(stderr, "unsupported network protocol\n");
|
DPRINTF("unsupported network protocol");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
s = socket(sa.sa.sa_family, SOCK_STREAM, 0);
|
s = socket(sa.sa.sa_family, SOCK_STREAM, 0);
|
||||||
|
|
@ -496,15 +554,29 @@ main(int argc, char *argv[])
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send HTTP response. */
|
/* Send HTTP response, based on protocol version. */
|
||||||
calcresponse(key1, key2, key3, response);
|
if (hybi10) {
|
||||||
|
char accepthdr[HYBI10_ACCEPTHDRLEN];
|
||||||
|
|
||||||
|
hybi10_calcaccepthdr(key, accepthdr);
|
||||||
|
printf("HTTP/1.1 101 Switching Protocols\r\n"
|
||||||
|
"Upgrade: websocket\r\n"
|
||||||
|
"Connection: Upgrade\r\n"
|
||||||
|
"Sec-WebSocket-Accept: %s\r\n"
|
||||||
|
"Sec-WebSocket-Protocol: base64\r\n\r\n", accepthdr);
|
||||||
|
} else {
|
||||||
|
char response[MD5_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
hixie76_calcresponse(key1, key2, key3, response);
|
||||||
printf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
|
printf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
|
||||||
"Upgrade: WebSocket\r\n"
|
"Upgrade: WebSocket\r\n"
|
||||||
"Connection: Upgrade\r\n"
|
"Connection: Upgrade\r\n"
|
||||||
"Sec-WebSocket-Origin: %s\r\n"
|
"Sec-WebSocket-Origin: %s\r\n"
|
||||||
"Sec-WebSocket-Location: ws://%s/%lu\r\n"
|
"Sec-WebSocket-Location: ws://%s/%lu\r\n"
|
||||||
"Sec-WebSocket-Protocol: base64\r\n\r\n", origin, host, port);
|
"Sec-WebSocket-Protocol: base64\r\n\r\n",
|
||||||
|
origin, host, port);
|
||||||
fwrite(response, sizeof response, 1, stdout);
|
fwrite(response, sizeof response, 1, stdout);
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
/* Spawn child process for bi-directional pipe. */
|
/* Spawn child process for bi-directional pipe. */
|
||||||
|
|
@ -514,10 +586,16 @@ main(int argc, char *argv[])
|
||||||
return (1);
|
return (1);
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
other = getppid();
|
other = getppid();
|
||||||
decode(stdin, s);
|
if (hybi10)
|
||||||
|
hybi10_decode(stdin, s);
|
||||||
|
else
|
||||||
|
hixie76_decode(stdin, s);
|
||||||
} else {
|
} else {
|
||||||
other = pid;
|
other = pid;
|
||||||
encode(s, STDOUT_FILENO);
|
if (hybi10)
|
||||||
|
hybi10_encode(s, STDOUT_FILENO);
|
||||||
|
else
|
||||||
|
hixie76_encode(s, STDOUT_FILENO);
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue