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.40 by root, Fri Aug 28 00:31:14 2009 UTC vs.
Revision 1.41 by root, Fri Aug 28 16:37:30 2009 UTC

119=cut 119=cut
120 120
121sub LATENCY() { 3 } # assumed max. network latency 121sub LATENCY() { 3 } # assumed max. network latency
122 122
123our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference 123our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference
124our @AUTH_SND = qw(hmac_md6_64_256); # auth types we send 124our @AUTH_SND = qw(tls_md6_64_256 hmac_md6_64_256); # auth types we send
125our @AUTH_RCV = (@AUTH_SND, qw(cleartext)); # auth types we accept 125our @AUTH_RCV = (@AUTH_SND, qw(tls_anon cleartext)); # auth types we accept
126 126
127#AnyEvent::Handle::register_write_type mp_record => sub { 127#AnyEvent::Handle::register_write_type mp_record => sub {
128#}; 128#};
129 129
130sub new { 130sub new {
179 179
180 my $greeting_kv = $self->{greeting} ||= {}; 180 my $greeting_kv = $self->{greeting} ||= {};
181 181
182 $self->{local_node} ||= $AnyEvent::MP::Kernel::NODE; 182 $self->{local_node} ||= $AnyEvent::MP::Kernel::NODE;
183 183
184 $greeting_kv->{"tls"} = "1.0" if $arg{tls_ctx}; 184 $greeting_kv->{tls} = "1.0" if $arg{tls_ctx};
185 $greeting_kv->{provider} = "AE-$AnyEvent::MP::Kernel::VERSION"; 185 $greeting_kv->{provider} = "AE-$AnyEvent::MP::Kernel::VERSION";
186 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport}; 186 $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport};
187 $greeting_kv->{timeout} = $arg{timeout}; 187 $greeting_kv->{timeout} = $arg{timeout};
188 188
189 # send greeting 189 # send greeting
212 return $self->error ("I refuse to talk to myself"); 212 return $self->error ("I refuse to talk to myself");
213 } elsif ($AnyEvent::MP::Kernel::NODE{$rnode} && $AnyEvent::MP::Kernel::NODE{$rnode}{transport}) { 213 } elsif ($AnyEvent::MP::Kernel::NODE{$rnode} && $AnyEvent::MP::Kernel::NODE{$rnode}{transport}) {
214 return $self->error ("$rnode already connected, not connecting again."); 214 return $self->error ("$rnode already connected, not connecting again.");
215 } 215 }
216 216
217 my $s_auth;
218 for my $auth_ (split /,/, $auths) {
219 if (grep $auth_ eq $_, @AUTH_SND) {
220 $s_auth = $auth_;
221 last;
222 }
223 }
224
225 defined $s_auth
226 or return $self->error ("$auths: no common auth type supported");
227
228 die unless $s_auth eq "hmac_md6_64_256"; # hardcoded atm.
229
230 my $s_framing;
231 for my $framing_ (split /,/, $framings) {
232 if (grep $framing_ eq $_, @FRAMINGS) {
233 $s_framing = $framing_;
234 last;
235 }
236 }
237
238 defined $s_framing
239 or return $self->error ("$framings: no common framing method supported");
240
241 $self->{remote_node} = $rnode; 217 $self->{remote_node} = $rnode;
242 218
243 $self->{remote_greeting} = { 219 $self->{remote_greeting} = {
244 map /^([^=]+)(?:=(.*))?/ ? ($1 => $2) : (), 220 map /^([^=]+)(?:=(.*))?/ ? ($1 => $2) : (),
245 @kv 221 @kv
250 my $rgreeting2 = $_[1]; 226 my $rgreeting2 = $_[1];
251 227
252 "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack? 228 "$lgreeting1\012$lgreeting2" ne "$rgreeting1\012$rgreeting2" # echo attack?
253 or return $self->error ("authentication error, echo attack?"); 229 or return $self->error ("authentication error, echo attack?");
254 230
231 my $tls = $self->{tls_ctx} && 1 == int $self->{remote_greeting}{tls};
232
233 my $s_auth;
234 for my $auth_ (split /,/, $auths) {
235 if (grep $auth_ eq $_, @AUTH_SND and ($auth_ !~ /^tls_/ or $tls)) {
236 $s_auth = $auth_;
237 last;
238 }
239 }
240
241 defined $s_auth
242 or return $self->error ("$auths: no common auth type supported");
243
244 my $s_framing;
245 for my $framing_ (split /,/, $framings) {
246 if (grep $framing_ eq $_, @FRAMINGS) {
247 $s_framing = $framing_;
248 last;
249 }
250 }
251
252 defined $s_framing
253 or return $self->error ("$framings: no common framing method supported");
254
255 my $key; 255 my $key;
256 my $lauth; 256 my $lauth;
257 257
258 if ($self->{tls_ctx} and 1 == int $self->{remote_greeting}{tls}) { 258 if ($tls) {
259 $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; 259 $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept";
260 $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); 260 $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx});
261 $s_auth = "tls"; 261
262 $lauth = ""; 262 $lauth =
263 $s_auth eq "tls_anon" ? ""
264 : $s_auth eq "tls_md6_64_256" ? Digest::MD6::md6_hex "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012"
265 : return $self->error ("$s_auth: fatal, selected unsupported snd auth method");
266
263 } elsif (length $secret) { 267 } elsif (length $secret) {
268 return $self->error ("$s_auth: fatal, selected unsupported snd auth method")
269 unless $s_auth eq "hmac_md6_64_256"; # hardcoded atm.
270
264 $key = Digest::MD6::md6 $secret; 271 $key = Digest::MD6::md6 $secret;
265 # we currently only support hmac_md6_64_256 272 # we currently only support hmac_md6_64_256
266 $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256; 273 $lauth = Digest::HMAC_MD6::hmac_md6_hex $key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256;
274
267 } else { 275 } else {
268 return $self->error ("unable to handshake TLS and no shared secret configured"); 276 return $self->error ("unable to handshake TLS and no shared secret configured");
269 } 277 }
270 278
271 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012"); 279 $self->{hdl}->push_write ("$s_auth;$lauth;$s_framing\012");
277 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline; 285 my ($auth_method, $rauth2, $r_framing) = split /;/, $rline;
278 286
279 my $rauth = 287 my $rauth =
280 $auth_method eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex $key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256 288 $auth_method eq "hmac_md6_64_256" ? Digest::HMAC_MD6::hmac_md6_hex $key, "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012", 64, 256
281 : $auth_method eq "cleartext" ? unpack "H*", $secret 289 : $auth_method eq "cleartext" ? unpack "H*", $secret
282 : $auth_method eq "tls" ? ($self->{tls} ? "" : "\012\012") # \012\012 never matches 290 : $auth_method eq "tls_anon" ? ($tls ? "" : "\012\012") # \012\012 never matches
291 : $auth_method eq "tls_md6_64_256" ? ($tls ? Digest::MD6::md6_hex "$rgreeting1\012$rgreeting2\012$lgreeting1\012$lgreeting2\012" : "\012\012")
283 : return $self->error ("$auth_method: fatal, selected unsupported auth method"); 292 : return $self->error ("$auth_method: fatal, selected unsupported rcv auth method");
284 293
285 if ($rauth2 ne $rauth) { 294 if ($rauth2 ne $rauth) {
286 return $self->error ("authentication failure/shared secret mismatch"); 295 return $self->error ("authentication failure/shared secret mismatch");
287 } 296 }
288 297
498 507
499=item the authentication method chosen 508=item the authentication method chosen
500 509
501This must be one of the methods offered by the other side in the greeting. 510This must be one of the methods offered by the other side in the greeting.
502 511
512Note that all methods starting with C<tls_> are only valid I<iff> TLS was
513successfully handshaked (and to be secure the implementation must enforce
514this).
515
503The currently supported authentication methods are: 516The currently supported authentication methods are:
504 517
505=over 4 518=over 4
506 519
507=item cleartext 520=item cleartext
532 545
533 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" 546 rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
534 547
535This is the token that is expected from the other side. 548This is the token that is expected from the other side.
536 549
537=item tls 550=item tls_anon
538 551
539This type is only valid iff TLS was enabled and the TLS handshake 552This type is only valid iff TLS was enabled and the TLS handshake
540was successful. It has no authentication data, as the server/client 553was successful. It has no authentication data, as the server/client
541certificate was successfully verified. 554certificate was successfully verified.
542 555
543Implementations supporting TLS I<must> accept this authentication type. 556This authentication type is slightly less secure than the others, as it
557allows a man-in-the-middle attacker to change some of the connection
558parameters (such as the framing format), although there is no known attack
559that exploits this in a way that is worse than just denying the service.
560
561By default, this implementation accepts but uses this authentication
562method.
563
564=item tls_md6_64_256
565
566This type is only valid iff TLS was enabled and the TLS handshake
567was successful.
568
569This authentication type simply calculates:
570
571 lauth = MD6 "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012"
572
573and lowercase-hex encodes the result and sends it as authentication
574data. No shared secret is required (authentication is done by TLS). The
575checksum solely exists to make tinkering with the greeting hard.
544 576
545=back 577=back
546 578
547=item the authentication data 579=item the authentication data
548 580

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines