Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hdb/db.c
34889 views
1
/*
2
* Copyright (c) 1997 - 2001 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_DB1
37
38
#if defined(HAVE_DB_185_H)
39
#include <db_185.h>
40
#elif defined(HAVE_DB_H)
41
#include <db.h>
42
#endif
43
44
static krb5_error_code
45
DB_close(krb5_context context, HDB *db)
46
{
47
DB *d = (DB*)db->hdb_db;
48
(*d->close)(d);
49
return 0;
50
}
51
52
static krb5_error_code
53
DB_destroy(krb5_context context, HDB *db)
54
{
55
krb5_error_code ret;
56
57
ret = hdb_clear_master_key (context, db);
58
free(db->hdb_name);
59
free(db);
60
return ret;
61
}
62
63
static krb5_error_code
64
DB_lock(krb5_context context, HDB *db, int operation)
65
{
66
DB *d = (DB*)db->hdb_db;
67
int fd = (*d->fd)(d);
68
if(fd < 0) {
69
krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB,
70
"Can't lock database: %s", db->hdb_name);
71
return HDB_ERR_CANT_LOCK_DB;
72
}
73
return hdb_lock(fd, operation);
74
}
75
76
static krb5_error_code
77
DB_unlock(krb5_context context, HDB *db)
78
{
79
DB *d = (DB*)db->hdb_db;
80
int fd = (*d->fd)(d);
81
if(fd < 0) {
82
krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB,
83
"Can't unlock database: %s", db->hdb_name);
84
return HDB_ERR_CANT_LOCK_DB;
85
}
86
return hdb_unlock(fd);
87
}
88
89
90
static krb5_error_code
91
DB_seq(krb5_context context, HDB *db,
92
unsigned flags, hdb_entry_ex *entry, int flag)
93
{
94
DB *d = (DB*)db->hdb_db;
95
DBT key, value;
96
krb5_data key_data, data;
97
int code;
98
99
code = db->hdb_lock(context, db, HDB_RLOCK);
100
if(code == -1) {
101
krb5_set_error_message(context, HDB_ERR_DB_INUSE, "Database %s in use", db->hdb_name);
102
return HDB_ERR_DB_INUSE;
103
}
104
code = (*d->seq)(d, &key, &value, flag);
105
db->hdb_unlock(context, db); /* XXX check value */
106
if(code == -1) {
107
code = errno;
108
krb5_set_error_message(context, code, "Database %s seq error: %s",
109
db->hdb_name, strerror(code));
110
return code;
111
}
112
if(code == 1) {
113
krb5_clear_error_message(context);
114
return HDB_ERR_NOENTRY;
115
}
116
117
key_data.data = key.data;
118
key_data.length = key.size;
119
data.data = value.data;
120
data.length = value.size;
121
memset(entry, 0, sizeof(*entry));
122
if (hdb_value2entry(context, &data, &entry->entry))
123
return DB_seq(context, db, flags, entry, R_NEXT);
124
if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
125
code = hdb_unseal_keys (context, db, &entry->entry);
126
if (code)
127
hdb_free_entry (context, entry);
128
}
129
if (code == 0 && entry->entry.principal == NULL) {
130
entry->entry.principal = malloc(sizeof(*entry->entry.principal));
131
if (entry->entry.principal == NULL) {
132
code = ENOMEM;
133
krb5_set_error_message(context, code, "malloc: out of memory");
134
hdb_free_entry (context, entry);
135
} else {
136
hdb_key2principal(context, &key_data, entry->entry.principal);
137
}
138
}
139
return code;
140
}
141
142
143
static krb5_error_code
144
DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
145
{
146
return DB_seq(context, db, flags, entry, R_FIRST);
147
}
148
149
150
static krb5_error_code
151
DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
152
{
153
return DB_seq(context, db, flags, entry, R_NEXT);
154
}
155
156
static krb5_error_code
157
DB_rename(krb5_context context, HDB *db, const char *new_name)
158
{
159
int ret;
160
char *old, *new;
161
162
asprintf(&old, "%s.db", db->hdb_name);
163
asprintf(&new, "%s.db", new_name);
164
ret = rename(old, new);
165
free(old);
166
free(new);
167
if(ret)
168
return errno;
169
170
free(db->hdb_name);
171
db->hdb_name = strdup(new_name);
172
return 0;
173
}
174
175
static krb5_error_code
176
DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
177
{
178
DB *d = (DB*)db->hdb_db;
179
DBT k, v;
180
int code;
181
182
k.data = key.data;
183
k.size = key.length;
184
code = db->hdb_lock(context, db, HDB_RLOCK);
185
if(code)
186
return code;
187
code = (*d->get)(d, &k, &v, 0);
188
db->hdb_unlock(context, db);
189
if(code < 0) {
190
code = errno;
191
krb5_set_error_message(context, code, "Database %s get error: %s",
192
db->hdb_name, strerror(code));
193
return code;
194
}
195
if(code == 1) {
196
krb5_clear_error_message(context);
197
return HDB_ERR_NOENTRY;
198
}
199
200
krb5_data_copy(reply, v.data, v.size);
201
return 0;
202
}
203
204
static krb5_error_code
205
DB__put(krb5_context context, HDB *db, int replace,
206
krb5_data key, krb5_data value)
207
{
208
DB *d = (DB*)db->hdb_db;
209
DBT k, v;
210
int code;
211
212
k.data = key.data;
213
k.size = key.length;
214
v.data = value.data;
215
v.size = value.length;
216
code = db->hdb_lock(context, db, HDB_WLOCK);
217
if(code)
218
return code;
219
code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE);
220
db->hdb_unlock(context, db);
221
if(code < 0) {
222
code = errno;
223
krb5_set_error_message(context, code, "Database %s put error: %s",
224
db->hdb_name, strerror(code));
225
return code;
226
}
227
if(code == 1) {
228
krb5_clear_error_message(context);
229
return HDB_ERR_EXISTS;
230
}
231
return 0;
232
}
233
234
static krb5_error_code
235
DB__del(krb5_context context, HDB *db, krb5_data key)
236
{
237
DB *d = (DB*)db->hdb_db;
238
DBT k;
239
krb5_error_code code;
240
k.data = key.data;
241
k.size = key.length;
242
code = db->hdb_lock(context, db, HDB_WLOCK);
243
if(code)
244
return code;
245
code = (*d->del)(d, &k, 0);
246
db->hdb_unlock(context, db);
247
if(code == 1) {
248
code = errno;
249
krb5_set_error_message(context, code, "Database %s put error: %s",
250
db->hdb_name, strerror(code));
251
return code;
252
}
253
if(code < 0)
254
return errno;
255
return 0;
256
}
257
258
static krb5_error_code
259
DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
260
{
261
char *fn;
262
krb5_error_code ret;
263
264
asprintf(&fn, "%s.db", db->hdb_name);
265
if (fn == NULL) {
266
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
267
return ENOMEM;
268
}
269
db->hdb_db = dbopen(fn, flags, mode, DB_BTREE, NULL);
270
free(fn);
271
/* try to open without .db extension */
272
if(db->hdb_db == NULL && errno == ENOENT)
273
db->hdb_db = dbopen(db->hdb_name, flags, mode, DB_BTREE, NULL);
274
if(db->hdb_db == NULL) {
275
ret = errno;
276
krb5_set_error_message(context, ret, "dbopen (%s): %s",
277
db->hdb_name, strerror(ret));
278
return ret;
279
}
280
if((flags & O_ACCMODE) == O_RDONLY)
281
ret = hdb_check_db_format(context, db);
282
else
283
ret = hdb_init_db(context, db);
284
if(ret == HDB_ERR_NOENTRY) {
285
krb5_clear_error_message(context);
286
return 0;
287
}
288
if (ret) {
289
DB_close(context, db);
290
krb5_set_error_message(context, ret, "hdb_open: failed %s database %s",
291
(flags & O_ACCMODE) == O_RDONLY ?
292
"checking format of" : "initialize",
293
db->hdb_name);
294
}
295
return ret;
296
}
297
298
krb5_error_code
299
hdb_db_create(krb5_context context, HDB **db,
300
const char *filename)
301
{
302
*db = calloc(1, sizeof(**db));
303
if (*db == NULL) {
304
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
305
return ENOMEM;
306
}
307
308
(*db)->hdb_db = NULL;
309
(*db)->hdb_name = strdup(filename);
310
if ((*db)->hdb_name == NULL) {
311
free(*db);
312
*db = NULL;
313
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
314
return ENOMEM;
315
}
316
(*db)->hdb_master_key_set = 0;
317
(*db)->hdb_openp = 0;
318
(*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
319
(*db)->hdb_open = DB_open;
320
(*db)->hdb_close = DB_close;
321
(*db)->hdb_fetch_kvno = _hdb_fetch_kvno;
322
(*db)->hdb_store = _hdb_store;
323
(*db)->hdb_remove = _hdb_remove;
324
(*db)->hdb_firstkey = DB_firstkey;
325
(*db)->hdb_nextkey= DB_nextkey;
326
(*db)->hdb_lock = DB_lock;
327
(*db)->hdb_unlock = DB_unlock;
328
(*db)->hdb_rename = DB_rename;
329
(*db)->hdb__get = DB__get;
330
(*db)->hdb__put = DB__put;
331
(*db)->hdb__del = DB__del;
332
(*db)->hdb_destroy = DB_destroy;
333
return 0;
334
}
335
336
#endif /* HAVE_DB1 */
337
338