summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-08-09 16:13:51 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-08-09 16:13:51 +0200
commitf6a2ca30971aab63bc4b98601a5bcb2eab918b9c (patch)
treeb8cae46c5867b524650c9ff2e14955d31cd6134e
parentde5499a73eb82e49da841144ea7d8a51892fb9b0 (diff)
downloadgnutls-f6a2ca30971aab63bc4b98601a5bcb2eab918b9c.tar.gz
gnutls-serv: added support for SNI (--sni-hostname)
-rw-r--r--src/serv-gaa.c147
-rw-r--r--src/serv-gaa.h46
-rw-r--r--src/serv.c97
-rw-r--r--src/serv.gaa9
4 files changed, 221 insertions, 78 deletions
diff --git a/src/serv-gaa.c b/src/serv-gaa.c
index 0decf14700..52d23f6096 100644
--- a/src/serv-gaa.c
+++ b/src/serv-gaa.c
@@ -131,6 +131,8 @@ void gaa_help(void)
__gaa_helpsingle('q', "quiet", "", "Suppress some messages.");
__gaa_helpsingle(0, "nodb", "", "Does not use the resume database.");
__gaa_helpsingle(0, "noticket", "", "Does not issue session tickets.");
+ __gaa_helpsingle(0, "sni-hostname-fatal", "", "Send fatal alert on sni-hostname mismatch");
+ __gaa_helpsingle(0, "sni-hostname", "HOSTNAME ", "Server's hostname for server name extension");
__gaa_helpsingle(0, "http", "", "Act as an HTTP Server.");
__gaa_helpsingle(0, "echo", "", "Act as an Echo Server.");
__gaa_helpsingle(0, "dhparams", "FILE ", "DH params file to use.");
@@ -170,48 +172,52 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 91 "serv.gaa"
+#line 97 "serv.gaa"
char *priorities;
-#line 88 "serv.gaa"
+#line 94 "serv.gaa"
char *opaque_prf_input;
-#line 85 "serv.gaa"
+#line 91 "serv.gaa"
char *srp_passwd_conf;
-#line 82 "serv.gaa"
+#line 88 "serv.gaa"
char *srp_passwd;
-#line 79 "serv.gaa"
+#line 85 "serv.gaa"
char *psk_hint;
-#line 76 "serv.gaa"
+#line 82 "serv.gaa"
char *psk_passwd;
-#line 73 "serv.gaa"
+#line 79 "serv.gaa"
int disable_client_cert;
-#line 70 "serv.gaa"
+#line 76 "serv.gaa"
int require_cert;
-#line 67 "serv.gaa"
+#line 73 "serv.gaa"
char *x509_dsacertfile;
-#line 64 "serv.gaa"
+#line 70 "serv.gaa"
char *x509_dsakeyfile;
-#line 61 "serv.gaa"
+#line 67 "serv.gaa"
char *x509_certfile;
-#line 58 "serv.gaa"
+#line 64 "serv.gaa"
char *x509_keyfile;
-#line 55 "serv.gaa"
+#line 61 "serv.gaa"
char *pgp_subkey;
-#line 52 "serv.gaa"
+#line 58 "serv.gaa"
char *pgp_certfile;
-#line 49 "serv.gaa"
+#line 55 "serv.gaa"
char *pgp_keyfile;
-#line 46 "serv.gaa"
+#line 52 "serv.gaa"
char *pgp_keyring;
-#line 43 "serv.gaa"
+#line 49 "serv.gaa"
char *x509_crlfile;
-#line 40 "serv.gaa"
+#line 46 "serv.gaa"
char *x509_cafile;
-#line 37 "serv.gaa"
+#line 43 "serv.gaa"
int fmtder;
-#line 34 "serv.gaa"
+#line 40 "serv.gaa"
char *dh_params_file;
-#line 30 "serv.gaa"
+#line 36 "serv.gaa"
int http;
+#line 33 "serv.gaa"
+ char *sni_hostname;
+#line 30 "serv.gaa"
+ int sni_hostname_fatal;
#line 27 "serv.gaa"
int noticket;
#line 24 "serv.gaa"
@@ -278,7 +284,7 @@ static int gaa_error = 0;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 31
+#define GAA_NB_OPTION 33
#define GAAOPTID_version 1
#define GAAOPTID_help 2
#define GAAOPTID_list 3
@@ -304,12 +310,14 @@ static int gaa_error = 0;
#define GAAOPTID_dhparams 23
#define GAAOPTID_echo 24
#define GAAOPTID_http 25
-#define GAAOPTID_noticket 26
-#define GAAOPTID_nodb 27
-#define GAAOPTID_quiet 28
-#define GAAOPTID_port 29
-#define GAAOPTID_generate 30
-#define GAAOPTID_debug 31
+#define GAAOPTID_sni_hostname 26
+#define GAAOPTID_sni_hostname_fatal 27
+#define GAAOPTID_noticket 28
+#define GAAOPTID_nodb 29
+#define GAAOPTID_quiet 30
+#define GAAOPTID_port 31
+#define GAAOPTID_generate 32
+#define GAAOPTID_debug 33
#line 168 "gaa.skel"
@@ -598,6 +606,12 @@ struct GAAOPTION_dhparams
int size1;
};
+struct GAAOPTION_sni_hostname
+{
+ char* arg1;
+ int size1;
+};
+
struct GAAOPTION_port
{
int arg1;
@@ -656,6 +670,7 @@ static int gaa_get_option_num(char *str, int status)
GAA_CHECK1STR("", GAAOPTID_x509crlfile);
GAA_CHECK1STR("", GAAOPTID_x509cafile);
GAA_CHECK1STR("", GAAOPTID_dhparams);
+ GAA_CHECK1STR("", GAAOPTID_sni_hostname);
GAA_CHECK1STR("p", GAAOPTID_port);
GAA_CHECK1STR("d", GAAOPTID_debug);
case GAA_MULTIPLE_OPTION:
@@ -668,6 +683,7 @@ static int gaa_get_option_num(char *str, int status)
GAA_CHECK1STR("", GAAOPTID_x509fmtder);
GAA_CHECK1STR("", GAAOPTID_echo);
GAA_CHECK1STR("", GAAOPTID_http);
+ GAA_CHECK1STR("", GAAOPTID_sni_hostname_fatal);
GAA_CHECK1STR("", GAAOPTID_noticket);
GAA_CHECK1STR("", GAAOPTID_nodb);
GAA_CHECK1STR("q", GAAOPTID_quiet);
@@ -701,6 +717,8 @@ static int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("dhparams", GAAOPTID_dhparams);
GAA_CHECKSTR("echo", GAAOPTID_echo);
GAA_CHECKSTR("http", GAAOPTID_http);
+ GAA_CHECKSTR("sni-hostname", GAAOPTID_sni_hostname);
+ GAA_CHECKSTR("sni-hostname-fatal", GAAOPTID_sni_hostname_fatal);
GAA_CHECKSTR("noticket", GAAOPTID_noticket);
GAA_CHECKSTR("nodb", GAAOPTID_nodb);
GAA_CHECKSTR("quiet", GAAOPTID_quiet);
@@ -736,6 +754,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
struct GAAOPTION_x509crlfile GAATMP_x509crlfile;
struct GAAOPTION_x509cafile GAATMP_x509cafile;
struct GAAOPTION_dhparams GAATMP_dhparams;
+ struct GAAOPTION_sni_hostname GAATMP_sni_hostname;
struct GAAOPTION_port GAATMP_port;
struct GAAOPTION_debug GAATMP_debug;
@@ -760,21 +779,21 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
{
case GAAOPTID_version:
OK = 0;
-#line 97 "serv.gaa"
+#line 103 "serv.gaa"
{ serv_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 95 "serv.gaa"
+#line 101 "serv.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_list:
OK = 0;
-#line 94 "serv.gaa"
+#line 100 "serv.gaa"
{ print_list(0); exit(0); ;};
return GAA_OK;
@@ -784,7 +803,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_priority.arg1, gaa_getstr, GAATMP_priority.size1);
gaa_index++;
-#line 92 "serv.gaa"
+#line 98 "serv.gaa"
{ gaaval->priorities = GAATMP_priority.arg1 ;};
return GAA_OK;
@@ -794,7 +813,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_opaque_prf_input.arg1, gaa_getstr, GAATMP_opaque_prf_input.size1);
gaa_index++;
-#line 89 "serv.gaa"
+#line 95 "serv.gaa"
{ gaaval->opaque_prf_input = GAATMP_opaque_prf_input.arg1 ;};
return GAA_OK;
@@ -804,7 +823,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_srppasswdconf.arg1, gaa_getstr, GAATMP_srppasswdconf.size1);
gaa_index++;
-#line 86 "serv.gaa"
+#line 92 "serv.gaa"
{ gaaval->srp_passwd_conf = GAATMP_srppasswdconf.arg1 ;};
return GAA_OK;
@@ -814,7 +833,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_srppasswd.arg1, gaa_getstr, GAATMP_srppasswd.size1);
gaa_index++;
-#line 83 "serv.gaa"
+#line 89 "serv.gaa"
{ gaaval->srp_passwd = GAATMP_srppasswd.arg1 ;};
return GAA_OK;
@@ -824,7 +843,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pskhint.arg1, gaa_getstr, GAATMP_pskhint.size1);
gaa_index++;
-#line 80 "serv.gaa"
+#line 86 "serv.gaa"
{ gaaval->psk_hint = GAATMP_pskhint.arg1 ;};
return GAA_OK;
@@ -834,21 +853,21 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pskpasswd.arg1, gaa_getstr, GAATMP_pskpasswd.size1);
gaa_index++;
-#line 77 "serv.gaa"
+#line 83 "serv.gaa"
{ gaaval->psk_passwd = GAATMP_pskpasswd.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_disable_client_cert:
OK = 0;
-#line 74 "serv.gaa"
+#line 80 "serv.gaa"
{ gaaval->disable_client_cert = 1 ;};
return GAA_OK;
break;
case GAAOPTID_require_cert:
OK = 0;
-#line 71 "serv.gaa"
+#line 77 "serv.gaa"
{ gaaval->require_cert = 1 ;};
return GAA_OK;
@@ -858,7 +877,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_x509dsacertfile.arg1, gaa_getstr, GAATMP_x509dsacertfile.size1);
gaa_index++;
-#line 68 "serv.gaa"
+#line 74 "serv.gaa"
{ gaaval->x509_dsacertfile = GAATMP_x509dsacertfile.arg1 ;};
return GAA_OK;
@@ -868,7 +887,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_x509dsakeyfile.arg1, gaa_getstr, GAATMP_x509dsakeyfile.size1);
gaa_index++;
-#line 65 "serv.gaa"
+#line 71 "serv.gaa"
{ gaaval->x509_dsakeyfile = GAATMP_x509dsakeyfile.arg1 ;};
return GAA_OK;
@@ -878,7 +897,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_x509certfile.arg1, gaa_getstr, GAATMP_x509certfile.size1);
gaa_index++;
-#line 62 "serv.gaa"
+#line 68 "serv.gaa"
{ gaaval->x509_certfile = GAATMP_x509certfile.arg1 ;};
return GAA_OK;
@@ -888,7 +907,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_x509keyfile.arg1, gaa_getstr, GAATMP_x509keyfile.size1);
gaa_index++;
-#line 59 "serv.gaa"
+#line 65 "serv.gaa"
{ gaaval->x509_keyfile = GAATMP_x509keyfile.arg1 ;};
return GAA_OK;
@@ -898,7 +917,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pgpsubkey.arg1, gaa_getstr, GAATMP_pgpsubkey.size1);
gaa_index++;
-#line 56 "serv.gaa"
+#line 62 "serv.gaa"
{ gaaval->pgp_subkey = GAATMP_pgpsubkey.arg1 ;};
return GAA_OK;
@@ -908,7 +927,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pgpcertfile.arg1, gaa_getstr, GAATMP_pgpcertfile.size1);
gaa_index++;
-#line 53 "serv.gaa"
+#line 59 "serv.gaa"
{ gaaval->pgp_certfile = GAATMP_pgpcertfile.arg1 ;};
return GAA_OK;
@@ -918,7 +937,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pgpkeyfile.arg1, gaa_getstr, GAATMP_pgpkeyfile.size1);
gaa_index++;
-#line 50 "serv.gaa"
+#line 56 "serv.gaa"
{ gaaval->pgp_keyfile = GAATMP_pgpkeyfile.arg1 ;};
return GAA_OK;
@@ -928,7 +947,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pgpkeyring.arg1, gaa_getstr, GAATMP_pgpkeyring.size1);
gaa_index++;
-#line 47 "serv.gaa"
+#line 53 "serv.gaa"
{ gaaval->pgp_keyring = GAATMP_pgpkeyring.arg1 ;};
return GAA_OK;
@@ -938,7 +957,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_x509crlfile.arg1, gaa_getstr, GAATMP_x509crlfile.size1);
gaa_index++;
-#line 44 "serv.gaa"
+#line 50 "serv.gaa"
{ gaaval->x509_crlfile = GAATMP_x509crlfile.arg1 ;};
return GAA_OK;
@@ -948,14 +967,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_x509cafile.arg1, gaa_getstr, GAATMP_x509cafile.size1);
gaa_index++;
-#line 41 "serv.gaa"
+#line 47 "serv.gaa"
{ gaaval->x509_cafile = GAATMP_x509cafile.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_x509fmtder:
OK = 0;
-#line 38 "serv.gaa"
+#line 44 "serv.gaa"
{ gaaval->fmtder = 1 ;};
return GAA_OK;
@@ -965,25 +984,42 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_dhparams.arg1, gaa_getstr, GAATMP_dhparams.size1);
gaa_index++;
-#line 35 "serv.gaa"
+#line 41 "serv.gaa"
{ gaaval->dh_params_file = GAATMP_dhparams.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_echo:
OK = 0;
-#line 32 "serv.gaa"
+#line 38 "serv.gaa"
{ gaaval->http = 0 ;};
return GAA_OK;
break;
case GAAOPTID_http:
OK = 0;
-#line 31 "serv.gaa"
+#line 37 "serv.gaa"
{ gaaval->http = 1 ;};
return GAA_OK;
break;
+ case GAAOPTID_sni_hostname:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_sni_hostname.arg1, gaa_getstr, GAATMP_sni_hostname.size1);
+ gaa_index++;
+#line 34 "serv.gaa"
+{ gaaval->sni_hostname = GAATMP_sni_hostname.arg1 ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_sni_hostname_fatal:
+ OK = 0;
+#line 31 "serv.gaa"
+{ gaaval->sni_hostname_fatal = 1 ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_noticket:
OK = 0;
#line 28 "serv.gaa"
@@ -1056,13 +1092,14 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
if(inited == 0)
{
-#line 101 "serv.gaa"
+#line 107 "serv.gaa"
{ gaaval->generate=0; gaaval->port=5556; gaaval->http=0; gaaval->nodb = 0; gaaval->noticket = 0;
gaaval->x509_cafile = NULL; gaaval->pgp_keyfile=NULL; gaaval->pgp_certfile=NULL;
gaaval->x509_keyfile=NULL; gaaval->x509_certfile=NULL; gaaval->x509_crlfile = NULL;
gaaval->x509_dsakeyfile=NULL; gaaval->x509_dsacertfile=NULL;
gaaval->srp_passwd=NULL; gaaval->srp_passwd_conf=NULL; gaaval->quiet = 0;
- gaaval->pgp_keyring=NULL; gaaval->fmtder = 0;
+ gaaval->pgp_keyring=NULL; gaaval->fmtder = 0; gaaval->sni_hostname_fatal = 0;
+ gaaval->sni_hostname = NULL;
gaaval->disable_client_cert = 0; gaaval->priorities = NULL;
gaaval->dh_params_file=NULL; gaaval->debug=0; gaaval->require_cert = 0; gaaval->psk_passwd = 0;
gaaval->opaque_prf_input=NULL; gaaval->pgp_subkey = NULL;;};
diff --git a/src/serv-gaa.h b/src/serv-gaa.h
index cb9f66cb8d..3d0f51dce8 100644
--- a/src/serv-gaa.h
+++ b/src/serv-gaa.h
@@ -8,48 +8,52 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 91 "serv.gaa"
+#line 97 "serv.gaa"
char *priorities;
-#line 88 "serv.gaa"
+#line 94 "serv.gaa"
char *opaque_prf_input;
-#line 85 "serv.gaa"
+#line 91 "serv.gaa"
char *srp_passwd_conf;
-#line 82 "serv.gaa"
+#line 88 "serv.gaa"
char *srp_passwd;
-#line 79 "serv.gaa"
+#line 85 "serv.gaa"
char *psk_hint;
-#line 76 "serv.gaa"
+#line 82 "serv.gaa"
char *psk_passwd;
-#line 73 "serv.gaa"
+#line 79 "serv.gaa"
int disable_client_cert;
-#line 70 "serv.gaa"
+#line 76 "serv.gaa"
int require_cert;
-#line 67 "serv.gaa"
+#line 73 "serv.gaa"
char *x509_dsacertfile;
-#line 64 "serv.gaa"
+#line 70 "serv.gaa"
char *x509_dsakeyfile;
-#line 61 "serv.gaa"
+#line 67 "serv.gaa"
char *x509_certfile;
-#line 58 "serv.gaa"
+#line 64 "serv.gaa"
char *x509_keyfile;
-#line 55 "serv.gaa"
+#line 61 "serv.gaa"
char *pgp_subkey;
-#line 52 "serv.gaa"
+#line 58 "serv.gaa"
char *pgp_certfile;
-#line 49 "serv.gaa"
+#line 55 "serv.gaa"
char *pgp_keyfile;
-#line 46 "serv.gaa"
+#line 52 "serv.gaa"
char *pgp_keyring;
-#line 43 "serv.gaa"
+#line 49 "serv.gaa"
char *x509_crlfile;
-#line 40 "serv.gaa"
+#line 46 "serv.gaa"
char *x509_cafile;
-#line 37 "serv.gaa"
+#line 43 "serv.gaa"
int fmtder;
-#line 34 "serv.gaa"
+#line 40 "serv.gaa"
char *dh_params_file;
-#line 30 "serv.gaa"
+#line 36 "serv.gaa"
int http;
+#line 33 "serv.gaa"
+ char *sni_hostname;
+#line 30 "serv.gaa"
+ int sni_hostname_fatal;
#line 27 "serv.gaa"
int noticket;
#line 24 "serv.gaa"
diff --git a/src/serv.c b/src/serv.c
index 2dfb4923c6..8de52ccec9 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -80,6 +80,9 @@ char *x509_cafile;
char *dh_params_file;
char *x509_crlfile = NULL;
+const char *sni_hostname = NULL;
+int sni_hostname_fatal = 0;
+
gnutls_datum_t session_ticket_key;
/* end of globals */
@@ -131,6 +134,7 @@ LIST_TYPE_DECLARE (listener_item, char *http_request; char *http_response;
int listen_socket; int fd;
gnutls_session_t tls_session;
int handshake_ok;
+ int no_close;
);
static const char *
@@ -150,7 +154,8 @@ listener_free (listener_item * j)
free (j->http_response);
if (j->fd >= 0)
{
- gnutls_bye (j->tls_session, GNUTLS_SHUT_WR);
+ if (j->no_close == 0)
+ gnutls_bye (j->tls_session, GNUTLS_SHUT_WR);
shutdown (j->fd, 2);
close (j->fd);
gnutls_deinit (j->tls_session);
@@ -326,6 +331,83 @@ generate_rsa_params (void)
LIST_DECLARE_INIT (listener_list, listener_item, listener_free);
+/* 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 = -1;
+ 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;
+}
+
static gnutls_session_t
initialize_session (void)
{
@@ -356,6 +438,9 @@ initialize_session (void)
exit (1);
}
+ if (sni_hostname != NULL)
+ gnutls_handshake_set_post_client_hello_function(session, &post_client_hello);
+
gnutls_credentials_set (session, GNUTLS_CRD_ANON, dh_cred);
if (srp_cred != NULL)
@@ -1144,6 +1229,7 @@ main (int argc, char **argv)
(gnutls_transport_ptr_t)
gl_fd_to_handle (accept_fd));
j->handshake_ok = 0;
+ j->no_close = 0;
if (verbose == 0)
{
@@ -1187,6 +1273,7 @@ main (int argc, char **argv)
while (ret == GNUTLS_E_AGAIN
|| ret == GNUTLS_E_INTERRUPTED);
j->http_state = HTTP_STATE_CLOSING;
+ j->no_close = 1;
}
else if (r == 0)
{
@@ -1238,6 +1325,7 @@ main (int argc, char **argv)
GERR (r);
j->http_state = HTTP_STATE_CLOSING;
+ j->no_close = 1;
}
}
else
@@ -1247,6 +1335,11 @@ main (int argc, char **argv)
{
check_alert (j->tls_session, r);
fprintf (stderr, "Error while receiving data\n");
+ do
+ {
+ ret = gnutls_alert_send_appropriate(j->tls_session, r);
+ }
+ while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
GERR (r);
}
}
@@ -1448,6 +1541,8 @@ gaa_parser (int argc, char **argv)
verbose = info.quiet;
nodb = info.nodb;
noticket = info.noticket;
+ sni_hostname = info.sni_hostname;
+ sni_hostname_fatal = info.sni_hostname_fatal;
if (info.http == 0)
http = 0;
diff --git a/src/serv.gaa b/src/serv.gaa
index 0828a864bc..7ca40f2d47 100644
--- a/src/serv.gaa
+++ b/src/serv.gaa
@@ -27,6 +27,12 @@ option (nodb) { $nodb = 1 } "Does not use the resume database."
#int noticket;
option (noticket) { $noticket = 1 } "Does not issue session tickets."
+#int sni_hostname_fatal;
+option (sni-hostname-fatal) { $sni_hostname_fatal = 1 } "Send fatal alert on sni-hostname mismatch"
+
+#char *sni_hostname;
+option (sni-hostname) STR "HOSTNAME" { $sni_hostname = $1 } "Server's hostname for server name extension"
+
#int http;
option (http) { $http = 1 } "Act as an HTTP Server."
option (echo) { $http = 0 } "Act as an Echo Server."
@@ -103,7 +109,8 @@ init { $generate=0; $port=5556; $http=0; $nodb = 0; $noticket = 0;
$x509_keyfile=NULL; $x509_certfile=NULL; $x509_crlfile = NULL;
$x509_dsakeyfile=NULL; $x509_dsacertfile=NULL;
$srp_passwd=NULL; $srp_passwd_conf=NULL; $quiet = 0;
- $pgp_keyring=NULL; $fmtder = 0;
+ $pgp_keyring=NULL; $fmtder = 0; $sni_hostname_fatal = 0;
+ $sni_hostname = NULL;
$disable_client_cert = 0; $priorities = NULL;
$dh_params_file=NULL; $debug=0; $require_cert = 0; $psk_passwd = 0;
$opaque_prf_input=NULL; $pgp_subkey = NULL;}