lists.torproject.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
tor-commits
July 2012
----- 2025 -----
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
tor-commits@lists.torproject.org
14 participants
949 discussions
Start a n
N
ew thread
[stegotorus/master] git-svn-id: svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@126 a58ff0ac-194c-e011-a152-003048836090
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 5e617e61d1165df71237147dc60400c2b5f47ec5 Author: Vinod Yegneswaran <vinod(a)csl.sri.com> Date: Sun Nov 6 02:46:06 2011 +0000 git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@126
a58ff0ac-194c-e011-a152-003048836090 --- src/steg/payloads.c | 59 ++++++++++++++++++++++++++++++++++++++++---------- start-server.csh | 5 +--- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/steg/payloads.c b/src/steg/payloads.c index 02be31b..c683f77 100644 --- a/src/steg/payloads.c +++ b/src/steg/payloads.c @@ -303,19 +303,7 @@ void gen_rfc_1123_date(char* buf, int buf_size) { -/* sample response header */ -/* - -HTTP/1.1 200 OK -Date: Fri, 21 Oct 2011 19:09:49 GMT -Server: Apache -Content-Length: 1441 -* Content-Encoding: gzip -Content-Type: text/html;charset=UTF-8 -* Keep-Alive: timeout=15, max=93 -Connection: close -*/ int gen_response_header(char* content_type, int gzip, int length, char* buf, int buflen) { @@ -501,6 +489,52 @@ unsigned int find_client_payload(char* buf, int len, int type) { * todo: * Use a more efficient regular expression matching algo */ + + + +int skipJSPattern(char *cp, int len) { + int i,j; + + char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while", + "else", "for", "document", "write", "writeln", "true", + "false", "True", "False", "window", "indexOf", "navigator", "case", "if"}; + + if (len < 1) return 0; + + // change the limit to 21 to enable if as a keyword + for (i=0; i < 20; i++) { + char* word = keywords[i]; + + if (len <= (int) strlen(word)) + continue; + + if (word[0] != cp[0]) + continue; + + for (j=1; j < (int) strlen(word); j++) { + if (isxdigit(word[j])) { + if (!isxdigit(cp[j])) + goto next_word; + else + continue; + } + + if (cp[j] != word[j]) + goto next_word; + } + if (!isalnum(cp[j])) + return strlen(word)+1; + + next_word: + continue; + } + + return 0; +} + + +/* + int skipJSPattern (char *cp, int len) { // log_debug("Turning off skipJSPattern for debugging"); @@ -561,6 +595,7 @@ int skipJSPattern (char *cp, int len) { return 0; } +*/ int isalnum_ (char c) { diff --git a/start-server.csh b/start-server.csh index eb421c4..b7d61e6 100644 --- a/start-server.csh +++ b/start-server.csh @@ -2,8 +2,5 @@ setenv EVENT_NOKQUEUE yes # ./obfsproxy --log-min-severity=debug chop server 87.73.82.145:8080 127.0.0.1:8080 127.0.0.1:8081 # ./obfsproxy --log-min-severity=warn chop server 87.73.82.145:8080 127.0.0.1:8080 127.0.0.1:8081 -#./obfsproxy --log-min-severity=error chop server 87.73.82.145:8080 127.0.0.1:8080 127.0.0.1:8081 +./obfsproxy --log-min-severity=error chop server 87.73.82.145:8080 127.0.0.1:8080 127.0.0.1:8081 -# ./obfsproxy --log-min-severity=debug chop server 87.73.82.145:8080 128.18.9.71:8080 128.18.9.71:8081 -# ./obfsproxy --log-min-severity=warn chop server 87.73.82.145:8080 128.18.9.71:8080 128.18.9.71:8081 -./obfsproxy --log-min-severity=error chop server 87.73.82.145:8080 128.18.9.71:8080 128.18.9.71:8081
1
0
0
0
[stegotorus/master] added gzip encoding to jsSteg
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 2d5331fb2bd8b1197be8c7cb4fc43c7790102902 Author: Steven Cheung <cheung(a)csl.sri.com> Date: Thu Nov 3 00:11:21 2011 +0000 added gzip encoding to jsSteg git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@118
a58ff0ac-194c-e011-a152-003048836090 --- src/steg/jsSteg.c | 551 ++++++++++++++++++++++++--------------------------- src/steg/jsSteg.h | 15 ++- src/steg/payloads.c | 18 +- 3 files changed, 277 insertions(+), 307 deletions(-) diff --git a/src/steg/jsSteg.c b/src/steg/jsSteg.c index 9c67949..a323d44 100644 --- a/src/steg/jsSteg.c +++ b/src/steg/jsSteg.c @@ -32,6 +32,101 @@ int isxString(char *str) { /* + * isGzipContent(char *msg) + * + * If the HTTP header of msg specifies that the content is gzipped, + * this function returns 1; otherwise, it returns 0 + * + * Assumptions: + * msg is null terminated + * + */ +int isGzipContent (char *msg) { + char *ptr = msg, *end; + int gzipFlag = 0; + + if (!strstr(msg, "\r\n\r\n")) + return 0; + + while (1) { + end = strstr(ptr, "\r\n"); + if (end == NULL) { + break; + } + + if (!strncmp(ptr, "Content-Encoding: gzip", 22)) { + gzipFlag = 1; + break; + } + + if (!strncmp(end, "\r\n\r\n", 4)){ + break; + } + ptr = end+2; + } + + return gzipFlag; +} + + +/* + * findContentType(char *msg) + * + * If the HTTP header of msg specifies that the content type: + * case (content type) + * javascript: return HTTP_CONTENT_JAVASCRIPT + * pdf: return HTTP_CONTENT_PDF + * shockwave: return HTTP_CONTENT_SWF + * html: return HTTP_CONTENT_HTML + * otherwise: return 0 + * + * Assumptions: + * msg is null terminated + * + */ +int findContentType (char *msg) { + char *ptr = msg, *end; + + if (!strstr(msg, "\r\n\r\n")) + return 0; + + while (1) { + end = strstr(ptr, "\r\n"); + if (end == NULL) { + break; + } + + if (!strncmp(ptr, "Content-Type:", 13)) { + + if (!strncmp(ptr+14, "text/javascript", 15) || + !strncmp(ptr+14, "application/javascript", 22) || + !strncmp(ptr+14, "application/x-javascript", 24)) { + return HTTP_CONTENT_JAVASCRIPT; + } + if (!strncmp(ptr+14, "text/html", 9)) { + return HTTP_CONTENT_HTML; + } + if (!strncmp(ptr+14, "application/pdf", 15) || + !strncmp(ptr+14, "application/x-pdf", 17)) { + return HTTP_CONTENT_PDF; + } + if (!strncmp(ptr+14, "application/x-shockwave-flash", strlen("application/x-shockwave-flash"))) { + return HTTP_CONTENT_SWF; + } + } + + if (!strncmp(end, "\r\n\r\n", 4)){ + break; + } + ptr = end+2; + } + + return 0; +} + + + +/* * int encode(char *data, char *jTemplate, char *jData, * unsigned int dlen, unsigned int jtlen, unsigned int jdlen) * @@ -618,205 +713,175 @@ x_http2_server_JS_transmit (steg_t* s, struct evbuffer *source, conn_t *conn, un int nv; struct evbuffer *dest = conn_get_outbound(conn); size_t sbuflen = evbuffer_get_length(source); - char outbuf[HTTP_MSG_BUF_SIZE]; + char *hend, *jsTemplate = NULL, *outbuf, *outbuf2; char data[(int) sbuflen*2]; - unsigned int datalen; - char newHdr[MAX_RESP_HDR_SIZE]; - int newHdrLen = 0; - - size_t sofar = 0; - unsigned int cnt = 0; - int r; - - - - // by dynamically configuring the size returned by x_http2_transmit_room(), - // we can ensure that the size of data (source) is less than the max - // data length the JavaScript (jsTemplate) can encode - - - - // do { - int i; - unsigned int jsLen; - int mode; - char *hend; - unsigned int hLen; - unsigned int mjs = 0; - - char *jsTemplate = NULL; - int jsTemplateSize = 0; - - - - - /* int hdrLen; - int content_len; - int fin2; - - char* tmp; - char data2[20000]; - int decCnt; - */ - - datalen = 0; - - - log_debug("sbuflen = %d sofar = %d\n", (int) sbuflen, (int) sofar); - - - if (content_type != HTTP_CONTENT_JAVASCRIPT && - content_type != HTTP_CONTENT_HTML) { - log_warn("SERVER ERROR: Unknown content type (%d)", content_type); - return -1; - } - - // log_debug("SERVER: dumping data with length %d:", (int) sbuflen); - // evbuffer_dump(source, stderr); - // Convert data in 'source' to hexadecimal and write it to data - - nv = evbuffer_peek(source, sbuflen - sofar, NULL, NULL, 0); - iv = xzalloc(sizeof(struct evbuffer_iovec) * nv); - - if (evbuffer_peek(source, sbuflen - sofar, NULL, iv, nv) != nv) { - free(iv); - return -1; - } - - // jsTemplate should be init already, by x_http2_new or the previous invocation - // of this function - - if (content_type == HTTP_CONTENT_JAVASCRIPT) { - mjs = get_max_JS_capacity(); - } else if (content_type == HTTP_CONTENT_HTML) { - mjs = get_max_HTML_capacity(); - } - - if (mjs <= 0) { - log_warn("SERVER ERROR: No JavaScript found in jsTemplate"); - return -1; - } + unsigned int datalen = 0, cnt = 0, mjs = 0; + int r, i, mode, jsLen, hLen, cLen, newHdrLen = 0, outbuf2len; + + int gzipMode = JS_GZIP_RESP; - if (sbuflen > (size_t) mjs) { - log_warn("SERVER ERROR: (server_transmit) jsTemplate cannot accommodate data %d %dn", - (int) sbuflen, (int) mjs); - return -1; - } - - cnt = 0; + log_debug("sbuflen = %d\n", (int) sbuflen); - for (i = 0; i < nv; i++) { - const unsigned char *p = iv[i].iov_base; - const unsigned char *limit = p + iv[i].iov_len; - char c; + if (content_type != HTTP_CONTENT_JAVASCRIPT && + content_type != HTTP_CONTENT_HTML) { + log_warn("SERVER ERROR: Unknown content type (%d)", content_type); + return -1; + } - while (p < limit && cnt < sbuflen-sofar) { - c = *p++; - data[datalen] = "0123456789abcdef"[(c & 0xF0) >> 4]; - data[datalen+1] = "0123456789abcdef"[(c & 0x0F) >> 0]; - datalen += 2; - cnt++; - } - } + // log_debug("SERVER: dumping data with length %d:", (int) sbuflen); + // evbuffer_dump(source, stderr); - log_debug("SERVER encoded data in hex string (len %d):", datalen); - // buf_dump((unsigned char*)data, datalen, stderr); + nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0); + iv = xzalloc(sizeof(struct evbuffer_iovec) * nv); + if (evbuffer_peek(source, sbuflen, NULL, iv, nv) != nv) { free(iv); + return -1; + } + if (content_type == HTTP_CONTENT_JAVASCRIPT) { + mjs = get_max_JS_capacity(); + } else if (content_type == HTTP_CONTENT_HTML) { + mjs = get_max_HTML_capacity(); + } + if (mjs <= 0) { + log_warn("SERVER ERROR: No JavaScript found in jsTemplate"); + return -1; + } - if (get_payload(content_type, datalen, &jsTemplate, &jsTemplateSize) == 1) { - log_debug("SERVER found the next HTTP response template with size %d", jsTemplateSize); - } else { - log_warn("SERVER couldn't find the next HTTP response template; reusing the previous one"); + if (sbuflen > (size_t) mjs) { + log_warn("SERVER ERROR: jsTemplate cannot accommodate data %d %dn", + (int) sbuflen, (int) mjs); + return -1; + } + + // Convert data in 'source' to hexadecimal and write it to data + cnt = 0; + for (i = 0; i < nv; i++) { + const unsigned char *p = iv[i].iov_base; + const unsigned char *limit = p + iv[i].iov_len; + char c; + + while (p < limit && cnt < sbuflen) { + c = *p++; + data[datalen] = "0123456789abcdef"[(c & 0xF0) >> 4]; + data[datalen+1] = "0123456789abcdef"[(c & 0x0F) >> 0]; + datalen += 2; + cnt++; } + } - log_debug("MJS %d %d", datalen, mjs); - + free(iv); + log_debug("SERVER encoded data in hex string (len %d):", datalen); + // buf_dump((unsigned char*)data, datalen, stderr); - if (jsTemplate == NULL) { - fprintf(stderr, "NO suitable payload found %d %d\n", datalen, mjs); - exit(-1); - } - // use encodeHTTPBody to embed data in the JS jsTemplate - // assumption: jsTemplate is null-terminated + if (get_payload(content_type, datalen, &jsTemplate, &jsLen) == 1) { + log_debug("SERVER found the applicable HTTP response template with size %d", jsLen); + } else { + log_warn("SERVER couldn't find the applicable HTTP response template"); + return -1; + } - log_debug("strlen(jsTemplate) = %d", (int)strlen(jsTemplate)); - log_debug("jsTemplateSize = %d", jsTemplateSize); - // unsigned int jsLen = strlen(jsTemplate); - jsLen = jsTemplateSize; + // log_debug("MJS %d %d", datalen, mjs); + if (jsTemplate == NULL) { + log_warn("NO suitable payload found %d %d", datalen, mjs); + return -1; + } + // assumption: jsTemplate is null-terminated + hend = strstr(jsTemplate, "\r\n\r\n"); + if (hend == NULL) { + log_warn("Unable to find end of header in the HTTP template"); + return -1; + } - mode = has_eligible_HTTP_content (jsTemplate, jsLen, HTTP_CONTENT_JAVASCRIPT); - hend = strstr(jsTemplate, "\r\n\r\n"); - if (hend == NULL) { - log_warn("Unable to find end of header in the HTTP template"); - return -1; - } + mode = has_eligible_HTTP_content (jsTemplate, jsLen, HTTP_CONTENT_JAVASCRIPT); - log_debug("SERVER: using HTTP resp template of length = %d\n", jsLen); - // log_debug("HTTP resp tempmlate:"); - // buf_dump((unsigned char*)jsTemplate, jsLen, stderr); + // log_debug("SERVER: using HTTP resp template of length = %d", jsLen); + // log_debug("HTTP resp tempmlate:"); + // buf_dump((unsigned char*)jsTemplate, jsLen, stderr); - hLen = hend+4-jsTemplate; - r = encodeHTTPBody(data, hend+4, outbuf, datalen, jsLen-hLen, HTTP_MSG_BUF_SIZE, mode); + hLen = hend+4-jsTemplate; + cLen = jsLen - hLen; + outbuf = malloc(cLen); + if (outbuf == NULL) { + log_warn("malloc for outbuf fails"); + return -1; + } - if (r < 0 || ((unsigned int) r < datalen)) { - fprintf(stderr, "incomplete data encoding\n"); - exit(-1); - log_debug("SERVER ERROR: Incomplete data encoding"); - return -1; - } + r = encodeHTTPBody(data, hend+4, outbuf, datalen, cLen, cLen, mode); - if (mode == CONTENT_JAVASCRIPT) { // JavaScript in HTTP body - newHdrLen = gen_response_header((char*) "application/x-javascript", 0, jsLen-hLen, newHdr, sizeof(newHdr)); - } else if (mode == CONTENT_HTML_JAVASCRIPT) { // JavaScript(s) embedded in HTML doc - newHdrLen = gen_response_header((char*) "text/html", 0, jsLen-hLen, newHdr, sizeof(newHdr)); - } else { // unknown mode - log_warn("SERVER ERROR: unknown mode for creating the HTTP response header"); - return -1; - } - if (newHdrLen < 0) { - log_warn("SERVER ERROR: gen_response_header fails for jsSteg"); - return -1; - } + if (r < 0 || ((unsigned int) r < datalen)) { + log_warn("SERVER ERROR: Incomplete data encoding"); + return -1; + } - if (evbuffer_add(dest, newHdr, newHdrLen)) { - log_warn("SERVER ERROR: evbuffer_add() fails for newHdr"); + // work in progress + if (gzipMode == 1) { + // conservative estimate: + // sizeof outbuf2 = cLen + 10-byte for gzip header + 8-byte for crc + outbuf2 = malloc(cLen+18); + if (outbuf2 == NULL) { + log_warn("malloc for outbuf2 fails"); return -1; } - // if (evbuffer_add(dest, jsTemplate, hLen)) { - // log_warn("SERVER ERROR: evbuffer_add() fails for jsTemplate"); - // return -1; - // } + outbuf2len = gzDeflate(outbuf, cLen, outbuf2, cLen+18, time(NULL)); - - if (evbuffer_add(dest, outbuf, jsLen-hLen)) { - log_warn("SERVER ERROR: evbuffer_add() fails for outbuf"); + if (outbuf2len <= 0) { + log_warn("gzDeflate for outbuf fails"); + free(outbuf2); return -1; } + free(outbuf); - sofar += datalen/2; - evbuffer_drain(source, datalen/2); - // } while (sbuflen > sofar); - + } else { + outbuf2 = outbuf; + outbuf2len = cLen; + } - // fprintf(stderr, "SERVER TRANSMITTED payload of size %d\n", (int) sbuflen); + // outbuf2 points to the HTTP payload (of length outbuf2len) to be sent + + if (mode == CONTENT_JAVASCRIPT) { // JavaScript in HTTP body + newHdrLen = gen_response_header((char*) "application/x-javascript", gzipMode, + outbuf2len, newHdr, sizeof(newHdr)); + } else if (mode == CONTENT_HTML_JAVASCRIPT) { // JavaScript(s) embedded in HTML doc + newHdrLen = gen_response_header((char*) "text/html", gzipMode, + outbuf2len, newHdr, sizeof(newHdr)); + } else { // unknown mode + log_warn("SERVER ERROR: unknown mode for creating the HTTP response header"); + free(outbuf2); + return -1; + } + if (newHdrLen < 0) { + log_warn("SERVER ERROR: gen_response_header fails for jsSteg"); + free(outbuf2); + return -1; + } - // obtain a usable HTTP response template for the next data, and - // modify jsTemplateCapacity + // newHdr points to the HTTP header (of length newHdrLen) to be sent + if (evbuffer_add(dest, newHdr, newHdrLen)) { + log_warn("SERVER ERROR: evbuffer_add() fails for newHdr"); + free(outbuf2); + return -1; + } - log_debug("SERVER finding the next HTTP response template"); + if (evbuffer_add(dest, outbuf2, outbuf2len)) { + log_warn("SERVER ERROR: evbuffer_add() fails for outbuf2"); + free(outbuf2); + return -1; + } + evbuffer_drain(source, sbuflen); + free(outbuf2); conn_close_after_transmit(conn); // downcast_steg(s)->have_transmitted = 1; return 0; @@ -836,17 +901,14 @@ x_http2_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, char buf[10]; char respMsg[HTTP_MSG_BUF_SIZE]; char data[HTTP_MSG_BUF_SIZE]; + char buf2[HTTP_MSG_BUF_SIZE]; - unsigned char *field; - unsigned char *fieldStart; - unsigned char* fieldEnd; - unsigned char *fieldValStart; + unsigned char *field, *fieldStart, *fieldEnd, *fieldValStart; char *httpBody; + int decCnt, fin, i, j, k, gzipMode=0, httpBodyLen, buf2len, contentType = 0; ev_ssize_t r; - int mode, decCnt, fin; struct evbuffer * scratch; - int i,j,k; char c; @@ -897,9 +959,7 @@ x_http2_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, if (response_len > evbuffer_get_length(source)) return RECV_INCOMPLETE; - - - + // read the entire HTTP resp if (response_len < HTTP_MSG_BUF_SIZE) { r = evbuffer_copyout(source, respMsg, response_len); @@ -921,21 +981,37 @@ x_http2_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, log_debug("CLIENT received HTTP response with length %d\n", response_len); // buf_dump((unsigned char*)respMsg, response_len, stderr); // log_debug("HTTP response header:"); - // buf_dump((unsigned char*)respMsg, hdrLen, stderr); - - httpBody = respMsg + hdrLen; - - log_debug("CLIENT Before has_eligible HTTP content\n"); - // find out if the resp is a JavaScript or JS embedded in HTML doc - mode = has_eligible_HTTP_content (respMsg, response_len, HTTP_CONTENT_JAVASCRIPT); - if (mode != 1 && mode != 2) { - log_debug("CLIENT ERROR: HTTP response not useful for jsSteg (mode %d)", mode); + // buf_dump((unsigned char*)respMsg, hdrLen+80, stderr); + + contentType = findContentType (respMsg); + if (contentType != HTTP_CONTENT_JAVASCRIPT && contentType != HTTP_CONTENT_HTML) { + log_warn("ERROR: Invalid content type (%d)", contentType); return RECV_BAD; } - log_debug("CLIENT Before decodeHTTPBody; mode: %d\n", mode); - - decCnt = decodeHTTPBody(httpBody, data, response_len-hdrLen, HTTP_MSG_BUF_SIZE, &fin, mode); + httpBody = respMsg + hdrLen; + httpBodyLen = response_len - hdrLen; + + gzipMode = isGzipContent(respMsg); + if (gzipMode) { + log_debug("gzip content encoding detected"); + buf2len = gzInflate(httpBody, httpBodyLen, buf2, HTTP_MSG_BUF_SIZE); + if (buf2len <= 0) { + log_warn("gzInflate for httpBody fails"); + return RECV_BAD; + } + buf2[buf2len] = 0; + httpBody = buf2; + httpBodyLen = buf2len; + } + + if (contentType == HTTP_CONTENT_JAVASCRIPT) { + decCnt = decodeHTTPBody(httpBody, data, httpBodyLen, HTTP_MSG_BUF_SIZE, + &fin, CONTENT_JAVASCRIPT); + } else { + decCnt = decodeHTTPBody(httpBody, data, httpBodyLen, HTTP_MSG_BUF_SIZE, + &fin, CONTENT_HTML_JAVASCRIPT); + } data[decCnt] = 0; log_debug("After decodeHTTPBody; decCnt: %d\n", decCnt); @@ -1011,119 +1087,6 @@ x_http2_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, } - -//int -//x_http2_handle_server_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) { -// -// int cnt = 0; -// -// do { -// struct evbuffer_ptr s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL); -// unsigned char* data; -// unsigned char* limit; -// unsigned char *p; -// int unwrapped_cookie_len; -// struct evbuffer *scratch; -// unsigned char c, h, secondhalf; -// unsigned char buf[evbuffer_get_length(source)]; -// -// -// if (s2.pos == -1) { -// log_debug("Did not find end of request %d", (int) evbuffer_get_length(source)); -// // evbuffer_dump(source, stderr); -// return RECV_INCOMPLETE; -// } -// -// log_debug("SERVER received request header of length %d", (int)s2.pos); -// -// data = evbuffer_pullup(source, s2.pos); -// if (data == NULL) { -// log_debug("SERVER evbuffer_pullup fails"); -// return RECV_BAD; -// } -// -// limit = data + s2.pos; -// -// data = (unsigned char*) strstr((char*) data, "Cookie:"); -// -// if (data == NULL || memcmp(data, "Cookie:", sizeof "Cookie:"-1)) { -// log_debug("Unexpected HTTP verb: %.*s", 5, data); -// return RECV_BAD; -// } -// -// p = data + sizeof "Cookie: "-1; -// unwrapped_cookie_len = unwrap_cookie(p, buf, (int) (limit - p)); -// -// log_debug("SERVER: received cookie of length = %d %d\n", unwrapped_cookie_len, (int) (limit-p)); -// // buf_dump(buf, unwrapped_cookie_len, stderr); -// // fprintf(stderr, "==========================\n"); -// // buf_dump(p, (int) (limit-p), stderr); -// -// -// // log_debug("hello SERVER received %d cnt = %d\n", (int) (limit - p), cnt); -// // buf_dump(p, (int) (limit-p), stderr); -// -// /* We need a scratch buffer here because the contract is that if -// we hit a decode error we *don't* write anything to 'dest'. */ -// scratch = evbuffer_new(); -// -// if (!scratch) return RECV_BAD; -// -// -// if (evbuffer_expand(scratch, unwrapped_cookie_len/2)) { -// log_debug("Evbuffer expand failed \n"); -// evbuffer_free(scratch); -// return RECV_BAD; -// } -// p = buf; -// -// -// secondhalf = 0; -// while ((int) (p - buf) < unwrapped_cookie_len) { -// if (!secondhalf) c = 0; -// if ('0' <= *p && *p <= '9') h = *p - '0'; -// else if ('a' <= *p && *p <= 'f') h = *p - 'a' + 10; -// else if ('A' <= *p && *p <= 'F') h = *p - 'A' + 10; -// else if (*p == '=' && !secondhalf) { -// p++; -// continue; -// } else { -// evbuffer_free(scratch); -// log_debug("Decode error: unexpected URI characterasdfaf %d", *p); -// return RECV_BAD; -// } -// -// c = (c << 4) + h; -// if (secondhalf) { -// evbuffer_add(scratch, &c, 1); -// // log_debug("adding to scratch"); -// cnt++; -// } -// secondhalf = !secondhalf; -// p++; -// } -// -// -// -// if (evbuffer_add_buffer(dest, scratch)) { -// evbuffer_free(scratch); -// log_debug("Failed to transfer buffer"); -// return RECV_BAD; -// } -// evbuffer_drain(source, s2.pos + sizeof("\r\n\r\n") - 1); -// evbuffer_free(scratch); -// } while (evbuffer_get_length(source)); -// -// -// log_debug("SERVER RECEIVED payload %d\n", cnt); -// // downcast_steg(s)->have_received = 1; -// conn_transmit_soon(conn, 100); -// return RECV_GOOD; -//} - - - - /***** int main() { diff --git a/src/steg/jsSteg.h b/src/steg/jsSteg.h index c076460..949aa25 100644 --- a/src/steg/jsSteg.h +++ b/src/steg/jsSteg.h @@ -9,23 +9,32 @@ #include "connections.h" #include "steg.h" #include <event2/buffer.h> +#include "zpack.h" - -/* error codes */ +// error codes #define INVALID_BUF_SIZE -1 #define INVALID_DATA_CHAR -2 +// controlling content gzipping for jsSteg +#define JS_GZIP_RESP 1 + int encodeHTTPBody(char *data, char *jTemplate, char *jData,unsigned int dlen, unsigned int jtlen, unsigned int jdlen, int mode); + int isxString(char *str); + +int isGzipContent (char *msg); + +int findContentType (char *msg); + int decodeHTTPBody (char *jData, char *dataBuf, unsigned int jdlen, unsigned int dataBufSize, int *fin, int mode); int encode(char *data, char *jTemplate, char *jData, unsigned int dlen, unsigned int jtlen, unsigned int jdlen ); -int encode2(char *data, char *jTemplate, char *jData, +int encode2(char *data, char *jTemplate, char *jData, unsigned int dlen, unsigned int jtlen, unsigned int jdlen, int *fin); diff --git a/src/steg/payloads.c b/src/steg/payloads.c index 017c469..02be31b 100644 --- a/src/steg/payloads.c +++ b/src/steg/payloads.c @@ -865,7 +865,7 @@ strInBinary (const char *pattern, unsigned int patternLen, int has_eligible_HTTP_content (char* buf, int len, int type) { char* ptr = buf; char* matchptr; - int tjFlag=0, thFlag=0, ceFlag=0, teFlag=0, http304Flag=0, clZeroFlag=0, pdfFlag=0, swfFlag=0; + int tjFlag=0, thFlag=0, ceFlag=0, teFlag=0, http304Flag=0, clZeroFlag=0, pdfFlag=0, swfFlag=0, gzipFlag=0; char* end, *cp; #ifdef DEBUG @@ -906,7 +906,9 @@ int has_eligible_HTTP_content (char* buf, int len, int type) { swfFlag = 1; } - } else if (!strncmp(ptr, "Content-Encoding:", 17)) { + } else if (!strncmp(ptr, "Content-Encoding: gzip", 22)) { + gzipFlag = 1; + } else if (!strncmp(ptr, "Content-Encoding:", 17)) { // Content-Encoding that is not gzip ceFlag = 1; } else if (!strncmp(ptr, "Transfer-Encoding:", 18)) { teFlag = 1; @@ -923,8 +925,8 @@ int has_eligible_HTTP_content (char* buf, int len, int type) { } #ifdef DEBUG - printf("tjFlag=%d; thFlag=%d; ceFlag=%d; teFlag=%d; http304Flag=%d; clZeroFlag=%d\n", - tjFlag, thFlag, ceFlag, teFlag, http304Flag, clZeroFlag); + printf("tjFlag=%d; thFlag=%d; gzipFlag=%d; ceFlag=%d; teFlag=%d; http304Flag=%d; clZeroFlag=%d\n", + tjFlag, thFlag, gzipFlag, ceFlag, teFlag, http304Flag, clZeroFlag); #endif // if (type == HTTP_CONTENT_JAVASCRIPT) @@ -933,12 +935,9 @@ int has_eligible_HTTP_content (char* buf, int len, int type) { if (http304Flag || clZeroFlag) return 0; // for now, we're not dealing with Transfer-Encoding (e.g., chunked) + // or Content-Encoding that is not gzip // if (teFlag) return 0; - // if (ceFlag) return 0; // for now, we remove "Content-Encoding: gzip" in fixContentLen if (teFlag || ceFlag) return 0; -/***** - if (teFlag) return 0; - *****/ if (tjFlag && ceFlag && end != NULL) { log_debug("(JS) gzip flag detected with hdr len %d", (int)(end-buf+4)); @@ -963,9 +962,8 @@ int has_eligible_HTTP_content (char* buf, int len, int type) { if (http304Flag || clZeroFlag) return 0; // for now, we're not dealing with Transfer-Encoding (e.g., chunked) - // or Content-Encoding (e.g., gzip) + // or Content-Encoding that is not gzip // if (teFlag) return 0; - // if (ceFlag) return 0; if (teFlag || ceFlag) return 0; // check if HTTP body contains "endstream";
1
0
0
0
[stegotorus/master] git-svn-id: svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@129 a58ff0ac-194c-e011-a152-003048836090
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 8afedcde7390e7515f35dd07f84af91015aa0b7e Author: Vinod Yegneswaran <vinod(a)csl.sri.com> Date: Mon Nov 7 20:35:29 2011 +0000 git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@129
a58ff0ac-194c-e011-a152-003048836090 --- src/steg/payloads.c | 152 ++++++++++++--------------------------------------- src/steg/payloads.h | 1 - 2 files changed, 36 insertions(+), 117 deletions(-) diff --git a/src/steg/payloads.c b/src/steg/payloads.c index 0cae234..a3e2f65 100644 --- a/src/steg/payloads.c +++ b/src/steg/payloads.c @@ -546,48 +546,51 @@ unsigned int find_client_payload(char* buf, int len, int type) { -int skipJSPattern(char *cp, int len) { - int i,j; +/* int skipJSPattern(char *cp, int len) { */ +/* int i,j; */ - char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while", - "else", "for", "document", "write", "writeln", "true", - "false", "True", "False", "window", "indexOf", "navigator", "case", "if"}; - if (len < 1) return 0; +/* char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while", */ +/* "else", "for", "document", "write", "writeln", "true", */ +/* "false", "True", "False", "window", "indexOf", "navigator", "case", "if"}; */ - // change the limit to 21 to enable if as a keyword - for (i=0; i < 20; i++) { - char* word = keywords[i]; - - if (len <= (int) strlen(word)) - continue; - if (word[0] != cp[0]) - continue; +/* return 0; */ +/* if (len < 1) return 0; */ - for (j=1; j < (int) strlen(word); j++) { - if (isxdigit(word[j])) { - if (!isxdigit(cp[j])) - goto next_word; - else - continue; - } +/* // change the limit to 21 to enable if as a keyword */ +/* for (i=0; i < 20; i++) { */ +/* char* word = keywords[i]; */ + +/* if (len <= (int) strlen(word)) */ +/* continue; */ + +/* if (word[0] != cp[0]) */ +/* continue; */ + +/* for (j=1; j < (int) strlen(word); j++) { */ +/* if (isxdigit(word[j])) { */ +/* if (!isxdigit(cp[j])) */ +/* goto next_word; */ +/* else */ +/* continue; */ +/* } */ - if (cp[j] != word[j]) - goto next_word; - } - if (!isalnum(cp[j])) - return strlen(word)+1; +/* if (cp[j] != word[j]) */ +/* goto next_word; */ +/* } */ +/* if (!isalnum(cp[j])) */ +/* return strlen(word)+1; */ - next_word: - continue; - } +/* next_word: */ +/* continue; */ +/* } */ + +/* return 0; */ +/* } */ - return 0; -} -/* int skipJSPattern (char *cp, int len) { @@ -649,7 +652,7 @@ int skipJSPattern (char *cp, int len) { return 0; } -*/ + int isalnum_ (char c) { @@ -753,89 +756,6 @@ int offset2Hex (char *p, int range, int isLastCharHex) { } /* - * capacityJS returns the number of usable hex char - * in the input HTTP message for data encoding - * - * Input: - * buf - pointer to HTTP message - * len - sizeof buf - * mode - - * CONTENT_JAVASCRIPT (case 1); HTTP message body is a JavaScript - * (e.g., Content-Type: {text/javascript, application/x-javascript, - * application/javascript}) - * CONTENT_HTML_JAVASCRIPT (case 2) - * Content-Type: text/html and HTTP message body contains - * <script type="text/javascript"> ... </script> - * - * Output: - * capacityJS returns the number of usable hex char that can be embedded - * in the HTTP message - * - * Note: - * This is a prototype for the simple version (all hex char are usable) - * will refine this to skip JavaScript keywords in the next iteration - * - */ - - - -unsigned int capacityJS (char* buf, int len, int mode) { - char *hEnd, *bp, *jsStart, *jsEnd; - int cnt=0; - - // jump to the beginning of the body of the HTTP message - hEnd = strstr(buf, "\r\n\r\n"); - if (hEnd == NULL) { - // cannot find the separator between HTTP header and HTTP body - return 0; - } - bp = hEnd + 4; - - if (mode == CONTENT_JAVASCRIPT) { - while (bp < (buf+len)) { - if (isxdigit(*bp)) { - cnt++; -#ifdef DEBUG - printf("%c", *bp); -#endif - } - bp++; - } -#ifdef DEBUG - printf("\n"); -#endif - return cnt; - } else if (mode == CONTENT_HTML_JAVASCRIPT) { - while (bp < (buf+len)) { - jsStart = strstr(bp, "<script type=\"text/javascript\">"); - if (jsStart == NULL) break; - bp = jsStart+31; - jsEnd = strstr(bp, "</script>"); - if (jsEnd == NULL) break; - // count the number of usable hex char between jsStart+31 and jsEnd - while (bp < jsEnd) { - if (isxdigit(*bp)) { - cnt++; -#ifdef DEBUG - printf("%c", *bp); -#endif - } - bp++; - } - bp += 9; - } -#ifdef DEBUG - printf("\n"); -#endif - return cnt; - } else { - fprintf(stderr, "Unknown mode (%d) for capacityJS() ... \n", mode); - return 0; - } - -} - -/* * capacityJS3 is the next iteration for capacityJS */ unsigned int capacityJS3 (char* buf, int len, int mode) { diff --git a/src/steg/payloads.h b/src/steg/payloads.h index 56729fe..7d66bbf 100644 --- a/src/steg/payloads.h +++ b/src/steg/payloads.h @@ -143,7 +143,6 @@ int skipJSPattern (char *cp, int len); int isalnum_ (char c); int offset2Alnum_ (char *p, int range); int offset2Hex (char *p, int range, int isLastCharHex); -unsigned int capacityJS (char* buf, int len, int mode); unsigned int capacityJS3 (char* buf, int len, int mode); unsigned int get_max_JS_capacity(void); unsigned int get_max_HTML_capacity(void);
1
0
0
0
[stegotorus/master] fixed pdfSteg so that client no longer receives an extra char
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 9a9cde1295e9ea0855e6227898542ffdfce71743 Author: Steven Cheung <cheung(a)csl.sri.com> Date: Mon Nov 7 21:05:37 2011 +0000 fixed pdfSteg so that client no longer receives an extra char git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@130
a58ff0ac-194c-e011-a152-003048836090 --- src/steg/pdfSteg.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-) diff --git a/src/steg/pdfSteg.c b/src/steg/pdfSteg.c index 4a91e55..81efdf4 100644 --- a/src/steg/pdfSteg.c +++ b/src/steg/pdfSteg.c @@ -126,7 +126,7 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, outbuf[cnt++] = delimiter1; ibp++; } else { // end-of-data pattern detected *endFlag = 1; - break; + return cnt; } } } @@ -490,12 +490,6 @@ x_http2_handle_client_PDF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest log_debug("CLIENT unwrapped data of length %d:", outbuflen); - // debugging - // buf_dump((unsigned char *)outbuf, outbuflen, stderr); - // ***** not sure why there is an extra char at the end of outbuf - outbuflen--; - - if (evbuffer_add(dest, outbuf, outbuflen)) { log_warn("CLIENT ERROR: evbuffer_add to dest fails\n"); return RECV_BAD;
1
0
0
0
[stegotorus/master] Linda's README for compiling obfsproxy on various platforms
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 1640842c048a05206144303f0f6df389ab79d711 Author: Linda Briesemeister <linda.briesemeister(a)sri.com> Date: Fri Nov 11 16:21:40 2011 +0000 Linda's README for compiling obfsproxy on various platforms git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@138
a58ff0ac-194c-e011-a152-003048836090 --- README.Linda | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 69 insertions(+), 0 deletions(-) diff --git a/README.Linda b/README.Linda new file mode 100644 index 0000000..2ecaa3c --- /dev/null +++ b/README.Linda @@ -0,0 +1,69 @@ +compiling obfsproxy on Mac OS X 10.6 +==================================== + +0) prelims + + a) autoconf 2.68 + +cd ~/src/autoconf-2.68 +./configure --prefix=/usr && make +make check # takes a long, long time! +sudo make install + + b) automake 1.11 + +cd ~/src/automake-1.11.1 +./configure --prefix=/usr && make +sudo make install + +1) obfsproxy + +cd ~/src/DEFIANCE/code/obfsproxy +./autogen.sh +./configure +make + + +compiling obfsproxy under Ubuntu 11.10 +====================================== + +in source directory: + +[ in file Makefile.am: add "-Wno-error=format" at the end of WARNINGS variable; remove "-Werror" & save ] + +$> ./autogen.sh +$> ./configure +[…] +configure: error: Package requirements (libcrypto >= 0.9.7) were not met: + +No package 'libcrypto' found +[…] +$> sudo find / -name openssl.pc +/usr/lib/i386-linux-gnu/pkgconfig/openssl.pc +$> echo $PKG_CONFIG_PATH + +$> export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig +$> ./configure +$> make + + +compiling obfsproxy under Ubuntu 10.04 (DETERlab) +================================================= + +create local disk space: + +$> sudo /usr/local/etc/emulab/mkextrafs.pl /mnt + +copy source code there to compile: + +$> sudo mkdir /mnt/local/alice +$> sudo chown linda:SAF-DEFIANCE /mnt/local/alice +$> cd /mnt/local/alice +$> tar -xzvf ~/src/obfsproxy-3.2.tar.gz +$> cd obfsproxy-3.2 +$> make clean # without this it will complain about some protocols not found! +$> emacs Makefile.am +[ add "-Wno-error=format" at the end of WARNINGS variable; remove "-Werror" & save & exit ] +$> ./autogen.sh +$> ./configure +$> make
1
0
0
0
[stegotorus/master] fixed bug in http2_server_receive.
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit c47a57efb1859b12c83d1d59215021cbb73e2f04 Author: Vinod Yegneswaran <vinod(a)csl.sri.com> Date: Fri Nov 11 19:34:57 2011 +0000 fixed bug in http2_server_receive. git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@139
a58ff0ac-194c-e011-a152-003048836090 --- src/steg/x_http2.c | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/steg/x_http2.c b/src/steg/x_http2.c index a1bc100..e714305 100644 --- a/src/steg/x_http2.c +++ b/src/steg/x_http2.c @@ -723,7 +723,6 @@ x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct ev do { struct evbuffer_ptr s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL); - unsigned char* limit; unsigned char *p; unsigned char c, h, secondhalf; char outbuf[MAX_COOKIE_SIZE]; @@ -749,12 +748,10 @@ x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct ev data[s2.pos+3] = 0; - limit = data + s2.pos; - type = find_uri_type((char *)data, s2.pos+4); if (strstr((char*) data, "Cookie") != NULL) { - p = (unsigned char*) strstr((char*) data, "Cookie:") + + sizeof "Cookie: "-1; + p = (unsigned char*) strstr((char*) data, "Cookie:") + sizeof "Cookie: "-1; cookie_mode = 1; } else @@ -765,7 +762,7 @@ x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct ev c = 0; - while (strncmp((char*) p, "\r\n", 4) != 0 && (cookie_mode != 0 || p[0] != '.')) { + while (strncmp((char*) p, "\r\n", 2) != 0 && (cookie_mode != 0 || p[0] != '.')) { if (!secondhalf) c = 0; if ('0' <= *p && *p <= '9')
1
0
0
0
[stegotorus/master] git-svn-id: svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@137 a58ff0ac-194c-e011-a152-003048836090
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit bc7435272a84dec0a3c865acf95fffb57e661c7b Author: Vinod Yegneswaran <vinod(a)csl.sri.com> Date: Fri Nov 11 05:20:14 2011 +0000 git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@137
a58ff0ac-194c-e011-a152-003048836090 --- src/steg/payloads.c | 241 ++++++++++++++++++++++++++++---------------------- src/steg/payloads.h | 2 +- src/steg/x_http.c | 2 +- src/steg/x_http2.c | 30 ++++--- 4 files changed, 153 insertions(+), 122 deletions(-) diff --git a/src/steg/payloads.c b/src/steg/payloads.c index a3e2f65..76bb213 100644 --- a/src/steg/payloads.c +++ b/src/steg/payloads.c @@ -387,28 +387,46 @@ int parse_client_headers(char* inbuf, char* outbuf, int len) { int -find_uri_type(char* buf) { +find_uri_type(char* buf_orig, int buflen) { char* uri; - int uri_len; char* ext; - if (strncmp(buf, "GET", 3) != 0 && strncmp(buf, "POST", 4) != 0) - return -1; + char* buf = malloc(buflen+1); + char* uri_end; + + + memcpy(buf, buf_orig, buflen); + buf[buflen] = 0; - buf = strchr(buf, ' ') + 1; - uri_len = strchr(buf, ' ') - buf; - if (uri_len < 0) { - fprintf(stderr, "buf = %sabc\n", buf); - exit (-1); + if (strncmp(buf, "GET", 3) != 0 + && strncmp(buf, "POST", 4) != 0) { + fprintf(stderr, "HERE %s\n", buf); + return -1; + } + + + + uri = strchr(buf, ' ') + 1; + if (uri == NULL) { + fprintf(stderr, "Invalid URL\n"); + return -1; } - uri = malloc(uri_len + 1); + uri_end = strchr(uri, ' '); + + if (uri_end == NULL) { + fprintf(stderr, "unterminated uri\n"); + return -1; + } + + uri_end[0] = 0; + + + - strncpy(uri, buf, uri_len); - uri[uri_len] = 0; ext = strrchr(uri, '/'); @@ -435,6 +453,9 @@ find_uri_type(char* buf) { if (!strncmp(ext, ".swf", 4) || !strncmp(ext, ".SWF", 4)) return HTTP_CONTENT_SWF; + + + free(buf); return -1; } @@ -503,9 +524,9 @@ unsigned int find_client_payload(char* buf, int len, int type) { pentry_header* p = &payload_hdrs[r]; if (p->ptype == type) { inbuf = payloads[r]; - if (find_uri_type(inbuf) != HTTP_CONTENT_SWF && - find_uri_type(inbuf) != HTTP_CONTENT_HTML && - find_uri_type(inbuf) != HTTP_CONTENT_JAVASCRIPT) { + if (find_uri_type(inbuf, p->length) != HTTP_CONTENT_SWF && + find_uri_type(inbuf, p->length) != HTTP_CONTENT_HTML && + find_uri_type(inbuf, p->length) != HTTP_CONTENT_JAVASCRIPT) { goto next; } if (p->length > len) { @@ -546,112 +567,111 @@ unsigned int find_client_payload(char* buf, int len, int type) { -/* int skipJSPattern(char *cp, int len) { */ -/* int i,j; */ +int skipJSPattern(char *cp, int len) { + int i,j; -/* char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while", */ -/* "else", "for", "document", "write", "writeln", "true", */ -/* "false", "True", "False", "window", "indexOf", "navigator", "case", "if"}; */ + char keywords [21][10]= {"function", "return", "var", "int", "random", "Math", "while", + "else", "for", "document", "write", "writeln", "true", + "false", "True", "False", "window", "indexOf", "navigator", "case", "if"}; -/* return 0; */ -/* if (len < 1) return 0; */ + if (len < 1) return 0; -/* // change the limit to 21 to enable if as a keyword */ -/* for (i=0; i < 20; i++) { */ -/* char* word = keywords[i]; */ + // change the limit to 21 to enable if as a keyword + for (i=0; i < 20; i++) { + char* word = keywords[i]; -/* if (len <= (int) strlen(word)) */ -/* continue; */ - -/* if (word[0] != cp[0]) */ -/* continue; */ - -/* for (j=1; j < (int) strlen(word); j++) { */ -/* if (isxdigit(word[j])) { */ -/* if (!isxdigit(cp[j])) */ -/* goto next_word; */ -/* else */ -/* continue; */ -/* } */ + if (len <= (int) strlen(word)) + continue; + + if (word[0] != cp[0]) + continue; + + for (j=1; j < (int) strlen(word); j++) { + if (isxdigit(word[j])) { + if (!isxdigit(cp[j])) + goto next_word; + else + continue; + } -/* if (cp[j] != word[j]) */ -/* goto next_word; */ -/* } */ -/* if (!isalnum(cp[j])) */ -/* return strlen(word)+1; */ + if (cp[j] != word[j]) + goto next_word; + } + if (!isalnum(cp[j])) + return strlen(word)+1; -/* next_word: */ -/* continue; */ -/* } */ + next_word: + continue; + } -/* return 0; */ -/* } */ + return 0; +} -int skipJSPattern (char *cp, int len) { +/* int skipJSPattern (char *cp, int len) { */ - // log_debug("Turning off skipJSPattern for debugging"); - // return 0; +/* // log_debug("Turning off skipJSPattern for debugging"); */ +/* // return 0; */ - if (len < 1) return 0; +/* if (len < 1) return 0; */ - if (len > 8) { - // "function " and "function(" - if (cp[0] == 'f' && - !strncmp(cp+1, "un", 2) && - isxdigit(cp[3]) && - !strncmp(cp+4, "tion", 4) && - (cp[8] == ' ' || cp[8] == '(')) - return 9; - } +/* if (len > 8) { */ +/* // "function " and "function(" */ +/* if (cp[0] == 'f' && */ +/* !strncmp(cp+1, "un", 2) && */ +/* isxdigit(cp[3]) && */ +/* !strncmp(cp+4, "tion", 4) && */ +/* (cp[8] == ' ' || cp[8] == '(')) */ +/* return 9; */ +/* } */ - if (len > 6) { - // "return " - if (cp[0] == 'r' && - isxdigit(cp[1]) && - !strncmp(cp+2, "turn ", 5)) - return 7; - // "switch " - if (cp[0] == 's' && - !strncmp(cp+1, "wit", 3) && - isxdigit(cp[4]) && - !strncmp(cp+5, "h ", 2)) - return 7; - } +/* if (len > 6) { */ +/* // "return " */ +/* if (cp[0] == 'r' && */ +/* isxdigit(cp[1]) && */ +/* !strncmp(cp+2, "turn ", 5)) */ +/* return 7; */ +/* // "switch " */ +/* if (cp[0] == 's' && */ +/* !strncmp(cp+1, "wit", 3) && */ +/* isxdigit(cp[4]) && */ +/* !strncmp(cp+5, "h ", 2)) */ +/* return 7; */ +/* } */ - if (len > 5) { - // "while " and "while(" - if (cp[0] == 'w' && - !strncmp(cp+1, "hil", 3) && - isxdigit(cp[4]) && - (cp[5] == ' ' || cp[5] == '(')) - return 6; - } +/* if (len > 5) { */ +/* // "while " and "while(" */ +/* if (cp[0] == 'w' && */ +/* !strncmp(cp+1, "hil", 3) && */ +/* isxdigit(cp[4]) && */ +/* (cp[5] == ' ' || cp[5] == '(')) */ +/* return 6; */ +/* } */ - if (len > 4) { - // "else " and "else{" - if (cp[0] == 'e' && - !strncmp(cp, "ls", 2) && - isxdigit(cp[3]) && - (cp[4] == ' ' || cp[4] == '{')) - return 5; - } +/* if (len > 4) { */ +/* // "else " and "else{" */ +/* if (cp[0] == 'e' && */ +/* !strncmp(cp, "ls", 2) && */ +/* isxdigit(cp[3]) && */ +/* (cp[4] == ' ' || cp[4] == '{')) */ +/* return 5; */ +/* } */ - if (len > 3) { - // "var " - if (cp[0] == 'v' && - isxdigit(cp[1]) && - cp[2] == 'r' && - cp[3] == ' ') - return 4; - } +/* if (len > 3) { */ +/* // "var " */ +/* if (cp[0] == 'v' && */ +/* isxdigit(cp[1]) && */ +/* cp[2] == 'r' && */ +/* cp[3] == ' ') */ +/* return 4; */ +/* } */ - return 0; -} +/* return 0; */ +/* } */ @@ -781,9 +801,10 @@ unsigned int capacityJS3 (char* buf, int len, int mode) { } else { bp = bp+j+1; } -// #ifdef DEBUG -// printf("got |%c|\n", *(bp-1)); -// #endif + + if (len < buf + len - bp) { + fprintf(stderr, "HERE\n"); + } j = offset2Hex(bp, (buf+len)-bp, 1); } // while return cnt; @@ -804,12 +825,20 @@ unsigned int capacityJS3 (char* buf, int len, int mode) { } else { bp = bp+j+1; } -#ifdef DEBUG -printf("got |%c|\n", *(bp-1)); -#endif + + if (len < jsEnd - buf || len < jsEnd - bp) { + fprintf(stderr, "HERE2\n"); + } + + j = offset2Hex(bp, jsEnd-bp, 1); } // while (j != -1) + if (buf + len < bp + 9) { + fprintf(stderr, "HERE3\n"); + } + + bp += 9; } // while (bp < (buf+len)) return cnt; diff --git a/src/steg/payloads.h b/src/steg/payloads.h index 7d66bbf..7629b14 100644 --- a/src/steg/payloads.h +++ b/src/steg/payloads.h @@ -153,7 +153,7 @@ char * strInBinary (const char *pattern, unsigned int patternLen, const char *bl unsigned int capacityPDF (char* buf, int len); unsigned int get_max_PDF_capacity(void); int find_content_length (char *hdr, int hlen); -int find_uri_type(char* buf); +int find_uri_type(char* buf, int size); int gen_response_header(char* content_type, int gzip, int length, char* buf, int buflen); diff --git a/src/steg/x_http.c b/src/steg/x_http.c index eb08401..c26fe1f 100644 --- a/src/steg/x_http.c +++ b/src/steg/x_http.c @@ -71,7 +71,7 @@ x_http_detect(conn_t *conn) { struct evbuffer *buf = conn_get_inbound(conn); unsigned char *data; - return 0; + return 0; /* Look for the text of http_response_1. */ if (evbuffer_get_length(buf) >= sizeof http_response_1 - 1) { diff --git a/src/steg/x_http2.c b/src/steg/x_http2.c index 3695c27..a1bc100 100644 --- a/src/steg/x_http2.c +++ b/src/steg/x_http2.c @@ -51,8 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#define MIN_COOKIE_SIZE 128 -#define MAX_COOKIE_SIZE 2048 +#define MIN_COOKIE_SIZE 24 +#define MAX_COOKIE_SIZE 1024 int @@ -187,7 +187,7 @@ x_http2_detect(conn_t *conn) struct evbuffer *buf = conn_get_inbound(conn); unsigned char *data; - // return 0; + //return 0; /***** Here is a list of HTTP response codes extracted from the server-portals.out trace @@ -490,7 +490,7 @@ x_http2_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn conn_cease_transmission(conn); - downcast_steg(s)->type = find_uri_type(buf); + downcast_steg(s)->type = find_uri_type(buf, sizeof(buf)); downcast_steg(s)->have_transmitted = 1; return 0; } @@ -528,6 +528,10 @@ int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen) { if (r == 0 && datalen > 0) uri[so_far++] = '/'; + if (r == 2 && datalen > 0) + uri[so_far++] = '_'; + + if (so_far > uri_sz - 6) { fprintf(stderr, "too small\n"); return 0; @@ -636,7 +640,7 @@ x_http2_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn) { evbuffer_drain(source, slen); conn_cease_transmission(conn); - downcast_steg(s)->type = find_uri_type(outbuf); + downcast_steg(s)->type = find_uri_type(outbuf, sizeof(outbuf)); downcast_steg(s)->have_transmitted = 1; return 0; @@ -675,7 +679,7 @@ x_http2_transmit(steg_t *s, struct evbuffer *source, conn_t *conn) the only plausible places to put it are the URL and cookies. This presently uses the URL. And it can't be binary. */ - if (evbuffer_get_length(source) < 128) + if (evbuffer_get_length(source) < 72) return x_http2_client_uri_transmit(s, source, conn); //@@ return x_http2_client_cookie_transmit(s, source, conn); //@@ } @@ -736,21 +740,21 @@ x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct ev log_debug("SERVER received request header of length %d", (int)s2.pos); data = evbuffer_pullup(source, s2.pos+4); + if (data == NULL) { log_debug("SERVER evbuffer_pullup fails"); return RECV_BAD; } - limit = data + s2.pos; - type = find_uri_type((char *)data); + data[s2.pos+3] = 0; - data[s2.pos+4] = 0; - // fprintf(stderr, "data = %s\n", data); + limit = data + s2.pos; + + type = find_uri_type((char *)data, s2.pos+4); if (strstr((char*) data, "Cookie") != NULL) { - data = (unsigned char*) strstr((char*) data, "Cookie:"); - p = data + sizeof "Cookie: "-1; + p = (unsigned char*) strstr((char*) data, "Cookie:") + + sizeof "Cookie: "-1; cookie_mode = 1; } else @@ -784,8 +788,6 @@ x_http2_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct ev outbuf[sofar] = 0; - // fprintf(stderr, "recvd = %d\n", sofar); - if (secondhalf) { fprintf(stderr, "incorrect cookie or uri recovery \n"); exit(-1);
1
0
0
0
[stegotorus/master] forgot to commit Makefile change
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 067e85e76d81b81cc712465e13b332c91c3e3aed Author: Jeffrey Wang <jeffreyw(a)stanford.edu> Date: Sun Dec 4 08:26:50 2011 +0000 forgot to commit Makefile change git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@170
a58ff0ac-194c-e011-a152-003048836090 --- Makefile.am | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Makefile.am b/Makefile.am index ebe3fdd..f3ed040 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,7 @@ PROTOCOLS = \ STEGANOGRAPHERS = \ src/steg/cookies.cc \ src/steg/crc32.cc \ + src/steg/embed.cc \ src/steg/http.cc \ src/steg/jsSteg.cc \ src/steg/payloads.cc \
1
0
0
0
[stegotorus/master] Linda's start script for obfsproxy server and client
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit f76325a6ba1a1b5b91323942ebd1759180b2257d Author: Linda Briesemeister <linda.briesemeister(a)sri.com> Date: Thu Nov 17 22:24:48 2011 +0000 Linda's start script for obfsproxy server and client git-svn-id:
svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@147
a58ff0ac-194c-e011-a152-003048836090 --- start-obfsproxy.sh | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 120 insertions(+), 0 deletions(-) diff --git a/start-obfsproxy.sh b/start-obfsproxy.sh new file mode 100755 index 0000000..06439fe --- /dev/null +++ b/start-obfsproxy.sh @@ -0,0 +1,120 @@ +#!/bin/bash + +ODIR=~/src/DEFIANCE/stegotorus + +################################################################################ +# helper functions: + +usage () { +if [ $# -gt 0 ]; then + echo " *** ERROR: $1" +fi +cat << EOF + +usage: $0 <OPTIONS> [server|client] [install-dir] + +Start obfsproxy server or client with given options. If the optional install-dir +is given, override the value set in the script. + +OPTIONS: + -h Show this message + -i <addr> IP address (default: 127.0.0.1) + -p <n> port number (default: 8080) + -l <severity> Log severity: warn, error, debug (default: debug) + -b <host> Host name (or IP address) of Tor Bridge + with port number attached via ':' or omitted + (default: 87.73.82.145:8080) + -n <n> Multiply the number of IP addresses on the client +EOF +} + +################################################################################ +# parse command line: + +# default values: +IP=127.0.0.1 +PORT=8080 +N=1 +LOG=debug +BRIDGE_IP=87.73.82.145 +BRIDGE_PORT=8080 +while getopts "hi:p:l:b:n:" OPTION +do + case $OPTION in + h|\?) + usage; exit 1 + ;; + i) + IP=$OPTARG + ;; + p) + PORT=$OPTARG + ;; + n) + N=$OPTARG + ;; + l) + LOG=`echo $OPTARG | tr '[A-Z]' '[a-z]'` # make lower case + ;; + b) + arr=(${OPTARG//:/ }) + BRIDGE_IP=${arr[0]} + if [ ${#arr[@]} -gt 1 ]; then + BRIDGE_PORT=${arr[1]} + fi + ;; + esac + shift $((OPTIND-1)); OPTIND=1 +done + +# test if $LOG is valid +case $LOG in + debug|warn|error) + ;; + *) + usage "Unknown log level given: $LOG"; exit 1 + ;; +esac + +# now $@ has remaining arguments: +if [ $# -lt 1 ]; then + usage "need 'server' or 'client' as argument"; exit 1 +fi +TYPE=`echo $1 | tr '[A-Z]' '[a-z]'` # turn argument into lower case +case $TYPE in + server|client) + ;; + *) + usage "argument $1 not recognized"; exit 1 + ;; +esac + +# check optional install location given as an argument +if [ $# -gt 1 ]; then + if [[ ! -d $2 ]]; then + usage "argument $2 is not a directory"; exit 1 + fi + if [[ ! -x $2/obfsproxy ]]; then + usage "directory $2 does not contain executable of 'obfsproxy'"; exit 1 + fi + ODIR=$2 +fi + +################################################################################ +# start obfsproxy + +echo "Using obfsproxy in \"$ODIR\"" +cd $ODIR +export EVENT_NOKQUEUE=yes +case $TYPE in + server) + ./obfsproxy --log-min-severity=$LOG chop server $BRIDGE_IP:$BRIDGE_PORT $IP:$PORT + ;; + client) + IPS="" + for (( c=1; c<=$N; c++)) ; do + IPS="${IPS}${IP}:${PORT} x_http2 " ; + done + ./obfsproxy --log-min-severity=$LOG chop socks 127.0.0.1:1080 $IPS + ;; +esac
1
0
0
0
[stegotorus/master] Merge branch 'master' into stegotorus
by zwol@torproject.org
20 Jul '12
20 Jul '12
commit 250e0f9ceaae483ae78e934529682c528d2ac7c0 Merge: 15ccb15 200c1ea Author: Zack Weinberg <zackw(a)cmu.edu> Date: Thu Dec 1 23:29:48 2011 +0000 Merge branch 'master' into stegotorus .gitignore | 6 +- LICENSE | 39 +- Makefile.am | 99 ++-- README | 8 +- autogen.sh | 2 - configure.ac | 55 +- doc/TODO | 30 +- doc/protocol-spec.txt | 104 --- doc/tor-obfs-howto.txt | 101 --- doc/tor-st-howto.txt | 101 +++ m4/pkg.m4 | 10 +- src/connections.c | 392 ----------- src/connections.cc | 400 ++++++++++++ src/connections.h | 103 +++- src/container.c | 1438 ----------------------------------------- src/container.h | 683 ------------------- src/crypt.c | 216 ------ src/crypt.cc | 269 ++++++++ src/crypt.h | 152 +++-- src/genmodtable.sh | 12 +- src/ht.h | 471 -------------- src/main.c | 399 ------------ src/main.cc | 398 ++++++++++++ src/network.c | 827 ----------------------- src/network.cc | 826 +++++++++++++++++++++++ src/protocol.c | 58 -- src/protocol.cc | 41 ++ src/protocol.h | 314 ++++------ src/protocol/chop.cc | 1308 +++++++++++++++++++++++++++++++++++++ src/protocol/x_null.cc | 243 +++++++ src/protocols/chop.c | 1379 --------------------------------------- src/protocols/dummy.c | 256 -------- src/protocols/obfs2.c | 659 ------------------- src/protocols/obfs2.h | 81 --- src/protocols/x_dsteg.c | 572 ---------------- src/protocols/x_rr.c | 1072 ------------------------------ src/rng.cc | 88 +++ src/rng.h | 19 +- src/sha256.c | 290 --------- src/sha256.h | 16 - src/socks.c | 614 ------------------ src/socks.cc | 612 ++++++++++++++++++ src/socks.h | 4 +- src/steg.c | 67 -- src/steg.cc | 44 ++ src/steg.h | 151 +++--- src/steg/x_http.c | 371 ----------- src/steg/x_http.cc | 360 ++++++++++ src/test/genunitgrps.sh | 2 +- src/test/itestlib.py | 165 +++++ src/test/obfstestlib.py | 165 ----- src/test/test_socks.py | 10 +- src/test/test_tl.py | 36 +- src/test/tinytest.c | 383 ----------- src/test/tinytest.cc | 383 +++++++++++ src/test/tltester.c | 662 ------------------- src/test/tltester.cc | 659 +++++++++++++++++++ src/test/unittest.c | 209 ------ src/test/unittest.cc | 119 ++++ src/test/unittest.h | 4 - src/test/unittest_config.c | 131 ---- src/test/unittest_config.cc | 86 +++ src/test/unittest_container.c | 768 ---------------------- src/test/unittest_crypt.c | 180 ----- src/test/unittest_crypt.cc | 407 ++++++++++++ src/test/unittest_obfs2.c | 268 -------- src/test/unittest_socks.c | 597 ----------------- src/test/unittest_socks.cc | 597 +++++++++++++++++ src/test/unittest_transfer.c | 146 ----- src/test/unittest_transfer.cc | 113 ++++ src/util.c | 709 -------------------- src/util.cc | 706 ++++++++++++++++++++ src/util.h | 170 +++-- 73 files changed, 8524 insertions(+), 14911 deletions(-) diff --cc Makefile.am index e8b68f5,de3c9b2..ebf44d9 --- a/Makefile.am +++ b/Makefile.am @@@ -2,72 -2,55 +2,63 @@@ # Copyright 2011 Nick Mathewson, George Kadianakis, Zack Weinberg # See LICENSE for other credits and copying information - ACLOCAL_AMFLAGS = -I m4 - WARNINGS = -std=gnu99 -pedantic -Wall -Wextra -Wformat=2 -Wwrite-strings \ - -Wstrict-prototypes -Wmissing-prototypes -Wdeclaration-after-statement \ - -Wno-unused-parameter -Wno-overlength-strings -Wno-long-long -Werror - AM_CPPFLAGS = -I. -I$(srcdir)/src -D_FORTIFY_SOURCE=2 - AM_CFLAGS = $(WARNINGS) @libevent_CFLAGS@ @libcrypto_CFLAGS@ - LDADD = libobfsproxy.a @libevent_LIBS@ @libcrypto_LIBS@ @ws32_LIBS@ + ACLOCAL_AMFLAGS = -I m4 --install - bin_PROGRAMS = obfsproxy - noinst_LIBRARIES = libobfsproxy.a - noinst_PROGRAMS = unittests tltester + WARNINGS = -Werror -Wall -Wextra -Wformat=2 + + AM_CXXFLAGS = -std=c++98 $(WARNINGS) + AM_CPPFLAGS = -I. -I$(srcdir)/src -D_FORTIFY_SOURCE=2 $(lib_CPPFLAGS) + LDADD = libstegotorus.a + + noinst_LIBRARIES = libstegotorus.a + noinst_PROGRAMS = unittests tltester + bin_PROGRAMS = stegotorus PROTOCOLS = \ - src/protocols/dummy.c \ - src/protocols/chop.c \ - src/protocols/obfs2.c \ - src/protocols/x_dsteg.c \ - src/protocols/x_rr.c + src/protocol/chop.cc \ + src/protocol/x_null.cc STEGANOGRAPHERS = \ - src/steg/x_http.c \ - src/steg/x_http.cc ++ src/steg/x_http.cc \ + src/steg/x_http2.c \ + src/steg/payloads.c \ + src/steg/cookies.c \ + src/steg/jsSteg.c \ + src/steg/swfSteg.c \ + src/steg/zpack.c \ + src/steg/crc32.c \ + src/steg/pdfSteg.c - libobfsproxy_a_SOURCES = \ - src/connections.c \ - src/container.c \ - src/crypt.c \ - src/network.c \ - src/protocol.c \ - src/socks.c \ - src/steg.c \ - src/util.c \ + libstegotorus_a_SOURCES = \ + src/connections.cc \ + src/crypt.cc \ + src/network.cc \ + src/protocol.cc \ + src/rng.cc \ + src/socks.cc \ + src/steg.cc \ + src/util.cc \ $(PROTOCOLS) $(STEGANOGRAPHERS) - nodist_libobfsproxy_a_SOURCES = protolist.c steglist.c - - if NEED_SHA256 - libobfsproxy_a_SOURCES += src/sha256.c - endif + nodist_libstegotorus_a_SOURCES = protolist.cc steglist.cc - obfsproxy_SOURCES = \ - src/main.c + stegotorus_SOURCES = \ + src/main.cc UTGROUPS = \ - src/test/unittest_container.c \ - src/test/unittest_crypt.c \ - src/test/unittest_socks.c \ - src/test/unittest_obfs2.c \ - src/test/unittest_config.c \ - src/test/unittest_transfer.c + src/test/unittest_crypt.cc \ + src/test/unittest_socks.cc \ + src/test/unittest_config.cc \ + src/test/unittest_transfer.cc unittests_SOURCES = \ - src/test/tinytest.c \ - src/test/unittest.c \ + src/test/tinytest.cc \ + src/test/unittest.cc \ $(UTGROUPS) - nodist_unittests_SOURCES = unitgrplist.c + nodist_unittests_SOURCES = unitgrplist.cc - tltester_SOURCES = src/test/tltester.c + tltester_SOURCES = src/test/tltester.cc noinst_HEADERS = \ src/connections.h \ diff --cc src/steg/x_http.cc index 0000000,9ee6eb5..e1d9780 mode 000000,100644..100644 --- a/src/steg/x_http.cc +++ b/src/steg/x_http.cc @@@ -1,0 -1,359 +1,360 @@@ + /* Copyright 2011 Zack Weinberg + See LICENSE for other credits and copying information + */ + + #include "util.h" + #include "connections.h" + #include "steg.h" + #include "crypt.h" + + #include <event2/buffer.h> + + /* This is an example steganography module. Don't use it to disguise real + traffic! It packages client->server traffic as HTTP GET requests and + server->client traffic as HTTP responses, but makes no actual attempt + to obscure the data proper. */ + + namespace { + struct x_http : steg_t + { + bool have_transmitted : 1; + bool have_received : 1; + STEG_DECLARE_METHODS(x_http); + }; + } + + STEG_DEFINE_MODULE(x_http, + 1024, /* client-server max data rate - made up */ + 10240, /* server-client max data rate - ditto */ + 1, /* max concurrent connections per IP */ + 1); /* max concurrent IPs */ + + /* Canned HTTP query and response headers. */ + static const char http_query_1[] = + "GET /"; + static const char http_query_2[] = + " HTTP/1.1\r\n" + "Host: "; + static const char http_query_3[] = + "\r\n" + "Connection: close\r\n\r\n"; + + static const char http_response_1[] = + "HTTP/1.1 200 OK\r\n" + "Expires: Thu, 01 Jan 1970 00:00:00 GMT\r\n" + "Cache-Control: no-store\r\n" + "Connection: close\r\n" + "Content-Type: application/octet-stream\r\n" + "Content-Length: "; + + + x_http::x_http() + : have_transmitted(false), have_received(false) + {} + + x_http::~x_http() + {} + + bool + x_http::detect(conn_t *conn) + { + struct evbuffer *buf = conn_get_inbound(conn); + uint8_t *data; ++ return 0; + + /* Look for the text of http_response_1. */ + if (evbuffer_get_length(buf) >= sizeof http_response_1 - 1) { + data = evbuffer_pullup(buf, sizeof http_response_1 - 1); + if (!memcmp(data, http_response_1, sizeof http_response_1 - 1)) + return true; + } + + /* The client always transmits "GET /" followed by at least four + characters that are either lowercase hex digits or equals + signs, so we need nine bytes of incoming data. */ + if (evbuffer_get_length(buf) >= 9) { + data = evbuffer_pullup(buf, 9); + if (!memcmp(data, "GET /", 5) && + (ascii_isxdigit(data[5]) || data[5] == '=') && + (ascii_isxdigit(data[6]) || data[6] == '=') && + (ascii_isxdigit(data[7]) || data[7] == '=') && + (ascii_isxdigit(data[8]) || data[8] == '=')) + return true; + } + + /* Didn't find either the client or the server pattern. */ + return false; + } + + size_t + x_http::transmit_room(conn_t *) + { + if (this->have_transmitted) + /* can't send any more on this connection */ + return 0; + + if (this->is_clientside) + /* per
http://www.boutell.com/newfaq/misc/urllength.html
, + IE<9 can handle no more than 2048 characters in the path + component of a URL; we're not talking to IE, but this limit + means longer paths look fishy; we hex-encode the path, so + we have to cut the number in half. */ + return 1024; + else { + if (!this->have_received) + return 0; + /* no practical limit applies */ + return SIZE_MAX; + } + } + + int + x_http::transmit(struct evbuffer *source, conn_t *conn) + { + struct evbuffer *dest = conn_get_outbound(conn); + + if (this->is_clientside) { + /* On the client side, we have to embed the data in a GET query somehow; + the only plausible places to put it are the URL and cookies. This + presently uses the URL. And it can't be binary. */ + struct evbuffer *scratch; + struct evbuffer_iovec *iv; + int i, nv; + + /* Convert all the data in 'source' to hexadecimal and write it to + 'scratch'. Data is padded to a multiple of four characters with + equals signs. */ + size_t slen = evbuffer_get_length(source); + size_t dlen = slen * 2; + + dlen = dlen + 3 - (dlen-1)%4; + if (dlen == 0) dlen = 4; + + scratch = evbuffer_new(); + if (!scratch) return -1; + if (evbuffer_expand(scratch, dlen)) { + evbuffer_free(scratch); + return -1; + } + + nv = evbuffer_peek(source, slen, NULL, NULL, 0); + iv = (struct evbuffer_iovec *)xzalloc(sizeof(struct evbuffer_iovec) * nv); + if (evbuffer_peek(source, slen, NULL, iv, nv) != nv) { + evbuffer_free(scratch); + free(iv); + return -1; + } + + for (i = 0; i < nv; i++) { + const uint8_t *p = (const uint8_t *)iv[i].iov_base; + const uint8_t *limit = p + iv[i].iov_len; + char hex[2], c; + while (p < limit) { + c = *p++; + hex[0] = "0123456789abcdef"[(c & 0xF0) >> 4]; + hex[1] = "0123456789abcdef"[(c & 0x0F) >> 0]; + evbuffer_add(scratch, hex, 2); + } + } + free(iv); + while (evbuffer_get_length(scratch) == 0 || + evbuffer_get_length(scratch) % 4 != 0) + evbuffer_add(scratch, "=", 1); + + if (evbuffer_add(dest, http_query_1, sizeof http_query_1-1) || + evbuffer_add_buffer(dest, scratch) || + evbuffer_add(dest, http_query_2, sizeof http_query_2-1) || + evbuffer_add(dest, conn->peername, strlen(conn->peername)) || + evbuffer_add(dest, http_query_3, sizeof http_query_3-1)) { + evbuffer_free(scratch); + return -1; + } + + evbuffer_free(scratch); + evbuffer_drain(source, slen); + conn_cease_transmission(conn); + this->have_transmitted = true; + return 0; + + } else { + /* On the server side, we just fake up some HTTP response headers + and then splat the data we were given. Binary is OK. */ + if (evbuffer_add(dest, http_response_1, sizeof http_response_1-1)) + return -1; + if (evbuffer_add_printf(dest, "%lu\r\n\r\n", + (unsigned long)evbuffer_get_length(source)) == -1) + return -1; + if (evbuffer_add_buffer(dest, source)) + return -1; + + conn_close_after_transmit(conn); + this->have_transmitted = true; + return 0; + } + } + + int + x_http::receive(conn_t *conn, struct evbuffer *dest) + { + struct evbuffer *source = conn_get_inbound(conn); + if (this->is_clientside) { + /* Linearize the buffer out past the longest possible + Content-Length header and subsequent blank line. 2**64 fits in + 20 characters, and then we have two CRLFs; minus one for the + NUL in sizeof http_response_1. Note that this does _not_ + guarantee that that much data is available. */ + + size_t hlen = evbuffer_get_length(source); + uint8_t *data, *p, *limit; + uint64_t clen; + + log_debug("x_http: %lu byte response stream available%s", + (unsigned long)hlen, + hlen >= sizeof http_response_1 - 1 ? "" : " (incomplete)"); + + if (this->have_received) { + log_warn("x_http: protocol error: multiple responses"); + return -1; + } + + if (hlen < sizeof http_response_1 - 1) + return 0; /* incomplete */ + + if (hlen > sizeof http_response_1 + 23) + hlen = sizeof http_response_1 + 23; + + data = evbuffer_pullup(source, hlen); + /* Validate response headers. */ + if (memcmp(data, http_response_1, sizeof http_response_1 - 1)) + return -1; + + /* There should be an unsigned number immediately after the text of + http_response_1, followed by the four characters \r\n\r\n. + We may not have the complete number yet. */ + p = data + sizeof http_response_1 - 1; + limit = data + hlen; + clen = 0; + while (p < limit && '0' <= *p && *p <= '9') { + clen = clen*10 + *p - '0'; + p++; + } + if (p+4 > limit) + return 0; /* incomplete */ + if (p[0] != '\r' || p[1] != '\n' || p[2] != '\r' || p[3] != '\n') + return -1; + + p += 4; + hlen = p - data; + /* Now we know how much data we're expecting after the blank line. */ + if (evbuffer_get_length(source) < hlen + clen) + return 0; /* incomplete */ + + /* we are go */ + if (evbuffer_drain(source, hlen)) + return -1; + + if ((uint64_t)evbuffer_remove_buffer(source, dest, clen) != clen) + return -1; + + log_debug("x_http: decoded %lu byte response", + (unsigned long)(hlen + clen)); + + if (evbuffer_get_length(source) > 0) { + log_warn("x_http: protocol error: extra response data"); + return -1; + } + + this->have_received = 1; + conn_expect_close(conn); + return 0; + } else { + /* We need a scratch buffer here because the contract is that if + we hit a decode error we *don't* write anything to 'dest'. */ + struct evbuffer *scratch; + struct evbuffer_ptr s2, s3; + uint8_t *data, *p, *limit; + uint8_t c, h, secondhalf; + + log_debug("x_http: %lu byte query stream available", + (unsigned long)evbuffer_get_length(source)); + + if (this->have_received) { + log_warn("x_http: protocol error: multiple queries"); + return -1; + } + + /* Search for the second and third invariant bits of the query headers + we expect. We completely ignore the contents of the Host header. */ + s2 = evbuffer_search(source, http_query_2, + sizeof http_query_2 - 1, NULL); + if (s2.pos == -1) { + log_debug("x_http: did not find second piece of HTTP query"); + return 0; + } + s3 = evbuffer_search(source, http_query_3, + sizeof http_query_3 - 1, &s2); + if (s3.pos == -1) { + log_debug("x_http: did not find third piece of HTTP query"); + return 0; + } + log_assert(s3.pos + sizeof http_query_3 - 1 + <= evbuffer_get_length(source)); + + data = evbuffer_pullup(source, s2.pos); + if (memcmp(data, "GET /", sizeof "GET /"-1)) { + log_debug("x_http: unexpected HTTP verb: %.*s", 5, data); + return -1; + } + + p = data + sizeof "GET /"-1; + limit = data + s2.pos; + + scratch = evbuffer_new(); + if (!scratch) return -1; + if (evbuffer_expand(scratch, (limit - p)/2)) { + evbuffer_free(scratch); + return -1; + } + + secondhalf = 0; + while (p < limit) { + if (!secondhalf) c = 0; + if ('0' <= *p && *p <= '9') h = *p - '0'; + else if ('a' <= *p && *p <= 'f') h = *p - 'a' + 10; + else if ('A' <= *p && *p <= 'F') h = *p - 'A' + 10; + else if (*p == '=' && !secondhalf) { + p++; + continue; + } else { + evbuffer_free(scratch); + log_debug("x_http: decode error: unexpected URI character %c", *p); + return -1; + } + + c = (c << 4) + h; + if (secondhalf) + evbuffer_add(scratch, &c, 1); + secondhalf = !secondhalf; + p++; + } + + if (evbuffer_add_buffer(dest, scratch)) { + evbuffer_free(scratch); + log_debug("x_http: failed to transfer buffer"); + return -1; + } + evbuffer_drain(source, s3.pos + sizeof http_query_3 - 1); + evbuffer_free(scratch); + log_debug("x_http: decoded %lu byte query", + (unsigned long)(s3.pos + sizeof http_query_3 - 1)); + + if (evbuffer_get_length(source) > 0) { + log_warn("x_http: protocol error: extra query data"); + return -1; + } + + this->have_received = 1; + conn_transmit_soon(conn, 2); + return 0; + } + }
1
0
0
0
← Newer
1
...
33
34
35
36
37
38
39
...
95
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Results per page:
10
25
50
100
200