summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Net/SSLeay.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Net/SSLeay.pm')
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Net/SSLeay.pm2610
1 files changed, 2610 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/Net/SSLeay.pm b/Master/tlpkg/tlperl/lib/Net/SSLeay.pm
new file mode 100755
index 00000000000..08a0ec30f6a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Net/SSLeay.pm
@@ -0,0 +1,2610 @@
+# Net::SSLeay.pm - Perl module for using Eric Young's implementation of SSL
+#
+# Copyright (c) 1996-2003 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
+# Copyright (C) 2005 Florian Ragwitz <rafl@debian.org>, All Rights Reserved.
+# Copyright (C) 2005 Mike McCauley <mikem@open.com.au>, All Rights Reserved.
+#
+# $Id$
+#
+# Version 1.04, 31.3.1999
+# 30.7.1999, Tracking OpenSSL-0.9.3a changes, --Sampo
+# 31.7.1999, version 1.05 --Sampo
+# 7.4.2001, fixed input error upon 0, OpenSSL-0.9.6a, version 1.06 --Sampo
+# 18.4.2001, added TLSv1 support by Stephen C. Koehler
+# <koehler@securecomputing.com>, version 1.07, --Sampo
+# 25.4.2001, 64 bit fixes by Marko Asplund <aspa@kronodoc.fi> --Sampo
+# 17.4.2001, more error codes from aspa --Sampo
+# 25.9.2001, added heaps and piles of newer OpenSSL auxiliary functions --Sampo
+# 6.11.2001, got rid of $p_errs madness --Sampo
+# 9.11.2001, added EGD (entropy gathering daemon) reference info --Sampo
+# 7.12.2001, Added proxy support by Bruno De Wolf <bruno.dewolf@@pandora._be>
+# 6.1.2002, cosmetic fix to socket options from Kwindla Hultman Kramer <kwindla@@allafrica_.com>
+# 25.3.2002, added post_https_cert and friends per patch from
+# mock@@obscurity.ogr, --Sampo
+# 3.4.2002, added `use bytes' from Marcus Taylor <marcus@@semantico_.com>
+# This avoids unicode/utf8 (as may appear in some XML docs)
+# from fooling the length comuptations. Dropped support for
+# perl5.005_03 because I do not have opportunity to test it. --Sampo
+# 5.4.2002, improved Unicode gotcha eliminator to support old perls --Sampo
+# 8.4.2002, added a small line end fix from Petr Dousa (pdousa@@kerio_.com)
+# 17.5.2002, Added BIO_s_mem, BIO_new, BIO_free, BIO_write, BIO_read
+# BIO_eof, BIO_pending, BIO_wpending, RSA_generate_key, RSA_free
+# --mikem@open._com.au
+# 10.8.2002, Added SSL_peek patch to ssl_read_until from
+# Peter Behroozi <peter@@fhpwireless_.com> --Sampo
+# 21.8.2002, Added SESSION_get_master_key, SSL_get_client_random, SSL_get_server_random
+# --mikem@open.com_.au
+# 2.9.2002, Added SSL_CTX_get_cert_store, X509_STORE_add_cert, X509_STORE_add_crl
+# X509_STORE_set_flags, X509_load_cert_file, X509_load_crl_file
+# X509_load_cert_crl_file, PEM_read_bio_X509_CRL,
+# constants for X509_V_FLAG_* in order to support certificate revocation lists.
+# --mikem@open.com_.au
+# 6.9.2002, fixed X509_STORE_set_flags to X509_STORE_CTX_set_flags, --Sampo
+# 19.9.2002, applied patch from Tim Engler <tim@burntcouch_.com>
+# 18.2.2003, applied patch from Toni Andjelkovic <toni@soth._at>
+# 13.6.2003, partially applied leak patch by Marian Jancar <mjancar@suse._cz>
+# 25.6.2003, write_partial() return value patch from
+# Kim Minh Kaplan <kmkaplan@selfoffice._com>
+# 17.8.2003, added http support :-) --Sampo
+# 17.8.2003, started 1.25 dev --Sampo
+# 30.11.2005, Applied a patch by Peter Behroozi that adds get1_session() for session caching --Florian
+# 30.11.2005, Applied a patch by ex8k-hbn@asahi-net.or.jp that limits the chunk size for tcp_read_all --Florian
+# 30.11.2005, Applied a patch by ivan-cpan-rt@420.am that avoids adding a Host header if an own is specified in do_httpx3
+# 13.12.2005, Added comments re thread safety and resetting of default_passwd_callback after use
+# --mikem@open.com.au
+#
+# The distribution and use of this module are subject to the conditions
+# listed in LICENSE file at the root of OpenSSL-0.9.7b
+# distribution (i.e. free, but mandatory attribution and NO WARRANTY).
+
+package Net::SSLeay;
+
+use strict;
+use Carp;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD $CRLF);
+use Socket;
+use Errno;
+
+require Exporter;
+use AutoLoader;
+
+# 0=no warns, 1=only errors, 2=ciphers, 3=progress, 4=dump data
+$Net::SSLeay::trace = 0; # Do not change here, use
+ # $Net::SSLeay::trace = [1-4] in caller
+
+# 2 = insist on v2 SSL protocol
+# 3 = insist on v3 SSL
+# 10 = insist on TLSv1
+# 0 or undef = guess (v23)
+#
+$Net::SSLeay::ssl_version = 0; # don't change here, use
+ # Net::SSLeay::version=[2,3,0] in caller
+
+#define to enable the "cat /proc/$$/stat" stuff
+$Net::SSLeay::linux_debug = 0;
+
+# Number of seconds to sleep after sending message and before half
+# closing connection. Useful with antiquated broken servers.
+$Net::SSLeay::slowly = 0;
+
+# RANDOM NUMBER INITIALIZATION
+#
+# Edit to your taste. Using /dev/random would be more secure, but may
+# block if randomness is not available, thus the default is
+# /dev/urandom. $how_random determines how many bits of randomness to take
+# from the device. You should take enough (read SSLeay/doc/rand), but
+# beware that randomness is limited resource so you should not waste
+# it either or you may end up with randomness depletion (situation where
+# /dev/random would block and /dev/urandom starts to return predictable
+# numbers).
+#
+# N.B. /dev/urandom does not exit on all systems, such as Solaris 2.6. In that
+# case you should get a third party package that emulates /dev/urandom
+# (e.g. via named pipe) or supply a random number file. Some such
+# packages are documented in Caveat section of the POD documentation.
+
+$Net::SSLeay::random_device = '/dev/urandom';
+$Net::SSLeay::how_random = 512;
+
+$VERSION = '1.35';
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(
+ AT_MD5_WITH_RSA_ENCRYPTION
+ CB_ACCEPT_EXIT
+ CB_ACCEPT_LOOP
+ CB_CONNECT_EXIT
+ CB_CONNECT_LOOP
+ CK_DES_192_EDE3_CBC_WITH_MD5
+ CK_DES_192_EDE3_CBC_WITH_SHA
+ CK_DES_64_CBC_WITH_MD5
+ CK_DES_64_CBC_WITH_SHA
+ CK_DES_64_CFB64_WITH_MD5_1
+ CK_IDEA_128_CBC_WITH_MD5
+ CK_NULL
+ CK_NULL_WITH_MD5
+ CK_RC2_128_CBC_EXPORT40_WITH_MD5
+ CK_RC2_128_CBC_WITH_MD5
+ CK_RC4_128_EXPORT40_WITH_MD5
+ CK_RC4_128_WITH_MD5
+ CLIENT_VERSION
+ ERROR_NONE
+ ERROR_SSL
+ ERROR_SYSCALL
+ ERROR_WANT_CONNECT
+ ERROR_WANT_READ
+ ERROR_WANT_WRITE
+ ERROR_WANT_X509_LOOKUP
+ ERROR_ZERO_RETURN
+ CT_X509_CERTIFICATE
+ FILETYPE_ASN1
+ FILETYPE_PEM
+ F_CLIENT_CERTIFICATE
+ F_CLIENT_HELLO
+ F_CLIENT_MASTER_KEY
+ F_D2I_SSL_SESSION
+ F_GET_CLIENT_FINISHED
+ F_GET_CLIENT_HELLO
+ F_GET_CLIENT_MASTER_KEY
+ F_GET_SERVER_FINISHED
+ F_GET_SERVER_HELLO
+ F_GET_SERVER_VERIFY
+ F_I2D_SSL_SESSION
+ F_READ_N
+ F_REQUEST_CERTIFICATE
+ F_SERVER_HELLO
+ F_SSL_ACCEPT
+ F_SSL_CERT_NEW
+ F_SSL_CONNECT
+ F_SSL_ENC_DES_CBC_INIT
+ F_SSL_ENC_DES_CFB_INIT
+ F_SSL_ENC_DES_EDE3_CBC_INIT
+ F_SSL_ENC_IDEA_CBC_INIT
+ F_SSL_ENC_NULL_INIT
+ F_SSL_ENC_RC2_CBC_INIT
+ F_SSL_ENC_RC4_INIT
+ F_SSL_GET_NEW_SESSION
+ F_SSL_MAKE_CIPHER_LIST
+ F_SSL_NEW
+ F_SSL_READ
+ F_SSL_RSA_PRIVATE_DECRYPT
+ F_SSL_RSA_PUBLIC_ENCRYPT
+ F_SSL_SESSION_NEW
+ F_SSL_SESSION_PRINT_FP
+ F_SSL_SET_CERTIFICATE
+ F_SSL_SET_FD
+ F_SSL_SET_RFD
+ F_SSL_SET_WFD
+ F_SSL_STARTUP
+ F_SSL_USE_CERTIFICATE
+ F_SSL_USE_CERTIFICATE_ASN1
+ F_SSL_USE_CERTIFICATE_FILE
+ F_SSL_USE_PRIVATEKEY
+ F_SSL_USE_PRIVATEKEY_ASN1
+ F_SSL_USE_PRIVATEKEY_FILE
+ F_SSL_USE_RSAPRIVATEKEY
+ F_SSL_USE_RSAPRIVATEKEY_ASN1
+ F_SSL_USE_RSAPRIVATEKEY_FILE
+ F_WRITE_PENDING
+ GEN_OTHERNAME
+ GEN_EMAIL
+ GEN_DNS
+ GEN_X400
+ GEN_DIRNAME
+ GEN_EDIPARTY
+ GEN_URI
+ GEN_IPADD
+ GEN_RID
+ MAX_MASTER_KEY_LENGTH_IN_BITS
+ MAX_RECORD_LENGTH_2_BYTE_HEADER
+ MAX_RECORD_LENGTH_3_BYTE_HEADER
+ MAX_SSL_SESSION_ID_LENGTH_IN_BYTES
+ MIN_RSA_MODULUS_LENGTH_IN_BYTES
+ MT_CLIENT_CERTIFICATE
+ MT_CLIENT_FINISHED
+ MT_CLIENT_HELLO
+ MT_CLIENT_MASTER_KEY
+ MT_ERROR
+ MT_REQUEST_CERTIFICATE
+ MT_SERVER_FINISHED
+ MT_SERVER_HELLO
+ MT_SERVER_VERIFY
+ NOTHING
+ NID_undef
+ NID_algorithm
+ NID_rsadsi
+ NID_pkcs
+ NID_md2
+ NID_md5
+ NID_rc4
+ NID_rsaEncryption
+ NID_md2WithRSAEncryption
+ NID_md5WithRSAEncryption
+ NID_pbeWithMD2AndDES_CBC
+ NID_pbeWithMD5AndDES_CBC
+ NID_X500
+ NID_X509
+ NID_commonName
+ NID_countryName
+ NID_localityName
+ NID_stateOrProvinceName
+ NID_organizationName
+ NID_organizationalUnitName
+ NID_rsa
+ NID_pkcs7
+ NID_pkcs7_data
+ NID_pkcs7_signed
+ NID_pkcs7_enveloped
+ NID_pkcs7_signedAndEnveloped
+ NID_pkcs7_digest
+ NID_pkcs7_encrypted
+ NID_pkcs3
+ NID_dhKeyAgreement
+ NID_des_ecb
+ NID_des_cfb64
+ NID_des_cbc
+ NID_des_ede
+ NID_des_ede3
+ NID_idea_cbc
+ NID_idea_cfb64
+ NID_idea_ecb
+ NID_rc2_cbc
+ NID_rc2_ecb
+ NID_rc2_cfb64
+ NID_rc2_ofb64
+ NID_sha
+ NID_shaWithRSAEncryption
+ NID_des_ede_cbc
+ NID_des_ede3_cbc
+ NID_des_ofb64
+ NID_idea_ofb64
+ NID_pkcs9
+ NID_pkcs9_emailAddress
+ NID_pkcs9_unstructuredName
+ NID_pkcs9_contentType
+ NID_pkcs9_messageDigest
+ NID_pkcs9_signingTime
+ NID_pkcs9_countersignature
+ NID_pkcs9_challengePassword
+ NID_pkcs9_unstructuredAddress
+ NID_pkcs9_extCertAttributes
+ NID_netscape
+ NID_netscape_cert_extension
+ NID_netscape_data_type
+ NID_des_ede_cfb64
+ NID_des_ede3_cfb64
+ NID_des_ede_ofb64
+ NID_des_ede3_ofb64
+ NID_sha1
+ NID_sha1WithRSAEncryption
+ NID_dsaWithSHA
+ NID_dsa_2
+ NID_pbeWithSHA1AndRC2_CBC
+ NID_id_pbkdf2
+ NID_dsaWithSHA1_2
+ NID_netscape_cert_type
+ NID_netscape_base_url
+ NID_netscape_revocation_url
+ NID_netscape_ca_revocation_url
+ NID_netscape_renewal_url
+ NID_netscape_ca_policy_url
+ NID_netscape_ssl_server_name
+ NID_netscape_comment
+ NID_netscape_cert_sequence
+ NID_desx_cbc
+ NID_id_ce
+ NID_subject_key_identifier
+ NID_key_usage
+ NID_private_key_usage_period
+ NID_subject_alt_name
+ NID_issuer_alt_name
+ NID_basic_constraints
+ NID_crl_number
+ NID_certificate_policies
+ NID_authority_key_identifier
+ NID_bf_cbc
+ NID_bf_ecb
+ NID_bf_cfb64
+ NID_bf_ofb64
+ NID_mdc2
+ NID_mdc2WithRSA
+ NID_rc4_40
+ NID_rc2_40_cbc
+ NID_givenName
+ NID_surname
+ NID_initials
+ NID_uniqueIdentifier
+ NID_crl_distribution_points
+ NID_md5WithRSA
+ NID_serialNumber
+ NID_title
+ NID_description
+ NID_cast5_cbc
+ NID_cast5_ecb
+ NID_cast5_cfb64
+ NID_cast5_ofb64
+ NID_pbeWithMD5AndCast5_CBC
+ NID_dsaWithSHA1
+ NID_md5_sha1
+ NID_sha1WithRSA
+ NID_dsa
+ NID_ripemd160
+ NID_ripemd160WithRSA
+ NID_rc5_cbc
+ NID_rc5_ecb
+ NID_rc5_cfb64
+ NID_rc5_ofb64
+ NID_rle_compression
+ NID_zlib_compression
+ NID_ext_key_usage
+ NID_id_pkix
+ NID_id_kp
+ NID_server_auth
+ NID_client_auth
+ NID_code_sign
+ NID_email_protect
+ NID_time_stamp
+ NID_ms_code_ind
+ NID_ms_code_com
+ NID_ms_ctl_sign
+ NID_ms_sgc
+ NID_ms_efs
+ NID_ns_sgc
+ NID_delta_crl
+ NID_crl_reason
+ NID_invalidity_date
+ NID_sxnet
+ NID_pbe_WithSHA1And128BitRC4
+ NID_pbe_WithSHA1And40BitRC4
+ NID_pbe_WithSHA1And3_Key_TripleDES_CBC
+ NID_pbe_WithSHA1And2_Key_TripleDES_CBC
+ NID_pbe_WithSHA1And128BitRC2_CBC
+ NID_pbe_WithSHA1And40BitRC2_CBC
+ NID_keyBag
+ NID_pkcs8ShroudedKeyBag
+ NID_certBag
+ NID_crlBag
+ NID_secretBag
+ NID_safeContentsBag
+ NID_friendlyName
+ NID_localKeyID
+ NID_x509Certificate
+ NID_sdsiCertificate
+ NID_x509Crl
+ NID_pbes2
+ NID_pbmac1
+ NID_hmacWithSHA1
+ NID_id_qt_cps
+ NID_id_qt_unotice
+ NID_rc2_64_cbc
+ NID_SMIMECapabilities
+ NID_pbeWithMD2AndRC2_CBC
+ NID_pbeWithMD5AndRC2_CBC
+ NID_pbeWithSHA1AndDES_CBC
+ NID_ms_ext_req
+ NID_ext_req
+ NID_name
+ NID_dnQualifier
+ NID_id_pe
+ NID_id_ad
+ NID_info_access
+ NID_ad_OCSP
+ NID_ad_ca_issuers
+ NID_OCSP_sign
+ OPENSSL_VERSION_NUMBER
+ PE_BAD_CERTIFICATE
+ PE_NO_CERTIFICATE
+ PE_NO_CIPHER
+ PE_UNSUPPORTED_CERTIFICATE_TYPE
+ READING
+ RWERR_BAD_MAC_DECODE
+ RWERR_BAD_WRITE_RETRY
+ RWERR_INTERNAL_ERROR
+ R_BAD_AUTHENTICATION_TYPE
+ R_BAD_CHECKSUM
+ R_BAD_MAC_DECODE
+ R_BAD_RESPONSE_ARGUMENT
+ R_BAD_SSL_FILETYPE
+ R_BAD_SSL_SESSION_ID_LENGTH
+ R_BAD_STATE
+ R_BAD_WRITE_RETRY
+ R_CHALLENGE_IS_DIFFERENT
+ R_CIPHER_CODE_TOO_LONG
+ R_CIPHER_TABLE_SRC_ERROR
+ R_CONECTION_ID_IS_DIFFERENT
+ R_INVALID_CHALLENGE_LENGTH
+ R_NO_CERTIFICATE_SET
+ R_NO_CERTIFICATE_SPECIFIED
+ R_NO_CIPHER_LIST
+ R_NO_CIPHER_MATCH
+ R_NO_CIPHER_WE_TRUST
+ R_NO_PRIVATEKEY
+ R_NO_PUBLICKEY
+ R_NO_READ_METHOD_SET
+ R_NO_WRITE_METHOD_SET
+ R_NULL_SSL_CTX
+ R_PEER_DID_NOT_RETURN_A_CERTIFICATE
+ R_PEER_ERROR
+ R_PEER_ERROR_CERTIFICATE
+ R_PEER_ERROR_NO_CIPHER
+ R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
+ R_PERR_ERROR_NO_CERTIFICATE
+ R_PUBLIC_KEY_ENCRYPT_ERROR
+ R_PUBLIC_KEY_IS_NOT_RSA
+ R_PUBLIC_KEY_NO_RSA
+ R_READ_WRONG_PACKET_TYPE
+ R_REVERSE_KEY_ARG_LENGTH_IS_WRONG
+ R_REVERSE_MASTER_KEY_LENGTH_IS_WRONG
+ R_REVERSE_SSL_SESSION_ID_LENGTH_IS_WRONG
+ R_SHORT_READ
+ R_SSL_SESSION_ID_IS_DIFFERENT
+ R_UNABLE_TO_EXTRACT_PUBLIC_KEY
+ R_UNDEFINED_INIT_STATE
+ R_UNKNOWN_REMOTE_ERROR_TYPE
+ R_UNKNOWN_STATE
+ R_UNSUPORTED_CIPHER
+ R_WRONG_PUBLIC_KEY_TYPE
+ R_X509_LIB
+ RSA_3
+ RSA_F4
+ SERVER_VERSION
+ SESSION
+ SESSION_ASN1_VERSION
+ ST_ACCEPT
+ ST_BEFORE
+ ST_CLIENT_START_ENCRYPTION
+ ST_CONNECT
+ ST_GET_CLIENT_FINISHED_A
+ ST_GET_CLIENT_FINISHED_B
+ ST_GET_CLIENT_HELLO_A
+ ST_GET_CLIENT_HELLO_B
+ ST_GET_CLIENT_MASTER_KEY_A
+ ST_GET_CLIENT_MASTER_KEY_B
+ ST_GET_SERVER_FINISHED_A
+ ST_GET_SERVER_FINISHED_B
+ ST_GET_SERVER_HELLO_A
+ ST_GET_SERVER_HELLO_B
+ ST_GET_SERVER_VERIFY_A
+ ST_GET_SERVER_VERIFY_B
+ ST_INIT
+ ST_OK
+ ST_READ_BODY
+ ST_READ_HEADER
+ ST_SEND_CLIENT_CERTIFICATE_A
+ ST_SEND_CLIENT_CERTIFICATE_B
+ ST_SEND_CLIENT_CERTIFICATE_C
+ ST_SEND_CLIENT_CERTIFICATE_D
+ ST_SEND_CLIENT_FINISHED_A
+ ST_SEND_CLIENT_FINISHED_B
+ ST_SEND_CLIENT_HELLO_A
+ ST_SEND_CLIENT_HELLO_B
+ ST_SEND_CLIENT_MASTER_KEY_A
+ ST_SEND_CLIENT_MASTER_KEY_B
+ ST_SEND_REQUEST_CERTIFICATE_A
+ ST_SEND_REQUEST_CERTIFICATE_B
+ ST_SEND_REQUEST_CERTIFICATE_C
+ ST_SEND_REQUEST_CERTIFICATE_D
+ ST_SEND_SERVER_FINISHED_A
+ ST_SEND_SERVER_FINISHED_B
+ ST_SEND_SERVER_HELLO_A
+ ST_SEND_SERVER_HELLO_B
+ ST_SEND_SERVER_VERIFY_A
+ ST_SEND_SERVER_VERIFY_B
+ ST_SERVER_START_ENCRYPTION
+ ST_X509_GET_CLIENT_CERTIFICATE
+ ST_X509_GET_SERVER_CERTIFICATE
+ TXT_DES_192_EDE3_CBC_WITH_MD5
+ TXT_DES_192_EDE3_CBC_WITH_SHA
+ TXT_DES_64_CBC_WITH_MD5
+ TXT_DES_64_CBC_WITH_SHA
+ TXT_DES_64_CFB64_WITH_MD5_1
+ TXT_IDEA_128_CBC_WITH_MD5
+ TXT_NULL
+ TXT_NULL_WITH_MD5
+ TXT_RC2_128_CBC_EXPORT40_WITH_MD5
+ TXT_RC2_128_CBC_WITH_MD5
+ TXT_RC4_128_EXPORT40_WITH_MD5
+ TXT_RC4_128_WITH_MD5
+ VERIFY_CLIENT_ONCE
+ VERIFY_FAIL_IF_NO_PEER_CERT
+ VERIFY_NONE
+ VERIFY_PEER
+ WRITING
+ X509_LOOKUP
+ X509_V_FLAG_CB_ISSUER_CHECK
+ X509_V_FLAG_USE_CHECK_TIME
+ X509_V_FLAG_CRL_CHECK
+ X509_V_FLAG_CRL_CHECK_ALL
+ X509_V_FLAG_IGNORE_CRITICAL
+ CTX_new
+ CTX_v2_new
+ CTX_v3_new
+ CTX_v23_new
+ CTX_free
+ new
+ free
+ accept
+ clear
+ connect
+ set_fd
+ set_rfd
+ set_wfd
+ get_fd
+ read
+ write
+ peek
+ use_RSAPrivateKey
+ use_RSAPrivateKey_ASN1
+ use_RSAPrivateKey_file
+ CTX_use_RSAPrivateKey_file
+ use_PrivateKey
+ use_PrivateKey_ASN1
+ use_PrivateKey_file
+ use_certificate
+ use_certificate_ASN1
+ use_certificate_file
+ CTX_use_certificate_file
+ load_error_strings
+ ERR_load_SSL_strings
+ ERR_load_RAND_strings
+ state_string
+ rstate_string
+ state_string_long
+ rstate_string_long
+ get_time
+ set_time
+ get_timeout
+ set_timeout
+ copy_session_id
+ set_read_ahead
+ get_read_ahead
+ pending
+ get_cipher_list
+ set_cipher_list
+ get_cipher
+ get_shared_ciphers
+ get_peer_certificate
+ set_verify
+ flush_sessions
+ set_bio
+ get_rbio
+ get_wbio
+ SESSION_new
+ SESSION_print
+ SESSION_free
+ i2d_SSL_SESSION
+ set_session
+ add_session
+ remove_session
+ d2i_SSL_SESSION
+ BIO_f_ssl
+ BIO_new
+ BIO_new_file
+ BIO_s_mem
+ BIO_free
+ BIO_read
+ BIO_write
+ BIO_eof
+ BIO_pending
+ BIO_wpending
+ ERR_get_error
+ ERR_error_string
+ err
+ clear_error
+ X509_get_issuer_name
+ X509_get_subject_name
+ X509_NAME_oneline
+ X509_NAME_get_text_by_NID
+ CTX_get_cert_store
+ X509_STORE_add_cert
+ X509_STORE_add_crl
+ X509_STORE_CTX_set_flags
+ X509_load_cert_file
+ X509_load_crl_file
+ X509_load_cert_crl_file
+ PEM_read_bio_X509_CRL
+ die_if_ssl_error
+ die_now
+ print_errs
+ set_cert_and_key
+ set_server_cert_and_key
+ make_form
+ make_headers
+ do_https
+ get_https
+ post_https
+ get_https4
+ post_https4
+ sslcat
+ ssl_read_CRLF
+ ssl_read_all
+ ssl_read_until
+ ssl_write_CRLF
+ ssl_write_all
+ get_http
+ post_http
+ get_httpx
+ post_httpx
+ get_https3
+ post_https3
+ get_http4
+ post_http4
+ get_httpx4
+ post_httpx4
+ tcpcat
+ tcpxcat
+ tcp_read_CRLF
+ tcp_read_all
+ tcp_read_until
+ tcp_write_CRLF
+ tcp_write_all
+ dump_peer_certificate
+ RSA_generate_key
+ RSA_free
+ X509_free
+ SESSION_get_master_key
+ get_client_random
+ get_server_random
+);
+
+sub AUTOLOAD {
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my $constname;
+ ($constname = $AUTOLOAD) =~ s/.*:://;
+ my $val = constant($constname);
+ if ($! != 0) {
+ if ($! =~ /((Invalid)|(not valid))/i || $!{EINVAL}) {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else {
+ croak "Your vendor has not defined SSLeay macro $constname";
+ }
+ }
+ eval "sub $AUTOLOAD { $val }";
+ goto &$AUTOLOAD;
+}
+
+eval {
+ require XSLoader;
+ XSLoader::load('Net::SSLeay', $VERSION);
+ 1;
+} or do {
+ require DynaLoader;
+ push @ISA, 'DynaLoader';
+ bootstrap Net::SSLeay $VERSION;
+};
+
+# Preloaded methods go here.
+
+$CRLF = "\x0d\x0a"; # because \r\n is not fully portable
+
+### Print SSLeay error stack
+
+sub print_errs {
+ my ($msg) = @_;
+ my ($count, $err, $errs, $e) = (0,0,'');
+ while ($err = ERR_get_error()) {
+ $count ++;
+ $e = "$msg $$: $count - " . ERR_error_string($err) . "\n";
+ $errs .= $e;
+ warn $e if $Net::SSLeay::trace;
+ }
+ return $errs;
+}
+
+# Death is conditional to SSLeay errors existing, i.e. this function checks
+# for errors and only dies in affirmative.
+# usage: Net::SSLeay::write($ssl, "foo") or die_if_ssl_error("SSL write ($!)");
+
+sub die_if_ssl_error {
+ my ($msg) = @_;
+ die "$$: $msg\n" if print_errs($msg);
+}
+
+# Unconditional death. Used to print SSLeay errors before dying.
+# usage: Net::SSLeay::connect($ssl) or die_now("Failed SSL connect ($!)");
+
+sub die_now {
+ my ($msg) = @_;
+ print_errs($msg);
+ die "$$: $msg\n";
+}
+
+# Perl 5.6.* unicode support causes that length() no longer reliably
+# reflects the byte length of a string. This eval is to fix that.
+# Thanks to Sean Burke for the snippet.
+
+BEGIN{
+eval 'use bytes; sub blength ($) { length $_[0] }';
+$@ and eval ' sub blength ($) { length $_[0] }' ;
+}
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+1;
+__END__
+# Documentation. Use `perl-root/pod/pod2html SSLeay.pm` to output html
+
+=head1 NAME
+
+Net::SSLeay - Perl extension for using OpenSSL
+
+=head1 SYNOPSIS
+
+ use Net::SSLeay qw(get_https post_https sslcat make_headers make_form);
+
+ ($page) = get_https('www.bacus.pt', 443, '/'); # 1
+
+ ($page, $response, %reply_headers)
+ = get_https('www.bacus.pt', 443, '/', # 2
+ make_headers(User-Agent => 'Cryptozilla/5.0b1',
+ Referer => 'https://www.bacus.pt'
+ ));
+
+ ($page, $result, %headers) = # 2b
+ = get_https('www.bacus.pt', 443, '/protected.html',
+ make_headers(Authorization =>
+ 'Basic ' . MIME::Base64::encode("$user:$pass",''))
+ );
+
+ ($page, $response, %reply_headers)
+ = post_https('www.bacus.pt', 443, '/foo.cgi', '', # 3
+ make_form(OK => '1',
+ name => 'Sampo'
+ ));
+
+ $reply = sslcat($host, $port, $request); # 4
+
+ ($reply, $err, $server_cert) = sslcat($host, $port, $request); # 5
+
+ $Net::SSLeay::trace = 2; # 0=no debugging, 1=ciphers, 2=trace, 3=dump data
+
+=head1 DESCRIPTION
+
+There is a related module called C<Net::SSLeay::Handle> included in this
+distribution that you might want to use instead. It has its own pod
+documentation.
+
+This module offers some high level convinience functions for accessing
+web pages on SSL servers (for symmetry, same API is offered for
+accessing http servers, too), a C<sslcat()> function for writing your own
+clients, and finally access to the SSL api of SSLeay/OpenSSL package
+so you can write servers or clients for more complicated applications.
+
+For high level functions it is most convinient to import them to your
+main namespace as indicated in the synopsis.
+
+Case 1 demonstrates typical invocation of get_https() to fetch an HTML
+page from secure server. The first argument provides host name or ip
+in dotted decimal notation of the remote server to contact. Second
+argument is the TCP port at the remote end (your own port is picked
+arbitrarily from high numbered ports as usual for TCP). The third
+argument is the URL of the page without the host name part. If in
+doubt consult HTTP specifications at L<http://www.w3c.org>.
+
+Case 2 demonstrates full fledged use of C<get_https()>. As can be seen,
+C<get_https()> parses the response and response headers and returns them as
+a list, which can be captured in a hash for later reference. Also a
+fourth argument to C<get_https()> is used to insert some additional headers
+in the request. C<make_headers()> is a function that will convert a list or
+hash to such headers. By default C<get_https()> supplies C<Host> (make virtual
+hosting easy) and C<Accept> (reportedly needed by IIS) headers.
+
+Case 2b demonstrates how to get password protected page. Refer to
+HTTP protocol specifications for further details (e.g. RFC-2617).
+
+Case 3 invokes C<post_https()> to submit a HTML/CGI form to secure
+server. First four arguments are equal to C<get_https()> (note that empty
+string (C<''>) is passed as header argument). The fifth argument is the
+contents of the form formatted according to CGI specification. In this
+case the helper function C<make_https()> is used to do the formatting,
+but you could pass any string. The C<post_https()> automatically adds
+C<Content-Type> and C<Content-Length> headers to the request.
+
+Case 4 shows the fundamental C<sslcat()> function (inspired in spirit by
+C<netcat> utility :-). Its your swiss army knife that allows you to
+easily contact servers, send some data, and then get the response. You
+are responsible for formatting the data and parsing the response -
+C<sslcat()> is just a transport.
+
+Case 5 is a full invocation of C<sslcat()> which allows return of errors
+as well as the server (peer) certificate.
+
+The C<$trace> global variable can be used to control the verbosity of high
+level functions. Level 0 guarantees silence, level 1 (the default)
+only emits error messages.
+
+=head2 Alternate versions of the API
+
+The above mentioned functions actually return the response headers as
+a list, which only gets converted to hash upon assignment (this
+assignment looses information if the same header occurs twice, as may
+be the case with cookies). There are also other variants of the
+functions that return unprocessed headers and that return a reference
+to a hash.
+
+ ($page, $response, @headers) = get_https('www.bacus.pt', 443, '/');
+ for ($i = 0; $i < $#headers; $i+=2) {
+ print "$headers[$i] = " . $headers[$i+1] . "\n";
+ }
+
+ ($page, $response, $headers, $server_cert)
+ = get_https3('www.bacus.pt', 443, '/');
+ print "$headers\n";
+
+ ($page, $response, %headers_ref, $server_cert)
+ = get_https4('www.bacus.pt', 443, '/');
+ for $k (sort keys %{headers_ref}) {
+ for $v (@{$headers_ref{$k}}) {
+ print "$k = $v\n";
+ }
+ }
+
+All of the above code fragments accomplish the same thing: display all
+values of all headers. The API functions ending in "3" return the
+headers simply as a scalar string and it is up to the application to
+split them up. The functions ending in "4" return a reference to
+hash of arrays (see L<perlref> and L<perllol> if you are
+not familiar with complex perl data structures). To access single value
+of such header hash you would do something like
+
+ print $headers_ref{COOKIE}[0];
+
+The variants 3 and 4 also allow you to discover the server certificate
+in case you would like to store or display it, e.g.
+
+ ($p, $resp, $hdrs, $server_cert) = get_https3('www.bacus.pt', 443, '/');
+ if (!defined($server_cert) || ($server_cert == 0)) {
+ warn "Subject Name: undefined, Issuer Name: undefined";
+ } else {
+ warn 'Subject Name: '
+ . Net::SSLeay::X509_NAME_oneline(
+ Net::SSLeay::X509_get_subject_name($server_cert))
+ . 'Issuer Name: '
+ . Net::SSLeay::X509_NAME_oneline(
+ Net::SSLeay::X509_get_issuer_name($server_cert));
+ }
+
+Beware that this method only allows after the fact verification of
+the certificate: by the time C<get_https3()> has returned the https
+request has already been sent to the server, whether you decide to
+tryst it or not. To do the verification correctly you must either
+employ the OpenSSL certificate verification framework or use
+the lower level API to first connect and verify the certificate
+and only then send the http data. See implementation of C<ds_https3()>
+for guidance on how to do this.
+
+=head2 Using client certificates
+
+Secure web communications are encrypted using symmetric crypto keys
+exchanged using encryption based on the certificate of the
+server. Therefore in all SSL connections the server must have a
+certificate. This serves both to authenticate the server to the
+clients and to perform the key exchange.
+
+Sometimes it is necessary to authenticate the client as well. Two
+options are available: HTTP basic authentication and client side
+certificate. The basic authentication over HTTPS is actually quite
+safe because HTTPS guarantees that the password will not travel in
+clear. Never-the-less, problems like easily guessable passwords
+remain. The client certificate method involves authentication of the
+client at SSL level using a certificate. For this to work, both the
+client and the server will have certificates (which typically are
+different) and private keys.
+
+The API functions outlined above accept additional arguments that
+allow one to supply the client side certificate and key files. The
+format of these files is the same as used for server certificates and
+the caveat about encrypting private key applies.
+
+ ($page, $result, %headers) = # 2c
+ = get_https('www.bacus.pt', 443, '/protected.html',
+ make_headers(Authorization =>
+ 'Basic ' . MIME::Base64::encode("$user:$pass",'')),
+ '', $mime_type6, $path_to_crt7, $path_to_key8);
+
+ ($page, $response, %reply_headers)
+ = post_https('www.bacus.pt', 443, '/foo.cgi', # 3b
+ make_headers('Authorization' =>
+ 'Basic ' . MIME::Base64::encode("$user:$pass",'')),
+ make_form(OK => '1', name => 'Sampo'),
+ $mime_type6, $path_to_crt7, $path_to_key8);
+
+Case 2c demonstrates getting password protected page that also requires
+client certificate, i.e. it is possible to use both authentication
+methods simultaneously.
+
+Case 3b is full blown post to secure server that requires both password
+authentication and client certificate, just like in case 2c.
+
+Note: Client will not send a certificate unless the server requests one.
+This is typically achieved by setting verify mode to C<VERIFY_PEER> on the
+server:
+
+ Net::SSLeay::set_verify(ssl, Net::SSLeay::VERIFY_PEER, 0);
+
+See C<perldoc ~openssl/doc/ssl/SSL_CTX_set_verify.pod> for full description.
+
+=head2 Working through Web proxy
+
+C<Net::SSLeay> can use a web proxy to make its connections. You need to
+first set the proxy host and port using C<set_proxy()> and then just
+use the normal API functions, e.g:
+
+ Net::SSLeay::set_proxy('gateway.myorg.com', 8080);
+ ($page) = get_https('www.bacus.pt', 443, '/');
+
+If your proxy requires authentication, you can supply username and
+password as well
+
+ Net::SSLeay::set_proxy('gateway.myorg.com', 8080, 'joe', 'salainen');
+ ($page, $result, %headers) =
+ = get_https('www.bacus.pt', 443, '/protected.html',
+ make_headers(Authorization =>
+ 'Basic ' . MIME::Base64::encode("susie:pass",''))
+ );
+
+This example demonstrates case where we authenticate to the proxy as
+C<"joe"> and to the final web server as C<"susie">. Proxy authentication
+requires C<MIME::Base64> module to work.
+
+=head2 Certificate verification and Certificate Revoocation Lists (CRLs)
+
+OpenSSL supports the ability to verify peer certificates. It can also
+optionally check the peer certificate against a Certificate Revocation
+List (CRL) from the certificates issuer. A CRL is a file, created by
+the certificate issuer that lists all the certificates that it
+previously signed, but which it now revokes. CRLs are in PEM format.
+
+You can enable C<Net::SSLeay CRL> checking like this:
+
+ &Net::SSLeay::X509_STORE_CTX_set_flags
+ (&Net::SSLeay::CTX_get_cert_store($ssl),
+ &Net::SSLeay::X509_V_FLAG_CRL_CHECK);
+
+After setting this flag, if OpenSSL checks a peer's certificate, then
+it will attempt to find a CRL for the issuer. It does this by looking
+for a specially named file in the search directory specified by
+CTX_load_verify_locations. CRL files are named with the hash of the
+issuer's subject name, followed by C<.r0>, C<.r1> etc. For example
+C<ab1331b2.r0>, C<ab1331b2.r1>. It will read all the .r files for the
+issuer, and then check for a revocation of the peer cerificate in all
+of them. (You can also force it to look in a specific named CRL
+file., see below). You can find out the hash of the issuer subject
+name in a CRL with
+
+ openssl crl -in crl.pem -hash -noout
+
+If the peer certificate does not pass the revocation list, or if no
+CRL is found, then the handshaking fails with an error.
+
+You can also force OpenSSL to look for CRLs in one or more arbitrarily
+named files.
+
+ my $bio = Net::SSLeay::BIO_new_file($crlfilename, 'r');
+ my $crl = Net::SSLeay::PEM_read_bio_X509_CRL($bio);
+ if ($crl) {
+ Net::SSLeay::X509_STORE_add_crl(Net::SSLeay::CTX_get_cert_store($ssl, $crl);
+ } else {
+ error reading CRL....
+ }
+
+
+=head2 Convenience routines
+
+To be used with Low level API
+
+ Net::SSLeay::randomize($rn_seed_file,$additional_seed);
+ Net::SSLeay::set_cert_and_key($ctx, $cert_path, $key_path);
+ $cert = Net::SSLeay::dump_peer_certificate($ssl);
+ Net::SSLeay::ssl_write_all($ssl, $message) or die "ssl write failure";
+ $got = Net::SSLeay::ssl_read_all($ssl) or die "ssl read failure";
+
+ $got = Net::SSLeay::ssl_read_CRLF($ssl [, $max_length]);
+ $got = Net::SSLeay::ssl_read_until($ssl [, $delimit [, $max_length]]);
+ Net::SSLeay::ssl_write_CRLF($ssl, $message);
+
+C<randomize()> seeds the eay PRNG with C</dev/urandom> (see top of C<SSLeay.pm>
+for how to change or configure this) and optionally with user provided
+data. It is very important to properly seed your random numbers, so
+do not forget to call this. The high level API functions automatically
+call C<randomize()> so it is not needed with them. See also caveats.
+
+C<set_cert_and_key()> takes two file names as arguments and sets
+the certificate and private key to those. This can be used to
+set either cerver certificates or client certificates.
+
+C<dump_peer_certificate()> allows you to get plaintext description of the
+certificate the peer (usually server) presented to us.
+
+C<ssl_read_all()> and C<ssl_write_all()> provide true blocking semantics for
+these operations (see limitation, below, for explanation). These are
+much preferred to the low level API equivalents (which implement BSD
+blocking semantics). The message argument to C<ssl_write_all()> can be
+reference. This is helpful to avoid unnecessary copy when writing
+something big, e.g:
+
+ $data = 'A' x 1000000000;
+ Net::SSLeay::ssl_write_all($ssl, \$data) or die "ssl write failed";
+
+C<ssl_read_CRLF()> uses C<ssl_read_all()> to read in a line terminated with a
+carriage return followed by a linefeed (CRLF). The CRLF is included in
+the returned scalar.
+
+C<ssl_read_until()> uses C<ssl_read_all()> to read from the SSL input
+stream until it encounters a programmer specified delimiter.
+If the delimiter is undefined, C<$/> is used. If C<$/> is undefined,
+C<\n> is used. One can optionally set a maximum length of bytes to read
+from the SSL input stream.
+
+C<ssl_write_CRLF()> writes C<$message> and appends CRLF to the SSL output stream.
+
+=head2 Low level API
+
+In addition to the high level functions outlined above, this module
+contains straight forward access to SSL part of OpenSSL C api. Only the SSL
+subpart of OpenSSL is implemented (if anyone wants to implement other
+parts, feel free to submit patches).
+
+See C<ssl.h> header from OpenSSL C distribution for list of low lever
+SSLeay functions to call (to check if some function has been
+implemented see directly in SSLeay.xs). The module strips SSLeay names
+of the initial C<"SSL_">, generally you should use C<Net::SSLeay::> in
+place. For example:
+
+In C:
+
+ #include <ssl.h>
+
+ err = SSL_set_verify (ssl, SSL_VERIFY_CLIENT_ONCE,
+ &your_call_back_here);
+
+In Perl:
+
+ use Net::SSLeay;
+
+ $err = Net::SSLeay::set_verify ($ssl,
+ Net::SSLeay::VERIFY_CLIENT_ONCE,
+ \&your_call_back_here);
+
+If the function does not start by C<SSL_> you should use the full
+function name, e.g.:
+
+ $err = Net::SSLeay::ERR_get_error;
+
+Following new functions behave in perlish way:
+
+ $got = Net::SSLeay::read($ssl);
+ # Performs SSL_read, but returns $got
+ # resized according to data received.
+ # Returns undef on failure.
+
+ Net::SSLeay::write($ssl, $foo) || die;
+ # Performs SSL_write, but automatically
+ # figures out the size of $foo
+
+In order to use the low level API you should start your programs with
+the following incantation:
+
+ use Net::SSLeay qw(die_now die_if_ssl_error);
+ Net::SSLeay::load_error_strings();
+ Net::SSLeay::SSLeay_add_ssl_algorithms(); # Important!
+ Net::SSLeay::ENGINE_load_builtin_engines(); # If you want built-in engines
+ Net::SSLeay::ENGINE_register_all_complete(); # If you want built-in engines
+ Net::SSLeay::randomize();
+
+C<die_now()> and C<die_if_ssl_error()> are used to conveniently print SSLeay error
+stack when something goes wrong, thusly:
+
+ Net::SSLeay::connect($ssl) or die_now("Failed SSL connect ($!)");
+ Net::SSLeay::write($ssl, "foo") or die_if_ssl_error("SSL write ($!)");
+
+You can also use C<Net::SSLeay::print_errs()> to dump the error stack without
+exiting the program. As can be seen, your code becomes much more readable
+if you import the error reporting functions to your main name space.
+
+I can not emphasize enough the need to check error returns. Use these
+functions even in most simple programs, they will reduce debugging
+time greatly. Do not ask questions in mailing list without having
+first sprinkled these in your code.
+
+=head2 Sockets
+
+Perl uses file handles for all I/O. While SSLeay has quite flexible BIO
+mechanism and perl has evolved PerlIO mechanism, this module still
+sticks to using file descriptors. Thus to attach SSLeay to socket you
+should use C<fileno()> to extract the underlying file descriptor:
+
+ Net::SSLeay::set_fd($ssl, fileno(S)); # Must use fileno
+
+You should also set C<$|> to 1 to eliminate STDIO buffering so you do not
+get confused if you use perl I/O functions to manipulate your socket
+handle.
+
+If you need to C<select(2)> on the socket, go right ahead, but be warned
+that OpenSSL does some internal buffering so SSL_read does not always
+return data even if socket selected for reading (just keep on
+selecting and trying to read). C<Net::SSLeay> is no different from the
+C language OpenSSL in this respect.
+
+=head2 Callbacks
+
+At this moment the implementation of verify_callback is crippeled in
+the sense that at any given time there can be only one call back which
+is shared by all SSL contexts, sessions and connections. This is
+due to having to keep the reference to the perl call back in a
+static variable so that the callback C glue can find it. To remove
+this restriction would require either a more complex data structure
+(like a hash?) in XSUB to map the call backs to their owners or,
+cleaner, adding a context pointer in the SSL structure. This context would
+then be passed to the C callback, which in our case would be the glue
+to look up the proper Perl function from the context and call it.
+
+---- inaccurate ----
+The verify call back looks like this in C:
+
+ int (*callback)(int ok,X509 *subj_cert,X509 *issuer_cert,
+ int depth,int errorcode,char *arg,STACK *cert_chain)
+
+The corresponding Perl function should be something like this:
+
+ sub verify {
+ my ($ok, $subj_cert, $issuer_cert, $depth, $errorcode,
+ $arg, $chain) = @_;
+ print "Verifying certificate...\n";
+ ...
+ return $ok;
+ }
+
+It is used like this:
+
+ Net::SSLeay::set_verify ($ssl, Net::SSLeay::VERIFY_PEER, \&verify);
+
+Callbacks for decrypting private keys are implemented, but have the
+same limitation as the verify_callback implementation (one password
+callback shared between all contexts.) You might use it something
+like this:
+
+ Net::SSLeay::CTX_set_default_passwd_cb($ctx, sub { "top-secret" });
+ Net::SSLeay::CTX_use_PrivateKey_file($ctx, "key.pem",
+ Net::SSLeay::FILETYPE_PEM)
+ or die "Error reading private key";
+ Net::SSLeay::CTX_set_default_passwd_cb($ctx, undef);
+
+No other callbacks are implemented. You do not need to use any
+callback for simple (i.e. normal) cases where the SSLeay built-in
+verify mechanism satisfies your needs.
+
+It is desirable to reset these callbacks to undef immediately after use to prevent
+thread safety problems and crashes on exit that can occur if different threads
+set different callbacks.
+
+---- end inaccurate ----
+
+If you want to use callback stuff, see examples/callback.pl! Its the
+only one I am able to make work reliably.
+
+=head2 X509 and RAND stuff
+
+This module largely lacks interface to the X509 and RAND routines, but
+as I was lazy and needed them, the following kludges are implemented:
+
+ $x509_name = Net::SSLeay::X509_get_subject_name($x509_cert);
+ $x509_name = Net::SSLeay::X509_get_issuer_name($x509_cert);
+ print Net::SSLeay::X509_NAME_oneline($x509_name);
+ $text = Net::SSLeay::X509_NAME_get_text_by_NID($name, $nid);
+
+ ($type1, $subject1, $type2, $subject2, ...) =
+ Net::SSLeay::X509_get_subjectAltNames($x509_cert)
+
+ subjectAltName types as per x509v3.h GEN_*, for example
+ GEN_DNS or GEN_IPADD which can be imported.
+
+ Net::SSLeay::RAND_seed($buf); # Perlishly figures out buf size
+ Net::SSLeay::RAND_bytes($buf, $num);
+ Net::SSLeay::RAND_pseudo_bytes($buf, $num);
+ Net::SSLeay::RAND_add($buf, $num, $entropy);
+ Net::SSLeay::RAND_poll();
+ Net::SSLeay::RAND_status();
+ Net::SSLeay::RAND_cleanup();
+ Net::SSLeay::RAND_file_name($num);
+ Net::SSLeay::RAND_load_file($file_name, $how_many_bytes);
+ Net::SSLeay::RAND_write_file($file_name);
+ Net::SSLeay::RAND_egd($path);
+ Net::SSLeay::RAND_egd_bytes($path, $bytes);
+
+Actually you should consider using the following helper functions:
+
+ print Net::SSLeay::dump_peer_certificate($ssl);
+ Net::SSLeay::randomize();
+
+=head2 RSA interface
+
+Some RSA functions are available:
+
+ $rsakey = Net::SSLeay::RSA_generate_key();
+ Net::SSLeay::CTX_set_tmp_rsa($ctx, $rsakey);
+ Net::SSLeay::RSA_free($rsakey);
+
+=head2 BIO interface
+
+Some BIO functions are available:
+
+ Net::SSLeay::BIO_s_mem();
+ $bio = Net::SSLeay::BIO_new(BIO_s_mem())
+ $bio = Net::SSLeay::BIO_new_file($filename, $mode);
+ Net::SSLeay::BIO_free($bio)
+ $count = Net::SSLeay::BIO_write($data);
+ $data = Net::SSLeay::BIO_read($bio);
+ $data = Net::SSLeay::BIO_read($bio, $maxbytes);
+ $is_eof = Net::SSLeay::BIO_eof($bio);
+ $count = Net::SSLeay::BIO_pending($bio);
+ $count = Net::SSLeay::BIO_wpending ($bio);
+
+=head2 Low level API
+
+Some very low level API functions are available:
+
+ $client_random = Net::SSLeay::get_client_random($ssl);
+ $server_random = Net::SSLeay::get_server_random($ssl);
+ $session = Net::SSLeay::get_session($ssl);
+ $master_key = Net::SSLeay::SESSION_get_master_key($session);
+ Net::SSLeay::SESSION_set_master_key($session, $master_secret);
+ $keyblocksize = Net::SSLeay::get_keyblock_size($session);
+
+=head2 HTTP (without S) API
+
+Over the years it has become clear that it would be convenient to use
+the light weight flavour API of C<Net::SSLeay> also for normal HTTP (see
+LWP for heavy weight object oriented approach). In fact it would be
+nice to be able to flip https on and off on the fly. Thus regular HTTP
+support was evolved.
+
+ use Net::SSLeay qw(get_http post_http tcpcat
+ get_httpx post_httpx tcpxcat
+ make_headers make_form);
+
+ ($page, $result, %headers) =
+ = get_http('www.bacus.pt', 443, '/protected.html',
+ make_headers(Authorization =>
+ 'Basic ' . MIME::Base64::encode("$user:$pass",''))
+ );
+
+ ($page, $response, %reply_headers)
+ = post_http('www.bacus.pt', 443, '/foo.cgi', '',
+ make_form(OK => '1',
+ name => 'Sampo'
+ ));
+
+ ($reply, $err) = tcpcat($host, $port, $request);
+
+ ($page, $result, %headers) =
+ = get_httpx($usessl, 'www.bacus.pt', 443, '/protected.html',
+ make_headers(Authorization =>
+ 'Basic ' . MIME::Base64::encode("$user:$pass",''))
+ );
+
+ ($page, $response, %reply_headers)
+ = post_httpx($usessl, 'www.bacus.pt', 443, '/foo.cgi', '',
+ make_form(OK => '1', name => 'Sampo' ));
+
+ ($reply, $err, $server_cert) = tcpxcat($usessl, $host, $port, $request);
+
+As can be seen, the C<"x"> family of APIs takes as first argument a flag
+which indicated whether SSL is used or not.
+
+=head1 EXAMPLES
+
+One very good example is to look at the implementation of C<sslcat()> in the
+C<SSLeay.pm> file.
+
+Following is a simple SSLeay client (with too little error checking :-(
+
+ #!/usr/local/bin/perl
+ use Socket;
+ use Net::SSLeay qw(die_now die_if_ssl_error) ;
+ Net::SSLeay::load_error_strings();
+ Net::SSLeay::SSLeay_add_ssl_algorithms();
+ Net::SSLeay::randomize();
+
+ ($dest_serv, $port, $msg) = @ARGV; # Read command line
+ $port = getservbyname ($port, 'tcp') unless $port =~ /^\d+$/;
+ $dest_ip = gethostbyname ($dest_serv);
+ $dest_serv_params = sockaddr_in($port, $dest_ip);
+
+ socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!";
+ connect (S, $dest_serv_params) or die "connect: $!";
+ select (S); $| = 1; select (STDOUT); # Eliminate STDIO buffering
+
+ # The network connection is now open, lets fire up SSL
+
+ $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!");
+ Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL)
+ and die_if_ssl_error("ssl ctx set options");
+ $ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!");
+ Net::SSLeay::set_fd($ssl, fileno(S)); # Must use fileno
+ $res = Net::SSLeay::connect($ssl) and die_if_ssl_error("ssl connect");
+ print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n";
+
+ # Exchange data
+
+ $res = Net::SSLeay::write($ssl, $msg); # Perl knows how long $msg is
+ die_if_ssl_error("ssl write");
+ CORE::shutdown S, 1; # Half close --> No more output, sends EOF to server
+ $got = Net::SSLeay::read($ssl); # Perl returns undef on failure
+ die_if_ssl_error("ssl read");
+ print $got;
+
+ Net::SSLeay::free ($ssl); # Tear down connection
+ Net::SSLeay::CTX_free ($ctx);
+ close S;
+
+Following is a simple SSLeay echo server (non forking):
+
+ #!/usr/local/bin/perl -w
+ use Socket;
+ use Net::SSLeay qw(die_now die_if_ssl_error);
+ Net::SSLeay::load_error_strings();
+ Net::SSLeay::SSLeay_add_ssl_algorithms();
+ Net::SSLeay::randomize();
+
+ $our_ip = "\0\0\0\0"; # Bind to all interfaces
+ $port = 1235;
+ $sockaddr_template = 'S n a4 x8';
+ $our_serv_params = pack ($sockaddr_template, &AF_INET, $port, $our_ip);
+
+ socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!";
+ bind (S, $our_serv_params) or die "bind: $!";
+ listen (S, 5) or die "listen: $!";
+ $ctx = Net::SSLeay::CTX_new () or die_now("CTX_new ($ctx): $!");
+ Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL)
+ and die_if_ssl_error("ssl ctx set options");
+
+ # Following will ask password unless private key is not encrypted
+ Net::SSLeay::CTX_use_RSAPrivateKey_file ($ctx, 'plain-rsa.pem',
+ &Net::SSLeay::FILETYPE_PEM);
+ die_if_ssl_error("private key");
+ Net::SSLeay::CTX_use_certificate_file ($ctx, 'plain-cert.pem',
+ &Net::SSLeay::FILETYPE_PEM);
+ die_if_ssl_error("certificate");
+
+ while (1) {
+ print "Accepting connections...\n";
+ ($addr = accept (NS, S)) or die "accept: $!";
+ select (NS); $| = 1; select (STDOUT); # Piping hot!
+
+ ($af,$client_port,$client_ip) = unpack($sockaddr_template,$addr);
+ @inetaddr = unpack('C4',$client_ip);
+ print "$af connection from " .
+ join ('.', @inetaddr) . ":$client_port\n";
+
+ # We now have a network connection, lets fire up SSLeay...
+
+ $ssl = Net::SSLeay::new($ctx) or die_now("SSL_new ($ssl): $!");
+ Net::SSLeay::set_fd($ssl, fileno(NS));
+
+ $err = Net::SSLeay::accept($ssl) and die_if_ssl_error('ssl accept');
+ print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n";
+
+ # Connected. Exchange some data.
+
+ $got = Net::SSLeay::read($ssl); # Returns undef on fail
+ die_if_ssl_error("ssl read");
+ print "Got `$got' (" . length ($got) . " chars)\n";
+
+ Net::SSLeay::write ($ssl, uc ($got)) or die "write: $!";
+ die_if_ssl_error("ssl write");
+
+ Net::SSLeay::free ($ssl); # Tear down connection
+ close NS;
+ }
+
+Yet another echo server. This one runs from C</etc/inetd.conf> so it avoids
+all the socket code overhead. Only caveat is opening rsa key file -
+it had better be without any encryption or else it will not know where
+to ask for the password. Note how C<STDIN> and C<STDOUT> are wired to SSL.
+
+ #!/usr/local/bin/perl
+ # /etc/inetd.conf
+ # ssltst stream tcp nowait root /path/to/server.pl server.pl
+ # /etc/services
+ # ssltst 1234/tcp
+
+ use Net::SSLeay qw(die_now die_if_ssl_error);
+ Net::SSLeay::load_error_strings();
+ Net::SSLeay::SSLeay_add_ssl_algorithms();
+ Net::SSLeay::randomize();
+
+ chdir '/key/dir' or die "chdir: $!";
+ $| = 1; # Piping hot!
+ open LOG, ">>/dev/console" or die "Can't open log file $!";
+ select LOG; print "server.pl started\n";
+
+ $ctx = Net::SSLeay::CTX_new() or die_now "CTX_new ($ctx) ($!)";
+ $ssl = Net::SSLeay::new($ctx) or die_now "new ($ssl) ($!)";
+ Net::SSLeay::set_options($ssl, &Net::SSLeay::OP_ALL)
+ and die_if_ssl_error("ssl set options");
+
+ # We get already open network connection from inetd, now we just
+ # need to attach SSLeay to STDIN and STDOUT
+ Net::SSLeay::set_rfd($ssl, fileno(STDIN));
+ Net::SSLeay::set_wfd($ssl, fileno(STDOUT));
+
+ Net::SSLeay::use_RSAPrivateKey_file ($ssl, 'plain-rsa.pem',
+ Net::SSLeay::FILETYPE_PEM);
+ die_if_ssl_error("private key");
+ Net::SSLeay::use_certificate_file ($ssl, 'plain-cert.pem',
+ Net::SSLeay::FILETYPE_PEM);
+ die_if_ssl_error("certificate");
+
+ Net::SSLeay::accept($ssl) and die_if_ssl_err("ssl accept: $!");
+ print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n";
+
+ $got = Net::SSLeay::read($ssl);
+ die_if_ssl_error("ssl read");
+ print "Got `$got' (" . length ($got) . " chars)\n";
+
+ Net::SSLeay::write ($ssl, uc($got)) or die "write: $!";
+ die_if_ssl_error("ssl write");
+
+ Net::SSLeay::free ($ssl); # Tear down the connection
+ Net::SSLeay::CTX_free ($ctx);
+ close LOG;
+
+There are also a number of example/test programs in the examples directory:
+
+ sslecho.pl - A simple server, not unlike the one above
+ minicli.pl - Implements a client using low level SSLeay routines
+ sslcat.pl - Demonstrates using high level sslcat utility function
+ get_page.pl - Is a utility for getting html pages from secure servers
+ callback.pl - Demonstrates certificate verification and callback usage
+ stdio_bulk.pl - Does SSL over Unix pipes
+ ssl-inetd-serv.pl - SSL server that can be invoked from inetd.conf
+ httpd-proxy-snif.pl - Utility that allows you to see how a browser
+ sends https request to given server and what reply
+ it gets back (very educative :-)
+ makecert.pl - Creates a self signed cert (does not use this module)
+
+=head1 LIMITATIONS
+
+C<Net::SSLeay::read()> uses internal buffer of 32KB, thus no single read
+will return more. In practice one read returns much less, usually
+as much as fits in one network packet. To work around this,
+you should use a loop like this:
+
+ $reply = '';
+ while ($got = Net::SSLeay::read($ssl)) {
+ last if print_errs('SSL_read');
+ $reply .= $got;
+ }
+
+Although there is no built-in limit in C<Net::SSLeay::write()>, the network
+packet size limitation applies here as well, thus use:
+
+ $written = 0;
+
+ while ($written < length($message)) {
+ $written += Net::SSLeay::write($ssl, substr($message, $written));
+ last if print_errs('SSL_write');
+ }
+
+Or alternatively you can just use the following convinence functions:
+
+ Net::SSLeay::ssl_write_all($ssl, $message) or die "ssl write failure";
+ $got = Net::SSLeay::ssl_read_all($ssl) or die "ssl read failure";
+
+=head1 KNOWN BUGS AND CAVEATS
+
+Autoloader emits
+
+ Argument "xxx" isn't numeric in entersub at blib/lib/Net/SSLeay.pm'
+
+warning if die_if_ssl_error is made autoloadable. If you figure out why,
+drop me a line.
+
+Callback set using C<SSL_set_verify()> does not appear to work. This may
+well be eay problem (e.g. see C<ssl/ssl_lib.c> line 1029). Try using
+C<SSL_CTX_set_verify()> instead and do not be surprised if even this stops
+working in future versions.
+
+Callback and certificate verification stuff is generally too little tested.
+
+Random numbers are not initialized randomly enough, especially if you
+do not have C</dev/random> and/or C</dev/urandom> (such as in Solaris
+platforms - but I've been suggested that cryptorand daemon from SUNski
+package solves this). In this case you should investigate third party
+software that can emulate these devices, e.g. by way of a named pipe
+to some program.
+
+Another gotcha with random number initialization is randomness
+depletion. This phenomenon, which has been extensively discussed in
+OpenSSL, Apache-SSL, and Apache-mod_ssl forums, can cause your
+script to block if you use C</dev/random> or to operate insecurely
+if you use C</dev/urandom>. What happens is that when too much
+randomness is drawn from the operating system's randomness pool
+then randomness can temporarily be unavailable. C</dev/random> solves
+this problem by waiting until enough randomness can be gathered - and
+this can take a long time since blocking reduces activity in the
+machine and less activity provides less random events: a vicious circle.
+C</dev/urandom> solves this dilemma more pragmatically by simply returning
+predictable "random" numbers. SomeC< /dev/urandom> emulation software
+however actually seems to implement C</dev/random> semantics. Caveat emptor.
+
+I've been pointed to two such daemons by Mik Firestone <mik@@speed.stdio._com>
+who has used them on Solaris 8:
+
+=over
+
+=item 1
+
+Entropy Gathering Daemon (EGD) at L<http://www.lothar.com/tech/crypto/>
+
+=item 2
+
+Pseudo-random number generating daemon (PRNGD) at
+L<http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html>
+
+=back
+
+If you are using the low level API functions to communicate with other
+SSL implementations, you would do well to call
+
+ Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL)
+ and die_if_ssl_error("ssl ctx set options");
+
+to cope with some well know bugs in some other SSL
+implementations. The high level API functions always set all known
+compatibility options.
+
+Sometimes C<sslcat()> (and the high level HTTPS functions that build on it)
+is too fast in signaling the EOF to legacy HTTPS servers. This causes
+the server to return empty page. To work around this problem you can
+set global variable
+
+ $Net::SSLeay::slowly = 1; # Add sleep so broken servers can keep up
+
+HTTP/1.1 is not supported. Specifically this module does not know to
+issue or serve multiple http requests per connection. This is a serious
+short coming, but using SSL session cache on your server helps to
+alleviate the CPU load somewhat.
+
+As of version 1.09 many newer OpenSSL auxiliary functions were
+added (from C<REM_AUTOMATICALLY_GENERATED_1_09> onwards in C<SSLeay.xs>).
+Unfortunately I have not had any opportunity to test these. Some of
+them are trivial enough that I believe they "just work", but others
+have rather complex interfaces with function pointers and all. In these
+cases you should proceed wit great caution.
+
+This module defaults to using OpenSSL automatic protocol negotiation
+code for automatically detecting the version of the SSL protocol
+that the other end talks. With most web servers this works just
+fine, but once in a while I get complaints from people that the module
+does not work with some web servers. Usually this can be solved
+by explicitly setting the protocol version, e.g.
+
+ $Net::SSLeay::ssl_version = 2; # Insist on SSLv2
+ $Net::SSLeay::ssl_version = 3; # Insist on SSLv3
+ $Net::SSLeay::ssl_version = 10; # Insist on TLSv1
+
+Although the autonegotiation is nice to have, the SSL standards
+do not formally specify any such mechanism. Most of the world has
+accepted the SSLeay/OpenSSL way of doing it as the de facto standard. But
+for the few that think differently, you have to explicitly speak
+the correct version. This is not really a bug, but rather a deficiency
+in the standards. If a site refuses to respond or sends back some
+nonsensical error codes (at SSL handshake level), try this option
+before mailing me.
+
+The high level API returns the certificate of the peer, thus allowing
+one to check what certificate was supplied. However, you will only be
+able to check the certificate after the fact, i.e. you already sent
+your form data by the time you find out that you did not trust them,
+oops.
+
+So, while being able to know the certificate after the fact is surely
+useful, the security minded would still choose to do the connection
+and certificate verification first and only after that exchange data
+with the site. Currently none of the high level API functions do
+this, thus you would have to program it using the low level API. A
+good place to start is to see how C<Net::SSLeay::http_cat()> function
+is implemented.
+
+The high level API functions use a global file handle C<SSLCAT_S>
+internally. This really should not be a problem because there is no
+way to interleave the high level API functions, unless you use threads
+(but threads are not very well supported in perl anyway (as of version
+5.6.1). However, you may run into problems if you call undocumented
+internal functions in an interleaved fashion.
+
+=head1 DIAGNOSTICS
+
+=over
+
+=item Random number generator not seeded!!!
+
+B<(W)> This warning indicates that C<randomize()> was not able to read
+C</dev/random> or C</dev/urandom>, possibly because your system does not
+have them or they are differently named. You can still use SSL, but
+the encryption will not be as strong.
+
+=item open_tcp_connection: destination host not found:`server' (port 123) ($!)
+
+Name lookup for host named C<server> failed.
+
+=item open_tcp_connection: failed `server', 123 ($!)
+
+The name was resolved, but establising the TCP connection failed.
+
+=item msg 123: 1 - error:140770F8:SSL routines:SSL23_GET_SERVER_HELLO:unknown proto
+
+SSLeay error string. First (123) number is PID, second number (1) indicates
+the position of the error message in SSLeay error stack. You often see
+a pile of these messages as errors cascade.
+
+=item msg 123: 1 - error:02001002::lib(2) :func(1) :reason(2)
+
+The same as above, but you didn't call load_error_strings() so SSLeay
+couldn't verbosely explain the error. You can still find out what it
+means with this command:
+
+ /usr/local/ssl/bin/ssleay errstr 02001002
+
+=item Password is being asked for private key
+
+This is normal behaviour if your private key is encrypted. Either
+you have to supply the password or you have to use unencrypted
+private key. Scan OpenSSL.org for the FAQ that explains how to
+do this (or just study examples/makecert.pl which is used
+during C<make test> to do just that).
+
+=back
+
+=head1 REPORTING BUGS AND SUPPORT
+
+Bug reports, patch submission, feature requests, subversion access to the latest
+source code etc can be obtained at
+L<http://alioth.debian.org/projects/net-ssleay>
+
+The developer mailing list (for people interested in contributin to the source code)
+can be found at
+L<http://lists.alioth.debian.org/mailman/listinfo/net-ssleay-devel>
+
+Commercial support for Net::SSLeay may be obtained from
+
+ Symlabs (netssleay@symlabs.com)
+ Tel: +351-214.222.630
+ Fax: +351-214.222.637
+
+=head1 VERSION
+
+There are currently two perl modules for using OpenSSL C
+library: C<Net::SSLeay> (maintaned by me) and C<SSLeay> (maintained by OpenSSL
+team). This module is the C<Net::SSLeay> variant.
+
+At the time of making this release, Eric's module was still quite
+sketchy and could not be used for real work, thus I felt motivated to
+make this maintenance release. This module is not planned to evolve to
+contain any further functionality, i.e. I will concentrate on just
+making a simple SSL connection over TCP socket. Presumably Eric's own
+module will offer full SSLeay API one day.
+
+This module uses OpenSSL-0.9.6c. It does not work with any earlier
+version and there is no guarantee that it will work with later
+versions either, though as long as C API does not change, it
+should. This module requires Perl 5.005 or newer, though I
+believe it would build with Perl 5.002 or newer.
+
+=head1 BUGS
+
+Please report any bugs or feature requests to
+C<bug-net_ssleay.pm at rt.cpan.org>, or through the web interface at
+L<http://rt.cpan.org/Public/Dist/Display.html?Name=Net_SSLeay.pm>.
+I will be notified, and then you'll automatically be notified of progress on
+your bug as I make changes.
+
+=head1 SUPPORT
+
+You can find documentation for this module with the C<perldoc> command.
+
+ perldoc Net::SSLeay
+
+You can also look for information at:
+
+=over 4
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/Net_SSLeay.pm>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/Net_SSLeay.pm>
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/Public/Dist/Display.html?Name=Net_SSLeay.pm>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/Net_SSLeay.pm>
+
+=back
+
+=head1 AUTHOR
+
+Maintained by Mike McCauley and Florian Ragwitz since November 2005
+
+Originally written by Sampo Kellomäki <sampo@symlabs.com>
+
+=head1 COPYRIGHT
+
+Copyright (c) 1996-2003 Sampo Kellomäki <sampo@symlabs.com>
+
+Copyright (C) 2005-2006 Florian Ragwitz <rafl@debian.org>
+
+Copyright (C) 2005 Mike McCauley <mikem@open.com.au>
+
+All Rights Reserved.
+
+Distribution and use of this module is under the same terms as the
+OpenSSL package itself (i.e. free, but mandatory attribution; NO
+WARRANTY). Please consult LICENSE file in the root of the OpenSSL
+distribution.
+
+While the source distribution of this perl module does not contain
+Eric's or OpenSSL's code, if you use this module you will use OpenSSL
+library. Please give Eric and OpenSSL team credit (as required by
+their licenses).
+
+And remember, you, and nobody else but you, are responsible for
+auditing this module and OpenSSL library for security problems,
+backdoors, and general suitability for your application.
+
+=head1 SEE ALSO
+
+ Net::SSLeay::Handle - File handle interface
+ ./Net_SSLeay/examples - Example servers and a clients
+ <http://symlabs.com/Net_SSLeay/index.html> - Net::SSLeay.pm home
+ <http://symlabs.com/Net_SSLeay/smime.html> - Another module using OpenSSL
+ <http://www.openssl.org/> - OpenSSL source, documentation, etc
+ openssl-users-request@openssl.org - General OpenSSL mailing list
+ <http://home.netscape.com/newsref/std/SSL.html> - SSL Draft specification
+ <http://www.w3c.org> - HTTP specifications
+ <http://www.ietf.org/rfc/rfc2617.txt> - How to send password
+ <http://www.lothar.com/tech/crypto/> - Entropy Gathering Daemon (EGD)
+ <http://www.aet.tu-cottbus.de/personen/jaenicke/postfix_tls/prngd.html>
+ - pseudo-random number generating daemon (PRNGD)
+ perl(1)
+ perlref(1)
+ perllol(1)
+ perldoc ~openssl/doc/ssl/SSL_CTX_set_verify.pod
+
+=cut
+
+# ';
+
+### Some methods that are macros in C
+
+sub want_nothing { want(shift) == 1 }
+sub want_read { want(shift) == 2 }
+sub want_write { want(shift) == 3 }
+sub want_X509_lookup { want(shift) == 4 }
+
+###
+### Open TCP stream to given host and port, looking up the details
+### from system databases or DNS.
+###
+
+sub open_tcp_connection {
+ my ($dest_serv, $port) = @_;
+ my ($errs);
+
+ $port = getservbyname($port, 'tcp') unless $port =~ /^\d+$/;
+ my $dest_serv_ip = gethostbyname($dest_serv);
+ unless (defined($dest_serv_ip)) {
+ $errs = "$0 $$: open_tcp_connection: destination host not found:"
+ . " `$dest_serv' (port $port) ($!)\n";
+ warn $errs if $trace;
+ return wantarray ? (0, $errs) : 0;
+ }
+ my $sin = sockaddr_in($port, $dest_serv_ip);
+
+ warn "Opening connection to $dest_serv:$port (" .
+ inet_ntoa($dest_serv_ip) . ")" if $trace>2;
+
+ my $proto = getprotobyname('tcp');
+ if (socket (SSLCAT_S, &PF_INET(), &SOCK_STREAM(), $proto)) {
+ warn "next connect" if $trace>3;
+ if (CORE::connect (SSLCAT_S, $sin)) {
+ my $old_out = select (SSLCAT_S); $| = 1; select ($old_out);
+ warn "connected to $dest_serv, $port" if $trace>3;
+ return wantarray ? (1, undef) : 1; # Success
+ }
+ }
+ $errs = "$0 $$: open_tcp_connection: failed `$dest_serv', $port ($!)\n";
+ warn $errs if $trace;
+ close SSLCAT_S;
+ return wantarray ? (0, $errs) : 0; # Fail
+}
+
+### Open connection via standard web proxy, if one was defined
+### using set_proxy().
+
+sub open_proxy_tcp_connection {
+ my ($dest_serv, $port) = @_;
+ return open_tcp_connection($dest_serv, $port) if !$proxyhost;
+
+ warn "Connect via proxy: $proxyhost:$proxyport" if $trace>2;
+ my ($ret, $errs) = open_tcp_connection($proxyhost, $proxyport);
+ return wantarray ? (0, $errs) : 0 if !$ret; # Connection fail
+
+ warn "Asking proxy to connect to $dest_serv:$port" if $trace>2;
+ #print SSLCAT_S "CONNECT $dest_serv:$port HTTP/1.0$proxyauth$CRLF$CRLF";
+ #my $line = <SSLCAT_S>; # *** bug? Mixing stdio with syscall read?
+ ($ret, $errs) =
+ tcp_write_all("CONNECT $dest_serv:$port HTTP/1.0$proxyauth$CRLF$CRLF");
+ return wantarray ? (0,$errs) : 0 if $errs;
+ ($line, $errs) = tcp_read_until($CRLF . $CRLF, 1024);
+ warn "Proxy response: $line" if $trace>2;
+ return wantarray ? (0,$errs) : 0 if $errs;
+ return wantarray ? (1,'') : 1; # Success
+}
+
+###
+### read and write helpers that block
+###
+
+sub debug_read {
+ my ($replyr, $gotr) = @_;
+ my $vm = $trace>2 && $linux_debug ?
+ (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown';
+ warn " got " . blength($$gotr) . ':'
+ . blength($$replyr) . " bytes (VM=$vm).\n" if $trace == 3;
+ warn " got `$$gotr' (" . blength($$gotr) . ':'
+ . blength($$replyr) . " bytes, VM=$vm)\n" if $trace>3;
+}
+
+sub ssl_read_all {
+ my ($ssl,$how_much) = @_;
+ $how_much = 2000000000 unless $how_much;
+ my ($got, $errs);
+ my $reply = '';
+
+ while ($how_much > 0) {
+ $got = Net::SSLeay::read($ssl,
+ ($how_much > 32768) ? 32768 : $how_much
+ );
+ last if $errs = print_errs('SSL_read');
+ $how_much -= blength($got);
+ debug_read(\$reply, \$got) if $trace>1;
+ last if $got eq ''; # EOF
+ $reply .= $got;
+ }
+
+ return wantarray ? ($reply, $errs) : $reply;
+}
+
+sub tcp_read_all {
+ my ($how_much) = @_;
+ $how_much = 2000000000 unless $how_much;
+ my ($n, $got, $errs);
+ my $reply = '';
+
+ my $bsize = 0x10000;
+ while ($how_much > 0) {
+ $n = sysread(SSLCAT_S,$got, (($bsize < $how_much) ? $bsize : $how_much));
+ warn "Read error: $! ($n,$how_much)" unless defined $n;
+ last if !$n; # EOF
+ $how_much -= $n;
+ debug_read(\$reply, \$got) if $trace>1;
+ $reply .= $got;
+ }
+ return wantarray ? ($reply, $errs) : $reply;
+}
+
+sub ssl_write_all {
+ my $ssl = $_[0];
+ my ($data_ref, $errs);
+ if (ref $_[1]) {
+ $data_ref = $_[1];
+ } else {
+ $data_ref = \$_[1];
+ }
+ my ($wrote, $written, $to_write) = (0,0, blength($$data_ref));
+ my $vm = $trace>2 && $linux_debug ?
+ (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown';
+ warn " write_all VM at entry=$vm\n" if $trace>2;
+ while ($to_write) {
+ #sleep 1; # *** DEBUG
+ warn "partial `$$data_ref'\n" if $trace>3;
+ $wrote = write_partial($ssl, $written, $to_write, $$data_ref);
+ if (defined $wrote && ($wrote > 0)) { # write_partial can return -1
+ $written += $wrote;
+ $to_write -= $wrote;
+ }
+ $vm = $trace>2 && $linux_debug ?
+ (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown';
+ warn " written so far $wrote:$written bytes (VM=$vm)\n" if $trace>2;
+
+ $errs .= print_errs('SSL_write');
+ return (wantarray ? (undef, $errs) : undef) if $errs;
+ }
+ return wantarray ? ($written, $errs) : $written;
+}
+
+sub tcp_write_all {
+ my ($data_ref, $errs);
+ if (ref $_[0]) {
+ $data_ref = $_[0];
+ } else {
+ $data_ref = \$_[0];
+ }
+ my ($wrote, $written, $to_write) = (0,0, blength($$data_ref));
+ my $vm = $trace>2 && $linux_debug ?
+ (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown';
+ warn " write_all VM at entry=$vm to_write=$to_write\n" if $trace>2;
+ while ($to_write) {
+ warn "partial `$$data_ref'\n" if $trace>3;
+ $wrote = syswrite(SSLCAT_S, $$data_ref, $to_write, $written);
+ if (defined $wrote && ($wrote > 0)) { # write_partial can return -1
+ $written += $wrote;
+ $to_write -= $wrote;
+ } elsif (!defined($wrote)) {
+ warn "tcp_write_all: $!";
+ return (wantarray ? (undef, "$!") : undef);
+ }
+ $vm = $trace>2 && $linux_debug ?
+ (split ' ', `cat /proc/$$/stat`)[22] : 'vm_unknown';
+ warn " written so far $wrote:$written bytes (VM=$vm)\n" if $trace>2;
+ }
+ return wantarray ? ($written, '') : $written;
+}
+
+### from patch by Clinton Wong <clintdw@netcom.com>
+
+# ssl_read_until($ssl [, $delimit [, $max_length]])
+# if $delimit missing, use $/ if it exists, otherwise use \n
+# read until delimiter reached, up to $max_length chars if defined
+
+sub ssl_read_until ($;$$) {
+ my ($ssl,$delim, $max_length) = @_;
+ local $[;
+
+ # guess the delim string if missing
+ if ( ! defined $delim ) {
+ if ( defined $/ && length $/ ) { $delim = $/ }
+ else { $delim = "\n" } # Note: \n,$/ value depends on the platform
+ }
+ my $len_delim = length $delim;
+
+ my ($got);
+ my $reply = '';
+
+ # If we have OpenSSL 0.9.6a or later, we can use SSL_peek to
+ # speed things up.
+ # N.B. 0.9.6a has security problems, so the support for
+ # anything earlier than 0.9.6e will be dropped soon.
+ if (&Net::SSLeay::OPENSSL_VERSION_NUMBER >= 0x0090601f) {
+ $max_length = 2000000000 unless (defined $max_length);
+ my ($pending, $peek_length, $found, $done);
+ while (blength($reply) < $max_length and !$done) {
+ #Block if necessary until we get some data
+ $got = Net::SSLeay::peek($ssl,1);
+ last if print_errs('SSL_peek');
+
+ $pending = Net::SSLeay::pending($ssl) + blength($reply);
+ $peek_length = ($pending > $max_length) ? $max_length : $pending;
+ $peek_length -= blength($reply);
+ $got = Net::SSLeay::peek($ssl, $peek_length);
+ last if print_errs('SSL_peek');
+ $peek_length = blength($got);
+
+ #$found = index($got, $delim); # Old and broken
+
+ # the delimiter may be split across two gets, so we prepend
+ # a little from the last get onto this one before we check
+ # for a match
+ my $match;
+ if(blength($reply) >= blength($delim) - 1) {
+ #if what we've read so far is greater or equal
+ #in length of what we need to prepatch
+ $match = substr $reply, blength($reply) - blength($delim) + 1;
+ } else {
+ $match = $reply;
+ }
+
+ $match .= $got;
+ $found = index($match, $delim);
+
+ if ($found > -1) {
+ #$got = Net::SSLeay::read($ssl, $found+$len_delim);
+ #read up to the end of the delimiter
+ $got = Net::SSLeay::read($ssl,
+ $found + $len_delim
+ - ((blength $match) - (blength $got)));
+ $done = 1;
+ } else {
+ $got = Net::SSLeay::read($ssl, $peek_length);
+ $done = 1 if ($peek_length == $max_length - blength($reply));
+ }
+
+ last if print_errs('SSL_read');
+ debug_read(\$reply, \$got) if $trace>1;
+ last if $got eq '';
+ $reply .= $got;
+ }
+ } else {
+ while (!defined $max_length || length $reply < $max_length) {
+ $got = Net::SSLeay::read($ssl,1); # one by one
+ last if print_errs('SSL_read');
+ debug_read(\$reply, \$got) if $trace>1;
+ last if $got eq '';
+ $reply .= $got;
+ last if $len_delim
+ && substr($reply, blength($reply)-$len_delim) eq $delim;
+ }
+ }
+ return $reply;
+}
+
+sub tcp_read_until {
+ my ($delim, $max_length) = @_;
+ local $[;
+
+ # guess the delim string if missing
+ if ( ! defined $delim ) {
+ if ( defined $/ && length $/ ) { $delim = $/ }
+ else { $delim = "\n" } # Note: \n,$/ value depends on the platform
+ }
+ my $len_delim = length $delim;
+
+ my ($n,$got);
+ my $reply = '';
+
+ while (!defined $max_length || length $reply < $max_length) {
+ $n = sysread(SSLCAT_S, $got, 1); # one by one
+ warn "tcp_read_until: $!" if !defined $n;
+ debug_read(\$reply, \$got) if $trace>1;
+ last if !$n; # EOF
+ $reply .= $got;
+ last if $len_delim
+ && substr($reply, blength($reply)-$len_delim) eq $delim;
+ }
+ return $reply;
+}
+
+# ssl_read_CRLF($ssl [, $max_length])
+sub ssl_read_CRLF ($;$) { ssl_read_until($_[0], $CRLF, $_[1]) }
+sub tcp_read_CRLF { tcp_read_until($CRLF, $_[0]) }
+
+# ssl_write_CRLF($ssl, $message) writes $message and appends CRLF
+sub ssl_write_CRLF ($$) {
+ # the next line uses less memory but might use more network packets
+ return ssl_write_all($_[0], $_[1]) + ssl_write_all($_[0], $CRLF);
+
+ # the next few lines do the same thing at the expense of memory, with
+ # the chance that it will use less packets, since CRLF is in the original
+ # message and won't be sent separately.
+
+ #my $data_ref;
+ #if (ref $_[1]) { $data_ref = $_[1] }
+ # else { $data_ref = \$_[1] }
+ #my $message = $$data_ref . $CRLF;
+ #return ssl_write_all($_[0], \$message);
+}
+
+sub tcp_write_CRLF {
+ # the next line uses less memory but might use more network packets
+ return tcp_write_all($_[0]) + tcp_write_all($CRLF);
+
+ # the next few lines do the same thing at the expense of memory, with
+ # the chance that it will use less packets, since CRLF is in the original
+ # message and won't be sent separately.
+
+ #my $data_ref;
+ #if (ref $_[1]) { $data_ref = $_[1] }
+ # else { $data_ref = \$_[1] }
+ #my $message = $$data_ref . $CRLF;
+ #return tcp_write_all($_[0], \$message);
+}
+
+### Quickly print out with whom we're talking
+
+sub dump_peer_certificate ($) {
+ my ($ssl) = @_;
+ my $cert = get_peer_certificate($ssl);
+ return if print_errs('get_peer_certificate');
+ print "no cert defined\n" if !defined($cert);
+ # Cipher=NONE with empty cert fix
+ if (!defined($cert) || ($cert == 0)) {
+ warn "cert = `$cert'\n" if $trace;
+ return "Subject Name: undefined\nIssuer Name: undefined\n";
+ } else {
+ my $x = 'Subject Name: '
+ . X509_NAME_oneline(X509_get_subject_name($cert)) . "\n"
+ . 'Issuer Name: '
+ . X509_NAME_oneline(X509_get_issuer_name($cert)) . "\n";
+ Net::SSLeay::X509_free($cert);
+ return $x;
+ }
+}
+
+### Arrange some randomness for eay PRNG
+
+sub randomize (;$$) {
+ my ($rn_seed_file, $seed, $egd_path) = @_;
+ my $rnsf = defined($rn_seed_file) && -r $rn_seed_file;
+
+ $egd_path = '';
+ $egd_path = $ENV{'EGD_PATH'} if $ENV{'EGD_PATH'};
+
+ RAND_seed(rand() + $$); # Stir it with time and pid
+
+ unless ($rnsf || -r $Net::SSLeay::random_device || $seed || -S $egd_path) {
+ warn "Random number generator not seeded!!!" if $trace;
+ }
+
+ RAND_load_file($rn_seed_file, -s _) if $rnsf;
+ RAND_seed($seed) if $seed;
+ RAND_seed($ENV{RND_SEED}) if $ENV{RND_SEED};
+ RAND_egd($egd_path) if -e $egd_path && -S _;
+ RAND_load_file($Net::SSLeay::random_device, $Net::SSLeay::how_random/8)
+ if -r $Net::SSLeay::random_device;
+}
+
+sub new_x_ctx {
+ if ($ssl_version == 2) { $ctx = CTX_v2_new(); }
+ elsif ($ssl_version == 3) { $ctx = CTX_v3_new(); }
+ elsif ($ssl_version == 10) { $ctx = CTX_tlsv1_new(); }
+ else { $ctx = CTX_new(); }
+ return $ctx;
+}
+
+###
+### Basic request - response primitive (don't use for https)
+###
+
+sub sslcat { # address, port, message, $crt, $key --> reply / (reply,errs,cert)
+ my ($dest_serv, $port, $out_message, $crt_path, $key_path) = @_;
+ my ($ctx, $ssl, $got, $errs, $written);
+
+ ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port);
+ return (wantarray ? (undef, $errs) : undef) unless $got;
+
+ ### Do SSL negotiation stuff
+
+ warn "Creating SSL $ssl_version context...\n" if $trace>2;
+ load_error_strings(); # Some bloat, but I'm after ease of use
+ SSLeay_add_ssl_algorithms(); # and debuggability.
+ randomize();
+
+ $ctx = new_x_ctx();
+ goto cleanup2 if $errs = print_errs('CTX_new') or !$ctx;
+
+ CTX_set_options($ctx, &OP_ALL);
+ goto cleanup2 if $errs = print_errs('CTX_set_options');
+
+ warn "Cert `$crt_path' given without key" if $crt_path && !$key_path;
+ set_cert_and_key($ctx, $crt_path, $key_path) if $crt_path;
+
+ warn "Creating SSL connection (context was '$ctx')...\n" if $trace>2;
+ $ssl = new($ctx);
+ goto cleanup if $errs = print_errs('SSL_new') or !$ssl;
+
+ warn "Setting fd (ctx $ctx, con $ssl)...\n" if $trace>2;
+ set_fd($ssl, fileno(SSLCAT_S));
+ goto cleanup if $errs = print_errs('set_fd');
+
+ warn "Entering SSL negotiation phase...\n" if $trace>2;
+
+ if ($trace>2) {
+ my $i = 0;
+ my $p = '';
+ my $cipher_list = 'Cipher list: ';
+ $p=Net::SSLeay::get_cipher_list($ssl,$i);
+ $cipher_list .= $p if $p;
+ do {
+ $i++;
+ $cipher_list .= ', ' . $p if $p;
+ $p=Net::SSLeay::get_cipher_list($ssl,$i);
+ } while $p;
+ $cipher_list .= '\n';
+ warn $cipher_list;
+ }
+
+ $got = Net::SSLeay::connect($ssl);
+ warn "SSLeay connect returned $got\n" if $trace>2;
+ goto cleanup if $errs = print_errs('SSL_connect');
+
+ my $server_cert = get_peer_certificate($ssl);
+ print_errs('get_peer_certificate');
+ if ($trace>1) {
+ warn "Cipher `" . get_cipher($ssl) . "'\n";
+ print_errs('get_ciper');
+ warn dump_peer_certificate($ssl);
+ }
+
+ ### Connected. Exchange some data (doing repeated tries if necessary).
+
+ warn "sslcat $$: sending " . blength($out_message) . " bytes...\n"
+ if $trace==3;
+ warn "sslcat $$: sending `$out_message' (" . blength($out_message)
+ . " bytes)...\n" if $trace>3;
+ ($written, $errs) = ssl_write_all($ssl, $out_message);
+ goto cleanup unless $written;
+
+ sleep $slowly if $slowly; # Closing too soon can abort broken servers
+ CORE::shutdown SSLCAT_S, 1; # Half close --> No more output, send EOF to server
+
+ warn "waiting for reply...\n" if $trace>2;
+ ($got, $errs) = ssl_read_all($ssl);
+ warn "Got " . blength($got) . " bytes.\n" if $trace==3;
+ warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3;
+
+cleanup:
+ free ($ssl);
+ $errs .= print_errs('SSL_free');
+cleanup2:
+ CTX_free ($ctx);
+ $errs .= print_errs('CTX_free');
+ close SSLCAT_S;
+ return wantarray ? ($got, $errs, $server_cert) : $got;
+}
+
+sub tcpcat { # address, port, message, $crt, $key --> reply / (reply,errs,cert)
+ my ($dest_serv, $port, $out_message) = @_;
+ my ($got, $errs, $written);
+
+ ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port);
+ return (wantarray ? (undef, $errs) : undef) unless $got;
+
+ ### Connected. Exchange some data (doing repeated tries if necessary).
+
+ warn "tcpcat $$: sending " . blength($out_message) . " bytes...\n"
+ if $trace==3;
+ warn "tcpcat $$: sending `$out_message' (" . blength($out_message)
+ . " bytes)...\n" if $trace>3;
+ ($written, $errs) = tcp_write_all($out_message);
+ goto cleanup unless $written;
+
+ sleep $slowly if $slowly; # Closing too soon can abort broken servers
+ CORE::shutdown SSLCAT_S, 1; # Half close --> No more output, send EOF to server
+
+ warn "waiting for reply...\n" if $trace>2;
+ ($got, $errs) = tcp_read_all($ssl);
+ warn "Got " . blength($got) . " bytes.\n" if $trace==3;
+ warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3;
+
+cleanup:
+ close SSLCAT_S;
+ return wantarray ? ($got, $errs) : $got;
+}
+
+sub tcpxcat {
+ my ($usessl, $site, $port, $req, $crt_path, $key_path) = @_;
+ if ($usessl) {
+ return sslcat($site, $port, $req, $crt_path, $key_path);
+ } else {
+ return tcpcat($site, $port, $req);
+ }
+}
+
+###
+### Basic request - response primitive, this is different from sslcat
+### because this does not shutdown the connection.
+###
+
+sub https_cat { # address, port, message --> returns reply / (reply,errs,cert)
+ my ($dest_serv, $port, $out_message, $crt_path, $key_path) = @_;
+ my ($ctx, $ssl, $got, $errs, $written);
+
+ ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port);
+ return (wantarray ? (undef, $errs) : undef) unless $got;
+
+ ### Do SSL negotiation stuff
+
+ warn "Creating SSL $ssl_version context...\n" if $trace>2;
+ load_error_strings(); # Some bloat, but I'm after ease of use
+ SSLeay_add_ssl_algorithms(); # and debuggability.
+ randomize();
+
+ $ctx = new_x_ctx();
+ goto cleanup2 if $errs = print_errs('CTX_new') or !$ctx;
+
+ CTX_set_options($ctx, &OP_ALL);
+ goto cleanup2 if $errs = print_errs('CTX_set_options');
+
+ warn "Cert `$crt_path' given without key" if $crt_path && !$key_path;
+ set_cert_and_key($ctx, $crt_path, $key_path) if $crt_path;
+
+ warn "Creating SSL connection (context was '$ctx')...\n" if $trace>2;
+ $ssl = new($ctx);
+ goto cleanup if $errs = print_errs('SSL_new') or !$ssl;
+
+ warn "Setting fd (ctx $ctx, con $ssl)...\n" if $trace>2;
+ set_fd($ssl, fileno(SSLCAT_S));
+ goto cleanup if $errs = print_errs('set_fd');
+
+ warn "Entering SSL negotiation phase...\n" if $trace>2;
+
+ if ($trace>2) {
+ my $i = 0;
+ my $p = '';
+ my $cipher_list = 'Cipher list: ';
+ $p=Net::SSLeay::get_cipher_list($ssl,$i);
+ $cipher_list .= $p if $p;
+ do {
+ $i++;
+ $cipher_list .= ', ' . $p if $p;
+ $p=Net::SSLeay::get_cipher_list($ssl,$i);
+ } while $p;
+ $cipher_list .= '\n';
+ warn $cipher_list;
+ }
+
+ $got = Net::SSLeay::connect($ssl);
+ warn "SSLeay connect failed" if $trace>2 && $got==0;
+ goto cleanup if $errs = print_errs('SSL_connect');
+
+ my $server_cert = get_peer_certificate($ssl);
+ print_errs('get_peer_certificate');
+ if ($trace>1) {
+ warn "Cipher `" . get_cipher($ssl) . "'\n";
+ print_errs('get_ciper');
+ warn dump_peer_certificate($ssl);
+ }
+
+ ### Connected. Exchange some data (doing repeated tries if necessary).
+
+ warn "https_cat $$: sending " . blength($out_message) . " bytes...\n"
+ if $trace==3;
+ warn "https_cat $$: sending `$out_message' (" . blength($out_message)
+ . " bytes)...\n" if $trace>3;
+ ($written, $errs) = ssl_write_all($ssl, $out_message);
+ goto cleanup unless $written;
+
+ warn "waiting for reply...\n" if $trace>2;
+ ($got, $errs) = ssl_read_all($ssl);
+ warn "Got " . blength($got) . " bytes.\n" if $trace==3;
+ warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3;
+
+cleanup:
+ free ($ssl);
+ $errs .= print_errs('SSL_free');
+cleanup2:
+ CTX_free ($ctx);
+ $errs .= print_errs('CTX_free');
+ close SSLCAT_S;
+ return wantarray ? ($got, $errs, $server_cert) : $got;
+}
+
+sub http_cat { # address, port, message --> returns reply / (reply,errs,cert)
+ my ($dest_serv, $port, $out_message) = @_;
+ my ($got, $errs, $written);
+
+ ($got, $errs) = open_proxy_tcp_connection($dest_serv, $port);
+ return (wantarray ? (undef, $errs) : undef) unless $got;
+
+ ### Connected. Exchange some data (doing repeated tries if necessary).
+
+ warn "http_cat $$: sending " . blength($out_message) . " bytes...\n"
+ if $trace==3;
+ warn "http_cat $$: sending `$out_message' (" . blength($out_message)
+ . " bytes)...\n" if $trace>3;
+ ($written, $errs) = tcp_write_all($out_message);
+ goto cleanup unless $written;
+
+ warn "waiting for reply...\n" if $trace>2;
+ ($got, $errs) = tcp_read_all(200000);
+ warn "Got " . blength($got) . " bytes.\n" if $trace==3;
+ warn "Got `$got' (" . blength($got) . " bytes)\n" if $trace>3;
+
+cleanup:
+ close SSLCAT_S;
+ return wantarray ? ($got, $errs) : $got;
+}
+
+sub httpx_cat {
+ my ($usessl, $site, $port, $req, $crt_path, $key_path) = @_;
+ warn "httpx_cat: usessl=$usessl ($site:$port)" if $trace;
+ if ($usessl) {
+ return https_cat($site, $port, $req, $crt_path, $key_path);
+ } else {
+ return http_cat($site, $port, $req);
+ }
+}
+
+###
+### Easy set up of private key and certificate
+###
+
+sub set_cert_and_key ($$$) {
+ my ($ctx, $cert_path, $key_path) = @_;
+ my $errs = '';
+ # Following will ask password unless private key is not encrypted
+ CTX_use_RSAPrivateKey_file ($ctx, $key_path, &FILETYPE_PEM);
+ $errs .= print_errs("private key `$key_path' ($!)");
+ CTX_use_certificate_file ($ctx, $cert_path, &FILETYPE_PEM);
+ $errs .= print_errs("certificate `$cert_path' ($!)");
+ return wantarray ? (undef, $errs) : ($errs eq '');
+}
+
+### Old deprecated API
+
+sub set_server_cert_and_key ($$$) { &set_cert_and_key }
+
+### Set up to use web proxy
+
+sub set_proxy ($$;**) {
+ ($proxyhost, $proxyport, $proxyuser, $proxypass) = @_;
+ require MIME::Base64 if $proxyuser;
+ $proxyauth = $CRLF . 'Proxy-authorization: Basic '
+ . MIME::Base64::encode("$proxyuser:$proxypass", '')
+ if $proxyuser;
+}
+
+###
+### Easy https manipulation routines
+###
+
+sub make_form {
+ my (@fields) = @_;
+ my $form;
+ while (@fields) {
+ my ($name, $data) = (shift(@fields), shift(@fields));
+ $data =~ s/([^\w\-.\@\$ ])/sprintf("%%%2.2x",ord($1))/gse;
+ $data =~ tr[ ][+];
+ $form .= "$name=$data&";
+ }
+ chop $form;
+ return $form;
+}
+
+sub make_headers {
+ my (@headers) = @_;
+ my $headers;
+ while (@headers) {
+ my $header = shift(@headers);
+ my $value = shift(@headers);
+ $header =~ s/:$//;
+ $value =~ s/\x0d?\x0a$//; # because we add it soon, see below
+ $headers .= "$header: $value$CRLF";
+ }
+ return $headers;
+}
+
+sub do_httpx3 {
+ my ($method, $usessl, $site, $port, $path, $headers,
+ $content, $mime_type, $crt_path, $key_path) = @_;
+ my ($response, $page, $h,$v);
+
+ if ($content) {
+ $mime_type = "application/x-www-form-urlencoded" unless $mime_type;
+ my $len = blength($content);
+ $content = "Content-Type: $mime_type$CRLF"
+ . "Content-Length: $len$CRLF$CRLF$content";
+ } else {
+ $content = "$CRLF$CRLF";
+ }
+ my $req = "$method $path HTTP/1.0$CRLF";
+ unless (defined $headers && $headers =~ /^Host:/m) {
+ $req .= "Host: $site";
+ unless (($port == 80 && !$usessl) || ($port == 443 && $usessl)) {
+ $req .= ":$port";
+ }
+ $req .= $CRLF;
+ }
+ $req .= (defined $headers ? $headers : '') . "Accept: */*$CRLF$content";
+
+ warn "do_httpx3($method,$usessl,$site:$port)" if $trace;
+ my ($http, $errs, $server_cert)
+ = httpx_cat($usessl, $site, $port, $req, $crt_path, $key_path);
+ return (undef, "HTTP/1.0 900 NET OR SSL ERROR$CRLF$CRLF$errs") if $errs;
+
+ $http = '' if !defined $http;
+ ($headers, $page) = split /\s?\n\s?\n/, $http, 2;
+ warn "headers >$headers< page >>$page<< http >>>$http<<<" if $trace>1;
+ ($response, $headers) = split /\s?\n/, $headers, 2;
+ return ($page, $response, $headers, $server_cert);
+}
+
+sub do_https3 { splice(@_,1,0) = 1; do_httpx3; } # Legacy undocumented
+
+### do_https2() is a legacy version in the sense that it is unable
+### to return all instances of duplicate headers.
+
+sub do_httpx2 {
+ my ($page, $response, $headers, $server_cert) = &do_httpx3;
+ X509_free($server_cert) if defined $server_cert;
+ return ($page, $response,
+ map( { ($h,$v)=/^(\S+)\:\s*(.*)$/; (uc($h),$v); }
+ split(/\s?\n/, $headers)
+ )
+ );
+}
+
+sub do_https2 { splice(@_,1,0) = 1; do_httpx2; } # Legacy undocumented
+
+### Returns headers as a hash where multiple instances of same header
+### are handled correctly.
+
+sub do_httpx4 {
+ my ($page, $response, $headers, $server_cert) = &do_httpx3;
+ X509_free($server_cert) if defined $server_cert;
+ my %hr = ();
+ for my $hh (split /\s?\n/, $headers) {
+ my ($h,$v)=/^(\S+)\:\s*(.*)$/;
+ push @{$hr{uc($h)}}, $v;
+ }
+ return ($page, $response, \%hr);
+}
+
+sub do_https4 { splice(@_,1,0) = 1; do_httpx4; } # Legacy undocumented
+
+# https
+
+sub get_https { do_httpx2(GET => 1, @_) }
+sub post_https { do_httpx2(POST => 1, @_) }
+sub put_https { do_httpx2(PUT => 1, @_) }
+sub head_https { do_httpx2(HEAD => 1, @_) }
+
+sub get_https3 { do_httpx3(GET => 1, @_) }
+sub post_https3 { do_httpx3(POST => 1, @_) }
+sub put_https3 { do_httpx3(PUT => 1, @_) }
+sub head_https3 { do_httpx3(HEAD => 1, @_) }
+
+sub get_https4 { do_httpx4(GET => 1, @_) }
+sub post_https4 { do_httpx4(POST => 1, @_) }
+sub put_https4 { do_httpx4(PUT => 1, @_) }
+sub head_https4 { do_httpx4(HEAD => 1, @_) }
+
+# http
+
+sub get_http { do_httpx2(GET => 0, @_) }
+sub post_http { do_httpx2(POST => 0, @_) }
+sub put_http { do_httpx2(PUT => 0, @_) }
+sub head_http { do_httpx2(HEAD => 0, @_) }
+
+sub get_http3 { do_httpx3(GET => 0, @_) }
+sub post_http3 { do_httpx3(POST => 0, @_) }
+sub put_http3 { do_httpx3(PUT => 0, @_) }
+sub head_http3 { do_httpx3(HEAD => 0, @_) }
+
+sub get_http4 { do_httpx4(GET => 0, @_) }
+sub post_http4 { do_httpx4(POST => 0, @_) }
+sub put_http4 { do_httpx4(PUT => 0, @_) }
+sub head_http4 { do_httpx4(HEAD => 0, @_) }
+
+# Either https or http
+
+sub get_httpx { do_httpx2(GET => @_) }
+sub post_httpx { do_httpx2(POST => @_) }
+sub put_httpx { do_httpx2(PUT => @_) }
+sub head_httpx { do_httpx2(HEAD => @_) }
+
+sub get_httpx3 { do_httpx3(GET => @_) }
+sub post_httpx3 { do_httpx3(POST => @_) }
+sub put_httpx3 { do_httpx3(PUT => @_) }
+sub head_httpx3 { do_httpx3(HEAD => @_) }
+
+sub get_httpx4 { do_httpx4(GET => @_) }
+sub post_httpx4 { do_httpx4(POST => @_) }
+sub put_httpx4 { do_httpx4(PUT => @_) }
+sub head_httpx4 { do_httpx4(HEAD => @_) }
+
+### Legacy, don't use
+# ($page, $respone_or_err, %headers) = do_https(...);
+
+sub do_https {
+ my ($site, $port, $path, $method, $headers,
+ $content, $mime_type, $crt_path, $key_path) = @_;
+
+ do_https2($method, $site, $port, $path, $headers,
+ $content, $mime_type, $crt_path, $key_path);
+}
+
+1;
+__END__