commit 696648906b49690340ea16517060a932d61e1e2e Author: Vinod Yegneswaran vinod@safdef.isc.org Date: Tue Feb 14 12:21:51 2012 -0800
b64 encoding support for http cookies --- src/steg/b64cookies.cc | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ src/steg/b64cookies.h | 20 ++++ src/steg/b64decode.cc | 88 ++++++++++++++++++ src/steg/b64decode.h | 66 ++++++++++++++ src/steg/b64encode.cc | 139 ++++++++++++++++++++++++++++ src/steg/b64encode.h | 75 +++++++++++++++ 6 files changed, 621 insertions(+), 0 deletions(-)
diff --git a/src/steg/b64cookies.cc b/src/steg/b64cookies.cc new file mode 100644 index 0000000..975c201 --- /dev/null +++ b/src/steg/b64cookies.cc @@ -0,0 +1,233 @@ + +#include "b64cookies.h" +#include <string.h> + +int unwrap_b64_cookie(char* inbuf, char* outbuf, int buflen) { + int i,j; + j = 0; + + for (i=0; i < buflen; i++) { + char c = inbuf[i]; + + if (c != ' ' && c != ';' && c != '=') + outbuf[j++] = c; + } + + return j; + +} + + + + + +int gen_one_b64cookie(char* outbuf, int& cookielen, char* data, int datalen) { + int sofar = 0; + int namelen; + int data_consumed = 0; + + cookielen = 4 + rand() % (datalen - 3); + + if (cookielen > 13) + namelen = rand() % 10 + 1; + else + namelen = rand() % (cookielen - 3) + 1; + + + while (sofar < namelen) { + outbuf[sofar++] = data[data_consumed++]; + } + + + outbuf[sofar++] = '='; + + while (sofar < cookielen) { + outbuf[sofar++] = data[data_consumed++]; + } + + return data_consumed; + +} + + + + +/* returns length of cookie */ +int gen_b64_cookie_field(char* outbuf, char* data, int datalen) { + int onecookielen; + int consumed = 0; + int cookielen = 0; + + + + + while (datalen - consumed > 0) { + int cnt = gen_one_b64cookie(outbuf, onecookielen, data + consumed, datalen - consumed); + + if (cnt < 0) { + fprintf(stderr, "error: couldn't create cookie %d\n", cnt); + return cnt; + } + + consumed += cnt; + outbuf += onecookielen; + cookielen += onecookielen; + + if (datalen - consumed < 5) { + memcpy(outbuf, data+consumed, datalen-consumed); + return cookielen + datalen - consumed; + } + + + if (datalen - consumed > 0) { + outbuf[0] = ';'; + outbuf++; + cookielen++; + } + } + + + return cookielen; +} + + + +void sanitize_b64(char* input, int len) { + char* i = strchr(input, '/'); + int eqcnt = 0; + + printf("len = %d\n", len); + + while (i != NULL) { + *i = '_'; + i = strchr(i+1, '/'); + } + + i = strchr(input, '+'); + + while (i != NULL) { + *i = '.'; + i = strchr(i+1, '+'); + } + + if (input[len-2] == '=') + eqcnt = 2; + else if (input[len-1] == '=') + eqcnt = 1; + + + while (eqcnt > 0) { + int pos = rand() % (len - 1) + 1; + if (pos >= len - eqcnt) { + input[pos] = '-'; + eqcnt--; + continue; + } + + //shift characters up and insert '-' in the middle + for (int j=len-eqcnt; j > pos; j--) + input[j] = input[j-1]; + + input[pos] = '-'; + eqcnt--; + + } + +} + + +void desanitize_b64(char* input, int len) { + char* i = strchr(input, '_'); + + + printf("len = %d\n", len); + while (i != NULL) { + *i = '/'; + i = strchr(i+1, '_'); + } + + i = strchr(input, '.'); + + while (i != NULL) { + *i = '+'; + i = strchr(i+1, '.'); + } + + + i = strchr(input, '-'); + if (i != NULL) { + int j; + for (j=i-input; j < len-1; j++) + input[j] = input[j+1]; + input[len-1] = '='; + + + i = strchr(input, '-'); + + if (i != NULL) { + for (j=i-input; j < len-2; j++) + input[j] = input[j+1]; + input[len-2] = '='; + } + + } + +} + + + + + +// int main () { +// char outbuf[200]; + +// char data[56] = "ba239023820389023802380389abc2322132321932847203aedfasd"; +// char data2[200]; +// int cookielen; + +// srand(time(NULL)); + +// bzero(data2, sizeof(data2)); +// bzero(outbuf, sizeof(outbuf)); + +// base64::encoder E; +// E.encode(data, strlen(data), data2); +// E.encode_end(data2+strlen(data2)); +// printf("%s", data2); +// // remove trailing newline +// data2[strlen(data2) - 1] = 0; + +// // /* substitute / with _, + with ., = with - that maybe inserted anywhere in the middle */ + +// sanitize_b64(data2, strlen(data2)); +// printf("%s\n", data2); + +// cookielen = gen_b64_cookie_field((char*) outbuf, (char*) data2, strlen(data2)); +// printf("cookie=%s\n", outbuf); + +// bzero(data2, sizeof(data2)); +// cookielen = unwrap_b64_cookie((char*) outbuf, (char*) data2, strlen(outbuf)); + + +// desanitize_b64(data2, cookielen); +// printf("%s\n", data2); +// printf("%d\n", cookielen); + +// data2[strlen(data2)] = '\n'; + + +// bzero(outbuf, 200); + + + +// base64::decoder D; +// D.decode(data2, strlen(data2), outbuf); +// printf("%s\n", outbuf); + + + +// } + + + + diff --git a/src/steg/b64cookies.h b/src/steg/b64cookies.h new file mode 100644 index 0000000..d0c6e6d --- /dev/null +++ b/src/steg/b64cookies.h @@ -0,0 +1,20 @@ +#ifndef _B64_COOKIES_H +#define _B64_COOKIES_H + + + +#include <stdio.h> +#include <strings.h> +#include <stdlib.h> +#include <string.h> +#include "b64encode.h" +#include "b64decode.h" + +int unwrap_b64_cookie( char* inbuf, char* outbuf, int buflen); +int gen_b64_cookie_field( char* outbuf, char* data, int datalen); +int gen_one_b64cookie( char* outbuf, int& cookielen, char* data, int datalen); +void sanitize_b64(char* input, int len); +void desanitize_b64(char* input, int len); + + +#endif diff --git a/src/steg/b64decode.cc b/src/steg/b64decode.cc new file mode 100755 index 0000000..3beffba --- /dev/null +++ b/src/steg/b64decode.cc @@ -0,0 +1,88 @@ +/* +cdecoder.c - c source to a base64 decoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include "b64decode.h" + +int base64_decode_value(char value_in) +{ + static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,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,-1,-1,-1,-1,-1,-1,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}; + static const char decoding_size = sizeof(decoding); + value_in -= 43; + if (value_in < 0 || value_in > decoding_size) return -1; + return decoding[(int)value_in]; +} + +void base64_init_decodestate(base64_decodestate* state_in) +{ + state_in->step = step_a; + state_in->plainchar = 0; +} + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) +{ + const char* codechar = code_in; + char* plainchar = plaintext_out; + char fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) + { + while (1) + { + case step_a: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + case step_b: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + case step_c: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + case step_d: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; +} + diff --git a/src/steg/b64decode.h b/src/steg/b64decode.h new file mode 100755 index 0000000..9514c87 --- /dev/null +++ b/src/steg/b64decode.h @@ -0,0 +1,66 @@ +/* +cdecode.h - c header for a base64 decoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CDECODE_H +#define BASE64_CDECODE_H + +#include <iostream> +#include "b64encode.h" + +typedef enum +{ + step_a, step_b, step_c, step_d +} base64_decodestep; + +typedef struct +{ + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); + +int base64_decode_value(char value_in); + +int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); + + + + +namespace base64 +{ + + struct decoder + { + base64_decodestate _state; + int _buffersize; + + decoder(int buffersize_in = BUFFERSIZE) + : _buffersize(buffersize_in) + { + } + + int decode(char value_in) + { + + return base64_decode_value(value_in); + } + + int decode(const char* code_in, const int length_in, char* plaintext_out) + { + base64_init_decodestate(&_state); + return base64_decode_block(code_in, length_in, plaintext_out, &_state); + } + + }; + +} // namespace base64 + + + + +#endif /* BASE64_CDECODE_H */ diff --git a/src/steg/b64encode.cc b/src/steg/b64encode.cc new file mode 100755 index 0000000..1f1352d --- /dev/null +++ b/src/steg/b64encode.cc @@ -0,0 +1,139 @@ +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + + +#include "b64encode.h" +#include "b64decode.h" + + +const int CHARS_PER_LINE = 72; + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + + + + + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar++ = '\n'; + + return codechar - code_out; +} + + + + +/* +int main() { + + char foo[12] = "AbcdwefA#"; + char foo2[22]; + + base64::encoder E; + + printf("%d\n", (int) strlen(foo)); + E.encode(foo, strlen(foo), foo2); + printf("%s\n", foo2); + printf("%d\n", E.encode_end(foo2+strlen(foo2))); + printf("%s\n", foo2); + + base64::decoder D; + D.decode(foo2, strlen(foo2), foo); + printf("%s\n", foo); +} + +*/ diff --git a/src/steg/b64encode.h b/src/steg/b64encode.h new file mode 100755 index 0000000..be8c666 --- /dev/null +++ b/src/steg/b64encode.h @@ -0,0 +1,75 @@ +/* +cencode.h - c header for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CENCODE_H +#define BASE64_CENCODE_H +#include <iostream> + + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + + + + + +static int BUFFERSIZE = 16777216; + +namespace base64 +{ + + struct encoder + { + base64_encodestate _state; + int _buffersize; + + encoder(int buffersize_in = BUFFERSIZE) + : _buffersize(buffersize_in) + {} + + int encode(char value_in) + { + + return base64_encode_value(value_in); + } + + int encode(const char* code_in, const int length_in, char* plaintext_out) + { + base64_init_encodestate(&_state); + + return base64_encode_block(code_in, length_in, plaintext_out, &_state); + } + + int encode_end(char* plaintext_out) + { + return base64_encode_blockend(plaintext_out, &_state); + } + + }; + +} // namespace base64 + + + +#endif /* BASE64_CENCODE_H */
tor-commits@lists.torproject.org