diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-01-11 11:40:46 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-01-11 11:40:46 +0000 |
commit | 4136be371aa30706e6390fd6a94ef9a1b5271ee6 (patch) | |
tree | 3e042eaac309fce253cdc775bd3703ff8569eace | |
parent | 1c75aebb022ab287f911b9e16014a6cc96601446 (diff) | |
download | gnutls-4136be371aa30706e6390fd6a94ef9a1b5271ee6.tar.gz |
added server side session resuming (using gdbm)
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | doc/API | 11 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/gnutls.c | 8 | ||||
-rw-r--r-- | lib/gnutls.h | 3 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 2 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 2 | ||||
-rw-r--r-- | lib/gnutls_errors.h | 2 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 100 | ||||
-rw-r--r-- | lib/gnutls_handshake.h | 2 | ||||
-rw-r--r-- | lib/gnutls_int.h | 4 | ||||
-rw-r--r-- | lib/gnutls_session.c | 8 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/cli.c | 2 | ||||
-rw-r--r-- | src/port.h | 2 | ||||
-rw-r--r-- | src/serv.c | 3 |
17 files changed, 112 insertions, 51 deletions
@@ -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. @@ -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) @@ -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); |