|
@@ -5,6 +5,7 @@
|
|
#include "or.h"
|
|
#include "or.h"
|
|
|
|
|
|
extern int global_role;
|
|
extern int global_role;
|
|
|
|
+static const char socks_userid[] = "anonymous";
|
|
|
|
|
|
int connection_ap_process_inbuf(connection_t *conn) {
|
|
int connection_ap_process_inbuf(connection_t *conn) {
|
|
|
|
|
|
@@ -19,8 +20,8 @@ int connection_ap_process_inbuf(connection_t *conn) {
|
|
|
|
|
|
|
|
|
|
switch(conn->state) {
|
|
switch(conn->state) {
|
|
- case AP_CONN_STATE_SS_WAIT:
|
|
+ case AP_CONN_STATE_SOCKS_WAIT:
|
|
- return ap_handshake_process_ss(conn);
|
|
+ return ap_handshake_process_socks(conn);
|
|
case AP_CONN_STATE_OPEN:
|
|
case AP_CONN_STATE_OPEN:
|
|
return connection_package_raw_inbuf(conn);
|
|
return connection_package_raw_inbuf(conn);
|
|
default:
|
|
default:
|
|
@@ -30,107 +31,91 @@ int connection_ap_process_inbuf(connection_t *conn) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-int ap_handshake_process_ss(connection_t *conn) {
|
|
+int ap_handshake_process_socks(connection_t *conn) {
|
|
- uint16_t len;
|
|
+ char c;
|
|
|
|
+ socks4_t socks4_info;
|
|
|
|
+ static char destaddr[512];
|
|
|
|
+ static int destlen=0;
|
|
|
|
|
|
assert(conn);
|
|
assert(conn);
|
|
|
|
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss() entered.");
|
|
+ log(LOG_DEBUG,"ap_handshake_process_socks() entered.");
|
|
|
|
|
|
- if(!conn->ss_received) {
|
|
+ if(!conn->socks_version) {
|
|
|
|
|
|
- if(conn->inbuf_datalen < sizeof(ss_t))
|
|
+ if(conn->inbuf_datalen < sizeof(socks4_t))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- if(connection_fetch_from_buf((char *)&conn->ss,sizeof(ss_t),conn) < 0)
|
|
+ if(connection_fetch_from_buf((char *)&socks4_info,sizeof(socks4_t),conn) < 0)
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
- conn->ss_received = sizeof(ss_t);
|
|
+ log(LOG_DEBUG,"ap_handshake_process_socks(): Successfully read socks info.");
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Successfully read ss.");
|
|
|
|
|
|
|
|
- if ((conn->ss.version == 0) || (conn->ss.version != OR_VERSION)) {
|
|
+ if(socks4_info.version != 4) {
|
|
- log(LOG_NOTICE,"ap_handshake_process_ss(): ss: Unsupported version '%c'.",conn->ss.version);
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): Unrecognized version %d.",socks4_info.version);
|
|
- if(tolower(conn->ss.version) == 'g') {
|
|
+ ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
|
- log(LOG_NOTICE,"ap_handshake_process_ss(): are you using the onion proxy as a web proxy?");
|
|
|
|
- }
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
- if (conn->ss.addr_fmt != SS_ADDR_FMT_ASCII_HOST_PORT) {
|
|
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): ss: Unrecognized address format.");
|
|
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
- }
|
|
+ conn->socks_version = socks4_info.version;
|
|
-
|
|
|
|
- if(!conn->dest_addr) {
|
|
|
|
|
|
|
|
- if(conn->inbuf_datalen < sizeof(uint16_t))
|
|
+ if(socks4_info.command != 1) {
|
|
- return 0;
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): command %d not '1'.",socks4_info.command);
|
|
-
|
|
+ ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
|
- if(connection_fetch_from_buf((char *)&len,sizeof(uint16_t),conn) < 0)
|
|
|
|
- return -1;
|
|
|
|
-
|
|
|
|
- len = ntohs(len);
|
|
|
|
- if(len > 512) {
|
|
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Addr length %d too high.",len);
|
|
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- conn->dest_addr = malloc(len+1);
|
|
+ conn->dest_port = ntohs(*(uint16_t*)&socks4_info.destport);
|
|
- if(!conn->dest_addr) {
|
|
+ if(!conn->dest_port) {
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Addr malloc failed");
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): Port is zero.");
|
|
|
|
+ ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
-
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): Dest port is %d.",conn->dest_port);
|
|
- conn->dest_addr[len] = 0;
|
|
+
|
|
- conn->dest_addr_len = len;
|
|
+ if(socks4_info.destip[0] ||
|
|
- log(LOG_DEBUG,"Preparing a dest_addr of %d+1 bytes.",len);
|
|
+ socks4_info.destip[1] ||
|
|
- }
|
|
+ socks4_info.destip[2] ||
|
|
- if(conn->dest_addr_len != conn->dest_addr_received) {
|
|
+ !socks4_info.destip[3]) {
|
|
-
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): destip not in form 0.0.0.x.");
|
|
- if(conn->inbuf_datalen < conn->dest_addr_len)
|
|
+ ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- if(connection_fetch_from_buf(conn->dest_addr,conn->dest_addr_len,conn) < 0)
|
|
|
|
return -1;
|
|
return -1;
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Read dest_addr '%s'.",conn->dest_addr);
|
|
+ }
|
|
|
|
+ log(LOG_DEBUG,"ap_handshake_process_socks(): Successfully read destip (0.0.0.x.)");
|
|
|
|
|
|
- conn->dest_addr_received = conn->dest_addr_len;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- if(!conn->dest_port) {
|
|
|
|
-
|
|
|
|
- if(conn->inbuf_datalen < sizeof(uint16_t))
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- if(connection_fetch_from_buf((char *)&len,sizeof(uint16_t),conn) < 0)
|
|
|
|
- return -1;
|
|
|
|
-
|
|
|
|
- len = ntohs(len);
|
|
|
|
- if(len > 10) {
|
|
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Port length %d too high.",len);
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- conn->dest_port = malloc(len+1);
|
|
+ if(!conn->read_username) {
|
|
- if(!conn->dest_port) {
|
|
+ while(conn->inbuf_datalen) {
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Port malloc failed");
|
|
+ if(connection_fetch_from_buf((char *)&c,1,conn) < 0)
|
|
- return -1;
|
|
+ return -1;
|
|
|
|
+ if(!c) {
|
|
|
|
+ conn->read_username = 1;
|
|
|
|
+ log(LOG_DEBUG,"ap_handshake_process_socks(): Successfully read username.");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- conn->dest_port[len] = 0;
|
|
|
|
- conn->dest_port_len = len;
|
|
|
|
- log(LOG_DEBUG,"Preparing a dest_port of %d+1 bytes.",len);
|
|
|
|
}
|
|
}
|
|
- if(conn->dest_port_len != conn->dest_port_received) {
|
|
|
|
|
|
|
|
- if(conn->inbuf_datalen < conn->dest_port_len)
|
|
+ if(!conn->dest_addr) {
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- if(connection_fetch_from_buf(conn->dest_port,conn->dest_port_len,conn) < 0)
|
|
|
|
- return -1;
|
|
|
|
- log(LOG_DEBUG,"ap_handshake_process_ss(): Read dest_port '%s'.",conn->dest_port);
|
|
|
|
|
|
|
|
- conn->dest_port_received = conn->dest_port_len;
|
|
+ while(conn->inbuf_datalen) {
|
|
|
|
+ if(connection_fetch_from_buf((char *)&c,1,conn) < 0)
|
|
|
|
+ return -1;
|
|
|
|
+ destaddr[destlen++] = c;
|
|
|
|
+ if(destlen > 500) {
|
|
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): dest_addr too long!");
|
|
|
|
+ ap_handshake_socks_reply(conn, SOCKS4_REQUEST_REJECT);
|
|
|
|
+ destlen = 0;
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ if(!c) {
|
|
|
|
+ conn->dest_addr = strdup(destaddr);
|
|
|
|
+ destlen = 0;
|
|
|
|
+ log(LOG_NOTICE,"ap_handshake_process_socks(): successfully read dest addr '%s'",
|
|
|
|
+ conn->dest_addr);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -291,6 +276,7 @@ int ap_handshake_send_onion(connection_t *ap_conn, connection_t *n_conn, circuit
|
|
}
|
|
}
|
|
free(tmpbuf);
|
|
free(tmpbuf);
|
|
|
|
|
|
|
|
+#if 0
|
|
|
|
|
|
cell.command = CELL_DATA;
|
|
cell.command = CELL_DATA;
|
|
cell.aci = circ->n_aci;
|
|
cell.aci = circ->n_aci;
|
|
@@ -302,12 +288,13 @@ int ap_handshake_send_onion(connection_t *ap_conn, connection_t *n_conn, circuit
|
|
circuit_close(circ);
|
|
circuit_close(circ);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
cell.command = CELL_DATA;
|
|
cell.command = CELL_DATA;
|
|
cell.aci = circ->n_aci;
|
|
cell.aci = circ->n_aci;
|
|
- cell.length = ap_conn->dest_addr_len+1;
|
|
+ strncpy(cell.payload, ap_conn->dest_addr, CELL_PAYLOAD_SIZE);
|
|
- strncpy(cell.payload, ap_conn->dest_addr, ap_conn->dest_addr_len+1);
|
|
+ cell.length = strlen(cell.payload)+1;
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): Sending a data cell for addr...");
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): Sending a data cell for addr...");
|
|
if(circuit_deliver_data_cell(&cell, circ, circ->n_conn, 'e') < 0) {
|
|
if(circuit_deliver_data_cell(&cell, circ, circ->n_conn, 'e') < 0) {
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): failed to deliver addr cell. Closing.");
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): failed to deliver addr cell. Closing.");
|
|
@@ -318,8 +305,8 @@ int ap_handshake_send_onion(connection_t *ap_conn, connection_t *n_conn, circuit
|
|
|
|
|
|
cell.command = CELL_DATA;
|
|
cell.command = CELL_DATA;
|
|
cell.aci = circ->n_aci;
|
|
cell.aci = circ->n_aci;
|
|
- cell.length = ap_conn->dest_port_len+1;
|
|
+ snprintf(cell.payload, CELL_PAYLOAD_SIZE, "%d", ap_conn->dest_port);
|
|
- strncpy(cell.payload, ap_conn->dest_port, ap_conn->dest_port_len+1);
|
|
+ cell.length = strlen(cell.payload)+1;
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): Sending a data cell for port...");
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): Sending a data cell for port...");
|
|
if(circuit_deliver_data_cell(&cell, circ, circ->n_conn, 'e') < 0) {
|
|
if(circuit_deliver_data_cell(&cell, circ, circ->n_conn, 'e') < 0) {
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): failed to deliver port cell. Closing.");
|
|
log(LOG_DEBUG,"ap_handshake_send_onion(): failed to deliver port cell. Closing.");
|
|
@@ -336,13 +323,24 @@ int ap_handshake_send_onion(connection_t *ap_conn, connection_t *n_conn, circuit
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-int connection_ap_send_connected(connection_t *conn) {
|
|
+int ap_handshake_socks_reply(connection_t *conn, char result) {
|
|
- char zero=0;
|
|
+ socks4_t socks4_info;
|
|
|
|
|
|
assert(conn);
|
|
assert(conn);
|
|
|
|
|
|
-
|
|
+ socks4_info.version = 4;
|
|
- return connection_write_to_buf(&zero, 1, conn);
|
|
+ socks4_info.command = result;
|
|
|
|
+ socks4_info.destport[0] = socks4_info.destport[1] = 0;
|
|
|
|
+ socks4_info.destip[0] = socks4_info.destip[1] = socks4_info.destip[2] = socks4_info.destip[3] = 0;
|
|
|
|
+
|
|
|
|
+ connection_write_to_buf((char *)&socks4_info, sizeof(socks4_t), conn);
|
|
|
|
+ return connection_flush_buf(conn);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int connection_ap_send_connected(connection_t *conn) {
|
|
|
|
+ assert(conn);
|
|
|
|
+
|
|
|
|
+ return ap_handshake_socks_reply(conn, SOCKS4_REQUEST_GRANTED);
|
|
}
|
|
}
|
|
|
|
|
|
int connection_ap_process_data_cell(cell_t *cell, connection_t *conn) {
|
|
int connection_ap_process_data_cell(cell_t *cell, connection_t *conn) {
|
|
@@ -388,7 +386,7 @@ int connection_ap_create_listener(crypto_pk_env_t *prkey, struct sockaddr_in *lo
|
|
}
|
|
}
|
|
|
|
|
|
int connection_ap_handle_listener_read(connection_t *conn) {
|
|
int connection_ap_handle_listener_read(connection_t *conn) {
|
|
- log(LOG_NOTICE,"AP: Received a connection request. Waiting for SS.");
|
|
+ log(LOG_NOTICE,"AP: Received a connection request. Waiting for socksinfo.");
|
|
- return connection_handle_listener_read(conn, CONN_TYPE_AP, AP_CONN_STATE_SS_WAIT);
|
|
+ return connection_handle_listener_read(conn, CONN_TYPE_AP, AP_CONN_STATE_SOCKS_WAIT);
|
|
}
|
|
}
|
|
|
|
|