Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hdb/db3.c
34889 views
1
/*
2
* Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
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.
16
*
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.
20
*
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.
32
*/
33
34
#include "hdb_locl.h"
35
36
#if HAVE_DB3
37
38
#ifdef HAVE_DBHEADER
39
#include <db.h>
40
#elif HAVE_DB5_DB_H
41
#include <db5/db.h>
42
#elif HAVE_DB4_DB_H
43
#include <db4/db.h>
44
#elif HAVE_DB3_DB_H
45
#include <db3/db.h>
46
#else
47
#include <db.h>
48
#endif
49
50
static krb5_error_code
51
DB_close(krb5_context context, HDB *db)
52
{
53
DB *d = (DB*)db->hdb_db;
54
DBC *dbcp = (DBC*)db->hdb_dbc;
55
56
(*dbcp->c_close)(dbcp);
57
db->hdb_dbc = 0;
58
(*d->close)(d, 0);
59
return 0;
60
}
61
62
static krb5_error_code
63
DB_destroy(krb5_context context, HDB *db)
64
{
65
krb5_error_code ret;
66
67
ret = hdb_clear_master_key (context, db);
68
free(db->hdb_name);
69
free(db);
70
return ret;
71
}
72
73
static krb5_error_code
74
DB_lock(krb5_context context, HDB *db, int operation)
75
{
76
DB *d = (DB*)db->hdb_db;
77
int fd;
78
if ((*d->fd)(d, &fd))
79
return HDB_ERR_CANT_LOCK_DB;
80
return hdb_lock(fd, operation);
81
}
82
83
static krb5_error_code
84
DB_unlock(krb5_context context, HDB *db)
85
{
86
DB *d = (DB*)db->hdb_db;
87
int fd;
88
if ((*d->fd)(d, &fd))
89
return HDB_ERR_CANT_LOCK_DB;
90
return hdb_unlock(fd);
91
}
92
93
94
static krb5_error_code
95
DB_seq(krb5_context context, HDB *db,
96
unsigned flags, hdb_entry_ex *entry, int flag)
97
{
98
DBT key, value;
99
DBC *dbcp = db->hdb_dbc;
100
krb5_data key_data, data;
101
int code;
102
103
memset(&key, 0, sizeof(DBT));
104
memset(&value, 0, sizeof(DBT));
105
if ((*db->hdb_lock)(context, db, HDB_RLOCK))
106
return HDB_ERR_DB_INUSE;
107
code = (*dbcp->c_get)(dbcp, &key, &value, flag);
108
(*db->hdb_unlock)(context, db); /* XXX check value */
109
if (code == DB_NOTFOUND)
110
return HDB_ERR_NOENTRY;
111
if (code)
112
return code;
113
114
key_data.data = key.data;
115
key_data.length = key.size;
116
data.data = value.data;
117
data.length = value.size;
118
memset(entry, 0, sizeof(*entry));
119
if (hdb_value2entry(context, &data, &entry->entry))
120
return DB_seq(context, db, flags, entry, DB_NEXT);
121
if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
122
code = hdb_unseal_keys (context, db, &entry->entry);
123
if (code)
124
hdb_free_entry (context, entry);
125
}
126
if (entry->entry.principal == NULL) {
127
entry->entry.principal = malloc(sizeof(*entry->entry.principal));
128
if (entry->entry.principal == NULL) {
129
hdb_free_entry (context, entry);
130
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
131
return ENOMEM;
132
} else {
133
hdb_key2principal(context, &key_data, entry->entry.principal);
134
}
135
}
136
return 0;
137
}
138
139
140
static krb5_error_code
141
DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
142
{
143
return DB_seq(context, db, flags, entry, DB_FIRST);
144
}
145
146
147
static krb5_error_code
148
DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
149
{
150
return DB_seq(context, db, flags, entry, DB_NEXT);
151
}
152
153
static krb5_error_code
154
DB_rename(krb5_context context, HDB *db, const char *new_name)
155
{
156
int ret;
157
char *old, *new;
158
159
asprintf(&old, "%s.db", db->hdb_name);
160
asprintf(&new, "%s.db", new_name);
161
ret = rename(old, new);
162
free(old);
163
free(new);
164
if(ret)
165
return errno;
166
167
free(db->hdb_name);
168
db->hdb_name = strdup(new_name);
169
return 0;
170
}
171
172
static krb5_error_code
173
DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
174
{
175
DB *d = (DB*)db->hdb_db;
176
DBT k, v;
177
int code;
178
179
memset(&k, 0, sizeof(DBT));
180
memset(&v, 0, sizeof(DBT));
181
k.data = key.data;
182
k.size = key.length;
183
k.flags = 0;
184
if ((code = (*db->hdb_lock)(context, db, HDB_RLOCK)))
185
return code;
186
code = (*d->get)(d, NULL, &k, &v, 0);
187
(*db->hdb_unlock)(context, db);
188
if(code == DB_NOTFOUND)
189
return HDB_ERR_NOENTRY;
190
if(code)
191
return code;
192
193
krb5_data_copy(reply, v.data, v.size);
194
return 0;
195
}
196
197
static krb5_error_code
198
DB__put(krb5_context context, HDB *db, int replace,
199
krb5_data key, krb5_data value)
200
{
201
DB *d = (DB*)db->hdb_db;
202
DBT k, v;
203
int code;
204
205
memset(&k, 0, sizeof(DBT));
206
memset(&v, 0, sizeof(DBT));
207
k.data = key.data;
208
k.size = key.length;
209
k.flags = 0;
210
v.data = value.data;
211
v.size = value.length;
212
v.flags = 0;
213
if ((code = (*db->hdb_lock)(context, db, HDB_WLOCK)))
214
return code;
215
code = (*d->put)(d, NULL, &k, &v, replace ? 0 : DB_NOOVERWRITE);
216
(*db->hdb_unlock)(context, db);
217
if(code == DB_KEYEXIST)
218
return HDB_ERR_EXISTS;
219
if(code)
220
return errno;
221
return 0;
222
}
223
224
static krb5_error_code
225
DB__del(krb5_context context, HDB *db, krb5_data key)
226
{
227
DB *d = (DB*)db->hdb_db;
228
DBT k;
229
krb5_error_code code;
230
memset(&k, 0, sizeof(DBT));
231
k.data = key.data;
232
k.size = key.length;
233
k.flags = 0;
234
code = (*db->hdb_lock)(context, db, HDB_WLOCK);
235
if(code)
236
return code;
237
code = (*d->del)(d, NULL, &k, 0);
238
(*db->hdb_unlock)(context, db);
239
if(code == DB_NOTFOUND)
240
return HDB_ERR_NOENTRY;
241
if(code)
242
return code;
243
return 0;
244
}
245
246
static krb5_error_code
247
DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
248
{
249
DBC *dbc = NULL;
250
char *fn;
251
krb5_error_code ret;
252
DB *d;
253
int myflags = 0;
254
255
if (flags & O_CREAT)
256
myflags |= DB_CREATE;
257
258
if (flags & O_EXCL)
259
myflags |= DB_EXCL;
260
261
if((flags & O_ACCMODE) == O_RDONLY)
262
myflags |= DB_RDONLY;
263
264
if (flags & O_TRUNC)
265
myflags |= DB_TRUNCATE;
266
267
asprintf(&fn, "%s.db", db->hdb_name);
268
if (fn == NULL) {
269
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
270
return ENOMEM;
271
}
272
if (db_create(&d, NULL, 0) != 0) {
273
free(fn);
274
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
275
return ENOMEM;
276
}
277
db->hdb_db = d;
278
279
#if (DB_VERSION_MAJOR >= 4) && (DB_VERSION_MINOR >= 1)
280
ret = (*d->open)(db->hdb_db, NULL, fn, NULL, DB_BTREE, myflags, mode);
281
#else
282
ret = (*d->open)(db->hdb_db, fn, NULL, DB_BTREE, myflags, mode);
283
#endif
284
285
if (ret == ENOENT) {
286
/* try to open without .db extension */
287
#if (DB_VERSION_MAJOR >= 4) && (DB_VERSION_MINOR >= 1)
288
ret = (*d->open)(db->hdb_db, NULL, db->hdb_name, NULL, DB_BTREE,
289
myflags, mode);
290
#else
291
ret = (*d->open)(db->hdb_db, db->hdb_name, NULL, DB_BTREE,
292
myflags, mode);
293
#endif
294
}
295
296
if (ret) {
297
free(fn);
298
krb5_set_error_message(context, ret, "opening %s: %s",
299
db->hdb_name, strerror(ret));
300
return ret;
301
}
302
free(fn);
303
304
ret = (*d->cursor)(d, NULL, &dbc, 0);
305
if (ret) {
306
krb5_set_error_message(context, ret, "d->cursor: %s", strerror(ret));
307
return ret;
308
}
309
db->hdb_dbc = dbc;
310
311
if((flags & O_ACCMODE) == O_RDONLY)
312
ret = hdb_check_db_format(context, db);
313
else
314
ret = hdb_init_db(context, db);
315
if(ret == HDB_ERR_NOENTRY)
316
return 0;
317
if (ret) {
318
DB_close(context, db);
319
krb5_set_error_message(context, ret, "hdb_open: failed %s database %s",
320
(flags & O_ACCMODE) == O_RDONLY ?
321
"checking format of" : "initialize",
322
db->hdb_name);
323
}
324
325
return ret;
326
}
327
328
krb5_error_code
329
hdb_db_create(krb5_context context, HDB **db,
330
const char *filename)
331
{
332
*db = calloc(1, sizeof(**db));
333
if (*db == NULL) {
334
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
335
return ENOMEM;
336
}
337
338
(*db)->hdb_db = NULL;
339
(*db)->hdb_name = strdup(filename);
340
if ((*db)->hdb_name == NULL) {
341
free(*db);
342
*db = NULL;
343
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
344
return ENOMEM;
345
}
346
(*db)->hdb_master_key_set = 0;
347
(*db)->hdb_openp = 0;
348
(*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
349
(*db)->hdb_open = DB_open;
350
(*db)->hdb_close = DB_close;
351
(*db)->hdb_fetch_kvno = _hdb_fetch_kvno;
352
(*db)->hdb_store = _hdb_store;
353
(*db)->hdb_remove = _hdb_remove;
354
(*db)->hdb_firstkey = DB_firstkey;
355
(*db)->hdb_nextkey= DB_nextkey;
356
(*db)->hdb_lock = DB_lock;
357
(*db)->hdb_unlock = DB_unlock;
358
(*db)->hdb_rename = DB_rename;
359
(*db)->hdb__get = DB__get;
360
(*db)->hdb__put = DB__put;
361
(*db)->hdb__del = DB__del;
362
(*db)->hdb_destroy = DB_destroy;
363
return 0;
364
}
365
#endif /* HAVE_DB3 */
366
367