and compression algorithms.
- Added check for C99 macro support by the compiler.
- Added functions gnutls_b64_encode_fmt2() and gnutls_b64_decode_fmt2()
-- Added the new libasn1 library.
+- Added the new libtasn1 library.
+- Removed the gdbm backend. Applications are now responsible for the
+ session resuming backend. The gnutls-serv application contains an
+ simple example on how to use gdbm for resuming.
Version 0.4.3 (23/05/2002)
- The gnutls-extra library now compiles fine, if the opencdk library is
if test x$ac_ext_libraries != xno; then
AC_MSG_RESULT(yes)
- AC_CHECK_LIB(gdbm, gdbm_open,, AC_MSG_WARN(
+ AC_CHECK_LIB(gdbm, gdbm_open, SERV_LIBS="-lgdbm", AC_MSG_WARN(
***
*** GDBM was not found. You will not be able to use the default gdbm session resumption backend.))
AC_CHECK_LIB(z, compress,,AC_MSG_WARN(
AC_SUBST(LIBGNUTLS_LIBS)
AC_SUBST(LIBGNUTLS_CFLAGS)
+SERV_LIBS="$LIBS $SERV_LIBS"
+AC_SUBST(SERV_LIBS)
LIBGNUTLS_EXTRA_LIBS="-L${libdir} -lgnutls-extra -lgnutls $LIBOPENCDK_LIBS"
LIBGNUTLS_EXTRA_CFLAGS="$LIBOPENCDK_CFLAGS -I${includedir}"
Current list:
* Audit the code
* Add function(s) to get the DHE/A parameters
-* Add function(s) to extract the certificate key's parameters
* Add PKCS-12 support
* Convert documentation to texinfo format
* Merge common stuff in DHE and DHA key exchange
after a successful handshake, without the expensive calculations. This is
achieved by using the previously
established keys. \gnutls{} supports this feature, and the
-example \hyperref{resume client}{resume client (see Section }{)}{resume-example} illustrates a typical use of it.
-\par
-Servers only need to use the
-\hyperref{gnutls\_db\_set\_name()}{gnutls\_db\_set\_name() (see Section }{)}{gnutls_db_set_name} function if they want to use the gdbm
-backend to store sessions.
+example \hyperref{resume client}{resume client (see section }{)}{resume-example} illustrates a typical use of it.
\par
Keep in mind that sessions are expired after some time, for security reasons, thus
it may be normal for a server not to resume a session even if you requested that.
client, to leave all the burden of resuming to the client. Ie. copy and keep the
nesessary parameters. See the functions:
\begin{itemize}
-\item \hyperref{gnutls\_session\_get\_data()}
-{gnutls\_session\_get\_data() on section }{}{gnutls_session_get_data}
-\item \hyperref{gnutls\_session\_get\_id()}
-{gnutls\_session\_get\_id() on section }{}{gnutls_session_get_id}
-\item \hyperref{gnutls\_session\_set\_data()}
-{gnutls\_session\_set\_data() on section }{}{gnutls_session_set_data}
+\item \printfunc{gnutls_session_get_data}{gnutls\_session\_get\_data}
+\item \printfunc{gnutls_session_get_id}{gnutls\_session\_get\_id}
+\item \printfunc{gnutls_session_set_data}{gnutls\_session\_set\_data}
\end{itemize}
\par
-The server side is different.
-Here the server only specifies a DB file, using
-\hyperref{gnutls\_db\_set\_name()}{gnutls\_db\_set\_name() (see Section }{)}{gnutls_db_set_name}.
-This DB file is used to store the sessions' required parameters for
-resuming. This means that this file contains very sensitive information,
-such as encryption keys. In a multi-threaded application every thread can
-read from the DB file and access all previously established sessions, but
-only one thread can write at a time. The current behaviour of gnutls is
-not to block to wait for the DB to be ready for writing, but continue the
-process normally (and do not save the parameters).
-\par
-The default behaviour is not efficient in servers where many connections
-per second arrive. Thus
- \gnutls{} provides the following callback functions:
+The server side is different. A server has to specify some callback functions
+which store, retrieve and delete session data. These can be registered with:
\begin{itemize}
-\item \hyperref{gnutls\_db\_set\_remove\_function()}{gnutls\_db\_set\_remove\_function() (see Section }{)}
-{gnutls_db_set_remove_function}
-\item \hyperref{gnutls\_db\_set\_store\_function()}{gnutls\_db\_set\_store\_function() (see Section }{)}
-{gnutls_db_set_store_function}
-\item \hyperref{gnutls\_db\_set\_retrieve\_function()}{gnutls\_db\_set\_retrieve\_function() (see Section }{)
-}{gnutls_db_set_retrieve_function}
-\item \hyperref{gnutls\_db\_set\_ptr()}{gnutls\_db\_set\_ptr() (see Section }{)}
-{gnutls_db_set_ptr}
+\item \printfunc{gnutls_db_set_remove_function}{gnutls\_db\_set\_remove\_function}
+\item \printfunc{gnutls_db_set_store_function}{gnutls\_db\_set\_store\_function}
+\item \printfunc{gnutls_db_set_retrieve_function}{gnutls\_db\_set\_retrieve\_function}
+\item \printfunc{gnutls_db_set_ptr}{gnutls\_db\_set\_ptr}
\end{itemize}
-These callback functions are required in order to use a session
-storage method, other than the default gdbm backend.
\par
-If an alternative backend is in use, it might be usefull to be able to check
-for expired sessions in order to remove them, and save space. This is what
-\hyperref{gnutls\_db\_clean()}{gnutls\_db\_clean() (see Section }{)}
-{gnutls_db_clean} does for the gdbm backend.
-\gnutls{} provides the function
-\hyperref{gnutls\_db\_check\_entry()}{gnutls\_db\_check\_entry() (see Section }{)
-}{gnutls_db_check_entry}, which takes as input session data, and
-returns a negative value if the data are to be removed.
+It might also be usefull to be able to check for expired sessions in order to remove
+them, and save space. The function
+\printfunc{gnutls_db_check_entry}{gnutls\_db\_check\_entry} is provided for that
+reason.
gnutls_init(&state, GNUTLS_SERVER);
- /* in order to support session resuming:
- */
- if ((ret = gnutls_db_set_name(state, "gnutls-rsm.db")) < 0)
- fprintf(stderr, "*** DB error (%d)\n\n", ret);
-
gnutls_protocol_set_priority(state, protocol_priority);
gnutls_cipher_set_priority(state, cipher_priority);
gnutls_compression_set_priority(state, comp_priority);
# include <sys/types.h>
#endif
-#ifdef HAVE_LIBGDBM
-# include <gdbm.h>
-#endif
-
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
void gnutls_db_set_cache_expiration( GNUTLS_STATE state, int seconds);
-int gnutls_db_set_name( GNUTLS_STATE state, const char* filename);
-int gnutls_db_clean( GNUTLS_STATE state);
-void gnutls_db_remove_session( GNUTLS_STATE state);
+void gnutls_db_remove_session( GNUTLS_STATE state);
void gnutls_db_set_retrieve_func( GNUTLS_STATE, GNUTLS_DB_RETR_FUNC);
void gnutls_db_set_remove_func( GNUTLS_STATE, GNUTLS_DB_REMOVE_FUNC);
void gnutls_db_set_store_func( GNUTLS_STATE, GNUTLS_DB_STORE_FUNC);
#define GNUTLS_DBNAME state->gnutls_internals.db_name
-#ifdef HAVE_LIBGDBM
-# define GNUTLS_DBF state->gnutls_internals.db_reader
-# define GNUTLS_REOPEN_DB() if (GNUTLS_DBF!=NULL) \
- gdbm_close( GNUTLS_DBF); \
- GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
-#endif
-
/**
- * gnutls_db_set_retrieve_function - Sets the function that will be used to get data
+ * gnutls_db_set_retrieve_func - Sets the function that will be used to get data
* @state: is a &GNUTLS_STATE structure.
* @retr_func: is the function.
*
* has been called.
*
**/
-void gnutls_db_set_retrieve_function( GNUTLS_STATE state, GNUTLS_DB_RETR_FUNC retr_func) {
+void gnutls_db_set_retrieve_func( GNUTLS_STATE state, GNUTLS_DB_RETR_FUNC retr_func) {
state->gnutls_internals.db_retrieve_func = retr_func;
}
/**
- * gnutls_db_set_remove_function - Sets the function that will be used to remove data
+ * gnutls_db_set_remove_func - Sets the function that will be used to remove data
* @state: is a &GNUTLS_STATE structure.
* @rem_func: is the function.
*
* has been called.
*
**/
-void gnutls_db_set_remove_function( GNUTLS_STATE state, GNUTLS_DB_REMOVE_FUNC rem_func) {
+void gnutls_db_set_remove_func( GNUTLS_STATE state, GNUTLS_DB_REMOVE_FUNC rem_func) {
state->gnutls_internals.db_remove_func = rem_func;
}
/**
- * gnutls_db_set_store_function - Sets the function that will be used to put data
+ * gnutls_db_set_store_func - Sets the function that will be used to put data
* @state: is a &GNUTLS_STATE structure.
* @store_func: is the function
*
* has been called.
*
**/
-void gnutls_db_set_store_function( GNUTLS_STATE state, GNUTLS_DB_STORE_FUNC store_func) {
+void gnutls_db_set_store_func( GNUTLS_STATE state, GNUTLS_DB_STORE_FUNC store_func) {
state->gnutls_internals.db_store_func = store_func;
}
state->gnutls_internals.expire_time = seconds;
}
-/**
- * gnutls_db_set_name - Sets the name of the database that holds TLS sessions.
- * @state: is a &GNUTLS_STATE structure.
- * @filename: is the filename for the database
- *
- * 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_db_set_store_func() etc.)
- *
- **/
-int gnutls_db_set_name( GNUTLS_STATE state, const char* filename) {
-#ifdef HAVE_LIBGDBM
-GDBM_FILE dbf;
-
- if (filename==NULL) return 0;
-
- /* deallocate previous name */
- if (GNUTLS_DBNAME!=NULL)
- gnutls_free(GNUTLS_DBNAME);
-
- /* set name */
- GNUTLS_DBNAME = gnutls_strdup(filename);
- if (GNUTLS_DBNAME==NULL) return GNUTLS_E_MEMORY_ERROR;
-
- /* open for reader */
- GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
- if (GNUTLS_DBF==NULL) {
- /* maybe it does not exist - so try to
- * create it.
- */
- dbf = gdbm_open( (char*)filename, 0, GDBM_WRCREAT, 0600, NULL);
- if (dbf==NULL) return GNUTLS_E_DB_ERROR;
- gdbm_close(dbf);
-
- /* try to open again */
- GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
- }
- if (GNUTLS_DBF==NULL)
- return GNUTLS_E_DB_ERROR;
-
- return 0;
-#else
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-#endif
-}
-
/**
* gnutls_db_check_entry - checks if the given db entry has expired
* @state: is a &GNUTLS_STATE structure.
* @session_entry: is the session data (not key)
*
- * This function should only be used if not using the gdbm backend.
* This function returns GNUTLS_E_EXPIRED, if the database entry
* has expired or 0 otherwise. This function is to be used when
* you want to clear unnesessary session which occupy space in your
return 0;
}
-/**
- * gnutls_db_clean - removes expired and invalid sessions from the database
- * @state: is a &GNUTLS_STATE structure.
- *
- * 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 should only
- * be called if using the gdbm backend.
- *
- **/
-int gnutls_db_clean( GNUTLS_STATE state) {
-#ifdef HAVE_LIBGDBM
-GDBM_FILE dbf;
-int ret;
-datum key;
-time_t timestamp;
-gnutls_datum _key;
-
- 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);
-
- timestamp = time(0);
-
- _key.data = key.dptr;
- _key.size = key.dsize;
- while( _key.data != NULL) {
-
- if ( gnutls_db_check_entry( state, _key)==GNUTLS_E_EXPIRED) {
- /* delete expired entry */
- gdbm_delete( dbf, key);
- }
-
- free(key.dptr);
- key = gdbm_nextkey(dbf, key);
- }
- ret = gdbm_reorganize(dbf);
-
- gdbm_close(dbf);
- GNUTLS_REOPEN_DB();
-
- if (ret!=0) return GNUTLS_E_DB_ERROR;
-
- return 0;
-#else
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
-#endif
-
-}
-
/* The format of storing data is:
* (forget it). Check gnutls_session_pack.c
*/
*/
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.data, session_id.size };
-datum content = {session_data.data, session_data.size};
-#endif
int ret = 0;
if (state->gnutls_internals.resumable==RESUME_FALSE) {
}
/* if we can't read why bother writing? */
-#ifdef HAVE_LIBGDBM
- if (GNUTLS_DBF!=NULL) { /* use gdbm */
- 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.
- */
- gnutls_assert();
- return GNUTLS_E_AGAIN;
- }
- ret = gdbm_store( dbf, key, content, GDBM_INSERT);
- if (ret<0) {
- gnutls_assert();
- }
- gdbm_close(dbf);
-
- return 0; /*GNUTLS_E_UNIMPLEMENTED_FEATURE;*/
- }
- else
-#endif
- if (state->gnutls_internals.db_store_func!=NULL)
- ret = state->gnutls_internals.db_store_func( state->gnutls_internals.db_ptr, session_id, session_data);
-
+ if (state->gnutls_internals.db_store_func!=NULL)
+ ret = state->gnutls_internals.db_store_func( state->gnutls_internals.db_ptr, session_id, session_data);
return (ret == 0 ? ret : GNUTLS_E_DB_ERROR);
*/
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 (session_id.data==NULL || session_id.size==0) {
return ret;
}
- /* if we can't read why bother writing? */
-#ifdef HAVE_LIBGDBM
- if (GNUTLS_DBF!=NULL) { /* use gdbm */
- content = gdbm_fetch( GNUTLS_DBF, key);
- ret.data = content.dptr;
- ret.size = content.dsize;
- } else
-#endif
- if (state->gnutls_internals.db_retrieve_func!=NULL)
- ret = state->gnutls_internals.db_retrieve_func( state->gnutls_internals.db_ptr, session_id);
+ if (state->gnutls_internals.db_retrieve_func!=NULL)
+ ret = state->gnutls_internals.db_retrieve_func( state->gnutls_internals.db_ptr, session_id);
return ret;
*/
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_INVALID_SESSION;
/* if we can't read why bother writing? */
-#ifdef HAVE_LIBGDBM
- if (GNUTLS_DBF!=NULL) { /* use gdbm */
-
- 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
-#endif
- if (state->gnutls_internals.db_remove_func!=NULL)
- ret = state->gnutls_internals.db_remove_func( state->gnutls_internals.db_ptr, session_id);
+ if (state->gnutls_internals.db_remove_func!=NULL)
+ ret = state->gnutls_internals.db_remove_func( state->gnutls_internals.db_ptr, session_id);
return (ret == 0 ? ret : GNUTLS_E_DB_ERROR);
if (ret == 0) { /* resumed! */
resume_copy_required_values(state);
-
state->gnutls_internals.resumed = RESUME_TRUE;
return 0;
} else {
int v2_hello; /* 0 if the client hello is v3+.
* non-zero if we got a v2 hello.
*/
-#ifdef HAVE_LIBGDBM
- GDBM_FILE db_reader;
-#endif
/* keeps the headers of the handshake packet
*/
HANDSHAKE_HEADER_BUFFER handshake_header_buffer;
return gnutls_x509_extract_certificate_subject_alt_name( cert, seq, ret, ret_size);
}
+int gnutls_db_set_name( GNUTLS_STATE state, const char* filename) {
+ return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+}
+
+int gnutls_db_clean( GNUTLS_STATE state) {
+ return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+}
+
/* nothing here */
#endif /* GNUTLS_BACKWARDS_COMPATIBLE */
/* remove auth info firstly */
_gnutls_free_auth_info(state );
-#ifdef HAVE_LIBGDBM
- /* close the database - resuming sessions */
- if ( state->gnutls_internals.db_reader != NULL)
- gdbm_close(state->gnutls_internals.db_reader);
-#endif
-
_gnutls_handshake_io_buffer_clear( state);
gnutls_sfree_datum(&state->connection_state.read_mac_secret);
* gnutls_x509_get_certificate_xml - This function parses an RDN sequence
* @cert: should contain a DER encoded certificate
* @res: The datum that will hold the result
- * @detail: The detail level (unused for now)
+ * @detail: The detail level (must be 0 for now)
*
* This function will return the XML structures of the given X.509 certificate.
- * The XML structures are allocated internaly and stored into res.
+ * The XML structures are allocated internaly (with malloc) and stored into res.
* Returns a negative error code in case of an error.
*
**/
bin_PROGRAMS = gnutls-serv gnutls-cli gnutls-srpcrypt gnutls-cli-debug
gnutls_serv_SOURCES = serv-gaa.c serv.c common.c
-gnutls_serv_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS)
+gnutls_serv_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) #$(SERV_LIBS)
gnutls_srpcrypt_SOURCES = crypt-gaa.c crypt.c
gnutls_srpcrypt_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS)
gnutls_cli_SOURCES = cli-gaa.c cli.c common.c
if (cert_list_size <= 0)
return;
-
printf(" - Certificate info:\n");
printf(" # Certificate is valid since: %s", my_ctime( &activet));
#include "common.h"
#include <signal.h>
#include "serv-gaa.h"
-
+#include <config.h>
/* konqueror cannot handle sending the page in multiple
* pieces.
GNUTLS_CERTIFICATE_SERVER_CREDENTIALS cert_cred;
+#ifdef HAVE_LIBGDBM
+
+# include <gdbm.h>
+
+ typedef struct {
+ GDBM_FILE read_dbf;
+ } DBF;
+
+ static DBF dbf;
+
+# define DB_FILE "gnutls-rsm.db"
+
+ static void wrap_gdbm_init(void);
+ static void wrap_gdbm_deinit(void);
+ static int wrap_gdbm_store( DBF* dbf, gnutls_datum key, gnutls_datum data);
+ static gnutls_datum wrap_gdbm_fetch( DBF* dbf, gnutls_datum key);
+ static int wrap_gdbm_delete( DBF* dbf, gnutls_datum key);
+
+#endif
+
+
#define DEFAULT_PRIME_BITS 1024
/* we use primes up to 1024 in this server.
GNUTLS_STATE initialize_state(void)
{
GNUTLS_STATE state;
- int ret;
gnutls_init(&state, GNUTLS_SERVER);
*/
gnutls_handshake_set_private_extensions( state, 1);
- if ((ret = gnutls_db_set_name(state, "gnutls-rsm.db")) < 0)
- fprintf(stderr,
- "*** DB error (%d). Resuming will not be possible.\n\n",
- ret);
+#ifdef HAVE_LIBGDBM
+ gnutls_db_set_retrieve_func( state, wrap_gdbm_fetch);
+ gnutls_db_set_remove_func( state, wrap_gdbm_delete);
+ gnutls_db_set_store_func( state, wrap_gdbm_store);
+ gnutls_db_set_ptr( state, &dbf);
+#endif
/* null cipher is here only for debuging
* purposes.
gaa_parser(argc, argv);
+#ifdef HAVE_LIBGDBM
+ wrap_gdbm_init();
+#endif
+
if (http == 1) {
strcpy(name, "HTTP Server");
} else {
gnutls_srp_free_server_sc(srp_cred);
gnutls_anon_free_server_sc(dh_cred);
+#ifdef HAVE_LIBGDBM
+ wrap_gdbm_deinit();
+#endif
gnutls_global_deinit();
return 0;
}
comp_priority[j] = 0;
}
-
-
-
}
void serv_version(void) {
fprintf(stderr, "GNU TLS test server, ");
fprintf(stderr, "version %s.\n", LIBGNUTLS_VERSION);
}
+
+#ifdef HAVE_LIBGDBM
+
+static void wrap_gdbm_init(void) {
+ GDBM_FILE tmpdbf;
+
+ /* create db */
+ tmpdbf = gdbm_open(DB_FILE, 0, GDBM_NEWDB, 0600, NULL);
+ if (tmpdbf==NULL) {
+ fprintf(stderr, "Error opening gdbm database\n");
+ exit(1);
+ }
+ gdbm_close( tmpdbf);
+
+ dbf.read_dbf = gdbm_open(DB_FILE, 0, GDBM_READER, 0600, NULL);
+ if (dbf.read_dbf==NULL) {
+ fprintf(stderr, "Error opening gdbm database\n");
+ exit(1);
+ }
+}
+
+static void wrap_gdbm_deinit(void) {
+ gdbm_close( dbf.read_dbf);
+}
+
+static int wrap_gdbm_store( DBF* dbf, gnutls_datum key, gnutls_datum data) {
+ datum _key, _data;
+ int res;
+ GDBM_FILE write_dbf;
+
+ write_dbf = gdbm_open(DB_FILE, 0, GDBM_WRITER, 0600, NULL);
+ if (write_dbf==NULL) {
+ fprintf(stderr, "Error opening gdbm database\n");
+ exit(1);
+ }
+
+ _key.dptr = key.data;
+ _key.dsize = key.size;
+
+ _data.dptr = data.data;
+ _data.dsize = data.size;
+
+ res = gdbm_store( write_dbf, _key, _data, GDBM_INSERT);
+
+ gdbm_close( write_dbf);
+ return res;
+}
+
+static gnutls_datum wrap_gdbm_fetch( DBF* dbf, gnutls_datum key) {
+ datum _key, _res;
+ gnutls_datum res2;
+
+ _key.dptr = key.data;
+ _key.dsize = key.size;
+
+ _res = gdbm_fetch( dbf->read_dbf, _key);
+
+ res2.data = _res.dptr;
+ res2.size = _res.dsize;
+
+ return res2;
+}
+
+static int wrap_gdbm_delete( DBF* dbf, gnutls_datum key) {
+ datum _key;
+ int res;
+ GDBM_FILE write_dbf;
+
+ write_dbf = gdbm_open(DB_FILE, 0, GDBM_WRITER, 0600, NULL);
+ if (write_dbf==NULL) {
+ fprintf(stderr, "Error opening gdbm database\n");
+ exit(1);
+ }
+
+ _key.dptr = key.data;
+ _key.dsize = key.size;
+
+ res = gdbm_delete( write_dbf, _key);
+ gdbm_close( write_dbf);
+
+ return res;
+}
+
+#endif /* HAVE LIBGDBM */