This commit is contained in:
Jeremy White 2017-04-23 13:57:54 +00:00 committed by GitHub
commit 2ee84c621d
3 changed files with 79 additions and 45 deletions

View File

@ -268,33 +268,43 @@ int decode_hixie(char *src, size_t srclength,
int encode_hybi(u_char const *src, size_t srclength, int encode_hybi(u_char const *src, size_t srclength,
char *target, size_t targsize, unsigned int opcode) char *target, size_t targsize, unsigned int opcode)
{ {
unsigned long long b64_sz, len_offset = 1, payload_offset = 2, len = 0; unsigned long long pay_sz, len_offset = 1, payload_offset = 2, len = 0;
if ((int)srclength <= 0) if ((int)srclength <= 0)
{ {
return 0; return 0;
} }
b64_sz = ((srclength - 1) / 3) * 4 + 4; if (opcode == 1)
pay_sz = ((srclength - 1) / 3) * 4 + 4;
if (opcode == 2)
pay_sz = srclength;
target[0] = (char)(opcode & 0x0F | 0x80); target[0] = (char)(opcode & 0x0F | 0x80);
if (b64_sz <= 125) { if (pay_sz <= 125) {
target[1] = (char) b64_sz; target[1] = (char) pay_sz;
payload_offset = 2; payload_offset = 2;
} else if ((b64_sz > 125) && (b64_sz < 65536)) { } else if ((pay_sz > 125) && (pay_sz < 65536)) {
target[1] = (char) 126; target[1] = (char) 126;
*(u_short*)&(target[2]) = htons(b64_sz); *(u_short*)&(target[2]) = htons(pay_sz);
payload_offset = 4; payload_offset = 4;
} else { } else {
handler_emsg("Sending frames larger than 65535 bytes not supported\n"); handler_emsg("Sending frames larger than 65535 bytes not supported\n");
return -1; return -1;
//target[1] = (char) 127; //target[1] = (char) 127;
//*(u_long*)&(target[2]) = htonl(b64_sz); //*(u_long*)&(target[2]) = htonl(pay_sz);
//payload_offset = 10; //payload_offset = 10;
} }
if (opcode == 1) {
len = b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset); len = b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset);
}
if (opcode == 2) {
len = srclength;
memcpy(target + payload_offset, src, len);
}
if (len < 0) { if (len < 0) {
return len; return len;
@ -316,7 +326,7 @@ int decode_hybi(unsigned char *src, size_t srclength,
*left = srclength; *left = srclength;
frame = src; frame = src;
//printf("Deocde new frame\n"); //printf("Decode new frame\n");
while (1) { while (1) {
// Need at least two bytes of the header // Need at least two bytes of the header
// Find beginning of next frame. First time hdr_length, masked and // Find beginning of next frame. First time hdr_length, masked and
@ -379,9 +389,11 @@ int decode_hybi(unsigned char *src, size_t srclength,
return -1; return -1;
} }
if (*opcode == 1) {
// Terminate with a null for base64 decode // Terminate with a null for base64 decode
save_char = payload[payload_length]; save_char = payload[payload_length];
payload[payload_length] = '\0'; payload[payload_length] = '\0';
}
// unmask the data // unmask the data
mask = payload - 4; mask = payload - 4;
@ -389,6 +401,7 @@ int decode_hybi(unsigned char *src, size_t srclength,
payload[i] ^= mask[i%4]; payload[i] ^= mask[i%4];
} }
if (*opcode == 1) {
// base64 decode the data // base64 decode the data
len = b64_pton((const char*)payload, target+target_offset, targsize); len = b64_pton((const char*)payload, target+target_offset, targsize);
@ -398,6 +411,13 @@ int decode_hybi(unsigned char *src, size_t srclength,
handler_emsg("Base64 decode error code %d", len); handler_emsg("Base64 decode error code %d", len);
return len; return len;
} }
}
if (*opcode == 2) {
len = payload_length;
memcpy(target + target_offset, payload, len);
}
target_offset += len; target_offset += len;
//printf(" len %d, raw %s\n", len, frame); //printf(" len %d, raw %s\n", len, frame);
@ -409,6 +429,7 @@ int decode_hybi(unsigned char *src, size_t srclength,
} }
*left = remaining; *left = remaining;
//printf(" returning %d, %d left\n", target_offset, *left);
return target_offset; return target_offset;
} }
@ -481,6 +502,10 @@ int parse_handshake(ws_ctx_t *ws_ctx, char *handshake) {
end = strstr(start, "\r\n"); end = strstr(start, "\r\n");
strncpy(headers->protocols, start, end-start); strncpy(headers->protocols, start, end-start);
headers->protocols[end-start] = '\0'; headers->protocols[end-start] = '\0';
if (strstr(headers->protocols, "binary"))
ws_ctx->binary = 1;
else
ws_ctx->binary = 0;
} else { } else {
// Hixie 75 or 76 // Hixie 75 or 76
ws_ctx->hybi = 0; ws_ctx->hybi = 0;

View File

@ -44,6 +44,7 @@ typedef struct {
SSL *ssl; SSL *ssl;
int hixie; int hixie;
int hybi; int hybi;
int binary;
headers_t *headers; headers_t *headers;
char *cin_buf; char *cin_buf;
char *cout_buf; char *cout_buf;

View File

@ -112,6 +112,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
if (FD_ISSET(target, &wlist)) { if (FD_ISSET(target, &wlist)) {
len = tout_end-tout_start; len = tout_end-tout_start;
bytes = send(target, ws_ctx->tout_buf + tout_start, len, 0); bytes = send(target, ws_ctx->tout_buf + tout_start, len, 0);
//printf("wrote %d bytes of an intended %d bytes\n", bytes, len);
if (pipe_error) { break; } if (pipe_error) { break; }
if (bytes < 0) { if (bytes < 0) {
handler_emsg("target connection error: %s\n", handler_emsg("target connection error: %s\n",
@ -149,13 +150,25 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
bytes = recv(target, ws_ctx->cin_buf, DBUFSIZE , 0); bytes = recv(target, ws_ctx->cin_buf, DBUFSIZE , 0);
if (pipe_error) { break; } if (pipe_error) { break; }
if (bytes <= 0) { if (bytes <= 0) {
unsigned char term_buf[48];
unsigned char term_rc[2] = {0x0,0};
handler_emsg("target closed connection\n"); handler_emsg("target closed connection\n");
bytes = encode_hybi(term_rc, 2, term_buf, sizeof(term_buf), 2);
term_buf[0] |= 8;
send(ws_ctx->sockfd, term_buf, bytes, 0);
shutdown(ws_ctx->sockfd, SHUT_WR);
close(target);
close(ws_ctx->sockfd);
break; break;
} }
else {
cout_start = 0; cout_start = 0;
if (ws_ctx->hybi) { if (ws_ctx->hybi) {
cout_end = encode_hybi(ws_ctx->cin_buf, bytes, cout_end = encode_hybi(ws_ctx->cin_buf, bytes,
ws_ctx->cout_buf, BUFSIZE, 1); ws_ctx->cout_buf, BUFSIZE, ws_ctx->binary ? 2 : 1);
} else { } else {
cout_end = encode_hixie(ws_ctx->cin_buf, bytes, cout_end = encode_hixie(ws_ctx->cin_buf, bytes,
ws_ctx->cout_buf, BUFSIZE); ws_ctx->cout_buf, BUFSIZE);
@ -173,6 +186,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
} }
traffic("{"); traffic("{");
} }
}
if (FD_ISSET(client, &rlist)) { if (FD_ISSET(client, &rlist)) {
bytes = ws_recv(ws_ctx, ws_ctx->tin_buf + tin_end, BUFSIZE-1); bytes = ws_recv(ws_ctx, ws_ctx->tin_buf + tin_end, BUFSIZE-1);
@ -181,6 +195,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
handler_emsg("client closed connection\n"); handler_emsg("client closed connection\n");
break; break;
} }
tin_end += bytes; tin_end += bytes;
/* /*
printf("before decode: "); printf("before decode: ");
@ -206,13 +221,6 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
break; break;
} }
/*
printf("decoded: ");
for (i=0; i< len; i++) {
printf("%u,", (unsigned char) *(ws_ctx->tout_buf+i));
}
printf("\n");
*/
if (len < 0) { if (len < 0) {
handler_emsg("decoding error\n"); handler_emsg("decoding error\n");
break; break;