diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71db3ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*~ +.*.sw* +ID +tags +/compile/ +/command/ + diff --git a/conf-certfile_ec b/conf-certfile_ec new file mode 100644 index 0000000..fcb6825 --- /dev/null +++ b/conf-certfile_ec @@ -0,0 +1,3 @@ + +# This is the sslserver certificate file. +# An empty name means no certificate file is compiled in. diff --git a/conf-keyfile_ec b/conf-keyfile_ec new file mode 100644 index 0000000..f727507 --- /dev/null +++ b/conf-keyfile_ec @@ -0,0 +1,3 @@ + +This is the sslserver key file. +An empty name means no key file is compiled in. diff --git a/conf-ld b/conf-ld index a01f6d3..0cfb4a4 100644 --- a/conf-ld +++ b/conf-ld @@ -1,4 +1,4 @@ -cc -s +cc -Wl,-z,relro -Wl,-z,now -pie # This will be used to link .o files into an executable. # The '-m64' option will be inclucded automatically. diff --git a/src/Makefile b/src/Makefile index 1b4038a..68c6533 100755 --- a/src/Makefile +++ b/src/Makefile @@ -4,10 +4,6 @@ SHELL=/bin/sh default: it -alloc.o: \ -compile alloc.c alloc.h error.h - ./compile alloc.c - alloc_re.o: \ compile alloc_re.c alloc.h byte.h ./compile alloc_re.c @@ -15,6 +11,10 @@ compile alloc_re.c alloc.h byte.h auto-str: load auto-str.o unix.a ./load auto-str unix.a +auto-str.o: \ + auto-str.c buffer.h exit.h + ./compile auto-str.c + auto_cadir.c: auto-str ../conf-cadir ./auto-str auto_cadir "`head -1 ../conf-cadir`" > auto_cadir.c @@ -45,6 +45,12 @@ auto_certfile.c: auto-str ../conf-certfile auto_certfile.o: compile auto_certfile.c ./compile auto_certfile.c +auto_certfile_ec.c: auto-str ../conf-certfile_ec + ./auto-str auto_certfile_ec "`head -1 ../conf-certfile_ec`" > auto_certfile_ec.c + +auto_certfile_ec.o: compile auto_certfile_ec.c + ./compile auto_certfile_ec.c + auto_ciphers.c: auto-str ../conf-ciphers ./auto-str auto_ciphers "`head -1 ../conf-ciphers`" > auto_ciphers.c @@ -63,6 +69,12 @@ auto_keyfile.c: auto-str ../conf-keyfile auto_keyfile.o: compile auto_keyfile.c ./compile auto_keyfile.c +auto_keyfile_ec.c: auto-str ../conf-keyfile_ec + ./auto-str auto_keyfile_ec "`head -1 ../conf-keyfile_ec`" > auto_keyfile_ec.c + +auto_keyfile_ec.o: compile auto_keyfile_ec.c + ./compile auto_keyfile_ec.c + buffer.o: \ compile buffer.c buffer.h ./compile buffer.c @@ -712,7 +724,7 @@ sslconnect: home warn-auto.sh sslconnect.sh sslhandle.o: \ compile sslhandle.c alloc.h auto_cadir.h auto_cafile.h auto_ccafile.h \ -auto_certchainfile.h auto_certfile.h auto_ciphers.h auto_dhfile.h auto_keyfile.h buffer.h \ +auto_certchainfile.h auto_certfile.h auto_certfile_ec.h auto_ciphers.h auto_dhfile.h auto_keyfile.h auto_keyfile_ec.h buffer.h \ byte.h coe.h dns.h env.h error.h exit.h fd.h fmt.h gen_alloc.h getln.h iopause.h \ ip4.h lock.h ndelay.h open.h prot.h remoteinfo.h rules.h scan.h sgetopt.h sig.h \ socket.h str.h stralloc.h strerr.h subgetopt.h tai.h ucspissl.h uint16.h uint64.h \ @@ -722,11 +734,11 @@ wait.h sslperl: load sslperl.o rules.o ip4_bit.o remoteinfo6.o timeoutconn6.o \ sslhandle.o cdb.a ucspissl.a unix.a dns.a \ auto_cafile.o auto_ccafile.o auto_cadir.o \ -auto_dhfile.o auto_certfile.o auto_keyfile.o \ +auto_dhfile.o auto_certfile.o auto_certfile_ec.o auto_keyfile.o auto_keyfile_ec.o \ auto_ciphers.o auto_certchainfile.o \ socket.lib ssl.lib socket.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 \ + auto_certfile.o auto_certfile_ec.o auto_keyfile.o auto_keyfile_ec.o auto_ciphers.o auto_certchainfile.o \ rules.o ip4_bit.o remoteinfo6.o timeoutconn6.o sslhandle.o \ cdb.a ucspissl.a unix.a dns.a \ `cat socket.lib` `cat ssl.lib` `cat socket.lib` `cat perlembed.lib` @@ -736,11 +748,11 @@ compile ccperl sslperl.c gen_alloc.h sslperl.c str.h stralloc.h strerr.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 \ +auto_dhfile.o auto_certfile.o auto_certfile_ec.o auto_keyfile.o auto_keyfile_ec.o auto_ciphers.o auto_certchainfile.o \ remoteinfo6.o timeoutconn6.o sslhandle.o ucspissl.a cdb.a unix.a rules.o ip4_bit.o \ socket.lib ssl.lib socket.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 \ + auto_certfile.o auto_certfile_ec.o auto_keyfile.o auto_keyfile_ec.o auto_ciphers.o auto_certchainfile.o \ rules.o ip4_bit.o remoteinfo6.o timeoutconn6.o sslhandle.o \ cdb.a ucspissl.a unix.a dns.a \ `cat socket.lib` `cat ssl.lib` @@ -750,23 +762,34 @@ compile sslprint.c buffer.h env.h ./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 \ +auto_certchainfile.o auto_dhfile.o auto_certfile.o auto_certfile_ec.o auto_keyfile.o auto_keyfile_ec.o auto_ciphers.o \ rules.o ip4_bit.o remoteinfo6.o timeoutconn6.o \ cdb.a ucspissl.a unix.a dns.a socket.lib ssl.lib ./load sslserver auto_cafile.o auto_ccafile.o auto_cadir.o auto_dhfile.o \ - auto_certchainfile.o auto_certfile.o auto_keyfile.o auto_ciphers.o \ + auto_certchainfile.o auto_certfile.o auto_certfile_ec.o auto_keyfile.o auto_keyfile_ec.o auto_ciphers.o \ rules.o ip4_bit.o remoteinfo6.o timeoutconn6.o cdb.a ucspissl.a unix.a dns.a \ `cat socket.lib` `cat ssl.lib` sslserver.o: \ compile sslserver.c alloc.h auto_cadir.h auto_cafile.h auto_ccafile.h \ -auto_certchainfile.h auto_certfile.h auto_ciphers.h auto_dhfile.h auto_keyfile.h buffer.h \ +auto_certchainfile.h auto_certfile.h auto_certfile_ec.h auto_ciphers.h auto_dhfile.h auto_keyfile.h auto_keyfile_ec.h buffer.h \ byte.h dns.h env.h error.h exit.h fd.h fmt.h gen_alloc.h getln.h iopause.h ip4.h \ ndelay.h open.h pathexec.h prot.h remoteinfo.h rules.h scan.h sgetopt.h sig.h \ socket.h str.h stralloc.h strerr.h subgetopt.h tai.h taia.h ucspissl.h uint16.h \ wait.h ./compile sslserver.c +remoteinfo6.o: \ +compile remoteinfo6.c fmt.h buffer.h socket.h uint16.h uint32.h \ + error.h iopause.h taia.h tai.h uint64.h timeoutconn.h remoteinfo.h \ + stralloc.h gen_alloc.h + ./compile remoteinfo6.c + +timeoutconn6.o: \ +compile timeoutconn6.c ndelay.h socket.h uint16.h uint32.h \ + iopause.h taia.h tai.h uint64.h error.h timeoutconn.h + ./compile timeoutconn6.c + str_chr.o: \ compile str_chr.c str.h ./compile str_chr.c @@ -918,7 +941,7 @@ uint64.h: choose compile load tryulong64.c uint64.h1 uint64.h2 ./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h unix.a: \ -makelib alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ +makelib alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ buffer_copy.o buffer_get.o buffer_put.o buffer_read.o buffer_write.o byte_chr.o \ byte_copy.o byte_cr.o byte_diff.o byte_zero.o case_diffb.o case_diffs.o coe.o \ dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_name.o dns_nd.o dns_packet.o \ @@ -938,7 +961,7 @@ stralloc_copy.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o stralloc_pend.o strerr_sys.o subgetopt.o 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 uint16_pack.o uint16_unpack.o uint32_pack.o \ uint32_unpack.o wait_nohang.o wait_pid.o - ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ + ./makelib unix.a alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ buffer_copy.o buffer_get.o buffer_put.o buffer_read.o buffer_write.o byte_chr.o \ byte_copy.o byte_cr.o byte_diff.o byte_zero.o case_diffb.o case_diffs.o coe.o \ dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_name.o dns_nd.o dns_packet.o \ diff --git a/src/alloc.c b/src/alloc.c deleted file mode 100644 index 5b21993..0000000 --- a/src/alloc.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Public domain. */ - -#include -#include "alloc.h" -#include "error.h" - -#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ -#define SPACE 2048 /* must be multiple of ALIGNMENT */ - -typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; -static aligned realspace[SPACE / ALIGNMENT]; -#define space ((char *) realspace) -static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ - -/*@null@*//*@out@*/char *alloc(unsigned int n) -{ - char *x; - n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ - if (n <= avail) { avail -= n; return space + avail; } - x = malloc(n); - if (!x) errno = error_nomem; - return x; -} - -void alloc_free(char *x) -{ - if (x >= space) - if (x < space + SPACE) - return; /* XXX: assuming that pointers are flat */ - free(x); -} diff --git a/src/alloc.h b/src/alloc.h index 8647a7d..1f49978 100644 --- a/src/alloc.h +++ b/src/alloc.h @@ -1,10 +1,24 @@ -/* Public domain. */ - #ifndef ALLOC_H #define ALLOC_H -extern /*@null@*//*@out@*/char *alloc(unsigned int); -extern void alloc_free(char *); -extern int alloc_re(char **,unsigned int,unsigned int); +#include +#include "error.h" + +static inline /*@null@*//*@out@*/char *alloc(n) +unsigned int n; +{ + char *x; + x = malloc(n); + if (!x) errno = error_nomem; + return x; +} + +static inline void alloc_free(x) +char *x; +{ + free(x); +} + +extern int alloc_re(char **, unsigned int, unsigned int); #endif diff --git a/src/auto-str.c b/src/auto-str.c index 5780d19..af6c72c 100644 --- a/src/auto-str.c +++ b/src/auto-str.c @@ -4,7 +4,7 @@ char bspace[256]; buffer b = BUFFER_INIT(buffer_unixwrite,1,bspace,sizeof bspace); -static void puts(const char *s) +static void putsx(const char *s) { if (buffer_puts(&b,s) == -1) _exit(111); } @@ -21,20 +21,20 @@ int main(int argc,char **argv) value = argv[2]; if (!value) _exit(100); - puts("const char "); - puts(name); - puts("[] = \"\\\n"); + putsx("const char "); + putsx(name); + putsx("[] = \"\\\n"); while ((ch = *value++)) { - puts("\\"); + putsx("\\"); octal[3] = 0; octal[2] = '0' + (ch & 7); ch >>= 3; octal[1] = '0' + (ch & 7); ch >>= 3; octal[0] = '0' + (ch & 7); - puts(octal); + putsx(octal); } - puts("\\\n\";\n"); + putsx("\\\n\";\n"); if (buffer_flush(&b) == -1) _exit(111); _exit(0); } diff --git a/src/auto_certfile_ec.c.do b/src/auto_certfile_ec.c.do new file mode 100644 index 0000000..d90fad3 --- /dev/null +++ b/src/auto_certfile_ec.c.do @@ -0,0 +1,3 @@ +dependon auto-str conf-certfile_ec +formake './auto-str auto_certfile_ec "`head -1 ../conf-certfile_ec`" > auto_certfile_ec.c' +./auto-str auto_certfile_ec "`head -1 ../conf-certfile_ec`" diff --git a/src/auto_certfile_ec.h b/src/auto_certfile_ec.h new file mode 100644 index 0000000..d2a9c85 --- /dev/null +++ b/src/auto_certfile_ec.h @@ -0,0 +1,6 @@ +#ifndef AUTO_CERTFILE_EC_H +#define AUTO_CERTFILE_EC_H + +extern const char auto_certfile_ec[]; + +#endif diff --git a/src/auto_keyfile_ec.c.do b/src/auto_keyfile_ec.c.do new file mode 100644 index 0000000..82464ea --- /dev/null +++ b/src/auto_keyfile_ec.c.do @@ -0,0 +1,3 @@ +dependon auto-str conf-keyfile_ec +formake './auto-str auto_keyfile_ec "`head -1 ../conf-keyfile_ec`" > auto_keyfile_ec.c' +./auto-str auto_keyfile_ec "`head -1 ../conf-keyfile_ec`" diff --git a/src/auto_keyfile_ec.h b/src/auto_keyfile_ec.h new file mode 100644 index 0000000..3e64305 --- /dev/null +++ b/src/auto_keyfile_ec.h @@ -0,0 +1,6 @@ +#ifndef AUTO_KEYFILE_EC_H +#define AUTO_KEYFILE_EC_H + +extern const char auto_keyfile_ec[]; + +#endif diff --git a/src/cdb.h b/src/cdb.h index 65d0b1a..e9125a4 100644 --- a/src/cdb.h +++ b/src/cdb.h @@ -5,8 +5,6 @@ #include "uint32.h" -#define CDB_HASHSTART 5381 -extern uint32 cdb_hashadd(uint32,unsigned char); extern uint32 cdb_hash(const char *,unsigned int); struct cdb { diff --git a/src/cdb_hash.c b/src/cdb_hash.c index 71102e1..02a8d67 100644 --- a/src/cdb_hash.c +++ b/src/cdb_hash.c @@ -1,21 +1,10 @@ -/* Public domain. */ - #include "cdb.h" +#include "siphash.h" -uint32 cdb_hashadd(uint32 h,unsigned char c) +uint32 cdb_hash(const char *k, unsigned int length) { - h += (h << 5); - return h ^ c; -} + static unsigned char cdbinitkey[32] = "cdbinitkey_foobarquxfubardeadbee"; -uint32 cdb_hash(const char *buf,unsigned int len) -{ - uint32 h; - - h = CDB_HASHSTART; - while (len) { - h = cdb_hashadd(h,*buf++); - --len; - } - return h; + return siphash(k, length, cdbinitkey); } + diff --git a/src/open.h b/src/open.h index 9939663..e75af5d 100644 --- a/src/open.h +++ b/src/open.h @@ -3,7 +3,16 @@ #ifndef OPEN_H #define OPEN_H +#include +#include +#include + +#ifndef O_CLOEXEC +#define O_CLOEXEC (0) +#endif + extern int open_read(const char *); +extern int open_read_cloexec(const char *); extern int open_excl(const char *); extern int open_append(const char *); extern int open_trunc(const char *); diff --git a/src/open_append.c b/src/open_append.c index d1b241b..b2bdb81 100644 --- a/src/open_append.c +++ b/src/open_append.c @@ -1,7 +1,5 @@ /* Public domain. */ -#include -#include #include "open.h" int open_append(const char *fn) diff --git a/src/open_read.c b/src/open_read.c index 99b3cd1..99325e7 100644 --- a/src/open_read.c +++ b/src/open_read.c @@ -1,8 +1,9 @@ /* Public domain. */ -#include -#include #include "open.h" int open_read(const char *fn) { return open(fn,O_RDONLY | O_NDELAY); } + +int open_read_cloexec(const char *fn) +{ return open(fn,O_RDONLY | O_NDELAY | O_CLOEXEC); } diff --git a/src/open_trunc.c b/src/open_trunc.c index 6e0c4c2..2d17369 100644 --- a/src/open_trunc.c +++ b/src/open_trunc.c @@ -1,7 +1,5 @@ /* Public domain. */ -#include -#include #include "open.h" int open_trunc(const char *fn) diff --git a/src/print-cc.sh b/src/print-cc.sh index d4f07bc..7a4c35d 100644 --- a/src/print-cc.sh +++ b/src/print-cc.sh @@ -27,7 +27,7 @@ ccedh="`head -1 ../conf-ecdh`" eval cc -pedantic tryssl.c $ccedh >/dev/null 2>&1 \ || ccedh="" -ccbase="cc -fomit-frame-pointer -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings" +ccbase="cc -gdwarf-4 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC -fstack-protector-strong -fstack-clash-protection -fcf-protection=full --param=ssp-buffer-size=4 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings" case "$cc:$systype" in auto:*:i386-*:*) diff --git a/src/siphash.h b/src/siphash.h new file mode 100644 index 0000000..fc7e843 --- /dev/null +++ b/src/siphash.h @@ -0,0 +1,81 @@ +#ifndef SIPHASH_H +#define SIPHASH_H + +#include + +#include "uint64.h" + +#define ROTL64(a,b) (((a)<<(b))|((a)>>(64-b))) + +static inline uint64 U8TO64_LE (const unsigned char *p) +{ + return *(const uint64 *)p; +} + +/* +static void INLINE +U64TO8_LE(unsigned char *p, const uint64 v) { + *(uint64 *)p = v; +} +*/ + +static inline uint64 siphash(const char *m, size_t len, void *k) +{ + uint64 v0, v1, v2, v3; + uint64 mi, k0, k1; + uint64 last7; + size_t i, blocks; + uint64 *key = k; + + k0 = key[0]; + k1 = key[1]; + v0 = key[2]; + v1 = key[3]; + v2 = k0 ^ 0x6c7967656e657261ull; + v3 = k1 ^ 0x7465646279746573ull; + + last7 = (uint64)(len & 0xff) << 56; + +#define sipcompress() \ + v0 += v1; v2 += v3; \ + v1 = ROTL64(v1,13); v3 = ROTL64(v3,16); \ + v1 ^= v0; v3 ^= v2; \ + v0 = ROTL64(v0,32); \ + v2 += v1; v0 += v3; \ + v1 = ROTL64(v1,17); v3 = ROTL64(v3,21); \ + v1 ^= v2; v3 ^= v0; \ + v2 = ROTL64(v2,32); + + for (i = 0, blocks = (len & ~7); i < blocks; i += 8) { + mi = U8TO64_LE(m + i); + v3 ^= mi; + sipcompress() + sipcompress() + v0 ^= mi; + } + + switch (len - blocks) { + case 7: last7 |= (uint64)m[i + 6] << 48; + case 6: last7 |= (uint64)m[i + 5] << 40; + case 5: last7 |= (uint64)m[i + 4] << 32; + case 4: last7 |= (uint64)m[i + 3] << 24; + case 3: last7 |= (uint64)m[i + 2] << 16; + case 2: last7 |= (uint64)m[i + 1] << 8; + case 1: last7 |= (uint64)m[i + 0] ; + case 0: + default:; + }; + v3 ^= last7; + sipcompress() + sipcompress() + v0 ^= last7; + v2 ^= 0xff; + sipcompress() + sipcompress() + sipcompress() + sipcompress() + return v0 ^ v1 ^ v2 ^ v3; +} + +#endif + diff --git a/src/ssl_certkey.c b/src/ssl_certkey.c index 3595b82..fac1698 100644 --- a/src/ssl_certkey.c +++ b/src/ssl_certkey.c @@ -1,19 +1,29 @@ #include "ucspissl.h" -int ssl_certkey(SSL_CTX *ctx,const char *certfile,const char *keyfile,pem_password_cb *passwd_cb) +int ssl_certkey(SSL_CTX *ctx,const char *certfile, const char *certfileec, + const char *keyfile, const char *keyfileec, pem_password_cb *passwd_cb) { if (!certfile) return 0; + SSL_CTX_set_default_passwd_cb(ctx,passwd_cb); + 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_RSAPrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM) != 1) - return -2; + if (keyfile) { + if (SSL_CTX_use_PrivateKey_file(ctx,keyfile,SSL_FILETYPE_PEM) != 1) + return -2; + } - if (SSL_CTX_check_private_key(ctx) != 1) + if (SSL_CTX_use_certificate_chain_file(ctx,certfileec) != 1) return -3; + if (keyfileec) { + if (SSL_CTX_use_PrivateKey_file(ctx,keyfileec,SSL_FILETYPE_PEM) != 1) + return -4; + } + + if (SSL_CTX_check_private_key(ctx) != 1) + return -5; return 0; } diff --git a/src/ssl_context.c b/src/ssl_context.c index d89de9b..619492e 100644 --- a/src/ssl_context.c +++ b/src/ssl_context.c @@ -6,11 +6,8 @@ SSL_CTX *ssl_context(const SSL_METHOD *m) 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 + SSL_CTX_set_options(ctx,SSL_OP_SINGLE_DH_USE | SSL_OP_NO_COMPRESSION | SSL_OP_CIPHER_SERVER_PREFERENCE | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #ifdef SSLv2_DISABLE SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2); #endif @@ -20,6 +17,7 @@ SSL_CTX *ssl_context(const SSL_METHOD *m) #ifdef TLSv1_DISABLE SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1); #endif + SSL_CTX_set_ecdh_auto(ctx, 1); return ctx; } diff --git a/src/ssl_env.c b/src/ssl_env.c index 7020dcc..6d6845e 100644 --- a/src/ssl_env.c +++ b/src/ssl_env.c @@ -76,6 +76,9 @@ int ssl_session_vars(SSL *ssl) { if (!env_str("SSL_PROTOCOL",SSL_get_version(ssl))) return 0; + if (!env_str("SSL_VERIFY_STATUS","unverified")) return 0; + if (!env_str("SSL_VERIFY_STRING","")) return 0; + #if OPENSSL_VERSION_NUMBER < 0x10100000L session = SSL_get_session(ssl); x = session->session_id; @@ -98,14 +101,14 @@ int ssl_session_vars(SSL *ssl) { 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_val("SSL_RFD",strnum,fmt_ulong(strnum,SSL_get_rfd(ssl)))) return 0; + if (!env_val("SSL_WFD",strnum,fmt_ulong(strnum,SSL_get_wfd(ssl)))) return 0; if (!env_str("SSL_VERSION_INTERFACE","ucspi-ssl")) return 0; if (!env_str("SSL_VERSION_LIBRARY",OPENSSL_VERSION_TEXT)) return 0; diff --git a/src/ssl_io.c b/src/ssl_io.c index 968e354..d5a089c 100644 --- a/src/ssl_io.c +++ b/src/ssl_io.c @@ -31,12 +31,12 @@ int ssl_io(SSL *ssl,int fdleft,int fdright,unsigned int timeout) { int rfd; int wfd; - rfd = SSL_get_fd(ssl); /* XXX */ + rfd = SSL_get_rfd(ssl); if (rfd == -1) { close(fdleft); close(fdright); return -1; } - wfd = SSL_get_fd(ssl); /* XXX */ + wfd = SSL_get_wfd(ssl); if (wfd == -1) { close(fdleft); close(fdright); return -1; diff --git a/src/sslclient.c b/src/sslclient.c index 47f4b3c..0ddde2b 100644 --- a/src/sslclient.c +++ b/src/sslclient.c @@ -63,8 +63,10 @@ void usage(void) { [ -a cafile ] \ [ -A cadir ] \ [ -c certfile ] \ +[ -C certfile_ec ] \ [ -z ciphers ] \ [ -k keyfile ] \ +[ -K keyfile_ec ] \ [ -V verifydepth ] \ [ -w progtimeout ] \ host port program"); @@ -109,6 +111,8 @@ buffer b; SSL_CTX *ctx; const char *certfile = 0; const char *keyfile = 0; +const char *certfileec = 0; +const char *keyfileec = 0; const char *cafile = auto_cafile; const char *cadir = auto_cadir; const char *ciphers = auto_ciphers; @@ -181,8 +185,10 @@ int main(int argc,char * const *argv) { case 'a': cafile = optarg; break; case 'A': cadir = optarg; break; case 'c': certfile = optarg; break; + case 'C': certfileec = optarg; break; case 'z': ciphers = optarg; break; case 'k': keyfile = optarg; break; + case 'K': keyfileec = optarg; break; case 'V': scan_ulong(optarg,&u); verifydepth = u; break; case '3': flag3 = 1; break; case 'S': flagsslenv = 0; break; @@ -341,10 +347,12 @@ int main(int argc,char * const *argv) { 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"); + switch (ssl_certkey(ctx,certfile,certfileec,keyfile,keyfileec,passwd_cb)) { + case -1: strerr_die2x(111,FATAL,"unable to load certificate 1"); + case -2: strerr_die2x(111,FATAL,"unable to load key pair 1"); + case -3: strerr_die2x(111,FATAL,"unable to load certificate 2"); + case -4: strerr_die2x(111,FATAL,"unable to load key pair 2"); + case -5: strerr_die2x(111,FATAL,"key does not match certificate"); default: break; } diff --git a/src/sslhandle.c b/src/sslhandle.c index 964b7a7..f70232d 100644 --- a/src/sslhandle.c +++ b/src/sslhandle.c @@ -44,6 +44,8 @@ #include "auto_certchainfile.h" #include "auto_certfile.h" #include "auto_keyfile.h" +#include "auto_certfile_ec.h" +#include "auto_keyfile_ec.h" #include "auto_ciphers.h" #include "iopause.h" #include "coe.h" @@ -70,6 +72,7 @@ unsigned int progtimeout = 3600; uint32 netif = 0; int selfpipe[2]; int flagexit = 0; +char retbuf[1024]; static stralloc tcpremoteinfo = {0}; @@ -107,6 +110,8 @@ SSL_CTX *ctx; const char *certchainfile = auto_certchainfile; const char *certfile = auto_certfile; const char *keyfile = auto_keyfile; +const char *certfileec = auto_certfile_ec; +const char *keyfileec = auto_keyfile_ec; stralloc password = {0}; int match = 0; const char *cafile = auto_cafile; @@ -701,6 +706,12 @@ int main(int argc,char * const *argv) { if ((x = env_get("KEYFILE"))) keyfile = x; if (keyfile && str_equal(keyfile,"")) keyfile = 0; + if ((x = env_get("CERTFILEEC"))) certfileec = x; + if (certfileec && str_equal(certfileec,"")) certfileec = 0; + + if ((x = env_get("KEYFILEEC"))) keyfileec = x; + if (keyfileec && str_equal(keyfileec,"")) keyfileec = 0; + if ((x = env_get("DHFILE"))) dhfile = x; if (dhfile && str_equal(dhfile,"")) dhfile = 0; @@ -780,11 +791,18 @@ int main(int argc,char * const *argv) { default: break; } } else { - 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"); - case -3: strerr_die2x(111,FATAL,"key does not match certificate"); - default: break; + switch (ssl_certkey(ctx, certfile, certfileec, + keyfile, keyfileec, passwd_cb)) { + case -1: strerr_die3x(111,FATAL,"unable to load RSA certificate: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -2: strerr_die3x(111,FATAL,"unable to RSA key: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -3: strerr_die3x(111,FATAL,"unable to load EC certificate: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -4: strerr_die3x(111,FATAL,"unable to load EC key: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -5: strerr_die3x(111,FATAL,"key does not match certificate: ", + ERR_error_string(ERR_get_error(), retbuf)); } } @@ -820,6 +838,8 @@ int main(int argc,char * const *argv) { strerr_warn5(self,": certchainfile ",strnum," ",certchainfile,0); strerr_warn5(self,": cert ",strnum," ",certfile,0); strerr_warn5(self,": key ",strnum," ",keyfile,0); + strerr_warn5(self,": cert EC ",strnum," ",certfileec,0); + strerr_warn5(self,": key EC ",strnum," ",keyfileec,0); /* XXX */ buffer_puts(buffer_2,self); strerr_warn6(": param ",strnum," ",dhfile," ",strnum2,0); diff --git a/src/sslserver.c b/src/sslserver.c index 98431e2..f4d02b5 100755 --- a/src/sslserver.c +++ b/src/sslserver.c @@ -44,8 +44,10 @@ #include "auto_ccafile.h" #include "auto_dhfile.h" #include "auto_certfile.h" +#include "auto_certfile_ec.h" #include "auto_certchainfile.h" #include "auto_keyfile.h" +#include "auto_keyfile_ec.h" #include "auto_ciphers.h" #include "fmt.h" @@ -101,6 +103,8 @@ SSL_CTX *ctx; const char *certchainfile = auto_certchainfile; const char *certfile = auto_certfile; const char *keyfile = auto_keyfile; +const char *certfileec = auto_certfile_ec; +const char *keyfileec = auto_keyfile_ec; stralloc password = {0}; int match = 0; const char *cafile = auto_cafile; @@ -110,6 +114,8 @@ const char *ciphers = auto_ciphers; int verifydepth = 1; const char *dhfile = auto_dhfile; int rsalen = SSL_RSA_LEN; +static int randfd; +char retbuf[1024]; char * const *prog; @@ -193,6 +199,18 @@ void found(char *data,unsigned int datalen) { } } +static inline void ssl_rand_seed(void) +{ + ssize_t nread; + char randbuf[32]; + + nread = read(randfd, randbuf, sizeof(randbuf)); + if (nread > 0) { + RAND_add(randbuf, nread, nread); + byte_zero(randbuf, nread); + } +} + void doit(int t) { int j; SSL *ssl = 0; @@ -209,7 +227,8 @@ void doit(int t) { uint32 scope_id; char *stripaddr; stralloc tlsinfo = {0}; - + int save_errno; + 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) @@ -238,12 +257,15 @@ void doit(int t) { close(pi[0]); close(po[1]); close(sslctl[1]); - if ((s = env_get("SSL_CHROOT"))) + if ((s = env_get("SSL_CHROOT"))) { if (chroot(s) == -1) { kill(childpid,SIGTERM); strerr_die2x(111,DROP,"unable to chroot"); } - + if (chdir("/") == -1) + strerr_die2x(111,DROP,"unable to chdir"); + } + if ((s = env_get("SSL_GID"))) { scan_ulong(s,&tmp_long); gid = tmp_long; @@ -275,11 +297,24 @@ void doit(int t) { kill(childpid,SIGTERM); strerr_die2sys(111,DROP,"unable to set socket options: "); } + + ssl_rand_seed(); + if (ssl_timeoutaccept(ssl,ssltimeout) == -1) { strnum[fmt_ulong(strnum,childpid)] = 0; kill(childpid,SIGTERM); strerr_die5x(111,DROP,"unable to accept SSL for pid: ",strnum," ",ssl_error_str(ssl_errno)); } + } else { + save_errno = errno; + if ((save_errno != error_noent) && (save_errno != error_intr) && + (save_errno != ECHILD)) { + kill(childpid,SIGTERM); + strerr_die3x(111,DROP,"unable to read TLS command socket: ", error_str(save_errno)); + } else { + /* child exited without issuing STARTTLS */ + _exit(0); + } } if (flagclientcert) { @@ -307,6 +342,7 @@ void doit(int t) { for (bytesleft = ssl_env.len; bytesleft > 0; bytesleft -= j) if ((j = write(sslctl[0],ssl_env.s,bytesleft)) < 0) { + SSL_free(ssl); kill(childpid,SIGTERM); strerr_die2sys(111,FATAL,"unable to write SSL environment: "); } @@ -332,6 +368,7 @@ void doit(int t) { if (ssl_cmd == 'Y' || ssl_cmd == 'y') { if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) { strnum[fmt_ulong(strnum,childpid)] = 0; + SSL_free(ssl); kill(childpid,SIGTERM); strerr_die5x(111,DROP,"unable to speak SSL for pid: ",strnum," ",ssl_error_str(ssl_errno)); } @@ -344,6 +381,7 @@ void doit(int t) { } /* Child-only below this point */ + ssl_rand_seed(); if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; @@ -540,8 +578,9 @@ void doit(int t) { if (write(sslctl[1],&ssl_cmd,1) < 1) strerr_die2sys(111,DROP,"unable to start SSL: "); if (flagsslenv) { - while ((j=read(sslctl[1],envbuf,8192)) > 0) { - stralloc_catb(&ssl_env,envbuf,j); + while ((j=read(sslctl[1],envbuf,sizeof(envbuf))) > 0) { + if (!stralloc_catb(&ssl_env,envbuf,j)) + strerr_die2x(111,DROP,"out of memory while appending to ssl_env"); if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len-2] == 0 && ssl_env.s[ssl_env.len-1] == 0) break; } @@ -600,12 +639,15 @@ void sigterm(void) void sigchld(void) { int wstat; int pid; + int crashed; while ((pid = wait_nohang(&wstat)) > 0) { if (verbosity >= 2) { + crashed = wait_crashed(wstat); strnum[fmt_ulong(strnum,pid)] = 0; - strnum2[fmt_ulong(strnum2,wstat)] = 0; - strerr_warn4("sslserver: ended by ",strnum," status ",strnum2,0); + strnum2[fmt_ulong(strnum2,crashed ? crashed : wait_exitcode(wstat))] = 0; + strerr_warn4("sslserver: end ",strnum, crashed ? " status signal " : " status exit ", + strnum2,0); } if (numchildren) --numchildren; printstatus(); } @@ -637,6 +679,7 @@ int main(int argc,char * const *argv) { unsigned long u; int s; int t; + int fd; while ((opt = getopt(argc,argv,"1346dDvVqQhHrRUXx:t:T:u:g:l:b:B:c:pPoOIEeSsw:nNzZm")) != opteof) switch(opt) { @@ -731,6 +774,12 @@ int main(int argc,char * const *argv) { if ((x = env_get("KEYFILE"))) keyfile = x; if (keyfile && str_equal(keyfile,"")) keyfile = 0; + if ((x = env_get("CERTFILEEC"))) certfileec = x; + if (certfileec && str_equal(certfileec,"")) certfileec = 0; + + if ((x = env_get("KEYFILEEC"))) keyfileec = x; + if (keyfileec && str_equal(keyfileec,"")) keyfileec = 0; + if ((x = env_get("DHFILE"))) dhfile = x; if (dhfile && str_equal(dhfile,"")) dhfile = 0; @@ -793,19 +842,28 @@ int main(int argc,char * const *argv) { } } else { - 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"); - case -3: strerr_die2x(111,FATAL,"key does not match certificate"); - default: break; + switch (ssl_certkey(ctx, certfile, certfileec, + keyfile, keyfileec, passwd_cb)) { + case -1: strerr_die3x(111,FATAL,"unable to load RSA certificate: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -2: strerr_die3x(111,FATAL,"unable to RSA key: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -3: strerr_die3x(111,FATAL,"unable to load EC certificate: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -4: strerr_die3x(111,FATAL,"unable to load EC key: ", + ERR_error_string(ERR_get_error(), retbuf)); + case -5: strerr_die3x(111,FATAL,"key does not match certificate: ", + ERR_error_string(ERR_get_error(), retbuf)); } } if (!ssl_ca(ctx,cafile,cadir,verifydepth)) - strerr_die2x(111,FATAL,"unable to load CA list"); + strerr_die3x(111,FATAL,"unable to load CA list: ", + ERR_error_string(ERR_get_error(), retbuf)); if (!ssl_cca(ctx,ccafile)) - strerr_die2x(111,FATAL,"unable to load client CA list"); + strerr_die3x(111,FATAL,"unable to load client CA list:", + ERR_error_string(ERR_get_error(), retbuf)); if (!ssl_params_rsa(ctx,rsalen)) strerr_die2x(111,FATAL,"unable to set RSA parameters"); @@ -829,8 +887,19 @@ int main(int argc,char * const *argv) { strerr_warn6("sslserver: param ",strnum," ",dhfile," ",strnum2,0); } - close(0); open_read("/dev/null"); - close(1); open_append("/dev/null"); + fd = open_append("/dev/null"); + if (fd == -1) + strerr_die2x(111,FATAL,"unable to open /dev/null"); + + randfd = open_read_cloexec("/dev/urandom"); + if (randfd == -1) + strerr_die2x(111,FATAL,"unable to open /dev/urandom"); + + if (dup2(fd, 0) == -1) + strerr_die2x(111,FATAL,"dup2(fd, 0) failed"); + if (dup2(fd, 1) == -1) + strerr_die2x(111,FATAL,"dup2(fd, 1) failed"); + if (fd > 2) close(fd); printstatus(); @@ -861,5 +930,5 @@ int main(int argc,char * const *argv) { char *ssl_error_str(int e) { SSL_load_error_strings(); - return ERR_error_string(e,0); + return ERR_error_string(e,retbuf); } diff --git a/src/ucspissl.h b/src/ucspissl.h index e410929..ccce5f2 100644 --- a/src/ucspissl.h +++ b/src/ucspissl.h @@ -10,13 +10,14 @@ #include #include #include +#include #ifdef SSL_TXT_ECDH #include #endif #include "stralloc.h" #define SSL_NAME_LEN 256 -#define SSL_RSA_LEN 2048 +#define SSL_RSA_LEN 4096 #if defined (LIBRESSL_VERSION_NUMBER) #define ssl_client() (ssl_context(TLS_client_method())) @@ -24,7 +25,7 @@ #else #define SSLv2_DISABLE #define SSLv3_DISABLE -// #define TLSv1_DISABLE +#define TLSv1_DISABLE #define ssl_client() (ssl_context(SSLv23_client_method())) #define ssl_server() (ssl_context(SSLv23_server_method())) #endif @@ -36,7 +37,8 @@ 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_certkey(SSL_CTX *,const char *,const char*, + 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 *);