summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-01-11 11:40:46 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-01-11 11:40:46 +0000
commit4136be371aa30706e6390fd6a94ef9a1b5271ee6 (patch)
tree3e042eaac309fce253cdc775bd3703ff8569eace /lib
parent1c75aebb022ab287f911b9e16014a6cc96601446 (diff)
downloadgnutls-4136be371aa30706e6390fd6a94ef9a1b5271ee6.tar.gz
added server side session resuming (using gdbm)
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/gnutls.c8
-rw-r--r--lib/gnutls.h3
-rw-r--r--lib/gnutls_algorithms.c2
-rw-r--r--lib/gnutls_errors.c2
-rw-r--r--lib/gnutls_errors.h2
-rw-r--r--lib/gnutls_handshake.c100
-rw-r--r--lib/gnutls_handshake.h2
-rw-r--r--lib/gnutls_int.h4
-rw-r--r--lib/gnutls_session.c8
10 files changed, 89 insertions, 46 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 406132bf99..b5e974c807 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,12 +2,12 @@ include_HEADERS = gnutls.h
EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h \
gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h \
gnutls_handshake.h gnutls_num.h gnutls_algorithms.h gnutls_dh.h \
- gnutls_kx.h gnutls_hash_int.h gnutls_cipher_int.h \
+ gnutls_kx.h gnutls_hash_int.h gnutls_cipher_int.h gnutls_db.h \
gnutls_cert.lex gnutls_compress_int.h gnutls_session.h gnutls_priority.h
lib_LTLIBRARIES = libgnutls.la
libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \
gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c \
gnutls_errors.c gnutls_algorithms.c gnutls_dh.c gnutls_kx.c \
gnutls_priority.c gnutls_hash_int.c gnutls_cipher_int.c \
- gnutls_compress_int.c gnutls_session.c
+ gnutls_compress_int.c gnutls_session.c gnutls_db.c
libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
diff --git a/lib/gnutls.c b/lib/gnutls.c
index 197916d42c..1e48b1e6cb 100644
--- a/lib/gnutls.c
+++ b/lib/gnutls.c
@@ -133,6 +133,13 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end)
(*state)->security_parameters.session_id_size = 0;
(*state)->gnutls_internals.resumed_security_parameters.session_id_size = 0;
(*state)->gnutls_internals.resumed = RESUME_FALSE;
+
+ (*state)->gnutls_internals.expire_time = 3600; /* one hour default */
+
+ (*state)->security_parameters.timestamp = 0;
+
+ /* gdbm db */
+ (*state)->gnutls_internals.db_name = NULL;
gnutls_set_lowat((*state), 1); /* the default for tcp */
@@ -176,6 +183,7 @@ int gnutls_deinit(GNUTLS_STATE * state)
if ((*state)->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority!=NULL)
gnutls_free((*state)->gnutls_internals.BulkCipherAlgorithmPriority.algorithm_priority);
+ gnutls_free((*state)->gnutls_internals.db_name);
gnutls_free(*state);
return 0;
diff --git a/lib/gnutls.h b/lib/gnutls.h
index 952fe244b6..9607cc9eb0 100644
--- a/lib/gnutls.h
+++ b/lib/gnutls.h
@@ -93,6 +93,9 @@ int gnutls_get_current_session( GNUTLS_STATE state, void* session, int *session_
int gnutls_get_current_session_id( GNUTLS_STATE state, void* session, int *session_size);
int gnutls_set_lowat( GNUTLS_STATE state, int num);
+int gnutls_set_cache_expiration( GNUTLS_STATE state, int seconds);
+int gnutls_set_db_name( GNUTLS_STATE state, char* filename);
+int gnutls_clean_db( GNUTLS_STATE state);
/* these are deprecated must be replaced by gnutls_errors.h */
#define GNUTLS_E_MAC_FAILED -1
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index cc7fdba27a..c8d43d5c7b 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -935,7 +935,7 @@ _gnutls_supported_ciphersuites(GNUTLS_STATE state,
tmp_ciphers[i].CipherSuite[1] =
cs_algorithms[i].id.CipherSuite[1];
}
-fprintf(stderr, "COUNT: %d\n",count);
+
for (i = 0; i < count; i++) {
if (_gnutls_kx_priority
(state,
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 50434de450..598db1f640 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -62,7 +62,9 @@ static gnutls_error_entry error_algorithms[] = {
GNUTLS_ERROR_ENTRY( GNUTLS_E_COMPRESSION_FAILED, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_MEMORY_ERROR, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNIMPLEMENTED_FEATURE, 1),
+ GNUTLS_ERROR_ENTRY( GNUTLS_E_EXPIRED, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_AGAIN, 0),
+ GNUTLS_ERROR_ENTRY( GNUTLS_E_DB_ERROR, 1),
{0}
};
diff --git a/lib/gnutls_errors.h b/lib/gnutls_errors.h
index 6520958749..251b20ed47 100644
--- a/lib/gnutls_errors.h
+++ b/lib/gnutls_errors.h
@@ -28,6 +28,8 @@
#define GNUTLS_E_DECOMPRESSION_FAILED -26
#define GNUTLS_E_COMPRESSION_FAILED -27
#define GNUTLS_E_AGAIN -28
+#define GNUTLS_E_EXPIRED -29
+#define GNUTLS_E_DB_ERROR -30
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -50
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index ee9a3aa613..ef9bea47b0 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -32,6 +32,7 @@
#include "gnutls_handshake.h"
#include "gnutls_num.h"
#include "gnutls_hash_int.h"
+#include "gnutls_db.h"
#ifdef DEBUG
#define ERR(x, y) fprintf(stderr, "GNUTLS Error: %s (%d)\n", x,y)
@@ -278,7 +279,6 @@ int _gnutls_send_handshake(int cd, GNUTLS_STATE state, void *i_data,
uint32 datasize;
int pos = 0;
-
#ifdef WORDS_BIGENDIAN
datasize = i_datasize;
#else
@@ -473,7 +473,7 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
char *rand;
char *data = NULL;
uint8 session_id_len, z;
- uint32 cur_time;
+ time_t cur_time;
int pos = 0;
GNUTLS_CipherSuite *cipher_suites;
uint8 *compression_methods;
@@ -484,7 +484,6 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
if (SessionID == NULL)
session_id_len = 0;
- rand = gcry_random_bytes(28, GCRY_STRONG_RANDOM);
if (state->security_parameters.entity == GNUTLS_CLIENT) {
@@ -503,8 +502,13 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
#endif
memmove(state->security_parameters.client_random,
&cur_time, 4);
+
+ rand = gcry_random_bytes(28, GCRY_STRONG_RANDOM);
memmove(&state->security_parameters.client_random[4], rand,
28);
+ gcry_free(rand);
+
+ state->security_parameters.timestamp = time(0);
memmove(&data[pos], state->security_parameters.client_random, 32);
pos += 32;
@@ -558,25 +562,14 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
} else { /* SERVER */
- datalen = 2 + sizeof(uint32) + session_id_len + 1 + 28;
+ datalen = 2 + session_id_len + 1 + 32;
data = gnutls_malloc(datalen);
data[pos++] = state->connection_state.version.major;
data[pos++] = state->connection_state.version.minor;
-#ifdef WORDS_BIGENDIAN
- cur_time = time(NULL);
-#else
- cur_time = byteswap32(time(NULL));
-#endif
- memmove(state->security_parameters.server_random,
- &cur_time, 4);
- memmove(&state->security_parameters.server_random[4], rand,
- 28);
- memmove(&data[pos], &cur_time, sizeof(uint32));
- pos += sizeof(uint32);
- memmove(&data[pos], rand, 28);
- pos += 28;
+ memmove( &data[pos], state->security_parameters.server_random, 32);
+ pos += 32;
memmove(&data[pos++], &session_id_len, sizeof(uint8));
if (session_id_len > 0) {
@@ -603,8 +596,6 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque * SessionID,
}
- gcry_free(rand);
-
return ret;
}
@@ -622,7 +613,9 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen)
int i, ret=0;
uint16 x, sizeOfSuites;
GNUTLS_Version version;
-
+ time_t cur_time;
+ char* rand;
+
if (state->security_parameters.entity == GNUTLS_CLIENT) {
if (datalen < 38) {
gnutls_assert();
@@ -661,10 +654,6 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen)
if ( (state->gnutls_internals.resumed_security_parameters.session_id_size > 0)
&& memcmp(&data[pos], state->gnutls_internals.resumed_security_parameters.session_id, session_id_len)==0) {
/* resume session */
-
-#ifdef DEBUG
- fprintf(stderr, "Resuming session\n");
-#endif
memcpy( state->gnutls_internals.resumed_security_parameters.server_random, state->security_parameters.server_random, 32);
memcpy( state->gnutls_internals.resumed_security_parameters.client_random, state->security_parameters.client_random, 32);
@@ -675,6 +664,7 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen)
state->gnutls_internals.resumed=RESUME_FALSE; /* we are not resuming */
state->security_parameters.session_id_size = session_id_len;
memcpy( state->security_parameters.session_id, &data[pos], session_id_len);
+
}
pos += session_id_len;
@@ -745,16 +735,42 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char *data, int datalen)
memmove(state->security_parameters.client_random,
&data[pos], 32);
- pos += 32;
+ pos+=32;
+
+ /* generate server random value */
+#ifdef WORDS_BIGENDIAN
+ cur_time = time(NULL);
+#else
+ cur_time = byteswap32(time(NULL));
+#endif
+ memmove(state->security_parameters.server_random,
+ &cur_time, 4);
+ rand = gcry_random_bytes(28, GCRY_STRONG_RANDOM);
+ memmove(&state->security_parameters.server_random[4], rand,
+ 28);
+ gcry_free(rand);
+ state->security_parameters.timestamp = time(NULL);
memmove(&session_id_len, &data[pos++], 1);
- pos += session_id_len;
- /* We should resume an old connection here. This is not
- * implemented yet.
- */
+ /* RESUME SESSION */
+ if (session_id_len > 32) return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+ ret = _gnutls_server_restore_session( state, &data[pos], session_id_len);
+ pos += session_id_len;
+
+ if (ret==0) { /* resumed! */
+ /* get the new random values */
+ memcpy( state->gnutls_internals.resumed_security_parameters.server_random, state->security_parameters.server_random, 32);
+ memcpy( state->gnutls_internals.resumed_security_parameters.client_random, state->security_parameters.client_random, 32);
+ state->gnutls_internals.resumed = RESUME_TRUE;
+ return 0;
+ } else {
+ _gnutls_generate_session_id(state->security_parameters.session_id, &state->security_parameters.session_id_size);
+ state->gnutls_internals.resumed = RESUME_FALSE;
+ }
+
/* Select a ciphersuite */
memmove(&sizeOfSuites, &data[pos], 2);
pos += 2;
@@ -852,8 +868,6 @@ int gnutls_handshake(int cd, GNUTLS_STATE state) {
int gnutls_handshake_begin(int cd, GNUTLS_STATE state)
{
int ret;
- char *session_id;
- uint8 session_id_size;
if (state->security_parameters.entity == GNUTLS_CLIENT) {
#ifdef HARD_DEBUG
@@ -897,20 +911,20 @@ int gnutls_handshake_begin(int cd, GNUTLS_STATE state)
return ret;
}
- _gnutls_generate_session_id(&session_id, &session_id_size);
ret =
- _gnutls_send_hello(cd, state, session_id,
- session_id_size);
+ _gnutls_send_hello(cd, state, state->security_parameters.session_id,
+ state->security_parameters.session_id_size);
if (ret < 0) {
ERR("send hello", ret);
gnutls_clearHashDataBuffer( state);
return ret;
}
- gnutls_free(session_id);
/* FIXME: send our certificate - if required */
-
+ /* NOTE: these should not be send if we are resuming */
+
/* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */
+ if (state->gnutls_internals.resumed==RESUME_FALSE)
ret = _gnutls_send_server_kx_message(cd, state);
if (ret < 0) {
ERR("send server kx", ret);
@@ -1047,6 +1061,7 @@ int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
} else { /* SERVER SIDE */
/* send the server hello done */
+ if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
ret =
_gnutls_send_handshake(cd, state, NULL, 0,
GNUTLS_SERVER_HELLO_DONE);
@@ -1058,6 +1073,7 @@ int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
/* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */
+ if (state->gnutls_internals.resumed==RESUME_FALSE) /* if we are not resuming */
ret = _gnutls_recv_client_kx_message(cd, state);
if (ret < 0) {
ERR("recv client kx", ret);
@@ -1065,6 +1081,7 @@ int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
return ret;
}
+
}
/* send and recv the change cipher spec and finished messages */
@@ -1102,6 +1119,10 @@ int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
}
}
+ if (state->security_parameters.entity == GNUTLS_SERVER) {
+ /* in order to support session resuming */
+ _gnutls_server_register_current_session( state);
+ }
/* clear handshake buffer */
gnutls_clearHashDataBuffer( state);
@@ -1109,18 +1130,17 @@ int gnutls_handshake_finish(int cd, GNUTLS_STATE state)
}
-int _gnutls_generate_session_id(char **session_id, uint8 * len)
+int _gnutls_generate_session_id(char *session_id, uint8 * len)
{
char *rand;
- *session_id = gnutls_malloc(32);
rand = gcry_random_bytes(32, GCRY_WEAK_RANDOM);
- memmove(*session_id, rand, 32);
+ memmove(session_id, rand, 32);
gcry_free(rand);
*len = 32;
#ifdef HARD_DEBUG
- fprintf(stderr, "SessionID: %s\n", _gnutls_bin2hex(*session_id, 32));
+ fprintf(stderr, "SessionID: %s\n", _gnutls_bin2hex(session_id, 32));
#endif
return 0;
}
diff --git a/lib/gnutls_handshake.h b/lib/gnutls_handshake.h
index cc00ce6628..b7e0708f9a 100644
--- a/lib/gnutls_handshake.h
+++ b/lib/gnutls_handshake.h
@@ -4,7 +4,7 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state, opaque* SessionID, uint8 Sess
int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char* data, int datalen);
int gnutls_handshake(int cd, GNUTLS_STATE state);
int _gnutls_recv_handshake( int cd, GNUTLS_STATE state, uint8**, int*, HandshakeType);
-int _gnutls_generate_session_id( char** session_id, uint8* len);
+int _gnutls_generate_session_id( char* session_id, uint8* len);
int _gnutls_recv_certificate(int cd, GNUTLS_STATE state, char *data, int datalen);
int gnutls_handshake_begin(int cd, GNUTLS_STATE state);
int gnutls_handshake_finish(int cd, GNUTLS_STATE state);
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index a203d20b8c..7c8c2a68ac 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -126,6 +126,7 @@ typedef struct {
opaque server_random[32];
opaque session_id[32];
uint8 session_id_size;
+ time_t timestamp;
} SecurityParameters;
typedef struct {
@@ -206,6 +207,9 @@ typedef struct {
int certificate_verify_needed; /* non zero if we should expect for certificate verify */
/* sockets internals */
int lowat;
+ /* gdbm */
+ char* db_name;
+ int expire_time;
} GNUTLS_INTERNALS;
typedef struct {
diff --git a/lib/gnutls_session.c b/lib/gnutls_session.c
index 16388fba9a..9fe4c92f5d 100644
--- a/lib/gnutls_session.c
+++ b/lib/gnutls_session.c
@@ -20,6 +20,7 @@
#include <defines.h>
#include "gnutls_int.h"
#include "gnutls_errors.h"
+#include "debug.h"
/* Returns all session parameters - in order to support resuming.
* The client should call this - and keep the returned session - if he wants to resume his
@@ -65,7 +66,10 @@ int gnutls_set_current_session( GNUTLS_STATE state, void* session, int session_s
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
}
- memcpy( &state->gnutls_internals.resumed_security_parameters, session, sizeof(SecurityParameters));
-
+ if ( time(0) - ((SecurityParameters*)session)->timestamp <= state->gnutls_internals.expire_time) {
+ memcpy( &state->gnutls_internals.resumed_security_parameters, session, sizeof(SecurityParameters));
+ } else {
+ return GNUTLS_E_EXPIRED;
+ }
return 0;
}