Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'dev' of https://github.com/cherokee/webserver

Conflicts:
	cherokee/source.c
  • Loading branch information...
commit 346efc7287f81be760cf709b5ec01ce1b78679b2 2 parents 82e2482 + 4536bb7
@skinkie authored
View
1  cherokee/connection-protected.h
@@ -291,6 +291,7 @@ ret_t cherokee_connection_instance_encoder (cherokee_connection_t *conn);
ret_t cherokee_connection_sleep (cherokee_connection_t *conn, cherokee_msec_t msecs);
void cherokee_connection_update_timeout (cherokee_connection_t *conn);
void cherokee_connection_add_expiration_header (cherokee_connection_t *conn, cherokee_buffer_t *buffer, cherokee_boolean_t use_maxage);
+ret_t cherokee_connection_build_host_string (cherokee_connection_t *conn, cherokee_buffer_t *buf);
ret_t cherokee_connection_build_host_port_string (cherokee_connection_t *conn, cherokee_buffer_t *buf);
/* Iteration
View
49 cherokee/connection.c
@@ -559,15 +559,38 @@ cherokee_connection_setup_error_handler (cherokee_connection_t *conn)
ret_t
cherokee_connection_setup_hsts_handler (cherokee_connection_t *conn)
{
- ret_t ret;
+ ret_t ret;
+ cherokee_list_t *i;
+ int port = -1;
+ cherokee_server_t *srv = CONN_SRV(conn);
/* Redirect to:
* "https://" + host + request + query_string
*/
- cherokee_buffer_clean (&conn->redirect);
+ cherokee_buffer_clean (&conn->redirect);
+
+ /* 1.- Proto */
cherokee_buffer_add_str (&conn->redirect, "https://");
- cherokee_connection_build_host_port_string (conn, &conn->redirect);
+ /* 2.- Host */
+ cherokee_connection_build_host_string (conn, &conn->redirect);
+
+ /* 3.- Port */
+ list_for_each (i, &srv->listeners) {
+ if (BIND_IS_TLS(i)) {
+ port = BIND(i)->port;
+ break;
+ }
+ }
+
+ if ((port != -1) &&
+ (! http_port_is_standard (port, true)))
+ {
+ cherokee_buffer_add_char (&conn->redirect, ':');
+ cherokee_buffer_add_ulong10 (&conn->redirect, port);
+ }
+
+ /* 4.- Request */
cherokee_buffer_add_buffer (&conn->redirect, &conn->request);
if (conn->query_string.len > 0) {
@@ -2958,8 +2981,8 @@ cherokee_connection_update_timeout (cherokee_connection_t *conn)
ret_t
-cherokee_connection_build_host_port_string (cherokee_connection_t *conn,
- cherokee_buffer_t *buf)
+cherokee_connection_build_host_string (cherokee_connection_t *conn,
+ cherokee_buffer_t *buf)
{
/* 1st choice: Request host */
if (! cherokee_buffer_is_empty (&conn->host)) {
@@ -2980,6 +3003,22 @@ cherokee_connection_build_host_port_string (cherokee_connection_t *conn,
cherokee_buffer_add_buffer (buf, &conn->bind->server_address);
}
+ return ret_ok;
+}
+
+ret_t
+cherokee_connection_build_host_port_string (cherokee_connection_t *conn,
+ cherokee_buffer_t *buf)
+{
+ ret_t ret;
+
+ /* Host
+ */
+ ret = cherokee_connection_build_host_string (conn, buf);
+ if (unlikely (ret != ret_ok)) {
+ return ret_error;
+ }
+
/* Port
*/
if ((conn->bind != NULL) &&
View
189 cherokee/source.c
@@ -70,124 +70,135 @@ cherokee_source_mrproper (cherokee_source_t *src)
}
-ret_t
-cherokee_source_connect (cherokee_source_t *src, cherokee_socket_t *sock)
+static ret_t
+source_set_address (cherokee_source_t *src,
+ cherokee_socket_t *sock)
{
ret_t ret;
+ cherokee_boolean_t tested_all;
cherokee_resolv_cache_t *resolv;
+ const struct addrinfo *addr;
+ const struct addrinfo *addr_info = NULL;
- /* Short path: it's already connecting
+ /* Query the resolv cache
*/
- if (sock->socket >= 0) {
- return cherokee_socket_connect (sock);
+ ret = cherokee_resolv_cache_get_default (&resolv);
+ if (unlikely (ret!=ret_ok)) {
+ return ret;
}
- /* Create the new socket and set the target IP info
+ ret = cherokee_resolv_cache_get_addrinfo (resolv, &src->host, &addr_info);
+ if ((ret != ret_ok) || (addr_info == NULL)) {
+ return ret_error;
+ }
+
+ /* Current address
*/
- if (! cherokee_buffer_is_empty (&src->unix_socket)) {
+ if (src->addr_current) {
+ tested_all = false;
+ addr = src->addr_current;
+ } else {
+ tested_all = true;
+ addr = addr_info;
+ }
- /* Create the socket descriptor
- */
- ret = cherokee_socket_create_fd (sock, AF_UNIX);
- if (unlikely (ret != ret_ok)) {
- return ret;
- }
+ /* Create the fd for the address family
+ *
+ * Iterates through the different addresses of the
+ * host and stores a pointer to the first one with
+ * a supported family.
+ */
+ while (addr != NULL) {
+ ret = cherokee_socket_create_fd (sock, addr->ai_family);
- ret = cherokee_socket_gethostbyname (sock, &src->unix_socket);
- if (unlikely (ret != ret_ok)) {
- return ret;
- }
- } else {
- cherokee_boolean_t tested_all;
- const struct addrinfo *addr;
- const struct addrinfo *addr_info = NULL;
+#ifdef TRACE_ENABLED
+ if (cherokee_trace_is_tracing()) {
+ ret_t ret2;
+ char ip[46];
- /* Query the resolv cache
- */
- ret = cherokee_resolv_cache_get_default (&resolv);
- if (unlikely (ret!=ret_ok)) {
- return ret;
+ ret2 = cherokee_ntop (addr->ai_family, addr->ai_addr, ip, sizeof(ip));
+ if (ret2 == ret_ok) {
+ TRACE (ENTRIES, "Connecting to %s, ret=%d\n", ip, ret);
+ }
}
+#endif
- ret = cherokee_resolv_cache_get_addrinfo (resolv, &src->host, &addr_info);
- if ((ret != ret_ok) || (addr_info == NULL)) {
- return ret_error;
+ if (ret == ret_ok) {
+ src->addr_current = addr;
+ break;
}
- /* Current address
- */
- if (src->addr_current) {
- tested_all = false;
- addr = src->addr_current;
- #if 0
- /* The following allows to 'loadbalance' and/or check other sources */
- addr = src->addr_current->ai_next;
- if (addr == NULL)
- addr = addr_info;
- #endif
- } else {
+ addr = addr->ai_next;
+ if (addr == NULL) {
+ if (tested_all) {
+ return ret_error;
+ }
+
tested_all = true;
+ src->addr_current = NULL;
addr = addr_info;
+ continue;
}
- /* Create the fd for the address family
- *
- * Iterates through the different addresses of the
- * host and stores a pointer to the first one with
- * a supported family.
- */
- while (addr != NULL) {
- ret = cherokee_socket_create_fd (sock, addr->ai_family);
+ cherokee_socket_close(sock);
+ }
-#ifdef TRACE_ENABLED
- if (cherokee_trace_is_tracing()) {
- ret_t ret2;
- char ip[46];
-
- ret2 = cherokee_ntop (addr->ai_family, addr->ai_addr, ip, sizeof(ip));
- if (ret2 == ret_ok) {
- TRACE (ENTRIES, "Connecting to %s, ret=%d\n", ip, ret);
- }
- }
-#endif
+ /* Update the new socket with the address info
+ */
+ switch (src->addr_current->ai_family) {
+ case AF_INET:
+ SOCKET_ADDR_IPv4(sock)->sin_port = htons(src->port);
+ break;
+ case AF_INET6:
+ SOCKET_ADDR_IPv6(sock)->sin6_port = htons(src->port);
+ break;
+ default:
+ SHOULDNT_HAPPEN;
+ return ret_error;
+ }
- if (ret == ret_ok) {
- src->addr_current = addr;
- break;
- }
+ ret = cherokee_socket_update_from_addrinfo (sock, src->addr_current, 0);
+ if (unlikely (ret != ret_ok)) {
+ return ret_error;
+ }
- addr = addr->ai_next;
- if (addr == NULL) {
- if (tested_all) {
- return ret_error;
- }
+ return ret_ok;
+}
- tested_all = true;
- src->addr_current = NULL;
- addr = addr_info;
- continue;
- }
- cherokee_socket_close(sock);
- }
+ret_t
+cherokee_source_connect (cherokee_source_t *src, cherokee_socket_t *sock)
+{
+ ret_t ret;
- /* Update the new socket with the address info
+ /* Short path: it's already connecting
+ */
+ if (sock->socket >= 0) {
+ return cherokee_socket_connect (sock);
+ }
+
+ /* Create the new socket and set the target IP info
+ */
+ if (! cherokee_buffer_is_empty (&src->unix_socket)) {
+
+ /* Create the socket descriptor
*/
- switch (src->addr_current->ai_family) {
- case AF_INET:
- SOCKET_ADDR_IPv4(sock)->sin_port = htons(src->port);
- break;
- case AF_INET6:
- SOCKET_ADDR_IPv6(sock)->sin6_port = htons(src->port);
- break;
- default:
- SHOULDNT_HAPPEN;
- return ret_error;
+ ret = cherokee_socket_create_fd (sock, AF_UNIX);
+ if (unlikely (ret != ret_ok)) {
+ return ret;
}
- ret = cherokee_socket_update_from_addrinfo (sock, src->addr_current, 0);
+ ret = cherokee_socket_gethostbyname (sock, &src->unix_socket);
if (unlikely (ret != ret_ok)) {
- return ret_error;
+ return ret;
+ }
+ } else {
+
+ /* Set next IP address
+ */
+ ret = source_set_address (src, sock);
+ if (ret != ret_ok) {
+ return ret;
}
}
View
8 cherokee/source_interpreter.c
@@ -724,6 +724,14 @@ cherokee_source_interpreter_connect_polling (cherokee_source_interpreter_t *src,
/* reset by peer: spawn process? */
TRACE (ENTRIES, "Connection refused (closing fd=%d)\n", socket->socket);
cherokee_socket_close (socket);
+
+ /* Try the next address quickly, if any */
+ if (SOURCE(src)->addr_current) {
+ SOURCE(src)->addr_current = SOURCE(src)->addr_current->ai_next;
+ if (SOURCE(src)->addr_current) {
+ return ret_eagain;
+ }
+ }
break;
default:
View
2  qa/091-Digest2.py
@@ -29,7 +29,7 @@ def JustBefore (self, www):
#
nested = TestBase(__file__)
nested.request = "GET /digest2/file HTTP/1.0\r\n"
- nested.Run(HOST, PORT, 0)
+ nested.Run(HOST, PORT)
# Parse the authentication information line
#
View
2  qa/092-Digest3.py
@@ -30,7 +30,7 @@ def JustBefore (self, www):
#
nested = TestBase(__file__)
nested.request = "GET /digest3/file HTTP/1.0\r\n"
- nested.Run(HOST, PORT, 0)
+ nested.Run(HOST, PORT)
# Parse the authentication information line
#
View
2  qa/100-Digest-htdigest.py
@@ -30,7 +30,7 @@ def JustBefore (self, www):
#
nested = TestBase(__file__)
nested.request = "GET /%s/file HTTP/1.0\r\n" % (DIR)
- nested.Run(HOST, PORT, 0)
+ nested.Run(HOST, PORT)
# Parse the authentication information line
#
View
2  qa/130-Digest-EmptyPasswd.py
@@ -29,7 +29,7 @@ def JustBefore (self, www):
#
nested = TestBase(__file__)
nested.request = "GET /digest_empty/file HTTP/1.0\r\n"
- nested.Run(HOST, PORT, 0)
+ nested.Run(HOST, PORT)
# Parse the authentication information line
#
View
2  qa/175-Digest-htdigest-2.py
@@ -38,7 +38,7 @@ def JustBefore (self, www):
#
nested = TestBase(__file__)
nested.request = "GET /%s/file HTTP/1.0\r\n" % (DIR)
- nested.Run(HOST, PORT, 0)
+ nested.Run(HOST, PORT)
# Parse the authentication information line
#
View
16 qa/292-HSTS1.py
@@ -12,6 +12,17 @@
vserver!2920!rule!1!handler = dirlist
"""
+# 6.2. HTTP Request Type
+#
+# If a HSTS Host receives a HTTP request message over a non-secure
+# transport, it SHOULD send a HTTP response message containing a
+# Status-Code of 301 and a Location header field value containing
+# either the HTTP request's original Effective Request URI (see
+# Section 12 "Constructing an Effective Request URI", below) altered as
+# necessary to have a URI scheme of "https", or a URI generated
+# according to local policy (which SHOULD employ a URI scheme of
+# "https").
+
class Test (TestBase):
def __init__ (self):
TestBase.__init__ (self, __file__)
@@ -19,7 +30,7 @@ def __init__ (self):
self.request = "HTTP / HTTP/1.0\r\n" + \
"Host: %s\r\n" %(NICK)
self.expected_error = 301
- self.expected_content = ["Strict-Transport-Security:", "max-age=%d"%(MAX_AGE)]
+ self.expected_content = ["https://"]
def Prepare (self, www):
droot = self.Mkdir (www, "%s_droot"%(NICK))
@@ -27,3 +38,6 @@ def Prepare (self, www):
vars = globals()
vars.update(locals())
self.conf = CONF %(vars)
+
+ def Precondition (self):
+ return not self.is_ssl
View
19 qa/293-HSTS-subdomains1.py
@@ -11,13 +11,23 @@
vserver!2930!rule!1!handler = dirlist
"""
+# 6.1. HTTP-over-Secure-Transport Request Type
+#
+# When replying to an HTTP request that was conveyed over a secure
+# transport, a HSTS Host SHOULD include in its response message a
+# Strict-Transport-Security HTTP Response Header that MUST satisfy the
+# grammar specified above in Section 5.1 "Strict-Transport-Security
+# HTTP Response Header Field". If a Strict-Transport-Security HTTP
+# Response Header is included, the HSTS Host MUST include only one such
+# header.
+
class Test (TestBase):
def __init__ (self):
TestBase.__init__ (self, __file__)
- self.name = "HSTS: with Subdomains"
- self.request = "HTTP / HTTP/1.0\r\n" + \
+ self.name = "HSTS over SSL"
+ self.request = "GET / HTTP/1.0\r\n" + \
"Host: %s\r\n" %(NICK)
- self.expected_error = 301
+ self.expected_error = 200
self.expected_content = ["Strict-Transport-Security:", "includeSubdomains"]
def Prepare (self, www):
@@ -26,3 +36,6 @@ def Prepare (self, www):
vars = globals()
vars.update(locals())
self.conf = CONF %(vars)
+
+ def Precondition (self):
+ return self.is_ssl
View
9 qa/294-HSTS-subdomains2.py
@@ -14,10 +14,10 @@
class Test (TestBase):
def __init__ (self):
TestBase.__init__ (self, __file__)
- self.name = "HSTS: without Subdomains"
- self.request = "HTTP / HTTP/1.0\r\n" + \
+ self.name = "HSTS over SSL: without Subdomains"
+ self.request = "GET / HTTP/1.0\r\n" + \
"Host: %s\r\n" %(NICK)
- self.expected_error = 301
+ self.expected_error = 200
self.expected_content = ["Strict-Transport-Security:"]
self.forbidden_content = ["includeSubdomains"]
@@ -27,3 +27,6 @@ def Prepare (self, www):
vars = globals()
vars.update(locals())
self.conf = CONF %(vars)
+
+ def Precondition (self):
+ return self.is_ssl
View
17 qa/base.py
@@ -49,6 +49,7 @@ def __init__ (self, file):
def _initialize (self):
self.ssl = None
+ self.is_ssl = False
self.reply = "" # "200 OK"..
self.version = None # HTTP/x.y: 9, 0 or 1
self.reply_err = None # 200
@@ -67,7 +68,7 @@ def _safe_read (self, s):
continue
raise
- def _do_request (self, host, port, ssl):
+ def _do_request (self, host, port):
for res in socket.getaddrinfo (host, port, socket.AF_UNSPEC, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
@@ -87,11 +88,11 @@ def _do_request (self, host, port, ssl):
if s is None:
raise Exception("Couldn't connect to the server")
- if ssl:
+ if self.is_ssl:
try:
self.ssl = socket.ssl (s)
- except:
- raise Exception("Couldn't handshake SSL")
+ except Exception, e:
+ raise Exception("Couldn't handshake SSL: "+str(e))
request = self.request + "\r\n"
if self.post is not None:
@@ -214,8 +215,8 @@ def JustAfter (self, www):
def CustomTest (self):
return 0
- def Run (self, host, port, ssl):
- self._do_request(host, port, ssl)
+ def Run (self, host, port):
+ self._do_request(host, port)
self._parse_output()
return self._check_result()
@@ -448,10 +449,10 @@ def JustAfter (self, www):
self.current_test = current
- def Run (self, host, port, ssl):
+ def Run (self, host, port):
for t in self.tests:
self.current_test = t
- r = t.Run(host, port, ssl)
+ r = t.Run(host, port)
if r == -1: return r
if self.delay > 0:
View
5 qa/conf.py.pre
@@ -17,9 +17,8 @@ LOGGER_ACCESS = "access.log"
LOGGER_ERROR = "error.log"
# TLS/SSL
-SSL_CERT_FILE = "/etc/cherokee/ssl/cherokee.pem"
-SSL_CERT_KEY_FILE = "/etc/cherokee/ssl/cherokee.pem"
-SSL_CA_FILE = "/etc/cherokee/ssl/cherokee.pem"
+SSL_CERT_FILE = "/etc/cherokee/ssl/cherokee.crt"
+SSL_CERT_KEY_FILE = "/etc/cherokee/ssl/cherokee.key"
# Misc options
SERVER_DELAY = 10
View
60 qa/pyscgi.py
@@ -5,7 +5,7 @@
http://www.cherokee-project.com/
"""
-# Copyright (c) 2006-2010, Alvaro Lopez Ortega <alvaro@alobbs.com>
+# Copyright (c) 2006-2011, Alvaro Lopez Ortega <alvaro@alobbs.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -43,9 +43,9 @@
import sys
import os
-__version__ = '1.15'
+__version__ = '1.16.1'
__author__ = 'Alvaro Lopez Ortega'
-__copyright__ = 'Copyright 2010, Alvaro Lopez Ortega'
+__copyright__ = 'Copyright 2011, Alvaro Lopez Ortega'
__license__ = 'BSD'
@@ -184,8 +184,58 @@ def process_request (self, request, client_address):
return SocketServer.ThreadingMixIn.process_request (self, request, client_address)
-class ThreadingUnixStreamServer_Custom (ThreadingMixIn_Custom, SocketServer.UnixStreamServer): pass
-class ThreadingTCPServer_Custom (ThreadingMixIn_Custom, SocketServer.TCPServer): pass
+class ThreadingUnixStreamServer_Custom (ThreadingMixIn_Custom, SocketServer.UnixStreamServer):
+ pass
+
+class ThreadingTCPServer_Custom (ThreadingMixIn_Custom, SocketServer.TCPServer):
+ def server_bind (self):
+ host, port = self.server_address
+
+ # Binding to a IP/host
+ if host:
+ return self.server_bind_multifamily()
+
+ # Binding all interfaces
+ return SocketServer.TCPServer.server_bind (self)
+
+ def server_bind_multifamily (self):
+ # Loop over the different addresses of 'host'
+ host, port = self.server_address
+ addresses = socket.getaddrinfo (host, port, socket.AF_UNSPEC,
+ socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
+
+ # Find a suitable address
+ s = None
+ for res in addresses:
+ af, socktype, protocol, canonicalname, sa = res
+
+ # Create socket
+ try:
+ s = socket.socket (af, socktype, protocol)
+ except socket.error:
+ s = None
+ continue
+
+ # Bind
+ try:
+ if self.allow_reuse_address:
+ s.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(sa)
+ except socket.error:
+ s.close()
+ s = None
+ continue
+
+ break
+
+ # If none successfully bind report error
+ if not s:
+ raise socket.error, "Could not create server socket"
+
+ self.socket = s
+
+ # Finally, fix the server_address
+ self.server_address = self.socket.getsockname()
# TCP port
View
11 qa/run-tests.py
@@ -217,7 +217,6 @@
server!bind!1!interface = %(listen)s
server!bind!2!port = %(PORT_TLS)d
server!bind!2!tls = 1
-server!bind!2!interface = %(listen)s
server!keepalive = 1
server!panic_action = %(panic)s
server!pid_file = %(pid)s
@@ -260,10 +259,9 @@
if ssl:
CONF_BASE += """
server!tls = libssl
-vserver!1!ssl_certificate_file = %s
-vserver!1!ssl_certificate_key_file = %s
-vserver!1!ssl_ca_list_file = %s
-""" % (SSL_CERT_FILE, SSL_CERT_KEY_FILE, SSL_CA_FILE)
+vserver!1!ssl_certificate_file = %(SSL_CERT_FILE)s
+vserver!1!ssl_certificate_key_file = %(SSL_CERT_KEY_FILE)s
+""" % (globals())
if log:
CONF_BASE += """
@@ -296,6 +294,7 @@
obj.tmp = tmp
obj.nobody = nobody
obj.php_conf = php_ext
+ obj.is_ssl = ssl
objs.append(obj)
# Prepare www files
@@ -467,7 +466,7 @@ def mainloop_iterator (objs, main_thread=True):
try:
obj.JustBefore(www)
- ret = obj.Run (client_host, client_port, ssl)
+ ret = obj.Run (client_host, client_port)
obj.JustAfter(www)
except Exception, e:
if not its_clean:
Please sign in to comment.
Something went wrong with that request. Please try again.