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"
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);
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.
45 int gnutls_set_cache_expiration( GNUTLS_STATE state
, int seconds
) {
46 state
->gnutls_internals
.expire_time
= seconds
;
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.
59 int gnutls_set_db_name( GNUTLS_STATE state
, char* filename
) {
63 if (filename
==NULL
) return 0;
65 /* deallocate previous name */
66 if (GNUTLS_DBNAME
!=NULL
)
67 gnutls_free(GNUTLS_DBNAME
);
70 GNUTLS_DBNAME
= gnutls_strdup(filename
);
71 if (GNUTLS_DBNAME
==NULL
) return GNUTLS_E_MEMORY_ERROR
;
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
80 dbf
= gdbm_open( filename
, 0, GDBM_WRCREAT
, 0600, NULL
);
81 if (dbf
==NULL
) return GNUTLS_E_DB_ERROR
;
84 /* try to open again */
85 GNUTLS_DBF
= gdbm_open(GNUTLS_DBNAME
, 0, GDBM_READER
, 0600, NULL
);
88 return GNUTLS_E_DB_ERROR
;
92 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
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
) {
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
);
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
);
129 key
= gdbm_nextkey(dbf
, key
);
131 ret
= gdbm_reorganize(dbf
);
136 if (ret
!=0) return GNUTLS_E_DB_ERROR
;
140 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
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
)
152 datum key
= { state
->security_parameters
.session_id
, state
->security_parameters
.session_id_size
};
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
;
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
);
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
);
194 return (ret
== 0 ? ret
: GNUTLS_E_UNKNOWN_ERROR
);
196 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
200 int _gnutls_server_restore_session( GNUTLS_STATE state
, uint8
* session_id
, int session_id_size
)
204 datum key
= { session_id
, session_id_size
};
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
);
222 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;
226 int _gnutls_db_remove_session( GNUTLS_STATE state
, uint8
* session_id
, int session_id_size
)
230 datum key
= { session_id
, session_id_size
};
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
);
240 return (ret
==0 ? ret
: GNUTLS_E_DB_ERROR
);
242 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;