]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
added hooks in order to use external database to store session to be
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 2 Nov 2001 10:07:05 +0000 (10:07 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Fri, 2 Nov 2001 10:07:05 +0000 (10:07 +0000)
resumed. Works but it is not finished.

NEWS
THANKS
configure.in
lib/gnutls.h.in
lib/gnutls_db.c
lib/gnutls_db.h
lib/gnutls_int.h
lib/gnutls_record.c

diff --git a/NEWS b/NEWS
index 959f4186e11e878a238192fbe77d0dc01c203fab..c056339091435b808d330eac53d1726452c10d91 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Version 0.2.10
+- Corrected bugs in non blocking IO
+- Added hooks to use external database to store sessions.
+
 Version 0.2.9 (27/10/2001)
 - AUTH_INFO types and structures were moved to library internals
 - AUTH_FAILED is no longer returned in SRP authentication
diff --git a/THANKS b/THANKS
index f6c84602cb552f08165128a8f6bd2777594d4a6b..e390f5b31b35dd443b0dfab9bd933e6ef854985a 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -4,3 +4,4 @@ Neil Spring <nspring@saavie.org>
 
 Paul Sheer <psheer@icon.co.za>
 
+Jon Nelson <jnelson@securepipe.com>
index dfc65a693bf9b46388791373002dc89c2dcb6646..86e53dbf2af34ce5e23122eb185e43837d1380a9 100644 (file)
@@ -11,7 +11,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os")
 
 GNUTLS_MAJOR_VERSION=0
 GNUTLS_MINOR_VERSION=2
-GNUTLS_MICRO_VERSION=9
+GNUTLS_MICRO_VERSION=10
 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION
 
 AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION")
index 1214994234994f1c3696337908c36a60a6e7aa11..f17bb0f5e8bc39a0d317326fa905bab640ebe6ad 100644 (file)
@@ -136,10 +136,18 @@ int gnutls_get_current_session( GNUTLS_STATE state, void* session, int *session_
 /* returns the session ID */
 int gnutls_get_current_session_id( GNUTLS_STATE state, void* session, int *session_size);
 
+typedef int (*DB_STORE_FUNC)(void*, gnutls_datum key, gnutls_datum data);
+typedef int (*DB_REMOVE_FUNC)(void*, gnutls_datum key);
+typedef gnutls_datum (*DB_RETR_FUNC)(void*, gnutls_datum key);
+
 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);
+void gnutls_set_db_retrieve_func( GNUTLS_STATE, DB_RETR_FUNC);
+void gnutls_set_db_remove_func( GNUTLS_STATE, DB_REMOVE_FUNC);
+void gnutls_set_db_store_func( GNUTLS_STATE, DB_STORE_FUNC);
+void gnutls_set_db_ptr( GNUTLS_STATE, void* db_ptr);
 
 void gnutls_set_max_handshake_data_buffer_size( GNUTLS_STATE state, int max);
 
@@ -222,9 +230,11 @@ int gnutls_dh_generate_params( gnutls_datum* prime, gnutls_datum* generator, int
 
 typedef ssize_t (*PULL_FUNC)(SOCKET, void*, size_t);
 typedef ssize_t (*PUSH_FUNC)(SOCKET, const void*, size_t);
+
 typedef void (*LOG_FUNC)( const char*);
 
-void gnutls_global_set_push_func( PUSH_FUNC push_func);
-void gnutls_global_set_pull_func( PULL_FUNC pull_func);
+void gnutls_set_push_func( GNUTLS_STATE, PUSH_FUNC push_func);
+void gnutls_set_pull_func( GNUTLS_STATE, PULL_FUNC pull_func);
+
 
 
index 0ed1f73539bc3e80eed07c567f991ffa9c79aef0..0a2da720d8e5a90884d1e295439ad6ebc7348abe 100644 (file)
@@ -24,6 +24,7 @@
 #include "gnutls_int.h"
 #include "gnutls_errors.h"
 #include "gnutls_session.h"
+#include <gnutls_db.h>
 #include "debug.h"
 
 #ifdef HAVE_LIBGDBM
        GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
 #endif
 
+/**
+  * gnutls_set_db_retrieve_function - Sets the function that will be used to get data
+  * @state: is a &GNUTLS_STATE structure.
+  * @retr_func: is the function.
+  *
+  * Sets the function that will be used to retrieve data from the resumed
+  * sessions database. This function must return 0 on success.
+  * This function should only be used if you do
+  * not plan to use the included gdbm backend.
+  *
+  * The first argument to store_func() will be null unless gnutls_db_set_db_ptr() 
+  * has been called.
+  *
+  **/
+void gnutls_set_db_retrieve_function( GNUTLS_STATE state, DB_RETR_FUNC retr_func) {
+       state->gnutls_internals.db_retrieve_func = retr_func;
+}
+
+/**
+  * gnutls_set_db_remove_function - Sets the function that will be used to remove data
+  * @state: is a &GNUTLS_STATE structure.
+  * @rem_func: is the function.
+  *
+  * Sets the function that will be used to remove data from the resumed
+  * sessions database. This function must return 0 on success.
+  * This function should only be used if you do
+  * not plan to use the included gdbm backend.
+  *
+  * The first argument to rem_func() will be null unless gnutls_db_set_db_ptr() 
+  * has been called.
+  *
+  **/
+void gnutls_set_db_remove_function( GNUTLS_STATE state, DB_REMOVE_FUNC rem_func) {
+       state->gnutls_internals.db_remove_func = rem_func;
+}
+
+/**
+  * gnutls_set_db_store_function - Sets the function that will be used to put data
+  * @state: is a &GNUTLS_STATE structure.
+  * @store_func: is the function
+  *
+  * Sets the function that will be used to store data from the resumed
+  * sessions database. This function must remove 0 on success. 
+  * This function should only be used if you do
+  * not plan to use the included gdbm backend.
+  *
+  * The first argument to store_func() will be null unless gnutls_db_set_ptr() 
+  * has been called.
+  *
+  **/
+void gnutls_set_db_store_function( GNUTLS_STATE state, DB_STORE_FUNC store_func) {
+       state->gnutls_internals.db_store_func = store_func;
+}
+
+/**
+  * gnutls_set_db_ptr - Sets a pointer to be sent to db functions
+  * @state: is a &GNUTLS_STATE structure.
+  * @ptr: is the pointer
+  *
+  * Sets the pointer that will be sent to store and retrieve functions, as
+  * the first argument.
+  *
+  **/
+void gnutls_set_db_ptr( GNUTLS_STATE state, void* ptr) {
+       state->gnutls_internals.db_ptr = ptr;
+}
+
 /**
   * gnutls_set_cache_expiration - Sets the expiration time for resumed sessions.
   * @state: is a &GNUTLS_STATE structure.
@@ -55,6 +123,9 @@ int gnutls_set_cache_expiration( GNUTLS_STATE state, int seconds) {
   * Sets the name of the (gdbm) database to be used to keep
   * the sessions to be resumed. This function also creates the database
   * - if it does not exist - and opens it for reading.
+  * You should not call this function if using an other backend
+  * than gdbm (ie. called function gnutls_set_db_store_func() etc.)
+  *
   **/
 int gnutls_set_db_name( GNUTLS_STATE state, char* filename) {
 #ifdef HAVE_LIBGDBM
@@ -100,7 +171,9 @@ GDBM_FILE dbf;
   *
   * This function Deletes all expired records in the resumed sessions' database. 
   * This database may become huge if this function is not called.
-  * (this function is also quite expensive)
+  * This function is also quite expensive. This function should only
+  * be called if using the gdbm backend.
+  *
   **/
 int gnutls_clean_db( GNUTLS_STATE state) {
 #ifdef HAVE_LIBGDBM
@@ -111,7 +184,7 @@ time_t timestamp;
 
        if (GNUTLS_DBF==NULL) return GNUTLS_E_DB_ERROR;
        if (GNUTLS_DBNAME==NULL) return GNUTLS_E_DB_ERROR;
-       
+
        dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_WRITER, 0600, NULL);
        if (dbf==NULL) return GNUTLS_E_AGAIN;
        key = gdbm_firstkey(dbf);
@@ -147,103 +220,206 @@ time_t timestamp;
  */
 int _gnutls_server_register_current_session( GNUTLS_STATE state)
 {
-#ifdef HAVE_LIBGDBM
-GDBM_FILE dbf;
-datum key = { state->security_parameters.session_id, state->security_parameters.session_id_size };
-datum content;
+gnutls_datum key = { state->security_parameters.session_id, state->security_parameters.session_id_size };
+gnutls_datum content;
 int ret = 0, pos;
 
        if (state->gnutls_internals.resumable==RESUME_FALSE) 
                return GNUTLS_E_INVALID_SESSION;
 
-       if (GNUTLS_DBNAME==NULL)
-               return GNUTLS_E_DB_ERROR;
-
        if (state->security_parameters.session_id==NULL || state->security_parameters.session_id_size==0)
                return GNUTLS_E_INVALID_SESSION;
 
-       /* if we can't read why bother writing? */
-       if (GNUTLS_DBF==NULL)
-               return GNUTLS_E_DB_ERROR;
-
 /* allocate space for data */
-       content.dsize = sizeof(SecurityParameters) + state->gnutls_key->auth_info_size
+       content.size = sizeof(SecurityParameters) + state->gnutls_key->auth_info_size
                + sizeof(state->gnutls_key->auth_info_size);
-       content.dptr = gnutls_malloc( content.dsize);
-       if (content.dptr==NULL) return GNUTLS_E_MEMORY_ERROR;
+       content.data = gnutls_malloc( content.size);
+       if (content.data==NULL) return GNUTLS_E_MEMORY_ERROR;
 
 /* copy data */
        pos = 0;
-       memcpy( &content.dptr[0], (void*)&state->security_parameters, sizeof(SecurityParameters));
+       memcpy( &content.data[0], (void*)&state->security_parameters, sizeof(SecurityParameters));
        pos+=sizeof(SecurityParameters);
-       
-       memcpy( &content.dptr[pos], &state->gnutls_key->auth_info_size,  sizeof(state->gnutls_key->auth_info_size));
+
+       memcpy( &content.data[pos], &state->gnutls_key->auth_info_size,  sizeof(state->gnutls_key->auth_info_size));
        pos+=sizeof(state->gnutls_key->auth_info_size);
-       
-       memcpy( &content.dptr[pos], state->gnutls_key->auth_info, state->gnutls_key->auth_info_size);
 
-       dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_WRITER, 0600, NULL);
-       if (dbf==NULL) {
-               gnutls_free(content.dptr);
-               /* cannot open db for writing. This may happen if multiple
-                * instances try to write. 
-                */
-               return GNUTLS_E_AGAIN;
-       }
-       ret = gdbm_store( dbf, key, content, GDBM_INSERT);
+       memcpy( &content.data[pos], state->gnutls_key->auth_info, state->gnutls_key->auth_info_size);
 
-       gnutls_free( content.dptr);
+       ret = _gnutls_store_session( state, key, content);
 
-       gdbm_close(dbf);
-       return (ret == 0 ? ret : GNUTLS_E_UNKNOWN_ERROR);
-#else
-       return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-#endif
+       gnutls_free( content.data);
+
+       return ret;
 }
 
 int _gnutls_server_restore_session( GNUTLS_STATE state, uint8* session_id, int session_id_size)
 {
-#ifdef HAVE_LIBGDBM
-datum content;
-datum key = { session_id, session_id_size};
+gnutls_datum data;
+gnutls_datum key = { session_id, session_id_size };
 int ret;
 
-       if (GNUTLS_DBNAME==NULL) return GNUTLS_E_DB_ERROR;
+       data = _gnutls_retrieve_session( state, key);
 
-       if (GNUTLS_DBF==NULL) return GNUTLS_E_DB_ERROR;
-       content = gdbm_fetch( GNUTLS_DBF, key);
-
-       if (content.dptr==NULL) {
+       if (data.data==NULL) {
                return GNUTLS_E_INVALID_SESSION;
        }
 
        /* expiration check is performed inside */
-       ret = gnutls_set_current_session( state, content.dptr, content.dsize);
-       free(content.dptr);
+       ret = gnutls_set_current_session( state, data.data, data.size);
+       free(data.data);
 
-       return ret;
-#else
-       return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-#endif
+       return 0;
 }
 
 int _gnutls_db_remove_session( GNUTLS_STATE state, uint8* session_id, int session_id_size)
 {
+gnutls_datum key = { session_id, session_id_size };
+
+       return _gnutls_remove_session( state, key);
+}
+
+
+/* Checks if both db_store and db_retrieve functions have
+ * been set up.
+ */
+static int _gnutls_db_func_is_ok( GNUTLS_STATE state) {
+       if (state->gnutls_internals.db_store_func!=NULL &&
+               state->gnutls_internals.db_retrieve_func!=NULL &&
+               state->gnutls_internals.db_remove_func!=NULL) return 0;
+       else return GNUTLS_E_DB_ERROR;
+}
+
+
+
+/* Stores session data to the db backend.
+ */
+int _gnutls_store_session( GNUTLS_STATE state, gnutls_datum session_id, gnutls_datum session_data)
+{
 #ifdef HAVE_LIBGDBM
 GDBM_FILE dbf;
-datum key = { session_id, session_id_size};
-int ret;
+datum key = { session_id.data, session_id.size };
+datum content = {session_data.data, session_data.size};
+#endif
+int ret = 0;
 
-       if (GNUTLS_DBNAME==NULL) return GNUTLS_E_DB_ERROR;
+       if (state->gnutls_internals.resumable==RESUME_FALSE) 
+               return GNUTLS_E_INVALID_SESSION;
 
-       dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
-       if (dbf==NULL) return GNUTLS_E_AGAIN;
-       ret = gdbm_delete( dbf, key);
-       gdbm_close(dbf);
+       if (GNUTLS_DBNAME==NULL && _gnutls_db_func_is_ok(state)!=0) {
+               return GNUTLS_E_DB_ERROR;
+       }
+       
+       if (session_id.data==NULL || session_id.size==0)
+               return GNUTLS_E_INVALID_SESSION;
+
+       if (session_data.data==NULL || session_data.size==0)
+               return GNUTLS_E_INVALID_SESSION;
 
-       return (ret==0 ? ret : GNUTLS_E_DB_ERROR);
+       /* if we can't read why bother writing? */
+       if (GNUTLS_DBF==NULL) { /* use external backend. */
+               
+               ret = state->gnutls_internals.db_store_func( state->gnutls_internals.db_ptr, session_id, session_data);
+       
+       } else { /* use gdbm */
+#ifdef HAVE_LIBGDBM
+               dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_WRITER, 0600, NULL);
+               if (dbf==NULL) {
+                       /* cannot open db for writing. This may happen if multiple
+                        * instances try to write. 
+                        */
+                       return GNUTLS_E_AGAIN;
+               }
+               ret = gdbm_store( dbf, key, content, GDBM_INSERT);
+
+               gdbm_close(dbf);
 #else
-       return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+               return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+#endif
+       }
+
+
+       return (ret == 0 ? ret : GNUTLS_E_DB_ERROR);
+
+}
+
+/* Retrieves session data from the db backend.
+ */
+gnutls_datum _gnutls_retrieve_session( GNUTLS_STATE state, gnutls_datum session_id)
+{
+#ifdef HAVE_LIBGDBM
+datum key = { session_id.data, session_id.size };
+datum content;
+#endif
+gnutls_datum ret = { NULL, 0 };
+
+       if (GNUTLS_DBNAME==NULL && _gnutls_db_func_is_ok(state)!=0) {
+               return ret;
+       }
+       
+       if (session_id.data==NULL || session_id.size==0)
+               return ret;
+
+       /* if we can't read why bother writing? */
+       if (GNUTLS_DBF==NULL) { /* use external backend. */
+               
+               ret = state->gnutls_internals.db_retrieve_func( state->gnutls_internals.db_ptr, session_id);
+       
+       } else { /* use gdbm */
+#ifdef HAVE_LIBGDBM
+               content = gdbm_fetch( GNUTLS_DBF, key);
+               ret.data = content.dptr;
+               ret.size = content.dsize;
+#else
+               return ret;
 #endif
+       }
+
+
+       return ret;
+
 }
 
+/* Removes session data from the db backend.
+ */
+int _gnutls_remove_session( GNUTLS_STATE state, gnutls_datum session_id)
+{
+#ifdef HAVE_LIBGDBM
+GDBM_FILE dbf;
+datum key = { session_id.data, session_id.size };
+#endif
+int ret = 0;
+
+       if (GNUTLS_DBNAME==NULL && _gnutls_db_func_is_ok(state)!=0) {
+               return GNUTLS_E_DB_ERROR;
+       }
+       
+       if (session_id.data==NULL || session_id.size==0)
+               return GNUTLS_E_INVALID_SESSION;
+
+       /* if we can't read why bother writing? */
+       if (GNUTLS_DBF==NULL) { /* use external backend. */
+               
+               ret = state->gnutls_internals.db_remove_func( state->gnutls_internals.db_ptr, session_id);
+       
+       } else { /* use gdbm */
+#ifdef HAVE_LIBGDBM
+               dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_WRITER, 0600, NULL);
+               if (dbf==NULL) {
+                       /* cannot open db for writing. This may happen if multiple
+                        * instances try to write. 
+                        */
+                       return GNUTLS_E_AGAIN;
+               }
+               ret = gdbm_delete( dbf, key);
+
+               gdbm_close(dbf);
+#else
+               return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+#endif
+       }
+
+
+       return (ret == 0 ? ret : GNUTLS_E_DB_ERROR);
+
+}
index 4c0c5f12284f5e46970fd901205b25c061eae370..bfc9c2ef3b7ae899b766cb77279153f7bff46ae6 100644 (file)
@@ -24,3 +24,6 @@ int _gnutls_server_register_current_session( GNUTLS_STATE state);
 int _gnutls_server_restore_session( GNUTLS_STATE state, uint8* session_id, int session_id_size);
 int gnutls_clean_db( GNUTLS_STATE state);
 int _gnutls_db_remove_session( GNUTLS_STATE state, uint8* session_id, int session_id_size);
+int _gnutls_store_session( GNUTLS_STATE state, gnutls_datum session_id, gnutls_datum session_data);
+gnutls_datum _gnutls_retrieve_session( GNUTLS_STATE state, gnutls_datum session_id);
+int _gnutls_remove_session( GNUTLS_STATE state, gnutls_datum session_id);
index 7577fcb5461c7161a07fecab0d936e4d398ab2d0..baa219aa24ae3cd36fa1155c757d57b311513516 100644 (file)
@@ -150,6 +150,11 @@ typedef enum ResumableSession { RESUME_TRUE, RESUME_FALSE } ResumableSession;
  */
 typedef ssize_t (*PULL_FUNC)(SOCKET, void*, size_t);
 typedef ssize_t (*PUSH_FUNC)(SOCKET, const void*, size_t);
+/* Store & Retrieve functions defines: 
+ */
+typedef int (*DB_STORE_FUNC)(void*, gnutls_datum key, gnutls_datum data);
+typedef int (*DB_REMOVE_FUNC)(void*, gnutls_datum key);
+typedef gnutls_datum (*DB_RETR_FUNC)(void*, gnutls_datum key);
 
 typedef struct {
        KXAlgorithm algorithm;
@@ -425,6 +430,13 @@ typedef struct {
         */
        PULL_FUNC _gnutls_pull_func;
        PUSH_FUNC _gnutls_push_func;
+       /* STORE & RETRIEVE functions. Only used if other
+        * backend than gdbm is used.
+        */
+       DB_STORE_FUNC db_store_func;
+       DB_RETR_FUNC db_retrieve_func;
+       DB_REMOVE_FUNC db_remove_func;
+       void* db_ptr;
 } GNUTLS_INTERNALS;
 
 struct GNUTLS_STATE_INT {
index 500e1b1e9c00355500402be91951f0f634496d46..0c2830b98d4135cdfae781d884874f5404b2b0ef 100644 (file)
@@ -55,7 +55,7 @@ void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) {
   * if you have changed the default low water value (default is 1).
   * Normally you will not need that function. 
   * This function is only usefull if using berkeley style sockets.
-  * Otherwise it does nothing.
+  * Otherwise it must be called and set lowat to zero.
   *
   **/
 int gnutls_set_lowat(GNUTLS_STATE state, int num) {
@@ -63,8 +63,6 @@ int gnutls_set_lowat(GNUTLS_STATE state, int num) {
        return 0;
 }
 
-extern ssize_t (*_gnutls_pull_func)( SOCKET, void*, size_t);
-
 /**
   * gnutls_init - This function initializes the state to null (null encryption etc...).
   * @con_end: is used to indicate if this state is to be used for server or 
@@ -108,10 +106,7 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end)
 
        (*state)->gnutls_internals.expire_time = DEFAULT_EXPIRE_TIME; /* one hour default */
 
-       if (_gnutls_pull_func==NULL)
-               gnutls_set_lowat((*state), DEFAULT_LOWAT); /* the default for tcp */
-       else
-               gnutls_set_lowat((*state), 0);
+       gnutls_set_lowat((*state), DEFAULT_LOWAT); /* the default for tcp */
 
        gnutls_set_max_handshake_data_buffer_size( (*state), MAX_HANDSHAKE_DATA_BUFFER_SIZE);