afslog.1: Remove documentation for removed no-v4 argument.
[heimdal.git] / lib / hdb / db.c
blob106e95f5a78341cf66b1ffffe3184872ae63a4a1
1 /*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "hdb_locl.h"
36 #if HAVE_DB1
38 #if defined(HAVE_DB_185_H)
39 #include <db_185.h>
40 #elif defined(HAVE_DB_H)
41 #include <db.h>
42 #endif
44 typedef struct {
45 HDB hdb; /* generic members */
46 int lock_fd; /* DB-specific */
47 } DB1_HDB;
49 static krb5_error_code
50 DB_close(krb5_context context, HDB *db)
52 DB1_HDB *db1 = (DB1_HDB *)db;
53 DB *d = (DB*)db->hdb_db;
55 heim_assert(d != 0, "Closing already closed HDB");
57 (*d->close)(d);
58 db->hdb_db = 0;
60 if (db1->lock_fd >= 0) {
61 close(db1->lock_fd);
62 db1->lock_fd = -1;
65 return 0;
68 static krb5_error_code
69 DB_destroy(krb5_context context, HDB *db)
71 krb5_error_code ret;
73 ret = hdb_clear_master_key (context, db);
74 free(db->hdb_name);
75 free(db);
76 return ret;
79 static krb5_error_code
80 DB_lock(krb5_context context, HDB *db, int operation)
83 return 0;
86 static krb5_error_code
87 DB_unlock(krb5_context context, HDB *db)
90 return 0;
94 static krb5_error_code
95 DB_seq(krb5_context context, HDB *db,
96 unsigned flags, hdb_entry_ex *entry, int flag)
98 DB *d = (DB*)db->hdb_db;
99 DBT key, value;
100 krb5_data key_data, data;
101 int code;
103 code = (*d->seq)(d, &key, &value, flag);
104 if(code == -1) {
105 code = errno;
106 krb5_set_error_message(context, code, "Database %s seq error: %s",
107 db->hdb_name, strerror(code));
108 return code;
110 if(code == 1) {
111 krb5_clear_error_message(context);
112 return HDB_ERR_NOENTRY;
115 key_data.data = key.data;
116 key_data.length = key.size;
117 data.data = value.data;
118 data.length = value.size;
119 memset(entry, 0, sizeof(*entry));
120 if (hdb_value2entry(context, &data, &entry->entry))
121 return DB_seq(context, db, flags, entry, R_NEXT);
122 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
123 code = hdb_unseal_keys (context, db, &entry->entry);
124 if (code)
125 hdb_free_entry (context, entry);
127 if (code == 0 && entry->entry.principal == NULL) {
128 entry->entry.principal = malloc(sizeof(*entry->entry.principal));
129 if (entry->entry.principal == NULL) {
130 code = ENOMEM;
131 krb5_set_error_message(context, code, "malloc: out of memory");
132 hdb_free_entry (context, entry);
133 } else {
134 hdb_key2principal(context, &key_data, entry->entry.principal);
137 return code;
141 static krb5_error_code
142 DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
144 return DB_seq(context, db, flags, entry, R_FIRST);
148 static krb5_error_code
149 DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
151 return DB_seq(context, db, flags, entry, R_NEXT);
154 static krb5_error_code
155 DB_rename(krb5_context context, HDB *db, const char *new_name)
157 int ret;
158 char *old, *new;
160 asprintf(&old, "%s.db", db->hdb_name);
161 asprintf(&new, "%s.db", new_name);
162 ret = rename(old, new);
163 free(old);
164 free(new);
165 if(ret)
166 return errno;
168 free(db->hdb_name);
169 db->hdb_name = strdup(new_name);
170 return 0;
173 static krb5_error_code
174 DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
176 DB *d = (DB*)db->hdb_db;
177 DBT k, v;
178 int code;
180 k.data = key.data;
181 k.size = key.length;
182 code = (*d->get)(d, &k, &v, 0);
183 if(code < 0) {
184 code = errno;
185 krb5_set_error_message(context, code, "Database %s get error: %s",
186 db->hdb_name, strerror(code));
187 return code;
189 if(code == 1) {
190 krb5_clear_error_message(context);
191 return HDB_ERR_NOENTRY;
194 krb5_data_copy(reply, v.data, v.size);
195 return 0;
198 static krb5_error_code
199 DB__put(krb5_context context, HDB *db, int replace,
200 krb5_data key, krb5_data value)
202 DB *d = (DB*)db->hdb_db;
203 DBT k, v;
204 int code;
206 k.data = key.data;
207 k.size = key.length;
208 v.data = value.data;
209 v.size = value.length;
210 code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE);
211 if(code < 0) {
212 code = errno;
213 krb5_set_error_message(context, code, "Database %s put error: %s",
214 db->hdb_name, strerror(code));
215 return code;
217 if(code == 1) {
218 krb5_clear_error_message(context);
219 return HDB_ERR_EXISTS;
221 return 0;
224 static krb5_error_code
225 DB__del(krb5_context context, HDB *db, krb5_data key)
227 DB *d = (DB*)db->hdb_db;
228 DBT k;
229 krb5_error_code code;
230 k.data = key.data;
231 k.size = key.length;
232 code = (*d->del)(d, &k, 0);
233 if(code == 1) {
234 code = errno;
235 krb5_set_error_message(context, code, "Database %s put error: %s",
236 db->hdb_name, strerror(code));
237 return code;
239 if(code < 0)
240 return errno;
241 return 0;
244 static DB *
245 _open_db(char *fn, int flags, int mode, int *fd)
247 #ifndef O_EXLOCK
248 int op;
249 int ret;
251 *fd = open(fn, flags, mode);
252 if (*fd == -1)
253 return NULL;
255 if ((flags & O_ACCMODE) == O_RDONLY)
256 op = LOCK_SH;
257 else
258 op = LOCK_EX;
260 ret = flock(*fd, op);
261 if (ret == -1) {
262 int saved_errno;
264 saved_errno = errno;
265 close(*fd);
266 errno = saved_errno;
267 return NULL;
269 #else
270 if ((flags & O_ACCMODE) == O_RDONLY)
271 flags |= O_SHLOCK;
272 else
273 flags |= O_EXLOCK;
274 #endif
276 return dbopen(fn, flags, mode, DB_BTREE, NULL);
279 static krb5_error_code
280 DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
282 DB1_HDB *db1 = (DB1_HDB *)db;
283 char *fn;
284 krb5_error_code ret;
286 asprintf(&fn, "%s.db", db->hdb_name);
287 if (fn == NULL) {
288 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
289 return ENOMEM;
291 db->hdb_db = _open_db(fn, flags, mode, &db1->lock_fd);
292 free(fn);
293 /* try to open without .db extension */
294 if(db->hdb_db == NULL && errno == ENOENT)
295 db->hdb_db = _open_db(db->hdb_name, flags, mode, &db1->lock_fd);
296 if(db->hdb_db == NULL) {
297 krb5_set_error_message(context, errno, "dbopen (%s): %s",
298 db->hdb_name, strerror(errno));
299 return errno;
301 if((flags & O_ACCMODE) == O_RDONLY)
302 ret = hdb_check_db_format(context, db);
303 else
304 ret = hdb_init_db(context, db);
305 if(ret == HDB_ERR_NOENTRY) {
306 krb5_clear_error_message(context);
307 return 0;
309 if (ret) {
310 DB_close(context, db);
311 krb5_set_error_message(context, ret, "hdb_open: failed %s database %s",
312 (flags & O_ACCMODE) == O_RDONLY ?
313 "checking format of" : "initialize",
314 db->hdb_name);
316 return ret;
319 krb5_error_code
320 hdb_db_create(krb5_context context, HDB **db,
321 const char *filename)
323 DB1_HDB **db1 = (DB1_HDB **)db;
324 *db = calloc(1, sizeof(**db1)); /* Allocate space for the larger db1 */
325 if (*db == NULL) {
326 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
327 return ENOMEM;
330 (*db)->hdb_db = NULL;
331 (*db)->hdb_name = strdup(filename);
332 if ((*db)->hdb_name == NULL) {
333 free(*db);
334 *db = NULL;
335 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
336 return ENOMEM;
338 (*db)->hdb_master_key_set = 0;
339 (*db)->hdb_openp = 0;
340 (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
341 (*db)->hdb_open = DB_open;
342 (*db)->hdb_close = DB_close;
343 (*db)->hdb_fetch_kvno = _hdb_fetch_kvno;
344 (*db)->hdb_store = _hdb_store;
345 (*db)->hdb_remove = _hdb_remove;
346 (*db)->hdb_firstkey = DB_firstkey;
347 (*db)->hdb_nextkey= DB_nextkey;
348 (*db)->hdb_lock = DB_lock;
349 (*db)->hdb_unlock = DB_unlock;
350 (*db)->hdb_rename = DB_rename;
351 (*db)->hdb__get = DB__get;
352 (*db)->hdb__put = DB__put;
353 (*db)->hdb__del = DB__del;
354 (*db)->hdb_destroy = DB_destroy;
356 (*db1)->lock_fd = -1;
357 return 0;
360 #endif /* HAVE_DB1 */