1 | =head1 NAME |
1 | =head1 NAME |
2 | |
2 | |
3 | AnyEvent::MP::Transport - actual transport protocol |
3 | AnyEvent::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 | |
11 | This is the superclass for MP transports, most of which is considered an |
11 | This implements the actual transport protocol for MP (it represents a |
12 | implementation detail. |
12 | single link), most of which is considered an implementation detail. |
13 | |
13 | |
14 | See the "PROTOCOL" section below if you want to write another client for |
14 | See the "PROTOCOL" section below if you want to write another client for |
15 | this protocol. |
15 | this protocol. |
16 | |
16 | |
17 | =head1 FUNCTIONS/METHODS |
17 | =head1 FUNCTIONS/METHODS |
… | |
… | |
111 | |
111 | |
112 | =cut |
112 | =cut |
113 | |
113 | |
114 | our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference |
114 | our @FRAMINGS = qw(json storable); # the framing types we accept and send, in order of preference |
115 | our @AUTH_SND = qw(hmac_md6_64_256); # auth types we send |
115 | our @AUTH_SND = qw(hmac_md6_64_256); # auth types we send |
116 | our @AUTH_RCV = (@AUTH_SND, qw(hex_secret)); # auth types we accept |
116 | our @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 | |
121 | sub new { |
121 | sub new { |
… | |
… | |
227 | # auth |
227 | # auth |
228 | require Digest::MD6; |
228 | require Digest::MD6; |
229 | require Digest::HMAC_MD6; |
229 | require Digest::HMAC_MD6; |
230 | |
230 | |
231 | my $key = Digest::MD6::md6 ($secret); |
231 | my $key = Digest::MD6::md6 ($secret); |
232 | 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); |
233 | |
233 | |
234 | my $rauth = |
234 | my $rauth = |
235 | $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) |
236 | : $s_auth eq "hex_secret" ? unpack "H*", $secret |
236 | : $s_auth eq "cleartext" ? unpack "H*", $secret |
237 | : die; |
237 | : die; |
238 | |
238 | |
239 | $lauth ne $rauth # echo attack? |
239 | $lauth ne $rauth # echo attack? |
240 | or return $self->error ("authentication error"); |
240 | or return $self->error ("authentication error"); |
241 | |
241 | |
… | |
… | |
432 | |
432 | |
433 | =item the authentication method chosen |
433 | =item the authentication method chosen |
434 | |
434 | |
435 | This must be one of the methods offered by the other side in the greeting. |
435 | This must be one of the methods offered by the other side in the greeting. |
436 | |
436 | |
|
|
437 | The currently supported authentication methods are: |
|
|
438 | |
|
|
439 | =over 4 |
|
|
440 | |
|
|
441 | =item cleartext |
|
|
442 | |
|
|
443 | This is simply the shared secret, lowercase-hex-encoded. This method is of |
|
|
444 | course very insecure, unless TLS is used, which is why this module will |
|
|
445 | accept, but not generate, cleartext auth replies. |
|
|
446 | |
|
|
447 | =item hmac_md6_64_256 |
|
|
448 | |
|
|
449 | This method uses an MD6 HMAC with 64 bit blocksize and 256 bit hash. First, the shared secret |
|
|
450 | is hashed with MD6: |
|
|
451 | |
|
|
452 | key = MD6 (secret) |
|
|
453 | |
|
|
454 | This secret is then used to generate the "local auth reply", by taking |
|
|
455 | the two local greeting lines and the two remote greeting lines (without |
|
|
456 | line endings), appending \012 to all of them, concatenating them and |
|
|
457 | calculating the MD6 HMAC with the key. |
|
|
458 | |
|
|
459 | lauth = HMAC_MD6 key, "lgreeting1\012lgreeting2\012rgreeting1\012rgreeting2\012" |
|
|
460 | |
|
|
461 | This authentication token is then lowercase-hex-encoded and sent to the |
|
|
462 | other side. |
|
|
463 | |
|
|
464 | Then the remote auth reply is generated using the same method, but local |
|
|
465 | and remote greeting lines swapped: |
|
|
466 | |
|
|
467 | rauth = HMAC_MD6 key, "rgreeting1\012rgreeting2\012lgreeting1\012lgreeting2\012" |
|
|
468 | |
|
|
469 | This is the token that is expected from the other side. |
|
|
470 | |
|
|
471 | =back |
|
|
472 | |
437 | =item the authentication data |
473 | =item the authentication data |
438 | |
474 | |
439 | The authentication data itself, usually base64 or hex-encoded data. |
475 | The authentication data itself, usually base64 or hex-encoded data, see |
|
|
476 | above. |
440 | |
477 | |
441 | =item the framing protocol chosen |
478 | =item the framing protocol chosen |
442 | |
479 | |
443 | This must be one of the framing protocols offered by the other side in the |
480 | This must be one of the framing protocols offered by the other side in the |
444 | greeting. Each side must accept the choice of the other side. |
481 | greeting. Each side must accept the choice of the other side. |
445 | |
482 | |
446 | =back |
483 | =back |
447 | |
484 | |
448 | Example: |
485 | Example: |
449 | |
486 | |
450 | hmac_md6_64_256;wIlLedBY956UCGSISG9mBZRDTG8xUi73/sVse2DSQp0;json |
487 | hmac_md6_64_256;363d5175df38bd9eaddd3f6ca18aa1c0c4aa22f0da245ac638d048398c26b8d3;json |
451 | |
488 | |
452 | =head2 DATA PHASE |
489 | =head2 DATA PHASE |
453 | |
490 | |
454 | After this, packets get exchanged using the chosen framing protocol. It is |
491 | After this, packets get exchanged using the chosen framing protocol. It is |
455 | quite possible that both sides use a different framing protocol. |
492 | quite possible that both sides use a different framing protocol. |