[squid-dev] [PATCH] Crypto-NG: Use Security::PeerOptions for listening port TLS settings

Amos Jeffries squid3 at treenet.co.nz
Tue Jun 30 15:27:29 UTC 2015


Sorry for the size of this one. The bulk of this patch is symbol
shuffling to de-duplicate the TLS settings storage and parsing code.

The actual changes are relatively small:

* Shuffle relevant AnyP::PortCfg settings into a Security::PeerOptions
member object.
 - removes a lot of duplicate config parsing code.

* Shuffle flags= and options= parsing code from Ssl:: to
Security::PeerOptions and update to use Tokenizer,
 - fixes performance regression using c_str() on the stored SBuf,
 - fixes performance issue with xstrdup() for option tokens,
 - removes several calls to c-string manipulation.

* Add cachemgr 'config' report dumper of Security::PeerOptions for use
by all directives using it to dump tls-* parameter names. The old
parameter names are still accepted, and deprecation will follow in a
separate patch.
 - fixes bug where cache_peer was not dumping out its SSL/TLS config
settings at all.

* Remove the now obsolete and unused Ssl::OpenSSLtoSquidSSLVersion()

* Change the tls_outgoing_options default value from "disable" which did
not parse previously (now does). To setting TLS/1.0 minimum version with
SSLv3 disabled.

* Fix tls-min-version=1.N handling not to alter stored options= config
string. Now updates the binary representation in parsedOptions directly.

* Expose the TLS context creation and configuration to non-OpenSSL builds.
 - fixes bug where context creation by OpenSSL failed silently.


Amos
-------------- next part --------------
=== modified file 'doc/release-notes/release-4.sgml'
--- doc/release-notes/release-4.sgml	2015-06-19 07:13:57 +0000
+++ doc/release-notes/release-4.sgml	2015-06-29 12:56:55 +0000
@@ -23,74 +23,80 @@
 <p>We welcome feedback and bug reports. If you find a bug, please see <url url="http://wiki.squid-cache.org/SquidFaq/BugReporting">
    for how to submit a report with a stack trace.
 
 <sect1>Known issues
 <p>
 Although this release is deemed good enough for use in many setups, please note the existence of 
 <url url="http://bugs.squid-cache.org/buglist.cgi?query_format=advanced&product=Squid&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&version=4" name="open bugs against Squid-4">.
 
 <sect1>Changes since earlier releases of Squid-4
 <p>
 The Squid-4 change history can be <url url="http://www.squid-cache.org/Versions/v4/changesets/" name="viewed here">.
 
 
 <sect>Major new features since Squid-3.5
 <p>Squid 4 represents a new feature release above 3.5.
 
 <p>The most important of these new features are:
 <itemize>
 	<item>Helper concurrency channels changes
 	<item>Configurable helper queue size
-	<item>SSLv2 support removal
+	<item>SSL support removal
 	<item>MSNT-multi-domain helper removal
 </itemize>
 
 Most user-facing changes are reflected in squid.conf (see below).
 
 
 <sect1>Configurable helper queue size
 <p>The new queue-size=N option to helpers configuration, allows users 
 to configure the maximum number of queued requests to busy helpers.
 
 <sect1>Helper concurrency channels changes
 <p> helper-mux.pl we have been distributing for the past few years to
     encourage use of concurrency is no longer compatible with Squid. If
     used it will spawn up to 2^64 helpers and DoS the Squid server.
 
 <p> Helpers utilizing arrays to handle fixed amounts of concurrency
     channels MUST be re-written to use queues and capable of handling a
     64-bit int as index or they will be vulnerable to buffer overrun and
     arbitrary memory accesses.
 
 <p> 32-bit helpers need re-writing to handle the concurrency channel ID
     as a 64-bit integer value. If not updated they will cause proxies to
     return unexpected results or timeout once crossing the 32-bit wrap
     boundary. Leading to undefined behaviour in the client HTTP traffic.
 
-<sect1>SSLv2 support removal
+<sect1>SSL support removal
 <p>Details in <url url="https://tools.ietf.org/html/rfc6176" name="RFC 6176">
+   and <url url="https://tools.ietf.org/html/rfc7568" name="RFC 7568">
 
 <p>SSLv2 is not fit for purpose. Squid no longer supports being configured with
 any settings regarding this protocol. That includes settings manually disabling
 its use since it is now forced to disable by default. Also settings enabling
 various client/server workarounds specific to SSLv2 are removed.
 
+<p>SSLv3 is not fit for purpose. Squid still accepts configuration, but use
+is deprecated and will be removed entirely in a future version.
+Squid default behavour is to follow the TLS built in negotiation mechanism
+which prefers the latest TLS version.
+
 
 <sect1>MSNT-multi-domain helper removal
 
 <p>The <em>basic_msnt_multi_domain_auth</em> helper has been removed. The
    <em>basic_smb_lm_auth</em> helper performs the same actions without extra
    Perl and Samba dependencies.
 
 
 <sect>Changes to squid.conf since Squid-3.5
 <p>
 There have been changes to Squid's configuration file since Squid-3.5.
 
 This section gives a thorough account of those changes in three categories:
 
 <itemize>
 	<item><ref id="newtags" name="New tags">
 	<item><ref id="modifiedtags" name="Changes to existing tags">
 	<item><ref id="removedtags" name="Removed tags">
 </itemize>
 <p>
@@ -101,59 +107,61 @@
 	<tag>tls_outgoing_options</tag>
 	<p>New tag to define TLS security context options for outgoing
 	   connections. For example to HTTPS servers.
 
 	<tag>url_rewrite_timeout</tag>
 	<p>Squid times active requests to redirector. This option sets
 	   the timeout value and the Squid reaction to a timed out
 	   request.
 
 </descrip>
 
 <sect1>Changes to existing tags<label id="modifiedtags">
 <p>
 <descrip>
 	<tag>auth_param</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number
 	   of queued requests.
 
 	<tag>cache_peer</tag>
 	<p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
-	<p>All <em>ssloptions=</em> values for
-	   SSLv2 configuration or disabling have been removed.
-	<p>Removed <em>sslversion=</em> option. Use <em>ssloptions=</em> instead.
+	<p>All <em>ssloptions=</em> values for SSLv2 configuration or disabling
+	   have been removed.
+	<p>Removed <em>sslversion=</em> option. Use <em>tls-options=</em> instead.
 	<p>Manual squid.conf update may be required on upgrade.
 
 	<tag>external_acl_type</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number
 	   of queued requests.
 
 	<tag>http_port</tag>
-	<p>All <em>option=</em> values for SSLv2
-	   configuration or disabling have been removed.
-	<p>Removed <em>version=</em> option. Use <em>options=</em> instead.
+	<p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
+	<p>All <em>option=</em> values for SSLv2 configuration or disabling
+	   have been removed.
+	<p>Removed <em>version=</em> option. Use <em>tls-options=</em> instead.
 	<p>Manual squid.conf update may be required on upgrade.
 
 	<tag>https_port</tag>
+	<p>New option <em>tls-min-version=1.N</em> to set minimum TLS version allowed.
 	<p>All <em>options=</em> values for SSLv2
 	   configuration or disabling have been removed.
-	<p>Removed <em>version=</em> option. Use <em>options=</em> instead.
+	<p>Removed <em>version=</em> option. Use <em>tls-options=</em> instead.
 	<p>New <em>options=SINGLE_ECDH_USE</em> parameter to enable ephemeral
 	   ECDH key exchange.
 	<p>Deprecated <em>dhparams=</em> option. Use <em>tls-dh=</em> instead.
 	   The new option allows to optionally specify an elliptic curve for
 	   ephemeral ECDH by adding <em>curve-name:</em> in front of the
 	   parameter file name.
 	<p>Manual squid.conf update may be required on upgrade.
 
 	<tag>refresh_pattern</tag>
 	<p>Removed <em>ignore-auth</em>. Its commonly desired behaviour is
 	   performed by default with correct HTTP/1.1 revalidation.
 	<p>Removed <em>ignore-must-revalidate</em>. Other more HTTP compliant
 	   directives can be used to prevent objects from caching.
 
 	<tag>sslcrtd_children</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number
 	   of queued requests.
 
 	<tag>sslcrtvalidator_children</tag>
 	<p>New parameter <em>queue-size=</em> to set the maximum number

=== modified file 'src/CachePeer.h'
--- src/CachePeer.h	2015-02-26 10:25:12 +0000
+++ src/CachePeer.h	2015-03-23 08:56:03 +0000
@@ -165,32 +165,31 @@
     struct {
         unsigned int hash;
         double load_multiplier;
         double load_factor; /* normalized weight value */
     } sourcehash;
 
     char *login;        /* Proxy authorization */
     time_t connect_timeout;
     int connect_fail_limit;
     int max_conn;
     struct {
         PconnPool *pool; ///< idle connection pool for this peer
         CbcPointer<PeerPoolMgr> mgr; ///< pool manager
         int limit; ///< the limit itself
         bool waitingForClose; ///< a conn must close before we open a standby conn
     } standby; ///< optional "cache_peer standby=limit" feature
     char *domain;       /* Forced domain */
 
     /// security settings for peer connection
     Security::PeerOptions secure;
-
+    Security::ContextPointer sslContext;
 #if USE_OPENSSL
-    SSL_CTX *sslContext;
     SSL_SESSION *sslSession;
 #endif
 
     int front_end_https;
     int connection_auth;
 };
 
 #endif /* SQUID_CACHEPEER_H_ */
 

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2015-06-01 06:21:54 +0000
+++ src/Makefile.am	2015-06-28 14:15:53 +0000
@@ -590,49 +590,49 @@
 
 nodist_squid_SOURCES = \
 	$(DISKIO_GEN_SOURCE) \
 	$(BUILT_SOURCES)
 
 squid_LDADD = \
 	$(AUTH_ACL_LIBS) \
 	ident/libident.la \
 	acl/libacls.la \
 	acl/libstate.la \
 	$(AUTH_LIBS) \
 	$(DISK_LIBS) \
 	acl/libapi.la \
 	clients/libclients.la \
 	servers/libservers.la \
 	ftp/libftp.la \
 	helper/libhelper.la \
 	http/libsquid-http.la \
 	parser/libsquid-parser.la \
 	dns/libdns.la \
-	security/libsecurity.la \
 	base/libbase.la \
 	libsquid.la \
 	ip/libip.la \
 	fs/libfs.la \
 	$(SSL_LIBS) \
 	ipc/libipc.la \
 	mgr/libmgr.la \
 	anyp/libanyp.la \
+	security/libsecurity.la \
 	comm/libcomm.la \
 	eui/libeui.la \
 	icmp/libicmp.la icmp/libicmp-core.la \
 	log/liblog.la \
 	format/libformat.la \
 	$(XTRA_OBJS) \
 	$(DISK_LINKOBJS) \
 	$(REPL_OBJS) \
 	$(DISK_OS_LIBS) \
 	$(NETTLELIB) \
 	$(CRYPTLIB) \
 	$(REGEXLIB) \
 	$(ADAPTATION_LIBS) \
 	$(ESI_LIBS) \
 	$(SNMP_LIBS) \
 	mem/libmem.la \
 	$(top_builddir)/lib/libmisccontainers.la \
 	$(top_builddir)/lib/libmiscencoding.la \
 	$(top_builddir)/lib/libmiscutil.la \
 	$(SSLLIB) \
@@ -1149,40 +1149,41 @@
 	tests/stub_SBufDetailedStats.cc \
 	String.cc \
 	StrList.h \
 	StrList.cc \
 	log/access_log.h \
 	tests/stub_access_log.cc \
 	cache_cf.h \
 	YesNoNone.h \
 	tests/stub_cache_cf.cc \
 	tests/stub_cache_manager.cc \
 	tests/stub_comm.cc \
 	tests/stub_debug.cc \
 	tests/stub_errorpage.cc \
 	tests/stub_event.cc \
 	tests/stub_fd.cc \
 	tests/stub_HelperChildConfig.cc \
 	tests/stub_libformat.cc \
 	tests/stub_libauth.cc \
 	tests/stub_libcomm.cc \
 	tests/stub_libmgr.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_libsslsquid.cc \
 	StatCounters.h \
 	StatCounters.cc \
 	StatHist.h \
 	tests/stub_StatHist.cc \
 	repl_modules.h \
 	tests/stub_store.cc \
 	tests/stub_store_stats.cc \
 	tools.h \
 	tests/stub_tools.cc \
 	tests/stub_HttpRequest.cc \
 	tests/testHttpReply.cc \
 	tests/testHttpReply.h \
 	tests/stub_time.cc \
 	url.cc \
 	wordlist.h \
 	wordlist.cc
 nodist_tests_testHttpReply_SOURCES=\
 	$(TESTSOURCES)
 tests_testHttpReply_LDFLAGS = $(LIBADD_DL)
@@ -1231,40 +1232,41 @@
 	HttpHeaderTools.cc \
 	HttpHdrContRange.cc \
 	HttpHdrRange.cc \
 	HttpHeaderFieldStat.h \
 	HttpHdrCc.h \
 	HttpHdrCc.cc \
 	HttpHdrCc.cci \
 	HttpHdrSc.cc \
 	HttpHdrScTarget.cc \
 	HttpMsg.cc \
 	int.h \
 	int.cc \
 	MasterXaction.cc \
 	MasterXaction.h \
 	Notes.cc \
 	Notes.h \
 	SquidList.h \
 	SquidList.cc \
 	mem_node.cc \
 	Parsing.cc \
+	tests/stub_libsecurity.cc \
 	SquidMath.cc \
 	StatCounters.cc \
 	StatCounters.h \
 	StatHist.h \
 	StrList.h \
 	StrList.cc \
 	tests/stub_StatHist.cc \
 	stmem.cc \
 	$(SBUF_SOURCE) \
 	SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc \
 	String.cc \
 	store_dir.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	swap_log_op.cc \
@@ -1656,40 +1658,41 @@
 	HttpHeader.cc \
 	HttpMsg.cc \
 	HttpReply.cc \
 	int.h \
 	int.cc \
 	SquidList.h \
 	SquidList.cc \
 	MasterXaction.cc \
 	MasterXaction.h \
 	MemBuf.cc \
 	MemObject.cc \
 	mem_node.cc \
 	Notes.h \
 	Notes.cc \
 	Parsing.cc \
 	refresh.h \
 	refresh.cc \
 	RemovalPolicy.cc \
 	RequestFlags.h \
 	RequestFlags.cc \
+	tests/stub_libsecurity.cc \
 	StatCounters.h \
 	StatCounters.cc \
 	StatHist.h \
 	tests/stub_StatHist.cc \
 	stmem.cc \
 	$(SBUF_SOURCE) \
 	SBufDetailedStats.h \
 	tests/stub_SBufDetailedStats.cc \
 	StoreFileSystem.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
 	store_dir.cc \
 	store_io.cc \
 	store_key_md5.h \
 	store_key_md5.cc \
 	store_swapout.cc \
 	store_swapmeta.cc \
 	repl_modules.h \
@@ -2135,41 +2138,40 @@
 	HttpHdrCc.cci \
 	HttpHdrContRange.cc \
 	HttpHdrRange.cc \
 	HttpHdrSc.cc \
 	HttpHdrScTarget.cc \
 	HttpMsg.cc \
 	HttpReply.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
 	RequestFlags.h \
 	RequestFlags.cc \
 	HttpRequest.cc \
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.h \
 	int.cc \
 	internal.h \
 	internal.cc \
-	tests/stub_libsecurity.cc \
 	SquidList.h \
 	SquidList.cc \
 	MasterXaction.cc \
 	MasterXaction.h \
 	MemBuf.cc \
 	MemObject.cc \
 	tests/stub_libmem.cc \
 	mem_node.cc \
 	mime.h \
 	mime.cc \
 	mime_header.h \
 	mime_header.cc \
 	multicast.h \
 	multicast.cc \
 	neighbors.h \
 	neighbors.cc \
 	Notes.cc \
 	Notes.h \
 	Parsing.cc \
 	pconn.cc \
@@ -2216,40 +2218,41 @@
 	store_swapin.h \
 	store_swapin.cc \
 	store_swapmeta.cc \
 	store_swapout.cc \
 	StoreFileSystem.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
 	String.cc \
 	StrList.h \
 	StrList.cc \
 	tests/stub_SwapDir.cc \
 	tests/testEventLoop.cc \
 	tests/testEventLoop.h \
 	tests/stub_main_cc.cc \
 	tests/stub_ipc_Forwarder.cc \
 	tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc \
 	tests/stub_libeui.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_store_stats.cc \
 	time.cc \
 	tools.h \
 	tools.cc \
 	Transients.cc \
 	tests/stub_tunnel.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
 	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
 	tests/stub_wccp2.cc \
 	whois.h \
 	tests/stub_whois.cc \
 	$(WIN32_SOURCE) \
 	wordlist.h \
 	wordlist.cc
 nodist_tests_testEventLoop_SOURCES = \
 	$(BUILT_SOURCES) \
@@ -2375,41 +2378,40 @@
 	HttpHeader.h \
 	HttpHeader.cc \
 	HttpHeaderFieldInfo.h \
 	HttpHeaderTools.h \
 	HttpHeaderTools.cc \
 	HttpMsg.cc \
 	HttpReply.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
 	RequestFlags.h \
 	RequestFlags.cc \
 	HttpRequest.cc \
 	icp_v2.cc \
 	icp_v3.cc \
 	int.h \
 	int.cc \
 	internal.h \
 	internal.cc \
 	$(IPC_SOURCE) \
 	ipcache.cc \
-	tests/stub_libsecurity.cc \
 	SquidList.h \
 	SquidList.cc \
 	MasterXaction.cc \
 	MasterXaction.h \
 	MemBuf.cc \
 	MemObject.cc \
 	tests/stub_libmem.cc \
 	mem_node.cc \
 	mime.h \
 	mime.cc \
 	mime_header.h \
 	mime_header.cc \
 	multicast.h \
 	multicast.cc \
 	neighbors.h \
 	neighbors.cc \
 	Notes.cc \
 	Notes.h \
 	Parsing.cc \
 	peer_digest.cc \
@@ -2454,40 +2456,41 @@
 	store_rebuild.h \
 	store_rebuild.cc \
 	store_swapin.h \
 	store_swapin.cc \
 	store_swapmeta.cc \
 	store_swapout.cc \
 	StoreFileSystem.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
 	String.cc \
 	StrList.h \
 	StrList.cc \
 	tests/stub_SwapDir.cc \
 	Transients.cc \
 	tests/test_http_range.cc \
 	tests/stub_external_acl.cc \
 	tests/stub_ipc_Forwarder.cc \
 	tests/stub_libeui.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_main_cc.cc \
 	tests/stub_MemStore.cc \
 	tests/stub_store_stats.cc \
 	tests/stub_EventLoop.cc \
 	time.cc \
 	tools.h \
 	tools.cc \
 	tests/stub_tunnel.cc \
 	$(UNLINKDSOURCE) \
 	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
 	tests/stub_wccp2.cc \
 	whois.h \
 	tests/stub_whois.cc \
 	$(WIN32_SOURCE) \
 	wordlist.h \
 	wordlist.cc
 nodist_tests_test_http_range_SOURCES = \
@@ -2542,40 +2545,41 @@
 tests_testHttp1Parser_SOURCES = \
 	Debug.h \
 	MemBuf.cc \
 	MemBuf.h \
 	tests/stub_MemObject.cc \
 	tests/stub_libmem.cc \
 	mime_header.cc \
 	mime_header.h \
 	String.cc \
 	cache_cf.h \
 	YesNoNone.h \
 	$(SBUF_SOURCE) \
 	tests/stub_SBufDetailedStats.cc \
 	tests/stub_cache_cf.cc \
 	tests/stub_cache_manager.cc \
 	tests/stub_comm.cc \
 	tests/stub_cbdata.cc \
 	tests/stub_debug.cc \
 	tests/stub_event.cc \
 	tests/stub_HelperChildConfig.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_stmem.cc \
 	tests/stub_store.cc \
 	tests/stub_store_stats.cc \
 	tools.h \
 	tests/stub_tools.cc \
 	tests/testHttp1Parser.cc \
 	tests/testHttp1Parser.h \
 	tests/stub_time.cc \
 	wordlist.h \
 	wordlist.cc
 nodist_tests_testHttp1Parser_SOURCES = \
 	$(TESTSOURCES)
 tests_testHttp1Parser_LDADD= \
 	http/libsquid-http.la \
 	parser/libsquid-parser.la \
 	anyp/libanyp.la \
 	SquidConfig.o \
 	base/libbase.la \
 	ip/libip.la \
 	$(top_builddir)/lib/libmiscutil.la \
@@ -2908,40 +2912,41 @@
 	tests/stub_access_log.cc \
 	tests/stub_acl.cc \
 	cache_cf.h \
 	YesNoNone.h \
 	tests/stub_cache_cf.cc \
 	tests/stub_cache_manager.cc \
 	tests/stub_client_side_request.cc \
 	tests/stub_comm.cc \
 	tests/stub_debug.cc \
 	tests/stub_DiskIOModule.cc \
 	tests/stub_errorpage.cc \
 	fd.h \
 	fde.h \
 	tests/stub_fd.cc \
 	tests/stub_helper.cc \
 	tests/stub_HelperChildConfig.cc \
 	tests/stub_http.cc \
 	tests/stub_libauth.cc \
 	tests/stub_libeui.cc \
 	tests/stub_libformat.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_libsslsquid.cc \
 	HttpBody.h \
 	HttpBody.cc \
 	tests/stub_HttpReply.cc \
 	tests/stub_HttpRequest.cc \
 	tests/stub_libcomm.cc \
 	tests/stub_MemStore.cc \
 	mime.h \
 	tests/stub_mime.cc \
 	tests/stub_Port.cc \
 	tests/stub_stat.cc \
 	tests/stub_store_client.cc \
 	tests/stub_store_stats.cc \
 	store_rebuild.h \
 	tests/stub_store_rebuild.cc \
 	tests/stub_store_swapout.cc \
 	tools.h \
 	Transients.cc \
 	tests/stub_tools.cc \
 	tests/stub_UdsOp.cc \
@@ -3058,40 +3063,41 @@
 tests_testUfs_SOURCES = \
 	tests/testUfs.cc \
 	tests/testUfs.h \
 	tests/stub_cache_manager.cc \
 	tests/stub_client_db.cc \
 	tests/stub_CollapsedForwarding.cc \
 	tests/stub_HelperChildConfig.cc \
 	tests/stub_icp.cc \
 	tests/stub_ipc.cc \
 	tests/stub_ipcache.cc \
 	tests/stub_libeui.cc \
 	tests/stub_libicmp.cc \
 	tests/stub_MemStore.cc \
 	tests/stub_neighbors.cc \
 	tests/stub_pconn.cc \
 	tests/stub_Port.cc \
 	tests/stub_UdsOp.cc \
 	internal.h \
 	tests/stub_internal.cc \
 	tests/stub_libformat.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_stat.cc \
 	store_rebuild.h \
 	tests/stub_store_rebuild.cc \
 	tests/stub_store_stats.cc \
 	fatal.h \
 	tests/stub_fatal.cc \
 	fd.h \
 	fd.cc \
 	fde.h \
 	fde.cc \
 	client_db.h \
 	disk.h \
 	disk.cc \
 	FileMap.h \
 	filemap.cc \
 	HttpBody.h \
 	HttpBody.cc \
 	HttpReply.cc \
 	int.h \
 	int.cc \
@@ -3334,40 +3340,41 @@
 	cache_cf.h \
 	YesNoNone.h \
 	tests/stub_cache_cf.cc \
 	client_db.h \
 	tests/stub_cache_manager.cc \
 	tests/stub_client_db.cc \
 	tests/stub_client_side_request.cc \
 	tests/stub_debug.cc \
 	tests/stub_errorpage.cc \
 	tests/stub_HelperChildConfig.cc \
 	tests/stub_http.cc \
 	tests/stub_HttpRequest.cc \
 	tests/stub_libauth.cc \
 	tests/stub_icp.cc \
 	tests/stub_ipc.cc \
 	tests/stub_ipcache.cc \
 	tests/stub_libeui.cc \
 	tests/stub_libformat.cc \
 	tests/stub_libicmp.cc \
 	tests/stub_libmgr.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_MemStore.cc \
 	mime.h \
 	tests/stub_mime.cc \
 	tests/stub_neighbors.cc \
 	tests/stub_Port.cc \
 	tests/stub_pconn.cc \
 	tests/stub_store_client.cc \
 	store_rebuild.h \
 	tests/stub_store_rebuild.cc \
 	tests/stub_store_stats.cc \
 	tools.h \
 	tests/stub_tools.cc \
 	time.cc \
 	url.cc \
 	wordlist.h \
 	wordlist.cc \
 	$(DELAY_POOL_SOURCE) \
 	$(DISKIO_SOURCE) \
 	$(UNLINKDSOURCE)
 nodist_tests_testRock_SOURCES = \
@@ -3486,41 +3493,40 @@
 	HttpHeader.h \
 	HttpHeader.cc \
 	HttpHeaderFieldInfo.h \
 	HttpHeaderTools.h \
 	HttpHeaderTools.cc \
 	HttpMsg.cc \
 	HttpReply.cc \
 	PeerPoolMgr.h \
 	PeerPoolMgr.cc \
 	RequestFlags.h \
 	RequestFlags.cc \
 	HttpRequest.cc \
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.h \
 	int.cc \
 	internal.h \
 	internal.cc \
-	tests/stub_libsecurity.cc \
 	SquidList.h \
 	SquidList.cc \
 	MasterXaction.cc \
 	MasterXaction.h \
 	multicast.h \
 	multicast.cc \
 	tests/stub_libmem.cc \
 	mem_node.cc \
 	MemBuf.cc \
 	MemObject.cc \
 	mime.h \
 	mime.cc \
 	mime_header.h \
 	mime_header.cc \
 	neighbors.h \
 	neighbors.cc \
 	Notes.h \
 	Notes.cc \
 	Parsing.cc \
 	pconn.cc \
@@ -3566,40 +3572,41 @@
 	store_rebuild.cc \
 	store_swapin.h \
 	store_swapin.cc \
 	store_swapmeta.cc \
 	store_swapout.cc \
 	StoreFileSystem.cc \
 	StoreIOState.cc \
 	tests/stub_StoreMeta.cc \
 	StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc \
 	String.cc \
 	StrList.h \
 	StrList.cc \
 	Transients.cc \
 	tests/stub_SwapDir.cc \
 	MemStore.cc \
 	tests/stub_debug.cc \
 	tests/stub_DiskIOModule.cc \
 	tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc \
+	tests/stub_libsecurity.cc \
 	tests/stub_main_cc.cc \
 	tests/stub_ipc_Forwarder.cc \
 	tests/stub_store_stats.cc \
 	tests/testURL.cc \
 	tests/testURL.h \
 	tests/testUriScheme.cc \
 	tests/testUriScheme.h \
 	tests/stub_time.cc \
 	tests/stub_EventLoop.cc \
 	tools.h \
 	tools.cc \
 	tests/stub_tunnel.cc \
 	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
 	tests/stub_wccp2.cc \
 	whois.h \
 	tests/stub_whois.cc \
 	FadingCounter.cc \

=== modified file 'src/SquidConfig.h'
--- src/SquidConfig.h	2015-05-15 12:50:09 +0000
+++ src/SquidConfig.h	2015-06-13 07:27:11 +0000
@@ -1,46 +1,43 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SQUIDCONFIG_H_
 #define SQUID_SQUIDCONFIG_H_
 
 #include "acl/forward.h"
 #include "base/RefCount.h"
 #include "ClientDelayConfig.h"
 #include "DelayConfig.h"
 #include "helper/ChildConfig.h"
 #include "HttpHeaderTools.h"
 #include "ip/Address.h"
 #include "Notes.h"
+#include "security/forward.h"
 #include "YesNoNone.h"
 
 #if USE_OPENSSL
-#if HAVE_OPENSSL_SSL_H
-#include <openssl/ssl.h>
-#endif
-
 class sslproxy_cert_sign;
 class sslproxy_cert_adapt;
 #endif
 
 namespace Mgr
 {
 class ActionPasswordList;
 } // namespace Mgr
 class CustomLog;
 class CpuAffinityMap;
 class external_acl;
 class HeaderManglers;
 class RefreshPattern;
 class RemovalPolicySettings;
 class SwapDir;
 
 namespace AnyP
 {
 class PortCfg;
 }
@@ -475,48 +472,48 @@
         int unclean_shutdown;
         char *ssl_engine;
         int session_ttl;
         size_t sessionCacheSize;
         char *certSignHash;
     } SSL;
 #endif
 
     wordlist *ext_methods;
 
     struct {
         int high_rptm;
         int high_pf;
         size_t high_memory;
     } warnings;
     char *store_dir_select_algorithm;
     int sleep_after_fork;   /* microseconds */
     time_t minimum_expiry_time; /* seconds */
     external_acl *externalAclHelperList;
 
-#if USE_OPENSSL
     struct {
+        Security::ContextPointer sslContext;
+#if USE_OPENSSL
         acl_access *cert_error;
-        SSL_CTX *sslContext;
         sslproxy_cert_sign *cert_sign;
         sslproxy_cert_adapt *cert_adapt;
-    } ssl_client;
 #endif
+    } ssl_client;
 
     char *accept_filter;
     int umask;
     int max_filedescriptors;
     int workers;
     CpuAffinityMap *cpuAffinityMap;
 
 #if USE_LOADABLE_MODULES
     wordlist *loadable_module_names;
 #endif
 
     int client_ip_max_connections;
 
     char *redirector_extras;
 
     struct UrlHelperTimeout {
         int action;
         char *response;
     } onUrlRewriteTimeout;
 

=== modified file 'src/adaptation/icap/ServiceRep.cc'
--- src/adaptation/icap/ServiceRep.cc	2015-05-26 17:25:04 +0000
+++ src/adaptation/icap/ServiceRep.cc	2015-06-13 12:06:24 +0000
@@ -67,41 +67,41 @@
     const bool have_port = cfg().port >= 0;
     if (!have_port) {
         struct servent *serv;
         if (cfg().protocol.caseCmp("icaps") == 0)
             serv = getservbyname("icaps", "tcp");
         else
             serv = getservbyname("icap", "tcp");
 
         if (serv) {
             writeableCfg().port = htons(serv->s_port);
         } else {
             writeableCfg().port = cfg().protocol.caseCmp("icaps") == 0 ? DEFAULT_ICAPS_PORT : DEFAULT_ICAP_PORT;
         }
     }
 
     if (cfg().protocol.caseCmp("icaps") == 0)
         writeableCfg().secure.encryptTransport = true;
 
     if (cfg().secure.encryptTransport) {
         debugs(3, DBG_IMPORTANT, "Initializing service " << cfg().resource << " SSL context");
-        sslContext = writeableCfg().secure.createContext(true);
+        sslContext = writeableCfg().secure.createClientContext(true);
     }
 
     theSessionFailures.configure(TheConfig.oldest_service_failure > 0 ?
                                  TheConfig.oldest_service_failure : -1);
 }
 
 void Adaptation::Icap::ServiceRep::noteFailure()
 {
     const int failures = theSessionFailures.count(1);
     debugs(93,4, HERE << " failure " << failures << " out of " <<
            TheConfig.service_failure_limit << " allowed in " <<
            TheConfig.oldest_service_failure << "sec " << status());
 
     if (isSuspended)
         return;
 
     if (TheConfig.service_failure_limit >= 0 &&
             failures > TheConfig.service_failure_limit)
         suspend("too many failures");
 

=== modified file 'src/anyp/PortCfg.cc'
--- src/anyp/PortCfg.cc	2015-06-29 12:46:17 +0000
+++ src/anyp/PortCfg.cc	2015-06-29 13:01:14 +0000
@@ -1,260 +1,191 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 #include "anyp/PortCfg.h"
 #include "comm.h"
 #include "fatal.h"
-#include "SBuf.h"
+#include "security/PeerOptions.h"
 #if USE_OPENSSL
 #include "ssl/support.h"
 #endif
 
 #include <cstring>
 #include <limits>
 
 AnyP::PortCfgPointer HttpPortList;
 #if USE_OPENSSL
 AnyP::PortCfgPointer HttpsPortList;
 #endif
 AnyP::PortCfgPointer FtpPortList;
 
 int NHttpSockets = 0;
 int HttpSockets[MAXTCPLISTENPORTS];
 
 AnyP::PortCfg::PortCfg() :
     next(),
     s(),
     transport(AnyP::PROTO_HTTP,1,1), // "Squid is an HTTP proxy", etc.
     name(NULL),
     defaultsite(NULL),
     flags(),
     allow_direct(false),
     vhost(false),
     actAsOrigin(false),
     ignore_cc(false),
     connection_auth_disabled(false),
     ftp_track_dirs(false),
     vport(0),
     disable_pmtu_discovery(0),
     listenConn()
 #if USE_OPENSSL
-    ,cert(NULL),
-    key(NULL),
-    version(0),
-    cipher(NULL),
-    options(NULL),
+    ,
     clientca(NULL),
-    cafile(NULL),
-    capath(NULL),
-    crlfile(NULL),
     dhfile(NULL),
     tls_dh(NULL),
-    sslflags(NULL),
     sslContextSessionId(NULL),
     generateHostCertificates(false),
     dynamicCertMemCacheSize(std::numeric_limits<size_t>::max()),
     staticSslContext(),
     signingCert(),
     signPkey(),
     certsToChain(),
     untrustedSigningCert(),
     untrustedSignPkey(),
     clientVerifyCrls(),
     clientCA(),
     dhParams(),
-    eecdhCurve(NULL),
-    sslContextFlags(0),
-    sslOptions(0)
+    eecdhCurve(NULL)
 #endif
 {
     memset(&tcp_keepalive, 0, sizeof(tcp_keepalive));
 }
 
 AnyP::PortCfg::~PortCfg()
 {
     if (Comm::IsConnOpen(listenConn)) {
         listenConn->close();
         listenConn = NULL;
     }
 
     safe_free(name);
     safe_free(defaultsite);
 
 #if USE_OPENSSL
-    safe_free(cert);
-    safe_free(key);
-    safe_free(cipher);
-    safe_free(options);
     safe_free(clientca);
-    safe_free(cafile);
-    safe_free(capath);
-    safe_free(crlfile);
     safe_free(dhfile);
     safe_free(tls_dh);
-    safe_free(sslflags);
     safe_free(sslContextSessionId);
     safe_free(eecdhCurve);
 #endif
 }
 
 AnyP::PortCfgPointer
 AnyP::PortCfg::clone() const
 {
     AnyP::PortCfgPointer b = new AnyP::PortCfg();
     b->s = s;
     if (name)
         b->name = xstrdup(name);
     if (defaultsite)
         b->defaultsite = xstrdup(defaultsite);
 
     b->transport = transport;
     b->flags = flags;
     b->allow_direct = allow_direct;
     b->vhost = vhost;
     b->vport = vport;
     b->connection_auth_disabled = connection_auth_disabled;
     b->ftp_track_dirs = ftp_track_dirs;
     b->disable_pmtu_discovery = disable_pmtu_discovery;
     b->tcp_keepalive = tcp_keepalive;
+    b->secure = secure;
 
 #if USE_OPENSSL
-    if (cert)
-        b->cert = xstrdup(cert);
-    if (key)
-        b->key = xstrdup(key);
-    b->version = version;
-    if (cipher)
-        b->cipher = xstrdup(cipher);
-    if (options)
-        b->options = xstrdup(options);
     if (clientca)
         b->clientca = xstrdup(clientca);
-    if (cafile)
-        b->cafile = xstrdup(cafile);
-    if (capath)
-        b->capath = xstrdup(capath);
-    if (crlfile)
-        b->crlfile = xstrdup(crlfile);
     if (dhfile)
         b->dhfile = xstrdup(dhfile);
     if (tls_dh)
         b->tls_dh = xstrdup(tls_dh);
-    if (sslflags)
-        b->sslflags = xstrdup(sslflags);
     if (sslContextSessionId)
         b->sslContextSessionId = xstrdup(sslContextSessionId);
 
 #if 0
     // TODO: AYJ: 2015-01-15: for now SSL does not clone the context object.
     // cloning should only be done before the PortCfg is post-configure initialized and opened
     SSL_CTX *sslContext;
 #endif
 
 #endif /*0*/
 
     return b;
 }
 
 #if USE_OPENSSL
 void
 AnyP::PortCfg::configureSslServerContext()
 {
-    if (cert)
-        Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, cert, key);
+    if (!secure.certFile.isEmpty())
+        Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, secure.certFile.c_str(), secure.privateKeyFile.c_str());
 
     if (!signingCert) {
         char buf[128];
         fatalf("No valid signing SSL certificate configured for %s_port %s", AnyP::ProtocolType_str[transport.protocol],  s.toUrl(buf, sizeof(buf)));
     }
 
     if (!signPkey)
         debugs(3, DBG_IMPORTANT, "No SSL private key configured for  " << AnyP::ProtocolType_str[transport.protocol] << "_port " << s);
 
     Ssl::generateUntrustedCert(untrustedSigningCert, untrustedSignPkey,
                                signingCert, signPkey);
 
     if (!untrustedSigningCert) {
         char buf[128];
         fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
     }
 
-    if (crlfile)
-        clientVerifyCrls.reset(Ssl::loadCrl(crlfile, sslContextFlags));
+    if (!secure.crlFile.isEmpty())
+        clientVerifyCrls.reset(Ssl::loadCrl(secure.crlFile.c_str(), secure.parsedFlags));
 
     if (clientca) {
         clientCA.reset(SSL_load_client_CA_file(clientca));
         if (clientCA.get() == NULL) {
             fatalf("Unable to read client CAs! from %s", clientca);
         }
     }
 
-    // backward compatibility hack for sslversion= configuration
-    if (version > 2) {
-        const char *add = NULL;
-        switch (version) {
-        case 3:
-            add = "NO_TLSv1,NO_TLSv1_1,NO_TLSv1_2";
-            break;
-        case 4:
-            add = "NO_SSLv3,NO_TLSv1_1,NO_TLSv1_2";
-            break;
-        case 5:
-            add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_2";
-            break;
-        case 6:
-            add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_1";
-            break;
-        default: // nothing
-            break;
-        }
-        if (add) {
-            SBuf tmpOpts;
-            if (options) {
-                tmpOpts.append(options, strlen(options));
-                tmpOpts.append(",",1);
-            }
-            tmpOpts.append(add, strlen(add));
-            xfree(options);
-            options = xstrdup(tmpOpts.c_str());
-        }
-        version = 0; // prevent options being repeatedly appended
-    }
+    secure.updateTlsVersionLimits();
 
     const char *dhParamsFile = dhfile; // backward compatibility for dhparams= configuration
     safe_free(eecdhCurve); // clear any previous EECDH configuration
     if (tls_dh && *tls_dh) {
         eecdhCurve = xstrdup(tls_dh);
         char *p = strchr(eecdhCurve, ':');
         if (p) {  // tls-dh=eecdhCurve:dhParamsFile
             *p = '\0';
             dhParamsFile = p+1;
         } else {  // tls-dh=dhParamsFile
             dhParamsFile = tls_dh;
             // a NULL eecdhCurve means "do not use EECDH"
             safe_free(eecdhCurve);
         }
     }
 
     if (dhParamsFile && *dhParamsFile)
         dhParams.reset(Ssl::readDHParams(dhParamsFile));
 
-    if (sslflags)
-        sslContextFlags = Ssl::parse_flags(sslflags);
-
-    sslOptions = Ssl::parse_options(options);
-
     staticSslContext.reset(sslCreateServerContext(*this));
 
     if (!staticSslContext) {
         char buf[128];
         fatalf("%s_port %s initialization error", AnyP::ProtocolType_str[transport.protocol],  s.toUrl(buf, sizeof(buf)));
     }
 }
 #endif
 

=== modified file 'src/anyp/PortCfg.h'
--- src/anyp/PortCfg.h	2015-06-29 12:46:17 +0000
+++ src/anyp/PortCfg.h	2015-06-29 12:59:14 +0000
@@ -1,35 +1,37 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_ANYP_PORTCFG_H
 #define SQUID_ANYP_PORTCFG_H
 
 #include "anyp/forward.h"
 #include "anyp/ProtocolVersion.h"
 #include "anyp/TrafficMode.h"
 #include "comm/Connection.h"
+#include "SBuf.h"
+#include "security/PeerOptions.h"
 
 #if USE_OPENSSL
 #include "ssl/gadgets.h"
 #endif
 
 namespace AnyP
 {
 
 class PortCfg : public RefCountable
 {
 public:
     PortCfg();
     ~PortCfg();
     AnyP::PortCfgPointer clone() const;
 #if USE_OPENSSL
     /// creates, configures, and validates SSL context and related port options
     void configureSslServerContext();
 #endif
 
     PortCfgPointer next;
@@ -50,70 +52,62 @@
 
     bool ftp_track_dirs; ///< whether transactions should track FTP directories
 
     int vport;               ///< virtual port support. -1 if dynamic, >0 static
     int disable_pmtu_discovery;
 
     struct {
         unsigned int idle;
         unsigned int interval;
         unsigned int timeout;
         bool enabled;
     } tcp_keepalive;
 
     /**
      * The listening socket details.
      * If Comm::ConnIsOpen() we are actively listening for client requests.
      * use listenConn->close() to stop.
      */
     Comm::ConnectionPointer listenConn;
 
+    /// TLS configuration options for this listening port
+    Security::PeerOptions secure;
+
 #if USE_OPENSSL
-    char *cert;
-    char *key;
-    int version;
-    char *cipher;
-    char *options;
     char *clientca;
-    char *cafile;
-    char *capath;
-    char *crlfile;
     char *dhfile;
     char *tls_dh;
-    char *sslflags;
     char *sslContextSessionId; ///< "session id context" for staticSslContext
     bool generateHostCertificates; ///< dynamically make host cert for sslBump
     size_t dynamicCertMemCacheSize; ///< max size of generated certificates memory cache
 
     Ssl::SSL_CTX_Pointer staticSslContext; ///< for HTTPS accelerator or static sslBump
     Ssl::X509_Pointer signingCert; ///< x509 certificate for signing generated certificates
     Ssl::EVP_PKEY_Pointer signPkey; ///< private key for sighing generated certificates
     Ssl::X509_STACK_Pointer certsToChain; ///<  x509 certificates to send with the generated cert
     Ssl::X509_Pointer untrustedSigningCert; ///< x509 certificate for signing untrusted generated certificates
     Ssl::EVP_PKEY_Pointer untrustedSignPkey; ///< private key for signing untrusted generated certificates
 
     Ssl::X509_CRL_STACK_Pointer clientVerifyCrls; ///< additional CRL lists to use when verifying the client certificate
     Ssl::X509_NAME_STACK_Pointer clientCA; ///< CA certificates to use when verifying client certificates
     Ssl::DH_Pointer dhParams; ///< DH parameters for temporary/ephemeral DH key exchanges
     char *eecdhCurve; ///< Elliptic curve for ephemeral EC-based DH key exchanges
-    long sslContextFlags; ///< flags modifying the use of SSL
-    long sslOptions; ///< SSL engine options
 #endif
 };
 
 } // namespace AnyP
 
 /// list of Squid http_port configured
 extern AnyP::PortCfgPointer HttpPortList;
 
 #if USE_OPENSSL
 /// list of Squid https_port configured
 extern AnyP::PortCfgPointer HttpsPortList;
 #endif
 
 /// list of Squid ftp_port configured
 extern AnyP::PortCfgPointer FtpPortList;
 
 #if !defined(MAXTCPLISTENPORTS)
 // Max number of TCP listening ports
 #define MAXTCPLISTENPORTS 128
 #endif

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2015-06-19 12:12:10 +0000
+++ src/cache_cf.cc	2015-06-30 15:13:41 +0000
@@ -848,58 +848,66 @@
 #endif
         }
     } else {
         Config2.effectiveUserID = geteuid();
         Config2.effectiveGroupID = getegid();
     }
 
     if (NULL != Config.effectiveGroup) {
 
         struct group *grp = getgrnam(Config.effectiveGroup);
 
         if (NULL == grp) {
             fatalf("getgrnam failed to find groupid for effective group '%s'",
                    Config.effectiveGroup);
             return;
         }
 
         Config2.effectiveGroupID = grp->gr_gid;
     }
 
-#if USE_OPENSSL
-
-    debugs(3, DBG_IMPORTANT, "Initializing https proxy context");
-
-    Config.ssl_client.sslContext = Security::ProxyOutgoingConfig.createContext(false);
+    if (Security::ProxyOutgoingConfig.encryptTransport) {
+        debugs(3, DBG_IMPORTANT, "Initializing https:// proxy context");
+        Config.ssl_client.sslContext = Security::ProxyOutgoingConfig.createClientContext(false);
+        if (!Config.ssl_client.sslContext) {
+            debugs(3, DBG_CRITICAL, "ERROR: Could not initialize https:// proxy context");
+            self_destruct();
+        }
+    }
 
     for (CachePeer *p = Config.peers; p != NULL; p = p->next) {
 
         // default value for ssldomain= is the peer host/IP
         if (p->secure.sslDomain.isEmpty())
             p->secure.sslDomain = p->host;
 
         if (p->secure.encryptTransport) {
-            debugs(3, DBG_IMPORTANT, "Initializing cache_peer " << p->name << " SSL context");
-            p->sslContext = p->secure.createContext(true);
+            debugs(3, DBG_IMPORTANT, "Initializing cache_peer " << p->name << " TLS context");
+            p->sslContext = p->secure.createClientContext(true);
+            if (!p->sslContext) {
+                debugs(3, DBG_CRITICAL, "ERROR: Could not initialize cache_peer " << p->name << " TLS context");
+                self_destruct();
+            }
         }
     }
 
+#if USE_OPENSSL
     for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
         if (!s->flags.tunnelSslBumping)
             continue;
 
         debugs(3, DBG_IMPORTANT, "Initializing http_port " << s->s << " SSL context");
         s->configureSslServerContext();
     }
 
     for (AnyP::PortCfgPointer s = HttpsPortList; s != NULL; s = s->next) {
         debugs(3, DBG_IMPORTANT, "Initializing https_port " << s->s << " SSL context");
         s->configureSslServerContext();
     }
 
 #endif
 
     // prevent infinite fetch loops in the request parser
     // due to buffer full but not enough data recived to finish parse
     if (Config.maxRequestBufferSize <= Config.maxRequestHeaderSize) {
         fatalf("Client request buffer of %u bytes cannot hold a request with %u bytes of headers." \
                " Change client_request_buffer_max or request_header_max_size limits.",
@@ -2172,46 +2180,42 @@
         } else if (!strcmp(token, "originserver")) {
             p->options.originserver = true;
         } else if (!strncmp(token, "name=", 5)) {
             safe_free(p->name);
 
             if (token[5])
                 p->name = xstrdup(token + 5);
         } else if (!strncmp(token, "forceddomain=", 13)) {
             safe_free(p->domain);
             if (token[13])
                 p->domain = xstrdup(token + 13);
 
         } else if (strncmp(token, "ssl", 3) == 0) {
 #if !USE_OPENSSL
             debugs(0, DBG_CRITICAL, "WARNING: cache_peer option '" << token << "' requires --with-openssl");
 #else
             p->secure.encryptTransport = true;
             p->secure.parse(token+3);
 #endif
         } else if (strncmp(token, "tls-", 4) == 0) {
-#if !USE_OPENSSL
-            debugs(0, DBG_CRITICAL, "WARNING: cache_peer option '" << token << "' requires --with-openssl");
-#else
             p->secure.encryptTransport = true;
             p->secure.parse(token+4);
-#endif
         } else if (strcmp(token, "front-end-https") == 0) {
             p->front_end_https = 1;
         } else if (strcmp(token, "front-end-https=on") == 0) {
             p->front_end_https = 1;
         } else if (strcmp(token, "front-end-https=auto") == 0) {
             p->front_end_https = 2;
         } else if (strcmp(token, "connection-auth=off") == 0) {
             p->connection_auth = 0;
         } else if (strcmp(token, "connection-auth") == 0) {
             p->connection_auth = 1;
         } else if (strcmp(token, "connection-auth=on") == 0) {
             p->connection_auth = 1;
         } else if (strcmp(token, "connection-auth=auto") == 0) {
             p->connection_auth = 2;
         } else if (token[0] == '#') {
             // start of a text comment. stop reading this line.
             break;
         } else {
             debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Ignoring unknown cache_peer option '" << token << "'");
         }
@@ -3545,98 +3549,90 @@
             self_destruct();
         }
     } else if (strcmp(token, "tcpkeepalive") == 0) {
         s->tcp_keepalive.enabled = true;
     } else if (strncmp(token, "tcpkeepalive=", 13) == 0) {
         char *t = token + 13;
         s->tcp_keepalive.enabled = true;
         s->tcp_keepalive.idle = xatoui(t,',');
         t = strchr(t, ',');
         if (t) {
             ++t;
             s->tcp_keepalive.interval = xatoui(t,',');
             t = strchr(t, ',');
         }
         if (t) {
             ++t;
             s->tcp_keepalive.timeout = xatoui(t);
         }
 #if USE_OPENSSL
     } else if (strcmp(token, "sslBump") == 0) {
-        debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
+        debugs(3, DBG_PARSE_NOTE(1), "WARNING: '" << token << "' is deprecated " <<
                "in " << cfg_directive << ". Use 'ssl-bump' instead.");
         s->flags.tunnelSslBumping = true;
     } else if (strcmp(token, "ssl-bump") == 0) {
         s->flags.tunnelSslBumping = true;
     } else if (strncmp(token, "cert=", 5) == 0) {
-        safe_free(s->cert);
-        s->cert = xstrdup(token + 5);
+        s->secure.parse(token);
     } else if (strncmp(token, "key=", 4) == 0) {
-        safe_free(s->key);
-        s->key = xstrdup(token + 4);
+        s->secure.parse(token);
     } else if (strncmp(token, "version=", 8) == 0) {
         debugs(3, DBG_PARSE_NOTE(1), "UPGRADE WARNING: '" << token << "' is deprecated " <<
                "in " << cfg_directive << ". Use 'options=' instead.");
-        s->version = xatoi(token + 8);
-        if (s->version < 1 || s->version > 6)
-            self_destruct();
+        s->secure.parse(token);
     } else if (strncmp(token, "options=", 8) == 0) {
-        safe_free(s->options);
-        s->options = xstrdup(token + 8);
+        s->secure.parse(token);
     } else if (strncmp(token, "cipher=", 7) == 0) {
-        safe_free(s->cipher);
-        s->cipher = xstrdup(token + 7);
+        s->secure.parse(token);
     } else if (strncmp(token, "clientca=", 9) == 0) {
         safe_free(s->clientca);
         s->clientca = xstrdup(token + 9);
     } else if (strncmp(token, "cafile=", 7) == 0) {
-        safe_free(s->cafile);
-        s->cafile = xstrdup(token + 7);
+        s->secure.parse(token);
     } else if (strncmp(token, "capath=", 7) == 0) {
-        safe_free(s->capath);
-        s->capath = xstrdup(token + 7);
+        s->secure.parse(token);
     } else if (strncmp(token, "crlfile=", 8) == 0) {
-        safe_free(s->crlfile);
-        s->crlfile = xstrdup(token + 8);
+        s->secure.parse(token);
     } else if (strncmp(token, "dhparams=", 9) == 0) {
         debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: '" << token << "' is deprecated " <<
                "in " << cfg_directive << ". Use 'tls-dh=' instead.");
         safe_free(s->dhfile);
         s->dhfile = xstrdup(token + 9);
     } else if (strncmp(token, "tls-dh=", 7) == 0) {
         safe_free(s->tls_dh);
         s->tls_dh = xstrdup(token + 7);
     } else if (strncmp(token, "sslflags=", 9) == 0) {
-        safe_free(s->sslflags);
-        s->sslflags = xstrdup(token + 9);
+        s->secure.parse(token+3);
     } else if (strncmp(token, "sslcontext=", 11) == 0) {
         safe_free(s->sslContextSessionId);
         s->sslContextSessionId = xstrdup(token + 11);
     } else if (strcmp(token, "generate-host-certificates") == 0) {
         s->generateHostCertificates = true;
     } else if (strcmp(token, "generate-host-certificates=on") == 0) {
         s->generateHostCertificates = true;
     } else if (strcmp(token, "generate-host-certificates=off") == 0) {
         s->generateHostCertificates = false;
     } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
         parseBytesOptionValue(&s->dynamicCertMemCacheSize, B_BYTES_STR, token + 28);
 #endif
+    } else if (strncmp(token, "tls-", 4) == 0) {
+        s->secure.parse(token+4);
     } else if (strcmp(token, "ftp-track-dirs") == 0) {
         s->ftp_track_dirs = true;
     } else {
         debugs(3, DBG_CRITICAL, "FATAL: Unknown " << cfg_directive << " option '" << token << "'.");
         self_destruct();
     }
 }
 
 void
 add_http_port(char *portspec)
 {
     AnyP::PortCfgPointer s = new AnyP::PortCfg();
     s->transport = parsePortProtocol(SBuf("HTTP"));
     parsePortSpecification(s, portspec);
     // we may need to merge better if the above returns a list with clones
     assert(s->next == NULL);
     s->next = HttpPortList;
     HttpPortList = s;
 }
 
@@ -3783,71 +3779,51 @@
         else
             pmtu = "transparent";
 
         storeAppendPrintf(e, " disable-pmtu-discovery=%s", pmtu);
     }
 
     if (s->s.isAnyAddr() && !s->s.isIPv6())
         storeAppendPrintf(e, " ipv4");
 
     if (s->tcp_keepalive.enabled) {
         if (s->tcp_keepalive.idle || s->tcp_keepalive.interval || s->tcp_keepalive.timeout) {
             storeAppendPrintf(e, " tcpkeepalive=%d,%d,%d", s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
         } else {
             storeAppendPrintf(e, " tcpkeepalive");
         }
     }
 
 #if USE_OPENSSL
     if (s->flags.tunnelSslBumping)
         storeAppendPrintf(e, " ssl-bump");
+#endif
 
-    if (s->cert)
-        storeAppendPrintf(e, " cert=%s", s->cert);
-
-    if (s->key)
-        storeAppendPrintf(e, " key=%s", s->key);
-
-    if (s->options)
-        storeAppendPrintf(e, " options=%s", s->options);
-
-    if (s->cipher)
-        storeAppendPrintf(e, " cipher=%s", s->cipher);
-
-    if (s->cafile)
-        storeAppendPrintf(e, " cafile=%s", s->cafile);
-
-    if (s->capath)
-        storeAppendPrintf(e, " capath=%s", s->capath);
-
-    if (s->crlfile)
-        storeAppendPrintf(e, " crlfile=%s", s->crlfile);
+    s->secure.dumpCfg(e, "tls-");
 
+#if USE_OPENSSL
     if (s->dhfile)
         storeAppendPrintf(e, " dhparams=%s", s->dhfile);
 
     if (s->tls_dh)
         storeAppendPrintf(e, " tls-dh=%s", s->tls_dh);
 
-    if (s->sslflags)
-        storeAppendPrintf(e, " sslflags=%s", s->sslflags);
-
     if (s->sslContextSessionId)
         storeAppendPrintf(e, " sslcontext=%s", s->sslContextSessionId);
 
     if (s->generateHostCertificates)
         storeAppendPrintf(e, " generate-host-certificates");
 
     if (s->dynamicCertMemCacheSize != std::numeric_limits<size_t>::max())
         storeAppendPrintf(e, "dynamic_cert_mem_cache_size=%lu%s\n", (unsigned long)s->dynamicCertMemCacheSize, B_BYTES_STR);
 #endif
 }
 
 static void
 dump_PortCfg(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s)
 {
     for (AnyP::PortCfgPointer p = s; p != NULL; p = p->next) {
         dump_generic_port(e, n, p);
         storeAppendPrintf(e, "\n");
     }
 }
 

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2015-06-19 07:13:57 +0000
+++ src/cf.data.pre	2015-06-29 04:55:53 +0000
@@ -2574,41 +2574,41 @@
 	
 	This option (on by default) prevents alternative DNS entries being
 	located to send intercepted traffic DIRECT to an origin server.
 	The clients original destination IP and port will be used instead.
 	
 	Regardless of this option setting, when dealing with intercepted
 	traffic Squid will verify the Host: header and any traffic which
 	fails Host verification will be treated as if this option were ON.
 	
 	see host_verify_strict for details on the verification process.
 DOC_END
 
 COMMENT_START
  TLS OPTIONS
  -----------------------------------------------------------------------------
 COMMENT_END
 
 NAME: tls_outgoing_options
 IFDEF: USE_GNUTLS||USE_OPENSSL
 TYPE: securePeerOptions
-DEFAULT: disable
+DEFAULT: min-version=1.0 options=NO_SSLv3
 LOC: Security::ProxyOutgoingConfig
 DOC_START
 	disable		Do not support https:// URLs.
 	
 	cert=/path/to/client/certificate
 			A client TLS certificate to use when connecting.
 	
 	key=/path/to/client/private_key
 			The private TLS key corresponding to the cert= above.
 			If key= is not specified cert= is assumed to reference
 			a PEM file containing both the certificate and the key.
 	
 	cipher=...	The list of valid TLS ciphers to use.
 
 	min-version=1.N
 			The minimum TLS protocol version to permit. To control
 			SSLv3 use the options= parameter.
 			Supported Values: 1.0 (default), 1.1, 1.2
 
 	options=... 	Specify various TLS/SSL implementation options:

=== modified file 'src/neighbors.cc'
--- src/neighbors.cc	2015-06-09 06:14:43 +0000
+++ src/neighbors.cc	2015-06-30 06:29:58 +0000
@@ -1539,40 +1539,41 @@
         storeAppendPrintf(sentry, " no-tproxy");
 
     if (p->max_conn > 0)
         storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
     if (p->standby.limit > 0)
         storeAppendPrintf(sentry, " standby=%d", p->standby.limit);
 
     if (p->options.originserver)
         storeAppendPrintf(sentry, " originserver");
 
     if (p->domain)
         storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
 
     if (p->connection_auth == 0)
         storeAppendPrintf(sentry, " connection-auth=off");
     else if (p->connection_auth == 1)
         storeAppendPrintf(sentry, " connection-auth=on");
     else if (p->connection_auth == 2)
         storeAppendPrintf(sentry, " connection-auth=auto");
 
+    p->secure.dumpCfg(sentry,"tls-");
     storeAppendPrintf(sentry, "\n");
 }
 
 static void
 dump_peers(StoreEntry * sentry, CachePeer * peers)
 {
     char ntoabuf[MAX_IPSTRLEN];
     icp_opcode op;
     int i;
 
     if (peers == NULL)
         storeAppendPrintf(sentry, "There are no neighbors installed.\n");
 
     for (CachePeer *e = peers; e; e = e->next) {
         assert(e->host != NULL);
         storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
                           neighborTypeStr(e),
                           e->name);
         storeAppendPrintf(sentry, "Host       : %s/%d/%d\n",
                           e->host,

=== modified file 'src/security/Context.h'
--- src/security/Context.h	2015-02-26 12:12:11 +0000
+++ src/security/Context.h	2015-03-21 10:41:16 +0000
@@ -1,30 +1,40 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SRC_SECURITY_CONTEXT_H
 #define SQUID_SRC_SECURITY_CONTEXT_H
 
 #if USE_OPENSSL
-#include "ssl/gadgets.h"
+#if HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#endif
+#endif
+
+#if USE_GNUTLS
+#if HAVE_GNUTLS_GNUTLS_H
+#include <gnutls/gnutls.h>
+#endif
 #endif
 
 namespace Security {
 
 #if USE_OPENSSL
-// XXX: make this a SSL_CTX_Pointer
 typedef SSL_CTX* ContextPointer;
 
+#elif USE_GNUTLS
+typedef gnutls_certificate_credentials_t* ContextPointer;
+
 #else
 // use void* so we can check against NULL
 typedef void* ContextPointer;
 #endif
 
 } // namespace Security
 
 #endif /* SQUID_SRC_SECURITY_CONTEXT_H */
 

=== modified file 'src/security/PeerOptions.cc'
--- src/security/PeerOptions.cc	2015-05-22 09:42:55 +0000
+++ src/security/PeerOptions.cc	2015-06-30 12:09:14 +0000
@@ -1,130 +1,445 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
+#include "base/Packable.h"
 #include "Debug.h"
+#include "fatal.h"
 #include "globals.h"
 #include "parser/Tokenizer.h"
 #include "Parsing.h"
+#include "parser/Tokenizer.h"
 #include "security/PeerOptions.h"
 
 #if USE_OPENSSL
 #include "ssl/support.h"
 #endif
 
 Security::PeerOptions Security::ProxyOutgoingConfig;
 
+Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) :
+    certFile(p.certFile),
+    privateKeyFile(p.privateKeyFile),
+    sslOptions(p.sslOptions),
+    caFile(p.caFile),
+    caDir(p.caDir),
+    crlFile(p.crlFile),
+    sslCipher(p.sslCipher),
+    sslFlags(p.sslFlags),
+    sslDomain(p.sslDomain),
+    parsedOptions(p.parsedOptions),
+    parsedFlags(p.parsedFlags),
+    sslVersion(p.sslVersion),
+    encryptTransport(p.encryptTransport)
+{
+}
+
 void
 Security::PeerOptions::parse(const char *token)
 {
-    if (strncmp(token, "cert=", 5) == 0) {
+    if (strncmp(token, "disable", 7) == 0) {
+        clear();
+    } else if (strncmp(token, "cert=", 5) == 0) {
         certFile = SBuf(token + 5);
         if (privateKeyFile.isEmpty())
             privateKeyFile = certFile;
     } else if (strncmp(token, "key=", 4) == 0) {
         privateKeyFile = SBuf(token + 4);
         if (certFile.isEmpty()) {
-            debugs(0, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
+            debugs(3, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
             certFile = privateKeyFile;
         }
     } else if (strncmp(token, "version=", 8) == 0) {
         debugs(0, DBG_PARSE_NOTE(1), "UPGRADE WARNING: SSL version= is deprecated. Use options= to limit protocols instead.");
         sslVersion = xatoi(token + 8);
     } else if (strncmp(token, "min-version=", 12) == 0) {
         tlsMinVersion = SBuf(token + 12);
     } else if (strncmp(token, "options=", 8) == 0) {
         sslOptions = SBuf(token + 8);
-#if USE_OPENSSL
-        // Pre-parse SSL client options to be applied when the client SSL objects created.
-        // Options must not used in the case of peek or stare bump mode.
-        // XXX: performance regression. c_str() can reallocate
-        parsedOptions = Ssl::parse_options(sslOptions.c_str());
-#endif
+        parsedOptions = parseOptions();
     } else if (strncmp(token, "cipher=", 7) == 0) {
         sslCipher = SBuf(token + 7);
     } else if (strncmp(token, "cafile=", 7) == 0) {
         caFile = SBuf(token + 7);
     } else if (strncmp(token, "capath=", 7) == 0) {
         caDir = SBuf(token + 7);
     } else if (strncmp(token, "crlfile=", 8) == 0) {
         crlFile = SBuf(token + 8);
     } else if (strncmp(token, "flags=", 6) == 0) {
+        if (parsedFlags != 0) {
+            debugs(3, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
+        }
         sslFlags = SBuf(token + 6);
+        parsedFlags = parseFlags();
     } else if (strncmp(token, "domain=", 7) == 0) {
         sslDomain = SBuf(token + 7);
+    } else {
+        debugs(3, DBG_CRITICAL, "ERROR: Unknown TLS option '" << token << "'");
     }
 }
 
-// XXX: make a GnuTLS variant
-Security::ContextPointer
-Security::PeerOptions::createContext(bool setOptions)
+void
+Security::PeerOptions::dumpCfg(Packable *p, const char *pfx) const
 {
-    Security::ContextPointer t = NULL;
+    if (!encryptTransport) {
+        p->appendf(" %sdisable", pfx);
+        return; // no other settings are relevant
+    }
 
+    if (!certFile.isEmpty())
+        p->appendf(" %scert=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(certFile));
+
+    if (!privateKeyFile.isEmpty() && privateKeyFile != certFile)
+        p->appendf(" %skey=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(privateKeyFile));
+
+    if (!sslOptions.isEmpty())
+        p->appendf(" %soptions=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslOptions));
+
+    if (!sslCipher.isEmpty())
+        p->appendf(" %scipher=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslCipher));
+
+    if (!caFile.isEmpty())
+        p->appendf(" %scafile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caFile));
+
+    if (!caDir.isEmpty())
+        p->appendf(" %scapath=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caDir));
+
+    if (!crlFile.isEmpty())
+        p->appendf(" %scrlfile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(crlFile));
+
+    if (!sslFlags.isEmpty())
+        p->appendf(" %sflags=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslFlags));
+}
+
+void
+Security::PeerOptions::updateTlsVersionLimits()
+{
     if (!tlsMinVersion.isEmpty()) {
         ::Parser::Tokenizer tok(tlsMinVersion);
         int64_t v = 0;
         if (tok.skip('1') && tok.skip('.') && tok.int64(v, 10, false, 1) && v <= 2) {
             // only account for TLS here - SSL versions are handled by options= parameter
+            // avoid affectign options= parameter in cachemgr config report
+#if SSL_OP_NO_TLSv1
             if (v > 0)
-                sslOptions.append(",NO_TLSv1",9);
+                parsedOptions |= SSL_OP_NO_TLSv1;
+#endif
+#if SSL_OP_NO_TLSv1_1
             if (v > 1)
-                sslOptions.append(",NO_TLSv1_1",11);
+                parsedOptions |= SSL_OP_NO_TLSv1_1;
+#endif
+#if SSL_OP_NO_TLSv1_2
             if (v > 2)
-                sslOptions.append(",NO_TLSv1_2",11);
+                parsedOptions |= SSL_OP_NO_TLSv1_2;
+#endif
 
         } else {
             debugs(0, DBG_PARSE_NOTE(1), "WARNING: Unknown TLS minimum version: " << tlsMinVersion);
         }
 
     } else if (sslVersion > 2) {
         // backward compatibility hack for sslversion= configuration
         // only use if tls-min-version=N.N is not present
-
+        // values 0-2 for auto and SSLv2 are not supported any longer.
+        // Do it this way so we DO cause changes to options= in cachemgr config report
         const char *add = NULL;
         switch (sslVersion) {
         case 3:
             add = "NO_TLSv1,NO_TLSv1_1,NO_TLSv1_2";
             break;
         case 4:
             add = "NO_SSLv3,NO_TLSv1_1,NO_TLSv1_2";
             break;
         case 5:
             add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_2";
             break;
         case 6:
             add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_1";
             break;
         default: // nothing
             break;
         }
         if (add) {
             if (!sslOptions.isEmpty())
                 sslOptions.append(",",1);
             sslOptions.append(add, strlen(add));
         }
         sslVersion = 0; // prevent sslOptions being repeatedly appended
     }
+}
+
+// XXX: make a GnuTLS variant
+Security::ContextPointer
+Security::PeerOptions::createClientContext(bool setOptions)
+{
+    Security::ContextPointer t = NULL;
 
+    updateTlsVersionLimits();
 #if USE_OPENSSL
     // XXX: temporary performance regression. c_str() data copies and prevents this being a const method
     t = sslCreateClientContext(certFile.c_str(), privateKeyFile.c_str(), sslCipher.c_str(),
-                               (setOptions ? sslOptions.c_str() : NULL), sslFlags.c_str(),
+                               (setOptions ? parsedOptions : 0), parsedFlags,
                                caFile.c_str(), caDir.c_str(), crlFile.c_str());
 #endif
 
     return t;
 }
 
+/// set of options we can parse and what they map to
+static struct ssl_option {
+    const char *name;
+    long value;
+
+} ssl_options[] = {
+
+#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+    {
+        "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+    },
+#endif
+#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
+    {
+        "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
+    },
+#endif
+#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
+    {
+        "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
+    },
+#endif
+#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
+    {
+        "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
+    },
+#endif
+#if SSL_OP_TLS_D5_BUG
+    {
+        "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
+    },
+#endif
+#if SSL_OP_TLS_BLOCK_PADDING_BUG
+    {
+        "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
+    },
+#endif
+#if SSL_OP_TLS_ROLLBACK_BUG
+    {
+        "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
+    },
+#endif
+#if SSL_OP_ALL
+    {
+        "ALL", (long)SSL_OP_ALL
+    },
+#endif
+#if SSL_OP_SINGLE_DH_USE
+    {
+        "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
+    },
+#endif
+#if SSL_OP_EPHEMERAL_RSA
+    {
+        "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
+    },
+#endif
+#if SSL_OP_PKCS1_CHECK_1
+    {
+        "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
+    },
+#endif
+#if SSL_OP_PKCS1_CHECK_2
+    {
+        "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
+    },
+#endif
+#if SSL_OP_NETSCAPE_CA_DN_BUG
+    {
+        "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
+    },
+#endif
+#if SSL_OP_NON_EXPORT_FIRST
+    {
+        "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
+    },
+#endif
+#if SSL_OP_CIPHER_SERVER_PREFERENCE
+    {
+        "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
+    },
+#endif
+#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
+    {
+        "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
+    },
+#endif
+#if SSL_OP_NO_SSLv3
+    {
+        "NO_SSLv3", SSL_OP_NO_SSLv3
+    },
+#endif
+#if SSL_OP_NO_TLSv1
+    {
+        "NO_TLSv1", SSL_OP_NO_TLSv1
+    },
+#endif
+#if SSL_OP_NO_TLSv1_1
+    {
+        "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
+    },
+#endif
+#if SSL_OP_NO_TLSv1_2
+    {
+        "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
+    },
+#endif
+#if SSL_OP_NO_COMPRESSION
+    {
+        "No_Compression", SSL_OP_NO_COMPRESSION
+    },
+#endif
+#if SSL_OP_NO_TICKET
+    {
+        "NO_TICKET", SSL_OP_NO_TICKET
+    },
+#endif
+#if SSL_OP_SINGLE_ECDH_USE
+    {
+        "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
+    },
+#endif
+    {
+        "", 0
+    },
+    {
+        NULL, 0
+    }
+};
+
+/**
+ * Pre-parse TLS options= parameter to be applied when the TLS objects created.
+ * Options must not used in the case of peek or stare bump mode.
+ */
+long
+Security::PeerOptions::parseOptions()
+{
+    long op = 0;
+    ::Parser::Tokenizer tok(sslOptions);
+
+    do {
+        enum {
+            MODE_ADD, MODE_REMOVE
+        } mode;
+
+        if (tok.skip('-') || tok.skip('!'))
+            mode = MODE_REMOVE;
+        else {
+            (void)tok.skip('+'); // default action is add. ignore if missing operator
+            mode = MODE_ADD;
+        }
+
+        static const CharacterSet optChars = CharacterSet("TLS-option", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT;
+        int64_t hex = 0;
+        SBuf option;
+        long value = 0;
+
+        if (tok.int64(hex, 16, false)) {
+            /* Special case.. hex specification */
+            value = hex;
+        }
+
+        else if (tok.prefix(option, optChars)) {
+            // find the named option in our supported set
+            for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) {
+                if (option.cmp(opttmp->name) == 0) {
+                    value = opttmp->value;
+                    break;
+                }
+            }
+        }
+
+        if (!value) {
+            fatalf("Unknown TLS option '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(option));
+        }
+
+        switch (mode) {
+
+        case MODE_ADD:
+            op |= value;
+            break;
+
+        case MODE_REMOVE:
+            op &= ~value;
+            break;
+        }
+
+        static const CharacterSet delims("TLS-option-delim",":,");
+        if (!tok.skipAll(delims) && !tok.atEnd()) {
+            fatalf("Unknown TLS option '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(tok.remaining()));
+        }
+
+    } while (!tok.atEnd());
+
+#if SSL_OP_NO_SSLv2
+    // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
+    op = op | SSL_OP_NO_SSLv2;
+#endif
+    return op;
+}
+
+/**
+ * Parses the TLS flags squid.conf parameter
+ */
+long
+Security::PeerOptions::parseFlags()
+{
+    if (sslFlags.isEmpty())
+        return 0;
+
+    static struct {
+        SBuf label;
+        long mask;
+    } flagTokens[] = {
+        { SBuf("NO_DEFAULT_CA"), SSL_FLAG_NO_DEFAULT_CA },
+        { SBuf("DELAYED_AUTH"), SSL_FLAG_DELAYED_AUTH },
+        { SBuf("DONT_VERIFY_PEER"), SSL_FLAG_DONT_VERIFY_PEER },
+        { SBuf("DONT_VERIFY_DOMAIN"), SSL_FLAG_DONT_VERIFY_DOMAIN },
+        { SBuf("NO_SESSION_REUSE"), SSL_FLAG_NO_SESSION_REUSE },
+#if X509_V_FLAG_CRL_CHECK
+        { SBuf("VERIFY_CRL"), SSL_FLAG_VERIFY_CRL },
+        { SBuf("VERIFY_CRL_ALL"), SSL_FLAG_VERIFY_CRL_ALL },
+#endif
+        { SBuf(), 0 }
+    };
+
+    ::Parser::Tokenizer tok(sslFlags);
+    static const CharacterSet delims("Flag-delimiter", ":,");
+
+    long fl = 0;
+    do {
+        long found = 0;
+        for (size_t i = 0; flagTokens[i].mask; ++i) {
+            if (tok.skip(flagTokens[i].label) == 0) {
+                found = flagTokens[i].mask;
+                break;
+            }
+        }
+        if (!found)
+            fatalf("Unknown TLS flag '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(tok.remaining()));
+        fl |= found;
+    } while (tok.skipOne(delims));
+
+    return fl;
+}
+
 void
 parse_securePeerOptions(Security::PeerOptions *opt)
 {
     while(const char *token = ConfigParser::NextToken())
         opt->parse(token);
 }
 

=== modified file 'src/security/PeerOptions.h'
--- src/security/PeerOptions.h	2015-05-22 09:42:55 +0000
+++ src/security/PeerOptions.h	2015-06-30 12:08:12 +0000
@@ -1,68 +1,83 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SRC_SECURITY_PEEROPTIONS_H
 #define SQUID_SRC_SECURITY_PEEROPTIONS_H
 
 #include "ConfigParser.h"
 #include "SBuf.h"
 #include "security/forward.h"
 
+class Packable;
+
 namespace Security
 {
 
 /// TLS squid.conf settings for a remote server peer
 class PeerOptions
 {
 public:
-    PeerOptions() : parsedOptions(0), sslVersion(0), encryptTransport(false) {}
+    PeerOptions() : parsedOptions(0), parsedFlags(0), sslVersion(0), encryptTransport(false) {}
+    PeerOptions(const PeerOptions &);
 
     /// parse a TLS squid.conf option
     void parse(const char *);
 
     /// reset the configuration details to default
     void clear() {*this = PeerOptions();}
 
-    /// generate a security context from these configured options
-    Security::ContextPointer createContext(bool setOptions);
+    /// generate a security client-context from these configured options
+    Security::ContextPointer createClientContext(bool setOptions);
+
+    /// sync the context options with tls-min-version=N configuration
+    void updateTlsVersionLimits();
+
+    /// output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
+    void dumpCfg(Packable *, const char *pfx) const;
 
+private:
+    long parseOptions();
+    long parseFlags();
+
+public:
     SBuf certFile;       ///< path of file containing PEM format X509 certificate
     SBuf privateKeyFile; ///< path of file containing private key in PEM format
     SBuf sslOptions;     ///< library-specific options string
     SBuf caFile;         ///< path of file containing trusted Certificate Authority
     SBuf caDir;          ///< path of directory containing a set of trusted Certificate Authorities
     SBuf crlFile;        ///< path of file containing Certificate Revoke List
 
     SBuf sslCipher;
-    SBuf sslFlags;
+    SBuf sslFlags;       ///< flags defining what TLS operations Squid performs
     SBuf sslDomain;
 
     SBuf tlsMinVersion;  ///< version label for minimum TLS version to permit
 
     long parsedOptions; ///< parsed value of sslOptions
+    long parsedFlags;   ///< parsed value of sslFlags
 
 private:
     int sslVersion;
 
 public:
     /// whether transport encryption (TLS/SSL) is to be used on connections to the peer
     bool encryptTransport;
 };
 
 /// configuration options for DIRECT server access
 extern PeerOptions ProxyOutgoingConfig;
 
 } // namespace Security
 
 // parse the tls_outgoing_options directive
 void parse_securePeerOptions(Security::PeerOptions *);
 #define free_securePeerOptions(x) Security::ProxyOutgoingConfig.clear()
-#define dump_securePeerOptions(e,n,x) // not supported yet
+#define dump_securePeerOptions(e,n,x) do { (e)->appendf(n); (x).dumpCfg((e),""); (e)->append("\n",1); } while(false)
 
 #endif /* SQUID_SRC_SECURITY_PEEROPTIONS_H */
 

=== modified file 'src/security/forward.h'
--- src/security/forward.h	2015-03-20 15:10:07 +0000
+++ src/security/forward.h	2015-03-25 09:39:15 +0000
@@ -1,24 +1,33 @@
 /*
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_SRC_SECURITY_FORWARD_H
 #define SQUID_SRC_SECURITY_FORWARD_H
 
 #include "security/Context.h"
 
+/* flags a SSL connection can be configured with */
+#define SSL_FLAG_NO_DEFAULT_CA      (1<<0)
+#define SSL_FLAG_DELAYED_AUTH       (1<<1)
+#define SSL_FLAG_DONT_VERIFY_PEER   (1<<2)
+#define SSL_FLAG_DONT_VERIFY_DOMAIN (1<<3)
+#define SSL_FLAG_NO_SESSION_REUSE   (1<<4)
+#define SSL_FLAG_VERIFY_CRL         (1<<5)
+#define SSL_FLAG_VERIFY_CRL_ALL     (1<<6)
+
 /// Network/connection security abstraction layer
 namespace Security
 {
 
 class EncryptorAnswer;
 class PeerOptions;
 
 } // namespace Security
 
 #endif /* SQUID_SRC_SECURITY_FORWARD_H */
 

=== modified file 'src/ssl/support.cc'
--- src/ssl/support.cc	2015-06-29 12:46:17 +0000
+++ src/ssl/support.cc	2015-06-30 10:45:09 +0000
@@ -337,315 +337,40 @@
         // Find the broken certificate. It may be intermediate.
         X509 *broken_cert = peer_cert; // reasonable default if search fails
         // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
         if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
             if (X509 *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
                 broken_cert = last_used_cert;
         }
 
         Ssl::ErrorDetail *errDetail =
             new Ssl::ErrorDetail(error_no, peer_cert, broken_cert);
 
         if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail,  errDetail)) {
             debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer);
             delete errDetail;
         }
     }
 
     return ok;
 }
 
-/// \ingroup ServerProtocolSSLInternal
-static struct ssl_option {
-    const char *name;
-    long value;
-}
-
-ssl_options[] = {
-
-#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
-    {
-        "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
-    },
-#endif
-#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
-    {
-        "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
-    },
-#endif
-#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
-    {
-        "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
-    },
-#endif
-#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
-    {
-        "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
-    },
-#endif
-#if SSL_OP_TLS_D5_BUG
-    {
-        "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
-    },
-#endif
-#if SSL_OP_TLS_BLOCK_PADDING_BUG
-    {
-        "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
-    },
-#endif
-#if SSL_OP_TLS_ROLLBACK_BUG
-    {
-        "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
-    },
-#endif
-#if SSL_OP_ALL
-    {
-        "ALL", (long)SSL_OP_ALL
-    },
-#endif
-#if SSL_OP_SINGLE_DH_USE
-    {
-        "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
-    },
-#endif
-#if SSL_OP_EPHEMERAL_RSA
-    {
-        "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
-    },
-#endif
-#if SSL_OP_PKCS1_CHECK_1
-    {
-        "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
-    },
-#endif
-#if SSL_OP_PKCS1_CHECK_2
-    {
-        "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
-    },
-#endif
-#if SSL_OP_NETSCAPE_CA_DN_BUG
-    {
-        "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
-    },
-#endif
-#if SSL_OP_NON_EXPORT_FIRST
-    {
-        "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
-    },
-#endif
-#if SSL_OP_CIPHER_SERVER_PREFERENCE
-    {
-        "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
-    },
-#endif
-#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
-    {
-        "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
-    },
-#endif
-#if SSL_OP_NO_SSLv3
-    {
-        "NO_SSLv3", SSL_OP_NO_SSLv3
-    },
-#endif
-#if SSL_OP_NO_TLSv1
-    {
-        "NO_TLSv1", SSL_OP_NO_TLSv1
-    },
-#endif
-#if SSL_OP_NO_TLSv1_1
-    {
-        "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
-    },
-#endif
-#if SSL_OP_NO_TLSv1_2
-    {
-        "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
-    },
-#endif
-#if SSL_OP_NO_COMPRESSION
-    {
-        "No_Compression", SSL_OP_NO_COMPRESSION
-    },
-#endif
-#if SSL_OP_NO_TICKET
-    {
-        "NO_TICKET", SSL_OP_NO_TICKET
-    },
-#endif
-#if SSL_OP_SINGLE_ECDH_USE
-    {
-        "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
-    },
-#endif
-    {
-        "", 0
-    },
-    {
-        NULL, 0
-    }
-};
-
-/// \ingroup ServerProtocolSSLInternal
-long
-Ssl::parse_options(const char *options)
-{
-    long op = 0;
-    char *tmp;
-    char *option;
-
-    if (!options)
-        goto no_options;
-
-    tmp = xstrdup(options);
-
-    option = strtok(tmp, ":,");
-
-    while (option) {
-
-        struct ssl_option *opt = NULL, *opttmp;
-        long value = 0;
-        enum {
-            MODE_ADD, MODE_REMOVE
-        } mode;
-
-        switch (*option) {
-
-        case '!':
-
-        case '-':
-            mode = MODE_REMOVE;
-            ++option;
-            break;
-
-        case '+':
-            mode = MODE_ADD;
-            ++option;
-            break;
-
-        default:
-            mode = MODE_ADD;
-            break;
-        }
-
-        for (opttmp = ssl_options; opttmp->name; ++opttmp) {
-            if (strcmp(opttmp->name, option) == 0) {
-                opt = opttmp;
-                break;
-            }
-        }
-
-        if (opt)
-            value = opt->value;
-        else if (strncmp(option, "0x", 2) == 0) {
-            /* Special case.. hex specification */
-            value = strtol(option + 2, NULL, 16);
-        } else {
-            fatalf("Unknown SSL option '%s'", option);
-            value = 0;      /* Keep GCC happy */
-        }
-
-        switch (mode) {
-
-        case MODE_ADD:
-            op |= value;
-            break;
-
-        case MODE_REMOVE:
-            op &= ~value;
-            break;
-        }
-
-        option = strtok(NULL, ":,");
-    }
-
-    safe_free(tmp);
-
-no_options:
-#if SSL_OP_NO_SSLv2
-    // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
-    op = op | SSL_OP_NO_SSLv2;
-#endif
-    return op;
-}
-
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_NO_DEFAULT_CA      (1<<0)
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_DELAYED_AUTH       (1<<1)
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_DONT_VERIFY_PEER   (1<<2)
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_DONT_VERIFY_DOMAIN (1<<3)
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_NO_SESSION_REUSE   (1<<4)
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_VERIFY_CRL     (1<<5)
-/// \ingroup ServerProtocolSSLInternal
-#define SSL_FLAG_VERIFY_CRL_ALL     (1<<6)
-
-/// \ingroup ServerProtocolSSLInternal
-long
-Ssl::parse_flags(const char *flags)
-{
-    long fl = 0;
-    char *tmp;
-    char *flag;
-
-    if (!flags)
-        return 0;
-
-    tmp = xstrdup(flags);
-
-    flag = strtok(tmp, ":,");
-
-    while (flag) {
-        if (strcmp(flag, "NO_DEFAULT_CA") == 0)
-            fl |= SSL_FLAG_NO_DEFAULT_CA;
-        else if (strcmp(flag, "DELAYED_AUTH") == 0)
-            fl |= SSL_FLAG_DELAYED_AUTH;
-        else if (strcmp(flag, "DONT_VERIFY_PEER") == 0)
-            fl |= SSL_FLAG_DONT_VERIFY_PEER;
-        else if (strcmp(flag, "DONT_VERIFY_DOMAIN") == 0)
-            fl |= SSL_FLAG_DONT_VERIFY_DOMAIN;
-        else if (strcmp(flag, "NO_SESSION_REUSE") == 0)
-            fl |= SSL_FLAG_NO_SESSION_REUSE;
-
-#if X509_V_FLAG_CRL_CHECK
-
-        else if (strcmp(flag, "VERIFY_CRL") == 0)
-            fl |= SSL_FLAG_VERIFY_CRL;
-        else if (strcmp(flag, "VERIFY_CRL_ALL") == 0)
-            fl |= SSL_FLAG_VERIFY_CRL_ALL;
-
-#endif
-
-        else
-            fatalf("Unknown ssl flag '%s'", flag);
-
-        flag = strtok(NULL, ":,");
-    }
-
-    safe_free(tmp);
-    return fl;
-}
-
 // "dup" function for SSL_get_ex_new_index("cert_err_check")
 static int
 ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
                     int, long, void *)
 {
     // We do not support duplication of ACLCheckLists.
     // If duplication is needed, we can count copies with cbdata.
     assert(false);
     return 0;
 }
 
 // "free" function for SSL_get_ex_new_index("cert_err_check")
 static void
 ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
                      int, long, void *)
 {
     delete static_cast<ACLChecklist *>(ptr); // may be NULL
 }
 
 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
@@ -850,185 +575,174 @@
         return false;
     }
 
     EC_KEY *ecdh = EC_KEY_new_by_curve_name(nid);
     if (ecdh == NULL)
         return false;
 
     const bool ok = SSL_CTX_set_tmp_ecdh(sslContext, ecdh) != 0;
     EC_KEY_free(ecdh);
     return ok;
 #else
     debugs(83, DBG_CRITICAL, "ERROR: EECDH is not available in this build. Please link against OpenSSL>=0.9.8 and ensure OPENSSL_NO_ECDH is not set.");
     return false;
 #endif
 }
 
 static bool
 configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
 {
     int ssl_error;
-    SSL_CTX_set_options(sslContext, port.sslOptions);
+    SSL_CTX_set_options(sslContext, port.secure.parsedOptions);
 
 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
     SSL_CTX_set_info_callback(sslContext, ssl_info_cb);
 #endif
 
     if (port.sslContextSessionId)
         SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
 
-    if (port.sslContextFlags & SSL_FLAG_NO_SESSION_REUSE) {
+    if (port.secure.parsedFlags & SSL_FLAG_NO_SESSION_REUSE) {
         SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
     }
 
     if (Config.SSL.unclean_shutdown) {
         debugs(83, 5, "Enabling quiet SSL shutdowns (RFC violation).");
 
         SSL_CTX_set_quiet_shutdown(sslContext, 1);
     }
 
-    if (port.cipher) {
-        debugs(83, 5, "Using chiper suite " << port.cipher << ".");
+    if (!port.secure.sslCipher.isEmpty()) {
+        debugs(83, 5, "Using chiper suite " << port.secure.sslCipher << ".");
 
-        if (!SSL_CTX_set_cipher_list(sslContext, port.cipher)) {
+        if (!SSL_CTX_set_cipher_list(sslContext, port.secure.sslCipher.c_str())) {
             ssl_error = ERR_get_error();
-            debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.cipher << "': " << ERR_error_string(ssl_error, NULL));
+            debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << ERR_error_string(ssl_error, NULL));
             return false;
         }
     }
 
     debugs(83, 9, "Setting RSA key generation callback.");
     SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
 
     if (port.eecdhCurve) {
         debugs(83, 9, "Setting Ephemeral ECDH curve to " << port.eecdhCurve << ".");
 
         if (!configureSslEECDH(sslContext, port.eecdhCurve)) {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Unable to configure Ephemeral ECDH: " << ERR_error_string(ssl_error, NULL));
             return false;
         }
     }
 
     debugs(83, 9, "Setting CA certificate locations.");
 
-    const char *cafile = port.cafile ? port.cafile : port.clientca;
-    if ((cafile || port.capath) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.capath)) {
+    const char *cafile = port.secure.caFile.isEmpty() ? port.clientca : port.secure.caFile.c_str();
+    if ((cafile || !port.secure.caDir.isEmpty()) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.secure.caDir.c_str())) {
         ssl_error = ERR_get_error();
         debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
     }
 
-    if (!(port.sslContextFlags & SSL_FLAG_NO_DEFAULT_CA) &&
+    if (!(port.secure.parsedFlags & SSL_FLAG_NO_DEFAULT_CA) &&
             !SSL_CTX_set_default_verify_paths(sslContext)) {
         ssl_error = ERR_get_error();
         debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
     }
 
     if (port.clientCA.get()) {
         ERR_clear_error();
         if (STACK_OF(X509_NAME) *clientca = SSL_dup_CA_list(port.clientCA.get())) {
             SSL_CTX_set_client_CA_list(sslContext, clientca);
         } else {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Failed to dupe the client CA list: " << ERR_error_string(ssl_error, NULL));
             return false;
         }
 
-        if (port.sslContextFlags & SSL_FLAG_DELAYED_AUTH) {
+        if (port.secure.parsedFlags & SSL_FLAG_DELAYED_AUTH) {
             debugs(83, 9, "Not requesting client certificates until acl processing requires one");
             SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
         } else {
             debugs(83, 9, "Requiring client certificates.");
             SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
         }
 
         if (port.clientVerifyCrls.get()) {
             X509_STORE *st = SSL_CTX_get_cert_store(sslContext);
             for (int i = 0; i < sk_X509_CRL_num(port.clientVerifyCrls.get()); ++i) {
                 X509_CRL *crl = sk_X509_CRL_value(port.clientVerifyCrls.get(), i);
                 if (!X509_STORE_add_crl(st, crl))
                     debugs(83, 2, "WARNING: Failed to add CRL");
             }
         }
 
 #if X509_V_FLAG_CRL_CHECK
-        if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL_ALL)
+        if (port.secure.parsedFlags & SSL_FLAG_VERIFY_CRL_ALL)
             X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
-        else if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL)
+        else if (port.secure.parsedFlags & SSL_FLAG_VERIFY_CRL)
             X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
 #endif
 
     } else {
         debugs(83, 9, "Not requiring any client certificates");
         SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
     }
 
     if (port.dhParams.get()) {
         SSL_CTX_set_tmp_dh(sslContext, port.dhParams.get());
     }
 
-    if (port.sslContextFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
+    if (port.secure.parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
         SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
 
     setSessionCallbacks(sslContext);
 
     return true;
 }
 
 SSL_CTX *
 sslCreateServerContext(AnyP::PortCfg &port)
 {
-    int ssl_error;
-    const char *keyfile, *certfile;
-    certfile = port.cert;
-    keyfile = port.key;
-
     ssl_initialize();
 
-    if (!keyfile)
-        keyfile = certfile;
-
-    if (!certfile)
-        certfile = keyfile;
-
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
     SSL_CTX *sslContext = SSL_CTX_new(TLS_server_method());
 #else
     SSL_CTX *sslContext = SSL_CTX_new(SSLv23_server_method());
 #endif
 
     if (sslContext == NULL) {
-        ssl_error = ERR_get_error();
+        int ssl_error = ERR_get_error();
         debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate SSL context: " << ERR_error_string(ssl_error, NULL));
         return NULL;
     }
 
     if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) {
-        ssl_error = ERR_get_error();
-        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
+        int ssl_error = ERR_get_error();
+        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << port.secure.certFile << "': " << ERR_error_string(ssl_error, NULL));
         SSL_CTX_free(sslContext);
         return NULL;
     }
 
     if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) {
-        ssl_error = ERR_get_error();
-        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
+        int ssl_error = ERR_get_error();
+        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << port.secure.privateKeyFile << "': " << ERR_error_string(ssl_error, NULL));
         SSL_CTX_free(sslContext);
         return NULL;
     }
 
     Ssl::addChainToSslContext(sslContext, port.certsToChain.get());
 
     /* Alternate code;
         debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
 
         if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
             SSL_CTX_free(sslContext);
             return NULL;
         }
 
         debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
         ssl_ask_password(sslContext, keyfile);
 
         if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
@@ -1041,166 +755,145 @@
         debugs(83, 5, "Comparing private and public SSL keys.");
 
         if (!SSL_CTX_check_private_key(sslContext)) {
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
                    keyfile << "': " << ERR_error_string(ssl_error, NULL));
             SSL_CTX_free(sslContext);
             return NULL;
         }
     */
 
     if (!configureSslContext(sslContext, port)) {
         debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
         SSL_CTX_free(sslContext);
         return NULL;
     }
 
     return sslContext;
 }
 
-int Ssl::OpenSSLtoSquidSSLVersion(int sslVersion)
-{
-    if (sslVersion == SSL2_VERSION)
-        return 2;
-    else if (sslVersion == SSL3_VERSION)
-        return 3;
-    else if (sslVersion == TLS1_VERSION)
-        return 4;
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-    else if (sslVersion == TLS1_1_VERSION)
-        return 5;
-    else if (sslVersion == TLS1_2_VERSION)
-        return 6;
-#endif
-    else
-        return 1;
-}
-
 #if defined(TLSEXT_TYPE_next_proto_neg)
 //Dummy next_proto_neg callback
 static int
 ssl_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
 {
     static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
     (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos, sizeof(supported_protos));
     return SSL_TLSEXT_ERR_OK;
 }
 #endif
 
 SSL_CTX *
-sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile)
+sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long fl, const char *CAfile, const char *CApath, const char *CRLfile)
 {
-    int ssl_error;
-    long fl = Ssl::parse_flags(flags);
-
     ssl_initialize();
 
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
     SSL_CTX *sslContext = SSL_CTX_new(TLS_client_method());
 #else
     SSL_CTX *sslContext = SSL_CTX_new(SSLv23_client_method());
 #endif
 
     if (sslContext == NULL) {
-        ssl_error = ERR_get_error();
+        int ssl_error = ERR_get_error();
         fatalf("Failed to allocate SSL context: %s\n",
                ERR_error_string(ssl_error, NULL));
     }
 
-    SSL_CTX_set_options(sslContext, Ssl::parse_options(options));
+    SSL_CTX_set_options(sslContext, options);
 
 #if defined(SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
     SSL_CTX_set_info_callback(sslContext, ssl_info_cb);
 #endif
 
     if (*cipher) {
         debugs(83, 5, "Using chiper suite " << cipher << ".");
 
         if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
-            ssl_error = ERR_get_error();
+            int ssl_error = ERR_get_error();
             fatalf("Failed to set SSL cipher suite '%s': %s\n",
                    cipher, ERR_error_string(ssl_error, NULL));
         }
     }
 
     if (*certfile) {
         debugs(83, DBG_IMPORTANT, "Using certificate in " << certfile);
 
         if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
-            ssl_error = ERR_get_error();
+            int ssl_error = ERR_get_error();
             fatalf("Failed to acquire SSL certificate '%s': %s\n",
                    certfile, ERR_error_string(ssl_error, NULL));
         }
 
         debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
         ssl_ask_password(sslContext, keyfile);
 
         if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
-            ssl_error = ERR_get_error();
+            int ssl_error = ERR_get_error();
             fatalf("Failed to acquire SSL private key '%s': %s\n",
                    keyfile, ERR_error_string(ssl_error, NULL));
         }
 
         debugs(83, 5, "Comparing private and public SSL keys.");
 
         if (!SSL_CTX_check_private_key(sslContext)) {
-            ssl_error = ERR_get_error();
+            int ssl_error = ERR_get_error();
             fatalf("SSL private key '%s' does not match public key '%s': %s\n",
                    certfile, keyfile, ERR_error_string(ssl_error, NULL));
         }
     }
 
     debugs(83, 9, "Setting RSA key generation callback.");
     SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
 
     if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
         debugs(83, 2, "NOTICE: Peer certificates are not verified for validity!");
         SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
     } else {
         debugs(83, 9, "Setting certificate verification callback.");
         SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
     }
 
     debugs(83, 9, "Setting CA certificate locations.");
 
     if ((*CAfile || *CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) {
-        ssl_error = ERR_get_error();
+        int ssl_error = ERR_get_error();
         debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
     }
 
     if (*CRLfile) {
         ssl_load_crl(sslContext, CRLfile);
         fl |= SSL_FLAG_VERIFY_CRL;
     }
 
 #if X509_V_FLAG_CRL_CHECK
     if (fl & SSL_FLAG_VERIFY_CRL_ALL)
         X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
     else if (fl & SSL_FLAG_VERIFY_CRL)
         X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
 
 #endif
 
     if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
             !SSL_CTX_set_default_verify_paths(sslContext)) {
-        ssl_error = ERR_get_error();
+        int ssl_error = ERR_get_error();
         debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
     }
 
 #if defined(TLSEXT_TYPE_next_proto_neg)
     SSL_CTX_set_next_proto_select_cb(sslContext, &ssl_next_proto_cb, NULL);
 #endif
     return sslContext;
 }
 
 /// \ingroup ServerProtocolSSLInternal
 int
 ssl_read_method(int fd, char *buf, int len)
 {
     SSL *ssl = fd_table[fd].ssl;
     int i;
 
 #if DONT_DO_THIS
 
     if (!SSL_is_init_finished(ssl)) {
         errno = ENOTCONN;

=== modified file 'src/ssl/support.h'
--- src/ssl/support.h	2015-05-22 09:42:55 +0000
+++ src/ssl/support.h	2015-06-30 10:45:03 +0000
@@ -75,41 +75,41 @@
 {
 public:
     ssl_error_t code; ///< certificate error code
     X509_Pointer cert; ///< certificate with the above error code
     CertError(ssl_error_t anErr, X509 *aCert);
     CertError(CertError const &err);
     CertError & operator = (const CertError &old);
     bool operator == (const CertError &ce) const;
     bool operator != (const CertError &ce) const;
 };
 
 /// Holds a list of certificate SSL errors
 typedef CbDataList<Ssl::CertError> CertErrors;
 
 } //namespace Ssl
 
 /// \ingroup ServerProtocolSSLAPI
 SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port);
 
 /// \ingroup ServerProtocolSSLAPI
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile);
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags, const char *CAfile, const char *CApath, const char *CRLfile);
 
 /// \ingroup ServerProtocolSSLAPI
 int ssl_read_method(int, char *, int);
 
 /// \ingroup ServerProtocolSSLAPI
 int ssl_write_method(int, const char *, int);
 
 /// \ingroup ServerProtocolSSLAPI
 void ssl_shutdown_method(SSL *ssl);
 
 /// \ingroup ServerProtocolSSLAPI
 const char *sslGetUserEmail(SSL *ssl);
 
 /// \ingroup ServerProtocolSSLAPI
 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name);
 
 /// \ingroup ServerProtocolSSLAPI
 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name);
 
 /// \ingroup ServerProtocolSSLAPI
@@ -148,46 +148,40 @@
  */
 extern const char *BumpModeStr[];
 
 /**
  \ingroup ServerProtocolSSLAPI
  * Return the short name of the ssl-bump mode "bm"
  */
 inline const char *bumpMode(int bm)
 {
     return (0 <= bm && bm < Ssl::bumpEnd) ? Ssl::BumpModeStr[bm] : NULL;
 }
 
 /**
  \ingroup ServerProtocolSSLAPI
  * Parses the SSL flags.
  */
 long parse_flags(const char *flags);
 
 /**
  \ingroup ServerProtocolSSLAPI
- * Parses the SSL options.
- */
-long parse_options(const char *options);
-
-/**
- \ingroup ServerProtocolSSLAPI
  * Load a CRLs list stored in a file
  */
 STACK_OF(X509_CRL) *loadCrl(const char *CRLFile, long &flags);
 
 /**
  \ingroup ServerProtocolSSLAPI
  * Load DH params from file
  */
 DH *readDHParams(const char *dhfile);
 
 /**
   \ingroup ServerProtocolSSLAPI
   * Generate a certificate to be used as untrusted signing certificate, based on a trusted CA
 */
 bool generateUntrustedCert(X509_Pointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey);
 
 /**
   \ingroup ServerProtocolSSLAPI
   * Decide on the kind of certificate and generate a CA- or self-signed one
 */
@@ -265,42 +259,40 @@
 bool checkX509ServerValidity(X509 *cert, const char *server);
 
 /**
    \ingroup ServerProtocolSSLAPI
    * Convert a given ASN1_TIME to a string form.
    \param tm the time in ASN1_TIME form
    \param buf the buffer to write the output
    \param len write at most len bytes
    \return The number of bytes written
  */
 int asn1timeToString(ASN1_TIME *tm, char *buf, int len);
 
 /**
    \ingroup ServerProtocolSSLAPI
    * Sets the hostname for the Server Name Indication (SNI) TLS extension
    * if supported by the used openssl toolkit.
    \return true if SNI set false otherwise
 */
 bool setClientSNI(SSL *ssl, const char *fqdn);
 
-int OpenSSLtoSquidSSLVersion(int sslVersion);
-
 /**
    \ingroup ServerProtocolSSLAPI
    * Initializes the shared session cache if configured
 */
 void initialize_session_cache();
 
 /**
    \ingroup ServerProtocolSSLAPI
    * Destroy the shared session cache if configured
 */
 void destruct_session_cache();
 } //namespace Ssl
 
 #if _SQUID_WINDOWS_
 
 #if defined(__cplusplus)
 
 /** \cond AUTODOCS-IGNORE */
 namespace Squid
 {

=== modified file 'src/tests/stub_libsecurity.cc'
--- src/tests/stub_libsecurity.cc	2015-03-20 15:10:07 +0000
+++ src/tests/stub_libsecurity.cc	2015-06-30 12:09:41 +0000
@@ -2,23 +2,27 @@
  * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
  * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #include "squid.h"
 #include "comm/Connection.h"
 
 #define STUB_API "security/libsecurity.la"
 #include "tests/STUB.h"
 
 #include "security/EncryptorAnswer.h"
 Security::EncryptorAnswer::~EncryptorAnswer() {}
 std::ostream &Security::operator <<(std::ostream &os, const Security::EncryptorAnswer &) STUB_RETVAL(os)
 
 #include "security/PeerOptions.h"
 Security::PeerOptions Security::ProxyOutgoingConfig;
 void Security::PeerOptions::parse(char const*) STUB
-Security::ContextPointer Security::PeerOptions::createContext(bool) STUB_RETVAL(NULL)
+Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL)
+void Security::PeerOptions::updateTlsVersionLimits() STUB
+void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB
+long Security::PeerOptions::parseOptions() STUB_RETVAL(0)
+long Security::PeerOptions::parseFlags() STUB_RETVAL(0)
 void parse_securePeerOptions(Security::PeerOptions *) STUB
 

=== modified file 'src/tests/stub_libsslsquid.cc'
--- src/tests/stub_libsslsquid.cc	2015-05-22 09:42:55 +0000
+++ src/tests/stub_libsslsquid.cc	2015-06-13 07:33:01 +0000
@@ -40,55 +40,54 @@
 void Ssl::GlobalContextStorage::reconfigureStart() STUB
 //Ssl::GlobalContextStorage Ssl::TheGlobalContextStorage;
 
 #include "ssl/ErrorDetail.h"
 Ssl::ssl_error_t parseErrorString(const char *name) STUB_RETVAL(0)
 //const char *Ssl::getErrorName(ssl_error_t value) STUB_RETVAL(NULL)
 Ssl::ErrorDetail::ErrorDetail(ssl_error_t err_no, X509 *, X509 *, const char *) STUB
 Ssl::ErrorDetail::ErrorDetail(ErrorDetail const &) STUB
 const String & Ssl::ErrorDetail::toString() const STUB_RETSTATREF(String)
 
 #include "ssl/support.h"
 namespace Ssl
 {
 //CertError::CertError(ssl_error_t anErr, X509 *aCert) STUB
 //CertError::CertError(CertError const &err) STUB
 CertError & CertError::operator = (const CertError &old) STUB_RETVAL(*this)
 bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false)
 bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false)
 } // namespace Ssl
 SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port) STUB_RETVAL(NULL)
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile) STUB_RETVAL(NULL)
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags, const char *CAfile, const char *CApath, const char *CRLfile) STUB_RETVAL(NULL)
 int ssl_read_method(int, char *, int) STUB_RETVAL(0)
 int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
 void ssl_shutdown_method(SSL *ssl) STUB
 const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
 const char *sslGetUserCertificatePEM(SSL *ssl) STUB_RETVAL(NULL)
 const char *sslGetUserCertificateChainPEM(SSL *ssl) STUB_RETVAL(NULL)
 namespace Ssl
 {
 //GETX509ATTRIBUTE GetX509UserAttribute;
 //GETX509ATTRIBUTE GetX509CAAttribute;
 //GETX509ATTRIBUTE GetX509Fingerprint;
 const char *BumpModeStr[] = {""};
 long parse_flags(const char *flags) STUB_RETVAL(0)
-long parse_options(const char *options) STUB_RETVAL(0)
 STACK_OF(X509_CRL) *loadCrl(const char *CRLFile, long &flags) STUB_RETVAL(NULL)
 DH *readDHParams(const char *dhfile) STUB_RETVAL(NULL)
 bool generateUntrustedCert(X509_Pointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey) STUB_RETVAL(false)
 SSL_CTX * generateSslContext(CertificateProperties const &properties, AnyP::PortCfg &port) STUB_RETVAL(NULL)
 bool verifySslCertificate(SSL_CTX * sslContext,  CertificateProperties const &properties) STUB_RETVAL(false)
 SSL_CTX * generateSslContextUsingPkeyAndCertFromMemory(const char * data, AnyP::PortCfg &port) STUB_RETVAL(NULL)
 void addChainToSslContext(SSL_CTX *sslContext, STACK_OF(X509) *certList) STUB
 void readCertChainAndPrivateKeyFromFiles(X509_Pointer & cert, EVP_PKEY_Pointer & pkey, X509_STACK_Pointer & chain, char const * certFilename, char const * keyFilename) STUB
 int matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data,  ASN1_STRING *cn_data)) STUB_RETVAL(0)
 bool checkX509ServerValidity(X509 *cert, const char *server) STUB_RETVAL(false)
 int asn1timeToString(ASN1_TIME *tm, char *buf, int len) STUB_RETVAL(0)
 bool setClientSNI(SSL *ssl, const char *fqdn) STUB_RETVAL(false)
 void initialize_session_cache() STUB
 void destruct_session_cache() STUB
 } //namespace Ssl
 
 #endif
 



More information about the squid-dev mailing list