… | |
… | |
34 | use Digest::HMAC_MD6 (); |
34 | use Digest::HMAC_MD6 (); |
35 | |
35 | |
36 | use AE (); |
36 | use AE (); |
37 | use AnyEvent::Socket (); |
37 | use AnyEvent::Socket (); |
38 | use AnyEvent::Handle 4.92 (); |
38 | use AnyEvent::Handle 4.92 (); |
|
|
39 | |
|
|
40 | use AnyEvent::MP::Config (); |
39 | |
41 | |
40 | our $PROTOCOL_VERSION = 0; |
42 | our $PROTOCOL_VERSION = 0; |
41 | |
43 | |
42 | =item $listener = mp_listener $host, $port, <constructor-args>, $cb->($transport) |
44 | =item $listener = mp_listener $host, $port, <constructor-args>, $cb->($transport) |
43 | |
45 | |
… | |
… | |
98 | local_id => $identifier, |
100 | local_id => $identifier, |
99 | on_recv => sub { receive-callback }, |
101 | on_recv => sub { receive-callback }, |
100 | on_error => sub { error-callback }, |
102 | on_error => sub { error-callback }, |
101 | |
103 | |
102 | # optional |
104 | # optional |
103 | secret => "shared secret", |
|
|
104 | on_eof => sub { clean-close-callback }, |
105 | on_eof => sub { clean-close-callback }, |
105 | on_connect => sub { successful-connect-callback }, |
106 | on_connect => sub { successful-connect-callback }, |
106 | greeting => { key => value }, |
107 | greeting => { key => value }, |
107 | |
108 | |
108 | # tls support |
109 | # tls support |
… | |
… | |
129 | $self->{queue} = []; |
130 | $self->{queue} = []; |
130 | |
131 | |
131 | { |
132 | { |
132 | Scalar::Util::weaken (my $self = $self); |
133 | Scalar::Util::weaken (my $self = $self); |
133 | |
134 | |
134 | $arg{secret} = AnyEvent::MP::Base::default_secret () |
135 | my $config = AnyEvent::MP::Config::node_config; |
|
|
136 | |
|
|
137 | $arg{secret} = $config->{secret} |
135 | unless exists $arg{secret}; |
138 | unless exists $arg{secret}; |
136 | |
139 | |
137 | $arg{timeout} = 30 |
140 | $arg{timeout} = 30 |
138 | unless exists $arg{timeout}; |
141 | unless exists $arg{timeout}; |
139 | |
142 | |
140 | $arg{timeout} = 1 + LATENCY |
143 | $arg{timeout} = 1 + LATENCY |
141 | if $arg{timeout} < 1 + LATENCY; |
144 | if $arg{timeout} < 1 + LATENCY; |
142 | |
145 | |
143 | my $secret = $arg{secret}; |
146 | my $secret = $arg{secret}; |
144 | |
147 | |
145 | if ($secret =~ /-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----.*-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----/s) { |
148 | if (exists $config->{cert}) { |
146 | # assume TLS mode |
|
|
147 | $arg{tls_ctx} = { |
149 | $arg{tls_ctx} = { |
148 | sslv2 => 0, |
150 | sslv2 => 0, |
149 | sslv3 => 0, |
151 | sslv3 => 0, |
150 | tlsv1 => 1, |
152 | tlsv1 => 1, |
151 | verify => 1, |
153 | verify => 1, |
152 | cert => $secret, |
154 | cert => $config->{cert}, |
153 | ca_cert => $secret, |
155 | ca_cert => $config->{cert}, |
154 | verify_require_client_cert => 1, |
156 | verify_require_client_cert => 1, |
155 | }; |
157 | }; |
156 | } |
158 | } |
157 | |
159 | |
158 | $self->{hdl} = new AnyEvent::Handle |
160 | $self->{hdl} = new AnyEvent::Handle |
… | |
… | |
235 | my $rgreeting2 = $_[1]; |
237 | my $rgreeting2 = $_[1]; |
236 | |
238 | |
237 | "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack? |
239 | "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack? |
238 | or return $self->error ("authentication error, echo attack?"); |
240 | or return $self->error ("authentication error, echo attack?"); |
239 | |
241 | |
240 | my $key = Digest::MD6::md6 $secret; |
242 | my $key; |
241 | my $lauth; |
243 | my $lauth; |
242 | |
244 | |
243 | if ($self->{tls_ctx} and 1 == int $self->{remote_greeting}{tls}) { |
245 | if ($self->{tls_ctx} and 1 == int $self->{remote_greeting}{tls}) { |
244 | $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; |
246 | $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; |
245 | $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); |
247 | $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); |
246 | $s_auth = "tls"; |
248 | $s_auth = "tls"; |
247 | $lauth = ""; |
249 | $lauth = ""; |
248 | } else { |
250 | } elsif (length $secret) { |
|
|
251 | $key = Digest::MD6::md6 $secret; |
249 | # we currently only support hmac_md6_64_256 |
252 | # we currently only support hmac_md6_64_256 |
250 | $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256; |
253 | $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256; |
|
|
254 | } else { |
|
|
255 | return $self->error ("unable to handshake TLS and no shared secret configured"); |
251 | } |
256 | } |
252 | |
257 | |
253 | $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012"); |
258 | $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012"); |
254 | |
259 | |
255 | # read the authentication response |
260 | # read the authentication response |