From b893dc3dd4b3ded21a11994ea54c431ecead26e4 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 16 2020 15:08:18 +0000 Subject: perl-Net-SSLeay-1.88 base --- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..20f1132 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# How to contribute + +Contributions to Net::SSLeay are welcome. + +## Source code repository +The Net::SSLeay source code is currently hosted on +[GitHub](https://github.com/radiator-software/p5-net-ssleay). + +If you clone Net::SSLeay from GitHub, a pre-requisite for building +Net::SSLeay is Module::Install Perl module. Module::Install is not +needed when building from release packages. + +## Issue tracking +Issues can be currently reported using CPAN [bug +tracker](https://rt.cpan.org/Public/Dist/Display.html?Name=net-ssleay) +or [GitHub](https://github.com/radiator-software/p5-net-ssleay) + +Choose the method that is more convenient for you. + +## Patches and code contributions +GitHub pull requests are preferred, but please do not hesitate to use +the CPAN bug tracker or any other means to send your contribution. + +All contributions to Net-SSLeay are assumed to be provided under the +terms of the Artistic License 2.0. See [`LICENSE`](LICENSE) for details. + +## More information +See [README](README) for more information about this module. diff --git a/Changes b/Changes new file mode 100644 index 0000000..34dcd0a --- /dev/null +++ b/Changes @@ -0,0 +1,1504 @@ +Revision history for Perl extension Net::SSLeay. + +1.88 2019-05-10 + - New stable release incorporating all changes from developer + releases 1.86_01 to 1.86_11. + - From this release, Net-SSLeay is switching to an "odd/even" + developer/stable release version numbering system, like that of + many core modules (e.g. ExtUtils::MakeMaker): developer releases + will have an odd minor version number (and the usual "_xx" suffix), + and stable releases will have an even minor version number. This + means there is no Net-SSLeay 1.87. + - Summary of major changes since version 1.85: + - Mike McCauley has stepped down as maintainer. The new maintainers + are Chris Novakovic, Heikki Vatiainen and Tuure Vartiainen. + - The source code has moved from the now-defunct Debian Subversion + server (alioth.debian.org) to GitHub + (https://github.com/radiator-software/p5-net-ssleay). + - Net-SSLeay is provided under the terms of the Artistic License + 2.0 - this has been the case since version 1.66, but references + to other licenses remained in the source code, causing ambiguity. + - Perl 5.8.1 or newer is now required to use Net-SSLeay. This has + already been the case for some time in practice, as the test + suite hasn't fully passed on Perl 5.6 for several years. + - Much-improved compatibility with OpenSSL 1.1.1, and improved + support for TLS 1.3. + - Fixed a long-standing bug in cb_data_advanced_put() that caused + memory leaks when callbacks were frequently added and removed. + - Support in the test suite for "hardened" OpenSSL configurations + that set a default security level of 2 or higher (e.g., in the + OpenSSL packages that ship with recent versions of Debian, Fedora + and Ubuntu). + +1.86_11 2019-05-08 + - Clarified Net-SSLeay's licensing terms: the module distribution has + been released under the terms of the Artistic License 2.0 since + version 1.66; references to other licenses have been removed. Fixes + RT#106314. Thanks to Kent Fredric for pointing out the ambiguity. + - Replace the HTTPS hosts in the external tests (some of which were + no longer online) with more resilient ones. Closes issue #26. + +1.86_10 2019-05-04 + - Use locally-generated certificate chain in local tests rather + than the Twitter one, which changes regularly and breaks the + test suite unnecessarily. Fixes RT#129201. Thanks to Petr Písař + for the report and patch, and Steffen Ullrich for an alternative + patch suggestion. + - In t/local/09_ctx_new.t, rather than checking that the functions + (CTX_)get_min_proto_version and (CTX_)get_max_proto_version return + 0x0000 (indicating the lowest and highest versions supported by + libssl respectively, which is not the case if a run-time + configuration is enforcing a different minimum or maximum), just + check whether the returned value is one of those mentioned on the + SSL_CTX_set_min_proto_version(3) man page. Partially fixes + RT#128025. Thanks to Slaven Rezić and Dmytro Zagashev for the + downstream reports. + - Move from 1024-bit keys/certificates to 2048-bit keys/certificates + across the entire test suite. This removes the need to manually + set the security level to 1 in tests that used the old keys, and + fixes large numbers of test failures on modern Linux distributions + that set the minimum OpenSSL security level to 2. Fixes RT#126270 + and the remainder of RT#128025. Thanks to Petr Písař and Slaven + Rezić for the downstream reports. + - In t/local/06_tcpecho.t and t/local/07_sslecho.t, connect to + 127.0.0.1 instead of localhost. This fixes these tests when + executed inside a network sandbox that disrupts the behaviour of + gethostbyname(). Fixes RT#128207. Thanks to Kent Fredric for the + downstream report. + +1.86_09 2019-03-12 + - Add missing files to MANIFEST that prevented tests from passing + when installing from the 1.86_08 release tarball. + +1.86_08 2019-03-12 + - Add and fix functions needed to properly implement client + side session reuse for TLS 1.3 with using + CTX_sess_set_new_cb. Newly exposed functions: + SSL_SESSION_dup and SSL_SESSION_up_ref. + Fixed functions: i2d_SSL_SESSION and d2i_SSL_SESSION. + Thanks to Steffen Ullrich. + - Add functions functions to allow reading multiple pems from + file and creating untrusted chain: These functions allow you + to: + - Read in a PEM file with multiple certificates as a + STACK_OF(X509_INFO) + - Determine the size of the STACK_OF(X509_INFO) and value at + an index, which allows you to loop over the stack. + - Retrieve the X509 structure from each X509_INFO structure + in the stack. + Then you can create a new STACK_OF(X509) and push the X509 + structures onto the new stack. You can then pass this + STACK_OF(X509) to X509_STORE_CTX_init which will allow you + to add additional untrusted certificates to the chain for + verification. Exposed functions are: + PEM_X509_INFO_read_bio + sk_X509_INFO_num + sk_X509_INFO_value + sk_X509_INFO_free + sk_X509_new_null + sk_X509_free + sk_X509_push + New function implemented by Net::SSLeay: + P_X509_INFO_get_x509 + Thanks to Marc Reisner. + - Add functions and constants that are necessary to verify a + certificate using a hash directory outside of an SSL/TLS + connection. Newly exposed functions: + X509_STORE_CTX_init + X509_STORE_CTX_free + X509_STORE_new + X509_STORE_free + X509_STORE_add_lookup + X509_LOOKUP_hash_dir + X509_LOOKUP_add_dir + Newly exposed constants: + X509_FILETYPE_ASN1 + X509_FILETYPE_DEFAULT + X509_FILETYPE_PEM + Thanks to Marc Reisner. + - Declare n_a in ssleay_set_psk_client_callback_invoke and + ssleay_ctx_set_psk_client_callback_invoke to avoid a compilation + error with Perl versions below 5.8.8. Fixes RT#128030. Thanks to + Graham Ollis for the report. + - Add X509_get0_serialNumber. Thanks to Marc Reisner. + - Enable Travis CI for LibreSSL 2.2.1, 2.7.5, 2.8.3 and 2.9.0 + on Perl 5.20 and more recent. + - Expose the following functions for curve and group selection: + - CTX_set_ecdh_auto, set_ecdh_auto + - CTX_set1_curves_list, set1_curves_list + - CTX_set1_groups_list, set1_groups_list + Thanks to Steffen Ullrich. + +1.86_07 2018-12-13 + - Net::SSLeay::RSA_generate_key() now prefers using + RSA_generate_key_ex. This avois deprecated RSA_generate_key + and allows removing the only Android specific code in + SSLeay.xs. Fixes RT#127593. Thanks to Rouven Weiler. + - SSL_CTX_get0_param, SSL_CTX_get0_param, + X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host, + X509_VERIFY_PARAM_set_hostflags, + X509_VERIFY_PARAM_get0_peername, + X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip and + X509_VERIFY_PARAM_set1_ip_asc added in 1.83 for OpenSSL + 1.0.2 and later are now available with LibreSSL 2.7.0 and + later. + - get_keyblock_size() now gets the MAC secret size from the + cipher on LibreSSL 2.7.0 and later, rather than reaching + into libssl internals. This effectively takes the OpenSSL + 1.1 code path for LibreSSL 2.7.0 instead of the OpenSSL 1.0 + code path. Thanks to Alexander Bluhm. + - get_client_random and get_server_random now use API + functions supported by LibreSSL 2.7.0 and later. Thanks to + Alexander Bluhm. + - Add X509_check_host(), X509_check_email(), X509_check_ip(), + and X509_check_ip_asc() for LibreSSL 2.5.0 and later. Thanks + to Alexander Bluhm. + - OpenSSL_version() and OpenSSL_version_num() are available + with LibreSSL 2.7.0 and later. Thanks to Alexander Bluhm. + - Use OPENSSL_cleanse() instead of memset(). Fixes + RT#116599. Thanks to A. Sinan Unur. + +1.86_06 2018-09-29 + - Net::SSLeay::read() and SSL_peek() now check SSL_get_error() + for SSL_ERROR_ZERO_RETURN for return values <= 0 to make + Net::SSLeay::read() behave more like underlying OpenSSL + function SSL_read(). + Convenience function ssl_read_all() now does an automatic + retry when ERROR_WANT_READ or ERROR_WANT_WRITE is returned + with Net::SSLeay::read(). + Convenience function ssl_read_until() now uses + Net::SSLeay::ssl_read_all() instead of + Net::SSLeay::read(). Tests 07_sslecho.t and 36_verify.t were + also updated to use ssl_read_all() and ssl_write_all(). The + tests now also disable TLSv1.3 session tickets and ignore + SIGPIPE to avoid this signal when the client has finished + before server has sent session tickets and called + Net::SSLeay::accept(). + Thanks to Petr Pisar and Sebastian Andrzej Siewior for the + patches (in #RT125218). + - Fix a memory leak in cb_data_advanced_put. Fixes + RT#127131. Noticed, investigated and patched by Paul + Evans. Thanks! + - Enable OpenSSL 1.1.1-pre9 with Travis CI. + - Add SSL_CTX_set_num_tickets, SSL_CTX_get_num_tickets, + SSL_set_num_ticket and SSL_get_num_tickets for controlling + the number of TLSv1.3 session tickets that are issued. Add + tests in 44_sess.t. Parts taken from a larger patch by Petr + Pisar of RedHat. + - Add SSL_CTX_set_ciphersuites and SSL_set_ciphersuites for + configuring the available TLSv1.3 ciphersuites. Add tests in + 43_misc_functions.t and clarify SSL_client_version tests. + - Add SSL_CTX_set_security_level, SSL_CTX_get_security_level, + SSL_set_security_level and SSL_get_security_level. + Add new test file 65_security_level.t. + All courtesy of Damyan Ivanov of Debian project. + - Fix export_keying_material return value check and context + handling. SSL_export_keying_material use_context is now + correctly set to non-zero value when context is an empty + string. This affects values exported with TLSv1.2 and earlier. + Update documentation in NetSSLeay.pod and add tests + in t/local/45_export.t. + - Add RAND_priv_bytes. Add new test file t/local/10_rand.t for + RAND_bytes, RAND_pseudo_bytes, RAND_priv_bytes, RAND_status, + RAND_poll, RAND_file_name and RAND_load_file. + - Update documentation for RAND_*bytes return values and + RAND_file_name behaviour with LibreSSL. + - Add SSL_SESSION_is_resumable. Add and update tests in 44_sess.t. + - Set OpenSSL security level to 1 in tests that use the test suite's + (1024-bit) RSA keys, which allows the test suite to pass when + Net-SSLeay is built against an OpenSSL with a higher default + security level. Fixes RT#126987. Thanks to Petr Pisar (in + RT#126270) and Damyan Ivanov (in RT#126987) for the reports and + patches, and to Damyan Ivanov for the preferred patch. + - Add SSL_CTX_sess_set_new_cb and SSL_CTX_sess_set_remove_cb. + Add new test file 44_sess.t for these and future session + related tests for which no specific test file is needed. + - Add SSL_get_version, SSL_client_version and SSL_is_dtls. + - Add SSL_peek_ex, SSL_read_ex, SSL_write_ex and SSL_has_pending. + Add tests in t/local/11_read.t + - Add SSL_CTX_set_post_handshake_auth contributed by Paul + Howarth. Add SSL_set_post_handshake_auth, + SSL_verify_client_post_handshake and constant + SSL_VERIFY_POST_HANDSHAKE. + - Applied a patch to set_cert_and_key() from Damyan Ivanov, + Debian Perl Group. This function now returns errors from + library's error stack only when an underlying routine + fails. Unrelated errors are now skipped. Fixes RT#126988. + - Add support for TLSv1.3 via $Net::SSLeay::ssl_version. + - Enhance t/local/43_misc_functions.t get_keyblock_size test + to work better with AEAD ciphers. + - Add constants SSL_OP_ENABLE_MIDDLEBOX_COMPAT and + SSL_OP_NO_ANTI_REPLAY for TLSv1.3 + - Fix compile time DEFINE=-DSHOW_XS_DEBUG to work with + non-threaded Perls. Fixes RT#127027. Thanks to SREZIC for + the report. Also fix other minor compile warnings. + +1.86_05 2018-08-22 + - Net-SSLeay now requires at least Perl 5.8.1. This is a + formalisation of what has been the de facto case for some time, + as the distribution hasn't compiled and passed its tests on Perl + 5.005 for several years. + - Increment Net::SSLeay::Handle's version number to keep it in sync + with Net::SSLeay's, thus satisfying Kwalitee's consistent_version + metric. + - Re-enable the d2i_X509_bio() test in t/local/33_x509_create_cert.t + for LibreSSL. Thanks to Alexander Bluhm. + - Automatically detect new library names on Windows for OpenSSL + 1.1.0 onwards (libcrypto, libssl). Fixes part of RT#121084. Thanks + to Jean-Damien Durand. + - Fix a typo preventing OpenSSL libraries built with the VC compiler + (i.e. ones with a ".lib" suffix) from being automatically detected + on Windows. Fixes part of RT#121084. Thanks to Jean-Damien Durand. + - Add missing call to va_end() following va_start() in TRACE(). + Fixes RT#126028. Thanks to Jitka Plesnikova. + - Added SSL_in_init() and the related functions for all + libraries and their versions. All return 0 or 1 as + documented by OpenSSL 1.1.1. Use of these functions is + recommended over using constants returned by get_state() and + state(). New constants TLS_ST_*, used by OpenSSL 1.1.0 and + later, will not be made available by Net::SSLeay. + +1.86_04 2018-07-30 + - Re-add SSLv3_method() for OpenSSL 1.0.2 and above. Fixes + RT#101484. + - Don't expose ENGINE-related functions when building against + OpenSSL builds without ENGINE support. Fixes RT#121538. Thanks to + Paul Green. + - Automatically detect OpenSSL 1.0.x on VMS, and update VMS + installation instructions to reflect removal of Module::Install + from the build system. Fixes RT#124388. Thanks to Craig A. Berry. + - Prevent memory leak in OCSP_cert2ids() and OCSP_response_verify(). + Fixes RT#125273. Thanks to Steffen Ullrich. + +1.86_03 2018-07-19 + - Convert packaging to ExtUtils::MakeMaker. Thanks to mohawk2. + - Module::Install is no longer a prerequisite when building + from the reposistory. + - Re-apply patch from ETJ permitting configure and build in + places with a space in the name. + +1.86_02 2018-07-06 + - Removed inc/ from repository. Module::Install is now a + prerequisite when building from the repository. This allowed + also removing "." from Makefile.PL lib path which was added + in version 1.81. These updates require no changes when + building from release packages. They also help AppVeyor + builds to work better with old Perls. + + - Added CONTRIBUTING.md, reformatted the previous Changes + entry to use CPAN::Changes::Spec guidelines and removed + unused version control tags from comments. + +1.86_01 2018-07-04 + - Net::SSLeay functionality was not changed in this release. + + - Maintainer changes: + - Mike McCauley, maintainer of Net-SSLeay since November 2005, + has stepped down. Thanks to Mike for his 13 years of + stewardship. + - Net-SSLeay is now maintained by Chris Novakovic, Heikki + Vatiainen and Tuure Vartiainen. + + - Version control system changes: + - The previous Debian-hosted SVN repository has been imported + into Git. The source code is now maintained on GitHub, at + https://github.com/radiator-software/p5-net-ssleay. + + - Fixes to commit metadata, branches and tags that git-svn + couldn't handle or had no way of handling, were done + manually or semi-automatically afterwards. For instance, the + "git-svn-id:" lines that git-svn appends to commit messages + were kept because Mike used SVN revision numbers in RT + replies to indicate when bugs had been fixed/patches applied + (which may be useful for future reference). + + - All commits were replayed onto a single master branch rather + than having separate dead-end branches for the old SVN + version tags (as this seems more "git-like"). + + - New lightweight tags were created for each public release + going back as far as the start of the SVN repository using + data from MetaCPAN (cross-referencing with the changelog + when it wasn't clear when a release was cut from the SVN + repo). + + - Florian's and Mike's email addresses were mapped to git + author/committer IDs + + - Continuous integration: + - Travis CI configuration was added for automated testing on + Linux using 64 bit Ubuntu Trusty. Build matrix dimensions + are: Perl 5.8 - 5.26 x OpenSSL 0.9.8zh - 1.1.0h. Only the + currently latest version for each major Perl and OpenSSL + release is chosen. + + - AppVeyor configuration was added for automated testing on + Windows. Build matrix dimensions are: Perl 5.8 - 5.26 x + 32bit and 64bit Perl environment x Windows Server 2012R2 and + Windows Server 2016. The Perl environment is Strawberry Perl + and its OpenSSL is used with builds. Only the latest major + versions are used, similarly to Travis CI. Net-SSLeay PPM + and PPD files are made available as artifacts. + + - Added README.md with link to master branch build and test + status. Did minor updates to README and other misc files. + + - Release packaging: + - Files t/local/43_misc_functions.t and + t/local/65_ticket_sharing_2.t were missing from MANIFEST. + + - Updated inc/ directory with Module::Install 1.19. Updated + Makefile.PL author and resource information. Synced + SSLeay.pm under ext/ with the latest changes under + inc/. Reordered use imports so that META.yml gets correctly + regenerated. More Module::Install related changes will + follow. + +1.85 2018-03-14 + Preparations for transferring maintenace to a new maintainer + Fixed test failure in t/local/33_x509_create_cert.t for some version of OpenSSL. + Fixed free() error that causes "Free to wrong pool ..." merssage on Windows. + Reported and patched by Steffen Ullrich. + +1.84 2018-01-17 + Fixed an error in t/local/04_basic.t causing a test failure if + Test::Exception not installed. Reported by Joel Berger. + +1.83 2018-01-16 + Fixed a problem with exporting OPENSSL_NO_NEXTPROTONEG even though they are not availble on LibreSSL. + Patch patch-SSLeay_xs-NO_NPN from Alexander Bluhm. + Patch from Heikki Vatiainen adds support for SSL_set_default_passwd_cb* for + OpenSSL 1.1.0f and later. LibreSSL does not support these functions, at + least yet. + Patch from Heikki Vatiainen adds new functions related to SSL_CTX_new. + Patch from Heikki Vatiainen adds two new functions introduced in OpenSSL 1.1.0, a number + of constants and a couple of const qualifiers to SSLeay.xs. Tests and + documentation .pod were also updated. + Patch from Heikki Vatiainen adds one new OpenSSL 1.1.0 function and has a minor fix for + LibreSSL version detection: + * Added support for SSL_use_certificate_chain_file + function introduced in OpenSSL 1.1.0. + * Fixed LibreSSL version detection to correctly parse + LibreSSL minor version. + Patch from Steffen Ulrich to fix memory leaks in OCSP handling. Thanks. + Patch from Heikki Vatiainen adds new functions for certificate verification introduced in + OpenSSL 1.02, a number of constants, new test data files, new tests and + updates to .pod documentation. + The new functions provide access to the built-in wildcard check + functionality available in OpenSSL 1.0.2 and later. + The patch also adds new tests for the new functions and updates some of + the current tests for CTX_set_default_passwd_cb* functions. + Added X509_STORE_CTX_new and X509_verify_cert. + SSL_OCSP_response_verify now clears the error queue if OCSP_basic_verify fails but the + intermediate certificate succeeds. Patch from Stefan Ullrich. + + +1.82 2017-10-31 + Added support for building under Linuxbrew (a linuxbrew version of MacOS Homebrew) + Patch from Matthew Altus, that implements SSL_CTX_set_psk_client_callback() and SSL_set_psk_client_callback(). + Patch to build with LibreSSL has no support for NPN + Also skip the NPN test if the SSL library is LibreSSL. + Fixed a problem with a variable declaration in ssleay_session_secret_cb_invoke reported by Graham Ollis. + Significant patch set from Open System Consultants: + - Bugfix: tlsext_status_cb_invoke(...): free ocsp_response only when allocated. + - The same callback is used on a server side for OCSP stapling and in that + case ocsp_response is NULL and not used. + - New feature: Added a binding SSL_set_session_ticket_ext_cb(ssl,callback,data) + - A callback used by EAP-FAST/EAP-TEAT to parse and process TLS session ticket. + - Tests are in t/local/65_ticket_sharing_2.t + - New feature: Added a binding SSL_set_session_ticket_ext(ssl,ticket) + - Used by EAP-FAST/EAP-TEAP to define TLS session ticket value. + - Tests are in t/local/65_ticket_sharing_2.t + - Bugfix: tlsext_ticket_key_cb_invoke(...): allow SHA256 HMAC key to be 32 bytes + instead of 16 bytes (which OpenSSL will pad with zeros up to 32 bytes). + - New feature: Added following bindings: + - X509_get_ex_data(cert,idx) + - X509_get_ex_new_index(argl,argp,new_func,dup_funL,free_func) + - X509_get_app_data(cert) + - X509_set_ex_data(cert,idx,data) + - X509_set_app_data(cert,arg) + - X509_STORE_CTX_get_ex_new_index(argl,argp,new_func,dup_func,free_func) + - X509_STORE_CTX_get_app_data(x509_store_ctx) + - X509_STORE_CTX_set_app_data(x509_store_ctx,arg) + - New feature: Added an implementation for SSL_get_finished(ssl,buf,count=2*EVP_MAX_MD_SIZE) + - Tests are in t/local/43_misc_functions.t + - New feature: Added an implementation for SSL_get_peer_finished(ssl,buf,count=2*EVP_MAX_MD_SIZE) + - Tests are in t/local/43_misc_functions.t + - Bugfix: SSL_get_keyblock_size(s): Calculate key block size correctly also with AEAD ciphers + which don’t use digest functions. + - New feature: Added a binding SSL_set_tlsext_status_ocsp_resp(ssl,staple) + - Used by a server side to include OCSP staple in ServerHello. + - Bugfix: SSL_OCSP_response_verify(ssl,rsp,svreq,flags): check that chain and last are not NULL + before trying to use them. + - Bugfix: inc/Module/Install/PRIVATE/Net/SSLeay.pm: Don’t quote include and lib paths. + +1.81 2017-03-28 + Patch from Alexander Bluhm to enable RSA_get_key_parameters with + LibreSSL. Again. + Fixed memory leak in X509_get_subjectAltNames. Reported and patched by Jim Westfall. + Added . to lib path in Makefile.PL and t/local/32_x509_get_cert_info.t + to accommodate people who are using a perl with -Ddefault_inc_excludes_dot + or perl 25 or later. + Fixed build failure if engine support not present. Patch from Paul Green. + Improvements to get_my_thread_id to work around possibility of ERRSV not being defined eg on OpenWRT. + Patch from ETJ permitting configure and build in places with a space in the name. + +1.80 2017-01-05 + Patch from Steffen Ulrich that fixed unexpected changes in the + control flow of the Perl program which seemed to be triggered by the + ticket key callback. Thanks Steffen. + +1.79 2017-01-03 + Patch to fix a few inline variable declarations that cause errors for + older compilers. From Andy Grundman. Thanks. + Patch: Generated C code is not compatible with MSVC, AIX cc, + probably others. Added some PREINIT blocks and replaced 2 cases of INIT with + PREINIT. From Andy Grundman. Thanks. + Patch to fix: Fails to compile if the OpenSSL library it's built + against has compression support compiled out. From Stephan + Wall. Thanks. + Added RSA_get_key_parameters() to return a list of pointers to RSA key + internals. + Patch to fix some documentation typos courtesy gregor herrmann. + RSA_get_key_parameters() is now only available prior OpenSSL 1.1. + Testing with openssl-1.1.0b. + +1.78 2016-08-13 + Fixed broken OCSP code and tests. Broken since 1.75. Patched by + Steffen Ullrich. Thanks. + +1.77 2016-08-01 + Fixed incorrect size to memset in tlsext_ticket_key_cb_invoke. + +1.76 2016-07-31 + Replaced bzero with memset. Bzero not present on windows. + +1.75 2016-07-31 + Compatibility with OpenSSL 1.1, tested with openssl-1.1.0-pre5: + - Conditionally remove threading locking code, not needed in 1.1 + - Rewrite code that accesses inside X509_ATTRIBUTE struct. + - SSL_CTX_need_tmp_RSA, SSL_CTX_set_tmp_rsa, + SSL_CTX_set_tmp_rsa_callback, SSL_set_tmp_rsa_callback support + not available in 1.1. + - SSL_session_reused is now native + - SSL_get_keyblock_size modifed to use new API + - OCSP functions modified to use new API under 1.1 + - SSL_set_state removed with 1.1 + - SSL_get_state and SSL_state are now equivalent and available in all + versions + - SSL_CTX_v2_new removed + - SESSION_set_master_key removed with 1.1. Code that previously used + SESSION_set_master_key must now set $secret in the session_secret + callback set with SSL_set_session_secret_cb + - With 1.1, $secret in the session_secret + callback set with SSL_set_session_secret_cb can be changed to alter + the master key (required by EAP-FAST). + Added a function EC_KEY_generate_key similar to RSA_generate_key and a + function EVP_PKEY_assign_EC_KEY similar to EVP_PKEY_assign_RSA. Using + these functions it is easy to create and use EC keys in the same way as + RSA keys. Patch provided by Steffen Ullrich. Thanks Steffen. + Testing with LibreSSL 2.4.1, with compatibility patch from Steffen + Ullrich. Thanks Steffen. + Patch from Steffen Ulrich provides support for cross context (and cross process) + session sharing using the stateless TLS session tickets. It uses the + SSL_CTX_set_tlsext_ticket_key_cb function to manage the encryption and + decryption of the tickets but provides a more simplified + interface. Includes new function CTX_set_tlsext_ticket_getkey_cb. + To not conflict with the OpenSSL name in case the more complex interface + will be implemented ever the current simplified interface is called + slightly different: CTX_set_tlsext_ticket_*get*key_cb. + Added documentation about downloading latest version from SVN. + Added missing Module/install files to SVN. + +1.74 2016-04-12 + README.OSX was missing from the distribution + +1.73 2016-04-11 + Added X509_get_X509_PUBKEY. Patch supplied by GUILHEM. Thanks. + Added README.OSX with instructions on how to build for recent OS X. + Added info about using OPENSSL_PREFIX to README.Win32. + Added comments in POD about installation documentation. + Added '/usr/local/opt/openssl/bin/openssl' to Openssl search path for + latest version of OSX homebrew openssl. Patch from Shoichi Kaji. + +1.72 2015-09-22 + Fixed a problem where SvPVx_nolen was undefined in some versions of + perl. Reported by Karen Etheridge. Replaced with SvPV_nolen. + Fixed a cast warning on Darwin reported by Karen Etheridge. + +1.71 2015-09-18 + Patch from Ben Kaduk: Conditionalise support for MD4, MD5. + Added support for linking libraries in /usr/local/lib64 for some flavours + of Linux like RH Tikanga. + Fixes to X509_check_host, X509_check_ip, SSL_CTX_set_alpn_protos, and + SSL_set_alpn_protos so they will compile on MSVC and AIX cc. Thanks to + AGRUNDMA. + Fixed typos in documentation for X509_NAME_new and X509_NAME_hash + incorrect version 1.45 instead of 1.55 given. + Version number in META.yml is now quoted per request from Satoshi Yagi. + + +1.70 2015-06-26 + Patch from Alexander Bluhm: The new OpenSSL 1.0.2 X509_check_* functions are not available in + current LibreSSL. So disable them in SSLeay.xs. + Fixed a problem with building against OSX homebrew's openssl. Patch from + Shoichi Kaji. + Removed a test in t/local/33_x509_create_cert.t which fails due to + changes in 1.0.1n and later + +1.69 2015-06-04 + Testing with OpenSSL 1.0.2, 1.0.2a. OK. + Completed LibreSSL compatibility with the kind assistance of Alexander + Bluhm. + Improved compatibility with OpenSSL 1.0.2a as suggested by Petr Pisar. + Added the X509_check_* functions introduced in OpenSSL 1.0.2, contributed + by Carsten Gaebler. + Added support for X509_V_FLAG_TRUSTED_FIRST constant, patch from Gisle Aas. + Patch allows get_keyblock_size to work correctly with + OpenSSL 1.0.1 and later versions. Contributed by Heikki Vatiainen. + +1.68 2015-01-24 + Fixed a problem on OSX when macports openssl 1.x is installed: headers from + macport were found but older OSX openssl libraries were linked, resulting + in "Symbol not found: _EVP_MD_do_all_sorted". + Added notes about runtime error "no OPENSSL_Applink", when calling + Net::SSLeay::P_PKCS12_load_file. + + +1.67 2015-01-17 + Improvements to inc/Module/Install/PRIVATE/Net/SSLeay.pm to handle the + case whe there are muliple OPENSSLs installed. Patch from HBRAND + Fixed a documentation error in get_peer_cert_chain, reported by tejas. + Fixed a problem with building on Windows that prevented correct OpenSSL + directory detection with version 1.0.1j as delivered with Shining Light OpenSSL. + Fixed a problem with building on Windows that prevented finding MT or MD + versions of SSL libraries. + Updated doc in README.Win32 to build with Microsoft Visual Studio 2010 Express. + Added Windows crypt32 library to Windows linking as some compilers/platforms seem to + require it and it is innocuous otherwise. For Steve Hay. + Fixed a failure in t/external/20_cert_chain.t where some platforms do not + have HTTPS in /etc/services. Reported and patched by Gisle Aas. + Recent 1.0.2 betas have dropped the SSLv3_method function. + This patch leaves out the function on newer versions, much the same as + the SSLv2 deprecation is handled. Patch from Tom Molesworth. + Fix the ALPN test, which was incorrectly failing on OpenSSL due to the + LibreSSL check (earlier versions bailed out before that line).Patch from + Tom Molesworth. + +1.66 2014-08-21 + Fixed compile problem with perl prior to 5.8.8, similar to + RT#76267. Reported by Graham Knop. + Fixed a problem with Socket::IPPROTO_TCP on early perls. + After discussions with the community and the original author Sampo + Kellomaki, the license conditions have been changed to "Perl Artisitic + License 2.0". + + +1.65 2014-07-14 + Added note to doc to make it clear that X509_get_subjectAltNames returns a + packed binary IP address for type 7 - GEN_IPADD. + Improvements to SSL_OCSP_response_verify to compile under non c99 + compilers. Requested by MERIJNB. + Port to Android, contributed by Brian Fraser. Includes Android specific + version of RSA_generate_key. + Added LibreSSL support, patch provided by Alexander Bluhm. Thanks! + Patch that fixes the support for SSL_set_info_callback and adds + SSL_CTX_set_info_callback and SSL_set_state. Support for these functions is + necessary to either detect renegotiation or to enforce + renegotiation. Contributed by Steffen Ullrich. Thanks! + Fixed a problem with SSL_set_state not available on some early OpenSSLs, + patched by Steffen Ullrich. Thanks! + Removed arbitrary size limits from calls to tcp_read_all in tcpcat() and + http_cat(). + Removed unnecessary Debian_SPANTS.txt from MANIFEST. Again. + +1.64 2014-06-11 + Fixes for test ocsp.t. Test now does not fail if HTTP::Tiny is not + installed. + Fixed repository in META.yml. + Fixed a problem with SSL_get_peer_cert_chain: if the SSL handshake + results in an anonymous authentication, like ADH-DES-CBC3-SHA, + get_peer_cert_chain will not return an empty list, but instead return the + SSL object. Reported and fixed by Steffen + Ullrich. Thanks. + Fixed a problem where patch + https://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=3009244da47b989c4cc59ba02cf81a4e9d8f8431 + caused a failed test in t/local/33_x509_create_cert.t. + +1.63 2014-05-19 + Fixed error in version number in META.yml + +1.62 2014-05-19 + Improvements to OCSP support: It turns out that some CA (like Verisign) + sign the OCSP response with the CA we have in the trust store and don't + attach this certifcate in the response. But OpenSSL by itself only + considers the certificates included in the response and + SSL_OCSP_response_verify added the certificates in the chain too. + Now, we also add the trusted CA from the store which + signed the lowest chain certificate, at least if we could not verify the + OCSP response without doing it. Patch from Steffen + Ullrich. Thanks. + Fixed some compiler warnings. + +1.61 2014-05-12 + Changes calloc to Newx and free to Safefree, otherwise there might be + problems because calloc is done from a different memory pool than free (depends + on the build options for perl, but seen on Windows). Patch from Steffen + Ullrich. Thanks. + + +1.60 2014-05-10 + Fixed a typo in an error message. Patch from gregor herrmann. Thanks. + Fixed a problem with building with openssl that does not support + OCSP. Also fixed some newly introduced warnings + if compiled with -Wall. Patch from Steffen Ullrich. Thanks. + fix build-failure on most Debian architectures: + SSLeay.xs: In function 'XS_Net__SSLeay_OCSP_response_results': + SSLeay.xs:5602:3: error: format not a string literal and no format + arguments. Patch from gregor herrmann. + + +1.59 2014-05-10 + Fixed local/30_error.t, so that tests do not fail if diagnostics are + enabled. + Fixed error messages about undefined strings used with length or + split. Reported and patched by Peter Heuchert. + Improvements to configuration of OPTIMIZE flags, to prevent overriding + of perls expected optimization flags. Caution: HPUX aCC optimize options are special. + SSL_peek() now returns openssl error code as second item when called in + array context, same as SSL_read. Patch from Andreas Mohr. + Fixed some warnings. + Added support for tlsv1.1 tlsv1.2 via $Net::SSLeay::ssl_version. Patch + from Andreas Mohr. + Improve examples in 'Using other perl modules based on + Net::SSLeay'. Patched by Andreas Mohr. + Added support for OCSP. Patched by Steffen Ullrich. Thanks! + Added missing t/external/ocsp.t + +1.58 2014-01-15 + Always use size_t for strlen() return value, requested by Alexander Bluhm. + t/external/20_cert_chain.t was missing from dist. + Version number in META.yml was incorrect + Improvements to test t/external/20_cert_chain.t to provoke following bug: + Fixed crash due to SSL_get_peer_cert_chain incorrectly free'ing the chain + after use. + Fixed a problem when compiling against openssl where OPENSSL_NO_EC is set. + +1.57 2014-01-09 + Fixed remaining problems with test suite: pod coverage and kwalitee tests + are only enabled with RELEASE_TESTING=1 + +1.56 2014-01-08 + Fixed a typo in documentation of BEAST Attack, patched by gregor + herrmann. + Added LICENSE file copied form OpenSSL distribution to prevent complaints + from various versions of kwalitee. + Adjusted license: in META.yml to be 'openssl' + Adds support for the basic operations necessary to support ECDH for PFS, + e.g. EC_KEY_new_by_curve_name, EC_KEY_free and SSL_CTX_set_tmp_ecdh. + Improvements to t/handle/external/50_external.t to handle the case when a + test connection was not possible. Patched by Alexandr Ciornii. + Added support for ALPN TLS extension. Patch from Lubomir Rintel. Tested + with openssl-1.0.2-stable-SNAP-20131205. + Fix an use-after-free error. Patch from Lubomir Rintel. + Fixed a problem with Invalid comparison on OBJ_cmp result in + t/local/36_verify.t. Contributed by paul. + Added support for get_peer_cert_chain(). Patch by Markus Benning. + Fixed a bug that could cause stack faults: mixed up PUTBACK with SPAGAIN in ssleay_RSA_generate_key_cb_invoke() + a final PUTBACK is needed here. A second issue is also fixed: + cb->data defaults to &PL_sv_undef but throught the code you do not check + against &PL_sv_undef, just NULL. + To avoid passing the 3rd optional arg at all, do not create it. This fixes all the + cb->data checks and wrong refcounts on &PL_sv_undef. Patched by Reini Urban. + Deleted support for SSL_get_tlsa_record_byname: it is not included in + OpenSSL git master. + +1.55 2013-06-08 + Added support for TLSV1_1 and TLSV1_2 methods with SSL_CTX_tlsv1_1_new(), + SSL_CTX_tlsv1_2_new(), TLSv1_1_method() and TLSv1_2_method(), where + available in the underlying openssl. + Added CRL support functions X509_CRL_get_ext(), X509_CRL_get_ext_by_NID(), + X509_CRL_get_ext_count(). Patch from Franck Youssef. + Fixed a problem which could cause content with a value of '0' to not be + correctly encoded by do_httpx3 and friends. Reported by Victor Efimov via + RT. + Added support for SSL_get_tlsa_record_byname() required for DANE support in + openssl-1.0.2 and later. SSL_get_tlsa_record_byname() was added to + OpenSSL with the financial assistance of .SE. + Testing with openssl-1.0.2-stable-SNAP-20130521. + Added X509_NAME_new and X509_NAME_hash, patched by Franck Youssef. + Fixed a number of typos in pod file thanks to dsteinbrunner. + +1.54 2013-03-23 + t/data/testcert_cdp.crt.pem_dump and t/data/testcert_cdp.crt.pem were + missing from MANIFEST. + Added MANIFEST to svn + Improvement to test 07_sslecho.t so that if set_cert_and_key fails we + can tell why. + +1.53 2013-03-22 + Added support for SSL_export_keying_material where present (ie in OpenSSL + 1.0.1 and later). + Changed t/handle/external/50_external.t to use www.airspayce.com instead of + perldition.org, who no longer have an https server. + Patch to fix a crash: P_X509_get_crl_distribution_points on an + X509 certificate with values in the CDP extension which do not have an + ia5 string will cause a segmentation fault when accessed. Patch from + Robert Duncan. + Change in t/local/32_x509_get_cert_info.t to not use + Net::SSLeay::ASN1_INTEGER_get, since it works differntly on 32 and 64 bit platforms. + Updated author and distribution location details to airspayce.com + + +1.52 2013-01-09 + Rebuild package with gnu format tar, to prevent problems with unpacking + on other systems such as old Solaris, + +1.51 2012-12-14 + Fixed a problem where SSL_set_SSL_CTX is not available with + OpenSSL < 0.9.8f. Reported by Paul. + +1.50 2012-12-13 + Fixed a problem where t/handle/external/50_external.t would crash if any + of the test sites were not contactable. + Now builds on VMS. Patch kindly supplied by Craig A. Berry. + Fixed a few compiler warnings in SSLeay.xs. Most of them + are just signed/unsigned pointer mismatches but there is one that actually + fixes returning what would be an arbitrary value off the stack from + get_my_thread_id if it happened to be called in a non-threaded build. + Patch kindly supplied by Craig A. Berry. + Added README.VMS, contributed by Craig A. Berry. + Added SSL_set_tlsext_host_name, SSL_get_servername, + SSL_get_servername_type, SSL_CTX_set_tlsext_servername_callback for + server side Server Name Indication (SNI) support. Patched by kmx. + Further mods for VMS building supplied by Craig A. Berry. + Fixed a problem with C++ comments preventing builds on AIX and + HPUX. Patched by Gisle Aas. + perdition.org not available for tests, changed to www.airspayce.com + Added SSL_FIPS_mode_set + Improvements to test suite so it succeeds with and without FIPS mode + enabled. Patch supplied by Petr Pisar. + Added documentation, warning not to pass UTF-8 data in the content + argument to post_https. Reported by Jason Terry. + +1.49 2012-09-25 + Fixed problem where on some platforms test t/local/07_tcpecho.t would + bail out if it could not bind port 1212. Now now tries a number of ports to bind to until + successful. + Improvements to unsigned casting contributed by Reini Urban. + Improvements to Net::SSLeay::read to make it easier to use with non-blocking IO: + contributed by James Marshall: It modifies + Net::SSLeay::read() to return the result from SSL_read() as the second + return value, if Net::SSLeay::read() is called in list context. Its + behavior should be unchanged if called in scalar or void context. This + result code seems to be required for full support of non-blocking I/O, + since users need to handle SSL_ERR_WANT_READ, SSL_ERROR_WANT_WRITE, etc. + Fixed a problem where t/local/kwalitee.t fails with + Module::CPANTS::Analyse 0.86. Patch from Paul. + Fixed a number of typos patched by Giles. + Fixed a compiler warning from Compiling with gcc-4.4 and -Wall, patched by Giles. + Fixed problems with get_https4: documentation was wrong, $header_ref was + not correctly set and $server_cert was not returned. + Fixed a problem that could cause a Perl exception about no blength + method on undef. Reported by "Stephen J. Smith via RT". https://rt.cpan.org/Ticket/Display.html?id=79309 + Added documentation about how to mitigatxe various SSL/TLS + vulnerabilities. + Fixed problem reported by Mike Doherty: SSL_MODE_* are defined in ssl.h, + and should be available as constants, but I do not see them listed in constants.h + +1.48 2012-04-25 + Removed unneeded Debian_CPANTS.txt from MANIFEST. + Fixed incorrect documentation about the best way to call CTX_set_options. + Fixed problem that caused Undefined subroutine utf8::encode @ + t/local/33_x509_create_cert.t (on perl 5.6.2). Thanks to kmx. + In examples and pod documentations, changed #!/usr/local/bin/perl to #!/usr/bin/perl. + t/local/06_tcpecho.t now tries a number of ports to bind to until + successful. + +1.47 2012-04-04 + Fixed overlong lines in pod, patch from Salvatore Bonaccorso, Debian Perl + Group + Fixed spelling errors in pod, patch from Salvatore Bonaccorso, Debian Perl + Group + Fixed extra "garbage" files in 1.46 tarball. Patch from kmx. + Fixed incorrect fail reports on some 64 bit platforms. Patch from paul. + Fix to avoid FAIL reports from cpantesters with missing openssl + Use my_snprintf from ppport.h to prevent link failures with perl 5.8 and + earlier when compiled with MSVC. + +1.46 2012-04-03 + Fixed a problem reported by Atoomic: + When bootstrapping Net::SSleay ( with DynaLoader ) if you override the SIG{DIE} signal, using + Net::SSLeay will result in an error. + Recreated META.yml, added META.yml to dist + Fixed typo: the word "corresponding" was mis-spelled as "coresponding" + throughout the POD. Patched by kmx. + Updated META.yml to include repository and bugtracker + Constants cleanup - removing non existing constants (perhaps from pre-0.9.6 era) - kmx + Automatic constants.c generation via helper_script/regen_openssl_constants.pl - kmx + Future changes in constants now under better control via + t/local/21_constants.t - kmx + Added missing new files + Reordering @EXPORT_OK (constants first, functions next) - kmx + Adding missing 51 constants to @EXPORT_OK + test to keep it in sync - kmx + Instructions "howto add new constant" added to helper_script/regen_openssl_constants.pl - kmx + NEWLY INTRODUCED CONSTANTS: + - Net::SSLeay::ASN1_STRFLGS_ESC_CTRL + - Net::SSLeay::ASN1_STRFLGS_ESC_MSB + - Net::SSLeay::ASN1_STRFLGS_ESC_QUOTE + - Net::SSLeay::ASN1_STRFLGS_RFC2253 + - Net::SSLeay::ERROR_WANT_ACCEPT + - Net::SSLeay::EVP_PKS_DSA + - Net::SSLeay::EVP_PKS_EC + - Net::SSLeay::EVP_PKS_RSA + - Net::SSLeay::EVP_PKT_ENC + - Net::SSLeay::EVP_PKT_EXCH + - Net::SSLeay::EVP_PKT_EXP + - Net::SSLeay::EVP_PKT_SIGN + - Net::SSLeay::EVP_PK_DH + - Net::SSLeay::EVP_PK_DSA + - Net::SSLeay::EVP_PK_EC + - Net::SSLeay::EVP_PK_RSA + - Net::SSLeay::MBSTRING_ASC + - Net::SSLeay::MBSTRING_BMP + - Net::SSLeay::MBSTRING_FLAG + - Net::SSLeay::MBSTRING_UNIV + - Net::SSLeay::MBSTRING_UTF8 + - Net::SSLeay::OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + - Net::SSLeay::OP_CISCO_ANYCONNECT + - Net::SSLeay::OP_CRYPTOPRO_TLSEXT_BUG + - Net::SSLeay::OP_LEGACY_SERVER_CONNECT + - Net::SSLeay::OP_NO_TLSv1_1 + - Net::SSLeay::OP_NO_TLSv1_2 + - Net::SSLeay::OP_SINGLE_ECDH_USE + - Net::SSLeay::OP_TLS_BLOCK_PADDING_BUG + - Net::SSLeay::X509_V_FLAG_CHECK_SS_SIGNATURE + - Net::SSLeay::X509_V_FLAG_EXTENDED_CRL_SUPPORT + - Net::SSLeay::X509_V_FLAG_POLICY_MASK + - Net::SSLeay::X509_V_FLAG_USE_DELTAS + - Net::SSLeay::X509_V_OK + - Net::SSLeay::XN_FLAG_COMPAT + - Net::SSLeay::XN_FLAG_DN_REV + - Net::SSLeay::XN_FLAG_DUMP_UNKNOWN_FIELDS + - Net::SSLeay::XN_FLAG_FN_ALIGN + - Net::SSLeay::XN_FLAG_FN_LN + - Net::SSLeay::XN_FLAG_FN_MASK + - Net::SSLeay::XN_FLAG_FN_NONE + - Net::SSLeay::XN_FLAG_FN_OID + - Net::SSLeay::XN_FLAG_FN_SN + - Net::SSLeay::XN_FLAG_MULTILINE + - Net::SSLeay::XN_FLAG_ONELINE + - Net::SSLeay::XN_FLAG_RFC2253 + - Net::SSLeay::XN_FLAG_SEP_COMMA_PLUS + - Net::SSLeay::XN_FLAG_SEP_CPLUS_SPC + - Net::SSLeay::XN_FLAG_SEP_MASK + - Net::SSLeay::XN_FLAG_SEP_MULTILINE + - Net::SSLeay::XN_FLAG_SEP_SPLUS_SPC + - Net::SSLeay::XN_FLAG_SPC_EQ + A number of tests were present in svn, but missing from MANIFEST, and + were therefore not included in the dist. Added. + NEWLY INTRODUCED FUNCTIONS: + - Net::SSLeay::ASN1_INTEGER_free + - Net::SSLeay::ASN1_INTEGER_get + - Net::SSLeay::ASN1_INTEGER_new + - Net::SSLeay::ASN1_INTEGER_set + - Net::SSLeay::EVP_PKEY_assign_RSA + - Net::SSLeay::EVP_PKEY_bits + - Net::SSLeay::EVP_PKEY_free + - Net::SSLeay::EVP_PKEY_new + - Net::SSLeay::EVP_PKEY_size + - Net::SSLeay::EVP_get_cipherbyname + - Net::SSLeay::OPENSSL_add_all_algorithms_conf + - Net::SSLeay::OPENSSL_add_all_algorithms_noconf + - Net::SSLeay::OpenSSL_add_all_algorithms + - Net::SSLeay::PEM_get_string_PrivateKey + - Net::SSLeay::PEM_get_string_X509_CRL + - Net::SSLeay::PEM_get_string_X509_REQ + - Net::SSLeay::PEM_read_bio_PrivateKey + - Net::SSLeay::PEM_read_bio_X509 + - Net::SSLeay::PEM_read_bio_X509_REQ + - Net::SSLeay::P_ASN1_INTEGER_get_dec + - Net::SSLeay::P_ASN1_INTEGER_get_hex + - Net::SSLeay::P_ASN1_INTEGER_set_dec + - Net::SSLeay::P_ASN1_INTEGER_set_hex + - Net::SSLeay::P_ASN1_STRING_get + - Net::SSLeay::P_X509_CRL_add_revoked_serial_hex + - Net::SSLeay::P_X509_CRL_get_serial + - Net::SSLeay::P_X509_CRL_set_serial + - Net::SSLeay::P_X509_REQ_add_extensions + - Net::SSLeay::P_X509_REQ_get_attr + - Net::SSLeay::P_X509_add_extensions + - Net::SSLeay::P_X509_copy_extensions + - Net::SSLeay::P_X509_get_crl_distribution_points + - Net::SSLeay::P_X509_get_ext_key_usage + - Net::SSLeay::P_X509_get_key_usage + - Net::SSLeay::P_X509_get_netscape_cert_type + - Net::SSLeay::P_X509_get_pubkey_alg + - Net::SSLeay::P_X509_get_signature_alg + - Net::SSLeay::P_PKCS12_load_file + - Net::SSLeay::X509V3_EXT_print + - Net::SSLeay::X509_CRL_digest + - Net::SSLeay::X509_CRL_free + - Net::SSLeay::X509_CRL_get_issuer + - Net::SSLeay::X509_CRL_get_lastUpdate + - Net::SSLeay::X509_CRL_get_nextUpdate + - Net::SSLeay::X509_CRL_get_version + - Net::SSLeay::X509_CRL_new + - Net::SSLeay::X509_CRL_set_issuer_name + - Net::SSLeay::X509_CRL_set_lastUpdate + - Net::SSLeay::X509_CRL_set_nextUpdate + - Net::SSLeay::X509_CRL_set_version + - Net::SSLeay::X509_CRL_sign + - Net::SSLeay::X509_CRL_sort + - Net::SSLeay::X509_CRL_verify + - Net::SSLeay::X509_EXTENSION_get_critical + - Net::SSLeay::X509_EXTENSION_get_data + - Net::SSLeay::X509_EXTENSION_get_object + - Net::SSLeay::X509_NAME_ENTRY_get_data + - Net::SSLeay::X509_NAME_ENTRY_get_object + - Net::SSLeay::X509_NAME_add_entry_by_NID + - Net::SSLeay::X509_NAME_add_entry_by_OBJ + - Net::SSLeay::X509_NAME_add_entry_by_txt + - Net::SSLeay::X509_NAME_cmp + - Net::SSLeay::X509_NAME_digest + - Net::SSLeay::X509_NAME_entry_count + - Net::SSLeay::X509_NAME_get_entry + - Net::SSLeay::X509_NAME_print_ex + - Net::SSLeay::X509_REQ_add1_attr_by_NID + - Net::SSLeay::X509_REQ_digest + - Net::SSLeay::X509_REQ_free + - Net::SSLeay::X509_REQ_get_attr_by_NID + - Net::SSLeay::X509_REQ_get_attr_by_OBJ + - Net::SSLeay::X509_REQ_get_attr_count + - Net::SSLeay::X509_REQ_get_pubkey + - Net::SSLeay::X509_REQ_get_subject_name + - Net::SSLeay::X509_REQ_get_version + - Net::SSLeay::X509_REQ_new + - Net::SSLeay::X509_REQ_set_pubkey + - Net::SSLeay::X509_REQ_set_subject_name + - Net::SSLeay::X509_REQ_set_version + - Net::SSLeay::X509_REQ_sign + - Net::SSLeay::X509_REQ_verify + - Net::SSLeay::X509_certificate_type + - Net::SSLeay::X509_digest + - Net::SSLeay::X509_get_ext_count + - Net::SSLeay::X509_get_pubkey + - Net::SSLeay::X509_get_serialNumber + - Net::SSLeay::X509_get_version + - Net::SSLeay::X509_issuer_and_serial_hash + - Net::SSLeay::X509_issuer_name_hash + - Net::SSLeay::X509_new + - Net::SSLeay::X509_pubkey_digest + - Net::SSLeay::X509_set_issuer_name + - Net::SSLeay::X509_set_pubkey + - Net::SSLeay::X509_set_serialNumber + - Net::SSLeay::X509_set_subject_name + - Net::SSLeay::X509_set_version + - Net::SSLeay::X509_sign + - Net::SSLeay::X509_subject_name_hash + - Net::SSLeay::X509_verify + - Net::SSLeay::d2i_X509_CRL_bio + - Net::SSLeay::d2i_X509_REQ_bio + - Net::SSLeay::d2i_X509_bio + - Net::SSLeay::set_tlsext_host_name + - Net::SSLeay::CTX_set_next_protos_advertised_cb + - Net::SSLeay::CTX_set_next_proto_select_cb + - Net::SSLeay::P_next_proto_negotiated + - Net::SSLeay::P_next_proto_last_status + Fixed a problem with multiple Safefree of GLOBAL_openssl_mutex when run + under apache2+mod_perl on recent Debain distros. Removed END and + openssl_threads_cleanup() since they can be called during thread + destruction, and not necessarily at process exit time. + Added missing helper_script/regen_openssl_constants.pl to MANIFEST. Add + MANIFEST to svn. + Fixed reported errors about try to plan twice in 21_constants.t on some platforms. + Removed MANIFEST from svn, improve possibility to use Module::Install in Net-SSleay + distribution in usual way. new target for make manifest + Fix 2 issues with CTX_use_PKCS12_file + 1/ leaking memory - missing EVP_PKEY_free + X509_free + 2/ pkcs12 filesize limitation + Fixed problems with regenerating scripts in Makefile.PL + Added missing dependencies for SSLeay.o to Makefile.PL + Added missing test files to svn + Fixed calling convention for Net::SSLeay::get_shared_ciphers + test + doc update + Added coding guidelines to SSLeay.xs + Fix for serial number issue. + Major patch to refactor callback code to make it more extensible and + remove duplicate code. Thanks to kmx. + Fixed a problem in t/local/07_sslecho.t when running on + openssl-0.9.6 + Fixed pod parsing errors reported by Olivier Mengué + Better prevention of leaking SVs in the new callback stuff + Debug messages in SSLeay.xs can be enabled by: perl Makefile.PL DEFINE=-DSHOW_XS_DEBUG + Fixing X509_NAME_oneline (calling OPENSSL_free at the right place) + Fixed a problem with crashing when run under apache2+modssl+modperl on + Debian Wheezy. Now detects if it is running under ModPerl and uses ModSSLs + thread locking instead. + Added more debg printing. Enable with + perl Makefile.PL DEFINE=-DSHOW_XS_DEBUG + Added NPN support, thanks to kmx + Added t/local/40_npn_support.t tests for new NPN support + Fixed some compiler warnings. Courtesy kmx. + Fixed a problem with Win32 detection. Courtesy kmx. + +1.45 2012-02-25 + Added mising doc for SESSION_cmp. Patch by paul. + +1.44 2012-02-25 + Added missing t/data/binary-test.file to MANIFEST + +1.43 2012-02-24 + Fixed some typos. Patched by Neil Bowers. + SSLeay.pm convenience functions now call Net::SSLeay::initialize that + initializes the SSL library at most once. + Patch from kmx to protect SSLeay_add_ssl_algorithms from multiple loads + and reentrancy in multi-threaded perls. + Patch from kmx to add reentrancy protection for callbacks in + multithreading. + Updated ppport.h, fixed some complaints from ppport.h + Fixed a problem with CTX_use_PKCS12_file on Windows, since the file was + not opened in binary mode. Reported by kmx. + Added resources line for SVN repository to Makefile. Suggested by kmx. + Fixed complaints unders some windows compilers about cast from pointer to integer of + different size. Suggested by kmx. + Added thread safety and dynamic locking. This should complete thread + safety work, making Net::SSLeay completely thread-safe. Patches by kind + assistance of kmx. + Improvements to openssl backwards compatibility. Now build with versions + back to 0.9.6. With extreme thanks to kmx. + Improvements to documentation, thanks to kmx. + SUMMARY OF NEWLY INTRODUCED FUNCTIONS: + - Net::SSLeay::initialize + - Net::SSLeay::SSLeay + - Net::SSLeay::SSLeay_version + - Net::SSLeay::CIPHER_get_name + - Net::SSLeay::ASN1_TIME_new + - Net::SSLeay::ASN1_TIME_free + - Net::SSLeay::ASN1_TIME_set + - Net::SSLeay::P_ASN1_TIME_get_isotime + - Net::SSLeay::P_ASN1_TIME_set_isotime + - Net::SSLeay::P_ASN1_TIME_put2string + - Net::SSLeay::OpenSSL_add_all_digests + - Net::SSLeay::P_EVP_MD_list_all + - Net::SSLeay::EVP_get_digestbyname + - Net::SSLeay::EVP_MD_type + - Net::SSLeay::EVP_MD_size + - Net::SSLeay::EVP_MD_CTX_md + - Net::SSLeay::EVP_MD_CTX_create + - Net::SSLeay::EVP_MD_CTX_destroy + - Net::SSLeay::EVP_DigestInit + - Net::SSLeay::EVP_DigestInit_ex + - Net::SSLeay::EVP_DigestUpdate + - Net::SSLeay::EVP_DigestFinal + - Net::SSLeay::EVP_DigestFinal_ex + - Net::SSLeay::EVP_Digest + - Net::SSLeay::SHA1 + - Net::SSLeay::SHA256 + - Net::SSLeay::SHA512 + - Net::SSLeay::EVP_sha1 + - Net::SSLeay::EVP_sha512 + Fixed a problem with set_proxy where the password was not properly + set. The code to do this went missing at some stage. Reported by Ulrich + Weber via RT. + Further improvements to testing time functions. + Added t/local/37_asn1_time.t + Added various digest functions, documentation and tests + Removed debug from P_ASN1_TIME_get_isotime. Courtesy kmx. + Remove unnecessary warnings about Random number generator not + seeded. Courtesy kmx. + Fixed an error in 04_basic.t triggered if Test::Exception not present. + Added documentation for many CTX_ functions. Courtesy kmx. + Fixed mionor typos in SSLeay.xs. Courtesy kmx. + Moved documentation to new lib/Net/SSLeay.pod. Courtesy kmx. + Additions to documentation in pod. Courtesy kmx. + Fixed some incorrect return types from SSL_set_options + SSL_CTX_set_options. Courtesy kmx. + Further documentation in pod. Courtesy kmx. + Small fixes to XS code + one new trivial function SSL_CIPHER_get_name + And one more thing - 02_pod_coverage.t is turned ON passing all tests - + never ever allow a new function without at least a short doc. Courtesy + kmx. + Removed 2 unnecessary 'local $[;' from SSLeay.pm + +1.42 2011-10-03 + Fixed incorrect documentation of how to enable CRL checking. Patched + by Steffen_Ullrich. + Fixed incorrect letter in Sebastien in Credits. Patch by Neil Bowers. + Reversed order of the Changes file to be reverse chronological. Patch by + Neil Bowers. + Fixed a a compile error when building on Windows with MSVC6. reported and + patched by "Andrew J. Savige via RT". + +1.41 2011-09-25 + Fixed incorrect const signatures for 1.0 that were causing warnings. + Patches provided by "Douglas + Christopher Wilson via RT". Now have clean compile with 0.9.8a through 1.0.0. +1.40 2011-09-23 + Fixed incorrect argument type in call to SSL_set1_param + Fixed a number of issues with pointer sizes, patched by "Douglas + Christopher Wilson via RT". Removed redundant pointer cast tests from t/ + Added Perl version requirements to SSLeay.pm +1.39 2011-09-21 + Downgraded Module::Install to 0.93 since 1.01 was causing problems in + the Makefile. Reported by Albert Chin. +1.38 2011-09-16 + - Fixed a problem with various symbols that only became + available in OpenSSL 0.9.8 such as X509_VERIFY_PARAM and + X509_POLICY_NODE, causing build failures with older versions of + OpenSSL. Patched by paul. +1.37 2011-09-16 + - Added X509_get_fingerprint, contributed by Thierry Walrant (with + minor changes die to the fact that stricmp is not avialable. Cert + types must be lowercase. Also added test to 07_sslecho.t + - Added suport for SSL_CTX_set1_param, SSL_set1_param, + selected X509_VERIFY_PARAM_* OBJ_* functions. Added new test + t/local/36_verify.t + - Fixed the prototype for randomize(), it missed one arg, and errors + are reported with perl 5.10.1 on Windows + - Fixed an uninitialized value warning in $Net::SSLeay::proxyauth, + reported by Andrey Rikov. + - Update so net-ssleay will compile if SSLV2 is not present. Patch + from Chris Butler. + - Fixed a problem where sslcat (and possibly other functions) expect RSA keys and will not + load DSA keys for client certificates. Reported and patched by "Jesse + DeFer via RT" + - Removed SSL_CTX_v2_new and SSLv2_method() for OpenSSL 1.0 and later. + - Added CTX_use_PKCS12_file contributed by "Andrew A. Budkin". +1.36 30.01.2010 + - Fix problems with building on GNU/kFreeBSD, to do with use of pack + instread of sockaddr_in. Patched by Debian Perl Group. (Closes RT#40144) + - Fixed a compile problem in t/local/ptr_cast_test.c for some gcc + versions. Reported by "Ryan McGuigan via RT". (Closes RT#52525) + - Improved OpenSSL detection on Win32/strawberry perl. Patch provided + by kmx. (Closes RT#49287) + - Fix test failures on some 64-bit platforms. (Closes RT#53585) + - Make X509_NAME_get_text_by_NID return its result without a trailing NUL. + Patched by Steffen Ullrich. (Closes RT#35754) + - SSL_set_session_secret_cb required for EAP-FAST is now enabled for both + SSL_F_SSL_SET_HELLO_EXTENSION and + SSL_F_SSL_SET_SESSION_TICKET_EXT. The name of this #define + changed after 0.9.8i. SSL_set_hello_extension is not available after + 0.9.8i. + - Added SSL_CTX_get_client_CA_list sk_X509_NAME_free sk_X509_NAME_num + sk_X509_NAME_value SSL_get_client_CA_list, from patch provided by + Joerg Schneider + - Added EVP_add_digest and EVP_sha256 (if available) + - Improve documentation on callback functions. + - Stop looping forever when writing to broken connections. Patched by + Martin Mares. (Closes RT#44170) + - Patches from "Martijn van Beers via RT" to add SSL_SENT_SHUTDOWN + and SSL_RECEIVED_SHUTDOWN, remove broken URLs, + and to fix some documentation issues. + - Various changes to build with OpenSSL 1.0 beta1: + SSL_SESSION_cmp has been removed + return type of SSL_CTX_sessions changed in an ugly way + - Fixed a build problem reported by SISYPHUS: + On Windows Vista64, ActivePerl 5.10.0 (build 1004, x64), running 'nmake + test', the process hangs forever when it comes to building the test + executable (as the executable fails to build). + - Applied patch from ecmenifee in to improve handling of errors in + ssl_write_all. (Closes RT#48132) + - Patch to permit compile and testing on OS/2 submitted by Ilya + Zakharevich. + - Fixed compile problems with openssl-1.0.0-beta3 due to MD2 now being + optional. Reported by paul [...] city-fan.org. + - Fixed compile problems with openssl-0.9.7 and earlier with undefined + symbol EVP_sha256. Reported by paul [...] city-fan.org. + - Fixed a typo reported by Dan Dascalescu. + - added RIPEMD160 digest function. Patch provided by dkg. + +1.35 25.07.2008 + - Fix test plan for autoload.t if Test::Exception isn't available. + - Skip rsa_generate_key.t if Test::Exception isn't available. + +1.34 24.07.2008 + - Fixed problem with X509_get_subjectAltNames, where some types of Alt + Name (eg DIRNAMEs) were not properly handled, resulting in seg faults. + Reported by Achim Grolms. + - Added support for ENGINE_load_builtin_engines and + ENGINE_register_all_complete in order to enable built-in OpenSSL + crypto engines for hardware acceleration etc. + - Added support for ENGINE_by_id and ENGINE_set_default, required + to enable Sun crypto acceleration + +1.33_01 14.02.2008 + - Fixed a compile problem with inc_paths /usr/kerberos/include + in inc/Module/Install/PRIVATE/Net/SSLeay.pm. Reported by "J. Nick + Koston via RT" + - Added optional support for SSL_set_hello_extension, + SSL_set_session_secret_cb to support various extension patches from + a patch to openssl-0.9.9-dev contributed by Jouni Malinen. + See wpa_supplicant/patches/openssl-0.9.9-session-ticket.patch in the + latest (git) version 0.6 and later of wpa_suplicant at + http://hostap.epitest.fi/. These additions are ifdefed to + SSL_F_SSL_SET_HELLO_EXTENSION which is added by the patch + Tested with openssl-SNAP-20070816. + - Added SSL_SESSION_set_master_key and SSL_get_keyblock_size. + - Added all SSL_OP_* options flags present in 0.9.9 + - Fixed a bug in SSL_set_tmp_dh + - Doc improvements in README.Win32 + - Fixed a problem with proxy connections: open_proxy_tcp_connection + was stopping after the first \n from the proxy, + but instead should have looked for + $CRLF . $CRLF to find the beginning of the SSL content + - Fixed missing / on /usr/kerberos/include, reported by several people + - removed bacus.pt from host list in t/handle/external/10_destroy.t, + since it seems no longer to respond. Reported by tco2. + - changed t/handle/external/10_destroy.t so this list of URIs to be + tested can be configured with environment variable SSLEAY_URIS, a + colon separated list of host names. Suggested by tco2. + - changed t/handle/external/50_external.t and t/external/08_external.t + so this list of sites to be + tested can be configured with environment variable SSLEAY_SITES, a + colon separated list of host names. Suggested by tco2. + - Fixed doucumentation in README of how to use OPENSSL_PREFIX + environment variable to control the location of openssl. Reported by + "Quanah Gibson-Mount via RT". + - Don't use Module::Installs auto_install. + - Bind NID_ and GEN_ constants. + - Default to not running external tests. + +1.32 03.08.2007 + - Don't let the tests die when something unexpected happens. Just BAIL_OUT. + - Some Win32 improvements. + +1.31_02 14.07.2007 + - Fix linking problems on Windows. Tested with VC++ 6.0, Shining Light + 0.9.7L on Windows Server 2003 with ActivePerl 5.8.8.820. Also tested + with OpenSSL 0.9.8e compiled from source. + - Unable to get working systems when compiling with MS Visual Studio + Express 2005. Contributions requested. This may be relevant: + http://www.itwriting.com/blog/?postid=261&replyto=2542 + - Fixed a number of minor compile warnings on Windows + - Updated README.Win32 to define building procedures on Windows + - Fixed incorrect test failure reports in 08_external. + - Add parens to function calls in Makefile.PL to prevent + warnings with some perls. + - Tested on Sparc Solaris 8, Sparc Solaris 10, OpenSuSE 10.2 x64, + OpenSuSE 10.0 x86, FreeBSD 6.0 x86, Ubuntu 6.10, Fedora Core 6 x86 + - Changed type of SSL_set_info_callback args to stop compiler warnings + on Windows + - Removed auto_include from Makefile.PL + - Removed build_requires('Test::NoWarnings') from Makefile.PL + - Testing with Strawberry Perl on Windows XP SP2, added doc to + README.Win32 + - Testing with Perl CamelPack 5.8.7 on Windows XP SP2,added doc to + README.Win32 + - Added optional support for SSL_set_hello_extension, + SSL_set_session_secret_cb to support various extension patches from + a patch to openssl-0.9.9-dev contributed by Jouni Malinen. + See wpa_supplicant/patches/openssl-0.9.9-session-ticket.patch in the + latest (git) version 0.6 and later of wpa_suplicant at + http://hostap.epitest.fi/. These additions are ifdefed to + SSL_F_SSL_SET_HELLO_EXTENSION which is added by the patch + Tested with openssl-SNAP-20070816. + - Added SSL_SESSION_set_master_key and SSL_get_keyblock_size. + - Added all SSL_OP_* options flags present in 0.9.9 + - Fixed a bug in SSL_set_tmp_dh + - Doc improvements in README.Win32 +1.31_01 02.07.2007 + - Only bind X509_STORE_set_trust #if OPENSSL_VERSION_NUMBER >= 0x0090800fL + - Removed %Filenum_Objects from Net::SSLeay::Handle so unused handles will be freed. + - Use ppport.h. + - improved openssl path guessing, forcing openssl path now + requires the -path flag (caution: incompatible flag change) + Path guessing works on windows too. + mikem, with patches from Stas Bekman + - Added /usr/sfw/bin/openssl to path guessing for Open Solaris, + suggested by Igor Boehme. + - Fixed a problem with X509_get_subjectAltNames not working when the + subjectAltNAmes are the first extension. Reported by Achim Grolms + +1.30 21.12.2005 + - Fixed the MD5 function for hashsums containing \0 + - Fixed some compile warnings with recent gcc. + - Fixed do_httpx3: + + Don't add additional Host: headers if it's already given + + Omit the :$port suffix for standard ports + + Thanks to ivan-cpan-rt@420.am + - Limit the chunk size when reading with tcp_read_all to 0x1000. + This fixes various rt tickets. + - Added patch to allow session caching + - Mike McCauley and Florian Ragwitz maintain this module now +1.25 18.8.2003 + - added tcpecho.pl and tcpcat.pl to MANIFEST + - fixed some further bugs with TCP read all, etc. + - fixed some const char pointer warnings +1.24 25.6.2003 + - write_partial() return value patch from + Kim Minh Kaplan + 3.8.2003 + - applied version check fix to Net::SSLeay::Handle.pm + from Jason Rhinelander + 17.8.2003 + - new features: http and raw tcp support + - fixed apparent STDIO vs. sysread bug in proxy connect +1.23 13.6.2003 + - some minor tweaks by many, mainly for RH build + - memory leak and cleanup patches from Marian Jancar +1.22 8.1.2003 + - proxy auth fix from Bill.Muller@@ubsw_..com + 18.2.2003 + - RAND patch from Toni Andjelkovic +1.21 6.9.2002 + - Patch by Mike McCauley mikem@open.com_.au + 19.9.2002 + - applied patch from Tim Engler + 30.10.2002, + - perl-5.8/gcc-3.2 patch on Makefile.PL from + Joern_Hoos@@notes.uni-paderborn._de, lucho@@galix._com, + bellis@@saberlogic._com, and simonclewer@@superquote._com +1.20 16.8.2002 + - Additional patch by Peter Behroozi --Sampo + - Patch by Mike McCauley mikem@open.com_.au +1.19 10.8.2002-16.8.2002 + - Added SSL_peek patch to ssl_read_until from + Peter Behroozi --Sampo + - Improved Windows instructions per Marcel Bucher +1.18 15.6.2002 + - applied minor patch by Mark Veltzer to Makefile.PL +1.17 8.6.2002 + - further fixes for Net::SSLeay::Handle from jbowlin@@_linklint.org + - improved README.Win32 and added RECIPE.Win32 from + Hermann Kelley +1.16 17.4.2002-22.5.2002 + - applied patch to fix CTX_set_default_passwd_cb() contributed + by Timo Kujala , --Sampo + - similar patch by Chris Ridd + - applied patch to add various API functions by mikem@open.com_.au + - 5.005_03 compat fix for Handle.pm from Jim Mintha +1.15 3.4.2002 + - added `use bytes' from Marcus Taylor + 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 +1.14 25.3.2002 + - added code to Makefile.PL to verify that the same C compiler + is used for both perl and openssl + - added code to Makefile.PL to support aCC on HPUX. Detective + work contributed by Marko Asplund. + - added peer certificate support to hilevel API, inspired + by mock@@_obscurity.org +1.13 13.2.2002 + - eliminated initializing random numbers using /etc/passwd per + comments by Matt Messier + - tested against openssl-0.9.6c +1.12 6.1.2002 + - cosmetic fix to socket options from + Kwindla Hultman Kramer +1.11 14.12.2001, + - Added proxy support to Net::SSLeay::Handle, too +1.10 7.12.2001, + - Added proxy support by Bruno De Wolf +1.09 20.8.2001, + - fixed Makefile.PL (computation of bin_path) and test.pl ($perl + use before defined) per Gordon Lack + 11.9.2001, + - Patch by Jeremy Mates to make Handle.pm + more acceptable for older perls + 25.9.2001, + - systematically implemented many of the newer functions of + openssl API (per popular request and for completeness) +1.08 25.4.2001, + - applied 64 bit fixes by Marko Asplund + 17.7.2001, + - applied error codes and SSL_*_method patch by Noel Burton-Krahn + via aspa + - warning cleanups by Jared Allison + - do last loop fixes from Jim Bowlin + - Fixed extra-newline-if-header-already-contained-newline problem + reported by Sean McMurray (first reported by + Yuao TANIGAWA but not fixed by me back + then for some reason, my bad) + - Added ability to set client certificate for https_cat and sslcat + as suggested by Avi Ben-Harush + - created do_https2 with more rational calling sequence + 18.7.2001, + - numerous windows oriented fixes from Eric A Selber + + - bumped OpenSSL version requirement to 0.9.6b and tested + - merged in Net::SSLeay::Handle by Jim Bowlin +1.07 18.4.2001, + - TLSv1 support by Stephen C. Koehler +1.06 7.4.2001, --Sampo + - fixed ssl_read_all bug where `0' input was mistaken for EOF. + - openssl-0.9.6a fixes (e.g. random number generator init) + - various minor fixes subnitted by fellow netters (sorry, I lost track + of your names so I do not name the contributors here) +1.05 31.1.1999, --Sampo + - fixed test cert creation (lack of symlinks, reported + by schinder@@_pobox.com) + - callbacks fixed and tested to work + - added Authentication examples + - added couple more X509_STORE_CTX family functions +1.04 31.1.1999, Sampo Kellomaki + - Backward incompatible changes in OpenSSL API mean that 1.04 will + drop support for SSLeay and all OpenSSL versions prior + to 0.9.2b release. Thanks guys! + - Detected errors in OpenSSL-0.9.2b/ssl/ssl.h - see patch in README + - Reordered arguments of several functions to track OpenSSL-0.9.2b + changes. This also changes the order of args in corresponding + perl functions. You have been warned! + - SSL_use_certificate_ASN1(s,d,len) // swapped d and len + - WARNING: Possibly fatal verify_callback parameter list issue + is still standing + - cleaned up many macros that used to access ctx->session directly, + OpenSSL-0.9.2b defines thes macros properly so I use them now. + - Added SSL_ctrl() and SSL_CTX_ctrl() + - Added SSL_get_options(), SSL_CTX_get_options(), + SSL_CTX_set_cipher_list() + - Removed SSL_add_session(), SSL_remove_session(), + and SSL_flush_sessions() per #if 0 in ssl.h, line 667 + - Updated paths in various utility programs + - Upgraded version number detection logic in Makefile.PL + - Added -rsaref flag to Makefile.PL. This allows linking against rsaref + 30.7.1999, final squeeze to get this out --Sampo + - upgrade to OpenSSL-0.9.3a + - upper case all header names so keys of the hash returned + from get_https are predictible + - fixed get_https and post_https so they don't do shutdown + anymore. This used to cause headaches when connection + renegotiation happened. + - applied ssl_read_CRLF patch by Clinton Wong + - ActivePerl diffs from anton@@_genua.de applied, + but not tested. +1.03 4.1.1999, Sampo Kellomaki + - Merged URI encoding patch to make_form + from Joe Rhett + - changed sslcat, ssl_read_all, ssl_write_all to return error messages + as second member of list. Functions continue to behave the old way + if scalar return value is used (they check this with wantarray). + Change was suggested by Joe Rhett. + - changed $trace levels so that 0 does not produce any output + - changed get_https and put_https to fake error 900 in $response + return field + - changed print_errs and some other internals to return textual + errors instead of error count + - changed SSLeay.xs comments from #if 0 to #define REM. This will + hopefully make it easier to compile with some vendor compilers + - Added version detection code for OpenSSL-0.9.1c and checked + build +1.02 8.7.1998, Sampo Kellomaki + - Added SSL_(CTX)?_set_options and associated constants + - Slight clean-ups +1.01 23.6.1998, Sampo Kellomaki + - made Makefile.PL check SSLeay version and to be more CPAN kosher + - changed build instructions to build outside perl source tree + - added random number initialization using /dev/urandom (if available) + - made ssl_write_all accept references, this is more memory efficient +1.00 19.6.1998, Sampo Kellomaki + - overhauled to SSLeay-0.9.0 + - renamed cat to sslcat + - added lots of convenience functions, like get_https + - added couple of X509 routines + - improved tests and documentation + - fixed callbacks (but found that old callbacks dont work) +0.04 19.7.1996 Fixed some 0.6.1 incompatibilities, namely removed + #include , fixed typo in SSL_get_cerificate, fixed + the return type of the same. --Sampo +0.03 Renamed everything Net::SSLeay +0.02 Trial with SSL.pm name +0.01 Thu Jun 27 03:56:00 1996 + - original version; created by h2xs 1.16 +#EOF diff --git a/Credits b/Credits new file mode 100644 index 0000000..7f9f4e7 --- /dev/null +++ b/Credits @@ -0,0 +1,8 @@ +anton@genua.de Win32 +Clinton Wong +Jim Bowlin for contributing Net::SSLeay::Handle +Eric A Selber for Windows fixes and testing +Marko Asplund for many suggestions and fixes +Sébastien Aperghis-Tramoni for many fixes and cleanups + +See Changes file for other contributions. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f29c7fb --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + The Artistic License 2.0 + + Copyright (c) 2000-2006, The Perl Foundation. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +Preamble + +This license establishes the terms under which a given free software +Package may be copied, modified, distributed, and/or redistributed. +The intent is that the Copyright Holder maintains some artistic +control over the development of that Package while still keeping the +Package available as open source and free software. + +You are always permitted to make arrangements wholly outside of this +license directly with the Copyright Holder of a given Package. If the +terms of this license do not permit the full use that you propose to +make of the Package, you should contact the Copyright Holder and seek +a different licensing arrangement. + +Definitions + + "Copyright Holder" means the individual(s) or organization(s) + named in the copyright notice for the entire Package. + + "Contributor" means any party that has contributed code or other + material to the Package, in accordance with the Copyright Holder's + procedures. + + "You" and "your" means any person who would like to copy, + distribute, or modify the Package. + + "Package" means the collection of files distributed by the + Copyright Holder, and derivatives of that collection and/or of + those files. A given Package may consist of either the Standard + Version, or a Modified Version. + + "Distribute" means providing a copy of the Package or making it + accessible to anyone else, or in the case of a company or + organization, to others outside of your company or organization. + + "Distributor Fee" means any fee that you charge for Distributing + this Package or providing support for this Package to another + party. It does not mean licensing fees. + + "Standard Version" refers to the Package if it has not been + modified, or has been modified only in ways explicitly requested + by the Copyright Holder. + + "Modified Version" means the Package, if it has been changed, and + such changes were not explicitly requested by the Copyright + Holder. + + "Original License" means this Artistic License as Distributed with + the Standard Version of the Package, in its current version or as + it may be modified by The Perl Foundation in the future. + + "Source" form means the source code, documentation source, and + configuration files for the Package. + + "Compiled" form means the compiled bytecode, object code, binary, + or any other form resulting from mechanical transformation or + translation of the Source form. + + +Permission for Use and Modification Without Distribution + +(1) You are permitted to use the Standard Version and create and use +Modified Versions for any purpose without restriction, provided that +you do not Distribute the Modified Version. + + +Permissions for Redistribution of the Standard Version + +(2) You may Distribute verbatim copies of the Source form of the +Standard Version of this Package in any medium without restriction, +either gratis or for a Distributor Fee, provided that you duplicate +all of the original copyright notices and associated disclaimers. At +your discretion, such verbatim copies may or may not include a +Compiled form of the Package. + +(3) You may apply any bug fixes, portability changes, and other +modifications made available from the Copyright Holder. The resulting +Package will still be considered the Standard Version, and as such +will be subject to the Original License. + + +Distribution of Modified Versions of the Package as Source + +(4) You may Distribute your Modified Version as Source (either gratis +or for a Distributor Fee, and with or without a Compiled form of the +Modified Version) provided that you clearly document how it differs +from the Standard Version, including, but not limited to, documenting +any non-standard features, executables, or modules, and provided that +you do at least ONE of the following: + + (a) make the Modified Version available to the Copyright Holder + of the Standard Version, under the Original License, so that the + Copyright Holder may include your modifications in the Standard + Version. + + (b) ensure that installation of your Modified Version does not + prevent the user installing or running the Standard Version. In + addition, the Modified Version must bear a name that is different + from the name of the Standard Version. + + (c) allow anyone who receives a copy of the Modified Version to + make the Source form of the Modified Version available to others + under + + (i) the Original License or + + (ii) a license that permits the licensee to freely copy, + modify and redistribute the Modified Version using the same + licensing terms that apply to the copy that the licensee + received, and requires that the Source form of the Modified + Version, and of any works derived from it, be made freely + available in that license fees are prohibited but Distributor + Fees are allowed. + + +Distribution of Compiled Forms of the Standard Version +or Modified Versions without the Source + +(5) You may Distribute Compiled forms of the Standard Version without +the Source, provided that you include complete instructions on how to +get the Source of the Standard Version. Such instructions must be +valid at the time of your distribution. If these instructions, at any +time while you are carrying out such distribution, become invalid, you +must provide new instructions on demand or cease further distribution. +If you provide valid instructions or cease distribution within thirty +days after you become aware that the instructions are invalid, then +you do not forfeit any of your rights under this license. + +(6) You may Distribute a Modified Version in Compiled form without +the Source, provided that you comply with Section 4 with respect to +the Source of the Modified Version. + + +Aggregating or Linking the Package + +(7) You may aggregate the Package (either the Standard Version or +Modified Version) with other packages and Distribute the resulting +aggregation provided that you do not charge a licensing fee for the +Package. Distributor Fees are permitted, and licensing fees for other +components in the aggregation are permitted. The terms of this license +apply to the use and Distribution of the Standard or Modified Versions +as included in the aggregation. + +(8) You are permitted to link Modified and Standard Versions with +other works, to embed the Package in a larger work of your own, or to +build stand-alone binary or bytecode versions of applications that +include the Package, and Distribute the result without restriction, +provided the result does not expose a direct interface to the Package. + + +Items That are Not Considered Part of a Modified Version + +(9) Works (including, but not limited to, modules and scripts) that +merely extend or make use of the Package, do not, by themselves, cause +the Package to be a Modified Version. In addition, such works are not +considered parts of the Package itself, and are not subject to the +terms of this license. + + +General Provisions + +(10) Any use, modification, and distribution of the Standard or +Modified Versions is governed by this Artistic License. By using, +modifying or distributing the Package, you accept this license. Do not +use, modify, or distribute the Package, if you do not accept this +license. + +(11) If your Modified Version has been derived from a Modified +Version made by someone other than you, you are nevertheless required +to ensure that your Modified Version complies with the requirements of +this license. + +(12) This license does not grant you the right to use any trademark, +service mark, tradename, or logo of the Copyright Holder. + +(13) This license includes the non-exclusive, worldwide, +free-of-charge patent license to make, have made, use, offer to sell, +sell, import and otherwise transfer the Package with respect to any +patent claims licensable by the Copyright Holder that are necessarily +infringed by the Package. If you institute patent litigation +(including a cross-claim or counterclaim) against any party alleging +that the Package constitutes direct or contributory patent +infringement, then this Artistic License to you shall terminate on the +date that such litigation is filed. + +(14) Disclaimer of Warranty: +THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS +IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL +LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..4a85f5f --- /dev/null +++ b/MANIFEST @@ -0,0 +1,130 @@ +Changes +constants.c +CONTRIBUTING.md +Credits +examples/bio.pl +examples/bulk.pl +examples/callback.pl +examples/cb-testi.pl +examples/cli-cert.pl +examples/ephemeral.pl +examples/get_authenticated_page.pl +examples/get_page.pl +examples/get_page_cert.pl +examples/https-proxy-snif.pl +examples/makecert.pl +examples/minicli.pl +examples/passwd-cb.pl +examples/req.conf +examples/server_key.pem +examples/ssl-inetd-serv.pl +examples/ssl_diff.pl +examples/sslcat.pl +examples/sslecho.pl +examples/stdio_bulk.pl +examples/tcpcat.pl +examples/tcpecho.pl +examples/x509_cert_details.pl +helper_script/regen_openssl_constants.pl +lib/Net/SSLeay.pm +lib/Net/SSLeay.pod +lib/Net/SSLeay/Handle.pm +LICENSE +Makefile.PL +MANIFEST This list of files +ppport.h +QuickRef +README +README.OSX +README.VMS +README.Win32 +SSLeay.xs +t/data/binary-test.file +t/data/cert_paypal.crt.pem +t/data/cert_paypal.crt.pem_dump +t/data/chain_leaf.crt.pem +t/data/pkcs12-full.p12 +t/data/pkcs12-no-chain.p12 +t/data/pkcs12-no-passwd.p12 +t/data/test_CA1_2048.crt.pem +t/data/test_CA1_2048.key.pem +t/data/test_CA1.crl.der +t/data/test_CA1.crt.der +t/data/test_CA1.crt.pem +t/data/test_CA1.encrypted_key.pem +t/data/test_CA1.key.der +t/data/test_CA1.key.pem +t/data/test_CAinter.crt.pem +t/data/test_CAinter.extensions +t/data/test_CAinter.key.pem +t/data/test_CAinter.req.pem +t/data/test_leaf.crt.pem +t/data/test_leaf.key.pem +t/data/test_leaf.req.pem +t/data/testcert_cdp.crt.pem +t/data/testcert_cdp.crt.pem_dump +t/data/testcert_extended.crt.pem +t/data/testcert_extended.crt.pem_dump +t/data/testcert_key_2048.pem +t/data/testcert_key_2048.pem.e +t/data/testcert_simple.crt.der +t/data/testcert_simple.crt.pem +t/data/testcert_simple.crt.pem_dump +t/data/testcert_strange.crt.pem +t/data/testcert_strange.crt.pem_dump +t/data/testcert_wildcard_CA1_2048.crt.pem +t/data/testcert_wildcard.conf +t/data/testcert_wildcard.crt.pem +t/data/testreq1.der +t/data/testreq1.pem +t/data/verisign.crl.der +t/data/verisign.crl.pem +t/external/08_external.t +t/external/15_altnames.t +t/external/20_cert_chain.t +t/external/ocsp.t +t/handle/external/10_destroy.t +t/handle/external/50_external.t +t/handle/local/05_use.t +t/local/01_pod.t +t/local/02_pod_coverage.t +t/local/03_use.t +t/local/04_basic.t +t/local/05_passwd_cb.t +t/local/06_tcpecho.t +t/local/07_sslecho.t +t/local/08_pipe.t +t/local/09_ctx_new.t +t/local/10_rand.t +t/local/11_read.t +t/local/15_bio.t +t/local/20_autoload.t +t/local/21_constants.t +t/local/30_error.t +t/local/31_rsa_generate_key.t +t/local/32_x509_get_cert_info.t +t/local/33_x509_create_cert.t +t/local/34_x509_crl.t +t/local/35_ephemeral.t +t/local/36_verify.t +t/local/37_asn1_time.t +t/local/38_priv-key.t +t/local/39_pkcs12.t +t/local/40_npn_support.t +t/local/41_alpn_support.t +t/local/42_info_callback.t +t/local/43_misc_functions.t +t/local/44_sess.t +t/local/45_exporter.t +t/local/50_digest.t +t/local/61_threads-cb-crash.t +t/local/62_threads-ctx_new-deadlock.t +t/local/63_ec_key_generate_key.t +t/local/64_ticket_sharing.t +t/local/65_security_level.t +t/local/65_ticket_sharing_2.t +t/local/66_curves.t +t/local/kwalitee.t +typemap +META.yml Module YAML meta-data (added by MakeMaker) +META.json Module JSON meta-data (added by MakeMaker) diff --git a/META.json b/META.json new file mode 100644 index 0000000..5ff68b8 --- /dev/null +++ b/META.json @@ -0,0 +1,70 @@ +{ + "abstract" : "Perl extension for using OpenSSL", + "author" : [ + "Sampo Kellomäki ", + "Florian Ragwitz ", + "Mike McCauley ", + "Chris Novakovic ", + "Tuure Vartiainen ", + "Heikki Vatiainen " + ], + "dynamic_config" : 0, + "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", + "license" : [ + "artistic_2" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Net-SSLeay", + "no_index" : { + "directory" : [ + "t", + "inc", + "helper_script", + "examples" + ] + }, + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "develop" : { + "requires" : { + "Test::Kwalitee" : "1.00", + "Test::Pod::Coverage" : "1.00" + } + }, + "runtime" : { + "requires" : { + "MIME::Base64" : "0", + "perl" : "5.008001" + } + }, + "test" : { + "requires" : { + "Test::More" : "0.60_01" + } + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=net-ssleay" + }, + "repository" : { + "type" : "git", + "web" : "https://github.com/radiator-software/p5-net-ssleay" + } + }, + "version" : "1.88", + "x_serialization_backend" : "JSON::PP version 2.27300" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..6671694 --- /dev/null +++ b/META.yml @@ -0,0 +1,35 @@ +--- +abstract: 'Perl extension for using OpenSSL' +author: + - 'Sampo Kellomäki ' + - 'Florian Ragwitz ' + - 'Mike McCauley ' + - 'Chris Novakovic ' + - 'Tuure Vartiainen ' + - 'Heikki Vatiainen ' +build_requires: + ExtUtils::MakeMaker: '0' + Test::More: 0.60_01 +configure_requires: + ExtUtils::MakeMaker: '0' +dynamic_config: 0 +generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' +license: artistic_2 +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Net-SSLeay +no_index: + directory: + - t + - inc + - helper_script + - examples +requires: + MIME::Base64: '0' + perl: '5.008001' +resources: + bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=net-ssleay + repository: https://github.com/radiator-software/p5-net-ssleay +version: '1.88' +x_serialization_backend: 'CPAN::Meta::YAML version 0.012' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..31d9c74 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,348 @@ +use 5.8.1; + +use strict; +use warnings; +use ExtUtils::MakeMaker; +use Config; +use File::Spec; +use File::Basename (); +use Symbol qw(gensym); + +# Define this to one if you want to link the openssl libraries statically into +# the Net-SSLeay loadable object on Windows +my $win_link_statically = 0; + +my $tests = prompt( + "Do you want to run external tests?\n". + "These tests *will* *fail* if you do not have network connectivity.", + 'n', +) =~ /^y/i ? 't/*/*.t t/*/*/*.t' : 't/local/*.t t/handle/local/*.t'; + +my %eumm_args = ( + NAME => 'Net::SSLeay', + ABSTRACT => 'Perl extension for using OpenSSL', + LICENSE => 'artistic_2', + AUTHOR => [ + 'Sampo Kellomäki ', + 'Florian Ragwitz ', + 'Mike McCauley ', + 'Chris Novakovic ', + 'Tuure Vartiainen ', + 'Heikki Vatiainen ' + ], + VERSION_FROM => 'lib/Net/SSLeay.pm', + MIN_PERL_VERSION => '5.8.1', + CONFIGURE_REQUIRES => { + 'ExtUtils::MakeMaker' => '0', + }, + TEST_REQUIRES => { + 'Test::More' => '0.60_01', + }, + PREREQ_PM => { + 'MIME::Base64' => '0', + }, + test => { TESTS => $tests }, + clean => { FILES => join ' ', map fixpath($_), qw( + makecert.out + makecert.err + sslecho.log + tcpecho.log + t/local/ptr_cast_test + examples/cert.pem + examples/key.pem + examples/key.pem.e + examples/*.0 + ) }, + META_MERGE => { + "meta-spec" => { version => 2 }, + dynamic_config => 0, + resources => { + repository => { + type => 'git', + url => 'git@github.com/radiator-software/p5-net-ssleay.git', + web => 'https://github.com/radiator-software/p5-net-ssleay', + }, + bugtracker => { + web => 'https://rt.cpan.org/Public/Dist/Display.html?Name=net-ssleay', + }, + }, + no_index => { directory => [ qw(helper_script examples) ] }, + prereqs => { + develop => { + requires => { + 'Test::Pod::Coverage' => '1.00', + 'Test::Kwalitee' => '1.00', + }, + }, + }, + }, + ssleay(), +); + +# This can go when EU::MM older than 6.58 are gone +$eumm_args{AUTHOR} = join(', ', @{$eumm_args{AUTHOR}}) unless eval { ExtUtils::MakeMaker->VERSION(6.58); }; + +# This can go when EU::MM older than 6.64 are gone +delete $eumm_args{TEST_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.64); }; + +WriteMakefile(%eumm_args); + +sub MY::postamble { +my $regen_script = File::Spec->catfile('helper_script', 'regen_openssl_constants.pl'); +my $constants_t = File::Spec->catfile('t', 'local', '21_constants.t'); +<<"MAKE"; +constants.c : $regen_script + \$(ABSPERLRUN) $regen_script -gen-c constants.c + +$constants_t : $regen_script + \$(ABSPERLRUN) $regen_script -gen-t $constants_t + +SSLeay$Config{'obj_ext'} : constants.c $constants_t + +MAKE +} + +sub ssleay { + my $prefix = find_openssl_prefix(); + my $exec = find_openssl_exec($prefix); + unless (-x $exec) { + print < $opts->{cccdlflags}, + OPTIMIZE => $opts->{optimize}, + INC => join(' ', map qq{-I"$_"}, @{$opts->{inc_paths}}), + LIBS => join(' ', (map '-L'.maybe_quote($_), @{$opts->{lib_paths}}), (map {"-l$_"} @{$opts->{lib_links}})), + ); + # From HMBRAND to handle multple version of OPENSSL installed + if (my $lp = join " " => map '-L'.maybe_quote($_), @{$opts->{lib_paths} || []}) + { + ($args{uc $_} = $Config{$_}) =~ s/-L/$lp -L/ for qw(lddlflags ldflags); + } + %args; +} + +sub maybe_quote { $_[0] =~ / / ? qq{"$_[0]"} : $_[0] } + +sub ssleay_get_build_opts { + my ($prefix, $exec) = @_; + + my $opts = { + lib_links => [], + cccdlflags => '', + }; + for ("$prefix/include", "$prefix/inc32", '/usr/kerberos/include') { + push @{$opts->{inc_paths}}, $_ if -f "$_/openssl/ssl.h"; + } + for ($prefix, "$prefix/lib64", "$prefix/lib", "$prefix/out32dll") { + push @{$opts->{lib_paths}}, $_ if -d $_; + } + + my $rsaref = ssleay_is_rsaref(); + + print <{lib_paths} }, "$prefix/lib/VC/static" if -d "$prefix/lib/VC/static"; + } + else { + push @{ $opts->{lib_paths} }, "$prefix/lib/VC" if -d "$prefix/lib/VC"; + } + + my $found = 0; + my @pairs = (); + # Library names depend on the compiler + @pairs = (['eay32','ssl32'],['crypto.dll','ssl.dll'],['crypto','ssl']) if $Config{cc} =~ /gcc/; + @pairs = (['libeay32','ssleay32'],['libeay32MD','ssleay32MD'],['libeay32MT','ssleay32MT'],['libcrypto','libssl']) if $Config{cc} =~ /cl/; + for my $dir (@{$opts->{lib_paths}}) { + for my $p (@pairs) { + $found = 1 if ($Config{cc} =~ /gcc/ && -f "$dir/lib$p->[0].a" && -f "$dir/lib$p->[1].a"); + $found = 1 if ($Config{cc} =~ /cl/ && -f "$dir/$p->[0].lib" && -f "$dir/$p->[1].lib"); + if ($found) { + $opts->{lib_links} = [$p->[0], $p->[1], 'crypt32']; # Some systems need this system lib crypt32 too + $opts->{lib_paths} = [$dir]; + last; + } + } + } + if (!$found) { + #fallback to the old behaviour + push @{ $opts->{lib_links} }, qw( libeay32MD ssleay32MD libeay32 ssleay32 libssl32 crypt32); + } + } + elsif ($^O eq 'VMS') { + if (-r 'sslroot:[000000]openssl.cnf') { # openssl.org source install + @{ $opts->{lib_paths} } = 'SSLLIB'; + @{ $opts->{lib_links} } = qw( ssl_libssl32.olb ssl_libcrypto32.olb ); + } + elsif (-r 'ssl1$root:[000000]openssl.cnf') { # VSI or HPE SSL1 install + @{ $opts->{lib_paths} } = 'SYS$SHARE'; + @{ $opts->{lib_links} } = qw( SSL1$LIBSSL_SHR32 SSL1$LIBCRYPTO_SHR32 ); + } + elsif (-r 'ssl$root:[000000]openssl.cnf') { # HP install + @{ $opts->{lib_paths} } = 'SYS$SHARE'; + @{ $opts->{lib_links} } = qw( SSL$LIBSSL_SHR32 SSL$LIBCRYPTO_SHR32 ); + } + @{ $opts->{lib_links} } = map { $_ =~ s/32\b//g } @{ $opts->{lib_links} } if $Config{use64bitall}; + } + else { + push @{ $opts->{lib_links} }, + ($rsaref + ? qw( ssl crypto RSAglue rsaref z ) + : qw( ssl crypto z ) + ); + + if (($Config{cc} =~ /aCC/i) && $^O eq 'hpux') { + print "*** Enabling HPUX aCC options (+e)\n"; + $opts->{optimize} = '+e -O2 -g'; + } + + if ( (($Config{ccname} || $Config{cc}) eq 'gcc') && ($Config{cccdlflags} =~ /-fpic/) ) { + print "*** Enabling gcc -fPIC optimization\n"; + $opts->{cccdlflags} .= '-fPIC'; + } + } + return $opts; +} + +sub ssleay_is_rsaref { + return $ENV{OPENSSL_RSAREF}; +} + +my $other_try = 0; +my @nopath; +sub check_no_path { # On OS/2 it would be typically on default paths + my $p; + if (not($other_try++) and $] >= 5.008001) { + use ExtUtils::MM; + my $mm = MM->new(); + my ($list) = $mm->ext("-lssl"); + return unless $list =~ /-lssl\b/; + for $p (split /\Q$Config{path_sep}/, $ENV{PATH}) { + @nopath = ("$p/openssl$Config{_exe}", # exe name + '.') # dummy lib path + if -x "$p/openssl$Config{_exe}" + } + } + @nopath; +} + +sub find_openssl_prefix { + my ($dir) = @_; + + if (defined $ENV{OPENSSL_PREFIX}) { + return $ENV{OPENSSL_PREFIX}; + } + + my @guesses = ( + '/home/linuxbrew/.linuxbrew/opt/openssl/bin/openssl' => '/home/linuxbrew/.linuxbrew/opt/openssl', # LinuxBrew openssl + '/usr/local/opt/openssl/bin/openssl' => '/usr/local/opt/openssl', # OSX homebrew openssl + '/usr/local/bin/openssl' => '/usr/local', # OSX homebrew openssl + '/opt/local/bin/openssl' => '/opt/local', # Macports openssl + '/usr/bin/openssl' => '/usr', + '/usr/sbin/openssl' => '/usr', + '/opt/ssl/bin/openssl' => '/opt/ssl', + '/opt/ssl/sbin/openssl' => '/opt/ssl', + '/usr/local/ssl/bin/openssl' => '/usr/local/ssl', + '/usr/local/openssl/bin/openssl' => '/usr/local/openssl', + '/apps/openssl/std/bin/openssl' => '/apps/openssl/std', + '/usr/sfw/bin/openssl' => '/usr/sfw', # Open Solaris + 'C:\OpenSSL\bin\openssl.exe' => 'C:\OpenSSL', + 'C:\OpenSSL-Win32\bin\openssl.exe' => 'C:\OpenSSL-Win32', + $Config{prefix} . '\bin\openssl.exe' => $Config{prefix}, # strawberry perl + $Config{prefix} . '\..\c\bin\openssl.exe' => $Config{prefix} . '\..\c', # strawberry perl + '/sslexe/openssl.exe' => '/sslroot', # VMS, openssl.org + '/ssl1$exe/openssl.exe' => '/ssl1$root',# VMS, VSI or HPE install + '/ssl$exe/openssl.exe' => '/ssl$root', # VMS, HP install + ); + + while (my $k = shift @guesses + and my $v = shift @guesses) { + if ( -x $k ) { + return $v; + } + } + (undef, $dir) = check_no_path() + and return $dir; + + return; +} + +sub find_openssl_exec { + my ($prefix) = @_; + + my $exe_path; + for my $subdir (qw( bin sbin out32dll ia64_exe alpha_exe )) { + my $path = File::Spec->catfile($prefix, $subdir, "openssl$Config{_exe}"); + if ( -x $path ) { + return $path; + } + } + ($prefix) = check_no_path() + and return $prefix; + return; +} + +sub check_openssl_version { + my ($prefix, $exec) = @_; + my ($major, $minor, $letter); + + { + my $pipe = gensym(); + open($pipe, qq{"$exec" version |}) + or die "Could not execute $exec"; + my $output = <$pipe>; + chomp $output; + close $pipe; + + if ( ($major, $minor, $letter) = $output =~ /^OpenSSL\s+(\d+\.\d+)\.(\d+)([a-z]?)/ ) { + print "*** Found OpenSSL-${major}.${minor}${letter} installed in $prefix\n"; + } elsif ( ($major, $minor) = $output =~ /^LibreSSL\s+(\d+\.\d+)\.(\d+)/ ) { + print "*** Found LibreSSL-${major}.${minor} installed in $prefix\n"; + } else { + die < 1) { + print <catdir(''); + $text =~ s{\b/}{$sep}g; + return $text; +} diff --git a/QuickRef b/QuickRef new file mode 100644 index 0000000..31b8acb --- /dev/null +++ b/QuickRef @@ -0,0 +1,288 @@ +(This quick reference list was contributed by anton@genua.de. Thanks, --Sampo) + +Net::SSLeay - useful function prototypes + + +#---------------------------------- +# Import frequently used functions +#---------------------------------- + +use Net::SSLeay qw(die_now die_if_ssl_error); + +$errs = die_if_ssl_error($msg); + Program dies with $msg if print_errs() was able to find and print + some errors. + $errs is 0 if no error occurred. + +die_now($msg); + Program dies unconditionally! print_errs($msg) is used to print out + errors before dying. + + +#-------------------------- +# Unsorted prototypes +#-------------------------- + +$count = Net::SSLeay::print_errs($msg); + Prints SSLeay-error stack with included $msg via 'warn'. Number of + printed errors is returned (->$count). + +void Net::SSLeay::randomize($seed_file,$seed_string); +void Net::SSLeay::randomize(); + Load random bytes from $seed_file and from string $seed_string. + Also uses $Net::SSLeay::random_device and $Net::SSLeay::how_random + (Bits!) if used without parameters. + +void Net::SSLeay::RAND_seed($seed_string); + Seeds randomgenerator with $seed_string. + +$bytes_read = Net::SSLeay::RAND_load_file($file_name, $how_much); + Loads $how_much bytes randomness from file $file_name. + +$bytes_written = Net::SSLeay::RAND_write_file($file_name); + Writes randomness to $file_name. + +void Net::SSLeay::load_error_strings(); + Load SSL error messages to make error output more informative. + +void Net::SSLeay::ERR_load_crypto_strings(); + Load crypto-API related error messages. + +void Net::SSLeay::SSLeay_add_ssl_algorithms(); + Add support for supported ciphers. + +void Net::SSLeay::ENGINE_load_builtin_engines + Load any built-in SSL engines suported by the underlybing OpenSSL + +void Net::SSLeay::ENGINE_register_all_complete + Register any built-in SSL engines + +$ctx = Net::SSLeay::CTX_new(); + Creates SSL-context. + +int Net::SSLeay::CTX_set_default_verify_paths($ctx); + Load default location where to find certificates to verify + remote certificates. This value is precompiled in SSLeay-Toolkit. + +int Net::SSLeay::CTX_load_verify_locations($ctx, $cert_file, $cert_dir); + Set verify location. File with certificates or hashed directory. + +void Net::SSLeay::CTX_set_verify($ctx, $mode , \&verify_cb); + Set mode and callback what to do with remote certificates. + $mode: + &Net::SSLeay::VERIFY_NONE + &Net::SSLeay::VERIFY_PEER + &Net::SSLeay::VERIFY_FAIL_IF_NO_PEER_CERT + &Net::SSLeay::VERIFY_CLIENT_ONCE + \&verify_cb: + $ok = verify_cb($ok,$x509_store_ctx); + Callback gets info if SSL-toolkit verified certificate ($ok) + and certificate store location. + +void Net::SSLeay::CTX_set_default_passwd_cb($ctx,\&passwd_cb); + If our RSA private key is passphrase protected and this callback is + defined, then do not ask on the terminal but call the function. + \&passwd_cb: + $passwd = verify_cb($verify); + If $verify is true, then the callback is supposed to make sure + the returned password has been verified. + +$bool = Net::SSLeay::CTX_use_certificate_file($ctx,$cert,$type); +$bool = Net::SSLeay::CTX_use_PrivateKey_file($ctx,$key,$type); + Functions to load cert/key from filename ($cert/$key) with filetype + $type into SSL-context. + Filetypes are: + &Net::SSLeay::FILETYPE_PEM + +$ssl = Net::SSLeay::new($ctx) + Creates a SSL-session in context $ctx. Returns 0 on failure. + +$bool = Net::SSLeay::use_certificate_file($ssl,$cert,$type); +$bool = Net::SSLeay::use_RSAPrivateKey_file($ssl,$key,$type); + Functions to load cert/key from filename ($cert/$key) with filetype + $type into SSL-session. + Filetypes are: + &Net::SSLeay::FILETYPE_PEM + +$bool = Net::SSLeay::set_fd($ssl, fileno(S)); + Connect SSL-Toolkit with TCP-connection. + $ssl SSL-Session + S open socket + $bool 0-failure 1-success + +$bool = Net::SSLeay::accept($ssl); + Make SSL-handshake on hot connection. I am server! + $ssl SSL-session + $bool 0-failure 1-success + +$bool = Net::SSLeay::connect($ssl); + Make SSL-handshake on hot connection. I am client! + $ssl SSL-session + $bool 0-failure 1-success + +$x509 = Net::SSLeay::get_peer_certificate($ssl); + Get X509 certificate from SSL_session. + +$x509 = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx) + Extract current certificate from cert-store. Cert-store is + used in callbacks! + +$asn1_utctime = Net::SSLeay::X509_get_notBefore($x509); +$asn1_utctime = Net::SSLeay::X509_get_notAfter($x509); +$x509_name = Net::SSLeay::X509_get_subject_name($x509); +$x509_name = Net::SSLeay::X509_get_issuer_name($x509); +($type1, $subject1, $type2, $subject2, ...) = Net::SSLeay::X509_get_subjectAltNames($x509) + subjectAltName types as per x509v3.h GEN_* for example: + GEN_DNS == 2 + GEN_IPADD == 7 + Return information from a certificate. + +$string = Net::SSLeay::P_ASN1_UTCTIME_put2string($asn1_utctime); + Convert a asn1_utctime structure to a printable string. + +$string = Net::SSLeay::X509_NAME_oneline($x509_name); + Convert a x509_name structure to a printable string. + +$string = Net::SSLeay::get_cipher($ssl) + Return the active cipher from SSL-session $ssl. + +$string = Net::SSLeay::dump_peer_certificate($ssl) + Return Subject/Issuer from peer-certificate in printable string. + +$string = Net::SSLeay::PEM_get_string_X509($x509); + Returns a printable string containing the X509 certificate PEM encoded + from $x509. + +$mode = Net::SSLeay::CTX_get_verify_mode($ctx) + Return verify-mode previously set with CTX_set_verify in SSL-context. + +$mode = Net::SSLeay::get_verify_mode($ssl) + Return verify-mode in SSL-session. + +$written_bytes = Net::SSLeay::ssl_write_all($ssl,$string); + Write $string to SSL-session. This call returns undef if write failed. + The whole string gets written! + +$written_bytes = $Net::SSLeay::write($ssl,$string); + Write $string to SSL-session. This call returns immediately. SSL maybe + wrote the string not completely - check yourself or use ssl_write_all! + +$string = Net::SSLeay::ssl_read_all($ssl,$how_much); + Read everything available from the SSL-session and return it. Read a + maximum of $how_much Bytes (default: 2000000000). + +$string = Net::SSLeay::read($ssl); + Read one bunch of data from the SSL-session and return. + +void Net::SSLeay::free ($ssl); + Free ressources from the SSL-session. + +void Net::SSLeay::CTX_free ($ctx); + Free ressources from the SSL-context. + + +#---------------------- +# Hash functions +#---------------------- + +# Several cryptographic digests (hash functions) are supported, possibly +# including MD2, MD4, MD5, and RIPEMD160. + +$hash = Net::SSLeay:MD5($data); + Computes md5 hash over $data. $hash is a binary string! Convert it to + a printable with $string = unpack("H32",Net::SSLeay::MD5($data)); + +$hash = Net::SSLeay:RIPEMD160($data); + Computes RIPEMD160 hash over $data. $hash is a binary string! Convert it to + a printable with $string = unpack("H40",Net::SSLeay::RIPEMD160($data)); + +Note that some digests may not be available, depending on the version +of OpenSSL used. + + +#---------------------- +# TCP-Connection hints +#---------------------- + +# Make socket unbuffered after connect succeeded. +# +select(S); $| = 1; select(STDOUT); + +# Close connection by half... from client to server. This signals EOF to +# server. (Clear some buffers, too...??) +# Use this if finished with sending data to remote side. +shutdown S, 1; + +# Finally close connection. Do this after reading everything availlable! +# +close S; + + +#------------------ +# TCP Client +#------------------ + +# #!/usr/bin/perl -w +use strict; +use Socket; +my ($remote,$port, $iaddr, $paddr, $proto, $line); + +$remote = shift || 'localhost'; +$port = shift || 3000; # random port +if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') } +die "No port" unless $port; +$iaddr = inet_aton($remote) || die "no host: $remote"; +$paddr = sockaddr_in($port, $iaddr); + +$proto = getprotobyname('tcp'); +socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; +connect(SOCK, $paddr) || die "connect: $!"; +while (defined($line = )) { + print $line; +} + +close (SOCK) || die "close: $!"; +exit; + + +#-------------------- +# TCP Server +#-------------------- + +# #!/usr/bin/perl -Tw +use strict; +BEGIN { $ENV{PATH} = '/usr/ucb:/bin' } +use Socket; +use Carp; + +sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" } + +my $EOL = "\015\012"; + +my $port = shift || 3000; +my $proto = getprotobyname('tcp'); +$port = $1 if $port =~ /(\d+)/; # untaint port number + +socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; +setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, + pack("l", 1)) || die "setsockopt: $!"; + +bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!"; +listen(Server,SOMAXCONN) || die "listen: $!"; + +logmsg "server started on port $port"; + +my $paddr; + +for ( ; $paddr = accept(Client,Server); close Client) { + my($port,$iaddr) = sockaddr_in($paddr); + my $name = gethostbyaddr($iaddr,AF_INET); + + logmsg "connection from $name [", + inet_ntoa($iaddr), "] + at port $port"; + + print Client "Hello there, $name, it's now ", + scalar localtime, $EOL; +} + diff --git a/README b/README new file mode 100644 index 0000000..2c559ad --- /dev/null +++ b/README @@ -0,0 +1,329 @@ +README - Net::SSLeay Perl module for using OpenSSL + +By popular demand... +-------------------- + + perl -MNet::SSLeay -e '($p)=Net::SSLeay::get_https("www.openssl.org", 443, "/"); print $p' + + +for the released versions: + https://metacpan.org/release/Net-SSLeay + +for the latest and possibly unstable version from git: + + https://github.com/radiator-software/p5-net-ssleay + + +Prerequisites +------------- + +Perl 5.8.1 or higher. + +OpenSSL-0.9.6j through to at least OpenSSL-1.1 and probably later + http://www.openssl.org/ - On Linux, you can either build and + install OpenSSL from scratch (its very portable) or you can + install the appropriate OpenSSL 'devel' package for your Linux + distribution: (rpm openssl-devel, deb libssl-dev). + + +Note: SSLeay is no longer supported. If you want to use Net::SSLeay with + SSLeay or early versions of OpenSSL, use version 1.03. The support + for SSLeay was dropped due to nobody maintaining it (all active + work goes on with OpenSSL) and due to incompatible API changes + in OpenSSL-0.9.2b. OpenSSL-0.9.1c support has also been dropped, + version 1.03 was the last one to support that. + +LibreSSL is also supported. + +You should use the same C compiler and options to compile OpenSSL, +perl, and Net::SSLeay. This is the only supported configuration. +If you insist on using different compilers (perhaps because you +obtained either OpenSSL or perl as binaries from a vendor and they +used a compiler that you do not have) then all requests for support +will be ignored. If the only way for you to use the same compiler +for all three components is to recompile your openssl or perl, then +that is exactly what I expect you to do before asking for support. + +Installing +---------- + +Unix: + # build or install OpenSSL as per instructions in that package + + gunzip bt # show stack trace + gdb perl # run live with debugging + # set break point in SSLeay.xs or in suspect function of OpenSSL + > br XS_Net__SSLeay_connect + > run yourscript.pl arg arg + +For gdb'ing make sure gdb finds all the relevant source code. This +may mean that you must run perl and OpenSSL from the directories where +the respective makefiles build them. + +You can also enable PR and PRN macros in SSLeay.xs and sprinkle +even some more around the code to figure out what's happening. + +Some exotic configurations of perl may cause unstability: make sure +OpenSSL uses the same malloc as perl. Recompile perl without +threads. Try not using the PerlIO abstraction. + +If you need to tweak build for some platform, please let me know +so I can fix it. Patches and gdb session dumps are also welcome. + +Copyright +--------- + +Copyright (c) 1996-2003 Sampo Kellomäki +Copyright (c) 2005-2010 Florian Ragwitz +Copyright (c) 2005-2018 Mike McCauley +Copyright (c) 2018- Chris Novakovic +Copyright (c) 2018- Tuure Vartiainen +Copyright (c) 2018- Heikki Vatiainen + +All rights reserved. + +License +------- + +Net-SSLeay is released under the terms of the Artistic License 2.0. For +details, see the LICENSE file. + +Recommended reading +------------------- + +===> HTTP protocol specification. It applies 100% to HTTPS too and doing +password authentication is explained there. <=== + +If you are newbie interested in grabbing web pages from https servers, +please read HTTP documentation from http://www.w3c.org/ before asking trivial +questions. That document also covers the basic-auth FAQ (URLs like +http://user:pass@host). Do not ask questions about authentication before +consulting the HTTP specification. HTTPS is just HTTP in SSL transport. + +If you are doing advanced stuff, and don't find documentation you need, +please try to extrapolate from OpenSSL documentation (which unfortunately +is quite sparse) and the source code. + +If you run into build problems, especially regarding shared libraries, +check your perl documentation, especially the perlxtut(1) man page, +which gives excellent tutorial of the build process of XSUBs. + + perlxtut(1) + perlxs(1) + perlguts(1) + perlcall(1) + +Say `perldoc Net::SSLeay' _NOW_! + +To download OpenSSL, see https://www.openssl.org/ + +Bug reports, patch submission, feature requests and git access to the +latest source code etc., can be obtained at +https://github.com/radiator-software/p5-net-ssleay + + diff --git a/README.OSX b/README.OSX new file mode 100644 index 0000000..52aafa6 --- /dev/null +++ b/README.OSX @@ -0,0 +1,66 @@ +As of 15 Jun 2015, Apply no longer ships OpenSSL with OS X: +(http://lists.apple.com/archives/macnetworkprog/2015/Jun/msg00025.html) + +Some OS X packages and bundles install OpenSSL, typically in /opt/local +if that is the case it is sufficient for you to unpack and build +Net-SSLeay in the usual way: + +#cd to a working directory +cd /Users/mikem/tmp/ +# unpack net-ssleay from wherever you got it: +tar zxvf /Volumes/projects/net-ssleay/trunk/Net-SSLeay-1.72.tar.gz +cd Net-SSLeay-1.72 +# Build it for 64 bits (default) +perl Makefile.PL +make +make test +# as root, install the compiled Net-SSLeay: +make install + +If a working openssl is not installed already the above will fail, +but you can still build your own OpenSSL to link against: +(https://wiki.openssl.org/index.php/Compilation_and_Installation), and build Net-SSLeay against it: +Test compilation etc in a private directory eg: + +#cd to a working directory +cd /Users/mikem/tmp/ +wd=`pwd` +# unpack openssl from wherever you got it: +tar zxvf /Volumes/src/openssl-1.0.2c.tar.gz +cd openssl-1.0.2c +# Build for 64 bits and install it in a local directory +darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp --prefix=$wd/openssl +make +make install_sw +cd $wd +# unpack net-ssleay from wherever you got it: +tar zxvf /Volumes/projects/net-ssleay/trunk/Net-SSLeay-1.72.tar.gz +cd Net-SSLeay-1.72 +# Build it for 64 bits (default) +OPENSSL_PREFIX=$wd/openssl perl Makefile.PL +make test +# You should see successful test run data and "Result: PASS" + +Real installation of OpenSSL and Net-SSLeay to public areas eg: + +#cd to a working directory +cd /Users/mikem/tmp/ +wd=`pwd` +# unpack openssl from wherever you got it: +tar zxvf /Volumes/src/openssl-1.0.2c.tar.gz +cd openssl-1.0.2c +# Build for 64 bits and install it in a local directory +darwin64-x86_64-cc shared enable-ec_nistp_64_gcc_128 no-ssl2 no-ssl3 no-comp +make +sudo make install_sw +cd $wd +# unpack net-ssleay from wherever you got it: +tar zxvf /Volumes/projects/net-ssleay/trunk/Net-SSLeay-1.72.tar.gz +cd Net-SSLeay-1.72 +# Build it for 64 bits (default) +perl Makefile.PL +make test +# You should see successful test run data and "Result: PASS" +# Install it, typically to /Library/Perl/5.18 or whereever +sudo make install + diff --git a/README.VMS b/README.VMS new file mode 100644 index 0000000..bb26df8 --- /dev/null +++ b/README.VMS @@ -0,0 +1,27 @@ +Building on OpenVMS +====================== +You'll need to either build and install OpenSSL from source using the +authoritative sources from openssl.org or install a PCSI kit from HPE or +VSI. Building against your own from-source installation currently uses +SSL object libraries that will be statically linked into the +Net::SSLeay shareable image. That means no updates to SSL without +updating Net::SSLeay. + +Building against a vendor installation gives you the possibility of SSL +updates without rebuilding Net::SSLeay, assuming the upgrade is binary +compatible, and also gets you the possibility of vendor support if you +encounter a problem that is within the SSL libraries. If you don't know +what any of this means, just use whatever is already on your system (if +anything) or install whatever is easiest. + +Once you've got a working installation of the SSL libraries, the steps +to build Net::SSLeay on VMS are really the same as building any other +package,and should look something like: + + $ gzip -d Net-SSLeay-xx.xx.tar.gz + $ vmstar -xvf Net-SSLeay-xx.xx.tar + $ set default [.Net-SSLeay-xx_xx] + $ perl Makefile.PL + $ mmk + $ mmk test + $ mmk install diff --git a/README.Win32 b/README.Win32 new file mode 100644 index 0000000..751723f --- /dev/null +++ b/README.Win32 @@ -0,0 +1,232 @@ +Building on Win 32 platforms +============================ +31.7.1999, Sampo Kellomaki +7.6.2002, reviewed and added comments, --Sampo +16.8.2002, added comments by Marcel Bucher --Sampo +10.7.2007. Complete rewrite to agree with latest version 1.31. References to +ancient versions and untested procedures removed --mikem +22.4.2010 Updated info for 64 bit versions --mikem + +Notes: + +1. With some combinations of Windows, perl, compiler and compiler options, you +may see a runtime error "no OPENSSL_Applink", when calling +Net::SSLeay::P_PKCS12_load_file. This appears to be due to incompatible +compile options between the openssl libraries and Net::SSLeay. In particular +it has been observed with Shining Light OpenSSL See +https://www.openssl.org/support/faq.html for more details. Alas, the +apparently simple and receommended solution of adding applink.c to the SSLeay +library does not work, since applink.c need to be in the .exe file, not the +.dll for this to work. Best workaround is to build and install OpenSSL for +windows yourself. + +2. If your OpenSSL is installed in an unusual place, you can tell +Net-SSLeay where to find it with the OPENSSL_PREFIX environment +variable: +set OPENSSL_PREFIX=c:\OpenSSL-1.0.1c +perl Makefile.PL +make +..... + +1. Windows Server 2003 + ActivePerl 5.8.8.820 + VC++ 6.0 + Microsoft Platform SDK SVR2003R2 + Shining Light Win32 OpenSSL 0.9.7L + http://www.shininglightpro.com/products/Win32OpenSSL.html + Dynamic linking to SSL DLLs + +Install all packages in the order listed above +Unpack and install the Net-SSLeay package + cd Net-SSLeay-xxxx + perl Makefile.PL + nmake + nmake test + nmake install + +Caution. There is an issue with Shining Light Win32 OpenSSL 0.9.7m and 0.9.8e +on Server 2003: These versions were built with VC 7.1 and the packages are +missing the 7.1 runtime DLL. This means that the openssl binaries from those +versions will not run on a standard Server 2003 platform, and this prevents +Net-SSLeay being built. Shining Light say this problem will be fixed in later +versions, where they will revert to the earlier build procedures. + +2. Windows Server 2003 + ActivePerl 5.8.8.820 + VC++ 6.0 + Microsoft Platform SDK SVR2003R2 + OpenSSL 0.9.8e source openssl-0.9.8e.tar.gz + Dynamic linking to SSL DLLs + +Install all packages in the order listed above +Unpack and build OpenSSL: + cd openssl-0.9.8e + perl Configure VC-WIN32 --prefix=c:/OpenSSL + ms\do_ms + nmake -f ms\ntdll.mak + nmake -f ms\ntdll.mak install +(if you have trouble getting to this stage, consult INSTALL.W32) + copy c:\OpenSSL\bin\*.dll c:\windows\system32 + +Unpack and install the Net-SSLeay package + cd Net-SSLeay-xxxx + perl Makefile.PL + nmake + copy c:\OpenSSL\bin\*.dll blib\arch\auto\Net\SSLeay\ + nmake test + nmake install + +3. Windows XP SP2 CAUTION: this is not working yet + ActivePerl 5.8.8.820 + Visual Studio Express 2005 + Microsoft Platform SDK SVR2003R2 + OpenSSL 0.9.8e source openssl-0.9.8e.tar.gz + Dynamic linking to SSL DLLs + +- Install all packages in the order listed above (make sure you follow the + instructions on the download page about adding the appropriate paths to the + Projects and Solutions section of the Options dialog box, and updating + corewin_express.vsprops file) +- Start a build shell with Start->All Programs->Microsoft Windows SDK->CMD Shell +- cd openssl-0.9.8e +- perl Configure VC-WIN32 --prefix=c:/OpenSSL +- ms\do_masm +- nmake -f ms\ntdll.mak +- nmake -f ms\ntdll.mak install + (if you have trouble getting to this stage, consult INSTALL.W32) +- cd Net-SSLeay-xxxx +- perl Makefile.PL +- nmake +- copy c:\OpenSSL\bin\*.dll blib\arch\auto\Net\SSLeay\ +- nmake test + CAUTION: nmake test fails at this stage. Any suggestions?? This may be + relevant: http://www.itwriting.com/blog/?postid=261&replyto=2542 +- nmake install + +4. Windows XP SP2 + Strawberry Perl 5.8.8-alpha-2 + OpenSSL 0.9.8e source openssl-0.9.8e.tar.gz + +- Install Strawberry Perl by running the installer + (strawberry-perl-5.8.8-alpha-2.exe in this example) +- Unpack openssl-0.9.8e.tar.gz +- cd openssl-0.9.8e +- ms\mingw32 +- cd out +- ..\ms\test + (if you have trouble getting to this stage, consult INSTALL.W32) +- md c:\openssl +- md c:\openssl\bin +- md c:\openssl\lib +- md c:\openssl\include +- md c:\openssl\include\openssl +- copy /b inc32\openssl\* c:\openssl\include\openssl +- copy /b out\libssl32.a c:\openssl\lib +- copy /b out\libeay32.a c:\openssl\lib +- copy /b libssl32.dll c:\openssl\bin +- copy /b libeay32.dll c:\openssl\bin +- copy /b out\openssl.exe c:\openssl\bin +- cd Net-SSLeay-xxxx +- c:\strawberry-perl\perl\bin\perl Makefile.PL +- dmake +- copy c:\openssl\bin\*.dll blib/arch/auto/Net/SSLeay +- dmake install + +4. Windows XP SP2 + Perl CamelPack perl-camelpack-5.8.7.exe + Shining Light Win32 OpenSSL 0.9.7L + http://www.shininglightpro.com/products/Win32OpenSSL.html + +Install all packages in the order listed above +Unpack and install the Net-SSLeay package + cd Net-SSLeay-xxxx + perl Makefile.PL (accept external tests and extra CPAN installs) + nmake + nmake install + +(Note that 'nmake test' does not seem to work with CamelPack 5.8.7) + +5. Windows Server 2003 + ActivePerl 5.8.8.820 + VC++ 6.0 + Microsoft Platform SDK SVR2003R2 + OpenSSL 0.9.8e source openssl-0.9.8e.tar.gz + tls extensions patch + from Radiator/goodies/openssl-0.9.8e-session-ticket-osc.patch + Dynamic linking to SSL DLLs + +Install all packages in the order listed above +Unpack, patch and and build OpenSSL, patch with + cd openssl-0.9.8e+extensions + patch -p1 < Radiator/goodies/openssl-0.9.8e-session-ticket-osc.patch + perl Configure VC-WIN32 --prefix=c:/OpenSSL enable-tlsext + ms\do_ms + nmake -f ms\ntdll.mak + nmake -f ms\ntdll.mak install +(if you have trouble getting to this stage, consult INSTALL.W32) + copy c:\OpenSSL\bin\*.dll c:\windows\system32 + +Unpack and install the Net-SSLeay package + cd Net-SSLeay-xxxx + perl Makefile.PL + nmake + copy c:\OpenSSL\bin\*.dll blib\arch\auto\Net\SSLeay\ + nmake test + nmake install + +6. Windows Server 2003 + ActivePerl 5.10.1 + Microsoft Platform SDK 2003 SP1 + OpenSSL 0.9.8i source including TLS extensions + Dynamic linking to SSL DLLs + +Build OpenSSL + S: + cd \openssl-0.9.8i+extensions + nmake -f ms\ntdll.mak clean + perl Configure VC-WIN64A --prefix=c:/OpenSSL enable-tlsext + ms\do_win64a + nmake -f ms\ntdll.mak + cd out32dll + ..\ms\test + nmake -f ms\ntdll.mak install +Now build Net-SSLeay + nmake clean + R: + cd \net-ssleay\trunk + perl Makefile.PL + nmake + copy c:\OpenSSL\bin\*.dll blib\arch\auto\Net\SSLeay + nmake test + nmake install + +7. Windows XP Professional SP3 + ActivePerl 5.16.1 + OpenSSL 1.0.1j binary from http://slproweb.com/download/Win32OpenSSL-1_0_1j.exe + Visual C++ 2008 Redistributables from http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF + Microsoft Visual Studio 2010 Express + with Visual Studio Command Prompt shell: + R: + cd \net-ssleay\trunk + perl Makefile.PL + nmake + nmake test (some warnings will be reported) + +8. Windows XP Professional SP3 on VMWare + ActivePerl 5.16.1 + OpenSSL 1.0.1 source code + Microsoft Visual Studio 2010 Express + with Visual Studio Command Prompt shell: +Build OpenSSL + S: + cd \openssl-1.0.1e + perl Configure VC-WIN32 no-asm --prefix=c:/OpenSSL + ms\do_ms + nmake -f ms\ntdll.mak + nmake -f ms\ntdll.mak install +Now build Net-SSLeay + R: + cd \net-ssleay\trunk + nmake clean + perl Makefile.PL + nmake + nmake test (some warnings will be reported) diff --git a/SSLeay.xs b/SSLeay.xs new file mode 100644 index 0000000..61dc2b2 --- /dev/null +++ b/SSLeay.xs @@ -0,0 +1,7491 @@ +/* SSLeay.xs - Perl module for using Eric Young's implementation of SSL + * + * Copyright (c) 1996-2003 Sampo Kellomäki + * Copyright (c) 2005-2010 Florian Ragwitz + * Copyright (c) 2005-2018 Mike McCauley + * Copyright (c) 2018- Chris Novakovic + * Copyright (c) 2018- Tuure Vartiainen + * Copyright (c) 2018- Heikki Vatiainen + * + * All rights reserved. + * + * Change data removed. See Changes + * + * This module is released under the terms of the Artistic License 2.0. For + * details, see the LICENSE file. + */ + +/* #### + * #### PLEASE READ THE FOLLOWING RULES BEFORE YOU START EDITING THIS FILE! #### + * #### + * + * Function naming conventions: + * + * 1/ never change the already existing function names (all calling convention) in a way + * that may cause backward incompatibility (e.g. add ALIAS with old name if necessary) + * + * 2/ it is recommended to keep the original openssl function names for functions that are: + * + * 1:1 wrappers to the original openssl functions + * see for example: X509_get_issuer_name(cert) >> Net::SSLeay::X509_get_issuer_name($cert) + * + * nearly 1:1 wrappers implementing only necessary "glue" e.g. buffer handling + * see for example: RAND_seed(buf,len) >> Net::SSLeay::RAND_seed($buf) + * + * 3/ OpenSSL functions starting with "SSL_" are added into SSLeay.xs with "SLL_" prefix + * (e.g. SSL_CTX_new) but keep in mind that they will be available in Net::SSLeay without + * "SSL_" prefix (e.g. Net::SSLeay::CTX_new) - keep this for all new functions + * + * 4/ The names of functions which do not fit rule 2/ (which means they implement some non + * trivial code around original openssl function or do more complex tasks) should be + * prefixed with "P_" - see for example: P_ASN1_TIME_set_isotime + * + * 5/ Exceptions from rules above: + * functions that are part or wider set of already existing function not following this rule + * for example: there already exists: PEM_get_string_X509_CRL + PEM_get_string_X509_REQ and you want + * to add PEM_get_string_SOMETHING - then no need to follow 3/ (do not prefix with "P_") + * + * Support for different openssl versions, different platforms, different compilers: + * + * 1/ SSleay.xs is expected to build/pass test suite + * - with openssl 0.9.6 and newer versions + * - with perl 5.8 and newer versions + * + * 2/ Fix all compiler warnings - we expect 100% clean build + * + * 3/ If you add a function which is available since certain openssl version + * use proper #ifdefs to assure that SSLeay.xs will compile also with older versions + * which are missing this function + * + * 4/ Even warnings arising from different use of "const" in different openssl versions + * needs to be hanled with #ifdefs - see for example: X509_NAME_add_entry_by_txt + * + * 5/ avoid using global C variables (it is very likely to break thread-safetyness) + * use rather global MY_CXT structure + * + * 6/ avoid using any UNIX/POSIX specific functions, keep in mind that SSLeay.xs must + * compile also on non-UNIX platforms like MS Windows and others + * + * 7/ avoid using c++ comments "//" (or other c++ features accepted by some c compiler) + * even if your compiler can handle them without warnings + * + * Passing test suite: + * + * 1/ any changes to SSLeay.xs must not introduce a failure of existing test suite + * + * 2/ it is strongly recommended to create test(s) for newly added function(s), especially + * when the new function is not only a 1:1 wrapper but contains a complex code + * + * 3/ it is mandatory to add a documentation for all newly added functions into SSLeay.pod + * otherwise t/local/02_pod_coverage.t fail (and you will be asked to add some doc into + * your patch) + * + * Preferred code layout: + * + * 1/ for simple 1:1 XS wrappers use: + * + * a/ functions with short "signature" (short list of args): + * + * long + * SSL_set_tmp_dh(SSL *ssl,DH *dh) + * + * b/ functions with long "signature" (long list of args): + * simply when approach a/ does not fit to 120 columns + * + * void + * SSL_any_functions(library_flag,function_name,reason,file_name,line) + * int library_flag + * int function_name + * int reason + * char *file_name + * int line + * + * 2/ for XS functions with full implementation use identation like this: + * + * int + * RAND_bytes(buf, num) + * SV *buf + * int num + * PREINIT: + * int rc; + * unsigned char *random; + * CODE: + * / * some code here * / + * RETVAL = rc; + * OUTPUT: + * RETVAL + * + * + * Runtime debugging: + * + * with TRACE(level,fmt,...) you can output debug messages. + * it behaves the same as + * warn sprintf($msg,...) if $Net::SSLeay::trace>=$level + * would do in Perl (e.g. it is using also the $Net::SSLeay::trace variable) + * + * + * THE LAST RULE: + * + * The fact that some parts of SSLeay.xs do not follow the rules above is not + * a reason why any new code can also break these rules in the same way + * + */ + +/* Prevent warnings about strncpy from Windows compilers */ +#define _CRT_SECURE_NO_DEPRECATE + +#ifdef __cplusplus +extern "C" { +#endif +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" +#include +#define NEED_newRV_noinc +#define NEED_sv_2pv_flags +#define NEED_my_snprintf +#include "ppport.h" +#ifdef __cplusplus +} +#endif + +/* OpenSSL-0.9.3a has some strange warning about this in + * openssl/des.h + */ +#undef _ + +/* Sigh: openssl 1.0 has + typedef void *BLOCK; +which conflicts with perls + typedef struct block BLOCK; +*/ +#define BLOCK OPENSSL_BLOCK +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_COMP +#include /* openssl-0.9.6a forgets to include this */ +#endif +#ifndef OPENSSL_NO_MD2 +#include +#endif +#ifndef OPENSSL_NO_MD4 +#include +#endif +#ifndef OPENSSL_NO_MD5 +#include /* openssl-SNAP-20020227 does not automatically include this */ +#endif +#if OPENSSL_VERSION_NUMBER >= 0x00905000L +#include +#endif +#include +#include +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +/* requires 0.9.7+ */ +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#endif +#ifdef OPENSSL_FIPS +#include +#endif +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +#include +#endif +#undef BLOCK + +/* Debugging output - to enable use: + * + * perl Makefile.PL DEFINE=-DSHOW_XS_DEBUG + * make + * + */ + +#ifdef SHOW_XS_DEBUG +#define PR1(s) fprintf(stderr,s); +#define PR2(s,t) fprintf(stderr,s,t); +#define PR3(s,t,u) fprintf(stderr,s,t,u); +#define PR4(s,t,u,v) fprintf(stderr,s,t,u,v); +#else +#define PR1(s) +#define PR2(s,t) +#define PR3(s,t,u) +#define PR4(s,t,u,v) +#endif + +static void TRACE(int level,char *msg,...) { + va_list args; + SV *trace = get_sv("Net::SSLeay::trace",0); + if (trace && SvIOK(trace) && SvIV(trace)>=level) { + char buf[4096]; + va_start(args,msg); + vsnprintf(buf,4095,msg,args); + warn("%s",buf); + va_end(args); + } +} + +#include "constants.c" + +/* ============= thread-safety related stuff ============== */ + +#define MY_CXT_KEY "Net::SSLeay::_guts" XS_VERSION + +typedef struct { + HV* global_cb_data; + UV tid; +} my_cxt_t; +START_MY_CXT + +#ifdef USE_ITHREADS +static perl_mutex LIB_init_mutex; +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static perl_mutex *GLOBAL_openssl_mutex = NULL; +#endif +#endif +static int LIB_initialized; + +UV get_my_thread_id(void) /* returns threads->tid() value */ +{ + dSP; + UV tid = 0; +#ifdef USE_ITHREADS + int count = 0; + + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv("threads", 0))); + PUTBACK; + count = call_method("tid", G_SCALAR|G_EVAL); + SPAGAIN; + /* Caution: recent perls do not appear support threads->tid() */ + if (SvTRUE(ERRSV) || count != 1) + { + /* if compatible threads not loaded or an error occurs return 0 */ + tid = 0; + } + else + tid = (UV)POPi; + PUTBACK; + FREETMPS; + LEAVE; +#endif + + return tid; +} + +/* IMPORTANT NOTE: + * openssl locking was implemented according to http://www.openssl.org/docs/crypto/threads.html + * we implement both static and dynamic locking as described on URL above + * locking is supported when OPENSSL_THREADS macro is defined which means openssl-0.9.7 or newer + * we intentionally do not implement cleanup of openssl's threading as it causes troubles + * with apache-mpm-worker+mod_perl+mod_ssl+net-ssleay + */ +#if defined(USE_ITHREADS) && defined(OPENSSL_THREADS) + + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static void openssl_locking_function(int mode, int type, const char *file, int line) +{ + PR3("openssl_locking_function %d %d\n", mode, type); + + if (!GLOBAL_openssl_mutex) return; + if (mode & CRYPTO_LOCK) + MUTEX_LOCK(&GLOBAL_openssl_mutex[type]); + else + MUTEX_UNLOCK(&GLOBAL_openssl_mutex[type]); +} + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +static unsigned long openssl_threadid_func(void) +{ + dMY_CXT; + return (unsigned long)(MY_CXT.tid); +} +#else +void openssl_threadid_func(CRYPTO_THREADID *id) +{ + dMY_CXT; + CRYPTO_THREADID_set_numeric(id, (unsigned long)(MY_CXT.tid)); +} +#endif + +struct CRYPTO_dynlock_value +{ + perl_mutex mutex; +}; + +struct CRYPTO_dynlock_value * openssl_dynlocking_create_function (const char *file, int line) +{ + struct CRYPTO_dynlock_value *retval; + New(0, retval, 1, struct CRYPTO_dynlock_value); + if (!retval) return NULL; + MUTEX_INIT(&retval->mutex); + return retval; +} + +void openssl_dynlocking_lock_function (int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) +{ + if (!l) return; + if (mode & CRYPTO_LOCK) + MUTEX_LOCK(&l->mutex); + else + MUTEX_UNLOCK(&l->mutex); +} + +void openssl_dynlocking_destroy_function (struct CRYPTO_dynlock_value *l, const char *file, int line) +{ + if (!l) return; + MUTEX_DESTROY(&l->mutex); + Safefree(l); +} +#endif + +void openssl_threads_init(void) +{ + int i; + + PR1("STARTED: openssl_threads_init\n"); + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /* initialize static locking */ + if ( !CRYPTO_get_locking_callback() ) { +#if OPENSSL_VERSION_NUMBER < 0x10000000L + if ( !CRYPTO_get_id_callback() ) { +#else + if ( !CRYPTO_THREADID_get_callback() ) { +#endif + PR2("openssl_threads_init static locking %d\n", CRYPTO_num_locks()); + New(0, GLOBAL_openssl_mutex, CRYPTO_num_locks(), perl_mutex); + if (!GLOBAL_openssl_mutex) return; + for (i=0; i= 0x1000000fL +static void handler_list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg) +{ + /* taken from apps/dgst.c */ + const char *mname; + if (!m) return; /* Skip aliases */ + mname = OBJ_nid2ln(EVP_MD_type(m)); + if (strcmp(from, mname)) return; /* Skip shortnames */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST) return; /* Skip clones */ +#endif + if (strchr(mname, ' ')) mname= EVP_MD_name(m); + av_push(arg, newSVpv(mname,0)); +} +#endif + +/* ============= callbacks - basic info ============= + * + * PLEASE READ THIS BEFORE YOU ADD ANY NEW CALLBACK!! + * + * There are basically 2 types of callbacks used in SSLeay: + * + * 1/ "one-time" callbacks - these are created+used+destroyed within one perl function implemented in XS + * these callbacks use a cpecial C structupe simple_cb_data_t to pass necessary data + * there are 2 related helper functions: simple_cb_data_new() + simple_cb_data_free + * for example see implementation of these functions: + * - RSA_generate_key + * - PEM_read_bio_PrivateKey + * + * 2/ "advanced" callbacks - these are setup/destroyed by one function but used by another function; these + * callbacks use global hash MY_CXT.global_cb_data to store perl functions + data to be uset at callback time + * there are 2 related helper functions: cb_data_advanced_put() + cb_data_advanced_get for manipulating + * global hash MY_CXT.global_cb_data which work like this: + * cb_data_advanced_put(, "data_name", dataSV) + * >>> + * global_cb_data->{"ptr_"}->{"data_name"} = dataSV) + * or + * data = cb_data_advanced_get(, "data_name") + * >>> + * my $data = global_cb_data->{"ptr_"}->{"data_name"} + * for example see implementation of these functions: + * - SSL_CTX_set_verify + * - SSL_set_verify + * - SSL_CTX_set_cert_verify_callback + * - SSL_CTX_set_default_passwd_cb + * - SSL_CTX_set_default_passwd_cb_userdata + * - SSL_set_session_secret_cb + * + * If you want to add a new callback: + * - you very likely need a new function "your_callback_name_invoke()" + * - decide whether your case fits case 1/ or 2/ (and implement likewise existing functions) + * - try to avoid adding a new style of callback implementation (or ask Net::SSLeay maintainers before) + * + */ + +/* ============= callback stuff - generic functions============== */ + +struct _ssleay_cb_t { + SV* func; + SV* data; +}; +typedef struct _ssleay_cb_t simple_cb_data_t; + +simple_cb_data_t* simple_cb_data_new(SV* func, SV* data) +{ + simple_cb_data_t* cb; + New(0, cb, 1, simple_cb_data_t); + if (cb) { + SvREFCNT_inc(func); + SvREFCNT_inc(data); + cb->func = func; + cb->data = (data == &PL_sv_undef) ? NULL : data; + } + return cb; +} + +void simple_cb_data_free(simple_cb_data_t* cb) +{ + if (cb) { + if (cb->func) { + SvREFCNT_dec(cb->func); + cb->func = NULL; + } + if (cb->data) { + SvREFCNT_dec(cb->data); + cb->data = NULL; + } + } + Safefree(cb); +} + +int cb_data_advanced_put(void *ptr, const char* data_name, SV* data) +{ + HV * L2HV; + SV ** svtmp; + int len; + char key_name[500]; + dMY_CXT; + + len = my_snprintf(key_name, sizeof(key_name), "ptr_%p", ptr); + if (len == sizeof(key_name)) return 0; /* error - key_name too short*/ + + /* get or create level-2 hash */ + svtmp = hv_fetch(MY_CXT.global_cb_data, key_name, strlen(key_name), 0); + if (svtmp == NULL) { + L2HV = newHV(); + hv_store(MY_CXT.global_cb_data, key_name, strlen(key_name), newRV_noinc((SV*)L2HV), 0); + } + else { + if (!SvOK(*svtmp) || !SvROK(*svtmp)) return 0; +#if defined(MUTABLE_PTR) + L2HV = (HV*)MUTABLE_PTR(SvRV(*svtmp)); +#else + L2HV = (HV*)(SvRV(*svtmp)); +#endif + } + + /* first delete already stored value */ + hv_delete(L2HV, data_name, strlen(data_name), G_DISCARD); + if (data!=NULL) { + if (SvOK(data)) + hv_store(L2HV, data_name, strlen(data_name), data, 0); + else + /* we're not storing data so discard it */ + SvREFCNT_dec(data); + } + + return 1; +} + +SV* cb_data_advanced_get(void *ptr, const char* data_name) +{ + HV * L2HV; + SV ** svtmp; + int len; + char key_name[500]; + dMY_CXT; + + len = my_snprintf(key_name, sizeof(key_name), "ptr_%p", ptr); + if (len == sizeof(key_name)) return &PL_sv_undef; /* return undef on error - key_name too short*/ + + /* get level-2 hash */ + svtmp = hv_fetch(MY_CXT.global_cb_data, key_name, strlen(key_name), 0); + if (svtmp == NULL) return &PL_sv_undef; + if (!SvOK(*svtmp)) return &PL_sv_undef; + if (!SvROK(*svtmp)) return &PL_sv_undef; +#if defined(MUTABLE_PTR) + L2HV = (HV*)MUTABLE_PTR(SvRV(*svtmp)); +#else + L2HV = (HV*)(SvRV(*svtmp)); +#endif + + /* get stored data */ + svtmp = hv_fetch(L2HV, data_name, strlen(data_name), 0); + if (svtmp == NULL) return &PL_sv_undef; + if (!SvOK(*svtmp)) return &PL_sv_undef; + + return *svtmp; +} + +int cb_data_advanced_drop(void *ptr) +{ + int len; + char key_name[500]; + dMY_CXT; + + len = my_snprintf(key_name, sizeof(key_name), "ptr_%p", ptr); + if (len == sizeof(key_name)) return 0; /* error - key_name too short*/ + + hv_delete(MY_CXT.global_cb_data, key_name, strlen(key_name), G_DISCARD); + return 1; +} + +/* ============= callback stuff - invoke functions ============== */ + +static int ssleay_verify_callback_invoke (int ok, X509_STORE_CTX* x509_store) +{ + dSP; + SSL* ssl; + int count = -1, res; + SV *cb_func; + + PR1("STARTED: ssleay_verify_callback_invoke\n"); + ssl = X509_STORE_CTX_get_ex_data(x509_store, SSL_get_ex_data_X509_STORE_CTX_idx()); + cb_func = cb_data_advanced_get(ssl, "ssleay_verify_callback!!func"); + + if (!SvOK(cb_func)) { + SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl); + cb_func = cb_data_advanced_get(ssl_ctx, "ssleay_verify_callback!!func"); + } + + if (!SvOK(cb_func)) + croak("Net::SSLeay: verify_callback called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PR2("verify callback glue ok=%d\n", ok); + + PUSHMARK(sp); + EXTEND( sp, 2 ); + PUSHs( sv_2mortal(newSViv(ok)) ); + PUSHs( sv_2mortal(newSViv(PTR2IV(x509_store))) ); + PUTBACK; + + PR1("About to call verify callback.\n"); + count = call_sv(cb_func, G_SCALAR); + PR1("Returned from verify callback.\n"); + + SPAGAIN; + + if (count != 1) + croak ( "Net::SSLeay: verify_callback perl function did not return a scalar.\n"); + + res = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return res; +} + +static int ssleay_ctx_passwd_cb_invoke(char *buf, int size, int rwflag, void *userdata) +{ + dSP; + int count = -1; + char *res; + SV *cb_func, *cb_data; + + PR1("STARTED: ssleay_ctx_passwd_cb_invoke\n"); + cb_func = cb_data_advanced_get(userdata, "ssleay_ctx_passwd_cb!!func"); + cb_data = cb_data_advanced_get(userdata, "ssleay_ctx_passwd_cb!!data"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ctx_passwd_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(sp); + XPUSHs(sv_2mortal(newSViv(rwflag))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + count = call_sv( cb_func, G_SCALAR ); + + SPAGAIN; + + if (count != 1) + croak("Net::SSLeay: ssleay_ctx_passwd_cb_invoke perl function did not return a scalar.\n"); + + res = POPp; + + if (res == NULL) { + *buf = '\0'; + } else { + strncpy(buf, res, size); + buf[size - 1] = '\0'; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return strlen(buf); +} + +#if OPENSSL_VERSION_NUMBER >= 0x1010006fL /* In OpenSSL 1.1.0 but actually called for $ssl from 1.1.0f */ +#ifndef LIBRESSL_VERSION_NUMBER +#ifndef OPENSSL_IS_BORINGSSL +static int ssleay_ssl_passwd_cb_invoke(char *buf, int size, int rwflag, void *userdata) +{ + dSP; + int count = -1; + char *res; + SV *cb_func, *cb_data; + + PR1("STARTED: ssleay_ssl_passwd_cb_invoke\n"); + cb_func = cb_data_advanced_get(userdata, "ssleay_ssl_passwd_cb!!func"); + cb_data = cb_data_advanced_get(userdata, "ssleay_ssl_passwd_cb!!data"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ssl_passwd_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(sp); + XPUSHs(sv_2mortal(newSViv(rwflag))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + count = call_sv( cb_func, G_SCALAR ); + + SPAGAIN; + + if (count != 1) + croak("Net::SSLeay: ssleay_ssl_passwd_cb_invoke perl function did not return a scalar.\n"); + + res = POPp; + + if (res == NULL) { + *buf = '\0'; + } else { + strncpy(buf, res, size); + buf[size - 1] = '\0'; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return strlen(buf); +} +#endif /* !BoringSSL */ +#endif /* !LibreSSL */ +#endif /* >= 1.1.0f */ + +int ssleay_ctx_cert_verify_cb_invoke(X509_STORE_CTX* x509_store_ctx, void* data) +{ + dSP; + int count = -1; + int res; + SV * cb_func, *cb_data; + void *ptr; + SSL *ssl; + + PR1("STARTED: ssleay_ctx_cert_verify_cb_invoke\n"); +#if OPENSSL_VERSION_NUMBER < 0x0090700fL + ssl = X509_STORE_CTX_get_ex_data(x509_store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + ptr = (void*) SSL_get_SSL_CTX(ssl); +#else + ssl = NULL; + ptr = (void*) data; +#endif + + cb_func = cb_data_advanced_get(ptr, "ssleay_ctx_cert_verify_cb!!func"); + cb_data = cb_data_advanced_get(ptr, "ssleay_ctx_cert_verify_cb!!data"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ctx_cert_verify_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(x509_store_ctx)))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + count = call_sv(cb_func, G_SCALAR); + + SPAGAIN; + + if (count != 1) + croak("Net::SSLeay: ssleay_ctx_cert_verify_cb_invoke perl function did not return a scalar.\n"); + + res = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return res; +} + +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) + +int tlsext_servername_callback_invoke(SSL *ssl, int *ad, void *arg) +{ + dSP; + int count = -1; + int res; + SV * cb_func, *cb_data; + + PR1("STARTED: tlsext_servername_callback_invoke\n"); + + cb_func = cb_data_advanced_get(arg, "tlsext_servername_callback!!func"); + cb_data = cb_data_advanced_get(arg, "tlsext_servername_callback!!data"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: tlsext_servername_callback_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + count = call_sv(cb_func, G_SCALAR); + + SPAGAIN; + + if (count != 1) + croak("Net::SSLeay: tlsext_servername_callback_invoke perl function did not return a scalar.\n"); + + res = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return res; +} + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_TLSEXT) + +int tlsext_status_cb_invoke(SSL *ssl, void *arg) +{ + dSP; + SV *cb_func, *cb_data; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + int len,res,nres = -1; + const unsigned char *p = NULL; + OCSP_RESPONSE *ocsp_response = NULL; + + cb_func = cb_data_advanced_get(ctx, "tlsext_status_cb!!func"); + cb_data = cb_data_advanced_get(ctx, "tlsext_status_cb!!data"); + + if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV)) + croak ("Net::SSLeay: tlsext_status_cb_invoke called, but not set to point to any perl function.\n"); + + len = SSL_get_tlsext_status_ocsp_resp(ssl, &p); + if (p) ocsp_response = d2i_OCSP_RESPONSE(NULL, &p, len); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + PUSHs( sv_2mortal(newSViv(PTR2IV(ocsp_response))) ); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + nres = call_sv(cb_func, G_SCALAR); + if (ocsp_response) OCSP_RESPONSE_free(ocsp_response); + + SPAGAIN; + + if (nres != 1) + croak("Net::SSLeay: tlsext_status_cb_invoke perl function did not return a scalar.\n"); + + res = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return res; +} + +int session_ticket_ext_cb_invoke(SSL *ssl, const unsigned char *data, int len, void *arg) +{ + dSP; + SV *cb_func, *cb_data; + int res,nres = -1; + + cb_func = cb_data_advanced_get(arg, "session_ticket_ext_cb!!func"); + cb_data = cb_data_advanced_get(arg, "session_ticket_ext_cb!!data"); + + if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV)) + croak ("Net::SSLeay: session_ticket_ext_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newSVpvn((const char *)data, len))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + nres = call_sv(cb_func, G_SCALAR); + + SPAGAIN; + + if (nres != 1) + croak("Net::SSLeay: session_ticket_ext_cb_invoke perl function did not return a scalar.\n"); + + res = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return res; +} + +#endif + +#if defined(SSL_F_SSL_SET_HELLO_EXTENSION) || defined(SSL_F_SSL_SET_SESSION_TICKET_EXT) + +int ssleay_session_secret_cb_invoke(SSL* s, void* secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + const SSL_CIPHER **cipher, void *arg) +{ + dSP; + int count = -1, res, i; + AV *ciphers = newAV(); + SV *pref_cipher = sv_newmortal(); + SV * cb_func, *cb_data; + SV * secretsv; + + PR1("STARTED: ssleay_session_secret_cb_invoke\n"); + cb_func = cb_data_advanced_get(arg, "ssleay_session_secret_cb!!func"); + cb_data = cb_data_advanced_get(arg, "ssleay_session_secret_cb!!data"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ctx_passwd_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + secretsv = sv_2mortal( newSVpv(secret, *secret_len)); + XPUSHs(secretsv); + for (i=0; i= 0x10100000L + { + /* Use any new master secret set by the callback function in secret */ + STRLEN newsecretlen; + char* newsecretdata = SvPV(secretsv, newsecretlen); + memcpy(secret, newsecretdata, newsecretlen); + } +#endif + } + + PUTBACK; + FREETMPS; + LEAVE; + + return res; +} + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L && !defined(OPENSSL_NO_PSK) +#define NET_SSLEAY_CAN_PSK_CLIENT_CALLBACK + +unsigned int ssleay_set_psk_client_callback_invoke(SSL *ssl, const char *hint, + char *identity, unsigned int max_identity_len, + unsigned char *psk, unsigned int max_psk_len) +{ + dSP; + int count = -1; + char *identity_val, *psk_val; + unsigned int psk_len = 0; + BIGNUM *psk_bn = NULL; + SV * cb_func; + SV * hintsv; + /* this n_a is required for building with old perls: */ + STRLEN n_a; + + PR1("STARTED: ssleay_set_psk_client_callback_invoke\n"); + cb_func = cb_data_advanced_get(ssl, "ssleay_set_psk_client_callback!!func"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_set_psk_client_callback_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + if (hint != NULL) { + hintsv = sv_2mortal( newSVpv(hint, strlen(hint))); + XPUSHs(hintsv); + } + + PUTBACK; + + count = call_sv( cb_func, G_ARRAY ); + + SPAGAIN; + + if (count != 2) + croak ("Net::SSLeay: ssleay_set_psk_client_callback_invoke perl function did not return 2 values.\n"); + + psk_val = POPpx; + identity_val = POPpx; + + my_snprintf(identity, max_identity_len, "%s", identity_val); + + if (BN_hex2bn(&psk_bn, psk_val) > 0) { + if (BN_num_bytes(psk_bn) <= max_psk_len) { + psk_len = BN_bn2bin(psk_bn, psk); + } + BN_free(psk_bn); + } + + PUTBACK; + FREETMPS; + LEAVE; + + return psk_len; +} + +unsigned int ssleay_ctx_set_psk_client_callback_invoke(SSL *ssl, const char *hint, + char *identity, unsigned int max_identity_len, + unsigned char *psk, unsigned int max_psk_len) +{ + dSP; + SSL_CTX *ctx; + int count = -1; + char *identity_val, *psk_val; + unsigned int psk_len = 0; + BIGNUM *psk_bn = NULL; + SV * cb_func; + SV * hintsv; + /* this n_a is required for building with old perls: */ + STRLEN n_a; + + ctx = SSL_get_SSL_CTX(ssl); + + PR1("STARTED: ssleay_ctx_set_psk_client_callback_invoke\n"); + cb_func = cb_data_advanced_get(ctx, "ssleay_ctx_set_psk_client_callback!!func"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ctx_set_psk_client_callback_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + if (hint != NULL) { + hintsv = sv_2mortal( newSVpv(hint, strlen(hint))); + XPUSHs(hintsv); + } + + PUTBACK; + + count = call_sv( cb_func, G_ARRAY ); + + SPAGAIN; + + if (count != 2) + croak ("Net::SSLeay: ssleay_ctx_set_psk_client_callback_invoke perl function did not return 2 values.\n"); + + psk_val = POPpx; + identity_val = POPpx; + + my_snprintf(identity, max_identity_len, "%s", identity_val); + + if (BN_hex2bn(&psk_bn, psk_val) > 0) { + if (BN_num_bytes(psk_bn) <= max_psk_len) { + psk_len = BN_bn2bin(psk_bn, psk); + } + BN_free(psk_bn); + } + + PUTBACK; + FREETMPS; + LEAVE; + + return psk_len; +} + +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG)) || (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT)) + +int next_proto_helper_AV2protodata(AV * list, unsigned char *out) +{ + int i, last_index, ptr = 0; + last_index = av_len(list); + if (last_index<0) return 0; + for(i=0; i<=last_index; i++) { + char *p = SvPV_nolen(*av_fetch(list, i, 0)); + size_t len = strlen(p); + if (len>255) return 0; + if (out) { + /* if out == NULL we only calculate the length of output */ + out[ptr] = (unsigned char)len; + strncpy((char*)out+ptr+1, p, len); + } + ptr += strlen(p) + 1; + } + return ptr; +} + +int next_proto_helper_protodata2AV(AV * list, const unsigned char *in, unsigned int inlen) +{ + unsigned int i = 0; + unsigned char il; + if (!list || inlen<2) return 0; + while (i inlen) return 0; + av_push(list, newSVpv((const char*)in+i, il)); + i += il; + } + return 1; +} + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(LIBRESSL_VERSION_NUMBER) + +int next_proto_select_cb_invoke(SSL *ssl, unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + SV *cb_func, *cb_data; + unsigned char *next_proto_data; + size_t next_proto_len; + int next_proto_status; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + /* this n_a is required for building with old perls: */ + STRLEN n_a; + + PR1("STARTED: next_proto_select_cb_invoke\n"); + cb_func = cb_data_advanced_get(ctx, "next_proto_select_cb!!func"); + cb_data = cb_data_advanced_get(ctx, "next_proto_select_cb!!data"); + /* clear last_status value = store undef */ + cb_data_advanced_put(ssl, "next_proto_select_cb!!last_status", NULL); + cb_data_advanced_put(ssl, "next_proto_select_cb!!last_negotiated", NULL); + + if (SvROK(cb_func) && (SvTYPE(SvRV(cb_func)) == SVt_PVCV)) { + int count = -1; + AV *list = newAV(); + SV *tmpsv; + dSP; + + if (!next_proto_helper_protodata2AV(list, in, inlen)) return SSL_TLSEXT_ERR_ALERT_FATAL; + + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newRV_inc((SV*)list))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + count = call_sv( cb_func, G_ARRAY ); + SPAGAIN; + if (count != 2) + croak ("Net::SSLeay: next_proto_select_cb_invoke perl function did not return 2 values.\n"); + next_proto_data = (unsigned char*)POPpx; + next_proto_status = POPi; + + next_proto_len = strlen((const char*)next_proto_data); + if (next_proto_len<=255) { + /* store last_status + last_negotiated into global hash */ + cb_data_advanced_put(ssl, "next_proto_select_cb!!last_status", newSViv(next_proto_status)); + tmpsv = newSVpv((const char*)next_proto_data, next_proto_len); + cb_data_advanced_put(ssl, "next_proto_select_cb!!last_negotiated", tmpsv); + *out = (unsigned char *)SvPVX(tmpsv); + *outlen = next_proto_len; + } + + PUTBACK; + FREETMPS; + LEAVE; + + return next_proto_len>255 ? SSL_TLSEXT_ERR_ALERT_FATAL : SSL_TLSEXT_ERR_OK; + } + else if (SvROK(cb_data) && (SvTYPE(SvRV(cb_data)) == SVt_PVAV)) { + next_proto_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), NULL); + Newx(next_proto_data, next_proto_len, unsigned char); + if (!next_proto_data) return SSL_TLSEXT_ERR_ALERT_FATAL; + next_proto_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), next_proto_data); + + next_proto_status = SSL_select_next_proto(out, outlen, in, inlen, next_proto_data, next_proto_len); + + /* store last_status + last_negotiated into global hash */ + cb_data_advanced_put(ssl, "next_proto_select_cb!!last_status", newSViv(next_proto_status)); + cb_data_advanced_put(ssl, "next_proto_select_cb!!last_negotiated", newSVpv((const char*)*out, *outlen)); + Safefree(next_proto_data); + return SSL_TLSEXT_ERR_OK; + } + return SSL_TLSEXT_ERR_ALERT_FATAL; +} + +int next_protos_advertised_cb_invoke(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg_unused) +{ + SV *cb_func, *cb_data; + unsigned char *protodata = NULL; + unsigned short protodata_len = 0; + SV *tmpsv; + AV *tmpav; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + PR1("STARTED: next_protos_advertised_cb_invoke"); + cb_func = cb_data_advanced_get(ctx, "next_protos_advertised_cb!!func"); + cb_data = cb_data_advanced_get(ctx, "next_protos_advertised_cb!!data"); + + if (SvROK(cb_func) && (SvTYPE(SvRV(cb_func)) == SVt_PVCV)) { + int count = -1; + dSP; + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + count = call_sv( cb_func, G_SCALAR ); + SPAGAIN; + if (count != 1) + croak ("Net::SSLeay: next_protos_advertised_cb_invoke perl function did not return scalar value.\n"); + tmpsv = POPs; + if (SvOK(tmpsv) && SvROK(tmpsv) && (SvTYPE(SvRV(tmpsv)) == SVt_PVAV)) { + tmpav = (AV*)SvRV(tmpsv); + protodata_len = next_proto_helper_AV2protodata(tmpav, NULL); + Newx(protodata, protodata_len, unsigned char); + if (protodata) next_proto_helper_AV2protodata(tmpav, protodata); + } + PUTBACK; + FREETMPS; + LEAVE; + } + else if (SvROK(cb_data) && (SvTYPE(SvRV(cb_data)) == SVt_PVAV)) { + tmpav = (AV*)SvRV(cb_data); + protodata_len = next_proto_helper_AV2protodata(tmpav, NULL); + Newx(protodata, protodata_len, unsigned char); + if (protodata) next_proto_helper_AV2protodata(tmpav, protodata); + } + if (protodata) { + tmpsv = newSVpv((const char*)protodata, protodata_len); + Safefree(protodata); + cb_data_advanced_put(ssl, "next_protos_advertised_cb!!last_advertised", tmpsv); + *out = (unsigned char *)SvPVX(tmpsv); + *outlen = protodata_len; + return SSL_TLSEXT_ERR_OK; + } + return SSL_TLSEXT_ERR_ALERT_FATAL; +} + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT) + +int alpn_select_cb_invoke(SSL *ssl, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + SV *cb_func, *cb_data; + unsigned char *alpn_data; + size_t alpn_len; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + PR1("STARTED: alpn_select_cb_invoke\n"); + cb_func = cb_data_advanced_get(ctx, "alpn_select_cb!!func"); + cb_data = cb_data_advanced_get(ctx, "alpn_select_cb!!data"); + + if (SvROK(cb_func) && (SvTYPE(SvRV(cb_func)) == SVt_PVCV)) { + int count = -1; + AV *list = newAV(); + SV *tmpsv; + SV *alpn_data_sv; + dSP; + + if (!next_proto_helper_protodata2AV(list, in, inlen)) return SSL_TLSEXT_ERR_ALERT_FATAL; + + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newRV_inc((SV*)list))); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + count = call_sv( cb_func, G_ARRAY ); + SPAGAIN; + if (count != 1) + croak ("Net::SSLeay: alpn_select_cb perl function did not return exactly 1 value.\n"); + alpn_data_sv = POPs; + if (SvOK(alpn_data_sv)) { + alpn_data = (unsigned char*)SvPV_nolen(alpn_data_sv); + alpn_len = strlen((const char*)alpn_data); + if (alpn_len <= 255) { + tmpsv = newSVpv((const char*)alpn_data, alpn_len); + *out = (unsigned char *)SvPVX(tmpsv); + *outlen = alpn_len; + } + } else { + alpn_data = NULL; + alpn_len = 0; + } + PUTBACK; + FREETMPS; + LEAVE; + + if (alpn_len>255) return SSL_TLSEXT_ERR_ALERT_FATAL; + return alpn_data ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK; + } + else if (SvROK(cb_data) && (SvTYPE(SvRV(cb_data)) == SVt_PVAV)) { + int status; + + alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), NULL); + Newx(alpn_data, alpn_len, unsigned char); + if (!alpn_data) return SSL_TLSEXT_ERR_ALERT_FATAL; + alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(cb_data), alpn_data); + + /* This is the same function that is used for NPN. */ + status = SSL_select_next_proto((unsigned char **)out, outlen, in, inlen, alpn_data, alpn_len); + Safefree(alpn_data); + return status == OPENSSL_NPN_NEGOTIATED ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK; + } + return SSL_TLSEXT_ERR_ALERT_FATAL; +} + +#endif + +int pem_password_cb_invoke(char *buf, int bufsize, int rwflag, void *data) { + dSP; + char *str; + int count = -1; + size_t str_len = 0; + simple_cb_data_t* cb = (simple_cb_data_t*)data; + /* this n_a is required for building with old perls: */ + STRLEN n_a; + + PR1("STARTED: pem_password_cb_invoke\n"); + if (cb->func && SvOK(cb->func)) { + ENTER; + SAVETMPS; + + PUSHMARK(sp); + + XPUSHs(sv_2mortal( newSViv(bufsize-1) )); + XPUSHs(sv_2mortal( newSViv(rwflag) )); + if (cb->data) XPUSHs( cb->data ); + + PUTBACK; + + count = call_sv( cb->func, G_SCALAR ); + + SPAGAIN; + + buf[0] = 0; /* start with an empty password */ + if (count != 1) { + croak("Net::SSLeay: pem_password_cb_invoke perl function did not return a scalar.\n"); + } + else { + str = POPpx; + str_len = strlen(str); + if (str_len+1 < bufsize) { + strcpy(buf, str); + } + else { + str_len = 0; + warn("Net::SSLeay: pem_password_cb_invoke password too long\n"); + } + } + + PUTBACK; + FREETMPS; + LEAVE; + } + return str_len; +} + +void ssleay_RSA_generate_key_cb_invoke(int i, int n, void* data) +{ + dSP; + int count = -1; + simple_cb_data_t* cb = (simple_cb_data_t*)data; + + /* PR1("STARTED: ssleay_RSA_generate_key_cb_invoke\n"); / * too noisy */ + if (cb->func && SvOK(cb->func)) { + ENTER; + SAVETMPS; + + PUSHMARK(sp); + + XPUSHs(sv_2mortal( newSViv(i) )); + XPUSHs(sv_2mortal( newSViv(n) )); + if (cb->data) XPUSHs( cb->data ); + + PUTBACK; + + count = call_sv( cb->func, G_VOID|G_DISCARD ); + + if (count != 0) + croak ("Net::SSLeay: ssleay_RSA_generate_key_cb_invoke " + "perl function did return something in void context.\n"); + + SPAGAIN; + FREETMPS; + LEAVE; + } +} + +void ssleay_info_cb_invoke(const SSL *ssl, int where, int ret) +{ + dSP; + SV *cb_func, *cb_data; + + cb_func = cb_data_advanced_get((void*)ssl, "ssleay_info_cb!!func"); + cb_data = cb_data_advanced_get((void*)ssl, "ssleay_info_cb!!data"); + + if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV)) + croak ("Net::SSLeay: ssleay_info_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newSViv(where)) ); + XPUSHs(sv_2mortal(newSViv(ret)) ); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + call_sv(cb_func, G_VOID); + + SPAGAIN; + PUTBACK; + FREETMPS; + LEAVE; +} + +void ssleay_ctx_info_cb_invoke(const SSL *ssl, int where, int ret) +{ + dSP; + SV *cb_func, *cb_data; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + cb_func = cb_data_advanced_get(ctx, "ssleay_ctx_info_cb!!func"); + cb_data = cb_data_advanced_get(ctx, "ssleay_ctx_info_cb!!data"); + + if ( ! SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV)) + croak ("Net::SSLeay: ssleay_ctx_info_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newSViv(where)) ); + XPUSHs(sv_2mortal(newSViv(ret)) ); + XPUSHs(sv_2mortal(newSVsv(cb_data))); + PUTBACK; + + call_sv(cb_func, G_VOID); + + SPAGAIN; + PUTBACK; + FREETMPS; + LEAVE; +} + +/* + * Support for tlsext_ticket_key_cb_invoke was already in 0.9.8 but it was + * broken in various ways during the various 1.0.0* versions. + * Better enable it only starting with 1.0.1. +*/ +#if defined(SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB) && OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_TLSEXT) +#define NET_SSLEAY_CAN_TICKET_KEY_CB + +int tlsext_ticket_key_cb_invoke( + SSL *ssl, + unsigned char *key_name, + unsigned char *iv, + EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, + int enc +){ + + dSP; + int count,usable_rv_count,hmac_key_len = 0; + SV *cb_func, *cb_data; + STRLEN svlen; + unsigned char key[48]; /* key[0..15] aes, key[16..32] or key[16..48] hmac */ + unsigned char name[16]; + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); + + PR1("STARTED: tlsext_ticket_key_cb_invoke\n"); + cb_func = cb_data_advanced_get(ctx, "tlsext_ticket_key_cb!!func"); + cb_data = cb_data_advanced_get(ctx, "tlsext_ticket_key_cb!!data"); + + if (!SvROK(cb_func) || (SvTYPE(SvRV(cb_func)) != SVt_PVCV)) + croak("callback must be a code reference"); + + ENTER; + SAVETMPS; + PUSHMARK(SP); + + XPUSHs(sv_2mortal(newSVsv(cb_data))); + + if (!enc) { + /* call as getkey(data,this_name) -> (key,current_name) */ + XPUSHs(sv_2mortal(newSVpv((const char *)key_name,16))); + } else { + /* call as getkey(data) -> (key,current_name) */ + } + + PUTBACK; + + count = call_sv( cb_func, G_ARRAY ); + + SPAGAIN; + + if (count>2) + croak("too much return values - only (name,key) should be returned"); + + usable_rv_count = 0; + if (count>0) { + SV *sname = POPs; + if (SvOK(sname)) { + unsigned char *pname = (unsigned char *)SvPV(sname,svlen); + if (svlen > 16) + croak("name must be at at most 16 bytes, got %d",(int)svlen); + if (svlen == 0) + croak("name should not be empty"); + OPENSSL_cleanse(name, 16); + memcpy(name,pname,svlen); + usable_rv_count++; + } + } + if (count>1) { + SV *skey = POPs; + if (SvOK(skey)) { + unsigned char *pkey = (unsigned char *)SvPV(skey,svlen); + if (svlen != 32 && svlen != 48) + croak("key must be 32 or 48 random bytes, got %d",(int)svlen); + hmac_key_len = (int)svlen - 16; + memcpy(key,pkey,(int)svlen); + usable_rv_count++; + } + } + + PUTBACK; + FREETMPS; + LEAVE; + + if (!enc && usable_rv_count == 0) { + TRACE(2,"no key returned for ticket"); + return 0; + } + if (usable_rv_count != 2) + croak("key functions needs to return (key,name)"); + + if (enc) { + /* encrypt ticket information with given key */ + RAND_bytes(iv, 16); + EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key, iv); + HMAC_Init_ex(hctx,key+16,hmac_key_len,EVP_sha256(),NULL); + memcpy(key_name,name,16); + return 1; + + } else { + HMAC_Init_ex(hctx,key+16,hmac_key_len,EVP_sha256(),NULL); + EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key, iv); + + if (memcmp(name,key_name,16) == 0) + return 1; /* current key was used */ + else + return 2; /* different key was used, need to be renewed */ + } +} + +#endif + +int ssleay_ssl_ctx_sess_new_cb_invoke(struct ssl_st *ssl, SSL_SESSION *sess) +{ + dSP; + int count, remove; + SSL_CTX *ctx; + SV *cb_func; + + PR1("STARTED: ssleay_ssl_ctx_sess_new_cb_invoke\n"); + ctx = SSL_get_SSL_CTX(ssl); + cb_func = cb_data_advanced_get(ctx, "ssleay_ssl_ctx_sess_new_cb!!func"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ssl_ctx_sess_new_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(sp); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl)))); + XPUSHs(sv_2mortal(newSViv(PTR2IV(sess)))); + PUTBACK; + + count = call_sv(cb_func, G_SCALAR); + + SPAGAIN; + + if (count != 1) + croak("Net::SSLeay: ssleay_ssl_ctx_sess_new_cb_invoke perl function did not return a scalar\n"); + + remove = POPi; + + PUTBACK; + FREETMPS; + LEAVE; + + return remove; +} + +void ssleay_ssl_ctx_sess_remove_cb_invoke(SSL_CTX *ctx, SSL_SESSION *sess) +{ + dSP; + SV *cb_func; + + PR1("STARTED: ssleay_ssl_ctx_sess_remove_cb_invoke\n"); + cb_func = cb_data_advanced_get(ctx, "ssleay_ssl_ctx_sess_remove_cb!!func"); + + if(!SvOK(cb_func)) + croak ("Net::SSLeay: ssleay_ssl_ctx_sess_remove_cb_invoke called, but not set to point to any perl function.\n"); + + ENTER; + SAVETMPS; + + PUSHMARK(sp); + XPUSHs(sv_2mortal(newSViv(PTR2IV(ctx)))); + XPUSHs(sv_2mortal(newSViv(PTR2IV(sess)))); + PUTBACK; + + call_sv(cb_func, G_VOID); + + SPAGAIN; + + PUTBACK; + FREETMPS; + LEAVE; +} + +/* ============= end of callback stuff, begin helper functions ============== */ + +time_t ASN1_TIME_timet(ASN1_TIME *asn1t) { + struct tm t; + const char *p = (const char*) asn1t->data; + size_t msec = 0, tz = 0, i, l; + time_t result; + int adj = 0; + + if (asn1t->type == V_ASN1_UTCTIME) { + if (asn1t->length<12 || asn1t->length>17) return 0; + if (asn1t->length>12) tz = 12; + } else { + if (asn1t->length<14) return 0; + if (asn1t->length>14) { + if (p[14] == '.') { + msec = 14; + for(i=msec+1;ilength && p[i]>='0' && p[i]<='9';i++) ; + if (ilength) tz = i; + } else { + tz = 14; + } + } + } + + l = msec ? msec : tz ? tz : asn1t->length; + for(i=0;i'9') return 0; + } + + /* extract data and time */ + OPENSSL_cleanse(&t, sizeof(t)); + if (asn1t->type == V_ASN1_UTCTIME) { /* YY - two digit year */ + t.tm_year = (p[0]-'0')*10 + (p[1]-'0'); + if (t.tm_year < 70) t.tm_year += 100; + i=2; + } else { /* YYYY */ + t.tm_year = (p[0]-'0')*1000 + (p[1]-'0')*100 + (p[2]-'0')*10 + p[3]-'0'; + t.tm_year -= 1900; + i=4; + } + t.tm_mon = (p[i+0]-'0')*10 + (p[i+1]-'0') -1; /* MM, starts with 0 in tm */ + t.tm_mday = (p[i+2]-'0')*10 + (p[i+3]-'0'); /* DD */ + t.tm_hour = (p[i+4]-'0')*10 + (p[i+5]-'0'); /* hh */ + t.tm_min = (p[i+6]-'0')*10 + (p[i+7]-'0'); /* mm */ + t.tm_sec = (p[i+8]-'0')*10 + (p[i+9]-'0'); /* ss */ + + /* skip msec, because time_t does not support it */ + + if (tz) { + /* TZ is 'Z' or [+-]DDDD and after TZ the string must stop*/ + if (p[tz] == 'Z') { + if (asn1t->length>tz+1 ) return 0; + } else if (asn1t->lengthlength>tz+5 ) return 0; + for(i=tz+1;i'9') return 0; + } + adj = ((p[tz+1]-'0')*10 + (p[tz+2]-'0'))*3600 + + ((p[tz+3]-'0')*10 + (p[tz+4]-'0'))*60; + if (p[tz]=='+') adj*= -1; /* +0500: subtract 5 hours to get UTC */ + } + } + + result = mktime(&t); + if (result == -1) return 0; /* broken time */ + return result + adj + ( t.tm_isdst ? 3600:0 ); +} + +X509 * find_issuer(X509 *cert,X509_STORE *store, STACK_OF(X509) *chain) { + int i; + X509 *issuer = NULL; + + /* search first in the chain */ + if (chain) { + for(i=0;i= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) + +unsigned long +OpenSSL_version_num() + +const char * +OpenSSL_version(t=OPENSSL_VERSION) + int t + +#endif /* OpenSSL 1.1.0 */ + + +#define REM1 "============= SSL CONTEXT functions ==============" + +SSL_CTX * +SSL_CTX_new() + CODE: + RETVAL = SSL_CTX_new (SSLv23_method()); + OUTPUT: + RETVAL + + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#ifndef OPENSSL_NO_SSL2 + +SSL_CTX * +SSL_CTX_v2_new() + CODE: + RETVAL = SSL_CTX_new (SSLv2_method()); + OUTPUT: + RETVAL + +#endif +#endif +#ifndef OPENSSL_NO_SSL3 + +SSL_CTX * +SSL_CTX_v3_new() + CODE: + RETVAL = SSL_CTX_new (SSLv3_method()); + OUTPUT: + RETVAL + +#endif + +SSL_CTX * +SSL_CTX_v23_new() + CODE: + RETVAL = SSL_CTX_new (SSLv23_method()); + OUTPUT: + RETVAL + +SSL_CTX * +SSL_CTX_tlsv1_new() + CODE: + RETVAL = SSL_CTX_new (TLSv1_method()); + OUTPUT: + RETVAL + +#ifdef SSL_TXT_TLSV1_1 + +SSL_CTX * +SSL_CTX_tlsv1_1_new() + CODE: + RETVAL = SSL_CTX_new (TLSv1_1_method()); + OUTPUT: + RETVAL + +#endif + +#ifdef SSL_TXT_TLSV1_2 + +SSL_CTX * +SSL_CTX_tlsv1_2_new() + CODE: + RETVAL = SSL_CTX_new (TLSv1_2_method()); + OUTPUT: + RETVAL + +#endif + +SSL_CTX * +SSL_CTX_new_with_method(meth) + SSL_METHOD * meth + CODE: + RETVAL = SSL_CTX_new (meth); + OUTPUT: + RETVAL + +void +SSL_CTX_free(ctx) + SSL_CTX * ctx + CODE: + cb_data_advanced_drop(ctx); /* clean callback related data from global hash */ + SSL_CTX_free(ctx); + +int +SSL_CTX_add_session(ctx,ses) + SSL_CTX * ctx + SSL_SESSION * ses + +int +SSL_CTX_remove_session(ctx,ses) + SSL_CTX * ctx + SSL_SESSION * ses + +void +SSL_CTX_flush_sessions(ctx,tm) + SSL_CTX * ctx + long tm + +int +SSL_CTX_set_default_verify_paths(ctx) + SSL_CTX * ctx + +int +SSL_CTX_load_verify_locations(ctx,CAfile,CApath) + SSL_CTX * ctx + char * CAfile + char * CApath + CODE: + RETVAL = SSL_CTX_load_verify_locations (ctx, + CAfile?(*CAfile?CAfile:NULL):NULL, + CApath?(*CApath?CApath:NULL):NULL + ); + OUTPUT: + RETVAL + +void +SSL_CTX_set_verify(ctx,mode,callback=&PL_sv_undef) + SSL_CTX * ctx + int mode + SV * callback + CODE: + + /* Former versions of SSLeay checked if the callback was a true boolean value + * and didn't call it if it was false. Therefor some people set the callback + * to '0' if they don't want to use it (IO::Socket::SSL for example). Therefor + * we don't execute the callback if it's value isn't something true to retain + * backwards compatibility. + */ + + if (callback==NULL || !SvOK(callback) || !SvTRUE(callback)) { + SSL_CTX_set_verify(ctx, mode, NULL); + cb_data_advanced_put(ctx, "ssleay_verify_callback!!func", NULL); + } else { + cb_data_advanced_put(ctx, "ssleay_verify_callback!!func", newSVsv(callback)); + SSL_CTX_set_verify(ctx, mode, &ssleay_verify_callback_invoke); + } + +#if OPENSSL_VERSION_NUMBER >= 0x10100001L && !defined(LIBRESSL_VERSION_NUMBER) + +void +SSL_CTX_set_security_level(SSL_CTX * ctx, int level) + +int +SSL_CTX_get_security_level(SSL_CTX * ctx) + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10101007L && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets) + +size_t +SSL_CTX_get_num_tickets(SSL_CTX *ctx) + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10101003L && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.1 */ + +void +SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val) + +#endif + +void +SSL_CTX_sess_set_new_cb(ctx, callback) + SSL_CTX * ctx + SV * callback + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_sess_set_new_cb(ctx, NULL); + cb_data_advanced_put(ctx, "ssleay_ssl_ctx_sess_new_cb!!func", NULL); + } + else { + cb_data_advanced_put(ctx, "ssleay_ssl_ctx_sess_new_cb!!func", newSVsv(callback)); + SSL_CTX_sess_set_new_cb(ctx, &ssleay_ssl_ctx_sess_new_cb_invoke); + } + +void +SSL_CTX_sess_set_remove_cb(ctx, callback) + SSL_CTX * ctx + SV * callback + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_sess_set_remove_cb(ctx, NULL); + cb_data_advanced_put(ctx, "ssleay_ssl_ctx_sess_remove_cb!!func", NULL); + } + else { + cb_data_advanced_put(ctx, "ssleay_ssl_ctx_sess_remove_cb!!func", newSVsv(callback)); + SSL_CTX_sess_set_remove_cb(ctx, &ssleay_ssl_ctx_sess_remove_cb_invoke); + } + +int +SSL_get_error(s,ret) + SSL * s + int ret + +#define REM10 "============= SSL functions ==============" + +SSL * +SSL_new(ctx) + SSL_CTX * ctx + +void +SSL_free(s) + SSL * s + CODE: + cb_data_advanced_drop(s); /* clean callback related data from global hash */ + SSL_free(s); + +#if 0 /* this seems to be gone in 0.9.0 */ +void +SSL_debug(file) + char * file + +#endif + +int +SSL_accept(s) + SSL * s + +void +SSL_clear(s) + SSL * s + +int +SSL_connect(s) + SSL * s + + +#if defined(WIN32) + +int +SSL_set_fd(s,fd) + SSL * s + perl_filehandle_t fd + CODE: + RETVAL = SSL_set_fd(s,_get_osfhandle(fd)); + OUTPUT: + RETVAL + +int +SSL_set_rfd(s,fd) + SSL * s + perl_filehandle_t fd + CODE: + RETVAL = SSL_set_rfd(s,_get_osfhandle(fd)); + OUTPUT: + RETVAL + +int +SSL_set_wfd(s,fd) + SSL * s + perl_filehandle_t fd + CODE: + RETVAL = SSL_set_wfd(s,_get_osfhandle(fd)); + OUTPUT: + RETVAL + +#else + +int +SSL_set_fd(s,fd) + SSL * s + perl_filehandle_t fd + +int +SSL_set_rfd(s,fd) + SSL * s + perl_filehandle_t fd + +int +SSL_set_wfd(s,fd) + SSL * s + perl_filehandle_t fd + +#endif + +int +SSL_get_fd(s) + SSL * s + +void +SSL_read(s,max=32768) + SSL * s + int max + PREINIT: + char *buf; + int got; + int succeeded = 1; + PPCODE: + New(0, buf, max, char); + + got = SSL_read(s, buf, max); + if (got <= 0 && SSL_ERROR_ZERO_RETURN != SSL_get_error(s, got)) + succeeded = 0; + + /* If in list context, return 2-item list: + * first return value: data gotten, or undef on error (got<0) + * second return value: result from SSL_read() + */ + if (GIMME_V==G_ARRAY) { + EXTEND(SP, 2); + PUSHs(sv_2mortal(succeeded ? newSVpvn(buf, got) : newSV(0))); + PUSHs(sv_2mortal(newSViv(got))); + + /* If in scalar or void context, return data gotten, or undef on error. */ + } else { + EXTEND(SP, 1); + PUSHs(sv_2mortal(succeeded ? newSVpvn(buf, got) : newSV(0))); + } + + Safefree(buf); + +void +SSL_peek(s,max=32768) + SSL * s + int max + PREINIT: + char *buf; + int got; + int succeeded = 1; + PPCODE: + New(0, buf, max, char); + + got = SSL_peek(s, buf, max); + if (got <= 0 && SSL_ERROR_ZERO_RETURN != SSL_get_error(s, got)) + succeeded = 0; + + /* If in list context, return 2-item list: + * first return value: data gotten, or undef on error (got<0) + * second return value: result from SSL_peek() + */ + if (GIMME_V==G_ARRAY) { + EXTEND(SP, 2); + PUSHs(sv_2mortal(succeeded ? newSVpvn(buf, got) : newSV(0))); + PUSHs(sv_2mortal(newSViv(got))); + + /* If in scalar or void context, return data gotten, or undef on error. */ + } else { + EXTEND(SP, 1); + PUSHs(sv_2mortal(succeeded ? newSVpvn(buf, got) : newSV(0))); + } + Safefree(buf); + +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.1 */ + +void +SSL_read_ex(s,max=32768) + SSL * s + int max + PREINIT: + char *buf; + size_t readbytes; + int succeeded; + PPCODE: + Newx(buf, max, char); + + succeeded = SSL_read_ex(s, buf, max, &readbytes); + + /* Return 2-item list: + * first return value: data gotten, or undef on error + * second return value: result from SSL_read_ex() + */ + EXTEND(SP, 2); + PUSHs(sv_2mortal(succeeded ? newSVpvn(buf, readbytes) : newSV(0))); + PUSHs(sv_2mortal(newSViv(succeeded))); + + Safefree(buf); + + +void +SSL_peek_ex(s,max=32768) + SSL * s + int max + PREINIT: + char *buf; + size_t readbytes; + int succeeded; + PPCODE: + Newx(buf, max, char); + + succeeded = SSL_peek_ex(s, buf, max, &readbytes); + + /* Return 2-item list: + * first return value: data gotten, or undef on error + * second return value: result from SSL_peek_ex() + */ + EXTEND(SP, 2); + PUSHs(sv_2mortal(succeeded ? newSVpvn(buf, readbytes) : newSV(0))); + PUSHs(sv_2mortal(newSViv(succeeded))); + + Safefree(buf); + +void +SSL_write_ex(s,buf) + SSL * s + PREINIT: + STRLEN len; + size_t written; + int succeeded; + INPUT: + char * buf = SvPV( ST(1), len); + PPCODE: + succeeded = SSL_write_ex(s, buf, len, &written); + + /* Return 2-item list: + * first return value: data gotten, or undef on error + * second return value: result from SSL_read_ex() + */ + EXTEND(SP, 2); + PUSHs(sv_2mortal(newSVuv(written))); + PUSHs(sv_2mortal(newSViv(succeeded))); + +#endif + +int +SSL_write(s,buf) + SSL * s + PREINIT: + STRLEN len; + INPUT: + char * buf = SvPV( ST(1), len); + CODE: + RETVAL = SSL_write (s, buf, (int)len); + OUTPUT: + RETVAL + +int +SSL_write_partial(s,from,count,buf) + SSL * s + int from + int count + PREINIT: + STRLEN ulen; + IV len; + INPUT: + char * buf = SvPV( ST(3), ulen); + CODE: + /* + if (SvROK( ST(3) )) { + SV* t = SvRV( ST(3) ); + buf = SvPV( t, len); + } else + buf = SvPV( ST(3), len); + */ + PR4("write_partial from=%d count=%d len=%lu\n",from,count,ulen); + /*PR2("buf='%s'\n",&buf[from]); / * too noisy */ + len = (IV)ulen; + len -= from; + if (len < 0) { + croak("from beyound end of buffer"); + RETVAL = -1; + } else + RETVAL = SSL_write (s, &(buf[from]), (count<=len)?count:len); + OUTPUT: + RETVAL + +int +SSL_use_RSAPrivateKey(s,rsa) + SSL * s + RSA * rsa + +int +SSL_use_RSAPrivateKey_ASN1(s,d,len) + SSL * s + unsigned char * d + long len + +int +SSL_use_RSAPrivateKey_file(s,file,type) + SSL * s + char * file + int type + +int +SSL_CTX_use_RSAPrivateKey_file(ctx,file,type) + SSL_CTX * ctx + char * file + int type + +int +SSL_use_PrivateKey(s,pkey) + SSL * s + EVP_PKEY * pkey + +int +SSL_use_PrivateKey_ASN1(pk,s,d,len) + int pk + SSL * s + unsigned char * d + long len + +int +SSL_use_PrivateKey_file(s,file,type) + SSL * s + char * file + int type + +int +SSL_CTX_use_PrivateKey_file(ctx,file,type) + SSL_CTX * ctx + char * file + int type + +int +SSL_use_certificate(s,x) + SSL * s + X509 * x + +int +SSL_use_certificate_ASN1(s,d,len) + SSL * s + unsigned char * d + long len + +int +SSL_use_certificate_file(s,file,type) + SSL * s + char * file + int type + +int +SSL_CTX_use_certificate_file(ctx,file,type) + SSL_CTX * ctx + char * file + int type + +const char * +SSL_state_string(s) + SSL * s + +const char * +SSL_rstate_string(s) + SSL * s + +const char * +SSL_state_string_long(s) + SSL * s + +const char * +SSL_rstate_string_long(s) + SSL * s + + +long +SSL_get_time(ses) + SSL_SESSION * ses + +long +SSL_set_time(ses,t) + SSL_SESSION * ses + long t + +long +SSL_get_timeout(ses) + SSL_SESSION * ses + +long +SSL_set_timeout(ses,t) + SSL_SESSION * ses + long t + +void +SSL_copy_session_id(to,from) + SSL * to + SSL * from + +void +SSL_set_read_ahead(s,yes=1) + SSL * s + int yes + +int +SSL_get_read_ahead(s) + SSL * s + +int +SSL_pending(s) + SSL * s + +#if OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.0 */ + +int +SSL_has_pending(s) + SSL * s + +#endif + +int +SSL_CTX_set_cipher_list(s,str) + SSL_CTX * s + char * str + +const char * +SSL_get_cipher_list(s,n) + SSL * s + int n + +int +SSL_set_cipher_list(s,str) + SSL * s + char * str + +const char * +SSL_get_cipher(s) + SSL * s + +void +SSL_get_shared_ciphers(s,ignored_param1=0,ignored_param2=0) + SSL *s + int ignored_param1 + int ignored_param2 + PREINIT: + char buf[8192]; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + if(SSL_get_shared_ciphers(s, buf, sizeof(buf))) + sv_setpvn(ST(0), buf, strlen(buf)); + +X509 * +SSL_get_peer_certificate(s) + SSL * s + +void +SSL_get_peer_cert_chain(s) + SSL * s + PREINIT: + STACK_OF(X509) *chain = NULL; + X509 *x; + int i; + PPCODE: + chain = SSL_get_peer_cert_chain(s); + if( chain == NULL ) { + XSRETURN_EMPTY; + } + for (i=0; i= 0x10101001L && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_SESSION_is_resumable(ses) + SSL_SESSION * ses + +SSL_SESSION * +SSL_SESSION_dup(sess) + SSL_SESSION * sess + +#endif +#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(LIBRESSL_VERSION_NUMBER) /* OpenSSL 1.1.1 */ + +void +SSL_set_post_handshake_auth(SSL *ssl, int val) + +int +SSL_verify_client_post_handshake(SSL *ssl) + +#endif + +void +i2d_SSL_SESSION(sess) + SSL_SESSION * sess + PPCODE: + STRLEN len; + unsigned char *pc,*pi; + if (!(len = i2d_SSL_SESSION(sess,NULL))) croak("invalid SSL_SESSION"); + Newx(pc,len,unsigned char); + if (!pc) croak("out of memory"); + pi = pc; + i2d_SSL_SESSION(sess,&pi); + XPUSHs(sv_2mortal(newSVpv((char*)pc,len))); + Safefree(pc); + + +SSL_SESSION * +d2i_SSL_SESSION(pv) + SV *pv + CODE: + RETVAL = NULL; + if (SvPOK(pv)) { + const unsigned char *p; + STRLEN len; + p = (unsigned char*)SvPV(pv,len); + RETVAL = d2i_SSL_SESSION(NULL,&p,len); + } + OUTPUT: + RETVAL + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) + +int +SSL_SESSION_up_ref(sess) + SSL_SESSION * sess + +#endif + +int +SSL_set_session(to,ses) + SSL * to + SSL_SESSION * ses + +#define REM30 "SSLeay-0.9.0 defines these as macros. I expand them here for safety's sake" + +SSL_SESSION * +SSL_get_session(s) + SSL * s + ALIAS: + SSL_get0_session = 1 + +SSL_SESSION * +SSL_get1_session(s) + SSL * s + +X509 * +SSL_get_certificate(s) + SSL * s + +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL +#define REM18 "NOTE: requires 0.9.8f+" + +SSL_CTX * +SSL_get_SSL_CTX(s) + SSL * s + +SSL_CTX * +SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) + +long +SSL_ctrl(ssl,cmd,larg,parg) + SSL * ssl + int cmd + long larg + char * parg + +#endif + +long +SSL_CTX_ctrl(ctx,cmd,larg,parg) + SSL_CTX * ctx + int cmd + long larg + char * parg + +long +SSL_get_options(ssl) + SSL * ssl + +long +SSL_set_options(ssl,op) + SSL * ssl + long op + +long +SSL_CTX_get_options(ctx) + SSL_CTX * ctx + +long +SSL_CTX_set_options(ctx,op) + SSL_CTX * ctx + long op + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + +struct lhash_st_SSL_SESSION * +SSL_CTX_sessions(ctx) + SSL_CTX * ctx + +#else + +LHASH * +SSL_CTX_sessions(ctx) + SSL_CTX * ctx + CODE: + /* NOTE: This should be deprecated. Corresponding macro was removed from ssl.h as of 0.9.2 */ + if (ctx == NULL) croak("NULL SSL context passed as argument."); + RETVAL = ctx -> sessions; + OUTPUT: + RETVAL + +#endif + +unsigned long +SSL_CTX_sess_number(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_connect(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_connect_good(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_connect_renegotiate(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_accept(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_accept_renegotiate(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_accept_good(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_hits(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_cb_hits(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_misses(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_timeouts(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_cache_full(ctx) + SSL_CTX * ctx + +int +SSL_CTX_sess_get_cache_size(ctx) + SSL_CTX * ctx + +long +SSL_CTX_sess_set_cache_size(ctx,size) + SSL_CTX * ctx + int size + +int +SSL_want(s) + SSL * s + + # OpenSSL 1.1.1 documents SSL_in_init and the related functions as + # returning 0 or 1. However, older versions and e.g. LibreSSL may + # return other values than 1 which we fold to 1. +int +SSL_in_before(s) + SSL * s + CODE: + RETVAL = SSL_in_before(s) == 0 ? 0 : 1; + OUTPUT: + RETVAL + +int +SSL_is_init_finished(s) + SSL * s + CODE: + RETVAL = SSL_is_init_finished(s) == 0 ? 0 : 1; + OUTPUT: + RETVAL + +int +SSL_in_init(s) + SSL * s + CODE: + RETVAL = SSL_in_init(s) == 0 ? 0 : 1; + OUTPUT: + RETVAL + +int +SSL_in_connect_init(s) + SSL * s + CODE: + RETVAL = SSL_in_connect_init(s) == 0 ? 0 : 1; + OUTPUT: + RETVAL + +int +SSL_in_accept_init(s) + SSL * s + CODE: + RETVAL = SSL_in_accept_init(s) == 0 ? 0 : 1; + OUTPUT: + RETVAL + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +int +SSL_state(s) + SSL * s + +int +SSL_get_state(ssl) + SSL * ssl + CODE: + RETVAL = SSL_state(ssl); + OUTPUT: + RETVAL + + +#else +int +SSL_state(s) + SSL * s + CODE: + RETVAL = SSL_get_state(s); + OUTPUT: + RETVAL + + +int +SSL_get_state(s) + SSL * s + +#endif +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) + +long +SSL_set_tlsext_host_name(SSL *ssl, const char *name) + +const char * +SSL_get_servername(const SSL *s, int type=TLSEXT_NAMETYPE_host_name) + +int +SSL_get_servername_type(const SSL *s) + +void +SSL_CTX_set_tlsext_servername_callback(ctx,callback=&PL_sv_undef,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_tlsext_servername_callback(ctx, NULL); + SSL_CTX_set_tlsext_servername_arg(ctx, NULL); + cb_data_advanced_put(ctx, "tlsext_servername_callback!!data", NULL); + cb_data_advanced_put(ctx, "tlsext_servername_callback!!func", NULL); + } else { + cb_data_advanced_put(ctx, "tlsext_servername_callback!!data", newSVsv(data)); + cb_data_advanced_put(ctx, "tlsext_servername_callback!!func", newSVsv(callback)); + SSL_CTX_set_tlsext_servername_callback(ctx, &tlsext_servername_callback_invoke); + SSL_CTX_set_tlsext_servername_arg(ctx, (void*)ctx); + } + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x1010006fL /* In OpenSSL 1.1.0 but actually called for $ssl starting from 1.1.0f */ +#ifndef LIBRESSL_VERSION_NUMBER +#ifndef OPENSSL_IS_BORINGSSL +void +SSL_set_default_passwd_cb(ssl,callback=&PL_sv_undef) + SSL * ssl + SV * callback + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_set_default_passwd_cb(ssl, NULL); + SSL_set_default_passwd_cb_userdata(ssl, NULL); + cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!func", NULL); + } + else { + cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!func", newSVsv(callback)); + SSL_set_default_passwd_cb_userdata(ssl, (void*)ssl); + SSL_set_default_passwd_cb(ssl, &ssleay_ssl_passwd_cb_invoke); + } + +void +SSL_set_default_passwd_cb_userdata(ssl,data=&PL_sv_undef) + SSL * ssl + SV * data + CODE: + /* SSL_set_default_passwd_cb_userdata is set in SSL_set_default_passwd_cb */ + if (data==NULL || !SvOK(data)) { + cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!data", NULL); + } + else { + cb_data_advanced_put(ssl, "ssleay_ssl_passwd_cb!!data", newSVsv(data)); + } + +#endif /* !BoringSSL */ +#endif /* !LibreSSL */ +#endif /* >= 1.1.0f */ + +#if OPENSSL_VERSION_NUMBER >= 0x10100001L && !defined(LIBRESSL_VERSION_NUMBER) + +void +SSL_set_security_level(SSL * ssl, int level) + +int +SSL_get_security_level(SSL * ssl) + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10101007L && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_set_num_tickets(SSL *ssl, size_t num_tickets) + +size_t +SSL_get_num_tickets(SSL *ssl) + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10101003L && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_set_ciphersuites(SSL *ssl, const char *str) + +#endif + +const BIO_METHOD * +BIO_f_ssl() + +const BIO_METHOD * +BIO_s_mem() + +unsigned long +ERR_get_error() + +unsigned long +ERR_peek_error() + +void +ERR_put_error(lib,func,reason,file,line) + int lib + int func + int reason + char * file + int line + +void +ERR_clear_error() + +char * +ERR_error_string(error,buf=NULL) + unsigned long error + char * buf + CODE: + RETVAL = ERR_error_string(error,buf); + OUTPUT: + RETVAL + +void +SSL_load_error_strings() + +void +ERR_load_crypto_strings() + +int +SSL_FIPS_mode_set(int onoff) + CODE: +#ifdef USE_ITHREADS + MUTEX_LOCK(&LIB_init_mutex); +#endif +#ifdef OPENSSL_FIPS + RETVAL = FIPS_mode_set(onoff); + if (!RETVAL) + { + ERR_load_crypto_strings(); + ERR_print_errors_fp(stderr); + } +#else + RETVAL = 1; + fprintf(stderr, "SSL_FIPS_mode_set not available: OpenSSL not compiled with FIPS support\n"); +#endif +#ifdef USE_ITHREADS + MUTEX_UNLOCK(&LIB_init_mutex); +#endif + OUTPUT: + RETVAL + + +int +SSL_library_init() + ALIAS: + SSLeay_add_ssl_algorithms = 1 + OpenSSL_add_ssl_algorithms = 2 + add_ssl_algorithms = 3 + CODE: +#ifdef USE_ITHREADS + MUTEX_LOCK(&LIB_init_mutex); +#endif + RETVAL = 0; + if (!LIB_initialized) { + RETVAL = SSL_library_init(); + LIB_initialized = 1; + } +#ifdef USE_ITHREADS + MUTEX_UNLOCK(&LIB_init_mutex); +#endif + OUTPUT: + RETVAL + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +#define REM5 "NOTE: requires 0.9.7+" +#ifndef OPENSSL_NO_ENGINE + +void +ENGINE_load_builtin_engines() + +void +ENGINE_register_all_complete() + +ENGINE* +ENGINE_by_id(id) + char * id + +int +ENGINE_set_default(e, flags) + ENGINE * e + int flags + +#endif /* OPENSSL_NO_ENGINE */ +#endif + +void +ERR_load_SSL_strings() + +void +ERR_load_RAND_strings() + +int +RAND_bytes(buf, num) + SV *buf + int num + PREINIT: + int rc; + unsigned char *random; + CODE: + New(0, random, num, unsigned char); + rc = RAND_bytes(random, num); + sv_setpvn(buf, (const char*)random, num); + Safefree(random); + RETVAL = rc; + OUTPUT: + RETVAL + +#if OPENSSL_VERSION_NUMBER >= 0x10101001L && !defined(LIBRESSL_VERSION_NUMBER) + +int +RAND_priv_bytes(buf, num) + SV *buf + int num + PREINIT: + int rc; + unsigned char *random; + CODE: + New(0, random, num, unsigned char); + rc = RAND_priv_bytes(random, num); + sv_setpvn(buf, (const char*)random, num); + Safefree(random); + RETVAL = rc; + OUTPUT: + RETVAL + +#endif + +int +RAND_pseudo_bytes(buf, num) + SV *buf + int num + PREINIT: + int rc; + unsigned char *random; + CODE: + New(0, random, num, unsigned char); + rc = RAND_pseudo_bytes(random, num); + sv_setpvn(buf, (const char*)random, num); + Safefree(random); + RETVAL = rc; + OUTPUT: + RETVAL + +void +RAND_add(buf, num, entropy) + SV *buf + int num + double entropy + PREINIT: + STRLEN len; + CODE: + RAND_add((const void *)SvPV(buf, len), num, entropy); + +int +RAND_poll() + +int +RAND_status() + +SV * +RAND_file_name(num) + size_t num + PREINIT: + char *buf; + CODE: + New(0, buf, num, char); + if (!RAND_file_name(buf, num)) { + Safefree(buf); + XSRETURN_UNDEF; + } + RETVAL = newSVpv(buf, 0); + Safefree(buf); + OUTPUT: + RETVAL + +void +RAND_seed(buf) + PREINIT: + STRLEN len; + INPUT: + char * buf = SvPV( ST(1), len); + CODE: + RAND_seed (buf, (int)len); + +void +RAND_cleanup() + +int +RAND_load_file(file_name, how_much) + char * file_name + int how_much + +int +RAND_write_file(file_name) + char * file_name + +#define REM40 "Minimal X509 stuff..., this is a bit ugly and should be put in its own modules Net::SSLeay::X509.pm" + +#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2050000fL) + +int +X509_check_host(X509 *cert, const char *name, unsigned int flags = 0, SV *peername = &PL_sv_undef) + PREINIT: + char *c_peername = NULL; + CODE: + RETVAL = X509_check_host(cert, name, 0, flags, (items == 4) ? &c_peername : NULL); + if (items == 4) + sv_setpv(peername, c_peername); + OUTPUT: + RETVAL + CLEANUP: + if (c_peername) + OPENSSL_free(c_peername); + +int +X509_check_email(X509 *cert, const char *address, unsigned int flags = 0) + CODE: + RETVAL = X509_check_email(cert, address, 0, flags); + OUTPUT: + RETVAL + +int +X509_check_ip(X509 *cert, SV *address, unsigned int flags = 0) + PREINIT: + unsigned char *c_address; + size_t addresslen; + CODE: + c_address = (unsigned char *)SvPV(address, addresslen); + RETVAL = X509_check_ip(cert, c_address, addresslen, flags); + OUTPUT: + RETVAL + +int +X509_check_ip_asc(X509 *cert, const char *address, unsigned int flags = 0) + +#endif + +X509_NAME* +X509_get_issuer_name(cert) + X509 * cert + +X509_NAME* +X509_get_subject_name(cert) + X509 * cert + +void * +X509_get_ex_data(cert,idx) + X509 * cert + int idx + +int +X509_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL) + long argl + void * argp + CRYPTO_EX_new * new_func + CRYPTO_EX_dup * dup_func + CRYPTO_EX_free * free_func + +void * +X509_get_app_data(cert) + X509 * cert + CODE: + RETVAL = X509_get_ex_data(cert,0); + OUTPUT: + RETVAL + +int +X509_set_ex_data(cert,idx,data) + X509 * cert + int idx + void * data + +int +X509_set_app_data(cert,arg) + X509 * cert + char * arg + CODE: + RETVAL = X509_set_ex_data(cert,0,arg); + OUTPUT: + RETVAL + +int +X509_set_issuer_name(X509 *x, X509_NAME *name) + +int +X509_set_subject_name(X509 *x, X509_NAME *name) + +int +X509_set_version(X509 *x, long version) + +int +X509_set_pubkey(X509 *x, EVP_PKEY *pkey) + +long +X509_get_version(X509 *x) + +EVP_PKEY * +X509_get_pubkey(X509 *x) + +ASN1_INTEGER * +X509_get_serialNumber(X509 *x) + +#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2080100fL) + +const ASN1_INTEGER * +X509_get0_serialNumber(const X509 *x) + +#endif + +int +X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) + +int +X509_certificate_type(X509 *x, EVP_PKEY *pubkey=NULL); + +int +X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) + +int +X509_verify(X509 *x, EVP_PKEY *r) + +X509_NAME * +X509_NAME_new() + +unsigned long +X509_NAME_hash(X509_NAME *name) + +void +X509_NAME_oneline(name) + X509_NAME * name + PREINIT: + char * buf; + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + if ((buf = X509_NAME_oneline(name, NULL, 0))) { + sv_setpvn( ST(0), buf, strlen(buf)); + OPENSSL_free(buf); /* mem was allocated by openssl */ + } + +void +X509_NAME_print_ex(name,flags=XN_FLAG_RFC2253,utf8_decode=0) + X509_NAME * name + unsigned long flags + int utf8_decode + PREINIT: + char * buf; + BIO * bp; + int n, i, ident=0; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + bp = BIO_new(BIO_s_mem()); + if (bp) { + if (X509_NAME_print_ex(bp, name, ident, flags)) { + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + i = BIO_read(bp,buf,n); + if (i>=0 && i<=n) { + sv_setpvn(ST(0), buf, i); + if (utf8_decode) sv_utf8_decode(ST(0)); + } + Safefree(buf); + } + } + BIO_free(bp); + } + +void +X509_NAME_get_text_by_NID(name,nid) + X509_NAME * name + int nid + PREINIT: + char* buf; + int length; + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + length = X509_NAME_get_text_by_NID(name, nid, NULL, 0); + + if (length>=0) { + New(0, buf, length+1, char); + if (X509_NAME_get_text_by_NID(name, nid, buf, length + 1)>=0) + sv_setpvn( ST(0), buf, length); + Safefree(buf); + } + +#if OPENSSL_VERSION_NUMBER >= 0x0090500fL +#define REM17 "requires 0.9.5+" + +int +X509_NAME_add_entry_by_NID(name,nid,type,bytes,loc=-1,set=0) + X509_NAME *name + int nid + int type + int loc + int set + PREINIT: + STRLEN len; + INPUT: + unsigned char *bytes = (unsigned char *)SvPV(ST(3), len); + CODE: + RETVAL = X509_NAME_add_entry_by_NID(name,nid,type,bytes,len,loc,set); + OUTPUT: + RETVAL + +int +X509_NAME_add_entry_by_OBJ(name,obj,type,bytes,loc=-1,set=0) + X509_NAME *name + ASN1_OBJECT *obj + int type + int loc + int set + PREINIT: + STRLEN len; + INPUT: + unsigned char *bytes = (unsigned char *)SvPV(ST(3), len); + CODE: + RETVAL = X509_NAME_add_entry_by_OBJ(name,obj,type,bytes,len,loc,set); + OUTPUT: + RETVAL + +int +X509_NAME_add_entry_by_txt(name,field,type,bytes,loc=-1,set=0) + X509_NAME *name + char *field + int type + int loc + int set + PREINIT: + STRLEN len; + INPUT: + unsigned char *bytes = (unsigned char *)SvPV(ST(3), len); + CODE: + RETVAL = X509_NAME_add_entry_by_txt(name,field,type,bytes,len,loc,set); + OUTPUT: + RETVAL + +#endif + +int +X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) + +int +X509_NAME_entry_count(X509_NAME *name) + +X509_NAME_ENTRY * +X509_NAME_get_entry(X509_NAME *name, int loc) + +ASN1_STRING * +X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) + +ASN1_OBJECT * +X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne) + +void +X509_CRL_free(X509_CRL *x) + +X509_CRL * +X509_CRL_new() + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +#define REM19 "requires 0.9.7+" + +int +X509_CRL_set_version(X509_CRL *x, long version) + +int +X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) + +int +X509_CRL_set_lastUpdate(X509_CRL *x, ASN1_TIME *tm) + +int +X509_CRL_set_nextUpdate(X509_CRL *x, ASN1_TIME *tm) + +int +X509_CRL_sort(X509_CRL *x) + +#endif + +long +X509_CRL_get_version(X509_CRL *x) + +X509_NAME * +X509_CRL_get_issuer(X509_CRL *x) + +ASN1_TIME * +X509_CRL_get_lastUpdate(X509_CRL *x) + +ASN1_TIME * +X509_CRL_get_nextUpdate(X509_CRL *x) + +int +X509_CRL_verify(X509_CRL *a, EVP_PKEY *r) + +int +X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +#define REM20 "requires 0.9.7+" + +int +P_X509_CRL_set_serial(crl,crl_number) + X509_CRL *crl + ASN1_INTEGER * crl_number; + CODE: + RETVAL = 0; + if (crl && crl_number) + if (X509_CRL_add1_ext_i2d(crl, NID_crl_number, crl_number, 0, 0)) RETVAL = 1; + OUTPUT: + RETVAL + +ASN1_INTEGER * +P_X509_CRL_get_serial(crl) + X509_CRL *crl + INIT: + int i; + CODE: + RETVAL = (ASN1_INTEGER *)X509_CRL_get_ext_d2i(crl, NID_crl_number, &i, NULL); + if (!RETVAL || i==-1) XSRETURN_UNDEF; + OUTPUT: + RETVAL + +void +P_X509_CRL_add_revoked_serial_hex(crl,serial_hex,rev_time,reason_code=0,comp_time=NULL) + X509_CRL *crl + char * serial_hex + ASN1_TIME *rev_time + long reason_code + ASN1_TIME *comp_time + PREINIT: + BIGNUM *bn = NULL; + ASN1_INTEGER *sn; + X509_REVOKED *rev; + ASN1_ENUMERATED *rsn = NULL; + int rv; + PPCODE: + rv=0; + rev = X509_REVOKED_new(); + if (rev) { + if (BN_hex2bn(&bn, serial_hex)) { + sn = BN_to_ASN1_INTEGER(bn, NULL); + if (sn) { + X509_REVOKED_set_serialNumber(rev, sn); + ASN1_INTEGER_free(sn); + rv = 1; + } + BN_free(bn); + } + } + if (!rv) XSRETURN_IV(0); + + if (!rev_time) XSRETURN_IV(0); + if (!X509_REVOKED_set_revocationDate(rev, rev_time)) XSRETURN_IV(0); + + if(reason_code) { + rv = 0; + rsn = ASN1_ENUMERATED_new(); + if (rsn) { + if (ASN1_ENUMERATED_set(rsn, reason_code)) + if (X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rsn, 0, 0)) + rv=1; + ASN1_ENUMERATED_free(rsn); + } + if (!rv) XSRETURN_IV(0); + } + + if(comp_time) { + X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0); + } + + if(!X509_CRL_add0_revoked(crl, rev)) XSRETURN_IV(0); + XSRETURN_IV(1); + +#endif + +X509_REQ * +X509_REQ_new() + +void +X509_REQ_free(X509_REQ *x) + +X509_NAME * +X509_REQ_get_subject_name(X509_REQ *x) + +int +X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) + +int +X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) + +EVP_PKEY * +X509_REQ_get_pubkey(X509_REQ *x) + +int +X509_REQ_sign(X509_REQ *x, EVP_PKEY *pk, const EVP_MD *md) + +int +X509_REQ_verify(X509_REQ *x, EVP_PKEY *r) + +int +X509_REQ_set_version(X509_REQ *x, long version) + +long +X509_REQ_get_version(X509_REQ *x) + +int +X509_REQ_get_attr_count(const X509_REQ *req); + +int +X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos=-1) + +int +X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, int lastpos=-1) + +int +X509_REQ_add1_attr_by_NID(req,nid,type,bytes) + X509_REQ *req + int nid + int type + PREINIT: + STRLEN len; + INPUT: + unsigned char *bytes = (unsigned char *)SvPV(ST(3), len); + CODE: + RETVAL = X509_REQ_add1_attr_by_NID(req,nid,type,bytes,len); + OUTPUT: + RETVAL + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +#define REM21 "requires 0.9.7+" + +void +P_X509_REQ_get_attr(req,n) + X509_REQ *req + int n + INIT: + X509_ATTRIBUTE * att; + int count, i; + ASN1_STRING * s; + ASN1_TYPE * t; + PPCODE: + att = X509_REQ_get_attr(req,n); + count = X509_ATTRIBUTE_count(att); + for (i=0; ivalue.asn1_string; + XPUSHs(sv_2mortal(newSViv(PTR2IV(s)))); + } + +#endif + +int +P_X509_REQ_add_extensions(x,...) + X509_REQ *x + PREINIT: + int i=1; + int nid; + char *data; + X509_EXTENSION *ex; + STACK_OF(X509_EXTENSION) *stack; + CODE: + if (items>1) { + RETVAL = 1; + stack = sk_X509_EXTENSION_new_null(); + while(i+11) { + RETVAL = 1; + while(i+1= 0x0090800fL +#ifndef OPENSSL_NO_SHA256 + if (!k && !strcmp(type,"sha256")) { + k = 1; digest_tp = EVP_sha256(); + } +#endif +#endif + if (!k && !strcmp(type,"ripemd160")) { + k = 1; digest_tp = EVP_ripemd160(); + } + if (!k) /* Default digest */ + digest_tp = EVP_sha1(); + if ( digest_tp == NULL ) { + /* Out of memory */ + XSRETURN_UNDEF; + } + if (!X509_digest(cert, digest_tp, digest, &dsz)) { + /* Out of memory */ + XSRETURN_UNDEF; + } + text[0] = '\0'; + for(k=0; k= 0 + && (subjAltNameExt = X509_get_ext(cert, i)) + && (subjAltNameDNs = X509V3_EXT_d2i(subjAltNameExt))) + { + num_gnames = sk_GENERAL_NAME_num(subjAltNameDNs); + + for (j = 0; j < num_gnames; j++) + { + subjAltNameDN = sk_GENERAL_NAME_value(subjAltNameDNs, j); + + switch (subjAltNameDN->type) + { + case GEN_OTHERNAME: + EXTEND(SP, 2); + count++; + PUSHs(sv_2mortal(newSViv(subjAltNameDN->type))); + PUSHs(sv_2mortal(newSVpv((const char*)ASN1_STRING_data(subjAltNameDN->d.otherName->value->value.utf8string), ASN1_STRING_length(subjAltNameDN->d.otherName->value->value.utf8string)))); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + EXTEND(SP, 2); + count++; + PUSHs(sv_2mortal(newSViv(subjAltNameDN->type))); + PUSHs(sv_2mortal(newSVpv((const char*)ASN1_STRING_data(subjAltNameDN->d.ia5), ASN1_STRING_length(subjAltNameDN->d.ia5)))); + break; + + case GEN_DIRNAME: + { + char * buf = X509_NAME_oneline(subjAltNameDN->d.dirn, NULL, 0); + EXTEND(SP, 2); + count++; + PUSHs(sv_2mortal(newSViv(subjAltNameDN->type))); + PUSHs(sv_2mortal(newSVpv((buf), strlen((buf))))); + break; + } + + case GEN_IPADD: + EXTEND(SP, 2); + count++; + PUSHs(sv_2mortal(newSViv(subjAltNameDN->type))); + PUSHs(sv_2mortal(newSVpv((const char*)subjAltNameDN->d.ip->data, subjAltNameDN->d.ip->length))); + break; + + } + } + sk_GENERAL_NAME_pop_free(subjAltNameDNs, GENERAL_NAME_free); + } + XSRETURN(count * 2); + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + +void +P_X509_get_crl_distribution_points(cert) + X509 * cert + INIT: + GENERAL_NAMES *gnames; + GENERAL_NAME *gn; + STACK_OF(DIST_POINT) *points; + DIST_POINT *p; + int i, j; + PPCODE: + points = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL); + if (points) + for (i = 0; i < sk_DIST_POINT_num(points); i++) { + p = sk_DIST_POINT_value(points, i); + if (!p->distpoint) + continue; + if (p->distpoint->type == 0) { + /* full name */ + gnames = p->distpoint->name.fullname; + for (j = 0; j < sk_GENERAL_NAME_num(gnames); j++) { + gn = sk_GENERAL_NAME_value(gnames, j); + + if (gn->type == GEN_URI) { + XPUSHs(sv_2mortal(newSVpv((char*)ASN1_STRING_data(gn->d.ia5),ASN1_STRING_length(gn->d.ia5)))); + } + } + } + else { + /* relative name - not supported */ + /* XXX-TODO: the code below is just an idea; do not enable it without proper test case + BIO *bp; + char *buf; + int n; + X509_NAME ntmp; + ntmp.entries = p->distpoint->name.relativename; + bp = BIO_new(BIO_s_mem()); + if (bp) { + X509_NAME_print_ex(bp, &ntmp, 0, XN_FLAG_RFC2253); + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + j = BIO_read(bp,buf,n); + if (j>=0 && j<=n) XPUSHs(sv_2mortal(newSVpvn(buf,j))); + Safefree(buf); + } + BIO_free(bp); + } + */ + } + } + +void +P_X509_get_ocsp_uri(cert) + X509 * cert + PPCODE: + AUTHORITY_INFO_ACCESS *info; + int i; + info = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL); + if (!info) XSRETURN_UNDEF; + + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); + if (OBJ_obj2nid(ad->method) == NID_ad_OCSP + && ad->location->type == GEN_URI) { + XPUSHs(sv_2mortal(newSVpv( + (char*)ASN1_STRING_data(ad->location->d.uniformResourceIdentifier), + ASN1_STRING_length(ad->location->d.uniformResourceIdentifier) + ))); + if (GIMME == G_SCALAR) break; /* get only first */ + } + } + + +void +P_X509_get_ext_key_usage(cert,format=0) + X509 * cert + int format + PREINIT: + EXTENDED_KEY_USAGE *extusage; + int i, nid; + char buffer[100]; /* openssl doc: a buffer length of 80 should be more than enough to handle any OID encountered in practice */ + ASN1_OBJECT *o; + PPCODE: + extusage = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL); + for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { + o = sk_ASN1_OBJECT_value(extusage,i); + nid = OBJ_obj2nid(o); + OBJ_obj2txt(buffer, sizeof(buffer)-1, o, 1); + if(format==0) + XPUSHs(sv_2mortal(newSVpv(buffer,0))); /* format 0: oid */ + else if(format==1 && nid>0) + XPUSHs(sv_2mortal(newSViv(nid))); /* format 1: nid */ + else if(format==2 && nid>0) + XPUSHs(sv_2mortal(newSVpv(OBJ_nid2sn(nid),0))); /* format 2: shortname */ + else if(format==3 && nid>0) + XPUSHs(sv_2mortal(newSVpv(OBJ_nid2ln(nid),0))); /* format 3: longname */ + } + +#endif + +void +P_X509_get_key_usage(cert) + X509 * cert + INIT: + ASN1_BIT_STRING * u; + PPCODE: + u = X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL); + if (u) { + if (ASN1_BIT_STRING_get_bit(u,0)) XPUSHs(sv_2mortal(newSVpv("digitalSignature",0))); + if (ASN1_BIT_STRING_get_bit(u,1)) XPUSHs(sv_2mortal(newSVpv("nonRepudiation",0))); + if (ASN1_BIT_STRING_get_bit(u,2)) XPUSHs(sv_2mortal(newSVpv("keyEncipherment",0))); + if (ASN1_BIT_STRING_get_bit(u,3)) XPUSHs(sv_2mortal(newSVpv("dataEncipherment",0))); + if (ASN1_BIT_STRING_get_bit(u,4)) XPUSHs(sv_2mortal(newSVpv("keyAgreement",0))); + if (ASN1_BIT_STRING_get_bit(u,5)) XPUSHs(sv_2mortal(newSVpv("keyCertSign",0))); + if (ASN1_BIT_STRING_get_bit(u,6)) XPUSHs(sv_2mortal(newSVpv("cRLSign",0))); + if (ASN1_BIT_STRING_get_bit(u,7)) XPUSHs(sv_2mortal(newSVpv("encipherOnly",0))); + if (ASN1_BIT_STRING_get_bit(u,8)) XPUSHs(sv_2mortal(newSVpv("decipherOnly",0))); + } + +void +P_X509_get_netscape_cert_type(cert) + X509 * cert + INIT: + ASN1_BIT_STRING * u; + PPCODE: + u = X509_get_ext_d2i(cert, NID_netscape_cert_type, NULL, NULL); + if (u) { + if (ASN1_BIT_STRING_get_bit(u,0)) XPUSHs(sv_2mortal(newSVpv("client",0))); + if (ASN1_BIT_STRING_get_bit(u,1)) XPUSHs(sv_2mortal(newSVpv("server",0))); + if (ASN1_BIT_STRING_get_bit(u,2)) XPUSHs(sv_2mortal(newSVpv("email",0))); + if (ASN1_BIT_STRING_get_bit(u,3)) XPUSHs(sv_2mortal(newSVpv("objsign",0))); + if (ASN1_BIT_STRING_get_bit(u,4)) XPUSHs(sv_2mortal(newSVpv("reserved",0))); + if (ASN1_BIT_STRING_get_bit(u,5)) XPUSHs(sv_2mortal(newSVpv("sslCA",0))); + if (ASN1_BIT_STRING_get_bit(u,6)) XPUSHs(sv_2mortal(newSVpv("emailCA",0))); + if (ASN1_BIT_STRING_get_bit(u,7)) XPUSHs(sv_2mortal(newSVpv("objCA",0))); + } + +int +X509_get_ext_by_NID(x,nid,loc=-1) + X509* x + int nid + int loc + +X509_EXTENSION * +X509_get_ext(x,loc) + X509* x + int loc + +int +X509_EXTENSION_get_critical(X509_EXTENSION *ex) + +ASN1_OCTET_STRING * +X509_EXTENSION_get_data(X509_EXTENSION *ne) + +ASN1_OBJECT * +X509_EXTENSION_get_object(X509_EXTENSION *ex) + +int +X509_get_ext_count(X509 *x) + +int +X509_CRL_get_ext_count(X509_CRL *x) + +int +X509_CRL_get_ext_by_NID(x,ni,loc=-1) + X509_CRL* x + int ni + int loc + +X509_EXTENSION * +X509_CRL_get_ext(x,loc) + X509_CRL* x + int loc + +void +X509V3_EXT_print(ext,flags=0,utf8_decode=0) + X509_EXTENSION * ext + unsigned long flags + int utf8_decode + PREINIT: + BIO * bp; + char * buf; + int i, n; + int indent=0; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + bp = BIO_new(BIO_s_mem()); + if (bp) { + if(X509V3_EXT_print(bp,ext,flags,indent)) { + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + i = BIO_read(bp,buf,n); + if (i>=0 && i<=n) { + sv_setpvn(ST(0), buf, i); + if (utf8_decode) sv_utf8_decode(ST(0)); + } + Safefree(buf); + } + } + BIO_free(bp); + } + +void * +X509V3_EXT_d2i(ext) + X509_EXTENSION *ext + +X509_STORE_CTX * +X509_STORE_CTX_new() + +void +X509_STORE_CTX_init(ctx, store=NULL, x509=NULL, chain=NULL) + X509_STORE_CTX * ctx + X509_STORE * store + X509 * x509 + STACK_OF(X509) * chain + +void +X509_STORE_CTX_free(ctx) + X509_STORE_CTX * ctx + +int +X509_verify_cert(x509_store_ctx) + X509_STORE_CTX * x509_store_ctx + +int +X509_STORE_CTX_get_error(x509_store_ctx) + X509_STORE_CTX * x509_store_ctx + +int +X509_STORE_CTX_get_error_depth(x509_store_ctx) + X509_STORE_CTX * x509_store_ctx + +int +X509_STORE_CTX_set_ex_data(x509_store_ctx,idx,data) + X509_STORE_CTX * x509_store_ctx + int idx + void * data + +int +X509_STORE_CTX_set_app_data(x509_store_ctx,arg) + X509_STORE_CTX * x509_store_ctx + char * arg + CODE: + RETVAL = X509_STORE_CTX_set_ex_data(x509_store_ctx,0,arg); + OUTPUT: + RETVAL + +void +X509_STORE_CTX_set_error(x509_store_ctx,s) + X509_STORE_CTX * x509_store_ctx + int s + +void +X509_STORE_CTX_set_cert(x509_store_ctx,x) + X509_STORE_CTX * x509_store_ctx + X509 * x + +X509_STORE * +X509_STORE_new() + +void +X509_STORE_free(store) + X509_STORE * store + +X509_LOOKUP * +X509_STORE_add_lookup(store, method) + X509_STORE * store + X509_LOOKUP_METHOD * method + +int +X509_STORE_add_cert(ctx, x) + X509_STORE *ctx + X509 *x + +int +X509_STORE_add_crl(ctx, x) + X509_STORE *ctx + X509_CRL *x + +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL + +void +X509_STORE_set_flags(ctx, flags) + X509_STORE *ctx + long flags + +void +X509_STORE_set_purpose(ctx, purpose) + X509_STORE *ctx + int purpose + +void +X509_STORE_set_trust(ctx, trust) + X509_STORE *ctx + int trust + +int +X509_STORE_set1_param(ctx, pm) + X509_STORE *ctx + X509_VERIFY_PARAM *pm + +#endif + +X509_LOOKUP_METHOD * +X509_LOOKUP_hash_dir() + +void +X509_LOOKUP_add_dir(lookup, dir, type) + X509_LOOKUP * lookup + char * dir + int type + +int +X509_load_cert_file(ctx, file, type) + X509_LOOKUP *ctx + char *file + int type + +int +X509_load_crl_file(ctx, file, type) + X509_LOOKUP *ctx + char *file + int type + +int +X509_load_cert_crl_file(ctx, file, type) + X509_LOOKUP *ctx + char *file + int type + +const char * +X509_verify_cert_error_string(n) + long n + +ASN1_INTEGER * +ASN1_INTEGER_new() + +void +ASN1_INTEGER_free(ASN1_INTEGER *i) + +int +ASN1_INTEGER_set(ASN1_INTEGER *i, long val) + +long +ASN1_INTEGER_get(ASN1_INTEGER *a) + +void +P_ASN1_INTEGER_set_hex(i,str) + ASN1_INTEGER * i + char * str + INIT: + BIGNUM *bn; + int rv = 1; + PPCODE: + bn = BN_new(); + if (!BN_hex2bn(&bn, str)) XSRETURN_IV(0); + if (!BN_to_ASN1_INTEGER(bn, i)) rv = 0; + BN_free(bn); + XSRETURN_IV(rv); + +void +P_ASN1_INTEGER_set_dec(i,str) + ASN1_INTEGER * i + char * str + INIT: + BIGNUM *bn; + int rv = 1; + PPCODE: + bn = BN_new(); + if (!BN_dec2bn(&bn, str)) XSRETURN_IV(0); + if (!BN_to_ASN1_INTEGER(bn, i)) rv = 0; + BN_free(bn); + XSRETURN_IV(rv); + +void +P_ASN1_INTEGER_get_hex(i) + ASN1_INTEGER * i + INIT: + BIGNUM *bn; + char *result; + PPCODE: + bn = BN_new(); + if (!bn) XSRETURN_UNDEF; + ASN1_INTEGER_to_BN(i, bn); + result = BN_bn2hex(bn); + BN_free(bn); + if (!result) XSRETURN_UNDEF; + XPUSHs(sv_2mortal(newSVpv((const char*)result, strlen(result)))); + OPENSSL_free(result); + +void +P_ASN1_INTEGER_get_dec(i) + ASN1_INTEGER * i + INIT: + BIGNUM *bn; + char *result; + PPCODE: + bn = BN_new(); + if (!bn) XSRETURN_UNDEF; + ASN1_INTEGER_to_BN(i, bn); + result = BN_bn2dec(bn); + BN_free(bn); + if (!result) XSRETURN_UNDEF; + XPUSHs(sv_2mortal(newSVpv((const char*)result, strlen(result)))); + OPENSSL_free(result); + +void +P_ASN1_STRING_get(s,utf8_decode=0) + ASN1_STRING * s + int utf8_decode + PREINIT: + SV * u8; + PPCODE: + u8 = newSVpv((const char*)ASN1_STRING_data(s), ASN1_STRING_length(s)); + if (utf8_decode) sv_utf8_decode(u8); + XPUSHs(sv_2mortal(u8)); + +ASN1_TIME * +X509_get_notBefore(cert) + X509 * cert + +ASN1_TIME * +X509_get_notAfter(cert) + X509 * cert + +ASN1_TIME * +X509_gmtime_adj(s, adj) + ASN1_TIME * s + long adj + +ASN1_TIME * +ASN1_TIME_set(s,t) + ASN1_TIME *s + time_t t + +void +ASN1_TIME_free(s) + ASN1_TIME *s + +time_t +ASN1_TIME_timet(s) + ASN1_TIME *s + +ASN1_TIME * +ASN1_TIME_new() + +void +P_ASN1_TIME_put2string(tm) + ASN1_TIME * tm + PREINIT: + BIO *bp=NULL; + int i=0; + char buffer[256]; + ALIAS: + P_ASN1_UTCTIME_put2string = 1 + CODE: + ST(0) = sv_newmortal(); /* undef retval to start with */ + if (tm) { + bp = BIO_new(BIO_s_mem()); + if (bp) { + ASN1_TIME_print(bp,tm); + i = BIO_read(bp,buffer,255); + buffer[i] = '\0'; + if (i>0) + sv_setpvn(ST(0), buffer, i); + BIO_free(bp); + } + } + +#if OPENSSL_VERSION_NUMBER >= 0x0090705f +#define REM15 "NOTE: requires 0.9.7e+" + +void +P_ASN1_TIME_get_isotime(tm) + ASN1_TIME *tm + PREINIT: + ASN1_GENERALIZEDTIME *tmp = NULL; + char buf[256]; + CODE: + buf[0] = '\0'; + /* ASN1_TIME_to_generalizedtime is buggy on pre-0.9.7e */ + ASN1_TIME_to_generalizedtime(tm,&tmp); + if (tmp) { + if (ASN1_GENERALIZEDTIME_check(tmp)) { + if (strlen((char*)tmp->data)>=14 && strlen((char*)tmp->data)<200) { + strcpy (buf,"yyyy-mm-ddThh:mm:ss"); + strncpy(buf, (char*)tmp->data, 4); + strncpy(buf+5, (char*)tmp->data+4, 2); + strncpy(buf+8, (char*)tmp->data+6, 2); + strncpy(buf+11,(char*)tmp->data+8, 2); + strncpy(buf+14,(char*)tmp->data+10,2); + strncpy(buf+17,(char*)tmp->data+12,2); + if (strlen((char*)tmp->data)>14) strcat(buf+19,(char*)tmp->data+14); + } + } + ASN1_GENERALIZEDTIME_free(tmp); + } + ST(0) = sv_newmortal(); + sv_setpv(ST(0), buf); + +void +P_ASN1_TIME_set_isotime(tm,str) + ASN1_TIME *tm + const char *str + PREINIT: + ASN1_TIME t; + char buf[256]; + int i,rv; + CODE: + if (!tm) XSRETURN_UNDEF; + /* we support only "2012-03-22T23:55:33" or "2012-03-22T23:55:33Z" or "2012-03-22T23:55:33" */ + if (strlen(str) < 19) XSRETURN_UNDEF; + for (i=0; i<4; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF; + for (i=5; i<7; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF; + for (i=8; i<10; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF; + for (i=11; i<13; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF; + for (i=14; i<16; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF; + for (i=17; i<19; i++) if ((str[i] > '9') || (str[i] < '0')) XSRETURN_UNDEF; + strncpy(buf, str, 4); + strncpy(buf+4, str+5, 2); + strncpy(buf+6, str+8, 2); + strncpy(buf+8, str+11, 2); + strncpy(buf+10, str+14, 2); + strncpy(buf+12, str+17, 2); + buf[14] = '\0'; + if (strlen(str)>19 && strlen(str)<200) strcat(buf,str+19); + + /* WORKAROUND: ASN1_TIME_set_string() not available in 0.9.8 !!!*/ + /* in 1.0.0 we would simply: rv = ASN1_TIME_set_string(tm,buf); */ + t.length = strlen(buf); + t.data = (unsigned char *)buf; + t.flags = 0; + t.type = V_ASN1_UTCTIME; + if (!ASN1_TIME_check(&t)) { + t.type = V_ASN1_GENERALIZEDTIME; + if (!ASN1_TIME_check(&t)) XSRETURN_UNDEF; + } + tm->type = t.type; + tm->flags = t.flags; + if (!ASN1_STRING_set(tm,t.data,t.length)) XSRETURN_UNDEF; + rv = 1; + + /* end of ASN1_TIME_set_string() reimplementation */ + + ST(0) = sv_newmortal(); + sv_setiv(ST(0), rv); /* 1 = success, undef = failure */ + +#endif + +int +EVP_PKEY_copy_parameters(to,from) + EVP_PKEY * to + EVP_PKEY * from + +EVP_PKEY * +EVP_PKEY_new() + +void +EVP_PKEY_free(EVP_PKEY *pkey) + +int +EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) + +int +EVP_PKEY_bits(EVP_PKEY *pkey) + +int +EVP_PKEY_size(EVP_PKEY *pkey) + +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + +int +EVP_PKEY_id(const EVP_PKEY *pkey) + +#endif + +void +PEM_get_string_X509(x509) + X509 * x509 + PREINIT: + BIO *bp; + int i, n; + char *buf; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + bp = BIO_new(BIO_s_mem()); + if (bp && x509) { + PEM_write_bio_X509(bp,x509); + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + i = BIO_read(bp,buf,n); + if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i); + Safefree(buf); + } + BIO_free(bp); + } + +void +PEM_get_string_X509_REQ(x509_req) + X509_REQ * x509_req + PREINIT: + BIO *bp; + int i, n; + char *buf; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + bp = BIO_new(BIO_s_mem()); + if (bp && x509_req) { + PEM_write_bio_X509_REQ(bp,x509_req); + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + i = BIO_read(bp,buf,n); + if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i); + Safefree(buf); + } + BIO_free(bp); + } + +void +PEM_get_string_X509_CRL(x509_crl) + X509_CRL * x509_crl + PREINIT: + BIO *bp; + int i, n; + char *buf; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + bp = BIO_new(BIO_s_mem()); + if (bp && x509_crl) { + PEM_write_bio_X509_CRL(bp,x509_crl); + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + i = BIO_read(bp,buf,n); + if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i); + Safefree(buf); + } + BIO_free(bp); + } + +void +PEM_get_string_PrivateKey(pk,passwd=NULL,enc_alg=NULL) + EVP_PKEY * pk + char * passwd + const EVP_CIPHER * enc_alg + PREINIT: + BIO *bp; + int i, n; + char *buf; + size_t passwd_len = 0; + pem_password_cb * cb = NULL; + void * u = NULL; + CODE: + ST(0) = sv_newmortal(); /* undef to start with */ + bp = BIO_new(BIO_s_mem()); + if (bp && pk) { + if (passwd) passwd_len = strlen(passwd); + if (passwd_len>0) { + /* encrypted key */ + if (!enc_alg) + PEM_write_bio_PrivateKey(bp,pk,EVP_des_cbc(),(unsigned char *)passwd,passwd_len,cb,u); + else + PEM_write_bio_PrivateKey(bp,pk,enc_alg,(unsigned char *)passwd,passwd_len,cb,u); + } + else { + /* unencrypted key */ + PEM_write_bio_PrivateKey(bp,pk,NULL,(unsigned char *)passwd,passwd_len,cb,u); + } + n = BIO_ctrl_pending(bp); + New(0, buf, n, char); + if (buf) { + i = BIO_read(bp,buf,n); + if (i>=0 && i<=n) sv_setpvn(ST(0), buf, i); + Safefree(buf); + } + BIO_free(bp); + } + +int +CTX_use_PKCS12_file(ctx, file, password=NULL) + SSL_CTX *ctx + char *file + char *password + PREINIT: + PKCS12 *p12; + EVP_PKEY *private_key; + X509 *certificate; + FILE *fp; + CODE: + RETVAL = 0; + if ((fp = fopen (file, "rb"))) { +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + OPENSSL_add_all_algorithms_noconf(); +#else + OpenSSL_add_all_algorithms(); +#endif + if ((p12 = d2i_PKCS12_fp(fp, NULL))) { + if (PKCS12_parse(p12, password, &private_key, &certificate, NULL)) { + if (private_key) { + if (SSL_CTX_use_PrivateKey(ctx, private_key)) RETVAL = 1; + EVP_PKEY_free(private_key); + } + if (certificate) { + if (SSL_CTX_use_certificate(ctx, certificate)) RETVAL = 1; + X509_free(certificate); + } + } + PKCS12_free(p12); + } + if (!RETVAL) ERR_print_errors_fp(stderr); + fclose(fp); + } + OUTPUT: + RETVAL + +void +P_PKCS12_load_file(file, load_chain=0, password=NULL) + char *file + int load_chain + char *password + PREINIT: + PKCS12 *p12; + EVP_PKEY *private_key = NULL; + X509 *certificate = NULL; + STACK_OF(X509) *cachain = NULL; + X509 *x; + FILE *fp; + int i, result; + PPCODE: + if ((fp = fopen (file, "rb"))) { +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + OPENSSL_add_all_algorithms_noconf(); +#else + OpenSSL_add_all_algorithms(); +#endif + if ((p12 = d2i_PKCS12_fp(fp, NULL))) { + if(load_chain) + result= PKCS12_parse(p12, password, &private_key, &certificate, &cachain); + else + result= PKCS12_parse(p12, password, &private_key, &certificate, NULL); + if (result) { + if (private_key) + XPUSHs(sv_2mortal(newSViv(PTR2IV(private_key)))); + else + XPUSHs(sv_2mortal(newSVpv(NULL,0))); /* undef */ + if (certificate) + XPUSHs(sv_2mortal(newSViv(PTR2IV(certificate)))); + else + XPUSHs(sv_2mortal(newSVpv(NULL,0))); /* undef */ + if (cachain) { + for (i=0; i= 0x00905000L + +void +RIPEMD160(data) + PREINIT: + STRLEN len; + unsigned char md[RIPEMD160_DIGEST_LENGTH]; + INPUT: + unsigned char * data = (unsigned char *) SvPV( ST(0), len); + CODE: + if (RIPEMD160(data,len,md)) { + XSRETURN_PVN((char *) md, RIPEMD160_DIGEST_LENGTH); + } else { + XSRETURN_UNDEF; + } + +#endif + +#if !defined(OPENSSL_NO_SHA) + +void +SHA1(data) + PREINIT: + STRLEN len; + unsigned char md[SHA_DIGEST_LENGTH]; + INPUT: + unsigned char * data = (unsigned char *) SvPV( ST(0), len); + CODE: + if (SHA1(data,len,md)) { + XSRETURN_PVN((char *) md, SHA_DIGEST_LENGTH); + } else { + XSRETURN_UNDEF; + } + +#endif +#if !defined(OPENSSL_NO_SHA256) && OPENSSL_VERSION_NUMBER >= 0x0090800fL + +void +SHA256(data) + PREINIT: + STRLEN len; + unsigned char md[SHA256_DIGEST_LENGTH]; + INPUT: + unsigned char * data = (unsigned char *) SvPV( ST(0), len); + CODE: + if (SHA256(data,len,md)) { + XSRETURN_PVN((char *) md, SHA256_DIGEST_LENGTH); + } else { + XSRETURN_UNDEF; + } + +#endif +#if !defined(OPENSSL_NO_SHA512) && OPENSSL_VERSION_NUMBER >= 0x0090800fL + +void +SHA512(data) + PREINIT: + STRLEN len; + unsigned char md[SHA512_DIGEST_LENGTH]; + INPUT: + unsigned char * data = (unsigned char *) SvPV( ST(0), len); + CODE: + if (SHA512(data,len,md)) { + XSRETURN_PVN((char *) md, SHA512_DIGEST_LENGTH); + } else { + XSRETURN_UNDEF; + } + +#endif + +#ifndef OPENSSL_NO_SSL2 +#if OPENSSL_VERSION_NUMBER < 0x10000000L + +const SSL_METHOD * +SSLv2_method() + +#endif +#endif + +#ifndef OPENSSL_NO_SSL3 + +const SSL_METHOD * +SSLv3_method() + +#endif + +const SSL_METHOD * +SSLv23_method() + +const SSL_METHOD * +SSLv23_server_method() + +const SSL_METHOD * +SSLv23_client_method() + +const SSL_METHOD * +TLSv1_method() + +const SSL_METHOD * +TLSv1_server_method() + +const SSL_METHOD * +TLSv1_client_method() + +#ifdef SSL_TXT_TLSV1_1 + +const SSL_METHOD * +TLSv1_1_method() + +const SSL_METHOD * +TLSv1_1_server_method() + +const SSL_METHOD * +TLSv1_1_client_method() + +#endif + +#ifdef SSL_TXT_TLSV1_2 + +const SSL_METHOD * +TLSv1_2_method() + +const SSL_METHOD * +TLSv1_2_server_method() + +const SSL_METHOD * +TLSv1_2_client_method() + +#endif + + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x20020002L) + +const SSL_METHOD * +TLS_method() + +const SSL_METHOD * +TLS_server_method() + +const SSL_METHOD * +TLS_client_method() + +#endif /* OpenSSL 1.1.0 or LibreSSL 2.2.2 */ + + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2060000fL) + +int +SSL_CTX_set_min_proto_version(ctx, version) + SSL_CTX * ctx + int version + +int +SSL_CTX_set_max_proto_version(ctx, version) + SSL_CTX * ctx + int version + +int +SSL_set_min_proto_version(ssl, version) + SSL * ssl + int version + +int +SSL_set_max_proto_version(ssl, version) + SSL * ssl + int version + +#endif /* OpenSSL 1.1.0 or LibreSSL 2.6.0 */ + + +#if OPENSSL_VERSION_NUMBER >= 0x1010007fL && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_CTX_get_min_proto_version(ctx) + SSL_CTX * ctx + +int +SSL_CTX_get_max_proto_version(ctx) + SSL_CTX * ctx + +int +SSL_get_min_proto_version(ssl) + SSL * ssl + +int +SSL_get_max_proto_version(ssl) + SSL * ssl + +#endif /* OpenSSL 1.1.0g */ + + +#if OPENSSL_VERSION_NUMBER < 0x10000000L + +int +SSL_set_ssl_method(ssl, method) + SSL * ssl + SSL_METHOD * method + +#else + +int +SSL_set_ssl_method(ssl, method) + SSL * ssl + const SSL_METHOD * method + +#endif + +const SSL_METHOD * +SSL_get_ssl_method(ssl) + SSL * ssl + +#define REM_AUTOMATICALLY_GENERATED_1_09 + +BIO * +BIO_new_buffer_ssl_connect(ctx) + SSL_CTX * ctx + +BIO * +BIO_new_file(filename,mode) + char * filename + char * mode + +BIO * +BIO_new_ssl(ctx,client) + SSL_CTX * ctx + int client + +BIO * +BIO_new_ssl_connect(ctx) + SSL_CTX * ctx + +BIO * +BIO_new(type) + BIO_METHOD * type; + +int +BIO_free(bio) + BIO * bio; + +void +BIO_read(s,max=32768) + BIO * s + int max + PREINIT: + char *buf = NULL; + int got; + CODE: + New(0, buf, max, char); + ST(0) = sv_newmortal(); /* Undefined to start with */ + if ((got = BIO_read(s, buf, max)) >= 0) + sv_setpvn( ST(0), buf, got); + Safefree(buf); + +int +BIO_write(s,buf) + BIO * s + PREINIT: + STRLEN len; + INPUT: + char * buf = SvPV( ST(1), len); + CODE: + RETVAL = BIO_write (s, buf, (int)len); + OUTPUT: + RETVAL + +int +BIO_eof(s) + BIO * s + +int +BIO_pending(s) + BIO * s + +int +BIO_wpending(s) + BIO * s + +int +BIO_ssl_copy_session_id(to,from) + BIO * to + BIO * from + +void +BIO_ssl_shutdown(ssl_bio) + BIO * ssl_bio + +int +SSL_add_client_CA(ssl,x) + SSL * ssl + X509 * x + +const char * +SSL_alert_desc_string(value) + int value + +const char * +SSL_alert_desc_string_long(value) + int value + +const char * +SSL_alert_type_string(value) + int value + +const char * +SSL_alert_type_string_long(value) + int value + +long +SSL_callback_ctrl(ssl,i,fp) + SSL * ssl + int i + callback_no_ret * fp + +int +SSL_check_private_key(ctx) + SSL * ctx + +#if OPENSSL_VERSION_NUMBER < 0x009080dfL +#define REM8 "NOTE: before 0.9.8m" + +char * +SSL_CIPHER_description(cipher,buf,size) + SSL_CIPHER * cipher + char * buf + int size + +#else + +char * +SSL_CIPHER_description(cipher,buf,size) + const SSL_CIPHER * cipher + char * buf + int size + +#endif + +#if OPENSSL_VERSION_NUMBER < 0x0090707fL +#define REM9 "NOTE: before 0.9.7g" + +const char * +SSL_CIPHER_get_name(SSL_CIPHER *c) + +int +SSL_CIPHER_get_bits(c,alg_bits=NULL) + SSL_CIPHER * c + int * alg_bits + +#else + +const char * +SSL_CIPHER_get_name(const SSL_CIPHER *c) + +int +SSL_CIPHER_get_bits(c,alg_bits=NULL) + const SSL_CIPHER * c + int * alg_bits + +#endif + +#ifndef OPENSSL_NO_COMP + +int +SSL_COMP_add_compression_method(id,cm) + int id + COMP_METHOD * cm + +#endif + +int +SSL_CTX_add_client_CA(ctx,x) + SSL_CTX * ctx + X509 * x + +long +SSL_CTX_callback_ctrl(ctx,i,fp) + SSL_CTX * ctx + int i + callback_no_ret * fp + +int +SSL_CTX_check_private_key(ctx) + SSL_CTX * ctx + +void * +SSL_CTX_get_ex_data(ssl,idx) + SSL_CTX * ssl + int idx + +int +SSL_CTX_get_quiet_shutdown(ctx) + SSL_CTX * ctx + +long +SSL_CTX_get_timeout(ctx) + SSL_CTX * ctx + +int +SSL_CTX_get_verify_depth(ctx) + SSL_CTX * ctx + +int +SSL_CTX_get_verify_mode(ctx) + SSL_CTX * ctx + +void +SSL_CTX_set_cert_store(ctx,store) + SSL_CTX * ctx + X509_STORE * store + +X509_STORE * +SSL_CTX_get_cert_store(ctx) + SSL_CTX * ctx + +void +SSL_CTX_set_cert_verify_callback(ctx,callback,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_cert_verify_callback(ctx, NULL, NULL); + cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!func", NULL); + cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!data", NULL); + } + else { + cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "ssleay_ctx_cert_verify_cb!!data", newSVsv(data)); +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + SSL_CTX_set_cert_verify_callback(ctx, ssleay_ctx_cert_verify_cb_invoke, ctx); +#else + SSL_CTX_set_cert_verify_callback(ctx, ssleay_ctx_cert_verify_cb_invoke, (char*)ctx); +#endif + } + +X509_NAME_STACK * +SSL_CTX_get_client_CA_list(ctx) + SSL_CTX *ctx + +void +SSL_CTX_set_client_CA_list(ctx,list) + SSL_CTX * ctx + X509_NAME_STACK * list + +void +SSL_CTX_set_default_passwd_cb(ctx,callback=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_default_passwd_cb(ctx, NULL); + SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL); + cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!func", NULL); + } + else { + cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!func", newSVsv(callback)); + SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)ctx); + SSL_CTX_set_default_passwd_cb(ctx, &ssleay_ctx_passwd_cb_invoke); + } + +void +SSL_CTX_set_default_passwd_cb_userdata(ctx,data=&PL_sv_undef) + SSL_CTX * ctx + SV * data + CODE: + /* SSL_CTX_set_default_passwd_cb_userdata is set in SSL_CTX_set_default_passwd_cb */ + if (data==NULL || !SvOK(data)) { + cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!data", NULL); + } + else { + cb_data_advanced_put(ctx, "ssleay_ctx_passwd_cb!!data", newSVsv(data)); + } + +int +SSL_CTX_set_ex_data(ssl,idx,data) + SSL_CTX * ssl + int idx + void * data + +int +SSL_CTX_set_purpose(s,purpose) + SSL_CTX * s + int purpose + +void +SSL_CTX_set_quiet_shutdown(ctx,mode) + SSL_CTX * ctx + int mode + +#if OPENSSL_VERSION_NUMBER < 0x10000000L + +int +SSL_CTX_set_ssl_version(ctx,meth) + SSL_CTX * ctx + SSL_METHOD * meth + +#else + +int +SSL_CTX_set_ssl_version(ctx,meth) + SSL_CTX * ctx + const SSL_METHOD * meth + +#endif + +long +SSL_CTX_set_timeout(ctx,t) + SSL_CTX * ctx + long t + +int +SSL_CTX_set_trust(s,trust) + SSL_CTX * s + int trust + +void +SSL_CTX_set_verify_depth(ctx,depth) + SSL_CTX * ctx + int depth + +int +SSL_CTX_use_certificate(ctx,x) + SSL_CTX * ctx + X509 * x + +int +SSL_CTX_use_certificate_chain_file(ctx,file) + SSL_CTX * ctx + const char * file + + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_use_certificate_chain_file(ssl,file) + SSL * ssl + const char * file + +#endif /* OpenSSL 1.1.0 */ + +int +SSL_CTX_use_PrivateKey(ctx,pkey) + SSL_CTX * ctx + EVP_PKEY * pkey + +int +SSL_CTX_use_RSAPrivateKey(ctx,rsa) + SSL_CTX * ctx + RSA * rsa + +int +SSL_do_handshake(s) + SSL * s + +SSL * +SSL_dup(ssl) + SSL * ssl + +const SSL_CIPHER * +SSL_get_current_cipher(s) + SSL * s + +long +SSL_get_default_timeout(s) + SSL * s + +void * +SSL_get_ex_data(ssl,idx) + SSL * ssl + int idx + +size_t +SSL_get_finished(ssl,buf,count=2*EVP_MAX_MD_SIZE) + SSL *ssl + SV *buf + size_t count + PREINIT: + unsigned char *finished; + size_t finished_len; + CODE: + Newx(finished, count, unsigned char); + finished_len = SSL_get_finished(ssl, finished, count); + if (count > finished_len) + count = finished_len; + sv_setpvn(buf, (const char *)finished, count); + Safefree(finished); + RETVAL = finished_len; + OUTPUT: + RETVAL + +size_t +SSL_get_peer_finished(ssl,buf,count=2*EVP_MAX_MD_SIZE) + SSL *ssl + SV *buf + size_t count + PREINIT: + unsigned char *finished; + size_t finished_len; + CODE: + Newx(finished, count, unsigned char); + finished_len = SSL_get_peer_finished(ssl, finished, count); + if (count > finished_len) + count = finished_len; + sv_setpvn(buf, (const char *)finished, count); + Safefree(finished); + RETVAL = finished_len; + OUTPUT: + RETVAL + +int +SSL_get_quiet_shutdown(ssl) + SSL * ssl + +int +SSL_get_shutdown(ssl) + SSL * ssl + +int +SSL_get_verify_depth(s) + SSL * s + +int +SSL_get_verify_mode(s) + SSL * s + +long +SSL_get_verify_result(ssl) + SSL * ssl + +int +SSL_renegotiate(s) + SSL * s + +#if OPENSSL_VERSION_NUMBER < 0x10000000L + +int +SSL_SESSION_cmp(a,b) + SSL_SESSION * a + SSL_SESSION * b + +#endif + +void * +SSL_SESSION_get_ex_data(ss,idx) + SSL_SESSION * ss + int idx + +long +SSL_SESSION_get_time(s) + SSL_SESSION * s + +long +SSL_SESSION_get_timeout(s) + SSL_SESSION * s + +int +SSL_SESSION_print_fp(fp,ses) + FILE * fp + SSL_SESSION * ses + +int +SSL_SESSION_set_ex_data(ss,idx,data) + SSL_SESSION * ss + int idx + void * data + +long +SSL_SESSION_set_time(s,t) + SSL_SESSION * s + long t + +long +SSL_SESSION_set_timeout(s,t) + SSL_SESSION * s + long t + +void +SSL_set_accept_state(s) + SSL * s + +void +sk_X509_NAME_free(sk) + X509_NAME_STACK *sk + +int +sk_X509_NAME_num(sk) + X509_NAME_STACK *sk + +X509_NAME * +sk_X509_NAME_value(sk,i) + X509_NAME_STACK *sk + int i + +X509_NAME_STACK * +SSL_get_client_CA_list(s) + SSL * s + +void +SSL_set_client_CA_list(s,list) + SSL * s + X509_NAME_STACK * list + +void +SSL_set_connect_state(s) + SSL * s + +int +SSL_set_ex_data(ssl,idx,data) + SSL * ssl + int idx + void * data + + +void +SSL_set_info_callback(ssl,callback,data=&PL_sv_undef) + SSL * ssl + SV * callback + SV * data + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_set_info_callback(ssl, NULL); + cb_data_advanced_put(ssl, "ssleay_info_cb!!func", NULL); + cb_data_advanced_put(ssl, "ssleay_info_cb!!data", NULL); + } else { + cb_data_advanced_put(ssl, "ssleay_info_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ssl, "ssleay_info_cb!!data", newSVsv(data)); + SSL_set_info_callback(ssl, ssleay_info_cb_invoke); + } + +void +SSL_CTX_set_info_callback(ctx,callback,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_info_callback(ctx, NULL); + cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!func", NULL); + cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!data", NULL); + } else { + cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "ssleay_ctx_info_cb!!data", newSVsv(data)); + SSL_CTX_set_info_callback(ctx, ssleay_ctx_info_cb_invoke); + } + +int +SSL_set_purpose(s,purpose) + SSL * s + int purpose + +void +SSL_set_quiet_shutdown(ssl,mode) + SSL * ssl + int mode + +void +SSL_set_shutdown(ssl,mode) + SSL * ssl + int mode + +int +SSL_set_trust(s,trust) + SSL * s + int trust + +void +SSL_set_verify_depth(s,depth) + SSL * s + int depth + +void +SSL_set_verify_result(ssl,v) + SSL * ssl + long v + +int +SSL_shutdown(s) + SSL * s + +const char * +SSL_get_version(ssl) + const SSL * ssl + +int +SSL_version(ssl) + SSL * ssl + +#if OPENSSL_VERSION_NUMBER >= 0x10100006L && !defined(LIBRESSL_VERSION_NUMBER) /* 1.1.0-pre6 */ + +int +SSL_client_version(ssl) + const SSL * ssl + +int +SSL_is_dtls(ssl) + const SSL * ssl + +#endif + +#define REM_MANUALLY_ADDED_1_09 + +X509_NAME_STACK * +SSL_load_client_CA_file(file) + const char * file + +int +SSL_add_file_cert_subjects_to_stack(stackCAs,file) + X509_NAME_STACK * stackCAs + const char * file + +#ifndef WIN32 +#ifndef VMS +#ifndef MAC_OS_pre_X + +int +SSL_add_dir_cert_subjects_to_stack(stackCAs,dir) + X509_NAME_STACK * stackCAs + const char * dir + +#endif +#endif +#endif + +int +SSL_CTX_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL) + long argl + void * argp + CRYPTO_EX_new * new_func + CRYPTO_EX_dup * dup_func + CRYPTO_EX_free * free_func + +int +SSL_CTX_set_session_id_context(ctx,sid_ctx,sid_ctx_len) + SSL_CTX * ctx + const unsigned char * sid_ctx + unsigned int sid_ctx_len + +int +SSL_set_session_id_context(ssl,sid_ctx,sid_ctx_len) + SSL * ssl + const unsigned char * sid_ctx + unsigned int sid_ctx_len + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +void +SSL_CTX_set_tmp_rsa_callback(ctx, cb) + SSL_CTX * ctx + cb_ssl_int_int_ret_RSA * cb + +void +SSL_set_tmp_rsa_callback(ssl, cb) + SSL * ssl + cb_ssl_int_int_ret_RSA * cb + +#endif + +void +SSL_CTX_set_tmp_dh_callback(ctx, dh) + SSL_CTX * ctx + cb_ssl_int_int_ret_DH * dh + +void +SSL_set_tmp_dh_callback(ssl,dh) + SSL * ssl + cb_ssl_int_int_ret_DH * dh + +int +SSL_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL) + long argl + void * argp + CRYPTO_EX_new * new_func + CRYPTO_EX_dup * dup_func + CRYPTO_EX_free * free_func + +int +SSL_SESSION_get_ex_new_index(argl,argp=NULL,new_func=NULL,dup_func=NULL,free_func=NULL) + long argl + void * argp + CRYPTO_EX_new * new_func + CRYPTO_EX_dup * dup_func + CRYPTO_EX_free * free_func + +#define REM_SEMIAUTOMATIC_MACRO_GEN_1_09 + +long +SSL_clear_num_renegotiations(ssl) + SSL * ssl + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL); + OUTPUT: + RETVAL + +long +SSL_CTX_add_extra_chain_cert(ctx,x509) + SSL_CTX * ctx + X509 * x509 + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char*)x509); + OUTPUT: + RETVAL + +void * +SSL_CTX_get_app_data(ctx) + SSL_CTX * ctx + CODE: + RETVAL = SSL_CTX_get_ex_data(ctx,0); + OUTPUT: + RETVAL + +long +SSL_CTX_get_mode(ctx) + SSL_CTX * ctx + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_MODE,0,NULL); + OUTPUT: + RETVAL + +long +SSL_CTX_get_read_ahead(ctx) + SSL_CTX * ctx + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL); + OUTPUT: + RETVAL + +long +SSL_CTX_get_session_cache_mode(ctx) + SSL_CTX * ctx + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL); + OUTPUT: + RETVAL + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +long +SSL_CTX_need_tmp_RSA(ctx) + SSL_CTX * ctx + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL); + OUTPUT: + RETVAL + +#endif + +int +SSL_CTX_set_app_data(ctx,arg) + SSL_CTX * ctx + char * arg + CODE: + RETVAL = SSL_CTX_set_ex_data(ctx,0,arg); + OUTPUT: + RETVAL + +long +SSL_CTX_set_mode(ctx,op) + SSL_CTX * ctx + long op + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_MODE,op,NULL); + OUTPUT: + RETVAL + +long +SSL_CTX_set_read_ahead(ctx,m) + SSL_CTX * ctx + long m + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL); + OUTPUT: + RETVAL + +long +SSL_CTX_set_session_cache_mode(ctx,m) + SSL_CTX * ctx + long m + CODE: + RETVAL = SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL); + OUTPUT: + RETVAL + +long +SSL_CTX_set_tmp_dh(ctx,dh) + SSL_CTX * ctx + DH * dh + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +long +SSL_CTX_set_tmp_rsa(ctx,rsa) + SSL_CTX * ctx + RSA * rsa + +#endif + +#if OPENSSL_VERSION_NUMBER > 0x10000000L && !defined OPENSSL_NO_EC + +EC_KEY * +EC_KEY_new_by_curve_name(nid) + int nid + +void +EC_KEY_free(key) + EC_KEY * key + +long +SSL_CTX_set_tmp_ecdh(ctx,ecdh) + SSL_CTX * ctx + EC_KEY * ecdh + +int +EVP_PKEY_assign_EC_KEY(pkey,key) + EVP_PKEY * pkey + EC_KEY * key + + +EC_KEY * +EC_KEY_generate_key(curve) + SV *curve; + CODE: + EC_GROUP *group = NULL; + EC_KEY *eckey = NULL; + int nid; + + RETVAL = 0; + if (SvIOK(curve)) { + nid = SvIV(curve); + } else { + nid = OBJ_sn2nid(SvPV_nolen(curve)); +#if OPENSSL_VERSION_NUMBER > 0x10002000L + if (!nid) nid = EC_curve_nist2nid(SvPV_nolen(curve)); +#endif + if (!nid) croak("unknown curve %s",SvPV_nolen(curve)); + } + + group = EC_GROUP_new_by_curve_name(nid); + if (!group) croak("unknown curve nid=%d",nid); + EC_GROUP_set_asn1_flag(group,OPENSSL_EC_NAMED_CURVE); + + eckey = EC_KEY_new(); + if ( eckey + && EC_KEY_set_group(eckey, group) + && EC_KEY_generate_key(eckey)) { + RETVAL = eckey; + } else { + if (eckey) EC_KEY_free(eckey); + } + if (group) EC_GROUP_free(group); + + OUTPUT: + RETVAL + + +#ifdef SSL_CTRL_SET_ECDH_AUTO + +long +SSL_CTX_set_ecdh_auto(ctx,onoff) + SSL_CTX * ctx + int onoff + +long +SSL_set_ecdh_auto(ssl,onoff) + SSL * ssl + int onoff + +#endif + +#ifdef SSL_CTRL_SET_CURVES_LIST + +long +SSL_CTX_set1_curves_list(ctx,list) + SSL_CTX * ctx + char * list + +long +SSL_set1_curves_list(ssl,list) + SSL * ssl + char * list + +#endif + +#if SSL_CTRL_SET_GROUPS_LIST + +long +SSL_CTX_set1_groups_list(ctx,list) + SSL_CTX * ctx + char * list + +long +SSL_set1_groups_list(ssl,list) + SSL * ssl + char * list + +#endif + + + +#endif + +void * +SSL_get_app_data(s) + SSL * s + CODE: + RETVAL = SSL_get_ex_data(s,0); + OUTPUT: + RETVAL + +int +SSL_get_cipher_bits(s,np=NULL) + SSL * s + int * np + CODE: + RETVAL = SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np); + OUTPUT: + RETVAL + +long +SSL_get_mode(ssl) + SSL * ssl + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_MODE,0,NULL); + OUTPUT: + RETVAL + +void +SSL_set_state(ssl,state) + SSL * ssl + int state + CODE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + /* not available */ +#elif defined(OPENSSL_NO_SSL_INTERN) + SSL_set_state(ssl,state); +#else + ssl->state = state; +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +long +SSL_need_tmp_RSA(ssl) + SSL * ssl + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL); + OUTPUT: + RETVAL + + +#endif + +long +SSL_num_renegotiations(ssl) + SSL * ssl + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL); + OUTPUT: + RETVAL + +void * +SSL_SESSION_get_app_data(ses) + SSL_SESSION * ses + CODE: + RETVAL = SSL_SESSION_get_ex_data(ses,0); + OUTPUT: + RETVAL + +long +SSL_session_reused(ssl) + SSL * ssl + +int +SSL_SESSION_set_app_data(s,a) + SSL_SESSION * s + void * a + CODE: + RETVAL = SSL_SESSION_set_ex_data(s,0,(char *)a); + OUTPUT: + RETVAL + +int +SSL_set_app_data(s,arg) + SSL * s + void * arg + CODE: + RETVAL = SSL_set_ex_data(s,0,(char *)arg); + OUTPUT: + RETVAL + +long +SSL_set_mode(ssl,op) + SSL * ssl + long op + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_MODE,op,NULL); + OUTPUT: + RETVAL + +int +SSL_set_pref_cipher(s,n) + SSL * s + const char * n + CODE: + RETVAL = SSL_set_cipher_list(s,n); + OUTPUT: + RETVAL + +long +SSL_set_tmp_dh(ssl,dh) + SSL * ssl + DH * dh + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +long +SSL_set_tmp_rsa(ssl,rsa) + SSL * ssl + char * rsa + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa); + OUTPUT: + RETVAL + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL + +RSA * +RSA_generate_key(bits,ee,perl_cb=&PL_sv_undef,perl_data=&PL_sv_undef) + int bits + unsigned long ee + SV* perl_cb + SV* perl_data + PREINIT: + simple_cb_data_t* cb_data = NULL; + CODE: + /* openssl 0.9.8 deprecated RSA_generate_key. */ + /* This equivalent was contributed by Brian Fraser for Android, */ + /* but was not portable to old OpenSSLs where RSA_generate_key_ex is not available. */ + /* It should now be more versatile. */ + /* as of openssl 1.1.0 it is not possible anymore to generate the BN_GENCB structure directly. */ + /* instead BN_EGNCB_new() has to be used. */ + int rc; + RSA * ret; + BIGNUM *e; + e = BN_new(); + if(!e) + croak("Net::SSLeay: RSA_generate_key perl function could not create BN structure.\n"); + BN_set_word(e, ee); + cb_data = simple_cb_data_new(perl_cb, perl_data); + + ret = RSA_new(); + if(!ret) { + simple_cb_data_free(cb_data); + BN_free(e); + croak("Net::SSLeay: RSA_generate_key perl function could not create RSA structure.\n"); + } +#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) + BN_GENCB *new_cb; + new_cb = BN_GENCB_new(); + if(!new_cb) { + simple_cb_data_free(cb_data); + BN_free(e); + RSA_free(ret); + croak("Net::SSLeay: RSA_generate_key perl function could not create BN_GENCB structure.\n"); + } + BN_GENCB_set_old(new_cb, ssleay_RSA_generate_key_cb_invoke, cb_data); + rc = RSA_generate_key_ex(ret, bits, e, new_cb); + BN_GENCB_free(new_cb); +#else + BN_GENCB new_cb; + BN_GENCB_set_old(&new_cb, ssleay_RSA_generate_key_cb_invoke, cb_data); + rc = RSA_generate_key_ex(ret, bits, e, &new_cb); +#endif + simple_cb_data_free(cb_data); + BN_free(e); + if (rc == -1 || ret == NULL) { + if (ret) RSA_free(ret); + croak("Net::SSLeay: Couldn't generate RSA key"); + } + e = NULL; + RETVAL = ret; + OUTPUT: + RETVAL + +#else + +RSA * +RSA_generate_key(bits,e,perl_cb=&PL_sv_undef,perl_data=&PL_sv_undef) + int bits + unsigned long e + SV* perl_cb + SV* perl_data + PREINIT: + simple_cb_data_t* cb = NULL; + CODE: + cb = simple_cb_data_new(perl_cb, perl_data); + RETVAL = RSA_generate_key(bits, e, ssleay_RSA_generate_key_cb_invoke, cb); + simple_cb_data_free(cb); + OUTPUT: + RETVAL + +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +void +RSA_get_key_parameters(rsa) + RSA * rsa +PPCODE: +{ + /* Caution: returned list consists of SV pointers to BIGNUMs, which would need to be blessed as Crypt::OpenSSL::Bignum for further use */ + XPUSHs(bn2sv(rsa->n)); + XPUSHs(bn2sv(rsa->e)); + XPUSHs(bn2sv(rsa->d)); + XPUSHs(bn2sv(rsa->p)); + XPUSHs(bn2sv(rsa->q)); + XPUSHs(bn2sv(rsa->dmp1)); + XPUSHs(bn2sv(rsa->dmq1)); + XPUSHs(bn2sv(rsa->iqmp)); +} + +#endif + +void +RSA_free(r) + RSA * r + +X509 * +X509_new() + +void +X509_free(a) + X509 * a + +X509_CRL * +d2i_X509_CRL_bio(BIO *bp,void *unused=NULL) + +X509_REQ * +d2i_X509_REQ_bio(BIO *bp,void *unused=NULL) + +X509 * +d2i_X509_bio(BIO *bp,void *unused=NULL) + +DH * +PEM_read_bio_DHparams(bio,x=NULL,cb=NULL,u=NULL) + BIO * bio + void * x + pem_password_cb * cb + void * u + +X509_CRL * +PEM_read_bio_X509_CRL(bio,x=NULL,cb=NULL,u=NULL) + BIO * bio + void * x + pem_password_cb * cb + void * u + +X509 * +PEM_read_bio_X509(BIO *bio,void *x=NULL,void *cb=NULL,void *u=NULL) + +STACK_OF(X509_INFO) * +PEM_X509_INFO_read_bio(bio, stack=NULL, cb=NULL, u=NULL) + BIO * bio + STACK_OF(X509_INFO) * stack + pem_password_cb * cb + void * u + +int +sk_X509_INFO_num(stack) + STACK_OF(X509_INFO) * stack + +X509_INFO * +sk_X509_INFO_value(stack, index) + const STACK_OF(X509_INFO) * stack + int index + +void +sk_X509_INFO_free(stack) + STACK_OF(X509_INFO) * stack + +STACK_OF(X509) * +sk_X509_new_null() + +void +sk_X509_free(stack) + STACK_OF(X509) * stack + +int +sk_X509_push(stack, data) + STACK_OF(X509) * stack + X509 * data + +X509 * +P_X509_INFO_get_x509(info) + X509_INFO * info + CODE: + RETVAL = info->x509; + OUTPUT: + RETVAL + +X509_REQ * +PEM_read_bio_X509_REQ(BIO *bio,void *x=NULL,pem_password_cb *cb=NULL,void *u=NULL) + +EVP_PKEY * +PEM_read_bio_PrivateKey(bio,perl_cb=&PL_sv_undef,perl_data=&PL_sv_undef) + BIO *bio + SV* perl_cb + SV* perl_data + PREINIT: + simple_cb_data_t* cb = NULL; + CODE: + RETVAL = 0; + if (SvOK(perl_cb)) { + /* setup our callback */ + cb = simple_cb_data_new(perl_cb, perl_data); + RETVAL = PEM_read_bio_PrivateKey(bio, NULL, pem_password_cb_invoke, (void*)cb); + simple_cb_data_free(cb); + } + else if (!SvOK(perl_cb) && SvOK(perl_data) && SvPOK(perl_data)) { + /* use perl_data as the password */ + RETVAL = PEM_read_bio_PrivateKey(bio, NULL, NULL, SvPVX(perl_data)); + } + else if (!SvOK(perl_cb) && !SvOK(perl_data)) { + /* will trigger default password callback */ + RETVAL = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + } + OUTPUT: + RETVAL + +void +DH_free(dh) + DH * dh + +long +SSL_total_renegotiations(ssl) + SSL * ssl + CODE: + RETVAL = SSL_ctrl(ssl,SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL); + OUTPUT: + RETVAL + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +void +SSL_SESSION_get_master_key(s) + SSL_SESSION * s + PREINIT: + size_t master_key_length; + unsigned char* master_key; + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + master_key_length = SSL_SESSION_get_master_key(s, 0, 0); /* get the length */ + New(0, master_key, master_key_length, unsigned char); + SSL_SESSION_get_master_key(s, master_key, master_key_length); + sv_setpvn(ST(0), (const char*)master_key, master_key_length); + Safefree(master_key); + +#else +void +SSL_SESSION_get_master_key(s) + SSL_SESSION * s + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + sv_setpvn(ST(0), (const char*)s->master_key, s->master_key_length); + +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +void +SSL_SESSION_set_master_key(s,key) + SSL_SESSION * s + PREINIT: + STRLEN len; + INPUT: + char * key = SvPV(ST(1), len); + CODE: + memcpy(s->master_key, key, len); + s->master_key_length = len; + +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) + +void +SSL_get_client_random(s) + SSL * s + PREINIT: + size_t random_length; + unsigned char* random_data; + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + random_length = SSL_get_client_random(s, 0, 0); /* get the length */ + New(0, random_data, random_length, unsigned char); + SSL_get_client_random(s, random_data, random_length); + sv_setpvn(ST(0), (const char*)random_data, random_length); + Safefree(random_data); + +#else + +void +SSL_get_client_random(s) + SSL * s + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + sv_setpvn(ST(0), (const char*)s->s3->client_random, SSL3_RANDOM_SIZE); + +#endif + +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) + +void +SSL_get_server_random(s) + SSL * s + PREINIT: + size_t random_length; + unsigned char* random_data; + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + random_length = SSL_get_server_random(s, 0, 0); /* get the length */ + New(0, random_data, random_length, unsigned char); + SSL_get_server_random(s, random_data, random_length); + sv_setpvn(ST(0), (const char*)random_data, random_length); + Safefree(random_data); + +#else + +void +SSL_get_server_random(s) + SSL * s + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ + sv_setpvn(ST(0), (const char*)s->s3->server_random, SSL3_RANDOM_SIZE); + +#endif + +int +SSL_get_keyblock_size(s) + SSL * s + CODE: +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) + const SSL_CIPHER *ssl_cipher; + int cipher = NID_undef, digest = NID_undef, mac_secret_size = 0; + const EVP_CIPHER *c = NULL; + const EVP_MD *h = NULL; + + ssl_cipher = SSL_get_current_cipher(s); + if (ssl_cipher) + cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher); + if (cipher != NID_undef) + c = EVP_get_cipherbynid(cipher); + + if (ssl_cipher) + digest = SSL_CIPHER_get_digest_nid(ssl_cipher); + if (digest != NID_undef) /* No digest if e.g., AEAD cipher */ + h = EVP_get_digestbynid(digest); + if (h) + mac_secret_size = EVP_MD_size(h); + + RETVAL = -1; + if (c) + RETVAL = 2 * (EVP_CIPHER_key_length(c) + mac_secret_size + + EVP_CIPHER_iv_length(c)); +#else + if (s == NULL || + s->enc_read_ctx == NULL || + s->enc_read_ctx->cipher == NULL || + s->read_hash == NULL) + { + RETVAL = -1; + } + else + { + const EVP_CIPHER *c; + const EVP_MD *h; + int md_size = -1; + c = s->enc_read_ctx->cipher; +#if OPENSSL_VERSION_NUMBER >= 0x10001000L + h = NULL; + if (s->s3) + md_size = s->s3->tmp.new_mac_secret_size; +#elif OPENSSL_VERSION_NUMBER >= 0x00909000L + h = EVP_MD_CTX_md(s->read_hash); + md_size = EVP_MD_size(h); +#else + h = s->read_hash; + md_size = EVP_MD_size(h); +#endif + /* No digest if e.g., AEAD cipher */ + RETVAL = (md_size >= 0) ? (2 * (EVP_CIPHER_key_length(c) + + md_size + + EVP_CIPHER_iv_length(c))) + : -1; + } +#endif + + OUTPUT: + RETVAL + + + +#if defined(SSL_F_SSL_SET_HELLO_EXTENSION) +int +SSL_set_hello_extension(s, type, data) + SSL * s + int type + PREINIT: + STRLEN len; + INPUT: + char * data = SvPV( ST(2), len); + CODE: + RETVAL = SSL_set_hello_extension(s, type, data, len); + OUTPUT: + RETVAL + +#endif + +#if defined(SSL_F_SSL_SET_HELLO_EXTENSION) || defined(SSL_F_SSL_SET_SESSION_TICKET_EXT) + +void +SSL_set_session_secret_cb(s,callback=&PL_sv_undef,data=&PL_sv_undef) + SSL * s + SV * callback + SV * data + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_set_session_secret_cb(s, NULL, NULL); + cb_data_advanced_put(s, "ssleay_session_secret_cb!!func", NULL); + cb_data_advanced_put(s, "ssleay_session_secret_cb!!data", NULL); + } + else { + cb_data_advanced_put(s, "ssleay_session_secret_cb!!func", newSVsv(callback)); + cb_data_advanced_put(s, "ssleay_session_secret_cb!!data", newSVsv(data)); + SSL_set_session_secret_cb(s, (tls_session_secret_cb_fn)&ssleay_session_secret_cb_invoke, s); + } + +#endif + +#ifdef NET_SSLEAY_CAN_PSK_CLIENT_CALLBACK + +void +SSL_set_psk_client_callback(s,callback=&PL_sv_undef) + SSL * s + SV * callback + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_set_psk_client_callback(s, NULL); + cb_data_advanced_put(s, "ssleay_set_psk_client_callback!!func", NULL); + } + else { + cb_data_advanced_put(s, "ssleay_set_psk_client_callback!!func", newSVsv(callback)); + SSL_set_psk_client_callback(s, ssleay_set_psk_client_callback_invoke); + } + +void +SSL_CTX_set_psk_client_callback(ctx,callback=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_psk_client_callback(ctx, NULL); + cb_data_advanced_put(ctx, "ssleay_ctx_set_psk_client_callback!!func", NULL); + } + else { + cb_data_advanced_put(ctx, "ssleay_ctx_set_psk_client_callback!!func", newSVsv(callback)); + SSL_CTX_set_psk_client_callback(ctx, ssleay_ctx_set_psk_client_callback_invoke); + } + +#endif + +#ifdef NET_SSLEAY_CAN_TICKET_KEY_CB + +void +SSL_CTX_set_tlsext_ticket_getkey_cb(ctx,callback=&PL_sv_undef,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_tlsext_ticket_key_cb(ctx, NULL); + cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!func", NULL); + cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!data", NULL); + } + else { + cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "tlsext_ticket_key_cb!!data", newSVsv(data)); + SSL_CTX_set_tlsext_ticket_key_cb(ctx, &tlsext_ticket_key_cb_invoke); + } + + +#endif + + +#if OPENSSL_VERSION_NUMBER < 0x0090700fL +#define REM11 "NOTE: before 0.9.7" + +int EVP_add_digest(EVP_MD *digest) + +#else + +int EVP_add_digest(const EVP_MD *digest) + +#endif + +#ifndef OPENSSL_NO_SHA + +const EVP_MD *EVP_sha1() + +#endif +#if !defined(OPENSSL_NO_SHA256) && OPENSSL_VERSION_NUMBER >= 0x0090800fL + +const EVP_MD *EVP_sha256() + +#endif +#if !defined(OPENSSL_NO_SHA512) && OPENSSL_VERSION_NUMBER >= 0x0090800fL + +const EVP_MD *EVP_sha512() + +#endif +void OpenSSL_add_all_digests() + +const EVP_MD * EVP_get_digestbyname(const char *name) + +int EVP_MD_type(const EVP_MD *md) + +int EVP_MD_size(const EVP_MD *md) + +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + +SV* +P_EVP_MD_list_all() + INIT: + AV * results; + CODE: + results = (AV *)sv_2mortal((SV *)newAV()); + EVP_MD_do_all_sorted(handler_list_md_fn, results); + RETVAL = newRV((SV *)results); + OUTPUT: + RETVAL + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL +#define REM16 "NOTE: requires 0.9.7+" + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) + +EVP_MD_CTX *EVP_MD_CTX_create() + +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) + +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) + +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) + +void +EVP_DigestUpdate(ctx,data) + PREINIT: + STRLEN len; + INPUT: + EVP_MD_CTX *ctx = INT2PTR(EVP_MD_CTX *, SvIV(ST(0))); + unsigned char *data = (unsigned char *) SvPV(ST(1), len); + CODE: + XSRETURN_IV(EVP_DigestUpdate(ctx,data,len)); + +void +EVP_DigestFinal(ctx) + EVP_MD_CTX *ctx + INIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + CODE: + if (EVP_DigestFinal(ctx,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + else + XSRETURN_UNDEF; + +void +EVP_DigestFinal_ex(ctx) + EVP_MD_CTX *ctx + INIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + CODE: + if (EVP_DigestFinal_ex(ctx,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + else + XSRETURN_UNDEF; + +void +EVP_Digest(...) + PREINIT: + STRLEN len; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + INPUT: + unsigned char *data = (unsigned char *) SvPV(ST(0), len); + EVP_MD *type = INT2PTR(EVP_MD *, SvIV(ST(1))); + ENGINE *impl = (items>2 && SvOK(ST(2))) ? INT2PTR(ENGINE *, SvIV(ST(2))) : NULL; + CODE: + if (EVP_Digest(data,len,md,&md_size,type,impl)) + XSRETURN_PVN((char *)md, md_size); + else + XSRETURN_UNDEF; + +#endif + +const EVP_CIPHER * +EVP_get_cipherbyname(const char *name) + +void +OpenSSL_add_all_algorithms() + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + +void +OPENSSL_add_all_algorithms_noconf() + +void +OPENSSL_add_all_algorithms_conf() + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + +int +SSL_CTX_set1_param(ctx, vpm) + SSL_CTX * ctx + X509_VERIFY_PARAM *vpm + +int +SSL_set1_param(ctx, vpm) + SSL * ctx + X509_VERIFY_PARAM *vpm + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL + +X509_VERIFY_PARAM * +X509_VERIFY_PARAM_new() + +void +X509_VERIFY_PARAM_free(param) + X509_VERIFY_PARAM *param + +int +X509_VERIFY_PARAM_inherit(to, from) + X509_VERIFY_PARAM *to + X509_VERIFY_PARAM *from + +int +X509_VERIFY_PARAM_set1(to, from) + X509_VERIFY_PARAM *to + X509_VERIFY_PARAM *from + +int +X509_VERIFY_PARAM_set1_name(param, name) + X509_VERIFY_PARAM *param + const char *name + +int +X509_VERIFY_PARAM_set_flags(param, flags) + X509_VERIFY_PARAM *param + unsigned long flags + +#if OPENSSL_VERSION_NUMBER >= 0x0090801fL +#define REM13 "NOTE: requires 0.9.8a+" + +int +X509_VERIFY_PARAM_clear_flags(param, flags) + X509_VERIFY_PARAM *param + unsigned long flags + +unsigned long +X509_VERIFY_PARAM_get_flags(param) + X509_VERIFY_PARAM *param + +#endif + +int +X509_VERIFY_PARAM_set_purpose(param, purpose) + X509_VERIFY_PARAM *param + int purpose + +int +X509_VERIFY_PARAM_set_trust(param, trust) + X509_VERIFY_PARAM *param + int trust + +void +X509_VERIFY_PARAM_set_depth(param, depth) + X509_VERIFY_PARAM *param + int depth + +void +X509_VERIFY_PARAM_set_time(param, t) + X509_VERIFY_PARAM *param + time_t t + +int +X509_VERIFY_PARAM_add0_policy(param, policy) + X509_VERIFY_PARAM *param + ASN1_OBJECT *policy + +int +X509_VERIFY_PARAM_set1_policies(param, policies) + X509_VERIFY_PARAM *param + STACK_OF(ASN1_OBJECT) *policies + +int +X509_VERIFY_PARAM_get_depth(param) + X509_VERIFY_PARAM *param + +int +X509_VERIFY_PARAM_add0_table(param) + X509_VERIFY_PARAM *param + +const X509_VERIFY_PARAM * +X509_VERIFY_PARAM_lookup(name) + const char *name + +void +X509_VERIFY_PARAM_table_cleanup() + +#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) /* OpenSSL 1.0.2, LibreSSL 2.7.0 */ + +X509_VERIFY_PARAM * +SSL_CTX_get0_param(ctx) + SSL_CTX * ctx + +X509_VERIFY_PARAM * +SSL_get0_param(ssl) + SSL * ssl + +int +X509_VERIFY_PARAM_set1_host(param, name) + X509_VERIFY_PARAM *param + PREINIT: + STRLEN namelen; + INPUT: + const char * name = SvPV(ST(1), namelen); + CODE: + RETVAL = X509_VERIFY_PARAM_set1_host(param, name, namelen); + OUTPUT: + RETVAL + +int +X509_VERIFY_PARAM_add1_host(param, name) + X509_VERIFY_PARAM *param + PREINIT: + STRLEN namelen; + INPUT: + const char * name = SvPV(ST(1), namelen); + CODE: + RETVAL = X509_VERIFY_PARAM_add1_host(param, name, namelen); + OUTPUT: + RETVAL + +void +X509_VERIFY_PARAM_set_hostflags(param, flags) + X509_VERIFY_PARAM *param + unsigned int flags + +char * +X509_VERIFY_PARAM_get0_peername(param) + X509_VERIFY_PARAM *param + +int +X509_VERIFY_PARAM_set1_email(param, email) + X509_VERIFY_PARAM *param + PREINIT: + STRLEN emaillen; + INPUT: + const char * email = SvPV(ST(1), emaillen); + CODE: + RETVAL = X509_VERIFY_PARAM_set1_email(param, email, emaillen); + OUTPUT: + RETVAL + +int +X509_VERIFY_PARAM_set1_ip(param, ip) + X509_VERIFY_PARAM *param + PREINIT: + STRLEN iplen; + INPUT: + const unsigned char * ip = (const unsigned char *)SvPV(ST(1), iplen); + CODE: + RETVAL = X509_VERIFY_PARAM_set1_ip(param, ip, iplen); + OUTPUT: + RETVAL + +int +X509_VERIFY_PARAM_set1_ip_asc(param, ipasc) + X509_VERIFY_PARAM *param + const char *ipasc + +#endif /* OpenSSL 1.0.2, LibreSSL 2.7.0 */ + +void +X509_policy_tree_free(tree) + X509_POLICY_TREE *tree + +int +X509_policy_tree_level_count(tree) + X509_POLICY_TREE *tree + +X509_POLICY_LEVEL * +X509_policy_tree_get0_level(tree, i) + X509_POLICY_TREE *tree + int i + +STACK_OF(X509_POLICY_NODE) * +X509_policy_tree_get0_policies(tree) + X509_POLICY_TREE *tree + +STACK_OF(X509_POLICY_NODE) * +X509_policy_tree_get0_user_policies(tree) + X509_POLICY_TREE *tree + +int +X509_policy_level_node_count(level) + X509_POLICY_LEVEL *level + +X509_POLICY_NODE * +X509_policy_level_get0_node(level, i) + X509_POLICY_LEVEL *level + int i + +const ASN1_OBJECT * +X509_policy_node_get0_policy(node) + const X509_POLICY_NODE *node + +STACK_OF(POLICYQUALINFO) * +X509_policy_node_get0_qualifiers(node) + X509_POLICY_NODE *node + +const X509_POLICY_NODE * +X509_policy_node_get0_parent(node) + const X509_POLICY_NODE *node + +#endif + +ASN1_OBJECT * +OBJ_dup(o) + ASN1_OBJECT *o + +ASN1_OBJECT * +OBJ_nid2obj(n) + int n + +const char * +OBJ_nid2ln(n) + int n + +const char * +OBJ_nid2sn(n) + int n + +int +OBJ_obj2nid(o) + ASN1_OBJECT *o + +ASN1_OBJECT * +OBJ_txt2obj(s, no_name=0) + const char *s + int no_name + +void +OBJ_obj2txt(a, no_name=0) + ASN1_OBJECT *a + int no_name + PREINIT: + char buf[100]; /* openssl doc: a buffer length of 80 should be more than enough to handle any OID encountered in practice */ + int len; + CODE: + len = OBJ_obj2txt(buf, sizeof(buf), a, no_name); + ST(0) = sv_newmortal(); + sv_setpvn(ST(0), buf, len); + +#if OPENSSL_VERSION_NUMBER < 0x0090700fL +#define REM14 "NOTE: before 0.9.7" + +int +OBJ_txt2nid(s) + char *s + +#else + +int +OBJ_txt2nid(s) + const char *s + +#endif + +int +OBJ_ln2nid(s) + const char *s + +int +OBJ_sn2nid(s) + const char *s + +int +OBJ_cmp(a, b) + ASN1_OBJECT *a + ASN1_OBJECT *b + +#if OPENSSL_VERSION_NUMBER >= 0x0090700fL + +void +X509_pubkey_digest(data,type) + const X509 *data + const EVP_MD *type + PREINIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + PPCODE: + if (X509_pubkey_digest(data,type,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + else + XSRETURN_UNDEF; + +#endif + +void +X509_digest(data,type) + const X509 *data + const EVP_MD *type + PREINIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + PPCODE: + if (X509_digest(data,type,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + XSRETURN_UNDEF; + +void +X509_CRL_digest(data,type) + const X509_CRL *data + const EVP_MD *type + PREINIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + PPCODE: + if (X509_CRL_digest(data,type,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + XSRETURN_UNDEF; + +void +X509_REQ_digest(data,type) + const X509_REQ *data + const EVP_MD *type + PREINIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + PPCODE: + if (X509_REQ_digest(data,type,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + XSRETURN_UNDEF; + +void +X509_NAME_digest(data,type) + const X509_NAME *data + const EVP_MD *type + PREINIT: + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_size; + PPCODE: + if (X509_NAME_digest(data,type,md,&md_size)) + XSRETURN_PVN((char *)md, md_size); + XSRETURN_UNDEF; + +unsigned long +X509_subject_name_hash(X509 *x) + +unsigned long +X509_issuer_name_hash(X509 *a) + +unsigned long +X509_issuer_and_serial_hash(X509 *a) + +ASN1_OBJECT * +P_X509_get_signature_alg(x) + X509 * x + CODE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + RETVAL = (X509_get0_tbs_sigalg(x)->algorithm); +#else + RETVAL = (x->cert_info->signature->algorithm); +#endif + OUTPUT: + RETVAL + +ASN1_OBJECT * +P_X509_get_pubkey_alg(x) + X509 * x + PREINIT: + CODE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + { + X509_ALGOR * algor; + X509_PUBKEY_get0_param(0, 0, 0, &algor, X509_get_X509_PUBKEY(x)); + RETVAL = (algor->algorithm); + } +#else + RETVAL = (x->cert_info->key->algor->algorithm); +#endif + OUTPUT: + RETVAL + +void +X509_get_X509_PUBKEY(x) + const X509 *x + PPCODE: + X509_PUBKEY *pkey; + STRLEN len; + unsigned char *pc, *pi; + if (!(pkey = X509_get_X509_PUBKEY(x))) croak("invalid certificate"); + if (!(len = i2d_X509_PUBKEY(pkey, NULL))) croak("invalid certificate public key"); + Newx(pc,len,unsigned char); + if (!pc) croak("out of memory"); + pi = pc; + i2d_X509_PUBKEY(pkey, &pi); + if (pi-pc != len) croak("invalid encoded length"); + XPUSHs(sv_2mortal(newSVpv((char*)pc,len))); + Safefree(pc); + +#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_NEXTPROTONEG) && !defined(LIBRESSL_VERSION_NUMBER) + +int +SSL_CTX_set_next_protos_advertised_cb(ctx,callback,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + RETVAL = 1; + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_next_protos_advertised_cb(ctx, NULL, NULL); + cb_data_advanced_put(ctx, "next_protos_advertised_cb!!func", NULL); + cb_data_advanced_put(ctx, "next_protos_advertised_cb!!data", NULL); + PR1("SSL_CTX_set_next_protos_advertised_cb - undef\n"); + } + else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVAV)) { + /* callback param array ref like ['proto1','proto2'] */ + cb_data_advanced_put(ctx, "next_protos_advertised_cb!!func", NULL); + cb_data_advanced_put(ctx, "next_protos_advertised_cb!!data", newSVsv(callback)); + SSL_CTX_set_next_protos_advertised_cb(ctx, next_protos_advertised_cb_invoke, ctx); + PR2("SSL_CTX_set_next_protos_advertised_cb - simple ctx=%p\n",ctx); + } + else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) { + cb_data_advanced_put(ctx, "next_protos_advertised_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "next_protos_advertised_cb!!data", newSVsv(data)); + SSL_CTX_set_next_protos_advertised_cb(ctx, next_protos_advertised_cb_invoke, ctx); + PR2("SSL_CTX_set_next_protos_advertised_cb - advanced ctx=%p\n",ctx); + } + else { + RETVAL = 0; + } + OUTPUT: + RETVAL + +int +SSL_CTX_set_next_proto_select_cb(ctx,callback,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + RETVAL = 1; + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_next_proto_select_cb(ctx, NULL, NULL); + cb_data_advanced_put(ctx, "next_proto_select_cb!!func", NULL); + cb_data_advanced_put(ctx, "next_proto_select_cb!!data", NULL); + PR1("SSL_CTX_set_next_proto_select_cb - undef\n"); + } + else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVAV)) { + /* callback param array ref like ['proto1','proto2'] */ + cb_data_advanced_put(ctx, "next_proto_select_cb!!func", NULL); + cb_data_advanced_put(ctx, "next_proto_select_cb!!data", newSVsv(callback)); + SSL_CTX_set_next_proto_select_cb(ctx, next_proto_select_cb_invoke, ctx); + PR2("SSL_CTX_set_next_proto_select_cb - simple ctx=%p\n",ctx); + } + else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) { + cb_data_advanced_put(ctx, "next_proto_select_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "next_proto_select_cb!!data", newSVsv(data)); + SSL_CTX_set_next_proto_select_cb(ctx, next_proto_select_cb_invoke, ctx); + PR2("SSL_CTX_set_next_proto_select_cb - advanced ctx=%p\n",ctx); + } + else { + RETVAL = 0; + } + OUTPUT: + RETVAL + +void +P_next_proto_negotiated(s) + const SSL *s + PREINIT: + const unsigned char *data; + unsigned int len; + PPCODE: + SSL_get0_next_proto_negotiated(s, &data, &len); + XPUSHs(sv_2mortal(newSVpv((char *)data, len))); + +void +P_next_proto_last_status(s) + const SSL *s + PPCODE: + XPUSHs(sv_2mortal(newSVsv(cb_data_advanced_get((void*)s, "next_proto_select_cb!!last_status")))); + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + +#if !defined(OPENSSL_NO_TLSEXT) + +int +SSL_set_tlsext_status_type(SSL *ssl,int cmd) + +long +SSL_set_tlsext_status_ocsp_resp(ssl,staple) + SSL * ssl + PREINIT: + char * p; + STRLEN staplelen; + INPUT: + char * staple = SvPV( ST(1), staplelen); + CODE: + /* OpenSSL will free the memory */ + New(0, p, staplelen, char); + memcpy(p, staple, staplelen); + RETVAL = SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,staplelen,(void *)p); + OUTPUT: + RETVAL + +int +SSL_CTX_set_tlsext_status_cb(ctx,callback,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + RETVAL = 1; + if (callback==NULL || !SvOK(callback)) { + cb_data_advanced_put(ctx, "tlsext_status_cb!!func", NULL); + cb_data_advanced_put(ctx, "tlsext_status_cb!!data", NULL); + SSL_CTX_set_tlsext_status_cb(ctx, NULL); + } else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) { + cb_data_advanced_put(ctx, "tlsext_status_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "tlsext_status_cb!!data", newSVsv(data)); + SSL_CTX_set_tlsext_status_cb(ctx, tlsext_status_cb_invoke); + } else { + croak("argument must be code reference"); + } + OUTPUT: + RETVAL + +int +SSL_set_session_ticket_ext_cb(ssl,callback,data=&PL_sv_undef) + SSL * ssl + SV * callback + SV * data + CODE: + RETVAL = 1; + if (callback==NULL || !SvOK(callback)) { + cb_data_advanced_put(ssl, "session_ticket_ext_cb!!func", NULL); + cb_data_advanced_put(ssl, "session_ticket_ext_cb!!data", NULL); + SSL_set_session_ticket_ext_cb(ssl, NULL, NULL); + } else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) { + cb_data_advanced_put(ssl, "session_ticket_ext_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ssl, "session_ticket_ext_cb!!data", newSVsv(data)); + SSL_set_session_ticket_ext_cb(ssl, (tls_session_ticket_ext_cb_fn)&session_ticket_ext_cb_invoke, ssl); + } else { + croak("argument must be code reference"); + } + OUTPUT: + RETVAL + +int +SSL_set_session_ticket_ext(ssl,ticket) + SSL *ssl + PREINIT: + unsigned char * p; + STRLEN ticketlen; + INPUT: + unsigned char * ticket = (unsigned char *)SvPV( ST(1), ticketlen); + CODE: + RETVAL = 0; + if (ticketlen > 0) { + Newx(p, ticketlen, unsigned char); + if (!p) + croak("Net::SSLeay: set_session_ticket_ext could not allocate memory.\n"); + memcpy(p, ticket, ticketlen); + RETVAL = SSL_set_session_ticket_ext(ssl, p, ticketlen); + Safefree(p); + } + OUTPUT: + RETVAL + +#endif + +OCSP_RESPONSE * +d2i_OCSP_RESPONSE(pv) + SV *pv + CODE: + RETVAL = NULL; + if (SvPOK(pv)) { + const unsigned char *p; + STRLEN len; + p = (unsigned char*)SvPV(pv,len); + RETVAL = d2i_OCSP_RESPONSE(NULL,&p,len); + } + OUTPUT: + RETVAL + +void +i2d_OCSP_RESPONSE(r) + OCSP_RESPONSE * r + PPCODE: + STRLEN len; + unsigned char *pc,*pi; + if (!(len = i2d_OCSP_RESPONSE(r,NULL))) croak("invalid OCSP response"); + Newx(pc,len,unsigned char); + if (!pc) croak("out of memory"); + pi = pc; + i2d_OCSP_RESPONSE(r,&pi); + XPUSHs(sv_2mortal(newSVpv((char*)pc,len))); + Safefree(pc); + +void +OCSP_RESPONSE_free(r) + OCSP_RESPONSE * r + + +OCSP_REQUEST * +d2i_OCSP_REQUEST(pv) + SV *pv + CODE: + RETVAL = NULL; + if (SvPOK(pv)) { + const unsigned char *p; + STRLEN len; + p = (unsigned char*)SvPV(pv,len); + RETVAL = d2i_OCSP_REQUEST(NULL,&p,len); + } + OUTPUT: + RETVAL + +void +i2d_OCSP_REQUEST(r) + OCSP_REQUEST * r + PPCODE: + STRLEN len; + unsigned char *pc,*pi; + if (!(len = i2d_OCSP_REQUEST(r,NULL))) croak("invalid OCSP request"); + Newx(pc,len,unsigned char); + if (!pc) croak("out of memory"); + pi = pc; + i2d_OCSP_REQUEST(r,&pi); + XPUSHs(sv_2mortal(newSVpv((char*)pc,len))); + Safefree(pc); + + +void +OCSP_REQUEST_free(r) + OCSP_REQUEST * r + + +const char * +OCSP_response_status_str(long status) + +long +OCSP_response_status(OCSP_RESPONSE *r) + +void +SSL_OCSP_cert2ids(ssl,...) + SSL *ssl + PPCODE: + SSL_CTX *ctx; + X509_STORE *store; + STACK_OF(X509) *chain; + X509 *cert,*issuer; + OCSP_CERTID *id; + int i; + STRLEN len; + unsigned char *pi; + + if (!ssl) croak("not a SSL object"); + ctx = SSL_get_SSL_CTX(ssl); + if (!ctx) croak("invalid SSL object - no context"); + store = SSL_CTX_get_cert_store(ctx); + chain = SSL_get_peer_cert_chain(ssl); + + for(i=0;i= 0) + sir = OCSP_resp_get0(bsr,first); + } + + if (sir) + { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + status = OCSP_single_get0_status(sir, &revocationReason, &revocationTime, &thisupdate, &nextupdate); +#else + status = sir->certStatus->type; + if (status == V_OCSP_CERTSTATUS_REVOKED) + revocationTime = sir->certStatus->value.revoked->revocationTime; + thisupdate = sir->thisUpdate; + nextupdate = sir->nextUpdate; +#endif + if (status == V_OCSP_CERTSTATUS_REVOKED) { + error = "certificate status is revoked"; + } else if (status != V_OCSP_CERTSTATUS_GOOD) { + error = "certificate status is unknown"; + } + else if (!OCSP_check_validity(thisupdate, nextupdate, 0, -1)) { + error = "response not yet valid or expired"; + } + } else { + error = "cannot find entry for certificate in OCSP response"; + } + + end: + if (want_array) { + AV *idav = newAV(); + if (!idsv) { + /* getall: create new SV with OCSP_CERTID */ + unsigned char *pi,*pc; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + int len = i2d_OCSP_CERTID(OCSP_SINGLERESP_get0_id(sir),NULL); +#else + int len = i2d_OCSP_CERTID(sir->certId,NULL); +#endif + if(!len) continue; + Newx(pc,len,unsigned char); + if (!pc) croak("out of memory"); + pi = pc; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) + i2d_OCSP_CERTID(OCSP_SINGLERESP_get0_id(sir),&pi); +#else + i2d_OCSP_CERTID(sir->certId,&pi); +#endif + idsv = newSVpv((char*)pc,len); + Safefree(pc); + } else { + /* reuse idsv from ST(..), but increment refcount */ + idsv = SvREFCNT_inc(idsv); + } + av_push(idav, idsv); + av_push(idav, error ? newSVpv(error,0) : newSV(0)); + if (sir) { + HV *details = newHV(); + av_push(idav,newRV_noinc((SV*)details)); + hv_store(details,"statusType",10, + newSViv(status),0); + if (nextupdate) hv_store(details,"nextUpdate",10, + newSViv(ASN1_TIME_timet(nextupdate)),0); + if (thisupdate) hv_store(details,"thisUpdate",10, + newSViv(ASN1_TIME_timet(thisupdate)),0); + if (status == V_OCSP_CERTSTATUS_REVOKED) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + OCSP_REVOKEDINFO *rev = sir->certStatus->value.revoked; + revocationReason = ASN1_ENUMERATED_get(rev->revocationReason); +#endif + hv_store(details,"revocationTime",14,newSViv(ASN1_TIME_timet(revocationTime)),0); + hv_store(details,"revocationReason",16,newSViv(revocationReason),0); + hv_store(details,"revocationReason_str",20,newSVpv( + OCSP_crl_reason_str(revocationReason),0),0); + } + } + XPUSHs(sv_2mortal(newRV_noinc((SV*)idav))); + } else if (!error) { + /* compute lowest nextUpdate */ + time_t nu = ASN1_TIME_timet(nextupdate); + if (!nextupd || nextupd>nu) nextupd = nu; + } + + if (certid) OCSP_CERTID_free(certid); + if (error && !want_array) { + OCSP_BASICRESP_free(bsr); + croak("%s", error); + } + } + OCSP_BASICRESP_free(bsr); + if (!want_array) + XPUSHs(sv_2mortal(newSViv(nextupd))); + + + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_TLSEXT) + +int +SSL_CTX_set_alpn_select_cb(ctx,callback,data=&PL_sv_undef) + SSL_CTX * ctx + SV * callback + SV * data + CODE: + RETVAL = 1; + if (callback==NULL || !SvOK(callback)) { + SSL_CTX_set_alpn_select_cb(ctx, NULL, NULL); + cb_data_advanced_put(ctx, "alpn_select_cb!!func", NULL); + cb_data_advanced_put(ctx, "alpn_select_cb!!data", NULL); + PR1("SSL_CTX_set_alpn_select_cb - undef\n"); + } + else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVAV)) { + /* callback param array ref like ['proto1','proto2'] */ + cb_data_advanced_put(ctx, "alpn_select_cb!!func", NULL); + cb_data_advanced_put(ctx, "alpn_select_cb!!data", newSVsv(callback)); + SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb_invoke, ctx); + PR2("SSL_CTX_set_alpn_select_cb - simple ctx=%p\n",ctx); + } + else if (SvROK(callback) && (SvTYPE(SvRV(callback)) == SVt_PVCV)) { + cb_data_advanced_put(ctx, "alpn_select_cb!!func", newSVsv(callback)); + cb_data_advanced_put(ctx, "alpn_select_cb!!data", newSVsv(data)); + SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb_invoke, ctx); + PR2("SSL_CTX_set_alpn_select_cb - advanced ctx=%p\n",ctx); + } + else { + RETVAL = 0; + } + OUTPUT: + RETVAL + +int +SSL_CTX_set_alpn_protos(ctx,data=&PL_sv_undef) + SSL_CTX * ctx + SV * data + PREINIT: + unsigned char *alpn_data; + unsigned char alpn_len; + + CODE: + RETVAL = -1; + + if (!SvROK(data) || (SvTYPE(SvRV(data)) != SVt_PVAV)) + croak("Net::SSLeay: CTX_set_alpn_protos needs a single array reference.\n"); + alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), NULL); + Newx(alpn_data, alpn_len, unsigned char); + if (!alpn_data) + croak("Net::SSLeay: CTX_set_alpn_protos could not allocate memory.\n"); + alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), alpn_data); + RETVAL = SSL_CTX_set_alpn_protos(ctx, alpn_data, alpn_len); + Safefree(alpn_data); + + OUTPUT: + RETVAL + +int +SSL_set_alpn_protos(ssl,data=&PL_sv_undef) + SSL * ssl + SV * data + PREINIT: + unsigned char *alpn_data; + unsigned char alpn_len; + + CODE: + RETVAL = -1; + + if (!SvROK(data) || (SvTYPE(SvRV(data)) != SVt_PVAV)) + croak("Net::SSLeay: set_alpn_protos needs a single array reference.\n"); + alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), NULL); + Newx(alpn_data, alpn_len, unsigned char); + if (!alpn_data) + croak("Net::SSLeay: set_alpn_protos could not allocate memory.\n"); + alpn_len = next_proto_helper_AV2protodata((AV*)SvRV(data), alpn_data); + RETVAL = SSL_set_alpn_protos(ssl, alpn_data, alpn_len); + Safefree(alpn_data); + + OUTPUT: + RETVAL + +void +P_alpn_selected(s) + const SSL *s + PREINIT: + const unsigned char *data; + unsigned int len; + PPCODE: + SSL_get0_alpn_selected(s, &data, &len); + XPUSHs(sv_2mortal(newSVpv((char *)data, len))); + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10001000L + +void +SSL_export_keying_material(ssl, outlen, label, context=&PL_sv_undef) + SSL * ssl + int outlen + SV * context + PREINIT: + unsigned char * out; + STRLEN llen; + STRLEN contextlen = 0; + char *context_arg = NULL; + int use_context = 0; + int ret; + INPUT: + char * label = SvPV( ST(2), llen); + PPCODE: + Newx(out, outlen, unsigned char); + + if (context != &PL_sv_undef) { + use_context = 1; + context_arg = SvPV( ST(3), contextlen); + } + ret = SSL_export_keying_material(ssl, out, outlen, label, llen, (unsigned char*)context_arg, contextlen, use_context); + PUSHs(sv_2mortal(ret>0 ? newSVpvn((const char *)out, outlen) : newSV(0))); + EXTEND(SP, 1); + Safefree(out); + +#endif + +#define REM_EOF "/* EOF - SSLeay.xs */" diff --git a/constants.c b/constants.c new file mode 100644 index 0000000..722190c --- /dev/null +++ b/constants.c @@ -0,0 +1,6844 @@ +/* DO NOT EDIT THIS FILE - update __DATA__ section of helper_script/regen_openssl_constants.pl */ + +static double +constant (const char *name, size_t len) { + /* Initially switch on the length of the name. */ + switch (len) { + case 5: + /* Names all of length 5. */ + /* RSA_3 ST_OK */ + /* Offset 0 gives the best switch position. */ + switch (*name++) { + case 'R': + if (!memcmp(name, "SA_3", 4)) { + /* R */ + +#ifdef RSA_3 + return RSA_3; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "T_OK", 4)) { + /* S */ + +#ifdef SSL_ST_OK + return SSL_ST_OK; +#else + goto not_there; +#endif + + } + break; + } + break; + case 6: + /* Names all of length 6. */ + /* OP_ALL RSA_F4 */ + /* Offset 0 gives the best switch position. */ + switch (*name++) { + case 'O': + if (!memcmp(name, "P_ALL", 5)) { + /* O */ + +#ifdef SSL_OP_ALL + return SSL_OP_ALL; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "SA_F4", 5)) { + /* R */ + +#ifdef RSA_F4 + return RSA_F4; +#else + goto not_there; +#endif + + } + break; + } + break; + case 7: + /* Names all of length 7. */ + /* CB_EXIT CB_LOOP CB_READ GEN_DNS GEN_RID GEN_URI NID_dsa NID_md2 NID_md5 + NID_rc4 NID_rsa NID_sha NOTHING READING ST_INIT WRITING */ + /* Offset 4 gives the best switch position. */ + switch (name[4]) { + case 'D': + if (!memcmp(name, "GEN_DNS", 7)) { + /* ^ */ + +#ifdef GEN_DNS + return GEN_DNS; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "CB_READ", 7)) { + /* ^ */ + +#ifdef SSL_CB_READ + return SSL_CB_READ; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "NOTHING", 7)) { + /* ^ */ + +#ifdef SSL_NOTHING + return SSL_NOTHING; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "READING", 7)) { + /* ^ */ + +#ifdef SSL_READING + return SSL_READING; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "WRITING", 7)) { + /* ^ */ + +#ifdef SSL_WRITING + return SSL_WRITING; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "ST_INIT", 7)) { + /* ^ */ + +#ifdef SSL_ST_INIT + return SSL_ST_INIT; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "CB_LOOP", 7)) { + /* ^ */ + +#ifdef SSL_CB_LOOP + return SSL_CB_LOOP; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "GEN_RID", 7)) { + /* ^ */ + +#ifdef GEN_RID + return GEN_RID; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "GEN_URI", 7)) { + /* ^ */ + +#ifdef GEN_URI + return GEN_URI; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "CB_EXIT", 7)) { + /* ^ */ + +#ifdef SSL_CB_EXIT + return SSL_CB_EXIT; +#else + goto not_there; +#endif + + } + break; + case 'd': + if (!memcmp(name, "NID_dsa", 7)) { + /* ^ */ + +#ifdef NID_dsa + return NID_dsa; +#else + goto not_there; +#endif + + } + break; + case 'm': + if (!memcmp(name, "NID_md2", 7)) { + /* ^ */ + +#ifdef NID_md2 + return NID_md2; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_md5", 7)) { + /* ^ */ + +#ifdef NID_md5 + return NID_md5; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_rc4", 7)) { + /* ^ */ + +#ifdef NID_rc4 + return NID_rc4; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rsa", 7)) { + /* ^ */ + +#ifdef NID_rsa + return NID_rsa; +#else + goto not_there; +#endif + + } + break; + case 's': + if (!memcmp(name, "NID_sha", 7)) { + /* ^ */ + +#ifdef NID_sha + return NID_sha; +#else + goto not_there; +#endif + + } + break; + } + break; + case 8: + /* Names all of length 8. */ + /* CB_ALERT CB_WRITE F_READ_N GEN_X400 NID_X500 NID_X509 NID_mdc2 NID_name + NID_pkcs NID_sha1 */ + /* Offset 5 gives the best switch position. */ + switch (name[5]) { + case '4': + if (!memcmp(name, "GEN_X400", 8)) { + /* ^ */ + +#ifdef GEN_X400 + return GEN_X400; +#else + goto not_there; +#endif + + } + break; + case '5': + if (!memcmp(name, "NID_X500", 8)) { + /* ^ */ + +#ifdef NID_X500 + return NID_X500; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_X509", 8)) { + /* ^ */ + +#ifdef NID_X509 + return NID_X509; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "F_READ_N", 8)) { + /* ^ */ + +#ifdef SSL_F_READ_N + return SSL_F_READ_N; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "CB_ALERT", 8)) { + /* ^ */ + +#ifdef SSL_CB_ALERT + return SSL_CB_ALERT; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "CB_WRITE", 8)) { + /* ^ */ + +#ifdef SSL_CB_WRITE + return SSL_CB_WRITE; +#else + goto not_there; +#endif + + } + break; + case 'a': + if (!memcmp(name, "NID_name", 8)) { + /* ^ */ + +#ifdef NID_name + return NID_name; +#else + goto not_there; +#endif + + } + break; + case 'd': + if (!memcmp(name, "NID_mdc2", 8)) { + /* ^ */ + +#ifdef NID_mdc2 + return NID_mdc2; +#else + goto not_there; +#endif + + } + break; + case 'h': + if (!memcmp(name, "NID_sha1", 8)) { + /* ^ */ + +#ifdef NID_sha1 + return NID_sha1; +#else + goto not_there; +#endif + + } + break; + case 'k': + if (!memcmp(name, "NID_pkcs", 8)) { + /* ^ */ + +#ifdef NID_pkcs + return NID_pkcs; +#else + goto not_there; +#endif + + } + break; + } + break; + case 9: + /* Names all of length 9. */ + /* ERROR_SSL EVP_PK_DH EVP_PK_EC F_SSL_NEW GEN_EMAIL GEN_IPADD NID_dsa_2 + NID_id_ad NID_id_ce NID_id_kp NID_id_pe NID_pbes2 NID_pkcs3 NID_pkcs7 + NID_pkcs9 NID_sxnet NID_title NID_undef ST_ACCEPT ST_BEFORE X509_V_OK */ + /* Offset 8 gives the best switch position. */ + switch (name[8]) { + case '2': + if (!memcmp(name, "NID_dsa_", 8)) { + /* 2 */ + +#ifdef NID_dsa_2 + return NID_dsa_2; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_pbes", 8)) { + /* 2 */ + +#ifdef NID_pbes2 + return NID_pbes2; +#else + goto not_there; +#endif + + } + break; + case '3': + if (!memcmp(name, "NID_pkcs", 8)) { + /* 3 */ + +#ifdef NID_pkcs3 + return NID_pkcs3; +#else + goto not_there; +#endif + + } + break; + case '7': + if (!memcmp(name, "NID_pkcs", 8)) { + /* 7 */ + +#ifdef NID_pkcs7 + return NID_pkcs7; +#else + goto not_there; +#endif + + } + break; + case '9': + if (!memcmp(name, "NID_pkcs", 8)) { + /* 9 */ + +#ifdef NID_pkcs9 + return NID_pkcs9; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "EVP_PK_E", 8)) { + /* C */ + +#ifdef EVP_PK_EC + return EVP_PK_EC; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "GEN_IPAD", 8)) { + /* D */ + +#ifdef GEN_IPADD + return GEN_IPADD; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "ST_BEFOR", 8)) { + /* E */ + +#ifdef SSL_ST_BEFORE + return SSL_ST_BEFORE; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "EVP_PK_D", 8)) { + /* H */ + +#ifdef EVP_PK_DH + return EVP_PK_DH; +#else + goto not_there; +#endif + + } + break; + case 'K': + if (!memcmp(name, "X509_V_O", 8)) { + /* K */ + +#ifdef X509_V_OK + return X509_V_OK; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "ERROR_SS", 8)) { + /* L */ + +#ifdef SSL_ERROR_SSL + return SSL_ERROR_SSL; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "GEN_EMAI", 8)) { + /* L */ + +#ifdef GEN_EMAIL + return GEN_EMAIL; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "ST_ACCEP", 8)) { + /* T */ + +#ifdef SSL_ST_ACCEPT + return SSL_ST_ACCEPT; +#else + goto not_there; +#endif + + } + break; + case 'W': + if (!memcmp(name, "F_SSL_NE", 8)) { + /* W */ + +#ifdef SSL_F_SSL_NEW + return SSL_F_SSL_NEW; +#else + goto not_there; +#endif + + } + break; + case 'd': + if (!memcmp(name, "NID_id_a", 8)) { + /* d */ + +#ifdef NID_id_ad + return NID_id_ad; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_id_c", 8)) { + /* e */ + +#ifdef NID_id_ce + return NID_id_ce; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_id_p", 8)) { + /* e */ + +#ifdef NID_id_pe + return NID_id_pe; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_titl", 8)) { + /* e */ + +#ifdef NID_title + return NID_title; +#else + goto not_there; +#endif + + } + break; + case 'f': + if (!memcmp(name, "NID_unde", 8)) { + /* f */ + +#ifdef NID_undef + return NID_undef; +#else + goto not_there; +#endif + + } + break; + case 'p': + if (!memcmp(name, "NID_id_k", 8)) { + /* p */ + +#ifdef NID_id_kp + return NID_id_kp; +#else + goto not_there; +#endif + + } + break; + case 't': + if (!memcmp(name, "NID_sxne", 8)) { + /* t */ + +#ifdef NID_sxnet + return NID_sxnet; +#else + goto not_there; +#endif + + } + break; + } + break; + case 10: + /* Names all of length 10. */ + /* ERROR_NONE EVP_PKS_EC EVP_PK_DSA EVP_PK_RSA F_SSL_READ NID_bf_cbc + NID_bf_ecb NID_crlBag NID_keyBag NID_ms_efs NID_ms_sgc NID_ns_sgc + NID_pbmac1 NID_rc4_40 NID_rsadsi R_X509_LIB SSLEAY_DIR ST_CONNECT */ + /* Offset 9 gives the best switch position. */ + switch (name[9]) { + case '0': + if (!memcmp(name, "NID_rc4_4", 9)) { + /* 0 */ + +#ifdef NID_rc4_40 + return NID_rc4_40; +#else + goto not_there; +#endif + + } + break; + case '1': + if (!memcmp(name, "NID_pbmac", 9)) { + /* 1 */ + +#ifdef NID_pbmac1 + return NID_pbmac1; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "EVP_PK_DS", 9)) { + /* A */ + +#ifdef EVP_PK_DSA + return EVP_PK_DSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "EVP_PK_RS", 9)) { + /* A */ + +#ifdef EVP_PK_RSA + return EVP_PK_RSA; +#else + goto not_there; +#endif + + } + break; + case 'B': + if (!memcmp(name, "R_X509_LI", 9)) { + /* B */ + +#ifdef SSL_R_X509_LIB + return SSL_R_X509_LIB; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "EVP_PKS_E", 9)) { + /* C */ + +#ifdef EVP_PKS_EC + return EVP_PKS_EC; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "F_SSL_REA", 9)) { + /* D */ + +#ifdef SSL_F_SSL_READ + return SSL_F_SSL_READ; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "ERROR_NON", 9)) { + /* E */ + +#ifdef SSL_ERROR_NONE + return SSL_ERROR_NONE; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "SSLEAY_DI", 9)) { + /* R */ + +#ifdef SSLEAY_DIR + return SSLEAY_DIR; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "ST_CONNEC", 9)) { + /* T */ + +#ifdef SSL_ST_CONNECT + return SSL_ST_CONNECT; +#else + goto not_there; +#endif + + } + break; + case 'b': + if (!memcmp(name, "NID_bf_ec", 9)) { + /* b */ + +#ifdef NID_bf_ecb + return NID_bf_ecb; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_bf_cb", 9)) { + /* c */ + +#ifdef NID_bf_cbc + return NID_bf_cbc; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_ms_sg", 9)) { + /* c */ + +#ifdef NID_ms_sgc + return NID_ms_sgc; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_ns_sg", 9)) { + /* c */ + +#ifdef NID_ns_sgc + return NID_ns_sgc; +#else + goto not_there; +#endif + + } + break; + case 'g': + if (!memcmp(name, "NID_crlBa", 9)) { + /* g */ + +#ifdef NID_crlBag + return NID_crlBag; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_keyBa", 9)) { + /* g */ + +#ifdef NID_keyBag + return NID_keyBag; +#else + goto not_there; +#endif + + } + break; + case 'i': + if (!memcmp(name, "NID_rsads", 9)) { + /* i */ + +#ifdef NID_rsadsi + return NID_rsadsi; +#else + goto not_there; +#endif + + } + break; + case 's': + if (!memcmp(name, "NID_ms_ef", 9)) { + /* s */ + +#ifdef NID_ms_efs + return NID_ms_efs; +#else + goto not_there; +#endif + + } + break; + } + break; + case 11: + /* Names all of length 11. */ + /* EVP_PKS_DSA EVP_PKS_RSA EVP_PKT_ENC EVP_PKT_EXP GEN_DIRNAME NID_ad_OCSP + NID_certBag NID_des_cbc NID_des_ecb NID_des_ede NID_ext_req NID_id_pkix + NID_rc2_cbc NID_rc2_ecb NID_rc5_cbc NID_rc5_ecb NID_surname NID_x509Crl + OPENSSL_DIR OP_NO_SSLv2 OP_NO_SSLv3 OP_NO_TLSv1 R_BAD_STATE VERIFY_NONE + VERIFY_PEER X509_LOOKUP */ + /* Offset 9 gives the best switch position. */ + switch (name[9]) { + case 'E': + if (!memcmp(name, "VERIFY_PEER", 11)) { + /* ^ */ + +#ifdef SSL_VERIFY_PEER + return SSL_VERIFY_PEER; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "OPENSSL_DIR", 11)) { + /* ^ */ + +#ifdef OPENSSL_DIR + return OPENSSL_DIR; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "GEN_DIRNAME", 11)) { + /* ^ */ + +#ifdef GEN_DIRNAME + return GEN_DIRNAME; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "EVP_PKT_ENC", 11)) { + /* ^ */ + +#ifdef EVP_PKT_ENC + return EVP_PKT_ENC; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "VERIFY_NONE", 11)) { + /* ^ */ + +#ifdef SSL_VERIFY_NONE + return SSL_VERIFY_NONE; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "EVP_PKS_DSA", 11)) { + /* ^ */ + +#ifdef EVP_PKS_DSA + return EVP_PKS_DSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "EVP_PKS_RSA", 11)) { + /* ^ */ + +#ifdef EVP_PKS_RSA + return EVP_PKS_RSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_ad_OCSP", 11)) { + /* ^ */ + +#ifdef NID_ad_OCSP + return NID_ad_OCSP; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "R_BAD_STATE", 11)) { + /* ^ */ + +#ifdef SSL_R_BAD_STATE + return SSL_R_BAD_STATE; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "X509_LOOKUP", 11)) { + /* ^ */ + +#ifdef SSL_X509_LOOKUP + return SSL_X509_LOOKUP; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "EVP_PKT_EXP", 11)) { + /* ^ */ + +#ifdef EVP_PKT_EXP + return EVP_PKT_EXP; +#else + goto not_there; +#endif + + } + break; + case 'a': + if (!memcmp(name, "NID_certBag", 11)) { + /* ^ */ + +#ifdef NID_certBag + return NID_certBag; +#else + goto not_there; +#endif + + } + break; + case 'b': + if (!memcmp(name, "NID_des_cbc", 11)) { + /* ^ */ + +#ifdef NID_des_cbc + return NID_des_cbc; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc2_cbc", 11)) { + /* ^ */ + +#ifdef NID_rc2_cbc + return NID_rc2_cbc; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc5_cbc", 11)) { + /* ^ */ + +#ifdef NID_rc5_cbc + return NID_rc5_cbc; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_des_ecb", 11)) { + /* ^ */ + +#ifdef NID_des_ecb + return NID_des_ecb; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc2_ecb", 11)) { + /* ^ */ + +#ifdef NID_rc2_ecb + return NID_rc2_ecb; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc5_ecb", 11)) { + /* ^ */ + +#ifdef NID_rc5_ecb + return NID_rc5_ecb; +#else + goto not_there; +#endif + + } + break; + case 'd': + if (!memcmp(name, "NID_des_ede", 11)) { + /* ^ */ + +#ifdef NID_des_ede + return NID_des_ede; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_ext_req", 11)) { + /* ^ */ + +#ifdef NID_ext_req + return NID_ext_req; +#else + goto not_there; +#endif + + } + break; + case 'i': + if (!memcmp(name, "NID_id_pkix", 11)) { + /* ^ */ + +#ifdef NID_id_pkix + return NID_id_pkix; +#else + goto not_there; +#endif + + } + break; + case 'm': + if (!memcmp(name, "NID_surname", 11)) { + /* ^ */ + +#ifdef NID_surname + return NID_surname; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_x509Crl", 11)) { + /* ^ */ + +#ifdef NID_x509Crl + return NID_x509Crl; +#else + goto not_there; +#endif + + } + break; + case 'v': + if (!memcmp(name, "OP_NO_SSLv2", 11)) { + /* ^ */ + +#ifdef SSL_OP_NO_SSLv2 + return SSL_OP_NO_SSLv2; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_SSLv3", 11)) { + /* ^ */ + +#ifdef SSL_OP_NO_SSLv3 + return SSL_OP_NO_SSLv3; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_TLSv1", 11)) { + /* ^ */ + +#ifdef SSL_OP_NO_TLSv1 + return SSL_OP_NO_TLSv1; +#else + goto not_there; +#endif + + } + break; + } + break; + case 12: + /* Names all of length 12. */ + /* EVP_PKT_EXCH EVP_PKT_SIGN FILETYPE_PEM F_SSL_SET_FD GEN_EDIPARTY + MBSTRING_ASC MBSTRING_BMP NID_bf_cfb64 NID_bf_ofb64 NID_des_ede3 + NID_desx_cbc NID_idea_cbc NID_idea_ecb NID_initials NID_md5_sha1 + NID_netscape OP_NO_TICKET R_PEER_ERROR R_SHORT_READ SSL3_VERSION + ST_READ_BODY TLS1_VERSION */ + /* Offset 10 gives the best switch position. */ + switch (name[10]) { + case '6': + if (!memcmp(name, "NID_bf_cfb64", 12)) { + /* ^ */ + +#ifdef NID_bf_cfb64 + return NID_bf_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_bf_ofb64", 12)) { + /* ^ */ + +#ifdef NID_bf_ofb64 + return NID_bf_ofb64; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "R_SHORT_READ", 12)) { + /* ^ */ + +#ifdef SSL_R_SHORT_READ + return SSL_R_SHORT_READ; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "EVP_PKT_EXCH", 12)) { + /* ^ */ + +#ifdef EVP_PKT_EXCH + return EVP_PKT_EXCH; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "ST_READ_BODY", 12)) { + /* ^ */ + +#ifdef SSL_ST_READ_BODY + return SSL_ST_READ_BODY; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "FILETYPE_PEM", 12)) { + /* ^ */ + +#ifdef SSL_FILETYPE_PEM + return SSL_FILETYPE_PEM; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_TICKET", 12)) { + /* ^ */ + +#ifdef SSL_OP_NO_TICKET + return SSL_OP_NO_TICKET; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "F_SSL_SET_FD", 12)) { + /* ^ */ + +#ifdef SSL_F_SSL_SET_FD + return SSL_F_SSL_SET_FD; +#else + goto not_there; +#endif + + } + break; + case 'G': + if (!memcmp(name, "EVP_PKT_SIGN", 12)) { + /* ^ */ + +#ifdef EVP_PKT_SIGN + return EVP_PKT_SIGN; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "MBSTRING_BMP", 12)) { + /* ^ */ + +#ifdef MBSTRING_BMP + return MBSTRING_BMP; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "R_PEER_ERROR", 12)) { + /* ^ */ + +#ifdef SSL_R_PEER_ERROR + return SSL_R_PEER_ERROR; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "SSL3_VERSION", 12)) { + /* ^ */ + +#ifdef SSL3_VERSION + return SSL3_VERSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "TLS1_VERSION", 12)) { + /* ^ */ + +#ifdef TLS1_VERSION + return TLS1_VERSION; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "MBSTRING_ASC", 12)) { + /* ^ */ + +#ifdef MBSTRING_ASC + return MBSTRING_ASC; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "GEN_EDIPARTY", 12)) { + /* ^ */ + +#ifdef GEN_EDIPARTY + return GEN_EDIPARTY; +#else + goto not_there; +#endif + + } + break; + case 'a': + if (!memcmp(name, "NID_md5_sha1", 12)) { + /* ^ */ + +#ifdef NID_md5_sha1 + return NID_md5_sha1; +#else + goto not_there; +#endif + + } + break; + case 'b': + if (!memcmp(name, "NID_desx_cbc", 12)) { + /* ^ */ + +#ifdef NID_desx_cbc + return NID_desx_cbc; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_idea_cbc", 12)) { + /* ^ */ + +#ifdef NID_idea_cbc + return NID_idea_cbc; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_idea_ecb", 12)) { + /* ^ */ + +#ifdef NID_idea_ecb + return NID_idea_ecb; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_des_ede3", 12)) { + /* ^ */ + +#ifdef NID_des_ede3 + return NID_des_ede3; +#else + goto not_there; +#endif + + } + break; + case 'l': + if (!memcmp(name, "NID_initials", 12)) { + /* ^ */ + +#ifdef NID_initials + return NID_initials; +#else + goto not_there; +#endif + + } + break; + case 'p': + if (!memcmp(name, "NID_netscape", 12)) { + /* ^ */ + +#ifdef NID_netscape + return NID_netscape; +#else + goto not_there; +#endif + + } + break; + } + break; + case 13: + /* Names all of length 13. */ + /* CB_READ_ALERT ERROR_SYSCALL FILETYPE_ASN1 F_SSL_SET_RFD F_SSL_SET_WFD + GEN_OTHERNAME MBSTRING_FLAG MBSTRING_UNIV MBSTRING_UTF8 NID_OCSP_sign + NID_algorithm NID_cast5_cbc NID_cast5_ecb NID_code_sign NID_delta_crl + NID_des_cfb64 NID_des_ofb64 NID_givenName NID_id_pbkdf2 NID_id_qt_cps + NID_key_usage NID_rc2_cfb64 NID_rc2_ofb64 NID_rc5_cfb64 NID_rc5_ofb64 + NID_ripemd160 NID_secretBag OP_NO_TLSv1_1 OP_NO_TLSv1_2 OP_NO_TLSv1_3 + OP_TLS_D5_BUG SENT_SHUTDOWN SSLEAY_CFLAGS XN_FLAG_FN_LN XN_FLAG_FN_SN */ + /* Offset 12 gives the best switch position. */ + switch (name[12]) { + case '0': + if (!memcmp(name, "NID_ripemd16", 12)) { + /* 0 */ + +#ifdef NID_ripemd160 + return NID_ripemd160; +#else + goto not_there; +#endif + + } + break; + case '1': + if (!memcmp(name, "FILETYPE_ASN", 12)) { + /* 1 */ + +#ifdef SSL_FILETYPE_ASN1 + return SSL_FILETYPE_ASN1; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_TLSv1_", 12)) { + /* 1 */ + +#ifdef SSL_OP_NO_TLSv1_1 + return SSL_OP_NO_TLSv1_1; +#else + goto not_there; +#endif + + } + break; + case '2': + if (!memcmp(name, "NID_id_pbkdf", 12)) { + /* 2 */ + +#ifdef NID_id_pbkdf2 + return NID_id_pbkdf2; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_TLSv1_", 12)) { + /* 2 */ + +#ifdef SSL_OP_NO_TLSv1_2 + return SSL_OP_NO_TLSv1_2; +#else + goto not_there; +#endif + + } + break; + case '3': + if (!memcmp(name, "OP_NO_TLSv1_", 12)) { + /* 3 */ + +#ifdef SSL_OP_NO_TLSv1_3 + return SSL_OP_NO_TLSv1_3; +#else + goto not_there; +#endif + + } + break; + case '4': + if (!memcmp(name, "NID_des_cfb6", 12)) { + /* 4 */ + +#ifdef NID_des_cfb64 + return NID_des_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_des_ofb6", 12)) { + /* 4 */ + +#ifdef NID_des_ofb64 + return NID_des_ofb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc2_cfb6", 12)) { + /* 4 */ + +#ifdef NID_rc2_cfb64 + return NID_rc2_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc2_ofb6", 12)) { + /* 4 */ + +#ifdef NID_rc2_ofb64 + return NID_rc2_ofb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc5_cfb6", 12)) { + /* 4 */ + +#ifdef NID_rc5_cfb64 + return NID_rc5_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc5_ofb6", 12)) { + /* 4 */ + +#ifdef NID_rc5_ofb64 + return NID_rc5_ofb64; +#else + goto not_there; +#endif + + } + break; + case '8': + if (!memcmp(name, "MBSTRING_UTF", 12)) { + /* 8 */ + +#ifdef MBSTRING_UTF8 + return MBSTRING_UTF8; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "F_SSL_SET_RF", 12)) { + /* D */ + +#ifdef SSL_F_SSL_SET_RFD + return SSL_F_SSL_SET_RFD; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_SSL_SET_WF", 12)) { + /* D */ + +#ifdef SSL_F_SSL_SET_WFD + return SSL_F_SSL_SET_WFD; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "GEN_OTHERNAM", 12)) { + /* E */ + +#ifdef GEN_OTHERNAME + return GEN_OTHERNAME; +#else + goto not_there; +#endif + + } + break; + case 'G': + if (!memcmp(name, "MBSTRING_FLA", 12)) { + /* G */ + +#ifdef MBSTRING_FLAG + return MBSTRING_FLAG; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_TLS_D5_BU", 12)) { + /* G */ + +#ifdef SSL_OP_TLS_D5_BUG + return SSL_OP_TLS_D5_BUG; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "ERROR_SYSCAL", 12)) { + /* L */ + +#ifdef SSL_ERROR_SYSCALL + return SSL_ERROR_SYSCALL; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "SENT_SHUTDOW", 12)) { + /* N */ + +#ifdef SSL_SENT_SHUTDOWN + return SSL_SENT_SHUTDOWN; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_FN_L", 12)) { + /* N */ + +#ifdef XN_FLAG_FN_LN + return XN_FLAG_FN_LN; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_FN_S", 12)) { + /* N */ + +#ifdef XN_FLAG_FN_SN + return XN_FLAG_FN_SN; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "SSLEAY_CFLAG", 12)) { + /* S */ + +#ifdef SSLEAY_CFLAGS + return SSLEAY_CFLAGS; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "CB_READ_ALER", 12)) { + /* T */ + +#ifdef SSL_CB_READ_ALERT + return SSL_CB_READ_ALERT; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "MBSTRING_UNI", 12)) { + /* V */ + +#ifdef MBSTRING_UNIV + return MBSTRING_UNIV; +#else + goto not_there; +#endif + + } + break; + case 'b': + if (!memcmp(name, "NID_cast5_ec", 12)) { + /* b */ + +#ifdef NID_cast5_ecb + return NID_cast5_ecb; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_cast5_cb", 12)) { + /* c */ + +#ifdef NID_cast5_cbc + return NID_cast5_cbc; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_givenNam", 12)) { + /* e */ + +#ifdef NID_givenName + return NID_givenName; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_key_usag", 12)) { + /* e */ + +#ifdef NID_key_usage + return NID_key_usage; +#else + goto not_there; +#endif + + } + break; + case 'g': + if (!memcmp(name, "NID_secretBa", 12)) { + /* g */ + +#ifdef NID_secretBag + return NID_secretBag; +#else + goto not_there; +#endif + + } + break; + case 'l': + if (!memcmp(name, "NID_delta_cr", 12)) { + /* l */ + +#ifdef NID_delta_crl + return NID_delta_crl; +#else + goto not_there; +#endif + + } + break; + case 'm': + if (!memcmp(name, "NID_algorith", 12)) { + /* m */ + +#ifdef NID_algorithm + return NID_algorithm; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_OCSP_sig", 12)) { + /* n */ + +#ifdef NID_OCSP_sign + return NID_OCSP_sign; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_code_sig", 12)) { + /* n */ + +#ifdef NID_code_sign + return NID_code_sign; +#else + goto not_there; +#endif + + } + break; + case 's': + if (!memcmp(name, "NID_id_qt_cp", 12)) { + /* s */ + +#ifdef NID_id_qt_cps + return NID_id_qt_cps; +#else + goto not_there; +#endif + + } + break; + } + break; + case 14: + /* Names all of length 14. */ + /* CB_ACCEPT_EXIT CB_ACCEPT_LOOP CB_WRITE_ALERT F_CLIENT_HELLO + F_SERVER_HELLO F_SSL_CERT_NEW NID_commonName NID_crl_number + NID_crl_reason NID_dsaWithSHA NID_idea_cfb64 NID_idea_ofb64 + NID_localKeyID NID_md5WithRSA NID_ms_ext_req NID_pkcs7_data + NID_rc2_40_cbc NID_rc2_64_cbc NID_time_stamp OPENSSL_CFLAGS + OP_NO_SSL_MASK R_BAD_CHECKSUM R_NO_PUBLICKEY R_NULL_SSL_CTX + SESS_CACHE_OFF SSLEAY_VERSION ST_READ_HEADER TLS1_1_VERSION + TLS1_2_VERSION TLS1_3_VERSION X509_TRUST_TSA XN_FLAG_COMPAT + XN_FLAG_DN_REV XN_FLAG_FN_OID XN_FLAG_SPC_EQ */ + /* Offset 13 gives the best switch position. */ + switch (name[13]) { + case '4': + if (!memcmp(name, "NID_idea_cfb6", 13)) { + /* 4 */ + +#ifdef NID_idea_cfb64 + return NID_idea_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_idea_ofb6", 13)) { + /* 4 */ + +#ifdef NID_idea_ofb64 + return NID_idea_ofb64; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "NID_dsaWithSH", 13)) { + /* A */ + +#ifdef NID_dsaWithSHA + return NID_dsaWithSHA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_md5WithRS", 13)) { + /* A */ + +#ifdef NID_md5WithRSA + return NID_md5WithRSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_TRUST_TS", 13)) { + /* A */ + +#ifdef X509_TRUST_TSA + return X509_TRUST_TSA; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "NID_localKeyI", 13)) { + /* D */ + +#ifdef NID_localKeyID + return NID_localKeyID; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_FN_OI", 13)) { + /* D */ + +#ifdef XN_FLAG_FN_OID + return XN_FLAG_FN_OID; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "SESS_CACHE_OF", 13)) { + /* F */ + +#ifdef SSL_SESS_CACHE_OFF + return SSL_SESS_CACHE_OFF; +#else + goto not_there; +#endif + + } + break; + case 'K': + if (!memcmp(name, "OP_NO_SSL_MAS", 13)) { + /* K */ + +#ifdef SSL_OP_NO_SSL_MASK + return SSL_OP_NO_SSL_MASK; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "R_BAD_CHECKSU", 13)) { + /* M */ + +#ifdef SSL_R_BAD_CHECKSUM + return SSL_R_BAD_CHECKSUM; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "SSLEAY_VERSIO", 13)) { + /* N */ + +#ifdef SSLEAY_VERSION + return SSLEAY_VERSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "TLS1_1_VERSIO", 13)) { + /* N */ + +#ifdef TLS1_1_VERSION + return TLS1_1_VERSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "TLS1_2_VERSIO", 13)) { + /* N */ + +#ifdef TLS1_2_VERSION + return TLS1_2_VERSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "TLS1_3_VERSIO", 13)) { + /* N */ + +#ifdef TLS1_3_VERSION + return TLS1_3_VERSION; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "F_CLIENT_HELL", 13)) { + /* O */ + +#ifdef SSL_F_CLIENT_HELLO + return SSL_F_CLIENT_HELLO; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_SERVER_HELL", 13)) { + /* O */ + +#ifdef SSL_F_SERVER_HELLO + return SSL_F_SERVER_HELLO; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "CB_ACCEPT_LOO", 13)) { + /* P */ + +#ifdef SSL_CB_ACCEPT_LOOP + return SSL_CB_ACCEPT_LOOP; +#else + goto not_there; +#endif + + } + break; + case 'Q': + if (!memcmp(name, "XN_FLAG_SPC_E", 13)) { + /* Q */ + +#ifdef XN_FLAG_SPC_EQ + return XN_FLAG_SPC_EQ; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "ST_READ_HEADE", 13)) { + /* R */ + +#ifdef SSL_ST_READ_HEADER + return SSL_ST_READ_HEADER; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "OPENSSL_CFLAG", 13)) { + /* S */ + +#ifdef OPENSSL_CFLAGS + return OPENSSL_CFLAGS; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "CB_ACCEPT_EXI", 13)) { + /* T */ + +#ifdef SSL_CB_ACCEPT_EXIT + return SSL_CB_ACCEPT_EXIT; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "CB_WRITE_ALER", 13)) { + /* T */ + +#ifdef SSL_CB_WRITE_ALERT + return SSL_CB_WRITE_ALERT; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_COMPA", 13)) { + /* T */ + +#ifdef XN_FLAG_COMPAT + return XN_FLAG_COMPAT; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "XN_FLAG_DN_RE", 13)) { + /* V */ + +#ifdef XN_FLAG_DN_REV + return XN_FLAG_DN_REV; +#else + goto not_there; +#endif + + } + break; + case 'W': + if (!memcmp(name, "F_SSL_CERT_NE", 13)) { + /* W */ + +#ifdef SSL_F_SSL_CERT_NEW + return SSL_F_SSL_CERT_NEW; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "R_NULL_SSL_CT", 13)) { + /* X */ + +#ifdef SSL_R_NULL_SSL_CTX + return SSL_R_NULL_SSL_CTX; +#else + goto not_there; +#endif + + } + break; + case 'Y': + if (!memcmp(name, "R_NO_PUBLICKE", 13)) { + /* Y */ + +#ifdef SSL_R_NO_PUBLICKEY + return SSL_R_NO_PUBLICKEY; +#else + goto not_there; +#endif + + } + break; + case 'a': + if (!memcmp(name, "NID_pkcs7_dat", 13)) { + /* a */ + +#ifdef NID_pkcs7_data + return NID_pkcs7_data; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_rc2_40_cb", 13)) { + /* c */ + +#ifdef NID_rc2_40_cbc + return NID_rc2_40_cbc; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rc2_64_cb", 13)) { + /* c */ + +#ifdef NID_rc2_64_cbc + return NID_rc2_64_cbc; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_commonNam", 13)) { + /* e */ + +#ifdef NID_commonName + return NID_commonName; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_crl_reaso", 13)) { + /* n */ + +#ifdef NID_crl_reason + return NID_crl_reason; +#else + goto not_there; +#endif + + } + break; + case 'p': + if (!memcmp(name, "NID_time_stam", 13)) { + /* p */ + +#ifdef NID_time_stamp + return NID_time_stamp; +#else + goto not_there; +#endif + + } + break; + case 'q': + if (!memcmp(name, "NID_ms_ext_re", 13)) { + /* q */ + +#ifdef NID_ms_ext_req + return NID_ms_ext_req; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_crl_numbe", 13)) { + /* r */ + +#ifdef NID_crl_number + return NID_crl_number; +#else + goto not_there; +#endif + + } + break; + } + break; + case 15: + /* Names all of length 15. */ + /* CB_CONNECT_EXIT CB_CONNECT_LOOP ERROR_WANT_READ F_WRITE_PENDING + MODE_AUTO_RETRY NID_cast5_cfb64 NID_cast5_ofb64 NID_client_auth + NID_countryName NID_des_ede_cbc NID_description NID_dnQualifier + NID_dsaWithSHA1 NID_info_access NID_mdc2WithRSA NID_ms_code_com + NID_ms_code_ind NID_ms_ctl_sign NID_server_auth NID_sha1WithRSA + OPENSSL_VERSION OP_NO_QUERY_MTU R_NO_PRIVATEKEY R_UNKNOWN_STATE + SESS_CACHE_BOTH SSLEAY_BUILT_ON SSLEAY_PLATFORM XN_FLAG_FN_MASK + XN_FLAG_FN_NONE XN_FLAG_ONELINE XN_FLAG_RFC2253 */ + /* Offset 14 gives the best switch position. */ + switch (name[14]) { + case '1': + if (!memcmp(name, "NID_dsaWithSHA", 14)) { + /* 1 */ + +#ifdef NID_dsaWithSHA1 + return NID_dsaWithSHA1; +#else + goto not_there; +#endif + + } + break; + case '3': + if (!memcmp(name, "XN_FLAG_RFC225", 14)) { + /* 3 */ + +#ifdef XN_FLAG_RFC2253 + return XN_FLAG_RFC2253; +#else + goto not_there; +#endif + + } + break; + case '4': + if (!memcmp(name, "NID_cast5_cfb6", 14)) { + /* 4 */ + +#ifdef NID_cast5_cfb64 + return NID_cast5_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_cast5_ofb6", 14)) { + /* 4 */ + +#ifdef NID_cast5_ofb64 + return NID_cast5_ofb64; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "NID_mdc2WithRS", 14)) { + /* A */ + +#ifdef NID_mdc2WithRSA + return NID_mdc2WithRSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_sha1WithRS", 14)) { + /* A */ + +#ifdef NID_sha1WithRSA + return NID_sha1WithRSA; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "ERROR_WANT_REA", 14)) { + /* D */ + +#ifdef SSL_ERROR_WANT_READ + return SSL_ERROR_WANT_READ; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "R_UNKNOWN_STAT", 14)) { + /* E */ + +#ifdef SSL_R_UNKNOWN_STATE + return SSL_R_UNKNOWN_STATE; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_FN_NON", 14)) { + /* E */ + +#ifdef XN_FLAG_FN_NONE + return XN_FLAG_FN_NONE; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_ONELIN", 14)) { + /* E */ + +#ifdef XN_FLAG_ONELINE + return XN_FLAG_ONELINE; +#else + goto not_there; +#endif + + } + break; + case 'G': + if (!memcmp(name, "F_WRITE_PENDIN", 14)) { + /* G */ + +#ifdef SSL_F_WRITE_PENDING + return SSL_F_WRITE_PENDING; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "SESS_CACHE_BOT", 14)) { + /* H */ + +#ifdef SSL_SESS_CACHE_BOTH + return SSL_SESS_CACHE_BOTH; +#else + goto not_there; +#endif + + } + break; + case 'K': + if (!memcmp(name, "XN_FLAG_FN_MAS", 14)) { + /* K */ + +#ifdef XN_FLAG_FN_MASK + return XN_FLAG_FN_MASK; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "SSLEAY_PLATFOR", 14)) { + /* M */ + +#ifdef SSLEAY_PLATFORM + return SSLEAY_PLATFORM; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "OPENSSL_VERSIO", 14)) { + /* N */ + +#ifdef OPENSSL_VERSION + return OPENSSL_VERSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "SSLEAY_BUILT_O", 14)) { + /* N */ + +#ifdef SSLEAY_BUILT_ON + return SSLEAY_BUILT_ON; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "CB_CONNECT_LOO", 14)) { + /* P */ + +#ifdef SSL_CB_CONNECT_LOOP + return SSL_CB_CONNECT_LOOP; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "CB_CONNECT_EXI", 14)) { + /* T */ + +#ifdef SSL_CB_CONNECT_EXIT + return SSL_CB_CONNECT_EXIT; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "OP_NO_QUERY_MT", 14)) { + /* U */ + +#ifdef SSL_OP_NO_QUERY_MTU + return SSL_OP_NO_QUERY_MTU; +#else + goto not_there; +#endif + + } + break; + case 'Y': + if (!memcmp(name, "MODE_AUTO_RETR", 14)) { + /* Y */ + +#ifdef SSL_MODE_AUTO_RETRY + return SSL_MODE_AUTO_RETRY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "R_NO_PRIVATEKE", 14)) { + /* Y */ + +#ifdef SSL_R_NO_PRIVATEKEY + return SSL_R_NO_PRIVATEKEY; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_des_ede_cb", 14)) { + /* c */ + +#ifdef NID_des_ede_cbc + return NID_des_ede_cbc; +#else + goto not_there; +#endif + + } + break; + case 'd': + if (!memcmp(name, "NID_ms_code_in", 14)) { + /* d */ + +#ifdef NID_ms_code_ind + return NID_ms_code_ind; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_countryNam", 14)) { + /* e */ + +#ifdef NID_countryName + return NID_countryName; +#else + goto not_there; +#endif + + } + break; + case 'h': + if (!memcmp(name, "NID_client_aut", 14)) { + /* h */ + +#ifdef NID_client_auth + return NID_client_auth; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_server_aut", 14)) { + /* h */ + +#ifdef NID_server_auth + return NID_server_auth; +#else + goto not_there; +#endif + + } + break; + case 'm': + if (!memcmp(name, "NID_ms_code_co", 14)) { + /* m */ + +#ifdef NID_ms_code_com + return NID_ms_code_com; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_descriptio", 14)) { + /* n */ + +#ifdef NID_description + return NID_description; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_ms_ctl_sig", 14)) { + /* n */ + +#ifdef NID_ms_ctl_sign + return NID_ms_ctl_sign; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_dnQualifie", 14)) { + /* r */ + +#ifdef NID_dnQualifier + return NID_dnQualifier; +#else + goto not_there; +#endif + + } + break; + case 's': + if (!memcmp(name, "NID_info_acces", 14)) { + /* s */ + +#ifdef NID_info_access + return NID_info_access; +#else + goto not_there; +#endif + + } + break; + } + break; + case 16: + /* Names all of length 16. */ + /* ERROR_WANT_WRITE NID_des_ede3_cbc NID_friendlyName NID_hmacWithSHA1 + NID_localityName NID_pkcs7_digest NID_pkcs7_signed NID_serialNumber + OPENSSL_BUILT_ON OPENSSL_PLATFORM OP_EPHEMERAL_RSA OP_PKCS1_CHECK_1 + OP_PKCS1_CHECK_2 OP_SINGLE_DH_USE R_BAD_MAC_DECODE R_NO_CIPHER_LIST + X509_PURPOSE_ANY X509_TRUST_EMAIL XN_FLAG_FN_ALIGN XN_FLAG_SEP_MASK */ + /* Offset 8 gives the best switch position. */ + switch (name[8]) { + case '7': + if (!memcmp(name, "NID_pkcs7_digest", 16)) { + /* ^ */ + +#ifdef NID_pkcs7_digest + return NID_pkcs7_digest; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_pkcs7_signed", 16)) { + /* ^ */ + +#ifdef NID_pkcs7_signed + return NID_pkcs7_signed; +#else + goto not_there; +#endif + + } + break; + case 'B': + if (!memcmp(name, "OPENSSL_BUILT_ON", 16)) { + /* ^ */ + +#ifdef OPENSSL_BUILT_ON + return OPENSSL_BUILT_ON; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "R_BAD_MAC_DECODE", 16)) { + /* ^ */ + +#ifdef SSL_R_BAD_MAC_DECODE + return SSL_R_BAD_MAC_DECODE; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "OP_EPHEMERAL_RSA", 16)) { + /* ^ */ + +#ifdef SSL_OP_EPHEMERAL_RSA + return SSL_OP_EPHEMERAL_RSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_SINGLE_DH_USE", 16)) { + /* ^ */ + +#ifdef SSL_OP_SINGLE_DH_USE + return SSL_OP_SINGLE_DH_USE; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "XN_FLAG_FN_ALIGN", 16)) { + /* ^ */ + +#ifdef XN_FLAG_FN_ALIGN + return XN_FLAG_FN_ALIGN; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "R_NO_CIPHER_LIST", 16)) { + /* ^ */ + +#ifdef SSL_R_NO_CIPHER_LIST + return SSL_R_NO_CIPHER_LIST; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "ERROR_WANT_WRITE", 16)) { + /* ^ */ + +#ifdef SSL_ERROR_WANT_WRITE + return SSL_ERROR_WANT_WRITE; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "OPENSSL_PLATFORM", 16)) { + /* ^ */ + +#ifdef OPENSSL_PLATFORM + return OPENSSL_PLATFORM; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_PURPOSE_ANY", 16)) { + /* ^ */ + +#ifdef X509_PURPOSE_ANY + return X509_PURPOSE_ANY; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_TRUST_EMAIL", 16)) { + /* ^ */ + +#ifdef X509_TRUST_EMAIL + return X509_TRUST_EMAIL; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_SEP_MASK", 16)) { + /* ^ */ + +#ifdef XN_FLAG_SEP_MASK + return XN_FLAG_SEP_MASK; +#else + goto not_there; +#endif + + } + break; + case 'W': + if (!memcmp(name, "NID_hmacWithSHA1", 16)) { + /* ^ */ + +#ifdef NID_hmacWithSHA1 + return NID_hmacWithSHA1; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "OP_PKCS1_CHECK_1", 16)) { + /* ^ */ + +#ifdef SSL_OP_PKCS1_CHECK_1 + return SSL_OP_PKCS1_CHECK_1; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_PKCS1_CHECK_2", 16)) { + /* ^ */ + +#ifdef SSL_OP_PKCS1_CHECK_2 + return SSL_OP_PKCS1_CHECK_2; +#else + goto not_there; +#endif + + } + break; + case 'a': + if (!memcmp(name, "NID_serialNumber", 16)) { + /* ^ */ + +#ifdef NID_serialNumber + return NID_serialNumber; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_des_ede3_cbc", 16)) { + /* ^ */ + +#ifdef NID_des_ede3_cbc + return NID_des_ede3_cbc; +#else + goto not_there; +#endif + + } + break; + case 'l': + if (!memcmp(name, "NID_localityName", 16)) { + /* ^ */ + +#ifdef NID_localityName + return NID_localityName; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_friendlyName", 16)) { + /* ^ */ + +#ifdef NID_friendlyName + return NID_friendlyName; +#else + goto not_there; +#endif + + } + break; + } + break; + case 17: + /* Names all of length 17. */ + /* CB_HANDSHAKE_DONE ERROR_WANT_ACCEPT ERROR_ZERO_RETURN F_D2I_SSL_SESSION + F_I2D_SSL_SESSION F_SSL_SESSION_NEW NID_ad_ca_issuers NID_des_ede_cfb64 + NID_des_ede_ofb64 NID_dsaWithSHA1_2 NID_email_protect NID_ext_key_usage + NID_id_qt_unotice NID_rsaEncryption OP_NO_ANTI_REPLAY OP_NO_COMPRESSION + OP_TLSEXT_PADDING RECEIVED_SHUTDOWN R_BAD_WRITE_RETRY R_NO_CIPHER_MATCH + SESS_CACHE_CLIENT SESS_CACHE_SERVER X509_FILETYPE_PEM X509_TRUST_COMPAT + XN_FLAG_MULTILINE */ + /* Offset 12 gives the best switch position. */ + switch (name[12]) { + case 'C': + if (!memcmp(name, "ERROR_WANT_ACCEPT", 17)) { + /* ^ */ + +#ifdef SSL_ERROR_WANT_ACCEPT + return SSL_ERROR_WANT_ACCEPT; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "OP_TLSEXT_PADDING", 17)) { + /* ^ */ + +#ifdef SSL_OP_TLSEXT_PADDING + return SSL_OP_TLSEXT_PADDING; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "ERROR_ZERO_RETURN", 17)) { + /* ^ */ + +#ifdef SSL_ERROR_ZERO_RETURN + return SSL_ERROR_ZERO_RETURN; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_ANTI_REPLAY", 17)) { + /* ^ */ + +#ifdef SSL_OP_NO_ANTI_REPLAY + return SSL_OP_NO_ANTI_REPLAY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "SESS_CACHE_SERVER", 17)) { + /* ^ */ + +#ifdef SSL_SESS_CACHE_SERVER + return SSL_SESS_CACHE_SERVER; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_FILETYPE_PEM", 17)) { + /* ^ */ + +#ifdef X509_FILETYPE_PEM + return X509_FILETYPE_PEM; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "NID_dsaWithSHA1_2", 17)) { + /* ^ */ + +#ifdef NID_dsaWithSHA1_2 + return NID_dsaWithSHA1_2; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "XN_FLAG_MULTILINE", 17)) { + /* ^ */ + +#ifdef XN_FLAG_MULTILINE + return XN_FLAG_MULTILINE; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "SESS_CACHE_CLIENT", 17)) { + /* ^ */ + +#ifdef SSL_SESS_CACHE_CLIENT + return SSL_SESS_CACHE_CLIENT; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "R_NO_CIPHER_MATCH", 17)) { + /* ^ */ + +#ifdef SSL_R_NO_CIPHER_MATCH + return SSL_R_NO_CIPHER_MATCH; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "F_SSL_SESSION_NEW", 17)) { + /* ^ */ + +#ifdef SSL_F_SSL_SESSION_NEW + return SSL_F_SSL_SESSION_NEW; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_TRUST_COMPAT", 17)) { + /* ^ */ + +#ifdef X509_TRUST_COMPAT + return X509_TRUST_COMPAT; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "R_BAD_WRITE_RETRY", 17)) { + /* ^ */ + +#ifdef SSL_R_BAD_WRITE_RETRY + return SSL_R_BAD_WRITE_RETRY; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "F_D2I_SSL_SESSION", 17)) { + /* ^ */ + +#ifdef SSL_F_D2I_SSL_SESSION + return SSL_F_D2I_SSL_SESSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_I2D_SSL_SESSION", 17)) { + /* ^ */ + +#ifdef SSL_F_I2D_SSL_SESSION + return SSL_F_I2D_SSL_SESSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_NO_COMPRESSION", 17)) { + /* ^ */ + +#ifdef SSL_OP_NO_COMPRESSION + return SSL_OP_NO_COMPRESSION; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "RECEIVED_SHUTDOWN", 17)) { + /* ^ */ + +#ifdef SSL_RECEIVED_SHUTDOWN + return SSL_RECEIVED_SHUTDOWN; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "CB_HANDSHAKE_DONE", 17)) { + /* ^ */ + +#ifdef SSL_CB_HANDSHAKE_DONE + return SSL_CB_HANDSHAKE_DONE; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_des_ede_cfb64", 17)) { + /* ^ */ + +#ifdef NID_des_ede_cfb64 + return NID_des_ede_cfb64; +#else + goto not_there; +#endif + + } + break; + case 'o': + if (!memcmp(name, "NID_des_ede_ofb64", 17)) { + /* ^ */ + +#ifdef NID_des_ede_ofb64 + return NID_des_ede_ofb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_email_protect", 17)) { + /* ^ */ + +#ifdef NID_email_protect + return NID_email_protect; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_id_qt_unotice", 17)) { + /* ^ */ + +#ifdef NID_id_qt_unotice + return NID_id_qt_unotice; +#else + goto not_there; +#endif + + } + break; + case 'p': + if (!memcmp(name, "NID_rsaEncryption", 17)) { + /* ^ */ + +#ifdef NID_rsaEncryption + return NID_rsaEncryption; +#else + goto not_there; +#endif + + } + break; + case 's': + if (!memcmp(name, "NID_ad_ca_issuers", 17)) { + /* ^ */ + +#ifdef NID_ad_ca_issuers + return NID_ad_ca_issuers; +#else + goto not_there; +#endif + + } + break; + case 'u': + if (!memcmp(name, "NID_ext_key_usage", 17)) { + /* ^ */ + +#ifdef NID_ext_key_usage + return NID_ext_key_usage; +#else + goto not_there; +#endif + + } + break; + } + break; + case 18: + /* Names all of length 18. */ + /* CB_HANDSHAKE_START ERROR_WANT_CONNECT F_GET_CLIENT_HELLO + F_GET_SERVER_HELLO NID_des_ede3_cfb64 NID_des_ede3_ofb64 + NID_dhKeyAgreement OP_COOKIE_EXCHANGE OP_SINGLE_ECDH_USE + R_BAD_SSL_FILETYPE VERIFY_CLIENT_ONCE X509_FILETYPE_ASN1 */ + /* Offset 11 gives the best switch position. */ + switch (name[11]) { + case '3': + if (!memcmp(name, "NID_des_ede3_cfb64", 18)) { + /* ^ */ + +#ifdef NID_des_ede3_cfb64 + return NID_des_ede3_cfb64; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_des_ede3_ofb64", 18)) { + /* ^ */ + +#ifdef NID_des_ede3_ofb64 + return NID_des_ede3_ofb64; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "ERROR_WANT_CONNECT", 18)) { + /* ^ */ + +#ifdef SSL_ERROR_WANT_CONNECT + return SSL_ERROR_WANT_CONNECT; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OP_SINGLE_ECDH_USE", 18)) { + /* ^ */ + +#ifdef SSL_OP_SINGLE_ECDH_USE + return SSL_OP_SINGLE_ECDH_USE; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "CB_HANDSHAKE_START", 18)) { + /* ^ */ + +#ifdef SSL_CB_HANDSHAKE_START + return SSL_CB_HANDSHAKE_START; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "R_BAD_SSL_FILETYPE", 18)) { + /* ^ */ + +#ifdef SSL_R_BAD_SSL_FILETYPE + return SSL_R_BAD_SSL_FILETYPE; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "VERIFY_CLIENT_ONCE", 18)) { + /* ^ */ + +#ifdef SSL_VERIFY_CLIENT_ONCE + return SSL_VERIFY_CLIENT_ONCE; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "X509_FILETYPE_ASN1", 18)) { + /* ^ */ + +#ifdef X509_FILETYPE_ASN1 + return X509_FILETYPE_ASN1; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "F_GET_SERVER_HELLO", 18)) { + /* ^ */ + +#ifdef SSL_F_GET_SERVER_HELLO + return SSL_F_GET_SERVER_HELLO; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "F_GET_CLIENT_HELLO", 18)) { + /* ^ */ + +#ifdef SSL_F_GET_CLIENT_HELLO + return SSL_F_GET_CLIENT_HELLO; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "OP_COOKIE_EXCHANGE", 18)) { + /* ^ */ + +#ifdef SSL_OP_COOKIE_EXCHANGE + return SSL_OP_COOKIE_EXCHANGE; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_dhKeyAgreement", 18)) { + /* ^ */ + +#ifdef NID_dhKeyAgreement + return NID_dhKeyAgreement; +#else + goto not_there; +#endif + + } + break; + } + break; + case 19: + /* Names all of length 19. */ + /* F_CLIENT_MASTER_KEY F_GET_SERVER_VERIFY NID_invalidity_date + NID_issuer_alt_name NID_pkcs7_encrypted NID_pkcs7_enveloped + NID_rle_compression NID_safeContentsBag NID_sdsiCertificate + NID_x509Certificate OPENSSL_ENGINES_DIR OP_ALLOW_NO_DHE_KEX + OP_CISCO_ANYCONNECT OP_NON_EXPORT_FIRST OP_NO_RENEGOTIATION + OP_TLS_ROLLBACK_BUG */ + /* Offset 13 gives the best switch position. */ + switch (name[13]) { + case 'C': + if (!memcmp(name, "OP_TLS_ROLLBACK_BUG", 19)) { + /* ^ */ + +#ifdef SSL_OP_TLS_ROLLBACK_BUG + return SSL_OP_TLS_ROLLBACK_BUG; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "F_CLIENT_MASTER_KEY", 19)) { + /* ^ */ + +#ifdef SSL_F_CLIENT_MASTER_KEY + return SSL_F_CLIENT_MASTER_KEY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "OPENSSL_ENGINES_DIR", 19)) { + /* ^ */ + +#ifdef OPENSSL_ENGINES_DIR + return OPENSSL_ENGINES_DIR; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "OP_ALLOW_NO_DHE_KEX", 19)) { + /* ^ */ + +#ifdef SSL_OP_ALLOW_NO_DHE_KEX + return SSL_OP_ALLOW_NO_DHE_KEX; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "OP_NO_RENEGOTIATION", 19)) { + /* ^ */ + +#ifdef SSL_OP_NO_RENEGOTIATION + return SSL_OP_NO_RENEGOTIATION; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "OP_CISCO_ANYCONNECT", 19)) { + /* ^ */ + +#ifdef SSL_OP_CISCO_ANYCONNECT + return SSL_OP_CISCO_ANYCONNECT; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "F_GET_SERVER_VERIFY", 19)) { + /* ^ */ + +#ifdef SSL_F_GET_SERVER_VERIFY + return SSL_F_GET_SERVER_VERIFY; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "OP_NON_EXPORT_FIRST", 19)) { + /* ^ */ + +#ifdef SSL_OP_NON_EXPORT_FIRST + return SSL_OP_NON_EXPORT_FIRST; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_pkcs7_enveloped", 19)) { + /* ^ */ + +#ifdef NID_pkcs7_enveloped + return NID_pkcs7_enveloped; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_rle_compression", 19)) { + /* ^ */ + +#ifdef NID_rle_compression + return NID_rle_compression; +#else + goto not_there; +#endif + + } + break; + case 'f': + if (!memcmp(name, "NID_sdsiCertificate", 19)) { + /* ^ */ + +#ifdef NID_sdsiCertificate + return NID_sdsiCertificate; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_x509Certificate", 19)) { + /* ^ */ + +#ifdef NID_x509Certificate + return NID_x509Certificate; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_safeContentsBag", 19)) { + /* ^ */ + +#ifdef NID_safeContentsBag + return NID_safeContentsBag; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_pkcs7_encrypted", 19)) { + /* ^ */ + +#ifdef NID_pkcs7_encrypted + return NID_pkcs7_encrypted; +#else + goto not_there; +#endif + + } + break; + case 't': + if (!memcmp(name, "NID_issuer_alt_name", 19)) { + /* ^ */ + +#ifdef NID_issuer_alt_name + return NID_issuer_alt_name; +#else + goto not_there; +#endif + + } + break; + case 'y': + if (!memcmp(name, "NID_invalidity_date", 19)) { + /* ^ */ + +#ifdef NID_invalidity_date + return NID_invalidity_date; +#else + goto not_there; +#endif + + } + break; + } + break; + case 20: + /* Names all of length 20. */ + /* ASN1_STRFLGS_ESC_MSB ASN1_STRFLGS_RFC2253 F_CLIENT_CERTIFICATE + F_SSL_USE_PRIVATEKEY MODE_RELEASE_BUFFERS NID_netscape_comment + NID_organizationName NID_ripemd160WithRSA NID_subject_alt_name + NID_uniqueIdentifier NID_zlib_compression OP_PRIORITIZE_CHACHA + R_NO_CERTIFICATE_SET SESSION_ASN1_VERSION X509_TRUST_OCSP_SIGN + X509_V_ERR_PATH_LOOP */ + /* Offset 13 gives the best switch position. */ + switch (name[13]) { + case 'A': + if (!memcmp(name, "R_NO_CERTIFICATE_SET", 20)) { + /* ^ */ + +#ifdef SSL_R_NO_CERTIFICATE_SET + return SSL_R_NO_CERTIFICATE_SET; +#else + goto not_there; +#endif + + } + break; + case 'B': + if (!memcmp(name, "MODE_RELEASE_BUFFERS", 20)) { + /* ^ */ + +#ifdef SSL_MODE_RELEASE_BUFFERS + return SSL_MODE_RELEASE_BUFFERS; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "ASN1_STRFLGS_ESC_MSB", 20)) { + /* ^ */ + +#ifdef ASN1_STRFLGS_ESC_MSB + return ASN1_STRFLGS_ESC_MSB; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "F_CLIENT_CERTIFICATE", 20)) { + /* ^ */ + +#ifdef SSL_F_CLIENT_CERTIFICATE + return SSL_F_CLIENT_CERTIFICATE; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "ASN1_STRFLGS_RFC2253", 20)) { + /* ^ */ + +#ifdef ASN1_STRFLGS_RFC2253 + return ASN1_STRFLGS_RFC2253; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_TRUST_OCSP_SIGN", 20)) { + /* ^ */ + +#ifdef X509_TRUST_OCSP_SIGN + return X509_TRUST_OCSP_SIGN; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "X509_V_ERR_PATH_LOOP", 20)) { + /* ^ */ + +#ifdef X509_V_ERR_PATH_LOOP + return X509_V_ERR_PATH_LOOP; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "F_SSL_USE_PRIVATEKEY", 20)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_PRIVATEKEY + return SSL_F_SSL_USE_PRIVATEKEY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "SESSION_ASN1_VERSION", 20)) { + /* ^ */ + +#ifdef SSL_SESSION_ASN1_VERSION + return SSL_SESSION_ASN1_VERSION; +#else + goto not_there; +#endif + + } + break; + case 'W': + if (!memcmp(name, "NID_ripemd160WithRSA", 20)) { + /* ^ */ + +#ifdef NID_ripemd160WithRSA + return NID_ripemd160WithRSA; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "OP_PRIORITIZE_CHACHA", 20)) { + /* ^ */ + +#ifdef SSL_OP_PRIORITIZE_CHACHA + return SSL_OP_PRIORITIZE_CHACHA; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_netscape_comment", 20)) { + /* ^ */ + +#ifdef NID_netscape_comment + return NID_netscape_comment; +#else + goto not_there; +#endif + + } + break; + case 'i': + if (!memcmp(name, "NID_organizationName", 20)) { + /* ^ */ + +#ifdef NID_organizationName + return NID_organizationName; +#else + goto not_there; +#endif + + } + break; + case 'l': + if (!memcmp(name, "NID_subject_alt_name", 20)) { + /* ^ */ + +#ifdef NID_subject_alt_name + return NID_subject_alt_name; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_uniqueIdentifier", 20)) { + /* ^ */ + +#ifdef NID_uniqueIdentifier + return NID_uniqueIdentifier; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_zlib_compression", 20)) { + /* ^ */ + +#ifdef NID_zlib_compression + return NID_zlib_compression; +#else + goto not_there; +#endif + + } + break; + } + break; + case 21: + /* Names all of length 21. */ + /* ASN1_STRFLGS_ESC_CTRL F_GET_CLIENT_FINISHED F_GET_SERVER_FINISHED + F_REQUEST_CERTIFICATE F_SSL_GET_NEW_SESSION F_SSL_USE_CERTIFICATE + NID_SMIMECapabilities NID_basic_constraints NID_netscape_base_url + NID_pkcs9_contentType NID_pkcs9_signingTime OP_NETSCAPE_CA_DN_BUG + VERIFY_POST_HANDSHAKE X509_FILETYPE_DEFAULT X509_PURPOSE_CRL_SIGN + X509_TRUST_SSL_CLIENT X509_TRUST_SSL_SERVER X509_V_ERR_INVALID_CA + X509_V_ERR_OUT_OF_MEM X509_V_FLAG_CRL_CHECK XN_FLAG_SEP_CPLUS_SPC + XN_FLAG_SEP_MULTILINE XN_FLAG_SEP_SPLUS_SPC */ + /* Offset 15 gives the best switch position. */ + switch (name[15]) { + case 'C': + if (!memcmp(name, "ASN1_STRFLGS_ESC_CTRL", 21)) { + /* ^ */ + +#ifdef ASN1_STRFLGS_ESC_CTRL + return ASN1_STRFLGS_ESC_CTRL; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_TRUST_SSL_CLIENT", 21)) { + /* ^ */ + +#ifdef X509_TRUST_SSL_CLIENT + return X509_TRUST_SSL_CLIENT; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "OP_NETSCAPE_CA_DN_BUG", 21)) { + /* ^ */ + +#ifdef SSL_OP_NETSCAPE_CA_DN_BUG + return SSL_OP_NETSCAPE_CA_DN_BUG; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "VERIFY_POST_HANDSHAKE", 21)) { + /* ^ */ + +#ifdef SSL_VERIFY_POST_HANDSHAKE + return SSL_VERIFY_POST_HANDSHAKE; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "F_SSL_GET_NEW_SESSION", 21)) { + /* ^ */ + +#ifdef SSL_F_SSL_GET_NEW_SESSION + return SSL_F_SSL_GET_NEW_SESSION; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_FILETYPE_DEFAULT", 21)) { + /* ^ */ + +#ifdef X509_FILETYPE_DEFAULT + return X509_FILETYPE_DEFAULT; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "F_REQUEST_CERTIFICATE", 21)) { + /* ^ */ + +#ifdef SSL_F_REQUEST_CERTIFICATE + return SSL_F_REQUEST_CERTIFICATE; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_SSL_USE_CERTIFICATE", 21)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_CERTIFICATE + return SSL_F_SSL_USE_CERTIFICATE; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "X509_PURPOSE_CRL_SIGN", 21)) { + /* ^ */ + +#ifdef X509_PURPOSE_CRL_SIGN + return X509_PURPOSE_CRL_SIGN; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_INVALID_CA", 21)) { + /* ^ */ + +#ifdef X509_V_ERR_INVALID_CA + return X509_V_ERR_INVALID_CA; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "F_GET_CLIENT_FINISHED", 21)) { + /* ^ */ + +#ifdef SSL_F_GET_CLIENT_FINISHED + return SSL_F_GET_CLIENT_FINISHED; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_GET_SERVER_FINISHED", 21)) { + /* ^ */ + +#ifdef SSL_F_GET_SERVER_FINISHED + return SSL_F_GET_SERVER_FINISHED; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_OUT_OF_MEM", 21)) { + /* ^ */ + +#ifdef X509_V_ERR_OUT_OF_MEM + return X509_V_ERR_OUT_OF_MEM; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_TRUST_SSL_SERVER", 21)) { + /* ^ */ + +#ifdef X509_TRUST_SSL_SERVER + return X509_TRUST_SSL_SERVER; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "XN_FLAG_SEP_MULTILINE", 21)) { + /* ^ */ + +#ifdef XN_FLAG_SEP_MULTILINE + return XN_FLAG_SEP_MULTILINE; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "XN_FLAG_SEP_CPLUS_SPC", 21)) { + /* ^ */ + +#ifdef XN_FLAG_SEP_CPLUS_SPC + return XN_FLAG_SEP_CPLUS_SPC; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_SEP_SPLUS_SPC", 21)) { + /* ^ */ + +#ifdef XN_FLAG_SEP_SPLUS_SPC + return XN_FLAG_SEP_SPLUS_SPC; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "X509_V_FLAG_CRL_CHECK", 21)) { + /* ^ */ + +#ifdef X509_V_FLAG_CRL_CHECK + return X509_V_FLAG_CRL_CHECK; +#else + goto not_there; +#endif + + } + break; + case 'l': + if (!memcmp(name, "NID_SMIMECapabilities", 21)) { + /* ^ */ + +#ifdef NID_SMIMECapabilities + return NID_SMIMECapabilities; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_pkcs9_contentType", 21)) { + /* ^ */ + +#ifdef NID_pkcs9_contentType + return NID_pkcs9_contentType; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_pkcs9_signingTime", 21)) { + /* ^ */ + +#ifdef NID_pkcs9_signingTime + return NID_pkcs9_signingTime; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_basic_constraints", 21)) { + /* ^ */ + +#ifdef NID_basic_constraints + return NID_basic_constraints; +#else + goto not_there; +#endif + + } + break; + case 's': + if (!memcmp(name, "NID_netscape_base_url", 21)) { + /* ^ */ + +#ifdef NID_netscape_base_url + return NID_netscape_base_url; +#else + goto not_there; +#endif + + } + break; + } + break; + case 22: + /* Names all of length 22. */ + /* ASN1_STRFLGS_ESC_QUOTE ERROR_WANT_X509_LOOKUP F_SSL_SESSION_PRINT_FP + NID_netscape_cert_type NID_netscape_data_type NID_pkcs9_emailAddress + OPENSSL_VERSION_NUMBER OP_NO_ENCRYPT_THEN_MAC R_PEER_ERROR_NO_CIPHER + SESS_CACHE_NO_INTERNAL TLSEXT_STATUSTYPE_ocsp V_OCSP_CERTSTATUS_GOOD + X509_TRUST_OBJECT_SIGN X509_V_ERR_UNSPECIFIED X509_V_FLAG_USE_DELTAS + XN_FLAG_SEP_COMMA_PLUS _TEST_INVALID_CONSTANT */ + /* Offset 18 gives the best switch position. */ + switch (name[18]) { + case 'F': + if (!memcmp(name, "X509_V_ERR_UNSPECIFIED", 22)) { + /* ^ */ + +#ifdef X509_V_ERR_UNSPECIFIED + return X509_V_ERR_UNSPECIFIED; +#else + goto not_there; +#endif + + } + break; + case 'G': + if (!memcmp(name, "V_OCSP_CERTSTATUS_GOOD", 22)) { + /* ^ */ + +#ifdef V_OCSP_CERTSTATUS_GOOD + return V_OCSP_CERTSTATUS_GOOD; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "X509_V_FLAG_USE_DELTAS", 22)) { + /* ^ */ + +#ifdef X509_V_FLAG_USE_DELTAS + return X509_V_FLAG_USE_DELTAS; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "OPENSSL_VERSION_NUMBER", 22)) { + /* ^ */ + +#ifdef OPENSSL_VERSION_NUMBER + return OPENSSL_VERSION_NUMBER; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "ERROR_WANT_X509_LOOKUP", 22)) { + /* ^ */ + +#ifdef SSL_ERROR_WANT_X509_LOOKUP + return SSL_ERROR_WANT_X509_LOOKUP; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "R_PEER_ERROR_NO_CIPHER", 22)) { + /* ^ */ + +#ifdef SSL_R_PEER_ERROR_NO_CIPHER + return SSL_R_PEER_ERROR_NO_CIPHER; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "XN_FLAG_SEP_COMMA_PLUS", 22)) { + /* ^ */ + +#ifdef XN_FLAG_SEP_COMMA_PLUS + return XN_FLAG_SEP_COMMA_PLUS; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "SESS_CACHE_NO_INTERNAL", 22)) { + /* ^ */ + +#ifdef SSL_SESS_CACHE_NO_INTERNAL + return SSL_SESS_CACHE_NO_INTERNAL; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_TRUST_OBJECT_SIGN", 22)) { + /* ^ */ + +#ifdef X509_TRUST_OBJECT_SIGN + return X509_TRUST_OBJECT_SIGN; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "F_SSL_SESSION_PRINT_FP", 22)) { + /* ^ */ + +#ifdef SSL_F_SSL_SESSION_PRINT_FP + return SSL_F_SSL_SESSION_PRINT_FP; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "_TEST_INVALID_CONSTANT", 22)) { + /* ^ */ + goto not_there; + } + break; + case 'U': + if (!memcmp(name, "ASN1_STRFLGS_ESC_QUOTE", 22)) { + /* ^ */ + +#ifdef ASN1_STRFLGS_ESC_QUOTE + return ASN1_STRFLGS_ESC_QUOTE; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "OP_NO_ENCRYPT_THEN_MAC", 22)) { + /* ^ */ + +#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC + return SSL_OP_NO_ENCRYPT_THEN_MAC; +#else + goto not_there; +#endif + + } + break; + case 'o': + if (!memcmp(name, "TLSEXT_STATUSTYPE_ocsp", 22)) { + /* ^ */ + +#ifdef TLSEXT_STATUSTYPE_ocsp + return TLSEXT_STATUSTYPE_ocsp; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_pkcs9_emailAddress", 22)) { + /* ^ */ + +#ifdef NID_pkcs9_emailAddress + return NID_pkcs9_emailAddress; +#else + goto not_there; +#endif + + } + break; + case 't': + if (!memcmp(name, "NID_netscape_cert_type", 22)) { + /* ^ */ + +#ifdef NID_netscape_cert_type + return NID_netscape_cert_type; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_netscape_data_type", 22)) { + /* ^ */ + +#ifdef NID_netscape_data_type + return NID_netscape_data_type; +#else + goto not_there; +#endif + + } + break; + } + break; + case 23: + /* Names all of length 23. */ + /* F_GET_CLIENT_MASTER_KEY F_SSL_USE_RSAPRIVATEKEY LIBRESSL_VERSION_NUMBER + NID_pkcs8ShroudedKeyBag NID_pkcs9_messageDigest NID_stateOrProvinceName + OP_CRYPTOPRO_TLSEXT_BUG R_BAD_RESPONSE_ARGUMENT R_PUBLIC_KEY_IS_NOT_RSA + X509_PURPOSE_SMIME_SIGN X509_PURPOSE_SSL_CLIENT X509_PURPOSE_SSL_SERVER + X509_TRUST_OCSP_REQUEST X509_V_ERR_CERT_REVOKED X509_V_ERR_INVALID_CALL + X509_V_ERR_STORE_LOOKUP X509_V_FLAG_INHIBIT_ANY X509_V_FLAG_INHIBIT_MAP + X509_V_FLAG_POLICY_MASK X509_V_FLAG_X509_STRICT */ + /* Offset 14 gives the best switch position. */ + switch (name[14]) { + case '0': + if (!memcmp(name, "X509_V_FLAG_X509_STRICT", 23)) { + /* ^ */ + +#ifdef X509_V_FLAG_X509_STRICT + return X509_V_FLAG_X509_STRICT; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "F_GET_CLIENT_MASTER_KEY", 23)) { + /* ^ */ + +#ifdef SSL_F_GET_CLIENT_MASTER_KEY + return SSL_F_GET_CLIENT_MASTER_KEY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_INVALID_CALL", 23)) { + /* ^ */ + +#ifdef X509_V_ERR_INVALID_CALL + return X509_V_ERR_INVALID_CALL; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "X509_V_FLAG_INHIBIT_ANY", 23)) { + /* ^ */ + +#ifdef X509_V_FLAG_INHIBIT_ANY + return X509_V_FLAG_INHIBIT_ANY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_INHIBIT_MAP", 23)) { + /* ^ */ + +#ifdef X509_V_FLAG_INHIBIT_MAP + return X509_V_FLAG_INHIBIT_MAP; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "OP_CRYPTOPRO_TLSEXT_BUG", 23)) { + /* ^ */ + +#ifdef SSL_OP_CRYPTOPRO_TLSEXT_BUG + return SSL_OP_CRYPTOPRO_TLSEXT_BUG; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_POLICY_MASK", 23)) { + /* ^ */ + +#ifdef X509_V_FLAG_POLICY_MASK + return X509_V_FLAG_POLICY_MASK; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "X509_PURPOSE_SMIME_SIGN", 23)) { + /* ^ */ + +#ifdef X509_PURPOSE_SMIME_SIGN + return X509_PURPOSE_SMIME_SIGN; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "LIBRESSL_VERSION_NUMBER", 23)) { + /* ^ */ + +#ifdef LIBRESSL_VERSION_NUMBER + return LIBRESSL_VERSION_NUMBER; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "X509_TRUST_OCSP_REQUEST", 23)) { + /* ^ */ + +#ifdef X509_TRUST_OCSP_REQUEST + return X509_TRUST_OCSP_REQUEST; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "F_SSL_USE_RSAPRIVATEKEY", 23)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_RSAPRIVATEKEY + return SSL_F_SSL_USE_RSAPRIVATEKEY; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_STORE_LOOKUP", 23)) { + /* ^ */ + +#ifdef X509_V_ERR_STORE_LOOKUP + return X509_V_ERR_STORE_LOOKUP; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "R_PUBLIC_KEY_IS_NOT_RSA", 23)) { + /* ^ */ + +#ifdef SSL_R_PUBLIC_KEY_IS_NOT_RSA + return SSL_R_PUBLIC_KEY_IS_NOT_RSA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_PURPOSE_SSL_CLIENT", 23)) { + /* ^ */ + +#ifdef X509_PURPOSE_SSL_CLIENT + return X509_PURPOSE_SSL_CLIENT; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_PURPOSE_SSL_SERVER", 23)) { + /* ^ */ + +#ifdef X509_PURPOSE_SSL_SERVER + return X509_PURPOSE_SSL_SERVER; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "X509_V_ERR_CERT_REVOKED", 23)) { + /* ^ */ + +#ifdef X509_V_ERR_CERT_REVOKED + return X509_V_ERR_CERT_REVOKED; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "R_BAD_RESPONSE_ARGUMENT", 23)) { + /* ^ */ + +#ifdef SSL_R_BAD_RESPONSE_ARGUMENT + return SSL_R_BAD_RESPONSE_ARGUMENT; +#else + goto not_there; +#endif + + } + break; + case 'a': + if (!memcmp(name, "NID_pkcs9_messageDigest", 23)) { + /* ^ */ + +#ifdef NID_pkcs9_messageDigest + return NID_pkcs9_messageDigest; +#else + goto not_there; +#endif + + } + break; + case 'd': + if (!memcmp(name, "NID_pkcs8ShroudedKeyBag", 23)) { + /* ^ */ + +#ifdef NID_pkcs8ShroudedKeyBag + return NID_pkcs8ShroudedKeyBag; +#else + goto not_there; +#endif + + } + break; + case 'v': + if (!memcmp(name, "NID_stateOrProvinceName", 23)) { + /* ^ */ + +#ifdef NID_stateOrProvinceName + return NID_stateOrProvinceName; +#else + goto not_there; +#endif + + } + break; + } + break; + case 24: + /* Names all of length 24. */ + /* F_SSL_RSA_PUBLIC_ENCRYPT NID_certificate_policies + NID_md2WithRSAEncryption NID_md5WithRSAEncryption + NID_netscape_renewal_url NID_pbeWithMD2AndDES_CBC + NID_pbeWithMD2AndRC2_CBC NID_pbeWithMD5AndDES_CBC + NID_pbeWithMD5AndRC2_CBC NID_shaWithRSAEncryption + OP_LEGACY_SERVER_CONNECT OP_MICROSOFT_SESS_ID_BUG + OP_TLS_BLOCK_PADDING_BUG R_CHALLENGE_IS_DIFFERENT + R_CIPHER_TABLE_SRC_ERROR R_PEER_ERROR_CERTIFICATE + R_READ_WRONG_PACKET_TYPE SESS_CACHE_NO_AUTO_CLEAR + X509_PURPOSE_OCSP_HELPER X509_V_ERR_CERT_REJECTED + X509_V_ERR_DANE_NO_MATCH X509_V_ERR_NO_VALID_SCTS + X509_V_FLAG_POLICY_CHECK */ + /* Offset 13 gives the best switch position. */ + switch (name[13]) { + case '2': + if (!memcmp(name, "NID_pbeWithMD2AndDES_CBC", 24)) { + /* ^ */ + +#ifdef NID_pbeWithMD2AndDES_CBC + return NID_pbeWithMD2AndDES_CBC; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_pbeWithMD2AndRC2_CBC", 24)) { + /* ^ */ + +#ifdef NID_pbeWithMD2AndRC2_CBC + return NID_pbeWithMD2AndRC2_CBC; +#else + goto not_there; +#endif + + } + break; + case '5': + if (!memcmp(name, "NID_pbeWithMD5AndDES_CBC", 24)) { + /* ^ */ + +#ifdef NID_pbeWithMD5AndDES_CBC + return NID_pbeWithMD5AndDES_CBC; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_pbeWithMD5AndRC2_CBC", 24)) { + /* ^ */ + +#ifdef NID_pbeWithMD5AndRC2_CBC + return NID_pbeWithMD5AndRC2_CBC; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "NID_md2WithRSAEncryption", 24)) { + /* ^ */ + +#ifdef NID_md2WithRSAEncryption + return NID_md2WithRSAEncryption; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_md5WithRSAEncryption", 24)) { + /* ^ */ + +#ifdef NID_md5WithRSAEncryption + return NID_md5WithRSAEncryption; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_shaWithRSAEncryption", 24)) { + /* ^ */ + +#ifdef NID_shaWithRSAEncryption + return NID_shaWithRSAEncryption; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "R_PEER_ERROR_CERTIFICATE", 24)) { + /* ^ */ + +#ifdef SSL_R_PEER_ERROR_CERTIFICATE + return SSL_R_PEER_ERROR_CERTIFICATE; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "R_CIPHER_TABLE_SRC_ERROR", 24)) { + /* ^ */ + +#ifdef SSL_R_CIPHER_TABLE_SRC_ERROR + return SSL_R_CIPHER_TABLE_SRC_ERROR; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "F_SSL_RSA_PUBLIC_ENCRYPT", 24)) { + /* ^ */ + +#ifdef SSL_F_SSL_RSA_PUBLIC_ENCRYPT + return SSL_F_SSL_RSA_PUBLIC_ENCRYPT; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "X509_V_ERR_DANE_NO_MATCH", 24)) { + /* ^ */ + +#ifdef X509_V_ERR_DANE_NO_MATCH + return X509_V_ERR_DANE_NO_MATCH; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_PURPOSE_OCSP_HELPER", 24)) { + /* ^ */ + +#ifdef X509_PURPOSE_OCSP_HELPER + return X509_PURPOSE_OCSP_HELPER; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_POLICY_CHECK", 24)) { + /* ^ */ + +#ifdef X509_V_FLAG_POLICY_CHECK + return X509_V_FLAG_POLICY_CHECK; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "OP_TLS_BLOCK_PADDING_BUG", 24)) { + /* ^ */ + +#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG + return SSL_OP_TLS_BLOCK_PADDING_BUG; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "R_READ_WRONG_PACKET_TYPE", 24)) { + /* ^ */ + +#ifdef SSL_R_READ_WRONG_PACKET_TYPE + return SSL_R_READ_WRONG_PACKET_TYPE; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "X509_V_ERR_CERT_REJECTED", 24)) { + /* ^ */ + +#ifdef X509_V_ERR_CERT_REJECTED + return X509_V_ERR_CERT_REJECTED; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "OP_MICROSOFT_SESS_ID_BUG", 24)) { + /* ^ */ + +#ifdef SSL_OP_MICROSOFT_SESS_ID_BUG + return SSL_OP_MICROSOFT_SESS_ID_BUG; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "R_CHALLENGE_IS_DIFFERENT", 24)) { + /* ^ */ + +#ifdef SSL_R_CHALLENGE_IS_DIFFERENT + return SSL_R_CHALLENGE_IS_DIFFERENT; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "OP_LEGACY_SERVER_CONNECT", 24)) { + /* ^ */ + +#ifdef SSL_OP_LEGACY_SERVER_CONNECT + return SSL_OP_LEGACY_SERVER_CONNECT; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "SESS_CACHE_NO_AUTO_CLEAR", 24)) { + /* ^ */ + +#ifdef SSL_SESS_CACHE_NO_AUTO_CLEAR + return SSL_SESS_CACHE_NO_AUTO_CLEAR; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_NO_VALID_SCTS", 24)) { + /* ^ */ + +#ifdef X509_V_ERR_NO_VALID_SCTS + return X509_V_ERR_NO_VALID_SCTS; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_netscape_renewal_url", 24)) { + /* ^ */ + +#ifdef NID_netscape_renewal_url + return NID_netscape_renewal_url; +#else + goto not_there; +#endif + + } + break; + case 't': + if (!memcmp(name, "NID_certificate_policies", 24)) { + /* ^ */ + +#ifdef NID_certificate_policies + return NID_certificate_policies; +#else + goto not_there; +#endif + + } + break; + } + break; + case 25: + /* Names all of length 25. */ + /* F_SSL_RSA_PRIVATE_DECRYPT F_SSL_USE_PRIVATEKEY_ASN1 + F_SSL_USE_PRIVATEKEY_FILE MODE_ENABLE_PARTIAL_WRITE + NID_pbeWithSHA1AndDES_CBC NID_pbeWithSHA1AndRC2_CBC + NID_sha1WithRSAEncryption OP_MSIE_SSLV2_RSA_PADDING + OP_NETSCAPE_CHALLENGE_BUG OP_SAFARI_ECDHE_ECDSA_BUG + R_BAD_AUTHENTICATION_TYPE V_OCSP_CERTSTATUS_REVOKED + V_OCSP_CERTSTATUS_UNKNOWN X509_V_ERR_CA_MD_TOO_WEAK + X509_V_ERR_CERT_UNTRUSTED X509_V_ERR_EMAIL_MISMATCH + X509_V_ERR_INVALID_NON_CA X509_V_ERR_SUBTREE_MINMAX + X509_V_FLAG_CRL_CHECK_ALL X509_V_FLAG_NOTIFY_POLICY + X509_V_FLAG_NO_ALT_CHAINS X509_V_FLAG_NO_CHECK_TIME + X509_V_FLAG_PARTIAL_CHAIN X509_V_FLAG_TRUSTED_FIRST */ + /* Offset 20 gives the best switch position. */ + switch (name[20]) { + case '2': + if (!memcmp(name, "NID_pbeWithSHA1AndRC2_CBC", 25)) { + /* ^ */ + +#ifdef NID_pbeWithSHA1AndRC2_CBC + return NID_pbeWithSHA1AndRC2_CBC; +#else + goto not_there; +#endif + + } + break; + case 'A': + if (!memcmp(name, "OP_SAFARI_ECDHE_ECDSA_BUG", 25)) { + /* ^ */ + +#ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG + return SSL_OP_SAFARI_ECDHE_ECDSA_BUG; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "F_SSL_RSA_PRIVATE_DECRYPT", 25)) { + /* ^ */ + +#ifdef SSL_F_SSL_RSA_PRIVATE_DECRYPT + return SSL_F_SSL_RSA_PRIVATE_DECRYPT; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_PARTIAL_CHAIN", 25)) { + /* ^ */ + +#ifdef X509_V_FLAG_PARTIAL_CHAIN + return X509_V_FLAG_PARTIAL_CHAIN; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "OP_MSIE_SSLV2_RSA_PADDING", 25)) { + /* ^ */ + +#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING + return SSL_OP_MSIE_SSLV2_RSA_PADDING; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "OP_NETSCAPE_CHALLENGE_BUG", 25)) { + /* ^ */ + +#ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG + return SSL_OP_NETSCAPE_CHALLENGE_BUG; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "X509_V_FLAG_TRUSTED_FIRST", 25)) { + /* ^ */ + +#ifdef X509_V_FLAG_TRUSTED_FIRST + return X509_V_FLAG_TRUSTED_FIRST; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "X509_V_FLAG_NO_ALT_CHAINS", 25)) { + /* ^ */ + +#ifdef X509_V_FLAG_NO_ALT_CHAINS + return X509_V_FLAG_NO_ALT_CHAINS; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "X509_V_ERR_SUBTREE_MINMAX", 25)) { + /* ^ */ + +#ifdef X509_V_ERR_SUBTREE_MINMAX + return X509_V_ERR_SUBTREE_MINMAX; +#else + goto not_there; +#endif + + } + break; + case 'K': + if (!memcmp(name, "V_OCSP_CERTSTATUS_UNKNOWN", 25)) { + /* ^ */ + +#ifdef V_OCSP_CERTSTATUS_UNKNOWN + return V_OCSP_CERTSTATUS_UNKNOWN; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_CRL_CHECK_ALL", 25)) { + /* ^ */ + +#ifdef X509_V_FLAG_CRL_CHECK_ALL + return X509_V_FLAG_CRL_CHECK_ALL; +#else + goto not_there; +#endif + + } + break; + case 'M': + if (!memcmp(name, "X509_V_ERR_EMAIL_MISMATCH", 25)) { + /* ^ */ + +#ifdef X509_V_ERR_EMAIL_MISMATCH + return X509_V_ERR_EMAIL_MISMATCH; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_INVALID_NON_CA", 25)) { + /* ^ */ + +#ifdef X509_V_ERR_INVALID_NON_CA + return X509_V_ERR_INVALID_NON_CA; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_NOTIFY_POLICY", 25)) { + /* ^ */ + +#ifdef X509_V_FLAG_NOTIFY_POLICY + return X509_V_FLAG_NOTIFY_POLICY; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "NID_pbeWithSHA1AndDES_CBC", 25)) { + /* ^ */ + +#ifdef NID_pbeWithSHA1AndDES_CBC + return NID_pbeWithSHA1AndDES_CBC; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "X509_V_ERR_CERT_UNTRUSTED", 25)) { + /* ^ */ + +#ifdef X509_V_ERR_CERT_UNTRUSTED + return X509_V_ERR_CERT_UNTRUSTED; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "V_OCSP_CERTSTATUS_REVOKED", 25)) { + /* ^ */ + +#ifdef V_OCSP_CERTSTATUS_REVOKED + return V_OCSP_CERTSTATUS_REVOKED; +#else + goto not_there; +#endif + + } + break; + case 'W': + if (!memcmp(name, "MODE_ENABLE_PARTIAL_WRITE", 25)) { + /* ^ */ + +#ifdef SSL_MODE_ENABLE_PARTIAL_WRITE + return SSL_MODE_ENABLE_PARTIAL_WRITE; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "F_SSL_USE_PRIVATEKEY_ASN1", 25)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_PRIVATEKEY_ASN1 + return SSL_F_SSL_USE_PRIVATEKEY_ASN1; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_SSL_USE_PRIVATEKEY_FILE", 25)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_PRIVATEKEY_FILE + return SSL_F_SSL_USE_PRIVATEKEY_FILE; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "R_BAD_AUTHENTICATION_TYPE", 25)) { + /* ^ */ + +#ifdef SSL_R_BAD_AUTHENTICATION_TYPE + return SSL_R_BAD_AUTHENTICATION_TYPE; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_CA_MD_TOO_WEAK", 25)) { + /* ^ */ + +#ifdef X509_V_ERR_CA_MD_TOO_WEAK + return X509_V_ERR_CA_MD_TOO_WEAK; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_FLAG_NO_CHECK_TIME", 25)) { + /* ^ */ + +#ifdef X509_V_FLAG_NO_CHECK_TIME + return X509_V_FLAG_NO_CHECK_TIME; +#else + goto not_there; +#endif + + } + break; + case 'p': + if (!memcmp(name, "NID_sha1WithRSAEncryption", 25)) { + /* ^ */ + +#ifdef NID_sha1WithRSAEncryption + return NID_sha1WithRSAEncryption; +#else + goto not_there; +#endif + + } + break; + } + break; + case 26: + /* Names all of length 26. */ + /* F_SSL_USE_CERTIFICATE_ASN1 F_SSL_USE_CERTIFICATE_FILE + NID_netscape_ca_policy_url NID_netscape_cert_sequence + NID_organizationalUnitName NID_pbeWithMD5AndCast5_CBC + NID_pkcs9_countersignature NID_pkcs9_unstructuredName + NID_subject_key_identifier OP_ENABLE_MIDDLEBOX_COMPAT + OP_NO_CLIENT_RENEGOTIATION R_INVALID_CHALLENGE_LENGTH + R_NO_CERTIFICATE_SPECIFIED R_PUBLIC_KEY_ENCRYPT_ERROR + X509_PURPOSE_NS_SSL_SERVER X509_PURPOSE_SMIME_ENCRYPT + X509_V_ERR_CRL_HAS_EXPIRED X509_V_ERR_INVALID_PURPOSE + X509_V_FLAG_SUITEB_128_LOS X509_V_FLAG_SUITEB_192_LOS + X509_V_FLAG_USE_CHECK_TIME */ + /* Offset 20 gives the best switch position. */ + switch (name[20]) { + case '2': + if (!memcmp(name, "X509_V_FLAG_SUITEB_128_LOS", 26)) { + /* ^ */ + +#ifdef X509_V_FLAG_SUITEB_128_LOS + return X509_V_FLAG_SUITEB_128_LOS; +#else + goto not_there; +#endif + + } + break; + case '9': + if (!memcmp(name, "X509_V_FLAG_SUITEB_192_LOS", 26)) { + /* ^ */ + +#ifdef X509_V_FLAG_SUITEB_192_LOS + return X509_V_FLAG_SUITEB_192_LOS; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "OP_ENABLE_MIDDLEBOX_COMPAT", 26)) { + /* ^ */ + +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT + return SSL_OP_ENABLE_MIDDLEBOX_COMPAT; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "R_NO_CERTIFICATE_SPECIFIED", 26)) { + /* ^ */ + +#ifdef SSL_R_NO_CERTIFICATE_SPECIFIED + return SSL_R_NO_CERTIFICATE_SPECIFIED; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "F_SSL_USE_CERTIFICATE_ASN1", 26)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_CERTIFICATE_ASN1 + return SSL_F_SSL_USE_CERTIFICATE_ASN1; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_SSL_USE_CERTIFICATE_FILE", 26)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_CERTIFICATE_FILE + return SSL_F_SSL_USE_CERTIFICATE_FILE; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "OP_NO_CLIENT_RENEGOTIATION", 26)) { + /* ^ */ + +#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION + return SSL_OP_NO_CLIENT_RENEGOTIATION; +#else + goto not_there; +#endif + + } + break; + case 'K': + if (!memcmp(name, "X509_V_FLAG_USE_CHECK_TIME", 26)) { + /* ^ */ + +#ifdef X509_V_FLAG_USE_CHECK_TIME + return X509_V_FLAG_USE_CHECK_TIME; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "R_INVALID_CHALLENGE_LENGTH", 26)) { + /* ^ */ + +#ifdef SSL_R_INVALID_CHALLENGE_LENGTH + return SSL_R_INVALID_CHALLENGE_LENGTH; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "X509_PURPOSE_SMIME_ENCRYPT", 26)) { + /* ^ */ + +#ifdef X509_PURPOSE_SMIME_ENCRYPT + return X509_PURPOSE_SMIME_ENCRYPT; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_PURPOSE_NS_SSL_SERVER", 26)) { + /* ^ */ + +#ifdef X509_PURPOSE_NS_SSL_SERVER + return X509_PURPOSE_NS_SSL_SERVER; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "X509_V_ERR_INVALID_PURPOSE", 26)) { + /* ^ */ + +#ifdef X509_V_ERR_INVALID_PURPOSE + return X509_V_ERR_INVALID_PURPOSE; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "X509_V_ERR_CRL_HAS_EXPIRED", 26)) { + /* ^ */ + +#ifdef X509_V_ERR_CRL_HAS_EXPIRED + return X509_V_ERR_CRL_HAS_EXPIRED; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "R_PUBLIC_KEY_ENCRYPT_ERROR", 26)) { + /* ^ */ + +#ifdef SSL_R_PUBLIC_KEY_ENCRYPT_ERROR + return SSL_R_PUBLIC_KEY_ENCRYPT_ERROR; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_netscape_ca_policy_url", 26)) { + /* ^ */ + +#ifdef NID_netscape_ca_policy_url + return NID_netscape_ca_policy_url; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_pkcs9_unstructuredName", 26)) { + /* ^ */ + +#ifdef NID_pkcs9_unstructuredName + return NID_pkcs9_unstructuredName; +#else + goto not_there; +#endif + + } + break; + case 'i': + if (!memcmp(name, "NID_organizationalUnitName", 26)) { + /* ^ */ + +#ifdef NID_organizationalUnitName + return NID_organizationalUnitName; +#else + goto not_there; +#endif + + } + break; + case 'n': + if (!memcmp(name, "NID_pkcs9_countersignature", 26)) { + /* ^ */ + +#ifdef NID_pkcs9_countersignature + return NID_pkcs9_countersignature; +#else + goto not_there; +#endif + + } + break; + case 'q': + if (!memcmp(name, "NID_netscape_cert_sequence", 26)) { + /* ^ */ + +#ifdef NID_netscape_cert_sequence + return NID_netscape_cert_sequence; +#else + goto not_there; +#endif + + } + break; + case 't': + if (!memcmp(name, "NID_pbeWithMD5AndCast5_CBC", 26)) { + /* ^ */ + +#ifdef NID_pbeWithMD5AndCast5_CBC + return NID_pbeWithMD5AndCast5_CBC; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "NID_subject_key_identifier", 26)) { + /* ^ */ + +#ifdef NID_subject_key_identifier + return NID_subject_key_identifier; +#else + goto not_there; +#endif + + } + break; + } + break; + case 27: + /* Names all of length 27. */ + /* NID_crl_distribution_points NID_netscape_cert_extension + NID_netscape_revocation_url NID_pbe_WithSHA1And40BitRC4 + NID_pkcs9_challengePassword NID_pkcs9_extCertAttributes + OP_CIPHER_SERVER_PREFERENCE OP_SSLEAY_080_CLIENT_DH_BUG + R_BAD_SSL_SESSION_ID_LENGTH R_UNKNOWN_REMOTE_ERROR_TYPE + VERIFY_FAIL_IF_NO_PEER_CERT X509_PURPOSE_TIMESTAMP_SIGN + X509_V_ERR_CA_KEY_TOO_SMALL X509_V_ERR_CERT_HAS_EXPIRED + X509_V_ERR_EE_KEY_TOO_SMALL X509_V_FLAG_CB_ISSUER_CHECK + X509_V_FLAG_EXPLICIT_POLICY X509_V_FLAG_IGNORE_CRITICAL + XN_FLAG_DUMP_UNKNOWN_FIELDS */ + /* Offset 13 gives the best switch position. */ + switch (name[13]) { + case 'B': + if (!memcmp(name, "X509_V_FLAG_CB_ISSUER_CHECK", 27)) { + /* ^ */ + +#ifdef X509_V_FLAG_CB_ISSUER_CHECK + return X509_V_FLAG_CB_ISSUER_CHECK; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "NID_pkcs9_extCertAttributes", 27)) { + /* ^ */ + +#ifdef NID_pkcs9_extCertAttributes + return NID_pkcs9_extCertAttributes; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "VERIFY_FAIL_IF_NO_PEER_CERT", 27)) { + /* ^ */ + +#ifdef SSL_VERIFY_FAIL_IF_NO_PEER_CERT + return SSL_VERIFY_FAIL_IF_NO_PEER_CERT; +#else + goto not_there; +#endif + + } + break; + case 'G': + if (!memcmp(name, "X509_V_FLAG_IGNORE_CRITICAL", 27)) { + /* ^ */ + +#ifdef X509_V_FLAG_IGNORE_CRITICAL + return X509_V_FLAG_IGNORE_CRITICAL; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "NID_pbe_WithSHA1And40BitRC4", 27)) { + /* ^ */ + +#ifdef NID_pbe_WithSHA1And40BitRC4 + return NID_pbe_WithSHA1And40BitRC4; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "R_UNKNOWN_REMOTE_ERROR_TYPE", 27)) { + /* ^ */ + +#ifdef SSL_R_UNKNOWN_REMOTE_ERROR_TYPE + return SSL_R_UNKNOWN_REMOTE_ERROR_TYPE; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "X509_V_ERR_CERT_HAS_EXPIRED", 27)) { + /* ^ */ + +#ifdef X509_V_ERR_CERT_HAS_EXPIRED + return X509_V_ERR_CERT_HAS_EXPIRED; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "R_BAD_SSL_SESSION_ID_LENGTH", 27)) { + /* ^ */ + +#ifdef SSL_R_BAD_SSL_SESSION_ID_LENGTH + return SSL_R_BAD_SSL_SESSION_ID_LENGTH; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "X509_PURPOSE_TIMESTAMP_SIGN", 27)) { + /* ^ */ + +#ifdef X509_PURPOSE_TIMESTAMP_SIGN + return X509_PURPOSE_TIMESTAMP_SIGN; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "XN_FLAG_DUMP_UNKNOWN_FIELDS", 27)) { + /* ^ */ + +#ifdef XN_FLAG_DUMP_UNKNOWN_FIELDS + return XN_FLAG_DUMP_UNKNOWN_FIELDS; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "OP_CIPHER_SERVER_PREFERENCE", 27)) { + /* ^ */ + +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE + return SSL_OP_CIPHER_SERVER_PREFERENCE; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "X509_V_FLAG_EXPLICIT_POLICY", 27)) { + /* ^ */ + +#ifdef X509_V_FLAG_EXPLICIT_POLICY + return X509_V_FLAG_EXPLICIT_POLICY; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "OP_SSLEAY_080_CLIENT_DH_BUG", 27)) { + /* ^ */ + +#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG + return SSL_OP_SSLEAY_080_CLIENT_DH_BUG; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_CA_KEY_TOO_SMALL", 27)) { + /* ^ */ + +#ifdef X509_V_ERR_CA_KEY_TOO_SMALL + return X509_V_ERR_CA_KEY_TOO_SMALL; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_EE_KEY_TOO_SMALL", 27)) { + /* ^ */ + +#ifdef X509_V_ERR_EE_KEY_TOO_SMALL + return X509_V_ERR_EE_KEY_TOO_SMALL; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_netscape_cert_extension", 27)) { + /* ^ */ + +#ifdef NID_netscape_cert_extension + return NID_netscape_cert_extension; +#else + goto not_there; +#endif + + } + break; + case 'i': + if (!memcmp(name, "NID_crl_distribution_points", 27)) { + /* ^ */ + +#ifdef NID_crl_distribution_points + return NID_crl_distribution_points; +#else + goto not_there; +#endif + + } + break; + case 'l': + if (!memcmp(name, "NID_pkcs9_challengePassword", 27)) { + /* ^ */ + +#ifdef NID_pkcs9_challengePassword + return NID_pkcs9_challengePassword; +#else + goto not_there; +#endif + + } + break; + case 'r': + if (!memcmp(name, "NID_netscape_revocation_url", 27)) { + /* ^ */ + +#ifdef NID_netscape_revocation_url + return NID_netscape_revocation_url; +#else + goto not_there; +#endif + + } + break; + } + break; + case 28: + /* Names all of length 28. */ + /* F_SSL_USE_RSAPRIVATEKEY_ASN1 F_SSL_USE_RSAPRIVATEKEY_FILE + NID_authority_key_identifier NID_netscape_ssl_server_name + NID_pbe_WithSHA1And128BitRC4 NID_pkcs7_signedAndEnveloped + NID_private_key_usage_period SESS_CACHE_NO_INTERNAL_STORE + X509_CHECK_FLAG_NO_WILDCARDS X509_V_ERR_CRL_NOT_YET_VALID + X509_V_ERR_HOSTNAME_MISMATCH X509_V_ERR_INVALID_EXTENSION + X509_V_ERR_OCSP_CERT_UNKNOWN X509_V_ERR_UNABLE_TO_GET_CRL + X509_V_ERR_UNNESTED_RESOURCE */ + /* Offset 11 gives the best switch position. */ + switch (name[11]) { + case 'C': + if (!memcmp(name, "X509_V_ERR_CRL_NOT_YET_VALID", 28)) { + /* ^ */ + +#ifdef X509_V_ERR_CRL_NOT_YET_VALID + return X509_V_ERR_CRL_NOT_YET_VALID; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "X509_CHECK_FLAG_NO_WILDCARDS", 28)) { + /* ^ */ + +#ifdef X509_CHECK_FLAG_NO_WILDCARDS + return X509_CHECK_FLAG_NO_WILDCARDS; +#else + goto not_there; +#endif + + } + break; + case 'H': + if (!memcmp(name, "X509_V_ERR_HOSTNAME_MISMATCH", 28)) { + /* ^ */ + +#ifdef X509_V_ERR_HOSTNAME_MISMATCH + return X509_V_ERR_HOSTNAME_MISMATCH; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "X509_V_ERR_INVALID_EXTENSION", 28)) { + /* ^ */ + +#ifdef X509_V_ERR_INVALID_EXTENSION + return X509_V_ERR_INVALID_EXTENSION; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "SESS_CACHE_NO_INTERNAL_STORE", 28)) { + /* ^ */ + +#ifdef SSL_SESS_CACHE_NO_INTERNAL_STORE + return SSL_SESS_CACHE_NO_INTERNAL_STORE; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_OCSP_CERT_UNKNOWN", 28)) { + /* ^ */ + +#ifdef X509_V_ERR_OCSP_CERT_UNKNOWN + return X509_V_ERR_OCSP_CERT_UNKNOWN; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "F_SSL_USE_RSAPRIVATEKEY_ASN1", 28)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 + return SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "F_SSL_USE_RSAPRIVATEKEY_FILE", 28)) { + /* ^ */ + +#ifdef SSL_F_SSL_USE_RSAPRIVATEKEY_FILE + return SSL_F_SSL_USE_RSAPRIVATEKEY_FILE; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_GET_CRL", 28)) { + /* ^ */ + +#ifdef X509_V_ERR_UNABLE_TO_GET_CRL + return X509_V_ERR_UNABLE_TO_GET_CRL; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_UNNESTED_RESOURCE", 28)) { + /* ^ */ + +#ifdef X509_V_ERR_UNNESTED_RESOURCE + return X509_V_ERR_UNNESTED_RESOURCE; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "NID_private_key_usage_period", 28)) { + /* ^ */ + +#ifdef NID_private_key_usage_period + return NID_private_key_usage_period; +#else + goto not_there; +#endif + + } + break; + case 'e': + if (!memcmp(name, "NID_netscape_ssl_server_name", 28)) { + /* ^ */ + +#ifdef NID_netscape_ssl_server_name + return NID_netscape_ssl_server_name; +#else + goto not_there; +#endif + + } + break; + case 'h': + if (!memcmp(name, "NID_pbe_WithSHA1And128BitRC4", 28)) { + /* ^ */ + +#ifdef NID_pbe_WithSHA1And128BitRC4 + return NID_pbe_WithSHA1And128BitRC4; +#else + goto not_there; +#endif + + } + break; + case 'i': + if (!memcmp(name, "NID_pkcs7_signedAndEnveloped", 28)) { + /* ^ */ + +#ifdef NID_pkcs7_signedAndEnveloped + return NID_pkcs7_signedAndEnveloped; +#else + goto not_there; +#endif + + } + break; + case 't': + if (!memcmp(name, "NID_authority_key_identifier", 28)) { + /* ^ */ + +#ifdef NID_authority_key_identifier + return NID_authority_key_identifier; +#else + goto not_there; +#endif + + } + break; + } + break; + case 29: + /* Names all of length 29. */ + /* NID_pkcs9_unstructuredAddress OCSP_RESPONSE_STATUS_TRYLATER + OP_MICROSOFT_BIG_SSLV3_BUFFER R_SSL_SESSION_ID_IS_DIFFERENT + SESS_CACHE_NO_INTERNAL_LOOKUP X509_V_ERR_AKID_SKID_MISMATCH + X509_V_ERR_CERT_NOT_YET_VALID X509_V_ERR_EXCLUDED_VIOLATION + X509_V_ERR_NO_EXPLICIT_POLICY X509_V_ERR_OCSP_VERIFY_FAILED + X509_V_ERR_OCSP_VERIFY_NEEDED X509_V_FLAG_ALLOW_PROXY_CERTS */ + /* Offset 16 gives the best switch position. */ + switch (name[16]) { + case 'A': + if (!memcmp(name, "OCSP_RESPONSE_STATUS_TRYLATER", 29)) { + /* ^ */ + +#ifdef OCSP_RESPONSE_STATUS_TRYLATER + return OCSP_RESPONSE_STATUS_TRYLATER; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "X509_V_ERR_EXCLUDED_VIOLATION", 29)) { + /* ^ */ + +#ifdef X509_V_ERR_EXCLUDED_VIOLATION + return X509_V_ERR_EXCLUDED_VIOLATION; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "X509_V_ERR_CERT_NOT_YET_VALID", 29)) { + /* ^ */ + +#ifdef X509_V_ERR_CERT_NOT_YET_VALID + return X509_V_ERR_CERT_NOT_YET_VALID; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "X509_V_ERR_NO_EXPLICIT_POLICY", 29)) { + /* ^ */ + +#ifdef X509_V_ERR_NO_EXPLICIT_POLICY + return X509_V_ERR_NO_EXPLICIT_POLICY; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_V_ERR_AKID_SKID_MISMATCH", 29)) { + /* ^ */ + +#ifdef X509_V_ERR_AKID_SKID_MISMATCH + return X509_V_ERR_AKID_SKID_MISMATCH; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "SESS_CACHE_NO_INTERNAL_LOOKUP", 29)) { + /* ^ */ + +#ifdef SSL_SESS_CACHE_NO_INTERNAL_LOOKUP + return SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; +#else + goto not_there; +#endif + + } + break; + case 'V': + if (!memcmp(name, "X509_V_ERR_OCSP_VERIFY_FAILED", 29)) { + /* ^ */ + +#ifdef X509_V_ERR_OCSP_VERIFY_FAILED + return X509_V_ERR_OCSP_VERIFY_FAILED; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_OCSP_VERIFY_NEEDED", 29)) { + /* ^ */ + +#ifdef X509_V_ERR_OCSP_VERIFY_NEEDED + return X509_V_ERR_OCSP_VERIFY_NEEDED; +#else + goto not_there; +#endif + + } + break; + case 'W': + if (!memcmp(name, "X509_V_FLAG_ALLOW_PROXY_CERTS", 29)) { + /* ^ */ + +#ifdef X509_V_FLAG_ALLOW_PROXY_CERTS + return X509_V_FLAG_ALLOW_PROXY_CERTS; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "OP_MICROSOFT_BIG_SSLV3_BUFFER", 29)) { + /* ^ */ + +#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER + return SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "R_SSL_SESSION_ID_IS_DIFFERENT", 29)) { + /* ^ */ + +#ifdef SSL_R_SSL_SESSION_ID_IS_DIFFERENT + return SSL_R_SSL_SESSION_ID_IS_DIFFERENT; +#else + goto not_there; +#endif + + } + break; + case 'c': + if (!memcmp(name, "NID_pkcs9_unstructuredAddress", 29)) { + /* ^ */ + +#ifdef NID_pkcs9_unstructuredAddress + return NID_pkcs9_unstructuredAddress; +#else + goto not_there; +#endif + + } + break; + } + break; + case 30: + /* Names all of length 30. */ + /* NID_netscape_ca_revocation_url OP_DONT_INSERT_EMPTY_FRAGMENTS + OP_SSLREF2_REUSE_CERT_TYPE_BUG R_UNABLE_TO_EXTRACT_PUBLIC_KEY + X509_V_ERR_CERT_CHAIN_TOO_LONG X509_V_ERR_DIFFERENT_CRL_SCOPE + X509_V_ERR_IP_ADDRESS_MISMATCH X509_V_ERR_PERMITTED_VIOLATION + X509_V_FLAG_CHECK_SS_SIGNATURE */ + /* Offset 24 gives the best switch position. */ + switch (name[24]) { + case 'G': + if (!memcmp(name, "OP_DONT_INSERT_EMPTY_FRAGMENTS", 30)) { + /* ^ */ + +#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + return SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "R_UNABLE_TO_EXTRACT_PUBLIC_KEY", 30)) { + /* ^ */ + +#ifdef SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY + return SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "X509_V_ERR_PERMITTED_VIOLATION", 30)) { + /* ^ */ + +#ifdef X509_V_ERR_PERMITTED_VIOLATION + return X509_V_ERR_PERMITTED_VIOLATION; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "X509_V_FLAG_CHECK_SS_SIGNATURE", 30)) { + /* ^ */ + +#ifdef X509_V_FLAG_CHECK_SS_SIGNATURE + return X509_V_FLAG_CHECK_SS_SIGNATURE; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_CERT_CHAIN_TOO_LONG", 30)) { + /* ^ */ + +#ifdef X509_V_ERR_CERT_CHAIN_TOO_LONG + return X509_V_ERR_CERT_CHAIN_TOO_LONG; +#else + goto not_there; +#endif + + } + break; + case 'P': + if (!memcmp(name, "OP_SSLREF2_REUSE_CERT_TYPE_BUG", 30)) { + /* ^ */ + +#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG + return SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_V_ERR_IP_ADDRESS_MISMATCH", 30)) { + /* ^ */ + +#ifdef X509_V_ERR_IP_ADDRESS_MISMATCH + return X509_V_ERR_IP_ADDRESS_MISMATCH; +#else + goto not_there; +#endif + + } + break; + case '_': + if (!memcmp(name, "X509_V_ERR_DIFFERENT_CRL_SCOPE", 30)) { + /* ^ */ + +#ifdef X509_V_ERR_DIFFERENT_CRL_SCOPE + return X509_V_ERR_DIFFERENT_CRL_SCOPE; +#else + goto not_there; +#endif + + } + break; + case 'o': + if (!memcmp(name, "NID_netscape_ca_revocation_url", 30)) { + /* ^ */ + +#ifdef NID_netscape_ca_revocation_url + return NID_netscape_ca_revocation_url; +#else + goto not_there; +#endif + + } + break; + } + break; + case 31: + /* Names all of length 31. */ + /* MIN_RSA_MODULUS_LENGTH_IN_BYTES MODE_ACCEPT_MOVING_WRITE_BUFFER + NID_pbe_WithSHA1And40BitRC2_CBC OCSP_RESPONSE_STATUS_SUCCESSFUL + X509_V_ERR_KEYUSAGE_NO_CERTSIGN X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + X509_V_ERR_PATH_LENGTH_EXCEEDED X509_V_FLAG_SUITEB_128_LOS_ONLY */ + /* Offset 30 gives the best switch position. */ + switch (name[30]) { + case 'C': + if (!memcmp(name, "NID_pbe_WithSHA1And40BitRC2_CB", 30)) { + /* C */ + +#ifdef NID_pbe_WithSHA1And40BitRC2_CBC + return NID_pbe_WithSHA1And40BitRC2_CBC; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "X509_V_ERR_PATH_LENGTH_EXCEEDE", 30)) { + /* D */ + +#ifdef X509_V_ERR_PATH_LENGTH_EXCEEDED + return X509_V_ERR_PATH_LENGTH_EXCEEDED; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "OCSP_RESPONSE_STATUS_SUCCESSFU", 30)) { + /* L */ + +#ifdef OCSP_RESPONSE_STATUS_SUCCESSFUL + return OCSP_RESPONSE_STATUS_SUCCESSFUL; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "X509_V_ERR_KEYUSAGE_NO_CERTSIG", 30)) { + /* N */ + +#ifdef X509_V_ERR_KEYUSAGE_NO_CERTSIGN + return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; +#else + goto not_there; +#endif + + } + if (!memcmp(name, "X509_V_ERR_KEYUSAGE_NO_CRL_SIG", 30)) { + /* N */ + +#ifdef X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + return X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "MODE_ACCEPT_MOVING_WRITE_BUFFE", 30)) { + /* R */ + +#ifdef SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + return SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "MIN_RSA_MODULUS_LENGTH_IN_BYTE", 30)) { + /* S */ + +#ifdef SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES + return SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES; +#else + goto not_there; +#endif + + } + break; + case 'Y': + if (!memcmp(name, "X509_V_FLAG_SUITEB_128_LOS_ONL", 30)) { + /* Y */ + +#ifdef X509_V_FLAG_SUITEB_128_LOS_ONLY + return X509_V_FLAG_SUITEB_128_LOS_ONLY; +#else + goto not_there; +#endif + + } + break; + } + break; + case 32: + /* Names all of length 32. */ + /* NID_pbe_WithSHA1And128BitRC2_CBC OCSP_RESPONSE_STATUS_SIGREQUIRED + X509_V_ERR_CRL_SIGNATURE_FAILURE X509_V_ERR_SUITE_B_INVALID_CURVE + X509_V_FLAG_EXTENDED_CRL_SUPPORT */ + /* Offset 25 gives the best switch position. */ + switch (name[25]) { + case 'D': + if (!memcmp(name, "X509_V_ERR_SUITE_B_INVALID_CURVE", 32)) { + /* ^ */ + +#ifdef X509_V_ERR_SUITE_B_INVALID_CURVE + return X509_V_ERR_SUITE_B_INVALID_CURVE; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "OCSP_RESPONSE_STATUS_SIGREQUIRED", 32)) { + /* ^ */ + +#ifdef OCSP_RESPONSE_STATUS_SIGREQUIRED + return OCSP_RESPONSE_STATUS_SIGREQUIRED; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "X509_V_ERR_CRL_SIGNATURE_FAILURE", 32)) { + /* ^ */ + +#ifdef X509_V_ERR_CRL_SIGNATURE_FAILURE + return X509_V_ERR_CRL_SIGNATURE_FAILURE; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "NID_pbe_WithSHA1And128BitRC2_CBC", 32)) { + /* ^ */ + +#ifdef NID_pbe_WithSHA1And128BitRC2_CBC + return NID_pbe_WithSHA1And128BitRC2_CBC; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_V_FLAG_EXTENDED_CRL_SUPPORT", 32)) { + /* ^ */ + +#ifdef X509_V_FLAG_EXTENDED_CRL_SUPPORT + return X509_V_FLAG_EXTENDED_CRL_SUPPORT; +#else + goto not_there; +#endif + + } + break; + } + break; + case 33: + /* Names all of length 33. */ + /* OCSP_RESPONSE_STATUS_UNAUTHORIZED X509_V_ERR_CERT_SIGNATURE_FAILURE */ + /* Offset 32 gives the best switch position. */ + switch (name[32]) { + case 'D': + if (!memcmp(name, "OCSP_RESPONSE_STATUS_UNAUTHORIZE", 32)) { + /* D */ + +#ifdef OCSP_RESPONSE_STATUS_UNAUTHORIZED + return OCSP_RESPONSE_STATUS_UNAUTHORIZED; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "X509_V_ERR_CERT_SIGNATURE_FAILUR", 32)) { + /* E */ + +#ifdef X509_V_ERR_CERT_SIGNATURE_FAILURE + return X509_V_ERR_CERT_SIGNATURE_FAILURE; +#else + goto not_there; +#endif + + } + break; + } + break; + case 34: + /* Names all of length 34. */ + /* OCSP_RESPONSE_STATUS_INTERNALERROR OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + X509_V_ERR_SUBJECT_ISSUER_MISMATCH X509_V_ERR_SUITE_B_INVALID_VERSION + X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED X509_V_ERR_UNSUPPORTED_NAME_SYNTAX */ + /* Offset 24 gives the best switch position. */ + switch (name[24]) { + case 'A': + if (!memcmp(name, "X509_V_ERR_UNSUPPORTED_NAME_SYNTAX", 34)) { + /* ^ */ + +#ifdef X509_V_ERR_UNSUPPORTED_NAME_SYNTAX + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", 34)) { + /* ^ */ + +#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + return SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "OCSP_RESPONSE_STATUS_INTERNALERROR", 34)) { + /* ^ */ + +#ifdef OCSP_RESPONSE_STATUS_INTERNALERROR + return OCSP_RESPONSE_STATUS_INTERNALERROR; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "X509_V_ERR_SUITE_B_INVALID_VERSION", 34)) { + /* ^ */ + +#ifdef X509_V_ERR_SUITE_B_INVALID_VERSION + return X509_V_ERR_SUITE_B_INVALID_VERSION; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED", 34)) { + /* ^ */ + +#ifdef X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED + return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "X509_V_ERR_SUBJECT_ISSUER_MISMATCH", 34)) { + /* ^ */ + +#ifdef X509_V_ERR_SUBJECT_ISSUER_MISMATCH + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; +#else + goto not_there; +#endif + + } + break; + } + break; + case 35: + /* Names all of length 35. */ + /* OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG R_PEER_DID_NOT_RETURN_A_CERTIFICATE + X509_CHECK_FLAG_NEVER_CHECK_SUBJECT X509_V_ERR_APPLICATION_VERIFICATION + X509_V_ERR_INVALID_POLICY_EXTENSION X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER + */ + /* Offset 29 gives the best switch position. */ + switch (name[29]) { + case 'C': + if (!memcmp(name, "X509_V_ERR_APPLICATION_VERIFICATION", 35)) { + /* ^ */ + +#ifdef X509_V_ERR_APPLICATION_VERIFICATION + return X509_V_ERR_APPLICATION_VERIFICATION; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "X509_V_ERR_INVALID_POLICY_EXTENSION", 35)) { + /* ^ */ + +#ifdef X509_V_ERR_INVALID_POLICY_EXTENSION + return X509_V_ERR_INVALID_POLICY_EXTENSION; +#else + goto not_there; +#endif + + } + break; + case 'F': + if (!memcmp(name, "R_PEER_DID_NOT_RETURN_A_CERTIFICATE", 35)) { + /* ^ */ + +#ifdef SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE + return SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE; +#else + goto not_there; +#endif + + } + break; + case 'G': + if (!memcmp(name, "OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", 35)) { + /* ^ */ + +#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + return SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER", 35)) { + /* ^ */ + +#ifdef X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER + return X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "X509_CHECK_FLAG_NEVER_CHECK_SUBJECT", 35)) { + /* ^ */ + +#ifdef X509_CHECK_FLAG_NEVER_CHECK_SUBJECT + return X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; +#else + goto not_there; +#endif + + } + break; + } + break; + case 36: + /* Names all of length 36. */ + /* OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + X509_V_ERR_CRL_PATH_VALIDATION_ERROR + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + X509_V_ERR_SUITE_B_INVALID_ALGORITHM + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT */ + /* Offset 25 gives the best switch position. */ + switch (name[25]) { + case 'A': + if (!memcmp(name, "X509_V_ERR_CRL_PATH_VALIDATION_ERROR", 36)) { + /* ^ */ + +#ifdef X509_V_ERR_CRL_PATH_VALIDATION_ERROR + return X509_V_ERR_CRL_PATH_VALIDATION_ERROR; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "X509_V_ERR_SUITE_B_INVALID_ALGORITHM", 36)) { + /* ^ */ + +#ifdef X509_V_ERR_SUITE_B_INVALID_ALGORITHM + return X509_V_ERR_SUITE_B_INVALID_ALGORITHM; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT", 36)) { + /* ^ */ + +#ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + return X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", 36)) { + /* ^ */ + +#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT + return X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; +#else + goto not_there; +#endif + + } + break; + case 'L': + if (!memcmp(name, "X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS", 36)) { + /* ^ */ + +#ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + return X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", 36)) { + /* ^ */ + +#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION + return SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN", 36)) { + /* ^ */ + +#ifdef X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + return X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; +#else + goto not_there; +#endif + + } + break; + } + break; + case 37: + /* Names all of length 37. */ + /* OCSP_RESPONSE_STATUS_MALFORMEDREQUEST + X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED */ + /* Offset 31 gives the best switch position. */ + switch (name[31]) { + case 'C': + if (!memcmp(name, "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED", 37)) { + /* ^ */ + +#ifdef X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED + return X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED; +#else + goto not_there; +#endif + + } + break; + case 'D': + if (!memcmp(name, "X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS", 37)) { + /* ^ */ + +#ifdef X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS + return X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "OCSP_RESPONSE_STATUS_MALFORMEDREQUEST", 37)) { + /* ^ */ + +#ifdef OCSP_RESPONSE_STATUS_MALFORMEDREQUEST + return OCSP_RESPONSE_STATUS_MALFORMEDREQUEST; +#else + goto not_there; +#endif + + } + break; + } + break; + case 38: + /* Names all of length 38. */ + /* NID_pbe_WithSHA1And2_Key_TripleDES_CBC + NID_pbe_WithSHA1And3_Key_TripleDES_CBC + X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE */ + /* Offset 19 gives the best switch position. */ + switch (name[19]) { + case '2': + if (!memcmp(name, "NID_pbe_WithSHA1And2_Key_TripleDES_CBC", 38)) { + /* ^ */ + +#ifdef NID_pbe_WithSHA1And2_Key_TripleDES_CBC + return NID_pbe_WithSHA1And2_Key_TripleDES_CBC; +#else + goto not_there; +#endif + + } + break; + case '3': + if (!memcmp(name, "NID_pbe_WithSHA1And3_Key_TripleDES_CBC", 38)) { + /* ^ */ + +#ifdef NID_pbe_WithSHA1And3_Key_TripleDES_CBC + return NID_pbe_WithSHA1And3_Key_TripleDES_CBC; +#else + goto not_there; +#endif + + } + break; + case 'R': + if (!memcmp(name, "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT", 38)) { + /* ^ */ + +#ifdef X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + return X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE", 38)) { + /* ^ */ + +#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; +#else + goto not_there; +#endif + + } + break; + case 'U': + if (!memcmp(name, "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH", 38)) { + /* ^ */ + +#ifdef X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; +#else + goto not_there; +#endif + + } + break; + } + break; + case 39: + /* Names all of length 39. */ + /* X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION */ + /* Offset 26 gives the best switch position. */ + switch (name[26]) { + case 'A': + if (!memcmp(name, "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION", 39)) { + /* ^ */ + +#ifdef X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION + return X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION; +#else + goto not_there; +#endif + + } + break; + case 'C': + if (!memcmp(name, "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION", 39)) { + /* ^ */ + +#ifdef X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION + return X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS", 39)) { + /* ^ */ + +#ifdef X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + return X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS; +#else + goto not_there; +#endif + + } + break; + } + break; + case 40: + /* Names all of length 40. */ + /* X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD + X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE + X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX + X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE */ + /* Offset 26 gives the best switch position. */ + switch (name[26]) { + case 'E': + if (!memcmp(name, "X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE", 40)) { + /* ^ */ + +#ifdef X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE + return X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE; +#else + goto not_there; +#endif + + } + break; + case 'I': + if (!memcmp(name, "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE", 40)) { + /* ^ */ + +#ifdef X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE + return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", 40)) { + /* ^ */ + +#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD + return X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX", 40)) { + /* ^ */ + +#ifdef X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; +#else + goto not_there; +#endif + + } + break; + } + break; + case 41: + /* Names all of length 41. */ + /* OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD + X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED */ + /* Offset 26 gives the best switch position. */ + switch (name[26]) { + case 'E': + if (!memcmp(name, "R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE", 41)) { + /* ^ */ + +#ifdef SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE + return SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE; +#else + goto not_there; +#endif + + } + break; + case 'N': + if (!memcmp(name, "OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", 41)) { + /* ^ */ + +#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + return SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; +#else + goto not_there; +#endif + + } + break; + case 'O': + if (!memcmp(name, "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", 41)) { + /* ^ */ + +#ifdef X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD + return X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; +#else + goto not_there; +#endif + + } + break; + case 'S': + if (!memcmp(name, "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD", 41)) { + /* ^ */ + +#ifdef X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD + return X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; +#else + goto not_there; +#endif + + } + break; + case 'T': + if (!memcmp(name, "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED", 41)) { + /* ^ */ + +#ifdef X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED + return X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED; +#else + goto not_there; +#endif + + } + break; + case 'X': + if (!memcmp(name, "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD", 41)) { + /* ^ */ + +#ifdef X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD + return X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; +#else + goto not_there; +#endif + + } + break; + } + break; + case 42: + /* Names all of length 42. */ + /* X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE */ + /* Offset 29 gives the best switch position. */ + switch (name[29]) { + case 'C': + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE", 42)) { + /* ^ */ + +#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE + return X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE; +#else + goto not_there; +#endif + + } + break; + case 'E': + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE", 42)) { + /* ^ */ + +#ifdef X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE + return X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; +#else + goto not_there; +#endif + + } + break; + } + break; + case 43: + /* Names all of length 43. */ + /* X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE + X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION */ + /* Offset 14 gives the best switch position. */ + switch (name[14]) { + case 'A': + if (!memcmp(name, "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION", 43)) { + /* ^ */ + +#ifdef X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION + return X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; +#else + goto not_there; +#endif + + } + break; + case 'B': + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE", 43)) { + /* ^ */ + +#ifdef X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE + return X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE; +#else + goto not_there; +#endif + + } + break; + } + break; + case 44: + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", 44)) { + +#ifdef X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + return X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; +#else + goto not_there; +#endif + + } + break; + case 45: + if (!memcmp(name, "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", 45)) { + +#ifdef X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY + return X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; +#else + goto not_there; +#endif + + } + break; + case 46: + if (!memcmp(name, "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM", 46)) { + +#ifdef X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM + return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM; +#else + goto not_there; +#endif + + } + break; + case 47: + if (!memcmp(name, "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256", 47)) { + +#ifdef X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 + return X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256; +#else + goto not_there; +#endif + + } + break; + } + + errno = EINVAL; + return 0; + +not_there: + errno = ENOENT; + return 0; + +} diff --git a/examples/bio.pl b/examples/bio.pl new file mode 100644 index 0000000..5406618 --- /dev/null +++ b/examples/bio.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl -w +# bio.pl mikem@open.com.au +# +# Test and demonstrate BIO interface + +use Net::SSLeay qw(die_now); + +$data = '0123456789' x 100; +$len = length($data); + +$b = &Net::SSLeay::BIO_new(&Net::SSLeay::BIO_s_mem()) + or die_now("Could not create memory BIO $!"); + +&Net::SSLeay::BIO_write($b, $data) + or die_now("Could not write memory BIO $!"); + +# Should now have 1000 bytes in BIO +$pending = &Net::SSLeay::BIO_pending($b); +die("Incorrect result from BIO_pending: $pending. Should be $len") + unless $pending == $len; + +# Partial read of 9 bytes +$len = 9; +$part = &Net::SSLeay::BIO_read($b, $len); +$nlen = length($part); +die("Incorrect result from BIO_read: $len. Should be 9") + unless $nlen == $len; + +die("Incorrect data from BIO_read: $len. Should be 012345678") + unless $part eq '012345678'; + +# Should be 991 bytes left +$len = 991; +$pending = &Net::SSLeay::BIO_pending($b); +die("Incorrect result from BIO_pending: $pending. Should be $len") + unless $pending == $len; + +# Read the rest +$part = &Net::SSLeay::BIO_read($b); +$nlen = length($part); +die("Incorrect result from BIO_read: $len. Should be 991") + unless $len == $nlen; + +&Net::SSLeay::BIO_free($b); + +print "OK\n"; +exit; diff --git a/examples/bulk.pl b/examples/bulk.pl new file mode 100755 index 0000000..f855c30 --- /dev/null +++ b/examples/bulk.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl -w +# bulk.pl - 8.6.1998, Sampo Kellomaki +# Send tons of stuff over SSL (just for testing). +# There's also an example about using the call back. + +use Socket; +use Net::SSLeay qw(die_now die_if_ssl_error); +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +($dest_serv, $port, $how_much) = @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); + +# The network connection is now open, lets fire up SSL + +$ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); +$ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); +Net::SSLeay::set_fd($ssl, fileno(S)); # Must use fileno +Net::SSLeay::connect($ssl); +die_if_ssl_error('bulk: ssl connect'); +print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; + +$cert = Net::SSLeay::get_peer_certificate($ssl); +die_if_ssl_error('get_peer_certificate'); +print "Subject Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_subject_name($cert)) . "\n"; +print "Issuer Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_issuer_name($cert)) . "\n"; + +# Exchange data + +$data = 'A' x $how_much; +Net::SSLeay::ssl_write_all($ssl, \$data) or die "ssl write failed"; +shutdown S, 1; # Half close --> No more output, sends EOF to server +$got = Net::SSLeay::ssl_read_all($ssl) or die "ssl read failed"; + +Net::SSLeay::free ($ssl); # Tear down connection +Net::SSLeay::CTX_free ($ctx); +close S; + +print $data eq $got ? "OK\n" : "ERROR\n"; +exit; + +__END__ diff --git a/examples/callback.pl b/examples/callback.pl new file mode 100755 index 0000000..c0f805b --- /dev/null +++ b/examples/callback.pl @@ -0,0 +1,101 @@ +#!/usr/bin/perl -w +# callback.pl - 8.6.1998, Sampo Kellomaki +# 31.7.1999, fixed callback args, --Sampo +# 7.4.2001, adapted to 0.9.6a and numerous bug reports --Sampo +# +# Test and demonstrate verify call back +# +# WARNING! Although this code works, it is by no means stable. Expect +# that this stuff may break with newer than 0.9.3a --Sampo + +use Socket; +use Net::SSLeay qw(die_now die_if_ssl_error); +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +($dest_serv, $port, $cert_dir) = @ARGV; # Read command line + +my $callback_called = 0; + +$ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); +#Net::SSLeay::CTX_set_default_verify_paths($ctx); +Net::SSLeay::CTX_load_verify_locations($ctx, '', $cert_dir) + or die_now("CTX load verify loc=`$cert_dir' $!"); +Net::SSLeay::CTX_set_verify($ctx, &Net::SSLeay::VERIFY_PEER, \&verify2); +die_if_ssl_error('callback: ctx set verify'); + +$port = getservbyname ($port, 'tcp') unless $port =~ /^\d+$/; +$dest_ip = gethostbyname ($dest_serv); + +$dest_serv_params = pack ('S n a4 x8', &AF_INET, $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); + +# The network connection is now open, lets fire up SSL + +$ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); +#Net::SSLeay::set_verify ($ssl, &Net::SSLeay::VERIFY_PEER, \&verify); +Net::SSLeay::set_fd($ssl, fileno(S)); +print "callback: starting ssl connect...\n"; +Net::SSLeay::connect($ssl); +die_if_ssl_error('callback: ssl connect'); + +print "Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; +print Net::SSLeay::dump_peer_certificate($ssl); + +Net::SSLeay::ssl_write_all($ssl,"\tcallback ok\n"); +shutdown S, 1; +my $ra; +print defined($ra = Net::SSLeay::ssl_read_all($ssl)) ? $ra : ''; + +Net::SSLeay::free ($ssl); +Net::SSLeay::CTX_free ($ctx); +close S; + +print $callback_called ? "OK\n" : "ERROR\n"; +exit; + +sub verify2 { + my ($ok, $x509_store_ctx) = @_; + print "**** Verify 2 called ($ok)\n"; + my $x = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx); + if ($x) { + print "Certificate:\n"; + print " Subject Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_subject_name($x)) + . "\n"; + print " Issuer Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_issuer_name($x)) + . "\n"; + } + $callback_called++; + return 1; +} + +sub verify { + my ($ok, $x509_store_ctx) = @_; + + print "**** Verify called ($ok)\n"; + my $x = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx); + if ($x) { + print "Certificate:\n"; + print " Subject Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_subject_name($x)) + . "\n"; + print " Issuer Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_issuer_name($x)) + . "\n"; + } + $callback_called++; + return 1; #$ok; # 1=accept cert, 0=reject +} + +__END__ diff --git a/examples/cb-testi.pl b/examples/cb-testi.pl new file mode 100644 index 0000000..1e2f62f --- /dev/null +++ b/examples/cb-testi.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl + +require Net::SSLeay; + +sub provide_password { +# ($buf,$siz,$rwflag,$pwd)=@_; + $_[0]="1234"; + return 4; +} + +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +Net::SSLeay::randomize(); + +$ctx=Net::SSLeay::CTX_new(); +Net::SSLeay::CTX_set_options($ctx,&Net::SSLeay::OP_ALL); + +Net::SSLeay::CTX_set_default_passwd_cb($ctx,\&provide_password); +$r=Net::SSLeay::CTX_use_PrivateKey_file($ctx,"server_key.pem",&Net::SSLeay::FILETYPE_PEM()); +if($r==0) { + print "v��r� avain\n"; +} else { + print "OK\n"; +} diff --git a/examples/cli-cert.pl b/examples/cli-cert.pl new file mode 100644 index 0000000..f5e5a0b --- /dev/null +++ b/examples/cli-cert.pl @@ -0,0 +1,116 @@ +#!/usr/bin/perl +# cli-cert.pl +# 8.6.1998, originally written as stdio_bulk.pl Sampo Kellomaki +# 8.12.2001, adapted to test client certificates +# +# Contact server using client side certificate. Demonstrates how to +# set up the client and how to make the server request the certificate. +# This also demonstrates how you can communicate via arbitrary stream, not +# just a TCP one. +# $Id: cli-cert.pl,v 1.2 2003/06/13 21:14:41 sampo Exp $ + +use Socket; +use Net::SSLeay qw(die_now die_if_ssl_error); +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +#$Net::SSLeay::trace = 2; + +($cert_pem, $key_pem, $cert_dir) = @ARGV; # Read command line +$how_much = 10000; + +### Note: the following initialization is common for both client +### and the server. In particular, it is important that VERIFY_PEER +### is sent on the server as well, because otherwise the client +### certificate will never be requested. + +$ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); +Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem) or die "key"; +Net::SSLeay::CTX_load_verify_locations($ctx, '', $cert_dir) + or die_now("CTX load verify loc=`$cert_dir' $!"); +Net::SSLeay::CTX_set_verify($ctx, &Net::SSLeay::VERIFY_PEER, \&verify); +die_if_ssl_error('callback: ctx set verify'); + +pipe RS, WC or die "pipe 1 ($!)"; +pipe RC, WS or die "pipe 2 ($!)"; +select WC; $| = 1; +select WS; $| = 1; +select STDOUT; +$| = 1; + +if ($child_pid = fork) { + print "$$: I'm the server for child $child_pid\n"; + $ssl = Net::SSLeay::new($ctx) or die_now "$$: new ($ssl) ($!)"; + + Net::SSLeay::set_rfd($ssl, fileno(RS)); + Net::SSLeay::set_wfd($ssl, fileno(WS)); + + Net::SSLeay::accept($ssl) and die_if_ssl_error("$$: ssl accept: $!"); + print "$$: Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; + print "$$: client cert: " . Net::SSLeay::dump_peer_certificate($ssl); + + $got = Net::SSLeay::ssl_read_all($ssl,$how_much) + or die "$$: ssl read failed"; + print "$$: got " . length($got) . " bytes\n"; + Net::SSLeay::ssl_write_all($ssl, \$got) or die "$$: ssl write failed"; + $got = ''; + + Net::SSLeay::free ($ssl); # Tear down connection + Net::SSLeay::CTX_free ($ctx); + + wait; # wait for child to read the stuff + + close WS; + close RS; + print "$$: server done ($?).\n" + . (($? >> 8) ? "ERROR\n" : "OK\n"); + exit; +} + +print "$$: I'm the child.\n"; +sleep 1; # Give server time to get its act together + +$ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); +Net::SSLeay::set_rfd($ssl, fileno(RC)); +Net::SSLeay::set_wfd($ssl, fileno(WC)); +Net::SSLeay::connect($ssl); +die_if_ssl_error("ssl connect"); + +print "$$: Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; +print "$$: server cert: " . Net::SSLeay::dump_peer_certificate($ssl); + +# Exchange data + +$data = 'B' x $how_much; +Net::SSLeay::ssl_write_all($ssl, \$data) or die "$$: ssl write failed"; +$got = Net::SSLeay::ssl_read_all($ssl, $how_much) + or die "$$: ssl read failed"; + +Net::SSLeay::free ($ssl); # Tear down connection +Net::SSLeay::CTX_free ($ctx); +close WC; +close RC; +exit ($data ne $got); + +sub verify { + return 1; + my ($ok, $x509_store_ctx) = @_; + print "$$: **** Verify 2 called ($ok)\n"; + my $x = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx); + if ($x) { + print "$$: Certificate:\n"; + print " Subject Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_subject_name($x)) + . "\n"; + print " Issuer Name: " + . Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_issuer_name($x)) + . "\n"; + } + $callback_called++; + return 1; +} + +__END__ diff --git a/examples/ephemeral.pl b/examples/ephemeral.pl new file mode 100644 index 0000000..88d1b31 --- /dev/null +++ b/examples/ephemeral.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl -w +# ephemeral.pl mikem@open.com.au +# +# Test and demonstrate setting ephemeral RSA key + +use Net::SSLeay qw(die_now); + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +$ctx = Net::SSLeay::CTX_new() + or die_now("Failed to create SSL_CTX $!"); + +$rsa = &Net::SSLeay::RSA_generate_key(512, 0x10001); # 0x10001 = RSA_F4 + +die_now("Failed to set ephemeral RSA key $!") + if (&Net::SSLeay::CTX_set_tmp_rsa($ctx, $rsa) < 0); + +print "OK\n"; +exit; diff --git a/examples/get_authenticated_page.pl b/examples/get_authenticated_page.pl new file mode 100755 index 0000000..24aa024 --- /dev/null +++ b/examples/get_authenticated_page.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +# 8.6.1998, Sampo Kellomaki +# Get a page via HTTP and print some info about it. +# Demonstrates how to generate password header + +use Net::SSLeay qw(get_https make_headers); +use MIME::Base64; + +($user, $pass, $site, $port, $path) = @ARGV; +die "Usage: ./get_authenticated_page.pl user pass www.bacus.com 443 /\n" + unless $path; + +($page, $result, %headers) = + get_https($site, $port, $path, + make_headers('Authorization' => + 'Basic ' . MIME::Base64::encode("$user:$pass")) + ); + +print "Result was `$result'\n"; +foreach $h (sort keys %headers) { + print "Header `$h'\tvalue `$headers{$h}'\n"; +} + +print "=================== Page follows =================\n"; +print $page; + +__END__ diff --git a/examples/get_page.pl b/examples/get_page.pl new file mode 100755 index 0000000..6e36739 --- /dev/null +++ b/examples/get_page.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +# 8.6.1998, Sampo Kellomaki +# Get a page via HTTP and print some info about it. + +use Net::SSLeay; + +($site, $port, $path) = @ARGV; +die "Usage: ./get_page.pl www.cryptsoft.com 443 /\n" unless $path; + +($page, $result, %headers) = &Net::SSLeay::get_https($site, $port, $path); + +print "Result was `$result'\n"; +foreach $h (sort keys %headers) { + print "Header `$h'\tvalue `$headers{$h}'\n"; +} + +print "=================== Page follows =================\n"; +print $page; + +__END__ diff --git a/examples/get_page_cert.pl b/examples/get_page_cert.pl new file mode 100644 index 0000000..9b6aff2 --- /dev/null +++ b/examples/get_page_cert.pl @@ -0,0 +1,33 @@ +#!/usr/bin/perl +# 8.6.1998, Sampo Kellomaki +# 25.3.2002, added certificate display --Sampo +# $Id: get_page_cert.pl,v 1.1 2002/03/25 23:47:15 sampo Exp $ +# Get a page via HTTP and print some info about it. + +use Net::SSLeay; + +($site, $port, $path) = @ARGV; +die "Usage: ./get_page.pl www.cryptsoft.com 443 /\n" unless $path; + +($page, $result, $headers, $server_cert) + = &Net::SSLeay::get_https3($site, $port, $path); + +if (!defined($server_cert) || ($server_cert == 0)) { + print "Subject Name: undefined, Issuer Name: undefined\n"; +} else { + print '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)) + . "\n"; +} + +print "Headers were `$headers'\n"; +print "Result was `$result'\n"; + +print "=================== Page follows =================\n"; +print $page; + +__END__ diff --git a/examples/https-proxy-snif.pl b/examples/https-proxy-snif.pl new file mode 100755 index 0000000..3b9927e --- /dev/null +++ b/examples/https-proxy-snif.pl @@ -0,0 +1,135 @@ +#!/usr/bin/perl +# 5.6.1998, Sampo Kellomaki + +$usage = <foo +

Bar Cool

+HTTP + ; + + &Net::SSLeay::free ($ssl); # Tear down connection + close NS; +} + +__END__ diff --git a/examples/makecert.pl b/examples/makecert.pl new file mode 100755 index 0000000..221f720 --- /dev/null +++ b/examples/makecert.pl @@ -0,0 +1,55 @@ +#!/usr/bin/perl +# 19.6.1998, Sampo Kellomaki +# 31.3.1999, Upgraded to OpenSSL-0.9.2b, --Sampo +# 31.7.1999, Upgraded to OpenSSL-0.9.3a, fixed depending on symlinks +# (thanks to schinder@@pobox_.com) --Sampo +# 7.4.2001, Upgraded to OpenSSL-0.9.6a --Sampo +# 9.11.2001, EGD patch from Mik Firestone --Sampo +# +# Make a self signed cert + +use strict; +use warnings; +use File::Copy; +use File::Spec::Functions qw(catfile); + +my $dir = shift || usage(); +my $exe_path = shift || '/usr/local/ssl/bin/openssl'; +my $egd = defined( $ENV{EGD_POOL} ) ? "-rand $ENV{EGD_POOL}" : ''; + +my $conf = catfile($dir, 'req.conf'); +my $key = catfile($dir, 'key.pem' ); +my $cert = catfile($dir, 'cert.pem'); + +open (REQ, "|$exe_path req -config $conf " + . "-x509 -days 3650 -new -keyout $key $egd >$cert") + or die "cant open req. check your path ($!)"; +print REQ < + +use Socket; +use Net::SSLeay; +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; +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); + +# The network connection is now open, lets fire up SSL + +$ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); +$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); +print "Cipher '" . Net::SSLeay::get_cipher($ssl) . "'\n"; + +# Exchange data + +$res = Net::SSLeay::write($ssl, $msg); # Perl knows how long $msg is +shutdown S, 1; # Half close --> No more output, sends EOF to server +$got = Net::SSLeay::read($ssl); # Perl returns undef on failure +print $got; + +Net::SSLeay::free ($ssl); # Tear down connection +Net::SSLeay::CTX_free ($ctx); +close S; + +__END__ diff --git a/examples/passwd-cb.pl b/examples/passwd-cb.pl new file mode 100644 index 0000000..da1d2bb --- /dev/null +++ b/examples/passwd-cb.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +# passwd-cb.pl +# +# Check using password callbacks to decrypt private keys +# $Id: passwd-cb.pl,v 1.2 2002/06/05 18:25:47 sampo Exp $ + +use Socket; +use Net::SSLeay qw(die_now die_if_ssl_error); +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my ($key_pem, $password) = @ARGV; + +print "Keyfile: `$key_pem', pw: `$password'\n"; +$calls = 0; + +sub callback { + $calls++; + print "Callback `$password'\n"; + return $password; +} + +my $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); +if (1) { +Net::SSLeay::CTX_set_default_passwd_cb($ctx, \&callback); +} +Net::SSLeay::CTX_use_PrivateKey_file($ctx, $key_pem, + &Net::SSLeay::FILETYPE_PEM()) + or print "CTX_use_PrivateKey_file failed\n"; + +print "calls=$calls\n"; + +#EOF diff --git a/examples/req.conf b/examples/req.conf new file mode 100644 index 0000000..0e102c1 --- /dev/null +++ b/examples/req.conf @@ -0,0 +1,42 @@ +# SSLeay config file for generating self signed certificate +# for testing Net::SSLeay.pm (see `make test' alias test.pl) +# +# 8.6.1998, Sampo Kellomaki + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attr +encrypt_rsa_key = no + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_min = 2 +countryName_max = 2 +countryName_default = PT + +stateOrProvinceName = State or Province Name (optional) + +localityName = Locality Name (eg, city) +localityName_default = Lisboa + +organizationName = Organization Name (eg, company) + +organizationalUnitName = Organizational Unit Name (eg, section) + +commonName = Common Name (the name of your machine) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 40 + +# Challenge password is used for delievering the cert (or what)??? + +[ req_attr ] +challengePassword = A challenge password +challengePassword_min = 0 +challengePassword_max = 80 + +#EOF diff --git a/examples/server_key.pem b/examples/server_key.pem new file mode 100644 index 0000000..07c79c8 --- /dev/null +++ b/examples/server_key.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,932256E9ACCDC996 + +wav+t55gSrsCnvgeikRqcQKXuUeXEqEcL6zwNsTMIis6rpGuXkBYH5Ezntm6h/5h +2vZDu2vTOeq7QbNmTbKWbU6Rw0e7hlnWcPFhg3ssLNrh0XW3ynZ56gLCj/TRHj9V +4c7UnozeDTb+XYEAp+1Yj21Bpepectak6j4dZfhhJteEGWMDj9faNTbA08LX87Wn +JiNhlhIWl7ncS/13riwLqsemHcTFlNCaoANaVCUKEGoIFZmz1OoYJvBWLj7HnxDU ++Z/lvf3o1glE1EP3XcCACGhapfZcALlYhz1qGTA6ProZ/sIJGLAYAi8uobJlA1E0 +SwGXNm4rtMocR7utO649/g92SFvGZmG715t2P8jBa4MqgV5H3oIIVJK1YiL6Zmk5 +jZMPmTDctXD61dLnTFXa+m0vLJMZAMD8UkhtbuCMYzTy0dIHBaxTYNxggSbfbbKJ +6QijHZHn+iygyudCxYWXtZQ1uyBFzU4wpEGqugngf3T0W2TWpiM3PQjh+vymxKRZ +UVY5LGejMuz3HpgFcJ+Hs6DCJYAECUWWjSPhTXvTifNIZq5XdaeCveyLkMnCHQ7y +LW64XcZ9jWzI+FOqRmLMYcUoHh8eZyB6X6ITC3wy2g1ovc5KrD+OuC+HOyLvvb+8 +avnSoc1+maBC7su7htE/EPP6X/zvNzLM4Ky4JvmNtFR5+CzD7xnwoS3jY97u6gMz +MHjb7t2pA7rFnVImwivvi/y3sEAL9P5N+mL+q82q9qsmcb58tlkAteUpcrOvlmRk +3kzlM0tz9/Rm4bYttEDBt67Fg4/hZbZ+m+5BMzVWWdtZIdHUIGJjew== +-----END RSA PRIVATE KEY----- diff --git a/examples/ssl-inetd-serv.pl b/examples/ssl-inetd-serv.pl new file mode 100755 index 0000000..7f2a183 --- /dev/null +++ b/examples/ssl-inetd-serv.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl +# ssl-inetd-serv.pl - SSL echo server run from inetd +# +# Copyright (c) 1996,1998 Sampo Kellomaki . All Rights Reserved. +# Date: 27.6.1996, 19.6.1998 +# +# /etc/inetd.conf: +# ssltst stream tcp nowait root /usr/sampo/ssl-inetd-serv.pl ssl-inetd +# +# /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(); + +chdir '/usr/sampo' or die "chdir: $!"; + +$| = 1; # STDOUT Piping hot! + +open LOG, ">>log" or die "Can't open log file $!"; +select LOG; $| = 1; +print "ssl-inetd-serv.pl started\n"; + +print "Creating SSL context...\n"; +$ctx = Net::SSLeay::CTX_new or die_now("CTX_new ($ctx) ($!)"); +print "Setting private key and certificate...\n"; +Net::SSLeay::set_server_cert_and_key($ctx, 'cert.pem', 'key.pem') or die "key"; + +print "Creating SSL connection (context was '$ctx')...\n"; +$ssl = Net::SSLeay::new($ctx) or die_now("new ($ssl) ($!)"); + +print "Setting fds (ctx $ctx, con $ssl)...\n"; +Net::SSLeay::set_rfd($ssl, fileno(STDIN)); +Net::SSLeay::set_wfd($ssl, fileno(STDOUT)); + +print "Entering SSL negotiation phase...\n"; + +Net::SSLeay::accept($ssl); +die_if_ssl_error("accept: $!"); + +print "Cipher '" . Net::SSLeay::get_cipher($ssl) . "'\n"; + +# +# Connected. Exchange some data. +# + +$got = Net::SSLeay::ssl_read_all($ssl) or die "$$: ssl read failed"; +print "Got `$got' (" . length ($got) . " chars)\n"; +$got = uc $got; +Net::SSLeay::ssl_write_all($ssl, $got) or die "$$: ssl write failed"; + +print "Tearing down the connection.\n"; + +Net::SSLeay::free ($ssl); +Net::SSLeay::CTX_free ($ctx); + +close LOG; + +__END__ diff --git a/examples/ssl_diff.pl b/examples/ssl_diff.pl new file mode 100755 index 0000000..e9fd1cf --- /dev/null +++ b/examples/ssl_diff.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +# 18.6.1998, Sampo Kellomaki +# Tool used to sync SSLeay.xs with ssl.h. Prints what .h has that .xs doesn't. +# Usage: examples/ssl_diff.pl *pat* SSLeay.xs /usr/local/ssl/include/ssl.h +# E.g: examples/ssl_diff.pl SSL_CTX_ SSLeay.xs /usr/local/ssl/include/ssl.h + +($pat, $xs, $h) = @ARGV; + +open XS, $xs or die "Cant open .xs `$xs' ($!)\n"; +foreach $_ () { + next unless ($name) = /^($pat.*?)\(/o; + $xs{$name} = 1; +} +close XS; + +open H, $h or die "Cant open .h `$h' ($!)\n"; +foreach $_ () { + next unless ($name) = /($pat.*?)\(/o; + print "$name\n" unless $xs{$name}; +} +close H; + +__END__ diff --git a/examples/sslcat.pl b/examples/sslcat.pl new file mode 100755 index 0000000..9254f90 --- /dev/null +++ b/examples/sslcat.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl +# sslcat.pl - Send a message and receive a reply from SSL server. +# +# Copyright (c) 1996-2001 Sampo Kellomaki , All Rights Reserved. +# $Id: sslcat.pl,v 1.3 2003/08/17 07:07:28 sampo Exp $ +# Date: 7.6.1996 + +$host = 'localhost' unless $host = shift; +$port = 443 unless $port = shift; +$msg = "get \n\r\n" unless $msg = shift; + +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; +print "$host $port $msg\n"; +use Net::SSLeay qw(sslcat); +print sslcat($host, $port, $msg); + +__END__ diff --git a/examples/sslecho.pl b/examples/sslecho.pl new file mode 100755 index 0000000..e4f1c0e --- /dev/null +++ b/examples/sslecho.pl @@ -0,0 +1,100 @@ +#!/usr/bin/perl -w +# sslecho.pl - Echo server using SSL +# +# Copyright (c) 1996,1998 Sampo Kellomaki , All Rights Reserved. +# Date: 27.6.1996, 8.6.1998 +# 7.12.2001, added more support for client side certificate testing --Sampo +# $Id: sslecho.pl,v 1.2 2001/12/08 17:43:14 sampo Exp $ +# +# Usage: ./sslecho.pl *port* *cert.pem* *key.pem* +# +# This server always binds to localhost as this is all that is needed +# for tests. + +die "Usage: ./sslecho.pl *port* *cert.pem* *key.pem*\n" unless $#ARGV == 2; +($port, $cert_pem, $key_pem) = @ARGV; +$our_ip = "\x7F\0\0\x01"; + +$trace = 2; +use Socket; +use Net::SSLeay qw(sslcat die_now die_if_ssl_error); +$Net::SSLeay::trace = 3; # Super verbose debugging + +# +# Create the socket and open a connection +# + +$our_serv_params = pack ('S n a4 x8', &AF_INET, $port, $our_ip); +socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!"; +bind (S, $our_serv_params) or die "bind: $! (port=$port)"; +listen (S, 5) or die "listen: $!"; + +# +# Prepare SSLeay +# + +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +Net::SSLeay::randomize(); + +print "sslecho: Creating SSL context...\n" if $trace>1; +$ctx = Net::SSLeay::CTX_new () or die_now("CTX_new ($ctx): $!\n"); +print "sslecho: Setting cert and RSA key...\n" if $trace>1; +Net::SSLeay::CTX_set_cipher_list($ctx,'ALL'); +Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem) or die "key"; + +while (1) { + + print "sslecho $$: Accepting connections...\n" if $trace>1; + ($addr = accept (NS, S)) or die "accept: $!"; + $old_out = select (NS); $| = 1; select ($old_out); # Piping hot! + + if ($trace) { + ($af,$client_port,$client_ip) = unpack('S n a4 x8',$addr); + @inetaddr = unpack('C4',$client_ip); + print "$af connection from " . join ('.', @inetaddr) + . ":$client_port\n" if $trace;; + } + + # + # Do SSL negotiation stuff + # + + print "sslecho: Creating SSL session (cxt=`$ctx')...\n" if $trace>1; + $ssl = Net::SSLeay::new($ctx) or die_now("ssl new ($ssl): $!"); + + print "sslecho: Setting fd (ctx $ctx, con $ssl)...\n" if $trace>1; + Net::SSLeay::set_fd($ssl, fileno(NS)); + + print "sslecho: Entering SSL negotiation phase...\n" if $trace>1; + + Net::SSLeay::accept($ssl); + die_if_ssl_error("ssl_echo: ssl accept: ($!)"); + + print "sslecho: Cipher `" . Net::SSLeay::get_cipher($ssl) + . "'\n" if $trace; + + # + # Connected. Exchange some data. + # + + $got = Net::SSLeay::ssl_read_all($ssl) or die "$$: ssl read failed"; + print "sslecho $$: got " . length($got) . " bytes\n" if $trace==2; + print "sslecho: Got `$got' (" . length ($got) . " chars)\n" if $trace>2; + $got = uc $got; + if ($got eq 'CLIENT-CERT-TEST') { + $got .= Net::SSLeay::dump_peer_certificate($ssl) . "END CERT\n"; + } + Net::SSLeay::ssl_write_all($ssl, $got) or die "$$: ssl write failed"; + $got = ''; # in case it was huge + + print "sslecho: Tearing down the connection.\n\n" if $trace>1; + + Net::SSLeay::free ($ssl); + close NS; +} +Net::SSLeay::CTX_free ($ctx); +close S; + +__END__ diff --git a/examples/stdio_bulk.pl b/examples/stdio_bulk.pl new file mode 100755 index 0000000..ff0dbf7 --- /dev/null +++ b/examples/stdio_bulk.pl @@ -0,0 +1,82 @@ +#!/usr/bin/perl +# stdio_bulk.pl - 8.6.1998, Sampo Kellomaki +# Send tons of stuff over SSL connected by STDIO pipe. +# This also demonstrates how you can communicate via arbitrary stream, not +# just a TCP one. +# $Id: stdio_bulk.pl,v 1.3 2003/06/13 21:14:41 sampo Exp $ + +use Socket; +use Net::SSLeay qw(die_now die_if_ssl_error); +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +#$Net::SSLeay::trace = 2; + +($cert_pem, $key_pem, $how_much) = @ARGV; # Read command line + +$ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); +Net::SSLeay::set_server_cert_and_key($ctx, $cert_pem, $key_pem) or die "key"; + +pipe RS, WC or die "pipe 1 ($!)"; +pipe RC, WS or die "pipe 2 ($!)"; +select WC; $| = 1; +select WS; $| = 1; +select STDOUT; +$| = 1; + +if ($child_pid = fork) { + print "$$: I'm the server for child $child_pid\n"; + $ssl = Net::SSLeay::new($ctx) or die_now "$$: new ($ssl) ($!)"; + + Net::SSLeay::set_rfd($ssl, fileno(RS)); + Net::SSLeay::set_wfd($ssl, fileno(WS)); + + Net::SSLeay::accept($ssl) and die_if_ssl_error("$$: ssl accept: $!"); + print "$$: Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; + #print "$$: " . Net::SSLeay::dump_peer_certificate($ssl); + + $got = Net::SSLeay::ssl_read_all($ssl,$how_much) + or die "$$: ssl read failed"; + print "$$: got " . length($got) . " bytes\n"; + Net::SSLeay::ssl_write_all($ssl, \$got) or die "$$: ssl write failed"; + $got = ''; + + Net::SSLeay::free ($ssl); # Tear down connection + Net::SSLeay::CTX_free ($ctx); + + wait; # wait for child to read the stuff + + close WS; + close RS; + print "$$: server done ($?).\n" + . (($? >> 8) ? "ERROR\n" : "OK\n"); + exit; +} + +print "$$: I'm the child.\n"; +sleep 1; # Give server time to get its act together + +$ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); +Net::SSLeay::set_rfd($ssl, fileno(RC)); +Net::SSLeay::set_wfd($ssl, fileno(WC)); +Net::SSLeay::connect($ssl); +die_if_ssl_error("ssl connect"); + +print "$$: Cipher `" . Net::SSLeay::get_cipher($ssl) . "'\n"; +print "$$: " . Net::SSLeay::dump_peer_certificate($ssl); + +# Exchange data + +$data = 'B' x $how_much; +Net::SSLeay::ssl_write_all($ssl, \$data) or die "$$: ssl write failed"; +$got = Net::SSLeay::ssl_read_all($ssl, $how_much) + or die "$$: ssl read failed"; + +Net::SSLeay::free ($ssl); # Tear down connection +Net::SSLeay::CTX_free ($ctx); +close WC; +close RC; +exit ($data ne $got); + +__END__ diff --git a/examples/tcpcat.pl b/examples/tcpcat.pl new file mode 100755 index 0000000..d505d9e --- /dev/null +++ b/examples/tcpcat.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl +# tcpcat.pl - Send a message and receive a reply from TCP server. +# +# Copyright (c) 2003 Sampo Kellomaki , All Rights Reserved. +# $Id$ +# 17.8.2003, created --Sampo + +$host = 'localhost' unless $host = shift; +$port = 443 unless $port = shift; +$msg = "get \n\r\n" unless $msg = shift; + +print "$host $port $msg\n"; +use Net::SSLeay qw(tcpcat); +print tcpcat($host, $port, $msg); + +__END__ diff --git a/examples/tcpecho.pl b/examples/tcpecho.pl new file mode 100755 index 0000000..cac04fb --- /dev/null +++ b/examples/tcpecho.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl -w +# tcpecho.pl - Echo server using TCP +# +# Copyright (c) 2003 Sampo Kellomaki , All Rights Reserved. +# $Id: tcpecho.pl,v 1.2 2003/08/17 07:44:47 sampo Exp $ +# 17.8.2003, created --Sampo +# +# Usage: ./tcpecho.pl *port* +# +# This server always binds to localhost as this is all that is needed +# for tests. + +die "Usage: ./tcpecho.pl *port*\n" unless $#ARGV == 0; +($port) = @ARGV; +$our_ip = "\x7F\0\0\x01"; + +$trace = 2; +use Socket; +use Net::SSLeay; + +# +# Create the socket and open a connection +# + +$our_serv_params = pack ('S n a4 x8', &AF_INET, $port, $our_ip); +socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!"; +bind (S, $our_serv_params) or die "bind: $! (port=$port)"; +listen (S, 5) or die "listen: $!"; + +#while (1) { # uncomment to turn off "one shot" behaviour + print "tcpecho $$: Accepting connections on port $port...\n" if $trace>1; + ($addr = accept(Net::SSLeay::SSLCAT_S, S)) or die "accept: $!"; + $old_out = select(Net::SSLeay::SSLCAT_S); $| = 1; select ($old_out); # Piping hot! + + if ($trace) { + ($af,$client_port,$client_ip) = unpack('S n a4 x8',$addr); + @inetaddr = unpack('C4',$client_ip); + print "$af connection from " . join ('.', @inetaddr) + . ":$client_port\n" if $trace;; + } + + # + # Connected. Exchange some data. + # + + $got = Net::SSLeay::tcp_read_all() or die "$$: read failed"; + print "tcpecho $$: got " . length($got) . " bytes\n" if $trace==2; + print "tcpecho: Got `$got' (" . length ($got) . " chars)\n" if $trace>2; + $got = uc $got; + Net::SSLeay::tcp_write_all($got) or die "$$: write failed"; + $got = ''; # in case it was huge + + print "tcpecho: Tearing down the connection.\n\n" if $trace>1; + close Net::SSLeay::SSLCAT_S; +#} +close S; + +__END__ diff --git a/examples/x509_cert_details.pl b/examples/x509_cert_details.pl new file mode 100755 index 0000000..94a387a --- /dev/null +++ b/examples/x509_cert_details.pl @@ -0,0 +1,250 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Getopt::Long; +use Data::Dumper; +use IO::Socket::INET; +use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +# --- commandline options and global variables + +my ($g_host, $g_pem, $g_dump, $g_showusage); + +GetOptions( + 'help|?' => \$g_showusage, + 'dump' => \$g_dump, + 'host=s@' => \$g_host, + 'pem=s@' => \$g_pem, +) or $g_showusage = 1; + +# --- subroutines + +sub show_usage { + die < + -help -? show this help + -pem process X509 certificate from file (PEM format) + -host : process X509 certificate presented by SSL server + -dump full dump of X509 certificate info + +Example: + $0 -pem file1.pem + $0 -pem file1.pem -pem file2.pem + $0 -host twitter.com:443 -dump + +EOL +} + +sub get_cert_details { + my $x509 = shift; + my $rv = {}; + my $flag_rfc22536_utf8 = (XN_FLAG_RFC2253) & (~ ASN1_STRFLGS_ESC_MSB); + + die 'ERROR: $x509 is NULL, gonna quit' unless $x509; + + warn "Info: dumping subject\n"; + my $subj_name = Net::SSLeay::X509_get_subject_name($x509); + my $subj_count = Net::SSLeay::X509_NAME_entry_count($subj_name); + $rv->{subject}->{count} = $subj_count; + $rv->{subject}->{oneline} = Net::SSLeay::X509_NAME_oneline($subj_name); + $rv->{subject}->{print_rfc2253} = Net::SSLeay::X509_NAME_print_ex($subj_name); + $rv->{subject}->{print_rfc2253_utf8} = Net::SSLeay::X509_NAME_print_ex($subj_name, $flag_rfc22536_utf8); + $rv->{subject}->{print_rfc2253_utf8_decoded} = Net::SSLeay::X509_NAME_print_ex($subj_name, $flag_rfc22536_utf8, 1); + for my $i (0..$subj_count-1) { + my $entry = Net::SSLeay::X509_NAME_get_entry($subj_name, $i); + my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry); + my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry); + my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object); + $rv->{subject}->{entries}->[$i] = { + oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1), + data => Net::SSLeay::P_ASN1_STRING_get($asn1_string), + data_utf8_decoded => Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1), + nid => ($nid>0) ? $nid : undef, + ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef, + sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef, + }; + } + + warn "Info: dumping issuer\n"; + my $issuer_name = Net::SSLeay::X509_get_issuer_name($x509); + my $issuer_count = Net::SSLeay::X509_NAME_entry_count($issuer_name); + $rv->{issuer}->{count} = $issuer_count; + $rv->{issuer}->{oneline} = Net::SSLeay::X509_NAME_oneline($issuer_name); + $rv->{issuer}->{print_rfc2253} = Net::SSLeay::X509_NAME_print_ex($issuer_name); + $rv->{issuer}->{print_rfc2253_utf8} = Net::SSLeay::X509_NAME_print_ex($issuer_name, $flag_rfc22536_utf8); + $rv->{issuer}->{print_rfc2253_utf8_decoded} = Net::SSLeay::X509_NAME_print_ex($issuer_name, $flag_rfc22536_utf8, 1); + for my $i (0..$issuer_count-1) { + my $entry = Net::SSLeay::X509_NAME_get_entry($issuer_name, $i); + my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry); + my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry); + my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object); + $rv->{issuer}->{entries}->[$i] = { + oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1), + data => Net::SSLeay::P_ASN1_STRING_get($asn1_string), + data_utf8_decoded => Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1), + nid => ($nid>0) ? $nid : undef, + ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef, + sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef, + }; + } + + warn "Info: dumping alternative names\n"; + $rv->{subject}->{altnames} = [ Net::SSLeay::X509_get_subjectAltNames($x509) ]; + #XXX-TODO maybe add a function for dumping issuerAltNames + #$rv->{issuer}->{altnames} = [ Net::SSLeay::X509_get_issuerAltNames($x509) ]; + + warn "Info: dumping hashes/fingerprints\n"; + $rv->{hash}->{subject} = { dec=>Net::SSLeay::X509_subject_name_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_subject_name_hash($x509)) }; + $rv->{hash}->{issuer} = { dec=>Net::SSLeay::X509_issuer_name_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_issuer_name_hash($x509)) }; + $rv->{hash}->{issuer_and_serial} = { dec=>Net::SSLeay::X509_issuer_and_serial_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_issuer_and_serial_hash($x509)) }; + $rv->{fingerprint}->{md5} = Net::SSLeay::X509_get_fingerprint($x509, "md5"); + $rv->{fingerprint}->{sha1} = Net::SSLeay::X509_get_fingerprint($x509, "sha1"); + my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"); + $rv->{digest_sha1}->{pubkey} = Net::SSLeay::X509_pubkey_digest($x509, $sha1_digest); + $rv->{digest_sha1}->{x509} = Net::SSLeay::X509_digest($x509, $sha1_digest); + + warn "Info: dumping expiration\n"; + $rv->{not_before} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($x509)); + $rv->{not_after} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509)); + + warn "Info: dumping serial number\n"; + my $ai = Net::SSLeay::X509_get_serialNumber($x509); + $rv->{serial} = { + hex => Net::SSLeay::P_ASN1_INTEGER_get_hex($ai), + dec => Net::SSLeay::P_ASN1_INTEGER_get_dec($ai), + long => Net::SSLeay::ASN1_INTEGER_get($ai), + }; + $rv->{version} = Net::SSLeay::X509_get_version($x509); + + warn "Info: dumping extensions\n"; + my $ext_count = Net::SSLeay::X509_get_ext_count($x509); + $rv->{extensions}->{count} = $ext_count; + for my $i (0..$ext_count-1) { + my $ext = Net::SSLeay::X509_get_ext($x509,$i); + my $asn1_string = Net::SSLeay::X509_EXTENSION_get_data($ext); + my $asn1_object = Net::SSLeay::X509_EXTENSION_get_object($ext); + my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object); + $rv->{extensions}->{entries}->[$i] = { + critical => Net::SSLeay::X509_EXTENSION_get_critical($ext), + oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1), + nid => ($nid>0) ? $nid : undef, + ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef, + sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef, + data => Net::SSLeay::X509V3_EXT_print($ext), + }; + } + + warn "Info: dumping CDP\n"; + $rv->{cdp} = [ Net::SSLeay::P_X509_get_crl_distribution_points($x509) ]; + warn "Info: dumping extended key usage\n"; + $rv->{extkeyusage} = { + oid => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,0) ], + nid => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,1) ], + sn => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,2) ], + ln => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,3) ], + }; + warn "Info: dumping key usage\n"; + $rv->{keyusage} = [ Net::SSLeay::P_X509_get_key_usage($x509) ]; + warn "Info: dumping netscape cert type\n"; + $rv->{ns_cert_type} = [ Net::SSLeay::P_X509_get_netscape_cert_type($x509) ]; + + warn "Info: dumping other info\n"; + $rv->{certificate_type} = Net::SSLeay::X509_certificate_type($x509); + $rv->{signature_alg} = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_signature_alg($x509)); + $rv->{pubkey_alg} = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_pubkey_alg($x509)); + $rv->{pubkey_size} = Net::SSLeay::EVP_PKEY_size(Net::SSLeay::X509_get_pubkey($x509)); + $rv->{pubkey_bits} = Net::SSLeay::EVP_PKEY_bits(Net::SSLeay::X509_get_pubkey($x509)); + $rv->{pubkey_id} = Net::SSLeay::EVP_PKEY_id(Net::SSLeay::X509_get_pubkey($x509)); + + return $rv; +} + +sub dump_details { + my ($data, $comment) = @_; + print "\n"; + eval { require Data::Dump }; + if (!$@) { + # Data::Dump creates nicer output + print "# $comment\n"; + print "# hashref dumped via Data::Dump\n"; + $Data::Dump::TRY_BASE64 = 0 if $Data::Dump::TRY_BASE64; + print Data::Dump::pp($data); + } + else { + print "# $comment\n"; + print "# hashref dumped via Data::Dumper\n"; + print Dumper($data); + } + print "\n"; +} + +sub print_basic_info { + my ($data) = @_; + print "\n"; + print "Subject: ", $data->{subject}->{print_rfc2253}, "\n"; + print "Issuer: ", $data->{issuer}->{print_rfc2253}, "\n"; + print "NotBefore: ", $data->{not_before}, "\n"; + print "NotAfter: ", $data->{not_after}, "\n"; + print "SHA1: ", $data->{fingerprint}->{sha1}, "\n"; + print "MD5: ", $data->{fingerprint}->{md5}, "\n"; + print "\n"; +} + +# --- main +show_usage() if $g_showusage || (!$g_host && !$g_pem); + +if ($g_pem) { + for my $f(@$g_pem) { + die "ERROR: non existing file '$f'" unless -f $f; + + warn "#### Going to load PEM file '$f'\n"; + my $bio = Net::SSLeay::BIO_new_file($f, 'rb') or die "ERROR: BIO_new_file failed"; + my $x509 = Net::SSLeay::PEM_read_bio_X509($bio) or die "ERROR: PEM_read_bio_X509 failed"; + + my $cert_details = get_cert_details($x509); + + warn "#### Certificate info\n"; + if ($g_dump) { + dump_details($cert_details, "exported via command: perl examples/x509_cert_details.pl -dump -pem $f > $f\_dump"); + } + else { + print_basic_info($cert_details); + } + warn "#### DONE\n"; + } +} + +if ($g_host) { + for my $h (@$g_host) { + my ($host, $port) = split /:/, $h; + die "ERROR: invalid host '$h'" unless $host && $port =~ /\d+/; + + warn "#### Going to connect to host=$host, port=$port\n"; + my $sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port, Proto => 'tcp') or die "ERROR: cannot create socket"; + my $ctx = Net::SSLeay::CTX_new() or die "ERROR: CTX_new failed"; + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + my $ssl = Net::SSLeay::new($ctx) or die "ERROR: new failed"; + Net::SSLeay::set_fd($ssl, fileno($sock)) or die "ERROR: set_fd failed"; + Net::SSLeay::connect($ssl) or die "ERROR: connect failed"; + my $x509 = Net::SSLeay::get_peer_certificate($ssl); + + my $cert_details = get_cert_details($x509); + + warn "#### Certificate info\n"; + if ($g_dump) { + dump_details($cert_details, "host: $h\n"); + } + else { + print_basic_info($cert_details); + } + warn "#### DONE\n"; + } +} diff --git a/helper_script/regen_openssl_constants.pl b/helper_script/regen_openssl_constants.pl new file mode 100644 index 0000000..3789eab --- /dev/null +++ b/helper_script/regen_openssl_constants.pl @@ -0,0 +1,721 @@ +use strict; +use warnings; + +####### HOWTO ADD A NEW CONSTANT: +# +# 1/ add new constant name (incl. SSL_ prefix) in __DATA__ part +# of this file (helper_script/regen_openssl_constants.pl) +# +# 3/ take the output of the following command: +# perl helper_script/regen_openssl_constants.pl -gen-pod +# and paste it manually into: +# a/ SSLeay.pm (@EXPORT_OK - the first 3-columns part) +# b/ SSLeay.pod (constants section) +# +# 3/ run: perl Makefile.PL && make && make test + +# some hints if you want to play more with this script: +# +# you can run this script manually from the Net::SSLeay dist dir like this: +# perl helper_script/regen_openssl_constants.pl -gen-c > constants.c +# +# or you can generate test file like this: +# perl helper_script/regen_openssl_constants.pl -gen-t > t/local/20_autoload.t +# +# or you can generate pod doc section with all available constants: +# perl helper_script/regen_openssl_constants.pl -gen-pod > 3columns-const-list.txt + +package MySubClass; +use base 'ExtUtils::Constant::Base'; + +sub assignment_clause_for_type { + my ($self, $args, $value) = @_; + my ($name, $valuex) = @{$args}{qw(name value)}; + return "goto not_there;" if $value && $value eq '_TEST_INVALID_CONSTANT'; + return <<"MARKER" + +#ifdef $value + return $value; +#else + goto not_there; +#endif +MARKER +} + +sub C_constant_return_type { "static double" } + +sub return_statement_for_notfound { + return <<"MARKER" + + errno = EINVAL; + return 0; + +not_there: + errno = ENOENT; + return 0; +MARKER +} + +package main; + +sub const_list_3columns { + my ($list, $include_test_constant) = @_; + my @c = sort map { $_->{name} } @$list; + @c = grep { $_ !~ /^_TEST_INVALID_CONSTANT$/ } @c unless $include_test_constant; + my $rows = int((scalar(@c)+2)/3); #3 columns + my $max_width_left = 0; + for my $i (0..$rows-1) { + my $l = length($c[$i]); + $max_width_left = $l if $max_width_left < $l; + } + my $max_width_middle = 0; + for my $i ($rows..2*$rows-1) { + my $l = length($c[$i]); + $max_width_middle = $l if $max_width_middle < $l; + } + my $rv = ''; + for my $i (0..$rows-1) { + my $left = $c[$i]; + my $middle = $c[$rows + $i] || ''; + my $right = $c[2*$rows + $i] || ''; + $rv .= " $left" . " " x ($max_width_left-length($left)); + $rv .= " $middle" . " " x ($max_width_middle-length($middle)); + $rv .= " $right\n"; + } + return $rv; +} + +sub t_file { + my ($count, $list) = @_; + return < 'Some tests need Test::Exception';"; +} +else +{ + eval 'use Test::More tests => $count;'; +} + +my \@c = (qw/ +$list +/); + +my \@missing; +my \%h = map { \$_=>1 } \@Net::SSLeay::EXPORT_OK; + +for (\@c) { + like(eval("&Net::SSLeay::\$_; 'ok'") || \$\@, qr/^(ok|Your vendor has not defined SSLeay macro.*)\$/, "\$_"); + push(\@missing, \$_) unless \$h{\$_}; +} + +is(join(",", sort \@missing), '', 'constants missing in \@EXPORT_OK count='.scalar(\@missing)); + +MARKER +} + +sub print_output { + my ($src, $filename) = @_; + if ($filename) { + open F, ">", $filename or die "cannot open $ARGV[1] for writting"; + binmode F; #to make sure that also on MS Windows we will have UNIX line ending + print F $src; + close F; + } + else { + print STDOUT $src; + } +} + +my @constants; + +while () { + s/^\s+|\s+$//g; # skip leading+trailing spaces + s/#.*$//; # skip comments + next if /^\s*$/; # skip empty lines + my $v = $_; + (my $n = $v) =~ s/^SSL_//; + push @constants, { name=>$n, value=>$v }; +} + +if ($ARGV[0] && $ARGV[0] eq '-gen-c') { + my $src = "/* DO NOT EDIT THIS FILE - update __DATA__ section of helper_script/regen_openssl_constants.pl */\n\n"; + $src .= MySubClass->C_constant({breakout=>~0,indent=>20}, @constants); + print_output($src, $ARGV[1]); + warn "\n### do not forget to update (manually) SSLeay.pod(constants list) + SSLeay.pm(\@EXPORT_OK)\n\n"; +} +elsif ($ARGV[0] && $ARGV[0] eq '-gen-t') { + my $src = t_file(scalar(@constants), const_list_3columns(\@constants)); + print_output($src, $ARGV[1]); +} +elsif ($ARGV[0] && $ARGV[0] eq '-gen-pod') { + my $src = const_list_3columns(\@constants); + print_output($src, $ARGV[1]); +} +else { + die "invalid param - usage:\n $0 -gen-c\n $0 -gen-pod\n $0 -gen-t\n"; +} + +__DATA__ +_TEST_INVALID_CONSTANT +ASN1_STRFLGS_ESC_CTRL +ASN1_STRFLGS_ESC_MSB +ASN1_STRFLGS_ESC_QUOTE +ASN1_STRFLGS_RFC2253 +EVP_PKS_DSA +EVP_PKS_EC +EVP_PKS_RSA +EVP_PKT_ENC +EVP_PKT_EXCH +EVP_PKT_EXP +EVP_PKT_SIGN +EVP_PK_DH +EVP_PK_DSA +EVP_PK_EC +EVP_PK_RSA +GEN_DIRNAME +GEN_DNS +GEN_EDIPARTY +GEN_EMAIL +GEN_IPADD +GEN_OTHERNAME +GEN_RID +GEN_URI +GEN_X400 +LIBRESSL_VERSION_NUMBER +MBSTRING_ASC +MBSTRING_BMP +MBSTRING_FLAG +MBSTRING_UNIV +MBSTRING_UTF8 +NID_OCSP_sign +NID_SMIMECapabilities +NID_X500 +NID_X509 +NID_ad_OCSP +NID_ad_ca_issuers +NID_algorithm +NID_authority_key_identifier +NID_basic_constraints +NID_bf_cbc +NID_bf_cfb64 +NID_bf_ecb +NID_bf_ofb64 +NID_cast5_cbc +NID_cast5_cfb64 +NID_cast5_ecb +NID_cast5_ofb64 +NID_certBag +NID_certificate_policies +NID_client_auth +NID_code_sign +NID_commonName +NID_countryName +NID_crlBag +NID_crl_distribution_points +NID_crl_number +NID_crl_reason +NID_delta_crl +NID_des_cbc +NID_des_cfb64 +NID_des_ecb +NID_des_ede +NID_des_ede3 +NID_des_ede3_cbc +NID_des_ede3_cfb64 +NID_des_ede3_ofb64 +NID_des_ede_cbc +NID_des_ede_cfb64 +NID_des_ede_ofb64 +NID_des_ofb64 +NID_description +NID_desx_cbc +NID_dhKeyAgreement +NID_dnQualifier +NID_dsa +NID_dsaWithSHA +NID_dsaWithSHA1 +NID_dsaWithSHA1_2 +NID_dsa_2 +NID_email_protect +NID_ext_key_usage +NID_ext_req +NID_friendlyName +NID_givenName +NID_hmacWithSHA1 +NID_id_ad +NID_id_ce +NID_id_kp +NID_id_pbkdf2 +NID_id_pe +NID_id_pkix +NID_id_qt_cps +NID_id_qt_unotice +NID_idea_cbc +NID_idea_cfb64 +NID_idea_ecb +NID_idea_ofb64 +NID_info_access +NID_initials +NID_invalidity_date +NID_issuer_alt_name +NID_keyBag +NID_key_usage +NID_localKeyID +NID_localityName +NID_md2 +NID_md2WithRSAEncryption +NID_md5 +NID_md5WithRSA +NID_md5WithRSAEncryption +NID_md5_sha1 +NID_mdc2 +NID_mdc2WithRSA +NID_ms_code_com +NID_ms_code_ind +NID_ms_ctl_sign +NID_ms_efs +NID_ms_ext_req +NID_ms_sgc +NID_name +NID_netscape +NID_netscape_base_url +NID_netscape_ca_policy_url +NID_netscape_ca_revocation_url +NID_netscape_cert_extension +NID_netscape_cert_sequence +NID_netscape_cert_type +NID_netscape_comment +NID_netscape_data_type +NID_netscape_renewal_url +NID_netscape_revocation_url +NID_netscape_ssl_server_name +NID_ns_sgc +NID_organizationName +NID_organizationalUnitName +NID_pbeWithMD2AndDES_CBC +NID_pbeWithMD2AndRC2_CBC +NID_pbeWithMD5AndCast5_CBC +NID_pbeWithMD5AndDES_CBC +NID_pbeWithMD5AndRC2_CBC +NID_pbeWithSHA1AndDES_CBC +NID_pbeWithSHA1AndRC2_CBC +NID_pbe_WithSHA1And128BitRC2_CBC +NID_pbe_WithSHA1And128BitRC4 +NID_pbe_WithSHA1And2_Key_TripleDES_CBC +NID_pbe_WithSHA1And3_Key_TripleDES_CBC +NID_pbe_WithSHA1And40BitRC2_CBC +NID_pbe_WithSHA1And40BitRC4 +NID_pbes2 +NID_pbmac1 +NID_pkcs +NID_pkcs3 +NID_pkcs7 +NID_pkcs7_data +NID_pkcs7_digest +NID_pkcs7_encrypted +NID_pkcs7_enveloped +NID_pkcs7_signed +NID_pkcs7_signedAndEnveloped +NID_pkcs8ShroudedKeyBag +NID_pkcs9 +NID_pkcs9_challengePassword +NID_pkcs9_contentType +NID_pkcs9_countersignature +NID_pkcs9_emailAddress +NID_pkcs9_extCertAttributes +NID_pkcs9_messageDigest +NID_pkcs9_signingTime +NID_pkcs9_unstructuredAddress +NID_pkcs9_unstructuredName +NID_private_key_usage_period +NID_rc2_40_cbc +NID_rc2_64_cbc +NID_rc2_cbc +NID_rc2_cfb64 +NID_rc2_ecb +NID_rc2_ofb64 +NID_rc4 +NID_rc4_40 +NID_rc5_cbc +NID_rc5_cfb64 +NID_rc5_ecb +NID_rc5_ofb64 +NID_ripemd160 +NID_ripemd160WithRSA +NID_rle_compression +NID_rsa +NID_rsaEncryption +NID_rsadsi +NID_safeContentsBag +NID_sdsiCertificate +NID_secretBag +NID_serialNumber +NID_server_auth +NID_sha +NID_sha1 +NID_sha1WithRSA +NID_sha1WithRSAEncryption +NID_shaWithRSAEncryption +NID_stateOrProvinceName +NID_subject_alt_name +NID_subject_key_identifier +NID_surname +NID_sxnet +NID_time_stamp +NID_title +NID_undef +NID_uniqueIdentifier +NID_x509Certificate +NID_x509Crl +NID_zlib_compression +OPENSSL_VERSION_NUMBER +OPENSSL_VERSION +OPENSSL_CFLAGS +OPENSSL_BUILT_ON +OPENSSL_PLATFORM +OPENSSL_DIR +OPENSSL_ENGINES_DIR +RSA_3 +RSA_F4 +SSL_CB_ACCEPT_EXIT +SSL_CB_ACCEPT_LOOP +SSL_CB_ALERT +SSL_CB_CONNECT_EXIT +SSL_CB_CONNECT_LOOP +SSL_CB_EXIT +SSL_CB_HANDSHAKE_DONE +SSL_CB_HANDSHAKE_START +SSL_CB_LOOP +SSL_CB_READ +SSL_CB_READ_ALERT +SSL_CB_WRITE +SSL_CB_WRITE_ALERT +SSL_ERROR_NONE +SSL_ERROR_SSL +SSL_ERROR_SYSCALL +SSL_ERROR_WANT_ACCEPT +SSL_ERROR_WANT_CONNECT +SSL_ERROR_WANT_READ +SSL_ERROR_WANT_WRITE +SSL_ERROR_WANT_X509_LOOKUP +SSL_ERROR_ZERO_RETURN +SSL_FILETYPE_ASN1 +SSL_FILETYPE_PEM +SSL_F_CLIENT_CERTIFICATE +SSL_F_CLIENT_HELLO +SSL_F_CLIENT_MASTER_KEY +SSL_F_D2I_SSL_SESSION +SSL_F_GET_CLIENT_FINISHED +SSL_F_GET_CLIENT_HELLO +SSL_F_GET_CLIENT_MASTER_KEY +SSL_F_GET_SERVER_FINISHED +SSL_F_GET_SERVER_HELLO +SSL_F_GET_SERVER_VERIFY +SSL_F_I2D_SSL_SESSION +SSL_F_READ_N +SSL_F_REQUEST_CERTIFICATE +SSL_F_SERVER_HELLO +SSL_F_SSL_CERT_NEW +SSL_F_SSL_GET_NEW_SESSION +SSL_F_SSL_NEW +SSL_F_SSL_READ +SSL_F_SSL_RSA_PRIVATE_DECRYPT +SSL_F_SSL_RSA_PUBLIC_ENCRYPT +SSL_F_SSL_SESSION_NEW +SSL_F_SSL_SESSION_PRINT_FP +SSL_F_SSL_SET_FD +SSL_F_SSL_SET_RFD +SSL_F_SSL_SET_WFD +SSL_F_SSL_USE_CERTIFICATE +SSL_F_SSL_USE_CERTIFICATE_ASN1 +SSL_F_SSL_USE_CERTIFICATE_FILE +SSL_F_SSL_USE_PRIVATEKEY +SSL_F_SSL_USE_PRIVATEKEY_ASN1 +SSL_F_SSL_USE_PRIVATEKEY_FILE +SSL_F_SSL_USE_RSAPRIVATEKEY +SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 +SSL_F_SSL_USE_RSAPRIVATEKEY_FILE +SSL_F_WRITE_PENDING +SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES +SSL_MODE_ENABLE_PARTIAL_WRITE +SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER +SSL_MODE_AUTO_RETRY +SSL_MODE_RELEASE_BUFFERS +SSL_NOTHING +SSL_OP_ALL +SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION +SSL_OP_ALLOW_NO_DHE_KEX +SSL_OP_CIPHER_SERVER_PREFERENCE +SSL_OP_CISCO_ANYCONNECT +SSL_OP_COOKIE_EXCHANGE +SSL_OP_CRYPTOPRO_TLSEXT_BUG +SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS +SSL_OP_ENABLE_MIDDLEBOX_COMPAT +SSL_OP_EPHEMERAL_RSA +SSL_OP_LEGACY_SERVER_CONNECT +SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER +SSL_OP_MICROSOFT_SESS_ID_BUG +SSL_OP_MSIE_SSLV2_RSA_PADDING +SSL_OP_NETSCAPE_CA_DN_BUG +SSL_OP_NETSCAPE_CHALLENGE_BUG +SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG +SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG +SSL_OP_NON_EXPORT_FIRST +SSL_OP_NO_ANTI_REPLAY +SSL_OP_NO_COMPRESSION +SSL_OP_NO_CLIENT_RENEGOTIATION +SSL_OP_NO_ENCRYPT_THEN_MAC +SSL_OP_NO_QUERY_MTU +SSL_OP_NO_RENEGOTIATION +SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION +SSL_OP_NO_SSL_MASK +SSL_OP_NO_SSLv2 +SSL_OP_NO_SSLv3 +SSL_OP_NO_TICKET +SSL_OP_NO_TLSv1 +SSL_OP_NO_TLSv1_1 +SSL_OP_NO_TLSv1_2 +SSL_OP_NO_TLSv1_3 +SSL_OP_PKCS1_CHECK_1 +SSL_OP_PKCS1_CHECK_2 +SSL_OP_PRIORITIZE_CHACHA +SSL_OP_SAFARI_ECDHE_ECDSA_BUG +SSL_OP_SINGLE_DH_USE +SSL_OP_SINGLE_ECDH_USE +SSL_OP_SSLEAY_080_CLIENT_DH_BUG +SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG +SSL_OP_TLS_BLOCK_PADDING_BUG +SSL_OP_TLS_D5_BUG +SSL_OP_TLS_ROLLBACK_BUG +SSL_OP_TLSEXT_PADDING +SSL_READING +SSL_RECEIVED_SHUTDOWN +SSL_R_BAD_AUTHENTICATION_TYPE +SSL_R_BAD_CHECKSUM +SSL_R_BAD_MAC_DECODE +SSL_R_BAD_RESPONSE_ARGUMENT +SSL_R_BAD_SSL_FILETYPE +SSL_R_BAD_SSL_SESSION_ID_LENGTH +SSL_R_BAD_STATE +SSL_R_BAD_WRITE_RETRY +SSL_R_CHALLENGE_IS_DIFFERENT +SSL_R_CIPHER_TABLE_SRC_ERROR +SSL_R_INVALID_CHALLENGE_LENGTH +SSL_R_NO_CERTIFICATE_SET +SSL_R_NO_CERTIFICATE_SPECIFIED +SSL_R_NO_CIPHER_LIST +SSL_R_NO_CIPHER_MATCH +SSL_R_NO_PRIVATEKEY +SSL_R_NO_PUBLICKEY +SSL_R_NULL_SSL_CTX +SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE +SSL_R_PEER_ERROR +SSL_R_PEER_ERROR_CERTIFICATE +SSL_R_PEER_ERROR_NO_CIPHER +SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE +SSL_R_PUBLIC_KEY_ENCRYPT_ERROR +SSL_R_PUBLIC_KEY_IS_NOT_RSA +SSL_R_READ_WRONG_PACKET_TYPE +SSL_R_SHORT_READ +SSL_R_SSL_SESSION_ID_IS_DIFFERENT +SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY +SSL_R_UNKNOWN_REMOTE_ERROR_TYPE +SSL_R_UNKNOWN_STATE +SSL_R_X509_LIB +SSL_SENT_SHUTDOWN +SSL_SESS_CACHE_OFF +SSL_SESS_CACHE_CLIENT +SSL_SESS_CACHE_SERVER +SSL_SESS_CACHE_BOTH +SSL_SESS_CACHE_NO_AUTO_CLEAR +SSL_SESS_CACHE_NO_INTERNAL_LOOKUP +SSL_SESS_CACHE_NO_INTERNAL_STORE +SSL_SESS_CACHE_NO_INTERNAL +SSL_SESSION_ASN1_VERSION +SSL_ST_ACCEPT +SSL_ST_BEFORE +SSL_ST_CONNECT +SSL_ST_INIT +SSL_ST_OK +SSL_ST_READ_BODY +SSL_ST_READ_HEADER +SSL_VERIFY_CLIENT_ONCE +SSL_VERIFY_FAIL_IF_NO_PEER_CERT +SSL_VERIFY_NONE +SSL_VERIFY_PEER +SSL_VERIFY_POST_HANDSHAKE +SSL_WRITING +SSL_X509_LOOKUP +SSL3_VERSION +SSLEAY_VERSION +SSLEAY_CFLAGS +SSLEAY_BUILT_ON +SSLEAY_PLATFORM +SSLEAY_DIR +X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT +X509_CHECK_FLAG_NEVER_CHECK_SUBJECT +X509_CHECK_FLAG_NO_WILDCARDS +X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS +X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS +X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS +X509_FILETYPE_ASN1 +X509_FILETYPE_DEFAULT +X509_FILETYPE_PEM +X509_PURPOSE_ANY +X509_PURPOSE_CRL_SIGN +X509_PURPOSE_NS_SSL_SERVER +X509_PURPOSE_OCSP_HELPER +X509_PURPOSE_SMIME_ENCRYPT +X509_PURPOSE_SMIME_SIGN +X509_PURPOSE_SSL_CLIENT +X509_PURPOSE_SSL_SERVER +X509_PURPOSE_TIMESTAMP_SIGN +X509_TRUST_COMPAT +X509_TRUST_EMAIL +X509_TRUST_OBJECT_SIGN +X509_TRUST_OCSP_REQUEST +X509_TRUST_OCSP_SIGN +X509_TRUST_SSL_CLIENT +X509_TRUST_SSL_SERVER +X509_TRUST_TSA +X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH +X509_V_ERR_AKID_SKID_MISMATCH +X509_V_ERR_APPLICATION_VERIFICATION +X509_V_ERR_CA_KEY_TOO_SMALL +X509_V_ERR_CA_MD_TOO_WEAK +X509_V_ERR_CERT_CHAIN_TOO_LONG +X509_V_ERR_CERT_HAS_EXPIRED +X509_V_ERR_CERT_NOT_YET_VALID +X509_V_ERR_CERT_REJECTED +X509_V_ERR_CERT_REVOKED +X509_V_ERR_CERT_SIGNATURE_FAILURE +X509_V_ERR_CERT_UNTRUSTED +X509_V_ERR_CRL_HAS_EXPIRED +X509_V_ERR_CRL_NOT_YET_VALID +X509_V_ERR_CRL_PATH_VALIDATION_ERROR +X509_V_ERR_CRL_SIGNATURE_FAILURE +X509_V_ERR_DANE_NO_MATCH +X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT +X509_V_ERR_DIFFERENT_CRL_SCOPE +X509_V_ERR_EE_KEY_TOO_SMALL +X509_V_ERR_EMAIL_MISMATCH +X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD +X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD +X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD +X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD +X509_V_ERR_EXCLUDED_VIOLATION +X509_V_ERR_HOSTNAME_MISMATCH +X509_V_ERR_INVALID_CA +X509_V_ERR_INVALID_CALL +X509_V_ERR_INVALID_EXTENSION +X509_V_ERR_INVALID_NON_CA +X509_V_ERR_INVALID_POLICY_EXTENSION +X509_V_ERR_INVALID_PURPOSE +X509_V_ERR_IP_ADDRESS_MISMATCH +X509_V_ERR_KEYUSAGE_NO_CERTSIGN +X509_V_ERR_KEYUSAGE_NO_CRL_SIGN +X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE +X509_V_ERR_NO_EXPLICIT_POLICY +X509_V_ERR_NO_VALID_SCTS +X509_V_ERR_OCSP_CERT_UNKNOWN +X509_V_ERR_OCSP_VERIFY_FAILED +X509_V_ERR_OCSP_VERIFY_NEEDED +X509_V_ERR_OUT_OF_MEM +X509_V_ERR_PATH_LENGTH_EXCEEDED +X509_V_ERR_PATH_LOOP +X509_V_ERR_PERMITTED_VIOLATION +X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED +X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED +X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION +X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN +X509_V_ERR_STORE_LOOKUP +X509_V_ERR_SUBJECT_ISSUER_MISMATCH +X509_V_ERR_SUBTREE_MINMAX +X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 +X509_V_ERR_SUITE_B_INVALID_ALGORITHM +X509_V_ERR_SUITE_B_INVALID_CURVE +X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM +X509_V_ERR_SUITE_B_INVALID_VERSION +X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED +X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY +X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE +X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE +X509_V_ERR_UNABLE_TO_GET_CRL +X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER +X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT +X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY +X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE +X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION +X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION +X509_V_ERR_UNNESTED_RESOURCE +X509_V_ERR_UNSPECIFIED +X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX +X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE +X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE +X509_V_ERR_UNSUPPORTED_NAME_SYNTAX +X509_V_FLAG_ALLOW_PROXY_CERTS +X509_V_FLAG_CB_ISSUER_CHECK +X509_V_FLAG_CHECK_SS_SIGNATURE +X509_V_FLAG_CRL_CHECK +X509_V_FLAG_CRL_CHECK_ALL +X509_V_FLAG_EXPLICIT_POLICY +X509_V_FLAG_EXTENDED_CRL_SUPPORT +X509_V_FLAG_IGNORE_CRITICAL +X509_V_FLAG_INHIBIT_ANY +X509_V_FLAG_INHIBIT_MAP +X509_V_FLAG_NO_ALT_CHAINS +X509_V_FLAG_NO_CHECK_TIME +X509_V_FLAG_NOTIFY_POLICY +X509_V_FLAG_PARTIAL_CHAIN +X509_V_FLAG_POLICY_CHECK +X509_V_FLAG_POLICY_MASK +X509_V_FLAG_SUITEB_128_LOS +X509_V_FLAG_SUITEB_128_LOS_ONLY +X509_V_FLAG_SUITEB_192_LOS +X509_V_FLAG_TRUSTED_FIRST +X509_V_FLAG_USE_CHECK_TIME +X509_V_FLAG_USE_DELTAS +X509_V_FLAG_X509_STRICT +X509_V_OK +XN_FLAG_COMPAT +XN_FLAG_DN_REV +XN_FLAG_DUMP_UNKNOWN_FIELDS +XN_FLAG_FN_ALIGN +XN_FLAG_FN_LN +XN_FLAG_FN_MASK +XN_FLAG_FN_NONE +XN_FLAG_FN_OID +XN_FLAG_FN_SN +XN_FLAG_MULTILINE +XN_FLAG_ONELINE +XN_FLAG_RFC2253 +XN_FLAG_SEP_COMMA_PLUS +XN_FLAG_SEP_CPLUS_SPC +XN_FLAG_SEP_MASK +XN_FLAG_SEP_MULTILINE +XN_FLAG_SEP_SPLUS_SPC +XN_FLAG_SPC_EQ +TLSEXT_STATUSTYPE_ocsp +TLS1_VERSION +TLS1_1_VERSION +TLS1_2_VERSION +TLS1_3_VERSION +OCSP_RESPONSE_STATUS_SUCCESSFUL +OCSP_RESPONSE_STATUS_MALFORMEDREQUEST +OCSP_RESPONSE_STATUS_INTERNALERROR +OCSP_RESPONSE_STATUS_TRYLATER +OCSP_RESPONSE_STATUS_SIGREQUIRED +OCSP_RESPONSE_STATUS_UNAUTHORIZED +V_OCSP_CERTSTATUS_GOOD +V_OCSP_CERTSTATUS_REVOKED +V_OCSP_CERTSTATUS_UNKNOWN diff --git a/lib/Net/SSLeay.pm b/lib/Net/SSLeay.pm new file mode 100644 index 0000000..7f14519 --- /dev/null +++ b/lib/Net/SSLeay.pm @@ -0,0 +1,1492 @@ +# Net::SSLeay.pm - Perl module for using Eric Young's implementation of SSL +# +# Copyright (c) 1996-2003 Sampo Kellomäki +# Copyright (c) 2005-2010 Florian Ragwitz +# Copyright (c) 2005-2018 Mike McCauley +# Copyright (c) 2018- Chris Novakovic +# Copyright (c) 2018- Tuure Vartiainen +# Copyright (c) 2018- Heikki Vatiainen +# +# All rights reserved. +# +# This module is released under the terms of the Artistic License 2.0. For +# details, see the LICENSE file distributed with Net-SSLeay's source code. + +package Net::SSLeay; + +use 5.8.1; + +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 +# 11 = insist on TLSv1.1 +# 12 = insist on TLSv1.2 +# 13 = insist on TLSv1.3 +# 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 exist 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.88'; # Also update $Net::SSLeay::Handle::VERSION +@ISA = qw(Exporter); + +#BEWARE: +# 3-columns part of @EXPORT_OK related to constants is the output of command: +# perl helper_script/regen_openssl_constants.pl -gen-pod +# if you add/remove any constant you need to update it manually + +@EXPORT_OK = qw( + ASN1_STRFLGS_ESC_CTRL NID_netscape R_UNKNOWN_REMOTE_ERROR_TYPE + ASN1_STRFLGS_ESC_MSB NID_netscape_base_url R_UNKNOWN_STATE + ASN1_STRFLGS_ESC_QUOTE NID_netscape_ca_policy_url R_X509_LIB + ASN1_STRFLGS_RFC2253 NID_netscape_ca_revocation_url SENT_SHUTDOWN + CB_ACCEPT_EXIT NID_netscape_cert_extension SESSION_ASN1_VERSION + CB_ACCEPT_LOOP NID_netscape_cert_sequence SESS_CACHE_BOTH + CB_ALERT NID_netscape_cert_type SESS_CACHE_CLIENT + CB_CONNECT_EXIT NID_netscape_comment SESS_CACHE_NO_AUTO_CLEAR + CB_CONNECT_LOOP NID_netscape_data_type SESS_CACHE_NO_INTERNAL + CB_EXIT NID_netscape_renewal_url SESS_CACHE_NO_INTERNAL_LOOKUP + CB_HANDSHAKE_DONE NID_netscape_revocation_url SESS_CACHE_NO_INTERNAL_STORE + CB_HANDSHAKE_START NID_netscape_ssl_server_name SESS_CACHE_OFF + CB_LOOP NID_ns_sgc SESS_CACHE_SERVER + CB_READ NID_organizationName SSL3_VERSION + CB_READ_ALERT NID_organizationalUnitName SSLEAY_BUILT_ON + CB_WRITE NID_pbeWithMD2AndDES_CBC SSLEAY_CFLAGS + CB_WRITE_ALERT NID_pbeWithMD2AndRC2_CBC SSLEAY_DIR + ERROR_NONE NID_pbeWithMD5AndCast5_CBC SSLEAY_PLATFORM + ERROR_SSL NID_pbeWithMD5AndDES_CBC SSLEAY_VERSION + ERROR_SYSCALL NID_pbeWithMD5AndRC2_CBC ST_ACCEPT + ERROR_WANT_ACCEPT NID_pbeWithSHA1AndDES_CBC ST_BEFORE + ERROR_WANT_CONNECT NID_pbeWithSHA1AndRC2_CBC ST_CONNECT + ERROR_WANT_READ NID_pbe_WithSHA1And128BitRC2_CBC ST_INIT + ERROR_WANT_WRITE NID_pbe_WithSHA1And128BitRC4 ST_OK + ERROR_WANT_X509_LOOKUP NID_pbe_WithSHA1And2_Key_TripleDES_CBC ST_READ_BODY + ERROR_ZERO_RETURN NID_pbe_WithSHA1And3_Key_TripleDES_CBC ST_READ_HEADER + EVP_PKS_DSA NID_pbe_WithSHA1And40BitRC2_CBC TLS1_1_VERSION + EVP_PKS_EC NID_pbe_WithSHA1And40BitRC4 TLS1_2_VERSION + EVP_PKS_RSA NID_pbes2 TLS1_3_VERSION + EVP_PKT_ENC NID_pbmac1 TLS1_VERSION + EVP_PKT_EXCH NID_pkcs TLSEXT_STATUSTYPE_ocsp + EVP_PKT_EXP NID_pkcs3 VERIFY_CLIENT_ONCE + EVP_PKT_SIGN NID_pkcs7 VERIFY_FAIL_IF_NO_PEER_CERT + EVP_PK_DH NID_pkcs7_data VERIFY_NONE + EVP_PK_DSA NID_pkcs7_digest VERIFY_PEER + EVP_PK_EC NID_pkcs7_encrypted VERIFY_POST_HANDSHAKE + EVP_PK_RSA NID_pkcs7_enveloped V_OCSP_CERTSTATUS_GOOD + FILETYPE_ASN1 NID_pkcs7_signed V_OCSP_CERTSTATUS_REVOKED + FILETYPE_PEM NID_pkcs7_signedAndEnveloped V_OCSP_CERTSTATUS_UNKNOWN + F_CLIENT_CERTIFICATE NID_pkcs8ShroudedKeyBag WRITING + F_CLIENT_HELLO NID_pkcs9 X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + F_CLIENT_MASTER_KEY NID_pkcs9_challengePassword X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS + F_D2I_SSL_SESSION NID_pkcs9_contentType X509_CHECK_FLAG_NEVER_CHECK_SUBJECT + F_GET_CLIENT_FINISHED NID_pkcs9_countersignature X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + F_GET_CLIENT_HELLO NID_pkcs9_emailAddress X509_CHECK_FLAG_NO_WILDCARDS + F_GET_CLIENT_MASTER_KEY NID_pkcs9_extCertAttributes X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + F_GET_SERVER_FINISHED NID_pkcs9_messageDigest X509_FILETYPE_ASN1 + F_GET_SERVER_HELLO NID_pkcs9_signingTime X509_FILETYPE_DEFAULT + F_GET_SERVER_VERIFY NID_pkcs9_unstructuredAddress X509_FILETYPE_PEM + F_I2D_SSL_SESSION NID_pkcs9_unstructuredName X509_LOOKUP + F_READ_N NID_private_key_usage_period X509_PURPOSE_ANY + F_REQUEST_CERTIFICATE NID_rc2_40_cbc X509_PURPOSE_CRL_SIGN + F_SERVER_HELLO NID_rc2_64_cbc X509_PURPOSE_NS_SSL_SERVER + F_SSL_CERT_NEW NID_rc2_cbc X509_PURPOSE_OCSP_HELPER + F_SSL_GET_NEW_SESSION NID_rc2_cfb64 X509_PURPOSE_SMIME_ENCRYPT + F_SSL_NEW NID_rc2_ecb X509_PURPOSE_SMIME_SIGN + F_SSL_READ NID_rc2_ofb64 X509_PURPOSE_SSL_CLIENT + F_SSL_RSA_PRIVATE_DECRYPT NID_rc4 X509_PURPOSE_SSL_SERVER + F_SSL_RSA_PUBLIC_ENCRYPT NID_rc4_40 X509_PURPOSE_TIMESTAMP_SIGN + F_SSL_SESSION_NEW NID_rc5_cbc X509_TRUST_COMPAT + F_SSL_SESSION_PRINT_FP NID_rc5_cfb64 X509_TRUST_EMAIL + F_SSL_SET_FD NID_rc5_ecb X509_TRUST_OBJECT_SIGN + F_SSL_SET_RFD NID_rc5_ofb64 X509_TRUST_OCSP_REQUEST + F_SSL_SET_WFD NID_ripemd160 X509_TRUST_OCSP_SIGN + F_SSL_USE_CERTIFICATE NID_ripemd160WithRSA X509_TRUST_SSL_CLIENT + F_SSL_USE_CERTIFICATE_ASN1 NID_rle_compression X509_TRUST_SSL_SERVER + F_SSL_USE_CERTIFICATE_FILE NID_rsa X509_TRUST_TSA + F_SSL_USE_PRIVATEKEY NID_rsaEncryption X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH + F_SSL_USE_PRIVATEKEY_ASN1 NID_rsadsi X509_V_ERR_AKID_SKID_MISMATCH + F_SSL_USE_PRIVATEKEY_FILE NID_safeContentsBag X509_V_ERR_APPLICATION_VERIFICATION + F_SSL_USE_RSAPRIVATEKEY NID_sdsiCertificate X509_V_ERR_CA_KEY_TOO_SMALL + F_SSL_USE_RSAPRIVATEKEY_ASN1 NID_secretBag X509_V_ERR_CA_MD_TOO_WEAK + F_SSL_USE_RSAPRIVATEKEY_FILE NID_serialNumber X509_V_ERR_CERT_CHAIN_TOO_LONG + F_WRITE_PENDING NID_server_auth X509_V_ERR_CERT_HAS_EXPIRED + GEN_DIRNAME NID_sha X509_V_ERR_CERT_NOT_YET_VALID + GEN_DNS NID_sha1 X509_V_ERR_CERT_REJECTED + GEN_EDIPARTY NID_sha1WithRSA X509_V_ERR_CERT_REVOKED + GEN_EMAIL NID_sha1WithRSAEncryption X509_V_ERR_CERT_SIGNATURE_FAILURE + GEN_IPADD NID_shaWithRSAEncryption X509_V_ERR_CERT_UNTRUSTED + GEN_OTHERNAME NID_stateOrProvinceName X509_V_ERR_CRL_HAS_EXPIRED + GEN_RID NID_subject_alt_name X509_V_ERR_CRL_NOT_YET_VALID + GEN_URI NID_subject_key_identifier X509_V_ERR_CRL_PATH_VALIDATION_ERROR + GEN_X400 NID_surname X509_V_ERR_CRL_SIGNATURE_FAILURE + LIBRESSL_VERSION_NUMBER NID_sxnet X509_V_ERR_DANE_NO_MATCH + MBSTRING_ASC NID_time_stamp X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + MBSTRING_BMP NID_title X509_V_ERR_DIFFERENT_CRL_SCOPE + MBSTRING_FLAG NID_undef X509_V_ERR_EE_KEY_TOO_SMALL + MBSTRING_UNIV NID_uniqueIdentifier X509_V_ERR_EMAIL_MISMATCH + MBSTRING_UTF8 NID_x509Certificate X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD + MIN_RSA_MODULUS_LENGTH_IN_BYTES NID_x509Crl X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD + MODE_ACCEPT_MOVING_WRITE_BUFFER NID_zlib_compression X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD + MODE_AUTO_RETRY NOTHING X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD + MODE_ENABLE_PARTIAL_WRITE OCSP_RESPONSE_STATUS_INTERNALERROR X509_V_ERR_EXCLUDED_VIOLATION + MODE_RELEASE_BUFFERS OCSP_RESPONSE_STATUS_MALFORMEDREQUEST X509_V_ERR_HOSTNAME_MISMATCH + NID_OCSP_sign OCSP_RESPONSE_STATUS_SIGREQUIRED X509_V_ERR_INVALID_CA + NID_SMIMECapabilities OCSP_RESPONSE_STATUS_SUCCESSFUL X509_V_ERR_INVALID_CALL + NID_X500 OCSP_RESPONSE_STATUS_TRYLATER X509_V_ERR_INVALID_EXTENSION + NID_X509 OCSP_RESPONSE_STATUS_UNAUTHORIZED X509_V_ERR_INVALID_NON_CA + NID_ad_OCSP OPENSSL_BUILT_ON X509_V_ERR_INVALID_POLICY_EXTENSION + NID_ad_ca_issuers OPENSSL_CFLAGS X509_V_ERR_INVALID_PURPOSE + NID_algorithm OPENSSL_DIR X509_V_ERR_IP_ADDRESS_MISMATCH + NID_authority_key_identifier OPENSSL_ENGINES_DIR X509_V_ERR_KEYUSAGE_NO_CERTSIGN + NID_basic_constraints OPENSSL_PLATFORM X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + NID_bf_cbc OPENSSL_VERSION X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE + NID_bf_cfb64 OPENSSL_VERSION_NUMBER X509_V_ERR_NO_EXPLICIT_POLICY + NID_bf_ecb OP_ALL X509_V_ERR_NO_VALID_SCTS + NID_bf_ofb64 OP_ALLOW_NO_DHE_KEX X509_V_ERR_OCSP_CERT_UNKNOWN + NID_cast5_cbc OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION X509_V_ERR_OCSP_VERIFY_FAILED + NID_cast5_cfb64 OP_CIPHER_SERVER_PREFERENCE X509_V_ERR_OCSP_VERIFY_NEEDED + NID_cast5_ecb OP_CISCO_ANYCONNECT X509_V_ERR_OUT_OF_MEM + NID_cast5_ofb64 OP_COOKIE_EXCHANGE X509_V_ERR_PATH_LENGTH_EXCEEDED + NID_certBag OP_CRYPTOPRO_TLSEXT_BUG X509_V_ERR_PATH_LOOP + NID_certificate_policies OP_DONT_INSERT_EMPTY_FRAGMENTS X509_V_ERR_PERMITTED_VIOLATION + NID_client_auth OP_ENABLE_MIDDLEBOX_COMPAT X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED + NID_code_sign OP_EPHEMERAL_RSA X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED + NID_commonName OP_LEGACY_SERVER_CONNECT X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION + NID_countryName OP_MICROSOFT_BIG_SSLV3_BUFFER X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + NID_crlBag OP_MICROSOFT_SESS_ID_BUG X509_V_ERR_STORE_LOOKUP + NID_crl_distribution_points OP_MSIE_SSLV2_RSA_PADDING X509_V_ERR_SUBJECT_ISSUER_MISMATCH + NID_crl_number OP_NETSCAPE_CA_DN_BUG X509_V_ERR_SUBTREE_MINMAX + NID_crl_reason OP_NETSCAPE_CHALLENGE_BUG X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 + NID_delta_crl OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_ALGORITHM + NID_des_cbc OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_CURVE + NID_des_cfb64 OP_NON_EXPORT_FIRST X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM + NID_des_ecb OP_NO_ANTI_REPLAY X509_V_ERR_SUITE_B_INVALID_VERSION + NID_des_ede OP_NO_CLIENT_RENEGOTIATION X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED + NID_des_ede3 OP_NO_COMPRESSION X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY + NID_des_ede3_cbc OP_NO_ENCRYPT_THEN_MAC X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE + NID_des_ede3_cfb64 OP_NO_QUERY_MTU X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE + NID_des_ede3_ofb64 OP_NO_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL + NID_des_ede_cbc OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER + NID_des_ede_cfb64 OP_NO_SSL_MASK X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT + NID_des_ede_ofb64 OP_NO_SSLv2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + NID_des_ofb64 OP_NO_SSLv3 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE + NID_description OP_NO_TICKET X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION + NID_desx_cbc OP_NO_TLSv1 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION + NID_dhKeyAgreement OP_NO_TLSv1_1 X509_V_ERR_UNNESTED_RESOURCE + NID_dnQualifier OP_NO_TLSv1_2 X509_V_ERR_UNSPECIFIED + NID_dsa OP_NO_TLSv1_3 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX + NID_dsaWithSHA OP_PKCS1_CHECK_1 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE + NID_dsaWithSHA1 OP_PKCS1_CHECK_2 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE + NID_dsaWithSHA1_2 OP_PRIORITIZE_CHACHA X509_V_ERR_UNSUPPORTED_NAME_SYNTAX + NID_dsa_2 OP_SAFARI_ECDHE_ECDSA_BUG X509_V_FLAG_ALLOW_PROXY_CERTS + NID_email_protect OP_SINGLE_DH_USE X509_V_FLAG_CB_ISSUER_CHECK + NID_ext_key_usage OP_SINGLE_ECDH_USE X509_V_FLAG_CHECK_SS_SIGNATURE + NID_ext_req OP_SSLEAY_080_CLIENT_DH_BUG X509_V_FLAG_CRL_CHECK + NID_friendlyName OP_SSLREF2_REUSE_CERT_TYPE_BUG X509_V_FLAG_CRL_CHECK_ALL + NID_givenName OP_TLSEXT_PADDING X509_V_FLAG_EXPLICIT_POLICY + NID_hmacWithSHA1 OP_TLS_BLOCK_PADDING_BUG X509_V_FLAG_EXTENDED_CRL_SUPPORT + NID_id_ad OP_TLS_D5_BUG X509_V_FLAG_IGNORE_CRITICAL + NID_id_ce OP_TLS_ROLLBACK_BUG X509_V_FLAG_INHIBIT_ANY + NID_id_kp READING X509_V_FLAG_INHIBIT_MAP + NID_id_pbkdf2 RECEIVED_SHUTDOWN X509_V_FLAG_NOTIFY_POLICY + NID_id_pe RSA_3 X509_V_FLAG_NO_ALT_CHAINS + NID_id_pkix RSA_F4 X509_V_FLAG_NO_CHECK_TIME + NID_id_qt_cps R_BAD_AUTHENTICATION_TYPE X509_V_FLAG_PARTIAL_CHAIN + NID_id_qt_unotice R_BAD_CHECKSUM X509_V_FLAG_POLICY_CHECK + NID_idea_cbc R_BAD_MAC_DECODE X509_V_FLAG_POLICY_MASK + NID_idea_cfb64 R_BAD_RESPONSE_ARGUMENT X509_V_FLAG_SUITEB_128_LOS + NID_idea_ecb R_BAD_SSL_FILETYPE X509_V_FLAG_SUITEB_128_LOS_ONLY + NID_idea_ofb64 R_BAD_SSL_SESSION_ID_LENGTH X509_V_FLAG_SUITEB_192_LOS + NID_info_access R_BAD_STATE X509_V_FLAG_TRUSTED_FIRST + NID_initials R_BAD_WRITE_RETRY X509_V_FLAG_USE_CHECK_TIME + NID_invalidity_date R_CHALLENGE_IS_DIFFERENT X509_V_FLAG_USE_DELTAS + NID_issuer_alt_name R_CIPHER_TABLE_SRC_ERROR X509_V_FLAG_X509_STRICT + NID_keyBag R_INVALID_CHALLENGE_LENGTH X509_V_OK + NID_key_usage R_NO_CERTIFICATE_SET XN_FLAG_COMPAT + NID_localKeyID R_NO_CERTIFICATE_SPECIFIED XN_FLAG_DN_REV + NID_localityName R_NO_CIPHER_LIST XN_FLAG_DUMP_UNKNOWN_FIELDS + NID_md2 R_NO_CIPHER_MATCH XN_FLAG_FN_ALIGN + NID_md2WithRSAEncryption R_NO_PRIVATEKEY XN_FLAG_FN_LN + NID_md5 R_NO_PUBLICKEY XN_FLAG_FN_MASK + NID_md5WithRSA R_NULL_SSL_CTX XN_FLAG_FN_NONE + NID_md5WithRSAEncryption R_PEER_DID_NOT_RETURN_A_CERTIFICATE XN_FLAG_FN_OID + NID_md5_sha1 R_PEER_ERROR XN_FLAG_FN_SN + NID_mdc2 R_PEER_ERROR_CERTIFICATE XN_FLAG_MULTILINE + NID_mdc2WithRSA R_PEER_ERROR_NO_CIPHER XN_FLAG_ONELINE + NID_ms_code_com R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE XN_FLAG_RFC2253 + NID_ms_code_ind R_PUBLIC_KEY_ENCRYPT_ERROR XN_FLAG_SEP_COMMA_PLUS + NID_ms_ctl_sign R_PUBLIC_KEY_IS_NOT_RSA XN_FLAG_SEP_CPLUS_SPC + NID_ms_efs R_READ_WRONG_PACKET_TYPE XN_FLAG_SEP_MASK + NID_ms_ext_req R_SHORT_READ XN_FLAG_SEP_MULTILINE + NID_ms_sgc R_SSL_SESSION_ID_IS_DIFFERENT XN_FLAG_SEP_SPLUS_SPC + NID_name R_UNABLE_TO_EXTRACT_PUBLIC_KEY XN_FLAG_SPC_EQ + BIO_eof + BIO_f_ssl + BIO_free + BIO_new + BIO_new_file + BIO_pending + BIO_read + BIO_s_mem + BIO_wpending + BIO_write + CTX_free + CTX_get_cert_store + CTX_new + CTX_use_RSAPrivateKey_file + CTX_use_certificate_file + CTX_v23_new + CTX_v2_new + CTX_v3_new + ERR_error_string + ERR_get_error + ERR_load_RAND_strings + ERR_load_SSL_strings + PEM_read_bio_X509_CRL + RSA_free + RSA_generate_key + SESSION + SESSION_free + SESSION_get_master_key + SESSION_new + SESSION_print + X509_NAME_get_text_by_NID + X509_NAME_oneline + X509_STORE_CTX_set_flags + X509_STORE_add_cert + X509_STORE_add_crl + X509_check_email + X509_check_host + X509_check_ip + X509_check_ip_asc + X509_free + X509_get_issuer_name + X509_get_subject_name + X509_load_cert_crl_file + X509_load_cert_file + X509_load_crl_file + accept + add_session + clear + clear_error + connect + copy_session_id + d2i_SSL_SESSION + die_if_ssl_error + die_now + do_https + dump_peer_certificate + err + flush_sessions + free + get_cipher + get_cipher_list + get_client_random + get_fd + get_http + get_http4 + get_https + get_https3 + get_https4 + get_httpx + get_httpx4 + get_peer_certificate + get_peer_cert_chain + get_rbio + get_read_ahead + get_server_random + get_shared_ciphers + get_time + get_timeout + get_wbio + i2d_SSL_SESSION + load_error_strings + make_form + make_headers + new + peek + pending + post_http + post_http4 + post_https + post_https3 + post_https4 + post_httpx + post_httpx4 + print_errs + read + remove_session + rstate_string + rstate_string_long + set_bio + set_cert_and_key + set_cipher_list + set_fd + set_read_ahead + set_rfd + set_server_cert_and_key + set_session + set_time + set_timeout + set_verify + set_wfd + ssl_read_CRLF + ssl_read_all + ssl_read_until + ssl_write_CRLF + ssl_write_all + sslcat + state_string + state_string_long + tcp_read_CRLF + tcp_read_all + tcp_read_until + tcp_write_CRLF + tcp_write_all + tcpcat + tcpxcat + use_PrivateKey + use_PrivateKey_ASN1 + use_PrivateKey_file + use_RSAPrivateKey + use_RSAPrivateKey_ASN1 + use_RSAPrivateKey_file + use_certificate + use_certificate_ASN1 + use_certificate_file + write + d2i_OCSP_RESPONSE + i2d_OCSP_RESPONSE + OCSP_RESPONSE_free + d2i_OCSP_REQUEST + i2d_OCSP_REQUEST + OCSP_REQUEST_free + OCSP_cert2ids + OCSP_ids2req + OCSP_response_status + OCSP_response_status_str + OCSP_response_verify + OCSP_response_results + OCSP_RESPONSE_STATUS_INTERNALERROR + OCSP_RESPONSE_STATUS_MALFORMEDREQUEST + OCSP_RESPONSE_STATUS_SIGREQUIRED + OCSP_RESPONSE_STATUS_SUCCESSFUL + OCSP_RESPONSE_STATUS_TRYLATER + OCSP_RESPONSE_STATUS_UNAUTHORIZED + TLSEXT_STATUSTYPE_ocsp + V_OCSP_CERTSTATUS_GOOD + V_OCSP_CERTSTATUS_REVOKED + V_OCSP_CERTSTATUS_UNKNOWN +); + +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 ($) { defined $_[0] ? length $_[0] : 0 }'; +$@ and eval ' sub blength ($) { defined $_[0] ? length $_[0] : 0 }' ; +} + +# Autoload methods go after __END__, and are processed by the autosplit program. + + +1; +__END__ + +### 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 = &Socket::IPPROTO_TCP; # getprotobyname('tcp') not available on android + 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 = ; # *** 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, $rv, $errs); + my $reply = ''; + + while ($how_much > 0) { + ($got, $rv) = Net::SSLeay::read($ssl, + ($how_much > 32768) ? 32768 : $how_much + ); + if (! defined $got) { + my $err = Net::SSLeay::get_error($ssl, $rv); + if ($err != Net::SSLeay::ERROR_WANT_READ() and + $err != Net::SSLeay::ERROR_WANT_WRITE()) { + $errs = print_errs('SSL_read'); + last; + } + next; + } + $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; + } else { + if (defined $wrote) { + # check error conditions via SSL_get_error per man page + if ( my $sslerr = get_error($ssl, $wrote) ) { + my $errstr = ERR_error_string($sslerr); + my $errname = ''; + SWITCH: { + $sslerr == constant("ERROR_NONE") && do { + # according to map page SSL_get_error(3ssl): + # The TLS/SSL I/O operation completed. + # This result code is returned if and only if ret > 0 + # so if we received it here complain... + warn "ERROR_NONE unexpected with invalid return value!" + if $trace; + $errname = "SSL_ERROR_NONE"; + }; + $sslerr == constant("ERROR_WANT_READ") && do { + # operation did not complete, call again later, so do not + # set errname and empty err_que since this is a known + # error that is expected but, we should continue to try + # writing the rest of our data with same io call and params. + warn "ERROR_WANT_READ (TLS/SSL Handshake, will continue)\n" + if $trace; + print_errs('SSL_write(want read)'); + last SWITCH; + }; + $sslerr == constant("ERROR_WANT_WRITE") && do { + # operation did not complete, call again later, so do not + # set errname and empty err_que since this is a known + # error that is expected but, we should continue to try + # writing the rest of our data with same io call and params. + warn "ERROR_WANT_WRITE (TLS/SSL Handshake, will continue)\n" + if $trace; + print_errs('SSL_write(want write)'); + last SWITCH; + }; + $sslerr == constant("ERROR_ZERO_RETURN") && do { + # valid protocol closure from other side, no longer able to + # write, since there is no longer a session... + warn "ERROR_ZERO_RETURN($wrote): TLS/SSLv3 Closure alert\n" + if $trace; + $errname = "SSL_ERROR_ZERO_RETURN"; + last SWITCH; + }; + $sslerr == constant("ERROR_SSL") && do { + # library/protocol error + warn "ERROR_SSL($wrote): Library/Protocol error occured\n" + if $trace; + $errname = "SSL_ERROR_SSL"; + last SWITCH; + }; + $sslerr == constant("ERROR_WANT_CONNECT") && do { + # according to man page, should never happen on call to + # SSL_write, so complain, but handle as known error type + warn "ERROR_WANT_CONNECT: Unexpected error for SSL_write\n" + if $trace; + $errname = "SSL_ERROR_WANT_CONNECT"; + last SWITCH; + }; + $sslerr == constant("ERROR_WANT_ACCEPT") && do { + # according to man page, should never happen on call to + # SSL_write, so complain, but handle as known error type + warn "ERROR_WANT_ACCEPT: Unexpected error for SSL_write\n" + if $trace; + $errname = "SSL_ERROR_WANT_ACCEPT"; + last SWITCH; + }; + $sslerr == constant("ERROR_WANT_X509_LOOKUP") && do { + # operation did not complete: waiting on call back, + # call again later, so do not set errname and empty err_que + # since this is a known error that is expected but, we should + # continue to try writing the rest of our data with same io + # call parameter. + warn "ERROR_WANT_X509_LOOKUP: (Cert Callback asked for in ". + "SSL_write will contine)\n" if $trace; + print_errs('SSL_write(want x509'); + last SWITCH; + }; + $sslerr == constant("ERROR_SYSCALL") && do { + # some IO error occured. According to man page: + # Check retval, ERR, fallback to errno + if ($wrote==0) { # EOF + warn "ERROR_SYSCALL($wrote): EOF violates protocol.\n" + if $trace; + $errname = "SSL_ERROR_SYSCALL(EOF)"; + } else { # -1 underlying BIO error reported. + # check error que for details, don't set errname since we + # are directly appending to errs + my $chkerrs = print_errs('SSL_write (syscall)'); + if ($chkerrs) { + warn "ERROR_SYSCALL($wrote): Have errors\n" if $trace; + $errs .= "ssl_write_all $$: 1 - ERROR_SYSCALL($wrote,". + "$sslerr,$errstr,$!)\n$chkerrs"; + } else { # que was empty, use errno + warn "ERROR_SYSCALL($wrote): errno($!)\n" if $trace; + $errs .= "ssl_write_all $$: 1 - ERROR_SYSCALL($wrote,". + "$sslerr) : $!\n"; + } + } + last SWITCH; + }; + warn "Unhandled val $sslerr from SSL_get_error(SSL,$wrote)\n" + if $trace; + $errname = "SSL_ERROR_?($sslerr)"; + } # end of SWITCH block + if ($errname) { # if we had an errname set add the error + $errs .= "ssl_write_all $$: 1 - $errname($wrote,$sslerr,". + "$errstr,$!)\n"; + } + } # endif on have SSL_get_error val + } # endif on $wrote defined + } # endelse on $wrote > 0 + $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; + # append remaining errors in que and report if errs exist + $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 + +# 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) = @_; + + # 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::ssl_read_all($ssl, $found+$len_delim); + #read up to the end of the delimiter + $got = Net::SSLeay::ssl_read_all($ssl, + $found + $len_delim + - ((blength($match)) - (blength($got)))); + $done = 1; + } else { + $got = Net::SSLeay::ssl_read_all($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::ssl_read_all($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) = @_; + + # 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) { + my $poll_retval = Net::SSLeay::RAND_poll(); + warn "Random number generator not seeded!!!" if $trace && !$poll_retval; + } + + RAND_load_file($rn_seed_file, -s _) if $rnsf; + RAND_seed($seed) if $seed; + RAND_seed($ENV{RND_SEED}) if $ENV{RND_SEED}; + 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) { + unless (exists &Net::SSLeay::CTX_v2_new) { + warn "ssl_version has been set to 2, but this version of OpenSSL has been compiled without SSLv2 support"; + return undef; + } + $ctx = CTX_v2_new(); + } + elsif ($ssl_version == 3) { $ctx = CTX_v3_new(); } + elsif ($ssl_version == 10) { $ctx = CTX_tlsv1_new(); } + elsif ($ssl_version == 11) { + unless (exists &Net::SSLeay::CTX_tlsv1_1_new) { + warn "ssl_version has been set to 11, but this version of OpenSSL has been compiled without TLSv1.1 support"; + return undef; + } + $ctx = CTX_tlsv1_1_new; + } + elsif ($ssl_version == 12) { + unless (exists &Net::SSLeay::CTX_tlsv1_2_new) { + warn "ssl_version has been set to 12, but this version of OpenSSL has been compiled without TLSv1.2 support"; + return undef; + } + $ctx = CTX_tlsv1_2_new; + } + elsif ($ssl_version == 13) { + unless (eval { Net::SSLeay::TLS1_3_VERSION(); } ) { + warn "ssl_version has been set to 13, but this version of OpenSSL has been compiled without TLSv1.3 support"; + return undef; + } + $ctx = CTX_new(); + unless(Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION())) { + warn "CTX_set_min_proto failed for TLSv1.3"; + return undef; + } + unless(Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION())) { + warn "CTX_set_max_proto failed for TLSv1.3"; + return undef; + } + } + else { $ctx = CTX_new(); } + return $ctx; +} + +### +### Standard initialisation. Initialise the ssl library in the usual way +### at most once. Override this if you need differnet initialisation +### SSLeay_add_ssl_algorithms is also protected against multiple runs in SSLeay.xs +### and is also mutex protected in threading perls +### + +my $library_initialised; +sub initialize +{ + if (!$library_initialised) + { + load_error_strings(); # Some bloat, but I'm after ease of use + SSLeay_add_ssl_algorithms(); # and debuggability. + randomize(); + $library_initialised++; + } +} + +### +### 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; + initialize(); # Will init at most once + + $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(); + 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; + initialize(); + + $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(); + 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_PrivateKey_file( $ctx, $key_path, &FILETYPE_PEM ) == 1 + or $errs .= print_errs("private key `$key_path' ($!)"); + CTX_use_certificate_file ($ctx, $cert_path, &FILETYPE_PEM) == 1 + or $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 = $proxyuser + ? $CRLF . 'Proxy-authorization: Basic ' + . MIME::Base64::encode("$proxyuser:$proxypass", '') + : ''; +} + +### +### 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); + + my $len = blength($content); + if ($len) { + $mime_type = "application/x-www-form-urlencoded" unless $mime_type; + $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, defined $headers ? + 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; + my %hr = (); + for my $hh (split /\s?\n/, $headers) { + my ($h,$v) = ($hh =~ /^(\S+)\:\s*(.*)$/); + push @{$hr{uc($h)}}, $v; + } + return ($page, $response, \%hr, $server_cert); +} + +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__ + diff --git a/lib/Net/SSLeay.pod b/lib/Net/SSLeay.pod new file mode 100644 index 0000000..24de6d8 --- /dev/null +++ b/lib/Net/SSLeay.pod @@ -0,0 +1,9783 @@ +=encoding utf-8 + +=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, '/'); # Case 1 + + ($page, $response, %reply_headers) + = get_https('www.bacus.pt', 443, '/', # Case 2 + make_headers(User-Agent => 'Cryptozilla/5.0b1', + Referer => 'https://www.bacus.pt' + )); + + ($page, $result, %headers) = # Case 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', '', # Case 3 + make_form(OK => '1', + name => 'Sampo' + )); + + $reply = sslcat($host, $port, $request); # Case 4 + + ($reply, $err, $server_cert) = sslcat($host, $port, $request); # Case 5 + + $Net::SSLeay::trace = 2; # 0=no debugging, 1=ciphers, 2=trace, 3=dump data + + Net::SSLeay::initialize(); # Initialize ssl library once + +=head1 DESCRIPTION + +L module contains perl bindings to openssl (L) library. + +B L cannot be built with pre-0.9.3 openssl. It is strongly recommended +to use at least 0.9.7 (as older versions are not tested during development). Some low level API functions +may be available with certain openssl versions. + +It is compatible with OpenSSL 1.0 and 1.1. Some functions are not available under OpenSSL 1.1. + +L module basically comprise of: + +=over + +=item * High level functions for accessing web servers (by using HTTP/HTTPS) + +=item * Low level API (mostly mapped 1:1 to openssl's C functions) + +=item * Convenience functions (related to low level API but with more perl friendly interface) + +=back + +There is also a related module called L included in this +distribution that you might want to use instead. It has its own pod +documentation. + +=head2 High level functions for accessing web servers + +This module offers some high level convenience functions for accessing +web pages on SSL servers (for symmetry, the same API is offered for +accessing http servers, too), an C function for writing your own +clients, and finally access to the SSL api of the SSLeay/OpenSSL package +so you can write servers or clients for more complicated applications. + +For high level functions it is most convenient to import them into your +main namespace as indicated in the synopsis. + +=head3 Basic set of functions + +=over + +=item * get_https + +=item * post_https + +=item * put_https + +=item * head_https + +=item * do_https + +=item * sslcat + +=item * https_cat + +=item * make_form + +=item * make_headers + +=back + +B demonstrates the typical invocation of get_https() to fetch an HTML +page from secure server. The first argument provides the hostname or IP +in dotted decimal notation of the remote server to contact. The 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 the HTTP specifications at L. + +B demonstrates full fledged use of C. As can be seen, +C 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 is used to insert some additional headers +in the request. C is a function that will convert a list or +hash to such headers. By default C supplies C (to make +virtual hosting easy) and C (reportedly needed by IIS) headers. + +B demonstrates how to get a password protected page. Refer to +the HTTP protocol specifications for further details (e.g. RFC-2617). + +B invokes C to submit a HTML/CGI form to a secure +server. The first four arguments are equal to C (note that +the empty string (C<''>) is passed as header argument). +The fifth argument is the +contents of the form formatted according to CGI specification. +Do not post UTF-8 data as content: use utf8::downgrade first. In this +case the helper function C is used to do the formatting, +but you could pass any string. C automatically adds +C and C headers to the request. + +B shows the fundamental C function (inspired in spirit by +the C utility :-). It's 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 is just a transport. + +B is a full invocation of C which allows the return of errors +as well as the server (peer) certificate. + +The C<$trace> global variable can be used to control the verbosity of the +high level functions. Level 0 guarantees silence, level 1 (the default) +only emits error messages. + +=head3 Alternate versions of high-level API + +=over + +=item * get_https3 + +=item * post_https3 + +=item * put_https3 + +=item * get_https4 + +=item * post_https4 + +=item * put_https4 + +=back + +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) + = 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 +a hash of arrays (see L and L if you are +not familiar with complex perl data structures). To access a single value +of such a header hash you would do something like + + print $$headers_ref{COOKIE}[0]; + +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 has returned the https +request has already been sent to the server, whether you decide to +trust 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 the implementation of C +for guidance on how to do this. + +=head3 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 a client side +certificate. The basic authentication over HTTPS is actually quite +safe because HTTPS guarantees that the password will not travel in +the clear. Never-the-less, problems like easily guessable passwords +remain. The client certificate method involves authentication of the +client at the SSL level using a certificate. For this to work, both the +client and the server 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 keys 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); + +B demonstrates getting a password protected page that also requires +a client certificate, i.e. it is possible to use both authentication +methods simultaneously. + +B is a full blown POST to a secure server that requires both password +authentication and a client certificate, just like in case 2c. + +Note: The client will not send a certificate unless the server requests one. +This is typically achieved by setting the verify mode to C on the +server: + + Net::SSLeay::set_verify(ssl, Net::SSLeay::VERIFY_PEER, 0); + +See C for a full description. + +=head3 Working through a web proxy + +=over + +=item * set_proxy + +=back + +C can use a web proxy to make its connections. You need to +first set the proxy host and port using C 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 a 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 the case where we authenticate to the proxy as +C<"joe"> and to the final web server as C<"susie">. Proxy authentication +requires the C module to work. + +=head3 HTTP (without S) API + +=over + +=item * get_http + +=item * post_http + +=item * tcpcat + +=item * get_httpx + +=item * post_httpx + +=item * tcpxcat + +=back + +Over the years it has become clear that it would be convenient to use +the light-weight flavour API of C for normal HTTP as well (see +C for the 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 the first argument a flag +which indicates whether SSL is used or not. + +=head2 Certificate verification and Certificate Revocation 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 checking like this: + + &Net::SSLeay::X509_STORE_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, C. It will read all the .r files for the +issuer, and then check for a revocation of the peer certificate 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.... + } + +Usually the URLs where you can download the CRLs is contained in the certificate +itself and you can extract them with + + my @url = Net::SSLeay::P_X509_get_crl_distribution_points($cert) + +But there is no automatic downloading of the CRLs and often these CRLs are too +huge to just download them to verify a single certificate. +Also, these CRLs are often in DER format which you need to convert to PEM before +you can use it: + + openssl crl -in crl.der -inform der -out crl.pem + +So as an alternative for faster and timely revocation checks you better use +the Online Status Revocation Protocol (OCSP). + +=head2 Certificate verification and Online Status Revocation Protocol (OCSP) + +While checking for revoked certificates is possible and fast with Certificate +Revocation Lists, you need to download the complete and often huge list before +you can verify a single certificate. + +A faster way is to ask the CA to check the revocation of just a single or a few +certificates using OCSP. Basically you generate for each certificate an +OCSP_CERTID based on the certificate itself and its issuer, put the ids +togetether into an OCSP_REQUEST and send the request to the URL given in the +certificate. + +As a result you get back an OCSP_RESPONSE and need to check the status of the +response, check that it is valid (e.g. signed by the CA) and finally extract the +information about each OCSP_CERTID to find out if the certificate is still valid +or got revoked. + +With Net::SSLeay this can be done like this: + + # get id(s) for given certs, like from get_peer_certificate + # or get_peer_cert_chain. This will croak if + # - one tries to make an OCSP_CERTID for a self-signed certificate + # - the issuer of the certificate cannot be found in the SSL objects + # store, nor in the current certificate chain + my $cert = Net::SSLeay::get_peer_certificate($ssl); + my $id = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) }; + die "failed to make OCSP_CERTID: $@" if $@; + + # create OCSP_REQUEST from id(s) + # Multiple can be put into the same request, if the same OCSP responder + # is responsible for them. + my $req = Net::SSLeay::OCSP_ids2req($id); + + # determine URI of OCSP responder + my $uri = Net::SSLeay::P_X509_get_ocsp_uri($cert); + + # Send stringified OCSP_REQUEST with POST to $uri. + # We can ignore certificate verification for https, because the OCSP + # response itself is signed. + my $ua = HTTP::Tiny->new(verify_SSL => 0); + my $res = $ua->request( 'POST',$uri, { + headers => { 'Content-type' => 'application/ocsp-request' }, + content => Net::SSLeay::i2d_OCSP_REQUEST($req) + }); + my $content = $res && $res->{success} && $res->{content} + or die "query failed"; + + # Extract OCSP_RESPONSE. + # this will croak if the string is not an OCSP_RESPONSE + my $resp = eval { Net::SSLeay::d2i_OCSP_RESPONSE($content) }; + + # Check status of response. + my $status = Net::SSLeay::OCSP_response_status($resp); + if ($status != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL()) + die "OCSP response failed: ". + Net::SSLeay::OCSP_response_status_str($status); + } + + # Verify signature of response and if nonce matches request. + # This will croak if there is a nonce in the response, but it does not match + # the request. It will return false if the signature could not be verified, + # in which case details can be retrieved with Net::SSLeay::ERR_get_error. + # It will not complain if the response does not contain a nonce, which is + # usually the case with pre-signed responses. + if ( ! eval { Net::SSLeay::OCSP_response_verify($ssl,$resp,$req) }) { + die "OCSP response verification failed"; + } + + # Extract information from OCSP_RESPONSE for each of the ids. + + # If called in scalar context it will return the time (as time_t), when the + # next update is due (minimum of all successful responses inside $resp). It + # will croak on the following problems: + # - response is expired or not yet valid + # - no response for given OCSP_CERTID + # - certificate status is not good (e.g. revoked or unknown) + if ( my $nextupd = eval { Net::SSLeay::OCSP_response_results($resp,$id) }) { + warn "certificate is valid, next update in ". + ($nextupd-time())." seconds\n"; + } else { + die "certificate is not valid: $@"; + } + + # But in array context it will return detailed information about each given + # OCSP_CERTID instead croaking on errors: + # if no @ids are given it will return information about all single responses + # in the OCSP_RESPONSE + my @results = Net::SSLeay::OCSP_response_results($resp,@ids); + for my $r (@results) { + print Dumper($r); + # @results are in the same order as the @ids and contain: + # $r->[0] - OCSP_CERTID + # $r->[1] - undef if no error (certificate good) OR error message as string + # $r->[2] - hash with details: + # thisUpdate - time_t of this single response + # nextUpdate - time_t when update is expected + # statusType - integer: + # V_OCSP_CERTSTATUS_GOOD(0) + # V_OCSP_CERTSTATUS_REVOKED(1) + # V_OCSP_CERTSTATUS_UNKNOWN(2) + # revocationTime - time_t (only if revoked) + # revocationReason - integer (only if revoked) + # revocationReason_str - reason as string (only if revoked) + } + +To further speed up certificate revocation checking one can use a TLS extension +to instruct the server to staple the OCSP response: + + # set TLS extension before doing SSL_connect + Net::SSLeay::set_tlsext_status_type($ssl, + Net::SSLeay::TLSEXT_STATUSTYPE_ocsp()); + + # setup callback to verify OCSP response + my $cert_valid = undef; + Net::SSLeay::CTX_set_tlsext_status_cb($context,sub { + my ($ssl,$resp) = @_; + if (!$resp) { + # Lots of servers don't return an OCSP response. + # In this case we must check the OCSP status outside the SSL + # handshake. + warn "server did not return stapled OCSP response\n"; + return 1; + } + # verify status + my $status = Net::SSLeay::OCSP_response_status($resp); + if ($status != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL()) { + warn "OCSP response failure: $status\n"; + return 1; + } + # verify signature - we have no OCSP_REQUEST here to check nonce + if (!eval { Net::SSLeay::OCSP_response_verify($ssl,$resp) }) { + warn "OCSP response verify failed\n"; + return 1; + } + # check if the certificate is valid + # we should check here against the peer_certificate + my $cert = Net::SSLeay::get_peer_certificate(); + my $certid = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) } or do { + warn "cannot get certid from cert: $@"; + $cert_valid = -1; + return 1; + }; + + if ( $nextupd = eval { + Net::SSLeay::OCSP_response_results($resp,$certid) }) { + warn "certificate not revoked\n"; + $cert_valid = 1; + } else { + warn "certificate not valid: $@"; + $cert_valid = 0; + } + }); + + # do SSL handshake here + .... + # check if certificate revocation was checked already + if ( ! defined $cert_valid) { + # check revocation outside of SSL handshake by asking OCSP responder + ... + } elsif ( ! $cert_valid ) { + die "certificate not valid - closing SSL connection"; + } elsif ( $cert_valid<0 ) { + die "cannot verify certificate revocation - self-signed ?"; + } else { + # everything fine + ... + } + + +=head2 Using Net::SSLeay in multi-threaded applications + +B + +Net::SSLeay module implements all necessary stuff to be ready for multi-threaded +environment - it requires openssl-0.9.7 or newer. The implementation fully follows thread safety related requirements +of openssl library(see L). + +If you are about to use Net::SSLeay (or any other module based on Net::SSLeay) in multi-threaded +perl application it is recommended to follow this best-practice: + +=head3 Initialization + +Load and initialize Net::SSLeay module in the main thread: + + use threads; + use Net::SSLeay; + + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + + sub do_master_job { + #... call whatever from Net::SSLeay + } + + sub do_worker_job { + #... call whatever from Net::SSLeay + } + + #start threads + my $master = threads->new(\&do_master_job, 'param1', 'param2'); + my @workers = threads->new(\&do_worker_job, 'arg1', 'arg2') for (1..10); + + #waiting for all threads to finish + $_->join() for (threads->list); + +NOTE: Openssl's C function (which is also aliased as +C, C and C) +is not re-entrant and multiple calls can cause a crash in threaded application. +Net::SSLeay implements flags preventing repeated calls to this function, +therefore even multiple initialization via Net::SSLeay::SSLeay_add_ssl_algorithms() +should work without trouble. + +=head3 Using callbacks + +Do not use callbacks across threads (the module blocks cross-thread callback operations +and throws a warning). Always do the callback setup, callback use and callback destruction +within the same thread. + +=head3 Using openssl elements + +All openssl elements (X509, SSL_CTX, ...) can be directly passed between threads. + + use threads; + use Net::SSLeay; + + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + + sub do_job { + my $context = shift; + Net::SSLeay::CTX_set_default_passwd_cb($context, sub { "secret" }); + #... + } + + my $c = Net::SSLeay::CTX_new(); + threads->create(\&do_job, $c); + +Or: + + use threads; + use Net::SSLeay; + + my $context; #does not need to be 'shared' + + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + + sub do_job { + Net::SSLeay::CTX_set_default_passwd_cb($context, sub { "secret" }); + #... + } + + $context = Net::SSLeay::CTX_new(); + threads->create(\&do_job); + + +=head3 Using other perl modules based on Net::SSLeay + +It should be fine to use any other module based on L (like L) +in multi-threaded applications. It is generally recommended to do any global initialization +of such a module in the main thread before calling C<< threads->new(..) >> or +C<< threads->create(..) >> but it might differ module by module. + +To be safe you can load and init Net::SSLeay explicitly in the main thread: + + use Net::SSLeay; + use Other::SSLeay::Based::Module; + + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + +Or even safer: + + use Net::SSLeay; + use Other::SSLeay::Based::Module; + + BEGIN { + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + } + +=head3 Combining Net::SSLeay with other modules linked with openssl + +B + +There are many other (XS) modules linked directly to openssl library (like L). + +As it is expected that also "another" module will call C at some point +we have again a trouble with multiple openssl initialization by Net::SSLeay and "another" module. + +As you can expect Net::SSLeay is not able to avoid multiple initialization of openssl library +called by "another" module, thus you have to handle this on your own (in some cases it might +not be possible at all to avoid this). + +=head3 Threading with get_https and friends + +The convenience functions get_https, post_https etc all initialize the SSL library by calling +Net::SSLeay::initialize which does the conventional library initialization: + + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); + +Net::SSLeay::initialize initializes the SSL library at most once. +You can override the Net::SSLeay::initialize function if you desire +some other type of initialization behaviour by get_https and friends. +You can call Net::SSLeay::initialize from your own code if you desire this conventional library initialization. + +=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); + +=over + +=item * randomize + +seeds the openssl PRNG with C (see the top of C +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 so it is not needed with them. See also caveats. + +=item * 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 server certificates or client certificates. + +=item * dump_peer_certificate + +allows you to get a plaintext description of the +certificate the peer (usually the server) presented to us. + +=item * ssl_read_all + +see ssl_write_all (below) + +=item * ssl_write_all + +C and C 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 can be +a reference. This is helpful to avoid unnecessary copying when writing +something big, e.g: + + $data = 'A' x 1000000000; + Net::SSLeay::ssl_write_all($ssl, \$data) or die "ssl write failed"; + +=item * ssl_read_CRLF + +uses C to read in a line terminated with a +carriage return followed by a linefeed (CRLF). The CRLF is included in +the returned scalar. + +=item * ssl_read_until + +uses C 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. + +=item * ssl_write_CRLF + +writes C<$message> and appends CRLF to the SSL output stream. + +=back + +=head2 Initialization + +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(); + +=head2 Error handling functions + +I can not emphasize the need to check for error enough. Use these +functions even in the most simple programs, they will reduce debugging +time greatly. Do not ask questions on the mailing list without having +first sprinkled these in your code. + +=over + +=item * die_now + +=item * die_if_ssl_error + +C and C are used to conveniently print the SSLeay error +stack when something goes wrong: + + Net::SSLeay::connect($ssl) or die_now("Failed SSL connect ($!)"); + + + Net::SSLeay::write($ssl, "foo") or die_if_ssl_error("SSL write ($!)"); + +=item * print_errs + +You can also use C 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 into your main name space. + +=back + +=head2 Sockets + +Perl uses file handles for all I/O. While SSLeay has a quite flexible BIO +mechanism and perl has an evolved PerlIO mechanism, this module still +sticks to using file descriptors. Thus to attach SSLeay to a socket you +should use C 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 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 the socket selected for reading (just keep on +selecting and trying to read). C is no different from the +C language OpenSSL in this respect. + +=head2 Callbacks + +You can establish a per-context verify callback function something like this: + + sub verify { + my ($ok, $x509_store_ctx) = @_; + print "Verifying certificate...\n"; + ... + return $ok; + } + +It is used like this: + + Net::SSLeay::set_verify ($ssl, Net::SSLeay::VERIFY_PEER, \&verify); + +Per-context callbacks for decrypting private keys are implemented. + + 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); + +If Hello Extensions are supported by your OpenSSL, +a session secret callback can be set up to be called when a session secret is set +by openssl. + +Establish it like this: + Net::SSLeay::set_session_secret_cb($ssl, \&session_secret_cb, $somedata); + +It will be called like this: + + sub session_secret_cb + { + my ($secret, \@cipherlist, \$preferredcipher, $somedata) = @_; + } + + +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 required to reset these callbacks to undef immediately after use to prevent +memory leaks, thread safety problems and crashes on exit that +can occur if different threads set different callbacks. + +If you want to use callback stuff, see examples/callback.pl! It's the +only one I am able to make work reliably. + +=head2 Low level API + +In addition to the high level functions outlined above, this module +contains straight-forward access to CRYPTO and SSL parts of OpenSSL C API. + +See the C<*.h> headers from OpenSSL C distribution for a list of low level +SSLeay functions to call (check SSLeay.xs to see if some function has been +implemented). The module strips the initial C<"SSL_"> off of the SSLeay names. +Generally you should use C in its place. + +Note that some functions are prefixed with C<"P_"> - these are very close to +the original API however contain some kind of a wrapper making its interface +more perl friendly. + +For example: + +In C: + + #include + + 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 with C you should use the full +function name, e.g.: + + $err = Net::SSLeay::ERR_get_error; + +The 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 + +=head3 Low level API: Version related functions + +=over + +=item * SSLeay + +B not available in Net-SSLeay-1.42 and before + +Gives version number (numeric) of underlaying openssl library. + + my $ver_number = Net::SSLeay::SSLeay(); + # returns: the number identifying the openssl release + # + # 0x00903100 => openssl-0.9.3 + # 0x00904100 => openssl-0.9.4 + # 0x00905100 => openssl-0.9.5 + # 0x0090600f => openssl-0.9.6 + # 0x0090601f => openssl-0.9.6a + # 0x0090602f => openssl-0.9.6b + # ... + # 0x009060df => openssl-0.9.6m + # 0x0090700f => openssl-0.9.7 + # 0x0090701f => openssl-0.9.7a + # 0x0090702f => openssl-0.9.7b + # ... + # 0x009070df => openssl-0.9.7m + # 0x0090800f => openssl-0.9.8 + # 0x0090801f => openssl-0.9.8a + # 0x0090802f => openssl-0.9.8b + # ... + # 0x0090814f => openssl-0.9.8t + # 0x1000000f => openssl-1.0.0 + # 0x1000004f => openssl-1.0.0d + # 0x1000007f => openssl-1.0.0g + +You can use it like this: + + if (Net::SSLeay::SSLeay() < 0x0090800f) { + die "you need openssl-0.9.8 or higher"; + } + +=item * SSLeay_version + +B not available in Net-SSLeay-1.42 and before + +Gives version number (string) of underlaying openssl library. + + my $ver_string = Net::SSLeay::SSLeay_version($type); + # $type + # SSLEAY_VERSION - e.g. 'OpenSSL 1.0.0d 8 Feb 2011' + # SSLEAY_CFLAGS - e.g. 'compiler: gcc -D_WINDLL -DOPENSSL_USE_APPLINK .....' + # SSLEAY_BUILT_ON - e.g. 'built on: Fri May 6 00:00:46 GMT 2011' + # SSLEAY_PLATFORM - e.g. 'platform: mingw' + # SSLEAY_DIR - e.g. 'OPENSSLDIR: "z:/...."' + # + # returns: string + + Net::SSLeay::SSLeay_version(); + #is equivalent to + Net::SSLeay::SSLeay_version(SSLEAY_VERSION); + +Check openssl doc L + +=item * OpenSSL_version_num + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 + +Gives version number (numeric) of underlaying openssl library. See L for interpreting the result. + + my $ver_number = Net::SSLeay::OpenSSL_version_num(); + # returns: the number identifying the openssl release + +=item * OpenSSL_version + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 + +Gives version number (string) of underlaying openssl library. + + my $ver_string = Net::SSLeay::OpenSSL_version($t); + # $t + # OPENSSL_VERSION - e.g. 'OpenSSL 1.1.0g 2 Nov 2017' + # OPENSSL_CFLAGS - e.g. 'compiler: cc -DDSO_DLFCN -DHAVE_DLFCN_H .....' + # OPENSSL_BUILT_ON - e.g. 'built on: reproducible build, date unspecified' + # OPENSSL_PLATFORM - e.g. 'platform: darwin64-x86_64-cc' + # OPENSSL_DIR - e.g. 'OPENSSLDIR: "/opt/openssl-1.1.0g"' + # OPENSSL_ENGINES_DIR - e.g. 'ENGINESDIR: "/opt/openssl-1.1.0g/lib/engines-1.1"' + # + # returns: string + + Net::SSLeay::OpenSSL_version(); + #is equivalent to + Net::SSLeay::OpenSSL_version(OPENSSL_VERSION); + +Check openssl doc L + +=back + +=head3 Low level API: Initialization related functions + +=over + +=item * library_init + +Initialize SSL library by registering algorithms. + + my $rv = Net::SSLeay::library_init(); + +Check openssl doc L + +While the original function from OpenSSL always returns 1, Net::SSLeay adds a +wrapper around it to make sure that the OpenSSL function is only called once. +Thus the function will return 1 if initialization was done and 0 if not, i.e. if +initialization was done already before. + +=item * add_ssl_algorithms + +The alias for L + + Net::SSLeay::add_ssl_algorithms(); + +=item * OpenSSL_add_ssl_algorithms + +The alias for L + + Net::SSLeay::OpenSSL_add_ssl_algorithms(); + +=item * SSLeay_add_ssl_algorithms + +The alias for L + + Net::SSLeay::SSLeay_add_ssl_algorithms(); + +=item * load_error_strings + +Registers the error strings for all libcrypto + libssl related functions. + + Net::SSLeay::load_error_strings(); + # + # returns: no return value + +Check openssl doc L + +=item * ERR_load_crypto_strings + +Registers the error strings for all libcrypto functions. No need to call this function if you have already called L. + + Net::SSLeay::ERR_load_crypto_strings(); + # + # returns: no return value + +Check openssl doc L + +=item * ERR_load_RAND_strings + +Registers the error strings for RAND related functions. No need to call this function if you have already called L. + + Net::SSLeay::ERR_load_RAND_strings(); + # + # returns: no return value + +=item * ERR_load_SSL_strings + +Registers the error strings for SSL related functions. No need to call this function if you have already called L. + + Net::SSLeay::ERR_load_SSL_strings(); + # + # returns: no return value + +=item * OpenSSL_add_all_algorithms + +B not available in Net-SSLeay-1.45 and before + +Add algorithms to internal table. + + Net::SSLeay::OpenSSL_add_all_algorithms(); + # + # returns: no return value + +Check openssl doc L + +=item * OPENSSL_add_all_algorithms_conf + +B not available in Net-SSLeay-1.45 and before + +Similar to L - will ALWAYS load the config file + + Net::SSLeay::OPENSSL_add_all_algorithms_conf(); + # + # returns: no return value + +=item * OPENSSL_add_all_algorithms_noconf + +B not available in Net-SSLeay-1.45 and before + +Similar to L - will NEVER load the config file + + Net::SSLeay::OPENSSL_add_all_algorithms_noconf(); + # + # returns: no return value + +=back + +=head3 Low level API: ERR_* and SSL_alert_* related functions + +B Please note that SSL_alert_* function have "SSL_" part stripped from their names. + +=over + +=item * ERR_clear_error + +Clear the error queue. + + Net::SSLeay::ERR_clear_error(); + # + # returns: no return value + +Check openssl doc L + +=item * ERR_error_string + +Generates a human-readable string representing the error code $error. + + my $rv = Net::SSLeay::ERR_error_string($error); + # $error - (unsigned integer) error code + # + # returns: string + +Check openssl doc L + +=item * ERR_get_error + +Returns the earliest error code from the thread's error queue and removes the entry. +This function can be called repeatedly until there are no more error codes to return. + + my $rv = Net::SSLeay::ERR_get_error(); + # + # returns: (unsigned integer) error code + +Check openssl doc L + +=item * ERR_peek_error + +Returns the earliest error code from the thread's error queue without modifying it. + + my $rv = Net::SSLeay::ERR_peek_error(); + # + # returns: (unsigned integer) error code + +Check openssl doc L + +=item * ERR_put_error + +Adds an error code to the thread's error queue. It signals that the error of $reason +code reason occurred in function $func of library $lib, in line number $line of $file. + + Net::SSLeay::ERR_put_error($lib, $func, $reason, $file, $line); + # $lib - (integer) library id (check openssl/err.h for constants e.g. ERR_LIB_SSL) + # $func - (integer) function id (check openssl/ssl.h for constants e.g. SSL_F_SSL23_READ) + # $reason - (integer) reason id (check openssl/ssl.h for constants e.g. SSL_R_SSL_HANDSHAKE_FAILURE) + # $file - (string) file name + # $line - (integer) line number in $file + # + # returns: no return value + +Check openssl doc L +and L + +=item * alert_desc_string + +Returns a two letter string as a short form describing the reason of the alert specified by value. + + my $rv = Net::SSLeay::alert_desc_string($value); + # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) + # + # returns: description string (2 letters) + +Check openssl doc L + +=item * alert_desc_string_long + +Returns a string describing the reason of the alert specified by value. + + my $rv = Net::SSLeay::alert_desc_string_long($value); + # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) + # + # returns: description string + +Check openssl doc L + +=item * alert_type_string + +Returns a one letter string indicating the type of the alert specified by value. + + my $rv = Net::SSLeay::alert_type_string($value); + # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) + # + # returns: string (1 letter) + +Check openssl doc L + +=item * alert_type_string_long + +Returns a string indicating the type of the alert specified by value. + + my $rv = Net::SSLeay::alert_type_string_long($value); + # $value - (integer) allert id (check openssl/ssl.h for SSL3_AD_* and TLS1_AD_* constants) + # + # returns: string + +Check openssl doc L + +=back + +=head3 Low level API: SSL_METHOD_* related functions + +=over + +=item * SSLv23_method, SSLv23_server_method and SSLv23_client_method + +B not available in Net-SSLeay-1.82 and before. + +Returns SSL_METHOD structure corresponding to general-purpose version-flexible TLS method, the return value can be later used as a param of L. + +B Consider using TLS_method, TLS_server_method or TLS_client_method with new code. + + my $rv = Net::SSLeay::SSLv2_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +=item * SSLv2_method + +Returns SSL_METHOD structure corresponding to SSLv2 method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. + + my $rv = Net::SSLeay::SSLv2_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +=item * SSLv3_method + +Returns SSL_METHOD structure corresponding to SSLv3 method, the return value can be later used as a param of L. + + my $rv = Net::SSLeay::SSLv3_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +Check openssl doc L + +=item * TLSv1_method, TLSv1_server_method and TLSv1_client_method + +B Server and client methods not available in Net-SSLeay-1.82 and before. + +Returns SSL_METHOD structure corresponding to TLSv1 method, the return value can be later used as a param of L. + + my $rv = Net::SSLeay::TLSv1_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +Check openssl doc L + +=item * TLSv1_1_method, TLSv1_1_server_method and TLSv1_1_client_method + +B Server and client methods not available in Net-SSLeay-1.82 and before. + +Returns SSL_METHOD structure corresponding to TLSv1_1 method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. + + my $rv = Net::SSLeay::TLSv1_1_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +Check openssl doc L + +=item * TLSv1_2_method, TLSv1_2_server_method and TLSv1_2_client_method + +B Server and client methods not available in Net-SSLeay-1.82 and before. + +Returns SSL_METHOD structure corresponding to TLSv1_2 method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. + + my $rv = Net::SSLeay::TLSv1_2_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +Check openssl doc L + +=item * TLS_method, TLS_server_method and TLS_client_method + +B Not available in Net-SSLeay-1.82 and before. + +Returns SSL_METHOD structure corresponding to general-purpose version-flexible TLS method, the return value can be later used as a param of L. Only available where supported by the underlying openssl. + + my $rv = Net::SSLeay::TLS_method(); + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +Check openssl doc L + +=back + +=head3 Low level API: ENGINE_* related functions + +=over + +=item * ENGINE_load_builtin_engines + +B Requires an OpenSSL build with dynamic engine loading support. + +Load all bundled ENGINEs into memory and make them visible. + + Net::SSLeay::ENGINE_load_builtin_engines(); + # + # returns: no return value + +Check openssl doc L + +=item * ENGINE_register_all_complete + +B Requires an OpenSSL build with dynamic engine loading support. + +Register all loaded ENGINEs for every algorithm they collectively implement. + + Net::SSLeay::ENGINE_register_all_complete(); + # + # returns: no return value + +Check openssl doc L + +=item * ENGINE_set_default + +B Requires an OpenSSL build with dynamic engine loading support. + +Set default engine to $e + set its flags to $flags. + + my $rv = Net::SSLeay::ENGINE_set_default($e, $flags); + # $e - value corresponding to openssl's ENGINE structure + # $flags - (integer) engine flags + # flags value can be made by bitwise "OR"ing: + # 0x0001 - ENGINE_METHOD_RSA + # 0x0002 - ENGINE_METHOD_DSA + # 0x0004 - ENGINE_METHOD_DH + # 0x0008 - ENGINE_METHOD_RAND + # 0x0010 - ENGINE_METHOD_ECDH + # 0x0020 - ENGINE_METHOD_ECDSA + # 0x0040 - ENGINE_METHOD_CIPHERS + # 0x0080 - ENGINE_METHOD_DIGESTS + # 0x0100 - ENGINE_METHOD_STORE + # 0x0200 - ENGINE_METHOD_PKEY_METHS + # 0x0400 - ENGINE_METHOD_PKEY_ASN1_METHS + # Obvious all-or-nothing cases: + # 0xFFFF - ENGINE_METHOD_ALL + # 0x0000 - ENGINE_METHOD_NONE + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * ENGINE_by_id + +Get ENGINE by its identification $id. + +B Requires an OpenSSL build with dynamic engine loading support. + + my $rv = Net::SSLeay::ENGINE_by_id($id); + # $id - (string) engine identification e.g. "dynamic" + # + # returns: value corresponding to openssl's ENGINE structure (0 on failure) + +Check openssl doc L + +=back + +=head3 Low level API: EVP_PKEY_* related functions + +=over + +=item * EVP_PKEY_copy_parameters + +Copies the parameters from key $from to key $to. + + my $rv = Net::SSLeay::EVP_PKEY_copy_parameters($to, $from); + # $to - value corresponding to openssl's EVP_PKEY structure + # $from - value corresponding to openssl's EVP_PKEY structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * EVP_PKEY_new + +B not available in Net-SSLeay-1.45 and before + +Creates a new EVP_PKEY structure. + + my $rv = Net::SSLeay::EVP_PKEY_new(); + # + # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) + +Check openssl doc L + +=item * EVP_PKEY_free + +B not available in Net-SSLeay-1.45 and before + +Free an allocated EVP_PKEY structure. + + Net::SSLeay::EVP_PKEY_free($pkey); + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: no return value + +Check openssl doc L + +=item * EVP_PKEY_assign_RSA + +B not available in Net-SSLeay-1.45 and before + +Set the key referenced by $pkey to $key + +B No reference counter will be increased, i.e. $key will be freed if +$pkey is freed. + + my $rv = Net::SSLeay::EVP_PKEY_assign_RSA($pkey, $key); + # $pkey - value corresponding to openssl's EVP_PKEY structure + # $key - value corresponding to openssl's RSA structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * EVP_PKEY_assign_EC_KEY + +B not available in Net-SSLeay-1.74 and before + +Set the key referenced by $pkey to $key + +B No reference counter will be increased, i.e. $key will be freed if +$pkey is freed. + + my $rv = Net::SSLeay::EVP_PKEY_assign_EC_KEY($pkey, $key); + # $pkey - value corresponding to openssl's EVP_PKEY structure + # $key - value corresponding to openssl's EC_KEY structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * EVP_PKEY_bits + +B not available in Net-SSLeay-1.45 and before + +Returns the size of the key $pkey in bits. + + my $rv = Net::SSLeay::EVP_PKEY_bits($pkey); + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: size in bits + +=item * EVP_PKEY_size + +B not available in Net-SSLeay-1.45 and before + +Returns the maximum size of a signature in bytes. The actual signature may be smaller. + + my $rv = Net::SSLeay::EVP_PKEY_size($pkey); + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: the maximum size in bytes + +Check openssl doc L + +=item * EVP_PKEY_id + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.0 + +Returns $pkey type (integer value of corresponding NID). + + my $rv = Net::SSLeay::EVP_PKEY_id($pkey); + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: (integer) key type + +Example: + + my $pubkey = Net::SSLeay::X509_get_pubkey($x509); + my $type = Net::SSLeay::EVP_PKEY_id($pubkey); + print Net::SSLeay::OBJ_nid2sn($type); #prints e.g. 'rsaEncryption' + +=back + +=head3 Low level API: PEM_* related functions + +Check openssl doc L + +=over + +=item * PEM_read_bio_X509 + +B not available in Net-SSLeay-1.45 and before + +Loads PEM formatted X509 certificate via given BIO structure. + + my $rv = Net::SSLeay::PEM_read_bio_X509($bio); + # $bio - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's X509 structure (0 on failure) + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); + my $x509 = Net::SSLeay::PEM_read_bio_X509($bio); + Net::SSLeay::BIO_free($bio); + +=item * PEM_read_bio_X509_REQ + +B not available in Net-SSLeay-1.45 and before + +Loads PEM formatted X509_REQ object via given BIO structure. + + my $rv = Net::SSLeay::PEM_read_bio_X509_REQ($bio, $x=NULL, $cb=NULL, $u=NULL); + # $bio - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's X509_REQ structure (0 on failure) + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); + my $x509_req = Net::SSLeay::PEM_read_bio_X509_REQ($bio); + Net::SSLeay::BIO_free($bio); + +=item * PEM_read_bio_DHparams + +Reads DH structure from BIO. + + my $rv = Net::SSLeay::PEM_read_bio_DHparams($bio); + # $bio - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's DH structure (0 on failure) + +=item * PEM_read_bio_X509_CRL + +Reads X509_CRL structure from BIO. + + my $rv = Net::SSLeay::PEM_read_bio_X509_CRL($bio); + # $bio - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's X509_CRL structure (0 on failure) + +=item * PEM_read_bio_PrivateKey + +B not available in Net-SSLeay-1.45 and before + +Loads PEM formatted private key via given BIO structure. + + my $rv = Net::SSLeay::PEM_read_bio_PrivateKey($bio, $cb, $data); + # $bio - value corresponding to openssl's BIO structure + # $cb - reference to perl callback function + # $data - data that will be passed to callback function (see examples below) + # + # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); + my $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio); #ask for password if needed + Net::SSLeay::BIO_free($bio); + +To use password you have the following options: + + $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, \&callback_func); # use callback func for getting password + $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, \&callback_func, $data); # use callback_func + pass $data to callback_func + $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, undef, "secret"); # use password "secret" + $privkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio, undef, ""); # use empty password + +Callback function signature: + + sub callback_func { + my ($max_passwd_size, $rwflag, $data) = @_; + # $max_passwd_size - maximum size of returned password (longer values will be discarded) + # $rwflag - indicates whether we are loading (0) or storing (1) - for PEM_read_bio_PrivateKey always 0 + # $data - the data passed to PEM_read_bio_PrivateKey as 3rd parameter + + return "secret"; + } + +=item * PEM_X509_INFO_read_bio + +Reads a BIO containing a PEM formatted file into a STACK_OF(X509_INFO) structure. + + my $rv = Net::SSLeay::PEM_X509_INFO_read_bio($bio); + # $bio - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's STACK_OF(X509_INFO) structure. + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'r'); + my $sk_x509_info = Net::SSLeay::PEM_X509_INFO_read_bio($bio); + Net::SSLeay::BIO_free($bio); + +=item * PEM_get_string_X509 + +B Does not exactly correspond to any low level API function + +Converts/exports X509 certificate to string (PEM format). + + Net::SSLeay::PEM_get_string_X509($x509); + # $x509 - value corresponding to openssl's X509 structure + # + # returns: string with $x509 in PEM format + +=item * PEM_get_string_PrivateKey + +B not available in Net-SSLeay-1.45 and before + +Converts public key $pk into PEM formatted string (optionally protected with password). + + my $rv = Net::SSLeay::PEM_get_string_PrivateKey($pk, $passwd, $enc_alg); + # $pk - value corresponding to openssl's EVP_PKEY structure + # $passwd - [optional] (string) password to use for key encryption + # $enc_alg - [optional] algorithm to use for key encryption (default: DES_CBC) - value corresponding to openssl's EVP_CIPHER structure + # + # returns: PEM formatted string + +Examples: + + $pem_privkey = Net::SSLeay::PEM_get_string_PrivateKey($pk); + $pem_privkey = Net::SSLeay::PEM_get_string_PrivateKey($pk, "secret"); + $pem_privkey = Net::SSLeay::PEM_get_string_PrivateKey($pk, "secret", Net::SSLeay::EVP_get_cipherbyname("DES-EDE3-CBC")); + +=item * PEM_get_string_X509_CRL + +B not available in Net-SSLeay-1.45 and before + +Converts X509_CRL object $x509_crl into PEM formatted string. + + Net::SSLeay::PEM_get_string_X509_CRL($x509_crl); + # $x509_crl - value corresponding to openssl's X509_CRL structure + # + # returns: no return value + +=item * PEM_get_string_X509_REQ + +B not available in Net-SSLeay-1.45 and before + +Converts X509_REQ object $x509_crl into PEM formatted string. + + Net::SSLeay::PEM_get_string_X509_REQ($x509_req); + # $x509_req - value corresponding to openssl's X509_REQ structure + # + # returns: no return value + +=back + +=head3 Low level API: d2i_* (DER format) related functions + +=over + +=item * d2i_X509_bio + +B not available in Net-SSLeay-1.45 and before + +Loads DER formatted X509 certificate via given BIO structure. + + my $rv = Net::SSLeay::d2i_X509_bio($bp); + # $bp - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's X509 structure (0 on failure) + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'); + my $x509 = Net::SSLeay::d2i_X509_bio($bio); + Net::SSLeay::BIO_free($bio); + +Check openssl doc L + +=item * d2i_X509_CRL_bio + +B not available in Net-SSLeay-1.45 and before + +Loads DER formatted X509_CRL object via given BIO structure. + + my $rv = Net::SSLeay::d2i_X509_CRL_bio($bp); + # $bp - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's X509_CRL structure (0 on failure) + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'); + my $x509_crl = Net::SSLeay::d2i_X509_CRL_bio($bio); + Net::SSLeay::BIO_free($bio); + +=item * d2i_X509_REQ_bio + +B not available in Net-SSLeay-1.45 and before + +Loads DER formatted X509_REQ object via given BIO structure. + + my $rv = Net::SSLeay::d2i_X509_REQ_bio($bp); + # $bp - value corresponding to openssl's BIO structure + # + # returns: value corresponding to openssl's X509_REQ structure (0 on failure) + +Example: + + my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'); + my $x509_req = Net::SSLeay::d2i_X509_REQ_bio($bio); + Net::SSLeay::BIO_free($bio); + +=back + +=head3 Low level API: PKCS12 related functions + +=over + +=item * P_PKCS12_load_file + +B not available in Net-SSLeay-1.45 and before + +Loads X509 certificate + private key + certificates of CA chain (if present in PKCS12 file). + + my ($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename, $load_chain, $password); + # $filename - name of PKCS12 file + # $load_chain - [optional] whether load (1) or not(0) CA chain (default: 0) + # $password - [optional] password for private key + # + # returns: triplet ($privkey, $cert, @cachain) + # $privkey - value corresponding to openssl's EVP_PKEY structure + # $cert - value corresponding to openssl's X509 structure + # @cachain - array of values corresponding to openssl's X509 structure (empty if no CA chain in PKCS12) + +B after you do the job you need to call X509_free() on $privkey + all members +of @cachain and EVP_PKEY_free() on $privkey. + +Examples: + + my ($privkey, $cert) = Net::SSLeay::P_PKCS12_load_file($filename); + #or + my ($privkey, $cert) = Net::SSLeay::P_PKCS12_load_file($filename, 0, $password); + #or + my ($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename, 1); + #or + my ($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename, 1, $password); + + #BEWARE: THIS IS WRONG - MEMORY LEAKS! (you cannot free @cachain items) + my ($privkey, $cert) = Net::SSLeay::P_PKCS12_load_file($filename, 1, $password); + +B With some combinations of Windows, perl, compiler and compiler options, you +may see a runtime error "no OPENSSL_Applink", when calling +Net::SSLeay::P_PKCS12_load_file. See README.Win32 for more details. + +=back + +=head3 Low level API: SESSION_* related functions + +=over + +=item * d2i_SSL_SESSION + +B does not work in Net-SSLeay-1.85 and before + +Transforms the binary ASN1 representation string of an SSL/TLS session into an +SSL_SESSION object. + + my $ses = Net::SSLeay::d2i_SSL_SESSION($data); + # $data - the session as ASN1 representation string + # + # returns: $ses - the new SSL_SESSION + +Check openssl doc L + +=item * i2d_SSL_SESSION + +B does not work in Net-SSLeay-1.85 and before + +Transforms the SSL_SESSION object in into the ASN1 representation and returns +it as string. + + my $data = Net::SSLeay::i2d_SSL_SESSION($ses); + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: $data - session as string + +Check openssl doc L + +=item * SESSION_new + +Creates a new SSL_SESSION structure. + + my $rv = Net::SSLeay::SESSION_new(); + # + # returns: value corresponding to openssl's SSL_SESSION structure (0 on failure) + +=item * SESSION_free + +Free an allocated SSL_SESSION structure. + + Net::SSLeay::SESSION_free($ses); + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: no return value + +Check openssl doc L + +=item * SESSION_up_ref + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0 or LibreSSL 2.7.0 + +Increases the reference counter on a SSL_SESSION structure. + + Net::SSLeay::SESSION_up_ref($ses); + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: 1 on success else 0 + +Check openssl doc +L + +=item * SESSION_dup + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Duplicates a SSL_SESSION structure. + + Net::SSLeay::SESSION_dup($ses); + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: the duplicated session + +Check openssl doc +L + +=item * SESSION_is_resumable + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Determine whether an SSL_SESSION object can be used for resumption. + + Net::SSLeay::SESSION_is_resumable($ses); + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: (integer) 1 if it can or 0 if not + +Check openssl doc L + +=item * SESSION_cmp + +Compare two SSL_SESSION structures. + + my $rv = Net::SSLeay::SESSION_cmp($sesa, $sesb); + # $sesa - value corresponding to openssl's SSL_SESSION structure + # $sesb - value corresponding to openssl's SSL_SESSION structure + # + # returns: 0 if the two structures are the same + +B Not available in openssl 1.0 or later + +=item * SESSION_get_app_data + +Can be used to get application defined value/data. + + my $rv = Net::SSLeay::SESSION_get_app_data($ses); + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: string/buffer/pointer ??? + +=item * SESSION_set_app_data + +Can be used to set some application defined value/data. + + my $rv = Net::SSLeay::SESSION_set_app_data($s, $a); + # $s - value corresponding to openssl's SSL_SESSION structure + # $a - (string/buffer/pointer ???) data + # + # returns: ??? + +=item * SESSION_get_ex_data + +Is used to retrieve the information for $idx from session $ses. + + my $rv = Net::SSLeay::SESSION_get_ex_data($ses, $idx); + # $ses - value corresponding to openssl's SSL_SESSION structure + # $idx - (integer) index for application specific data + # + # returns: pointer to ??? + +Check openssl doc L + +=item * SESSION_set_ex_data + +Is used to store application data at arg for idx into the session object. + + my $rv = Net::SSLeay::SESSION_set_ex_data($ss, $idx, $data); + # $ss - value corresponding to openssl's SSL_SESSION structure + # $idx - (integer) ??? + # $data - (pointer) ??? + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * SESSION_get_ex_new_index + +Is used to register a new index for application specific data. + + my $rv = Net::SSLeay::SESSION_get_ex_new_index($argl, $argp, $new_func, $dup_func, $free_func); + # $argl - (long) ??? + # $argp - (pointer) ??? + # $new_func - function pointer ??? (CRYPTO_EX_new *) + # $dup_func - function pointer ??? (CRYPTO_EX_dup *) + # $free_func - function pointer ??? (CRYPTO_EX_free *) + # + # returns: (integer) ??? + +Check openssl doc L + +=item * SESSION_get_master_key + +B Does not exactly correspond to any low level API function + +Returns 'master_key' value from SSL_SESSION structure $s + + Net::SSLeay::SESSION_get_master_key($s); + # $s - value corresponding to openssl's SSL_SESSION structure + # + # returns: master key (binary data) + +=item * SESSION_set_master_key + +Sets 'master_key' value for SSL_SESSION structure $s + + Net::SSLeay::SESSION_set_master_key($s, $key); + # $s - value corresponding to openssl's SSL_SESSION structure + # $key - master key (binary data) + # + # returns: no return value + +Not available with OpenSSL 1.1 and later. +Code that previously used + SESSION_set_master_key must now set $secret in the session_secret + callback set with SSL_set_session_secret_cb. + +=item * SESSION_get_time + +Returns the time at which the session s was established. +The time is given in seconds since 1.1.1970. + + my $rv = Net::SSLeay::SESSION_get_time($s); + # $s - value corresponding to openssl's SSL_SESSION structure + # + # returns: timestamp (seconds since 1.1.1970) + +Check openssl doc L + +=item * get_time + +Technically the same functionality as L. + + my $rv = Net::SSLeay::get_time($s); + +=item * SESSION_get_timeout + +Returns the timeout value set for session $s in seconds. + + my $rv = Net::SSLeay::SESSION_get_timeout($s); + # $s - value corresponding to openssl's SSL_SESSION structure + # + # returns: timeout (in seconds) + +Check openssl doc L + +=item * get_timeout + +Technically the same functionality as L. + + my $rv = Net::SSLeay::get_timeout($s); + +=item * SESSION_print + +B Does not exactly correspond to any low level API function + +Prints session details (e.g. protocol version, cipher, session-id ...) to BIO. + + my $rv = Net::SSLeay::SESSION_print($fp, $ses); + # $fp - value corresponding to openssl's BIO structure + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: 1 on success, 0 on failure + +You have to use necessary BIO functions like this: + + # let us have $ssl corresponding to openssl's SSL structure + my $ses = Net::SSLeay::get_session($ssl); + my $bio = Net::SSLeay::BIO_new(&Net::SSLeay::BIO_s_mem); + Net::SSLeay::SESSION_print($bio, $ses); + print Net::SSLeay::BIO_read($bio); + +=item * SESSION_print_fp + +Prints session details (e.g. protocol version, cipher, session-id ...) to file handle. + + my $rv = Net::SSLeay::SESSION_print_fp($fp, $ses); + # $fp - perl file handle + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: 1 on success, 0 on failure + +Example: + + # let us have $ssl corresponding to openssl's SSL structure + my $ses = Net::SSLeay::get_session($ssl); + open my $fh, ">", "output.txt"; + Net::SSLeay::SESSION_print_fp($fh,$ses); + +=item * SESSION_set_time + +Replaces the creation time of the session s with the chosen value $t (seconds since 1.1.1970). + + my $rv = Net::SSLeay::SESSION_set_time($ses, $t); + # $ses - value corresponding to openssl's SSL_SESSION structure + # $t - time value + # + # returns: 1 on success + +Check openssl doc L + +=item * set_time + +Technically the same functionality as L. + + my $rv = Net::SSLeay::set_time($ses, $t); + +=item * SESSION_set_timeout + +Sets the timeout value for session s in seconds to $t. + + my $rv = Net::SSLeay::SESSION_set_timeout($s, $t); + # $s - value corresponding to openssl's SSL_SESSION structure + # $t - timeout (in seconds) + # + # returns: 1 on success + +Check openssl doc L + +=item * set_timeout + +Technically the same functionality as L. + + my $rv = Net::SSLeay::set_timeout($ses, $t); + +=back + +=head3 Low level API: SSL_CTX_* related functions + +B Please note that the function described in this chapter have "SSL_" part stripped from their original openssl names. + +=over + +=item * CTX_add_client_CA + +Adds the CA name extracted from $cacert to the list of CAs sent to the client when requesting a client certificate for $ctx. + + my $rv = Net::SSLeay::CTX_add_client_CA($ctx, $cacert); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $cacert - value corresponding to openssl's X509 structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_add_extra_chain_cert + +Adds the certificate $x509 to the certificate chain presented together with the certificate. Several certificates can be added one after the other. + + my $rv = Net::SSLeay::CTX_add_extra_chain_cert($ctx, $x509); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $x509 - value corresponding to openssl's X509 structure + # + # returns: 1 on success, check out the error stack to find out the reason for failure otherwise + +Check openssl doc L + +=item * CTX_add_session + +Adds the session $ses to the context $ctx. + + my $rv = Net::SSLeay::CTX_add_session($ctx, $ses); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_callback_ctrl + +??? (more info needed) + + my $rv = Net::SSLeay::CTX_callback_ctrl($ctx, $cmd, $fp); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $cmd - (integer) command id + # $fp - (function pointer) ??? + # + # returns: ??? + +Check openssl doc L + +=item * CTX_check_private_key + +Checks the consistency of a private key with the corresponding certificate loaded into $ctx. + + my $rv = Net::SSLeay::CTX_check_private_key($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_ctrl + +Internal handling function for SSL_CTX objects. + +B openssl doc says: This function should never be called directly! + + my $rv = Net::SSLeay::CTX_ctrl($ctx, $cmd, $larg, $parg); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $cmd - (integer) command id + # $larg - (integer) long ??? + # $parg - (string/pointer) ??? + # + # returns: (long) result of given command ??? + + #valid $cmd values + 1 - SSL_CTRL_NEED_TMP_RSA + 2 - SSL_CTRL_SET_TMP_RSA + 3 - SSL_CTRL_SET_TMP_DH + 4 - SSL_CTRL_SET_TMP_ECDH + 5 - SSL_CTRL_SET_TMP_RSA_CB + 6 - SSL_CTRL_SET_TMP_DH_CB + 7 - SSL_CTRL_SET_TMP_ECDH_CB + 8 - SSL_CTRL_GET_SESSION_REUSED + 9 - SSL_CTRL_GET_CLIENT_CERT_REQUEST + 10 - SSL_CTRL_GET_NUM_RENEGOTIATIONS + 11 - SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS + 12 - SSL_CTRL_GET_TOTAL_RENEGOTIATIONS + 13 - SSL_CTRL_GET_FLAGS + 14 - SSL_CTRL_EXTRA_CHAIN_CERT + 15 - SSL_CTRL_SET_MSG_CALLBACK + 16 - SSL_CTRL_SET_MSG_CALLBACK_ARG + 17 - SSL_CTRL_SET_MTU + 20 - SSL_CTRL_SESS_NUMBER + 21 - SSL_CTRL_SESS_CONNECT + 22 - SSL_CTRL_SESS_CONNECT_GOOD + 23 - SSL_CTRL_SESS_CONNECT_RENEGOTIATE + 24 - SSL_CTRL_SESS_ACCEPT + 25 - SSL_CTRL_SESS_ACCEPT_GOOD + 26 - SSL_CTRL_SESS_ACCEPT_RENEGOTIATE + 27 - SSL_CTRL_SESS_HIT + 28 - SSL_CTRL_SESS_CB_HIT + 29 - SSL_CTRL_SESS_MISSES + 30 - SSL_CTRL_SESS_TIMEOUTS + 31 - SSL_CTRL_SESS_CACHE_FULL + 32 - SSL_CTRL_OPTIONS + 33 - SSL_CTRL_MODE + 40 - SSL_CTRL_GET_READ_AHEAD + 41 - SSL_CTRL_SET_READ_AHEAD + 42 - SSL_CTRL_SET_SESS_CACHE_SIZE + 43 - SSL_CTRL_GET_SESS_CACHE_SIZE + 44 - SSL_CTRL_SET_SESS_CACHE_MODE + 45 - SSL_CTRL_GET_SESS_CACHE_MODE + 50 - SSL_CTRL_GET_MAX_CERT_LIST + 51 - SSL_CTRL_SET_MAX_CERT_LIST + 52 - SSL_CTRL_SET_MAX_SEND_FRAGMENT + 53 - SSL_CTRL_SET_TLSEXT_SERVERNAME_CB + 54 - SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG + 55 - SSL_CTRL_SET_TLSEXT_HOSTNAME + 56 - SSL_CTRL_SET_TLSEXT_DEBUG_CB + 57 - SSL_CTRL_SET_TLSEXT_DEBUG_ARG + 58 - SSL_CTRL_GET_TLSEXT_TICKET_KEYS + 59 - SSL_CTRL_SET_TLSEXT_TICKET_KEYS + 60 - SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT + 61 - SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB + 62 - SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG + 63 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB + 64 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG + 65 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE + 66 - SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS + 67 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS + 68 - SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS + 69 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS + 70 - SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP + 71 - SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP + 72 - SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + 73 - DTLS_CTRL_GET_TIMEOUT + 74 - DTLS_CTRL_HANDLE_TIMEOUT + 75 - DTLS_CTRL_LISTEN + 76 - SSL_CTRL_GET_RI_SUPPORT + 77 - SSL_CTRL_CLEAR_OPTIONS + 78 - SSL_CTRL_CLEAR_MODE + + 82 - SSL_CTRL_GET_EXTRA_CHAIN_CERTS + 83 - SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS + + 88 - SSL_CTRL_CHAIN + 89 - SSL_CTRL_CHAIN_CERT + + 90 - SSL_CTRL_GET_CURVES + 91 - SSL_CTRL_SET_CURVES + 92 - SSL_CTRL_SET_CURVES_LIST + 93 - SSL_CTRL_GET_SHARED_CURVE + 94 - SSL_CTRL_SET_ECDH_AUTO + 97 - SSL_CTRL_SET_SIGALGS + 98 - SSL_CTRL_SET_SIGALGS_LIST + 99 - SSL_CTRL_CERT_FLAGS + 100 - SSL_CTRL_CLEAR_CERT_FLAGS + 101 - SSL_CTRL_SET_CLIENT_SIGALGS + 102 - SSL_CTRL_SET_CLIENT_SIGALGS_LIST + 103 - SSL_CTRL_GET_CLIENT_CERT_TYPES + 104 - SSL_CTRL_SET_CLIENT_CERT_TYPES + 105 - SSL_CTRL_BUILD_CERT_CHAIN + 106 - SSL_CTRL_SET_VERIFY_CERT_STORE + 107 - SSL_CTRL_SET_CHAIN_CERT_STORE + 108 - SSL_CTRL_GET_PEER_SIGNATURE_NID + 109 - SSL_CTRL_GET_SERVER_TMP_KEY + 110 - SSL_CTRL_GET_RAW_CIPHERLIST + 111 - SSL_CTRL_GET_EC_POINT_FORMATS + 112 - SSL_CTRL_GET_TLSA_RECORD + 113 - SSL_CTRL_SET_TLSA_RECORD + 114 - SSL_CTRL_PULL_TLSA_RECORD + +Check openssl doc L + +=item * CTX_flush_sessions + +Causes a run through the session cache of $ctx to remove sessions expired at time $tm. + + Net::SSLeay::CTX_flush_sessions($ctx, $tm); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $tm - specifies the time which should be used for the expiration test (seconds since 1.1.1970) + # + # returns: no return value + +Check openssl doc L + +=item * CTX_free + +Free an allocated SSL_CTX object. + + Net::SSLeay::CTX_free($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: no return value + +Check openssl doc L + +=item * CTX_get_app_data + +Can be used to get application defined value/data. + + my $rv = Net::SSLeay::CTX_get_app_data($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: string/buffer/pointer ??? + +=item * CTX_set_app_data + +Can be used to set some application defined value/data. + + my $rv = Net::SSLeay::CTX_set_app_data($ctx, $arg); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $arg - (string/buffer/pointer ???) data + # + # returns: ??? + +=item * CTX_get0_param + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Returns the current verification parameters. + + my $vpm = Net::SSLeay::CTX_get0_param($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's X509_VERIFY_PARAM structure + +Check openssl doc L + +=item * CTX_get_cert_store + +Returns the current certificate verification storage. + + my $rv = Net::SSLeay::CTX_get_cert_store($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's X509_STORE structure (0 on failure) + +Check openssl doc L + +=item * CTX_get_client_CA_list + +Returns the list of client CAs explicitly set for $ctx using L. + + my $rv = Net::SSLeay::CTX_get_client_CA_list($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's X509_NAME_STACK structure (0 on failure) + +Check openssl doc L + +=item * CTX_get_ex_data + +Is used to retrieve the information for index $idx from $ctx. + + my $rv = Net::SSLeay::CTX_get_ex_data($ssl, $idx); + # $ssl - value corresponding to openssl's SSL_CTX structure + # $idx - (integer) index for application specific data + # + # returns: pointer to ??? + +Check openssl doc L + +=item * CTX_get_ex_new_index + +Is used to register a new index for application specific data. + + my $rv = Net::SSLeay::CTX_get_ex_new_index($argl, $argp, $new_func, $dup_func, $free_func); + # $argl - (long) ??? + # $argp - (pointer) ??? + # $new_func - function pointer ??? (CRYPTO_EX_new *) + # $dup_func - function pointer ??? (CRYPTO_EX_dup *) + # $free_func - function pointer ??? (CRYPTO_EX_free *) + # + # returns: (integer) ??? + +Check openssl doc L + +=item * CTX_get_mode + +Returns the mode set for ctx. + + my $rv = Net::SSLeay::CTX_get_mode($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: mode (bitmask) + + #to decode the return value (bitmask) use: + 0x00000001 corresponds to SSL_MODE_ENABLE_PARTIAL_WRITE + 0x00000002 corresponds to SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + 0x00000004 corresponds to SSL_MODE_AUTO_RETRY + 0x00000008 corresponds to SSL_MODE_NO_AUTO_CHAIN + 0x00000010 corresponds to SSL_MODE_RELEASE_BUFFERS + (note: some of the bits might not be supported by older openssl versions) + +Check openssl doc L + +=item * CTX_set_mode + +Adds the mode set via bitmask in $mode to $ctx. Options already set before are not cleared. + + my $rv = Net::SSLeay::CTX_set_mode($ctx, $mode); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $mode - mode bitmask + # + # returns: the new mode bitmask after adding $mode + +For bitmask details see L (above). + +Check openssl doc L + +=item * CTX_get_options + +Returns the options (bitmask) set for $ctx. + + my $rv = Net::SSLeay::CTX_get_options($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: options (bitmask) + +B The available constants and their values in bitmask depend +on the TLS library. For example, SSL_OP_NO_TLSv1_3 became available +much later than SSL_OP_NO_COMPRESS which is already deprecated by some +libraries. Also, some previously used option values have been recycled +and are now used for newer options. See the list of constants in this +document for options Net::SSLeay currently supports. + +You are strongly encouraged to B if you need +to use numeric values directly. The following is a sample of historic +values. It may not be correct anymore. + + #to decode the return value (bitmask) use: + 0x00000004 corresponds to SSL_OP_LEGACY_SERVER_CONNECT + 0x00000800 corresponds to SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS + 0x00004000 corresponds to SSL_OP_NO_TICKET + 0x00010000 corresponds to SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + 0x00400000 corresponds to SSL_OP_CIPHER_SERVER_PREFERENCE + 0x04000000 corresponds to SSL_OP_NO_TLSv1 + +Check openssl doc L + +=item * CTX_set_options + +Adds the options set via bitmask in $options to ctx. Options already set before are not cleared. + + Net::SSLeay::CTX_set_options($ctx, $options); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $options - options bitmask + # + # returns: the new options bitmask after adding $options + +For bitmask details see L (above). + +Check openssl doc L + +=item * CTX_get_quiet_shutdown + +Returns the 'quiet shutdown' setting of $ctx. + + my $rv = Net::SSLeay::CTX_get_quiet_shutdown($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: (integer) the current setting + +Check openssl doc L + +=item * CTX_get_read_ahead + + my $rv = Net::SSLeay::CTX_get_read_ahead($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: (integer) read_ahead value + +=item * CTX_get_session_cache_mode + +Returns the currently used cache mode (bitmask). + + my $rv = Net::SSLeay::CTX_get_session_cache_mode($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: mode (bitmask) + +B SESS_CACHE_OFF and other constants are not available in +Net-SSLeay-1.82 and before. If the constants are not available, the +following values have historically been correct. You are strongly +encouraged to B for the current values. + + #to decode the return value (bitmask) use: + 0x0000 corresponds to SSL_SESS_CACHE_OFF + 0x0001 corresponds to SSL_SESS_CACHE_CLIENT + 0x0002 corresponds to SSL_SESS_CACHE_SERVER + 0x0080 corresponds to SSL_SESS_CACHE_NO_AUTO_CLEAR + 0x0100 corresponds to SSL_SESS_CACHE_NO_INTERNAL_LOOKUP + 0x0200 corresponds to SSL_SESS_CACHE_NO_INTERNAL_STORE + (note: some of the bits might not be supported by older openssl versions) + +Check openssl doc L + +=item * CTX_set_session_cache_mode + +Enables/disables session caching by setting the operational mode for $ctx to $mode. + + my $rv = Net::SSLeay::CTX_set_session_cache_mode($ctx, $mode); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $mode - mode (bitmask) + # + # returns: previously set cache mode + +For bitmask details see L (above). + +Check openssl doc L + +=item * CTX_get_timeout + +Returns the currently set timeout value for $ctx. + + my $rv = Net::SSLeay::CTX_get_timeout($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: timeout in seconds + +Check openssl doc L + +=item * CTX_get_verify_depth + +Returns the verification depth limit currently set in $ctx. If no limit has been explicitly set, -1 is returned and the default value will be used.", + + my $rv = Net::SSLeay::CTX_get_verify_depth($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: depth limit currently set in $ctx, -1 if no limit has been explicitly set + +Check openssl doc L + +=item * CTX_get_verify_mode + +Returns the verification mode (bitmask) currently set in $ctx. + + my $rv = Net::SSLeay::CTX_get_verify_mode($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: mode (bitmask) + +For bitmask details see L. + +Check openssl doc L + +=item * CTX_set_verify + +Sets the verification flags for $ctx to be $mode and specifies the verify_callback function to be used. + + Net::SSLeay::CTX_set_verify($ctx, $mode, $callback); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $mode - mode (bitmask), see OpenSSL manual + # $callback - [optional] reference to perl callback function + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_post_handshake_auth + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Enable the Post-Handshake Authentication extension to be added to the ClientHello such that post-handshake authentication can be requested by the server. + + Net::SSLeay::CTX_set_posthandshake_auth($ctx, $val); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $val - 0 then the extension is not sent, otherwise it is + # + # returns: no return value + +Check openssl doc L + +=item * CTX_load_verify_locations + +Specifies the locations for $ctx, at which CA certificates for verification purposes are located. The certificates available via $CAfile and $CApath are trusted. + + my $rv = Net::SSLeay::CTX_load_verify_locations($ctx, $CAfile, $CApath); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $CAfile - (string) file of CA certificates in PEM format, the file can contain several CA certificates (or '') + # $CApath - (string) directory containing CA certificates in PEM format (or '') + # + # returns: 1 on success, 0 on failure (check the error stack to find out the reason) + +Check openssl doc L + +=item * CTX_need_tmp_RSA + +Return the result of C + + my $rv = Net::SSLeay::CTX_need_tmp_RSA($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: result of SSL_CTRL_NEED_TMP_RSA command + +Not available with OpenSSL 1.1 and later. + +=item * CTX_new + +The same as L + + my $rv = Net::SSLeay::CTX_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +Check openssl doc L + +Not available with OpenSSL 1.1 and later. + +=item * CTX_v2_new + +Creates a new SSL_CTX object - based on SSLv2_method() - as framework to establish TLS/SSL enabled connections. + + my $rv = Net::SSLeay::CTX_v2_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +=item * CTX_v23_new + +Creates a new SSL_CTX object - based on SSLv23_method() - as framework to establish TLS/SSL enabled connections. + + my $rv = Net::SSLeay::CTX_v23_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +=item * CTX_v3_new + +Creates a new SSL_CTX object - based on SSLv3_method() - as framework to establish TLS/SSL enabled connections. + + my $rv = Net::SSLeay::CTX_v3_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +=item * CTX_tlsv1_new + +Creates a new SSL_CTX object - based on TLSv1_method() - as framework to establish TLS/SSL enabled connections. + + my $rv = Net::SSLeay::CTX_tlsv1_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +=item * CTX_tlsv1_1_new + +Creates a new SSL_CTX object - based on TLSv1_1_method() - as framework to establish TLS/SSL +enabled connections. Only available where supported by the underlying openssl. + + my $rv = Net::SSLeay::CTX_tlsv1_1_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +=item * CTX_tlsv1_2_new + +Creates a new SSL_CTX object - based on TLSv1_2_method() - as framework to establish TLS/SSL +enabled connections. Only available where supported by the underlying openssl. + + my $rv = Net::SSLeay::CTX_tlsv1_2_new(); + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +=item * CTX_new_with_method + +Creates a new SSL_CTX object based on $meth method + + my $rv = Net::SSLeay::CTX_new_with_method($meth); + # $meth - value corresponding to openssl's SSL_METHOD structure + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + + #example + my $ctx = Net::SSLeay::CTX_new_with_method(&Net::SSLeay::TLSv1_method); + +Check openssl doc L + +=item * CTX_set_min_proto_version, CTX_set_max_proto_version, set_min_proto_version and set_max_proto_version, + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 or LibreSSL 2.6.0 + +Set the minimum and maximum supported protocol for $ctx or $ssl. + + my $rv = Net::SSLeay::CTX_set_min_proto_version($ctx, $version) + # $ctx - value corresponding to openssl's SSL_CTX structure + # $version - (integer) constat version value or 0 for automatic lowest or highest value + # + # returns: 1 on success, 0 on failure + + #example: allow only TLS 1.2 for a SSL_CTX + my $rv_min = Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_2_VERSION()); + my $rv_max = Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_2_VERSION()); + + #example: allow only TLS 1.1 for a SSL + my $rv_min = Net::SSLeay::set_min_proto_version($ssl, Net::SSLeay::TLS1_1_VERSION()); + my $rv_max = Net::SSLeay::set_max_proto_version($ssl, Net::SSLeay::TLS1_1_VERSION()); + +Check openssl doc L + +=item * CTX_get_min_proto_version, CTX_get_max_proto_version, get_min_proto_version and get_max_proto_version, + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0g + +Get the minimum and maximum supported protocol for $ctx or $ssl. + + my $version = Net::SSLeay::CTX_get_min_proto_version($ctx) + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: 0 automatic lowest or highest value, configured value otherwise + +Check openssl doc L + +=item * CTX_remove_session + +Removes the session $ses from the context $ctx. + + my $rv = Net::SSLeay::CTX_remove_session($ctx, $ses); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_sess_accept + + my $rv = Net::SSLeay::CTX_sess_accept($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of started SSL/TLS handshakes in server mode + +Check openssl doc L + +=item * CTX_sess_accept_good + + my $rv = Net::SSLeay::CTX_sess_accept_good($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of successfully established SSL/TLS sessions in server mode + +Check openssl doc L + +=item * CTX_sess_accept_renegotiate + + my $rv = Net::SSLeay::CTX_sess_accept_renegotiate($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of start renegotiations in server mode + +Check openssl doc L + +=item * CTX_sess_cache_full + + my $rv = Net::SSLeay::CTX_sess_cache_full($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of sessions that were removed because the maximum session cache size was exceeded + +Check openssl doc L + +=item * CTX_sess_cb_hits + + my $rv = Net::SSLeay::CTX_sess_cb_hits($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of successfully retrieved sessions from the external session cache in server mode + +Check openssl doc L + +=item * CTX_sess_connect + + my $rv = Net::SSLeay::CTX_sess_connect($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of started SSL/TLS handshakes in client mode + +Check openssl doc L + +=item * CTX_sess_connect_good + + my $rv = Net::SSLeay::CTX_sess_connect_good($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of successfully established SSL/TLS sessions in client mode + +Check openssl doc L + +=item * CTX_sess_connect_renegotiate + + my $rv = Net::SSLeay::CTX_sess_connect_renegotiate($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of start renegotiations in client mode + +Check openssl doc L + +=item * CTX_sess_get_cache_size + +Returns the currently valid session cache size. + + my $rv = Net::SSLeay::CTX_sess_get_cache_size($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: current size + +Check openssl doc L + +=item * CTX_sess_hits + + my $rv = Net::SSLeay::CTX_sess_hits($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of successfully reused sessions + +Check openssl doc L + +=item * CTX_sess_misses + + my $rv = Net::SSLeay::CTX_sess_misses($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of sessions proposed by clients that were not found in the internal session cache in server mode + +Check openssl doc L + +=item * CTX_sess_number + + my $rv = Net::SSLeay::CTX_sess_number($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: current number of sessions in the internal session cache + +Check openssl doc L + +=item * CTX_sess_set_cache_size + +Sets the size of the internal session cache of context $ctx to $size. + + Net::SSLeay::CTX_sess_set_cache_size($ctx, $size); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $size - cache size (0 = unlimited) + # + # returns: previously valid size + +Check openssl doc L + +=item * CTX_sess_timeouts + +Returns the number of sessions proposed by clients and either found in the internal or external session cache in +server mode, but that were invalid due to timeout. These sessions are not included in the SSL_CTX_sess_hits count. + + my $rv = Net::SSLeay::CTX_sess_timeouts($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: number of sessions + +Check openssl doc L + +=item * CTX_sess_set_new_cb + +B not available in Net-SSLeay-1.85 and before + +Sets the callback function, which is automatically called whenever a new session was negotiated. + + Net::SSLeay::CTX_sess_set_new_cb($ctx, $func); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $func - perl reference to callback function + # + # returns: no return value + +Check openssl doc L + +=item * CTX_sess_set_remove_cb + +B not available in Net-SSLeay-1.85 and before + +Sets the callback function, which is automatically called whenever a session is removed by the SSL engine. + + Net::SSLeay::CTX_sess_set_remove_cb($ctx, $func); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $func - perl reference to callback function + # + # returns: no return value + +Check openssl doc L + +=item * CTX_sessions + +Returns a pointer to the lhash databases containing the internal session cache for ctx. + + my $rv = Net::SSLeay::CTX_sessions($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's LHASH structure (0 on failure) + +Check openssl doc L + +=item * CTX_set1_param + +Applies X509 verification parameters $vpm on $ctx + + my $rv = Net::SSLeay::CTX_set1_param($ctx, $vpm); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $vpm - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_set_cert_store + +Sets/replaces the certificate verification storage of $ctx to/with $store. + + Net::SSLeay::CTX_set_cert_store($ctx, $store); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $store - value corresponding to openssl's X509_STORE structure + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_cert_verify_callback + +Sets the verification callback function for $ctx. SSL objects that are created from $ctx +inherit the setting valid at the time when C is called. + + Net::SSLeay::CTX_set_cert_verify_callback($ctx, $func, $data); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $func - perl reference to callback function + # $data - [optional] data that will be passed to callback function when invoked + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_cipher_list + +Sets the list of available ciphers for $ctx using the control string $str. +The list of ciphers is inherited by all ssl objects created from $ctx. + + my $rv = Net::SSLeay::CTX_set_cipher_list($s, $str); + # $s - value corresponding to openssl's SSL_CTX structure + # $str - (string) cipher list e.g. '3DES:+RSA' + # + # returns: 1 if any cipher could be selected and 0 on complete failure + +The format of $str is described in L + +Check openssl doc L + +=item * CTX_set_ciphersuites + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Configure the available TLSv1.3 ciphersuites. + + my $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, $str); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $str - colon (":") separated list of TLSv1.3 ciphersuite names in order of preference + # + # returns: (integer) 1 if the requested ciphersuite list was configured, and 0 otherwise + +Check openssl doc L + +=item * CTX_set_client_CA_list + +Sets the list of CAs sent to the client when requesting a client certificate for $ctx. + + Net::SSLeay::CTX_set_client_CA_list($ctx, $list); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $list - value corresponding to openssl's X509_NAME_STACK structure + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_default_passwd_cb + +Sets the default password callback called when loading/storing a PEM certificate with encryption. + + Net::SSLeay::CTX_set_default_passwd_cb($ctx, $func); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $func - perl reference to callback function + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_default_passwd_cb_userdata + +Sets a pointer to userdata which will be provided to the password callback on invocation. + + Net::SSLeay::CTX_set_default_passwd_cb_userdata($ctx, $userdata); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $userdata - data that will be passed to callback function when invoked + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_default_verify_paths + +??? (more info needed) + + my $rv = Net::SSLeay::CTX_set_default_verify_paths($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: 1 on success, 0 on failure + +=item * CTX_set_ex_data + +Is used to store application data at $data for $idx into the $ctx object. + + my $rv = Net::SSLeay::CTX_set_ex_data($ssl, $idx, $data); + # $ssl - value corresponding to openssl's SSL_CTX structure + # $idx - (integer) ??? + # $data - (pointer) ??? + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_set_purpose + + my $rv = Net::SSLeay::CTX_set_purpose($s, $purpose); + # $s - value corresponding to openssl's SSL_CTX structure + # $purpose - (integer) purpose identifier + # + # returns: 1 on success, 0 on failure + + #avainable purpose identifier + 1 - X509_PURPOSE_SSL_CLIENT + 2 - X509_PURPOSE_SSL_SERVER + 3 - X509_PURPOSE_NS_SSL_SERVER + 4 - X509_PURPOSE_SMIME_SIGN + 5 - X509_PURPOSE_SMIME_ENCRYPT + 6 - X509_PURPOSE_CRL_SIGN + 7 - X509_PURPOSE_ANY + 8 - X509_PURPOSE_OCSP_HELPER + 9 - X509_PURPOSE_TIMESTAMP_SIGN + + #or use corresponding constants + $purpose = &Net::SSLeay::X509_PURPOSE_SSL_CLIENT; + ... + $purpose = &Net::SSLeay::X509_PURPOSE_TIMESTAMP_SIGN; + +=item * CTX_set_quiet_shutdown + +Sets the 'quiet shutdown' flag for $ctx to be mode. SSL objects created from $ctx inherit the mode valid at the time C is called. + + Net::SSLeay::CTX_set_quiet_shutdown($ctx, $mode); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $mode - 0 or 1 + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_read_ahead + + my $rv = Net::SSLeay::CTX_set_read_ahead($ctx, $val); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $val - read_ahead value to be set + # + # returns: the original read_ahead value + +=item * CTX_set_session_id_context + +Sets the context $sid_ctx of length $sid_ctx_len within which a session can be reused for the $ctx object. + + my $rv = Net::SSLeay::CTX_set_session_id_context($ctx, $sid_ctx, $sid_ctx_len); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $sid_ctx - data buffer + # $sid_ctx_len - length of data in $sid_ctx + # + # returns: 1 on success, 0 on failure (the error is logged to the error stack) + +Check openssl doc L + +=item * CTX_set_ssl_version + +Sets a new default TLS/SSL method for SSL objects newly created from this $ctx. +SSL objects already created with C are not +affected, except when C is being called. + + my $rv = Net::SSLeay::CTX_set_ssl_version($ctx, $meth); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $meth - value corresponding to openssl's SSL_METHOD structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_set_timeout + +Sets the timeout for newly created sessions for $ctx to $t. The timeout value $t must be given in seconds. + + my $rv = Net::SSLeay::CTX_set_timeout($ctx, $t); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $t - timeout in seconds + # + # returns: previously set timeout value + +Check openssl doc L + +=item * CTX_set_tmp_dh + +Sets DH parameters to be used to be $dh. The key is inherited by all ssl objects created from $ctx. + + my $rv = Net::SSLeay::CTX_set_tmp_dh($ctx, $dh); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $dh - value corresponding to openssl's DH structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * CTX_set_tmp_dh_callback + +Sets the callback function for $ctx to be used when a DH parameters are required to $tmp_dh_callback. + + Net::SSLeay::CTX_set_tmp_dh_callback($ctx, $tmp_dh_callback); + # $ctx - value corresponding to openssl's SSL_CTX structure + # tmp_dh_callback - (function pointer) ??? + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_tmp_rsa + +Sets the temporary/ephemeral RSA key to be used to be $rsa. + + my $rv = Net::SSLeay::CTX_set_tmp_rsa($ctx, $rsa); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $rsa - value corresponding to openssl's RSA structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +Not available with OpenSSL 1.1 and later. + +=item * CTX_set_tmp_rsa_callback + +Sets the callback function for ctx to be used when a temporary/ephemeral RSA key is required to $tmp_rsa_callback. + +??? (does this function really work?) + + Net::SSLeay::CTX_set_tmp_rsa_callback($ctx, $tmp_rsa_callback); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $tmp_rsa_callback - (function pointer) ??? + # + # returns: no return value + +Check openssl doc L + +Not available with OpenSSL 1.1 and later. + +=item * CTX_set_trust + + my $rv = Net::SSLeay::CTX_set_trust($s, $trust); + # $s - value corresponding to openssl's SSL_CTX structure + # $trust - (integer) trust identifier + # + # returns: the original value + + #available trust identifiers + 1 - X509_TRUST_COMPAT + 2 - X509_TRUST_SSL_CLIENT + 3 - X509_TRUST_SSL_SERVER + 4 - X509_TRUST_EMAIL + 5 - X509_TRUST_OBJECT_SIGN + 6 - X509_TRUST_OCSP_SIGN + 7 - X509_TRUST_OCSP_REQUEST + 8 - X509_TRUST_TSA + + #or use corresponding constants + $trust = &Net::SSLeay::X509_TRUST_COMPAT; + ... + $trust = &Net::SSLeay::X509_TRUST_TSA; + +=item * CTX_set_verify_depth + +Sets the maximum depth for the certificate chain verification that shall be allowed for ctx. + + Net::SSLeay::CTX_set_verify_depth($ctx, $depth); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $depth - max. depth + # + # returns: no return value + +Check openssl doc L + +=item * CTX_use_PKCS12_file + +Adds the certificate and private key from PKCS12 file $p12filename to $ctx. + + my $rv = Net::SSLeay::CTX_use_PKCS12_file($ctx, $p12filename, $password); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $p12filename - (string) filename + # $password - (string) password to decrypt private key + # + # returns: 1 on success, 0 on failure + +=item * CTX_use_PrivateKey + +Adds the private key $pkey to $ctx. + + my $rv = Net::SSLeay::CTX_use_PrivateKey($ctx, $pkey); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_use_PrivateKey_file + +Adds the first private key found in $file to $ctx. + + my $rv = Net::SSLeay::CTX_use_PrivateKey_file($ctx, $file, $type); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_use_RSAPrivateKey + +Adds the RSA private key $rsa to $ctx. + + my $rv = Net::SSLeay::CTX_use_RSAPrivateKey($ctx, $rsa); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $rsa - value corresponding to openssl's RSA structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_use_RSAPrivateKey_file + +Adds the first RSA private key found in $file to $ctx. + + my $rv = Net::SSLeay::CTX_use_RSAPrivateKey_file($ctx, $file, $type); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +=item * CTX_use_certificate + +Loads the certificate $x into $ctx + + my $rv = Net::SSLeay::CTX_use_certificate($ctx, $x); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $x - value corresponding to openssl's X509 structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_use_certificate_chain_file + +Loads a certificate chain from $file into $ctx. The certificates must be in PEM format and must be sorted +starting with the subject's certificate (actual client or server certificate), followed by intermediate +CA certificates if applicable, and ending at the highest level (root) CA. + + my $rv = Net::SSLeay::CTX_use_certificate_chain_file($ctx, $file); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $file - (string) file name + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_use_certificate_file + +Loads the first certificate stored in $file into $ctx. + + my $rv = Net::SSLeay::CTX_use_certificate_file($ctx, $file, $type); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * CTX_get_security_level + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + +Returns the security level associated with $ctx. + + my $level = Net::SSLeay::CTX_get_security_level($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: (integer) current security level + +Check openssl doc L + +=item * CTX_set_security_level + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + +Sets the security level associated with $ctx to $level. + + Net::SSLeay::CTX_set_security_level($ctx, $level); + # $ssl - value corresponding to openssl's SSL_CTX structure + # $level - new security level + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_num_tickets + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Set number of TLSv1.3 session tickets that will be sent to a client. + + my $rv = Net::SSLeay::CTX_set_num_tickets($ctx, $number_of_tickets); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $number_of_tickets - number of tickets to send + # + # returns: 1 on success, 0 on failure + +Set to zero if you do not no want to support a session resumption. + +Check openssl doc L + +=item * CTX_get_num_tickets + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Get number of TLSv1.3 session tickets that will be sent to a client. + + my $number_of_tickets = Net::SSLeay::CTX_get_num_tickets($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: (integer) number of tickets to send + +Check openssl doc L + +=back + +=head3 Low level API: SSL_* related functions + +B Please note that the function described in this chapter have "SSL_" part stripped from their original openssl names. + +=over + +=item * new + +Creates a new SSL structure which is needed to hold the data for a TLS/SSL connection. +The new structure inherits the settings of the underlying context $ctx: connection +method (SSLv2/v3/TLSv1), options, verification settings, timeout settings. + + my $rv = Net::SSLeay::new($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's SSL structure (0 on failure) + +Check openssl doc L + +=item * accept + +Waits for a TLS/SSL client to initiate the TLS/SSL handshake. The communication +channel must already have been set and assigned to the ssl by setting an underlying BIO. + + my $rv = Net::SSLeay::accept($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 = success, 0 = handshake not successful, <0 = fatal error during handshake + +Check openssl doc L + +=item * add_client_CA + +Adds the CA name extracted from cacert to the list of CAs sent to the client +when requesting a client certificate for the chosen ssl, overriding the setting +valid for ssl's SSL_CTX object. + + my $rv = Net::SSLeay::add_client_CA($ssl, $x); + # $ssl - value corresponding to openssl's SSL structure + # $x - value corresponding to openssl's X509 structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * callback_ctrl + +??? (more info needed) + + my $rv = Net::SSLeay::callback_ctrl($ssl, $cmd, $fp); + # $ssl - value corresponding to openssl's SSL structure + # $cmd - (integer) command id + # $fp - (function pointer) ??? + # + # returns: ??? + +Check openssl doc L + +=item * check_private_key + +Checks the consistency of a private key with the corresponding certificate loaded into $ssl + + my $rv = Net::SSLeay::check_private_key($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * clear + +Reset SSL object to allow another connection. + + Net::SSLeay::clear($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: no return value + +Check openssl doc L + +=item * connect + +Initiate the TLS/SSL handshake with an TLS/SSL server. + + my $rv = Net::SSLeay::connect($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 = success, 0 = handshake not successful, <0 = fatal error during handshake + +Check openssl doc L + +=item * copy_session_id + +Copies the session structure fro $from to $to (+ also the private key and certificate associated with $from). + + Net::SSLeay::copy_session_id($to, $from); + # $to - value corresponding to openssl's SSL structure + # $from - value corresponding to openssl's SSL structure + # + # returns: no return value + +=item * ctrl + +Internal handling function for SSL objects. + +B openssl doc says: This function should never be called directly! + + my $rv = Net::SSLeay::ctrl($ssl, $cmd, $larg, $parg); + # $ssl - value corresponding to openssl's SSL structure + # $cmd - (integer) command id + # $larg - (integer) long ??? + # $parg - (string/pointer) ??? + # + # returns: (long) result of given command ??? + +For more details about valid $cmd values check L. + +Check openssl doc L + +=item * do_handshake + +Will wait for a SSL/TLS handshake to take place. If the connection is in client +mode, the handshake will be started. The handshake routines may have to be +explicitly set in advance using either SSL_set_connect_state or SSL_set_accept_state(3). + + my $rv = Net::SSLeay::do_handshake($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 = success, 0 = handshake not successful, <0 = fatal error during handshake + +Check openssl doc L + +=item * dup + +Returns a duplicate of $ssl. + + my $rv = Net::SSLeay::dup($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's SSL structure (0 on failure) + +=item * free + +Free an allocated SSL structure. + + Net::SSLeay::free($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: no return value + +Check openssl doc L + +=item * get0_param + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Returns the current verification parameters. + + my $vpm = Net::SSLeay::get0_param($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's X509_VERIFY_PARAM structure + +Check openssl doc L + +=item * get_SSL_CTX + +Returns a pointer to the SSL_CTX object, from which $ssl was created with Net::SSLeay::new. + + my $rv = Net::SSLeay::get_SSL_CTX($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's SSL_CTX structure (0 on failure) + +Check openssl doc L + +=item * set_SSL_CTX + +Sets the SSL_CTX the corresponds to an SSL session. + + my $the_ssl_ctx = Net::SSLeay::set_SSL_CTX($ssl, $ssl_ctx); + # $ssl - value corresponding to openssl's SSL structure + # $ssl_ctx - Change the ssl object to the given ssl_ctx + # + # returns - the ssl_ctx + +=item * get_app_data + +Can be used to get application defined value/data. + + my $rv = Net::SSLeay::get_app_data($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: string/buffer/pointer ??? + +=item * set_app_data + +Can be used to set some application defined value/data. + + my $rv = Net::SSLeay::set_app_data($ssl, $arg); + # $ssl - value corresponding to openssl's SSL structure + # $arg - (string/buffer/pointer ???) data + # + # returns: ??? + +=item * get_certificate + +Gets X509 certificate from an established SSL connection. + + my $rv = Net::SSLeay::get_certificate($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's X509 structure (0 on failure) + +=item * get_cipher + +Obtains the name of the currently used cipher. + + my $rv = Net::SSLeay::get_cipher($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (string) cipher name e.g. 'DHE-RSA-AES256-SHA' or '', when no session has been established. + +Check openssl doc L + +=item * get_cipher_bits + +Obtain the number of secret/algorithm bits used. + + my $rv = Net::SSLeay::get_cipher_bits($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: number of secret bits used by current cipher + +Check openssl doc L +and L + +=item * get_cipher_list + +Returns the name (string) of the SSL_CIPHER listed for $ssl with priority $n. + + my $rv = Net::SSLeay::get_cipher_list($ssl, $n); + # $ssl - value corresponding to openssl's SSL structure + # $n - (integer) priority + # + # returns: (string) cipher name e.g. 'EDH-DSS-DES-CBC3-SHA' or '' in case of error + +Call Net::SSLeay::get_cipher_list with priority starting from 0 to obtain +the sorted list of available ciphers, until '' is returned: + + my $priority = 0; + while (my $c = Net::SSLeay::get_cipher_list($ssl, $priority)) { + print "cipher[$priority] = $c\n"; + $priority++; + } + +Check openssl doc L + +=item * get_client_CA_list + +Returns the list of client CAs explicitly set for $ssl using C +or $ssl's SSL_CTX object with C, when in server mode. + +In client mode, returns the list of client CAs sent from the server, if any. + + my $rv = Net::SSLeay::get_client_CA_list($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's STACK_OF(X509_NAME) structure (0 on failure) + +Check openssl doc L + +=item * get_current_cipher + +Returns the cipher actually used. + + my $rv = Net::SSLeay::get_current_cipher($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's SSL_CIPHER structure (0 on failure) + +Check openssl doc L + +=item * get_default_timeout + +Returns the default timeout value assigned to SSL_SESSION objects negotiated for the protocol valid for $ssl. + + my $rv = Net::SSLeay::get_default_timeout($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (long) timeout in seconds + +Check openssl doc L + +=item * get_error + +Returns a result code for a preceding call to C, C, C, C, C or C on $ssl. + + my $rv = Net::SSLeay::get_error($ssl, $ret); + # $ssl - value corresponding to openssl's SSL structure + # $ret - return value of preceding TLS/SSL I/O operation + # + # returns: result code, which is one of the following values: + # 0 - SSL_ERROR_NONE + # 1 - SSL_ERROR_SSL + # 2 - SSL_ERROR_WANT_READ + # 3 - SSL_ERROR_WANT_WRITE + # 4 - SSL_ERROR_WANT_X509_LOOKUP + # 5 - SSL_ERROR_SYSCALL + # 6 - SSL_ERROR_ZERO_RETURN + # 7 - SSL_ERROR_WANT_CONNECT + # 8 - SSL_ERROR_WANT_ACCEPT + +Check openssl doc L + +=item * get_ex_data + +Is used to retrieve the information for $idx from $ssl. + + my $rv = Net::SSLeay::get_ex_data($ssl, $idx); + # $ssl - value corresponding to openssl's SSL structure + # $idx - (integer) index for application specific data + # + # returns: pointer to ??? + +Check openssl doc L + +=item * set_ex_data + +Is used to store application data at $data for $idx into the $ssl object. + + my $rv = Net::SSLeay::set_ex_data($ssl, $idx, $data); + # $ssl - value corresponding to openssl's SSL structure + # $idx - (integer) ??? + # $data - (pointer) ??? + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * get_ex_new_index + +Is used to register a new index for application specific data. + + my $rv = Net::SSLeay::get_ex_new_index($argl, $argp, $new_func, $dup_func, $free_func); + # $argl - (long) ??? + # $argp - (pointer) ??? + # $new_func - function pointer ??? (CRYPTO_EX_new *) + # $dup_func - function pointer ??? (CRYPTO_EX_dup *) + # $free_func - function pointer ??? (CRYPTO_EX_free *) + # + # returns: (integer) ??? + +Check openssl doc L + +=item * get_fd + +Returns the file descriptor which is linked to $ssl. + + my $rv = Net::SSLeay::get_fd($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: file descriptor (>=0) or -1 on failure + +Check openssl doc L + +=item * get_finished + +Obtains the latest 'Finished' message sent to the peer. Return value +is zero if there's been no Finished message yet. Default count is +2*EVP_MAX_MD_SIZE that is long enough for all possible Finish +messages. If you supply a non-default count, the resulting return +value may be longer than returned buf's length. + + my $rv = Net::SSLeay::get_finished($ssl, $buf, $count); + # $ssl - value corresponding to openssl's SSL structure + # $buf - buffer where the returned data will be stored + # $count - [optional] max size of return data - default is 2*EVP_MAX_MD_SIZE + # + # returns: length of latest Finished message + +=item * get_peer_finished + +Obtains the latest 'Finished' message expected from the +peer. Parameters and return value are similar to get_finished(). + + my $rv = Net::SSLeay::get_peer_finished($ssl, $buf, $count); + # $ssl - value corresponding to openssl's SSL structure + # $buf - buffer where the returned data will be stored + # $count - [optional] max size of return data - default is 2*EVP_MAX_MD_SIZE + # + # returns: length of latest Finished message + +=item * get_keyblock_size + +Gets the length of the TLS keyblock. + +B Does not exactly correspond to any low level API function. + + my $rv = Net::SSLeay::get_keyblock_size($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: keyblock size, -1 on error + +=item * get_mode + +Returns the mode (bitmask) set for $ssl. + + my $rv = Net::SSLeay::get_mode($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: mode (bitmask) + +To decode the return value (bitmask) see documentation for L. + +Check openssl doc L + +=item * set_mode + +Adds the mode set via bitmask in $mode to $ssl. Options already set before are not cleared. + + my $rv = Net::SSLeay::set_mode($ssl, $mode); + # $ssl - value corresponding to openssl's SSL structure + # $mode - mode (bitmask) + # + # returns: the new mode bitmask after adding $mode + +For $mode bitmask details see L. + +Check openssl doc L + +=item * get_options + +Returns the options (bitmask) set for $ssl. + + my $rv = Net::SSLeay::get_options($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: options (bitmask) + +To decode the return value (bitmask) see documentation for L. + +Check openssl doc L + +=item * set_options + +Adds the options set via bitmask in $options to $ssl. Options already set before are not cleared! + + Net::SSLeay::set_options($ssl, $options); + # $ssl - value corresponding to openssl's SSL structure + # $options - options (bitmask) + # + # returns: the new options bitmask after adding $options + +For $options bitmask details see L. + +Check openssl doc L + +=item * get_peer_certificate + +Get the X509 certificate of the peer. + + my $rv = Net::SSLeay::get_peer_certificate($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's X509 structure (0 on failure) + +Check openssl doc L + +=item * get_peer_cert_chain + +Get the certificate chain of the peer as an array of X509 structures. + + my @rv = Net::SSLeay::get_peer_cert_chain($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: list of X509 structures + +Check openssl doc L + +=item * get_quiet_shutdown + +Returns the 'quiet shutdown' setting of ssl. + + my $rv = Net::SSLeay::get_quiet_shutdown($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) current 'quiet shutdown' value + +Check openssl doc L + +=item * get_rbio + +Get 'read' BIO linked to an SSL object $ssl. + + my $rv = Net::SSLeay::get_rbio($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * get_read_ahead + + my $rv = Net::SSLeay::get_read_ahead($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) read_ahead value + +=item * set_read_ahead + + Net::SSLeay::set_read_ahead($ssl, $val); + # $ssl - value corresponding to openssl's SSL structure + # $val - read_ahead value to be set + # + # returns: the original read_ahead value + +=item * get_security_level + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + +Returns the security level associated with $ssl. + + my $level = Net::SSLeay::get_security_level($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) current security level + +Check openssl doc L + +=item * set_security_level + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + +Sets the security level associated with $ssl to $level. + + Net::SSLeay::set_security_level($ssl, $level); + # $ssl - value corresponding to openssl's SSL structure + # $level - new security level + # + # returns: no return value + +Check openssl doc L + +=item * set_num_tickets + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Set number of TLSv1.3 session tickets that will be sent to a client. + + my $rv = Net::SSLeay::set_num_tickets($ssl, $number_of_tickets); + # $ssl - value corresponding to openssl's SSL structure + # $number_of_tickets - number of tickets to send + # + # returns: 1 on success, 0 on failure + +Set to zero if you do not no want to support a session resumption. + +Check openssl doc L + +=item * get_num_tickets + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Get number of TLSv1.3 session tickets that will be sent to a client. + + my $number_of_tickets = Net::SSLeay::get_num_tickets($ctx); + # $ctx - value corresponding to openssl's SSL structure + # + # returns: number of tickets to send + +Check openssl doc L + +=item * get_server_random + +Returns internal SSLv3 server_random value. + + Net::SSLeay::get_server_random($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: server_random value (binary data) + +=item * get_client_random + +B Does not exactly correspond to any low level API function + +Returns internal SSLv3 client_random value. + + Net::SSLeay::get_client_random($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: client_random value (binary data) + +=item * export_keying_material + +Returns keying material based on the string $label and optional +$context. Note that with TLSv1.2 and lower, empty context (empty +string) and undefined context (no value or 'undef') will return +different values. + + my $out = Net::SSLeay::export_keying_material($ssl, $olen, $label, $context); + # $ssl - value corresponding to openssl's SSL structure + # $olen - number of bytes to return + # $label - application specific label + # $context - [optional] context - default is undef for no context + # + # returns: keying material (binary data) or undef on error + +Check openssl doc L + +=item * get_session + +Retrieve TLS/SSL session data used in $ssl. The reference count of the SSL_SESSION is NOT incremented. + + my $rv = Net::SSLeay::get_session($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's SSL_SESSION structure (0 on failure) + +Check openssl doc L + +=item * SSL_get0_session + +The alias for L (note that the name is C NOT C). + + my $rv = Net::SSLeay::SSL_get0_session(); + +=item * get1_session + +Returns a pointer to the SSL_SESSION actually used in $ssl. The reference count of the SSL_SESSION is incremented by 1. + + my $rv = Net::SSLeay::get1_session($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's SSL_SESSION structure (0 on failure) + +Check openssl doc L + +=item * get_shared_ciphers + +Returns string with a list (colon ':' separated) of ciphers shared between client and server +within SSL session $ssl. + + my $rv = Net::SSLeay::get_shared_ciphers() + # + # returns: string like 'ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:...' + +=item * get_shutdown + +Returns the shutdown mode of $ssl. + + my $rv = Net::SSLeay::get_shutdown($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: shutdown mode (bitmask) of ssl + + #to decode the return value (bitmask) use: + 0 - No shutdown setting, yet + 1 - SSL_SENT_SHUTDOWN + 2 - SSL_RECEIVED_SHUTDOWN + +Check openssl doc L + +=item * get_ssl_method + +Returns a function pointer to the TLS/SSL method set in $ssl. + + my $rv = Net::SSLeay::get_ssl_method($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's SSL_METHOD structure (0 on failure) + +Check openssl doc L + +=item * in_init, in_before, is_init_finished, in_connect_init, in_accept_init + +B not available in Net-SSLeay-1.85 and before. + +Retrieve information about the handshake state machine. All functions take $ssl as the only argument and return 0 or 1. These functions are recommended over get_state() and state(). + + my $rv = Net::SSLeay::is_init_finished($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: All functions return 1 or 0 + +Check openssl doc L + +=item * get_state + +B OpenSSL 1.1.0 and later use different constants which are not made available. Use is_init_finished() and related functions instead. + +Returns the SSL connection state. + + my $rv = Net::SSLeay::get_state($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) state value + # to decode the returned state check: + # SSL_ST_* constants in openssl/ssl.h + # SSL2_ST_* constants in openssl/ssl2.h + # SSL23_ST_* constants in openssl/ssl23.h + # SSL3_ST_* + DTLS1_ST_* constants in openssl/ssl3.h + +=item * state + +Exactly the same as L. + + my $rv = Net::SSLeay::state($ssl); + +=item * set_state + +Sets the SSL connection state. + + Net::SSLeay::set_state($ssl,Net::SSLeay::SSL_ST_ACCEPT()); + +Not available with OpenSSL 1.1 and later. + +=item * get_verify_depth + +Returns the verification depth limit currently set in $ssl. + + my $rv = Net::SSLeay::get_verify_depth($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: current depth or -1 if no limit has been explicitly set + +Check openssl doc L + +=item * set_verify_depth + +Sets the maximum depth for the certificate chain verification that shall be allowed for $ssl. + + Net::SSLeay::set_verify_depth($ssl, $depth); + # $ssl - value corresponding to openssl's SSL structure + # $depth - (integer) depth + # + # returns: no return value + +Check openssl doc L + +=item * get_verify_mode + +Returns the verification mode (bitmask) currently set in $ssl. + + my $rv = Net::SSLeay::get_verify_mode($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: mode (bitmask) + +To decode the return value (bitmask) see documentation for L. + +Check openssl doc L + +=item * set_verify + +Sets the verification flags for $ssl to be $mode and specifies the $verify_callback function to be used. + + Net::SSLeay::set_verify($ssl, $mode, $callback); + # $ssl - value corresponding to openssl's SSL structure + # $mode - mode (bitmask) + # $callback - [optional] reference to perl callback function + # + # returns: no return value + +For $mode bitmask details see L. + +Check openssl doc L + +=item * set_post_handshake_auth + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Enable the Post-Handshake Authentication extension to be added to the ClientHello such that post-handshake authentication can be requested by the server. + + Net::SSLeay::set_posthandshake_auth($ssl, $val); + # $ssl - value corresponding to openssl's SSL structure + # $val - 0 then the extension is not sent, otherwise it is + # + # returns: no return value + +Check openssl doc L + +=item * verify_client_post_handshake + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +verify_client_post_handshake causes a CertificateRequest message to be sent by a server on the given ssl connection. + + my $rv = Net::SSLeay::verify_client_post_handshake($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 if the request succeeded, and 0 if the request failed. The error stack can be examined to determine the failure reason. + +Check openssl doc L + +=item * get_verify_result + +Returns the result of the verification of the X509 certificate presented by the peer, if any. + + my $rv = Net::SSLeay::get_verify_result($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) + # 0 - X509_V_OK: ok + # 2 - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate + # 3 - X509_V_ERR_UNABLE_TO_GET_CRL: unable to get certificate CRL + # 4 - X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: unable to decrypt certificate's signature + # 5 - X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: unable to decrypt CRL's signature + # 6 - X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: unable to decode issuer public key + # 7 - X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure + # 8 - X509_V_ERR_CRL_SIGNATURE_FAILURE: CRL signature failure + # 9 - X509_V_ERR_CERT_NOT_YET_VALID: certificate is not yet valid + # 10 - X509_V_ERR_CERT_HAS_EXPIRED: certificate has expired + # 11 - X509_V_ERR_CRL_NOT_YET_VALID: CRL is not yet valid + # 12 - X509_V_ERR_CRL_HAS_EXPIRED: CRL has expired + # 13 - X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: format error in certificate's notBefore field + # 14 - X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: format error in certificate's notAfter field + # 15 - X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: format error in CRL's lastUpdate field + # 16 - X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: format error in CRL's nextUpdate field + # 17 - X509_V_ERR_OUT_OF_MEM: out of memory + # 18 - X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: self signed certificate + # 19 - X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: self signed certificate in certificate chain + # 20 - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate + # 21 - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: unable to verify the first certificate + # 22 - X509_V_ERR_CERT_CHAIN_TOO_LONG: certificate chain too long + # 23 - X509_V_ERR_CERT_REVOKED: certificate revoked + # 24 - X509_V_ERR_INVALID_CA: invalid CA certificate + # 25 - X509_V_ERR_PATH_LENGTH_EXCEEDED: path length constraint exceeded + # 26 - X509_V_ERR_INVALID_PURPOSE: unsupported certificate purpose + # 27 - X509_V_ERR_CERT_UNTRUSTED: certificate not trusted + # 28 - X509_V_ERR_CERT_REJECTED: certificate rejected + # 29 - X509_V_ERR_SUBJECT_ISSUER_MISMATCH: subject issuer mismatch + # 30 - X509_V_ERR_AKID_SKID_MISMATCH: authority and subject key identifier mismatch + # 31 - X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: authority and issuer serial number mismatch + # 32 - X509_V_ERR_KEYUSAGE_NO_CERTSIGN:key usage does not include certificate signing + # 50 - X509_V_ERR_APPLICATION_VERIFICATION: application verification failure + +Check openssl doc L + +=item * set_verify_result + +Override result of peer certificate verification. + + Net::SSLeay::set_verify_result($ssl, $v); + # $ssl - value corresponding to openssl's SSL structure + # $v - (integer) result value + # + # returns: no return value + +For more info about valid return values see L + +Check openssl doc L + +=item * get_wbio + +Get 'write' BIO linked to an SSL object $ssl. + + my $rv = Net::SSLeay::get_wbio($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * load_client_CA_file + +Load X509 certificates from file (PEM formatted). + + my $rv = Net::SSLeay::load_client_CA_file($file); + # $file - (string) file name + # + # returns: value corresponding to openssl's STACK_OF(X509_NAME) structure (0 on failure) + +Check openssl doc L + +=item * clear_num_renegotiations + +Executes SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS command on $ssl. + + my $rv = Net::SSLeay::clear_num_renegotiations($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: command result + +=item * need_tmp_RSA + +Executes SSL_CTRL_NEED_TMP_RSA command on $ssl. + + my $rv = Net::SSLeay::need_tmp_RSA($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: command result + +Not available with OpenSSL 1.1 and later. + +=item * num_renegotiations + +Executes SSL_CTRL_GET_NUM_RENEGOTIATIONS command on $ssl. + + my $rv = Net::SSLeay::num_renegotiations($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: command result + +=item * total_renegotiations + +Executes SSL_CTRL_GET_TOTAL_RENEGOTIATIONS command on $ssl. + + my $rv = Net::SSLeay::total_renegotiations($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: command result + +=item * peek + +Copies $max bytes from the specified $ssl into the returned value. +In contrast to the C function, the data in the SSL +buffer is unmodified after the SSL_peek() operation. + + Net::SSLeay::peek($ssl, $max); + # $ssl - value corresponding to openssl's SSL structure + # $max - [optional] max bytes to peek (integer) - default is 32768 + # + # in scalar context: data read from the TLS/SSL connection, undef on error + # in list context: two-item array consisting of data read (undef on error), + # and return code from SSL_peek(). + +=item * peek_ex + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Copies $max bytes from the specified $ssl into the returned value. +In contrast to the C function, the data in the SSL +buffer is unmodified after the SSL_peek_ex() operation. + + my($got, $rv) = Net::SSLeay::peek_ex($ssl, $max); + # $ssl - value corresponding to openssl's SSL structure + # $max - [optional] max bytes to peek (integer) - default is 32768 + # + # returns a list: two-item list consisting of data read (undef on error), + # and return code from SSL_peek_ex(). + +Check openssl doc L + +=item * pending + +Obtain number of readable bytes buffered in $ssl object. + + my $rv = Net::SSLeay::pending($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: the number of bytes pending + +Check openssl doc L + +=item * has_pending + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + +Returns 1 if $ssl has buffered data (whether processed or unprocessed) and 0 otherwise. + + my $rv = Net::SSLeay::has_pending($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) 1 or 0 + +Check openssl doc L + +=item * read + +Tries to read $max bytes from the specified $ssl. + + my $got = Net::SSLeay::read($ssl, $max); + my($got, $rv) = Net::SSLeay::read($ssl, $max); + # $ssl - value corresponding to openssl's SSL structure + # $max - [optional] max bytes to read (integer) - default is 32768 + # + # returns: + # in scalar context: data read from the TLS/SSL connection, undef on error + # in list context: two-item array consisting of data read (undef on error), + # and return code from SSL_read(). + +Check openssl doc L + +=item * read_ex + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Tries to read $max bytes from the specified $ssl. + + my($got, $rv) = Net::SSLeay::read_ex($ssl, $max); + # $ssl - value corresponding to openssl's SSL structure + # $max - [optional] max bytes to read (integer) - default is 32768 + # + # returns a list: two-item list consisting of data read (undef on error), + # and return code from SSL_read_ex(). + +Check openssl doc L + +=item * renegotiate + +Turn on flags for renegotiation so that renegotiation will happen + + my $rv = Net::SSLeay::renegotiate($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 on success, 0 on failure + +=item * rstate_string + +Returns a 2 letter string indicating the current read state of the SSL object $ssl. + + my $rv = Net::SSLeay::rstate_string($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 2-letter string + +Check openssl doc L + +=item * rstate_string_long + +Returns a string indicating the current read state of the SSL object ssl. + + my $rv = Net::SSLeay::rstate_string_long($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: string with current state + +Check openssl doc L + +=item * session_reused + +Query whether a reused session was negotiated during handshake. + + my $rv = Net::SSLeay::session_reused($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 0 - new session was negotiated; 1 - session was reused. + +Check openssl doc L + +=item * set1_param + +Applies X509 verification parameters $vpm on $ssl + + my $rv = Net::SSLeay::set1_param($ssl, $vpm); + # $ssl - value corresponding to openssl's SSL structure + # $vpm - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: 1 on success, 0 on failure + +=item * set_accept_state + +Sets $ssl to work in server mode. + + Net::SSLeay::set_accept_state($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: no return value + +Check openssl doc L + +=item * set_bio + +Connects the BIOs $rbio and $wbio for the read and write operations of the TLS/SSL (encrypted) side of $ssl. + + Net::SSLeay::set_bio($ssl, $rbio, $wbio); + # $ssl - value corresponding to openssl's SSL structure + # $rbio - value corresponding to openssl's BIO structure + # $wbio - value corresponding to openssl's BIO structure + # + # returns: no return value + +Check openssl doc L + +=item * set_cipher_list + +Sets the list of ciphers only for ssl. + + my $rv = Net::SSLeay::set_cipher_list($ssl, $str); + # $ssl - value corresponding to openssl's SSL structure + # $str - (string) cipher list e.g. '3DES:+RSA' + # + # returns: 1 if any cipher could be selected and 0 on complete failure + +Check openssl doc L + +=item * set_ciphersuites + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Configure the available TLSv1.3 ciphersuites. + + my $rv = Net::SSLeay::set_ciphersuites($ssl, $str); + # $ssl - value corresponding to openssl's SSL structure + # $str - colon (":") separated list of TLSv1.3 ciphersuite names in order of preference + # + # returns: (integer) 1 if the requested ciphersuite list was configured, and 0 otherwise + +Check openssl doc L + +=item * set_client_CA_list + +Sets the list of CAs sent to the client when requesting a client certificate +for the chosen $ssl, overriding the setting valid for $ssl's SSL_CTX object. + + my $rv = Net::SSLeay::set_client_CA_list($ssl, $list); + # $ssl - value corresponding to openssl's SSL structure + # $list - value corresponding to openssl's STACK_OF(X509_NAME) structure + # + # returns: no return value + +Check openssl doc L + +=item * set_connect_state + +Sets $ssl to work in client mode. + + Net::SSLeay::set_connect_state($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: no return value + +Check openssl doc L + +=item * set_fd + +Sets the file descriptor $fd as the input/output facility for the TLS/SSL (encrypted) +side of $ssl, $fd will typically be the socket file descriptor of a network connection. + + my $rv = Net::SSLeay::set_fd($ssl, $fd); + # $ssl - value corresponding to openssl's SSL structure + # $fd - (integer) file handle (got via perl's fileno) + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_psk_client_callback + +Sets the psk client callback. + + Net::SSLeay::set_psk_client_callback($ssl, sub { my $hint = shift; return ($identity, $key) } ); + # $ssl - value corresponding to openssl's SSL structure + # $hint - PSK identity hint send by the server + # $identity - PSK identity + # $key - PSK key, hex string without the leading '0x', e.g. 'deadbeef' + # + # returns: no return value + +Check openssl doc L + +=item * set_rfd + +Sets the file descriptor $fd as the input (read) facility for the TLS/SSL (encrypted) side of $ssl. + + my $rv = Net::SSLeay::set_rfd($ssl, $fd); + # $ssl - value corresponding to openssl's SSL structure + # $fd - (integer) file handle (got via perl's fileno) + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_wfd + + my $rv = Net::SSLeay::set_wfd($ssl, $fd); + # $ssl - value corresponding to openssl's SSL structure + # $fd - (integer) file handle (got via perl's fileno) + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_info_callback + +Sets the callback function, that can be used to obtain state information for $ssl during connection setup and use. +When callback is undef, the callback setting currently valid for ctx is used. + + Net::SSLeay::set_info_callback($ssl, $cb, [$data]); + # $ssl - value corresponding to openssl's SSL structure + # $cb - sub { my ($ssl,$where,$ret,$data) = @_; ... } + # + # returns: no return value + +Check openssl doc L + +=item * CTX_set_info_callback + +Sets the callback function on ctx, that can be used to obtain state information during ssl connection setup and use. +When callback is undef, an existing callback will be disabled. + + Net::SSLeay::CTX_set_info_callback($ssl, $cb, [$data]); + # $ssl - value corresponding to openssl's SSL structure + # $cb - sub { my ($ssl,$where,$ret,$data) = @_; ... } + # + # returns: no return value + +Check openssl doc L + +=item * set_pref_cipher + +Sets the list of available ciphers for $ssl using the control string $str. + + my $rv = Net::SSLeay::set_pref_cipher($ssl, $str); + # $ssl - value corresponding to openssl's SSL structure + # $str - (string) cipher list e.g. '3DES:+RSA' + # + # returns: 1 if any cipher could be selected and 0 on complete failure + +Check openssl doc L + +=item * CTX_set_psk_client_callback + +Sets the psk client callback. + + Net::SSLeay::CTX_set_psk_client_callback($ssl, sub { my $hint = shift; return ($identity, $key) } ); + # $ssl - value corresponding to openssl's SSL structure + # $hint - PSK identity hint send by the server + # $identity - PSK identity + # $key - PSK key, hex string without the leading '0x', e.g. 'deadbeef' + # + # returns: no return value + +Check openssl doc L + +=item * set_purpose + + my $rv = Net::SSLeay::set_purpose($ssl, $purpose); + # $ssl - value corresponding to openssl's SSL structure + # $purpose - (integer) purpose identifier + # + # returns: 1 on success, 0 on failure + +For more info about available $purpose identifiers see L. + +=item * set_quiet_shutdown + +Sets the 'quiet shutdown' flag for $ssl to be $mode. + + Net::SSLeay::set_quiet_shutdown($ssl, $mode); + # $ssl - value corresponding to openssl's SSL structure + # $mode - 0 or 1 + # + # returns: no return value + +Check openssl doc L + +=item * set_session + +Set a TLS/SSL session to be used during TLS/SSL connect. + + my $rv = Net::SSLeay::set_session($to, $ses); + # $to - value corresponding to openssl's SSL structure + # $ses - value corresponding to openssl's SSL_SESSION structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_session_id_context + +Sets the context $sid_ctx of length $sid_ctx_len within which a session can be reused for the $ssl object. + + my $rv = Net::SSLeay::set_session_id_context($ssl, $sid_ctx, $sid_ctx_len); + # $ssl - value corresponding to openssl's SSL structure + # $sid_ctx - data buffer + # $sid_ctx_len - length of data in $sid_ctx + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_session_secret_cb + +Setup pre-shared secret session resumption function. + + Net::SSLeay::set_session_secret_cb($ssl, $func, $data); + # $ssl - value corresponding to openssl's SSL structure + # $func - perl reference to callback function + # $data - [optional] data that will be passed to callback function when invoked + # + # returns: no return value + +The callback function will be called like: +callback_function($secret, $ciphers, $pref_cipher, $data); + +# $secret is the current master session key, usually all 0s at the beginning of a session +# $ciphers is ref to an array of peer cipher names +# $pref_cipher is a ref to an index into the list of cipher names of +# the preferred cipher. Set it if you want to specify a preferred cipher +# $data is the data passed to set_session_secret_cb + +The callback function should return 1 if it likes the suggested cipher (or has selected an alternative +by setting pref_cipher), else it should return 0 (in which case OpenSSL will select its own preferred cipher). + +With OpenSSL 1.1 and later, callback_function can change the master key for the session by +altering $secret and returning 1. + +=item * CTX_set_tlsext_ticket_getkey_cb + +Setup encryption for TLS session tickets (stateless session reuse). + + Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($ctx, $func, $data); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $func - perl reference to callback function + # $data - [optional] data that will be passed to callback function when invoked + # + # returns: no return value + +The callback function will be called like: +getkey($data,[$key_name]) -> ($key,$current_key_name) + +# $data is the data passed to set_session_secret_cb +# $key_name is the name of the key OpenSSL has extracted from the session ticket +# $key is the requested key for ticket encryption + HMAC +# $current_key_name is the name for the currently valid key + +OpenSSL will call the function without a key name if it generates a new ticket. +It then needs the callback to return the encryption+HMAC key and an identifier +(key name) for this key. + +When OpenSSL gets a session ticket from the client it extracts the key name and +calls the callback with this name as argument. It then expects the callback to +return the encryption+HMAC key matching the requested key name and and also the +key name which should be used at the moment. If the requested key name and the +returned key name differ it means that this session ticket was created with an +expired key and need to be renewed. In this case OpenSSL will call the callback +again with no key name to create a new session ticket based on the old one. + +The key must be at least 32 byte of random data which can be created with +RAND_bytes. Internally the first 16 byte are used as key in AES-128 encryption +while the next 16 byte are used for the SHA-256 HMAC. +The key name are binary data and must be exactly 16 byte long. + +Example: + + Net::SSLeay::RAND_bytes(my $oldkey,32); + Net::SSLeay::RAND_bytes(my $newkey,32); + my $oldkey_name = pack("a16",'oldsecret'); + my $newkey_name = pack("a16",'newsecret'); + + my @keys = ( + [ $newkey_name, $newkey ], # current active key + [ $oldkey_name, $oldkey ], # already expired + ); + + Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($server2->_ctx, sub { + my ($mykeys,$name) = @_; + + # return (current_key, current_key_name) if no name given + return ($mykeys->[0][1],$mykeys->[0][0]) if ! $name; + + # return (matching_key, current_key_name) if we find a key matching + # the given name + for(my $i = 0; $i<@$mykeys; $i++) { + next if $name ne $mykeys->[$i][0]; + return ($mykeys->[$i][1],$mykeys->[0][0]); + } + + # no matching key found + return; + },\@keys); + + +This function is based on the OpenSSL function SSL_CTX_set_tlsext_ticket_key_cb +but provides a simpler to use interface. For more information see +L + +=item * set_session_ticket_ext_cb + +Setup callback for TLS session tickets (stateless session reuse). + + Net::SSLeay::set_session_ticket_ext_cb($ssl, $func, $data); + # $ssl - value corresponding to openssl's SSL structure + # $func - perl reference to callback function + # $data - [optional] data that will be passed to callback function when invoked + # + # returns: no return value + +The callback function will be called like: +getticket($ssl,$ticket,$data) -> $return_value + +# $ssl is a value corresponding to openssl's SSL structure +# $ticket is a value of received TLS session ticket (can also be empty) +# $data is the data passed to set_session_ticket_ext_cb +# $return_value is either 0 (failure) or 1 (success) + +This function is based on the OpenSSL function SSL_set_session_ticket_ext_cb. + +=item * set_session_ticket_ext + +Set TLS session ticket (stateless session reuse). + + Net::SSLeay::set_session_ticket_ext($ssl, $ticket); + # $ssl - value corresponding to openssl's SSL structure + # $ticket - is a value of TLS session ticket which client will send (can also be empty string) + # + # returns: no return value + +The callback function will be called like: +getticket($ssl,$ticket,$data) -> $return_value + +# $ssl is a value corresponding to openssl's SSL structure +# $ticket is a value of received TLS session ticket (can also be empty) +# $data is the data passed to set_session_ticket_ext_cb +# $return_value is either 0 (failure) or 1 (success) + +This function is based on the OpenSSL function SSL_set_session_ticket_ext_cb. + +=item * set_shutdown + +Sets the shutdown state of $ssl to $mode. + + Net::SSLeay::set_shutdown($ssl, $mode); + # $ssl - value corresponding to openssl's SSL structure + # $mode - (integer) shutdown mode: + # 0 - No shutdown + # 1 - SSL_SENT_SHUTDOWN + # 2 - SSL_RECEIVED_SHUTDOWN + # 3 - SSL_RECEIVED_SHUTDOWN+SSL_SENT_SHUTDOWN + # + # returns: no return value + +Check openssl doc L + +=item * set_ssl_method + +Sets a new TLS/SSL method for a particular $ssl object. + + my $rv = Net::SSLeay::set_ssl_method($ssl, $method); + # $ssl - value corresponding to openssl's SSL structure + # $method - value corresponding to openssl's SSL_METHOD structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_tmp_dh + +Sets DH parameters to be used to be $dh. + + my $rv = Net::SSLeay::set_tmp_dh($ssl, $dh); + # $ssl - value corresponding to openssl's SSL structure + # $dh - value corresponding to openssl's DH structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * set_tmp_dh_callback + +Sets the callback function for $ssl to be used when a DH parameters are required to $dh_cb. + +??? (does this function really work?) + + Net::SSLeay::set_tmp_dh_callback($ssl, $dh); + # $ssl - value corresponding to openssl's SSL structure + # $dh_cb - pointer to function ??? + # + # returns: no return value + +Check openssl doc L + +=item * set_tmp_rsa + +Sets the temporary/ephemeral RSA key to be used in $ssl to be $rsa. + + my $rv = Net::SSLeay::set_tmp_rsa($ssl, $rsa); + # $ssl - value corresponding to openssl's SSL structure + # $rsa - value corresponding to openssl's RSA structure + # + # returns: 1 on success, 0 on failure + +Example: + + $rsakey = Net::SSLeay::RSA_generate_key(); + Net::SSLeay::set_tmp_rsa($ssl, $rsakey); + Net::SSLeay::RSA_free($rsakey); + +Check openssl doc L + +=item * set_tmp_rsa_callback + +Sets the callback function for $ssl to be used when a temporary/ephemeral RSA key is required to $tmp_rsa_callback. + +??? (does this function really work?) + + Net::SSLeay::set_tmp_rsa_callback($ssl, $tmp_rsa_callback); + # $ssl - value corresponding to openssl's SSL structure + # $tmp_rsa_callback - (function pointer) ??? + # + # returns: no return value + +Check openssl doc L + +=item * set_trust + + my $rv = Net::SSLeay::set_trust($ssl, $trust); + # $ssl - value corresponding to openssl's SSL structure + # $trust - (integer) trust identifier + # + # returns: the original value + +For more details about $trust values see L. + +=item * shutdown + +Shuts down an active TLS/SSL connection. It sends the 'close notify' shutdown alert to the peer. + + my $rv = Net::SSLeay::shutdown($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 1 - shutdown was successfully completed + # 0 - shutdown is not yet finished, + # -1 - shutdown was not successful + +Check openssl doc L + +=item * state_string + +Returns a 6 letter string indicating the current state of the SSL object $ssl. + + my $rv = Net::SSLeay::state_string($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: 6-letter string + +Check openssl doc L + +=item * state_string_long + +Returns a string indicating the current state of the SSL object $ssl. + + my $rv = Net::SSLeay::state_string_long($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: state strings + +Check openssl doc L + +=item * set_default_passwd_cb + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0f. Not needed with LibreSSL. + +Sets the default password callback called when loading/storing a PEM certificate with encryption for $ssl. + + Net::SSLeay::set_default_passwd_cb($ssl, $func); + # $ssl - value corresponding to openssl's SSL structure + # $func - perl reference to callback function + # + # returns: no return value + +Check openssl doc L + +=item * set_default_passwd_cb_userdata + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0f. Not needed with LibreSSL. + +Sets a pointer to userdata which will be provided to the password callback of $ssl on invocation. + + Net::SSLeay::set_default_passwd_cb_userdata($ssl, $userdata); + # $ssl - value corresponding to openssl's SSL structure + # $userdata - data that will be passed to callback function when invoked + # + # returns: no return value + +Check openssl doc L + +=item * use_PrivateKey + +Adds $pkey as private key to $ssl. + + my $rv = Net::SSLeay::use_PrivateKey($ssl, $pkey); + # $ssl - value corresponding to openssl's SSL structure + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_PrivateKey_ASN1 + +Adds the private key of type $pk stored in $data to $ssl. + + my $rv = Net::SSLeay::use_PrivateKey_ASN1($pk, $ssl, $d, $len); + # $pk - (integer) key type, NID of corresponding algorithm + # $ssl - value corresponding to openssl's SSL structure + # $data - key data (binary) + # $len - length of $data + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_PrivateKey_file + +Adds the first private key found in $file to $ssl. + + my $rv = Net::SSLeay::use_PrivateKey_file($ssl, $file, $type); + # $ssl - value corresponding to openssl's SSL structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_RSAPrivateKey + +Adds $rsa as RSA private key to $ssl. + + my $rv = Net::SSLeay::use_RSAPrivateKey($ssl, $rsa); + # $ssl - value corresponding to openssl's SSL structure + # $rsa - value corresponding to openssl's RSA structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_RSAPrivateKey_ASN1 + +Adds RSA private key stored in $data to $ssl. + + my $rv = Net::SSLeay::use_RSAPrivateKey_ASN1($ssl, $data, $len); + # $ssl - value corresponding to openssl's SSL structure + # $data - key data (binary) + # $len - length of $data + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_RSAPrivateKey_file + +Adds the first RSA private key found in $file to $ssl. + + my $rv = Net::SSLeay::use_RSAPrivateKey_file($ssl, $file, $type); + # $ssl - value corresponding to openssl's SSL structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_certificate + +Loads the certificate $x into $ssl. + + my $rv = Net::SSLeay::use_certificate($ssl, $x); + # $ssl - value corresponding to openssl's SSL structure + # $x - value corresponding to openssl's X509 structure + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_certificate_ASN1 + +Loads the ASN1 encoded certificate from $data to $ssl. + + my $rv = Net::SSLeay::use_certificate_ASN1($ssl, $data, $len); + # $ssl - value corresponding to openssl's SSL structure + # $data - certificate data (binary) + # $len - length of $data + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_certificate_chain_file + +B: not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.1.0 + +Loads a certificate chain from $file into $ssl. The certificates must be in PEM format and must be sorted +starting with the subject's certificate (actual client or server certificate), followed by intermediate +CA certificates if applicable, and ending at the highest level (root) CA. + + my $rv = Net::SSLeay::use_certificate_chain_file($ssl, $file); + # $ssl - value corresponding to openssl's SSL structure + # $file - (string) file name + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * use_certificate_file + +Loads the first certificate stored in $file into $ssl. + + my $rv = Net::SSLeay::use_certificate_file($ssl, $file, $type); + # $ssl - value corresponding to openssl's SSL structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, otherwise check out the error stack to find out the reason + +Check openssl doc L + +=item * get_version + +Returns SSL/TLS protocol name + + my $rv = Net::SSLeay::get_version($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (string) protocol name, see OpenSSL manual for the full list + # TLSv1 + # TLSv1.3 + +Check openssl doc L + +=item * version + +Returns SSL/TLS protocol version + + my $rv = Net::SSLeay::version($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) protocol version, see OpenSSL manual for the full list + # 0x0301 - TLS1_VERSION (TLSv1) + # 0xFEFF - DTLS1_VERSION (DTLSv1) + +Check openssl doc L + +=item * client_version + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + +Returns TLS protocol version used by the client when initiating the connection + + my $rv = Net::SSLeay::client_version($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) protocol version, see OpenSSL manual for the full list + # 0x0301 - TLS1_VERSION (TLSv1) + # 0xFEFF - DTLS1_VERSION (DTLSv1) + +Check openssl doc L + +=item * is_dtls + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.0, not in LibreSSL + + my $rv = Net::SSLeay::is_dtls($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) zero or one + # 0 - connection is not using DTLS + # 1 - connection is using DTLS + +Check openssl doc L + +=item * want + +Returns state information for the SSL object $ssl. + + my $rv = Net::SSLeay::want($ssl); + # $ssl - value corresponding to openssl's SSL structure + # + # returns: state + # 1 - SSL_NOTHING + # 2 - SSL_WRITING + # 3 - SSL_READING + # 4 - SSL_X509_LOOKUP + +Check openssl doc L + +=item * write + +Writes data from the buffer $data into the specified $ssl connection. + + my $rv = Net::SSLeay::write($ssl, $data); + # $ssl - value corresponding to openssl's SSL structure + # $data - data to be written + # + # returns: >0 - (success) number of bytes actually written to the TLS/SSL connection + # 0 - write not successful, probably the underlying connection was closed + # <0 - error + +Check openssl doc L + +=item * write_ex + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Writes data from the buffer $data into the specified $ssl connection. + + my ($len, $rv) = Net::SSLeay::write_ex($ssl, $data); + # $ssl - value corresponding to openssl's SSL structure + # $data - data to be written + # + # returns a list: two-item list consisting of number of bytes written, + # and return code from SSL_write_ex() + +Check openssl doc L + +=item * write_partial + +B Does not exactly correspond to any low level API function + +Writes a fragment of data in $data from the buffer $data into the specified +$ssl connection. This is a non-blocking function like L. + + my $rv = Net::SSLeay::write_partial($ssl, $from, $count, $data); + # $ssl - value corresponding to openssl's SSL structure + # $from - (integer) offset from the beginning of $data + # $count - (integer) length of data to be written + # $data - data buffer + # + # returns: >0 - (success) number of bytes actually written to the TLS/SSL connection + # 0 - write not successful, probably the underlying connection was closed + # <0 - error + +=item * set_tlsext_host_name + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.8f + +Sets TLS servername extension on SLL object $ssl to value $name. + + my $rv = set_tlsext_host_name($ssl, $name); + # $ssl - value corresponding to openssl's SSL structure + # $name - (string) name to be set + # + # returns: 1 on success, 0 on failure + +=back + +=head3 Low level API: RAND_* related functions + +Check openssl doc related to RAND stuff L + +=over + +=item * RAND_add + +Mixes the $num bytes at $buf into the PRNG state. + + Net::SSLeay::RAND_add($buf, $num, $entropy); + # $buf - buffer with data to be mixed into the PRNG state + # $num - number of bytes in $buf + # $entropy - estimate of how much randomness is contained in $buf (in bytes) + # + # returns: no return value + +Check openssl doc L + +=item * RAND_seed + +Equivalent to L when $num == $entropy. + + Net::SSLeay::RAND_seed($buf); # Perlishly figures out buf size + # $buf - buffer with data to be mixed into the PRNG state + # $num - number of bytes in $buf + # + # returns: no return value + +Check openssl doc L + +=item * RAND_status + +Gives PRNG status (seeded enough or not). + + my $rv = Net::SSLeay::RAND_status(); + #returns: 1 if the PRNG has been seeded with enough data, 0 otherwise + +Check openssl doc L + +=item * RAND_bytes + +Puts $num cryptographically strong pseudo-random bytes into $buf. + + my $rv = Net::SSLeay::RAND_bytes($buf, $num); + # $buf - buffer where the random data will be stored + # $num - the size (in bytes) of requested random data + # + # returns: 1 on success, -1 if not supported by the current RAND method, or 0 on other failure + +Check openssl doc L + +=item * RAND_priv_bytes + +B not available in Net-SSLeay-1.85 and before; requires at least OpenSSL 1.1.1, not in LibreSSL + +Puts $num cryptographically strong pseudo-random bytes into $buf. + + my $rv = Net::SSLeay::RAND_priv_bytes($buf, $num); + # $buf - buffer where the random data will be stored + # $num - the size (in bytes) of requested random data + # + # returns: 1 on success, -1 if not supported by the current RAND method, or 0 on other failure + +RAND_priv_bytes has the same semantics as RAND_bytes, but see see the documentation for more information. + +Check openssl doc L + +=item * RAND_pseudo_bytes + +Puts $num pseudo-random (not necessarily unpredictable) bytes into $buf. + + my $rv = Net::SSLeay::RAND_pseudo_bytes($buf, $num); + # $buf - buffer where the random data will be stored + # $num - the size (in bytes) of requested random data + # + # returns: 1 if the bytes generated are cryptographically strong, 0 otherwise + +Check openssl doc L + +=item * RAND_cleanup + +Erase the PRNG state. + + Net::SSLeay::RAND_cleanup(); + # no args, no return value + +Check openssl doc L + +=item * RAND_egd_bytes + +Queries the entropy gathering daemon EGD on socket $path for $bytes bytes. + + my $rv = Net::SSLeay::RAND_egd_bytes($path, $bytes); + # $path - path to a socket of entropy gathering daemon EGD + # $bytes - number of bytes we want from EGD + # + # returns: the number of bytes read from the daemon on success, and -1 on failure + +Check openssl doc L + +=item * RAND_file_name + +Generates a default path for the random seed file. + + my $file = Net::SSLeay::RAND_file_name($num); + # $num - maximum size of returned file name + # + # returns: string with file name on success, '' (empty string) on failure + +Check openssl doc L + +=item * RAND_load_file + +B Is no longer functional on LibreSSL + +Reads $max_bytes of bytes from $file_name and adds them to the PRNG. + + my $rv = Net::SSLeay::RAND_load_file($file_name, $max_bytes); + # $file_name - the name of file + # $max_bytes - bytes to read from $file_name; -1 => the complete file is read + # + # returns: the number of bytes read + +Check openssl doc L + +=item * RAND_write_file + +Writes 1024 random bytes to $file_name which can be used to initialize the PRNG by calling L in a later session. + + my $rv = Net::SSLeay::RAND_write_file($file_name); + # $file_name - the name of file + # + # returns: the number of bytes written, and -1 if the bytes written were generated without appropriate seed + +Check openssl doc L + +=item * RAND_poll + +Collects some entropy from operating system and adds it to the PRNG. + + my $rv = Net::SSLeay::RAND_poll(); + # returns: 1 on success, 0 on failure (unable to gather reasonable entropy) + +=back + +=head3 Low level API: OBJ_* related functions + +=over + +=item * OBJ_cmp + +Compares ASN1_OBJECT $a to ASN1_OBJECT $b. + + my $rv = Net::SSLeay::OBJ_cmp($a, $b); + # $a - value corresponding to openssl's ASN1_OBJECT structure + # $b - value corresponding to openssl's ASN1_OBJECT structure + # + # returns: if the two are identical 0 is returned + +Check openssl doc L + +=item * OBJ_dup + +Returns a copy/duplicate of $o. + + my $rv = Net::SSLeay::OBJ_dup($o); + # $o - value corresponding to openssl's ASN1_OBJECT structure + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +Check openssl doc L + +=item * OBJ_nid2ln + +Returns long name for given NID $n. + + my $rv = Net::SSLeay::OBJ_nid2ln($n); + # $n - (integer) NID + # + # returns: (string) long name e.g. 'commonName' + +Check openssl doc L + +=item * OBJ_ln2nid + +Returns NID corresponding to given long name $n. + + my $rv = Net::SSLeay::OBJ_ln2nid($s); + # $s - (string) long name e.g. 'commonName' + # + # returns: (integer) NID + +=item * OBJ_nid2sn + +Returns short name for given NID $n. + + my $rv = Net::SSLeay::OBJ_nid2sn($n); + # $n - (integer) NID + # + # returns: (string) short name e.g. 'CN' + +Example: + + print Net::SSLeay::OBJ_nid2sn(&Net::SSLeay::NID_commonName); + +=item * OBJ_sn2nid + +Returns NID corresponding to given short name $s. + + my $rv = Net::SSLeay::OBJ_sn2nid($s); + # $s - (string) short name e.g. 'CN' + # + # returns: (integer) NID + +Example: + + print "NID_commonName constant=", &Net::SSLeay::NID_commonName; + print "OBJ_sn2nid('CN')=", Net::SSLeay::OBJ_sn2nid('CN'); + +=item * OBJ_nid2obj + +Returns ASN1_OBJECT for given NID $n. + + my $rv = Net::SSLeay::OBJ_nid2obj($n); + # $n - (integer) NID + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +Check openssl doc L + +=item * OBJ_obj2nid + +Returns NID corresponding to given ASN1_OBJECT $o. + + my $rv = Net::SSLeay::OBJ_obj2nid($o); + # $o - value corresponding to openssl's ASN1_OBJECT structure + # + # returns: (integer) NID + +Check openssl doc L + +=item * OBJ_txt2obj + +Converts the text string s into an ASN1_OBJECT structure. If $no_name is 0 then +long names (e.g. 'commonName') and short names (e.g. 'CN') will be interpreted +as well as numerical forms (e.g. '2.5.4.3'). If $no_name is 1 only the numerical +form is acceptable. + + my $rv = Net::SSLeay::OBJ_txt2obj($s, $no_name); + # $s - text string to be converted + # $no_name - (integer) 0 or 1 + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +Check openssl doc L + +=item * OBJ_obj2txt + +Converts the ASN1_OBJECT a into a textual representation. + + Net::SSLeay::OBJ_obj2txt($a, $no_name); + # $a - value corresponding to openssl's ASN1_OBJECT structure + # $no_name - (integer) 0 or 1 + # + # returns: textual representation e.g. 'commonName' ($no_name=0), '2.5.4.3' ($no_name=1) + +Check openssl doc L + +=item * OBJ_txt2nid + +Returns NID corresponding to text string $s which can be a long name, a short name or the numerical representation of an object. + + my $rv = Net::SSLeay::OBJ_txt2nid($s); + # $s - (string) e.g. 'commonName' or 'CN' or '2.5.4.3' + # + # returns: (integer) NID + +Example: + + my $nid = Net::SSLeay::OBJ_txt2nid('2.5.4.3'); + Net::SSLeay::OBJ_nid2sn($n); + +Check openssl doc L + +=back + +=head3 Low level API: ASN1_INTEGER_* related functions + +=over + +=item * ASN1_INTEGER_new + +B not available in Net-SSLeay-1.45 and before + +Creates a new ASN1_INTEGER structure. + + my $rv = Net::SSLeay::ASN1_INTEGER_new(); + # + # returns: value corresponding to openssl's ASN1_INTEGER structure (0 on failure) + +=item * ASN1_INTEGER_free + +B not available in Net-SSLeay-1.45 and before + +Free an allocated ASN1_INTEGER structure. + + Net::SSLeay::ASN1_INTEGER_free($i); + # $i - value corresponding to openssl's ASN1_INTEGER structure + # + # returns: no return value + +=item * ASN1_INTEGER_get + +B not available in Net-SSLeay-1.45 and before + +Returns integer value of given ASN1_INTEGER object. + +B If the value stored in ASN1_INTEGER is greater than max. integer that can be stored +in 'long' type (usually 32bit but may vary according to platform) then this function will return -1. +For getting large ASN1_INTEGER values consider using L or L. + + my $rv = Net::SSLeay::ASN1_INTEGER_get($a); + # $a - value corresponding to openssl's ASN1_INTEGER structure + # + # returns: integer value of ASN1_INTEGER object in $a + +=item * ASN1_INTEGER_set + +B not available in Net-SSLeay-1.45 and before + +Sets value of given ASN1_INTEGER object to value $val + +B $val has max. limit (= max. integer that can be stored in 'long' type). +For setting large ASN1_INTEGER values consider using L or L. + + my $rv = Net::SSLeay::ASN1_INTEGER_set($i, $val); + # $i - value corresponding to openssl's ASN1_INTEGER structure + # $val - integer value + # + # returns: 1 on success, 0 on failure + +=item * P_ASN1_INTEGER_get_dec + +B not available in Net-SSLeay-1.45 and before + +Returns string with decimal representation of integer value of given ASN1_INTEGER object. + + Net::SSLeay::P_ASN1_INTEGER_get_dec($i); + # $i - value corresponding to openssl's ASN1_INTEGER structure + # + # returns: string with decimal representation + +=item * P_ASN1_INTEGER_get_hex + +B not available in Net-SSLeay-1.45 and before + +Returns string with hexadecimal representation of integer value of given ASN1_INTEGER object. + + Net::SSLeay::P_ASN1_INTEGER_get_hex($i); + # $i - value corresponding to openssl's ASN1_INTEGER structure + # + # returns: string with hexadecimal representation + +=item * P_ASN1_INTEGER_set_dec + +B not available in Net-SSLeay-1.45 and before + +Sets value of given ASN1_INTEGER object to value $val (decimal string, suitable for large integers) + + Net::SSLeay::P_ASN1_INTEGER_set_dec($i, $str); + # $i - value corresponding to openssl's ASN1_INTEGER structure + # $str - string with decimal representation + # + # returns: 1 on success, 0 on failure + +=item * P_ASN1_INTEGER_set_hex + +B not available in Net-SSLeay-1.45 and before + +Sets value of given ASN1_INTEGER object to value $val (hexadecimal string, suitable for large integers) + + Net::SSLeay::P_ASN1_INTEGER_set_hex($i, $str); + # $i - value corresponding to openssl's ASN1_INTEGER structure + # $str - string with hexadecimal representation + # + # returns: 1 on success, 0 on failure + +=back + +=head3 Low level API: ASN1_STRING_* related functions + +=over + +=item * P_ASN1_STRING_get + +B not available in Net-SSLeay-1.45 and before + +Returns string value of given ASN1_STRING object. + + Net::SSLeay::P_ASN1_STRING_get($s, $utf8_decode); + # $s - value corresponding to openssl's ASN1_STRING structure + # $utf8_decode - [optional] 0 or 1 whether the returned value should be utf8 decoded (default=0) + # + # returns: string + + $string = Net::SSLeay::P_ASN1_STRING_get($s); + #is the same as: + $string = Net::SSLeay::P_ASN1_STRING_get($s, 0); + +=back + +=head3 Low level API: ASN1_TIME_* related functions + +=over + +=item * ASN1_TIME_new + +B not available in Net-SSLeay-1.42 and before + + my $time = ASN1_TIME_new(); + # returns: value corresponding to openssl's ASN1_TIME structure + +=item * ASN1_TIME_free + +B not available in Net-SSLeay-1.42 and before + + ASN1_TIME_free($time); + # $time - value corresponding to openssl's ASN1_TIME structure + +=item * ASN1_TIME_set + +B not available in Net-SSLeay-1.42 and before + + ASN1_TIME_set($time, $t); + # $time - value corresponding to openssl's ASN1_TIME structure + # $t - time value in seconds since 1.1.1970 + +B It is platform dependent how this function will handle dates after 2038. +Although perl's integer is large enough the internal implementation of this function +is dependent on the size of time_t structure (32bit time_t has problem with 2038). + +If you want to safely set date and time after 2038 use function L. + +=item * P_ASN1_TIME_get_isotime + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7e + +B Does not exactly correspond to any low level API function + +Gives ISO-8601 string representation of ASN1_TIME structure. + + my $datetime_string = P_ASN1_TIME_get_isotime($time); + # $time - value corresponding to openssl's ASN1_TIME structure + # + # returns: datetime string like '2033-05-16T20:39:37Z' or '' on failure + +The output format is compatible with module L + +=item * P_ASN1_TIME_set_isotime + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7e + +B Does not exactly correspond to any low level API function + +Sets time and date value of ANS1_time structure. + + my $rv = P_ASN1_TIME_set_isotime($time, $string); + # $time - value corresponding to openssl's ASN1_TIME structure + # $string - ISO-8601 timedate string like '2033-05-16T20:39:37Z' + # + # returns: 1 on success, 0 on failure + +The C<$string> parameter has to be in full form like C<"2012-03-22T23:55:33"> or +C<"2012-03-22T23:55:33Z"> or C<"2012-03-22T23:55:33CET">. Short forms like +C<"2012-03-22T23:55"> or C<"2012-03-22"> are not supported. + +=item * P_ASN1_TIME_put2string + +B not available in Net-SSLeay-1.42 and before, has bugs with openssl-0.9.8i + +B Does not exactly correspond to any low level API function + +Gives string representation of ASN1_TIME structure. + + my $str = P_ASN1_TIME_put2string($time); + # $time - value corresponding to openssl's ASN1_TIME structure + # + # returns: datetime string like 'May 16 20:39:37 2033 GMT' + +=item * P_ASN1_UTCTIME_put2string + +B deprecated function, only for backward compatibility, just an alias +for L + +=back + +=head3 Low level API: X509_* related functions + +=over + +=item * X509_new + +B not available in Net-SSLeay-1.45 and before + +Allocates and initializes a X509 structure. + + my $rv = Net::SSLeay::X509_new(); + # + # returns: value corresponding to openssl's X509 structure (0 on failure) + +Check openssl doc L + +=item * X509_free + +Frees up the X509 structure. + + Net::SSLeay::X509_free($a); + # $a - value corresponding to openssl's X509 structure + # + # returns: no return value + +Check openssl doc L + +=item * X509_check_host + +B not available in Net-SSLeay-1.68 and before; requires at +least OpenSSL 1.0.2. X509_CHECK_FLAG_NEVER_CHECK_SUBJECT requires OpenSSL 1.1.0. + +Checks f the certificate Subject Alternative Name (SAN) or Subject CommonName +(CN) matches the specified host name. + + my $rv = Net::SSLeay::X509_check_host($cert, $name, $flags, $peername); + # $cert - value corresponding to openssl's X509 structure + # $name - host name to check + # $flags (optional, default: 0) - can be the bitwise OR of: + # &Net::SSLeay::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + # &Net::SSLeay::X509_CHECK_FLAG_NO_WILDCARDS + # &Net::SSLeay::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + # &Net::SSLeay::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS + # &Net::SSLeay::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + # &Net::SSLeay::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT + # $peername (optional) - If not omitted and $host matches $cert, + # a copy of the matching SAN or CN from + # the peer certificate is stored in $peername. + # + # returns: + # 1 for a successful match + # 0 for a failed match + # -1 for an internal error + # -2 if the input is malformed + +Check openssl doc L. + +=item * X509_check_email + +B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. + +Checks if the certificate matches the specified email address. + + my $rv = Net::SSLeay::X509_check_email($cert, $address, $flags); + # $cert - value corresponding to openssl's X509 structure + # $address - email address to check + # $flags (optional, default: 0) - see X509_check_host() + # + # returns: see X509_check_host() + +Check openssl doc L. + +=item * X509_check_ip + +B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. + +Checks if the certificate matches the specified IPv4 or IPv6 address. + + my $rv = Net::SSLeay::X509_check_email($cert, $address, $flags); + # $cert - value corresponding to openssl's X509 structure + # $address - IP address to check in binary format, in network byte order + # $flags (optional, default: 0) - see X509_check_host() + # + # returns: see X509_check_host() + +Check openssl doc L. + +=item * X509_check_ip_asc + +B not available in Net-SSLeay-1.68 and before; requires at least OpenSSL 1.0.2. + +Checks if the certificate matches the specified IPv4 or IPv6 address. + + my $rv = Net::SSLeay::X509_check_email($cert, $address, $flags); + # $cert - value corresponding to openssl's X509 structure + # $address - IP address to check in text representation + # $flags (optional, default: 0) - see X509_check_host() + # + # returns: see X509_check_host() + +Check openssl doc L. + +=item * X509_certificate_type + +B not available in Net-SSLeay-1.45 and before + +Returns bitmask with type of certificate $x. + + my $rv = Net::SSLeay::X509_certificate_type($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: (integer) bitmask with certificate type + + #to decode bitmask returned by this function use these constants: + &Net::SSLeay::EVP_PKS_DSA + &Net::SSLeay::EVP_PKS_EC + &Net::SSLeay::EVP_PKS_RSA + &Net::SSLeay::EVP_PKT_ENC + &Net::SSLeay::EVP_PKT_EXCH + &Net::SSLeay::EVP_PKT_EXP + &Net::SSLeay::EVP_PKT_SIGN + &Net::SSLeay::EVP_PK_DH + &Net::SSLeay::EVP_PK_DSA + &Net::SSLeay::EVP_PK_EC + &Net::SSLeay::EVP_PK_RSA + +=item * X509_digest + +B not available in Net-SSLeay-1.45 and before + +Computes digest/fingerprint of X509 $data using $type hash function. + + my $digest_value = Net::SSLeay::X509_digest($data, $type); + # $data - value corresponding to openssl's X509 structure + # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() + # + # returns: hash value (binary) + + #to get printable (hex) value of digest use: + print unpack('H*', $digest_value); + +=item * X509_issuer_and_serial_hash + +B not available in Net-SSLeay-1.45 and before + +Sort of a checksum of issuer name and serial number of X509 certificate $x. +The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). +The resulting value might differ across different openssl versions for the same X509 certificate. + + my $rv = Net::SSLeay::X509_issuer_and_serial_hash($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: number representing checksum + +=item * X509_issuer_name_hash + +B not available in Net-SSLeay-1.45 and before + +Sort of a checksum of issuer name of X509 certificate $x. +The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). +The resulting value might differ across different openssl versions for the same X509 certificate. + + my $rv = Net::SSLeay::X509_issuer_name_hash($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: number representing checksum + +=item * X509_subject_name_hash + +B not available in Net-SSLeay-1.45 and before + +Sort of a checksum of subject name of X509 certificate $x. +The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). +The resulting value might differ across different openssl versions for the same X509 certificate. + + my $rv = Net::SSLeay::X509_subject_name_hash($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: number representing checksum + +=item * X509_pubkey_digest + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Computes digest/fingerprint of public key from X509 certificate $data using $type hash function. + + my $digest_value = Net::SSLeay::X509_pubkey_digest($data, $type); + # $data - value corresponding to openssl's X509 structure + # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() + # + # returns: hash value (binary) + + #to get printable (hex) value of digest use: + print unpack('H*', $digest_value); + +=item * X509_set_issuer_name + +B not available in Net-SSLeay-1.45 and before + +Sets issuer of X509 certificate $x to $name. + + my $rv = Net::SSLeay::X509_set_issuer_name($x, $name); + # $x - value corresponding to openssl's X509 structure + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: 1 on success, 0 on failure + +=item * X509_set_pubkey + +B not available in Net-SSLeay-1.45 and before + +Sets public key of X509 certificate $x to $pkey. + + my $rv = Net::SSLeay::X509_set_pubkey($x, $pkey); + # $x - value corresponding to openssl's X509 structure + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: 1 on success, 0 on failure + +=item * X509_set_serialNumber + +B not available in Net-SSLeay-1.45 and before + +Sets serial number of X509 certificate $x to $serial. + + my $rv = Net::SSLeay::X509_set_serialNumber($x, $serial); + # $x - value corresponding to openssl's X509 structure + # $serial - value corresponding to openssl's ASN1_INTEGER structure + # + # returns: 1 on success, 0 on failure + + #to create $serial value use one of these: + $serial = Net::SSLeay::P_ASN1_INTEGER_set_hex('45ad6f'); + $serial = Net::SSLeay::P_ASN1_INTEGER_set_dec('7896541238529631478'); + $serial = Net::SSLeay::ASN1_INTEGER_set(45896); + +=item * X509_set_subject_name + +B not available in Net-SSLeay-1.45 and before + +Sets subject of X509 certificate $x to $name. + + my $rv = Net::SSLeay::X509_set_subject_name($x, $name); + # $x - value corresponding to openssl's X509 structure + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: 1 on success, 0 on failure + +=item * X509_set_version + +B not available in Net-SSLeay-1.45 and before + +Set 'version' value for X509 certificate $ to $version. + + my $rv = Net::SSLeay::X509_set_version($x, $version); + # $x - value corresponding to openssl's X509 structure + # $version - (integer) version number + # + # returns: 1 on success, 0 on failure + +=item * X509_sign + +B not available in Net-SSLeay-1.45 and before + +Sign X509 certificate $x with private key $pkey (using digest algorithm $md). + + my $rv = Net::SSLeay::X509_sign($x, $pkey, $md); + # $x - value corresponding to openssl's X509 structure + # $pkey - value corresponding to openssl's EVP_PKEY structure + # $md - value corresponding to openssl's EVP_MD structure + # + # returns: 1 on success, 0 on failure + +=item * X509_verify + +B not available in Net-SSLeay-1.45 and before + +Verifies X509 object $a using public key $r (pubkey of issuing CA). + + my $rv = Net::SSLeay::X509_verify($x, $r); + # $x - value corresponding to openssl's X509 structure + # $r - value corresponding to openssl's EVP_PKEY structure + # + # returns: 0 - verify failure, 1 - verify OK, <0 - error + +=item * X509_get_ext_count + +B not available in Net-SSLeay-1.45 and before + +Returns the total number of extensions in X509 object $x. + + my $rv = Net::SSLeay::X509_get_ext_count($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: count of extensions + +=item * X509_get_pubkey + +B not available in Net-SSLeay-1.45 and before + +Returns public key corresponding to given X509 object $x. + + my $rv = Net::SSLeay::X509_get_pubkey($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) + +B This method returns only the public key's key bits, without the +algorithm or parameters. Use C to return the full +public key (SPKI) instead. + +=item * X509_get_X509_PUBKEY + +B not available in Net-SSLeay-1.72 and before + +Returns the full public key (SPKI) of given X509 certificate $x. + + Net::SSLeay::X509_get_X509_PUBKEY($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: public key data in DER format (binary) + +=item * X509_get_serialNumber + +B not available in Net-SSLeay-1.45 and before + +Returns serial number of X509 certificate $x. + + my $rv = Net::SSLeay::X509_get_serialNumber($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's ASN1_INTEGER structure (0 on failure) + +See L, L or L to decode ASN1_INTEGER object. + +=item * X509_get0_serialNumber + +B available in Net-SSLeay-1.86 onwards + +X509_get0_serialNumber() is the same as X509_get_serialNumber() except it accepts a const parameter and returns a const result. + +=item * X509_get_version + +B not available in Net-SSLeay-1.45 and before + +Returns 'version' value of given X509 certificate $x. + + my $rv = Net::SSLeay::X509_get_version($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: (integer) version + +=item * X509_get_ext + +Returns X509_EXTENSION from $x509 based on given position/index. + + my $rv = Net::SSLeay::X509_get_ext($x509, $index); + # $x509 - value corresponding to openssl's X509 structure + # $index - (integer) position/index of extension within $x509 + # + # returns: value corresponding to openssl's X509_EXTENSION structure (0 on failure) + +=item * X509_get_ext_by_NID + +Returns X509_EXTENSION from $x509 based on given NID. + + my $rv = Net::SSLeay::X509_get_ext_by_NID($x509, $nid, $loc); + # $x509 - value corresponding to openssl's X509 structure + # $nid - (integer) NID value + # $loc - (integer) position to start lookup at + # + # returns: position/index of extension, negative value on error + # call Net::SSLeay::X509_get_ext($x509, $rv) to get the actual extension + +=item * X509_get_fingerprint + +Returns fingerprint of certificate $cert. + +B Does not exactly correspond to any low level API function. The implementation +is basen on openssl's C. + + Net::SSLeay::X509_get_fingerprint($x509, $type); + # $x509 - value corresponding to openssl's X509 structure + # $type - (string) digest type, currently supported values: + # "md5" + # "sha1" + # "sha256" + # "ripemd160" + # + # returns: certificate digest - hexadecimal string (NOT binary data!) + +=item * X509_get_issuer_name + +Return an X509_NAME object representing the issuer of the certificate $cert. + + my $rv = Net::SSLeay::X509_get_issuer_name($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's X509_NAME structure (0 on failure) + +=item * X509_get_notAfter + +Return an object giving the time after which the certificate $cert is not valid. + + my $rv = Net::SSLeay::X509_get_notAfter($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) + +To get human readable/printable form the return value you can use: + + my $time = Net::SSLeay::X509_get_notAfter($cert); + print "notAfter=", Net::SSLeay::P_ASN1_TIME_get_isotime($time), "\n"; + +=item * X509_get_notBefore + +Return an object giving the time before which the certificate $cert is not valid + + my $rv = Net::SSLeay::X509_get_notBefore($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) + +To get human readable/printable form the return value you can use: + + my $time = Net::SSLeay::X509_get_notBefore($cert); + print "notBefore=", Net::SSLeay::P_ASN1_TIME_get_isotime($time), "\n"; + +=item * X509_get_subjectAltNames + +B Does not exactly correspond to any low level API function. + +Returns the list of alternative subject names from X509 certificate $cert. + + my @rv = Net::SSLeay::X509_get_subjectAltNames($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: list containing pairs - name_type (integer), name_value (string) + # where name_type can be: + # 0 - GEN_OTHERNAME + # 1 - GEN_EMAIL + # 2 - GEN_DNS + # 3 - GEN_X400 + # 4 - GEN_DIRNAME + # 5 - GEN_EDIPARTY + # 6 - GEN_URI + # 7 - GEN_IPADD + # 8 - GEN_RID + +Note: type 7 - GEN_IPADD contains the IP address as a packed binary address. + +=item * X509_get_subject_name + +Returns the subject of the certificate $cert. + + my $rv = Net::SSLeay::X509_get_subject_name($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's X509_NAME structure (0 on failure) + +=item * X509_gmtime_adj + +Adjust th ASN1_TIME object to the timestamp (in GMT). + + my $rv = Net::SSLeay::X509_gmtime_adj($s, $adj); + # $s - value corresponding to openssl's ASN1_TIME structure + # $adj - timestamp (seconds since 1.1.1970) + # + # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) + +B this function may fail for dates after 2038 as it is dependent on time_t size on your +system (32bit time_t does not work after 2038). Consider using L instead). + +=item * X509_load_cert_crl_file + +Takes PEM file and loads all X509 certificates and X509 CRLs from that file into X509_LOOKUP structure. + + my $rv = Net::SSLeay::X509_load_cert_crl_file($ctx, $file, $type); + # $ctx - value corresponding to openssl's X509_LOOKUP structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # if not FILETYPE_PEM then behaves as Net::SSLeay::X509_load_cert_file() + # + # returns: 1 on success, 0 on failure + +=item * X509_load_cert_file + +Loads/adds X509 certificate from $file to X509_LOOKUP structure + + my $rv = Net::SSLeay::X509_load_cert_file($ctx, $file, $type); + # $ctx - value corresponding to openssl's X509_LOOKUP structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, 0 on failure + +=item * X509_load_crl_file + +Loads/adds X509 CRL from $file to X509_LOOKUP structure + + my $rv = Net::SSLeay::X509_load_crl_file($ctx, $file, $type); + # $ctx - value corresponding to openssl's X509_LOOKUP structure + # $file - (string) file name + # $type - (integer) type - use constants &Net::SSLeay::FILETYPE_PEM or &Net::SSLeay::FILETYPE_ASN1 + # + # returns: 1 on success, 0 on failure + +=item * X509_policy_level_get0_node + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_level_get0_node($level, $i); + # $level - value corresponding to openssl's X509_POLICY_LEVEL structure + # $i - (integer) index/position + # + # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) + +=item * X509_policy_level_node_count + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_level_node_count($level); + # $level - value corresponding to openssl's X509_POLICY_LEVEL structure + # + # returns: (integer) node count + +=item * X509_policy_node_get0_parent + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_node_get0_parent($node); + # $node - value corresponding to openssl's X509_POLICY_NODE structure + # + # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) + +=item * X509_policy_node_get0_policy + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_node_get0_policy($node); + # $node - value corresponding to openssl's X509_POLICY_NODE structure + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +=item * X509_policy_node_get0_qualifiers + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_node_get0_qualifiers($node); + # $node - value corresponding to openssl's X509_POLICY_NODE structure + # + # returns: value corresponding to openssl's STACK_OF(POLICYQUALINFO) structure (0 on failure) + +=item * X509_policy_tree_free + +??? (more info needed) + + Net::SSLeay::X509_policy_tree_free($tree); + # $tree - value corresponding to openssl's X509_POLICY_TREE structure + # + # returns: no return value + +=item * X509_policy_tree_get0_level + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_tree_get0_level($tree, $i); + # $tree - value corresponding to openssl's X509_POLICY_TREE structure + # $i - (integer) level index + # + # returns: value corresponding to openssl's X509_POLICY_LEVEL structure (0 on failure) + +=item * X509_policy_tree_get0_policies + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_tree_get0_policies($tree); + # $tree - value corresponding to openssl's X509_POLICY_TREE structure + # + # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) + +=item * X509_policy_tree_get0_user_policies + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_tree_get0_user_policies($tree); + # $tree - value corresponding to openssl's X509_POLICY_TREE structure + # + # returns: value corresponding to openssl's X509_POLICY_NODE structure (0 on failure) + +=item * X509_policy_tree_level_count + +??? (more info needed) + + my $rv = Net::SSLeay::X509_policy_tree_level_count($tree); + # $tree - value corresponding to openssl's X509_POLICY_TREE structure + # + # returns: (integer) count + +=item * X509_verify_cert_error_string + +Returns a human readable error string for verification error $n. + + my $rv = Net::SSLeay::X509_verify_cert_error_string($n); + # $n - (long) numeric error code + # + # returns: error string + +Check openssl doc L + +=item * P_X509_add_extensions + +B not available in Net-SSLeay-1.45 and before + +Adds one or more X509 extensions to X509 object $x. + + my $rv = Net::SSLeay::P_X509_add_extensions($x, $ca_cert, $nid, $value); + # $x - value corresponding to openssl's X509 structure + # $ca_cert - value corresponding to openssl's X509 structure (issuer's cert - necessary for sertting NID_authority_key_identifier) + # $nid - NID identifying extension to be set + # $value - extension value + # + # returns: 1 on success, 0 on failure + +You can set more extensions at once: + + my $rv = Net::SSLeay::P_X509_add_extensions($x509, $ca_cert, + &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', + &Net::SSLeay::NID_subject_key_identifier => 'hash', + &Net::SSLeay::NID_authority_key_identifier => 'keyid', + &Net::SSLeay::NID_authority_key_identifier => 'issuer', + &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', + &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', + &Net::SSLeay::NID_netscape_cert_type => 'server', + &Net::SSLeay::NID_subject_alt_name => 'DNS:s1.dom.com,DNS:s2.dom.com,DNS:s3.dom.com', + ); + +=item * P_X509_copy_extensions + +B not available in Net-SSLeay-1.45 and before + +Copies X509 extensions from X509_REQ object to X509 object - handy when you need to turn X509_REQ into X509 certificate. + + Net::SSLeay::P_X509_copy_extensions($x509_req, $x509, $override); + # $x509_req - value corresponding to openssl's X509_REQ structure + # $x509 - value corresponding to openssl's X509 structure + # $override - (integer) flag indication whether to override already existing items in $x509 (default 1) + # + # returns: 1 on success, 0 on failure + +=item * P_X509_get_crl_distribution_points + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Get the list of CRL distribution points from X509 certificate. + + my @cdp = Net::SSLeay::P_X509_get_crl_distribution_points($x509); + # $x509 - value corresponding to openssl's X509 structure + # + # returns: list of distribution points (usually URLs) + +=item * P_X509_get_ext_key_usage + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Gets the list of extended key usage of given X509 certificate $cert. + + my @ext_usage = Net::SSLeay::P_X509_get_ext_key_usage($cert, $format); + # $cert - value corresponding to openssl's X509 structure + # $format - choose type of return values: 0=OIDs, 1=NIDs, 2=shortnames, 3=longnames + # + # returns: list of values + +Examples: + + my @extkeyusage_oid = Net::SSLeay::P_X509_get_ext_key_usage($x509,0); + # returns for example: ("1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2") + + my @extkeyusage_nid = Net::SSLeay::P_X509_get_ext_key_usage($x509,1); + # returns for example: (129, 130) + + my @extkeyusage_sn = Net::SSLeay::P_X509_get_ext_key_usage($x509,2); + # returns for example: ("serverAuth", "clientAuth") + + my @extkeyusage_ln = Net::SSLeay::P_X509_get_ext_key_usage($x509,3); + # returns for example: ("TLS Web Server Authentication", "TLS Web Client Authentication") + +=item * P_X509_get_key_usage + +B not available in Net-SSLeay-1.45 and before + +Gets the list of key usage of given X509 certificate $cert. + + my @keyusage = Net::SSLeay::P_X509_get_key_usage($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: list of key usage values which can be none, one or more from the following list: + # "digitalSignature" + # "nonRepudiation" + # "keyEncipherment" + # "dataEncipherment" + # "keyAgreement" + # "keyCertSign" + # "cRLSign" + # "encipherOnly" + # "decipherOnly" + +=item * P_X509_get_netscape_cert_type + +B not available in Net-SSLeay-1.45 and before + +Gets the list of Netscape cert types of given X509 certificate $cert. + + Net::SSLeay::P_X509_get_netscape_cert_type($cert); + # $cert - value corresponding to openssl's X509 structure + # + # returns: list of Netscape type values which can be none, one or more from the following list: + # "client" + # "server" + # "email" + # "objsign" + # "reserved" + # "sslCA" + # "emailCA" + # "objCA" + +=item * P_X509_get_pubkey_alg + +B not available in Net-SSLeay-1.45 and before + +Returns ASN1_OBJECT corresponding to X509 certificate public key algorithm. + + my $rv = Net::SSLeay::P_X509_get_pubkey_alg($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +To get textual representation use: + + my $alg = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_pubkey_alg($x509)); + # returns for example: "rsaEncryption" + +=item * P_X509_get_signature_alg + +B not available in Net-SSLeay-1.45 and before + +Returns ASN1_OBJECT corresponding to X509 signarite key algorithm. + + my $rv = Net::SSLeay::P_X509_get_signature_alg($x); + # $x - value corresponding to openssl's X509 structure + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +To get textual representation use: + + my $alg = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_signature_alg($x509)) + # returns for example: "sha1WithRSAEncryption" + +=item * sk_X509_new_null + +Returns a new, empty, STACK_OF(X509) structure. + + my $rv = Net::SSLeay::sk_X509_new_null(); + # + # returns: value corresponding to openssl's STACK_OF(X509) structure + +=item * sk_X509_push + +Pushes an X509 structure onto a STACK_OF(X509) structure. + + my $rv = Net::SSLeay::sk_X509_push($sk_x509, $x509); + # $sk_x509 - value corresponding to openssl's STACK_OF(X509) structure + # $x509 - value corresponding to openssl's X509 structure + # + # returns: 1 if successful, 0 if unsuccessful + +=back + +=head3 Low level API: X509_REQ_* related functions + +=over + +=item * X509_REQ_new + +B not available in Net-SSLeay-1.45 and before + +Creates a new X509_REQ structure. + + my $rv = Net::SSLeay::X509_REQ_new(); + # + # returns: value corresponding to openssl's X509_REQ structure (0 on failure) + +=item * X509_REQ_free + +B not available in Net-SSLeay-1.45 and before + +Free an allocated X509_REQ structure. + + Net::SSLeay::X509_REQ_free($x); + # $x - value corresponding to openssl's X509_REQ structure + # + # returns: no return value + +=item * X509_REQ_add1_attr_by_NID + +B not available in Net-SSLeay-1.45 and before + +Adds an attribute whose name is defined by a NID $nid. The field value to be added is in $bytes. + + my $rv = Net::SSLeay::X509_REQ_add1_attr_by_NID($req, $nid, $type, $bytes); + # $req - value corresponding to openssl's X509_REQ structure + # $nid - (integer) NID value + # $type - (integer) type of data in $bytes (see below) + # $bytes - data to be set + # + # returns: 1 on success, 0 on failure + + # values for $type - use constants: + &Net::SSLeay::MBSTRING_UTF8 - $bytes contains utf8 encoded data + &Net::SSLeay::MBSTRING_ASC - $bytes contains ASCII data + +=item * X509_REQ_digest + +B not available in Net-SSLeay-1.45 and before + +Computes digest/fingerprint of X509_REQ $data using $type hash function. + + my $digest_value = Net::SSLeay::X509_REQ_digest($data, $type); + # $data - value corresponding to openssl's X509_REQ structure + # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() + # + # returns: hash value (binary) + + #to get printable (hex) value of digest use: + print unpack('H*', $digest_value); + +=item * X509_REQ_get_attr_by_NID + +B not available in Net-SSLeay-1.45 and before + +Retrieve the next index matching $nid after $lastpos ($lastpos should initially be set to -1). + + my $rv = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid, $lastpos=-1); + # $req - value corresponding to openssl's X509_REQ structure + # $nid - (integer) NID value + # $lastpos - [optional] (integer) index where to start search (default -1) + # + # returns: index (-1 if there are no more entries) + +Note: use L to get the actual attribute value - e.g. + + my $index = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid); + my @attr_values = Net::SSLeay::P_X509_REQ_get_attr($req, $index); + +=item * X509_REQ_get_attr_by_OBJ + +B not available in Net-SSLeay-1.45 and before + +Retrieve the next index matching $obj after $lastpos ($lastpos should initially be set to -1). + + my $rv = Net::SSLeay::X509_REQ_get_attr_by_OBJ($req, $obj, $lastpos=-1); + # $req - value corresponding to openssl's X509_REQ structure + # $obj - value corresponding to openssl's ASN1_OBJECT structure + # $lastpos - [optional] (integer) index where to start search (default -1) + # + # returns: index (-1 if there are no more entries) + +Note: use L to get the actual attribute value - e.g. + + my $index = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid); + my @attr_values = Net::SSLeay::P_X509_REQ_get_attr($req, $index); + +=item * X509_REQ_get_attr_count + +B not available in Net-SSLeay-1.45 and before + +Returns the total number of attributes in $req. + + my $rv = Net::SSLeay::X509_REQ_get_attr_count($req); + # $req - value corresponding to openssl's X509_REQ structure + # + # returns: (integer) items count + +=item * X509_REQ_get_pubkey + +B not available in Net-SSLeay-1.45 and before + +Returns public key corresponding to given X509_REQ object $x. + + my $rv = Net::SSLeay::X509_REQ_get_pubkey($x); + # $x - value corresponding to openssl's X509_REQ structure + # + # returns: value corresponding to openssl's EVP_PKEY structure (0 on failure) + +=item * X509_REQ_get_subject_name + +B not available in Net-SSLeay-1.45 and before + +Returns X509_NAME object corresponding to subject name of given X509_REQ object $x. + + my $rv = Net::SSLeay::X509_REQ_get_subject_name($x); + # $x - value corresponding to openssl's X509_REQ structure + # + # returns: value corresponding to openssl's X509_NAME structure (0 on failure) + +=item * X509_REQ_get_version + +B not available in Net-SSLeay-1.45 and before + +Returns 'version' value for given X509_REQ object $x. + + my $rv = Net::SSLeay::X509_REQ_get_version($x); + # $x - value corresponding to openssl's X509_REQ structure + # + # returns: (integer) version e.g. 0 = "version 1" + +=item * X509_REQ_set_pubkey + +B not available in Net-SSLeay-1.45 and before + +Sets public key of given X509_REQ object $x to $pkey. + + my $rv = Net::SSLeay::X509_REQ_set_pubkey($x, $pkey); + # $x - value corresponding to openssl's X509_REQ structure + # $pkey - value corresponding to openssl's EVP_PKEY structure + # + # returns: 1 on success, 0 on failure + +=item * X509_REQ_set_subject_name + +B not available in Net-SSLeay-1.45 and before + +Sets subject name of given X509_REQ object $x to X509_NAME object $name. + + my $rv = Net::SSLeay::X509_REQ_set_subject_name($x, $name); + # $x - value corresponding to openssl's X509_REQ structure + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: 1 on success, 0 on failure + +=item * X509_REQ_set_version + +B not available in Net-SSLeay-1.45 and before + +Sets 'version' of given X509_REQ object $x to $version. + + my $rv = Net::SSLeay::X509_REQ_set_version($x, $version); + # $x - value corresponding to openssl's X509_REQ structure + # $version - (integer) e.g. 0 = "version 1" + # + # returns: 1 on success, 0 on failure + +=item * X509_REQ_sign + +B not available in Net-SSLeay-1.45 and before + +Sign X509_REQ object $x with private key $pk (using digest algorithm $md). + + my $rv = Net::SSLeay::X509_REQ_sign($x, $pk, $md); + # $x - value corresponding to openssl's X509_REQ structure + # $pk - value corresponding to openssl's EVP_PKEY structure (requestor's private key) + # $md - value corresponding to openssl's EVP_MD structure + # + # returns: 1 on success, 0 on failure + +=item * X509_REQ_verify + +B not available in Net-SSLeay-1.45 and before + +Verifies X509_REQ object $x using public key $r (pubkey of requesting party). + + my $rv = Net::SSLeay::X509_REQ_verify($x, $r); + # $x - value corresponding to openssl's X509_REQ structure + # $r - value corresponding to openssl's EVP_PKEY structure + # + # returns: 0 - verify failure, 1 - verify OK, <0 - error + +=item * P_X509_REQ_add_extensions + +B not available in Net-SSLeay-1.45 and before + +Adds one or more X509 extensions to X509_REQ object $x. + + my $rv = Net::SSLeay::P_X509_REQ_add_extensions($x, $nid, $value); + # $x - value corresponding to openssl's X509_REQ structure + # $nid - NID identifying extension to be set + # $value - extension value + # + # returns: 1 on success, 0 on failure + +You can set more extensions at once: + + my $rv = Net::SSLeay::P_X509_REQ_add_extensions($x509_req, + &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', + &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', + &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', + &Net::SSLeay::NID_netscape_cert_type => 'server', + &Net::SSLeay::NID_subject_alt_name => 'DNS:s1.com,DNS:s2.com', + &Net::SSLeay::NID_crl_distribution_points => 'URI:http://pki.com/crl1,URI:http://pki.com/crl2', + ); + +=item * P_X509_REQ_get_attr + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Returns attribute value for X509_REQ's attribute at index $n. + + Net::SSLeay::P_X509_REQ_get_attr($req, $n); + # $req - value corresponding to openssl's X509_REQ structure + # $n - (integer) attribute index + # + # returns: value corresponding to openssl's ASN1_STRING structure + +=back + +=head3 Low level API: X509_CRL_* related functions + +=over + +=item * X509_CRL_new + +B not available in Net-SSLeay-1.45 and before + +Creates a new X509_CRL structure. + + my $rv = Net::SSLeay::X509_CRL_new(); + # + # returns: value corresponding to openssl's X509_CRL structure (0 on failure) + +=item * X509_CRL_free + +B not available in Net-SSLeay-1.45 and before + +Free an allocated X509_CRL structure. + + Net::SSLeay::X509_CRL_free($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: no return value + +=item * X509_CRL_digest + +B not available in Net-SSLeay-1.45 and before + +Computes digest/fingerprint of X509_CRL $data using $type hash function. + + my $digest_value = Net::SSLeay::X509_CRL_digest($data, $type); + # $data - value corresponding to openssl's X509_CRL structure + # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() + # + # returns: hash value (binary) + +Example: + + my $x509_crl + my $md = Net::SSLeay::EVP_get_digestbyname("sha1"); + my $digest_value = Net::SSLeay::X509_CRL_digest($x509_crl, $md); + #to get printable (hex) value of digest use: + print "digest=", unpack('H*', $digest_value), "\n"; + +=item * X509_CRL_get_ext + +B not available in Net-SSLeay-1.54 and before + +Returns X509_EXTENSION from $x509 based on given position/index. + + my $rv = Net::SSLeay::X509_CRL_get_ext($x509, $index); + # $x509 - value corresponding to openssl's X509_CRL structure + # $index - (integer) position/index of extension within $x509 + # + # returns: value corresponding to openssl's X509_EXTENSION structure (0 on failure) + +=item * X509_CRL_get_ext_by_NID + +B not available in Net-SSLeay-1.54 and before + +Returns X509_EXTENSION from $x509 based on given NID. + + my $rv = Net::SSLeay::X509_CRL_get_ext_by_NID($x509, $nid, $loc); + # $x509 - value corresponding to openssl's X509_CRL structure + # $nid - (integer) NID value + # $loc - (integer) position to start lookup at + # + # returns: position/index of extension, negative value on error + # call Net::SSLeay::X509_CRL_get_ext($x509, $rv) to get the actual extension + +=item * X509_CRL_get_ext_count + +B not available in Net-SSLeay-1.54 and before + +Returns the total number of extensions in X509_CRL object $x. + + my $rv = Net::SSLeay::X509_CRL_get_ext_count($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: count of extensions + +=item * X509_CRL_get_issuer + +B not available in Net-SSLeay-1.45 and before + +Returns X509_NAME object corresponding to the issuer of X509_CRL $x. + + my $rv = Net::SSLeay::X509_CRL_get_issuer($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: value corresponding to openssl's X509_NAME structure (0 on failure) + +See other C functions to get more info from X509_NAME structure. + +=item * X509_CRL_get_lastUpdate + +B not available in Net-SSLeay-1.45 and before + +Returns 'lastUpdate' date-time value of X509_CRL object $x. + + my $rv = Net::SSLeay::X509_CRL_get_lastUpdate($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) + +=item * X509_CRL_get_nextUpdate + +B not available in Net-SSLeay-1.45 and before + +Returns 'nextUpdate' date-time value of X509_CRL object $x. + + my $rv = Net::SSLeay::X509_CRL_get_nextUpdate($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: value corresponding to openssl's ASN1_TIME structure (0 on failure) + +=item * X509_CRL_get_version + +B not available in Net-SSLeay-1.45 and before + +Returns 'version' value of given X509_CRL structure $x. + + my $rv = Net::SSLeay::X509_CRL_get_version($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: (integer) version + +=item * X509_CRL_set_issuer_name + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Sets the issuer of X509_CRL object $x to X509_NAME object $name. + + my $rv = Net::SSLeay::X509_CRL_set_issuer_name($x, $name); + # $x - value corresponding to openssl's X509_CRL structure + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: 1 on success, 0 on failure + +=item * X509_CRL_set_lastUpdate + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Sets 'lastUpdate' value of X509_CRL object $x to $tm. + + my $rv = Net::SSLeay::X509_CRL_set_lastUpdate($x, $tm); + # $x - value corresponding to openssl's X509_CRL structure + # $tm - value corresponding to openssl's ASN1_TIME structure + # + # returns: 1 on success, 0 on failure + +=item * X509_CRL_set_nextUpdate + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Sets 'nextUpdate' value of X509_CRL object $x to $tm. + + my $rv = Net::SSLeay::X509_CRL_set_nextUpdate($x, $tm); + # $x - value corresponding to openssl's X509_CRL structure + # $tm - value corresponding to openssl's ASN1_TIME structure + # + # returns: 1 on success, 0 on failure + +=item * X509_CRL_set_version + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Sets 'version' value of given X509_CRL structure $x to $version. + + my $rv = Net::SSLeay::X509_CRL_set_version($x, $version); + # $x - value corresponding to openssl's X509_CRL structure + # $version - (integer) version number (1 = version 2 CRL) + # + # returns: 1 on success, 0 on failure + +Note that if you want to use any X509_CRL extension you need to set "version 2 CRL" - C. + +=item * X509_CRL_sign + +B not available in Net-SSLeay-1.45 and before + +Sign X509_CRL object $x with private key $pkey (using digest algorithm $md). + + my $rv = Net::SSLeay::X509_CRL_sign($x, $pkey, $md); + # $x - value corresponding to openssl's X509_CRL structure + # $pkey - value corresponding to openssl's EVP_PKEY structure + # $md - value corresponding to openssl's EVP_MD structure + # + # returns: 1 on success, 0 on failure + +=item * X509_CRL_sort + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Sorts the data of X509_CRL object so it will be written in serial number order. + + my $rv = Net::SSLeay::X509_CRL_sort($x); + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: 1 on success, 0 on failure + +=item * X509_CRL_verify + +B not available in Net-SSLeay-1.45 and before + +Verifies X509_CRL object $a using public key $r (pubkey of issuing CA). + + my $rv = Net::SSLeay::X509_CRL_verify($a, $r); + # $a - value corresponding to openssl's X509_CRL structure + # $r - value corresponding to openssl's EVP_PKEY structure + # + # returns: 0 - verify failure, 1 - verify OK, <0 - error + +=item * P_X509_CRL_add_revoked_serial_hex + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Adds given serial number $serial_hex to X509_CRL object $crl. + + Net::SSLeay::P_X509_CRL_add_revoked_serial_hex($crl, $serial_hex, $rev_time, $reason_code, $comp_time); + # $crl - value corresponding to openssl's X509_CRL structure + # $serial_hex - string (hexadecimal) representation of serial number + # $rev_time - (revocation time) value corresponding to openssl's ASN1_TIME structure + # $reason_code - [optional] (integer) reason code (see below) - default 0 + # $comp_time - [optional] (compromise time) value corresponding to openssl's ASN1_TIME structure + # + # returns: no return value + + reason codes: + 0 - unspecified + 1 - keyCompromise + 2 - CACompromise + 3 - affiliationChanged + 4 - superseded + 5 - cessationOfOperation + 6 - certificateHold + 7 - removeFromCRL + +=item * P_X509_CRL_get_serial + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Returns serial number of X509_CRL object. + + my $rv = Net::SSLeay::P_X509_CRL_get_serial($crl); + # $crl - value corresponding to openssl's X509_CRL structure + # + # returns: value corresponding to openssl's ASN1_INTEGER structure (0 on failure) + +=item * P_X509_CRL_set_serial + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.7 + +Sets serial number of X509_CRL object to $crl_number. + + my $rv = Net::SSLeay::P_X509_CRL_set_serial($crl, $crl_number); + # $crl - value corresponding to openssl's X509_CRL structure + # $crl_number - value corresponding to openssl's ASN1_INTEGER structure + # + # returns: 1 on success, 0 on failure + +=back + +=head3 Low level API: X509_EXTENSION_* related functions + +=over + +=item * X509_EXTENSION_get_critical + +B not available in Net-SSLeay-1.45 and before + +Returns 'critical' flag of given X509_EXTENSION object $ex. + + my $rv = Net::SSLeay::X509_EXTENSION_get_critical($ex); + # $ex - value corresponding to openssl's X509_EXTENSION structure + # + # returns: (integer) 1 - critical, 0 - noncritical + +=item * X509_EXTENSION_get_data + +B not available in Net-SSLeay-1.45 and before + +Returns value (raw data) of X509_EXTENSION object $ne. + + my $rv = Net::SSLeay::X509_EXTENSION_get_data($ne); + # $ne - value corresponding to openssl's X509_EXTENSION structure + # + # returns: value corresponding to openssl's ASN1_OCTET_STRING structure (0 on failure) + +Note: you can use L to convert ASN1_OCTET_STRING into perl scalar variable. + +=item * X509_EXTENSION_get_object + +B not available in Net-SSLeay-1.45 and before + +Returns OID (ASN1_OBJECT) of X509_EXTENSION object $ne. + + my $rv = Net::SSLeay::X509_EXTENSION_get_object($ex); + # $ex - value corresponding to openssl's X509_EXTENSION structure + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +=item * X509V3_EXT_print + +B not available in Net-SSLeay-1.45 and before + +Returns string representation of given X509_EXTENSION object $ext. + + Net::SSLeay::X509V3_EXT_print($ext, $flags, $utf8_decode); + # $ext - value corresponding to openssl's X509_EXTENSION structure + # $flags - [optional] (integer) Currently the flag argument is unused and should be set to 0 + # $utf8_decode - [optional] 0 or 1 whether the returned value should be utf8 decoded (default=0) + # + # returns: no return value + +=item * X509V3_EXT_d2i + +Parses an extension and returns its internal structure. + + my $rv = Net::SSLeay::X509V3_EXT_d2i($ext); + # $ext - value corresponding to openssl's X509_EXTENSION structure + # + # returns: pointer ??? + +=back + +=head3 Low level API: X509_NAME_* related functions + +=over + +=item * X509_NAME_ENTRY_get_data + +B not available in Net-SSLeay-1.45 and before + +Retrieves the field value of $ne in and ASN1_STRING structure. + + my $rv = Net::SSLeay::X509_NAME_ENTRY_get_data($ne); + # $ne - value corresponding to openssl's X509_NAME_ENTRY structure + # + # returns: value corresponding to openssl's ASN1_STRING structure (0 on failure) + +Check openssl doc L + +=item * X509_NAME_ENTRY_get_object + +B not available in Net-SSLeay-1.45 and before + +Retrieves the field name of $ne in and ASN1_OBJECT structure. + + my $rv = Net::SSLeay::X509_NAME_ENTRY_get_object($ne); + # $ne - value corresponding to openssl's X509_NAME_ENTRY structure + # + # returns: value corresponding to openssl's ASN1_OBJECT structure (0 on failure) + +Check openssl doc L + +=item * X509_NAME_new + +B not available in Net-SSLeay-1.55 and before; requires at least openssl-0.9.5 + +Creates a new X509_NAME structure. +Adds a field whose name is defined by a string $field. The field value to be added is in $bytes. + + my $rv = Net::SSLeay::X509_NAME_new(); + # + # returns: value corresponding to openssl's X509_NAME structure (0 on failure) + +=item * X509_NAME_hash + +B not available in Net-SSLeay-1.55 and before; requires at least openssl-0.9.5 + +Sort of a checksum of issuer name $name. +The result is not a full hash (e.g. sha-1), it is kind-of-a-hash truncated to the size of 'unsigned long' (32 bits). +The resulting value might differ across different openssl versions for the same X509 certificate. + + my $rv = Net::SSLeay::X509_NAME_hash($name); + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: number representing checksum + +=item * X509_NAME_add_entry_by_txt + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.5 + +Adds a field whose name is defined by a string $field. The field value to be added is in $bytes. + + my $rv = Net::SSLeay::X509_NAME_add_entry_by_txt($name, $field, $type, $bytes, $len, $loc, $set); + # $name - value corresponding to openssl's X509_NAME structure + # $field - (string) field definition (name) - e.g. "organizationName" + # $type - (integer) type of data in $bytes (see below) + # $bytes - data to be set + # $loc - [optional] (integer) index where the new entry is inserted: if it is -1 (default) it is appended + # $set - [optional] (integer) determines how the new type is added. If it is 0 (default) a new RDN is created + # + # returns: 1 on success, 0 on failure + + # values for $type - use constants: + &Net::SSLeay::MBSTRING_UTF8 - $bytes contains utf8 encoded data + &Net::SSLeay::MBSTRING_ASC - $bytes contains ASCII data + +Unicode note: when passing non-ascii (unicode) string in $bytes do not forget to set C<$flags = &Net::SSLeay::MBSTRING_UTF8> and encode the perl $string via C<$bytes = encode('utf-8', $string)>. + +Check openssl doc L + +=item * X509_NAME_add_entry_by_NID + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.5 + +Adds a field whose name is defined by a NID $nid. The field value to be added is in $bytes. + + my $rv = Net::SSLeay::X509_NAME_add_entry_by_NID($name, $nid, $type, $bytes, $len, $loc, $set); + # $name - value corresponding to openssl's X509_NAME structure + # $nid - (integer) field definition - NID value + # $type - (integer) type of data in $bytes (see below) + # $bytes - data to be set + # $loc - [optional] (integer) index where the new entry is inserted: if it is -1 (default) it is appended + # $set - [optional] (integer) determines how the new type is added. If it is 0 (default) a new RDN is created + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_NAME_add_entry_by_OBJ + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-0.9.5 + +Adds a field whose name is defined by a object (OID) $obj . The field value to be added is in $bytes. + + my $rv = Net::SSLeay::X509_NAME_add_entry_by_OBJ($name, $obj, $type, $bytes, $len, $loc, $set); + # $name - value corresponding to openssl's X509_NAME structure + # $obj - field definition - value corresponding to openssl's ASN1_OBJECT structure + # $type - (integer) type of data in $bytes (see below) + # $bytes - data to be set + # $loc - [optional] (integer) index where the new entry is inserted: if it is -1 (default) it is appended + # $set - [optional] (integer) determines how the new type is added. If it is 0 (default) a new RDN is created + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_NAME_cmp + +B not available in Net-SSLeay-1.45 and before + +Compares two X509_NAME obejcts. + + my $rv = Net::SSLeay::X509_NAME_cmp($a, $b); + # $a - value corresponding to openssl's X509_NAME structure + # $b - value corresponding to openssl's X509_NAME structure + # + # returns: 0 if $a matches $b; non zero otherwise + +=item * X509_NAME_digest + +B not available in Net-SSLeay-1.45 and before + +Computes digest/fingerprint of X509_NAME $data using $type hash function. + + my $digest_value = Net::SSLeay::X509_NAME_digest($data, $type); + # $data - value corresponding to openssl's X509_NAME structure + # $type - value corresponding to openssl's EVP_MD structure - e.g. got via EVP_get_digestbyname() + # + # returns: hash value (binary) + + #to get printable (hex) value of digest use: + print unpack('H*', $digest_value); + +=item * X509_NAME_entry_count + +B not available in Net-SSLeay-1.45 and before + +Returns the total number of entries in $name. + + my $rv = Net::SSLeay::X509_NAME_entry_count($name); + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: (integer) entries count + +Check openssl doc L + +=item * X509_NAME_get_entry + +B not available in Net-SSLeay-1.45 and before + +Retrieves the X509_NAME_ENTRY from $name corresponding to index $loc. Acceptable values for $loc run +from 0 to C. The value returned is an internal pointer which must not be freed. + + my $rv = Net::SSLeay::X509_NAME_get_entry($name, $loc); + # $name - value corresponding to openssl's X509_NAME structure + # $loc - (integer) index of wanted entry + # + # returns: value corresponding to openssl's X509_NAME_ENTRY structure (0 on failure) + +Check openssl doc L + +=item * X509_NAME_print_ex + +B not available in Net-SSLeay-1.45 and before + +Returns a string with human readable version of $name. + + Net::SSLeay::X509_NAME_print_ex($name, $flags, $utf8_decode); + # $name - value corresponding to openssl's X509_NAME structure + # $flags - [optional] conversion flags (default XN_FLAG_RFC2253) - see below + # $utf8_decode - [optional] 0 or 1 whether the returned value should be utf8 decoded (default=0) + # + # returns: string representation of $name + + #available conversion flags - use constants: + &Net::SSLeay::XN_FLAG_COMPAT + &Net::SSLeay::XN_FLAG_DN_REV + &Net::SSLeay::XN_FLAG_DUMP_UNKNOWN_FIELDS + &Net::SSLeay::XN_FLAG_FN_ALIGN + &Net::SSLeay::XN_FLAG_FN_LN + &Net::SSLeay::XN_FLAG_FN_MASK + &Net::SSLeay::XN_FLAG_FN_NONE + &Net::SSLeay::XN_FLAG_FN_OID + &Net::SSLeay::XN_FLAG_FN_SN + &Net::SSLeay::XN_FLAG_MULTILINE + &Net::SSLeay::XN_FLAG_ONELINE + &Net::SSLeay::XN_FLAG_RFC2253 + &Net::SSLeay::XN_FLAG_SEP_COMMA_PLUS + &Net::SSLeay::XN_FLAG_SEP_CPLUS_SPC + &Net::SSLeay::XN_FLAG_SEP_MASK + &Net::SSLeay::XN_FLAG_SEP_MULTILINE + &Net::SSLeay::XN_FLAG_SEP_SPLUS_SPC + &Net::SSLeay::XN_FLAG_SPC_EQ + +Most likely you will be fine with default: + + Net::SSLeay::X509_NAME_print_ex($name, &Net::SSLeay::XN_FLAG_RFC2253); + +Or you might want RFC2253-like output without utf8 chars escaping: + + use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/; + my $flag_rfc22536_utf8 = (XN_FLAG_RFC2253) & (~ ASN1_STRFLGS_ESC_MSB); + my $result = Net::SSLeay::X509_NAME_print_ex($name, $flag_rfc22536_utf8, 1); + +Check openssl doc L + +=item * X509_NAME_get_text_by_NID + +Retrieves the text from the first entry in name which matches $nid, if no +such entry exists -1 is returned. + +B this is a legacy function which has various limitations which +makes it of minimal use in practice. It can only find the first matching +entry and will copy the contents of the field verbatim: this can be highly +confusing if the target is a multicharacter string type like a BMPString or a UTF8String. + + Net::SSLeay::X509_NAME_get_text_by_NID($name, $nid); + # $name - value corresponding to openssl's X509_NAME structure + # $nid - NID value (integer) + # + # returns: text value + +Check openssl doc L + +=item * X509_NAME_oneline + +Return an ASCII version of $name. + + Net::SSLeay::X509_NAME_oneline($name); + # $name - value corresponding to openssl's X509_NAME structure + # + # returns: (string) ASCII version of $name + +Check openssl doc L + +=item * sk_X509_NAME_free + +Free an allocated STACK_OF(X509_NAME) structure. + + Net::SSLeay::sk_X509_NAME_free($sk); + # $sk - value corresponding to openssl's STACK_OF(X509_NAME) structure + # + # returns: no return value + +=item * sk_X509_NAME_num + +Return number of items in STACK_OF(X509_NAME) + + my $rv = Net::SSLeay::sk_X509_NAME_num($sk); + # $sk - value corresponding to openssl's STACK_OF(X509_NAME) structure + # + # returns: number of items + +=item * sk_X509_NAME_value + +Returns X509_NAME from position $index in STACK_OF(X509_NAME) + + my $rv = Net::SSLeay::sk_X509_NAME_value($sk, $i); + # $sk - value corresponding to openssl's STACK_OF(X509_NAME) structure + # $i - (integer) index/position + # + # returns: value corresponding to openssl's X509_NAME structure (0 on failure) + +=item * add_file_cert_subjects_to_stack + +Add a file of certs to a stack. All certs in $file that are not already in the $stackCAs will be added. + + my $rv = Net::SSLeay::add_file_cert_subjects_to_stack($stackCAs, $file); + # $stackCAs - value corresponding to openssl's STACK_OF(X509_NAME) structure + # $file - (string) filename + # + # returns: 1 on success, 0 on failure + +=item * add_dir_cert_subjects_to_stack + +Add a directory of certs to a stack. All certs in $dir that are not already in the $stackCAs will be added. + + my $rv = Net::SSLeay::add_dir_cert_subjects_to_stack($stackCAs, $dir); + # $stackCAs - value corresponding to openssl's STACK_OF(X509_NAME) structure + # $dir - (string) the directory to append from. All files in this directory will be examined as potential certs. Any that are acceptable to SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be included. + # + # returns: 1 on success, 0 on failure + +=back + +=head3 Low level API: X509_STORE_* related functions + +=over + +=item * X509_STORE_CTX_new + +returns a newly initialised X509_STORE_CTX structure. + +=item * X509_STORE_CTX_init + +X509_STORE_CTX_init() sets up an X509_STORE_CTX for a subsequent verification operation. +It must be called before each call to X509_verify_cert(). + +Net::SSLeay::X509_STORE_CTX_init($x509_store_ctx, $x509_store, $x509, $chain); + +# $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure (required) +# $x509_store - value corresponding to openssl's X509_STORE structure (optional) +# $x509 - value corresponding to openssl's X509 structure (optional) +# $chain - value corresponding to openssl's STACK_OF(X509) structure (optional) + +Check openssl doc L + +=item * X509_STORE_CTX_free + +Frees an X509_STORE_CTX structure. + +Net::SSLeay::X509_STORE_CTX_free($x509_store_ctx); + +# $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + +=item * X509_verify_cert + +The X509_verify_cert() function attempts to discover and validate a +certificate chain based on parameters in ctx. A complete description +of the process is contained in the verify(1) manual page. + +If this function returns 0, use X509_STORE_CTX_get_error to get additional error +information. + +my $rv = Net::SSLeay::X509_verify_cert($x509_store_ctx); +# $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure +# +# returns: 1 if a complete chain can be built and validated, otherwise 0 + +Check openssl doc L + +=item * X509_STORE_CTX_get_current_cert + +Returns the certificate in ctx which caused the error or 0 if no certificate is relevant. + + my $rv = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # + # returns: value corresponding to openssl's X509 structure (0 on failure) + +Check openssl doc L + +=item * X509_STORE_CTX_get_error + +Returns the error code of $ctx. + + my $rv = Net::SSLeay::X509_STORE_CTX_get_error($x509_store_ctx); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # + # returns: (integer) error code + +For more info about erro code values check function L. + +Check openssl doc L + +=item * X509_STORE_CTX_get_error_depth + +Returns the depth of the error. This is a non-negative integer representing +where in the certificate chain the error occurred. If it is zero it occurred +in the end entity certificate, one if it is the certificate which signed +the end entity certificate and so on. + + my $rv = Net::SSLeay::X509_STORE_CTX_get_error_depth($x509_store_ctx); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # + # returns: (integer) depth + +Check openssl doc L + +=item * X509_STORE_CTX_get_ex_data + +Is used to retrieve the information for $idx from $x509_store_ctx. + + my $rv = Net::SSLeay::X509_STORE_CTX_get_ex_data($x509_store_ctx, $idx); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # $idx - (integer) index for application specific data + # + # returns: pointer to ??? + +=item * X509_STORE_CTX_set_ex_data + +Is used to store application data at arg for idx into $x509_store_ctx. + + my $rv = Net::SSLeay::X509_STORE_CTX_set_ex_data($x509_store_ctx, $idx, $data); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # $idx - (integer) ??? + # $data - (pointer) ??? + # + # returns: 1 on success, 0 on failure + +=item * X509_STORE_CTX_set_cert + +Sets the certificate to be verified in $x509_store_ctx to $x. + + Net::SSLeay::X509_STORE_CTX_set_cert($x509_store_ctx, $x); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # $x - value corresponding to openssl's X509 structure + # + # returns: no return value + +Check openssl doc L + +=item * X509_STORE_new + +Returns a newly initialized X509_STORE structure. + +my $rv = Net::SSLeay::X509_STORE_new(); +# +# returns: value corresponding to openssl's X509_STORE structure (0 on failure) + +=item * X509_STORE_free + +Frees an X509_STORE structure + +Net::SSLeay::X509_STORE_free($x509_store); +# $x509_store - value corresponding to openssl's X509_STORE structure + +=item * X509_STORE_add_lookup + +Adds a lookup to an X509_STORE for a given lookup method. + +my $method = &Net::SSLeay::X509_LOOKUP_hash_dir; +my $rv = Net::SSLeay::X509_STORE_add_lookup($x509_store, $method); +# $method - value corresponding to openssl's X509_LOOKUP_METHOD structure +# $x509_store - value corresponding to openssl's X509_STORE structure +# +# returns: value corresponding to openssl's X509_LOOKUP structure + +Check openssl doc L + +=item * X509_STORE_CTX_set_error + +Sets the error code of $ctx to $s. For example it might be used in a verification callback to set an error based on additional checks. + + Net::SSLeay::X509_STORE_CTX_set_error($x509_store_ctx, $s); + # $x509_store_ctx - value corresponding to openssl's X509_STORE_CTX structure + # $s - (integer) error id + # + # returns: no return value + +Check openssl doc L + +=item * X509_STORE_add_cert + +Adds X509 certificate $x into the X509_STORE $store. + + my $rv = Net::SSLeay::X509_STORE_add_cert($store, $x); + # $store - value corresponding to openssl's X509_STORE structure + # $x - value corresponding to openssl's X509 structure + # + # returns: 1 on success, 0 on failure + +=item * X509_STORE_add_crl + +Adds X509 CRL $x into the X509_STORE $store. + + my $rv = Net::SSLeay::X509_STORE_add_crl($store, $x); + # $store - value corresponding to openssl's X509_STORE structure + # $x - value corresponding to openssl's X509_CRL structure + # + # returns: 1 on success, 0 on failure + +=item * X509_STORE_set1_param + +??? (more info needed) + + my $rv = Net::SSLeay::X509_STORE_set1_param($store, $pm); + # $store - value corresponding to openssl's X509_STORE structure + # $pm - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: 1 on success, 0 on failure + +=item * X509_LOOKUP_hash_dir + +Returns an X509_LOOKUP structure that instructs an X509_STORE to +load files from a directory containing certificates with filenames +in the format I or crls with filenames in the format IBI + +my $rv = Net::SSLeay::X509_LOOKUP_hash_dir(); +# +# returns: value corresponding to openssl's X509_LOOKUP_METHOD structure, with the hashed directory method + +Check openssl doc L + +=item * X509_LOOKUP_add_dir + +Add a directory to an X509_LOOKUP structure, usually obtained from +X509_STORE_add_lookup. + +my $method = &Net::SSLeay::X509_LOOKUP_hash_dir; +my $lookup = Net::SSLeay::X509_STORE_add_lookup($x509_store, $method); +my $type = &Net::SSLeay::X509_FILETYPE_PEM; +Net::SSLeay::X509_LOOKUP_add_dir($lookup, $dir, $type); +# $lookup - value corresponding to openssl's X509_LOOKUP structure +# $dir - string path to a directory +s# $type - constant corresponding to the type of file in the directory - can be X509_FILETYPE_PEM, X509_FILETYPE_DEFAULT, or X509_FILETYPE_ASN1 + +=item * X509_STORE_set_flags + + Net::SSLeay::X509_STORE_set_flags($ctx, $flags); + # $ctx - value corresponding to openssl's X509_STORE structure + # $flags - (unsigned long) flags to be set (bitmask) + # + # returns: no return value + + #to create $flags value use corresponding constants like + $flags = Net::SSLeay::X509_V_FLAG_CRL_CHECK(); + +For more details about $flags bitmask see L. + +=item * X509_STORE_set_purpose + + Net::SSLeay::X509_STORE_set_purpose($ctx, $purpose); + # $ctx - value corresponding to openssl's X509_STORE structure + # $purpose - (integer) purpose identifier + # + # returns: no return value + +For more details about $purpose identifier check L. + +=item * X509_STORE_set_trust + + Net::SSLeay::X509_STORE_set_trust($ctx, $trust); + # $ctx - value corresponding to openssl's X509_STORE structure + # $trust - (integer) trust identifier + # + # returns: no return value + +For more details about $trust identifier check L. + +=back + +=head3 Low Level API: X509_INFO related functions + +=over + +=item * sk_X509_INFO_num + +Returns the number of values in a STACK_OF(X509_INFO) structure. + + my $rv = Net::SSLeay::sk_X509_INFO_num($sk_x509_info); + # $sk_x509_info - value corresponding to openssl's STACK_OF(X509_INFO) structure + # + # returns: number of values in $sk_X509_info + +=item * sk_X509_INFO_value + +Returns the value of a STACK_OF(X509_INFO) structure at a given index. + + my $rv = Net::SSLeay::sk_X509_INFO_value($sk_x509_info, $index); + # $sk_x509_info - value corresponding to openssl's STACK_OF(X509_INFO) structure + # $index - index into the stack + # + # returns: value corresponding to openssl's X509_INFO structure at the given index + +=item * P_X509_INFO_get_x509 + +Returns the X509 structure stored in an X509_INFO structure. + + my $rv = Net::SSLeay::P_X509_INFO_get_x509($x509_info); + # $x509_info - value corresponding to openssl's X509_INFO structure + # + # returns: value corresponding to openssl's X509 structure + +=back + +=head3 Low level API: X509_VERIFY_PARAM_* related functions + +=over + +=item * X509_VERIFY_PARAM_add0_policy + +Enables policy checking (it is disabled by default) and adds $policy to the acceptable policy set. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_add0_policy($param, $policy); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $policy - value corresponding to openssl's ASN1_OBJECT structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_VERIFY_PARAM_add0_table + +??? (more info needed) + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_add0_table($param); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: 1 on success, 0 on failure + +=item * X509_VERIFY_PARAM_add1_host + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Adds an additional reference identifier that can match the peer's certificate. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_add1_host($param, $name); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $name - (string) name to be set + # + # returns: 1 on success, 0 on failure + +See also OpenSSL docs, L and +L for more information, including +wildcard matching. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_clear_flags + +Clears the flags $flags in param. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_clear_flags($param, $flags); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $flags - (unsigned long) flags to be set (bitmask) + # + # returns: 1 on success, 0 on failure + +For more details about $flags bitmask see L. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_free + +Frees up the X509_VERIFY_PARAM structure. + + Net::SSLeay::X509_VERIFY_PARAM_free($param); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: no return value + +=item * X509_VERIFY_PARAM_get0_peername + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Returns the DNS hostname or subject CommonName from the peer certificate that matched one of the reference identifiers. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_get0_peername($param); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: (string) name e.g. '*.example.com' or undef + +Check openssl doc L + +=item * X509_VERIFY_PARAM_get_depth + +Returns the current verification depth. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_get_depth($param); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: (ineger) depth + +Check openssl doc L + +=item * X509_VERIFY_PARAM_get_flags + +Returns the current verification flags. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_get_flags($param); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: (unsigned long) flags to be set (bitmask) + +For more details about returned flags bitmask see L. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set_flags + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set_flags($param, $flags); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $flags - (unsigned long) flags to be set (bitmask) + # + # returns: 1 on success, 0 on failure + + #to create $flags value use corresponding constants like + $flags = Net::SSLeay::X509_V_FLAG_CRL_CHECK(); + +For more details about $flags bitmask, see the OpenSSL docs below. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_inherit + +??? (more info needed) + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_inherit($to, $from); + # $to - value corresponding to openssl's X509_VERIFY_PARAM structure + # $from - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: 1 on success, 0 on failure + +=item * X509_VERIFY_PARAM_lookup + +Finds X509_VERIFY_PARAM by name. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_lookup($name); + # $name - (string) name we want to find + # + # returns: value corresponding to openssl's X509_VERIFY_PARAM structure (0 on failure) + +=item * X509_VERIFY_PARAM_new + +Creates a new X509_VERIFY_PARAM structure. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_new(); + # + # returns: value corresponding to openssl's X509_VERIFY_PARAM structure (0 on failure) + +=item * X509_VERIFY_PARAM_set1 + +Sets the name of X509_VERIFY_PARAM structure $to to the same value +as the name of X509_VERIFY_PARAM structure $from. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1($to, $from); + # $to - value corresponding to openssl's X509_VERIFY_PARAM structure + # $from - value corresponding to openssl's X509_VERIFY_PARAM structure + # + # returns: 1 on success, 0 on failure + +=item * X509_VERIFY_PARAM_set1_email + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Sets the expected RFC822 email address to email. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_email($param, $email); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $email - (string) email to be set + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set1_host + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Sets the expected DNS hostname to name clearing any previously specified host name or names. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_host($param, $name); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $name - (string) name to be set + # + # returns: 1 on success, 0 on failure + +See also OpenSSL docs, L and +L for more information, including +wildcard matching. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set1_ip + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Sets the expected IP address to ip. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_ip($param, $ip); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $ip - (binary) 4 octet IPv4 or 16 octet IPv6 address + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set1_ip_asc + +B not available in Net-SSLeay-1.82 and before; requires at least OpenSSL 1.0.2 + +Sets the expected IP address to ipasc. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_asc($param, $ipasc); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $ip - (string) IPv4 or IPv6 address + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set1_name + +Sets the name of X509_VERIFY_PARAM structure $param to $name. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_name($param, $name); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $name - (string) name to be set + # + # returns: 1 on success, 0 on failure + +=item * X509_VERIFY_PARAM_set1_policies + +Enables policy checking (it is disabled by default) and sets the acceptable policy set to policies. +Any existing policy set is cleared. The policies parameter can be 0 to clear an existing policy set. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set1_policies($param, $policies); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $policies - value corresponding to openssl's STACK_OF(ASN1_OBJECT) structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set_depth + +Sets the maximum verification depth to depth. That is the maximum number of untrusted CA certificates that can appear in a chain. + + Net::SSLeay::X509_VERIFY_PARAM_set_depth($param, $depth); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $depth - (integer) depth to be set + # + # returns: no return value + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set_hostflags + + Net::SSLeay::X509_VERIFY_PARAM_set_hostflags($param, $flags); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $flags - (unsigned int) flags to be set (bitmask) + # + # returns: no return value + +See also OpenSSL docs, L and L for more information. +The flags for controlling wildcard checks and other features are defined in OpenSSL docs. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set_purpose + +Sets the verification purpose in $param to $purpose. This determines the acceptable purpose +of the certificate chain, for example SSL client or SSL server. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set_purpose($param, $purpose); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $purpose - (integer) purpose identifier + # + # returns: 1 on success, 0 on failure + +For more details about $purpose identifier check L. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set_time + +Sets the verification time in $param to $t. Normally the current time is used. + + Net::SSLeay::X509_VERIFY_PARAM_set_time($param, $t); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $t - (time_t) time in seconds since 1.1.1970 + # + # returns: no return value + +Check openssl doc L + +=item * X509_VERIFY_PARAM_set_trust + +Sets the trust setting in $param to $trust. + + my $rv = Net::SSLeay::X509_VERIFY_PARAM_set_trust($param, $trust); + # $param - value corresponding to openssl's X509_VERIFY_PARAM structure + # $trust - (integer) trust identifier + # + # returns: 1 on success, 0 on failure + +For more details about $trust identifier check L. + +Check openssl doc L + +=item * X509_VERIFY_PARAM_table_cleanup + +??? (more info needed) + + Net::SSLeay::X509_VERIFY_PARAM_table_cleanup(); + # + # returns: no return value + +=back + +=head3 Low level API: Cipher (EVP_CIPHER_*) related functions + +=over + +=item * EVP_get_cipherbyname + +B not available in Net-SSLeay-1.45 and before + +Returns an EVP_CIPHER structure when passed a cipher name. + + my $rv = Net::SSLeay::EVP_get_cipherbyname($name); + # $name - (string) cipher name e.g. 'aes-128-cbc', 'camellia-256-ecb', 'des-ede', ... + # + # returns: value corresponding to openssl's EVP_CIPHER structure + +Check openssl doc L + +=back + +=head3 Low level API: Digest (EVP_MD_*) related functions + +=over + +=item * OpenSSL_add_all_digests + +B not available in Net-SSLeay-1.42 and before + + Net::SSLeay::OpenSSL_add_all_digests(); + # no args, no return value + +http://www.openssl.org/docs/crypto/OpenSSL_add_all_algorithms.html + +=item * P_EVP_MD_list_all + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-1.0.0 + +B Does not exactly correspond to any low level API function + + my $rv = Net::SSLeay::P_EVP_MD_list_all(); + # + # returns: arrayref - list of available digest names + +The returned digest names correspond to values expected by L. + +Note that some of the digests are available by default and some only after calling L. + +=item * EVP_get_digestbyname + +B not available in Net-SSLeay-1.42 and before + + my $rv = Net::SSLeay::EVP_get_digestbyname($name); + # $name - string with digest name + # + # returns: value corresponding to openssl's EVP_MD structure + +The $name param can be: + + md2 + md4 + md5 + mdc2 + ripemd160 + sha + sha1 + sha224 + sha256 + sha512 + whirlpool + +Or better check the supported digests by calling L. + +=item * EVP_MD_type + +B not available in Net-SSLeay-1.42 and before + + my $rv = Net::SSLeay::EVP_MD_type($md); + # $md - value corresponding to openssl's EVP_MD structure + # + # returns: the NID (integer) of the OBJECT IDENTIFIER representing the given message digest + +=item * EVP_MD_size + +B not available in Net-SSLeay-1.42 and before + + my $rv = Net::SSLeay::EVP_MD_size($md); + # $md - value corresponding to openssl's EVP_MD structure + # + # returns: the size of the message digest in bytes (e.g. 20 for SHA1) + +=item * EVP_MD_CTX_md + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + + Net::SSLeay::EVP_MD_CTX_md($ctx); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # + # returns: value corresponding to openssl's EVP_MD structure + +=item * EVP_MD_CTX_create + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Allocates, initializes and returns a digest context. + + my $rv = Net::SSLeay::EVP_MD_CTX_create(); + # + # returns: value corresponding to openssl's EVP_MD_CTX structure + +The complete idea behind EVP_MD_CTX looks like this example: + + Net::SSLeay::OpenSSL_add_all_digests(); + + my $md = Net::SSLeay::EVP_get_digestbyname("sha1"); + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + Net::SSLeay::EVP_DigestInit($ctx, $md); + + while(my $chunk = get_piece_of_data()) { + Net::SSLeay::EVP_DigestUpdate($ctx,$chunk); + } + + my $result = Net::SSLeay::EVP_DigestFinal($ctx); + Net::SSLeay::EVP_MD_CTX_destroy($ctx); + + print "digest=", unpack('H*', $result), "\n"; #print hex value + +=item * EVP_DigestInit_ex + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Sets up digest context $ctx to use a digest $type from ENGINE $impl, $ctx must be +initialized before calling this function, type will typically be supplied by a function +such as L. If $impl is 0 then the default implementation of digest $type is used. + + my $rv = Net::SSLeay::EVP_DigestInit_ex($ctx, $type, $impl); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # $type - value corresponding to openssl's EVP_MD structure + # $impl - value corresponding to openssl's ENGINE structure + # + # returns: 1 for success and 0 for failure + +=item * EVP_DigestInit + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Behaves in the same way as L except the passed context $ctx does not have +to be initialized, and it always uses the default digest implementation. + + my $rv = Net::SSLeay::EVP_DigestInit($ctx, $type); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # $type - value corresponding to openssl's EVP_MD structure + # + # returns: 1 for success and 0 for failure + +=item * EVP_MD_CTX_destroy + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Cleans up digest context $ctx and frees up the space allocated to it, it should be +called only on a context created using L. + + Net::SSLeay::EVP_MD_CTX_destroy($ctx); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # + # returns: no return value + +=item * EVP_DigestUpdate + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + + my $rv = Net::SSLeay::EVP_DigestUpdate($ctx, $data); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # $data - data to be hashed + # + # returns: 1 for success and 0 for failure + +=item * EVP_DigestFinal_ex + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Retrieves the digest value from $ctx. After calling L no +additional calls to L can be made, but +L can be called to initialize a new digest operation. + + my $digest_value = Net::SSLeay::EVP_DigestFinal_ex($ctx); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # + # returns: hash value (binary) + + #to get printable (hex) value of digest use: + print unpack('H*', $digest_value); + +=item * EVP_DigestFinal + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Similar to L except the digest context ctx is automatically cleaned up. + + my $rv = Net::SSLeay::EVP_DigestFinal($ctx); + # $ctx - value corresponding to openssl's EVP_MD_CTX structure + # + # returns: hash value (binary) + + #to get printable (hex) value of digest use: + print unpack('H*', $digest_value); + +=item * MD2 + +B no supported by default in openssl-1.0.0 + +Computes MD2 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::MD2($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * MD4 + +Computes MD4 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::MD4($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * MD5 + +Computes MD5 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::MD5($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * RIPEMD160 + +Computes RIPEMD160 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::RIPEMD160($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * SHA1 + +B not available in Net-SSLeay-1.42 and before + +Computes SHA1 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::SHA1($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * SHA256 + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.8 + +Computes SHA256 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::SHA256($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * SHA512 + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.8 + +Computes SHA512 from given $data (all data needs to be loaded into memory) + + my $digest = Net::SSLeay::SHA512($data); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * EVP_Digest + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.7 + +Computes "any" digest from given $data (all data needs to be loaded into memory) + + my $md = Net::SSLeay::EVP_get_digestbyname("sha1"); #or any other algorithm + my $digest = Net::SSLeay::EVP_Digest($data, $md); + print "digest(hexadecimal)=", unpack('H*', $digest); + +=item * EVP_sha1 + +B not available in Net-SSLeay-1.42 and before + + my $md = Net::SSLeay::EVP_sha1(); + # + # returns: value corresponding to openssl's EVP_MD structure + +=item * EVP_sha256 + +B requires at least openssl-0.9.8 + + my $md = Net::SSLeay::EVP_sha256(); + # + # returns: value corresponding to openssl's EVP_MD structure + +=item * EVP_sha512 + +B not available in Net-SSLeay-1.42 and before; requires at least openssl-0.9.8 + + my $md = Net::SSLeay::EVP_sha512(); + # + # returns: value corresponding to openssl's EVP_MD structure + +=item * EVP_add_digest + + my $rv = Net::SSLeay::EVP_add_digest($digest); + # $digest - value corresponding to openssl's EVP_MD structure + # + # returns: 1 on success, 0 otherwise + +=back + +=head3 Low level API: CIPHER_* related functions + +=over + +=item * CIPHER_get_name + +B not available in Net-SSLeay-1.42 and before + +Returns name of the cipher used. + + my $rv = Net::SSLeay::CIPHER_description($cipher); + # $cipher - value corresponding to openssl's SSL_CIPHER structure + # + # returns: (string) cipher name e.g. 'DHE-RSA-AES256-SHA' + +Check openssl doc L + +Example: + + my $ssl_cipher = Net::SSLeay::get_current_cipher($ssl); + my $cipher_name = Net::SSLeay::CIPHER_get_name($ssl_cipher); + +=item * CIPHER_description + +Returns a textual description of the cipher used. + +??? (does this function really work?) + + my $rv = Net::SSLeay::CIPHER_description($cipher, $buf, $size); + # $cipher - value corresponding to openssl's SSL_CIPHER structure + # $bufer - (string/buffer) ??? + # $size - (integer) ??? + # + # returns: (string) cipher description e.g. 'DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1' + +Check openssl doc L + +=item * CIPHER_get_bits + +Returns the number of secret bits used for cipher. + + my $rv = Net::SSLeay::CIPHER_get_bits($c); + # $c - value corresponding to openssl's SSL_CIPHER structure + # + # returns: (integert) number of secret bits, 0 on error + + +Check openssl doc L + +=back + +=head3 Low level API: RSA_* related functions + +=over + +=item * RSA_generate_key + +Generates a key pair and returns it in a newly allocated RSA structure. +The pseudo-random number generator must be seeded prior to calling RSA_generate_key. + + my $rv = Net::SSLeay::RSA_generate_key($bits, $e, $perl_cb, $perl_cb_arg); + # $bits - (integer) modulus size in bits e.g. 512, 1024, 2048 + # $e - (integer) public exponent, an odd number, typically 3, 17 or 65537 + # $perl_cb - [optional] reference to perl callback function + # $perl_cb_arg - [optional] data that will be passed to callback function when invoked + # + # returns: value corresponding to openssl's RSA structure (0 on failure) + +Check openssl doc L + +=item * RSA_free + +Frees the RSA structure and its components. The key is erased before the memory is returned to the system. + + Net::SSLeay::RSA_free($r); + # $r - value corresponding to openssl's RSA structure + # + # returns: no return value + +Check openssl doc L + +=item * RSA_get_key_parameters + +Returns a list of pointers to BIGNUMs representing the parameters of the key in +this order: +(n, e, d, p, q, dmp1, dmq1, iqmp) +Caution: returned list consists of SV pointers to BIGNUMs, which would need to be blessed as Crypt::OpenSSL::Bignum for further use + +my (@params) = RSA_get_key_parameters($r); + +=back + +=head3 Low level API: BIO_* related functions + +=over + +=item * BIO_eof + +Returns 1 if the BIO has read EOF, the precise meaning of 'EOF' varies according to the BIO type. + + my $rv = Net::SSLeay::BIO_eof($s); + # $s - value corresponding to openssl's BIO structure + # + # returns: 1 if EOF has been reached 0 otherwise + +Check openssl doc L + +=item * BIO_f_ssl + +Returns the SSL BIO method. This is a filter BIO which is a wrapper +round the OpenSSL SSL routines adding a BIO 'flavour' to SSL I/O. + + my $rv = Net::SSLeay::BIO_f_ssl(); + # + # returns: value corresponding to openssl's BIO_METHOD structure (0 on failure) + +Check openssl doc L + +=item * BIO_free + +Frees up a single BIO. + + my $rv = Net::SSLeay::BIO_free($bio;); + # $bio; - value corresponding to openssl's BIO structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * BIO_new + +Returns a new BIO using method $type + + my $rv = Net::SSLeay::BIO_new($type); + # $type - value corresponding to openssl's BIO_METHOD structure + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * BIO_new_buffer_ssl_connect + +Creates a new BIO chain consisting of a buffering BIO, an SSL BIO (using ctx) and a connect BIO. + + my $rv = Net::SSLeay::BIO_new_buffer_ssl_connect($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * BIO_new_file + +Creates a new file BIO with mode $mode the meaning of mode is the same +as the stdio function fopen(). The BIO_CLOSE flag is set on the returned BIO. + + my $rv = Net::SSLeay::BIO_new_file($filename, $mode); + # $filename - (string) filename + # $mode - (string) opening mode (as mode by stdio function fopen) + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * BIO_new_ssl + +Allocates an SSL BIO using SSL_CTX ctx and using client mode if client is non zero. + + my $rv = Net::SSLeay::BIO_new_ssl($ctx, $client); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $client - (integer) 0 or 1 - indicates ssl client mode + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * BIO_new_ssl_connect + +Creates a new BIO chain consisting of an SSL BIO (using ctx) followed by a connect BIO. + + my $rv = Net::SSLeay::BIO_new_ssl_connect($ctx); + # $ctx - value corresponding to openssl's SSL_CTX structure + # + # returns: value corresponding to openssl's BIO structure (0 on failure) + +Check openssl doc L + +=item * BIO_pending + +Return the number of pending characters in the BIOs read buffers. + + my $rv = Net::SSLeay::BIO_pending($s); + # $s - value corresponding to openssl's BIO structure + # + # returns: the amount of pending data + +Check openssl doc L + +=item * BIO_wpending + +Return the number of pending characters in the BIOs write buffers. + + my $rv = Net::SSLeay::BIO_wpending($s); + # $s - value corresponding to openssl's BIO structure + # + # returns: the amount of pending data + +Check openssl doc L + +=item * BIO_read + +Read the underlying descriptor. + + Net::SSLeay::BIO_read($s, $max); + # $s - value corresponding to openssl's BIO structure + # $max - [optional] max. bytes to read (if not specified, the value 32768 is used) + # + # returns: data + +Check openssl doc L + +=item * BIO_write + +Attempts to write data from $buffer to BIO $b. + + my $rv = Net::SSLeay::BIO_write($b, $buffer); + # $b - value corresponding to openssl's BIO structure + # $buffer - data + # + # returns: amount of data successfully written + # or that no data was successfully read or written if the result is 0 or -1 + # or -2 when the operation is not implemented in the specific BIO type + +Check openssl doc L + +=item * BIO_s_mem + +Return the memory BIO method function. + + my $rv = Net::SSLeay::BIO_s_mem(); + # + # returns: value corresponding to openssl's BIO_METHOD structure (0 on failure) + +Check openssl doc L + +=item * BIO_ssl_copy_session_id + +Copies an SSL session id between BIO chains from and to. It does this by locating +the SSL BIOs in each chain and calling SSL_copy_session_id() on the internal SSL pointer. + + my $rv = Net::SSLeay::BIO_ssl_copy_session_id($to, $from); + # $to - value corresponding to openssl's BIO structure + # $from - value corresponding to openssl's BIO structure + # + # returns: 1 on success, 0 on failure + +Check openssl doc L + +=item * BIO_ssl_shutdown + +Closes down an SSL connection on BIO chain bio. It does this by locating the +SSL BIO in the chain and calling SSL_shutdown() on its internal SSL pointer. + + Net::SSLeay::BIO_ssl_shutdown($ssl_bio); + # $ssl_bio - value corresponding to openssl's BIO structure + # + # returns: no return value + +Check openssl doc L + +=back + +=head3 Low level API: Server side Server Name Indication (SNI) support + +=over + +=item * set_tlsext_host_name + +TBA + +=item * get_servername + +TBA + +=item * get_servername_type + +TBA + +=item * CTX_set_tlsext_servername_callback + +B requires at least OpenSSL 0.9.8f + +This function is used in a server to support Server side Server Name Indication (SNI). + + Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, $code) + # $ctx - SSL context + # $code - reference to a subroutine that will be called when a new connection is being initiated + # + # returns: no return value +On the client side: +use set_tlsext_host_name($ssl, $servername) before initiating the SSL connection. + +On the server side: +Set up an additional SSL_CTX() for each different certificate; + +Add a servername callback to each SSL_CTX() using CTX_set_tlsext_servername_callback(); + +The callback function is required to retrieve the client-supplied servername +with get_servername(ssl). Figure out the right +SSL_CTX to go with that host name, then switch the SSL object to that SSL_CTX +with set_SSL_CTX(). + +Example: + + # set callback + Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, + sub { + my $ssl = shift; + my $h = Net::SSLeay::get_servername($ssl); + Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}) if exists $hostnames{$h}; + } ); + + +More complete example: + + # ... initialize Net::SSLeay + + my %hostnames = ( + 'sni1' => { cert=>'sni1.pem', key=>'sni1.key' }, + 'sni2' => { cert=>'sni2.pem', key=>'sni2.key' }, + ); + + # create a new context for each certificate/key pair + for my $name (keys %hostnames) { + $hostnames{$name}->{ctx} = Net::SSLeay::CTX_new or die; + Net::SSLeay::CTX_set_cipher_list($hostnames{$name}->{ctx}, 'ALL'); + Net::SSLeay::set_cert_and_key($hostnames{$name}->{ctx}, + $hostnames{$name}->{cert}, $hostnames{$name}->{key}) or die; + } + + # create default context + my $ctx = Net::SSLeay::CTX_new or die; + Net::SSLeay::CTX_set_cipher_list($ctx, 'ALL'); + Net::SSLeay::set_cert_and_key($ctx, 'cert.pem','key.pem') or die; + + # set callback + Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub { + my $ssl = shift; + my $h = Net::SSLeay::get_servername($ssl); + Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}) if exists $hostnames{$h}; + } ); + + # ... later + + $s = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($s, fileno($accepted_socket)); + Net::SSLeay::accept($s); + +=back + +=head3 Low level API: NPN (next protocol negotiation) related functions + +NPN is being replaced with ALPN, a more recent TLS extension for application +protocol negotiation that's in process of being adopted by IETF. Please look +below for APLN API description. + +Simple approach for using NPN support looks like this: + + ### client side + use Net::SSLeay; + use IO::Socket::INET; + + Net::SSLeay::initialize(); + my $sock = IO::Socket::INET->new(PeerAddr=>'encrypted.google.com:443') or die; + my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + Net::SSLeay::CTX_set_next_proto_select_cb($ctx, ['http1.1','spdy/2']); + my $ssl = Net::SSLeay::new($ctx) or die; + Net::SSLeay::set_fd($ssl, fileno($sock)) or die; + Net::SSLeay::connect($ssl); + + warn "client:negotiated=",Net::SSLeay::P_next_proto_negotiated($ssl), "\n"; + warn "client:last_status=", Net::SSLeay::P_next_proto_last_status($ssl), "\n"; + + ### server side + use Net::SSLeay; + use IO::Socket::INET; + + Net::SSLeay::initialize(); + my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + Net::SSLeay::set_cert_and_key($ctx, "cert.pem", "key.pem"); + Net::SSLeay::CTX_set_next_protos_advertised_cb($ctx, ['spdy/2','http1.1']); + my $sock = IO::Socket::INET->new(LocalAddr=>'localhost', LocalPort=>5443, Proto=>'tcp', Listen=>20) or die; + + while (1) { + my $ssl = Net::SSLeay::new($ctx); + warn("server:waiting for incoming connection...\n"); + my $fd = $sock->accept(); + Net::SSLeay::set_fd($ssl, $fd->fileno); + Net::SSLeay::accept($ssl); + warn "server:negotiated=",Net::SSLeay::P_next_proto_negotiated($ssl),"\n"; + my $got = Net::SSLeay::read($ssl); + Net::SSLeay::ssl_write_all($ssl, "length=".length($got)); + Net::SSLeay::free($ssl); + $fd->close(); + } + # check with: openssl s_client -connect localhost:5443 -nextprotoneg http/1.1,spdy/2 + +Please note that the selection (negotiation) is performed by client side, the server side simply advertise the list of supported protocols. + +Advanced approach allows you to implement your own negotiation algorithm. + + #see below documentation for: + Net::SSleay::CTX_set_next_proto_select_cb($ctx, $perl_callback_function, $callback_data); + Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, $perl_callback_function, $callback_data); + +Detection of NPN support (works even in older Net::SSLeay versions): + + use Net::SSLeay; + + if (exists &Net::SSLeay::P_next_proto_negotiated) { + # do NPN stuff + } + +=over + +=item * CTX_set_next_proto_select_cb + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 + +B You need CTX_set_next_proto_select_cb on B of SSL connection. + +Simple usage - in this case a "common" negotiation algorithm (as implemented by openssl's function SSL_select_next_proto) is used. + + $rv = Net::SSleay::CTX_set_next_proto_select_cb($ctx, $arrayref); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $arrayref - list of accepted protocols - e.g. ['http1.0', 'http1.1'] + # + # returns: 0 on success, 1 on failure + +Advanced usage (you probably do not need this): + + $rv = Net::SSleay::CTX_set_next_proto_select_cb($ctx, $perl_callback_function, $callback_data); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $perl_callback_function - reference to perl function + # $callback_data - [optional] data to passed to callback function when invoked + # + # returns: 0 on success, 1 on failure + + # where callback function looks like + sub npn_advertised_cb_invoke { + my ($ssl, $arrayref_proto_list_advertised_by_server, $callback_data) = @_; + my $status; + # ... + $status = 1; #status can be: + # 0 - OPENSSL_NPN_UNSUPPORTED + # 1 - OPENSSL_NPN_NEGOTIATED + # 2 - OPENSSL_NPN_NO_OVERLAP + return $status, ['http1.1','spdy/2']; # the callback has to return 2 values + } + +To undefine/clear this callback use: + + Net::SSleay::CTX_set_next_proto_select_cb($ctx, undef); + +=item * CTX_set_next_protos_advertised_cb + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 + +B You need CTX_set_next_proto_select_cb on B of SSL connection. + +Simple usage: + + $rv = Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, $arrayref); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $arrayref - list of advertised protocols - e.g. ['http1.0', 'http1.1'] + # + # returns: 0 on success, 1 on failure + +Advanced usage (you probably do not need this): + + $rv = Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, $perl_callback_function, $callback_data); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $perl_callback_function - reference to perl function + # $callback_data - [optional] data to passed to callback function when invoked + # + # returns: 0 on success, 1 on failure + + # where callback function looks like + sub npn_advertised_cb_invoke { + my ($ssl, $callback_data) = @_; + # ... + return ['http1.1','spdy/2']; # the callback has to return arrayref + } + +To undefine/clear this callback use: + + Net::SSleay::CTX_set_next_protos_advertised_cb($ctx, undef); + +=item * P_next_proto_negotiated + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 + +Returns the name of negotiated protocol for given SSL connection $ssl. + + $rv = Net::SSLeay::P_next_proto_negotiated($ssl) + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (string) negotiated protocol name (or undef if no negotiation was done or failed with fatal error) + +=item * P_next_proto_last_status + +B not available in Net-SSLeay-1.45 and before; requires at least openssl-1.0.1 + +Returns the result of the last negotiation for given SSL connection $ssl. + + $rv = Net::SSLeay::P_next_proto_last_status($ssl) + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (integer) negotiation status + # 0 - OPENSSL_NPN_UNSUPPORTED + # 1 - OPENSSL_NPN_NEGOTIATED + # 2 - OPENSSL_NPN_NO_OVERLAP + +=back + +=head3 Low level API: ALPN (application layer protocol negotiation) related functions + +Application protocol can be negotiated via two different mechanisms employing +two different TLS extensions: NPN (obsolete) and ALPN (recommended). + +The API is rather similar, with slight differences reflecting protocol +specifics. In particular, with ALPN the protocol negotiation takes place on +server, while with NPN the client implements the protocol negotiation logic. + +With ALPN, the most basic implementation looks like this: + + ### client side + use Net::SSLeay; + use IO::Socket::INET; + + Net::SSLeay::initialize(); + my $sock = IO::Socket::INET->new(PeerAddr=>'encrypted.google.com:443') or die; + my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + Net::SSLeay::CTX_set_alpn_protos($ctx, ['http/1.1', 'http/2.0', 'spdy/3]); + my $ssl = Net::SSLeay::new($ctx) or die; + Net::SSLeay::set_fd($ssl, fileno($sock)) or die; + Net::SSLeay::connect($ssl); + + warn "client:selected=",Net::SSLeay::P_alpn_selected($ssl), "\n"; + + ### server side + use Net::SSLeay; + use IO::Socket::INET; + + Net::SSLeay::initialize(); + my $ctx = Net::SSLeay::CTX_tlsv1_new() or die; + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + Net::SSLeay::set_cert_and_key($ctx, "cert.pem", "key.pem"); + Net::SSLeay::CTX_set_alpn_select_cb($ctx, ['http/1.1', 'http/2.0', 'spdy/3]); + my $sock = IO::Socket::INET->new(LocalAddr=>'localhost', LocalPort=>5443, Proto=>'tcp', Listen=>20) or die; + + while (1) { + my $ssl = Net::SSLeay::new($ctx); + warn("server:waiting for incoming connection...\n"); + my $fd = $sock->accept(); + Net::SSLeay::set_fd($ssl, $fd->fileno); + Net::SSLeay::accept($ssl); + warn "server:selected=",Net::SSLeay::P_alpn_selected($ssl),"\n"; + my $got = Net::SSLeay::read($ssl); + Net::SSLeay::ssl_write_all($ssl, "length=".length($got)); + Net::SSLeay::free($ssl); + $fd->close(); + } + # check with: openssl s_client -connect localhost:5443 -alpn spdy/3,http/1.1 + +Advanced approach allows you to implement your own negotiation algorithm. + + #see below documentation for: + Net::SSleay::CTX_set_alpn_select_cb($ctx, $perl_callback_function, $callback_data); + +Detection of ALPN support (works even in older Net::SSLeay versions): + + use Net::SSLeay; + + if (exists &Net::SSLeay::P_alpn_selected) { + # do ALPN stuff + } + +=over + +=item * CTX_set_alpn_select_cb + +B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 + +B You need CTX_set_alpn_select_cb on B of TLS connection. + +Simple usage - in this case a "common" negotiation algorithm (as implemented by openssl's function SSL_select_next_proto) is used. + + $rv = Net::SSleay::CTX_set_alpn_select_cb($ctx, $arrayref); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $arrayref - list of accepted protocols - e.g. ['http/2.0', 'http/1.1', 'spdy/3'] + # + # returns: 0 on success, 1 on failure + +Advanced usage (you probably do not need this): + + $rv = Net::SSleay::CTX_set_alpn_select_cb($ctx, $perl_callback_function, $callback_data); + # $ctx - value corresponding to openssl's SSL_CTX structure + # $perl_callback_function - reference to perl function + # $callback_data - [optional] data to passed to callback function when invoked + # + # returns: 0 on success, 1 on failure + + # where callback function looks like + sub alpn_select_cb_invoke { + my ($ssl, $arrayref_proto_list_advertised_by_client, $callback_data) = @_; + # ... + if ($negotiated) { + return 'http/2.0'; + } else { + return undef; + } + } + +To undefine/clear this callback use: + + Net::SSleay::CTX_set_alpn_select_cb($ctx, undef); + +=item * set_alpn_protos + +B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 + +B You need set_alpn_protos on B of TLS connection. + +This adds list of supported application layer protocols to ClientHello message sent by a client. +It advertises the enumeration of supported protocols: + + Net::SSLeay::set_alpn_protos($ssl, ['http/1.1', 'http/2.0', 'spdy/3]); + # returns 0 on success + +=item * CTX_set_alpn_protos + +B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 + +B You need CTX_set_alpn_protos on B of TLS connection. + +This adds list of supported application layer protocols to ClientHello message sent by a client. +It advertises the enumeration of supported protocols: + + Net::SSLeay::CTX_set_alpn_protos($ctx, ['http/1.1', 'http/2.0', 'spdy/3]); + # returns 0 on success + +=item * P_alpn_selected + +B not available in Net-SSLeay-1.55 and before; requires at least openssl-1.0.2 + +Returns the name of negotiated protocol for given TLS connection $ssl. + + $rv = Net::SSLeay::P_alpn_selected($ssl) + # $ssl - value corresponding to openssl's SSL structure + # + # returns: (string) negotiated protocol name (or undef if no negotiation was done or failed with fatal error) + +=back + +=head3 Low level API: DANE Support + +OpenSSL version 1.0.2 adds preliminary support RFC6698 Domain Authentication of +Named Entities (DANE) Transport Layer Association within OpenSSL + +=over + +=item * SSL_get_tlsa_record_byname + +B DELETED from net-ssleay, since it is not supported by OpenSSL + +In order to facilitate DANE there is additional interface, +SSL_get_tlsa_record_byname, accepting hostname, port and socket type +that returns packed TLSA record. In order to make it even easier there +is additional SSL_ctrl function that calls SSL_get_tlsa_record_byname +for you. Latter is recommended for programmers that wish to maintain +broader binary compatibility, e.g. make application work with both 1.0.2 +and prior version (in which case call to SSL_ctrl with new code +returning error would have to be ignored when running with prior version). + +Net::SSLeay::get_tlsa_record_byname($name, $port, $type); + +=back + +=head3 Low level API: Other functions + +=over + +=item * COMP_add_compression_method + +Adds the compression method cm with the identifier id to the list of available compression methods. +This list is globally maintained for all SSL operations within this application. +It cannot be set for specific SSL_CTX or SSL objects. + + my $rv = Net::SSLeay::COMP_add_compression_method($id, $cm); + # $id - (integer) compression method id + # 0 to 63: methods defined by the IETF + # 64 to 192: external party methods assigned by IANA + # 193 to 255: reserved for private use + # + # $cm - value corresponding to openssl's COMP_METHOD structure + # + # returns: 0 on success, 1 on failure (check the error queue to find out the reason) + +Check openssl doc L + +=item * DH_free + +Frees the DH structure and its components. The values are erased before the memory is returned to the system. + + Net::SSLeay::DH_free($dh); + # $dh - value corresponding to openssl's DH structure + # + # returns: no return value + +Check openssl doc L + +=item * FIPS_mode_set + +Enable or disable FIPS mode in a FIPS capable OpenSSL. + + Net::SSLeay:: FIPS_mode_set($enable); + # $enable - (integer) 1 to enable, 0 to disable + +=back + +=head3 Low level API: EC related functions + +=over + +=item * CTX_set_tmp_ecdh + +TBA + +=item * EC_KEY_free + +TBA + +=item * EC_KEY_new_by_curve_name + +TBA + +=item * EC_KEY_generate_key + +Generates a EC key and returns it in a newly allocated EC_KEY structure. +The EC key then can be used to create a PKEY which can be used in calls +like X509_set_pubkey. + + my $key = Net::SSLeay::EVP_PKEY_new(); + my $ec = Net::SSLeay::EC_KEY_generate_key($curve); + Net::SSLeay::EVP_PKEY_assign_EC_KEY($key,$ec); + + # $curve - curve name like 'secp521r1' or the matching Id (integer) of the curve + # + # returns: value corresponding to openssl's EC_KEY structure (0 on failure) + +This function has no equivalent in OpenSSL but combines multiple OpenSSL +functions for an easier interface. + +=item * CTX_set_ecdh_auto, set_ecdh_auto + +These functions enable or disable the automatic curve selection on the server +side by calling SSL_CTX_set_ecdh_auto or SSL_set_ecdh_auto respectively. +If enabled the highest preference curve is automatically used for ECDH temporary +keys used during key exchange. +This function is no longer available for OpenSSL 1.1.0 or higher. + + Net::SSLeay::CTX_set_ecdh_auto($ctx,1); + Net::SSLeay::set_ecdh_auto($ssl,1); + +=item * CTX_set1_curves_list, set1_curves_list + +These functions set the supported curves (in order of preference) by calling +SSL_CTX_set1_curves_list or SSL_set1_curves_list respectively. +For a TLS client these curves are offered to the server in the supported curves +extension while on the server side these are used to determine the shared +curve. +These functions are only available since OpenSSL 1.1.0. + + Net::SSLeay::CTX_set1_curves_list($ctx,"P-521:P-384:P-256"); + Net::SSLeay::set1_curves_list($ssl,"P-521:P-384:P-256"); + +=item * CTX_set1_groups_list, set1_groups_list + +These functions set the supported groups (in order of preference) by calling +SSL_CTX_set1_groups_list or SSL_set1_groups_list respectively. +This is practically the same as CTX_set1_curves_list and set1_curves_list except +that all DH groups can be given as supported by TLS 1.3. +These functions are only available since OpenSSL 1.1.1. + + Net::SSLeay::CTX_set1_groups_list($ctx,"P-521:P-384:P-256"); + Net::SSLeay::set1_groups_list($ssl,"P-521:P-384:P-256"); + +=back + + +=head2 Constants + +There are many openssl constants available in L. You can use them like this: + + use Net::SSLeay; + print &Net::SSLeay::NID_commonName; + #or + print Net::SSLeay::NID_commonName(); + +Or you can import them and use: + + use Net::SSLeay qw/NID_commonName/; + print &NID_commonName; + #or + print NID_commonName(); + #or + print NID_commonName; + +The constants names are derived from openssl constants, however constants starting with C prefix +have name with C part stripped - e.g. openssl's constant C is available as C + +The list of all available constant names: + +=for comment the next part is the output of: perl helper_script/regen_openssl_constants.pl -gen-pod + + ASN1_STRFLGS_ESC_CTRL NID_netscape R_UNKNOWN_REMOTE_ERROR_TYPE + ASN1_STRFLGS_ESC_MSB NID_netscape_base_url R_UNKNOWN_STATE + ASN1_STRFLGS_ESC_QUOTE NID_netscape_ca_policy_url R_X509_LIB + ASN1_STRFLGS_RFC2253 NID_netscape_ca_revocation_url SENT_SHUTDOWN + CB_ACCEPT_EXIT NID_netscape_cert_extension SESSION_ASN1_VERSION + CB_ACCEPT_LOOP NID_netscape_cert_sequence SESS_CACHE_BOTH + CB_ALERT NID_netscape_cert_type SESS_CACHE_CLIENT + CB_CONNECT_EXIT NID_netscape_comment SESS_CACHE_NO_AUTO_CLEAR + CB_CONNECT_LOOP NID_netscape_data_type SESS_CACHE_NO_INTERNAL + CB_EXIT NID_netscape_renewal_url SESS_CACHE_NO_INTERNAL_LOOKUP + CB_HANDSHAKE_DONE NID_netscape_revocation_url SESS_CACHE_NO_INTERNAL_STORE + CB_HANDSHAKE_START NID_netscape_ssl_server_name SESS_CACHE_OFF + CB_LOOP NID_ns_sgc SESS_CACHE_SERVER + CB_READ NID_organizationName SSL3_VERSION + CB_READ_ALERT NID_organizationalUnitName SSLEAY_BUILT_ON + CB_WRITE NID_pbeWithMD2AndDES_CBC SSLEAY_CFLAGS + CB_WRITE_ALERT NID_pbeWithMD2AndRC2_CBC SSLEAY_DIR + ERROR_NONE NID_pbeWithMD5AndCast5_CBC SSLEAY_PLATFORM + ERROR_SSL NID_pbeWithMD5AndDES_CBC SSLEAY_VERSION + ERROR_SYSCALL NID_pbeWithMD5AndRC2_CBC ST_ACCEPT + ERROR_WANT_ACCEPT NID_pbeWithSHA1AndDES_CBC ST_BEFORE + ERROR_WANT_CONNECT NID_pbeWithSHA1AndRC2_CBC ST_CONNECT + ERROR_WANT_READ NID_pbe_WithSHA1And128BitRC2_CBC ST_INIT + ERROR_WANT_WRITE NID_pbe_WithSHA1And128BitRC4 ST_OK + ERROR_WANT_X509_LOOKUP NID_pbe_WithSHA1And2_Key_TripleDES_CBC ST_READ_BODY + ERROR_ZERO_RETURN NID_pbe_WithSHA1And3_Key_TripleDES_CBC ST_READ_HEADER + EVP_PKS_DSA NID_pbe_WithSHA1And40BitRC2_CBC TLS1_1_VERSION + EVP_PKS_EC NID_pbe_WithSHA1And40BitRC4 TLS1_2_VERSION + EVP_PKS_RSA NID_pbes2 TLS1_3_VERSION + EVP_PKT_ENC NID_pbmac1 TLS1_VERSION + EVP_PKT_EXCH NID_pkcs TLSEXT_STATUSTYPE_ocsp + EVP_PKT_EXP NID_pkcs3 VERIFY_CLIENT_ONCE + EVP_PKT_SIGN NID_pkcs7 VERIFY_FAIL_IF_NO_PEER_CERT + EVP_PK_DH NID_pkcs7_data VERIFY_NONE + EVP_PK_DSA NID_pkcs7_digest VERIFY_PEER + EVP_PK_EC NID_pkcs7_encrypted VERIFY_POST_HANDSHAKE + EVP_PK_RSA NID_pkcs7_enveloped V_OCSP_CERTSTATUS_GOOD + FILETYPE_ASN1 NID_pkcs7_signed V_OCSP_CERTSTATUS_REVOKED + FILETYPE_PEM NID_pkcs7_signedAndEnveloped V_OCSP_CERTSTATUS_UNKNOWN + F_CLIENT_CERTIFICATE NID_pkcs8ShroudedKeyBag WRITING + F_CLIENT_HELLO NID_pkcs9 X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + F_CLIENT_MASTER_KEY NID_pkcs9_challengePassword X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS + F_D2I_SSL_SESSION NID_pkcs9_contentType X509_CHECK_FLAG_NEVER_CHECK_SUBJECT + F_GET_CLIENT_FINISHED NID_pkcs9_countersignature X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + F_GET_CLIENT_HELLO NID_pkcs9_emailAddress X509_CHECK_FLAG_NO_WILDCARDS + F_GET_CLIENT_MASTER_KEY NID_pkcs9_extCertAttributes X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + F_GET_SERVER_FINISHED NID_pkcs9_messageDigest X509_FILETYPE_ASN1 + F_GET_SERVER_HELLO NID_pkcs9_signingTime X509_FILETYPE_DEFAULT + F_GET_SERVER_VERIFY NID_pkcs9_unstructuredAddress X509_FILETYPE_PEM + F_I2D_SSL_SESSION NID_pkcs9_unstructuredName X509_LOOKUP + F_READ_N NID_private_key_usage_period X509_PURPOSE_ANY + F_REQUEST_CERTIFICATE NID_rc2_40_cbc X509_PURPOSE_CRL_SIGN + F_SERVER_HELLO NID_rc2_64_cbc X509_PURPOSE_NS_SSL_SERVER + F_SSL_CERT_NEW NID_rc2_cbc X509_PURPOSE_OCSP_HELPER + F_SSL_GET_NEW_SESSION NID_rc2_cfb64 X509_PURPOSE_SMIME_ENCRYPT + F_SSL_NEW NID_rc2_ecb X509_PURPOSE_SMIME_SIGN + F_SSL_READ NID_rc2_ofb64 X509_PURPOSE_SSL_CLIENT + F_SSL_RSA_PRIVATE_DECRYPT NID_rc4 X509_PURPOSE_SSL_SERVER + F_SSL_RSA_PUBLIC_ENCRYPT NID_rc4_40 X509_PURPOSE_TIMESTAMP_SIGN + F_SSL_SESSION_NEW NID_rc5_cbc X509_TRUST_COMPAT + F_SSL_SESSION_PRINT_FP NID_rc5_cfb64 X509_TRUST_EMAIL + F_SSL_SET_FD NID_rc5_ecb X509_TRUST_OBJECT_SIGN + F_SSL_SET_RFD NID_rc5_ofb64 X509_TRUST_OCSP_REQUEST + F_SSL_SET_WFD NID_ripemd160 X509_TRUST_OCSP_SIGN + F_SSL_USE_CERTIFICATE NID_ripemd160WithRSA X509_TRUST_SSL_CLIENT + F_SSL_USE_CERTIFICATE_ASN1 NID_rle_compression X509_TRUST_SSL_SERVER + F_SSL_USE_CERTIFICATE_FILE NID_rsa X509_TRUST_TSA + F_SSL_USE_PRIVATEKEY NID_rsaEncryption X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH + F_SSL_USE_PRIVATEKEY_ASN1 NID_rsadsi X509_V_ERR_AKID_SKID_MISMATCH + F_SSL_USE_PRIVATEKEY_FILE NID_safeContentsBag X509_V_ERR_APPLICATION_VERIFICATION + F_SSL_USE_RSAPRIVATEKEY NID_sdsiCertificate X509_V_ERR_CA_KEY_TOO_SMALL + F_SSL_USE_RSAPRIVATEKEY_ASN1 NID_secretBag X509_V_ERR_CA_MD_TOO_WEAK + F_SSL_USE_RSAPRIVATEKEY_FILE NID_serialNumber X509_V_ERR_CERT_CHAIN_TOO_LONG + F_WRITE_PENDING NID_server_auth X509_V_ERR_CERT_HAS_EXPIRED + GEN_DIRNAME NID_sha X509_V_ERR_CERT_NOT_YET_VALID + GEN_DNS NID_sha1 X509_V_ERR_CERT_REJECTED + GEN_EDIPARTY NID_sha1WithRSA X509_V_ERR_CERT_REVOKED + GEN_EMAIL NID_sha1WithRSAEncryption X509_V_ERR_CERT_SIGNATURE_FAILURE + GEN_IPADD NID_shaWithRSAEncryption X509_V_ERR_CERT_UNTRUSTED + GEN_OTHERNAME NID_stateOrProvinceName X509_V_ERR_CRL_HAS_EXPIRED + GEN_RID NID_subject_alt_name X509_V_ERR_CRL_NOT_YET_VALID + GEN_URI NID_subject_key_identifier X509_V_ERR_CRL_PATH_VALIDATION_ERROR + GEN_X400 NID_surname X509_V_ERR_CRL_SIGNATURE_FAILURE + LIBRESSL_VERSION_NUMBER NID_sxnet X509_V_ERR_DANE_NO_MATCH + MBSTRING_ASC NID_time_stamp X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + MBSTRING_BMP NID_title X509_V_ERR_DIFFERENT_CRL_SCOPE + MBSTRING_FLAG NID_undef X509_V_ERR_EE_KEY_TOO_SMALL + MBSTRING_UNIV NID_uniqueIdentifier X509_V_ERR_EMAIL_MISMATCH + MBSTRING_UTF8 NID_x509Certificate X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD + MIN_RSA_MODULUS_LENGTH_IN_BYTES NID_x509Crl X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD + MODE_ACCEPT_MOVING_WRITE_BUFFER NID_zlib_compression X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD + MODE_AUTO_RETRY NOTHING X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD + MODE_ENABLE_PARTIAL_WRITE OCSP_RESPONSE_STATUS_INTERNALERROR X509_V_ERR_EXCLUDED_VIOLATION + MODE_RELEASE_BUFFERS OCSP_RESPONSE_STATUS_MALFORMEDREQUEST X509_V_ERR_HOSTNAME_MISMATCH + NID_OCSP_sign OCSP_RESPONSE_STATUS_SIGREQUIRED X509_V_ERR_INVALID_CA + NID_SMIMECapabilities OCSP_RESPONSE_STATUS_SUCCESSFUL X509_V_ERR_INVALID_CALL + NID_X500 OCSP_RESPONSE_STATUS_TRYLATER X509_V_ERR_INVALID_EXTENSION + NID_X509 OCSP_RESPONSE_STATUS_UNAUTHORIZED X509_V_ERR_INVALID_NON_CA + NID_ad_OCSP OPENSSL_BUILT_ON X509_V_ERR_INVALID_POLICY_EXTENSION + NID_ad_ca_issuers OPENSSL_CFLAGS X509_V_ERR_INVALID_PURPOSE + NID_algorithm OPENSSL_DIR X509_V_ERR_IP_ADDRESS_MISMATCH + NID_authority_key_identifier OPENSSL_ENGINES_DIR X509_V_ERR_KEYUSAGE_NO_CERTSIGN + NID_basic_constraints OPENSSL_PLATFORM X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + NID_bf_cbc OPENSSL_VERSION X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE + NID_bf_cfb64 OPENSSL_VERSION_NUMBER X509_V_ERR_NO_EXPLICIT_POLICY + NID_bf_ecb OP_ALL X509_V_ERR_NO_VALID_SCTS + NID_bf_ofb64 OP_ALLOW_NO_DHE_KEX X509_V_ERR_OCSP_CERT_UNKNOWN + NID_cast5_cbc OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION X509_V_ERR_OCSP_VERIFY_FAILED + NID_cast5_cfb64 OP_CIPHER_SERVER_PREFERENCE X509_V_ERR_OCSP_VERIFY_NEEDED + NID_cast5_ecb OP_CISCO_ANYCONNECT X509_V_ERR_OUT_OF_MEM + NID_cast5_ofb64 OP_COOKIE_EXCHANGE X509_V_ERR_PATH_LENGTH_EXCEEDED + NID_certBag OP_CRYPTOPRO_TLSEXT_BUG X509_V_ERR_PATH_LOOP + NID_certificate_policies OP_DONT_INSERT_EMPTY_FRAGMENTS X509_V_ERR_PERMITTED_VIOLATION + NID_client_auth OP_ENABLE_MIDDLEBOX_COMPAT X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED + NID_code_sign OP_EPHEMERAL_RSA X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED + NID_commonName OP_LEGACY_SERVER_CONNECT X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION + NID_countryName OP_MICROSOFT_BIG_SSLV3_BUFFER X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + NID_crlBag OP_MICROSOFT_SESS_ID_BUG X509_V_ERR_STORE_LOOKUP + NID_crl_distribution_points OP_MSIE_SSLV2_RSA_PADDING X509_V_ERR_SUBJECT_ISSUER_MISMATCH + NID_crl_number OP_NETSCAPE_CA_DN_BUG X509_V_ERR_SUBTREE_MINMAX + NID_crl_reason OP_NETSCAPE_CHALLENGE_BUG X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 + NID_delta_crl OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_ALGORITHM + NID_des_cbc OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_CURVE + NID_des_cfb64 OP_NON_EXPORT_FIRST X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM + NID_des_ecb OP_NO_ANTI_REPLAY X509_V_ERR_SUITE_B_INVALID_VERSION + NID_des_ede OP_NO_CLIENT_RENEGOTIATION X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED + NID_des_ede3 OP_NO_COMPRESSION X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY + NID_des_ede3_cbc OP_NO_ENCRYPT_THEN_MAC X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE + NID_des_ede3_cfb64 OP_NO_QUERY_MTU X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE + NID_des_ede3_ofb64 OP_NO_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL + NID_des_ede_cbc OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER + NID_des_ede_cfb64 OP_NO_SSL_MASK X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT + NID_des_ede_ofb64 OP_NO_SSLv2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + NID_des_ofb64 OP_NO_SSLv3 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE + NID_description OP_NO_TICKET X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION + NID_desx_cbc OP_NO_TLSv1 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION + NID_dhKeyAgreement OP_NO_TLSv1_1 X509_V_ERR_UNNESTED_RESOURCE + NID_dnQualifier OP_NO_TLSv1_2 X509_V_ERR_UNSPECIFIED + NID_dsa OP_NO_TLSv1_3 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX + NID_dsaWithSHA OP_PKCS1_CHECK_1 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE + NID_dsaWithSHA1 OP_PKCS1_CHECK_2 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE + NID_dsaWithSHA1_2 OP_PRIORITIZE_CHACHA X509_V_ERR_UNSUPPORTED_NAME_SYNTAX + NID_dsa_2 OP_SAFARI_ECDHE_ECDSA_BUG X509_V_FLAG_ALLOW_PROXY_CERTS + NID_email_protect OP_SINGLE_DH_USE X509_V_FLAG_CB_ISSUER_CHECK + NID_ext_key_usage OP_SINGLE_ECDH_USE X509_V_FLAG_CHECK_SS_SIGNATURE + NID_ext_req OP_SSLEAY_080_CLIENT_DH_BUG X509_V_FLAG_CRL_CHECK + NID_friendlyName OP_SSLREF2_REUSE_CERT_TYPE_BUG X509_V_FLAG_CRL_CHECK_ALL + NID_givenName OP_TLSEXT_PADDING X509_V_FLAG_EXPLICIT_POLICY + NID_hmacWithSHA1 OP_TLS_BLOCK_PADDING_BUG X509_V_FLAG_EXTENDED_CRL_SUPPORT + NID_id_ad OP_TLS_D5_BUG X509_V_FLAG_IGNORE_CRITICAL + NID_id_ce OP_TLS_ROLLBACK_BUG X509_V_FLAG_INHIBIT_ANY + NID_id_kp READING X509_V_FLAG_INHIBIT_MAP + NID_id_pbkdf2 RECEIVED_SHUTDOWN X509_V_FLAG_NOTIFY_POLICY + NID_id_pe RSA_3 X509_V_FLAG_NO_ALT_CHAINS + NID_id_pkix RSA_F4 X509_V_FLAG_NO_CHECK_TIME + NID_id_qt_cps R_BAD_AUTHENTICATION_TYPE X509_V_FLAG_PARTIAL_CHAIN + NID_id_qt_unotice R_BAD_CHECKSUM X509_V_FLAG_POLICY_CHECK + NID_idea_cbc R_BAD_MAC_DECODE X509_V_FLAG_POLICY_MASK + NID_idea_cfb64 R_BAD_RESPONSE_ARGUMENT X509_V_FLAG_SUITEB_128_LOS + NID_idea_ecb R_BAD_SSL_FILETYPE X509_V_FLAG_SUITEB_128_LOS_ONLY + NID_idea_ofb64 R_BAD_SSL_SESSION_ID_LENGTH X509_V_FLAG_SUITEB_192_LOS + NID_info_access R_BAD_STATE X509_V_FLAG_TRUSTED_FIRST + NID_initials R_BAD_WRITE_RETRY X509_V_FLAG_USE_CHECK_TIME + NID_invalidity_date R_CHALLENGE_IS_DIFFERENT X509_V_FLAG_USE_DELTAS + NID_issuer_alt_name R_CIPHER_TABLE_SRC_ERROR X509_V_FLAG_X509_STRICT + NID_keyBag R_INVALID_CHALLENGE_LENGTH X509_V_OK + NID_key_usage R_NO_CERTIFICATE_SET XN_FLAG_COMPAT + NID_localKeyID R_NO_CERTIFICATE_SPECIFIED XN_FLAG_DN_REV + NID_localityName R_NO_CIPHER_LIST XN_FLAG_DUMP_UNKNOWN_FIELDS + NID_md2 R_NO_CIPHER_MATCH XN_FLAG_FN_ALIGN + NID_md2WithRSAEncryption R_NO_PRIVATEKEY XN_FLAG_FN_LN + NID_md5 R_NO_PUBLICKEY XN_FLAG_FN_MASK + NID_md5WithRSA R_NULL_SSL_CTX XN_FLAG_FN_NONE + NID_md5WithRSAEncryption R_PEER_DID_NOT_RETURN_A_CERTIFICATE XN_FLAG_FN_OID + NID_md5_sha1 R_PEER_ERROR XN_FLAG_FN_SN + NID_mdc2 R_PEER_ERROR_CERTIFICATE XN_FLAG_MULTILINE + NID_mdc2WithRSA R_PEER_ERROR_NO_CIPHER XN_FLAG_ONELINE + NID_ms_code_com R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE XN_FLAG_RFC2253 + NID_ms_code_ind R_PUBLIC_KEY_ENCRYPT_ERROR XN_FLAG_SEP_COMMA_PLUS + NID_ms_ctl_sign R_PUBLIC_KEY_IS_NOT_RSA XN_FLAG_SEP_CPLUS_SPC + NID_ms_efs R_READ_WRONG_PACKET_TYPE XN_FLAG_SEP_MASK + NID_ms_ext_req R_SHORT_READ XN_FLAG_SEP_MULTILINE + NID_ms_sgc R_SSL_SESSION_ID_IS_DIFFERENT XN_FLAG_SEP_SPLUS_SPC + NID_name R_UNABLE_TO_EXTRACT_PUBLIC_KEY XN_FLAG_SPC_EQ + +=head2 INTERNAL ONLY functions (do not use these) + +The following functions are not intended for use from outside of L module. +They might be removed, renamed or changed without prior notice in future version. + +Simply B! + +=over + +=item * hello + +=item * blength + +=item * constant + +=back + +=head1 EXAMPLES + +One very good example to look at is the implementation of C in the +C file. + +The following is a simple SSLeay client (with too little error checking :-( + + #!/usr/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) + or 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; + +The following is a simple SSLeay echo server (non forking): + + #!/usr/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) + or 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 so it avoids +all the socket code overhead. Only caveat is opening an 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 and C are wired to SSL. + + #!/usr/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 INSTALLATION + +See README and README.* in the distribution directory for installation guidance on a variety of platforms. + +=head1 LIMITATIONS + +C uses an 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, 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 convenience 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 + +An OpenSSL bug CVE-2015-0290 "OpenSSL Multiblock Corrupted Pointer Issue" +can cause POST requests of over 90kB to fail or crash. This bug is reported to be fixed in +OpenSSL 1.0.2a. + +Autoloader emits a + + 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 does not appear to work. This may +well be an openssl problem (e.g. see C line 1029). Try using +C 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 and/or C (such as in Solaris +platforms - but it's been suggested that cryptorand daemon from the 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 or to operate insecurely +if you use C. What happens is that when too much +randomness is drawn from the operating system's randomness pool +then randomness can temporarily be unavailable. C 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 solves this dilemma more pragmatically by simply returning +predictable "random" numbers. SomeC< /dev/urandom> emulation software +however actually seems to implement C semantics. Caveat emptor. + +I've been pointed to two such daemons by Mik Firestone +who has used them on Solaris 8: + +=over + +=item 1 + +Entropy Gathering Daemon (EGD) at L + +=item 2 + +Pseudo-random number generating daemon (PRNGD) at +L + +=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) + or 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 (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 the 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 +shortcoming, but using the 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 onwards in C). +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/TLS 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 + $Net::SSLeay::ssl_version = 11; # Insist on TLSv1.1 + $Net::SSLeay::ssl_version = 12; # Insist on TLSv1.2 + $Net::SSLeay::ssl_version = 13; # Insist on TLSv1.3 + +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 the SSL handshake level), try this option +before mailing me. + +On some systems, OpenSSL may be compiled without support for SSLv2. +If this is the case, Net::SSLeay will warn if ssl_version has been set +to 2. + +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 then 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 the C function +is implemented. + +The high level API functions use a global file handle C +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). However, you +may run into problems if you call undocumented internal functions in an +interleaved fashion. The best solution is to "require Net::SSLeay" in +one thread after all the threads have been created. + +=head1 DIAGNOSTICS + +=over + +=item Random number generator not seeded!!! + +B<(W)> This warning indicates that C was not able to read +C or C, 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 failed. + +=item open_tcp_connection: failed `server', 123 ($!) + +The name was resolved, but establishing the TCP connection failed. + +=item msg 123: 1 - error:140770F8:SSL routines:SSL23_GET_SERVER_HELLO:unknown proto + +SSLeay error string. The first number (123) is the PID, the 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 an 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 to do just that). + +=back + +=head1 SECURITY + +You can mitigate some of the security vulnerabilities that might be present in your SSL/TLS application: + + +=head2 BEAST Attack + +http://blogs.cisco.com/security/beat-the-beast-with-tls/ +https://community.qualys.com/blogs/securitylabs/2011/10/17/mitigating-the-beast-attack-on-tls +http://blog.zoller.lu/2011/09/beast-summary-tls-cbc-countermeasures.html + +The BEAST attack relies on a weakness in the way CBC mode is used in SSL/TLS. +In OpenSSL versions 0.9.6d and later, the protocol-level mitigation is enabled by default, +thus making it not vulnerable to the BEAST attack. + +Solutions: + +=over + +=item * Compile with OpenSSL versions 0.9.6d or later, which enables SSL_OP_ALL by default + +=item * Ensure SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS is not enabled (its not enabled by default) + +=item * Don't support SSLv2, SSLv3 + +=item * Actively control the ciphers your server supports with set_cipher_list: + +=back + +Net::SSLeay::set_cipher_list($ssl, 'RC4-SHA:HIGH:!ADH'); + + +=head2 Session Resumption + +http://www.openssl.org/docs/ssl/SSL_CTX_set_options.html + +The SSL Labs vulnerability test on your SSL server might report in red: + +Session resumption No (IDs assigned but not accepted) + +This report is not really bug or a vulnerability, since the server will not +accept session resumption requests. +However, you can prevent this noise in the report by disabling the session cache altogether: +Net::SSLeay::CTX_set_session_cache_mode($ssl_ctx, Net::SSLeay::SESS_CACHE_OFF()); +Use 0 if you don't have SESS_CACHE_OFF constant. + + +=head2 Secure Renegotiation and DoS Attack + +https://community.qualys.com/blogs/securitylabs/2011/10/31/tls-renegotiation-and-denial-of-service-attacks + +This is not a "security flaw," it is more of a DoS vulnerability. + +Solutions: + +=over + +=item * Do not support SSLv2 + +=item * Do not set the SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION option + +=item * Compile with OpenSSL 0.9.8m or later + +=back + +=head1 BUGS + +If you encounter a problem with this module that you believe is a bug, +please report it in one of the following ways: + +=over + +=item * + +L +under the Net-SSLeay GitHub project at +L; + +=item * + +L using +the CPAN RT bug tracker's web interface at +L; + +=item * + +send an email to the CPAN RT bug tracker at +L. + +=back + +Please make sure your bug report includes the following information: + +=over + +=item * the code you are trying to run; + +=item * your operating system name and version; + +=item * the output of C; + +=item * the version of OpenSSL or LibreSSL you are using. + +=back + +=head1 AUTHOR + +Originally written by Sampo Kellomäki. + +Maintained by Florian Ragwitz between November 2005 and January 2010. + +Maintained by Mike McCauley between November 2005 and June 2018. + +Maintained by Chris Novakovic, Tuure Vartiainen and Heikki Vatiainen since June 2018. + +=head1 COPYRIGHT + +Copyright (c) 1996-2003 Sampo Kellomäki + +Copyright (c) 2005-2010 Florian Ragwitz + +Copyright (c) 2005-2018 Mike McCauley + +Copyright (c) 2018- Chris Novakovic + +Copyright (c) 2018- Tuure Vartiainen + +Copyright (c) 2018- Heikki Vatiainen + +All rights reserved. + +=head1 LICENSE + +This module is released under the terms of the Artistic License 2.0. For +details, see the C file distributed with Net-SSLeay's source code. + +=head1 SEE ALSO + + Net::SSLeay::Handle - File handle interface + ./examples - Example servers and a clients + - OpenSSL source, documentation, etc + openssl-users-request@openssl.org - General OpenSSL mailing list + - TLS 1.0 specification + - HTTP specifications + - How to send password + - Entropy Gathering Daemon (EGD) + + - pseudo-random number generating daemon (PRNGD) + perl(1) + perlref(1) + perllol(1) + perldoc ~openssl/doc/ssl/SSL_CTX_set_verify.pod diff --git a/lib/Net/SSLeay/Handle.pm b/lib/Net/SSLeay/Handle.pm new file mode 100644 index 0000000..7cf53c5 --- /dev/null +++ b/lib/Net/SSLeay/Handle.pm @@ -0,0 +1,430 @@ +package Net::SSLeay::Handle; + +use 5.8.1; + +use strict; + +use Socket; +use Net::SSLeay; + +require Exporter; + +=encoding utf-8 + +=head1 NAME + +Net::SSLeay::Handle - Perl module that lets SSL (HTTPS) sockets be +handled as standard file handles. + +=head1 SYNOPSIS + + use Net::SSLeay::Handle qw/shutdown/; + my ($host, $port) = ("localhost", 443); + + tie(*SSL, "Net::SSLeay::Handle", $host, $port); + + print SSL "GET / HTTP/1.0\r\n"; + shutdown(\*SSL, 1); + print while (); + close SSL; + +=head1 DESCRIPTION + +Net::SSLeay::Handle allows you to request and receive HTTPS web pages +using "old-fashion" file handles as in: + + print SSL "GET / HTTP/1.0\r\n"; + +and + + print while (); + +If you export the shutdown routine, then the only extra code that +you need to add to your program is the tie function as in: + + my $socket; + if ($scheme eq "https") { + tie(*S2, "Net::SSLeay::Handle", $host, $port); + $socket = \*S2; + else { + $socket = Net::SSLeay::Handle->make_socket($host, $port); + } + print $socket $request_headers; + ... + +=cut + +use vars qw(@ISA @EXPORT_OK $VERSION); +@ISA = qw(Exporter); +@EXPORT_OK = qw(shutdown); +$VERSION = '1.88'; + +my $Initialized; #-- only _initialize() once +my $Debug = 0; #-- pretty hokey + +#== Tie Handle Methods ======================================================== +# +# see perldoc perltie for details. +# +#============================================================================== + +sub TIEHANDLE { + my ($class, $socket, $port) = @_; + $Debug > 10 and print "TIEHANDLE(@{[join ', ', @_]})\n"; + + ref $socket eq "GLOB" or $socket = $class->make_socket($socket, $port); + + $class->_initialize(); + + my $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); + my $ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); + + my $fileno = fileno($socket); + + Net::SSLeay::set_fd($ssl, $fileno); # Must use fileno + + my $resp = Net::SSLeay::connect($ssl); + + $Debug and print "Cipher '" . Net::SSLeay::get_cipher($ssl) . "'\n"; + + my $self = bless { + ssl => $ssl, + ctx => $ctx, + socket => $socket, + fileno => $fileno, + }, $class; + + return $self; +} + +sub PRINT { + my $self = shift; + + my $ssl = _get_ssl($self); + my $resp = 0; + for my $msg (@_) { + defined $msg or last; + $resp = Net::SSLeay::write($ssl, $msg) or last; + } + return $resp; +} + +sub READLINE { + my $self = shift; + my $ssl = _get_ssl($self); + if (wantarray) { + my @lines; + while (my $line = Net::SSLeay::ssl_read_until($ssl)) { + push @lines, $line; + } + return @lines; + } else { + my $line = Net::SSLeay::ssl_read_until($ssl); + return $line ? $line : undef; + } +} + +sub READ { + my ($self, $buf, $len, $offset) = \ (@_); + my $ssl = _get_ssl($$self); + defined($$offset) or + return length($$buf = Net::SSLeay::ssl_read_all($ssl, $$len)); + + defined(my $read = Net::SSLeay::ssl_read_all($ssl, $$len)) + or return undef; + + my $buf_len = length($$buf); + $$offset > $buf_len and $$buf .= chr(0) x ($$offset - $buf_len); + substr($$buf, $$offset) = $read; + return length($read); +} + +sub WRITE { + my $self = shift; + my ($buf, $len, $offset) = @_; + $offset = 0 unless defined $offset; + + # Return number of characters written. + my $ssl = $self->_get_ssl(); + return $len if Net::SSLeay::write($ssl, substr($buf, $offset, $len)); + return undef; +} + +sub CLOSE { + my $self = shift; + my $fileno = $self->{fileno}; + $Debug > 10 and print "close($fileno)\n"; + Net::SSLeay::free ($self->{ssl}); + Net::SSLeay::CTX_free ($self->{ctx}); + close $self->{socket}; +} + +sub FILENO { $_[0]->{fileno} } + + +=head1 FUNCTIONS + +=over + +=item shutdown + + shutdown(\*SOCKET, $mode) + +Calls to the main shutdown() don't work with tied sockets created with this +module. This shutdown should be able to distinquish between tied and untied +sockets and do the right thing. + +=cut + +sub shutdown { + my ($obj, @params) = @_; + + my $socket = UNIVERSAL::isa($obj, 'Net::SSLeay::Handle') ? + $obj->{socket} : $obj; + return shutdown($socket, @params); +} + +=item debug + + my $debug = Net::SSLeay::Handle->debug() + Net::SSLeay::Handle->debug(1) + +Get/set debugging mode. Always returns the debug value before the function call. +if an additional argument is given the debug option will be set to this value. + +=cut + +sub debug { + my ($class, $debug) = @_; + my $old_debug = $Debug; + @_ >1 and $Debug = $debug || 0; + return $old_debug; +} + +#=== Internal Methods ========================================================= + +=item make_socket + + my $sock = Net::SSLeay::Handle->make_socket($host, $port); + +Creates a socket that is connected to $post using $port. It uses +$Net::SSLeay::proxyhost and proxyport if set and authentificates itself against +this proxy depending on $Net::SSLeay::proxyauth. It also turns autoflush on for +the created socket. + +=cut + +sub make_socket { + my ($class, $host, $port) = @_; + $Debug > 10 and print "_make_socket(@{[join ', ', @_]})\n"; + $host ||= 'localhost'; + $port ||= 443; + + my $phost = $Net::SSLeay::proxyhost; + my $pport = $Net::SSLeay::proxyhost ? $Net::SSLeay::proxyport : $port; + + my $dest_ip = gethostbyname($phost || $host); + my $host_params = sockaddr_in($pport, $dest_ip); + + socket(my $socket, &PF_INET(), &SOCK_STREAM(), 0) or die "socket: $!"; + connect($socket, $host_params) or die "connect: $!"; + + my $old_select = select($socket); $| = 1; select($old_select); + $phost and do { + my $auth = $Net::SSLeay::proxyauth; + my $CRLF = $Net::SSLeay::CRLF; + print $socket "CONNECT $host:$port HTTP/1.0$auth$CRLF$CRLF"; + my $line = <$socket>; + }; + return $socket; +} + +=back + +=cut + +sub _initialize { + $Initialized++ and return; + Net::SSLeay::load_error_strings(); + Net::SSLeay::SSLeay_add_ssl_algorithms(); + Net::SSLeay::randomize(); +} + +sub __dummy { + my $host = $Net::SSLeay::proxyhost; + my $port = $Net::SSLeay::proxyport; + my $auth = $Net::SSLeay::proxyauth; +} + +#--- _get_self($socket) ------------------------------------------------------- +# Returns a hash containing attributes for $socket (= \*SOMETHING) based +# on fileno($socket). Will return undef if $socket was not created here. +#------------------------------------------------------------------------------ + +sub _get_self { return $_[0]; } + +#--- _get_ssl($socket) -------------------------------------------------------- +# Returns a the "ssl" attribute for $socket (= \*SOMETHING) based +# on fileno($socket). Will cause a warning and return undef if $socket was not +# created here. +#------------------------------------------------------------------------------ + +sub _get_ssl { + return $_[0]->{ssl}; +} + +1; + +__END__ + +=head2 USING EXISTING SOCKETS + +One of the motivations for writing this module was to avoid +duplicating socket creation code (which is mostly error handling). +The calls to tie() above where it is passed a $host and $port is +provided for convenience testing. If you already have a socket +connected to the right host and port, S1, then you can do something +like: + + my $socket \*S1; + if ($scheme eq "https") { + tie(*S2, "Net::SSLeay::Handle", $socket); + $socket = \*S2; + } + my $last_sel = select($socket); $| = 1; select($last_sel); + print $socket $request_headers; + ... + +Note: As far as I know you must be careful with the globs in the tie() +function. The first parameter must be a glob (*SOMETHING) and the +last parameter must be a reference to a glob (\*SOMETHING_ELSE) or a +scaler that was assigned to a reference to a glob (as in the example +above) + +Also, the two globs must be different. When I tried to use the same +glob, I got a core dump. + +=head2 EXPORT + +None by default. + +You can export the shutdown() function. + +It is suggested that you do export shutdown() or use the fully +qualified Net::SSLeay::Handle::shutdown() function to shutdown SSL +sockets. It should be smart enough to distinguish between SSL and +non-SSL sockets and do the right thing. + +=head1 EXAMPLES + + use Net::SSLeay::Handle qw/shutdown/; + my ($host, $port) = ("localhost", 443); + + tie(*SSL, "Net::SSLeay::Handle", $host, $port); + + print SSL "GET / HTTP/1.0\r\n"; + shutdown(\*SSL, 1); + print while (); + close SSL; + +=head1 TODO + +Better error handling. Callback routine? + +=head1 CAVEATS + +Tying to a file handle is a little tricky (for me at least). + +The first parameter to tie() must be a glob (*SOMETHING) and the last +parameter must be a reference to a glob (\*SOMETHING_ELSE) or a scaler +that was assigned to a reference to a glob ($s = \*SOMETHING_ELSE). +Also, the two globs must be different. When I tried to use the same +glob, I got a core dump. + +I was able to associate attributes to globs created by this module +(like *SSL above) by making a hash of hashes keyed by the file head1. + +=head1 CHANGES + +Please see Net-SSLeay-Handle-0.50/Changes file. + +=head1 BUGS + +If you encounter a problem with this module that you believe is a bug, +please report it in one of the following ways: + +=over + +=item * + +L +under the Net-SSLeay GitHub project at +L; + +=item * + +L using +the CPAN RT bug tracker's web interface at +L; + +=item * + +send an email to the CPAN RT bug tracker at +L. + +=back + +Please make sure your bug report includes the following information: + +=over + +=item * the code you are trying to run; + +=item * your operating system name and version; + +=item * the output of C; + +=item * the version of OpenSSL or LibreSSL you are using. + +=back + +=head1 AUTHOR + +Originally written by Jim Bowlin. + +Maintained by Sampo Kellomäki between July 2001 and August 2003. + +Maintained by Florian Ragwitz between November 2005 and January 2010. + +Maintained by Mike McCauley between November 2005 and June 2018. + +Maintained by Chris Novakovic, Tuure Vartiainen and Heikki Vatiainen since June 2018. + +=head1 COPYRIGHT + +Copyright (c) 2001 Jim Bowlin + +Copyright (c) 2001-2003 Sampo Kellomäki + +Copyright (c) 2005-2010 Florian Ragwitz + +Copyright (c) 2005-2018 Mike McCauley + +Copyright (c) 2018- Chris Novakovic + +Copyright (c) 2018- Tuure Vartiainen + +Copyright (c) 2018- Heikki Vatiainen + +All rights reserved. + +=head1 LICENSE + +This module is released under the terms of the Artistic License 2.0. For +details, see the C file distributed with Net-SSLeay's source code. + +=head1 SEE ALSO + +Net::SSLeay, perl(1), http://openssl.org/ + +=cut diff --git a/ppport.h b/ppport.h new file mode 100644 index 0000000..6d650f4 --- /dev/null +++ b/ppport.h @@ -0,0 +1,7063 @@ +#if 0 +<<'SKIP'; +#endif +/* +---------------------------------------------------------------------- + + ppport.h -- Perl/Pollution/Portability Version 3.19 + + Automatically created by Devel::PPPort running under perl 5.014002. + + Do NOT edit this file directly! -- Edit PPPort_pm.PL and the + includes in parts/inc/ instead. + + Use 'perldoc ppport.h' to view the documentation below. + +---------------------------------------------------------------------- + +SKIP + +=pod + +=head1 NAME + +ppport.h - Perl/Pollution/Portability version 3.19 + +=head1 SYNOPSIS + + perl ppport.h [options] [source files] + + Searches current directory for files if no [source files] are given + + --help show short help + + --version show version + + --patch=file write one patch file with changes + --copy=suffix write changed copies with suffix + --diff=program use diff program and options + + --compat-version=version provide compatibility with Perl version + --cplusplus accept C++ comments + + --quiet don't output anything except fatal errors + --nodiag don't show diagnostics + --nohints don't show hints + --nochanges don't suggest changes + --nofilter don't filter input files + + --strip strip all script and doc functionality from + ppport.h + + --list-provided list provided API + --list-unsupported list unsupported API + --api-info=name show Perl API portability information + +=head1 COMPATIBILITY + +This version of F is designed to support operation with Perl +installations back to 5.003, and has been tested up to 5.10.0. + +=head1 OPTIONS + +=head2 --help + +Display a brief usage summary. + +=head2 --version + +Display the version of F. + +=head2 --patch=I + +If this option is given, a single patch file will be created if +any changes are suggested. This requires a working diff program +to be installed on your system. + +=head2 --copy=I + +If this option is given, a copy of each file will be saved with +the given suffix that contains the suggested changes. This does +not require any external programs. Note that this does not +automagially add a dot between the original filename and the +suffix. If you want the dot, you have to include it in the option +argument. + +If neither C<--patch> or C<--copy> are given, the default is to +simply print the diffs for each file. This requires either +C or a C program to be installed. + +=head2 --diff=I + +Manually set the diff program and options to use. The default +is to use C, when installed, and output unified +context diffs. + +=head2 --compat-version=I + +Tell F to check for compatibility with the given +Perl version. The default is to check for compatibility with Perl +version 5.003. You can use this option to reduce the output +of F if you intend to be backward compatible only +down to a certain Perl version. + +=head2 --cplusplus + +Usually, F will detect C++ style comments and +replace them with C style comments for portability reasons. +Using this option instructs F to leave C++ +comments untouched. + +=head2 --quiet + +Be quiet. Don't print anything except fatal errors. + +=head2 --nodiag + +Don't output any diagnostic messages. Only portability +alerts will be printed. + +=head2 --nohints + +Don't output any hints. Hints often contain useful portability +notes. Warnings will still be displayed. + +=head2 --nochanges + +Don't suggest any changes. Only give diagnostic output and hints +unless these are also deactivated. + +=head2 --nofilter + +Don't filter the list of input files. By default, files not looking +like source code (i.e. not *.xs, *.c, *.cc, *.cpp or *.h) are skipped. + +=head2 --strip + +Strip all script and documentation functionality from F. +This reduces the size of F dramatically and may be useful +if you want to include F in smaller modules without +increasing their distribution size too much. + +The stripped F will have a C<--unstrip> option that allows +you to undo the stripping, but only if an appropriate C +module is installed. + +=head2 --list-provided + +Lists the API elements for which compatibility is provided by +F. Also lists if it must be explicitly requested, +if it has dependencies, and if there are hints or warnings for it. + +=head2 --list-unsupported + +Lists the API elements that are known not to be supported by +F and below which version of Perl they probably +won't be available or work. + +=head2 --api-info=I + +Show portability information for API elements matching I. +If I is surrounded by slashes, it is interpreted as a regular +expression. + +=head1 DESCRIPTION + +In order for a Perl extension (XS) module to be as portable as possible +across differing versions of Perl itself, certain steps need to be taken. + +=over 4 + +=item * + +Including this header is the first major one. This alone will give you +access to a large part of the Perl API that hasn't been available in +earlier Perl releases. Use + + perl ppport.h --list-provided + +to see which API elements are provided by ppport.h. + +=item * + +You should avoid using deprecated parts of the API. For example, using +global Perl variables without the C prefix is deprecated. Also, +some API functions used to have a C prefix. Using this form is +also deprecated. You can safely use the supported API, as F +will provide wrappers for older Perl versions. + +=item * + +If you use one of a few functions or variables that were not present in +earlier versions of Perl, and that can't be provided using a macro, you +have to explicitly request support for these functions by adding one or +more C<#define>s in your source code before the inclusion of F. + +These functions or variables will be marked C in the list shown +by C<--list-provided>. + +Depending on whether you module has a single or multiple files that +use such functions or variables, you want either C or global +variants. + +For a C function or variable (used only in a single source +file), use: + + #define NEED_function + #define NEED_variable + +For a global function or variable (used in multiple source files), +use: + + #define NEED_function_GLOBAL + #define NEED_variable_GLOBAL + +Note that you mustn't have more than one global request for the +same function or variable in your project. + + Function / Variable Static Request Global Request + ----------------------------------------------------------------------------------------- + PL_parser NEED_PL_parser NEED_PL_parser_GLOBAL + PL_signals NEED_PL_signals NEED_PL_signals_GLOBAL + eval_pv() NEED_eval_pv NEED_eval_pv_GLOBAL + grok_bin() NEED_grok_bin NEED_grok_bin_GLOBAL + grok_hex() NEED_grok_hex NEED_grok_hex_GLOBAL + grok_number() NEED_grok_number NEED_grok_number_GLOBAL + grok_numeric_radix() NEED_grok_numeric_radix NEED_grok_numeric_radix_GLOBAL + grok_oct() NEED_grok_oct NEED_grok_oct_GLOBAL + load_module() NEED_load_module NEED_load_module_GLOBAL + my_snprintf() NEED_my_snprintf NEED_my_snprintf_GLOBAL + my_sprintf() NEED_my_sprintf NEED_my_sprintf_GLOBAL + my_strlcat() NEED_my_strlcat NEED_my_strlcat_GLOBAL + my_strlcpy() NEED_my_strlcpy NEED_my_strlcpy_GLOBAL + newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL + newRV_noinc() NEED_newRV_noinc NEED_newRV_noinc_GLOBAL + newSV_type() NEED_newSV_type NEED_newSV_type_GLOBAL + newSVpvn_flags() NEED_newSVpvn_flags NEED_newSVpvn_flags_GLOBAL + newSVpvn_share() NEED_newSVpvn_share NEED_newSVpvn_share_GLOBAL + pv_display() NEED_pv_display NEED_pv_display_GLOBAL + pv_escape() NEED_pv_escape NEED_pv_escape_GLOBAL + pv_pretty() NEED_pv_pretty NEED_pv_pretty_GLOBAL + sv_2pv_flags() NEED_sv_2pv_flags NEED_sv_2pv_flags_GLOBAL + sv_2pvbyte() NEED_sv_2pvbyte NEED_sv_2pvbyte_GLOBAL + sv_catpvf_mg() NEED_sv_catpvf_mg NEED_sv_catpvf_mg_GLOBAL + sv_catpvf_mg_nocontext() NEED_sv_catpvf_mg_nocontext NEED_sv_catpvf_mg_nocontext_GLOBAL + sv_pvn_force_flags() NEED_sv_pvn_force_flags NEED_sv_pvn_force_flags_GLOBAL + sv_setpvf_mg() NEED_sv_setpvf_mg NEED_sv_setpvf_mg_GLOBAL + sv_setpvf_mg_nocontext() NEED_sv_setpvf_mg_nocontext NEED_sv_setpvf_mg_nocontext_GLOBAL + vload_module() NEED_vload_module NEED_vload_module_GLOBAL + vnewSVpvf() NEED_vnewSVpvf NEED_vnewSVpvf_GLOBAL + warner() NEED_warner NEED_warner_GLOBAL + +To avoid namespace conflicts, you can change the namespace of the +explicitly exported functions / variables using the C +macro. Just C<#define> the macro before including C: + + #define DPPP_NAMESPACE MyOwnNamespace_ + #include "ppport.h" + +The default namespace is C. + +=back + +The good thing is that most of the above can be checked by running +F on your source code. See the next section for +details. + +=head1 EXAMPLES + +To verify whether F is needed for your module, whether you +should make any changes to your code, and whether any special defines +should be used, F can be run as a Perl script to check your +source code. Simply say: + + perl ppport.h + +The result will usually be a list of patches suggesting changes +that should at least be acceptable, if not necessarily the most +efficient solution, or a fix for all possible problems. + +If you know that your XS module uses features only available in +newer Perl releases, if you're aware that it uses C++ comments, +and if you want all suggestions as a single patch file, you could +use something like this: + + perl ppport.h --compat-version=5.6.0 --cplusplus --patch=test.diff + +If you only want your code to be scanned without any suggestions +for changes, use: + + perl ppport.h --nochanges + +You can specify a different C program or options, using +the C<--diff> option: + + perl ppport.h --diff='diff -C 10' + +This would output context diffs with 10 lines of context. + +If you want to create patched copies of your files instead, use: + + perl ppport.h --copy=.new + +To display portability information for the C function, +use: + + perl ppport.h --api-info=newSVpvn + +Since the argument to C<--api-info> can be a regular expression, +you can use + + perl ppport.h --api-info=/_nomg$/ + +to display portability information for all C<_nomg> functions or + + perl ppport.h --api-info=/./ + +to display information for all known API elements. + +=head1 BUGS + +If this version of F is causing failure during +the compilation of this module, please check if newer versions +of either this module or C are available on CPAN +before sending a bug report. + +If F was generated using the latest version of +C and is causing failure of this module, please +file a bug report using the CPAN Request Tracker at L. + +Please include the following information: + +=over 4 + +=item 1. + +The complete output from running "perl -V" + +=item 2. + +This file. + +=item 3. + +The name and version of the module you were trying to build. + +=item 4. + +A full log of the build that failed. + +=item 5. + +Any other information that you think could be relevant. + +=back + +For the latest version of this code, please get the C +module from CPAN. + +=head1 COPYRIGHT + +Version 3.x, Copyright (c) 2004-2009, Marcus Holland-Moritz. + +Version 2.x, Copyright (C) 2001, Paul Marquess. + +Version 1.x, Copyright (C) 1999, Kenneth Albanowski. + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=head1 SEE ALSO + +See L. + +=cut + +use strict; + +# Disable broken TRIE-optimization +BEGIN { eval '${^RE_TRIE_MAXBUF} = -1' if $] >= 5.009004 && $] <= 5.009005 } + +my $VERSION = 3.19; + +my %opt = ( + quiet => 0, + diag => 1, + hints => 1, + changes => 1, + cplusplus => 0, + filter => 1, + strip => 0, + version => 0, +); + +my($ppport) = $0 =~ /([\w.]+)$/; +my $LF = '(?:\r\n|[\r\n])'; # line feed +my $HS = "[ \t]"; # horizontal whitespace + +# Never use C comments in this file! +my $ccs = '/'.'*'; +my $cce = '*'.'/'; +my $rccs = quotemeta $ccs; +my $rcce = quotemeta $cce; + +eval { + require Getopt::Long; + Getopt::Long::GetOptions(\%opt, qw( + help quiet diag! filter! hints! changes! cplusplus strip version + patch=s copy=s diff=s compat-version=s + list-provided list-unsupported api-info=s + )) or usage(); +}; + +if ($@ and grep /^-/, @ARGV) { + usage() if "@ARGV" =~ /^--?h(?:elp)?$/; + die "Getopt::Long not found. Please don't use any options.\n"; +} + +if ($opt{version}) { + print "This is $0 $VERSION.\n"; + exit 0; +} + +usage() if $opt{help}; +strip() if $opt{strip}; + +if (exists $opt{'compat-version'}) { + my($r,$v,$s) = eval { parse_version($opt{'compat-version'}) }; + if ($@) { + die "Invalid version number format: '$opt{'compat-version'}'\n"; + } + die "Only Perl 5 is supported\n" if $r != 5; + die "Invalid version number: $opt{'compat-version'}\n" if $v >= 1000 || $s >= 1000; + $opt{'compat-version'} = sprintf "%d.%03d%03d", $r, $v, $s; +} +else { + $opt{'compat-version'} = 5; +} + +my %API = map { /^(\w+)\|([^|]*)\|([^|]*)\|(\w*)$/ + ? ( $1 => { + ($2 ? ( base => $2 ) : ()), + ($3 ? ( todo => $3 ) : ()), + (index($4, 'v') >= 0 ? ( varargs => 1 ) : ()), + (index($4, 'p') >= 0 ? ( provided => 1 ) : ()), + (index($4, 'n') >= 0 ? ( nothxarg => 1 ) : ()), + } ) + : die "invalid spec: $_" } qw( +AvFILLp|5.004050||p +AvFILL||| +CLASS|||n +CPERLscope|5.005000||p +CX_CURPAD_SAVE||| +CX_CURPAD_SV||| +CopFILEAV|5.006000||p +CopFILEGV_set|5.006000||p +CopFILEGV|5.006000||p +CopFILESV|5.006000||p +CopFILE_set|5.006000||p +CopFILE|5.006000||p +CopSTASHPV_set|5.006000||p +CopSTASHPV|5.006000||p +CopSTASH_eq|5.006000||p +CopSTASH_set|5.006000||p +CopSTASH|5.006000||p +CopyD|5.009002||p +Copy||| +CvPADLIST||| +CvSTASH||| +CvWEAKOUTSIDE||| +DEFSV_set|5.011000||p +DEFSV|5.004050||p +END_EXTERN_C|5.005000||p +ENTER||| +ERRSV|5.004050||p +EXTEND||| +EXTERN_C|5.005000||p +F0convert|||n +FREETMPS||| +GIMME_V||5.004000|n +GIMME|||n +GROK_NUMERIC_RADIX|5.007002||p +G_ARRAY||| +G_DISCARD||| +G_EVAL||| +G_METHOD|5.006001||p +G_NOARGS||| +G_SCALAR||| +G_VOID||5.004000| +GetVars||| +GvSVn|5.009003||p +GvSV||| +Gv_AMupdate||| +HEf_SVKEY||5.004000| +HeHASH||5.004000| +HeKEY||5.004000| +HeKLEN||5.004000| +HePV||5.004000| +HeSVKEY_force||5.004000| +HeSVKEY_set||5.004000| +HeSVKEY||5.004000| +HeUTF8||5.011000| +HeVAL||5.004000| +HvNAMELEN_get|5.009003||p +HvNAME_get|5.009003||p +HvNAME||| +INT2PTR|5.006000||p +IN_LOCALE_COMPILETIME|5.007002||p +IN_LOCALE_RUNTIME|5.007002||p +IN_LOCALE|5.007002||p +IN_PERL_COMPILETIME|5.008001||p +IS_NUMBER_GREATER_THAN_UV_MAX|5.007002||p +IS_NUMBER_INFINITY|5.007002||p +IS_NUMBER_IN_UV|5.007002||p +IS_NUMBER_NAN|5.007003||p +IS_NUMBER_NEG|5.007002||p +IS_NUMBER_NOT_INT|5.007002||p +IVSIZE|5.006000||p +IVTYPE|5.006000||p +IVdf|5.006000||p +LEAVE||| +LVRET||| +MARK||| +MULTICALL||5.011000| +MY_CXT_CLONE|5.009002||p +MY_CXT_INIT|5.007003||p +MY_CXT|5.007003||p +MoveD|5.009002||p +Move||| +NOOP|5.005000||p +NUM2PTR|5.006000||p +NVTYPE|5.006000||p +NVef|5.006001||p +NVff|5.006001||p +NVgf|5.006001||p +Newxc|5.009003||p +Newxz|5.009003||p +Newx|5.009003||p +Nullav||| +Nullch||| +Nullcv||| +Nullhv||| +Nullsv||| +ORIGMARK||| +PAD_BASE_SV||| +PAD_CLONE_VARS||| +PAD_COMPNAME_FLAGS||| +PAD_COMPNAME_GEN_set||| +PAD_COMPNAME_GEN||| +PAD_COMPNAME_OURSTASH||| +PAD_COMPNAME_PV||| +PAD_COMPNAME_TYPE||| +PAD_DUP||| +PAD_RESTORE_LOCAL||| +PAD_SAVE_LOCAL||| +PAD_SAVE_SETNULLPAD||| +PAD_SETSV||| +PAD_SET_CUR_NOSAVE||| +PAD_SET_CUR||| +PAD_SVl||| +PAD_SV||| +PERLIO_FUNCS_CAST|5.009003||p +PERLIO_FUNCS_DECL|5.009003||p +PERL_ABS|5.008001||p +PERL_BCDVERSION|5.011000||p +PERL_GCC_BRACE_GROUPS_FORBIDDEN|5.008001||p +PERL_HASH|5.004000||p +PERL_INT_MAX|5.004000||p +PERL_INT_MIN|5.004000||p +PERL_LONG_MAX|5.004000||p +PERL_LONG_MIN|5.004000||p +PERL_MAGIC_arylen|5.007002||p +PERL_MAGIC_backref|5.007002||p +PERL_MAGIC_bm|5.007002||p +PERL_MAGIC_collxfrm|5.007002||p +PERL_MAGIC_dbfile|5.007002||p +PERL_MAGIC_dbline|5.007002||p +PERL_MAGIC_defelem|5.007002||p +PERL_MAGIC_envelem|5.007002||p +PERL_MAGIC_env|5.007002||p +PERL_MAGIC_ext|5.007002||p +PERL_MAGIC_fm|5.007002||p +PERL_MAGIC_glob|5.011000||p +PERL_MAGIC_isaelem|5.007002||p +PERL_MAGIC_isa|5.007002||p +PERL_MAGIC_mutex|5.011000||p +PERL_MAGIC_nkeys|5.007002||p +PERL_MAGIC_overload_elem|5.007002||p +PERL_MAGIC_overload_table|5.007002||p +PERL_MAGIC_overload|5.007002||p +PERL_MAGIC_pos|5.007002||p +PERL_MAGIC_qr|5.007002||p +PERL_MAGIC_regdata|5.007002||p +PERL_MAGIC_regdatum|5.007002||p +PERL_MAGIC_regex_global|5.007002||p +PERL_MAGIC_shared_scalar|5.007003||p +PERL_MAGIC_shared|5.007003||p +PERL_MAGIC_sigelem|5.007002||p +PERL_MAGIC_sig|5.007002||p +PERL_MAGIC_substr|5.007002||p +PERL_MAGIC_sv|5.007002||p +PERL_MAGIC_taint|5.007002||p +PERL_MAGIC_tiedelem|5.007002||p +PERL_MAGIC_tiedscalar|5.007002||p +PERL_MAGIC_tied|5.007002||p +PERL_MAGIC_utf8|5.008001||p +PERL_MAGIC_uvar_elem|5.007003||p +PERL_MAGIC_uvar|5.007002||p +PERL_MAGIC_vec|5.007002||p +PERL_MAGIC_vstring|5.008001||p +PERL_PV_ESCAPE_ALL|5.009004||p +PERL_PV_ESCAPE_FIRSTCHAR|5.009004||p +PERL_PV_ESCAPE_NOBACKSLASH|5.009004||p +PERL_PV_ESCAPE_NOCLEAR|5.009004||p +PERL_PV_ESCAPE_QUOTE|5.009004||p +PERL_PV_ESCAPE_RE|5.009005||p +PERL_PV_ESCAPE_UNI_DETECT|5.009004||p +PERL_PV_ESCAPE_UNI|5.009004||p +PERL_PV_PRETTY_DUMP|5.009004||p +PERL_PV_PRETTY_ELLIPSES|5.010000||p +PERL_PV_PRETTY_LTGT|5.009004||p +PERL_PV_PRETTY_NOCLEAR|5.010000||p +PERL_PV_PRETTY_QUOTE|5.009004||p +PERL_PV_PRETTY_REGPROP|5.009004||p +PERL_QUAD_MAX|5.004000||p +PERL_QUAD_MIN|5.004000||p +PERL_REVISION|5.006000||p +PERL_SCAN_ALLOW_UNDERSCORES|5.007003||p +PERL_SCAN_DISALLOW_PREFIX|5.007003||p +PERL_SCAN_GREATER_THAN_UV_MAX|5.007003||p +PERL_SCAN_SILENT_ILLDIGIT|5.008001||p +PERL_SHORT_MAX|5.004000||p +PERL_SHORT_MIN|5.004000||p +PERL_SIGNALS_UNSAFE_FLAG|5.008001||p +PERL_SUBVERSION|5.006000||p +PERL_SYS_INIT3||5.006000| +PERL_SYS_INIT||| +PERL_SYS_TERM||5.011000| +PERL_UCHAR_MAX|5.004000||p +PERL_UCHAR_MIN|5.004000||p +PERL_UINT_MAX|5.004000||p +PERL_UINT_MIN|5.004000||p +PERL_ULONG_MAX|5.004000||p +PERL_ULONG_MIN|5.004000||p +PERL_UNUSED_ARG|5.009003||p +PERL_UNUSED_CONTEXT|5.009004||p +PERL_UNUSED_DECL|5.007002||p +PERL_UNUSED_VAR|5.007002||p +PERL_UQUAD_MAX|5.004000||p +PERL_UQUAD_MIN|5.004000||p +PERL_USE_GCC_BRACE_GROUPS|5.009004||p +PERL_USHORT_MAX|5.004000||p +PERL_USHORT_MIN|5.004000||p +PERL_VERSION|5.006000||p +PL_DBsignal|5.005000||p +PL_DBsingle|||pn +PL_DBsub|||pn +PL_DBtrace|||pn +PL_Sv|5.005000||p +PL_bufend|5.011000||p +PL_bufptr|5.011000||p +PL_compiling|5.004050||p +PL_copline|5.011000||p +PL_curcop|5.004050||p +PL_curstash|5.004050||p +PL_debstash|5.004050||p +PL_defgv|5.004050||p +PL_diehook|5.004050||p +PL_dirty|5.004050||p +PL_dowarn|||pn +PL_errgv|5.004050||p +PL_error_count|5.011000||p +PL_expect|5.011000||p +PL_hexdigit|5.005000||p +PL_hints|5.005000||p +PL_in_my_stash|5.011000||p +PL_in_my|5.011000||p +PL_last_in_gv|||n +PL_laststatval|5.005000||p +PL_lex_state|5.011000||p +PL_lex_stuff|5.011000||p +PL_linestr|5.011000||p +PL_modglobal||5.005000|n +PL_na|5.004050||pn +PL_no_modify|5.006000||p +PL_ofsgv|||n +PL_parser|5.009005||p +PL_perl_destruct_level|5.004050||p +PL_perldb|5.004050||p +PL_ppaddr|5.006000||p +PL_rsfp_filters|5.004050||p +PL_rsfp|5.004050||p +PL_rs|||n +PL_signals|5.008001||p +PL_stack_base|5.004050||p +PL_stack_sp|5.004050||p +PL_statcache|5.005000||p +PL_stdingv|5.004050||p +PL_sv_arenaroot|5.004050||p +PL_sv_no|5.004050||pn +PL_sv_undef|5.004050||pn +PL_sv_yes|5.004050||pn +PL_tainted|5.004050||p +PL_tainting|5.004050||p +PL_tokenbuf|5.011000||p +POP_MULTICALL||5.011000| +POPi|||n +POPl|||n +POPn|||n +POPpbytex||5.007001|n +POPpx||5.005030|n +POPp|||n +POPs|||n +PTR2IV|5.006000||p +PTR2NV|5.006000||p +PTR2UV|5.006000||p +PTR2nat|5.009003||p +PTR2ul|5.007001||p +PTRV|5.006000||p +PUSHMARK||| +PUSH_MULTICALL||5.011000| +PUSHi||| +PUSHmortal|5.009002||p +PUSHn||| +PUSHp||| +PUSHs||| +PUSHu|5.004000||p +PUTBACK||| +PerlIO_clearerr||5.007003| +PerlIO_close||5.007003| +PerlIO_context_layers||5.009004| +PerlIO_eof||5.007003| +PerlIO_error||5.007003| +PerlIO_fileno||5.007003| +PerlIO_fill||5.007003| +PerlIO_flush||5.007003| +PerlIO_get_base||5.007003| +PerlIO_get_bufsiz||5.007003| +PerlIO_get_cnt||5.007003| +PerlIO_get_ptr||5.007003| +PerlIO_read||5.007003| +PerlIO_seek||5.007003| +PerlIO_set_cnt||5.007003| +PerlIO_set_ptrcnt||5.007003| +PerlIO_setlinebuf||5.007003| +PerlIO_stderr||5.007003| +PerlIO_stdin||5.007003| +PerlIO_stdout||5.007003| +PerlIO_tell||5.007003| +PerlIO_unread||5.007003| +PerlIO_write||5.007003| +Perl_signbit||5.009005|n +PoisonFree|5.009004||p +PoisonNew|5.009004||p +PoisonWith|5.009004||p +Poison|5.008000||p +RETVAL|||n +Renewc||| +Renew||| +SAVECLEARSV||| +SAVECOMPPAD||| +SAVEPADSV||| +SAVETMPS||| +SAVE_DEFSV|5.004050||p +SPAGAIN||| +SP||| +START_EXTERN_C|5.005000||p +START_MY_CXT|5.007003||p +STMT_END|||p +STMT_START|||p +STR_WITH_LEN|5.009003||p +ST||| +SV_CONST_RETURN|5.009003||p +SV_COW_DROP_PV|5.008001||p +SV_COW_SHARED_HASH_KEYS|5.009005||p +SV_GMAGIC|5.007002||p +SV_HAS_TRAILING_NUL|5.009004||p +SV_IMMEDIATE_UNREF|5.007001||p +SV_MUTABLE_RETURN|5.009003||p +SV_NOSTEAL|5.009002||p +SV_SMAGIC|5.009003||p +SV_UTF8_NO_ENCODING|5.008001||p +SVfARG|5.009005||p +SVf_UTF8|5.006000||p +SVf|5.006000||p +SVt_IV||| +SVt_NV||| +SVt_PVAV||| +SVt_PVCV||| +SVt_PVHV||| +SVt_PVMG||| +SVt_PV||| +Safefree||| +Slab_Alloc||| +Slab_Free||| +Slab_to_rw||| +StructCopy||| +SvCUR_set||| +SvCUR||| +SvEND||| +SvGAMAGIC||5.006001| +SvGETMAGIC|5.004050||p +SvGROW||| +SvIOK_UV||5.006000| +SvIOK_notUV||5.006000| +SvIOK_off||| +SvIOK_only_UV||5.006000| +SvIOK_only||| +SvIOK_on||| +SvIOKp||| +SvIOK||| +SvIVX||| +SvIV_nomg|5.009001||p +SvIV_set||| +SvIVx||| +SvIV||| +SvIsCOW_shared_hash||5.008003| +SvIsCOW||5.008003| +SvLEN_set||| +SvLEN||| +SvLOCK||5.007003| +SvMAGIC_set|5.009003||p +SvNIOK_off||| +SvNIOKp||| +SvNIOK||| +SvNOK_off||| +SvNOK_only||| +SvNOK_on||| +SvNOKp||| +SvNOK||| +SvNVX||| +SvNV_set||| +SvNVx||| +SvNV||| +SvOK||| +SvOOK_offset||5.011000| +SvOOK||| +SvPOK_off||| +SvPOK_only_UTF8||5.006000| +SvPOK_only||| +SvPOK_on||| +SvPOKp||| +SvPOK||| +SvPVX_const|5.009003||p +SvPVX_mutable|5.009003||p +SvPVX||| +SvPV_const|5.009003||p +SvPV_flags_const_nolen|5.009003||p +SvPV_flags_const|5.009003||p +SvPV_flags_mutable|5.009003||p +SvPV_flags|5.007002||p +SvPV_force_flags_mutable|5.009003||p +SvPV_force_flags_nolen|5.009003||p +SvPV_force_flags|5.007002||p +SvPV_force_mutable|5.009003||p +SvPV_force_nolen|5.009003||p +SvPV_force_nomg_nolen|5.009003||p +SvPV_force_nomg|5.007002||p +SvPV_force|||p +SvPV_mutable|5.009003||p +SvPV_nolen_const|5.009003||p +SvPV_nolen|5.006000||p +SvPV_nomg_const_nolen|5.009003||p +SvPV_nomg_const|5.009003||p +SvPV_nomg|5.007002||p +SvPV_renew|5.009003||p +SvPV_set||| +SvPVbyte_force||5.009002| +SvPVbyte_nolen||5.006000| +SvPVbytex_force||5.006000| +SvPVbytex||5.006000| +SvPVbyte|5.006000||p +SvPVutf8_force||5.006000| +SvPVutf8_nolen||5.006000| +SvPVutf8x_force||5.006000| +SvPVutf8x||5.006000| +SvPVutf8||5.006000| +SvPVx||| +SvPV||| +SvREFCNT_dec||| +SvREFCNT_inc_NN|5.009004||p +SvREFCNT_inc_simple_NN|5.009004||p +SvREFCNT_inc_simple_void_NN|5.009004||p +SvREFCNT_inc_simple_void|5.009004||p +SvREFCNT_inc_simple|5.009004||p +SvREFCNT_inc_void_NN|5.009004||p +SvREFCNT_inc_void|5.009004||p +SvREFCNT_inc|||p +SvREFCNT||| +SvROK_off||| +SvROK_on||| +SvROK||| +SvRV_set|5.009003||p +SvRV||| +SvRXOK||5.009005| +SvRX||5.009005| +SvSETMAGIC||| +SvSHARED_HASH|5.009003||p +SvSHARE||5.007003| +SvSTASH_set|5.009003||p +SvSTASH||| +SvSetMagicSV_nosteal||5.004000| +SvSetMagicSV||5.004000| +SvSetSV_nosteal||5.004000| +SvSetSV||| +SvTAINTED_off||5.004000| +SvTAINTED_on||5.004000| +SvTAINTED||5.004000| +SvTAINT||| +SvTRUE||| +SvTYPE||| +SvUNLOCK||5.007003| +SvUOK|5.007001|5.006000|p +SvUPGRADE||| +SvUTF8_off||5.006000| +SvUTF8_on||5.006000| +SvUTF8||5.006000| +SvUVXx|5.004000||p +SvUVX|5.004000||p +SvUV_nomg|5.009001||p +SvUV_set|5.009003||p +SvUVx|5.004000||p +SvUV|5.004000||p +SvVOK||5.008001| +SvVSTRING_mg|5.009004||p +THIS|||n +UNDERBAR|5.009002||p +UTF8_MAXBYTES|5.009002||p +UVSIZE|5.006000||p +UVTYPE|5.006000||p +UVXf|5.007001||p +UVof|5.006000||p +UVuf|5.006000||p +UVxf|5.006000||p +WARN_ALL|5.006000||p +WARN_AMBIGUOUS|5.006000||p +WARN_ASSERTIONS|5.011000||p +WARN_BAREWORD|5.006000||p +WARN_CLOSED|5.006000||p +WARN_CLOSURE|5.006000||p +WARN_DEBUGGING|5.006000||p +WARN_DEPRECATED|5.006000||p +WARN_DIGIT|5.006000||p +WARN_EXEC|5.006000||p +WARN_EXITING|5.006000||p +WARN_GLOB|5.006000||p +WARN_INPLACE|5.006000||p +WARN_INTERNAL|5.006000||p +WARN_IO|5.006000||p +WARN_LAYER|5.008000||p +WARN_MALLOC|5.006000||p +WARN_MISC|5.006000||p +WARN_NEWLINE|5.006000||p +WARN_NUMERIC|5.006000||p +WARN_ONCE|5.006000||p +WARN_OVERFLOW|5.006000||p +WARN_PACK|5.006000||p +WARN_PARENTHESIS|5.006000||p +WARN_PIPE|5.006000||p +WARN_PORTABLE|5.006000||p +WARN_PRECEDENCE|5.006000||p +WARN_PRINTF|5.006000||p +WARN_PROTOTYPE|5.006000||p +WARN_QW|5.006000||p +WARN_RECURSION|5.006000||p +WARN_REDEFINE|5.006000||p +WARN_REGEXP|5.006000||p +WARN_RESERVED|5.006000||p +WARN_SEMICOLON|5.006000||p +WARN_SEVERE|5.006000||p +WARN_SIGNAL|5.006000||p +WARN_SUBSTR|5.006000||p +WARN_SYNTAX|5.006000||p +WARN_TAINT|5.006000||p +WARN_THREADS|5.008000||p +WARN_UNINITIALIZED|5.006000||p +WARN_UNOPENED|5.006000||p +WARN_UNPACK|5.006000||p +WARN_UNTIE|5.006000||p +WARN_UTF8|5.006000||p +WARN_VOID|5.006000||p +XCPT_CATCH|5.009002||p +XCPT_RETHROW|5.009002||p +XCPT_TRY_END|5.009002||p +XCPT_TRY_START|5.009002||p +XPUSHi||| +XPUSHmortal|5.009002||p +XPUSHn||| +XPUSHp||| +XPUSHs||| +XPUSHu|5.004000||p +XSPROTO|5.010000||p +XSRETURN_EMPTY||| +XSRETURN_IV||| +XSRETURN_NO||| +XSRETURN_NV||| +XSRETURN_PV||| +XSRETURN_UNDEF||| +XSRETURN_UV|5.008001||p +XSRETURN_YES||| +XSRETURN|||p +XST_mIV||| +XST_mNO||| +XST_mNV||| +XST_mPV||| +XST_mUNDEF||| +XST_mUV|5.008001||p +XST_mYES||| +XS_VERSION_BOOTCHECK||| +XS_VERSION||| +XSprePUSH|5.006000||p +XS||| +ZeroD|5.009002||p +Zero||| +_aMY_CXT|5.007003||p +_pMY_CXT|5.007003||p +aMY_CXT_|5.007003||p +aMY_CXT|5.007003||p +aTHXR_|5.011000||p +aTHXR|5.011000||p +aTHX_|5.006000||p +aTHX|5.006000||p +add_data|||n +addmad||| +allocmy||| +amagic_call||| +amagic_cmp_locale||| +amagic_cmp||| +amagic_i_ncmp||| +amagic_ncmp||| +any_dup||| +ao||| +append_elem||| +append_list||| +append_madprops||| +apply_attrs_my||| +apply_attrs_string||5.006001| +apply_attrs||| +apply||| +atfork_lock||5.007003|n +atfork_unlock||5.007003|n +av_arylen_p||5.009003| +av_clear||| +av_create_and_push||5.009005| +av_create_and_unshift_one||5.009005| +av_delete||5.006000| +av_exists||5.006000| +av_extend||| +av_fetch||| +av_fill||| +av_iter_p||5.011000| +av_len||| +av_make||| +av_pop||| +av_push||| +av_reify||| +av_shift||| +av_store||| +av_undef||| +av_unshift||| +ax|||n +bad_type||| +bind_match||| +block_end||| +block_gimme||5.004000| +block_start||| +boolSV|5.004000||p +boot_core_PerlIO||| +boot_core_UNIVERSAL||| +boot_core_mro||| +bytes_from_utf8||5.007001| +bytes_to_uni|||n +bytes_to_utf8||5.006001| +call_argv|5.006000||p +call_atexit||5.006000| +call_list||5.004000| +call_method|5.006000||p +call_pv|5.006000||p +call_sv|5.006000||p +calloc||5.007002|n +cando||| +cast_i32||5.006000| +cast_iv||5.006000| +cast_ulong||5.006000| +cast_uv||5.006000| +check_type_and_open||| +check_uni||| +checkcomma||| +checkposixcc||| +ckWARN|5.006000||p +ck_anoncode||| +ck_bitop||| +ck_concat||| +ck_defined||| +ck_delete||| +ck_die||| +ck_each||| +ck_eof||| +ck_eval||| +ck_exec||| +ck_exists||| +ck_exit||| +ck_ftst||| +ck_fun||| +ck_glob||| +ck_grep||| +ck_index||| +ck_join||| +ck_lfun||| +ck_listiob||| +ck_match||| +ck_method||| +ck_null||| +ck_open||| +ck_readline||| +ck_repeat||| +ck_require||| +ck_return||| +ck_rfun||| +ck_rvconst||| +ck_sassign||| +ck_select||| +ck_shift||| +ck_sort||| +ck_spair||| +ck_split||| +ck_subr||| +ck_substr||| +ck_svconst||| +ck_trunc||| +ck_unpack||| +ckwarn_d||5.009003| +ckwarn||5.009003| +cl_and|||n +cl_anything|||n +cl_init_zero|||n +cl_init|||n +cl_is_anything|||n +cl_or|||n +clear_placeholders||| +closest_cop||| +convert||| +cop_free||| +cr_textfilter||| +create_eval_scope||| +croak_nocontext|||vn +croak_xs_usage||5.011000| +croak|||v +csighandler||5.009003|n +curmad||| +custom_op_desc||5.007003| +custom_op_name||5.007003| +cv_ckproto_len||| +cv_clone||| +cv_const_sv||5.004000| +cv_dump||| +cv_undef||| +cx_dump||5.005000| +cx_dup||| +cxinc||| +dAXMARK|5.009003||p +dAX|5.007002||p +dITEMS|5.007002||p +dMARK||| +dMULTICALL||5.009003| +dMY_CXT_SV|5.007003||p +dMY_CXT|5.007003||p +dNOOP|5.006000||p +dORIGMARK||| +dSP||| +dTHR|5.004050||p +dTHXR|5.011000||p +dTHXa|5.006000||p +dTHXoa|5.006000||p +dTHX|5.006000||p +dUNDERBAR|5.009002||p +dVAR|5.009003||p +dXCPT|5.009002||p +dXSARGS||| +dXSI32||| +dXSTARG|5.006000||p +deb_curcv||| +deb_nocontext|||vn +deb_stack_all||| +deb_stack_n||| +debop||5.005000| +debprofdump||5.005000| +debprof||| +debstackptrs||5.007003| +debstack||5.007003| +debug_start_match||| +deb||5.007003|v +del_sv||| +delete_eval_scope||| +delimcpy||5.004000| +deprecate_old||| +deprecate||| +despatch_signals||5.007001| +destroy_matcher||| +die_nocontext|||vn +die_where||| +die|||v +dirp_dup||| +div128||| +djSP||| +do_aexec5||| +do_aexec||| +do_aspawn||| +do_binmode||5.004050| +do_chomp||| +do_chop||| +do_close||| +do_dump_pad||| +do_eof||| +do_exec3||| +do_execfree||| +do_exec||| +do_gv_dump||5.006000| +do_gvgv_dump||5.006000| +do_hv_dump||5.006000| +do_ipcctl||| +do_ipcget||| +do_join||| +do_kv||| +do_magic_dump||5.006000| +do_msgrcv||| +do_msgsnd||| +do_oddball||| +do_op_dump||5.006000| +do_op_xmldump||| +do_open9||5.006000| +do_openn||5.007001| +do_open||5.004000| +do_pmop_dump||5.006000| +do_pmop_xmldump||| +do_print||| +do_readline||| +do_seek||| +do_semop||| +do_shmio||| +do_smartmatch||| +do_spawn_nowait||| +do_spawn||| +do_sprintf||| +do_sv_dump||5.006000| +do_sysseek||| +do_tell||| +do_trans_complex_utf8||| +do_trans_complex||| +do_trans_count_utf8||| +do_trans_count||| +do_trans_simple_utf8||| +do_trans_simple||| +do_trans||| +do_vecget||| +do_vecset||| +do_vop||| +docatch||| +doeval||| +dofile||| +dofindlabel||| +doform||| +doing_taint||5.008001|n +dooneliner||| +doopen_pm||| +doparseform||| +dopoptoeval||| +dopoptogiven||| +dopoptolabel||| +dopoptoloop||| +dopoptosub_at||| +dopoptowhen||| +doref||5.009003| +dounwind||| +dowantarray||| +dump_all||5.006000| +dump_eval||5.006000| +dump_exec_pos||| +dump_fds||| +dump_form||5.006000| +dump_indent||5.006000|v +dump_mstats||| +dump_packsubs||5.006000| +dump_sub||5.006000| +dump_sv_child||| +dump_trie_interim_list||| +dump_trie_interim_table||| +dump_trie||| +dump_vindent||5.006000| +dumpuntil||| +dup_attrlist||| +emulate_cop_io||| +eval_pv|5.006000||p +eval_sv|5.006000||p +exec_failed||| +expect_number||| +fbm_compile||5.005000| +fbm_instr||5.005000| +feature_is_enabled||| +fetch_cop_label||5.011000| +filter_add||| +filter_del||| +filter_gets||| +filter_read||| +find_and_forget_pmops||| +find_array_subscript||| +find_beginning||| +find_byclass||| +find_hash_subscript||| +find_in_my_stash||| +find_runcv||5.008001| +find_rundefsvoffset||5.009002| +find_script||| +find_uninit_var||| +first_symbol|||n +fold_constants||| +forbid_setid||| +force_ident||| +force_list||| +force_next||| +force_version||| +force_word||| +forget_pmop||| +form_nocontext|||vn +form||5.004000|v +fp_dup||| +fprintf_nocontext|||vn +free_global_struct||| +free_tied_hv_pool||| +free_tmps||| +gen_constant_list||| +get_arena||| +get_aux_mg||| +get_av|5.006000||p +get_context||5.006000|n +get_cvn_flags||5.009005| +get_cv|5.006000||p +get_db_sub||| +get_debug_opts||| +get_hash_seed||| +get_hv|5.006000||p +get_isa_hash||| +get_mstats||| +get_no_modify||| +get_num||| +get_op_descs||5.005000| +get_op_names||5.005000| +get_opargs||| +get_ppaddr||5.006000| +get_re_arg||| +get_sv|5.006000||p +get_vtbl||5.005030| +getcwd_sv||5.007002| +getenv_len||| +glob_2number||| +glob_assign_glob||| +glob_assign_ref||| +gp_dup||| +gp_free||| +gp_ref||| +grok_bin|5.007003||p +grok_hex|5.007003||p +grok_number|5.007002||p +grok_numeric_radix|5.007002||p +grok_oct|5.007003||p +group_end||| +gv_AVadd||| +gv_HVadd||| +gv_IOadd||| +gv_SVadd||| +gv_autoload4||5.004000| +gv_check||| +gv_const_sv||5.009003| +gv_dump||5.006000| +gv_efullname3||5.004000| +gv_efullname4||5.006001| +gv_efullname||| +gv_ename||| +gv_fetchfile_flags||5.009005| +gv_fetchfile||| +gv_fetchmeth_autoload||5.007003| +gv_fetchmethod_autoload||5.004000| +gv_fetchmethod_flags||5.011000| +gv_fetchmethod||| +gv_fetchmeth||| +gv_fetchpvn_flags|5.009002||p +gv_fetchpvs|5.009004||p +gv_fetchpv||| +gv_fetchsv||5.009002| +gv_fullname3||5.004000| +gv_fullname4||5.006001| +gv_fullname||| +gv_get_super_pkg||| +gv_handler||5.007001| +gv_init_sv||| +gv_init||| +gv_name_set||5.009004| +gv_stashpvn|5.004000||p +gv_stashpvs|5.009003||p +gv_stashpv||| +gv_stashsv||| +he_dup||| +hek_dup||| +hfreeentries||| +hsplit||| +hv_assert||5.011000| +hv_auxinit|||n +hv_backreferences_p||| +hv_clear_placeholders||5.009001| +hv_clear||| +hv_common_key_len||5.010000| +hv_common||5.010000| +hv_copy_hints_hv||| +hv_delayfree_ent||5.004000| +hv_delete_common||| +hv_delete_ent||5.004000| +hv_delete||| +hv_eiter_p||5.009003| +hv_eiter_set||5.009003| +hv_exists_ent||5.004000| +hv_exists||| +hv_fetch_ent||5.004000| +hv_fetchs|5.009003||p +hv_fetch||| +hv_free_ent||5.004000| +hv_iterinit||| +hv_iterkeysv||5.004000| +hv_iterkey||| +hv_iternext_flags||5.008000| +hv_iternextsv||| +hv_iternext||| +hv_iterval||| +hv_kill_backrefs||| +hv_ksplit||5.004000| +hv_magic_check|||n +hv_magic||| +hv_name_set||5.009003| +hv_notallowed||| +hv_placeholders_get||5.009003| +hv_placeholders_p||5.009003| +hv_placeholders_set||5.009003| +hv_riter_p||5.009003| +hv_riter_set||5.009003| +hv_scalar||5.009001| +hv_store_ent||5.004000| +hv_store_flags||5.008000| +hv_stores|5.009004||p +hv_store||| +hv_undef||| +ibcmp_locale||5.004000| +ibcmp_utf8||5.007003| +ibcmp||| +incline||| +incpush_if_exists||| +incpush_use_sep||| +incpush||| +ingroup||| +init_argv_symbols||| +init_debugger||| +init_global_struct||| +init_i18nl10n||5.006000| +init_i18nl14n||5.006000| +init_ids||| +init_interp||| +init_main_stash||| +init_perllib||| +init_postdump_symbols||| +init_predump_symbols||| +init_stacks||5.005000| +init_tm||5.007002| +instr||| +intro_my||| +intuit_method||| +intuit_more||| +invert||| +io_close||| +isALNUMC|5.006000||p +isALNUM||| +isALPHA||| +isASCII|5.006000||p +isBLANK|5.006001||p +isCNTRL|5.006000||p +isDIGIT||| +isGRAPH|5.006000||p +isGV_with_GP|5.009004||p +isLOWER||| +isPRINT|5.004000||p +isPSXSPC|5.006001||p +isPUNCT|5.006000||p +isSPACE||| +isUPPER||| +isXDIGIT|5.006000||p +is_an_int||| +is_gv_magical_sv||| +is_handle_constructor|||n +is_list_assignment||| +is_lvalue_sub||5.007001| +is_uni_alnum_lc||5.006000| +is_uni_alnumc_lc||5.006000| +is_uni_alnumc||5.006000| +is_uni_alnum||5.006000| +is_uni_alpha_lc||5.006000| +is_uni_alpha||5.006000| +is_uni_ascii_lc||5.006000| +is_uni_ascii||5.006000| +is_uni_cntrl_lc||5.006000| +is_uni_cntrl||5.006000| +is_uni_digit_lc||5.006000| +is_uni_digit||5.006000| +is_uni_graph_lc||5.006000| +is_uni_graph||5.006000| +is_uni_idfirst_lc||5.006000| +is_uni_idfirst||5.006000| +is_uni_lower_lc||5.006000| +is_uni_lower||5.006000| +is_uni_print_lc||5.006000| +is_uni_print||5.006000| +is_uni_punct_lc||5.006000| +is_uni_punct||5.006000| +is_uni_space_lc||5.006000| +is_uni_space||5.006000| +is_uni_upper_lc||5.006000| +is_uni_upper||5.006000| +is_uni_xdigit_lc||5.006000| +is_uni_xdigit||5.006000| +is_utf8_alnumc||5.006000| +is_utf8_alnum||5.006000| +is_utf8_alpha||5.006000| +is_utf8_ascii||5.006000| +is_utf8_char_slow|||n +is_utf8_char||5.006000| +is_utf8_cntrl||5.006000| +is_utf8_common||| +is_utf8_digit||5.006000| +is_utf8_graph||5.006000| +is_utf8_idcont||5.008000| +is_utf8_idfirst||5.006000| +is_utf8_lower||5.006000| +is_utf8_mark||5.006000| +is_utf8_print||5.006000| +is_utf8_punct||5.006000| +is_utf8_space||5.006000| +is_utf8_string_loclen||5.009003| +is_utf8_string_loc||5.008001| +is_utf8_string||5.006001| +is_utf8_upper||5.006000| +is_utf8_xdigit||5.006000| +isa_lookup||| +items|||n +ix|||n +jmaybe||| +join_exact||| +keyword||| +leave_scope||| +lex_end||| +lex_start||| +linklist||| +listkids||| +list||| +load_module_nocontext|||vn +load_module|5.006000||pv +localize||| +looks_like_bool||| +looks_like_number||| +lop||| +mPUSHi|5.009002||p +mPUSHn|5.009002||p +mPUSHp|5.009002||p +mPUSHs|5.011000||p +mPUSHu|5.009002||p +mXPUSHi|5.009002||p +mXPUSHn|5.009002||p +mXPUSHp|5.009002||p +mXPUSHs|5.011000||p +mXPUSHu|5.009002||p +mad_free||| +madlex||| +madparse||| +magic_clear_all_env||| +magic_clearenv||| +magic_clearhint||| +magic_clearisa||| +magic_clearpack||| +magic_clearsig||| +magic_dump||5.006000| +magic_existspack||| +magic_freearylen_p||| +magic_freeovrld||| +magic_getarylen||| +magic_getdefelem||| +magic_getnkeys||| +magic_getpack||| +magic_getpos||| +magic_getsig||| +magic_getsubstr||| +magic_gettaint||| +magic_getuvar||| +magic_getvec||| +magic_get||| +magic_killbackrefs||| +magic_len||| +magic_methcall||| +magic_methpack||| +magic_nextpack||| +magic_regdata_cnt||| +magic_regdatum_get||| +magic_regdatum_set||| +magic_scalarpack||| +magic_set_all_env||| +magic_setamagic||| +magic_setarylen||| +magic_setcollxfrm||| +magic_setdbline||| +magic_setdefelem||| +magic_setenv||| +magic_sethint||| +magic_setisa||| +magic_setmglob||| +magic_setnkeys||| +magic_setpack||| +magic_setpos||| +magic_setregexp||| +magic_setsig||| +magic_setsubstr||| +magic_settaint||| +magic_setutf8||| +magic_setuvar||| +magic_setvec||| +magic_set||| +magic_sizepack||| +magic_wipepack||| +make_matcher||| +make_trie_failtable||| +make_trie||| +malloc_good_size|||n +malloced_size|||n +malloc||5.007002|n +markstack_grow||| +matcher_matches_sv||| +measure_struct||| +memEQ|5.004000||p +memNE|5.004000||p +mem_collxfrm||| +mem_log_common|||n +mess_alloc||| +mess_nocontext|||vn +mess||5.006000|v +method_common||| +mfree||5.007002|n +mg_clear||| +mg_copy||| +mg_dup||| +mg_find||| +mg_free||| +mg_get||| +mg_length||5.005000| +mg_localize||| +mg_magical||| +mg_set||| +mg_size||5.005000| +mini_mktime||5.007002| +missingterm||| +mode_from_discipline||| +modkids||| +mod||| +more_bodies||| +more_sv||| +moreswitches||| +mro_get_from_name||5.011000| +mro_get_linear_isa_dfs||| +mro_get_linear_isa||5.009005| +mro_get_private_data||5.011000| +mro_isa_changed_in||| +mro_meta_dup||| +mro_meta_init||| +mro_method_changed_in||5.009005| +mro_register||5.011000| +mro_set_mro||5.011000| +mro_set_private_data||5.011000| +mul128||| +mulexp10|||n +my_atof2||5.007002| +my_atof||5.006000| +my_attrs||| +my_bcopy|||n +my_betoh16|||n +my_betoh32|||n +my_betoh64|||n +my_betohi|||n +my_betohl|||n +my_betohs|||n +my_bzero|||n +my_chsize||| +my_clearenv||| +my_cxt_index||| +my_cxt_init||| +my_dirfd||5.009005| +my_exit_jump||| +my_exit||| +my_failure_exit||5.004000| +my_fflush_all||5.006000| +my_fork||5.007003|n +my_htobe16|||n +my_htobe32|||n +my_htobe64|||n +my_htobei|||n +my_htobel|||n +my_htobes|||n +my_htole16|||n +my_htole32|||n +my_htole64|||n +my_htolei|||n +my_htolel|||n +my_htoles|||n +my_htonl||| +my_kid||| +my_letoh16|||n +my_letoh32|||n +my_letoh64|||n +my_letohi|||n +my_letohl|||n +my_letohs|||n +my_lstat||| +my_memcmp||5.004000|n +my_memset|||n +my_ntohl||| +my_pclose||5.004000| +my_popen_list||5.007001| +my_popen||5.004000| +my_setenv||| +my_snprintf|5.009004||pvn +my_socketpair||5.007003|n +my_sprintf|5.009003||pvn +my_stat||| +my_strftime||5.007002| +my_strlcat|5.009004||pn +my_strlcpy|5.009004||pn +my_swabn|||n +my_swap||| +my_unexec||| +my_vsnprintf||5.009004|n +need_utf8|||n +newANONATTRSUB||5.006000| +newANONHASH||| +newANONLIST||| +newANONSUB||| +newASSIGNOP||| +newATTRSUB||5.006000| +newAVREF||| +newAV||| +newBINOP||| +newCONDOP||| +newCONSTSUB|5.004050||p +newCVREF||| +newDEFSVOP||| +newFORM||| +newFOROP||| +newGIVENOP||5.009003| +newGIVWHENOP||| +newGP||| +newGVOP||| +newGVREF||| +newGVgen||| +newHVREF||| +newHVhv||5.005000| +newHV||| +newIO||| +newLISTOP||| +newLOGOP||| +newLOOPEX||| +newLOOPOP||| +newMADPROP||| +newMADsv||| +newMYSUB||| +newNULLLIST||| +newOP||| +newPADOP||| +newPMOP||| +newPROG||| +newPVOP||| +newRANGE||| +newRV_inc|5.004000||p +newRV_noinc|5.004000||p +newRV||| +newSLICEOP||| +newSTATEOP||| +newSUB||| +newSVOP||| +newSVREF||| +newSV_type|5.009005||p +newSVhek||5.009003| +newSViv||| +newSVnv||| +newSVpvf_nocontext|||vn +newSVpvf||5.004000|v +newSVpvn_flags|5.011000||p +newSVpvn_share|5.007001||p +newSVpvn_utf8|5.011000||p +newSVpvn|5.004050||p +newSVpvs_flags|5.011000||p +newSVpvs_share||5.009003| +newSVpvs|5.009003||p +newSVpv||| +newSVrv||| +newSVsv||| +newSVuv|5.006000||p +newSV||| +newTOKEN||| +newUNOP||| +newWHENOP||5.009003| +newWHILEOP||5.009003| +newXS_flags||5.009004| +newXSproto||5.006000| +newXS||5.006000| +new_collate||5.006000| +new_constant||| +new_ctype||5.006000| +new_he||| +new_logop||| +new_numeric||5.006000| +new_stackinfo||5.005000| +new_version||5.009000| +new_warnings_bitfield||| +next_symbol||| +nextargv||| +nextchar||| +ninstr||| +no_bareword_allowed||| +no_fh_allowed||| +no_op||| +not_a_number||| +nothreadhook||5.008000| +nuke_stacks||| +num_overflow|||n +offer_nice_chunk||| +oopsAV||| +oopsHV||| +op_clear||| +op_const_sv||| +op_dump||5.006000| +op_free||| +op_getmad_weak||| +op_getmad||| +op_null||5.007002| +op_refcnt_dec||| +op_refcnt_inc||| +op_refcnt_lock||5.009002| +op_refcnt_unlock||5.009002| +op_xmldump||| +open_script||| +pMY_CXT_|5.007003||p +pMY_CXT|5.007003||p +pTHX_|5.006000||p +pTHX|5.006000||p +packWARN|5.007003||p +pack_cat||5.007003| +pack_rec||| +package||| +packlist||5.008001| +pad_add_anon||| +pad_add_name||| +pad_alloc||| +pad_block_start||| +pad_check_dup||| +pad_compname_type||| +pad_findlex||| +pad_findmy||| +pad_fixup_inner_anons||| +pad_free||| +pad_leavemy||| +pad_new||| +pad_peg|||n +pad_push||| +pad_reset||| +pad_setsv||| +pad_sv||5.011000| +pad_swipe||| +pad_tidy||| +pad_undef||| +parse_body||| +parse_unicode_opts||| +parser_dup||| +parser_free||| +path_is_absolute|||n +peep||| +pending_Slabs_to_ro||| +perl_alloc_using|||n +perl_alloc|||n +perl_clone_using|||n +perl_clone|||n +perl_construct|||n +perl_destruct||5.007003|n +perl_free|||n +perl_parse||5.006000|n +perl_run|||n +pidgone||| +pm_description||| +pmflag||| +pmop_dump||5.006000| +pmop_xmldump||| +pmruntime||| +pmtrans||| +pop_scope||| +pregcomp||5.009005| +pregexec||| +pregfree2||5.011000| +pregfree||| +prepend_elem||| +prepend_madprops||| +printbuf||| +printf_nocontext|||vn +process_special_blocks||| +ptr_table_clear||5.009005| +ptr_table_fetch||5.009005| +ptr_table_find|||n +ptr_table_free||5.009005| +ptr_table_new||5.009005| +ptr_table_split||5.009005| +ptr_table_store||5.009005| +push_scope||| +put_byte||| +pv_display|5.006000||p +pv_escape|5.009004||p +pv_pretty|5.009004||p +pv_uni_display||5.007003| +qerror||| +qsortsvu||| +re_compile||5.009005| +re_croak2||| +re_dup_guts||| +re_intuit_start||5.009005| +re_intuit_string||5.006000| +readpipe_override||| +realloc||5.007002|n +reentrant_free||| +reentrant_init||| +reentrant_retry|||vn +reentrant_size||| +ref_array_or_hash||| +refcounted_he_chain_2hv||| +refcounted_he_fetch||| +refcounted_he_free||| +refcounted_he_new_common||| +refcounted_he_new||| +refcounted_he_value||| +refkids||| +refto||| +ref||5.011000| +reg_check_named_buff_matched||| +reg_named_buff_all||5.009005| +reg_named_buff_exists||5.009005| +reg_named_buff_fetch||5.009005| +reg_named_buff_firstkey||5.009005| +reg_named_buff_iter||| +reg_named_buff_nextkey||5.009005| +reg_named_buff_scalar||5.009005| +reg_named_buff||| +reg_namedseq||| +reg_node||| +reg_numbered_buff_fetch||| +reg_numbered_buff_length||| +reg_numbered_buff_store||| +reg_qr_package||| +reg_recode||| +reg_scan_name||| +reg_skipcomment||| +reg_temp_copy||| +reganode||| +regatom||| +regbranch||| +regclass_swash||5.009004| +regclass||| +regcppop||| +regcppush||| +regcurly|||n +regdump_extflags||| +regdump||5.005000| +regdupe_internal||| +regexec_flags||5.005000| +regfree_internal||5.009005| +reghop3|||n +reghop4|||n +reghopmaybe3|||n +reginclass||| +reginitcolors||5.006000| +reginsert||| +regmatch||| +regnext||5.005000| +regpiece||| +regpposixcc||| +regprop||| +regrepeat||| +regtail_study||| +regtail||| +regtry||| +reguni||| +regwhite|||n +reg||| +repeatcpy||| +report_evil_fh||| +report_uninit||| +require_pv||5.006000| +require_tie_mod||| +restore_magic||| +rninstr||| +rsignal_restore||| +rsignal_save||| +rsignal_state||5.004000| +rsignal||5.004000| +run_body||| +run_user_filter||| +runops_debug||5.005000| +runops_standard||5.005000| +rvpv_dup||| +rxres_free||| +rxres_restore||| +rxres_save||| +safesyscalloc||5.006000|n +safesysfree||5.006000|n +safesysmalloc||5.006000|n +safesysrealloc||5.006000|n +same_dirent||| +save_I16||5.004000| +save_I32||| +save_I8||5.006000| +save_adelete||5.011000| +save_aelem||5.004050| +save_alloc||5.006000| +save_aptr||| +save_ary||| +save_bool||5.008001| +save_clearsv||| +save_delete||| +save_destructor_x||5.006000| +save_destructor||5.006000| +save_freeop||| +save_freepv||| +save_freesv||| +save_generic_pvref||5.006001| +save_generic_svref||5.005030| +save_gp||5.004000| +save_hash||| +save_hek_flags|||n +save_helem_flags||5.011000| +save_helem||5.004050| +save_hints||| +save_hptr||| +save_int||| +save_item||| +save_iv||5.005000| +save_lines||| +save_list||| +save_long||| +save_magic||| +save_mortalizesv||5.007001| +save_nogv||| +save_op||| +save_padsv_and_mortalize||5.011000| +save_pptr||| +save_pushi32ptr||| +save_pushptri32ptr||| +save_pushptrptr||| +save_pushptr||5.011000| +save_re_context||5.006000| +save_scalar_at||| +save_scalar||| +save_set_svflags||5.009000| +save_shared_pvref||5.007003| +save_sptr||| +save_svref||| +save_vptr||5.006000| +savepvn||| +savepvs||5.009003| +savepv||| +savesharedpvn||5.009005| +savesharedpv||5.007003| +savestack_grow_cnt||5.008001| +savestack_grow||| +savesvpv||5.009002| +sawparens||| +scalar_mod_type|||n +scalarboolean||| +scalarkids||| +scalarseq||| +scalarvoid||| +scalar||| +scan_bin||5.006000| +scan_commit||| +scan_const||| +scan_formline||| +scan_heredoc||| +scan_hex||| +scan_ident||| +scan_inputsymbol||| +scan_num||5.007001| +scan_oct||| +scan_pat||| +scan_str||| +scan_subst||| +scan_trans||| +scan_version||5.009001| +scan_vstring||5.009005| +scan_word||| +scope||| +screaminstr||5.005000| +search_const||| +seed||5.008001| +sequence_num||| +sequence_tail||| +sequence||| +set_context||5.006000|n +set_numeric_local||5.006000| +set_numeric_radix||5.006000| +set_numeric_standard||5.006000| +setdefout||| +share_hek_flags||| +share_hek||5.004000| +si_dup||| +sighandler|||n +simplify_sort||| +skipspace0||| +skipspace1||| +skipspace2||| +skipspace||| +softref2xv||| +sortcv_stacked||| +sortcv_xsub||| +sortcv||| +sortsv_flags||5.009003| +sortsv||5.007003| +space_join_names_mortal||| +ss_dup||| +stack_grow||| +start_force||| +start_glob||| +start_subparse||5.004000| +stashpv_hvname_match||5.011000| +stdize_locale||| +store_cop_label||| +strEQ||| +strGE||| +strGT||| +strLE||| +strLT||| +strNE||| +str_to_version||5.006000| +strip_return||| +strnEQ||| +strnNE||| +study_chunk||| +sub_crush_depth||| +sublex_done||| +sublex_push||| +sublex_start||| +sv_2bool||| +sv_2cv||| +sv_2io||| +sv_2iuv_common||| +sv_2iuv_non_preserve||| +sv_2iv_flags||5.009001| +sv_2iv||| +sv_2mortal||| +sv_2num||| +sv_2nv||| +sv_2pv_flags|5.007002||p +sv_2pv_nolen|5.006000||p +sv_2pvbyte_nolen|5.006000||p +sv_2pvbyte|5.006000||p +sv_2pvutf8_nolen||5.006000| +sv_2pvutf8||5.006000| +sv_2pv||| +sv_2uv_flags||5.009001| +sv_2uv|5.004000||p +sv_add_arena||| +sv_add_backref||| +sv_backoff||| +sv_bless||| +sv_cat_decode||5.008001| +sv_catpv_mg|5.004050||p +sv_catpvf_mg_nocontext|||pvn +sv_catpvf_mg|5.006000|5.004000|pv +sv_catpvf_nocontext|||vn +sv_catpvf||5.004000|v +sv_catpvn_flags||5.007002| +sv_catpvn_mg|5.004050||p +sv_catpvn_nomg|5.007002||p +sv_catpvn||| +sv_catpvs|5.009003||p +sv_catpv||| +sv_catsv_flags||5.007002| +sv_catsv_mg|5.004050||p +sv_catsv_nomg|5.007002||p +sv_catsv||| +sv_catxmlpvn||| +sv_catxmlsv||| +sv_chop||| +sv_clean_all||| +sv_clean_objs||| +sv_clear||| +sv_cmp_locale||5.004000| +sv_cmp||| +sv_collxfrm||| +sv_compile_2op||5.008001| +sv_copypv||5.007003| +sv_dec||| +sv_del_backref||| +sv_derived_from||5.004000| +sv_destroyable||5.010000| +sv_does||5.009004| +sv_dump||| +sv_dup_inc_multiple||| +sv_dup||| +sv_eq||| +sv_exp_grow||| +sv_force_normal_flags||5.007001| +sv_force_normal||5.006000| +sv_free2||| +sv_free_arenas||| +sv_free||| +sv_gets||5.004000| +sv_grow||| +sv_i_ncmp||| +sv_inc||| +sv_insert_flags||5.011000| +sv_insert||| +sv_isa||| +sv_isobject||| +sv_iv||5.005000| +sv_kill_backrefs||| +sv_len_utf8||5.006000| +sv_len||| +sv_magic_portable|5.011000|5.004000|p +sv_magicext||5.007003| +sv_magic||| +sv_mortalcopy||| +sv_ncmp||| +sv_newmortal||| +sv_newref||| +sv_nolocking||5.007003| +sv_nosharing||5.007003| +sv_nounlocking||| +sv_nv||5.005000| +sv_peek||5.005000| +sv_pos_b2u_midway||| +sv_pos_b2u||5.006000| +sv_pos_u2b_cached||| +sv_pos_u2b_forwards|||n +sv_pos_u2b_midway|||n +sv_pos_u2b||5.006000| +sv_pvbyten_force||5.006000| +sv_pvbyten||5.006000| +sv_pvbyte||5.006000| +sv_pvn_force_flags|5.007002||p +sv_pvn_force||| +sv_pvn_nomg|5.007003|5.005000|p +sv_pvn||5.005000| +sv_pvutf8n_force||5.006000| +sv_pvutf8n||5.006000| +sv_pvutf8||5.006000| +sv_pv||5.006000| +sv_recode_to_utf8||5.007003| +sv_reftype||| +sv_release_COW||| +sv_replace||| +sv_report_used||| +sv_reset||| +sv_rvweaken||5.006000| +sv_setiv_mg|5.004050||p +sv_setiv||| +sv_setnv_mg|5.006000||p +sv_setnv||| +sv_setpv_mg|5.004050||p +sv_setpvf_mg_nocontext|||pvn +sv_setpvf_mg|5.006000|5.004000|pv +sv_setpvf_nocontext|||vn +sv_setpvf||5.004000|v +sv_setpviv_mg||5.008001| +sv_setpviv||5.008001| +sv_setpvn_mg|5.004050||p +sv_setpvn||| +sv_setpvs|5.009004||p +sv_setpv||| +sv_setref_iv||| +sv_setref_nv||| +sv_setref_pvn||| +sv_setref_pv||| +sv_setref_uv||5.007001| +sv_setsv_cow||| +sv_setsv_flags||5.007002| +sv_setsv_mg|5.004050||p +sv_setsv_nomg|5.007002||p +sv_setsv||| +sv_setuv_mg|5.004050||p +sv_setuv|5.004000||p +sv_tainted||5.004000| +sv_taint||5.004000| +sv_true||5.005000| +sv_unglob||| +sv_uni_display||5.007003| +sv_unmagic||| +sv_unref_flags||5.007001| +sv_unref||| +sv_untaint||5.004000| +sv_upgrade||| +sv_usepvn_flags||5.009004| +sv_usepvn_mg|5.004050||p +sv_usepvn||| +sv_utf8_decode||5.006000| +sv_utf8_downgrade||5.006000| +sv_utf8_encode||5.006000| +sv_utf8_upgrade_flags_grow||5.011000| +sv_utf8_upgrade_flags||5.007002| +sv_utf8_upgrade_nomg||5.007002| +sv_utf8_upgrade||5.007001| +sv_uv|5.005000||p +sv_vcatpvf_mg|5.006000|5.004000|p +sv_vcatpvfn||5.004000| +sv_vcatpvf|5.006000|5.004000|p +sv_vsetpvf_mg|5.006000|5.004000|p +sv_vsetpvfn||5.004000| +sv_vsetpvf|5.006000|5.004000|p +sv_xmlpeek||| +svtype||| +swallow_bom||| +swap_match_buff||| +swash_fetch||5.007002| +swash_get||| +swash_init||5.006000| +sys_init3||5.010000|n +sys_init||5.010000|n +sys_intern_clear||| +sys_intern_dup||| +sys_intern_init||| +sys_term||5.010000|n +taint_env||| +taint_proper||| +tmps_grow||5.006000| +toLOWER||| +toUPPER||| +to_byte_substr||| +to_uni_fold||5.007003| +to_uni_lower_lc||5.006000| +to_uni_lower||5.007003| +to_uni_title_lc||5.006000| +to_uni_title||5.007003| +to_uni_upper_lc||5.006000| +to_uni_upper||5.007003| +to_utf8_case||5.007003| +to_utf8_fold||5.007003| +to_utf8_lower||5.007003| +to_utf8_substr||| +to_utf8_title||5.007003| +to_utf8_upper||5.007003| +token_free||| +token_getmad||| +tokenize_use||| +tokeq||| +tokereport||| +too_few_arguments||| +too_many_arguments||| +uiv_2buf|||n +unlnk||| +unpack_rec||| +unpack_str||5.007003| +unpackstring||5.008001| +unshare_hek_or_pvn||| +unshare_hek||| +unsharepvn||5.004000| +unwind_handler_stack||| +update_debugger_info||| +upg_version||5.009005| +usage||| +utf16_to_utf8_reversed||5.006001| +utf16_to_utf8||5.006001| +utf8_distance||5.006000| +utf8_hop||5.006000| +utf8_length||5.007001| +utf8_mg_pos_cache_update||| +utf8_to_bytes||5.006001| +utf8_to_uvchr||5.007001| +utf8_to_uvuni||5.007001| +utf8n_to_uvchr||| +utf8n_to_uvuni||5.007001| +utilize||| +uvchr_to_utf8_flags||5.007003| +uvchr_to_utf8||| +uvuni_to_utf8_flags||5.007003| +uvuni_to_utf8||5.007001| +validate_suid||| +varname||| +vcmp||5.009000| +vcroak||5.006000| +vdeb||5.007003| +vdie_common||| +vdie_croak_common||| +vdie||| +vform||5.006000| +visit||| +vivify_defelem||| +vivify_ref||| +vload_module|5.006000||p +vmess||5.006000| +vnewSVpvf|5.006000|5.004000|p +vnormal||5.009002| +vnumify||5.009000| +vstringify||5.009000| +vverify||5.009003| +vwarner||5.006000| +vwarn||5.006000| +wait4pid||| +warn_nocontext|||vn +warner_nocontext|||vn +warner|5.006000|5.004000|pv +warn|||v +watch||| +whichsig||| +write_no_mem||| +write_to_stderr||| +xmldump_all||| +xmldump_attr||| +xmldump_eval||| +xmldump_form||| +xmldump_indent|||v +xmldump_packsubs||| +xmldump_sub||| +xmldump_vindent||| +yyerror||| +yylex||| +yyparse||| +yywarn||| +); + +if (exists $opt{'list-unsupported'}) { + my $f; + for $f (sort { lc $a cmp lc $b } keys %API) { + next unless $API{$f}{todo}; + print "$f ", '.'x(40-length($f)), " ", format_version($API{$f}{todo}), "\n"; + } + exit 0; +} + +# Scan for possible replacement candidates + +my(%replace, %need, %hints, %warnings, %depends); +my $replace = 0; +my($hint, $define, $function); + +sub find_api +{ + my $code = shift; + $code =~ s{ + / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]*) + | "[^"\\]*(?:\\.[^"\\]*)*" + | '[^'\\]*(?:\\.[^'\\]*)*' }{}egsx; + grep { exists $API{$_} } $code =~ /(\w+)/mg; +} + +while () { + if ($hint) { + my $h = $hint->[0] eq 'Hint' ? \%hints : \%warnings; + if (m{^\s*\*\s(.*?)\s*$}) { + for (@{$hint->[1]}) { + $h->{$_} ||= ''; # suppress warning with older perls + $h->{$_} .= "$1\n"; + } + } + else { undef $hint } + } + + $hint = [$1, [split /,?\s+/, $2]] + if m{^\s*$rccs\s+(Hint|Warning):\s+(\w+(?:,?\s+\w+)*)\s*$}; + + if ($define) { + if ($define->[1] =~ /\\$/) { + $define->[1] .= $_; + } + else { + if (exists $API{$define->[0]} && $define->[1] !~ /^DPPP_\(/) { + my @n = find_api($define->[1]); + push @{$depends{$define->[0]}}, @n if @n + } + undef $define; + } + } + + $define = [$1, $2] if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(.*)}; + + if ($function) { + if (/^}/) { + if (exists $API{$function->[0]}) { + my @n = find_api($function->[1]); + push @{$depends{$function->[0]}}, @n if @n + } + undef $function; + } + else { + $function->[1] .= $_; + } + } + + $function = [$1, ''] if m{^DPPP_\(my_(\w+)\)}; + + $replace = $1 if m{^\s*$rccs\s+Replace:\s+(\d+)\s+$rcce\s*$}; + $replace{$2} = $1 if $replace and m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+)}; + $replace{$2} = $1 if m{^\s*#\s*define\s+(\w+)(?:\([^)]*\))?\s+(\w+).*$rccs\s+Replace\s+$rcce}; + $replace{$1} = $2 if m{^\s*$rccs\s+Replace (\w+) with (\w+)\s+$rcce\s*$}; + + if (m{^\s*$rccs\s+(\w+(\s*,\s*\w+)*)\s+depends\s+on\s+(\w+(\s*,\s*\w+)*)\s+$rcce\s*$}) { + my @deps = map { s/\s+//g; $_ } split /,/, $3; + my $d; + for $d (map { s/\s+//g; $_ } split /,/, $1) { + push @{$depends{$d}}, @deps; + } + } + + $need{$1} = 1 if m{^#if\s+defined\(NEED_(\w+)(?:_GLOBAL)?\)}; +} + +for (values %depends) { + my %s; + $_ = [sort grep !$s{$_}++, @$_]; +} + +if (exists $opt{'api-info'}) { + my $f; + my $count = 0; + my $match = $opt{'api-info'} =~ m!^/(.*)/$! ? $1 : "^\Q$opt{'api-info'}\E\$"; + for $f (sort { lc $a cmp lc $b } keys %API) { + next unless $f =~ /$match/; + print "\n=== $f ===\n\n"; + my $info = 0; + if ($API{$f}{base} || $API{$f}{todo}) { + my $base = format_version($API{$f}{base} || $API{$f}{todo}); + print "Supported at least starting from perl-$base.\n"; + $info++; + } + if ($API{$f}{provided}) { + my $todo = $API{$f}{todo} ? format_version($API{$f}{todo}) : "5.003"; + print "Support by $ppport provided back to perl-$todo.\n"; + print "Support needs to be explicitly requested by NEED_$f.\n" if exists $need{$f}; + print "Depends on: ", join(', ', @{$depends{$f}}), ".\n" if exists $depends{$f}; + print "\n$hints{$f}" if exists $hints{$f}; + print "\nWARNING:\n$warnings{$f}" if exists $warnings{$f}; + $info++; + } + print "No portability information available.\n" unless $info; + $count++; + } + $count or print "Found no API matching '$opt{'api-info'}'."; + print "\n"; + exit 0; +} + +if (exists $opt{'list-provided'}) { + my $f; + for $f (sort { lc $a cmp lc $b } keys %API) { + next unless $API{$f}{provided}; + my @flags; + push @flags, 'explicit' if exists $need{$f}; + push @flags, 'depend' if exists $depends{$f}; + push @flags, 'hint' if exists $hints{$f}; + push @flags, 'warning' if exists $warnings{$f}; + my $flags = @flags ? ' ['.join(', ', @flags).']' : ''; + print "$f$flags\n"; + } + exit 0; +} + +my @files; +my @srcext = qw( .xs .c .h .cc .cpp -c.inc -xs.inc ); +my $srcext = join '|', map { quotemeta $_ } @srcext; + +if (@ARGV) { + my %seen; + for (@ARGV) { + if (-e) { + if (-f) { + push @files, $_ unless $seen{$_}++; + } + else { warn "'$_' is not a file.\n" } + } + else { + my @new = grep { -f } glob $_ + or warn "'$_' does not exist.\n"; + push @files, grep { !$seen{$_}++ } @new; + } + } +} +else { + eval { + require File::Find; + File::Find::find(sub { + $File::Find::name =~ /($srcext)$/i + and push @files, $File::Find::name; + }, '.'); + }; + if ($@) { + @files = map { glob "*$_" } @srcext; + } +} + +if (!@ARGV || $opt{filter}) { + my(@in, @out); + my %xsc = map { /(.*)\.xs$/ ? ("$1.c" => 1, "$1.cc" => 1) : () } @files; + for (@files) { + my $out = exists $xsc{$_} || /\b\Q$ppport\E$/i || !/($srcext)$/i; + push @{ $out ? \@out : \@in }, $_; + } + if (@ARGV && @out) { + warning("Skipping the following files (use --nofilter to avoid this):\n| ", join "\n| ", @out); + } + @files = @in; +} + +die "No input files given!\n" unless @files; + +my(%files, %global, %revreplace); +%revreplace = reverse %replace; +my $filename; +my $patch_opened = 0; + +for $filename (@files) { + unless (open IN, "<$filename") { + warn "Unable to read from $filename: $!\n"; + next; + } + + info("Scanning $filename ..."); + + my $c = do { local $/; }; + close IN; + + my %file = (orig => $c, changes => 0); + + # Temporarily remove C/XS comments and strings from the code + my @ccom; + + $c =~ s{ + ( ^$HS*\#$HS*include\b[^\r\n]+\b(?:\Q$ppport\E|XSUB\.h)\b[^\r\n]* + | ^$HS*\#$HS*(?:define|elif|if(?:def)?)\b[^\r\n]* ) + | ( ^$HS*\#[^\r\n]* + | "[^"\\]*(?:\\.[^"\\]*)*" + | '[^'\\]*(?:\\.[^'\\]*)*' + | / (?: \*[^*]*\*+(?:[^$ccs][^*]*\*+)* / | /[^\r\n]* ) ) + }{ defined $2 and push @ccom, $2; + defined $1 ? $1 : "$ccs$#ccom$cce" }mgsex; + + $file{ccom} = \@ccom; + $file{code} = $c; + $file{has_inc_ppport} = $c =~ /^$HS*#$HS*include[^\r\n]+\b\Q$ppport\E\b/m; + + my $func; + + for $func (keys %API) { + my $match = $func; + $match .= "|$revreplace{$func}" if exists $revreplace{$func}; + if ($c =~ /\b(?:Perl_)?($match)\b/) { + $file{uses_replace}{$1}++ if exists $revreplace{$func} && $1 eq $revreplace{$func}; + $file{uses_Perl}{$func}++ if $c =~ /\bPerl_$func\b/; + if (exists $API{$func}{provided}) { + $file{uses_provided}{$func}++; + if (!exists $API{$func}{base} || $API{$func}{base} > $opt{'compat-version'}) { + $file{uses}{$func}++; + my @deps = rec_depend($func); + if (@deps) { + $file{uses_deps}{$func} = \@deps; + for (@deps) { + $file{uses}{$_} = 0 unless exists $file{uses}{$_}; + } + } + for ($func, @deps) { + $file{needs}{$_} = 'static' if exists $need{$_}; + } + } + } + if (exists $API{$func}{todo} && $API{$func}{todo} > $opt{'compat-version'}) { + if ($c =~ /\b$func\b/) { + $file{uses_todo}{$func}++; + } + } + } + } + + while ($c =~ /^$HS*#$HS*define$HS+(NEED_(\w+?)(_GLOBAL)?)\b/mg) { + if (exists $need{$2}) { + $file{defined $3 ? 'needed_global' : 'needed_static'}{$2}++; + } + else { warning("Possibly wrong #define $1 in $filename") } + } + + for (qw(uses needs uses_todo needed_global needed_static)) { + for $func (keys %{$file{$_}}) { + push @{$global{$_}{$func}}, $filename; + } + } + + $files{$filename} = \%file; +} + +# Globally resolve NEED_'s +my $need; +for $need (keys %{$global{needs}}) { + if (@{$global{needs}{$need}} > 1) { + my @targets = @{$global{needs}{$need}}; + my @t = grep $files{$_}{needed_global}{$need}, @targets; + @targets = @t if @t; + @t = grep /\.xs$/i, @targets; + @targets = @t if @t; + my $target = shift @targets; + $files{$target}{needs}{$need} = 'global'; + for (@{$global{needs}{$need}}) { + $files{$_}{needs}{$need} = 'extern' if $_ ne $target; + } + } +} + +for $filename (@files) { + exists $files{$filename} or next; + + info("=== Analyzing $filename ==="); + + my %file = %{$files{$filename}}; + my $func; + my $c = $file{code}; + my $warnings = 0; + + for $func (sort keys %{$file{uses_Perl}}) { + if ($API{$func}{varargs}) { + unless ($API{$func}{nothxarg}) { + my $changes = ($c =~ s{\b(Perl_$func\s*\(\s*)(?!aTHX_?)(\)|[^\s)]*\))} + { $1 . ($2 eq ')' ? 'aTHX' : 'aTHX_ ') . $2 }ge); + if ($changes) { + warning("Doesn't pass interpreter argument aTHX to Perl_$func"); + $file{changes} += $changes; + } + } + } + else { + warning("Uses Perl_$func instead of $func"); + $file{changes} += ($c =~ s{\bPerl_$func(\s*)\((\s*aTHX_?)?\s*} + {$func$1(}g); + } + } + + for $func (sort keys %{$file{uses_replace}}) { + warning("Uses $func instead of $replace{$func}"); + $file{changes} += ($c =~ s/\b$func\b/$replace{$func}/g); + } + + for $func (sort keys %{$file{uses_provided}}) { + if ($file{uses}{$func}) { + if (exists $file{uses_deps}{$func}) { + diag("Uses $func, which depends on ", join(', ', @{$file{uses_deps}{$func}})); + } + else { + diag("Uses $func"); + } + } + $warnings += hint($func); + } + + unless ($opt{quiet}) { + for $func (sort keys %{$file{uses_todo}}) { + print "*** WARNING: Uses $func, which may not be portable below perl ", + format_version($API{$func}{todo}), ", even with '$ppport'\n"; + $warnings++; + } + } + + for $func (sort keys %{$file{needed_static}}) { + my $message = ''; + if (not exists $file{uses}{$func}) { + $message = "No need to define NEED_$func if $func is never used"; + } + elsif (exists $file{needs}{$func} && $file{needs}{$func} ne 'static') { + $message = "No need to define NEED_$func when already needed globally"; + } + if ($message) { + diag($message); + $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_$func\b.*$LF//mg); + } + } + + for $func (sort keys %{$file{needed_global}}) { + my $message = ''; + if (not exists $global{uses}{$func}) { + $message = "No need to define NEED_${func}_GLOBAL if $func is never used"; + } + elsif (exists $file{needs}{$func}) { + if ($file{needs}{$func} eq 'extern') { + $message = "No need to define NEED_${func}_GLOBAL when already needed globally"; + } + elsif ($file{needs}{$func} eq 'static') { + $message = "No need to define NEED_${func}_GLOBAL when only used in this file"; + } + } + if ($message) { + diag($message); + $file{changes} += ($c =~ s/^$HS*#$HS*define$HS+NEED_${func}_GLOBAL\b.*$LF//mg); + } + } + + $file{needs_inc_ppport} = keys %{$file{uses}}; + + if ($file{needs_inc_ppport}) { + my $pp = ''; + + for $func (sort keys %{$file{needs}}) { + my $type = $file{needs}{$func}; + next if $type eq 'extern'; + my $suffix = $type eq 'global' ? '_GLOBAL' : ''; + unless (exists $file{"needed_$type"}{$func}) { + if ($type eq 'global') { + diag("Files [@{$global{needs}{$func}}] need $func, adding global request"); + } + else { + diag("File needs $func, adding static request"); + } + $pp .= "#define NEED_$func$suffix\n"; + } + } + + if ($pp && ($c =~ s/^(?=$HS*#$HS*define$HS+NEED_\w+)/$pp/m)) { + $pp = ''; + $file{changes}++; + } + + unless ($file{has_inc_ppport}) { + diag("Needs to include '$ppport'"); + $pp .= qq(#include "$ppport"\n) + } + + if ($pp) { + $file{changes} += ($c =~ s/^($HS*#$HS*define$HS+NEED_\w+.*?)^/$1$pp/ms) + || ($c =~ s/^(?=$HS*#$HS*include.*\Q$ppport\E)/$pp/m) + || ($c =~ s/^($HS*#$HS*include.*XSUB.*\s*?)^/$1$pp/m) + || ($c =~ s/^/$pp/); + } + } + else { + if ($file{has_inc_ppport}) { + diag("No need to include '$ppport'"); + $file{changes} += ($c =~ s/^$HS*?#$HS*include.*\Q$ppport\E.*?$LF//m); + } + } + + # put back in our C comments + my $ix; + my $cppc = 0; + my @ccom = @{$file{ccom}}; + for $ix (0 .. $#ccom) { + if (!$opt{cplusplus} && $ccom[$ix] =~ s!^//!!) { + $cppc++; + $file{changes} += $c =~ s/$rccs$ix$rcce/$ccs$ccom[$ix] $cce/; + } + else { + $c =~ s/$rccs$ix$rcce/$ccom[$ix]/; + } + } + + if ($cppc) { + my $s = $cppc != 1 ? 's' : ''; + warning("Uses $cppc C++ style comment$s, which is not portable"); + } + + my $s = $warnings != 1 ? 's' : ''; + my $warn = $warnings ? " ($warnings warning$s)" : ''; + info("Analysis completed$warn"); + + if ($file{changes}) { + if (exists $opt{copy}) { + my $newfile = "$filename$opt{copy}"; + if (-e $newfile) { + error("'$newfile' already exists, refusing to write copy of '$filename'"); + } + else { + local *F; + if (open F, ">$newfile") { + info("Writing copy of '$filename' with changes to '$newfile'"); + print F $c; + close F; + } + else { + error("Cannot open '$newfile' for writing: $!"); + } + } + } + elsif (exists $opt{patch} || $opt{changes}) { + if (exists $opt{patch}) { + unless ($patch_opened) { + if (open PATCH, ">$opt{patch}") { + $patch_opened = 1; + } + else { + error("Cannot open '$opt{patch}' for writing: $!"); + delete $opt{patch}; + $opt{changes} = 1; + goto fallback; + } + } + mydiff(\*PATCH, $filename, $c); + } + else { +fallback: + info("Suggested changes:"); + mydiff(\*STDOUT, $filename, $c); + } + } + else { + my $s = $file{changes} == 1 ? '' : 's'; + info("$file{changes} potentially required change$s detected"); + } + } + else { + info("Looks good"); + } +} + +close PATCH if $patch_opened; + +exit 0; + + +sub try_use { eval "use @_;"; return $@ eq '' } + +sub mydiff +{ + local *F = shift; + my($file, $str) = @_; + my $diff; + + if (exists $opt{diff}) { + $diff = run_diff($opt{diff}, $file, $str); + } + + if (!defined $diff and try_use('Text::Diff')) { + $diff = Text::Diff::diff($file, \$str, { STYLE => 'Unified' }); + $diff = <
$tmp") { + print F $str; + close F; + + if (open F, "$prog $file $tmp |") { + while () { + s/\Q$tmp\E/$file.patched/; + $diff .= $_; + } + close F; + unlink $tmp; + return $diff; + } + + unlink $tmp; + } + else { + error("Cannot open '$tmp' for writing: $!"); + } + + return undef; +} + +sub rec_depend +{ + my($func, $seen) = @_; + return () unless exists $depends{$func}; + $seen = {%{$seen||{}}}; + return () if $seen->{$func}++; + my %s; + grep !$s{$_}++, map { ($_, rec_depend($_, $seen)) } @{$depends{$func}}; +} + +sub parse_version +{ + my $ver = shift; + + if ($ver =~ /^(\d+)\.(\d+)\.(\d+)$/) { + return ($1, $2, $3); + } + elsif ($ver !~ /^\d+\.[\d_]+$/) { + die "cannot parse version '$ver'\n"; + } + + $ver =~ s/_//g; + $ver =~ s/$/000000/; + + my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; + + $v = int $v; + $s = int $s; + + if ($r < 5 || ($r == 5 && $v < 6)) { + if ($s % 10) { + die "cannot parse version '$ver'\n"; + } + } + + return ($r, $v, $s); +} + +sub format_version +{ + my $ver = shift; + + $ver =~ s/$/000000/; + my($r,$v,$s) = $ver =~ /(\d+)\.(\d{3})(\d{3})/; + + $v = int $v; + $s = int $s; + + if ($r < 5 || ($r == 5 && $v < 6)) { + if ($s % 10) { + die "invalid version '$ver'\n"; + } + $s /= 10; + + $ver = sprintf "%d.%03d", $r, $v; + $s > 0 and $ver .= sprintf "_%02d", $s; + + return $ver; + } + + return sprintf "%d.%d.%d", $r, $v, $s; +} + +sub info +{ + $opt{quiet} and return; + print @_, "\n"; +} + +sub diag +{ + $opt{quiet} and return; + $opt{diag} and print @_, "\n"; +} + +sub warning +{ + $opt{quiet} and return; + print "*** ", @_, "\n"; +} + +sub error +{ + print "*** ERROR: ", @_, "\n"; +} + +my %given_hints; +my %given_warnings; +sub hint +{ + $opt{quiet} and return; + my $func = shift; + my $rv = 0; + if (exists $warnings{$func} && !$given_warnings{$func}++) { + my $warn = $warnings{$func}; + $warn =~ s!^!*** !mg; + print "*** WARNING: $func\n", $warn; + $rv++; + } + if ($opt{hints} && exists $hints{$func} && !$given_hints{$func}++) { + my $hint = $hints{$func}; + $hint =~ s/^/ /mg; + print " --- hint for $func ---\n", $hint; + } + $rv; +} + +sub usage +{ + my($usage) = do { local(@ARGV,$/)=($0); <> } =~ /^=head\d$HS+SYNOPSIS\s*^(.*?)\s*^=/ms; + my %M = ( 'I' => '*' ); + $usage =~ s/^\s*perl\s+\S+/$^X $0/; + $usage =~ s/([A-Z])<([^>]+)>/$M{$1}$2$M{$1}/g; + + print < }; + my($copy) = $self =~ /^=head\d\s+COPYRIGHT\s*^(.*?)^=\w+/ms; + $copy =~ s/^(?=\S+)/ /gms; + $self =~ s/^$HS+Do NOT edit.*?(?=^-)/$copy/ms; + $self =~ s/^SKIP.*(?=^__DATA__)/SKIP +if (\@ARGV && \$ARGV[0] eq '--unstrip') { + eval { require Devel::PPPort }; + \$@ and die "Cannot require Devel::PPPort, please install.\\n"; + if (eval \$Devel::PPPort::VERSION < $VERSION) { + die "$0 was originally generated with Devel::PPPort $VERSION.\\n" + . "Your Devel::PPPort is only version \$Devel::PPPort::VERSION.\\n" + . "Please install a newer version, or --unstrip will not work.\\n"; + } + Devel::PPPort::WriteFile(\$0); + exit 0; +} +print <$0" or die "cannot strip $0: $!\n"; + print OUT "$pl$c\n"; + + exit 0; +} + +__DATA__ +*/ + +#ifndef _P_P_PORTABILITY_H_ +#define _P_P_PORTABILITY_H_ + +#ifndef DPPP_NAMESPACE +# define DPPP_NAMESPACE DPPP_ +#endif + +#define DPPP_CAT2(x,y) CAT2(x,y) +#define DPPP_(name) DPPP_CAT2(DPPP_NAMESPACE, name) + +#ifndef PERL_REVISION +# if !defined(__PATCHLEVEL_H_INCLUDED__) && !(defined(PATCHLEVEL) && defined(SUBVERSION)) +# define PERL_PATCHLEVEL_H_IMPLICIT +# include +# endif +# if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) +# include +# endif +# ifndef PERL_REVISION +# define PERL_REVISION (5) + /* Replace: 1 */ +# define PERL_VERSION PATCHLEVEL +# define PERL_SUBVERSION SUBVERSION + /* Replace PERL_PATCHLEVEL with PERL_VERSION */ + /* Replace: 0 */ +# endif +#endif + +#define _dpppDEC2BCD(dec) ((((dec)/100)<<8)|((((dec)%100)/10)<<4)|((dec)%10)) +#define PERL_BCDVERSION ((_dpppDEC2BCD(PERL_REVISION)<<24)|(_dpppDEC2BCD(PERL_VERSION)<<12)|_dpppDEC2BCD(PERL_SUBVERSION)) + +/* It is very unlikely that anyone will try to use this with Perl 6 + (or greater), but who knows. + */ +#if PERL_REVISION != 5 +# error ppport.h only works with Perl version 5 +#endif /* PERL_REVISION != 5 */ +#ifndef dTHR +# define dTHR dNOOP +#endif +#ifndef dTHX +# define dTHX dNOOP +#endif + +#ifndef dTHXa +# define dTHXa(x) dNOOP +#endif +#ifndef pTHX +# define pTHX void +#endif + +#ifndef pTHX_ +# define pTHX_ +#endif + +#ifndef aTHX +# define aTHX +#endif + +#ifndef aTHX_ +# define aTHX_ +#endif + +#if (PERL_BCDVERSION < 0x5006000) +# ifdef USE_THREADS +# define aTHXR thr +# define aTHXR_ thr, +# else +# define aTHXR +# define aTHXR_ +# endif +# define dTHXR dTHR +#else +# define aTHXR aTHX +# define aTHXR_ aTHX_ +# define dTHXR dTHX +#endif +#ifndef dTHXoa +# define dTHXoa(x) dTHXa(x) +#endif + +#ifdef I_LIMITS +# include +#endif + +#ifndef PERL_UCHAR_MIN +# define PERL_UCHAR_MIN ((unsigned char)0) +#endif + +#ifndef PERL_UCHAR_MAX +# ifdef UCHAR_MAX +# define PERL_UCHAR_MAX ((unsigned char)UCHAR_MAX) +# else +# ifdef MAXUCHAR +# define PERL_UCHAR_MAX ((unsigned char)MAXUCHAR) +# else +# define PERL_UCHAR_MAX ((unsigned char)~(unsigned)0) +# endif +# endif +#endif + +#ifndef PERL_USHORT_MIN +# define PERL_USHORT_MIN ((unsigned short)0) +#endif + +#ifndef PERL_USHORT_MAX +# ifdef USHORT_MAX +# define PERL_USHORT_MAX ((unsigned short)USHORT_MAX) +# else +# ifdef MAXUSHORT +# define PERL_USHORT_MAX ((unsigned short)MAXUSHORT) +# else +# ifdef USHRT_MAX +# define PERL_USHORT_MAX ((unsigned short)USHRT_MAX) +# else +# define PERL_USHORT_MAX ((unsigned short)~(unsigned)0) +# endif +# endif +# endif +#endif + +#ifndef PERL_SHORT_MAX +# ifdef SHORT_MAX +# define PERL_SHORT_MAX ((short)SHORT_MAX) +# else +# ifdef MAXSHORT /* Often used in */ +# define PERL_SHORT_MAX ((short)MAXSHORT) +# else +# ifdef SHRT_MAX +# define PERL_SHORT_MAX ((short)SHRT_MAX) +# else +# define PERL_SHORT_MAX ((short) (PERL_USHORT_MAX >> 1)) +# endif +# endif +# endif +#endif + +#ifndef PERL_SHORT_MIN +# ifdef SHORT_MIN +# define PERL_SHORT_MIN ((short)SHORT_MIN) +# else +# ifdef MINSHORT +# define PERL_SHORT_MIN ((short)MINSHORT) +# else +# ifdef SHRT_MIN +# define PERL_SHORT_MIN ((short)SHRT_MIN) +# else +# define PERL_SHORT_MIN (-PERL_SHORT_MAX - ((3 & -1) == 3)) +# endif +# endif +# endif +#endif + +#ifndef PERL_UINT_MAX +# ifdef UINT_MAX +# define PERL_UINT_MAX ((unsigned int)UINT_MAX) +# else +# ifdef MAXUINT +# define PERL_UINT_MAX ((unsigned int)MAXUINT) +# else +# define PERL_UINT_MAX (~(unsigned int)0) +# endif +# endif +#endif + +#ifndef PERL_UINT_MIN +# define PERL_UINT_MIN ((unsigned int)0) +#endif + +#ifndef PERL_INT_MAX +# ifdef INT_MAX +# define PERL_INT_MAX ((int)INT_MAX) +# else +# ifdef MAXINT /* Often used in */ +# define PERL_INT_MAX ((int)MAXINT) +# else +# define PERL_INT_MAX ((int)(PERL_UINT_MAX >> 1)) +# endif +# endif +#endif + +#ifndef PERL_INT_MIN +# ifdef INT_MIN +# define PERL_INT_MIN ((int)INT_MIN) +# else +# ifdef MININT +# define PERL_INT_MIN ((int)MININT) +# else +# define PERL_INT_MIN (-PERL_INT_MAX - ((3 & -1) == 3)) +# endif +# endif +#endif + +#ifndef PERL_ULONG_MAX +# ifdef ULONG_MAX +# define PERL_ULONG_MAX ((unsigned long)ULONG_MAX) +# else +# ifdef MAXULONG +# define PERL_ULONG_MAX ((unsigned long)MAXULONG) +# else +# define PERL_ULONG_MAX (~(unsigned long)0) +# endif +# endif +#endif + +#ifndef PERL_ULONG_MIN +# define PERL_ULONG_MIN ((unsigned long)0L) +#endif + +#ifndef PERL_LONG_MAX +# ifdef LONG_MAX +# define PERL_LONG_MAX ((long)LONG_MAX) +# else +# ifdef MAXLONG +# define PERL_LONG_MAX ((long)MAXLONG) +# else +# define PERL_LONG_MAX ((long) (PERL_ULONG_MAX >> 1)) +# endif +# endif +#endif + +#ifndef PERL_LONG_MIN +# ifdef LONG_MIN +# define PERL_LONG_MIN ((long)LONG_MIN) +# else +# ifdef MINLONG +# define PERL_LONG_MIN ((long)MINLONG) +# else +# define PERL_LONG_MIN (-PERL_LONG_MAX - ((3 & -1) == 3)) +# endif +# endif +#endif + +#if defined(HAS_QUAD) && (defined(convex) || defined(uts)) +# ifndef PERL_UQUAD_MAX +# ifdef ULONGLONG_MAX +# define PERL_UQUAD_MAX ((unsigned long long)ULONGLONG_MAX) +# else +# ifdef MAXULONGLONG +# define PERL_UQUAD_MAX ((unsigned long long)MAXULONGLONG) +# else +# define PERL_UQUAD_MAX (~(unsigned long long)0) +# endif +# endif +# endif + +# ifndef PERL_UQUAD_MIN +# define PERL_UQUAD_MIN ((unsigned long long)0L) +# endif + +# ifndef PERL_QUAD_MAX +# ifdef LONGLONG_MAX +# define PERL_QUAD_MAX ((long long)LONGLONG_MAX) +# else +# ifdef MAXLONGLONG +# define PERL_QUAD_MAX ((long long)MAXLONGLONG) +# else +# define PERL_QUAD_MAX ((long long) (PERL_UQUAD_MAX >> 1)) +# endif +# endif +# endif + +# ifndef PERL_QUAD_MIN +# ifdef LONGLONG_MIN +# define PERL_QUAD_MIN ((long long)LONGLONG_MIN) +# else +# ifdef MINLONGLONG +# define PERL_QUAD_MIN ((long long)MINLONGLONG) +# else +# define PERL_QUAD_MIN (-PERL_QUAD_MAX - ((3 & -1) == 3)) +# endif +# endif +# endif +#endif + +/* This is based on code from 5.003 perl.h */ +#ifdef HAS_QUAD +# ifdef cray +#ifndef IVTYPE +# define IVTYPE int +#endif + +#ifndef IV_MIN +# define IV_MIN PERL_INT_MIN +#endif + +#ifndef IV_MAX +# define IV_MAX PERL_INT_MAX +#endif + +#ifndef UV_MIN +# define UV_MIN PERL_UINT_MIN +#endif + +#ifndef UV_MAX +# define UV_MAX PERL_UINT_MAX +#endif + +# ifdef INTSIZE +#ifndef IVSIZE +# define IVSIZE INTSIZE +#endif + +# endif +# else +# if defined(convex) || defined(uts) +#ifndef IVTYPE +# define IVTYPE long long +#endif + +#ifndef IV_MIN +# define IV_MIN PERL_QUAD_MIN +#endif + +#ifndef IV_MAX +# define IV_MAX PERL_QUAD_MAX +#endif + +#ifndef UV_MIN +# define UV_MIN PERL_UQUAD_MIN +#endif + +#ifndef UV_MAX +# define UV_MAX PERL_UQUAD_MAX +#endif + +# ifdef LONGLONGSIZE +#ifndef IVSIZE +# define IVSIZE LONGLONGSIZE +#endif + +# endif +# else +#ifndef IVTYPE +# define IVTYPE long +#endif + +#ifndef IV_MIN +# define IV_MIN PERL_LONG_MIN +#endif + +#ifndef IV_MAX +# define IV_MAX PERL_LONG_MAX +#endif + +#ifndef UV_MIN +# define UV_MIN PERL_ULONG_MIN +#endif + +#ifndef UV_MAX +# define UV_MAX PERL_ULONG_MAX +#endif + +# ifdef LONGSIZE +#ifndef IVSIZE +# define IVSIZE LONGSIZE +#endif + +# endif +# endif +# endif +#ifndef IVSIZE +# define IVSIZE 8 +#endif + +#ifndef PERL_QUAD_MIN +# define PERL_QUAD_MIN IV_MIN +#endif + +#ifndef PERL_QUAD_MAX +# define PERL_QUAD_MAX IV_MAX +#endif + +#ifndef PERL_UQUAD_MIN +# define PERL_UQUAD_MIN UV_MIN +#endif + +#ifndef PERL_UQUAD_MAX +# define PERL_UQUAD_MAX UV_MAX +#endif + +#else +#ifndef IVTYPE +# define IVTYPE long +#endif + +#ifndef IV_MIN +# define IV_MIN PERL_LONG_MIN +#endif + +#ifndef IV_MAX +# define IV_MAX PERL_LONG_MAX +#endif + +#ifndef UV_MIN +# define UV_MIN PERL_ULONG_MIN +#endif + +#ifndef UV_MAX +# define UV_MAX PERL_ULONG_MAX +#endif + +#endif + +#ifndef IVSIZE +# ifdef LONGSIZE +# define IVSIZE LONGSIZE +# else +# define IVSIZE 4 /* A bold guess, but the best we can make. */ +# endif +#endif +#ifndef UVTYPE +# define UVTYPE unsigned IVTYPE +#endif + +#ifndef UVSIZE +# define UVSIZE IVSIZE +#endif +#ifndef sv_setuv +# define sv_setuv(sv, uv) \ + STMT_START { \ + UV TeMpUv = uv; \ + if (TeMpUv <= IV_MAX) \ + sv_setiv(sv, TeMpUv); \ + else \ + sv_setnv(sv, (double)TeMpUv); \ + } STMT_END +#endif +#ifndef newSVuv +# define newSVuv(uv) ((uv) <= IV_MAX ? newSViv((IV)uv) : newSVnv((NV)uv)) +#endif +#ifndef sv_2uv +# define sv_2uv(sv) ((PL_Sv = (sv)), (UV) (SvNOK(PL_Sv) ? SvNV(PL_Sv) : sv_2nv(PL_Sv))) +#endif + +#ifndef SvUVX +# define SvUVX(sv) ((UV)SvIVX(sv)) +#endif + +#ifndef SvUVXx +# define SvUVXx(sv) SvUVX(sv) +#endif + +#ifndef SvUV +# define SvUV(sv) (SvIOK(sv) ? SvUVX(sv) : sv_2uv(sv)) +#endif + +#ifndef SvUVx +# define SvUVx(sv) ((PL_Sv = (sv)), SvUV(PL_Sv)) +#endif + +/* Hint: sv_uv + * Always use the SvUVx() macro instead of sv_uv(). + */ +#ifndef sv_uv +# define sv_uv(sv) SvUVx(sv) +#endif + +#if !defined(SvUOK) && defined(SvIOK_UV) +# define SvUOK(sv) SvIOK_UV(sv) +#endif +#ifndef XST_mUV +# define XST_mUV(i,v) (ST(i) = sv_2mortal(newSVuv(v)) ) +#endif + +#ifndef XSRETURN_UV +# define XSRETURN_UV(v) STMT_START { XST_mUV(0,v); XSRETURN(1); } STMT_END +#endif +#ifndef PUSHu +# define PUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); PUSHTARG; } STMT_END +#endif + +#ifndef XPUSHu +# define XPUSHu(u) STMT_START { sv_setuv(TARG, (UV)(u)); XPUSHTARG; } STMT_END +#endif + +#ifdef HAS_MEMCMP +#ifndef memNE +# define memNE(s1,s2,l) (memcmp(s1,s2,l)) +#endif + +#ifndef memEQ +# define memEQ(s1,s2,l) (!memcmp(s1,s2,l)) +#endif + +#else +#ifndef memNE +# define memNE(s1,s2,l) (bcmp(s1,s2,l)) +#endif + +#ifndef memEQ +# define memEQ(s1,s2,l) (!bcmp(s1,s2,l)) +#endif + +#endif +#ifndef MoveD +# define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t)) +#endif + +#ifndef CopyD +# define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t)) +#endif + +#ifdef HAS_MEMSET +#ifndef ZeroD +# define ZeroD(d,n,t) memzero((char*)(d), (n) * sizeof(t)) +#endif + +#else +#ifndef ZeroD +# define ZeroD(d,n,t) ((void)memzero((char*)(d), (n) * sizeof(t)), d) +#endif + +#endif +#ifndef PoisonWith +# define PoisonWith(d,n,t,b) (void)memset((char*)(d), (U8)(b), (n) * sizeof(t)) +#endif + +#ifndef PoisonNew +# define PoisonNew(d,n,t) PoisonWith(d,n,t,0xAB) +#endif + +#ifndef PoisonFree +# define PoisonFree(d,n,t) PoisonWith(d,n,t,0xEF) +#endif + +#ifndef Poison +# define Poison(d,n,t) PoisonFree(d,n,t) +#endif +#ifndef Newx +# define Newx(v,n,t) New(0,v,n,t) +#endif + +#ifndef Newxc +# define Newxc(v,n,t,c) Newc(0,v,n,t,c) +#endif + +#ifndef Newxz +# define Newxz(v,n,t) Newz(0,v,n,t) +#endif + +#ifndef PERL_UNUSED_DECL +# ifdef HASATTRIBUTE +# if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER) +# define PERL_UNUSED_DECL +# else +# define PERL_UNUSED_DECL __attribute__((unused)) +# endif +# else +# define PERL_UNUSED_DECL +# endif +#endif + +#ifndef PERL_UNUSED_ARG +# if defined(lint) && defined(S_SPLINT_S) /* www.splint.org */ +# include +# define PERL_UNUSED_ARG(x) NOTE(ARGUNUSED(x)) +# else +# define PERL_UNUSED_ARG(x) ((void)x) +# endif +#endif + +#ifndef PERL_UNUSED_VAR +# define PERL_UNUSED_VAR(x) ((void)x) +#endif + +#ifndef PERL_UNUSED_CONTEXT +# ifdef USE_ITHREADS +# define PERL_UNUSED_CONTEXT PERL_UNUSED_ARG(my_perl) +# else +# define PERL_UNUSED_CONTEXT +# endif +#endif +#ifndef NOOP +# define NOOP /*EMPTY*/(void)0 +#endif + +#ifndef dNOOP +# define dNOOP extern int /*@unused@*/ Perl___notused PERL_UNUSED_DECL +#endif + +#ifndef NVTYPE +# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) +# define NVTYPE long double +# else +# define NVTYPE double +# endif +typedef NVTYPE NV; +#endif + +#ifndef INT2PTR +# if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) +# define PTRV UV +# define INT2PTR(any,d) (any)(d) +# else +# if PTRSIZE == LONGSIZE +# define PTRV unsigned long +# else +# define PTRV unsigned +# endif +# define INT2PTR(any,d) (any)(PTRV)(d) +# endif +#endif + +#ifndef PTR2ul +# if PTRSIZE == LONGSIZE +# define PTR2ul(p) (unsigned long)(p) +# else +# define PTR2ul(p) INT2PTR(unsigned long,p) +# endif +#endif +#ifndef PTR2nat +# define PTR2nat(p) (PTRV)(p) +#endif + +#ifndef NUM2PTR +# define NUM2PTR(any,d) (any)PTR2nat(d) +#endif + +#ifndef PTR2IV +# define PTR2IV(p) INT2PTR(IV,p) +#endif + +#ifndef PTR2UV +# define PTR2UV(p) INT2PTR(UV,p) +#endif + +#ifndef PTR2NV +# define PTR2NV(p) NUM2PTR(NV,p) +#endif + +#undef START_EXTERN_C +#undef END_EXTERN_C +#undef EXTERN_C +#ifdef __cplusplus +# define START_EXTERN_C extern "C" { +# define END_EXTERN_C } +# define EXTERN_C extern "C" +#else +# define START_EXTERN_C +# define END_EXTERN_C +# define EXTERN_C extern +#endif + +#if defined(PERL_GCC_PEDANTIC) +# ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN +# define PERL_GCC_BRACE_GROUPS_FORBIDDEN +# endif +#endif + +#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus) +# ifndef PERL_USE_GCC_BRACE_GROUPS +# define PERL_USE_GCC_BRACE_GROUPS +# endif +#endif + +#undef STMT_START +#undef STMT_END +#ifdef PERL_USE_GCC_BRACE_GROUPS +# define STMT_START (void)( /* gcc supports ``({ STATEMENTS; })'' */ +# define STMT_END ) +#else +# if defined(VOIDFLAGS) && (VOIDFLAGS) && (defined(sun) || defined(__sun__)) && !defined(__GNUC__) +# define STMT_START if (1) +# define STMT_END else (void)0 +# else +# define STMT_START do +# define STMT_END while (0) +# endif +#endif +#ifndef boolSV +# define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no) +#endif + +/* DEFSV appears first in 5.004_56 */ +#ifndef DEFSV +# define DEFSV GvSV(PL_defgv) +#endif + +#ifndef SAVE_DEFSV +# define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) +#endif + +#ifndef DEFSV_set +# define DEFSV_set(sv) (DEFSV = (sv)) +#endif + +/* Older perls (<=5.003) lack AvFILLp */ +#ifndef AvFILLp +# define AvFILLp AvFILL +#endif +#ifndef ERRSV +# define ERRSV get_sv("@",FALSE) +#endif + +/* Hint: gv_stashpvn + * This function's backport doesn't support the length parameter, but + * rather ignores it. Portability can only be ensured if the length + * parameter is used for speed reasons, but the length can always be + * correctly computed from the string argument. + */ +#ifndef gv_stashpvn +# define gv_stashpvn(str,len,create) gv_stashpv(str,create) +#endif + +/* Replace: 1 */ +#ifndef get_cv +# define get_cv perl_get_cv +#endif + +#ifndef get_sv +# define get_sv perl_get_sv +#endif + +#ifndef get_av +# define get_av perl_get_av +#endif + +#ifndef get_hv +# define get_hv perl_get_hv +#endif + +/* Replace: 0 */ +#ifndef dUNDERBAR +# define dUNDERBAR dNOOP +#endif + +#ifndef UNDERBAR +# define UNDERBAR DEFSV +#endif +#ifndef dAX +# define dAX I32 ax = MARK - PL_stack_base + 1 +#endif + +#ifndef dITEMS +# define dITEMS I32 items = SP - MARK +#endif +#ifndef dXSTARG +# define dXSTARG SV * targ = sv_newmortal() +#endif +#ifndef dAXMARK +# define dAXMARK I32 ax = POPMARK; \ + register SV ** const mark = PL_stack_base + ax++ +#endif +#ifndef XSprePUSH +# define XSprePUSH (sp = PL_stack_base + ax - 1) +#endif + +#if (PERL_BCDVERSION < 0x5005000) +# undef XSRETURN +# define XSRETURN(off) \ + STMT_START { \ + PL_stack_sp = PL_stack_base + ax + ((off) - 1); \ + return; \ + } STMT_END +#endif +#ifndef XSPROTO +# define XSPROTO(name) void name(pTHX_ CV* cv) +#endif + +#ifndef SVfARG +# define SVfARG(p) ((void*)(p)) +#endif +#ifndef PERL_ABS +# define PERL_ABS(x) ((x) < 0 ? -(x) : (x)) +#endif +#ifndef dVAR +# define dVAR dNOOP +#endif +#ifndef SVf +# define SVf "_" +#endif +#ifndef UTF8_MAXBYTES +# define UTF8_MAXBYTES UTF8_MAXLEN +#endif +#ifndef CPERLscope +# define CPERLscope(x) x +#endif +#ifndef PERL_HASH +# define PERL_HASH(hash,str,len) \ + STMT_START { \ + const char *s_PeRlHaSh = str; \ + I32 i_PeRlHaSh = len; \ + U32 hash_PeRlHaSh = 0; \ + while (i_PeRlHaSh--) \ + hash_PeRlHaSh = hash_PeRlHaSh * 33 + *s_PeRlHaSh++; \ + (hash) = hash_PeRlHaSh; \ + } STMT_END +#endif + +#ifndef PERLIO_FUNCS_DECL +# ifdef PERLIO_FUNCS_CONST +# define PERLIO_FUNCS_DECL(funcs) const PerlIO_funcs funcs +# define PERLIO_FUNCS_CAST(funcs) (PerlIO_funcs*)(funcs) +# else +# define PERLIO_FUNCS_DECL(funcs) PerlIO_funcs funcs +# define PERLIO_FUNCS_CAST(funcs) (funcs) +# endif +#endif + +/* provide these typedefs for older perls */ +#if (PERL_BCDVERSION < 0x5009003) + +# ifdef ARGSproto +typedef OP* (CPERLscope(*Perl_ppaddr_t))(ARGSproto); +# else +typedef OP* (CPERLscope(*Perl_ppaddr_t))(pTHX); +# endif + +typedef OP* (CPERLscope(*Perl_check_t)) (pTHX_ OP*); + +#endif +#ifndef isPSXSPC +# define isPSXSPC(c) (isSPACE(c) || (c) == '\v') +#endif + +#ifndef isBLANK +# define isBLANK(c) ((c) == ' ' || (c) == '\t') +#endif + +#ifdef EBCDIC +#ifndef isALNUMC +# define isALNUMC(c) isalnum(c) +#endif + +#ifndef isASCII +# define isASCII(c) isascii(c) +#endif + +#ifndef isCNTRL +# define isCNTRL(c) iscntrl(c) +#endif + +#ifndef isGRAPH +# define isGRAPH(c) isgraph(c) +#endif + +#ifndef isPRINT +# define isPRINT(c) isprint(c) +#endif + +#ifndef isPUNCT +# define isPUNCT(c) ispunct(c) +#endif + +#ifndef isXDIGIT +# define isXDIGIT(c) isxdigit(c) +#endif + +#else +# if (PERL_BCDVERSION < 0x5010000) +/* Hint: isPRINT + * The implementation in older perl versions includes all of the + * isSPACE() characters, which is wrong. The version provided by + * Devel::PPPort always overrides a present buggy version. + */ +# undef isPRINT +# endif +#ifndef isALNUMC +# define isALNUMC(c) (isALPHA(c) || isDIGIT(c)) +#endif + +#ifndef isASCII +# define isASCII(c) ((c) <= 127) +#endif + +#ifndef isCNTRL +# define isCNTRL(c) ((c) < ' ' || (c) == 127) +#endif + +#ifndef isGRAPH +# define isGRAPH(c) (isALNUM(c) || isPUNCT(c)) +#endif + +#ifndef isPRINT +# define isPRINT(c) (((c) >= 32 && (c) < 127)) +#endif + +#ifndef isPUNCT +# define isPUNCT(c) (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64) || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126)) +#endif + +#ifndef isXDIGIT +# define isXDIGIT(c) (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#endif + +#endif + +#ifndef PERL_SIGNALS_UNSAFE_FLAG + +#define PERL_SIGNALS_UNSAFE_FLAG 0x0001 + +#if (PERL_BCDVERSION < 0x5008000) +# define D_PPP_PERL_SIGNALS_INIT PERL_SIGNALS_UNSAFE_FLAG +#else +# define D_PPP_PERL_SIGNALS_INIT 0 +#endif + +#if defined(NEED_PL_signals) +static U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; +#elif defined(NEED_PL_signals_GLOBAL) +U32 DPPP_(my_PL_signals) = D_PPP_PERL_SIGNALS_INIT; +#else +extern U32 DPPP_(my_PL_signals); +#endif +#define PL_signals DPPP_(my_PL_signals) + +#endif + +/* Hint: PL_ppaddr + * Calling an op via PL_ppaddr requires passing a context argument + * for threaded builds. Since the context argument is different for + * 5.005 perls, you can use aTHXR (supplied by ppport.h), which will + * automatically be defined as the correct argument. + */ + +#if (PERL_BCDVERSION <= 0x5005005) +/* Replace: 1 */ +# define PL_ppaddr ppaddr +# define PL_no_modify no_modify +/* Replace: 0 */ +#endif + +#if (PERL_BCDVERSION <= 0x5004005) +/* Replace: 1 */ +# define PL_DBsignal DBsignal +# define PL_DBsingle DBsingle +# define PL_DBsub DBsub +# define PL_DBtrace DBtrace +# define PL_Sv Sv +# define PL_bufend bufend +# define PL_bufptr bufptr +# define PL_compiling compiling +# define PL_copline copline +# define PL_curcop curcop +# define PL_curstash curstash +# define PL_debstash debstash +# define PL_defgv defgv +# define PL_diehook diehook +# define PL_dirty dirty +# define PL_dowarn dowarn +# define PL_errgv errgv +# define PL_error_count error_count +# define PL_expect expect +# define PL_hexdigit hexdigit +# define PL_hints hints +# define PL_in_my in_my +# define PL_laststatval laststatval +# define PL_lex_state lex_state +# define PL_lex_stuff lex_stuff +# define PL_linestr linestr +# define PL_na na +# define PL_perl_destruct_level perl_destruct_level +# define PL_perldb perldb +# define PL_rsfp_filters rsfp_filters +# define PL_rsfp rsfp +# define PL_stack_base stack_base +# define PL_stack_sp stack_sp +# define PL_statcache statcache +# define PL_stdingv stdingv +# define PL_sv_arenaroot sv_arenaroot +# define PL_sv_no sv_no +# define PL_sv_undef sv_undef +# define PL_sv_yes sv_yes +# define PL_tainted tainted +# define PL_tainting tainting +# define PL_tokenbuf tokenbuf +/* Replace: 0 */ +#endif + +/* Warning: PL_parser + * For perl versions earlier than 5.9.5, this is an always + * non-NULL dummy. Also, it cannot be dereferenced. Don't + * use it if you can avoid is and unless you absolutely know + * what you're doing. + * If you always check that PL_parser is non-NULL, you can + * define DPPP_PL_parser_NO_DUMMY to avoid the creation of + * a dummy parser structure. + */ + +#if (PERL_BCDVERSION >= 0x5009005) +# ifdef DPPP_PL_parser_NO_DUMMY +# define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ + (croak("panic: PL_parser == NULL in %s:%d", \ + __FILE__, __LINE__), (yy_parser *) NULL))->var) +# else +# ifdef DPPP_PL_parser_NO_DUMMY_WARNING +# define D_PPP_parser_dummy_warning(var) +# else +# define D_PPP_parser_dummy_warning(var) \ + warn("warning: dummy PL_" #var " used in %s:%d", __FILE__, __LINE__), +# endif +# define D_PPP_my_PL_parser_var(var) ((PL_parser ? PL_parser : \ + (D_PPP_parser_dummy_warning(var) &DPPP_(dummy_PL_parser)))->var) +#if defined(NEED_PL_parser) +static yy_parser DPPP_(dummy_PL_parser); +#elif defined(NEED_PL_parser_GLOBAL) +yy_parser DPPP_(dummy_PL_parser); +#else +extern yy_parser DPPP_(dummy_PL_parser); +#endif + +# endif + +/* PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf depends on PL_parser */ +/* Warning: PL_expect, PL_copline, PL_rsfp, PL_rsfp_filters, PL_linestr, PL_bufptr, PL_bufend, PL_lex_state, PL_lex_stuff, PL_tokenbuf + * Do not use this variable unless you know exactly what you're + * doint. It is internal to the perl parser and may change or even + * be removed in the future. As of perl 5.9.5, you have to check + * for (PL_parser != NULL) for this variable to have any effect. + * An always non-NULL PL_parser dummy is provided for earlier + * perl versions. + * If PL_parser is NULL when you try to access this variable, a + * dummy is being accessed instead and a warning is issued unless + * you define DPPP_PL_parser_NO_DUMMY_WARNING. + * If DPPP_PL_parser_NO_DUMMY is defined, the code trying to access + * this variable will croak with a panic message. + */ + +# define PL_expect D_PPP_my_PL_parser_var(expect) +# define PL_copline D_PPP_my_PL_parser_var(copline) +# define PL_rsfp D_PPP_my_PL_parser_var(rsfp) +# define PL_rsfp_filters D_PPP_my_PL_parser_var(rsfp_filters) +# define PL_linestr D_PPP_my_PL_parser_var(linestr) +# define PL_bufptr D_PPP_my_PL_parser_var(bufptr) +# define PL_bufend D_PPP_my_PL_parser_var(bufend) +# define PL_lex_state D_PPP_my_PL_parser_var(lex_state) +# define PL_lex_stuff D_PPP_my_PL_parser_var(lex_stuff) +# define PL_tokenbuf D_PPP_my_PL_parser_var(tokenbuf) +# define PL_in_my D_PPP_my_PL_parser_var(in_my) +# define PL_in_my_stash D_PPP_my_PL_parser_var(in_my_stash) +# define PL_error_count D_PPP_my_PL_parser_var(error_count) + + +#else + +/* ensure that PL_parser != NULL and cannot be dereferenced */ +# define PL_parser ((void *) 1) + +#endif +#ifndef mPUSHs +# define mPUSHs(s) PUSHs(sv_2mortal(s)) +#endif + +#ifndef PUSHmortal +# define PUSHmortal PUSHs(sv_newmortal()) +#endif + +#ifndef mPUSHp +# define mPUSHp(p,l) sv_setpvn(PUSHmortal, (p), (l)) +#endif + +#ifndef mPUSHn +# define mPUSHn(n) sv_setnv(PUSHmortal, (NV)(n)) +#endif + +#ifndef mPUSHi +# define mPUSHi(i) sv_setiv(PUSHmortal, (IV)(i)) +#endif + +#ifndef mPUSHu +# define mPUSHu(u) sv_setuv(PUSHmortal, (UV)(u)) +#endif +#ifndef mXPUSHs +# define mXPUSHs(s) XPUSHs(sv_2mortal(s)) +#endif + +#ifndef XPUSHmortal +# define XPUSHmortal XPUSHs(sv_newmortal()) +#endif + +#ifndef mXPUSHp +# define mXPUSHp(p,l) STMT_START { EXTEND(sp,1); sv_setpvn(PUSHmortal, (p), (l)); } STMT_END +#endif + +#ifndef mXPUSHn +# define mXPUSHn(n) STMT_START { EXTEND(sp,1); sv_setnv(PUSHmortal, (NV)(n)); } STMT_END +#endif + +#ifndef mXPUSHi +# define mXPUSHi(i) STMT_START { EXTEND(sp,1); sv_setiv(PUSHmortal, (IV)(i)); } STMT_END +#endif + +#ifndef mXPUSHu +# define mXPUSHu(u) STMT_START { EXTEND(sp,1); sv_setuv(PUSHmortal, (UV)(u)); } STMT_END +#endif + +/* Replace: 1 */ +#ifndef call_sv +# define call_sv perl_call_sv +#endif + +#ifndef call_pv +# define call_pv perl_call_pv +#endif + +#ifndef call_argv +# define call_argv perl_call_argv +#endif + +#ifndef call_method +# define call_method perl_call_method +#endif +#ifndef eval_sv +# define eval_sv perl_eval_sv +#endif + +/* Replace: 0 */ +#ifndef PERL_LOADMOD_DENY +# define PERL_LOADMOD_DENY 0x1 +#endif + +#ifndef PERL_LOADMOD_NOIMPORT +# define PERL_LOADMOD_NOIMPORT 0x2 +#endif + +#ifndef PERL_LOADMOD_IMPORT_OPS +# define PERL_LOADMOD_IMPORT_OPS 0x4 +#endif + +#ifndef G_METHOD +# define G_METHOD 64 +# ifdef call_sv +# undef call_sv +# endif +# if (PERL_BCDVERSION < 0x5006000) +# define call_sv(sv, flags) ((flags) & G_METHOD ? perl_call_method((char *) SvPV_nolen_const(sv), \ + (flags) & ~G_METHOD) : perl_call_sv(sv, flags)) +# else +# define call_sv(sv, flags) ((flags) & G_METHOD ? Perl_call_method(aTHX_ (char *) SvPV_nolen_const(sv), \ + (flags) & ~G_METHOD) : Perl_call_sv(aTHX_ sv, flags)) +# endif +#endif + +/* Replace perl_eval_pv with eval_pv */ + +#ifndef eval_pv +#if defined(NEED_eval_pv) +static SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); +static +#else +extern SV* DPPP_(my_eval_pv)(char *p, I32 croak_on_error); +#endif + +#ifdef eval_pv +# undef eval_pv +#endif +#define eval_pv(a,b) DPPP_(my_eval_pv)(aTHX_ a,b) +#define Perl_eval_pv DPPP_(my_eval_pv) + +#if defined(NEED_eval_pv) || defined(NEED_eval_pv_GLOBAL) + +SV* +DPPP_(my_eval_pv)(char *p, I32 croak_on_error) +{ + dSP; + SV* sv = newSVpv(p, 0); + + PUSHMARK(sp); + eval_sv(sv, G_SCALAR); + SvREFCNT_dec(sv); + + SPAGAIN; + sv = POPs; + PUTBACK; + + if (croak_on_error && SvTRUE(GvSV(errgv))) + croak(SvPVx(GvSV(errgv), na)); + + return sv; +} + +#endif +#endif + +#ifndef vload_module +#if defined(NEED_vload_module) +static void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); +static +#else +extern void DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args); +#endif + +#ifdef vload_module +# undef vload_module +#endif +#define vload_module(a,b,c,d) DPPP_(my_vload_module)(aTHX_ a,b,c,d) +#define Perl_vload_module DPPP_(my_vload_module) + +#if defined(NEED_vload_module) || defined(NEED_vload_module_GLOBAL) + +void +DPPP_(my_vload_module)(U32 flags, SV *name, SV *ver, va_list *args) +{ + dTHR; + dVAR; + OP *veop, *imop; + + OP * const modname = newSVOP(OP_CONST, 0, name); + /* 5.005 has a somewhat hacky force_normal that doesn't croak on + SvREADONLY() if PL_compling is true. Current perls take care in + ck_require() to correctly turn off SvREADONLY before calling + force_normal_flags(). This seems a better fix than fudging PL_compling + */ + SvREADONLY_off(((SVOP*)modname)->op_sv); + modname->op_private |= OPpCONST_BARE; + if (ver) { + veop = newSVOP(OP_CONST, 0, ver); + } + else + veop = NULL; + if (flags & PERL_LOADMOD_NOIMPORT) { + imop = sawparens(newNULLLIST()); + } + else if (flags & PERL_LOADMOD_IMPORT_OPS) { + imop = va_arg(*args, OP*); + } + else { + SV *sv; + imop = NULL; + sv = va_arg(*args, SV*); + while (sv) { + imop = append_elem(OP_LIST, imop, newSVOP(OP_CONST, 0, sv)); + sv = va_arg(*args, SV*); + } + } + { + const line_t ocopline = PL_copline; + COP * const ocurcop = PL_curcop; + const int oexpect = PL_expect; + +#if (PERL_BCDVERSION >= 0x5004000) + utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0), + veop, modname, imop); +#else + utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(), + modname, imop); +#endif + PL_expect = oexpect; + PL_copline = ocopline; + PL_curcop = ocurcop; + } +} + +#endif +#endif + +#ifndef load_module +#if defined(NEED_load_module) +static void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); +static +#else +extern void DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...); +#endif + +#ifdef load_module +# undef load_module +#endif +#define load_module DPPP_(my_load_module) +#define Perl_load_module DPPP_(my_load_module) + +#if defined(NEED_load_module) || defined(NEED_load_module_GLOBAL) + +void +DPPP_(my_load_module)(U32 flags, SV *name, SV *ver, ...) +{ + va_list args; + va_start(args, ver); + vload_module(flags, name, ver, &args); + va_end(args); +} + +#endif +#endif +#ifndef newRV_inc +# define newRV_inc(sv) newRV(sv) /* Replace */ +#endif + +#ifndef newRV_noinc +#if defined(NEED_newRV_noinc) +static SV * DPPP_(my_newRV_noinc)(SV *sv); +static +#else +extern SV * DPPP_(my_newRV_noinc)(SV *sv); +#endif + +#ifdef newRV_noinc +# undef newRV_noinc +#endif +#define newRV_noinc(a) DPPP_(my_newRV_noinc)(aTHX_ a) +#define Perl_newRV_noinc DPPP_(my_newRV_noinc) + +#if defined(NEED_newRV_noinc) || defined(NEED_newRV_noinc_GLOBAL) +SV * +DPPP_(my_newRV_noinc)(SV *sv) +{ + SV *rv = (SV *)newRV(sv); + SvREFCNT_dec(sv); + return rv; +} +#endif +#endif + +/* Hint: newCONSTSUB + * Returns a CV* as of perl-5.7.1. This return value is not supported + * by Devel::PPPort. + */ + +/* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */ +#if (PERL_BCDVERSION < 0x5004063) && (PERL_BCDVERSION != 0x5004005) +#if defined(NEED_newCONSTSUB) +static void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); +static +#else +extern void DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv); +#endif + +#ifdef newCONSTSUB +# undef newCONSTSUB +#endif +#define newCONSTSUB(a,b,c) DPPP_(my_newCONSTSUB)(aTHX_ a,b,c) +#define Perl_newCONSTSUB DPPP_(my_newCONSTSUB) + +#if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL) + +/* This is just a trick to avoid a dependency of newCONSTSUB on PL_parser */ +/* (There's no PL_parser in perl < 5.005, so this is completely safe) */ +#define D_PPP_PL_copline PL_copline + +void +DPPP_(my_newCONSTSUB)(HV *stash, const char *name, SV *sv) +{ + U32 oldhints = PL_hints; + HV *old_cop_stash = PL_curcop->cop_stash; + HV *old_curstash = PL_curstash; + line_t oldline = PL_curcop->cop_line; + PL_curcop->cop_line = D_PPP_PL_copline; + + PL_hints &= ~HINT_BLOCK_SCOPE; + if (stash) + PL_curstash = PL_curcop->cop_stash = stash; + + newSUB( + +#if (PERL_BCDVERSION < 0x5003022) + start_subparse(), +#elif (PERL_BCDVERSION == 0x5003022) + start_subparse(0), +#else /* 5.003_23 onwards */ + start_subparse(FALSE, 0), +#endif + + newSVOP(OP_CONST, 0, newSVpv((char *) name, 0)), + newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */ + newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) + ); + + PL_hints = oldhints; + PL_curcop->cop_stash = old_cop_stash; + PL_curstash = old_curstash; + PL_curcop->cop_line = oldline; +} +#endif +#endif + +/* + * Boilerplate macros for initializing and accessing interpreter-local + * data from C. All statics in extensions should be reworked to use + * this, if you want to make the extension thread-safe. See ext/re/re.xs + * for an example of the use of these macros. + * + * Code that uses these macros is responsible for the following: + * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" + * 2. Declare a typedef named my_cxt_t that is a structure that contains + * all the data that needs to be interpreter-local. + * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. + * 4. Use the MY_CXT_INIT macro such that it is called exactly once + * (typically put in the BOOT: section). + * 5. Use the members of the my_cxt_t structure everywhere as + * MY_CXT.member. + * 6. Use the dMY_CXT macro (a declaration) in all the functions that + * access MY_CXT. + */ + +#if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ + defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) + +#ifndef START_MY_CXT + +/* This must appear in all extensions that define a my_cxt_t structure, + * right after the definition (i.e. at file scope). The non-threads + * case below uses it to declare the data as static. */ +#define START_MY_CXT + +#if (PERL_BCDVERSION < 0x5004068) +/* Fetches the SV that keeps the per-interpreter data. */ +#define dMY_CXT_SV \ + SV *my_cxt_sv = get_sv(MY_CXT_KEY, FALSE) +#else /* >= perl5.004_68 */ +#define dMY_CXT_SV \ + SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ + sizeof(MY_CXT_KEY)-1, TRUE) +#endif /* < perl5.004_68 */ + +/* This declaration should be used within all functions that use the + * interpreter-local data. */ +#define dMY_CXT \ + dMY_CXT_SV; \ + my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) + +/* Creates and zeroes the per-interpreter data. + * (We allocate my_cxtp in a Perl SV so that it will be released when + * the interpreter goes away.) */ +#define MY_CXT_INIT \ + dMY_CXT_SV; \ + /* newSV() allocates one more than needed */ \ + my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ + Zero(my_cxtp, 1, my_cxt_t); \ + sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) + +/* This macro must be used to access members of the my_cxt_t structure. + * e.g. MYCXT.some_data */ +#define MY_CXT (*my_cxtp) + +/* Judicious use of these macros can reduce the number of times dMY_CXT + * is used. Use is similar to pTHX, aTHX etc. */ +#define pMY_CXT my_cxt_t *my_cxtp +#define pMY_CXT_ pMY_CXT, +#define _pMY_CXT ,pMY_CXT +#define aMY_CXT my_cxtp +#define aMY_CXT_ aMY_CXT, +#define _aMY_CXT ,aMY_CXT + +#endif /* START_MY_CXT */ + +#ifndef MY_CXT_CLONE +/* Clones the per-interpreter data. */ +#define MY_CXT_CLONE \ + dMY_CXT_SV; \ + my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ + Copy(INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)), my_cxtp, 1, my_cxt_t);\ + sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) +#endif + +#else /* single interpreter */ + +#ifndef START_MY_CXT + +#define START_MY_CXT static my_cxt_t my_cxt; +#define dMY_CXT_SV dNOOP +#define dMY_CXT dNOOP +#define MY_CXT_INIT NOOP +#define MY_CXT my_cxt + +#define pMY_CXT void +#define pMY_CXT_ +#define _pMY_CXT +#define aMY_CXT +#define aMY_CXT_ +#define _aMY_CXT + +#endif /* START_MY_CXT */ + +#ifndef MY_CXT_CLONE +#define MY_CXT_CLONE NOOP +#endif + +#endif + +#ifndef IVdf +# if IVSIZE == LONGSIZE +# define IVdf "ld" +# define UVuf "lu" +# define UVof "lo" +# define UVxf "lx" +# define UVXf "lX" +# else +# if IVSIZE == INTSIZE +# define IVdf "d" +# define UVuf "u" +# define UVof "o" +# define UVxf "x" +# define UVXf "X" +# endif +# endif +#endif + +#ifndef NVef +# if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \ + defined(PERL_PRIfldbl) && (PERL_BCDVERSION != 0x5006000) + /* Not very likely, but let's try anyway. */ +# define NVef PERL_PRIeldbl +# define NVff PERL_PRIfldbl +# define NVgf PERL_PRIgldbl +# else +# define NVef "e" +# define NVff "f" +# define NVgf "g" +# endif +#endif + +#ifndef SvREFCNT_inc +# ifdef PERL_USE_GCC_BRACE_GROUPS +# define SvREFCNT_inc(sv) \ + ({ \ + SV * const _sv = (SV*)(sv); \ + if (_sv) \ + (SvREFCNT(_sv))++; \ + _sv; \ + }) +# else +# define SvREFCNT_inc(sv) \ + ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL) +# endif +#endif + +#ifndef SvREFCNT_inc_simple +# ifdef PERL_USE_GCC_BRACE_GROUPS +# define SvREFCNT_inc_simple(sv) \ + ({ \ + if (sv) \ + (SvREFCNT(sv))++; \ + (SV *)(sv); \ + }) +# else +# define SvREFCNT_inc_simple(sv) \ + ((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL) +# endif +#endif + +#ifndef SvREFCNT_inc_NN +# ifdef PERL_USE_GCC_BRACE_GROUPS +# define SvREFCNT_inc_NN(sv) \ + ({ \ + SV * const _sv = (SV*)(sv); \ + SvREFCNT(_sv)++; \ + _sv; \ + }) +# else +# define SvREFCNT_inc_NN(sv) \ + (PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv) +# endif +#endif + +#ifndef SvREFCNT_inc_void +# ifdef PERL_USE_GCC_BRACE_GROUPS +# define SvREFCNT_inc_void(sv) \ + ({ \ + SV * const _sv = (SV*)(sv); \ + if (_sv) \ + (void)(SvREFCNT(_sv)++); \ + }) +# else +# define SvREFCNT_inc_void(sv) \ + (void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0) +# endif +#endif +#ifndef SvREFCNT_inc_simple_void +# define SvREFCNT_inc_simple_void(sv) STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END +#endif + +#ifndef SvREFCNT_inc_simple_NN +# define SvREFCNT_inc_simple_NN(sv) (++SvREFCNT(sv), (SV*)(sv)) +#endif + +#ifndef SvREFCNT_inc_void_NN +# define SvREFCNT_inc_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) +#endif + +#ifndef SvREFCNT_inc_simple_void_NN +# define SvREFCNT_inc_simple_void_NN(sv) (void)(++SvREFCNT((SV*)(sv))) +#endif + +#ifndef newSV_type + +#if defined(NEED_newSV_type) +static SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); +static +#else +extern SV* DPPP_(my_newSV_type)(pTHX_ svtype const t); +#endif + +#ifdef newSV_type +# undef newSV_type +#endif +#define newSV_type(a) DPPP_(my_newSV_type)(aTHX_ a) +#define Perl_newSV_type DPPP_(my_newSV_type) + +#if defined(NEED_newSV_type) || defined(NEED_newSV_type_GLOBAL) + +SV* +DPPP_(my_newSV_type)(pTHX_ svtype const t) +{ + SV* const sv = newSV(0); + sv_upgrade(sv, t); + return sv; +} + +#endif + +#endif + +#if (PERL_BCDVERSION < 0x5006000) +# define D_PPP_CONSTPV_ARG(x) ((char *) (x)) +#else +# define D_PPP_CONSTPV_ARG(x) (x) +#endif +#ifndef newSVpvn +# define newSVpvn(data,len) ((data) \ + ? ((len) ? newSVpv((data), (len)) : newSVpv("", 0)) \ + : newSV(0)) +#endif +#ifndef newSVpvn_utf8 +# define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0) +#endif +#ifndef SVf_UTF8 +# define SVf_UTF8 0 +#endif + +#ifndef newSVpvn_flags + +#if defined(NEED_newSVpvn_flags) +static SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); +static +#else +extern SV * DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags); +#endif + +#ifdef newSVpvn_flags +# undef newSVpvn_flags +#endif +#define newSVpvn_flags(a,b,c) DPPP_(my_newSVpvn_flags)(aTHX_ a,b,c) +#define Perl_newSVpvn_flags DPPP_(my_newSVpvn_flags) + +#if defined(NEED_newSVpvn_flags) || defined(NEED_newSVpvn_flags_GLOBAL) + +SV * +DPPP_(my_newSVpvn_flags)(pTHX_ const char *s, STRLEN len, U32 flags) +{ + SV *sv = newSVpvn(D_PPP_CONSTPV_ARG(s), len); + SvFLAGS(sv) |= (flags & SVf_UTF8); + return (flags & SVs_TEMP) ? sv_2mortal(sv) : sv; +} + +#endif + +#endif + +/* Backwards compatibility stuff... :-( */ +#if !defined(NEED_sv_2pv_flags) && defined(NEED_sv_2pv_nolen) +# define NEED_sv_2pv_flags +#endif +#if !defined(NEED_sv_2pv_flags_GLOBAL) && defined(NEED_sv_2pv_nolen_GLOBAL) +# define NEED_sv_2pv_flags_GLOBAL +#endif + +/* Hint: sv_2pv_nolen + * Use the SvPV_nolen() or SvPV_nolen_const() macros instead of sv_2pv_nolen(). + */ +#ifndef sv_2pv_nolen +# define sv_2pv_nolen(sv) SvPV_nolen(sv) +#endif + +#ifdef SvPVbyte + +/* Hint: SvPVbyte + * Does not work in perl-5.6.1, ppport.h implements a version + * borrowed from perl-5.7.3. + */ + +#if (PERL_BCDVERSION < 0x5007000) + +#if defined(NEED_sv_2pvbyte) +static char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); +static +#else +extern char * DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp); +#endif + +#ifdef sv_2pvbyte +# undef sv_2pvbyte +#endif +#define sv_2pvbyte(a,b) DPPP_(my_sv_2pvbyte)(aTHX_ a,b) +#define Perl_sv_2pvbyte DPPP_(my_sv_2pvbyte) + +#if defined(NEED_sv_2pvbyte) || defined(NEED_sv_2pvbyte_GLOBAL) + +char * +DPPP_(my_sv_2pvbyte)(pTHX_ SV *sv, STRLEN *lp) +{ + sv_utf8_downgrade(sv,0); + return SvPV(sv,*lp); +} + +#endif + +/* Hint: sv_2pvbyte + * Use the SvPVbyte() macro instead of sv_2pvbyte(). + */ + +#undef SvPVbyte + +#define SvPVbyte(sv, lp) \ + ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ + ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pvbyte(sv, &lp)) + +#endif + +#else + +# define SvPVbyte SvPV +# define sv_2pvbyte sv_2pv + +#endif +#ifndef sv_2pvbyte_nolen +# define sv_2pvbyte_nolen(sv) sv_2pv_nolen(sv) +#endif + +/* Hint: sv_pvn + * Always use the SvPV() macro instead of sv_pvn(). + */ + +/* Hint: sv_pvn_force + * Always use the SvPV_force() macro instead of sv_pvn_force(). + */ + +/* If these are undefined, they're not handled by the core anyway */ +#ifndef SV_IMMEDIATE_UNREF +# define SV_IMMEDIATE_UNREF 0 +#endif + +#ifndef SV_GMAGIC +# define SV_GMAGIC 0 +#endif + +#ifndef SV_COW_DROP_PV +# define SV_COW_DROP_PV 0 +#endif + +#ifndef SV_UTF8_NO_ENCODING +# define SV_UTF8_NO_ENCODING 0 +#endif + +#ifndef SV_NOSTEAL +# define SV_NOSTEAL 0 +#endif + +#ifndef SV_CONST_RETURN +# define SV_CONST_RETURN 0 +#endif + +#ifndef SV_MUTABLE_RETURN +# define SV_MUTABLE_RETURN 0 +#endif + +#ifndef SV_SMAGIC +# define SV_SMAGIC 0 +#endif + +#ifndef SV_HAS_TRAILING_NUL +# define SV_HAS_TRAILING_NUL 0 +#endif + +#ifndef SV_COW_SHARED_HASH_KEYS +# define SV_COW_SHARED_HASH_KEYS 0 +#endif + +#if (PERL_BCDVERSION < 0x5007002) + +#if defined(NEED_sv_2pv_flags) +static char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); +static +#else +extern char * DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); +#endif + +#ifdef sv_2pv_flags +# undef sv_2pv_flags +#endif +#define sv_2pv_flags(a,b,c) DPPP_(my_sv_2pv_flags)(aTHX_ a,b,c) +#define Perl_sv_2pv_flags DPPP_(my_sv_2pv_flags) + +#if defined(NEED_sv_2pv_flags) || defined(NEED_sv_2pv_flags_GLOBAL) + +char * +DPPP_(my_sv_2pv_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) +{ + STRLEN n_a = (STRLEN) flags; + return sv_2pv(sv, lp ? lp : &n_a); +} + +#endif + +#if defined(NEED_sv_pvn_force_flags) +static char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); +static +#else +extern char * DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags); +#endif + +#ifdef sv_pvn_force_flags +# undef sv_pvn_force_flags +#endif +#define sv_pvn_force_flags(a,b,c) DPPP_(my_sv_pvn_force_flags)(aTHX_ a,b,c) +#define Perl_sv_pvn_force_flags DPPP_(my_sv_pvn_force_flags) + +#if defined(NEED_sv_pvn_force_flags) || defined(NEED_sv_pvn_force_flags_GLOBAL) + +char * +DPPP_(my_sv_pvn_force_flags)(pTHX_ SV *sv, STRLEN *lp, I32 flags) +{ + STRLEN n_a = (STRLEN) flags; + return sv_pvn_force(sv, lp ? lp : &n_a); +} + +#endif + +#endif + +#if (PERL_BCDVERSION < 0x5008008) || ( (PERL_BCDVERSION >= 0x5009000) && (PERL_BCDVERSION < 0x5009003) ) +# define DPPP_SVPV_NOLEN_LP_ARG &PL_na +#else +# define DPPP_SVPV_NOLEN_LP_ARG 0 +#endif +#ifndef SvPV_const +# define SvPV_const(sv, lp) SvPV_flags_const(sv, lp, SV_GMAGIC) +#endif + +#ifndef SvPV_mutable +# define SvPV_mutable(sv, lp) SvPV_flags_mutable(sv, lp, SV_GMAGIC) +#endif +#ifndef SvPV_flags +# define SvPV_flags(sv, lp, flags) \ + ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ + ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_2pv_flags(sv, &lp, flags)) +#endif +#ifndef SvPV_flags_const +# define SvPV_flags_const(sv, lp, flags) \ + ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ + ? ((lp = SvCUR(sv)), SvPVX_const(sv)) : \ + (const char*) sv_2pv_flags(sv, &lp, flags|SV_CONST_RETURN)) +#endif +#ifndef SvPV_flags_const_nolen +# define SvPV_flags_const_nolen(sv, flags) \ + ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ + ? SvPVX_const(sv) : \ + (const char*) sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags|SV_CONST_RETURN)) +#endif +#ifndef SvPV_flags_mutable +# define SvPV_flags_mutable(sv, lp, flags) \ + ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ + ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) : \ + sv_2pv_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) +#endif +#ifndef SvPV_force +# define SvPV_force(sv, lp) SvPV_force_flags(sv, lp, SV_GMAGIC) +#endif + +#ifndef SvPV_force_nolen +# define SvPV_force_nolen(sv) SvPV_force_flags_nolen(sv, SV_GMAGIC) +#endif + +#ifndef SvPV_force_mutable +# define SvPV_force_mutable(sv, lp) SvPV_force_flags_mutable(sv, lp, SV_GMAGIC) +#endif + +#ifndef SvPV_force_nomg +# define SvPV_force_nomg(sv, lp) SvPV_force_flags(sv, lp, 0) +#endif + +#ifndef SvPV_force_nomg_nolen +# define SvPV_force_nomg_nolen(sv) SvPV_force_flags_nolen(sv, 0) +#endif +#ifndef SvPV_force_flags +# define SvPV_force_flags(sv, lp, flags) \ + ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ + ? ((lp = SvCUR(sv)), SvPVX(sv)) : sv_pvn_force_flags(sv, &lp, flags)) +#endif +#ifndef SvPV_force_flags_nolen +# define SvPV_force_flags_nolen(sv, flags) \ + ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ + ? SvPVX(sv) : sv_pvn_force_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, flags)) +#endif +#ifndef SvPV_force_flags_mutable +# define SvPV_force_flags_mutable(sv, lp, flags) \ + ((SvFLAGS(sv) & (SVf_POK|SVf_THINKFIRST)) == SVf_POK \ + ? ((lp = SvCUR(sv)), SvPVX_mutable(sv)) \ + : sv_pvn_force_flags(sv, &lp, flags|SV_MUTABLE_RETURN)) +#endif +#ifndef SvPV_nolen +# define SvPV_nolen(sv) \ + ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ + ? SvPVX(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC)) +#endif +#ifndef SvPV_nolen_const +# define SvPV_nolen_const(sv) \ + ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ + ? SvPVX_const(sv) : sv_2pv_flags(sv, DPPP_SVPV_NOLEN_LP_ARG, SV_GMAGIC|SV_CONST_RETURN)) +#endif +#ifndef SvPV_nomg +# define SvPV_nomg(sv, lp) SvPV_flags(sv, lp, 0) +#endif + +#ifndef SvPV_nomg_const +# define SvPV_nomg_const(sv, lp) SvPV_flags_const(sv, lp, 0) +#endif + +#ifndef SvPV_nomg_const_nolen +# define SvPV_nomg_const_nolen(sv) SvPV_flags_const_nolen(sv, 0) +#endif +#ifndef SvPV_renew +# define SvPV_renew(sv,n) STMT_START { SvLEN_set(sv, n); \ + SvPV_set((sv), (char *) saferealloc( \ + (Malloc_t)SvPVX(sv), (MEM_SIZE)((n)))); \ + } STMT_END +#endif +#ifndef SvMAGIC_set +# define SvMAGIC_set(sv, val) \ + STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ + (((XPVMG*) SvANY(sv))->xmg_magic = (val)); } STMT_END +#endif + +#if (PERL_BCDVERSION < 0x5009003) +#ifndef SvPVX_const +# define SvPVX_const(sv) ((const char*) (0 + SvPVX(sv))) +#endif + +#ifndef SvPVX_mutable +# define SvPVX_mutable(sv) (0 + SvPVX(sv)) +#endif +#ifndef SvRV_set +# define SvRV_set(sv, val) \ + STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ + (((XRV*) SvANY(sv))->xrv_rv = (val)); } STMT_END +#endif + +#else +#ifndef SvPVX_const +# define SvPVX_const(sv) ((const char*)((sv)->sv_u.svu_pv)) +#endif + +#ifndef SvPVX_mutable +# define SvPVX_mutable(sv) ((sv)->sv_u.svu_pv) +#endif +#ifndef SvRV_set +# define SvRV_set(sv, val) \ + STMT_START { assert(SvTYPE(sv) >= SVt_RV); \ + ((sv)->sv_u.svu_rv = (val)); } STMT_END +#endif + +#endif +#ifndef SvSTASH_set +# define SvSTASH_set(sv, val) \ + STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \ + (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END +#endif + +#if (PERL_BCDVERSION < 0x5004000) +#ifndef SvUV_set +# define SvUV_set(sv, val) \ + STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ + (((XPVIV*) SvANY(sv))->xiv_iv = (IV) (val)); } STMT_END +#endif + +#else +#ifndef SvUV_set +# define SvUV_set(sv, val) \ + STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \ + (((XPVUV*) SvANY(sv))->xuv_uv = (val)); } STMT_END +#endif + +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(vnewSVpvf) +#if defined(NEED_vnewSVpvf) +static SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); +static +#else +extern SV * DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args); +#endif + +#ifdef vnewSVpvf +# undef vnewSVpvf +#endif +#define vnewSVpvf(a,b) DPPP_(my_vnewSVpvf)(aTHX_ a,b) +#define Perl_vnewSVpvf DPPP_(my_vnewSVpvf) + +#if defined(NEED_vnewSVpvf) || defined(NEED_vnewSVpvf_GLOBAL) + +SV * +DPPP_(my_vnewSVpvf)(pTHX_ const char *pat, va_list *args) +{ + register SV *sv = newSV(0); + sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); + return sv; +} + +#endif +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf) +# define sv_vcatpvf(sv, pat, args) sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf) +# define sv_vsetpvf(sv, pat, args) sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)) +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg) +#if defined(NEED_sv_catpvf_mg) +static void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); +static +#else +extern void DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...); +#endif + +#define Perl_sv_catpvf_mg DPPP_(my_sv_catpvf_mg) + +#if defined(NEED_sv_catpvf_mg) || defined(NEED_sv_catpvf_mg_GLOBAL) + +void +DPPP_(my_sv_catpvf_mg)(pTHX_ SV *sv, const char *pat, ...) +{ + va_list args; + va_start(args, pat); + sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + SvSETMAGIC(sv); + va_end(args); +} + +#endif +#endif + +#ifdef PERL_IMPLICIT_CONTEXT +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_catpvf_mg_nocontext) +#if defined(NEED_sv_catpvf_mg_nocontext) +static void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); +static +#else +extern void DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...); +#endif + +#define sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) +#define Perl_sv_catpvf_mg_nocontext DPPP_(my_sv_catpvf_mg_nocontext) + +#if defined(NEED_sv_catpvf_mg_nocontext) || defined(NEED_sv_catpvf_mg_nocontext_GLOBAL) + +void +DPPP_(my_sv_catpvf_mg_nocontext)(SV *sv, const char *pat, ...) +{ + dTHX; + va_list args; + va_start(args, pat); + sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + SvSETMAGIC(sv); + va_end(args); +} + +#endif +#endif +#endif + +/* sv_catpvf_mg depends on sv_catpvf_mg_nocontext */ +#ifndef sv_catpvf_mg +# ifdef PERL_IMPLICIT_CONTEXT +# define sv_catpvf_mg Perl_sv_catpvf_mg_nocontext +# else +# define sv_catpvf_mg Perl_sv_catpvf_mg +# endif +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vcatpvf_mg) +# define sv_vcatpvf_mg(sv, pat, args) \ + STMT_START { \ + sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ + SvSETMAGIC(sv); \ + } STMT_END +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg) +#if defined(NEED_sv_setpvf_mg) +static void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); +static +#else +extern void DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...); +#endif + +#define Perl_sv_setpvf_mg DPPP_(my_sv_setpvf_mg) + +#if defined(NEED_sv_setpvf_mg) || defined(NEED_sv_setpvf_mg_GLOBAL) + +void +DPPP_(my_sv_setpvf_mg)(pTHX_ SV *sv, const char *pat, ...) +{ + va_list args; + va_start(args, pat); + sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + SvSETMAGIC(sv); + va_end(args); +} + +#endif +#endif + +#ifdef PERL_IMPLICIT_CONTEXT +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_setpvf_mg_nocontext) +#if defined(NEED_sv_setpvf_mg_nocontext) +static void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); +static +#else +extern void DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...); +#endif + +#define sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) +#define Perl_sv_setpvf_mg_nocontext DPPP_(my_sv_setpvf_mg_nocontext) + +#if defined(NEED_sv_setpvf_mg_nocontext) || defined(NEED_sv_setpvf_mg_nocontext_GLOBAL) + +void +DPPP_(my_sv_setpvf_mg_nocontext)(SV *sv, const char *pat, ...) +{ + dTHX; + va_list args; + va_start(args, pat); + sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*)); + SvSETMAGIC(sv); + va_end(args); +} + +#endif +#endif +#endif + +/* sv_setpvf_mg depends on sv_setpvf_mg_nocontext */ +#ifndef sv_setpvf_mg +# ifdef PERL_IMPLICIT_CONTEXT +# define sv_setpvf_mg Perl_sv_setpvf_mg_nocontext +# else +# define sv_setpvf_mg Perl_sv_setpvf_mg +# endif +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(sv_vsetpvf_mg) +# define sv_vsetpvf_mg(sv, pat, args) \ + STMT_START { \ + sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*)); \ + SvSETMAGIC(sv); \ + } STMT_END +#endif + +#ifndef newSVpvn_share + +#if defined(NEED_newSVpvn_share) +static SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); +static +#else +extern SV * DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash); +#endif + +#ifdef newSVpvn_share +# undef newSVpvn_share +#endif +#define newSVpvn_share(a,b,c) DPPP_(my_newSVpvn_share)(aTHX_ a,b,c) +#define Perl_newSVpvn_share DPPP_(my_newSVpvn_share) + +#if defined(NEED_newSVpvn_share) || defined(NEED_newSVpvn_share_GLOBAL) + +SV * +DPPP_(my_newSVpvn_share)(pTHX_ const char *src, I32 len, U32 hash) +{ + SV *sv; + if (len < 0) + len = -len; + if (!hash) + PERL_HASH(hash, (char*) src, len); + sv = newSVpvn((char *) src, len); + sv_upgrade(sv, SVt_PVIV); + SvIVX(sv) = hash; + SvREADONLY_on(sv); + SvPOK_on(sv); + return sv; +} + +#endif + +#endif +#ifndef SvSHARED_HASH +# define SvSHARED_HASH(sv) (0 + SvUVX(sv)) +#endif +#ifndef HvNAME_get +# define HvNAME_get(hv) HvNAME(hv) +#endif +#ifndef HvNAMELEN_get +# define HvNAMELEN_get(hv) (HvNAME_get(hv) ? (I32)strlen(HvNAME_get(hv)) : 0) +#endif +#ifndef GvSVn +# define GvSVn(gv) GvSV(gv) +#endif + +#ifndef isGV_with_GP +# define isGV_with_GP(gv) isGV(gv) +#endif +#ifndef WARN_ALL +# define WARN_ALL 0 +#endif + +#ifndef WARN_CLOSURE +# define WARN_CLOSURE 1 +#endif + +#ifndef WARN_DEPRECATED +# define WARN_DEPRECATED 2 +#endif + +#ifndef WARN_EXITING +# define WARN_EXITING 3 +#endif + +#ifndef WARN_GLOB +# define WARN_GLOB 4 +#endif + +#ifndef WARN_IO +# define WARN_IO 5 +#endif + +#ifndef WARN_CLOSED +# define WARN_CLOSED 6 +#endif + +#ifndef WARN_EXEC +# define WARN_EXEC 7 +#endif + +#ifndef WARN_LAYER +# define WARN_LAYER 8 +#endif + +#ifndef WARN_NEWLINE +# define WARN_NEWLINE 9 +#endif + +#ifndef WARN_PIPE +# define WARN_PIPE 10 +#endif + +#ifndef WARN_UNOPENED +# define WARN_UNOPENED 11 +#endif + +#ifndef WARN_MISC +# define WARN_MISC 12 +#endif + +#ifndef WARN_NUMERIC +# define WARN_NUMERIC 13 +#endif + +#ifndef WARN_ONCE +# define WARN_ONCE 14 +#endif + +#ifndef WARN_OVERFLOW +# define WARN_OVERFLOW 15 +#endif + +#ifndef WARN_PACK +# define WARN_PACK 16 +#endif + +#ifndef WARN_PORTABLE +# define WARN_PORTABLE 17 +#endif + +#ifndef WARN_RECURSION +# define WARN_RECURSION 18 +#endif + +#ifndef WARN_REDEFINE +# define WARN_REDEFINE 19 +#endif + +#ifndef WARN_REGEXP +# define WARN_REGEXP 20 +#endif + +#ifndef WARN_SEVERE +# define WARN_SEVERE 21 +#endif + +#ifndef WARN_DEBUGGING +# define WARN_DEBUGGING 22 +#endif + +#ifndef WARN_INPLACE +# define WARN_INPLACE 23 +#endif + +#ifndef WARN_INTERNAL +# define WARN_INTERNAL 24 +#endif + +#ifndef WARN_MALLOC +# define WARN_MALLOC 25 +#endif + +#ifndef WARN_SIGNAL +# define WARN_SIGNAL 26 +#endif + +#ifndef WARN_SUBSTR +# define WARN_SUBSTR 27 +#endif + +#ifndef WARN_SYNTAX +# define WARN_SYNTAX 28 +#endif + +#ifndef WARN_AMBIGUOUS +# define WARN_AMBIGUOUS 29 +#endif + +#ifndef WARN_BAREWORD +# define WARN_BAREWORD 30 +#endif + +#ifndef WARN_DIGIT +# define WARN_DIGIT 31 +#endif + +#ifndef WARN_PARENTHESIS +# define WARN_PARENTHESIS 32 +#endif + +#ifndef WARN_PRECEDENCE +# define WARN_PRECEDENCE 33 +#endif + +#ifndef WARN_PRINTF +# define WARN_PRINTF 34 +#endif + +#ifndef WARN_PROTOTYPE +# define WARN_PROTOTYPE 35 +#endif + +#ifndef WARN_QW +# define WARN_QW 36 +#endif + +#ifndef WARN_RESERVED +# define WARN_RESERVED 37 +#endif + +#ifndef WARN_SEMICOLON +# define WARN_SEMICOLON 38 +#endif + +#ifndef WARN_TAINT +# define WARN_TAINT 39 +#endif + +#ifndef WARN_THREADS +# define WARN_THREADS 40 +#endif + +#ifndef WARN_UNINITIALIZED +# define WARN_UNINITIALIZED 41 +#endif + +#ifndef WARN_UNPACK +# define WARN_UNPACK 42 +#endif + +#ifndef WARN_UNTIE +# define WARN_UNTIE 43 +#endif + +#ifndef WARN_UTF8 +# define WARN_UTF8 44 +#endif + +#ifndef WARN_VOID +# define WARN_VOID 45 +#endif + +#ifndef WARN_ASSERTIONS +# define WARN_ASSERTIONS 46 +#endif +#ifndef packWARN +# define packWARN(a) (a) +#endif + +#ifndef ckWARN +# ifdef G_WARN_ON +# define ckWARN(a) (PL_dowarn & G_WARN_ON) +# else +# define ckWARN(a) PL_dowarn +# endif +#endif + +#if (PERL_BCDVERSION >= 0x5004000) && !defined(warner) +#if defined(NEED_warner) +static void DPPP_(my_warner)(U32 err, const char *pat, ...); +static +#else +extern void DPPP_(my_warner)(U32 err, const char *pat, ...); +#endif + +#define Perl_warner DPPP_(my_warner) + +#if defined(NEED_warner) || defined(NEED_warner_GLOBAL) + +void +DPPP_(my_warner)(U32 err, const char *pat, ...) +{ + SV *sv; + va_list args; + + PERL_UNUSED_ARG(err); + + va_start(args, pat); + sv = vnewSVpvf(pat, &args); + va_end(args); + sv_2mortal(sv); + warn("%s", SvPV_nolen(sv)); +} + +#define warner Perl_warner + +#define Perl_warner_nocontext Perl_warner + +#endif +#endif + +/* concatenating with "" ensures that only literal strings are accepted as argument + * note that STR_WITH_LEN() can't be used as argument to macros or functions that + * under some configurations might be macros + */ +#ifndef STR_WITH_LEN +# define STR_WITH_LEN(s) (s ""), (sizeof(s)-1) +#endif +#ifndef newSVpvs +# define newSVpvs(str) newSVpvn(str "", sizeof(str) - 1) +#endif + +#ifndef newSVpvs_flags +# define newSVpvs_flags(str, flags) newSVpvn_flags(str "", sizeof(str) - 1, flags) +#endif + +#ifndef sv_catpvs +# define sv_catpvs(sv, str) sv_catpvn(sv, str "", sizeof(str) - 1) +#endif + +#ifndef sv_setpvs +# define sv_setpvs(sv, str) sv_setpvn(sv, str "", sizeof(str) - 1) +#endif + +#ifndef hv_fetchs +# define hv_fetchs(hv, key, lval) hv_fetch(hv, key "", sizeof(key) - 1, lval) +#endif + +#ifndef hv_stores +# define hv_stores(hv, key, val) hv_store(hv, key "", sizeof(key) - 1, val, 0) +#endif +#ifndef gv_fetchpvn_flags +# define gv_fetchpvn_flags(name, len, flags, svt) gv_fetchpv(name, flags, svt) +#endif + +#ifndef gv_fetchpvs +# define gv_fetchpvs(name, flags, svt) gv_fetchpvn_flags(name "", sizeof(name) - 1, flags, svt) +#endif + +#ifndef gv_stashpvs +# define gv_stashpvs(name, flags) gv_stashpvn(name "", sizeof(name) - 1, flags) +#endif +#ifndef SvGETMAGIC +# define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END +#endif +#ifndef PERL_MAGIC_sv +# define PERL_MAGIC_sv '\0' +#endif + +#ifndef PERL_MAGIC_overload +# define PERL_MAGIC_overload 'A' +#endif + +#ifndef PERL_MAGIC_overload_elem +# define PERL_MAGIC_overload_elem 'a' +#endif + +#ifndef PERL_MAGIC_overload_table +# define PERL_MAGIC_overload_table 'c' +#endif + +#ifndef PERL_MAGIC_bm +# define PERL_MAGIC_bm 'B' +#endif + +#ifndef PERL_MAGIC_regdata +# define PERL_MAGIC_regdata 'D' +#endif + +#ifndef PERL_MAGIC_regdatum +# define PERL_MAGIC_regdatum 'd' +#endif + +#ifndef PERL_MAGIC_env +# define PERL_MAGIC_env 'E' +#endif + +#ifndef PERL_MAGIC_envelem +# define PERL_MAGIC_envelem 'e' +#endif + +#ifndef PERL_MAGIC_fm +# define PERL_MAGIC_fm 'f' +#endif + +#ifndef PERL_MAGIC_regex_global +# define PERL_MAGIC_regex_global 'g' +#endif + +#ifndef PERL_MAGIC_isa +# define PERL_MAGIC_isa 'I' +#endif + +#ifndef PERL_MAGIC_isaelem +# define PERL_MAGIC_isaelem 'i' +#endif + +#ifndef PERL_MAGIC_nkeys +# define PERL_MAGIC_nkeys 'k' +#endif + +#ifndef PERL_MAGIC_dbfile +# define PERL_MAGIC_dbfile 'L' +#endif + +#ifndef PERL_MAGIC_dbline +# define PERL_MAGIC_dbline 'l' +#endif + +#ifndef PERL_MAGIC_mutex +# define PERL_MAGIC_mutex 'm' +#endif + +#ifndef PERL_MAGIC_shared +# define PERL_MAGIC_shared 'N' +#endif + +#ifndef PERL_MAGIC_shared_scalar +# define PERL_MAGIC_shared_scalar 'n' +#endif + +#ifndef PERL_MAGIC_collxfrm +# define PERL_MAGIC_collxfrm 'o' +#endif + +#ifndef PERL_MAGIC_tied +# define PERL_MAGIC_tied 'P' +#endif + +#ifndef PERL_MAGIC_tiedelem +# define PERL_MAGIC_tiedelem 'p' +#endif + +#ifndef PERL_MAGIC_tiedscalar +# define PERL_MAGIC_tiedscalar 'q' +#endif + +#ifndef PERL_MAGIC_qr +# define PERL_MAGIC_qr 'r' +#endif + +#ifndef PERL_MAGIC_sig +# define PERL_MAGIC_sig 'S' +#endif + +#ifndef PERL_MAGIC_sigelem +# define PERL_MAGIC_sigelem 's' +#endif + +#ifndef PERL_MAGIC_taint +# define PERL_MAGIC_taint 't' +#endif + +#ifndef PERL_MAGIC_uvar +# define PERL_MAGIC_uvar 'U' +#endif + +#ifndef PERL_MAGIC_uvar_elem +# define PERL_MAGIC_uvar_elem 'u' +#endif + +#ifndef PERL_MAGIC_vstring +# define PERL_MAGIC_vstring 'V' +#endif + +#ifndef PERL_MAGIC_vec +# define PERL_MAGIC_vec 'v' +#endif + +#ifndef PERL_MAGIC_utf8 +# define PERL_MAGIC_utf8 'w' +#endif + +#ifndef PERL_MAGIC_substr +# define PERL_MAGIC_substr 'x' +#endif + +#ifndef PERL_MAGIC_defelem +# define PERL_MAGIC_defelem 'y' +#endif + +#ifndef PERL_MAGIC_glob +# define PERL_MAGIC_glob '*' +#endif + +#ifndef PERL_MAGIC_arylen +# define PERL_MAGIC_arylen '#' +#endif + +#ifndef PERL_MAGIC_pos +# define PERL_MAGIC_pos '.' +#endif + +#ifndef PERL_MAGIC_backref +# define PERL_MAGIC_backref '<' +#endif + +#ifndef PERL_MAGIC_ext +# define PERL_MAGIC_ext '~' +#endif + +/* That's the best we can do... */ +#ifndef sv_catpvn_nomg +# define sv_catpvn_nomg sv_catpvn +#endif + +#ifndef sv_catsv_nomg +# define sv_catsv_nomg sv_catsv +#endif + +#ifndef sv_setsv_nomg +# define sv_setsv_nomg sv_setsv +#endif + +#ifndef sv_pvn_nomg +# define sv_pvn_nomg sv_pvn +#endif + +#ifndef SvIV_nomg +# define SvIV_nomg SvIV +#endif + +#ifndef SvUV_nomg +# define SvUV_nomg SvUV +#endif + +#ifndef sv_catpv_mg +# define sv_catpv_mg(sv, ptr) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_catpv(TeMpSv,ptr); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_catpvn_mg +# define sv_catpvn_mg(sv, ptr, len) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_catpvn(TeMpSv,ptr,len); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_catsv_mg +# define sv_catsv_mg(dsv, ssv) \ + STMT_START { \ + SV *TeMpSv = dsv; \ + sv_catsv(TeMpSv,ssv); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_setiv_mg +# define sv_setiv_mg(sv, i) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_setiv(TeMpSv,i); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_setnv_mg +# define sv_setnv_mg(sv, num) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_setnv(TeMpSv,num); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_setpv_mg +# define sv_setpv_mg(sv, ptr) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_setpv(TeMpSv,ptr); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_setpvn_mg +# define sv_setpvn_mg(sv, ptr, len) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_setpvn(TeMpSv,ptr,len); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_setsv_mg +# define sv_setsv_mg(dsv, ssv) \ + STMT_START { \ + SV *TeMpSv = dsv; \ + sv_setsv(TeMpSv,ssv); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_setuv_mg +# define sv_setuv_mg(sv, i) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_setuv(TeMpSv,i); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif + +#ifndef sv_usepvn_mg +# define sv_usepvn_mg(sv, ptr, len) \ + STMT_START { \ + SV *TeMpSv = sv; \ + sv_usepvn(TeMpSv,ptr,len); \ + SvSETMAGIC(TeMpSv); \ + } STMT_END +#endif +#ifndef SvVSTRING_mg +# define SvVSTRING_mg(sv) (SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_vstring) : NULL) +#endif + +/* Hint: sv_magic_portable + * This is a compatibility function that is only available with + * Devel::PPPort. It is NOT in the perl core. + * Its purpose is to mimic the 5.8.0 behaviour of sv_magic() when + * it is being passed a name pointer with namlen == 0. In that + * case, perl 5.8.0 and later store the pointer, not a copy of it. + * The compatibility can be provided back to perl 5.004. With + * earlier versions, the code will not compile. + */ + +#if (PERL_BCDVERSION < 0x5004000) + + /* code that uses sv_magic_portable will not compile */ + +#elif (PERL_BCDVERSION < 0x5008000) + +# define sv_magic_portable(sv, obj, how, name, namlen) \ + STMT_START { \ + SV *SvMp_sv = (sv); \ + char *SvMp_name = (char *) (name); \ + I32 SvMp_namlen = (namlen); \ + if (SvMp_name && SvMp_namlen == 0) \ + { \ + MAGIC *mg; \ + sv_magic(SvMp_sv, obj, how, 0, 0); \ + mg = SvMAGIC(SvMp_sv); \ + mg->mg_len = -42; /* XXX: this is the tricky part */ \ + mg->mg_ptr = SvMp_name; \ + } \ + else \ + { \ + sv_magic(SvMp_sv, obj, how, SvMp_name, SvMp_namlen); \ + } \ + } STMT_END + +#else + +# define sv_magic_portable(a, b, c, d, e) sv_magic(a, b, c, d, e) + +#endif + +#ifdef USE_ITHREADS +#ifndef CopFILE +# define CopFILE(c) ((c)->cop_file) +#endif + +#ifndef CopFILEGV +# define CopFILEGV(c) (CopFILE(c) ? gv_fetchfile(CopFILE(c)) : Nullgv) +#endif + +#ifndef CopFILE_set +# define CopFILE_set(c,pv) ((c)->cop_file = savepv(pv)) +#endif + +#ifndef CopFILESV +# define CopFILESV(c) (CopFILE(c) ? GvSV(gv_fetchfile(CopFILE(c))) : Nullsv) +#endif + +#ifndef CopFILEAV +# define CopFILEAV(c) (CopFILE(c) ? GvAV(gv_fetchfile(CopFILE(c))) : Nullav) +#endif + +#ifndef CopSTASHPV +# define CopSTASHPV(c) ((c)->cop_stashpv) +#endif + +#ifndef CopSTASHPV_set +# define CopSTASHPV_set(c,pv) ((c)->cop_stashpv = ((pv) ? savepv(pv) : Nullch)) +#endif + +#ifndef CopSTASH +# define CopSTASH(c) (CopSTASHPV(c) ? gv_stashpv(CopSTASHPV(c),GV_ADD) : Nullhv) +#endif + +#ifndef CopSTASH_set +# define CopSTASH_set(c,hv) CopSTASHPV_set(c, (hv) ? HvNAME(hv) : Nullch) +#endif + +#ifndef CopSTASH_eq +# define CopSTASH_eq(c,hv) ((hv) && (CopSTASHPV(c) == HvNAME(hv) \ + || (CopSTASHPV(c) && HvNAME(hv) \ + && strEQ(CopSTASHPV(c), HvNAME(hv))))) +#endif + +#else +#ifndef CopFILEGV +# define CopFILEGV(c) ((c)->cop_filegv) +#endif + +#ifndef CopFILEGV_set +# define CopFILEGV_set(c,gv) ((c)->cop_filegv = (GV*)SvREFCNT_inc(gv)) +#endif + +#ifndef CopFILE_set +# define CopFILE_set(c,pv) CopFILEGV_set((c), gv_fetchfile(pv)) +#endif + +#ifndef CopFILESV +# define CopFILESV(c) (CopFILEGV(c) ? GvSV(CopFILEGV(c)) : Nullsv) +#endif + +#ifndef CopFILEAV +# define CopFILEAV(c) (CopFILEGV(c) ? GvAV(CopFILEGV(c)) : Nullav) +#endif + +#ifndef CopFILE +# define CopFILE(c) (CopFILESV(c) ? SvPVX(CopFILESV(c)) : Nullch) +#endif + +#ifndef CopSTASH +# define CopSTASH(c) ((c)->cop_stash) +#endif + +#ifndef CopSTASH_set +# define CopSTASH_set(c,hv) ((c)->cop_stash = (hv)) +#endif + +#ifndef CopSTASHPV +# define CopSTASHPV(c) (CopSTASH(c) ? HvNAME(CopSTASH(c)) : Nullch) +#endif + +#ifndef CopSTASHPV_set +# define CopSTASHPV_set(c,pv) CopSTASH_set((c), gv_stashpv(pv,GV_ADD)) +#endif + +#ifndef CopSTASH_eq +# define CopSTASH_eq(c,hv) (CopSTASH(c) == (hv)) +#endif + +#endif /* USE_ITHREADS */ +#ifndef IN_PERL_COMPILETIME +# define IN_PERL_COMPILETIME (PL_curcop == &PL_compiling) +#endif + +#ifndef IN_LOCALE_RUNTIME +# define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE) +#endif + +#ifndef IN_LOCALE_COMPILETIME +# define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) +#endif + +#ifndef IN_LOCALE +# define IN_LOCALE (IN_PERL_COMPILETIME ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) +#endif +#ifndef IS_NUMBER_IN_UV +# define IS_NUMBER_IN_UV 0x01 +#endif + +#ifndef IS_NUMBER_GREATER_THAN_UV_MAX +# define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 +#endif + +#ifndef IS_NUMBER_NOT_INT +# define IS_NUMBER_NOT_INT 0x04 +#endif + +#ifndef IS_NUMBER_NEG +# define IS_NUMBER_NEG 0x08 +#endif + +#ifndef IS_NUMBER_INFINITY +# define IS_NUMBER_INFINITY 0x10 +#endif + +#ifndef IS_NUMBER_NAN +# define IS_NUMBER_NAN 0x20 +#endif +#ifndef GROK_NUMERIC_RADIX +# define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(sp, send) +#endif +#ifndef PERL_SCAN_GREATER_THAN_UV_MAX +# define PERL_SCAN_GREATER_THAN_UV_MAX 0x02 +#endif + +#ifndef PERL_SCAN_SILENT_ILLDIGIT +# define PERL_SCAN_SILENT_ILLDIGIT 0x04 +#endif + +#ifndef PERL_SCAN_ALLOW_UNDERSCORES +# define PERL_SCAN_ALLOW_UNDERSCORES 0x01 +#endif + +#ifndef PERL_SCAN_DISALLOW_PREFIX +# define PERL_SCAN_DISALLOW_PREFIX 0x02 +#endif + +#ifndef grok_numeric_radix +#if defined(NEED_grok_numeric_radix) +static bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); +static +#else +extern bool DPPP_(my_grok_numeric_radix)(pTHX_ const char ** sp, const char * send); +#endif + +#ifdef grok_numeric_radix +# undef grok_numeric_radix +#endif +#define grok_numeric_radix(a,b) DPPP_(my_grok_numeric_radix)(aTHX_ a,b) +#define Perl_grok_numeric_radix DPPP_(my_grok_numeric_radix) + +#if defined(NEED_grok_numeric_radix) || defined(NEED_grok_numeric_radix_GLOBAL) +bool +DPPP_(my_grok_numeric_radix)(pTHX_ const char **sp, const char *send) +{ +#ifdef USE_LOCALE_NUMERIC +#ifdef PL_numeric_radix_sv + if (PL_numeric_radix_sv && IN_LOCALE) { + STRLEN len; + char* radix = SvPV(PL_numeric_radix_sv, len); + if (*sp + len <= send && memEQ(*sp, radix, len)) { + *sp += len; + return TRUE; + } + } +#else + /* older perls don't have PL_numeric_radix_sv so the radix + * must manually be requested from locale.h + */ +#include + dTHR; /* needed for older threaded perls */ + struct lconv *lc = localeconv(); + char *radix = lc->decimal_point; + if (radix && IN_LOCALE) { + STRLEN len = strlen(radix); + if (*sp + len <= send && memEQ(*sp, radix, len)) { + *sp += len; + return TRUE; + } + } +#endif +#endif /* USE_LOCALE_NUMERIC */ + /* always try "." if numeric radix didn't match because + * we may have data from different locales mixed */ + if (*sp < send && **sp == '.') { + ++*sp; + return TRUE; + } + return FALSE; +} +#endif +#endif + +#ifndef grok_number +#if defined(NEED_grok_number) +static int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); +static +#else +extern int DPPP_(my_grok_number)(pTHX_ const char * pv, STRLEN len, UV * valuep); +#endif + +#ifdef grok_number +# undef grok_number +#endif +#define grok_number(a,b,c) DPPP_(my_grok_number)(aTHX_ a,b,c) +#define Perl_grok_number DPPP_(my_grok_number) + +#if defined(NEED_grok_number) || defined(NEED_grok_number_GLOBAL) +int +DPPP_(my_grok_number)(pTHX_ const char *pv, STRLEN len, UV *valuep) +{ + const char *s = pv; + const char *send = pv + len; + const UV max_div_10 = UV_MAX / 10; + const char max_mod_10 = UV_MAX % 10; + int numtype = 0; + int sawinf = 0; + int sawnan = 0; + + while (s < send && isSPACE(*s)) + s++; + if (s == send) { + return 0; + } else if (*s == '-') { + s++; + numtype = IS_NUMBER_NEG; + } + else if (*s == '+') + s++; + + if (s == send) + return 0; + + /* next must be digit or the radix separator or beginning of infinity */ + if (isDIGIT(*s)) { + /* UVs are at least 32 bits, so the first 9 decimal digits cannot + overflow. */ + UV value = *s - '0'; + /* This construction seems to be more optimiser friendly. + (without it gcc does the isDIGIT test and the *s - '0' separately) + With it gcc on arm is managing 6 instructions (6 cycles) per digit. + In theory the optimiser could deduce how far to unroll the loop + before checking for overflow. */ + if (++s < send) { + int digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + digit = *s - '0'; + if (digit >= 0 && digit <= 9) { + value = value * 10 + digit; + if (++s < send) { + /* Now got 9 digits, so need to check + each time for overflow. */ + digit = *s - '0'; + while (digit >= 0 && digit <= 9 + && (value < max_div_10 + || (value == max_div_10 + && digit <= max_mod_10))) { + value = value * 10 + digit; + if (++s < send) + digit = *s - '0'; + else + break; + } + if (digit >= 0 && digit <= 9 + && (s < send)) { + /* value overflowed. + skip the remaining digits, don't + worry about setting *valuep. */ + do { + s++; + } while (s < send && isDIGIT(*s)); + numtype |= + IS_NUMBER_GREATER_THAN_UV_MAX; + goto skip_value; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + numtype |= IS_NUMBER_IN_UV; + if (valuep) + *valuep = value; + + skip_value: + if (GROK_NUMERIC_RADIX(&s, send)) { + numtype |= IS_NUMBER_NOT_INT; + while (s < send && isDIGIT(*s)) /* optional digits after the radix */ + s++; + } + } + else if (GROK_NUMERIC_RADIX(&s, send)) { + numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */ + /* no digits before the radix means we need digits after it */ + if (s < send && isDIGIT(*s)) { + do { + s++; + } while (s < send && isDIGIT(*s)); + if (valuep) { + /* integer approximation is valid - it's 0. */ + *valuep = 0; + } + } + else + return 0; + } else if (*s == 'I' || *s == 'i') { + s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; + s++; if (s == send || (*s != 'F' && *s != 'f')) return 0; + s++; if (s < send && (*s == 'I' || *s == 'i')) { + s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; + s++; if (s == send || (*s != 'I' && *s != 'i')) return 0; + s++; if (s == send || (*s != 'T' && *s != 't')) return 0; + s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0; + s++; + } + sawinf = 1; + } else if (*s == 'N' || *s == 'n') { + /* XXX TODO: There are signaling NaNs and quiet NaNs. */ + s++; if (s == send || (*s != 'A' && *s != 'a')) return 0; + s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; + s++; + sawnan = 1; + } else + return 0; + + if (sawinf) { + numtype &= IS_NUMBER_NEG; /* Keep track of sign */ + numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT; + } else if (sawnan) { + numtype &= IS_NUMBER_NEG; /* Keep track of sign */ + numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT; + } else if (s < send) { + /* we can have an optional exponent part */ + if (*s == 'e' || *s == 'E') { + /* The only flag we keep is sign. Blow away any "it's UV" */ + numtype &= IS_NUMBER_NEG; + numtype |= IS_NUMBER_NOT_INT; + s++; + if (s < send && (*s == '-' || *s == '+')) + s++; + if (s < send && isDIGIT(*s)) { + do { + s++; + } while (s < send && isDIGIT(*s)); + } + else + return 0; + } + } + while (s < send && isSPACE(*s)) + s++; + if (s >= send) + return numtype; + if (len == 10 && memEQ(pv, "0 but true", 10)) { + if (valuep) + *valuep = 0; + return IS_NUMBER_IN_UV; + } + return 0; +} +#endif +#endif + +/* + * The grok_* routines have been modified to use warn() instead of + * Perl_warner(). Also, 'hexdigit' was the former name of PL_hexdigit, + * which is why the stack variable has been renamed to 'xdigit'. + */ + +#ifndef grok_bin +#if defined(NEED_grok_bin) +static UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); +static +#else +extern UV DPPP_(my_grok_bin)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); +#endif + +#ifdef grok_bin +# undef grok_bin +#endif +#define grok_bin(a,b,c,d) DPPP_(my_grok_bin)(aTHX_ a,b,c,d) +#define Perl_grok_bin DPPP_(my_grok_bin) + +#if defined(NEED_grok_bin) || defined(NEED_grok_bin_GLOBAL) +UV +DPPP_(my_grok_bin)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) +{ + const char *s = start; + STRLEN len = *len_p; + UV value = 0; + NV value_nv = 0; + + const UV max_div_2 = UV_MAX / 2; + bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; + bool overflowed = FALSE; + + if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { + /* strip off leading b or 0b. + for compatibility silently suffer "b" and "0b" as valid binary + numbers. */ + if (len >= 1) { + if (s[0] == 'b') { + s++; + len--; + } + else if (len >= 2 && s[0] == '0' && s[1] == 'b') { + s+=2; + len-=2; + } + } + } + + for (; len-- && *s; s++) { + char bit = *s; + if (bit == '0' || bit == '1') { + /* Write it in this wonky order with a goto to attempt to get the + compiler to make the common case integer-only loop pretty tight. + With gcc seems to be much straighter code than old scan_bin. */ + redo: + if (!overflowed) { + if (value <= max_div_2) { + value = (value << 1) | (bit - '0'); + continue; + } + /* Bah. We're just overflowed. */ + warn("Integer overflow in binary number"); + overflowed = TRUE; + value_nv = (NV) value; + } + value_nv *= 2.0; + /* If an NV has not enough bits in its mantissa to + * represent a UV this summing of small low-order numbers + * is a waste of time (because the NV cannot preserve + * the low-order bits anyway): we could just remember when + * did we overflow and in the end just multiply value_nv by the + * right amount. */ + value_nv += (NV)(bit - '0'); + continue; + } + if (bit == '_' && len && allow_underscores && (bit = s[1]) + && (bit == '0' || bit == '1')) + { + --len; + ++s; + goto redo; + } + if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) + warn("Illegal binary digit '%c' ignored", *s); + break; + } + + if ( ( overflowed && value_nv > 4294967295.0) +#if UVSIZE > 4 + || (!overflowed && value > 0xffffffff ) +#endif + ) { + warn("Binary number > 0b11111111111111111111111111111111 non-portable"); + } + *len_p = s - start; + if (!overflowed) { + *flags = 0; + return value; + } + *flags = PERL_SCAN_GREATER_THAN_UV_MAX; + if (result) + *result = value_nv; + return UV_MAX; +} +#endif +#endif + +#ifndef grok_hex +#if defined(NEED_grok_hex) +static UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); +static +#else +extern UV DPPP_(my_grok_hex)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); +#endif + +#ifdef grok_hex +# undef grok_hex +#endif +#define grok_hex(a,b,c,d) DPPP_(my_grok_hex)(aTHX_ a,b,c,d) +#define Perl_grok_hex DPPP_(my_grok_hex) + +#if defined(NEED_grok_hex) || defined(NEED_grok_hex_GLOBAL) +UV +DPPP_(my_grok_hex)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) +{ + const char *s = start; + STRLEN len = *len_p; + UV value = 0; + NV value_nv = 0; + + const UV max_div_16 = UV_MAX / 16; + bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; + bool overflowed = FALSE; + const char *xdigit; + + if (!(*flags & PERL_SCAN_DISALLOW_PREFIX)) { + /* strip off leading x or 0x. + for compatibility silently suffer "x" and "0x" as valid hex numbers. + */ + if (len >= 1) { + if (s[0] == 'x') { + s++; + len--; + } + else if (len >= 2 && s[0] == '0' && s[1] == 'x') { + s+=2; + len-=2; + } + } + } + + for (; len-- && *s; s++) { + xdigit = strchr((char *) PL_hexdigit, *s); + if (xdigit) { + /* Write it in this wonky order with a goto to attempt to get the + compiler to make the common case integer-only loop pretty tight. + With gcc seems to be much straighter code than old scan_hex. */ + redo: + if (!overflowed) { + if (value <= max_div_16) { + value = (value << 4) | ((xdigit - PL_hexdigit) & 15); + continue; + } + warn("Integer overflow in hexadecimal number"); + overflowed = TRUE; + value_nv = (NV) value; + } + value_nv *= 16.0; + /* If an NV has not enough bits in its mantissa to + * represent a UV this summing of small low-order numbers + * is a waste of time (because the NV cannot preserve + * the low-order bits anyway): we could just remember when + * did we overflow and in the end just multiply value_nv by the + * right amount of 16-tuples. */ + value_nv += (NV)((xdigit - PL_hexdigit) & 15); + continue; + } + if (*s == '_' && len && allow_underscores && s[1] + && (xdigit = strchr((char *) PL_hexdigit, s[1]))) + { + --len; + ++s; + goto redo; + } + if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) + warn("Illegal hexadecimal digit '%c' ignored", *s); + break; + } + + if ( ( overflowed && value_nv > 4294967295.0) +#if UVSIZE > 4 + || (!overflowed && value > 0xffffffff ) +#endif + ) { + warn("Hexadecimal number > 0xffffffff non-portable"); + } + *len_p = s - start; + if (!overflowed) { + *flags = 0; + return value; + } + *flags = PERL_SCAN_GREATER_THAN_UV_MAX; + if (result) + *result = value_nv; + return UV_MAX; +} +#endif +#endif + +#ifndef grok_oct +#if defined(NEED_grok_oct) +static UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); +static +#else +extern UV DPPP_(my_grok_oct)(pTHX_ const char * start, STRLEN * len_p, I32 * flags, NV * result); +#endif + +#ifdef grok_oct +# undef grok_oct +#endif +#define grok_oct(a,b,c,d) DPPP_(my_grok_oct)(aTHX_ a,b,c,d) +#define Perl_grok_oct DPPP_(my_grok_oct) + +#if defined(NEED_grok_oct) || defined(NEED_grok_oct_GLOBAL) +UV +DPPP_(my_grok_oct)(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result) +{ + const char *s = start; + STRLEN len = *len_p; + UV value = 0; + NV value_nv = 0; + + const UV max_div_8 = UV_MAX / 8; + bool allow_underscores = *flags & PERL_SCAN_ALLOW_UNDERSCORES; + bool overflowed = FALSE; + + for (; len-- && *s; s++) { + /* gcc 2.95 optimiser not smart enough to figure that this subtraction + out front allows slicker code. */ + int digit = *s - '0'; + if (digit >= 0 && digit <= 7) { + /* Write it in this wonky order with a goto to attempt to get the + compiler to make the common case integer-only loop pretty tight. + */ + redo: + if (!overflowed) { + if (value <= max_div_8) { + value = (value << 3) | digit; + continue; + } + /* Bah. We're just overflowed. */ + warn("Integer overflow in octal number"); + overflowed = TRUE; + value_nv = (NV) value; + } + value_nv *= 8.0; + /* If an NV has not enough bits in its mantissa to + * represent a UV this summing of small low-order numbers + * is a waste of time (because the NV cannot preserve + * the low-order bits anyway): we could just remember when + * did we overflow and in the end just multiply value_nv by the + * right amount of 8-tuples. */ + value_nv += (NV)digit; + continue; + } + if (digit == ('_' - '0') && len && allow_underscores + && (digit = s[1] - '0') && (digit >= 0 && digit <= 7)) + { + --len; + ++s; + goto redo; + } + /* Allow \octal to work the DWIM way (that is, stop scanning + * as soon as non-octal characters are seen, complain only iff + * someone seems to want to use the digits eight and nine). */ + if (digit == 8 || digit == 9) { + if (!(*flags & PERL_SCAN_SILENT_ILLDIGIT)) + warn("Illegal octal digit '%c' ignored", *s); + } + break; + } + + if ( ( overflowed && value_nv > 4294967295.0) +#if UVSIZE > 4 + || (!overflowed && value > 0xffffffff ) +#endif + ) { + warn("Octal number > 037777777777 non-portable"); + } + *len_p = s - start; + if (!overflowed) { + *flags = 0; + return value; + } + *flags = PERL_SCAN_GREATER_THAN_UV_MAX; + if (result) + *result = value_nv; + return UV_MAX; +} +#endif +#endif + +#if !defined(my_snprintf) +#if defined(NEED_my_snprintf) +static int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); +static +#else +extern int DPPP_(my_my_snprintf)(char * buffer, const Size_t len, const char * format, ...); +#endif + +#define my_snprintf DPPP_(my_my_snprintf) +#define Perl_my_snprintf DPPP_(my_my_snprintf) + +#if defined(NEED_my_snprintf) || defined(NEED_my_snprintf_GLOBAL) + +int +DPPP_(my_my_snprintf)(char *buffer, const Size_t len, const char *format, ...) +{ + dTHX; + int retval; + va_list ap; + va_start(ap, format); +#ifdef HAS_VSNPRINTF + retval = vsnprintf(buffer, len, format, ap); +#else + retval = vsprintf(buffer, format, ap); +#endif + va_end(ap); + if (retval < 0 || (len > 0 && (Size_t)retval >= len)) + Perl_croak(aTHX_ "panic: my_snprintf buffer overflow"); + return retval; +} + +#endif +#endif + +#if !defined(my_sprintf) +#if defined(NEED_my_sprintf) +static int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); +static +#else +extern int DPPP_(my_my_sprintf)(char * buffer, const char * pat, ...); +#endif + +#define my_sprintf DPPP_(my_my_sprintf) +#define Perl_my_sprintf DPPP_(my_my_sprintf) + +#if defined(NEED_my_sprintf) || defined(NEED_my_sprintf_GLOBAL) + +int +DPPP_(my_my_sprintf)(char *buffer, const char* pat, ...) +{ + va_list args; + va_start(args, pat); + vsprintf(buffer, pat, args); + va_end(args); + return strlen(buffer); +} + +#endif +#endif + +#ifdef NO_XSLOCKS +# ifdef dJMPENV +# define dXCPT dJMPENV; int rEtV = 0 +# define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0) +# define XCPT_TRY_END JMPENV_POP; +# define XCPT_CATCH if (rEtV != 0) +# define XCPT_RETHROW JMPENV_JUMP(rEtV) +# else +# define dXCPT Sigjmp_buf oldTOP; int rEtV = 0 +# define XCPT_TRY_START Copy(top_env, oldTOP, 1, Sigjmp_buf); rEtV = Sigsetjmp(top_env, 1); if (rEtV == 0) +# define XCPT_TRY_END Copy(oldTOP, top_env, 1, Sigjmp_buf); +# define XCPT_CATCH if (rEtV != 0) +# define XCPT_RETHROW Siglongjmp(top_env, rEtV) +# endif +#endif + +#if !defined(my_strlcat) +#if defined(NEED_my_strlcat) +static Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); +static +#else +extern Size_t DPPP_(my_my_strlcat)(char * dst, const char * src, Size_t size); +#endif + +#define my_strlcat DPPP_(my_my_strlcat) +#define Perl_my_strlcat DPPP_(my_my_strlcat) + +#if defined(NEED_my_strlcat) || defined(NEED_my_strlcat_GLOBAL) + +Size_t +DPPP_(my_my_strlcat)(char *dst, const char *src, Size_t size) +{ + Size_t used, length, copy; + + used = strlen(dst); + length = strlen(src); + if (size > 0 && used < size - 1) { + copy = (length >= size - used) ? size - used - 1 : length; + memcpy(dst + used, src, copy); + dst[used + copy] = '\0'; + } + return used + length; +} +#endif +#endif + +#if !defined(my_strlcpy) +#if defined(NEED_my_strlcpy) +static Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); +static +#else +extern Size_t DPPP_(my_my_strlcpy)(char * dst, const char * src, Size_t size); +#endif + +#define my_strlcpy DPPP_(my_my_strlcpy) +#define Perl_my_strlcpy DPPP_(my_my_strlcpy) + +#if defined(NEED_my_strlcpy) || defined(NEED_my_strlcpy_GLOBAL) + +Size_t +DPPP_(my_my_strlcpy)(char *dst, const char *src, Size_t size) +{ + Size_t length, copy; + + length = strlen(src); + if (size > 0) { + copy = (length >= size) ? size - 1 : length; + memcpy(dst, src, copy); + dst[copy] = '\0'; + } + return length; +} + +#endif +#endif +#ifndef PERL_PV_ESCAPE_QUOTE +# define PERL_PV_ESCAPE_QUOTE 0x0001 +#endif + +#ifndef PERL_PV_PRETTY_QUOTE +# define PERL_PV_PRETTY_QUOTE PERL_PV_ESCAPE_QUOTE +#endif + +#ifndef PERL_PV_PRETTY_ELLIPSES +# define PERL_PV_PRETTY_ELLIPSES 0x0002 +#endif + +#ifndef PERL_PV_PRETTY_LTGT +# define PERL_PV_PRETTY_LTGT 0x0004 +#endif + +#ifndef PERL_PV_ESCAPE_FIRSTCHAR +# define PERL_PV_ESCAPE_FIRSTCHAR 0x0008 +#endif + +#ifndef PERL_PV_ESCAPE_UNI +# define PERL_PV_ESCAPE_UNI 0x0100 +#endif + +#ifndef PERL_PV_ESCAPE_UNI_DETECT +# define PERL_PV_ESCAPE_UNI_DETECT 0x0200 +#endif + +#ifndef PERL_PV_ESCAPE_ALL +# define PERL_PV_ESCAPE_ALL 0x1000 +#endif + +#ifndef PERL_PV_ESCAPE_NOBACKSLASH +# define PERL_PV_ESCAPE_NOBACKSLASH 0x2000 +#endif + +#ifndef PERL_PV_ESCAPE_NOCLEAR +# define PERL_PV_ESCAPE_NOCLEAR 0x4000 +#endif + +#ifndef PERL_PV_ESCAPE_RE +# define PERL_PV_ESCAPE_RE 0x8000 +#endif + +#ifndef PERL_PV_PRETTY_NOCLEAR +# define PERL_PV_PRETTY_NOCLEAR PERL_PV_ESCAPE_NOCLEAR +#endif +#ifndef PERL_PV_PRETTY_DUMP +# define PERL_PV_PRETTY_DUMP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE +#endif + +#ifndef PERL_PV_PRETTY_REGPROP +# define PERL_PV_PRETTY_REGPROP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE +#endif + +/* Hint: pv_escape + * Note that unicode functionality is only backported to + * those perl versions that support it. For older perl + * versions, the implementation will fall back to bytes. + */ + +#ifndef pv_escape +#if defined(NEED_pv_escape) +static char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); +static +#else +extern char * DPPP_(my_pv_escape)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, STRLEN * const escaped, const U32 flags); +#endif + +#ifdef pv_escape +# undef pv_escape +#endif +#define pv_escape(a,b,c,d,e,f) DPPP_(my_pv_escape)(aTHX_ a,b,c,d,e,f) +#define Perl_pv_escape DPPP_(my_pv_escape) + +#if defined(NEED_pv_escape) || defined(NEED_pv_escape_GLOBAL) + +char * +DPPP_(my_pv_escape)(pTHX_ SV *dsv, char const * const str, + const STRLEN count, const STRLEN max, + STRLEN * const escaped, const U32 flags) +{ + const char esc = flags & PERL_PV_ESCAPE_RE ? '%' : '\\'; + const char dq = flags & PERL_PV_ESCAPE_QUOTE ? '"' : esc; + char octbuf[32] = "%123456789ABCDF"; + STRLEN wrote = 0; + STRLEN chsize = 0; + STRLEN readsize = 1; +#if defined(is_utf8_string) && defined(utf8_to_uvchr) + bool isuni = flags & PERL_PV_ESCAPE_UNI ? 1 : 0; +#endif + const char *pv = str; + const char * const end = pv + count; + octbuf[0] = esc; + + if (!(flags & PERL_PV_ESCAPE_NOCLEAR)) + sv_setpvs(dsv, ""); + +#if defined(is_utf8_string) && defined(utf8_to_uvchr) + if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count)) + isuni = 1; +#endif + + for (; pv < end && (!max || wrote < max) ; pv += readsize) { + const UV u = +#if defined(is_utf8_string) && defined(utf8_to_uvchr) + isuni ? utf8_to_uvchr((U8*)pv, &readsize) : +#endif + (U8)*pv; + const U8 c = (U8)u & 0xFF; + + if (u > 255 || (flags & PERL_PV_ESCAPE_ALL)) { + if (flags & PERL_PV_ESCAPE_FIRSTCHAR) + chsize = my_snprintf(octbuf, sizeof octbuf, + "%"UVxf, u); + else + chsize = my_snprintf(octbuf, sizeof octbuf, + "%cx{%"UVxf"}", esc, u); + } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) { + chsize = 1; + } else { + if (c == dq || c == esc || !isPRINT(c)) { + chsize = 2; + switch (c) { + case '\\' : /* fallthrough */ + case '%' : if (c == esc) + octbuf[1] = esc; + else + chsize = 1; + break; + case '\v' : octbuf[1] = 'v'; break; + case '\t' : octbuf[1] = 't'; break; + case '\r' : octbuf[1] = 'r'; break; + case '\n' : octbuf[1] = 'n'; break; + case '\f' : octbuf[1] = 'f'; break; + case '"' : if (dq == '"') + octbuf[1] = '"'; + else + chsize = 1; + break; + default: chsize = my_snprintf(octbuf, sizeof octbuf, + pv < end && isDIGIT((U8)*(pv+readsize)) + ? "%c%03o" : "%c%o", esc, c); + } + } else { + chsize = 1; + } + } + if (max && wrote + chsize > max) { + break; + } else if (chsize > 1) { + sv_catpvn(dsv, octbuf, chsize); + wrote += chsize; + } else { + char tmp[2]; + my_snprintf(tmp, sizeof tmp, "%c", c); + sv_catpvn(dsv, tmp, 1); + wrote++; + } + if (flags & PERL_PV_ESCAPE_FIRSTCHAR) + break; + } + if (escaped != NULL) + *escaped= pv - str; + return SvPVX(dsv); +} + +#endif +#endif + +#ifndef pv_pretty +#if defined(NEED_pv_pretty) +static char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); +static +#else +extern char * DPPP_(my_pv_pretty)(pTHX_ SV * dsv, char const * const str, const STRLEN count, const STRLEN max, char const * const start_color, char const * const end_color, const U32 flags); +#endif + +#ifdef pv_pretty +# undef pv_pretty +#endif +#define pv_pretty(a,b,c,d,e,f,g) DPPP_(my_pv_pretty)(aTHX_ a,b,c,d,e,f,g) +#define Perl_pv_pretty DPPP_(my_pv_pretty) + +#if defined(NEED_pv_pretty) || defined(NEED_pv_pretty_GLOBAL) + +char * +DPPP_(my_pv_pretty)(pTHX_ SV *dsv, char const * const str, const STRLEN count, + const STRLEN max, char const * const start_color, char const * const end_color, + const U32 flags) +{ + const U8 dq = (flags & PERL_PV_PRETTY_QUOTE) ? '"' : '%'; + STRLEN escaped; + + if (!(flags & PERL_PV_PRETTY_NOCLEAR)) + sv_setpvs(dsv, ""); + + if (dq == '"') + sv_catpvs(dsv, "\""); + else if (flags & PERL_PV_PRETTY_LTGT) + sv_catpvs(dsv, "<"); + + if (start_color != NULL) + sv_catpv(dsv, D_PPP_CONSTPV_ARG(start_color)); + + pv_escape(dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR); + + if (end_color != NULL) + sv_catpv(dsv, D_PPP_CONSTPV_ARG(end_color)); + + if (dq == '"') + sv_catpvs(dsv, "\""); + else if (flags & PERL_PV_PRETTY_LTGT) + sv_catpvs(dsv, ">"); + + if ((flags & PERL_PV_PRETTY_ELLIPSES) && escaped < count) + sv_catpvs(dsv, "..."); + + return SvPVX(dsv); +} + +#endif +#endif + +#ifndef pv_display +#if defined(NEED_pv_display) +static char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); +static +#else +extern char * DPPP_(my_pv_display)(pTHX_ SV * dsv, const char * pv, STRLEN cur, STRLEN len, STRLEN pvlim); +#endif + +#ifdef pv_display +# undef pv_display +#endif +#define pv_display(a,b,c,d,e) DPPP_(my_pv_display)(aTHX_ a,b,c,d,e) +#define Perl_pv_display DPPP_(my_pv_display) + +#if defined(NEED_pv_display) || defined(NEED_pv_display_GLOBAL) + +char * +DPPP_(my_pv_display)(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim) +{ + pv_pretty(dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP); + if (len > cur && pv[cur] == '\0') + sv_catpvs(dsv, "\\0"); + return SvPVX(dsv); +} + +#endif +#endif + +#endif /* _P_P_PORTABILITY_H_ */ + +/* End of File ppport.h */ diff --git a/t/data/binary-test.file b/t/data/binary-test.file new file mode 100644 index 0000000..119cecc Binary files /dev/null and b/t/data/binary-test.file differ diff --git a/t/data/cert_paypal.crt.pem b/t/data/cert_paypal.crt.pem new file mode 100644 index 0000000..8a47b3a --- /dev/null +++ b/t/data/cert_paypal.crt.pem @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +MIIGSzCCBTOgAwIBAgIQLjOHT2/i1B7T//819qTJGDANBgkqhkiG9w0BAQUFADCB +ujELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug +YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE0MDIGA1UEAxMr +VmVyaVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBDQTAeFw0x +MTAzMjMwMDAwMDBaFw0xMzA0MDEyMzU5NTlaMIIBDzETMBEGCysGAQQBgjc8AgED +EwJVUzEZMBcGCysGAQQBgjc8AgECEwhEZWxhd2FyZTEdMBsGA1UEDxMUUHJpdmF0 +ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzMwMTQyNjcxCzAJBgNVBAYTAlVTMRMw +EQYDVQQRFAo5NTEzMS0yMDIxMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQH +FAhTYW4gSm9zZTEWMBQGA1UECRQNMjIxMSBOIDFzdCBTdDEVMBMGA1UEChQMUGF5 +UGFsLCBJbmMuMRowGAYDVQQLFBFQYXlQYWwgUHJvZHVjdGlvbjEXMBUGA1UEAxQO +d3d3LnBheXBhbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCd +szetUP2zRUbaN1vHuX9WV2mMq0IIVQ5NX2kpFCwBYc4vwW/CHiMr+dgs8lDduCfH +5uxhyRxKtJa6GElIIiP8qFB5HFWf1uUgoDPC1he4HaxUkowCnVEqjEowOy9R9Cr4 +yyrmqmMEDccVsx4d3dOY2JF1FrLDHT7qH/GCBnyYw+nZJ88ci6HqnVJiNM+NX/D/ +d7Y3r3V1bp7y1DaJwK/z/uMwNCC+lcM59w+nwAvLutgCW6WitFHMB+HpSsOSJlIZ +ydpj0Ox+javRR1FIdhRUFMK4wwcbD8PvULi1gM+sYsJIzP0mHDlhWRIDImG1zmy2 +x7ZLp0HA5WayjI5aSn9fAgMBAAGjggHzMIIB7zAJBgNVHRMEAjAAMB0GA1UdDgQW +BBQxqt0MVbSO4lWE5aB52xc8nEq5RTALBgNVHQ8EBAMCBaAwQgYDVR0fBDswOTA3 +oDWgM4YxaHR0cDovL0VWU2VjdXJlLWNybC52ZXJpc2lnbi5jb20vRVZTZWN1cmUy +MDA2LmNybDBEBgNVHSAEPTA7MDkGC2CGSAGG+EUBBxcGMCowKAYIKwYBBQUHAgEW +HGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUH +AwEGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFPyKULqeuSVae1WFT5UAY4/pWGtDMHwG +CCsGAQUFBwEBBHAwbjAtBggrBgEFBQcwAYYhaHR0cDovL0VWU2VjdXJlLW9jc3Au +dmVyaXNpZ24uY29tMD0GCCsGAQUFBzAChjFodHRwOi8vRVZTZWN1cmUtYWlhLnZl +cmlzaWduLmNvbS9FVlNlY3VyZTIwMDYuY2VyMG4GCCsGAQUFBwEMBGIwYKFeoFww +WjBYMFYWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFEtruSiWBgy70FI4mymsSweL +IQUYMCYWJGh0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28xLmdpZjANBgkq +hkiG9w0BAQUFAAOCAQEAisdjAvky8ehg4A0J3ED6+yR0BU77cqtrLUKqzaLcLL/B +wuj8gErM8LLaWMGM/FJcoNEUgSkMI3/Qr1YXtXFvdqo3urqMhi/SsuUJU85Gnoxr +Vr0rWoBqOOnmcsVEgtYeusK0sQbxq5JlE1eq9xqYZrKuOuA/8JS1V7Ss1iFrtA5i +pwotaEK3k5NEJOQh9/Zm+fy1vZfUyyX+iVSlmyFHC4bzu2DlzZln3UzjBJeXoEfe +YjQyLpdUhUhuPslV1qs+Bmi6O+e6htDHvD05wUaRzk6vsPcEQ3EqsPbdpLgejb5p +9YDR12XLZeQjO1uiunCsJkDIf9/5Mqpu57pw8v1QNA== +-----END CERTIFICATE----- diff --git a/t/data/cert_paypal.crt.pem_dump b/t/data/cert_paypal.crt.pem_dump new file mode 100644 index 0000000..95e4914 --- /dev/null +++ b/t/data/cert_paypal.crt.pem_dump @@ -0,0 +1,276 @@ + +# exported via command: perl examples/x509_cert_details.pl -dump -pem t/data/cert_paypal.crt.pem > t/data/cert_paypal.crt.pem_dump +# hashref dumped via Data::Dump +{ + cdp => ["http://EVSecure-crl.verisign.com/EVSecure2006.crl"], + certificate_type => 49, + digest_sha1 => { + pubkey => pack("H*","31aadd0c55b48ee25584e5a079db173c9c4ab945"), + x509 => pack("H*","d8465221467a0d153df09f2eaf6d439002139a68"), + }, + extensions => { + count => 9, + entries => [ + { + critical => 0, + data => "CA:FALSE", + ln => "X509v3 Basic Constraints", + nid => 87, + oid => "2.5.29.19", + sn => "basicConstraints", + }, + { + critical => 0, + data => "31:AA:DD:0C:55:B4:8E:E2:55:84:E5:A0:79:DB:17:3C:9C:4A:B9:45", + ln => "X509v3 Subject Key Identifier", + nid => 82, + oid => "2.5.29.14", + sn => "subjectKeyIdentifier", + }, + { + critical => 0, + data => "Digital Signature, Key Encipherment", + ln => "X509v3 Key Usage", + nid => 83, + oid => "2.5.29.15", + sn => "keyUsage", + }, + { + critical => 0, + data => "\nFull Name:\n URI:http://EVSecure-crl.verisign.com/EVSecure2006.crl\n", + ln => "X509v3 CRL Distribution Points", + nid => 103, + oid => "2.5.29.31", + sn => "crlDistributionPoints", + }, + { + critical => 0, + data => "Policy: 2.16.840.1.113733.1.7.23.6\n CPS: https://www.verisign.com/rpa\n", + ln => "X509v3 Certificate Policies", + nid => 89, + oid => "2.5.29.32", + sn => "certificatePolicies", + }, + { + critical => 0, + data => "TLS Web Server Authentication, TLS Web Client Authentication", + ln => "X509v3 Extended Key Usage", + nid => 126, + oid => "2.5.29.37", + sn => "extendedKeyUsage", + }, + { + critical => 0, + data => "keyid:FC:8A:50:BA:9E:B9:25:5A:7B:55:85:4F:95:00:63:8F:E9:58:6B:43\n", + ln => "X509v3 Authority Key Identifier", + nid => 90, + oid => "2.5.29.35", + sn => "authorityKeyIdentifier", + }, + { + critical => 0, + data => "OCSP - URI:http://EVSecure-ocsp.verisign.com\nCA Issuers - URI:http://EVSecure-aia.verisign.com/EVSecure2006.cer\n", + ln => "Authority Information Access", + nid => 177, + oid => "1.3.6.1.5.5.7.1.1", + sn => "authorityInfoAccess", + }, + { + critical => 0, + data => undef, + ln => undef, + nid => undef, + oid => "1.3.6.1.5.5.7.1.12", + sn => undef, + }, + ], + }, + extkeyusage => { + ln => [ + "TLS Web Server Authentication", + "TLS Web Client Authentication", + ], + nid => [129, 130], + oid => ["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"], + sn => ["serverAuth", "clientAuth"], + }, + fingerprint => { + md5 => "BF:47:CE:CA:D8:61:EF:A7:7D:14:88:AD:4A:73:CB:5B", + sha1 => "D8:46:52:21:46:7A:0D:15:3D:F0:9F:2E:AF:6D:43:90:02:13:9A:68", + }, + hash => { + issuer => { dec => 1853825729, hex => "6E7F22C1" }, + issuer_and_serial => { dec => 62796555, hex => "3BE330B" }, + subject => { dec => 493395107, hex => "1D689CA3" }, + }, + issuer => { + count => 5, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "VeriSign, Inc.", + data_utf8_decoded => "VeriSign, Inc.", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "VeriSign Trust Network", + data_utf8_decoded => "VeriSign Trust Network", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "Terms of use at https://www.verisign.com/rpa (c)06", + data_utf8_decoded => "Terms of use at https://www.verisign.com/rpa (c)06", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "VeriSign Class 3 Extended Validation SSL CA", + data_utf8_decoded => "VeriSign Class 3 Extended Validation SSL CA", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)06/CN=VeriSign Class 3 Extended Validation SSL CA", + print_rfc2253 => "CN=VeriSign Class 3 Extended Validation SSL CA,OU=Terms of use at https://www.verisign.com/rpa (c)06,OU=VeriSign Trust Network,O=VeriSign\\, Inc.,C=US", + print_rfc2253_utf8 => "CN=VeriSign Class 3 Extended Validation SSL CA,OU=Terms of use at https://www.verisign.com/rpa (c)06,OU=VeriSign Trust Network,O=VeriSign\\, Inc.,C=US", + print_rfc2253_utf8_decoded => "CN=VeriSign Class 3 Extended Validation SSL CA,OU=Terms of use at https://www.verisign.com/rpa (c)06,OU=VeriSign Trust Network,O=VeriSign\\, Inc.,C=US", + }, + keyusage => ["digitalSignature", "keyEncipherment"], + not_after => "2013-04-01T23:59:59Z", + not_before => "2011-03-23T00:00:00Z", + ns_cert_type => [], + pubkey_alg => "rsaEncryption", + pubkey_bits => 2048, + pubkey_id => 6, + pubkey_size => 256, + serial => { + dec => "61412039364839793000795191320888264984", + hex => "2E33874F6FE2D41ED3FFFF35F6A4C918", + long => -1, + }, + signature_alg => "sha1WithRSAEncryption", + subject => { + altnames => [], + count => 12, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => undef, + nid => undef, + oid => "1.3.6.1.4.1.311.60.2.1.3", + sn => undef, + }, + { + data => "Delaware", + data_utf8_decoded => "Delaware", + ln => undef, + nid => undef, + oid => "1.3.6.1.4.1.311.60.2.1.2", + sn => undef, + }, + { + data => "Private Organization", + data_utf8_decoded => "Private Organization", + ln => "businessCategory", + nid => 860, + oid => "2.5.4.15", + sn => "businessCategory", + }, + { + data => 3014267, + data_utf8_decoded => 3014267, + ln => "serialNumber", + nid => 105, + oid => "2.5.4.5", + sn => "serialNumber", + }, + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "95131-2021", + data_utf8_decoded => "95131-2021", + ln => "postalCode", + nid => 661, + oid => "2.5.4.17", + sn => "postalCode", + }, + { + data => "California", + data_utf8_decoded => "California", + ln => "stateOrProvinceName", + nid => 16, + oid => "2.5.4.8", + sn => "ST", + }, + { + data => "San Jose", + data_utf8_decoded => "San Jose", + ln => "localityName", + nid => 15, + oid => "2.5.4.7", + sn => "L", + }, + { + data => "2211 N 1st St", + data_utf8_decoded => "2211 N 1st St", + ln => "streetAddress", + nid => 660, + oid => "2.5.4.9", + sn => "street", + }, + { + data => "PayPal, Inc.", + data_utf8_decoded => "PayPal, Inc.", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "PayPal Production", + data_utf8_decoded => "PayPal Production", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "www.paypal.com", + data_utf8_decoded => "www.paypal.com", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/businessCategory=Private Organization/serialNumber=3014267/C=US/postalCode=95131-2021/ST=California/L=San Jose/street=2211 N 1st St/O=PayPal, Inc./OU=PayPal Production/CN=www.paypal.com", + print_rfc2253 => "CN=www.paypal.com,OU=PayPal Production,O=PayPal\\, Inc.,street=2211 N 1st St,L=San Jose,ST=California,postalCode=95131-2021,C=US,serialNumber=3014267,businessCategory=Private Organization,1.3.6.1.4.1.311.60.2.1.2=#130844656C6177617265,1.3.6.1.4.1.311.60.2.1.3=#13025553", + print_rfc2253_utf8 => "CN=www.paypal.com,OU=PayPal Production,O=PayPal\\, Inc.,street=2211 N 1st St,L=San Jose,ST=California,postalCode=95131-2021,C=US,serialNumber=3014267,businessCategory=Private Organization,1.3.6.1.4.1.311.60.2.1.2=#130844656C6177617265,1.3.6.1.4.1.311.60.2.1.3=#13025553", + print_rfc2253_utf8_decoded => "CN=www.paypal.com,OU=PayPal Production,O=PayPal\\, Inc.,street=2211 N 1st St,L=San Jose,ST=California,postalCode=95131-2021,C=US,serialNumber=3014267,businessCategory=Private Organization,1.3.6.1.4.1.311.60.2.1.2=#130844656C6177617265,1.3.6.1.4.1.311.60.2.1.3=#13025553", + }, + version => 2, +} diff --git a/t/data/chain_leaf.crt.pem b/t/data/chain_leaf.crt.pem new file mode 100644 index 0000000..2b382b7 --- /dev/null +++ b/t/data/chain_leaf.crt.pem @@ -0,0 +1,45 @@ +-----BEGIN CERTIFICATE----- +MIICmjCCAYICAQEwDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UEAwwMSW50ZXJtZWRp +YXRlMB4XDTE5MDQxNzE1MTY1M1oXDTI5MDQxNDE1MTY1M1owDzENMAsGA1UEAwwE +TGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOa0eYS3XsiXadYF +53ZTfaNhbbkpCWnFddFQ/c3Z7QToJ6DkTiqDNTpHodvrG+CFDVuO0RJONQDf4jH6 +6B6ityFYWc4RkAPqfat0k7NZpj5dVWp9uDgmEWABmf0KE9WqzYDbtTljlS1POHI9 +UFCdF3/T0UbGtdKSzzo/STJf8vLOTf5YJQZHImvZeQbCgXtBN8hdLtfdU5FQYbaK +cGyDvW6mBg1ZxYgJx+hE9NNeAsAWp2rAXGZIatQ98KNmwY5VH6cBX4ggasQucUUI +Bg5ih7fvWP2k0FyaiIsme9nWLsbuNg3s3tMahuRO1rE0Z0Vj/5JBUmT6J27ZBKGZ +Rn7C2x8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAgleJwB7rE7w+B4jlRqP72kkR +XL7MZSV2vr+CTS4t+iLlbHweApiEJmQ3szY69d/gtdznSacp8CHOGihRazRsudn2 +G6QHbjXNBs16KnEEnHiIbk0YrnAa0xxrKvxOHPX+lfvYEcN2QqVtiFF0IsTqck8I +vMYYe5zf4RDd2S1q31l67LoFSmFhrAqPbDITrx8tMhyAEW6zNxNkCaM/+8Bu94E3 +Ec7QDmpbE4Qz80qzmCmpv7NBnvrn0uYO1IkPrq2XetbhWHoliYImeS2OojdnPVbx +sP1q5i9FYnnvFA8xl4TORjqtIajX6bXVkWZBXkbtDGKLnxzJ+vPagxwEzOphmA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICIjCCAYugAwIBAgIDEjRWMA0GCSqGSIb3DQEBBQUAMCsxCzAJBgNVBAYTAlVT +MQ4wDAYDVQQKEwVEZW1vMTEMMAoGA1UEAxMDQ0ExMCAXDTEyMDEwMTAwMDAwMFoY +DzIxMTExMjMxMjM1OTU5WjArMQswCQYDVQQGEwJVUzEOMAwGA1UEChMFRGVtbzEx +DDAKBgNVBAMTA0NBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy1ygNguH +72n0l+1uy9HEM6t2LWJEmC0w4tAuXk9H1FseQMV28eBQXdyg3wK+yli6l6c9k9Aj +HAZ/6TXTVmOxtTgkXbvHlwcE3pTiHJSvZWGQMORCPNkjjiVBiLBdGQ3qFKyV+NA5 +K4XnVy0jkeS/BHx7KO7m+DOLVow8FO1CstUCAwEAAaNSMFAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyBzakgqpSAg6dnYVOATxNNkV0CAwCwYDVR0PBAQDAgEG +MBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOBgQBG1QBfo1kZRN50 +/a3ZoQufIj0FJLMS/WkUnW0RLqEewyhEK9u86eoglcz5SxdD4T+VN9+MxoZ2J83P +b21Y4FUDqnkdoGAPdoxX+7iLQcxVoMK72n72QSSzvfnjsr9+pazLp1P6ZK9epbZf +s2WM0ty3a+sYmXANG8wGazAyRDMi0Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICTzCCAbigAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMQswCQYDVQQGEwJVUzEO +MAwGA1UEChMFRGVtbzExDDAKBgNVBAMTA0NBMTAeFw0xOTA0MTcxNTEzMjFaFw0y +OTA0MTQxNTEzMjFaMBcxFTATBgNVBAMMDEludGVybWVkaWF0ZTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMjKRTFhhQvcFd8kkjjevKPjZRFmhd5zVWAB +tqrAEdhWwxpI3Jg1j49sbBWL2WKFhASPzYgPTE1CTQ6eH46ySmgLt8qzdPp8+kiC +RDU0h7j0YQS2jLIgMsF2J8Xt8RRjjgAw25Mv2ZgppdUR8xr6KpqIaUqsve0a8wCu +8ZFCaGMd0OcRGd7HaGSZ3Inafa8r3XtJ+HT+6iJLKyRfvwVv+9bYyyQKW8gVxMBs +51bSfELsgMzNi61HHLzp3LIE7LpWCsjiZiRIC32ZRLBzhg6Nia/TY3ooyYJJI1mH +gGAxO2QbYuRpKjitLvTxrGhGljAnbs+jbYoGz9PqLkHsmcV2YVMCAwEAAaMTMBEw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQC5/u770nJSh9Iev0OA +0tZ7lsVAJisJEHN34plK1oUD76mFh514ntLLDElfzMYJfXpL0WD87nisIeLpXysC +BC3QQgqfpbylZtFON5W5lxyjfVnQwFsvDC3UdK6rxCoFk/zvHeU5dahwGUHN7t7G +lJm4FfFveSZwMn7Pvgq1eKNJ4g== +-----END CERTIFICATE----- diff --git a/t/data/pkcs12-full.p12 b/t/data/pkcs12-full.p12 new file mode 100644 index 0000000..4b08fe1 Binary files /dev/null and b/t/data/pkcs12-full.p12 differ diff --git a/t/data/pkcs12-no-chain.p12 b/t/data/pkcs12-no-chain.p12 new file mode 100644 index 0000000..9979364 Binary files /dev/null and b/t/data/pkcs12-no-chain.p12 differ diff --git a/t/data/pkcs12-no-passwd.p12 b/t/data/pkcs12-no-passwd.p12 new file mode 100644 index 0000000..b6122d0 Binary files /dev/null and b/t/data/pkcs12-no-passwd.p12 differ diff --git a/t/data/test_CA1.crl.der b/t/data/test_CA1.crl.der new file mode 100644 index 0000000..5f2cf7c Binary files /dev/null and b/t/data/test_CA1.crl.der differ diff --git a/t/data/test_CA1.crt.der b/t/data/test_CA1.crt.der new file mode 100644 index 0000000..8031955 Binary files /dev/null and b/t/data/test_CA1.crt.der differ diff --git a/t/data/test_CA1.crt.pem b/t/data/test_CA1.crt.pem new file mode 100644 index 0000000..20196a8 --- /dev/null +++ b/t/data/test_CA1.crt.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICIjCCAYugAwIBAgIDEjRWMA0GCSqGSIb3DQEBBQUAMCsxCzAJBgNVBAYTAlVT +MQ4wDAYDVQQKEwVEZW1vMTEMMAoGA1UEAxMDQ0ExMCAXDTEyMDEwMTAwMDAwMFoY +DzIxMTExMjMxMjM1OTU5WjArMQswCQYDVQQGEwJVUzEOMAwGA1UEChMFRGVtbzEx +DDAKBgNVBAMTA0NBMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy1ygNguH +72n0l+1uy9HEM6t2LWJEmC0w4tAuXk9H1FseQMV28eBQXdyg3wK+yli6l6c9k9Aj +HAZ/6TXTVmOxtTgkXbvHlwcE3pTiHJSvZWGQMORCPNkjjiVBiLBdGQ3qFKyV+NA5 +K4XnVy0jkeS/BHx7KO7m+DOLVow8FO1CstUCAwEAAaNSMFAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyBzakgqpSAg6dnYVOATxNNkV0CAwCwYDVR0PBAQDAgEG +MBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOBgQBG1QBfo1kZRN50 +/a3ZoQufIj0FJLMS/WkUnW0RLqEewyhEK9u86eoglcz5SxdD4T+VN9+MxoZ2J83P +b21Y4FUDqnkdoGAPdoxX+7iLQcxVoMK72n72QSSzvfnjsr9+pazLp1P6ZK9epbZf +s2WM0ty3a+sYmXANG8wGazAyRDMi0Q== +-----END CERTIFICATE----- diff --git a/t/data/test_CA1.encrypted_key.pem b/t/data/test_CA1.encrypted_key.pem new file mode 100644 index 0000000..28b188d --- /dev/null +++ b/t/data/test_CA1.encrypted_key.pem @@ -0,0 +1,17 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQITsuxC3a/3nMCAggA +MBQGCCqGSIb3DQMHBAhA/86UKBTLSgSCAoCF4ohLfVgalUA/BBo6vxHdVug5jJb7 +VcS8ruRoi4auq+Szdi9pX/4K0r6fvOmxPe5Gr2+c8Qr7NgNM8Ji1g6QAlomWBsV0 +S0cK0RRPAz54J7/OV+7f5mucU2IcpsG79bcWIZAuBXZkfSqb4EUxmtFiMlp2ffwu +v7IsSIKUqB4zy35pFg5i33lLfEAuen0fCMdfBXMv/Y9N+0BwbD3hYEkAzEOjPvND +Kc8coLZoTMPe8UqcTU5brA85CSRMJw2Q+7vE7y3QiSVzyd+wv/vJwg6thbSZ/J6K +5sFH+wrPDqOZ/u0kRq20dvkP31EncBt2/ZYbYfd7yrZkO6o0haJZcOFOaWmDzyJU +ql0XROVp9JLCliFTX5Vi9/dTcgxf50XZiz7CSSpryTpp+dVvGdn0YpT4R2YM6U3K +zm88/GDxUYICbtAgNWwbzgDFGboHs8fRh78h9TmBDVEWGA2ArdNwHao5jDHCxbfz +lhidH8D6LmXBmkBKYZ17GHkE7lwi3xxnu4TwLcMdtlSo0FKm8cisQI2ZYnU13qbY +0tTl2gdeBgN3bpgmFi8sfk2RJhhMpBcBj3QpZKmmed1A+w4DG0yuQM+Y45fGyVu7 +nkZDr/ZcdqxxXILy5nzD9Q4YnLhPfj9qhJELL4o+zi52Q89zkpYMyIHz0VOk0geL +lU/N+ASfnlNIZMevIh9lo2EachOJZ4K6EQMf2cauueWNLhIvX5ZMCH2QarDK1Qk6 +nymASwq3tkEHhxIf4lbekDTOdELQcGq1hiVReaxKmJRwJ52LBEA+7fA+iegeTL54 +8dt2qaEC+2y4Y8o3kbJGVFFZ/0FBZEfUEQ8UxkHHnEemYeJSH3R2jBC1 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/t/data/test_CA1.key.der b/t/data/test_CA1.key.der new file mode 100644 index 0000000..f47e283 Binary files /dev/null and b/t/data/test_CA1.key.der differ diff --git a/t/data/test_CA1.key.pem b/t/data/test_CA1.key.pem new file mode 100644 index 0000000..78f0c3b --- /dev/null +++ b/t/data/test_CA1.key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDLXKA2C4fvafSX7W7L0cQzq3YtYkSYLTDi0C5eT0fUWx5AxXbx +4FBd3KDfAr7KWLqXpz2T0CMcBn/pNdNWY7G1OCRdu8eXBwTelOIclK9lYZAw5EI8 +2SOOJUGIsF0ZDeoUrJX40DkrhedXLSOR5L8EfHso7ub4M4tWjDwU7UKy1QIDAQAB +AoGAOryhJZsFAziWRf91HfeTdN0UQB1+9HkxAoHgsqqxc3tx7IFcTpZcgA/Gg0M2 +uhkQo9bRKU1XprOV5FUAmpYm8E1YmlkdjbkT/JAA2/s4hJH3Z5Bp6rngQzqb1cqw +6Wcfg7n5w6TVAX4Jk2Z1wYF2BMRQyolVKawSRa2B5YJ4hQ0CQQD5XLOpIcjZx8F6 +1E5S0P6L4qb3xtuH3hLlGQmGJvh+vmlnIXhknpr/tIzWSKjQPV3d69ZB8m7Ovqar +gKuYZkzXAkEA0MZziJETLqmmggyrfEXrPmjo4Tkp5eOlU4KvMiCKj8fBDV0OSAa6 +FWRWU/jr0pURjQZg8SX+pUUw9L16/Tk8MwJBAJgDe0LP5bFdpQVMB7NU1NhSA5dp +EstxBfPDn5q4hyQ8z+Se8tXkGnlnh7PZ94962Y5ABw2MzSAb+V7zwafWNWECQQDJ +QQTOeUtMiC4C38PPoHcNSoRz2G8TNUeCIVBRuhzYTW9EOpgxxopLZNXzTNnHvfuV +PrjkvgOjvfdbdezBfhMRAkEA0cr/p6NLmEa1bTtlpy9dqVpwZg2o7PKEHl+qIazn +zKknV1Ik47IylxRFMRvWJJ9X8AOFxgtQ1I4ATXuemeoaYA== +-----END RSA PRIVATE KEY----- diff --git a/t/data/test_CA1_2048.crt.pem b/t/data/test_CA1_2048.crt.pem new file mode 100644 index 0000000..60ff867 --- /dev/null +++ b/t/data/test_CA1_2048.crt.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNzCCAh+gAwIBAgIUbhAOnOyiRbWO/M87lSQZ6BzQ2gswDQYJKoZIhvcNAQEL +BQAwKzELMAkGA1UEBhMCVVMxDjAMBgNVBAoMBURlbW8xMQwwCgYDVQQDDANDQTEw +HhcNMTkwNTAyMjEwODQ5WhcNMjkwNDI5MjEwODQ5WjArMQswCQYDVQQGEwJVUzEO +MAwGA1UECgwFRGVtbzExDDAKBgNVBAMMA0NBMTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAM2TLF8rIUGq5WpimgA9/34IKQz69tekrTdyfNeBKEqvoMqh +ssKtrUThB2dkJCRCh95OVskkDShKmvc/uskhXQj3E4bzK8JltCuR3F5iII0q+kRm +rF6dixd3y83eFEHiCX7Br2QS5qZt3ctTIFjzJTUHYsoK76vVw3rRD0KH4VptyD4w +ttqf+Bsi3ucVGkFAcwIBnMpmPirWPg86kjNqJ5dImiIq7LgHRWmwMXgL4sQmMEcP +DiH26M36disHq1z1b4F40RJ69O3P0Vp8H6X0sMSZvKAfCB5do+B50PGU1lCtiipo +thB+pWXpsQTL9G38Pg0qgr15Qx+oapoXvt7uWLcCAwEAAaNTMFEwHQYDVR0OBBYE +FASq0tq6+Cc3H8zRXeY11hqw/6OeMB8GA1UdIwQYMBaAFASq0tq6+Cc3H8zRXeY1 +1hqw/6OeMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJXU8o+Y +G5eml1qHnzUDBEekfBQ3WDavXBrVaOlXQ1tPCErpjKYGwaIfhtvNYM+TNnZqoCJ4 +Bc1z/1ov+Vi/2RUXZefJL1ZrGk1Fr6+PzYQDrRWv9xQjKDquVTIwaD3raRd2rQ8j +Av3y/4F2Ro2rWpjfw7Vd3wjcy6Nnh9WnGnaMw2wnNjtex4twSf04+qJflvd3LG+9 +BWxAiyu8iNYndn1eE/Wvqtu1Du3ksKTfF+1bfRL1KDGpvk1s9gwChyNj2goMwWkU +GcWEnIVTMd/aHz++kve2I6QSUbdV4O5wt6WbY/tQ/9bcML6CfPzdK4GyItW6HeRF +H5eAZT7iYP7G8Zg= +-----END CERTIFICATE----- diff --git a/t/data/test_CA1_2048.key.pem b/t/data/test_CA1_2048.key.pem new file mode 100644 index 0000000..c0e7b86 --- /dev/null +++ b/t/data/test_CA1_2048.key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNkyxfKyFBquVq +YpoAPf9+CCkM+vbXpK03cnzXgShKr6DKobLCra1E4QdnZCQkQofeTlbJJA0oSpr3 +P7rJIV0I9xOG8yvCZbQrkdxeYiCNKvpEZqxenYsXd8vN3hRB4gl+wa9kEuambd3L +UyBY8yU1B2LKCu+r1cN60Q9Ch+Fabcg+MLban/gbIt7nFRpBQHMCAZzKZj4q1j4P +OpIzaieXSJoiKuy4B0VpsDF4C+LEJjBHDw4h9ujN+nYrB6tc9W+BeNESevTtz9Fa +fB+l9LDEmbygHwgeXaPgedDxlNZQrYoqaLYQfqVl6bEEy/Rt/D4NKoK9eUMfqGqa +F77e7li3AgMBAAECggEAbjUeLo7yrz+s6dGeec7C74/0Ye8Q8h5odjc8UlP9g7yP +2NHDAbcWEr0IuRbogT/hkv4wbHiVTSph1Xcm7bijJbE/mLM4nGjlpA34M+krRkLq +FE1uzvJqpNQmQGF0PrWtHXU8T8wKNuLjaqNPzh/brIgfH+2o+1gICgmVwrcRyuXl +zAkAQPkFDabDwfy7c1JlJhA+LbZmUD6knuT/N4xpVly/D15i3CB8U8gGpuGvA8h8 +oUG107jJ/wN5WV7ILA8r01AbUOW1sT59bP6XtXtOrit40NVRJAeAeeUdxK/lTxeA +mgpgHwefkXnsuOOGGro3qtbl+wX+iLs1EcUkVvSn4QKBgQDreN2ujEXJarjqK49q +d4l4lQW2BlRUqIUkyylUGvdDP6ECExJAaaw2Lj+IAXS9nsr/0QwD7Qsrfg1y5pzq +zj+YBI+rlZmyv8nklm8HfpGsVc7XwZbRSoL9IeRfgSQYGK6Rbo4usaWeTFJO6JFY +ZzhUjMaX+tqdQUS+i4LCwRd1OQKBgQDffxPmrBqwR6qEh/1CqqWPcZB0XrKP8Ken +mgF9EzhJ0lPkY+21+omwZ7lkPGYbw9MA8ObRrtyDVByxN2NSyga8b/S95a4LpDi8 +Oker+sWoxhjScnHf0XlcG2pTIRgVELdoLNgFZnTk0RhwNfZyAuL2vZANUBep2zqb +gn4IKuOtbwKBgCCG8LB05gr9uA949vWxD4ddpo1PcITFRqcffVUF6JQcjQQ5WDMX +pddSKiqCcPrknYwa93rvWrSmU/tESfbRiM1aC/Ka1sFvZtcxxKKXZE4XCFybfFbq +4Q9QiDh9IVxGxI6IZBGlLoigaFpIHBPHJmvfimtiFqLUakecA/MdMz1ZAoGBANDR +mhWPvkvwWfkEWnRcnt38nJyuEiZ9Exh8w2FKgPAwjWO6nlLGaLmi4EwwRrMwb0jU +zMUjnTMzdq958dpbmpmb/U8kd063PK9ZwLeGUgIUPQL8HTujK8IMd3Z+WFLuUH8M +TzYUeamFWFEXilESM1+Y1CwsJj/07rh33yvgbuQPAoGANM7ls/vt0i4qEhKBFZ/i +kOhjnOruKPtWw/8Q3LYLIxlvAn8gJGnSADsGiENIoTwsYSoXRsYQ3X2vdzComeF4 +fI7uXB7pllosN5jeeTpReiOL+hF47j8R/kxqMOPn6VdfMrmlS26l6CF3gVJU2roR +KcMQGzOuxPxshAH2bhdPR78= +-----END PRIVATE KEY----- diff --git a/t/data/test_CAinter.crt.pem b/t/data/test_CAinter.crt.pem new file mode 100644 index 0000000..12e978f --- /dev/null +++ b/t/data/test_CAinter.crt.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICTzCCAbigAwIBAgIBAjANBgkqhkiG9w0BAQsFADArMQswCQYDVQQGEwJVUzEO +MAwGA1UEChMFRGVtbzExDDAKBgNVBAMTA0NBMTAeFw0xOTA0MTcxNTEzMjFaFw0y +OTA0MTQxNTEzMjFaMBcxFTATBgNVBAMMDEludGVybWVkaWF0ZTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMjKRTFhhQvcFd8kkjjevKPjZRFmhd5zVWAB +tqrAEdhWwxpI3Jg1j49sbBWL2WKFhASPzYgPTE1CTQ6eH46ySmgLt8qzdPp8+kiC +RDU0h7j0YQS2jLIgMsF2J8Xt8RRjjgAw25Mv2ZgppdUR8xr6KpqIaUqsve0a8wCu +8ZFCaGMd0OcRGd7HaGSZ3Inafa8r3XtJ+HT+6iJLKyRfvwVv+9bYyyQKW8gVxMBs +51bSfELsgMzNi61HHLzp3LIE7LpWCsjiZiRIC32ZRLBzhg6Nia/TY3ooyYJJI1mH +gGAxO2QbYuRpKjitLvTxrGhGljAnbs+jbYoGz9PqLkHsmcV2YVMCAwEAAaMTMBEw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQC5/u770nJSh9Iev0OA +0tZ7lsVAJisJEHN34plK1oUD76mFh514ntLLDElfzMYJfXpL0WD87nisIeLpXysC +BC3QQgqfpbylZtFON5W5lxyjfVnQwFsvDC3UdK6rxCoFk/zvHeU5dahwGUHN7t7G +lJm4FfFveSZwMn7Pvgq1eKNJ4g== +-----END CERTIFICATE----- diff --git a/t/data/test_CAinter.extensions b/t/data/test_CAinter.extensions new file mode 100644 index 0000000..9a3aedb --- /dev/null +++ b/t/data/test_CAinter.extensions @@ -0,0 +1 @@ +basicConstraints=critical,CA:TRUE diff --git a/t/data/test_CAinter.key.pem b/t/data/test_CAinter.key.pem new file mode 100644 index 0000000..3e6e9c2 --- /dev/null +++ b/t/data/test_CAinter.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyMpFMWGFC9wV3ySSON68o+NlEWaF3nNVYAG2qsAR2FbDGkjc +mDWPj2xsFYvZYoWEBI/NiA9MTUJNDp4fjrJKaAu3yrN0+nz6SIJENTSHuPRhBLaM +siAywXYnxe3xFGOOADDbky/ZmCml1RHzGvoqmohpSqy97RrzAK7xkUJoYx3Q5xEZ +3sdoZJncidp9ryvde0n4dP7qIksrJF+/BW/71tjLJApbyBXEwGznVtJ8QuyAzM2L +rUccvOncsgTsulYKyOJmJEgLfZlEsHOGDo2Jr9NjeijJgkkjWYeAYDE7ZBti5Gkq +OK0u9PGsaEaWMCduz6NtigbP0+ouQeyZxXZhUwIDAQABAoIBAQCs7Nbukmg9MIx9 +o0dzRxD7rImMlNlSHc43YwJoyAYWZZKd/oZNaEN9aAkl/U149jgenaKLPXGfUCyB +HFldUduXBBCDuE5UtHHxJI+NqvIAricoIffGKMjNqO7UHfp0btELBQj2GE20KJoz +iMPwReePM1BLCb6Ah6ckvYY6bhDs2mfaQKwOHu7JuEinCf//5jjuqmCWSzLYSN6G +Z8GZJ7wkqC5US1DzxW9S6XtfHpj1UIiasI6UriF0Zc3C/xD3v6rjXEhB7skiOs/5 +IReOL8HNISnMF9X5L3d1+JT0M7FE+jkST5IhplA0TxaMydf7mKl0yw30ujkfg5fM +CxmaW0GBAoGBAO6YGs7SAcay3zT8f0gs/8DWP/Xnxn9MkQ3OetG6GHiP73rV+RZn +72hp1l0GFjeRmEKu5yb9Fy1EHiXsee8ZKsBOmlZPBKB8/sPwKWBn3ZlxIiVQriuj +5uMNwTgEdTVfSfrp0W4ho6hVc+6M301FkhYlHCaRIbPw8CadRlx4oBazAoGBANdw +JsTBYFQoxDIeZMiXIDvdKoZV+jXluI9KvpCHCKQx36hLRBwYr0lQcXJWWcWyCfew +6aBA6nw6aoPCpTvrD4n/wC0WPsAhqyOCB1yCH8cvMbul65AHx0sArGOa1xzZH8Eg ++GVj801MhQNMT8cXTUCVm5fs1qQVbYKWa+wD2trhAoGBAIVo7Yx5pt6Yw/AXw3/z +EWqdIhR47efeQzlqHAjLOsWnDewsWuQpZ5eFnoRTU/bsZSvcKooFeIEqFoV0DdYg +x2PST8A03Mx0N+wNjMVILoOO293rmAf01LRey4xsCbG3P2Gafi1Lh/wnE/TuNio5 +3W6ef3gdLLA158JfrKkmFbW7AoGABrt6equQVxDvEKHihGI0n6pJqekF6KlFGzU6 +v0l4+6iTVK8FcdtTnvbklK4eIA9wQE1G/7sHmNo6eeObRkQSOD3Fw6LuUxK6RmHJ +2Ro35AGVjEejFN0pXS6oNHSiRESEuYROPtzgvYmmnnPECnSv9VS3iAferUH+KhaJ +SNbWAAECgYBO4VJbt4EP08uQleYBoO9JVHVmYYKtavFL3YR08k4xh4qtndwVeRZT +Z9ywS3maA383wvuCy3xUBmi0AY7xDvgaPaPYZT6YIaiosdEaMkI+juV/Uno96W+w +wuRywxcAi1JNm3rbIGpUbdUxxo4ATOlD3C7A/X5AmRC24YRGol8Ciw== +-----END RSA PRIVATE KEY----- diff --git a/t/data/test_CAinter.req.pem b/t/data/test_CAinter.req.pem new file mode 100644 index 0000000..dfb7a0f --- /dev/null +++ b/t/data/test_CAinter.req.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICXDCCAUQCAQAwFzEVMBMGA1UEAwwMSW50ZXJtZWRpYXRlMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyMpFMWGFC9wV3ySSON68o+NlEWaF3nNVYAG2 +qsAR2FbDGkjcmDWPj2xsFYvZYoWEBI/NiA9MTUJNDp4fjrJKaAu3yrN0+nz6SIJE +NTSHuPRhBLaMsiAywXYnxe3xFGOOADDbky/ZmCml1RHzGvoqmohpSqy97RrzAK7x +kUJoYx3Q5xEZ3sdoZJncidp9ryvde0n4dP7qIksrJF+/BW/71tjLJApbyBXEwGzn +VtJ8QuyAzM2LrUccvOncsgTsulYKyOJmJEgLfZlEsHOGDo2Jr9NjeijJgkkjWYeA +YDE7ZBti5GkqOK0u9PGsaEaWMCduz6NtigbP0+ouQeyZxXZhUwIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBAEwFJmFml/WqQebFs3/KvL174FUDzNRMfsNuekJHJAVY +r3TjSWrhLhRq/O71gCFn/WnaE/GACciE3djW+Y61GYJ33kXsoxiKhmmGdfJmpND8 +6J5IglzsF2RedJZoZ+pwJ0XML1jSIjozxGSqNai++r9nKzVKve97JVSM1faBMuBf +5fWn4uxE8ODlgFE2nAkd5srarGDgEtwqPaLwvWzlONhCK9iBvoSrvTo9It6ibjG+ +fnbHb3ZhkWXKrILEz3NSHRaQHlQxoDGBfHhxZGj0CfjcTj+piZzpyqxpIELP0jNO +mKhN0Gg3nR2eU6XHjy0JRhqqADUF77SQRomwTTRE5eU= +-----END CERTIFICATE REQUEST----- diff --git a/t/data/test_leaf.crt.pem b/t/data/test_leaf.crt.pem new file mode 100644 index 0000000..642e909 --- /dev/null +++ b/t/data/test_leaf.crt.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmjCCAYICAQEwDQYJKoZIhvcNAQELBQAwFzEVMBMGA1UEAwwMSW50ZXJtZWRp +YXRlMB4XDTE5MDQxNzE1MTY1M1oXDTI5MDQxNDE1MTY1M1owDzENMAsGA1UEAwwE +TGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOa0eYS3XsiXadYF +53ZTfaNhbbkpCWnFddFQ/c3Z7QToJ6DkTiqDNTpHodvrG+CFDVuO0RJONQDf4jH6 +6B6ityFYWc4RkAPqfat0k7NZpj5dVWp9uDgmEWABmf0KE9WqzYDbtTljlS1POHI9 +UFCdF3/T0UbGtdKSzzo/STJf8vLOTf5YJQZHImvZeQbCgXtBN8hdLtfdU5FQYbaK +cGyDvW6mBg1ZxYgJx+hE9NNeAsAWp2rAXGZIatQ98KNmwY5VH6cBX4ggasQucUUI +Bg5ih7fvWP2k0FyaiIsme9nWLsbuNg3s3tMahuRO1rE0Z0Vj/5JBUmT6J27ZBKGZ +Rn7C2x8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAgleJwB7rE7w+B4jlRqP72kkR +XL7MZSV2vr+CTS4t+iLlbHweApiEJmQ3szY69d/gtdznSacp8CHOGihRazRsudn2 +G6QHbjXNBs16KnEEnHiIbk0YrnAa0xxrKvxOHPX+lfvYEcN2QqVtiFF0IsTqck8I +vMYYe5zf4RDd2S1q31l67LoFSmFhrAqPbDITrx8tMhyAEW6zNxNkCaM/+8Bu94E3 +Ec7QDmpbE4Qz80qzmCmpv7NBnvrn0uYO1IkPrq2XetbhWHoliYImeS2OojdnPVbx +sP1q5i9FYnnvFA8xl4TORjqtIajX6bXVkWZBXkbtDGKLnxzJ+vPagxwEzOphmA== +-----END CERTIFICATE----- diff --git a/t/data/test_leaf.key.pem b/t/data/test_leaf.key.pem new file mode 100644 index 0000000..bc7ecc3 --- /dev/null +++ b/t/data/test_leaf.key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA5rR5hLdeyJdp1gXndlN9o2FtuSkJacV10VD9zdntBOgnoORO +KoM1Okeh2+sb4IUNW47REk41AN/iMfroHqK3IVhZzhGQA+p9q3STs1mmPl1Van24 +OCYRYAGZ/QoT1arNgNu1OWOVLU84cj1QUJ0Xf9PRRsa10pLPOj9JMl/y8s5N/lgl +Bkcia9l5BsKBe0E3yF0u191TkVBhtopwbIO9bqYGDVnFiAnH6ET0014CwBanasBc +Zkhq1D3wo2bBjlUfpwFfiCBqxC5xRQgGDmKHt+9Y/aTQXJqIiyZ72dYuxu42Deze +0xqG5E7WsTRnRWP/kkFSZPonbtkEoZlGfsLbHwIDAQABAoIBACt/2e3JOWjvC7ic +EmGAKo9UvoCMGUdFQQq/j6txrLwhHd+7THW9mZqsiPtTYEU8MSGTUx51eo74p8iu +u3eTTJ5P71boftQOMbXTXEoT3EGkDYfvvn1vyBTnGGbasJS4CNmEE66HdUg+yLDZ +mLwqcpTalnoW24+huMsNxbpm1wMqwWqQstpWG7LL+BaPc3AlvS6A4Zk0wxF6av0P +7AWcfqa+9tLIuphH0aJc6LTedkk65SfhGuJAl0p9mR8fLMtqpDIiyAzN6eteHKe8 +1+sSk0Qwm6wzPtk4EaT92dXTuRcsqHIGezsLtI0LRaXSTuVrwzYzS+DPyvsm/3h4 +fx9+FukCgYEA88yVSAsFRXBpcM5QOVgHMT0gr2y/ieCvcn6IV9s/rTs3P4Lnp7u3 +INHjOKEIIKDo1i/++RfLy6gZFJolT2AoO5KwgGh7gAzQhTaeiRFe0guDfQ/TyqIy +jZkCuhue9ONqOEBJzf8d7yoLIGuABQmmwd9ynUmEUj6ZwA9R+cq3q5MCgYEA8kAi +61ZvAT0oqheZSrxNCXXAYUtJno1btZL6eGn5yZJYY686TAR/sXZ/VprkBPljLSKC +2SMy+3cJylmB1hDE1mPZVKOXb5GOxbZVcPlmRi3yVgSrRmWiR93o3Kk9Ee2Bozbh +gGDSe75+k0zPvGuKWNFawLTgYnV2jHMe7jvmwcUCgYAcMLnKPMv9PYRTsOeB2fXq +8aCH6FE1hi+DU7I8RnPUehZnV6GluYTxXJOjhqtD6pdBvQcEkoXUJLnRsglCZmIA +kXOrRWmSYujxnmEyhDmsm/w2R9A7jAnAacLw9iSpOGqd2oEuOqOhdgEXXJbO/lCz +9jxwh4GvaOGqXZsjARe/1QKBgFRK5Numk7GGqmOlGn3az6N/CZXRMKiu3z5rCiRk +G7p75a2qB0r0Ncp2RRDJjJX+gPfvjkAn81F0tj9mrbri0tsWm0TMN6FmsJszOr+4 +yFGbIzuzHDW+n50KJkDB0rIuRnGYYxbcmeDdBAYVMCOL9/O3xTBQv9MCtGFinVyg +E0dRAoGBAM/qws7uzcrr5m0YGrC7vkyONS2Cb9pzygjHpvwE/tUZA4+4LJYdHIVE +j7FBejnhTL9o9HvDwBBEPZXoSt3Ev0TnF/LKR1PcuDHWhyDHphdkq7BSk1tswW5/ +NXVb289b59dV3QpwrLzF6jQtAvm1bUXc1PoNFhrBjFzUGLslz5Io +-----END RSA PRIVATE KEY----- diff --git a/t/data/test_leaf.req.pem b/t/data/test_leaf.req.pem new file mode 100644 index 0000000..fcc5f45 --- /dev/null +++ b/t/data/test_leaf.req.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICVDCCATwCAQAwDzENMAsGA1UEAwwETGVhZjCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAOa0eYS3XsiXadYF53ZTfaNhbbkpCWnFddFQ/c3Z7QToJ6Dk +TiqDNTpHodvrG+CFDVuO0RJONQDf4jH66B6ityFYWc4RkAPqfat0k7NZpj5dVWp9 +uDgmEWABmf0KE9WqzYDbtTljlS1POHI9UFCdF3/T0UbGtdKSzzo/STJf8vLOTf5Y +JQZHImvZeQbCgXtBN8hdLtfdU5FQYbaKcGyDvW6mBg1ZxYgJx+hE9NNeAsAWp2rA +XGZIatQ98KNmwY5VH6cBX4ggasQucUUIBg5ih7fvWP2k0FyaiIsme9nWLsbuNg3s +3tMahuRO1rE0Z0Vj/5JBUmT6J27ZBKGZRn7C2x8CAwEAAaAAMA0GCSqGSIb3DQEB +CwUAA4IBAQAIZ7M0DLAkqPm8kdM+h53+BMkK2ngfb1K0qgRMAc3ij8ernF+QsqV1 +CiBk4w2bGQ+pxVf5XNjVuw0otV3C0NSlFSAmZXldXdJpW7WUWLG7HTstjjfNMJ3v +9XxrqqoHBIvdWNk4Lni8nDqzm8SDtZRByqO9sv/Mlg2cq1A6TrQAOaDMz8YaHtom +LFCzEkqtaxuG1fi5F5Px+HJQT3gF1shwdEED6pCuVIgGpNDBceZq76eweKC9WEOq +77Is1jkfBC046dAVDpmz+avNbiP0SABemcSnvOJUnGM7EjLMY51OoZ0nc3CH0cO3 +RVw6jE12UUQXyaxEZqAbKCk0CXfAOIBw +-----END CERTIFICATE REQUEST----- diff --git a/t/data/testcert_cdp.crt.pem b/t/data/testcert_cdp.crt.pem new file mode 100644 index 0000000..d91d305 --- /dev/null +++ b/t/data/testcert_cdp.crt.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIJAIwko/NtbQ85MA0GCSqGSIb3DQEBBQUAME8xCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIEwVTdGF0ZTENMAsGA1UEBxMEQ2l0eTEQMA4GA1UEChMH +Q29tcGFueTEPMA0GA1UECxMGSXNzdWVyMB4XDTEzMDMwNjE2MTUxMloXDTIzMDMw +NDE2MTUxMlowbTELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVN0YXRlMQ0wCwYDVQQH +EwRDaXR5MRAwDgYDVQQKEwdDb21wYW55MRMwEQYDVQQLEwpEZXBhcnRtZW50MRgw +FgYDVQQDEw9jZHAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDQRPMJY8AiU3rqT5qeYqfIwwfJUYiTa3jchUsyjMugECsABMFpSyRu +3rlXjbHxFHtFeSQHCqdISJ40rQ0Dl4HHEiTxQjEbIYsPLBBTKee5qpnmBysLXnh2 +r9NgeQgpdFHNWJg+6oDPwylgplC7kgxG82jvMFg+ZXxqnhZJP5Fm0xwjrWFNvaqp +3A5w8PmbuadutDs0JLWRLHKPSZPKAMGPhUoyHJa7LnvpE/J2ny+h4iUvM8K9nqpN +TlSJBWKOfMHL4H2DtkqMyCL74z+REiXbDJ7O8Rj8kshxf3XvkiVdps7/sMaL+PKB +A0MQiaxmusr19dQxmQLHX4zrrCk4EOj/AgMBAAGjgbswgbgwgbUGA1UdHwSBrTCB +qjBgoF6gXKRaMFgxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxFeGFtcGxlIENvcnAx +IDAeBgNVBAsTF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MRAwDgYDVQQDEwdUZXN0 +aW5nMCWgI6Ahhh9odHRwOi8vd3d3LmV4YW1wbGUuY29tL3Rlc3QucGVtMB+gHaAb +hhlsZGFwczovL2xkYXAuZXhhbXBsZS5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQAZ +0WCkvDqTopszsW/FeD5Gdpk6Q8VqoYU1GjepybIIHgCgWfaFla31yyte4CCIPVaM +Gk+t+k920JnKRyRLvLYtHj5jwbi3x04JnlT2qf2nETIwQhlBBo0U2yqAWYYojNt9 +tr4awo4rjOPEbdN5J46696wskGgnkI3hpDZrR2LYzYPyEedST2CRyabrhlciNl9k +o65Souo5ZJsQ0Iq9PYrxWc6LvezILMoXG3DU8EudJr1N5Y0Q79W85ofkcpLlpJoK +7lNeG0AkxYQ1WqP3KbtzWCjaWL1RXyI9MbaDh0Qcdn+bWW8bj7osSCDrBR88Ve7N +F93dvxcZnHu7MJ+R3w8W +-----END CERTIFICATE----- diff --git a/t/data/testcert_cdp.crt.pem_dump b/t/data/testcert_cdp.crt.pem_dump new file mode 100644 index 0000000..fd6cf41 --- /dev/null +++ b/t/data/testcert_cdp.crt.pem_dump @@ -0,0 +1,155 @@ + +# exported via command: perl examples/x509_cert_details.pl -dump -pem t/data/testcert_cdp.crt.pem > t/data/testcert_cdp.crt.pem_dump +# hashref dumped via Data::Dump +{ + cdp => [ + "http://www.example.com/test.pem", + "ldaps://ldap.example.com/", + ], + certificate_type => 305, + digest_sha1 => { + pubkey => pack("H*","0bb24ad27d36b416081056515bbffbecf59162aa"), + x509 => pack("H*","3c0b54e83db793e09991fb382d98c5557a1c01b5"), + }, + extensions => { + count => 1, + entries => [ + { + critical => 0, + data => "\nFull Name:\n DirName: C = US, O = Example Corp, OU = Certification Authority, CN = Testing\n\nFull Name:\n URI:http://www.example.com/test.pem\n\nFull Name:\n URI:ldaps://ldap.example.com/\n", + ln => "X509v3 CRL Distribution Points", + nid => 103, + oid => "2.5.29.31", + sn => "crlDistributionPoints", + }, + ], + }, + extkeyusage => { ln => [], nid => [], oid => [], sn => [] }, + fingerprint => { + md5 => "70:C6:E6:37:B0:08:F5:FD:79:29:F5:D9:06:B1:A9:20", + sha1 => "3C:0B:54:E8:3D:B7:93:E0:99:91:FB:38:2D:98:C5:55:7A:1C:01:B5", + }, + hash => { + issuer => { dec => 2797460151, hex => "A6BDDAB7" }, + issuer_and_serial => { dec => 3184907103, hex => "BDD5D35F" }, + subject => { dec => 359323249, hex => "156AD671" }, + }, + issuer => { + count => 5, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "State", + data_utf8_decoded => "State", + ln => "stateOrProvinceName", + nid => 16, + oid => "2.5.4.8", + sn => "ST", + }, + { + data => "City", + data_utf8_decoded => "City", + ln => "localityName", + nid => 15, + oid => "2.5.4.7", + sn => "L", + }, + { + data => "Company", + data_utf8_decoded => "Company", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "Issuer", + data_utf8_decoded => "Issuer", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + ], + oneline => "/C=US/ST=State/L=City/O=Company/OU=Issuer", + print_rfc2253 => "OU=Issuer,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8 => "OU=Issuer,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8_decoded => "OU=Issuer,O=Company,L=City,ST=State,C=US", + }, + keyusage => [], + not_after => "2023-03-04T16:15:12Z", + not_before => "2013-03-06T16:15:12Z", + ns_cert_type => [], + pubkey_alg => "rsaEncryption", + pubkey_bits => 2048, + pubkey_id => 6, + pubkey_size => 256, + serial => { dec => "10098376530379738937", hex => "8C24A3F36D6D0F39", long => -1 }, + signature_alg => "sha1WithRSAEncryption", + subject => { + altnames => [], + count => 6, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "State", + data_utf8_decoded => "State", + ln => "stateOrProvinceName", + nid => 16, + oid => "2.5.4.8", + sn => "ST", + }, + { + data => "City", + data_utf8_decoded => "City", + ln => "localityName", + nid => 15, + oid => "2.5.4.7", + sn => "L", + }, + { + data => "Company", + data_utf8_decoded => "Company", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "Department", + data_utf8_decoded => "Department", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "cdp.example.com", + data_utf8_decoded => "cdp.example.com", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/ST=State/L=City/O=Company/OU=Department/CN=cdp.example.com", + print_rfc2253 => "CN=cdp.example.com,OU=Department,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8 => "CN=cdp.example.com,OU=Department,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8_decoded => "CN=cdp.example.com,OU=Department,O=Company,L=City,ST=State,C=US", + }, + version => 2, +} diff --git a/t/data/testcert_extended.crt.pem b/t/data/testcert_extended.crt.pem new file mode 100644 index 0000000..e43df17 --- /dev/null +++ b/t/data/testcert_extended.crt.pem @@ -0,0 +1,40 @@ +-----BEGIN CERTIFICATE----- +MIIHGTCCBoKgAwIBAgIDEjRYMA0GCSqGSIb3DQEBBQUAMCsxCzAJBgNVBAYTAlVT +MQ4wDAYDVQQKEwVEZW1vMTEMMAoGA1UEAxMDQ0ExMB4XDTEyMDIwMTAwMDAwMFoX +DTM1MDMzMTIzNTk1OVowggHVMQswCQYDVQQGEwJVUzEOMAwGA1UECBMFU3RhdGUx +DTALBgNVBAcTBENpdHkxEDAOBgNVBAoTB0NvbXBhbnkxDTALBgNVBAsTBFVuaXQx +HTAbBgNVBAMTFGV4dGVuZGVkLnNlcnZlci5jZXJ0MSwwKgYJKoZIhvcNAQkBFh1h +bnllbWFpbEBleHRlbmRlZC5zZXJ2ZXIuY2VydDEVMBMGA1UECxMMQW5vdGhlciBV +bml0MRkwFwYDVQQLExBZZXQgQW5vdGhlciBVbml0MRUwEwYDVQQEEwxTdXJuYW1l +IHRleHQxEzARBgNVBAwTClRpdGxlIHRleHQxGTAXBgNVBA0TEERlc2NyaXB0aW9u +IHRleHQxEjAQBgNVBCkTCU5hbWUgdGV4dDEXMBUGA1UEKhMOR2l2ZW5OYW1lIHRl +eHQxFjAUBgNVBCsTDUluaXRpYWxzIHRleHQxFTATBgNVBC4TDGRuLnF1YWxpZmll +cjENMAsGA1UESBMEUm9sZTEdMBsGA1UELAwUZ2VuZXJhdGlvbl9xdWFsaWZpZXIx +FzAVBgNVBEETDlBzZXVkb255bSB0ZXh0MR0wGwYDVQQtDBR4NTAwX3VuaXFfaWRl +bnRpZmllcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2aWvhnencjZ7M/Ff +h2FyRejq29hF/XOSmJmmZgwirs9dnOq3kXrnx0y9XMBKPj1kdYW5omesX6pMIAyl +MNl5fADUtBQkxCneXnIcKAgvgxaqz1VqnTu3UBN4H/g82KOEkMw2mXEaY0TmvG3e +DgU9zvd/8T0ZUlTP6QmGA2OBkqcCAwEAAaOCA50wggOZMAwGA1UdEwEB/wQCMAAw +HQYDVR0OBBYEFKJ+nSndaOLx9HyMFO6u1yJFYi3/MFUGA1UdIwROMEyAFMgc2pIK +qUgIOnZ2FTgE8TTZFdAgoS+kLTArMQswCQYDVQQGEwJVUzEOMAwGA1UEChMFRGVt +bzExDDAKBgNVBAMTA0NBMYIDEjRWMAwGA1UdDwQFAwMH4oAwXgYDVR0lAQH/BFQw +UgYIKwYBBQUHAwEGCCsGAQUFBwMDBgorBgEEAYI3CgMBBggrBgEFBQcDBQYIKwYB +BQUHAwYGCCsGAQUFBwMHBggrBgEFBQcDDQYIKwYBBQUHAw4weAYDVR0RBHEwb4EO +YWx0MUBlbWFpbC5jb22IBCoDBAWGHGh0dHA6Ly9uYW1lLmRvbS5jb20vd2hhdGV2 +ZXKCDGRucy5uYW1lLmNvbYcECgsMDaATBgQqAwQFoAsMCW90aGVybmFtZYcQKgAU +UEABDAEAAAAAAAAAkzBWBgNVHRIETzBNgRhpc3N1ZXIuYWx0bmFtZUBlbWFpbC5j +b22IAyoAAIYVaHR0cDovL2lzc3Vlci5jb20veHl6gg9pc3N1ZXIuYWx0Lm5hbWWH +BAECAwQwQwYDVR0fBDwwOjAboBmgF4YVaHR0cDovL3NlcnYxLmNvbS9jcmwxMBug +GaAXhhVodHRwOi8vc2VydjEuY29tL2NybDIwMAYIKwYBBQUHAQEEJDAiMCAGCCsG +AQUFBzABhhRodHRwOi8vb2NzcC93aGF0ZXZlcjARBglghkgBhvhCAQEEBAMCAFEw +KwYJYIZIAYb4QgECBB4WHGh0dHA6Ly9uZXRzY2FwZS5iYXNlLnVybC94enkwMQYJ +YIZIAYb4QgEDBCQWImh0dHA6Ly9uZXRzY2FwZS5yZXZvY2F0aW9uLnVybC94enkw +NAYJYIZIAYb4QgEEBCcWJWh0dHA6Ly9uZXRzY2FwZS5jYS5yZXZvY2F0aW9uLnVy +bC94enkwOgYJYIZIAYb4QgEHBC0WK2h0dHA6Ly9uZXRzY2FwZS5jZXJ0aWZpY2F0 +ZS5yZW5ld2FsLnVybC94enkwMAYJYIZIAYb4QgEIBCMWIWh0dHA6Ly9uZXRzY2Fw +ZS5jYS5wb2xpY3kudXJsL3h6eTAeBglghkgBhvhCAQwEERYPc3NsLnNlcnZlci5u +YW1lMCUGCWCGSAGG+EIBDQQYFhZuZXRzY2FwZSBjb21tZW50IGZpZWxkMA0GCSqG +SIb3DQEBBQUAA4GBAKfdXUWwBvGjchb0VxVKspuvbpUnADOKcro1kdviRQRek46l +6Rjvq7vUZoUyeDOkFg08kxQQgNFOdnYLtuL6BkhGD7lVArM4s9anyp30umHgWEpR +0W6H0lfKI7nkc49sM7NJX0Srg4b6FVHhrNKhXC3ZPCOMIUqfW/Qi3ENJfVYM +-----END CERTIFICATE----- diff --git a/t/data/testcert_extended.crt.pem_dump b/t/data/testcert_extended.crt.pem_dump new file mode 100644 index 0000000..cb0b1f3 --- /dev/null +++ b/t/data/testcert_extended.crt.pem_dump @@ -0,0 +1,423 @@ + +# exported via command: perl examples/x509_cert_details.pl -dump -pem t/data/testcert_extended.crt.pem > t/data/testcert_extended.crt.pem_dump +# hashref dumped via Data::Dump +{ + cdp => ["http://serv1.com/crl1", "http://serv1.com/crl2"], + certificate_type => 4145, + digest_sha1 => { + pubkey => pack("H*","a27e9d29dd68e2f1f47c8c14eeaed72245622dff"), + x509 => pack("H*","c682b9055dde00ce08f61be9bc485597a1f54bb3"), + }, + extensions => { + count => 17, + entries => [ + { + critical => 1, + data => "CA:FALSE", + ln => "X509v3 Basic Constraints", + nid => 87, + oid => "2.5.29.19", + sn => "basicConstraints", + }, + { + critical => 0, + data => "A2:7E:9D:29:DD:68:E2:F1:F4:7C:8C:14:EE:AE:D7:22:45:62:2D:FF", + ln => "X509v3 Subject Key Identifier", + nid => 82, + oid => "2.5.29.14", + sn => "subjectKeyIdentifier", + }, + { + critical => 0, + data => "keyid:C8:1C:DA:92:0A:A9:48:08:3A:76:76:15:38:04:F1:34:D9:15:D0:20\nDirName:/C=US/O=Demo1/CN=CA1\nserial:12:34:56\n", + ln => "X509v3 Authority Key Identifier", + nid => 90, + oid => "2.5.29.35", + sn => "authorityKeyIdentifier", + }, + { + critical => 0, + data => "Digital Signature, Non Repudiation, Key Encipherment, CRL Sign, Decipher Only", + ln => "X509v3 Key Usage", + nid => 83, + oid => "2.5.29.15", + sn => "keyUsage", + }, + { + critical => 1, + data => "TLS Web Server Authentication, Code Signing, Microsoft Trust List Signing, IPSec End System, IPSec Tunnel, IPSec User, 1.3.6.1.5.5.7.3.13, 1.3.6.1.5.5.7.3.14", + ln => "X509v3 Extended Key Usage", + nid => 126, + oid => "2.5.29.37", + sn => "extendedKeyUsage", + }, + { + critical => 0, + data => "email:alt1\@email.com, Registered ID:1.2.3.4.5, URI:http://name.dom.com/whatever, DNS:dns.name.com, IP Address:10.11.12.13, othername:, IP Address:2A00:1450:4001:C01:0:0:0:93", + ln => "X509v3 Subject Alternative Name", + nid => 85, + oid => "2.5.29.17", + sn => "subjectAltName", + }, + { + critical => 0, + data => "email:issuer.altname\@email.com, Registered ID:1.2.0.0, URI:http://issuer.com/xyz, DNS:issuer.alt.name, IP Address:1.2.3.4", + ln => "X509v3 Issuer Alternative Name", + nid => 86, + oid => "2.5.29.18", + sn => "issuerAltName", + }, + { + critical => 0, + data => "\nFull Name:\n URI:http://serv1.com/crl1\n\nFull Name:\n URI:http://serv1.com/crl2\n", + ln => "X509v3 CRL Distribution Points", + nid => 103, + oid => "2.5.29.31", + sn => "crlDistributionPoints", + }, + { + critical => 0, + data => "OCSP - URI:http://ocsp/whatever\n", + ln => "Authority Information Access", + nid => 177, + oid => "1.3.6.1.5.5.7.1.1", + sn => "authorityInfoAccess", + }, + { + critical => 0, + data => "SSL Server, Object Signing, Object Signing CA", + ln => "Netscape Cert Type", + nid => 71, + oid => "2.16.840.1.113730.1.1", + sn => "nsCertType", + }, + { + critical => 0, + data => "http://netscape.base.url/xzy", + ln => "Netscape Base Url", + nid => 72, + oid => "2.16.840.1.113730.1.2", + sn => "nsBaseUrl", + }, + { + critical => 0, + data => "http://netscape.revocation.url/xzy", + ln => "Netscape Revocation Url", + nid => 73, + oid => "2.16.840.1.113730.1.3", + sn => "nsRevocationUrl", + }, + { + critical => 0, + data => "http://netscape.ca.revocation.url/xzy", + ln => "Netscape CA Revocation Url", + nid => 74, + oid => "2.16.840.1.113730.1.4", + sn => "nsCaRevocationUrl", + }, + { + critical => 0, + data => "http://netscape.certificate.renewal.url/xzy", + ln => "Netscape Renewal Url", + nid => 75, + oid => "2.16.840.1.113730.1.7", + sn => "nsRenewalUrl", + }, + { + critical => 0, + data => "http://netscape.ca.policy.url/xzy", + ln => "Netscape CA Policy Url", + nid => 76, + oid => "2.16.840.1.113730.1.8", + sn => "nsCaPolicyUrl", + }, + { + critical => 0, + data => "ssl.server.name", + ln => "Netscape SSL Server Name", + nid => 77, + oid => "2.16.840.1.113730.1.12", + sn => "nsSslServerName", + }, + { + critical => 0, + data => "netscape comment field", + ln => "Netscape Comment", + nid => 78, + oid => "2.16.840.1.113730.1.13", + sn => "nsComment", + }, + ], + }, + extkeyusage => { + ln => [ + "TLS Web Server Authentication", + "Code Signing", + "Microsoft Trust List Signing", + "IPSec End System", + "IPSec Tunnel", + "IPSec User", + ], + nid => [129, 131, 136, 294, 295, 296], + oid => [ + "1.3.6.1.5.5.7.3.1", + "1.3.6.1.5.5.7.3.3", + "1.3.6.1.4.1.311.10.3.1", + "1.3.6.1.5.5.7.3.5", + "1.3.6.1.5.5.7.3.6", + "1.3.6.1.5.5.7.3.7", + "1.3.6.1.5.5.7.3.13", + "1.3.6.1.5.5.7.3.14", + ], + sn => [ + "serverAuth", + "codeSigning", + "msCTLSign", + "ipsecEndSystem", + "ipsecTunnel", + "ipsecUser", + ], + }, + fingerprint => { + md5 => "D5:72:82:D5:85:06:4D:62:6F:17:1D:D7:77:BF:D6:11", + sha1 => "C6:82:B9:05:5D:DE:00:CE:08:F6:1B:E9:BC:48:55:97:A1:F5:4B:B3", + }, + hash => { + issuer => { dec => 2914546923, hex => "ADB874EB" }, + issuer_and_serial => { dec => 12265665, hex => "BB28C1" }, + subject => { dec => 2258074781, hex => "86977C9D" }, + }, + issuer => { + count => 3, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "Demo1", + data_utf8_decoded => "Demo1", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "CA1", + data_utf8_decoded => "CA1", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/O=Demo1/CN=CA1", + print_rfc2253 => "CN=CA1,O=Demo1,C=US", + print_rfc2253_utf8 => "CN=CA1,O=Demo1,C=US", + print_rfc2253_utf8_decoded => "CN=CA1,O=Demo1,C=US", + }, + keyusage => [ + "digitalSignature", + "nonRepudiation", + "keyEncipherment", + "cRLSign", + "decipherOnly", + ], + not_after => "2035-03-31T23:59:59Z", + not_before => "2012-02-01T00:00:00Z", + ns_cert_type => ["server", "objsign", "objCA"], + pubkey_alg => "rsaEncryption", + pubkey_bits => 1024, + pubkey_id => 6, + pubkey_size => 128, + serial => { dec => 1193048, hex => 123458, long => 1193048 }, + signature_alg => "sha1WithRSAEncryption", + subject => { + altnames => [ + 1, + "alt1\@email.com", + 6, + "http://name.dom.com/whatever", + 2, + "dns.name.com", + 7, + "\n\13\f\r", + 0, + "othername", + 7, + "*\0\24P\@\1\f\1\0\0\0\0\0\0\0\x93", + ], + count => 20, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "State", + data_utf8_decoded => "State", + ln => "stateOrProvinceName", + nid => 16, + oid => "2.5.4.8", + sn => "ST", + }, + { + data => "City", + data_utf8_decoded => "City", + ln => "localityName", + nid => 15, + oid => "2.5.4.7", + sn => "L", + }, + { + data => "Company", + data_utf8_decoded => "Company", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "Unit", + data_utf8_decoded => "Unit", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "extended.server.cert", + data_utf8_decoded => "extended.server.cert", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + { + data => "anyemail\@extended.server.cert", + data_utf8_decoded => "anyemail\@extended.server.cert", + ln => "emailAddress", + nid => 48, + oid => "1.2.840.113549.1.9.1", + sn => "emailAddress", + }, + { + data => "Another Unit", + data_utf8_decoded => "Another Unit", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "Yet Another Unit", + data_utf8_decoded => "Yet Another Unit", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "Surname text", + data_utf8_decoded => "Surname text", + ln => "surname", + nid => 100, + oid => "2.5.4.4", + sn => "SN", + }, + { + data => "Title text", + data_utf8_decoded => "Title text", + ln => "title", + nid => 106, + oid => "2.5.4.12", + sn => "title", + }, + { + data => "Description text", + data_utf8_decoded => "Description text", + ln => "description", + nid => 107, + oid => "2.5.4.13", + sn => "description", + }, + { + data => "Name text", + data_utf8_decoded => "Name text", + ln => "name", + nid => 173, + oid => "2.5.4.41", + sn => "name", + }, + { + data => "GivenName text", + data_utf8_decoded => "GivenName text", + ln => "givenName", + nid => 99, + oid => "2.5.4.42", + sn => "GN", + }, + { + data => "Initials text", + data_utf8_decoded => "Initials text", + ln => "initials", + nid => 101, + oid => "2.5.4.43", + sn => "initials", + }, + { + data => "dn.qualifier", + data_utf8_decoded => "dn.qualifier", + ln => "dnQualifier", + nid => 174, + oid => "2.5.4.46", + sn => "dnQualifier", + }, + { + data => "Role", + data_utf8_decoded => "Role", + ln => "role", + nid => 400, + oid => "2.5.4.72", + sn => "role", + }, + { + data => "generation_qualifier", + data_utf8_decoded => "generation_qualifier", + ln => "generationQualifier", + nid => 509, + oid => "2.5.4.44", + sn => "generationQualifier", + }, + { + data => "Pseudonym text", + data_utf8_decoded => "Pseudonym text", + ln => "pseudonym", + nid => 510, + oid => "2.5.4.65", + sn => "pseudonym", + }, + { + data => "x500_uniq_identifier", + data_utf8_decoded => "x500_uniq_identifier", + ln => "x500UniqueIdentifier", + nid => 503, + oid => "2.5.4.45", + sn => "x500UniqueIdentifier", + }, + ], + oneline => "/C=US/ST=State/L=City/O=Company/OU=Unit/CN=extended.server.cert/emailAddress=anyemail\@extended.server.cert/OU=Another Unit/OU=Yet Another Unit/SN=Surname text/title=Title text/description=Description text/name=Name text/GN=GivenName text/initials=Initials text/dnQualifier=dn.qualifier/role=Role/generationQualifier=generation_qualifier/pseudonym=Pseudonym text/x500UniqueIdentifier=x500_uniq_identifier", + print_rfc2253 => "x500UniqueIdentifier=x500_uniq_identifier,pseudonym=Pseudonym text,generationQualifier=generation_qualifier,role=Role,dnQualifier=dn.qualifier,initials=Initials text,GN=GivenName text,name=Name text,description=Description text,title=Title text,SN=Surname text,OU=Yet Another Unit,OU=Another Unit,emailAddress=anyemail\@extended.server.cert,CN=extended.server.cert,OU=Unit,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8 => "x500UniqueIdentifier=x500_uniq_identifier,pseudonym=Pseudonym text,generationQualifier=generation_qualifier,role=Role,dnQualifier=dn.qualifier,initials=Initials text,GN=GivenName text,name=Name text,description=Description text,title=Title text,SN=Surname text,OU=Yet Another Unit,OU=Another Unit,emailAddress=anyemail\@extended.server.cert,CN=extended.server.cert,OU=Unit,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8_decoded => "x500UniqueIdentifier=x500_uniq_identifier,pseudonym=Pseudonym text,generationQualifier=generation_qualifier,role=Role,dnQualifier=dn.qualifier,initials=Initials text,GN=GivenName text,name=Name text,description=Description text,title=Title text,SN=Surname text,OU=Yet Another Unit,OU=Another Unit,emailAddress=anyemail\@extended.server.cert,CN=extended.server.cert,OU=Unit,O=Company,L=City,ST=State,C=US", + }, + version => 2, +} diff --git a/t/data/testcert_key_2048.pem b/t/data/testcert_key_2048.pem new file mode 100644 index 0000000..f31b5b8 --- /dev/null +++ b/t/data/testcert_key_2048.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAvV7G2AH1z4X+65tg3eiKmAlZWnH8oq04cwrN2V7VbSMuAU6w +xxLrio4IgJuDaMC5/bgEMAsV/TapoZAKMI9tX4ESF7eQH0EweoUpB2lW7NNYnlki +9jggDZJFmXnEHiFqUxxSNLHVDE5BFVpBk3UT4P0BjPjiNC1wnHgD+yap/sTLWrwa +650/fC4+mixgZ/5JbTg4hXKNuim7zcmYZ6LW4nwRB5mJNyzDww5U/RIB+J6gHt/p +j1V0Gi72Hc5Xo9Vlvq/yGozqQuf46qtFEOiyH/evZI31tMqGJNOWC4Pzif88lqdW +JVktfOGACJRSU3GK1n4tTlyClS+gYnhZZQYBtwIDAQABAoIBAQCig9rb99qvjQw3 +wHHCH1YJokRXlWk9ZrECMax1Nqis77sEjjaxsbAIiVoMnOmKlZNIhYq6fFkTpLyx +FX9ZK02u34LabcM2v2hOTUbnwGRD/CCaTF7vtTz0yKoIS3KedQjdaHm4FUGEPQgn +vfx3AsvbkuWoyNK/+psg/PJVsFnFdD4yCTtfsQ7XcSBD3vsWorIR5h+TiWhUhLHn +EjmsDCVTbhSucYSTkLbOv4bOM7vBRV2esrzNBijrVCp1esdqG8BvCRO/t18XdDT2 +qtt4LhXGm7IVBe9NFjmRmkjhhCXQhcy+MIrh2Vlik/TriVqY9XI5Fl7/mOYBQxo0 +NKRIpL9ZAoGBANyq5oUQi12KlyOLtpFPGfbSozonxsqNlo5REqOPXqCXOveLqH50 +3LlRiOtrV2FUIcQfoCSGp4zEuXzGcIT0FGsyuDKacgwV9OS8B1IiIRYQodliDxNh +2G9BSoVtMHoQCqcF2OWWSmOFQ2EkO66bE25U4i9a0Z8syfulrkpRM3N1AoGBANux +AbdxYxUEDCYbpAbiZB3t2qQnOCQrs2yltgdv6TVtMJOSR8GFrIP5xiqkv35Spw73 +af5JNpKUUTGLc0Q0tSMnOktoANZzwjSgitwHTThBtOGG2pJUA04wG+QGzh4y0/42 +m+uX6ziXcGySvhYysG/Mr8JxXpyE7S07VMhe0Nb7AoGBAM6iNhSahnaEhbziYoY1 +VTHc0r5tauhXp4kC//orEcg9dRlDLPelhN8AK7+Pl5ZrSuc1Wid59EGMIclmpQzK +5qfvKa8xEuSgVt8t94kArozT7Er8WPOkZyDfOeIxefiDNwZqIk3y6xvAOXUokb6S +NqLVV6xSVgLA1S8RWWD8IrrVAoGADqVJOQJ9GXyQlsXG9JKJHBmsNr9Klda3+mk9 +rlc+k8o4r83TrMoNiyrOlC8xeOlnq67AySv2UGVE2Gm0gHqHDNXjo/1F+QX0j2+Y +cjymYDa5KUPFNHYXVlIMufHeMdMvoMXhNR6Glto5q3NI6s/sRTe/C9Zk+Ug/S4Gm +EEmJ4JsCgYBXPrCMarZQt7pihV0a9a37M2uUNQ125FFZB5FduPlX5hvz1sJiygeJ +zBM8OSuU8rxwgdr/kuQtLiHq77TDC4nwxPJ6yaVuWZZekXyZokS+etB75dg8VNNr +hp9rO3sH7EkDa7qwk5Ej1dJXt45iBc5iaxJAfPIL5SO6A0R4wAxVKw== +-----END RSA PRIVATE KEY----- diff --git a/t/data/testcert_key_2048.pem.e b/t/data/testcert_key_2048.pem.e new file mode 100644 index 0000000..271549e --- /dev/null +++ b/t/data/testcert_key_2048.pem.e @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,E28DC531E35ECB89F4E70551770E28DD + +JTfR0conc9awrr35SjVhrAC4KyiWRC1MlZYtVEJzKaeI22eYdJL2sIV3Xu2gbSNd +kRZCnruHpjYfE35etNEZCb69Aj3qCCcb+UjMekH+uOk4JMxOzB75dVGc5DnCFQbu +myHPiprL4ibQ3rs2mp9Dscl6YXMFhGdYa3XGc6hev7taqVykitWDKbMgb0Vgpdqq +5q2yyZzKhQhckjY/NCKTYOY/PWKEKvftqOAZI8obG4HJF9f75JcSmpa1QVEy6Qau +6e0lMSZ9D/le+VnZ4rqCOhU1WahhtpB6CQTuuRrUmr69cPiWltUiOUkoRziJhh8e +rHiXVEPGci7Nox1sxlO3xWJAVrQW9P2bmoxXXmBr8Fm7ZjEwAICdRb70y3HLQsLZ +6Zy9zdr5GUjVhGsm93snVvLJrm5pNuL68H17j05V2m0CT2RnS0q85iZQwJbuRkL/ +ukgHxZ6pXmS9IEJSUtjnekPEs4H+tKeZdSyyc35qTNZ5s1iCkpo3juTcy0wOEiOp +kPCzGNn1VVq8LGIOlKAlAfjULi16BMN9M6/tABLK13e5Rxq9viosJYlQIrcUiUAa +vxuGtCzFi3wyXmTKSa5dpBOOSDv9pzPcxQJyC8Ln+2YYAByF48hJQAK3jo6qAz1k +94zD1AgSIkHwceQYOw/E8xHIpLFiScESOMYwOFKftLjUs3DD7BUWZArSPZ/32NbY +2XtwWaXNvt2WozvGh0YMxjMI4ypEaVdxTLdi2Ejqbd6acYSOv/c+VTU3/Dbq4W+u +9hKXTtwUjElQeKvjuAzIcYXRLZ53RO0rvijMw2F+O27ymVzgsJGSY1077bLOPN7e +nOhIoCQanzAi89HvDYAPdcmUGCBhD0YE78lAxFQxlf3Rx408wwzl14TKjgFSJAVr +CCC/4HSqjrgw1YtcKHYtdQBDVtOVQdkaIBlt+SFKf04Di4dcfD/xsU+mq/FxIwBd +134tsQvOcEvouKPoHVLzFVcAw//1hUpLx4BPFE+dkdHX8AFECZDyTUks2j6NMJgb +i2eRVVdxVVFLLTW4iuW3qXGCADk+kcn2l6/+dl+2fvsReHGzAD0Pt2yz63G3dFuL +bOodcB6mrgAFqLtetldpc1ioX7KOJinZhtXw8+V7GQGno7GY9rbem77bbt1R1wCr +BaQmUYly/9tEmjn4XJfvH21HX9yIUpfFpACzMbGhVeQ3qClsNAcqvluL/bkqudVM +xrUn+iUiY1TM0toVS5+/w11nu9gn2IR0xGpmimE4cbiZRtxE/vFkm9Vtw1kdk0yR +EPbV3Z7MXLKWc7jqQ/L6r/geUbW4P+Vl2bbPK1RKkxn1KtEMITK3ag2y19K1Uj+w +0wpZi6YovC2ekNt/GjIvafbw1UOJb9L8fWxMflk2ndKmLMF4pF2G7C9+F1pdzTV0 +ouOQ28V6/7oxClBsH/UMKt/QJVRwOhEiriZfGH3OXWhZTnOCmmFjYpoNjVi3uXFl +nNi4pP/RG5inbymPQHIs8wSyfzC2qwSxY1lSR8d/JT0wcwnaXD75SzWU3QiaQ1Mc +1xQM4A9qp039QPmj2ENUzkma+917feEWYVyiQ2zw06zZfzA9WUodUdd+HwaemHSD +-----END RSA PRIVATE KEY----- diff --git a/t/data/testcert_simple.crt.der b/t/data/testcert_simple.crt.der new file mode 100644 index 0000000..c0e5138 Binary files /dev/null and b/t/data/testcert_simple.crt.der differ diff --git a/t/data/testcert_simple.crt.pem b/t/data/testcert_simple.crt.pem new file mode 100644 index 0000000..c36b304 --- /dev/null +++ b/t/data/testcert_simple.crt.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICXDCCAcWgAwIBAgIDEjRXMA0GCSqGSIb3DQEBBQUAMCsxCzAJBgNVBAYTAlVT +MQ4wDAYDVQQKEwVEZW1vMTEMMAoGA1UEAxMDQ0ExMB4XDTEyMDIwMTAwMDAwMFoX +DTM1MDMzMTIzNTk1OVowajELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVN0YXRlMQ0w +CwYDVQQHEwRDaXR5MRAwDgYDVQQKEwdDb21wYW55MQ0wCwYDVQQLEwRVbml0MRsw +GQYDVQQDExJzaW1wbGUuc2VydmVyLmNlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKP1gdEac7+0cOBA6XdrJx1HQnapyVdu2vuPBGqcwMkblR8Xr1S+PA4w +YEBLWr+lxOfqyQ06MLbD6L+l9JNzMf2xQ9O3ri7MLn4MSIqWb3GhPXADhLGu5Zg6 +XRm/hzo5Sns76PLWfNGP2odRr4wgesp0omrJ8mX+zjKTG2BAuinxAgMBAAGjTzBN +MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDAowXW3JXGnFY8SJCnQHA5cgHraMAsG +A1UdDwQEAwIF4DARBglghkgBhvhCAQEEBAMCBkAwDQYJKoZIhvcNAQEFBQADgYEA +tBy2oSyYEHZcRFa2FbfxTO+YO9jikcMhz+96BuObtipgrZWi0pLmiqcN8K+zhkgm +Z61lKLasC7ElklspkFXAG3JKk+jun/GbKNi1yTcLc6C3hzL5zj+RNPT1o1PuyLA7 +bfp/7FbMMHMmsQZC+yiwW/ZYeA4MGpBKOyS1resQTHU= +-----END CERTIFICATE----- diff --git a/t/data/testcert_simple.crt.pem_dump b/t/data/testcert_simple.crt.pem_dump new file mode 100644 index 0000000..0f7d411 --- /dev/null +++ b/t/data/testcert_simple.crt.pem_dump @@ -0,0 +1,160 @@ + +# exported via command: perl examples/x509_cert_details.pl -dump -pem t/data/testcert_simple.crt.pem > t/data/testcert_simple.crt.pem_dump +# hashref dumped via Data::Dump +{ + cdp => [], + certificate_type => 4145, + digest_sha1 => { + pubkey => pack("H*","3028c175b72571a7158f122429d01c0e5c807ada"), + x509 => pack("H*","3b508c923e7beebe635dead24e714f3854421f8b"), + }, + extensions => { + count => 4, + entries => [ + { + critical => 1, + data => "CA:FALSE", + ln => "X509v3 Basic Constraints", + nid => 87, + oid => "2.5.29.19", + sn => "basicConstraints", + }, + { + critical => 0, + data => "30:28:C1:75:B7:25:71:A7:15:8F:12:24:29:D0:1C:0E:5C:80:7A:DA", + ln => "X509v3 Subject Key Identifier", + nid => 82, + oid => "2.5.29.14", + sn => "subjectKeyIdentifier", + }, + { + critical => 0, + data => "Digital Signature, Non Repudiation, Key Encipherment", + ln => "X509v3 Key Usage", + nid => 83, + oid => "2.5.29.15", + sn => "keyUsage", + }, + { + critical => 0, + data => "SSL Server", + ln => "Netscape Cert Type", + nid => 71, + oid => "2.16.840.1.113730.1.1", + sn => "nsCertType", + }, + ], + }, + extkeyusage => { ln => [], nid => [], oid => [], sn => [] }, + fingerprint => { + md5 => "C2:37:93:E7:9F:04:14:18:9F:B0:51:FF:4E:97:A2:92", + sha1 => "3B:50:8C:92:3E:7B:EE:BE:63:5D:EA:D2:4E:71:4F:38:54:42:1F:8B", + }, + hash => { + issuer => { dec => 2914546923, hex => "ADB874EB" }, + issuer_and_serial => { dec => 1890711708, hex => "70B1F89C" }, + subject => { dec => 2279978609, hex => "87E5B671" }, + }, + issuer => { + count => 3, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "Demo1", + data_utf8_decoded => "Demo1", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "CA1", + data_utf8_decoded => "CA1", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/O=Demo1/CN=CA1", + print_rfc2253 => "CN=CA1,O=Demo1,C=US", + print_rfc2253_utf8 => "CN=CA1,O=Demo1,C=US", + print_rfc2253_utf8_decoded => "CN=CA1,O=Demo1,C=US", + }, + keyusage => ["digitalSignature", "nonRepudiation", "keyEncipherment"], + not_after => "2035-03-31T23:59:59Z", + not_before => "2012-02-01T00:00:00Z", + ns_cert_type => ["server"], + pubkey_alg => "rsaEncryption", + pubkey_bits => 1024, + pubkey_id => 6, + pubkey_size => 128, + serial => { dec => 1193047, hex => 123457, long => 1193047 }, + signature_alg => "sha1WithRSAEncryption", + subject => { + altnames => [], + count => 6, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "State", + data_utf8_decoded => "State", + ln => "stateOrProvinceName", + nid => 16, + oid => "2.5.4.8", + sn => "ST", + }, + { + data => "City", + data_utf8_decoded => "City", + ln => "localityName", + nid => 15, + oid => "2.5.4.7", + sn => "L", + }, + { + data => "Company", + data_utf8_decoded => "Company", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "Unit", + data_utf8_decoded => "Unit", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "simple.server.cert", + data_utf8_decoded => "simple.server.cert", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/ST=State/L=City/O=Company/OU=Unit/CN=simple.server.cert", + print_rfc2253 => "CN=simple.server.cert,OU=Unit,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8 => "CN=simple.server.cert,OU=Unit,O=Company,L=City,ST=State,C=US", + print_rfc2253_utf8_decoded => "CN=simple.server.cert,OU=Unit,O=Company,L=City,ST=State,C=US", + }, + version => 2, +} diff --git a/t/data/testcert_strange.crt.pem b/t/data/testcert_strange.crt.pem new file mode 100644 index 0000000..7f17704 --- /dev/null +++ b/t/data/testcert_strange.crt.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICyTCCAjKgAwIBAgIDEjRbMA0GCSqGSIb3DQEBBQUAMCsxCzAJBgNVBAYTAlVT +MQ4wDAYDVQQKEwVEZW1vMTEMMAoGA1UEAxMDQ0ExMB4XDTEyMDIwMTAwMDAwMFoX +DTEzMDgzMTIzNTk1OVowgbgxCzAJBgNVBAYTAlVTMRswGQYDVQQIExJTdGF0ZS9D +PVhZWi9PVT1hYmMxIDAeBgNVBAcTF0NpdHksQz1YWVosT1U9YWJjIEQuRS5GMUQw +QgYDVQQKDDtTVEFSVCAhIEAgIyAkICUgXiAmICogKCApICwgLiAtID8gOiBfIC8g +WyBdICIgJyB8IFwgPSArIEVORDEQMA4GA1UECwwHxb5sdXTDvTESMBAGA1UEAwwJ +xI1lcnZlbsO9MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpv4zJaHhIWnyn +lFh02Iih0Fyap32zfGvjpUmtegfwZarTtcRvsk4ZcCVPIAyb6uOm/Aw1j45jPrQo +hVGyL3xXDtBFUUVXIuIQMQhRbcd/8bGJSCNJLD+MViAhlfj0I392wT14i6OWh7g5 +sPHfyC3vmo7zpNV4nmBwZJ3Lru99hwIDAQABo20wazAMBgNVHRMBAf8EAjAAMB0G +A1UdDgQWBBQLKC3+aBCNLilibbbxm/jHluGgITALBgNVHQ8EBAMCBLAwEQYJYIZI +AYb4QgEBBAQDAgWgMBwGCWCGSAGG+EIBDQQPFg1hc2NpaSBjb21tZW50MA0GCSqG +SIb3DQEBBQUAA4GBADtG7WGAf0rXmYGddM1TgQO0xD39W4V+RjUpkTcHZsjYBkZ7 +d/Cyw9ejLCdtKWByy00JLWfJd12K4vvTswOKofl5iss0gMZ6La65Vl3unqdtLUFw +0LEItTTiRcNLN67ZxsI0TAyEUw5aTV/W9MDqKbBWZHUkHW68W8ozIHII1l5t +-----END CERTIFICATE----- diff --git a/t/data/testcert_strange.crt.pem_dump b/t/data/testcert_strange.crt.pem_dump new file mode 100644 index 0000000..4a34292 --- /dev/null +++ b/t/data/testcert_strange.crt.pem_dump @@ -0,0 +1,168 @@ + +# exported via command: perl examples/x509_cert_details.pl -dump -pem t/data/testcert_strange.crt.pem > t/data/testcert_strange.crt.pem_dump +# hashref dumped via Data::Dump +{ + cdp => [], + certificate_type => 4145, + digest_sha1 => { + pubkey => pack("H*","0b282dfe68108d2e29626db6f19bf8c796e1a021"), + x509 => pack("H*","af4f947a9521276579416937e202fa7a6ef40cd8"), + }, + extensions => { + count => 5, + entries => [ + { + critical => 1, + data => "CA:FALSE", + ln => "X509v3 Basic Constraints", + nid => 87, + oid => "2.5.29.19", + sn => "basicConstraints", + }, + { + critical => 0, + data => "0B:28:2D:FE:68:10:8D:2E:29:62:6D:B6:F1:9B:F8:C7:96:E1:A0:21", + ln => "X509v3 Subject Key Identifier", + nid => 82, + oid => "2.5.29.14", + sn => "subjectKeyIdentifier", + }, + { + critical => 0, + data => "Digital Signature, Key Encipherment, Data Encipherment", + ln => "X509v3 Key Usage", + nid => 83, + oid => "2.5.29.15", + sn => "keyUsage", + }, + { + critical => 0, + data => "SSL Client, S/MIME", + ln => "Netscape Cert Type", + nid => 71, + oid => "2.16.840.1.113730.1.1", + sn => "nsCertType", + }, + { + critical => 0, + data => "ascii comment", + ln => "Netscape Comment", + nid => 78, + oid => "2.16.840.1.113730.1.13", + sn => "nsComment", + }, + ], + }, + extkeyusage => { ln => [], nid => [], oid => [], sn => [] }, + fingerprint => { + md5 => "66:F4:35:3B:5E:0F:9D:49:B5:C3:62:8E:89:C5:CB:45", + sha1 => "AF:4F:94:7A:95:21:27:65:79:41:69:37:E2:02:FA:7A:6E:F4:0C:D8", + }, + hash => { + issuer => { dec => 2914546923, hex => "ADB874EB" }, + issuer_and_serial => { dec => 2845199978, hex => "A9964E6A" }, + subject => { dec => 2051971852, hex => "7A4E9B0C" }, + }, + issuer => { + count => 3, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "Demo1", + data_utf8_decoded => "Demo1", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "CA1", + data_utf8_decoded => "CA1", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/O=Demo1/CN=CA1", + print_rfc2253 => "CN=CA1,O=Demo1,C=US", + print_rfc2253_utf8 => "CN=CA1,O=Demo1,C=US", + print_rfc2253_utf8_decoded => "CN=CA1,O=Demo1,C=US", + }, + keyusage => ["digitalSignature", "keyEncipherment", "dataEncipherment"], + not_after => "2013-08-31T23:59:59Z", + not_before => "2012-02-01T00:00:00Z", + ns_cert_type => ["client", "email"], + pubkey_alg => "rsaEncryption", + pubkey_bits => 1024, + pubkey_id => 6, + pubkey_size => 128, + serial => { dec => 1193051, hex => "12345B", long => 1193051 }, + signature_alg => "sha1WithRSAEncryption", + subject => { + altnames => [], + count => 6, + entries => [ + { + data => "US", + data_utf8_decoded => "US", + ln => "countryName", + nid => 14, + oid => "2.5.4.6", + sn => "C", + }, + { + data => "State/C=XYZ/OU=abc", + data_utf8_decoded => "State/C=XYZ/OU=abc", + ln => "stateOrProvinceName", + nid => 16, + oid => "2.5.4.8", + sn => "ST", + }, + { + data => "City,C=XYZ,OU=abc D.E.F", + data_utf8_decoded => "City,C=XYZ,OU=abc D.E.F", + ln => "localityName", + nid => 15, + oid => "2.5.4.7", + sn => "L", + }, + { + data => "START ! \@ # \$ % ^ & * ( ) , . - ? : _ / [ ] \" ' | \\ = + END", + data_utf8_decoded => "START ! \@ # \$ % ^ & * ( ) , . - ? : _ / [ ] \" ' | \\ = + END", + ln => "organizationName", + nid => 17, + oid => "2.5.4.10", + sn => "O", + }, + { + data => "\xC5\xBElut\xC3\xBD", + data_utf8_decoded => "\x{17E}lut\xFD", + ln => "organizationalUnitName", + nid => 18, + oid => "2.5.4.11", + sn => "OU", + }, + { + data => "\xC4\x8Derven\xC3\xBD", + data_utf8_decoded => "\x{10D}erven\xFD", + ln => "commonName", + nid => 13, + oid => "2.5.4.3", + sn => "CN", + }, + ], + oneline => "/C=US/ST=State/C=XYZ/OU=abc/L=City,C=XYZ,OU=abc D.E.F/O=START ! \@ # \$ % ^ & * ( ) , . - ? : _ / [ ] \" ' | \\ = + END/OU=\\xC5\\xBElut\\xC3\\xBD/CN=\\xC4\\x8Derven\\xC3\\xBD", + print_rfc2253 => "CN=\\C4\\8Derven\\C3\\BD,OU=\\C5\\BElut\\C3\\BD,O=START ! \@ # \$ % ^ & * ( ) \\, . - ? : _ / [ ] \\\" ' | \\\\ = \\+ END,L=City\\,C=XYZ\\,OU=abc D.E.F,ST=State/C=XYZ/OU=abc,C=US", + print_rfc2253_utf8 => "CN=\xC4\x8Derven\xC3\xBD,OU=\xC5\xBElut\xC3\xBD,O=START ! \@ # \$ % ^ & * ( ) \\, . - ? : _ / [ ] \\\" ' | \\\\ = \\+ END,L=City\\,C=XYZ\\,OU=abc D.E.F,ST=State/C=XYZ/OU=abc,C=US", + print_rfc2253_utf8_decoded => "CN=\x{10D}erven\xFD,OU=\x{17E}lut\xFD,O=START ! \@ # \$ % ^ & * ( ) \\, . - ? : _ / [ ] \\\" ' | \\\\ = \\+ END,L=City\\,C=XYZ\\,OU=abc D.E.F,ST=State/C=XYZ/OU=abc,C=US", + }, + version => 2, +} diff --git a/t/data/testcert_wildcard.conf b/t/data/testcert_wildcard.conf new file mode 100644 index 0000000..672b69c --- /dev/null +++ b/t/data/testcert_wildcard.conf @@ -0,0 +1,43 @@ +# testcert_wildcard.conf +# +# Instructions and configuration for creating a certificate with +# a wildcard name and some extensions to test +# +# Use the commands below to first create a certificate signing request +# and then sign it. +# +# First time only: Create a serial file and private key. The same +# serial and key files can also be used for other test +# certificates. Note: uses current date in initial serial number. +# +# test -e test_CA1.srl || echo 2017121800 | tee test_CA1.srl +# test -e testcert_key_2048.pem || openssl genrsa -out testcert_key_2048.pem 2048 +# +# openssl req -new -key testcert_key_2048.pem -text -config testcert_wildcard.conf -out testcert_wildcard.csr.pem +# openssl x509 -req -CA test_CA1.crt.pem -CAkey test_CA1.key.pem -CAserial test_CA1.srl -days 5480 -text -in testcert_wildcard.csr.pem -extfile testcert_wildcard.conf -out testcert_wildcard.crt.pem + +basicConstraints=critical,CA:FALSE +extendedKeyUsage=serverAuth,clientAuth +certificatePolicies=1.2.4.5, 1.1.3.4 +subjectAltName=@subject_alt_section +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +[subject_alt_section] +DNS=*.example.com +email=wildcard@example.com +IP.1=10.20.30.40 +IP.2=2001:db8:148:100::31 + +[ req ] +distinguished_name = req_distinguished_name +prompt = no + +[ req_distinguished_name ] +C = US +ST = State +L = City +O = Company +OU = Unit +CN = *.example.com +emailAddress = wildcard@example.com diff --git a/t/data/testcert_wildcard.crt.pem b/t/data/testcert_wildcard.crt.pem new file mode 100644 index 0000000..7270c0c --- /dev/null +++ b/t/data/testcert_wildcard.crt.pem @@ -0,0 +1,79 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 137826015233 (0x2017121801) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = Demo1, CN = CA1 + Validity + Not Before: Dec 18 17:15:18 2017 GMT + Not After : Dec 19 17:15:18 2032 GMT + Subject: C = US, ST = State, L = City, O = Company, OU = Unit, CN = *.example.com, emailAddress = wildcard@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bd:5e:c6:d8:01:f5:cf:85:fe:eb:9b:60:dd:e8: + 8a:98:09:59:5a:71:fc:a2:ad:38:73:0a:cd:d9:5e: + d5:6d:23:2e:01:4e:b0:c7:12:eb:8a:8e:08:80:9b: + 83:68:c0:b9:fd:b8:04:30:0b:15:fd:36:a9:a1:90: + 0a:30:8f:6d:5f:81:12:17:b7:90:1f:41:30:7a:85: + 29:07:69:56:ec:d3:58:9e:59:22:f6:38:20:0d:92: + 45:99:79:c4:1e:21:6a:53:1c:52:34:b1:d5:0c:4e: + 41:15:5a:41:93:75:13:e0:fd:01:8c:f8:e2:34:2d: + 70:9c:78:03:fb:26:a9:fe:c4:cb:5a:bc:1a:eb:9d: + 3f:7c:2e:3e:9a:2c:60:67:fe:49:6d:38:38:85:72: + 8d:ba:29:bb:cd:c9:98:67:a2:d6:e2:7c:11:07:99: + 89:37:2c:c3:c3:0e:54:fd:12:01:f8:9e:a0:1e:df: + e9:8f:55:74:1a:2e:f6:1d:ce:57:a3:d5:65:be:af: + f2:1a:8c:ea:42:e7:f8:ea:ab:45:10:e8:b2:1f:f7: + af:64:8d:f5:b4:ca:86:24:d3:96:0b:83:f3:89:ff: + 3c:96:a7:56:25:59:2d:7c:e1:80:08:94:52:53:71: + 8a:d6:7e:2d:4e:5c:82:95:2f:a0:62:78:59:65:06: + 01:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Certificate Policies: + Policy: 1.2.4.5 + Policy: 1.1.3.4 + + X509v3 Subject Alternative Name: + DNS:*.example.com, email:wildcard@example.com, IP Address:10.20.30.40, IP Address:2001:DB8:148:100:0:0:0:31 + X509v3 Subject Key Identifier: + 4B:42:86:BA:E2:BE:3D:40:0D:11:1D:66:E7:BE:94:39:B2:84:D3:06 + X509v3 Authority Key Identifier: + keyid:C8:1C:DA:92:0A:A9:48:08:3A:76:76:15:38:04:F1:34:D9:15:D0:20 + + Signature Algorithm: sha256WithRSAEncryption + 20:cb:ec:9d:8b:e8:2d:61:74:5e:30:b0:95:88:4e:80:09:df: + c9:7f:b0:c9:d2:19:4e:2c:5a:eb:02:0f:ce:e8:8a:52:fa:22: + 59:b1:c3:7b:39:db:f0:7d:9a:91:19:ef:d5:f7:73:5b:6b:47: + 3d:48:c3:c7:4a:2e:7b:7f:3d:ff:65:53:11:21:95:2c:00:fd: + 39:76:25:8e:05:68:c4:b9:cc:bd:ca:28:60:bf:6d:4c:00:d0: + 4e:b4:4c:62:6b:34:48:2c:60:b9:33:76:3f:3b:72:57:11:ec: + f4:2d:5f:b3:f1:a1:c8:d4:5b:5f:23:6b:b0:ec:28:5a:0b:43: + 7f:e3 +-----BEGIN CERTIFICATE----- +MIIDhjCCAu+gAwIBAgIFIBcSGAEwDQYJKoZIhvcNAQELBQAwKzELMAkGA1UEBhMC +VVMxDjAMBgNVBAoTBURlbW8xMQwwCgYDVQQDEwNDQTEwHhcNMTcxMjE4MTcxNTE4 +WhcNMzIxMjE5MTcxNTE4WjCBijELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRl +MQ0wCwYDVQQHDARDaXR5MRAwDgYDVQQKDAdDb21wYW55MQ0wCwYDVQQLDARVbml0 +MRYwFAYDVQQDDA0qLmV4YW1wbGUuY29tMSMwIQYJKoZIhvcNAQkBFhR3aWxkY2Fy +ZEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1e +xtgB9c+F/uubYN3oipgJWVpx/KKtOHMKzdle1W0jLgFOsMcS64qOCICbg2jAuf24 +BDALFf02qaGQCjCPbV+BEhe3kB9BMHqFKQdpVuzTWJ5ZIvY4IA2SRZl5xB4halMc +UjSx1QxOQRVaQZN1E+D9AYz44jQtcJx4A/smqf7Ey1q8GuudP3wuPposYGf+SW04 +OIVyjbopu83JmGei1uJ8EQeZiTcsw8MOVP0SAfieoB7f6Y9VdBou9h3OV6PVZb6v +8hqM6kLn+OqrRRDosh/3r2SN9bTKhiTTlguD84n/PJanViVZLXzhgAiUUlNxitZ+ +LU5cgpUvoGJ4WWUGAbcCAwEAAaOB0TCBzjAMBgNVHRMBAf8EAjAAMB0GA1UdJQQW +MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAXBgNVHSAEEDAOMAUGAyoEBTAFBgMpAwQw +RgYDVR0RBD8wPYINKi5leGFtcGxlLmNvbYEUd2lsZGNhcmRAZXhhbXBsZS5jb22H +BAoUHiiHECABDbgBSAEAAAAAAAAAADEwHQYDVR0OBBYEFEtChrrivj1ADREdZue+ +lDmyhNMGMB8GA1UdIwQYMBaAFMgc2pIKqUgIOnZ2FTgE8TTZFdAgMA0GCSqGSIb3 +DQEBCwUAA4GBACDL7J2L6C1hdF4wsJWIToAJ38l/sMnSGU4sWusCD87oilL6Ilmx +w3s52/B9mpEZ79X3c1trRz1Iw8dKLnt/Pf9lUxEhlSwA/Tl2JY4FaMS5zL3KKGC/ +bUwA0E60TGJrNEgsYLkzdj87clcR7PQtX7PxocjUW18ja7DsKFoLQ3/j +-----END CERTIFICATE----- diff --git a/t/data/testcert_wildcard_CA1_2048.crt.pem b/t/data/testcert_wildcard_CA1_2048.crt.pem new file mode 100644 index 0000000..bd7f916 --- /dev/null +++ b/t/data/testcert_wildcard_CA1_2048.crt.pem @@ -0,0 +1,89 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 137858712322 (0x2019050302) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = Demo1, CN = CA1 + Validity + Not Before: May 2 21:25:06 2019 GMT + Not After : May 3 21:25:06 2034 GMT + Subject: C = US, ST = State, L = City, O = Company, OU = Unit, CN = *.example.com, emailAddress = wildcard@example.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:bd:5e:c6:d8:01:f5:cf:85:fe:eb:9b:60:dd:e8: + 8a:98:09:59:5a:71:fc:a2:ad:38:73:0a:cd:d9:5e: + d5:6d:23:2e:01:4e:b0:c7:12:eb:8a:8e:08:80:9b: + 83:68:c0:b9:fd:b8:04:30:0b:15:fd:36:a9:a1:90: + 0a:30:8f:6d:5f:81:12:17:b7:90:1f:41:30:7a:85: + 29:07:69:56:ec:d3:58:9e:59:22:f6:38:20:0d:92: + 45:99:79:c4:1e:21:6a:53:1c:52:34:b1:d5:0c:4e: + 41:15:5a:41:93:75:13:e0:fd:01:8c:f8:e2:34:2d: + 70:9c:78:03:fb:26:a9:fe:c4:cb:5a:bc:1a:eb:9d: + 3f:7c:2e:3e:9a:2c:60:67:fe:49:6d:38:38:85:72: + 8d:ba:29:bb:cd:c9:98:67:a2:d6:e2:7c:11:07:99: + 89:37:2c:c3:c3:0e:54:fd:12:01:f8:9e:a0:1e:df: + e9:8f:55:74:1a:2e:f6:1d:ce:57:a3:d5:65:be:af: + f2:1a:8c:ea:42:e7:f8:ea:ab:45:10:e8:b2:1f:f7: + af:64:8d:f5:b4:ca:86:24:d3:96:0b:83:f3:89:ff: + 3c:96:a7:56:25:59:2d:7c:e1:80:08:94:52:53:71: + 8a:d6:7e:2d:4e:5c:82:95:2f:a0:62:78:59:65:06: + 01:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Certificate Policies: + Policy: 1.2.4.5 + Policy: 1.1.3.4 + + X509v3 Subject Alternative Name: + DNS:*.example.com, email:wildcard@example.com, IP Address:10.20.30.40, IP Address:2001:DB8:148:100:0:0:0:31 + X509v3 Subject Key Identifier: + 4B:42:86:BA:E2:BE:3D:40:0D:11:1D:66:E7:BE:94:39:B2:84:D3:06 + X509v3 Authority Key Identifier: + keyid:04:AA:D2:DA:BA:F8:27:37:1F:CC:D1:5D:E6:35:D6:1A:B0:FF:A3:9E + + Signature Algorithm: sha256WithRSAEncryption + 41:ac:0b:fc:0c:dc:8c:d7:85:3e:53:56:79:ce:c0:21:dc:0a: + d4:ac:f5:82:2e:fb:3e:b2:6c:3f:b7:dd:c4:7c:f8:03:d5:df: + 4c:b0:38:b9:4d:85:5f:92:8e:ce:c4:b9:97:38:86:51:b4:4c: + 46:5d:87:34:df:ae:c0:42:df:0c:dc:7b:16:19:08:88:70:2c: + 27:e8:4c:b7:9b:0a:07:a9:ee:39:94:0d:a3:21:fe:e0:da:ff: + f6:67:cd:9d:fc:f8:a8:32:5b:14:c9:aa:b2:f6:17:1a:74:06: + f8:46:67:de:5d:b4:63:e7:31:c6:7e:89:af:67:cc:c2:2c:f8: + 82:4a:a4:df:63:5d:e4:0f:22:d6:17:33:07:f6:9b:cb:82:23: + 38:ad:9c:6f:f3:28:8b:90:62:26:a1:ab:41:bf:28:9b:8f:cf: + 30:9f:ff:41:47:ad:f9:88:91:97:e7:de:5c:3f:61:90:65:b7: + 29:15:e5:72:fb:41:37:d9:3c:d7:ed:a4:9e:63:66:70:c9:f9: + 29:c6:63:da:87:cd:80:0f:a3:54:57:20:db:d8:10:6a:69:da: + e2:57:9e:24:1e:1a:36:0f:4b:a6:4f:8d:dc:4c:a4:8c:16:52: + a1:4d:71:9a:f8:f0:4d:9b:d9:7f:76:51:74:40:9d:68:21:0a: + 09:2c:9f:1c +-----BEGIN CERTIFICATE----- +MIIEBzCCAu+gAwIBAgIFIBkFAwIwDQYJKoZIhvcNAQELBQAwKzELMAkGA1UEBhMC +VVMxDjAMBgNVBAoMBURlbW8xMQwwCgYDVQQDDANDQTEwHhcNMTkwNTAyMjEyNTA2 +WhcNMzQwNTAzMjEyNTA2WjCBijELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRl +MQ0wCwYDVQQHDARDaXR5MRAwDgYDVQQKDAdDb21wYW55MQ0wCwYDVQQLDARVbml0 +MRYwFAYDVQQDDA0qLmV4YW1wbGUuY29tMSMwIQYJKoZIhvcNAQkBFhR3aWxkY2Fy +ZEBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1e +xtgB9c+F/uubYN3oipgJWVpx/KKtOHMKzdle1W0jLgFOsMcS64qOCICbg2jAuf24 +BDALFf02qaGQCjCPbV+BEhe3kB9BMHqFKQdpVuzTWJ5ZIvY4IA2SRZl5xB4halMc +UjSx1QxOQRVaQZN1E+D9AYz44jQtcJx4A/smqf7Ey1q8GuudP3wuPposYGf+SW04 +OIVyjbopu83JmGei1uJ8EQeZiTcsw8MOVP0SAfieoB7f6Y9VdBou9h3OV6PVZb6v +8hqM6kLn+OqrRRDosh/3r2SN9bTKhiTTlguD84n/PJanViVZLXzhgAiUUlNxitZ+ +LU5cgpUvoGJ4WWUGAbcCAwEAAaOB0TCBzjAMBgNVHRMBAf8EAjAAMB0GA1UdJQQW +MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAXBgNVHSAEEDAOMAUGAyoEBTAFBgMpAwQw +RgYDVR0RBD8wPYINKi5leGFtcGxlLmNvbYEUd2lsZGNhcmRAZXhhbXBsZS5jb22H +BAoUHiiHECABDbgBSAEAAAAAAAAAADEwHQYDVR0OBBYEFEtChrrivj1ADREdZue+ +lDmyhNMGMB8GA1UdIwQYMBaAFASq0tq6+Cc3H8zRXeY11hqw/6OeMA0GCSqGSIb3 +DQEBCwUAA4IBAQBBrAv8DNyM14U+U1Z5zsAh3ArUrPWCLvs+smw/t93EfPgD1d9M +sDi5TYVfko7OxLmXOIZRtExGXYc0367AQt8M3HsWGQiIcCwn6Ey3mwoHqe45lA2j +If7g2v/2Z82d/PioMlsUyaqy9hcadAb4RmfeXbRj5zHGfomvZ8zCLPiCSqTfY13k +DyLWFzMH9pvLgiM4rZxv8yiLkGImoatBvyibj88wn/9BR635iJGX595cP2GQZbcp +FeVy+0E32TzX7aSeY2ZwyfkpxmPah82AD6NUVyDb2BBqadriV54kHho2D0umT43c +TKSMFlKhTXGa+PBNm9l/dlF0QJ1oIQoJLJ8c +-----END CERTIFICATE----- diff --git a/t/data/testreq1.der b/t/data/testreq1.der new file mode 100644 index 0000000..1ba96df Binary files /dev/null and b/t/data/testreq1.der differ diff --git a/t/data/testreq1.pem b/t/data/testreq1.pem new file mode 100644 index 0000000..6444758 --- /dev/null +++ b/t/data/testreq1.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICCjCCAXMCAQAwRDELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0NvbXBhbnkxDTAL +BgNVBAsTBFVuaXQxFDASBgNVBAMTC1Rlc3RSZXF1ZXN0MIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDAMgwTy8Chs4Vqp7ceM8vish5H7rphVOpF+SNbb8nHzSGc +itOuJxmFOSjDv7+qwdiVqYhnHTItbM6yL+SsZ4deWM1sVqx5ZgJr9b+oyWHDgoEU +3w6GNuoKFVCI7lTClmdwFKISnVzzCZ1wzvIK0T75GGXvPxcdZXijuLvM0a6+wwID +AQABoIGFMB4GCSqGSIb3DQEJBzEREw9TZWNyZXQgUGFzc3dvcmQwJAYJKoZIhvcN +AQkCMRcTFVVuc3RydWN0dXJlZCBOYW1lIFh5ejA9BgkqhkiG9w0BCQ4xMDAuMAwG +A1UdEwEB/wQCMAAwCwYDVR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDANBgkq +hkiG9w0BAQUFAAOBgQASE7TRoU+HIZsno7NKDgjG8mMfUPahb25fmF2QzxUXWB1s +DDzICubFgv9kNX+pyUfeAz5q1f4/rEDfwGdf7gizwOg6DD9Cd0BfixHtOAgGunkV +oWCdqpHb0WXmS9LQemmNTCqS2Vpx3MXt9MuyPQ3JN7P1rotugr+72j/WJyKVKQ== +-----END CERTIFICATE REQUEST----- diff --git a/t/data/verisign.crl.der b/t/data/verisign.crl.der new file mode 100644 index 0000000..3f43ced Binary files /dev/null and b/t/data/verisign.crl.der differ diff --git a/t/data/verisign.crl.pem b/t/data/verisign.crl.pem new file mode 100644 index 0000000..932e197 --- /dev/null +++ b/t/data/verisign.crl.pem @@ -0,0 +1,1216 @@ +-----BEGIN X509 CRL----- +MILjkzCC4nswDQYJKoZIhvcNAQEFBQAwgboxCzAJBgNVBAYTAlVTMRcwFQYDVQQK +Ew5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29y +azE7MDkGA1UECxMyVGVybXMgb2YgdXNlIGF0IGh0dHBzOi8vd3d3LnZlcmlzaWdu +LmNvbS9ycGEgKGMpMDYxNDAyBgNVBAMTK1ZlcmlTaWduIENsYXNzIDMgRXh0ZW5k +ZWQgVmFsaWRhdGlvbiBTU0wgQ0EXDTEyMDMwODIxMDAxM1oXDTEyMDMxNTIxMDAx +M1owguGNMCECEAEHXgkUYOIimMXUJC3tBbMXDTExMDcwNzIxNDc0NFowIQIQAR7b +/JYRsc//JkqXxETdvRcNMTEwNjI1MDE0MjAzWjAhAhABKSs4AJXA3refnSt+o9/0 +Fw0xMTA0MTIyMDA2MzRaMCECEAE/SLiJouqloIKCthV4ET0XDTEwMDkwMzIxMDIx +NlowIQIQAUBDD4vGzxNOsm4LggGE4hcNMTIwMzA1MDkyODEzWjAhAhABSOtIh8Nv +Zm7P/meVq/WGFw0xMTA5MTQxNDQ2MDNaMCECEAFzgUmMr6/7ifWjNMXJWMkXDTEx +MTEwMTIxMzU0N1owIQIQAX05N+HHLpSk0mpX8McpJxcNMTAwNjIxMTE1NTA3WjAh +AhABfdo7FfwOW5ILfNguolTDFw0xMDA1MTQxNTA0MzRaMCECEAG3VTrBQkE83AQ0 +M+I4zoMXDTExMDMyNDE3NDczNlowIQIQAbhvClLbanIev89fystJ0xcNMTEwNDEz +MTkyMTQ0WjAhAhAB8D2a1rvWXHp/ZyA7UYrWFw0xMDA4MTMxMjQyMzFaMCECEAH8 +zFZUuHChsEmsgssJDHkXDTExMTAyNjE1MjM0M1owIQIQAlxY9dGEjXnYWZ5yjlcc +/hcNMTAwNzI5MTkxODU0WjAhAhACZtYTX98PqJ0Y07SMkWdNFw0xMTEwMDQwMDIx +NTVaMCECEAJrtAIH0SgIpxmFW0B8OWQXDTEyMDIyNDEzNTIyM1owIQIQAoKtmAnH +9Nyr1IEbPU5lvhcNMTEwNDEyMTMxNzI0WjAhAhACtfkwf7HleXVUII3ZepWDFw0x +MDA5MDgyMjM5MDdaMCECEAK77yAJS4ju1nEcql5HmQcXDTExMDYyMDE1NDAyNFow +IQIQAsllSsE77FIFsJN/3vCTMBcNMTIwMTA0MDE1NjMyWjAhAhAC3N9RKQMadQt3 +BTi1NxCmFw0xMTAxMjgxNzE3MDlaMCECEAL2Kq12gb/H/azN9mbViEAXDTEyMDEw +MzE4MTExN1owIQIQAvzjVOwxwihZ+XEtoNePvhcNMTAwNzE1MTkyODU1WjAhAhAC +/j+1PplmQRa5ERIrp4deFw0xMTA2MTMxMzQyMTJaMCECEAMXTdOplcGGpSPp52L+ +NZgXDTEyMDEzMDE2NDI1MFowIQIQAzgYpKRHmlM20T4oAbrT+RcNMTEwMTI0MTkx +NjAwWjAhAhADTFUUIiHbOGAR+L3P/2SlFw0xMTA4MDMxNTU1MzJaMCECEANOfo7o +zDT4OTVwA2V01Q8XDTExMDgxOTExNDYwOFowIQIQA1XJkQpiXLkzz3lxaFHU3BcN +MTEwNzI1MTkxMTE5WjAhAhADVlOQAVlKil0EmPTpDyQwFw0xMDAyMTExMzU5MDFa +MCECEANiOsEJo0XsWkCco+wX0LQXDTExMTExNzIyMjE0NFowIQIQA2W71Tc9TAQf +dEqnJHDWbxcNMTAwODAyMTAwMjI3WjAhAhADZbwz5GLl3uVtBziAezCeFw0xMTA4 +MTIxNDM5MjdaMCECEAN4cmDkTTO50CR9c9ORRWwXDTExMDMwMTE4MTE1MVowIQIQ +A4NKdE6WStY8Hqh1uNa3nRcNMTEwMTI1MTQ1NzAyWjAhAhADkZA+KmW63V33WO9+ +MozPFw0xMTAzMTAwMDM3NDJaMCECEAOU6w1dnocSzwSM9KwIe20XDTEyMDExODE0 +NDQ1NFowIQIQA6xcxQgYaQw4UVpKEDGXsBcNMTIwMTA3MTUwMjA4WjAhAhADrJrH +iYRiw4+ShmOkrB5rFw0xMTEwMDQxODQ0MjlaMCECEAO4UtcJp306G4KqheT1lg8X +DTExMDgyMzE3NTcyNFowIQIQA84oChxRsZerMDuIbVzZ0xcNMTEwODI1MDQwNTQw +WjAhAhAD7Z2CC9/F821lnXa2YZeQFw0xMTA2MDkxNDI1NDBaMCECEAQD4eyln3YN +/UhyuZ8u7WMXDTExMTExMDAxMDI0OFowIQIQBBv7UVyPflXzlJe5TK0FdhcNMTEx +MDA2MTg1MjIwWjAhAhAEJHXJJSXO6XXH102HRhwxFw0xMDEyMDkyMTM1MDBaMCEC +EAQ1ruJZHlJF+re/IB5BMvIXDTExMDMyMTIwMjcxMlowIQIQBFf7913VUIlx5KfR +woSNsBcNMTIwMjE0MTAwODA2WjAhAhAEY3aKQc7qjWyYsQME9ca9Fw0xMDA5MzAx +NTU5NDFaMCECEARu1ESMbBNhnODwpUghg44XDTExMDIyMjE1NDgwNVowIQIQBHQH +WweWUgR7PizHzGO1OhcNMTAwNTI2MTY0MjE4WjAhAhAEmZ/z5ZRbUUUSUtWIB3eL +Fw0xMTA5MjAxOTA4MjJaMCECEASgA5xqHppG7hcmgrz9SDgXDTEwMDkwMjA4NTAz +OFowIQIQBMnIEOFL8y3mbAUqnNgjWRcNMTEwODA4MjEyMjMxWjAhAhAEy5mcix3b +mCufBNPkmkB4Fw0xMTEwMTEwMDE2NDZaMCECEAT4IdfD3ct8mK6bZdIw6iQXDTEy +MDIyNDIwMzAyMFowIQIQBP0RSI/jstDzPVz6GM2J6xcNMTExMDI0MjI0NTU4WjAh +AhAFElWiETg29UnnY7yBzGIuFw0xMTEwMDcxODAzNTRaMCECEAVQI1I/XSGOWT7M +WbgvLQEXDTExMDMxNTE2NDMyNVowIQIQBVqAQa2fDHNE71olviJbzBcNMTExMjI4 +MTkyNDQ4WjAhAhAFXkjwjvsC/bZjjp+Z/KSLFw0xMDA3MjgxNzU1NTZaMCECEAVg +bE0Z6ZoGc2OkjnE0+t0XDTExMDQxMTE0MTA0NVowIQIQBWP6oP6I1/w4gS8rzNav +1BcNMTExMDE4MjAwNTI0WjAhAhAFj+a0G5nMpfesWWjgkQehFw0xMDA1MjYxNDU3 +MDBaMCECEAW6bUkT1P/jHHWq3Ch0x+MXDTExMDkyMzEyMDU1MVowIQIQBbsFq8QM +ytBvDDHB3cbKrBcNMTEwMjE3MTYzNDE5WjAhAhAFux1hkxurLxMNVbFM8qMPFw0x +MTA2MDMxNzEzMjFaMCECEAXHbvI/JYeEBsXO/fjSpAsXDTExMTIzMDA1NTMyMFow +IQIQBdApUZ6FVDw/IZs8nuLd7RcNMTIwMTI2MjEwMjU2WjAhAhAF6k2qbRNWA5ES +j1g5Hy1cFw0xMjAxMTAwNjMzNDdaMCECEAYJAM+ccJcQDIYgJm3gbDEXDTEwMDMx +MDE5MjYwM1owIQIQBhGaerYOm8G/qPQUla5NEhcNMTEwNDI3MTk1MDMyWjAhAhAG +EbCdo5XoE+k2EIi89fDZFw0xMTAyMDQxOTEyMTdaMCECEAZH+4IUN0INCY75SSgc +X3kXDTEwMDYyMjEwMzAxNlowIQIQBk/tWOFQedVV1uFBDPc8OxcNMTEwNTIwMTQy +MjUxWjAhAhAGZa+s3NUZay/o28bXoGjfFw0xMTExMjMxNzQyMzBaMCECEAZ8x8es +yRlg0riovvAsigUXDTEwMDkyNzE5NDkwM1owIQIQBn2K75pGwcjyUg5bFiYLNxcN +MTAwNTExMjE0ODMxWjAhAhAGf20ZOx3WlJX0qUCBGZbpFw0xMTAzMjQxODU3Mjda +MCECEAaYFl9KTLsUmGQecCkWzvcXDTExMTIwNjEyMjIwOFowIQIQBp0M6MIpnZBt +y9XbEsr3pBcNMTExMDE0MjAyMjIwWjAhAhAGq+p6HJ6RjxmD3FF4MnC7Fw0xMTAz +MjExNjU2MTlaMCECEAbQSbgjfwPPRptZZjgBm7oXDTEwMDUyODIzNDQ0MFowIQIQ +Bvdh1Rl+R44XSFRp1xie3xcNMTExMTA5MTg0MjE5WjAhAhAHBX6iSoHMym50/FEm +zMhhFw0xMjAxMjYxMzMxMDhaMCECEAcS4ro+oodUIUQA/YpGaO8XDTExMDkwNjE1 +NDAwMVowIQIQBySidp4UOfm5DAbR8iwZThcNMTExMTI0MDA0NjMzWjAhAhAHfQxa +A1ihjUC7TA/ENVmSFw0xMTExMDEyMTQ1MjVaMCECEAeAQ9BLxkgkvg7XKM+6HQYX +DTEyMDExNzIzMzg0N1owIQIQB4Q7/PbWqdeqDK+Dd7Cy0hcNMTIwMjAxMDEyMjE4 +WjAhAhAH1hKY7kSMAXzcn2Q7qQXFFw0xMTA5MDkxOTQ0MDFaMCECEAgJSI13rAmw +FkV/uG7HxGIXDTExMDYwNzA4NDYzM1owIQIQCBlMxC584o7TClK7xVAfgxcNMTEw +MTMxMTcwNTI5WjAhAhAILaBAhptYmAUFdDbgPH1tFw0xMTEyMDExNTAzMThaMCEC +EAhAyeHjLPD1MTIzYSo+4yUXDTEyMDIxOTE2MzkwNFowIQIQCEOKSlFT3UM4PLOX +rNnqLRcNMTEwMTIxMDE0MDQ1WjAhAhAIgqp9QX3XEx1TRhcciIPwFw0xMDAzMjIx +NjA3NDZaMCECEAiPw0bbOAxQEPN38wYNpTMXDTExMDIxNTExNDIxOFowIQIQCI/Z +KEYcvweGUipr+quddxcNMTEwODAzMTcwNjU5WjAhAhAIkYmrZSGtBVDB0rE5IlE3 +Fw0xMTEyMDcxNTM3NTNaMCECEAicGhc2HpMuouqy9GJS7DkXDTEyMDIxNzIyMTQw +MFowIQIQCNMJPtP69LLFdKfHvFfu1RcNMTExMjIzMDYwODA3WjAhAhAI01vxHLA6 +QAqR3wkVCE4HFw0xMTA4MTcyMTUwNDZaMCECEAjgODVfblCkiAiKjEUQHXwXDTEw +MTAxNTA4MDIyMVowIQIQCOl28Rn8tVZtYIPFvNAjkhcNMTEwNDI3MTk1MjQwWjAh +AhAJEYH3aE8KFVHCXLFhAuOKFw0xMTAzMDkyMzU5NTdaMCECEAkfgsqAOpdGsCUT +5+XAgvEXDTExMDYxNTE4NDM0NlowIQIQCTHs3sRUqAEvUP6TFE06ZxcNMTAxMjE3 +MTQxMzQyWjAhAhAJOQfiaxiL2kCkla9uCnVHFw0xMDExMTAwMDM0MzNaMCECEAlB +KBaUXmu0A5iRG63/vMUXDTEwMDkxMDE3NDYyNlowIQIQCU8t1K+I5SDUH/9THoq3 +KxcNMTEwNjEzMTQ0OTQxWjAhAhAJiFpqWuIfh0Nk2gDkdXfkFw0xMjAyMTYxNTAy +MTdaMCECEAm0jXgoQpWvlq4S1G0ph6YXDTEyMDExOTE1NTI0MlowIQIQCbXaKvCl +ar8D7CXe5NrdahcNMTEwNzI4MjI0MjE4WjAhAhAJvqRZSY0lnW8bXsN0uNIpFw0x +MDAyMTgxNzE4MTZaMCECEAnGSvPsQTccPEZPFYxjNVsXDTExMDQxNDE3MTkxM1ow +IQIQCd03AA+G8rLBfCz5pBTrdhcNMTEwNjMwMDAzMzAwWjAhAhAJ47FmXyKCvRaN +EkvMqNPOFw0xMjAyMTcxNDI2MDZaMCECEAnsvcw4GsOFC5kzRZi3l+EXDTExMTEw +MTIwNTYyNlowIQIQCftu+fG8WI5ODF1Dhh7KHBcNMTIwMTE5MTg0ODIxWjAhAhAK +J+l+lTQx7Tuy1tq6sNf+Fw0xMTA3MjkwNTM0NDJaMCECEAoqUS+pbIFVYEBkyLAG +gmgXDTExMTAwMzIzMDczOVowIQIQCi3Fk8oZMrxLrSDYDyKLQBcNMTExMjI5MTcy +MjIyWjAhAhAKMIvEG9Zctn6KghRV6xGAFw0xMjAyMTQxNzI2MzRaMCECEAo6jkGa +E8bpB7TF3duxIPkXDTExMDMwOTIwNTIyOFowIQIQCj7G9cbinyCydqx5cBElTRcN +MTEwNjE3MTUwMjIyWjAhAhAKW02zKqXcv8N4Om1n9aBjFw0xMTEyMDYxNjM5NTVa +MCECEApg8h5EsXY0mOxK7ICHBtEXDTExMDgwNDE5MjI0OFowIQIQCm684ZWvyPJV +lHBq4FFw3xcNMTAxMjE3MDAxNzAyWjAhAhAKgTkNWmXeosPpx4XCYRNdFw0xMTA5 +MDYxNTQwMTFaMCECEAqISvqYQY8UA2fSrU6CdzAXDTExMDIwNzE2MjIxN1owIQIQ +Css/27OHnXrLKSqE0y/jlBcNMTEwNjE2MDA1MzA1WjAhAhAK1DY1oZKjYiKYDcnR +dzQeFw0xMjAyMDExNzA2NDNaMCECEArv1rFg9sLTD8AxxCUUmucXDTExMDkxNDIz +MDIxMlowIQIQCwHkIvwj6ILVW4Auozs0TBcNMTEwNTE4MTExNDU4WjAhAhALFYS6 +5nJ5IRagk6f8sGIMFw0xMTEwMDExMDU4MTVaMCECEAse5Vh2h9wfgtmbzjOrLJYX +DTEwMTEwMjE5MDMxN1owIQIQCyUtFtbR7jELnAo0FPDgxBcNMTExMDExMjAwNDI3 +WjAhAhALJnAmnrqT70J+UfnQTL+QFw0xMDA0MjcxODU4NDJaMCECEAstvEyxz11J +EQIeUrPACvEXDTExMDExMTAxMjIwN1owIQIQCz/FaVk83zucIORN5hkBcRcNMTEw +NDEzMTc1NTUwWjAhAhALcpI+BqJOlm9GF7QRfBZ0Fw0xMDA0MzAyMDU5MDZaMCEC +EAuwaoyi6ZbxVGi0BtmRUAEXDTExMDMwNDAyNDMxM1owIQIQC7DAK5X/VjThNnQK +lcnWzxcNMTEwNTAyMDc0MjE3WjAhAhALwgU6MFhHncqO0N3VOrUvFw0xMTAzMTgw +NzA1MjJaMCECEAvGZRjR7hJSCwziLJvi6sgXDTEyMDMwNjAzMzYzNVowIQIQC9Rk +6aBTekBRtVQi4I6CrRcNMTExMjI2MTc0NDQ4WjAhAhAMFTvJ3zPY39+X8DTqbyk1 +Fw0xMDA5MDkxOTU1MzVaMCECEAwynJ3wEL7bxmW3c/Oqi/EXDTEyMDEyNTIyMzg0 +MlowIQIQDFAHCRoO6If9JMFZzSXrQxcNMTEwNzAxMTAxNzEwWjAhAhAMXuW9NwVl +DqSUBJonwFyKFw0xMTA0MTMxNzI0NTRaMCECEAxyoDx5f40ckZinm7yPsOMXDTEx +MDQwNTE1MzI1OVowIQIQDJtWUQ6UJAXRMq5hl7V8LhcNMTAxMTEwMTI0NzExWjAh +AhAM5rGGiBHSFS02+SE41Go9Fw0xMTA2MzAwMDI1NDRaMCECEA0JbgAyfcOxHSoJ ++AkiAXgXDTEyMDIwNzE0NDkwMFowIQIQDQ0b8WzrQjUJzyNHPBLHCxcNMTIwMTEz +MDAxOTI3WjAhAhANDqvr6zaP1rjb1dgF76DFFw0xMTA1MDkyMjE1NThaMCECEA0U +2yDnYZCKHhDVCQMUHngXDTExMDQyNTE1NTgwMFowIQIQDShYvITeoyLnGSu15jgq +6xcNMTEwMzE2MTMyNTQ5WjAhAhANLQ/uyRwqjeydnUF7OprkFw0xMTA3MjgyMDUy +MTZaMCECEA0ulsGYdgW745YTJx4Gh1EXDTExMTIxMzE5NTcyOVowIQIQDTGGzFM+ +9kuAhMZBKR/BHRcNMTIwMTMxMTUzMzA0WjAhAhANSaOcJ2QKjTkAeELlYofMFw0x +MTEwMDcwMjI4MDBaMCECEA1STxzpOHpGzPHH+caot9IXDTExMTAyNDE5MjIxM1ow +IQIQDYinrFVRKd3EXZtrB/WiXBcNMTAwNzE1MTk0MjA3WjAhAhANi6LbFNtnJ7By +QB3So+LwFw0xMTExMTUxODA2NTdaMCECEA2Vr7fbsezjDZS/JOjiyUIXDTExMTAy +NDE1MzkwMFowIQIQDbgAvrD6He6C09j3l2HTrxcNMTEwMzA5MjEwNTEyWjAhAhAN +vq4lz6DmN0RBl/EYXVLnFw0xMTA3MjkxNTQ2MDdaMCECEA3G4yc7OiSCyx/R+6vw +xuoXDTExMDkxMzE2NTAwMlowIQIQDegLsjAgLjb4Ft+y5kkMdRcNMTIwMjI5MTMz +MTMzWjAhAhAN65GKXBFAZWChHQ2RDgKWFw0xMTA3MzExODUxMTVaMCECEA3voKS8 +81BBXiipoP7khpAXDTExMDkyNjE1MjgyNVowIQIQDfYme6SAErUjhrpMxTn3yRcN +MTExMjA3MjIzODM1WjAhAhAN+F4S0+TmLrvkx0Y3wh8JFw0xMDAzMjYxMDQ5MzZa +MCECEA38Q1Q6Z0cqvPVdl+IksOEXDTExMDcxNDAwMjIwNVowIQIQDgSB512wjHea +LcFYrFMCBBcNMTAwOTE1MjM0MjA3WjAhAhAOdVBiqvig+qKB/aCEB17vFw0xMjAx +MTMwMDQ3MzZaMCECEA6AVJicA2bgkG6KBn3zIYsXDTEwMTIyMDIwMjI1MlowIQIQ +DpQ2eB9bTYLeelVS3IYLVRcNMTEwNDI3MTk1ODA5WjAhAhAOpz50wlqcCb1BzcLK +6dsJFw0xMTA1MDkxNzA5NDdaMCECEA8I4dlSJNoNOkQ4IxH4zWcXDTEwMDcxNjE2 +MzczM1owIQIQDxhO5disXDBzkDTDKad8uxcNMTExMDE4MjAxNjA4WjAhAhAPQL9x +DXcQkTIaM5VvMbjZFw0xMTA4MjMxNzQzNTZaMCECEA9E4ahxTaCZGIsCgoGZIxYX +DTEwMDIxODA5NDkxOVowIQIQD1oScOY98Dq6teF8sWrCTBcNMTAwNTE0MTUwMzMx +WjAhAhAPYVjd/gK6IFNq87pjvcZ7Fw0xMTExMDkyMzMyMDFaMCECEA+DfOaPEX6z +u28E5aWMdKYXDTExMDgxMDEzMzY1MFowIQIQD4yjWhyNxgks7aFYi4/7ixcNMTEx +MjAyMTQzNDU3WjAhAhAPn0VxTFrGjOHBmNiZUmDcFw0xMjAyMjQwNzE1MTdaMCEC +EA+fbWOMHLa0JJp6Mpg1BmUXDTExMTExNzIyMjIwM1owIQIQD7UMwNk0bhmNkH/y +E2ISSBcNMTExMTIxMDgyNzMyWjAhAhAPvPVmMZarPHzZzzJton3XFw0xMDA5MTAy +MjU5MTVaMCECEA+/W1WzO6jBHkYnjOOpjgsXDTEyMDIyMzE0MzEyMlowIQIQD+u0 +4wgsBpksRMZXi9UNlxcNMTExMTE4MTYyODA2WjAhAhAQV7XRGXVu0inwXfEKws7m +Fw0xMDA3MTkwNzE4MTlaMCECEBCYsqZ6P7hheelEGQMzng4XDTExMTExODE1NTMy +M1owIQIQELUivNsyZCz81fgaszSZ2hcNMTEwNTAyMTE0MDM0WjAhAhAQx8/Q8tNN +c5a0Bx3GlE9SFw0xMTAyMjQxOTA2NTdaMCECEBEPc7ZUku6pBRsCtjzjuhoXDTEx +MDgxNjAzMjEwN1owIQIQES++KrxJGz0gk+NRkHzEeBcNMTIwMjEyMTYyMjI1WjAh +AhARNA/xKzOsYZE4d/xhyB4+Fw0xMTEwMTcwODI2MDdaMCECEBE7XWq5DKrVan5u +MFEW+wgXDTEwMDgwMzE1Mjc1MFowIQIQET4U2J5Wfdqsi53xngz73xcNMTEwNTEx +MTE0ODE3WjAhAhARV7P2e4QMeZKepDQPjft4Fw0xMTAyMjgxMzU1MTVaMCECEBFt +MfPeHlaMpWRURzQ43fkXDTEyMDEyNTE5MjQyNFowIQIQEYMyTUl+8oHByx0Y7qqb +fBcNMTEwMTIwMDgyODAxWjAhAhARjI/a2QubvUj5fZOoYEArFw0xMjAxMTMyMDIw +NTlaMCECEBGPQURdnM34r5NmKnknKj8XDTExMDcyNTIzMDg0NVowIQIQEaVElnyt +97CdhxsKU9tNsxcNMTEwNTEyMTgyMTU1WjAhAhARvsydFxCDTdgp2WV4j4fJFw0x +MDEwMDgyMTUzMDhaMCECEBHT4gQeGs+kvKhi2uTLquEXDTExMTAxODIwMTQzN1ow +IQIQEdWQJB3hY5R8LQtEZxbx4hcNMTEwODE1MTAwOTA2WjAhAhAR2/uTcCJCb9sS +M8nD2HX1Fw0xMDA5MTQxNDI2MTZaMCECEBHpG4xcu5HwFYtoU8qBHq4XDTExMDMx +MTIwMDczMlowIQIQEfLt0EhAhu7rLBZC/9SZWhcNMTEwNjIwMTQzMzM0WjAhAhAS +HCCjlykObDzS/fc/obqyFw0xMTEwMTkxNzA1NDZaMCECEBIi0yGdkDG5ZUyfUjR7 +bLQXDTEyMDIwOTA0NDIxNlowIQIQEiosoeDIIPssNWJTlPYr5hcNMTAwODEwMTc1 +MzQyWjAhAhASLsTqOOycJRbz5ceFb0HaFw0xMTA4MjQxNDUyMDVaMCECEBIwZR9V +GXumHKWhGj9k9PMXDTEyMDEwNjIxMTQxMFowIQIQEkwzppl8eAp2kQL1J0IB/BcN +MTEwMzA5MTk1NDU4WjAhAhASb8NU4Q43C9vsk+TOua6TFw0xMTA5MTUxMzAwMzBa +MCECEBLBUMeKALmlHo8z7BqdD20XDTExMTIwNzIwNDY0MlowIQIQEsYfDmyADdwG +8Se8Rwc9dxcNMTEwNjIyMTU1NDA4WjAhAhASxrS+ii877vO/qQ9Xyz1/Fw0xMTA4 +MDkwNzIyMTdaMCECEBLJxleL3lMawxoLAlYSC+kXDTEyMDIwODE1MjMwM1owIQIQ +EuwVTHb0PVv9Kyz+W0MpVxcNMTExMDA0MTYwNTU5WjAhAhATCpyoWycQyCdAwccG +IHiIFw0xMTEyMDkxNTIyMzRaMCECEBMg/dvD+0JU2Qf1vDtEoLIXDTEyMDIyOTEy +MTIzM1owIQIQEzxapzV0xwt3xywUom9/XBcNMTAxMDAxMTg1NzMzWjAhAhATSEF4 ++MQKHfrxkZR+I6dHFw0xMTA1MDkxNTQyMzNaMCECEBNO7RFkR0ZwRIVYj8IbmGYX +DTEyMDExMDA2MzQwMlowIQIQE1zt895Rr4RzXEH5jcZbBBcNMTAxMjAzMTQyNzIx +WjAhAhATbihwk47xFz3dXzYayyqJFw0xMDEwMDQyMTE0MjVaMCECEBOWxamOPYFR +1vY86g618h4XDTExMDczMDIxNDY0NlowIQIQE5efhCCAqNKTHIOPzFD1HRcNMTEx +MjI5MjE0NTU0WjAhAhATsNH7BkiPVo+r0oq1ZjuDFw0xMTA3MjkxNjI4NTZaMCEC +EBPPbKq9d1HzpJ1vkrEIEiIXDTExMDIwOTA0NDgxOVowIQIQE9tZ+oR6C1DUGJ75 +FZH1YhcNMTEwMzA0MTEzODE0WjAhAhAUChFPETct0zfcjBOOsoJeFw0xMTEyMDUx +MTQ3NThaMCECEBQgC831lqySI6iw7BxpgMMXDTExMTAyMDE4NDgxNVowIQIQFCHk +VOdSOYe1TKHX39cDXBcNMTEwNzE0MDY0MjE2WjAhAhAUJUWoI9eEkScjuPMU6kzP +Fw0xMTEwMzExNDMyNDBaMCECEBQrrUxbupcLdpgzPJjpAK0XDTEwMDYxMDIwMDU0 +N1owIQIQFGcYY58yQNPO8bmKgpqfxxcNMTIwMjAxMTA1MjA2WjAhAhAUaeMoEGaW +s7ZWWCNHFxwjFw0xMTEwMTgyMDA1NDlaMCECEBRzZGqXhc/lw0FqQqOCEYkXDTEy +MDMwMTA2NDQwMFowIQIQFJ2dUB7G1LidLq5e5xh8fRcNMTIwMTEwMDQ1MzU5WjAh +AhAUosOOCoW0BNXQcXhYfNSsFw0xMTA1MDYxNDM4NTVaMCECEBSkFGYvyigPrrIF +//6lU6oXDTEwMDIxMTEzNTQzOVowIQIQFKdcpgtlgCU1UkIPumBKUBcNMTAxMTE1 +MTI0NDQxWjAhAhAUwkqvQrvQbpTjM7jnVFl3Fw0xMTEyMTQxNTA4NTdaMCECEBTI +u0JfU8iqgCrSCSnJEIIXDTExMTIyNjEzMDc0NVowIQIQFNf7AnOLKlGNm/2OVthe +vhcNMTExMDIxMTMxNzAzWjAhAhAU4TnGclYDUqOMkmceStBHFw0xMTA5MTUxMzAx +MDlaMCECEBTjT8kmkICTh8hpHAJfEU4XDTExMTAwNDE3MzA1NlowIQIQFR89kI7l +d3tE4qUkJT7vSRcNMTEwNDE0MTQyNjMxWjAhAhAVbVBbgNQ7d9Z27hY45QSpFw0x +MjAxMTcxNjE3MzVaMCECEBVzasOIHWSSHpJHPcTp0VQXDTExMDcwNzE2NTYzOVow +IQIQFYHRZB5O9piy/STJS8fQXhcNMTExMDAzMTI0NTUyWjAhAhAVg82JuApKKE2T +Md6l7L2WFw0xMTEyMTYwNDU4MDJaMCECEBWFvT65O/Scp8VOaQKtDN0XDTExMDQy +NzE5NTEwNlowIQIQFcaIV0JtEkGNpcYZ5Qv0gRcNMTExMDE4MjAxMjQ4WjAhAhAV +x7CGajTvnnszF1sluwRUFw0xMTAzMjQxODU3MjdaMCECEBXIkTo/9FQIQ2dg03vU +fGYXDTEwMDIxMDE2NDI0M1owIQIQFdQa8UGUQLtDaVhEcydA1BcNMTEwNDEzMjIz +NjI4WjAhAhAV8V460PP4pcoz6OABH+NpFw0xMDA2MjgwNDM3MzZaMCECEBYCPuoc +bz+Lf3o0gv3bPeMXDTEyMDIyNDA2NDgyN1owIQIQFiebfI3BL4rPoLRHKh3ZoRcN +MTEwNTI0MTUxOTA3WjAhAhAWKFzK+z3xRnrE0AuOHUqwFw0xMjAyMDkwNDQyMTRa +MCECEBYptmSmCTRRMBcbECzMKDcXDTEwMTEwMTE1MTYxNFowIQIQFjXmsq4YbU2l +WRDhaGC2yRcNMTExMDIwMTUyNzUyWjAhAhAWO+do9yJUgY6YC4vcvMIaFw0xMTEy +MTMxOTQxNDNaMCECEBZ3T4XxcHdD0HUvNGc2mXAXDTExMTEzMDExMjYzMVowIQIQ +Fou0X4XYKOt4b4G+I86FbRcNMTEwOTIwMDgzMTM2WjAhAhAWlI7/H/WmxOx0S4lE +9qWpFw0xMTA1MjMxNTQ1MjBaMCECEBafvYoT5iiWNkTlyNbX/TkXDTExMDUyMjA5 +MDIwMlowIQIQFqqG8sfTraw9R8CDkqU0XxcNMTIwMjA4MTUwMjM4WjAhAhAWt9so +xdkalfA+Oo8QcOYzFw0xMTAzMTgwODU0MDRaMCECEBbR3IBXr1nPxslGlKKGf2YX +DTEyMDEzMTA5MDMyOFowIQIQFvzQ4TucP/HFJsNZ5oDPdhcNMTExMjA3MTcyMjQz +WjAhAhAXEGhDGf2IDEvwWbuku/OdFw0xMTA0MjEwMDM1MTJaMCECEBcYP/dXWWwS +JR8E5zLd9xMXDTExMTAyNjE1NDA1MlowIQIQFz6qvNqn9OydbYMVF4fW6RcNMTEw +NjMwMTAyNDE5WjAhAhAXbV5AqKMFPkPDbk5SpKWEFw0xMjAyMjkxMjExMTRaMCEC +EBdxf1xnxhXDH/Uq/e9D8d8XDTExMTAxODIwMDkwOVowIQIQF3IIoYuytDDJIhu3 +F3yU/RcNMTIwMjI3MjE0MjI5WjAhAhAXfV6eZFuPqiJ0WZAV7QrHFw0xMDAzMTAx +OTI0MzFaMCECEBeLlfIPdp2qdPe0mg4Eq4MXDTEyMDEyNTE0MDc1MlowIQIQF5rg +9Rz+mvfnWFVysFMV2RcNMTExMTE0MTM0MjMzWjAhAhAXr7g1dH5T5krcgB0nBJtH +Fw0xMTAxMjgxODA4MzVaMCECEBfE+p8zqubSt8QJcAlSaO8XDTEyMDIyOTEyMTM0 +MVowIQIQF8cuv05t1MFDMZhJvtRcKRcNMTEwNDI2MTg0NjI1WjAhAhAX0fBvqYGT +3TdLueSO3t/lFw0xMTAzMDkwMTM4MzRaMCECEBfbGXdknEEEJRJXjfq5lvcXDTEy +MDExMjIyNTQzNlowIQIQF+uy3pWQ/grz4kLQRWjbqxcNMTExMDMxMTQzMzM0WjAh +AhAX+vFvxFlUS126JiU13r8LFw0xMTEwMjExNDQ5MzFaMCECEBgHqw0a1we3+ZwV +K1KYhHsXDTEwMDYyNDE5MTg1M1owIQIQGBGkEYiJyEt0uOC2ls9i9RcNMTAwMzE3 +MjE1NDUzWjAhAhAYE1EW/3GhUOmt/tCvmXcHFw0xMTA2MzAwMDI5MjRaMCECEBgW +7g/FOyWVU2QY61JpK2MXDTExMDYwOTEzMzE1MFowIQIQGEaki7gOudyUUL4rKHbh +mhcNMTExMjAzMTY0ODU1WjAhAhAYW8i5Z6GI+ObOG+DZdDY5Fw0xMjAzMDUxMTM0 +MTVaMCECEBheVK5A+m/Iuu3p5mBhGEsXDTEwMDQxNDIxMDc0OVowIQIQGGwdbXfh +P6lhA4DuxxMl8xcNMTExMDE4MjAwNzMwWjAhAhAYcSKPgiuPQQjzzrOe5LclFw0x +MDA1MjcxNjUzMDJaMCECEBjE4ZOzNWHMvI/DILPWz0MXDTEyMDIyMDIzMjQ0N1ow +IQIQGPmfA94fnPACRxF+pz0nIxcNMTIwMTE5MTg0NTI2WjAhAhAY+c0uu1stTnT/ +vRE30m9tFw0xMTEwMDYxMzA5NDBaMCECEBj84nNJbwmy2D1djJiNa2gXDTEwMDUx +MzE1NTkxOVowIQIQGSiIqNbNDtFApCm0wUOXmBcNMTEwODMwMTAzNDU0WjAhAhAZ +Mzt4QC4JtdF2uR5h2sMJFw0xMTExMDMxODQ0MzVaMCECEBlHfSpPljMHRnrNILLT +oloXDTEyMDIyOTEyMDMyN1owIQIQGVN+c5h7LBYANM9flSylOhcNMTEwMTE3MTIx +MzMxWjAhAhAZVv+0VDUW1U9eI1OTgxLaFw0xMTA2MTgwOTQyMDFaMCECEBleDMP+ +xvETS1E0ebaHzbAXDTExMDIxNzIzMTkyMVowIQIQGWeZi0ndR9+/7OCGFl4R4RcN +MTAwNDIzMTQ0MTQxWjAhAhAZcaI4hvkEUIkFt2XD6/YcFw0xMjAyMTIwOTAwMDZa +MCECEBmBwKPXZQzDFW5T1wQyJ8MXDTExMTIyMTE4NDkzOFowIQIQGYyl2jhVEh3c +/LV6y5JA/RcNMTExMjEyMTM0NjQzWjAhAhAZnHFSkgDiz0tWiw0gWqy/Fw0xMTAz +MTExNjA1NTJaMCECEBmqXyY6wikqCToPr/V3HNYXDTEwMDIyMzEzNTYyOVowIQIQ +Gazjpo521eCzbJUJi4vwORcNMTAwNTA3MjMzNTU2WjAhAhAZyYdYq6WWcU7yV4e1 +U3TRFw0xMTEyMTkyMTUwMTBaMCECEBnrJSto02WaOQ07WOxu0D4XDTEwMDMxMDE5 +Mjc1M1owIQIQGf/rRIDwkLRr97d3IvOF2xcNMTEwODI1MjEwMjI2WjAhAhAaDuYC +68CIYWV7W04Szv7rFw0xMjAxMTMxNjQyMTVaMCECEBodzArbvMvT9DVuu+4NydUX +DTEyMDEyODE4MDA0MlowIQIQGicj8IzHLHKJrvkE4g3lKBcNMTIwMzA3MTcwOTAy +WjAhAhAaNUx419CWlxxl7oB3IewPFw0xMTEwMDUxMTE0MTNaMCECEBpWLCA9qlM0 +qUygoBLT+NAXDTEyMDEwNjE4MDI0N1owIQIQGlvri1PTe1H8ikNonQE/YhcNMTIw +MTMxMDkxNTMxWjAhAhAafZH36qsr5sYlz2+Pt6yrFw0xMTA2MTAyMjAyMjZaMCEC +EBqCqOp5mqnNq00EAXtWBDUXDTEwMDMxMDE5MjcwNlowIQIQGooBO7DqbEOoiiEq +JxP/2xcNMTIwMjEzMTY0ODQzWjAhAhAapGXGSBoHTXGL1rNTlYXSFw0xMjAxMTcy +MzM5MTRaMCECEBrKgHS987QHW41BAES40K0XDTExMDExNDE1NTkwNlowIQIQGtIY +B0yLwExvxKKYWPOO4hcNMTEwODE3MTgyOTA4WjAhAhAa1hs5jbjqmhxR34SzKJlH +Fw0xMDAyMDEwMzAyMTNaMCECEBrmvauFk4nXeDQjEQeg4LwXDTExMDQyNjE3Mjkw +NFowIQIQGweG1rY37YNECodRxSJfSBcNMTAwMzExMTk1NDM2WjAhAhAbCk7d3e07 +rHLg6a+jXjN0Fw0xMDA0MDgxOTMwNTZaMCECEBsahRD178gQdc45Q3X4FCAXDTEw +MDQxNTIwMjIyMVowIQIQGySJ446t/uOvYaSBWr3VUhcNMTAxMTA4MDgyODQ0WjAh +AhAbL99n/ZvprcEIv3jTvqUrFw0xMTEwMTIxNDI1NTBaMCECEBs9u28nS9CNC23/ +C0XLlyQXDTEwMTAxMjA2NTIzMVowIQIQG5OQbAo3WomGR+x7qkWCjBcNMTEwMzIx +MTY1NjA2WjAhAhAbmdJEbX8SVV29OK9sjmFaFw0xMDAzMjkxMTAzMzVaMCECEBu8 +R9kt4SA+1cDlJNXi6B4XDTEyMDExNzEwMTQ0NFowIQIQG9nd+FNlTN6nNXCOo3eo +3xcNMTExMjAxMTUwMjQzWjAhAhAb5koNtdAvC+ns1coi+y9yFw0xMjAyMjkxMjA3 +MTJaMCECEBwU6kMOyxJ/zeLx9V1TIJcXDTEyMDIyMzE3MTQwN1owIQIQHCGqZZW8 +KClBng/vumpc5hcNMTEwNjE3MTUwMjEwWjAhAhAcI+C+oBDg2ercJTOmyQcbFw0x +MTEwMjYwODA0NTVaMCECEBxIRe6BpR2yaYe19yew1K0XDTEyMDMwMjAzNDUwMlow +IQIQHGYaNvYtatP0uZwO+qEeXxcNMTIwMjExMDQxMjI4WjAhAhAck4eZX2boF2BQ +AnTeohX5Fw0xMTA4MjIxNzEyMjRaMCECEByWrrIs/oUaXiV4mMZVKSMXDTEwMDMy +OTEyMDIzN1owIQIQHKDRa3HI669Yr9PiWgh5hxcNMTIwMzA2MTQ0MjQ1WjAhAhAc +o9CanhvuG0CeDCCHWpr4Fw0xMjAyMjIxODE5NTZaMCECEByqKbKHMriZOsan6Emp +UEoXDTEyMDMwNjIyMzQzNVowIQIQHLdsdiA8KrSWNnUWgZGKChcNMTIwMTAyMjAy +MjA4WjAhAhAcuwo0pyENR2baP5/7YfTYFw0xMTA5MjYxNTMwMjFaMCECEBy9eIZE +sglLCaY9wgd+2eMXDTEyMDIyMDE4MzkzNVowIQIQHMH+t+CabkY8ZDGLJcQFnhcN +MTEwMjI0MjI1ODI1WjAhAhAc33kLOrkpq1ek2E6bsWoUFw0xMjAyMTYyMTI2MTVa +MCECEBzx4phjhJNXmonhQZ3/QJ0XDTExMDEyNjExNDIwN1owIQIQHP3mX8qdm04z +TyRSfq7i9BcNMTEwNTIzMTU0OTMwWjAhAhAdCDmbE/tWy+ax711cITJ4Fw0xMTA2 +MDgxOTQyMDNaMCECEB0SaQfU1Jt0D+E/Zw2miTYXDTExMDYzMDAwMzQwMFowIQIQ +HR8ZzhuRQbAvlOOzlKMaUBcNMTIwMTE3MTUyMjMwWjAhAhAdNzjN4RhIjS6KGSVE +gyXjFw0xMTAzMDExODM5NDNaMCECEB1bhkjDTV+pnCCCGl4oYs0XDTEwMTAxMzE2 +NTYzM1owIQIQHV3roSE5cFZg/OQlNypNuRcNMTEwMTE0MTU1MTEzWjAhAhAdbY1h +neg+jPcb6VKjaXAqFw0xMTA2MzAxNDI5MDlaMCECEB1v1Qsghk0f2AuI/GV+7/sX +DTEwMTAxODE0MjI0NVowIQIQHYaBVV7N9BPnM3sMP3LVHBcNMTAwODE5MTYyODQx +WjAhAhAds6jhEAqwyuQhd2Y1no4AFw0xMjAxMDkyMTI4NDRaMCECEB26HT6YOHfK +cJKZSBMnDDUXDTEyMDIyMDEwMjE1M1owIQIQHbsjLe2lpX/xpvfpWc1ipBcNMTIw +MTA1MTgyNzQ4WjAhAhAdvOyEQ1GKlSthPMUKhuMrFw0xMTA5MjYwODQyNTNaMCEC +EB3ad0PvC7EEWzTiaGJwfPcXDTExMDcyODIxMTUzN1owIQIQHf8OgjZuDN2sdy3u +7no0dxcNMTEwMjE0MTk0NTM2WjAhAhAeAiNGbTUnWwknlixuOBxWFw0xMTExMTMy +MTQ4NDlaMCECEB4GK2lWOV+Y1/0NS39GNXkXDTEwMDgwMzEzMzg1OFowIQIQHha2 +yd+j2FV2CX74Y6SK0RcNMTEwMzAxMjExOTU5WjAhAhAeGGX8ZikVHU0Aw7o85Pr+ +Fw0xMDA2MjQxOTE2MDRaMCECEB4genOL9Ug6xdc6lC94LJ8XDTExMDQyMTEzMTU1 +OVowIQIQHjQc3yczQmGP4gEcVh8P6RcNMTAwNjA3MTY0NTUzWjAhAhAePqAmH57m +1eJIxOjVAQQmFw0xMTAxMjQxOTE3MTBaMCECEB5JE1EluPIbz2N6yX+y90IXDTEx +MDQyNzE5NTczMlowIQIQHlBWlaeLLhzbuPQVy23hABcNMTExMjE0MTA0OTA2WjAh +AhAeXYBm2Imx6CoXS9hVZPIiFw0xMTEwMTAxNjQ5NDFaMCECEB5fItwyparXGdFT +w80XU40XDTExMDQwOTAxMDAwNFowIQIQHnigquENVbnqlO+B64YDkhcNMTIwMTMw +MTkyMjIwWjAhAhAeltvGsxntPjxSCACR0IIPFw0xMTAzMzExNzUzNTVaMCECEB64 +7qmWja2hUYi7Cc1QvAoXDTEwMDMwMzE1NTgyOVowIQIQHsC6t2Ka2JV7I63bOh3W +gBcNMTIwMjE2MTUwMjM1WjAhAhAeyILxYpGaoXkOGVTtrkXSFw0xMTExMTgxNTI1 +MjlaMCECEB7jeYzJvfKS1Xyf4o3Nb4sXDTExMTIyMzAzNDk0MlowIQIQHwtkqrH7 +LNHQSBMqBT1R8BcNMTEwMzAxMjAxNzIxWjAhAhAfDXSb2U2HPSGNxWgnIPo1Fw0x +MTAzMTIwMDIxMzdaMCECEB8dSCACpO/PZdHh40kpuWMXDTEyMDIwMzIyMTQ1N1ow +IQIQHyg38qmzDyGpkKljwlco9hcNMTIwMjAzMTI1NjU5WjAhAhAfYDuVyKbRh2eW +tsJeqD5oFw0xMTA4MDIwOTA0MTRaMCECEB9j2wlU4vMM+xb1WrCEyzEXDTExMTIy +MDE0Mjc0OVowIQIQH4iwTe40qtlUlqnzoioxdRcNMTIwMTAzMjI1MjE2WjAhAhAf +jdXdCNjeHxOGYxHi4SYxFw0xMTA5MTIyMTEyMzNaMCECEB+3GIXyhzPbcF65LVu+ +CfYXDTExMDQyOTE0NDgwMVowIQIQH81k4IJsbKM3XCsZ3Pgu5xcNMTIwMjAxMjI0 +MjI0WjAhAhAf4KzpM5Pp106o+7OSOF95Fw0xMjAxMTMxODMzMDJaMCECEB/rGbYM +RAkl0IP08E+r1C4XDTExMDUxNjE4MjY0NFowIQIQH+0ntsZ0Wm8XlYU3LYg5KxcN +MTAwODA0MTcwNTA0WjAgAg8L4LaiNiOTfRYbNUENhS8XDTExMDcwODE4MjIxMFow +IAIPDedudpTOEaRjt7HjSrnbFw0xMTA4MjUyMTU3MjNaMCECECAP+kx/r1MJrq8h +aFgyyq0XDTExMDkxMzE1MTQ1N1owIAIPEB8GNy+HyFq/SOoCSwGMFw0xMTEyMDUx +NzIwNTdaMCECECAWvyRYMfUdcCfZpuYTKOYXDTExMDkwOTExNDM1MFowIQIQIBzj +F7u96kSRqwdZOgNEphcNMTExMjE1MTYwODAxWjAgAg81FycPf+hnjOHhZzcDz7YX +DTExMDYwOTE0NDkyNVowIAIPS/G73zZ4HNOLXKtxNAcWFw0xMTA3MTIxMjIwNTla +MCACD1cwM8lZiE98XLrST2QBvxcNMTIwMTE4MTUyNzQ2WjAgAg9xwsC1pmmDUOPr +MtdbNx0XDTExMDgyMzIxMjUxOFowIAIPddkckV50vVelzT89+jb4Fw0xMTA2MjIy +MTM4MjVaMCACD3h3JU+LukDynbS7I6DH8RcNMTIwMTEyMTk1MzE2WjAhAhAAm3QB +0H+QgDZr44VGjYvOFw0xMTA2MTExMjMxMDJaMCECECCjcGMUx9KKiNos/uiXA1QX +DTExMTEyMjE1MjI0MFowIQIQIKRl7aQW9vZk8MUrjHmWTBcNMTEwNzA1MjIzNDUx +WjAhAhAApKAikQuRYOh+L0AedyWRFw0xMjAxMDUwMzEwNTBaMCECECCktLqtMeRe +Ac4c2AdawM4XDTExMDQxMjE0MjMxMFowIQIQIKoDGeaLiGtVFLUjgznIqBcNMTAx +MjIxMTA0MjQ3WjAhAhAgsm0nG1JSsNEKbuPyGkRiFw0xMTEyMjExODI1NDBaMCEC +EADD2tt0HaC+4KiOMWfMKNAXDTExMDkwNTEzNTIwOVowIQIQIMeTg+1mVNzM4+v8 +HtQ6BBcNMTIwMjI0MjMwMjI1WjAhAhAAyVfqef7byBAtJ80ygQGJFw0xMTAxMTIy +MjAyMTRaMCECECDR/79SnlxacAzSI/w6q2MXDTEwMDUwNjIyNDY1MFowIQIQANeR +/x3eXTEvvuA7HObqXhcNMTAwNjAzMjAwNTA1WjAhAhAg3uJhHJUdLU2R/uVE86FZ +Fw0xMjAxMTAwMDM4NTJaMCECECDhHv02xISMlLMCRo1gECUXDTExMDgwNDEwNDYy +OVowIQIQAPLxnrQCeDYiqODQ7ngiDhcNMTEwNDI3MTIwNjQwWjAhAhAhBw466HCN +8GbagnkQI6pLFw0xMTA0MTkxOTQ2MzNaMCECECEJEUjSfIV9KfbQGbF1QMkXDTEw +MDYxMDE2MjM0MFowIQIQIRkvE0TQg6OzLp5vrQx77xcNMTExMDE4MjAwODQwWjAh +AhAhJN05CcWMx15UzlLH3LXvFw0xMTEwMjYxOTIyMTZaMCECECE7NFk5J3BM6Zfb +QPkvUtUXDTEyMDIyNzEwMjYxNFowIQIQIV7JXKgTEQeierZiyaHXOBcNMTEwOTE1 +MTQzOTU0WjAhAhAhabtWVseQggKIGqR0YUlgFw0xMDEyMTUwMDMyMzJaMCECECGG +ZYZcleX0sFg+yoEbqaMXDTEwMDkwNzE3MTA0NVowIQIQIZp4+xNNtcJiovYSJQ9/ +rxcNMTEwNzE4MTk1ODEzWjAhAhAhqQUnsiEc3/Qx1U95DCgVFw0xMjAyMDcxNDEw +MDlaMCECECHoM1omTFhtQZhYjo3k7e0XDTExMTExODIwNTM0MlowIQIQIhn07CwS +f7aBKtcUpThsLRcNMTEwODA1MTQ1NjIwWjAhAhAiKbLzKjH2DsBDpgHD4HbPFw0x +MTA5MjcxNjU4MjdaMCECECIzM3yy7cPwZmUs+Xv5IJoXDTEyMDEyNTE1MTM0OFow +IQIQIkDp5ga8rTzN+rOTTVAZdBcNMTAwNzE0MTUyNTAxWjAhAhAiWm5srH6YgAD6 +Eq5JOG2mFw0xMDA3MDMwMTM5MDBaMCECECJlc3KkiBC5/q9dLhINpUcXDTEyMDEx +NzEyNDIyMlowIQIQIoKEacLyvaEt5E8g5sLObRcNMTExMTE3MTkyOTU3WjAhAhAi +pDNpB5/VveUhk5SlmPL+Fw0xMTA4MDgyMTIyMjFaMCECECLSGm9xi0SqSq3h0KBZ +AFAXDTEyMDIxNTE5NDIwOVowIQIQIub5AOUgforxljk6AyLwqBcNMTEwNjA5MTQy +NTU0WjAhAhAi6OaBUccufRcn+9mntRP7Fw0xMTA3MjgyMzE0MTJaMCECECMZL8+S +GtPqMDchAm20VnUXDTExMTAxODIwMTczNVowIQIQIx0IrwOb311w/VzLg5tmeRcN +MTEwOTAyMTU0MjE3WjAhAhAjIxhB7lsckhQTd2n1nsjJFw0xMTA4MDMxNzM3Mzha +MCECECMj9d0x4zDarbhalsRnrtMXDTEwMDcyNzE5MzA1N1owIQIQIzFitAOwknKM +scOCBEA44BcNMTEwOTMwMTg0MjAyWjAhAhAjP+XHYWHbbDFXfrdglNXMFw0xMTA2 +MjAxOTU5MzhaMCECECNEvX4q7HaEEX07luHrUgoXDTExMDcwNzE0NDEwOVowIQIQ +I0X43ij4Z8XJaRKuCRhlyhcNMTEwNTA5MTMwOTQ1WjAhAhAjRmdzb37lmMJYWpic +ckEAFw0xMTEwMjAxODA5MDhaMCECECNcGKlWRArXg/ww24wkor8XDTEyMDMwMTA5 +MDQyM1owIQIQI1yK1LRIvNB1jCD+y5U1jxcNMTExMDI4MjA1NzQxWjAhAhAjbM92 +sQuvBQTljUS/2nvKFw0xMjAxMTYxOTQyMDhaMCECECOViw9E6kbly3WcCl6rVH8X +DTExMDYyMjE5MjkzNlowIQIQI6wst1g/LFA52Y1Hq30QFBcNMTEwOTA2MjIyMjAx +WjAhAhAjxzpKiWGNoqho9dXqSW30Fw0xMTA0MjcxMzM3MDlaMCECECPc4mg9oN+P +Eb96pmXCZ58XDTEyMDExMjE3MTQzNVowIQIQI91doNNWxJA0oJP5hJy9gBcNMTAw +NzE0MjEyODQ3WjAhAhAj5Vrfr3C5UTi5rrG+fg5IFw0xMTA3MjUxOTQ4MzRaMCEC +ECPmEHfoMaCPzTLEg4vFUsgXDTExMDIyNDE1NDI1OFowIQIQI+pSEblCapvGnLAG +Oibs0xcNMTExMTAxMjEwODAyWjAhAhAkAS2vUQm30PI3YK/9wPNFFw0xMjAzMDEx +MzM2MTVaMCECECQDBXsUue/RTtyssjKYET0XDTEyMDMwMzE3MjkzMVowIQIQJA4z +5q2gflWJafRvKGyBlRcNMTExMjAxMTQ0ODE4WjAhAhAkLspG6HUtGCqNdqgmkq4a +Fw0xMTA4MDgyMTIyMjlaMCECECRGg/JrbdoORn1OPl3O7kEXDTEwMDYxNjA4NDMy +NVowIQIQJHmeSRKVqsQiaMa7Srb3EhcNMTEwNjMwMDAzMDAyWjAhAhAkgPOMGTe/ +0NQLsSi/Ve92Fw0xMTExMTAyMzUzNDhaMCECECSpKSsOdqVR0h/ctkpXgQAXDTEx +MDYwNDE4NDIwMlowIQIQJLctn0kciJXsrJHSq6tp+RcNMTEwNzIyMTYxNDM3WjAh +AhAkwZtYbNxQRh+YE1tZECBYFw0xMTA1MjQwODQyNDFaMCECECTD5aX5Kft/VCJV +03p485MXDTEwMDYwNzE2NDUxN1owIQIQJM6ShezC4cqyBupeAoLC2xcNMTAxMTEx +MTYyNjQ4WjAhAhAk/fxn4ad+Eti5Fk0Ghx2CFw0xMjAyMTYxNDAxNTBaMCECECUs +keulVVCaYKz8dGoIzVgXDTExMDYyODEwNDAzMVowIQIQJTzjnXWCTqtF8kGmbBHe +2RcNMTIwMTExMTU0MDQ1WjAhAhAlRYmO7btpUJFgPnrluLLGFw0xMjAyMDYyMjIw +MzRaMCECECVRT07j09niALqrxB0+dukXDTExMDQwMTE5MTkwMFowIQIQJWtBsPIj +cl8dlE8KrteIqhcNMTEwNDI3MTk0NzA4WjAhAhAlh6Ej2fgLbx90NjzpHVPbFw0x +MTA5MjMwMTIyMDJaMCECECWZx9Zr7EZg/r+VMt/SF9EXDTExMTAyOTIwMDI1Nlow +IQIQJZ2hjEzQyd2tzKBB0dSmIRcNMTEwNjE3MTAwMDUwWjAhAhAlnajj2XS+wymx +GsHrtnNrFw0xMTExMjExNjQwMTdaMCECECWdsJr5zgg77tN730HOImoXDTExMTAy +MTE1MzQzOFowIQIQJa8XAuqAUouR3BzI79F9RRcNMTIwMjA5MDMxODI5WjAhAhAl +ve1HxwwT61B2yWnbm/FvFw0xMTAyMjIxNDU1MTJaMCECECXLtdd2Uxug041Ijn9o +c9gXDTExMDcwNTE2NDMzM1owIQIQJe9IiB4d1IZq7uKjJ9f63BcNMTAxMjAyMTQz +NjE2WjAhAhAmFA4zVNaLlDWFTItB/XRcFw0xMTAzMDkyMTE2MTlaMCECECYrRYoq +ONOirBXLa6OXIHcXDTEyMDEyMzEzMTUzNFowIQIQJj5GAOadUF1nVCTRZbK+xhcN +MTEwNDAxMTc1NDMyWjAhAhAmQDt6Z0LplbLL5h4/nmoxFw0xMTA4MTcxNTAwMTBa +MCECECZxRGmvgpbgwlpcnWjwSG0XDTEyMDExNjE4NDYxN1owIQIQJnOgBKNDFa8S +HD6+MLruOBcNMTIwMTExMTg0MzM1WjAhAhAmhzCSDT8jqkn/JU435ctmFw0xMDAz +MDUyMTE1NDVaMCECECaMy5EZD+S2dqqvKHXakNMXDTEyMDExMjIxNDM1MFowIQIQ +JsTWef2ePmAQclk7AEMgEBcNMTEwMjE3MTMwODUyWjAhAhAm0LFfzackKXjE0gIj +9CQoFw0xMDA2MDEyMTQ2NDJaMCECECbUSJTLO1JZpI8Pw8xJwboXDTExMDYxNjAw +NTE1MlowIQIQJulXHbSVYt46Y7gx4RO89hcNMTExMjAzMTQwOTU2WjAhAhAnDSFf +e6aU91B6yxm+E8U0Fw0xMTExMjMyMDAzMDJaMCECECccrL07h+rQV1RAXIsS5XgX +DTExMDcwNTE2NDMwMVowIQIQJzJ+BylUzWf7jSwyaALQ2RcNMTEwOTMwMjAwNDUx +WjAhAhAnQCHr0W/XxeS4awTEt66SFw0xMTA4MDIxNzE1NTdaMCECECdCpvqsxz26 +qXF6YgM1EZ0XDTEyMDMwMjE4MjIyNFowIQIQJ0SybTS9DQiPM0QCJd0PFxcNMTAw +ODE4MjI0ODIwWjAhAhAnTAI9l14Yc6pQ9C2yqC0qFw0xMTA2MjUwMjA4NThaMCEC +ECdcuiHhb/eovDEZ4nYcaw8XDTEyMDMwODA1MjI0NlowIQIQJ2NsrI/5lDOKTojH +f3S2UhcNMTExMjE5MDc0OTUwWjAhAhAncW1JIaSHfCaQw6t96YRpFw0xMTA2MjQw +MzA3MzlaMCECECd0eZSgj4vsOUCKxY5RNz8XDTExMDMwNzA5MjU1MFowIQIQJ3ko +h3F7/2IdJ09c327sCBcNMTExMDA0MTg0MzUyWjAhAhAn3gFUGD/j2h8HydL2sRaB +Fw0xMTA5MTAwOTU4NTNaMCECECff/M/HGmgEgELM5MJ3ypoXDTExMDQxMDAxMDAw +M1owIQIQJ/PkLT5oV/ULix67yOfpSRcNMTIwMTEyMTAwMDIyWjAhAhAn/7dNzHXE +BaG0J9VMEylYFw0xMTA2MjAxOTU4MzVaMCECECgp9G6hEUSuV4g4ASaOv5MXDTEw +MDgyNjE3MjU0OVowIQIQKEcdUbDN1RVnKZ7DEDeU+RcNMTIwMjI3MTcxNTM5WjAh +AhAoWwwW2aCVsvDAAP9SyrnMFw0xMTA0MjAxNzQ1MTlaMCECEChheoX04HeXlqt3 +dXQJz2EXDTEwMDIwMTAzMDIxN1owIQIQKHx0UtHbmD125iD8R608zxcNMTAwNzA2 +MTI1NzUyWjAhAhAok2f2+k3eBtOiO8XMZMWLFw0xMTA4MDIyMzM1NTdaMCECECiW +qjhyvqngt8Kdc1pYCnsXDTExMDkwODE2NTUyNVowIQIQKMMD/O8L0CmRETHrrEZu +PBcNMTExMjA2MTM0ODE0WjAhAhAox+oGYwUoNoYH3V8FgJqPFw0xMTA5MjgwODQy +MjFaMCECECjXpO7N/rUAh/Yq60jXfckXDTEwMDYwNDIyMTU0OVowIQIQKOkoQsZF +e9iTFiJA4nJ6gxcNMTExMTI3MTkzMjI2WjAhAhApBDVSja/yQP7fgDqSRbP7Fw0x +MTEwMDMxNDMxNThaMCECECkL6FnCDEZioKdUH7ku8eYXDTEwMDIyNjIxMDY0NFow +IQIQKRvA0q6ftTMvCReGT4stHxcNMTEwMjE0MTkwNzQxWjAhAhApXLD6psykDt8O +++KIfkcpFw0xMTA0MjcxMjA4MzhaMCECECldNgOT97xOWVwP1iE9pgQXDTExMDQy +MDEzMDI1M1owIQIQKW5/cxDTRNNz8lcIcI0I5xcNMTExMTIzMTcwNTQ0WjAhAhAp +hVGmpkmgwgT1XnWymS6vFw0xMTA1MjcxNTQ4MjVaMCECECm6wsf0HhhFvOnqxNcV +LHoXDTExMDYwMjEzMzYzN1owIQIQKcKq5y6DL6uDG/XfOvpeGBcNMTAwNzA5MTYz +ODUxWjAhAhApxDYlGuWM6pGCmDeHz2F+Fw0xMTA3MTgwMDAyMDZaMCECECnI2U20 +6KtEifhko3xV6vsXDTEyMDMwNjA1MjMwMlowIQIQKdAX5o/B113P4GoyI7izNxcN +MTAxMTA5MTc1NzMzWjAhAhAp5cWeUZlEPSePnSxctJZgFw0xMjAxMTkxODQ2NDRa +MCECECn1Q2HfFwoqu5cwCTsaC6IXDTEyMDIyOTEyMDI1OFowIQIQKiVJoT/tQ1jP +z7IxkbzYkxcNMTEwNTE5MDA1MjM0WjAhAhAqNKBxaemOyHCn470AOWrYFw0xMTEw +MTIxOTEzMzFaMCECECqLjki3vDrIaxEceHpbh3IXDTExMDQyNzE5NTAwMlowIQIQ +Ko0FOpk+ST4uCRbNHNScnRcNMTEwOTEzMTY1MDM1WjAhAhAqj+fvGYhJlOqW68gJ +7lc+Fw0xMTA5MTMxNjQ3MzBaMCECECqRueuD84f9pbgH0/ciP/MXDTExMDMwOTE1 +NDI0N1owIQIQKrNqVUctMEllkby+a9HAoxcNMTEwNTEyMTQwMzMxWjAhAhAqtTrB +jp7QbC9ksfAicwPNFw0xMDEwMTIyMDAwMjdaMCECECrLREABs8A6hUhSA9+/rt0X +DTEwMDUwMzE2MDIzMFowIQIQKsuQniouhle4IKZEtPDNhhcNMTEwNzIwMDc1MzMw +WjAhAhAq5ARH+qGqGmFLsmjdQCKlFw0xMTExMTcyMjIxMTRaMCECECr75+XH7yar +YI5ScLv637YXDTExMDQxMzIwMTcxNlowIQIQKwIuo6z2GPospohjqNswHxcNMTEw +MjE3MjMxNTQ0WjAhAhArHxVz2GQmRULjyGtzW4usFw0xMTA1MDMxMzAyMDdaMCEC +ECs0R3TzmuMuBHD3VthWASQXDTExMDMxMDIzMDMzNFowIQIQK0jKDJoeN4Yf6KIG +OU6X8BcNMTEwNDI2MDgxMDIxWjAhAhArUHJU67o5sNKiutxcebrgFw0xMTAyMTcy +MzExNDRaMCECECu3HHke4J3295kQogoraEQXDTEwMTAxNDE5MzYzMFowIQIQK7e2 +MshMgSnKuenhBwBC7BcNMTExMDA3MTYzMDIxWjAhAhArweWHwky059984KfNl9f6 +Fw0xMTA2MjcxNDI1MjdaMCECECvc4f9By7iXwFZa5ANvfWsXDTExMDMwMTEyNDA1 +NVowIQIQK+yRYknbc+vaoH59UpWBEhcNMTExMjA2MTEyMjQxWjAhAhAsB/Tv6jKc +BlBJ7g1ofxT0Fw0xMTAyMjgxOTMwNDNaMCECECwYgXnOdm8kOb0MBXcvFUgXDTEw +MDMzMTIyMzkzMlowIQIQLB8i/k4e4DKO/5wYXfrdnhcNMTEwOTA5MTEzMDExWjAh +AhAsOM0u9iTU/tQvYztBo/LiFw0xMTA0MTgxNDMyMjVaMCECECw6VAmvEIFwIBFe ++br+iNIXDTEwMTExMDE3Mzk0OFowIQIQLHj7oyVXttjI0t1Oi8s/rhcNMTIwMTAz +MjI1MTIxWjAhAhAskm05O+ysOoyG21zPxForFw0xMDA1MTQxNTA2MzNaMCECECyn +nKInD3ztwyeZj1c/fKsXDTExMDYxMzE3MjUyNlowIQIQLLwOn25EjDROitG9cW8z +TBcNMTExMTAxMjIyODI0WjAhAhAsw1SHcsm+lN2TPvUbG1TDFw0xMTA5MTYwMDI3 +NDdaMCECECznLwKKNkClDTP5ZHBsP2YXDTExMDkyMTE0MTQ1NFowIQIQLPLnCzmt +CrKyuUHvPvhjpxcNMTEwMzA0MTg1NDM0WjAhAhAs98OM0aHjSV+GqjPbQrqcFw0x +MTEyMTkxNzA2MzFaMCECEC0IA/zgULeta/JVDy39hoIXDTEyMDIyODExNDQyMlow +IQIQLUrp2/DyhFo/onOPmd6bGRcNMTEwNjAyMTQxMTAyWjAhAhAtYZxpObTKenPk +6VVDcCsaFw0xMDA2MDcxNjQ1NDhaMCECEC2aY781BZ3Y+fNz7nIQDfAXDTExMTEw +MTIxNTQwNVowIQIQLavgrWF1aj5oWMh5/1SZQxcNMTExMTAxMjE0ODMyWjAhAhAt +rIIcS8VhfMLa0WYjp95rFw0xMTEwMTIxOTE0MzdaMCECEC28r4vnHJhUnclQ5iTe +2KsXDTExMDcxMjExNTYwNlowIQIQLd0XhoNVpUTU4lOdIH/9CxcNMTIwMjI0MDky +NjUwWjAhAhAt40ytQ98aXZm2tTdy+Nc7Fw0xMDA3MTQxNTI3NTBaMCECEC4jNKnB +w9FsB28SFsZgJO8XDTExMDgyNTExNTMyNFowIQIQLl0aSFRkFF9UQkbPG6P4XBcN +MTEwMzIxMTUyNzU1WjAhAhAugj07B5feNC0GGkOZ8FogFw0xMTAzMjkxNzAzNDda +MCECEC6H8zFLNloEhvRriRduoY8XDTEwMDYxMDA1NDQzOVowIQIQLqh90FtQDru8 +iLeCnvTKWxcNMTEwNDE1MjA1NzA0WjAhAhAuqut2LZLmurATI0FiRhLHFw0xMjAx +MzExODQyMjBaMCECEC64G6Ok4d0tRARO0xrkH7cXDTEyMDExNzAwMDIzMFowIQIQ +LrlkrwQ73J4f7Sq0yaK8pBcNMTEwNDIxMTkyMzI3WjAhAhAuv4yMuG9PP5OQvGOH +YMQtFw0xMjAyMTYwNjQzMDlaMCECEC7D/zljZxvbd5xnK9YMGeEXDTEwMDQzMDA3 +NDIyNlowIQIQLtZW9FtdF5N0KuE75fnweBcNMTEwNzIxMDQwMjA5WjAhAhAu+HwQ +9MHFhH1resu4AbLNFw0xMTA0MDYxNTExMTdaMCECEC78hBEuo2l+EywmtE/3iqIX +DTExMTEyMzE0Mjg0NVowIQIQLyJm7GTsogqDhEqXQ2p//xcNMTEwOTE3MTQyMjA4 +WjAhAhAvN2p0pCpfUdur/yhEuQRtFw0xMTEwMDMxNjIyMThaMCECEC9UrFc2oq8X +u06uJIEhalEXDTEyMDExOTE4NDQyOFowIQIQL2khGXX2ZL/2UtuKaK6uzhcNMTEw +NDEyMTMxNzAyWjAhAhAva5hxlmEPBDPcV6tOjjmsFw0xMTA2MDgxNDE4MTRaMCEC +EC9ua+lTEB9AXAF8h241fTcXDTExMDUxOTE3MTcwMVowIQIQL35V3aERuokZYTGI +Q5wRFhcNMTEwOTA4MTg0MjEwWjAhAhAvpkN/xaTGsphc8s89bwsZFw0xMTA3MDUw +ODQyMTlaMCECEC+wzVXe1Sd+p+RdHHzlHAwXDTExMTAxNDEzNTUxN1owIQIQL85q +bN+fCgHtSAimAlS96hcNMTEwNDI3MTk1NDUzWjAhAhAv7b28XrM0Wr7DKHLleDAW +Fw0xMTAzMDkyMjQ0NDVaMCECEC/6kFj6K4qxCVyFvZysRTIXDTEyMDIyNDEzNDAw +MlowIQIQMDSeo8pv1nbMZaX6xsVJkBcNMTIwMTA1MTkwODUyWjAhAhAwOekRGGXp +SjtG3A5xQ16lFw0xMjAyMjEyMTE5MzRaMCECEDA6nNpmvZMSqSjvFO15vFgXDTEy +MDIyOTEyMzg1MVowIQIQME46ZT7aP3SFqC+DiyVT2xcNMTExMTA3MDkyNjIxWjAh +AhAwZR3hM99Zg0KGJ4LjBtBhFw0xMTA0MjcwNjI3MzRaMCECEDBvALQgI/tR0rVL +tox34fYXDTExMDQyNzE5NTMxM1owIQIQMIUleBQph/FIgro6OyQjYBcNMTEwODE3 +MTgzMDU5WjAhAhAwmChnFtVDj0ct1a10zpmvFw0xMDA4MzEyMDAyMjFaMCECEDCs +hF608Fw468pTOkYfLGQXDTEwMDcyMjEzNTcyNFowIQIQMMVZOgPLFeC8sHNlZEw8 +lxcNMTIwMTEwMDQ1NDI1WjAhAhAw+DeZ9WIxPXi7N7NEHXe4Fw0xMjAzMDExNzMw +MTFaMCECEDD95bly1+7xMLA721e1t4MXDTEyMDEzMDE5MDIxNlowIQIQMRJ0hdat +QBlNWkEZlsvaDBcNMTExMjEyMTIyMjA0WjAhAhAxISlwdkUezF2CNWOfPur+Fw0x +MTAzMDcxNTAyMTFaMCECEDEnTgjzBOob43d8C3RTZCgXDTExMDcwNDEwMjc1MFow +IQIQMSlPIhbZ10mPbLk4iBYvORcNMTIwMTExMTE1NzUxWjAhAhAxRZAGid/Crblc +dsV3PSdYFw0xMTEwMDYwODExMzNaMCECEDFXx/elCbZuoTC/PDujhkgXDTExMDQx +OTEyMTQ0NlowIQIQMWeIt/rdbdR8b6VfLpZ1PRcNMTExMTAxMjEyODA3WjAhAhAx +a8X1M551ATHnR9mszZ28Fw0xMDA3MjkxOTE4NTZaMCECEDF5mE5YJjJzhFgsGbP3 +VfkXDTExMDIxNjE3NTUwMFowIQIQMX7UN33ehv5rC34ftD5LQhcNMTIwMjA4MTgx +MzQ4WjAhAhAxm/e14+H0AZq7KuJn1b9vFw0xMTAzMzExMDIyNDBaMCECEDGcqzzm +qp0hKWfl0PkTYB0XDTEyMDEyMDAwMjIxN1owIQIQMZ861Or2kCVeZPjbD0eJGRcN +MTEwNDAxMDEwMDA0WjAhAhAxoCrD+xHhFqNY44rF8bQMFw0xMTEwMTAxODQ3MDRa +MCECEDG/j7S+If92CJLp1kqI6gsXDTEyMDIxNzE0Mjk1MlowIQIQMc3VnY9b8y0p +jisDGAtEghcNMTEwNTE2MTM0MzMzWjAhAhAx0CSfDjMW8WXgvuV2xVmOFw0xMTAy +MDMxNDA5NTdaMCECEDH2SArCCVadnraB7LNtBLIXDTEyMDIwNjE2MjgyOFowIQIQ +MgcssTe9ABVJ4dfLENgRwBcNMTIwMjA1MDMxNjU3WjAhAhAyFVdwNFWfvEmJQAai +JUZzFw0xMTAxMjQxOTE5NTRaMCECEDIkhEfyknrH+w/ptD3+k2kXDTExMDUyNzEx +MTgzOVowIQIQMitG0OSGob67HiLc4aiJMxcNMTIwMzA3MjMzOTUxWjAhAhAyTG0Q +JotSO7Q8JrmlYGgSFw0xMTA5MDcxNTI3NTdaMCECEDJdl+ae4QuN1So4zIi7SssX +DTExMTEyMTAxMzA1MVowIQIQMmYFro5Lxs51NQoiGvi0JRcNMTExMDE4MjAxMDQ3 +WjAhAhAykZIthrsf4b6tYov0QdGiFw0xMTAzMDQwODAyMjZaMCECEDKm/Bb2fTjI +OwvbvYklmVEXDTExMDcxMTEwMjIxMFowIQIQMtl9E73X0kLpuEuWQSiETRcNMTAw +NzEzMTQyMjE5WjAhAhAy28+52XyOVIQMI9T71P/VFw0xMTAzMTcwOTM4MjBaMCEC +EDMNJi2rsTqLhtyEmTDvatkXDTExMDIxODE0MjIxNlowIQIQMxS2NJGMe7eIRxGO +8abO4xcNMTEwNDI3MTk1MTU5WjAhAhAzGhpeKOBNuZC5GPv/BfWNFw0xMTA1MDYx +NDAyMTJaMCECEDMdIznZP4DW5EVECuwbd6MXDTExMDQyODEzMDkwN1owIQIQM031 +G1g8B8x5vrbB2EEXyhcNMTExMTE1MTk1NzMxWjAhAhAzaD2914kTEhkB+ceTgx80 +Fw0xMjAxMTkxODQ5MjJaMCECEDN5TvM4MFLDS9byK82r2KAXDTExMDYwNDIyNDIw +M1owIQIQM4CZsEKSjT/GcqvGgFpOlBcNMTEwNTMxMjEwMDQzWjAhAhAzr2foLUz3 +ppxIwS/Flc0nFw0xMTA0MDQyMDQ1NDZaMCECEDO1uwBx2npKmmbVZLW/3zIXDTEx +MDMyNTE0MjQ0NFowIQIQM8+3IrmvW96pIHxBdDYewxcNMTIwMTEwMDQ1NTAxWjAh +AhAz0pP3o8xScuXRD6BZmWInFw0xMTA4MDUwMjIwMjlaMCECEDPbAhTT+uxjoBOs +1qCRFCwXDTExMDkxNDIxMzg0MFowIQIQM918aU7iewvaQnJke3sAnhcNMTEwNjAx +MTUxMDE3WjAhAhAz6NwrGcTNtrynUEguJJ+AFw0xMTAzMzEwNTQ4NDNaMCECEDP1 +bi4D/C+X/AHBxuOvZxEXDTExMDgwMTE4NTUwNlowIQIQM/igFuWn3XtT3ZOlD+8J +fBcNMTEwNjEzMTQ0OTE0WjAhAhA0E1aFl3ElAKycJVzjY7prFw0xMjAzMDcwOTU0 +MzhaMCECEDQXWue7z83qqsRmGMfTEpQXDTEyMDIwMzE3NTQyOVowIQIQNBeg0w2U +5akmGv4vfxLrOhcNMTEwMzAxMTI0MTEwWjAhAhA0L7bBe0ukRhzEaH+iScgKFw0x +MTAxMDUwMDM0NTlaMCECEDQ6S5lpQMBvalK0hR+8eqEXDTEwMDUwNzIzNTYyNVow +IQIQNFdtQvZxYo9GUBT3PudrjxcNMTExMDExMjAyMjE2WjAhAhA0Y+SPLRG/Dkpu +tOXKAra0Fw0xMTA1MTcxNjIzMDFaMCECEDSN+OZKt8EsZrZtaE4CThYXDTEyMDEz +MTA5MTU1N1owIQIQNJWVAoAmrV0Fl8SqgG/NxhcNMTEwODI2MTQyMTEzWjAhAhA0 +m4U/RxP8HCIFG1GhZZIjFw0xMTA1MjMxNDIwMTZaMCECEDSdojqgS3QU6/3wP2iZ +RZ0XDTExMDYwOTEyNTI0MlowIQIQNLbli4o50QtKHyrZH50EjxcNMTEwNjMwMDAz +NDI4WjAhAhA0ySNiVS+xf2dZMq4YxoVmFw0xMTEwMDYxNDIyNDJaMCECEDTwPpTp +2RDgP164tiY9RdIXDTEyMDEyNDExMDkwMlowIQIQNP9SyYJgStYRc8js5II8+xcN +MTEwMzE3MTEzMjMyWjAhAhA1EkjTc+D5TXoTjZhqSMs3Fw0xMTA1MDQxODE0NDRa +MCECEDUZjSMBoEhJkpUsQ0KPd/wXDTExMDIyNTIwNTY0NFowIQIQNRwXqCXl0eGz +290+z+gkFxcNMTAwOTA0MTkzNjE3WjAhAhA1NWHsMKOJ3Z+eCxhMkmWzFw0xMTEy +MjMxOTI2MzBaMCECEDVi0tzkNDU6dTDjkoUOLpcXDTExMDEyMzE2NDIwMlowIQIQ +NY2lODXg4EWYfNlXrz0LtBcNMTIwMTMxMTI1NjMwWjAhAhA1nA8kg5EeQKUIUvUf +LJ+PFw0xMDEwMjYwNTUzMDVaMCECEDWe6IIT3fo+KuBUwTBhfyAXDTExMDQyNjE3 +NDc0M1owIQIQNdA5p7g4z0OsdCAWLCLLmhcNMTEwMjIyMjAyMTQ5WjAhAhA2Cf2C +S1hLUT1PlOCLB0IHFw0xMTA4MTExMzI3MjFaMCECEDY3BDwXdbTJS5BvktABgO8X +DTEwMDgxNjEyMDA1NFowIQIQNkocF3KcslFBNMBvoBEs1hcNMTIwMjExMDQxMTU0 +WjAhAhA2biGZrnZWbA3eVqzNLutwFw0xMTA2MjgyMDMxNTlaMCECEDaA9HKVCbis +Sj/M3gYRSiUXDTEwMDgxMjA5NTE1NFowIQIQNoMZZubyMlRTmTpyag8meBcNMTEw +NjIxMTM1NTQzWjAhAhA2ohKigjXONkzT/eO+ya+cFw0xMjAzMDIwMTM1MTRaMCEC +EDarAtU6uAZzLAe3lD7KH+QXDTEwMDYyMTE4MTQyMVowIQIQNqxYszue1Q0gqvWM +xFtQoRcNMTExMjI5MTYwMjMzWjAhAhA2ri4/lBNGc5h43ksZUQINFw0xMTEwMTkx +ODU0MThaMCECEDa5s5eZ6XZFUwZUXswBAvoXDTEwMDYyMzIyNDM0NFowIQIQNtKr +6y3WDmdmhEPNnCNm3hcNMTEwNzI3MTQ1NDU1WjAhAhA21TVcAXsFTRJKQKL8W9Zg +Fw0xMDA1MTIyMDMxMzFaMCECEDbX3pNC8EkhS8lC94RqumoXDTExMTAxOTE2Mzky +OVowIQIQNwbgIvSXegm7hW24v8UtNxcNMTEwMzE1MTEwNDQ0WjAhAhA3DTLeC8yy +EzMZMKDCxwqoFw0xMTEwMDYxNzEzMTNaMCECEDctzMf834Qwh2I+NFyHBBMXDTEx +MDgxNjAzMjEyMFowIQIQNzczuXYbepF/h34VwASToxcNMTEwNDI3MTk1NjE0WjAh +AhA3PQjqGLocBVCrj6yomQQ8Fw0xMDA2MDcyMDU0MjdaMCECEDc/JXGOHB+Q3acG +YQMcwFQXDTExMDUwNDEyNDIyOFowIQIQN0a2IyRmYSjoUmOpYFCMRhcNMTExMTIw +MTYyMjA0WjAhAhA3c8AQjz4l0xYswpj8RUGkFw0xMTA0MjcxOTUyMzBaMCECEDd3 +nSM3IM+M9lVytbDlga8XDTExMDkxNTExNTg1MFowIQIQN8dpxPPzdewGRAFcqM3W +LhcNMTEwNzA4MTUyMjIyWjAhAhA3y3BTrRQ/V136ZRGsRDS5Fw0xMTA2MjIxOTE2 +MTRaMCECEDfSutGIfZsPWxpDp3bTEZcXDTExMDkxNTAxNDU1NFowIQIQN9qD9Gqy +B6l2IuoEjiOPkxcNMTExMDE5MTk1NTU4WjAhAhA39/IBOyZO5f702u2lzWEnFw0x +MTExMDEyMjI1NTdaMCECEDf9a4pcj0P60mV0tRvY9NEXDTEyMDIxNzE0MjgwM1ow +IQIQOB+z7nzZBUunxbw6wg3grhcNMTExMjAxMTUzNzM2WjAhAhA4KndQAE7hRETc +/y+DSkJWFw0xMTA2MTQxNzMwMjNaMCECEDhQEFbfiS227LMJuQghCG4XDTEwMDIy +NjE1MjczOFowIQIQOKV7n+x+/Z9c/yxeNGb+RhcNMTIwMjA2MjIxNjMwWjAhAhA4 +9maZmJ82B/V9nqvlEUorFw0xMTEwMDMxNzQ5MDlaMCECEDkBjJl87d8R7gENtpjb +TjIXDTExMTIyNjE2MjIxN1owIQIQOVvEx5o/+JR8BzfdWuAUFRcNMTIwMjEzMTY0 +ODMwWjAhAhA5X2u8tRFKoRF9frJh6EOoFw0xMTA5MTkxMzAyNDlaMCECEDluq3Zl +NPsR3GN1DoD3A2IXDTExMDkxMzE2NDc0MlowIQIQObAo2+OxT0RW5svcWTvs5xcN +MTExMTIyMTgwMTU1WjAhAhA5v24rX3+YExEMmSucrPHcFw0xMjAzMDYwMDA3MjVa +MCECEDnG/unsQ6esr2YzhY0oqhEXDTExMDExNzEwNTAwNlowIQIQOiAK0bSY5U9E +pFizA+2YFRcNMTExMTAxMjIxNjUyWjAhAhA6JEOTimFXSEE0gbVy/rcEFw0xMjAx +MDMxOTA3MTBaMCECEDosrhlypOEDHcqNw4NUSCsXDTEwMDgyNDE0MDQyMFowIQIQ +On00j9qPEuAzNT7VepXOkhcNMTIwMjE2MTMxODIwWjAhAhA6nmOEm/13h71MEpYd +Tpm4Fw0xMjAyMTIyMTEzNDNaMCECEDqghY34uUzRtHzH+786HFQXDTExMTEwMjE5 +MzcyMFowIQIQOti8npdOhNTs46586LjlqBcNMTAwMjI4MDYyMjA4WjAhAhA64J+c +KtepoBCwpEormWR6Fw0xMDA0MzAyMTAwMDVaMCECEDsE6pCVwaXQTwPpIMv0xEMX +DTExMTIyMzA2MTIyMVowIQIQOw3nz/MqEFOwI+9oJhHRQRcNMTIwMjI5MTIxNTE0 +WjAhAhA7Kfr+nPdXzv2BY9UqVlgMFw0xMTA3MDYyMDMzMzFaMCECEDtFYkTC2n9J +I41PSuz/HoIXDTExMDQxOTE3NDIyMVowIQIQO2wmeUeKkvA/vwvtEaf62BcNMTEw +MzI2MDEwMDAxWjAhAhA7c2UIUGWXe+ZmZnmA8M8+Fw0xMTA3MDEwNDAxMzZaMCEC +EDtzlqJmtYqWsfigESJCyTQXDTExMTAxNzAwNDIxNFowIQIQO4KcgvY3iFdkADkR +lKIVxRcNMTExMTI1MTU0ODQ1WjAhAhA7i9IFCBJAVZCRcUfJRWl4Fw0xMTA3Mjcw +OTAyMzVaMCECEDun4JcsiaRCDhyFnpa75BUXDTEwMDUxMjA2NTA0MVowIQIQO6wZ +UsXINFkY7rydzqmgixcNMTEwNzI4MTgxMDQ2WjAhAhA7uAaYygFs2bKhwwQefxKH +Fw0xMjAxMjQyMTUyMjdaMCECEDu9PEXiKUX6FBpKXhvNG2wXDTEyMDIwMzE4MDIy +OFowIQIQO9NZlSUo72YCvoDwpqMV+BcNMTEwNTIwMjAzMDUwWjAhAhA740DSZeU8 +Nl4tZkiUHSmCFw0xMTA0MjUxNDU4MTRaMCECEDvpQ0N0rxk0KjH+1rik2/0XDTEw +MTEwODEzMjIwOVowIQIQO/Onn0iJd0uqh03Uf8QaRhcNMTIwMTE2MDEwMjA2WjAh +AhA7/2u9WExqXBjh8TAkSR++Fw0xMDA4MTkxOTAzMTJaMCECEDwQ7ka0H3td6YGp +rJP0+H4XDTEyMDIxMDEyMDU1MFowIQIQPBYqaduIXCEJ6yCcDCRqmhcNMTAwNTE0 +MTUwNzI5WjAhAhA8Gwfg7fCjCN9R9M69ISg0Fw0xMDExMjMxNjQ5MDFaMCECEDw7 +Ujt7bjH3vAxkCxHsT+sXDTExMDkwNzE3NTMyMlowIQIQPEFRnFtQ408cdeMW9r27 +ghcNMTEwNDI3MTk1NjQ0WjAhAhA8Tr/C0Q2hRKmZhr0hin8FFw0xMTA0MDQxNTAz +MjdaMCECEDxVDaaQCNrGnnSY9fJMOloXDTExMTEwMTIyMDUyMVowIQIQPG9DqvLu +l3mhkFbUmX94ixcNMTEwMjIzMTAxMjMzWjAhAhA8eZh+7AjNKohBCoKXjq2bFw0x +MjAxMTgxNDEyMzVaMCECEDyKj4yZAXopW3IELdqgYuMXDTExMDQyNzE5NTgzNVow +IQIQPJVYK/x1xLvzAYPiIcYsMBcNMTIwMjI0MTcyODAxWjAhAhA8lzwGPikoJhDa +N16TdDI8Fw0xMjAxMjcxNjA1MjRaMCECEDyeYxiMIsmI3V9xcX6/DRwXDTEwMDUx +NzEyMjMyMlowIQIQPK+LTWYAmbEiKdM1nkzO1xcNMTEwMzA5MTk1NTMwWjAhAhA8 +yxmQKuHL+dw1osXuxmEaFw0xMDEwMjkwOTI3MDJaMCECEDzoetrzaARboAJgeF82 +yBMXDTExMTEyMzE5MTczOVowIQIQPPnrYrepqoF2SqINKJi2ERcNMTIwMTE5MTg0 +NTEzWjAhAhA8/bvsAgXIZHIeH6a4dq4GFw0xMDEyMjQwMTI2MTRaMCECED0CQ6xp +DmZFvgIIiotN5RwXDTEwMDMxMDE5MjUxM1owIQIQPQfqkK0eHeV2HufaAaRkERcN +MTEwMjEwMjE0NDU1WjAhAhA9KsHnR/mINxkCe3FrpWXVFw0xMjAyMDIwMTQ0NDNa +MCECED04A9lEnwL9ZnBY6+OfkpoXDTExMDUwODEzMjcxNlowIQIQPTjQwUNLM5ee +QOD/uHT2lxcNMTAwOTE3MTg0MDE5WjAhAhA9QuK2xcsXSsOi7hE0h9AHFw0xMTA2 +MTMxMzQyNDRaMCECED1dKWoIWztexStbB/9iutEXDTExMTIxNjA0NTc1MVowIQIQ +PXwGwcgk2y/bvOEE1fvLzhcNMTIwMjE3MTQyNzIzWjAhAhA9oGUXLDmqidmaUhX9 +N0t5Fw0xMjAyMTcxNDI4MjdaMCECED2hi6t3Q5S1uZR6xhsCNvkXDTExMTAxODIw +MTUyM1owIQIQPaZNq/nfuDdXxsbAYOiIdBcNMTIwMTI2MjAwNTEwWjAhAhA9suqc +pz+cgflubotf1pD7Fw0xMjAxMTkxODQ3NDRaMCECED3pcxj+rb8+XBghvBUlepcX +DTExMTEyNzIwMDI0NlowIQIQPgSP6I2t1T9tYBsYqKoTnhcNMTAxMjI4MTEzNjMw +WjAhAhA+dPCok+hsO/z6P8P/QXVxFw0xMTA5MjExNTExMTdaMCECED6BhFsa3HfY +c+zmoiwBqVkXDTEwMDMwOTE5NDgzOFowIQIQPoVqu4s5CO1lemnm1jrzGBcNMTEx +MDA0MDAzMDUzWjAhAhA+nT5CYNfJ9rgF4YPqP8LCFw0xMDEwMTMwMjQyMDJaMCEC +ED6xXJ6Dqa3p74p85DArbXMXDTExMDcxMTE2NDQ0M1owIQIQPsYav4UczxlWG5QI +BSeq4xcNMTAwNjEwMjIyNDU0WjAhAhA+yQxXoibMhkMdvpbsaUPLFw0xMTEwMTEw +OTQwMjNaMCECED7N2zkRz+oJHh8eGleRaG4XDTExMDgxNzA5MjIyNFowIQIQPtQd +5t044SVRM6GzoYCTfxcNMTEwNDIxMTE0MDQ0WjAhAhA+4AoPJnVFf65aXqRnvqnA +Fw0xMjAzMDMxOTQyMDhaMCECED7hih0q29kpstOo3YgWvYQXDTExMDYyMTEzMzcy +OVowIQIQPvwH2zj3Dbv3yNkhOEAy+xcNMTEwMzIxMTQyODI3WjAhAhA/GQcBFSaa +Ka94whkMnMsWFw0xMDEyMDgyMTM5NDRaMCECED8ZCTkTw9ofo7EfhlGuDRcXDTEx +MDIwOTAwMTI1OFowIQIQPym8Smcuc1ahL/Nz2V2aTBcNMTEwODAxMTYxMTMzWjAh +AhA/QTjkcmbLd3ANXSrIzdHMFw0xMDA5MTAxMjMwMDdaMCECED9Y1XVKbYcz9WG4 +ZelWvDUXDTEyMDExNjAxMDIwN1owIQIQP1r5G+W2cf0GNUI66t+00xcNMTEwNTE1 +MTMyMjE1WjAhAhA/YWm4M73b4qQgfiZWey6IFw0xMTAzMjUwNzAyMTlaMCECED9n +VXlng82inshHkpR/qtwXDTExMDIwOTE0MTEwNVowIQIQP335EpBjhbt8JfSvadiv ++xcNMTExMTI5MTMyMjQ1WjAhAhA/gOhzPWUpoDfk+F7xIAhIFw0xMTEyMDUxMDQy +NTNaMCECED+EIUf9wjGArwiJFj+c7SoXDTExMDMyOTE0MTU1MVowIQIQP6A/StHC +7luUquf9sGtcQRcNMTIwMTEyMjAwNTA3WjAhAhA/sY6BZam5w4j9Zkkyv0j3Fw0x +MTEyMTYwNDU4MTdaMCECED/GB747sUJoFlWmODFDit8XDTExMDExNDEzMjAzNFow +IQIQP89QcK2CSJjZEPDgjWkKHRcNMTEwOTI2MTUzMTU5WjAhAhA/1g69SjIv9s2/ +92mx1kuQFw0xMDA4MzExMzM2NDNaMCECED/YcKumkXrBcHwbZ09i3lMXDTExMDky +MzE4MDEzNlowIQIQP+XLZowZtQiWcMrgjMEl6hcNMTIwMTI2MDI0MTAyWjAhAhA/ +9PSz/TgGvJ48m1FpFakFFw0xMjAxMDYyMTM1MzNaMCECEEAXjcg45gzHZ8kyTGBh +xFUXDTEyMDExOTE4NDcyOFowIQIQQBv1Ll7ItysIRtxuHAUOsxcNMTEwODE1MTUy +MjA4WjAhAhBAHYqUt3DVj2DkQlnHR16kFw0xMjAxMTkxODQ3MDFaMCECEEA7+Jm2 ++9om0ccfBpUWFYcXDTEyMDExNjE5MzUxM1owIQIQQE2TEvGGx8FDJt2cAFdq6xcN +MTIwMjA5MTcyODQyWjAhAhBAclOVFe1O8BxHO8q7bBNFFw0xMTEyMDgwMzE2MjBa +MCECEECMNat7hfkWz1tDaBztG7QXDTEwMDMxMjE1MjE0OFowIQIQQKawiVTx7GEb +RtpyxklKgxcNMTEwMjAyMjIzMjEyWjAhAhBAuhS1IeuZHcj3PPQ6ABJsFw0xMTEy +MTEyMDE5MDdaMCECEEDg1N+FHHJ9vSZiIQMqkAAXDTEwMDcwNjEzMTIyMVowIQIQ +QOQxQ8NwZteCXTVXCKN9excNMTExMjE1MTAzMDIwWjAhAhBBJ4qbfiFnprbWGed9 +QDbTFw0xMDA4MjMwNDQ1MTNaMCECEEFU9WfyqVbqdNoh8/cuZ/wXDTExMDgwMzA5 +NDcxOVowIQIQQYHsyzlFSXfnh9h8IjaCshcNMTExMjA2MTYyMjUxWjAhAhBBhglE +nAfIYexmCexRue7CFw0xMDA5MTMxOTQyMjdaMCECEEGn8JJ+RMhRHMVUrazsshMX +DTEyMDIwMzE3NTM0OFowIQIQQcHvQ7t4zV5IFb6db6mD4xcNMTEwMzAxMTgzOTMy +WjAhAhBB8ug/SL4Tv3WS8GxKYuS3Fw0xMDEwMjcxOTI4NDZaMCECEEIXh01zm3pe +gOFxgTnG0K0XDTExMDMxMTE5MTQ1MlowIQIQQhpr3TpRrXT+iX9JspQJwBcNMTEw +NjAxMjAwMDM0WjAhAhBCazMHPA2YT2knOF1IJYFhFw0xMTAzMDkxMTMzNTJaMCEC +EEKEOQue+z7h/BV5uUsqnXsXDTEyMDIxMzE2NDQzNFowIQIQQtmblji6bIjd3B+w +Nd9XaxcNMTAxMjE2MDIwNTM4WjAhAhBC/H0GUtaOIWcC/uTgVyUmFw0xMTA0MTEx +MzU1MjhaMCECEEL9ICAcrtDkrwrgdMuIzpwXDTExMTAwNDEyMzAzMlowIQIQQwlg +aWNH79JpSO0KIdLJmBcNMTEwOTI4MTYwMzM3WjAhAhBDHV49CcNRzaqMD2kKBi7M +Fw0xMTExMjMyMDQyMjNaMCECEEMtdIA/Z+7BTjxdvhiAnIwXDTExMDgxNTE0MjI0 +NlowIQIQQzKQ41Ztn1V6Ty6/ooTTmhcNMTAwNjE3MTczOTIwWjAhAhBDMzv627w9 +jF/b5B4qTXnmFw0xMjAyMDYyMzE4MTdaMCECEENBBEbTmrcdFrSeTML939oXDTEy +MDIyNDIwNTQ1OFowIQIQQ0hPLW7haVhMqd3YgL3VaxcNMTEwMzE3MTYzNjE5WjAh +AhBDXUVCV8fE3vcxWfA4Zj7XFw0xMjAxMzEwNDU1MTdaMCECEENixyHyn/zAmSrE +0/WiVBwXDTExMDQyNzE5NDYxOVowIQIQQ2dh1EhkWRAP3Xb/Ll3KNBcNMTIwMzA1 +MTYzNjU5WjAhAhBDcyZwrAQK2o1gt1gLaTwkFw0xMTExMTgxOTQ1MjNaMCECEEOH +xfsCZXZIOrWVJlYHwPYXDTExMTEyNzE5MjQ0NFowIQIQQ5FUKfyNbxj3cH0Zj1sB +ORcNMTEwMzA3MTgyMzI4WjAhAhBDkiKc0ZKE/APMz8On8v6BFw0xMTA5MjAxODU4 +NDBaMCECEEO95RlZD799e0U74abcoc0XDTExMDEwNjIzMTMxNlowIQIQQ9ODCNpK +0PB0ugTkfgwurBcNMTIwMTEyMTQzOTIxWjAhAhBD+q/hTLU1GKyYj/q1OuzgFw0x +MTA3MjUxNTQwNDJaMCECEEQNmPuD/AlugeXxQfQ4C7wXDTExMDMwNzE1MDIwOFow +IQIQRA587LyNwatWCQS/j490NxcNMTIwMTE2MDEwMjA4WjAhAhBEMzbJsRLhynAL +FPCtDNg7Fw0xMTA5MjgyMzIyMDJaMCECEERzDzOzfFvEg9UhrKBU9Y4XDTExMTAy +MDE4MDIxNlowIQIQRHOSmGNtggIvLm/gGjSLexcNMTEwNzEyMTY0NjQ2WjAhAhBE +eEYQL62KkOs9y2KsGcS/Fw0xMTA5MTcyMzM4MjZaMCECEER+f9TGswxN5TynReaw +mUsXDTEwMDMwMTE3NDIyM1owIQIQRIg91PGfOdZ2J1YrapINQRcNMTEwNDI3MTk0 +NjQzWjAhAhBEjxIdoEW9fGWmRLFWpo53Fw0xMTA0MjEyMDE0NThaMCECEESj1GP6 +SyIE4wBGHpfakdEXDTExMDcwNjA5MDI0MlowIQIQROj4wt0o4cGC+gRdpM2YjxcN +MTExMDMwMTQ0MjEwWjAhAhBE8R4EDu/RyBeFq55HADLlFw0xMTExMTUwMjExNDla +MCECEEUp2TIDCQQETJv4NHVrvEIXDTExMTIxOTA5NTY1N1owIQIQRTCJjYDeaQmi +NGf8wjMothcNMTExMTAxMjE1NjM2WjAhAhBFM0tA+ssX21hDk4q9bUZbFw0xMDEx +MjQwODUzMDNaMCECEEVAY0HPUPZFsUqIuU+ToRcXDTEwMDcxNTE4MTkxNFowIQIQ +RUihH7tRmTtpcnYjnHFBOxcNMTEwODA1MjEyMTU1WjAhAhBFYXqAKuGBURZ1B046 +7DjdFw0xMTEwMTQyMDIyMjJaMCECEEVk+SBUm/jdRK1hpKK4gPMXDTExMDMzMDE1 +MDY1M1owIQIQRXa/0Fe10xhxm/BwA7TM/xcNMTAwNzIzMDkyMjM3WjAhAhBFds9s +DjvPAWwY4tDgS/LgFw0xMTAxMDMyMDMwMDVaMCECEEV6O0snUgx6q0graJfeXK0X +DTExMTAzMDE2MDIwNlowIQIQRXs/CBYonN8pbZyFjCz47RcNMTEwNTAzMTc1OTI1 +WjAhAhBFjIaNDL8wmU32eAZeRM0lFw0xMjAyMjExNjU3MzFaMCECEEWgcHFTLD0Q +o+WHV1KQtngXDTExMTAxMTE3MzAzMlowIQIQRcueqijyHg1BJ+i3eSbMuRcNMTIw +MjA3MTgzMTQ4WjAhAhBF/9csuHIbpa1T/VCgyieOFw0xMTExMDkxMDAxMjhaMCEC +EEYhZMl+glYkYxLwlHebB84XDTExMDgwMzE3NTAyM1owIQIQRjSYWEw3Z+c5sCQY +eUl8FxcNMTExMTI1MTU0OTM4WjAhAhBGOR3uxmzP1yg15R2RtLLNFw0xMTA0MDMx +ODM4NTBaMCECEEZYdrMUgFb1NbZPRrAj7vkXDTExMDcxNTEzNTkxNVowIQIQRm2h +VRBPFtjIj7mdFxbdPRcNMTAwOTMwMDgzODAzWjAhAhBGxVUrC5VaO/VkWu9QxLtH +Fw0xMDA3MDIxOTM3MzJaMCECEEbL/ZBS3Ih7q8iWMpZScGwXDTEyMDMwMjAwMzcx +NFowIQIQRtsfX6SEezBut+YOdK803hcNMTExMDA0MTczNjExWjAhAhBG6IdCDGrD +207ZkU7xAe05Fw0xMTA0MTYxMzQ2MjZaMCECEEb1JLF68a9VCaBEKHytavkXDTEw +MDkxNTIyNDIxOFowIQIQRvZmg95TEVJC0D8Ti0pArRcNMTAwNjA4MTQwNzEyWjAh +AhBHAWqqLmu77ejGXEtA/8hHFw0xMTEwMDQxNTQyMDNaMCECEEcv/vNUNj71Qiqs +4+fOut4XDTEwMDQxOTIwNTk1NlowIQIQR1z+ntulUpAf0qunYKPnjRcNMTEwNDEy +MTkxNjMzWjAhAhBHahTxl//bNl/EruMDJJQNFw0xMTA3MDUxNjQzNTJaMCECEEdy +AScR8e94fNuExt1TO+kXDTExMDMxMDE2MDIxNlowIQIQR7HVGhZEmP1ATR1uOgUM +BRcNMTIwMTE5MTg0NjI1WjAhAhBHx1vptYJhNua72ux5+lXkFw0xMjAxMTkxMDIy +MjhaMCECEEfjjiWu8d+xjNndEdPivu4XDTExMDUyNTIwMzQ0N1owIQIQR+eeFckL +IT5iKJ9yNDmdtBcNMTAwNjE1MTk1NTQzWjAhAhBH+IWcfmRYRq9skxpBRkS8Fw0x +MDEyMjkxOTQ3MTNaMCECEEf+ds6F81ep7cXfjuBgZHYXDTExMDkyNzIyNDY1MVow +IQIQSAZdVxP3DS8NGEKguUUX+hcNMTIwMjI5MjEyMzAyWjAhAhBIFgMGu3FfzWT+ +h94SbcTMFw0xMDAzMDUwMDQwMTFaMCECEEghqjIhYxu4gwGRMdOBiPsXDTEwMTIy +NzA2NDMxMFowIQIQSC2zQpF3yTxH2wGb8hrHAhcNMTExMTAxMjEzOTMxWjAhAhBI +MwhpgUbmeLj5Y2YYfwI7Fw0xMTA5MTUyMDAxMzhaMCECEEhCAC+lX5Y7mHrt9S8H +5cAXDTEwMDgyNjE4MTIxNlowIQIQSE6PGTr49CpDaOjhdgVEnxcNMTAxMDE1MTcw +NzIzWjAhAhBIVaCx2Z9IUSJg+REM1rIWFw0xMTAzMjkwNjA3MjFaMCECEEiPLjT3 +0bBdfEC5ZyiDdfEXDTExMDMzMTE1MzYzNVowIQIQSI9tDchEoH1hB6I8m5DUnhcN +MTExMDA0MTkwNjQ4WjAhAhBInPO/NZ5dfdMcvwlQUPDQFw0xMTA0MjcxOTQ4MDJa +MCECEEjP/vwj17pGOHHXZ+UOFrkXDTEyMDIyMzE1NDg0NVowIQIQSNizP3K64Sy2 +DOKPFNsCwBcNMTEwOTI3MTc0MjE2WjAhAhBI4DcIQlw0bUZDTEO6l3rHFw0xMDAz +MTAxOTIwMjRaMCECEEjxOBju1WuV8WYl4UO5qTYXDTExMTIwNDEyMDA1NlowIQIQ +SQA/9ZhfTYy25B3zfpbUOxcNMTEwNTA1MTMxNzM3WjAhAhBJDsLZOT0om+1vP8SF +cFtiFw0xMDEwMjUyMTIyMjhaMCECEElXup+HdEgnDSj3KESAFTAXDTEwMDkyMTEw +NTIwNVowIQIQSZSEN1jOUAn3LdvpSgB2eRcNMTExMjEyMTUwMzQwWjAhAhBJxtkz +mVnjkcbRCvgqECx6Fw0xMjAxMjcxOTQ0MzlaMCECEEnTIGNZot3tJ2xqJKogOeUX +DTEyMDIxNjAwMDYzNVowIQIQSeY387FAFP+3Kd9o9g6HThcNMTEwNTExMTkxNjI3 +WjAhAhBKEb3HPKc1gjKdJToMgNpRFw0xMTAxMjUxMjQ0NDFaMCECEEoVyPhEQBN+ +SzCL/pv2rSAXDTExMDkxNDIzMDIxM1owIQIQSjDUnpSg/GHzcczeYBIqeBcNMTAw +NzA3MDQwMjEwWjAhAhBKQYzDrp6iF9Z2KGvjfRVBFw0xMTEwMTgyMDE4NTNaMCEC +EEpKEDY0exXnQQufvbHK04MXDTExMDUxNzA4MTUxMlowIQIQSlLU2TFujojzrNTh +6AlXZxcNMTExMDA3MTc1MDEzWjAhAhBKVgVdqJ518H4q6W4dBI24Fw0xMDEwMTIw +NjQ5NTRaMCECEEpaHmzSXimFjHBMrIkbafEXDTEyMDExMjA2MTcxOFowIQIQSlr3 +OYmrzEClH51IimINOBcNMTEwNzA3MjA0NzU0WjAhAhBKas23mbI03B1us865L4ci +Fw0xMTA4MTAxNTQxMDJaMCECEEpxtkl0loUvToGmXZwqzckXDTExMDgyNDE1NTcz +OVowIQIQSqC+5C6aDXGj7l4LVgawVhcNMTEwOTIzMjAzMzAxWjAhAhBKokKWihoB +FgSSAdnytI2mFw0xMTA4MDIyMTI4MjFaMCECEEqy73A0aj0t0err1N2BQzwXDTEx +MTExNDE1MjIyNlowIQIQSrkzMZ8TZ5tIvnX0mdFIrhcNMTExMTA5MDYyNDIzWjAh +AhBKvf3xlhwF6wCPXEpZFMklFw0xMTA0MjcxOTU1MzVaMCECEErOD2/w69hrH3iY +nX1jpJAXDTExMDgwMjE2MDcxNFowIQIQSw3LJSEAPpUdWhqbtXW0+RcNMTExMDE2 +MTgyMjAzWjAhAhBLFoFbLp9KqJB9ybZJru9CFw0xMTEyMTMyMDUwMTlaMCECEEsd +BTIPkLxAf7ZfaRgjVpkXDTExMDgxMTIwMTA0MlowIQIQSyyG7OMKKLBc/SHk3CU/ +NhcNMTIwMjEyMTYyMjI5WjAhAhBLMZjjOSxAfiaQ1WvTvqucFw0xMjAxMjMyMzEw +NDBaMCECEEs3xaRWSJIYc64S/DWf2OQXDTExMDQyOTIwMzYwOVowIQIQSz2hIly/ +ov3+x5QtUCxQpxcNMTAxMjA5MTU1NTQxWjAhAhBLP5TZ7mKszdJJ+T6V5y4LFw0x +MjAyMDgxNDM3MDJaMCECEEtO3Qd3pHD0sNp/6EV8QK0XDTEwMTAwMTE0NDUyMlow +IQIQS36QAsYKneBJDU5mxIq+UxcNMTEwOTA4MTUwMjM3WjAhAhBLlUNx5nVbaIKa +kmde/CwvFw0xMDEwMjIyMTAyMDlaMCECEEvAaW5Uzj/gt/wLksjV/cAXDTExMDgy +MjE1MjAyOFowIQIQS8D56IKoEiZyKzofmrJPExcNMTIwMTA0MDE1NzMzWjAhAhBL +yDaRYZURtmStJeWSRV7CFw0xMDAzMTAyMDM5MjFaMCECEEvt0SeLL/JqK+DRQTJ/ +EyoXDTExMDYyNzE0Mjc1OFowIQIQS/dG7N+WhYc6l/nppqmXyhcNMTIwMzAzMDEw +MjA2WjAhAhBMBgD5reiypRgzUj+xsbZvFw0xMTExMDEyMjE5NDhaMCECEEwTNX7o +JIAKN7XnQz0I9FUXDTExMTEwMTIyMTQwMlowIQIQTCsOU5UGb79kqpAu51NdzxcN +MTEwOTE0MDEwMjA1WjAhAhBMLA6MbBm/eiObi9ALYI3uFw0xMTAxMTcwNTQ3NDVa +MCECEEw0Irw4Wd2OBlhXzAzW7TQXDTExMDMyNDE3NTIxMlowIQIQTDb6NLIOKJC6 +Av4jojnSvxcNMTExMTA3MDgyNzM2WjAhAhBMVcUR8Rzuy6PVndltKdCgFw0xMTA2 +MDYwMDQ1NTdaMCECEExtEAZ5bCAogUWl7qPbFgUXDTEyMDIxNzE0MjYyNFowIQIQ +THqa65zEc8bNwesq2Iu2DxcNMTEwMzI0MTUzNDEwWjAhAhBMyk92Uvj89WaujmDN +IxoCFw0xMjAxMDcwNzMzMzZaMCECEEzLOqBwARE8ElFMA5IOJmkXDTEwMDcxNjE3 +NDU0NFowIQIQTM4Occge+bfPSm+3Sl7ZvBcNMTEwMzI5MTA0NTQ1WjAhAhBM0hNd +UwLPTiVKlVI9h9fMFw0xMTA0MDQxNDMxMjBaMCECEEzg+Cude/hDNc/6SuVC50QX +DTExMDUyNTE2MTQxMlowIQIQTOkXazmH8GuK07Rz5Qs2hBcNMTExMDI3MTUxMjAz +WjAhAhBM/oE8700TzkC9ltjV8G3bFw0xMjAxMTkxODQ1NDZaMCECEE0pN1RV8Lz9 +SHj6aVuo9oUXDTExMDUyNzIwNDIwN1owIQIQTU/R1AljgXm/x4q0jq18PRcNMTIw +MjE2MjAwNzM0WjAhAhBNaneab/W1cs1pVKLtF8Q2Fw0xMTA2MDgyMjA2MzhaMCEC +EE1vsrrOwjo34s5xlq0GFpgXDTExMDIxNzE5MjkxMVowIQIQTXWqzW8AOBqV9AwC +cc/wGhcNMTIwMTE5MTg0ODAxWjAhAhBNhW2GtTBBLtDBimLHLn0gFw0xMTA5MDEx +MTA2MDZaMCECEE2W1Idq03XxuYJ3YtOWwHkXDTEwMDcxNTE5MTk1MFowIQIQTap4 +aA2/J/q6oG7C1kzqGhcNMTEwMjI4MTU1MDM5WjAhAhBNwVdv8w1FF92ycvoZLxXi +Fw0xMTA0MDUxNjU3MTBaMCECEE3PcXLcfILo0TyZDHC0tuAXDTExMDMxMTEwMzkz +OVowIQIQTdewePWB/3IFrMfyFzMfqxcNMTAwNDIwMDg0NzMzWjAhAhBN2Ua5b4eZ +1CBI7HfbZKrLFw0xMTA2MjcxNDI2MjdaMCECEE35GZ1Lc3I2h80TrMxCn4cXDTEy +MDIwMTEyMDIwNVowIQIQThVdDQ3BPEusXO8CDbMMqxcNMTEwNjEyMTY0MjAyWjAh +AhBOLZmuVR95Nf6aH9Nx83L6Fw0xMTA3MjYxMDAxMjNaMCECEE4vbP9bpmavt+Wr +HmvWkJwXDTEwMDYwNDA4NDIyN1owIQIQTjBWDdXCxIfrb6+EPTo+QRcNMTEwOTI3 +MDQ1NTMxWjAhAhBOi4MzBSJuQrVgBw+mHLZCFw0xMDA2MjQxMzU0MzlaMCECEE6W ++zGD4m+LrX8/CqJo+uwXDTEwMDcyNDE1MjIwOVowIQIQTp1BKVYoCHlzKg3RSj7s +LRcNMTExMjE5MDEwMDAxWjAhAhBOpGFaczeaqdjaXIkYczkfFw0xMTExMDEyMTUx +MTNaMCECEE7A/UAoGyHwnSqJXxbTFIIXDTEyMDIyNDA1NTAxN1owIQIQTuFaHySZ +lZbnhI/cz9KIBxcNMTEwNjI0MTkyMjEwWjAhAhBO67Ip6W+oK/6EMYwUFtD5Fw0x +MDEwMTUxNzA2MzBaMCECEE8Bkz+HqJsqEtvOedwn2uoXDTExMTIwMzE1MjkzNFow +IQIQTxFNCxJViVIVKQyn7DdiPhcNMTEwNDA0MDEwMDEyWjAhAhBPF+zzTsp+ZRd0 +mxlCOZNQFw0xMTExMjUxMTU1MTZaMCECEE9kaITvp79aujLgUhc6/JsXDTExMTIx +OTE2MDYzOVowIQIQT2SbcNWiNMsCtog7GqpDkBcNMTEwNDA0MTUyNDI4WjAhAhBP +bH7Q0/vhayAnFY1aAlKsFw0xMTEyMjYxOTQzNTFaMCECEE9z9tS0r++h3D9FXmJE +v1oXDTExMDQyNjE0MjY0MlowIQIQT5mDWLgzqSfeJHt18NTlXhcNMTEwNzI4MTc1 +MDU2WjAhAhBPp2qtIbCGXEsxlI3R7PDcFw0xMDA4MTcwMTM5MjZaMCECEE/+7WSf +zj+pkwZ9u+r26lUXDTEyMDIxMDE4MjIyNlowIQIQUABm7YCj/VLickYMrm0jbhcN +MTEwODIzMDg1NTM3WjAhAhBQJJAede0tO91+zFDEbmEdFw0xMjAxMTIxOTUyMjJa +MCECEFAxtNcA96e5MeX6vGNUbd8XDTExMDMyNTExMjIxNFowIQIQUFnFmjwC7CS5 +3UzqhpZQixcNMTIwMTAzMTY0MDM2WjAhAhBQWhlrWn/TP55VKdmlJUZKFw0xMjAx +MzAyMzAyNDhaMCECEFB1UAoXzjbJwj+3HDkaw0kXDTEyMDExOTE4NDkwM1owIQIQ +UIgth9BJffHwhpbp/pN9xhcNMTIwMjE3MDk0MjQwWjAhAhBQu1LYk9bRzoP2UiBU +O5rDFw0xMTAyMjQxNTQwNDFaMCECEFELWkJz/4GY8Pc9CAJFsBkXDTExMDYzMDAw +MjY1N1owIQIQURzLRRmKi2MV0RHLu6IQ9RcNMTEwMTI0MTkyMTU0WjAhAhBRHm93 +0Q9PtBeMUmGDmGuHFw0xMTA5MjAxNDMzNTlaMCECEFE3QCDKTZbViUDyM89Moy0X +DTExMTIyMTIyNDI0NFowIQIQUWZ4lwblQKPcTQK1gD0UVBcNMTIwMTE4MjEwMzI0 +WjAhAhBRfVtvYbH39/dWNIk4NJPgFw0xMjAxMzAyMjE1MTVaMCECEFGWZigYM1c0 +JMnuD9uqiC0XDTEyMDIyNjE1MjIxNlowIQIQUabSTy+DhdKHkwDNT6Y61BcNMTEw +NDI3MTk0ODM5WjAhAhBRsZuaKh70iHTTeX/fKGq7Fw0xMTA4MTgyMDM0NDJaMCEC +EFG6VRVNJkPebMHHCw2j+rYXDTExMTIxNTE1MDkxOVowIQIQUcsnaHMvxP9D3fI2 +HoOwUhcNMTAwNDI5MTYyMzAwWjAhAhBRz8aYQQEw8YQA9AQrCH2GFw0xMTAzMTEx +NDI5MjdaMCECEFHQ6Rcgg0QnOmY0JmNxgskXDTExMDMyMjE1MTM1M1owIQIQUdOp +zTOVibr1IePo4hCJgBcNMTExMDE4MjAyMDA0WjAhAhBR8H2mUmlzbxqIj7/7XEYW +Fw0xMjAxMDUxNTE1MTJaMCECEFH5RwHYhNdqx8KGLCpe57cXDTExMDcwNTE2NTgz +NlowIQIQUf5u/I54O1QZ+Dyi1QqQURcNMTAxMDI2MTM0NzQyWjAhAhBR/40fJ2kZ +LgK0hbsIcMVuFw0xMTA0MjcxOTUzNDhaMCECEFIAzFT66R7H91KHpFxX17kXDTEx +MDcwMTA5NTUxNFowIQIQUgKTjdpvNMwHvu4AAJtScRcNMTExMTE1MjA0NzQ2WjAh +AhBSL8H0rzgaqMtoyOiPzr0SFw0xMTA4MzAyMzQ0NTlaMCECEFI0v31xHGvJCgoZ +nJKDI0gXDTExMTIyMTE3NDIxNlowIQIQUkOlPRmwUtAS+2Ne6JBLfhcNMTEwNzA1 +MTQ1NjMwWjAhAhBSRF4dvJ84SLLc4CVvuf67Fw0xMDA2MTAxOTQ1MDZaMCECEFJK +W7wmKTZE6h9UVENCbUUXDTExMDMwOTE4NDk1MlowIQIQUk4u1qauNnLRuLPllKhD +dxcNMTIwMjI3MTAyMjA4WjAhAhBSUuachb0c6ZZbB+pMo970Fw0xMTAzMDcxNTAy +MDlaMCECEFJhc3JdVcylEkkXCf1uTNgXDTExMDkxNTEzMDA1MlowIQIQUmGv+OiL +00VGozSnmh4zmRcNMTEwMjAyMjIxNjAzWjAhAhBShrQeGhR9MWH84a+Dyx3XFw0x +MTEwMjAxODQ4NThaMCECEFLFiW30PeQeRp9+N0JCP5EXDTEyMDMwODEzMzEwM1ow +IQIQUsYktM04xHsSX/g31z4fHhcNMTExMDA3MTgyMzQ3WjAhAhBS0YtTijhEO2A8 +MN2cntupFw0xMDEwMTUxMDM4MThaMCECEFL7wu/Q66FRdp+9fwKmPjIXDTExMDYw +OTEzNTAzOVowIQIQUwRq6JNm519BQw9eVEULbBcNMTAwNTEzMTAyMjMwWjAhAhBT +QTYclehcE+h6NTxbPpx+Fw0xMTEyMTIyMjA1NDRaMCECEFNQqEV9QEoTWwekJb+a +/EYXDTExMDUxNzIwMzY1MlowIQIQU1VPh2LmbbyV+jdP0zRy6hcNMTEwNjI0MjAz +OTUyWjAhAhBTdhBD0oNE4F2L0y3N6zVbFw0xMjAzMDcwOTI4NTJaMCECEFO+KFfI +HTw963JUUFwVL2wXDTEwMTAyODIzNDIwOVowIQIQU8a81MfWLEYAFSZL3ot03BcN +MTEwOTMwMDIyNTMwWjAhAhBT7txEDCJATHOdVX+YvjHCFw0xMDAyMjQxNDQ2NDNa +MCECEFP8H78Cr9C/syvVj3k8A1oXDTExMDMyOTE0MDE0OVowIQIQVA4mMtbEwymg +wZqxUkryHBcNMTAwNzIyMTgwNjEwWjAhAhBUD0i9X0rnakHLcWOREwftFw0xMTAz +MTQxMzM4MzFaMCECEFQ1PPS0abTFTVsafLhP8GEXDTEwMTAwNTIzMTIyMlowIQIQ +VHhCJMmB4gPeZ2wAq03ePBcNMTEwODAzMDAwMjMzWjAhAhBUfGJjOHUZfxTtTzE3 +f23eFw0xMTExMjkxMzIzMTBaMCECEFSg0H4NPBxgFNOhMuYD0CYXDTExMDEyMDIy +MDYyMFowIQIQVQDF4mVoBX6vb863pORQohcNMTEwMjExMTYyMjM3WjAhAhBVEFyr +JCv3dOph1tL64ABsFw0xMTA1MjUyMTQyMjVaMCECEFUj/bl5xzs+wAAGKx83fJYX +DTExMDYwNjA4MjIyN1owIQIQVShZGq+slh6N7A7ZN7qpxhcNMTExMTE2MTU1ODM5 +WjAhAhBVNR13nNpVr+WFm/osZnqMFw0xMjAzMDgxNDE0NTZaMCECEFVTAz36wMiB +NrYfoXOtTggXDTExMDgwNTIyMzczOFowIQIQVVZ8gXLxI8tUM9n4wNP29BcNMTEx +MTA5MTMzNjI1WjAhAhBVVoiK7m/yH1Za55EzhBCdFw0xMTEwMTEyMDQ3MDlaMCEC +EFVq8wuEKXzht5jNAxSrJ6AXDTExMTAxMTIwMjIzMFowIQIQVY58QTsxFYH4ZcPY +adswhxcNMTIwMTE2MDEwMjA0WjAhAhBVnStOeK3OdgtkQEL3AqbvFw0xMDAzMTEy +MDQ1NDRaMCECEFXjaahucTCS216g0dFR43oXDTExMDQwOTIwNDU0NlowIQIQVffh +mWXip+c7l2BReeDLVhcNMTAwNjI0MTExMzMzWjAhAhBWCKeHKNIH78Pi/zqPkrRd +Fw0xMDA3MDIxNTA4MDZaMCECEFYonAGoAc61f1wTDw21utgXDTExMDUyNDE0NDI1 +NlowIQIQVjbhjA/TUZG3goc4MtJUrRcNMTEwNjMwMDAyODA5WjAhAhBWOB507b/7 +qVrCA98v9x04Fw0xMTAzMjIxNTE3MzdaMCECEFZV2tkNXIRJcn6QxfXcr7UXDTEx +MDYxNjAwNTIyMFowIQIQVmmXTA9i5ZsuJbYnUxCL2xcNMTExMjIzMTAwMzI4WjAh +AhBWhNzy8Gi9D0kwNsJxtoFyFw0xMTA1MTIwMzAyMDdaMCECEFaWmCXSQiUjpj3s +B2tbXjkXDTEwMDUyMTEzNDIyNlowIQIQVqjL+CYlJOQ4lnLL6OzO4RcNMTExMjA1 +MDU1ODM5WjAhAhBWtXIPqrXHPRb5qgI8kDq7Fw0xMjAyMTIxNTIyMDdaMCECEFa9 +KIaHerq0DOFhWIakPyIXDTEwMTEwNTE1MDIzOVowIQIQVsLBZ45L9aJ456IP5feJ +WRcNMTIwMTI1MTc0MjQxWjAhAhBWz/v8tIMKLTHFra3PgWLWFw0xMjAxMTIxOTU0 +MDNaMCECEFcJfcDj1I6wje6/jIaUbTEXDTExMDUwMzE0NDIzMVowIQIQVw7+QGlx +YjS3oekjzXWi7hcNMTExMDE4MjAyMjUzWjAhAhBXJ83oJNXmWKfFc/nI2l8IFw0x +MTA1MjUxMTE1MzVaMCECEFdMwCkRi4U+5I33IwtkZS0XDTExMTAwNDAwMjE0OFow +IQIQV1oocggJLONjBOatE214JhcNMTAxMDEyMDY0ODQ4WjAhAhBXcBJHL9/fzpUZ +ZG3zgOPIFw0xMTA3MDcxNTMyMTdaMCECEFdyaeYsXwwfxBobt7iAzSwXDTExMDYx +NjAwNTQwMFowIQIQV3dvy4p+eQuhwsFNqcjb3BcNMTExMDE4MjAyMTM4WjAhAhBX +lLxOoICDswizG4ZzmwhgFw0xMDA5MjgxNzQ1MTFaMCECEFew/q8OBrDTAeiCr9ry +b3wXDTExMDcxMjE0MjI0N1owIQIQV8Ru2n7OLkJg+J45FW334RcNMTEwOTEyMTUw +NTMzWjAhAhBX02B93DuuxFPgZ+bCcU3aFw0xMTA4MjkxNTU2NDRaMCECEFffbVbq +HjtR5mAdv9HI05YXDTExMDgxNjIxMDk0M1owIQIQWBIG85SG/5BYkCol4eb+vRcN +MTExMDE5MDE0ODI0WjAhAhBYEqjN7OE5AYLbweU9phm5Fw0xMDA4MTgxMjQyNDFa +MCECEFgYMhmVnfdj3Dl9Z+iE/NoXDTEyMDEyNjE0NTE1MFowIQIQWB+O9dfWLX0Q +55vzKiHCRBcNMTAxMDE4MjEzODQ4WjAhAhBYRoOhbs/xrfPsGzSOu22xFw0xMTA5 +MDgxNTA3MDlaMCECEFh4NUGth5m63QX1K/ywCsgXDTEyMDIxNDA2NTcyOFowIQIQ +WIfPxFem1s2ZpAyTfKO14BcNMTEwOTI2MDEwNzMxWjAhAhBYjVwR8/XrjL21DsMU +Y1FDFw0xMjAzMDgxNDQxNDRaMCECEFipf4pkCnntJMTb5ZUrHgUXDTExMDUyMDE3 +NTgyM1owIQIQWKnQglnJ4DVt6iEWZ2XyYBcNMTExMTE0MTU0MjIyWjAhAhBYrA8B +9JUTLCe6vW5sRgF5Fw0xMDAzMTIxNjMyMzNaMCECEFiskmWe+Skmio8OjGia5+8X +DTEwMDMxMTExMTk1NlowIQIQWLYuETzo256VkeTYkcn/fRcNMTEwOTA5MTYwODU1 +WjAhAhBY7kXakxOvAbwnJcDuxFjqFw0xMTA4MjUyMDQ2NTdaMCECEFj45fAlvL/i +nVRFhjUgWu4XDTExMTEyMjAxMzU0MVowIQIQWP1lezYbBH3c0yd/xlLClRcNMTEw +MTI4MDkyMjE3WjAhAhBZYTwSyyY1hJL3TP88XispFw0xMTExMTQxMjI0MzBaMCEC +EFlt5G8xsAx5FWnL0oufUq0XDTEyMDIwOTAxNDI0NlowIQIQWX1U2MFdJNCMmp56 +vnOTvxcNMTEwOTI2MDEwMjA1WjAhAhBZk4A2nen3WsyA8GXD0ljaFw0xMjAxMTkx +ODQ0NDhaMCECEFnQGYAGd6BSrtm71VEfhrIXDTExMDMxMDE5MDI0MlowIQIQWeGm +MNFZiBOqt6riGtWqxBcNMTEwNjA5MTQyNTE2WjAhAhBZ7UxNo32cyyS9PnX5HbEb +Fw0xMTA1MDYxNjAzMDFaMCECEFosSW2CzmZ9oAzitw9F+2wXDTExMDgyNDExNTg1 +NlowIQIQWjAHq+lH9iIlackVn7JfcRcNMTEwODA1MjIzNjQwWjAhAhBaMr31EJc3 +Hrunn9BT9h85Fw0xMTEyMTkxODM2MjBaMCECEFo9U8cim+XMRMrZsILTyYUXDTEw +MDgxOTA0NDUzNVowIQIQWnFJLbrI2NiAxQRqChWvARcNMTAxMjAxMTEyODM5WjAh +AhBai8KoNtc1f8jGZj83tZ0+Fw0xMTA2MjcxNDI3MTJaMCECEFqhdqwiAloZUPO7 +85aPeRsXDTExMTAxOTIwMjIyMlowIQIQWqp9xI5KQy59no3Ua7N7DxcNMTExMTE2 +MjIzODU3WjAhAhBbCPQqXjN8izUOeFGZVWZ8Fw0xMjAzMDUxMTAyMDJaMCECEFsM +lfJbTz53RLaJlegKxoMXDTExMTEwMTIyMTExN1owIQIQWxPuLRDVIUD5mGG+Is50 ++xcNMTAwODI1MDkxOTM3WjAhAhBbFJtPcudW6+sLN03xqpARFw0xMTExMDEyMTQ0 +MDJaMCECEFsuPQW+Xt948bMhqB3jBrQXDTExMTIxMzE0NTI1OVowIQIQW0ij13ho +Ykqxbw5lMTslshcNMTEwNTE5MTcxNjM3WjAhAhBbWED/byTavnnZkYSNkYtEFw0x +MjAzMDgxMzM0MDJaMCECEFtZ9Oe+sCGXQBgrQ5ILadAXDTEwMDYwMzA5NTEyN1ow +IQIQW3h7kZmS+dYsPXTZi8AvMBcNMTAwOTEzMTkxMjM3WjAhAhBbiWV7rjzD56Cc +0oA5jxrPFw0xMTEyMTMyMzQ1MzdaMCECEFuixSr2thUVogn5JtUJYPgXDTExMTEw +MTIyMDgzOFowIQIQW7uF49fJghXJ3lb7KmMMhBcNMTIwMTAzMjI1MjQ5WjAhAhBb +6q41I+uSDKcMMpeWN070Fw0xMTA3MTIxMzA1MTlaMCECEFwNomYDHefmKC4Q6jUr +nMQXDTExMTAxOTAwMDIxOVowIQIQXA+R4bcasA7zCDJMvG6CShcNMTExMjMxMTUw +NDIzWjAhAhBcGyc5o3A2Qn7ghCgkBJkHFw0xMjAzMDYxNDAyMjlaMCECEFwhlDcx +mFi7Y07MPvx+5aoXDTExMDkxMzE3MTkzM1owIQIQXDS9lXc0MMvNXNqHGkujIxcN +MTAwODE2MjMxMzU3WjAhAhBcSRoKO2yuJTNMKQmez1IAFw0xMDA2MjIwOTMxMDZa +MCECEFxJXJP19NJHF3vGtRg2jVIXDTExMDMxNDEwMjYwOFowIQIQXGimha8TpbHO +b0g8Mr4SRRcNMTIwMjE3MTcwMjQzWjAhAhBcgzi6zpVaDqZguMnL+7FtFw0xMTEw +MjExNTM1MTlaMCECEFyF2r64S+p6+DOkrm+eqV4XDTExMDQyNzEyMTkyNFowIQIQ +XJN6neLYWjf216AtDAH7cxcNMTAwMzEwMjIzNjAzWjAhAhBclNkQBZ7ZcczxXL/r +8xmxFw0xMTEyMTQyMTEyMzhaMCECEFzWcXKzdmVrPAX7bBouM9EXDTEwMDcxNTIw +MDUwMFowIQIQXOAskT+EW+suAPivFlTqmxcNMTEwMjExMTYyMjMwWjAhAhBc5F+0 +ScHkUiv5ThMMepeTFw0xMTExMTQxMTQ1NTJaMCECEFz2gsAPOdtFt+Tg/YeptPgX +DTExMTAwNjIxMTMxMFowIQIQXPakpe/C8gzbrF4Wi0kHBxcNMTIwMTA3MTUwMjAz +WjAhAhBc+hu+jkots8jITvVwFghYFw0xMDA3MTIxNjUzNDVaMCECEF0DMJYpTbUe +SY6bGb5Gbj0XDTExMDQyNjE4NDY1M1owIQIQXSSo6MOOMvTh7/ryFbWDsxcNMTAx +MDA0MTU1MjI0WjAhAhBdJUsfLZ0Qqez4FdKRcUDtFw0xMTEwMTgxODQyMDhaMCEC +EF0qjBahP0IVevdQ6fReg8AXDTExMDMxNDEzMzYxNVowIQIQXS9lynZuOgdXhI8I +Sc0oshcNMTExMjE2MDU0MDAwWjAhAhBdXAbV/EaM/VZhdXjbZ0zCFw0xMTEyMDYx +MjAyMTdaMCECEF1e4c35H7kTPOfLvd9okecXDTExMDMwMjE3MzMwMlowIQIQXZ4o +xBGEhnnkNd/EwXFhOBcNMTExMjIwMDEwMjM1WjAhAhBdvNT1cVLGK7CNgmPpNIj2 +Fw0xMTAzMjIxNjI3NDJaMCECEF3VJsgbELCly9Vk5E9hiBQXDTExMTAwNjA4MTIw +MFowIQIQXf9eGi+fnql4ydE09tYUPxcNMTAwODA0MTcwNDM2WjAhAhBeBvaEi/kd +oGy33hQ9gcimFw0xMTExMjgyMjM0NDNaMCECEF4HGZ/tYYy370gkMmswmysXDTEw +MTAwMTE0NDQ0OVowIQIQXg8IkSP5su4tu4SU9oQjpRcNMTExMjEyMDg0NTE3WjAh +AhBeEp/aOTOJRTUPJUfPekGYFw0xMTAzMTcwNzA2MjNaMCECEF4joUhB+/AcgYIZ +msBxb9gXDTEyMDMwMzIwMDIwN1owIQIQXiezkeqnDptpnpYsCwdifRcNMTEwNjA5 +MjEzODEzWjAhAhBeMyAFFfwGyIhUPSeE6l5WFw0xMTA2MTYwMDUzMjFaMCECEF5f +IY9UEi1JZF99dZUkU4cXDTEwMTIwMjE4MDgwM1owIQIQXoyOiYUzYmkoCUpnqWwf +SRcNMTExMDA0MTg0ODQ0WjAhAhBejygChgdlYN2XhJQem7JXFw0xMTEwMDQwMDIx +MzBaMCECEF6RefgyKXrgSzIWnAgtCGwXDTEyMDEwODAyMDIwM1owIQIQXsBjbcJ0 +WsqZSqXotqmj2BcNMTAxMTAzMTI1NTU4WjAhAhBexuTNyk8jRtNRK4pjZdzYFw0x +MDA3MTUyMzExMzVaMCECEF7K7bc6OGtt6W9u+JIlOGgXDTExMDIxODE5MDIyOFow +IQIQXs1cu0KV67/biJV0c5qONhcNMTIwMzAxMjEzOTE1WjAhAhBe5fWoYmXCF9H0 +pcvAv5ARFw0xMTEwMTgyMDE2NTFaMCECEF716pBCC9QU5PfbTj6GBncXDTExMDYw +MjIwNTAyMlowIQIQXxurO7UmUGN1MY4LkAqD3BcNMTEwNzEzMTU0MDIwWjAhAhBf +TcOr8UGcYWgtyjUGTqUTFw0xMTEyMjMwNjA3MzZaMCECEF9V4dZED9+ovToqVOUi +0zEXDTExMDYzMDAwMzAzMFowIQIQX1gZ2B3UgrIInj7Ha3BZRBcNMTIwMjA0MTIw +MjEwWjAhAhBfhKWVmPKm3ExWJFmTDSEiFw0xMTA4MTYxMzQyMzdaMCECEF+TghEB +mcWj9dbUIeS0ETAXDTEwMTIwMjA2NDIxMlowIQIQX55fxce9EpBMnNAao5NcEhcN +MTExMDE5MDAxNDUwWjAhAhBfoPakXI+/3lNfM0outMk4Fw0xMDEwMTgyMTM3NTFa +MCECEF/W421a21Zwsy7Emht/fzMXDTEwMDkyODIwMTkxM1owIQIQX9yPRZw9sUew +sqz7OiozhBcNMTAwODA1MjE0OTI2WjAhAhBf5r4UPhfpwipbQ/rSL/9yFw0xMTAz +MjIyMTIyMjRaMCECEGANpTDh/87mz3/cWTafgMEXDTExMTAxMDEwMzg1MVowIQIQ +YBRHc3a7n1OyJ7KziCWlGxcNMTExMDAzMjI1NjU1WjAhAhBgPhmo3VScApRydOxY +uDKqFw0xMTA3MTEwOTMwMTRaMCECEGBEuZ8PazAJQTTli3EeiYkXDTExMDkwNzE5 +MDUxNVowIQIQYFOgZ8q8D7MeblwJ1+izQhcNMTIwMTE4MTU1MzU1WjAhAhBgWSYP +eTUHMiAidSUUH9q2Fw0xMjAzMDcyMTAyNTBaMCECEGBaRsG2DvODUNv+y6HlvGMX +DTExMTIwMjE3NDYyMVowIQIQYGEKIJMMATUM0hXFDjSjVBcNMTEwNjMwMDQ1MzE5 +WjAhAhBgYVRjLNCv9+QNGpnmGVlbFw0xMDEwMTQyMDE2MTRaMCECEGBvMnL2us8P +vOSvHR59c8kXDTExMDYwOTE4MjA0NlowIQIQYJW/k3Kn5OCBmKbo4VknYxcNMTEw +OTAxMTAxODMxWjAhAhBgs0EstqsFzsMTW2vx9KApFw0xMTAzMDcyMjE2MDZaMCEC +EGDb2UpNB2IpDJvZaQf4ldcXDTExMDUwNjE4NDcxN1owIQIQYOweC94mESpugHaN +GSL8fhcNMTExMjE1MjEwMDAzWjAhAhBg/N+YeSQGcSVFtpwV+aNHFw0xMTEyMDkw +NDQzNDFaMCECEGEGHTaLEyfI3IJsok7z9yYXDTEyMDIxMzE4NDgwMVowIQIQYR9Y +cwz6ghAJYstgoctSEBcNMTExMTI1MTIwNjI0WjAhAhBhZ+wG8MLy2KMtq96ithcc +Fw0xMTEyMjMwNjA2NTNaMCECEGGBSYl/3e2ypvGIBjR1Vr8XDTEyMDExMjE2MDkw +M1owIQIQYYdNq6vLt0bvLFv+lZpl2RcNMTEwMTI0MTkxODQxWjAhAhBhinO5QECt +JJgP5hhyoNrYFw0xMTAzMDkyMDQ2MjZaMCECEGGaoPlBUkdlWPrk6db/b1wXDTEx +MDQwMTE5MTgxM1owIQIQYc38AEaaNpmp6ggwZa0yNhcNMTEwNDI5MTY1MDEzWjAh +AhBh1tf4w1B9BXX4Q71wzdcqFw0xMjAyMTIxNjAyMzJaMCECEGHYmK3+I9DAD8kz +VLc/ZOcXDTExMDkyMjEwMDYyOFowIQIQYey+XkVkTaVzIDXDM6+kCRcNMTEwODIy +MTUyODQ1WjAhAhBiCcSJpQ9QXV4XYuLt8lhhFw0xMTExMTQxNzE1MjlaMCECEGIi +vn76o6tBmjd5UgPIc+cXDTEwMDYxMTIyNDIyMFowIQIQYi0Mhl1Frj5iwjEgw8Uj +lhcNMTEwODE3MjEzMTE4WjAhAhBiZKonYhFmJeuc7aOoH0y1Fw0xMTExMTExNzUw +MTNaMCECEGKZLqKXtik5hSAmhfV9tL0XDTEyMDExNzE3MDI0OFowIQIQYrtDkqPm +U3Hl1yY4lNhNKRcNMTEwMzA5MjA0MDMzWjAhAhBizSHn50TExiadsPCjekLyFw0x +MTA3MjgxNDUwMzBaMCECEGLanIVtlT/uCkD01dB922MXDTEyMDEzMTE1MDAyN1ow +IQIQYtvUvy9va3D1tkpvngJLShcNMTExMDMxMTI0NzAxWjAhAhBi+RBKCc+zvroj +k3U/fsN5Fw0xMDA2MjQxNDIxMjRaMCECEGL7r7MTAJOlyx7P7i5vYtQXDTExMDQx +NDA1MTYyNFowIQIQYwPxNfCZV/98anGQdOuyChcNMTExMTIyMTUyMjIyWjAhAhBj +E/snw2g9SHnI51zzmaeTFw0xMDA3MDkyMDQ3NDRaMCECEGMYgl7DkmjvvEQIskDe +/kAXDTEwMDkyOTE0MDYzMlowIQIQYysRCqG0hktHW3lhLcrWDhcNMTAwNDIxMTQx +NzQ3WjAhAhBjMMm8eJsmCwYRRBy2hF2tFw0xMTAxMjYxMzIyMjlaMCECEGM6JD/b +Sl+j8iVJ5bvgcwcXDTExMDMyODEyNDEzMVowIQIQY04U+7Tjx9AGGwNz8Vc0SBcN +MTIwMTEyMTU1NzI2WjAhAhBjaeEEunr0+5rtlSK1zdhTFw0xMTA1MzEwOTIyNDRa +MCECEGOABAdYgPwLyFMRENZOllEXDTEwMDgwMjE3MjA0N1owIQIQY4l6JiWpvGKI +nrnGkuaDtBcNMTExMjA2MjMwMzM1WjAhAhBjkGXlJpiWZJQAo1NGydYEFw0xMDEy +MTMwOTMwNThaMCECEGOhFkHcUWJqrpFyEWK8Mm4XDTExMDMwODE0NTA1M1owIQIQ +Y7/ReHtMrbvq6Uzt99NiNhcNMTEwMzEwMDQyMjA2WjAhAhBjxxtvI+UwPyIM5f8h +ejbNFw0xMTEwMTgxMjM0MDVaMCECEGPSikHnmGidLk9BQdMKrhgXDTExMDIxNTIx +NDIxN1owIQIQY+2AyXYzxyTysrjM879kcxcNMTExMjAxMTUwNDQ4WjAhAhBj7fAH +8BEq10Vp1rcGdU8CFw0xMTEwMTkxODQ3MjRaMCECEGPuLFWbpt7QAFCpPFNqWVwX +DTEwMTAyNjE1MzAxMlowIQIQZCNuEjeLtEFp+yf9Ls6ZixcNMTEwNDE5MTYyMjU4 +WjAhAhBkJcXS14lpssjnx8PdliUZFw0xMTA5MzAxOTU3MjJaMCECEGQxCpDgUe1f +Gx/QJhMKAWMXDTExMDQyMDE3NDU0NVowIQIQZIKWmA3isKATt9xrQD4xphcNMTIw +MjIwMTk1NjU3WjAhAhBkjnj9tfWcNlx4Nop+koIFFw0xMTA2MjcxODE1NDFaMCEC +EGSlWXOAFaZUg2SwPI+o8iwXDTExMTEwODA4NTIyNlowIQIQZNUIVzLqC1zmY/cZ +6U9I3BcNMTEwMjI1MTMyODM1WjAhAhBk4B/LwiFh2Avdr7YTXVICFw0xMTA5MDIx +NjI2MjlaMCECEGThyq4skqaztsssSEB0g6oXDTEyMDIxNzE0MjcwMlowIQIQZOWN +9Yzg/vzHw70K+5DW+BcNMTExMTE0MDEzOTI5WjAhAhBk7xxuCPkKb8KoUbQMp0SM +Fw0xMTAyMTExNjIyMjhaMCECEGT61HLsETrh8OqXJysPqRoXDTEwMDcxMDAwMTcx +OFowIQIQZPuAoREi1NSYBo9d1fAWeRcNMTEwMTI1MTQ1NjIzWjAhAhBlEDSbQIRf +DzOumXATEQbEFw0xMjAyMDYyMjE4NTRaMCECEGUoHITx+n0iiut4St0QrvYXDTEy +MDIyOTEyMzQ0MFowIQIQZUtBvqy1CXiVoo2AHoyhoRcNMTExMDMxMTYyMjM2WjAh +AhBlUQFHTg+8hzgI1O1/9Cq3Fw0xMTAzMjgwMjAxNTBaMCECEGVd7oXfia0vg/9E +h4HRNJoXDTExMTEwNzE4MTAyNVowIQIQZWBAHGwNAzLp6Zd2fTUnkxcNMTAxMTI2 +MTkwMDUyWjAhAhBleil8e8tCxRofMHe7BjMQFw0xMTAzMDIwOTAyMTBaMCECEGWK +qUj4BVhoa8RUdqD/m8sXDTEwMDgwMzE1MTExOFowIQIQZZ/lnRQHWv2MilIxcPPW +5BcNMTIwMjE3MTQyOTA1WjAhAhBlqpW66Sj7rC2iesUKQFejFw0xMTA3MTIwMTAw +MDFaMCECEGXVt2dHO5kymB2wuzJUzNkXDTExMTExMDE2MDMyNFowIQIQZd6sLv5W +G7UKFJHx+6ECvhcNMTIwMTA1MDM1OTU0WjAhAhBmAsYzBpaGtHERg2Z9YyBZFw0x +MDA0MDYyMDA4MjJaMCECEGYIvVEGlKMoa+lEj04LOPAXDTEyMDIyNDIxMDI0Nlow +IQIQZjlFq7KdGfeQkDDNSTyTBxcNMTAxMTEyMTAyNzUwWjAhAhBmaa+ZHIRXgR74 +QJghrjVfFw0xMTA0MjcxOTQ3MzBaMCECEGam5E7c3xJ54OoO6HVzc9cXDTEyMDEx +NzE5MzMyMVowIQIQZqez4OnxAyENxripTPY6RxcNMTEwMzEwMTE1MjI5WjAhAhBm +rUm2CG3a+xcsWJby2Y5LFw0xMDExMzAxNTQwNTNaMCECEGa7I0A/5xhPJ3xU7ybY +IRwXDTEyMDIyOTEyMTQ1MFowIQIQZtPtglKxw2OGq4gXxtte8hcNMTEwNDE1MTA1 +NTA5WjAhAhBnEXI9xT1XsUsO5elWrRQ1Fw0xMDA5MDcyMjA4MTdaMCECEGcShCx1 +XvGbrrRWLmNm/IMXDTExMTIwODE0MTczMVowIQIQZxNVR1ZgaxAz6eSe8KdjvxcN +MTExMDA0MTEyNDU5WjAhAhBnHzpoOxRYl7gtmCRAjFwAFw0xMTAyMDgwMTAxMDFa +MCECEGcqxkiyj4MinlABovtdn+0XDTExMDkwNjA2MTAyN1owIQIQZzQAnGSRFQKV +atSnxRJPUBcNMTEwODE3MTA1NjU5WjAhAhBnQqmddpW055Mc1h3IYtlaFw0xMTAx +MjUwMzQ3NTdaMCECEGdo3odZcG0rcg8X3YCc000XDTExMDIwNzE2MjIxOVowIQIQ +Z24FUxQj0Vgggq/286uj9BcNMTIwMTE4MTQzNzM3WjAhAhBoBH0yTV5v8U1vATMU +R3SYFw0xMTAzMTUxMjIyMjJaMCECEGgKWtgO7KBtW6nx1bzXIG8XDTEyMDIxNTE5 +MDIzOFowIQIQaAunEL/nduG8ZpfrVa+toxcNMTIwMjEwMTM0MjIwWjAhAhBoFD+4 +g+hve/av0TeVdfuGFw0xMTA3MTQyMDUzNTdaMCECEGhAuxu3RHM2I0QbHpcRO1cX +DTEwMTAyNzA5MTIzOVowIQIQaEi3aWFzEF9a2dw7HVNhXhcNMTEwNjMwMDAyNTEw +WjAhAhBoZaT3BHGK4usWtbxz5XtUFw0xMTAzMjIxNDI4NDJaMCECEGhvW5jKIMO8 +paVUGKrHwcwXDTExMDMxMTA5NTcwNVowIQIQaHwhh642d2CjerZBFNtiDRcNMTEw +ODAyMjMzNjIwWjAhAhBohZKiNwRZE5r2PqE1rB+wFw0xMTEwMDcxODIzMTlaMCEC +EGiGP91TGzine40vjlFD3MUXDTEwMTAxODIxMzk0NlowIQIQaLzJ32u/vw5Z312u +C3PichcNMTExMTA3MjIyMTA0WjAhAhBoxC4ypBk7kG3t69eTOPC3Fw0xMjAxMDYw +MzE0MjZaMCECEGjEm2SQSzi/b8M7Tliy47IXDTEyMDIyMDE4NDAwN1owIQIQaNhK +22NETEKR4mYQ0BOxdhcNMTExMjIyMTYyMjQ4WjAhAhBo7p/h1zZ+CjW+3g0w5C25 +Fw0xMjAyMTMyMTU4NDlaMCECEGj4IkUDfdjKoFeYRyWKrgwXDTEyMDEyMTA3NDQw +N1owIQIQaREkU19WjFnAtkQXBe+75hcNMTEwODI2MTAxODIzWjAhAhBpGaa5E6Jw +8KqzyKEaF67YFw0xMTAyMjUwODAyMzBaMCECEGkh++HtFCMFEPqvi1COv0cXDTEx +MDUxMDE1MjAzNFowIQIQaUity9lxbdJG4/6oox1yOhcNMTExMTIzMjAxNzQ3WjAh +AhBpZ87Zv38Nb+AUcu0IsddbFw0xMjAxMTMxODMxMzhaMCECEGlzLlFqOj1ywvtq +WJ5Yz08XDTExMDEwODIwMjE0OVowIQIQaXNskkxB9EBtGRbq3WmFVRcNMTEwNTA0 +MjMzNzEwWjAhAhBpnn5kKE42lHi8xRZ+ILREFw0xMjAxMTgxODE0MTlaMCECEGm9 +6tHNj1eqG5pxM3Po83gXDTExMTEyNDEwNTkwMFowIQIQactn1zYtWWXUWf054S+9 +dBcNMTEwNDExMTM1NTExWjAhAhBp2HIdMH20cfTLIIdw90rDFw0xMTExMjExNDI4 +NDVaMCECEGnepxV888pJgaAewwntLXoXDTExMDYyMDIwMDAyNlowIQIQaeHyuJn9 +qDRKRu54Ul3qlRcNMTIwMjI5MTIxODQ1WjAhAhBp78RUKKrb4PL9cJXk30oZFw0x +MTA1MTcxNTQ2NDJaMCECEGoVFozPYDU1W6gzzjvG0fsXDTExMDQwODE1NTQxM1ow +IQIQaiNXrKpCKsAFFrSxKefTqxcNMTAxMjA5MTgwNDI4WjAhAhBqKcpifsJTO0RM +odQ7AO8KFw0xMTA1MDIyMzA5MTFaMCECEGpR010JxXr9QZz7kygxsngXDTExMDQy +NzEyMDgyNFowIQIQal3Aaa1hD1KhWugflvt/ehcNMTEwOTE2MTgwNjQ3WjAhAhBq +ZwcLHMjJ7pR1C/G4uDbsFw0xMTAyMjgxODU1NDZaMCECEGpwzwneBofePVMTcRj2 +DggXDTEyMDEyMTIyMjIxMlowIQIQap6FA2YAGdHEUOa3wOmtFxcNMTExMDA2MTY1 +NjA0WjAhAhBqtygyjbbW/rDJ3TMOn9EcFw0xMTAzMTAwMDAwMDFaMCECEGrLij1D +pW1wcSU6LcSn6RsXDTEwMDkwMjA4NDg1M1owIQIQauFi4Q23N75NNg308tJUshcN +MTEwOTI3MTg0OTExWjAhAhBq8mmZNPgkit1avBw8QCylFw0xMjAxMDkxODA3MjFa +MCECEGsClx46Uch0udNSMJp5rE4XDTExMTEyMzE2NDAwNlowIQIQawZ6XErNhqkI +FOQK/czOTBcNMTEwNjMwMDAyNDAyWjAhAhBrFO+THOce+gGKSqmqAxLdFw0xMDAz +MTAxOTIyNTlaMCECEGtTRCgr56pCGYNjdbRMzMkXDTExMDcyODIxMDAxM1owIQIQ +a2cbrNik+P0HgKVNjev0YRcNMTIwMTA1MjE0NjIxWjAhAhBraz3iC0mLpBZA3IXO +J7GwFw0xMTEwMDUwMjA1MzZaMCECEGttSG40n5426brzNyC+Sf8XDTEyMDExODE0 +MDIzMFowIQIQa4UwthFapc6Z/C7GLPWmHxcNMTEwODE2MTM0MzI5WjAhAhBrlgib +hYgpMpZD6ma8GGtSFw0xMTA4MTYxNzQzNTJaMCECEGubflvM3vyYi7MrZdf/56wX +DTEyMDIxMjE2MDIyMlowIQIQa6zWAtQXhroP5J/yenDMUxcNMTExMDE4MTMzOTAx +WjAhAhBrrZsiU29Mdmhg3+cSev3wFw0xMjAxMTYyMzIyMzNaMCECEGuwpzSaZoLC +FuM2yIXxya0XDTExMTIyNzEzMzE0MVowIQIQa853c5tHXpdJLKBfHX6V8BcNMTEw +NjA3MTQ0NTU4WjAhAhBr4Twx3pKIH43Dd/CSbTKpFw0xMTA2MjAxNjAwMDBaMCEC +EGvoMUtSZxLF+yJt0NNpd+YXDTEyMDEwNDAxNTY0N1owIQIQa/P0AYnH+dK+DAtF +vjL2vBcNMTEwMTEyMDcxMjI0WjAhAhBr+JVigqzKPRaJuewqj/rKFw0xMTA5MDIx +NjE0MjVaMCECEGwCSqIFGfl7esWuRLrHY9kXDTExMDgwMjE0MDgwMlowIQIQbAud +DHg921roE2lgGvEHEhcNMTAwNzI2MDk0MzU2WjAhAhBsFuwc71X/3jBvfCVGCEFx +Fw0xMTA0MTQxODI5NTFaMCECEGwdD1TMQHkpVQAL357gHk0XDTEwMTAwMTE0NDQx +M1owIQIQbCW5SFWXD4xSOAOLwxjAuRcNMTAxMDE5MjAwNDA2WjAhAhBsLHngwQXZ +rLdx8xqYPaDxFw0xMTAzMTIyMTEwMzRaMCECEGxaLSDxzikaVPoZWQTInToXDTEy +MDEzMDE5MDIxNFowIQIQbH3URF29potH3FER4Zuj9xcNMTExMDAxMTgyNjQxWjAh +AhBshZ4MT52/c/VX5Y6QtYgQFw0xMTExMTcwNjM3MjlaMCECEGyJqJKAySvWyKbT +mL8lUmYXDTExMDgzMDE1MDkzNVowIQIQbJxQEL4icJnDHvo1E66FhxcNMTEwODAy +MjIzNDA2WjAhAhBsvPxL+tspDj/C4hwda1rFFw0xMDEwMjkxNDUxMjdaMCECEGzB +BWDKZrC1ErrjAgacLWwXDTExMTIwNTE2MjI0OVowIQIQbMlBUvj64ppCcmz6C4MG +bBcNMTExMDE5MTk1NzQ3WjAhAhBs0sMEKmwSULMyT7B0x56+Fw0xMjAyMDgwMTAw +NTRaMCECEGzTxi2Z0oTDNXiHplvksLUXDTEyMDMwNjEzMDkxOFowIQIQbN5Qr/2w +5CbDAaGJuFX23hcNMTExMDA0MTcxMDQ0WjAhAhBs5ExY2HGrzdPprRsAAVlaFw0x +MDEyMDMxMjIwMThaMCECEGzkWnDrIR8RK/TOjzPdHOUXDTExMDMxMDAxMTAxOFow +IQIQbTzCR5PKHuAHCU2h+WN/ShcNMTEwNTIwMTAxODU1WjAhAhBtTPnM/QVgMSLZ +0yf6nMvlFw0xMTExMTYyMTMxNThaMCECEG1QjKYmAkGasXuozwCIIBcXDTExMDMw +NzE1MDIxMFowIQIQbWDY5DYy5mxcX+FYdP07VxcNMTEwOTE2MTIyMjQ5WjAhAhBt +fX1bO0jf0MYiXkuRg+tOFw0xMTEwMTcxMTQyMDhaMCECEG3GYiqluIa+RNDpeVOn +eGcXDTExMDMzMDE0MjU0MlowIQIQbdo/lTgo9VS0ItgA20N9sxcNMTEwOTE0MjMw +MjA3WjAhAhBt4HFx9kko5BeFdgyVO6qZFw0xMTA2MDkxNDI1MjhaMCECEG4BKeXs +zVtZ+stvlwLwGc0XDTExMDMxNDEwNDUxMFowIQIQbgwRS7HIjaOTOH6ajtQ0iBcN +MTExMDE4MjAyMzM1WjAhAhBuEZFvBOwtAZHxa1Ljjs+PFw0xMDEwMDUxNjAyNDla +MCECEG4n1WhfnPdoYcnbeiH1c98XDTEwMDkyMDAzMTEyNFowIQIQbinlBD3lUbaz +rV7QgYEulRcNMTEwNjAyMTczMjExWjAhAhBuKebzqzwIDH4TGcV+UHFjFw0xMTEw +MTkxODU2MzhaMCECEG5sfW7lCLIdh+Ob94pf7A0XDTExMTAwNDIwNTUxM1owIQIQ +boaoDmoDgKuVPARHLn2wDxcNMTEwNzIwMTY1MzE1WjAhAhBuj1JOKBwFOcSv2Gth +ccWpFw0xMTA5MjcwMjU3MjhaMCECEG6R8CkHf6OS5hZXumQATnQXDTExMDMwMTE0 +NDQzM1owIQIQbpKLF31yNR2785YoEnLWBxcNMTAwMzE5MDEwOTM0WjAhAhBulEE7 +rLCqu/pZgVKaz7foFw0xMjAxMDYwNTEwNDBaMCECEG6o7+0EKWftjKishjJy/NcX +DTExMDgxNTE3MTkxMVowIQIQbrg2/QyYl16um0gRkLP19RcNMTIwMTMxMTI1NzQx +WjAhAhBuwQ5nkMOVCNu0buYAYvLtFw0xMTEyMTQxNDM3MDdaMCECEG7hdDUZxc4e +jmOADqmf39gXDTEwMDkxNzEyMzMxM1owIQIQbudZnMb9ZsKMjJdOUiOeiRcNMTIw +MjAzMTc1NDU2WjAhAhBu8cEdqazuO11Oa/fHKlzdFw0xMTAxMjUxNDU3MDVaMCEC +EG8AeRgXDospGeuoMG/z7yMXDTExMTAzMTEzNDA0N1owIQIQbwySTOVe7rKUExTG +mOb50hcNMTIwMjE3MTAyMzA2WjAhAhBvDxGKI4zHtlBb08aQe9ncFw0xMDA5MjAx +MjM2NThaMCECEG8+kG7ssfCh7KONzLXwwv0XDTExMDIyMzA3NTcwMFowIQIQb2hi +jUCEu0SVLwCMVtBHPxcNMTIwMjA5MDIwMjUxWjAhAhBvsTw/8zq+O0OKhlnjNGRK +Fw0xMjAyMjMxNTI3MjZaMCECEG+18LKvhRWrG1evAnVdxlIXDTEyMDIxNzE2MDI1 +OFowIQIQb7jkglBTFPkOpaFjNYDgphcNMTExMDI3MjE1NDMwWjAhAhBvyX3A9mbd +FqZ0LyMfU1czFw0xMTEwMTgyMDExMzNaMCECEG/WtWGguuBfMOksQqJXM0MXDTEy +MDExMTIxMDI0NlowIQIQb95Q7WRbj0rAnCY+6QdRuhcNMTIwMTMxMTI1NTAyWjAh +AhBwCYNCQy5hMhdrrFVlL2SVFw0xMjAxMTcyMDQyMjVaMCECEHAJwxt3PR6DVMa4 +sRiCAr0XDTEwMTAxOTA4MjYxMlowIQIQcAtjiBE8UO7S0H3TPPGbjRcNMTEwODAz +MTc0ODU5WjAhAhBwJ0oJvWCj64DM5TdkjuqoFw0xMTAxMjgxNzA0MDFaMCECEHBJ +vLh81CIe1wCBvHaimLEXDTExMTAxODIwMTM0MFowIQIQcFZy1iia0C9jx4MP3eci +2xcNMTEwNDI3MTUwNjA4WjAhAhBwX/Wq2Qz0+fN30URVQYcjFw0xMTExMDcyMTQ4 +NTlaMCECEHCSe2Et+1WOauCKyr4Z0uQXDTEwMTIwMzEzMjA0OFowIQIQcKif/vvm +7dfugJe78aHu4xcNMTEwMzA3MDkyMTU1WjAhAhBwur+LB+lmtHA+8yq7hImHFw0x +MTAyMTExNjIyMzVaMCECEHEGwuY9IdZPCxFD9dmQ4y4XDTEyMDMwNjEwNDc1OVow +IQIQcSdClXJU2/mTPLK4bCZW5hcNMTEwOTI4MDEwNTA3WjAhAhBxXQ+qalIBaCgA +WFSqnnP+Fw0xMDEwMTUxMTIyMzBaMCECEHFjpyPJkZQ8N6WrqPoGyCoXDTEyMDIy +MjE0MzQ1OVowIQIQcYSB+ULP9X0rhuewObHjOBcNMTExMjIzMDYwNzEzWjAhAhBx +nkJuppRDHWR7wp53eazKFw0xMjAzMDgxODQyMzRaMCECEHGxjxohmU7Fl/M1tVfh +YW0XDTExMTExNjE5MTQzNVowIQIQcbRAU0xmaSFm0ah4leNCIRcNMTEwNjMwMDAy +ODUyWjAhAhBxw9jJb9yz8n5P9MJHYoFLFw0xMTEyMTMyMTMzMzZaMCECEHHg+ghs +h7g11RVAKh2v4rAXDTExMTExMDIwMjAxM1owIQIQcgpY+Oj7wFjcibXFsONydBcN +MTEwOTI2MTA0MzEwWjAhAhByGhYlzkE0cGrT7x7YYB2kFw0xMjAxMjMxMzE0MjFa +MCECEHIicaNQePVh00BTHAfxujIXDTExMDkxNDE0MzYyM1owIQIQcje3QeOJn1eP +Tzvxy9nrmhcNMTIwMTA0MDE1NzAyWjAhAhByQcyg/CznqJOOwaMemAb7Fw0xMDEx +MjMxNjQ3MzFaMCECEHKGWvCI0GajR/cB/Bke84wXDTEyMDIyNDE3MzU0OVowIQIQ +cq7J6d0YElM1ZVAMtK+8lBcNMTExMTEwMjM1MzE5WjAhAhBywSKQFM64B2wEJPM2 +VFQ4Fw0xMTA1MTYwNDQ2MDZaMCECEHLGJEHE2FuzU2UqDM70qDAXDTExMDgzMTE1 +MzI1MlowIQIQcvAt9t/UJgRmvhtGbG0DuhcNMTEwNDE4MDU1NzU0WjAhAhBzHFNR ++hOx41QqWnh+XhGiFw0xMTA2MDMxMzQ1MDRaMCECEHMk6Wf1TsldJvwpEWqLuJkX +DTExMDQyNzE5NDgyNFowIQIQc0X0QfbWqEX8vTwX56PMhBcNMTIwMTMwMTY1MDE3 +WjAhAhBzU+QMAgCttpTwMLF1pl4xFw0xMTA2MTAwNzQyMDFaMCECEHNhmSxLSm6N +wlPYCReqMa4XDTExMDkwNjEzNTAwNFowIQIQc2hrd/RoKLAA9DyWvttUxhcNMTIw +MjI4MDk0OTI2WjAhAhBzfgz6iKaYRtcHDdV4Lm1tFw0xMTA0MjAxNDIyMzNaMCEC +EHOGjJk+9uulnfU4nA+OiPUXDTEyMDEwNzE1MDIxMFowIQIQc56NXP5OqRZntrfL +Z4y8GxcNMTEwMzMwMjE1MzE3WjAhAhBzpREPrDRuvP9+dtQYV5qzFw0xMTA1MTMx +NDEwNDdaMCECEHOrF7isVTccO9GwV47NtdMXDTExMDgwNTIyMDIzOFowIQIQc8L2 +C+AyTNITrjR5/BhvyxcNMTEwNjIwMjAwMTExWjAhAhBzy9VtMXKBPf6E5ejo5S+l +Fw0xMjAzMDIwMjMzNTRaMCECEHPO6+XnzjuMBNt3KzRhFsgXDTExMDQwMTEzNDU1 +NVowIQIQc9nMwuFQIgwTOPLoNHDORRcNMTEwODA1MDIyMTI1WjAhAhBz+Ah+8Obc +oHzVikWd4McEFw0xMTA1MTYwNTUyMTVaMCECEHQBYq9Z1SL+a/MtC+Hl83cXDTEw +MTEwMzIyNTcwN1owIQIQdCGZCF8UajKdHMrjdvyusRcNMTEwOTEyMTgzMTE2WjAh +AhB0Kyj0HfPv7HoaDu+UT9BaFw0xMDA2MzAwMzE2MjVaMCECEHQ8SMrO9S/qQ7yg +vhTGIj8XDTEwMTIwMTAzMzcwN1owIQIQdEKt5rcFHTjLCJhh4NvsDxcNMTEwOTMw +MTQ0MTI0WjAhAhB0iMlP8HL3jLT7cf22twqeFw0xMTA1MjQxODM0MjZaMCECEHSm +97RLH50xAbU6qkv1LAUXDTExMTIwNTE0NTM0NlowIQIQdKnsE6gVctMNatjB482W +ShcNMTEwODA1MDIyMDU3WjAhAhB0xJJviKAZstM9nZNBLTeCFw0xMjAxMTIwOTU4 +NDVaMCECEHTV3HshGf1v9sM761gw1MoXDTExMDYzMDAwMzIzMFowIQIQdNdQJMWG +lkjV6251voGeuBcNMTExMTAxMTgzMjMzWjAhAhB06mps3novKasEsxcX8JfKFw0x +MDA4MjMyMTMyMjVaMCECEHUEsOScRYybeLuf8QKtNxYXDTExMTAxODE1NDgyMlow +IQIQdRYQIcVEdFLfLF9k/CL4AhcNMTExMjA1MDcxNTA0WjAhAhB1HVXpftOLHXTu +bYMKx7+gFw0xMjAzMDExODAyMjlaMCECEHUhCXVTDzCx04n4iQKGnBQXDTExMTEx +ODE5NTc0NFowIQIQdScZfdkW+gbCzA3iWkobMxcNMTEwOTIxMTUxMTE0WjAhAhB1 +LQTWsnOa1E2JMMVet31eFw0xMTEyMjIwNzA5MjJaMCECEHU/e/tH90qGfXFMjrw7 +ZZYXDTExMDkyODE3MzUwN1owIQIQdUIFJPtNVzBnj41LG5lpOBcNMTExMjIxMjMx +MTM1WjAhAhB1ak/kW8HndJFPbUZZyxutFw0xMTA3MTUwMTAwMDFaMCECEHVuf9PI +/FL7TXh6L7Q1yVMXDTEyMDMwMTA5MDQxN1owIQIQdaT/6AMLJqCeZF/bVwprcRcN +MTExMDEwMTcyOTU5WjAhAhB1twv6vnQNL5YsSHrRuHTnFw0xMTA2MjQyMjAwNDVa +MCECEHXI/UGKxRcqmBGWK9RSUygXDTExMDMyMTE3NTUwNVowIQIQddVab3oiIIPS +ZSZqjUDx1BcNMTAwNjAxMTY0NjM0WjAhAhB1+c6KvZmPYEzYpttIDe4gFw0xMTEw +MjQxOTUyMDdaMCECEHX77mqYJA6togfc5WGGmIIXDTExMTIwMjE3MTMzMFowIQIQ +dhk0SavRiTZqASF/4LspxRcNMTIwMTA5MTY1NzA0WjAhAhB2UJKIQnzDk8Fo3TH9 +T6QXFw0xMTA4MDUwNTAyMDFaMCECEHZQ0MZV4RzE46Xv4zwjTeoXDTEyMDEzMTIw +MzkzNFowIQIQdlZ5tgivxRc9+dGiNeRI3xcNMTExMjEyMTkwMTM3WjAhAhB2XX+B +Ax/m+JDe5panWg3oFw0xMTA0MTgwOTQ3NTRaMCECEHZi65czusY+pvdHJJp7D9IX +DTExMDQxMTExMTYzOVowIQIQdmpxDXHRvcMIkYHEJdsHxBcNMTAwNTEzMTUxMDI0 +WjAhAhB2cAVRw65C/KEWs54EOXRQFw0xMTEyMjkxOTQyMTVaMCECEHZ2/7M3kjGb +3Xg/0wDAryQXDTExMTEwMzIxNDIwMlowIQIQdnhsmQ4r5jweJ7IUBZ0/BxcNMTEw +MzIzMTgyMjE2WjAhAhB2wBXCnBd2jHtgIgxOdXTnFw0xMTA0MjcxMzUyMjRaMCEC +EHbxbYQ1qfxgbd+miTAQ7dIXDTExMDUwMzIyNTYwNVowIQIQdxdKkPvBy3DXGIkF +fm3f0RcNMTEwODA0MjMxNTU1WjAhAhB3XY+AXFPWbrRl/NzyoRv9Fw0xMTExMjIy +MDAyMjdaMCECEHd9ph/EMbxWAhj7LDbo7FUXDTExMDYwOTIyNDIwN1owIQIQd4XT +Alpgm5WULSgyHwT9BRcNMTExMjE1MTUwOTQwWjAhAhB3h1OjJlLCgr+Id+ShG4OU +Fw0xMDA3MTQyMjU3NDBaMCECEHeMQm0FojD4rrS7OeEkgU4XDTExMTIyMzExNTg1 +N1owIQIQd5tlUnNPCQPzviPKXNtxmxcNMTAwNDEyMjAxNzUwWjAhAhB3m4R8r9M0 +AEaujYjY5k0gFw0xMjAxMTYxODAxMjFaMCECEHeh3svFgBZyG+jhDMMi3YkXDTEy +MDEwNTE4MzQxNFowIQIQd7n7rdBS0mC8z6esGaalMRcNMTEwNTMwMDQxMzMyWjAh +AhB3y2PV7G7zzw9OE1bo0+epFw0xMTEwMTkyMDIzMzNaMCECEHfdfi5qORi+cxQD +La/XFccXDTExMTEwMTIyMjMyOVowIQIQd/aZemGF8/aD7Jxk3JO8KxcNMTEwNDE4 +MTIxNjEwWjAhAhB4AyuRTKYzXM987W4xVtR3Fw0xMDA5MTYxMzE5MjFaMCECEHgN +HTDUs8Gqqc8W9Ov8/HkXDTExMDUxODExMTY0MlowIQIQeB6YRAF8VJiNYGAUj1HT +tBcNMTIwMjAyMTAyMDQyWjAhAhB4VWBJZFvcLxg6OpOIdg1WFw0xMTA0MDExMzQ0 +MzdaMCECEHhrd6EiQkjdQ4p0wxYzw4sXDTExMTIyMDA4Mzg1NFowIQIQeHya3uc8 +nmuDFw2NazOFKBcNMTExMDI0MTUwMjIyWjAhAhB4nA0VsfGgNH98bduaYXgDFw0x +MDA5MTAyMjU4NDRaMCECEHinkLX9G/mjKksdbvMaElYXDTExMDUwMzAyMzI0OFow +IQIQeNEngynwscSDQA9Otgr+bRcNMTEwMzA5MTA1MzE3WjAhAhB44buvDYmLoQtL +/tGo3qbgFw0xMTEwMjEyMTE2MjVaMCECEHjydey6kEakoCSMbzjqyP8XDTExMTIy +MTIyNDIxMlowIQIQeQrnkS5TxWikyxWfpMyClxcNMTEwODE4MTMxNzAyWjAhAhB5 +F64RbYi48I3kUgfBxiAFFw0xMTA0MDExOTIwMDJaMCECEHkZf5w2oLIiTm2wKnoY +lGkXDTEwMDgyNDAyNDA1N1owIQIQeSyzBfb1Mm/H5hm5DCDpiRcNMTAwNzIxMTMz +NjA3WjAhAhB5aUMn0knVEjvwQ6UFiucdFw0xMjAyMjAxNTIyMzVaMCECEHmbDMsN +0rJ0ztAa2XV/BT4XDTEwMTEwODE5NDIwNlowIQIQebMIU+fugZMHx+KuProouhcN +MTAwNDMwMjA1OTQyWjAhAhB5xe1UgyHRSV4gU8UV16dzFw0xMTA5MTUxMTQyMDRa +MCECEHnNtVHfM8S/l0fRGD7tIBsXDTExMDQxMzE2MTAzNlowIQIQeeKoQn9h4QUn +cbG0BTOQZBcNMTExMTEyMTcwNzAwWjAhAhB6EJWONK3hjWYaaSh1OAewFw0xMTA3 +MjcxNTM0MTFaMCECEHpUuqwwgkTOmWVrQ0cJKvsXDTExMDYzMDAwMjczMVowIQIQ +emyu2A/faLIHM4eK8RePLBcNMTAxMTE4MTY0MjM4WjAhAhB6yOlF2XDDSff80CYN +pehjFw0xMTAxMjcxMDQyNDhaMCECEHra2euNU4TvBDgm68EABEMXDTExMDgzMDA4 +Mzk1NFowIQIQeuLVhiXe0PBRL+uOjrV1AxcNMTAxMDEyMDY1MTI0WjAhAhB65DeZ +VbH/MQKA24roJLCrFw0xMTEyMDUwNTU3NTJaMCECEHsF8DDBp4reIBcP5b2hAN4X +DTExMDMwOTE4NDYyNVowIQIQewr297r0lzmzleY5ziPUbBcNMTIwMjA2MTUzOTE1 +WjAhAhB7EO0difT0wLR/LF3hNxeeFw0xMjAyMDIxNTAzNTlaMCECEHs9QRG57aV4 +U5UxIPKHCawXDTEwMTAxNTE3MDY0NFowIQIQe2VSfkvTBC3+9SGPzWwVShcNMTAw +NzE1MTkyMDEwWjAhAhB7b4a1UbJxSLh+uKeEaLchFw0xMTA3MjcyMDU2MDJaMCEC +EHt2fiHwaYqoYeK7tFMJLVcXDTEwMDcyNjE3NTY0MVowIQIQe4HK9WKiMQV8x8JJ +K0W9vRcNMTEwNzA2MTgwNzAxWjAhAhB7ne2Rc1UVwDEJF5O5/kHpFw0xMTA0Mjcx +OTU5MDZaMCECEHusGkpgjsrvElrEsH4/JIcXDTExMDMyODIzMjIwNFowIQIQe7Iw +fzJozCSNJsWdhitjVBcNMTAwMjE3MTQyMDE0WjAhAhB7ssEnnkzZgT2A6abWFjKV +Fw0xMDA2MDQxMjAzNTZaMCECEHvZ5vmJsCdZPOAZ0cNTgV4XDTExMDMwNzE0NDIy +OVowIQIQe+fO6FnPSgT4uwnaKXaVbhcNMTExMjI3MTYyMzUxWjAhAhB79BYudwjM +EyZ3i8/oHCfFFw0xMTA5MDgwNzEwMTlaMCECEHv/WHRXXRYQUsgIcBXmZwsXDTEx +MDMyODA3MDIwOVowIQIQfBdDZ5BIWeZ71+AT8wfSWBcNMTIwMTA3MTUwMjA2WjAh +AhB8Gc4yVhXFBAeKA9GqsAW1Fw0xMDA1MjExOTI0MzJaMCECEHwbcle2Iaoa7/QU +u4Mi+lUXDTExMDYyNDE5MjIwOFowIQIQfCORoZuM8PJ3+tseLXILChcNMTIwMjEy +MTUyMjEyWjAhAhB8SlWTms/DxblWThsCGyRDFw0xMTEwMjQwMDAyMDdaMCECEHxP +wdyYvmxPQEW8LwCdWaIXDTEwMDQxOTIyMTAxNVowIQIQfIjVlb6rTTUiPwurRoL9 +HxcNMTEwMzE3MjMwMTAyWjAhAhB8msxX/6WhKhJblbLUHdwHFw0xMTA5MDYxNTU0 +MTRaMCECEHymELFLUvhOsNJijFmdxcIXDTEyMDEwMzEwNDc1NFowIQIQfKzk9Zcy +cc6UlyE0dXkgHhcNMTAxMDAxMTQ0MzQwWjAhAhB82QHEPLBoSL02d9zERO46Fw0x +MTA4MDQyMTU3NTlaMCECEHzoyfy41drwb15EspGqvZEXDTExMDkyNzEzNTQ0MFow +IQIQfPdDYsYdQpc3rkkRKrkpNhcNMTEwODIzMDkxOTAwWjAhAhB9H3D+FfuRaa5o +nIMAGHmkFw0xMDA3MjIxNzQ2MjJaMCECEH1HeonTikFyYsAgaXWY/KEXDTExMDMx +NzE4NDYzOFowIQIQfVTgM3d5/SaMP/+4+csc7RcNMTEwNjA3MDg0NzA0WjAhAhB9 +VX+ZrKkabo68j9Ej1+AHFw0xMjAxMzAxODAyNDVaMCECEH168tPRgrnEgM5Frseu +MtcXDTExMDQxMzAxMDAwMlowIQIQfXzejzzreMZMEtw8tBjcvhcNMTAwODE5MTc1 +NTA2WjAhAhB9jugzldis4mEVwXAggsfuFw0xMTAxMjQxOTE4MDhaMCECEH2hU8XJ +1b+PRct5ZwQzUo0XDTExMDQwNjE2MjYwNVowIQIQfaaOTRZxwbV3fXozBAfOoxcN +MTAwOTIzMTY1NDEwWjAhAhB9rwcsNviOxW4cDndZNNrrFw0xMTA4MjUxNzUyNTVa +MCECEH3oyHIFjmbmUvJ1gBYZVuUXDTEwMDcxNDIyMDYwOVowIQIQffLSLGK4vlEr +NDzFmu2siBcNMTEwNDA2MDY1MjM5WjAhAhB+EjGgKCQgUO5cJS9Ero07Fw0xMDA1 +MDQxMTE2MThaMCECEH4emMzNUIVrpU80UJtQHkAXDTEyMDIwOTE3NDIzNVowIQIQ +fjQKgyEGZhJKO/jmdDo9rRcNMTIwMTEyMTk0OTI3WjAhAhB+OsB2xrSL1Ym8e4oR +GEI8Fw0xMTA2MzAwMDMzMjZaMCECEH5GbwwHRrcuf4heLSKqF68XDTEwMDYyMjE3 +NDU0NVowIQIQfk+60d1oy/wFVa+fEcLqZBcNMTIwMTEwMTExNTQ3WjAhAhB+ZhG3 +ZZD4dgTge79HksqaFw0xMTEwMDYyMTQzMTBaMCECEH6NZB3DMPqHm2prhejWa3oX +DTEyMDIyMDE0Mzg1NlowIQIQfpIC4JFFtsiucoqP1QvK2BcNMTIwMjAxMjEwNzEx +WjAhAhB+sApL9FhF3mPP0LLVY4N2Fw0xMTA3MDUxNzQyMTlaMCECEH6whAonj9tD +1019w9+9/KMXDTEyMDIxNDE5MDkxMlowIQIQfuWSaiqS7ayShsmh1oZxJBcNMTIw +MTE5MTg0NjA2WjAhAhB+5vevHJ9o6kUz7Z+R8x33Fw0xMTEwMjAwNzE3NDRaMCEC +EH8SGrY/hha+qZuKO8QY9i8XDTEwMDcxNDE1MjQzOFowIQIQfx0kzcesd3FsGLca +XFOt1RcNMTAxMDA4MjE1MjE2WjAhAhB/Llizsy3hEAu6/uIUr19dFw0xMDAzMTAx +OTE4MzNaMCECEH9JYkal0bmay8bRCt6SZ1wXDTEwMDgwNjIwNTYwM1owIQIQf1Fz +fMj5tW5njKOLYEAB8xcNMTEwNzA0MDc1OTQyWjAhAhB/YM/G94vNzFXXaxVaQ3Nb +Fw0xMTA1MzExNTAyMjRaMCECEH9oYBvhMlcUl2avwLDrWqkXDTExMTIwMjA0MjIw +OVowIQIQf2iJa7r2uwbqWcAfsm0X8RcNMTAwNzA1MjMyMjAxWjAhAhB/hgfREjLr +TksPjfIrTHjUFw0xMDA3MDMwMTM4MjFaMCECEH+Iitja+ZhmmflnYdYu3E0XDTEx +MTAxMjE5MTM1N1owIQIQf5RrViDLUqQxqm1qJQTwBRcNMTIwMzA3MDAzMTI4WjAh +AhB/oZO+YXKtmW/B7gmbiGl5Fw0xMTAzMjUxNzQ1NDBaMCECEH+9e6m248PUPA8K +BanycwUXDTExMTAyMDE2MzIyNVowIQIQf8okPavXyAL5o1KNkLxIvxcNMTExMDE5 +MTg1MzM4WjAhAhB/0HtSAsivZH5JKjciG8O1Fw0xMTA2MTcxNTAzMzdaMCECEH/X +iNM0yUjIOcnhiu2q6fIXDTEyMDIyNTE1MjIxM1owIQIQf+bLcL72BIT2Ke/AYad2 +yRcNMTExMTA4MDA1NzE1WjAhAhB//IZFnrjLK3d4KhFJuzYLFw0xMjAyMDExNTMy +NDBaMA0GCSqGSIb3DQEBBQUAA4IBAQBV4CW4vxjq9kapeHdU7lvidSghkJywFqCN +NW3hO3JP2Q8iFQ+kPU97Nh7v/lLvrFqtQnMceRSMon2qQPDp73ZPCZRAbQo4C1KU +T9IbI4yg8rGUol/wyrquTeVT0g4eJKXzC/R7FvTSWFaCXeqf9kUdqY4pAyPu92ob +IdihctQyStjMlDOyV+kFMseXA1E0prQobGhaszIUJZ/LTYpd9/5I3ExZMvqqq3+8 +Dq06Tbl5tXNlDkMUL2Vh7J7HYCAH/FsXX1w0fbVNwoVYXstd0s5OV67sdwLurN2j +kL/Yw5LDcTi5JNBR2gYcHCPm6U8G4fvOSbIuYuwkt3jf7XOelJOu +-----END X509 CRL----- diff --git a/t/external/08_external.t b/t/external/08_external.t new file mode 100644 index 0000000..ede58a9 --- /dev/null +++ b/t/external/08_external.t @@ -0,0 +1,30 @@ +#!/usr/bin/perl +# Test complete connection a number of external SSL web servers + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; + +my @sites = qw( + www.google.com + www.microsoft.com + www.kernel.org +); +@sites = split(/:/, $ENV{SSLEAY_SITES}) if exists $ENV{SSLEAY_SITES}; +if (@sites) { + plan tests => scalar @sites * 2; +} +else { + plan skip_all => 'No external hosts specified for SSL testing'; +} + +my $site; +for $site (@sites) { + SKIP: { + my ($p, $r, %h) = Net::SSLeay::get_https($site, 443, '/'); + skip 'could not connect', 2 unless defined $h{'CONTENT-TYPE'}; + pass('connection'); + ok($r =~ /^HTTP\/1/s, 'correct response'); + } +} diff --git a/t/external/15_altnames.t b/t/external/15_altnames.t new file mode 100644 index 0000000..734e9ed --- /dev/null +++ b/t/external/15_altnames.t @@ -0,0 +1,34 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; + +my @sites = qw( + www.google.com + www.microsoft.com + www.kernel.org +); + +@sites = split(/:/, $ENV{SSLEAY_ALTNAME_SITES}) + if exists $ENV{SSLEAY_ALTNAME_SITES}; + +if (@sites) { + plan tests => scalar @sites * 3; +} +else { + plan skip_all => 'No external hosts specified for SSL testing'; +} + +for my $site (@sites) { + SKIP: { + my ($p, $r, $c) = Net::SSLeay::sslcat($site, 443, 'GET / HTTP/1.0'); + skip 'could not connect', 3 unless defined $c; + pass('connection'); + + my @altnames = Net::SSLeay::X509_get_subjectAltNames($c); + ok(scalar @altnames, 'get_subjectAltNames works'); + ok(scalar @altnames % 2 == 0, 'get_subjectAltNames returns pairs'); + } +} diff --git a/t/external/20_cert_chain.t b/t/external/20_cert_chain.t new file mode 100644 index 0000000..b8fcb7e --- /dev/null +++ b/t/external/20_cert_chain.t @@ -0,0 +1,51 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use Net::SSLeay qw( die_if_ssl_error ); + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my @sites = qw( www.verisign.com ); + +if (@sites) { + plan tests => scalar @sites * 3; +} +else { + plan skip_all => 'No external hosts specified for SSL testing'; +} + +for my $site (@sites) { + SKIP: { + my $port = getservbyname ('https', 'tcp') || 443; + my $dest_ip = gethostbyname ( $site ); + + socket (S, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!"; + connect (S, sockaddr_in($port, $dest_ip) ) or die "connect: $!"; + select (S); $| = 1; select (STDOUT); + + my $ctx = Net::SSLeay::CTX_new() or die_now("Failed to create SSL_CTX $!"); + my $ssl = Net::SSLeay::new($ctx) or die_now("Failed to create SSL $!"); + Net::SSLeay::set_fd($ssl, fileno(S)); # Must use fileno + Net::SSLeay::connect($ssl); + die_if_ssl_error('bulk: ssl connect'); + + my @chain = Net::SSLeay::get_peer_cert_chain($ssl); + ok(scalar @chain, 'get_peer_cert_chain returns some elements'); + SKIP: { + if( ! scalar @chain ) { + skip('check returned no certificate chain!', 2); + } + my $x509 = $chain[0]; + ok(my $subject = Net::SSLeay::X509_get_subject_name($x509), "X509_get_subject_name"); + like(Net::SSLeay::X509_NAME_oneline($subject), qr|/OU=.*?/CN=|, "X509_NAME_oneline"); + }; + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + } +} diff --git a/t/external/ocsp.t b/t/external/ocsp.t new file mode 100644 index 0000000..39f158d --- /dev/null +++ b/t/external/ocsp.t @@ -0,0 +1,266 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use IO::Socket::INET; +use Net::SSLeay; + +plan skip_all => "no OCSP support" + if ! defined &Net::SSLeay::OCSP_response_status; + +#$Net::SSLeay::trace=3; + +my @tests = ( + { + # this should give us OCSP stapling + host => 'www.microsoft.com', + port => 443, + fingerprint => '5f0b37e633840ca02468552ea3b1197e5e118f7b', + ocsp_staple => 1, + expect_status => Net::SSLeay::V_OCSP_CERTSTATUS_GOOD(), + }, + { + # no OCSP stapling + host => 'www.heise.de', + port => 443, + fingerprint => '36a7d7bfc59db65c040bccd291ae563d9ef7bafc', + expect_status => Net::SSLeay::V_OCSP_CERTSTATUS_GOOD(), + }, + { + # this is revoked + host => 'revoked.grc.com', + port => 443, + fingerprint => '310665f4c8e78db761c764e798dca66047341264', + expect_status => Net::SSLeay::V_OCSP_CERTSTATUS_REVOKED(), + }, +); + +my $release_tests = $ENV{RELEASE_TESTING} ? 1:0; +plan tests => $release_tests + @tests; + + +my $timeout = 10; # used to TCP connect and SSL connect +my $http_ua = eval { require HTTP::Tiny } && HTTP::Tiny->new(verify_SSL => 0); + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +my $sha1 = Net::SSLeay::EVP_get_digestbyname('sha1'); + + +my @fp_mismatch; +TEST: +for my $test (@tests) { + my $cleanup = __cleanup__->new; + SKIP: { + skip 'HTTP::Tiny required but not installed', 1 + unless $http_ua; + + my $cl = IO::Socket::INET->new( + PeerAddr => $test->{host}, + PeerPort => $test->{port}, + Timeout => $timeout, + ); + skip "TCP connect to $test->{host}:$test->{port} failed: $!",1 + if !$cl; + diag("tcp connect to $test->{host}:$test->{port} ok"); + + my $ctx = Net::SSLeay::CTX_new() or die "failed to create CTX"; + + # enable verification with hopefully usable CAs + Net::SSLeay::CTX_set_default_verify_paths($ctx); + Net::SSLeay::CTX_load_verify_locations($ctx, + Mozilla::CA::SSL_ca_file(),'') + if eval { require Mozilla::CA }; + Net::SSLeay::CTX_set_verify($ctx,Net::SSLeay::VERIFY_PEER(),undef); + + # setup TLS extension callback to catch stapled OCSP response + my $stapled_response; + Net::SSLeay::CTX_set_tlsext_status_cb($ctx,sub { + my ($ssl,$resp) = @_; + diag("got ".($resp ? '':'no ')."stapled OCSP response"); + return 1 if ! $resp; + $stapled_response = Net::SSLeay::i2d_OCSP_RESPONSE($resp); + return 1; + }); + + # create SSL object only after we have the context fully done since + # some parts of the context (like verification mode) will be copied + # to the SSL object and thus later changes to the CTX don't affect + # the SSL object + my $ssl = Net::SSLeay::new($ctx) or die "failed to create SSL"; + + # setup TLS extension to request stapled OCSP response + Net::SSLeay::set_tlsext_status_type($ssl, + Net::SSLeay::TLSEXT_STATUSTYPE_ocsp()); + + # non-blocking SSL_connect with timeout + $cl->blocking(0); + Net::SSLeay::set_fd($ssl,fileno($cl)); + my $end = time() + $timeout; + my ($rv,@err); + while (($rv = Net::SSLeay::connect($ssl)) < 0) { + my $to = $end-time(); + $to<=0 and last; + my $err = Net::SSLeay::get_error($ssl,$rv); + vec( my $vec = '',fileno($cl),1) = 1; + if ( $err == Net::SSLeay::ERROR_WANT_READ()) { + select($vec,undef,undef,$to); + } elsif ( $err == Net::SSLeay::ERROR_WANT_WRITE()) { + select(undef,$vec,undef,$to); + } else { + while ( my $err = Net::SSLeay::ERR_get_error()) { + push @err, Net::SSLeay::ERR_error_string($err); + } + last + } + } + skip "SSL_connect with $test->{host}:$test->{port} failed: @err",1 + if $rv<=0; + diag("SSL_connect ok"); + + # make sure we talk to the right party, e.g. no SSL interception + my $leaf_cert = Net::SSLeay::get_peer_certificate($ssl); + $cleanup->add(sub { Net::SSLeay::X509_free($leaf_cert) }) if $leaf_cert; + my $fp = $leaf_cert + && unpack("H*",Net::SSLeay::X509_digest($leaf_cert,$sha1)); + skip "could not get fingerprint",1 if !$fp; + if ($fp ne $test->{fingerprint}) { + push @fp_mismatch, [ $fp,$test ]; + skip("bad fingerprint for $test->{host}:$test->{port} -". + " expected $test->{fingerprint}, got $fp",1) + } + diag("fingerprint matches"); + + if ( $test->{ocsp_staple} && ! $stapled_response ) { + fail("did not get expected stapled OCSP response on $test->{host}:$test->{port}"); + next TEST; + } + + # create OCSP_REQUEST for all certs + my @requests; + for my $cert (Net::SSLeay::get_peer_cert_chain($ssl)) { + my $subj = Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_subject_name($cert)); + my $uri = Net::SSLeay::P_X509_get_ocsp_uri($cert); + if (!$uri) { + diag("no OCSP URI for cert $subj"); + next; + } + my $id = eval { Net::SSLeay::OCSP_cert2ids($ssl,$cert) } or do { + fail("failed to get OCSP_CERTIDs for cert $subj: $@"); + next TEST; + }; + my $req = Net::SSLeay::OCSP_ids2req($id); + push @requests, [ $uri,$req,$id,$subj ]; + $cleanup->add(sub { Net::SSLeay::OCSP_REQUEST_free($req) }); + } + if (!@requests) { + fail("no certificate checks for $test->{host}:$test->{port}"); + next TEST; + } + + my $check_response = sub { + my ($resp,$req,$id,$expect_status) = @_; + if ( Net::SSLeay::OCSP_response_status($resp) + != Net::SSLeay::OCSP_RESPONSE_STATUS_SUCCESSFUL()) { + return [ undef,"response bad status ". + Net::SSLeay::OCSP_response_status_str(Net::SSLeay::OCSP_response_status($resp)) ]; + } elsif ( ! eval { + Net::SSLeay::OCSP_response_verify($ssl,$resp,$req) }) { + return [ undef,"cannot verify response: $@" ]; + } + # extract result for id + my ($status) = Net::SSLeay::OCSP_response_results($resp,$id); + return [ undef,"no data for cert in response: $status->[1]" ] + if ! $status->[2]; + if ($expect_status != $status->[2]{statusType}) { + return [ undef, + "unexpected status=$status->[2]{statusType} (expected $expect_status): $status->[1]" ] + } elsif ( $status->[2]{nextUpdate} ) { + diag("status=$expect_status as expected: nextUpd=".localtime($status->[2]{nextUpdate})); + } else { + diag("status=$expect_status as expected: no nextUpd"); + } + return $status; + }; + + if ($stapled_response) { + my $stat = $check_response->( + Net::SSLeay::d2i_OCSP_RESPONSE($stapled_response), + undef, # no OCSP_REQUEST + $requests[0][2], # stapled response is for the leaf certificate + $test->{expect_status} + ); + if (!$stat->[0]) { + fail($stat->[1]); + next TEST; + } + } + + for(my $i=0;$i<@requests;$i++) { + my ($uri,$req,$id,$subj) = @{$requests[$i]}; + if ( ! $http_ua ) { + diag("no HTTP: skip checking $uri | $subj"); + next + } + my $res = $http_ua->request('POST',$uri, { + headers => { 'Content-type' => 'application/ocsp-request' }, + content => Net::SSLeay::i2d_OCSP_REQUEST($req), + timeout => $timeout, + }); + if (!$res->{success}) { + if ($res->{status} == 599) { + # internal error, assume network problem + diag("disabling HTTP because of $http_ua->{reason}"); + $http_ua = undef; + } + diag("$http_ua->{reason}: skip checking $uri | $subj"); + next; + } + my $resp = eval { Net::SSLeay::d2i_OCSP_RESPONSE($res->{content}) }; + if (!$resp) { + diag("bad OCSP response($@): skip checking $uri | $subj"); + next; + } + my $stat = $check_response->( + $resp, + $req, + $id, + ($i>0) ? Net::SSLeay::V_OCSP_CERTSTATUS_GOOD() : $test->{expect_status}, + ); + if (!$stat->[0]) { + fail($stat->[1]); + next TEST; + } + } + + pass("OCSP test $test->{host}:$test->{port} ok"); + } +} + +if ($release_tests) { + if (!@fp_mismatch) { + pass("all fingerprints matched"); + } else { + for(@fp_mismatch) { + my ($fp,$test) = @$_; + diag("fingerprint mismatch for $test->{host}:$test->{port} -". + " expected $test->{fingerprint}, got $fp") + } + fail("some fingerprints did not matched - please adjust test"); + } +} + +{ + # cleanup stuff when going out of scope + package __cleanup__; + sub new { bless [],shift }; + sub add { my $self = shift; push @$self,@_ } + sub DESTROY { + my $self = shift; + &$_ for(@$self) + } +} diff --git a/t/handle/external/10_destroy.t b/t/handle/external/10_destroy.t new file mode 100644 index 0000000..cf2279e --- /dev/null +++ b/t/handle/external/10_destroy.t @@ -0,0 +1,55 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; + +my @uris = qw( + www.google.com + www.microsoft.com + www.kernel.org +); +@uris = split(/:/, $ENV{SSLEAY_URIS}) if exists $ENV{SSLEAY_URIS}; +if (@uris) { + plan tests => scalar @uris * 2; +} +else { + plan skip_all => 'No external hosts specified for SSL testing'; +} + +use File::Spec; +use Symbol qw(gensym); +use Net::SSLeay::Handle; + +# On some platforms, such as Solaris, the act of resolving the host name +# opens (and leaves open) a connection to the DNS client, which breaks +# the fd counting algorithm below. Make sure the DNS is operating before +# we count the FDs for the first time. +for my $uri (@uris) { + my $dummy = gethostbyname($uri); +} + +my $fdcount_start = count_fds(); + +for my $uri (@uris) { + { + my $ssl = gensym(); + tie(*$ssl, "Net::SSLeay::Handle", $uri, 443); + print $ssl "GET / HTTP/1.0\r\n\r\n"; + + my $response = do { local $/ = undef; <$ssl> }; + like( $response, qr/^HTTP\/1/s, 'correct response' ); + } + + my $fdcount_end = count_fds(); + is ($fdcount_end, $fdcount_start, 'handle gets destroyed when it goes out of scope'); +} + +sub count_fds { + my $fdpath = File::Spec->devnull(); + my $fh = gensym(); + open($fh, $fdpath) or die; + my $count = fileno($fh); + close($fh); + return $count; +} diff --git a/t/handle/external/50_external.t b/t/handle/external/50_external.t new file mode 100644 index 0000000..40df5b9 --- /dev/null +++ b/t/handle/external/50_external.t @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Symbol qw(gensym); +use Net::SSLeay::Handle; + +my @sites = qw( + www.google.com + www.microsoft.com + www.kernel.org +); +@sites = split(/:/, $ENV{SSLEAY_SITES}) if exists $ENV{SSLEAY_SITES}; +if (@sites) { + plan tests => scalar @sites * 7; +} +else { + plan skip_all => 'No external hosts specified for SSL testing'; +} + + +for my $site (@sites) { + SKIP: { + my $ssl = gensym(); + eval { + tie(*$ssl, 'Net::SSLeay::Handle', $site, 443); + }; + + skip('could not connect to '.$site, 2) if $@; + pass('connection to '.$site); + + print $ssl "GET / HTTP/1.0\r\n\r\n"; + my $resp = do { local $/ = undef; <$ssl> }; + + like( $resp, qr/^HTTP\/1/, 'response' ); + } +} + +{ + my @sock; + for (my $i = 0; $i < scalar @sites; $i++) { + SKIP: { + my $ssl = gensym(); + eval { + tie(*$ssl, 'Net::SSLeay::Handle', $sites[$i], 443); + }; + + $sock[$i] = undef; #so scalar @sock == scalar @sites + + skip('could not connect', 2) if $@; + pass('connection'); + + $sock[$i] = $ssl; + + ok( $ssl, 'got handle' ); + } + } + + for my $sock (@sock) { + SKIP : { + skip('not connected', 2) unless defined $sock; + pass('connected'); + + print $sock "GET / HTTP/1.0\r\n\r\n"; + + my $resp = do { local $/ = undef; <$sock> }; + like( $resp, qr/^HTTP\/1/, 'response' ); + } + } + + for my $sock (@sock) { + SKIP : { + skip('not connected', 1) unless defined $sock; + ok(close($sock), 'socket closed'); + } + } +} diff --git a/t/handle/local/05_use.t b/t/handle/local/05_use.t new file mode 100644 index 0000000..6e82b4f --- /dev/null +++ b/t/handle/local/05_use.t @@ -0,0 +1,9 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 1; + +BEGIN { + use_ok('Net::SSLeay::Handle'); +} diff --git a/t/local/01_pod.t b/t/local/01_pod.t new file mode 100644 index 0000000..7668d00 --- /dev/null +++ b/t/local/01_pod.t @@ -0,0 +1,12 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +eval "use Test::Pod 1.00"; +plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; + +all_pod_files_ok(qw( + blib/lib/Net/SSLeay.pm + blib/lib/Net/SSLeay/Handle.pm +)); diff --git a/t/local/02_pod_coverage.t b/t/local/02_pod_coverage.t new file mode 100644 index 0000000..bbb73e0 --- /dev/null +++ b/t/local/02_pod_coverage.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; + +BEGIN { + unless ($ENV{RELEASE_TESTING}) + { + plan(skip_all => 'these tests are for only for release candidate testing. Enable with RELEASE_TESTING=1'); + } +} + + +eval "use Test::Pod::Coverage 1.00"; +plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage" if $@; + +plan tests => 2; + +pod_coverage_ok('Net::SSLeay'); +pod_coverage_ok('Net::SSLeay::Handle'); diff --git a/t/local/03_use.t b/t/local/03_use.t new file mode 100644 index 0000000..2cf3952 --- /dev/null +++ b/t/local/03_use.t @@ -0,0 +1,26 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 1; + +BEGIN { + use_ok('Net::SSLeay'); +} + +diag(""); +diag("Testing Net::SSLeay $Net::SSLeay::VERSION"); +diag(""); +diag("Perl information:"); +diag(" Version: '" . $] . "'"); +diag(" Executable path: '" . $^X . "'"); +diag(""); +diag("libssl information:"); +diag(" SSLEAY_VERSION: '" . Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_VERSION()) . "'"); +diag(" SSLEAY_CFLAGS: '" . Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_CFLAGS()) . "'"); +diag(" SSLEAY_BUILT_ON: '" . Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_BUILT_ON()) . "'"); +diag(" SSLEAY_PLATFORM: '" . Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_PLATFORM()) . "'"); +diag(" SSLEAY_DIR: '" . Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_DIR()) . "'"); +if (eval "&Net::SSLeay::OPENSSL_ENGINES_DIR") { + diag(" OPENSSL_ENGINES_DIR: '" . Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_ENGINES_DIR()) . "'"); +} diff --git a/t/local/04_basic.t b/t/local/04_basic.t new file mode 100644 index 0000000..007c7a5 --- /dev/null +++ b/t/local/04_basic.t @@ -0,0 +1,40 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 14; +use Net::SSLeay; + +eval "use Test::Exception;"; + +SKIP: { + skip 'Need Test::Exception for the some tests', 6 if $@; + lives_ok( sub { Net::SSLeay::randomize() }, 'randomizing' ); + lives_ok( sub { Net::SSLeay::load_error_strings() }, 'loading error strings' ); + lives_ok( sub { Net::SSLeay::SSLeay_add_ssl_algorithms() }, 'adding ssl algorithms' ); + #version numbers: 0x00903100 ~ 0.9.3, 0x0090600f ~ 0.6.9 + ok( Net::SSLeay::SSLeay() >= 0x00903100, 'SSLeay (version min 0.9.3)' ); + isnt( Net::SSLeay::SSLeay_version(), '', 'SSLeay (version string)' ); + is( Net::SSLeay::SSLeay_version(), Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_VERSION()), 'SSLeay_version optional argument' ); +} + +is(Net::SSLeay::hello(), 1, 'hello world'); + +if (exists &Net::SSLeay::OpenSSL_version) +{ + is(Net::SSLeay::SSLeay(), Net::SSLeay::OpenSSL_version_num(), 'OpenSSL_version_num'); + + is(Net::SSLeay::OpenSSL_version(), Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_VERSION()), 'OpenSSL_version optional argument'); + + is(Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_VERSION()), Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_VERSION()), 'OpenSSL_version(OPENSSL_VERSION)'); + is(Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_CFLAGS()), Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_CFLAGS()), 'OpenSSL_version(OPENSSL_CFLAGS)'); + is(Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_BUILT_ON()), Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_BUILT_ON()), 'OpenSSL_version(OPENSSL_BUILT_ON)'); + is(Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_PLATFORM()), Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_PLATFORM()), 'OpenSSL_version(OPENSSL_PLATFORM)'); + is(Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_DIR()), Net::SSLeay::OpenSSL_version(Net::SSLeay::OPENSSL_DIR()), 'OpenSSL_version(OPENSSL_DIR)'); +} +else +{ + SKIP: { + skip('Only on OpenSSL 1.1.0 or later', 7); + } +} diff --git a/t/local/05_passwd_cb.t b/t/local/05_passwd_cb.t new file mode 100644 index 0000000..e9388d2 --- /dev/null +++ b/t/local/05_passwd_cb.t @@ -0,0 +1,182 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 36; +use File::Spec; +use Net::SSLeay; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::add_ssl_algorithms(); +Net::SSLeay::OpenSSL_add_all_algorithms(); + +my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem.e'); +my $key_password = 'secret'; +my $cb_1_calls = 0; +my $cb_2_calls = 0; +my $cb_3_calls = 0; +my $cb_4_calls = 0; +my $cb_bad_calls = 0; + +sub callback1 { + my ($rwflag, $userdata) = @_; + + $cb_1_calls++; + + is ($rwflag, 0, 'rwflag is set correctly'); + is( $$userdata, $key_password, 'received userdata properly' ); + return $$userdata; +} + +sub callback2 { + my ($rwflag, $userdata) = @_; + + $cb_2_calls++; + + is( $$userdata, $key_password, 'received userdata properly' ); + return $$userdata; +} + +sub callback3 { + my ($rwflag, $userdata) = @_; + + $cb_3_calls++; + + is( $userdata, undef, 'received no userdata' ); + return $key_password; +} + +sub callback_bad { + my ($rwflag, $userdata) = @_; + + $cb_bad_calls++; + + is( $userdata, $key_password, 'received userdata properly' ); + return $key_password . 'incorrect'; # Return incorrect password +} + +my $ctx_1 = Net::SSLeay::CTX_new(); +ok($ctx_1, 'CTX_new 1'); + +my $ctx_2 = Net::SSLeay::CTX_new(); +ok($ctx_2, 'CTX_new 2'); + +my $ctx_3 = Net::SSLeay::CTX_new(); +ok($ctx_3, 'CTX_new 3'); + +my $ctx_4 = Net::SSLeay::CTX_new(); +ok($ctx_4, 'CTX_new 4'); + +Net::SSLeay::CTX_set_default_passwd_cb($ctx_1, \&callback1); +Net::SSLeay::CTX_set_default_passwd_cb_userdata($ctx_1, \$key_password); + +Net::SSLeay::CTX_set_default_passwd_cb($ctx_2, \&callback2); +Net::SSLeay::CTX_set_default_passwd_cb_userdata($ctx_2, \$key_password); + +Net::SSLeay::CTX_set_default_passwd_cb($ctx_3, \&callback3); + +ok( Net::SSLeay::CTX_use_PrivateKey_file($ctx_1, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'CTX_use_PrivateKey_file works with right passphrase and userdata' ); + +ok( Net::SSLeay::CTX_use_PrivateKey_file($ctx_2, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'CTX_use_PrivateKey_file works with right passphrase and userdata' ); + +ok( Net::SSLeay::CTX_use_PrivateKey_file($ctx_3, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'CTX_use_PrivateKey_file works with right passphrase and without userdata' ); + +Net::SSLeay::CTX_set_default_passwd_cb($ctx_4, sub { $cb_4_calls++; return 'secret';}); +ok( Net::SSLeay::CTX_use_PrivateKey_file($ctx_4, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'CTX_use_PrivateKey_file works when callback data is unset' ); + +ok( $cb_1_calls == 1 + && $cb_2_calls == 1 + && $cb_3_calls == 1 + && $cb_4_calls == 1, + 'different cbs per ctx work' ); + +$key_password = 'incorrect'; + +ok( !Net::SSLeay::CTX_use_PrivateKey_file($ctx_1, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'CTX_use_PrivateKey_file doesn\'t work with wrong passphrase' ); + +is($cb_1_calls, 2, 'callback1 called 2 times'); + + +# OpenSSL 1.1.0 has SSL_set_default_passwd_cb, but the callback is not +# called for SSL before OpenSSL 1.1.0f +if (exists &Net::SSLeay::set_default_passwd_cb) +{ + test_ssl_funcs(); +} +else +{ + SKIP: { + skip('Do not have Net::SSLeay::set_default_passwd_cb', 19); + }; +} + +exit(0); + +sub test_ssl_funcs +{ + my $ctx_1 = Net::SSLeay::CTX_new(); + my $ssl_1 = Net::SSLeay::new($ctx_1); + ok($ssl_1, 'SSL_new 1'); + + my $ctx_2 = Net::SSLeay::CTX_new(); + my $ssl_2 = Net::SSLeay::new($ctx_2); + ok($ssl_2, 'SSL_new 2'); + + my $ctx_3 = Net::SSLeay::CTX_new(); + my $ssl_3 = Net::SSLeay::new($ctx_3); + ok($ssl_3, 'SSL_new 3'); + + my $ctx_4 = Net::SSLeay::CTX_new(); + my $ssl_4 = Net::SSLeay::new($ctx_4); + ok($ssl_4, 'SSL_new 4'); + + $cb_1_calls = $cb_2_calls = $cb_3_calls = $cb_4_calls = $cb_bad_calls = 0; + $key_password = 'secret'; + + Net::SSLeay::set_default_passwd_cb($ssl_1, \&callback1); + Net::SSLeay::set_default_passwd_cb_userdata($ssl_1, \$key_password); + + Net::SSLeay::set_default_passwd_cb($ssl_2, \&callback2); + Net::SSLeay::set_default_passwd_cb_userdata($ssl_2, \$key_password); + + Net::SSLeay::set_default_passwd_cb($ssl_3, \&callback3); + + ok( Net::SSLeay::use_PrivateKey_file($ssl_1, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'use_PrivateKey_file works with right passphrase and userdata' ); + + ok( Net::SSLeay::use_PrivateKey_file($ssl_2, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'use_PrivateKey_file works with right passphrase and userdata' ); + + # Setting the callback for CTX should not change anything + Net::SSLeay::CTX_set_default_passwd_cb($ctx_2, \&callback_bad); + Net::SSLeay::CTX_set_default_passwd_cb_userdata($ctx_2, \$key_password); + ok( Net::SSLeay::use_PrivateKey_file($ssl_2, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'use_PrivateKey_file works with right passphrase and userdata after bad passphrase set for CTX' ); + + ok( Net::SSLeay::use_PrivateKey_file($ssl_3, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'use_PrivateKey_file works with right passphrase and without userdata' ); + + Net::SSLeay::set_default_passwd_cb($ssl_4, sub { $cb_4_calls++; return 'secret';}); + ok( Net::SSLeay::use_PrivateKey_file($ssl_4, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'use_PrivateKey_file works when callback data is unset' ); + + ok( $cb_1_calls == 1 + && $cb_2_calls == 2 + && $cb_3_calls == 1 + && $cb_4_calls == 1 + && $cb_bad_calls == 0, + 'different cbs per ssl work' ); + + $key_password = 'incorrect'; + + ok( !Net::SSLeay::use_PrivateKey_file($ssl_1, $key_pem, &Net::SSLeay::FILETYPE_PEM), + 'use_PrivateKey_file doesn\'t work with wrong passphrase' ); + + is($cb_1_calls, 2, 'callback1 called 2 times'); +} diff --git a/t/local/06_tcpecho.t b/t/local/06_tcpecho.t new file mode 100644 index 0000000..6207b4c --- /dev/null +++ b/t/local/06_tcpecho.t @@ -0,0 +1,77 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use Symbol qw(gensym); +use Net::SSLeay; +use Config; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +plan tests => 4; + +my $sock; +my $pid; + +my $port = 1211; +my $msg = 'ssleay-tcp-test'; +my $port_trials = 1000; +{ + my $ip = "\x7F\0\0\x01"; + my $serv_params = sockaddr_in($port, $ip); + $sock = gensym(); + socket($sock, AF_INET, SOCK_STREAM, 0) or die "socket failed: $!"; + # Try to find an available port to bind to + my $i; + for ($i = 0; $i < $port_trials; $i++) + { + my $serv_params = sockaddr_in($port, $ip); + + last if bind($sock, $serv_params); + $port++; + } + die "Could not find a port to bind to" if $i >= 1000; + listen($sock, 2) or die "listen failed $!"; +} + +{ + $pid = fork(); + die "fork failed: $!" unless defined $pid; + if ($pid == 0) { + my $addr = accept(Net::SSLeay::SSLCAT_S, $sock) or die "accept failed $!"; + + my $old_out = select(Net::SSLeay::SSLCAT_S); + $| = 1; + select($old_out); + + my $got = Net::SSLeay::tcp_read_all(); + is($got, $msg, 'tcp_read_all'); + + ok(Net::SSLeay::tcp_write_all(uc($got)), 'tcp_write_all'); + + close Net::SSLeay::SSLCAT_S; + close $sock; + + exit; + } +} + +my @results; +{ + my ($got) = Net::SSLeay::tcpcat('127.0.0.1', $port, $msg); + push @results, [ $got eq uc($msg), 'sent and received correctly' ]; +} + +waitpid $pid, 0; +push @results, [ $? == 0, 'server exited with 0' ]; + +END { + Test::More->builder->current_test(2); + for my $t (@results) { + ok( $t->[0], $t->[1] ); + } +} diff --git a/t/local/07_sslecho.t b/t/local/07_sslecho.t new file mode 100644 index 0000000..e876715 --- /dev/null +++ b/t/local/07_sslecho.t @@ -0,0 +1,384 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Symbol qw(gensym); +use Net::SSLeay; +use Config; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +plan tests => 102; +$SIG{'PIPE'} = 'IGNORE'; + +my $sock; +my $pid; + +my $port = 1212; +my $dest_ip = "\x7F\0\0\x01"; +my $dest_serv_params = sockaddr_in($port, $dest_ip); +my $port_trials = 1000; + +my $msg = 'ssleay-test'; +my $ca_cert_pem = File::Spec->catfile('t', 'data', 'test_CA1_2048.crt.pem'); +my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard_CA1_2048.crt.pem'); +my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + +my $cert_name = (Net::SSLeay::SSLeay >= 0x0090700f) ? + '/C=US/ST=State/L=City/O=Company/OU=Unit/CN=*.example.com/emailAddress=wildcard@example.com' : + '/C=US/ST=State/L=City/O=Company/OU=Unit/CN=*.example.com/Email=wildcard@example.com'; +my $cert_issuer = '/C=US/O=Demo1/CN=CA1'; +my $cert_sha1_fp = '91:41:FD:7D:99:02:2E:70:91:53:EF:C6:F3:F8:9D:E2:CF:B0:5F:0C'; + +$ENV{RND_SEED} = '1234567890123456789012345678901234567890'; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::library_init(); + +{ + my $ip = "\x7F\0\0\x01"; + my $serv_params = sockaddr_in($port, $ip); + $sock = gensym(); + socket($sock, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + # Try to find an available port to bind to + my $i; + for ($i = 0; $i < $port_trials; $i++) + { + my $serv_params = sockaddr_in($port, $ip); + + last if bind($sock, $serv_params); + $port++; + } + BAIL_OUT("Could not find a port to bind to: $!") if $i >= 1000; + listen($sock, 3) or BAIL_OUT("failed to listen on socket: $!"); + + + my $ctx = Net::SSLeay::CTX_new(); + ok($ctx, 'CTX_new'); + ok(Net::SSLeay::CTX_set_cipher_list($ctx, 'ALL'), 'CTX_set_cipher_list'); + my ($dummy, $errs) = Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + ok($errs eq '', "set_cert_and_key: $errs"); + SKIP: { + skip 'Disabling session tickets requires OpenSSL >= 1.1.1', 1 + unless defined (&Net::SSLeay::CTX_set_num_tickets); + # TLS 1.3 server sends session tickets after a handhake as part of + # the SSL_accept(). If a client finishes all its job including closing + # TCP connection before a server sends the tickets, SSL_accept() fails + # with SSL_ERROR_SYSCALL and EPIPE errno and the server receives + # SIGPIPE signal. + ok(Net::SSLeay::CTX_set_num_tickets($ctx, 0), 'Session tickets disabled'); + } + + $pid = fork(); + BAIL_OUT("failed to fork: $!") unless defined $pid; + if ($pid == 0) { + for (1 .. 7) { + my $ns = gensym(); + my $addr = accept($ns, $sock); + + my $old_out = select($ns); + $| = 1; + select($old_out); + + my $ssl = Net::SSLeay::new($ctx); + ok($ssl, 'new'); + + is(Net::SSLeay::in_before($ssl), 1, 'in_before is 1'); + is(Net::SSLeay::in_init($ssl), 1, 'in_init is 1'); + + ok(Net::SSLeay::set_fd($ssl, fileno($ns)), 'set_fd using fileno'); + ok(Net::SSLeay::accept($ssl), 'accept'); + + is(Net::SSLeay::is_init_finished($ssl), 1, 'is_init_finished is 1'); + + ok(Net::SSLeay::get_cipher($ssl), 'get_cipher'); + like(Net::SSLeay::get_shared_ciphers($ssl), qr/(AES|RSA|SHA|CBC|DES)/, 'get_shared_ciphers'); + + my $got = Net::SSLeay::ssl_read_all($ssl); + is($got, $msg, 'ssl_read_all') if $_ < 7; + ok(Net::SSLeay::ssl_write_all($ssl, uc($got)), 'ssl_write_all'); + + Net::SSLeay::free($ssl); + close $ns; + } + + Net::SSLeay::CTX_free($ctx); + close $sock; + + exit; + } +} + +my @results; +{ + my ($got) = Net::SSLeay::sslcat('127.0.0.1', $port, $msg); + push @results, [ $got eq uc($msg), 'send and received correctly' ]; + +} + +{ + my $s = gensym(); + socket($s, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket"); + connect($s, $dest_serv_params) or BAIL_OUT("failed to connect"); + + { + my $old_out = select($s); + $| = 1; + select($old_out); + } + + push @results, [ my $ctx = Net::SSLeay::CTX_new(), 'CTX_new' ]; + push @results, [ my $ssl = Net::SSLeay::new($ctx), 'new' ]; + + push @results, [ Net::SSLeay::set_fd($ssl, $s), 'set_fd using glob ref' ]; + push @results, [ Net::SSLeay::connect($ssl), 'connect' ]; + + push @results, [ Net::SSLeay::get_cipher($ssl), 'get_cipher' ]; + + push @results, [ Net::SSLeay::ssl_write_all($ssl, $msg), 'write' ]; + shutdown($s, 1); + + my $got = Net::SSLeay::ssl_read_all($ssl); + push @results, [ $got eq uc($msg), 'read' ]; + + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + + shutdown($s, 2); + close $s; + +} + +{ + my $verify_cb_1_called = 0; + my $verify_cb_2_called = 0; + my $verify_cb_3_called = 0; + { + my $ctx = Net::SSLeay::CTX_new(); + push @results, [ Net::SSLeay::CTX_load_verify_locations($ctx, $ca_cert_pem, ''), 'CTX_load_verify_locations' ]; + Net::SSLeay::CTX_set_verify($ctx, &Net::SSLeay::VERIFY_PEER, \&verify); + + my $ctx2 = Net::SSLeay::CTX_new(); + Net::SSLeay::CTX_set_cert_verify_callback($ctx2, \&verify4, 1); + + { + my $s = gensym(); + socket($s, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s, $dest_serv_params) or BAIL_OUT("failed to connect: $!"); + + { + my $old_out = select($s); + $| = 1; + select($old_out); + } + + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, fileno($s)); + Net::SSLeay::connect($ssl); + + Net::SSLeay::ssl_write_all($ssl, $msg); + + shutdown $s, 2; + close $s; + Net::SSLeay::free($ssl); + + push @results, [ $verify_cb_1_called == 1, 'verify cb 1 called once' ]; + push @results, [ $verify_cb_2_called == 0, 'verify cb 2 wasn\'t called yet' ]; + push @results, [ $verify_cb_3_called == 0, 'verify cb 3 wasn\'t called yet' ]; + } + + { + my $s1 = gensym(); + socket($s1, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s1, $dest_serv_params) or BAIL_OUT("failed to connect: $!"); + + { + my $old_out = select($s1); + $| = 1; + select($old_out); + } + + my $s2 = gensym(); + socket($s2, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s2, $dest_serv_params) or BAIL_OUT("failed to connect: $!"); + + { + my $old_out = select($s2); + $| = 1; + select($old_out); + } + + my $s3 = gensym(); + socket($s3, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s3, $dest_serv_params) or BAIL_OUT("failed to connect: $!"); + + { + my $old_out = select($s3); + $| = 1; + select($old_out); + } + + my $ssl1 = Net::SSLeay::new($ctx); + Net::SSLeay::set_verify($ssl1, &Net::SSLeay::VERIFY_PEER, \&verify2); + Net::SSLeay::set_fd($ssl1, $s1); + + my $ssl2 = Net::SSLeay::new($ctx); + Net::SSLeay::set_verify($ssl2, &Net::SSLeay::VERIFY_PEER, \&verify3); + Net::SSLeay::set_fd($ssl2, $s2); + + my $ssl3 = Net::SSLeay::new($ctx2); + Net::SSLeay::set_fd($ssl3, $s3); + + Net::SSLeay::connect($ssl1); + Net::SSLeay::ssl_write_all($ssl1, $msg); + shutdown $s1, 2; + + Net::SSLeay::connect($ssl2); + Net::SSLeay::ssl_write_all($ssl2, $msg); + shutdown $s2, 2; + + Net::SSLeay::connect($ssl3); + Net::SSLeay::ssl_write_all($ssl3, $msg); + shutdown $s3, 2; + + close $s1; + close $s2; + close $s3; + + Net::SSLeay::free($ssl1); + Net::SSLeay::free($ssl2); + Net::SSLeay::free($ssl3); + + push @results, [ $verify_cb_1_called == 1, 'verify cb 1 wasn\'t called again' ]; + push @results, [ $verify_cb_2_called == 1, 'verify cb 2 called once' ]; + push @results, [ $verify_cb_3_called == 1, 'verify cb 3 wasn\'t called yet' ]; + } + + + Net::SSLeay::CTX_free($ctx); + Net::SSLeay::CTX_free($ctx2); + } + + sub verify { + my ($ok, $x509_store_ctx) = @_; + + # Skip intermediate certs but propagate possible not ok condition + my $depth = Net::SSLeay::X509_STORE_CTX_get_error_depth($x509_store_ctx); + return $ok unless $depth == 0; + + $verify_cb_1_called++; + + my $cert = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx); + push @results, [ $cert, 'verify cb cert' ]; + + my $issuer_name = Net::SSLeay::X509_get_issuer_name( $cert ); + my $issuer = Net::SSLeay::X509_NAME_oneline( $issuer_name ); + + my $subject_name = Net::SSLeay::X509_get_subject_name( $cert ); + my $subject = Net::SSLeay::X509_NAME_oneline( $subject_name ); + + my $cn = Net::SSLeay::X509_NAME_get_text_by_NID($subject_name, &Net::SSLeay::NID_commonName); + + my $fingerprint = Net::SSLeay::X509_get_fingerprint($cert, 'SHA-1'); + + push @results, [ $ok == 1, 'verify is ok' ]; + push @results, [ $issuer eq $cert_issuer, 'cert issuer' ]; + push @results, [ $subject eq $cert_name, 'cert subject' ]; + push @results, [ substr($cn, length($cn) - 1, 1) ne "\0", 'tailing 0 character is not returned from get_text_by_NID' ]; + push @results, [ $fingerprint eq $cert_sha1_fp, 'SHA-1 fingerprint' ]; + + return 1; + } + + sub verify2 { + my ($ok, $x509_store_ctx) = @_; + + # Skip intermediate certs but propagate possible not ok condition + my $depth = Net::SSLeay::X509_STORE_CTX_get_error_depth($x509_store_ctx); + return $ok unless $depth == 0; + + $verify_cb_2_called++; + push @results, [ $ok == 1, 'verify 2 is ok' ]; + return $ok; + } + + sub verify3 { + my ($ok, $x509_store_ctx) = @_; + + # Skip intermediate certs but propagate possible not ok condition + my $depth = Net::SSLeay::X509_STORE_CTX_get_error_depth($x509_store_ctx); + return $ok unless $depth == 0; + + $verify_cb_3_called++; + push @results, [ $ok == 1, 'verify 3 is ok' ]; + return $ok; + } + + sub verify4 { + my ($cert_store, $userdata) = @_; + push @results, [$userdata == 1, 'CTX_set_cert_verify_callback']; + return $userdata; + } +} + +{ + my $s = gensym(); + socket($s, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s, $dest_serv_params) or BAIL_OUT("failed to connect: $!"); + + { + my $old_out = select($s); + $| = 1; + select($old_out); + } + + my $ctx = Net::SSLeay::CTX_new(); + my $ssl = Net::SSLeay::new($ctx); + + Net::SSLeay::set_fd($ssl, fileno($s)); + Net::SSLeay::connect($ssl); + + my $cert = Net::SSLeay::get_peer_certificate($ssl); + + my $subject = Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_subject_name($cert) + ); + + my $issuer = Net::SSLeay::X509_NAME_oneline( + Net::SSLeay::X509_get_issuer_name($cert) + ); + + push @results, [ $subject eq $cert_name, 'get_peer_certificate subject' ]; + push @results, [ $issuer eq $cert_issuer, 'get_peer_certificate issuer' ]; + + my $data = 'a' x 1024 ** 2; + my $written = Net::SSLeay::ssl_write_all($ssl, \$data); + push @results, [ $written == length $data, 'ssl_write_all' ]; + + shutdown $s, 1; + + my $got = Net::SSLeay::ssl_read_all($ssl); + push @results, [ $got eq uc($data), 'ssl_read_all' ]; + + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + + close $s; +} + +waitpid $pid, 0; +push @results, [ $? == 0, 'server exited with 0' ]; + +END { + Test::More->builder->current_test(73); + for my $t (@results) { + ok( $t->[0], $t->[1] ); + } +} diff --git a/t/local/08_pipe.t b/t/local/08_pipe.t new file mode 100644 index 0000000..f34e8b2 --- /dev/null +++ b/t/local/08_pipe.t @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; +use Symbol qw( gensym ); +use IO::Handle; +use File::Spec; +use Config; + +BEGIN { + plan skip_all => "Either pipes or fork() not supported on $^O" + if ($^O eq 'MSWin32' || !$Config{d_fork}); +} + +plan tests => 11; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::OpenSSL_add_ssl_algorithms(); + +my $cert = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); +my $key = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + +my $how_much = 1024 ** 2; + +my $rs = gensym(); +my $ws = gensym(); +my $rc = gensym(); +my $wc = gensym(); + +pipe $rs, $wc or die "pipe 1 ($!)"; +pipe $rc, $ws or die "pipe 2 ($!)"; + +for my $h ($rs, $ws, $rc, $wc) { + my $old_select = select $h; + $| = 1; + select $old_select; +} + +my $pid = fork(); +die unless defined $pid; + +if ($pid == 0) { + my $ctx = Net::SSLeay::CTX_new(); + Net::SSLeay::set_server_cert_and_key($ctx, $cert, $key); + + my $ssl = Net::SSLeay::new($ctx); + + ok( Net::SSLeay::set_rfd($ssl, fileno($rs)), 'set_rfd using fileno' ); + ok( Net::SSLeay::set_wfd($ssl, fileno($ws)), 'set_wfd using fileno' ); + + ok( Net::SSLeay::accept($ssl), 'accept' ); + + ok( my $got = Net::SSLeay::ssl_read_all($ssl, $how_much), 'ssl_read_all' ); + + is( Net::SSLeay::ssl_write_all($ssl, \$got), length $got, 'ssl_write_all' ); + + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + + close $ws; + close $rs; + exit; +} + +my @results; +{ + my $ctx = Net::SSLeay::CTX_new(); + my $ssl = Net::SSLeay::new($ctx); + + my $rc_handle = IO::Handle->new_from_fd( fileno($rc), 'r' ); + my $wc_handle = IO::Handle->new_from_fd( fileno($wc), 'w' ); + push @results, [ Net::SSLeay::set_rfd($ssl, $rc_handle), 'set_rfd using an io handle' ]; + push @results, [ Net::SSLeay::set_wfd($ssl, $wc_handle), 'set_wfd using an io handle' ]; + + push @results, [ Net::SSLeay::connect($ssl), 'connect' ]; + + my $data = 'B' x $how_much; + + push @results, [ Net::SSLeay::ssl_write_all($ssl, \$data) == length $data, 'ssl_write_all' ]; + + my $got = Net::SSLeay::ssl_read_all($ssl, $how_much); + push @results, [ $got eq $data, 'ssl_read_all' ]; + + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + + close $wc; + close $rc; +} + +waitpid $pid, 0; +push @results, [ $? == 0, 'server exited with 0' ]; + +Test::More->builder->current_test(5); +for my $t (@results) { + ok( $t->[0], $t->[1] ); +} diff --git a/t/local/09_ctx_new.t b/t/local/09_ctx_new.t new file mode 100644 index 0000000..67f685a --- /dev/null +++ b/t/local/09_ctx_new.t @@ -0,0 +1,187 @@ +#!/usr/bin/perl + +# Tests for SSL_CTX_new and related functions +# Also test handshake state machine retrieval + +use strict; +use warnings; +use Test::More tests => 44; +use Net::SSLeay; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::add_ssl_algorithms(); +Net::SSLeay::OpenSSL_add_all_algorithms(); + +sub is_known_proto_version { + return 1 if $_[0] == 0x0000; # Automatic version selection + return 1 if $_[0] == Net::SSLeay::SSL3_VERSION(); # OpenSSL 0.9.8+ + return 1 if $_[0] == Net::SSLeay::TLS1_VERSION(); # OpenSSL 0.9.8+ + return 1 if $_[0] == Net::SSLeay::TLS1_1_VERSION(); # OpenSSL 0.9.8+ + return 1 if $_[0] == Net::SSLeay::TLS1_2_VERSION(); # OpenSSL 0.9.8+ + if (eval { Net::SSLeay::TLS1_3_VERSION() }) { + return 1 if $_[0] == Net::SSLeay::TLS1_3_VERSION(); # OpenSSL 1.1.1+ + } + + return; +} + +# Shortcuts from SSLeay.xs +my $ctx = Net::SSLeay::CTX_new(); +ok($ctx, 'CTX_new'); +$ctx = Net::SSLeay::CTX_v23_new(); +ok($ctx, 'CTX_v23_new'); +$ctx = Net::SSLeay::CTX_tlsv1_new(); +ok($ctx, 'CTX_tlsv1_new'); + +my $ctx_23 = Net::SSLeay::CTX_new_with_method(Net::SSLeay::SSLv23_method()); +ok($ctx_23, 'CTX_new with SSLv23_method'); + +my $ctx_23_client = Net::SSLeay::CTX_new_with_method(Net::SSLeay::SSLv23_client_method()); +ok($ctx_23_client, 'CTX_new with SSLv23_client_method'); + +my $ctx_23_server = Net::SSLeay::CTX_new_with_method(Net::SSLeay::SSLv23_server_method()); +ok($ctx_23_server, 'CTX_new with SSLv23_server_method'); + +my $ctx_tls1 = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_method()); +ok($ctx_tls1, 'CTX_new with TLSv1_method'); + +# Retrieve information about the handshake state machine +is(Net::SSLeay::in_connect_init(Net::SSLeay::new($ctx_23_client)), 1, 'in_connect_init() is 1 for client'); +is(Net::SSLeay::in_accept_init(Net::SSLeay::new($ctx_23_client)), 0, 'in_accept_init() is 0 for client'); +is(Net::SSLeay::in_connect_init(Net::SSLeay::new($ctx_23_server)), 0, 'in_connect_init() is 0 for server'); +is(Net::SSLeay::in_accept_init(Net::SSLeay::new($ctx_23_server)), 1, 'in_accept_init() is 1 for server'); + +# Need recent enough OpenSSL or LibreSSL for TLS_method functions +my ($ctx_tls, $ssl_tls, $ctx_tls_client, $ssl_tls_client, $ctx_tls_server, $ssl_tls_server); +if (exists &Net::SSLeay::TLS_method) +{ + $ctx_tls = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLS_method()); + ok($ctx_tls, 'CTX_new with TLS_method'); + + $ssl_tls = Net::SSLeay::new($ctx_tls); + ok($ssl_tls, 'New SSL created with ctx_tls'); + + $ctx_tls_client = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLS_client_method()); + ok($ctx_tls_client, 'CTX_new with TLS_client_method'); + + $ctx_tls_server = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLS_server_method()); + ok($ctx_tls_server, 'CTX_new with TLS_server_method'); +} +else +{ + SKIP: { + skip('Do not have Net::SSLeay::TLS_method', 4); + }; +} + +# Having TLS_method() does not necessarily that proto setters are available +if ($ctx_tls && exists &Net::SSLeay::CTX_set_min_proto_version) +{ + my $ver_1_0 = Net::SSLeay::TLS1_VERSION(); + ok($ver_1_0, "Net::SSLeay::TLS1_VERSION() returns non-false: $ver_1_0, hex " . sprintf('0x%04x', $ver_1_0)); + my $ver_min = Net::SSLeay::TLS1_1_VERSION(); + ok($ver_min, "Net::SSLeay::TLS1_1_VERSION() returns non-false: $ver_min, hex " . sprintf('0x%04x', $ver_min)); + my $ver_max = Net::SSLeay::TLS1_2_VERSION(); + ok($ver_max, "Net::SSLeay::TLS1_2_VERSION() returns $ver_max, hex " . sprintf('0x%04x', $ver_max)); + isnt($ver_1_0, $ver_min, 'Version 1_0 and 1_1 values are different'); + isnt($ver_min, $ver_max, 'Version 1_1 and 1_2 values are different'); + + my $rv; + + $rv = Net::SSLeay::CTX_set_min_proto_version($ctx_tls_client, $ver_min); + is($rv, 1, 'Setting client CTX minimum version'); + + $rv = Net::SSLeay::CTX_set_min_proto_version($ctx_tls_client, 0); + is($rv, 1, 'Setting client CTX minimum version to automatic'); + + $rv = Net::SSLeay::CTX_set_min_proto_version($ctx_tls_client, -1); + is($rv, 0, 'Setting client CTX minimum version to bad value'); + + $rv = Net::SSLeay::CTX_set_min_proto_version($ctx_tls_client, $ver_min); + is($rv, 1, 'Setting client CTX minimum version back to good value'); + + $rv = Net::SSLeay::CTX_set_max_proto_version($ctx_tls_client, $ver_max); + is($rv, 1, 'Setting client CTX maximum version'); + + # This SSL should have min and max versions set based on its + # CTX. We test the getters later, if they exist. + $ssl_tls_client = Net::SSLeay::new($ctx_tls_client); + ok($ssl_tls_client, 'New SSL created from client CTX'); + + # This SSL should have min and max versions set to automatic based + # on its CTX. We change them now and test the getters later, if + # they exist. + $ssl_tls_server = Net::SSLeay::new($ctx_tls_server); + ok($ssl_tls_server, 'New SSL created from server CTX'); + $rv = Net::SSLeay::set_min_proto_version($ssl_tls_server, Net::SSLeay::TLS1_VERSION()); + is($rv, 1, 'Setting SSL minimum version for ssl_tls_server'); + $rv = Net::SSLeay::set_max_proto_version($ssl_tls_server, Net::SSLeay::TLS1_2_VERSION()); + is($rv, 1, 'Setting SSL maximum version for ssl_tls_server'); +} +else +{ + SKIP: { + skip('Do not have Net::SSLeay::CTX_get_min_proto_version', 14); + }; +} + +# Having TLS_method() does not necessarily that proto getters are available +if ($ctx_tls && exists &Net::SSLeay::CTX_get_min_proto_version) +{ + my $ver; + $ver = Net::SSLeay::CTX_get_min_proto_version($ctx_tls); + ok(is_known_proto_version($ver), 'TLS_method CTX has known minimum version'); + $ver = Net::SSLeay::CTX_get_max_proto_version($ctx_tls); + ok(is_known_proto_version($ver), 'TLS_method CTX has known maximum version'); + + $ver = Net::SSLeay::get_min_proto_version($ssl_tls); + ok(is_known_proto_version($ver), 'SSL from TLS_method CTX has known minimum version'); + $ver = Net::SSLeay::get_max_proto_version($ssl_tls); + ok(is_known_proto_version($ver), 'SSL from TLS_method CTX has known maximum version'); + + # First see if our CTX has min and max settings enabled + $ver = Net::SSLeay::CTX_get_min_proto_version($ctx_tls_client); + is($ver, Net::SSLeay::TLS1_1_VERSION(), 'TLS_client CTX has minimum version correctly set'); + $ver = Net::SSLeay::CTX_get_max_proto_version($ctx_tls_client); + is($ver, Net::SSLeay::TLS1_2_VERSION(), 'TLS_client CTX has maximum version correctly set'); + + # Then see if our client SSL has min and max settings enabled + $ver = Net::SSLeay::get_min_proto_version($ssl_tls_client); + is($ver, Net::SSLeay::TLS1_1_VERSION(), 'SSL from TLS_client CTX has minimum version correctly set'); + $ver = Net::SSLeay::get_max_proto_version($ssl_tls_client); + is($ver, Net::SSLeay::TLS1_2_VERSION(), 'SSL from TLS_client CTX has maximum version correctly set'); + + # Then see if our server SSL has min and max settings enabled + $ver = Net::SSLeay::get_min_proto_version($ssl_tls_server); + is($ver, Net::SSLeay::TLS1_VERSION(), 'SSL from TLS_server CTX has minimum version correctly set'); + $ver = Net::SSLeay::get_max_proto_version($ssl_tls_server); + is($ver, Net::SSLeay::TLS1_2_VERSION(), 'SSL from TLS_server CTX has maximum version correctly set'); +} +else +{ + SKIP: { + skip('Do not have Net::SSLeay::CTX_get_min_proto_version', 10); + }; +} + +if (eval {Net::SSLeay::TLS1_3_VERSION()}) +{ + my $ver_1_2 = Net::SSLeay::TLS1_2_VERSION(); + ok($ver_1_2, "Net::SSLeay::TLS1_2_VERSION() returns non-false: $ver_1_2, hex " . sprintf('0x%04x', $ver_1_2)); + my $ver_1_3 = Net::SSLeay::TLS1_3_VERSION(); + ok($ver_1_3, "Net::SSLeay::TLS1_3_VERSION() returns non-false: $ver_1_3, hex " . sprintf('0x%04x', $ver_1_3)); + isnt($ver_1_2, $ver_1_3, 'Version 1_2 and 1_3 values are different'); + + my $rv = 0; + ok(eval {$rv = Net::SSLeay::OP_NO_TLSv1_3()}, 'Have OP_NO_TLSv1_3'); + isnt($rv, 0, 'OP_NO_TLSv1_3 returns non-zero value'); +} +else +{ + SKIP: { + skip('Do not have Net::SSLeay::TLS1_3_VERSION', 5); + }; +} + +exit(0); diff --git a/t/local/10_rand.t b/t/local/10_rand.t new file mode 100644 index 0000000..c39c6a3 --- /dev/null +++ b/t/local/10_rand.t @@ -0,0 +1,82 @@ +#!/usr/bin/perl + +# RAND related tests + +use strict; +use warnings; +use Test::More; +use File::Spec; +use Net::SSLeay; + +plan tests => 52; + +is(Net::SSLeay::RAND_status(), 1, 'RAND_status'); +is(Net::SSLeay::RAND_poll(), 1, 'RAND_poll'); + +# RAND_file_name +my $file_name = Net::SSLeay::RAND_file_name(300); +isnt($file_name, undef, 'RAND_file_name returns defined value'); +isnt($file_name, "", "RAND_file_name returns non-empty string: $file_name"); + +# RAND_load_file +my $binary_file = File::Spec->catfile('t', 'data', 'binary-test.file'); +my $binary_file_size = -s $binary_file; +cmp_ok($binary_file_size, '>=', 1000, "Have binary file with good size: $binary_file $binary_file_size"); +is(Net::SSLeay::RAND_load_file($binary_file, $binary_file_size), $binary_file_size, 'RAND_load with specific size'); +if (Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER")) +{ + # RAND_load_file does nothing on LibreSSL but should return something sane + cmp_ok(Net::SSLeay::RAND_load_file($binary_file, -1), '>', 0, 'RAND_load with -1 is positive with LibreSSL'); +} else { + is(Net::SSLeay::RAND_load_file($binary_file, -1), $binary_file_size, 'RAND_load with -1 returns file size'); +} + +test_rand_bytes(); + +exit(0); + +sub test_rand_bytes +{ + my ($ret, $rand_bytes, $rand_length, $rand_expected_length); + + my @rand_lengths = (0, 1, 1024, 65536, 1024**2); + + foreach $rand_expected_length (@rand_lengths) + { + $rand_length = $rand_expected_length; + $ret = Net::SSLeay::RAND_bytes($rand_bytes, $rand_length); + test_rand_bytes_results('RAND_bytes', $ret, $rand_bytes, $rand_length, $rand_expected_length); + } + + foreach $rand_expected_length (@rand_lengths) + { + $rand_length = $rand_expected_length; + $ret = Net::SSLeay::RAND_pseudo_bytes($rand_bytes, $rand_length); + test_rand_bytes_results('RAND_pseudo_bytes', $ret, $rand_bytes, $rand_length, $rand_expected_length); + } + + if (defined &Net::SSLeay::RAND_priv_bytes) + { + foreach $rand_expected_length (@rand_lengths) + { + $rand_length = $rand_expected_length; + $ret = Net::SSLeay::RAND_priv_bytes($rand_bytes, $rand_length); + test_rand_bytes_results('RAND_priv_bytes', $ret, $rand_bytes, $rand_length, $rand_expected_length); + } + } else { + SKIP : { + # Multiplier is the test count in test_rand_bytes_results + skip("Do not have Net::SSLeay::RAND_priv_bytes", ((scalar @rand_lengths) * 3)); + }; + } +} + +sub test_rand_bytes_results +{ + my ($func, $ret, $rand_bytes, $rand_length, $rand_expected_length) = @_; + + # RAND_bytes functions do not update their rand_length argument, but check for this + is($ret, 1, "$func: $rand_expected_length return value ok"); + is(length($rand_bytes), $rand_length, "$func: length of rand_bytes and rand_length match"); + is(length($rand_bytes), $rand_expected_length, "$func: length of rand_bytes is expected length $rand_length"); +} diff --git a/t/local/11_read.t b/t/local/11_read.t new file mode 100644 index 0000000..e43ee7f --- /dev/null +++ b/t/local/11_read.t @@ -0,0 +1,321 @@ +#!/usr/bin/perl + +# Various SSL read and write related tests: +# - SSL_read, SSL_peek, SSL_read_ex, SSL_peek_ex, +# - SSL_write_ex, SSL_pending and SSL_has_pending. + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; +use IO::Socket::INET; +use Storable; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +my $tests = 53; +plan tests => $tests; + +my $pid; +alarm(30); +END { kill 9,$pid if $pid } + +my $server; +Net::SSLeay::initialize(); + +# See that lengths differ for all msgs +my $msg1 = "1 first message from server"; +my $msg2 = "2 second message from server"; +my $msg3 = "3 third message from server: pad"; + +my @rounds = qw(openssl openssl-1.1.0 openssl-1.1.1); + +sub server +{ + # SSL server - just handle connections, send to client and exit + my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); + my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + + $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3) + or BAIL_OUT("failed to create server socket: $!"); + + defined($pid = fork()) or BAIL_OUT("failed to fork: $!"); + if ($pid == 0) { + foreach my $round (@rounds) + { + my ($ctx, $ssl, $cl); + + next if skip_round($round); + + $cl = $server->accept or BAIL_OUT("accept failed: $!"); + + $ctx = Net::SSLeay::CTX_new(); + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + + $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, fileno($cl)); + Net::SSLeay::accept($ssl); + + Net::SSLeay::write($ssl, $msg1); + Net::SSLeay::write($ssl, $msg2); + + my $msg = Net::SSLeay::read($ssl); + Net::SSLeay::write($ssl, $msg); + } + exit(0); + } +} + +sub client +{ + my $saddr = $server->sockhost.':'.$server->sockport; + foreach my $round (@rounds) + { + my ($ctx, $ssl, $cl); + + $cl = IO::Socket::INET->new($saddr) + or BAIL_OUT("failed to connect to server: $!"); + + $ctx = Net::SSLeay::CTX_new(); + $ssl = Net::SSLeay::new($ctx); + + my ($reason, $num_tests) = skip_round($round); + if ($reason) { + SKIP: { + skip($reason, $num_tests); + } + next; + } + + round_openssl($ctx, $ssl, $cl) if $round eq 'openssl'; + round_openssl_1_1_0($ctx, $ssl, $cl) if $round eq 'openssl-1.1.0'; + round_openssl_1_1_1($ctx, $ssl, $cl) if $round eq 'openssl-1.1.1'; + + Net::SSLeay::shutdown($ssl); + Net::SSLeay::free($ssl); + } + return; +} + +# Returns list for skip() if we should skip this round, false if we +# shouldn't +sub skip_round +{ + my ($round) = @_; + + return if $round eq 'openssl'; + + if ($round eq 'openssl-1.1.0') { + if (Net::SSLeay::constant("OPENSSL_VERSION_NUMBER") < 0x1010000f || + Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER")) + { + return ("Need OpenSSL 1.1.0 or later", 6); + } else { + return; + } + } + + if ($round eq 'openssl-1.1.1') { + if (Net::SSLeay::constant("OPENSSL_VERSION_NUMBER") < 0x1010100f || + Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER")) + { + return ("Need OpenSSL 1.1.1 or later", 26); + } else { + return; + } + } + + diag("Unknown round: $round"); + return; +} + +sub round_openssl +{ + my ($ctx, $ssl, $cl) = @_; + + my ($peek_msg, $read_msg, $len, $err, $ret); + + # ssl is not connected yet + $peek_msg = Net::SSLeay::peek($ssl); + is($peek_msg, undef, "scalar: peek returns undef for closed ssl"); + + ($peek_msg, $len) = Net::SSLeay::peek($ssl); + is($peek_msg, undef, "list: peek returns undef for closed ssl"); + cmp_ok($len, '<=', 0, 'list: peek returns length <=0 for closed ssl'); + $err = Net::SSLeay::get_error($ssl, $len); + isnt($err, Net::SSLeay::ERROR_WANT_READ(), "peek err $err is not retryable WANT_READ"); + isnt($err, Net::SSLeay::ERROR_WANT_WRITE(), "peek err $err is not retryable WANT_WRITE"); + + $read_msg = Net::SSLeay::read($ssl); + is($read_msg, undef, "scalar: read returns undef for closed ssl"); + + ($read_msg, $len) = Net::SSLeay::read($ssl); + is($read_msg, undef, "list: read returns undef for closed ssl"); + cmp_ok($len, '<=', 0, 'list: read returns length <=0 for closed ssl'); + $err = Net::SSLeay::get_error($ssl, $len); + isnt($err, Net::SSLeay::ERROR_WANT_READ(), "read err $err is not retryable WANT_READ"); + isnt($err, Net::SSLeay::ERROR_WANT_WRITE(), "read err $err is not retryable WANT_WRITE"); + + $ret = Net::SSLeay::pending($ssl); + is($ret, 0, "pending returns 0 for closed ssl"); + + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::connect($ssl); + + # msg1 + $ret = Net::SSLeay::pending($ssl); + is($ret, 0, "pending returns 0"); + + $peek_msg = Net::SSLeay::peek($ssl); + is($peek_msg, $msg1, "scalar: peek returns msg1"); + + # processing was triggered by peek + $ret = Net::SSLeay::pending($ssl); + is($ret, length($msg1), "pending returns msg1 length"); + + ($peek_msg, $len) = Net::SSLeay::peek($ssl); + is($peek_msg, $msg1, "list: peek returns msg1"); + is($len, length($msg1), "list: peek returns msg1 length"); + + $read_msg = Net::SSLeay::read($ssl); + is($peek_msg, $read_msg, "scalar: read and peek agree about msg1"); + + # msg2 + $peek_msg = Net::SSLeay::peek($ssl); + is($peek_msg, $msg2, "scalar: peek returns msg2"); + + ($read_msg, $len) = Net::SSLeay::read($ssl); + is($peek_msg, $read_msg, "list: read and peek agree about msg2"); + is($len, length($msg2), "list: read returns msg2 length"); + + # msg3 + Net::SSLeay::write($ssl, $msg3); + is(Net::SSLeay::read($ssl), $msg3, "ping with msg3"); + + return; +} + +# Test has_pending and other functionality added in 1.1.0. +# Revisit: Better tests for has_pending +sub round_openssl_1_1_0 +{ + my ($ctx, $ssl, $cl) = @_; + + my ($peek_msg, $read_msg, $len, $err, $ret); + + # ssl is not connected yet + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 0, "1.1.0: has_pending returns 0 for closed ssl"); + + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::connect($ssl); + + # msg1 + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 0, "1.1.0: has_pending returns 0"); + + # This triggers processing after which we have pending data + $peek_msg = Net::SSLeay::peek($ssl); + is($peek_msg, $msg1, "1.1.0: peek returns msg1"); + + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 1, "1.1.0: has_pending returns 1"); + + Net::SSLeay::read($ssl); # Read and discard + + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 0, "1.1.0: has_pending returns 0 after read"); + + # msg2 + Net::SSLeay::read($ssl); # Read and discard + + # msg3 + Net::SSLeay::write($ssl, $msg3); + is(Net::SSLeay::read($ssl), $msg3, "1.1.0: ping with msg3"); + + return; +} + +sub round_openssl_1_1_1 +{ + my ($ctx, $ssl, $cl) = @_; + + my ($peek_msg, $read_msg, $len, $err, $err_ex, $ret); + + # ssl is not connected yet + ($peek_msg, $ret) = Net::SSLeay::peek_ex($ssl); + is($peek_msg, undef, "1.1.1: list: peek_ex returns undef message for closed ssl"); + is($ret, 0, '1.1.1: list: peek_ex returns 0 for closed ssl'); + $err = Net::SSLeay::get_error($ssl, $ret); + isnt($err, Net::SSLeay::ERROR_WANT_READ(), "1.1.1: peek_ex err $err is not retryable WANT_READ"); + isnt($err, Net::SSLeay::ERROR_WANT_WRITE(), "1.1.1: peek_ex err $err is not retryable WANT_WRITE"); + + ($read_msg, $len) = Net::SSLeay::read($ssl); + is($read_msg, undef, "1.1.1: list: read returns undef message for closed ssl"); + cmp_ok($len, '<=', 0, '1.1.1: list: read returns length <=0 for closed ssl'); + $err = Net::SSLeay::get_error($ssl, $len); + isnt($err, Net::SSLeay::ERROR_WANT_READ(), "1.1.1: read err $err is not retryable WANT_READ"); + isnt($err, Net::SSLeay::ERROR_WANT_WRITE(), "1.1.1: read err $err is not retryable WANT_WRITE"); + + ($read_msg, $ret) = Net::SSLeay::read_ex($ssl); + is($read_msg, undef, "1.1.1: list: read_ex returns undef message for closed sssl"); + is($ret, 0, "1.1.1: list: read_ex returns 0 for closed sssl"); + $err_ex = Net::SSLeay::get_error($ssl, $ret); + is ($err_ex, $err, '1.1.1: read_ex and read err are equal'); + + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::connect($ssl); + + # msg1 + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 0, "1.1.1: has_pending returns 0"); + + # This triggers processing after which we have pending data + ($peek_msg, $ret) = Net::SSLeay::peek_ex($ssl); + is($peek_msg, $msg1, "1.1.1: list: peek_ex returns msg1"); + is($ret, 1, "1.1.1: list: peek_ex returns 1"); + + $len = Net::SSLeay::pending($ssl); + is($len, length($msg1), "1.1.1: pending returns msg1 length"); + + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 1, "1.1.1: has_pending returns 1"); + + ($read_msg, $ret) = Net::SSLeay::read_ex($ssl); + is($read_msg, $msg1, "1.1.1: list: read_ex returns msg1"); + is($ret, 1, "1.1.1: list: read_ex returns 1"); + + $len = Net::SSLeay::pending($ssl); + is($len, 0, "1.1.1: pending returns 0 after read_ex"); + + $ret = Net::SSLeay::has_pending($ssl); + is($ret, 0, "1.1.1: has_pending returns 0 after read_ex"); + + # msg2 + Net::SSLeay::read($ssl); # Read and discard + + # msg3 + ($len, $ret) = Net::SSLeay::write_ex($ssl, $msg3); + is($len, length($msg3), "1.1.1: write_ex wrote all"); + is($ret, 1, "1.1.1: write_ex returns 1"); + + my ($read_msg1, $ret1) = Net::SSLeay::read_ex($ssl, 5); + my ($read_msg2, $ret2) = Net::SSLeay::read_ex($ssl, (length($msg3) - 5)); + + is($ret1, 1, '1.1.1: ping with msg3 part1 ok'); + is($ret2, 1, '1.1.1: ping with msg3 part2 ok'); + is(length($read_msg1), 5, '1.1.1: ping with msg3, part1 length was 5'); + is($read_msg1 . $read_msg2, $msg3, "1.1.1: ping with msg3 in two parts"); + + return; +} + +server(); +client(); +waitpid $pid, 0; +exit(0); diff --git a/t/local/15_bio.t b/t/local/15_bio.t new file mode 100644 index 0000000..20f72c9 --- /dev/null +++ b/t/local/15_bio.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 7; +use Net::SSLeay; + +my $data = '0123456789' x 100; +my $len = length $data; + +ok( my $bio = Net::SSLeay::BIO_new( &Net::SSLeay::BIO_s_mem ), 'BIO_new' ); +is( Net::SSLeay::BIO_write($bio, $data), $len, 'BIO_write' ); +is( Net::SSLeay::BIO_pending($bio), $len, 'BIO_pending' ); + +my $read_len = 9; +is( Net::SSLeay::BIO_read($bio, $read_len), substr($data, 0, $read_len), 'BIO_read part' ); +is( Net::SSLeay::BIO_pending($bio), $len - $read_len, 'BIO_pending' ); + +is( Net::SSLeay::BIO_read($bio), substr($data, $read_len), 'BIO_read rest' ); + +ok( Net::SSLeay::BIO_free($bio), 'BIO_free' ); diff --git a/t/local/20_autoload.t b/t/local/20_autoload.t new file mode 100644 index 0000000..a0d63d6 --- /dev/null +++ b/t/local/20_autoload.t @@ -0,0 +1,171 @@ +#!/usr/bin/perl + +# DO NOT EDIT THIS FILE - update __DATA__ section of helper_script/regen_openssl_constants.pl + +use strict; +use warnings; +use Net::SSLeay; + +eval "use Test::Exception;"; +if ($@) +{ + eval "use Test::More skip_all => 'Some tests need Test::Exception';"; +} +else +{ + eval 'use Test::More tests => 417;'; +} + +my @c = (qw/ + ASN1_STRFLGS_ESC_CTRL NID_hmacWithSHA1 OP_COOKIE_EXCHANGE + ASN1_STRFLGS_ESC_MSB NID_id_ad OP_CRYPTOPRO_TLSEXT_BUG + ASN1_STRFLGS_ESC_QUOTE NID_id_ce OP_DONT_INSERT_EMPTY_FRAGMENTS + ASN1_STRFLGS_RFC2253 NID_id_kp OP_EPHEMERAL_RSA + CB_ACCEPT_EXIT NID_id_pbkdf2 OP_LEGACY_SERVER_CONNECT + CB_ACCEPT_LOOP NID_id_pe OP_MICROSOFT_BIG_SSLV3_BUFFER + CB_CONNECT_EXIT NID_id_pkix OP_MICROSOFT_SESS_ID_BUG + CB_CONNECT_LOOP NID_id_qt_cps OP_MSIE_SSLV2_RSA_PADDING + ERROR_NONE NID_id_qt_unotice OP_NETSCAPE_CA_DN_BUG + ERROR_SSL NID_idea_cbc OP_NETSCAPE_CHALLENGE_BUG + ERROR_SYSCALL NID_idea_cfb64 OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG + ERROR_WANT_ACCEPT NID_idea_ecb OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG + ERROR_WANT_CONNECT NID_idea_ofb64 OP_NON_EXPORT_FIRST + ERROR_WANT_READ NID_info_access OP_NO_COMPRESSION + ERROR_WANT_WRITE NID_initials OP_NO_QUERY_MTU + ERROR_WANT_X509_LOOKUP NID_invalidity_date OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + ERROR_ZERO_RETURN NID_issuer_alt_name OP_NO_SSLv2 + EVP_PKS_DSA NID_keyBag OP_NO_SSLv3 + EVP_PKS_EC NID_key_usage OP_NO_TICKET + EVP_PKS_RSA NID_localKeyID OP_NO_TLSv1 + EVP_PKT_ENC NID_localityName OP_NO_TLSv1_1 + EVP_PKT_EXCH NID_md2 OP_NO_TLSv1_2 + EVP_PKT_EXP NID_md2WithRSAEncryption OP_PKCS1_CHECK_1 + EVP_PKT_SIGN NID_md5 OP_PKCS1_CHECK_2 + EVP_PK_DH NID_md5WithRSA OP_SINGLE_DH_USE + EVP_PK_DSA NID_md5WithRSAEncryption OP_SINGLE_ECDH_USE + EVP_PK_EC NID_md5_sha1 OP_SSLEAY_080_CLIENT_DH_BUG + EVP_PK_RSA NID_mdc2 OP_SSLREF2_REUSE_CERT_TYPE_BUG + FILETYPE_ASN1 NID_mdc2WithRSA OP_TLS_BLOCK_PADDING_BUG + FILETYPE_PEM NID_ms_code_com OP_TLS_D5_BUG + F_CLIENT_CERTIFICATE NID_ms_code_ind OP_TLS_ROLLBACK_BUG + F_CLIENT_HELLO NID_ms_ctl_sign READING + F_CLIENT_MASTER_KEY NID_ms_efs RECEIVED_SHUTDOWN + F_D2I_SSL_SESSION NID_ms_ext_req RSA_3 + F_GET_CLIENT_FINISHED NID_ms_sgc RSA_F4 + F_GET_CLIENT_HELLO NID_name R_BAD_AUTHENTICATION_TYPE + F_GET_CLIENT_MASTER_KEY NID_netscape R_BAD_CHECKSUM + F_GET_SERVER_FINISHED NID_netscape_base_url R_BAD_MAC_DECODE + F_GET_SERVER_HELLO NID_netscape_ca_policy_url R_BAD_RESPONSE_ARGUMENT + F_GET_SERVER_VERIFY NID_netscape_ca_revocation_url R_BAD_SSL_FILETYPE + F_I2D_SSL_SESSION NID_netscape_cert_extension R_BAD_SSL_SESSION_ID_LENGTH + F_READ_N NID_netscape_cert_sequence R_BAD_STATE + F_REQUEST_CERTIFICATE NID_netscape_cert_type R_BAD_WRITE_RETRY + F_SERVER_HELLO NID_netscape_comment R_CHALLENGE_IS_DIFFERENT + F_SSL_CERT_NEW NID_netscape_data_type R_CIPHER_TABLE_SRC_ERROR + F_SSL_GET_NEW_SESSION NID_netscape_renewal_url R_INVALID_CHALLENGE_LENGTH + F_SSL_NEW NID_netscape_revocation_url R_NO_CERTIFICATE_SET + F_SSL_READ NID_netscape_ssl_server_name R_NO_CERTIFICATE_SPECIFIED + F_SSL_RSA_PRIVATE_DECRYPT NID_ns_sgc R_NO_CIPHER_LIST + F_SSL_RSA_PUBLIC_ENCRYPT NID_organizationName R_NO_CIPHER_MATCH + F_SSL_SESSION_NEW NID_organizationalUnitName R_NO_PRIVATEKEY + F_SSL_SESSION_PRINT_FP NID_pbeWithMD2AndDES_CBC R_NO_PUBLICKEY + F_SSL_SET_FD NID_pbeWithMD2AndRC2_CBC R_NULL_SSL_CTX + F_SSL_SET_RFD NID_pbeWithMD5AndCast5_CBC R_PEER_DID_NOT_RETURN_A_CERTIFICATE + F_SSL_SET_WFD NID_pbeWithMD5AndDES_CBC R_PEER_ERROR + F_SSL_USE_CERTIFICATE NID_pbeWithMD5AndRC2_CBC R_PEER_ERROR_CERTIFICATE + F_SSL_USE_CERTIFICATE_ASN1 NID_pbeWithSHA1AndDES_CBC R_PEER_ERROR_NO_CIPHER + F_SSL_USE_CERTIFICATE_FILE NID_pbeWithSHA1AndRC2_CBC R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE + F_SSL_USE_PRIVATEKEY NID_pbe_WithSHA1And128BitRC2_CBC R_PUBLIC_KEY_ENCRYPT_ERROR + F_SSL_USE_PRIVATEKEY_ASN1 NID_pbe_WithSHA1And128BitRC4 R_PUBLIC_KEY_IS_NOT_RSA + F_SSL_USE_PRIVATEKEY_FILE NID_pbe_WithSHA1And2_Key_TripleDES_CBC R_READ_WRONG_PACKET_TYPE + F_SSL_USE_RSAPRIVATEKEY NID_pbe_WithSHA1And3_Key_TripleDES_CBC R_SHORT_READ + F_SSL_USE_RSAPRIVATEKEY_ASN1 NID_pbe_WithSHA1And40BitRC2_CBC R_SSL_SESSION_ID_IS_DIFFERENT + F_SSL_USE_RSAPRIVATEKEY_FILE NID_pbe_WithSHA1And40BitRC4 R_UNABLE_TO_EXTRACT_PUBLIC_KEY + F_WRITE_PENDING NID_pbes2 R_UNKNOWN_REMOTE_ERROR_TYPE + GEN_DIRNAME NID_pbmac1 R_UNKNOWN_STATE + GEN_DNS NID_pkcs R_X509_LIB + GEN_EDIPARTY NID_pkcs3 SENT_SHUTDOWN + GEN_EMAIL NID_pkcs7 SESSION_ASN1_VERSION + GEN_IPADD NID_pkcs7_data ST_ACCEPT + GEN_OTHERNAME NID_pkcs7_digest ST_BEFORE + GEN_RID NID_pkcs7_encrypted ST_CONNECT + GEN_URI NID_pkcs7_enveloped ST_INIT + GEN_X400 NID_pkcs7_signed ST_OK + LIBRESSL_VERSION_NUMBER NID_pkcs7_signedAndEnveloped ST_READ_BODY + MBSTRING_ASC NID_pkcs8ShroudedKeyBag ST_READ_HEADER + MBSTRING_BMP NID_pkcs9 TLSEXT_STATUSTYPE_ocsp + MBSTRING_FLAG NID_pkcs9_challengePassword VERIFY_CLIENT_ONCE + MBSTRING_UNIV NID_pkcs9_contentType VERIFY_FAIL_IF_NO_PEER_CERT + MBSTRING_UTF8 NID_pkcs9_countersignature VERIFY_NONE + MIN_RSA_MODULUS_LENGTH_IN_BYTES NID_pkcs9_emailAddress VERIFY_PEER + MODE_ACCEPT_MOVING_WRITE_BUFFER NID_pkcs9_extCertAttributes V_OCSP_CERTSTATUS_GOOD + MODE_AUTO_RETRY NID_pkcs9_messageDigest V_OCSP_CERTSTATUS_REVOKED + MODE_ENABLE_PARTIAL_WRITE NID_pkcs9_signingTime V_OCSP_CERTSTATUS_UNKNOWN + MODE_RELEASE_BUFFERS NID_pkcs9_unstructuredAddress WRITING + NID_OCSP_sign NID_pkcs9_unstructuredName X509_LOOKUP + NID_SMIMECapabilities NID_private_key_usage_period X509_PURPOSE_ANY + NID_X500 NID_rc2_40_cbc X509_PURPOSE_CRL_SIGN + NID_X509 NID_rc2_64_cbc X509_PURPOSE_NS_SSL_SERVER + NID_ad_OCSP NID_rc2_cbc X509_PURPOSE_OCSP_HELPER + NID_ad_ca_issuers NID_rc2_cfb64 X509_PURPOSE_SMIME_ENCRYPT + NID_algorithm NID_rc2_ecb X509_PURPOSE_SMIME_SIGN + NID_authority_key_identifier NID_rc2_ofb64 X509_PURPOSE_SSL_CLIENT + NID_basic_constraints NID_rc4 X509_PURPOSE_SSL_SERVER + NID_bf_cbc NID_rc4_40 X509_PURPOSE_TIMESTAMP_SIGN + NID_bf_cfb64 NID_rc5_cbc X509_TRUST_COMPAT + NID_bf_ecb NID_rc5_cfb64 X509_TRUST_EMAIL + NID_bf_ofb64 NID_rc5_ecb X509_TRUST_OBJECT_SIGN + NID_cast5_cbc NID_rc5_ofb64 X509_TRUST_OCSP_REQUEST + NID_cast5_cfb64 NID_ripemd160 X509_TRUST_OCSP_SIGN + NID_cast5_ecb NID_ripemd160WithRSA X509_TRUST_SSL_CLIENT + NID_cast5_ofb64 NID_rle_compression X509_TRUST_SSL_SERVER + NID_certBag NID_rsa X509_TRUST_TSA + NID_certificate_policies NID_rsaEncryption X509_V_FLAG_ALLOW_PROXY_CERTS + NID_client_auth NID_rsadsi X509_V_FLAG_CB_ISSUER_CHECK + NID_code_sign NID_safeContentsBag X509_V_FLAG_CHECK_SS_SIGNATURE + NID_commonName NID_sdsiCertificate X509_V_FLAG_CRL_CHECK + NID_countryName NID_secretBag X509_V_FLAG_CRL_CHECK_ALL + NID_crlBag NID_serialNumber X509_V_FLAG_EXPLICIT_POLICY + NID_crl_distribution_points NID_server_auth X509_V_FLAG_EXTENDED_CRL_SUPPORT + NID_crl_number NID_sha X509_V_FLAG_IGNORE_CRITICAL + NID_crl_reason NID_sha1 X509_V_FLAG_INHIBIT_ANY + NID_delta_crl NID_sha1WithRSA X509_V_FLAG_INHIBIT_MAP + NID_des_cbc NID_sha1WithRSAEncryption X509_V_FLAG_NOTIFY_POLICY + NID_des_cfb64 NID_shaWithRSAEncryption X509_V_FLAG_POLICY_CHECK + NID_des_ecb NID_stateOrProvinceName X509_V_FLAG_POLICY_MASK + NID_des_ede NID_subject_alt_name X509_V_FLAG_USE_CHECK_TIME + NID_des_ede3 NID_subject_key_identifier X509_V_FLAG_USE_DELTAS + NID_des_ede3_cbc NID_surname X509_V_FLAG_X509_STRICT + NID_des_ede3_cfb64 NID_sxnet X509_V_OK + NID_des_ede3_ofb64 NID_time_stamp XN_FLAG_COMPAT + NID_des_ede_cbc NID_title XN_FLAG_DN_REV + NID_des_ede_cfb64 NID_undef XN_FLAG_DUMP_UNKNOWN_FIELDS + NID_des_ede_ofb64 NID_uniqueIdentifier XN_FLAG_FN_ALIGN + NID_des_ofb64 NID_x509Certificate XN_FLAG_FN_LN + NID_description NID_x509Crl XN_FLAG_FN_MASK + NID_desx_cbc NID_zlib_compression XN_FLAG_FN_NONE + NID_dhKeyAgreement NOTHING XN_FLAG_FN_OID + NID_dnQualifier OCSP_RESPONSE_STATUS_INTERNALERROR XN_FLAG_FN_SN + NID_dsa OCSP_RESPONSE_STATUS_MALFORMEDREQUEST XN_FLAG_MULTILINE + NID_dsaWithSHA OCSP_RESPONSE_STATUS_SIGREQUIRED XN_FLAG_ONELINE + NID_dsaWithSHA1 OCSP_RESPONSE_STATUS_SUCCESSFUL XN_FLAG_RFC2253 + NID_dsaWithSHA1_2 OCSP_RESPONSE_STATUS_TRYLATER XN_FLAG_SEP_COMMA_PLUS + NID_dsa_2 OCSP_RESPONSE_STATUS_UNAUTHORIZED XN_FLAG_SEP_CPLUS_SPC + NID_email_protect OPENSSL_VERSION_NUMBER XN_FLAG_SEP_MASK + NID_ext_key_usage OP_ALL XN_FLAG_SEP_MULTILINE + NID_ext_req OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION XN_FLAG_SEP_SPLUS_SPC + NID_friendlyName OP_CIPHER_SERVER_PREFERENCE XN_FLAG_SPC_EQ + NID_givenName OP_CISCO_ANYCONNECT + +/); + +my @missing; +my %h = map { $_=>1 } @Net::SSLeay::EXPORT_OK; + +for (@c) { + like(eval("&Net::SSLeay::$_; 'ok'") || $@, qr/^(ok|Your vendor has not defined SSLeay macro.*)$/, "$_"); + push(@missing, $_) unless $h{$_}; +} + +is(join(",", sort @missing), '', 'constants missing in @EXPORT_OK count='.scalar(@missing)); + diff --git a/t/local/21_constants.t b/t/local/21_constants.t new file mode 100644 index 0000000..90e58cb --- /dev/null +++ b/t/local/21_constants.t @@ -0,0 +1,216 @@ +#!/usr/bin/perl + +# DO NOT EDIT THIS FILE - update __DATA__ section of helper_script/regen_openssl_constants.pl + +use strict; +use warnings; +use Net::SSLeay; + +eval "use Test::Exception;"; +if ($@) +{ + eval "use Test::More skip_all => 'Some tests need Test::Exception';"; +} +else +{ + eval 'use Test::More tests => 553;'; +} + +my @c = (qw/ + ASN1_STRFLGS_ESC_CTRL NID_netscape R_UNKNOWN_REMOTE_ERROR_TYPE + ASN1_STRFLGS_ESC_MSB NID_netscape_base_url R_UNKNOWN_STATE + ASN1_STRFLGS_ESC_QUOTE NID_netscape_ca_policy_url R_X509_LIB + ASN1_STRFLGS_RFC2253 NID_netscape_ca_revocation_url SENT_SHUTDOWN + CB_ACCEPT_EXIT NID_netscape_cert_extension SESSION_ASN1_VERSION + CB_ACCEPT_LOOP NID_netscape_cert_sequence SESS_CACHE_BOTH + CB_ALERT NID_netscape_cert_type SESS_CACHE_CLIENT + CB_CONNECT_EXIT NID_netscape_comment SESS_CACHE_NO_AUTO_CLEAR + CB_CONNECT_LOOP NID_netscape_data_type SESS_CACHE_NO_INTERNAL + CB_EXIT NID_netscape_renewal_url SESS_CACHE_NO_INTERNAL_LOOKUP + CB_HANDSHAKE_DONE NID_netscape_revocation_url SESS_CACHE_NO_INTERNAL_STORE + CB_HANDSHAKE_START NID_netscape_ssl_server_name SESS_CACHE_OFF + CB_LOOP NID_ns_sgc SESS_CACHE_SERVER + CB_READ NID_organizationName SSL3_VERSION + CB_READ_ALERT NID_organizationalUnitName SSLEAY_BUILT_ON + CB_WRITE NID_pbeWithMD2AndDES_CBC SSLEAY_CFLAGS + CB_WRITE_ALERT NID_pbeWithMD2AndRC2_CBC SSLEAY_DIR + ERROR_NONE NID_pbeWithMD5AndCast5_CBC SSLEAY_PLATFORM + ERROR_SSL NID_pbeWithMD5AndDES_CBC SSLEAY_VERSION + ERROR_SYSCALL NID_pbeWithMD5AndRC2_CBC ST_ACCEPT + ERROR_WANT_ACCEPT NID_pbeWithSHA1AndDES_CBC ST_BEFORE + ERROR_WANT_CONNECT NID_pbeWithSHA1AndRC2_CBC ST_CONNECT + ERROR_WANT_READ NID_pbe_WithSHA1And128BitRC2_CBC ST_INIT + ERROR_WANT_WRITE NID_pbe_WithSHA1And128BitRC4 ST_OK + ERROR_WANT_X509_LOOKUP NID_pbe_WithSHA1And2_Key_TripleDES_CBC ST_READ_BODY + ERROR_ZERO_RETURN NID_pbe_WithSHA1And3_Key_TripleDES_CBC ST_READ_HEADER + EVP_PKS_DSA NID_pbe_WithSHA1And40BitRC2_CBC TLS1_1_VERSION + EVP_PKS_EC NID_pbe_WithSHA1And40BitRC4 TLS1_2_VERSION + EVP_PKS_RSA NID_pbes2 TLS1_3_VERSION + EVP_PKT_ENC NID_pbmac1 TLS1_VERSION + EVP_PKT_EXCH NID_pkcs TLSEXT_STATUSTYPE_ocsp + EVP_PKT_EXP NID_pkcs3 VERIFY_CLIENT_ONCE + EVP_PKT_SIGN NID_pkcs7 VERIFY_FAIL_IF_NO_PEER_CERT + EVP_PK_DH NID_pkcs7_data VERIFY_NONE + EVP_PK_DSA NID_pkcs7_digest VERIFY_PEER + EVP_PK_EC NID_pkcs7_encrypted VERIFY_POST_HANDSHAKE + EVP_PK_RSA NID_pkcs7_enveloped V_OCSP_CERTSTATUS_GOOD + FILETYPE_ASN1 NID_pkcs7_signed V_OCSP_CERTSTATUS_REVOKED + FILETYPE_PEM NID_pkcs7_signedAndEnveloped V_OCSP_CERTSTATUS_UNKNOWN + F_CLIENT_CERTIFICATE NID_pkcs8ShroudedKeyBag WRITING + F_CLIENT_HELLO NID_pkcs9 X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + F_CLIENT_MASTER_KEY NID_pkcs9_challengePassword X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS + F_D2I_SSL_SESSION NID_pkcs9_contentType X509_CHECK_FLAG_NEVER_CHECK_SUBJECT + F_GET_CLIENT_FINISHED NID_pkcs9_countersignature X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS + F_GET_CLIENT_HELLO NID_pkcs9_emailAddress X509_CHECK_FLAG_NO_WILDCARDS + F_GET_CLIENT_MASTER_KEY NID_pkcs9_extCertAttributes X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + F_GET_SERVER_FINISHED NID_pkcs9_messageDigest X509_FILETYPE_ASN1 + F_GET_SERVER_HELLO NID_pkcs9_signingTime X509_FILETYPE_DEFAULT + F_GET_SERVER_VERIFY NID_pkcs9_unstructuredAddress X509_FILETYPE_PEM + F_I2D_SSL_SESSION NID_pkcs9_unstructuredName X509_LOOKUP + F_READ_N NID_private_key_usage_period X509_PURPOSE_ANY + F_REQUEST_CERTIFICATE NID_rc2_40_cbc X509_PURPOSE_CRL_SIGN + F_SERVER_HELLO NID_rc2_64_cbc X509_PURPOSE_NS_SSL_SERVER + F_SSL_CERT_NEW NID_rc2_cbc X509_PURPOSE_OCSP_HELPER + F_SSL_GET_NEW_SESSION NID_rc2_cfb64 X509_PURPOSE_SMIME_ENCRYPT + F_SSL_NEW NID_rc2_ecb X509_PURPOSE_SMIME_SIGN + F_SSL_READ NID_rc2_ofb64 X509_PURPOSE_SSL_CLIENT + F_SSL_RSA_PRIVATE_DECRYPT NID_rc4 X509_PURPOSE_SSL_SERVER + F_SSL_RSA_PUBLIC_ENCRYPT NID_rc4_40 X509_PURPOSE_TIMESTAMP_SIGN + F_SSL_SESSION_NEW NID_rc5_cbc X509_TRUST_COMPAT + F_SSL_SESSION_PRINT_FP NID_rc5_cfb64 X509_TRUST_EMAIL + F_SSL_SET_FD NID_rc5_ecb X509_TRUST_OBJECT_SIGN + F_SSL_SET_RFD NID_rc5_ofb64 X509_TRUST_OCSP_REQUEST + F_SSL_SET_WFD NID_ripemd160 X509_TRUST_OCSP_SIGN + F_SSL_USE_CERTIFICATE NID_ripemd160WithRSA X509_TRUST_SSL_CLIENT + F_SSL_USE_CERTIFICATE_ASN1 NID_rle_compression X509_TRUST_SSL_SERVER + F_SSL_USE_CERTIFICATE_FILE NID_rsa X509_TRUST_TSA + F_SSL_USE_PRIVATEKEY NID_rsaEncryption X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH + F_SSL_USE_PRIVATEKEY_ASN1 NID_rsadsi X509_V_ERR_AKID_SKID_MISMATCH + F_SSL_USE_PRIVATEKEY_FILE NID_safeContentsBag X509_V_ERR_APPLICATION_VERIFICATION + F_SSL_USE_RSAPRIVATEKEY NID_sdsiCertificate X509_V_ERR_CA_KEY_TOO_SMALL + F_SSL_USE_RSAPRIVATEKEY_ASN1 NID_secretBag X509_V_ERR_CA_MD_TOO_WEAK + F_SSL_USE_RSAPRIVATEKEY_FILE NID_serialNumber X509_V_ERR_CERT_CHAIN_TOO_LONG + F_WRITE_PENDING NID_server_auth X509_V_ERR_CERT_HAS_EXPIRED + GEN_DIRNAME NID_sha X509_V_ERR_CERT_NOT_YET_VALID + GEN_DNS NID_sha1 X509_V_ERR_CERT_REJECTED + GEN_EDIPARTY NID_sha1WithRSA X509_V_ERR_CERT_REVOKED + GEN_EMAIL NID_sha1WithRSAEncryption X509_V_ERR_CERT_SIGNATURE_FAILURE + GEN_IPADD NID_shaWithRSAEncryption X509_V_ERR_CERT_UNTRUSTED + GEN_OTHERNAME NID_stateOrProvinceName X509_V_ERR_CRL_HAS_EXPIRED + GEN_RID NID_subject_alt_name X509_V_ERR_CRL_NOT_YET_VALID + GEN_URI NID_subject_key_identifier X509_V_ERR_CRL_PATH_VALIDATION_ERROR + GEN_X400 NID_surname X509_V_ERR_CRL_SIGNATURE_FAILURE + LIBRESSL_VERSION_NUMBER NID_sxnet X509_V_ERR_DANE_NO_MATCH + MBSTRING_ASC NID_time_stamp X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT + MBSTRING_BMP NID_title X509_V_ERR_DIFFERENT_CRL_SCOPE + MBSTRING_FLAG NID_undef X509_V_ERR_EE_KEY_TOO_SMALL + MBSTRING_UNIV NID_uniqueIdentifier X509_V_ERR_EMAIL_MISMATCH + MBSTRING_UTF8 NID_x509Certificate X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD + MIN_RSA_MODULUS_LENGTH_IN_BYTES NID_x509Crl X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD + MODE_ACCEPT_MOVING_WRITE_BUFFER NID_zlib_compression X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD + MODE_AUTO_RETRY NOTHING X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD + MODE_ENABLE_PARTIAL_WRITE OCSP_RESPONSE_STATUS_INTERNALERROR X509_V_ERR_EXCLUDED_VIOLATION + MODE_RELEASE_BUFFERS OCSP_RESPONSE_STATUS_MALFORMEDREQUEST X509_V_ERR_HOSTNAME_MISMATCH + NID_OCSP_sign OCSP_RESPONSE_STATUS_SIGREQUIRED X509_V_ERR_INVALID_CA + NID_SMIMECapabilities OCSP_RESPONSE_STATUS_SUCCESSFUL X509_V_ERR_INVALID_CALL + NID_X500 OCSP_RESPONSE_STATUS_TRYLATER X509_V_ERR_INVALID_EXTENSION + NID_X509 OCSP_RESPONSE_STATUS_UNAUTHORIZED X509_V_ERR_INVALID_NON_CA + NID_ad_OCSP OPENSSL_BUILT_ON X509_V_ERR_INVALID_POLICY_EXTENSION + NID_ad_ca_issuers OPENSSL_CFLAGS X509_V_ERR_INVALID_PURPOSE + NID_algorithm OPENSSL_DIR X509_V_ERR_IP_ADDRESS_MISMATCH + NID_authority_key_identifier OPENSSL_ENGINES_DIR X509_V_ERR_KEYUSAGE_NO_CERTSIGN + NID_basic_constraints OPENSSL_PLATFORM X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + NID_bf_cbc OPENSSL_VERSION X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE + NID_bf_cfb64 OPENSSL_VERSION_NUMBER X509_V_ERR_NO_EXPLICIT_POLICY + NID_bf_ecb OP_ALL X509_V_ERR_NO_VALID_SCTS + NID_bf_ofb64 OP_ALLOW_NO_DHE_KEX X509_V_ERR_OCSP_CERT_UNKNOWN + NID_cast5_cbc OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION X509_V_ERR_OCSP_VERIFY_FAILED + NID_cast5_cfb64 OP_CIPHER_SERVER_PREFERENCE X509_V_ERR_OCSP_VERIFY_NEEDED + NID_cast5_ecb OP_CISCO_ANYCONNECT X509_V_ERR_OUT_OF_MEM + NID_cast5_ofb64 OP_COOKIE_EXCHANGE X509_V_ERR_PATH_LENGTH_EXCEEDED + NID_certBag OP_CRYPTOPRO_TLSEXT_BUG X509_V_ERR_PATH_LOOP + NID_certificate_policies OP_DONT_INSERT_EMPTY_FRAGMENTS X509_V_ERR_PERMITTED_VIOLATION + NID_client_auth OP_ENABLE_MIDDLEBOX_COMPAT X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED + NID_code_sign OP_EPHEMERAL_RSA X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED + NID_commonName OP_LEGACY_SERVER_CONNECT X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION + NID_countryName OP_MICROSOFT_BIG_SSLV3_BUFFER X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN + NID_crlBag OP_MICROSOFT_SESS_ID_BUG X509_V_ERR_STORE_LOOKUP + NID_crl_distribution_points OP_MSIE_SSLV2_RSA_PADDING X509_V_ERR_SUBJECT_ISSUER_MISMATCH + NID_crl_number OP_NETSCAPE_CA_DN_BUG X509_V_ERR_SUBTREE_MINMAX + NID_crl_reason OP_NETSCAPE_CHALLENGE_BUG X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 + NID_delta_crl OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_ALGORITHM + NID_des_cbc OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG X509_V_ERR_SUITE_B_INVALID_CURVE + NID_des_cfb64 OP_NON_EXPORT_FIRST X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM + NID_des_ecb OP_NO_ANTI_REPLAY X509_V_ERR_SUITE_B_INVALID_VERSION + NID_des_ede OP_NO_CLIENT_RENEGOTIATION X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED + NID_des_ede3 OP_NO_COMPRESSION X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY + NID_des_ede3_cbc OP_NO_ENCRYPT_THEN_MAC X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE + NID_des_ede3_cfb64 OP_NO_QUERY_MTU X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE + NID_des_ede3_ofb64 OP_NO_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL + NID_des_ede_cbc OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER + NID_des_ede_cfb64 OP_NO_SSL_MASK X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT + NID_des_ede_ofb64 OP_NO_SSLv2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY + NID_des_ofb64 OP_NO_SSLv3 X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE + NID_description OP_NO_TICKET X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION + NID_desx_cbc OP_NO_TLSv1 X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION + NID_dhKeyAgreement OP_NO_TLSv1_1 X509_V_ERR_UNNESTED_RESOURCE + NID_dnQualifier OP_NO_TLSv1_2 X509_V_ERR_UNSPECIFIED + NID_dsa OP_NO_TLSv1_3 X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX + NID_dsaWithSHA OP_PKCS1_CHECK_1 X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE + NID_dsaWithSHA1 OP_PKCS1_CHECK_2 X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE + NID_dsaWithSHA1_2 OP_PRIORITIZE_CHACHA X509_V_ERR_UNSUPPORTED_NAME_SYNTAX + NID_dsa_2 OP_SAFARI_ECDHE_ECDSA_BUG X509_V_FLAG_ALLOW_PROXY_CERTS + NID_email_protect OP_SINGLE_DH_USE X509_V_FLAG_CB_ISSUER_CHECK + NID_ext_key_usage OP_SINGLE_ECDH_USE X509_V_FLAG_CHECK_SS_SIGNATURE + NID_ext_req OP_SSLEAY_080_CLIENT_DH_BUG X509_V_FLAG_CRL_CHECK + NID_friendlyName OP_SSLREF2_REUSE_CERT_TYPE_BUG X509_V_FLAG_CRL_CHECK_ALL + NID_givenName OP_TLSEXT_PADDING X509_V_FLAG_EXPLICIT_POLICY + NID_hmacWithSHA1 OP_TLS_BLOCK_PADDING_BUG X509_V_FLAG_EXTENDED_CRL_SUPPORT + NID_id_ad OP_TLS_D5_BUG X509_V_FLAG_IGNORE_CRITICAL + NID_id_ce OP_TLS_ROLLBACK_BUG X509_V_FLAG_INHIBIT_ANY + NID_id_kp READING X509_V_FLAG_INHIBIT_MAP + NID_id_pbkdf2 RECEIVED_SHUTDOWN X509_V_FLAG_NOTIFY_POLICY + NID_id_pe RSA_3 X509_V_FLAG_NO_ALT_CHAINS + NID_id_pkix RSA_F4 X509_V_FLAG_NO_CHECK_TIME + NID_id_qt_cps R_BAD_AUTHENTICATION_TYPE X509_V_FLAG_PARTIAL_CHAIN + NID_id_qt_unotice R_BAD_CHECKSUM X509_V_FLAG_POLICY_CHECK + NID_idea_cbc R_BAD_MAC_DECODE X509_V_FLAG_POLICY_MASK + NID_idea_cfb64 R_BAD_RESPONSE_ARGUMENT X509_V_FLAG_SUITEB_128_LOS + NID_idea_ecb R_BAD_SSL_FILETYPE X509_V_FLAG_SUITEB_128_LOS_ONLY + NID_idea_ofb64 R_BAD_SSL_SESSION_ID_LENGTH X509_V_FLAG_SUITEB_192_LOS + NID_info_access R_BAD_STATE X509_V_FLAG_TRUSTED_FIRST + NID_initials R_BAD_WRITE_RETRY X509_V_FLAG_USE_CHECK_TIME + NID_invalidity_date R_CHALLENGE_IS_DIFFERENT X509_V_FLAG_USE_DELTAS + NID_issuer_alt_name R_CIPHER_TABLE_SRC_ERROR X509_V_FLAG_X509_STRICT + NID_keyBag R_INVALID_CHALLENGE_LENGTH X509_V_OK + NID_key_usage R_NO_CERTIFICATE_SET XN_FLAG_COMPAT + NID_localKeyID R_NO_CERTIFICATE_SPECIFIED XN_FLAG_DN_REV + NID_localityName R_NO_CIPHER_LIST XN_FLAG_DUMP_UNKNOWN_FIELDS + NID_md2 R_NO_CIPHER_MATCH XN_FLAG_FN_ALIGN + NID_md2WithRSAEncryption R_NO_PRIVATEKEY XN_FLAG_FN_LN + NID_md5 R_NO_PUBLICKEY XN_FLAG_FN_MASK + NID_md5WithRSA R_NULL_SSL_CTX XN_FLAG_FN_NONE + NID_md5WithRSAEncryption R_PEER_DID_NOT_RETURN_A_CERTIFICATE XN_FLAG_FN_OID + NID_md5_sha1 R_PEER_ERROR XN_FLAG_FN_SN + NID_mdc2 R_PEER_ERROR_CERTIFICATE XN_FLAG_MULTILINE + NID_mdc2WithRSA R_PEER_ERROR_NO_CIPHER XN_FLAG_ONELINE + NID_ms_code_com R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE XN_FLAG_RFC2253 + NID_ms_code_ind R_PUBLIC_KEY_ENCRYPT_ERROR XN_FLAG_SEP_COMMA_PLUS + NID_ms_ctl_sign R_PUBLIC_KEY_IS_NOT_RSA XN_FLAG_SEP_CPLUS_SPC + NID_ms_efs R_READ_WRONG_PACKET_TYPE XN_FLAG_SEP_MASK + NID_ms_ext_req R_SHORT_READ XN_FLAG_SEP_MULTILINE + NID_ms_sgc R_SSL_SESSION_ID_IS_DIFFERENT XN_FLAG_SEP_SPLUS_SPC + NID_name R_UNABLE_TO_EXTRACT_PUBLIC_KEY XN_FLAG_SPC_EQ + +/); + +my @missing; +my %h = map { $_=>1 } @Net::SSLeay::EXPORT_OK; + +for (@c) { + like(eval("&Net::SSLeay::$_; 'ok'") || $@, qr/^(ok|Your vendor has not defined SSLeay macro.*)$/, "$_"); + push(@missing, $_) unless $h{$_}; +} + +is(join(",", sort @missing), '', 'constants missing in @EXPORT_OK count='.scalar(@missing)); + diff --git a/t/local/30_error.t b/t/local/30_error.t new file mode 100644 index 0000000..cc74cd0 --- /dev/null +++ b/t/local/30_error.t @@ -0,0 +1,75 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; + +eval "use Test::Exception; use Test::Warn; use Test::NoWarnings; 1;"; +plan skip_all => 'Requires Test::Exception, Test::Warn and Test::NoWarnings' if $@; +plan tests => 11; + +use Net::SSLeay; +Net::SSLeay::load_error_strings(); + +# Note, die_now usually just prints the process id and the argument string eg: +# 57611: test +# but on some systems, perhaps if diagnostics are enabled, it might [roduce something like: +# found: Uncaught exception from user code: +# 57611: test +# therefore the qr match strings below have been chnaged so they dont have tooccur at the +# beginning of the line. +{ + throws_ok(sub { + Net::SSLeay::die_now('test') + }, qr/$$: test\n$/, 'die_now dies without errors'); + + lives_ok(sub { + Net::SSLeay::die_if_ssl_error('test'); + }, 'die_if_ssl_error lives without errors'); + + put_err(); + throws_ok(sub { + Net::SSLeay::die_now('test'); + }, qr/$$: test\n$/, 'die_now dies with errors'); + + put_err(); + throws_ok(sub { + Net::SSLeay::die_if_ssl_error('test'); + }, qr/$$: test\n$/, 'die_if_ssl_error dies with errors'); +} + +{ + local $Net::SSLeay::trace = 1; + + throws_ok(sub { + Net::SSLeay::die_now('foo'); + }, qr/$$: foo\n$/, 'die_now dies without arrors and with trace'); + + lives_ok(sub { + Net::SSLeay::die_if_ssl_error('foo'); + }, 'die_if_ssl_error lives without errors and with trace'); + + put_err(); + warning_like(sub { + throws_ok(sub { + Net::SSLeay::die_now('foo'); + }, qr/^$$: foo\n$/, 'die_now dies with errors and trace'); + }, qr/foo $$: 1 - error:2006d080/i, 'die_now raises warnings about the occurred error when tracing'); + + put_err(); + warning_like(sub { + throws_ok(sub { + Net::SSLeay::die_if_ssl_error('foo'); + }, qr/^$$: foo\n$/, 'die_if_ssl_error dies with errors and trace'); + }, qr/foo $$: 1 - error:2006d080/i, 'die_if_ssl_error raises warnings about the occurred error when tracing'); +} + +sub put_err { + Net::SSLeay::ERR_put_error( + 32, #lib + 109, #func + 128, #reason + 1, #file + 1, #line + ); +} diff --git a/t/local/31_rsa_generate_key.t b/t/local/31_rsa_generate_key.t new file mode 100644 index 0000000..c0f3619 --- /dev/null +++ b/t/local/31_rsa_generate_key.t @@ -0,0 +1,73 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; + +eval 'use Test::Exception'; +plan skip_all => 'Test::Exception required' if $@; + +plan tests => 14; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +lives_ok(sub { + Net::SSLeay::RSA_generate_key(2048, 0x10001); +}, 'RSA_generate_key with valid callback'); + +dies_ok(sub { + Net::SSLeay::RSA_generate_key(2048, 0x10001, 1); +}, 'RSA_generate_key with invalid callback'); + +{ + my $called = 0; + + lives_ok(sub { + Net::SSLeay::RSA_generate_key(2048, 0x10001, \&cb); + }, 'RSA_generate_key with valid callback'); + + cmp_ok( $called, '>', 0, 'callback has been called' ); + + sub cb { + my ($i, $n, $d) = @_; + + if ($called == 0) { + is( wantarray(), undef, 'RSA_generate_key callback is executed in void context' ); + is( $d, undef, 'userdata will be undef if no userdata was given' ); + + ok( defined $i, 'first argument is defined' ); + ok( defined $n, 'second argument is defined' ); + } + + $called++; + } +} + +{ + my $called = 0; + my $userdata = 'foo'; + + lives_ok(sub { + Net::SSLeay::RSA_generate_key(2048, 0x10001, \&cb_data, $userdata); + }, 'RSA_generate_key with valid callback and userdata'); + + cmp_ok( $called, '>', 0, 'callback has been called' ); + + sub cb_data { + my ($i, $n, $d) = @_; + + if ($called == 0) { + is( wantarray(), undef, 'RSA_generate_key callback is executed in void context' ); + + ok( defined $i, 'first argument is defined' ); + ok( defined $n, 'second argument is defined' ); + is( $d, $userdata, 'third argument is the userdata we passed in' ); + } + + $called++; + } +} diff --git a/t/local/32_x509_get_cert_info.t b/t/local/32_x509_get_cert_info.t new file mode 100644 index 0000000..b8b3dd6 --- /dev/null +++ b/t/local/32_x509_get_cert_info.t @@ -0,0 +1,248 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 1016; +use Net::SSLeay; +use File::Spec; +use lib '.'; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +# Check some basic X509 features added in 1.54: +my $name = Net::SSLeay::X509_NAME_new(); +ok ($name, "X509_NAME_new"); +my $hash = Net::SSLeay::X509_NAME_hash($name); +ok ($hash = 4003674586, "X509_NAME_hash"); + +# NOTE: *.pem_dump files are generated by helper script e.g.: +# perl examples/X509_cert_details.pl -dump -pem t/data/cert_paypal.crt.pem > t/data/cert_paypal.crt.pem_dump +# +# Caution from perl 25 onwards, need use lib '.'; above in order to 'do' these files +my $dump = { + "cert_paypal.crt.pem" => do(File::Spec->catfile('t', 'data', 'cert_paypal.crt.pem_dump')), + "testcert_extended.crt.pem" => do(File::Spec->catfile('t', 'data', 'testcert_extended.crt.pem_dump')), + "testcert_simple.crt.pem" => do(File::Spec->catfile('t', 'data', 'testcert_simple.crt.pem_dump')), + "testcert_strange.crt.pem" => do(File::Spec->catfile('t', 'data', 'testcert_strange.crt.pem_dump')), + "testcert_cdp.crt.pem" => do(File::Spec->catfile('t', 'data', 'testcert_cdp.crt.pem_dump')), +}; + +my %available_digests = map {$_=>1} qw( md5 sha1 ); +if (Net::SSLeay::SSLeay >= 0x1000000f) { + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + %available_digests = map { $_=>1 } grep { + # P_EVP_MD_list_all() does not remove digests disabled in FIPS + my $md; + $md = Net::SSLeay::EVP_get_digestbyname($_) and + Net::SSLeay::EVP_DigestInit($ctx, $md) + } @{Net::SSLeay::P_EVP_MD_list_all()}; +} + +for my $f (keys (%$dump)) { + my $filename = File::Spec->catfile('t', 'data', $f); + ok(my $bio = Net::SSLeay::BIO_new_file($filename, 'rb'), "BIO_new_file\t$f"); + ok(my $x509 = Net::SSLeay::PEM_read_bio_X509($bio), "PEM_read_bio_X509\t$f"); + ok(Net::SSLeay::X509_get_pubkey($x509), "X509_get_pubkey\t$f"); #only test whether the function works + + ok(my $subj_name = Net::SSLeay::X509_get_subject_name($x509), "X509_get_subject_name\t$f"); + is(my $subj_count = Net::SSLeay::X509_NAME_entry_count($subj_name), $dump->{$f}->{subject}->{count}, "X509_NAME_entry_count\t$f"); + + #BEWARE: values are not the same across different openssl versions therefore cannot test exact match + #is(Net::SSLeay::X509_NAME_oneline($subj_name), $dump->{$f}->{subject}->{oneline}, "X509_NAME_oneline\t$f"); + #is(Net::SSLeay::X509_NAME_print_ex($subj_name), $dump->{$f}->{subject}->{print_rfc2253}, "X509_NAME_print_ex\t$f"); + like(Net::SSLeay::X509_NAME_oneline($subj_name), qr|/OU=.*?/CN=|, "X509_NAME_oneline\t$f"); + like(Net::SSLeay::X509_NAME_print_ex($subj_name), qr|CN=.*?,OU=|, "X509_NAME_print_ex\t$f"); + + for my $i (0..$subj_count-1) { + ok(my $entry = Net::SSLeay::X509_NAME_get_entry($subj_name, $i), "X509_NAME_get_entry\t$f:$i"); + ok(my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry), "X509_NAME_ENTRY_get_data\t$f:$i"); + ok(my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry), "X509_NAME_ENTRY_get_object\t$f:$i"); + is(Net::SSLeay::OBJ_obj2txt($asn1_object,1), $dump->{$f}->{subject}->{entries}->[$i]->{oid}, "OBJ_obj2txt\t$f:$i"); + is(Net::SSLeay::P_ASN1_STRING_get($asn1_string), $dump->{$f}->{subject}->{entries}->[$i]->{data}, "P_ASN1_STRING_get.1\t$f:$i"); + is(Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1), $dump->{$f}->{subject}->{entries}->[$i]->{data_utf8_decoded}, "P_ASN1_STRING_get.2\t$f:$i"); + if (defined $dump->{$f}->{entries}->[$i]->{nid}) { + is(my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object), $dump->{$f}->{subject}->{entries}->[$i]->{nid}, "OBJ_obj2nid\t$f:$i"); + is(Net::SSLeay::OBJ_nid2ln($nid), $dump->{$f}->{subject}->{entries}->[$i]->{ln}, "OBJ_nid2ln\t$f:$i"); + is(Net::SSLeay::OBJ_nid2sn($nid), $dump->{$f}->{subject}->{entries}->[$i]->{sn}, "OBJ_nid2sn\t$f:$i"); + } + } + + ok(my $issuer_name = Net::SSLeay::X509_get_issuer_name($x509), "X509_get_subject_name\t$f"); + is(my $issuer_count = Net::SSLeay::X509_NAME_entry_count($issuer_name), $dump->{$f}->{issuer}->{count}, "X509_NAME_entry_count\t$f"); + is(Net::SSLeay::X509_NAME_oneline($issuer_name), $dump->{$f}->{issuer}->{oneline}, "X509_NAME_oneline\t$f"); + is(Net::SSLeay::X509_NAME_print_ex($issuer_name), $dump->{$f}->{issuer}->{print_rfc2253}, "X509_NAME_print_ex\t$f"); + + for my $i (0..$issuer_count-1) { + ok(my $entry = Net::SSLeay::X509_NAME_get_entry($issuer_name, $i), "X509_NAME_get_entry\t$f:$i"); + ok(my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry), "X509_NAME_ENTRY_get_data\t$f:$i"); + ok(my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry), "X509_NAME_ENTRY_get_object\t$f:$i"); + is(Net::SSLeay::OBJ_obj2txt($asn1_object,1), $dump->{$f}->{issuer}->{entries}->[$i]->{oid}, "OBJ_obj2txt\t$f:$i"); + is(Net::SSLeay::P_ASN1_STRING_get($asn1_string), $dump->{$f}->{issuer}->{entries}->[$i]->{data}, "P_ASN1_STRING_get.1\t$f:$i"); + is(Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1), $dump->{$f}->{issuer}->{entries}->[$i]->{data_utf8_decoded}, "P_ASN1_STRING_get.2\t$f:$i"); + if (defined $dump->{$f}->{entries}->[$i]->{nid}) { + is(my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object), $dump->{$f}->{issuer}->{entries}->[$i]->{nid}, "OBJ_obj2nid\t$f:$i"); + is(Net::SSLeay::OBJ_nid2ln($nid), $dump->{$f}->{issuer}->{entries}->[$i]->{ln}, "OBJ_nid2ln\t$f:$i"); + is(Net::SSLeay::OBJ_nid2sn($nid), $dump->{$f}->{issuer}->{entries}->[$i]->{sn}, "OBJ_nid2sn\t$f:$i"); + } + } + + my @subjectaltnames = Net::SSLeay::X509_get_subjectAltNames($x509); + is(scalar(@subjectaltnames), scalar(@{$dump->{$f}->{subject}->{altnames}}), "subjectaltnames size\t$f"); + for my $i (0..$#subjectaltnames) { + SKIP: { + skip('altname types are different on pre-0.9.7', 1) unless Net::SSLeay::SSLeay >= 0x0090700f || ($i%2)==1; + is($subjectaltnames[$i], $dump->{$f}->{subject}->{altnames}->[$i], "subjectaltnames match\t$f:$i"); + } + } + + #BEWARE: values are not the same across different openssl versions or FIPS mode, therefore testing just >0 + #is(Net::SSLeay::X509_subject_name_hash($x509), $dump->{$f}->{hash}->{subject}->{dec}, 'X509_subject_name_hash dec'); + #is(Net::SSLeay::X509_issuer_name_hash($x509), $dump->{$f}->{hash}->{issuer}->{dec}, 'X509_issuer_name_hash dec'); + #is(Net::SSLeay::X509_issuer_and_serial_hash($x509), $dump->{$f}->{hash}->{issuer_and_serial}->{dec}, "X509_issuer_and_serial_hash dec\t$f"); + cmp_ok(Net::SSLeay::X509_subject_name_hash($x509), '>', 0, "X509_subject_name_hash dec\t$f"); + cmp_ok(Net::SSLeay::X509_issuer_name_hash($x509), '>', 0, "X509_issuer_name_hash dec\t$f"); + cmp_ok(Net::SSLeay::X509_issuer_and_serial_hash($x509), '>', 0, "X509_issuer_and_serial_hash dec\t$f"); + + for my $digest (qw( md5 sha1 )) { + is(Net::SSLeay::X509_get_fingerprint($x509, $digest), + (exists $available_digests{$digest} ? + $dump->{$f}->{fingerprint}->{$digest} : + undef), + "X509_get_fingerprint $digest\t$f"); + } + + my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"); + SKIP: { + skip('requires openssl-0.9.7', 1) unless Net::SSLeay::SSLeay >= 0x0090700f; + is(Net::SSLeay::X509_pubkey_digest($x509, $sha1_digest), $dump->{$f}->{digest_sha1}->{pubkey}, "X509_pubkey_digest\t$f"); + } + is(Net::SSLeay::X509_digest($x509, $sha1_digest), $dump->{$f}->{digest_sha1}->{x509}, "X509_digest\t$f"); + + + SKIP: { + skip('P_ASN1_TIME_get_isotime requires 0.9.7e+', 2) unless Net::SSLeay::SSLeay >= 0x0090705f; + is(Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($x509)), $dump->{$f}->{not_before}, "X509_get_notBefore\t$f"); + is(Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509)), $dump->{$f}->{not_after}, "X509_get_notAfter\t$f"); + } + + ok(my $ai = Net::SSLeay::X509_get_serialNumber($x509), "X509_get_serialNumber\t$f"); + + is(Net::SSLeay::P_ASN1_INTEGER_get_hex($ai), $dump->{$f}->{serial}->{hex}, "serial P_ASN1_INTEGER_get_hex\t$f"); + is(Net::SSLeay::P_ASN1_INTEGER_get_dec($ai), $dump->{$f}->{serial}->{dec}, "serial P_ASN1_INTEGER_get_dec\t$f"); + + SKIP: { + # X509_get0_serialNumber should function the same as X509_get_serialNumber + skip('X509_get0_serialNumber requires OpenSSL 1.1.0+ or LibreSSL 2.8.1+', 3) unless defined (&Net::SSLeay::X509_get0_serialNumber); + ok(my $ai = Net::SSLeay::X509_get0_serialNumber($x509), "X509_get0_serialNumber\t$f"); + + is(Net::SSLeay::P_ASN1_INTEGER_get_hex($ai), $dump->{$f}->{serial}->{hex}, "serial P_ASN1_INTEGER_get_hex\t$f"); + is(Net::SSLeay::P_ASN1_INTEGER_get_dec($ai), $dump->{$f}->{serial}->{dec}, "serial P_ASN1_INTEGER_get_dec\t$f"); + } + + # On platforms with 64-bit long int returns 4294967295 rather than -1 + # Caution, there is much difference between 32 and 64 bit behaviours with + # Net::SSLeay::ASN1_INTEGER_get. + # This test is deleted +# my $asn1_integer = Net::SSLeay::ASN1_INTEGER_get($ai); +# if ($asn1_integer == 4294967295) { +# $asn1_integer = -1; +# } +# is($asn1_integer, $dump->{$f}->{serial}->{long}, "serial ASN1_INTEGER_get\t$f"); + + is(Net::SSLeay::X509_get_version($x509), $dump->{$f}->{version}, "X509_get_version\t$f"); + + is(my $ext_count = Net::SSLeay::X509_get_ext_count($x509), $dump->{$f}->{extensions}->{count}, "X509_get_ext_count\t$f"); + for my $i (0..$ext_count-1) { + ok(my $ext = Net::SSLeay::X509_get_ext($x509,$i), "X509_get_ext\t$f:$i"); + ok(my $asn1_string = Net::SSLeay::X509_EXTENSION_get_data($ext), "X509_EXTENSION_get_data\t$f:$i"); + ok(my $asn1_object = Net::SSLeay::X509_EXTENSION_get_object($ext), "X509_EXTENSION_get_object\t$f:$i"); + SKIP: { + skip('X509_EXTENSION_get_critical works differently on pre-0.9.7', 1) unless Net::SSLeay::SSLeay >= 0x0090700f; + is(Net::SSLeay::X509_EXTENSION_get_critical($ext), $dump->{$f}->{extensions}->{entries}->[$i]->{critical}, "X509_EXTENSION_get_critical\t$f:$i"); + } + is(Net::SSLeay::OBJ_obj2txt($asn1_object,1), $dump->{$f}->{extensions}->{entries}->[$i]->{oid}, "OBJ_obj2txt\t$f:$i"); + + if (defined $dump->{$f}->{extensions}->{entries}->[$i]->{nid}) { + is(my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object), $dump->{$f}->{extensions}->{entries}->[$i]->{nid}, "OBJ_obj2nid\t$f:$i"); + is(Net::SSLeay::OBJ_nid2ln($nid), $dump->{$f}->{extensions}->{entries}->[$i]->{ln}, "OBJ_nid2ln nid=$nid\t$f:$i"); + is(Net::SSLeay::OBJ_nid2sn($nid), $dump->{$f}->{extensions}->{entries}->[$i]->{sn}, "OBJ_nid2sn nid=$nid\t$f:$i"); + #BEARE: handling some special cases - mostly things that varies with different openssl versions + SKIP: { + if ($nid==103) { + skip('X509V3_EXT_print output on CRL distribution points differs across openssl versions', 1); + } + elsif ($nid==85 && $f eq 'testcert_extended.crt.pem' && Net::SSLeay::SSLeay < 0x0090800f) { + skip('0.9.7 does not print correctly IPv6 addresses', 1); + } + else { + is(Net::SSLeay::X509V3_EXT_print($ext), $dump->{$f}->{extensions}->{entries}->[$i]->{data}, "X509V3_EXT_print nid=$nid\t$f:$i"); + } + } + } + } + + SKIP: { + skip('crl_distribution_points requires 0.9.7+', int(@{$dump->{$f}->{cdp}})+1) unless Net::SSLeay::SSLeay >= 0x0090700f; + my @cdp = Net::SSLeay::P_X509_get_crl_distribution_points($x509); + is(scalar(@cdp), scalar(@{$dump->{$f}->{cdp}}), "cdp size\t$f"); + for my $i (0..$#cdp) { + is($cdp[$i], $dump->{$f}->{cdp}->[$i], "cdp match\t$f:$i"); + } + } + + my @keyusage = Net::SSLeay::P_X509_get_key_usage($x509); + my @ns_cert_type = Net::SSLeay::P_X509_get_netscape_cert_type($x509); + is(scalar(@keyusage), scalar(@{$dump->{$f}->{keyusage}}), "keyusage size\t$f"); + is(scalar(@ns_cert_type), scalar(@{$dump->{$f}->{ns_cert_type}}), "ns_cert_type size\t$f"); + for my $i (0..$#keyusage) { + is($keyusage[$i], $dump->{$f}->{keyusage}->[$i], "keyusage match\t$f:$i"); + } + for my $i (0..$#ns_cert_type) { + is($ns_cert_type[$i], $dump->{$f}->{ns_cert_type}->[$i], "ns_cert_type match\t$f:$i"); + } + + SKIP: { + my $test_count = 4 + scalar(@{$dump->{$f}->{extkeyusage}->{oid}}) + + scalar(@{$dump->{$f}->{extkeyusage}->{nid}}) + + scalar(@{$dump->{$f}->{extkeyusage}->{sn}}) + + scalar(@{$dump->{$f}->{extkeyusage}->{ln}}); + + skip('extended key usage requires 0.9.7+', $test_count) unless Net::SSLeay::SSLeay >= 0x0090700f; + my @extkeyusage_oid = Net::SSLeay::P_X509_get_ext_key_usage($x509,0); + my @extkeyusage_nid = Net::SSLeay::P_X509_get_ext_key_usage($x509,1); + my @extkeyusage_sn = Net::SSLeay::P_X509_get_ext_key_usage($x509,2); + my @extkeyusage_ln = Net::SSLeay::P_X509_get_ext_key_usage($x509,3); + + is(scalar(@extkeyusage_oid), scalar(@{$dump->{$f}->{extkeyusage}->{oid}}), "extku_oid size\t$f"); + is(scalar(@extkeyusage_nid), scalar(@{$dump->{$f}->{extkeyusage}->{nid}}), "extku_nid size\t$f"); + is(scalar(@extkeyusage_sn), scalar(@{$dump->{$f}->{extkeyusage}->{sn}}), "extku_sn size\t$f"); + is(scalar(@extkeyusage_ln), scalar(@{$dump->{$f}->{extkeyusage}->{ln}}), "extku_ln size\t$f"); + + for my $i (0..$#extkeyusage_oid) { + is($extkeyusage_oid[$i], $dump->{$f}->{extkeyusage}->{oid}->[$i], "extkeyusage_oid match\t$f:$i"); + } + for my $i (0..$#extkeyusage_nid) { + is($extkeyusage_nid[$i], $dump->{$f}->{extkeyusage}->{nid}->[$i], "extkeyusage_nid match\t$f:$i"); + } + for my $i (0..$#extkeyusage_sn) { + is($extkeyusage_sn[$i], $dump->{$f}->{extkeyusage}->{sn}->[$i], "extkeyusage_sn match\t$f:$i"); + } + for my $i (0..$#extkeyusage_ln) { + is($extkeyusage_ln[$i], $dump->{$f}->{extkeyusage}->{ln}->[$i], "extkeyusage_ln match\t$f:$i"); + } + } + + ok(my $pubkey = Net::SSLeay::X509_get_pubkey($x509), "X509_get_pubkey"); + is(Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_signature_alg($x509)), $dump->{$f}->{signature_alg}, "P_X509_get_signature_alg"); + is(Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_pubkey_alg($x509)), $dump->{$f}->{pubkey_alg}, "P_X509_get_pubkey_alg"); + is(Net::SSLeay::EVP_PKEY_size($pubkey), $dump->{$f}->{pubkey_size}, "EVP_PKEY_size"); + is(Net::SSLeay::EVP_PKEY_bits($pubkey), $dump->{$f}->{pubkey_bits}, "EVP_PKEY_bits"); + SKIP: { + skip('EVP_PKEY_id requires 1.0.0+', 1) unless Net::SSLeay::SSLeay >= 0x1000000f; + is(Net::SSLeay::EVP_PKEY_id($pubkey), $dump->{$f}->{pubkey_id}, "EVP_PKEY_id"); + } + +} diff --git a/t/local/33_x509_create_cert.t b/t/local/33_x509_create_cert.t new file mode 100755 index 0000000..437524e --- /dev/null +++ b/t/local/33_x509_create_cert.t @@ -0,0 +1,304 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 123; +use Net::SSLeay qw/MBSTRING_ASC MBSTRING_UTF8 EVP_PK_RSA EVP_PKT_SIGN EVP_PKT_ENC/; +use File::Spec; +use utf8; + +#use File::Slurp; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $ca_crt_pem = File::Spec->catfile('t', 'data', 'test_CA1.crt.pem'); +my $ca_key_pem = File::Spec->catfile('t', 'data', 'test_CA1.key.pem'); + +ok(my $bio1 = Net::SSLeay::BIO_new_file($ca_crt_pem, 'r'), "BIO_new_file 1"); +ok(my $ca_cert = Net::SSLeay::PEM_read_bio_X509($bio1), "PEM_read_bio_X509"); +ok(my $bio2 = Net::SSLeay::BIO_new_file($ca_key_pem, 'r'), "BIO_new_file 2"); +ok(my $ca_pk = Net::SSLeay::PEM_read_bio_PrivateKey($bio2), "PEM_read_bio_PrivateKey"); +is(Net::SSLeay::X509_verify($ca_cert, $ca_pk), 1, "X509_verify"); + +ok(my $ca_subject = Net::SSLeay::X509_get_subject_name($ca_cert), "X509_get_subject_name"); +ok(my $ca_issuer = Net::SSLeay::X509_get_issuer_name($ca_cert), "X509_get_issuer_name"); +is(Net::SSLeay::X509_NAME_cmp($ca_issuer, $ca_subject), 0, "X509_NAME_cmp"); + +{ ### X509 certificate - create directly, sign with $ca_pk + ok(my $pk = Net::SSLeay::EVP_PKEY_new(), "EVP_PKEY_new"); + ok(my $rsa = Net::SSLeay::RSA_generate_key(2048, &Net::SSLeay::RSA_F4), "RSA_generate_key"); + ok(Net::SSLeay::EVP_PKEY_assign_RSA($pk,$rsa), "EVP_PKEY_assign_RSA"); + + SKIP: + { + skip 'openssl<1.1.0 required', 1 unless Net::SSLeay::SSLeay < 0x10100000 + or Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER"); + my @params = Net::SSLeay::RSA_get_key_parameters($rsa); + ok(@params == 8, "RSA_get_key_parameters"); + } + + ok(my $x509 = Net::SSLeay::X509_new(), "X509_new"); + ok(Net::SSLeay::X509_set_pubkey($x509,$pk), "X509_set_pubkey"); + ok(my $name = Net::SSLeay::X509_get_subject_name($x509), "X509_get_subject_name"); + + ok(Net::SSLeay::X509_NAME_add_entry_by_NID($name, &Net::SSLeay::NID_commonName, MBSTRING_UTF8, "Common name text X509"), "X509_NAME_add_entry_by_NID"); + #set countryName via add_entry_by_OBJ + ok(my $obj = Net::SSLeay::OBJ_nid2obj(&Net::SSLeay::NID_countryName), "OBJ_nid2obj"); + ok(Net::SSLeay::X509_NAME_add_entry_by_OBJ($name, $obj, MBSTRING_UTF8, "UK"), "X509_NAME_add_entry_by_OBJ"); + #set organizationName via add_entry_by_txt + ok(Net::SSLeay::X509_NAME_add_entry_by_txt($name, "organizationName", MBSTRING_UTF8, "Company Name"), "X509_NAME_add_entry_by_txt"); + + ok(Net::SSLeay::X509_set_version($x509, 3), "X509_set_version"); + ok(my $sn = Net::SSLeay::X509_get_serialNumber($x509), "X509_get_serialNumber"); + + my $pubkey = Net::SSLeay::X509_get_X509_PUBKEY($x509); + ok($pubkey ne '', "X509_get_X509_PUBKEY"); + + ##let us do some ASN1_INTEGER related testing + #test big integer via P_ASN1_INTEGER_set_dec + Net::SSLeay::P_ASN1_INTEGER_set_dec($sn, '123456789123456789123456789123456789123456789'); + # On platforms with 64-bit long int returns 4294967295 rather than -1 + my $asn1_integer = Net::SSLeay::ASN1_INTEGER_get(Net::SSLeay::X509_get_serialNumber($x509)); + if ($asn1_integer == 4294967295) { + $asn1_integer = -1; + } + is($asn1_integer, -1, "ASN1_INTEGER_get"); + is(Net::SSLeay::P_ASN1_INTEGER_get_hex(Net::SSLeay::X509_get_serialNumber($x509)), '058936E53D139AFEFABB2683F150B684045F15', "P_ASN1_INTEGER_get_hex"); + #test short integer via P_ASN1_INTEGER_set_hex + Net::SSLeay::P_ASN1_INTEGER_set_hex($sn, 'D05F14'); + is(Net::SSLeay::ASN1_INTEGER_get(Net::SSLeay::X509_get_serialNumber($x509)), 13655828, "ASN1_INTEGER_get"); + is(Net::SSLeay::P_ASN1_INTEGER_get_dec(Net::SSLeay::X509_get_serialNumber($x509)), '13655828', "P_ASN1_INTEGER_get_dec"); + #test short integer via ASN1_INTEGER_set + Net::SSLeay::ASN1_INTEGER_set($sn, 123456); + is(Net::SSLeay::P_ASN1_INTEGER_get_hex(Net::SSLeay::X509_get_serialNumber($x509)), '01E240', "P_ASN1_INTEGER_get_hex"); + + Net::SSLeay::X509_set_issuer_name($x509, Net::SSLeay::X509_get_subject_name($ca_cert)); + SKIP: { + skip 'openssl-0.9.7e required', 2 unless Net::SSLeay::SSLeay >= 0x0090705f; + ok(Net::SSLeay::P_ASN1_TIME_set_isotime(Net::SSLeay::X509_get_notBefore($x509), "2010-02-01T00:00:00Z"), "P_ASN1_TIME_set_isotime+X509_get_notBefore"); + ok(Net::SSLeay::P_ASN1_TIME_set_isotime(Net::SSLeay::X509_get_notAfter($x509), "2099-02-01T00:00:00Z"), "P_ASN1_TIME_set_isotime+X509_get_notAfter"); + } + + ok(Net::SSLeay::P_X509_add_extensions($x509,$ca_cert, + &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', + &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', + &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', + &Net::SSLeay::NID_netscape_cert_type => 'server', + &Net::SSLeay::NID_subject_alt_name => 'DNS:s1.dom.com,DNS:s2.dom.com,DNS:s3.dom.com', + &Net::SSLeay::NID_crl_distribution_points => 'URI:http://pki.dom.com/crl1.pem,URI:http://pki.dom.com/crl2.pem', + ), "P_X509_add_extensions"); + + ok(my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"), "EVP_get_digestbyname"); + ok(Net::SSLeay::X509_sign($x509, $ca_pk, $sha1_digest), "X509_sign"); + + is(Net::SSLeay::X509_get_version($x509), 3, "X509_get_version"); + is(Net::SSLeay::X509_verify($x509, Net::SSLeay::X509_get_pubkey($ca_cert)), 1, "X509_verify"); + + like(my $crt_pem = Net::SSLeay::PEM_get_string_X509($x509), qr/-----BEGIN CERTIFICATE-----/, "PEM_get_string_X509"); + + like(my $key_pem1 = Net::SSLeay::PEM_get_string_PrivateKey($pk), qr/-----BEGIN (RSA )?PRIVATE KEY-----/, "PEM_get_string_PrivateKey+nopasswd"); + like(my $key_pem2 = Net::SSLeay::PEM_get_string_PrivateKey($pk,"password"), qr/-----BEGIN (ENCRYPTED|RSA) PRIVATE KEY-----/, "PEM_get_string_PrivateKey+passwd"); + + Net::SSLeay::OpenSSL_add_all_algorithms(); + if (Net::SSLeay::SSLeay >= 0x0090700f) { + #just test whether we can call the following functions + Net::SSLeay::OPENSSL_add_all_algorithms_conf(); + Net::SSLeay::OPENSSL_add_all_algorithms_noconf(); + } + ok(my $alg1 = Net::SSLeay::EVP_get_cipherbyname("DES-EDE3-CBC"), "EVP_get_cipherbyname"); + like(my $key_pem3 = Net::SSLeay::PEM_get_string_PrivateKey($pk,"password",$alg1), qr/-----BEGIN (ENCRYPTED|RSA) PRIVATE KEY-----/, "PEM_get_string_PrivateKey+passwd+enc_alg"); + +# DES-EDE3-OFB has no ASN1 support, detected by changes to do_pk8pkey as of openssl 1.0.1n +# https://git.openssl.org/?p=openssl.git;a=commit;h=4d9dc0c269be87b92da188df1fbd8bfee4700eb3 +# this test now fails +# ok(my $alg2 = Net::SSLeay::EVP_get_cipherbyname("DES-EDE3-OFB"), "EVP_get_cipherbyname"); +# like(my $key_pem4 = Net::SSLeay::PEM_get_string_PrivateKey($pk,"password",$alg2), qr/-----BEGIN (ENCRYPTED|RSA) PRIVATE KEY-----/, "PEM_get_string_PrivateKey+passwd+enc_alg"); + + is(Net::SSLeay::X509_NAME_print_ex($name), "O=Company Name,C=UK,CN=Common name text X509", "X509_NAME_print_ex"); + + # 2014-06-06: Sigh, some versions of openssl have this patch, which afffects the results of this test: + # https://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=3009244da47b989c4cc59ba02cf81a4e9d8f8431 + # with this patch, the result is "ce83889f1beab8e70aa142e07e94b0ebbd9d59e0" +# is(unpack("H*",Net::SSLeay::X509_NAME_digest($name, $sha1_digest)), "044d7ea7fddced7b9b63799600b9989a63b36819", "X509_NAME_digest"); + + ok(my $ext_idx = Net::SSLeay::X509_get_ext_by_NID($x509, &Net::SSLeay::NID_ext_key_usage), "X509_get_ext_by_NID"); + ok(my $ext = Net::SSLeay::X509_get_ext($x509, $ext_idx), "X509_get_ext"); + is(Net::SSLeay::X509V3_EXT_print($ext), 'TLS Web Server Authentication, TLS Web Client Authentication', "X509V3_EXT_print"); + + #write_file("tmp_cert1.crt.pem", $crt_pem); + #write_file("tmp_cert1.key1.pem", $key_pem1); + #write_file("tmp_cert1.key2.pem", $key_pem2); + #write_file("tmp_cert1.key3.pem", $key_pem3); + #write_file("tmp_cert1.key4.pem", $key_pem4); +} + +{ ### X509_REQ certificate request >> sign >> X509 certificate + + ## PHASE1 - create certificate request + ok(my $pk = Net::SSLeay::EVP_PKEY_new(), "EVP_PKEY_new"); + ok(my $rsa = Net::SSLeay::RSA_generate_key(2048, &Net::SSLeay::RSA_F4), "RSA_generate_key"); + ok(Net::SSLeay::EVP_PKEY_assign_RSA($pk,$rsa), "EVP_PKEY_assign_RSA"); + + ok(my $req = Net::SSLeay::X509_REQ_new(), "X509_REQ_new"); + ok(Net::SSLeay::X509_REQ_set_pubkey($req,$pk), "X509_REQ_set_pubkey"); + ok(my $name = Net::SSLeay::X509_REQ_get_subject_name($req), "X509_REQ_get_subject_name"); + ok(Net::SSLeay::X509_NAME_add_entry_by_txt($name, "commonName", MBSTRING_UTF8, "Common name text X509_REQ"), "X509_NAME_add_entry_by_txt"); + ok(Net::SSLeay::X509_NAME_add_entry_by_txt($name, "countryName", MBSTRING_UTF8, "UK"), "X509_NAME_add_entry_by_txt"); + ok(Net::SSLeay::X509_NAME_add_entry_by_txt($name, "organizationName", MBSTRING_UTF8, "Company Name"), "X509_NAME_add_entry_by_txt"); + + ok(Net::SSLeay::P_X509_REQ_add_extensions($req, + &Net::SSLeay::NID_key_usage => 'digitalSignature,keyEncipherment', + &Net::SSLeay::NID_basic_constraints => 'CA:FALSE', + &Net::SSLeay::NID_ext_key_usage => 'serverAuth,clientAuth', + &Net::SSLeay::NID_netscape_cert_type => 'server', + &Net::SSLeay::NID_subject_alt_name => 'DNS:s1.com,DNS:s2.com', + &Net::SSLeay::NID_crl_distribution_points => 'URI:http://pki.com/crl1,URI:http://pki.com/crl2', + ), "P_X509_REQ_add_extensions"); + + #54 = NID_pkcs9_challengePassword - XXX-TODO add new constant + ok(Net::SSLeay::X509_REQ_add1_attr_by_NID($req, 54, MBSTRING_ASC, 'password xyz'), "X509_REQ_add1_attr_by_NID"); + #49 = NID_pkcs9_unstructuredName - XXX-TODO add new constant + ok(Net::SSLeay::X509_REQ_add1_attr_by_NID($req, 49, MBSTRING_ASC, 'Any Uns.name'), "X509_REQ_add1_attr_by_NID"); + + ok(Net::SSLeay::X509_REQ_set_version($req, 2), "X509_REQ_set_version"); + + ok(my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"), "EVP_get_digestbyname"); + ok(Net::SSLeay::X509_REQ_sign($req, $pk, $sha1_digest), "X509_REQ_sign"); + + ok(my $req_pubkey = Net::SSLeay::X509_REQ_get_pubkey($req), "X509_REQ_get_pubkey"); + is(Net::SSLeay::X509_REQ_verify($req, $req_pubkey), 1, "X509_REQ_verify"); + + is(Net::SSLeay::X509_REQ_get_version($req), 2, "X509_REQ_get_version"); + ok(my $obj_challengePassword = Net::SSLeay::OBJ_txt2obj('1.2.840.113549.1.9.7'), "OBJ_txt2obj"); + ok(my $nid_challengePassword = Net::SSLeay::OBJ_obj2nid($obj_challengePassword), "OBJ_obj2nid"); + is(Net::SSLeay::X509_REQ_get_attr_count($req), 3, "X509_REQ_get_attr_count"); + is(my $n1 = Net::SSLeay::X509_REQ_get_attr_by_NID($req, $nid_challengePassword,-1), 1, "X509_REQ_get_attr_by_NID"); + is(my $n2 = Net::SSLeay::X509_REQ_get_attr_by_OBJ($req, $obj_challengePassword,-1), 1, "X509_REQ_get_attr_by_OBJ"); + + SKIP: { + skip('requires openssl-0.9.7', 3) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(my @attr_values = Net::SSLeay::P_X509_REQ_get_attr($req, $n1), "P_X509_REQ_get_attr"); + is(scalar(@attr_values), 1, "attr_values size"); + is(Net::SSLeay::P_ASN1_STRING_get($attr_values[0]), "password xyz", "attr_values[0]"); + } + + like(my $req_pem = Net::SSLeay::PEM_get_string_X509_REQ($req), qr/-----BEGIN CERTIFICATE REQUEST-----/, "PEM_get_string_X509_REQ"); + like(my $key_pem = Net::SSLeay::PEM_get_string_PrivateKey($pk), qr/-----BEGIN (RSA )?PRIVATE KEY-----/, "PEM_get_string_PrivateKey"); + + #write_file("tmp_cert2.req.pem", $req_pem); + #write_file("tmp_cert2.key.pem", $key_pem); + + ## PHASE2 - turn X509_REQ into X509 cert + sign with CA key + ok(my $x509ss = Net::SSLeay::X509_new(), "X509_new"); + ok(Net::SSLeay::X509_set_version($x509ss, 2), "X509_set_version"); + ok(my $sn = Net::SSLeay::X509_get_serialNumber($x509ss), "X509_get_serialNumber"); + Net::SSLeay::P_ASN1_INTEGER_set_hex($sn, 'ABCDEF'); + Net::SSLeay::X509_set_issuer_name($x509ss, Net::SSLeay::X509_get_subject_name($ca_cert)); + ok(Net::SSLeay::X509_gmtime_adj(Net::SSLeay::X509_get_notBefore($x509ss), 0), "X509_gmtime_adj + X509_get_notBefore"); + ok(Net::SSLeay::X509_gmtime_adj(Net::SSLeay::X509_get_notAfter($x509ss), 60*60*24*100), "X509_gmtime_adj + X509_get_notAfter"); + ok(Net::SSLeay::X509_set_subject_name($x509ss, Net::SSLeay::X509_REQ_get_subject_name($req)), "X509_set_subject_name + X509_REQ_get_subject_name"); + + ok(Net::SSLeay::P_X509_copy_extensions($req, $x509ss), "P_X509_copy_extensions"); + + ok(my $tmppkey = Net::SSLeay::X509_REQ_get_pubkey($req), "X509_REQ_get_pubkey"); + ok(Net::SSLeay::X509_set_pubkey($x509ss,$tmppkey), "X509_set_pubkey"); + Net::SSLeay::EVP_PKEY_free($tmppkey); + + ok(Net::SSLeay::X509_sign($x509ss, $ca_pk, $sha1_digest), "X509_sign"); + like(my $crt_pem = Net::SSLeay::PEM_get_string_X509($x509ss), qr/-----BEGIN CERTIFICATE-----/, "PEM_get_string_X509"); + + #write_file("tmp_cert2.crt.pem", $crt_pem); + + ## PHASE3 - check some certificate parameters + is(Net::SSLeay::X509_NAME_print_ex(Net::SSLeay::X509_get_subject_name($x509ss)), "O=Company Name,C=UK,CN=Common name text X509_REQ", "X509_NAME_print_ex 1"); + is(Net::SSLeay::X509_NAME_print_ex(Net::SSLeay::X509_get_issuer_name($x509ss)), "CN=CA1,O=Demo1,C=US", "X509_NAME_print_ex 2"); + SKIP: { + skip 'openssl-0.9.7e required', 2 unless Net::SSLeay::SSLeay >= 0x0090705f; + like(Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($x509ss)), qr/^\d\d\d\d-\d\d-\d\d/, "X509_get_notBefore"); + like(Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509ss)), qr/^\d\d\d\d-\d\d-\d\d/, "X509_get_notAfter"); + } + + my $mask = EVP_PK_RSA | EVP_PKT_SIGN | EVP_PKT_ENC; + is(Net::SSLeay::X509_certificate_type($x509ss)&$mask, $mask, "X509_certificate_type"); + + is(Net::SSLeay::X509_REQ_free($req), undef, "X509_REQ_free"); + is(Net::SSLeay::X509_free($x509ss), undef, "X509_free"); +} + +{ ### X509 certificate - unicode + ok(my $x509 = Net::SSLeay::X509_new(), "X509_new"); + ok(my $name = Net::SSLeay::X509_get_subject_name($x509), "X509_get_subject_name"); + my $txt = "\x{17E}lut\xFD"; + utf8::encode($txt); + ok(Net::SSLeay::X509_NAME_add_entry_by_txt($name, "CN", MBSTRING_UTF8, $txt), "X509_NAME_add_entry_by_txt"); + ok(Net::SSLeay::X509_NAME_add_entry_by_txt($name, "OU", MBSTRING_UTF8, "Unit"), "X509_NAME_add_entry_by_txt"); + is(Net::SSLeay::X509_NAME_print_ex($name), 'OU=Unit,CN=\C5\BElut\C3\BD', "X509_NAME_print_ex"); +} + +{ ### X509 certificate - copy some fields from other certificate + + my $orig_crt_pem = File::Spec->catfile('t', 'data', 'test_leaf.crt.pem'); + ok(my $bio = Net::SSLeay::BIO_new_file($orig_crt_pem, 'r'), "BIO_new_file"); + ok(my $orig_cert = Net::SSLeay::PEM_read_bio_X509($bio), "PEM_read_bio_X509"); + + ok(my $pk = Net::SSLeay::EVP_PKEY_new(), "EVP_PKEY_new"); + ok(my $rsa = Net::SSLeay::RSA_generate_key(2048, &Net::SSLeay::RSA_F4), "RSA_generate_key"); + ok(Net::SSLeay::EVP_PKEY_assign_RSA($pk,$rsa), "EVP_PKEY_assign_RSA"); + + ok(my $x509 = Net::SSLeay::X509_new(), "X509_new"); + ok(Net::SSLeay::X509_set_pubkey($x509,$pk), "X509_set_pubkey"); + ok(my $name = Net::SSLeay::X509_get_subject_name($orig_cert), "X509_get_subject_name"); + ok(Net::SSLeay::X509_set_subject_name($x509, $name), "X509_set_subject_name"); + + ok(my $sn = Net::SSLeay::X509_get_serialNumber($orig_cert), "X509_get_serialNumber"); + ok(Net::SSLeay::X509_set_serialNumber($x509, $sn), "X509_get_serialNumber"); + + Net::SSLeay::X509_set_issuer_name($x509, Net::SSLeay::X509_get_subject_name($ca_cert)); + SKIP: { + skip 'openssl-0.9.7e required', 2 unless Net::SSLeay::SSLeay >= 0x0090705f; + ok(Net::SSLeay::P_ASN1_TIME_set_isotime(Net::SSLeay::X509_get_notBefore($x509), "2010-02-01T00:00:00Z") , "P_ASN1_TIME_set_isotime+X509_get_notBefore"); + ok(Net::SSLeay::P_ASN1_TIME_set_isotime(Net::SSLeay::X509_get_notAfter($x509), "2099-02-01T00:00:00Z"), "P_ASN1_TIME_set_isotime+X509_get_notAfter"); + } + + ok(my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"), "EVP_get_digestbyname"); + ok(Net::SSLeay::X509_sign($x509, $ca_pk, $sha1_digest), "X509_sign"); + + like(my $crt_pem = Net::SSLeay::PEM_get_string_X509($x509), qr/-----BEGIN CERTIFICATE-----/, "PEM_get_string_X509"); + like(my $key_pem = Net::SSLeay::PEM_get_string_PrivateKey($pk), qr/-----BEGIN (RSA )?PRIVATE KEY-----/, "PEM_get_string_PrivateKey"); + + #write_file("tmp_cert3.crt.pem", $crt_pem); + #write_file("tmp_cert3.key.pem", $key_pem); +} + +{ ### X509 request from file + some special tests + my $req_pem = File::Spec->catfile('t', 'data', 'testreq1.pem'); + ok(my $bio = Net::SSLeay::BIO_new_file($req_pem, 'r'), "BIO_new_file"); + ok(my $req = Net::SSLeay::PEM_read_bio_X509_REQ($bio), "PEM_read_bio_X509"); + + ok(my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"), "EVP_get_digestbyname"); + is(unpack("H*", Net::SSLeay::X509_REQ_digest($req, $sha1_digest)), "1eda97a279f2bb518f96d1690aa9342c72d1c4ee", "X509_REQ_digest"); + + ok(my $req2 = Net::SSLeay::X509_REQ_new(), "X509_REQ_new"); + ok(my $name = Net::SSLeay::X509_REQ_get_subject_name($req), "X509_REQ_get_subject_name"); + ok(Net::SSLeay::X509_REQ_set_subject_name($req2, $name), "X509_REQ_set_subject_name"); + is(Net::SSLeay::X509_REQ_free($req), undef, "X509_REQ_free"); +} + +{ ### X509 + X509_REQ loading DER format + my $req_der = File::Spec->catfile('t', 'data', 'testreq1.der'); + ok(my $bio1 = Net::SSLeay::BIO_new_file($req_der, 'r'), "BIO_new_file"); + ok(my $req = Net::SSLeay::d2i_X509_REQ_bio($bio1), "d2i_X509_REQ_bio"); + + my $x509_der = File::Spec->catfile('t', 'data', 'testcert_simple.crt.der'); + ok(my $bio2 = Net::SSLeay::BIO_new_file($x509_der, 'r'), "BIO_new_file"); + + + SKIP: + { + skip 'd2i_X509_bio fails for openssl-1.1.0e and later', 1 unless Net::SSLeay::SSLeay < 0x1010005f or Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER"); + ok(my $x509 = Net::SSLeay::d2i_X509_bio($bio2), "d2i_X509_bio"); + } +} diff --git a/t/local/34_x509_crl.t b/t/local/34_x509_crl.t new file mode 100755 index 0000000..f108d39 --- /dev/null +++ b/t/local/34_x509_crl.t @@ -0,0 +1,141 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 41; +use Net::SSLeay; +use File::Spec; + +#use File::Slurp; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $ca_crt_pem = File::Spec->catfile('t', 'data', 'test_CA1.crt.pem'); +my $ca_key_pem = File::Spec->catfile('t', 'data', 'test_CA1.key.pem'); +ok(my $bio1 = Net::SSLeay::BIO_new_file($ca_crt_pem, 'r'), "BIO_new_file 1"); +ok(my $ca_cert = Net::SSLeay::PEM_read_bio_X509($bio1), "PEM_read_bio_X509"); +ok(my $bio2 = Net::SSLeay::BIO_new_file($ca_key_pem, 'r'), "BIO_new_file 2"); +ok(my $ca_pk = Net::SSLeay::PEM_read_bio_PrivateKey($bio2), "PEM_read_bio_PrivateKey"); + +{ ### X509_CRL show info + my $crl_der = File::Spec->catfile('t', 'data', 'verisign.crl.der'); + my $crl_pem = File::Spec->catfile('t', 'data', 'verisign.crl.pem'); + + ok(my $bio1 = Net::SSLeay::BIO_new_file($crl_der, 'rb'), "BIO_new_file 1"); + ok(my $bio2 = Net::SSLeay::BIO_new_file($crl_pem, 'r'), "BIO_new_file 2"); + + ok(my $crl1 = Net::SSLeay::d2i_X509_CRL_bio($bio1), "d2i_X509_CRL_bio"); + ok(my $crl2 = Net::SSLeay::PEM_read_bio_X509_CRL($bio2), "PEM_read_bio_X509_CRL"); + + ok(my $name1 = Net::SSLeay::X509_CRL_get_issuer($crl1), "X509_CRL_get_issuer 1"); + ok(my $name2 = Net::SSLeay::X509_CRL_get_issuer($crl2), "X509_CRL_get_issuer 2"); + is(Net::SSLeay::X509_NAME_cmp($name1, $name2), 0, "X509_NAME_cmp"); + + is(Net::SSLeay::X509_NAME_print_ex($name1), 'CN=VeriSign Class 3 Extended Validation SSL CA,OU=Terms of use at https://www.verisign.com/rpa (c)06,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US', "X509_NAME_print_ex"); + + ok(my $time_last = Net::SSLeay::X509_CRL_get_lastUpdate($crl1), "X509_CRL_get_lastUpdate"); + ok(my $time_next = Net::SSLeay::X509_CRL_get_nextUpdate($crl1), "X509_CRL_get_nextUpdate"); + SKIP: { + skip 'openssl-0.9.7e required', 2 unless Net::SSLeay::SSLeay >= 0x0090705f; + is(Net::SSLeay::P_ASN1_TIME_get_isotime($time_last), "2012-03-08T21:00:13Z", "P_ASN1_TIME_get_isotime last"); + is(Net::SSLeay::P_ASN1_TIME_get_isotime($time_next), "2012-03-15T21:00:13Z", "P_ASN1_TIME_get_isotime next"); + } + + is(Net::SSLeay::X509_CRL_get_version($crl1), 0, "X509_CRL_get_version"); + ok(my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"), "EVP_get_digestbyname"); + is(unpack("H*",Net::SSLeay::X509_CRL_digest($crl1, $sha1_digest)), "2a49fa78444070d2bce08b2ea5213099b3e065fd", "X509_CRL_digest"); +} + +{ ### X509_CRL create + ok(my $crl = Net::SSLeay::X509_CRL_new(), "X509_CRL_new"); + + ok(my $name = Net::SSLeay::X509_get_subject_name($ca_cert), "X509_get_subject_name"); + SKIP: { + skip('requires openssl-0.9.7', 1) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(Net::SSLeay::X509_CRL_set_issuer_name($crl, $name), "X509_CRL_set_issuer_name"); + } + + if (Net::SSLeay::SSLeay >= 0x0090705f) { + Net::SSLeay::P_ASN1_TIME_set_isotime(Net::SSLeay::X509_CRL_get_lastUpdate($crl), "2010-02-01T00:00:00Z"); + Net::SSLeay::P_ASN1_TIME_set_isotime(Net::SSLeay::X509_CRL_get_nextUpdate($crl), "2011-02-01T00:00:00Z"); + } + else { + # P_ASN1_TIME_set_isotime not available before openssl-0.9.7e + Net::SSLeay::X509_gmtime_adj(Net::SSLeay::X509_CRL_get_lastUpdate($crl), 0); + Net::SSLeay::X509_gmtime_adj(Net::SSLeay::X509_CRL_get_lastUpdate($crl), 0); + } + + SKIP: { + skip('requires openssl-0.9.7', 2) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(Net::SSLeay::X509_CRL_set_version($crl, 1), "X509_CRL_set_version"); + my $ser = Net::SSLeay::ASN1_INTEGER_new(); + Net::SSLeay::P_ASN1_INTEGER_set_hex($ser, "4AFED5654654BCEDED4AFED5654654BCEDED"); + ok(Net::SSLeay::P_X509_CRL_set_serial($crl, $ser), "P_X509_CRL_set_serial"); + Net::SSLeay::ASN1_INTEGER_free($ser); + } + + my @rev_table = ( + { serial_hex=>'1A2B3D', rev_datetime=>"2011-02-01T00:00:00Z", comp_datetime=>"2911-11-11T00:00:00Z", reason=>2 }, # 2 = cACompromise + { serial_hex=>'2A2B3D', rev_datetime=>"2011-03-01T00:00:00Z", comp_datetime=>"2911-11-11T00:00:00Z", reason=>3 }, # 3 = affiliationChanged + ); + + my $rev_datetime = Net::SSLeay::ASN1_TIME_new(); + my $comp_datetime = Net::SSLeay::ASN1_TIME_new(); + for my $item (@rev_table) { + if (Net::SSLeay::SSLeay >= 0x0090705f) { + Net::SSLeay::P_ASN1_TIME_set_isotime($rev_datetime, $item->{rev_datetime}); + Net::SSLeay::P_ASN1_TIME_set_isotime($comp_datetime, $item->{comp_datetime}); + } + else { + # P_ASN1_TIME_set_isotime not available before openssl-0.9.7e + Net::SSLeay::X509_gmtime_adj($rev_datetime, 0); + Net::SSLeay::X509_gmtime_adj($comp_datetime, 0); + } + SKIP: { + skip('requires openssl-0.9.7', 1) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(Net::SSLeay::P_X509_CRL_add_revoked_serial_hex($crl, $item->{serial_hex}, $rev_datetime, $item->{reason}, $comp_datetime), "P_X509_CRL_add_revoked_serial_hex"); + } + } + Net::SSLeay::ASN1_TIME_free($rev_datetime); + Net::SSLeay::ASN1_TIME_free($comp_datetime); + + ok(my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1"), "EVP_get_digestbyname"); + SKIP: { + skip('requires openssl-0.9.7', 1) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(Net::SSLeay::X509_CRL_sort($crl), "X509_CRL_sort"); + } + ok(Net::SSLeay::X509_CRL_sign($crl, $ca_pk, $sha1_digest), "X509_CRL_sign"); + + like(my $crl_pem = Net::SSLeay::PEM_get_string_X509_CRL($crl), qr/-----BEGIN X509 CRL-----/, "PEM_get_string_X509_CRL"); + + #write_file("tmp.crl.pem", $crl_pem); + + is(Net::SSLeay::X509_CRL_free($crl), undef, "X509_CRL_free"); +} + +{ ### special tests + my $crl_der = File::Spec->catfile('t', 'data', 'test_CA1.crl.der'); + ok(my $bio = Net::SSLeay::BIO_new_file($crl_der, 'rb'), "BIO_new_file"); + ok(my $crl = Net::SSLeay::d2i_X509_CRL_bio($bio), "d2i_X509_CRL_bio"); + is(Net::SSLeay::X509_CRL_verify($crl, Net::SSLeay::X509_get_pubkey($ca_cert)), 1, "X509_CRL_verify"); + + ok(my $time_last = Net::SSLeay::X509_CRL_get_lastUpdate($crl), "X509_CRL_get_lastUpdate"); + ok(my $time_next = Net::SSLeay::X509_CRL_get_nextUpdate($crl), "X509_CRL_get_nextUpdate"); + + SKIP: { + skip('requires openssl-0.9.7', 2) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(my $sn = Net::SSLeay::P_X509_CRL_get_serial($crl), "P_X509_CRL_get_serial"); + is(Net::SSLeay::ASN1_INTEGER_get($sn), 2, "ASN1_INTEGER_get"); + } + + SKIP: { + skip('requires openssl-0.9.7', 3) unless Net::SSLeay::SSLeay >= 0x0090700f; + ok(my $crl2 = Net::SSLeay::X509_CRL_new(), "X509_CRL_new"); + ok(Net::SSLeay::X509_CRL_set_lastUpdate($crl2, $time_last), "X509_CRL_set_lastUpdate"); + ok(Net::SSLeay::X509_CRL_set_nextUpdate($crl2, $time_next), "X509_CRL_set_nextUpdate"); + Net::SSLeay::X509_CRL_free($crl2); + } +} diff --git a/t/local/35_ephemeral.t b/t/local/35_ephemeral.t new file mode 100644 index 0000000..86e1d78 --- /dev/null +++ b/t/local/35_ephemeral.t @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; + +BEGIN { + plan skip_all => "libressl and OpenSSL 1.1 removed support for ephemeral/temporary RSA private keys" if Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER") || Net::SSLeay::constant("OPENSSL_VERSION_NUMBER") >= 0x10100000; +} + +plan tests => 3; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +ok( my $ctx = Net::SSLeay::CTX_new(), 'CTX_new' ); +ok( my $rsa = Net::SSLeay::RSA_generate_key(2048, Net::SSLeay::RSA_F4()), 'RSA_generate_key' ); +ok( Net::SSLeay::CTX_set_tmp_rsa($ctx, $rsa), 'CTX_set_tmp_rsa' ); diff --git a/t/local/36_verify.t b/t/local/36_verify.t new file mode 100644 index 0000000..669d427 --- /dev/null +++ b/t/local/36_verify.t @@ -0,0 +1,361 @@ +#!/usr/bin/perl +# +# Test various verify and ASN functions +# added 2010-04-16 + +use strict; +use warnings; +use Test::More tests => 103; +use Net::SSLeay; +use File::Spec; +use IO::Socket::INET; +use Config; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::add_ssl_algorithms(); +Net::SSLeay::OpenSSL_add_all_algorithms(); + +# Our CA cert and a cert signed with it +my $ca_pem = File::Spec->catfile('t', 'data', 'test_CA1_2048.crt.pem'); +#my $ca_dir = File::Spec->catfile('t', 'data'); +my $ca_dir = ''; +my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard_CA1_2048.crt.pem'); +my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + +my $pm; +my $pm2; +my $verify_result = -1; + +SKIP: { + skip 'openssl-0.9.8 required', 7 unless Net::SSLeay::SSLeay >= 0x0090800f; + $pm = Net::SSLeay::X509_VERIFY_PARAM_new(); + ok($pm, 'X509_VERIFY_PARAM_new'); + $pm2 = Net::SSLeay::X509_VERIFY_PARAM_new(); + ok($pm2, 'X509_VERIFY_PARAM_new 2'); + ok(Net::SSLeay::X509_VERIFY_PARAM_inherit($pm2, $pm), 'X509_VERIFY_PARAM_inherit'); + ok(Net::SSLeay::X509_VERIFY_PARAM_set1($pm2, $pm), 'X509_VERIFY_PARAM_inherit'); + ok(Net::SSLeay::X509_VERIFY_PARAM_set1_name($pm, 'fred'), 'X509_VERIFY_PARAM_set1_name'); + ok(Net::SSLeay::X509_V_FLAG_ALLOW_PROXY_CERTS() == 0x40, 'X509_V_FLAG_ALLOW_PROXY_CERTS'); + ok(Net::SSLeay::X509_VERIFY_PARAM_set_flags($pm, Net::SSLeay::X509_V_FLAG_ALLOW_PROXY_CERTS()), 'X509_VERIFY_PARAM_set_flags'); +} + +SKIP: { + skip 'openssl-0.9.8a required', 3 unless Net::SSLeay::SSLeay >= 0x0090801f; + ok(Net::SSLeay::X509_VERIFY_PARAM_get_flags($pm) == Net::SSLeay::X509_V_FLAG_ALLOW_PROXY_CERTS(), 'X509_VERIFY_PARAM_get_flags'); + ok(Net::SSLeay::X509_VERIFY_PARAM_clear_flags($pm, Net::SSLeay::X509_V_FLAG_ALLOW_PROXY_CERTS()), 'X509_VERIFY_PARAM_clear_flags'); + ok(Net::SSLeay::X509_VERIFY_PARAM_get_flags($pm) == 0, 'X509_VERIFY_PARAM_get_flags'); +}; + +SKIP: { + skip 'openssl-0.9.8 required', 4 unless Net::SSLeay::SSLeay >= 0x0090800f; + ok(Net::SSLeay::X509_PURPOSE_SSL_CLIENT() == 1, 'X509_PURPOSE_SSL_CLIENT'); + ok(Net::SSLeay::X509_VERIFY_PARAM_set_purpose($pm, Net::SSLeay::X509_PURPOSE_SSL_CLIENT()), 'X509_VERIFY_PARAM_set_purpose'); + ok(Net::SSLeay::X509_TRUST_EMAIL() == 4, 'X509_TRUST_EMAIL'); + ok(Net::SSLeay::X509_VERIFY_PARAM_set_trust($pm, Net::SSLeay::X509_TRUST_EMAIL()), 'X509_VERIFY_PARAM_set_trust'); + Net::SSLeay::X509_VERIFY_PARAM_set_depth($pm, 5); + Net::SSLeay::X509_VERIFY_PARAM_set_time($pm, time); + Net::SSLeay::X509_VERIFY_PARAM_free($pm); + Net::SSLeay::X509_VERIFY_PARAM_free($pm2); +} + +# Test ASN1 objects +my $asn_object = Net::SSLeay::OBJ_txt2obj('1.2.3.4', 0); +ok($asn_object, 'OBJ_txt2obj'); +ok(Net::SSLeay::OBJ_obj2txt($asn_object, 0) eq '1.2.3.4', 'OBJ_obj2txt'); + +ok(Net::SSLeay::OBJ_txt2nid('1.2.840.113549.1') == 2, 'OBJ_txt2nid'); # NID_pkcs +ok(Net::SSLeay::OBJ_txt2nid('1.2.840.113549.2.5') == 4, 'OBJ_txt2nid'); # NID_md5 + +ok(Net::SSLeay::OBJ_ln2nid('RSA Data Security, Inc. PKCS') == 2, 'OBJ_ln2nid'); # NID_pkcs +ok(Net::SSLeay::OBJ_ln2nid('md5') == 4, 'OBJ_ln2nid'); # NID_md5 + +ok(Net::SSLeay::OBJ_sn2nid('pkcs') == 2, 'OBJ_sn2nid'); # NID_pkcs +ok(Net::SSLeay::OBJ_sn2nid('MD5') == 4, 'OBJ_sn2nid'); # NID_md5 + +my $asn_object2 = Net::SSLeay::OBJ_txt2obj('1.2.3.4', 0); +ok(Net::SSLeay::OBJ_cmp($asn_object2, $asn_object) == 0, 'OBJ_cmp'); +$asn_object2 = Net::SSLeay::OBJ_txt2obj('1.2.3.5', 0); +ok(Net::SSLeay::OBJ_cmp($asn_object2, $asn_object) != 0, 'OBJ_cmp'); + +ok(1, "Finished with tests that don't need fork"); + +my $server; +SKIP: { + skip "fork() not supported on $^O", 54, unless $Config{d_fork}; + + $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3) + or BAIL_OUT("failed to create server socket: $!"); + + run_server(); + my $server_addr = $server->sockhost.':'.$server->sockport; + close($server); + client($server_addr); +} + +verify_local_trust(); + +sub test_policy_checks +{ + my ($ctx, $cl, $ok) = @_; + + $pm = Net::SSLeay::X509_VERIFY_PARAM_new(); + + # Certificate must have this policy + Net::SSLeay::X509_VERIFY_PARAM_set_flags($pm, Net::SSLeay::X509_V_FLAG_POLICY_CHECK() | Net::SSLeay::X509_V_FLAG_EXPLICIT_POLICY()); + + my $oid = $ok ? '1.1.3.4' : '1.1.3.3.99.88.77'; + my $pobject = Net::SSLeay::OBJ_txt2obj($oid, 1); + ok($pobject, "OBJ_txt2obj($oid)"); + is(Net::SSLeay::X509_VERIFY_PARAM_add0_policy($pm, $pobject), 1, "X509_VERIFY_PARAM_add0_policy($oid)"); + + my $ssl = client_get_ssl($ctx, $cl, $pm); + my $ret = Net::SSLeay::connect($ssl); + is($verify_result, Net::SSLeay::get_verify_result($ssl), 'Verify callback result and get_verify_result are equal'); + if ($ok) { + is($ret, 1, 'connect ok: policy checks succeeded'); + is($verify_result, Net::SSLeay::X509_V_OK(), 'Verify result is X509_V_OK'); + print "connect failed: $ret: " . Net::SSLeay::print_errs() . "\n" unless $ret == 1; + } else { + isnt($ret, 1, 'connect not ok: policy checks must fail') if !$ok; + is($verify_result, Net::SSLeay::X509_V_ERR_NO_EXPLICIT_POLICY(), 'Verify result is X509_V_ERR_NO_EXPLICIT_POLICY'); + } + + Net::SSLeay::X509_VERIFY_PARAM_free($pm); +} + +# These need at least OpenSSL 1.0.2 or LibreSSL 2.7.0 +sub test_hostname_checks +{ + my ($ctx, $cl, $ok) = @_; + SKIP: { + skip 'No Net::SSLeay::X509_VERIFY_PARAM_set1_host, skipping hostname_checks', 13 unless (exists &Net::SSLeay::X509_VERIFY_PARAM_set1_host); + + $pm = Net::SSLeay::X509_VERIFY_PARAM_new(); + + # Note: wildcards are supported by default + is(Net::SSLeay::X509_VERIFY_PARAM_set1_host($pm, 'server.example.com'), 1, 'X509_VERIFY_PARAM_set1_host(server.example.com)') if $ok; + is(Net::SSLeay::X509_VERIFY_PARAM_add1_host($pm, 'server.not.example.com'), 1, 'X509_VERIFY_PARAM_add1_host(server.not.example.com)') if !$ok; + + is(Net::SSLeay::X509_VERIFY_PARAM_set1_email($pm, 'wildcard@example.com'), 1, 'X509_VERIFY_PARAM_set1_email'); + + # Note: 'set' means that only one successfully set can be active + # set1_ip: IPv4 or IPv6 address as 4 or 16 octet binary. + # setip_ip_asc: IPv4 or IPv6 address as ASCII string + is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip($pm, pack('CCCC', 10, 20, 30, 40)), 1, 'X509_VERIFY_PARAM_set1_ip(10.20.30.40)'); +# is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip($pm, pack('NNNN', hex('20010db8'), hex('01480100'), 0, hex('31'))), 1, 'X509_VERIFY_PARAM_set1_ip(2001:db8:148:100::31)'); +# is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip_asc($pm, '10.20.30.40'), 1, 'X509_VERIFY_PARAM_set1_ip_asc(10.20.30.40)'); +# is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip_asc($pm, '2001:db8:148:100::31'), 1, 'X509_VERIFY_PARAM_set1_ip_asc(2001:db8:148:100::31))'); + + # Also see that incorrect values do not change anything. + is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip($pm, '123'), 0, 'X509_VERIFY_PARAM_set1_ip(123)'); + is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip($pm, '123456789012345'), 0, 'X509_VERIFY_PARAM_set1_ip(123456789012345)'); + is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip_asc($pm, '10.20.30.256'), 0, 'X509_VERIFY_PARAM_set1_ip_asc(10.20.30.256)'); + is(Net::SSLeay::X509_VERIFY_PARAM_set1_ip_asc($pm, '12345::'), 0, 'X509_VERIFY_PARAM_set1_ip_asc(12345::)'); + + my $ssl = client_get_ssl($ctx, $cl, $pm); + my $ret = Net::SSLeay::connect($ssl); + is($verify_result, Net::SSLeay::get_verify_result($ssl), 'Verify callback result and get_verify_result are equal'); + if ($ok) { + is($ret, 1, 'connect ok: hostname checks succeeded'); + is($verify_result, Net::SSLeay::X509_V_OK(), 'Verify result is X509_V_OK'); + print "connect failed: $ret: " . Net::SSLeay::print_errs() . "\n" unless $ret == 1; + } else { + isnt($ret, 1, 'connect not ok: hostname checks must fail') if !$ok; + is($verify_result, Net::SSLeay::X509_V_ERR_HOSTNAME_MISMATCH(), 'Verify result is X509_V_ERR_HOSTNAME_MISMATCH'); + } + + # For some reason OpenSSL 1.0.2 and LibreSSL return undef for get0_peername. Are we doing this wrong? + $pm2 = Net::SSLeay::get0_param($ssl); + my $peername = Net::SSLeay::X509_VERIFY_PARAM_get0_peername($pm2); + if ($ok) { + is($peername, '*.example.com', 'X509_VERIFY_PARAM_get0_peername returns *.example.com') + if (Net::SSLeay::SSLeay >= 0x10100000 && !Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER")); + is($peername, undef, 'X509_VERIFY_PARAM_get0_peername returns undefined for OpenSSL 1.0.2 and LibreSSL') + if (Net::SSLeay::SSLeay < 0x10100000 || Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER")); + } else { + is($peername, undef, 'X509_VERIFY_PARAM_get0_peername returns undefined'); + } + + Net::SSLeay::X509_VERIFY_PARAM_free($pm); + Net::SSLeay::X509_VERIFY_PARAM_free($pm2); + } +} + +sub test_wildcard_checks +{ + my ($ctx, $cl) = @_; + SKIP: { + skip 'No Net::SSLeay::X509_VERIFY_PARAM_set1_host, skipping wildcard_checks', 7 unless (exists &Net::SSLeay::X509_VERIFY_PARAM_set1_host); + + $pm = Net::SSLeay::X509_VERIFY_PARAM_new(); + + # Wildcards are allowed by default: disallow + is(Net::SSLeay::X509_VERIFY_PARAM_set1_host($pm, 'www.example.com'), 1, 'X509_VERIFY_PARAM_set1_host'); + is(Net::SSLeay::X509_VERIFY_PARAM_set_hostflags($pm, Net::SSLeay::X509_CHECK_FLAG_NO_WILDCARDS()), undef, 'X509_VERIFY_PARAM_set_hostflags(X509_CHECK_FLAG_NO_WILDCARDS)'); + + my $ssl = client_get_ssl($ctx, $cl, $pm); + my $ret = Net::SSLeay::connect($ssl); + isnt($ret, 1, 'Connect must fail in wildcard test'); + is($verify_result, Net::SSLeay::get_verify_result($ssl), 'Verify callback result and get_verify_result are equal'); + is($verify_result, Net::SSLeay::X509_V_ERR_HOSTNAME_MISMATCH(), 'Verify result is X509_V_ERR_HOSTNAME_MISMATCH'); + + Net::SSLeay::X509_VERIFY_PARAM_free($pm); + } +} + +sub verify_local_trust { + my $digicert_ca = File::Spec->catfile('t', 'data', 'test_CA1.crt.pem'); + my $twitter_chain = File::Spec->catfile('t', 'data', 'chain_leaf.crt.pem'); + + # read in twitter chain + my $bio = Net::SSLeay::BIO_new_file($twitter_chain, 'r'); + ok(my $x509_info_sk = Net::SSLeay::PEM_X509_INFO_read_bio($bio), "PEM_X509_INFO_read_bio able to read in entire chain"); + Net::SSLeay::BIO_free($bio); + # read in just twitter certificate + $bio = Net::SSLeay::BIO_new_file($twitter_chain, 'r'); + ok(my $cert = Net::SSLeay::PEM_read_bio_X509($bio), "PEM_read_bio_X509 able to read in single cert from chain"); + Net::SSLeay::BIO_free($bio); + # read in root CA (digicert CA) + $bio = Net::SSLeay::BIO_new_file($digicert_ca, 'r'); + ok(my $ca = Net::SSLeay::PEM_read_bio_X509($bio), "PEM_read_bio_X509 able to read in root CA"); + Net::SSLeay::BIO_free($bio); + + ok(my $x509_sk = Net::SSLeay::sk_X509_new_null(), "sk_X509_new_null creates STACK_OF(X509) successfully"); + ok(my $num = Net::SSLeay::sk_X509_INFO_num($x509_info_sk), "sk_X509_INFO_num is nonzero"); + + # set up STORE_CTX and verify twitter cert using only root CA, should fail due to incomplete chain + ok(my $store = Net::SSLeay::X509_STORE_new(), "X509_STORE_new creates new store"); + ok(Net::SSLeay::X509_STORE_add_cert($store, $ca), "X509_STORE_add_cert CA cert"); + ok(my $ctx = Net::SSLeay::X509_STORE_CTX_new(), "X509_STORE_CTX_new creates new store context"); + Net::SSLeay::X509_STORE_CTX_init($ctx, $store, $cert); + ok(!Net::SSLeay::X509_verify_cert($ctx), 'X509_verify_cert correctly fails'); + is(Net::SSLeay::X509_STORE_CTX_get_error($ctx), + Net::SSLeay::X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY(), "X509_STORE_CTX_get_error returns unable to get local issuer certificate"); + Net::SSLeay::X509_STORE_free($store); + Net::SSLeay::X509_STORE_CTX_free($ctx); + + # add all certificates from twitter chain to X509 stack + for (my $i = 0; $i < $num; $i++) { + ok(my $x509_info = Net::SSLeay::sk_X509_INFO_value($x509_info_sk, $i), "sk_X509_INFO_value"); + ok(my $x509 = Net::SSLeay::P_X509_INFO_get_x509($x509_info), "P_X509_INFO_get_x509"); + ok(Net::SSLeay::sk_X509_push($x509_sk, $x509), "sk_X509_push"); + } + + # set up STORE_CTX and verify twitter cert using root CA and chain, should succeed + ok($store = Net::SSLeay::X509_STORE_new(), "X509_STORE_new creates new store"); + ok(Net::SSLeay::X509_STORE_add_cert($store, $ca), "X509_STORE_add_cert CA cert"); + ok($ctx = Net::SSLeay::X509_STORE_CTX_new(), "X509_STORE_CTX_new creates new store context"); + Net::SSLeay::X509_STORE_CTX_init($ctx, $store, $cert, $x509_sk); + ok(Net::SSLeay::X509_verify_cert($ctx), 'X509_verify_cert correctly succeeds'); + is(Net::SSLeay::X509_STORE_CTX_get_error($ctx), Net::SSLeay::X509_V_OK(), "X509_STORE_CTX_get_error returns ok"); + Net::SSLeay::X509_STORE_free($store); + Net::SSLeay::X509_STORE_CTX_free($ctx); + + Net::SSLeay::sk_X509_free($x509_sk); +} + +# Prepare and return a new $ssl based on callers verification needs +# Note that this adds tests to caller's test count. +sub client_get_ssl +{ + my ($ctx, $cl, $pm) = @_; + + my $store = Net::SSLeay::CTX_get_cert_store($ctx); + ok($store, 'CTX_get_cert_store'); + is(Net::SSLeay::X509_STORE_set1_param($store, $pm), 1, 'X509_STORE_set1_param'); + + # Needs OpenSSL 1.0.0 or later + #Net::SSLeay::CTX_set1_param($ctx, $pm); + + $verify_result = -1; # Last verification result, set by callback below + my $verify_cb = sub { $verify_result = Net::SSLeay::X509_STORE_CTX_get_error($_[1]); return $_[0];}; + + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_verify($ssl, Net::SSLeay::VERIFY_PEER(), $verify_cb); + Net::SSLeay::set_fd($ssl, $cl); + + return $ssl; +} + +# SSL client - connect to server and test different verification +# settings +sub client { + my ($server_addr) = @_; + + my ($ctx, $cl); + foreach my $task (qw( + policy_checks_ok policy_checks_fail + hostname_checks_ok hostname_checks_fail + wildcard_checks + finish)) + { + $ctx = Net::SSLeay::CTX_new(); + is(Net::SSLeay::CTX_load_verify_locations($ctx, $ca_pem, $ca_dir), 1, "load_verify_locations($ca_pem $ca_dir)"); + + $cl = IO::Socket::INET->new($server_addr) or BAIL_OUT("failed to connect to server: $!"); + + test_policy_checks($ctx, $cl, 1) if $task eq 'policy_checks_ok'; + test_policy_checks($ctx, $cl, 0) if $task eq 'policy_checks_fail'; + test_hostname_checks($ctx, $cl, 1) if $task eq 'hostname_checks_ok'; + test_hostname_checks($ctx, $cl, 0) if $task eq 'hostname_checks_fail'; + test_wildcard_checks($ctx, $cl) if $task eq 'wildcard_checks'; + last if $task eq 'finish'; # Leaves $cl alive + + close($cl); + } + + # Tell the server to quit and see that our connection is still up + $ctx = Net::SSLeay::CTX_new(); + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::connect($ssl); + my $end = "end"; + Net::SSLeay::ssl_write_all($ssl, $end); + Net::SSLeay::shutdown($ssl); + ok($end eq Net::SSLeay::ssl_read_all($ssl), 'Successful termination'); + return; +} + +# SSL server - just accept connnections and exit when told to by +# the client +sub run_server +{ + my $pid; + defined($pid = fork()) or BAIL_OUT("failed to fork: $!"); + + return if $pid != 0; + + $SIG{'PIPE'} = 'IGNORE'; + my $ctx = Net::SSLeay::CTX_new(); + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + my $ret = Net::SSLeay::CTX_check_private_key($ctx); + BAIL_OUT("Server: CTX_check_private_key failed: $cert_pem, $key_pem") unless $ret == 1; + if (defined &Net::SSLeay::CTX_set_num_tickets) { + # TLS 1.3 server sends session tickets after a handhake as part of + # the SSL_accept(). If a client finishes all its job including closing + # TCP connectino before a server sends the tickets, SSL_accept() fails + # with SSL_ERROR_SYSCALL and EPIPE errno and the server receives + # SIGPIPE signal. + my $ret = Net::SSLeay::CTX_set_num_tickets($ctx, 0); + BAIL_OUT("Session tickets disabled") unless $ret; + } + + while (1) + { + my $cl = $server->accept or BAIL_OUT("accept failed: $!"); + my $ssl = Net::SSLeay::new($ctx); + + Net::SSLeay::set_fd($ssl, fileno($cl)); + my $ret = Net::SSLeay::accept($ssl); + next unless $ret == 1; + + # Termination request or other message from client + my $msg = Net::SSLeay::ssl_read_all($ssl); + if (defined $msg and $msg eq 'end') + { + Net::SSLeay::ssl_write_all($ssl, 'end'); + exit (0); + } + } +} diff --git a/t/local/37_asn1_time.t b/t/local/37_asn1_time.t new file mode 100644 index 0000000..8b72775 --- /dev/null +++ b/t/local/37_asn1_time.t @@ -0,0 +1,40 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 10; +use Net::SSLeay; + +my $atime1 = Net::SSLeay::ASN1_TIME_new(); +ok($atime1, 'ASN1_TIME_new [1]'); + +Net::SSLeay::ASN1_TIME_set($atime1, 1999888777); +SKIP: { + skip 'openssl-0.9.8i is buggy', 2 if Net::SSLeay::SSLeay == 0x0090809f; + is(Net::SSLeay::P_ASN1_TIME_put2string($atime1), 'May 16 20:39:37 2033 GMT', 'P_ASN1_TIME_put2string'); + is(Net::SSLeay::P_ASN1_UTCTIME_put2string($atime1), 'May 16 20:39:37 2033 GMT', 'P_ASN1_UTCTIME_put2string'); +} +SKIP: { + skip 'openssl-0.9.7e required', 1 unless Net::SSLeay::SSLeay >= 0x0090705f; + is(Net::SSLeay::P_ASN1_TIME_get_isotime($atime1), '2033-05-16T20:39:37Z', 'P_ASN1_TIME_get_isotime'); +} +Net::SSLeay::ASN1_TIME_free($atime1); + +my $atime2 = Net::SSLeay::ASN1_TIME_new(); +ok($atime2, 'ASN1_TIME_new [2]'); +SKIP: { + skip 'openssl-0.9.7e required', 2 unless Net::SSLeay::SSLeay >= 0x0090705f; + Net::SSLeay::P_ASN1_TIME_set_isotime($atime2, '2075-06-19T13:08:52Z'); + SKIP: { + skip 'openssl-0.9.8i is buggy', 1 if Net::SSLeay::SSLeay == 0x0090809f; + is(Net::SSLeay::P_ASN1_TIME_put2string($atime2), 'Jun 19 13:08:52 2075 GMT', 'P_ASN1_TIME_put2string y=2075'); + } + is(Net::SSLeay::P_ASN1_TIME_get_isotime($atime2), '2075-06-19T13:08:52Z', 'P_ASN1_TIME_get_isotime y=2075'); +} +Net::SSLeay::ASN1_TIME_free($atime2); + +my $atime3 = Net::SSLeay::ASN1_TIME_new(); +ok($atime1, 'ASN1_TIME_new [3]'); +ok(Net::SSLeay::X509_gmtime_adj($atime3, 60*60*24*365*2)); +like(Net::SSLeay::P_ASN1_TIME_put2string($atime3), qr/[A-Z][a-z]+ +\d+ +\d+:\d+:\d+ +20\d\d/, 'X509_gmtime_adj'); +Net::SSLeay::ASN1_TIME_free($atime3); diff --git a/t/local/38_priv-key.t b/t/local/38_priv-key.t new file mode 100755 index 0000000..a80dbd1 --- /dev/null +++ b/t/local/38_priv-key.t @@ -0,0 +1,41 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 10; +use Net::SSLeay; +use File::Spec; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); +Net::SSLeay::OpenSSL_add_all_algorithms(); + +my $key_pem_encrypted = File::Spec->catfile('t', 'data', 'test_CA1.encrypted_key.pem'); +my $key_pem = File::Spec->catfile('t', 'data', 'test_CA1.key.pem'); + +{ + ok(my $bio_pem = Net::SSLeay::BIO_new_file($key_pem, 'r'), "BIO_new_file 3"); + ok(Net::SSLeay::PEM_read_bio_PrivateKey($bio_pem), "PEM_read_bio_PrivateKey no password"); +} + +{ + ok(my $bio_pem_encrypted = Net::SSLeay::BIO_new_file($key_pem_encrypted, 'r'), "BIO_new_file"); + ok(Net::SSLeay::PEM_read_bio_PrivateKey($bio_pem_encrypted, sub {"secret"}), "PEM_read_bio_PrivateKey encrypted - callback"); +} + +{ + ok(my $bio_pem_encrypted = Net::SSLeay::BIO_new_file($key_pem_encrypted, 'r'), "BIO_new_file"); + ok(Net::SSLeay::PEM_read_bio_PrivateKey($bio_pem_encrypted, undef, "secret"), "PEM_read_bio_PrivateKey encrypted - password"); +} + +{ + ok(my $bio_pem_encrypted = Net::SSLeay::BIO_new_file($key_pem_encrypted, 'r'), "BIO_new_file"); + ok(!Net::SSLeay::PEM_read_bio_PrivateKey($bio_pem_encrypted, sub {"invalid"}), "PEM_read_bio_PrivateKey encrypted - callback (wrong password)"); +} + +{ + ok(my $bio_pem_encrypted = Net::SSLeay::BIO_new_file($key_pem_encrypted, 'r'), "BIO_new_file"); + ok(!Net::SSLeay::PEM_read_bio_PrivateKey($bio_pem_encrypted, undef, "invalid"), "PEM_read_bio_PrivateKey encrypted - password (wrong password)"); +} diff --git a/t/local/39_pkcs12.t b/t/local/39_pkcs12.t new file mode 100644 index 0000000..11de9dd --- /dev/null +++ b/t/local/39_pkcs12.t @@ -0,0 +1,59 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 19; +use Net::SSLeay; +use File::Spec; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $filename1 = File::Spec->catfile('t', 'data', 'pkcs12-no-chain.p12'); +my $filename2 = File::Spec->catfile('t', 'data', 'pkcs12-full.p12'); +my $filename3 = File::Spec->catfile('t', 'data', 'pkcs12-no-passwd.p12'); + +{ + my($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename1, 1, "secret"); + ok($privkey, '$privkey [1]'); + ok($cert, '$cert [1]'); + is(scalar(@cachain), 0, 'size of @cachain [1]'); + my $subj_name = Net::SSLeay::X509_get_subject_name($cert); + is(Net::SSLeay::X509_NAME_oneline($subj_name), '/C=US/O=Org/OU=Unit/CN=pkcs12-test', "X509_NAME_oneline [1]"); +} + +{ + my($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename2, 1, "secret"); + ok($privkey, '$privkey [2]'); + ok($cert, '$cert [2]'); + is(scalar(@cachain), 2, 'size of @cachain [2]'); + my $subj_name = Net::SSLeay::X509_get_subject_name($cert); + my $ca1_subj_name = Net::SSLeay::X509_get_subject_name($cachain[0]); + my $ca2_subj_name = Net::SSLeay::X509_get_subject_name($cachain[1]); + is(Net::SSLeay::X509_NAME_oneline($subj_name), '/C=US/O=Org/OU=Unit/CN=pkcs12-test', "X509_NAME_oneline [2/1]"); + like(Net::SSLeay::X509_NAME_oneline($ca1_subj_name), qr/C=.*CN=.*/, "X509_NAME_oneline [2/2]"); + like(Net::SSLeay::X509_NAME_oneline($ca2_subj_name), qr/C=.*CN=.*/, "X509_NAME_oneline [2/3]"); + SKIP: { + skip("cert order in CA chain is different in openssl pre-1.0.0", 2) unless Net::SSLeay::SSLeay >= 0x01000000; + is(Net::SSLeay::X509_NAME_oneline($ca1_subj_name), '/C=US/O=Demo1/CN=CA1', "X509_NAME_oneline [2/4]"); + is(Net::SSLeay::X509_NAME_oneline($ca2_subj_name), '/C=US/OU=Demo2/CN=CA2', "X509_NAME_oneline [2/5]"); + } +} + +{ + my($privkey, $cert, @cachain) = Net::SSLeay::P_PKCS12_load_file($filename3, 1); + ok($privkey, '$privkey [3]'); + ok($cert, '$cert [3]'); + is(scalar(@cachain), 0, 'size of @cachain [3]'); + my $subj_name = Net::SSLeay::X509_get_subject_name($cert); + is(Net::SSLeay::X509_NAME_oneline($subj_name), '/C=US/O=Org/OU=Unit/CN=pkcs12-test', "X509_NAME_oneline [3]"); +} + +{ + my($privkey, $cert, @should_be_empty) = Net::SSLeay::P_PKCS12_load_file($filename2, 0, "secret"); + ok($privkey, '$privkey [4]'); + ok($cert, '$cert [4]'); + is(scalar(@should_be_empty), 0, 'size of @should_be_empty'); +} \ No newline at end of file diff --git a/t/local/40_npn_support.t b/t/local/40_npn_support.t new file mode 100644 index 0000000..8dc258c --- /dev/null +++ b/t/local/40_npn_support.t @@ -0,0 +1,106 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Symbol qw(gensym); +use Net::SSLeay; +use Config; + +BEGIN { + plan skip_all => "openssl 1.0.1 required" unless Net::SSLeay::SSLeay >= 0x10001000; + plan skip_all => "libressl removed support for NPN" if Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER"); + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +plan tests => 7; + +my $sock; +my $pid; + +my $port = 40000+int(rand(9999)); +my $ip = "\x7F\0\0\x01"; +my $serv_params = sockaddr_in($port, $ip); + +my $msg = 'ssleay-npn-test'; +my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); +my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); +my @results; +Net::SSLeay::initialize(); + +{ + # SSL server + $sock = gensym(); + socket($sock, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + bind($sock, $serv_params) or BAIL_OUT("failed to bind socket: $!"); + listen($sock, 3) or BAIL_OUT("failed to listen on socket: $!"); + + $pid = fork(); + BAIL_OUT("failed to fork: $!") unless defined $pid; + if ($pid == 0) { + my $ns = gensym(); + my $addr = accept($ns, $sock); + my $old_out = select($ns); + $| = 1; + select($old_out); + + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + + my $rv = Net::SSLeay::CTX_set_next_protos_advertised_cb($ctx, ['spdy/2','http1.1']); + is($rv, 1, 'CTX_set_next_protos_advertised_cb'); + + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, fileno($ns)); + Net::SSLeay::accept($ssl); + + is('spdy/2' , Net::SSLeay::P_next_proto_negotiated($ssl), 'P_next_proto_negotiated/server'); + + my $got = Net::SSLeay::ssl_read_all($ssl); + is($got, $msg, 'ssl_read_all compare'); + + Net::SSLeay::ssl_write_all($ssl, uc($got)); + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + close $ns; + close $sock; + exit; + } +} + +{ + # SSL client + my $s1 = gensym(); + socket($s1, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s1, $serv_params) or BAIL_OUT("failed to connect: $!"); + my $old_out = select($s1); + $| = 1; + select($old_out); + + my $ctx1 = Net::SSLeay::CTX_tlsv1_new(); + + my $rv = Net::SSLeay::CTX_set_next_proto_select_cb($ctx1, ['http1.1','spdy/2']); + push @results, [ $rv==1, 'CTX_set_next_proto_select_cb']; + + Net::SSLeay::CTX_set_options($ctx1, &Net::SSLeay::OP_ALL); + my $ssl1 = Net::SSLeay::new($ctx1); + Net::SSLeay::set_fd($ssl1, $s1); + Net::SSLeay::connect($ssl1); + Net::SSLeay::ssl_write_all($ssl1, $msg); + + push @results, [ 'spdy/2' eq Net::SSLeay::P_next_proto_negotiated($ssl1), 'P_next_proto_negotiated/client']; + push @results, [ 1 == Net::SSLeay::P_next_proto_last_status($ssl1), 'P_next_proto_last_status/client']; + + Net::SSLeay::free($ssl1); + Net::SSLeay::CTX_free($ctx1); + close $s1; +} + +waitpid $pid, 0; +push @results, [$? == 0, 'server exited with 0']; +END { + Test::More->builder->current_test(3); + ok( $_->[0], $_->[1] ) for (@results); +} diff --git a/t/local/41_alpn_support.t b/t/local/41_alpn_support.t new file mode 100644 index 0000000..c01f486 --- /dev/null +++ b/t/local/41_alpn_support.t @@ -0,0 +1,104 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Symbol qw(gensym); +use Net::SSLeay; +use Config; + +BEGIN { + plan skip_all => "openssl 1.0.2 required" unless Net::SSLeay::SSLeay >= 0x10002000; + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +plan tests => 6; + +my $sock; +my $pid; + +my $port = 40000+int(rand(9999)); +my $ip = "\x7F\0\0\x01"; +my $serv_params = sockaddr_in($port, $ip); + +my $msg = 'ssleay-alpn-test'; +my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); +my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); +my @results; +Net::SSLeay::initialize(); + +{ + # SSL server + $sock = gensym(); + socket($sock, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + bind($sock, $serv_params) or BAIL_OUT("failed to bind socket: $!"); + listen($sock, 3) or BAIL_OUT("failed to listen on socket: $!"); + + $pid = fork(); + BAIL_OUT("failed to fork: $!") unless defined $pid; + if ($pid == 0) { + my $ns = gensym(); + my $addr = accept($ns, $sock); + my $old_out = select($ns); + $| = 1; + select($old_out); + + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + + my $rv = Net::SSLeay::CTX_set_alpn_select_cb($ctx, ['http/1.1','spdy/2']); + is($rv, 1, 'CTX_set_alpn_select_cb'); + + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, fileno($ns)); + Net::SSLeay::accept($ssl); + + is(Net::SSLeay::P_alpn_selected($ssl), 'spdy/2', 'P_alpn_selected/server'); + + my $got = Net::SSLeay::ssl_read_all($ssl); + is($got, $msg, 'ssl_read_all compare'); + + Net::SSLeay::ssl_write_all($ssl, uc($got)); + Net::SSLeay::free($ssl); + Net::SSLeay::CTX_free($ctx); + close $ns; + close $sock; + exit; + } +} + +{ + # SSL client + my $s1 = gensym(); + socket($s1, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!"); + connect($s1, $serv_params) or BAIL_OUT("failed to connect: $!"); + my $old_out = select($s1); + $| = 1; + select($old_out); + + my $ctx1 = Net::SSLeay::CTX_tlsv1_new(); + + my $rv = Net::SSLeay::CTX_set_alpn_protos($ctx1, ['spdy/2','http/1.1']); + push @results, [ $rv==0, 'CTX_set_alpn_protos']; + + Net::SSLeay::CTX_set_options($ctx1, &Net::SSLeay::OP_ALL); + my $ssl1 = Net::SSLeay::new($ctx1); + Net::SSLeay::set_fd($ssl1, $s1); + Net::SSLeay::connect($ssl1); + Net::SSLeay::ssl_write_all($ssl1, $msg); + + push @results, [ 'spdy/2' eq Net::SSLeay::P_alpn_selected($ssl1), 'P_alpn_selected/client']; + + Net::SSLeay::free($ssl1); + Net::SSLeay::CTX_free($ctx1); + close $s1; +} + +waitpid $pid, 0; +push @results, [$? == 0, 'server exited with 0']; +END { + Test::More->builder->current_test(3); + ok( $_->[0], $_->[1] ) for (@results); +} diff --git a/t/local/42_info_callback.t b/t/local/42_info_callback.t new file mode 100644 index 0000000..36ffdf3 --- /dev/null +++ b/t/local/42_info_callback.t @@ -0,0 +1,114 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; +use IO::Socket::INET; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +plan tests => 2; + + +my $pid; +alarm(30); +END { kill 9,$pid if $pid } + +my $server; +Net::SSLeay::initialize(); + +{ + # SSL server - just handle single connect and shutdown connection + my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); + my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + + $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3) + or BAIL_OUT("failed to create server socket: $!"); + + defined($pid = fork()) or BAIL_OUT("failed to fork: $!"); + if ($pid == 0) { + for(qw(ctx ssl)) { + my $cl = $server->accept or BAIL_OUT("accept failed: $!"); + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, fileno($cl)); + Net::SSLeay::accept($ssl); + for(1,2) { + last if Net::SSLeay::shutdown($ssl)>0; + } + } + exit; + } +} + +sub client { + my ($where,$expect) = @_; + # SSL client - connect and shutdown, all the while getting state updates + # with info callback + + my @states; + my $infocb = sub { + my ($ssl,$where,$ret) = @_; + push @states,[$where,$ret]; + }; + + my $saddr = $server->sockhost.':'.$server->sockport; + my $cl = IO::Socket::INET->new($saddr) + or BAIL_OUT("failed to connect to server: $!"); + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + Net::SSLeay::CTX_set_info_callback($ctx, $infocb) if $where eq 'ctx'; + my $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::set_info_callback($ssl, $infocb) if $where eq 'ssl'; + Net::SSLeay::connect($ssl); + for(1,2) { + last if Net::SSLeay::shutdown($ssl)>0; + } + + for my $st (@states) { + my @txt; + for(qw( + CB_READ_ALERT CB_WRITE_ALERT + CB_ACCEPT_EXIT CB_ACCEPT_LOOP + CB_CONNECT_EXIT CB_CONNECT_LOOP + CB_HANDSHAKE_START CB_HANDSHAKE_DONE + CB_READ CB_WRITE CB_ALERT + CB_LOOP CB_EXIT + )) { + my $i = eval "Net::SSLeay::$_()" + or BAIL_OUT("no state $_ known"); + if (($st->[0] & $i) == $i) { + $st->[0] &= ~$i; + push @txt,$_; + } + } + die "incomplete: @txt | $st->[0]" if $st->[0]; + $st = join("|",@txt); + } + + if ("@states" =~ $expect) { + pass("$where: @states"); + } else { + fail("$where: @states"); + } +} + +my $expect = qr{^ + CB_HANDSHAKE_START\s + (CB_CONNECT_LOOP\s)+ + CB_HANDSHAKE_DONE\s + CB_CONNECT_EXIT\b +}x; + +client('ctx',$expect); +client('ssl',$expect); +waitpid $pid, 0; + diff --git a/t/local/43_misc_functions.t b/t/local/43_misc_functions.t new file mode 100644 index 0000000..08593d6 --- /dev/null +++ b/t/local/43_misc_functions.t @@ -0,0 +1,285 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; +use IO::Socket::INET; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +my $tests = 34; +plan tests => $tests; + +my $pid; +alarm(30); +END { kill 9,$pid if $pid } + +# Values that were previously looked up for get_keyblock_size test +# Revisit: currently the only known user for get_keyblock_size is +# EAP-FAST. How it works with AEAD ciphers is for future study. +our %non_aead_cipher_to_keyblock_size = + ( + 'RC4-MD5' => 64, + 'RC4-SHA' => 72, + 'AES256-SHA256' => 160, + 'AES128-SHA256' => 128, + 'AES128-SHA' => 104, + 'AES256-SHA' => 136, + ); + +our %tls_1_2_aead_cipher_to_keyblock_size = ( + 'AES128-GCM-SHA256' => 56, + 'AES256-GCM-SHA384' => 88, + ); + +our %tls_1_3_aead_cipher_to_keyblock_size = ( + # Only in TLS 1.3 + 'TLS_AES_128_GCM_SHA256' => 56, + 'TLS_AES_256_GCM_SHA384' => 88, + 'TLS_CHACHA20_POLY1305_SHA256' => 88, + ); + +# Combine the AEAD hashes +our %aead_cipher_to_keyblock_size = (%tls_1_2_aead_cipher_to_keyblock_size, %tls_1_3_aead_cipher_to_keyblock_size); + +# Combine the hashes +our %cipher_to_keyblock_size = (%non_aead_cipher_to_keyblock_size, %aead_cipher_to_keyblock_size); + +our %version_str2int = + ( + 'SSLv3' => sub {return eval {Net::SSLeay::SSL3_VERSION();}}, + 'TLSv1' => sub {return eval {Net::SSLeay::TLS1_VERSION();}}, + 'TLSv1.1' => sub {return eval {Net::SSLeay::TLS1_1_VERSION();}}, + 'TLSv1.2' => sub {return eval {Net::SSLeay::TLS1_2_VERSION();}}, + 'TLSv1.3' => sub {return eval {Net::SSLeay::TLS1_3_VERSION();}}, + ); + +my $server; +Net::SSLeay::initialize(); + +{ + # SSL server - just handle single connect, send information to + # client and exit + + my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); + my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + + $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3) + or BAIL_OUT("failed to create server socket: $!"); + + defined($pid = fork()) or BAIL_OUT("failed to fork: $!"); + if ($pid == 0) { + my $cl = $server->accept or BAIL_OUT("accept failed: $!"); + my $ctx = Net::SSLeay::CTX_new(); + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); +# my $get_keyblock_size_ciphers = join(':', keys(%cipher_to_keyblock_size)); + my $get_keyblock_size_ciphers = join(':', keys(%non_aead_cipher_to_keyblock_size)); + Net::SSLeay::CTX_set_cipher_list($ctx, $get_keyblock_size_ciphers); + my $ssl = Net::SSLeay::new($ctx); + + Net::SSLeay::set_fd($ssl, fileno($cl)); + Net::SSLeay::accept($ssl); + + # Send our idea of Finished messages to the client. + my ($f_len, $finished_s, $finished_c); + + $f_len = Net::SSLeay::get_finished($ssl, $finished_s); + Net::SSLeay::write($ssl, "server: $f_len ". unpack('H*', $finished_s)); + + $f_len = Net::SSLeay::get_peer_finished($ssl, $finished_c); + Net::SSLeay::write($ssl, "client: $f_len ". unpack('H*', $finished_c)); + + # Echo back the termination request from client + my $end = Net::SSLeay::read($ssl); + Net::SSLeay::write($ssl, $end); + exit(0); + } +} + +sub client { + # SSL client - connect to server and receive information that we + # compare to our expected values + + my ($f_len, $f_len_trunc, $finished_s, $finished_c, $msg, $expected); + + my $saddr = $server->sockhost.':'.$server->sockport; + my $cl = IO::Socket::INET->new($saddr) + or BAIL_OUT("failed to connect to server: $!"); + my $ctx = Net::SSLeay::CTX_new(); + Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL); + my $ssl = Net::SSLeay::new($ctx); + + Net::SSLeay::set_fd($ssl, $cl); + + client_test_finished($ssl); + client_test_keyblock_size($ssl); + client_test_version_funcs($ssl); + client_test_ciphersuites(); + + # Tell the server to quit and see that our connection is still up + my $end = "end"; + Net::SSLeay::write($ssl, $end); + ok($end eq Net::SSLeay::read($ssl), 'Successful termination'); + return; +} + +client(); +waitpid $pid, 0; +exit(0); + +# Test get_finished() and get_peer_finished() with server. +sub client_test_finished +{ + my ($ssl) = @_; + my ($f_len, $f_len_trunc, $finished_s, $finished_c, $msg, $expected); + + # Finished messages have not been sent yet + $f_len = Net::SSLeay::get_peer_finished($ssl, $finished_s); + ok($f_len == 0, 'Return value for get_peer_finished is empty before connect for server'); + ok(defined $finished_s && $finished_s eq '', 'Server Finished is empty'); + + $f_len = Net::SSLeay::get_finished($ssl, $finished_c); + ok($f_len == 0, 'Finished is empty before connect for client'); + ok(defined $finished_c && $finished_c eq '', 'Client Finished is empty'); + + # Complete connection. After this we have Finished messages from both peers. + Net::SSLeay::connect($ssl); + + $f_len = Net::SSLeay::get_peer_finished($ssl, $finished_s); + ok($f_len, 'Server Finished is not empty'); + ok($f_len == length($finished_s), 'Return value for get_peer_finished equals to Finished length'); + $expected = "server: $f_len " . unpack('H*', $finished_s); + $msg = Net::SSLeay::read($ssl); + ok($msg eq $expected, 'Server Finished is equal'); + + $f_len = Net::SSLeay::get_finished($ssl, $finished_c); + ok($f_len, 'Client Finished is not empty'); + ok($f_len == length($finished_c), 'Return value for get_finished equals to Finished length'); + $expected = "client: $f_len " . unpack('H*', $finished_c); + $msg = Net::SSLeay::read($ssl); + ok($msg eq $expected, 'Client Finished is equal'); + + ok($finished_s ne $finished_c, 'Server and Client Finished are not equal'); + + # Finished should still be the same. See that we can fetch truncated values. + my $trunc8_s = substr($finished_s, 0, 8); + $f_len_trunc = Net::SSLeay::get_peer_finished($ssl, $finished_s, 8); + ok($f_len_trunc == $f_len, 'Return value for get_peer_finished is unchanged when count is set'); + ok($trunc8_s eq $finished_s, 'Count works for get_peer_finished'); + + my $trunc8_c = substr($finished_c, 0, 8); + $f_len_trunc = Net::SSLeay::get_finished($ssl, $finished_c, 8); + ok($f_len_trunc == $f_len, 'Return value for get_finished is unchanged when count is set'); + ok($trunc8_c eq $finished_c, 'Count works for get_finished'); + +} + +# Test get_keyblock_size +# Notes: With TLS 1.3 the cipher is always an AEAD cipher. If AEAD +# ciphers are enabled for TLS 1.2 and earlier, with LibreSSL +# get_keyblock_size returns -1 when AEAD cipher is chosen. +sub client_test_keyblock_size +{ + my ($ssl) = @_; + + my $cipher = Net::SSLeay::get_cipher($ssl); + ok($cipher, "get_cipher returns a value: $cipher"); + + my $keyblock_size = &Net::SSLeay::get_keyblock_size($ssl); + ok(defined $keyblock_size, 'get_keyblock_size return value is defined'); + if ($keyblock_size == -1) + { + # Accept -1 with AEAD ciphers with LibreSSL + like(Net::SSLeay::SSLeay_version(Net::SSLeay::SSLEAY_VERSION()), qr/^LibreSSL/, 'get_keyblock_size returns -1 with LibreSSL'); + ok(defined $aead_cipher_to_keyblock_size{$cipher}, 'keyblock size is -1 for an AEAD cipher'); + } + else + { + ok($keyblock_size >= 0, 'get_keyblock_size return value is not negative'); + ok($cipher_to_keyblock_size{$cipher} == $keyblock_size, "keyblock size $keyblock_size is the expected value $cipher_to_keyblock_size{$cipher}"); + } +} + +# Test SSL_get_version and related functions +sub client_test_version_funcs +{ + my ($ssl) = @_; + + my $version_str = Net::SSLeay::get_version($ssl); + my $version_const = $version_str2int{$version_str}; + my $version = Net::SSLeay::version($ssl); + + ok(defined $version_const, "Net::SSLeay::get_version return value $version_str is known"); + is(&$version_const, $version, "Net:SSLeay::version return value $version matches get_version string"); + + if (defined &Net::SSLeay::client_version) { + if ($version_str eq 'TLSv1.3') { + # Noticed that client_version and version are equal for all SSL/TLS versions except of TLSv1.3 + # For more, see https://github.com/openssl/openssl/issues/7079 + is(Net::SSLeay::client_version($ssl), &{$version_str2int{'TLSv1.2'}}, + 'Net::SSLeay::client_version TLSv1.2 is expected when Net::SSLeay::version indicates TLSv1.3'); + } else { + is(Net::SSLeay::client_version($ssl), $version, 'Net::SSLeay::client_version equals to Net::SSLeay::version'); + } + is(Net::SSLeay::is_dtls($ssl), 0, 'Net::SSLeay::is_dtls returns 0'); + } else + { + SKIP: { + skip('Do not have Net::SSLeay::client_version nor Net::SSLeay::is_dtls', 2); + }; + } + + return; +} + +sub client_test_ciphersuites +{ + unless (defined &Net::SSLeay::CTX_set_ciphersuites) + { + SKIP: { + skip('Do not have Net::SSLeay::CTX_set_ciphersuites', 10); + } + return; + } + + my $ciphersuites = join(':', keys(%tls_1_3_aead_cipher_to_keyblock_size)); + + my ($ctx, $rv, $ssl); + $ctx = Net::SSLeay::CTX_new(); + $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, $ciphersuites); + is($rv, 1, 'CTX set good ciphersuites'); + $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, ''); + is($rv, 1, 'CTX set empty ciphersuites'); + { + no warnings 'uninitialized'; + $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, undef); + }; + is($rv, 1, 'CTX set undef ciphersuites'); + $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, 'nosuchthing:' . $ciphersuites); + is($rv, 0, 'CTX set partially bad ciphersuites'); + $rv = Net::SSLeay::CTX_set_ciphersuites($ctx, 'nosuchthing:'); + is($rv, 0, 'CTX set bad ciphersuites'); + + $ssl = Net::SSLeay::new($ctx); + $rv = Net::SSLeay::set_ciphersuites($ssl, $ciphersuites); + is($rv, 1, 'SSL set good ciphersuites'); + $rv = Net::SSLeay::set_ciphersuites($ssl, ''); + is($rv, 1, 'SSL set empty ciphersuites'); + { + no warnings 'uninitialized'; + $rv = Net::SSLeay::set_ciphersuites($ssl, undef); + }; + is($rv, 1, 'SSL set undef ciphersuites'); + $rv = Net::SSLeay::set_ciphersuites($ssl, 'nosuchthing:' . $ciphersuites); + is($rv, 0, 'SSL set partially bad ciphersuites'); + $rv = Net::SSLeay::set_ciphersuites($ssl, 'nosuchthing:'); + is($rv, 0, 'SSL set bad ciphersuites'); + + return; +} diff --git a/t/local/44_sess.t b/t/local/44_sess.t new file mode 100644 index 0000000..0b0a61c --- /dev/null +++ b/t/local/44_sess.t @@ -0,0 +1,429 @@ +#!/usr/bin/perl + +# Various session related tests. Currently: +# - SSL_CTX_sess_set_get_cb and related functions + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; +use IO::Socket::INET; +use Storable; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; +} + +my $tests = 58; +plan tests => $tests; + +my $pid; +alarm(30); +END { kill 9,$pid if $pid } + +# The -end round is just for communicating stats back to client +my @rounds = qw(TLSv1 TLSv1.1 TLSv1.2 TLSv1.3 TLSv1.3-num-tickets-ssl TLSv1.3-num-tickets-ctx-6 TLSv1.3-num-tickets-ctx-0 TLSv1-end); +my (%server_stats, %client_stats); + +# Update client and server stats so that when something fails, it +# remains in failed state +sub set_client_stat +{ + my ($round, $param, $is_ok) = @_; + + if ($is_ok) { + $client_stats{$round}->{$param} = 1 unless defined $client_stats{$round}->{$param}; + return; + } + $client_stats{$round}->{$param} = 0; +} + +sub set_server_stat +{ + my ($round, $param, $is_ok) = @_; + + if ($is_ok) { + $server_stats{$round}->{$param} = 1 unless defined $server_stats{$round}->{$param}; + return; + } + $server_stats{$round}->{$param} = 0; +} + +# Separate session callbacks for client and server. The callbacks +# update stats and check that SSL_CTX, SSL and SESSION are as +# expected. +sub client_new_cb +{ + my ($ssl, $ssl_session, $expected_ctx, $round) = @_; + + $client_stats{$round}->{new_cb_called}++; + + my $ctx = Net::SSLeay::get_SSL_CTX($ssl); + my $ssl_version = Net::SSLeay::get_version($ssl); + my $is_ok = ($ctx eq $expected_ctx && + $ssl_session eq Net::SSLeay::SSL_get0_session($ssl) && + $round =~ m/^$ssl_version/); + diag("client_new_cb params not ok: $round") unless $is_ok; + set_client_stat($round, 'new_params_ok', $is_ok); + + if (defined &Net::SSLeay::SESSION_is_resumable) { + my $is_resumable = Net::SSLeay::SESSION_is_resumable($ssl_session); + BAIL_OUT("is_resumable is not 0 or 1: $round") unless defined $is_resumable && ($is_resumable == 0 || $is_resumable == 1); + set_client_stat($round, 'new_session_is_resumable', $is_resumable); + } + + #Net::SSLeay::SESSION_print_fp(*STDOUT, $ssl_session); + return 0; +} + +sub client_remove_cb +{ + my ($ctx, $ssl_session, $expected_ctx, $round) = @_; + + $client_stats{$round}->{remove_cb_called}++; + + my $is_ok = ($ctx eq $expected_ctx); + diag("client_remove_cb params not ok: $round") unless $is_ok; + set_client_stat($round, 'remove_params_ok', $is_ok); + + #Net::SSLeay::SESSION_print_fp(*STDOUT, $ssl_session); + return; +} + +sub server_new_cb +{ + my ($ssl, $ssl_session, $expected_ctx, $round) = @_; + + $server_stats{$round}->{new_cb_called}++; + + my $ctx = Net::SSLeay::get_SSL_CTX($ssl); + my $ssl_version = Net::SSLeay::get_version($ssl); + my $is_ok = ($ctx eq $expected_ctx && + $ssl_session eq Net::SSLeay::SSL_get0_session($ssl) && + $round =~ m/^$ssl_version/); + diag("server_new_cb params not ok: $round") unless $is_ok; + set_server_stat($round, 'new_params_ok', $is_ok); + + if (defined &Net::SSLeay::SESSION_is_resumable) { + my $is_resumable = Net::SSLeay::SESSION_is_resumable($ssl_session); + BAIL_OUT("is_resumable is not 0 or 1: $round") unless defined $is_resumable && ($is_resumable == 0 || $is_resumable == 1); + set_server_stat($round, 'new_session_is_resumable', $is_resumable); + } + + #Net::SSLeay::SESSION_print_fp(*STDOUT, $ssl_session); + return 0; +} + +sub server_remove_cb +{ + my ($ctx, $ssl_session, $expected_ctx, $round) = @_; + + $server_stats{$round}->{remove_cb_called}++; + + my $is_ok = ($ctx eq $expected_ctx); + diag("server_remove_cb params not ok: $round") unless $is_ok; + set_server_stat($round, 'remove_params_ok', $is_ok); + + return; +} + +my ($server, $server_ctx, $client_ctx, $server_ssl, $client_ssl); +Net::SSLeay::initialize(); + +# Helper for client and server +sub make_ctx +{ + my ($round) = @_; + + my $ctx; + if ($round =~ /^TLSv1\.3/) { + return undef unless eval { Net::SSLeay::TLS1_3_VERSION(); }; + + # Use API introduced in OpenSSL 1.1.0 + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLS_method()); + Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION()); + Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION()); + } + elsif ($round =~ /^TLSv1\.2/) { + return undef unless exists &Net::SSLeay::TLSv1_2_method; + + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_2_method()); + } + elsif ($round =~ /^TLSv1\.1/) { + return undef unless exists &Net::SSLeay::TLSv1_1_method; + + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_1_method()); + } + else + { + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_method()); + } + + return $ctx; +} + +sub server +{ + # SSL server - just handle connections, send information to + # client and exit + my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); + my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + + $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3) + or BAIL_OUT("failed to create server socket: $!"); + + defined($pid = fork()) or BAIL_OUT("failed to fork: $!"); + if ($pid == 0) { + my ($ctx, $ssl, $ret, $cl); + + foreach my $round (@rounds) + { + $cl = $server->accept or BAIL_OUT("accept failed: $!"); + + $ctx = make_ctx($round); + next unless $ctx; + + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + Net::SSLeay::CTX_set_session_cache_mode($ctx, Net::SSLeay::SESS_CACHE_SERVER()); + # Need OP_NO_TICKET to enable server side (Session ID based) resumption. + # See also SSL_CTX_set_options documenation about its use with TLSv1.3 + Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL() | Net::SSLeay::OP_NO_TICKET()) + if ($round !~ /^TLSv1\.3/); + + Net::SSLeay::CTX_sess_set_new_cb($ctx, sub {server_new_cb(@_, $ctx, $round);}); + Net::SSLeay::CTX_sess_set_remove_cb($ctx, sub {server_remove_cb(@_, $ctx, $round);}); + + # Test set_num_tickets separately for CTX and SSL + if (defined &Net::SSLeay::CTX_set_num_tickets) + { + Net::SSLeay::CTX_set_num_tickets($ctx, 6) if ($round eq 'TLSv1.3-num-tickets-ctx-6'); + Net::SSLeay::CTX_set_num_tickets($ctx, 0) if ($round eq 'TLSv1.3-num-tickets-ctx-0'); + $server_stats{$round}->{get_num_tickets} = Net::SSLeay::CTX_get_num_tickets($ctx); + } + + $ssl = Net::SSLeay::new($ctx); + if (defined &Net::SSLeay::set_num_tickets) + { + Net::SSLeay::set_num_tickets($ssl, 4) if ($round eq 'TLSv1.3-num-tickets-ssl'); + $server_stats{$round}->{get_num_tickets} = Net::SSLeay::get_num_tickets($ssl); + } + Net::SSLeay::set_fd($ssl, fileno($cl)); + Net::SSLeay::accept($ssl); + + Net::SSLeay::write($ssl, "msg from server: $round"); + my $end = Net::SSLeay::read($ssl); + #print "client said: $end\n"; + if ($end eq 'end') + { + Net::SSLeay::write($ssl, $end); + Net::SSLeay::write($ssl, Storable::freeze(\%server_stats)); + } + Net::SSLeay::shutdown($ssl); + my $sess = Net::SSLeay::get1_session($ssl); + $ret = Net::SSLeay::CTX_remove_session($ctx, $sess); + + if (defined &Net::SSLeay::SESSION_is_resumable) { + my $is_resumable = Net::SSLeay::SESSION_is_resumable($sess); + BAIL_OUT("is_resumable is not 0 or 1: $round") unless defined $is_resumable && ($is_resumable == 0 || $is_resumable == 1); + set_server_stat($round, 'old_session_is_resumable', $is_resumable); + } + + Net::SSLeay::SESSION_free($sess) unless $ret; # Not cached, undo get1 + Net::SSLeay::free($ssl); + } + #use Data::Dumper; print "Server:\n" . Dumper(\%server_stats); + exit(0); + } +} + +sub client { + # SSL client - connect to server and receive information that we + # compare to our expected values + + my $saddr = $server->sockhost.':'.$server->sockport; + my ($ctx, $ssl, $ret, $cl); + my $end = "end"; + + foreach my $round (@rounds) + { + $cl = IO::Socket::INET->new($saddr) + or BAIL_OUT("failed to connect to server: $!"); + + $ctx = make_ctx($round); + next unless $ctx; + + Net::SSLeay::CTX_set_session_cache_mode($ctx, Net::SSLeay::SESS_CACHE_CLIENT()); + Net::SSLeay::CTX_set_options($ctx, Net::SSLeay::OP_ALL()); + Net::SSLeay::CTX_sess_set_new_cb($ctx, sub {client_new_cb(@_, $ctx, $round);}); + Net::SSLeay::CTX_sess_set_remove_cb($ctx, sub {client_remove_cb(@_, $ctx, $round);}); + $ssl = Net::SSLeay::new($ctx); + + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::connect($ssl); + my $msg = Net::SSLeay::read($ssl); + #print "server said: $msg\n"; + if ($round =~ /end/) + { + Net::SSLeay::write($ssl, $end); + last; + } + + Net::SSLeay::write($ssl, "continue"); + my $sess = Net::SSLeay::get1_session($ssl); + $ret = Net::SSLeay::CTX_remove_session($ctx, $sess); + Net::SSLeay::SESSION_free($sess) unless $ret; # Not cached, undo get1 + + if (defined &Net::SSLeay::SESSION_is_resumable) { + my $is_resumable = Net::SSLeay::SESSION_is_resumable($sess); + BAIL_OUT("is_resumable is not 0 or 1: $round") unless defined $is_resumable && ($is_resumable == 0 || $is_resumable == 1); + set_client_stat($round, 'old_session_is_resumable', $is_resumable); + } + + Net::SSLeay::shutdown($ssl); + Net::SSLeay::free($ssl); + } + + # Server should have acked our end request. Also see that our connection is still up + my $server_end = Net::SSLeay::read($ssl); + is($server_end, $end, "Successful termination"); + + # Stats from server + my $server_stats_ref = Storable::thaw(Net::SSLeay::read($ssl)); + + my $sess = Net::SSLeay::get1_session($ssl); + $ret = Net::SSLeay::CTX_remove_session($ctx, $sess); + Net::SSLeay::SESSION_free($sess) unless $ret; # Not cached, undo get1 + Net::SSLeay::shutdown($ssl); + Net::SSLeay::free($ssl); + + test_stats($server_stats_ref, \%client_stats); + + return; +} + +sub test_stats +{ + my ($srv_stats, $clt_stats) = @_; + + is($srv_stats->{'TLSv1'}->{new_cb_called}, 1, 'Server TLSv1 new_cb call count'); + is($srv_stats->{'TLSv1'}->{new_params_ok}, 1, 'Server TLSv1 new_cb params were correct'); + is($srv_stats->{'TLSv1'}->{remove_cb_called}, 1, 'Server TLSv1 remove_cb call count'); + is($srv_stats->{'TLSv1'}->{remove_params_ok}, 1, 'Server TLSv1 remove_cb params were correct'); + + is($clt_stats->{'TLSv1'}->{new_cb_called}, 1, 'Client TLSv1 new_cb call count'); + is($clt_stats->{'TLSv1'}->{new_params_ok}, 1, 'Client TLSv1 new_cb params were correct'); + is($clt_stats->{'TLSv1'}->{remove_cb_called}, 1, 'Client TLSv1 remove_cb call count'); + is($clt_stats->{'TLSv1'}->{remove_params_ok}, 1, 'Client TLSv1 remove_cb params were correct'); + + if (defined &Net::SSLeay::SESSION_is_resumable) { + is($srv_stats->{'TLSv1'}->{new_session_is_resumable}, 1, 'Server TLSv1 session is resumable'); + is($srv_stats->{'TLSv1'}->{old_session_is_resumable}, 0, 'Server TLSv1 session is no longer resumable'); + + is($clt_stats->{'TLSv1'}->{new_session_is_resumable}, 1, 'Client TLSv1 session is resumable'); + is($clt_stats->{'TLSv1'}->{old_session_is_resumable}, 0, 'Client TLSv1 session is no longer resumable'); + } else { + SKIP: { + skip('Do not have Net::SSLeay::SESSION_is_resumable', 4); + } + } + + if (exists &Net::SSLeay::TLSv1_1_method) + { + # Should be the same as TLSv1 + is($srv_stats->{'TLSv1.1'}->{new_cb_called}, 1, 'Server TLSv1.1 new_cb call count'); + is($srv_stats->{'TLSv1.1'}->{new_params_ok}, 1, 'Server TLSv1.1 new_cb params were correct'); + is($srv_stats->{'TLSv1.1'}->{remove_cb_called}, 1, 'Server TLSv1.1 remove_cb call count'); + is($srv_stats->{'TLSv1.1'}->{remove_params_ok}, 1, 'Server TLSv1.1 remove_cb params were correct'); + if (defined &Net::SSLeay::SESSION_is_resumable) { + is($srv_stats->{'TLSv1.1'}->{new_session_is_resumable}, 1, 'Server TLSv1.1 session is resumable'); + is($srv_stats->{'TLSv1.1'}->{old_session_is_resumable}, 0, 'Server TLSv1.1 session is no longer resumable'); + + is($clt_stats->{'TLSv1.1'}->{new_session_is_resumable}, 1, 'Client TLSv1.1 session is resumable'); + is($clt_stats->{'TLSv1.1'}->{old_session_is_resumable}, 0, 'Client TLSv1.1 session is no longer resumable'); + } else { + SKIP: { + skip('Do not have Net::SSLeay::SESSION_is_resumable', 4); + } + } + + is($clt_stats->{'TLSv1.1'}->{new_cb_called}, 1, 'Client TLSv1.1 new_cb call count'); + is($clt_stats->{'TLSv1.1'}->{new_params_ok}, 1, 'Client TLSv1.1 new_cb params were correct'); + is($clt_stats->{'TLSv1.1'}->{remove_cb_called}, 1, 'Client TLSv1.1 remove_cb call count'); + is($clt_stats->{'TLSv1.1'}->{remove_params_ok}, 1, 'Client TLSv1.1 remove_cb params were correct'); + } else { + SKIP: { + skip('Do not have support for TLSv1.1', 12); + } + } + + if (exists &Net::SSLeay::TLSv1_2_method) + { + # Should be the same as TLSv1 + is($srv_stats->{'TLSv1.2'}->{new_cb_called}, 1, 'Server TLSv1.2 new_cb call count'); + is($srv_stats->{'TLSv1.2'}->{new_params_ok}, 1, 'Server TLSv1.2 new_cb params were correct'); + is($srv_stats->{'TLSv1.2'}->{remove_cb_called}, 1, 'Server TLSv1.2 remove_cb call count'); + is($srv_stats->{'TLSv1.2'}->{remove_params_ok}, 1, 'Server TLSv1.2 remove_cb params were correct'); + if (defined &Net::SSLeay::SESSION_is_resumable) { + is($srv_stats->{'TLSv1.2'}->{new_session_is_resumable}, 1, 'Server TLSv1.2 session is resumable'); + is($srv_stats->{'TLSv1.2'}->{old_session_is_resumable}, 0, 'Server TLSv1.2 session is no longer resumable'); + + is($clt_stats->{'TLSv1.2'}->{new_session_is_resumable}, 1, 'Client TLSv1.2 session is resumable'); + is($clt_stats->{'TLSv1.2'}->{old_session_is_resumable}, 0, 'Client TLSv1.2 session is no longer resumable'); + } else { + SKIP: { + skip('Do not have Net::SSLeay::SESSION_is_resumable', 4); + } + } + + is($clt_stats->{'TLSv1.2'}->{new_cb_called}, 1, 'Client TLSv1.2 new_cb call count'); + is($clt_stats->{'TLSv1.2'}->{new_params_ok}, 1, 'Client TLSv1.2 new_cb params were correct'); + is($clt_stats->{'TLSv1.2'}->{remove_cb_called}, 1, 'Client TLSv1.2 remove_cb call count'); + is($clt_stats->{'TLSv1.2'}->{remove_params_ok}, 1, 'Client TLSv1.2 remove_cb params were correct'); + } else { + SKIP: { + skip('Do not have support for TLSv1.2', 12); + } + } + + if (eval { Net::SSLeay::TLS1_3_VERSION(); }) + { + # OpenSSL sends two session tickets by default: new_cb called two times + is($srv_stats->{'TLSv1.3'}->{new_cb_called}, 2, 'Server TLSv1.3 new_cb call count'); + is($srv_stats->{'TLSv1.3'}->{new_params_ok}, 1, 'Server TLSv1.3 new_cb params were correct'); + is($srv_stats->{'TLSv1.3'}->{remove_cb_called}, 1, 'Server TLSv1.3 remove_cb call count'); + is($srv_stats->{'TLSv1.3'}->{remove_params_ok}, 1, 'Server TLSv1.3 remove_cb params were correct'); + is($srv_stats->{'TLSv1.3-num-tickets-ssl'}->{get_num_tickets}, 4, 'Server TLSv1.3 get_num_tickets 4'); + is($srv_stats->{'TLSv1.3-num-tickets-ssl'}->{new_cb_called}, 4, 'Server TLSv1.3 new_cb call count with set_num_tickets 4'); + is($srv_stats->{'TLSv1.3-num-tickets-ctx-6'}->{get_num_tickets}, 6, 'Server TLSv1.3 CTX_get_num_tickets 6'); + is($srv_stats->{'TLSv1.3-num-tickets-ctx-6'}->{new_cb_called}, 6, 'Server TLSv1.3 new_cb call count with CTX_set_num_tickets 6'); + is($srv_stats->{'TLSv1.3-num-tickets-ctx-0'}->{get_num_tickets}, 0, 'Server TLSv1.3 CTX_get_num_tickets 0'); + is($srv_stats->{'TLSv1.3-num-tickets-ctx-0'}->{new_cb_called}, undef, 'Server TLSv1.3 new_cb call count with CTX_set_num_tickets 0'); + is($srv_stats->{'TLSv1.3'}->{new_session_is_resumable}, 1, 'Server TLSv1.3 session is resumable'); + is($srv_stats->{'TLSv1.3'}->{old_session_is_resumable}, 0, 'Server TLSv1.3 session is no longer resumable'); + + is($clt_stats->{'TLSv1.3'}->{new_cb_called}, 2, 'Client TLSv1.3 new_cb call count'); + is($clt_stats->{'TLSv1.3'}->{new_params_ok}, 1, 'Client TLSv1.3 new_cb params were correct'); + is($clt_stats->{'TLSv1.3'}->{remove_cb_called}, 1, 'Client TLSv1.3 remove_cb call count'); + is($clt_stats->{'TLSv1.3'}->{remove_params_ok}, 1, 'Client TLSv1.3 remove_cb params were correct'); + is($clt_stats->{'TLSv1.3-num-tickets-ssl'}->{new_cb_called}, 4, 'Client TLSv1.3 new_cb call count with set_num_tickets 4'); + is($clt_stats->{'TLSv1.3-num-tickets-ctx-6'}->{new_cb_called}, 6, 'Client TLSv1.3 new_cb call count with CTX_set_num_tickets 6'); + is($clt_stats->{'TLSv1.3-num-tickets-ctx-0'}->{new_cb_called}, undef, 'Client TLSv1.3 new_cb call count with CTX_set_num_tickets 0'); + is($clt_stats->{'TLSv1.3'}->{new_session_is_resumable}, 1, 'Client TLSv1.3 session is resumable'); + is($clt_stats->{'TLSv1.3'}->{old_session_is_resumable}, 0, 'Client TLSv1.3 session is no longer resumable'); + } else { + SKIP: { + skip('Do not have support for TLSv1.3', 21); + } + } + + # use Data::Dumper; print "Server:\n" . Dumper(\%srv_stats); + # use Data::Dumper; print "Client:\n" . Dumper(\%clt_stats); +} + +server(); +client(); +waitpid $pid, 0; +exit(0); diff --git a/t/local/45_exporter.t b/t/local/45_exporter.t new file mode 100644 index 0000000..fd7d6a7 --- /dev/null +++ b/t/local/45_exporter.t @@ -0,0 +1,193 @@ +#!/usr/bin/perl + +# Various TLS exporter related tests. + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; +use IO::Socket::INET; +use Storable; + +BEGIN { + plan skip_all => "fork() not supported on $^O" unless $Config{d_fork}; + plan skip_all => "No export_keying_material()" unless defined &Net::SSLeay::export_keying_material; + +} + +my $tests = 36; +plan tests => $tests; + +my $pid; +alarm(30); +END { kill 9,$pid if $pid } + +my @rounds = qw(TLSv1 TLSv1.1 TLSv1.2 TLSv1.3); +my (%server_stats, %client_stats); + +my ($server, $server_ctx, $client_ctx, $server_ssl, $client_ssl); +Net::SSLeay::initialize(); + +# Helper for client and server +sub make_ctx +{ + my ($round) = @_; + + my $ctx; + if ($round =~ /^TLSv1\.3/) { + return undef unless eval { Net::SSLeay::TLS1_3_VERSION(); }; + + # Use API introduced in OpenSSL 1.1.0 + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLS_method()); + Net::SSLeay::CTX_set_min_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION()); + Net::SSLeay::CTX_set_max_proto_version($ctx, Net::SSLeay::TLS1_3_VERSION()); + } + elsif ($round =~ /^TLSv1\.2/) { + return undef unless exists &Net::SSLeay::TLSv1_2_method; + + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_2_method()); + } + elsif ($round =~ /^TLSv1\.1/) { + return undef unless exists &Net::SSLeay::TLSv1_1_method; + + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_1_method()); + } + else + { + $ctx = Net::SSLeay::CTX_new_with_method(Net::SSLeay::TLSv1_method()); + } + + return $ctx; +} + +sub server +{ + # SSL server - just handle connections, write, wait for read and repeat + my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'); + my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + + $server = IO::Socket::INET->new( LocalAddr => '127.0.0.1', Listen => 3) + or BAIL_OUT("failed to create server socket: $!"); + + defined($pid = fork()) or BAIL_OUT("failed to fork: $!"); + if ($pid == 0) { + my ($ctx, $ssl, $ret, $cl); + + foreach my $round (@rounds) + { + $cl = $server->accept or BAIL_OUT("accept failed: $!"); + + $ctx = make_ctx($round); + next unless $ctx; + + Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem); + $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, fileno($cl)); + Net::SSLeay::accept($ssl); + + Net::SSLeay::write($ssl, $round); + my $msg = Net::SSLeay::read($ssl); + + Net::SSLeay::shutdown($ssl); + Net::SSLeay::free($ssl); + } + exit(0); + } +} + +sub client { + # SSL client - connect to server, read, test and repeat + + my $saddr = $server->sockhost.':'.$server->sockport; + my ($ctx, $ssl, $ret, $cl); + my $end = "end"; + + foreach my $round (@rounds) + { + $cl = IO::Socket::INET->new($saddr) + or BAIL_OUT("failed to connect to server: $!"); + + $ctx = make_ctx($round); + unless($ctx) { + SKIP: { + skip("Skipping round $round", 9); + } + next; + } + + $ssl = Net::SSLeay::new($ctx); + Net::SSLeay::set_fd($ssl, $cl); + Net::SSLeay::connect($ssl); + my $msg = Net::SSLeay::read($ssl); + + test_export($ssl); + + Net::SSLeay::write($ssl, $msg); + + Net::SSLeay::shutdown($ssl); + Net::SSLeay::free($ssl); + } + + return; +} + +sub test_export +{ + my ($ssl) = @_; + + my ($bytes1_0, $bytes1_1, $bytes1_2, $bytes1_3, $bytes2_0, $bytes2_2_64); + + my $tls_version = Net::SSLeay::get_version($ssl); + + $bytes1_0 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1'); + $bytes1_1 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1', undef); + $bytes1_2 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1', ''); + $bytes1_3 = Net::SSLeay::export_keying_material($ssl, 64, 'label 1', 'context'); + $bytes2_0 = Net::SSLeay::export_keying_material($ssl, 128, 'label 1', ''); + $bytes2_2_64 = substr($bytes2_0, 0, 64); + + is(length($bytes1_0), 64, "$tls_version: Got enough for bytes1_0"); + is(length($bytes1_1), 64, "$tls_version: Got enough for bytes1_1"); + is(length($bytes1_2), 64, "$tls_version: Got enough for bytes1_2"); + is(length($bytes1_3), 64, "$tls_version: Got enough for bytes1_3"); + is(length($bytes2_0), 128, "$tls_version: Got enough for bytes2_0"); + + $bytes1_0 = unpack('H*', $bytes1_0); + $bytes1_1 = unpack('H*', $bytes1_1); + $bytes1_2 = unpack('H*', $bytes1_2); + $bytes1_3 = unpack('H*', $bytes1_3); + $bytes2_0 = unpack('H*', $bytes2_0); + $bytes2_2_64 = unpack('H*', $bytes2_2_64); + + # Last argument should default to undef + is($bytes1_0, $bytes1_1, "$tls_version: context default param is undef"); + + # Empty and undefined context are the same for TLSv1.3. + # Different length export changes the whole values for TLSv1.3. + if ($tls_version eq 'TLSv1.3') { + is($bytes1_0, $bytes1_2, "$tls_version: empty and undefined context yields equal values"); + isnt($bytes2_2_64, $bytes1_2, "$tls_version: export length does matter"); + } else { + isnt($bytes1_0, $bytes1_2, "$tls_version: empty and undefined context yields different values"); + is($bytes2_2_64, $bytes1_2, "$tls_version: export length does not matter"); + } + + isnt($bytes1_3, $bytes1_0, "$tls_version: different context"); + + return; +} + +# For SSL_export_keying_material_early available with TLSv1.3 +sub test_export_early +{ + + return; +} + +server(); +client(); +waitpid $pid, 0; +exit(0); diff --git a/t/local/50_digest.t b/t/local/50_digest.t new file mode 100644 index 0000000..f223c34 --- /dev/null +++ b/t/local/50_digest.t @@ -0,0 +1,299 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More tests => 203; +use File::Spec; +use Net::SSLeay; + +sub digest_chunked_f1 { + my ($file, $digest) = @_; + + my $md = Net::SSLeay::EVP_get_digestbyname($digest) or BAIL_OUT "digest '$digest' not available"; + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + Net::SSLeay::EVP_DigestInit($ctx, $md); + + open my $fh, "<", $file or BAIL_OUT "cannot open file '$file'"; + binmode $fh; + while(my $len = sysread($fh, my $chunk, 500)) { + Net::SSLeay::EVP_DigestUpdate($ctx,$chunk); + } + close $fh; + + my $result = Net::SSLeay::EVP_DigestFinal($ctx); + Net::SSLeay::EVP_MD_CTX_destroy($ctx); + + return $result; +} + +sub digest_chunked_f2 { + my ($file, $digest) = @_; + + my $md = Net::SSLeay::EVP_get_digestbyname($digest) or BAIL_OUT "digest '$digest' not available"; + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + Net::SSLeay::EVP_DigestInit_ex($ctx, $md, 0); #NULL ENGINE just to test whether the function exists + + open my $fh, "<", $file or BAIL_OUT "cannot open file '$file'"; + binmode $fh; + while(my $len = sysread($fh, my $chunk, 5)) { + Net::SSLeay::EVP_DigestUpdate($ctx,$chunk); + } + close $fh; + + my $result = Net::SSLeay::EVP_DigestFinal_ex($ctx); + Net::SSLeay::EVP_MD_CTX_destroy($ctx); + + return $result; +} + +sub digest_file { + my ($file, $expected_results, $available_digests) = @_; + + for my $d (sort keys %$expected_results) { + SKIP: { + skip "digest '$d' not available (or pre-1.0.0)", 2 unless $available_digests->{$d}; + is( unpack("H*", digest_chunked_f1($file, $d)), $expected_results->{$d}, "$d chunked.1 [$file]"); + is( unpack("H*", digest_chunked_f2($file, $d)), $expected_results->{$d}, "$d chunked.2 [$file]"); + } + } + + open my $f, "<", $file or BAIL_OUT "cannot open file '$file'"; + binmode $f; + sysread($f, my $data, -s $file) or BAIL_OUT "sysread failed"; + close $f; + + is(length($data), -s $file, 'got the whole file'); + + SKIP: { + skip "Net::SSLeay::MD2 not available", 1 + unless exists &Net::SSLeay::MD2 and exists $available_digests->{md2}; + is( unpack("H*", Net::SSLeay::MD2($data)), $expected_results->{md2}, "MD2 all-in-one-go [$file]"); + } + SKIP: { + skip "Net::SSLeay::MD4 not available", 1 + unless exists &Net::SSLeay::MD4 and exists $available_digests->{md4}; + is( unpack("H*", Net::SSLeay::MD4($data)), $expected_results->{md4}, "MD4 all-in-one-go [$file]"); + } + SKIP: { + skip "Net::SSLeay::MD5 not available", 1 + unless exists &Net::SSLeay::MD5 and exists $available_digests->{md5}; + is( unpack("H*", Net::SSLeay::MD5($data)), $expected_results->{md5}, "MD5 all-in-one-go [$file]"); + } + SKIP: { + skip "Net::SSLeay::RIPEMD160 not available", 1 + unless exists &Net::SSLeay::RIPEMD160 and + exists $available_digests->{ripemd160}; + is( unpack("H*", Net::SSLeay::RIPEMD160($data)), $expected_results->{ripemd160}, "RIPEMD160 all-in-one-go [$file]"); + } +} + +sub digest_strings { + my ($fps, $available_digests) = @_; + + for my $data (sort keys %$fps) { + + for my $d (sort keys %{$fps->{$data}}) { + SKIP: { + skip "digest '$d' not available (or pre-1.0.0)", 2 unless $available_digests->{$d}; + my $md = Net::SSLeay::EVP_get_digestbyname($d) or BAIL_OUT "digest '$d' not available"; + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + Net::SSLeay::EVP_DigestInit($ctx, $md); + Net::SSLeay::EVP_DigestUpdate($ctx, $data); + my $result1 = Net::SSLeay::EVP_DigestFinal($ctx); + Net::SSLeay::EVP_MD_CTX_destroy($ctx); + is(unpack('H*', $result1), $fps->{$data}->{$d}, "$d for '$data'"); + # test EVP_Digest + my $result2 = Net::SSLeay::EVP_Digest($data, Net::SSLeay::EVP_get_digestbyname($d)); + is(unpack('H*', $result2), $fps->{$data}->{$d}, "EVP_Digest($d)"); + } + } + + + + SKIP: { + skip "Net::SSLeay::MD2 not available", 1 + unless exists &Net::SSLeay::MD2 and exists $available_digests->{md2}; + is(unpack('H*', Net::SSLeay::MD2($data)), $fps->{$data}->{md2}, "MD2 hash for '$data'"); + } + SKIP: { + skip "Net::SSLeay::MD4 not available", 1 + unless exists &Net::SSLeay::MD4 and exists $available_digests->{md4}; + is(unpack('H*', Net::SSLeay::MD4($data)), $fps->{$data}->{md4}, "MD4 hash for '$data'"); + } + SKIP: { + skip "Net::SSLeay::MD5 not available", 1 + unless exists &Net::SSLeay::MD5 and exists $available_digests->{md5}; + is(unpack('H*', Net::SSLeay::MD5($data)), $fps->{$data}->{md5}, "MD5 hash for '$data'"); + } + SKIP: { + skip "Net::SSLeay::RIPEMD160 not available", 1 + unless exists &Net::SSLeay::RIPEMD160 and + exists $available_digests->{ripemd160}; + is(unpack('H*', Net::SSLeay::RIPEMD160($data)), $fps->{$data}->{ripemd160}, "RIPEMD160 hash for '$data'"); + } + + SKIP: { + skip "Net::SSLeay::SHA1 not available", 1 + unless exists &Net::SSLeay::SHA1 and exists $available_digests->{sha1}; + is(unpack('H*', Net::SSLeay::SHA1($data)), $fps->{$data}->{sha1}, "SHA1 hash for '$data'"); + } + SKIP: { + skip "Net::SSLeay::SHA256 not available", 1 + unless exists &Net::SSLeay::SHA256 and + exists $available_digests->{sha256}; + is(unpack('H*', Net::SSLeay::SHA256($data)), $fps->{$data}->{sha256}, "SHA256 hash for '$data'"); + } + SKIP: { + skip "Net::SSLeay::SHA512 not available", 1 + unless exists &Net::SSLeay::SHA512 and + exists $available_digests->{sha512}; + is(unpack('H*', Net::SSLeay::SHA512($data)), $fps->{$data}->{sha512}, "SHA512 hash for '$data'"); + } + } +} + +my %all_digests; + +eval { + Net::SSLeay::initialize(); + Net::SSLeay::OpenSSL_add_all_digests(); + if (Net::SSLeay::SSLeay >= 0x1000000f) { + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + %all_digests = map { $_=>1 } grep { + # P_EVP_MD_list_all() does not remove digests disabled in FIPS + my $md; + $md = Net::SSLeay::EVP_get_digestbyname($_) and + Net::SSLeay::EVP_DigestInit($ctx, $md) + } @{Net::SSLeay::P_EVP_MD_list_all()}; + } + else { + %all_digests = (); + } +}; + +is($@, '', 'digest init OK'); +SKIP: { + skip "pre-1.0.0", 1 unless Net::SSLeay::SSLeay >= 0x1000000f; + isnt(scalar(keys %all_digests), 0, 'non-empty digest list'); +} + +my $file = File::Spec->catfile('t', 'data', 'binary-test.file'); +my $file_digests = { + md2 => '67ae6d821be6898101414c56b1fb4f46', + md4 => '480438696e7d9a6ab3ecc1e2a3419f78', + md5 => 'cc89b43c171818c347639fa5170aee16', + mdc2 => 'ee605fe3fc966a7b17185ebdbcd13ada', + ripemd160 => 'cb70ba43fc6d263f6d7816170c1a33f28c2000fe', + sha => 'c151c6f408cb94bc5c53b17852efbe8bfbeec2b9', + sha1 => '059404d1d0e952d0457a6c99b6e68b3b44c8ef13', + sha224 => '161c65efa1b9762f7e0448b5b369a3e2c236876b0b57a35add5106bb', + sha256 => 'e416730ddaa34729adb32ec6ddad4e50fca1fe97de313e800196b1f8cd5032bd', + sha512 => '8b5e7181fc76d49e1cb7971a6980b5d8db6b23c3b0553cf42f559156fd08e64567d17c4147c864efd4d3a5e22fb6602d613a055f7f14faad22744dbc3df89d59', + whirlpool => '31079767aa2dd9b8ab01caadd954a88aaaf6001941c38d17ba43c0ef80a074c3eedf35b73c3941929dea281805c6c5ffc0a619abef4c6a3365d6cb31412d0e0c', +}; + +my %fps = ( + '' => { + md2 => '8350e5a3e24c153df2275c9f80692773', + md4 => '31d6cfe0d16ae931b73c59d7e0c089c0', + md5 => 'd41d8cd98f00b204e9800998ecf8427e', + ripemd160 => '9c1185a5c5e9fc54612808977ee8f548b2258d31', + sha1 => 'da39a3ee5e6b4b0d3255bfef95601890afd80709', + sha256 => 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', + sha512 => 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', + }, + 'a' => { + md2 => '32ec01ec4a6dac72c0ab96fb34c0b5d1', + md4 => 'bde52cb31de33e46245e05fbdbd6fb24', + md5 => '0cc175b9c0f1b6a831c399e269772661', + ripemd160 => '0bdc9d2d256b3ee9daae347be6f4dc835a467ffe', + sha1=>'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', + sha256=>'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', + sha512=>'1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75', + }, + '38' => { + md2 => '4b85c826321a5ce87db408c908d0709e', + md4 => 'ae9c7ebfb68ea795483d270f5934b71d', + md5 => 'a5771bce93e200c36f7cd9dfd0e5deaa', + ripemd160 => '6b2d075b1cd34cd1c3e43a995f110c55649dad0e', + sha1=>'5b384ce32d8cdef02bc3a139d4cac0a22bb029e8', + sha256=>'aea92132c4cbeb263e6ac2bf6c183b5d81737f179f21efdc5863739672f0f470', + sha512=>'caae34a5e81031268bcdaf6f1d8c04d37b7f2c349afb705b575966f63e2ebf0fd910c3b05160ba087ab7af35d40b7c719c53cd8b947c96111f64105fd45cc1b2', + }, + 'abc' => { + md2 => 'da853b0d3f88d99b30283a69e6ded6bb', + md4 => 'a448017aaf21d8525fc10ae87aa6729d', + md5 => '900150983cd24fb0d6963f7d28e17f72', + ripemd160 => '8eb208f7e05d987a9b044a8e98c6b087f15a0bfc', + sha1=>'a9993e364706816aba3e25717850c26c9cd0d89d', + sha256=>'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', + sha512=>'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', + }, + 'message digest' => { + md2 => 'ab4f496bfb2a530b219ff33031fe06b0', + md4 => 'd9130a8164549fe818874806e1c7014b', + md5 => 'f96b697d7cb7938d525a2f31aaf161d0', + ripemd160 => '5d0689ef49d2fae572b881b123a85ffa21595f36', + sha1=>'c12252ceda8be8994d5fa0290a47231c1d16aae3', + sha256=>'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650', + sha512=>'107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c', + }, + 'abcdefghijklmnopqrstuvwxyz' => { + md2 => '4e8ddff3650292ab5a4108c3aa47940b', + md4 => 'd79e1c308aa5bbcdeea8ed63df412da9', + md5 => 'c3fcd3d76192e4007dfb496cca67e13b', + ripemd160 => 'f71c27109c692c1b56bbdceb5b9d2865b3708dbc', + sha1=>'32d10c7b8cf96570ca04ce37f2a19d84240d3a89', + sha256=>'71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73', + sha512=>'4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1', + }, + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' => { + md2 => 'da33def2a42df13975352846c30338cd', + md4 => '043f8582f241db351ce627e153e7f0e4', + md5 => 'd174ab98d277d9f5a5611c2c9f419d9f', + ripemd160 => 'b0e20b6e3116640286ed3a87a5713079b21f5189', + sha1=>'761c457bf73b14d27e9e9265c46f4b4dda11f940', + sha256=>'db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0', + sha512=>'1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894', + }, + '12345678901234567890123456789012345678901234567890123456789012345678901234567890' => { + md2 => 'd5976f79d83d3a0dc9806c3c66f3efd8', + md4 => 'e33b4ddc9c38f2199c3e7b164fcc0536', + md5 => '57edf4a22be3c955ac49da2e2107b67a', + ripemd160 => '9b752e45573d4b39f4dbd3323cab82bf63326bfb', + sha1=>'50abf5706a150990a08b2c5ea40fa0e585554732', + sha256=>'f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e', + sha512=>'72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843', + }, +); + +SKIP: { + skip "MD5 not available", 3 unless exists &Net::SSLeay::MD5; + is(Net::SSLeay::EVP_MD_type(Net::SSLeay::EVP_get_digestbyname("MD5")), 4, 'EVP_MD_type md5'); + is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_get_digestbyname("MD5")), 16, 'EVP_MD_size md5'); + + SKIP: { + skip "pre-0.9.7", 1 unless Net::SSLeay::SSLeay >= 0x0090700f; + my $md = Net::SSLeay::EVP_get_digestbyname("md5"); + my $ctx = Net::SSLeay::EVP_MD_CTX_create(); + skip "MD5 not available", 1 unless Net::SSLeay::EVP_DigestInit($ctx, $md); + my $md2 = Net::SSLeay::EVP_MD_CTX_md($ctx); + is(Net::SSLeay::EVP_MD_size($md2), 16, 'EVP_MD_size via EVP_MD_CTX_md md5'); + } +} + +SKIP: { + skip "Net::SSLeay::EVP_sha512 not available", 1 unless exists &Net::SSLeay::EVP_sha512; + is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_sha512()), 64, 'EVP_MD_size sha512'); +} +SKIP: { + skip "Net::SSLeay::EVP_sha256 not available", 1 unless exists &Net::SSLeay::EVP_sha256; + is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_sha256()), 32, 'EVP_MD_size sha256'); +} +SKIP: { + skip "Net::SSLeay::EVP_sha1 not available", 1 unless exists &Net::SSLeay::EVP_sha1; + is(Net::SSLeay::EVP_MD_size(Net::SSLeay::EVP_sha1()), 20, 'EVP_MD_size sha1'); +} + +digest_file($file, $file_digests, \%all_digests); +digest_strings(\%fps, \%all_digests); diff --git a/t/local/61_threads-cb-crash.t b/t/local/61_threads-cb-crash.t new file mode 100644 index 0000000..65fa9a8 --- /dev/null +++ b/t/local/61_threads-cb-crash.t @@ -0,0 +1,69 @@ +use strict; +use warnings; +use Config; +use Test::More; + +BEGIN { + plan skip_all => "your perl is not compiled with ithreads" unless $Config{useithreads}; + require threads; +}; + +#XXX-TODO perhaps perl+ithreads related issue (needs more investigation) +plan skip_all => "this test sometimes crashes on cygwin" if $^O eq 'cygwin'; + +# NOTE: expect warnings about threads still running under perl 5.8 and threads 1.71 +plan tests => 1; + +use FindBin; +use File::Spec; +use Net::SSLeay; + +my $start_time = time; +my $file = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem'); + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +#exit the whole program if it runs too long +threads->new( sub { sleep 20; warn "FATAL: TIMEOUT!"; exit } )->detach; + +#print STDERR "Gonna start main thread part\n"; +my $ctx = Net::SSLeay::CTX_new() or warn "CTX_new failed" and exit; +Net::SSLeay::CTX_set_default_passwd_cb($ctx, \&callback); +Net::SSLeay::CTX_use_PrivateKey_file($ctx, $file, &Net::SSLeay::FILETYPE_PEM) or warn "CTX_use_PrivateKey_file (file=$file) failed" and exit; +Net::SSLeay::CTX_set_default_passwd_cb($ctx, undef); +Net::SSLeay::CTX_free($ctx); + +#print STDERR "Gonna start multi-threading part\n"; +threads->new(\&do_check) for (1..10); + +#print STDERR "Waiting for all threads to finish\n"; +do_sleep(50) while(threads->list()); + +pass("successfully finished, duration=".(time-$start_time)); +exit(0); + +sub callback { + #printf STDERR ("[thread:%04d] Inside callback\n", threads->tid); + return "secret"; # password +} + +sub do_sleep { + my $miliseconds = shift; + select(undef, undef, undef, $miliseconds/1000); +} + +sub do_check { + #printf STDERR ("[thread:%04d] do_check started\n", threads->tid); + + my $c = Net::SSLeay::CTX_new() or warn "CTX_new failed" and exit; + Net::SSLeay::CTX_set_default_passwd_cb($c, \&callback); + Net::SSLeay::CTX_use_PrivateKey_file($c, $file, &Net::SSLeay::FILETYPE_PEM) or warn "CTX_use_PrivateKey_file (file=$file) failed" and exit; + Net::SSLeay::CTX_set_default_passwd_cb($c, undef); + Net::SSLeay::CTX_free($c); + #do_sleep(rand(500)); + + #printf STDERR ("[thread:%04d] do_check finished\n", threads->tid); + threads->detach(); +} diff --git a/t/local/62_threads-ctx_new-deadlock.t b/t/local/62_threads-ctx_new-deadlock.t new file mode 100644 index 0000000..c4845b2 --- /dev/null +++ b/t/local/62_threads-ctx_new-deadlock.t @@ -0,0 +1,55 @@ +use strict; +use warnings; +use Config; +use Test::More; + +BEGIN { + plan skip_all => "your perl is not compiled with ithreads" unless $Config{useithreads}; + require threads; +}; + +#XXX-TODO perhaps perl+ithreads related issue (needs more investigation) +plan skip_all => "this test sometimes crashes on cygwin" if $^O eq 'cygwin'; + +plan tests => 1; + +use FindBin; +use Net::SSLeay; + +my $start_time = time; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +#exit the whole program if it runs too long +threads->new( sub { sleep 20; warn "FATAL: TIMEOUT!"; exit } )->detach; + +#print STDERR "Gonna start multi-threading part\n"; +threads->new(\&do_check) for (1..20); + +#print STDERR "Waiting for all threads to finish\n"; +do_sleep(50) while (threads->list()); + +pass("successfully finished, duration=".(time-$start_time)); +exit(0); + +sub do_sleep { + my $miliseconds = shift; + select(undef, undef, undef, $miliseconds/1000); +} + +sub do_check { + #printf STDERR ("[thread:%04d] do_check started\n", threads->tid); + + my $c = Net::SSLeay::CTX_new() or warn "CTX_new failed" and exit; + my $d = Net::SSLeay::new($c) or warn "SSL_new" and exit; + my $e = Net::SSLeay::SESSION_new() or warn "SSL_SESSION_new failed" and exit; + Net::SSLeay::set_session($d,$e); + Net::SSLeay::SESSION_free($e); + Net::SSLeay::free($d); + Net::SSLeay::CTX_free($c); + + #printf STDERR ("[thread:%04d] do_check finished\n", threads->tid); + threads->detach(); +} diff --git a/t/local/63_ec_key_generate_key.t b/t/local/63_ec_key_generate_key.t new file mode 100644 index 0000000..8c8375b --- /dev/null +++ b/t/local/63_ec_key_generate_key.t @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; + +if (!defined &Net::SSLeay::EC_KEY_generate_key) { + plan skip_all => "no suport for ECC in your OpenSSL"; + exit(0); +} + +plan tests => 4; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $ec = Net::SSLeay::EC_KEY_generate_key('prime256v1'); +ok($ec,'EC key created'); + +if ($ec) { + my $key = Net::SSLeay::EVP_PKEY_new(); + my $rv = Net::SSLeay::EVP_PKEY_assign_EC_KEY($key,$ec); + ok($rv,'EC key assigned to PKEY'); + + my $pem = Net::SSLeay::PEM_get_string_PrivateKey($key); + ok( $pem =~m{^---.* PRIVATE KEY}m, "output key as PEM"); + + my $bio = Net::SSLeay::BIO_new( Net::SSLeay::BIO_s_mem()); + Net::SSLeay::BIO_write($bio,$pem); + my $newkey = Net::SSLeay::PEM_read_bio_PrivateKey($bio); + ok($newkey,"read key again from PEM"); +} diff --git a/t/local/64_ticket_sharing.t b/t/local/64_ticket_sharing.t new file mode 100644 index 0000000..ddc28ab --- /dev/null +++ b/t/local/64_ticket_sharing.t @@ -0,0 +1,291 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; + +# for debugging only +my $DEBUG = 0; +my $PCAP = 0; +require Net::PcapWriter if $PCAP; + +plan skip_all => "no support for tlsext_ticket_key_cb" + if ! defined &Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb; +plan tests => 15; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $SSL_ERROR; # set in _minSSL +my %TRANSFER; # set in _handshake + +my $client = _minSSL->new(); +my $server = _minSSL->new( cert => [ + File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'), + File::Spec->catfile('t', 'data', 'testcert_key_2048.pem') +]); + + +# initial tests without reuse +# ---------------------------------------------- +is( _handshake($client,$server), 'full', "initial handshake is full"); +is( _handshake($client,$server), 'full', "another full handshake"); + +# explicitly reuse session in client to check that server accepts it +# ---------------------------------------------- + +my ($save_session,$reuse); +if (0) { + # simple version - get via get1_session and apply via set_session + my $saved; + $save_session = sub { $saved = Net::SSLeay::get1_session($client->_ssl) }; + $reuse = sub { Net::SSLeay::set_session($client->_ssl, $saved) }; +} else { + # don't store the session directly but only a serialized version + my $saved; + $save_session = sub { + $saved = Net::SSLeay::i2d_SSL_SESSION( + Net::SSLeay::get_session($client->_ssl)); + }; + $reuse = sub { + Net::SSLeay::set_session($client->_ssl, + Net::SSLeay::d2i_SSL_SESSION($saved)); + }; +} + +&$save_session; +is( _handshake($client,$server,$reuse),'reuse',"handshake with reuse"); +is( _handshake($client,$server,$reuse),'reuse',"handshake again with reuse"); + +# create another server and connect client with session from old server +# should not be reused +# ---------------------------------------------- +my $server2 = _minSSL->new( cert => [ + File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem'), + File::Spec->catfile('t', 'data', 'testcert_key_2048.pem') +]); +is( _handshake($client,$server2,$reuse),'full',"handshake with server2 is full"); + +# now attach the same ticket key callback to both servers +# ---------------------------------------------- +Net::SSLeay::RAND_bytes(my $key,32); +my $key_name = pack("a16",'secret'); +my $keycb = sub { + my ($mykey,$name) = @_; + return ($mykey,$key_name) if ! $name or $key_name eq $name; + return; # unknown key +}; +Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($server->_ctx, $keycb,$key); +Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($server2->_ctx,$keycb,$key); +is( _handshake($client,$server),'full',"initial full handshake with server1"); + +&$save_session; +is( _handshake($client,$server,$reuse), 'reuse',"reuse session with server1"); +is( _handshake($client,$server2,$reuse),'reuse',"reuse session with server2"); + +# simulate rotation for $key: the callback returns now the right key, but +# has a different current_name. It is expected that the callback is called again +# for encryption with the new key and that a new session ticket gets sent to +# the client +# ---------------------------------------------- +Net::SSLeay::RAND_bytes(my $newkey,32); +my $newkey_name = pack("a16",'newsecret'); +my @keys = ( + [ $newkey_name, $newkey ], # current default key + [ $key_name, $key ], # already expired +); +my @was_called_with; +my %old_transfer = %TRANSFER; +Net::SSLeay::CTX_set_tlsext_ticket_getkey_cb($server2->_ctx, sub { + my (undef,$name) = @_; + push @was_called_with,$name || ''; + return ($keys[0][1],$keys[0][0]) if ! $name; + for(my $i = 0; $i<@keys; $i++) { + return ($keys[$i][1],$keys[0][0]) if $name eq $keys[$i][0]; + } + return; +}); + +my $expect_reuse = _handshake($client,$server2,$reuse); +if ($expect_reuse eq '> < > <') { + # broken handshake seen with openssl 1.0.0 when a ticket was used where + # the key is still known but expired. It will do + # Encrypted Handshake Message, Change Cipher Spec, Encrypted Handshake Message + # in the last packet from server to client + is($expect_reuse,'> < > <',"(slightly broken) reuse session with old key with server2"); + ok( @was_called_with >= 2,'callback was called at least 2 times'); +} else { + is($expect_reuse,'reuse',"reuse session with old key with server2"); + is( 0+@was_called_with,2,'callback was called 2 times'); +} + +is( $was_called_with[0],$key_name, 'first with the old key name'); +is( $was_called_with[1],"", 'then with undef to get the current key'); +ok( $TRANSFER{client} == $old_transfer{client}, 'no more data from client to server'); +ok( $TRANSFER{server} > $old_transfer{server}, 'but more data from server (new ticket)'); + +# finally try to reuse the session created with new key against server1 +# this should result in a full handshake since server1 does not know newkey +# ---------------------------------------------- +&$save_session; +is( _handshake($client,$server,$reuse),'full',"full handshake with new ticker on server1"); + + + +my $i; +sub _handshake { + my ($client,$server,$after_init) = @_; + $client->state_connect; + $server->state_accept; + &$after_init if $after_init; + + my $pcap = $PCAP && do { + my $fname = 'test'.(++$i).'.pcap'; + open(my $fh,'>',$fname); + diag("pcap in $fname"); + $fh->autoflush; + Net::PcapWriter->new($fh)->tcp_conn('1.1.1.1',1000,'2.2.2.2',443); + }; + + my ($client_done,$server_done,@hs); + %TRANSFER = (); + for(my $tries = 0; $tries < 10 and !$client_done || !$server_done; $tries++ ) { + $client_done ||= $client->handshake || 0; + $server_done ||= $server->handshake || 0; + + my $transfer = 0; + if (defined(my $data = $client->bio_read())) { + $pcap && $pcap->write(0,$data); + $DEBUG && warn "client -> server: ".length($data)." bytes\n"; + $server->bio_write($data); + push @hs,'>'; + $TRANSFER{client} += length($data); + $transfer++; + } + if (defined(my $data = $server->bio_read())) { + $pcap && $pcap->write(1,$data); + $DEBUG && warn "server -> client: ".length($data)." bytes\n"; + $client->bio_write($data); + # assume certificate was sent if length>700 + push @hs, length($data) > 700 ? '<[C]':'<'; + $TRANSFER{server} += length($data); + $transfer++; + } + if (!$transfer) { + # no more data to transfer - assume we are done + $client_done = $server_done = 1; + } + } + + return + !$client_done || !$server_done ? 'failed' : + "@hs" eq '> <[C] > <' ? 'full' : + "@hs" eq '> < >' ? 'reuse' : + "@hs"; +} + + +{ + package _minSSL; + sub new { + my ($class,%args) = @_; + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::CTX_set_options($ctx,Net::SSLeay::OP_ALL()); + Net::SSLeay::CTX_set_cipher_list($ctx,'AES128-SHA'); + my $id = 'client'; + if ($args{cert}) { + my ($cert,$key) = @{ delete $args{cert} }; + Net::SSLeay::set_cert_and_key($ctx, $cert, $key) + || die "failed to use cert file $cert,$key"; + $id = 'server'; + } + + my $self = bless { id => $id, ctx => $ctx }, $class; + return $self; + } + + sub state_accept { + my $self = shift; + _reset($self); + Net::SSLeay::set_accept_state($self->{ssl}); + } + + sub state_connect { + my $self = shift; + _reset($self); + Net::SSLeay::set_connect_state($self->{ssl}); + } + + sub handshake { + my $self = shift; + my $rv = Net::SSLeay::do_handshake($self->{ssl}); + $rv = _error($self,$rv); + return $rv; + } + + sub ssl_read { + my ($self) = @_; + my ($data,$rv) = Net::SSLeay::read($self->{ssl}); + return _error($self,$rv || -1) if !$rv || $rv<0; + return $data; + } + + sub bio_write { + my ($self,$data) = @_; + defined $data and $data ne '' or return; + Net::SSLeay::BIO_write($self->{rbio},$data); + } + + sub ssl_write { + my ($self,$data) = @_; + my $rv = Net::SSLeay::write($self->{ssl},$data); + return _error($self,$rv || -1) if !$rv || $rv<0; + return $rv; + } + + sub bio_read { + my ($self) = @_; + return Net::SSLeay::BIO_read($self->{wbio}); + } + + sub _ssl { shift->{ssl} } + sub _ctx { shift->{ctx} } + + sub _reset { + my $self = shift; + my $ssl = Net::SSLeay::new($self->{ctx}); + Net::SSLeay::set_security_level($ssl, 1) if exists &Net::SSLeay::set_security_level; + my @bio = ( + Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()), + Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()), + ); + Net::SSLeay::set_bio($ssl,$bio[0],$bio[1]); + $self->{ssl} = $ssl; + $self->{rbio} = $bio[0]; + $self->{wbio} = $bio[1]; + } + + sub _error { + my ($self,$rv) = @_; + if ($rv>0) { + $SSL_ERROR = undef; + return $rv; + } + my $err = Net::SSLeay::get_error($self->{ssl},$rv); + if ($err == Net::SSLeay::ERROR_WANT_READ() + || $err == Net::SSLeay::ERROR_WANT_WRITE()) { + $SSL_ERROR = $err; + $DEBUG && warn "[$self->{id}] rw:$err\n"; + return; + } + $DEBUG && warn "[$self->{id}] ".Net::SSLeay::ERR_error_string($err)."\n"; + return; + } + +} diff --git a/t/local/65_security_level.t b/t/local/65_security_level.t new file mode 100644 index 0000000..76cfe1f --- /dev/null +++ b/t/local/65_security_level.t @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Net::SSLeay; + +plan skip_all => 'openssl-1.1.0 required' unless Net::SSLeay::SSLeay >= 0x10100001; +plan skip_all => 'get/set_security_level not available with LibreSSL' if Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER"); + +plan tests => 20; + + +my $ctx = Net::SSLeay::CTX_new(); +ok( defined Net::SSLeay::CTX_get_security_level($ctx), + "CTX_get_security_level() returns a value" +); + +ok( Net::SSLeay::CTX_get_security_level($ctx) >= 0, + "CTX_get_security_level() is non-negative" +); + +for (0..7) { + Net::SSLeay::CTX_set_security_level($ctx, $_); + is( Net::SSLeay::CTX_get_security_level($ctx), + $_, "CTX_get_security_level() matches CTX_set_security_level($_)" ); +} + +my $ssl = Net::SSLeay::new($ctx); +ok( defined Net::SSLeay::get_security_level($ssl), + "get_security_level() returns a value" +); + +ok( Net::SSLeay::get_security_level($ssl) >= 0, + "get_security_level() is non-negative" +); + +for (0..7) { + Net::SSLeay::set_security_level($ssl, $_); + is( Net::SSLeay::get_security_level($ssl), + $_, "get_security_level() matches set_security_level($_)" ); +} diff --git a/t/local/65_ticket_sharing_2.t b/t/local/65_ticket_sharing_2.t new file mode 100644 index 0000000..0509c5c --- /dev/null +++ b/t/local/65_ticket_sharing_2.t @@ -0,0 +1,207 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; + +# for debugging only +my $DEBUG = 0; +my $PCAP = 0; +require Net::PcapWriter if $PCAP; + +plan skip_all => "no support for session_ticket_ext_cb" + if ! defined &Net::SSLeay::set_session_ticket_ext_cb; +my $tests = 4; +plan tests => $tests; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $SSL_ERROR; # set in _minSSL +my %TRANSFER; # set in _handshake + +my $SESSION_TICKET = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff"; +my $SESSION_TICKET_CB_DATA = "dada"; +my $set_session_ticket_ext_cb_run = 0; + +my $client = _minSSL->new(); +my $server = _minSSL->new( cert => [ + File::Spec->catfile('t','data','testcert_wildcard.crt.pem'), + File::Spec->catfile('t','data','testcert_key_2048.pem') +]); + + +# now attach the ticket callback to server +# ---------------------------------------------- +my $ticketcb = sub { + my ($ssl, $ticket, $data) = @_; + + is(unpack('H*', $data), unpack('H*', $SESSION_TICKET_CB_DATA), 'server set callback data with set_session_ticket_ext_cb'); + is(unpack('H*', $ticket), unpack('H*', $SESSION_TICKET), 'client set session ticket with set_session_ticket_ext'); + + $set_session_ticket_ext_cb_run = 1; + return 1; +}; +my $set_ticket_cb = sub { + Net::SSLeay::set_session_ticket_ext_cb($server->_ssl, $ticketcb, $SESSION_TICKET_CB_DATA); + Net::SSLeay::set_session_ticket_ext($client->_ssl, $SESSION_TICKET); +}; +is( _handshake($client,$server,$set_ticket_cb),'full',"full handshake with a ticket"); +ok($set_session_ticket_ext_cb_run == 1, 'server run a callback set with set_session_ticket_ext_cb'); + +my $i; +sub _handshake { + my ($client,$server,$after_init) = @_; + $client->state_connect; + $server->state_accept; + &$after_init if $after_init; + + my $pcap = $PCAP && do { + my $fname = 'test'.(++$i).'.pcap'; + open(my $fh,'>',$fname); + diag("pcap in $fname"); + $fh->autoflush; + Net::PcapWriter->new($fh)->tcp_conn('1.1.1.1',1000,'2.2.2.2',443); + }; + + my ($client_done,$server_done,@hs); + %TRANSFER = (); + for(my $tries = 0; $tries < 10 and !$client_done || !$server_done; $tries++ ) { + $client_done ||= $client->handshake || 0; + $server_done ||= $server->handshake || 0; + + my $transfer = 0; + if (defined(my $data = $client->bio_read())) { + $pcap && $pcap->write(0,$data); + $DEBUG && warn "client -> server: ".length($data)." bytes\n"; + $server->bio_write($data); + push @hs,'>'; + $TRANSFER{client} += length($data); + $transfer++; + } + if (defined(my $data = $server->bio_read())) { + $pcap && $pcap->write(1,$data); + $DEBUG && warn "server -> client: ".length($data)." bytes\n"; + $client->bio_write($data); + # assume certificate was sent if length>700 + push @hs, length($data) > 700 ? '<[C]':'<'; + $TRANSFER{server} += length($data); + $transfer++; + } + if (!$transfer) { + # no more data to transfer - assume we are done + $client_done = $server_done = 1; + } + } + + return + !$client_done || !$server_done ? 'failed' : + "@hs" eq '> <[C] > <' ? 'full' : + "@hs" eq '> < >' ? 'reuse' : + "@hs"; +} + + +{ + package _minSSL; + sub new { + my ($class,%args) = @_; + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::CTX_set_options($ctx,Net::SSLeay::OP_ALL()); + Net::SSLeay::CTX_set_cipher_list($ctx,'AES128-SHA'); + my $id = 'client'; + if ($args{cert}) { + my ($cert,$key) = @{ delete $args{cert} }; + Net::SSLeay::set_cert_and_key($ctx, $cert, $key) + || die "failed to use cert file $cert,$key"; + $id = 'server'; + } + + my $self = bless { id => $id, ctx => $ctx }, $class; + return $self; + } + + sub state_accept { + my $self = shift; + _reset($self); + Net::SSLeay::set_accept_state($self->{ssl}); + } + + sub state_connect { + my $self = shift; + _reset($self); + Net::SSLeay::set_connect_state($self->{ssl}); + } + + sub handshake { + my $self = shift; + my $rv = Net::SSLeay::do_handshake($self->{ssl}); + $rv = _error($self,$rv); + return $rv; + } + + sub ssl_read { + my ($self) = @_; + my ($data,$rv) = Net::SSLeay::read($self->{ssl}); + return _error($self,$rv || -1) if !$rv || $rv<0; + return $data; + } + + sub bio_write { + my ($self,$data) = @_; + defined $data and $data ne '' or return; + Net::SSLeay::BIO_write($self->{rbio},$data); + } + + sub ssl_write { + my ($self,$data) = @_; + my $rv = Net::SSLeay::write($self->{ssl},$data); + return _error($self,$rv || -1) if !$rv || $rv<0; + return $rv; + } + + sub bio_read { + my ($self) = @_; + return Net::SSLeay::BIO_read($self->{wbio}); + } + + sub _ssl { shift->{ssl} } + sub _ctx { shift->{ctx} } + + sub _reset { + my $self = shift; + my $ssl = Net::SSLeay::new($self->{ctx}); + my @bio = ( + Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()), + Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()), + ); + Net::SSLeay::set_bio($ssl,$bio[0],$bio[1]); + $self->{ssl} = $ssl; + $self->{rbio} = $bio[0]; + $self->{wbio} = $bio[1]; + } + + sub _error { + my ($self,$rv) = @_; + if ($rv>0) { + $SSL_ERROR = undef; + return $rv; + } + my $err = Net::SSLeay::get_error($self->{ssl},$rv); + if ($err == Net::SSLeay::ERROR_WANT_READ() + || $err == Net::SSLeay::ERROR_WANT_WRITE()) { + $SSL_ERROR = $err; + $DEBUG && warn "[$self->{id}] rw:$err\n"; + return; + } + $DEBUG && warn "[$self->{id}] ".Net::SSLeay::ERR_error_string($err)."\n"; + return; + } + +} diff --git a/t/local/66_curves.t b/t/local/66_curves.t new file mode 100644 index 0000000..0ca821b --- /dev/null +++ b/t/local/66_curves.t @@ -0,0 +1,200 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Test::More; +use Socket; +use File::Spec; +use Net::SSLeay; +use Config; + +# for debugging only +my $DEBUG = 0; +my $PCAP = 0; +require Net::PcapWriter if $PCAP; + +my @set_list = ( + defined &Net::SSLeay::CTX_set1_groups_list ? (\&Net::SSLeay::CTX_set1_groups_list) : (), + defined &Net::SSLeay::CTX_set1_curves_list ? (\&Net::SSLeay::CTX_set1_curves_list) : (), +); + +plan skip_all => "no support for CTX_set_curves_list" if ! @set_list; +my $tests = 4*@set_list; +plan tests => $tests; + +Net::SSLeay::randomize(); +Net::SSLeay::load_error_strings(); +Net::SSLeay::ERR_load_crypto_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $SSL_ERROR; # set in _minSSL +my %TRANSFER; # set in _handshake + +my $client = _minSSL->new(); +my $server = _minSSL->new( cert => [ + File::Spec->catfile('t','data','testcert_wildcard.crt.pem'), + File::Spec->catfile('t','data','testcert_key_2048.pem') +]); + + +my $set_curves; +while ($set_curves = shift @set_list) { + ok(_handshake($client,$server,'P-521:P-384','P-521',1), 'first curve'); + ok(_handshake($client,$server,'P-521:P-384','P-384',1), 'second curve'); + ok(_handshake($client,$server,'P-521:P-384','P-256',0), 'wrong curve failed'); + ok(_handshake($client,$server,'P-521:P-384','P-384:P-521',1), 'both curve'); +} + + +my $i; +sub _handshake { + my ($client,$server,$server_curve,$client_curve,$expect_ok) = @_; + $client->state_connect($client_curve); + $server->state_accept($server_curve); + + my $pcap = $PCAP && do { + my $fname = 'test'.(++$i).'.pcap'; + open(my $fh,'>',$fname); + diag("pcap in $fname"); + $fh->autoflush; + Net::PcapWriter->new($fh)->tcp_conn('1.1.1.1',1000,'2.2.2.2',443); + }; + + my ($client_done,$server_done,@hs); + %TRANSFER = (); + for(my $tries = 0; $tries < 10 and !$client_done || !$server_done; $tries++ ) { + $client_done ||= $client->handshake || 0; + $server_done ||= $server->handshake || 0; + + my $transfer = 0; + if (defined(my $data = $client->bio_read())) { + $pcap && $pcap->write(0,$data); + $DEBUG && warn "client -> server: ".length($data)." bytes\n"; + $server->bio_write($data); + push @hs,'>'; + $TRANSFER{client} += length($data); + $transfer++; + } + if (defined(my $data = $server->bio_read())) { + $pcap && $pcap->write(1,$data); + $DEBUG && warn "server -> client: ".length($data)." bytes\n"; + $client->bio_write($data); + # assume certificate was sent if length>700 + push @hs, length($data) > 700 ? '<[C]':'<'; + $TRANSFER{server} += length($data); + $transfer++; + } + if (!$transfer) { + # no more data to transfer - assume we are done + $client_done = $server_done = 1; + } + } + + my $result = "$client_done - $server_done - @hs"; + return $result eq '1 - 1 - > <[C] > <' if $expect_ok; + return 1 if $result eq '1 - 1 - > <'; # failed connect with OpenSSL >= 1.1.0 + return 1 if $result =~ qr{^\Q0 - 0 - > < < <}; # OpenSSL 1.0.2, LibreSSL + return 0; # unexpected result +} + + +{ + package _minSSL; + sub new { + my ($class,%args) = @_; + my $ctx = Net::SSLeay::CTX_tlsv1_new(); + Net::SSLeay::CTX_set_options($ctx,Net::SSLeay::OP_ALL()); + Net::SSLeay::CTX_set_cipher_list($ctx,'ECDHE'); + Net::SSLeay::CTX_set_ecdh_auto($ctx,1) + if defined &Net::SSLeay::CTX_set_ecdh_auto; + my $id = 'client'; + if ($args{cert}) { + my ($cert,$key) = @{ delete $args{cert} }; + Net::SSLeay::set_cert_and_key($ctx, $cert, $key) + || die "failed to use cert file $cert,$key"; + $id = 'server'; + } + + my $self = bless { id => $id, ctx => $ctx }, $class; + return $self; + } + + sub state_accept { + my ($self,$curve) = @_; + _reset($self,$curve); + Net::SSLeay::set_accept_state($self->{ssl}); + } + + sub state_connect { + my ($self,$curve) = @_; + _reset($self,$curve); + Net::SSLeay::set_connect_state($self->{ssl}); + } + + sub handshake { + my $self = shift; + my $rv = Net::SSLeay::do_handshake($self->{ssl}); + $rv = _error($self,$rv); + return $rv; + } + + sub ssl_read { + my ($self) = @_; + my ($data,$rv) = Net::SSLeay::read($self->{ssl}); + return _error($self,$rv || -1) if !$rv || $rv<0; + return $data; + } + + sub bio_write { + my ($self,$data) = @_; + defined $data and $data ne '' or return; + Net::SSLeay::BIO_write($self->{rbio},$data); + } + + sub ssl_write { + my ($self,$data) = @_; + my $rv = Net::SSLeay::write($self->{ssl},$data); + return _error($self,$rv || -1) if !$rv || $rv<0; + return $rv; + } + + sub bio_read { + my ($self) = @_; + return Net::SSLeay::BIO_read($self->{wbio}); + } + + sub _ssl { shift->{ssl} } + sub _ctx { shift->{ctx} } + + sub _reset { + my ($self,$curve) = @_; + $set_curves->($self->{ctx},$curve) if $curve; + my $ssl = Net::SSLeay::new($self->{ctx}); + my @bio = ( + Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()), + Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem()), + ); + Net::SSLeay::set_bio($ssl,$bio[0],$bio[1]); + $self->{ssl} = $ssl; + $self->{rbio} = $bio[0]; + $self->{wbio} = $bio[1]; + } + + sub _error { + my ($self,$rv) = @_; + if ($rv>0) { + $SSL_ERROR = undef; + return $rv; + } + my $err = Net::SSLeay::get_error($self->{ssl},$rv); + if ($err == Net::SSLeay::ERROR_WANT_READ() + || $err == Net::SSLeay::ERROR_WANT_WRITE()) { + $SSL_ERROR = $err; + $DEBUG && warn "[$self->{id}] rw:$err\n"; + return; + } + $DEBUG && warn "[$self->{id}] ".Net::SSLeay::ERR_error_string($err)."\n"; + return; + } + +} diff --git a/t/local/kwalitee.t b/t/local/kwalitee.t new file mode 100644 index 0000000..f3de431 --- /dev/null +++ b/t/local/kwalitee.t @@ -0,0 +1,9 @@ +BEGIN { + unless ($ENV{RELEASE_TESTING}) + { + use Test::More; + plan(skip_all => 'these tests are for only for release candidate testing. Enable with RELEASE_TESTING=1'); + } +} + +use Test::Kwalitee; diff --git a/typemap b/typemap new file mode 100644 index 0000000..373e711 --- /dev/null +++ b/typemap @@ -0,0 +1,92 @@ +TYPEMAP +SSL_METHOD * T_PTR +const SSL_METHOD * T_PTR +SSL_CTX * T_PTR +SSL_SESSION * T_PTR +SSL * T_PTR +RSA * T_PTR +DH * T_PTR +EC_KEY * T_PTR +const X509 * T_PTR +const X509_CRL * T_PTR +const X509_REQ * T_PTR +const X509_NAME * T_PTR +const EVP_CIPHER * T_PTR +const EVP_PKEY * T_PTR +const SSL * T_PTR +X509 * T_PTR +X509_CRL * T_PTR +X509_LOOKUP * T_PTR +X509_LOOKUP_METHOD * T_PTR +X509_NAME * T_PTR +X509_NAME_ENTRY * T_PTR +X509_EXTENSION * T_PTR +X509_REQ * T_PTR +X509_PUBKEY * T_PTR +BIGNUM * T_PTR +BIO * T_PTR +const BIO_METHOD * T_PTR +BIO_METHOD * T_PTR +EVP_PKEY * T_PTR +const EVP_MD * T_PTR +EVP_MD * T_PTR +EVP_MD_CTX * T_PTR +const EVP_MD_CTX * T_PTR +CERT * T_PTR +LHASH * T_PTR +struct lhash_st_SSL_SESSION * T_PTR +struct cert_st * T_PTR +X509_STORE_CTX * T_PTR +ASN1_TIME * T_PTR +ASN1_OCTET_STRING * T_PTR +const ASN1_INTEGER * T_PTR +ASN1_INTEGER * T_PTR +ASN1_STRING * T_PTR +EVP_PKEY * T_PTR +const char * T_PV +const unsigned char * T_PV +CRYPTO_EX_new * T_PTR +CRYPTO_EX_dup * T_PTR +CRYPTO_EX_free * T_PTR +SSL_CIPHER * T_PTR +const SSL_CIPHER * T_PTR +int * T_PTR +COMP_METHOD * T_PTR +X509_INFO * T_PTR +X509_STORE * T_PTR +X509_NAME_STACK * T_PTR +X509_VERIFY_PARAM * T_PTR +const X509_VERIFY_PARAM * T_PTR +X509_POLICY_LEVEL * T_PTR +X509_POLICY_TREE * T_PTR +X509_POLICY_NODE * T_PTR +const X509_POLICY_NODE * T_PTR +STACK_OF(X509) * T_PTR +const STACK_OF(X509) * T_PTR +STACK_OF(X509_INFO) * T_PTR +const STACK_OF(X509_INFO) * T_PTR +STACK_OF(X509_POLICY_NODE) * T_PTR +STACK_OF(POLICYQUALINFO) * T_PTR +ASN1_OBJECT * T_PTR +const ASN1_OBJECT * T_PTR +STACK_OF(ASN1_OBJECT) * T_PTR +ENGINE * T_PTR +OCSP_RESPONSE * T_PTR +OCSP_REQUEST * T_PTR +pem_password_cb * T_PTR +generate_key_cb * T_PTR +callback_ret_int * T_PTR +callback_no_ret * T_PTR +cb_ssl_int_int_ret_void * T_PTR +cb_ssl_int_int_ret_RSA * T_PTR +cb_ssl_int_int_ret_DH * T_PTR +perl_filehandle_t T_PERL_IO_HANDLE + +INPUT + +T_PERL_IO_HANDLE + if ($arg && SvOK($arg) && SvROK($arg)) { + $var = ($type)PerlIO_fileno( IoIFP( sv_2io(SvRV($arg)) ) ); + } else { + $var = ($type)SvIV($arg); + }