line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Protocol::SOCKS::Server; |
2
|
|
|
|
|
|
|
$Protocol::SOCKS::Server::VERSION = '0.003'; |
3
|
1
|
|
|
1
|
|
30735
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
35
|
|
4
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
1495
|
use parent qw(Protocol::SOCKS); |
|
1
|
|
|
|
|
328
|
|
|
1
|
|
|
|
|
5
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Protocol::SOCKS::Server - server support for SOCKS protocol |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 VERSION |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Version 0.003 |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 DESCRIPTION |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
This provides an abstraction for dealing with the server side of the SOCKS protocol. |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=cut |
21
|
|
|
|
|
|
|
|
22
|
1
|
|
|
1
|
|
50
|
use Future; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
23
|
1
|
|
|
1
|
|
7
|
use Socket qw(inet_pton inet_ntop inet_ntoa AF_INET AF_INET6); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
64
|
|
24
|
|
|
|
|
|
|
|
25
|
1
|
|
|
1
|
|
6
|
use Protocol::SOCKS::Constants qw(:all); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
771
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 METHODS |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=cut |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head2 completion |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
Returns the completion future. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=cut |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
0
|
0
|
1
|
0
|
sub completion { $_[0]->{completion} ||= $_[0]->new_future } |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head2 auth |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Returns the auth Future. |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=cut |
44
|
|
|
|
|
|
|
|
45
|
0
|
|
0
|
0
|
1
|
0
|
sub auth { $_[0]->{auth} ||= $_[0]->new_future } |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head2 auth_methods |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
Returns the list of auth methods we can handle. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=cut |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub auth_methods { |
54
|
3
|
|
|
3
|
1
|
4
|
my $self = shift; |
55
|
3
|
|
100
|
|
|
4
|
@{ $self->{auth_methods} ||= [ AUTH_NONE ] } |
|
3
|
|
|
|
|
29
|
|
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head2 init_packet |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Initial client packet. |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=cut |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub init_packet { |
65
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
66
|
0
|
|
|
|
|
0
|
my @methods = (0); |
67
|
0
|
|
|
|
|
0
|
pack 'C1C/C*', $self->version, $self->auth_methods; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head2 on_read |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Handler for reading data from the client. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=cut |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub on_read { |
77
|
2
|
|
|
2
|
1
|
1782
|
my ($self, $buf) = @_; |
78
|
2
|
50
|
|
|
|
7
|
if(!$self->init->is_ready) { |
79
|
2
|
50
|
|
|
|
26
|
return if length($$buf) < 3; |
80
|
2
|
|
|
|
|
12
|
my (undef, $method_count) = unpack 'C1C', substr $$buf, 0, 2; |
81
|
2
|
50
|
|
|
|
8
|
return unless length($$buf) >= 2 + $method_count; |
82
|
|
|
|
|
|
|
|
83
|
2
|
|
|
|
|
8
|
my ($version, $methods) = unpack 'C1C/C*', substr $$buf, 0, 2 + $method_count, ''; |
84
|
2
|
50
|
|
|
|
9
|
die "Invalid version" unless $version == $self->version; |
85
|
2
|
|
|
|
|
3
|
my $auth_method; |
86
|
|
|
|
|
|
|
METHOD: |
87
|
2
|
|
|
|
|
11
|
for my $method (split //, $methods) { |
88
|
3
|
100
|
|
|
|
9
|
next METHOD unless grep $method == $_, $self->auth_methods; |
89
|
1
|
|
|
|
|
3
|
$auth_method = $method; |
90
|
1
|
|
|
|
|
3
|
last METHOD; |
91
|
|
|
|
|
|
|
} |
92
|
2
|
100
|
|
|
|
6
|
unless(defined $auth_method) { |
93
|
1
|
|
|
|
|
5
|
$self->write( |
94
|
|
|
|
|
|
|
pack 'C1C1', |
95
|
|
|
|
|
|
|
$self->version, |
96
|
|
|
|
|
|
|
AUTH_FAIL, |
97
|
|
|
|
|
|
|
); |
98
|
1
|
|
|
|
|
375
|
return $self->init->fail(auth => 'no suitable methods'); |
99
|
|
|
|
|
|
|
} |
100
|
1
|
|
|
|
|
10
|
$self->init->done($version => $auth_method); |
101
|
1
|
|
|
|
|
53
|
return $self->write( |
102
|
|
|
|
|
|
|
pack 'C1C1', |
103
|
|
|
|
|
|
|
$self->version, |
104
|
|
|
|
|
|
|
$auth_method |
105
|
|
|
|
|
|
|
) |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
0
|
0
|
|
|
|
0
|
return unless my $details = $self->parse_request($buf); |
109
|
|
|
|
|
|
|
|
110
|
0
|
|
|
|
|
0
|
my $f = shift @{$self->{awaiting_reply}}; |
|
0
|
|
|
|
|
0
|
|
111
|
0
|
|
|
|
|
0
|
$f->done($details); |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head2 init |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Resolves with version and auth method when connection |
117
|
|
|
|
|
|
|
has been established |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=cut |
120
|
|
|
|
|
|
|
|
121
|
6
|
|
66
|
6
|
1
|
1321
|
sub init { $_[0]->{init} ||= $_[0]->new_future } |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head2 parse_request |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Parse a client request. |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=cut |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub parse_request { |
130
|
0
|
|
|
0
|
1
|
|
my ($self, $buffref) = @_; |
131
|
0
|
0
|
|
|
|
|
return unless length $$buffref >= 6; |
132
|
0
|
|
|
|
|
|
my ($version, $cmd, $reserved, $atype) = unpack 'C1C1C1C1', substr $$buffref, 0, 4; |
133
|
0
|
0
|
0
|
|
|
|
die "unknown command $cmd" unless $cmd > 0 && $cmd < 4; |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
substr $$buffref, 0, 3, ''; |
136
|
0
|
|
|
|
|
|
my $addr = $self->extract_address($buffref); |
137
|
0
|
|
|
|
|
|
my $port = unpack 'n1', substr $$buffref, 0, 2, ''; |
138
|
0
|
|
|
|
|
|
warn "Addr $addr, port $port\n"; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
1; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
__END__ |