Loading src/or/buffers.c +146 −74 Original line number Diff line number Diff line Loading @@ -317,66 +317,135 @@ int fetch_from_buf_http(buf_t *buf, return 1; } /* There is a (possibly incomplete) socks handshake on *buf, of the * forms * socks4: "socksheader || username\0". * socks4a: "socksheader || username\0 || destaddr\0". /* There is a (possibly incomplete) socks handshake on buf, of one * of the forms * socks4: "socksheader username\0" * socks4a: "socksheader username\0 destaddr\0" * socks5 phase one: "version #methods methods" * socks5 phase two: "version command 0 addresstype..." * If it's a complete and valid handshake, and destaddr fits in addr_out, * then pull the handshake off the buf, assign to addr_out and port_out, * and return 1. * If it's invalid or too big, return -1. * Else it's not all there yet, change nothing and return 0. * Else it's not all there yet, leave buf alone and return 0. * If you want to specify the socks reply, write it into *reply * and set *replylen, else leave *replylen alone. * If returning 0 or -1, *addr_out and *port_out are undefined. */ int fetch_from_buf_socks(buf_t *buf, int fetch_from_buf_socks(buf_t *buf, char *socks_version, char *reply, int *replylen, char *addr_out, int max_addrlen, uint16_t *port_out) { socks4_t socks4_info; unsigned char len; char *tmpbuf=NULL; uint16_t port; enum {socks4, socks4a } socks_prot = socks4a; uint32_t destip; enum {socks4, socks4a} socks4_prot = socks4a; char *next, *startaddr; struct in_addr in; if(buf->datalen < sizeof(socks4_t)) /* basic info available? */ return 0; /* not yet */ if(buf->datalen < 2) /* version and another byte */ return 0; switch(*(buf->buf)) { /* which version of socks? */ /* an inlined socks4_unpack() */ socks4_info.version = (unsigned char) *(buf->buf); socks4_info.command = (unsigned char) *(buf->buf+1); socks4_info.destport = ntohs(*(uint16_t*)(buf->buf+2)); socks4_info.destip = ntohl(*(uint32_t*)(buf->buf+4)); case 5: /* socks5 */ if(socks4_info.version != 4) { log_fn(LOG_WARNING,"Unrecognized version %d.",socks4_info.version); if(*socks_version != 5) { /* we need to negotiate a method */ unsigned char nummethods = (unsigned char)*(buf->buf+1); assert(!*socks_version); log_fn(LOG_DEBUG,"socks5: learning offered methods"); if(buf->datalen < 2+nummethods) return 0; if(!nummethods || !memchr(buf->buf+2, 0, nummethods)) { log_fn(LOG_WARNING,"socks5: offered methods don't include 'no auth'. Rejecting."); *replylen = 2; /* 2 bytes of response */ *reply = 5; /* socks5 reply */ *(reply+1) = 0xFF; /* reject all methods */ return -1; } buf->datalen -= (2+nummethods); /* remove packet from buf */ memmove(buf->buf, buf->buf + 2 + nummethods, buf->datalen); if(socks4_info.command != 1) { /* not a connect? we don't support it. */ log_fn(LOG_WARNING,"command %d not '1'.",socks4_info.command); *replylen = 2; /* 2 bytes of response */ *reply = 5; /* socks5 reply */ *(reply+1) = 0; /* choose the 'no auth' method */ *socks_version = 5; /* remember that we've already negotiated auth */ log_fn(LOG_DEBUG,"socks5: accepted method 0"); return 0; } /* we know the method; read in the request */ log_fn(LOG_DEBUG,"socks5: checking request"); if(buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */ return 0; /* not yet */ if(*(buf->buf+1) != 1) { /* not a connect? we don't support it. */ log_fn(LOG_WARNING,"socks5: command %d not '1'.",*(buf->buf+1)); return -1; } port = socks4_info.destport; if(!port) { log_fn(LOG_WARNING,"Port is zero."); switch(*(buf->buf+3)) { /* address type */ case 1: /* IPv4 address */ log_fn(LOG_DEBUG,"socks5: ipv4 address type"); if(buf->datalen < 10) /* ip/port there? */ return 0; /* not yet */ destip = ntohl(*(uint32_t*)(buf->buf+4)); in.s_addr = htonl(destip); tmpbuf = inet_ntoa(in); if(strlen(tmpbuf)+1 > max_addrlen) { log_fn(LOG_WARNING,"socks5 IP takes %d bytes, which doesn't fit in %d", strlen(tmpbuf)+1,max_addrlen); return -1; } strcpy(addr_out,tmpbuf); *port_out = ntohs(*(uint16_t*)(buf->buf+8)); buf->datalen -= 10; memmove(buf->buf, buf->buf+10, buf->datalen); return 1; case 3: /* fqdn */ log_fn(LOG_DEBUG,"socks5: fqdn address type"); len = (unsigned char)*(buf->buf+4); if(buf->datalen < 7+len) /* addr/port there? */ return 0; /* not yet */ if(len+1 > max_addrlen) { log_fn(LOG_WARNING,"socks5 hostname is %d bytes, which doesn't fit in %d", len+1,max_addrlen); return -1; } memcpy(addr_out,buf->buf+5,len); addr_out[len] = 0; *port_out = ntohs(*(uint16_t*)(buf->buf+5+len)); buf->datalen -= (5+len+2); memmove(buf->buf, buf->buf+(5+len+2), buf->datalen); return 1; default: /* unsupported */ log_fn(LOG_WARNING,"socks5: unsupported address type %d",*(buf->buf+3)); return -1; } assert(0); case 4: /* socks4 */ *socks_version = 4; if(buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */ return 0; /* not yet */ if(!socks4_info.destip) { log_fn(LOG_WARNING,"DestIP is zero."); if(*(buf->buf+1) != 1) { /* not a connect? we don't support it. */ log_fn(LOG_WARNING,"socks4: command %d not '1'.",*(buf->buf+1)); return -1; } if(socks4_info.destip >> 8) { struct in_addr in; log_fn(LOG_DEBUG,"destip not in form 0.0.0.x."); in.s_addr = htonl(socks4_info.destip); *port_out = ntohs(*(uint16_t*)(buf->buf+2)); destip = ntohl(*(uint32_t*)(buf->buf+4)); if(!*port_out || !destip) { log_fn(LOG_WARNING,"socks4: Port or DestIP is zero."); return -1; } if(destip >> 8) { log_fn(LOG_DEBUG,"socks4: destip not in form 0.0.0.x."); in.s_addr = htonl(destip); tmpbuf = inet_ntoa(in); if(max_addrlen <= strlen(tmpbuf)) { log_fn(LOG_WARNING,"socks4 addr too long."); if(strlen(tmpbuf)+1 > max_addrlen) { log_fn(LOG_WARNING,"socks4 addr (%d bytes) too long.", strlen(tmpbuf)); return -1; } log_fn(LOG_DEBUG,"Successfully read destip (%s)", tmpbuf); socks_prot = socks4; log_fn(LOG_DEBUG,"socks4: successfully read destip (%s)", tmpbuf); socks4_prot = socks4; } next = memchr(buf->buf+SOCKS4_NETWORK_LEN, 0, buf->datalen); Loading @@ -386,7 +455,7 @@ int fetch_from_buf_socks(buf_t *buf, } startaddr = next+1; if(socks_prot == socks4a) { if(socks4_prot == socks4a) { next = memchr(startaddr, 0, buf->buf+buf->datalen-startaddr); if(!next) { log_fn(LOG_DEBUG,"Destaddr not here yet."); Loading @@ -398,12 +467,15 @@ int fetch_from_buf_socks(buf_t *buf, } } log_fn(LOG_DEBUG,"Everything is here. Success."); *port_out = port; strcpy(addr_out, socks_prot == socks4 ? tmpbuf : startaddr); strcpy(addr_out, socks4_prot == socks4 ? tmpbuf : startaddr); buf->datalen -= (next-buf->buf+1); /* next points to the final \0 on inbuf */ memmove(buf->buf, next+1, buf->datalen); // log_fn(LOG_DEBUG,"buf_datalen is now %d:'%s'",*buf_datalen,buf); return 1; default: /* version is not socks4 or socks5 */ log_fn(LOG_WARNING,"Socks version %d not recognized.",*(buf->buf)); return -1; } } /* Loading src/or/connection_edge.c +52 −30 Original line number Diff line number Diff line Loading @@ -9,15 +9,11 @@ extern or_options_t options; /* command-line and config-file options */ static int connection_ap_handshake_process_socks(connection_t *conn); static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ, char *destaddr, uint16_t destport); static int connection_ap_handshake_socks_reply(connection_t *conn, char result); static int connection_ap_handshake_socks_reply(connection_t *conn, char *reply, int replylen, char success); static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); #define SOCKS4_REQUEST_GRANTED 90 #define SOCKS4_REQUEST_REJECT 91 #define SOCKS4_REQUEST_IDENT_FAILED 92 #define SOCKS4_REQUEST_IDENT_CONFLICT 93 int connection_edge_process_inbuf(connection_t *conn) { assert(conn); Loading Loading @@ -242,7 +238,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection break; } log_fn(LOG_INFO,"Connected! Notifying application."); if(connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_GRANTED) < 0) { if(connection_ap_handshake_socks_reply(conn, NULL, 0, 1) < 0) { /*ENDCLOSE*/ conn->marked_for_close = 1; } break; Loading Loading @@ -307,6 +303,9 @@ int connection_edge_finished_flushing(connection_t *conn) { case EXIT_CONN_STATE_OPEN: connection_stop_writing(conn); return connection_consider_sending_sendme(conn, conn->type); case AP_CONN_STATE_SOCKS_WAIT: connection_stop_writing(conn); return 0; default: log_fn(LOG_WARNING,"BUG: called in unexpected state."); return -1; Loading Loading @@ -445,23 +444,29 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { static int connection_ap_handshake_process_socks(connection_t *conn) { circuit_t *circ; char destaddr[200]; /* XXX why 200? but not 256, because it won't fit in a cell */ char reply[256]; uint16_t destport; int replylen=0; int sockshere; assert(conn); log_fn(LOG_DEBUG,"entered."); switch(fetch_from_buf_socks(conn->inbuf, destaddr, sizeof(destaddr), &destport)) { case -1: sockshere = fetch_from_buf_socks(conn->inbuf, &conn->socks_version, reply, &replylen, destaddr, sizeof(destaddr), &destport); if(sockshere == -1 || sockshere == 0) { if(replylen) { /* we should send reply back */ log_fn(LOG_DEBUG,"reply is already set for us. Using it."); connection_ap_handshake_socks_reply(conn, reply, replylen, 0); } else if(sockshere == -1) { /* send normal reject */ log_fn(LOG_WARNING,"Fetching socks handshake failed. Closing."); connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT); return -1; case 0: log_fn(LOG_DEBUG,"Fetching socks handshake, not all here yet. Ignoring."); return 0; /* case 1, fall through */ connection_ap_handshake_socks_reply(conn, NULL, 0, 0); } else { log_fn(LOG_DEBUG,"socks handshake not all here yet."); } return sockshere; } /* else socks handshake is done, continue processing */ /* find the circuit that we should use, if there is one. */ circ = circuit_get_newest_open(); Loading Loading @@ -521,26 +526,43 @@ static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t * return 0; } static int connection_ap_handshake_socks_reply(connection_t *conn, char result) { char buf[SOCKS4_NETWORK_LEN]; assert(conn); static int connection_ap_handshake_socks_reply(connection_t *conn, char *reply, int replylen, char success) { char buf[256]; /* an inlined socks4_pack() */ memset(buf,0,sizeof(buf)); buf[1] = result; /* command */ if(replylen) { /* we already have a reply in mind */ connection_write_to_buf(reply, replylen, conn); return connection_flush_buf(conn); /* try to flush it */ } if(conn->socks_version == 4) { memset(buf,0,SOCKS4_NETWORK_LEN); #define SOCKS4_GRANTED 90 #define SOCKS4_REJECT 91 buf[1] = (success ? SOCKS4_GRANTED : SOCKS4_REJECT); /* leave version, destport, destip zero */ if(connection_write_to_buf(buf, sizeof(buf), conn) < 0) return -1; return connection_flush_buf(conn); /* try to flush it, in case we're about to close the conn */ connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, conn); return connection_flush_buf(conn); /* try to flush it */ } if(conn->socks_version == 5) { buf[0] = 5; /* version 5 */ #define SOCKS5_SUCCESS 0 #define SOCKS5_GENERIC_ERROR 1 buf[1] = success ? SOCKS5_SUCCESS : SOCKS5_GENERIC_ERROR; buf[2] = 0; buf[3] = 1; /* ipv4 addr */ memset(buf+4,0,6); /* XXX set external addr/port to 0, see what breaks */ connection_write_to_buf(buf,10,conn); return connection_flush_buf(conn); /* try to flush it */ } assert(0); } /*ENDCLOSE*/ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { connection_t *n_stream; char *colon; if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0,cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) { if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0, cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) { log_fn(LOG_WARNING,"relay begin cell has no \\0. Dropping."); return 0; } Loading src/or/or.h +4 −1 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ #ifdef MS_WINDOWS #include <io.h> #include <process.h> #define WIN32_LEAN_AND_MEAN #include <windows.h> #define snprintf _snprintf Loading Loading @@ -301,6 +302,7 @@ struct connection_t { */ /* Used only by edge connections: */ char socks_version; char stream_id[STREAM_ID_SIZE]; struct connection_t *next_stream; /* points to the next stream at this edge, if any */ struct crypt_path_t *cpath_layer; /* a pointer to which node in the circ this conn exits at */ Loading Loading @@ -465,7 +467,8 @@ int fetch_from_buf(char *string, int string_len, buf_t *buf); int fetch_from_buf_http(buf_t *buf, char *headers_out, int max_headerlen, char *body_out, int max_bodylen); int fetch_from_buf_socks(buf_t *buf, int fetch_from_buf_socks(buf_t *buf, char *socks_version, char *reply, int *replylen, char *addr_out, int max_addrlen, uint16_t *port_out); Loading src/or/main.c +7 −7 File changed.Contains only whitespace changes. Show changes Loading
src/or/buffers.c +146 −74 Original line number Diff line number Diff line Loading @@ -317,66 +317,135 @@ int fetch_from_buf_http(buf_t *buf, return 1; } /* There is a (possibly incomplete) socks handshake on *buf, of the * forms * socks4: "socksheader || username\0". * socks4a: "socksheader || username\0 || destaddr\0". /* There is a (possibly incomplete) socks handshake on buf, of one * of the forms * socks4: "socksheader username\0" * socks4a: "socksheader username\0 destaddr\0" * socks5 phase one: "version #methods methods" * socks5 phase two: "version command 0 addresstype..." * If it's a complete and valid handshake, and destaddr fits in addr_out, * then pull the handshake off the buf, assign to addr_out and port_out, * and return 1. * If it's invalid or too big, return -1. * Else it's not all there yet, change nothing and return 0. * Else it's not all there yet, leave buf alone and return 0. * If you want to specify the socks reply, write it into *reply * and set *replylen, else leave *replylen alone. * If returning 0 or -1, *addr_out and *port_out are undefined. */ int fetch_from_buf_socks(buf_t *buf, int fetch_from_buf_socks(buf_t *buf, char *socks_version, char *reply, int *replylen, char *addr_out, int max_addrlen, uint16_t *port_out) { socks4_t socks4_info; unsigned char len; char *tmpbuf=NULL; uint16_t port; enum {socks4, socks4a } socks_prot = socks4a; uint32_t destip; enum {socks4, socks4a} socks4_prot = socks4a; char *next, *startaddr; struct in_addr in; if(buf->datalen < sizeof(socks4_t)) /* basic info available? */ return 0; /* not yet */ if(buf->datalen < 2) /* version and another byte */ return 0; switch(*(buf->buf)) { /* which version of socks? */ /* an inlined socks4_unpack() */ socks4_info.version = (unsigned char) *(buf->buf); socks4_info.command = (unsigned char) *(buf->buf+1); socks4_info.destport = ntohs(*(uint16_t*)(buf->buf+2)); socks4_info.destip = ntohl(*(uint32_t*)(buf->buf+4)); case 5: /* socks5 */ if(socks4_info.version != 4) { log_fn(LOG_WARNING,"Unrecognized version %d.",socks4_info.version); if(*socks_version != 5) { /* we need to negotiate a method */ unsigned char nummethods = (unsigned char)*(buf->buf+1); assert(!*socks_version); log_fn(LOG_DEBUG,"socks5: learning offered methods"); if(buf->datalen < 2+nummethods) return 0; if(!nummethods || !memchr(buf->buf+2, 0, nummethods)) { log_fn(LOG_WARNING,"socks5: offered methods don't include 'no auth'. Rejecting."); *replylen = 2; /* 2 bytes of response */ *reply = 5; /* socks5 reply */ *(reply+1) = 0xFF; /* reject all methods */ return -1; } buf->datalen -= (2+nummethods); /* remove packet from buf */ memmove(buf->buf, buf->buf + 2 + nummethods, buf->datalen); if(socks4_info.command != 1) { /* not a connect? we don't support it. */ log_fn(LOG_WARNING,"command %d not '1'.",socks4_info.command); *replylen = 2; /* 2 bytes of response */ *reply = 5; /* socks5 reply */ *(reply+1) = 0; /* choose the 'no auth' method */ *socks_version = 5; /* remember that we've already negotiated auth */ log_fn(LOG_DEBUG,"socks5: accepted method 0"); return 0; } /* we know the method; read in the request */ log_fn(LOG_DEBUG,"socks5: checking request"); if(buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */ return 0; /* not yet */ if(*(buf->buf+1) != 1) { /* not a connect? we don't support it. */ log_fn(LOG_WARNING,"socks5: command %d not '1'.",*(buf->buf+1)); return -1; } port = socks4_info.destport; if(!port) { log_fn(LOG_WARNING,"Port is zero."); switch(*(buf->buf+3)) { /* address type */ case 1: /* IPv4 address */ log_fn(LOG_DEBUG,"socks5: ipv4 address type"); if(buf->datalen < 10) /* ip/port there? */ return 0; /* not yet */ destip = ntohl(*(uint32_t*)(buf->buf+4)); in.s_addr = htonl(destip); tmpbuf = inet_ntoa(in); if(strlen(tmpbuf)+1 > max_addrlen) { log_fn(LOG_WARNING,"socks5 IP takes %d bytes, which doesn't fit in %d", strlen(tmpbuf)+1,max_addrlen); return -1; } strcpy(addr_out,tmpbuf); *port_out = ntohs(*(uint16_t*)(buf->buf+8)); buf->datalen -= 10; memmove(buf->buf, buf->buf+10, buf->datalen); return 1; case 3: /* fqdn */ log_fn(LOG_DEBUG,"socks5: fqdn address type"); len = (unsigned char)*(buf->buf+4); if(buf->datalen < 7+len) /* addr/port there? */ return 0; /* not yet */ if(len+1 > max_addrlen) { log_fn(LOG_WARNING,"socks5 hostname is %d bytes, which doesn't fit in %d", len+1,max_addrlen); return -1; } memcpy(addr_out,buf->buf+5,len); addr_out[len] = 0; *port_out = ntohs(*(uint16_t*)(buf->buf+5+len)); buf->datalen -= (5+len+2); memmove(buf->buf, buf->buf+(5+len+2), buf->datalen); return 1; default: /* unsupported */ log_fn(LOG_WARNING,"socks5: unsupported address type %d",*(buf->buf+3)); return -1; } assert(0); case 4: /* socks4 */ *socks_version = 4; if(buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */ return 0; /* not yet */ if(!socks4_info.destip) { log_fn(LOG_WARNING,"DestIP is zero."); if(*(buf->buf+1) != 1) { /* not a connect? we don't support it. */ log_fn(LOG_WARNING,"socks4: command %d not '1'.",*(buf->buf+1)); return -1; } if(socks4_info.destip >> 8) { struct in_addr in; log_fn(LOG_DEBUG,"destip not in form 0.0.0.x."); in.s_addr = htonl(socks4_info.destip); *port_out = ntohs(*(uint16_t*)(buf->buf+2)); destip = ntohl(*(uint32_t*)(buf->buf+4)); if(!*port_out || !destip) { log_fn(LOG_WARNING,"socks4: Port or DestIP is zero."); return -1; } if(destip >> 8) { log_fn(LOG_DEBUG,"socks4: destip not in form 0.0.0.x."); in.s_addr = htonl(destip); tmpbuf = inet_ntoa(in); if(max_addrlen <= strlen(tmpbuf)) { log_fn(LOG_WARNING,"socks4 addr too long."); if(strlen(tmpbuf)+1 > max_addrlen) { log_fn(LOG_WARNING,"socks4 addr (%d bytes) too long.", strlen(tmpbuf)); return -1; } log_fn(LOG_DEBUG,"Successfully read destip (%s)", tmpbuf); socks_prot = socks4; log_fn(LOG_DEBUG,"socks4: successfully read destip (%s)", tmpbuf); socks4_prot = socks4; } next = memchr(buf->buf+SOCKS4_NETWORK_LEN, 0, buf->datalen); Loading @@ -386,7 +455,7 @@ int fetch_from_buf_socks(buf_t *buf, } startaddr = next+1; if(socks_prot == socks4a) { if(socks4_prot == socks4a) { next = memchr(startaddr, 0, buf->buf+buf->datalen-startaddr); if(!next) { log_fn(LOG_DEBUG,"Destaddr not here yet."); Loading @@ -398,12 +467,15 @@ int fetch_from_buf_socks(buf_t *buf, } } log_fn(LOG_DEBUG,"Everything is here. Success."); *port_out = port; strcpy(addr_out, socks_prot == socks4 ? tmpbuf : startaddr); strcpy(addr_out, socks4_prot == socks4 ? tmpbuf : startaddr); buf->datalen -= (next-buf->buf+1); /* next points to the final \0 on inbuf */ memmove(buf->buf, next+1, buf->datalen); // log_fn(LOG_DEBUG,"buf_datalen is now %d:'%s'",*buf_datalen,buf); return 1; default: /* version is not socks4 or socks5 */ log_fn(LOG_WARNING,"Socks version %d not recognized.",*(buf->buf)); return -1; } } /* Loading
src/or/connection_edge.c +52 −30 Original line number Diff line number Diff line Loading @@ -9,15 +9,11 @@ extern or_options_t options; /* command-line and config-file options */ static int connection_ap_handshake_process_socks(connection_t *conn); static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ, char *destaddr, uint16_t destport); static int connection_ap_handshake_socks_reply(connection_t *conn, char result); static int connection_ap_handshake_socks_reply(connection_t *conn, char *reply, int replylen, char success); static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); #define SOCKS4_REQUEST_GRANTED 90 #define SOCKS4_REQUEST_REJECT 91 #define SOCKS4_REQUEST_IDENT_FAILED 92 #define SOCKS4_REQUEST_IDENT_CONFLICT 93 int connection_edge_process_inbuf(connection_t *conn) { assert(conn); Loading Loading @@ -242,7 +238,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection break; } log_fn(LOG_INFO,"Connected! Notifying application."); if(connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_GRANTED) < 0) { if(connection_ap_handshake_socks_reply(conn, NULL, 0, 1) < 0) { /*ENDCLOSE*/ conn->marked_for_close = 1; } break; Loading Loading @@ -307,6 +303,9 @@ int connection_edge_finished_flushing(connection_t *conn) { case EXIT_CONN_STATE_OPEN: connection_stop_writing(conn); return connection_consider_sending_sendme(conn, conn->type); case AP_CONN_STATE_SOCKS_WAIT: connection_stop_writing(conn); return 0; default: log_fn(LOG_WARNING,"BUG: called in unexpected state."); return -1; Loading Loading @@ -445,23 +444,29 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { static int connection_ap_handshake_process_socks(connection_t *conn) { circuit_t *circ; char destaddr[200]; /* XXX why 200? but not 256, because it won't fit in a cell */ char reply[256]; uint16_t destport; int replylen=0; int sockshere; assert(conn); log_fn(LOG_DEBUG,"entered."); switch(fetch_from_buf_socks(conn->inbuf, destaddr, sizeof(destaddr), &destport)) { case -1: sockshere = fetch_from_buf_socks(conn->inbuf, &conn->socks_version, reply, &replylen, destaddr, sizeof(destaddr), &destport); if(sockshere == -1 || sockshere == 0) { if(replylen) { /* we should send reply back */ log_fn(LOG_DEBUG,"reply is already set for us. Using it."); connection_ap_handshake_socks_reply(conn, reply, replylen, 0); } else if(sockshere == -1) { /* send normal reject */ log_fn(LOG_WARNING,"Fetching socks handshake failed. Closing."); connection_ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT); return -1; case 0: log_fn(LOG_DEBUG,"Fetching socks handshake, not all here yet. Ignoring."); return 0; /* case 1, fall through */ connection_ap_handshake_socks_reply(conn, NULL, 0, 0); } else { log_fn(LOG_DEBUG,"socks handshake not all here yet."); } return sockshere; } /* else socks handshake is done, continue processing */ /* find the circuit that we should use, if there is one. */ circ = circuit_get_newest_open(); Loading Loading @@ -521,26 +526,43 @@ static int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t * return 0; } static int connection_ap_handshake_socks_reply(connection_t *conn, char result) { char buf[SOCKS4_NETWORK_LEN]; assert(conn); static int connection_ap_handshake_socks_reply(connection_t *conn, char *reply, int replylen, char success) { char buf[256]; /* an inlined socks4_pack() */ memset(buf,0,sizeof(buf)); buf[1] = result; /* command */ if(replylen) { /* we already have a reply in mind */ connection_write_to_buf(reply, replylen, conn); return connection_flush_buf(conn); /* try to flush it */ } if(conn->socks_version == 4) { memset(buf,0,SOCKS4_NETWORK_LEN); #define SOCKS4_GRANTED 90 #define SOCKS4_REJECT 91 buf[1] = (success ? SOCKS4_GRANTED : SOCKS4_REJECT); /* leave version, destport, destip zero */ if(connection_write_to_buf(buf, sizeof(buf), conn) < 0) return -1; return connection_flush_buf(conn); /* try to flush it, in case we're about to close the conn */ connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, conn); return connection_flush_buf(conn); /* try to flush it */ } if(conn->socks_version == 5) { buf[0] = 5; /* version 5 */ #define SOCKS5_SUCCESS 0 #define SOCKS5_GENERIC_ERROR 1 buf[1] = success ? SOCKS5_SUCCESS : SOCKS5_GENERIC_ERROR; buf[2] = 0; buf[3] = 1; /* ipv4 addr */ memset(buf+4,0,6); /* XXX set external addr/port to 0, see what breaks */ connection_write_to_buf(buf,10,conn); return connection_flush_buf(conn); /* try to flush it */ } assert(0); } /*ENDCLOSE*/ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { connection_t *n_stream; char *colon; if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0,cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) { if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0, cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) { log_fn(LOG_WARNING,"relay begin cell has no \\0. Dropping."); return 0; } Loading
src/or/or.h +4 −1 Original line number Diff line number Diff line Loading @@ -84,6 +84,7 @@ #ifdef MS_WINDOWS #include <io.h> #include <process.h> #define WIN32_LEAN_AND_MEAN #include <windows.h> #define snprintf _snprintf Loading Loading @@ -301,6 +302,7 @@ struct connection_t { */ /* Used only by edge connections: */ char socks_version; char stream_id[STREAM_ID_SIZE]; struct connection_t *next_stream; /* points to the next stream at this edge, if any */ struct crypt_path_t *cpath_layer; /* a pointer to which node in the circ this conn exits at */ Loading Loading @@ -465,7 +467,8 @@ int fetch_from_buf(char *string, int string_len, buf_t *buf); int fetch_from_buf_http(buf_t *buf, char *headers_out, int max_headerlen, char *body_out, int max_bodylen); int fetch_from_buf_socks(buf_t *buf, int fetch_from_buf_socks(buf_t *buf, char *socks_version, char *reply, int *replylen, char *addr_out, int max_addrlen, uint16_t *port_out); Loading