summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-10-21 07:34:07 +0200
committerDaiki Ueno <dueno@redhat.com>2018-11-12 14:08:45 +0100
commit16d8812337db0a65b2593f0d7c30cc1a6a79e657 (patch)
treecb1fbf9d6ccc7c546bf95ce7032be991ed91e980
parent79f2f1cf5b91491be5f0e3486c416594ec522b25 (diff)
downloadgnutls-16d8812337db0a65b2593f0d7c30cc1a6a79e657.tar.gz
serv: enable anti-replay when early data is used
Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--src/serv.c143
1 files changed, 107 insertions, 36 deletions
diff --git a/src/serv.c b/src/serv.c
index fbe51b604a..75871270a5 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -87,6 +87,7 @@ const char **alpn_protos = NULL;
unsigned alpn_protos_size = 0;
gnutls_datum_t session_ticket_key;
+gnutls_anti_replay_t anti_replay;
static void tcp_server(const char *name, int port);
/* end of globals */
@@ -117,7 +118,7 @@ gnutls_psk_server_credentials_t psk_cred = NULL;
gnutls_anon_server_credentials_t dh_cred = NULL;
gnutls_certificate_credentials_t cert_cred = NULL;
-const int ssl_session_cache = 128;
+const int ssl_session_cache = 2048;
static void wrap_db_init(void);
static void wrap_db_deinit(void);
@@ -125,6 +126,8 @@ static int wrap_db_store(void *dbf, gnutls_datum_t key,
gnutls_datum_t data);
static gnutls_datum_t wrap_db_fetch(void *dbf, gnutls_datum_t key);
static int wrap_db_delete(void *dbf, gnutls_datum_t key);
+static int wrap_db_add(void *dbf, gnutls_datum_t key,
+ gnutls_datum_t data);
static void cmd_parser(int argc, char **argv);
@@ -398,6 +401,7 @@ gnutls_session_t initialize_session(int dtls)
gnutls_db_set_retrieve_function(session, wrap_db_fetch);
gnutls_db_set_remove_function(session, wrap_db_delete);
gnutls_db_set_store_function(session, wrap_db_store);
+ gnutls_db_set_add_function(session, wrap_db_add);
gnutls_db_set_ptr(session, NULL);
}
@@ -405,6 +409,9 @@ gnutls_session_t initialize_session(int dtls)
gnutls_session_ticket_enable_server(session,
&session_ticket_key);
+ if (earlydata)
+ gnutls_anti_replay_enable(session, anti_replay);
+
if (sni_hostname != NULL)
gnutls_handshake_set_post_client_hello_function(session,
&post_client_hello);
@@ -1257,6 +1264,14 @@ int main(int argc, char **argv)
if (noticket == 0)
gnutls_session_ticket_key_generate(&session_ticket_key);
+ if (earlydata) {
+ ret = gnutls_anti_replay_init(&anti_replay);
+ if (ret < 0) {
+ fprintf(stderr, "Error while initializing anti-replay: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+
if (HAVE_OPT(MTU))
mtu = OPT_VALUE_MTU;
else
@@ -1653,6 +1668,9 @@ static void tcp_server(const char *name, int port)
if (noticket == 0)
gnutls_free(session_ticket_key.data);
+ if (earlydata)
+ gnutls_anti_replay_deinit(anti_replay);
+
if (nodb == 0)
wrap_db_deinit();
gnutls_global_deinit();
@@ -1746,50 +1764,86 @@ static void cmd_parser(int argc, char **argv)
/* session resuming support */
-#define SESSION_ID_SIZE 32
+#define SESSION_ID_SIZE 128
#define SESSION_DATA_SIZE (16*1024)
typedef struct {
- char session_id[SESSION_ID_SIZE];
+ unsigned char session_id[SESSION_ID_SIZE];
unsigned int session_id_size;
- char session_data[SESSION_DATA_SIZE];
- unsigned int session_data_size;
+ gnutls_datum_t session_data;
} CACHE;
static CACHE *cache_db;
-int cache_db_ptr = 0;
+static int cache_db_ptr;
+static int cache_db_alloc;
static void wrap_db_init(void)
{
- /* allocate cache_db */
- cache_db = calloc(1, ssl_session_cache * sizeof(CACHE));
}
static void wrap_db_deinit(void)
{
+ int i;
+
+ for (i = 0; i < cache_db_ptr; i++)
+ free(cache_db[i].session_data.data);
+ free(cache_db);
}
static int
wrap_db_store(void *dbf, gnutls_datum_t key, gnutls_datum_t data)
{
-
- if (cache_db == NULL)
- return -1;
+ int i;
+ time_t now = time(0);
if (key.size > SESSION_ID_SIZE)
- return -1;
+ return GNUTLS_E_DB_ERROR;
if (data.size > SESSION_DATA_SIZE)
- return -1;
+ return GNUTLS_E_DB_ERROR;
- memcpy(cache_db[cache_db_ptr].session_id, key.data, key.size);
- cache_db[cache_db_ptr].session_id_size = key.size;
+ if (cache_db_ptr < cache_db_alloc)
+ i = cache_db_ptr++;
+ else {
+ /* find empty or expired slot to store the new entry */
+ for (i = 0; i < cache_db_ptr; i++)
+ if (cache_db[i].session_id_size == 0 ||
+ !(now <
+ gnutls_db_check_entry_expire_time(&cache_db[i].
+ session_data)))
+ break;
+
+ if (i == cache_db_ptr) {
+ /* try to allocate additional slots */
+ if (cache_db_ptr == ssl_session_cache) {
+ fprintf(stderr,
+ "Error: too many sessions\n");
+ return GNUTLS_E_DB_ERROR;
+ }
+ cache_db_alloc = cache_db_alloc * 2 + 1;
+ cache_db = realloc(cache_db,
+ cache_db_alloc * sizeof(CACHE));
+ if (!cache_db)
+ return GNUTLS_E_MEMORY_ERROR;
+ memset(cache_db + cache_db_ptr, 0,
+ (cache_db_alloc - cache_db_ptr) * sizeof(CACHE));
+ cache_db_ptr++;
+ }
+ }
- memcpy(cache_db[cache_db_ptr].session_data, data.data, data.size);
- cache_db[cache_db_ptr].session_data_size = data.size;
+ memcpy(cache_db[i].session_id, key.data, key.size);
+ cache_db[i].session_id_size = key.size;
- cache_db_ptr++;
- cache_db_ptr %= ssl_session_cache;
+ /* resize the data slot if needed */
+ if (cache_db[i].session_data.size < data.size) {
+ cache_db[i].session_data.data =
+ realloc(cache_db[i].session_data.data,
+ data.size);
+ if (!cache_db[i].session_data.data)
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memcpy(cache_db[i].session_data.data, data.data, data.size);
+ cache_db[i].session_data.size = data.size;
return 0;
}
@@ -1797,22 +1851,22 @@ wrap_db_store(void *dbf, gnutls_datum_t key, gnutls_datum_t data)
static gnutls_datum_t wrap_db_fetch(void *dbf, gnutls_datum_t key)
{
gnutls_datum_t res = { NULL, 0 };
+ time_t now = time(0);
int i;
- if (cache_db == NULL)
- return res;
-
- for (i = 0; i < ssl_session_cache; i++) {
+ for (i = 0; i < cache_db_ptr; i++) {
if (key.size == cache_db[i].session_id_size &&
memcmp(key.data, cache_db[i].session_id,
- key.size) == 0) {
- res.size = cache_db[i].session_data_size;
+ key.size) == 0 &&
+ now < gnutls_db_check_entry_expire_time(&cache_db[i].
+ session_data)) {
+ res.size = cache_db[i].session_data.size;
- res.data = gnutls_malloc(res.size);
+ res.data = malloc(res.size);
if (res.data == NULL)
return res;
- memcpy(res.data, cache_db[i].session_data,
+ memcpy(res.data, cache_db[i].session_data.data,
res.size);
return res;
@@ -1825,20 +1879,37 @@ static int wrap_db_delete(void *dbf, gnutls_datum_t key)
{
int i;
- if (cache_db == NULL)
- return -1;
-
- for (i = 0; i < ssl_session_cache; i++) {
- if (key.size == (unsigned int) cache_db[i].session_id_size
- && memcmp(key.data, cache_db[i].session_id,
- key.size) == 0) {
+ for (i = 0; i < cache_db_ptr; i++) {
+ if (key.size == cache_db[i].session_id_size &&
+ memcmp(key.data, cache_db[i].session_id,
+ key.size) == 0) {
cache_db[i].session_id_size = 0;
- cache_db[i].session_data_size = 0;
+ free(cache_db[i].session_data.data);
+ cache_db[i].session_data.data = NULL;
+ cache_db[i].session_data.size = 0;
return 0;
}
}
- return -1;
+ return GNUTLS_E_DB_ERROR;
+}
+
+static int
+wrap_db_add(void *dbf, gnutls_datum_t key, gnutls_datum_t data)
+{
+ time_t now = time(0);
+ int i;
+
+ for (i = 0; i < cache_db_ptr; i++) {
+ if (key.size == cache_db[i].session_id_size &&
+ memcmp(key.data, cache_db[i].session_id,
+ key.size) == 0 &&
+ now < gnutls_db_check_entry_expire_time(&cache_db[i].
+ session_data))
+ return GNUTLS_E_DB_ENTRY_EXISTS;
+ }
+
+ return wrap_db_store(dbf, key, data);
}