1package Net::SSL::Handshake; 2 3use Moose; 4 5use English qw( -no_match_vars ); 6use IO::Socket::INET; 7use IO::Socket::Timeout qw(IO::Socket::INET); 8use Net::IDN::Encode qw(domain_to_ascii); 9use Readonly; 10use Carp qw(croak); 11 12use 5.010; 13 14use Net::SSL::CipherSuites; 15use Net::SSL::Handshake::Extensions::ServerName; 16use Net::SSL::Handshake::Extensions::EllipticCurves; 17use Net::SSL::Handshake::Extensions::ECPointFormats; 18 19use Exporter qw(import); 20 21my @ssl_versions = qw($SSLv2 $SSLv3 $TLSv1 $TLSv11 $TLSv12); 22 23our @EXPORT_OK = ( @ssl_versions, qw(%CONTENT_TYPE) ); 24our %EXPORT_TAGS = ( all => \@EXPORT_OK, ssl_versions => \@ssl_versions, ); 25 26Readonly my $MT_CLIENT_HELLO => 1; 27Readonly my $MT_SERVER_HELLO => 4; 28 29 30Readonly our $SSLv2 => 0x0002; 31Readonly our $SSLv3 => 0x0300; 32Readonly our $TLSv1 => 0x0301; 33Readonly our $TLSv11 => 0x0302; 34Readonly our $TLSv12 => 0x0303; 35 36Readonly our %CONTENT_TYPE => ( 37 change_cipher_spec => 20, 38 alert => 21, 39 handshake => 22, 40 application_data => 23, 41 early_handshake => 25, 42 ); 43 44 45Readonly our %HANDSHAKE_TYPE => ( 46 client_hello => 1, 47 server_hello => 2, 48 session_ticket => 4, 49 hello_retry_request => 6, 50 encrypted_extensions => 8, 51 certificate => 11, 52 certificate_request => 13, 53 certificate_verify => 15, 54 server_configuration => 17, 55 finished => 20, 56 ); 57 58 59=encoding utf8 60 61=head1 NAME 62 63Net::SSL::Handshake - SSL Handshake on an existing connection or open a new one 64 65=head1 VERSION 66 67Version 0.1.x, $Revision: 646 $ 68 69=cut 70 71use version; our $VERSION = qv( "v0.1." . ( sprintf "%d", q$Revision: 646 $ =~ /(\d+)/xg ) ); 72 73 74 75=head1 SYNOPSIS 76 77=encoding utf8 78 79 my $handshake = Net::SSL::Handshake->new( 80 socket => $socket, 81 timeout => $timeout, 82 host => $hostname, 83 port => $port, 84 ciphers => $ciphers, 85 ); 86 $handshake->hello; 87 88 89 90<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 91=head1 DESCRIPTION 92 93 94Attributes: 95 96 Tieouts for IO::Socket::Timeout (read, write) 97 Default: read from socket obj???? or 30 seconds? or whatelse! 98 99 socket 100 101 version 102 103 random and other parameters to ssl etc (default random) 104 105+++ IDN via Net::IDN::Encode (for SNI) 106 107Modules: 108 109 Net::SSL::StartTLS::SMTP, ... 110 111 112 113 Peter Mosman openssl: https://github.com/PeterMosmans/openssl/ 114 115 116# Build OpenSSL TEST! 117 118 git clone https://github.com/PeterMosmans/openssl.git --depth 1 -b 1.0.2-chacha openssl-chacha 119 120 # config, make & Inst 121 CFLAGS="-O3 -fno-strict-aliasing -pipe -march=native -mtune=native -fstack-protector" ./Configure darwin64-x86_64-cc --prefix=/Users/alvar/Documents/Code/externes/openssl-chacha/installdir --openssldir=/Users/alvar/Documents/Code/externes/openssl-chacha/installdir/openssl enable-asm threads shared zlib enable-ssl2 enable-ssl3 enable-md2 enable-rc5 no-gmp no-rfc3779 enable-ec_nistp_64_gcc_128 zlib no-shared experimental-jpake enable-md2 enable-rc5 enable-rfc3779 enable-gost enable-static-engine 122 make depend && make && make test && make report && make install 123 124 # Via: https://github.com/jvehent/cipherscan 125 126# cert list 127 128 openssl ciphers -l -V ALL:eNULL:aNULL 129 /Users/alvar/Documents/Code/externes/openssl-chacha/installdir/bin/openssl ciphers -l -V ALL:eNULL:aNULL 130 131 132 133# Self singned cert: 134openssl req -new -newkey rsa:2048 -days 36500 -nodes -x509 -keyout server.pem -out server.pem 135 136# Server: man s_server 137 138# Install openssl with SSLv2 and SSLv3 etc 139 140 CFLAGS="-O3 -fno-strict-aliasing -pipe -march=native -mtune=native -fstack-protector" ./Configure darwin64-x86_64-cc --prefix=/Users/alvar/Documents/Code/externes/openssl-1.0.2d/installdir --openssldir=/Users/alvar/Documents/Code/externes/openssl-1.0.2d/installdir/openssl enable-asm threads shared zlib zlib-dynamic enable-ssl2 enable-ssl3 enable-md2 enable-rc5 no-gmp no-rfc3779 enable-ec_nistp_64_gcc_128 141 make depend 142 make && make test && make install 143 144 145# Start server 146 147 Users/alvar/Documents/Code/externes/openssl-1.0.2d/installdir/bin/openssl s_server -HTTP -accept 443 148 149# oder mit www 150 151 152 153# Standard TLS/SSL handshake 154handshake_pkts = { 155"TLS v1.3": '\x80\x2c\x01\x03\x04\x00\x03\x00\x00\x00\x20', 156"TLS v1.2": '\x80\x2c\x01\x03\x03\x00\x03\x00\x00\x00\x20', 157"TLS v1.1": '\x80\x2c\x01\x03\x02\x00\x03\x00\x00\x00\x20', 158"TLS v1.0": '\x80\x2c\x01\x03\x01\x00\x03\x00\x00\x00\x20', 159"SSL v3.0": '\x80\x2c\x01\x03\x00\x00\x03\x00\x00\x00\x20', 160"SSL v2.0": '\x80\x2c\x01\x00\x02\x00\x03\x00\x00\x00\x20' 161} 162 163https://github.com/iphelix/sslmap/blob/master/sslmap.py 164 165=head2 SSL Handshake 166 167 168https://github.com/iphelix/sslmap/blob/master/sslmap.py 169 170https://labs.portcullis.co.uk/tools/ssl-cipher-suite-enum/ 171 172https://github.com/drwetter/testssl.sh 173https://testssl.sh 174 175 176pack types: 177 178 C unsigned 8 bit char 179 n unsigned short, 16 bit, network order 180 a binary string, NULL padded 181 182 183 184 185 186=head3 SSLv2 187 188 189Client sends 190 191 192Client hello max 256 bytes for F5! (Bug) https://code.google.com/p/chromium/issues/detail?id=245500 193Fixed at least since 09/29/2011 194 195 196Client-Hello SSLv2: 197 198 # Header 199 n Message len | 0x8000 200 201 # Data. len: message len 202 C Message Type: SSL_MT_CLIENT_HELLO 203 n Client-Version 204 n Cipher spec len 205 n Session-ID len => 0 206 n challenge len 207 a* cipher spec data 208 a* session id data => empty 209 a* challenge data 210 211alternative header (3 bytes): 212 213 # Header 214 n Message len 215 C Padding (number of bytes added at the end of data part!) 216 217 218 219=head3 SSLv3 and TLS 220 221 222 223 224 225 C record Type / SSL record type = 22 (SSL3_RT_HANDSHAKE) 226 n SSL Version 227 n Record len 228 229 # Record: 230 C Message Type / Handshake type 231 C 0x00 / Length of data to follow in this record (3 Bytes!) 232 n Message len / Length rest 233 234 ## Data 235 n SSL/TLS Version 236 a[32] challenge 237 C session ID len 238 n cipher spec len 239 a* cipher spec 240 C compression method len (1) 241 C* compression method (0x00) 242 n length extensions 243 a* extensions data 244 245 246 ## Extensions: SNI, 247 248 249 250 251 # Hello Extensions format: 252 253 n extension type 254 n Length extension data 255 a* data 256 257 258 # data for hello extension sni: 259 260 n len of list (bytes) 261 C Nametype (host_name: 0x00) 262 n len host name 263 a* hostname (IDN!) 264 265 266 $clientHello_extensions = pack( 267 "n n n C n a[$clientHello{'extension_sni_len'}]", 268 $clientHello{'extension_type_server_name'}, #n 269 $clientHello{'extension_len'}, #n 270 $clientHello{'extension_sni_list_len'}, #n 271 $clientHello{'extension_sni_type'}, #C 272 $clientHello{'extension_sni_len'}, #n 273 $clientHello{'extension_sni_name'}, #a[$clientHello{'extension_sni_len'}] 274 ); 275 276 277 278 279 280 281 282 283 "n a[32] C n a[$clientHello{'cipher_spec_len'}] C C[$clientHello{'compression_method_len'}] a[$clientHello{'extensions_total_len'}]", 284 $clientHello{'version'}, # n 285 $clientHello{'challenge'}, # A[32] = gmt + random [4] + [28] Bytes 286 $clientHello{'session_id_len'}, # C 287 $clientHello{'cipher_spec_len'}, # n 288 $clientHello{'cipher_spec'}, # A[$clientHello{'cipher_spec_len'}] 289 $clientHello{'compression_method_len'}, # C (0x01) 290 $clientHello{'compression_method'}, # C[len] (0x00) 291 $clientHello_extensions # optional 292 ); 293 294 295 296https://www-01.ibm.com/support/knowledgecenter/#!/SSB23S_1.1.0.10/com.ibm.ztpf-ztpfdf.doc_put.10/gtps5/s5rcd.html?cp=SSB23S_1.1.0.10%2F0-1-8-2-3 297 298 299possible handshake types: 300 301 SSL3_MT_HELLO_REQUEST 0 (x'00') 302 SSL3_MT_CLIENT_HELLO 1 (x'01') 303 SSL3_MT_SERVER_HELLO 2 (x'02') 304 SSL3_MT_CERTIFICATE 11 (x'0B') 305 SSL3_MT_SERVER_KEY_EXCHANGE 12 (x'0C') 306 SSL3_MT_CERTIFICATE_REQUEST 13 (x'0D') 307 SSL3_MT_SERVER_DONE 14 (x'0E') 308 SSL3_MT_CERTIFICATE_VERIFY 15 (x'0F') 309 SSL3_MT_CLIENT_KEY_EXCHANGE 16 (x'10') 310 SSL3_MT_FINISHED 20 (x'14') 311 312 313 314 315 316 $clientHello{'msg_len'} = length($clientHello_tmp); 317 $clientHello{'record_len'} = $clientHello{'msg_len'} + 4; 318 319 $clientHello = pack( 320 "C n n C C n a*", 321 $clientHello{'record_type'}, # C 322 $clientHello{'record_version'}, # n 323 $clientHello{'record_len'}, # n 324 $clientHello{'msg_type'}, # C 325 0x00, # C (0x00) 326 $clientHello{'msg_len'}, # n 327 $clientHello_tmp # a 328 ); 329 330 331 332 333 334Server-Hello: 335 336 337 338 339 340 341The SSL Handshake Protocol defines the following errors: 342 343NO-CIPHER-ERROR 344This error is returned by the client to the server when it cannot find a cipher or key size that it supports that is also supported by the server. 345This error is not recoverable. 346 347 348 349=cut 350 351 352has record_template => ( 353 is => "ro", 354 isa => "Str", 355 traits => ['String'], 356 default => "", 357 handles => { add_record_template => "append", clear_record_template => "clear", } 358 ); 359has _record_data => ( 360 is => "ro", 361 isa => "ArrayRef", 362 traits => ['Array'], 363 default => sub { [] }, 364 handles => { add_record_data => "push", clear_record_data => "clear", record_data => "elements", } 365 ); 366 367#<<< 368 369 370has socket => ( is => "ro", isa => "Object", handles => [qw(send recv )], lazy => 1, builder => "_build_socket", clearer => "close", ); 371has host => ( is => "ro", isa => "Str", ); 372has port => ( is => "ro", isa => "Int", default => 443, ); 373has error => ( is => "rw", isa => "Int", default => 0, ); 374has ciphers => ( is => "ro", isa => "Net::SSL::CipherSuites", required => 1, ); 375has accepted_ciphers => ( is => "rw", isa => "Net::SSL::CipherSuites", default => sub { Net::SSL::CipherSuites->new }); 376has timeout => ( is => "ro", isa => "Int", default => 60, ); 377has ssl_version => ( is => "ro", isa => "Int", default => $TLSv12); 378has sni => ( is => "ro", isa => "Bool", default => 1); 379 380# Server messages 381has server_version => ( is => "rw", isa => "Int", ); 382has server_cert => ( is => "rw", isa => "Str", ); 383 384has ok => (is => "ro", isa => "Bool", writer => "_ok", ); 385 386 387# TODO: readonly with private writer! 388has alert => (is => "rw", isa => "Bool", ); 389has no_cipher_found => (is => "rw", isa => "Bool", ); 390 391 392#>>> 393 394sub _build_socket 395 { 396 my $self = shift; 397 398 die __PACKAGE__ . ": need parameter socket or host!\n" unless $self->host; 399 400 my $idn_host = domain_to_ascii( $self->host ); 401 402 my $socket = IO::Socket::INET->new( Timeout => $self->timeout, PeerAddr => $idn_host, PeerPort => $self->port ) 403 // die __PACKAGE__ . ": Can't connect to ${ \$self->host }:${ \$self->port }: $OS_ERROR\n"; 404 405 IO::Socket::Timeout->enable_timeouts_on($socket); 406 $socket->read_timeout( $self->timeout ); 407 $socket->write_timeout( $self->timeout ); 408 409 return $socket; 410 } 411 412# for some Debug 413#sub _to_hex 414# { 415# return join( " ", map { sprintf "%02X", $ARG } unpack( "C*", shift ) ); 416# } 417# 418 419=head2 send_record 420 421sends the record to the server 422 423=cut 424 425sub send_record 426 { 427 my $self = shift; 428 my $content_type = shift // $CONTENT_TYPE{handshake}; 429 430 # say _to_hex( $self->record_as_string($content_type) ); 431 432 $self->send( $self->record_as_string($content_type) ) // croak "Error while sending data"; 433 434 # TODO: TImeout check! 435 436 $self->clear_record; # oder beim aufruf? 437 438 return; 439 } 440 441 442=head2 add_to_record 443 444adds a template and some data to a record 445 446 447=cut 448 449sub add_to_record 450 { 451 my $self = shift; 452 my $pattern = shift; 453 my @data = @ARG; 454 455 $self->add_record_template($pattern); 456 $self->add_record_data(@data); 457 458 return $self; 459 } 460 461 462=head2 record_as_string 463 464returns the record as a string; checks for SSLv2/ SSLv3 / TLS 465 466=cut 467 468 469sub record_as_string 470 { 471 my $self = shift; 472 my $content_type = shift; 473 474 my $record_data = pack( $self->record_template, $self->record_data ); 475 476 my $record_header; 477 478 if ( $self->ssl_version == $SSLv2 ) 479 { 480 $record_header = pack( "n", length($record_data) | 0x8000 ); 481 } 482 else 483 { 484 $record_header = pack( "C n n", $content_type, $self->ssl_version == $SSLv3 ? $SSLv3 : $TLSv1, length($record_data), ); 485 } 486 487 return $record_header . $record_data; 488 489 } ## end sub record_as_string 490 491=head2 clear_record 492 493clears the template etc 494 495=cut 496 497sub clear_record 498 { 499 my $self = shift; 500 $self->clear_record_template; 501 $self->clear_record_data; 502 return $self; 503 } 504 505=head2 challenge 506 507generate some random ... 508 509=cut 510 511sub challenge 512 { 513 return pack( "NC[28]", time, ( map { int( rand(256) ) } ( 1 .. 28 ) ) ); 514 } 515 516 517=head2 close_notify 518 519send a "close notify" alert 520 521=cut 522 523sub close_notify 524 { 525 my $self = shift; 526 527 $self->add_to_record( "CC", 1, 0 ); 528 $self->send_record( $CONTENT_TYPE{alert} ); 529 530 return $self; 531 } 532 533=head2 ->hello 534 535Send client hello, receive and parse server hello. 536 537... 538 539=cut 540 541sub hello 542 { 543 my $self = shift; 544 545 $self->build_client_hello; 546 $self->send_record; 547 $self->receive_record; 548 549 $self->close_notify unless $self->ssl_version == $SSLv2; 550 $self->close; 551 552 return $self; 553 } 554 555 556=head2 build_client_hello 557 558build client hello message 559 560=cut 561 562sub build_client_hello 563 { 564 my $self = shift; 565 566 my $cipher_spec = $self->ciphers->cipher_spec( $self->ssl_version ); 567 568 if ( $self->ssl_version == $SSLv2 ) 569 { 570 # C Message Type: SSL_MT_CLIENT_HELLO 571 # n Client-Version 572 # n Cipher spec len 573 # n Session-ID len => 0 574 # n challenge len 575 # a* cipher spec data 576 # a* session id data => empty 577 # a* challenge data 578 579 $self->add_to_record( 580 "Cnnnna*a[0]a[32]", $MT_CLIENT_HELLO, $self->ssl_version, length($cipher_spec), 581 0, 32, $cipher_spec, "", 582 $self->challenge 583 ); 584 } 585 else 586 { 587 588 # uint8 CipherSuite[2]; /* Cryptographic suite selector */ 589 # 590 # enum { null(0), (255) } CompressionMethod; 591 # 592 # struct { 593 # ProtocolVersion client_version = { 3, 4 }; /* TLS v1.3 */ 594 # Random random; 595 # SessionID session_id; 596 # CipherSuite cipher_suites<2..2^16-2>; 597 # CompressionMethod compression_methods<1..2^8-1>; 598 # Extension extensions<0..2^16-1>; 599 # } ClientHello; 600 # 601 602 # von außen: erst record, dann handshare-record, dann client-hello. 603 604 # build ClientHello 605 my $cipher_spec_len = length($cipher_spec); 606 607 my $extensions = $self->build_extensions; 608 my $client_hello = pack( 609 "n a[32] C n a[$cipher_spec_len] C C a*", 610 $self->ssl_version, 611 $self->challenge, 612 0, 613 length($cipher_spec), 614 $cipher_spec, 615 1, # compression len 616 0, # compression type 617 $extensions, 618 ); 619 620 # 621 # struct { 622 # HandshakeType msg_type; /* handshake type */ 623 # uint24 length; /* bytes in message */ 624 # select (HandshakeType) { 625 # case client_hello: ClientHello; 626 # case server_hello: ServerHello; 627 # case hello_retry_request: HelloRetryRequest; 628 # case encrypted_extensions: EncryptedExtensions; 629 # case server_configuration:ServerConfiguration; 630 # case certificate: Certificate; 631 # case certificate_request: CertificateRequest; 632 # case certificate_verify: CertificateVerify; 633 # case finished: Finished; 634 # case session_ticket: NewSessionTicket; 635 # } body; 636 # } Handshake; 637 638 639 $self->add_to_record( 640 "C C n a*", 641 $HANDSHAKE_TYPE{client_hello}, 642 0, # first byte length (type C) 643 length($client_hello), 644 $client_hello, 645 ); 646 647 648 } ## end else [ if ( $self->ssl_version...)] 649 650 return $self; 651 } ## end sub build_client_hello 652 653 654=head2 ->build_extensions 655 656Builds the hello extensions 657 658=cut 659 660sub build_extensions 661 { 662 my $self = shift; 663 664 my $extensions = ""; 665 666 $extensions .= Net::SSL::Handshake::Extensions::ServerName->new( hostname => $self->host )->data if $self->sni; 667 $extensions .= Net::SSL::Handshake::Extensions::ECPointFormats->new()->data; 668 $extensions .= Net::SSL::Handshake::Extensions::EllipticCurves->new()->data; 669 670 # $extensions .= ... 671 672 return pack( "n a*", length($extensions), $extensions ); 673 } 674 675 676 677=head2 receive_record 678 679receive and parse server record ... 680 681=cut 682 683sub receive_record 684 { 685 my $self = shift; 686 687 my $data; 688 $self->recv( $data, 1 ); 689 croak "Nothing received!" unless length($data); 690 691 my $content_type = unpack( "C", $data ); 692 693 return $self->sslv2_server_hello($data) if $content_type & 0x80; # = $MT_SERVER_HELLO; 694 695 # say "v3+"; 696 # 697 # die "jkgkjhgkjhg"; 698 # 699 # #use Data::Dumper; 700 # # say Dumper( [ $msg, $session_id_hit, $cert_type, $server_version, $cert_len, $cipher_spec_len, $connection_id_len ] ), 701 # # "\n", _to_hex($cert_data), "\n", _to_hex( $cipher_spec), "\n", _to_hex("$connection_id"); 702 # 703 # 704 # 705 # $content_type &= 0x7f; 706 # return $self->sslv2_server_hello($content_type) if $content_type == $MT_SERVER_HELLO; 707 708 undef $data; 709 $self->recv( $data, 4 ); 710 croak "no protocol-version/length received" unless length($data); 711 712 my ( $protocol_version, $record_lenght ) = unpack( "nn", $data ); 713 714 $self->server_version($protocol_version); 715 716 undef $data; 717 $self->recv( $data, $record_lenght ) // die "FATAL: No data!\n"; 718 719 return $self->parse_handshake($data) if $content_type == $CONTENT_TYPE{handshake}; 720 return $self->parse_alert($data) if $content_type == $CONTENT_TYPE{alert}; 721 die "Ups, the Server sent a NOT IMPLEMENTED ContentType: $content_type\n"; 722 } ## end sub receive_record 723 724 725=head2 parse_handshake($data) 726 727Parse SSLv3+ Handshake 728 729 730=cut 731 732 733sub parse_handshake 734 { 735 my $self = shift; 736 my $data = shift; 737 738 my ( $msg_type, $zero, $length, $rest ) = unpack( "C C n a*", $data ); 739 740 die "Expected server_hello, got $msg_type\n" if $msg_type != $HANDSHAKE_TYPE{server_hello}; 741 742 743 744 # TLS 1.3!!! 745 # struct { 746 # ProtocolVersion server_version; 747 # Random random; 748 # CipherSuite cipher_suite; 749 # select (extensions_present) { 750 # case false: 751 # struct {}; 752 # case true: 753 # Extension extensions<0..2^16-1>; 754 # }; 755 # } ServerHello; 756 757 # SSLv3 ==> TLS 1.2: 758 # struct { 759 # ProtocolVersion server_version; 760 # Random random; 761 # SessionID session_id; 762 # CipherSuite cipher_suite; 763 # CompressionMethod compression_method; 764 # select (extensions_present) { 765 # case false: 766 # struct {}; 767 # case true: 768 # Extension extensions<0..2^16-1>; 769 # }; 770 # } ServerHello; 771 772 my ( $server_version, $random, $session_id_len, $rest2 ) = unpack( "n a[32] C a*", $rest ); 773 my ( $session_id, $cipher_suite, $compression_method, $extensions ) = unpack( "a[$session_id_len] a[2] C a*", $rest2 ); 774 775 $self->server_version($server_version); 776 777 if ( length($cipher_suite) ) 778 { 779 $self->accepted_ciphers->add( Net::SSL::CipherSuites->new_by_cipher_spec($cipher_suite) ); 780 $self->_ok(1); 781 } 782 783 784 return $self; 785 } ## end sub parse_handshake 786 787 788=head2 sslv2_server_hello 789 790 791SERVER-HELLO (Phase 1; Sent in the clear) 792 793 0 char MSG-SERVER-HELLO 794 1 char SESSION-ID-HIT 795 2 char CERTIFICATE-TYPE 796 3 char SERVER-VERSION-MSB 797 4 char SERVER-VERSION-LSB 798 5 char CERTIFICATE-LENGTH-MSB 799 6 char CERTIFICATE-LENGTH-LSB 800 7 char CIPHER-SPECS-LENGTH-MSB 801 8 char CIPHER-SPECS-LENGTH-LSB 802 9 char CONNECTION-ID-LENGTH-MSB 803 10 char CONNECTION-ID-LENGTH-LSB 804 char CERTIFICATE-DATA[MSB<<8|LSB] 805 char CIPHER-SPECS-DATA[MSB<<8|LSB] 806 char CONNECTION-ID-DATA[MSB<<8|LSB] 807 808 809=cut 810 811Readonly my $SERVER_HELLO_HEAD_LEN => 11; 812 813sub sslv2_server_hello 814 { 815 my $self = shift; 816 my $first_byte = shift; 817 818 819 my $data; 820 $self->recv( $data, 1 ); 821 822 my $record_len = unpack( "n", "$first_byte$data" ) & 0x7fff; 823 824 undef $data; 825 $self->recv( $data, $record_len ); 826 827 die "Not enough Data for SSLv2 record!\n" unless length($data); 828 829 # 830 # all received; parse data ... 831 # 832 833 my ( $msg, $session_id_hit, $cert_type, $server_version, $cert_len, $cipher_spec_len, $connection_id_len, $rest ) 834 = unpack( "C C C n n n n a*", $data ); 835 836 die "Got no cert len at unpack SSLv2 server hello; got not enough data?\n" unless $cert_len; 837 838 my ( $cert_data, $cipher_spec, $connection_id ) = unpack( "a[$cert_len] a[$cipher_spec_len] a[$connection_id_len]", $rest ); 839 840 841 $self->server_version($server_version); 842 $self->server_cert($cert_data); 843 844 die "Wrong Server Version: $server_version\n" if $server_version != $SSLv2; 845 846 if ( length($cipher_spec) ) 847 { 848 $self->accepted_ciphers->add( Net::SSL::CipherSuites->new_by_cipher_spec_sslv2($cipher_spec) ); 849 $self->_ok(1); 850 } 851 852 return $self; 853 } ## end sub sslv2_server_hello 854 855 856=head2 parse_alert 857 858parse alert message 859 860=cut 861 862 863sub parse_alert 864 { 865 my $self = shift; 866 my $data = shift; 867 868 $self->alert(1); 869 870 $self->no_cipher_found(1) if $data eq "\x02\x28"; 871 872 # say "ALERT-ZEUG: " . _to_hex($data); 873 874 return $self; 875 } 876 877 8781; 879 880