ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP/Transport.pm
(Generate patch)

Comparing AnyEvent-MP/MP/Transport.pm (file contents):
Revision 1.11 by root, Mon Aug 3 15:40:53 2009 UTC vs.
Revision 1.18 by root, Tue Aug 4 18:33:30 2009 UTC

1=head1 NAME 1=head1 NAME
2 2
3AnyEvent::MP::Transport - actual transport protocol 3AnyEvent::MP::Transport - actual transport protocol handler
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use AnyEvent::MP::Transport; 7 use AnyEvent::MP::Transport;
8 8
9=head1 DESCRIPTION 9=head1 DESCRIPTION
10 10
11This is the superclass for MP transports, most of which is considered an 11This implements the actual transport protocol for MP (it represents a
12implementation detail. 12single link), most of which is considered an implementation detail.
13 13
14See the "PROTOCOL" section below if you want to write another client for 14See the "PROTOCOL" section below if you want to write another client for
15this protocol. 15this protocol.
16 16
17=head1 FUNCTIONS/METHODS 17=head1 FUNCTIONS/METHODS
111 111
112=cut 112=cut
113 113
114our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference 114our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference
115our @AUTH_SND = qw(hmac_md6_64_256); # auth types we send 115our @AUTH_SND = qw(hmac_md6_64_256); # auth types we send
116our @AUTH_RCV = (@AUTH_SND, qw(hex_secret)); # auth types we accept 116our @AUTH_RCV = (@AUTH_SND, qw(cleartext)); # auth types we accept
117 117
118#AnyEvent::Handle::register_write_type mp_record => sub { 118#AnyEvent::Handle::register_write_type mp_record => sub {
119#}; 119#};
120 120
121sub new { 121sub new {
141 $arg{secret} = AnyEvent::MP::Base::default_secret () 141 $arg{secret} = AnyEvent::MP::Base::default_secret ()
142 unless exists $arg{secret}; 142 unless exists $arg{secret};
143 143
144 $self->{hdl} = new AnyEvent::Handle 144 $self->{hdl} = new AnyEvent::Handle
145 fh => delete $arg{fh}, 145 fh => delete $arg{fh},
146 rbuf_max => 64 * 1024,
147 autocork => 1, 146 autocork => 1,
148 no_delay => 1, 147 no_delay => 1,
149 on_error => sub { 148 on_error => sub {
150 $self->error ($_[2]); 149 $self->error ($_[2]);
151 }, 150 },
158 if $arg{tls_ctx}; 157 if $arg{tls_ctx};
159 $greeting_kv->{provider} = "AE-$VERSION"; 158 $greeting_kv->{provider} = "AE-$VERSION";
160 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport}; 159 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport};
161 160
162 # send greeting 161 # send greeting
163 my $lgreeting1 = "aemp;$PROTOCOL_VERSION;$PROTOCOL_VERSION" # version, min 162 my $lgreeting1 = "aemp;$PROTOCOL_VERSION"
164 . ";$AnyEvent::MP::Base::UNIQ" 163 . ";$AnyEvent::MP::Base::UNIQ"
165 . ";$AnyEvent::MP::Base::NODE" 164 . ";$AnyEvent::MP::Base::NODE"
166 . ";" . (join ",", @AUTH_RCV) 165 . ";" . (join ",", @AUTH_RCV)
167 . ";" . (join ",", @FRAMINGS) 166 . ";" . (join ",", @FRAMINGS)
168 . (join "", map ";$_=$greeting_kv->{$_}", keys %$greeting_kv); 167 . (join "", map ";$_=$greeting_kv->{$_}", keys %$greeting_kv);
168
169 my $lgreeting2 = MIME::Base64::encode_base64 AnyEvent::MP::Base::nonce (33), ""; 169 my $lgreeting2 = MIME::Base64::encode_base64 AnyEvent::MP::Base::nonce (33), "";
170 170
171 $self->{hdl}->push_write ("$lgreeting1\012$lgreeting2\012"); 171 $self->{hdl}->push_write ("$lgreeting1\012$lgreeting2\012");
172 172
173 # expect greeting 173 # expect greeting
174 $self->{hdl}->rbuf_max (4 * 1024);
174 $self->{hdl}->push_read (line => sub { 175 $self->{hdl}->push_read (line => sub {
175 my $rgreeting1 = $_[1]; 176 my $rgreeting1 = $_[1];
176 177
177 my ($aemp, $version, $version_min, $uniq, $rnode, $auths, $framings, @kv) = split /;/, $rgreeting1; 178 my ($aemp, $version, $uniq, $rnode, $auths, $framings, @kv) = split /;/, $rgreeting1;
178 179
179 if ($aemp ne "aemp") { 180 if ($aemp ne "aemp") {
180 return $self->error ("unparsable greeting"); 181 return $self->error ("unparsable greeting");
181 } elsif ($version_min > $PROTOCOL_VERSION) { 182 } elsif ($version != $PROTOCOL_VERSION) {
182 return $self->error ("version mismatch (we: $PROTOCOL_VERSION, they: $version_min .. $version)"); 183 return $self->error ("version mismatch (we: $PROTOCOL_VERSION, they: $version)");
183 } 184 }
184 185
185 my $s_auth; 186 my $s_auth;
186 for my $auth_ (split /,/, $auths) { 187 for my $auth_ (split /,/, $auths) {
187 if (grep $auth_ eq $_, @AUTH_SND) { 188 if (grep $auth_ eq $_, @AUTH_SND) {
226 # auth 227 # auth
227 require Digest::MD6; 228 require Digest::MD6;
228 require Digest::HMAC_MD6; 229 require Digest::HMAC_MD6;
229 230
230 my $key = Digest::MD6::md6 ($secret); 231 my $key = Digest::MD6::md6 ($secret);
231 my $lauth = Digest::HMAC_MD6::hmac_md6_base64 ($key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256); 232 my $lauth = Digest::HMAC_MD6::hmac_md6_hex ($key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256);
232 233
233 my $rauth = 234 my $rauth =
234 $s_auth eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_base64 ($key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256) 235 $s_auth eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex ($key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256)
235 : $s_auth eq "hex_secret" ? unpack "H*", $secret 236 : $s_auth eq "cleartext" ? unpack "H*", $secret
236 : die; 237 : die;
237 238
238 $lauth ne $rauth # echo attack? 239 $lauth ne $rauth # echo attack?
239 or return $self->error ("authentication error"); 240 or return $self->error ("authentication error");
240 241
241 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012"); 242 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012");
242 243
243 $self->{hdl}->rbuf_max (64); # enough for 44 reply bytes or so 244 # reasd the authentication response
244 $self->{hdl}->push_read (line => sub { 245 $self->{hdl}->push_read (line => sub {
245 my ($hdl, $rline) = @_; 246 my ($hdl, $rline) = @_;
246 247
247 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline; 248 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline;
248 249
255 $hdl->rbuf_max (undef); 256 $hdl->rbuf_max (undef);
256 my $queue = delete $self->{queue}; # we are connected 257 my $queue = delete $self->{queue}; # we are connected
257 258
258 $self->connected; 259 $self->connected;
259 260
261 my $src_node = $self->{node};
262
260 $hdl->push_write ($self->{s_framing} => $_) 263 $hdl->push_write ($self->{s_framing} => $_)
261 for @$queue; 264 for @$queue;
262 265
263 my $rmsg; $rmsg = sub { 266 my $rmsg; $rmsg = sub {
264 $_[0]->push_read ($r_framing => $rmsg); 267 $_[0]->push_read ($r_framing => $rmsg);
265 268
269 local $AnyEvent::MP::Base::SRCNODE = $src_node;
266 AnyEvent::MP::Base::_inject ($_[1]); 270 AnyEvent::MP::Base::_inject (@{ $_[1] });
267 }; 271 };
268 $hdl->push_read ($r_framing => $rmsg); 272 $hdl->push_read ($r_framing => $rmsg);
269 }); 273 });
270 }); 274 });
271 }); 275 });
276 280
277sub error { 281sub error {
278 my ($self, $msg) = @_; 282 my ($self, $msg) = @_;
279 283
280 if ($self->{node} && $self->{node}{transport} == $self) { 284 if ($self->{node} && $self->{node}{transport} == $self) {
285 $self->{node}->fail (transport_error => $msg);
281 $self->{node}->clr_transport; 286 $self->{node}->clr_transport;
282 } 287 }
283 $AnyEvent::MP::Base::WARN->("$self->{peerhost}:$self->{peerport}: $msg"); 288 $AnyEvent::MP::Base::WARN->("$self->{peerhost}:$self->{peerport}: $msg");
284 $self->destroy; 289 $self->destroy;
285} 290}
322The greeting consists of two text lines that are ended by either an ASCII 327The greeting consists of two text lines that are ended by either an ASCII
323CR LF pair, or a single ASCII LF (recommended). 328CR LF pair, or a single ASCII LF (recommended).
324 329
325=head2 GREETING 330=head2 GREETING
326 331
332All the lines until after authentication must not exceed 4kb in length,
333including delimiter. Afterwards there is no limit on the packet size that
334can be received.
335
336=head3 First Greeting Line
337
338Example:
339
340 aemp;0;fec.4a7720fc;127.0.0.1:1235,[::1]:1235;hmac_md6_64_256;json,storable;provider=AE-0.0
341
327The first line contains strings separated (not ended) by C<;> 342The first line contains strings separated (not ended) by C<;>
328characters. The first seven strings are fixed by the protocol, the 343characters. The first even ixtrings are fixed by the protocol, the
329remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;> 344remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;>
330characters themselves. 345characters themselves.
331 346
332The seven fixed strings are: 347The fixed strings are:
333 348
334=over 4 349=over 4
335 350
336=item C<aemp> 351=item protocol identification
337 352
338The constant C<aemp> to identify the protocol. 353The constant C<aemp> to identify the protocol.
339 354
340=item protocol version 355=item protocol version
341 356
342The (maximum) protocol version supported by this end, currently C<0>.
343
344=item minimum protocol version
345
346The minimum protocol version supported by this end, currently C<0>. 357The protocol version supported by this end, currently C<0>. If the
358versions don't match then no communication is possible. Minor extensions
359are supposed to be handled through additional key-value pairs.
347 360
348=item a token uniquely identifying the current node instance 361=item a token uniquely identifying the current node instance
349 362
350This is a string that must change between restarts. It usually contains 363This is a string that must change between restarts. It usually contains
351things like the current time, the (OS) process id or similar values, but 364things like the current time, the (OS) process id or similar values, but
392 405
393Indicates that the other side supports TLS (version should be 1.0) and 406Indicates that the other side supports TLS (version should be 1.0) and
394wishes to do a TLS handshake. 407wishes to do a TLS handshake.
395 408
396=back 409=back
410
411=head3 Second Greeting Line
397 412
398After this greeting line there will be a second line containing a 413After this greeting line there will be a second line containing a
399cryptographic nonce, i.e. random data of high quality. To keep the 414cryptographic nonce, i.e. random data of high quality. To keep the
400protocol text-only, these are usually 32 base64-encoded octets, but 415protocol text-only, these are usually 32 base64-encoded octets, but
401it could be anything that doesn't contain any ASCII CR or ASCII LF 416it could be anything that doesn't contain any ASCII CR or ASCII LF
402characters. 417characters.
403 418
404Example of the two lines of greeting: 419I<< The two nonces B<must> be different, and an aemp implementation
420B<must> check and fail when they are identical >>.
405 421
406 aemp;0;0;e7d.4a76f48f;10.0.0.1:4040;hmac_md6_64_256,hex_secret;json,storable;provider=AE-0.0;peeraddr=127.0.0.1:1235 422Example of a nonce line:
407 XntegV2Guvss0qNn7phCPnoU87xqxV+4Mqm/5y4iQm6a 423
424 p/I122ql7kJR8lumW3lXlXCeBnyDAvz8NQo3x5IFowE4
408 425
409=head2 TLS handshake 426=head2 TLS handshake
410 427
411If, after the handshake, both sides indicate interest in TLS, then the 428I<< If, after the handshake, both sides indicate interest in TLS, then the
412connection I<must> use TLS, or fail. 429connection B<must> use TLS, or fail.>>
413 430
414Both sides compare their nonces, and the side who sent the lower nonce 431Both sides compare their nonces, and the side who sent the lower nonce
415value ("string" comparison on the raw octet values) becomes the client, 432value ("string" comparison on the raw octet values) becomes the client,
416and the one with the higher nonce the server. 433and the one with the higher nonce the server.
417 434
428 445
429=item the authentication method chosen 446=item the authentication method chosen
430 447
431This must be one of the methods offered by the other side in the greeting. 448This must be one of the methods offered by the other side in the greeting.
432 449
450The currently supported authentication methods are:
451
452=over 4
453
454=item cleartext
455
456This is simply the shared secret, lowercase-hex-encoded. This method is of
457course very insecure, unless TLS is used, which is why this module will
458accept, but not generate, cleartext auth replies.
459
460=item hmac_md6_64_256
461
462This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash. First, the shared secret
463is hashed with MD6:
464
465 key = MD6 (secret)
466
467This secret is then used to generate the "local auth reply", by taking
468the two local greeting lines and the two remote greeting lines (without
469line endings), appending \012 to all of them, concatenating them and
470calculating the MD6 HMAC with the key.
471
472 lauth = HMAC_MD6 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012"
473
474This authentication token is then lowercase-hex-encoded and sent to the
475other side.
476
477Then the remote auth reply is generated using the same method, but local
478and remote greeting lines swapped:
479
480 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
481
482This is the token that is expected from the other side.
483
484=back
485
433=item the authentication data 486=item the authentication data
434 487
435The authentication data itself, usually base64 or hex-encoded data. 488The authentication data itself, usually base64 or hex-encoded data, see
489above.
436 490
437=item the framing protocol chosen 491=item the framing protocol chosen
438 492
439This must be one of the framing protocols offered by the other side in the 493This must be one of the framing protocols offered by the other side in the
440greeting. Each side must accept the choice of the other side. 494greeting. Each side must accept the choice of the other side.
441 495
442=back 496=back
443 497
444Example (the actual reply matching the previous example): 498Example of an authentication reply:
445 499
446 hmac_md6_64_256;wIlLedBY956UCGSISG9mBZRDTG8xUi73/sVse2DSQp0;json 500 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json
447 501
448=head2 DATA PHASE 502=head2 DATA PHASE
449 503
450After this, packets get exchanged using the chosen framing protocol. It is 504After this, packets get exchanged using the chosen framing protocol. It is
451quite possible that both sides use a different framing protocol. 505quite possible that both sides use a different framing protocol.
452 506
507=head2 FULL EXAMPLE
508
509This is an actual protocol dump of a handshake, followed by a single data
510packet. The greater than/less than lines indicate the direction of the
511transfer only.
512
513 > aemp;0;nndKd+gn;10.0.0.1:4040;hmac_md6_64_256,cleartext;json,storable;provider=AE-0.0;peeraddr=127.0.0.1:1235
514 > sRG8bbc4TDbkpvH8FTP4HBs87OhepH6VuApoZqXXskuG
515 < aemp;0;nmpKd+gh;127.0.0.1:1235,[::1]:1235;hmac_md6_64_256,cleartext;json,storable;provider=AE-0.0;peeraddr=127.0.0.1:58760
516 < dCEUcL/LJVSTJcx8byEsOzrwhzJYOq+L3YcopA5T6EAo
517 > hmac_md6_64_256;9513d4b258975accfcb2ab7532b83690e9c119a502c612203332a591c7237788;json
518 < hmac_md6_64_256;0298d6ba2240faabb2b2e881cf86b97d70a113ca74a87dc006f9f1e9d3010f90;json
519 > ["","lookup","pinger","10.0.0.1:4040#nndKd+gn.a","resolved"]
520
453=head1 SEE ALSO 521=head1 SEE ALSO
454 522
455L<AnyEvent>. 523L<AnyEvent>.
456 524
457=head1 AUTHOR 525=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines