2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 /* This file contains functions that manipulate a database backend for
27 #include "gnutls_int.h"
28 #include "gnutls_errors.h"
29 #include <gnutls_db.h>
30 #include <gnutls_session_pack.h>
31 #include <gnutls_datum.h>
34 * gnutls_db_set_retrieve_function:
35 * @session: is a #gnutls_session_t structure.
36 * @retr_func: is the function.
38 * Sets the function that will be used to retrieve data from the
39 * resumed sessions database. This function must return a
40 * gnutls_datum_t containing the data on success, or a gnutls_datum_t
41 * containing null and 0 on failure.
43 * The datum's data must be allocated using the function
46 * The first argument to @retr_func will be null unless
47 * gnutls_db_set_ptr() has been called.
50 gnutls_db_set_retrieve_function(gnutls_session_t session,
51 gnutls_db_retr_func retr_func)
53 session->internals.db_retrieve_func = retr_func;
57 * gnutls_db_set_remove_function:
58 * @session: is a #gnutls_session_t structure.
59 * @rem_func: is the function.
61 * Sets the function that will be used to remove data from the
62 * resumed sessions database. This function must return 0 on success.
64 * The first argument to @rem_func will be null unless
65 * gnutls_db_set_ptr() has been called.
68 gnutls_db_set_remove_function(gnutls_session_t session,
69 gnutls_db_remove_func rem_func)
71 session->internals.db_remove_func = rem_func;
75 * gnutls_db_set_store_function:
76 * @session: is a #gnutls_session_t structure.
77 * @store_func: is the function
79 * Sets the function that will be used to store data in the resumed
80 * sessions database. This function must return 0 on success.
82 * The first argument to @store_func will be null unless
83 * gnutls_db_set_ptr() has been called.
86 gnutls_db_set_store_function(gnutls_session_t session,
87 gnutls_db_store_func store_func)
89 session->internals.db_store_func = store_func;
94 * @session: is a #gnutls_session_t structure.
95 * @ptr: is the pointer
97 * Sets the pointer that will be provided to db store, retrieve and
98 * delete functions, as the first argument.
100 void gnutls_db_set_ptr(gnutls_session_t session, void *ptr)
102 session->internals.db_ptr = ptr;
107 * @session: is a #gnutls_session_t structure.
109 * Get db function pointer.
111 * Returns: the pointer that will be sent to db store, retrieve and
112 * delete functions, as the first argument.
114 void *gnutls_db_get_ptr(gnutls_session_t session)
116 return session->internals.db_ptr;
120 * gnutls_db_set_cache_expiration:
121 * @session: is a #gnutls_session_t structure.
122 * @seconds: is the number of seconds.
124 * Set the expiration time for resumed sessions. The default is 3600
125 * (one hour) at the time of this writing.
127 void gnutls_db_set_cache_expiration(gnutls_session_t session, int seconds)
129 session->internals.expire_time = seconds;
133 * gnutls_db_get_default_cache_expiration:
135 * Returns the expiration time (in seconds) of stored sessions for resumption.
137 unsigned gnutls_db_get_default_cache_expiration(void)
139 return DEFAULT_EXPIRE_TIME;
143 * gnutls_db_check_entry:
144 * @session: is a #gnutls_session_t structure.
145 * @session_entry: is the session data (not key)
147 * This function has no effect.
149 * Returns: Returns %GNUTLS_E_EXPIRED, if the database entry has
150 * expired or 0 otherwise.
153 gnutls_db_check_entry(gnutls_session_t session,
154 gnutls_datum_t session_entry)
160 * gnutls_db_check_entry_time:
161 * @entry: is a pointer to a #gnutls_datum_t structure.
162 * @t: is the time of the session handshake
164 * This function returns the time that this entry was active.
165 * It can be used for database entry expiration.
167 * Returns: The time this entry was created, or zero on error.
169 time_t gnutls_db_check_entry_time(gnutls_datum_t * entry)
175 return gnutls_assert_val(0);
177 magic = _gnutls_read_uint32(entry->data);
179 if (magic != PACKED_SESSION_MAGIC)
180 return gnutls_assert_val(0);
182 t = _gnutls_read_uint32(&entry->data[4]);
187 /* Checks if both db_store and db_retrieve functions have
190 static int db_func_is_ok(gnutls_session_t session)
192 if (session->internals.db_store_func != NULL &&
193 session->internals.db_retrieve_func != NULL)
196 return GNUTLS_E_DB_ERROR;
199 /* Stores session data to the db backend.
202 store_session(gnutls_session_t session,
203 gnutls_datum_t session_id, gnutls_datum_t session_data)
207 if (db_func_is_ok(session) != 0) {
208 return GNUTLS_E_DB_ERROR;
211 if (session_data.data == NULL || session_data.size == 0) {
213 return GNUTLS_E_INVALID_SESSION;
216 /* if we can't read why bother writing? */
217 ret = session->internals.db_store_func(session->internals.db_ptr,
218 session_id, session_data);
220 return (ret == 0 ? ret : GNUTLS_E_DB_ERROR);
223 int _gnutls_server_register_current_session(gnutls_session_t session)
226 gnutls_datum_t content;
229 key.data = session->security_parameters.session_id;
230 key.size = session->security_parameters.session_id_size;
232 if (session->internals.resumable == RESUME_FALSE) {
234 return GNUTLS_E_INVALID_SESSION;
237 if (session->security_parameters.session_id_size == 0) {
239 return GNUTLS_E_INVALID_SESSION;
242 ret = _gnutls_session_pack(session, &content);
248 ret = store_session(session, key, content);
249 _gnutls_free_datum(&content);
255 _gnutls_server_restore_session(gnutls_session_t session,
256 uint8_t * session_id, int session_id_size)
262 if (session_id == NULL || session_id_size == 0) {
264 return GNUTLS_E_INVALID_REQUEST;
267 if (session->internals.premaster_set != 0) { /* hack for CISCO's DTLS-0.9 */
268 if (session_id_size ==
269 session->internals.resumed_security_parameters.
271 && memcmp(session_id,
273 resumed_security_parameters.session_id,
274 session_id_size) == 0)
278 key.data = session_id;
279 key.size = session_id_size;
281 if (db_func_is_ok(session) != 0) {
283 return GNUTLS_E_INVALID_SESSION;
287 session->internals.db_retrieve_func(session->internals.db_ptr,
290 if (data.data == NULL) {
292 return GNUTLS_E_INVALID_SESSION;
295 /* expiration check is performed inside */
296 ret = gnutls_session_set_data(session, data.data, data.size);
297 gnutls_free(data.data);
309 * gnutls_db_remove_session:
310 * @session: is a #gnutls_session_t structure.
312 * This function will remove the current session data from the
313 * session database. This will prevent future handshakes reusing
314 * these session data. This function should be called if a session
315 * was terminated abnormally, and before gnutls_deinit() is called.
317 * Normally gnutls_deinit() will remove abnormally terminated
320 void gnutls_db_remove_session(gnutls_session_t session)
322 gnutls_datum_t session_id;
325 session_id.data = session->security_parameters.session_id;
326 session_id.size = session->security_parameters.session_id_size;
328 if (session->internals.db_remove_func == NULL) {
330 return /* GNUTLS_E_DB_ERROR */ ;
333 if (session_id.data == NULL || session_id.size == 0) {
335 return /* GNUTLS_E_INVALID_SESSION */ ;
338 /* if we can't read why bother writing? */
339 ret = session->internals.db_remove_func(session->internals.db_ptr,