|
Packit Service |
99d1c0 |
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
Packit Service |
99d1c0 |
/* plugins/kdb/db2/kdb_db2.c */
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Copyright 1997,2006,2007-2009 by the Massachusetts Institute of Technology.
|
|
Packit Service |
99d1c0 |
* All Rights Reserved.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* Export of this software from the United States of America may
|
|
Packit Service |
99d1c0 |
* require a specific license from the United States Government.
|
|
Packit Service |
99d1c0 |
* It is the responsibility of any person or organization contemplating
|
|
Packit Service |
99d1c0 |
* export to obtain such a license before exporting.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
|
Packit Service |
99d1c0 |
* distribute this software and its documentation for any purpose and
|
|
Packit Service |
99d1c0 |
* without fee is hereby granted, provided that the above copyright
|
|
Packit Service |
99d1c0 |
* notice appear in all copies and that both that copyright notice and
|
|
Packit Service |
99d1c0 |
* this permission notice appear in supporting documentation, and that
|
|
Packit Service |
99d1c0 |
* the name of M.I.T. not be used in advertising or publicity pertaining
|
|
Packit Service |
99d1c0 |
* to distribution of the software without specific, written prior
|
|
Packit Service |
99d1c0 |
* permission. Furthermore if you modify this software you must label
|
|
Packit Service |
99d1c0 |
* your software as modified software and not distribute it in such a
|
|
Packit Service |
99d1c0 |
* fashion that it might be confused with the original M.I.T. software.
|
|
Packit Service |
99d1c0 |
* M.I.T. makes no representations about the suitability of
|
|
Packit Service |
99d1c0 |
* this software for any purpose. It is provided "as is" without express
|
|
Packit Service |
99d1c0 |
* or implied warranty.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Copyright (C) 1998 by the FundsXpress, INC.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* All rights reserved.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* Export of this software from the United States of America may require
|
|
Packit Service |
99d1c0 |
* a specific license from the United States Government. It is the
|
|
Packit Service |
99d1c0 |
* responsibility of any person or organization contemplating export to
|
|
Packit Service |
99d1c0 |
* obtain such a license before exporting.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
|
|
Packit Service |
99d1c0 |
* distribute this software and its documentation for any purpose and
|
|
Packit Service |
99d1c0 |
* without fee is hereby granted, provided that the above copyright
|
|
Packit Service |
99d1c0 |
* notice appear in all copies and that both that copyright notice and
|
|
Packit Service |
99d1c0 |
* this permission notice appear in supporting documentation, and that
|
|
Packit Service |
99d1c0 |
* the name of FundsXpress. not be used in advertising or publicity pertaining
|
|
Packit Service |
99d1c0 |
* to distribution of the software without specific, written prior
|
|
Packit Service |
99d1c0 |
* permission. FundsXpress makes no representations about the suitability of
|
|
Packit Service |
99d1c0 |
* this software for any purpose. It is provided "as is" without express
|
|
Packit Service |
99d1c0 |
* or implied warranty.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
Packit Service |
99d1c0 |
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
Packit Service |
99d1c0 |
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#include "k5-int.h"
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#if HAVE_UNISTD_H
|
|
Packit Service |
99d1c0 |
#include <unistd.h>
|
|
Packit Service |
99d1c0 |
#endif
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#include <db.h>
|
|
Packit Service |
99d1c0 |
#include <stdio.h>
|
|
Packit Service |
99d1c0 |
#include <errno.h>
|
|
Packit Service |
99d1c0 |
#include <utime.h>
|
|
Packit Service |
99d1c0 |
#include "kdb5.h"
|
|
Packit Service |
99d1c0 |
#include "kdb_db2.h"
|
|
Packit Service |
99d1c0 |
#include "kdb_xdr.h"
|
|
Packit Service |
99d1c0 |
#include "policy_db.h"
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#define KDB_DB2_DATABASE_NAME "database_name"
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
#define SUFFIX_DB ""
|
|
Packit Service |
99d1c0 |
#define SUFFIX_LOCK ".ok"
|
|
Packit Service |
99d1c0 |
#define SUFFIX_POLICY ".kadm5"
|
|
Packit Service |
99d1c0 |
#define SUFFIX_POLICY_LOCK ".kadm5.lock"
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Locking:
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* There are two distinct locking protocols used. One is designed to
|
|
Packit Service |
99d1c0 |
* lock against processes (the admin_server, for one) which make
|
|
Packit Service |
99d1c0 |
* incremental changes to the database; the other is designed to lock
|
|
Packit Service |
99d1c0 |
* against utilities (kdb5_edit, kpropd, kdb5_convert) which replace the
|
|
Packit Service |
99d1c0 |
* entire database in one fell swoop.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* The first locking protocol is implemented using flock() in the
|
|
Packit Service |
99d1c0 |
* krb_dbl_lock() and krb_dbl_unlock routines.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* The second locking protocol is necessary because DBM "files" are
|
|
Packit Service |
99d1c0 |
* actually implemented as two separate files, and it is impossible to
|
|
Packit Service |
99d1c0 |
* atomically rename two files simultaneously. It assumes that the
|
|
Packit Service |
99d1c0 |
* database is replaced only very infrequently in comparison to the time
|
|
Packit Service |
99d1c0 |
* needed to do a database read operation.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* A third file is used as a "version" semaphore; the modification
|
|
Packit Service |
99d1c0 |
* time of this file is the "version number" of the database.
|
|
Packit Service |
99d1c0 |
* At the start of a read operation, the reader checks the version
|
|
Packit Service |
99d1c0 |
* number; at the end of the read operation, it checks again. If the
|
|
Packit Service |
99d1c0 |
* version number changed, or if the semaphore was nonexistant at
|
|
Packit Service |
99d1c0 |
* either time, the reader sleeps for a second to let things
|
|
Packit Service |
99d1c0 |
* stabilize, and then tries again; if it does not succeed after
|
|
Packit Service |
99d1c0 |
* KRB5_DBM_MAX_RETRY attempts, it gives up.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* On update, the semaphore file is deleted (if it exists) before any
|
|
Packit Service |
99d1c0 |
* update takes place; at the end of the update, it is replaced, with
|
|
Packit Service |
99d1c0 |
* a version number strictly greater than the version number which
|
|
Packit Service |
99d1c0 |
* existed at the start of the update.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* If the system crashes in the middle of an update, the semaphore
|
|
Packit Service |
99d1c0 |
* file is not automatically created on reboot; this is a feature, not
|
|
Packit Service |
99d1c0 |
* a bug, since the database may be inconsistant. Note that the
|
|
Packit Service |
99d1c0 |
* absence of a semaphore file does not prevent another _update_ from
|
|
Packit Service |
99d1c0 |
* taking place later. Database replacements take place automatically
|
|
Packit Service |
99d1c0 |
* only on replica servers; a crash in the middle of an update will be
|
|
Packit Service |
99d1c0 |
* fixed by the next propagation. A crash in the middle of an on the
|
|
Packit Service |
99d1c0 |
* master would be somewhat more serious, but this would likely be
|
|
Packit Service |
99d1c0 |
* noticed by an administrator, who could fix the problem and retry
|
|
Packit Service |
99d1c0 |
* the operation.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Evaluate to true if the krb5_context c contains an initialized db2
|
|
Packit Service |
99d1c0 |
* context. */
|
|
Packit Service |
99d1c0 |
#define inited(c) ((c)->dal_handle->db_context && \
|
|
Packit Service |
99d1c0 |
((krb5_db2_context *)(c)->dal_handle->db_context)-> \
|
|
Packit Service |
99d1c0 |
db_inited)
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
get_db_opt(char *input, char **opt, char **val)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
char *pos = strchr(input, '=');
|
|
Packit Service |
99d1c0 |
if (pos == NULL) {
|
|
Packit Service |
99d1c0 |
*opt = NULL;
|
|
Packit Service |
99d1c0 |
*val = strdup(input);
|
|
Packit Service |
99d1c0 |
if (*val == NULL) {
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
*opt = malloc((pos - input) + 1);
|
|
Packit Service |
99d1c0 |
*val = strdup(pos + 1);
|
|
Packit Service |
99d1c0 |
if (!*opt || !*val) {
|
|
Packit Service |
99d1c0 |
free(*opt);
|
|
Packit Service |
99d1c0 |
*opt = NULL;
|
|
Packit Service |
99d1c0 |
free(*val);
|
|
Packit Service |
99d1c0 |
*val = NULL;
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
memcpy(*opt, input, pos - input);
|
|
Packit Service |
99d1c0 |
(*opt)[pos - input] = '\0';
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return (0);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Restore dbctx to the uninitialized state. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
ctx_clear(krb5_db2_context *dbc)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Free any dynamically allocated memory. File descriptors and locks
|
|
Packit Service |
99d1c0 |
* are the caller's problem.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
free(dbc->db_lf_name);
|
|
Packit Service |
99d1c0 |
free(dbc->db_name);
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Clear the structure and reset the defaults.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
memset(dbc, 0, sizeof(krb5_db2_context));
|
|
Packit Service |
99d1c0 |
dbc->db = NULL;
|
|
Packit Service |
99d1c0 |
dbc->db_lf_name = NULL;
|
|
Packit Service |
99d1c0 |
dbc->db_lf_file = -1;
|
|
Packit Service |
99d1c0 |
dbc->db_name = NULL;
|
|
Packit Service |
99d1c0 |
dbc->db_nb_locks = FALSE;
|
|
Packit Service |
99d1c0 |
dbc->tempdb = FALSE;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Set *dbc_out to the db2 database context for context. If one does not
|
|
Packit Service |
99d1c0 |
* exist, create one in the uninitialized state. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_get(krb5_context context, krb5_db2_context **dbc_out)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
kdb5_dal_handle *dal_handle;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dal_handle = context->dal_handle;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dal_handle->db_context == NULL) {
|
|
Packit Service |
99d1c0 |
dbc = (krb5_db2_context *) malloc(sizeof(krb5_db2_context));
|
|
Packit Service |
99d1c0 |
if (dbc == NULL)
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
else {
|
|
Packit Service |
99d1c0 |
memset(dbc, 0, sizeof(krb5_db2_context));
|
|
Packit Service |
99d1c0 |
ctx_clear(dbc);
|
|
Packit Service |
99d1c0 |
dal_handle->db_context = dbc;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
*dbc_out = dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Using db_args and the profile, initialize the configurable parameters of the
|
|
Packit Service |
99d1c0 |
* DB context inside context. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
configure_context(krb5_context context, char *conf_section, char **db_args)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code status;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
char **t_ptr, *opt = NULL, *val = NULL, *pval = NULL;
|
|
Packit Service |
99d1c0 |
profile_t profile = KRB5_DB_GET_PROFILE(context);
|
|
Packit Service |
99d1c0 |
int bval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = ctx_get(context, &dbc;;
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Allow unlockiter to be overridden by command line db_args. */
|
|
Packit Service |
99d1c0 |
status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section,
|
|
Packit Service |
99d1c0 |
KRB5_CONF_UNLOCKITER, FALSE, &bval);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbc->unlockiter = bval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
for (t_ptr = db_args; t_ptr && *t_ptr; t_ptr++) {
|
|
Packit Service |
99d1c0 |
free(opt);
|
|
Packit Service |
99d1c0 |
free(val);
|
|
Packit Service |
99d1c0 |
status = get_db_opt(*t_ptr, &opt, &val;;
|
|
Packit Service |
99d1c0 |
if (opt && !strcmp(opt, "dbname")) {
|
|
Packit Service |
99d1c0 |
dbc->db_name = strdup(val);
|
|
Packit Service |
99d1c0 |
if (dbc->db_name == NULL) {
|
|
Packit Service |
99d1c0 |
status = ENOMEM;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
else if (!opt && !strcmp(val, "temporary")) {
|
|
Packit Service |
99d1c0 |
dbc->tempdb = 1;
|
|
Packit Service |
99d1c0 |
} else if (!opt && !strcmp(val, "merge_nra")) {
|
|
Packit Service |
99d1c0 |
;
|
|
Packit Service |
99d1c0 |
} else if (opt && !strcmp(opt, "hash")) {
|
|
Packit Service |
99d1c0 |
dbc->hashfirst = TRUE;
|
|
Packit Service |
99d1c0 |
} else if (!opt && !strcmp(val, "unlockiter")) {
|
|
Packit Service |
99d1c0 |
dbc->unlockiter = TRUE;
|
|
Packit Service |
99d1c0 |
} else if (!opt && !strcmp(val, "lockiter")) {
|
|
Packit Service |
99d1c0 |
dbc->unlockiter = FALSE;
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
status = EINVAL;
|
|
Packit Service |
99d1c0 |
k5_setmsg(context, status,
|
|
Packit Service |
99d1c0 |
_("Unsupported argument \"%s\" for db2"),
|
|
Packit Service |
99d1c0 |
opt ? opt : val);
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dbc->db_name == NULL) {
|
|
Packit Service |
99d1c0 |
/* Check for database_name in the db_module section. */
|
|
Packit Service |
99d1c0 |
status = profile_get_string(profile, KDB_MODULE_SECTION, conf_section,
|
|
Packit Service |
99d1c0 |
KDB_DB2_DATABASE_NAME, NULL, &pval);
|
|
Packit Service |
99d1c0 |
if (status == 0 && pval == NULL) {
|
|
Packit Service |
99d1c0 |
/* For compatibility, check for database_name in the realm. */
|
|
Packit Service |
99d1c0 |
status = profile_get_string(profile, KDB_REALM_SECTION,
|
|
Packit Service |
99d1c0 |
KRB5_DB_GET_REALM(context),
|
|
Packit Service |
99d1c0 |
KDB_DB2_DATABASE_NAME,
|
|
Packit Service |
99d1c0 |
DEFAULT_KDB_FILE, &pval);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbc->db_name = strdup(pval);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section,
|
|
Packit Service |
99d1c0 |
KRB5_CONF_DISABLE_LAST_SUCCESS, FALSE, &bval);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbc->disable_last_success = bval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section,
|
|
Packit Service |
99d1c0 |
KRB5_CONF_DISABLE_LOCKOUT, FALSE, &bval);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbc->disable_lockout = bval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
free(opt);
|
|
Packit Service |
99d1c0 |
free(val);
|
|
Packit Service |
99d1c0 |
profile_release_string(pval);
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Set *out to one of the filenames used for the DB described by dbc. sfx
|
|
Packit Service |
99d1c0 |
* should be one of SUFFIX_DB, SUFFIX_LOCK, SUFFIX_POLICY, or
|
|
Packit Service |
99d1c0 |
* SUFFIX_POLICY_LOCK.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_dbsuffix(krb5_db2_context *dbc, const char *sfx, char **out)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
char *result;
|
|
Packit Service |
99d1c0 |
const char *tilde;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
*out = NULL;
|
|
Packit Service |
99d1c0 |
tilde = dbc->tempdb ? "~" : "";
|
|
Packit Service |
99d1c0 |
if (asprintf(&result, "%s%s%s", dbc->db_name, tilde, sfx) < 0)
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
*out = result;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Generate all four files corresponding to dbc. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_allfiles(krb5_db2_context *dbc, char **dbname_out, char **lockname_out,
|
|
Packit Service |
99d1c0 |
char **polname_out, char **plockname_out)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
char *a = NULL, *b = NULL, *c = NULL, *d = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
*dbname_out = *lockname_out = *polname_out = *plockname_out = NULL;
|
|
Packit Service |
99d1c0 |
if (ctx_dbsuffix(dbc, SUFFIX_DB, &a))
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
if (ctx_dbsuffix(dbc, SUFFIX_LOCK, &b))
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
if (ctx_dbsuffix(dbc, SUFFIX_POLICY, &c))
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
if (ctx_dbsuffix(dbc, SUFFIX_POLICY_LOCK, &d))
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
*dbname_out = a;
|
|
Packit Service |
99d1c0 |
*lockname_out = b;
|
|
Packit Service |
99d1c0 |
*polname_out = c;
|
|
Packit Service |
99d1c0 |
*plockname_out = d;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
error:
|
|
Packit Service |
99d1c0 |
free(a);
|
|
Packit Service |
99d1c0 |
free(b);
|
|
Packit Service |
99d1c0 |
free(c);
|
|
Packit Service |
99d1c0 |
free(d);
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Open the DB2 database described by dbc, using the specified flags and mode,
|
|
Packit Service |
99d1c0 |
* and return the resulting handle. Try both hash and btree database types;
|
|
Packit Service |
99d1c0 |
* dbc->hashfirst determines which is attempted first. If dbc->hashfirst
|
|
Packit Service |
99d1c0 |
* indicated the wrong type, update it to indicate the correct type.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
open_db(krb5_context context, krb5_db2_context *dbc, int flags, int mode,
|
|
Packit Service |
99d1c0 |
DB **db_out)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
char *fname = NULL;
|
|
Packit Service |
99d1c0 |
DB *db;
|
|
Packit Service |
99d1c0 |
BTREEINFO bti;
|
|
Packit Service |
99d1c0 |
HASHINFO hashi;
|
|
Packit Service |
99d1c0 |
bti.flags = 0;
|
|
Packit Service |
99d1c0 |
bti.cachesize = 0;
|
|
Packit Service |
99d1c0 |
bti.psize = 4096;
|
|
Packit Service |
99d1c0 |
bti.lorder = 0;
|
|
Packit Service |
99d1c0 |
bti.minkeypage = 0;
|
|
Packit Service |
99d1c0 |
bti.compare = NULL;
|
|
Packit Service |
99d1c0 |
bti.prefix = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
*db_out = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (ctx_dbsuffix(dbc, SUFFIX_DB, &fname) != 0)
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
hashi.bsize = 4096;
|
|
Packit Service |
99d1c0 |
hashi.cachesize = 0;
|
|
Packit Service |
99d1c0 |
hashi.ffactor = 40;
|
|
Packit Service |
99d1c0 |
hashi.hash = NULL;
|
|
Packit Service |
99d1c0 |
hashi.lorder = 0;
|
|
Packit Service |
99d1c0 |
hashi.nelem = 1;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Try our best guess at the database type. */
|
|
Packit Service |
99d1c0 |
db = dbopen(fname, flags, mode,
|
|
Packit Service |
99d1c0 |
dbc->hashfirst ? DB_HASH : DB_BTREE,
|
|
Packit Service |
99d1c0 |
dbc->hashfirst ? (void *) &hashi : (void *) &bti);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (db == NULL && IS_EFTYPE(errno)) {
|
|
Packit Service |
99d1c0 |
db = dbopen(fname, flags, mode,
|
|
Packit Service |
99d1c0 |
dbc->hashfirst ? DB_BTREE : DB_HASH,
|
|
Packit Service |
99d1c0 |
dbc->hashfirst ? (void *) &bti : (void *) &hashi);
|
|
Packit Service |
99d1c0 |
/* If that worked, update our guess for next time. */
|
|
Packit Service |
99d1c0 |
if (db != NULL)
|
|
Packit Service |
99d1c0 |
dbc->hashfirst = !dbc->hashfirst;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Don't try unlocked iteration with a hash database. */
|
|
Packit Service |
99d1c0 |
if (db != NULL && dbc->hashfirst)
|
|
Packit Service |
99d1c0 |
dbc->unlockiter = FALSE;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (db == NULL) {
|
|
Packit Service |
99d1c0 |
k5_prependmsg(context, errno, _("Cannot open DB2 database '%s'"),
|
|
Packit Service |
99d1c0 |
fname);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
*db_out = db;
|
|
Packit Service |
99d1c0 |
free(fname);
|
|
Packit Service |
99d1c0 |
return (db == NULL) ? errno : 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_unlock(krb5_context context, krb5_db2_context *dbc)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval, retval2;
|
|
Packit Service |
99d1c0 |
DB *db;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = osa_adb_release_lock(dbc->policy_db);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!dbc->db_locks_held) /* lock already unlocked */
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_NOTLOCKED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
db = dbc->db;
|
|
Packit Service |
99d1c0 |
if (--(dbc->db_locks_held) == 0) {
|
|
Packit Service |
99d1c0 |
db->close(db);
|
|
Packit Service |
99d1c0 |
dbc->db = NULL;
|
|
Packit Service |
99d1c0 |
dbc->db_lock_mode = 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval2 = krb5_lock_file(context, dbc->db_lf_file,
|
|
Packit Service |
99d1c0 |
KRB5_LOCKMODE_UNLOCK);
|
|
Packit Service |
99d1c0 |
if (retval2)
|
|
Packit Service |
99d1c0 |
return retval2;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* We may be unlocking because osa_adb_get_lock() failed. */
|
|
Packit Service |
99d1c0 |
if (retval == OSA_ADB_NOTLOCKED)
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_lock(krb5_context context, krb5_db2_context *dbc, int lockmode)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
int kmode;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (lockmode == KRB5_DB_LOCKMODE_PERMANENT ||
|
|
Packit Service |
99d1c0 |
lockmode == KRB5_DB_LOCKMODE_EXCLUSIVE)
|
|
Packit Service |
99d1c0 |
kmode = KRB5_LOCKMODE_EXCLUSIVE;
|
|
Packit Service |
99d1c0 |
else if (lockmode == KRB5_DB_LOCKMODE_SHARED)
|
|
Packit Service |
99d1c0 |
kmode = KRB5_LOCKMODE_SHARED;
|
|
Packit Service |
99d1c0 |
else
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dbc->db_locks_held == 0 || dbc->db_lock_mode < kmode) {
|
|
Packit Service |
99d1c0 |
/* Acquire or upgrade the lock. */
|
|
Packit Service |
99d1c0 |
retval = krb5_lock_file(context, dbc->db_lf_file, kmode);
|
|
Packit Service |
99d1c0 |
/* Check if we tried to lock something not open for write. */
|
|
Packit Service |
99d1c0 |
if (retval == EBADF && kmode == KRB5_LOCKMODE_EXCLUSIVE)
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_CANTLOCK_DB;
|
|
Packit Service |
99d1c0 |
else if (retval == EACCES || retval == EAGAIN || retval == EWOULDBLOCK)
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_CANTLOCK_DB;
|
|
Packit Service |
99d1c0 |
else if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Open the DB (or re-open it for read/write). */
|
|
Packit Service |
99d1c0 |
if (dbc->db != NULL)
|
|
Packit Service |
99d1c0 |
dbc->db->close(dbc->db);
|
|
Packit Service |
99d1c0 |
retval = open_db(context, dbc,
|
|
Packit Service |
99d1c0 |
kmode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR,
|
|
Packit Service |
99d1c0 |
0600, &dbc->db);
|
|
Packit Service |
99d1c0 |
if (retval) {
|
|
Packit Service |
99d1c0 |
dbc->db_locks_held = 0;
|
|
Packit Service |
99d1c0 |
dbc->db_lock_mode = 0;
|
|
Packit Service |
99d1c0 |
(void) osa_adb_release_lock(dbc->policy_db);
|
|
Packit Service |
99d1c0 |
(void) krb5_lock_file(context, dbc->db_lf_file,
|
|
Packit Service |
99d1c0 |
KRB5_LOCKMODE_UNLOCK);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc->db_lock_mode = kmode;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
dbc->db_locks_held++;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Acquire or upgrade the policy lock. */
|
|
Packit Service |
99d1c0 |
retval = osa_adb_get_lock(dbc->policy_db, lockmode);
|
|
Packit Service |
99d1c0 |
if (retval) {
|
|
Packit Service |
99d1c0 |
(void) ctx_unlock(context, dbc);
|
|
Packit Service |
99d1c0 |
if (retval == OSA_ADB_NOEXCL_PERM || retval == OSA_ADB_CANTLOCK_DB ||
|
|
Packit Service |
99d1c0 |
retval == OSA_ADB_NOLOCKFILE)
|
|
Packit Service |
99d1c0 |
retval = KRB5_KDB_CANTLOCK_DB;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Initialize the lock file and policy database fields of dbc. The db_name and
|
|
Packit Service |
99d1c0 |
* tempdb fields must already be set. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_init(krb5_db2_context *dbc)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
char *polname = NULL, *plockname = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = ctx_dbsuffix(dbc, SUFFIX_LOCK, &dbc->db_lf_name);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* should be opened read/write so that write locking can work with
|
|
Packit Service |
99d1c0 |
* POSIX systems
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
if ((dbc->db_lf_file = open(dbc->db_lf_name, O_RDWR, 0666)) < 0) {
|
|
Packit Service |
99d1c0 |
if ((dbc->db_lf_file = open(dbc->db_lf_name, O_RDONLY, 0666)) < 0) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
set_cloexec_fd(dbc->db_lf_file);
|
|
Packit Service |
99d1c0 |
dbc->db_inited++;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = ctx_dbsuffix(dbc, SUFFIX_POLICY, &polname);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
retval = ctx_dbsuffix(dbc, SUFFIX_POLICY_LOCK, &plockname);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
retval = osa_adb_init_db(&dbc->policy_db, polname, plockname,
|
|
Packit Service |
99d1c0 |
OSA_ADB_POLICY_DB_MAGIC);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
free(polname);
|
|
Packit Service |
99d1c0 |
free(plockname);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
ctx_clear(dbc);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
ctx_fini(krb5_db2_context *dbc)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (dbc->db_lf_file != -1)
|
|
Packit Service |
99d1c0 |
(void) close(dbc->db_lf_file);
|
|
Packit Service |
99d1c0 |
if (dbc->policy_db)
|
|
Packit Service |
99d1c0 |
(void) osa_adb_fini_db(dbc->policy_db, OSA_ADB_POLICY_DB_MAGIC);
|
|
Packit Service |
99d1c0 |
ctx_clear(dbc);
|
|
Packit Service |
99d1c0 |
free(dbc);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_fini(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (context->dal_handle->db_context != NULL) {
|
|
Packit Service |
99d1c0 |
ctx_fini(context->dal_handle->db_context);
|
|
Packit Service |
99d1c0 |
context->dal_handle->db_context = NULL;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Return successfully if the db2 name set in context can be opened. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
check_openable(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
DB *db;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
retval = open_db(context, dbc, O_RDONLY, 0, &db);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
db->close(db);
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Return the last modification time of the database.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* Think about using fstat.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_get_age(krb5_context context, char *db_name, time_t *age)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
struct stat st;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return (KRB5_KDB_DBNOTINITED);
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (fstat(dbc->db_lf_file, &st) < 0)
|
|
Packit Service |
99d1c0 |
*age = -1;
|
|
Packit Service |
99d1c0 |
else
|
|
Packit Service |
99d1c0 |
*age = st.st_mtime;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Try to update the timestamp on dbc's lockfile. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
ctx_update_age(krb5_db2_context *dbc)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
struct stat st;
|
|
Packit Service |
99d1c0 |
time_t now;
|
|
Packit Service |
99d1c0 |
struct utimbuf utbuf;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
now = time((time_t *) NULL);
|
|
Packit Service |
99d1c0 |
if (fstat(dbc->db_lf_file, &st) != 0)
|
|
Packit Service |
99d1c0 |
return;
|
|
Packit Service |
99d1c0 |
if (st.st_mtime >= now) {
|
|
Packit Service |
99d1c0 |
utbuf.actime = st.st_mtime + 1;
|
|
Packit Service |
99d1c0 |
utbuf.modtime = st.st_mtime + 1;
|
|
Packit Service |
99d1c0 |
(void) utime(dbc->db_lf_name, &utbuf);
|
|
Packit Service |
99d1c0 |
} else
|
|
Packit Service |
99d1c0 |
(void) utime(dbc->db_lf_name, (struct utimbuf *) NULL);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_lock(krb5_context context, int lockmode)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
return ctx_lock(context, context->dal_handle->db_context, lockmode);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_unlock(krb5_context context)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
return ctx_unlock(context, context->dal_handle->db_context);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Zero out and unlink filename. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
destroy_file(char *filename)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
struct stat statb;
|
|
Packit Service |
99d1c0 |
int dowrite, j, nb, fd, retval;
|
|
Packit Service |
99d1c0 |
off_t pos;
|
|
Packit Service |
99d1c0 |
char buf[BUFSIZ], zbuf[BUFSIZ];
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
fd = open(filename, O_RDWR, 0);
|
|
Packit Service |
99d1c0 |
if (fd < 0)
|
|
Packit Service |
99d1c0 |
return errno;
|
|
Packit Service |
99d1c0 |
set_cloexec_fd(fd);
|
|
Packit Service |
99d1c0 |
/* fstat() will probably not fail unless using a remote filesystem
|
|
Packit Service |
99d1c0 |
* (which is inappropriate for the kerberos database) so this check
|
|
Packit Service |
99d1c0 |
* is mostly paranoia. */
|
|
Packit Service |
99d1c0 |
if (fstat(fd, &statb) == -1)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Stroll through the file, reading in BUFSIZ chunks. If everything
|
|
Packit Service |
99d1c0 |
* is zero, then we're done for that block, otherwise, zero the block.
|
|
Packit Service |
99d1c0 |
* We would like to just blast through everything, but some DB
|
|
Packit Service |
99d1c0 |
* implementations make holey files and writing data to the holes
|
|
Packit Service |
99d1c0 |
* causes actual blocks to be allocated which is no good, since
|
|
Packit Service |
99d1c0 |
* we're just about to unlink it anyways.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
memset(zbuf, 0, BUFSIZ);
|
|
Packit Service |
99d1c0 |
pos = 0;
|
|
Packit Service |
99d1c0 |
while (pos < statb.st_size) {
|
|
Packit Service |
99d1c0 |
dowrite = 0;
|
|
Packit Service |
99d1c0 |
nb = read(fd, buf, BUFSIZ);
|
|
Packit Service |
99d1c0 |
if (nb < 0)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
for (j = 0; j < nb; j++) {
|
|
Packit Service |
99d1c0 |
if (buf[j] != '\0') {
|
|
Packit Service |
99d1c0 |
dowrite = 1;
|
|
Packit Service |
99d1c0 |
break;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
/* For signedness */
|
|
Packit Service |
99d1c0 |
j = nb;
|
|
Packit Service |
99d1c0 |
if (dowrite) {
|
|
Packit Service |
99d1c0 |
lseek(fd, pos, SEEK_SET);
|
|
Packit Service |
99d1c0 |
nb = write(fd, zbuf, j);
|
|
Packit Service |
99d1c0 |
if (nb < 0)
|
|
Packit Service |
99d1c0 |
goto error;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
pos += nb;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
/* ??? Is fsync really needed? I don't know of any non-networked
|
|
Packit Service |
99d1c0 |
* filesystem which will discard queued writes to disk if a file
|
|
Packit Service |
99d1c0 |
* is deleted after it is closed. --jfc */
|
|
Packit Service |
99d1c0 |
#ifndef NOFSYNC
|
|
Packit Service |
99d1c0 |
fsync(fd);
|
|
Packit Service |
99d1c0 |
#endif
|
|
Packit Service |
99d1c0 |
close(fd);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (unlink(filename))
|
|
Packit Service |
99d1c0 |
return errno;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
error:
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
close(fd);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Initialize dbc by locking and creating the DB. If the DB already exists,
|
|
Packit Service |
99d1c0 |
* clear it out if dbc->tempdb is set; otherwise return EEXIST. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_create_db(krb5_context context, krb5_db2_context *dbc)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval = 0;
|
|
Packit Service |
99d1c0 |
char *dbname = NULL, *polname = NULL, *plockname = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = ctx_allfiles(dbc, &dbname, &dbc->db_lf_name, &polname,
|
|
Packit Service |
99d1c0 |
&plockname);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
rpm-build |
f9650e |
dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name,
|
|
rpm-build |
f9650e |
O_CREAT | O_RDWR | O_TRUNC, 0600);
|
|
Packit Service |
99d1c0 |
if (dbc->db_lf_file < 0) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
retval = krb5_lock_file(context, dbc->db_lf_file, KRB5_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (retval != 0)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
set_cloexec_fd(dbc->db_lf_file);
|
|
Packit Service |
99d1c0 |
dbc->db_lock_mode = KRB5_LOCKMODE_EXCLUSIVE;
|
|
Packit Service |
99d1c0 |
dbc->db_locks_held = 1;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dbc->tempdb) {
|
|
Packit Service |
99d1c0 |
/* Temporary DBs are locked for their whole lifetime. Since we have
|
|
Packit Service |
99d1c0 |
* the lock, any remnant files can be safely destroyed. */
|
|
Packit Service |
99d1c0 |
(void) destroy_file(dbname);
|
|
Packit Service |
99d1c0 |
(void) unlink(polname);
|
|
Packit Service |
99d1c0 |
(void) unlink(plockname);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = open_db(context, dbc, O_RDWR | O_CREAT | O_EXCL, 0600, &dbc->db);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Create the policy database, initialize a handle to it, and lock it. */
|
|
Packit Service |
99d1c0 |
retval = osa_adb_create_db(polname, plockname, OSA_ADB_POLICY_DB_MAGIC);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
retval = osa_adb_init_db(&dbc->policy_db, polname, plockname,
|
|
Packit Service |
99d1c0 |
OSA_ADB_POLICY_DB_MAGIC);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
retval = osa_adb_get_lock(dbc->policy_db, KRB5_DB_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc->db_inited = 1;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
if (retval) {
|
|
Packit Service |
99d1c0 |
if (dbc->db != NULL)
|
|
Packit Service |
99d1c0 |
dbc->db->close(dbc->db);
|
|
Packit Service |
99d1c0 |
if (dbc->db_locks_held > 0) {
|
|
Packit Service |
99d1c0 |
(void) krb5_lock_file(context, dbc->db_lf_file,
|
|
Packit Service |
99d1c0 |
KRB5_LOCKMODE_UNLOCK);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
if (dbc->db_lf_file >= 0)
|
|
Packit Service |
99d1c0 |
close(dbc->db_lf_file);
|
|
Packit Service |
99d1c0 |
ctx_clear(dbc);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
free(dbname);
|
|
Packit Service |
99d1c0 |
free(polname);
|
|
Packit Service |
99d1c0 |
free(plockname);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_get_principal(krb5_context context, krb5_const_principal searchfor,
|
|
Packit Service |
99d1c0 |
unsigned int flags, krb5_db_entry **entry)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
DB *db;
|
|
Packit Service |
99d1c0 |
DBT key, contents;
|
|
Packit Service |
99d1c0 |
krb5_data keydata, contdata;
|
|
Packit Service |
99d1c0 |
int dbret;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
*entry = NULL;
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = ctx_lock(context, dbc, KRB5_LOCKMODE_SHARED);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* XXX deal with wildcard lookups */
|
|
Packit Service |
99d1c0 |
retval = krb5_encode_princ_dbkey(context, &keydata, searchfor);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
key.data = keydata.data;
|
|
Packit Service |
99d1c0 |
key.size = keydata.length;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
db = dbc->db;
|
|
Packit Service |
99d1c0 |
dbret = (*db->get)(db, &key, &contents, 0);
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
krb5_free_data_contents(context, &keydata);
|
|
Packit Service |
99d1c0 |
switch (dbret) {
|
|
Packit Service |
99d1c0 |
case 1:
|
|
Packit Service |
99d1c0 |
retval = KRB5_KDB_NOENTRY;
|
|
Packit Service |
99d1c0 |
/* Fall through. */
|
|
Packit Service |
99d1c0 |
case -1:
|
|
Packit Service |
99d1c0 |
default:
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
case 0:
|
|
Packit Service |
99d1c0 |
contdata.data = contents.data;
|
|
Packit Service |
99d1c0 |
contdata.length = contents.size;
|
|
Packit Service |
99d1c0 |
retval = krb5_decode_princ_entry(context, &contdata, entry);
|
|
Packit Service |
99d1c0 |
break;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
(void) krb5_db2_unlock(context); /* unlock read lock */
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_put_principal(krb5_context context, krb5_db_entry *entry,
|
|
Packit Service |
99d1c0 |
char **db_args)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
int dbret;
|
|
Packit Service |
99d1c0 |
DB *db;
|
|
Packit Service |
99d1c0 |
DBT key, contents;
|
|
Packit Service |
99d1c0 |
krb5_data contdata, keydata;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_clear_error_message (context);
|
|
Packit Service |
99d1c0 |
if (db_args) {
|
|
Packit Service |
99d1c0 |
/* DB2 does not support db_args DB arguments for principal */
|
|
Packit Service |
99d1c0 |
k5_setmsg(context, EINVAL, _("Unsupported argument \"%s\" for db2"),
|
|
Packit Service |
99d1c0 |
db_args[0]);
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
if ((retval = ctx_lock(context, dbc, KRB5_LOCKMODE_EXCLUSIVE)))
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
db = dbc->db;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5_encode_princ_entry(context, &contdata, entry);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
contents.data = contdata.data;
|
|
Packit Service |
99d1c0 |
contents.size = contdata.length;
|
|
Packit Service |
99d1c0 |
retval = krb5_encode_princ_dbkey(context, &keydata, entry->princ);
|
|
Packit Service |
99d1c0 |
if (retval) {
|
|
Packit Service |
99d1c0 |
krb5_free_data_contents(context, &contdata);
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
key.data = keydata.data;
|
|
Packit Service |
99d1c0 |
key.size = keydata.length;
|
|
Packit Service |
99d1c0 |
dbret = (*db->put)(db, &key, &contents, 0);
|
|
Packit Service |
99d1c0 |
retval = dbret ? errno : 0;
|
|
Packit Service |
99d1c0 |
krb5_free_data_contents(context, &keydata);
|
|
Packit Service |
99d1c0 |
krb5_free_data_contents(context, &contdata);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
ctx_update_age(dbc);
|
|
Packit Service |
99d1c0 |
(void) krb5_db2_unlock(context); /* unlock database */
|
|
Packit Service |
99d1c0 |
return (retval);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_delete_principal(krb5_context context, krb5_const_principal searchfor)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
krb5_db_entry *entry;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
DB *db;
|
|
Packit Service |
99d1c0 |
DBT key, contents;
|
|
Packit Service |
99d1c0 |
krb5_data keydata, contdata;
|
|
Packit Service |
99d1c0 |
int i, dbret;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
if ((retval = ctx_lock(context, dbc, KRB5_LOCKMODE_EXCLUSIVE)))
|
|
Packit Service |
99d1c0 |
return (retval);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if ((retval = krb5_encode_princ_dbkey(context, &keydata, searchfor)))
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
key.data = keydata.data;
|
|
Packit Service |
99d1c0 |
key.size = keydata.length;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
db = dbc->db;
|
|
Packit Service |
99d1c0 |
dbret = (*db->get) (db, &key, &contents, 0);
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
switch (dbret) {
|
|
Packit Service |
99d1c0 |
case 1:
|
|
Packit Service |
99d1c0 |
retval = KRB5_KDB_NOENTRY;
|
|
Packit Service |
99d1c0 |
/* Fall through. */
|
|
Packit Service |
99d1c0 |
case -1:
|
|
Packit Service |
99d1c0 |
default:
|
|
Packit Service |
99d1c0 |
goto cleankey;
|
|
Packit Service |
99d1c0 |
case 0:
|
|
Packit Service |
99d1c0 |
;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
contdata.data = contents.data;
|
|
Packit Service |
99d1c0 |
contdata.length = contents.size;
|
|
Packit Service |
99d1c0 |
retval = krb5_decode_princ_entry(context, &contdata, &entry);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleankey;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Clear encrypted key contents */
|
|
Packit Service |
99d1c0 |
for (i = 0; i < entry->n_key_data; i++) {
|
|
Packit Service |
99d1c0 |
if (entry->key_data[i].key_data_length[0]) {
|
|
Packit Service |
99d1c0 |
memset(entry->key_data[i].key_data_contents[0], 0,
|
|
Packit Service |
99d1c0 |
(unsigned) entry->key_data[i].key_data_length[0]);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5_encode_princ_entry(context, &contdata, entry);
|
|
Packit Service |
99d1c0 |
krb5_db_free_principal(context, entry);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleankey;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
contents.data = contdata.data;
|
|
Packit Service |
99d1c0 |
contents.size = contdata.length;
|
|
Packit Service |
99d1c0 |
dbret = (*db->put) (db, &key, &contents, 0);
|
|
Packit Service |
99d1c0 |
retval = dbret ? errno : 0;
|
|
Packit Service |
99d1c0 |
krb5_free_data_contents(context, &contdata);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleankey;
|
|
Packit Service |
99d1c0 |
dbret = (*db->del) (db, &key, 0);
|
|
Packit Service |
99d1c0 |
retval = dbret ? errno : 0;
|
|
Packit Service |
99d1c0 |
cleankey:
|
|
Packit Service |
99d1c0 |
krb5_free_data_contents(context, &keydata);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
ctx_update_age(dbc);
|
|
Packit Service |
99d1c0 |
(void) krb5_db2_unlock(context); /* unlock write lock */
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
typedef krb5_error_code (*ctx_iterate_cb)(krb5_pointer, krb5_db_entry *);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Cursor structure for ctx_iterate() */
|
|
Packit Service |
99d1c0 |
typedef struct iter_curs {
|
|
Packit Service |
99d1c0 |
DBT key;
|
|
Packit Service |
99d1c0 |
DBT data;
|
|
Packit Service |
99d1c0 |
DBT keycopy;
|
|
Packit Service |
99d1c0 |
unsigned int startflag;
|
|
Packit Service |
99d1c0 |
unsigned int stepflag;
|
|
Packit Service |
99d1c0 |
krb5_context ctx;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
int lockmode;
|
|
Packit Service |
99d1c0 |
krb5_boolean islocked;
|
|
Packit Service |
99d1c0 |
} iter_curs;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Lock DB handle of curs, updating curs->islocked. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
curs_lock(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = ctx_lock(curs->ctx, curs->dbc, curs->lockmode);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
curs->islocked = TRUE;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Unlock DB handle of curs, updating curs->islocked. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
curs_unlock(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
ctx_unlock(curs->ctx, curs->dbc);
|
|
Packit Service |
99d1c0 |
curs->islocked = FALSE;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Set up curs and lock DB. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
curs_init(iter_curs *curs, krb5_context ctx, krb5_db2_context *dbc,
|
|
Packit Service |
99d1c0 |
krb5_flags iterflags)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
int isrecurse = iterflags & KRB5_DB_ITER_RECURSE;
|
|
Packit Service |
99d1c0 |
unsigned int prevflag = R_PREV;
|
|
Packit Service |
99d1c0 |
unsigned int nextflag = R_NEXT;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
curs->keycopy.size = 0;
|
|
Packit Service |
99d1c0 |
curs->keycopy.data = NULL;
|
|
Packit Service |
99d1c0 |
curs->islocked = FALSE;
|
|
Packit Service |
99d1c0 |
curs->ctx = ctx;
|
|
Packit Service |
99d1c0 |
curs->dbc = dbc;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (iterflags & KRB5_DB_ITER_WRITE)
|
|
Packit Service |
99d1c0 |
curs->lockmode = KRB5_LOCKMODE_EXCLUSIVE;
|
|
Packit Service |
99d1c0 |
else
|
|
Packit Service |
99d1c0 |
curs->lockmode = KRB5_LOCKMODE_SHARED;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (isrecurse) {
|
|
Packit Service |
99d1c0 |
#ifdef R_RNEXT
|
|
Packit Service |
99d1c0 |
if (dbc->hashfirst) {
|
|
Packit Service |
99d1c0 |
k5_setmsg(ctx, EINVAL, _("Recursive iteration is not supported "
|
|
Packit Service |
99d1c0 |
"for hash databases"));
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
prevflag = R_RPREV;
|
|
Packit Service |
99d1c0 |
nextflag = R_RNEXT;
|
|
Packit Service |
99d1c0 |
#else
|
|
Packit Service |
99d1c0 |
k5_setmsg(ctx, EINVAL, _("Recursive iteration not supported "
|
|
Packit Service |
99d1c0 |
"in this version of libdb"));
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
#endif
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
if (iterflags & KRB5_DB_ITER_REV) {
|
|
Packit Service |
99d1c0 |
curs->startflag = R_LAST;
|
|
Packit Service |
99d1c0 |
curs->stepflag = prevflag;
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
curs->startflag = R_FIRST;
|
|
Packit Service |
99d1c0 |
curs->stepflag = nextflag;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return curs_lock(curs);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Get initial entry. */
|
|
Packit Service |
99d1c0 |
static int
|
|
Packit Service |
99d1c0 |
curs_start(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
DB *db = curs->dbc->db;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return db->seq(db, &curs->key, &curs->data, curs->startflag);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Save iteration state so DB can be unlocked/closed. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
curs_save(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (!curs->dbc->unlockiter)
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
curs->keycopy.data = malloc(curs->key.size);
|
|
Packit Service |
99d1c0 |
if (curs->keycopy.data == NULL)
|
|
Packit Service |
99d1c0 |
return ENOMEM;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
curs->keycopy.size = curs->key.size;
|
|
Packit Service |
99d1c0 |
memcpy(curs->keycopy.data, curs->key.data, curs->key.size);
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Free allocated cursor resources */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
curs_free(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
free(curs->keycopy.data);
|
|
Packit Service |
99d1c0 |
curs->keycopy.size = 0;
|
|
Packit Service |
99d1c0 |
curs->keycopy.data = NULL;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Move one step of iteration (forwards or backwards as requested). Free
|
|
Packit Service |
99d1c0 |
* curs->keycopy as a side effect, if needed. */
|
|
Packit Service |
99d1c0 |
static int
|
|
Packit Service |
99d1c0 |
curs_step(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
int dbret;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = curs->dbc;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dbc->unlockiter) {
|
|
Packit Service |
99d1c0 |
/* Reacquire libdb cursor using saved copy of key. */
|
|
Packit Service |
99d1c0 |
curs->key = curs->keycopy;
|
|
Packit Service |
99d1c0 |
dbret = dbc->db->seq(dbc->db, &curs->key, &curs->data, R_CURSOR);
|
|
Packit Service |
99d1c0 |
curs_free(curs);
|
|
Packit Service |
99d1c0 |
if (dbret)
|
|
Packit Service |
99d1c0 |
return dbret;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return dbc->db->seq(dbc->db, &curs->key, &curs->data, curs->stepflag);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Run one invocation of the callback, unlocking the mutex and possibly the DB
|
|
Packit Service |
99d1c0 |
* around the invocation. */
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
curs_run_cb(iter_curs *curs, ctx_iterate_cb func, krb5_pointer func_arg)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = curs->dbc;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval, lockerr;
|
|
Packit Service |
99d1c0 |
krb5_db_entry *entry;
|
|
Packit Service |
99d1c0 |
krb5_context ctx = curs->ctx;
|
|
Packit Service |
99d1c0 |
krb5_data contdata;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
contdata = make_data(curs->data.data, curs->data.size);
|
|
Packit Service |
99d1c0 |
retval = krb5_decode_princ_entry(ctx, &contdata, &entry);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
/* Save libdb key across possible DB closure. */
|
|
Packit Service |
99d1c0 |
retval = curs_save(curs);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dbc->unlockiter)
|
|
Packit Service |
99d1c0 |
curs_unlock(curs);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
k5_mutex_unlock(krb5_db2_mutex);
|
|
Packit Service |
99d1c0 |
retval = (*func)(func_arg, entry);
|
|
Packit Service |
99d1c0 |
krb5_db_free_principal(ctx, entry);
|
|
Packit Service |
99d1c0 |
k5_mutex_lock(krb5_db2_mutex);
|
|
Packit Service |
99d1c0 |
if (dbc->unlockiter) {
|
|
Packit Service |
99d1c0 |
lockerr = curs_lock(curs);
|
|
Packit Service |
99d1c0 |
if (lockerr)
|
|
Packit Service |
99d1c0 |
return lockerr;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Free cursor resources and unlock the DB if needed. */
|
|
Packit Service |
99d1c0 |
static void
|
|
Packit Service |
99d1c0 |
curs_fini(iter_curs *curs)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
curs_free(curs);
|
|
Packit Service |
99d1c0 |
if (curs->islocked)
|
|
Packit Service |
99d1c0 |
curs_unlock(curs);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_iterate(krb5_context context, krb5_db2_context *dbc,
|
|
Packit Service |
99d1c0 |
ctx_iterate_cb func, krb5_pointer func_arg, krb5_flags iterflags)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
int dbret;
|
|
Packit Service |
99d1c0 |
iter_curs curs;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = curs_init(&curs, context, dbc, iterflags);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
dbret = curs_start(&curs;;
|
|
Packit Service |
99d1c0 |
while (dbret == 0) {
|
|
Packit Service |
99d1c0 |
retval = curs_run_cb(&curs, func, func_arg);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbret = curs_step(&curs;;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
switch (dbret) {
|
|
Packit Service |
99d1c0 |
case 1:
|
|
Packit Service |
99d1c0 |
case 0:
|
|
Packit Service |
99d1c0 |
break;
|
|
Packit Service |
99d1c0 |
case -1:
|
|
Packit Service |
99d1c0 |
default:
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
curs_fini(&curs;;
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_iterate(krb5_context context, char *match_expr, ctx_iterate_cb func,
|
|
Packit Service |
99d1c0 |
krb5_pointer func_arg, krb5_flags iterflags)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
return ctx_iterate(context, context->dal_handle->db_context, func,
|
|
Packit Service |
99d1c0 |
func_arg, iterflags);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_boolean
|
|
Packit Service |
99d1c0 |
krb5_db2_set_lockmode(krb5_context context, krb5_boolean mode)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_boolean old;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
old = mode;
|
|
Packit Service |
99d1c0 |
if (dbc) {
|
|
Packit Service |
99d1c0 |
old = dbc->db_nb_locks;
|
|
Packit Service |
99d1c0 |
dbc->db_nb_locks = mode;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
return old;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* DAL API functions
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_lib_init()
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_lib_cleanup()
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
/* right now, no cleanup required */
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_open(krb5_context context, char *conf_section, char **db_args,
|
|
Packit Service |
99d1c0 |
int mode)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code status = 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_clear_error_message(context);
|
|
Packit Service |
99d1c0 |
if (inited(context))
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = configure_context(context, conf_section, db_args);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = check_openable(context);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return ctx_init(context->dal_handle->db_context);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_create(krb5_context context, char *conf_section, char **db_args)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code status = 0;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_clear_error_message(context);
|
|
Packit Service |
99d1c0 |
if (inited(context))
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = configure_context(context, conf_section, db_args);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
status = ctx_create_db(context, dbc);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (!dbc->tempdb)
|
|
Packit Service |
99d1c0 |
krb5_db2_unlock(context);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_destroy(krb5_context context, char *conf_section, char **db_args)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code status;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc;
|
|
Packit Service |
99d1c0 |
char *dbname = NULL, *lockname = NULL, *polname = NULL, *plockname = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (inited(context)) {
|
|
Packit Service |
99d1c0 |
status = krb5_db2_fini(context);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_clear_error_message(context);
|
|
Packit Service |
99d1c0 |
status = configure_context(context, conf_section, db_args);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = check_openable(context);
|
|
Packit Service |
99d1c0 |
if (status != 0)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = ctx_allfiles(dbc, &dbname, &lockname, &polname, &plockname);
|
|
Packit Service |
99d1c0 |
if (status)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
status = destroy_file(dbname);
|
|
Packit Service |
99d1c0 |
if (status)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
status = unlink(lockname);
|
|
Packit Service |
99d1c0 |
if (status)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
status = osa_adb_destroy_db(polname, plockname, OSA_ADB_POLICY_DB_MAGIC);
|
|
Packit Service |
99d1c0 |
if (status)
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
status = krb5_db2_fini(context);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
free(dbname);
|
|
Packit Service |
99d1c0 |
free(lockname);
|
|
Packit Service |
99d1c0 |
free(polname);
|
|
Packit Service |
99d1c0 |
free(plockname);
|
|
Packit Service |
99d1c0 |
return status;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* policy functions */
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_create_policy(krb5_context context, osa_policy_ent_t policy)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return osa_adb_create_policy(dbc->policy_db, policy);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_get_policy(krb5_context context,
|
|
Packit Service |
99d1c0 |
char *name, osa_policy_ent_t *policy)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return osa_adb_get_policy(dbc->policy_db, name, policy);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_put_policy(krb5_context context, osa_policy_ent_t policy)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return osa_adb_put_policy(dbc->policy_db, policy);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_iter_policy(krb5_context context,
|
|
Packit Service |
99d1c0 |
char *match_entry,
|
|
Packit Service |
99d1c0 |
osa_adb_iter_policy_func func, void *data)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return osa_adb_iter_policy(dbc->policy_db, func, data);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_delete_policy(krb5_context context, char *policy)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return osa_adb_destroy_policy(dbc->policy_db, policy);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Merge non-replicated attributes from src into dst, setting
|
|
Packit Service |
99d1c0 |
* changed to non-zero if dst was changed.
|
|
Packit Service |
99d1c0 |
*
|
|
Packit Service |
99d1c0 |
* Non-replicated attributes are: last_success, last_failed,
|
|
Packit Service |
99d1c0 |
* fail_auth_count, and any negative TL data values.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_merge_principal(krb5_context context,
|
|
Packit Service |
99d1c0 |
krb5_db_entry *src,
|
|
Packit Service |
99d1c0 |
krb5_db_entry *dst,
|
|
Packit Service |
99d1c0 |
int *changed)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
*changed = 0;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dst->last_success != src->last_success) {
|
|
Packit Service |
99d1c0 |
dst->last_success = src->last_success;
|
|
Packit Service |
99d1c0 |
(*changed)++;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dst->last_failed != src->last_failed) {
|
|
Packit Service |
99d1c0 |
dst->last_failed = src->last_failed;
|
|
Packit Service |
99d1c0 |
(*changed)++;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (dst->fail_auth_count != src->fail_auth_count) {
|
|
Packit Service |
99d1c0 |
dst->fail_auth_count = src->fail_auth_count;
|
|
Packit Service |
99d1c0 |
(*changed)++;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
struct nra_context {
|
|
Packit Service |
99d1c0 |
krb5_context kcontext;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *db_context;
|
|
Packit Service |
99d1c0 |
};
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Iteration callback merges non-replicated attributes from
|
|
Packit Service |
99d1c0 |
* old database.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_merge_nra_iterator(krb5_pointer ptr, krb5_db_entry *entry)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
struct nra_context *nra = (struct nra_context *)ptr;
|
|
Packit Service |
99d1c0 |
kdb5_dal_handle *dal_handle = nra->kcontext->dal_handle;
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
int changed;
|
|
Packit Service |
99d1c0 |
krb5_db_entry *s_entry;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dst_db;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
memset(&s_entry, 0, sizeof(s_entry));
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dst_db = dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
dal_handle->db_context = nra->db_context;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* look up the new principal in the old DB */
|
|
Packit Service |
99d1c0 |
retval = krb5_db2_get_principal(nra->kcontext, entry->princ, 0, &s_entry);
|
|
Packit Service |
99d1c0 |
if (retval != 0) {
|
|
Packit Service |
99d1c0 |
/* principal may be newly created, so ignore */
|
|
Packit Service |
99d1c0 |
dal_handle->db_context = dst_db;
|
|
Packit Service |
99d1c0 |
return 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* merge non-replicated attributes from the old entry in */
|
|
Packit Service |
99d1c0 |
krb5_db2_merge_principal(nra->kcontext, s_entry, entry, &changed);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
dal_handle->db_context = dst_db;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* if necessary, commit the modified new entry to the new DB */
|
|
Packit Service |
99d1c0 |
if (changed) {
|
|
Packit Service |
99d1c0 |
retval = krb5_db2_put_principal(nra->kcontext, entry, NULL);
|
|
Packit Service |
99d1c0 |
} else {
|
|
Packit Service |
99d1c0 |
retval = 0;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_db_free_principal(nra->kcontext, s_entry);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* Merge non-replicated attributes (that is, lockout-related
|
|
Packit Service |
99d1c0 |
* attributes and negative TL data types) from the real database
|
|
Packit Service |
99d1c0 |
* into the temporary one.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_merge_nra(krb5_context context, krb5_db2_context *dbc_temp,
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc_real)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
struct nra_context nra;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
nra.kcontext = context;
|
|
Packit Service |
99d1c0 |
nra.db_context = dbc_real;
|
|
Packit Service |
99d1c0 |
return ctx_iterate(context, dbc_temp, krb5_db2_merge_nra_iterator, &nra, 0);
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/*
|
|
Packit Service |
99d1c0 |
* In the filesystem, promote the temporary database described by dbc_temp to
|
|
Packit Service |
99d1c0 |
* the real database described by dbc_real. Both must be exclusively locked.
|
|
Packit Service |
99d1c0 |
*/
|
|
Packit Service |
99d1c0 |
static krb5_error_code
|
|
Packit Service |
99d1c0 |
ctx_promote(krb5_context context, krb5_db2_context *dbc_temp,
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc_real)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
char *tdb = NULL, *tlock = NULL, *tpol = NULL, *tplock = NULL;
|
|
Packit Service |
99d1c0 |
char *rdb = NULL, *rlock = NULL, *rpol = NULL, *rplock = NULL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Generate all filenames of interest (including a few we don't need). */
|
|
Packit Service |
99d1c0 |
retval = ctx_allfiles(dbc_temp, &tdb, &tlock, &tpol, &tplock);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
retval = ctx_allfiles(dbc_real, &rdb, &rlock, &rpol, &rplock);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Rename the principal and policy databases into place. */
|
|
Packit Service |
99d1c0 |
if (rename(tdb, rdb)) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
if (rename(tpol, rpol)) {
|
|
Packit Service |
99d1c0 |
retval = errno;
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
ctx_update_age(dbc_real);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Release and remove the temporary DB lockfiles. */
|
|
Packit Service |
99d1c0 |
(void) unlink(tlock);
|
|
Packit Service |
99d1c0 |
(void) unlink(tplock);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
free(tdb);
|
|
Packit Service |
99d1c0 |
free(tlock);
|
|
Packit Service |
99d1c0 |
free(tpol);
|
|
Packit Service |
99d1c0 |
free(tplock);
|
|
Packit Service |
99d1c0 |
free(rdb);
|
|
Packit Service |
99d1c0 |
free(rlock);
|
|
Packit Service |
99d1c0 |
free(rpol);
|
|
Packit Service |
99d1c0 |
free(rplock);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_promote_db(krb5_context context, char *conf_section, char **db_args)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
krb5_boolean merge_nra = FALSE, real_locked = FALSE;
|
|
Packit Service |
99d1c0 |
krb5_db2_context *dbc_temp, *dbc_real = NULL;
|
|
Packit Service |
99d1c0 |
char **db_argp;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* context must be initialized with an exclusively locked temp DB. */
|
|
Packit Service |
99d1c0 |
if (!inited(context))
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_DBNOTINITED;
|
|
Packit Service |
99d1c0 |
dbc_temp = context->dal_handle->db_context;
|
|
Packit Service |
99d1c0 |
if (dbc_temp->db_lock_mode != KRB5_LOCKMODE_EXCLUSIVE)
|
|
Packit Service |
99d1c0 |
return KRB5_KDB_NOTLOCKED;
|
|
Packit Service |
99d1c0 |
if (!dbc_temp->tempdb)
|
|
Packit Service |
99d1c0 |
return EINVAL;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Check db_args for whether we should merge non-replicated attributes. */
|
|
Packit Service |
99d1c0 |
for (db_argp = db_args; *db_argp; db_argp++) {
|
|
Packit Service |
99d1c0 |
if (!strcmp(*db_argp, "merge_nra")) {
|
|
Packit Service |
99d1c0 |
merge_nra = TRUE;
|
|
Packit Service |
99d1c0 |
break;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Make a db2 context for the real DB. */
|
|
Packit Service |
99d1c0 |
dbc_real = k5alloc(sizeof(*dbc_real), &retval);
|
|
Packit Service |
99d1c0 |
if (dbc_real == NULL)
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
ctx_clear(dbc_real);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Try creating the real DB. */
|
|
Packit Service |
99d1c0 |
dbc_real->db_name = strdup(dbc_temp->db_name);
|
|
Packit Service |
99d1c0 |
if (dbc_real->db_name == NULL)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbc_real->tempdb = FALSE;
|
|
Packit Service |
99d1c0 |
retval = ctx_create_db(context, dbc_real);
|
|
Packit Service |
99d1c0 |
if (retval == EEXIST) {
|
|
Packit Service |
99d1c0 |
/* The real database already exists, so open and lock it. */
|
|
Packit Service |
99d1c0 |
dbc_real->db_name = strdup(dbc_temp->db_name);
|
|
Packit Service |
99d1c0 |
if (dbc_real->db_name == NULL)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
dbc_real->tempdb = FALSE;
|
|
Packit Service |
99d1c0 |
retval = ctx_init(dbc_real);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
retval = ctx_lock(context, dbc_real, KRB5_DB_LOCKMODE_EXCLUSIVE);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
} else if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
real_locked = TRUE;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
if (merge_nra) {
|
|
Packit Service |
99d1c0 |
retval = ctx_merge_nra(context, dbc_temp, dbc_real);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Perform filesystem manipulations for the promotion. */
|
|
Packit Service |
99d1c0 |
retval = ctx_promote(context, dbc_temp, dbc_real);
|
|
Packit Service |
99d1c0 |
if (retval)
|
|
Packit Service |
99d1c0 |
goto cleanup;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
/* Unlock and finalize context since the temp DB is gone. */
|
|
Packit Service |
99d1c0 |
(void) krb5_db2_unlock(context);
|
|
Packit Service |
99d1c0 |
krb5_db2_fini(context);
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
cleanup:
|
|
Packit Service |
99d1c0 |
if (real_locked)
|
|
Packit Service |
99d1c0 |
(void) ctx_unlock(context, dbc_real);
|
|
Packit Service |
99d1c0 |
if (dbc_real)
|
|
Packit Service |
99d1c0 |
ctx_fini(dbc_real);
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
krb5_error_code
|
|
Packit Service |
99d1c0 |
krb5_db2_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
|
|
Packit Service |
99d1c0 |
krb5_db_entry *client, krb5_db_entry *server,
|
|
Packit Service |
99d1c0 |
krb5_timestamp kdc_time, const char **status,
|
|
Packit Service |
99d1c0 |
krb5_pa_data ***e_data)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
krb5_error_code retval;
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
retval = krb5_db2_lockout_check_policy(kcontext, client, kdc_time);
|
|
Packit Service |
99d1c0 |
if (retval == KRB5KDC_ERR_CLIENT_REVOKED)
|
|
Packit Service |
99d1c0 |
*status = "LOCKED_OUT";
|
|
Packit Service |
99d1c0 |
return retval;
|
|
Packit Service |
99d1c0 |
}
|
|
Packit Service |
99d1c0 |
|
|
Packit Service |
99d1c0 |
void
|
|
Packit Service |
99d1c0 |
krb5_db2_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
|
|
Packit Service |
99d1c0 |
const krb5_address *local_addr,
|
|
Packit Service |
99d1c0 |
const krb5_address *remote_addr, krb5_db_entry *client,
|
|
Packit Service |
99d1c0 |
krb5_db_entry *server, krb5_timestamp authtime,
|
|
Packit Service |
99d1c0 |
krb5_error_code error_code)
|
|
Packit Service |
99d1c0 |
{
|
|
Packit Service |
99d1c0 |
(void) krb5_db2_lockout_audit(kcontext, client, authtime, error_code);
|
|
Packit Service |
99d1c0 |
}
|