~ubuntu-branches/ubuntu/precise/krb5/precise-updates

« back to all changes in this revision

Viewing changes to src/plugins/kdb/db2/kdb_db2.c

  • Committer: Package Import Robot
  • Author(s): Sam Hartman
  • Date: 2011-12-01 19:34:41 UTC
  • mfrom: (28.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20111201193441-9tipg3aru1jsidyv
Tags: 1.10+dfsg~alpha1-6
* Fix segfault with unknown hostnames in krb5_sname_to_principal,
  Closes: #650671
* Indicate that this library breaks libsmbclient versions that depend on
  krb5_locate_kdc, Closes: #650603, #650611

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 
2
/* plugins/kdb/db2/kdb_db2.c */
2
3
/*
3
 
 * lib/kdb/kdb_db2.c
4
 
 *
5
4
 * Copyright 1997,2006,2007-2009 by the Massachusetts Institute of Technology.
6
5
 * All Rights Reserved.
7
6
 *
69
68
 
70
69
#define KDB_DB2_DATABASE_NAME "database_name"
71
70
 
72
 
static krb5_error_code krb5_db2_start_update(krb5_context);
73
 
static krb5_error_code krb5_db2_end_update(krb5_context);
 
71
#define SUFFIX_DB ""
 
72
#define SUFFIX_LOCK ".ok"
 
73
#define SUFFIX_POLICY ".kadm5"
 
74
#define SUFFIX_POLICY_LOCK ".kadm5.lock"
74
75
 
75
76
/*
76
77
 * Locking:
116
117
 * retry the operation.
117
118
 */
118
119
 
119
 
#define free_dbsuffix(name) free(name)
120
 
 
121
 
/*
122
 
 * Routines to deal with context.
123
 
 */
124
 
#define k5db2_inited(c) (c->dal_handle->db_context                   \
125
 
                         && ((krb5_db2_context *) c->dal_handle->db_context)->db_inited)
 
120
/* Evaluate to true if the krb5_context c contains an initialized db2
 
121
 * context. */
 
122
#define inited(c) ((c)->dal_handle->db_context &&                       \
 
123
                   ((krb5_db2_context *)(c)->dal_handle->db_context)->  \
 
124
                   db_inited)
126
125
 
127
126
static krb5_error_code
128
 
krb5_db2_get_db_opt(char *input, char **opt, char **val)
 
127
get_db_opt(char *input, char **opt, char **val)
129
128
{
130
129
    char   *pos = strchr(input, '=');
131
130
    if (pos == NULL) {
151
150
 
152
151
}
153
152
 
154
 
/*
155
 
 * Restore the default context.
156
 
 */
 
153
/* Restore dbctx to the uninitialized state. */
157
154
static void
158
 
k5db2_clear_context(krb5_db2_context *dbctx)
 
155
ctx_clear(krb5_db2_context *dbc)
159
156
{
160
157
    /*
161
158
     * Free any dynamically allocated memory.  File descriptors and locks
162
159
     * are the caller's problem.
163
160
     */
164
 
    free(dbctx->db_lf_name);
165
 
    free(dbctx->db_name);
 
161
    free(dbc->db_lf_name);
 
162
    free(dbc->db_name);
166
163
    /*
167
164
     * Clear the structure and reset the defaults.
168
165
     */
169
 
    memset(dbctx, 0, sizeof(krb5_db2_context));
170
 
    dbctx->db_name = NULL;
171
 
    dbctx->db_nb_locks = FALSE;
172
 
    dbctx->tempdb = FALSE;
 
166
    memset(dbc, 0, sizeof(krb5_db2_context));
 
167
    dbc->db = NULL;
 
168
    dbc->db_lf_name = NULL;
 
169
    dbc->db_lf_file = -1;
 
170
    dbc->db_name = NULL;
 
171
    dbc->db_nb_locks = FALSE;
 
172
    dbc->tempdb = FALSE;
173
173
}
174
174
 
 
175
/* Set *dbc_out to the db2 database context for context.  If one does not
 
176
 * exist, create one in the uninitialized state. */
175
177
static krb5_error_code
176
 
k5db2_init_context(krb5_context context)
 
178
ctx_get(krb5_context context, krb5_db2_context **dbc_out)
177
179
{
178
 
    krb5_db2_context *db_ctx;
 
180
    krb5_db2_context *dbc;
179
181
    kdb5_dal_handle *dal_handle;
180
182
 
181
183
    dal_handle = context->dal_handle;
182
184
 
183
185
    if (dal_handle->db_context == NULL) {
184
 
        db_ctx = (krb5_db2_context *) malloc(sizeof(krb5_db2_context));
185
 
        if (db_ctx == NULL)
 
186
        dbc = (krb5_db2_context *) malloc(sizeof(krb5_db2_context));
 
187
        if (dbc == NULL)
186
188
            return ENOMEM;
187
189
        else {
188
 
            memset(db_ctx, 0, sizeof(krb5_db2_context));
189
 
            k5db2_clear_context((krb5_db2_context *) db_ctx);
190
 
            dal_handle->db_context = (void *) db_ctx;
 
190
            memset(dbc, 0, sizeof(krb5_db2_context));
 
191
            ctx_clear(dbc);
 
192
            dal_handle->db_context = dbc;
191
193
        }
192
194
    }
193
 
    return (0);
 
195
    *dbc_out = dal_handle->db_context;
 
196
    return 0;
194
197
}
195
198
 
196
199
/* Using db_args and the profile, initialize the configurable parameters of the
199
202
configure_context(krb5_context context, char *conf_section, char **db_args)
200
203
{
201
204
    krb5_error_code status;
202
 
    krb5_db2_context *db_ctx;
 
205
    krb5_db2_context *dbc;
203
206
    char **t_ptr, *opt = NULL, *val = NULL, *pval = NULL;
204
207
    profile_t profile = KRB5_DB_GET_PROFILE(context);
205
208
    int bval;
206
209
 
207
 
    status = k5db2_init_context(context);
 
210
    status = ctx_get(context, &dbc);
208
211
    if (status != 0)
209
212
        return status;
210
 
    db_ctx = context->dal_handle->db_context;
211
213
 
212
214
    for (t_ptr = db_args; t_ptr && *t_ptr; t_ptr++) {
213
215
        free(opt);
214
216
        free(val);
215
 
        status = krb5_db2_get_db_opt(*t_ptr, &opt, &val);
 
217
        status = get_db_opt(*t_ptr, &opt, &val);
216
218
        if (opt && !strcmp(opt, "dbname")) {
217
 
            db_ctx->db_name = strdup(val);
218
 
            if (db_ctx->db_name == NULL) {
 
219
            dbc->db_name = strdup(val);
 
220
            if (dbc->db_name == NULL) {
219
221
                status = ENOMEM;
220
222
                goto cleanup;
221
223
            }
222
224
        }
223
225
        else if (!opt && !strcmp(val, "temporary")) {
224
 
            db_ctx->tempdb = 1;
 
226
            dbc->tempdb = 1;
225
227
        } else if (!opt && !strcmp(val, "merge_nra")) {
226
228
            ;
227
229
        } else if (opt && !strcmp(opt, "hash")) {
228
 
            db_ctx->hashfirst = TRUE;
 
230
            dbc->hashfirst = TRUE;
229
231
        } else {
230
232
            status = EINVAL;
231
233
            krb5_set_error_message(context, status,
232
 
                                   "Unsupported argument \"%s\" for db2",
 
234
                                   _("Unsupported argument \"%s\" for db2"),
233
235
                                   opt ? opt : val);
234
236
            goto cleanup;
235
237
        }
236
238
    }
237
239
 
238
 
    if (db_ctx->db_name == NULL) {
 
240
    if (dbc->db_name == NULL) {
239
241
        /* Check for database_name in the db_module section. */
240
242
        status = profile_get_string(profile, KDB_MODULE_SECTION, conf_section,
241
243
                                    KDB_DB2_DATABASE_NAME, NULL, &pval);
248
250
        }
249
251
        if (status != 0)
250
252
            goto cleanup;
251
 
        db_ctx->db_name = strdup(pval);
 
253
        dbc->db_name = strdup(pval);
252
254
    }
253
255
 
254
256
    status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section,
255
257
                                 KRB5_CONF_DISABLE_LAST_SUCCESS, FALSE, &bval);
256
258
    if (status != 0)
257
259
        goto cleanup;
258
 
    db_ctx->disable_last_success = bval;
 
260
    dbc->disable_last_success = bval;
259
261
 
260
262
    status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section,
261
263
                                 KRB5_CONF_DISABLE_LOCKOUT, FALSE, &bval);
262
264
    if (status != 0)
263
265
        goto cleanup;
264
 
    db_ctx->disable_lockout = bval;
 
266
    dbc->disable_lockout = bval;
265
267
 
266
268
cleanup:
267
269
    free(opt);
271
273
}
272
274
 
273
275
/*
274
 
 * Utility routine: generate name of database file.
275
 
 */
276
 
 
277
 
static char *
278
 
gen_dbsuffix(char *db_name, char *sfx)
279
 
{
280
 
    char   *dbsuffix;
281
 
 
282
 
    if (sfx == NULL)
283
 
        return ((char *) NULL);
284
 
 
285
 
    if (asprintf(&dbsuffix, "%s%s", db_name, sfx) < 0)
286
 
        return (0);
287
 
    return dbsuffix;
288
 
}
289
 
 
 
276
 * Set *out to one of the filenames used for the DB described by dbc.  sfx
 
277
 * should be one of SUFFIX_DB, SUFFIX_LOCK, SUFFIX_POLICY, or
 
278
 * SUFFIX_POLICY_LOCK.
 
279
 */
 
280
static krb5_error_code
 
281
ctx_dbsuffix(krb5_db2_context *dbc, const char *sfx, char **out)
 
282
{
 
283
    char *result;
 
284
    const char *tilde;
 
285
 
 
286
    *out = NULL;
 
287
    tilde = dbc->tempdb ? "~" : "";
 
288
    if (asprintf(&result, "%s%s%s", dbc->db_name, tilde, sfx) < 0)
 
289
        return ENOMEM;
 
290
    *out = result;
 
291
    return 0;
 
292
}
 
293
 
 
294
/* Generate all four files corresponding to dbc. */
 
295
static krb5_error_code
 
296
ctx_allfiles(krb5_db2_context *dbc, char **dbname_out, char **lockname_out,
 
297
             char **polname_out, char **plockname_out)
 
298
{
 
299
    char *a = NULL, *b = NULL, *c = NULL, *d = NULL;
 
300
 
 
301
    *dbname_out = *lockname_out = *polname_out = *plockname_out = NULL;
 
302
    if (ctx_dbsuffix(dbc, SUFFIX_DB, &a))
 
303
        goto error;
 
304
    if (ctx_dbsuffix(dbc, SUFFIX_LOCK, &b))
 
305
        goto error;
 
306
    if (ctx_dbsuffix(dbc, SUFFIX_POLICY, &c))
 
307
        goto error;
 
308
    if (ctx_dbsuffix(dbc, SUFFIX_POLICY_LOCK, &d))
 
309
        goto error;
 
310
    *dbname_out = a;
 
311
    *lockname_out = b;
 
312
    *polname_out = c;
 
313
    *plockname_out = d;
 
314
    return 0;
 
315
error:
 
316
    free(a);
 
317
    free(b);
 
318
    free(c);
 
319
    free(d);
 
320
    return ENOMEM;
 
321
}
 
322
 
 
323
/*
 
324
 * Open the DB2 database described by dbc, using the specified flags and mode,
 
325
 * and return the resulting handle.  Try both hash and btree database types;
 
326
 * dbc->hashfirst determines which is attempted first.  If dbc->hashfirst
 
327
 * indicated the wrong type, update it to indicate the correct type.
 
328
 */
290
329
static DB *
291
 
k5db2_dbopen(krb5_db2_context *dbc, char *fname, int flags, int mode, int tempdb)
 
330
open_db(krb5_db2_context *dbc, int flags, int mode)
292
331
{
293
 
    DB     *db;
 
332
    char *fname = NULL;
 
333
    DB *db;
294
334
    BTREEINFO bti;
295
335
    HASHINFO hashi;
296
336
    bti.flags = 0;
301
341
    bti.compare = NULL;
302
342
    bti.prefix = NULL;
303
343
 
304
 
    if (tempdb) {
305
 
        fname = gen_dbsuffix(fname, "~");
306
 
    } else {
307
 
        fname = strdup(fname);
308
 
    }
309
 
    if (fname == NULL)
310
 
    {
 
344
    if (ctx_dbsuffix(dbc, SUFFIX_DB, &fname) != 0) {
311
345
        errno = ENOMEM;
312
346
        return NULL;
313
347
    }
314
348
 
315
 
 
316
349
    hashi.bsize = 4096;
317
350
    hashi.cachesize = 0;
318
351
    hashi.ffactor = 40;
320
353
    hashi.lorder = 0;
321
354
    hashi.nelem = 1;
322
355
 
 
356
    /* Try our best guess at the database type. */
323
357
    db = dbopen(fname, flags, mode,
324
358
                dbc->hashfirst ? DB_HASH : DB_BTREE,
325
359
                dbc->hashfirst ? (void *) &hashi : (void *) &bti);
326
 
    if (db != NULL) {
327
 
        free(fname);
328
 
        return db;
329
 
    }
 
360
    if (db != NULL)
 
361
        goto done;
 
362
 
 
363
    /* If that was wrong, retry with the other type. */
330
364
    switch (errno) {
331
365
#ifdef EFTYPE
332
366
    case EFTYPE:
335
369
        db = dbopen(fname, flags, mode,
336
370
                    dbc->hashfirst ? DB_BTREE : DB_HASH,
337
371
                    dbc->hashfirst ? (void *) &bti : (void *) &hashi);
 
372
        /* If that worked, update our guess for next time. */
338
373
        if (db != NULL)
339
374
            dbc->hashfirst = !dbc->hashfirst;
340
 
    default:
341
 
        free(fname);
342
 
        return db;
343
 
    }
344
 
}
345
 
 
346
 
/*
347
 
 * initialization for data base routines.
348
 
 */
349
 
 
350
 
krb5_error_code
351
 
krb5_db2_init(krb5_context context)
352
 
{
353
 
    char   *filename = NULL;
354
 
    krb5_db2_context *db_ctx;
355
 
    krb5_error_code retval;
356
 
    char    policy_db_name[1024], policy_lock_name[1024];
357
 
 
358
 
    if (k5db2_inited(context))
359
 
        return 0;
360
 
 
361
 
    /* Check for presence of our context, if not present, allocate one. */
362
 
    if ((retval = k5db2_init_context(context)))
363
 
        return (retval);
364
 
 
365
 
    db_ctx = context->dal_handle->db_context;
366
 
    db_ctx->db = NULL;
367
 
 
368
 
    if (!(filename = gen_dbsuffix(db_ctx->db_name, db_ctx->tempdb
369
 
                                  ?KDB2_TEMP_LOCK_EXT:KDB2_LOCK_EXT)))
370
 
        return ENOMEM;
371
 
    db_ctx->db_lf_name = filename;      /* so it gets freed by clear_context */
 
375
        break;
 
376
    }
 
377
 
 
378
done:
 
379
    free(fname);
 
380
    return db;
 
381
}
 
382
 
 
383
static krb5_error_code
 
384
ctx_unlock(krb5_context context, krb5_db2_context *dbc)
 
385
{
 
386
    krb5_error_code retval;
 
387
    DB *db;
 
388
 
 
389
    retval = osa_adb_release_lock(dbc->policy_db);
 
390
    if (retval)
 
391
        return retval;
 
392
 
 
393
    if (!dbc->db_locks_held) /* lock already unlocked */
 
394
        return KRB5_KDB_NOTLOCKED;
 
395
 
 
396
    db = dbc->db;
 
397
    if (--(dbc->db_locks_held) == 0) {
 
398
        db->close(db);
 
399
        dbc->db = NULL;
 
400
        dbc->db_lock_mode = 0;
 
401
 
 
402
        retval = krb5_lock_file(context, dbc->db_lf_file,
 
403
                                KRB5_LOCKMODE_UNLOCK);
 
404
    }
 
405
    return retval;
 
406
}
 
407
 
 
408
#define MAX_LOCK_TRIES 5
 
409
 
 
410
static krb5_error_code
 
411
ctx_lock(krb5_context context, krb5_db2_context *dbc, int lockmode)
 
412
{
 
413
    krb5_error_code retval;
 
414
    int kmode, tries;
 
415
 
 
416
    if (lockmode == KRB5_DB_LOCKMODE_PERMANENT ||
 
417
        lockmode == KRB5_DB_LOCKMODE_EXCLUSIVE)
 
418
        kmode = KRB5_LOCKMODE_EXCLUSIVE;
 
419
    else if (lockmode == KRB5_DB_LOCKMODE_SHARED)
 
420
        kmode = KRB5_LOCKMODE_SHARED;
 
421
    else
 
422
        return EINVAL;
 
423
 
 
424
    if (dbc->db_locks_held == 0 || dbc->db_lock_mode < kmode) {
 
425
        /* Acquire or upgrade the lock. */
 
426
        for (tries = 0; tries < MAX_LOCK_TRIES; tries++) {
 
427
            retval = krb5_lock_file(context, dbc->db_lf_file,
 
428
                                    kmode | KRB5_LOCKMODE_DONTBLOCK);
 
429
            if (retval == 0)
 
430
                break;
 
431
            if (retval == EBADF && kmode == KRB5_LOCKMODE_EXCLUSIVE)
 
432
                /* Tried to lock something we don't have write access to. */
 
433
                return KRB5_KDB_CANTLOCK_DB;
 
434
            sleep(1);
 
435
        }
 
436
        if (retval == EACCES)
 
437
            return KRB5_KDB_CANTLOCK_DB;
 
438
        else if (retval == EAGAIN || retval == EWOULDBLOCK)
 
439
            return OSA_ADB_CANTLOCK_DB;
 
440
        else if (retval)
 
441
            return retval;
 
442
 
 
443
        /* Open the DB (or re-open it for read/write). */
 
444
        if (dbc->db != NULL)
 
445
            dbc->db->close(dbc->db);
 
446
        dbc->db = open_db(dbc,
 
447
                          kmode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR,
 
448
                          0600);
 
449
        if (dbc->db == NULL) {
 
450
            retval = errno;
 
451
            dbc->db_locks_held = 0;
 
452
            dbc->db_lock_mode = 0;
 
453
            (void) osa_adb_release_lock(dbc->policy_db);
 
454
            (void) krb5_lock_file(context, dbc->db_lf_file,
 
455
                                  KRB5_LOCKMODE_UNLOCK);
 
456
            return retval;
 
457
        }
 
458
 
 
459
        dbc->db_lock_mode = kmode;
 
460
    }
 
461
    dbc->db_locks_held++;
 
462
 
 
463
    /* Acquire or upgrade the policy lock. */
 
464
    retval = osa_adb_get_lock(dbc->policy_db, lockmode);
 
465
    if (retval)
 
466
        (void) ctx_unlock(context, dbc);
 
467
    return retval;
 
468
}
 
469
 
 
470
/* Initialize the lock file and policy database fields of dbc.  The db_name and
 
471
 * tempdb fields must already be set. */
 
472
static krb5_error_code
 
473
ctx_init(krb5_db2_context *dbc)
 
474
{
 
475
    krb5_error_code retval;
 
476
    char *polname = NULL, *plockname = NULL;
 
477
 
 
478
    retval = ctx_dbsuffix(dbc, SUFFIX_LOCK, &dbc->db_lf_name);
 
479
    if (retval)
 
480
        return retval;
372
481
 
373
482
    /*
374
483
     * should be opened read/write so that write locking can work with
375
484
     * POSIX systems
376
485
     */
377
 
    if ((db_ctx->db_lf_file = open(filename, O_RDWR, 0666)) < 0) {
378
 
        if ((db_ctx->db_lf_file = open(filename, O_RDONLY, 0666)) < 0) {
 
486
    if ((dbc->db_lf_file = open(dbc->db_lf_name, O_RDWR, 0666)) < 0) {
 
487
        if ((dbc->db_lf_file = open(dbc->db_lf_name, O_RDONLY, 0666)) < 0) {
379
488
            retval = errno;
380
 
            goto err_out;
 
489
            goto cleanup;
381
490
        }
382
491
    }
383
 
    set_cloexec_fd(db_ctx->db_lf_file);
384
 
    db_ctx->db_inited++;
385
 
 
386
 
    if ((retval = krb5_db2_get_age(context, NULL, &db_ctx->db_lf_time)))
387
 
        goto err_out;
388
 
 
389
 
    snprintf(policy_db_name, sizeof(policy_db_name), "%s%s.kadm5",
390
 
             db_ctx->db_name, db_ctx->tempdb ? "~" : "");
391
 
    snprintf(policy_lock_name, sizeof(policy_lock_name),
392
 
             "%s.lock", policy_db_name);
393
 
 
394
 
    if ((retval = osa_adb_init_db(&db_ctx->policy_db, policy_db_name,
395
 
                                  policy_lock_name, OSA_ADB_POLICY_DB_MAGIC)))
396
 
    {
397
 
        goto err_out;
398
 
    }
399
 
    return 0;
400
 
 
401
 
err_out:
402
 
    db_ctx->db = NULL;
403
 
    k5db2_clear_context(db_ctx);
404
 
    return (retval);
405
 
}
406
 
 
407
 
/*
408
 
 * gracefully shut down database--must be called by ANY program that does
409
 
 * a krb5_db2_init
410
 
 */
 
492
    set_cloexec_fd(dbc->db_lf_file);
 
493
    dbc->db_inited++;
 
494
 
 
495
    retval = ctx_dbsuffix(dbc, SUFFIX_POLICY, &polname);
 
496
    if (retval)
 
497
        goto cleanup;
 
498
    retval = ctx_dbsuffix(dbc, SUFFIX_POLICY_LOCK, &plockname);
 
499
    if (retval)
 
500
        goto cleanup;
 
501
    retval = osa_adb_init_db(&dbc->policy_db, polname, plockname,
 
502
                             OSA_ADB_POLICY_DB_MAGIC);
 
503
 
 
504
cleanup:
 
505
    free(polname);
 
506
    free(plockname);
 
507
    if (retval)
 
508
        ctx_clear(dbc);
 
509
    return retval;
 
510
}
 
511
 
 
512
static void
 
513
ctx_fini(krb5_db2_context *dbc)
 
514
{
 
515
    if (dbc->db_lf_file != -1)
 
516
        (void) close(dbc->db_lf_file);
 
517
    if (dbc->policy_db)
 
518
        (void) osa_adb_fini_db(dbc->policy_db, OSA_ADB_POLICY_DB_MAGIC);
 
519
    ctx_clear(dbc);
 
520
    free(dbc);
 
521
}
 
522
 
411
523
krb5_error_code
412
524
krb5_db2_fini(krb5_context context)
413
525
{
414
 
    krb5_error_code retval = 0;
415
 
    krb5_db2_context *db_ctx;
416
 
 
417
 
    db_ctx = context->dal_handle->db_context;
418
 
    if (k5db2_inited(context)) {
419
 
        if (close(db_ctx->db_lf_file))
420
 
            retval = errno;
421
 
        else
422
 
            retval = 0;
423
 
    }
424
 
    if (db_ctx) {
425
 
        if (db_ctx->policy_db) {
426
 
            retval =
427
 
                osa_adb_fini_db(db_ctx->policy_db, OSA_ADB_POLICY_DB_MAGIC);
428
 
            if (retval)
429
 
                return retval;
430
 
        }
431
 
 
432
 
        k5db2_clear_context(db_ctx);
433
 
        free(context->dal_handle->db_context);
 
526
    if (context->dal_handle->db_context != NULL) {
 
527
        ctx_fini(context->dal_handle->db_context);
434
528
        context->dal_handle->db_context = NULL;
435
529
    }
436
 
    return retval;
 
530
    return 0;
437
531
}
438
532
 
439
 
 
440
 
 
441
533
/* Return successfully if the db2 name set in context can be opened. */
442
534
static krb5_error_code
443
535
check_openable(krb5_context context)
444
536
{
445
537
    DB     *db;
446
 
    krb5_db2_context *db_ctx;
 
538
    krb5_db2_context *dbc;
447
539
 
448
 
    db_ctx = context->dal_handle->db_context;
449
 
    db = k5db2_dbopen(db_ctx, db_ctx->db_name, O_RDONLY, 0, db_ctx->tempdb);
 
540
    dbc = context->dal_handle->db_context;
 
541
    db = open_db(dbc, O_RDONLY, 0);
450
542
    if (db == NULL)
451
543
        return errno;
452
 
    (*db->close) (db);
 
544
    db->close(db);
453
545
    return 0;
454
546
}
455
547
 
462
554
krb5_error_code
463
555
krb5_db2_get_age(krb5_context context, char *db_name, time_t *age)
464
556
{
465
 
    krb5_db2_context *db_ctx;
 
557
    krb5_db2_context *dbc;
466
558
    struct stat st;
467
559
 
468
 
    if (!k5db2_inited(context))
 
560
    if (!inited(context))
469
561
        return (KRB5_KDB_DBNOTINITED);
470
 
    db_ctx = context->dal_handle->db_context;
 
562
    dbc = context->dal_handle->db_context;
471
563
 
472
 
    if (fstat(db_ctx->db_lf_file, &st) < 0)
 
564
    if (fstat(dbc->db_lf_file, &st) < 0)
473
565
        *age = -1;
474
566
    else
475
567
        *age = st.st_mtime;
476
568
    return 0;
477
569
}
478
570
 
479
 
/*
480
 
 * Remove the semaphore file; indicates that database is currently
481
 
 * under renovation.
482
 
 *
483
 
 * This is only for use when moving the database out from underneath
484
 
 * the server (for example, during slave updates).
485
 
 */
486
 
 
487
 
static krb5_error_code
488
 
krb5_db2_start_update(krb5_context context)
489
 
{
490
 
    return 0;
491
 
}
492
 
 
493
 
static krb5_error_code
494
 
krb5_db2_end_update(krb5_context context)
495
 
{
496
 
    krb5_error_code retval;
497
 
    krb5_db2_context *db_ctx;
 
571
/* Try to update the timestamp on dbc's lockfile. */
 
572
static void
 
573
ctx_update_age(krb5_db2_context *dbc)
 
574
{
498
575
    struct stat st;
499
 
    time_t  now;
 
576
    time_t now;
500
577
    struct utimbuf utbuf;
501
578
 
502
 
    if (!k5db2_inited(context))
503
 
        return (KRB5_KDB_DBNOTINITED);
504
 
 
505
 
    retval = 0;
506
 
    db_ctx = context->dal_handle->db_context;
507
579
    now = time((time_t *) NULL);
508
 
    if (fstat(db_ctx->db_lf_file, &st) == 0) {
509
 
        if (st.st_mtime >= now) {
510
 
            utbuf.actime = st.st_mtime + 1;
511
 
            utbuf.modtime = st.st_mtime + 1;
512
 
            if (utime(db_ctx->db_lf_name, &utbuf))
513
 
                retval = errno;
514
 
        } else {
515
 
            if (utime(db_ctx->db_lf_name, (struct utimbuf *) NULL))
516
 
                retval = errno;
517
 
        }
 
580
    if (fstat(dbc->db_lf_file, &st) != 0)
 
581
        return;
 
582
    if (st.st_mtime >= now) {
 
583
        utbuf.actime = st.st_mtime + 1;
 
584
        utbuf.modtime = st.st_mtime + 1;
 
585
        (void) utime(dbc->db_lf_name, &utbuf);
518
586
    } else
519
 
        retval = errno;
520
 
    if (!retval) {
521
 
        if (fstat(db_ctx->db_lf_file, &st) == 0)
522
 
            db_ctx->db_lf_time = st.st_mtime;
523
 
        else
524
 
            retval = errno;
525
 
    }
526
 
    return (retval);
 
587
        (void) utime(dbc->db_lf_name, (struct utimbuf *) NULL);
527
588
}
528
589
 
529
 
#define MAX_LOCK_TRIES 5
530
 
 
531
590
krb5_error_code
532
 
krb5_db2_lock(krb5_context context, int in_mode)
 
591
krb5_db2_lock(krb5_context context, int lockmode)
533
592
{
534
 
    krb5_db2_context *db_ctx;
535
 
    int     krb5_lock_mode;
536
 
    DB     *db;
537
 
    krb5_error_code retval;
538
 
    time_t  mod_time;
539
 
    int     mode, gotlock, tries;
540
 
 
541
 
    switch (in_mode) {
542
 
    case KRB5_DB_LOCKMODE_PERMANENT:
543
 
        mode = KRB5_DB_LOCKMODE_EXCLUSIVE;
544
 
        break;
545
 
    case KRB5_DB_LOCKMODE_EXCLUSIVE:
546
 
        mode = KRB5_LOCKMODE_EXCLUSIVE;
547
 
        break;
548
 
 
549
 
    case KRB5_DB_LOCKMODE_SHARED:
550
 
        mode = KRB5_LOCKMODE_SHARED;
551
 
        break;
552
 
    default:
553
 
        return EINVAL;
554
 
    }
555
 
 
556
 
    if (!k5db2_inited(context))
 
593
    if (!inited(context))
557
594
        return KRB5_KDB_DBNOTINITED;
558
 
 
559
 
    db_ctx = context->dal_handle->db_context;
560
 
    if (db_ctx->db_locks_held && (db_ctx->db_lock_mode >= mode)) {
561
 
        /* No need to upgrade lock, just return */
562
 
        db_ctx->db_locks_held++;
563
 
        goto policy_lock;
564
 
    }
565
 
 
566
 
    if ((mode != KRB5_LOCKMODE_SHARED) && (mode != KRB5_LOCKMODE_EXCLUSIVE))
567
 
        return KRB5_KDB_BADLOCKMODE;
568
 
 
569
 
    krb5_lock_mode = mode | KRB5_LOCKMODE_DONTBLOCK;
570
 
    for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
571
 
        retval = krb5_lock_file(context, db_ctx->db_lf_file, krb5_lock_mode);
572
 
        if (retval == 0) {
573
 
            gotlock++;
574
 
            break;
575
 
        } else if (retval == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
576
 
            /* tried to exclusive-lock something we don't have */
577
 
            /* write access to */
578
 
            return KRB5_KDB_CANTLOCK_DB;
579
 
        sleep(1);
580
 
    }
581
 
    if (retval == EACCES)
582
 
        return KRB5_KDB_CANTLOCK_DB;
583
 
    else if (retval == EAGAIN || retval == EWOULDBLOCK)
584
 
        return OSA_ADB_CANTLOCK_DB;
585
 
    else if (retval != 0)
586
 
        return retval;
587
 
 
588
 
    if ((retval = krb5_db2_get_age(context, NULL, &mod_time)))
589
 
        goto lock_error;
590
 
 
591
 
    db = k5db2_dbopen(db_ctx, db_ctx->db_name,
592
 
                      mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR, 0600, db_ctx->tempdb);
593
 
    if (db) {
594
 
        db_ctx->db_lf_time = mod_time;
595
 
        db_ctx->db = db;
596
 
    } else {
597
 
        retval = errno;
598
 
        db_ctx->db = NULL;
599
 
        goto lock_error;
600
 
    }
601
 
 
602
 
    db_ctx->db_lock_mode = mode;
603
 
    db_ctx->db_locks_held++;
604
 
 
605
 
policy_lock:
606
 
    if ((retval = osa_adb_get_lock(db_ctx->policy_db, in_mode))) {
607
 
        krb5_db2_unlock(context);
608
 
    }
609
 
    return retval;
610
 
 
611
 
lock_error:;
612
 
    db_ctx->db_lock_mode = 0;
613
 
    db_ctx->db_locks_held = 0;
614
 
    krb5_db2_unlock(context);
615
 
    return retval;
 
595
    return ctx_lock(context, context->dal_handle->db_context, lockmode);
616
596
}
617
597
 
618
598
krb5_error_code
619
599
krb5_db2_unlock(krb5_context context)
620
600
{
621
 
    krb5_db2_context *db_ctx;
622
 
    DB     *db;
623
 
    krb5_error_code retval;
624
 
 
625
 
    if (!k5db2_inited(context))
 
601
    if (!inited(context))
626
602
        return KRB5_KDB_DBNOTINITED;
627
 
 
628
 
    db_ctx = context->dal_handle->db_context;
629
 
 
630
 
    if ((retval = osa_adb_release_lock(db_ctx->policy_db))) {
631
 
        return retval;
632
 
    }
633
 
 
634
 
    if (!db_ctx->db_locks_held) /* lock already unlocked */
635
 
        return KRB5_KDB_NOTLOCKED;
636
 
    db = db_ctx->db;
637
 
    if (--(db_ctx->db_locks_held) == 0) {
638
 
        (*db->close) (db);
639
 
        db_ctx->db = NULL;
640
 
 
641
 
        retval = krb5_lock_file(context, db_ctx->db_lf_file,
642
 
                                KRB5_LOCKMODE_UNLOCK);
643
 
        db_ctx->db_lock_mode = 0;
644
 
        return (retval);
645
 
    }
646
 
    return 0;
647
 
}
648
 
 
649
 
/* Create the database, assuming it's not there. */
650
 
static krb5_error_code
651
 
create_db(krb5_context context, char *db_name)
652
 
{
653
 
    krb5_error_code retval = 0;
654
 
    char   *okname;
655
 
    char   *db_name2 = NULL;
656
 
    int     fd;
657
 
    krb5_db2_context *db_ctx;
658
 
    DB     *db;
659
 
    char    policy_db_name[1024], policy_lock_name[1024];
660
 
 
661
 
    retval = k5db2_init_context(context);
662
 
    if (retval != 0)
663
 
        return retval;
664
 
 
665
 
    db_ctx = context->dal_handle->db_context;
666
 
    db = k5db2_dbopen(db_ctx, db_name, O_RDWR | O_CREAT | O_EXCL, 0600,
667
 
                      db_ctx->tempdb);
668
 
    if (db == NULL)
669
 
        return errno;
670
 
    (*db->close)(db);
671
 
 
672
 
    db_name2 = db_ctx->tempdb ? gen_dbsuffix(db_name, "~") : strdup(db_name);
673
 
    if (db_name2 == NULL)
674
 
        return ENOMEM;
675
 
    okname = gen_dbsuffix(db_name2, KDB2_LOCK_EXT);
676
 
    if (!okname)
677
 
        retval = ENOMEM;
678
 
    else {
679
 
        fd = open(okname, O_CREAT | O_RDWR | O_TRUNC, 0600);
680
 
        if (fd < 0)
681
 
            retval = errno;
682
 
        else
683
 
            close(fd);
684
 
        free_dbsuffix(okname);
685
 
    }
686
 
 
687
 
    snprintf(policy_db_name, sizeof(policy_db_name), "%s.kadm5", db_name2);
688
 
    snprintf(policy_lock_name, sizeof(policy_lock_name),
689
 
             "%s.lock", policy_db_name);
690
 
 
691
 
    retval = osa_adb_create_db(policy_db_name,
692
 
                               policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
693
 
    free(db_name2);
694
 
    return retval;
695
 
}
696
 
 
697
 
/*
698
 
 * Destroy the database.  Zero's out all of the files, just to be sure.
699
 
 */
700
 
static krb5_error_code
701
 
destroy_file_suffix(char *dbname, char *suffix)
702
 
{
703
 
    char   *filename;
 
603
    return ctx_unlock(context, context->dal_handle->db_context);
 
604
}
 
605
 
 
606
/* Zero out and unlink filename. */
 
607
static krb5_error_code
 
608
destroy_file(char *filename)
 
609
{
704
610
    struct stat statb;
705
 
    int     nb, fd;
706
 
    int     j;
707
 
    off_t   pos;
708
 
    char    buf[BUFSIZ];
709
 
    char    zbuf[BUFSIZ];
710
 
    int     dowrite;
 
611
    int dowrite, j, nb, fd, retval;
 
612
    off_t pos;
 
613
    char buf[BUFSIZ], zbuf[BUFSIZ];
711
614
 
712
 
    filename = gen_dbsuffix(dbname, suffix);
713
 
    if (filename == 0)
714
 
        return ENOMEM;
715
 
    if ((fd = open(filename, O_RDWR, 0)) < 0) {
716
 
        free(filename);
 
615
    fd = open(filename, O_RDWR, 0);
 
616
    if (fd < 0)
717
617
        return errno;
718
 
    }
719
618
    set_cloexec_fd(fd);
720
619
    /* fstat() will probably not fail unless using a remote filesystem
721
620
     * (which is inappropriate for the kerberos database) so this check
722
621
     * is mostly paranoia.  */
723
 
    if (fstat(fd, &statb) == -1) {
724
 
        int     retval = errno;
725
 
        free(filename);
726
 
        return retval;
727
 
    }
 
622
    if (fstat(fd, &statb) == -1)
 
623
        goto error;
728
624
    /*
729
625
     * Stroll through the file, reading in BUFSIZ chunks.  If everything
730
626
     * is zero, then we're done for that block, otherwise, zero the block.
738
634
    while (pos < statb.st_size) {
739
635
        dowrite = 0;
740
636
        nb = read(fd, buf, BUFSIZ);
741
 
        if (nb < 0) {
742
 
            int     retval = errno;
743
 
            free(filename);
744
 
            return retval;
745
 
        }
 
637
        if (nb < 0)
 
638
            goto error;
746
639
        for (j = 0; j < nb; j++) {
747
640
            if (buf[j] != '\0') {
748
641
                dowrite = 1;
754
647
        if (dowrite) {
755
648
            lseek(fd, pos, SEEK_SET);
756
649
            nb = write(fd, zbuf, j);
757
 
            if (nb < 0) {
758
 
                int     retval = errno;
759
 
                free(filename);
760
 
                return retval;
761
 
            }
 
650
            if (nb < 0)
 
651
                goto error;
762
652
        }
763
653
        pos += nb;
764
654
    }
770
660
#endif
771
661
    close(fd);
772
662
 
773
 
    if (unlink(filename)) {
774
 
        free(filename);
775
 
        return (errno);
776
 
    }
777
 
    free(filename);
778
 
    return (0);
 
663
    if (unlink(filename))
 
664
        return errno;
 
665
    return 0;
 
666
 
 
667
error:
 
668
    retval = errno;
 
669
    close(fd);
 
670
    return retval;
779
671
}
780
672
 
781
 
/*
782
 
 * Since the destroy operation happens outside the init/fini bracket, we
783
 
 * have some tomfoolery to undergo here.  If we're operating under no
784
 
 * database context, then we initialize with the default.  If the caller
785
 
 * wishes a different context (e.g. different dispatch table), it's their
786
 
 * responsibility to call kdb5_db_set_dbops() before this call.  That will
787
 
 * set up the right dispatch table values (e.g. name extensions).
788
 
 *
789
 
 * Not quite valid due to ripping out of dbops...
790
 
 */
 
673
/* Initialize dbc by locking and creating the DB.  If the DB already exists,
 
674
 * clear it out if dbc->tempdb is set; otherwise return EEXIST. */
791
675
static krb5_error_code
792
 
destroy_db(krb5_context context, char *dbname)
 
676
ctx_create_db(krb5_context context, krb5_db2_context *dbc)
793
677
{
794
 
    krb5_error_code retval1, retval2;
795
 
    krb5_boolean tmpcontext;
796
 
    char    policy_db_name[1024], policy_lock_name[1024];
797
 
 
798
 
    tmpcontext = 0;
799
 
    if (!context->dal_handle->db_context) {
800
 
        tmpcontext = 1;
801
 
        if ((retval1 = k5db2_init_context(context)))
802
 
            return (retval1);
803
 
    }
804
 
 
805
 
    retval1 = retval2 = 0;
806
 
    retval1 = destroy_file_suffix(dbname, "");
807
 
    retval2 = destroy_file_suffix(dbname, KDB2_LOCK_EXT);
808
 
 
809
 
    if (tmpcontext) {
810
 
        k5db2_clear_context(context->dal_handle->db_context);
811
 
        free(context->dal_handle->db_context);
812
 
        context->dal_handle->db_context = NULL;
813
 
    }
814
 
 
815
 
    if (retval1 || retval2)
816
 
        return (retval1 ? retval1 : retval2);
817
 
 
818
 
    snprintf(policy_db_name, sizeof(policy_db_name), "%s.kadm5", dbname);
819
 
    snprintf(policy_lock_name, sizeof(policy_lock_name),
820
 
             "%s.lock", policy_db_name);
821
 
 
822
 
    retval1 = osa_adb_destroy_db(policy_db_name,
823
 
                                 policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
824
 
 
825
 
    return retval1;
 
678
    krb5_error_code retval = 0;
 
679
    char *dbname = NULL, *polname = NULL, *plockname = NULL;
 
680
 
 
681
    retval = ctx_allfiles(dbc, &dbname, &dbc->db_lf_name, &polname,
 
682
                          &plockname);
 
683
    if (retval)
 
684
        return retval;
 
685
 
 
686
    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
 
687
                           0600);
 
688
    if (dbc->db_lf_file < 0) {
 
689
        retval = errno;
 
690
        goto cleanup;
 
691
    }
 
692
    retval = krb5_lock_file(context, dbc->db_lf_file,
 
693
                            KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
 
694
    if (retval != 0)
 
695
        goto cleanup;
 
696
    set_cloexec_fd(dbc->db_lf_file);
 
697
    dbc->db_lock_mode = KRB5_LOCKMODE_EXCLUSIVE;
 
698
    dbc->db_locks_held = 1;
 
699
 
 
700
    if (dbc->tempdb) {
 
701
        /* Temporary DBs are locked for their whole lifetime.  Since we have
 
702
         * the lock, any remnant files can be safely destroyed. */
 
703
        (void) destroy_file(dbname);
 
704
        (void) unlink(polname);
 
705
        (void) unlink(plockname);
 
706
    }
 
707
 
 
708
    dbc->db = open_db(dbc, O_RDWR | O_CREAT | O_EXCL, 0600);
 
709
    if (dbc->db == NULL) {
 
710
        retval = errno;
 
711
        goto cleanup;
 
712
    }
 
713
 
 
714
    /* Create the policy database, initialize a handle to it, and lock it. */
 
715
    retval = osa_adb_create_db(polname, plockname, OSA_ADB_POLICY_DB_MAGIC);
 
716
    if (retval)
 
717
        goto cleanup;
 
718
    retval = osa_adb_init_db(&dbc->policy_db, polname, plockname,
 
719
                             OSA_ADB_POLICY_DB_MAGIC);
 
720
    if (retval)
 
721
        goto cleanup;
 
722
    retval = osa_adb_get_lock(dbc->policy_db, KRB5_DB_LOCKMODE_EXCLUSIVE);
 
723
    if (retval)
 
724
        goto cleanup;
 
725
 
 
726
    dbc->db_inited = 1;
 
727
 
 
728
cleanup:
 
729
    if (retval) {
 
730
        if (dbc->db != NULL)
 
731
            dbc->db->close(dbc->db);
 
732
        if (dbc->db_locks_held > 0) {
 
733
            (void) krb5_lock_file(context, dbc->db_lf_file,
 
734
                                  KRB5_LOCKMODE_UNLOCK);
 
735
        }
 
736
        if (dbc->db_lf_file >= 0)
 
737
            close(dbc->db_lf_file);
 
738
        ctx_clear(dbc);
 
739
    }
 
740
    free(dbname);
 
741
    free(polname);
 
742
    free(plockname);
 
743
    return retval;
826
744
}
827
745
 
828
746
krb5_error_code
829
747
krb5_db2_get_principal(krb5_context context, krb5_const_principal searchfor,
830
748
                       unsigned int flags, krb5_db_entry **entry)
831
749
{
832
 
    krb5_db2_context *db_ctx;
 
750
    krb5_db2_context *dbc;
833
751
    krb5_error_code retval;
834
752
    DB     *db;
835
753
    DBT     key, contents;
837
755
    int     trynum, dbret;
838
756
 
839
757
    *entry = NULL;
840
 
    if (!k5db2_inited(context))
 
758
    if (!inited(context))
841
759
        return KRB5_KDB_DBNOTINITED;
842
760
 
843
 
    db_ctx = context->dal_handle->db_context;
 
761
    dbc = context->dal_handle->db_context;
844
762
 
845
763
    for (trynum = 0; trynum < KRB5_DB2_MAX_RETRY; trynum++) {
846
 
        if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_SHARED))) {
847
 
            if (db_ctx->db_nb_locks)
 
764
        if ((retval = ctx_lock(context, dbc, KRB5_LOCKMODE_SHARED))) {
 
765
            if (dbc->db_nb_locks)
848
766
                return (retval);
849
767
            sleep(1);
850
768
            continue;
861
779
    key.data = keydata.data;
862
780
    key.size = keydata.length;
863
781
 
864
 
    db = db_ctx->db;
 
782
    db = dbc->db;
865
783
    dbret = (*db->get)(db, &key, &contents, 0);
866
784
    retval = errno;
867
785
    krb5_free_data_contents(context, &keydata);
900
818
    DBT     key, contents;
901
819
    krb5_data contdata, keydata;
902
820
    krb5_error_code retval;
903
 
    krb5_db2_context *db_ctx;
 
821
    krb5_db2_context *dbc;
904
822
 
905
823
    krb5_clear_error_message (context);
906
824
    if (db_args) {
907
825
        /* DB2 does not support db_args DB arguments for principal */
908
826
        krb5_set_error_message(context, EINVAL,
909
 
                               "Unsupported argument \"%s\" for db2",
 
827
                               _("Unsupported argument \"%s\" for db2"),
910
828
                               db_args[0]);
911
829
        return EINVAL;
912
830
    }
913
831
 
914
 
    if (!k5db2_inited(context))
 
832
    if (!inited(context))
915
833
        return KRB5_KDB_DBNOTINITED;
916
834
 
917
 
    db_ctx = context->dal_handle->db_context;
918
 
    if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
 
835
    dbc = context->dal_handle->db_context;
 
836
    if ((retval = ctx_lock(context, dbc, KRB5_LOCKMODE_EXCLUSIVE)))
919
837
        return retval;
920
838
 
921
 
    db = db_ctx->db;
922
 
    if ((retval = krb5_db2_start_update(context))) {
923
 
        (void) krb5_db2_unlock(context);
924
 
        return retval;
925
 
    }
 
839
    db = dbc->db;
926
840
 
927
841
    retval = krb5_encode_princ_entry(context, &contdata, entry);
928
842
    if (retval)
943
857
    krb5_free_data_contents(context, &contdata);
944
858
 
945
859
cleanup:
946
 
    (void) krb5_db2_end_update(context);
 
860
    ctx_update_age(dbc);
947
861
    (void) krb5_db2_unlock(context); /* unlock database */
948
862
    return (retval);
949
863
}
953
867
{
954
868
    krb5_error_code retval;
955
869
    krb5_db_entry *entry;
956
 
    krb5_db2_context *db_ctx;
 
870
    krb5_db2_context *dbc;
957
871
    DB     *db;
958
872
    DBT     key, contents;
959
873
    krb5_data keydata, contdata;
960
874
    int     i, dbret;
961
875
 
962
 
    if (!k5db2_inited(context))
 
876
    if (!inited(context))
963
877
        return KRB5_KDB_DBNOTINITED;
964
878
 
965
 
    db_ctx = context->dal_handle->db_context;
966
 
    if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
967
 
        return (retval);
968
 
 
969
 
    if ((retval = krb5_db2_start_update(context))) {
970
 
        (void) krb5_db2_unlock(context);     /* unlock write lock */
971
 
        return (retval);
972
 
    }
 
879
    dbc = context->dal_handle->db_context;
 
880
    if ((retval = ctx_lock(context, dbc, KRB5_LOCKMODE_EXCLUSIVE)))
 
881
        return (retval);
973
882
 
974
883
    if ((retval = krb5_encode_princ_dbkey(context, &keydata, searchfor)))
975
884
        goto cleanup;
976
885
    key.data = keydata.data;
977
886
    key.size = keydata.length;
978
887
 
979
 
    db = db_ctx->db;
 
888
    db = dbc->db;
980
889
    dbret = (*db->get) (db, &key, &contents, 0);
981
890
    retval = errno;
982
891
    switch (dbret) {
1021
930
    krb5_free_data_contents(context, &keydata);
1022
931
 
1023
932
cleanup:
1024
 
    (void) krb5_db2_end_update(context);
 
933
    ctx_update_age(dbc);
1025
934
    (void) krb5_db2_unlock(context); /* unlock write lock */
1026
935
    return retval;
1027
936
}
1028
937
 
1029
 
krb5_error_code
1030
 
krb5_db2_iterate_ext(krb5_context context,
1031
 
                     krb5_error_code(*func) (krb5_pointer, krb5_db_entry *),
1032
 
                     krb5_pointer func_arg, int backwards, int recursive)
 
938
static krb5_error_code
 
939
ctx_iterate(krb5_context context, krb5_db2_context *dbc,
 
940
            krb5_error_code (*func)(krb5_pointer, krb5_db_entry *),
 
941
            krb5_pointer func_arg)
1033
942
{
1034
 
    krb5_db2_context *db_ctx;
1035
 
    DB     *db;
1036
 
    DBT     key, contents;
 
943
    DB *db;
 
944
    DBT key, contents;
1037
945
    krb5_data contdata;
1038
946
    krb5_db_entry *entry;
1039
 
    krb5_error_code retval;
1040
 
    int     dbret;
1041
 
    void   *cookie;
1042
 
 
1043
 
    cookie = NULL;
1044
 
    if (!k5db2_inited(context))
1045
 
        return KRB5_KDB_DBNOTINITED;
1046
 
 
1047
 
    db_ctx = context->dal_handle->db_context;
1048
 
    retval = krb5_db2_lock(context, KRB5_LOCKMODE_SHARED);
1049
 
 
 
947
    krb5_error_code retval, retval2;
 
948
    int dbret;
 
949
 
 
950
    retval = ctx_lock(context, dbc, KRB5_LOCKMODE_SHARED);
1050
951
    if (retval)
1051
952
        return retval;
1052
953
 
1053
 
    db = db_ctx->db;
1054
 
    if (recursive && db->type != DB_BTREE) {
1055
 
        (void) krb5_db2_unlock(context);
1056
 
        return KRB5_KDB_UK_RERROR;      /* Not optimal, but close enough. */
1057
 
    }
1058
 
 
1059
 
    if (!recursive) {
1060
 
        dbret = (*db->seq) (db, &key, &contents, backwards ? R_LAST : R_FIRST);
1061
 
    } else {
1062
 
#ifdef HAVE_BT_RSEQ
1063
 
        dbret = bt_rseq(db, &key, &contents, &cookie,
1064
 
                        backwards ? R_LAST : R_FIRST);
1065
 
#else
1066
 
        (void) krb5_db2_unlock(context);
1067
 
        return KRB5_KDB_UK_RERROR;      /* Not optimal, but close enough. */
1068
 
#endif
1069
 
    }
 
954
    db = dbc->db;
 
955
    dbret = db->seq(db, &key, &contents, R_FIRST);
1070
956
    while (dbret == 0) {
1071
 
        krb5_error_code retval2;
1072
 
 
1073
957
        contdata.data = contents.data;
1074
958
        contdata.length = contents.size;
1075
959
        retval = krb5_decode_princ_entry(context, &contdata, &entry);
1090
974
            retval = retval2;
1091
975
            break;
1092
976
        }
1093
 
        if (!recursive) {
1094
 
            dbret = (*db->seq) (db, &key, &contents,
1095
 
                                backwards ? R_PREV : R_NEXT);
1096
 
        } else {
1097
 
#ifdef HAVE_BT_RSEQ
1098
 
            dbret = bt_rseq(db, &key, &contents, &cookie,
1099
 
                            backwards ? R_PREV : R_NEXT);
1100
 
#else
1101
 
            (void) krb5_db2_unlock(context);
1102
 
            return KRB5_KDB_UK_RERROR;  /* Not optimal, but close enough. */
1103
 
#endif
1104
 
        }
 
977
        dbret = db->seq(db, &key, &contents, R_NEXT);
1105
978
    }
1106
979
    switch (dbret) {
1107
980
    case 1:
1111
984
    default:
1112
985
        retval = errno;
1113
986
    }
1114
 
    (void) krb5_db2_unlock(context);
 
987
    (void) ctx_unlock(context, dbc);
1115
988
    return retval;
1116
989
}
1117
990
 
1120
993
                 krb5_error_code(*func) (krb5_pointer, krb5_db_entry *),
1121
994
                 krb5_pointer func_arg)
1122
995
{
1123
 
    return krb5_db2_iterate_ext(context, func, func_arg, 0, 0);
 
996
    if (!inited(context))
 
997
        return KRB5_KDB_DBNOTINITED;
 
998
    return ctx_iterate(context, context->dal_handle->db_context, func,
 
999
                       func_arg);
1124
1000
}
1125
1001
 
1126
1002
krb5_boolean
1127
1003
krb5_db2_set_lockmode(krb5_context context, krb5_boolean mode)
1128
1004
{
1129
1005
    krb5_boolean old;
1130
 
    krb5_db2_context *db_ctx;
 
1006
    krb5_db2_context *dbc;
1131
1007
 
1132
 
    db_ctx = context->dal_handle->db_context;
 
1008
    dbc = context->dal_handle->db_context;
1133
1009
    old = mode;
1134
 
    if (db_ctx) {
1135
 
        old = db_ctx->db_nb_locks;
1136
 
        db_ctx->db_nb_locks = mode;
 
1010
    if (dbc) {
 
1011
        old = dbc->db_nb_locks;
 
1012
        dbc->db_nb_locks = mode;
1137
1013
    }
1138
1014
    return old;
1139
1015
}
1161
1037
    krb5_error_code status = 0;
1162
1038
 
1163
1039
    krb5_clear_error_message(context);
1164
 
    if (k5db2_inited(context))
 
1040
    if (inited(context))
1165
1041
        return 0;
1166
1042
 
1167
1043
    status = configure_context(context, conf_section, db_args);
1172
1048
    if (status != 0)
1173
1049
        return status;
1174
1050
 
1175
 
    return krb5_db2_init(context);
 
1051
    return ctx_init(context->dal_handle->db_context);
1176
1052
}
1177
1053
 
1178
1054
krb5_error_code
1179
1055
krb5_db2_create(krb5_context context, char *conf_section, char **db_args)
1180
1056
{
1181
1057
    krb5_error_code status = 0;
1182
 
    krb5_db2_context *db_ctx;
 
1058
    krb5_db2_context *dbc;
1183
1059
 
1184
1060
    krb5_clear_error_message(context);
1185
 
    if (k5db2_inited(context))
 
1061
    if (inited(context))
1186
1062
        return 0;
1187
1063
 
1188
1064
    status = configure_context(context, conf_section, db_args);
1189
1065
    if (status != 0)
1190
1066
        return status;
1191
1067
 
1192
 
    status = check_openable(context);
1193
 
    if (status == 0)
1194
 
        return EEXIST;
1195
 
 
1196
 
    db_ctx = context->dal_handle->db_context;
1197
 
    status = create_db(context, db_ctx->db_name);
 
1068
    dbc = context->dal_handle->db_context;
 
1069
    status = ctx_create_db(context, dbc);
1198
1070
    if (status != 0)
1199
1071
        return status;
1200
1072
 
1201
 
    return krb5_db2_init(context);
 
1073
    if (!dbc->tempdb)
 
1074
        krb5_db2_unlock(context);
 
1075
 
 
1076
    return 0;
1202
1077
}
1203
1078
 
1204
1079
krb5_error_code
1205
1080
krb5_db2_destroy(krb5_context context, char *conf_section, char **db_args)
1206
1081
{
1207
 
    krb5_error_code status = 0;
1208
 
    krb5_db2_context *db_ctx;
1209
 
    char *db_name;
 
1082
    krb5_error_code status;
 
1083
    krb5_db2_context *dbc;
 
1084
    char *dbname = NULL, *lockname = NULL, *polname = NULL, *plockname = NULL;
1210
1085
 
1211
 
    if (k5db2_inited(context)) {
 
1086
    if (inited(context)) {
1212
1087
        status = krb5_db2_fini(context);
1213
1088
        if (status != 0)
1214
1089
            return status;
1223
1098
    if (status != 0)
1224
1099
        return status;
1225
1100
 
1226
 
    db_ctx = context->dal_handle->db_context;
1227
 
    db_name = gen_dbsuffix(db_ctx->db_name, db_ctx->tempdb ? "~" : "");
1228
 
    if (db_name == NULL)
1229
 
        return ENOMEM;
1230
 
    status = destroy_db(context, db_name);
1231
 
    free(db_name);
 
1101
    dbc = context->dal_handle->db_context;
 
1102
 
 
1103
    status = ctx_allfiles(dbc, &dbname, &lockname, &polname, &plockname);
 
1104
    if (status)
 
1105
        goto cleanup;
 
1106
    status = destroy_file(dbname);
 
1107
    if (status)
 
1108
        goto cleanup;
 
1109
    status = unlink(lockname);
 
1110
    if (status)
 
1111
        goto cleanup;
 
1112
    status = osa_adb_destroy_db(polname, plockname, OSA_ADB_POLICY_DB_MAGIC);
 
1113
    if (status)
 
1114
        return status;
 
1115
 
 
1116
    status = krb5_db2_fini(context);
 
1117
 
 
1118
cleanup:
 
1119
    free(dbname);
 
1120
    free(lockname);
 
1121
    free(polname);
 
1122
    free(plockname);
1232
1123
    return status;
1233
1124
}
1234
1125
 
1295
1186
}
1296
1187
 
1297
1188
 
1298
 
/* */
1299
 
 
1300
 
krb5_error_code
1301
 
krb5_db2_promote_db(krb5_context context, char *conf_section, char **db_args)
1302
 
{
1303
 
    krb5_error_code status = 0;
1304
 
    char *db_name = NULL;
1305
 
    char *temp_db_name = NULL;
1306
 
    char **db_argp;
1307
 
    int merge_nra = 0;
1308
 
    krb5_db2_context *db_ctx = context->dal_handle->db_context;
1309
 
 
1310
 
    krb5_clear_error_message (context);
1311
 
 
1312
 
    db_name = strdup(db_ctx->db_name);
1313
 
    if (db_name == NULL) {
1314
 
        status = ENOMEM;
1315
 
        goto clean_n_exit;
1316
 
    }
1317
 
 
1318
 
    temp_db_name = gen_dbsuffix(db_name, "~");
1319
 
    if (temp_db_name == NULL) {
1320
 
        status = ENOMEM;
1321
 
        goto clean_n_exit;
1322
 
    }
1323
 
 
1324
 
    for (db_argp = db_args; *db_argp; db_argp++) {
1325
 
        if (!strcmp(*db_argp, "merge_nra")) {
1326
 
            merge_nra++;
1327
 
            break;
1328
 
        }
1329
 
    }
1330
 
 
1331
 
    status = krb5_db2_rename(context, temp_db_name, db_name, merge_nra);
1332
 
    if (status)
1333
 
        goto clean_n_exit;
1334
 
 
1335
 
clean_n_exit:
1336
 
    free(db_name);
1337
 
    free(temp_db_name);
1338
 
    return status;
1339
 
}
1340
 
 
1341
1189
/*
1342
1190
 * Merge non-replicated attributes from src into dst, setting
1343
1191
 * changed to non-zero if dst was changed.
1420
1268
 
1421
1269
/*
1422
1270
 * Merge non-replicated attributes (that is, lockout-related
1423
 
 * attributes and negative TL data types) from the old database
1424
 
 * into the new one.
1425
 
 *
1426
 
 * Note: src_db is locked on success.
 
1271
 * attributes and negative TL data types) from the real database
 
1272
 * into the temporary one.
1427
1273
 */
1428
1274
static krb5_error_code
1429
 
krb5_db2_begin_nra_merge(krb5_context context,
1430
 
                         krb5_db2_context *src_db,
1431
 
                         krb5_db2_context *dst_db)
 
1275
ctx_merge_nra(krb5_context context, krb5_db2_context *dbc_temp,
 
1276
              krb5_db2_context *dbc_real)
1432
1277
{
1433
 
    krb5_error_code retval;
1434
 
    kdb5_dal_handle *dal_handle = context->dal_handle;
1435
1278
    struct nra_context nra;
1436
1279
 
1437
1280
    nra.kcontext = context;
1438
 
    nra.db_context = dst_db;
1439
 
 
1440
 
    assert(dal_handle->db_context == dst_db);
1441
 
    dal_handle->db_context = src_db;
1442
 
 
1443
 
    retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE);
1444
 
    if (retval) {
1445
 
        dal_handle->db_context = dst_db;
1446
 
        return retval;
1447
 
    }
1448
 
 
1449
 
    retval = krb5_db2_iterate_ext(context, krb5_db2_merge_nra_iterator,
1450
 
                                  &nra, 0, 0);
1451
 
    if (retval != 0)
1452
 
        (void) krb5_db2_unlock(context);
1453
 
 
1454
 
    dal_handle->db_context = dst_db;
1455
 
 
1456
 
    return retval;
 
1281
    nra.db_context = dbc_real;
 
1282
    return ctx_iterate(context, dbc_temp, krb5_db2_merge_nra_iterator, &nra);
1457
1283
}
1458
1284
 
1459
1285
/*
1460
 
 * Finish merge of non-replicated attributes by unlocking
1461
 
 * src_db.
 
1286
 * In the filesystem, promote the temporary database described by dbc_temp to
 
1287
 * the real database described by dbc_real.  Both must be exclusively locked.
1462
1288
 */
1463
1289
static krb5_error_code
1464
 
krb5_db2_end_nra_merge(krb5_context context,
1465
 
                       krb5_db2_context *src_db,
1466
 
                       krb5_db2_context *dst_db)
 
1290
ctx_promote(krb5_context context, krb5_db2_context *dbc_temp,
 
1291
            krb5_db2_context *dbc_real)
1467
1292
{
1468
1293
    krb5_error_code retval;
1469
 
    kdb5_dal_handle *dal_handle = context->dal_handle;
1470
 
 
1471
 
    dal_handle->db_context = src_db;
1472
 
    retval = krb5_db2_unlock(context);
1473
 
    dal_handle->db_context = dst_db;
1474
 
 
 
1294
    char *tdb = NULL, *tlock = NULL, *tpol = NULL, *tplock = NULL;
 
1295
    char *rdb = NULL, *rlock = NULL, *rpol = NULL, *rplock = NULL;
 
1296
 
 
1297
    /* Generate all filenames of interest (including a few we don't need). */
 
1298
    retval = ctx_allfiles(dbc_temp, &tdb, &tlock, &tpol, &tplock);
 
1299
    if (retval)
 
1300
        return retval;
 
1301
    retval = ctx_allfiles(dbc_real, &rdb, &rlock, &rpol, &rplock);
 
1302
    if (retval)
 
1303
        goto cleanup;
 
1304
 
 
1305
    /* Rename the principal and policy databases into place. */
 
1306
    if (rename(tdb, rdb)) {
 
1307
        retval = errno;
 
1308
        goto cleanup;
 
1309
    }
 
1310
    if (rename(tpol, rpol)) {
 
1311
        retval = errno;
 
1312
        goto cleanup;
 
1313
    }
 
1314
 
 
1315
    ctx_update_age(dbc_real);
 
1316
 
 
1317
    /* Release and remove the temporary DB lockfiles. */
 
1318
    (void) unlink(tlock);
 
1319
    (void) unlink(tplock);
 
1320
 
 
1321
cleanup:
 
1322
    free(tdb);
 
1323
    free(tlock);
 
1324
    free(tpol);
 
1325
    free(tplock);
 
1326
    free(rdb);
 
1327
    free(rlock);
 
1328
    free(rpol);
 
1329
    free(rplock);
1475
1330
    return retval;
1476
1331
}
1477
1332
 
1478
 
/* Retrieved from pre-DAL code base.  */
1479
 
/*
1480
 
 * "Atomically" rename the database in a way that locks out read
1481
 
 * access in the middle of the rename.
1482
 
 *
1483
 
 * Not perfect; if we crash in the middle of an update, we don't
1484
 
 * necessarily know to complete the transaction the rename, but...
1485
 
 *
1486
 
 * Since the rename operation happens outside the init/fini bracket, we
1487
 
 * have to go through the same stuff that we went through up in db_destroy.
1488
 
 */
1489
1333
krb5_error_code
1490
 
krb5_db2_rename(krb5_context context, char *from, char *to, int merge_nra)
 
1334
krb5_db2_promote_db(krb5_context context, char *conf_section, char **db_args)
1491
1335
{
1492
 
    char *fromok;
1493
1336
    krb5_error_code retval;
1494
 
    krb5_db2_context *s_context, *db_ctx;
1495
 
    kdb5_dal_handle *dal_handle = context->dal_handle;
1496
 
 
1497
 
    s_context = dal_handle->db_context;
1498
 
    dal_handle->db_context = NULL;
1499
 
    if ((retval = k5db2_init_context(context)))
 
1337
    krb5_boolean merge_nra = FALSE, real_locked = FALSE;
 
1338
    krb5_db2_context *dbc_temp, *dbc_real = NULL;
 
1339
    char **db_argp;
 
1340
 
 
1341
    /* context must be initialized with an exclusively locked temp DB. */
 
1342
    if (!inited(context))
 
1343
        return KRB5_KDB_DBNOTINITED;
 
1344
    dbc_temp = context->dal_handle->db_context;
 
1345
    if (dbc_temp->db_lock_mode != KRB5_LOCKMODE_EXCLUSIVE)
 
1346
        return KRB5_KDB_NOTLOCKED;
 
1347
    if (!dbc_temp->tempdb)
 
1348
        return EINVAL;
 
1349
 
 
1350
    /* Check db_args for whether we should merge non-replicated attributes. */
 
1351
    for (db_argp = db_args; *db_argp; db_argp++) {
 
1352
        if (!strcmp(*db_argp, "merge_nra")) {
 
1353
            merge_nra = TRUE;
 
1354
            break;
 
1355
        }
 
1356
    }
 
1357
 
 
1358
    /* Make a db2 context for the real DB. */
 
1359
    dbc_real = k5alloc(sizeof(*dbc_real), &retval);
 
1360
    if (dbc_real == NULL)
1500
1361
        return retval;
1501
 
    db_ctx = (krb5_db2_context *) dal_handle->db_context;
1502
 
 
1503
 
    /*
1504
 
     * Create the database if it does not already exist; the
1505
 
     * files must exist because krb5_db2_lock, called below,
1506
 
     * will fail otherwise.
1507
 
     */
1508
 
    retval = create_db(context, to);
1509
 
    if (retval != 0 && retval != EEXIST)
1510
 
        goto errout;
1511
 
 
1512
 
    /*
1513
 
     * Set the database to the target, so that other processes sharing
1514
 
     * the target will stop their activity, and notice the new database.
1515
 
     */
1516
 
    db_ctx->db_name = strdup(to);
1517
 
    if (db_ctx->db_name == NULL) {
1518
 
        retval = ENOMEM;
1519
 
        goto errout;
1520
 
    }
1521
 
 
1522
 
    retval = check_openable(context);
1523
 
    if (retval)
1524
 
        goto errout;
1525
 
 
1526
 
    retval = krb5_db2_init(context);
1527
 
    if (retval)
1528
 
        goto errout;
1529
 
 
1530
 
    db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT);
1531
 
    if (db_ctx->db_lf_name == NULL) {
1532
 
        retval = ENOMEM;
1533
 
        goto errout;
1534
 
    }
1535
 
    db_ctx->db_lf_file = open(db_ctx->db_lf_name, O_RDWR|O_CREAT, 0600);
1536
 
    if (db_ctx->db_lf_file < 0) {
1537
 
        retval = errno;
1538
 
        goto errout;
1539
 
    }
1540
 
    set_cloexec_fd(db_ctx->db_lf_file);
1541
 
 
1542
 
    db_ctx->db_inited = 1;
1543
 
 
1544
 
    retval = krb5_db2_get_age(context, NULL, &db_ctx->db_lf_time);
1545
 
    if (retval)
1546
 
        goto errout;
1547
 
 
1548
 
    fromok = gen_dbsuffix(from, KDB2_LOCK_EXT);
1549
 
    if (fromok == NULL) {
1550
 
        retval = ENOMEM;
1551
 
        goto errout;
1552
 
    }
1553
 
 
1554
 
    if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
1555
 
        goto errfromok;
1556
 
 
1557
 
    if ((retval = krb5_db2_start_update(context)))
1558
 
        goto errfromok;
1559
 
 
1560
 
    if (merge_nra) {
1561
 
        if ((retval = krb5_db2_begin_nra_merge(context, s_context, db_ctx)))
1562
 
            goto errfromok;
1563
 
    }
1564
 
 
1565
 
    if (rename(from, to)) {
1566
 
        retval = errno;
1567
 
        goto errfromok;
1568
 
    }
1569
 
    if (unlink(fromok)) {
1570
 
        retval = errno;
1571
 
        goto errfromok;
1572
 
    }
1573
 
 
1574
 
    if (merge_nra) {
1575
 
        krb5_db2_end_nra_merge(context, s_context, db_ctx);
1576
 
    }
1577
 
 
1578
 
    retval = krb5_db2_end_update(context);
1579
 
    if (retval)
1580
 
        goto errfromok;
1581
 
 
1582
 
    {
1583
 
        /* XXX moved so that NRA merge works */
1584
 
        /* Ugly brute force hack.
1585
 
 
1586
 
           Should be going through nice friendly helper routines for
1587
 
           this, but it's a mess of jumbled so-called interfaces right
1588
 
           now.  */
1589
 
        char    policy[2048], new_policy[2048];
1590
 
        assert (strlen(db_ctx->db_name) < 2000);
1591
 
        snprintf(policy, sizeof(policy), "%s.kadm5", db_ctx->db_name);
1592
 
        snprintf(new_policy, sizeof(new_policy),
1593
 
                 "%s~.kadm5", db_ctx->db_name);
1594
 
        if (0 != rename(new_policy, policy)) {
1595
 
            retval = errno;
1596
 
            goto errfromok;
1597
 
        }
1598
 
        strlcat(new_policy, ".lock",sizeof(new_policy));
1599
 
        (void) unlink(new_policy);
1600
 
    }
1601
 
 
1602
 
errfromok:
1603
 
    free_dbsuffix(fromok);
1604
 
errout:
1605
 
    if (dal_handle->db_context) {
1606
 
        if (db_ctx->db_lf_file >= 0) {
1607
 
            krb5_db2_unlock(context);
1608
 
            close(db_ctx->db_lf_file);
1609
 
        }
1610
 
        k5db2_clear_context((krb5_db2_context *) dal_handle->db_context);
1611
 
        free(dal_handle->db_context);
1612
 
    }
1613
 
 
1614
 
    dal_handle->db_context = s_context;
1615
 
    (void) krb5_db2_unlock(context); /* unlock saved context db */
1616
 
 
 
1362
    ctx_clear(dbc_real);
 
1363
 
 
1364
    /* Try creating the real DB. */
 
1365
    dbc_real->db_name = strdup(dbc_temp->db_name);
 
1366
    if (dbc_real->db_name == NULL)
 
1367
        goto cleanup;
 
1368
    dbc_real->tempdb = FALSE;
 
1369
    retval = ctx_create_db(context, dbc_real);
 
1370
    if (retval == EEXIST) {
 
1371
        /* The real database already exists, so open and lock it. */
 
1372
        dbc_real->db_name = strdup(dbc_temp->db_name);
 
1373
        if (dbc_real->db_name == NULL)
 
1374
            goto cleanup;
 
1375
        dbc_real->tempdb = FALSE;
 
1376
        retval = ctx_init(dbc_real);
 
1377
        if (retval)
 
1378
            goto cleanup;
 
1379
        retval = ctx_lock(context, dbc_real, KRB5_DB_LOCKMODE_EXCLUSIVE);
 
1380
        if (retval)
 
1381
            goto cleanup;
 
1382
    } else if (retval)
 
1383
        goto cleanup;
 
1384
    real_locked = TRUE;
 
1385
 
 
1386
    if (merge_nra) {
 
1387
        retval = ctx_merge_nra(context, dbc_temp, dbc_real);
 
1388
        if (retval)
 
1389
            goto cleanup;
 
1390
    }
 
1391
 
 
1392
    /* Perform filesystem manipulations for the promotion. */
 
1393
    retval = ctx_promote(context, dbc_temp, dbc_real);
 
1394
    if (retval)
 
1395
        goto cleanup;
 
1396
 
 
1397
    /* Unlock and finalize context since the temp DB is gone. */
 
1398
    (void) krb5_db2_unlock(context);
 
1399
    krb5_db2_fini(context);
 
1400
 
 
1401
cleanup:
 
1402
    if (real_locked)
 
1403
        (void) ctx_unlock(context, dbc_real);
 
1404
    if (dbc_real)
 
1405
        ctx_fini(dbc_real);
1617
1406
    return retval;
1618
1407
}
1619
1408
 
1621
1410
krb5_db2_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
1622
1411
                         krb5_db_entry *client, krb5_db_entry *server,
1623
1412
                         krb5_timestamp kdc_time, const char **status,
1624
 
                         krb5_data *e_data)
 
1413
                         krb5_pa_data ***e_data)
1625
1414
{
1626
1415
    krb5_error_code retval;
1627
1416