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.20 by root, Tue Aug 4 23:16:57 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
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 $self->{node}->fail (transport_error => $msg);
285 $self->{node}->clr_transport; 295 $self->{node}->clr_transport;
286 } 296 }
287 $AnyEvent::MP::Base::WARN->("$self->{peerhost}:$self->{peerport}: $msg"); 297 $AnyEvent::MP::Base::WARN->("$self->{peerhost}:$self->{peerport}: $msg");
288 $self->destroy; 298 $self->destroy;
289} 299}
326The greeting consists of two text lines that are ended by either an ASCII 336The greeting consists of two text lines that are ended by either an ASCII
327CR LF pair, or a single ASCII LF (recommended). 337CR LF pair, or a single ASCII LF (recommended).
328 338
329=head2 GREETING 339=head2 GREETING
330 340
341All the lines until after authentication must not exceed 4kb in length,
342including delimiter. Afterwards there is no limit on the packet size that
343can be received.
344
345=head3 First Greeting Line
346
347Example:
348
349 aemp;0;fec.4a7720fc;127.0.0.1:1235,[::1]:1235;hmac_md6_64_256;json,storable;provider=AE-0.0
350
331The first line contains strings separated (not ended) by C<;> 351The first line contains strings separated (not ended) by C<;>
332characters. The first even ixtrings are fixed by the protocol, the 352characters. The first even ixtrings are fixed by the protocol, the
333remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;> 353remaining strings are C<KEY=VALUE> pairs. None of them may contain C<;>
334characters themselves. 354characters themselves.
335 355
336All the lines until after authentication must not exceed 4kb in length, including delimiter.
337
338The fixed strings are: 356The fixed strings are:
339 357
340=over 4 358=over 4
341 359
342=item C<aemp> 360=item protocol identification
343 361
344The constant C<aemp> to identify the protocol. 362The constant C<aemp> to identify the protocol.
345 363
346=item protocol version 364=item protocol version
347 365
348The protocol version supported by this end, currently C<0>. If the 366The protocol version supported by this end, currently C<0>. If the
349versions don't match then no communication is possible. Minor extensions 367versions don't match then no communication is possible. Minor extensions
350are supposed to be handled by addign additional key-value pairs. 368are supposed to be handled through additional key-value pairs.
351 369
352=item a token uniquely identifying the current node instance 370=item a token uniquely identifying the current node instance
353 371
354This is a string that must change between restarts. It usually contains 372This is a string that must change between restarts. It usually contains
355things like the current time, the (OS) process id or similar values, but 373things like the current time, the (OS) process id or similar values, but
396 414
397Indicates that the other side supports TLS (version should be 1.0) and 415Indicates that the other side supports TLS (version should be 1.0) and
398wishes to do a TLS handshake. 416wishes to do a TLS handshake.
399 417
400=back 418=back
419
420=head3 Second Greeting Line
401 421
402After this greeting line there will be a second line containing a 422After this greeting line there will be a second line containing a
403cryptographic nonce, i.e. random data of high quality. To keep the 423cryptographic nonce, i.e. random data of high quality. To keep the
404protocol text-only, these are usually 32 base64-encoded octets, but 424protocol text-only, these are usually 32 base64-encoded octets, but
405it could be anything that doesn't contain any ASCII CR or ASCII LF 425it could be anything that doesn't contain any ASCII CR or ASCII LF
406characters. 426characters.
407 427
408Example of the two lines of greeting: 428I<< The two nonces B<must> be different, and an aemp implementation
429B<must> check and fail when they are identical >>.
409 430
410 aemp;0;fec.4a7720fc;127.0.0.1:1235,[::1]:1235;hmac_md6_64_256;json,storable;provider=AE-0.0 431Example of a nonce line:
432
411 p/I122ql7kJR8lumW3lXlXCeBnyDAvz8NQo3x5IFowE4 433 p/I122ql7kJR8lumW3lXlXCeBnyDAvz8NQo3x5IFowE4
412 434
413=head2 TLS handshake 435=head2 TLS handshake
414 436
415If, after the handshake, both sides indicate interest in TLS, then the 437I<< If, after the handshake, both sides indicate interest in TLS, then the
416connection I<must> use TLS, or fail. 438connection B<must> use TLS, or fail. >>
417 439
418Both sides compare their nonces, and the side who sent the lower nonce 440Both sides compare their nonces, and the side who sent the lower nonce
419value ("string" comparison on the raw octet values) becomes the client, 441value ("string" comparison on the raw octet values) becomes the client,
420and the one with the higher nonce the server. 442and the one with the higher nonce the server.
421 443
466 488
467 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" 489 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
468 490
469This is the token that is expected from the other side. 491This is the token that is expected from the other side.
470 492
493=item tls
494
495This type is only valid iff TLS was enabled and the TLS handshake
496was successful. It has no authentication data, as the server/client
497certificate was successfully verified.
498
499Implementations supporting TLS I<must> accept this authentication type.
500
471=back 501=back
472 502
473=item the authentication data 503=item the authentication data
474 504
475The authentication data itself, usually base64 or hex-encoded data, see 505The 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 510This 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. 511greeting. Each side must accept the choice of the other side.
482 512
483=back 513=back
484 514
485Example: 515Example of an authentication reply:
486 516
487 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json 517 hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json
488 518
489=head2 DATA PHASE 519=head2 DATA PHASE
490 520
491After this, packets get exchanged using the chosen framing protocol. It is 521After this, packets get exchanged using the chosen framing protocol. It is
492quite possible that both sides use a different framing protocol. 522quite possible that both sides use a different framing protocol.
493 523
524=head2 FULL EXAMPLE
525
526This is an actual protocol dump of a handshake, followed by a single data
527packet. The greater than/less than lines indicate the direction of the
528transfer only.
529
530 > 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
531 > sRG8bbc4TDbkpvH8FTP4HBs87OhepH6VuApoZqXXskuG
532 < 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
533 < dCEUcL/LJVSTJcx8byEsOzrwhzJYOq+L3YcopA5T6EAo
534 > hmac_md6_64_256;9513d4b258975accfcb2ab7532b83690e9c119a502c612203332a591c7237788;json
535 < hmac_md6_64_256;0298d6ba2240faabb2b2e881cf86b97d70a113ca74a87dc006f9f1e9d3010f90;json
536 > ["","lookup","pinger","10.0.0.1:4040#nndKd+gn.a","resolved"]
537
494=head1 SEE ALSO 538=head1 SEE ALSO
495 539
496L<AnyEvent>. 540L<AnyEvent>.
497 541
498=head1 AUTHOR 542=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines