Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ZerXes
Tor
Commits
a6bab569
Commit
a6bab569
authored
Oct 04, 2003
by
Roger Dingledine
Browse files
socks5 now works
(or at least, we can talk to mozilla.) svn:r536
parent
750b238a
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/or/buffers.c
View file @
a6bab569
...
...
@@ -317,93 +317,165 @@ 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
;
uint
16
_t
port
;
enum
{
socks4
,
socks4a
}
socks_prot
=
socks4a
;
uint
32
_t
destip
;
enum
{
socks4
,
socks4a
}
socks
4
_prot
=
socks4a
;
char
*
next
,
*
startaddr
;
struct
in_addr
in
;
if
(
buf
->
datalen
<
sizeof
(
socks4_t
))
/* basic info available? */
return
0
;
/* not yet */
/* 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
));
if
(
socks4_info
.
version
!=
4
)
{
log_fn
(
LOG_WARNING
,
"Unrecognized version %d."
,
socks4_info
.
version
);
return
-
1
;
}
if
(
socks4_info
.
command
!=
1
)
{
/* not a connect? we don't support it. */
log_fn
(
LOG_WARNING
,
"command %d not '1'."
,
socks4_info
.
command
);
return
-
1
;
}
port
=
socks4_info
.
destport
;
if
(
!
port
)
{
log_fn
(
LOG_WARNING
,
"Port is zero."
);
return
-
1
;
}
if
(
!
socks4_info
.
destip
)
{
log_fn
(
LOG_WARNING
,
"DestIP is zero."
);
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
);
tmpbuf
=
inet_ntoa
(
in
);
if
(
max_addrlen
<=
strlen
(
tmpbuf
))
{
log_fn
(
LOG_WARNING
,
"socks4 addr too long."
);
return
-
1
;
}
log_fn
(
LOG_DEBUG
,
"Successfully read destip (%s)"
,
tmpbuf
);
socks_prot
=
socks4
;
}
next
=
memchr
(
buf
->
buf
+
SOCKS4_NETWORK_LEN
,
0
,
buf
->
datalen
);
if
(
!
next
)
{
log_fn
(
LOG_DEBUG
,
"Username not here yet."
);
if
(
buf
->
datalen
<
2
)
/* version and another byte */
return
0
;
}
startaddr
=
next
+
1
;
if
(
socks_prot
==
socks4a
)
{
next
=
memchr
(
startaddr
,
0
,
buf
->
buf
+
buf
->
datalen
-
startaddr
);
if
(
!
next
)
{
log_fn
(
LOG_DEBUG
,
"Destaddr not here yet."
);
return
0
;
}
if
(
max_addrlen
<=
next
-
startaddr
)
{
log_fn
(
LOG_WARNING
,
"Destaddr too long."
);
switch
(
*
(
buf
->
buf
))
{
/* which version of socks? */
case
5
:
/* socks5 */
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
);
*
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
;
}
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
(
*
(
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
;
}
*
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
(
strlen
(
tmpbuf
)
+
1
>
max_addrlen
)
{
log_fn
(
LOG_WARNING
,
"socks4 addr (%d bytes) too long."
,
strlen
(
tmpbuf
));
return
-
1
;
}
log_fn
(
LOG_DEBUG
,
"socks4: successfully read destip (%s)"
,
tmpbuf
);
socks4_prot
=
socks4
;
}
next
=
memchr
(
buf
->
buf
+
SOCKS4_NETWORK_LEN
,
0
,
buf
->
datalen
);
if
(
!
next
)
{
log_fn
(
LOG_DEBUG
,
"Username not here yet."
);
return
0
;
}
startaddr
=
next
+
1
;
if
(
socks4_prot
==
socks4a
)
{
next
=
memchr
(
startaddr
,
0
,
buf
->
buf
+
buf
->
datalen
-
startaddr
);
if
(
!
next
)
{
log_fn
(
LOG_DEBUG
,
"Destaddr not here yet."
);
return
0
;
}
if
(
max_addrlen
<=
next
-
startaddr
)
{
log_fn
(
LOG_WARNING
,
"Destaddr too long."
);
return
-
1
;
}
}
log_fn
(
LOG_DEBUG
,
"Everything is here. Success."
);
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
);
return
1
;
default:
/* version is not socks4 or socks5 */
log_fn
(
LOG_WARNING
,
"Socks version %d not recognized."
,
*
(
buf
->
buf
));
return
-
1
;
}
}
log_fn
(
LOG_DEBUG
,
"Everything is here. Success."
);
*
port_out
=
port
;
strcpy
(
addr_out
,
socks_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
;
}
/*
...
...
src/or/connection_edge.c
View file @
a6bab569
...
...
@@ -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
);
...
...
@@ -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
;
...
...
@@ -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
;
...
...
@@ -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
();
...
...
@@ -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
);
/* an inlined socks4_pack() */
memset
(
buf
,
0
,
sizeof
(
buf
));
buf
[
1
]
=
result
;
/* command */
/* leave version, destport, destip zero */
static
int
connection_ap_handshake_socks_reply
(
connection_t
*
conn
,
char
*
reply
,
int
replylen
,
char
success
)
{
char
buf
[
256
];
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 */
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 */
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
;
}
...
...
src/or/main.c
View file @
a6bab569
...
...
@@ -678,13 +678,13 @@ static void dumpstats(void) { /* dump stats to stdout */
circuit_dump_by_conn
(
conn
);
/* dump info about all the circuits using this conn */
printf
(
"
\n
"
);
}
printf
(
"Cells processed: %
10lud padding
\n
"
" %
10lud create
\n
"
" %
10lud created
\n
"
" %
10lud relay
\n
"
" (%
10lud relayed)
\n
"
" (%
10lud delivered)
\n
"
" %
10lud destroy
\n
"
,
printf
(
"Cells processed: %10lud padding
\n
"
" %10lud create
\n
"
" %10lud created
\n
"
" %10lud relay
\n
"
" (%10lud relayed)
\n
"
" (%10lud delivered)
\n
"
" %10lud destroy
\n
"
,
stats_n_padding_cells_processed
,
stats_n_create_cells_processed
,
stats_n_created_cells_processed
,
...
...
src/or/or.h
View file @
a6bab569
...
...
@@ -84,6 +84,7 @@
#ifdef MS_WINDOWS
#include
<io.h>
#include
<process.h>
#define WIN32_LEAN_AND_MEAN
#include
<windows.h>
#define snprintf _snprintf
...
...
@@ -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 */
...
...
@@ -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
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment