From 5d614f2ac301ffdb83b1f37a872b3a0fd89f08cd Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Wed, 15 Feb 2017 14:38:13 +1300 Subject: Add osc(1df) --- README.markdown | 2 ++ bin/osc | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ man/man1/osc.1df | 22 +++++++++++++++ 3 files changed, 110 insertions(+) create mode 100755 bin/osc create mode 100644 man/man1/osc.1df diff --git a/README.markdown b/README.markdown index 586594a4..bce41cd0 100644 --- a/README.markdown +++ b/README.markdown @@ -483,6 +483,8 @@ Installed by the `install-bin` target: * `mkmv(1df)` creates a directory and moves preceding arguments into it. * `motd(1df)` shows the system MOTD. * `onl(1df)` crunches input down to one printable line. +* `osc(1df)` implements a `netcat(1)`-like wrapper for `openssl(1)`'s + `s_client` subcommand. * `pa(1df)` prints its arguments, one per line. * `pp(1df)` prints the full path of each argument using `$PWD`. * `pph(1df)` runs `pp(1df)` and includes a leading `$HOSTNAME:`. diff --git a/bin/osc b/bin/osc new file mode 100755 index 00000000..c1fe6ed0 --- /dev/null +++ b/bin/osc @@ -0,0 +1,86 @@ +#!/bin/sh +# Sane and safe OpenSSL s_client(1ssl) connection +self=osc + +# Check we have openssl(1); we need to fail early lest we go setting up FIFOs +# needlessly +if ! command -v openssl >/dev/null 2>&1 ; then + printf >&2 '%s: openssl(1) not found in $PATH\n' + exit 1 +fi + +# Hostname is first argument; assume localhost if empty/unset +host=${1:-localhost} +# Service name or port is second argument; assume HTTPS if empty/unset +serv=${2:-https} + +# Start building the command-line string +set -- +## If we have rlwrap, use it, but don't complain if we don't +if command -v rlwrap >/dev/null 2>&1 ; then + set -- "$@" rlwrap +fi +## The actual openssl(1ssl) and subcommand call +set -- "$@" openssl s_client +## No insecure SSL methods +set -- "$@" -no_ssl2 -no_ssl3 +## Don't dump nonsense to terminal, and don't renegotiate on R or quit on Q +set -- "$@" -quiet +## But do cut the connection if I issue ^D, even though I just set -quiet +set -- "$@" -no_ign_eof +## Do verify the certificate chain and don't connect if we can't +set -- "$@" -verify 5 -verify_return_error +## We might add STARTTLS for the supported services: +case $serv in + ftp|21) + set -- "$@" -starttls ftp + ;; + smtp|25) + set -- "$@" -starttls smtp + ;; + pop3|110) + set -- "$@" -starttls pop3 + ;; + imap|143) + set -- "$@" -starttls imap + ;; +esac +## Finally, add the host and service to connect to +set -- "$@" -connect "$host":"$serv" + +# Do the POSIX dance to kill child processes and clean up temp files even if +# killed by a signal +td= fil= +cleanup() { + trap - EXIT "$1" + [ -n "$fil" ] && kill -TERM "$fil" + [ -n "$td" ] && rm -fr -- "$td" + if [ "$1" != EXIT ] ; then + kill -"$1" "$$" + fi +} +for sig in EXIT HUP INT TERM ; do + trap "cleanup $sig" "$sig" +done + +# Create a temporary directory and a FIFO in it +td=$(mktd "$self") || exit +mkfifo -- "$td"/verify-filter || exit + +# Open a read-write file descriptor onto the FIFO +exec 3<>"$td"/verify-filter || exit + +# Start a background filter process on the FIFO to get rid of the leading +# verification output set to stderr; as soon as we find a single line that +# doesn't look like that routine output, print all future lines to stderr as +# normal +awk ' +body{print;next} +/^verify depth is [0-9]+$/{next} +/^depth=[0-9]+ /{next} +/^verify return:[0-9]+$/{next} +{body=1;print} +' <&3 >&2 & fil=$! + +# Start the process with the options we stacked up +"$@" 2>&3 diff --git a/man/man1/osc.1df b/man/man1/osc.1df new file mode 100644 index 00000000..9fb61dde --- /dev/null +++ b/man/man1/osc.1df @@ -0,0 +1,22 @@ +.TH OSC 1df "February 2017" "Manual page for osc" +.SH NAME +.B osc +\- netcat-like wrapper for openssl s_client +.SH SYNOPSIS +.B osc [HOST [SERVICE]] +.SH DESCRIPTION +.B osc +runs openssl(1ssl)'s s_client subcommand with some options to make it behave a +bit like netcat(1), quieting errors and even handling STARTTLS if it knows how, +but still forcing correct verification of certificates and only connecting with +TLS (not SSL). +.P +If rlwrap(1) is available, the client will be run within that to allow line +editing. +.P +It's intended to be run as an interactive tool for cases where you want to +focus more on debugging the data exchange with the actual server, and not +debugging the OpenSSL negotiation itself. The author finds it handy for poking +his STARTTLS SMTP mailserver. +.SH AUTHOR +Tom Ryder -- cgit v1.2.3