Hello community, here is the log from the commit of package pound for openSUSE:Factory checked in at 2015-03-18 13:08:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pound (Old) and /work/SRC/openSUSE:Factory/.pound.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pound" Changes: -------- --- /work/SRC/openSUSE:Factory/pound/pound.changes 2012-05-08 11:15:17.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.pound.new/pound.changes 2015-03-18 13:08:21.000000000 +0100 @@ -1,0 +2,33 @@ +Thu Mar 12 00:54:42 UTC 2015 - [email protected] + +- Update to version 2.7 + * added support for larger DH keys + compile-time parameter for + DH bits (workaround for OpenSSL limitation) + * added support for elliptical curve encryption + * added protocol version in X-SSL-cipher + * added "Disable PROTO" directives (fix for Poodle vulnerability) + * added Cert, Disable and Cipher directives for HTTPS back-ends. + The directive HTTPS "cert" no longer supported. + * added filtering of "Expect: 100-continue" headers + * Add support for PATCH HTTP method + * Anonymise configuration option - show last client address byte as 0 + * SSLAllowClientRenegotiation + * SSLHonorCipherOrder + * Certificate alternate names support + * poundctl shows the length of the request queue + * fixed lh_retrieve warning + * fixed potential memory leak on client certificates + * fixed alt names problem + * removed debugging messages + * fixed address comparison for RewriteLocation (IPv4/IPv6 problem) + * re-patched the redirect patch (Frank Schmierler) + * fixed RPC handling + * sanitize URLs for redirection (prevent CSRF) + * SSL disable empty fragments + SSL disable compression + (CRIME attack prevention) + * fixed bug in configuration of DISABLED directive + * changed the log level from WARNING to NOTICE if the thread arg is NULL + * fixed testing of gcc options +- Add systemd support for openSUSE > 12.3 + +------------------------------------------------------------------- Old: ---- Pound-2.6.tgz New: ---- Pound-2.7.tgz pound.service ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pound.spec ++++++ --- /var/tmp/diff_new_pack.tPDCJZ/_old 2015-03-18 13:08:22.000000000 +0100 +++ /var/tmp/diff_new_pack.tPDCJZ/_new 2015-03-18 13:08:22.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package pound # -# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -15,6 +15,11 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # +%if 0%{?suse_version} > 1230 +%bcond_without systemd +%else +%bcond_with systemd +%endif Name: pound BuildRequires: openssl-devel @@ -22,14 +27,21 @@ License: SUSE-GPL-3.0+-with-openssl-exception Group: Productivity/Networking/Web/Proxy Url: http://www.apsis.ch/pound/ -Version: 2.6 +Version: 2.7 Release: 0 Source0: http://www.apsis.ch/pound/Pound-%version.tgz Source1: pound.cfg Source2: init.pound +Source3: %{name}.service Patch: pound.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build -PreReq: pwdutils %insserv_prereq +PreReq: pwdutils +%if %{with systemd} +%{?systemd_requires} +BuildRequires: systemd-rpm-macros +%else +PreReq: %insserv_prereq +%endif %description The Pound program is a reverse proxy, load balancer and HTTPS front-end @@ -37,12 +49,6 @@ among several Web-servers and to allow for a convenient SSL wrapper for those Web servers that do not offer it natively. - - -Authors: --------- - Robert Segall <[email protected]> - %package doc Summary: Doumentation for pound Group: Documentation/Other @@ -55,12 +61,6 @@ This package contains the documentation for pound. - - -Authors: --------- - Robert Segall <[email protected]> - %prep %setup -q -n Pound-%version %patch @@ -76,39 +76,59 @@ %install %makeinstall # Install pound init script -mkdir -p $RPM_BUILD_ROOT/etc/init.d -install -m 0744 %SOURCE2 $RPM_BUILD_ROOT/etc/init.d/pound -install -m 0644 %SOURCE1 $RPM_BUILD_ROOT/etc/pound.cfg +%if %{with systemd} +install -Dm 0644 %SOURCE3 %{buildroot}/%{_unitdir}/pound.service +ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rc%{name} +%else +install -Dm 0744 %SOURCE2 $RPM_BUILD_ROOT/etc/init.d/pound ln -sf ../../etc/init.d/pound $RPM_BUILD_ROOT/usr/sbin/rcpound +%endif +install -Dm 0644 %SOURCE1 $RPM_BUILD_ROOT/etc/pound.cfg mkdir -p %buildroot%_defaultdocdir/%name/examples install -m644 GPL.txt README FAQ %buildroot%_defaultdocdir/%name/ install -m755 z2_2_5_1.py z2_2_6_1.py %buildroot%_defaultdocdir/%name/examples/ -%clean -rm -rf ${RPM_BUILD_ROOT} - %pre # Add the "pound" user and group %{_sbindir}/groupadd -r pound 2> /dev/null || : %{_sbindir}/useradd -c "Pound" -g pound -r -d /var/lib/pound pound 2> /dev/null || : +%if %{with systemd} +%service_add_pre %{name}.service +%endif %post +%if %{with systemd} +%service_add_post %{name}.service +%else %{fillup_and_insserv -f -n pound pound} +%endif %postun +%if %{with systemd} +%service_del_postun %{name}.service +%else %restart_on_update pound %insserv_cleanup +%endif %preun +%if %{with systemd} +%service_del_preun %{name}.service +%else %stop_on_removal pound +%endif %files %defattr(-,root,root) %doc %_defaultdocdir/%name/GPL.txt +%if %{with systemd} +%{_unitdir}/%{name}.service +%else /etc/init.d/pound +%endif %attr(555, root, root) /usr/sbin/pound %attr(555, root, root) /usr/sbin/poundctl -/usr/sbin/rcpound +%{_sbindir}/rcpound %_mandir/man8/pound.8.gz %_mandir/man8/poundctl.8.gz %config(noreplace) /etc/pound.cfg ++++++ Pound-2.6.tgz -> Pound-2.7.tgz ++++++ ++++ 3971 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/CHANGELOG new/Pound-2.7/CHANGELOG --- old/Pound-2.6/CHANGELOG 2011-12-28 14:57:46.000000000 +0100 +++ new/Pound-2.7/CHANGELOG 2015-01-26 17:47:53.000000000 +0100 @@ -1,4 +1,120 @@ ------------------------------------------------------------------------ +r81 | roseg | 2015-01-26 17:47:53 +0100 (Mon, 26 Jan 2015) | 30 lines + +Release 2.7 + +Enhancements: + - added support for larger DH keys + compile-time parameter for DH bits (workaround for OpenSSL limitation) + - added support for elliptical curve encryption + - added protocol version in X-SSL-cipher (Tom Fitzhenry) + - added "Disable PROTO" directives (fix for Poodle vulnerability) + - added Cert, Disable and Cipher directives for HTTPS back-ends. The directive HTTPS "cert" no longer supported. + - added filtering of "Expect: 100-continue" headers + - Add support for PATCH HTTP method + - Anonymise configuration option - show last client address byte as 0 (based on an idea by Christian Doering) + - SSLAllowClientRenegotiation (based on a patch from Joe Gooch) + - SSLHonorCipherOrder (based on a patch from Joe Gooch) + - Certificate alternate names support (based on a patch from Jonas Pasche) + - poundctl shows the length of the request queue (based on a request from Leo) + +Bug fixes: + - fixed lh_retrieve warning + - fixed potential memory leak on client certificates + - fixed alt names problem (Joe Gooch) + - removed debugging messages + - fixed address comparison for RewriteLocation (IPv4/IPv6 problem - Christopher Bartz) + - re-patched the redirect patch (Frank Schmierler) + - fixed RPC handling (Frank Schmierler) + - sanitize URLs for redirection (prevent CSRF) + - SSL disable empty fragments + SSL disable compression (CRIME attack prevention) + - fixed bug in configuration of DISABLED directive + - changed the log level from WARNING to NOTICE if the thread arg is NULL + - fixed testing of gcc options + +------------------------------------------------------------------------ +r80 | roseg | 2014-12-29 11:47:54 +0100 (Mon, 29 Dec 2014) | 10 lines + +Release 2.7f + +Enhancements: + - compile-time parameter for DH bits (workaround for OpenSSL limitation) + +Bug fixes: + - allow '-' and '=' again in URLs (redirect) + - fixed lh_retrieve warning + - fixed "Disable" regex typo + +------------------------------------------------------------------------ +r79 | roseg | 2014-12-08 14:39:00 +0100 (Mon, 08 Dec 2014) | 12 lines + +Release 2.7e + +Enhancements: + - added support for elliptical curve encryption + - added support for larger DH keys + - added protocol version in X-SSL-cipher (Tom Fitzhenry) + +Bug fixes: + - fixed potential memory leak on client certificates + - fixed alt names problem (Joe Gooch) + - removed debugging messages + +------------------------------------------------------------------------ +r78 | roseg | 2014-10-18 12:36:28 +0200 (Sat, 18 Oct 2014) | 10 lines + +Release 2.7d + +Enhancements: + - added "Disable PROTO" directives (fix for Poodle vulnerability) + - added Cert, Disable and Cipher directives for HTTPS back-ends. The + directive HTTPS "cert" no longer supported. + +Bug fixes: + - fixed address comparison for RewriteLocation (IPv4/IPv6 problem - Christopher Bartz) + +------------------------------------------------------------------------ +r77 | roseg | 2014-04-21 13:16:07 +0200 (Mon, 21 Apr 2014) | 9 lines + +Release 2.7c + +Enhancements: + - added filtering of "Expect: 100-continue" headers + +Bug fixes: + - re-patched the redirect patch (Frank Schmierler) + - fixed RPC handling (Frank Schmierler) + +------------------------------------------------------------------------ +r76 | roseg | 2013-09-26 14:33:21 +0200 (Thu, 26 Sep 2013) | 12 lines + +Release 2.7b + +Enhancements: + - Add support for PATCH HTTP method + +Bug fixes: + - sanitize URLs for redirection (prevent CSRF) + - SSL disable empty fragments + - SSL disable compression (CRIME attack prevention) + - fixed bug in configuration of DISABLED directive + - changed the log level from WARNING to NOTICE if the thread arg is NULL + +------------------------------------------------------------------------ +r75 | roseg | 2012-04-09 15:37:26 +0200 (Mon, 09 Apr 2012) | 12 lines + +Release 2.7a + +Enhancements: + - Anonymise configuration option - show last client address byte as 0 (based on an idea by Christian Doering) + - SSLAllowClientRenegotiation (based on a patch from Joe Gooch) + - SSLHonorCipherOrder (based on a patch from Joe Gooch) + - Certificate alternate names support (based on a patch from Jonas Pasche) + - poundctl shows the length of the request queue (based on a request from Leo) + +Bug fixes: + - fixed testing of gcc options + +------------------------------------------------------------------------ r74 | roseg | 2011-12-28 14:57:45 +0100 (Wed, 28 Dec 2011) | 10 lines Release 2.6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/config.c new/Pound-2.7/config.c --- old/Pound-2.6/config.c 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/config.c 2015-01-26 17:47:53.000000000 +0100 @@ -31,13 +31,15 @@ #include "pound.h" +#include <openssl/x509v3.h> + #ifdef MISS_FACILITYNAMES /* This is lifted verbatim from the Linux sys/syslog.h */ typedef struct _code { - char *c_name; - int c_val; + char *c_name; + int c_val; } CODE; static CODE facilitynames[] = { @@ -76,17 +78,18 @@ static regex_t Err414, Err500, Err501, Err503, MaxRequest, HeadRemove, RewriteLocation, RewriteDestination; static regex_t Service, ServiceName, URL, HeadRequire, HeadDeny, BackEnd, Emergency, Priority, HAport, HAportAddr; static regex_t Redirect, RedirectN, TimeOut, Session, Type, TTL, ID, DynScale; -static regex_t ClientCert, AddHeader, Ciphers, CAlist, VerifyList, CRLlist, NoHTTPS11; -static regex_t Grace, Include, ConnTO, IgnoreCase, HTTPS, HTTPSCert, Disabled, Threads, CNName; +static regex_t ClientCert, AddHeader, DisableProto, SSLAllowClientRenegotiation, SSLHonorCipherOrder, Ciphers; +static regex_t CAlist, VerifyList, CRLlist, NoHTTPS11, Grace, Include, ConnTO, IgnoreCase, HTTPS; +static regex_t Disabled, Threads, CNName, Anonymise, ECDHCurve; static regmatch_t matches[5]; static char *xhttp[] = { "^(GET|POST|HEAD) ([^ ]+) HTTP/1.[01]$", - "^(GET|POST|HEAD|PUT|DELETE) ([^ ]+) HTTP/1.[01]$", - "^(GET|POST|HEAD|PUT|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT) ([^ ]+) HTTP/1.[01]$", - "^(GET|POST|HEAD|PUT|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT|SUBSCRIBE|UNSUBSCRIBE|BPROPPATCH|POLL|BMOVE|BCOPY|BDELETE|BPROPFIND|NOTIFY|CONNECT) ([^ ]+) HTTP/1.[01]$", - "^(GET|POST|HEAD|PUT|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT|SUBSCRIBE|UNSUBSCRIBE|BPROPPATCH|POLL|BMOVE|BCOPY|BDELETE|BPROPFIND|NOTIFY|CONNECT|RPC_IN_DATA|RPC_OUT_DATA) ([^ ]+) HTTP/1.[01]$", + "^(GET|POST|HEAD|PUT|PATCH|DELETE) ([^ ]+) HTTP/1.[01]$", + "^(GET|POST|HEAD|PUT|PATCH|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT) ([^ ]+) HTTP/1.[01]$", + "^(GET|POST|HEAD|PUT|PATCH|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT|SUBSCRIBE|UNSUBSCRIBE|BPROPPATCH|POLL|BMOVE|BCOPY|BDELETE|BPROPFIND|NOTIFY|CONNECT) ([^ ]+) HTTP/1.[01]$", + "^(GET|POST|HEAD|PUT|PATCH|DELETE|LOCK|UNLOCK|PROPFIND|PROPPATCH|SEARCH|MKCOL|MOVE|COPY|OPTIONS|TRACE|MKACTIVITY|CHECKOUT|MERGE|REPORT|SUBSCRIBE|UNSUBSCRIBE|BPROPPATCH|POLL|BMOVE|BCOPY|BDELETE|BPROPFIND|NOTIFY|CONNECT|RPC_IN_DATA|RPC_OUT_DATA) ([^ ]+) HTTP/1.[01]$", }; static int log_level = 1; @@ -96,6 +99,11 @@ static int be_connto = 15; static int dynscale = 0; static int ignore_case = 0; +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH +static int EC_nid = NID_X9_62_prime256v1; +#endif +#endif #define MAX_FIN 8 @@ -167,6 +175,54 @@ } } +unsigned char ** +get_subjectaltnames(X509 *x509, unsigned int *count) +{ + unsigned int local_count; + unsigned char **result; + STACK_OF(GENERAL_NAME) *san_stack = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL); + unsigned char *temp[sk_GENERAL_NAME_num(san_stack)]; + GENERAL_NAME *name; + int i; + + local_count = 0; + result = NULL; + name = NULL; + *count = 0; + if(san_stack == NULL) + return NULL; + while(sk_GENERAL_NAME_num(san_stack) > 0) { + name = sk_GENERAL_NAME_pop(san_stack); + switch(name->type) { + case GEN_DNS: + temp[local_count] = strndup(ASN1_STRING_data(name->d.dNSName), ASN1_STRING_length(name->d.dNSName) + + 1); + if(temp[local_count] == NULL) + conf_err("out of memory"); + local_count++; + break; + default: + logmsg(LOG_INFO, "unsupported subjectAltName type encountered: %i", name->type); + } + GENERAL_NAME_free(name); + } + + result = (unsigned char**)malloc(sizeof(unsigned char*)*local_count); + if(result == NULL) + conf_err("out of memory"); + for(i = 0;i < local_count; i++) { + result[i] = strndup(temp[i], strlen(temp[i])+1); + if(result[i] == NULL) + conf_err("out of memory"); + free(temp[i]); + } + *count = local_count; + + sk_GENERAL_NAME_pop_free(san_stack, GENERAL_NAME_free); + + return result; +} + /* * parse a back-end */ @@ -200,7 +256,7 @@ lin[strlen(lin) - 1] = '\0'; if(!regexec(&Address, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; - if(get_host(lin + matches[1].rm_so, &res->addr)) { + if(get_host(lin + matches[1].rm_so, &res->addr, PF_UNSPEC)) { /* if we can't resolve it assume this is a UNIX domain socket */ res->addr.ai_socktype = SOCK_STREAM; res->addr.ai_family = AF_UNIX; @@ -264,7 +320,7 @@ if(is_emergency) conf_err("HAportAddr is not supported for Emergency back-ends"); lin[matches[1].rm_eo] = '\0'; - if(get_host(lin + matches[1].rm_so, &res->ha_addr)) { + if(get_host(lin + matches[1].rm_so, &res->ha_addr, PF_UNSPEC)) { /* if we can't resolve it assume this is a UNIX domain socket */ res->addr.ai_socktype = SOCK_STREAM; res->ha_addr.ai_family = AF_UNIX; @@ -289,16 +345,36 @@ } else if(!regexec(&HTTPS, lin, 4, matches, 0)) { if((res->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) conf_err("SSL_CTX_new failed - aborted"); + SSL_CTX_set_app_data(res->ctx, res); SSL_CTX_set_verify(res->ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_mode(res->ctx, SSL_MODE_AUTO_RETRY); +#ifdef SSL_MODE_SEND_FALLBACK_SCSV + SSL_CTX_set_mode(res->ctx, SSL_MODE_SEND_FALLBACK_SCSV); +#endif SSL_CTX_set_options(res->ctx, SSL_OP_ALL); +#ifdef SSL_OP_NO_COMPRESSION + SSL_CTX_set_options(res->ctx, SSL_OP_NO_COMPRESSION); +#endif + SSL_CTX_clear_options(res->ctx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); + SSL_CTX_clear_options(res->ctx, SSL_OP_LEGACY_SERVER_CONNECT); sprintf(lin, "%d-Pound-%ld", getpid(), random()); SSL_CTX_set_session_id_context(res->ctx, (unsigned char *)lin, strlen(lin)); SSL_CTX_set_tmp_rsa_callback(res->ctx, RSA_tmp_callback); SSL_CTX_set_tmp_dh_callback(res->ctx, DH_tmp_callback); - } else if(!regexec(&HTTPSCert, lin, 4, matches, 0)) { - if((res->ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) - conf_err("SSL_CTX_new failed - aborted"); +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH + /* This generates a EC_KEY structure with no key, but a group defined */ + EC_KEY *ecdh; + if((ecdh = EC_KEY_new_by_curve_name(EC_nid)) == NULL) + conf_err("Unable to generate temp ECDH key"); + SSL_CTX_set_tmp_ecdh(res->ctx, ecdh); + SSL_CTX_set_options(res->ctx, SSL_OP_SINGLE_ECDH_USE); + EC_KEY_free(ecdh); +#endif +#endif + } else if(!regexec(&Cert, lin, 4, matches, 0)) { + if(res->ctx == NULL) + conf_err("BackEnd Cert can only be used after HTTPS - aborted"); lin[matches[1].rm_eo] = '\0'; if(SSL_CTX_use_certificate_chain_file(res->ctx, lin + matches[1].rm_so) != 1) conf_err("SSL_CTX_use_certificate_chain_file failed - aborted"); @@ -306,13 +382,31 @@ conf_err("SSL_CTX_use_PrivateKey_file failed - aborted"); if(SSL_CTX_check_private_key(res->ctx) != 1) conf_err("SSL_CTX_check_private_key failed - aborted"); - SSL_CTX_set_verify(res->ctx, SSL_VERIFY_NONE, NULL); - SSL_CTX_set_mode(res->ctx, SSL_MODE_AUTO_RETRY); - SSL_CTX_set_options(res->ctx, SSL_OP_ALL); - sprintf(lin, "%d-Pound-%ld", getpid(), random()); - SSL_CTX_set_session_id_context(res->ctx, (unsigned char *)lin, strlen(lin)); - SSL_CTX_set_tmp_rsa_callback(res->ctx, RSA_tmp_callback); - SSL_CTX_set_tmp_dh_callback(res->ctx, DH_tmp_callback); + } else if(!regexec(&Ciphers, lin, 4, matches, 0)) { + if(res->ctx == NULL) + conf_err("BackEnd Ciphers can only be used after HTTPS - aborted"); + lin[matches[1].rm_eo] = '\0'; + SSL_CTX_set_cipher_list(res->ctx, lin + matches[1].rm_so); + } else if(!regexec(&DisableProto, lin, 4, matches, 0)) { + if(res->ctx == NULL) + conf_err("BackEnd Disable can only be used after HTTPS - aborted"); + lin[matches[1].rm_eo] = '\0'; + if(strcasecmp(lin + matches[1].rm_so, "SSLv2") == 0) + SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2); + else if(strcasecmp(lin + matches[1].rm_so, "SSLv3") == 0) + SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); +#ifdef SSL_OP_NO_TLSv1 + else if(strcasecmp(lin + matches[1].rm_so, "TLSv1") == 0) + SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); +#endif +#ifdef SSL_OP_NO_TLSv1_1 + else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_1") == 0) + SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); +#endif +#ifdef SSL_OP_NO_TLSv1_2 + else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_2") == 0) + SSL_CTX_set_options(res->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); +#endif } else if(!regexec(&Disabled, lin, 4, matches, 0)) { res->disabled = atoi(lin + matches[1].rm_so); } else if(!regexec(&End, lin, 4, matches, 0)) { @@ -601,9 +695,11 @@ } else if(!regexec(&Disabled, lin, 4, matches, 0)) { res->disabled = atoi(lin + matches[1].rm_so); } else if(!regexec(&End, lin, 4, matches, 0)) { - for(be = res->backends; be; be = be->next) - res->tot_pri += be->priority; - res->abs_pri = res->tot_pri; + for(be = res->backends; be; be = be->next) { + if(!be->disabled) + res->tot_pri += be->priority; + res->abs_pri += be->priority; + } return res; } else { conf_err("unknown directive"); @@ -669,7 +765,7 @@ lin[strlen(lin) - 1] = '\0'; if(!regexec(&Address, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; - if(get_host(lin + matches[1].rm_so, &res->addr)) + if(get_host(lin + matches[1].rm_so, &res->addr, PF_UNSPEC)) conf_err("Unknown Listener address"); if(res->addr.ai_family != AF_INET && res->addr.ai_family != AF_INET6) conf_err("Unknown Listener address family"); @@ -805,13 +901,24 @@ /* logmsg(LOG_DEBUG, "Received SSL SNI Header for servername %s", servername); */ SSL_set_SSL_CTX(ssl, NULL); - for(pc = ctx; pc; pc = pc->next) + for(pc = ctx; pc; pc = pc->next) { if(fnmatch(pc->server_name, server_name, 0) == 0) { /* logmsg(LOG_DEBUG, "Found cert for %s", servername); */ SSL_set_SSL_CTX(ssl, pc->ctx); return SSL_TLSEXT_ERR_OK; } + else if(pc->subjectAltNameCount > 0 && pc->subjectAltNames != NULL) { + int i; + for(i = 0; i < pc->subjectAltNameCount; i++) { + if(fnmatch(pc->subjectAltNames[i], server_name, 0) == 0) { + SSL_set_SSL_CTX(ssl, pc->ctx); + return SSL_TLSEXT_ERR_OK; + } + } + } + } + /* logmsg(LOG_DEBUG, "No match for %s, default used", server_name); */ SSL_set_SSL_CTX(ssl, ctx->ctx); return SSL_TLSEXT_ERR_OK; @@ -824,15 +931,23 @@ static LISTENER * parse_HTTPS(void) { - char lin[MAXBUF]; - LISTENER *res; - SERVICE *svc; - MATCHER *m; - int has_addr, has_port, has_other; + char lin[MAXBUF]; + LISTENER *res; + SERVICE *svc; + MATCHER *m; + int has_addr, has_port, has_other; + long ssl_op_enable, ssl_op_disable; struct hostent *host; struct sockaddr_in in; struct sockaddr_in6 in6; - POUND_CTX *pc; + POUND_CTX *pc; + + ssl_op_enable = SSL_OP_ALL; +#ifdef SSL_OP_NO_COMPRESSION + ssl_op_enable |= SSL_OP_NO_COMPRESSION; +#endif + ssl_op_disable = SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION | SSL_OP_LEGACY_SERVER_CONNECT + | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; if((res = (LISTENER *)malloc(sizeof(LISTENER))) == NULL) conf_err("ListenHTTPS config: out of memory - aborted"); @@ -844,6 +959,7 @@ res->err500 = "An internal server error occurred. Please try again later."; res->err501 = "This method may not be used."; res->err503 = "The service is not available. Please try again later."; + res->allow_client_reneg = 0; res->log_level = log_level; if(regcomp(&res->verb, xhttp[0], REG_ICASE | REG_NEWLINE | REG_EXTENDED)) conf_err("xHTTP bad default pattern - aborted"); @@ -853,7 +969,7 @@ lin[strlen(lin) - 1] = '\0'; if(!regexec(&Address, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; - if(get_host(lin + matches[1].rm_so, &res->addr)) + if(get_host(lin + matches[1].rm_so, &res->addr, PF_UNSPEC)) conf_err("Unknown Listener address"); if(res->addr.ai_family != AF_INET && res->addr.ai_family != AF_INET6) conf_err("Unknown Listener address family"); @@ -959,6 +1075,9 @@ fclose(fcert); memset(server_name, '\0', MAXBUF); X509_NAME_oneline(X509_get_subject_name(x509), server_name, MAXBUF - 1); + pc->subjectAltNameCount = 0; + pc->subjectAltNames = NULL; + pc->subjectAltNames = get_subjectaltnames(x509, &(pc->subjectAltNameCount)); X509_free(x509); if(!regexec(&CNName, server_name, 4, matches, 0)) { server_name[matches[1].rm_eo] = '\0'; @@ -1029,6 +1148,41 @@ strcat(res->add_head, "\r\n"); strcat(res->add_head, lin + matches[1].rm_so); } + } else if(!regexec(&DisableProto, lin, 4, matches, 0)) { + lin[matches[1].rm_eo] = '\0'; + if(strcasecmp(lin + matches[1].rm_so, "SSLv2") == 0) + ssl_op_enable |= SSL_OP_NO_SSLv2; + else if(strcasecmp(lin + matches[1].rm_so, "SSLv3") == 0) + ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; +#ifdef SSL_OP_NO_TLSv1 + else if(strcasecmp(lin + matches[1].rm_so, "TLSv1") == 0) + ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1; +#endif +#ifdef SSL_OP_NO_TLSv1_1 + else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_1") == 0) + ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; +#endif +#ifdef SSL_OP_NO_TLSv1_2 + else if(strcasecmp(lin + matches[1].rm_so, "TLSv1_2") == 0) + ssl_op_enable |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; +#endif + } else if(!regexec(&SSLAllowClientRenegotiation, lin, 4, matches, 0)) { + res->allow_client_reneg = atoi(lin + matches[1].rm_so); + if (res->allow_client_reneg == 2) { + ssl_op_enable |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + ssl_op_disable &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + } else { + ssl_op_disable |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + ssl_op_enable &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + } + } else if(!regexec(&SSLHonorCipherOrder, lin, 4, matches, 0)) { + if (atoi(lin + matches[1].rm_so)) { + ssl_op_enable |= SSL_OP_CIPHER_SERVER_PREFERENCE; + ssl_op_disable &= ~SSL_OP_CIPHER_SERVER_PREFERENCE; + } else { + ssl_op_disable |= SSL_OP_CIPHER_SERVER_PREFERENCE; + ssl_op_enable &= ~SSL_OP_CIPHER_SERVER_PREFERENCE; + } } else if(!regexec(&Ciphers, lin, 4, matches, 0)) { has_other = 1; if(res->ctx == NULL) @@ -1100,17 +1254,32 @@ if(!has_addr || !has_port || res->ctx == NULL) conf_err("ListenHTTPS missing Address, Port or Certificate - aborted"); #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - if(!SSL_CTX_set_tlsext_servername_callback(res->ctx->ctx, SNI_server_name) - || !SSL_CTX_set_tlsext_servername_arg(res->ctx->ctx, res->ctx)) - conf_err("ListenHTTPS: can't set SNI callback"); + if(res->ctx->next) + if(!SSL_CTX_set_tlsext_servername_callback(res->ctx->ctx, SNI_server_name) + || !SSL_CTX_set_tlsext_servername_arg(res->ctx->ctx, res->ctx)) + conf_err("ListenHTTPS: can't set SNI callback"); #endif for(pc = res->ctx; pc; pc = pc->next) { + SSL_CTX_set_app_data(pc->ctx, res); SSL_CTX_set_mode(pc->ctx, SSL_MODE_AUTO_RETRY); - SSL_CTX_set_options(pc->ctx, SSL_OP_ALL); + SSL_CTX_set_options(pc->ctx, ssl_op_enable); + SSL_CTX_clear_options(pc->ctx, ssl_op_disable); sprintf(lin, "%d-Pound-%ld", getpid(), random()); SSL_CTX_set_session_id_context(pc->ctx, (unsigned char *)lin, strlen(lin)); SSL_CTX_set_tmp_rsa_callback(pc->ctx, RSA_tmp_callback); SSL_CTX_set_tmp_dh_callback(pc->ctx, DH_tmp_callback); + SSL_CTX_set_info_callback(pc->ctx, SSLINFO_callback); +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH + /* This generates a EC_KEY structure with no key, but a group defined */ + EC_KEY *ecdh; + if((ecdh = EC_KEY_new_by_curve_name(EC_nid)) == NULL) + conf_err("Unable to generate temp ECDH key"); + SSL_CTX_set_tmp_ecdh(pc->ctx, ecdh); + SSL_CTX_set_options(pc->ctx, SSL_OP_SINGLE_ECDH_USE); + EC_KEY_free(ecdh); +#endif +#endif } return res; } else { @@ -1181,6 +1350,14 @@ be_connto = atoi(lin + matches[1].rm_so); } else if(!regexec(&IgnoreCase, lin, 4, matches, 0)) { ignore_case = atoi(lin + matches[1].rm_so); +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH + } else if(!regexec(&ECDHCurve, lin, 4, matches, 0)) { + lin[matches[1].rm_eo] = '\0'; + if((EC_nid = OBJ_sn2nid(lin + matches[1].rm_so)) == 0) + conf_err("ECDHCurve config: invalid curve name"); +#endif +#endif #if HAVE_OPENSSL_ENGINE_H } else if(!regexec(&SSLEngine, lin, 4, matches, 0)) { lin[matches[1].rm_eo] = '\0'; @@ -1238,6 +1415,8 @@ ; svc->next = parse_service(lin + matches[1].rm_so); } + } else if(!regexec(&Anonymise, lin, 4, matches, 0)) { + anonymise = 1; } else { conf_err("unknown directive - aborted"); } @@ -1305,6 +1484,9 @@ || regcomp(&DynScale, "^[ \t]*DynScale[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&ClientCert, "^[ \t]*ClientCert[ \t]+([0-3])[ \t]+([1-9])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&AddHeader, "^[ \t]*AddHeader[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&SSLAllowClientRenegotiation, "^[ \t]*SSLAllowClientRenegotiation[ \t]+([012])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&DisableProto, "^[ \t]*Disable[ \t]+(SSLv2|SSLv3|TLSv1|TLSv1_1|TLSv1_2)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&SSLHonorCipherOrder, "^[ \t]*SSLHonorCipherOrder[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&Ciphers, "^[ \t]*Ciphers[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CAlist, "^[ \t]*CAlist[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&VerifyList, "^[ \t]*VerifyList[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) @@ -1314,9 +1496,14 @@ || regcomp(&ConnTO, "^[ \t]*ConnTO[ \t]+([1-9][0-9]*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&IgnoreCase, "^[ \t]*IgnoreCase[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&HTTPS, "^[ \t]*HTTPS[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) - || regcomp(&HTTPSCert, "^[ \t]*HTTPS[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) - || regcomp(&Disabled, "^[ \t]*Disabled[ \t]+[01][ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&Disabled, "^[ \t]*Disabled[ \t]+([01])[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CNName, ".*[Cc][Nn]=([-*.A-Za-z0-9]+).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) + || regcomp(&Anonymise, "^[ \t]*Anonymise[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH + || regcomp(&ECDHCurve, "^[ \t]*ECDHCurve[ \t]+\"(.+)\"[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) +#endif +#endif ) { logmsg(LOG_ERR, "bad config Regex - aborted"); exit(1); @@ -1373,6 +1560,10 @@ if(strcmp(C_GROUP, "")) logmsg(LOG_DEBUG, " --with-group=%s", C_GROUP); #endif +#ifdef C_DH_LEN + if(strcmp(C_DH_LEN, "0")) + logmsg(LOG_DEBUG, " --with-dh=%s", C_DH_LEN); +#endif logmsg(LOG_DEBUG, "Exiting..."); exit(0); break; @@ -1463,6 +1654,9 @@ regfree(&DynScale); regfree(&ClientCert); regfree(&AddHeader); + regfree(&SSLAllowClientRenegotiation); + regfree(&DisableProto); + regfree(&SSLHonorCipherOrder); regfree(&Ciphers); regfree(&CAlist); regfree(&VerifyList); @@ -1472,9 +1666,14 @@ regfree(&ConnTO); regfree(&IgnoreCase); regfree(&HTTPS); - regfree(&HTTPSCert); regfree(&Disabled); regfree(&CNName); + regfree(&Anonymise); +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +#ifndef OPENSSL_NO_ECDH + regfree(&ECDHCurve); +#endif +#endif /* set the facility only here to ensure the syslog gets opened if necessary */ log_facility = def_facility; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/http.c new/Pound-2.7/http.c --- old/Pound-2.6/http.c 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/http.c 2015-01-26 17:47:53.000000000 +0100 @@ -52,7 +52,8 @@ static void redirect_reply(BIO *const c, const char *url, const int code) { - char rep[MAXBUF], cont[MAXBUF], *code_msg; + char rep[MAXBUF], cont[MAXBUF], safe_url[MAXBUF], *code_msg; + int i, j; switch(code) { case 301: @@ -65,12 +66,24 @@ code_msg = "Found"; break; } + /* + * Make sure to return a safe version of the URL (otherwise CSRF becomes a possibility) + */ + memset(safe_url, 0, MAXBUF); + for(i = j = 0; i < MAXBUF && j < MAXBUF && url[i]; i++) + if(isalnum(url[i]) || url[i] == '_' || url[i] == '.' || url[i] == ':' || url[i] == '/' + || url[i] == '?' || url[i] == '&' || url[i] == ';' || url[i] == '-' || url[i] == '=') + safe_url[j++] = url[i]; + else { + sprintf(safe_url + j, "%%%02x", url[i]); + j += 3; + } snprintf(cont, sizeof(cont), "<html><head><title>Redirect</title></head><body><h1>Redirect</h1><p>You should go to <a href=\"%s\">%s</a></p></body></html>", - url, url); + safe_url, safe_url); snprintf(rep, sizeof(rep), "HTTP/1.0 %d %s\r\nLocation: %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n", - code, code_msg, url, strlen(cont)); + code, code_msg, safe_url, strlen(cont)); BIO_write(c, rep, strlen(rep)); BIO_write(c, cont, strlen(cont)); BIO_flush(c); @@ -246,6 +259,11 @@ static int err_to = -1; +typedef struct { + int timeout; + RENEG_STATE *reneg_state; +} BIO_ARG; + /* * Time-out for client read/gets * the SSL manual says not to do it, but it works well enough anyway... @@ -253,6 +271,7 @@ static long bio_callback(BIO *const bio, const int cmd, const char *argp, int argi, long argl, long ret) { + BIO_ARG *bio_arg; struct pollfd p; int to, p_res, p_err; @@ -260,11 +279,24 @@ return ret; /* a time-out already occured */ - if((to = *((int *)BIO_get_callback_arg(bio)) * 1000) < 0) { + if((bio_arg = (BIO_ARG*)BIO_get_callback_arg(bio))==NULL) + return ret; + if((to = bio_arg->timeout * 1000) < 0) { errno = ETIMEDOUT; return -1; } + /* Renegotiations */ + /* logmsg(LOG_NOTICE, "RENEG STATE %d", bio_arg->reneg_state==NULL?-1:*bio_arg->reneg_state); */ + if (bio_arg->reneg_state != NULL && *bio_arg->reneg_state == RENEG_ABORT) { + logmsg(LOG_NOTICE, "REJECTING renegotiated session"); + errno = ECONNABORTED; + return -1; + } + + if (to == 0) + return ret; + for(;;) { memset(&p, 0, sizeof(p)); BIO_get_fd(bio, &p.fd); @@ -299,7 +331,7 @@ return -1; case 0: /* timeout - mark the BIO as unusable for the future */ - BIO_set_callback_arg(bio, (char *)&err_to); + bio_arg->timeout = err_to; #ifdef EBUG logmsg(LOG_WARNING, "(%lx) CALLBACK timeout poll after %d secs: %s", pthread_self(), to / 1000, strerror(p_err)); @@ -503,7 +535,14 @@ regmatch_t matches[4]; struct linger l; double start_req, end_req; + RENEG_STATE reneg_state; + BIO_ARG ba1, ba2; + reneg_state = RENEG_INIT; + ba1.reneg_state = &reneg_state; + ba2.reneg_state = &reneg_state; + ba1.timeout = 0; + ba2.timeout = 0; from_host = ((thr_arg *)arg)->from_host; memcpy(&from_host_addr, from_host.ai_addr, from_host.ai_addrlen); from_host.ai_addr = (struct sockaddr *)&from_host_addr; @@ -512,6 +551,9 @@ free(((thr_arg *)arg)->from_host.ai_addr); free(arg); + if(lstn->allow_client_reneg) + reneg_state = RENEG_ALLOW; + n = 1; setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&n, sizeof(n)); l.l_onoff = 1; @@ -535,10 +577,9 @@ close(sock); return; } - if(lstn->to > 0) { - BIO_set_callback_arg(cl, (char *)&lstn->to); - BIO_set_callback(cl, bio_callback); - } + ba1.timeout = lstn->to; + BIO_set_callback_arg(cl, (char *)&ba1); + BIO_set_callback(cl, bio_callback); if(lstn->ctx != NULL) { if((ssl = SSL_new(lstn->ctx->ctx)) == NULL) { @@ -547,6 +588,7 @@ BIO_free_all(cl); return; } + SSL_set_app_data(ssl, &reneg_state); SSL_set_bio(ssl, cl, cl); if((bb = BIO_new(BIO_f_ssl())) == NULL) { logmsg(LOG_WARNING, "(%lx) BIO_new(Bio_f_ssl()) failed", pthread_self()); @@ -572,6 +614,7 @@ && SSL_get_verify_result(ssl) != X509_V_OK) { addr2str(caddr, MAXBUF - 1, &from_host, 1); logmsg(LOG_NOTICE, "Bad certificate from %s", caddr); + X509_free(x509); BIO_reset(cl); BIO_free_all(cl); return; @@ -584,6 +627,8 @@ if((bb = BIO_new(BIO_f_buffer())) == NULL) { logmsg(LOG_WARNING, "(%lx) BIO_new(buffer) failed", pthread_self()); + if(x509 != NULL) + X509_free(x509); BIO_reset(cl); BIO_free_all(cl); return; @@ -679,9 +724,21 @@ case HEADER_CONTENT_LENGTH: if(chunked || cont >= 0L) headers_ok[n] = 0; - else - if((cont = ATOL(buf)) < 0L) - headers_ok[n] = 0; + else { + if((cont = ATOL(buf)) < 0L) + headers_ok[n] = 0; + if(is_rpc == 1 && (cont < 0x20000L || cont > 0x80000000L)) + is_rpc = -1; + } + break; + case HEADER_EXPECT: + /* + * we do NOT support the "Expect: 100-continue" headers + * support may involve severe performance penalties (non-responding back-end, etc) + * as a stop-gap measure we just skip these headers + */ + if(!strcasecmp("100-continue", buf)) + headers_ok[n] = 0; break; case HEADER_ILLEGAL: if(lstn->log_level > 0) { @@ -848,7 +905,8 @@ } BIO_set_close(be, BIO_CLOSE); if(backend->to > 0) { - BIO_set_callback_arg(be, (char *)&backend->to); + ba2.timeout = backend->to; + BIO_set_callback_arg(be, (char *)&ba2); BIO_set_callback(be, bio_callback); } if(backend->ctx != NULL) { @@ -952,12 +1010,12 @@ /* if SSL put additional headers for client certificate */ if(cur_backend->be_type == 0 && ssl != NULL) { - SSL_CIPHER *cipher; + const SSL_CIPHER *cipher; if((cipher = SSL_get_current_cipher(ssl)) != NULL) { SSL_CIPHER_description(cipher, buf, MAXBUF - 1); strip_eol(buf); - if(BIO_printf(be, "X-SSL-cipher: %s\r\n", buf) <= 0) { + if(BIO_printf(be, "X-SSL-cipher: %s/%s\r\n", SSL_get_version(ssl), buf) <= 0) { str_be(buf, MAXBUF - 1, cur_backend); end_req = cur_time(); logmsg(LOG_WARNING, "(%lx) e500 error write X-SSL-cipher to %s: %s (%.3f sec)", @@ -1339,8 +1397,12 @@ case HEADER_CONTENT_LENGTH: cont = ATOL(buf); /* treat RPC_OUT_DATA like reply without content-length */ - if(is_rpc == 0 && cont == 0x40000000L) - cont = -1L; + if(is_rpc == 0) { + if(cont >= 0x20000L && cont <= 0x80000000L) + cont = -1L; + else + is_rpc = -1; + } break; case HEADER_LOCATION: if(v_host[0] && need_rewrite(lstn->rewr_loc, buf, loc_path, v_host, lstn, cur_backend)) { @@ -1497,6 +1559,12 @@ memset(s_res_bytes, 0, LOG_BYTES_SIZE); log_bytes(s_res_bytes, res_bytes); addr2str(caddr, MAXBUF - 1, &from_host, 1); + if(anonymise) { + char *last; + + if((last = strrchr(caddr, '.')) != NULL || (last = strrchr(caddr, ':')) != NULL) + strcpy(++last, "0"); + } str_be(buf, MAXBUF - 1, cur_backend); switch(lstn->log_level) { case 0: @@ -1568,7 +1636,7 @@ for(;;) { while((arg = get_thr_arg()) == NULL) - logmsg(LOG_WARNING, "NULL get_thr_arg"); + logmsg(LOG_NOTICE, "NULL get_thr_arg"); do_http(arg); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/pound.8 new/Pound-2.7/pound.8 --- old/Pound-2.6/pound.8 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/pound.8 2015-01-26 17:47:53.000000000 +0100 @@ -310,6 +310,9 @@ Use an OpenSSL hardware acceleration card called \fIname\fR. Available only if OpenSSL-engine is installed on your system. .TP +\fBECDHcurve\fR "name" +Use the named curve for elliptical curve encryption (default: prime256v1). +.TP \fBControl\fR "/path/to/socket" Set the control socket path. If not defined .B Pound @@ -320,6 +323,10 @@ .TP \fBInclude\fR "/path/to/file" Include the file as though it were part of the configuration file. +.TP +\fBAnonymise\fR +Replace the last byte of the client address with 0 for logging purposes. +Default: log the client address in full. .SH "HTTP Listener" An HTTP listener defines an address and port that .B Pound @@ -356,7 +363,7 @@ (default) accept only standard HTTP requests (GET, POST, HEAD). .IP .I 1 -additionally allow extended HTTP requests (PUT, DELETE). +additionally allow extended HTTP requests (PUT, PATCH, DELETE). .IP .I 2 additionally allow standard WebDAV verbs (LOCK, UNLOCK, PROPFIND, @@ -494,6 +501,13 @@ depth limit is 9, allowing for the peer certificate and additional 9 CA certificates that must be verified. .TP +\fBDisable\fR SSLv2|SSLv3|TLSv1|TLSv1_1|TLSv1_2 +Disable the protocol \fBand all lower protocols as well\fR. +This is due to a limitation in OpenSSL, which does not support disabling a single +protocol. For example, +.I Disable TLSv1 +would disable SSLv2, SSLv3 and TLSv1, thus allowing only TLSv1_1 and TLSv1_2. +.TP \fBCiphers\fR "acceptable:cipher:list" This is the list of ciphers that will be accepted by the SSL connection; it is a string in the same format as in OpenSSL @@ -501,6 +515,20 @@ and .I SSL_CTX_set_cipher_list(3). .TP +\fBSSLHonorCipherOrder\fR 0|1 +If this value is 1, the server will broadcast a preference to use \fBCiphers\fR in +the order supplied in the \fBCiphers\fR directive. If the value is 0, the server +will treat the Ciphers list as the list of Ciphers it will accept, but no preference +will be indicated. Default value is 0. +.TP +\fBSSLAllowClientRenegotiation\fR 0|1|2 +If this value is 0, client initiated renegotiation will be disabled. This will +mitigate DoS exploits based on client renegotiation, regardless of the patch status +of clients and servers related to "Secure renegotiation". If the value is 1, secure +renegotiation is supported. If the value is 2, insecure renegotiation is supported, +with unpatched clients. \fBThis can lead to a DoS and a Man in the Middle attack!\fR +The default value is 0. +.TP \fBCAlist\fR "CAcert_file" Set the list of "trusted" CA's for this server. The CAcert_file is a file containing a sequence of CA certificates (PEM format). The names of the defined CA certificates @@ -548,7 +576,9 @@ .B Pound returns an error. You may define multiple .I URL -conditions per service. If no +conditions per service, in which case +.B all +patterns must match. If no .I URL was defined then all requests match. The matching is by default case-sensitive, but this can be overridden by specifying @@ -695,12 +725,38 @@ .B mandatory parameter for non Unix-domain back-ends. .TP -\fBHTTPS\fR [ "cert" ] -The back-end is using HTTPS. If the optional parameter -.I cert -is specified, +\fBHTTPS\fR +The back-end is using HTTPS. +.TP +\fBCert\fR "certificate file" +Specify the certificate that .B Pound -will present this certificate to the back-end. +will use as a client. The +.I certificate file +is the file containing the certificate, possibly a certificate chain and the signature. +This directive may appear only after the +.I HTTPS +directive. +.TP +\fBDisable\fR SSLv2|SSLv3|TLSv1|TLSv1_1|TLSv1_2 +Disable the protocol \fBand all lower protocols as well\fR. +This is due to a limitation in OpenSSL, which does not support disabling a single +protocol. For example, +.I Disable TLSv1 +would disable SSLv2, SSLv3 and TLSv1, thus allowing only TLSv1_1 and TLSv1_2. +This directive may appear only after the +.I HTTPS +directive. +.TP +\fBCiphers\fR "acceptable:cipher:list" +This is the list of ciphers that will be accepted by the SSL connection; it is a +string in the same format as in OpenSSL +.I ciphers(1) +and +.I SSL_CTX_set_cipher_list(3). +This directive may appear only after the +.I HTTPS +directive. .TP \fBPriority\fR val The priority of this back-end (between 1 and 9, 5 is default). Higher priority diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/pound.c new/Pound-2.7/pound.c --- old/Pound-2.6/pound.c 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/pound.c 2015-01-26 17:47:53.000000000 +0100 @@ -35,6 +35,7 @@ *ctrl_name; /* control socket name */ int alive_to, /* check interval for resurrection */ + anonymise, /* anonymise client address */ daemonize, /* run as daemon */ log_facility, /* log facility to use */ print_log, /* print log messages to stdout/stderr */ @@ -167,6 +168,21 @@ } /* + * get the current queue length + */ +get_thr_qlen(void) +{ + int res; + thr_arg *tap; + + (void)pthread_mutex_lock(&arg_mut); + for(res = 0, tap = first; tap != NULL; tap = tap->next, res++) + ; + (void)pthread_mutex_unlock(&arg_mut); + return res; +} + +/* * handle SIGTERM/SIGQUIT - exit */ static RETSIGTYPE @@ -251,6 +267,23 @@ CRYPTO_set_locking_callback(l_lock); init_timer(); + /* Disable SSL Compression for OpenSSL pre-1.0. 1.0 is handled with an option in config.c */ +#if OPENSSL_VERSION_NUMBER >= 0x00907000L +#ifndef SSL_OP_NO_COMPRESSION + { + int i,n; + STACK_OF(SSL_COMP) *ssl_comp_methods; + + ssl_comp_methods = SSL_COMP_get_compression_methods(); + n = sk_SSL_COMP_num(ssl_comp_methods); + + for(i=n-1; i>=0; i--) { + sk_SSL_COMP_delete(ssl_comp_methods, i); + } + } +#endif +#endif + /* prepare regular expressions */ if(regcomp(&HEADER, "^([a-z0-9!#$%&'*+.^_`|~-]+):[ \t]*(.*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) || regcomp(&CHUNK_HEAD, "^([0-9a-f]+).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/pound.h new/Pound-2.7/pound.h --- old/Pound-2.6/pound.h 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/pound.h 2015-01-26 17:47:53.000000000 +0100 @@ -267,6 +267,7 @@ *ctrl_name; /* control socket name */ extern int numthreads, /* number of worker threads */ + anonymise, /* anonymise client address */ alive_to, /* check interval for resurrection */ daemonize, /* run as daemon */ log_facility, /* log facility to use */ @@ -379,31 +380,35 @@ typedef struct _pound_ctx { SSL_CTX *ctx; char *server_name; + unsigned char **subjectAltNames; + unsigned int subjectAltNameCount; struct _pound_ctx *next; } POUND_CTX; /* Listener definition */ typedef struct _listener { - struct addrinfo addr; /* IPv4/6 address */ - int sock; /* listening socket */ - POUND_CTX *ctx; /* CTX for SSL connections */ - int clnt_check; /* client verification mode */ - int noHTTPS11; /* HTTP 1.1 mode for SSL */ - char *add_head; /* extra SSL header */ - regex_t verb; /* pattern to match the request verb against */ - int to; /* client time-out */ - int has_pat; /* was a URL pattern defined? */ - regex_t url_pat; /* pattern to match the request URL against */ - char *err414, /* error messages */ + struct addrinfo addr; /* IPv4/6 address */ + int sock; /* listening socket */ + POUND_CTX *ctx; /* CTX for SSL connections */ + int clnt_check; /* client verification mode */ + int noHTTPS11; /* HTTP 1.1 mode for SSL */ + char *add_head; /* extra SSL header */ + regex_t verb; /* pattern to match the request verb against */ + int to; /* client time-out */ + int has_pat; /* was a URL pattern defined? */ + regex_t url_pat; /* pattern to match the request URL against */ + char *err414, /* error messages */ *err500, *err501, *err503; - LONG max_req; /* max. request size */ - MATCHER *head_off; /* headers to remove */ - int rewr_loc; /* rewrite location response */ - int rewr_dest; /* rewrite destination header */ - int disabled; /* true if the listener is disabled */ - int log_level; /* log level for this listener */ + LONG max_req; /* max. request size */ + MATCHER *head_off; /* headers to remove */ + int rewr_loc; /* rewrite location response */ + int rewr_dest; /* rewrite destination header */ + int disabled; /* true if the listener is disabled */ + int log_level; /* log level for this listener */ + int allow_client_reneg; /* Allow Client SSL Renegotiation */ + int disable_ssl_v2; /* Disable SSL version 2 */ SERVICE *services; struct _listener *next; } LISTENER; @@ -419,6 +424,9 @@ struct _thr_arg *next; } thr_arg; /* argument to processing threads: socket, origin */ +/* Track SSL handshare/renegotiation so we can reject client-renegotiations. */ +typedef enum { RENEG_INIT=0, RENEG_REJECT, RENEG_ALLOW, RENEG_ABORT } RENEG_STATE; + /* Header types */ #define HEADER_ILLEGAL -1 #define HEADER_OTHER 0 @@ -432,6 +440,7 @@ #define HEADER_USER_AGENT 8 #define HEADER_URI 9 #define HEADER_DESTINATION 10 +#define HEADER_EXPECT 11 /* control request stuff */ typedef enum { @@ -476,6 +485,11 @@ extern thr_arg *get_thr_arg(void); /* + * get the current queue length + */ +extern get_thr_qlen(void); + +/* * handle an HTTP request */ extern void *thr_http(void *); @@ -513,7 +527,7 @@ /* * Search for a host name, return the addrinfo for it */ -extern int get_host(char *const, struct addrinfo *); +extern int get_host(char *const, struct addrinfo *, int); /* * Find if a redirect needs rewriting @@ -577,7 +591,7 @@ */ #define N_RSA_KEYS 11 #ifndef T_RSA_KEYS -#define T_RSA_KEYS 1800 +#define T_RSA_KEYS 7200 #endif /* @@ -591,6 +605,11 @@ extern DH *DH_tmp_callback(SSL *, int, int); /* + * Renegotiation callback + */ +extern void SSLINFO_callback(const SSL *s, int where, int rc); + +/* * expiration stuff */ #ifndef EXPIRE_TO diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/poundctl.c new/Pound-2.7/poundctl.c --- old/Pound-2.6/poundctl.c 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/poundctl.c 2015-01-26 17:47:53.000000000 +0100 @@ -342,9 +342,16 @@ write(sock, &cmd, sizeof(cmd)); if (!is_set) { + int n; + n_lstn = 0; if(xml_out) printf("<pound>\n"); + if(read(sock, &n, sizeof(n)) == sizeof(n)) + if(xml_out) + printf("<queue size=\"%d\"/>\n", n); + else + printf("Requests in queue: %d\n", n); while(read(sock, (void *)&lstn, sizeof(LISTENER)) == sizeof(LISTENER)) { if(lstn.disabled < 0) break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/Pound-2.6/svc.c new/Pound-2.7/svc.c --- old/Pound-2.6/svc.c 2011-12-28 14:57:45.000000000 +0100 +++ new/Pound-2.7/svc.c 2015-01-26 17:47:53.000000000 +0100 @@ -82,7 +82,11 @@ TABNODE t, *res; t.key = key; +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + if((res = (TABNODE *)LHM_lh_retrieve(TABNODE, tab, &t)) != NULL) { +#else if((res = (TABNODE *)lh_retrieve(tab, &t)) != NULL) { +#endif res->last_acc = time(NULL); return res->content; } @@ -390,6 +394,7 @@ { "Referer", 7, HEADER_REFERER }, { "User-agent", 10, HEADER_USER_AGENT }, { "Destination", 11, HEADER_DESTINATION }, + { "Expect", 6, HEADER_EXPECT }, { "", 0, HEADER_OTHER }, }; int i; @@ -749,7 +754,7 @@ * Search for a host name, return the addrinfo for it */ int -get_host(char *const name, struct addrinfo *res) +get_host(char *const name, struct addrinfo *res, int ai_family) { struct addrinfo *chain, *ap; struct addrinfo hints; @@ -757,7 +762,7 @@ #ifdef HAVE_INET_NTOP memset (&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; + hints.ai_family = ai_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_CANONNAME; if((ret_val = getaddrinfo(name, NULL, &hints, &chain)) == 0) { @@ -800,7 +805,6 @@ struct sockaddr_in6 in6_addr, be6_addr; regmatch_t matches[4]; char *proto, *host, *port, *cp, buf[MAXBUF]; - int ret_val; /* check if rewriting is required at all */ if(rewr_loc == 0) @@ -827,7 +831,7 @@ * Check if the location has the same address as the listener or the back-end */ memset(&addr, 0, sizeof(addr)); - if(get_host(host, &addr)) + if(get_host(host, &addr, be->addr.ai_family)) return 0; /* @@ -837,31 +841,37 @@ free(addr.ai_addr); return 0; } - memset(buf, '\0', MAXBUF); - strncpy(buf, v_host, MAXBUF - 1); - if((cp = strchr(buf, ':')) != NULL) - *cp = '\0'; if(addr.ai_family == AF_INET) { + memcpy(&in_addr, addr.ai_addr, sizeof(in_addr)); + memcpy(&be_addr, be->addr.ai_addr, sizeof(be_addr)); + if(port) + in_addr.sin_port = (in_port_t)htons(atoi(port)); + else if(!strcasecmp(proto, "https")) + in_addr.sin_port = (in_port_t)htons(443); + else + in_addr.sin_port = (in_port_t)htons(80); /* - * check if the Location points to the Listener but with the wrong port or protocol + * check if the Location points to the back-end */ - memcpy(&be_addr, lstn->addr.ai_addr, sizeof(be_addr)); - if((memcmp(&be_addr.sin_addr.s_addr, &in_addr.sin_addr.s_addr, sizeof(in_addr.sin_addr.s_addr)) == 0 - || strcasecmp(host, buf) == 0) - && (memcmp(&be_addr.sin_port, &in_addr.sin_port, sizeof(in_addr.sin_port)) != 0 - || strcasecmp(proto, (lstn->ctx == NULL)? "http": "https"))) { + if(memcmp(&be_addr.sin_addr.s_addr, &in_addr.sin_addr.s_addr, sizeof(in_addr.sin_addr.s_addr)) == 0 + && memcmp(&be_addr.sin_port, &in_addr.sin_port, sizeof(in_addr.sin_port)) == 0) { free(addr.ai_addr); return 1; } } else /* AF_INET6 */ { + memcpy(&in6_addr, addr.ai_addr, sizeof(in6_addr)); + memcpy(&be6_addr, be->addr.ai_addr, sizeof(be6_addr)); + if(port) + in6_addr.sin6_port = (in_port_t)htons(atoi(port)); + else if(!strcasecmp(proto, "https")) + in6_addr.sin6_port = (in_port_t)htons(443); + else + in6_addr.sin6_port = (in_port_t)htons(80); /* - * check if the Location points to the Listener but with the wrong port or protocol + * check if the Location points to the back-end */ - memcpy(&be6_addr, lstn->addr.ai_addr, sizeof(be6_addr)); - if((memcmp(&be6_addr.sin6_addr.s6_addr, &in6_addr.sin6_addr.s6_addr, sizeof(in6_addr.sin6_addr.s6_addr)) == 0 - || strcasecmp(host, buf) == 0) - && (memcmp(&be6_addr.sin6_port, &in6_addr.sin6_port, sizeof(in6_addr.sin6_port)) != 0 - || strcasecmp(proto, (lstn->ctx == NULL)? "http": "https"))) { + if(memcmp(&be6_addr.sin6_addr.s6_addr, &in6_addr.sin6_addr.s6_addr, sizeof(in6_addr.sin6_addr.s6_addr)) == 0 + && memcmp(&be6_addr.sin6_port, &in6_addr.sin6_port, sizeof(in6_addr.sin6_port)) == 0) { free(addr.ai_addr); return 1; } @@ -874,25 +884,29 @@ free(addr.ai_addr); return 0; } + memset(buf, '\0', MAXBUF); + strncpy(buf, v_host, MAXBUF - 1); + if((cp = strchr(buf, ':')) != NULL) + *cp = '\0'; if(addr.ai_family == AF_INET) { - memcpy(&in_addr, addr.ai_addr, sizeof(in_addr)); memcpy(&be_addr, lstn->addr.ai_addr, sizeof(be_addr)); /* * check if the Location points to the Listener but with the wrong port or protocol */ - if(memcmp(&be_addr.sin_addr.s_addr, &in_addr.sin_addr.s_addr, sizeof(in_addr.sin_addr.s_addr)) == 0 + if((memcmp(&be_addr.sin_addr.s_addr, &in_addr.sin_addr.s_addr, sizeof(in_addr.sin_addr.s_addr)) == 0 + || strcasecmp(host, buf) == 0) && (memcmp(&be_addr.sin_port, &in_addr.sin_port, sizeof(in_addr.sin_port)) != 0 || strcasecmp(proto, lstn->ctx? "http": "https"))) { free(addr.ai_addr); return 1; } } else { - memcpy(&in6_addr, addr.ai_addr, sizeof(in6_addr)); memcpy(&be6_addr, lstn->addr.ai_addr, sizeof(be6_addr)); /* * check if the Location points to the Listener but with the wrong port or protocol */ - if(memcmp(&be6_addr.sin6_addr.s6_addr, &in6_addr.sin6_addr.s6_addr, sizeof(in6_addr.sin6_addr.s6_addr)) == 0 + if((memcmp(&be6_addr.sin6_addr.s6_addr, &in6_addr.sin6_addr.s6_addr, sizeof(in6_addr.sin6_addr.s6_addr)) == 0 + || strcasecmp(host, buf) == 0) && (memcmp(&be6_addr.sin6_port, &in6_addr.sin6_port, sizeof(in6_addr.sin6_port)) != 0 || strcasecmp(proto, lstn->ctx? "http": "https"))) { free(addr.ai_addr); @@ -1435,8 +1449,9 @@ } #include "dh512.h" -#include "dh1024.h" +#if DH_LEN == 1024 +#include "dh1024.h" static DH *DH512_params, *DH1024_params; DH * @@ -1444,6 +1459,16 @@ { return keylength == 512? DH512_params: DH1024_params; } +#else +#include "dh2048.h" +static DH *DH512_params, *DH2048_params; + +DH * +DH_tmp_callback(/* not used */SSL *s, /* not used */int is_export, int keylength) +{ + return keylength == 512? DH512_params: DH2048_params; +} +#endif static time_t last_RSA, last_rescale, last_alive, last_expire; @@ -1475,7 +1500,11 @@ pthread_mutex_init(&RSA_mut, NULL); DH512_params = get_dh512(); +#if DH_LEN == 1024 DH1024_params = get_dh1024(); +#else + DH2048_params = get_dh2048(); +#endif return; } @@ -1638,7 +1667,7 @@ { CTRL_CMD cmd; struct sockaddr sa; - int ctl, dummy, ret_val; + int ctl, dummy, n, ret_val; LISTENER *lstn, dummy_lstn; SERVICE *svc, dummy_svc; BACKEND *be, dummy_be; @@ -1676,6 +1705,8 @@ switch(cmd.cmd) { case CTRL_LST: /* logmsg(LOG_INFO, "thr_control() list"); */ + n = get_thr_qlen(); + (void)write(ctl, (void *)&n, sizeof(n)); for(lstn = listeners; lstn; lstn = lstn->next) { (void)write(ctl, (void *)lstn, sizeof(LISTENER)); (void)write(ctl, lstn->addr.ai_addr, lstn->addr.ai_addrlen); @@ -1777,7 +1808,7 @@ logmsg(LOG_WARNING, "thr_control() add session lock: %s", strerror(ret_val)); t_add(svc->sessions, cmd.key, &be, sizeof(be)); if(ret_val = pthread_mutex_unlock(&svc->mut)) - logmsg(LOG_WARNING, "thr_control() add session unlock: %s", strerror(ret_val)); + logmsg(LOG_WARNING, "thoriginalfiler_control() add session unlock: %s", strerror(ret_val)); break; case CTRL_DEL_SESS: if((svc = sel_svc(&cmd)) == NULL) { @@ -1797,3 +1828,27 @@ close(ctl); } } + +void +SSLINFO_callback(const SSL *ssl, int where, int rc) +{ + RENEG_STATE *reneg_state; + + /* Get our thr_arg where we're tracking this connection info */ + if((reneg_state = (RENEG_STATE *)SSL_get_app_data(ssl)) == NULL) + return; + + /* If we're rejecting renegotiations, move to ABORT if Client Hello is being read. */ + if((where & SSL_CB_ACCEPT_LOOP) && *reneg_state == RENEG_REJECT) { + int state; + + state = SSL_get_state(ssl); + if (state == SSL3_ST_SR_CLNT_HELLO_A || state == SSL23_ST_SR_CLNT_HELLO_A) { + *reneg_state = RENEG_ABORT; + logmsg(LOG_WARNING,"rejecting client initiated renegotiation"); + } + } else if(where & SSL_CB_HANDSHAKE_DONE && *reneg_state == RENEG_INIT) { + // Reject any followup renegotiations + *reneg_state = RENEG_REJECT; + } +} ++++++ pound.service ++++++ [Unit] Description=A reverse proxy, load balancer, and SSL wrapper [Service] Type=forking PIDFile=/run/pound.pid ExecStart=/usr/bin/pound -f /etc/pound.cfg -p /run/pound.pid [Install] WantedBy=multi-user.target -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
