# --- SDE-COPYRIGHT-NOTE-BEGIN --- # This copyright note is auto-generated by ./scripts/Create-CopyPatch. # # Filename: package/.../ucspi-ssl/ucspi-ssl-0.70.2-UCSPI-TLS.patch # Copyright (C) 2011 The OpenSDE Project # # More information can be found in the files COPYING and README. # # This patch file is dual-licensed. It is available under the license the # patched project is licensed under, as long as it is an OpenSource license # as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms # of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # --- SDE-COPYRIGHT-NOTE-END --- From f9051950183f6bee0624c3d8fdef2e1cd70c5135 Mon Sep 17 00:00:00 2001 From: Christian Wiese Date: Wed, 16 Nov 2011 17:39:24 +0100 Subject: [PATCH 1/2] added UCSPI-TLS support by appyling changes made by Scott Gifford Note: original tarball including UCSPI-TLS support: http://www.suspectclass.com/sgifford/ucspi-tls/files/ucspi-ssl-0.70.2-sg.tar.gz see: http://www.suspectclass.com/sgifford/ucspi-tls/ --- src/CHANGES | 5 +- src/Makefile | 27 ++++-- src/conf-ld | 2 +- src/conf-ld~ | 3 + src/ssl.h | 2 +- src/sslclient.c | 200 ++++++++++++++++++++++++++++------------ src/sslperl.c | 1 + src/sslserver.c | 244 ++++++++++++++++++++++++++++++++----------------- src/ucspissltest.c | 206 +++++++++++++++++++++++++++++++++++++++++ src/ucspitls.c | 107 +++++++++++++++++++++ src/ucspitls.h | 1 + src/ucspitls_master.c | 44 +++++++++ src/ucspitls_master.h | 1 + 13 files changed, 687 insertions(+), 156 deletions(-) create mode 100644 src/conf-ld~ create mode 100644 src/ucspissltest.c create mode 100644 src/ucspitls.c create mode 100644 src/ucspitls.h create mode 100644 src/ucspitls_master.c create mode 100644 src/ucspitls_master.h diff --git ucspi-ssl-0.70.2/src/CHANGES ucspi-ssl-0.70.2-tls/src/CHANGES index b9c54a0..1d88cb3 100644 --- ucspi-ssl-0.70.2/src/CHANGES +++ ucspi-ssl-0.70.2-tls/src/CHANGES @@ -89,4 +89,7 @@ Add () around args to barf in makeinclude.sh (Peter Conrad). Version 0.70.2. - +20110901 + Add support for UCSPI-TLS in server (Scott Gifford) + Add support for UCSPI-TLS in client (Scott Gifford, sponsored by Meixler Technologies, Inc.) + For details see: http://www.suspectclass.com/sgifford/ucspi-tls/ \ No newline at end of file diff --git ucspi-ssl-0.70.2/src/Makefile ucspi-ssl-0.70.2-tls/src/Makefile index a563ea3..2246751 100644 --- ucspi-ssl-0.70.2/src/Makefile +++ ucspi-ssl-0.70.2-tls/src/Makefile @@ -37,7 +37,8 @@ clean: tai_pack.o taia_add.o taia_approx.o taia_frac.o taia_less.o taia_now.o \ taia_pack.o taia_sub.o taia_uint.o timeoutconn.o uint16_pack.o \ uint16_unpack.o uint32.h uint32_pack.o uint32_unpack.o uint64.h unix.a \ - wait_nohang.o wait_pid.o + wait_nohang.o wait_pid.o tryssl.o \ + ucspissltest ucspissltest.o ucspitls.o addcr: load addcr.o unix.a ./load addcr unix.a @@ -337,7 +338,7 @@ ip4_scan.o: compile ip4_scan.c scan.h ip4.h ./compile ip4_scan.c it: sysdeps sslclient sslserver https@ sslcat sslconnect sslprint \ -connect-io addcr delcr sslperl +connect-io addcr delcr sslperl ucspissltest load: conf-ld print-ld.sh systype warn-auto.sh rm -f load @@ -537,9 +538,9 @@ sslcat: makeinclude makescrip warn-auto.sh sslcat.sh chmod 755 sslcat sslclient: load sslclient.o remoteinfo.o timeoutconn.o ssl.a unix.a \ -auto_cafile.o auto_cadir.o auto_ciphers.o socket.lib ssl.lib +auto_cafile.o auto_cadir.o auto_ciphers.o wait_nohang.o ucspitls_master.o socket.lib ssl.lib ./load sslclient remoteinfo.o timeoutconn.o ssl.a unix.a auto_cafile.o \ - auto_cadir.o auto_ciphers.o `cat socket.lib` `cat ssl.lib` + auto_cadir.o auto_ciphers.o wait_nohang.o ucspitls_master.o `cat socket.lib` `cat ssl.lib` sslclient.o: compile sslclient.c ssl.h sig.h exit.h sgetopt.h uint16.h \ fmt.h scan.h str.h ip4.h uint16.h socket.h fd.h stralloc.h buffer.h \ @@ -594,10 +595,10 @@ sslprint.o: compile sslprint.c buffer.h env.h sslserver: load sslserver.o auto_cafile.o auto_ccafile.o auto_cadir.o \ auto_dhfile.o auto_certfile.o auto_keyfile.o auto_ciphers.o rules.o \ -remoteinfo.o timeoutconn.o cdb.a ssl.a unix.a socket.lib ssl.lib +remoteinfo.o timeoutconn.o wait_nohang.o ucspitls_master.o ucspitls.o cdb.a ssl.a unix.a socket.lib ssl.lib ./load sslserver auto_cafile.o auto_ccafile.o auto_cadir.o auto_dhfile.o \ auto_certfile.o auto_keyfile.o auto_ciphers.o rules.o remoteinfo.o \ - timeoutconn.o cdb.a ssl.a unix.a `cat socket.lib` `cat ssl.lib` + timeoutconn.o wait_nohang.o ucspitls_master.o ucspitls.o cdb.a ssl.a unix.a `cat socket.lib` `cat ssl.lib` sslserver.o: compile sslserver.c ssl.h uint16.h str.h byte.h fmt.h scan.h \ ip4.h fd.h exit.h env.h prot.h open.h wait.h stralloc.h alloc.h buffer.h \ @@ -607,7 +608,7 @@ auto_ccafile.h auto_dhfile.h auto_certfile.h auto_keyfile.h \ auto_ciphers.h stralloc.h gen_alloc.h buffer.h stralloc.h subgetopt.h \ uint16.h stralloc.h uint16.h stralloc.h stralloc.h iopause.h taia.h \ gen_alloc.h gen_alloc.h gen_alloc.h gen_alloc.h gen_alloc.h taia.h tai.h \ -tai.h uint64.h uint64.h +tai.h uint64.h uint64.h ucspitls.h ./compile sslserver.c str_chr.o: compile str_chr.c str.h @@ -762,3 +763,15 @@ wait_nohang.o: compile wait_nohang.c haswaitp.h wait_pid.o: compile wait_pid.c error.h haswaitp.h ./compile wait_pid.c + +ucspissltest.o: ucspissltest.c ucspitls.h + ./compile ucspissltest.c + +ucspitls.o: ucspitls.c ucspitls.h + ./compile ucspitls.c + +ucspitls_master.o: ucspitls_master.c ucspitls_master.h wait.h strerr.h + ./compile ucspitls_master.c + +ucspissltest: load ucspissltest.o ucspitls.o sgetopt.o sgetopt.h subgetopt.h subgetopt.o buffer.o buffer_2.o + ./load ucspissltest ucspitls.o unix.a diff --git ucspi-ssl-0.70.2/src/conf-ld ucspi-ssl-0.70.2-tls/src/conf-ld index 59a0de7..3d700b6 100644 --- ucspi-ssl-0.70.2/src/conf-ld +++ ucspi-ssl-0.70.2-tls/src/conf-ld @@ -1,3 +1,3 @@ -gcc -s +gcc This will be used to link .o files into an executable. diff --git ucspi-ssl-0.70.2/src/conf-ld~ ucspi-ssl-0.70.2-tls/src/conf-ld~ new file mode 100644 index 0000000..1d0518a --- /dev/null +++ ucspi-ssl-0.70.2-tls/src/conf-ld~ @@ -0,0 +1,3 @@ +gcc + +This will be used to link .o files into an executable. diff --git ucspi-ssl-0.70.2/src/ssl.h ucspi-ssl-0.70.2-tls/src/ssl.h index 907a3aa..a92d106 100644 --- ucspi-ssl-0.70.2/src/ssl.h +++ ucspi-ssl-0.70.2-tls/src/ssl.h @@ -20,7 +20,7 @@ extern int ssl_verify(SSL *,const char *); extern int ssl_params(SSL_CTX *,const char *,int); extern int ssl_server_env(SSL *,stralloc *); extern int ssl_client_env(SSL *,stralloc *); -extern void ssl_error_str(); +extern char *ssl_error_str(int); extern int ssl_error(int (*)(const char *)); #define ssl_client() (ssl_context(SSLv23_client_method())) diff --git ucspi-ssl-0.70.2/src/sslclient.c ucspi-ssl-0.70.2-tls/src/sslclient.c index ed35bda..0feb3d2 100644 --- ucspi-ssl-0.70.2/src/sslclient.c +++ ucspi-ssl-0.70.2-tls/src/sslclient.c @@ -31,6 +31,7 @@ #include "byte.h" #include "ndelay.h" #include "wait.h" +#include "ucspitls_master.h" #define FATAL "sslclient: fatal: " #define CONNECT "sslclient: unable to connect to " @@ -71,6 +72,7 @@ int flagremotehost = 1; int flag3 = 0; int flagsslenv = 0; int flagtcpenv = 0; +int flagsslwait = 0; unsigned long itimeout = 26; unsigned long ctimeout[2] = { 2, 58 }; unsigned int progtimeout = 3600; @@ -130,6 +132,62 @@ int passwd_cb(char *buf,int size,int rwflag,void *userdata) { return password.len; } +SSL *start_ssl(int s) { + int cloop; + SSL *ssl; + + ctx = ssl_client(); + ssl_errstr(); + if (!ctx) + strerr_die2x(111,FATAL,"unable to create SSL context"); + + switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) { + case -1: strerr_die2x(111,FATAL,"unable to load certificate"); + case -2: strerr_die2x(111,FATAL,"unable to load key pair"); + case -3: strerr_die2x(111,FATAL,"key does not match certificate"); + default: break; + } + + if (!ssl_ca(ctx,cafile,cadir,verifydepth)) + strerr_die2x(111,FATAL,"unable to load CA list"); + + if (!ssl_ciphers(ctx,ciphers)) + strerr_die2x(111,FATAL,"unable to set cipher list"); + + ssl = ssl_new(ctx,s); + if (!ssl) strerr_die2x(111,FATAL,"unable to create SSL instance"); + + for (cloop = 0;cloop < 2;++cloop) { + if (!ssl_timeoutconn(ssl,ctimeout[cloop])) goto SSLCONNECTED; + if (!cloop && ctimeout[1]) continue; + strerr_warn2(FATAL,"unable to SSL connect:",&strerr_sys); + ssl_error(error_warn); + } + return NULL; /* Failure */ + + SSLCONNECTED: + ndelay_off(s); + + if (verbosity >= 2) + strerr_warn1("sslclient: ssl connect",0); + + if (flagservercert) + switch(ssl_verify(ssl,flagname ? hostname : 0)) { + case -1: + strerr_die2x(111,FATAL,"unable to verify server certificate"); + case -2: + strerr_die2x(111,FATAL,"no server certificate"); + case -3: + strerr_die2x(111,FATAL,"server name does not match certificate"); + default: break; + } + + if (!flagdelay) + socket_tcpnodelay(s); /* if it fails, bummer */ + + return ssl; +} + int main(int argc,char * const *argv) { unsigned long u; int opt; @@ -137,8 +195,12 @@ int main(int argc,char * const *argv) { int j; int s; int cloop; - SSL *ssl; + SSL *ssl = NULL; int wstat; + int sslctl[2]; + char sslctl_cmd; + stralloc ssl_env = { 0 }; + buffer ssl_env_buf; dns_random_init(seed); @@ -146,7 +208,7 @@ int main(int argc,char * const *argv) { close(7); sig_ignore(sig_pipe); - while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:a:A:c:C:k:V:3eEsSnN0xXw:")) != opteof) + while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:a:A:c:C:k:V:3eEsSnN0xXw:yY")) != opteof) switch(opt) { case 'd': flagdelay = 1; break; case 'D': flagdelay = 0; break; @@ -181,6 +243,8 @@ int main(int argc,char * const *argv) { case 'n': flagname = 1; break; case 'x': flagservercert = 1; break; case 'X': flagservercert = 0; break; + case 'y': flagsslwait = 1; break; + case 'Y': flagsslwait = 0; break; default: usage(); } argv += optind; @@ -305,57 +369,24 @@ int main(int argc,char * const *argv) { } env("SSLREMOTEINFO",x); if (flagtcpenv) env("TCPREMOTEINFO",x); - - ctx = ssl_client(); - ssl_errstr(); - if (!ctx) - strerr_die2x(111,FATAL,"unable to create SSL context"); - - switch (ssl_certkey(ctx,certfile,keyfile,passwd_cb)) { - case -1: strerr_die2x(111,FATAL,"unable to load certificate"); - case -2: strerr_die2x(111,FATAL,"unable to load key pair"); - case -3: strerr_die2x(111,FATAL,"key does not match certificate"); - default: break; - } - - if (!ssl_ca(ctx,cafile,cadir,verifydepth)) - strerr_die2x(111,FATAL,"unable to load CA list"); - - if (!ssl_ciphers(ctx,ciphers)) - strerr_die2x(111,FATAL,"unable to set cipher list"); - - ssl = ssl_new(ctx,s); - if (!ssl) strerr_die2x(111,FATAL,"unable to create SSL instance"); - - for (cloop = 0;cloop < 2;++cloop) { - if (!ssl_timeoutconn(ssl,ctimeout[cloop])) goto SSLCONNECTED; - if (!cloop && ctimeout[1]) continue; - strerr_warn2(FATAL,"unable to SSL connect:",&strerr_sys); - ssl_error(error_warn); - } - - _exit(111); - - SSLCONNECTED: - - ndelay_off(s); - - if (verbosity >= 2) - strerr_warn1("sslclient: ssl connect",0); - - if (flagservercert) - switch(ssl_verify(ssl,flagname ? hostname : 0)) { - case -1: - strerr_die2x(111,FATAL,"unable to verify server certificate"); - case -2: - strerr_die2x(111,FATAL,"no server certificate"); - case -3: - strerr_die2x(111,FATAL,"server name does not match certificate"); - default: break; + + if (flagsslwait) { + /* Create delayed SSL control socket */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,FATAL,"unable to create socketpair: "); + + /* Copy the socket to file descriptors 6 and 7 right now, so we + * don't use them for something else later. + */ + if (fd_copy(6,s) == -1) + strerr_die2sys(111,FATAL,"unable to set up descriptor 6: "); + if (fd_copy(7,s) == -1) + strerr_die2sys(111,FATAL,"unable to set up descriptor 7: "); + } else { + /* If we aren't delaying SSL, start it now, so we won't run the client if it fails */ + if (!(ssl = start_ssl(s))) { + _exit(111); } - - if (!flagdelay) - socket_tcpnodelay(s); /* if it fails, bummer */ + } if (pipe(pi) == -1) strerr_die2sys(111,FATAL,"unable to create pipe: "); if (pipe(po) == -1) strerr_die2sys(111,FATAL,"unable to create pipe: "); @@ -372,11 +403,47 @@ int main(int argc,char * const *argv) { switch(opt = fork()) { case -1: + /* Error */ strerr_die2sys(111,FATAL,"unable to fork: "); case 0: + /* Child runs after switch */ break; default: + /* Parent */ close(pi[0]); close(po[1]); + if (flagsslwait) { + if (close(sslctl[1]) != 0) { + strerr_die2sys(111, FATAL, "Error closing SSL control socket: "); + } + + /* This will exit on a fatal error or if the client quits + * without activating SSL + */ + sslctl_cmd = ucspitls_master_wait_for_activation(sslctl[0]); + + /* If we got here, SSL has been requested. */ + if (!(ssl = start_ssl(s))) { + _exit(111); + } + + if (sslctl_cmd == 'Y') { + if (!ssl_client_env(ssl, &ssl_env)) nomem(); + stralloc_0(&ssl_env); /* Add another NUL */ + buffer_init(&ssl_env_buf,buffer_unixwrite,sslctl[0],NULL,0); + if (buffer_putflush(&ssl_env_buf, ssl_env.s, ssl_env.len) == -1) { + strerr_die2sys(111, FATAL, "unable to write SSL environment: "); + } + } else if (sslctl_cmd != 'y') { + strerr_die2x(111,FATAL,"Unrecognized command on SSL socket"); + } + if (close(sslctl[0]) != 0) { + strerr_die2sys(111, FATAL, "Error closing SSL control socket: "); + } + } + + if (verbosity >= 2) + strerr_warn1("sslclient: ssl_io starting",0); + if (ssl_io(ssl,pi[1],po[0],progtimeout)) { strerr_warn2(FATAL,"unable to speak SSL:",&strerr_sys); ssl_error(error_warn); @@ -389,17 +456,28 @@ int main(int argc,char * const *argv) { _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) - strerr_die2sys(111,FATAL,"unable to set up descriptor 6: "); - if (fd_move(7,po[1]) == -1) - strerr_die2sys(111,FATAL,"unable to set up descriptor 7: "); + + /* Child */ + close(pi[1]); close(po[0]); close(sslctl[0]); + + if (flagsslwait) { + strnum[fmt_ulong(strnum,sslctl[1])]=0; + env("SSLCTLFD",strnum); + strnum[fmt_ulong(strnum,pi[0])]=0; + env("SSLREADFD",strnum); + strnum[fmt_ulong(strnum,po[1])]=0; + env("SSLWRITEFD",strnum); + } else { + ssl_close(ssl); + if (fd_move(6,pi[0]) == -1) + strerr_die2sys(111,FATAL,"unable to set up descriptor 6: "); + if (fd_move(7,po[1]) == -1) + strerr_die2sys(111,FATAL,"unable to set up descriptor 7: "); + + if (flagsslenv && !ssl_client_env(ssl,0)) nomem(); + } sig_uncatch(sig_pipe); pathexec(argv); strerr_die4sys(111,FATAL,"unable to run ",*argv,": "); } - diff --git ucspi-ssl-0.70.2/src/sslperl.c ucspi-ssl-0.70.2-tls/src/sslperl.c index 8cf7811..e32a1cb 100644 --- ucspi-ssl-0.70.2/src/sslperl.c +++ ucspi-ssl-0.70.2-tls/src/sslperl.c @@ -13,6 +13,7 @@ #endif extern const char *self; +extern char **environ; /* ActiveState Perl requires this be called my_perl */ static PerlInterpreter *my_perl = 0; diff --git ucspi-ssl-0.70.2/src/sslserver.c ucspi-ssl-0.70.2-tls/src/sslserver.c index b516e98..52f4494 100644 --- ucspi-ssl-0.70.2/src/sslserver.c +++ ucspi-ssl-0.70.2-tls/src/sslserver.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include "ssl.h" #include "uint16.h" @@ -39,10 +41,12 @@ #include "auto_certfile.h" #include "auto_keyfile.h" #include "auto_ciphers.h" +#include "fmt.h" +#include "ucspitls_master.h" +#include "ucspitls.h" int verbosity = 1; int flagkillopts = 1; -int flagafter = 0; int flagdelay = 0; const char *banner = ""; int flagremoteinfo = 1; @@ -51,6 +55,7 @@ int flagparanoid = 0; int flagclientcert = 0; int flagsslenv = 0; int flagtcpenv = 0; +int flagsslwait = 0; unsigned long timeout = 26; unsigned long ssltimeout = 26; unsigned int progtimeout = 3600; @@ -72,6 +77,9 @@ static stralloc remotehostsa; char *remotehost = 0; char *verifyhost = 0; +unsigned long uid = 0; +unsigned long gid = 0; + char strnum[FMT_ULONG]; char strnum2[FMT_ULONG]; @@ -106,10 +114,13 @@ stralloc envsa = {0}; X509 *cert; char buf[SSL_NAME_LEN]; +#define FATAL "sslserver: fatal: " + /* ---------------------------- child */ #define DROP "sslserver: warning: dropping connection, " +#define DROPSSL "sslserver: warning: SSL disabled due to server error, " int flagdeny = 0; int flagallownorules = 0; @@ -180,9 +191,104 @@ void doit(int t) { int j; SSL *ssl; int wstat; + int sslctl[2]; + char *s; + unsigned long tmp_long; + char sslctl_cmd; + stralloc ssl_env = { 0 }; + buffer ssl_env_buf; - remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; + if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); + if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: "); + + switch(fork()) { + case -1: + strerr_die2sys(111,DROP,"unable to fork: "); + case 0: + /* Child */ + break; + default: + /* Parent */ + + close(pi[0]); close(po[1]); close(sslctl[1]); + + if ((s=env_get("SSL_CHROOT"))) + if (chroot(s) == -1) + strerr_die2x(111,DROPSSL,"unable to chroot"); + + if ((s=env_get("SSL_GID"))) { + scan_ulong(s,&tmp_long); + gid = tmp_long; + } + if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,DROPSSL,"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) + strerr_die2sys(111,DROPSSL,"unable to set uid: "); + + /* This will exit on a fatal error or if the client quits + * without activating SSL + */ + sslctl_cmd = ucspitls_master_wait_for_activation(sslctl[0]); + + /* If we got here, SSL must have been activated */ + ssl = ssl_new(ctx,t); + if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance"); + if (ndelay_on(t) == -1) + strerr_die2sys(111,DROP,"unable to set socket options: "); + if (ssl_timeoutaccept(ssl,ssltimeout) == -1) + strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno)); + + if (verbosity >= 2) { + strnum[fmt_ulong(strnum,getpid())] = 0; + strerr_warn3("sslserver: ssl ",strnum," accept ",0); + } + + if (flagclientcert) { + switch(ssl_verify(ssl,verifyhost)) { + case -1: + strerr_die2x(111,DROP,"unable to verify client certificate"); + case -2: + strerr_die2x(111,DROP,"no client certificate"); + case -3: + strerr_die2x(111,DROP,"client name does not match certificate"); + default: break; + } + } + + if (sslctl_cmd == 'Y') { + ssl_server_env(ssl, &ssl_env); + stralloc_0(&ssl_env); /* Add another NUL */ + buffer_init(&ssl_env_buf,buffer_unixwrite,sslctl[0],NULL,0); + if (buffer_putflush(&ssl_env_buf, ssl_env.s, ssl_env.len) == -1) { + strerr_die2sys(111, FATAL, "unable to write SSL environment: "); + } + } else if (sslctl_cmd != 'y') { + strerr_die2x(111,DROP,"Protocol error on SSL control descriptor: invalid command character read"); + } + + if (close(sslctl[0]) != 0) { + strerr_die2sys(111, DROP, "Error closing SSL control socket: "); + } + + if (ssl_io(ssl,pi[1],po[0],3600) != 0) + strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno)); + if (wait_nohang(&wstat) > 0) + _exit(wait_exitcode(wstat)); + ssl_close(ssl); + _exit(0); + } + + /* Child-only below this point */ + if (close(sslctl[0]) != 0) { + strerr_die2sys(111, DROP, "Error closing SSL control socket: "); + } + + remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn4("sslserver: pid ",strnum," from ",remoteipstr,0); @@ -278,59 +384,11 @@ void doit(int t) { if (flagdeny) _exit(100); - if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); - if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); - - ssl = ssl_new(ctx,t); - if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance"); - if (ndelay_on(t) == -1) - strerr_die2sys(111,DROP,"unable to set socket options: "); - if (ssl_timeoutaccept(ssl,ssltimeout) == -1) { - strerr_warn2(DROP,"unable to SSL accept:",&strerr_sys); - ssl_error(error_warn); - ssl_close(ssl); - _exit(111); - } + if (gid) if (prot_gid(gid) == -1) + strerr_die2sys(111,FATAL,"unable to set gid: "); + if (uid) if (prot_uid(uid) == -1) + strerr_die2sys(111,FATAL,"unable to set uid: "); - if (verbosity >= 2) { - strnum[fmt_ulong(strnum,getpid())] = 0; - strerr_warn3("sslserver: ssl ",strnum," accept ",0); - } - - if (flagclientcert) { - switch(ssl_verify(ssl,verifyhost)) { - case -1: - strerr_die2x(111,DROP,"unable to verify client certificate"); - case -2: - strerr_die2x(111,DROP,"no client certificate"); - case -3: - strerr_die2x(111,DROP,"client name does not match certificate"); - default: break; - } - } - - switch(j = fork()) { - case -1: - strerr_die2sys(111,DROP,"unable to fork: "); - case 0: - break; - default: - sig_ignore(sig_pipe); - sig_uncatch(sig_child); - sig_unblock(sig_child); - close(pi[0]); close(po[1]); - if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) { - strerr_warn2(DROP,"unable to speak SSL:",&strerr_sys); - ssl_error(error_warn); - ssl_close(ssl); - wait_pid(&wstat,j); - _exit(111); - } - ssl_close(ssl); - if (wait_pid(&wstat,j) > 0) - _exit(wait_exitcode(wstat)); - _exit(0); - } close(pi[1]); close(po[0]); sig_uncatch(sig_child); @@ -338,13 +396,32 @@ void doit(int t) { sig_uncatch(sig_term); sig_uncatch(sig_pipe); - if (flagsslenv && !ssl_server_env(ssl,0)) drop_nomem(); - ssl_close(ssl); - - if (fd_move(0,pi[0]) == -1) - strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); - if (fd_move(1,po[1]) == -1) - strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); + if (fcntl(sslctl[1],F_SETFD,0) == -1) + strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); + strnum[fmt_ulong(strnum,sslctl[1])]=0; + setenv("SSLCTLFD",strnum,1); + + if (fcntl(pi[0],F_SETFD,0) == -1) + strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); + strnum[fmt_ulong(strnum,pi[0])]=0; + setenv("SSLREADFD",strnum,1); + + if (fcntl(po[1],F_SETFD,0) == -1) + strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); + strnum[fmt_ulong(strnum,po[1])]=0; + setenv("SSLWRITEFD",strnum,1); + + if (flagsslwait) { + if (fd_copy(0,t) == -1) + strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); + if (fd_copy(1,t) == -1) + strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); + } else { + if (fd_move(0,pi[0]) == -1) + strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); + if (fd_move(1,po[1]) == -1) + strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); + } if (flagkillopts) socket_ipoptionskill(t); @@ -357,6 +434,12 @@ void doit(int t) { strerr_die2sys(111,DROP,"unable to print banner: "); } + if (!flagsslwait) { + strnum[fmt_ulong(strnum,flagsslenv)] = 0; + strerr_warn2("flagsslenv: ", strnum, 0); + ucspitls(flagsslenv,0,1); + } + pathexec(prog); strerr_die4sys(111,DROP,"unable to run ",*prog,": "); } @@ -365,13 +448,11 @@ void doit(int t) { /* ---------------------------- parent */ -#define FATAL "sslserver: fatal: " - void usage(void) { strerr_warn1("\ sslserver: usage: sslserver \ -[ -13UXpPhHrRoOdDqQviIeEsS ] \ +[ -13UXpPhHrRoOdDqQviIeEsSnN ] \ [ -c limit ] \ [ -x rules.cdb ] \ [ -B banner ] \ @@ -392,8 +473,6 @@ 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) { @@ -449,7 +528,7 @@ int main(int argc,char * const *argv) { int s; int t; - while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:pPoO3IiEeSsaAw:")) != opteof) + while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:T:u:g:l:b:B:c:pPoO3IiEeSsaAw:nNyY")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; @@ -485,8 +564,8 @@ int main(int argc,char * const *argv) { 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 'n': case 'y': flagsslwait = 1; break; + case 'N': case 'Y': flagsslwait = 0; break; default: usage(); } argc -= optind; @@ -566,13 +645,6 @@ int main(int argc,char * const *argv) { strerr_die2sys(111,FATAL,"unable to listen: "); ndelay_off(s); - if (!flagafter) { - if (gid) if (prot_gid(gid) == -1) - strerr_die2sys(111,FATAL,"unable to set gid: "); - if (uid) if (prot_uid(uid) == -1) - strerr_die2sys(111,FATAL,"unable to set uid: "); - } - localportstr[fmt_ulong(localportstr,localport)] = 0; if (flag1) { buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace); @@ -603,13 +675,6 @@ int main(int argc,char * const *argv) { if (!ssl_params(ctx,dhfile,rsalen)) strerr_die2x(111,FATAL,"unable to set cipher parameters"); - if (flagafter) { - if (gid) if (prot_gid(gid) == -1) - strerr_die2sys(111,FATAL,"unable to set gid: "); - if (uid) if (prot_uid(uid) == -1) - strerr_die2sys(111,FATAL,"unable to set uid: "); - } - if (!ssl_ciphers(ctx,ciphers)) strerr_die2x(111,FATAL,"unable to set cipher list"); @@ -624,8 +689,9 @@ int main(int argc,char * const *argv) { strerr_warn6("sslserver: param ",strnum," ",dhfile," ",strnum2,0); } - close(0); - close(1); + close(0); open_read("/dev/null"); + close(1); open_append("/dev/null"); + printstatus(); for (;;) { @@ -650,3 +716,11 @@ int main(int argc,char * const *argv) { close(t); } } + +/* taken from 0.68 */ +char *ssl_error_str(int e) +{ + SSL_load_error_strings(); + return ERR_error_string(e,0); +} + diff --git ucspi-ssl-0.70.2/src/ucspissltest.c ucspi-ssl-0.70.2-tls/src/ucspissltest.c new file mode 100644 index 0000000..4acdba1 --- /dev/null +++ ucspi-ssl-0.70.2-tls/src/ucspissltest.c @@ -0,0 +1,206 @@ +#include +#include +#include +#include +#include +#include +#include +#include "ucspitls.h" +#include "sgetopt.h" + +void usage(char *progname, int exit_status) { + printf("Usage: %s [-yYsScCvqQ]\n", progname); + printf( + "\t-y: Delay SSL until SIGUSR1 is received\n" + "\t-Y: Disable delayed SSL; plaintext mode, or SSL handled in sslclient/sslserver (default)\n" + "\t-s: Send SSL environment\n" + "\t-S: Don't send SSL environment (default)\n" + "\t-c: Client mode, for use with sslclient\n" + "\t-C: Server mode, for use with sslserver (default)\n" + "\t-v: Verbose mode\n" + "\t-q: Quiet mode\n" + "\t-Q: Non-quiet, non-verbose output (default)\n" + ); + printf("Signals:\n" + "\tSIGUSR1: Switch to SSL mode (if running with -y)\n" + "\tSIGUSR2: Dump environment to stderr\n" + ); + printf("Examples:\n" + " Delayed TLS server with no environment (send SIGUSR1 to start TLS):\n" + "\tenv DHFILE=./dh1024.pem CERTFILE=./localhost.cert KEYFILE=./localhost.key ./sslserver -3 3 0 ) { + fprintf(stderr,"%s started, pid %d\n", argv[0], getpid()); + if (flagsslwait) { + fprintf(stderr,"Send USR1 to activate TLS\n"); + } + fprintf(stderr,"Send USR2 to dump environment\n"); + } + + /* Initialize data structures for select */ + FD_ZERO(&read_fds); + max_read_fd = -1; + for(i=0;i 0) { + fprintf(stderr,"SSL requested, starting\n"); + } + if (!ucspitls(flagsslenv,readfd,writefd)) { + fprintf(stderr,"SSL activation failed\n"); + return 127; + } + if (verbosity > 0) { + fprintf(stderr,"SSL complete\n"); + } + } + if (dump_env) { + dump_env = 0; + system("env >&2"); + } + + /* See what's readable with select(). Note this is not a + * super-efficient implementation, it really is designed for + * testing. */ + for(i=0;i 0) { + fprintf(stderr,"fd %d closed\n", fd_sets[i][0]); + } + return fd_sets[i][0]; + } else if (nr < 0) { + /* Error */ + fprintf(stderr,"read from fd %d failed: %s\n", fd_sets[i][0], strerror(errno)); + return fd_sets[i][0]; + } else { + /* Successfully read nr bytes */ + total_written = 0; + while (total_written < nr) { + nw = write(fd_sets[i][1], buf + total_written, nr - total_written); + if (nw <= 0) { + fprintf(stderr,"write to fd %d failed: %s\n", fd_sets[i][1], strerror(errno)); + return fd_sets[i][1]; + } + total_written += nw; + } + } + } + } + } + return 0; +} diff --git ucspi-ssl-0.70.2/src/ucspitls.c ucspi-ssl-0.70.2-tls/src/ucspitls.c new file mode 100644 index 0000000..2ede81c --- /dev/null +++ ucspi-ssl-0.70.2-tls/src/ucspitls.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 16384 + +/* This is written in a simple style, not using the ucspi-ssl string + * libraries, so it is easy to embed in other programs. + */ + +/* Read a file descriptor from the environment, or return -1 on error +*/ +static int fdenv(const char *envname) { + char *fdstr; + long fd; + + if (!(fdstr=getenv(envname))) + return -1; + errno = 0; + fd = strtol(fdstr, NULL, 10); + if (errno != 0) return -1; + if (fd < 0 || fd > INT_MAX) return -1; + + return fd; +} + +/* Activate UCSPI-TLS */ +int ucspitls(int want_env, int readfd, int writefd) +{ + int fd; + char *addenv = malloc(BUFSIZE); + int curbufsize = BUFSIZE; + int readret; + int totalrb; + + /* Figure out our control FD */ + if ( (fd = fdenv("SSLCTLFD")) < 0) { + return 0; + } + + if (want_env) { + /* Request the environment on the SSL control FD */ + + if (write((int)fd, "Y", 1) < 1) + return 0; + } else { + /* Activate SSL but don't request the environment */ + if (write((int)fd, "y", 1) < 1) + return 0; + } + + + /* Read what is sent over the file descriptor. This should + * basically always happen in one read, so other situations are + * handled correctly but inefficiently. + */ + totalrb = 0; + addenv[0] = '\0'; + while ((readret = read(fd,addenv + totalrb,curbufsize - totalrb)) > 0) { + totalrb += readret; + if (totalrb == curbufsize) { + curbufsize += BUFSIZE; + addenv = realloc(addenv, curbufsize); + } + } + if (readret == -1) { + fprintf(stderr,"Error reading SSL environment: %s\n",strerror(errno)); + return 0; + } + + if (want_env) { + /* Parse the variables we read, and add them to the environment */ + char *nextenv = addenv; + while (*nextenv) { + char *val = strchr(nextenv,'='); + if (val && strncmp(nextenv,"SSL_",4) == 0) { + *val = '\0'; + ++val; + setenv(nextenv,val,1); + } else { + val = nextenv; // So we will start searching in the right place + } + nextenv = strchr(val, '\0') + 1; + } + } + + /* Now get the new file descriptors for reading and writing, and dup + * them to the client's read and write fd, respectively. The client + * should be sure to discard any buffered data from before encyption + * was activated, to avoid any issues like CVE-2011-0411. + */ + if ((fd = fdenv("SSLREADFD")) < 0) + return 0; + if (dup2((int)fd,readfd) == -1) + return 0; + + if ((fd = fdenv("SSLWRITEFD")) < 0) + return 0; + if (dup2((int)fd,writefd) == -1) + return 0; + + /* It worked! */ + return 1; +} diff --git ucspi-ssl-0.70.2/src/ucspitls.h ucspi-ssl-0.70.2-tls/src/ucspitls.h new file mode 100644 index 0000000..5a54500 --- /dev/null +++ ucspi-ssl-0.70.2-tls/src/ucspitls.h @@ -0,0 +1 @@ +int ucspitls(int want_env, int readfd, int writefd); diff --git ucspi-ssl-0.70.2/src/ucspitls_master.c ucspi-ssl-0.70.2-tls/src/ucspitls_master.c new file mode 100644 index 0000000..e6b4142 --- /dev/null +++ ucspi-ssl-0.70.2-tls/src/ucspitls_master.c @@ -0,0 +1,44 @@ +#include +#include +#include "wait.h" +#include "strerr.h" + +#define FATAL "Fatal error in SSL activation: " + +/* Returns UCSPI-TLS command character (y or Y) on success. + * On failure or child exit, exits directly and does not return. + */ +char ucspitls_master_wait_for_activation(int fd) { + char sslctl_read_ret; + char sslctl_cmd; + int wstat; + + /* Read the TLS command socket. This will block until/unless + * TLS is requested. + */ + while(1) { + sslctl_read_ret = read(fd,&sslctl_cmd,1); + if ( sslctl_read_ret == 1 ) { + /* SSL was requested */ + break; + } else if (sslctl_read_ret == 0) { + /* EOF from client, it must have exited */ + if (wait_nohang(&wstat) <= 0) { + strerr_die2sys(111, FATAL, "Error waiting for child socket: "); + } + _exit(wait_exitcode(wstat)); + } else if (sslctl_read_ret < 0) { + /* Error. Is it retryable? */ + if (errno == EAGAIN || errno == EINTR) { + /* Do nothing, let the loop run again */ + } else { + strerr_die2sys(111,FATAL,"Read error on SSL control descriptor"); + } + } else { + /* Too many characters read, should not really happen */ + strerr_die2x(111,FATAL,"Protocol error on SSL control descriptor: too many characters read"); + } + } + + return sslctl_cmd; +} diff --git ucspi-ssl-0.70.2/src/ucspitls_master.h ucspi-ssl-0.70.2-tls/src/ucspitls_master.h new file mode 100644 index 0000000..acb84db --- /dev/null +++ ucspi-ssl-0.70.2-tls/src/ucspitls_master.h @@ -0,0 +1 @@ +char ucspitls_master_wait_for_activation(int fd); -- 1.6.6.2 From 8f95e2c9d839a21e449f5de5975ef31010edadc7 Mon Sep 17 00:00:00 2001 From: Christian Wiese Date: Wed, 16 Nov 2011 17:43:41 +0100 Subject: [PATCH 2/2] removed src/conf-ld~ --- src/conf-ld~ | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) delete mode 100644 src/conf-ld~ diff --git ucspi-ssl-0.70.2/src/conf-ld~ ucspi-ssl-0.70.2-tls/src/conf-ld~ deleted file mode 100644 index 1d0518a..0000000 --- ucspi-ssl-0.70.2/src/conf-ld~ +++ /dev/null @@ -1,3 +0,0 @@ -gcc - -This will be used to link .o files into an executable. -- 1.6.6.2