commit 46762842d8eb314b13a158e725c472da0e0d3601 Author: George Kadianakis desnacked@gmail.com Date: Sat Jun 11 00:03:33 2011 +0200
Updated function documentation. --- src/main.c | 2 +- src/network.c | 46 ++++++++++++++++++++++--- src/protocol.c | 5 +-- src/protocols/dummy.c | 29 +++++++++++++-- src/protocols/obfs2.c | 3 ++ src/protocols/obfs2_crypt.c | 42 +++++++++++++++++++++++ src/socks.c | 79 +++++++++++++++++++++++++++++++----------- src/util.c | 16 +++++++++ 8 files changed, 188 insertions(+), 34 deletions(-)
diff --git a/src/main.c b/src/main.c index ace9e8c..9399783 100644 --- a/src/main.c +++ b/src/main.c @@ -80,7 +80,7 @@ populate_options(char **options_string, }
/** - Returns 1 if 'name' is the nmae of a supported protocol, otherwise + Returns 1 if 'name' is the name of a supported protocol, otherwise it returns 0. */ static int diff --git a/src/network.c b/src/network.c index e3c2fa0..a0ab6e9 100644 --- a/src/network.c +++ b/src/network.c @@ -36,10 +36,9 @@ static void input_event_cb(struct bufferevent *bev, short what, void *arg); static void output_event_cb(struct bufferevent *bev, short what, void *arg);
/** - This function sets up the protocol defined by 'options' and - attempts to bind a new listener for it. + This function spawns a listener according to the 'proto_params'.
- Returns the listener on success, NULL on fail. + Returns the listener on success and NULL on fail. */ listener_t * listener_new(struct event_base *base, @@ -72,6 +71,9 @@ listener_new(struct event_base *base, return lsn; }
+/** + Deallocates listener_t 'lsn'. +*/ void listener_free(listener_t *lsn) { @@ -83,9 +85,16 @@ listener_free(listener_t *lsn) free(lsn); }
+/** + This function is called when a new connection is received. + + It initializes the protocol we are using, sets up the necessary + callbacks for input/output and does the protocol handshake. +*/ static void simple_listener_cb(struct evconnlistener *evcl, - evutil_socket_t fd, struct sockaddr *sourceaddr, int socklen, void *arg) + evutil_socket_t fd, struct sockaddr *sourceaddr, + int socklen, void *arg) { listener_t *lsn = arg; struct event_base *base; @@ -174,6 +183,9 @@ simple_listener_cb(struct evconnlistener *evcl, evutil_closesocket(fd); }
+/** + Deallocates conn_t 'conn'. +*/ static void conn_free(conn_t *conn) { @@ -189,6 +201,10 @@ conn_free(conn_t *conn) free(conn); }
+/** + Closes associated connection if the output evbuffer of 'bev' is + empty. +*/ static void close_conn_on_flush(struct bufferevent *bev, void *arg) { @@ -198,7 +214,9 @@ close_conn_on_flush(struct bufferevent *bev, void *arg) conn_free(conn); }
-/** This is only used in the input bufferevent of clients. */ +/** + This callback is responsible for handling SOCKS traffic. +*/ static void socks_read_cb(struct bufferevent *bev, void *arg) { @@ -253,6 +271,9 @@ socks_read_cb(struct bufferevent *bev, void *arg) } }
+/** + This callback is responsible for handling plaintext traffic. +*/ static void plaintext_read_cb(struct bufferevent *bev, void *arg) { @@ -267,6 +288,11 @@ plaintext_read_cb(struct bufferevent *bev, void *arg) conn_free(conn); }
+/** + This callback is responsible for handling obfusacted + traffic -- traffic that has already been obfuscated + by our protocol. +*/ static void obfuscated_read_cb(struct bufferevent *bev, void *arg) { @@ -288,6 +314,10 @@ obfuscated_read_cb(struct bufferevent *bev, void *arg) bufferevent_get_output(conn->output)); }
+/** + Something broke in our connection or we reached EOF. + We prepare the connection to be closed ASAP. +*/ static void error_or_eof(conn_t *conn, struct bufferevent *bev_err, struct bufferevent *bev_flush) @@ -311,6 +341,9 @@ error_or_eof(conn_t *conn, bufferevent_enable(bev_flush, EV_WRITE); }
+/** + We land in here when an event happens on conn->input. +*/ static void input_event_cb(struct bufferevent *bev, short what, void *arg) { @@ -325,6 +358,9 @@ input_event_cb(struct bufferevent *bev, short what, void *arg) /* XXX we don't expect any other events */ }
+/** + We land in here when an event happens on conn->output. +*/ static void output_event_cb(struct bufferevent *bev, short what, void *arg) { diff --git a/src/protocol.c b/src/protocol.c index 544dcef..0845c11 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -40,9 +40,8 @@ set_up_protocol(int n_options, char **options, }
/** - This function creates a protocol object. - It's called once per connection. - It creates a new protocol_t structure and fills it's vtable etc. + This function is called once per connection and creates a protocol + object to be used during the session. Return a 'protocol_t' if successful, NULL otherwise. */ struct protocol_t * diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c index bdf97fc..be4c287 100644 --- a/src/protocols/dummy.c +++ b/src/protocols/dummy.c @@ -26,9 +26,10 @@ static int parse_and_set_options(int n_options, char **options, struct protocol_params_t *params);
static protocol_vtable *vtable=NULL; + /** - This function sets up the protocol and populates 'listner' - according to 'options'. + This function populates 'params' according to 'options' and sets up + the protocol vtable.
'options' is an array like this: {"dummy","socks","127.0.0.1:6666"} @@ -56,6 +57,9 @@ dummy_init(int n_options, char **options, return 1; }
+/** + Helper: Parses 'options' and fills 'params'. +*/ static int parse_and_set_options(int n_options, char **options, struct protocol_params_t *params) @@ -96,6 +100,9 @@ parse_and_set_options(int n_options, char **options, return 1; }
+/** + Prints dummy protocol usage information. +*/ static void usage(void) { @@ -109,8 +116,12 @@ usage(void) "\tobfsproxy dummy socks 127.0.0.1:5000\n"); }
- - +/* + This is called everytime we get a connection for the dummy + protocol. + + It sets up the protocol vtable in 'proto_struct'. +*/ void * dummy_new(struct protocol_t *proto_struct, struct protocol_params_t *params) @@ -122,6 +133,11 @@ dummy_new(struct protocol_t *proto_struct, return (void *)666U; }
+/** + Responsible for sending data according to the dummy protocol. + + The dummy protocol just puts the data of 'source' in 'dest'. +*/ static int dummy_send(void *nothing, struct evbuffer *source, struct evbuffer *dest) { @@ -130,6 +146,11 @@ dummy_send(void *nothing, return evbuffer_add_buffer(dest,source); }
+/* + Responsible for receiving data according to the dummy protocol. + + The dummy protocol just puts the data of 'source' into 'dest'. +*/ static enum recv_ret dummy_recv(void *nothing, struct evbuffer *source, struct evbuffer *dest) { diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c index 676ddd7..f4302a2 100644 --- a/src/protocols/obfs2.c +++ b/src/protocols/obfs2.c @@ -61,6 +61,9 @@ obfs2_init(int n_options, char **options, return 1; }
+/** + Helper: Parses 'options' and fills 'params'. +*/ int parse_and_set_options(int n_options, char **options, struct protocol_params_t *params) diff --git a/src/protocols/obfs2_crypt.c b/src/protocols/obfs2_crypt.c index 681fab6..4e814e7 100644 --- a/src/protocols/obfs2_crypt.c +++ b/src/protocols/obfs2_crypt.c @@ -48,6 +48,9 @@ get_uint32(const void *ptr) #include "../sha256.c" #endif
+/** + Initializes the obfs2 crypto subsystem. +*/ int initialize_crypto(void) { @@ -77,6 +80,9 @@ initialize_crypto(void) #endif }
+/** + Cleans up the obfs2 crypto subsystem. +*/ void cleanup_crypto(void) { @@ -91,18 +97,33 @@ cleanup_crypto(void) struct digest_t { SHA256_CTX ctx; }; + +/** + Returns a new SHA256 digest container, or NULL on failure. +*/ digest_t * digest_new(void) { digest_t *d = malloc(sizeof(digest_t)); + if (!d) + return NULL; SHA256_Init(&d->ctx); return d; } + +/** + Updates the contents of the SHA256 container 'd' with the first + 'len' bytes of 'buf'. +*/ void digest_update(digest_t *d, const uchar *buf, size_t len) { SHA256_Update(&d->ctx, buf, len); } + +/** + Returns the digest stored in 'd' into 'buf' of length 'len'. +*/ size_t digest_getdigest(digest_t *d, uchar *buf, size_t len) { @@ -123,6 +144,8 @@ digest_t * digest_new(void) { digest_t *d = malloc(sizeof(digest_t)); + if (!d) + return NULL; sha256_init(&d->ctx); return d; } @@ -156,6 +179,9 @@ digest_free(digest_t *d) Stream crypto ===== */
+/** + Initializes the AES cipher with 'key'. +*/ crypt_t * crypt_new(const uchar *key, size_t keylen) { @@ -171,12 +197,20 @@ crypt_new(const uchar *key, size_t keylen)
return k; } + +/** + Sets the IV of 'key' to 'iv'. +*/ void crypt_set_iv(crypt_t *key, const uchar *iv, size_t ivlen) { assert(ivlen == sizeof(key->ivec)); memcpy(key->ivec, iv, ivlen); } + +/* + In-place encrypts 'buf' with 'key'. +*/ void stream_crypt(crypt_t *key, uchar *buf, size_t len) { @@ -185,6 +219,10 @@ stream_crypt(crypt_t *key, uchar *buf, size_t len) &key->key, key->ivec, key->ecount_buf, &key->pos); } + +/** + Deallocates memory space of 'key'. +*/ void crypt_free(crypt_t *key) { @@ -196,6 +234,10 @@ crypt_free(crypt_t *key) PRNG ===== */
+/** + Fills 'buf' with 'buflen' random bytes and returns 0 on success. + Returns -1 on failure. +*/ int random_bytes(uchar *buf, size_t buflen) { diff --git a/src/socks.c b/src/socks.c index 7cf179b..d3c69f2 100644 --- a/src/socks.c +++ b/src/socks.c @@ -48,6 +48,11 @@ static enum socks_ret socks5_do_negotiation(struct evbuffer *dest,
typedef unsigned char uchar;
+/** + Creates a new SOCKS state. + + Returns a 'socks_state_t' on success, NULL on fail. +*/ socks_state_t * socks_state_new(void) { @@ -59,6 +64,9 @@ socks_state_new(void) return state; }
+/** + Deallocates memory of socks_state_t 's'. +*/ void socks_state_free(socks_state_t *s) { @@ -108,17 +116,15 @@ socks_errno_to_reply(socks_state_t *state, int error) #undef ERR
/** - Takes a command request from 'source', it evaluates it and if it's - legit it parses it into 'parsereq'. - - It returns '1' if everything went fine. - It returns '0' if we need more data from the client. - It returns '-1' if we didn't like something. - It returns '-2' if the client asked for something else than CONNECT. - If that's the case we should send a reply back to the client - telling him that we don't support it. + Takes a SOCKS5 command request from 'source', it evaluates it and + if it's legit it parses it into 'parsereq'.
- Disclaimer: This is just a temporary documentation. + It returns SOCKS_GOOD if everything went fine. + It returns SOCKS_INCOMPLETE if we need more data from the client. + It returns SOCKS_BROKEN if we didn't like something. + It returns SOCKS_CMD_NOT_CONNECT if the client asked for something + else other than CONNECT. If that's the case we should send a reply + back to the client telling him that we don't support it.
Client Request (Client -> Server) */ @@ -223,7 +229,8 @@ socks5_handle_request(struct evbuffer *source, struct parsereq *parsereq) }
/** - This sends the appropriate reply to the client on 'reply_dest'. + This sends the appropriate SOCKS5 reply to the client on + 'reply_dest', according to 'status'.
Server Reply (Server -> Client): | version | rep | rsv | atyp | destaddr | destport @@ -281,7 +288,7 @@ socks5_send_reply(struct evbuffer *reply_dest, socks_state_t *state,
/** This function handles the initial SOCKS5 packet in 'source' sent by - the client, which negotiates the version and method of SOCKS. If + the client which negotiates the version and method of SOCKS. If the packet is actually valid, we reply to 'dest'.
Method Negotiation Packet (Client -> Server): @@ -351,7 +358,14 @@ socks5_do_negotiation(struct evbuffer *dest, unsigned int neg_was_success) return SOCKS_GOOD; }
-/* rename to socks4_handle_request or something. */ +/** + Takes a SOCKS4/SOCKS4a command request from 'source', it evaluates + it and if it's legit it parses it into 'parsereq'. + + It returns SOCKS_GOOD if everything went fine. + It returns SOCKS_INCOMPLETE if we need more data from the client. + It returns SOCKS_BROKEN if we didn't like something. +*/ enum socks_ret socks4_read_request(struct evbuffer *source, socks_state_t *state) { @@ -418,13 +432,18 @@ socks4_read_request(struct evbuffer *source, socks_state_t *state) } else { struct in_addr in; in.s_addr = htonl(ipaddr); - if (evutil_inet_ntop(AF_INET, &in, state->parsereq.addr, sizeof(state->parsereq.addr)) == NULL) + if (evutil_inet_ntop(AF_INET, &in, state->parsereq.addr, + sizeof(state->parsereq.addr)) == NULL) return SOCKS_BROKEN; }
return SOCKS_GOOD; }
+/** + This sends the appropriate SOCKS4 reply to the client on + 'reply_dest', according to 'status'. +*/ int socks4_send_reply(struct evbuffer *dest, socks_state_t *state, int status) { @@ -448,12 +467,15 @@ socks4_send_reply(struct evbuffer *dest, socks_state_t *state, int status) }
/** - We are given data from the network. - If we haven't negotiated with the connection, we try to negotiate. - If we have already negotiated, we suppose it's a CONNECT request and - try to be helpful. - - Returns 1 on done, -1 on unrecoverable error, 0 on "need more bytes + We are given SOCKS data from the network. + We figure out what what SOCKS version it is and act accordingly. + + It returns SOCKS_GOOD if everything went fine. + It returns SOCKS_INCOMPLETE if we need more data from the client. + It returns SOCKS_BROKEN if we didn't like something. + It returns SOCKS_CMD_NOT_CONNECT if the client asked for something + else other than CONNECT. If that's the case we should send a reply + back to the client telling him that we don't support it. */ enum socks_ret handle_socks(struct evbuffer *source, struct evbuffer *dest, @@ -533,12 +555,22 @@ handle_socks(struct evbuffer *source, struct evbuffer *dest, return SOCKS_BROKEN; }
+/** + Returns the protocol status of the SOCKS state 'state'. +*/ enum socks_status_t socks_state_get_status(const socks_state_t *state) { return state->state; }
+/** + If we have previously parsed a SOCKS CONNECT request, this function + places the corresponding address/port to 'af_out', 'addr_out' and + 'port_out'. + + It returns 0 on success and -1 if it was called unnecessarily. +*/ int socks_state_get_address(const socks_state_t *state, int *af_out, @@ -553,6 +585,10 @@ socks_state_get_address(const socks_state_t *state, return 0; }
+/** + Places the address/port in 'sa' into the SOCKS state 'state' for + later retrieval. +*/ int socks_state_set_address(socks_state_t *state, const struct sockaddr *sa) { @@ -583,11 +619,12 @@ socks_state_set_address(socks_state_t *state, const struct sockaddr *sa)
/** This function sends a SOCKS{5,4} "Server Reply" to 'dest'. + 'error' is 0 if no errors were encountered during the SOCKS operation (normally a CONNECT with no errors means that the connect() was successful). If 'error' is not 0, it means that an error was encountered and - error carries the errno(3) of the error. + error carries the errno(3). */ int socks_send_reply(socks_state_t *state, struct evbuffer *dest, int error) diff --git a/src/util.c b/src/util.c index d4eddb6..1d44a52 100644 --- a/src/util.c +++ b/src/util.c @@ -27,6 +27,17 @@ static void logv(int severity, const char *format, va_list ap);
/************************ Obfsproxy Network Routines *************************/
+/** + Accepts a string 'address' of the form ADDRESS:PORT and attempts to + parse it into 'addr_out' and put it's length into 'addrlen_out'. + + If 'nodns' is set it means that 'address' was an IP address. + If 'passive' is set it means that the address is destined for + listening and not for connecting. + + If no port was given in 'address', we set 'default_port' as the + port. +*/ int resolve_address_port(const char *address, int nodns, int passive, @@ -369,6 +380,10 @@ logv(int severity, const char *format, va_list ap) }
#ifdef NEED_LOG_WRAPPERS +/** + If our platform doesn't support the log_* macros defined in + util.h, we use these functions. +*/ void log_info(const char *format, ...) { @@ -399,4 +414,5 @@ log_debug(const char *format, ...)
va_end(ap); } + #endif