summaryrefslogtreecommitdiff
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
parent1c75aebb022ab287f911b9e16014a6cc96601446 (diff)
downloadgnutls-4136be371aa30706e6390fd6a94ef9a1b5271ee6.tar.gz
added server side session resuming (using gdbm)
-rw-r--r--NEWS5
-rw-r--r--configure.in1
-rw-r--r--doc/API11
-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
-rw-r--r--src/Makefile.am4
-rw-r--r--src/cli.c2
-rw-r--r--src/port.h2
-rw-r--r--src/serv.c3
17 files changed, 112 insertions, 51 deletions
diff --git a/NEWS b/NEWS
index 59fcb641fd..292fb75404 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,7 @@
-Version 0.0.6
+Version 0.0.7
+- Added server side session resuming (using gdbm)
+
+Version 0.0.6 (20/12/2000)
- Added client side session resuming
- Better documentation (check doc/API)
- Better socket handling (gnutls can be used with select())
diff --git a/configure.in b/configure.in
index 3aef18c781..5db5936ffd 100644
--- a/configure.in
+++ b/configure.in
@@ -128,6 +128,7 @@ AC_CHECK_HEADERS(termios.h termio.h sgtty.h)
AC_CHECK_FUNCS(bzero signal sigaction memset fcntl fsync siglongjmp,,)
AC_CHECK_FUNCS(lstat stat umask utime memmove bcopy getpwuid waitpid,,)
+AC_CHECK_LIB(gdbm, gdbm_open,, AC_MSG_WARN("GDBM was not found. You will not be able to use Server side Session Resuming."))
AC_CHECK_LIB(z, compress,,AC_MSG_WARN("ZLIB was not found. You will not be able to use ZLIB compression."))
dnl Checks for libraries.
diff --git a/doc/API b/doc/API
index 543d77f85c..aefd0298ab 100644
--- a/doc/API
+++ b/doc/API
@@ -130,3 +130,14 @@ int gnutls_set_lowat( GNUTLS_STATE state, int num);
if there are pending data to socket buffer. Used only
if you have changed the default low water value (default is 1).
Normally you will not need that function.
+
+int gnutls_set_cache_expiration( GNUTLS_STATE state, int seconds);
+ Sets the expiration time for resumed sessions.
+
+int gnutls_set_db_name( GNUTLS_STATE state, char* filename);
+ Sets the name of the (gdbm) database to be used to keep
+ the sessions to be resumed.
+
+int gnutls_clean_db( GNUTLS_STATE state);
+ Deletes all the records in the db. This db may become huge
+ if this is not called.
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;
}
diff --git a/src/Makefile.am b/src/Makefile.am
index 34769a9c75..dc4bd9abf3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
EXTRA_DIST = port.h
noinst_PROGRAMS = serv cli
serv_SOURCES = serv.c
-serv_LDADD = ../lib/libgnutls.la -lgcrypt
+serv_LDADD = ../lib/libgnutls.la $(GCRYPT_LIBS)
cli_SOURCES = cli.c
-cli_LDADD = ../lib/libgnutls.la -lgcrypt
+cli_LDADD = ../lib/libgnutls.la $(GCRYPT_LIBS)
diff --git a/src/cli.c b/src/cli.c
index 5c4f0b5a32..d66c9c9ba4 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -204,7 +204,7 @@ int main()
continue;
}
gnutls_write( sd, state, buffer, strlen(buffer));
- fprintf(stdout, "- Sended: %d bytes\n", strlen(buffer));
+ fprintf(stdout, "- Sent: %d bytes\n", strlen(buffer));
}
}
if (user_term!=0) gnutls_close(sd, state);
diff --git a/src/port.h b/src/port.h
index 003fa6f42e..696b48cb7d 100644
--- a/src/port.h
+++ b/src/port.h
@@ -1,2 +1,2 @@
-#define PORT 5555
+#define PORT 5556
#define SERVER "127.0.0.1"
diff --git a/src/serv.c b/src/serv.c
index 4265ea4db3..c0e3fbe803 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -58,9 +58,12 @@ int main()
err = listen(listen_sd, 1024);
ERR(err, "listen");
+
+
client_len = sizeof(sa_cli);
for (;;) {
gnutls_init(&state, GNUTLS_SERVER);
+ gnutls_set_db_name(state, "/tmp/gdb");
gnutls_set_cipher_priority( state, 4, GNUTLS_TWOFISH, GNUTLS_RIJNDAEL, GNUTLS_3DES, GNUTLS_ARCFOUR);
gnutls_set_compression_priority( state, 2, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION);
gnutls_set_kx_priority( state, 1, GNUTLS_KX_ANON_DH);