summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--THANKS1
-rw-r--r--configure.in2
-rw-r--r--lib/gnutls.h.in14
-rw-r--r--lib/gnutls_db.c294
-rw-r--r--lib/gnutls_db.h3
-rw-r--r--lib/gnutls_int.h12
-rw-r--r--lib/gnutls_record.c9
8 files changed, 270 insertions, 69 deletions
diff --git a/NEWS b/NEWS
index 959f4186e1..c056339091 100644
--- 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 f6c84602cb..e390f5b31b 100644
--- a/THANKS
+++ b/THANKS
@@ -4,3 +4,4 @@ Neil Spring <nspring@saavie.org>
Paul Sheer <psheer@icon.co.za>
+Jon Nelson <jnelson@securepipe.com>
diff --git a/configure.in b/configure.in
index dfc65a693b..86e53dbf2a 100644
--- a/configure.in
+++ b/configure.in
@@ -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")
diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in
index 1214994234..f17bb0f5e8 100644
--- a/lib/gnutls.h.in
+++ b/lib/gnutls.h.in
@@ -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);
+
diff --git a/lib/gnutls_db.c b/lib/gnutls_db.c
index 0ed1f73539..0a2da720d8 100644
--- a/lib/gnutls_db.c
+++ b/lib/gnutls_db.c
@@ -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
@@ -35,6 +36,73 @@
#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.
* @seconds: is the number of seconds.
@@ -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);
+
+}
diff --git a/lib/gnutls_db.h b/lib/gnutls_db.h
index 4c0c5f1228..bfc9c2ef3b 100644
--- a/lib/gnutls_db.h
+++ b/lib/gnutls_db.h
@@ -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);
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 7577fcb546..baa219aa24 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -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 {
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 500e1b1e9c..0c2830b98d 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -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);