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.13 by root, Mon Aug 3 22:05:55 2009 UTC vs.
Revision 1.22 by root, Wed Aug 5 19:55:58 2009 UTC

26 26
27use Scalar::Util; 27use Scalar::Util;
28use MIME::Base64 (); 28use MIME::Base64 ();
29use Storable (); 29use Storable ();
30use JSON::XS (); 30use JSON::XS ();
31
32use Digest::MD6 ();
33use Digest::HMAC_MD6 ();
31 34
32use AE (); 35use AE ();
33use AnyEvent::Socket (); 36use AnyEvent::Socket ();
34use AnyEvent::Handle (); 37use AnyEvent::Handle ();
35 38
126 $self->{queue} = []; 129 $self->{queue} = [];
127 130
128 { 131 {
129 Scalar::Util::weaken (my $self = $self); 132 Scalar::Util::weaken (my $self = $self);
130 133
131 $arg{tls_ctx_disabled} ||= {
132 sslv2 => 0,
133 sslv3 => 0,
134 tlsv1 => 1,
135 verify => 1,
136 cert_file => "secret.pem",
137 ca_file => "secret.pem",
138 verify_require_client_cert => 1,
139 };
140
141 $arg{secret} = AnyEvent::MP::Base::default_secret () 134 $arg{secret} = AnyEvent::MP::Base::default_secret ()
142 unless exists $arg{secret}; 135 unless exists $arg{secret};
136
137 my $secret = $arg{secret};
138
139 if ($secret =~ /-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----.*-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----/s) {
140 # assume TLS mode
141 $arg{tls_ctx} = {
142 sslv2 => 0,
143 sslv3 => 0,
144 tlsv1 => 1,
145 verify => 1,
146 cert => $secret,
147 ca_cert => $secret,
148 verify_require_client_cert => 1,
149 };
150 }
143 151
144 $self->{hdl} = new AnyEvent::Handle 152 $self->{hdl} = new AnyEvent::Handle
145 fh => delete $arg{fh}, 153 fh => delete $arg{fh},
146 autocork => 1, 154 autocork => 1,
147 no_delay => 1, 155 no_delay => 1,
149 $self->error ($_[2]); 157 $self->error ($_[2]);
150 }, 158 },
151 peername => delete $arg{peername}, 159 peername => delete $arg{peername},
152 ; 160 ;
153 161
154 my $secret = $arg{secret};
155 my $greeting_kv = $self->{greeting} ||= {}; 162 my $greeting_kv = $self->{greeting} ||= {};
156 $greeting_kv->{"tls"} = "1.0" 163 $greeting_kv->{"tls"} = "1.0"
157 if $arg{tls_ctx}; 164 if $arg{tls_ctx};
158 $greeting_kv->{provider} = "AE-$VERSION"; 165 $greeting_kv->{provider} = "AE-$VERSION";
159 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport}; 166 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport};
217 224
218 # read nonce 225 # read nonce
219 $self->{hdl}->push_read (line => sub { 226 $self->{hdl}->push_read (line => sub {
220 my $rgreeting2 = $_[1]; 227 my $rgreeting2 = $_[1];
221 228
229 "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack?
230 or return $self->error ("authentication error, echo attack?");
231
232 my $key = Digest::MD6::md6 $secret;
233 my $lauth;
234
222 if ($self->{tls_ctx} and 1 == int $self->{remote_greeting}{tls}) { 235 if ($self->{tls_ctx} and 1 == int $self->{remote_greeting}{tls}) {
223 $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; 236 $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept";
224 $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); 237 $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx});
238 $s_auth = "tls";
239 $lauth = "";
240 } else {
241 # we currently only support hmac_md6_64_256
242 $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256;
225 } 243 }
226
227 # auth
228 require Digest::MD6;
229 require Digest::HMAC_MD6;
230
231 my $key = Digest::MD6::md6 ($secret);
232 my $lauth = Digest::HMAC_MD6::hmac_md6_hex ($key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256);
233
234 my $rauth =
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)
236 : $s_auth eq "cleartext" ? unpack "H*", $secret
237 : die;
238
239 $lauth ne $rauth # echo attack?
240 or return $self->error ("authentication error");
241 244
242 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012"); 245 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012");
243 246
244 # reasd the authentication response 247 # read the authentication response
245 $self->{hdl}->push_read (line => sub { 248 $self->{hdl}->push_read (line => sub {
246 my ($hdl, $rline) = @_; 249 my ($hdl, $rline) = @_;
247 250
248 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline; 251 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline;
252
253 my $rauth =
254 $auth_method eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex $key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256
255 : $auth_method eq "cleartext" ? unpack "H*", $secret
256 : $auth_method eq "tls" ? ($self->{tls} ? "" : "\012\012") # \012\012 never matches
257 : return $self->error ("$auth_method: fatal, selected unsupported auth method");
249 258
250 if ($rauth2 ne $rauth) { 259 if ($rauth2 ne $rauth) {
251 return $self->error ("authentication failure/shared secret mismatch"); 260 return $self->error ("authentication failure/shared secret mismatch");
252 } 261 }
253 262
261 my $src_node = $self->{node}; 270 my $src_node = $self->{node};
262 271
263 $hdl->push_write ($self->{s_framing} => $_) 272 $hdl->push_write ($self->{s_framing} => $_)
264 for @$queue; 273 for @$queue;
265 274
266 my $rmsg; $rmsg = sub { 275 my $rmsg; $rmsg = sub {
267 $_[0]->push_read ($r_framing => $rmsg); 276 $_[0]->push_read ($r_framing => $rmsg);
268 277
269 local $AnyEvent::MP::Base::SRCNODE = $src_node; 278 local $AnyEvent::MP::Base::SRCNODE = $src_node;
270 AnyEvent::MP::Base::_inject (@{ $_[1] }); 279 AnyEvent::MP::Base::_inject (@{ $_[1] });
271 }; 280 };
280 289
281sub error { 290sub error {
282 my ($self, $msg) = @_; 291 my ($self, $msg) = @_;
283 292
284 if ($self->{node} && $self->{node}{transport} == $self) { 293 if ($self->{node} && $self->{node}{transport} == $self) {
294 #TODO: store error, but do not instantly fail
295 $self->{node}->fail (transport_error => $self->{node}{noderef}, $msg);
285 $self->{node}->clr_transport; 296 $self->{node}->clr_transport;
286 } 297 }
287 $AnyEvent::MP::Base::WARN->("$self->{peerhost}:$self->{peerport}: $msg"); 298 $AnyEvent::MP::Base::WARN->("$self->{peerhost}:$self->{peerport}: $msg");
288 $self->destroy; 299 $self->destroy;
289} 300}
326The greeting consists of two text lines that are ended by either an ASCII 337The greeting consists of two text lines that are ended by either an ASCII
327CR LF pair, or a single ASCII LF (recommended). 338CR LF pair, or a single ASCII LF (recommended).
328 339
329=head2 GREETING 340=head2 GREETING
330 341
342All the lines until after authentication must not exceed 4kb in length,
343including delimiter. Afterwards there is no limit on the packet size that
344can be received.
345
346=head3 First Greeting Line
347
348Example:
349
350 aemp;0;fec.4a7720fc;127.0.0.1:1235,[::1]:1235;hmac_md6_64_256;json,storable;provider=AE-0.0
351
331The first line contains strings separated (not ended) by C<;> 352The first line contains strings separated (not ended) by C<;>
332characters. The first even ixtrings are fixed by the protocol, the 353characters. The first even ixtrings are fixed by the protocol, the
333remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;> 354remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;>
334characters themselves. 355characters themselves.
335 356
336All the lines until after authentication must not exceed 4kb in length, including delimiter.
337
338The fixed strings are: 357The fixed strings are:
339 358
340=over 4 359=over 4
341 360
342=item C<aemp> 361=item protocol identification
343 362
344The constant C<aemp> to identify the protocol. 363The constant C<aemp> to identify the protocol.
345 364
346=item protocol version 365=item protocol version
347 366
348The protocol version supported by this end, currently C<0>. If the 367The protocol version supported by this end, currently C<0>. If the
349versions don't match then no communication is possible. Minor extensions 368versions don't match then no communication is possible. Minor extensions
350are supposed to be handled by addign additional key-value pairs. 369are supposed to be handled through additional key-value pairs.
351 370
352=item a token uniquely identifying the current node instance 371=item a token uniquely identifying the current node instance
353 372
354This is a string that must change between restarts. It usually contains 373This is a string that must change between restarts. It usually contains
355things like the current time, the (OS) process id or similar values, but 374things like the current time, the (OS) process id or similar values, but
396 415
397Indicates that the other side supports TLS (version should be 1.0) and 416Indicates that the other side supports TLS (version should be 1.0) and
398wishes to do a TLS handshake. 417wishes to do a TLS handshake.
399 418
400=back 419=back
420
421=head3 Second Greeting Line
401 422
402After this greeting line there will be a second line containing a 423After this greeting line there will be a second line containing a
403cryptographic nonce, i.e. random data of high quality. To keep the 424cryptographic nonce, i.e. random data of high quality. To keep the
404protocol text-only, these are usually 32 base64-encoded octets, but 425protocol text-only, these are usually 32 base64-encoded octets, but
405it could be anything that doesn't contain any ASCII CR or ASCII LF 426it could be anything that doesn't contain any ASCII CR or ASCII LF
406characters. 427characters.
407 428
408Example of the two lines of greeting: 429I<< The two nonces B<must> be different, and an aemp implementation
430B<must> check and fail when they are identical >>.
409 431
410 aemp;0;fec.4a7720fc;127.0.0.1:1235,[::1]:1235;hmac_md6_64_256;json,storable;provider=AE-0.0 432Example of a nonce line:
433
411 p/I122ql7kJR8lumW3lXlXCeBnyDAvz8NQo3x5IFowE4 434 p/I122ql7kJR8lumW3lXlXCeBnyDAvz8NQo3x5IFowE4
412 435
413=head2 TLS handshake 436=head2 TLS handshake
414 437
415If, after the handshake, both sides indicate interest in TLS, then the 438I<< If, after the handshake, both sides indicate interest in TLS, then the
416connection I<must> use TLS, or fail. 439connection B<must> use TLS, or fail. >>
417 440
418Both sides compare their nonces, and the side who sent the lower nonce 441Both sides compare their nonces, and the side who sent the lower nonce
419value ("string" comparison on the raw octet values) becomes the client, 442value ("string" comparison on the raw octet values) becomes the client,
420and the one with the higher nonce the server. 443and the one with the higher nonce the server.
421 444
466 489
467 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" 490 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
468 491
469This is the token that is expected from the other side. 492This is the token that is expected from the other side.
470 493
494=item tls
495
496This type is only valid iff TLS was enabled and the TLS handshake
497was successful. It has no authentication data, as the server/client
498certificate was successfully verified.
499
500Implementations supporting TLS I<must> accept this authentication type.
501
471=back 502=back
472 503
473=item the authentication data 504=item the authentication data
474 505
475The authentication data itself, usually base64 or hex-encoded data, see 506The authentication data itself, usually base64 or hex-encoded data, see
480This must be one of the framing protocols offered by the other side in the 511This must be one of the framing protocols offered by the other side in the
481greeting. Each side must accept the choice of the other side. 512greeting. Each side must accept the choice of the other side.
482 513
483=back 514=back
484 515
485Example: 516Example of an authentication reply:
486 517
487 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json 518 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json
488 519
489=head2 DATA PHASE 520=head2 DATA PHASE
490 521
491After this, packets get exchanged using the chosen framing protocol. It is 522After this, packets get exchanged using the chosen framing protocol. It is
492quite possible that both sides use a different framing protocol. 523quite possible that both sides use a different framing protocol.
493 524
525=head2 FULL EXAMPLE
526
527This is an actual protocol dump of a handshake, followed by a single data
528packet. The greater than/less than lines indicate the direction of the
529transfer only.
530
531 > 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
532 > sRG8bbc4TDbkpvH8FTP4HBs87OhepH6VuApoZqXXskuG
533 < 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
534 < dCEUcL/LJVSTJcx8byEsOzrwhzJYOq+L3YcopA5T6EAo
535 > hmac_md6_64_256;9513d4b258975accfcb2ab7532b83690e9c119a502c612203332a591c7237788;json
536 < hmac_md6_64_256;0298d6ba2240faabb2b2e881cf86b97d70a113ca74a87dc006f9f1e9d3010f90;json
537 > ["","lookup","pinger","10.0.0.1:4040#nndKd+gn.a","resolved"]
538
494=head1 SEE ALSO 539=head1 SEE ALSO
495 540
496L<AnyEvent>. 541L<AnyEvent>.
497 542
498=head1 AUTHOR 543=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines