You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.2 KiB
157 lines
4.2 KiB
diff --git a/src/serv-args.def b/src/serv-args.def |
|
index 44b67f1ab..027737772 100644 |
|
--- a/src/serv-args.def |
|
+++ b/src/serv-args.def |
|
@@ -8,6 +8,19 @@ detail = "Server program that listens to incoming TLS connections."; |
|
|
|
#include args-std.def |
|
|
|
+flag = { |
|
+ name = sni-hostname; |
|
+ descrip = "Server's hostname for server name extension"; |
|
+ arg-type = string; |
|
+ doc = "Server name of type host_name that the server will recognise as its own. If the server receives client hello with different name, it will send a warning-level unrecognized_name alert."; |
|
+}; |
|
+ |
|
+flag = { |
|
+ name = sni-hostname-fatal; |
|
+ descrip = "Send fatal alert on sni-hostname mismatch"; |
|
+ doc = ""; |
|
+}; |
|
+ |
|
flag = { |
|
name = noticket; |
|
descrip = "Don't accept session tickets"; |
|
diff --git a/src/serv.c b/src/serv.c |
|
index a1f9adfa8..f5ff48786 100644 |
|
--- a/src/serv.c |
|
+++ b/src/serv.c |
|
@@ -49,6 +49,8 @@ |
|
#include "sockets.h" |
|
#include "udp-serv.h" |
|
|
|
+#define _GNUTLS_E_UNRECOGNIZED_NAME -294 |
|
+ |
|
/* konqueror cannot handle sending the page in multiple |
|
* pieces. |
|
*/ |
|
@@ -81,6 +83,8 @@ const char *dh_params_file = NULL; |
|
const char *x509_crlfile = NULL; |
|
const char *priorities = NULL; |
|
const char *status_response_ocsp = NULL; |
|
+const char *sni_hostname = NULL; |
|
+int sni_hostname_fatal = 0; |
|
|
|
gnutls_datum_t session_ticket_key; |
|
static void tcp_server(const char *name, int port); |
|
@@ -312,6 +316,83 @@ int ret; |
|
return 0; |
|
} |
|
|
|
+/* callback used to verify if the host name advertised in client hello matches |
|
+ * the one configured in server |
|
+ */ |
|
+static int |
|
+post_client_hello(gnutls_session_t session) |
|
+{ |
|
+ int ret; |
|
+ /* DNS names (only type supported) may be at most 256 byte long */ |
|
+ char *name; |
|
+ size_t len = 256; |
|
+ unsigned int type; |
|
+ int i; |
|
+ |
|
+ name = malloc(len); |
|
+ if (name == NULL) |
|
+ return GNUTLS_E_MEMORY_ERROR; |
|
+ |
|
+ for (i=0; ; ) { |
|
+ ret = gnutls_server_name_get(session, name, &len, &type, i); |
|
+ if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { |
|
+ char *new_name; |
|
+ new_name = realloc(name, len); |
|
+ if (new_name == NULL) { |
|
+ ret = GNUTLS_E_MEMORY_ERROR; |
|
+ goto end; |
|
+ } |
|
+ name = new_name; |
|
+ continue; /* retry call with same index */ |
|
+ } |
|
+ |
|
+ /* check if it is the last entry in list */ |
|
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) |
|
+ break; |
|
+ i++; |
|
+ if (ret != GNUTLS_E_SUCCESS) |
|
+ goto end; |
|
+ /* unknown types need to be ignored */ |
|
+ if (type != GNUTLS_NAME_DNS) |
|
+ continue; |
|
+ |
|
+ if (strlen(sni_hostname) != len) |
|
+ continue; |
|
+ /* API guarantees that the name of type DNS will be null terminated */ |
|
+ if (!strncmp(name, sni_hostname, len)) { |
|
+ ret = GNUTLS_E_SUCCESS; |
|
+ goto end; |
|
+ } |
|
+ }; |
|
+ /* when there is no extension, we can't send the extension specific alert */ |
|
+ if (i == 0) { |
|
+ fprintf(stderr, "Warning: client did not include SNI extension, using default host\n"); |
|
+ ret = GNUTLS_E_SUCCESS; |
|
+ goto end; |
|
+ } |
|
+ |
|
+ if (sni_hostname_fatal == 1) { |
|
+ /* abort the connection, propagate error up the stack */ |
|
+ ret = _GNUTLS_E_UNRECOGNIZED_NAME; |
|
+ goto end; |
|
+ } |
|
+ |
|
+ fprintf(stderr, "Warning: client provided unrecognized host name\n"); |
|
+ /* since we just want to send an alert, not abort the connection, we |
|
+ * need to send it ourselves |
|
+ */ |
|
+ do { |
|
+ ret = gnutls_alert_send(session, |
|
+ GNUTLS_AL_WARNING, |
|
+ GNUTLS_A_UNRECOGNIZED_NAME); |
|
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); |
|
+ |
|
+ /* continue handshake, fall through */ |
|
+end: |
|
+ free(name); |
|
+ return ret; |
|
+} |
|
+ |
|
gnutls_session_t initialize_session(int dtls) |
|
{ |
|
gnutls_session_t session; |
|
@@ -343,6 +424,10 @@ gnutls_session_t initialize_session(int dtls) |
|
&session_ticket_key); |
|
#endif |
|
|
|
+ if (sni_hostname != NULL) |
|
+ gnutls_handshake_set_post_client_hello_function(session, |
|
+ &post_client_hello); |
|
+ |
|
if (gnutls_priority_set_direct(session, priorities, &err) < 0) { |
|
fprintf(stderr, "Syntax error at: %s\n", err); |
|
exit(1); |
|
@@ -1629,6 +1714,12 @@ static void cmd_parser(int argc, char **argv) |
|
if (HAVE_OPT(OCSP_RESPONSE)) |
|
status_response_ocsp = OPT_ARG(OCSP_RESPONSE); |
|
|
|
+ if (HAVE_OPT(SNI_HOSTNAME)) |
|
+ sni_hostname = OPT_ARG(SNI_HOSTNAME); |
|
+ |
|
+ if (HAVE_OPT(SNI_HOSTNAME_FATAL)) |
|
+ sni_hostname_fatal = 1; |
|
+ |
|
} |
|
|
|
/* session resuming support */ |
|
-- |
|
2.14.3 |
|
|
|
|