package SPVM::IO::Socket::SSL; our $VERSION = "0.010"; 1; =head1 Name SPVM::IO::Socket::SSL - Sockets for SSL Communication. =head1 Description IO::Socket::SSL class in L<SPVM> represents sockets for SSL communication. =head1 Usage use IO::Socket::SSL; # Client my $host = "www.google.com"; my $port = 443; my $socket = IO::Socket::SSL->new({PeerAddr => $host, PeerPort => $port}); my $write_buffer = "GET / HTTP/1.0\r\nHost: $host\r\n\r\n"; $socket->write($write_buffer); my $read_buffer = (mutable string)new_string_len 100000; while (1) { my $read_length = $socket->read($read_buffer); if ($read_length < 0) { die "Read error"; } if ($read_length < length $read_buffer) { last; } } # Server my $server_socket = IO::Socket::SSL->new({ Listen => 10, }); my $accepted_socket = $server_socket->accept; =head1 Super Class L<IO::Socket::IP|SPVM::IO::Socket::IP> =head1 Fields =head2 ssl_ctx C<has ssl_ctx : ro L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX>;> A L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX> object. =head2 ssl C<has ssl : ro L<Net::SSLeay|SPVM::Net::SSLeay>;> A L<Net::SSLeay|SPVM::Net::SSLeay> object. This object is set after L</"connect_SSL"> method or L</"accept_SSL"> method succeeds. =head2 before_connect_SSL_cbs_list C<has before_connect_SSL_cbs_list : ro List of L<IO::Socket::SSL::Callback::BeforeConnectSSL|SPVM::IO::Socket::SSL::Callback::BeforeConnectSSL>;> A list of callbacks called before L</"connect_SSL"> method. =head2 before_accept_SSL_cbs_list C<has before_accept_SSL_cbs_list : ro List of L<IO::Socket::SSL::Callback::BeforeAcceptSSL|SPVM::IO::Socket::SSL::Callback::BeforeAcceptSSL>;> A list of callbacks called before L</"accept_SSL"> method. =head1 Constructor Options The following options are available adding to the options of its super class L<IO::Socket::IP|SPVM::IO::Socket::IP>. =head2 SSL_startHandshake Type: L<Int|SPVM::Int> Default: 1 It this option is a true value, L</"configure"> method calls L</"connect_SSL"> method for a client socket, and L</"accept"> method calls L</"accept_SSL">. =head2 SSL_verify_mode Type: L<Int|SPVM::Int> If L</"SSL_verify_mode"> option is not specified and the instance is a client socket, the option value is set to C<SSL_VERIFY_PEER>. L</"configure_SSL"> method calls L<set_verify|SPVM::Net::SSLeay::SSL_CTX#set_verify> method given the string specified by L</"SSL_verify_mode"> option, the callback specified by L</"SSL_verify_callback"> option. =head2 SSL_verify_callback Type: L<Net::SSLeay::Callback::Verify|SPVM::Net::SSLeay::Callback::Verify> See L</"SSL_verify_mode"> option. =head2 SSL_hostname Type: string This option only has effect in a client socket. If the string specified by L</"SSL_hostname"> option is not defined and the string specified by L<PeerAddr|IO::Socket::IP/"PeerAddr"> option does not represents an IP address, it is set to the string specified by L<PeerAddr|IO::Socket::IP/"PeerAddr"> option. If the string is a non-empty string, a callback that calls L<Net::SSLeay#set_tlsext_host_name|SPVM::Net::SSLeay/"set_tlsext_host_name"> method just before calling L</"connect_SSL"> is added. =head2 SSL_passwd_cb Type: L<Net::SSLeay::Callback::PemPassword|SPVM::Net::SSLeay::Callback::PemPassword> If the callback specified by this option is defined, L</"configure_SSL"> method calls L<Net::SSLeay::SSL_CTX#set_default_passwd_cb|SPVM::Net::SSLeay::SSL_CTX#set_default_passwd_cb> method given the callback. =head2 SSL_ca Type: L<Net::SSLeay::X509|SPVM::Net::SSLeay::X509>[] If the array specified by L</"SSL_ca"> option is defined, the certificates are added to the X509 store by calling L<Net::SSLeay::X509_STORE#add_cert|SPVM::Net::SSLeay::X509_STORE/"add_cert"> method repeatedly. Otherwise if the file name specified by L</"SSL_ca_file"> option or the path name specified by L</"SSL_ca_path"> option is defined, the locations are added by calling L<Net::SSLeay::SSL_CTX#load_verify_locations|SPVM::Net::SSLeay::SSL_CTX/"load_verify_locations"> method given the file name, the path name. Otherwise the default CA certificates are set by calling L<Net::SSLeay::SSL_CTX#set_default_verify_paths|SPVM::Net::SSLeay::SSL_CTX/"set_default_verify_paths"> or L<Net::SSLeay::SSL_CTX#set_default_verify_paths_windows|SPVM::Net::SSLeay::SSL_CTX/"set_default_verify_paths_windows"> in Windows. =head2 SSL_ca_file Type: string See L</"SSL_ca">. =head2 SSL_ca_path Type: string See L</"SSL_ca">. =head2 SSL_cert Type: L<Net::SSLeay::X509|SPVM::Net::SSLeay::X509>[] If the array specified by L</"SSL_cert"> option is defined, the first element is added as a certificate by calling L<Net::SSLeay::SSL_CTX#use_certificate|SPVM::Net::SSLeay::SSL_CTX/"use_certificate"> method and the rest elements are added as chain certificates using L<Net::SSLeay::SSL_CTX#add_extra_chain_cert|SPVM::Net::SSLeay::SSL_CTX/"add_extra_chain_cert"> method repeatedly. Otherwise if the file name specified by L</"SSL_cert_file"> option is defined, a certificate and chain certificates contained in the file are added by calling L<Net::SSLeay::SSL_CTX#use_certificate_chain_file|SPVM::Net::SSLeay::SSL_CTX/"use_certificate_chain_file"> method. =head2 SSL_cert_file Type: string See L</"SSL_cert"> =head2 SSL_key Type: L<Net::SSLeay::EVP_PKEY|SPVM::Net::SSLeay::EVP_PKEY> If the L<Net::SSLeay::EVP_PKEY|SPVM::Net::SSLeay::EVP_PKEY> object specified by L</"SSL_key"> option is defined, the object is added as a private key by calling L<Net::SSLeay::SSL_CTX#use_PrivateKey|SPVM::Net::SSLeay::SSL_CTX/"use_PrivateKey"> method. Otherwise if the file name specified by L</"SSL_key_file"> option is defined, the private key contained in the file is added by calling L<Net::SSLeay::SSL_CTX#use_PrivateKey_file|SPVM::Net::SSLeay::SSL_CTX/"use_PrivateKey_file"> method given the file name, C<SSL_FILETYPE_PEM>. =head2 SSL_key_file Type: string See L</"SSL_key">. =head2 SSL_check_crl Type: L<Int|SPVM::Int> The option value is a true value, C<X509_V_FLAG_CRL_CHECK> flag is set by calling L<Net::SSLeay::X509_VERIFY_PARAM#set_flags|SPVM::Net::SSLeay::X509_VERIFY_PARAM/"set_flags"> method. =head2 SSL_crl_file Type: string Adds all CRLs contained in the file specified by this option to the certificate store by calling L<Net::SSLeay::X509_STORE#add_crl|Net::SSLeay::X509_STORE/"add_crl"> method. =head2 SSL_alpn_protocols Type: string[] If the value of C<SSL_alpn_protocols> option is defined, performs the following logic. In client socket, calls L<Net::SSLeay::SSL_CTX#set_alpn_protos_with_protocols|SPVM::Net::SSLeay::SSL_CTX/"set_alpn_protos_with_protocols"> method given the option value. In server socket, calls L<Net::SSLeay::SSL_CTX#set_alpn_select_cb_with_protocols|SPVM::Net::SSLeay::SSL_CTX/"set_alpn_select_cb_with_protocols"> method given the option value. =head1 Class Methods =head2 new C<static method new : L<IO::Socket::SSL|SPVM::IO::Socket::SSL> ($options : object[] = undef);> Creates a new L<IO::Socket::SSL|SPVM::IO::Socket::SSL> object, calls L</"init"> method given the options $options, calls L</"configure"> method, and returns the new object. See L</"Constructor Options"> about $options. Note: If the value of L</"PeerAddr"> option is defined, a client socket is created. If the value of L</"Listen"> option is a positive value, a server socket is created. If the socket is a client socket and L</"PeerAddr"> is assumed to be a domain name, the domain name is used for SNI. If the socket is a client socket, the verify mode is set to L<SSL_VERIFY_PEER>. If L</"PeerAddr"> is assumed to be a domain name(Nor IPv4(Exactly match IPv4 pattern) and IPv6(Contains C<:>)), the host name verification is enabled by calling L<X509_VERIFY_PARAM#set1_host|SPVM::X509_VERIFY_PARAM/"set1_host"> method. C<X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS> is added to the host flags. The socket is set to non-blocking mode, but the L<goroutine scheduler|SPVM::Go> allows it to be treated as if it were synchronous. =head1 Instance Methods =head2 init C<protected method init : void ($options : object[] = undef);> Initialize the instance given the options $options. See L</"Constructor Options"> about $options. =head2 option_names C<protected method option_names : string[] ();> Returns available option names passed to L</"init"> method. =head2 configure C<protected method configure : void ();> Congigures the instance by the following logic. Calls L<configure|SPVM::IO::Socket::IP> method in the super class and calls L</"configure_SSL"> method. If the value of L</"SSL_startHandshake"> option is a true value and the instance is a client socket, calls L</"connect_SSL"> method. =head2 configure_SSL C<protected method configure_SSL : void ();> Creates a new L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX> object, configures the new L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX> using L<options|/"Constructor Options"> passed to L</"init"> method, and sets L</"ssl_ctx"> field to the new L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX> object. =head2 connect_SSL C<method connect_SSL : void ();> Creates a new L<Net::SSLeay|SPVM::Net::SSLeay> object, and connects the SSL connection by calling L<Net::SSLeay#connect|SPVM::Net::SSLeay/"connect"> method. If there are callbacks in L</"before_connect_SSL_cbs_list"> field, these callbacks are performed given the instance, the new L<Net::SSLeay|SPVM::Net::SSLeay> object before calling L<Net::SSLeay#connect|SPVM::Net::SSLeay/"connect"> method. If an IO wait occurs, the program jumps to the L<goroutine scheduler|SPVM::Go>, and retries this operation until it succeeds or the timeout seconds set by L<Timeout|SPVM::IO::Socket/"Timeout"> field expires. Exceptions: Exceptions thrown by L<Net::SSLeay#connect|SPVM::Net::SSLeay/"connect"> method could be thrown. If timeout occurs, an exception is thrown with C<eval_error_id> set to the basic type ID of L<Go::Error::IOTimeout|SPVM::Go::Error::IOTimeout>. =head2 accept_SSL C<method accept_SSL : void ();> Creates a new L<Net::SSLeay|SPVM::Net::SSLeay> object, and accepts the SSL connection by calling L<Net::SSLeay#accept|SPVM::Net::SSLeay/"accept"> method. If there are callbacks in L</"before_accept_SSL_cbs_list"> field, these callbacks are performed given the instance, the new L<Net::SSLeay|SPVM::Net::SSLeay> object before calling L<Net::SSLeay#accept|SPVM::Net::SSLeay/"accept"> method. If an IO wait occurs, the program jumps to the L<goroutine scheduler|SPVM::Go>, and retries this operation until it succeeds or the timeout seconds set by L<Timeout|SPVM::IO::Socket/"Timeout"> field expires. Exceptions: Exceptions thrown by L<Net::SSLeay#accept|SPVM::Net::SSLeay/"accept"> method could be thrown. If timeout occurs, an exception is thrown with C<eval_error_id> set to the basic type ID of L<Go::Error::IOTimeout|SPVM::Go::Error::IOTimeout>. =head2 accept C<method accept : L<IO::Socket::SSL|SPVM::IO::Socket::SSL> ($peer_ref : Sys::Socket::Sockaddr[] = undef);> Creates a new L<IO::Socket::SSL|SPVM::IO::Socket::SSL> object by calling L<accept|SPVM::IO::Socket::IP/"accept"> method in the super class. And sets the L</"ssl_ctx"> field in the new object to the value of L</"ssl_ctx"> field in the instance. And if the value of L</"SSL_startHandshake"> option is a true value, calls L</"accept_SSL"> method. And returns the new object. =head2 read C<method read : int ($buffer : mutable string, $length : int = -1, $offset : int = 0);> Reads the buffer $buffer at offset $offset to the length $length from the socket by calling L<Net::SSLeay#read|SPVM::Net::SSLeay/"read"> method. If an IO wait occurs, the program jumps to the L<goroutine scheduler|SPVM::Go>, and retries this operation until it succeeds or the timeout seconds set by L<Timeout|SPVM::IO::Socket/"Timeout"> field expires. Exceptions: Exceptions thrown by L<Net::SSLeay#read|SPVM::Net::SSLeay/"read"> method could be thrown. If timeout occurs, an exception is thrown with C<eval_error_id> set to the basic type ID of L<Go::Error::IOTimeout|SPVM::Go::Error::IOTimeout>. =head2 write C<method write : int ($buffer : string, $length : int = -1, $offset : int = 0);> Writes the buffer $buffer at offset $offset to the length $length to the socket by calling L<Net::SSLeay#write|SPVM::Net::SSLeay/"write"> method. If an IO wait occurs, the program jumps to the L<goroutine scheduler|SPVM::Go>, and retries this operation until it succeeds or the timeout seconds set by L<Timeout|SPVM::IO::Socket/"Timeout"> field expires. Exceptions: Exceptions thrown by L<Net::SSLeay#write|SPVM::Net::SSLeay/"write"> method could be thrown. If timeout occurs, an exception is thrown with C<eval_error_id> set to the basic type ID of L<Go::Error::IOTimeout|SPVM::Go::Error::IOTimeout>. =head2 shutdown_SSL C<method shutdown_SSL : int ();> Shutdowns the SSL connection by calling L<Net::SSLeay#shutdown|SPVM::Net::SSLeay/"shutdown"> method. If an IO wait occurs, the program jumps to the L<goroutine scheduler|SPVM::Go>, and retries this operation until it succeeds or the timeout seconds set by L<Timeout|SPVM::IO::Socket/"Timeout"> field expires. Exceptions: Exceptions thrown by L<Net::SSLeay#shutdown|SPVM::Net::SSLeay/"shutdown"> method could be thrown. If timeout occurs, an exception is thrown with C<eval_error_id> set to the basic type ID of L<Go::Error::IOTimeout|SPVM::Go::Error::IOTimeout>. =head2 alpn_selected C<method alpn_selected : string ();> Calls L<Net::SSLeay#get0_alpn_selected_return_string|SPVM::Net::SSLeay/"get0_alpn_selected_return_string"> method and returns its return value. =head2 get_sslversion C<method get_sslversion : string ();> Calls L<Net::SSLeay#get_version|SPVM::Net::SSLeay/"get_version"> method given the value of L</"ssl"> field, and returns its return value. Exceptions: If the version number is unknown, an exception is thrown. =head2 get_sslversion_int C<method get_sslversion_int : int ();> Calls L<Net::SSLeay#version|SPVM::Net::SSLeay/"version"> method given the value of L</"ssl"> field, and returns its return value. =head2 get_cipher C<method get_cipher : string ();> Calls L<Net::SSLeay#get_cipher|SPVM::Net::SSLeay/"get_cipher"> method given the value of L</"ssl"> field, and returns its return value. Exceptions: Exceptions thrown by L<Net::SSLeay#get_cipher|SPVM::Net::SSLeay/"get_cipher"> method could be thrown. =head2 get_servername C<method get_servername : string ();> Calls L<Net::SSLeay#get_servername|SPVM::Net::SSLeay/"get_servername"> method given the value of L</"ssl"> field, the value of C<TLSEXT_NAMETYPE_host_name>, and returns its return value. Exceptions: Exceptions thrown by L<Net::SSLeay#get_servername|SPVM::Net::SSLeay/"get_servername"> method could be thrown. =head2 peer_certificate C<method peer_certificate : L<Net::SSLeay::X509|SPVM::Net::SSLeay::X509> ();> Calls L<Net::SSLeay#get_peer_certificate|SPVM::Net::SSLeay/"get_peer_certificate"> method given the value of L</"ssl"> field, and returns its return value. Exceptions: Exceptions thrown by L<Net::SSLeay#get1_peer_certificate|SPVM::Net::SSLeay/"get1_peer_certificate"> method could be thrown. =head2 peer_certificates C<method peer_certificates : L<Net::SSLeay::X509|SPVM::Net::SSLeay::X509>[];> Returns the array that contains a certificate and all chain certificates of the peer. If a certificate cannot be got, return an empty array. =head2 sock_certificate C<method sock_certificate : L<Net::SSLeay::X509|SPVM::Net::SSLeay::X509> ();> Calls L<Net::SSLeay#get_certificate|SPVM::Net::SSLeay/"get_certificate"> method given the value of L</"ssl"> field, and returns its return value. Exceptions: Exceptions thrown by L<Net::SSLeay#get_certificate|SPVM::Net::SSLeay/"get_certificate"> method could be thrown. =head2 add_before_connect_SSL_cb C<method add_before_connect_SSL_cb : void ($cb : L<IO::Socket::SSL::Callback::BeforeConnectSSL|SPVM::IO::Socket::SSL::Callback::BeforeConnectSSL>);> Adds the callback $cb to the end of the elements of L</"before_connect_SSL_cb_list"> field. =head2 add_before_accept_SSL_cb C<method add_before_accept_SSL_cb : void ($cb : L<IO::Socket::SSL::Callback::BeforeAcceptSSL|SPVM::IO::Socket::SSL::Callback::BeforeAcceptSSL>);> Adds the callback $cb to the end of the elements of L</"before_accept_SSL_cb_list"> field. =head2 dump_peer_certificate C<method dump_peer_certificate : string ();> Calls L<Net::SSLeay#dump_peer_certificate|SPVM::Net::SSLeay/"dump_peer_certificate"> method given the value of L</"ssl"> field, and returns its return value. Exceptions: Exceptions thrown by L<Net::SSLeay#dump_peer_certificate|SPVM::Net::SSLeay/"dump_peer_certificate"> method could be thrown. =head2 stat C<method stat : L<Sys::IO::Stat|SPVM::Sys::IO::Stat> ();> This method is not supported in L<IO::Socket::SSL|SPVM::IO::Socket::SSL>. Exceptions: An exception is thrown. =head2 send C<method send : int ($buffer : string, $flags : int = 0, $length : int = -1, $offset : int = 0);> This method is not supported in L<IO::Socket::SSL|SPVM::IO::Socket::SSL>. Exceptions: An exception is thrown. =head2 sendto C<method sendto : int ($buffer : string, $flags : int, $to : Sys::Socket::Sockaddr, $length : int = -1, $offset : int = 0);> This method is not supported in L<IO::Socket::SSL|SPVM::IO::Socket::SSL>. Exceptions: An exception is thrown. =head2 recv C<method recv : int ($buffer : mutable string, $length : int = -1, $flags : int = 0, $offset : int = 0);> This method is not supported in L<IO::Socket::SSL|SPVM::IO::Socket::SSL>. Exceptions: An exception is thrown. =head2 recvfrom C<method recvfrom : int ($buffer : mutable string, $length : int, $flags : int, $from_ref : Sys::Socket::Sockaddr[], $offset : int = 0);> This method is not supported in L<IO::Socket::SSL|SPVM::IO::Socket::SSL>. Exceptions: An exception is thrown. =head2 DESTROY C<method DESTROY : void ();> Shutdowns the SSL connection and closes the socket. Implementation: If the socket is opened, performs the following logic. If the SSL connection is established, calls L</"shutdown_SSL"> method. And closes the socket. =head1 FAQ =head2 How to customize L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX> object? Sets L</"SSL_startHandshake"> option to 0, gets a L<Net::SSLeay::SSL_CTX|SPVM::Net::SSLeay::SSL_CTX> object by L</"ssl_ctx"> getter, customizes it, and calls L</"connect_SSL"> method in a client or calls L</"accept_SSL"> method. Client: use Net::SSLeay::Constant as SSL; my $host = "www.google.com"; my $port = 443; my $socket = IO::Socket::SSL->new({PeerAddr => $host, PeerPort => $port, SSL_startHandshake => 0}); my $ssl_ctx = $socket->ssl_ctx; $ssl_ctx->set_min_proto_version(SSL->TLS1_1_VERSION); $socket->connect_SSL; my $ssl = $socket->ssl; Server: use Net::SSLeay::Constant as SSL; my $host = "www.google.com"; my $port = 443; my $socket = IO::Socket::SSL->new({Listen => 1, SSL_startHandshake => 0}); my $ssl_ctx = $socket->ssl_ctx; $ssl_ctx->set_min_proto_version(SSL->TLS1_1_VERSION); my $accepted_socket = $socket->accept; $accepted_socket->accept_SSL; =head2 How to create L<Net::SSLeay::X509|SPVM::Net::SSLeay::X509> objects for C<SSL_ca> option from the return value of L<Mozilla::CA#SSL_ca|SPVM::Mozilla::CA/"SSL_ca"> method? use Mozilla::CA; use Net::SSLeay::BIO; use Net::SSLeay::PEM; use List; my $ca_content = Mozilla::CA->SSL_ca; my $bio = Net::SSLeay::BIO->new; $bio->write($ca_content); my $cas_list = List->new(new Net::SSLeay::X509[0]); while (1) { my $ca = (Net::SSLeay::X509)undef; eval { $ca = Net::SSLeay::PEM->read_bio_X509($bio); } if ($@) { if (eval_error_id isa_error Net::SSLeay::Error::PEM_R_NO_START_LINE) { last; } else { die $@; } } $cas_list->push($ca); } my $cas = (Net::SSLeay::X509[])$cas_list->to_array; my $SSL_ca = $cas; =head1 See Also =over 2 =item * L<IO::Socket::IP|SPVM::IO::Socket::IP> =item * L<Net::SSLeay|SPVM::Net::SSLeay> =back =head1 Repository L<SPVM::IO::Socket::SSL - Github|https://github.com/yuki-kimoto/SPVM-IO-Socket-SSL> =head1 Author Yuki Kimoto C<kimoto.yuki@gmail.com> =head1 Copyright & License Copyright (c) 2024 Yuki Kimoto MIT License