From 14bee768fb27483b355d98feef2a96de81d75017 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Thu, 15 Apr 2004 03:57:00 +0000 Subject: [PATCH] * Brought over the SSL/TLS stuff from Citadel. I think it's complete but it has a crashy crashy bug in it. Don't use it yet. --- webcit/ChangeLog | 5 + webcit/Makefile.in | 4 +- webcit/configure.in | 119 +++++++++++- webcit/crypto.c | 448 ++++++++++++++++++++++++++++++++++++++++++++ webcit/webcit.h | 23 +++ webcit/webserver.c | 36 +++- 6 files changed, 630 insertions(+), 5 deletions(-) create mode 100644 webcit/crypto.c diff --git a/webcit/ChangeLog b/webcit/ChangeLog index e56d02bea..efdffadef 100644 --- a/webcit/ChangeLog +++ b/webcit/ChangeLog @@ -1,4 +1,8 @@ $Log$ +Revision 506.3 2004/04/15 03:57:00 ajc +* Brought over the SSL/TLS stuff from Citadel. I think it's complete but + it has a crashy crashy bug in it. Don't use it yet. + Revision 506.2 2004/04/13 19:41:36 ajc * GET /freebusy/user.vcf *and* /freebusy/user.vfb now both work. (freebusy data fetch for anonymous Kolab type clients) @@ -1762,3 +1766,4 @@ Sun Dec 6 19:50:55 EST 1998 Art Cancro 1998-12-03 Nathan Bryant * webserver.c: warning fix + diff --git a/webcit/Makefile.in b/webcit/Makefile.in index 90d59eff2..e8b305014 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -34,7 +34,7 @@ webserver: webserver.o context_loop.o tools.o ical_dezonify.o \ vcard.o vcard_edit.o preferences.o html2html.o listsub.o \ mime_parser.o graphics.o netconf.o siteconfig.o subst.o \ calendar.o calendar_tools.o calendar_view.o event.o \ - availability.o iconbar.o \ + availability.o iconbar.o crypto.o \ $(LIBOBJS) $(CC) webserver.o context_loop.o tools.o cookie_conversion.o \ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o listsub.o \ @@ -42,7 +42,7 @@ webserver: webserver.o context_loop.o tools.o ical_dezonify.o \ locate_host.o siteconfig.o subst.o vcard.o vcard_edit.o floors.o \ mime_parser.o graphics.o netconf.o preferences.o html2html.o \ summary.o calendar.o calendar_tools.o calendar_view.o event.o \ - availability.o ical_dezonify.o iconbar.o \ + availability.o ical_dezonify.o iconbar.o crypto.o \ $(LIBOBJS) $(LIBS) $(LDFLAGS) -o webserver .c.o: diff --git a/webcit/configure.in b/webcit/configure.in index f7720f4e4..b974dd231 100644 --- a/webcit/configure.in +++ b/webcit/configure.in @@ -6,7 +6,14 @@ AC_CANONICAL_HOST AC_ARG_WITH(with_libical, [ --with-libical use libical calendaring library]) AC_ARG_WITH(with_newt, [ --with-newt use newt window library]) - +AC_ARG_WITH(ssl, + [ --with-ssl=PATH Specify path to OpenSSL installation ], + [ + if test "x$withval" != "xno" ; then + tryssldir=$withval + fi + ] +) dnl Set some system-specific variables which are OK to set before compiler dnl checks: PTHREAD_DEFS=-D_REENTRANT @@ -122,6 +129,116 @@ if test "x$ok_newt" = xyes ; then AC_DEFINE(HAVE_NEWT) fi +# The big search for OpenSSL +if test "$with_ssl" != "no"; then + saved_LIBS="$LIBS" + saved_LDFLAGS="$LDFLAGS" + saved_CFLAGS="$CFLAGS" + if test "x$prefix" != "xNONE"; then + tryssldir="$tryssldir $prefix" + fi + AC_CACHE_CHECK([for OpenSSL], ac_cv_openssldir, [ + for ssldir in $tryssldir "" /usr /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /usr/pkg /opt /opt/openssl ; do + CFLAGS="$saved_CFLAGS" + LDFLAGS="$saved_LDFLAGS" + LIBS="$saved_LIBS -lssl -lcrypto" + + # Skip directories if they don't exist + if test ! -z "$ssldir" -a ! -d "$ssldir" ; then + continue; + fi + if test ! -z "$ssldir" -a "x$ssldir" != "x/usr"; then + # Try to use $ssldir/lib if it exists, otherwise + # $ssldir + if test -d "$ssldir/lib" ; then + LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir/lib $LDFLAGS" + fi + else + LDFLAGS="-L$ssldir $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir $LDFLAGS" + fi + fi + # Try to use $ssldir/include if it exists, otherwise + # $ssldir + if test -d "$ssldir/include" ; then + CFLAGS="-I$ssldir/include $saved_CFLAGS" + else + CFLAGS="-I$ssldir $saved_CFLAGS" + fi + fi + + # Basic test to check for compatible version and correct linking + # *does not* test for RSA - that comes later. + AC_TRY_RUN( + [ + #include + #include + int main(void) + { + char a[2048]; + memset(a, 0, sizeof(a)); + RAND_add(a, sizeof(a), sizeof(a)); + return(RAND_status() <= 0); + } + ], + [ + found_crypto=1 + break; + ], [] + ) + + if test ! -z "$found_crypto" ; then + break; + fi + done + + if test -z "$ssldir" ; then + ssldir="(system)" + fi + + if test ! -z "$found_crypto" ; then + ac_cv_openssldir=$ssldir + else + ac_cv_openssldir="no" + fi + ]) + LIBS="$saved_LIBS" + LDFLAGS="$saved_LDFLAGS" + CFLAGS="$saved_CFLAGS" + + if test "x$ac_cv_openssldir" != "xno" ; then + AC_DEFINE(HAVE_OPENSSL) + LIBS="-lssl -lcrypto $LIBS" + dnl Need to recover ssldir - test above runs in subshell + ssldir=$ac_cv_openssldir + if test ! -z "$ssldir" -a "x$ssldir" != "x/usr" -a "x$ssldir" != "x(system)"; then + # Try to use $ssldir/lib if it exists, otherwise + # $ssldir + if test -d "$ssldir/lib" ; then + LDFLAGS="-L$ssldir/lib $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir/lib $LDFLAGS" + fi + else + LDFLAGS="-L$ssldir $saved_LDFLAGS" + if test ! -z "$need_dash_r" ; then + LDFLAGS="-R$ssldir $LDFLAGS" + fi + fi + # Try to use $ssldir/include if it exists, otherwise + # $ssldir + if test -d "$ssldir/include" ; then + CFLAGS="-I$ssldir/include $saved_CFLAGS" + else + CFLAGS="-I$ssldir $saved_CFLAGS" + fi + fi + fi +fi + AC_SUBST(SETUP_LIBS) diff --git a/webcit/crypto.c b/webcit/crypto.c new file mode 100644 index 000000000..145beb79e --- /dev/null +++ b/webcit/crypto.c @@ -0,0 +1,448 @@ +/* $Id$ */ + +#ifdef HAVE_OPENSSL + + +#include +#include +#include +#include +#include +#include + +#include +#include "webcit.h" +#include "webserver.h" + +#define CTDL_CRYPTO_DIR "./keys" +#define CTDL_KEY_PATH CTDL_CRYPTO_DIR "/citadel.key" +#define CTDL_CSR_PATH CTDL_CRYPTO_DIR "/citadel.csr" +#define CTDL_CER_PATH CTDL_CRYPTO_DIR "/citadel.cer" +#define SIGN_DAYS 3650 /* Ten years */ + + +/* Shared Diffie-Hellman parameters */ +#define DH_P "1A74527AEE4EE2568E85D4FB2E65E18C9394B9C80C42507D7A6A0DBE9A9A54B05A9A96800C34C7AA5297095B69C88901EEFD127F969DCA26A54C0E0B5C5473EBAEB00957D2633ECAE3835775425DE66C0DE6D024DBB17445E06E6B0C78415E589B8814F08531D02FD43778451E7685541079CFFB79EF0D26EFEEBBB69D1E80383" +#define DH_G "2" +#define DH_L 1024 +#define CIT_CIPHERS "ALL:RC4+RSA:+SSLv2:@STRENGTH" /* see ciphers(1) */ + +SSL_CTX *ssl_ctx; /* SSL context */ +pthread_mutex_t **SSLCritters; /* Things needing locking */ + +static unsigned long id_callback(void) +{ + return (unsigned long) pthread_self(); +} + + /* + * Set up the cert things on the server side. We do need both the + * private key (in key_file) and the cert (in cert_file). + * Both files may be identical. + * + * This function is taken from OpenSSL apps/s_cb.c + */ + +static int ctdl_install_certificate(SSL_CTX * ctx, + const char *cert_file, const char *key_file) +{ + if (cert_file != NULL) { + if (SSL_CTX_use_certificate_file(ctx, cert_file, + SSL_FILETYPE_PEM) <= 0) { + lprintf(3, "unable to get certificate from '%s'", + cert_file); + return (0); + } + if (key_file == NULL) + key_file = cert_file; + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, + SSL_FILETYPE_PEM) <= 0) { + lprintf(3, "unable to get private key from '%s'", + key_file); + return (0); + } + /* Now we know that a key and cert have been set against + * the SSL context */ + if (!SSL_CTX_check_private_key(ctx)) { + lprintf(3, + "Private key does not match the certificate public key"); + return (0); + } + } + return (1); +} + + +void init_ssl(void) +{ + SSL_METHOD *ssl_method; + DH *dh; + RSA *rsa=NULL; + X509_REQ *req = NULL; + X509 *cer = NULL; + EVP_PKEY *pk = NULL; + EVP_PKEY *req_pkey = NULL; + X509_NAME *name = NULL; + FILE *fp; + + if (!access("/var/run/egd-pool", F_OK)) + RAND_egd("/var/run/egd-pool"); + + if (!RAND_status()) { + lprintf(3, + "PRNG not adequately seeded, won't do SSL/TLS\n"); + return; + } + SSLCritters = + malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t *)); + if (!SSLCritters) { + lprintf(1, "citserver: can't allocate memory!!\n"); + /* Nothing's been initialized, just die */ + exit(1); + } else { + int a; + + for (a = 0; a < CRYPTO_num_locks(); a++) { + SSLCritters[a] = malloc(sizeof(pthread_mutex_t)); + if (!SSLCritters[a]) { + lprintf(1, + "citserver: can't allocate memory!!\n"); + /* Nothing's been initialized, just die */ + exit(1); + } + pthread_mutex_init(SSLCritters[a], NULL); + } + } + + /* + * Initialize SSL transport layer + */ + SSL_library_init(); + SSL_load_error_strings(); + ssl_method = SSLv23_server_method(); + if (!(ssl_ctx = SSL_CTX_new(ssl_method))) { + lprintf(3, "SSL_CTX_new failed: %s\n", + ERR_reason_error_string(ERR_get_error())); + return; + } + if (!(SSL_CTX_set_cipher_list(ssl_ctx, CIT_CIPHERS))) { + lprintf(3, "SSL: No ciphers available\n"); + SSL_CTX_free(ssl_ctx); + ssl_ctx = NULL; + return; + } +#if 0 +#if SSLEAY_VERSION_NUMBER >= 0x00906000L + SSL_CTX_set_mode(ssl_ctx, SSL_CTX_get_mode(ssl_ctx) | + SSL_MODE_AUTO_RETRY); +#endif +#endif + + CRYPTO_set_locking_callback(ssl_lock); + CRYPTO_set_id_callback(id_callback); + + /* Load DH parameters into the context */ + dh = DH_new(); + if (!dh) { + lprintf(3, "init_ssl() can't allocate a DH object: %s\n", + ERR_reason_error_string(ERR_get_error())); + SSL_CTX_free(ssl_ctx); + ssl_ctx = NULL; + return; + } + if (!(BN_hex2bn(&(dh->p), DH_P))) { + lprintf(3, "init_ssl() can't assign DH_P: %s\n", + ERR_reason_error_string(ERR_get_error())); + SSL_CTX_free(ssl_ctx); + ssl_ctx = NULL; + return; + } + if (!(BN_hex2bn(&(dh->g), DH_G))) { + lprintf(3, "init_ssl() can't assign DH_G: %s\n", + ERR_reason_error_string(ERR_get_error())); + SSL_CTX_free(ssl_ctx); + ssl_ctx = NULL; + return; + } + dh->length = DH_L; + SSL_CTX_set_tmp_dh(ssl_ctx, dh); + DH_free(dh); + + /* Get our certificates in order. + * First, create the key/cert directory if it's not there already... + */ + mkdir(CTDL_CRYPTO_DIR, 0700); + + /* + * Generate a key pair if we don't have one. + */ + if (access(CTDL_KEY_PATH, R_OK) != 0) { + lprintf(5, "Generating RSA key pair.\n"); + rsa = RSA_generate_key(1024, /* modulus size */ + 65537, /* exponent */ + NULL, /* no callback */ + NULL); /* no callback */ + if (rsa == NULL) { + lprintf(3, "Key generation failed: %s\n", + ERR_reason_error_string(ERR_get_error())); + } + if (rsa != NULL) { + fp = fopen(CTDL_KEY_PATH, "w"); + if (fp != NULL) { + chmod(CTDL_KEY_PATH, 0600); + if (PEM_write_RSAPrivateKey(fp, /* the file */ + rsa, /* the key */ + NULL, /* no enc */ + NULL, /* no passphr */ + 0, /* no passphr */ + NULL, /* no callbk */ + NULL /* no callbk */ + ) != 1) { + lprintf(3, "Cannot write key: %s\n", + ERR_reason_error_string(ERR_get_error())); + unlink(CTDL_KEY_PATH); + } + fclose(fp); + } + RSA_free(rsa); + } + } + + /* + * Generate a CSR if we don't have one. + */ + if (access(CTDL_CSR_PATH, R_OK) != 0) { + lprintf(5, "Generating a certificate signing request.\n"); + + /* + * Read our key from the file. No, we don't just keep this + * in memory from the above key-generation function, because + * there is the possibility that the key was already on disk + * and we didn't just generate it now. + */ + fp = fopen(CTDL_KEY_PATH, "r"); + if (fp) { + rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + } + + if (rsa) { + + /* Create a public key from the private key */ + if (pk=EVP_PKEY_new(), pk != NULL) { + EVP_PKEY_assign_RSA(pk, rsa); + if (req = X509_REQ_new(), req != NULL) { + + /* Set the public key */ + X509_REQ_set_pubkey(req, pk); + X509_REQ_set_version(req, 0L); + + name = X509_REQ_get_subject_name(req); + + /* Tell it who we are */ + + /* + X509_NAME_add_entry_by_txt(name, "C", + MBSTRING_ASC, "US", -1, -1, 0); + + X509_NAME_add_entry_by_txt(name, "ST", + MBSTRING_ASC, "New York", -1, -1, 0); + + X509_NAME_add_entry_by_txt(name, "L", + MBSTRING_ASC, "Mount Kisco", -1, -1, 0); + */ + + X509_NAME_add_entry_by_txt(name, "O", + MBSTRING_ASC, "FIXME.FIXME.org", -1, -1, 0); + + X509_NAME_add_entry_by_txt(name, "OU", + MBSTRING_ASC, "Citadel server", -1, -1, 0); + + X509_NAME_add_entry_by_txt(name, "CN", + MBSTRING_ASC, "FIXME.FIXME.org", -1, -1, 0); + + X509_REQ_set_subject_name(req, name); + + /* Sign the CSR */ + if (!X509_REQ_sign(req, pk, EVP_md5())) { + lprintf(3, "X509_REQ_sign(): error\n"); + } + else { + /* Write it to disk. */ + fp = fopen(CTDL_CSR_PATH, "w"); + if (fp != NULL) { + chmod(CTDL_CSR_PATH, 0600); + PEM_write_X509_REQ(fp, req); + fclose(fp); + } + } + + X509_REQ_free(req); + } + } + + RSA_free(rsa); + } + + else { + lprintf(3, "Unable to read private key.\n"); + } + } + + + + /* + * Generate a self-signed certificate if we don't have one. + */ + if (access(CTDL_CER_PATH, R_OK) != 0) { + lprintf(5, "Generating a self-signed certificate.\n"); + + /* Same deal as before: always read the key from disk because + * it may or may not have just been generated. + */ + fp = fopen(CTDL_KEY_PATH, "r"); + if (fp) { + rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + } + + /* This also holds true for the CSR. */ + req = NULL; + cer = NULL; + pk = NULL; + if (rsa) { + if (pk=EVP_PKEY_new(), pk != NULL) { + EVP_PKEY_assign_RSA(pk, rsa); + } + + fp = fopen(CTDL_CSR_PATH, "r"); + if (fp) { + req = PEM_read_X509_REQ(fp, NULL, NULL, NULL); + fclose(fp); + } + + if (req) { + if (cer = X509_new(), cer != NULL) { + + X509_set_issuer_name(cer, req->req_info->subject); + X509_set_subject_name(cer, req->req_info->subject); + X509_gmtime_adj(X509_get_notBefore(cer),0); + X509_gmtime_adj(X509_get_notAfter(cer),(long)60*60*24*SIGN_DAYS); + req_pkey = X509_REQ_get_pubkey(req); + X509_set_pubkey(cer, req_pkey); + EVP_PKEY_free(req_pkey); + + /* Sign the cert */ + if (!X509_sign(cer, pk, EVP_md5())) { + lprintf(3, "X509_sign(): error\n"); + } + else { + /* Write it to disk. */ + fp = fopen(CTDL_CER_PATH, "w"); + if (fp != NULL) { + chmod(CTDL_CER_PATH, 0600); + PEM_write_X509(fp, cer); + fclose(fp); + } + } + X509_free(cer); + } + } + + RSA_free(rsa); + } + } + + + /* + * Now try to bind to the key and certificate. + */ + if (ctdl_install_certificate(ssl_ctx, + CTDL_CER_PATH, + CTDL_KEY_PATH) != 1) + { + lprintf(3, "Cannot install certificate: %s\n", + ERR_reason_error_string(ERR_get_error())); + } + +} + + +/* + * starttls() starts SSL/TLS encryption for the current session. + */ +int starttls(void) { + + int retval, bits, alg_bits; + + if (!ssl_ctx) { + return(1); + } + if (!(WC->ssl = SSL_new(ssl_ctx))) { + lprintf(3, "SSL_new failed: %s\n", + ERR_reason_error_string(ERR_get_error())); + return(2); + } + if (!(SSL_set_fd(WC->ssl, WC->http_sock))) { + lprintf(3, "SSL_set_fd failed: %s\n", + ERR_reason_error_string(ERR_get_error())); + SSL_free(WC->ssl); + WC->ssl = NULL; + return(3); + } + retval = SSL_accept(WC->ssl); + if (retval < 1) { + /* + * Can't notify the client of an error here; they will + * discover the problem at the SSL layer and should + * revert to unencrypted communications. + */ + long errval; + + errval = SSL_get_error(WC->ssl, retval); + lprintf(3, "SSL_accept failed: %s\n", + ERR_reason_error_string(ERR_get_error())); + SSL_free(WC->ssl); + WC->ssl = NULL; + return(4); + } + BIO_set_close(WC->ssl->rbio, BIO_NOCLOSE); + bits = + SSL_CIPHER_get_bits(SSL_get_current_cipher(WC->ssl), + &alg_bits); + lprintf(5, "SSL/TLS using %s on %s (%d of %d bits)\n", + SSL_CIPHER_get_name(SSL_get_current_cipher(WC->ssl)), + SSL_CIPHER_get_version(SSL_get_current_cipher(WC->ssl)), + bits, alg_bits); + return(0); +} + + + +/* + * endtls() shuts down the TLS connection + * + * WARNING: This may make your session vulnerable to a known plaintext + * attack in the current implmentation. + */ +void endtls(void) +{ + lprintf(5, "Ending SSL/TLS\n"); + SSL_shutdown(WC->ssl); + SSL_free(WC->ssl); + WC->ssl = NULL; +} + + +/* + * ssl_lock() callback for OpenSSL mutex locks + */ +void ssl_lock(int mode, int n, const char *file, int line) +{ + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(SSLCritters[n]); + else + pthread_mutex_unlock(SSLCritters[n]); +} + +#endif /* HAVE_OPENSSL */ diff --git a/webcit/webcit.h b/webcit/webcit.h index a19416dcc..afb3c9d7b 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -15,6 +15,14 @@ #include #endif +#ifdef HAVE_OPENSSL +/* Work around RedHat's b0rken OpenSSL includes */ +#define OPENSSL_NO_KRB5 +#include +#include +#include +#endif + #define CALENDAR_ROOM_NAME "Calendar" #define PRODID "-//Citadel//NONSGML Citadel Calendar//EN" @@ -219,6 +227,9 @@ struct wcsession { int outside_frameset_allowed; /* nonzero if current req is allowed * outside of the main frameset */ char last_chat_user[SIZ]; +#ifdef HAVE_OPENSSL + SSL *ssl; +#endif }; #define extract(dest,source,parmnum) extract_token(dest,source,parmnum,'|') @@ -232,6 +243,7 @@ extern char floorlist[128][SIZ]; extern char *axdefs[]; extern char *ctdlhost, *ctdlport; extern char *server_cookie; +extern int is_https; extern struct wcsubst *global_subst; @@ -437,3 +449,14 @@ void display_customize_iconbar(void); void commit_iconbar(void); int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen); void spawn_another_worker_thread(void); + + + +#ifdef HAVE_OPENSSL +void init_ssl(void); +void endtls(void); +void ssl_lock(int mode, int n, const char *file, int line); +int starttls(void); +extern SSL_CTX *ssl_ctx; +#endif + diff --git a/webcit/webserver.c b/webcit/webserver.c index b6f2d1a8d..a8f0ac4d9 100644 --- a/webcit/webserver.c +++ b/webcit/webserver.c @@ -35,7 +35,6 @@ #include #include #include - #include "webcit.h" #include "webserver.h" @@ -45,6 +44,7 @@ int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp); int verbosity = 9; /* Logging level */ int msock; /* master listening socket */ +int is_https = 0; /* Nonzero if I am an HTTPS service */ extern void *context_loop(int); extern void *housekeeping_loop(void); extern pthread_mutex_t SessionListMutex; @@ -228,7 +228,11 @@ int main(int argc, char **argv) char tracefile[PATH_MAX]; /* Parse command line */ +#ifdef HAVE_OPENSSL + while ((a = getopt(argc, argv, "hp:t:cs")) != EOF) +#else while ((a = getopt(argc, argv, "hp:t:c")) != EOF) +#endif switch (a) { case 'p': port = atoi(optarg); @@ -255,9 +259,15 @@ int main(int argc, char **argv) } } break; + case 's': + is_https = 1; + break; default: fprintf(stderr, "usage: webserver [-p localport] " "[-t tracefile] [-c] " +#ifdef HAVE_OPENSSL + "[-s] " +#endif "[remotehost [remoteport]]\n"); return 1; } @@ -306,6 +316,15 @@ int main(int argc, char **argv) (void *(*)(void *)) housekeeping_loop, NULL); + /* + * If this is an HTTPS server, fire up SSL + */ +#ifdef HAVE_OPENSSL + if (is_https) { + init_ssl(); + } +#endif + /* Start a few initial worker threads */ for (i=0; i<(MIN_WORKER_THREADS); ++i) { spawn_another_worker_thread(); @@ -324,9 +343,11 @@ void worker_entry(void) { int ssock; int i = 0; int time_to_die = 0; + int fail_this_transaction = 0; do { /* Only one thread can accept at a time */ + fail_this_transaction = 0; ssock = accept(msock, NULL, 0); if (ssock < 0) { lprintf(2, "accept() failed: %s\n", strerror(errno)); @@ -336,8 +357,19 @@ void worker_entry(void) { setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + /* If we are an HTTPS server, go crypto now. */ +#ifdef HAVE_OPENSSL + if (is_https) { + if (starttls() != 0) { + fail_this_transaction = 1; + } + } +#endif + /* Perform an HTTP transaction... */ - context_loop(ssock); + if (fail_this_transaction == 0) { + context_loop(ssock); + } /* ...and close the socket. */ lingering_close(ssock); -- 2.30.2