--- AnyEvent-MP/MP/Transport.pm 2009/08/03 14:47:25 1.7 +++ AnyEvent-MP/MP/Transport.pm 2009/08/03 15:40:53 1.11 @@ -45,7 +45,7 @@ See C, below, for constructor arguments. -Defaults for peerhost, peerport, fh and tls are provided. +Defaults for peerhost, peerport and fh are provided. =cut @@ -60,7 +60,6 @@ fh => $fh, peerhost => $host, peerport => $port, - tls => "accept", @args, ); } @@ -84,7 +83,6 @@ peername => $host, peerhost => $nhost, peerport => $nport, - tls => "accept", @args, ); } @@ -107,7 +105,6 @@ greeting => { key => value }, # tls support - tls => "accept|connect", tls_ctx => AnyEvent::TLS, peername => $peername, # for verification ; @@ -131,10 +128,15 @@ { Scalar::Util::weaken (my $self = $self); - if (exists $arg{connect}) { - $arg{tls} ||= "connect"; - $arg{tls_ctx} ||= { sslv2 => 0, sslv3 => 0, tlsv1 => 1, verify => 1 }; - } + $arg{tls_ctx_disabled} ||= { + sslv2 => 0, + sslv3 => 0, + tlsv1 => 1, + verify => 1, + cert_file => "secret.pem", + ca_file => "secret.pem", + verify_require_client_cert => 1, + }; $arg{secret} = AnyEvent::MP::Base::default_secret () unless exists $arg{secret}; @@ -152,8 +154,8 @@ my $secret = $arg{secret}; my $greeting_kv = $self->{greeting} ||= {}; - $greeting_kv->{"tls1.0"} ||= $arg{tls} - if exists $arg{tls} && $arg{tls_ctx}; + $greeting_kv->{"tls"} = "1.0" + if $arg{tls_ctx}; $greeting_kv->{provider} = "AE-$VERSION"; $greeting_kv->{peeraddr} = AnyEvent::Socket::format_hostport $self->{peerhost}, $self->{peerport}; @@ -212,22 +214,20 @@ @kv }; - if (exists $self->{tls} and $self->{tls_ctx} and exists $self->{remote_greeting}{"tls1.0"}) { - if ($self->{tls} ne $self->{remote_greeting}{"tls1.0"}) { - return $self->error ("TLS server/client mismatch"); - } - $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); - } - # read nonce $self->{hdl}->push_read (line => sub { my $rgreeting2 = $_[1]; + if ($self->{tls_ctx} and 1 == int $self->{remote_greeting}{tls}) { + $self->{tls} = $lgreeting2 lt $rgreeting2 ? "connect" : "accept"; + $self->{hdl}->starttls ($self->{tls}, $self->{tls_ctx}); + } + # auth require Digest::MD6; require Digest::HMAC_MD6; - my $key = Digest::MD6::md6_hex ($secret); + my $key = Digest::MD6::md6 ($secret); my $lauth = Digest::HMAC_MD6::hmac_md6_base64 ($key, "$lgreeting1\012$lgreeting2\012$rgreeting1\012$rgreeting2\012", 64, 256); my $rauth = @@ -324,7 +324,7 @@ =head2 GREETING -The first line contains strings seperated (not ended) by C<;> +The first line contains strings separated (not ended) by C<;> characters. The first seven strings are fixed by the protocol, the remaining strings are C pairs. None of them may contain C<;> characters themselves. @@ -371,9 +371,85 @@ receiving side should choose the first framing format it supports for sending packets (which might be different from the format it has to accept). - . ";$self->{peerhost};$self->{peerport}" - . (join "", map ";$_=$greeting_kv->{$_}", keys %$greeting_kv); - my $lgreeting2 = MIME::Base64::encode_base64 AnyEvent::MP::Base::nonce (33), ""; +=back + +The remaining arguments are C pairs. The following key-value +pairs are known at this time: + +=over 4 + +=item provider= + +The software provider for this implementation. For AnyEvent::MP, this is +C or whatever version it currently is at. + +=item peeraddr=: + +The peer address (socket address of the other side) as seen locally, in the same format +as noderef endpoints. + +=item tls=. + +Indicates that the other side supports TLS (version should be 1.0) and +wishes to do a TLS handshake. + +=back + +After this greeting line there will be a second line containing a +cryptographic nonce, i.e. random data of high quality. To keep the +protocol text-only, these are usually 32 base64-encoded octets, but +it could be anything that doesn't contain any ASCII CR or ASCII LF +characters. + +Example of the two lines of greeting: + + 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 + XntegV2Guvss0qNn7phCPnoU87xqxV+4Mqm/5y4iQm6a + +=head2 TLS handshake + +If, after the handshake, both sides indicate interest in TLS, then the +connection I use TLS, or fail. + +Both sides compare their nonces, and the side who sent the lower nonce +value ("string" comparison on the raw octet values) becomes the client, +and the one with the higher nonce the server. + +=head2 AUTHENTICATION PHASE + +After the greeting is received (and the optional TLS handshake), +the authentication phase begins, which consists of sending a single +C<;>-separated line with three fixed strings and any number of +C pairs. + +The three fixed strings are: + +=over 4 + +=item the authentication method chosen + +This must be one of the methods offered by the other side in the greeting. + +=item the authentication data + +The authentication data itself, usually base64 or hex-encoded data. + +=item the framing protocol chosen + +This must be one of the framing protocols offered by the other side in the +greeting. Each side must accept the choice of the other side. + +=back + +Example (the actual reply matching the previous example): + + hmac_md6_64_256;wIlLedBY956UCGSISG9mBZRDTG8xUi73/sVse2DSQp0;json + +=head2 DATA PHASE + +After this, packets get exchanged using the chosen framing protocol. It is +quite possible that both sides use a different framing protocol. + =head1 SEE ALSO L.