|
@@ -395,19 +395,16 @@ int fetch_from_buf_http(buf_t *buf,
|
|
|
* 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 a complete and valid handshake, and destaddr fits in
|
|
|
+ * MAX_SOCKS_ADDR_LEN bytes, then pull the handshake off the buf,
|
|
|
+ * assign to *req, and return 1.
|
|
|
* If it's invalid or too big, return -1.
|
|
|
* 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, char *socks_version,
|
|
|
- char *reply, int *replylen,
|
|
|
- char *addr_out, int max_addrlen,
|
|
|
- uint16_t *port_out) {
|
|
|
+int fetch_from_buf_socks(buf_t *buf, socks_request_t *req) {
|
|
|
unsigned char len;
|
|
|
char *tmpbuf=NULL;
|
|
|
uint32_t destip;
|
|
@@ -421,25 +418,25 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
|
|
|
case 5: /* socks5 */
|
|
|
|
|
|
- if(*socks_version != 5) { /* we need to negotiate a method */
|
|
|
+ if(req->socks_version != 5) { /* we need to negotiate a method */
|
|
|
unsigned char nummethods = (unsigned char)*(buf->mem+1);
|
|
|
- assert(!*socks_version);
|
|
|
+ assert(!req->socks_version);
|
|
|
log_fn(LOG_DEBUG,"socks5: learning offered methods");
|
|
|
if(buf->datalen < 2+nummethods)
|
|
|
return 0;
|
|
|
if(!nummethods || !memchr(buf->mem+2, 0, nummethods)) {
|
|
|
log_fn(LOG_WARN,"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 */
|
|
|
+ req->replylen = 2; /* 2 bytes of response */
|
|
|
+ req->reply[0] = 5; /* socks5 reply */
|
|
|
+ req->reply[1] = 0xFF; /* reject all methods */
|
|
|
return -1;
|
|
|
}
|
|
|
buf_remove_from_front(buf,2+nummethods);/* remove packet from buf */
|
|
|
|
|
|
- *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 */
|
|
|
+ req->replylen = 2; /* 2 bytes of response */
|
|
|
+ req->reply[0] = 5; /* socks5 reply */
|
|
|
+ req->reply[1] = 0; /* choose the 'no auth' method */
|
|
|
+ req->socks_version = 5; /* remember that we've already negotiated auth */
|
|
|
log_fn(LOG_DEBUG,"socks5: accepted method 0");
|
|
|
return 0;
|
|
|
}
|
|
@@ -459,13 +456,13 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
destip = ntohl(*(uint32_t*)(buf->mem+4));
|
|
|
in.s_addr = htonl(destip);
|
|
|
tmpbuf = inet_ntoa(in);
|
|
|
- if(strlen(tmpbuf)+1 > max_addrlen) {
|
|
|
+ if(strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
|
|
|
log_fn(LOG_WARN,"socks5 IP takes %d bytes, which doesn't fit in %d",
|
|
|
- strlen(tmpbuf)+1,max_addrlen);
|
|
|
+ strlen(tmpbuf)+1,MAX_SOCKS_ADDR_LEN);
|
|
|
return -1;
|
|
|
}
|
|
|
- strcpy(addr_out,tmpbuf);
|
|
|
- *port_out = ntohs(*(uint16_t*)(buf->mem+8));
|
|
|
+ strcpy(req->addr,tmpbuf);
|
|
|
+ req->port = ntohs(*(uint16_t*)(buf->mem+8));
|
|
|
buf_remove_from_front(buf, 10);
|
|
|
return 1;
|
|
|
case 3: /* fqdn */
|
|
@@ -473,14 +470,14 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
len = (unsigned char)*(buf->mem+4);
|
|
|
if(buf->datalen < 7+len) /* addr/port there? */
|
|
|
return 0; /* not yet */
|
|
|
- if(len+1 > max_addrlen) {
|
|
|
+ if(len+1 > MAX_SOCKS_ADDR_LEN) {
|
|
|
log_fn(LOG_WARN,"socks5 hostname is %d bytes, which doesn't fit in %d",
|
|
|
- len+1,max_addrlen);
|
|
|
+ len+1,MAX_SOCKS_ADDR_LEN);
|
|
|
return -1;
|
|
|
}
|
|
|
- memcpy(addr_out,buf->mem+5,len);
|
|
|
- addr_out[len] = 0;
|
|
|
- *port_out = ntohs(*(uint16_t*)(buf->mem+5+len));
|
|
|
+ memcpy(req->addr,buf->mem+5,len);
|
|
|
+ req->addr[len] = 0;
|
|
|
+ req->port = ntohs(*(uint16_t*)(buf->mem+5+len));
|
|
|
buf_remove_from_front(buf, 5+len+2);
|
|
|
return 1;
|
|
|
default: /* unsupported */
|
|
@@ -490,7 +487,7 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
assert(0);
|
|
|
case 4: /* socks4 */
|
|
|
|
|
|
- *socks_version = 4;
|
|
|
+ req->socks_version = 4;
|
|
|
if(buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */
|
|
|
return 0; /* not yet */
|
|
|
|
|
@@ -499,9 +496,9 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- *port_out = ntohs(*(uint16_t*)(buf->mem+2));
|
|
|
+ req->port = ntohs(*(uint16_t*)(buf->mem+2));
|
|
|
destip = ntohl(*(uint32_t*)(buf->mem+4));
|
|
|
- if(!*port_out || !destip) {
|
|
|
+ if(!req->port || !destip) {
|
|
|
log_fn(LOG_WARN,"socks4: Port or DestIP is zero.");
|
|
|
return -1;
|
|
|
}
|
|
@@ -509,7 +506,7 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
log_fn(LOG_DEBUG,"socks4: destip not in form 0.0.0.x.");
|
|
|
in.s_addr = htonl(destip);
|
|
|
tmpbuf = inet_ntoa(in);
|
|
|
- if(strlen(tmpbuf)+1 > max_addrlen) {
|
|
|
+ if(strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
|
|
|
log_fn(LOG_WARN,"socks4 addr (%d bytes) too long.", strlen(tmpbuf));
|
|
|
return -1;
|
|
|
}
|
|
@@ -530,13 +527,13 @@ int fetch_from_buf_socks(buf_t *buf, char *socks_version,
|
|
|
log_fn(LOG_DEBUG,"Destaddr not here yet.");
|
|
|
return 0;
|
|
|
}
|
|
|
- if(max_addrlen <= next-startaddr) {
|
|
|
+ if(MAX_SOCKS_ADDR_LEN <= next-startaddr) {
|
|
|
log_fn(LOG_WARN,"Destaddr too long.");
|
|
|
return -1;
|
|
|
}
|
|
|
}
|
|
|
log_fn(LOG_DEBUG,"Everything is here. Success.");
|
|
|
- strcpy(addr_out, socks4_prot == socks4 ? tmpbuf : startaddr);
|
|
|
+ strcpy(req->addr, socks4_prot == socks4 ? tmpbuf : startaddr);
|
|
|
buf_remove_from_front(buf, next-buf->mem+1); /* next points to the final \0 on inbuf */
|
|
|
return 1;
|
|
|
|