---------------------
PatchSet 5519 
Date: 2002/11/29 17:49:17
Author: hno
Branch: ssl-2_5
Tag: (none) 
Log:
Imported SSL update patch

  * Client certificate support
  * SSL encrypted peers support
  * Gatewaying of https:// URLs for non-SSL enabled browsers
  * Hardware SSL acceleration support
  * Some bugfixes & optimizations

Members: 
	configure.in:1.42.2.30->1.42.2.30.2.1 
	src/HttpHeader.c:1.10.6.4->1.10.6.4.2.1 
	src/access_log.c:1.15.6.2->1.15.6.2.2.1 
	src/acl.c:1.43.2.11->1.43.2.11.2.1 
	src/cache_cf.c:1.38.6.9->1.38.6.9.2.1 
	src/cf.data.pre:1.49.2.27->1.49.2.27.2.1 
	src/client_side.c:1.47.2.21->1.47.2.21.2.1 
	src/enums.h:1.29.2.7->1.29.2.7.2.1 
	src/external_acl.c:1.2.4.11->1.2.4.11.2.1 
	src/forward.c:1.13.6.1->1.13.6.1.8.1 
	src/globals.h:1.14.6.2->1.14.6.2.2.1 
	src/http.c:1.17.6.3->1.17.6.3.2.1 
	src/mem.c:1.13->1.13.24.1 
	src/ssl_support.c:1.6.6.1->1.6.6.1.2.1 
	src/ssl_support.h:1.5->1.5.44.1 
	src/structs.h:1.48.2.8->1.48.2.8.2.1 
	src/typedefs.h:1.25.6.1->1.25.6.1.2.1 

Index: squid/configure.in
===================================================================
RCS file: /cvsroot/squid-sf//squid/configure.in,v
retrieving revision 1.42.2.30
retrieving revision 1.42.2.30.2.1
diff -u -r1.42.2.30 -r1.42.2.30.2.1
--- squid/configure.in	22 Oct 2002 08:36:20 -0000	1.42.2.30
+++ squid/configure.in	29 Nov 2002 17:49:17 -0000	1.42.2.30.2.1
@@ -3,7 +3,7 @@
 dnl
 dnl  Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
 dnl
-dnl  $Id: configure.in,v 1.42.2.30 2002/10/22 08:36:20 squidadm Exp $
+dnl  $Id: configure.in,v 1.42.2.30.2.1 2002/11/29 17:49:17 hno Exp $
 dnl
 dnl
 dnl
@@ -11,7 +11,7 @@
 AC_CONFIG_AUX_DIR(cfgaux)
 AM_INIT_AUTOMAKE(squid, 2.5.STABLE1-CVS)
 AM_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.42.2.30 $)dnl
+AC_REVISION($Revision: 1.42.2.30.2.1 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AM_MAINTAINER_MODE
 
@@ -1144,6 +1144,7 @@
 	openssl/err.h \
 	openssl/md5.h \
 	openssl/ssl.h \
+	openssl/engine.h \
 	poll.h \
 	pwd.h \
 	regex.h \
Index: squid/src/HttpHeader.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/HttpHeader.c,v
retrieving revision 1.10.6.4
retrieving revision 1.10.6.4.2.1
diff -u -r1.10.6.4 -r1.10.6.4.2.1
--- squid/src/HttpHeader.c	25 Jun 2002 08:12:12 -0000	1.10.6.4
+++ squid/src/HttpHeader.c	29 Nov 2002 17:49:17 -0000	1.10.6.4.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHeader.c,v 1.10.6.4 2002/06/25 08:12:12 squidadm Exp $
+ * $Id: HttpHeader.c,v 1.10.6.4.2.1 2002/11/29 17:49:17 hno Exp $
  *
  * DEBUG: section 55    HTTP Header
  * AUTHOR: Alex Rousskov
@@ -129,6 +129,7 @@
 #if X_ACCELERATOR_VARY
     {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr},
 #endif
+    {"Front-End-Https", HDR_FRONT_END_HTTPS, ftStr},
     {"Other:", HDR_OTHER, ftStr}	/* ':' will not allow matches */
 };
 static HttpHeaderFieldInfo *Headers = NULL;
Index: squid/src/access_log.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/access_log.c,v
retrieving revision 1.15.6.2
retrieving revision 1.15.6.2.2.1
diff -u -r1.15.6.2 -r1.15.6.2.2.1
--- squid/src/access_log.c	16 Jun 2002 19:51:59 -0000	1.15.6.2
+++ squid/src/access_log.c	29 Nov 2002 17:49:17 -0000	1.15.6.2.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: access_log.c,v 1.15.6.2 2002/06/16 19:51:59 squidadm Exp $
+ * $Id: access_log.c,v 1.15.6.2.2.1 2002/11/29 17:49:17 hno Exp $
  *
  * DEBUG: section 46    Access Log
  * AUTHOR: Duane Wessels
@@ -235,13 +235,20 @@
 accessLogSquid(AccessLogEntry * al)
 {
     const char *client = NULL;
-    char *user = NULL;
+    const char *user = NULL;
     if (Config.onoff.log_fqdn)
 	client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
     if (client == NULL)
 	client = inet_ntoa(al->cache.caddr);
-    user = accessLogFormatName(al->cache.authuser ?
-	al->cache.authuser : al->cache.rfc931);
+    user = accessLogFormatName(al->cache.authuser);
+#if USE_SSL
+    if (!user)
+	user = accessLogFormatName(al->cache.ssluser);
+#endif
+    if (!user)
+	user = accessLogFormatName(al->cache.rfc931);
+    if (user && !*user)
+	safe_free(user);
     logfilePrintf(logfile, "%9d.%03d %6d %s %s/%03d %ld %s %s %s %s%s/%s %s",
 	(int) current_time.tv_sec,
 	(int) current_time.tv_usec / 1000,
@@ -252,7 +259,7 @@
 	(long int) al->cache.size,
 	al->private.method_str,
 	al->url,
-	user && *user ? user : dash_str,
+	user ? user : dash_str,
 	al->hier.ping.timedout ? "TIMEOUT_" : "",
 	hier_strings[al->hier.code],
 	al->hier.host,
Index: squid/src/acl.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/acl.c,v
retrieving revision 1.43.2.11
retrieving revision 1.43.2.11.2.1
diff -u -r1.43.2.11 -r1.43.2.11.2.1
--- squid/src/acl.c	10 Nov 2002 22:44:12 -0000	1.43.2.11
+++ squid/src/acl.c	29 Nov 2002 17:49:18 -0000	1.43.2.11.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: acl.c,v 1.43.2.11 2002/11/10 22:44:12 squidadm Exp $
+ * $Id: acl.c,v 1.43.2.11.2.1 2002/11/29 17:49:18 hno Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -101,6 +101,14 @@
 static SPLAYCMP aclArpCompare;
 static SPLAYWALKEE aclDumpArpListWalkee;
 #endif
+#if USE_SSL
+static void aclParseCertList(void *curlist);
+static int aclMatchUserCert(void *data, aclCheck_t *);
+static int aclMatchCACert(void *data, aclCheck_t *);
+static wordlist *aclDumpCertList(void *data);
+static void aclDestroyCertList(void *data);
+#endif
+
 static int aclCacheMatchAcl(dlink_list * cache, squid_acl acltype, void *data, char *MatchParam);
 
 static squid_acl
@@ -178,6 +186,12 @@
 	return ACL_MAX_USER_IP;
     if (!strcmp(s, "external"))
 	return ACL_EXTERNAL;
+#if USE_SSL
+    if (!strcmp(s, "user_cert"))
+	return ACL_USER_CERT;
+    if (!strcmp(s, "ca_cert"))
+	return ACL_CA_CERT;
+#endif
     return ACL_NONE;
 }
 
@@ -252,6 +266,12 @@
 	return "max_user_ip";
     if (type == ACL_EXTERNAL)
 	return "external";
+#if USE_SSL
+    if (type == ACL_USER_CERT)
+	return "user_cert";
+    if (type == ACL_CA_CERT)
+	return "ca_cert";
+#endif
     return "ERROR";
 }
 
@@ -672,6 +692,91 @@
     }
 }
 
+#if USE_SSL
+static void
+aclParseCertList(void *curlist)
+{
+    acl_cert_data **datap = curlist;
+    splayNode **Top;
+    char *t;
+    char *attribute = strtokFile();
+    if (!attribute)
+	self_destruct();
+    if (*datap) {
+	if (strcasecmp((*datap)->attribute, attribute) != 0)
+	    self_destruct();
+    } else {
+	*datap = memAllocate(MEM_ACL_DENY_INFO_LIST);
+	(*datap)->attribute = xstrdup(attribute);
+    }
+    Top = &(*datap)->values;
+    while ((t = strtokFile())) {
+	*Top = splay_insert(xstrdup(t), *Top, aclDomainCompare);
+    }
+}
+
+static int
+aclMatchUserCert(void *data, aclCheck_t * checklist)
+{
+    acl_cert_data *cert_data = data;
+    const char *value;
+    SSL *ssl = fd_table[checklist->conn->fd].ssl;
+
+    if (!ssl)
+	return 0;
+    value = sslGetUserAttribute(ssl, cert_data->attribute);
+    if (!value)
+	return 0;
+    cert_data->values = splay_splay(value, cert_data->values, (SPLAYCMP *) strcmp);
+    return !splayLastResult;
+}
+
+static int
+aclMatchCACert(void *data, aclCheck_t * checklist)
+{
+    acl_cert_data *cert_data = data;
+    const char *value;
+    SSL *ssl = fd_table[checklist->conn->fd].ssl;
+
+    if (!ssl)
+	return 0;
+    value = sslGetCAAttribute(ssl, cert_data->attribute);
+    if (!value)
+	return 0;
+    cert_data->values = splay_splay(value, cert_data->values, (SPLAYCMP *) strcmp);
+    return !splayLastResult;
+}
+
+static void
+aclDestroyCertList(void *curlist)
+{
+    acl_cert_data **datap = curlist;
+    if (!*datap)
+	return;
+    splay_destroy((*datap)->values, xfree);
+    memFree(*datap, MEM_ACL_CERT_DATA);
+    *datap = NULL;
+}
+
+static void
+aclDumpCertListWalkee(void *node_data, void *outlist)
+{
+    /* outlist is really a wordlist ** */
+    wordlistAdd(outlist, node_data);
+}
+
+static wordlist *
+aclDumpCertList(void *curlist)
+{
+    acl_cert_data *data = curlist;
+    wordlist *wl = NULL;
+    wordlistAdd(&wl, data->attribute);
+    if (data->values)
+	splay_walk(data->values, aclDumpCertListWalkee, &wl);
+    return wl;
+}
+#endif
+
 void
 aclParseAclLine(acl ** head)
 {
@@ -812,6 +917,12 @@
     case ACL_EXTERNAL:
 	aclParseExternal(&A->data);
 	break;
+#if USE_SSL
+    case ACL_USER_CERT:
+    case ACL_CA_CERT:
+	aclParseCertList(&A->data);
+	break;
+#endif
     case ACL_NONE:
     case ACL_ENUM_MAX:
 	fatal("Bad ACL type");
@@ -1676,6 +1787,14 @@
     case ACL_EXTERNAL:
 	return aclMatchExternal(ae->data, checklist);
 	/* NOTREACHED */
+#if USE_SSL
+    case ACL_USER_CERT:
+	return aclMatchUserCert(ae->data, checklist);
+	/* NOTREACHED */
+    case ACL_CA_CERT:
+	return aclMatchCACert(ae->data, checklist);
+	/* NOTREACHED */
+#endif
     case ACL_NONE:
     case ACL_ENUM_MAX:
 	break;
@@ -2120,6 +2239,12 @@
 	case ACL_EXTERNAL:
 	    aclDestroyExternal(&a->data);
 	    break;
+#if USE_SSL
+	case ACL_USER_CERT:
+	case ACL_CA_CERT:
+	    aclDestroyCertList(&a->data);
+	    break;
+#endif
 	case ACL_NONE:
 	case ACL_ENUM_MAX:
 	    debug(28, 1) ("aclDestroyAcls: no case for ACL type %d\n", a->type);
@@ -2533,6 +2658,11 @@
 #endif
     case ACL_EXTERNAL:
 	return aclDumpExternal(a->data);
+#if USE_SSL
+    case ACL_USER_CERT:
+    case ACL_CA_CERT:
+	return aclDumpCertList(a->data);
+#endif
     case ACL_NONE:
     case ACL_ENUM_MAX:
 	break;
Index: squid/src/cache_cf.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/cache_cf.c,v
retrieving revision 1.38.6.9
retrieving revision 1.38.6.9.2.1
diff -u -r1.38.6.9 -r1.38.6.9.2.1
--- squid/src/cache_cf.c	15 Nov 2002 03:14:10 -0000	1.38.6.9
+++ squid/src/cache_cf.c	29 Nov 2002 17:49:18 -0000	1.38.6.9.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cache_cf.c,v 1.38.6.9 2002/11/15 03:14:10 squidadm Exp $
+ * $Id: cache_cf.c,v 1.38.6.9.2.1 2002/11/29 17:49:18 hno Exp $
  *
  * DEBUG: section 3     Configuration File Parsing
  * AUTHOR: Harvest Derived
@@ -433,6 +433,9 @@
 	    debug(22, 0) ("WARNING: 'maxconn' ACL (%s) won't work with client_db disabled\n", a->name);
 	}
     }
+#if USE_SSL
+    Config.ssl_client.sslContext = sslCreateClientContext(Config.ssl_client.cert, Config.ssl_client.key, Config.ssl_client.version, Config.ssl_client.cipher, Config.ssl_client.options, Config.ssl_client.flags, Config.ssl_client.cafile, Config.ssl_client.capath);
+#endif
 }
 
 /* Parse a time specification from the config file.  Store the
@@ -1465,6 +1468,42 @@
 	    p->options.allow_miss = 1;
 	} else if (!strncasecmp(token, "max-conn=", 9)) {
 	    p->max_conn = atoi(token + 9);
+#if USE_SSL
+	} else if (strcmp(token, "ssl") == 0) {
+	    p->use_ssl = 1;
+	} else if (strncmp(token, "sslcert=", 8) == 0) {
+	    safe_free(p->sslcert);
+	    p->sslcert = xstrdup(token + 8);
+	} else if (strncmp(token, "sslkey=", 7) == 0) {
+	    safe_free(p->sslkey);
+	    p->sslkey = xstrdup(token + 7);
+	} else if (strncmp(token, "sslversion=", 11) == 0) {
+	    p->sslversion = atoi(token + 11);
+	} else if (strncmp(token, "ssloptions=", 11) == 0) {
+	    safe_free(p->ssloptions);
+	    p->ssloptions = xstrdup(token + 11);
+	} else if (strncmp(token, "sslcipher=", 10) == 0) {
+	    safe_free(p->sslcipher);
+	    p->sslcipher = xstrdup(token + 10);
+	} else if (strncmp(token, "sslcafile=", 10) == 0) {
+	    safe_free(p->sslcafile);
+	    p->sslcipher = xstrdup(token + 10);
+	} else if (strncmp(token, "sslcapath=", 10) == 0) {
+	    safe_free(p->sslcapath);
+	    p->sslcipher = xstrdup(token + 10);
+	} else if (strncmp(token, "sslflags=", 9) == 0) {
+	    safe_free(p->sslflags);
+	    p->sslflags = xstrdup(token + 9);
+	} else if (strncmp(token, "ssldomain=", 10) == 0) {
+	    safe_free(p->ssldomain);
+	    p->ssldomain = xstrdup(token + 10);
+#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 {
 	    debug(3, 0) ("parse_peer: token='%s'\n", token);
 	    self_destruct();
@@ -1492,6 +1531,11 @@
 	cbdataLock(p->digest);	/* so we know when/if digest disappears */
     }
 #endif
+#if USE_SSL
+    if (p->use_ssl) {
+	p->sslContext = sslCreateClientContext(p->sslcert, p->sslkey, p->sslversion, p->sslcipher, p->ssloptions, p->sslflags, p->sslcafile, p->sslcapath);
+    }
+#endif
     while (*head != NULL)
 	head = &(*head)->next;
     *head = p;
@@ -2330,12 +2374,25 @@
 	} else if (strncmp(token, "cipher=", 7) == 0) {
 	    safe_free(s->cipher);
 	    s->cipher = xstrdup(token + 7);
+	} 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);
+	} else if (strncmp(token, "capath=", 7) == 0) {
+	    safe_free(s->capath);
+	    s->capath = xstrdup(token + 7);
+	} else if (strncmp(token, "sslflags=", 9) == 0) {
+	    safe_free(s->sslflags);
+	    s->sslflags = xstrdup(token + 9);
 	} else {
 	    self_destruct();
 	}
     }
     while (*head)
 	head = &(*head)->next;
+    s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath);
     *head = s;
 }
 
@@ -2343,18 +2400,26 @@
 dump_https_port_list(StoreEntry * e, const char *n, const https_port_list * s)
 {
     while (s) {
-	storeAppendPrintf(e, "%s %s:%d cert=\"%s\" key=\"%s\"",
+	storeAppendPrintf(e, "%s %s:%d",
 	    n,
 	    inet_ntoa(s->s.sin_addr),
-	    ntohs(s->s.sin_port),
-	    s->cert,
-	    s->key);
+	    ntohs(s->s.sin_port));
+	if (s->cert)
+	    storeAppendPrintf(e, " cert=%s", s->cert);
+	if (s->key)
+	    storeAppendPrintf(e, " key=%s", s->cert);
 	if (s->version)
 	    storeAppendPrintf(e, " version=%d", s->version);
 	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->sslflags)
+	    storeAppendPrintf(e, " sslflags=%s", s->sslflags);
 	storeAppendPrintf(e, "\n");
 	s = s->next;
     }
Index: squid/src/cf.data.pre
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v
retrieving revision 1.49.2.27
retrieving revision 1.49.2.27.2.1
diff -u -r1.49.2.27 -r1.49.2.27.2.1
--- squid/src/cf.data.pre	10 Nov 2002 22:44:12 -0000	1.49.2.27
+++ squid/src/cf.data.pre	29 Nov 2002 17:49:18 -0000	1.49.2.27.2.1
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.49.2.27 2002/11/10 22:44:12 squidadm Exp $
+# $Id: cf.data.pre,v 1.49.2.27.2.1 2002/11/29 17:49:18 hno Exp $
 #
 #
 # SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -131,6 +131,26 @@
 			    NO_TLSv1  Disallow the use of TLSv1
 			See src/ssl_support.c or OpenSSL documentation
 			for a more complete list.
+
+	   clientca=	File containing the list of CAs to use when
+			requesting a client certificate
+
+	   cafile=	File containing additional CA certificates to
+			use when verifying client certificates. If unset
+			clientca will be used.
+
+	   capath=	Directory containing additional CA certificates
+			to use when verifying client certificates
+
+	   sslflags=	Various flags modifying the use of SSL:
+			    DELAYED_AUTH
+				Don't request client certificates
+				immediately, but wait until acl processing
+				requires a certificate
+			    NO_DEFAULT_CA	
+				Don't use the default CA list built in
+				to OpenSSL.
+
 DOC_END
 
 NAME: ssl_unclean_shutdown
@@ -143,6 +163,85 @@
 	messages.
 DOC_END
 
+NAME: ssl_engine
+IFDEF: USE_SSL
+TYPE: string
+LOC: Config.SSL.ssl_engine
+DEFAULT: none
+DOC_START
+	The openssl engine to use. You will need to set this if you
+	would like to use hardware SSL acceleration for example.
+DOC_END
+
+NAME: sslproxy_client_certificate
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.cert
+TYPE: string
+DOC_START
+	Client SSL Certificate to use when proxying https:// URLs
+DOC_END
+
+NAME: sslproxy_client_key
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.key
+TYPE: string
+DOC_START
+	Client SSL Key to use when proxying https:// URLs
+DOC_END
+
+NAME: sslproxy_version
+IFDEF: USE_SSL
+DEFAULT: 1
+LOC: Config.ssl_client.version
+TYPE: int
+DOC_START
+	SSL version level to use when proxying https:// URLs
+DOC_END
+
+NAME: sslproxy_options
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.options
+TYPE: string
+DOC_START
+	SSL engine options to use when proxying https:// URLs
+DOC_END
+
+NAME: sslproxy_cipher
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.cipher
+TYPE: string
+DOC_START
+	SSL cipher list to use when proxying https:// URLs
+DOC_END
+
+NAME: sslproxy_cafile
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.cafile
+TYPE: string
+DOC_START
+DOC_END
+
+NAME: sslproxy_capath
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.capath
+TYPE: string
+DOC_START
+DOC_END
+
+NAME: sslproxy_flags
+IFDEF: USE_SSL
+DEFAULT: none
+LOC: Config.ssl_client.flags
+TYPE: string
+DOC_START
+DOC_END
+
 NAME: icp_port udp_port
 TYPE: ushort
 DEFAULT: 3130
@@ -236,7 +335,7 @@
 DOC_START
 	To specify other caches in a hierarchy, use the format:
 
-		cache_peer hostname type http_port icp_port
+		cache_peer hostname type http_port icp_port [options]
 
 	For example,
 
@@ -274,6 +373,13 @@
 		     digest-url=url
 		     allow-miss
 		     max-conn
+		     ssl
+		     sslcert=/path/to/ssl/certificate
+		     sslkey=/path/to/ssl/key
+		     sslversion=1|2|3|4
+		     sslcipher=...
+		     ssloptions=...
+		     front-end-https[=on|auto]
 
 		     use 'proxy-only' to specify that objects fetched
 		     from this cache should not be saved locally.
@@ -363,6 +469,64 @@
 		     use 'max-conn' to limit the amount of connections Squid
 		     may open to this peer.
 
+		     use 'ssl' to indicate that connections to this peer should
+		     bs SSL/TLS encrypted.
+
+		     use 'sslcert=/path/to/ssl/certificate' to specify a client
+		     SSL certificate to use when connecting to this peer.
+
+		     use 'sslkey=/path/to/ssl/key' to specify the private SSL
+		     key corresponding to sslcert above. If 'sslkey' is not
+		     specified then 'sslcert' is assumed to reference a
+		     combined file containing both the certificate and the key.
+
+		     use sslversion=1|2|3|4 to specify the SSL version to use
+		     when connecting to this peer
+			1 = automatic (default)
+			2 = SSL v2 only
+			3 = SSL v3 only
+			4 = TLS v1 only
+
+		     use sslcipher=... to specify the list of valid SSL chipers
+		     to use when connecting to this peer
+
+		     use ssloptions=... to specify various SSL engine options:
+			NO_SSLv2  Disallow the use of SSLv2
+			NO_SSLv3  Disallow the use of SSLv3
+			NO_TLSv1  Disallow the use of TLSv1
+		     See src/ssl_support.c or the OpenSSL documentation for
+		     a more complete list.
+
+		     use cafile=... to specify a file containing additional
+		     CA certificates to use when verifying the peer certificate
+
+		     use capath=... to specify a directory containing additional
+		     CA certificates to use when verifying the peer certificate
+
+		     use sslflags=... to specify various flags modifying the
+		     SSL implementation:
+			DONT_VERIFY_PEER
+				Accept certificates even if they fail to
+				verify.
+			NO_DEFAULT_CA	
+				Don't use the default CA list built in
+				to OpenSSL.
+			DONT_VERIFY_DOMAIN
+				Don't verify that the peer certificate
+				matches the server name
+
+		     use sslname= to specify the peer name as advertised
+		     in it's certificate. Used for verifying the correctness
+		     of the received peer certificate. If not specified the
+		     peer hostname will be used.
+
+		     use front-end-https to enable the "Front-End-Https: On"
+		     header needed when using Squid as a SSL frontend infront
+		     of Microsoft OWA. See MS KB document Q307347 for details
+		     on this header. If set to auto then the header will
+		     only be added if the request is forwarded as a https://
+		     URL.
+
 	NOTE: non-ICP neighbors must be specified as 'parent'.
 DOC_END
 
@@ -1465,6 +1629,8 @@
 	  %PROTO	Requested protocol
 	  %PORT		Requested port
 	  %METHOD	Request method
+	  %USER_CERT_xx	SSL User certificate attribute xx
+	  %USER_CA_xx	SSL User certificate CA attribute xx
 	  %{Header}	HTTP request header
 	  %{Hdr:member}	HTTP request header list member
 	  %{Hdr:;member}
@@ -1988,6 +2154,14 @@
 	  # external ACL lookup via a helper class defined by the
 	  # external_acl_type directive.
 
+	acl aclname user_cert attribute values...
+	  # match against attributes in a user SSL certificate
+	  # attribute is one of DN/C/O/CN/L/ST
+
+	acl aclname ca_cert attribute values...
+	  # match against attributes a users issuing CA SSL certificate
+	  # attribute is one of DN/C/O/CN/L/ST
+
 Examples:
 acl myexample dst_as 1241
 acl password proxy_auth REQUIRED
Index: squid/src/client_side.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v
retrieving revision 1.47.2.21
retrieving revision 1.47.2.21.2.1
diff -u -r1.47.2.21 -r1.47.2.21.2.1
--- squid/src/client_side.c	11 Nov 2002 22:16:28 -0000	1.47.2.21
+++ squid/src/client_side.c	29 Nov 2002 17:49:19 -0000	1.47.2.21.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.c,v 1.47.2.21 2002/11/11 22:16:28 squidadm Exp $
+ * $Id: client_side.c,v 1.47.2.21.2.1 2002/11/29 17:49:19 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -818,6 +818,9 @@
 	    packerClean(&p);
 	    memBufClean(&mb);
 	}
+#if USE_SSL
+	http->al.cache.ssluser = sslGetUserEmail(fd_table[conn->fd].ssl);
+#endif
 	accessLogLog(&http->al);
 	clientUpdateCounters(http);
 	clientdbUpdate(conn->peer.sin_addr, http->log_type, PROTO_HTTP, http->out.size);
@@ -3320,20 +3323,25 @@
 {
     ConnStateData *conn = data;
     X509 *client_cert;
+    SSL *ssl = fd_table[fd].ssl;
     int ret;
 
-    if ((ret = SSL_accept(fd_table[fd].ssl)) <= 0) {
-	if (BIO_sock_should_retry(ret)) {
+    if ((ret = SSL_accept(ssl)) <= 0) {
+	int ssl_error = SSL_get_error(ssl, ret);
+	switch (ssl_error) {
+	case SSL_ERROR_WANT_READ:
 	    commSetSelect(fd, COMM_SELECT_READ, clientNegotiateSSL, conn, 0);
 	    return;
+	case SSL_ERROR_WANT_WRITE:
+	    commSetSelect(fd, COMM_SELECT_WRITE, clientNegotiateSSL, conn, 0);
+	    return;
+	default:
+	    debug(81, 1) ("clientNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n",
+		fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret);
+	    comm_close(fd);
+	    return;
 	}
-	ret = ERR_get_error();
-	if (ret) {
-	    debug(83, 1) ("clientNegotiateSSL: Error negotiating SSL connection on FD %d: %s\n",
-		fd, ERR_error_string(ret, NULL));
-	}
-	comm_close(fd);
-	return;
+	/* NOTREACHED */
     }
     debug(83, 5) ("clientNegotiateSSL: FD %d negotiated cipher %s\n", fd,
 	SSL_get_cipher(fd_table[fd].ssl));
@@ -3613,7 +3621,7 @@
 	    continue;
 	CBDATA_INIT_TYPE(https_port_data);
 	https_port = cbdataAlloc(https_port_data);
-	https_port->sslContext = sslCreateContext(s->cert, s->key, s->version, s->cipher, s->options);
+	https_port->sslContext = s->sslContext;
 	comm_listen(fd);
 	commSetSelect(fd, COMM_SELECT_READ, httpsAccept, https_port, 0);
 	commSetDefer(fd, httpAcceptDefer, NULL);
Index: squid/src/enums.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/enums.h,v
retrieving revision 1.29.2.7
retrieving revision 1.29.2.7.2.1
diff -u -r1.29.2.7 -r1.29.2.7.2.1
--- squid/src/enums.h	23 Sep 2002 21:46:19 -0000	1.29.2.7
+++ squid/src/enums.h	29 Nov 2002 17:49:19 -0000	1.29.2.7.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.29.2.7 2002/09/23 21:46:19 squidadm Exp $
+ * $Id: enums.h,v 1.29.2.7.2.1 2002/11/29 17:49:19 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -136,6 +136,10 @@
     ACL_REP_MIME_TYPE,
     ACL_MAX_USER_IP,
     ACL_EXTERNAL,
+#if USE_SSL
+    ACL_USER_CERT,
+    ACL_CA_CERT,
+#endif
     ACL_ENUM_MAX
 } squid_acl;
 
@@ -246,6 +250,7 @@
 #if X_ACCELERATOR_VARY
     HDR_X_ACCELERATOR_VARY,
 #endif
+    HDR_FRONT_END_HTTPS,
     HDR_OTHER,
     HDR_ENUM_END
 } http_hdr_type;
@@ -616,6 +621,9 @@
     MEM_TLV,
     MEM_SWAP_LOG_DATA,
     MEM_CLIENT_REQ_BUF,
+#if USE_SSL
+    MEM_ACL_CERT_DATA,
+#endif
     MEM_MAX
 } mem_type;
 
Index: squid/src/external_acl.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/external_acl.c,v
retrieving revision 1.2.4.11
retrieving revision 1.2.4.11.2.1
diff -u -r1.2.4.11 -r1.2.4.11.2.1
--- squid/src/external_acl.c	10 Nov 2002 22:44:13 -0000	1.2.4.11
+++ squid/src/external_acl.c	29 Nov 2002 17:49:19 -0000	1.2.4.11.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: external_acl.c,v 1.2.4.11 2002/11/10 22:44:13 squidadm Exp $
+ * $Id: external_acl.c,v 1.2.4.11.2.1 2002/11/29 17:49:19 hno Exp $
  *
  * DEBUG: section 82    External ACL
  * AUTHOR: Henrik Nordstrom, MARA Systems AB
@@ -93,7 +93,8 @@
 
 struct _external_acl_format {
     enum {
-	EXT_ACL_LOGIN = 1,
+	EXT_ACL_UNKNOWN,
+	EXT_ACL_LOGIN,
 #if USE_IDENT
 	EXT_ACL_IDENT,
 #endif
@@ -105,7 +106,12 @@
 	EXT_ACL_HEADER,
 	EXT_ACL_HEADER_MEMBER,
 	EXT_ACL_HEADER_ID,
-	EXT_ACL_HEADER_ID_MEMBER
+	EXT_ACL_HEADER_ID_MEMBER,
+#if USE_SSL
+	EXT_ACL_USER_CERT,
+	EXT_ACL_CA_CERT,
+#endif
+	EXT_ACL_END
     } type;
     external_acl_format *next;
     char *header;
@@ -251,6 +257,15 @@
 	    format->type = EXT_ACL_PORT;
 	else if (strcmp(token, "%METHOD") == 0)
 	    format->type = EXT_ACL_METHOD;
+#if USE_SSL
+	else if (strncmp(token, "%USER_CERT_", 11)) {
+	    format->type = EXT_ACL_USER_CERT;
+	    format->header = xstrdup(token + 11);
+	} else if (strncmp(token, "%CA_CERT_", 11)) {
+	    format->type = EXT_ACL_USER_CERT;
+	    format->header = xstrdup(token + 11);
+	}
+#endif
 	else {
 	    self_destruct();
 	}
@@ -313,6 +328,16 @@
 		DUMP_EXT_ACL_TYPE(PROTO);
 		DUMP_EXT_ACL_TYPE(PORT);
 		DUMP_EXT_ACL_TYPE(METHOD);
+	    case EXT_ACL_USER_CERT:
+		storeAppendPrintf(sentry, " %%USER_CERT_%s", format->header);
+		break;
+	    case EXT_ACL_CA_CERT:
+		storeAppendPrintf(sentry, " %%USER_CERT_%s", format->header);
+		break;
+	    case EXT_ACL_UNKNOWN:
+	    case EXT_ACL_END:
+		fatal("unknown external_acl format error");
+		break;
 	    }
 	}
 	for (word = node->cmdline; word; word = word->next)
@@ -536,6 +561,26 @@
 	    sb = httpHeaderGetListMember(&request->header, format->header_id, format->member, format->separator);
 	    str = strBuf(sb);
 	    break;
+#if USE_SSL
+	case EXT_ACL_USER_CERT:
+	    if (cbdataValid(ch->conn)) {
+		SSL *ssl = fd_table[ch->conn->fd].ssl;
+		if (ssl)
+		    str = sslGetUserAttribute(ssl, format->header);
+	    }
+	    break;
+	case EXT_ACL_CA_CERT:
+	    if (cbdataValid(ch->conn)) {
+		SSL *ssl = fd_table[ch->conn->fd].ssl;
+		if (ssl)
+		    str = sslGetCAAttribute(ssl, format->header);
+	    }
+	    break;
+#endif
+	case EXT_ACL_UNKNOWN:
+	case EXT_ACL_END:
+	    fatal("unknown external_acl format error");
+	    break;
 	}
 	if (str)
 	    if (!*str)
Index: squid/src/forward.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/forward.c,v
retrieving revision 1.13.6.1
retrieving revision 1.13.6.1.8.1
diff -u -r1.13.6.1 -r1.13.6.1.8.1
--- squid/src/forward.c	1 Apr 2002 20:31:13 -0000	1.13.6.1
+++ squid/src/forward.c	29 Nov 2002 17:49:20 -0000	1.13.6.1.8.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: forward.c,v 1.13.6.1 2002/04/01 20:31:13 squidadm Exp $
+ * $Id: forward.c,v 1.13.6.1.8.1 2002/11/29 17:49:20 hno Exp $
  *
  * DEBUG: section 17    Request Forwarding
  * AUTHOR: Duane Wessels
@@ -177,16 +177,106 @@
     }
 }
 
+#if USE_SSL
+static void
+fwdNegotiateSSL(int fd, void *data)
+{
+    FwdState *fwdState = data;
+    FwdServer *fs = fwdState->servers;
+    SSL *ssl = fd_table[fd].ssl;
+    int ret;
+    ErrorState *err;
+    request_t *request = fwdState->request;
+    if ((ret = SSL_connect(ssl)) <= 0) {
+	int ssl_error = SSL_get_error(ssl, ret);
+	switch (ssl_error) {
+	case SSL_ERROR_WANT_READ:
+	    commSetSelect(fd, COMM_SELECT_READ, fwdNegotiateSSL, fwdState, 0);
+	    return;
+	case SSL_ERROR_WANT_WRITE:
+	    commSetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSL, fwdState, 0);
+	    return;
+	default:
+	    debug(81, 1) ("fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret);
+	    err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
+#ifdef EPROTO
+	    err->xerrno = EPROTO;
+#else
+	    err->xerrno = EACCES;
+#endif
+	    if (fs->peer) {
+		err->host = xstrdup(fs->peer->host);
+		err->port = fs->peer->http_port;
+	    } else {
+		err->host = xstrdup(request->host);
+		err->port = request->port;
+	    }
+	    err->request = requestLink(request);
+	    fwdFail(fwdState, err);
+	    if (fs->peer) {
+		peerConnectFailed(fs->peer);
+		fs->peer->stats.conn_open--;
+	    }
+	    comm_close(fd);
+	    return;
+	}
+    }
+    fwdDispatch(fwdState);
+}
+
+static void
+fwdInitiateSSL(FwdState * fwdState)
+{
+    FwdServer *fs = fwdState->servers;
+    int fd = fwdState->server_fd;
+    SSL *ssl;
+    SSL_CTX *sslContext = NULL;
+    peer *peer = fs->peer;
+    if (peer) {
+	assert(peer->use_ssl);
+	sslContext = peer->sslContext;
+    } else {
+	sslContext = Config.ssl_client.sslContext;
+    }
+    assert(sslContext);
+    if ((ssl = SSL_new(sslContext)) == NULL) {
+	ErrorState *err;
+	debug(83, 1) ("fwdInitiateSSL: Error allocating handle: %s\n",
+	    ERR_error_string(ERR_get_error(), NULL));
+	err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
+	err->xerrno = errno;
+	err->request = requestLink(fwdState->request);
+	fwdFail(fwdState, err);
+	fwdStateFree(fwdState);
+	return;
+    }
+    SSL_set_fd(ssl, fd);
+    if (peer) {
+	if (peer->ssldomain)
+	    SSL_set_ex_data(ssl, ssl_ex_index_server, peer->ssldomain);
+#if NOT_YET
+	else if (peer->name)
+	    SSL_set_ex_data(ssl, ssl_ex_index_server, peer->name);
+#endif
+	else
+	    SSL_set_ex_data(ssl, ssl_ex_index_server, peer->host);
+    } else {
+	SSL_set_ex_data(ssl, ssl_ex_index_server, fwdState->request->host);
+    }
+    fd_table[fd].ssl = ssl;
+    fd_table[fd].read_method = &ssl_read_method;
+    fd_table[fd].write_method = &ssl_write_method;
+    fwdNegotiateSSL(fd, fwdState);
+}
+#endif
+
 static void
 fwdConnectDone(int server_fd, int status, void *data)
 {
     FwdState *fwdState = data;
-    static FwdState *current = NULL;
     FwdServer *fs = fwdState->servers;
     ErrorState *err;
     request_t *request = fwdState->request;
-    assert(current != fwdState);
-    current = fwdState;
     assert(fwdState->server_fd == server_fd);
     if (status == COMM_ERR_DNS) {
 	/*
@@ -226,18 +316,16 @@
     } else {
 	debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(fwdState->entry));
 	if (fs->peer)
-	    hierarchyNote(&fwdState->request->hier, fs->code, fs->peer->host);
-	else if (Config.onoff.log_ip_on_direct)
-	    hierarchyNote(&fwdState->request->hier, fs->code, fd_table[server_fd].ipaddr);
-	else
-	    hierarchyNote(&fwdState->request->hier, fs->code, request->host);
-	fd_note(server_fd, storeUrl(fwdState->entry));
-	fd_table[server_fd].uses++;
-	if (fs->peer)
 	    peerConnectSucceded(fs->peer);
+#if USE_SSL
+	if ((fs->peer && fs->peer->use_ssl) ||
+	    (!fs->peer && request->protocol == PROTO_HTTPS)) {
+	    fwdInitiateSSL(fwdState);
+	    return;
+	}
+#endif
 	fwdDispatch(fwdState);
     }
-    current = NULL;
 }
 
 static void
@@ -354,7 +442,7 @@
 	fwdState->server_fd = fd;
 	fwdState->n_tries++;
 	comm_add_close_handler(fd, fwdServerClosed, fwdState);
-	fwdConnectDone(fd, COMM_OK, fwdState);
+	fwdDispatch(fwdState);
 	return;
     }
 #if URL_CHECKSUM_DEBUG
@@ -431,21 +519,31 @@
     request_t *request = fwdState->request;
     StoreEntry *entry = fwdState->entry;
     ErrorState *err;
+    FwdServer *fs = fwdState->servers;
+    int server_fd = fwdState->server_fd;
     debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n",
 	fwdState->client_fd,
 	RequestMethodStr[request->method],
 	storeUrl(entry));
-    /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */
-    assert(entry->ping_status != PING_WAITING);
-    assert(entry->lock_count);
-    EBIT_SET(entry->flags, ENTRY_DISPATCHED);
-    netdbPingSite(request->host);
     /*
      * Assert that server_fd is set.  This is to guarantee that fwdState
      * is attached to something and will be deallocated when server_fd
      * is closed.
      */
-    assert(fwdState->server_fd > -1);
+    assert(server_fd > -1);
+    if (fs->peer)
+	hierarchyNote(&fwdState->request->hier, fs->code, fs->peer->host);
+    else if (Config.onoff.log_ip_on_direct)
+	hierarchyNote(&fwdState->request->hier, fs->code, fd_table[server_fd].ipaddr);
+    else
+	hierarchyNote(&fwdState->request->hier, fs->code, request->host);
+    fd_note(server_fd, storeUrl(fwdState->entry));
+    fd_table[server_fd].uses++;
+    /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */
+    assert(entry->ping_status != PING_WAITING);
+    assert(entry->lock_count);
+    EBIT_SET(entry->flags, ENTRY_DISPATCHED);
+    netdbPingSite(request->host);
     if (fwdState->servers && (p = fwdState->servers->peer)) {
 	p->stats.fetches++;
 	fwdState->request->peer_login = p->login;
@@ -453,6 +551,11 @@
     } else {
 	fwdState->request->peer_login = NULL;
 	switch (request->protocol) {
+#if USE_SSL
+	case PROTO_HTTPS:
+	    httpStart(fwdState);
+	    break;
+#endif
 	case PROTO_HTTP:
 	    httpStart(fwdState);
 	    break;
Index: squid/src/globals.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/globals.h,v
retrieving revision 1.14.6.2
retrieving revision 1.14.6.2.2.1
diff -u -r1.14.6.2 -r1.14.6.2.2.1
--- squid/src/globals.h	15 Jul 2002 00:44:14 -0000	1.14.6.2
+++ squid/src/globals.h	29 Nov 2002 17:49:20 -0000	1.14.6.2.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: globals.h,v 1.14.6.2 2002/07/15 00:44:14 squidadm Exp $
+ * $Id: globals.h,v 1.14.6.2.2.1 2002/11/29 17:49:20 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -164,4 +164,7 @@
 extern char *WIN32_OS_string;	/* NULL */
 #endif
 
+extern int ssl_ex_index_server;	/* -1 */
+extern int ssl_ctx_ex_index_dont_verify_domain; /* -1 */
+
 #endif /* SQUID_GLOBALS_H */
Index: squid/src/http.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/http.c,v
retrieving revision 1.17.6.3
retrieving revision 1.17.6.3.2.1
diff -u -r1.17.6.3 -r1.17.6.3.2.1
--- squid/src/http.c	7 Sep 2002 23:16:47 -0000	1.17.6.3
+++ squid/src/http.c	29 Nov 2002 17:49:20 -0000	1.17.6.3.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.c,v 1.17.6.3 2002/09/07 23:16:47 squidadm Exp $
+ * $Id: http.c,v 1.17.6.3.2.1 2002/11/29 17:49:20 hno Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -832,6 +832,10 @@
 	case HDR_CACHE_CONTROL:
 	    /* append these after the loop if needed */
 	    break;
+	case HDR_FRONT_END_HTTPS:
+	    if (!flags.front_end_https)
+		httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
+	    break;
 	default:
 	    /* pass on all other header fields */
 	    httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
@@ -912,6 +916,12 @@
 	    httpHeaderPutStr(hdr_out, HDR_CONNECTION, "keep-alive");
 	}
     }
+    /* append Front-End-Https */
+    if (flags.front_end_https) {
+	if (flags.front_end_https == 1 || request->protocol == PROTO_HTTPS)
+	    httpHeaderPutStr(hdr_out, HDR_FRONT_END_HTTPS, "On");
+    }
+
     /* Now mangle the headers. */
     httpHdrMangleList(hdr_out, request);
     stringClean(&strConnection);
@@ -985,10 +995,12 @@
 	httpState->flags.keepalive = 1;
     else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50)
 	httpState->flags.keepalive = 1;
-    if (httpState->peer)
+    if (httpState->peer) {
 	if (neighborType(httpState->peer, httpState->request) == PEER_SIBLING &&
 	    !httpState->peer->options.allow_miss)
 	    httpState->flags.only_if_cached = 1;
+	httpState->flags.front_end_https = httpState->peer->front_end_https;
+    }
     memBufDefInit(&mb);
     httpBuildRequestPrefix(req,
 	httpState->orig_request,
@@ -1019,7 +1031,7 @@
 	httpState->peer = fwd->servers->peer;	/* might be NULL */
     if (httpState->peer) {
 	proxy_req = requestCreate(orig_req->method,
-	    PROTO_NONE, storeUrl(httpState->entry));
+	    orig_req->protocol, storeUrl(httpState->entry));
 	xstrncpy(proxy_req->host, httpState->peer->host, SQUIDHOSTNAMELEN);
 	proxy_req->port = httpState->peer->http_port;
 	proxy_req->flags = orig_req->flags;
Index: squid/src/mem.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/mem.c,v
retrieving revision 1.13
retrieving revision 1.13.24.1
diff -u -r1.13 -r1.13.24.1
--- squid/src/mem.c	7 Sep 2001 23:55:49 -0000	1.13
+++ squid/src/mem.c	29 Nov 2002 17:49:20 -0000	1.13.24.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mem.c,v 1.13 2001/09/07 23:55:49 squidadm Exp $
+ * $Id: mem.c,v 1.13.24.1 2002/11/29 17:49:20 hno Exp $
  *
  * DEBUG: section 13    High Level Memory Pool Management
  * AUTHOR: Harvest Derived
@@ -199,6 +199,9 @@
     memDataInit(MEM_ACL_IP_DATA, "acl_ip_data", sizeof(acl_ip_data), 0);
     memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0);
     memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0);
+#if USE_SSL
+    memDataInit(MEM_ACL_CERT_DATA, "acl_cert_data", sizeof(acl_cert_data), 0);
+#endif
     memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0);
     memDataInit(MEM_AUTH_USER_T, "auth_user_t",
 	sizeof(auth_user_t), 0);
Index: squid/src/ssl_support.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ssl_support.c,v
retrieving revision 1.6.6.1
retrieving revision 1.6.6.1.2.1
diff -u -r1.6.6.1 -r1.6.6.1.2.1
--- squid/src/ssl_support.c	21 Jul 2002 01:07:44 -0000	1.6.6.1
+++ squid/src/ssl_support.c	29 Nov 2002 17:49:20 -0000	1.6.6.1.2.1
@@ -55,12 +55,43 @@
 ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
 {
     char buffer[256];
+    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+    SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
+    const char *server = SSL_get_ex_data(ssl, ssl_ex_index_server);
+    void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
+    X509 *peer_cert = ctx->cert;
 
-    X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buffer,
+    X509_NAME_oneline(X509_get_subject_name(peer_cert), buffer,
 	sizeof(buffer));
-    if (ok)
-	debug(83, 5) ("SSL Certificate OK: %s\n", buffer);
-    else {
+
+    if (ok) {
+	debug(83, 5) ("SSL Certificate signature OK: %s\n", buffer);
+	if (server) {
+	    int i;
+	    int found = 0;
+	    char cn[1024];
+	    X509_NAME *name = X509_get_subject_name(peer_cert);
+	    debug(83, 3) ("Verifying server domain %s to certificate dn %s\n",
+		server, buffer);
+	    for (i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
+		ASN1_STRING *data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
+		if (data->length > sizeof(cn) - 1)
+		    continue;
+		memcpy(cn, data->data, data->length);
+		cn[data->length] = '\0';
+		debug(83, 4) ("Verifying server domain %s to certificate cn %s\n",
+		    server, cn);
+		if (matchDomainName(server, cn[0] == '*' ? cn + 1 : cn) == 0) {
+		    found = 1;
+		    break;
+		}
+	    }
+	    if (!found) {
+		debug(83, 2) ("ERROR: Certificate %s does not match domainname %s\n", buffer, server);
+		ok = 0;
+	    }
+	}
+    } else {
 	switch (ctx->error) {
 	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
 	    debug(83, 5) ("SSL Certficate error: CA not known: %s\n", buffer);
@@ -78,11 +109,13 @@
 	    debug(83, 5) ("SSL Certificate has invalid \'not after\' field: %s\n", buffer);
 	    break;
 	default:
-	    debug(83, 5) ("SSL unknown certificate error %d in %s\n",
+	    debug(83, 1) ("SSL unknown certificate error %d in %s\n",
 		ctx->error, buffer);
 	    break;
 	}
     }
+    if (!dont_verify_domain && server) {
+    }
     return ok;
 }
 
@@ -225,22 +258,88 @@
     return op;
 }
 
-SSL_CTX *
-sslCreateContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options)
+#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)
+
+static 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
+	    fatalf("Unknown ssl flag '%s'", flag);
+	flag = strtok(NULL, ":,");
+    }
+    safe_free(tmp);
+    return fl;
+}
+
+
+static void
+ssl_initialize(void)
 {
-    int ssl_error;
-    SSL_METHOD *method;
-    SSL_CTX *sslContext;
     static int ssl_initialized = 0;
     if (!ssl_initialized) {
 	ssl_initialized = 1;
 	SSL_load_error_strings();
 	SSLeay_add_ssl_algorithms();
+#ifdef HAVE_OPENSSL_ENGINE_H
+	if (Config.SSL.ssl_engine) {
+	    ENGINE *e;
+	    if (!(e = ENGINE_by_id(Config.SSL.ssl_engine))) {
+		fatalf("Unable to find SSL engine '%s'\n", Config.SSL.ssl_engine);
+	    }
+	    if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+		int ssl_error = ERR_get_error();
+		fatalf("Failed to initialise SSL engine: %s\n",
+		    ERR_error_string(ssl_error, NULL));
+	    }
+	}
+#else
+	if (Config.SSL.ssl_engine) {
+	    fatalf("Your OpenSSL has no SSL engine support\n");
+	}
+#endif
     }
+    ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL);
+    ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
+
+}
+
+SSL_CTX *
+sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath)
+{
+    int ssl_error;
+    SSL_METHOD *method;
+    SSL_CTX *sslContext;
+    long fl = ssl_parse_flags(flags);
+
+    ssl_initialize();
+
     if (!keyfile)
 	keyfile = certfile;
     if (!certfile)
 	certfile = keyfile;
+    if (!CAfile)
+	CAfile = clientCA;
 
     debug(83, 1) ("Initialising SSL.\n");
     switch (version) {
@@ -275,41 +374,168 @@
 	debug(83, 5) ("Using chiper suite %s.\n", cipher);
 	if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
 	    ssl_error = ERR_get_error();
-	    fatalf("Failed to set SSL cipher suite: %s\n",
-		ERR_error_string(ssl_error, NULL));
+	    fatalf("Failed to set SSL cipher suite '%s': %s\n",
+		cipher, ERR_error_string(ssl_error, NULL));
 	}
     }
     debug(83, 1) ("Using certificate in %s\n", certfile);
-    if (!SSL_CTX_use_certificate_file(sslContext, certfile, SSL_FILETYPE_PEM)) {
+    if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
 	ssl_error = ERR_get_error();
-	fatalf("Failed to acquire SSL certificate: %s\n",
-	    ERR_error_string(ssl_error, NULL));
+	debug(83, 1) ("Failed to acquire SSL certificate '%s': %s\n",
+	    certfile, ERR_error_string(ssl_error, NULL));
+	goto error;
     }
     debug(83, 1) ("Using private key in %s\n", keyfile);
     if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
 	ssl_error = ERR_get_error();
-	fatalf("Failed to acquire SSL private key: %s\n",
-	    ERR_error_string(ssl_error, NULL));
+	debug(83, 1) ("Failed to acquire SSL private key '%s': %s\n",
+	    keyfile, ERR_error_string(ssl_error, NULL));
+	goto error;
     }
     debug(83, 5) ("Comparing private and public SSL keys.\n");
-    if (!SSL_CTX_check_private_key(sslContext))
-	fatal("SSL private key does not match public key: %s\n");
+    if (!SSL_CTX_check_private_key(sslContext)) {
+	ssl_error = ERR_get_error();
+	debug(83, 0) ("SSL private key '%s' does not match public key '%s': %s\n",
+	    certfile, keyfile, ERR_error_string(ssl_error, NULL));
+	goto error;
+    }
+    debug(83, 9) ("Setting RSA key generation callback.\n");
+    SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
 
+    debug(83, 9) ("Setting CA certificate locations.\n");
+    if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
+	ssl_error = ERR_get_error();
+	debug(83, 1) ("Error error setting CA certificate locations: %s\n",
+	    ERR_error_string(ssl_error, NULL));
+	debug(83, 1) ("continuing anyway...\n");
+    }
+    if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
+	!SSL_CTX_set_default_verify_paths(sslContext)) {
+	ssl_error = ERR_get_error();
+	debug(83, 1) ("Error error setting default CA certificate location: %s\n",
+	    ERR_error_string(ssl_error, NULL));
+	debug(83, 1) ("continuing anyway...\n");
+    }
+    if (clientCA) {
+	debug(83, 9) ("Set client certifying authority list.\n");
+	SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(clientCA));
+	if (fl & SSL_FLAG_DELAYED_AUTH) {
+	    debug(83, 9) ("Not requesting client certificates until acl processing requires one\n");
+	    SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
+	} else {
+	    debug(83, 9) ("Requiring client certificates.\n");
+	    SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
+	}
+    } else {
+	debug(83, 9) ("Not requiring any client certificates\n");
+	SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
+    }
+
+    if (fl & SSL_FLAG_DONT_VERIFY_DOMAIN)
+	SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
+    return sslContext;
+  error:
+    SSL_CTX_free(sslContext);
+    return NULL;
+}
+
+SSL_CTX *
+sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath)
+{
+    int ssl_error;
+    SSL_METHOD *method;
+    SSL_CTX *sslContext;
+    long fl = ssl_parse_flags(flags);
+
+    ssl_initialize();
+
+    if (!keyfile)
+	keyfile = certfile;
+    if (!certfile)
+	certfile = keyfile;
+
+    debug(83, 1) ("Initialising SSL.\n");
+    switch (version) {
+    case 2:
+	debug(83, 5) ("Using SSLv2.\n");
+	method = SSLv2_client_method();
+	break;
+    case 3:
+	debug(83, 5) ("Using SSLv3.\n");
+	method = SSLv3_client_method();
+	break;
+    case 4:
+	debug(83, 5) ("Using TLSv1.\n");
+	method = TLSv1_client_method();
+	break;
+    case 1:
+    default:
+	debug(83, 5) ("Using SSLv2/SSLv3.\n");
+	method = SSLv23_client_method();
+	break;
+    }
+
+    sslContext = SSL_CTX_new(method);
+    if (sslContext == NULL) {
+	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));
+
+    if (cipher) {
+	debug(83, 5) ("Using chiper suite %s.\n", cipher);
+	if (!SSL_CTX_set_cipher_list(sslContext, cipher)) {
+	    ssl_error = ERR_get_error();
+	    fatalf("Failed to set SSL cipher suite '%s': %s\n",
+		cipher, ERR_error_string(ssl_error, NULL));
+	}
+    }
+    if (certfile) {
+	debug(83, 1) ("Using certificate in %s\n", certfile);
+	if (!SSL_CTX_use_certificate_chain_file(sslContext, certfile)) {
+	    ssl_error = ERR_get_error();
+	    fatalf("Failed to acquire SSL certificate '%s': %s\n",
+		certfile, ERR_error_string(ssl_error, NULL));
+	}
+	debug(83, 1) ("Using private key in %s\n", keyfile);
+	if (!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)) {
+	    ssl_error = ERR_get_error();
+	    fatalf("Failed to acquire SSL private key '%s': %s\n",
+		keyfile, ERR_error_string(ssl_error, NULL));
+	}
+	debug(83, 5) ("Comparing private and public SSL keys.\n");
+	if (!SSL_CTX_check_private_key(sslContext)) {
+	    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));
+	}
+    }
     debug(83, 9) ("Setting RSA key generation callback.\n");
     SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
 
-    debug(83, 9) ("Setting certificate verification callback.\n");
-    SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, ssl_verify_cb);
+    if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
+	debug(83, 1) ("NOTICE: Peer certificates are not verified for validity!\n");
+	SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
+    } else {
+	debug(83, 9) ("Setting certificate verification callback.\n");
+	SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
+    }
 
-    debug(83, 9) ("Setting default CA certificate location.\n");
-    if (!SSL_CTX_set_default_verify_paths(sslContext)) {
+    debug(83, 9) ("Setting CA certificate locations.\n");
+    if ((!SSL_CTX_load_verify_locations(sslContext, CAfile, CApath))) {
+	ssl_error = ERR_get_error();
+	debug(83, 1) ("Error error setting CA certificate locations: %s\n",
+	    ERR_error_string(ssl_error, NULL));
+	debug(83, 1) ("continuing anyway...\n");
+    }
+    if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
+	!SSL_CTX_set_default_verify_paths(sslContext)) {
 	ssl_error = ERR_get_error();
 	debug(83, 1) ("Error error setting default CA certificate location: %s\n",
 	    ERR_error_string(ssl_error, NULL));
 	debug(83, 1) ("continuing anyway...\n");
     }
-    debug(83, 9) ("Set client certifying authority list.\n");
-    SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile));
     return sslContext;
 }
 
@@ -354,3 +580,91 @@
     }
     SSL_shutdown(ssl);
 }
+
+static const char *
+ssl_get_attribute(X509_NAME * name, const char *attribute_name)
+{
+    static char buffer[1024];
+    int nid;
+
+    buffer[0] = '\0';
+
+    if (strcmp(attribute_name, "DN") == 0) {
+	X509_NAME_oneline(name, buffer, sizeof(buffer));
+	goto done;
+    }
+    nid = OBJ_txt2nid((char *) attribute_name);
+    if (nid == 0) {
+	debug(83, 1) ("WARNING: Unknown SSL attribute name '%s'\n", attribute_name);
+	return NULL;
+    }
+    X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
+  done:
+    return *buffer ? buffer : NULL;
+}
+
+const char *
+sslGetUserAttribute(SSL * ssl, const char *attribute_name)
+{
+    X509 *cert;
+    X509_NAME *name;
+
+    if (!ssl)
+	return NULL;
+
+    cert = SSL_get_peer_certificate(ssl);
+    if (!cert)
+	return NULL;
+
+    name = X509_get_issuer_name(cert);
+
+    return ssl_get_attribute(name, attribute_name);
+}
+
+const char *
+sslGetCAAttribute(SSL * ssl, const char *attribute_name)
+{
+    X509 *cert;
+    X509_NAME *name;
+
+    if (!ssl)
+	return NULL;
+
+    cert = SSL_get_peer_certificate(ssl);
+    if (!cert)
+	return NULL;
+
+    name = X509_get_subject_name(cert);
+
+    return ssl_get_attribute(name, attribute_name);
+}
+
+#if 0
+char *
+sslGetUserEmail(SSL * ssl)
+{
+    X509 *cert;
+    X509_NAME *name;
+
+    static char email[128];
+
+    if (!ssl)
+	return NULL;
+    cert = SSL_get_peer_certificate(ssl);
+    if (!cert)
+	return NULL;
+
+    name = X509_get_subject_name(cert);
+
+    if (X509_NAME_get_text_by_NID(name, NID_pkcs9_emailAddress, email, sizeof(email)) > 0)
+	return email;
+    else
+	return NULL;
+}
+#endif
+
+const char *
+sslGetUserEmail(SSL * ssl)
+{
+    return sslGetUserAttribute(ssl, "Email");
+}
Index: squid/src/ssl_support.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ssl_support.h,v
retrieving revision 1.5
retrieving revision 1.5.44.1
diff -u -r1.5 -r1.5.44.1
--- squid/src/ssl_support.h	19 Oct 2001 22:48:48 -0000	1.5
+++ squid/src/ssl_support.h	29 Nov 2002 17:49:20 -0000	1.5.44.1
@@ -42,10 +42,18 @@
 #if HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
 #endif
+#if HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
 
-SSL_CTX *sslCreateContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options);
+SSL_CTX *sslCreateServerContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *clientCA, const char *CAfile, const char *CApath);
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, int version, const char *cipher, const char *options, const char *flags, const char *CAfile, const char *CApath);
 int ssl_read_method(int, char *, int);
 int ssl_write_method(int, const char *, int);
 void ssl_shutdown_method(int);
 
+const char *sslGetUserEmail(SSL *ssl);
+const char *sslGetUserAttribute(SSL *ssl, const char *attribute);
+const char *sslGetCAAttribute(SSL *ssl, const char *attribute);
+
 #endif /* SQUID_SSL_SUPPORT_H */
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.48.2.8
retrieving revision 1.48.2.8.2.1
diff -u -r1.48.2.8 -r1.48.2.8.2.1
--- squid/src/structs.h	10 Nov 2002 22:44:13 -0000	1.48.2.8
+++ squid/src/structs.h	29 Nov 2002 17:49:20 -0000	1.48.2.8.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.48.2.8 2002/11/10 22:44:13 squidadm Exp $
+ * $Id: structs.h,v 1.48.2.8.2.1 2002/11/29 17:49:20 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -48,6 +48,13 @@
     dlink_node *tail;
 };
 
+#if USE_SSL
+struct _acl_cert_data {
+    splayNode *values;
+    char *attribute;
+};
+#endif
+
 struct _acl_user_data {
     splayNode *names;
     struct {
@@ -339,8 +346,12 @@
     int version;
     char *cipher;
     char *options;
+    char *clientca;
+    char *cafile;
+    char *capath;
+    char *sslflags;
+    SSL_CTX *sslContext;
 };
-
 #endif
 
 #if DELAY_POOLS
@@ -680,6 +691,7 @@
 #if USE_SSL
     struct {
 	int unclean_shutdown;
+	char *ssl_engine;
     } SSL;
 #endif
     wordlist *ext_methods;
@@ -691,6 +703,19 @@
     char *store_dir_select_algorithm;
     int sleep_after_fork;	/* microseconds */
     external_acl *externalAclHelperList;
+#if USE_SSL
+    struct {
+	char *cert;
+	char *key;
+	int version;
+	char *options;
+	char *cipher;
+	char *cafile;
+	char *capath;
+	char *flags;
+	SSL_CTX *sslContext;
+    } ssl_client;
+#endif
 };
 
 struct _SquidConfig2 {
@@ -966,6 +991,7 @@
     unsigned int proxying:1;
     unsigned int keepalive:1;
     unsigned int only_if_cached:1;
+    unsigned int front_end_https:2;
 };
 
 struct _HttpStateData {
@@ -1037,6 +1063,9 @@
 	int msec;
 	const char *rfc931;
 	const char *authuser;
+#if USE_SSL
+	const char *ssluser;
+#endif
     } cache;
     struct {
 	char *request;
@@ -1304,6 +1333,20 @@
     char *login;		/* Proxy authorization */
     time_t connect_timeout;
     int max_conn;
+#if USE_SSL
+    int use_ssl;
+    char *sslcert;
+    char *sslkey;
+    int sslversion;
+    char *ssloptions;
+    char *sslcipher;
+    char *sslcafile;
+    char *sslcapath;
+    char *sslflags;
+    char *ssldomain;
+    SSL_CTX *sslContext;
+#endif
+    int front_end_https;
 };
 
 struct _net_db_name {
Index: squid/src/typedefs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v
retrieving revision 1.25.6.1
retrieving revision 1.25.6.1.2.1
diff -u -r1.25.6.1 -r1.25.6.1.2.1
--- squid/src/typedefs.h	23 Jun 2002 13:56:26 -0000	1.25.6.1
+++ squid/src/typedefs.h	29 Nov 2002 17:49:21 -0000	1.25.6.1.2.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.25.6.1 2002/06/23 13:56:26 squidadm Exp $
+ * $Id: typedefs.h,v 1.25.6.1.2.1 2002/11/29 17:49:21 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -68,6 +68,9 @@
 typedef struct _acl_proxy_auth_match_cache acl_proxy_auth_match_cache;
 typedef struct _authscheme_entry authscheme_entry_t;
 typedef struct _authScheme authScheme;
+#if USE_SSL
+typedef struct _acl_cert_data acl_cert_data;
+#endif
 typedef struct _acl_user_data acl_user_data;
 typedef struct _acl_user_ip_data acl_user_ip_data;
 typedef struct _acl_arp_data acl_arp_data;
