@@ -5,42 +5,154 @@ use Test::More;
5
5
use Proc::Daemon;
6
6
use constant PIDFILE => ' /tmp/socksserver.pid' ;
7
7
8
- my $d = Proc::Daemon-> new( pid_file => PIDFILE, work_dir => ' .' , );
8
+ my $d = Proc::Daemon-> new(
9
+ pid_file => PIDFILE,
10
+ work_dir => ' .' ,
11
+ );
9
12
die ' Already running' unless ( 0 == ( -r PIDFILE ? $d -> Status(PIDFILE) : 0 ) );
10
13
11
14
my $k = $d -> Init();
12
15
unless ( 0 == $k ) {
13
16
plan tests => 1;
14
17
ok $k , " Started Daemon at $k " ;
18
+ sleep 2;
19
+ until (
20
+ my $s = IO::Socket::Socks-> new(
21
+ ProxyAddr => ' 127.0.0.1' ,
22
+ ProxyPort => 9051,
23
+ ConnectAddr => ' nulloooooooooooo.onion' ,
24
+ ConnectPort => ' 25' ,
25
+ )
26
+ )
27
+ {
28
+ warn $IO::Socket::Socks::SOCKS_ERROR ;
29
+ sleep 2;
30
+ }
15
31
exit 0;
16
32
}
17
33
18
- my ( $output , $failure_output , $todo_output , ) ;
34
+ my $output ;
19
35
my $builder = Test::More-> builder;
20
36
$builder -> output( \$output );
21
- $builder -> failure_output( \$failure_output );
22
- $builder -> todo_output( \$todo_output );
37
+ $builder -> failure_output( \$output );
38
+ $builder -> todo_output( \$output );
23
39
24
40
my $tests = 0;
25
41
26
42
my %tree = (
43
+ ' manualhttpdooooo.onion:80' => sub {
44
+ my $client = shift ;
45
+ use HTTP::Headers;
46
+ my $h = HTTP::Headers-> new;
47
+ my ( $hname , $hdata );
48
+ while ( ( $_ = <$client > ) =~ / ^[\r ]?$ / ) {
49
+ if ( $hname != undef ) {
50
+ if (/ ^[ \t ]/ ) {
51
+ $hdata .= $_ ;
52
+ } else {
53
+ $h -> push_header( $hname => $hdata );
54
+ / ^([^:]*):?(.*)$ / ;
55
+ $hname = $1 ;
56
+ $hdata = $2 ;
57
+ }
58
+ } else {
59
+ / ^([^:]*):?(.*)$ / ;
60
+ $hname = $1 ;
61
+ $hdata = $2 ;
62
+ }
63
+ }
64
+ $h -> push_header( $hname => $hdata );
65
+ },
66
+ ' perlhttpdooooooo.onion:80' => sub {
67
+ my $client = shift ;
68
+ use HTTP::Daemon();
69
+
70
+ # This should not work.
71
+ HTTP::Daemon::ClientConn::get_request($client );
72
+ },
73
+ ' echooooooooooooo.onion:80' => sub {
74
+ my $client = shift ;
75
+ my $len = 1;
76
+ do {
77
+ my $request = ' ' ;
78
+ while ( 0 < $len && $request !~ / \n /m ) {
79
+ $len = $client -> read ( my $b , 1 );
80
+ $request .= $b ;
81
+ }
82
+ if ( 0 < $len ) {
83
+ $tests ++;
84
+ ok $request =~ m % HTTP/1.1\r ?\n % im , ' Have HTTP 1.1' ;
85
+ if ( $request =~ m % //[a-z2-7] {16}\\ .onion% i ) {
86
+ $tests ++;
87
+ ok $request =~ m % //[a-z2-7] {16}\\ .onion/% i ,
88
+ ' Correct hostname in request line' ;
89
+ }
90
+ }
91
+ while ( 0 < $len && $request !~ / \n\r ?\n /m ) {
92
+ $len = $client -> read ( my $b , 1 );
93
+ $request .= $b ;
94
+ }
95
+ if ( 0 < $len ) {
96
+ if ( $request =~ / ^Host:\s *([a-z2-7]{16}\\ .onion[^\r\n ]*)/mi ) {
97
+ $tests ++;
98
+ my $h = $1 ;
99
+ ok $request =~ m % ^Host:\s *[a-z2-7] {16}\\ .onion\r ?\n /% i ,
100
+ " Correct hostname in host header: $h " ;
101
+ }
102
+ if ( $request =~ / ^Cookie:([^\r\n ]*)/mi ) {
103
+ $tests ++;
104
+ my $h = $1 ;
105
+ fail " Correct cookie domain: $h " ;
106
+ }
107
+ if ( $request =~ / ^Content-Length:\s *([1-9][0-9]*)/mi ) {
108
+ my ( $b , $clen ) = ( undef , $1 );
109
+ while ( 0 < $clen ) {
110
+ $len = $client -> read ( $b , $clen );
111
+ $request .= $b ;
112
+ $clen -= $len ;
113
+ }
114
+ }
115
+ }
116
+ my $clen = length $request ;
117
+ $client -> print (
118
+ " HTTP/1.1 200 Success\r\n Content-Type: text/plain\r\n Content-Length: $clen \r\n\r\n $request "
119
+ );
120
+ } while ( 0 != $len );
121
+ },
122
+ ' proxy2httpdooooo.onion:80' => sub {
123
+ my $client = shift ;
124
+
125
+ # Open connection to httpd and enter bi-directional pass-through.
126
+ # Ends when socket closes.
127
+ },
128
+ ' nulloooooooooooo.onion:25' => sub {
129
+ my $client = shift ;
130
+ },
27
131
' exit:25' => sub {
28
132
my $client = shift ;
29
133
done_testing($tests );
30
- $client -> send ( $output . $failure_output . $todo_output );
31
- $client -> close ();
134
+ $client -> print ($output );
32
135
exit 0;
33
136
},
34
137
);
35
138
36
139
use IO::Socket::Socks ' :constants' ;
37
140
38
- my $s = IO::Socket::Socks-> new(
39
- ProxyAddr => ' localhost' ,
40
- ProxyPort => 9051,
41
- Listen => 1,
42
- SocksResolve => 0,
43
- ) or die $IO::Socket::Socks::SOCKS_ERROR ;
141
+ $IO::Socket::Socks::SOCKS4_RESOLVE = 1;
142
+ $IO::Socket::Socks::SOCKS5_RESOLVE = 0;
143
+ my $s ;
144
+ until (
145
+ $s = IO::Socket::Socks-> new(
146
+ SocksVersion => [ 4, 5 ],
147
+ ProxyAddr => ' 127.0.0.1' ,
148
+ ProxyPort => 9051,
149
+ Listen => 1,
150
+ )
151
+ )
152
+ {
153
+ diag $IO::Socket::Socks::SOCKS_ERROR ;
154
+ sleep 3;
155
+ }
44
156
45
157
ok $s , ' Have socks server' ;
46
158
$tests ++;
@@ -49,20 +161,42 @@ while (1) {
49
161
my $client = $s -> accept();
50
162
51
163
unless ($client ) {
52
- print STDERR " ERROR: $IO::Socket::Socks::SOCKS_ERROR \n " ;
164
+ fail $IO::Socket::Socks::SOCKS_ERROR ;
165
+ $tests ++;
53
166
next ;
54
167
}
55
168
56
169
my $command = $client -> command();
57
170
if ( $command -> [0] == CMD_CONNECT ) {
58
-
59
- # Handle the CONNECT
60
- $client -> command_reply( REPLY_SUCCESS, $command -> [1], $command -> [2] );
171
+ my $host = $client -> version == 4 ? " 0.0.0.1" : $command -> [1];
172
+ if ( exists $tree {" $command ->[1]:$command ->[2]" } ) {
173
+
174
+ # Handle the CONNECT
175
+ $client -> command_reply(
176
+ $client -> version == 4 ? REQUEST_GRANTED : REPLY_SUCCESS,
177
+ $host , $command -> [2] );
178
+ $client -> autoflush(1);
179
+ $tree {" $command ->[1]:$command ->[2]" }($client );
180
+ } else {
181
+ diag " Not found in tree: $command ->[1]:$command ->[2]" ;
182
+ diag $client -> command_reply(
183
+ $client -> version == 4
184
+ ? REQUEST_FAILED
185
+ : REPLY_ADDR_NOT_SUPPORTED,
186
+ $host , $command -> [2]
187
+ );
188
+ }
189
+ } else {
190
+ diag ' Unknowen command from socks:' ;
191
+ use Data::Dumper;
192
+ diag Dumper $command ;
193
+ $client -> command_reply( $client -> version == 4
194
+ ? REQUEST_FAILED
195
+ : REPLY_CMD_NOT_SUPPORTED,
196
+ $command -> [1], $command -> [2] );
61
197
}
62
198
63
- $tree {" $command ->[1]:$command ->[2]" }($client )
64
- if ( exists $tree {" $command ->[1]:$command ->[2]" } );
65
-
199
+ sleep 2;
66
200
$client -> close ();
67
201
}
68
202
0 commit comments