*** empty log message ***
[gnutls.git] / lib / gnutls_db.c
blob2e79ceeefdeec2777df62eb354424fe83adbc157
1 /*
2 * Copyright (C) 2000 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 /* This file contains functions that manipulate a database
22 * for resumed sessions.
24 #include "gnutls_int.h"
25 #include "gnutls_errors.h"
26 #include "gnutls_session.h"
27 #include "debug.h"
29 #ifdef HAVE_LIBGDBM
30 # define GNUTLS_DBF state->gnutls_internals.db_reader
31 # define GNUTLS_DBNAME state->gnutls_internals.db_name
32 # define GNUTLS_REOPEN_DB() if (GNUTLS_DBF!=NULL) \
33 gdbm_close( GNUTLS_DBF); \
34 GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
35 #endif
37 /**
38 * gnutls_set_cache_expiration - Sets the expiration time for resumed sessions.
39 * @state: is a &GNUTLS_STATE structure.
40 * @seconds: is the number of seconds.
42 * Sets the expiration time for resumed sessions. The default is 3600 (one hour)
43 * at the time writing this.
44 **/
45 int gnutls_set_cache_expiration( GNUTLS_STATE state, int seconds) {
46 state->gnutls_internals.expire_time = seconds;
47 return 0;
50 /**
51 * gnutls_set_db_name - Sets the name of the database that holds TLS sessions.
52 * @state: is a &GNUTLS_STATE structure.
53 * @filename: is the filename for the database
55 * Sets the name of the (gdbm) database to be used to keep
56 * the sessions to be resumed. This function also creates the database
57 * - if it does not exist - and opens it for reading.
58 **/
59 int gnutls_set_db_name( GNUTLS_STATE state, char* filename) {
60 #ifdef HAVE_LIBGDBM
61 GDBM_FILE dbf;
63 if (filename==NULL) return 0;
65 /* deallocate previous name */
66 if (GNUTLS_DBNAME!=NULL)
67 gnutls_free(GNUTLS_DBNAME);
69 /* set name */
70 GNUTLS_DBNAME = gnutls_strdup(filename);
71 if (GNUTLS_DBNAME==NULL) return GNUTLS_E_MEMORY_ERROR;
74 /* open for reader */
75 GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
76 if (GNUTLS_DBF==NULL) {
77 /* maybe it does not exist - so try to
78 * create it.
80 dbf = gdbm_open( filename, 0, GDBM_WRCREAT, 0600, NULL);
81 if (dbf==NULL) return GNUTLS_E_DB_ERROR;
82 gdbm_close(dbf);
84 /* try to open again */
85 GNUTLS_DBF = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
87 if (GNUTLS_DBF==NULL)
88 return GNUTLS_E_DB_ERROR;
90 return 0;
91 #else
92 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
93 #endif
97 /**
98 * gnutls_clean_db - removes expired and invalid sessions from the database
99 * @state: is a &GNUTLS_STATE structure.
101 * This function Deletes all expired records in the resumed sessions' database.
102 * This database may become huge if this function is not called.
103 * (this function is also quite expensive)
105 int gnutls_clean_db( GNUTLS_STATE state) {
106 #ifdef HAVE_LIBGDBM
107 GDBM_FILE dbf;
108 int ret;
109 datum key;
110 time_t timestamp;
112 if (GNUTLS_DBF==NULL) return GNUTLS_E_DB_ERROR;
113 if (GNUTLS_DBNAME==NULL) return GNUTLS_E_DB_ERROR;
115 dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_WRITER, 0600, NULL);
116 if (dbf==NULL) return GNUTLS_E_AGAIN;
117 key = gdbm_firstkey(dbf);
119 timestamp = time(0);
121 while( key.dptr != NULL) {
123 if ( timestamp - ((SecurityParameters*)(key.dptr))->timestamp <= state->gnutls_internals.expire_time || ((SecurityParameters*)(key.dptr))->timestamp > timestamp|| ((SecurityParameters*)(key.dptr))->timestamp == 0) {
124 /* delete expired entry */
125 gdbm_delete( dbf, key);
128 free(key.dptr);
129 key = gdbm_nextkey(dbf, key);
131 ret = gdbm_reorganize(dbf);
133 gdbm_close(dbf);
134 GNUTLS_REOPEN_DB();
136 if (ret!=0) return GNUTLS_E_DB_ERROR;
138 return 0;
139 #else
140 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
141 #endif
145 /* The format of storing data is:
146 * SECURITY_PARAMETERS + AUTH_INFO_SIZE + AUTH_INFO
148 int _gnutls_server_register_current_session( GNUTLS_STATE state)
150 #ifdef HAVE_LIBGDBM
151 GDBM_FILE dbf;
152 datum key = { state->security_parameters.session_id, state->security_parameters.session_id_size };
153 datum content;
154 int ret = 0;
156 if (state->gnutls_internals.resumable==RESUME_FALSE)
157 return GNUTLS_E_INVALID_SESSION;
159 if (GNUTLS_DBNAME==NULL)
160 return GNUTLS_E_DB_ERROR;
162 if (state->security_parameters.session_id==NULL || state->security_parameters.session_id_size==0)
163 return GNUTLS_E_INVALID_SESSION;
165 /* if we can't read why bother writing? */
166 if (GNUTLS_DBF==NULL)
167 return GNUTLS_E_DB_ERROR;
169 /* allocate space for data */
170 content.dsize = sizeof(SecurityParameters) + state->gnutls_key->auth_info_size
171 + sizeof(state->gnutls_key->auth_info_size);
172 content.dptr = gnutls_malloc( content.dsize);
173 if (content.dptr==NULL) return GNUTLS_E_MEMORY_ERROR;
175 /* copy data */
176 memcpy( content.dptr, (void*)&state->security_parameters, sizeof(SecurityParameters));
177 memcpy( &content.dptr[sizeof(SecurityParameters)], &state->gnutls_key->auth_info_size, sizeof(state->gnutls_key->auth_info_size));
178 memcpy( &content.dptr[sizeof(state->gnutls_key->auth_info_size)+sizeof(SecurityParameters)],
179 state->gnutls_key->auth_info, state->gnutls_key->auth_info_size);
181 dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_WRITER, 0600, NULL);
182 if (dbf==NULL) {
183 gnutls_free(content.dptr);
184 /* cannot open db for writing. This may happen if multiple
185 * instances try to write.
187 return GNUTLS_E_AGAIN;
189 ret = gdbm_store( dbf, key, content, GDBM_INSERT);
191 gnutls_free( content.dptr);
193 gdbm_close(dbf);
194 return (ret == 0 ? ret : GNUTLS_E_UNKNOWN_ERROR);
195 #else
196 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
197 #endif
200 int _gnutls_server_restore_session( GNUTLS_STATE state, uint8* session_id, int session_id_size)
202 #ifdef HAVE_LIBGDBM
203 datum content;
204 datum key = { session_id, session_id_size};
205 int ret;
207 if (GNUTLS_DBNAME==NULL) return GNUTLS_E_DB_ERROR;
209 if (GNUTLS_DBF==NULL) return GNUTLS_E_DB_ERROR;
210 content = gdbm_fetch( GNUTLS_DBF, key);
212 if (content.dptr==NULL) {
213 return GNUTLS_E_INVALID_SESSION;
216 /* expiration check is performed inside */
217 ret = gnutls_set_current_session( state, content.dptr, content.dsize);
218 free(content.dptr);
220 return ret;
221 #else
222 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
223 #endif
226 int _gnutls_db_remove_session( GNUTLS_STATE state, uint8* session_id, int session_id_size)
228 #ifdef HAVE_LIBGDBM
229 GDBM_FILE dbf;
230 datum key = { session_id, session_id_size};
231 int ret;
233 if (GNUTLS_DBNAME==NULL) return GNUTLS_E_DB_ERROR;
235 dbf = gdbm_open(GNUTLS_DBNAME, 0, GDBM_READER, 0600, NULL);
236 if (dbf==NULL) return GNUTLS_E_AGAIN;
237 ret = gdbm_delete( dbf, key);
238 gdbm_close(dbf);
240 return (ret==0 ? ret : GNUTLS_E_DB_ERROR);
241 #else
242 return GNUTLS_E_UNIMPLEMENTED_FEATURE;
243 #endif