ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/AnyEvent-MP/MP/Transport.pm
Revision: 1.87
Committed: Sun Aug 28 15:38:42 2016 UTC (7 years, 10 months ago) by root
Branch: MAIN
CVS Tags: rel-2_02, rel-2_01, rel-2_0, HEAD
Changes since 1.86: +23 -5 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3 root 1.13 AnyEvent::MP::Transport - actual transport protocol handler
4 root 1.1
5     =head1 SYNOPSIS
6    
7     use AnyEvent::MP::Transport;
8    
9     =head1 DESCRIPTION
10    
11 root 1.43 This module implements (and documents) the actual transport protocol for
12     AEMP.
13 root 1.1
14 root 1.7 See the "PROTOCOL" section below if you want to write another client for
15     this protocol.
16 root 1.1
17     =head1 FUNCTIONS/METHODS
18    
19     =over 4
20    
21     =cut
22    
23     package AnyEvent::MP::Transport;
24    
25     use common::sense;
26    
27 root 1.27 use Scalar::Util ();
28     use List::Util ();
29 root 1.1 use MIME::Base64 ();
30 root 1.82
31 root 1.85 use Digest::SHA3 ();
32     use Digest::HMAC ();
33 root 1.19
34 root 1.82 use AnyEvent ();
35 root 1.1 use AnyEvent::Socket ();
36 root 1.27 use AnyEvent::Handle 4.92 ();
37 root 1.2
38 root 1.30 use AnyEvent::MP::Config ();
39    
40 root 1.55 our $PROTOCOL_VERSION = 1;
41 root 1.1
42 root 1.75 our @HOOK_GREET; # called at connect/accept time
43     our @HOOK_GREETED; # called at greeting1 time
44     our @HOOK_CONNECT; # called at data phase
45     our @HOOK_DESTROY; # called at destroy time
46 root 1.59 our %HOOK_PROTOCOL = (
47     "aemp-dataconn" => sub {
48     require AnyEvent::MP::DataConn;
49     &AnyEvent::MP::DataConn::_inject;
50     },
51     );
52 root 1.52
53 root 1.75 =item $listener = mp_server $host, $port, <constructor-args>
54 root 1.1
55     Creates a listener on the given host/port using
56     C<AnyEvent::Socket::tcp_server>.
57    
58     See C<new>, below, for constructor arguments.
59    
60 root 1.10 Defaults for peerhost, peerport and fh are provided.
61 root 1.1
62     =cut
63    
64 root 1.46 sub mp_server($$;%) {
65     my ($host, $port, %arg) = @_;
66 root 1.1
67     AnyEvent::Socket::tcp_server $host, $port, sub {
68     my ($fh, $host, $port) = @_;
69    
70 root 1.39 my $tp = new AnyEvent::MP::Transport
71 root 1.1 fh => $fh,
72     peerhost => $host,
73     peerport => $port,
74 root 1.46 %arg,
75 root 1.39 ;
76     $tp->{keepalive} = $tp;
77 root 1.46 }, delete $arg{prepare}
78 root 1.1 }
79    
80 root 1.2 =item $guard = mp_connect $host, $port, <constructor-args>, $cb->($transport)
81    
82     =cut
83    
84     sub mp_connect {
85 root 1.31 my $release = pop;
86 root 1.2 my ($host, $port, @args) = @_;
87    
88 root 1.51 new AnyEvent::MP::Transport
89     connect => [$host, $port],
90 root 1.52 peerhost => $host,
91     peerport => $port,
92 root 1.51 release => $release,
93     @args,
94     ;
95 root 1.2 }
96    
97 root 1.1 =item new AnyEvent::MP::Transport
98    
99 root 1.75 Create a new transport - usually used via C<mp_server> or C<mp_connect>
100     instead.
101    
102 root 1.1 # immediately starts negotiation
103     my $transport = new AnyEvent::MP::Transport
104 root 1.2 # mandatory
105 root 1.75 fh => $filehandle,
106     local_id => $identifier,
107     on_recv => sub { receive-callback },
108     on_error => sub { error-callback },
109 root 1.1
110     # optional
111 root 1.75 on_greet => sub { before sending greeting },
112     on_greeted => sub { after receiving greeting },
113 root 1.1 on_connect => sub { successful-connect-callback },
114 root 1.75 greeting => { key => value },
115 root 1.1
116     # tls support
117 root 1.75 tls_ctx => AnyEvent::TLS,
118     peername => $peername, # for verification
119 root 1.1 ;
120    
121     =cut
122    
123 root 1.85 sub hmac_sha3_512_hex($$) {
124     Digest::HMAC::hmac_hex $_[1], $_[0], \&Digest::SHA3::sha3_512, 72
125     }
126    
127 root 1.1 sub new {
128     my ($class, %arg) = @_;
129    
130     my $self = bless \%arg, $class;
131    
132     {
133     Scalar::Util::weaken (my $self = $self);
134    
135 root 1.50 my $config = $AnyEvent::MP::Kernel::CONFIG;
136 root 1.30
137 root 1.50 my $timeout = $config->{monitor_timeout};
138 root 1.64 my $lframing = $config->{framing_format};
139 root 1.50 my $auth_snd = $config->{auth_offer};
140     my $auth_rcv = $config->{auth_accept};
141 root 1.31
142 root 1.42 $self->{secret} = $config->{secret}
143     unless exists $self->{secret};
144 root 1.2
145 root 1.42 my $secret = $self->{secret};
146 root 1.19
147 root 1.30 if (exists $config->{cert}) {
148 root 1.42 $self->{tls_ctx} = {
149 root 1.19 sslv2 => 0,
150     sslv3 => 0,
151     tlsv1 => 1,
152     verify => 1,
153 root 1.30 cert => $config->{cert},
154     ca_cert => $config->{cert},
155 root 1.19 verify_require_client_cert => 1,
156     };
157     }
158    
159 root 1.1 $self->{hdl} = new AnyEvent::Handle
160 root 1.52 +($self->{fh} ? (fh => $self->{fh}) : (connect => $self->{connect})),
161 root 1.63 autocork => $config->{autocork},
162     no_delay => exists $config->{nodelay} ? $config->{nodelay} : 1,
163 root 1.48 keepalive => 1,
164     on_error => sub {
165 root 1.1 $self->error ($_[2]);
166     },
167 root 1.49 rtimeout => $timeout,
168 root 1.1 ;
169    
170 root 1.52 my $greeting_kv = $self->{local_greeting} ||= {};
171 root 1.24
172 root 1.42 $greeting_kv->{tls} = "1.0" if $self->{tls_ctx};
173 root 1.75 $greeting_kv->{provider} = "AE-$AnyEvent::MP::Config::VERSION";
174 root 1.7 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport};
175 root 1.23
176 root 1.58 my $protocol = $self->{protocol} || "aemp";
177    
178 root 1.52 # can modify greeting_kv
179 root 1.75 $_->($self) for $protocol eq "aemp" ? @HOOK_GREET : ();
180     (delete $self->{on_greet})->($self)
181     if exists $self->{on_greet};
182 root 1.52
183 root 1.1 # send greeting
184 root 1.58 my $lgreeting1 = "$protocol;$PROTOCOL_VERSION"
185 root 1.52 . ";$AnyEvent::MP::Kernel::NODE"
186 root 1.50 . ";" . (join ",", @$auth_rcv)
187     . ";" . (join ",", @$lframing)
188 root 1.7 . (join "", map ";$_=$greeting_kv->{$_}", keys %$greeting_kv);
189 root 1.12
190 root 1.31 my $lgreeting2 = MIME::Base64::encode_base64 AnyEvent::MP::Kernel::nonce (66), "";
191 root 1.1
192 root 1.7 $self->{hdl}->push_write ("$lgreeting1\012$lgreeting2\012");
193 root 1.72 return unless $self;
194 root 1.1
195     # expect greeting
196 root 1.12 $self->{hdl}->rbuf_max (4 * 1024);
197 root 1.1 $self->{hdl}->push_read (line => sub {
198 root 1.7 my $rgreeting1 = $_[1];
199 root 1.1
200 root 1.26 my ($aemp, $version, $rnode, $auths, $framings, @kv) = split /;/, $rgreeting1;
201 root 1.1
202 root 1.53 $self->{remote_node} = $rnode;
203    
204     $self->{remote_greeting} = {
205     map /^([^=]+)(?:=(.*))?/ ? ($1 => $2) : (),
206     @kv
207     };
208    
209 root 1.60 # maybe upgrade the protocol
210     if ($protocol eq "aemp" and $aemp =~ /^aemp-\w+$/) {
211     # maybe check for existence of the protocol handler?
212     $self->{protocol} = $protocol = $aemp;
213     }
214    
215 root 1.75 $_->($self) for $protocol eq "aemp" ? @HOOK_GREETED : ();
216     (delete $self->{on_greeted})->($self)
217     if exists $self->{on_greeted};
218 root 1.54
219 root 1.60 if ($aemp ne $protocol and $aemp ne "aemp") {
220 root 1.58 return $self->error ("unparsable greeting, expected '$protocol', got '$aemp'");
221 root 1.12 } elsif ($version != $PROTOCOL_VERSION) {
222     return $self->error ("version mismatch (we: $PROTOCOL_VERSION, they: $version)");
223 root 1.60 } elsif ($protocol eq "aemp") {
224     if ($rnode eq $AnyEvent::MP::Kernel::NODE) {
225     return $self->error ("I refuse to talk to myself");
226     } elsif ($AnyEvent::MP::Kernel::NODE{$rnode} && $AnyEvent::MP::Kernel::NODE{$rnode}{transport}) {
227     return $self->error ("$rnode already connected, not connecting again.");
228     }
229 root 1.1 }
230    
231 root 1.7 # read nonce
232     $self->{hdl}->push_read (line => sub {
233     my $rgreeting2 = $_[1];
234    
235 root 1.19 "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack?
236     or return $self->error ("authentication error, echo attack?");
237    
238 root 1.41 my $tls = $self->{tls_ctx} && 1 == int $self->{remote_greeting}{tls};
239    
240     my $s_auth;
241     for my $auth_ (split /,/, $auths) {
242 root 1.50 if (grep $auth_ eq $_, @$auth_snd and ($auth_ !~ /^tls_/ or $tls)) {
243 root 1.41 $s_auth = $auth_;
244     last;
245     }
246     }
247    
248     defined $s_auth
249     or return $self->error ("$auths: no common auth type supported");
250    
251     my $s_framing;
252     for my $framing_ (split /,/, $framings) {
253 root 1.50 if (grep $framing_ eq $_, @$lframing) {
254 root 1.41 $s_framing = $framing_;
255     last;
256     }
257     }
258    
259     defined $s_framing
260     or return $self->error ("$framings: no common framing method supported");
261    
262 root 1.19 my $lauth;
263    
264 root 1.41 if ($tls) {
265 root 1.8 $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept";
266     $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx});
267 root 1.66 return unless $self->{hdl}; # starttls might destruct us
268 root 1.41
269     $lauth =
270 root 1.85 $s_auth eq "tls_anon" ? ""
271     : $s_auth eq "tls_sha3_512" ? Digest::SHA3::sha3_512_hex "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012"
272 root 1.41 : return $self->error ("$s_auth: fatal, selected unsupported snd auth method");
273    
274 root 1.30 } elsif (length $secret) {
275 root 1.41 return $self->error ("$s_auth: fatal, selected unsupported snd auth method")
276 root 1.85 unless $s_auth eq "hmac_sha3_512"; # hardcoded atm.
277 root 1.41
278 root 1.85 $lauth = hmac_sha3_512_hex $secret, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012";
279 root 1.41
280 root 1.30 } else {
281     return $self->error ("unable to handshake TLS and no shared secret configured");
282 root 1.8 }
283 root 1.2
284 root 1.7 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012");
285 root 1.72 return unless $self;
286 root 1.2
287 root 1.19 # read the authentication response
288 root 1.7 $self->{hdl}->push_read (line => sub {
289     my ($hdl, $rline) = @_;
290 root 1.2
291 root 1.7 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline;
292 root 1.1
293 root 1.19 my $rauth =
294 root 1.85 $auth_method eq "hmac_sha3_512" ? hmac_sha3_512_hex $secret, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012"
295     : $auth_method eq "cleartext" ? unpack "H*", $secret
296     : $auth_method eq "tls_anon" ? ($tls ? "" : "\012\012") # \012\012 never matches
297     : $auth_method eq "tls_sha3_512" ? ($tls ? Digest::SHA3::sha3_512_hex "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" : "\012\012")
298 root 1.41 : return $self->error ("$auth_method: fatal, selected unsupported rcv auth method");
299 root 1.19
300 root 1.7 if ($rauth2 ne $rauth) {
301     return $self->error ("authentication failure/shared secret mismatch");
302     }
303 root 1.1
304 root 1.79 $self->{r_framing} = $r_framing;
305 root 1.7 $self->{s_framing} = $s_framing;
306 root 1.2
307 root 1.7 $hdl->rbuf_max (undef);
308 root 1.1
309 root 1.49 # we rely on TCP retransmit timeouts and keepalives
310     $self->{hdl}->rtimeout (undef);
311    
312     $self->{remote_greeting}{untrusted} = 1
313     if $auth_method eq "tls_anon";
314 root 1.24
315 root 1.64 if ($protocol eq "aemp" and $self->{hdl}) {
316 root 1.77 # listener-less nodes need to continuously probe
317 root 1.78 # unless (@$AnyEvent::MP::Kernel::BINDS) {
318     # $self->{hdl}->wtimeout ($timeout);
319     # $self->{hdl}->on_wtimeout (sub { $self->{send}->([]) });
320     # }
321 root 1.58
322     # receive handling
323 root 1.79 $self->set_snd_framing;
324     $self->set_rcv_framing;
325 root 1.58 }
326 root 1.67
327     $self->connected;
328 root 1.7 });
329 root 1.1 });
330     });
331     }
332    
333     $self
334     }
335    
336 root 1.79 sub set_snd_framing {
337     my ($self) = @_;
338    
339     my $framing = $self->{s_framing};
340     my $hdl = $self->{hdl};
341     my $push_write = $hdl->can ("push_write");
342    
343 root 1.87 if ($framing eq "cbor") {
344     require CBOR::XS;
345 root 1.79 $self->{send} = sub {
346 root 1.87 $push_write->($hdl, CBOR::XS::encode_cbor ($_[0]));
347     };
348     } elsif ($framing eq "json") {
349     require JSON::XS;
350     $self->{send} = sub {
351     $push_write->($hdl, JSON::XS::encode_json ($_[0]));
352 root 1.79 };
353     } else {
354     $self->{send} = sub {
355     $push_write->($hdl, $framing => $_[0]);
356     };
357     }
358     }
359    
360     sub set_rcv_framing {
361     my ($self) = @_;
362    
363     my $node = $self->{remote_node};
364     my $framing = $self->{r_framing};
365     my $hdl = $self->{hdl};
366     my $push_read = $hdl->can ("push_read");
367    
368 root 1.87 if ($framing eq "cbor") {
369     require CBOR::XS;
370     my $coder = CBOR::XS->new;
371    
372     $hdl->on_read (sub {
373     $AnyEvent::MP::Kernel::SRCNODE = $node;
374    
375     AnyEvent::MP::Kernel::_inject (@$_)
376     for $coder->incr_parse_multiple ($_[0]{rbuf});
377    
378     ()
379     });
380     } elsif ($framing eq "json") {
381     require JSON::XS;
382 root 1.79 my $coder = JSON::XS->new->utf8;
383    
384     $hdl->on_read (sub {
385     $AnyEvent::MP::Kernel::SRCNODE = $node;
386    
387     AnyEvent::MP::Kernel::_inject (@$_)
388     for $coder->incr_parse (delete $_[0]{rbuf});
389    
390     ()
391     });
392     } else {
393     my $rmsg; $rmsg = $self->{rmsg} = sub {
394     $push_read->($_[0], $framing => $rmsg);
395    
396     $AnyEvent::MP::Kernel::SRCNODE = $node;
397     AnyEvent::MP::Kernel::_inject (@{ $_[1] });
398     };
399     eval {
400     $push_read->($hdl, $framing => $rmsg);
401     };
402     Scalar::Util::weaken $rmsg;
403     return $self->error ("$framing: unusable remote framing")
404     if $@;
405     }
406     }
407    
408 root 1.1 sub error {
409     my ($self, $msg) = @_;
410    
411 root 1.39 delete $self->{keepalive};
412    
413 root 1.58 if ($self->{protocol}) {
414 root 1.59 $HOOK_PROTOCOL{$self->{protocol}}->($self, $msg);
415 root 1.58 } else {
416 root 1.84 AE::log 9 => "$self->{peerhost}:$self->{peerport} disconnected - $msg.";
417 root 1.39
418 root 1.58 $self->{node}->transport_error (transport_error => $self->{node}{id}, $msg)
419     if $self->{node} && $self->{node}{transport} == $self;
420     }
421 root 1.31
422     (delete $self->{release})->()
423     if exists $self->{release};
424    
425 root 1.4 $self->destroy;
426 root 1.1 }
427    
428 root 1.2 sub connected {
429     my ($self) = @_;
430    
431 root 1.39 delete $self->{keepalive};
432    
433 root 1.58 if ($self->{protocol}) {
434 root 1.59 $self->{hdl}->on_error (undef);
435     $HOOK_PROTOCOL{$self->{protocol}}->($self, undef);
436 root 1.58 } else {
437 root 1.81 AE::log 9 => "$self->{peerhost}:$self->{peerport} connected as $self->{remote_node}.";
438 root 1.58
439     my $node = AnyEvent::MP::Kernel::add_node ($self->{remote_node});
440     Scalar::Util::weaken ($self->{node} = $node);
441     $node->transport_connect ($self);
442 root 1.39
443 root 1.75 $_->($self) for @HOOK_CONNECT;
444 root 1.58 }
445 root 1.61
446     (delete $self->{release})->()
447     if exists $self->{release};
448 root 1.75
449     (delete $self->{on_connect})->($self)
450     if exists $self->{on_connect};
451 root 1.2 }
452    
453 root 1.1 sub destroy {
454     my ($self) = @_;
455    
456 root 1.42 (delete $self->{release})->()
457     if exists $self->{release};
458    
459 root 1.2 $self->{hdl}->destroy
460     if $self->{hdl};
461 root 1.52
462 root 1.75 (delete $self->{on_destroy})->($self)
463     if exists $self->{on_destroy};
464 root 1.59 $_->($self) for $self->{protocol} ? () : @HOOK_DESTROY;
465 root 1.74
466     $self->{protocol} = "destroyed"; # to keep hooks from invoked twice.
467 root 1.1 }
468    
469     sub DESTROY {
470     my ($self) = @_;
471    
472     $self->destroy;
473     }
474    
475     =back
476    
477 root 1.7 =head1 PROTOCOL
478    
479 root 1.59 The AEMP protocol is comparatively simple, and consists of three phases
480     which are symmetrical for both sides: greeting (followed by optionally
481     switching to TLS mode), authentication and packet exchange.
482 root 1.7
483 root 1.43 The protocol is designed to allow both full-text and binary streams.
484 root 1.7
485     The greeting consists of two text lines that are ended by either an ASCII
486     CR LF pair, or a single ASCII LF (recommended).
487    
488     =head2 GREETING
489    
490 root 1.15 All the lines until after authentication must not exceed 4kb in length,
491 root 1.43 including line delimiter. Afterwards there is no limit on the packet size
492     that can be received.
493 root 1.15
494     =head3 First Greeting Line
495 root 1.12
496 root 1.16 Example:
497    
498 root 1.87 aemp;0;rain;tls_sha3_512,hmac_sha3_512,tls_anon,cleartext;cbor,json,storable;timeout=12;peeraddr=10.0.0.1:48082
499 root 1.16
500     The first line contains strings separated (not ended) by C<;>
501 root 1.43 characters. The first five strings are fixed by the protocol, the
502 root 1.16 remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;>
503 root 1.43 characters themselves (when escaping is needed, use C<%3b> to represent
504     C<;> and C<%25> to represent C<%>)-
505 root 1.16
506 root 1.12 The fixed strings are:
507 root 1.7
508     =over 4
509    
510 root 1.18 =item protocol identification
511 root 1.7
512 root 1.43 The constant C<aemp> to identify this protocol.
513 root 1.7
514     =item protocol version
515    
516 root 1.55 The protocol version supported by this end, currently C<1>. If the
517 root 1.12 versions don't match then no communication is possible. Minor extensions
518 root 1.18 are supposed to be handled through additional key-value pairs.
519 root 1.7
520 root 1.43 =item the node ID
521 root 1.7
522 root 1.57 This is the node ID of the connecting node.
523 root 1.7
524     =item the acceptable authentication methods
525    
526     A comma-separated list of authentication methods supported by the
527     node. Note that AnyEvent::MP supports a C<hex_secret> authentication
528 root 1.43 method that accepts a clear-text password (hex-encoded), but will not use
529     this authentication method itself.
530 root 1.7
531 root 1.43 The receiving side should choose the first authentication method it
532     supports.
533 root 1.7
534     =item the acceptable framing formats
535    
536 root 1.43 A comma-separated list of packet encoding/framing formats understood. The
537 root 1.7 receiving side should choose the first framing format it supports for
538     sending packets (which might be different from the format it has to accept).
539    
540 root 1.10 =back
541 root 1.8
542     The remaining arguments are C<KEY=VALUE> pairs. The following key-value
543     pairs are known at this time:
544    
545     =over 4
546    
547     =item provider=<module-version>
548    
549     The software provider for this implementation. For AnyEvent::MP, this is
550     C<AE-0.0> or whatever version it currently is at.
551    
552     =item peeraddr=<host>:<port>
553    
554 root 1.39 The peer address (socket address of the other side) as seen locally.
555 root 1.8
556     =item tls=<major>.<minor>
557    
558     Indicates that the other side supports TLS (version should be 1.0) and
559     wishes to do a TLS handshake.
560    
561 root 1.76 =item nproto=<major>.<fractional>
562    
563     Informs the other side of the node protocol implemented by this
564     node. Major version mismatches are fatal. If this key is missing, then it
565     is assumed that the node doesn't support the node protocol.
566    
567     The node protocol is currently undocumented, but includes port
568     monitoring, spawning and informational requests.
569    
570     =item gproto=<major>.<fractional>
571    
572     Informs the other side of the global protocol implemented by this
573     node. Major version mismatches are fatal. If this key is missing, then it
574     is assumed that the node doesn't support the global protocol.
575    
576     The global protocol is currently undocumented, but includes node address
577     lookup and shared database operations.
578    
579 root 1.8 =back
580    
581 root 1.15 =head3 Second Greeting Line
582    
583 root 1.8 After this greeting line there will be a second line containing a
584     cryptographic nonce, i.e. random data of high quality. To keep the
585     protocol text-only, these are usually 32 base64-encoded octets, but
586     it could be anything that doesn't contain any ASCII CR or ASCII LF
587     characters.
588    
589 root 1.14 I<< The two nonces B<must> be different, and an aemp implementation
590     B<must> check and fail when they are identical >>.
591    
592 root 1.43 Example of a nonce line (yes, it's random-looking because it is random
593     data):
594 root 1.8
595 root 1.43 2XYhdG7/O6epFa4wuP0ujAEx1rXYWRcOypjUYK7eF6yWAQr7gwIN9m/2+mVvBrTPXz5GJDgfGm9d8QRABAbmAP/s
596 root 1.8
597     =head2 TLS handshake
598    
599 root 1.14 I<< If, after the handshake, both sides indicate interest in TLS, then the
600 root 1.43 connection B<must> use TLS, or fail to continue. >>
601 root 1.8
602     Both sides compare their nonces, and the side who sent the lower nonce
603     value ("string" comparison on the raw octet values) becomes the client,
604     and the one with the higher nonce the server.
605    
606     =head2 AUTHENTICATION PHASE
607    
608     After the greeting is received (and the optional TLS handshake),
609     the authentication phase begins, which consists of sending a single
610     C<;>-separated line with three fixed strings and any number of
611     C<KEY=VALUE> pairs.
612    
613     The three fixed strings are:
614    
615     =over 4
616    
617     =item the authentication method chosen
618    
619     This must be one of the methods offered by the other side in the greeting.
620    
621 root 1.41 Note that all methods starting with C<tls_> are only valid I<iff> TLS was
622     successfully handshaked (and to be secure the implementation must enforce
623     this).
624    
625 root 1.13 The currently supported authentication methods are:
626    
627     =over 4
628    
629     =item cleartext
630    
631     This is simply the shared secret, lowercase-hex-encoded. This method is of
632 root 1.43 course very insecure if TLS is not used (and not completely secure even
633     if TLS is used), which is why this module will accept, but not generate,
634     cleartext auth replies.
635 root 1.13
636 root 1.85 =item hmac_sha3_512
637 root 1.13
638 root 1.85 This method uses a SHA-3/512 HMAC with 576 bit blocksize and 512 bit hash,
639     and requires a shared secret. It is the preferred auth method when a
640     shared secret is available.
641 root 1.13
642 root 1.85 The secret is used to generate the "local auth reply", by taking the
643     two local greeting lines and the two remote greeting lines (without
644 root 1.13 line endings), appending \012 to all of them, concatenating them and
645 root 1.85 calculating the HMAC with the key:
646 root 1.13
647 root 1.85 lauth = HMAC_SHA3_512 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012"
648 root 1.13
649     This authentication token is then lowercase-hex-encoded and sent to the
650     other side.
651    
652     Then the remote auth reply is generated using the same method, but local
653     and remote greeting lines swapped:
654    
655 root 1.85 rauth = HMAC_SHA3_512 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
656 root 1.13
657     This is the token that is expected from the other side.
658    
659 root 1.85 =item hmac_md6_64_256 [obsolete, not supported]
660    
661     This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash, and
662     requires a shared secret. It is similar to C<hmac_sha3_512>, but uses
663     MD6 instead of SHA-3 and instead of using the secret directly, it uses
664     MD6(secret) as HMAC key.
665    
666 root 1.41 =item tls_anon
667 root 1.19
668 root 1.43 This type is only valid I<iff> TLS was enabled and the TLS handshake
669 root 1.19 was successful. It has no authentication data, as the server/client
670     certificate was successfully verified.
671    
672 root 1.43 This authentication type is somewhat insecure, as it allows a
673     man-in-the-middle attacker to change some of the connection parameters
674     (such as the framing format), although there is no known attack that
675     exploits this in a way that is worse than just denying the service.
676 root 1.41
677 root 1.43 By default, this implementation accepts but never generates this auth
678     reply.
679 root 1.41
680 root 1.85 =item tls_sha3_512
681 root 1.41
682 root 1.43 This type is only valid I<iff> TLS was enabled and the TLS handshake was
683     successful.
684 root 1.41
685     This authentication type simply calculates:
686    
687 root 1.85 lauth = SHA3_512 "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
688 root 1.41
689     and lowercase-hex encodes the result and sends it as authentication
690     data. No shared secret is required (authentication is done by TLS). The
691 root 1.43 checksum exists only to make tinkering with the greeting hard.
692 root 1.19
693 root 1.85 =item tls_md6_64_256 [deprecated, unsupported]
694    
695     Same as C<tls_sha3_512>, except MD6 is used.
696    
697 root 1.13 =back
698    
699 root 1.8 =item the authentication data
700    
701 root 1.13 The authentication data itself, usually base64 or hex-encoded data, see
702     above.
703 root 1.8
704     =item the framing protocol chosen
705    
706     This must be one of the framing protocols offered by the other side in the
707 root 1.43 greeting. Each side must accept the choice of the other side, and generate
708     packets in the format it chose itself.
709 root 1.8
710     =back
711    
712 root 1.16 Example of an authentication reply:
713 root 1.9
714 root 1.13 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json
715 root 1.9
716 root 1.8 =head2 DATA PHASE
717    
718     After this, packets get exchanged using the chosen framing protocol. It is
719     quite possible that both sides use a different framing protocol.
720    
721 root 1.16 =head2 FULL EXAMPLE
722    
723 root 1.17 This is an actual protocol dump of a handshake, followed by a single data
724 root 1.16 packet. The greater than/less than lines indicate the direction of the
725     transfer only.
726    
727 root 1.43 > aemp;0;anon/57Cs1CggVJjzYaQp13XXg4;tls_md6_64_256,hmac_md6_64_256,tls_anon,cleartext;json,storable;provider=AE-0.8;timeout=12;peeraddr=10.0.0.17:4040
728     > yLgdG1ov/02shVkVQer3wzeuywZK+oraTdEQBmIqWHaegxSGDG4g+HqogLQbvdypFOsoDWJ1Sh4ImV4DMhvUBwTK
729    
730     < aemp;0;ruth;tls_md6_64_256,hmac_md6_64_256,tls_anon,cleartext;json,storable;provider=AE-0.8;timeout=12;peeraddr=10.0.0.1:37108
731     < +xMQXP8ElfNmuvEhsmcp+s2wCJOuQAsPxSg3d2Ewhs6gBnJz+ypVdWJ/wAVrXqlIJfLeVS/CBy4gEGkyWHSuVb1L
732    
733     > hmac_md6_64_256;5ad913855742ae5a03a5aeb7eafa4c78629de136bed6acd73eea36c9e98df44a;json
734    
735     < hmac_md6_64_256;84cd590976f794914c2ca26dac3a207a57a6798b9171289c114de07cf0c20401;json
736     < ["","AnyEvent::MP::_spawn","57Cs1CggVJjzYaQp13XXg4.c","AnyEvent::MP::Global::connect",0,"anon/57Cs1CggVJjzYaQp13XXg4"]
737     ...
738    
739     The shared secret in use was C<8ugxrtw6H5tKnfPWfaSr4HGhE8MoJXmzTT1BWq7sLutNcD0IbXprQlZjIbl7MBKoeklG3IEfY9GlJthC0pENzk>.
740 root 1.16
741 root 1.65 =head2 SIMPLE HANDSHAKE FOR NON-PERL NODES
742    
743     Implementing the full set of options for handshaking can be a daunting
744     task.
745    
746     If security is not so important (because you only connect locally and
747     control the host, a common case), and you want to interface with an AEMP
748     node from another programming language, then you can also implement a
749     simplified handshake.
750    
751     For example, in a simple implementation you could decide to simply not
752     check the authenticity of the other side and use cleartext authentication
753     yourself. The the handshake is as simple as sending three lines of text,
754     reading three lines of text, and then you can exchange JSON-formatted
755     messages:
756    
757 root 1.85 aemp;1;<nodename>;hmac_sha3_512;json
758 root 1.65 <nonce>
759     cleartext;<hexencoded secret>;json
760    
761     The nodename should be unique within the network, preferably unique with
762     every connection, the <nonce> could be empty or some random data, and the
763     hexencoded secret would be the shared secret, in lowercase hex (e.g. if
764     the secret is "geheim", the hex-encoded version would be "67656865696d").
765    
766     Note that apart from the low-level handshake and framing protocol, there
767     is a high-level protocol, e.g. for monitoring, building the mesh or
768     spawning. All these messages are sent to the node port (the empty string)
769     and can safely be ignored if you do not need the relevant functionality.
770    
771     =head3 USEFUL HINTS
772    
773     Since taking part in the global protocol to find port groups is
774     nontrivial, hardcoding port names should be considered as well, i.e. the
775     non-Perl node could simply listen to messages for a few well-known ports.
776    
777     Alternatively, the non-Perl node could call a (already loaded) function
778     in the Perl node by sending it a special message:
779    
780     ["", "Some::Function::name", "myownport", 1, 2, 3]
781    
782     This would call the function C<Some::Function::name> with the string
783     C<myownport> and some additional arguments.
784    
785 root 1.49 =head2 MONITORING
786    
787     Monitoring the connection itself is transport-specific. For TCP, all
788     connection monitoring is currently left to TCP retransmit time-outs
789     on a busy link, and TCP keepalive (which should be enabled) for idle
790     connections.
791    
792     This is not sufficient for listener-less nodes, however: they need
793     to regularly send data (30 seconds, or the monitoring interval, is
794     recommended), so TCP actively probes.
795    
796 elmex 1.73 Future implementations of AnyEvent::MP::Transport might query the kernel TCP
797 root 1.49 buffer after a write timeout occurs, and if it is non-empty, shut down the
798     connections, but this is an area of future research :)
799    
800     =head2 NODE PROTOCOL
801    
802     The transport simply transfers messages, but to implement a full node, a
803     special node port must exist that understands a number of requests.
804    
805     If you are interested in implementing this, drop us a note so we finish
806     the documentation.
807    
808 root 1.1 =head1 SEE ALSO
809    
810 root 1.29 L<AnyEvent::MP>.
811 root 1.1
812     =head1 AUTHOR
813    
814     Marc Lehmann <schmorp@schmorp.de>
815     http://home.schmorp.de/
816    
817     =cut
818    
819     1
820