diff options
author | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-14 21:28:19 +0200 |
---|---|---|
committer | Jannis Hoffmann <jannis@fehcom.de> | 2024-07-14 21:28:19 +0200 |
commit | 1087d4df2a7342d2832ba3bab1843bf4a3040775 (patch) | |
tree | 96cd6ea198cc542f29c0660d5e5f7083af84d711 |
159 files changed, 10628 insertions, 0 deletions
@@ -0,0 +1,123 @@ +Installation supplements +------------------------ + +Caution: You need to have fehQlibs installed! + +Within the ./src directory you find some conf-* files for your adjustments: + +1. Customization +- conf-man (man page target) => /usr/share/man + +2. Compilation - files are autogenerated +- conf-cc (don't need to be touched) +- conf-ccperl (no adjustments required) +- conf-ldperl (no adjustments required) + +Note: The current version detects the AMD64 environment +and the possible support for dynamic load libraries. + +3. Installation dependencies & default - autogenerated +- conf-qlibs (the fehQlibs install directory; default: /usr/local/qlibs) +- conf-perl (no adjustments required) +- conf-ssl (default; add path to inlcude alternative or additional openssl header file) +- conf-ssllib (default; the cryto libs to include) + + Note: If you installed OpenSSL 1.1.1b at /usr/local customizations are included as sample. + +4. Certificate and key file handling -- these are parms declared for each server; thus may stay empty/untouched. + Default values MAY be provided as: +- conf-cafile +- conf-ccafile +- conf-certfile +- conf-certchainfile +- conf-ciphers (a current sample is provided, but not active) +- conf-dhfile (you may use the 'dh2048.pem' in ucspi-ssl's ./etc dir) +- conf-keyfile + +5. Installation procedure + Usually, you just install the package with + +- package/install + +or -- in case the Perl install failes -- + +- package/install base +(- package/man) + +6. Testing +- package/rts -- or -- +- package/rts base (if Perl is not installed/working). + + The etc/ directory includes some X.509 certs and keyfiles + for testing. Have a look at those ! + +7. ucspi-tcp dependencies + The vanilla ucspi-tcp-0.88 package from Dan Bernstein does not support + building 'tcprules' with CIDR support. + + Download and install 'ucspi-tcp6' from + http://www.fehcom.de/ipnet/ucspi-tcp6.html. + +8. Compatibility + This version has been successfully tested against: + +- OpenSSL 1.0.2j, 1.1.0c, 1.1.1b-s, 1.1.1t, + 3.0.0, 3.0.7, 3.1.0, 3.1.3, 3.2.0-alpha2 +- LibreSSL 2.5.4, 2.6.0, 2.7.0, 2.9.1 + 3.6.0, 3.7.0, 3.7.2 + + Other intermittend releases are expected to work as well. + + You can sucessfully use ucspi-ssl with 'foreign' *SSL installations. + Apart from the header files used open compilation, the execution + requires a tailored LD_LIBRARY_PATH pointing to the *SSL libs. + This can be done in the run script calling ie. sslserver together + with the application. Otherwise, the ssl* modules will always + use the default libraries; which may not work. + See src/rts.it for a sample given LibreSSL. + + +9. LibreSSL + LibreSSL has has different understanding of + +- how to work with CIPHER_SUITES and +- how to use the 'libssl' and 'libcrypto'. + + libssl and libcrypto are enumerated (eg. libssl.so.52). + In case you are building ucspi-ssl based on static libs, + you need to do the following in the LibreSSL dir: + +- ln -s ssl/.libs/libssl.a . +- ln -s crypto/.libs/libcrypto.a . + +10. OpenSSL 3.0/3.1/3.2 + OpenSSL have changed their APIs significantly. + The current ucspi-ssl includes deprecated calls: + - RSA_new(), RSA_generate_key_ex(), RSA_free() + - PEM_read_bio_DHparams(), EC_KEY_new_by_curve_name(), EC_KEY_free() + + In case you install openssl-3.x.y, you not only need to + - modify conf-ssl and conf-ssllib + but also to inlude libssl.so.3 in your library path: + (1) export LD_LIBRARY_PATH=<path>/opensssl-3.x.y + (2) include that path to your standard lib path or + (3) copy libssl.so.3 to your standard lib path. + + A check would show the statically linked OpenSSL libs like this: + + $ export LD_LIBRARY_PATH=/home/ucspi/_SSL/openssl-3.0.7 + + $ ldd sslserver + + sslserver: + libssl.so.3 => /home/ucspi/_SSL/openssl-3.0.7/libssl.so.3 (0x800260000) + libcrypto.so.3 => /home/ucspi/_SSL/openssl-3.0.7/libcrypto.so.3 (0x80030b000) + libc.so.7 => /lib/libc.so.7 (0x800745000) + libthr.so.3 => /lib/libthr.so.3 (0x800b4f000) + + Verify everything is working while perfoming the tests: + +- package/rts !! + +Erwin Hoffmann, October 2023 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e983f25 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +/*! \mainpage + +ucspi-ssl-0.12 +============== + +ucspi-ssl is a joined project of William Baxter +(Copyright 2001 SuperScript Technology, Inc.) and me (FEHCom). + +ucspi-ssl home page +------------------- + +- https://www.superscript.com/ +- https://www.fehcom.de/ipnet/ucspi-ssl.html + +Requirements +------------ + +- OpenSSL or LibreSSL providing crypto services. +- fehQlibs(>=17) need to be installed (usually located at /usr/local) + for network and DNS services. + +Installation and Customization +------------------------------ + +- Read INSTALL for installation instructions. +- Read doc/CERTS for the X.509 certificates shipped. +- Read doc/CHAIN-SSL how to configure X.509 chaining support. + +Changelog and Internals +----------------------- + +- Read doc/CHANGES for changes and bug fixes. +- Read doc/UCSPI-SSL to find some internal information. +- Read doc/TLS_1_3 how to use an OpenSSL/LibreSSL version providing TLS 1.3 support. +- Read doc/TLSVERSION_CIPHERSUITES how to tweak TLS version and cipher suites. +- Read doc/TODO what is missing still. +- Read INSTALL if you like to use ucspi-ssl with OpenSSL 3.x exceptionally. + +Cryptomaterial and X.509 certs +------------------------------ + +- In the directory ./etc you will find some X.509 certificate, key files + and other crypto material required for a first setup. +- All X.509 certificates use now ECC crypto instead of RSA. +- Read etc/README.certs.md. + + +Erwin Hoffmann, October 2023. diff --git a/conf-cadir b/conf-cadir new file mode 100644 index 0000000..80d386a --- /dev/null +++ b/conf-cadir @@ -0,0 +1,4 @@ +/usr/local/ssl/certs + +# This is the ucspi-ssl CA directory. +# An empty name means no certificate directory is compiled in. diff --git a/conf-cafile b/conf-cafile new file mode 100644 index 0000000..f8d31bd --- /dev/null +++ b/conf-cafile @@ -0,0 +1,3 @@ + +# This is the ucspi-ssl CA file. +# An empty name means no certificate file is compiled in. @@ -0,0 +1,3 @@ +cc -O2 -g -Wall + +# This will be used to compile .c files. diff --git a/conf-ccafile b/conf-ccafile new file mode 100644 index 0000000..d0ab55b --- /dev/null +++ b/conf-ccafile @@ -0,0 +1,3 @@ + +# This is the ucspi-ssl client CA file. +# An empty name means no client certificate file is compiled in. diff --git a/conf-ccperl b/conf-ccperl new file mode 100644 index 0000000..e411971 --- /dev/null +++ b/conf-ccperl @@ -0,0 +1,7 @@ +auto + +# The compiler arguments required for sslperl. +# All arguments must appear on a single line. +# If the word "auto" appears, use the output from + +#=> `head -1 conf-perl` -MExtUtils::Embed -e ccopts diff --git a/conf-certchainfile b/conf-certchainfile new file mode 100644 index 0000000..fcb6825 --- /dev/null +++ b/conf-certchainfile @@ -0,0 +1,3 @@ + +# This is the sslserver certificate file. +# An empty name means no certificate file is compiled in. diff --git a/conf-certfile b/conf-certfile new file mode 100644 index 0000000..fcb6825 --- /dev/null +++ b/conf-certfile @@ -0,0 +1,3 @@ + +# This is the sslserver certificate file. +# An empty name means no certificate file is compiled in. diff --git a/conf-ciphers b/conf-ciphers new file mode 100644 index 0000000..c4399d6 --- /dev/null +++ b/conf-ciphers @@ -0,0 +1,16 @@ + +# This is the list of ciphers to use. Sample for TLS < 1.3: + +ALL:!EXP:!MD5:!RC4:!ADH:!DES:!3DES:!PSK:!aNULL + +# This is the list of ciphers to use. Sample for TLS 1.3: + +TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384 + +Comment: + +a) CHACHA20_POLY1305 has preference (hardest to break) +b) AES_128_GCM comes next (-> GCM is 128 bit only!) +c) AES_256_GCM is last (AES is mostly HW accelerated) + +# An empty name means use the ciphers compiled into openssl. diff --git a/conf-dhfile b/conf-dhfile new file mode 100644 index 0000000..19fb6d0 --- /dev/null +++ b/conf-dhfile @@ -0,0 +1,7 @@ +/package/host/superscript.com/net/ucspi-ssl/etc/dh1024.pem + +# This is ucspi-ssl's DH parameter file. + +# /usr/local/ssl/pem/dh1024.pem + +# This is OpenSSL's DH default parameter file. diff --git a/conf-home b/conf-home new file mode 100644 index 0000000..a68e872 --- /dev/null +++ b/conf-home @@ -0,0 +1,4 @@ +/usr/local + +This is the ucspi-ssl home directory. Programs will be installed in +.../bin. diff --git a/conf-keyfile b/conf-keyfile new file mode 100644 index 0000000..69f26ed --- /dev/null +++ b/conf-keyfile @@ -0,0 +1,3 @@ + +# This is the sslserver key file. +# An empty name means no key file is compiled in. @@ -0,0 +1,4 @@ +cc -s + +# This will be used to link .o files into an executable. +# The '-m64' option will be inclucded automatically. diff --git a/conf-ldperl b/conf-ldperl new file mode 100644 index 0000000..83ed11b --- /dev/null +++ b/conf-ldperl @@ -0,0 +1,7 @@ +auto + +# The loader arguments required for tcpperl. +# All arguments must appear on a single line. +# If the word "auto" appears, use the output from + +#=> `head -1 conf-perl` -MExtUtils::Embed -e ldopts diff --git a/conf-man b/conf-man new file mode 100644 index 0000000..944b0af --- /dev/null +++ b/conf-man @@ -0,0 +1,4 @@ + +/usr/share/man + +# Directories to install man pages - if no manpath is available diff --git a/conf-perl b/conf-perl new file mode 100644 index 0000000..79d4318 --- /dev/null +++ b/conf-perl @@ -0,0 +1,3 @@ +perl + +# How to run perl when searching for compiler and loader options. diff --git a/conf-qlibs b/conf-qlibs new file mode 100644 index 0000000..8d1fd94 --- /dev/null +++ b/conf-qlibs @@ -0,0 +1,3 @@ +/usr/local/qlibs + +# This is the path to your qlibs directory diff --git a/conf-rsa b/conf-rsa new file mode 100644 index 0000000..480a5c9 --- /dev/null +++ b/conf-rsa @@ -0,0 +1,3 @@ +2048 + +# The length of the RSA key diff --git a/conf-ssl b/conf-ssl new file mode 100644 index 0000000..3ed85f8 --- /dev/null +++ b/conf-ssl @@ -0,0 +1,12 @@ +-I/usr/local/openssl-3.0.7/include/ + +# using the system default it could stay empty; otherwise check for that + +-I/usr/local/openssl-3.0.7/include/ +-I/home/ucspi/_SSL/libressl-3.7.2/include/ + +-I/usr/kerberos/include + +# This will be used to include headers from a different version, +# or if openssl requires additional support, e.g. kerberos support on RedHat Linux. + diff --git a/conf-ssllib b/conf-ssllib new file mode 100644 index 0000000..0f2cf61 --- /dev/null +++ b/conf-ssllib @@ -0,0 +1,11 @@ +-L/usr/local/openssl-3.0.7 -lssl -lcrypto + +-lssl -lcrypto + +# These are samples for OpenSSL and LibreSSL to be semi-statically linked + +-L/home/ucspi/_SSL/libressl-3.7.2/ssl/.libs -L/home/ucspi/_SSL/libressl-3.7.2/crypto/.libs -lssl -lcrypto +-L/usr/local/openssl-3.0.7 -lssl -lcrypto + +# This will be used to add SSL and crypto support by the given library path (-L) +# In case the ssl and crypto lib is not in your lib path, use LD_LIBRARY_PATH additionally upon call! diff --git a/doc/CHAIN-SSL b/doc/CHAIN-SSL new file mode 100644 index 0000000..9180ae2 --- /dev/null +++ b/doc/CHAIN-SSL @@ -0,0 +1,54 @@ +SSL UCSPI Certificate Chain Support +----------------------------------- + +Scope: +----- + +This version of UCSPI-SSL allows the SSL server to issue certificate chains. +In this case, the SSL client does not need to verify the certificates on +his own behalf, rather the client uses the presented certificates from the server. +However, the final root certificate has to be known by the client. + + +Usage: +----- + +1. Concatinate all relevant X.509 certifcates in one file. + The first one is the certificate of the server, the last one + should be the root certificate. + +2. Tell the sslserver the name and location of this file. + Use the environment variable CERTCHAINFILE. + +3. Provide a separate keyfile for your own (the first certificate) + employing the environment variable KEYFILE. + +4. If this variable variable is present, it takes precedence over + CERTFILE. + + +UI considerations: +----------------- + +a) Providing a particular cipher for sslclient is now facilited with + option "-z cipher" instead of "-C cipher". + +b) Reversely, the location of the certificate chain file is available + via option "-C certchainfile". + +c) For sslserver use the environment variable CERTCHAINFILE. + + +Security considerations: +----------------------- + +Your own keyfile can be password protected. + + +Performance considerations: +-------------------------- + +The server needs to open one thread per certificate. +Thus, the server carries the burden to provide the certificates. + +Erwin Hoffmann - 2011-02-16 diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 0000000..9510cdb --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,341 @@ +20011209 + Initial release. + version: 0.50 + +20021207 + Convert to new build project. + Update libraries. + Correct load ordering for ssl programs. + +20030118 + Option to set TCP environment variables. + Option to set SSL environment variables a la mod_perl. + Added sslperl. + Correct closure handling in ssl_io.c. + +20030128 + Correct setting of TCPREMOTEINFO. + +20040127 + Improved env tracking in handlers. + Updated tests. + +20040204 + Clean up signal handling, process usage. + +20040209 + Added nN options to sslclient. + +20040313 + Added conf-ssl. + Version 0.65. + +20040317 + Delete conf-home. + Permit nN opts in sslclient. + Version 0.66. + +20040320 + Allow sslclient to avoid server verification. + Support cipher selection. + Correct execution botch in sslperl. + Clean up ssl_io and signal interaction. + Version 0.67. + +20040502 + Read SSL setup info before dropping privilege. + Version 0.68. + +20050417 + Don't fail on setsid if already group leader (Gabriel Russell). + Add compatibility macros for older Perl. + Don't leak pointer returned from eval_pv. + Support for partial testing. + Remove dependency on daemontools from rts. + +20050515 + Partial-install bug fix in package/upgrade. + +20050605 + Don't lose file descriptors in sslclient (Paul Jarc). + +20050610 + Close socket for deny rule (Fred Lindberg). + +20050703 + Revise ssl_io. + Free ssl object in sslhandle.c. + Add progtimeout option. + +20050717 + Version 0.70. + +20090811 + Included ucspi-ssl-0.70_ucspitls-0.6.patch (STARTTLS support) + originally designed and provided by Scott Gifford (FEH). + +20100319 + Added Certchain support for sslserver and sslclient (FEH). + +20120217 + Integration and added man-pages (FEH). + Version 0.80. + +20120921 + Synced with ucspi-tcp6-0.95. + Version 0.82 + +20121003 + Fixed integration bug in ssl_very.c. + Included patches from Peter Conrad. + Version 0.83. + +20121005 + Bug fix in sslserver. Several small + corrections. + Version 0.83a + +20121019 + Fix for large X509 serial numbers on x86 (tx. Peter Conrad). + SAN DNSname has precedence over CN in subject. + Re-edited man pages and rts tests. + Version 0.84. + +20130602 + Added IPv6 support (tx. to Felix von Leitner and Brandon Turner). + UI: Changed sslserver client cert call from '-i/-I' to '-z/-Z' + for compatibility reasons. + Added '-4/-6' support for client scripts. + Version 0.90. + +20130804 + Added output environment variables TCP6* for sslserver. + sslperl, sslhandle, and sslprint are not IPv6 ready yet. + Version 0.91 test. + +20130910 + Added IPv6 capabilities to sslhandle, sslprint, sslperl. + Changed verification of X.509 certs. + Removed obsolete socket_4 calls in sslserver. + Version 0.92 beta. + +20140112 + Streamlined code with ucspi-tcp6-1.00. + Supplied new certs with customized SAN. + Make rts working (at least some how). + +20140331 + Added support for personalized client certs. + New option '-m' in sslserver, complementing '-z'. + CCAFILE='-' disables client cert request. + Version 0.94 beta. + +20141221 + Added verbose log output for SSL connection informations. + Version 0.95a beta. + +20140208 + Fixed wrongly nested CONNECT error code for sslclient.c + producing wrong warning messages while connecting to + an IPv4 address. + Added call of '-ldl' in ssl.lib. + Version 0.95b beta. + +20151101 + Mitigation of SSL connection hanging during + coincident change of daylight-saving settings. + +20160228 + Fixed bug in sslserver's dnsip lookup in case of paranoid settings + and additonal existance of IPv6 AAAA records for incoming IPv4 connection. + Version 0.96. + +20160802 + Serveral fixes from 'troy@' included to cope with compiler errors and + to solve a bug in function getbitasaddress in ip4_bit.c (= ucspi-tcp6-1.02). + Reordered conf-* variables in main dir to allow easier generation of + packages (i.e. RPM). Fixed script to identify different HW architecture + and OS. This version works in 32 bit mode on Raspian Linux / RasPi 7. + + Added ECDH capabilites (tx to Frank Bergmann for the patches). + Version 0.97. + +20161226 + Added compatibility with LibreSSL. + Fixed missing negative return call treatment from 'poll' (tx Frank Bergmann). + Tentative 'emake' fix for Gentoo build. + Version 0.98a. + +20170209 + Added OpenSSL 1.1 tweaks -- works under Debian (9) 'Stretch'. + Version 0.99. + +20170308 + Included PID in sslserver + sslhandle abend logs in case of SSL failure. + Version 0.99a. + +20170617 + Convenience release: Removed references to 'gcc' and used 'cc' instead. + Version 0.99b. + +20170712 + Convenience release: Added `correct` pid display in error log. + +20171028 + Fixed cosmetic bug in sslserver displaying parent and not child pid in log. + Tx Bruce Guenter. + +20171105 + Clean ups. + +20180811 + Fixed missing 'return 0' in ssl_params.c for ECDH handshake (tx. J.W.). + Version 0.99e + +---- + +20180809 + Complete refurbish based on fehQlibs. + Native handling of IPv4/IPv6 address for sslclient. + Version 0.10 + +20180810 + Added experimental 'ecdhparam' file. + Version 0.10.1 + +20180816 + Removed experimental 'ecdhparam' handling -- OpenSSL does not support it. + fehQlibs-08 required. + Version 0.10.2 + +20181010 + Finished TLS 1.3 integration (based on OpenSSL 1.1.1). + Removed compiler flags for ECDH -- now required. + fehQlibs-09 based. + Version 0.10.6 + +20181109 + Better handling of read EAGAIN (sslserver may hang). + Include socket_dualstack option (required for OS with IPv6_V6ONLY). + fehQlibs-10 required. + Version 0.10.7 + +20190318 + Added dualstack handling for servers applying the + pseudo IP address ':0' on call (common now for all servers). + Tailored TLS error handling for EAGAIN end error codes. + Rewrote IPv4 CIDR address evaluation for rules. + Version 0.10.8 + +20190505 + Fixed broken evaluation of CIDR and IPv6 addresses; + adjusted with ucspi-tcp6-1.10.5. + Improved compatibility with LibreSSL and included description. + Version 0.10.9 + +20190608 + Added DSA/DSS (+ECC) signature verification additionally to RSA. + Added compatibility with fehQlibs-12. + Version 0.10.10 + +20190728 + Compatibility improvements for the forthcoming s/qmail. + Fixed potential stack corruption in sslclient/sslhande/sslserver + while assigning hostname => 0. + Improved OpenSSL + LibreSSL compatibility: + LibreSSL 2.5 to 2.9 is working + OpenSSL 1.0.2 to 1.1.1 is working + Added SNI for sslclient. + Fixes for sslhandle. + Included new CIPHERLIST API for ssl_ciphers. + Removed dependency on conf-tcpbin; modules are expected to be in the path. + Modules rts.base and rts.sslperl are working now. + Version 0.10.11 + +20190810 + Added compatibility with fehQlibs-13. + Fixed wrong behavior of sslserver/sslclient given a local or remote IPv4 + address. sslhandle is now an own program (man sslhandle.3). + Code streamlined with ucspi-tcp6-1.11.0. + +20191012 + Removed paranthesis from host in https@: [$host]:$port -> $host:port. Tx, A.E. + Version 0.11.0 + +20191021 + Fixed TLSv1* macro's names in ucspissl.h to match ssl_context.c. +20191107 + Clearified usage of 'SSL_CTX_set_ciphersuites()' in ssl_ciphers.c. + Version 0.11.1 +202002117 + Adopted some fixes contributed by Alan S. (mtx): + DNS IP Name qualification; X.509 DNS name matching; certs are only read on demand. + Support of STARTTLS in sslclient is postponed to next minor version. + Version 0.11.2 +20200221 + Straightend error codes and exiting for sslserver/sslhandle instead of dropping + the session in case of errors. + Version 0.11.3 +20200303 + Fixed iopause return value evaluation in remoteinfo.c. +20200323 + Removed return call evaluation of iopause in ssl_io.c and ssl_timeout.c + Not clear, whether this is resulting the polling. + Version 0.11.4 +20200730 + Added pollmax limit to sslserver and sslhandle. + sslclient streamlined with tcpclient. fehQlibs-15 are required. + Version 0.11.5 +20200920 + GCC 10 compliance enforced; removed it-perl from basic install. + Version 0.11.6a +20210319 + fehQlibs-17 changes included regarding socket interface. + Synced with ucspi-tcp6-1.12.3 providing MAXCONIP capabilities. + Successful integration tests for OpenSSL 3.0.0-alpha13 and LibreSSL 3.3.1. + Version 0.12.1 +20210325 + Fixed sslserver's binding to IPv4/IPv6 addresses; code aligned with tcpserver. + Version 0.12.2 +20211017 + sslhandle to bind to IPv4 sockets, if told so. + Compatibility tests with OpenSSL 3.0. Still preliminary. + Version 0.12.3 +20220824 + Fixed early logmsg() call in sslserver. + Version 0.12.3 +20221228 + Checked compatibility with LibreSSL 3.6/3.7. + The selected ciphers are now shown during start of sslserver/sslhandle. + Fixed duplicate symbol in sslhandle (Who). + Version 0.12.4 +20230403 + Included tests on tai_now in ssl_timeout.c and removed obsolete pollmax variables. + ssl_io.c closes TLS connection gracefully upon SSL_ERROR_SSL recognition + and not continue looping. + Version 0.12.5 +20230403 + ssl_io uses now two specific return codes under condition 'BOMB' avoiding unnecessary + error messages in case of TLS client termination. + Version 0.12.6 +20230529 + sslserver MAXCONIP feature is working now from the cdb read by the children. + MAXCONIP works even the general limit is 0. + Fixed wrong '-m' option for sslserver. + Added ip and port information in case sslserver/sslclient can't bind to local addresses. + Tweaked rts to include external load libraries. + Version 0.12.7 +20231010 + Added new x509 certs and key material; all ECC now. + Fixed wrong evaluation of peer cert in ssl_verify (none-critical). + Version 0.12.8 +20231128 + Included IP info in sslserver's TLS error messages for a quick lookup. + Fixed sslhandle's wrong if nesting. + sslserver return FATAL (and not ERROR) in case TLS is requested but missing. + Enhanced compatibility with OpenSSL 3.x.y. + Version 0.12.9 +20231204 + Added argument '-y cdb' to sslserver in order to allow a rule checking + for IP addresses prior of the DNS/IDENT lookup (to cope with DDos attacks). + Version 0.12.10 diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 0000000..aea2c94 --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,70 @@ +AUTHOR +====== + +Author: + Dr. Erwin Hoffmann - FEHCom Germany +Web-Site: + https://www.fehcom.de/ipnet/ucspi-ssl.html +E-Mail: + feh@fehcom.de + +CONTRIBUTIONS +============= + +ucspi-ssl is based on William E. Baxter's (superscript.com) version used by permission: + https://www.superscript.com/ +which is put into the Public Domain. + +ucspi-ssl uses enhancements from Scott Gifford's and Charly Brady's API +to support STARTTLS communication: + https://github.com/scottgifford/ucspi-ssl +License state unknown + +LICENSE +======= + +Given these restrictions: + +ucspi-ssl is free software placed into the Public Domain. + +This includes: + You can download and use ucspi-ssl (and parts of it) as you like. + You can modify the source code without notification to or permission by the author. +Please check: + http://www.cr.yp.to/softwarelaw.html +Note: + ucspi-ssl depends on third party software with different + license and/or distribution conditions; in particular + - OpenSSL + - LibreSSL + + +DEPENDENCIES +============ + +ucspi-ssl depends on the following package: + - fehQlibs found on https://www/ipnet/qlibs.html +which is Public Domain as well. + + +Note: +----- + +The author of the program may unsolicitedly change the dependencies. +Thus, it is your obligation to follow and consider any changes! + + +FITNESS +======= + +The author does not guarantee a specific fitness of ucspi-ssl. +If you use ucspi-ssl, it's on your own risk. + + +DISTRIBUTION +============ + +ucspi-ssl may be included in ports and packages under the following conditions: + The port/package has to show the current version number of ucspi-ssl. + This license file has to be included in the distribution. + diff --git a/doc/README.rts b/doc/README.rts new file mode 100755 index 0000000..60ef73b --- /dev/null +++ b/doc/README.rts @@ -0,0 +1,78 @@ +Rudimentary Test System (RTS) +============================= + +History +------- + +Starting with ucspi-tcp, DJB introduced a script called 'rts.test' +to do some unit/system tests for the modules included in here. + +This piece of software was never documented nor its purpose was defined. +William Baxter modified it to work with ucspi-ssl. +DJB used it in the release of djbdns. + + +Components +---------- + +Within (slash)package 'rts' consists of the following pieces: + + a) package/rts [component] is a generic shell script. + b) src/rts.[it], src/rts.[component] are the scripts containing the specific unit tests. + src/rts.it is usually the supervising script, + while src/rts.base includes typically the 'basic' unit tests, + src/rts.[component] is optional. + c) src/exp.[it], src.[bases] and perhaps src/exp.[component] + include the expected results (adapted). + +While [it] and [base] are mandatory, any further [component] needs +to be defined by the (slash)package installation. + + +Defaults and Adjustments +------------------------ + + 1. In order to use rts, the binaries are expected to be install + at their default directories. + 2. Since ucspi-ssl depends on *SSL libraries, the shared libs + shall be available in their default locations. + 3. If you use custom installed *SSL libs, you need to modify + the LD_LIBRARY_PATH. See the file rts.base to get the idea. + + +Invocation +---------- + +'rts' is typically called after a successful compilation and installation. +The $PATH variable includes the current directory of the executed rts.it (./compile). +In order to test the included modules one calls: + + package/rts --> all tests are done (including optional) + package/rts base --> basic unit tests + package/rts [component] --> optional component test + + +Results +------- + +The script rts.[component] is executed in + + ./compile/rts-temp + +to be raised upon call. The results are written to + + ./compile/out.[component] + +and then diff'ed against exp.[component], cleaned up for trivial +run dependencies (like port numbers) and the difference is displayed. + +If there is no difference, nothing is displayed => working as expected. + +However, even if differences are given, they may be due to environment/call +dependencies (like process ids) resulting in some mangled output. + +In case package/rts is called again, the previous results are overwritten. + + +--eh (May, 2023). + diff --git a/doc/TLSVERSION_CIPHERSUITES b/doc/TLSVERSION_CIPHERSUITES new file mode 100644 index 0000000..645e44a --- /dev/null +++ b/doc/TLSVERSION_CIPHERSUITES @@ -0,0 +1,62 @@ +TLS Version & Cipher Suites +--------------------------- + +ucspi-ssl provides two hooks to adjust the TLS version and the Cipher Suite: + +1. Client and Server (sslclient, sslhandle, sslserver): + +The TLS/SSL protocol versions + +- SSLv2 and +- SSLv3 + +are disabled in ucspissl.h. + +- TLSv1 is already included here, but is still commented out. + + +2. The Cipher Suite accepted by the Server (sslhandle, sslserver) + +a) Pre-TLS 1.3 + +Here, you can adjust the settings by means of CIPHER environment variables. +Some typical choices: + +#CIPHERS="'TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH'" +#CIPHERS="TLSv1+HIGH:!SSLv2:!MD5" +CIPHERS="TLSv1.2+HIGH:TLSv1.1+HIGH:!TLSv1+HIGH:!aNULL:!eNULL:@STRENGTH" + +This variable can be statically defined for all connections or used +as environment variable specified with the tcprule database. + +OpenSSL supports even very old and inscure crypto primites like MD5 or DES; +however under current circumstances they are not negotiated. + +b) TLS 1.3 + +While previous TLS understand some phrasings like 'DEFAULT', 'HIGH' in TLS 1.3 +a new API and a new scheme is used +(https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_cipher_list.html): + +>> An empty list is permissible. The default value for the this setting is: + + "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" << + +This means 'TLS_AES_256_GCM_SHA384' has priority. However, you can tweak this to: + + "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" + +thus, the first choice is CHACHA20. In case AES_256 is present, it has +precedence over CHACHA20. + +Remember: In any case, only ECDHE is used as handshake protocol. + + +3. Online Resources + +OpenSSL: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_cipher_list.html + +LibreSSL: https://fossies.org/linux/libressl/man/SSL_CTX_set_cipher_list.3 + + +--eh, Oktober 2023. diff --git a/doc/TLS_1_3 b/doc/TLS_1_3 new file mode 100644 index 0000000..51c7c42 --- /dev/null +++ b/doc/TLS_1_3 @@ -0,0 +1,36 @@ +Installing ucspi-ssl with TLS 1.3 support +----------------------------------------- + +ucspi-ssl-0.10 can use TLS 1.3 capabilities alongside +with your system's previous *SSL installation: + +a) OpenSSL 1.1.1: + +- Download OpenSSL and untar OpenSSL at some path; ie. /usr/local. +- Execute./conf && make. Don't do 'make install'!! + +- conf-ssl: Include path to the header files via -I <path>. + (-I/usr/local/openssl-1.1.1/include) +- conf-ssllib: Include path to the libraries via -L <path>. + (-L/usr/local/openssl-1.1.1 -lssl -lcrypto) + +b) LibreSSL 2.9.x: + +Download LibreSSL and untar LibreSSL at some path; ie. /usr/local. +Execute./conf && make. Don't do 'make install'!! +Do a + ln -s ssl/.libs/libssl.so . + ln -s crypto/.libs/libcrypto.so . +in the LibreSSL main directory. + +- conf-ssl: Include path to the header files via -I <path>. + (-I/usr/local/libressl-2.9.1/include) +- conf-ssllib: Include path to the libraries via -L <path>. + (-L/usr/local/libressl-2.9.1 -lssl -lcrypto) + + + +Recompile ucspi-ssl. +This should be it. + +E. Hoffmann, September 2019. diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 0000000..1c9da9b --- /dev/null +++ b/doc/TODO @@ -0,0 +1,7 @@ +Program like stunnel (web). +Rules tests (web). +CRL support (feh). +OCSPI support (feh). +DANE support (feh). +SSL connection caching (feh). +Migrate whole openssl stuff to wolfssl (bergmann). diff --git a/doc/UCSPI-SSL b/doc/UCSPI-SSL new file mode 100644 index 0000000..69bd25e --- /dev/null +++ b/doc/UCSPI-SSL @@ -0,0 +1,48 @@ +SSL UCSPI protocol definition +Copyright 2001 +SuperScript Technology, Inc. sst@superscript.com + +This document defines the SSL protocol for UCSPI-1996 tools. An SSL +client communicates with an SSL server, on the same machine or on a +different machine, via the TCP/IP protocol through an Internet-domain +socket. The descriptors passed to a SSL UCSPI application are copies of +that socket, dup()ed from a single connect() or accept(). + +[address] consists of two arguments: [hostname] [port]. + +There are three possibilities for [hostname]: the number 0, referring to +the local host; a dotted-decimal IP address, such as 192.48.96.5; or a +name understood by the system's resolver, such as mail.uu.net. SSL UCSPI +servers use only the first IP address from the resolver; SSL UCSPI +clients try each address in turn. + +There are three possibilities for [port]: a positive numeric TCP port +number, such as 25; the number 0, which permits selection of any port +number; or a name understood by the system's getservbyname(), such as +smtp. + +The client and server set up the following environment variables: + + PROTO: the string SSL + SSLLOCALIP: the dotted-decimal IP address of the local host + SSLLOCALPORT: the local SSL port number, in decimal + SSLREMOTEIP: the dotted-decimal IP address of the remote host + SSLREMOTEPORT: the remote SSL port number, in decimal + SSLLOCALHOST, if possible: the resolver's name for SSLLOCALIP + SSLREMOTEHOST, if possible: the resolver's name for SSLREMOTEIP + SSLREMOTEINFO, if possible: the result of a 931/1413/IDENT/TAP query + +Uppercase letters in SSLLOCALHOST and SSLREMOTEHOST are converted to +lowercase. SSLREMOTEINFO is a connection-specific string supplied by the +remote host via 931/1413/IDENT/TAP. + +SSL UCSPI tools take a -R option to turn off 931/1413/IDENT/TAP +querying, and a -r option to turn it back on. SSL UCSPI tools take a -I +option to turn off checking for a client certificate, and a -i option to +turn it back on. SSL UCSPI clients take a -p [locport] option to +require a particular TCP port on the local side of the connection. SSL +UCSPI servers take a -1 option to print the local port number (in +decimal, followed by a newline) to descriptor 1 before closing +descriptor 1 and after preparing to receive connections. SSL UCSPI +servers and clients take a -3 option to read a null-terminated key +password from file descriptor 3. diff --git a/etc/127.0.0.1.pw b/etc/127.0.0.1.pw Binary files differnew file mode 100644 index 0000000..c85ca4d --- /dev/null +++ b/etc/127.0.0.1.pw diff --git a/etc/127.0.0.1_cert.pem b/etc/127.0.0.1_cert.pem new file mode 100644 index 0000000..47de390 --- /dev/null +++ b/etc/127.0.0.1_cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICwjCCAmmgAwIBAgIUdQHW4sgGy2mrH8B4218AK8rDcDwwCgYIKoZIzj0EAwIw +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMB4XDTIzMDkyMDEzMDUxNFoXDTI4MTIwMjEzMDUxNFow +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmDn4CQK9 +gXsdTyM0LrBcl7d3mL3Xiu3X0Eglwf+mpJeP/FYABJsUuj/b03bUUwdjIGH7xoj6 +CQa5f4XSz3ooAKOB5DCB4TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAaBgNVHREEEzARhwR/AAABgglsb2NhbGhvc3QwgZUGA1Ud +IwSBjTCBiqFypHAwbjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREw +DwYDVQQHEwhCcm9va2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxh +Ym9yYXRvcnkxETAPBgNVBAMTCGxvb3BiYWNrghR1AdbiyAbLaasfwHjbXwArysNw +PDAKBggqhkjOPQQDAgNHADBEAiBbOFAkXh9D1CSt641D7Nsr9QS7eArxMLBebWls +3QBXnwIgK7EmciEPznKaXXcTB8n9NwQUvMDaM0lqpE0XyEgENqA= +-----END CERTIFICATE----- diff --git a/etc/127.0.0.1_key.pem b/etc/127.0.0.1_key.pem new file mode 100644 index 0000000..983f8ec --- /dev/null +++ b/etc/127.0.0.1_key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,AB1B9F788B65B4711CF737FDFB536BE4 + +DX4AvhWLBwAAW6qoW6N52rKo3DfBAHkHXY+DEj7GvxHyqXEedzvUXJhFpd9U/MR2 +F/TzuTjTtKRJmTI7ULdRT90/GDch9DybL7abZiCfSPqA1gl/S2E1ewhUb7O8Iz7n +Z+1v+lYOWDznfmSbqyJCUZmz9QI2rASj2dApyeVJlCA= +-----END EC PRIVATE KEY----- diff --git a/etc/127.0.0.1_key.pem.plain b/etc/127.0.0.1_key.pem.plain new file mode 100644 index 0000000..010f8dc --- /dev/null +++ b/etc/127.0.0.1_key.pem.plain @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINvQSFUQX4cojQJ/TkdGAqecoOEI8m/V9UzKBkJTQn1HoAoGCCqGSM49 +AwEHoUQDQgAEmDn4CQK9gXsdTyM0LrBcl7d3mL3Xiu3X0Eglwf+mpJeP/FYABJsU +uj/b03bUUwdjIGH7xoj6CQa5f4XSz3ooAA== +-----END EC PRIVATE KEY----- diff --git a/etc/::1.pw b/etc/::1.pw Binary files differnew file mode 100644 index 0000000..c85ca4d --- /dev/null +++ b/etc/::1.pw diff --git a/etc/::1_cert.pem b/etc/::1_cert.pem new file mode 100644 index 0000000..d67aea7 --- /dev/null +++ b/etc/::1_cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIICzzCCAnWgAwIBAgIUBtVH6POMnmJlLyH0MuUJvpKtTy8wCgYIKoZIzj0EAwIw +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMB4XDTIzMDkyMDEzMDU1MloXDTI4MTIwMjEzMDU1Mlow +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELAT3LgqE +fyay4gJstMSag4n6qWIW+A4lTS2coTdKpDruQu+4MU/hlJTI8RvtYPwE7Qvn69uT +rQUkOASI37tMMKOB8DCB7TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAmBgNVHREEHzAdhxAAAAAAAAAAAAAAAAAAAAABgglsb2Nh +bGhvc3QwgZUGA1UdIwSBjTCBiqFypHAwbjELMAkGA1UEBhMCVVMxETAPBgNVBAgT +CE5ldyBZb3JrMREwDwYDVQQHEwhCcm9va2x5bjEmMCQGA1UEChMddWNzcGktc3Ns +IHJlc2VhcmNoIGxhYm9yYXRvcnkxETAPBgNVBAMTCGxvb3BiYWNrghQG1Ufo84ye +YmUvIfQy5Qm+kq1PLzAKBggqhkjOPQQDAgNIADBFAiEAhMpsgcfPqkPFz+OVfEOn +CT6ateSu6FWl2j9uUzeV3OoCIDWDHBu9jp6M676IDqnBIwDTl+fK6s11AJuJLH+J +yqzP +-----END CERTIFICATE----- diff --git a/etc/::1_key.pem b/etc/::1_key.pem new file mode 100644 index 0000000..cf6fdc5 --- /dev/null +++ b/etc/::1_key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,BBE021D3F3B68368FA5295064A41EC65 + +6N0F4500DFvZAX4dQ1VAxk+gFvZaIYFuawF5YYEVwNY3/DwM71r1XsH7nGyThKN7 +4ZisRFIZ8qOXVl8pDxomQlaW3yMut0JUYoTf5mZhulMhDLNBUM4xhmuRbXqReKA4 +krTUgazSMpz74VoKdZHmWdjqABru9kgWnS28BhmBPS4= +-----END EC PRIVATE KEY----- diff --git a/etc/::1_key.pem.plain b/etc/::1_key.pem.plain new file mode 100644 index 0000000..e27f00e --- /dev/null +++ b/etc/::1_key.pem.plain @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMe4kJ7pk/Uc+9D/1XmQtGwMW1OUFxYSZrntSrXBMoFRoAoGCCqGSM49 +AwEHoUQDQgAELAT3LgqEfyay4gJstMSag4n6qWIW+A4lTS2coTdKpDruQu+4MU/h +lJTI8RvtYPwE7Qvn69uTrQUkOASI37tMMA== +-----END EC PRIVATE KEY----- diff --git a/etc/README.certs.md b/etc/README.certs.md new file mode 100644 index 0000000..05487d1 --- /dev/null +++ b/etc/README.certs.md @@ -0,0 +1,281 @@ +/*! \mainpage + +README.certs +============ + +1. X.509 Certs and key files +---------------------------- + +In this directory you will find: + +a) rootCA_cert.pem -- ECC root CA PEM file; almost 10 years valid +b) rootCA_key.pem -- encypted corresponding key file for signing - password 12345 +c) rootCA_key.pem.plain -- unencypted corresponding key file for signing + +e) ::1_cert.pem -- ECC IPv6 localhost PEM cert +f) ::1_key.pem -- encrypted corresponding key file for authentication - password testcert +g) ::1_key.pem.plain -- unencrypted corresponding key file for authentication + +h) 127.0.0.1_cert.pem -- ECC IPv4 localhost PEM cert +i) 127.0.0.1_key.pem -- enrypted corresponding key file for authentication - password testcert +j) 127.0.0.1_key.pem.plain -- unencrypted corresponding key file for authentication + +k) localhost_cert.pem -- ECC generic localhost PEM cert +l) localhost.pem -- encrypted corresponding key file for authentication - password testcert +m) localhost.pem -- unencrypted corresponding key file for authentication + +n) chain6.pem -- chained ::1_cert.pam + rootCA_cert.pem +o) chain4.pem -- chained 127.0.0.1_cert.pam + rootCA_cert.pem + +p) dh2048.pem -- Diffie-Hellman parameter file with 2048 bit + +All x509 certs are generated by means of the ECC prime256v1 algorithm. +CA cert validity: About 10 years from September 2023. +Other certs valdity is about 5 years starting at September 2023. + +2. Usage +-------- + +These x509 certs and key files are provided to allow an initial +setup and test of UCSPI-SSL's sslserver and companions. + +The use of ECC signatures requires OpenSSL > 1.1.1 or LibreSSL > 3.3.1. + +3. rootCA_cert.pem +------------------ + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2a:33:3a:76:03:ac:7a:0f:23:38:0a:5c:e3:43:f2:9d:74:9d:ae:99 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = ucspi-ssl research ca + Validity + Not Before: Sep 20 13:04:38 2023 GMT + Not After : Oct 17 13:04:38 2033 GMT + Subject: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = ucspi-ssl research ca + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:74:87:e3:06:ee:44:a1:7b:4c:ca:d4:d9:13:fa: + d2:8a:4c:08:42:84:ae:3f:f9:97:9d:c2:49:48:ad: + 0f:3d:ba:c2:26:df:28:22:45:63:7c:fe:28:b1:e1: + 90:1d:33:4f:62:3f:b0:ff:0c:04:52:0b:75:1b:6b: + 72:76:a1:00:07 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Subject Key Identifier: + A5:33:0C:F4:15:5B:BD:10:6A:71:A2:79:EB:00:77:8C:7A:30:35:83 + X509v3 Authority Key Identifier: + keyid:A5:33:0C:F4:15:5B:BD:10:6A:71:A2:79:EB:00:77:8C:7A:30:35:83 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:99:53:0a:1c:5f:b2:1c:80:c0:05:17:05:f7: + 75:96:28:87:bd:c3:d5:ca:2f:bf:a4:17:5e:66:ac:bb:4f:68: + 50:02:20:37:25:2a:62:2e:5d:31:8f:d7:71:3a:4d:b9:39:6b: + f8:02:5a:50:7b:c9:74:33:11:57:24:a9:2b:7a:39:37:b6 +-----BEGIN CERTIFICATE----- +MIICSzCCAfGgAwIBAgIUKjM6dgOseg8jOApc40PynXSdrpkwCgYIKoZIzj0EAwIw +ezELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxHjAc +BgNVBAMTFXVjc3BpLXNzbCByZXNlYXJjaCBjYTAeFw0yMzA5MjAxMzA0MzhaFw0z +MzEwMTcxMzA0MzhaMHsxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazER +MA8GA1UEBxMIQnJvb2tseW4xJjAkBgNVBAoTHXVjc3BpLXNzbCByZXNlYXJjaCBs +YWJvcmF0b3J5MR4wHAYDVQQDExV1Y3NwaS1zc2wgcmVzZWFyY2ggY2EwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAAR0h+MG7kShe0zK1NkT+tKKTAhChK4/+ZedwklI +rQ89usIm3ygiRWN8/iix4ZAdM09iP7D/DARSC3Uba3J2oQAHo1MwUTAdBgNVHQ4E +FgQUpTMM9BVbvRBqcaJ56wB3jHowNYMwHwYDVR0jBBgwFoAUpTMM9BVbvRBqcaJ5 +6wB3jHowNYMwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAmVMK +HF+yHIDABRcF93WWKIe9w9XKL7+kF15mrLtPaFACIDclKmIuXTGP13E6Tbk5a/gC +WlB7yXQzEVckqSt6OTe2 +-----END CERTIFICATE----- + +4. ::1_cert.pem +--------------- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 06:d5:47:e8:f3:8c:9e:62:65:2f:21:f4:32:e5:09:be:92:ad:4f:2f + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = loopback + Validity + Not Before: Sep 20 13:05:52 2023 GMT + Not After : Dec 2 13:05:52 2028 GMT + Subject: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = loopback + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:2c:04:f7:2e:0a:84:7f:26:b2:e2:02:6c:b4:c4: + 9a:83:89:fa:a9:62:16:f8:0e:25:4d:2d:9c:a1:37: + 4a:a4:3a:ee:42:ef:b8:31:4f:e1:94:94:c8:f1:1b: + ed:60:fc:04:ed:0b:e7:eb:db:93:ad:05:24:38:04: + 88:df:bb:4c:30 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Subject Alternative Name: + IP Address:0:0:0:0:0:0:0:1, DNS:localhost + X509v3 Authority Key Identifier: + DirName:/C=US/ST=New York/L=Brooklyn/O=ucspi-ssl research laboratory/CN=loopback + serial:06:D5:47:E8:F3:8C:9E:62:65:2F:21:F4:32:E5:09:BE:92:AD:4F:2F + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:84:ca:6c:81:c7:cf:aa:43:c5:cf:e3:95:7c: + 43:a7:09:3e:9a:b5:e4:ae:e8:55:a5:da:3f:6e:53:37:95:dc: + ea:02:20:35:83:1c:1b:bd:8e:9e:8c:eb:be:88:0e:a9:c1:23: + 00:d3:97:e7:ca:ea:cd:75:00:9b:89:2c:7f:89:ca:ac:cf +-----BEGIN CERTIFICATE----- +MIICzzCCAnWgAwIBAgIUBtVH6POMnmJlLyH0MuUJvpKtTy8wCgYIKoZIzj0EAwIw +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMB4XDTIzMDkyMDEzMDU1MloXDTI4MTIwMjEzMDU1Mlow +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELAT3LgqE +fyay4gJstMSag4n6qWIW+A4lTS2coTdKpDruQu+4MU/hlJTI8RvtYPwE7Qvn69uT +rQUkOASI37tMMKOB8DCB7TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAmBgNVHREEHzAdhxAAAAAAAAAAAAAAAAAAAAABgglsb2Nh +bGhvc3QwgZUGA1UdIwSBjTCBiqFypHAwbjELMAkGA1UEBhMCVVMxETAPBgNVBAgT +CE5ldyBZb3JrMREwDwYDVQQHEwhCcm9va2x5bjEmMCQGA1UEChMddWNzcGktc3Ns +IHJlc2VhcmNoIGxhYm9yYXRvcnkxETAPBgNVBAMTCGxvb3BiYWNrghQG1Ufo84ye +YmUvIfQy5Qm+kq1PLzAKBggqhkjOPQQDAgNIADBFAiEAhMpsgcfPqkPFz+OVfEOn +CT6ateSu6FWl2j9uUzeV3OoCIDWDHBu9jp6M676IDqnBIwDTl+fK6s11AJuJLH+J +yqzP +-----END CERTIFICATE----- + +5. 127.0.0.1_cert.pem +--------------------- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 75:01:d6:e2:c8:06:cb:69:ab:1f:c0:78:db:5f:00:2b:ca:c3:70:3c + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = loopback + Validity + Not Before: Sep 20 13:05:14 2023 GMT + Not After : Dec 2 13:05:14 2028 GMT + Subject: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = loopback + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:98:39:f8:09:02:bd:81:7b:1d:4f:23:34:2e:b0: + 5c:97:b7:77:98:bd:d7:8a:ed:d7:d0:48:25:c1:ff: + a6:a4:97:8f:fc:56:00:04:9b:14:ba:3f:db:d3:76: + d4:53:07:63:20:61:fb:c6:88:fa:09:06:b9:7f:85: + d2:cf:7a:28:00 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Subject Alternative Name: + IP Address:127.0.0.1, DNS:localhost + X509v3 Authority Key Identifier: + DirName:/C=US/ST=New York/L=Brooklyn/O=ucspi-ssl research laboratory/CN=loopback + serial:75:01:D6:E2:C8:06:CB:69:AB:1F:C0:78:DB:5F:00:2B:CA:C3:70:3C + + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:5b:38:50:24:5e:1f:43:d4:24:ad:eb:8d:43:ec: + db:2b:f5:04:bb:78:0a:f1:30:b0:5e:6d:69:6c:dd:00:57:9f: + 02:20:2b:b1:26:72:21:0f:ce:72:9a:5d:77:13:07:c9:fd:37: + 04:14:bc:c0:da:33:49:6a:a4:4d:17:c8:48:04:36:a0 +-----BEGIN CERTIFICATE----- +MIICwjCCAmmgAwIBAgIUdQHW4sgGy2mrH8B4218AK8rDcDwwCgYIKoZIzj0EAwIw +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMB4XDTIzMDkyMDEzMDUxNFoXDTI4MTIwMjEzMDUxNFow +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmDn4CQK9 +gXsdTyM0LrBcl7d3mL3Xiu3X0Eglwf+mpJeP/FYABJsUuj/b03bUUwdjIGH7xoj6 +CQa5f4XSz3ooAKOB5DCB4TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAaBgNVHREEEzARhwR/AAABgglsb2NhbGhvc3QwgZUGA1Ud +IwSBjTCBiqFypHAwbjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREw +DwYDVQQHEwhCcm9va2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxh +Ym9yYXRvcnkxETAPBgNVBAMTCGxvb3BiYWNrghR1AdbiyAbLaasfwHjbXwArysNw +PDAKBggqhkjOPQQDAgNHADBEAiBbOFAkXh9D1CSt641D7Nsr9QS7eArxMLBebWls +3QBXnwIgK7EmciEPznKaXXcTB8n9NwQUvMDaM0lqpE0XyEgENqA= +-----END CERTIFICATE----- + +6. localhost_cert.pem +--------------------- + +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7a:6a:2a:23:7c:b4:99:26:bd:19:ee:88:72:b4:1c:8e:4d:3b:5a:40 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = localhost + Validity + Not Before: Sep 20 13:06:24 2023 GMT + Not After : Dec 2 13:06:24 2028 GMT + Subject: C = US, ST = New York, L = Brooklyn, O = ucspi-ssl research laboratory, CN = localhost + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:13:bc:51:f1:ce:42:39:a5:da:fd:81:e7:4d:03: + fd:3d:93:9d:63:ce:d7:32:0c:1b:c1:f3:1a:43:84: + f4:c5:db:79:c9:7e:e5:3d:ad:de:ca:66:fd:f5:a7: + 1c:80:18:20:b6:c6:b1:18:76:30:0a:3f:5f:ac:ca: + a4:90:d4:8b:b0 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Subject Alternative Name: + DNS:localhost, IP Address:0.0.0.0, IP Address:0:0:0:0:0:0:0:0 + X509v3 Authority Key Identifier: + DirName:/C=US/ST=New York/L=Brooklyn/O=ucspi-ssl research laboratory/CN=localhost + serial:7A:6A:2A:23:7C:B4:99:26:BD:19:EE:88:72:B4:1C:8E:4D:3B:5A:40 + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:71:4c:08:c1:2a:7e:31:a9:33:5a:92:cb:da:81: + 85:ed:74:66:38:f8:5b:f1:55:1c:e4:bb:ba:3e:4e:83:76:fb: + 02:21:00:d3:82:51:6f:87:b0:32:14:1e:e0:f0:8c:43:cf:1c: + f2:2b:ca:70:a9:d3:26:55:00:91:94:29:87:06:8d:3e:3e +-----BEGIN CERTIFICATE----- +MIIC2DCCAn6gAwIBAgIUemoqI3y0mSa9Ge6IcrQcjk07WkAwCgYIKoZIzj0EAwIw +bzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxEjAQ +BgNVBAMTCWxvY2FsaG9zdDAeFw0yMzA5MjAxMzA2MjRaFw0yODEyMDIxMzA2MjRa +MG8xCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazERMA8GA1UEBxMIQnJv +b2tseW4xJjAkBgNVBAoTHXVjc3BpLXNzbCByZXNlYXJjaCBsYWJvcmF0b3J5MRIw +EAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQTvFHx +zkI5pdr9gedNA/09k51jztcyDBvB8xpDhPTF23nJfuU9rd7KZv31pxyAGCC2xrEY +djAKP1+syqSQ1Iuwo4H3MIH0MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBMGA1Ud +JQQMMAoGCCsGAQUFBwMCMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEAAAAAIcQAAAA +AAAAAAAAAAAAAAAAADCBlgYDVR0jBIGOMIGLoXOkcTBvMQswCQYDVQQGEwJVUzER +MA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCEJyb29rbHluMSYwJAYDVQQKEx11 +Y3NwaS1zc2wgcmVzZWFyY2ggbGFib3JhdG9yeTESMBAGA1UEAxMJbG9jYWxob3N0 +ghR6aiojfLSZJr0Z7ohytByOTTtaQDAKBggqhkjOPQQDAgNIADBFAiBxTAjBKn4x +qTNaksvagYXtdGY4+FvxVRzku7o+ToN2+wIhANOCUW+HsDIUHuDwjEPPHPIrynCp +0yZVAJGUKYcGjT4+ +-----END CERTIFICATE----- diff --git a/etc/chain4.pem b/etc/chain4.pem new file mode 100644 index 0000000..e077b1f --- /dev/null +++ b/etc/chain4.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIICwzCCAmmgAwIBAgIUN7BRYDaZRn7lfl1+YKNJkUjn94MwCgYIKoZIzj0EAwIw +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMB4XDTIzMDkyMDA5MjAxMVoXDTI4MDgyNDA5MjAxMVow +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB8Bd3b6g +C+BJ7scSs8A4RWIJEDIszPNUfe7WekTLeZQ+d0zotI662zN4L/4w347Np259Lltj +scIAK21VW0A6cqOB5DCB4TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAaBgNVHREEEzARhwR/AAABgglsb2NhbGhvc3QwgZUGA1Ud +IwSBjTCBiqFypHAwbjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREw +DwYDVQQHEwhCcm9va2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxh +Ym9yYXRvcnkxETAPBgNVBAMTCGxvb3BiYWNrghQ3sFFgNplGfuV+XX5go0mRSOf3 +gzAKBggqhkjOPQQDAgNIADBFAiBufnYWcxTdLx+lq8G+53FGUML6XQD8CIwaDiLu +2RRo7wIhAKf7UAarBn5jM43Pk/uMM7apYl26hJqwHxfWmSRg39nH +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICSjCCAfGgAwIBAgIUVEurfE97+agqBpy4eFwmRtox8mIwCgYIKoZIzj0EAwIw +ezELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxHjAc +BgNVBAMTFXVjc3BpLXNzbCByZXNlYXJjaCBjYTAeFw0yMzA5MjAwOTEwMzJaFw0z +MzEwMTcwOTEwMzJaMHsxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazER +MA8GA1UEBxMIQnJvb2tseW4xJjAkBgNVBAoTHXVjc3BpLXNzbCByZXNlYXJjaCBs +YWJvcmF0b3J5MR4wHAYDVQQDExV1Y3NwaS1zc2wgcmVzZWFyY2ggY2EwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAASLB+0+8+OjIMt8d9b3APWKJg2m/3Awz2i+yQbM +ueuZcBl2iJ5ARw8SLdGP2HlXqD21S2Odky4n1tFyenAinFsxo1MwUTAdBgNVHQ4E +FgQU1Oskvg3Ho/3cpocdtSzwMO9iclEwHwYDVR0jBBgwFoAU1Oskvg3Ho/3cpocd +tSzwMO9iclEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNHADBEAiBsFlRi +cqi7FdZW3D/W/PGrJh746xrgyRl9xaUdRilroQIgJM49nsvckrAPw/2blYHBV/H8 +/RwE/Jr8CGVYICGy030= +-----END CERTIFICATE----- diff --git a/etc/chain6.pem b/etc/chain6.pem new file mode 100644 index 0000000..a4e59fc --- /dev/null +++ b/etc/chain6.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIICzzCCAnWgAwIBAgIUBtVH6POMnmJlLyH0MuUJvpKtTy8wCgYIKoZIzj0EAwIw +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMB4XDTIzMDkyMDEzMDU1MloXDTI4MTIwMjEzMDU1Mlow +bjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxETAP +BgNVBAMTCGxvb3BiYWNrMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELAT3LgqE +fyay4gJstMSag4n6qWIW+A4lTS2coTdKpDruQu+4MU/hlJTI8RvtYPwE7Qvn69uT +rQUkOASI37tMMKOB8DCB7TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUE +DDAKBggrBgEFBQcDATAmBgNVHREEHzAdhxAAAAAAAAAAAAAAAAAAAAABgglsb2Nh +bGhvc3QwgZUGA1UdIwSBjTCBiqFypHAwbjELMAkGA1UEBhMCVVMxETAPBgNVBAgT +CE5ldyBZb3JrMREwDwYDVQQHEwhCcm9va2x5bjEmMCQGA1UEChMddWNzcGktc3Ns +IHJlc2VhcmNoIGxhYm9yYXRvcnkxETAPBgNVBAMTCGxvb3BiYWNrghQG1Ufo84ye +YmUvIfQy5Qm+kq1PLzAKBggqhkjOPQQDAgNIADBFAiEAhMpsgcfPqkPFz+OVfEOn +CT6ateSu6FWl2j9uUzeV3OoCIDWDHBu9jp6M676IDqnBIwDTl+fK6s11AJuJLH+J +yqzP +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICSzCCAfGgAwIBAgIUKjM6dgOseg8jOApc40PynXSdrpkwCgYIKoZIzj0EAwIw +ezELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxHjAc +BgNVBAMTFXVjc3BpLXNzbCByZXNlYXJjaCBjYTAeFw0yMzA5MjAxMzA0MzhaFw0z +MzEwMTcxMzA0MzhaMHsxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazER +MA8GA1UEBxMIQnJvb2tseW4xJjAkBgNVBAoTHXVjc3BpLXNzbCByZXNlYXJjaCBs +YWJvcmF0b3J5MR4wHAYDVQQDExV1Y3NwaS1zc2wgcmVzZWFyY2ggY2EwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAAR0h+MG7kShe0zK1NkT+tKKTAhChK4/+ZedwklI +rQ89usIm3ygiRWN8/iix4ZAdM09iP7D/DARSC3Uba3J2oQAHo1MwUTAdBgNVHQ4E +FgQUpTMM9BVbvRBqcaJ56wB3jHowNYMwHwYDVR0jBBgwFoAUpTMM9BVbvRBqcaJ5 +6wB3jHowNYMwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAmVMK +HF+yHIDABRcF93WWKIe9w9XKL7+kF15mrLtPaFACIDclKmIuXTGP13E6Tbk5a/gC +WlB7yXQzEVckqSt6OTe2 +-----END CERTIFICATE----- diff --git a/etc/dh2048.pem b/etc/dh2048.pem new file mode 100644 index 0000000..74bf248 --- /dev/null +++ b/etc/dh2048.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAqnI4e0GO/I2aCHDei9aycopVzMcfvf/JK4gcxrzvAbCfj6EwPYIc +iJZB1+lkAvF3ab1EOgsxRdYB4Yq/s1ThM7H2oEH3yQqN20zPsF3M5neEHPJS0SBb +hQPQchY3BFe8U4Y279FVLTC8G1zabBewRjLSiuUNIQKogbaFMtGco2HLbqDJ01kY +DY95WDU7oSb2FPa7u8+rQUYLgR3fRjIXD35cDd/WeS8fUWidUhlR4X9K2AXq5d8s +Ew1x3fPmwTNi1bP9438oMKPzrVpY9TsvEJMkOMYsfOJlL1dQ8Az/aKR+5oxYX3pm +gUKBYrLHlbPtmW6a2UUWQCJIAJ/gcBBiywIBAg== +-----END DH PARAMETERS----- diff --git a/etc/localhost.pw b/etc/localhost.pw Binary files differnew file mode 100644 index 0000000..c85ca4d --- /dev/null +++ b/etc/localhost.pw diff --git a/etc/localhost_cert.pem b/etc/localhost_cert.pem new file mode 100644 index 0000000..3a72347 --- /dev/null +++ b/etc/localhost_cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC2DCCAn6gAwIBAgIUemoqI3y0mSa9Ge6IcrQcjk07WkAwCgYIKoZIzj0EAwIw +bzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxEjAQ +BgNVBAMTCWxvY2FsaG9zdDAeFw0yMzA5MjAxMzA2MjRaFw0yODEyMDIxMzA2MjRa +MG8xCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazERMA8GA1UEBxMIQnJv +b2tseW4xJjAkBgNVBAoTHXVjc3BpLXNzbCByZXNlYXJjaCBsYWJvcmF0b3J5MRIw +EAYDVQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQTvFHx +zkI5pdr9gedNA/09k51jztcyDBvB8xpDhPTF23nJfuU9rd7KZv31pxyAGCC2xrEY +djAKP1+syqSQ1Iuwo4H3MIH0MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBMGA1Ud +JQQMMAoGCCsGAQUFBwMCMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEAAAAAIcQAAAA +AAAAAAAAAAAAAAAAADCBlgYDVR0jBIGOMIGLoXOkcTBvMQswCQYDVQQGEwJVUzER +MA8GA1UECBMITmV3IFlvcmsxETAPBgNVBAcTCEJyb29rbHluMSYwJAYDVQQKEx11 +Y3NwaS1zc2wgcmVzZWFyY2ggbGFib3JhdG9yeTESMBAGA1UEAxMJbG9jYWxob3N0 +ghR6aiojfLSZJr0Z7ohytByOTTtaQDAKBggqhkjOPQQDAgNIADBFAiBxTAjBKn4x +qTNaksvagYXtdGY4+FvxVRzku7o+ToN2+wIhANOCUW+HsDIUHuDwjEPPHPIrynCp +0yZVAJGUKYcGjT4+ +-----END CERTIFICATE----- diff --git a/etc/localhost_key.pem b/etc/localhost_key.pem new file mode 100644 index 0000000..3a43e19 --- /dev/null +++ b/etc/localhost_key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,54AAA04CB6E610C382C85398143D9141 + +OXjBuAb3HPOKmTMPbL6vTPgH/4U2JrSjpINRz2a36m8zrpNtWxR/afhuxEEjoOos +eOi7VncvCBQmfPCkRQ9Qz2dBk4BIiLyKuHvnIfmjnwpMZNkcvGk0DxasL0pIB0AS +OAhrQXlq/p+PFzQzbHJcwxKIcMZlHwZxYvBucxh/5OA= +-----END EC PRIVATE KEY----- diff --git a/etc/localhost_key.pem.plain b/etc/localhost_key.pem.plain new file mode 100644 index 0000000..62cf3bb --- /dev/null +++ b/etc/localhost_key.pem.plain @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIEtSI0464/pczgdCvhrMkRw/wj3W3vw2RIUNgt6e0uT+oAoGCCqGSM49 +AwEHoUQDQgAEE7xR8c5COaXa/YHnTQP9PZOdY87XMgwbwfMaQ4T0xdt5yX7lPa3e +ymb99accgBggtsaxGHYwCj9frMqkkNSLsA== +-----END EC PRIVATE KEY----- diff --git a/etc/rootCA_cert.pem b/etc/rootCA_cert.pem new file mode 100644 index 0000000..ed02b49 --- /dev/null +++ b/etc/rootCA_cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSzCCAfGgAwIBAgIUKjM6dgOseg8jOApc40PynXSdrpkwCgYIKoZIzj0EAwIw +ezELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhCcm9v +a2x5bjEmMCQGA1UEChMddWNzcGktc3NsIHJlc2VhcmNoIGxhYm9yYXRvcnkxHjAc +BgNVBAMTFXVjc3BpLXNzbCByZXNlYXJjaCBjYTAeFw0yMzA5MjAxMzA0MzhaFw0z +MzEwMTcxMzA0MzhaMHsxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazER +MA8GA1UEBxMIQnJvb2tseW4xJjAkBgNVBAoTHXVjc3BpLXNzbCByZXNlYXJjaCBs +YWJvcmF0b3J5MR4wHAYDVQQDExV1Y3NwaS1zc2wgcmVzZWFyY2ggY2EwWTATBgcq +hkjOPQIBBggqhkjOPQMBBwNCAAR0h+MG7kShe0zK1NkT+tKKTAhChK4/+ZedwklI +rQ89usIm3ygiRWN8/iix4ZAdM09iP7D/DARSC3Uba3J2oQAHo1MwUTAdBgNVHQ4E +FgQUpTMM9BVbvRBqcaJ56wB3jHowNYMwHwYDVR0jBBgwFoAUpTMM9BVbvRBqcaJ5 +6wB3jHowNYMwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAmVMK +HF+yHIDABRcF93WWKIe9w9XKL7+kF15mrLtPaFACIDclKmIuXTGP13E6Tbk5a/gC +WlB7yXQzEVckqSt6OTe2 +-----END CERTIFICATE----- diff --git a/man/Makefile b/man/Makefile new file mode 100644 index 0000000..82c9f4e --- /dev/null +++ b/man/Makefile @@ -0,0 +1,44 @@ +# Don't edit Makefile! Use ../conf-* for configuration. + +SHELL=/bin/sh + +default: one two + +https@.0: \ +https@.1 + nroff -man https@.1 > https@.0 + +sslcat.0: \ +sslcat.1 + nroff -man sslcat.1 > sslcat.0 + +sslclient.0: \ +sslclient.1 + nroff -man sslclient.1 > sslclient.0 + +sslconnect.0: \ +sslconnect.1 + nroff -man sslconnect.1 > sslconnect.0 + +sslhandle.0: \ +sslhandle.1 + nroff -man sslhandle.1 > sslhandle.0 + +sslserver.0: \ +sslserver.1 + nroff -man sslserver.1 > sslserver.0 + +clean: \ +TARGETS + rm -f `cat TARGETS` + gzip -q -d *.gz + +ucspi-tls.0: \ +ucspi-tls.2 + nroff -man ucspi-tls.2 > ucspi-tls.0 + +one: \ +https@.0 sslcat.0 sslclient.0 sslconnect.0 sslserver.0 sslhandle.0 + +two: \ +ucspi-tls.0 diff --git a/man/Makefile.mandoc b/man/Makefile.mandoc new file mode 100644 index 0000000..343da1b --- /dev/null +++ b/man/Makefile.mandoc @@ -0,0 +1,44 @@ +# Don't edit Makefile! Use ../conf-* for configuration. + +SHELL=/bin/sh + +default: one two + +https@.0: \ +https@.1 + mandoc -man https@.1 > https@.0 + +sslcat.0: \ +sslcat.1 + mandoc -man sslcat.1 > sslcat.0 + +sslclient.0: \ +sslclient.1 + mandoc -man sslclient.1 > sslclient.0 + +sslconnect.0: \ +sslconnect.1 + mandoc -man sslconnect.1 > sslconnect.0 + +sslhandle.0: \ +sslhandle.1 + mandoc -man sslhandle.1 > sslhandle.0 + +sslserver.0: \ +sslserver.1 + mandoc -man sslserver.1 > sslserver.0 + +clean: \ +TARGETS + rm -f `cat TARGETS` + gzip -q -d *.gz + +ucspi-tls.0: \ +ucspi-tls.2 + mandoc -man ucspi-tls.2 > ucspi-tls.0 + +one: \ +https@.0 sslcat.0 sslclient.0 sslconnect.0 sslserver.0 sslhandle.0 + +two: \ +ucspi-tls.0 diff --git a/man/TARGETS b/man/TARGETS new file mode 100644 index 0000000..7bb7ddb --- /dev/null +++ b/man/TARGETS @@ -0,0 +1,7 @@ +https@.0 +sslcat.0 +sslclient.0 +sslconnect.0 +sslhandle.0 +sslserver.0 +ucspi-tls.0 diff --git a/man/https@.1 b/man/https@.1 new file mode 100644 index 0000000..eccd29f --- /dev/null +++ b/man/https@.1 @@ -0,0 +1,57 @@ +.TH https@ 1 +.SH NAME +https@ \- simple HTTPS client +.SH SYNOPSIS +.B https@ +.I host +[ +.I page +.I port +.I args +] +.SH DESCRIPTION +.B https@ +connects via the IP[v4|v6] protocol to +.I host +on +.I port +via TCP, and then attempts an SSL connection. It sends the request: + +.EX + GET /page HTTP/1.0 + Host: host +.EE + +and prints the body of the response, removing the CR from the end of each line. + +If +.I port +is not supplied, +.B https@ +uses TCP port 443 (HTTPS). + +If +.I page +is not supplied, +.B https@ +asks for / from +.IR host . + +If +.I host is not supplied, +.B https@ +connects to the local host. + +If +.I args +are supplied, they are passed to +.B https@ +unmodified. +.SH SEE ALSO +sslserver(1), +sslclient(1), +sslconnect(1), +sslcat(1), +tcp-environ(5). +.SH REFERENCE +http://httpd.apache.org/docs/2.4/mod/mod_ssl.html diff --git a/man/sslcat.1 b/man/sslcat.1 new file mode 100644 index 0000000..786d80e --- /dev/null +++ b/man/sslcat.1 @@ -0,0 +1,48 @@ +.TH sslcat 1 +.SH sslcat +sslcat \- simple ssl upload of a file with verbose output +.SH SYNOPSIS +.B sslcat +[ +.I host +.I port +.I args +] +.SH DESCRIPTION +.B sslcat +connects via the IP[v4|v6] protocol to +.I host +on +.I port +via TCP, and then attempts an SSL connection while +sending the data available on file descriptor 6 +to the server. +It prints any data it receives. +.B sslcat +can be used to transfer binary data. +It does no conversion other than SSL encoding and decoding. + +If +.I port +is not supplied, +.B sslcat +uses TCP port 443 (HTTPS). + +If +.I host +is not supplied, +.B sslcat +connects to the local host. + +If +.I args +are supplied, they are passed to +.B sslclient +unmodified. + +.SH SEE ALSO +sslserver(1), +sslclient(1), +sslcat(1), +https@(1), +tcp-environ(5) diff --git a/man/sslclient.1 b/man/sslclient.1 new file mode 100644 index 0000000..7ef0041 --- /dev/null +++ b/man/sslclient.1 @@ -0,0 +1,254 @@ +.TH sslclient 1 +.SH NAME +sslclient \- setup a TLS client connection +.SH SYNOPSIS +.B sslclient +[ +.I opts +] +.I host +.I port +.I prog +.SH DESCRIPTION +.I opts +is a series of getopt-style options, +.I host +is a host name for the client to connect to, and +.I prog +is one or more arguments specifying a program to run +for each successful connection. + +.B sslclient +attempts to connect to a TCP server at +.I host +.IR port . +The server's address is given by +.I host +and +.IR port . +.I host +may be +.IR 0 , +which is identical to +.IR 127.0.0.1 , +or +.IR ::1 +referring to the IPv6 loopback address, +a compactified IPv6 address, +a dotted-decimal IPv4 address, +or a host name. +If a host name is given, +.B sslclient +facilitates a DNS lookup and tries each address in turn. + +If the connection succeeds, +.B sslclient +runs +.IR prog , +with file descriptors 6 and 7 reading from and +writing to a child process ssl. +The ssl process attempts an SSL connect via the network. +If it succeeds, it translates data between +.I prog +and the network, performing any necessary SSL encoding and decoding. + +Before running +.I prog, +.B sslclient +sets certain environment variables. +.SH OPTIONS +.B General Options: +.TP +.B \-q +Quiet. Do not print error messages. +.TP +.B \-Q +(Default.) Print error messages. +.TP +.B \-v +Verbose. Print error messages and status messages. +.P +.B Connection options: +.TP +.B \-4 +Use IPv4 sockets for connections and DNS queries. +.TP +.B \-6 +Force IPv6 mode for connections and set up in UCSPI environment variables. +.TP +.B \-T \fIx+y +Give up on the connection attempt or SSL connection attempt after +.I x+y +seconds. The default value is: 2+58. When a +.I host +has several IP addresses, +.B sslclient +tries to connect to the first IP address, waits +.I x +seconds, tries to connect to the second IP address, waits +- Ix +seconds, etc.; then it retries each address that timed out, waiting +.I y +seconds per address. You may omit +.I +y +to skip the second try. +.TP +.B \-i \fIlocalip +Use +.I localip +as the IP address for the local side of the connection; quit if +.I localip +is not available. Normally +.B sslclient +lets the operating system choose an address. +.TP +.B \-p \fIlocalport +Use +.I localport +as the TCP port for the local side of the connection; quit if +.I localport +is not available. Normally +.B sslclient +lets the operating system choose a port. +.TP +.B \-d +Delay sending data for a fraction of a second whenever +the remote host is responding slowly. +This is currently the default, but it may not be in the future; +if you want it, set it explicitly. +.TP +.B \-D +Never delay sending data; enable TCP_NODELAY. +.TP +.B \-I \fIifname +Use +.I ifname +as the local network interface. This is only defined for IPv6 sockets +and needed if you use link-local IPv6 addresses. +.TP +.B \-M +(Default.) No Server Name Indications are present. +.TP +.B \-m +Employ Server Name Indication (SNI) for +the given +.I hostname +in the Client Helo. + +\fINote\fR: You can use \fIDNSCACHEIP\fR to set the DNS resolver IP dynamically. + +.P +.B X509 certificate handling: +.TP +.B \-3 +Read a null-terminated +.I key password +from file descriptor 3. +.TP +.B \-a \fIcafile +Override the compiled-in CA file name. +The CA file contains the list of CAs used to verify the server certificate. +.TP +.B \-A \fIcadir +Override the compiled-in CA directory name. +The CA directory contains certificates files used +to verify the client certificate. This list augments the list from +.I \-a \fIcafile. +.TP +.B \-c \fIcertfile +Use the client certificate in +.IR certfile . +.TP +.B \-k \fIkeyfile +Use the client certificate key in +.IR keyfile . +.TP +.B \-V \fIverifydepth +Verify the server certificate chain to depth +.IR verifydepth . +The default value is 1. +.TP +.B \-z \fIciphers +Use the cipher list specified in +.IR ciphers . +.TP +.B \-x +(Default.) Verify the server certificate. +.TP +.B \-X +Do not verify the server certificate. +.TP +.B \-n +(Default.) Verify that the server host name matches +the FQDN provided in the certificate. +.TP +.B \-N +Do not verify that the server host name matches +the FQDN provided in the certificate. +.P +.B Data-gathering options: +.TP +.B \-h +(Default.) Look up the remote host name in DNS +to set the environment variable $SSLREMOTEHOST. +.TP +.B \-H +Do not look up the remote host name in DNS; +remove the environment variable $SSLREMOTEHOST. +.TP +.B \-l \fIlocalname +Do not look up the local host name in DNS; use +.I localname +for the environment variable $SSLLOCALHOST. +A common choice for +.I localname +is +.I 0 +or +.IR :: . +.TP +.B \-r +Attempt to obtain $SSLREMOTEINFO from the remote host. +.TP +.B \-R +(Default.) Do not attempt to obtain $SSLREMOTEINFO from the remote host. +.TP +.B \-t \fIn +Give up on the $SSLREMOTEINFO connection attempt after +.I n +seconds. The default value is: 26. +.TP +.B \-w \fIn +Give up on a connection or program after waiting +.I n +seconds for read or write. The default value is: 3600. +.TP +.B \-s +Store client and server certificate information in the environment, a la mod_ssl. +.TP +.B \-S +(Default.) Do not store client and server certificate information in the environment. +.TP +.B \-e +Set protocol environment a la +.BR tcpserver . +Set $PROTO, $TCPLOCALIP, $TCPLOCALPORT, $TCPLOCALHOST, $TCPREMOTEIP, +$TCPREMOTEPORT, $TCPREMOTEHOST, and $TCPREMOTEINFO +from the corresponding $SSL variables. +.TP +.B \-E +(Default.) Do not set any +.B tcpserver +environment variables. +.SH SEE ALSO +sslserver(1), +sslhandle(1), +sslconnect(1), +sslcat(1), +https@(1), +ucspi-tls(2), +tcpclient(1), +tcpserver(1), +tcp-environ(5). +.SH REFERENCE +http://httpd.apache.org/docs/2.4/mod/mod_ssl.html diff --git a/man/sslconnect.1 b/man/sslconnect.1 new file mode 100644 index 0000000..9888e23 --- /dev/null +++ b/man/sslconnect.1 @@ -0,0 +1,55 @@ +.TH sslconnect 1 +.SH sslconnect +sslconnect \- simple sslclient with verbose output +.SH SYNOPSIS +.B sslconnect +[ +.I host +.I port +.I args +] +.SH DESCRIPTION +.B sslconnect +connects via the IP[v4|v6] protocol to +.I host on +.I port +using TCP, and attempts an SSL connection. +It sends its standard input to the server, +printing a CR after each LF, and prints any data +it receives from the server to standard output. +.B sslconnect +can be used to fetch binary data. +It does no conversion other than SSL encoding +and decoding on received data. + +If +.I host +is not supplied, +.B sslconnect +connects to the local host. + +If +.I port +is not supplied, +.B sslconnect +uses TCP port 465 (SMTPS) and thus is +complementary to +.BR mconnect . + +If +.I args +are supplied, they are passed to +.B sslclient +unmodified. + +Unlike a standard SMTP(S) client, +.B sslconnect +does not perform a DNS MX lookup, +thus the FQDN or IP rof the MTA must be specified. +.SH SEE ALSO +sslserver(1), +sslhandle(1), +sslclient(1), +sslcat(1), +https@(1), +tcp-environ(5) diff --git a/man/sslhandle.1 b/man/sslhandle.1 new file mode 100644 index 0000000..8ca1b1f --- /dev/null +++ b/man/sslhandle.1 @@ -0,0 +1,578 @@ +.TH sslhandle 1 +.SH NAME +sslhandle \- preforking TLS server +.SH SYNOPSIS +.B sslhandle +[ +.I opts +] +.I host +.I port +.I prog +.SH DESCRIPTION +.I opts +is a series of getopt-style options, +.I host +is a host name or IP address, +.I port +is a TCP port, and +.I prog +is one or more arguments specifying a program +to run for each accepted connection. +The +.I server +subroutine is called within a loop, with one iteration per request +listening to +.I \-c \fIn +incoming connections simultanously. +It must release any resources allocated to handle a particular request before returning to its caller. + +The server's address is given by +.I host +and +.IR port . + +.SH BINDINGS +.B sslhandle +will be attached to the primary IP address of +.I host +while the host name is fed through qualification using +.IR dns_ip6_qualify . +If +.I host +is given as dotted decimal IPv4 or compactified IPv6 +address, +.B sslhandle +will bind uniquely to those. In order to bind +.B sslhandle +to a LLU IPv6 address (ie. fe80::a:b:c) additionally the interface name +.B \-I\fIifname +has to be provided. + +\fINote\fR: The kernel might use temporary changing SLAAC addresses. + +.B sslhandle +can be instructed to be multi-homing capable while binding +to all available IP addresses. Now +.I host +is given as +.I 0.0.0.0 +or +.IR :: . + +Further, +.B sslhandle +can be forced to provide dual-stack capabilities, thus allowing +IPv4 and IPv6 clients to attach to the same instance once +.I host +equals ':0' as pseudo IP address. + +.I port +may be a numeric port number +or a port name. If +.I port +is 0, +.B sslhandle +will choose a free port. + +.SH SERVING +.B sslhandle +listens for connections from TCP clients. +Typically, for each connection, it runs +.IR prog , +with file descriptor 0 reading from, +and file descriptor 1 writing to a child process +.IR ssl . +The +.I ssl +process attempts an SSL accept via the network. +If it succeeds, it translates data between +.I prog +and the network, performing any necessary SSL encoding and decoding. +Before running +.IR prog , +.B sslhandle +reads and sets certain environment variables. + +.B sslhandle +exists, if the parent process receives a SIGTERM. +.SH OPTIONS +.B General Options: +.TP +.B \-q +Quiet. Do not print error messages. +.TP +.B \-Q +(Default.) Print error messages. +.TP +.B \-v +Verbose. Print error messages and status messages. +.TP +.B \-V +Print additional verbose SSL connection informations (protocol and cipher). + +.P +.B Connection options: +.TP +.B \-1 +After preparing to receive connections, +print the local port number to standard output. +.TP +.B \-4 +Use IPv4 sockets for connections. +.TP +.B \-6 +Use IPv6 connections. This will set \fIPROTO\fR to \fBTCP6\fR and put +IPv6 addresses in \fITCP6LOCALIP\fR and \fITCP6REMOTEIP\fR. +.TP +.B \-c \fIn +Do not handle more than +.I n +simultaneous connections. +If there are +.I n +simultaneous connections copies of +.I prog +running, defer acceptance of a new connection until one copy finishes. +.I n +must be a positive integer. The default value is 40. +.TP +.B \-x \fIcdb +Follow the rules compiled into +.I cdb +by +.BR tcprules . +These rules may specify setting environment variables +or rejecting connections from bad sources. +You can rerun +.B tcprules +to change the rules while +.B sslhandle +is running. +.TP +.B \-X +With +.B \-x \fIcdb, +allow connections even if +.B \-I cdb +does not exist. Normally +.B sslhandle +will drop the connection if +.I cdb +does not exist. +.TP +.B \-B \fIbanner +Write +.I banner +to the network immediately after each SSL connection is made. The +.I banner +is subject to SSL encryption. +.TP +.B \-f \fIlockfile +Additional filename given for locking. If +.I lockfile +is provided and not exclusive readable +.B sslhandle +will not start. +Utilize this option if your accept system call suffers from the thundering herd problem. +.TP +.B \-g \fIgid +Switch group ID to +.I gid +after preparing to receive connections. +.I gid +must be a positive integer. +.TP +.B \-u \fIuid +Switch user ID to +.I uid +after preparing to receive connections. +.I uid +must be a positive integer. +.TP +.B \-U +Same as +.B \-g +$GID +.B \-u +$UID. Typically, $GID and $UID are set by +.BR envuidgid . +.TP +.B \-I \fIifname +Bind to the network interface +.I ifname +("eth0" on Linux, for example). This is only defined and needed for +IPv6 link-local addresses. +.TP +.B \-b \fIn +Allow a backlog of approximately +.I n +pending connections. +.TP +.B \-o +Leave IP options alone. If the client is sending packets +along an IP source route, send packets back along the same route. +.TP +.B \-O +(Default.) Kill IP options. +A client can still use source routing to connect and to send data, +but packets will be sent back along the default route. +.TP +.B \-d +Delay sending data for a fraction of a second whenever the +remote host is responding slowly. This is currently the default, +but it may not be in the future; if you want it, set it explicitly. +.TP +.B \-D +Never delay sending data; enable TCP_NODELAY. +.TP +.B \-t \fIn +Give up on the $SSLREMOTEINFO connection attempt after +.I n +seconds. The default value is: 26. +.TP +.B \-T \fIn +Give up on the SSL connection attempt after +.I n +seconds. The default value is: 26. +.TP +.B \-w \fIn +Give up on a connection or program after waiting +.I n +seconds for read or write. The default value is: 3600. + +.P +.B SSL and TLS connection options: +.TP +.B \-s +Store client and server certificate information in the environment, a la +.IR mod_ssl . +.TP +.B \-S +(Default.) Do not store client and server certificate information in the environment. + +.P +.B X509 certificate and encryption options: +.TP +.B \-3 +Read a null-terminated +.I key password +from file descriptor +.IR 3 . +.TP +.B \-m +(Mail.) Require valid client certificates, but don't check for matching FQDN. +.TP +.B \-z +(Host.) Require valid client certificates and match FQDN (if given) against SAN/DN. +.TP +.B \-Z +(Default.) Do not require client certificates. + +.P +.B Data-gathering options: +.TP +.B \-h +(Default.) Look up the remote host name in DNS to set the +environment variable $SSLREMOTEHOST. +In this case, additionally the CN/SAN in the X509 certificate can be +checked, provided, the option +.B \-z +is set. +.TP +.B \-H +Do not look up the remote host name in DNS; +remove the environment variable $SSLREMOTEHOST. +To avoid loops, you must use this option for servers on TCP port 53. +.TP +.B \-p +Paranoid. After looking up the remote host name in DNS, +look up the IP addresses in DNS for that host name, +and remove the environment variable $SSLREMOTEHOST +if none of the addresses match the client's IP address. +.TP +.B \-P +(Default.) Not paranoid. +.TP +.B \-l \fIlocalname +Do not look up the local host name in DNS; use +.I localname +for the environment variable $SSLLOCALHOST. +A common choice for +.I localname +is 0. To avoid loops, you must use this option for servers on TCP port 53. +.TP +.B \-r +Attempt to obtain $SSLREMOTEINFO from the remote host. +.TP +.B \-R +(Default.) Do not attempt to obtain $SSLREMOTEINFO from the remote host. +To avoid loops, you must use this option for servers on TCP ports 53 and 113. +.TP +.B \-e +Set protocol environment a la +.B tcpserver . +Set $TCPLOCALIP, $TCPLOCALPORT, $TCPLOCALHOST, $TCPREMOTEIP, +$TCPREMOTEPORT, $TCPREMOTEHOST, and $TCPREMOTEINFO as well as for IPv6 +connections additionally $TCP6REMOTEIP, $TCP6RMEOTEHOST, and $TCP6REMOTEINFO +from the current $SSL environment (see below). +.TP +.B \-E +(Default.) Do not set any +.B tcpserver +environment variables. +.SH "DNS RESOLVER SETTINGS" +Use \fI$DNSCACHEIP\fR to set the DNS resolver IP dynamically +irrespectively from the settings in +.IR /etc/resolv.conf . +If the environment variable \fI$LOCALDOMAIN\fR is populated, +this name will be appended to unqualified host names. +Additional rewriting of local to public names is facilitated +in case the file +.I /etc/dnswritefile +exists and is populated, or alternatively the environment +variable \fI$DNSREWRITEFILE\fR points to a differnent file. +.SH "SSL ENVIRONMENT VARIABLES READ" +These variables define the run-time environment of +.B sslhandle +and are used to specify X509 certificates and keyfile per connection. +.TP +.B $SSL_USER=\fIname +The user, reading the certificates and keyfile. +.TP +.B $SSL_GROUP=\fIgroup +The respective user group. +.TP +.B $SSL_UID=\fIuid +The numerical UID of the $SSL_USER. +.TP +.B $SSL_CHROOT=\fIpath +Perform reading of certificates and keyfile in a $SSL_CHROOT jail. +.TP +.B $CAFILE=\fIpath +If set, overrides the compiled-in CA file name. +The CA file contains the list of CAs used to verify the client certificate. +Certificates in $CAFILE are processed when the server starts. +.TP +.B $CADIR=\fIpath +If set, overrides the compiled-in CA directory name. +The CA directory contains certificates files used to verify the client certificate. +This list augments the list from $CAFILE. +Certificates in $CADIR are processed during certificate verification. +.TP +.B $CERTFILE=\fIpath +If set, overrides the compiled-in certificate file name. +The server presents this certificate to clients. +.TP +.B $CERTCHAINFILE=\fIpath +If set, overrides the compiled-in certificate chainfile name. +The server presents this list of certificats to clients. +.I Note: +Providing $CERTCHAINFILE has precedence over $CERTFILE. +Certificates in this file needs to be 'ordered' starting from the +uppermost root certificates and placing your host's certificate at the end. +.TP +.B $CIPHERS=\fIstring +If set, override the compiled-in SSL cipher list +defining the security level for the connection. +A typical choice would be 'TLSv1+HIGH:!SSLv2:!MD5'. +.TP +.B $DHFILE=\fIpath +If set, overrides the compiled-in DH parameter file name. +.TP +.B $KEYFILE=\fIpath +If set, overrides the compiled-in key file name. +The key is used when loading the server certificate. +Setting $KEYFILE to the empty instructs the server +not to use a +.I keyfile +when loading it's certificate. +.TP +.B $VERIFYDEPTH=\fIn +If set, overrides the compiled-in verification depth. Default: 1. +.TP +.B $CCAFILE=\fIpath +If set, overrides the compiled-in client CA file name for client certificate request. +The client CA file contains the list of CAs sent to the client +when requesting a client certificate. +.I Note: +Setting of $CCAFILE is required while using the option +.IR \-z +or +.IR \-m. +However, declaring +.B $CCAFILE="-" +disables (on a per-connection base) the client certificate request. +.TP +.B $CCAVERIFY +If set, +.B sslhandle +requests a valid client certificate on a per-connection base, unlike the general +option +.IR \-z . +.SH "SSL ENVIRONMENT VARAIBLES SET" +In case +.B sslhandle +is called with the option +.BR \-e , +the following +.I mod_ssl +environment variables are provided: +.TP +.B SSL_PROTOCOL +The TLS protocol version (SSLv3, TLSv1, ...). +.TP +.B SSL_SESSION_ID +The hex-encoded SSL session id. +.TP +.B SSL_CIPHER +The cipher specification name. +.TP +.B SSL_CIPHER_USEKEYSIZE +Number of cipher bits (actually used). +.TP +.B SSL_CIPHER_ALGKEYSIZE +Number of cipher bits (possible). +.TP +.B SSL_VERSION_INTERFACE +The mod_ssl program version. +.TP +.B SSL_VERSION_LIBRARY +The OpenSSL program version. +.TP +.B SSL_CLIENT_M_VERSION +The version of the client certificate. +.TP +.B SSL_CLIENT_M_SERIAL +The serial of the client certificate. +.TP +.B SSL_CLIENT_S_DN +Subject DN in client's certificate. +.TP +.B SSL_CLIENT_S_DN_x509 +Component of client's Subject DN. +.TP +.B SSL_CLIENT_I_DN +Issuer DN of client's certificate. +.TP +.B SSL_CLIENT_I_DN_x509 +Component of client's Issuer DN. +.TP +.B SSL_CLIENT_V_START +Validity of client's certificate (start time). +.TP +.B SSL_CLIENT_V_END +Validity of client's certificate (end time). +.TP +.B SSL_CLIENT_A_SIG +Algorithm used for the signature of client's certificate. +.TP +.B SSL_CLIENT_A_KEY +Algorithm used for the public key of client's certificate. +.TP +.B SSL_CLIENT_CERT +PEM-encoded client certificate. +.TP +.B SSL_CLIENT_CERT_CHAIN \fIn +PEM-encoded certificates in client certificate chain. +.TP +.B SSL_CLIENT_VERIFY +NONE, SUCCESS, GENEROUS or FAILED:reason. +.TP +.B SSL_SERVER_M_SERIAL +The serial of the server certificate. +.TP +.B SSL_SERVER_S_DN +Subject DN in server's certificate. +.TP +.B SSL_SERVER_S_DN_x509 +Component of server's Subject DN. +.TP +.B SSL_SERVER_I_DN +Issuer DN of server's certificate. +.TP +.B SSL_SERVER_I_DN_x509 +Component of server's Issuer DN. +.TP +.B SSL_SERVER_V_START +Validity of server's certificate (start time). +.TP +.B SSL_SERVER_V_END +Validity of server's certificate (end time). +.TP +.B SSL_SERVER_A_SIG +Algorithm used for the signature of server's certificate. +.TP +.B SSL_SERVER_A_KEY +Algorithm used for the public key of server's certificate. +.TP +.B SSL_SERVER_CERT +PEM-encoded server certificate. +.P +For $SSL_CLIENT_x_DN_x509 and $SSL_SERVER_x_DN_x509, +x509 denotes a component of the DN: +C, ST, L, O, OU, CN, T, I, G, S, D, UID, Email. + +.P +Other SSL environment variables set: +.P +.BR PROTO, +.BR SSLLOCALHOST, +.BR SSLLOCALIP, +.BR SSLLOCALPORT, +.BR SSLREMOTEHOST, +.BR SSLREMOTEINFO, +.BR SSLREMOTEIP, +.BR SSLREMOTEPORT. + +.P +TCP environment variables set: +.P +.BR TCPLOCALHOST, +.BR TCPLOCALIP, +.BR TCPLOCALPORT, +.BR TCPREMOTEHOST, +.BR TCPREMOTEINFO, +.BR TCPREMOTEIP, +.BR TCPREMOTEPORT. + +.P +TCP6 environment variables set: +.P +.BR TCP6INTERFACE, +.BR TCP6LOCALHOST, +.BR TCP6LOCALIP, +.BR TCP6LOCALPORT, +.BR TCP6REMOTEHOST, +.BR TCP6REMOTEIP, +.BR TCP6REMOTEPORT. +.SH "LOGGING AND ERROR MESSAGES" +.B sslhandle +prints information about individual connections +in case +.I -v +or +.I -V +is specified as argument. +TLS error messages are provided if possible: +.TP +.B unable to speak TLS for pid: ... DH lib +TLS handshake failure. +.TP +.B unable to accept TLS for pid: ... +The remote socket was prematurely closed. +.P +.SH "SEE ALSO" +sslserver(1), +sslclient(1), +sslconnect(1), +sslcat(1), +https@(1), +ucspi-tls(2), +tcprules(1), +tcprulescheck(1), +tcpserver(1), +tcp-environ(5) +.SH REFERENCE +http://httpd.apache.org/docs/2.4/mod/mod_ssl.html +http://www.superscript.com/ucspi-ssl/prefork.html diff --git a/man/sslserver.1 b/man/sslserver.1 new file mode 100644 index 0000000..2d31845 --- /dev/null +++ b/man/sslserver.1 @@ -0,0 +1,657 @@ +.TH sslserver 1 +.SH NAME +sslserver \- accept TLS connections and setup SSL CTX +.SH SYNOPSIS +.B sslserver +[ +.I opts +] +.I host +.I port +.I prog +.SH DESCRIPTION +.I opts +is a series of getopt-style options, +.I host +is a host name or IP address, +.I port +is a TCP port, and +.I prog +is one or more arguments specifying a program +to run for each accepted connection. + +The server's address is given by +.I host +and +.IR port . +.SH BINDINGS +.B sslserver +will be attached to the primary IP address of +.I host +while the host name is fed through qualification using +.IR dns_ip6_qualify . +If +.I host +is given as dotted decimal IPv4 or compactified IPv6 +address, +.B sslserver +will bind uniquely to those. In order to bind +.B sslserver +to a LLU IPv6 address (ie. fe80::a:b:c) additionally the interface name +.B \-I\fIifname +has to be provided. + +\fINote\fR: The kernel might use temporary changing SLAAC addresses. + +.B sslserver +can be instructed to be multi-homing capable while binding +to all available IP addresses. Now +.I host +is given as +.I 0.0.0.0 +or +.IR :: . + +Further, +.B sslserver +can be forced to provide dual-stack capabilities, thus allowing +IPv4 and IPv6 clients to attach to the same instance once +.I host +equals ':0' as pseudo IP address. + +.I port +may be a numeric port number +or a port name. If +.I port +is 0, +.B sslserver +will choose a free port. +.SH SERVING +.B sslserver +listens for connections from TCP clients. +Typically, for each connection, it runs +.IR prog , +with file descriptor 0 reading from, +and file descriptor 1 writing to a child process +.IR ssl . +If however +.B sslserver +is called with the option +.IR \-n , +it communcates with +.I prog +on mutually chosen, arbitrary file descriptors. +.I prog +needs to support the UCSPI-TLS API. +The +.I ssl +process attempts an SSL accept via the network. +If it succeeds, it translates data between +.I prog +and the network, performing any necessary SSL encoding and decoding. +Before running +.IR prog , +.B sslserver +reads and sets certain environment variables. + +.B sslserver +exits when it receives SIGTERM. +.SH OPTIONS +.B General Options: +.TP +.B \-q +Quiet. Do not print error messages. +.TP +.B \-Q +(Default.) Print error messages. +.TP +.B \-v +Verbose. Print error and status messages. +.TP +.B \-V +Print additional verbose SSL connection informations (protocol and cipher). + +.P +.B Connection options: +.TP +.B \-1 +After preparing to receive connections, +print the local port number to standard output. +.TP +.B \-4 +Use IPv4 sockets for connections. +.TP +.B \-6 +Use IPv6 connections. This will set \fIPROTO\fR to \fBTCP6\fR and put +IPv6 addresses in \fITCP6LOCALIP\fR and \fITCP6REMOTEIP\fR. +.TP +.B \-c \fIn +Do not handle more than +.I n +simultaneous connections. +If there are +.I n +simultaneous connections copies of +.I prog +running, defer acceptance of a new connection until one copy finishes. +.I n +must be a positive integer. The default value is 40. +.TP +.B \-x \fIcdb +Follow the rules compiled into +.I cdb +by +.BR tcprules . +These rules may specify setting environment variables +or rejecting connections from bad sources. +You can rerun +.B tcprules +to change the rules while +.B sslserver +is running. +.TP +.B \-X +With +.B \-x \fIcdb, +allow connections even if +.I cdb +does not exist. Normally +.B sslserver +will drop the connection if +.I cdb +does not exist. +.TP +.B \-y \fIcdb +Evaluate and follow IP rules compiled into +.I cdb +prior of doing a \fIDNS\fR or \fIIDENT\fR lookup. +A shared \fIcdb\fR is possible. +.TP +.B \-B \fIbanner +Write +.I banner +to the network immediately after each SSL connection is made. The +.I banner +is subject to SSL encryption. +.TP +.B \-g \fIgid +Switch group ID to +.I gid +after preparing to receive connections. +.I gid +must be a positive integer. +.TP +.B \-u \fIuid +Switch user ID to +.I uid +after preparing to receive connections. +.I uid +must be a positive integer. +.TP +.B \-U +Same as +.B \-g +$GID +.B \-u +$UID. Typically, $GID and $UID are set by +.BR envuidgid . +.TP +.B \-I \fIifname +Bind to the network interface +.I ifname +("eth0" on Linux, for example). This is only defined and needed for +IPv6 link-local addresses. +.TP +.B \-b \fIn +Allow a backlog of approximately +.I n +pending connections. +.TP +.B \-o +Leave IP options alone. If the client is sending packets +along an IP source route, send packets back along the same route. +.TP +.B \-O +(Default.) Kill IP options. +A client can still use source routing to connect and to send data, +but packets will be sent back along the default route. +.TP +.B \-d +Delay sending data for a fraction of a second whenever the +remote host is responding slowly. This is currently the default, +but it may not be in the future; if you want it, set it explicitly. +.TP +.B \-D +Never delay sending data; enable TCP_NODELAY. +.TP +.B \-t \fIn +Give up on the $SSLREMOTEINFO connection attempt after +.I n +seconds. The default value is: 26. +.TP +.B \-T \fIn +Give up on the SSL connection attempt after +.I n +seconds. The default value is: 26. +.TP +.B \-w \fIn +Give up on a connection or program after waiting +.I n +seconds for read or write. The default value is: 3600. + +.P +.B SSL and TLS connection options: +.TP +.B \-n +Delay setup of SSL environment until a STARTTLS/STLS command +has been issued by the client. +.TP +.B \-N +(Default.) Setup the SSL environment immediately. +.TP +.B \-s +Store client and server certificate information in the environment, a la +.IR mod_ssl . +.TP +.B \-S +(Default.) Do not store client and server certificate information in the environment. + +.P +.B X509 certificate and encryption options: +.TP +.B \-3 +Read a null-terminated +.I key password +from file descriptor +.IR 3 . +.TP +.B \-m +(Mail.) Require valid client certificates, but don't check for matching FQDN. +.TP +.B \-z +(Host.) Require valid client certificates and match FQDN (if given) against SAN/DN. +.TP +.B \-Z +(Default.) Do not require client certificates. + +.P +.B Data-gathering options: +.TP +.B \-h +(Default.) Look up the remote host name in DNS to set the +environment variable $SSLREMOTEHOST. +In this case, additionally the CN/SAN in the X509 certificate can be +checked, provided, the option +.B \-z +is set. +.TP +.B \-H +Do not look up the remote host name in DNS; +remove the environment variable $SSLREMOTEHOST. +To avoid loops, you must use this option for servers on TCP port 53. +.TP +.B \-p +Paranoid. After looking up the remote host name in DNS, +look up the IP addresses in DNS for that host name, +and remove the environment variable $SSLREMOTEHOST +if none of the addresses match the client's IP address. +.TP +.B \-P +(Default.) Not paranoid. +.TP +.B \-l \fIlocalname +Do not look up the local host name in DNS; use +.I localname +for the environment variable $SSLLOCALHOST. +A common choice for +.I localname +is 0. To avoid loops, you must use this option for servers on TCP port 53. +.TP +.B \-r +Attempt to obtain $SSLREMOTEINFO from the remote host. +.TP +.B \-R +(Default.) Do not attempt to obtain $SSLREMOTEINFO from the remote host. +To avoid loops, you must use this option for servers on TCP ports 53 and 113. +.TP +.B \-e +Set protocol environment a la +.B tcpserver . +Set $TCPLOCALIP, $TCPLOCALPORT, $TCPLOCALHOST, $TCPREMOTEIP, +$TCPREMOTEPORT, $TCPREMOTEHOST, and $TCPREMOTEINFO as well as for IPv6 +connections additionally $TCP6LOCALIP, $TCP6LOCALPORT, $TCP6LOCALHOST +together with $TCP6REMOTEIP, $TCP6REMOTEPORT, $TCP6RMEOTEHOST and +$TCP6INTERFACE from the current $SSL environment (see below). +.TP +.B \-E +(Default.) Do not set any +.B tcpserver +environment variables. +.SH "DNS RESOLVER SETTINGS" +Use \fI$DNSCACHEIP\fR to set the DNS resolver IP dynamically +irrespectively from the settings in +.IR /etc/resolv.conf . +If the environment variable \fI$LOCALDOMAIN\fR is populated, +this name will be appended to unqualified host names. +Additional rewriting of local to public names is facilitated +in case the file +.I /etc/dnswritefile +exists and is populated, or alternatively the environment +variable \fI$DNSREWRITEFILE\fR points to a differnent file. +.SH "ENVIRONMENT VARIABLES READ" +.B sslserver +acknowledges the environment variable +.I MAXCONIP="n" +where +.I n +is the number of +.B sslserver +children spawned for a particular remote IP address. +.I n +is restricted to the general connection limit +.I c +provided as call argument. +.I MAXCONIP +is typically defined in +.BR sslserver 's +cdb for a given condition and thus only active meeting those. +.I MAXCONIP +defaults +.I 0 +meaning no restriction. +.SH "SSL ENVIRONMENT VARIABLES READ" +These variables define the run-time environment of +.B sslserver +and are used to specify X509 certificates and keyfile per connection. +.TP +.B $SSL_USER=\fIname +The user, reading the certificates and keyfile. +.TP +.B $SSL_GROUP=\fIgroup +The respective user group. +.TP +.B $SSL_UID=\fIuid +The numerical UID of the $SSL_USER. +.TP +.B $SSL_CHROOT=\fIpath +Perform reading of certificates and keyfile in a $SSL_CHROOT jail. +.TP +.B $CAFILE=\fIpath +If set, overrides the compiled-in CA file name. +The CA file contains the list of CAs used to verify the client certificate. +Certificates in $CAFILE are processed when the server starts. +.TP +.B $CADIR=\fIpath +If set, overrides the compiled-in CA directory name. +The CA directory contains certificates files used to verify the client certificate. +This list augments the list from $CAFILE. +Certificates in $CADIR are processed during certificate verification. +.TP +.B $CERTFILE=\fIpath +If set, overrides the compiled-in certificate file name. +The server presents this certificate to clients. +.TP +.B $CERTCHAINFILE=\fIpath +If set, overrides the compiled-in certificate chainfile name. +The server presents this list of certificats to clients. +.I Note: +Providing $CERTCHAINFILE has precedence over $CERTFILE. +Certificates in this file needs to be 'ordered' starting from the +uppermost root certificates and placing your host's certificate at the end. +.TP +.B $CIPHERS=\fIstring +If set, override the compiled-in SSL cipher list +defining the security level for the connection. +A typical choice would be 'TLSv1+HIGH:!SSLv2:!MD5'. +.TP +.B $DHFILE=\fIpath +If set, overrides the compiled-in DH parameter file name. +.TP +.B $KEYFILE=\fIpath +If set, overrides the compiled-in key file name. +The key is used when loading the server certificate. +Setting $KEYFILE to the empty instructs the server +not to use a +.I keyfile +when loading it's certificate. +.TP +.B $VERIFYDEPTH=\fIn +If set, overrides the compiled-in verification depth. Default: 1. +.TP +.B $CCAFILE=\fIpath +If set, overrides the compiled-in client CA file name for client certificate request. +The client CA file contains the list of CAs sent to the client +when requesting a client certificate. +.I Note: +Setting of $CCAFILE is required while using the option +.IR \-z +or +.IR \-m. +However, declaring +.B $CCAFILE="-" +disables (on a per-connection base) the client certificate request. +.TP +.B $CCAVERIFY +If set, +.B sslserver +requests a valid client certificate on a per-connection base, unlike the general +option +.IR \-z . +.SH "SSL ENVIRONMENT VARAIBLES SET" +In case +.B sslserver +is called with the option +.BR \-e , +the following +.I mod_ssl +environment variables are provided: +.TP +.B SSL_PROTOCOL +The TLS protocol version (SSLv3, TLSv1, ...). +.TP +.B SSL_SESSION_ID +The hex-encoded SSL session id. +.TP +.B SSL_CIPHER +The cipher specification name. +.TP +.B SSL_CIPHER_USEKEYSIZE +Number of cipher bits (actually used). +.TP +.B SSL_CIPHER_ALGKEYSIZE +Number of cipher bits (possible). +.TP +.B SSL_VERSION_INTERFACE +The mod_ssl program version. +.TP +.B SSL_VERSION_LIBRARY +The OpenSSL program version. +.TP +.B SSL_CLIENT_M_VERSION +The version of the client certificate. +.TP +.B SSL_CLIENT_M_SERIAL +The serial of the client certificate. +.TP +.B SSL_CLIENT_S_DN +Subject DN in client's certificate. +.TP +.B SSL_CLIENT_S_DN_x509 +Component of client's Subject DN. +.TP +.B SSL_CLIENT_I_DN +Issuer DN of client's certificate. +.TP +.B SSL_CLIENT_I_DN_x509 +Component of client's Issuer DN. +.TP +.B SSL_CLIENT_V_START +Validity of client's certificate (start time). +.TP +.B SSL_CLIENT_V_END +Validity of client's certificate (end time). +.TP +.B SSL_CLIENT_A_SIG +Algorithm used for the signature of client's certificate. +.TP +.B SSL_CLIENT_A_KEY +Algorithm used for the public key of client's certificate. +.TP +.B SSL_CLIENT_CERT +PEM-encoded client certificate. +.TP +.B SSL_CLIENT_CERT_CHAIN \fIn +PEM-encoded certificates in client certificate chain. +.TP +.B SSL_CLIENT_VERIFY +NONE, SUCCESS, GENEROUS or FAILED:reason. +.TP +.B SSL_SERVER_M_SERIAL +The serial of the server certificate. +.TP +.B SSL_SERVER_S_DN +Subject DN in server's certificate. +.TP +.B SSL_SERVER_S_DN_x509 +Component of server's Subject DN. +.TP +.B SSL_SERVER_I_DN +Issuer DN of server's certificate. +.TP +.B SSL_SERVER_I_DN_x509 +Component of server's Issuer DN. +.TP +.B SSL_SERVER_V_START +Validity of server's certificate (start time). +.TP +.B SSL_SERVER_V_END +Validity of server's certificate (end time). +.TP +.B SSL_SERVER_A_SIG +Algorithm used for the signature of server's certificate. +.TP +.B SSL_SERVER_A_KEY +Algorithm used for the public key of server's certificate. +.TP +.B SSL_SERVER_CERT +PEM-encoded server certificate. +.P +For \fBSSL_CLIENT_x_DN_x509\fR and \fBSSL_SERVER_x_DN_x509\fR, +x509 denotes a component of the DN: +C, ST, L, O, OU, CN, T, I, G, S, D, UID, Email. + +.P +Other SSL environment variables set: +.P +.BR PROTO, +.BR SSLLOCALHOST, +.BR SSLLOCALIP, +.BR SSLLOCALPORT, +.BR SSLREMOTEHOST, +.BR SSLREMOTEINFO, +.BR SSLREMOTEIP, +.BR SSLREMOTEPORT. + +.P +TCP environment variables set: +.P +.BR TCPLOCALHOST, +.BR TCPLOCALIP, +.BR TCPLOCALPORT, +.BR TCPREMOTEHOST, +.BR TCPREMOTEINFO, +.BR TCPREMOTEIP, +.BR TCPREMOTEPORT. + +.P +TCP6 environment variables set: +.P +.BR TCP6INTERFACE, +.BR TCP6LOCALHOST, +.BR TCP6LOCALIP, +.BR TCP6LOCALPORT, +.BR TCP6REMOTEHOST, +.BR TCP6REMOTEIP, +.BR TCP6REMOTEPORT. +.SH "LOGGING AND ERROR MESSAGES" +.B sslserver +prints particular state information for individual connections in case +.I -v +is specified. Here, the +local and remote IP addresses and port together +with the number of used/available/ip connection limited children: + +.EX + sslserver: status 1/40/0 + sslserver: pid xxxx from <ip> + sslserver: [ok|deny] xxxx <local>:<localip>:<localport> <remotehost>:<remoteip>:<remoteport> + sslserver: ended by xyz status nnnn +.EE + +If +.I MAXCONIP +is given as global environment variable, one may encounter: + +.EX + sslserver: status z/40/<maxconip> + sslserver: WARNING ip connection limit of <maxconip> exceeded for: <remoteip> +.EE + +Rather, if +.I MAXCONIP +is read from the cdb, the following message might appear: + +.EX + sslserver: status 1/40/0 + sslserver: pid xxxx from <ip> + sslserver: deny xxxx ... ip connection limit:<maxconip> exceeded + sslserver: ended by xyz status nnnn +.EE + +In all cases, the resolved host names depends on the usage of +.IR l , +.I -h +and +.IR -p . +If +.I -V +is instead given as argument, lines like + +.EX + sslserver: tls xxxx accept TLSv1.2:ECDH-RSA-AES256-GCM-SHA384 + sslserver: tls xxxx accept TLSv1.3:TLS_CHACHA20_POLY1305_SHA256 +.EE + +show additionally the negotiated cipher suite. +.P +.B Error and particular messages +.P +TLS error messages are provided, if possible: +.TP +.I sslerver: error: (111) unable to speak TLS from: ... for pid: ... DH lib +.P +TLS handshake failure. +.TP +.I sslserver: error: (111) unable to accept TLS from: ... for pid: ... system lib +.P +The remote socket was prematurely closed; usually because +the X.509 cert was not accepted by the client. +.TP +.I sslserver: info: valid client cert received for pid: <pid> +.P +A client X.509 cert has been accepted for +mutual authentication. +.P +.SH "SEE ALSO" +sslhandle(1), +sslclient(1), +sslconnect(1), +sslcat(1), +https@(1), +ucspi-tls(2), +tcprules(1), +tcprulescheck(1), +tcpserver(1), +tcp-environ(5) +.SH REFERENCE +http://httpd.apache.org/docs/2.4/mod/mod_ssl.html diff --git a/man/ucspi-tls.2 b/man/ucspi-tls.2 new file mode 100644 index 0000000..a3d8639 --- /dev/null +++ b/man/ucspi-tls.2 @@ -0,0 +1,61 @@ +.TH ucspi-tls 2 +.SH NAME +UCSPI-TLS \- advanced and secure communication between server and prog +.SH DESCRIPTON +A +.B UCSPI-TLS +enhanced server makes optional SSL services available to the +client by providing three file descriptors: a +.I control socket, +a +.I reading pipe, +and a +.I writing pipe. + +The file descriptor number of the control socket will be in the +environment variable $SSLCTLFD. + +The file descriptor number of the reading pipe will be in the +environment variable $SSLREADFD, and the file descriptor number of the +writing pipe will be in the environment variable $SSLWRITEFD. + +It's possible for all three of these file descriptors to be the same. + +.SH USAGE +.B UCSPI-TLS +provides standard IN and OUT (file descriptors 0 and 1) +to connected directly to the socket, for unencrypted communication. + +The +.I control socket +must accept at least these two commands: +.TP +.B y +Start TLS. +.TP +.B Y +Start TLS, and send optional SSL connection information +back over the control socket. +.P +The SSL connection information will be in the in the form of an +environment string, with zero or more environment variables, +terminated by two ASCII NULL's. Each environment variable is stored +as "VAR=val\0", and an additional trailing \0 is used to indicate +the end of all environment variables. If there are no variables to +set, "\0\0" should be used. + +When TLS is started, the +.B UCSPI-TLS +enabled server will take control of the socket, +and the application is expected to switch to the file descriptors in +$SSLREADFD and $SSLWRITEFD for all future communications. +Using the regular socket after activating TLS will +probably just confuse the client. +.SH REFERENCE +Where possible, the environment variables set should be the same +ones as Apache's +.I mod_ssl: + +http://httpd.apache.org/docs-2.4/mod/mod_ssl.html +.SH CREDITS +Scott Gifford, Charlie Brady diff --git a/package/build b/package/build new file mode 100644 index 0000000..bac2ceb --- /dev/null +++ b/package/build @@ -0,0 +1 @@ +20231204180637 diff --git a/package/command-cp b/package/command-cp new file mode 100644 index 0000000..1083552 --- /dev/null +++ b/package/command-cp @@ -0,0 +1,3 @@ + +Directories to copy commands into, one per line. +The first empty line terminates the list. diff --git a/package/command-ln b/package/command-ln new file mode 100644 index 0000000..3a56315 --- /dev/null +++ b/package/command-ln @@ -0,0 +1,4 @@ +/usr/local/bin + +Directories to soft link commands into, one per line. +The first empty line terminates the list. diff --git a/package/commands-base b/package/commands-base new file mode 100644 index 0000000..a1d0820 --- /dev/null +++ b/package/commands-base @@ -0,0 +1,7 @@ +sslclient +sslserver +https@ +sslcat +sslconnect +sslprint +sslhandle diff --git a/package/commands-sslperl b/package/commands-sslperl new file mode 100644 index 0000000..68065ca --- /dev/null +++ b/package/commands-sslperl @@ -0,0 +1 @@ +sslperl diff --git a/package/commands-sys b/package/commands-sys new file mode 100644 index 0000000..fa5d3e9 --- /dev/null +++ b/package/commands-sys @@ -0,0 +1 @@ +sysdeps diff --git a/package/compile b/package/compile new file mode 100755 index 0000000..9deb12c --- /dev/null +++ b/package/compile @@ -0,0 +1,88 @@ +#!/bin/sh +shout() { echo "compile: $@" >&2; } +barf() { shout "fatal: $@"; exit 111; } +safe() { "$@" || barf "cannot $@"; } +umask 022 +[ -d package ] || barf "no package directory" +[ -d src ] || barf "no src directory" + +here=`env - PATH=$PATH pwd` + +safe mkdir -p compile command +[ -h compile/src ] || safe ln -s $here/src compile/src + +for i in `ls src` +do + [ -h compile/$i ] || safe ln -s src/$i compile/$i +done + +for i in `sed -e '/^it-/!d' -e 's/^it-//' < compile/it=d` +do + all="$all $i" +done +other="`grep -v '^it-' compile/it=d`" +usage() { shout "usage: package/rts [ [-]$all ]"; exit 100; } +targets="" +if [ $# -eq 0 ] +then + targets="$all" +else + if [ "$1" = "-" ] + then + shift + suppress=":" + for i in ${1+"$@"} + do + case "$all " in + *\ $i\ *) + ;; + *) + usage + ;; + esac + suppress="$suppress$i:" + done + for i in $all + do + case "$suppress" in + *:$i:*) + ;; + *) + targets="$targets $i" + ;; + esac + done + else + for i in ${1+"$@"} + do + case "$all " in + *\ $i\ *) + ;; + *) + usage + ;; + esac + targets="$targets $i" + done + fi +fi + +[ "X$all" != "X" ] && [ "X$targets" = "X" ] && usage + +commands= +for i in $targets +do + commands="$commands `cat package/commands-$i`" +done + +safe cd compile +safe make $other `echo "$targets" | sed -e 's/ / it-/g'` +safe cd $here + +for i in $commands +do + safe rm -f command/$i'{new}' + safe cp -p compile/$i command/$i'{new}' + safe mv -f command/$i'{new}' command/$i +done + diff --git a/package/files b/package/files new file mode 100644 index 0000000..e867db0 --- /dev/null +++ b/package/files @@ -0,0 +1,164 @@ +conf-cadir +conf-cafile +conf-cc +conf-ccafile +conf-ccperl +conf-certchainfile +conf-certfile +conf-ciphers +conf-dhfile +conf-home +conf-keyfile +conf-ld +conf-ldperl +conf-man +conf-perl +conf-qlibs +conf-rsa +conf-ssl +conf-ssllib +INSTALL +README.md +doc +doc/CHAIN-SSL +doc/CHANGES +doc/LICENSE +doc/README.rts +doc/UCSPI-SSL +doc/TLS_1_3 +doc/TLSVERSION_CIPHERSUITES +doc/TODO +etc +etc/README.certs.md +etc/127.0.0.1_cert.pem +etc/127.0.0.1_key.pem +etc/127.0.0.1_key.pem.plain +etc/127.0.0.1.pw +etc/::1_cert.pem +etc/::1_key.pem +etc/::1_key.pem.plain +etc/::1.pw +etc/chain4.pem +etc/chain6.pem +etc/dh2048.pem +etc/localhost_cert.pem +etc/localhost_key.pem +etc/localhost_key.pem.plain +etc/localhost.pw +etc/rootCA_cert.pem +man +man/Makefile +man/Makefile.mandoc +man/TARGETS +man/https@.1 +man/sslcat.1 +man/sslclient.1 +man/sslconnect.1 +man/sslhandle.1 +man/sslserver.1 +man/ucspi-tls.2 +package +package/command-cp +package/command-ln +package/commands-base +package/commands-sys +package/commands-sslperl +package/build +package/compile +package/files +package/install +package/man +package/path +package/report +package/rts +package/run +package/upgrade +package/version +src +src/Makefile +src/TARGETS +src/auto-str.c +src/auto_cadir.h +src/auto_cafile.h +src/auto_ccafile.h +src/auto_certchainfile.h +src/auto_certfile.h +src/auto_ciphers.h +src/auto_dhfile.h +src/auto_keyfile.h +src/chkshsgr.c +src/choose.sh +src/coe.c +src/coe.h +src/exp.base +src/exp.it +src/exp.sslperl +src/exit.h +src/find-systype.sh +src/fork.h1 +src/fork.h2 +src/hassgact.h1 +src/hassgact.h2 +src/hassgprm.h1 +src/hassgprm.h2 +src/hasshsgr.h1 +src/hasshsgr.h2 +src/haswaitp.h1 +src/haswaitp.h2 +src/https@.sh +src/ip_bit.h +src/ip4_bit.c +src/ip6_bit.c +src/it-base=d +src/it-sslperl=d +src/it-sys=d +src/it=d +src/print-ar.sh +src/print-cc.sh +src/print-ccperl.sh +src/print-dl.sh +src/print-ld.sh +src/print-ldperl.sh +src/print-perlembed.sh +src/remoteinfo.c +src/remoteinfo.h +src/rts.base +src/rts.it +src/rts.sslperl +src/rules.c +src/rules.h +src/select.h1 +src/select.h2 +src/ssl_ca.c +src/ssl_cca.c +src/ssl_certkey.c +src/ssl_chainfile.c +src/ssl_ciphers.c +src/ssl_context.c +src/ssl_env.c +src/ssl_error.c +src/ssl_io.c +src/ssl_new.c +src/ssl_params.c +src/ssl_timeout.c +src/ssl_verify.c +src/sslcat.sh +src/sslclient.c +src/sslconnect.sh +src/sslhandle.c +src/sslperl.c +src/sslprint.c +src/sslserver.c +src/trycpp.c +src/trylsock.c +src/trysgact.c +src/trysgprm.c +src/tryshsgr.c +src/tryssl.c +src/trysysel.c +src/tryvfork.c +src/ucspissl.c +src/ucspissl.h +src/warn-auto.sh +src/warn-shsgr +src/x86cpuid.c diff --git a/package/install b/package/install new file mode 100755 index 0000000..58a2f08 --- /dev/null +++ b/package/install @@ -0,0 +1,5 @@ +#!/bin/sh -e +package/compile ${1+"$@"} +package/upgrade ${1+"$@"} +package/man ${1+"$@"} +package/run ${1+"$@"} diff --git a/package/man b/package/man new file mode 100755 index 0000000..6213c77 --- /dev/null +++ b/package/man @@ -0,0 +1,125 @@ +#!/bin/sh +shout() { echo "$0: $@" >&2; } +barf() { shout "fatal: $@"; exit 111; } +safe() { "$@" || barf "cannot $@"; } + +here=`env - PATH=$PATH pwd` +me=`echo $here | awk -F/ '{print $NF}'` +unix=`uname -a | cut -d' ' -f1 | tr [a-z] [A-Z]` +mandir="" +usemanpath=0 +usemandoc=0 + +if [ `which manpath` 2>/dev/null ] +then + usemanpath=1 +fi + +if [ `which mandoc` 2>/dev/null ] +then + usemandoc=1 + shout "Using mandoc facility for man files." +fi + +safe umask 022 +[ -d man ] || barf "no man directory" + +if [ -f conf-man ] +then + mandir=`head -1 conf-man` + if [ -d "$mandir" ] + then + shout "Setting manual man-dir: $mandir." + else + if [ $usemanpath -eq 0 ] + then + barf "`manpath` not available; use conf-man instead." + fi + mandir=`manpath | awk -F: '{print $1}'` + if [ -d "$mandir" ] + then + shout "Setting manpath man-dir: $mandir." + else + barf "can't determine man-path directory." + fi + fi +else + barf "can't determine man-path directory." + exit 1 +fi + +cd man +if [ $usemandoc -eq 1 ] +then + safe make -f Makefile.mandoc +else + safe make +fi + +if [ $usemandoc -eq 0 ] +then + shout "Installing ${me} compressed man-files in ${mandir}." +else + shout "Installing ${me} un-compressed man-files in ${mandir}." +fi + +for i in `ls *[1-8]` +do + all="$all $i" +done + +for manfile in $all +do + dir="man`echo $manfile | awk -F. '{print $NF}'`" + [ -d $mandir/$dir ] || safe mkdir $mandir/$dir + if [ $usemandoc -eq 0 ] + then + safe gzip $manfile && \ + cp "$manfile.gz" "$mandir/$dir/$manfile.gz" + else + safe cp "$manfile" "$mandir/$dir/$manfile" + fi +done + +## nroff: Required for old catman systems only + +if [ $usemandoc -eq 0 ] +then + shout "Installing ${me} nroff'ed man-files in ${mandir}/catX." + + all="" + for i in `ls *0` + do + all="$all $i" + done + + for manfile in $all + do + catname=`echo $manfile | awk -F. '{print $1}'` + catfiles=`ls -1 ${catname}* | grep -v '.0' | grep -v '.9'` + + for catfile in $catfiles + do + dir="$mandir/cat`echo $catfile | awk -F. '{print $(NF-1)}'`" + safe mkdir -p $dir + safe cp "$manfile" "$dir/$manfile" + done + done +else + if [ `which makewhatis` 2>/dev/null ] + then + makewhatis $mandir + shout "Installing ${me} mandoc files in db (makewhatis)." + elif [ `which catman` 2>/dev/null ] + then + catman $mandir + shout "Installing ${me} mandoc files in db (catman)." + else + man -w $mandir + shout "Installing ${me} mandoc files in db (man -w)." + fi +fi + +cd .. + +exit 0 diff --git a/package/path b/package/path new file mode 100644 index 0000000..feda59c --- /dev/null +++ b/package/path @@ -0,0 +1 @@ +host/superscript.com/net diff --git a/package/report b/package/report new file mode 100755 index 0000000..1d3ec0a --- /dev/null +++ b/package/report @@ -0,0 +1,10 @@ +#!/bin/sh -e +test -d compile || ( echo 'Wrong working directory.'; exit 1 ) +here=`env - PATH=$PATH pwd` +( echo ucspi-ssl-`head -1 package/version` + echo $here + if test -r compile/sysdeps + then + cat compile/sysdeps + fi +) | mail feh@fehcom.de diff --git a/package/rts b/package/rts new file mode 100755 index 0000000..b585d1a --- /dev/null +++ b/package/rts @@ -0,0 +1,76 @@ +#!/bin/sh +shout() { echo "rts: $@" >&2; } +barf() { shout "fatal: $@"; exit 111; } +safe() { "$@" || barf "cannot $@"; } + +umask 022 +[ -d package ] || barf "no package directory" +[ -d src ] || barf "no src directory" +[ -d compile ] || barf "no compile directory" +[ -d etc ] || barf "no etc directory" + +for i in `sed -e '/^it-/!d' -e 's/^it-//' < compile/it=d` +do + all="$all $i" +done +usage() { shout "usage: package/rts [ [-]$all ]"; exit 100; } + +targets="" +if [ $# -eq 0 ] +then + targets="$all" +else + if [ "$1" = "-" ] + then + shift + suppress=":" + for i in ${1+"$@"} + do + case "$all " in + *\ $i\ *) + ;; + *) + usage + ;; + esac + suppress="$suppress$i:" + done + for i in $all + do + case "$suppress" in + *:$i:*) + ;; + *) + targets="$targets $i" + ;; + esac + done + else + for i in ${1+"$@"} + do + case "$all " in + *\ $i\ *) + ;; + *) + usage + ;; + esac + targets="$targets $i" + done + fi +fi + +[ "X$all" != "X" ] && [ "X$targets" = "X" ] && usage + +export here=`env - PATH=$PATH pwd` +safe cd compile +PATH="$here/compile:/command:$PATH" +export PATH +. $here/compile/rts.it > $here/compile/out.it 2>&1 +cat -v $here/compile/out.it | diff - $here/compile/exp.it +for i in $targets +do + export here + . $here/compile/rts.$i 2>&1 | cat -v > $here/compile/out.$i + diff $here/compile/out.$i $here/compile/exp.$i +done diff --git a/package/run b/package/run new file mode 100755 index 0000000..f11f4e1 --- /dev/null +++ b/package/run @@ -0,0 +1,2 @@ +#!/bin/sh -e +exit 0 diff --git a/package/upgrade b/package/upgrade new file mode 100755 index 0000000..cc3ead0 --- /dev/null +++ b/package/upgrade @@ -0,0 +1,109 @@ +#!/bin/sh +shout() { echo "upgrade: $@" >&2; } +barf() { shout "fatal: $@"; exit 111; } +safe() { "$@" || barf "cannot $@"; } + +umask 022 +[ -d package ] || barf "no package directory" +[ -d src ] || barf "no src directory" + +for i in `sed -e '/^it-/!d' -e 's/^it-//' < compile/it=d` +do + all="$all $i" +done +usage() { shout "usage: package/upgrade [ [-]$all ]"; exit 100; } +targets="" +if [ $# -eq 0 ] +then + for i in $all + do + targets="$all" + done +else + if [ "$1" = "-" ] + then + shift + suppress=":" + for i in ${1+"$@"} + do + case "$all " in + *\ $i\ *) + ;; + *) + usage + ;; + esac + suppress="$suppress$i:" + done + for i in $all + do + case "$suppress" in + *:$i:*) + ;; + *) + targets="$targets $i" + ;; + esac + done + else + for i in ${1+"$@"} + do + case "$all " in + *\ $i\ *) + ;; + *) + usage + ;; + esac + targets="$targets $i" + done + fi +fi + +[ "X$targets" = "X" ] && barf "no targets" + +version="`head -1 package/version`" +here="`pwd`" +command="`echo $here | sed -e 's/-'$version'$//'`/command" +package="`basename $here | sed -e 's/-'$version'$//'`" +echo "symlink $package -> $package-$version" +safe rm -f $package +safe ln -s $package-$version $package +safe mv -f $package .. + +commands= +for i in $targets +do + commands="$commands `cat package/commands-$i`" +done + +if [ -r package/command-cp ] +then + for i in `sed -e '/^$/q' < package/command-cp` + do + echo "copying commands into $i" + safe mkdir -p $i + for j in $commands + do + safe rm -f $i/$j'{new}' + safe cp -p command/$j $i/$j'{new}' + safe mv -f $i/$j'{new}' $i/$j + done + done +fi + +if [ -r package/command-ln ] +then + for i in `sed -e '/^$/q' < package/command-ln` + do + echo "linking commands into $i" + safe mkdir -p $i + for j in $commands + do + safe rm -f $i/$j'{new}' + safe ln -s $command/$j $i/$j'{new}' + safe mv -f $i/$j'{new}' $i/$j + done + done +fi + diff --git a/package/version b/package/version new file mode 100644 index 0000000..54dbed4 --- /dev/null +++ b/package/version @@ -0,0 +1 @@ +0.12.10 diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..f1f124b --- /dev/null +++ b/src/Makefile @@ -0,0 +1,351 @@ +# Don't edit Makefile! Use conf-* for configuration. + +SHELL=/bin/sh + +default: it + +auto-str: \ +load auto-str.o + ./load auto-str + +auto-str.o: \ +compile auto-str.c + ./compile auto-str.c + +auto_cadir.c: \ +auto-str ../conf-cadir + ./auto-str auto_cadir "`head -1 ../conf-cadir`" > auto_cadir.c + +auto_cadir.o: \ +compile auto_cadir.c + ./compile auto_cadir.c + +auto_cafile.c: \ +auto-str ../conf-cafile + ./auto-str auto_cafile "`head -1 ../conf-cafile`" > auto_cafile.c + +auto_cafile.o: \ +compile auto_cafile.c + ./compile auto_cafile.c + +auto_ccafile.c: \ +auto-str ../conf-ccafile + ./auto-str auto_ccafile "`head -1 ../conf-ccafile`" > auto_ccafile.c + +auto_ccafile.o: \ +compile auto_ccafile.c + ./compile auto_ccafile.c + +auto_certchainfile.c: \ +auto-str ../conf-certchainfile + ./auto-str auto_certchainfile "`head -1 ../conf-certchainfile`" > auto_certchainfile.c + +auto_certchainfile.o: \ +compile auto_certchainfile.c + ./compile auto_certchainfile.c + +auto_certfile.c: \ +auto-str ../conf-certfile + ./auto-str auto_certfile "`head -1 ../conf-certfile`" > auto_certfile.c + +auto_certfile.o: \ +compile auto_certfile.c + ./compile auto_certfile.c + +auto_ciphers.c: \ +auto-str ../conf-ciphers + ./auto-str auto_ciphers "`head -1 ../conf-ciphers`" > auto_ciphers.c + +auto_ciphers.o: \ +compile auto_ciphers.c + ./compile auto_ciphers.c + +auto_dhfile.c: \ +auto-str ../conf-dhfile + ./auto-str auto_dhfile "`head -1 ../conf-dhfile`" > auto_dhfile.c + +auto_dhfile.o: \ +compile auto_dhfile.c + ./compile auto_dhfile.c + +auto_keyfile.c: \ +auto-str ../conf-keyfile + ./auto-str auto_keyfile "`head -1 ../conf-keyfile`" > auto_keyfile.c + +auto_keyfile.o: \ +compile auto_keyfile.c + ./compile auto_keyfile.c + +ccperl: \ +../conf-ccperl ../conf-perl print-ccperl.sh + rm -f ccperl + sh print-ccperl.sh > ccperl + +chkshsgr: \ +load chkshsgr.o + ./load chkshsgr + +chkshsgr.o: \ +compile chkshsgr.c + ./compile chkshsgr.c + +choose: \ +warn-auto.sh choose.sh + rm -f choose + cat warn-auto.sh choose.sh \ + | sed s}HOME}"`head -1 ../conf-home`"}g \ + > choose + chmod 755 choose + +coe.o: \ +compile coe.c coe.h + ./compile coe.c + +compile: \ +../conf-cc ../conf-ssl print-cc.sh systype warn-auto.sh + rm -f compile + sh print-cc.sh > compile + chmod 755 compile + +hassgact.h: \ +choose compile trysgact.c hassgact.h1 hassgact.h2 + ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h + +hassgprm.h: \ +choose compile trysgprm.c hassgprm.h1 hassgprm.h2 + ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h + +hasshsgr.h: \ +choose compile tryshsgr.c hasshsgr.h1 hasshsgr.h2 chkshsgr warn-shsgr + ./chkshsgr || ( cat warn-shsgr; exit 1 ) + ./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h + +https@: warn-auto.sh https@.sh + rm -f https@ + cat warn-auto.sh https@.sh \ + | sed s}HOME}"`head -1 ../conf-home`"}g \ + > https@ + chmod 755 https@ + +it: it-sys it-base it-sslperl + +it-base: sslclient sslserver https@ sslcat sslconnect sslprint sslhandle + +it-sslperl: sslperl + +it-sys: sysdeps auto-str + +load: \ +../conf-ld print-ld.sh systype warn-auto.sh + rm -f load + sh print-ld.sh > load + chmod 755 load + +makelib: \ +print-ar.sh systype warn-auto.sh + rm -f makelib + sh print-ar.sh > makelib + chmod 755 makelib + +perlembed.lib: \ +../conf-perl ../conf-ldperl print-perlembed.sh + rm -f perlembed.lib + sh print-ldperl.sh > perlembed.lib + +remoteinfo.o: \ +compile remoteinfo.c remoteinfo.h + ./compile remoteinfo.c + +rules.o: \ +compile rules.c rules.h ip4_bit.c ip6_bit.c ip_bit.h + ./compile rules.c ip4_bit.c ip6_bit.c ip_bit.h + +socket.lib: \ +trylsock.c compile load + ( ( ./compile trylsock.c && \ + ./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \ + && echo -lsocket -lnsl || exit 0 ) > socket.lib + rm -f trylsock.o trylsock + +ssl.lib: \ +../conf-ssllib print-dl.sh + rm -f ssl.lib + sh print-dl.sh > ssl.lib + chmod 755 ssl.lib + +ssl_ca.o: \ +compile ssl_ca.c ucspissl.h + ./compile ssl_ca.c + +ssl_cca.o: \ +compile ssl_cca.c ucspissl.h + ./compile ssl_cca.c + +ssl_chainfile.o: \ +compile ssl_chainfile.c ucspissl.h + ./compile ssl_chainfile.c + +ssl_certkey.o: \ +compile ssl_certkey.c ucspissl.h + ./compile ssl_certkey.c + +ssl_ciphers.o: \ +compile ssl_ciphers.c ucspissl.h + ./compile ssl_ciphers.c + +ssl_context.o: \ +compile ssl_context.c ucspissl.h + ./compile ssl_context.c + +ssl_env.o: \ +compile ssl_env.c ucspissl.h + ./compile ssl_env.c + +ssl_error.o: \ +compile ssl_error.c ucspissl.h + ./compile ssl_error.c + +ssl_io.o: \ +compile ssl_io.c ucspissl.h + ./compile ssl_io.c + +ssl_new.o: \ +compile ssl_new.c ucspissl.h + ./compile ssl_new.c + +ssl_params.o: \ +compile ssl_params.c ucspissl.h + ./compile ssl_params.c + +ssl_timeout.o: \ +compile ssl_timeout.c ucspissl.h + ./compile ssl_timeout.c + +ssl_verify.o: \ +compile ssl_verify.c ucspissl.h + ./compile ssl_verify.c + +sslcat: \ +warn-auto.sh sslcat.sh + rm -f sslcat + cat warn-auto.sh sslcat.sh \ + | sed s}HOME}"`head -1 ../conf-home`"}g \ + > sslcat + chmod 755 sslcat + +sslclient: \ +load sslclient.o auto_cafile.o auto_cadir.o auto_ciphers.o \ +remoteinfo.o ucspissl.a socket.lib ssl.lib + ./load sslclient auto_cafile.o auto_cadir.o auto_ciphers.o \ + remoteinfo.o ucspissl.a \ + `cat socket.lib` `cat ssl.lib` + +sslclient.o: \ +compile sslclient.c auto_cadir.h auto_cafile.h auto_ciphers.h \ +remoteinfo.h ucspissl.h + ./compile sslclient.c + +sslconnect: \ +warn-auto.sh sslconnect.sh + rm -f sslconnect + cat warn-auto.sh sslconnect.sh \ + | sed s}HOME}"`head -1 ../conf-home`"}g \ + > sslconnect + chmod 755 sslconnect + +sslhandle: \ +load sslhandle.o auto_cafile.o auto_ccafile.o auto_cadir.o \ +auto_certchainfile.o auto_dhfile.o \ +auto_certfile.o auto_keyfile.o auto_ciphers.o \ +coe.o rules.o ip4_bit.o ip6_bit.o remoteinfo.o sslprint.o \ +ucspissl.a socket.lib ssl.lib + ./load sslhandle auto_cafile.o auto_ccafile.o auto_cadir.o \ + auto_dhfile.o auto_ciphers.o \ + auto_certchainfile.o auto_certfile.o auto_keyfile.o \ + coe.o rules.o ip4_bit.o ip6_bit.o remoteinfo.o sslprint.o \ + ucspissl.a `cat socket.lib` `cat ssl.lib` + +sslhandle.o: \ +compile sslhandle.c auto_cadir.h auto_cafile.h auto_ccafile.h \ +auto_certchainfile.h auto_certfile.h auto_ciphers.h \ +auto_dhfile.h auto_keyfile.h rules.h ip_bit.h ucspissl.h coe.h \ +remoteinfo.o rules.o ip4_bit.o ip6_bit.o ucspissl.a + ./compile sslhandle.c + +sslperl: \ +load sslperl.o ucspissl.a sslhandle.o \ +auto_cafile.o auto_ccafile.o auto_cadir.o \ +auto_dhfile.o auto_certfile.o auto_keyfile.o \ +auto_ciphers.o auto_certchainfile.o \ +coe.o rules.o remoteinfo.o ip4_bit.o ip6_bit.o \ +socket.lib ssl.lib perlembed.lib + ./load sslperl auto_cafile.o auto_ccafile.o auto_cadir.o \ + auto_dhfile.o auto_certfile.o auto_keyfile.o \ + auto_ciphers.o auto_certchainfile.o ucspissl.a sslhandle.o \ + rules.o ip4_bit.o ip6_bit.o remoteinfo.o coe.o \ + ucspissl.a `cat socket.lib` `cat ssl.lib` `cat perlembed.lib` + +sslperl.o: \ +compile ccperl sslperl.c sslperl.c ucspissl.h + ./compile `cat ccperl` sslperl.c + +sslprint: \ +load sslprint.o auto_cafile.o auto_ccafile.o auto_cadir.o \ +auto_dhfile.o auto_certfile.o auto_keyfile.o \ +auto_ciphers.o auto_certchainfile.o coe.o sslhandle.o \ +rules.o ip4_bit.o ip6_bit.o remoteinfo.o \ +ucspissl.a socket.lib ssl.lib + ./load sslprint auto_cafile.o auto_ccafile.o auto_cadir.o \ + auto_dhfile.o auto_certfile.o auto_keyfile.o \ + auto_ciphers.o auto_certchainfile.o \ + rules.o ip4_bit.o ip6_bit.o remoteinfo.o coe.o sslhandle.o \ + ucspissl.a `cat socket.lib` `cat ssl.lib` + +sslprint.o: \ +compile sslprint.c + ./compile sslprint.c + +sslserver: \ +load sslserver.o auto_cafile.o auto_ccafile.o auto_cadir.o \ +auto_certchainfile.o auto_dhfile.o \ +auto_certfile.o auto_keyfile.o auto_ciphers.o \ +rules.o ip4_bit.o ip6_bit.o remoteinfo.o \ +ucspissl.a socket.lib ssl.lib + ./load sslserver auto_cafile.o auto_ccafile.o auto_cadir.o \ + auto_dhfile.o auto_ciphers.o \ + auto_certchainfile.o auto_certfile.o auto_keyfile.o \ + rules.o ip4_bit.o ip6_bit.o remoteinfo.o ucspissl.a \ + `cat socket.lib` `cat ssl.lib` + +sslserver.o: \ +compile sslserver.c auto_cadir.h auto_cafile.h auto_ccafile.h \ +auto_certchainfile.h auto_certfile.h auto_ciphers.h \ +auto_dhfile.h auto_keyfile.h \ +remoteinfo.h rules.h ip_bit.h ucspissl.h + ./compile sslserver.c + +sysdeps: \ +systype compile load hassgact.h hassgprm.h + rm -f sysdeps + cat systype compile load >> sysdeps + grep sysdep hassgact.h >> sysdeps + grep sysdep hassgprm.h >> sysdeps + +systype: \ +find-systype.sh trycpp.c x86cpuid.c + sh find-systype.sh > systype + +ucspissl.a: \ +makelib ssl_ca.o ssl_cca.o ssl_certkey.o ssl_chainfile.o ssl_ciphers.o \ +ssl_context.o ssl_env.o ssl_error.o ssl_io.o ssl_new.o ssl_params.o \ +ssl_timeout.o ssl_verify.o ucspissl.o + ./makelib ucspissl.a ssl_ca.o ssl_cca.o ssl_certkey.o ssl_chainfile.o \ + ssl_ciphers.o ssl_context.o ssl_env.o ssl_error.o ssl_io.o ssl_new.o \ + ssl_params.o ssl_timeout.o ssl_verify.o ucspissl.o + +ucspissl.o: \ +compile ucspissl.c ucspissl.h + ./compile ucspissl.c + +clean: + rm -f `cat TARGETS` diff --git a/src/TARGETS b/src/TARGETS new file mode 100644 index 0000000..0c8ccf5 --- /dev/null +++ b/src/TARGETS @@ -0,0 +1,62 @@ +auto-str +auto-str.o +auto_cadir.c +auto_cadir.o +auto_cafile.c +auto_cafile.o +auto_ccafile.c +auto_ccafile.o +auto_certchainfile.c +auto_certchainfile.o +auto_certfile.c +auto_certfile.o +auto_ciphers.c +auto_ciphers.o +auto_dhfile.c +auto_dhfile.o +auto_keyfile.c +auto_keyfile.o +ccperl +choose +coe.o +compile +hasgact.h +hasgprm.h +https@ +load +makelib +perlembed.lib +remoteinfo.o +rules.o +socket.lib +ssl.lib +ssl_ca.o +ssl_cca.o +ssl_certkey.o +ssl_chainfile.o +ssl_ciphers.o +ssl_context.o +ssl_env.o +ssl_error.o +ssl_io.o +ssl_new.o +ssl_params.o +ssl_timeout.o +ssl_verify.o +sslcat +sslclient +sslclient.o +sslconnect +sslhandle.o +sslperl +sslperl.o +sslprint +sslprint.o +sslserver +sslserver.o +sysdeps +systype +tryssl.o +ucspissl.a +ucspissl.o +*.gch diff --git a/src/auto-str.c b/src/auto-str.c new file mode 100644 index 0000000..4086921 --- /dev/null +++ b/src/auto-str.c @@ -0,0 +1,42 @@ +/* what to do */ +#include "readwrite.h" +#include "exit.h" +#include "buffer.h" + +char bspace[BUFFER_SMALL]; +buffer b = BUFFER_INIT(buffer_unixwrite,1,bspace,sizeof(bspace)); + +static void outs(const char *s) +{ + if (buffer_puts(&b,s) == -1) _exit(111); +} + +int main(int argc,char **argv) +{ + char *name; + char *value; + unsigned char ch; + char octal[4]; + + name = argv[1]; + if (!name) _exit(100); + value = argv[2]; + if (!value) _exit(100); + + outs("const char "); + outs(name); + outs("[] = \"\\\n"); + + while ((ch = *value++)) { + outs("\\"); + octal[3] = 0; + octal[2] = '0' + (ch & 7); ch >>= 3; + octal[1] = '0' + (ch & 7); ch >>= 3; + octal[0] = '0' + (ch & 7); + outs(octal); + } + + outs("\\\n\";\n"); + if (buffer_flush(&b) == -1) _exit(111); + _exit(0); +} diff --git a/src/auto_cadir.h b/src/auto_cadir.h new file mode 100644 index 0000000..9d9dfe2 --- /dev/null +++ b/src/auto_cadir.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CADIR_H +#define AUTO_CADIR_H + +extern const char auto_cadir[]; + +#endif diff --git a/src/auto_cafile.h b/src/auto_cafile.h new file mode 100644 index 0000000..102ca55 --- /dev/null +++ b/src/auto_cafile.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CAFILE_H +#define AUTO_CAFILE_H + +extern const char auto_cafile[]; + +#endif diff --git a/src/auto_ccafile.h b/src/auto_ccafile.h new file mode 100644 index 0000000..9d39c72 --- /dev/null +++ b/src/auto_ccafile.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CCAFILE_H +#define AUTO_CCAFILE_H + +extern const char auto_ccafile[]; + +#endif diff --git a/src/auto_certchainfile.h b/src/auto_certchainfile.h new file mode 100644 index 0000000..31d4df8 --- /dev/null +++ b/src/auto_certchainfile.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CERTCHAINFILE_H +#define AUTO_CERTCHAINFILE_H + +extern const char auto_certchainfile[]; + +#endif diff --git a/src/auto_certfile.h b/src/auto_certfile.h new file mode 100644 index 0000000..add5826 --- /dev/null +++ b/src/auto_certfile.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CERTFILE_H +#define AUTO_CERTFILE_H + +extern const char auto_certfile[]; + +#endif diff --git a/src/auto_ciphers.h b/src/auto_ciphers.h new file mode 100644 index 0000000..2842fbd --- /dev/null +++ b/src/auto_ciphers.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CIPHERS_H +#define AUTO_CIPHERS_H + +extern const char auto_ciphers[]; + +#endif diff --git a/src/auto_dhfile.h b/src/auto_dhfile.h new file mode 100644 index 0000000..83afa2a --- /dev/null +++ b/src/auto_dhfile.h @@ -0,0 +1,6 @@ +#ifndef AUTO_DHFILE_H +#define AUTO_DHFILE_H + +extern const char auto_dhfile[]; + +#endif diff --git a/src/auto_keyfile.h b/src/auto_keyfile.h new file mode 100644 index 0000000..feac74f --- /dev/null +++ b/src/auto_keyfile.h @@ -0,0 +1,6 @@ +#ifndef AUTO_KEYFILE_H +#define AUTO_KEYFILE_H + +extern const char auto_keyfile[]; + +#endif diff --git a/src/chkshsgr.c b/src/chkshsgr.c new file mode 100644 index 0000000..12442ea --- /dev/null +++ b/src/chkshsgr.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <unistd.h> +#include "exit.h" + +int main() +{ + short x[4]; + + x[0] = x[1] = 0; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + _exit(0); +} diff --git a/src/choose.sh b/src/choose.sh new file mode 100644 index 0000000..feff2da --- /dev/null +++ b/src/choose.sh @@ -0,0 +1,18 @@ + +result="$4" + +case "$1" in + *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *r*) ./$2 >/dev/null 2>&1 || result="$3" ;; +esac + +rm -f $2.o $2 + +exec cat "$result" diff --git a/src/coe.c b/src/coe.c new file mode 100644 index 0000000..50b2397 --- /dev/null +++ b/src/coe.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <fcntl.h> +#include "coe.h" + +int coe(int fd) +{ + return fcntl(fd,F_SETFD,1); +} diff --git a/src/coe.h b/src/coe.h new file mode 100644 index 0000000..b17db54 --- /dev/null +++ b/src/coe.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef COE_H +#define COE_H + +extern int coe(int); + +#endif diff --git a/src/exit.h b/src/exit.h new file mode 100644 index 0000000..39011c8 --- /dev/null +++ b/src/exit.h @@ -0,0 +1,6 @@ +#ifndef EXIT_H +#define EXIT_H + +extern void _exit(); + +#endif diff --git a/src/exp.base b/src/exp.base new file mode 100644 index 0000000..c182da0 --- /dev/null +++ b/src/exp.base @@ -0,0 +1,325 @@ +---> test sslserver + sslclient: four instances of sslserver (ports 50013, 50014, 50015, 50016) are used +---> sslserver @port 50015 requires client certs +++++ +---> test sslclient/sslserver behavior with wrong parm (timeout 2 secs) +++++ +--- sslclient prints usage message without enough arguments +sslclient: usage: sslclient [ -463hHrRdDiqQveEsSnNxX ] [ -i localip ] [ -p localport ] [ -T timeoutconn ] [ -l localname ] [ -t timeoutinfo ] [ -I interface ] [ -a cafile ] [ -A cadir ] [ -c certfile ] [ -z ciphers ] [ -k keyfile ] [ -V verifydepth ] [ -w progtimeout ] host port program +100 +--- sslclient prints error message with unknown port name +sslclient: fatal: (111) unable to figure out port number for nonexistentport +111 +--- sslclient prints error message when connection fails +sslclient: drop: (110) unable to connect to: 127.0.0.1 port: 16 +110 +--- sslclient -q does not print error message when connection fails +110 +--- sslclient prints error message with unknown host name +sslclient: error: (111) No IP address for: nonexistent.local. +111 +--- sslclient prints error message with unresolvable host name +sslclient: error: (111) No IP address for: thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. +111 +--- sslserver prints usage message without enough arguments +sslserver: usage: sslserver [ -1346UXpPhHrRoOdDqQvVIeEsSnNmzZ ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] [ -I interface ] [ -T ssltimeout ] [ -w progtimeout ] host port program +100 +--- sslserver prints error message with unknown port name +sslserver: fatal: (111) unable to figure out port number for: nonexistentport +111 +--- sslserver prints error message with unknown host name +sslserver: fatal: (111) no IP address for: nonexistent.local. +111 +--- sslserver prints error message with unresolvable host name +sslserver: fatal: (111) temporarily unable to figure out IP address for: thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. +111 +--- sslserver prints error message with non-local host name +sslserver: fatal: (111) unable to bind to: ... +111 +---> test sslclient to connect to sslserver (on different port; note: cert verify will fail on localhost) +++++ +--- sslclient sets basic environment variables +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslserver -e also sets TCP environment variables +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient recognizes -D, -z, -r, -h, -t (with elective cipher) +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient sets basic environment variables +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient -e sets TCP environment variables +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient -s sets TLS environment variables +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient looks up host names properly (localhost. -> ip6-loopback) +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient -v works +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslserver -N does not check certificates CN +sslclient: tls connected to: ::1 port: 50014 +ok +0 +--- sslserver and sslclient print errors for incompatible cipher lists for TLS < 1.3 +sslclient: error: (111) unable to set cipher list +111 +--- sslclient -X ignores any server certificate +sslclient: tls connected to: ::1 port: 50014 +ok +0 +--- sslclient -n checks hostname with certificates SAN/CN +sslclient: fatal: (111) unable to bind to: ::1 port: 50027 +111 +---> test sslclient to connect to sslserver requiring client cert +++++ +--- sslserver prints error for no client certificate +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslserver prints error for bad client certificate +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslclient uses certificates +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +---> test sslcat to connect to sslserver@5016 +++++ +--- sslcat works +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslconnect works +banner0 +--- https@ works +0 +---> test sslconnect to connect to sslserver@5013 +++++ +--- sslclient and sslserver handle larger data +sslclient: tls connected to: ::1 port: 50013 +0 +--- sslserver times out +sslclient: tls connected to: ::1 port: 50013 +bannerhereur^M +0 +sslclient: tls connected to: ::1 port: 50013 +banner0 +---> test sslprint@50021 +++++ +--- sslprint prints usage message without enough arguments +sslprint: usage: sslprint[ -1346UXpPhHrRoOdDqQviIeEsS ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] [ -T ssltimeout ] [ -w progtimeout ] [ -f lockfile ] [ -I interface ] host port program +100 +--- sslprint prints error message with unknown port name +sslprint: fatal: (111) unable to figure out port number for: nonexistentport +111 +--- sslprint prints error message with unknown host name +sslprint: fatal: (111) no IP address for: nonexistent.local. +111 +--- sslprint prints error message with unresolvable host name +sslprint: fatal: (111) temporarily unable to figure out IP address for: thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. +111 +--- sslprint prints error message with non-local host name +sslprint: fatal: (111) unable to bind +111 +--- sslprint prints error message with used port +sslprint: fatal: (111) unable to bind +111 +--- sslprint sets basic environment variables +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslprint exits when environment changes +sslclient: error: (110) missing credentials (CA) or unable to validate server certificate +110 +--- sslprint does not lose descriptors +110 +--- sslserver -1v prints proper messages +::x1 : 50016 +sslserver::x ciphers x +sslserver::x cafile x xxx/rootCA_cert.pem +sslserver::x ccafile x +sslserver::x cadir x xxx/etc +sslserver::x certchainfile x +sslserver::x cert x xxx/::1_cert.pem +sslserver::x key x xxx/::1_key.pem +sslserver::x dhparam x xxx +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_CHACHA20_POLY1305_SHA256 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +::x1 : 50015 +sslserver::x ciphers x +sslserver::x cafile x xxx/rootCA_cert.pem +sslserver::x ccafile x xxx/rootCA_cert.pem +sslserver::x cadir x xxx/etc +sslserver::x certchainfile x +sslserver::x cert x xxx/::1_cert.pem +sslserver::x key x xxx/::1_key.pem +sslserver::x dhparam x xxx +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x error: (111) unable to accept TLS for pid: x +sslserver::x ended by x status 28416 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x error: (111) unable to accept TLS for pid: x +sslserver::x ended by x status 28416 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x error: (111) unable to accept TLS for pid: x +sslserver::x ended by x status 28416 +sslserver::x status: 0/1/0 +::x1 : 50014 +sslserver::x ciphers x +sslserver::x cafile x xxx/rootCA_cert.pem +sslserver::x ccafile x +sslserver::x cadir x xxx/etc +sslserver::x certchainfile x +sslserver::x cert x xxx/::1_cert.pem +sslserver::x key x xxx/::1_key.pem +sslserver::x dhparam x xxx +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x error: (111) unable to accept TLS for pid: x +sslserver::x ended by x status 28416 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +::x1 : 50013 +sslserver::x ciphers x +sslserver::x cafile x xxx/rootCA_cert.pem +sslserver::x ccafile x +sslserver::x cadir x xxx/etc +sslserver::x certchainfile x +sslserver::x cert x xxx/::1_cert.pem +sslserver::x key x xxx/::1_key.pem +sslserver::x dhparam x xxx +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +sslserver::x status: 1/1/0 +sslserver::x pid x from ::1 +sslserver::x ok x Localserver:::1:x ip6-loopback:::1::x +sslserver::x tls x accept TLSv1.3:TLS_AES_256_GCM_SHA384 +sslserver::x ended by x status 0 +sslserver::x status: 0/1/0 +::x1 : 50021 +sslprint::x ciphers x +sslprint::x cafile x xxx/rootCA_cert.pem +sslprint::x ccafile x +sslprint::x cadir x xxx/etc +sslprint::x certchainfile x +sslprint::x cert x xxx/::1_cert.pem +sslprint::x key x xxx/::1_key.pem +sslprint::x dhparam x xxx +sslprint::x status: 0/1 +sslprint::x status: 1/1 +sslprint::x pid x from :: +sslprint::x ok x Localserver:::1:x ip6-localnet:::::x +sslprint::x end x status 13 +sslprint::x status: 0/1 +sslprint::x status: 1/1 +sslprint::x pid x from :: +sslprint::x ok x Localserver:::1:x ip6-localnet:::::x +sslprint::x end x status 13 +sslprint::x status: 0/1 +sslprint::x status: 1/1 +sslprint::x pid x from :: +sslprint::x ok x Localserver:::1:x ip6-localnet:::::x +sslprint::x end x status 13 +sslprint::x status: 0/1 +sslprint::x status: 1/1 +sslprint::x end x status 15 +sslprint::x status: 0/1 diff --git a/src/exp.it b/src/exp.it new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/exp.it diff --git a/src/exp.sslperl b/src/exp.sslperl new file mode 100644 index 0000000..0a783dc --- /dev/null +++ b/src/exp.sslperl @@ -0,0 +1,105 @@ +--- sslperl works +sslperlHello, World! (1): here you are +0 +sslperlHello, World! (2): here you are +0 +sslperlHello, World! (1): here you are +0 +sslperlHello, World! (2): here you are +0 +--- sslperl prints usage message without enough arguments +sslperl: usage: sslperl[ -1346UXpPhHrRoOdDqQviIeEsS ] [ -c limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] [ -u uid ] [ -b backlog ] [ -l localname ] [ -t timeout ] [ -T ssltimeout ] [ -w progtimeout ] [ -f lockfile ] [ -I interface ] host port program +100 +--- sslperl prints error message with unknown port name +sslperl: fatal: (111) unable to figure out port number for: nonexistentport +111 +--- sslperl prints error message with unknown host name +sslperl: fatal: (111) temporarily unable to figure out IP address for: nonexistent.local. +111 +--- sslperl prints error message with unresolvable host name +sslperl: fatal: (111) no IP address for: thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. +111 +--- sslperl prints error message with non-local host name +sslperl: fatal: (111) unable to bind +111 +--- sslperl preserves environment +sslperl changed environment +0 +--- sslperl handles larger requests +sslclient: tls connected to: 127.0.0.1 port: 50022 +0 +--- sslserver -1v prints proper messages +127.0.0.1 : 50022 +sslperl: cafile x xxx/rootCA.pem +sslperl: ccafile x +sslperl: cadir x xxx/etc +sslperl: certchainfile x +sslperl: cert x xxx/::x +sslperl: key x xxx/::x +sslperl: dhparam x xxx +sslperl: status: 0/1/0 +sslperl: status: 1/1/0 +sslperl: pid x from 127.0.0.1 +sslperl: ok x Localserver:127.0.0.1:50022 ip4-loopback:127.0.0.1::x +sslperl: tls x accept +log: Hello, World! (1): here you are +sslperl: drop: (110) environ changed +sslperl: done ... +sslperl: pid x from 127.0.0.1 +sslperl: ok x Localserver:127.0.0.1:50022 ip4-loopback:127.0.0.1::x +sslperl: tls x accept +log: Hello, World! (2): here you are +sslperl: end x status 0 +sslperl: status: 0/1/0 +sslperl: status: 1/1/0 +sslperl: pid x from 127.0.0.1 +sslperl: ok x Localserver:127.0.0.1:50022 ip4-loopback:127.0.0.1::x +sslperl: tls x accept +log: Hello, World! (1): here you are +sslperl: drop: (110) environ changed +sslperl: done ... +sslperl: pid x from 127.0.0.1 +sslperl: ok x Localserver:127.0.0.1:50022 ip4-loopback:127.0.0.1::x +sslperl: tls x accept +log: Hello, World! (2): here you are +sslperl: end x status 0 +sslperl: status: 0/1/0 +sslperl: status: 1/1/0 +sslperl: end x status 15 +sslperl: status: 0/1/0 +127.0.0.1 : 50022 +sslperl: cafile x xxx/rootCA.pem +sslperl: ccafile x +sslperl: cadir x xxx/etc +sslperl: certchainfile x +sslperl: cert x xxx/::x +sslperl: key x xxx/::x +sslperl: dhparam x xxx +sslperl: status: 0/1/0 +sslperl: status: 1/1/0 +sslperl: pid x from 127.0.0.1 +sslperl: ok x Localserver:127.0.0.1:50022 ip4-loopback:127.0.0.1::x +sslperl: tls x accept +log: NOW= +log: changed environment +sslperl: drop: (110) environ changed +sslperl: done ... +sslperl: end x status 15 +sslperl: status: 0/1/0 +127.0.0.1 : 50022 +sslperl: cafile x xxx/rootCA.pem +sslperl: ccafile x +sslperl: cadir x xxx/etc +sslperl: certchainfile x +sslperl: cert x xxx/::x +sslperl: key x xxx/::x +sslperl: dhparam x xxx +sslperl: status: 0/1/0 +sslperl: status: 1/1/0 +sslperl: pid x from 127.0.0.1 +sslperl: ok x Localserver:127.0.0.1:50022 ip4-loopback:127.0.0.1::x +sslperl: tls x accept +sslperl: drop: (110) environ changed +sslperl: done ... +sslperl: end x status 15 +sslperl: status: 0/1/0 diff --git a/src/find-systype.sh b/src/find-systype.sh new file mode 100644 index 0000000..15322b4 --- /dev/null +++ b/src/find-systype.sh @@ -0,0 +1,151 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null + +sys="`uname -s | tr '/:[:upper:]' '..[:lower:]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os|freebsd|netbsd|openbsd) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + cc -c trycpp.c + cc -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro + ;; +arm) + # too many on the rood + chip=arm + ;; +arm64) + # pi 3+ + chip=arm64 +esac + +if cc -c x86cpuid.c +then + if cc -o x86cpuid x86cpuid.o + then + x86cpuid="`./x86cpuid | tr /: ..`" + case "$x86cpuid" in + ?*) + chip="$x86cpuid" + ;; + esac + fi +fi +rm -f x86cpuid x86cpuid.o + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' diff --git a/src/fork.h1 b/src/fork.h1 new file mode 100644 index 0000000..ddd589d --- /dev/null +++ b/src/fork.h1 @@ -0,0 +1,9 @@ +#ifndef FORK_H +#define FORK_H + +/* sysdep: -vfork */ + +extern int fork(); +#define vfork fork + +#endif diff --git a/src/fork.h2 b/src/fork.h2 new file mode 100644 index 0000000..7c1b0b9 --- /dev/null +++ b/src/fork.h2 @@ -0,0 +1,9 @@ +#ifndef FORK_H +#define FORK_H + +/* sysdep: +vfork */ + +extern int fork(); +extern int vfork(); + +#endif diff --git a/src/hassgact.h1 b/src/hassgact.h1 new file mode 100644 index 0000000..7639d24 --- /dev/null +++ b/src/hassgact.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -sigaction */ diff --git a/src/hassgact.h2 b/src/hassgact.h2 new file mode 100644 index 0000000..60ff776 --- /dev/null +++ b/src/hassgact.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +sigaction */ +#define HASSIGACTION 1 diff --git a/src/hassgprm.h1 b/src/hassgprm.h1 new file mode 100644 index 0000000..ef3eee9 --- /dev/null +++ b/src/hassgprm.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -sigprocmask */ diff --git a/src/hassgprm.h2 b/src/hassgprm.h2 new file mode 100644 index 0000000..be9d0d7 --- /dev/null +++ b/src/hassgprm.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +sigprocmask */ +#define HASSIGPROCMASK 1 diff --git a/src/hasshsgr.h1 b/src/hasshsgr.h1 new file mode 100644 index 0000000..3806277 --- /dev/null +++ b/src/hasshsgr.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -shortsetgroups */ diff --git a/src/hasshsgr.h2 b/src/hasshsgr.h2 new file mode 100644 index 0000000..5624ed0 --- /dev/null +++ b/src/hasshsgr.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +shortsetgroups */ +#define HASSHORTSETGROUPS 1 diff --git a/src/haswaitp.h1 b/src/haswaitp.h1 new file mode 100644 index 0000000..0d6f82c --- /dev/null +++ b/src/haswaitp.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -waitpid */ diff --git a/src/haswaitp.h2 b/src/haswaitp.h2 new file mode 100644 index 0000000..015413f --- /dev/null +++ b/src/haswaitp.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +waitpid */ +#define HASWAITPID 1 diff --git a/src/https@.sh b/src/https@.sh new file mode 100644 index 0000000..6a902b7 --- /dev/null +++ b/src/https@.sh @@ -0,0 +1,15 @@ +host=${1-0} +path=${2-} +port=${3-443} +args="" +if [ $# -gt 3 ] +then + shift; shift; shift + args="$@" +fi +echo "GET /${path} HTTP/1.1 +Host: $host:$port +" | HOME/bin/sslclient -XRHl0 $args -- "$host" "$port" sh -c ' + addcr >&7 + exec HOME/bin/delcr <&6 +' | awk '/^$/ { body=1; next } { if (body) print }' diff --git a/src/ip4_bit.c b/src/ip4_bit.c new file mode 100644 index 0000000..02dbf7a --- /dev/null +++ b/src/ip4_bit.c @@ -0,0 +1,101 @@ +/*** + @file ip4_bit.c + @author Jens Wehrenbrecht, feh + @funcs ip4_bitstring, bitstring_ip4 +*/ +#include "ip.h" +#include "byte.h" +#include "scan.h" +#include "str.h" +#include "fmt.h" +#include "ip_bit.h" + +#define BITSUBSTITUTION + +static char strnum[FMT_ULONG]; + +/*** + /fn ip4_bitstring + /brief This function converts a IPv4 address into its binary representation with given prefix len + /param out: ip4string 0-terminated destination address. + /param in: ip4address The source address. + /param in: prefix The net prefix bits (maximum 32 bits for IPv4). + /return -1: lack of memory; 1: non valid IP address; 0: successful converted. +*/ + +int ip4_bitstring(stralloc *ip4string, char *ip, unsigned int prefix) +{ + int i, j; + char ip4[4]; + int count = 0; + unsigned char number; +#ifdef BITSUBSTITUTION + const char *letterarray = "abcdefghijklmnopqrstuvwxyz123456"; +#endif + + if (!stralloc_copys(ip4string,"")) return -1; + if (!stralloc_readyplus(ip4string,32)) return -1; + ip4_scan(ip,ip4); + + for (i = 0; i < 4; i++) { + number = (unsigned char) ip4[i]; + for (j = 7; j >= 0; j--) { + if (number & (1<<j)) { +#ifdef BITSUBSTITUTION + if (!stralloc_catb(ip4string,letterarray + count,1)) return -1; +#else + if (!stralloc_cats(ip4string,"1")) return -1; +#endif + } else { + if (!stralloc_cats(ip4string,"0")) return -1; + } + count++; + prefix--; + if (prefix == 0) return 0; + } + } + + return 1; +} + +/*** + /fn bitstring_ip4 + /brief This function takes an IPv4 bitstring and translates it to an IPv4 address + prefix + /param in: ip4string The source address (with '_' start token). + /param out: ip4addr 0-terminated estination IPv4 address + net prefix (eg. 127.0.0.0/16). + /return -1: lack of memory; 1: non valid IPv4 address; 0: successful converted. +*/ + +int bitstring_ip4(stralloc *ip4addr, stralloc *ip4string) +{ + int j; + int num = 0; + int value = 256; + int prefix; + + if (!stralloc_copys(ip4addr,"")) return -1; + prefix = ip4string->len - 1; + + if (prefix <= 0) return 1; + if (prefix <= 1 || prefix > 32) return 1; + + for (j = 1; j <= prefix; j++) { + if (ip4string->s[j] != '0') { + num += (value/2); + value /= 2; + } else + value /= 2; + if (j % 8 == 0 || j == prefix) { + if (!stralloc_catb(ip4addr,strnum,fmt_ulong(strnum,num))) return -1; + if (j < 32) if (!stralloc_cats(ip4addr,".")) return -1; + num = 0; + value = 256; + } + } + + if (!stralloc_cats(ip4addr,"/")) return -1; + if (!stralloc_catb(ip4addr,strnum,fmt_ulong(strnum,prefix))) return -1; + if (!stralloc_0(ip4addr)) return -1; + + return 0; +} diff --git a/src/ip6_bit.c b/src/ip6_bit.c new file mode 100644 index 0000000..528f0b0 --- /dev/null +++ b/src/ip6_bit.c @@ -0,0 +1,180 @@ +/** + @file ip6_bit.c + @author Li Minh Bui, feh + @funcs bytetohex, ip6_bitstring, bitstring_ip6, ip6_fmt_str +*/ +#include "ip.h" +#include "byte.h" +#include "str.h" +#include "fmt.h" +#include "stralloc.h" +#include "ip_bit.h" + +#define BITSUBSTITUTION + +/*** + /fn bytetohex + /brief Convert a number of max 255 to hex. + /param decimal The decimal number. + /param hex The converted hex value. +*/ + +void bytetohex(unsigned char decimal, char hex[3]) +{ + char* hexdigits = "0123456789ABCDEF"; + int rest, number; + hex[0] = '0'; + hex[1] = '0'; + hex[2] = '\0'; + + number = decimal / 16; + rest = decimal % 16; + + hex[0] = hexdigits[number]; + hex[1] = hexdigits[rest]; +} + +static char strnum[FMT_ULONG]; + +/*** + /fn ip6_bitstring + /brief This function converts a IPv6 address into its binary representation. + /param out: ip6string The destination address. + /param in: ip6addr The source address. + /param in: prefix The net prefix bits (maximum 128 bits for IPv6). + /return -1: lack of memory; 1: non valid IPv6 address; 0: successful converted. +*/ + +int ip6_bitstring(stralloc *ip6string, char *ip6addr, unsigned int prefix) +{ + char ip6[16]; + int bit, octettbitpos, number, shiftedvalue; + int i, slashpos, ip6len; + +#ifdef BITSUBSTITUTION + char subvalueforbitone[1]; + subvalueforbitone[0] = 96; /* substitution starts from token '_' = 96 */ +#endif + + ip6len = str_len(ip6addr); + slashpos = byte_chr(ip6addr,ip6len,'/'); + if (!stralloc_copyb(ip6string,ip6addr,slashpos)) return -1; + ip6addr[slashpos] = '\0'; + + if (!ip6_scan(ip6addr,ip6)) return 1; + if (!stralloc_copys(ip6string,"")) return -1; + + for (i = 0; i < 16; i++) { + number = (unsigned char) ip6[i]; + + for (octettbitpos = 7; octettbitpos >= 0; octettbitpos--) { + shiftedvalue = 1 << octettbitpos; + bit = number / shiftedvalue; + number = number - bit * (shiftedvalue); + + if (bit) { +#ifdef BITSUBSTITUTION + if (!stralloc_catb(ip6string,subvalueforbitone,1)) return -1; + subvalueforbitone[0]++; +#else + if (!stralloc_cats(ip6string,"1")) return -1; +#endif + } else + if (!stralloc_cats(ip6string,"0")) return -1; + + prefix--; + if (prefix == 0) return 0; + } + } + + return 1; +} + +/*** + /fn bitstring_ip6 + /brief This function converts a bit string which is produced by ip6_bitstring() + into an IPv6 address. The string may start with a '^'. + /param in: ip6string Source string which need to be converted. + /param out ip6addr 0-terminated IPv6 destination address with net prefix. + /return -1: No memory could allocated,0: Failure,1: Success. +*/ + +int bitstring_ip6(stralloc *ip6addr ,stralloc *ip6string) +{ + int j = 0; + int i = 0; + int len, prefix, shiftedvalue; + int bitpos = 7; + int decimalnumber = 0; + char ip6[16] = {0}; + char ip6compact[40] = {0}; + + if (!stralloc_copys(ip6addr,"")) return -1; + prefix = ip6string->len - 1; + + if (prefix <= 0) return 1; + if (prefix <= 1 || prefix > 128) return 1; + + if (ip6string->s[0] == '^') j = 1; + + for (i = j, j = 0; i <= prefix; i++) { + if (ip6string->s[i] != '0') { + shiftedvalue = 1 << bitpos; + decimalnumber += shiftedvalue; + } + bitpos--; + if (bitpos == -1) { /* Put each converted byte into the array. */ + if (j < 16) { + ip6[j] = (unsigned char) decimalnumber; + j++; + bitpos = 7; + decimalnumber = 0; + } + } + } + + if (bitpos < 7) { /* Last bit was read,but the number was not converted. */ + ip6[j] = (unsigned char) decimalnumber; + j++; + } + + len = ip6_fmt(ip6compact,ip6); + if (!len) return 1; + + if (!stralloc_copyb(ip6addr,ip6compact,len)) return -1; + if (!stralloc_cats(ip6addr,"/")) return -1; + if (!stralloc_catb(ip6addr,strnum,fmt_ulong(strnum,prefix))) return -1; + if (!stralloc_0(ip6addr)) return -1; + + return 0; +} +/*** + /fn ip6_fmt_str + /brief This function expands any valid IPv6 address into its full format of 16 bytes. + It returns the number of processed tokens on success. + /param src Source IPv6 address. + /param destination Expanded IPv6 address. + /return -1: No memory could allocated; 1: failure, 0: success +*/ + +unsigned int ip6_fmt_str(stralloc *dest, char *src) +{ + stralloc addr = {0}; + char ip6[16]; + char hexvalue[3] = {0, 0, 0}; + int i; + + if (!stralloc_copys(&addr,src)) return -1; + if (!stralloc_0(&addr)) return -1; + + if (ip6_scan(addr.s,ip6) == 0) return 1; + if (!stralloc_copys(dest,"")) return -1; + + for (i = 0; i < 16; i++) { + bytetohex((unsigned char)ip6[i],hexvalue); + stralloc_catb(dest,hexvalue,2); + if (!((i+1) % 2) && (i+1) < 16) + if (!stralloc_cats(dest,":")) return -1; /*Append ':' after every two bytes.*/ + } + return 0; +} diff --git a/src/ip_bit.h b/src/ip_bit.h new file mode 100644 index 0000000..49df160 --- /dev/null +++ b/src/ip_bit.h @@ -0,0 +1,15 @@ +#ifndef IP_BIT_H +#define IP_BIT_H + +#include "stralloc.h" + +extern int bitstring_ip4(stralloc *,stralloc *); +extern int ip4_bitstring(stralloc *,char *,unsigned int); +extern unsigned int ip4_cscan(const char *,char [4]); +extern void getnum(char *,int,unsigned long *); + +extern int bitstring_ip6(stralloc *,stralloc *); +extern int ip6_bitstring(stralloc *,char *,unsigned int); +extern unsigned int ip6_fmt_str(stralloc *,char *); + +#endif diff --git a/src/it-base=d b/src/it-base=d new file mode 100644 index 0000000..a1d0820 --- /dev/null +++ b/src/it-base=d @@ -0,0 +1,7 @@ +sslclient +sslserver +https@ +sslcat +sslconnect +sslprint +sslhandle diff --git a/src/it-sslperl=d b/src/it-sslperl=d new file mode 100644 index 0000000..68065ca --- /dev/null +++ b/src/it-sslperl=d @@ -0,0 +1 @@ +sslperl diff --git a/src/it-sys=d b/src/it-sys=d new file mode 100644 index 0000000..fa5d3e9 --- /dev/null +++ b/src/it-sys=d @@ -0,0 +1 @@ +sysdeps diff --git a/src/it=d b/src/it=d new file mode 100644 index 0000000..304fcac --- /dev/null +++ b/src/it=d @@ -0,0 +1 @@ +it-base diff --git a/src/print-ar.sh b/src/print-ar.sh new file mode 100644 index 0000000..99bc116 --- /dev/null +++ b/src/print-ar.sh @@ -0,0 +1,14 @@ +cat warn-auto.sh +echo 'main="$1"; shift' +echo 'rm -f "$main"' +echo 'ar cr "$main" ${1+"$@"}' +case "`cat systype`" in + sunos-5.*) ;; + unix_sv*) ;; + irix64-*) ;; + irix-*) ;; + dgux-*) ;; + hp-ux-*) ;; + sco*) ;; + *) echo 'ranlib "$main"' ;; +esac diff --git a/src/print-cc.sh b/src/print-cc.sh new file mode 100644 index 0000000..2a46533 --- /dev/null +++ b/src/print-cc.sh @@ -0,0 +1,62 @@ +cc="`head -1 ../conf-cc`" +systype="`cat systype`" + +ccqlibs="`head -1 ../conf-qlibs`" +[ -d "$ccqlibs"/include ] && ccqlibs="-I${ccqlibs}/include" \ +|| ccqlibs="" + +cc -c trycpp.c -malign-double >/dev/null 2>&1 \ +&& ccad="-malign-double" + +cc -c trycpp.c -march=ultrasparc >/dev/null 2>&1 \ +&& ccus="-march=ultrasparc" + +cc -c trycpp.c -march=powerpc >/dev/null 2>&1 \ +&& ccpp="-march=powerpc" + +cc -c trycpp.c -march=21164 >/dev/null 2>&1 \ +&& cc21="-march=21164" + +cc -c trycpp.c -march=native >/dev/null 2>&1 \ +&& ccarm="-march=native" + +rm -f trycpp.o + +ccssl="`head -1 ../conf-ssl`" +eval cc -c tryssl.c ${ccssl} >/dev/null 2>&1 \ +|| ccssl="" + +ccbase="cc -fomit-frame-pointer -Wall" + +case "$cc:$systype" in + auto:*:i386-*:*) + cc="$ccbase -O1 $ccad" + ;; + auto:*:amd64-*:*) + cc="$ccbase -O2 $ccad" + ;; + auto:*:x86_64-*:*) + cc="$ccbase -O2 $ccad" + ;; + auto:*:sparc-*:*:*:*) + cc="$ccbase -O1 $ccus" + ;; + auto:*:ppc-*:*:*:*) + cc="$ccbase -O2 $ccpp" + ;; + auto:*:alpha-*:*:*:*) + cc="$ccbase -O2 $cc21" + ;; + auto:aix-*:-:-:*:-) + cc="$ccbase -O2 $ccpp" + ;; + auto:*:armv7l-:*) + cc="$ccbase -O2 $ccarm" + ;; + auto:*) + cc="$ccbase -O2" + ;; +esac + +cat warn-auto.sh +echo exec "$cc" ${ccqlibs} ${ccssl} '-c ${1+"$@"}' diff --git a/src/print-ccperl.sh b/src/print-ccperl.sh new file mode 100644 index 0000000..9cda68d --- /dev/null +++ b/src/print-ccperl.sh @@ -0,0 +1,10 @@ +ccopts="`head -1 ../conf-ccperl`" +runperl="`head -1 ../conf-perl`" + +case "$ccopts" in + auto) + ccopts="`$runperl -MExtUtils::Embed -e ccopts`" + ;; +esac + +echo "$ccopts" diff --git a/src/print-dl.sh b/src/print-dl.sh new file mode 100644 index 0000000..faa491c --- /dev/null +++ b/src/print-dl.sh @@ -0,0 +1,14 @@ +ssllib="`head -1 ../conf-ssllib`" + +dlflag=0 + +rm -f trycpp.o + +dlflag=`cc -c tryssl.c -ldl 2>&1 | wc -l` +if [ $dlflag -eq 0 ]; then + ssllib="$ssllib -ldl" +fi + +rm -f trycpp.o + +echo $ssllib diff --git a/src/print-ld.sh b/src/print-ld.sh new file mode 100644 index 0000000..c13472c --- /dev/null +++ b/src/print-ld.sh @@ -0,0 +1,18 @@ +ld="`head -1 ../conf-ld`" +qlibs="`head -1 ../conf-qlibs`" +systype="`cat systype`" + +flag=0 + +rm -f trycpp.o + +flag=`cc -c tryssl.c -m64 2>&1 | wc -l` +if [ $flag -eq 0 ]; then + ld="$ld -m64" +fi + +rm -f trycpp.o + +cat warn-auto.sh +echo 'main="$1"; shift' +echo exec "$ld" -L"${qlibs}" '-o "$main" "$main".o ${1+"$@"} -ldnsresolv -lqlibs' diff --git a/src/print-ldperl.sh b/src/print-ldperl.sh new file mode 100644 index 0000000..02331f0 --- /dev/null +++ b/src/print-ldperl.sh @@ -0,0 +1,10 @@ +ldopts="`head -1 ../conf-ldperl`" +runperl="`head -1 ../conf-perl`" + +case "$ldopts" in + auto) + ldopts="`$runperl -MExtUtils::Embed -e ldopts`" + ;; +esac + +echo "$ldopts" diff --git a/src/print-perlembed.sh b/src/print-perlembed.sh new file mode 100644 index 0000000..337da8e --- /dev/null +++ b/src/print-perlembed.sh @@ -0,0 +1,10 @@ +ldopts="`head -1 ../conf-ldperl`" +runperl="`head -1 ../conf-perl`" + +case "$ldopts" in + auto) + ldopts="$runperl -MExtUtils::Embed -e ldopts" + ;; +esac + +echo "$ldopts" diff --git a/src/remoteinfo.c b/src/remoteinfo.c new file mode 100644 index 0000000..665d2e5 --- /dev/null +++ b/src/remoteinfo.c @@ -0,0 +1,102 @@ +#include <unistd.h> +#include "fmt.h" +#include "buffer.h" +#include "socket_if.h" +#include "error.h" +#include "iopause.h" +#include "timeoutconn.h" +#include "dnsresolv.h" +#include "remoteinfo.h" + +static struct taia now; +static struct taia deadline; + +static int mywrite(int fd,char *buf,int len) +{ + iopause_fd x; + int r; + + x.fd = fd; + x.events = IOPAUSE_WRITE; + for (;;) { + taia_now(&now); + r = iopause(&x,1,&deadline,&now); + if (r > 0 && x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + return write(fd,buf,len); +} + +static int myread(int fd,char *buf,int len) +{ + iopause_fd x; + int r; + + x.fd = fd; + x.events = IOPAUSE_READ; + for (;;) { + taia_now(&now); + r = iopause(&x,1,&deadline,&now); + if (r > 0 && x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + return read(fd,buf,len); +} + +static int doit(stralloc *out,int s,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) +{ + buffer b; + char bspace[128]; + char strnum[FMT_ULONG]; + int numcolons; + char ch; + + if (socket_bind(s,iplocal,0,netif) == -1) return -1; + if (timeoutconn(s,ipremote,113,timeout,netif) == -1) return -1; + + buffer_init(&b,(ssize_t (*)())mywrite,s,bspace,sizeof(bspace)); + buffer_put(&b,strnum,fmt_ulong(strnum,portremote)); + buffer_put(&b," , ",3); + buffer_put(&b,strnum,fmt_ulong(strnum,portlocal)); + buffer_put(&b,"\r\n",2); + if (buffer_flush(&b) == -1) return -1; + + buffer_init(&b,(ssize_t (*)())myread,s,bspace,sizeof(bspace)); + numcolons = 0; + for (;;) { + if (buffer_get(&b,&ch,1) != 1) return -1; + if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; + if (ch == '\n') return 0; + if (numcolons < 3) { + if (ch == ':') ++numcolons; + } + else { + if (!stralloc_append(out,&ch)) return -1; + if (out->len > 256) return 0; + } + } +} + +int remoteinfo(stralloc *out,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) +{ + int s; + int r; + + if (!stralloc_copys(out,"")) return -1; + + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + + s = socket_tcp(); + if (s == -1) return -1; + r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout,netif); + close(s); + return r; +} diff --git a/src/remoteinfo.h b/src/remoteinfo.h new file mode 100644 index 0000000..37092d0 --- /dev/null +++ b/src/remoteinfo.h @@ -0,0 +1,9 @@ +#ifndef REMOTEINFO_H +#define REMOTEINFO_H + +#include "stralloc.h" +#include "uint_t.h" + +extern int remoteinfo(stralloc *,char *,uint16,char *,uint16,unsigned int,uint32); + +#endif diff --git a/src/rts.base b/src/rts.base new file mode 100644 index 0000000..0096007 --- /dev/null +++ b/src/rts.base @@ -0,0 +1,329 @@ +#!/bin/sh +# Assumptions: +# ucspi-tcp +# available TCP ports on ::1: 50013--50021 +# 127.0.0.1 is resolved as 'localhost' +# ::1/128 is resolved as 'ip6-loopback' +# 0.0.0.0 and ::/128 is resolved as 'localnet' +# +# $here is ucspi-ssl current directory +# +# Not tested: +# setting UID or GID +# rules +# write timeout + +echo '---> test sslserver + sslclient: four instances of sslserver (ports 50013, 50014, 50015, 50016) are used' +echo '---> sslserver @port 50015 requires client certs' +echo '++++' + +sslserver -w 2 \ +-s -E -c 1 -Bbanner -Vo -D -1 -3 -Xx rules.cdb -Rt5 -h -l Localserver -b 2 \ +::1 50016 ./print 3< $CADIR/::1.pw > log.50016 2>&1 & +pid_50016=$! + +sslserver -w 2 \ +-s -e -c 1 -Bbanner -Vo -D -1 -3 -Xx rules.cdb -Rt5 -h -l Localserver -b 2 -m \ +::1 50015 ./print 3< $CADIR/::1.pw > log.50015 2>&1 & +pid_50015=$! + +CIPHERS='' sslserver -w 2 \ +-s -e -c 1 -Bbanner -Vo -D -1 -3 -Xx rules.cdb -Rt5 -h -l Localserver -b 2 \ +::1 50014 ./print >log.50014 3< $CADIR/::1.pw 2>&1 & +pid_50014=$! +sleep 1 + +sslserver -w 2 \ +-s -e -c 1 -Bbanner -Vo -D -1 -3 -Xx rules.cdb -Rt5 -h -l Localserver -b 2 \ +::1 50013 cat - >log.50013 3< $CADIR/::1.pw 2>&1 & +pid_50013=$! +sleep 1 + +echo '---> test sslclient/sslserver behavior with wrong parm (timeout 2 secs)' +echo '++++' + +echo '--- sslclient prints usage message without enough arguments' +sslclient -T2 0 0; echo $? + +echo '--- sslclient prints error message with unknown port name' +sslclient -T2 0 nonexistentport echo wrong; echo $? + +echo '--- sslclient prints error message when connection fails' +sslclient -T2 0 016 echo wrong; echo $? + +echo '--- sslclient -q does not print error message when connection fails' +sslclient -T2 -q 0 016 echo wrong; echo $? + +echo '--- sslclient prints error message with unknown host name' +sslclient nonexistent.local. 016 echo wrong; echo $? + +echo '--- sslclient prints error message with unresolvable host name' +sslclient thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 50016 echo wrong; echo $? + +echo '--- sslserver prints usage message without enough arguments' +sslserver 0 0; echo $? + +echo '--- sslserver prints error message with unknown port name' +sslserver 0 nonexistentport echo wrong; echo $? + +echo '--- sslserver prints error message with unknown host name' +sslserver nonexistent.local. 016 echo wrong; echo $? + +echo '--- sslserver prints error message with unresolvable host name' +sslserver thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 50016 echo wrong; echo $? + +echo '--- sslserver prints error message with non-local host name' +( sslserver 1.2.3.4 016 echo wrong 2>&1 + echo $? +) | sed -e 's/unable to bind to: .*/unable to bind to: .../' + + +echo '---> test sslclient to connect to sslserver (on different port; note: cert verify will fail on localhost)' +echo '++++' + +echo '--- sslclient sets basic environment variables' +{ + sslclient -p 50017 -R -N -H -T 10 -l Local -a "$CAFILE" ::1 50016 sh -c 'cat <&6' + echo $? +} | sed -e 's/unable to bind to: .*/unable to bind to: .../' + + +echo '--- sslserver -e also sets TCP environment variables' +{ + sslclient -p 50018 -e -S -R -N -H -T 10 -l Local -a "$CAFILE" ::1 50016 sh -c 'cat <&6' + echo $? +} | sanitize + +echo '--- sslclient recognizes -D, -z, -r, -h, -t (with elective cipher)' +{ + sslclient -p 50019 -N -D -r -t1 -l Local -a "$CAFILE" \ + -z 'TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256' \ + ::1 50016 sh -c 'cat <&6' + echo $? +} +#} | sanitize + +echo '--- sslclient sets basic environment variables' +{ + sslclient -p 50020 -R -N -H -l Local -a "$CAFILE" ::1 50016 ./print + echo $? +} | sanitize + +echo '--- sslclient -e sets TCP environment variables' +{ + sslclient -p 50021 -e -R -N -H -l Local -a "$CAFILE" ::1 50016 ./print + echo $? +} | sanitize + +echo '--- sslclient -s sets TLS environment variables' +{ + sslclient -p 50022 -s -R -N -H -l Local -a "$CAFILE" ::1 50016 ./print + echo $? +} | sanitize + +echo '--- sslclient looks up host names properly (localhost. -> ip6-loopback)' +{ + sslclient -p 50023 -R -N -a "$CAFILE" localhost. 50016 ./print + echo $? +} | sanitize + +echo '--- sslclient -v works' +sslclient -p 50024 -v -R -N -H -l Local -a "$CAFILE" ::1 50016 echo ok +echo $? + +echo '--- sslserver -N does not check certificates CN' +( exec 2>&1 + sslclient -p 50025 -v -R -H -N -l ip6-localhost -a "$CAFILE" -X ::1 50014 sh -c 'sleep 1; echo ok' + echo $? +) | sanitize + +echo '--- sslserver and sslclient print errors for incompatible cipher lists for TLS < 1.3' +( exec 2>&1 + sslclient -p 50026 -v -R -H -N -l ip6-localhost -z 'FOOBAR' -a "$CAFILE" ::1 50014 \ + sh -c 'sleep 1; echo ok' + echo $? +) | sanitize + +echo '--- sslclient -X ignores any server certificate' +( exec 2>&1 + sslclient -p 50027 -v -R -H -l ip6-localhost -X ::1 50014 \ + sh -c 'sleep 1; echo ok' + echo $? +) | sanitize + +echo '--- sslclient -n checks hostname with certificates SAN/CN' +( exec 2>&1 + sslclient -p 50027 -v -R -H -l ip6-localhost -a "$CAFILE" ::1 50014 \ + sh -c 'sleep 1; echo ok' + echo $? +) | sanitize + +echo '---> test sslclient to connect to sslserver requiring client cert' +echo '++++' + +echo '--- sslserver prints error for no client certificate' +( exec 2>&1 + sslclient -p 50028 -v -R -N -h -l ip6-localhost -a "$CAFILE" ::1 50015 \ + sh -c 'sleep 1; echo ok' + echo $? +) | sanitize + +echo '--- sslserver prints error for bad client certificate' +( exec 2>&1 + exec 3< $CADIR/::1.pw + sslclient -p 50029 -v -R -h -l ip6-localhost -a "$CAFILE" -c "$CERTFILE" -k "$KEYFILE" -3 \ + ::1 50015 sh -c 'sleep 1; echo ok' + echo $? +) | sanitize + +echo '--- sslclient uses certificates' +( exec 2>&1 + exec 3< $CADIR/localhost.pw + sslclient -p 50030 -v -s -R -N -h -l ip6-localhost -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 \ + ::1 50015 sh -c 'cat <&6; ./print' + echo $? +) | sanitize + +echo '---> test sslcat to connect to sslserver@5016' +echo '++++' + +echo '--- sslcat works' +{ + sslcat ::1 50013 -N -a "$CAFILE" -N + echo $? +} | sanitize + +echo '--- sslconnect works' +{ + sslconnect ::1 50013 -N -a "$CAFILE" </dev/null + echo $? +} | sanitize + +echo '--- https@ works' +https@ ::1 somefile 50013 -X -a "$CAFILE" +echo $? + + +echo '---> test sslconnect to connect to sslserver@5013' +echo '++++' + + +echo '--- sslclient and sslserver handle larger data' +( exec 2>&1 + exec 3< $CADIR/localhost.pw + { for i in 0 1 2 3 4 5 6 7 8 9 + do + for j in 0 1 2 3 4 5 6 7 8 9 + do + for k in 0 1 2 3 4 5 6 7 8 9 + do + echo "abcdefghijklmnopqrstuvwxyz" + echo "abcdefghijklmnopqrstuvwxyz" + echo "abcdefghijklmnopqrstuvwxyz" + echo "abcdefghijklmnopqrstuvwxyz" + done + done + done + } | sslconnect ::1 50013 -v -s -N \ + -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 > /dev/null + echo $? +) | sanitize + +echo '--- sslserver times out' +( exec 2>&1 + exec 3< $CADIR/localhost.pw + ( exec echo hereur ) | sslconnect ::1 50013 -v -s -N \ + -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 + echo $? +) | sanitize + +( exec 2>&1 + exec 3< $CADIR/localhost.pw + ( sleep 6; exec echo hereur; ) | sslconnect ::1 50013 -v -s -N \ + -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 + echo $? +) | sanitize + +## Kill all sslserver processes + +kill -TERM $pid_50013 +kill -TERM $pid_50014 +kill -TERM $pid_50015 +kill -TERM $pid_50016 +wait $pid_50013 +wait $pid_50014 +wait $pid_50015 +wait $pid_50016 + +echo '---> test sslprint@50021' +echo '++++' + + +sslprint \ +-s -c 1 -Bsslprint -vo -D -e -1 -3 -Xx rules.cdb -Rt5 -hp -l Localserver -b 2 \ +::1 50021 3< $CADIR/::1.pw > log.sslprint 2>&1 & +pid_50021=$! +sleep 2 + +echo '--- sslprint prints usage message without enough arguments' +sslprint 0; echo $? + +echo '--- sslprint prints error message with unknown port name' +sslprint 0 nonexistentport; echo $? + +echo '--- sslprint prints error message with unknown host name' +sslprint nonexistent.local. 016; echo $? + +echo '--- sslprint prints error message with unresolvable host name' +sslprint thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 016; echo $? + +echo '--- sslprint prints error message with non-local host name' +( sslprint 1.2.3.4 16 2>&1 + echo $? +) | sed -e 's/unable to bind to: .*/unable to bind to: .../' + + +echo '--- sslprint prints error message with used port' +sslprint -R -H -l Localserver ::1 50021 echo wrong +echo $? + +echo '--- sslprint sets basic environment variables' +{ sslclient -R -H -T 5 -l Local -a "$CAFILE" -N ::1 50021 sh -c 'cat <&6' + echo $? +} | sanitize + +echo '--- sslprint exits when environment changes' +{ sslclient -R -H -T 5 -l Local -a "$CAFILE" -N ::1 50021 sh -c 'cat <&6' + echo $? +} | sanitize + +echo '--- sslprint does not lose descriptors' +{ sslclient -R -H -T 5 -l Local -a "$CAFILE" -N ::1 50021 sh -c 'cat <&6' \ + 0<&- 2<&- + echo $? +} | sanitize + +sleep 1 +kill -TERM $pid_50021 +wait $pid_50021 + + +echo '--- sslserver -1v prints proper messages' +cat log.50016 log.50015 log.50014 log.50013 log.sslprint | \ +sed -e 's/::*/::x/' \ + -e 's} [0-9]* } x }g' \ + -e 's} ip6-loopback:::1::[0-9]*} ip6-loopback:::1::x}' \ + -e 's} :::1:[0-9]*} :::1:x}' \ + -e 's} cafile x .*/\([^/]*\)} cafile x xxx/\1}' \ + -e 's} ccafile x .*/\([^/]*\)} ccafile x xxx/\1}' \ + -e 's} cadir x .*/\([^/]*\)} cadir x xxx/\1}' \ + -e 's} cert x .*/\([^/]*\)} cert x xxx/\1}' \ + -e 's} key x .*/\([^/]*\)} key x xxx/\1}' \ + -e 's} dhparam x .*} dhparam x xxx}' \ + -e 's} speak TLS: .*} speak TLS: ...}' \ + -e 's} accept TLS: .*} accept TLS: ...}' \ + -e 's} done [0-9]*$} done ...}' \ + -e 's} Localserver:::1:[0-9]*} Localserver:::1:x}' \ + -e 's} ip6-localnet:::::[0-9]*} ip6-localnet:::::x}' \ + -e 's} valid client cert received for pid: .*} valid client cert received for pid: ...}' + diff --git a/src/rts.it b/src/rts.it new file mode 100644 index 0000000..7c0fa0e --- /dev/null +++ b/src/rts.it @@ -0,0 +1,197 @@ +# Umbrella script to provide *SSL environment +# and helper functions + +PATH="`pwd`:$PATH" +CADIR=`pwd | cut -d':' -f1 | sed s/compile/etc/` + +# include the ssl and crypto libs by means of LD_LIBRARY_PATH +#export LD_LIBRARY_PATH="/home/ucspi/_SSL/libressl-3.7.2/ssl/.libs:/home/ucspi/_SSL/libressl-3.7.2/crypto/.libs" +export LD_LIBRARY_PATH="/home/ucspi/_SSL/openssl-3.2.0-alpha2" + +rm -rf rts-tmp +mkdir rts-tmp +cd rts-tmp + +CAFILE="$CADIR/rootCA_cert.pem" +if [ ! -f $CAFILE ] +then + echo "$CAFILE does no exist!" + exit 1 +fi +CERTFILE="$CADIR/::1_cert.pem" +if [ ! -f $CERTFILE ] +then + echo "$CERTFILE does no exist!" + exit 1 +fi +CHAINFILE="$CADIR/chain6.pem" +if [ ! -f $CHAINFILE ] +then + echo "$CHAINFILE does no exist!" + exit 1 +fi +KEYFILE="$CADIR/::1_key.pem" +if [ ! -f $KEYFILE ] +then + echo "$KEYFILE does no exist!" + exit 1 +fi +CCAFILE="$CADIR/rootCA_cert.pem" +if [ ! -f $CCAFILE ] +then + echo "$CCAFILE does no exist!" + exit 1 +fi +CCERTFILE="$CADIR/localhost_cert.pem" +if [ ! -f $CCERTFILE ] +then + echo "$CCERTFILE does no exist!" + exit 1 +fi +CKEYFILE="$CADIR/localhost_key.pem" +if [ ! -f $CKEYFILE ] +then + echo "$CKEYFILE does no exist!" + exit 1 +fi +DHFILE="$CADIR/dh2048.pem" +if [ ! -f $DHFILE ] +then + echo "$DHFILE does no exist!" + exit 1 +fi + +export CADIR CAFILE CCAFILE CERTFILE CHAINFILE KEYFILE CCERTFILE CKEYFILE DHFILE + +# Create ./print file + +echo '#!/bin/sh +# trap "" 13 + echo "" + echo PROTO="$PROTO" + echo SSLLOCALHOST="${SSLLOCALHOST-unset}" + echo SSLLOCALIP="${SSLLOCALIP-unset}" + echo SSLLOCALPORT="${SSLLOCALPORT-unset}" + echo SSLREMOTEHOST="${SSLREMOTEHOST-unset}" + echo SSLREMOTEIP="${SSLREMOTEIP-unset}" + echo SSLREMOTEPORT="${SSLREMOTEPORT-unset}" + echo SSLREMOTEINFO="${SSLREMOTEINFO-unset}" + + echo TCPLOCALHOST="${TCPLOCALHOST-unset}" + echo TCPLOCALIP="${TCPLOCALIP-unset}" + echo TCPLOCALPORT="${TCPLOCALPORT-unset}" + + echo TCPREMOTEHOST="${TCPREMOTEHOST-unset}" + echo TCPREMOTEIP="${TCPREMOTEIP-unset}" + echo TCPREMOTEPORT="${TCPREMOTEPORT-unset}" + echo TCPREMOTEINFO="${TCPREMOTEINFO-unset}" + + echo TCP6REMOTEHOST="${TCP6REMOTEHOST-unset}" + echo TCP6REMOTEIP="${TCP6REMOTEIP-unset}" + echo TCP6REMOTEPORT="${TCP6REMOTEPORT-unset}" + + echo SSL_PROTOCOL="${SSL_PROTOCOL-unset}" + echo SSL_SESSION_ID="${SSL_SESSION_ID-unset}" + echo SSL_CIPHER="${SSL_CIPHER-unset}" + echo SSL_CIPHER_EXPORT="${SSL_CIPHER_EXPORT-unset}" + echo SSL_CIPHER_USEKEYSIZE="${SSL_CIPHER_USEKEYSIZE-unset}" + echo SSL_CIPHER_ALGKEYSIZE="${SSL_CIPHER_ALGKEYSIZE-unset}" + echo SSL_VERSION_INTERFACE="${SSL_VERSION_INTERFACE-unset}" + echo SSL_VERSION_LIBRARY="${SSL_VERSION_LIBRARY-unset}" + + echo SSL_SERVER_M_VERSION="${SSL_SERVER_M_VERSION-unset}" + echo SSL_SERVER_M_SERIAL="${SSL_SERVER_M_SERIAL-unset}" + echo SSL_SERVER_S_DN="${SSL_SERVER_S_DN-unset}" + echo SSL_SERVER_S_DN_C="${SSL_SERVER_S_DN_C-unset}" + echo SSL_SERVER_S_DN_ST="${SSL_SERVER_S_DN_ST-unset}" + echo SSL_SERVER_S_DN_L="${SSL_SERVER_S_DN_L-unset}" + echo SSL_SERVER_S_DN_O="${SSL_SERVER_S_DN_O-unset}" + echo SSL_SERVER_S_DN_OU="${SSL_SERVER_S_DN_OU-unset}" + echo SSL_SERVER_S_DN_CN="${SSL_SERVER_S_DN_CN-unset}" + echo SSL_SERVER_S_DN_T="${SSL_SERVER_S_DN_T-unset}" + echo SSL_SERVER_S_DN_I="${SSL_SERVER_S_DN_I-unset}" + echo SSL_SERVER_S_DN_G="${SSL_SERVER_S_DN_G-unset}" + echo SSL_SERVER_S_DN_S="${SSL_SERVER_S_DN_S-unset}" + echo SSL_SERVER_S_DN_D="${SSL_SERVER_S_DN_D-unset}" + echo SSL_SERVER_S_DN_UID="${SSL_SERVER_S_DN_UID-unset}" + echo SSL_SERVER_S_DN_Email="${SSL_SERVER_S_DN_Email-unset}" + echo SSL_SERVER_I_DN="${SSL_SERVER_I_DN-unset}" + echo SSL_SERVER_I_DN_C="${SSL_SERVER_I_DN_C-unset}" + echo SSL_SERVER_I_DN_ST="${SSL_SERVER_I_DN_ST-unset}" + echo SSL_SERVER_I_DN_L="${SSL_SERVER_I_DN_L-unset}" + echo SSL_SERVER_I_DN_O="${SSL_SERVER_I_DN_O-unset}" + echo SSL_SERVER_I_DN_OU="${SSL_SERVER_I_DN_OU-unset}" + echo SSL_SERVER_I_DN_CN="${SSL_SERVER_I_DN_CN-unset}" + echo SSL_SERVER_I_DN_T="${SSL_SERVER_I_DN_T-unset}" + echo SSL_SERVER_I_DN_I="${SSL_SERVER_I_DN_I-unset}" + echo SSL_SERVER_I_DN_G="${SSL_SERVER_I_DN_G-unset}" + echo SSL_SERVER_I_DN_S="${SSL_SERVER_I_DN_S-unset}" + echo SSL_SERVER_I_DN_D="${SSL_SERVER_I_DN_D-unset}" + echo SSL_SERVER_I_DN_UID="${SSL_SERVER_I_DN_UID-unset}" + echo SSL_SERVER_I_DN_Email="${SSL_SERVER_I_DN_Email-unset}" + echo SSL_SERVER_V_START="${SSL_SERVER_V_START-unset}" + echo SSL_SERVER_V_END="${SSL_SERVER_V_END-unset}" + echo SSL_SERVER_A_SIG="${SSL_SERVER_A_SIG-unset}" + echo SSL_SERVER_A_KEY="${SSL_SERVER_A_KEY-unset}" + echo SSL_SERVER_CERT="${SSL_SERVER_CERT-unset}" + + echo SSL_CLIENT_M_VERSION="${SSL_CLIENT_M_VERSION-unset}" + echo SSL_CLIENT_M_SERIAL="${SSL_CLIENT_M_SERIAL-unset}" + echo SSL_CLIENT_S_DN="${SSL_CLIENT_S_DN-unset}" + echo SSL_CLIENT_S_DN_C="${SSL_CLIENT_S_DN_C-unset}" + echo SSL_CLIENT_S_DN_ST="${SSL_CLIENT_S_DN_ST-unset}" + echo SSL_CLIENT_S_DN_L="${SSL_CLIENT_S_DN_L-unset}" + echo SSL_CLIENT_S_DN_O="${SSL_CLIENT_S_DN_O-unset}" + echo SSL_CLIENT_S_DN_OU="${SSL_CLIENT_S_DN_OU-unset}" + echo SSL_CLIENT_S_DN_CN="${SSL_CLIENT_S_DN_CN-unset}" + echo SSL_CLIENT_S_DN_T="${SSL_CLIENT_S_DN_T-unset}" + echo SSL_CLIENT_S_DN_I="${SSL_CLIENT_S_DN_I-unset}" + echo SSL_CLIENT_S_DN_G="${SSL_CLIENT_S_DN_G-unset}" + echo SSL_CLIENT_S_DN_S="${SSL_CLIENT_S_DN_S-unset}" + echo SSL_CLIENT_S_DN_D="${SSL_CLIENT_S_DN_D-unset}" + echo SSL_CLIENT_S_DN_UID="${SSL_CLIENT_S_DN_UID-unset}" + echo SSL_CLIENT_S_DN_Email="${SSL_CLIENT_S_DN_Email-unset}" + echo SSL_CLIENT_I_DN="${SSL_CLIENT_I_DN-unset}" + echo SSL_CLIENT_I_DN_C="${SSL_CLIENT_I_DN_C-unset}" + echo SSL_CLIENT_I_DN_ST="${SSL_CLIENT_I_DN_ST-unset}" + echo SSL_CLIENT_I_DN_L="${SSL_CLIENT_I_DN_L-unset}" + echo SSL_CLIENT_I_DN_O="${SSL_CLIENT_I_DN_O-unset}" + echo SSL_CLIENT_I_DN_OU="${SSL_CLIENT_I_DN_OU-unset}" + echo SSL_CLIENT_I_DN_CN="${SSL_CLIENT_I_DN_CN-unset}" + echo SSL_CLIENT_I_DN_T="${SSL_CLIENT_I_DN_T-unset}" + echo SSL_CLIENT_I_DN_I="${SSL_CLIENT_I_DN_I-unset}" + echo SSL_CLIENT_I_DN_G="${SSL_CLIENT_I_DN_G-unset}" + echo SSL_CLIENT_I_DN_S="${SSL_CLIENT_I_DN_S-unset}" + echo SSL_CLIENT_I_DN_D="${SSL_CLIENT_I_DN_D-unset}" + echo SSL_CLIENT_I_DN_UID="${SSL_CLIENT_I_DN_UID-unset}" + echo SSL_CLIENT_I_DN_Email="${SSL_CLIENT_I_DN_Email-unset}" + echo SSL_CLIENT_V_START="${SSL_CLIENT_V_START-unset}" + echo SSL_CLIENT_V_END="${SSL_CLIENT_V_END-unset}" + echo SSL_CLIENT_A_SIG="${SSL_CLIENT_A_SIG-unset}" + echo SSL_CLIENT_A_KEY="${SSL_CLIENT_A_KEY-unset}" + echo SSL_CLIENT_CERT="${SSL_CLIENT_CERT-unset}" + echo SSL_CLIENT_CERT_CHAIN_0="${SSL_CLIENT_CERT_CHAIN_0-unset}" + echo SSL_CLIENT_CERT_CHAIN_1="${SSL_CLIENT_CERT_CHAIN_1-unset}" +' > print +chmod 755 print + + +# Sanitze output + +sanitize() { + sed -e 's/^SSL_SESSION_ID=.*/SSL_SESSION_ID=.../' \ + -e 's/^SSLREMOTEPORT=.*/SSLREMOTEPORT=.../' \ + -e 's/^SSLLOCALPORT=.*/SSLLOCALPORT=.../' \ + -e 's/^TCPREMOTEPORT=.*/TCPREMOTEPORT=.../' \ + -e 's/^TCP6REMOTEPORT=.*/TCP6REMOTEPORT=.../' \ + -e 's/^TCPLOCALPORT=.*/TCPLOCALPORT=.../' \ + -e 's/^SSL_VERSION_LIBRARY=.*/SSL_VERSION_LIBRARY=.../' \ + -e 's/^SSL_CIPHER_USEKEYSIZE=.*/SSL_CIPHER_USEKEYSIZE=.../' \ + -e 's/^SSL_CIPHER_ALGKEYSIZE=.*/SSL_CIPHER_ALGKEYSIZE=.../' \ + -e 's/^SSL_CIPHER=.*/SSL_CIPHER=.../' \ + -e 's/^SSL_PROTOCOL=TLSv1.*/SSL_PROTOCOL=TLSv1.../' \ + -e 's/Localserver:::1:[0-9]*/Localserver:::1:... /' \ + -e 's/ip6-localnet:::::[0-9]*/ip6-localnet:::::.../' +} + +# done diff --git a/src/rts.sslperl b/src/rts.sslperl new file mode 100644 index 0000000..3d1e560 --- /dev/null +++ b/src/rts.sslperl @@ -0,0 +1,157 @@ +# Assumptions: +# available TCP ports on 127.0.0.1: 50022 + +echo 'package Embedded::test; +my $n = 0; +$| = 1; +sub server (@) { + ++$n; + print STDERR "log: Hello, World! ($n): @_\n"; + print "Hello, World! ($n): @_\n"; + + $n > 1 and exit(0); +} +1; +' > hello.pm + +sanitize() { + sed -e 's/^SSL_SESSION_ID=.*/SSL_SESSION_ID=.../' \ + -e 's/^SSLREMOTEPORT=.*/SSLREMOTEPORT=.../' \ + -e 's/^SSLLOCALPORT=.*/SSLLOCALPORT=.../' \ + -e 's/^TCPREMOTEPORT=.*/TCPREMOTEPORT=.../' \ + -e 's/^TCP6REMOTEPORT=.*/TCP6REMOTEPORT=.../' \ + -e 's/^TCPLOCALPORT=.*/TCPLOCALPORT=.../' \ + -e 's/^SSL_VERSION_LIBRARY=.*/SSL_VERSION_LIBRARY=.../' \ + -e 's/^SSL_CIPHER_USEKEYSIZE=.*/SSL_CIPHER_USEKEYSIZE=.../' \ + -e 's/^SSL_CIPHER_ALGKEYSIZE=.*/SSL_CIPHER_ALGKEYSIZE=.../' \ + -e 's/^SSL_CIPHER=.*/SSL_CIPHER=.../' \ + -e 's/^SSL_PROTOCOL=TLSv1.*/SSL_PROTOCOL=TLSv1.../' +} + +sslperl -w 2 \ +-s -c 1 -Bsslperl -vo -D -1 -3 -Xx rules.cdb -Rt5 -hp -l Localserver -b 2 \ +-a -A \ +127.0.0.1 50022 hello.pm 'Embedded::test::server' here you are \ +3< $CADIR/127.0.0.1.pw >log.50022 2>&1 & +pid_50022=$! +sleep 2 + +echo '--- sslperl works' +{ sslclient -R -N -H -T 10 -l Local -a "$CAFILE" -4 0 50022 sh -c 'cat <&6' + echo $? +} | sanitize +{ sslclient -R -N -H -T 10 -l Local -a "$CAFILE" -4 0 50022 sh -c 'cat <&6' + echo $? +} | sanitize +{ sslclient -R -N -H -T 10 -l Local -a "$CAFILE" -4 0 50022 sh -c 'cat <&6' + echo $? +} | sanitize +{ sslclient -R -N -H -T 10 -l Local -X -4 0 50022 sh -c 'cat <&6' + echo $? +} | sanitize + +echo '--- sslperl prints usage message without enough arguments' +sslperl 0; echo $? + +echo '--- sslperl prints error message with unknown port name' +sslperl 0 nonexistentport echo wrong; echo $? + +echo '--- sslperl prints error message with unknown host name' +sslperl nonexistent.local. 016 echo wrong; echo $? + +echo '--- sslperl prints error message with unresolvable host name' +sslperl thislabelistoolongbecausednshasalimitof63charactersinasinglelabel. 50022 echo wrong; echo $? + +echo '--- sslperl prints error message with non-local host name' +( sslperl 1.2.3.4 016 echo wrong 2>&1 + echo $? +) | sed -e 's/unable to bind: .*$/unable to bind: .../' + +kill -TERM $pid_50022 +wait $pid_50022 + +echo '--- sslperl preserves environment' +echo 'package Embedded::test; +my $n = 0; +$| = 1; +sub server () { + print STDERR "log: NOW=$ENV{NOW}\n"; + print STDERR "log: changed environment\n"; + print " changed environment\n"; + $ENV{'HERE'} = 'NOW'; +} +1; +' > hello.pm + +sslperl -w 2 \ +-s -c 1 -Bsslperl -vo -D -1 -3 -Xx rules.cdb -Rt5 -hp -l Localserver -b 2 \ +-a -A \ +127.0.0.1 50022 hello.pm 'Embedded::test::server' here you are \ +3< $CADIR/127.0.0.1.pw >>log.50022 2>&1 & +pid_50022=$! +sleep 2 + +{ sslclient -R -N -H -T 10 -l Local -a "$CAFILE" -4 0 50022 sh -c 'cat <&6' + echo $? +} | sanitize + +kill -TERM $pid_50022 +wait $pid_50022 + +echo '--- sslperl handles larger requests' +echo 'package Embedded::test; +my $n = 0; +$| = 1; +sub server (@) { + print @_; + while(<>) { + print $_; + } +} +1; +' > echo.pm + +sslperl -w 2 \ +-s -c 1 -Bsslperl -vo -D -1 -3 -Xx rules.cdb -Rt5 -hp -l Localserver -b 2 \ +-a -A \ +127.0.0.1 50022 echo.pm 'Embedded::test::server' here you are \ +3< $CADIR/127.0.0.1.pw >>log.50022 2>&1 & +pid_50022=$! +sleep 2 + +( exec 2>&1 + exec 3< $CADIR/localhost.pw + { for i in 0 1 2 3 4 5 6 7 8 9 + do + for j in 0 1 2 3 4 5 6 7 8 9 + do + for k in 0 1 2 3 4 5 6 7 8 9 + do + echo "abcdefghijklmnopqrstuvwxyz" + echo "abcdefghijklmnopqrstuvwxyz" + echo "abcdefghijklmnopqrstuvwxyz" + echo "abcdefghijklmnopqrstuvwxyz" + done + done + done + } | sslconnect 127.0.0.1 50022 -v -s \ + -a "$CAFILE" -c "$CCERTFILE" -k "$CKEYFILE" -3 >/dev/null + echo $? +) | sanitize + +kill -TERM $pid_50022 +wait $pid_50022 + +echo '--- sslserver -1v prints proper messages' +cat log.50022 | \ +sed -e 's/::.*/::x/' -e 's/ [0-9]* / x /' \ + -e 's} cafile x .*/\([^/]*\)} cafile x xxx/\1}' \ + -e 's} ccafile x .*/\([^/]*\)} ccafile x xxx/\1}' \ + -e 's} cadir x .*/\([^/]*\)} cadir x xxx/\1}' \ + -e 's} cert x .*/\([^/]*\)} cert x xxx/\1}' \ + -e 's} key x .*/\([^/]*\)} key x xxx/\1}' \ + -e 's/ dhparam x .*/ dhparam x xxx/' \ + -e 's/ ecdhparam x .*/ ecdhparam x xxx/' \ + -e 's/ speak TLS: .*/ speak TLS: .../' \ + -e 's/ accept TLS: .*/ accept TLS: .../' \ + -e 's/ done [0-9]*$/ done .../' diff --git a/src/rules.c b/src/rules.c new file mode 100644 index 0000000..279ffae --- /dev/null +++ b/src/rules.c @@ -0,0 +1,141 @@ +#include "alloc.h" +#include "stralloc.h" +#include "open.h" +#include "cdbread.h" +#include "byte.h" +#include "fmt.h" +#include "getln.h" +#include "ip.h" +#include "str.h" +#include "ip_bit.h" +#include "rules.h" + +stralloc rules_name = {0}; +stralloc ipstring = {0}; + +static struct cdb c; + +static int dorule(void (*callback)(char *,unsigned int)) { + char *data; + unsigned int datalen; + + switch (cdb_find(&c,rules_name.s,rules_name.len)) { + case -1: return -1; + case 0: return 0; + } + + datalen = cdb_datalen(&c); + data = alloc(datalen); + if (!data) return -1; + if (cdb_read(&c,data,datalen,cdb_datapos(&c)) == -1) { + alloc_free(data); + return -1; + } + + callback(data, datalen); + alloc_free(data); + return 1; +} + +static int doit(void (*callback)(char *,unsigned int),char *ip,char *host,char *info) { + int p; + int r; + int ipv6 = str_len(ip) - byte_chr(ip,str_len(ip),':'); + + if (info) { /* 1. info@ip */ + if (!stralloc_copys(&rules_name,info)) return -1; + if (!stralloc_cats(&rules_name,"@")) return -1; + if (ipv6) { + if (!ip6_fmt_str(&ipstring,ip)) + if (!stralloc_catb(&rules_name,ipstring.s,ipstring.len)) return -1; + } + else + if (!stralloc_cats(&rules_name,ip)) return -1; + r = dorule(callback); + if (r) return r; + + if (host) { /* 2. info@=host */ + if (!stralloc_copys(&rules_name,info)) return -1; + if (!stralloc_cats(&rules_name,"@=")) return -1; + if (!stralloc_cats(&rules_name,host)) return -1; + r = dorule(callback); + if (r) return r; + } + } + + if (ipv6) { /* 3. IPv6/IPv4 */ + if (!ip6_fmt_str(&ipstring,ip)) { + if (!stralloc_copyb(&rules_name,ipstring.s,ipstring.len)) return -1; + r = dorule(callback); + if (r) return r; + } + } else { + if (!stralloc_copys(&rules_name,ip)) return -1; + r = dorule(callback); + if (r) return r; + } + + if (host) { /* 4. =host */ + if (!stralloc_copys(&rules_name,"=")) return -1; + if (!stralloc_cats(&rules_name,host)) return -1; + r = dorule(callback); + if (r) return r; + } + + if (!ipv6) { /* 5. IPv4 class-based */ + if (!stralloc_copys(&rules_name,ip)) return -1; + while (rules_name.len > 0) { + if (ip[rules_name.len - 1] == '.') { + r = dorule(callback); + if (r) return r; + } + --rules_name.len; + } + } + + if (ipv6) { /* 6. IPv6/IPv4 CIDR */ + if (!ip6_bitstring(&ipstring,ip,128)) { + for (p = 129; p > 1; p--) { + if (!stralloc_copys(&rules_name,"^")) return -1; + if (!stralloc_catb(&rules_name,ipstring.s,p)) return -1; + r = dorule(callback); + if (r) return r; + } + } + } else { + if (!ip4_bitstring(&ipstring,ip,32)) { + for (p = 33; p > 1; p--) { + if (!stralloc_copys(&rules_name,"_")) return -1; + if (!stralloc_catb(&rules_name,ipstring.s,p)) return -1; + r = dorule(callback); + if (r) return r; + } + } + } + + if (host) { /* 7. =host. */ + while (*host) { + if (*host == '.') { + if (!stralloc_copys(&rules_name,"=")) return -1; + if (!stralloc_cats(&rules_name,host)) return -1; + r = dorule(callback); + if (r) return r; + } + ++host; + } + if (!stralloc_copys(&rules_name,"=")) return -1; /* 8. = rule */ + r = dorule(callback); + if (r) return r; + } + + rules_name.len = 0; + return dorule(callback); +} + +int rules(void (*callback)(char *,unsigned int),int fd,char *ip,char *host,char *info) { + int r; + cdb_init(&c,fd); + r = doit(callback,ip,host,info); + cdb_free(&c); + return r; +} diff --git a/src/rules.h b/src/rules.h new file mode 100644 index 0000000..15d9b90 --- /dev/null +++ b/src/rules.h @@ -0,0 +1,9 @@ +#ifndef RULES_H +#define RULES_H + +#include "stralloc.h" + +extern stralloc rules_name; +extern int rules(void (*)(char *,unsigned int),int,char *,char *,char *); + +#endif diff --git a/src/select.h1 b/src/select.h1 new file mode 100644 index 0000000..68e971f --- /dev/null +++ b/src/select.h1 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef SELECT_H +#define SELECT_H + +/* sysdep: -sysselect */ + +#include <sys/types.h> +#include <sys/time.h> +extern int select(); + +#endif diff --git a/src/select.h2 b/src/select.h2 new file mode 100644 index 0000000..4bd4fcf --- /dev/null +++ b/src/select.h2 @@ -0,0 +1,13 @@ +/* Public domain. */ + +#ifndef SELECT_H +#define SELECT_H + +/* sysdep: +sysselect */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/select.h> +extern int select(); + +#endif diff --git a/src/ssl_ca.c b/src/ssl_ca.c new file mode 100644 index 0000000..a6ab523 --- /dev/null +++ b/src/ssl_ca.c @@ -0,0 +1,11 @@ +#include "ucspissl.h" + +int ssl_ca(SSL_CTX *ctx,const char *certfile,const char *certdir,int d) +{ + if (!SSL_CTX_load_verify_locations(ctx,certfile,certdir)) return 0; + + SSL_CTX_set_verify_depth(ctx,d); + + return 1; +} + diff --git a/src/ssl_cca.c b/src/ssl_cca.c new file mode 100644 index 0000000..112a9f1 --- /dev/null +++ b/src/ssl_cca.c @@ -0,0 +1,18 @@ +#include "ucspissl.h" + +int ssl_cca(SSL_CTX *ctx,const char *certfile) +{ + STACK_OF(X509_NAME) *x; + + if (!certfile) return 1; + + x = SSL_load_client_CA_file(certfile); + if (!x) return 0; + + SSL_CTX_set_client_CA_list(ctx,x); + + SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0); + + return 1; +} + diff --git a/src/ssl_certkey.c b/src/ssl_certkey.c new file mode 100644 index 0000000..8292cbe --- /dev/null +++ b/src/ssl_certkey.c @@ -0,0 +1,19 @@ +#include "ucspissl.h" + +int ssl_certkey(SSL_CTX *ctx,const char *certfile,const char *keyfile,pem_password_cb *passwd_cb) +{ + if (!certfile) return 0; + + if (SSL_CTX_use_certificate_chain_file(ctx,certfile) != 1) + return -1; + + if (!keyfile) keyfile = certfile; + SSL_CTX_set_default_passwd_cb(ctx,passwd_cb); + if (SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM) != 1) + return -2; + + if (SSL_CTX_check_private_key(ctx) != 1) + return -3; + + return 0; +} diff --git a/src/ssl_chainfile.c b/src/ssl_chainfile.c new file mode 100644 index 0000000..9e353c2 --- /dev/null +++ b/src/ssl_chainfile.c @@ -0,0 +1,24 @@ +/** + @file ssl_certchainfile.c + @author feh + @brief Enables Certificate chain file presentation for sslserver +*/ +#include "ucspissl.h" + +int ssl_chainfile(SSL_CTX *ctx,const char *certchainfile,const char *keyfile,pem_password_cb *passwd_cb) +{ + if (!certchainfile) return 0; + if (!keyfile) return 0; + + if (SSL_CTX_use_certificate_chain_file(ctx,certchainfile) <= 0) + return -1; + + SSL_CTX_set_default_passwd_cb(ctx,passwd_cb); + if (SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM) != 1) + return -2; + + if (SSL_CTX_check_private_key(ctx) != 1) + return -3; + + return 0; +} diff --git a/src/ssl_ciphers.c b/src/ssl_ciphers.c new file mode 100644 index 0000000..168c2bb --- /dev/null +++ b/src/ssl_ciphers.c @@ -0,0 +1,21 @@ +#include "ucspissl.h" + +int ssl_ciphers(SSL_CTX *ctx,const char *ciphers) { + int r = 0; // no cipher selected + + if (!ciphers) return -1; + +/* TLS <= 1.2 SSL_CTX_set_cipher_list() + TLS = 1.3 SSL_CTX_set_ciphersuites() [only OpenSSL here] + + see: https://community.openvpn.net/openvpn/ticket/1159 +*/ + +#if (OPENSSL_VERSION_NUMBER > 0x10101000L && !LIBRESSL_VERSION_NUMBER) // 0xmnnffppsL + if ((r = SSL_CTX_set_ciphersuites(ctx,ciphers)) == 0) +#endif + r = SSL_CTX_set_cipher_list(ctx,ciphers); // TLS < 1.3 and fallback + + return r; +} + diff --git a/src/ssl_context.c b/src/ssl_context.c new file mode 100644 index 0000000..03ce58a --- /dev/null +++ b/src/ssl_context.c @@ -0,0 +1,34 @@ +#include "ucspissl.h" + +SSL_CTX *ssl_context(const SSL_METHOD *m) +{ + SSL_CTX *ctx; + + SSL_library_init(); + ctx = SSL_CTX_new(m); +#ifdef SSL_TWEAKING + SSL_CTX_set_options(ctx,SSL_OP_SINGLE_DH_USE|SSL_OP_NO_COMPRESSION|SSL_OP_CIPHER_SERVER_PREFERENCE); +#else + SSL_CTX_set_options(ctx,SSL_OP_SINGLE_DH_USE); +#endif +#ifdef SSLv2_DISABLE + SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2); +#endif +#ifdef SSLv3_DISABLE + SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv3); +#endif +#ifdef TLSv1_DISABLE + SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1); +#endif +#ifdef TLSv1_1_DISABLE + SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_1); +#endif +#ifdef TLSv1_2_DISABLE + SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_2); +#endif +#ifdef TLSv1_3_DISABLE + SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_3); +#endif + return ctx; +} + diff --git a/src/ssl_env.c b/src/ssl_env.c new file mode 100644 index 0000000..4ddff35 --- /dev/null +++ b/src/ssl_env.c @@ -0,0 +1,435 @@ +#include <unistd.h> +#include <string.h> +#include "fmt.h" +#include "pathexec.h" +#include "ucspissl.h" +#include "stralloc.h" +#include "str.h" + +static char strnum[FMT_ULONG]; +static stralloc ctemp = {0}; +static stralloc *envsa = 0; +static stralloc btemp = {0}; +static stralloc etemp = {0}; + +#define set_env_id(n,e,v) \ +if (!set_env_name_entry((n),(e),(v))) return 0 + +static int env_val(const char *env,const void *val,int len) { + const char *v = val; + if (envsa) { + if (!stralloc_cats(envsa,env)) return 0; + if (!stralloc_catb(envsa,"=",1)) return 0; + if (!stralloc_catb(envsa,v,len)) return 0; + if (!stralloc_0(envsa)) return 0; + return 1; + } + if (!stralloc_copyb(&etemp,v,len)) return 0; + if (!stralloc_0(&etemp)) return 0; + return pathexec_env(env,etemp.s); +} + +static int env_str(const char *env,const char *val) { + if (envsa) { + return env_val(env,val,str_len(val)); + if (!stralloc_cats(envsa,env)) return 0; + if (!stralloc_catb(envsa,"=",1)) return 0; + if (!stralloc_catb(envsa,val,str_len(val) + 1)) return 0; + return 1; + } + return pathexec_env(env,val); +} + +static int set_env_name_entry(X509_NAME *xname,const char *env,int nid) { + X509_NAME_ENTRY *xne; + int m; + int n; + + if (!env) return 1; +#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L)) + for (m = 0; m < sk_X509_NAME_ENTRY_num(xname->entries); m++) { + xne = sk_X509_NAME_ENTRY_value(xname->entries,m); + n = OBJ_obj2nid(xne->object); + if (n == nid) + if (!env_val(env,xne->value->data,xne->value->length)) return 0; +#else + for (m = 0; m < X509_NAME_entry_count(xname); m++) { + xne = X509_NAME_get_entry(xname,m); + n = OBJ_obj2nid(X509_NAME_ENTRY_get_object(xne)); + if (n == nid) + if (!env_val(env,X509_NAME_ENTRY_get_data(xne)->data,X509_NAME_ENTRY_get_data(xne)->length)) return 0; +#endif + } + + return 1; +} + +int ssl_session_vars(SSL *ssl) { + unsigned const char *x; + SSL_SESSION *session; + unsigned int n = 0; + int m; + const SSL_CIPHER *cipher; + unsigned char u; + unsigned char c; + + if (!env_str("SSL_PROTOCOL",SSL_get_version(ssl))) + return 0; + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) // 0xmnnffppsL + session = SSL_get_session(ssl); + x = session->session_id; + n = session->session_id_length; +#else + session = SSL_get1_session(ssl); + x = SSL_SESSION_get_id(session,&n); +#endif + + if (!stralloc_ready(&btemp,2 * n)) return 0; + btemp.len = 2 * n; + while (n--) { + u = x[n]; + c = '0' + (u & 15); + if (c > '0' + 9) c += 'a' - '0' - 10; + btemp.s[2 * n + 1] = c; + u >>= 4; + c = '0' + (u & 15); + if (c > '0' + 9) c += 'a' - '0' - 10; + btemp.s[2 * n] = c; + } + if (!env_val("SSL_SESSION_ID",btemp.s,btemp.len)) return 0; + + if (!env_str("SSL_CIPHER",SSL_get_cipher_name(ssl))) return 0; + + cipher = SSL_get_current_cipher(ssl); + if (!cipher) return 0; + n = SSL_CIPHER_get_bits(cipher,&m); + if (!env_str("SSL_CIPHER_EXPORT",n < 56 ? "true" : "false")) return 0; + if (!env_val("SSL_CIPHER_USEKEYSIZE",strnum,fmt_ulong(strnum,n))) return 0; + if (!env_val("SSL_CIPHER_ALGKEYSIZE",strnum,fmt_ulong(strnum,m))) return 0; + + if (!env_str("SSL_VERSION_INTERFACE","ucspi-ssl")) return 0; + if (!env_str("SSL_VERSION_LIBRARY",OPENSSL_VERSION_TEXT)) return 0; + + return 1; +} + +static int ssl_client_bio_vars(X509 *cert,STACK_OF(X509) *chain,BIO *bio) { + ASN1_STRING *astring; + int n; + int m; + + astring = X509_get_notBefore(cert); + if (!ASN1_UTCTIME_print(bio,astring)) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val("SSL_CLIENT_V_START",btemp.s,btemp.len)) return 0; + + astring = X509_get_notAfter(cert); + if (!ASN1_UTCTIME_print(bio,astring)) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val("SSL_CLIENT_V_END",btemp.s,btemp.len)) return 0; + + if (!PEM_write_bio_X509(bio,cert)) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val("SSL_CLIENT_CERT",btemp.s,btemp.len)) return 0; + + if (chain) { + for (m = 0; m < sk_X509_num(chain); m++) { + if (!stralloc_copys(&ctemp,"SSL_CLIENT_CERT_CHAIN_")) return 0; + if (!stralloc_catb(&ctemp,strnum,fmt_ulong(strnum,m))) return 0; + if (!stralloc_0(&ctemp)) return 0; + + if (m < sk_X509_num(chain)) { + if (!PEM_write_bio_X509(bio,sk_X509_value(chain,m))) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val(ctemp.s,btemp.s,btemp.len)) return 0; + } + } + } + + return 1; +} + +static int ssl_client_vars(X509 *cert,STACK_OF(X509) *chain) { + X509_NAME *xname; + X509_PUBKEY *pubkey; + const X509_ALGOR *sigalg; + const ASN1_OBJECT *calgoid; + ASN1_OBJECT *algoid; + BIGNUM *bn; + BIO *bio; + char *x = 0; + int n; + + if (!cert) return 1; + + if (!env_val("SSL_CLIENT_M_VERSION",strnum,fmt_ulong(strnum,X509_get_version(cert) + 1))) + return 0; + + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), 0); + x = BN_bn2dec(bn); + BN_free(bn); + if (!env_val("SSL_CLIENT_M_SERIAL",x,strlen(x))) + return 0; + OPENSSL_free(x); + + xname = X509_get_subject_name(cert); + x = X509_NAME_oneline(xname,0,0); + n = env_str("SSL_CLIENT_S_DN",x); + free(x); + if (!n) return 0; + + set_env_id(xname,"SSL_CLIENT_S_DN_C",NID_countryName); + set_env_id(xname,"SSL_CLIENT_S_DN_ST",NID_stateOrProvinceName); + set_env_id(xname,"SSL_CLIENT_S_DN_L",NID_localityName); + set_env_id(xname,"SSL_CLIENT_S_DN_O",NID_organizationName); + set_env_id(xname,"SSL_CLIENT_S_DN_OU",NID_organizationalUnitName); + set_env_id(xname,"SSL_CLIENT_S_DN_CN",NID_commonName); + set_env_id(xname,"SSL_CLIENT_S_DN_T",NID_title); + set_env_id(xname,"SSL_CLIENT_S_DN_I",NID_initials); + set_env_id(xname,"SSL_CLIENT_S_DN_G",NID_givenName); + set_env_id(xname,"SSL_CLIENT_S_DN_S",NID_surname); + set_env_id(xname,"SSL_CLIENT_S_DN_D",NID_description); + set_env_id(xname,"SSL_CLIENT_S_DN_UID",NID_x500UniqueIdentifier); + set_env_id(xname,"SSL_CLIENT_S_DN_Email",NID_pkcs9_emailAddress); + + xname = X509_get_issuer_name(cert); + x = X509_NAME_oneline(xname,0,0); + n = env_str("SSL_CLIENT_I_DN",x); + free(x); + if (!n) return 0; + + set_env_id(xname,"SSL_CLIENT_I_DN_C",NID_countryName); + set_env_id(xname,"SSL_CLIENT_I_DN_ST",NID_stateOrProvinceName); + set_env_id(xname,"SSL_CLIENT_I_DN_L",NID_localityName); + set_env_id(xname,"SSL_CLIENT_I_DN_O",NID_organizationName); + set_env_id(xname,"SSL_CLIENT_I_DN_OU",NID_organizationalUnitName); + set_env_id(xname,"SSL_CLIENT_I_DN_CN",NID_commonName); + set_env_id(xname,"SSL_CLIENT_I_DN_T",NID_title); + set_env_id(xname,"SSL_CLIENT_I_DN_I",NID_initials); + set_env_id(xname,"SSL_CLIENT_I_DN_G",NID_givenName); + set_env_id(xname,"SSL_CLIENT_I_DN_S",NID_surname); + set_env_id(xname,"SSL_CLIENT_I_DN_D",NID_description); + set_env_id(xname,"SSL_CLIENT_I_DN_UID",NID_x500UniqueIdentifier); + set_env_id(xname,"SSL_CLIENT_I_DN_Email",NID_pkcs9_emailAddress); + +/* Signature Algorithm for PubKey */ +#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L)) + n = OBJ_obj2nid(cert->cert_info->signature->algorithm); +#else + sigalg = X509_get0_tbs_sigalg(cert); + X509_ALGOR_get0(&calgoid,0,0,sigalg); + n = OBJ_obj2nid(calgoid); +#endif + if (!env_str("SSL_CLIENT_A_SIG",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n))) + return 0; + +/* Algorithm for PubKey */ +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) // 0xmnnffppsL + n = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); +#else + pubkey = X509_get_X509_PUBKEY(cert); + X509_PUBKEY_get0_param(&algoid,0,0,0,pubkey); + n = OBJ_obj2nid(algoid); +#endif + if (!env_str("SSL_CLIENT_A_KEY",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n))) + return 0; + + bio = BIO_new(BIO_s_mem()); + if (!bio) return 0; + n = ssl_client_bio_vars(cert,chain,bio); + BIO_free(bio); + if (!n) return 0; + + return 1; +} + +static int ssl_server_bio_vars(X509 *cert,STACK_OF(X509) *chain,BIO *bio) { + ASN1_STRING *astring; + int n; + int m; + + astring = X509_get_notBefore(cert); + if (!ASN1_UTCTIME_print(bio,astring)) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val("SSL_SERVER_V_START",btemp.s,btemp.len)) return 0; + + astring = X509_get_notAfter(cert); + if (!ASN1_UTCTIME_print(bio,astring)) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val("SSL_SERVER_V_END",btemp.s,btemp.len)) return 0; + + if (!PEM_write_bio_X509(bio,cert)) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val("SSL_SERVER_CERT",btemp.s,btemp.len)) return 0; + + if (chain) { + for (m = 0; m < sk_X509_num(chain); m++) { + if (!stralloc_copys(&ctemp,"SSL_SERVER_CERT_CHAIN_")) return 0; + if (!stralloc_catb(&ctemp,strnum,fmt_ulong(strnum,m))) return 0; + if (!stralloc_0(&ctemp)) return 0; + + if (m < sk_X509_num(chain)) { + if (!PEM_write_bio_X509(bio,sk_X509_value(chain,m))) return 0; + n = BIO_pending(bio); + if (!stralloc_ready(&btemp,n)) return 0; + btemp.len = n; + n = BIO_read(bio,btemp.s,n); + if (n != btemp.len) return 0; + if (!env_val(ctemp.s,btemp.s,btemp.len)) return 0; + } + } + } + + return 1; +} + +static int ssl_server_vars(X509 *cert,STACK_OF(X509) *chain) { + X509_NAME *xname; + X509_PUBKEY *pubkey; + const X509_ALGOR *sigalg; + const ASN1_OBJECT *calgoid; + ASN1_OBJECT *algoid; + BIGNUM *bn; + BIO *bio; + char *x = 0; + int n; + + if (!cert) return 1; + + if (!env_val("SSL_SERVER_M_VERSION",strnum,fmt_ulong(strnum,X509_get_version(cert) + 1))) + return 0; + + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), 0); + x = BN_bn2dec(bn); + BN_free(bn); + if (!env_val("SSL_SERVER_M_SERIAL",x,strlen(x))) return 0; + OPENSSL_free(x); + + xname = X509_get_subject_name(cert); + x = X509_NAME_oneline(xname,0,0); + n = env_str("SSL_SERVER_S_DN",x); + free(x); + if (!n) return 0; + + set_env_id(xname,"SSL_SERVER_S_DN_C",NID_countryName); + set_env_id(xname,"SSL_SERVER_S_DN_ST",NID_stateOrProvinceName); + set_env_id(xname,"SSL_SERVER_S_DN_L",NID_localityName); + set_env_id(xname,"SSL_SERVER_S_DN_O",NID_organizationName); + set_env_id(xname,"SSL_SERVER_S_DN_OU",NID_organizationalUnitName); + set_env_id(xname,"SSL_SERVER_S_DN_CN",NID_commonName); + set_env_id(xname,"SSL_SERVER_S_DN_T",NID_title); + set_env_id(xname,"SSL_SERVER_S_DN_I",NID_initials); + set_env_id(xname,"SSL_SERVER_S_DN_G",NID_givenName); + set_env_id(xname,"SSL_SERVER_S_DN_S",NID_surname); + set_env_id(xname,"SSL_SERVER_S_DN_D",NID_description); + set_env_id(xname,"SSL_SERVER_S_DN_UID",NID_x500UniqueIdentifier); + set_env_id(xname,"SSL_SERVER_S_DN_Email",NID_pkcs9_emailAddress); + + xname = X509_get_issuer_name(cert); + x = X509_NAME_oneline(xname,0,0); + n = env_str("SSL_SERVER_I_DN",x); + free(x); + if (!n) return 0; + + set_env_id(xname,"SSL_SERVER_I_DN_C",NID_countryName); + set_env_id(xname,"SSL_SERVER_I_DN_ST",NID_stateOrProvinceName); + set_env_id(xname,"SSL_SERVER_I_DN_L",NID_localityName); + set_env_id(xname,"SSL_SERVER_I_DN_O",NID_organizationName); + set_env_id(xname,"SSL_SERVER_I_DN_OU",NID_organizationalUnitName); + set_env_id(xname,"SSL_SERVER_I_DN_CN",NID_commonName); + set_env_id(xname,"SSL_SERVER_I_DN_T",NID_title); + set_env_id(xname,"SSL_SERVER_I_DN_I",NID_initials); + set_env_id(xname,"SSL_SERVER_I_DN_G",NID_givenName); + set_env_id(xname,"SSL_SERVER_I_DN_S",NID_surname); + set_env_id(xname,"SSL_SERVER_I_DN_D",NID_description); + set_env_id(xname,"SSL_SERVER_I_DN_UID",NID_x500UniqueIdentifier); + set_env_id(xname,"SSL_SERVER_I_DN_Email",NID_pkcs9_emailAddress); + +/* Signature Algorithm of PubKey */ +#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L)) + n = OBJ_obj2nid(cert->cert_info->signature->algorithm); +#else + sigalg = X509_get0_tbs_sigalg(cert); + X509_ALGOR_get0(&calgoid,0,0,sigalg); + n = OBJ_obj2nid(calgoid); +#endif + if (!env_str("SSL_SERVER_A_SIG",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n))) + return 0; + +/* Algorithm of PubKey */ +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) // 0xmnnffppsL + n = OBJ_obj2nid(cert->cert_info->key->algor->algorithm); +#else + pubkey = X509_get_X509_PUBKEY(cert); + X509_PUBKEY_get0_param(&algoid,0,0,0,pubkey); + n = OBJ_obj2nid(algoid); +#endif + if (!env_str("SSL_SERVER_A_KEY",(n == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(n))) + return 0; + + bio = BIO_new(BIO_s_mem()); + if (!bio) return 0; + n = ssl_server_bio_vars(cert,chain,bio); + BIO_free(bio); + + if (!n) return 0; + + return 1; +} + +int ssl_client_env(SSL *ssl,stralloc *sa) { + envsa = sa; + if (!ssl_session_vars(ssl)) return 0; + if (!ssl_client_vars(SSL_get_certificate(ssl),0)) + return 0; +#if (OPENSSL_VERSION_NUMBER > 0x30000000L) // 0xmnnffppsL + if (!ssl_server_vars(0,SSL_get_peer_cert_chain(ssl))) +#else + if (!ssl_server_vars(SSL_get_peer_certificate(ssl),SSL_get_peer_cert_chain(ssl))) +#endif + return 0; + return 1; +} + +int ssl_server_env(SSL *ssl,stralloc *sa) { + envsa = sa; + if (!ssl_session_vars(ssl)) return 0; + if (!ssl_server_vars(SSL_get_certificate(ssl),0)) + return 0; +#if (OPENSSL_VERSION_NUMBER > 0x30000000L) // 0xmnnffppsL + if (!ssl_server_vars(0,SSL_get_peer_cert_chain(ssl))) +#else + if (!ssl_client_vars(SSL_get_peer_certificate(ssl),SSL_get_peer_cert_chain(ssl))) +#endif + return 0; + return 1; +} diff --git a/src/ssl_error.c b/src/ssl_error.c new file mode 100644 index 0000000..88a01a1 --- /dev/null +++ b/src/ssl_error.c @@ -0,0 +1,12 @@ +#include "ucspissl.h" + +int ssl_error(int (*op)(const char *)) { + unsigned long e; + int r; + + e = ERR_get_error(); + if (!e) return 0; + r = op(ERR_error_string(e,0)); + if (r) return r; + return ssl_error(op); +} diff --git a/src/ssl_io.c b/src/ssl_io.c new file mode 100644 index 0000000..883380f --- /dev/null +++ b/src/ssl_io.c @@ -0,0 +1,269 @@ +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include "iopause.h" +#include "buffer.h" +#include "taia.h" +#include "ucspissl.h" +#include "error.h" + +static int leftstatus = 0; +static char leftbuf[16 * 1024]; +static int leftlen; +static int leftpos; + +static int rightstatus = 0; +static char rightbuf[16 * 1024]; +static int rightlen; +static int rightpos; + +int ssl_io(SSL *ssl,int fdleft,int fdright,unsigned int timeout) { + struct taia now; + struct taia deadline; + iopause_fd x[4]; + int xlen; + iopause_fd *io0; + iopause_fd *ioleft; + iopause_fd *io1; + iopause_fd *ioright; + int r; + int rc = 0; + int rfd; + int wfd; + + rfd = SSL_get_fd(ssl); /* XXX */ + if (rfd == -1) { + close(fdleft); close(fdright); + return -1; + } + wfd = SSL_get_fd(ssl); /* XXX */ + if (wfd == -1) { + close(fdleft); close(fdright); + return -1; + } + + for (;;) { + xlen = 0; + + if (leftstatus == -1 && rightstatus == -1) + goto DONE; + + io0 = 0; + if (leftstatus == 0 && rightstatus != 1) { + io0 = &x[xlen++]; + io0->fd = rfd; + io0->events = IOPAUSE_READ; + } + + ioleft = 0; + if (leftstatus == 1) { + ioleft = &x[xlen++]; + ioleft->fd = fdleft; + ioleft->events = IOPAUSE_WRITE; + } + + ioright = 0; + if (rightstatus == 0) { + ioright = &x[xlen++]; + ioright->fd = fdright; + ioright->events = IOPAUSE_READ; + } + + io1 = 0; + if (rightstatus == 1) { + io1 = &x[xlen++]; + io1->fd = wfd; + io1->events = IOPAUSE_WRITE; + } + + if (taia_now(&now) == -1) { + errno = ETIMEDOUT; + rc = -1; + goto BOMB; + } + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + iopause(x,xlen,&deadline,&now); + + for (r = 0; r < xlen; ++r) + if (x[r].revents) goto EVENTS; + + if (io0 && !ssl_pending(ssl)) { + close(fdleft); + leftstatus = -1; + continue; + } + errno = ETIMEDOUT; + rc = -1; + goto BOMB; + + +EVENTS: + if (io0 && io0->revents) { + r = SSL_read(ssl,leftbuf,sizeof(leftbuf)); + ssl_errno = SSL_get_error(ssl,r); + switch (ssl_errno) { + case SSL_ERROR_NONE: + leftstatus = 1; + leftpos = 0; + leftlen = r; + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + break; + case SSL_ERROR_ZERO_RETURN: + if (rightstatus == -1) goto DONE; + close(fdleft); + leftstatus = -1; + break; + case SSL_ERROR_SYSCALL: + if (errno == EAGAIN || errno == EINTR) break; + close(fdleft); + leftstatus = -1; + if (!errno) break; + /* premature close */ + if (errno == ECONNRESET && rightstatus == -1) goto DONE; + goto BOMB; + case SSL_ERROR_SSL: +/* Continuing after a received SSL error given the socket is still + * potentially active might be a noble cause, but is impracticle. + * We consider an SSL_ERROR_SSL as application failure; not TLS + * and close the connection gracefully. + * if (errno == EAGAIN || errno == EINTR) break; + * if (!errno) break; + */ + goto DONE; + default: + close(fdleft); + leftstatus = -1; + if (rightstatus == 1) break; + if (ssl_shutdown_pending(ssl)) goto DONE; + goto BOMB; + } + } + + if (ioleft && ioleft->revents) { + r = buffer_unixwrite(fdleft,leftbuf + leftpos,leftlen - leftpos); + if (r == -1) { + if (errno == EINTR || errno == EWOULDBLOCK) { + /* retry */ + } + else if (errno == EPIPE || errno == EAGAIN) { + if (rightstatus == -1) goto DONE; + close(fdleft); + leftstatus = -1; + } else { + rc = -1; + goto BOMB; + } + } + else { + leftpos += r; + if (leftpos == leftlen) { + leftstatus = 0; + if ((r = ssl_pending(ssl))) { + if (r > sizeof(leftbuf)) r = sizeof(leftbuf); + r = SSL_read(ssl,leftbuf,r); + ssl_errno = SSL_get_error(ssl,r); + switch (ssl_errno) { + case SSL_ERROR_NONE: + leftstatus = 1; + leftpos = 0; + leftlen = r; + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + break; + case SSL_ERROR_ZERO_RETURN: + if (rightstatus == -1) goto DONE; + close(fdleft); + leftstatus = -1; + break; + default: + rc = -1; + goto BOMB; + } + } + } + } + } + + if (ioright && ioright->revents) { + r = buffer_unixread(fdright,rightbuf,sizeof(rightbuf)); + if (r == -1) { + if (errno == EINTR || errno == EWOULDBLOCK) { + /* retry */ + } else { + rc = -1; + goto BOMB; /* errno == EAGAIN => unrecoverable */ + } + } + else if (r == 0) { + close(fdright); + rightstatus = -1; + if (ssl_shutdown(ssl)) goto DONE; + if (leftstatus == -1) goto DONE; + } + else { + rightstatus = 1; + rightpos = 0; + rightlen = r; + } + } + + if (io1 && io1->revents) { + r = SSL_write(ssl,rightbuf + rightpos,rightlen - rightpos); + ssl_errno = SSL_get_error(ssl,r); + switch (ssl_errno) { + case SSL_ERROR_NONE: + rightpos += r; + if (rightpos == rightlen) rightstatus = 0; + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_X509_LOOKUP: + break; + case SSL_ERROR_ZERO_RETURN: + close(fdright); + rightstatus = -1; + if (leftstatus == -1) goto DONE; + if (ssl_shutdown(ssl)) goto DONE; + break; + case SSL_ERROR_SYSCALL: + if (errno == EAGAIN || errno == EINTR) break; + if (errno == EPIPE) { + close(fdright); + rightstatus = -1; + if (leftstatus == -1) goto DONE; + if (ssl_shutdown(ssl)) goto DONE; + break; + } + default: + rc = -1; + goto BOMB; + } + } + } + + +BOMB: + r = errno; + if (leftstatus != -1) close(fdleft); + if (rightstatus != -1) close(fdright); + if (!ssl_shutdown_sent(ssl)) ssl_shutdown(ssl); + if (!ssl_shutdown_pending(ssl)) ssl_shutdown(ssl); + shutdown(wfd,2); + errno = r; + return rc; + + +DONE: + if (!ssl_shutdown_sent(ssl)) ssl_shutdown(ssl); + if (!ssl_shutdown_pending(ssl)) ssl_shutdown(ssl); + shutdown(wfd,2); + if (leftstatus != -1) close(fdleft); + if (rightstatus != -1) close(fdright); + return 0; +} diff --git a/src/ssl_new.c b/src/ssl_new.c new file mode 100644 index 0000000..4833778 --- /dev/null +++ b/src/ssl_new.c @@ -0,0 +1,16 @@ +#include "ucspissl.h" +#include "ndelay.h" + +SSL *ssl_new(SSL_CTX *ctx,int s) +{ + BIO *sbio; + SSL *ssl; + + ssl = SSL_new(ctx); + if (!ssl) return 0; + sbio = BIO_new_socket(s,BIO_NOCLOSE); + if (!sbio) return 0; + SSL_set_bio(ssl,sbio,sbio); + return ssl; +} + diff --git a/src/ssl_params.c b/src/ssl_params.c new file mode 100644 index 0000000..d3a49d0 --- /dev/null +++ b/src/ssl_params.c @@ -0,0 +1,80 @@ +/** + @file ssl_params.c + @author web, bergmann + @brief setup RSA, DH, ECDH +*/ +#include "ucspissl.h" + +int ssl_params_rsa(SSL_CTX *ctx,int len) +{ + RSA *rsa; + long res; + BIGNUM *e; + + /* check if ephemeral RSA key is actually needed */ + if (!SSL_CTX_need_tmp_RSA(ctx)) return 1; + + if (len) { + e = BN_new(); + rsa = RSA_new(); + BN_set_word(e,RSA_F4); + + res = (long) RSA_generate_key_ex(rsa,len,e,NULL); + BN_free(e); + + if (res == -1) return 0; + if (!rsa) return 0; + + /* seldom "needed": maybe deal with an export cipher */ + res = SSL_CTX_set_tmp_rsa(ctx,rsa); + RSA_free(rsa); + if (!res) return 0; + } + + return 1; +} + +int ssl_params_dh(SSL_CTX *ctx,const char *dhfile) +{ + DH *dh; + BIO *bio; + + if (dhfile) { + dh = 0; + bio = BIO_new_file(dhfile,"r"); + if (!bio) return 0; + dh = PEM_read_bio_DHparams(bio,0,0,0); + BIO_free(bio); + if (!dh) return 0; + if (!SSL_CTX_set_tmp_dh(ctx,dh)) return 0; + } + + return 1; +} + +int ssl_params_ecdh(SSL_CTX *ctx,const char *ecdhfile) +{ + EC_KEY *ecdh; + + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); +#ifdef SSL_CTRL_SET_ECDH_AUTO + SSL_CTX_set_ecdh_auto(ctx,1); +#else + /* insecure and compatible curves, see http://safecurves.cr.yp.to/ */ + ecdh = EC_KEY_new_by_curve_name(NID_secp521r1); + if (ecdh == NULL) { + /* NIST P-384 / AES-256 */ + ecdh = EC_KEY_new_by_curve_name(NID_secp384r1); + } + if (ecdh == NULL) { + /* NIST P-256 / AES-128 */ + ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + } + if (ecdh != NULL) { + SSL_CTX_set_tmp_ecdh(ctx,ecdh); + EC_KEY_free(ecdh); + return 1; + } +#endif + return 0; +} diff --git a/src/ssl_timeout.c b/src/ssl_timeout.c new file mode 100644 index 0000000..737f72f --- /dev/null +++ b/src/ssl_timeout.c @@ -0,0 +1,125 @@ +#include "ucspissl.h" +#include "iopause.h" +#include "logmsg.h" + +#define WHO "ssl_timeout" + +int ssl_timeoutaccept(SSL *ssl,unsigned int timeout) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + int r; + int rfd; + int wfd; + + if (taia_now(&now) == -1) { + errno = ETIMEDOUT; + return -1; + } + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + + rfd = SSL_get_fd(ssl); /* XXX */ + wfd = SSL_get_fd(ssl); /* XXX */ + + SSL_set_accept_state(ssl); + + for (;;) { + r = SSL_accept(ssl); + if (r == 1) return 0; + ssl_errno = SSL_get_error(ssl,r); + errno = EPROTO; + if ((ssl_errno != SSL_ERROR_WANT_READ) && (ssl_errno != SSL_ERROR_WANT_WRITE)) + return -1; + if (ssl_errno == SSL_ERROR_WANT_READ) { + x.events = IOPAUSE_READ; + x.fd = rfd; + if (x.fd == -1) return -1; + } + else { + x.events = IOPAUSE_WRITE; + x.fd = wfd; + if (x.fd == -1) return -1; + } + for (;;) { + if (taia_now(&now) == -1) { + errno = ETIMEDOUT; + return -1; + } + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + } +} + +int ssl_timeoutconn(SSL *ssl,unsigned int timeout) +{ + struct taia now; + struct taia deadline; + iopause_fd x; + int r; + int rfd; + int wfd; + + taia_now(&now); + taia_uint(&deadline,timeout); + taia_add(&deadline,&now,&deadline); + + rfd = SSL_get_fd(ssl); /* XXX */ + wfd = SSL_get_fd(ssl); /* XXX */ + + SSL_set_connect_state(ssl); + + for (;;) { + r = SSL_connect(ssl); + errno = EPROTO; + if (r == 1) return 0; + ssl_errno = SSL_get_error(ssl,r); + if ((ssl_errno != SSL_ERROR_WANT_READ) && (ssl_errno != SSL_ERROR_WANT_WRITE)) + return -1; + if (ssl_errno == SSL_ERROR_WANT_READ) { + x.events = IOPAUSE_READ; + x.fd = rfd; + if (x.fd == -1) return -1; + } + else { + x.events = IOPAUSE_WRITE; + x.fd = wfd; + if (x.fd == -1) return -1; + } + for (;;) { + if (taia_now(&now) == -1) { + errno = ETIMEDOUT; + return -1; + } + iopause(&x,1,&deadline,&now); + if (x.revents) break; + if (taia_less(&deadline,&now)) { + errno = ETIMEDOUT; + return -1; + } + } + } +} + +stralloc sslerror = {0}; + +int ssl_verberror(void) +{ + char buf[256]; + unsigned long err; + + if (!stralloc_copys(&sslerror,"")) return -1; + + while ((err = ERR_get_error()) != 0) { + ERR_error_string_n(err,buf,sizeof(buf)); + if (!stralloc_cats(&sslerror,buf)) return -1; + if (!stralloc_cats(&sslerror," ")) return -1; + } + return err; +} diff --git a/src/ssl_verify.c b/src/ssl_verify.c new file mode 100644 index 0000000..474c45b --- /dev/null +++ b/src/ssl_verify.c @@ -0,0 +1,63 @@ +/** + @file ssl_verify.c + @author web, feh -- parts of code borrowed from Pavel Shramov; tx Peter Conrad + @brief Compares 'hostname' against SubAltName DNS:hostname + DN: /CN=hostname +*/ +#include "ucspissl.h" +#include "case.h" +#include "str.h" + +int ssl_verify(SSL *ssl,const char *hostname,stralloc *dnsout) +{ + X509 *cert; + STACK_OF(GENERAL_NAME) *extensions; + const GENERAL_NAME *ext; + char buf[SSL_NAME_LEN]; + char *dnsname = 0; + int i; + int num; + int len; + int dname = 0; + +#if (OPENSSL_VERSION_NUMBER > 0x30100000L) + cert = SSL_get1_peer_certificate(ssl); +#else + cert = SSL_get_peer_certificate(ssl); +#endif + if (!cert) return -1; + + if (SSL_get_verify_result(ssl) != X509_V_OK) return -2; + + if (hostname) { + if (!stralloc_copys(dnsout,"")) return 1; + extensions = X509_get_ext_d2i(cert,NID_subject_alt_name,0,0); + num = sk_GENERAL_NAME_num(extensions); /* num = 0, if no SAN extensions */ + + for (i = 0; i < num; ++i) { + ext = sk_GENERAL_NAME_value(extensions,i); + if (ext->type == GEN_DNS) { + if (ASN1_STRING_type(ext->d.dNSName) != V_ASN1_IA5STRING) continue; +#if ((OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER > 0 && LIBRESSL_VERSION_NUMBER < 0x20700000L)) + dnsname = (char *)ASN1_STRING_data(ext->d.dNSName); +#else + dnsname = (char *)ASN1_STRING_get0_data(ext->d.dNSName); +#endif + len = ASN1_STRING_length(ext->d.dNSName); + if (len != str_len(dnsname)) continue; + if (!stralloc_copyb(dnsout,dnsname,len)) return 1; + if (case_diffs((char *)hostname,dnsname) == 0) return 0; + dname = 1; + } + } + + if (!dname) { + X509_NAME_get_text_by_NID(X509_get_subject_name(cert),NID_commonName,buf,sizeof(buf)); + buf[SSL_NAME_LEN - 1] = 0; + if (!stralloc_copyb(dnsout,buf,str_len(buf))) return 1; + if (case_diffs((char *)hostname,buf) == 0) return 0; + } + + return -3; + } + return 0; +} diff --git a/src/sslcat.sh b/src/sslcat.sh new file mode 100644 index 0000000..f923935 --- /dev/null +++ b/src/sslcat.sh @@ -0,0 +1,9 @@ +host=${1-0} +port=${2-443} +args="" +if [ $# -gt 2 ] +then + shift; shift + args="$@" +fi +exec sslclient -RHl0 $args -- "$host" "$port" sh -c 'exec cat <&6' diff --git a/src/sslclient.c b/src/sslclient.c new file mode 100644 index 0000000..1d4ce57 --- /dev/null +++ b/src/sslclient.c @@ -0,0 +1,449 @@ +/** + @file sslclient.c + @author web, fefe, feh + @brief IPv6 enabled sslclient +*/ +#include <unistd.h> +#include <sys/types.h> +#include <sys/param.h> +#include <netdb.h> +#include <arpa/inet.h> +#include "ucspissl.h" +#include "sig.h" +#include "exit.h" +#include "getoptb.h" +#include "uint_t.h" +#include "fmt.h" +#include "scan.h" +#include "str.h" +#include "ip.h" +#include "socket_if.h" +#include "fd.h" +#include "stralloc.h" +#include "buffer.h" +#include "getln.h" +#include "logmsg.h" +#include "pathexec.h" +#include "timeoutconn.h" +#include "remoteinfo.h" +#include "dnsresolv.h" +#include "byte.h" +#include "ndelay.h" +#include "wait.h" +#include "auto_cafile.h" +#include "auto_cadir.h" +#include "auto_ciphers.h" + +#define WHO "sslclient" + +void nomem(void) { + logmsg(WHO,111,FATAL,"out of memory"); +} +void env(const char *s,const char *t) { + if (!pathexec_env(s,t)) nomem(); +} + +void usage(void) { + logmsg(WHO,100,USAGE,"sslclient \ +[ -463hHrRdDiqQveEsSnNxX ] \ +[ -i localip ] \ +[ -p localport ] \ +[ -T timeoutconn ] \ +[ -l localname ] \ +[ -t timeoutinfo ] \ +[ -I interface ] \ +[ -a cafile ] \ +[ -A cadir ] \ +[ -c certfile ] \ +[ -z ciphers ] \ +[ -k keyfile ] \ +[ -V verifydepth ] \ +[ -w progtimeout ] \ +host port program"); +} + +int verbosity = 1; +int flagdelay = 0; +int flagremoteinfo = 0; +int flagremotehost = 1; +int flag3 = 0; +int flagsslenv = 0; +int flagtcpenv = 0; +int flagsni = 0; +unsigned long itimeout = 26; +unsigned long ctimeout[2] = { 2, 58 }; +unsigned int progtimeout = 3600; +uint32 netif = 0; + +const char *loopback = "127.0.0.1"; +char iplocal[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; +uint16 portlocal = 0; +const char *forcelocal = 0; + +char ipremote[16]; +uint16 portremote; + +const char *hostname; +int flagname = 1; +int flagservercert = 1; +static stralloc addresses; +static stralloc certname; +static stralloc moreaddresses; + +static stralloc tmp; +static stralloc fqdn; +static char strnum[FMT_ULONG]; +static char ipstr[IP6_FMT]; + +char seed[128]; + +char bspace[16]; +buffer b; + +SSL_CTX *ctx; +const char *certfile = 0; +const char *keyfile = 0; +const char *cafile = auto_cafile; +const char *cadir = auto_cadir; +const char *ciphers = auto_ciphers; +stralloc password = {0}; +int match = 0; +int verifydepth = 1; + +int pi[2]; +int po[2]; +int pt[2]; + +void read_passwd() { + if (!password.len) { + buffer_init(&b,buffer_unixread,3,bspace,sizeof(bspace)); + if (getln(&b,&password,&match,'\0') == -1) + logmsg(WHO,111,ERROR,"unable to read password"); + close(3); + if (match) --password.len; + } +} + +int passwd_cb(char *buf,int size,int rwflag,void *userdata) { + if (size < password.len) + logmsg(WHO,111,ERROR,"password too long"); + + byte_copy(buf,password.len,password.s); + return password.len; +} + +int main(int argc,char * const *argv) { + unsigned long u; + int opt; + const char *x; + int j; + int s; + int r; + int cloop; + SSL *ssl; + int wstat; + int ipflag = 0; + + dns_random_init(seed); + + close(6); + close(7); + sig_ignore(sig_pipe); + + while ((opt = getopt(argc,argv,"dDvqQhHrRimM:p:t:T:l:a:A:c:z:k:V:346eEsSnN0xXw:")) != opteof) + switch(opt) { + case '4': ipflag = 1; break; + case '6': ipflag = 0; break; + case 'd': flagdelay = 1; break; + case 'D': flagdelay = 0; break; + case 'm': flagsni = 1; break; + case 'M': flagsni = 0; break; + case 'v': verbosity = 2; break; + case 'q': verbosity = 0; break; + case 'Q': verbosity = 1; break; + case 'l': forcelocal = optarg; break; + case 'H': flagremotehost = 0; break; + case 'h': flagremotehost = 1; break; + case 'R': flagremoteinfo = 0; break; + case 'r': flagremoteinfo = 1; break; + case 't': scan_ulong(optarg,&itimeout); break; + case 'T': j = scan_ulong(optarg,&ctimeout[0]); + if (optarg[j] == '+') ++j; + scan_ulong(optarg + j,&ctimeout[1]); + break; + case 'w': scan_uint(optarg,&progtimeout); break; + case 'i': if (!ip6_scan(optarg,iplocal)) usage(); break; + case 'I': netif = socket_getifidx(optarg); break; + case 'p': scan_ulong(optarg,&u); portlocal = u; break; + case 'a': cafile = optarg; break; + case 'A': cadir = optarg; break; + case 'c': certfile = optarg; break; + case 'z': ciphers = optarg; break; + case 'k': keyfile = optarg; break; + case 'V': scan_ulong(optarg,&u); verifydepth = u; break; + case '3': flag3 = 1; break; + case 'S': flagsslenv = 0; break; + case 's': flagsslenv = 1; break; + case 'E': flagtcpenv = 0; break; + case 'e': flagtcpenv = 1; break; + case 'N': flagname = 0; break; + case 'n': flagname = 1; break; + case 'x': flagservercert = 1; break; + case 'X': flagservercert = 0; break; + default: usage(); + } + argv += optind; + + if (!verbosity) + buffer_2->fd = -1; + + hostname = *argv; + if (!hostname || str_equal((char *)hostname,"")) usage(); + if (str_equal((char *)hostname,"0")) hostname = loopback; + + x = *++argv; + if (!x) usage(); + if (!x[scan_ulong(x,&u)]) + portremote = u; + else { + struct servent *se; + se = getservbyname(x,"tcp"); + if (!se) + logmsg(WHO,111,FATAL,B("unable to figure out port number for ",x)); + uint16_unpack_big((char*)&se->s_port,&portremote); + } + + if (flag3) read_passwd(); + + if (cafile && str_equal(cafile,"")) cafile = 0; + if (cadir && str_equal(cadir,"")) cadir= 0; + if (ciphers && str_equal(ciphers,"")) ciphers= 0; + + if (certfile && str_equal(certfile,"")) certfile = 0; + if (keyfile && str_equal(keyfile,"")) keyfile = 0; + + if (!*++argv) usage(); + + if (!stralloc_copys(&tmp,hostname)) nomem(); + dns_ip_qualify(&addresses,&fqdn,&tmp); + if (addresses.len < 16) + logmsg(WHO,111,ERROR,B("No IP address for: ",hostname)); + + if (addresses.len == 16) { + ctimeout[0] += ctimeout[1]; + ctimeout[1] = 0; + } + + for (cloop = 0; cloop < 2; ++cloop) { + if (!stralloc_copys(&moreaddresses,"")) nomem(); + for (j = 0; j + 16 <= addresses.len; j += 16) { + if (ipflag == 1 || ip6_isv4mapped(addresses.s + j)) { + s = socket_tcp4(); + if (s == -1) logmsg(WHO,111,FATAL,"unable to create socket"); + r = socket_bind4(s,iplocal,portlocal); + } else { + s = socket_tcp6(); + if (s == -1) logmsg(WHO,111,FATAL,"unable to create socket"); + r = socket_bind6(s,iplocal,portlocal,netif); + } + if (r == -1) { + strnum[fmt_ulong(strnum,portlocal)] = 0; + if (ip6_isv4mapped(addresses.s + j)) + ipstr[ip4_fmt(ipstr,addresses.s + j + 12)] = 0; + else + ipstr[ip6_fmt(ipstr,addresses.s + j)] = 0; + + logmsg(WHO,111,FATAL,B("unable to bind to: ",ipstr," port: ",strnum)); + } + if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop],netif) == 0) + goto CONNECTED; + close(s); + if (!cloop && ctimeout[1] && (errno == ETIMEDOUT)) { + if (!stralloc_catb(&moreaddresses,addresses.s + j,16)) nomem(); + } + else { + strnum[fmt_ulong(strnum,portremote)] = 0; + if (ip6_isv4mapped(addresses.s + j)) + ipstr[ip4_fmt(ipstr,addresses.s + j + 12)] = 0; + else + ipstr[ip6_fmt(ipstr,addresses.s + j)] = 0; + } + } + if (!stralloc_copy(&addresses,&moreaddresses)) nomem(); + } + logmsg(WHO,110,DROP,B("unable to connect to: ",ipstr," port: ",strnum)); + + _exit(111); + + + CONNECTED: + + /* Local */ + + if (socket_local(s,iplocal,&portlocal,&netif) == -1) + logmsg(WHO,111,FATAL,"unable to get local address"); + + if (ip6_isv4mapped(iplocal)) { + env("PROTO","TCP6"); + ipstr[ip4_fmt(ipstr,iplocal + 12)] = 0; + } else { + env("PROTO","TCP6"); + if (flagtcpenv && netif) env("TCP6INTERFACE",socket_getifname(netif)); + ipstr[ip6_fmt(ipstr,iplocal)] = 0; + } + + env("SSLLOCALIP",ipstr); + if (flagtcpenv) env("TCPLOCALIP",ipstr); + + strnum[fmt_ulong(strnum,portlocal)] = 0; + env("SSLLOCALPORT",strnum); + if (flagtcpenv) env("TCPLOCALPORT",strnum); + + x = forcelocal; + if (!x) + if (dns_name(&tmp,iplocal) >= 0) { + if (!stralloc_0(&tmp)) nomem(); + x = tmp.s; + } + env("SSLLOCALHOST",x); + if (flagtcpenv) env("TCPLOCALHOST",x); + + /* Remote */ + + if (socket_remote(s,ipremote,&portremote,&netif) == -1) + logmsg(WHO,111,FATAL,"unable to get remote address"); + + if (ip6_isv4mapped(ipremote)) + ipstr[ip4_fmt(ipstr,ipremote + 12)] = 0; + else + ipstr[ip6_fmt(ipstr,ipremote)] = 0; + + env("SSLREMOTEIP",ipstr); + if (flagtcpenv) env("TCPREMOTEIP",ipstr); + + strnum[fmt_ulong(strnum,portremote)] = 0; + env("SSLREMOTEPORT",strnum); + if (flagtcpenv) env("TCPREMOTEPORT",strnum); + + x = 0; + if (flagremotehost) + if (dns_name(&tmp,ipremote) >= 0) { + if (!stralloc_0(&tmp)) nomem(); + x = tmp.s; + } + + env("SSLREMOTEHOST",x); + if (flagtcpenv) env("TCPREMOTEHOST",x); + + x = 0; + if (flagremoteinfo) + if (remoteinfo(&tmp,ipremote,portremote,iplocal,portlocal,itimeout,netif) == 0) { + if (!stralloc_0(&tmp)) nomem(); + x = tmp.s; + } + env("SSLREMOTEINFO",x); + if (flagtcpenv) env("TCPREMOTEINFO",x); + + /* Context */ + + ctx = ssl_client(); + ssl_errstr(); + if (!ctx) + logmsg(WHO,111,FATAL,"unable to create TLS context"); + + switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) { + case -1: logmsg(WHO,111,ERROR,"unable to load certificate"); + case -2: logmsg(WHO,111,ERROR,"unable to load key pair"); + case -3: logmsg(WHO,111,ERROR,"key does not match certificate"); + default: break; + } + + if (flagservercert && !ssl_ca(ctx,cafile,cadir,verifydepth)) + logmsg(WHO,111,ERROR,"unable to load CA list"); + + if (!ssl_ciphers(ctx,ciphers)) + logmsg(WHO,111,ERROR,"unable to set cipher list"); + + ssl = ssl_new(ctx,s); + if (!ssl) logmsg(WHO,111,FATAL,"unable to create TLS instance"); + + if (flagsni) + if (!SSL_set_tlsext_host_name(ssl,hostname)) + logmsg(WHO,111,FATAL,B("unable to set TLS SNI extensions for hostname: ",(char *)hostname)); + + for (cloop = 0; cloop < 2; ++cloop) { + if (!ssl_timeoutconn(ssl,ctimeout[cloop])) goto SSLCONNECTED; + if (!cloop && ctimeout[1]) continue; + logmsg(WHO,111,FATAL,"unable to TLS connect"); + } + + _exit(111); + + SSLCONNECTED: + + ndelay_off(s); + + if (flagservercert) + switch(ssl_verify(ssl,hostname,&certname)) { + case -1: + logmsg(WHO,110,ERROR,"no server certificate"); + case -2: + logmsg(WHO,110,ERROR,"missing credentials (CA) or unable to validate server certificate"); + case -3: + if (!stralloc_0(&certname)) nomem(); + if (flagname) + logmsg(WHO,110,ERROR,B("server hostname does not match certificate: ",(char *)hostname," <=> ",certname.s)); + default: break; + } + + if (verbosity >= 2) + log_who(WHO,B("tls connected to: ",ipstr," port: ",strnum)); + + if (!flagdelay) + socket_tcpnodelay(s); /* if it fails, bummer */ + + if (pipe(pi) == -1) logmsg(WHO,111,FATAL,"unable to create pipe"); + if (pipe(po) == -1) logmsg(WHO,111,FATAL,"unable to create pipe"); + if (pi[0] == 7) { + if (pipe(pt) == -1) logmsg(WHO,111,FATAL,"unable to create pipe"); + close(pi[0]); close(pi[1]); + pi[0] = pt[0]; pi[1] = pt[1]; + } + if (po[1] == 6) { + if (pipe(pt) == -1) logmsg(WHO,111,FATAL,"unable to create pipe"); + close(po[0]); close(po[1]); + po[0] = pt[0]; po[1] = pt[1]; + } + + switch (opt = fork()) { + case -1: + logmsg(WHO,111,FATAL,"unable to fork"); + case 0: + break; + default: + close(pi[0]); close(po[1]); + if (ssl_io(ssl,pi[1],po[0],progtimeout)) { + logmsg(WHO,110,DROP,"unable to speak TLS"); + ssl_close(ssl); + wait_pid(&wstat,opt); + _exit(111); + } + ssl_close(ssl); + if (wait_pid(&wstat,opt) > 0) + _exit(wait_exitcode(wstat)); + _exit(0); + } + ssl_close(ssl); close(pi[1]); close(po[0]); + + if (flagsslenv && !ssl_client_env(ssl,0)) nomem(); + + if (fd_move(6,pi[0]) == -1) + logmsg(WHO,111,FATAL,"unable to set up descriptor 6"); + if (fd_move(7,po[1]) == -1) + logmsg(WHO,111,FATAL,"unable to set up descriptor 7"); + sig_uncatch(sig_pipe); + + pathexec(argv); + logmsg(WHO,111,FATAL,B("unable to run: ",*argv)); + return 0; /* never happens, but avoids compile warning */ +} diff --git a/src/sslconnect.sh b/src/sslconnect.sh new file mode 100644 index 0000000..3462540 --- /dev/null +++ b/src/sslconnect.sh @@ -0,0 +1,9 @@ +host=${1-0} +port=${2-465} +args="" +if [ $# -gt 2 ] +then + shift; shift + args="$@" +fi +exec sslclient -XRHl0 $args -- "$host" "$port" mconnect-io diff --git a/src/sslhandle.c b/src/sslhandle.c new file mode 100644 index 0000000..f31cee9 --- /dev/null +++ b/src/sslhandle.c @@ -0,0 +1,887 @@ +/** + @file sslhandle.c + @author web, feh + @brief IPv6 enabled TLS framework for a preforking server +*/ +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netdb.h> +#include <signal.h> +#include <arpa/inet.h> +#include "ucspissl.h" +#include "uint_t.h" +#include "str.h" +#include "byte.h" +#include "fmt.h" +#include "scan.h" +#include "ip.h" +#include "fd.h" +#include "exit.h" +#include "env.h" +#include "prot.h" +#include "open.h" +#include "wait.h" +#include "stralloc.h" +#include "alloc.h" +#include "buffer.h" +#include "getln.h" +#include "logmsg.h" +#include "getoptb.h" +#include "socket_if.h" +#include "ndelay.h" +#include "remoteinfo.h" +#include "rules.h" +#include "sig.h" +#include "iopause.h" +#include "dnsresolv.h" +#include "auto_cafile.h" +#include "auto_cadir.h" +#include "auto_ccafile.h" +#include "auto_dhfile.h" +#include "auto_certchainfile.h" +#include "auto_certfile.h" +#include "auto_keyfile.h" +#include "auto_ciphers.h" +#include "iopause.h" +#include "coe.h" +#include "lock.h" + + +extern void server(int argcs,char * const *argvs); +char *who; + +int verbosity = 1; +int flagkillopts = 1; +int flagafter = 0; +int flagdelay = 0; +const char *banner = ""; +int flagremoteinfo = 1; +int flagremotehost = 1; +int flagparanoid = 0; +int flagclientcert = 0; +int flagsslenv = 0; +int flagtcpenv = 0; +unsigned long timeout = 26; +unsigned long ssltimeout = 26; +unsigned int progtimeout = 3600; +uint32 netif = 0; +int selfpipe[2]; +int flagexit = 0; +int flagdualstack = 0; + +static stralloc tcpremoteinfo = {0}; + +uint16 localport; +char localportstr[FMT_ULONG]; +char localip[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; +char localipstr[IP6_FMT]; +static stralloc localhostsa; +const char *localhost = 0; +const char *lockfile = 0; +int fdlock; + +uint16 remoteport; +char remoteportstr[FMT_ULONG]; +char remoteip[16]; +char remoteipstr[IP6_FMT]; +static stralloc remotehostsa; +char *remotehost = 0; + +const char *hostname; +const char *loopback = "127.0.0.1"; + +static char strnum[FMT_ULONG]; +static char strnum2[FMT_ULONG]; + +static stralloc tmp; +static stralloc fqdn; +static stralloc addresses; +static stralloc certname; +stralloc envplus = {0}; +stralloc envtmp = {0}; + +char bspace[16]; +buffer b; + +SSL_CTX *ctx; +const char *certchainfile = auto_certchainfile; +const char *certfile = auto_certfile; +const char *keyfile = auto_keyfile; +stralloc password = {0}; +int match = 0; +const char *cafile = auto_cafile; +const char *ccafile = auto_ccafile; +const char *cadir = auto_cadir; +const char *ciphers = auto_ciphers; +int verifydepth = 1; +const char *dhfile = auto_dhfile; +int rsalen = SSL_RSA_LEN; + +int pi[2]; +int po[2]; + +X509 *cert; +char buf[SSL_NAME_LEN]; + +char **e; +char **e1; + +/* ---------------------------- child */ + + +int flagdeny = 0; +int flagallownorules = 0; +const char *fnrules = 0; + +void drop_nomem(void) { + logmsg(who,111,FATAL,"out of memory"); +} +void drop_notemp(void) { + logmsg(who,111,FATAL,"out of timestamps"); +} +void cats(const char *s) { + if (!stralloc_cats(&tmp,s)) drop_nomem(); +} +void append(const char *ch) { + if (!stralloc_append(&tmp,ch)) drop_nomem(); +} +void safecats(const char *s) { + char ch; + int i; + + for (i = 0;i < 100;++i) { + ch = s[i]; + if (!ch) return; + if (ch < 33) ch = '?'; + if (ch > 126) ch = '?'; + if (ch == '%') ch = '?'; /* logger stupidity */ + append(&ch); + } + cats("..."); +} +void env(const char *s,const char *t) { + if (!s) return; + if (!stralloc_copys(&envtmp,s)) drop_nomem(); + if (t) { + if (!stralloc_cats(&envtmp,"=")) drop_nomem(); + if (!stralloc_cats(&envtmp,t)) drop_nomem(); + } + if (!stralloc_0(&envtmp)) drop_nomem(); + if (!stralloc_cat(&envplus,&envtmp)) drop_nomem(); +} +static void env_def() { + unsigned int elen; + unsigned int i; + unsigned int j; + unsigned int split; + unsigned int t; + + if (!stralloc_cats(&envplus,"")) return; + + elen = 0; + for (i = 0; environ[i]; ++i) + ++elen; + for (i = 0; i < envplus.len; ++i) + if (!envplus.s[i]) + ++elen; + + e = (char **) alloc((elen + 1) * sizeof(char *)); + if (!e) return; + + elen = 0; + for (i = 0; environ[i]; ++i) + e[elen++] = environ[i]; + + j = 0; + for (i = 0; i < envplus.len; ++i) + if (!envplus.s[i]) { + split = str_chr(envplus.s + j,'='); + for (t = 0;t < elen;++t) + if (byte_equal(envplus.s + j,split,e[t])) + if (e[t][split] == '=') { + --elen; + e[t] = e[elen]; + break; + } + if (envplus.s[j + split]) + e[elen++] = envplus.s + j; + j = i + 1; + } + e[elen] = 0; + + e1 = environ; + environ = e; +} +void env_reset(void) { + if (e) { + if (e != environ) { + alloc_free((char *)e); + logmsg(who,111,FATAL,"environ changed"); + } + } + + environ = e1; + envplus.len = 0; +} +int error_warn(const char *x) { + if (!x) return 0; + log_who(who,"x"); + return 0; +} +void drop_rules(void) { + logmsg(who,111,FATAL,B("unable to read: ",(char *)fnrules)); +} + +void found(char *data,unsigned int datalen) { + unsigned int next0; + unsigned int split; + + while ((next0 = byte_chr(data,datalen,0)) < datalen) { + switch(data[0]) { + case 'D': + flagdeny = 1; + break; + case '+': + split = str_chr(data + 1,'='); + if (data[1 + split] == '=') { + data[1 + split] = 0; + env(data + 1,data + 1 + split + 1); + } + break; + } + ++next0; + data += next0; datalen -= next0; + } +} + +int doit(int t) { + int j; + SSL *ssl; + uint32 netif; + + if (ip6_isv4mapped(remoteip)) { + remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0; + localipstr[ip4_fmt(localipstr,localip + 12)] = 0; + } else { + remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; + localipstr[ip6_fmt(localipstr,localip)] = 0; + } + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + log_who(who,B("pid ",strnum," from ",remoteipstr)); + } + + if (socket_local(t,localip,&localport,&netif) == -1) + logmsg(who,111,FATAL,"unable to get local address"); + + remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; + + if (!localhost) + if (dns_name(&localhostsa,localip) >= 0) + if (localhostsa.len) { + if (!stralloc_0(&localhostsa)) drop_nomem(); + localhost = localhostsa.s; + } + + env("PROTO","TLS"); + env("SSLLOCALIP",localipstr); + env("SSLLOCALPORT",localportstr); + env("SSLLOCALHOST",localhost); + env("SSLREMOTEIP",remoteipstr); + env("SSLREMOTEPORT",remoteportstr); + env("SSLREMOTEHOST",remotehost); + + if (flagtcpenv) { + env("TCPLOCALIP",localipstr); + env("TCPLOCALPORT",localportstr); + env("TCPLOCALHOST",localhost); + env("TCPREMOTEIP",remoteipstr); + env("TCPREMOTEPORT",remoteportstr); + env("TCPREMOTEHOST",remotehost); + if (!ip6_isv4mapped(localip)) { + env("PROTO","TCP6"); + env("TCP6LOCALIP",localipstr); + env("TCP6LOCALHOST",localhost); + env("TCP6LOCALPORT",localportstr); + env("TCP6REMOTEIP",remoteipstr); + env("TCP6REMOTEPORT",remoteportstr); + env("TCP6REMOTEHOST",remotehost); + if (netif) + env("TCP6INTERFACE",socket_getifname(netif)); + } else + env("PROTO","TCP"); + } + + if (flagremotehost) + if (dns_name(&remotehostsa,remoteip) >= 0) + if (remotehostsa.len) { + if (flagparanoid) { + if (dns_ip6(&tmp,&remotehostsa) >= 0) + for (j = 0; j + 16 <= tmp.len; j += 16) + if (byte_equal(remoteip,16,tmp.s + j)) { + flagparanoid = 0; + break; + } + if (dns_ip4(&tmp,&remotehostsa) >= 0) + for (j = 0; j + 4 <= tmp.len; j += 4) + if (byte_equal(remoteip,4,tmp.s + j)) { + flagparanoid = 0; + break; + } + } + if (!flagparanoid) { + if (!stralloc_0(&remotehostsa)) drop_nomem(); + remotehost = remotehostsa.s; + } + } + + if (flagremoteinfo) { + if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) + flagremoteinfo = 0; + if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); + } + env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + if (flagtcpenv) + env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + + if (fnrules) { + int fdrules; + flagdeny = 0; + fdrules = open_read(fnrules); + if (fdrules == -1) { + if (errno != ENOENT) drop_rules(); + if (!flagallownorules) drop_rules(); + } else { + if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) + drop_rules(); + close(fdrules); + } + } + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + if (!stralloc_copys(&tmp,who)) drop_nomem(); + if (!stralloc_cats(&tmp,": ")) drop_nomem(); + safecats(flagdeny ? "deny" : "ok"); + cats(" "); safecats(strnum); + cats(" "); if (localhost) safecats(localhost); + cats(":"); safecats(localipstr); + cats(":"); safecats(localportstr); + cats(" "); if (remotehost) safecats(remotehost); + cats(":"); safecats(remoteipstr); + cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); + cats(":"); safecats(remoteportstr); + cats("\n"); + buffer_putflush(buffer_2,tmp.s,tmp.len); + } + + if (flagdeny) { + close(t); + return(0); + } + + if (pipe(pi) == -1) logmsg(who,111,FATAL,"unable to create pipe"); + if (pipe(po) == -1) logmsg(who,111,FATAL,"unable to create pipe"); + + ssl = ssl_new(ctx,t); + if (!ssl) logmsg(who,111,FATAL,"unable to create SSL instance"); + if (ndelay_on(t) == -1) + logmsg(who,111,FATAL,"unable to set socket options"); + if (ssl_timeoutaccept(ssl,ssltimeout) == -1) { + strnum[fmt_ulong(strnum,getpid())] = 0; + logmsg(who,110,DROP,B("unable to TLS accept for pid:",strnum)); + ssl_error(error_warn); + } + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + log_who(who,B("tls ",strnum," accept ")); + } + + if (flagclientcert) { + switch(ssl_verify(ssl,remotehost,&certname)) { + case -1: + logmsg(who,110,ERROR,"no client certificate"); + case -2: + logmsg(who,110,ERROR,"missing credentials (CA) or unable to validate client certificate"); + case -3: + if (!stralloc_0(&certname)) drop_nomem(); + logmsg(who,110,ERROR,B("client hostname name does not match certificate: ",remotehost," <=> ",certname.s)); + default: + break; + } + } + + switch(fork()) { + case -1: + logmsg(who,111,FATAL,"unable to fork "); + case 0: + close(pi[0]); close(po[1]); + sig_uncatch(sig_child); + sig_unblock(sig_child); + if (ssl_io(ssl,pi[1],po[0],progtimeout) == -1) { + strnum[fmt_ulong(strnum,getpid())] = 0; + logmsg(who,-99,WARN,B("unable to speak TLS for pid: ",strnum)); + ssl_error(error_warn); + _exit(111); + } + _exit(0); + } + close(pi[1]); close(po[0]); + + if (flagsslenv && !ssl_server_env(ssl,&envplus)) drop_nomem(); + env_def(); + + if (fd_move(0,pi[0]) == -1) + logmsg(who,111,FATAL,"unable to set up descriptor 0"); + if (fd_move(1,po[1]) == -1) + logmsg(who,111,FATAL,"unable to set up descriptor 1"); + + if (flagkillopts) { + socket_ipoptionskill(t); + } + if (!flagdelay) + socket_tcpnodelay(t); + + if (*banner) { + buffer_init(&b,buffer_unixwrite,1,bspace,sizeof(bspace)); + if (buffer_putsflush(&b,banner) == -1) + logmsg(who,111,FATAL,"unable to print banner"); + } + + ssl_free(ssl); + return 1; +} + +void done(void) { + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + if (!stralloc_copys(&tmp,who)) drop_nomem(); + if (!stralloc_cats(&tmp,": ")) drop_nomem(); + cats("done "); safecats(strnum); cats("\n"); + buffer_putflush(buffer_2,tmp.s,tmp.len); + } +} + + +/* ---------------------------- parent */ + +void usage(void) +{ + logmsg(who,100,USAGE,B(who,"\ +[ -1346UXpPhHrRoOdDqQviIeEsS ] \ +[ -c limit ] \ +[ -x rules.cdb ] \ +[ -B banner ] \ +[ -g gid ] \ +[ -u uid ] \ +[ -b backlog ] \ +[ -l localname ] \ +[ -t timeout ] \ +[ -T ssltimeout ] \ +[ -w progtimeout ] \ +[ -f lockfile ] \ +[ -I interface ] \ +host port program")); +} + +unsigned long limit = 40; +unsigned long numchildren = 0; + +int flag1 = 0; +int flag3 = 0; +unsigned long backlog = 20; +unsigned long uid = 0; +unsigned long gid = 0; + +void printstatus(void) { + if (verbosity < 2) return; + strnum[fmt_ulong(strnum,numchildren)] = 0; + strnum2[fmt_ulong(strnum2,limit)] = 0; + log_who(who,B("status: ",strnum,"/",strnum2)); +} + +void trigger(void) { + buffer_unixwrite(selfpipe[1],"",1); +} + +void sigterm(void) { + int pid; + + flagexit = 1; + pid = getpid(); + if (pid < 0) logmsg(who,111,FATAL,"cannot get pid"); + kill(-pid,SIGTERM); + trigger(); +} + +void sigchld(void) { + int wstat; + int pid; + + while ((pid = wait_nohang(&wstat)) > 0) { + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,pid)] = 0; + strnum2[fmt_ulong(strnum2,wstat)] = 0; + log_who(who,B("end ",strnum," status ",strnum2)); + } + if (numchildren) --numchildren; printstatus(); + if (flagexit && !numchildren) _exit(0); + } + trigger(); +} + +void read_passwd(void) { + if (!password.len) { + buffer_init(&b,buffer_unixread,3,bspace,sizeof(bspace)); + if (getln(&b,&password,&match,'\0') == -1) + logmsg(who,111,ERROR,"unable to read password"); + close(3); + if (match) --password.len; + } +} + +int passwd_cb(char *buff,int size,int rwflag,void *userdata) { + if (size < password.len) + logmsg(who,111,ERROR,"password too long"); + + byte_copy(buff,password.len,password.s); + return password.len; +} + +void spawn(int s,int argc,char * const *argv) { + int t; + + while (numchildren >= limit) sig_pause(); + while (numchildren < limit) { + ++numchildren; printstatus(); + + switch(fork()) { + case 0: + sig_uncatch(sig_child); + sig_unblock(sig_child); + sig_uncatch(sig_term); + sig_uncatch(sig_pipe); + for (;;) { + if (lockfile) { + if (lock_ex(fdlock) == -1) + logmsg(who,111,FATAL,B("unable to lock: ",(char *)lockfile)); + if (flagdualstack) + t = socket_accept6(s,remoteip,&remoteport,&netif); + else + t = socket_accept4(s,remoteip,&remoteport); + lock_un(fdlock); + } else { + if (flagdualstack) + t = socket_accept6(s,remoteip,&remoteport,&netif); + else + t = socket_accept4(s,remoteip,&remoteport); + } + + if (t == -1) continue; + if (!doit(t)) continue; + server(argc,argv); + close(0); close(1); + env_reset(); + done(); + } + break; + case -1: + logmsg(who,111,FATAL,"unable to fork"); + --numchildren; printstatus(); + } + } +} + +int main(int argc,char * const *argv) { + int opt; + struct servent *se; + char *x; + int j; + int s; + int ipflag = 0; + iopause_fd io[2]; + char ch; + struct taia deadline; + struct taia stamp; + unsigned long u; + + who = argv[0]; + while ((opt = getopt(argc,argv,"dDvqQhHrRUXx:t:T:u:g:l:b:B:c:pPoO1346I:EeSsaAf:w:zZ")) != opteof) + switch(opt) { + case 'b': scan_ulong(optarg,&backlog); break; + case 'c': scan_ulong(optarg,&limit); break; + case 'X': flagallownorules = 1; break; + case 'x': fnrules = optarg; break; + case 'B': banner = optarg; break; + case 'd': flagdelay = 1; break; + case 'D': flagdelay = 0; break; + case 'v': verbosity = 2; break; + case 'q': verbosity = 0; break; + case 'Q': verbosity = 1; break; + case 'P': flagparanoid = 0; break; + case 'p': flagparanoid = 1; break; + case 'O': flagkillopts = 1; break; + case 'o': flagkillopts = 0; break; + case 'H': flagremotehost = 0; break; + case 'h': flagremotehost = 1; break; + case 'R': flagremoteinfo = 0; break; + case 'r': flagremoteinfo = 1; break; + case 't': scan_ulong(optarg,&timeout); break; + case 'T': scan_ulong(optarg,&ssltimeout); break; + case 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid); + x = env_get("GID"); if (x) scan_ulong(x,&gid); break; + case 'u': scan_ulong(optarg,&uid); break; + case 'g': scan_ulong(optarg,&gid); break; + case 'l': localhost = optarg; break; + case 'I': netif = socket_getifidx(optarg); break; + case '1': flag1 = 1; break; + case '3': flag3 = 1; break; + case '4': ipflag = 1; break; + case '6': ipflag = 2; break; + case 'Z': flagclientcert = 0; break; + case 'z': flagclientcert = 1; break; + case 'S': flagsslenv = 0; break; + case 's': flagsslenv = 1; break; + case 'E': flagtcpenv = 0; break; + case 'e': flagtcpenv = 1; break; + case 'A': flagafter = 0; break; + case 'a': flagafter = 1; break; + case 'f': lockfile = optarg; break; + case 'w': scan_uint(optarg,&progtimeout); break; + default: usage(); + } + argc -= optind; + argv += optind; + + if (!verbosity) buffer_2->fd = -1; + + hostname = *argv++; + if (!hostname || str_equal((char *)hostname,"")) usage(); + if (str_equal((char *)hostname,"0")) hostname = loopback; + else if (str_equal((char *)hostname,":0")) { + flagdualstack = 1; + hostname = "::"; + } + + x = *argv++; --argc; + if (!x) usage(); + if (!x[scan_ulong(x,&u)]) + localport = u; + else { + se = getservbyname(x,"tcp"); + if (!se) + logmsg(who,111,FATAL,B("unable to figure out port number for: ",x)); + uint16_unpack_big((char*)&se->s_port,&localport); + } + + if ((x = env_get("VERIFYDEPTH"))) { + scan_ulong(x,&u); + verifydepth = u; + } + + if ((x = env_get("CAFILE"))) cafile = x; + if (cafile && str_equal((char *)cafile,"")) cafile = 0; + + if ((x = env_get("CCAFILE"))) ccafile = x; + if (ccafile && str_equal((char *)ccafile,"")) ccafile = 0; + if (!flagclientcert) ccafile = 0; + + if ((x = env_get("CADIR"))) cadir = x; + if (cadir && str_equal((char *)cadir,"")) cadir= 0; + + if ((x = env_get("CERTCHAINFILE"))) certchainfile = x; + if (certchainfile && str_equal((char *)certchainfile,"")) certchainfile = 0; + + if ((x = env_get("CERTFILE"))) certfile = x; + if (certfile && str_equal((char *)certfile,"")) certfile = 0; + + if ((x = env_get("KEYFILE"))) keyfile = x; + if (keyfile && str_equal((char *)keyfile,"")) keyfile = 0; + + if ((x = env_get("DHFILE"))) dhfile = x; + if (dhfile && str_equal((char *)dhfile,"")) dhfile = 0; + + if ((x = env_get("CIPHERS"))) ciphers = x; + if (ciphers && str_equal((char *)ciphers,"")) ciphers = 0; + + if (setsid() == -1) + if (getpgrp() != getpid()) + logmsg(who,111,FATAL,"unable to create process group"); + + if (lockfile) { + fdlock = open_append(lockfile); + if (fdlock == -1) + logmsg(who,111,FATAL,B("unable to open: ",(char *)lockfile)); + } + + if (pipe(selfpipe) == -1) + logmsg(who,111,FATAL,"unable to create pipe"); + + coe(selfpipe[0]); + coe(selfpipe[1]); + ndelay_on(selfpipe[0]); + ndelay_on(selfpipe[1]); + + sig_block(sig_child); + sig_catch(sig_child,sigchld); + sig_catch(sig_term,sigterm); + sig_ignore(sig_pipe); + + /* IP address only */ + + if (ip4_scan(hostname,localip)) { + if (!stralloc_copyb(&addresses,(char *)V4mappedprefix,12)) drop_nomem(); + if (!stralloc_catb(&addresses,localip,4)) drop_nomem(); + byte_copy(localip,16,addresses.s); + } else if (ip6_scan(hostname,localip)) { + if (!stralloc_copyb(&addresses,localip,16)) drop_nomem(); + byte_copy(localip,16,addresses.s); + } + + /* Asynchronous DNS IPv4/IPv6 Name qualification */ + + if (!addresses.len) { + if (!stralloc_copys(&tmp,hostname)) drop_nomem(); + if (dns_ip_qualify(&addresses,&fqdn,&tmp) < 0) + logmsg(who,111,FATAL,B("temporarily unable to figure out IP address for: ",(char *)hostname)); + + byte_copy(localip,16,addresses.s); + + for (j = 0; j < addresses.len; j += 16) { // Select best matching IP address + if (ipflag == 1 && !ip6_isv4mapped(addresses.s + j)) continue; + if (ipflag == 2 && !ip6_isv4mapped(addresses.s + j)) continue; + byte_copy(localip,16,addresses.s + j); + } + + } + if (addresses.len < 16) + logmsg(who,111,FATAL,B("no IP address for: ",(char *)hostname)); + + if (ip6_isv4mapped(localip)) + s = socket_tcp4(); + else + s = socket_tcp6(); + if (s == -1) + logmsg(who,111,FATAL,"unable to create socket"); + + if (flagdualstack) + socket_dualstack(s); + if (socket_bind_reuse(s,localip,localport,netif) == -1) + logmsg(who,111,FATAL,"unable to bind"); + if (socket_local(s,localip,&localport,&netif) == -1) + logmsg(who,111,FATAL,"unable to get local address"); + if (socket_listen(s,backlog) == -1) + logmsg(who,111,FATAL,"unable to listen"); + ndelay_off(s); + + if (!flagafter) { + if (gid) if (prot_gid(gid) == -1) + logmsg(who,111,FATAL,"unable to set gid"); + if (uid) if (prot_uid(uid) == -1) + logmsg(who,111,FATAL,"unable to set uid"); + } + + if (ip6_isv4mapped(localip)) + localipstr[ip4_fmt(localipstr,localip + 12)] = 0; + else + localipstr[ip6_fmt(localipstr,localip)] = 0; + + localportstr[fmt_ulong(localportstr,localport)] = 0; + + if (flag1) { + buffer_init(&b,buffer_unixwrite,1,bspace,sizeof(bspace)); + buffer_puts(&b,localipstr); + buffer_puts(&b," : "); + buffer_puts(&b,localportstr); + buffer_puts(&b,"\n"); + buffer_flush(&b); + } + + if (flag3) read_passwd(); + + ctx = ssl_server(); + ssl_errstr(); + if (!ctx) logmsg(who,111,FATAL,"unable to create TLS context"); + + if (certchainfile) { + switch (ssl_chainfile(ctx,certchainfile,keyfile,passwd_cb)) { + case -1: logmsg(who,111,ERROR,"unable to load certificate chain file"); + case -2: logmsg(who,111,ERROR,"unable to load key"); + case -3: logmsg(who,111,ERROR,"key does not match certificate"); + default: break; + } + } else { + switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) { + case -1: logmsg(who,111,ERROR,"unable to load certificate"); + case -2: logmsg(who,111,ERROR,"unable to load key"); + case -3: logmsg(who,111,ERROR,"key does not match certificate"); + default: break; + } + } + + if (flagclientcert && !ssl_ca(ctx,cafile,cadir,verifydepth)) + logmsg(who,111,ERROR,"unable to load CA list"); + + if (!ssl_cca(ctx,ccafile)) + logmsg(who,111,ERROR,"unable to load client CA list"); + + if (!ssl_params_rsa(ctx,rsalen)) + logmsg(who,111,ERROR,"unable to set RSA parameters"); + if (!ssl_params_dh(ctx,dhfile)) + logmsg(who,111,ERROR,"unable to set DH parameters"); + + if (flagafter) { + if (gid) if (prot_gid(gid) == -1) + logmsg(who,111,FATAL,"unable to set gid"); + if (uid) if (prot_uid(uid) == -1) + logmsg(who,111,FATAL,"unable to set uid"); + } + + if (!ssl_ciphers(ctx,ciphers)) + logmsg(who,111,ERROR,"unable to set cipher list"); + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + strnum2[fmt_ulong(strnum2,rsalen)] = 0; + log_who(who,B("ciphers ",strnum," ",(char *)ciphers)); + log_who(who,B("cafile ",strnum," ",(char *)cafile)); + log_who(who,B("ccafile ",strnum," ",(char *)ccafile)); + log_who(who,B("cadir ",strnum," ",(char *)cadir)); + log_who(who,B("certchainfile ",strnum," ",(char *)certchainfile)); + log_who(who,B("cert ",strnum," ",(char *)certfile)); + log_who(who,B("key ",strnum," ",(char *)keyfile)); + /* XXX */ + log_who(who,B("dhparam ",strnum," ",(char *)dhfile," ",strnum2)); + } + + close(0); + close(1); + printstatus(); + + for (;;) { + int pause_ret, read_ret; + if (!flagexit) spawn(s,argc,argv); + + sig_unblock(sig_child); + io[0].fd = selfpipe[0]; + io[0].events = IOPAUSE_READ; + taia_now(&stamp); + taia_uint(&deadline,3600); + taia_add(&deadline,&stamp,&deadline); + pause_ret = iopause(io,1,&deadline,&stamp); + sig_block(sig_child); + + if (flagexit && !numchildren) _exit(0); + while ((read_ret = buffer_unixread(selfpipe[0],&ch,1)) == 1) + ; + if ((pause_ret > 0) && (read_ret == 0)) { + flagexit = 1; + --numchildren; + } + if (flagexit && !numchildren) _exit(0); + } +} diff --git a/src/sslperl.c b/src/sslperl.c new file mode 100644 index 0000000..1d01da1 --- /dev/null +++ b/src/sslperl.c @@ -0,0 +1,105 @@ +#include <EXTERN.h> +#include <perl.h> +#include "exit.h" +#include "logmsg.h" +#include "stralloc.h" +#include "str.h" +#include "ucspissl.h" + +#ifndef eval_pv +#define eval_pv perl_eval_pv +#endif + +#ifndef call_argv +#define call_argv perl_call_argv +#endif + +extern char *Who = "PERL!"; + +//extern const char *Who; + +/* ActiveState Perl requires this be called my_perl */ +static PerlInterpreter *my_perl = 0; + +static void usage(void) { + logmsg(Who,100,USAGE,"sslargs file sub args"); +} + +static stralloc newenv = {0}; +static char *trivenv[] = { 0 }; +static char **perlenv = trivenv; +static char **origenv = 0; + +void env_append(const char *c) { + if (!stralloc_append(&newenv,c)) + logmsg(Who,111,FATAL,"out of memory"); +} + +#define EXTERN_C extern + +EXTERN_C void xs_init() { +} + +void server(int argc,char **argv) { + char *prog[] = { "", *argv }; + int i; + int j; + int split; + const char *x; + + ++argv; --argc; + if (!argv) usage(); + if (!*argv) usage(); + + origenv = environ; + environ = perlenv; + + if (!my_perl) { + my_perl = perl_alloc(); + if (!my_perl) logmsg(Who,111,FATAL,"out of memory"); + perl_construct(my_perl); + if (perl_parse(my_perl,xs_init,2,prog,trivenv)) + logmsg(Who,111,FATAL,"perl_parse failed"); + + if (perl_run(my_perl)) + logmsg(Who,111,FATAL,"perl_run failed"); + } + + if (!stralloc_copys(&newenv,"%ENV=(")) + logmsg(Who,111,FATAL,"out of memory"); + + for (i = 0; origenv[i]; ++i) { + x = origenv[i]; + if (!x) continue; + split = str_chr(x,'='); + env_append("'"); + for (j = 0; j < split; ++j) { + if (*x == '\'' || *x == '\\') env_append("\\"); + env_append(x++); + } + env_append("'"); + env_append(","); + env_append("'"); + if (*x == '=') ++x; + while (*x) { + if (*x == '\'' || *x == '\\') env_append("\\"); + env_append(x++); + } + env_append("'"); + env_append(","); + } + env_append(")"); + env_append("\0"); + + ENTER; + SAVETMPS; + eval_pv(newenv.s,TRUE); + FREETMPS; + LEAVE; + + if (call_argv(*argv,G_VOID|G_DISCARD,argv + 1)) + logmsg(Who,111,FATAL,"interpreter failed"); + + perlenv = environ; + environ = origenv; +} diff --git a/src/sslprint.c b/src/sslprint.c new file mode 100644 index 0000000..0033107 --- /dev/null +++ b/src/sslprint.c @@ -0,0 +1,411 @@ +#include "buffer.h" +#include "env.h" + +static char *e[] = {0}; +static int n = 0; + +void server(int argc,const char * const *argv) { + char *x; + + buffer_puts(buffer_1,"\nPROTO="); + x = env_get("PROTO"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLLOCALHOST="); + x = env_get("SSLLOCALHOST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLLOCALIP="); + x = env_get("SSLLOCALIP"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLLOCALPORT="); + x = env_get("SSLLOCALPORT"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLREMOTEHOST="); + x = env_get("SSLREMOTEHOST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLREMOTEIP="); + x = env_get("SSLREMOTEIP"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLREMOTEPORT="); + x = env_get("SSLREMOTEPORT"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSLREMOTEINFO="); + x = env_get("SSLREMOTEINFO"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPLOCALHOST="); + x = env_get("TCPLOCALHOST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPLOCALIP="); + x = env_get("TCPLOCALIP"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPLOCALPORT="); + x = env_get("TCPLOCALPORT"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPREMOTEHOST="); + x = env_get("TCPREMOTEHOST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPREMOTEIP="); + x = env_get("TCPREMOTEIP"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPREMOTEPORT="); + x = env_get("TCPREMOTEPORT"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCPREMOTEINFO="); + x = env_get("TCPREMOTEINFO"); + buffer_puts(buffer_1,x ? x : "unset"); + + + buffer_puts(buffer_1,"\nTCP6REMOTEHOST="); + x = env_get("TCP6REMOTEHOST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCP6REMOTEIP="); + x = env_get("TCP6REMOTEIP"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nTCP6REMOTEPORT="); + x = env_get("TCP6REMOTEPORT"); + buffer_puts(buffer_1,x ? x : "unset"); + + + buffer_puts(buffer_1,"\nSSL_PROTOCOL="); + x = env_get("SSL_PROTOCOL"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SESSION_ID="); + x = env_get("SSL_SESSION_ID"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CIPHER="); + x = env_get("SSL_CIPHER"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CIPHER_EXPORT="); + x = env_get("SSL_CIPHER_EXPORT"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CIPHER_USEKEYSIZE="); + x = env_get("SSL_CIPHER_USEKEYSIZE"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CIPHER_ALGKEYSIZE="); + x = env_get("SSL_CIPHER_ALGKEYSIZE"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_VERSION_INTERFACE="); + x = env_get("SSL_VERSION_INTERFACE"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_VERSION_LIBRARY="); + x = env_get("SSL_VERSION_LIBRARY"); + buffer_puts(buffer_1,x ? x : "unset"); + + + buffer_puts(buffer_1,"\nSSL_SERVER_M_VERSION="); + x = env_get("SSL_SERVER_M_VERSION"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_M_SERIAL="); + x = env_get("SSL_SERVER_M_SERIAL"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN="); + x = env_get("SSL_SERVER_S_DN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_C="); + x = env_get("SSL_SERVER_S_DN_C"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_ST="); + x = env_get("SSL_SERVER_S_DN_ST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_L="); + x = env_get("SSL_SERVER_S_DN_L"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_O="); + x = env_get("SSL_SERVER_S_DN_O"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_OU="); + x = env_get("SSL_SERVER_S_DN_OU"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_CN="); + x = env_get("SSL_SERVER_S_DN_CN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_T="); + x = env_get("SSL_SERVER_S_DN_T"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_I="); + x = env_get("SSL_SERVER_S_DN_I"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_G="); + x = env_get("SSL_SERVER_S_DN_G"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_S="); + x = env_get("SSL_SERVER_S_DN_S"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_D="); + x = env_get("SSL_SERVER_S_DN_D"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_UID="); + x = env_get("SSL_SERVER_S_DN_UID"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_S_DN_Email="); + x = env_get("SSL_SERVER_S_DN_Email"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN="); + x = env_get("SSL_SERVER_I_DN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_C="); + x = env_get("SSL_SERVER_I_DN_C"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_ST="); + x = env_get("SSL_SERVER_I_DN_ST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_L="); + x = env_get("SSL_SERVER_I_DN_L"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_O="); + x = env_get("SSL_SERVER_I_DN_O"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_OU="); + x = env_get("SSL_SERVER_I_DN_OU"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_CN="); + x = env_get("SSL_SERVER_I_DN_CN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_T="); + x = env_get("SSL_SERVER_I_DN_T"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_I="); + x = env_get("SSL_SERVER_I_DN_I"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_G="); + x = env_get("SSL_SERVER_I_DN_G"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_S="); + x = env_get("SSL_SERVER_I_DN_S"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_D="); + x = env_get("SSL_SERVER_I_DN_D"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_UID="); + x = env_get("SSL_SERVER_I_DN_UID"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_I_DN_Email="); + x = env_get("SSL_SERVER_I_DN_Email"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_V_START="); + x = env_get("SSL_SERVER_V_START"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_V_END="); + x = env_get("SSL_SERVER_V_END"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_A_SIG="); + x = env_get("SSL_SERVER_A_SIG"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_A_KEY="); + x = env_get("SSL_SERVER_A_KEY"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_SERVER_CERT="); + x = env_get("SSL_SERVER_CERT"); + buffer_puts(buffer_1,x ? x : "unset"); + + + buffer_puts(buffer_1,"\nSSL_CLIENT_M_VERSION="); + x = env_get("SSL_CLIENT_M_VERSION"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_M_SERIAL="); + x = env_get("SSL_CLIENT_M_SERIAL"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN="); + x = env_get("SSL_CLIENT_S_DN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_C="); + x = env_get("SSL_CLIENT_S_DN_C"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_ST="); + x = env_get("SSL_CLIENT_S_DN_ST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_L="); + x = env_get("SSL_CLIENT_S_DN_L"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_O="); + x = env_get("SSL_CLIENT_S_DN_O"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_OU="); + x = env_get("SSL_CLIENT_S_DN_OU"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_CN="); + x = env_get("SSL_CLIENT_S_DN_CN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_T="); + x = env_get("SSL_CLIENT_S_DN_T"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_I="); + x = env_get("SSL_CLIENT_S_DN_I"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_G="); + x = env_get("SSL_CLIENT_S_DN_G"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_S="); + x = env_get("SSL_CLIENT_S_DN_S"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_D="); + x = env_get("SSL_CLIENT_S_DN_D"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_UID="); + x = env_get("SSL_CLIENT_S_DN_UID"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_S_DN_Email="); + x = env_get("SSL_CLIENT_S_DN_Email"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN="); + x = env_get("SSL_CLIENT_I_DN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_C="); + x = env_get("SSL_CLIENT_I_DN_C"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_ST="); + x = env_get("SSL_CLIENT_I_DN_ST"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_L="); + x = env_get("SSL_CLIENT_I_DN_L"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_O="); + x = env_get("SSL_CLIENT_I_DN_O"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_OU="); + x = env_get("SSL_CLIENT_I_DN_OU"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_CN="); + x = env_get("SSL_CLIENT_I_DN_CN"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_T="); + x = env_get("SSL_CLIENT_I_DN_T"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_I="); + x = env_get("SSL_CLIENT_I_DN_I"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_G="); + x = env_get("SSL_CLIENT_I_DN_G"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_S="); + x = env_get("SSL_CLIENT_I_DN_S"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_D="); + x = env_get("SSL_CLIENT_I_DN_D"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_UID="); + x = env_get("SSL_CLIENT_I_DN_UID"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_I_DN_Email="); + x = env_get("SSL_CLIENT_I_DN_Email"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_V_START="); + x = env_get("SSL_CLIENT_V_START"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_V_END="); + x = env_get("SSL_CLIENT_V_END"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_A_SIG="); + x = env_get("SSL_CLIENT_A_SIG"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_A_KEY="); + x = env_get("SSL_CLIENT_A_KEY"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_CERT="); + x = env_get("SSL_CLIENT_CERT"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_CERT_CHAIN_0="); + x = env_get("SSL_CLIENT_CERT_CHAIN_0"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_puts(buffer_1,"\nSSL_CLIENT_CERT_CHAIN_1="); + x = env_get("SSL_CLIENT_CERT_CHAIN_1"); + buffer_puts(buffer_1,x ? x : "unset"); + + buffer_putsflush(buffer_1,"\n"); + + if (++n > 1) { + environ = e; + } +} diff --git a/src/sslserver.c b/src/sslserver.c new file mode 100644 index 0000000..b342430 --- /dev/null +++ b/src/sslserver.c @@ -0,0 +1,991 @@ +/** + @file sslserver.c + @author web, fefe, feh + @brief IPv6 enabled dualstack sslserver +*/ +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netdb.h> +#include <fcntl.h> +#include <arpa/inet.h> +#include <signal.h> +#include "ucspissl.h" +#include "uint_t.h" +#include "str.h" +#include "byte.h" +#include "fmt.h" +#include "scan.h" +#include "ip.h" +#include "fd.h" +#include "exit.h" +#include "env.h" +#include "prot.h" +#include "open.h" +#include "wait.h" +#include "stralloc.h" +#include "genalloc.h" +#include "alloc.h" +#include "buffer.h" +#include "getln.h" +#include "error.h" +#include "logmsg.h" +#include "getoptb.h" +#include "pathexec.h" +#include "socket_if.h" +#include "ndelay.h" +#include "remoteinfo.h" +#include "rules.h" +#include "sig.h" +#include "iopause.h" +#include "dnsresolv.h" +#include "auto_cafile.h" +#include "auto_cadir.h" +#include "auto_ccafile.h" +#include "auto_dhfile.h" +#include "auto_certfile.h" +#include "auto_certchainfile.h" +#include "auto_keyfile.h" +#include "auto_ciphers.h" + +#define WHO "sslserver" + +int verbosity = 1; +int flagkillopts = 1; +int flagdelay = 0; +const char *banner = ""; +int flagremoteinfo = 0; +int flagremotehost = 1; +int flagparanoid = 0; +int flagclientcert = 0; +int flagsslenv = 0; +int flagtcpenv = 1; +int flagsslwait = 0; +unsigned long timeout = 26; +unsigned long ssltimeout = 26; +unsigned int progtimeout = 3600; +uint32 netif = 0; + +static stralloc tcpremoteinfo; + +uint16 localport; +char iplocal[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; +char localportstr[FMT_ULONG]; +char localip[16]; +char localipstr[IP6_FMT]; +static stralloc localhostsa; +const char *localhost = 0; + +uint16 remoteport; +char remoteportstr[FMT_ULONG]; +char remoteip[16]; +char remoteipstr[IP6_FMT]; +static stralloc remotehostsa; +char *remotehost = 0; +char *verifyhost = 0; + +const char *hostname; +const char *thishost = "0.0.0.0"; + +unsigned long uid = 0; +unsigned long gid = 0; + +static char strnum[FMT_ULONG]; +static char strnum2[FMT_ULONG]; +static char strnum3[FMT_ULONG]; + +static stralloc tmp; +static stralloc fqdn; +static stralloc addresses; + +unsigned long limit = 40; +unsigned long numchildren = 0; +unsigned long ipchildren = 0; +unsigned long maxconip = 0; + +char bspace[16]; +buffer bo; + +void drop_nomem(void) +{ + logmsg(WHO,111,FATAL,"out of memory"); +} + +/* ---------------------------- per ip limit */ + +struct child { + char ipaddr[16]; + uint32 num; +}; + +GEN_ALLOC_typedef(child_alloc,struct child,c,len,a) +GEN_ALLOC_readyplus(child_alloc,struct child,c,len,a,i,n,x,24,child_readyplus) +GEN_ALLOC_append(child_alloc,struct child,c,len,a,i,n,x,24,child_readyplus,child_append) + +child_alloc children = {0}; + +void ipchild_append(char ip[16],unsigned long n) +{ + struct child *ipchild = 0; + int i; + + for (i = 0; i <= n; ++i) { + ipchild = &children.c[i]; + if (byte_equal(ipchild->ipaddr,16,ip)) { + ++ipchild->num; + break; + } else { + byte_copy(ipchild->ipaddr,16,ip); + ++ipchild->num; + break; + } + } +} + +void ipchild_clear(char ip[16]) +{ + struct child *ipchild = 0; + int i; + + for (i = 0; i <= children.len; ++i) { + ipchild = &children.c[i]; + if (byte_equal(ipchild->ipaddr,16,ip)) { + if (ipchild->num) --ipchild->num; + break; + } + } +} + +int ipchild_limit(char ip[16],unsigned long n) +{ + int i; + + for (i = 0; i <= n; ++i) + if (byte_equal(children.c[i].ipaddr,16,ip)) + return children.c[i].num; + + return 0; +} + +SSL_CTX *ctx; +const char *certchainfile = auto_certchainfile; +const char *certfile = auto_certfile; +const char *keyfile = auto_keyfile; +stralloc password = {0}; +stralloc certname = {0}; +int match = 0; +const char *cafile = auto_cafile; +const char *ccafile = auto_ccafile; +const char *cadir = auto_cadir; +const char *ciphers = auto_ciphers; +int verifydepth = 1; +const char *dhfile = auto_dhfile; +int rsalen = SSL_RSA_LEN; + +char * const *prog; + +int pi[2]; +int po[2]; +int pt[2]; + +stralloc envsa = {0}; + +X509 *cert; +char buf[SSL_NAME_LEN]; + +/* ---------------------------- child */ + +int flagdualstack = 0; +int flagdeny = 0; +int flagallownorules = 0; +const char *fnrules = 0; +const char *fniprules = 0; + +void cats(const char *s) +{ + if (!stralloc_cats(&tmp,s)) drop_nomem(); +} +void append(const char *ch) +{ + if (!stralloc_append(&tmp,ch)) drop_nomem(); +} +void safecats(const char *s) { + char ch; + int i; + + for (i = 0;i < 100;++i) { + ch = s[i]; + if (!ch) return; + if (ch < 33) ch = '?'; + if (ch > 126) ch = '?'; + if (ch == '%') ch = '?'; /* logger stupidity */ + append(&ch); + } + cats("..."); +} + +void env(const char *s,const char *t) { + if (!pathexec_env(s,t)) drop_nomem(); +} + +void drop_rules(const char *fnbase) { + logmsg(WHO,110,FATAL,B("unable to read: ",fnbase)); +} + +void found(char *data,unsigned int datalen) { + unsigned int next0; + unsigned int split; + + while ((next0 = byte_chr(data,datalen,0)) < datalen) { + switch(data[0]) { + case 'D': + flagdeny = 1; + break; + case '+': + split = str_chr(data + 1,'='); + if (data[1 + split] == '=') { + data[1 + split] = 0; + env(data + 1,data + 1 + split + 1); + if (!str_diff(data + 1,"MAXCONIP")) { + scan_ulong(data + 1 + split + 1,&maxconip); + if (limit && maxconip > limit) maxconip = limit; + if (ipchildren >= maxconip) flagdeny = 2; + } + } + break; + } + ++next0; + data += next0; datalen -= next0; + } +} + +void doit(int t) { + int j; + SSL *ssl = 0; + int wstat; + int sslctl[2]; + char *s; + unsigned long tmp_long; + char ssl_cmd; + stralloc ssl_env = {0}; + int bytesleft; + char envbuf[8192]; + int childpid; + uint32 netif = 0; + stralloc tlsinfo = {0}; + + if (pipe(pi) == -1) logmsg(WHO,111,FATAL,"unable to create pipe"); + if (pipe(po) == -1) logmsg(WHO,111,FATAL,"unable to create pipe"); + if (socketpair(AF_UNIX,SOCK_STREAM,0,sslctl) == -1) + logmsg(WHO,111,FATAL,"unable to create socketpair"); + +/* Get remote IP and FQDN to validate X.509 cert */ + + if (ip6_isv4mapped(remoteip)) { + localipstr[ip4_fmt(localipstr,localip + 12)] = 0; + remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0; + } else { + remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; + localipstr[ip6_fmt(localipstr,localip)] = 0; + } + +/* Early evaluation of IP rules (only) */ + + if (fniprules) { + int fdrules; + fdrules = open_read(fniprules); + if (fdrules == -1) { + if (errno != ENOENT) drop_rules(fniprules); + if (!flagallownorules) drop_rules(fniprules); + } else { + if (rules(found,fdrules,remoteipstr,0,0) == -1) + drop_rules(fniprules); + close(fdrules); + } + } + + if (flagdeny) goto FINISH; + +/* Early lookup of remote information (before child invoked) */ + + if (flagremotehost) + if (dns_name(&remotehostsa,remoteip) >= 0) + if (remotehostsa.len) { + if (flagparanoid) { + verifyhost = remoteipstr; + if (dns_ip6(&tmp,&remotehostsa) >= 0) + for (j = 0; j + 16 <= tmp.len; j += 16) + if (byte_equal(remoteip,16,tmp.s + j)) { + flagparanoid = 0; + break; + } + if (dns_ip4(&tmp,&remotehostsa) >= 0) + for (j = 0; j + 4 <= tmp.len; j += 4) + if (byte_equal(remoteip + 12,4,tmp.s + j)) { + flagparanoid = 0; + break; + } + } + if (!flagparanoid) { + if (!stralloc_0(&remotehostsa)) drop_nomem(); + remotehost = remotehostsa.s; + verifyhost = remotehostsa.s; + } + } + + if (flagremoteinfo) { + if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) + flagremoteinfo = 0; + if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); + } + + if (fnrules) { + int fdrules; + fdrules = open_read(fnrules); + if (fdrules == -1) { + if (errno != ENOENT) drop_rules(fnrules); + if (!flagallownorules) drop_rules(fnrules); + } else { + if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) + drop_rules(fnrules); + close(fdrules); + } + } + + if (flagdeny) goto FINISH; + +/* Prepare the child process */ + + switch (childpid = fork()) { + case -1: + logmsg(WHO,111,FATAL,"unable to fork"); + case 0: + /* Child */ + close(sslctl[0]); + break; + default: + /* Parent */ + + close(pi[0]); close(po[1]); close(sslctl[1]); + + if ((s = env_get("SSL_CHROOT"))) + if (chroot(s) == -1) { + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,"unable to chroot"); + } + + if ((s = env_get("SSL_GID"))) { + scan_ulong(s,&tmp_long); + gid = tmp_long; + } + if (gid) if (prot_gid(gid) == -1) { + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,"unable to set gid"); + } + + if ((s = env_get("SSL_UID"))) { + scan_ulong(s,&tmp_long); + uid = tmp_long; + } + if (uid) + if (prot_uid(uid) == -1) { + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,"unable to set uid"); + } + +/* Get remote IP info to report in logmsg */ + + if (ip6_isv4mapped(remoteip)) + remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0; + else + remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; + +/* Read the TLS command socket. This will block until/unless TLS is requested. */ + + if (read(sslctl[0],&ssl_cmd,1) == 1) { + ssl = ssl_new(ctx,t); + if (!ssl) { + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,"unable to create TLS instance"); + } + if (ndelay_on(t) == -1) { + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,"unable to set socket options"); + } + if (ssl_timeoutaccept(ssl,ssltimeout) == -1) { + strnum[fmt_ulong(strnum,childpid)] = 0; + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,B("unable to accept TLS from: ",remoteipstr," for pid: ",strnum," ",ERR_reason_error_string(ssl_errno))); + } + } else if (errno == EAGAIN) { + strnum[fmt_ulong(strnum,childpid)] = 0; + kill(childpid,SIGTERM); + _exit(100); + } + +/* Check the remote client cert during TLS handshake; if requested */ + + if (flagclientcert) { + if (flagclientcert == 2) verifyhost = 0; + switch (ssl_verify(ssl,verifyhost,&certname)) { + case -1: + kill(childpid,SIGTERM); + logmsg(WHO,110,ERROR,B("no client certificate from: ",remoteipstr," for pid: ",strnum)); + case -2: + kill(childpid,SIGTERM); + logmsg(WHO,110,ERROR,B("missing credentials (CA) or unable to validate client certificate from: ",remoteipstr," for pid: ",strnum)); + case -3: + kill(childpid,SIGTERM); + if (!stralloc_0(&certname)) drop_nomem(); + logmsg(WHO,110,ERROR,B("client hostname does not match certificate for pid: ",strnum," ",verifyhost," <=> ",certname.s)); + default: + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,childpid)] = 0; + logmsg(WHO,0,INFO,B("valid client cert received from: ",remoteipstr," for pid: ",strnum)); + } + break; + } + } + +/* Request TLS communication pipe from/to the child process (the application called) */ + + if (ssl_cmd == 'Y') { + ssl_server_env(ssl,&ssl_env); + if (!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */ + env("SSLCTL",ssl_env.s); + + for (bytesleft = ssl_env.len; bytesleft > 0; bytesleft -= j) + if ((j = write(sslctl[0],ssl_env.s,bytesleft)) < 0) { + kill(childpid,SIGTERM); + logmsg(WHO,111,FATAL,"unable to write TLS environment"); + } + } + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,childpid)] = 0; + if (verbosity >= 3 && ssl_env.len > 1) { + s = ssl_env.s; + if ((j = str_chr(s,'='))) + if (!stralloc_copys(&tlsinfo,s + j + 1)) drop_nomem(); + if (!stralloc_cats(&tlsinfo,":")) drop_nomem(); + s = s + str_len(s) + 1; + s = s + str_len(s) + 1; + if ((j = str_chr(s,'='))) + if (!stralloc_cats(&tlsinfo,s + j + 1)) drop_nomem(); + if (!stralloc_0(&tlsinfo)) drop_nomem(); + log_who(WHO,B("tls ",strnum," accept ",tlsinfo.s)); + } else + log_who(WHO,B("tls ",strnum," accept")); + } + + if (ssl_cmd == 'Y' || ssl_cmd == 'y') { + if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) { + strnum[fmt_ulong(strnum,childpid)] = 0; + kill(childpid,SIGTERM); + logmsg(WHO,111,ERROR,B("unable to speak TLS with: ",remoteipstr," for pid: ",strnum," ",ERR_reason_error_string(ssl_errno))); + } + if (wait_nohang(&wstat) > 0) + _exit(wait_exitcode(wstat)); + ssl_close(ssl); + } + kill(childpid,SIGTERM); + _exit(0); + } + +/* Child-only below this point */ + + if (ip6_isv4mapped(remoteip)) + localipstr[ip4_fmt(localipstr,localip + 12)] = 0; + else + localipstr[ip6_fmt(localipstr,localip)] = 0; + localportstr[fmt_ulong(localportstr,localport)] = 0; + + if (socket_local(t,localip,&localport,&netif) == -1) + logmsg(WHO,111,FATAL,B("unable to set local address/port: ",localipstr,"/",localportstr)); + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + log_who(WHO,B("pid ",strnum," from ",remoteipstr)); + } + + if (!localhost) + if (dns_name(&localhostsa,localip) >= 0) + if (localhostsa.len) { + if (!stralloc_0(&localhostsa)) drop_nomem(); + localhost = localhostsa.s; + } + + remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; + +/* Setup environment variables */ + + env("PROTO","TLS"); + env("SSLLOCALIP",localipstr); + env("SSLLOCALPORT",localportstr); + env("SSLLOCALHOST",localhost); + env("SSLREMOTEIP",remoteipstr); + env("SSLREMOTEPORT",remoteportstr); + env("SSLREMOTEHOST",remotehost); + env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + + if (flagtcpenv) { + env("TCPLOCALIP",localipstr); + env("TCPLOCALPORT",localportstr); + env("TCPLOCALHOST",localhost); + env("TCPREMOTEIP",remoteipstr); + env("TCPREMOTEPORT",remoteportstr); + env("TCPREMOTEHOST",remotehost); + if (!ip6_isv4mapped(remoteip)) { + env("PROTO","TCP6"); + env("TCP6LOCALIP",localipstr); + env("TCP6LOCALHOST",localhost); + env("TCP6LOCALPORT",localportstr); + env("TCP6REMOTEIP",remoteipstr); + env("TCP6REMOTEPORT",remoteportstr); + env("TCP6REMOTEHOST",remotehost); + if (netif) + env("TCP6INTERFACE",socket_getifname(netif)); + } else + env("PROTO","TCP"); + env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); + } + + FINISH: + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + strnum2[fmt_ulong(strnum2,maxconip)] = 0; + if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem(); + safecats(flagdeny ? "deny" : "ok"); + cats(" "); safecats(strnum); + cats(" "); if (localhost) safecats(localhost); + cats(":"); safecats(localipstr); + cats(":"); safecats(localportstr); + cats(" "); if (remotehost) safecats(remotehost); + cats(":"); safecats(remoteipstr); + cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); + cats(":"); safecats(remoteportstr); + if (flagdeny == 2) { cats(" ip connection limit:"); cats(strnum2); cats(" exceeded"); } + cats("\n"); + buffer_putflush(buffer_2,tmp.s,tmp.len); + } + + if (flagdeny) _exit(100); + + if (gid) if (prot_gid(gid) == -1) + logmsg(WHO,111,FATAL,"unable to set gid"); + if (uid) if (prot_uid(uid) == -1) + logmsg(WHO,111,FATAL,"unable to set uid"); + + close(pi[1]); close(po[0]); close(sslctl[0]); + + sig_uncatch(sig_child); + sig_unblock(sig_child); + sig_uncatch(sig_term); + sig_uncatch(sig_pipe); + + if (fcntl(sslctl[1],F_SETFD,0) == -1) + logmsg(WHO,111,FATAL,"unable to clear close-on-exec flag"); + strnum[fmt_ulong(strnum,sslctl[1])] = 0; + env("SSLCTLFD",strnum); + + if (fcntl(pi[0],F_SETFD,0) == -1) + logmsg(WHO,111,FATAL,"unable to clear close-on-exec flag"); + strnum[fmt_ulong(strnum,pi[0])] = 0; + env("SSLREADFD",strnum); + + if (fcntl(po[1],F_SETFD,0) == -1) + logmsg(WHO,111,FATAL,"unable to clear close-on-exec flag"); + strnum[fmt_ulong(strnum,po[1])] = 0; + env("SSLWRITEFD",strnum); + + if (flagsslwait) { + if (fd_copy(0,t) == -1) + logmsg(WHO,111,FATAL,"unable to set up descriptor 0"); + if (fd_copy(1,t) == -1) + logmsg(WHO,111,FATAL,"unable to set up descriptor 1"); + } else { + if (fd_move(0,pi[0]) == -1) + logmsg(WHO,111,FATAL,"unable to set up descriptor 0"); + if (fd_move(1,po[1]) == -1) + logmsg(WHO,111,FATAL,"unable to set up descriptor 1"); + } + + if (flagkillopts) + socket_ipoptionskill(t); + + if (!flagdelay) + socket_tcpnodelay(t); + + if (*banner) { + buffer_init(&bo,buffer_unixwrite,1,bspace,sizeof(bspace)); + if (buffer_putsflush(&bo,banner) == -1) + logmsg(WHO,111,FATAL,"unable to print banner"); + } + + if (!flagsslwait) { + ssl_cmd = flagsslenv ? 'Y' : 'y'; + if (write(sslctl[1],&ssl_cmd,1) < 1) + logmsg(WHO,111,FATAL,"unable to start TLS"); + if (flagsslenv) { + while ((j = read(sslctl[1],envbuf,8192)) > 0) { + stralloc_catb(&ssl_env,envbuf,j); + if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len - 2] == 0 && ssl_env.s[ssl_env.len - 1] == 0) + break; + } + if (j < 0) + logmsg(WHO,111,FATAL,"unable to read TLS environment"); + pathexec_multienv(&ssl_env); + } + } + + pathexec(prog); + logmsg(WHO,111,FATAL,B("unable to run: ",*prog)); +} + +/* ---------------------------- parent */ + +void usage(void) +{ + logmsg(WHO,100,USAGE,"sslserver \ +[ -1346UXpPhHrRoOdDqQvVIeEsSnNmzZ ] \ +[ -c limit ] \ +[ -y iprules.cdb ] \ +[ -x rules.cdb ] \ +[ -B banner ] \ +[ -g gid ] \ +[ -u uid ] \ +[ -b backlog ] \ +[ -l localname ] \ +[ -t timeout ] \ +[ -I interface ] \ +[ -T ssltimeout ] \ +[ -w progtimeout ] \ +host port program"); +} + +int flag1 = 0; +int flag3 = 0; +unsigned long backlog = 20; + +void printstatus(void) +{ + if (verbosity < 2) return; + strnum[fmt_ulong(strnum,numchildren)] = 0; + strnum2[fmt_ulong(strnum2,limit)] = 0; + strnum3[fmt_ulong(strnum3,maxconip)] = 0; + log_who(WHO,B("status: ",strnum,"/",strnum2,"/",strnum3)); +} + +void sigterm(void) +{ + _exit(0); +} + +void sigchld(void) +{ + int wstat; + int pid; + + while ((pid = wait_nohang(&wstat)) > 0) { + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,pid + 1)] = 0; + strnum2[fmt_ulong(strnum2,wstat)] = 0; + log_who(WHO,B("ended by ",strnum," status ",strnum2)); + } + if (maxconip) ipchild_clear(remoteip); + if (numchildren) --numchildren; + printstatus(); + } +} + +void read_passwd(void) { + if (!password.len) { + buffer_init(&bo,buffer_unixread,3,bspace,sizeof(bspace)); + if (getln(&bo,&password,&match,'\0') == -1) + logmsg(WHO,111,ERROR,"unable to read password"); + close(3); + if (match) --password.len; + } +} + +int passwd_cb(char *buff,int size,int rwflag,void *userdata) { + if (size < password.len) + logmsg(WHO,111,ERROR,"password too long"); + + byte_copy(buff,password.len,password.s); + return password.len; +} + +int main(int argc,char * const *argv) { + int opt; + struct servent *se; + char *x; + unsigned long u = 0; + int j; + int s; + int t; + int ipflag = 0; + + while ((opt = getopt(argc,argv,"1346dDvVqQhHrRUXx:y:t:T:u:g:l:b:B:c:pPoOIEeSsw:nNzZm")) != opteof) + switch(opt) { + case 'b': scan_ulong(optarg,&backlog); break; + case 'c': scan_ulong(optarg,&limit); break; + case 'X': flagallownorules = 1; break; + case 'x': fnrules = optarg; break; + case 'y': fniprules = optarg; break; + case 'B': banner = optarg; break; + case 'd': flagdelay = 1; break; + case 'D': flagdelay = 0; break; + case 'v': verbosity = 2; break; + case 'V': verbosity = 3; break; + case 'q': verbosity = 0; break; + case 'Q': verbosity = 1; break; + case 'P': flagparanoid = 0; break; + case 'p': flagparanoid = 1; break; + case 'O': flagkillopts = 1; break; + case 'o': flagkillopts = 0; break; + case 'H': flagremotehost = 0; break; + case 'h': flagremotehost = 1; break; + case 'R': flagremoteinfo = 0; break; + case 'r': flagremoteinfo = 1; break; + case 't': scan_ulong(optarg,&timeout); break; + case 'T': scan_ulong(optarg,&ssltimeout); break; + case 'w': scan_uint(optarg,&progtimeout); break; + case 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid); + x = env_get("GID"); if (x) scan_ulong(x,&gid); break; + case 'u': scan_ulong(optarg,&uid); break; + case 'g': scan_ulong(optarg,&gid); break; + case 'I': netif = socket_getifidx(optarg); break; + case 'l': localhost = optarg; break; + case '1': flag1 = 1; break; + case '3': flag3 = 1; break; + case '4': ipflag = 1; break; + case '6': ipflag = 2; break; + case 'Z': flagclientcert = 0; break; + case 'z': flagclientcert = 1; break; + case 'm': flagclientcert = 2; break; + case 'S': flagsslenv = 0; break; + case 's': flagsslenv = 1; break; + case 'E': flagtcpenv = 0; break; + case 'e': flagtcpenv = 1; break; + case 'n': flagsslwait = 1; break; + case 'N': flagsslwait = 0; break; + default: usage(); + } + argc -= optind; + argv += optind; + + if (!verbosity) buffer_2->fd = -1; + + hostname = *argv++; + if (!hostname || (str_equal((char *)hostname,""))) usage(); + if (str_equal((char *)hostname,"0")) hostname = thishost; + else if (str_equal((char *)hostname,":0")) { + flagdualstack = 1; + hostname = "::"; + } + + x = *argv++; + if (!x) usage(); + prog = argv; + if (!*argv) usage(); + if (!x[scan_ulong(x,&u)]) + localport = u; + else { + se = getservbyname(x,"tcp"); + if (!se) + logmsg(WHO,111,FATAL,B("unable to figure out port number for: ",x)); + uint16_unpack_big((char *)&se->s_port,&localport); + } + + if ((x = env_get("MAXCONIP"))) { scan_ulong(x,&u); maxconip = u; } + if (limit && maxconip > limit) maxconip = limit; + if (!child_readyplus(&children,limit)) drop_nomem(); + + if ((x = env_get("VERIFYDEPTH"))) { scan_ulong(x,&u); verifydepth = u; } + + if ((x = env_get("CAFILE"))) cafile = x; + if (cafile && str_equal((char *)cafile,"")) cafile = 0; + + if ((x = env_get("CCAFILE"))) ccafile = x; + if (ccafile && str_equal((char *)ccafile,"")) ccafile = 0; + if (ccafile && str_equal((char*)ccafile,"-")) flagclientcert = 0; + if (!flagclientcert) ccafile = 0; + + if ((x = env_get("CADIR"))) cadir = x; + if (cadir && str_equal((char *)cadir,"")) cadir= 0; + + if ((x = env_get("CERTCHAINFILE"))) certchainfile = x; + if (certchainfile && str_equal((char *)certchainfile,"")) certchainfile = 0; + + if ((x = env_get("CERTFILE"))) certfile = x; + if (certfile && str_equal((char *)certfile,"")) certfile = 0; + + if ((x = env_get("KEYFILE"))) keyfile = x; + if (keyfile && str_equal((char *)keyfile,"")) keyfile = 0; + + if ((x = env_get("DHFILE"))) dhfile = x; + if (dhfile && str_equal((char *)dhfile,"")) dhfile = 0; + + if ((x = env_get("CIPHERS"))) ciphers = x; + if (ciphers && str_equal((char *)ciphers,"")) ciphers = 0; + + sig_block(sig_child); + sig_catch(sig_child,sigchld); + sig_catch(sig_term,sigterm); + sig_ignore(sig_pipe); + + /* IP address only */ + + if (ip4_scan(hostname,localip)) { + if (!stralloc_copyb(&addresses,(char *)V4mappedprefix,12)) drop_nomem(); + if (!stralloc_catb(&addresses,localip,4)) drop_nomem(); + byte_copy(localip,16,addresses.s); + } else if (ip6_scan(hostname,localip)) { + if (!stralloc_copyb(&addresses,localip,16)) drop_nomem(); + byte_copy(localip,16,addresses.s); + } + + /* Asynchronous DNS IPv4/IPv6 Name qualification */ + + if (!addresses.len) { + if (!stralloc_copys(&tmp,hostname)) drop_nomem(); + if (dns_ip_qualify(&addresses,&fqdn,&tmp) < 0) + logmsg(WHO,111,FATAL,B("temporarily unable to figure out IP address for: ",(char *)hostname)); + + byte_copy(localip,16,addresses.s); + + for (j = 0; j < addresses.len; j += 16) { // Select best matching IP address + if (ipflag == 1 && !ip6_isv4mapped(addresses.s + j)) continue; + if (ipflag == 2 && !ip6_isv4mapped(addresses.s + j)) continue; + byte_copy(localip,16,addresses.s + j); + } + + } + if (addresses.len < 16) + logmsg(WHO,111,FATAL,B("no IP address for: ",(char *)hostname)); + + if (ip6_isv4mapped(localip)) + s = socket_tcp4(); + else + s = socket_tcp6(); + if (s == -1) + logmsg(WHO,111,FATAL,"unable to create socket"); + + if (ip6_isv4mapped(localip)) + localipstr[ip4_fmt(localipstr,localip + 12)] = 0; + else + localipstr[ip6_fmt(localipstr,localip)] = 0; + localportstr[fmt_ulong(localportstr,localport)] = 0; + + if (flagdualstack) + socket_dualstack(s); + if (socket_bind_reuse(s,localip,localport,netif) == -1) + logmsg(WHO,111,FATAL,B("unable to bind to: ",localipstr," port: ",localportstr)); + if (socket_local(s,localip,&localport,&netif) == -1) + logmsg(WHO,111,FATAL,B("unable to set local address/port: ",localipstr,"/",localportstr)); + if (socket_listen(s,backlog) == -1) + logmsg(WHO,111,FATAL,"unable to listen"); + ndelay_off(s); + + if (flag1) { + buffer_init(&bo,write,1,bspace,sizeof(bspace)); + buffer_puts(&bo,localipstr); + buffer_puts(&bo," : "); + buffer_puts(&bo,localportstr); + buffer_puts(&bo,"\n"); + buffer_flush(&bo); + } + + if (flag3) read_passwd(); + + ctx = ssl_server(); + ssl_errstr(); + if (!ctx) logmsg(WHO,111,FATAL,"unable to create TLS context"); + + if (certchainfile) { + switch (ssl_chainfile(ctx,certchainfile,keyfile,passwd_cb)) { + case -1: logmsg(WHO,111,ERROR,"unable to load certificate chain file"); + case -2: logmsg(WHO,111,ERROR,"unable to load key"); + case -3: logmsg(WHO,111,ERROR,"key does not match certificate"); + default: break; + } + } else { + switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) { + case -1: logmsg(WHO,111,ERROR,"unable to load certificate"); + case -2: logmsg(WHO,111,ERROR,"unable to load key"); + case -3: logmsg(WHO,111,ERROR,"key does not match certificate"); + default: break; + } + } + + if (flagclientcert && !ssl_ca(ctx,cafile,cadir,verifydepth)) + logmsg(WHO,111,ERROR,"unable to load CA list"); + if (!ssl_cca(ctx,ccafile)) + logmsg(WHO,111,ERROR,"unable to load client CA list"); + if (!ssl_params_rsa(ctx,rsalen)) + logmsg(WHO,111,ERROR,"unable to set RSA parameters"); + if (!ssl_params_dh(ctx,dhfile)) + logmsg(WHO,111,ERROR,"unable to set DH parameters"); + if (!ssl_ciphers(ctx,ciphers)) + logmsg(WHO,111,ERROR,"unable to set cipher list"); + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + strnum2[fmt_ulong(strnum2,rsalen)] = 0; + log_who(WHO,B("ciphers ",strnum," ",(char *)ciphers)); + log_who(WHO,B("cafile ",strnum," ",(char *)cafile)); + log_who(WHO,B("ccafile ",strnum," ",(char *)ccafile)); + log_who(WHO,B("cadir ",strnum," ",(char *)cadir)); + log_who(WHO,B("certchainfile ",strnum," ",(char *)certchainfile)); + log_who(WHO,B("cert ",strnum," ",(char *)certfile)); + log_who(WHO,B("key ",strnum," ",(char *)keyfile)); + log_who(WHO,B("dhparam ",strnum," ",(char *)dhfile," ",strnum2)); + } + + close(0); open_read("/dev/null"); + close(1); open_append("/dev/null"); + + printstatus(); + + for (;;) { + while (numchildren >= limit) sig_pause(); + strnum[fmt_ulong(x,numchildren)] = 0; + + sig_unblock(sig_child); + t = socket_accept(s,remoteip,&remoteport,&netif); + sig_block(sig_child); + if (t == -1) continue; + + if (maxconip) { + ipchildren = ipchild_limit(remoteip,numchildren); + if (ipchildren >= maxconip) { + if (ip6_isv4mapped(remoteip)) + remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0; + else + remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; + + strnum[fmt_ulong(strnum,maxconip)] = 0; + logmsg(WHO,100,WARN,B("ip connection limit of ",strnum," exceeded for: ",remoteipstr)); + close(t); + continue; + } + ipchild_append(remoteip,numchildren); // needs to happen in parent + } + ++numchildren; + printstatus(); + + switch (fork()) { + case 0: + close(s); + doit(t); + logmsg(WHO,111,FATAL,B("unable to run: ",*argv)); + case -1: + if (maxconip) ipchild_clear(remoteip); --numchildren; + logmsg(WHO,111,FATAL,B("unable to fork: ",strnum)); + } + close(t); + } +} diff --git a/src/trycpp.c b/src/trycpp.c new file mode 100644 index 0000000..e4503d4 --- /dev/null +++ b/src/trycpp.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +int main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} diff --git a/src/trylsock.c b/src/trylsock.c new file mode 100644 index 0000000..c32bd40 --- /dev/null +++ b/src/trylsock.c @@ -0,0 +1,4 @@ +int main() +{ + ; +} diff --git a/src/trysgact.c b/src/trysgact.c new file mode 100644 index 0000000..e264ef2 --- /dev/null +++ b/src/trysgact.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <signal.h> + +main() +{ + struct sigaction sa; + sa.sa_handler = 0; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(0,&sa,(struct sigaction *) 0); +} diff --git a/src/trysgprm.c b/src/trysgprm.c new file mode 100644 index 0000000..a46c82c --- /dev/null +++ b/src/trysgprm.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <signal.h> + +main() +{ + sigset_t ss; + + sigemptyset(&ss); + sigaddset(&ss,SIGCHLD); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +} diff --git a/src/tryshsgr.c b/src/tryshsgr.c new file mode 100644 index 0000000..c5ed6d6 --- /dev/null +++ b/src/tryshsgr.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +int main() +{ + short x[4]; + + x[0] = x[1] = 1; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 1) _exit(1); + x[1] = 2; + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 2) _exit(1); + _exit(0); +} diff --git a/src/tryssl.c b/src/tryssl.c new file mode 100644 index 0000000..81dc4d1 --- /dev/null +++ b/src/tryssl.c @@ -0,0 +1,6 @@ +#include <openssl/ssl.h> + +int main() +{ + ; +} diff --git a/src/trysysel.c b/src/trysysel.c new file mode 100644 index 0000000..5be862d --- /dev/null +++ b/src/trysysel.c @@ -0,0 +1,11 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <time.h> +#include <sys/time.h> +#include <sys/select.h> /* SVR4 silliness */ + +void foo() +{ + ; +} diff --git a/src/tryvfork.c b/src/tryvfork.c new file mode 100644 index 0000000..cc39699 --- /dev/null +++ b/src/tryvfork.c @@ -0,0 +1,4 @@ +main() +{ + vfork(); +} diff --git a/src/ucspissl.c b/src/ucspissl.c new file mode 100644 index 0000000..3cbd8b4 --- /dev/null +++ b/src/ucspissl.c @@ -0,0 +1,4 @@ +#include "ucspissl.h" + +int ssl_errno = 0; + diff --git a/src/ucspissl.h b/src/ucspissl.h new file mode 100644 index 0000000..5243689 --- /dev/null +++ b/src/ucspissl.h @@ -0,0 +1,70 @@ +/** + @file ucspissl.h + @author web, feh + @brief Header file to be used with sqmail; previously called ssl.h. (name clash) + + All OpenSSL/LibreSSL header files are called from here +*/ +#ifndef UCSPISSL_H +#define UCSPISSL_H + +#include "openssl/asn1.h" +#include "openssl/ec.h" +#include "openssl/err.h" +#include "openssl/evp.h" +#include "openssl/ssl.h" +#include "openssl/pem.h" +#include "openssl/rsa.h" +#include "openssl/opensslv.h" +#include "openssl/safestack.h" +#include "openssl/x509.h" +#include "openssl/x509v3.h" +#include "stralloc.h" + +#define SSLv2_DISABLE +#define SSLv3_DISABLE +// #define TLSv1_DISABLE +// #define TLSv1_1_DISABLE +// #define TLSv1_2_DISABLE +// #define TLSv1_3_DISABLE + +#define SSL_NAME_LEN 256 +#define SSL_RSA_LEN 4096 + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) // 0xmnnffppsL +#define ssl_client() (ssl_context(SSLv23_client_method())) +#define ssl_server() (ssl_context(SSLv23_server_method())) +#else +#define ssl_client() (ssl_context(TLS_client_method())) +#define ssl_server() (ssl_context(TLS_server_method())) +#endif + +extern int ssl_errno; +extern int ssl_io(SSL *,int,int,unsigned int); +extern SSL_CTX *ssl_context(const SSL_METHOD *); +extern int ssl_timeoutconn(SSL *,unsigned int); +extern int ssl_timeoutaccept(SSL *,unsigned int); +extern SSL *ssl_new(SSL_CTX *,int); +extern int ssl_certkey(SSL_CTX *,const char *,const char *,pem_password_cb *); +extern int ssl_chainfile(SSL_CTX *,const char *,const char *,pem_password_cb *); +extern int ssl_ca(SSL_CTX *,const char *,const char *,int); +extern int ssl_cca(SSL_CTX *,const char *); +extern int ssl_ciphers(SSL_CTX *,const char *); +extern int ssl_verify(SSL *,const char *,stralloc *); +extern int ssl_params_rsa(SSL_CTX *,int); +extern int ssl_params_dh(SSL_CTX *,const char *); +extern int ssl_server_env(SSL *,stralloc *); +extern int ssl_client_env(SSL *,stralloc *); +extern int ssl_error(int (*)(const char *)); +extern char *ssl_error_str(int); + +#define ssl_errstr() (SSL_load_error_strings()) +#define ssl_free(ssl) (SSL_free((ssl))) +#define ssl_close(ssl) (close(SSL_get_fd((ssl)))) + +#define ssl_pending(ssl) (SSL_pending((ssl))) +#define ssl_shutdown(ssl) (SSL_shutdown((ssl))) +#define ssl_shutdown_pending(ssl) (SSL_get_shutdown((ssl)) & SSL_RECEIVED_SHUTDOWN) +#define ssl_shutdown_sent(ssl) (SSL_get_shutdown((ssl)) & SSL_SENT_SHUTDOWN) + +#endif diff --git a/src/warn-auto.sh b/src/warn-auto.sh new file mode 100644 index 0000000..36d2313 --- /dev/null +++ b/src/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! diff --git a/src/warn-shsgr b/src/warn-shsgr new file mode 100644 index 0000000..37c351e --- /dev/null +++ b/src/warn-shsgr @@ -0,0 +1,3 @@ +Oops. Your getgroups() returned 0, and setgroups() failed; this means +that I can't reliably do my shsgr test. Please either ``make'' as root +or ``make'' while you're in one or more supplementary groups. diff --git a/src/x86cpuid.c b/src/x86cpuid.c new file mode 100644 index 0000000..f81c593 --- /dev/null +++ b/src/x86cpuid.c @@ -0,0 +1,40 @@ +/* Public domain. */ + +#include <signal.h> + +void nope() +{ + exit(1); +} + +int main() +{ + unsigned long x[4]; + unsigned long y[4]; + int i; + int j; + char c; + + signal(SIGILL,nope); + + x[0] = 0; + x[1] = 0; + x[2] = 0; + x[3] = 0; + + asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) ); + if (!x[0]) return 0; + asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) ); + + for (i = 1;i < 4;++i) + for (j = 0;j < 4;++j) { + c = x[i] >> (8 * j); + if (c < 32) c = 32; + if (c > 126) c = 126; + putchar(c); + } + + printf("-%08x-%08x\n",y[0],y[3]); + + return 0; +} |