diff -ur stunnel-3.9/common.h stunnel-3.9-new/common.h --- stunnel-3.9/common.h Wed Dec 13 17:33:07 2000 +++ stunnel-3.9-new/common.h Thu Dec 14 14:25:37 2000 @@ -18,6 +18,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define PHI_CHAIN_HACK 1 + #define OPT_CLIENT 0x01 #define OPT_CERT 0x02 #define OPT_DAEMON 0x04 @@ -149,6 +151,9 @@ char pem[STRLEN]; /* pem (priv key/cert) filename */ char cert_dir[STRLEN]; /* directory for hashed certs */ char cert_file[STRLEN]; /* file containing bunches of certs */ +#ifdef PHI_CHAIN_HACK + char chain_file[STRLEN]; /* file containing bunches of certs */ +#endif char pidfile[STRLEN]; unsigned long dpid; int clients; diff -ur stunnel-3.9/ssl.c stunnel-3.9-new/ssl.c --- stunnel-3.9/ssl.c Wed Dec 13 17:32:23 2000 +++ stunnel-3.9-new/ssl.c Thu Dec 14 14:29:55 2000 @@ -163,6 +163,67 @@ return(0); /* assume we don't have enough */ } +#ifdef PHI_CHAIN_HACK + /* Stolen with much glee from mod_ssl, thanks guys, you rock + * -Phi + */ + + /* + * Read a file that optionally contains the server certificate in PEM + * format, possibly followed by a sequence of CA certificates that + * should be sent to the peer in the SSL Certificate message. + */ + int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, char *file, int skipfirst, int (*cb)()) { + BIO *bio; + X509 *x509; + unsigned long err; + int n; + + if ((bio = BIO_new(BIO_s_file_internal())) == NULL) + return -1; + if (BIO_read_filename(bio, file) <= 0) { + BIO_free(bio); + return -1; + } + /* optionally skip a leading server certificate */ + if (skipfirst) { + if ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) { + BIO_free(bio); + return -1; + } + X509_free(x509); + } + /* free a perhaps already configured extra chain */ + if (ctx->extra_certs != NULL) { + sk_X509_pop_free(ctx->extra_certs, X509_free); + ctx->extra_certs = NULL; + } + /* create new extra chain by loading the certs */ + n = 0; + while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) { + if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) { + X509_free(x509); + BIO_free(bio); + return -1; + } + n++; + } + /* Make sure that only the error is just an EOF */ + if ((err = ERR_peek_error()) > 0) { + if (!( ERR_GET_LIB(err) == ERR_LIB_PEM + && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) { + BIO_free(bio); + return -1; + } + while (ERR_get_error() > 0) ; + } + BIO_free(bio); + return n; +} + +#endif + + int add_rand_file( char *filename ) { int readbytes; int writebytes; @@ -362,6 +423,19 @@ exit(1); } } + +#ifdef PHI_CHAIN_HACK + if (options.chain_file[0]) { + log(LOG_DEBUG, "Chain file specified, loading.."); + if (SSL_CTX_use_certificate_chain(ctx, options.chain_file, 0, NULL) < 0) { + sslerror("Couldn't configure CA certificate chain"); + exit(1); + } + log(LOG_DEBUG, "Loaded."); + } + +#endif + if(options.verify_level!=SSL_VERIFY_NONE) { log(LOG_DEBUG, "cert_defaults is %d", options.cert_defaults); @@ -374,6 +448,7 @@ exit(1); } } + /* put in defaults (if not set on cmd line) if -S says to */ if ( options.cert_defaults & STUNNEL_CERT_DEFAULTS ) { diff -ur stunnel-3.9/stunnel.c stunnel-3.9-new/stunnel.c --- stunnel-3.9/stunnel.c Wed Dec 13 17:33:49 2000 +++ stunnel-3.9-new/stunnel.c Thu Dec 14 14:41:19 2000 @@ -239,11 +239,21 @@ options.rand_write=1; options.random_bytes=RANDOM_BYTES; opterr=0; + +#ifdef PHI_CHAIN_HACK + while ((c = getopt(argc, argv, "Q:A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:E:R:WB:VP:S:")) != EOF) +#else while ((c = getopt(argc, argv, "A:a:cp:v:d:fTl:L:r:s:g:t:u:n:N:hC:D:E:R:WB:VP:S:")) != EOF) +#endif switch (c) { case 'A': safecopy(options.cert_file,optarg); break; +#ifdef PHI_CHAIN_HACK + case 'Q': + safecopy(options.chain_file,optarg); + break; +#endif case 'a': safecopy(options.cert_dir, optarg); break; @@ -1064,6 +1074,9 @@ #endif "\n -T\t\ttransparent proxy mode on hosts that support it." "\n -p pemfile\tprivate key/certificate PEM filename" +#ifdef PHI_CHAIN_HACK + "\n -Q pemfile\tfile containing certificate chain" +#endif "\n -v level\tverify peer certificate" "\n\t\t level 1 - verify peer certificate if present" "\n\t\t level 2 - require valid peer certificate always"