cleaned up errno handling.
[gnutls.git] / lib / gnutls_db.c
blob135a59598453dc79911a7e4f39c371b94ea04a49
1 /*
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 3 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
24 * resumed sessions.
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>
33 /**
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
44 * gnutls_malloc().
46 * The first argument to @retr_func will be null unless
47 * gnutls_db_set_ptr() has been called.
48 **/
49 void
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;
56 /**
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.
66 **/
67 void
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;
74 /**
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.
84 **/
85 void
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;
92 /**
93 * gnutls_db_set_ptr:
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.
99 **/
100 void
101 gnutls_db_set_ptr (gnutls_session_t session, void *ptr)
103 session->internals.db_ptr = ptr;
107 * gnutls_db_get_ptr:
108 * @session: is a #gnutls_session_t structure.
110 * Get db function pointer.
112 * Returns: the pointer that will be sent to db store, retrieve and
113 * delete functions, as the first argument.
115 void *
116 gnutls_db_get_ptr (gnutls_session_t session)
118 return session->internals.db_ptr;
122 * gnutls_db_set_cache_expiration:
123 * @session: is a #gnutls_session_t structure.
124 * @seconds: is the number of seconds.
126 * Set the expiration time for resumed sessions. The default is 3600
127 * (one hour) at the time of this writing.
129 void
130 gnutls_db_set_cache_expiration (gnutls_session_t session, int seconds)
132 session->internals.expire_time = seconds;
136 * gnutls_db_check_entry:
137 * @session: is a #gnutls_session_t structure.
138 * @session_entry: is the session data (not key)
140 * Check if database entry has expired. This function is to be used
141 * when you want to clear unnecessary sessions which occupy space in
142 * your backend.
144 * Returns: Returns %GNUTLS_E_EXPIRED, if the database entry has
145 * expired or 0 otherwise.
148 gnutls_db_check_entry (gnutls_session_t session, gnutls_datum_t session_entry)
150 time_t timestamp;
152 timestamp = gnutls_time (0);
154 if (session_entry.data != NULL)
155 if (timestamp -
156 ((security_parameters_st *) (session_entry.data))->timestamp <=
157 session->internals.expire_time
158 || ((security_parameters_st *) (session_entry.data))->timestamp >
159 timestamp
160 || ((security_parameters_st *) (session_entry.data))->timestamp == 0)
161 return GNUTLS_E_EXPIRED;
163 return 0;
166 /* Checks if both db_store and db_retrieve functions have
167 * been set up.
169 static int
170 db_func_is_ok (gnutls_session_t session)
172 if (session->internals.db_store_func != NULL &&
173 session->internals.db_retrieve_func != NULL &&
174 session->internals.db_remove_func != NULL)
175 return 0;
176 else
177 return GNUTLS_E_DB_ERROR;
180 /* Stores session data to the db backend.
182 static int
183 store_session (gnutls_session_t session,
184 gnutls_datum_t session_id,
185 gnutls_datum_t session_data)
187 int ret = 0;
189 if (session->internals.resumable == RESUME_FALSE)
191 gnutls_assert ();
192 return GNUTLS_E_INVALID_SESSION;
195 if (db_func_is_ok (session) != 0)
197 return GNUTLS_E_DB_ERROR;
200 if (session_id.data == NULL || session_id.size == 0)
202 gnutls_assert ();
203 return GNUTLS_E_INVALID_SESSION;
206 if (session_data.data == NULL || session_data.size == 0)
208 gnutls_assert ();
209 return GNUTLS_E_INVALID_SESSION;
212 /* if we can't read why bother writing? */
213 if (session->internals.db_store_func != NULL)
214 ret = session->internals.db_store_func (session->internals.db_ptr,
215 session_id, session_data);
217 return (ret == 0 ? ret : GNUTLS_E_DB_ERROR);
221 _gnutls_server_register_current_session (gnutls_session_t session)
223 gnutls_datum_t key;
224 gnutls_datum_t content;
225 int ret = 0;
227 key.data = session->security_parameters.session_id;
228 key.size = session->security_parameters.session_id_size;
230 if (session->internals.resumable == RESUME_FALSE)
232 gnutls_assert ();
233 return GNUTLS_E_INVALID_SESSION;
236 if (session->security_parameters.session_id == NULL
237 || session->security_parameters.session_id_size == 0)
239 gnutls_assert ();
240 return GNUTLS_E_INVALID_SESSION;
243 ret = _gnutls_session_pack (session, &content);
244 if (ret < 0)
246 gnutls_assert ();
247 return ret;
250 ret = store_session (session, key, content);
251 _gnutls_free_datum (&content);
253 return ret;
256 /* Retrieves session data from the db backend.
258 static gnutls_datum_t
259 retrieve_session (gnutls_session_t session, gnutls_datum_t session_id)
261 gnutls_datum_t ret = { NULL, 0 };
263 if (session_id.data == NULL || session_id.size == 0)
265 gnutls_assert ();
266 return ret;
269 if (session->internals.db_retrieve_func != NULL)
270 ret = session->internals.db_retrieve_func (session->internals.db_ptr,
271 session_id);
273 return ret;
277 _gnutls_server_restore_session (gnutls_session_t session,
278 uint8_t * session_id, int session_id_size)
280 gnutls_datum_t data;
281 gnutls_datum_t key;
282 int ret;
284 key.data = session_id;
285 key.size = session_id_size;
287 if (db_func_is_ok (session) != 0)
289 gnutls_assert ();
290 return GNUTLS_E_INVALID_SESSION;
293 data = retrieve_session (session, key);
295 if (data.data == NULL)
297 gnutls_assert ();
298 return GNUTLS_E_INVALID_SESSION;
301 /* expiration check is performed inside */
302 ret = gnutls_session_set_data (session, data.data, data.size);
303 if (ret < 0)
305 gnutls_assert ();
306 return ret;
309 gnutls_free (data.data);
311 return 0;
315 * gnutls_db_remove_session:
316 * @session: is a #gnutls_session_t structure.
318 * This function will remove the current session data from the
319 * session database. This will prevent future handshakes reusing
320 * these session data. This function should be called if a session
321 * was terminated abnormally, and before gnutls_deinit() is called.
323 * Normally gnutls_deinit() will remove abnormally terminated
324 * sessions.
326 void
327 gnutls_db_remove_session (gnutls_session_t session)
329 gnutls_datum_t session_id;
330 int ret = 0;
332 session_id.data = session->security_parameters.session_id;
333 session_id.size = session->security_parameters.session_id_size;
335 if (db_func_is_ok (session) != 0)
337 gnutls_assert ();
338 return /* GNUTLS_E_DB_ERROR */;
341 if (session_id.data == NULL || session_id.size == 0)
343 gnutls_assert ();
344 return /* GNUTLS_E_INVALID_SESSION */;
347 /* if we can't read why bother writing? */
348 if (session->internals.db_remove_func != NULL)
350 ret = session->internals.db_remove_func (session->internals.db_ptr,
351 session_id);
352 if (ret != 0)
353 gnutls_assert ();