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