This patch makes some changes to the config validation of http_port lines
and documentation of http_port.

It alters documentation to call accel, tproxy, intercept, and sslbump
options "mode flags" since they determine the overall code paths which
traffic received is handled by.

The http_port syntax docs are updated to show that mode flags must go
first before any options. This is not strictly true, since the mode flag
only must go before mode-specific options. But its clearer to explain the
syntax docs like this. Both mode and options remain completely optional
(except that some options require certain modes as before).

The parser is updated to validate that only one of the mode flags is used.
Attempts to mix them will result in a fatal error. Attempts to use any of
the mode-specific options without the correct mode being enabled first will
result in a fatal message.

As a side-effect of this the implicit enabling of accel on several of its
options has been dropped. Explicit use as mode flag is preferred (and
required) instead for clear reading of the config.

Implications for older configs are that the http_port may fail a parse
check until some basic re-ordering of options or splitting of http_port
into multiple entries is done. Hopefully the messages omitted on failure
are clear enough for people to follow easily.

Slightly related future work;
  adding a "ssl" mode flag to http_port and merging the https_port
directive as just another mode of http_port.

Amos
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2010-04-17 02:29:04 +0000
+++ src/cache_cf.cc	2010-04-21 01:55:12 +0000
@@ -3001,37 +3001,97 @@
 static void
 parse_http_port_option(http_port_list * s, char *token)
 {
-    if (strncmp(token, "defaultsite=", 12) == 0) {
+    /* modes first */
+
+    if (strcmp(token, "accel") == 0) {
+        if (s->intercepted || s->spoof_client_ip) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Accelerator mode requires its own port. It cannot be shared with other modes.");
+            self_destruct();
+        }
+        s->accel = 1;
+    } else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
+        if (s->accel || s->spoof_client_ip) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Intercept mode requires its own interception port. It cannot be shared with other modes.");
+            self_destruct();
+        }
+        s->intercepted = 1;
+        Ip::Interceptor.StartInterception();
+        /* Log information regarding the port modes under interception. */
+        debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
+        debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)");
+
+#if USE_IPV6
+        /* INET6: until transparent REDIRECT works on IPv6 SOCKET, force wildcard to IPv4 */
+        debugs(3, DBG_IMPORTANT, "Disabling IPv6 on port " << s->s << " (interception enabled)");
+        if ( !s->s.SetIPv4() ) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: IPv6 addresses cannot be transparent (protocol does not provide NAT)" << s->s );
+            self_destruct();
+        }
+#endif
+    } else if (strcmp(token, "tproxy") == 0) {
+        if (s->intercepted || s->accel) {
+            debugs(3,DBG_CRITICAL, "FATAL: http(s)_port: TPROXY option requires its own interception port. It cannot be shared with other modes.");
+            self_destruct();
+        }
+        s->spoof_client_ip = 1;
+        Ip::Interceptor.StartTransparency();
+        /* Log information regarding the port modes under transparency. */
+        debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s);
+        debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)");
+
+        if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work.");
+            self_destruct();
+        }
+
+    } else if (strncmp(token, "defaultsite=", 12) == 0) {
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: defaultsite option requires Acceleration mode flag.");
+            self_destruct();
+        }
         safe_free(s->defaultsite);
         s->defaultsite = xstrdup(token + 12);
-        s->accel = 1;
-    } else if (strncmp(token, "name=", 5) == 0) {
-        safe_free(s->name);
-        s->name = xstrdup(token + 5);
     } else if (strcmp(token, "vhost") == 0) {
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vhost option requires Acceleration mode flag.");
+            self_destruct();
+        }
         s->vhost = 1;
-        s->accel = 1;
     } else if (strcmp(token, "vport") == 0) {
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
+            self_destruct();
+        }
         s->vport = -1;
-        s->accel = 1;
     } else if (strncmp(token, "vport=", 6) == 0) {
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
+            self_destruct();
+        }
         s->vport = xatos(token + 6);
-        s->accel = 1;
     } else if (strncmp(token, "protocol=", 9) == 0) {
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: protocol option requires Acceleration mode flag.");
+            self_destruct();
+        }
         s->protocol = xstrdup(token + 9);
-        s->accel = 1;
-    } else if (strcmp(token, "accel") == 0) {
-        s->accel = 1;
     } else if (strcmp(token, "allow-direct") == 0) {
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
+            self_destruct();
+        }
         s->allow_direct = 1;
     } else if (strcmp(token, "ignore-cc") == 0) {
+#if !HTTP_VIOLATIONS
+        if (!s->accel) {
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: ignore-cc option requires Scceleration mode flag.");
+            self_destruct();
+        }
+#endif
         s->ignore_cc = 1;
-#if !HTTP_VIOLATIONS
-        if (!s->accel) {
-            debugs(3, DBG_CRITICAL, "FATAL: ignore-cc is only valid in accelerator mode");
-            self_destruct();
-        }
-#endif
+    } else if (strncmp(token, "name=", 5) == 0) {
+        safe_free(s->name);
+        s->name = xstrdup(token + 5);
     } else if (strcmp(token, "no-connection-auth") == 0) {
         s->connection_auth_disabled = true;
     } else if (strcmp(token, "connection-auth=off") == 0) {
@@ -3049,42 +3109,10 @@
             s->disable_pmtu_discovery = DISABLE_PMTU_ALWAYS;
         else
             self_destruct();
-
-    } else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
-        s->intercepted = 1;
-        Ip::Interceptor.StartInterception();
-        /* Log information regarding the port modes under interception. */
-        debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
-        debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)");
-
-#if USE_IPV6
-        /* INET6: until transparent REDIRECT works on IPv6 SOCKET, force wildcard to IPv4 */
-        debugs(3, DBG_IMPORTANT, "Disabling IPv6 on port " << s->s << " (interception enabled)");
-        if ( !s->s.SetIPv4() ) {
-            debugs(3, DBG_CRITICAL, "http(s)_port: IPv6 addresses cannot be transparent (protocol does not provide NAT)" << s->s );
-            self_destruct();
-        }
-#endif
-    } else if (strcmp(token, "tproxy") == 0) {
-        if (s->intercepted || s->accel) {
-            debugs(3,DBG_CRITICAL, "http(s)_port: TPROXY option requires its own interception port. It cannot be shared.");
-            self_destruct();
-        }
-        s->spoof_client_ip = 1;
-        Ip::Interceptor.StartTransparency();
-        /* Log information regarding the port modes under transparency. */
-        debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s);
-        debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)");
-
-        if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
-            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work.");
-            self_destruct();
-        }
-
     } else if (strcmp(token, "ipv4") == 0) {
 #if USE_IPV6
         if ( !s->s.SetIPv4() ) {
-            debugs(3, 0, "http(s)_port: IPv6 addresses cannot be used a IPv4-Only." << s->s );
+            debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: IPv6 addresses cannot be used a IPv4-Only." << s->s );
             self_destruct();
         }
 #endif
@@ -3106,6 +3134,10 @@
             t = strchr(t, ',');
         }
 #if USE_SSL
+    } else if (strcmp(token, "sslBump") == 0) {
+        s->sslBump = 1; // accelerated when bumped, otherwise not
+    } else if (strcmp(token, "ssl") == 0) {
+        s->ssl = 1;
     } else if (strncmp(token, "cert=", 5) == 0) {
         safe_free(s->cert);
         s->cert = xstrdup(token + 5);
@@ -3114,7 +3146,6 @@
         s->key = xstrdup(token + 4);
     } else if (strncmp(token, "version=", 8) == 0) {
         s->version = xatoi(token + 8);
-
         if (s->version < 1 || s->version > 4)
             self_destruct();
     } else if (strncmp(token, "options=", 8) == 0) {
@@ -3144,17 +3175,10 @@
     } else if (strncmp(token, "sslcontext=", 11) == 0) {
         safe_free(s->sslcontext);
         s->sslcontext = xstrdup(token + 11);
-    } else if (strcmp(token, "sslBump") == 0) {
-        s->sslBump = 1; // accelerated when bumped, otherwise not
 #endif
     } else {
         self_destruct();
     }
-
-    if ( s->spoof_client_ip && (s->intercepted || s->accel) ) {
-        debugs(3,DBG_CRITICAL, "http(s)_port: TPROXY option requires its own interception port. It cannot be shared.");
-        self_destruct();
-    }
 }
 
 static http_port_list *
@@ -3268,18 +3292,24 @@
                       n,
                       s->s.ToURL(buf,MAX_IPSTRLEN));
 
-    if (s->defaultsite)
-        storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
-
     if (s->intercepted)
         storeAppendPrintf(e, " intercept");
 
+    if (s->spoof_client_ip)
+        storeAppendPrintf(e, " tproxy");
+
+    if (s->accel)
+        storeAppendPrintf(e, " accel");
+
     if (s->vhost)
         storeAppendPrintf(e, " vhost");
 
     if (s->vport)
         storeAppendPrintf(e, " vport");
 
+    if (s->defaultsite)
+        storeAppendPrintf(e, " defaultsite=%s", s->defaultsite);
+
     if (s->connection_auth_disabled)
         storeAppendPrintf(e, " connection-auth=off");
     else
@@ -3305,6 +3335,9 @@
     }
 
 #if USE_SSL
+    if (s->sslBump)
+        storeAppendPrintf(e, " sslBump");
+
     if (s->cert)
         storeAppendPrintf(e, " cert=%s", s->cert);
 
@@ -3337,9 +3370,6 @@
 
     if (s->sslcontext)
         storeAppendPrintf(e, " sslcontext=%s", s->sslcontext);
-
-    if (s->sslBump)
-        storeAppendPrintf(e, " sslBump");
 #endif
 }
 

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2010-04-17 02:29:04 +0000
+++ src/cf.data.pre	2010-04-21 01:37:57 +0000
@@ -1133,17 +1133,16 @@
 DEFAULT: none
 LOC: Config.Sockaddr.http
 DOC_START
-	Usage:	port [options]
-		hostname:port [options]
-		1.2.3.4:port [options]
+	Usage:	port [mode] [options]
+		hostname:port [mode] [options]
+		1.2.3.4:port [mode] [options]
 
 	The socket addresses where Squid will listen for HTTP client
 	requests.  You may specify multiple socket addresses.
 	There are three forms: port alone, hostname with port, and
 	IP address with port.  If you specify a hostname or IP
 	address, Squid binds the socket to that specific
-	address.  This replaces the old 'tcp_incoming_address'
-	option.  Most likely, you do not need to bind to a specific
+	address. Most likely, you do not need to bind to a specific
 	address, so you can use the port number alone.
 
 	If you are running Squid in accelerator mode, you
@@ -1155,7 +1154,7 @@
 
 	You may specify multiple socket addresses on multiple lines.
 
-	Options:
+	Modes:
 
 	   intercept	Support for IP-Layer interception of
 			outgoing requests without browser settings.
@@ -1168,6 +1167,20 @@
 	   accel	Accelerator mode. Also needs at least one of
 			vhost / vport / defaultsite.
 
+	   sslbump 	Intercept each CONNECT request matching ssl_bump ACL,
+			establish secure connection with the client and with
+			the server, decrypt HTTP messages as they pass through
+			Squid, and treat them as unencrypted HTTP messages,
+			becoming the man-in-the-middle.
+
+			The ssl_bump option is required to fully enable
+			the SslBump feature.
+
+	Omitting the mode flag causes default forward proxy mode to be used.
+
+
+	Accelerator Mode Options:
+
 	   allow-direct	Allow direct forwarding in accelerator mode. Normally
 			accelerated requests are denied direct forwarding as if
 			never_direct was used.
@@ -1178,23 +1191,91 @@
 			accelerators should consider the default.
 			Implies accel.
 
-	   vhost	Accelerator mode using Host header for virtual
-			domain support. Implies accel.
-
-	   vport	Accelerator with IP based virtual host support.
-			Implies accel.
-
-	   vport=NN	As above, but uses specified port number rather
-			than the http_port number. Implies accel.
+	   vhost	Using the Host header for virtual domain support.
+			Also uses the port as specified in Host: header.
+
+	   vport	IP based virtual host support. Using the http_port number
+			in passed on Host: headers.
+
+	   vport=NN	Uses the specified port number rather than the
+			http_port number.
 
 	   protocol=	Protocol to reconstruct accelerated requests with.
-			Defaults to http.
+			Defaults to http://.
 
 	   ignore-cc	Ignore request Cache-Control headers.
 
 	   		Warning: This option violates HTTP specifications if
 			used in non-accelerator setups.
 
+
+	SSL Bump Mode Options:
+
+	   cert=	Path to SSL certificate (PEM format).
+
+	   key=		Path to SSL private key file (PEM format)
+			if not specified, the certificate file is
+			assumed to be a combined certificate and
+			key file.
+
+	   version=	The version of SSL/TLS supported
+			    1	automatic (default)
+			    2	SSLv2 only
+			    3	SSLv3 only
+			    4	TLSv1 only
+
+	   cipher=	Colon separated list of supported ciphers.
+
+	   options=	Various SSL engine options. The most important
+			being:
+			    NO_SSLv2  Disallow the use of SSLv2
+			    NO_SSLv3  Disallow the use of SSLv3
+			    NO_TLSv1  Disallow the use of TLSv1
+			    SINGLE_DH_USE Always create a new key when using
+				      temporary/ephemeral DH key exchanges
+			See src/ssl_support.c or OpenSSL SSL_CTX_set_options
+			documentation for a complete list of options.
+
+	   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
+			and CRL lists to use when verifying client certificates.
+
+	   crlfile=	File of additional CRL lists to use when verifying
+			the client certificate, in addition to CRLs stored in
+			the capath. Implies VERIFY_CRL flag below.
+
+	   dhparams=	File containing DH parameters for temporary/ephemeral
+			DH key exchanges.
+
+	   sslflags=	Various flags modifying the use of SSL:
+			    DELAYED_AUTH
+				Don't request client certificates
+				immediately, but wait until acl processing
+				requires a certificate (not yet implemented).
+			    NO_DEFAULT_CA
+				Don't use the default CA lists built in
+				to OpenSSL.
+			    NO_SESSION_REUSE
+				Don't allow for session reuse. Each connection
+				will result in a new SSL session.
+			    VERIFY_CRL
+				Verify CRL lists when accepting client
+				certificates.
+			    VERIFY_CRL_ALL
+				Verify CRL lists for all certificates in the
+				client certificate chain.
+
+	   sslcontext=	SSL session ID context identifier.
+
+
+	Other Options:
+
 	   connection-auth[=on|off]
 	                use connection-auth=off to tell Squid to prevent 
 	                forwarding Microsoft connection oriented authentication
@@ -1216,22 +1297,6 @@
 			sporadically hang or never complete requests set
 			disable-pmtu-discovery option to 'transparent'.
 
-	   sslBump 	Intercept each CONNECT request matching ssl_bump ACL,
-			establish secure connection with the client and with
-			the server, decrypt HTTP messages as they pass through
-			Squid, and treat them as unencrypted HTTP messages,
-			becoming the man-in-the-middle.
-
-			When this option is enabled, additional options become
-			available to specify SSL-related properties of the
-			client-side connection: cert, key, version, cipher,
-			options, clientca, cafile, capath, crlfile, dhparams,
-			sslflags, and sslcontext. See the https_port directive
-			for more information on these options.
-
-			The ssl_bump option is required to fully enable
-			the SslBump feature.
-
 	   name=	Specifies a internal name for the port. Defaults to
 			the port specification (port or addr:port)
 

Reply via email to