Index: src/base.h
===================================================================
--- src/base.h.orig	2013-03-26 15:01:06.414997517 +0100
+++ src/base.h	2013-03-26 16:37:12.813039493 +0100
@@ -31,6 +31,9 @@
 #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
 # define USE_OPENSSL
 # include <openssl/ssl.h>
+# if ! defined OPENSSL_NO_TLSEXT && ! defined SSL_CTRL_SET_TLSEXT_HOSTNAME
+#  define OPENSSL_NO_TLSEXT
+# endif
 #endif
 
 #ifdef HAVE_FAM_H
@@ -415,6 +418,9 @@ typedef struct {
 
 #ifdef USE_OPENSSL
 	SSL *ssl;
+# ifndef OPENSSL_NO_TLSEXT
+	buffer *tlsext_server_name;
+# endif
 #endif
 	/* etag handling */
 	etag_flags_t etag_flags;
Index: src/configfile.c
===================================================================
--- src/configfile.c.orig	2008-08-19 19:40:42.000000000 +0200
+++ src/configfile.c	2013-03-26 16:37:12.813039493 +0100
@@ -159,7 +159,7 @@ static int config_insert(server *srv) {
 		s->max_write_idle = 360;
 		s->use_xattr     = 0;
 		s->is_ssl        = 0;
-		s->ssl_use_sslv2 = 1;
+		s->ssl_use_sslv2 = 0;
 		s->use_ipv6      = 0;
 #ifdef HAVE_LSTAT
 		s->follow_symlink = 1;
@@ -289,6 +289,7 @@ int config_setup_connection(server *srv,
 	PATCH(is_ssl);
 
 	PATCH(ssl_pemfile);
+	PATCH(ssl_ctx);
 	PATCH(ssl_ca_file);
 	PATCH(ssl_cipher_list);
 	PATCH(ssl_use_sslv2);
@@ -344,6 +345,7 @@ int config_patch_connection(server *srv,
 				PATCH(etag_use_size);
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
 				PATCH(ssl_pemfile);
+				PATCH(ssl_ctx);
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
 				PATCH(ssl_ca_file);
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
Index: src/configfile-glue.c
===================================================================
--- src/configfile-glue.c.orig	2008-07-30 21:38:32.000000000 +0200
+++ src/configfile-glue.c	2013-03-26 15:01:06.463997512 +0100
@@ -272,6 +272,10 @@ static cond_result_t config_check_cond_n
 			default:
 				break;
 			}
+#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
+		} else if (!buffer_is_empty(con->tlsext_server_name)) {
+			l = con->tlsext_server_name;
+#endif
 		} else {
 			l = srv->empty_string;
 		}
Index: src/connections.c
===================================================================
--- src/connections.c.orig	2013-03-26 15:01:06.418997516 +0100
+++ src/connections.c	2013-03-26 16:37:12.813039493 +0100
@@ -678,6 +678,9 @@ connection *connection_init(server *srv)
 	CLEAN(server_name);
 	CLEAN(error_handler);
 	CLEAN(dst_addr_buf);
+#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
+	CLEAN(tlsext_server_name);
+#endif
 
 #undef CLEAN
 	con->write_queue = chunkqueue_init();
@@ -742,6 +745,9 @@ void connections_free(server *srv) {
 		CLEAN(server_name);
 		CLEAN(error_handler);
 		CLEAN(dst_addr_buf);
+#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
+		CLEAN(tlsext_server_name);
+#endif
 #undef CLEAN
 		free(con->plugin_ctx);
 		free(con->cond_cache);
@@ -1349,6 +1355,9 @@ connection *connection_accept(server *sr
 				return NULL;
 			}
 
+#ifndef OPENSSL_NO_TLSEXT
+			SSL_set_app_data(con->ssl, con);
+#endif
 			SSL_set_accept_state(con->ssl);
 			con->conf.is_ssl=1;
 
Index: src/network.c
===================================================================
--- src/network.c.orig	2013-03-26 15:01:06.431997515 +0100
+++ src/network.c	2013-03-26 16:38:04.711034681 +0100
@@ -16,6 +16,7 @@
 #include "plugin.h"
 #include "joblist.h"
 
+#include "configfile.h"
 #include "network_backends.h"
 #include "sys-mmap.h"
 #include "sys-socket.h"
@@ -62,6 +63,45 @@ handler_t network_server_handle_fdevent(
 	return HANDLER_GO_ON;
 }
 
+#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
+int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) {
+	const char *servername;
+	connection *con = (connection *) SSL_get_app_data(ssl);
+
+	buffer_copy_string(con->uri.scheme, "https");
+
+	if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
+		log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+				"failed to get TLS server name");
+		return SSL_TLSEXT_ERR_NOACK;
+	}
+	buffer_copy_string(con->tlsext_server_name, servername);
+	buffer_to_lower(con->tlsext_server_name);
+
+	config_cond_cache_reset(srv, con);
+	config_setup_connection(srv, con);
+
+	config_patch_connection(srv, con, COMP_SERVER_SOCKET);
+	config_patch_connection(srv, con, COMP_HTTP_SCHEME);
+	config_patch_connection(srv, con, COMP_HTTP_HOST);
+
+	if (NULL == con->conf.ssl_ctx) {
+		log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+				"null SSL_CTX for TLS server name", con->tlsext_server_name);
+		return SSL_TLSEXT_ERR_ALERT_FATAL;
+	}
+
+	/* switch to new SSL_CTX in reaction to a client's server_name extension */
+	if (con->conf.ssl_ctx != SSL_set_SSL_CTX(ssl, con->conf.ssl_ctx)) {
+		log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+				"failed to set SSL_CTX for TLS server name", con->tlsext_server_name);
+		return SSL_TLSEXT_ERR_ALERT_FATAL;
+	}
+
+	return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
 int network_server_init(server *srv, buffer *host_token, specific_config *s) {
 	int val;
 	socklen_t addr_len;
@@ -312,78 +352,10 @@ int network_server_init(server *srv, buf
 
 	if (s->is_ssl) {
 #ifdef USE_OPENSSL
-		if (srv->ssl_is_init == 0) {
-			SSL_load_error_strings();
-			SSL_library_init();
-			srv->ssl_is_init = 1;
-
-			if (0 == RAND_status()) {
-				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
-						"not enough entropy in the pool");
-				return -1;
-			}
-		}
-
-		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
-			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
-					ERR_error_string(ERR_get_error(), NULL));
-			return -1;
-		}
-
-		if (!s->ssl_use_sslv2) {
-			/* disable SSLv2 */
-			if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {
-				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
-						ERR_error_string(ERR_get_error(), NULL));
-				return -1;
-			}
-		}
-
-		if (!buffer_is_empty(s->ssl_cipher_list)) {
-			/* Disable support for low encryption ciphers */
-			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
-				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
-						ERR_error_string(ERR_get_error(), NULL));
-				return -1;
-			}
-		}
-
-		if (buffer_is_empty(s->ssl_pemfile)) {
+		if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) {
 			log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
 			return -1;
 		}
-
-		if (!buffer_is_empty(s->ssl_ca_file)) {
-			if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
-				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
-				return -1;
-			}
-		}
-
-		if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
-			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
-			return -1;
-		}
-
-		if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
-			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
-					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
-			return -1;
-		}
-
-		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
-			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
-					"Private key does not match the certificate public key, reason:",
-					ERR_error_string(ERR_get_error(), NULL),
-					s->ssl_pemfile);
-			return -1;
-		}
-		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
-		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
-
-		srv_socket->ssl_ctx = s->ssl_ctx;
 #else
 
 		buffer_free(srv_socket->srv_token);
@@ -491,6 +463,99 @@ int network_init(server *srv) {
 		{ NETWORK_BACKEND_UNSET,        	NULL }
 	};
 
+#ifdef USE_OPENSSL
+	/* load SSL certificates */
+	for (i = 0; i < srv->config_context->used; i++) {
+		data_config *dc = (data_config *)srv->config_context->data[i];
+		specific_config *s = srv->config_storage[i];
+
+		if (buffer_is_empty(s->ssl_pemfile)) continue;
+
+#ifdef OPENSSL_NO_TLSEXT
+		if (COMP_HTTP_HOST == dc->comp) {
+		    log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+				    "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
+		    return -1;
+		}
+#endif
+
+		if (srv->ssl_is_init == 0) {
+			SSL_load_error_strings();
+			SSL_library_init();
+			srv->ssl_is_init = 1;
+
+			if (0 == RAND_status()) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						"not enough entropy in the pool");
+				return -1;
+			}
+		}
+
+		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+					ERR_error_string(ERR_get_error(), NULL));
+			return -1;
+		}
+
+		if (!s->ssl_use_sslv2) {
+			/* disable SSLv2 */
+			if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {	
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL));
+				return -1;
+			}
+		}
+
+		if (!buffer_is_empty(s->ssl_cipher_list)) {
+			/* Disable support for low encryption ciphers */
+			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
+				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL));
+				return -1;
+			}
+		}
+
+		if (!buffer_is_empty(s->ssl_ca_file)) {
+			if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
+				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
+				return -1;
+			}
+		}
+
+		if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
+			return -1;
+		}
+
+		if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
+			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
+			return -1;
+		}
+
+		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
+			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
+					"Private key does not match the certificate public key, reason:",
+					ERR_error_string(ERR_get_error(), NULL),
+					s->ssl_pemfile);
+			return -1;
+		}
+		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
+		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+# ifndef OPENSSL_NO_TLSEXT
+		if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
+		    !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
+			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+					"failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
+			return -1;
+		}
+# endif
+	}
+#endif
+
 	b = buffer_init();
 
 	buffer_copy_string_buffer(b, srv->srvconf.bindhost);
Index: tests/bug-06.conf
===================================================================
--- tests/bug-06.conf.orig	2008-07-29 23:22:13.000000000 +0200
+++ tests/bug-06.conf	2013-03-26 15:01:06.467997512 +0100
@@ -102,7 +102,7 @@ cgi.assign                  = ( ".pl"  =
 
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
Index: tests/bug-12.conf
===================================================================
--- tests/bug-12.conf.orig	2008-07-29 23:22:13.000000000 +0200
+++ tests/bug-12.conf	2013-03-26 15:01:06.469997512 +0100
@@ -104,7 +104,7 @@ cgi.assign                  = ( ".pl"  =
 
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
Index: tests/fastcgi-10.conf
===================================================================
--- tests/fastcgi-10.conf.orig	2008-07-29 23:22:13.000000000 +0200
+++ tests/fastcgi-10.conf	2013-03-26 15:01:06.469997512 +0100
@@ -81,7 +81,7 @@ cgi.assign                  = ( ".pl"  =
 
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
Index: tests/fastcgi-13.conf
===================================================================
--- tests/fastcgi-13.conf.orig	2008-07-30 19:40:09.000000000 +0200
+++ tests/fastcgi-13.conf	2013-03-26 15:01:06.469997512 +0100
@@ -98,7 +98,7 @@ cgi.assign                  = ( ".pl"  =
 
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
Index: tests/fastcgi-auth.conf
===================================================================
--- tests/fastcgi-auth.conf.orig	2008-07-29 23:22:13.000000000 +0200
+++ tests/fastcgi-auth.conf	2013-03-26 15:01:06.470997511 +0100
@@ -102,7 +102,7 @@ cgi.assign                  = ( ".pl"  =
 
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
Index: tests/fastcgi-responder.conf
===================================================================
--- tests/fastcgi-responder.conf.orig	2008-07-29 23:22:13.000000000 +0200
+++ tests/fastcgi-responder.conf	2013-03-26 15:01:06.470997511 +0100
@@ -105,7 +105,7 @@ cgi.assign                  = ( ".pl"  =
 
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
Index: tests/lighttpd.conf
===================================================================
--- tests/lighttpd.conf.orig	2008-07-29 23:22:13.000000000 +0200
+++ tests/lighttpd.conf	2013-03-26 15:01:06.471997511 +0100
@@ -95,7 +95,7 @@ userdir.include-user = ( "jan" )
 userdir.path = "/"
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 $HTTP["host"] == "auth-htpasswd.example.org" {
 	auth.backend                = "htpasswd"
Index: tests/proxy.conf
===================================================================
--- tests/proxy.conf.orig	2013-03-26 15:01:06.401997518 +0100
+++ tests/proxy.conf	2013-03-26 15:01:06.471997511 +0100
@@ -84,7 +84,7 @@ userdir.include-user = ( "jan" )
 userdir.path = "/"
 
 ssl.engine                  = "disable"
-ssl.pemfile                 = "server.pem"
+#ssl.pemfile                 = "server.pem"
 
 auth.backend                = "plain"
 auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
