예제 #1
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
krb5_error_code
krb5_db2_put_principal(krb5_context context, krb5_db_entry *entry,
                       char **db_args)
{
    int     dbret;
    DB     *db;
    DBT     key, contents;
    krb5_data contdata, keydata;
    krb5_error_code retval;
    krb5_db2_context *db_ctx;

    krb5_clear_error_message (context);
    if (db_args) {
        /* DB2 does not support db_args DB arguments for principal */
        krb5_set_error_message(context, EINVAL,
                               "Unsupported argument \"%s\" for db2",
                               db_args[0]);
        return EINVAL;
    }

    if (!k5db2_inited(context))
        return KRB5_KDB_DBNOTINITED;

    db_ctx = context->dal_handle->db_context;
    if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
        return retval;

    db = db_ctx->db;
    if ((retval = krb5_db2_start_update(context))) {
        (void) krb5_db2_unlock(context);
        return retval;
    }

    retval = krb5_encode_princ_entry(context, &contdata, entry);
    if (retval)
        goto cleanup;
    contents.data = contdata.data;
    contents.size = contdata.length;
    retval = krb5_encode_princ_dbkey(context, &keydata, entry->princ);
    if (retval) {
        krb5_free_data_contents(context, &contdata);
        goto cleanup;
    }

    key.data = keydata.data;
    key.size = keydata.length;
    dbret = (*db->put)(db, &key, &contents, 0);
    retval = dbret ? errno : 0;
    krb5_free_data_contents(context, &keydata);
    krb5_free_data_contents(context, &contdata);

cleanup:
    (void) krb5_db2_end_update(context);
    (void) krb5_db2_unlock(context); /* unlock database */
    return (retval);
}
예제 #2
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
/*
 * Merge non-replicated attributes (that is, lockout-related
 * attributes and negative TL data types) from the old database
 * into the new one.
 *
 * Note: src_db is locked on success.
 */
static krb5_error_code
krb5_db2_begin_nra_merge(krb5_context context,
                         krb5_db2_context *src_db,
                         krb5_db2_context *dst_db)
{
    krb5_error_code retval;
    kdb5_dal_handle *dal_handle = context->dal_handle;
    struct nra_context nra;

    nra.kcontext = context;
    nra.db_context = dst_db;

    assert(dal_handle->db_context == dst_db);
    dal_handle->db_context = src_db;

    retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE);
    if (retval) {
        dal_handle->db_context = dst_db;
        return retval;
    }

    retval = krb5_db2_iterate_ext(context, krb5_db2_merge_nra_iterator,
                                  &nra, 0, 0);
    if (retval != 0)
        (void) krb5_db2_unlock(context);

    dal_handle->db_context = dst_db;

    return retval;
}
예제 #3
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
krb5_error_code
krb5_db2_get_principal(krb5_context context, krb5_const_principal searchfor,
                       unsigned int flags, krb5_db_entry **entry)
{
    krb5_db2_context *db_ctx;
    krb5_error_code retval;
    DB     *db;
    DBT     key, contents;
    krb5_data keydata, contdata;
    int     trynum, dbret;

    *entry = NULL;
    if (!k5db2_inited(context))
        return KRB5_KDB_DBNOTINITED;

    db_ctx = context->dal_handle->db_context;

    for (trynum = 0; trynum < KRB5_DB2_MAX_RETRY; trynum++) {
        if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_SHARED))) {
            if (db_ctx->db_nb_locks)
                return (retval);
            sleep(1);
            continue;
        }
        break;
    }
    if (trynum == KRB5_DB2_MAX_RETRY)
        return KRB5_KDB_DB_INUSE;

    /* XXX deal with wildcard lookups */
    retval = krb5_encode_princ_dbkey(context, &keydata, searchfor);
    if (retval)
        goto cleanup;
    key.data = keydata.data;
    key.size = keydata.length;

    db = db_ctx->db;
    dbret = (*db->get)(db, &key, &contents, 0);
    retval = errno;
    krb5_free_data_contents(context, &keydata);
    switch (dbret) {
    case 1:
        retval = KRB5_KDB_NOENTRY;
        /* Fall through. */
    case -1:
    default:
        goto cleanup;
    case 0:
        contdata.data = contents.data;
        contdata.length = contents.size;
        retval = krb5_decode_princ_entry(context, &contdata, entry);
        break;
    }

cleanup:
    (void) krb5_db2_unlock(context); /* unlock read lock */
    return retval;
}
예제 #4
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
/*
 * Finish merge of non-replicated attributes by unlocking
 * src_db.
 */
static krb5_error_code
krb5_db2_end_nra_merge(krb5_context context,
                       krb5_db2_context *src_db,
                       krb5_db2_context *dst_db)
{
    krb5_error_code retval;
    kdb5_dal_handle *dal_handle = context->dal_handle;

    dal_handle->db_context = src_db;
    retval = krb5_db2_unlock(context);
    dal_handle->db_context = dst_db;

    return retval;
}
예제 #5
0
파일: kdb_db2.c 프로젝트: DirectXMan12/krb5
krb5_error_code
krb5_db2_get_principal(krb5_context context, krb5_const_principal searchfor,
                       unsigned int flags, krb5_db_entry **entry)
{
    krb5_db2_context *dbc;
    krb5_error_code retval;
    DB     *db;
    DBT     key, contents;
    krb5_data keydata, contdata;
    int     dbret;

    *entry = NULL;
    if (!inited(context))
        return KRB5_KDB_DBNOTINITED;

    dbc = context->dal_handle->db_context;

    retval = ctx_lock(context, dbc, KRB5_LOCKMODE_SHARED);
    if (retval)
        return retval;

    /* XXX deal with wildcard lookups */
    retval = krb5_encode_princ_dbkey(context, &keydata, searchfor);
    if (retval)
        goto cleanup;
    key.data = keydata.data;
    key.size = keydata.length;

    db = dbc->db;
    dbret = (*db->get)(db, &key, &contents, 0);
    retval = errno;
    krb5_free_data_contents(context, &keydata);
    switch (dbret) {
    case 1:
        retval = KRB5_KDB_NOENTRY;
        /* Fall through. */
    case -1:
    default:
        goto cleanup;
    case 0:
        contdata.data = contents.data;
        contdata.length = contents.size;
        retval = krb5_decode_princ_entry(context, &contdata, entry);
        break;
    }

cleanup:
    (void) krb5_db2_unlock(context); /* unlock read lock */
    return retval;
}
예제 #6
0
파일: kdb_db2.c 프로젝트: DirectXMan12/krb5
krb5_error_code
krb5_db2_create(krb5_context context, char *conf_section, char **db_args)
{
    krb5_error_code status = 0;
    krb5_db2_context *dbc;

    krb5_clear_error_message(context);
    if (inited(context))
        return 0;

    status = configure_context(context, conf_section, db_args);
    if (status != 0)
        return status;

    dbc = context->dal_handle->db_context;
    status = ctx_create_db(context, dbc);
    if (status != 0)
        return status;

    if (!dbc->tempdb)
        krb5_db2_unlock(context);

    return 0;
}
예제 #7
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
krb5_error_code
krb5_db2_delete_principal(krb5_context context, krb5_const_principal searchfor)
{
    krb5_error_code retval;
    krb5_db_entry *entry;
    krb5_db2_context *db_ctx;
    DB     *db;
    DBT     key, contents;
    krb5_data keydata, contdata;
    int     i, dbret;

    if (!k5db2_inited(context))
        return KRB5_KDB_DBNOTINITED;

    db_ctx = context->dal_handle->db_context;
    if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
        return (retval);

    if ((retval = krb5_db2_start_update(context))) {
        (void) krb5_db2_unlock(context);     /* unlock write lock */
        return (retval);
    }

    if ((retval = krb5_encode_princ_dbkey(context, &keydata, searchfor)))
        goto cleanup;
    key.data = keydata.data;
    key.size = keydata.length;

    db = db_ctx->db;
    dbret = (*db->get) (db, &key, &contents, 0);
    retval = errno;
    switch (dbret) {
    case 1:
        retval = KRB5_KDB_NOENTRY;
        /* Fall through. */
    case -1:
    default:
        goto cleankey;
    case 0:
        ;
    }
    contdata.data = contents.data;
    contdata.length = contents.size;
    retval = krb5_decode_princ_entry(context, &contdata, &entry);
    if (retval)
        goto cleankey;

    /* Clear encrypted key contents */
    for (i = 0; i < entry->n_key_data; i++) {
        if (entry->key_data[i].key_data_length[0]) {
            memset(entry->key_data[i].key_data_contents[0], 0,
                   (unsigned) entry->key_data[i].key_data_length[0]);
        }
    }

    retval = krb5_encode_princ_entry(context, &contdata, entry);
    krb5_dbe_free(context, entry);
    if (retval)
        goto cleankey;

    contents.data = contdata.data;
    contents.size = contdata.length;
    dbret = (*db->put) (db, &key, &contents, 0);
    retval = dbret ? errno : 0;
    krb5_free_data_contents(context, &contdata);
    if (retval)
        goto cleankey;
    dbret = (*db->del) (db, &key, 0);
    retval = dbret ? errno : 0;
cleankey:
    krb5_free_data_contents(context, &keydata);

cleanup:
    (void) krb5_db2_end_update(context);
    (void) krb5_db2_unlock(context); /* unlock write lock */
    return retval;
}
예제 #8
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
krb5_error_code
krb5_db2_lock(krb5_context context, int in_mode)
{
    krb5_db2_context *db_ctx;
    int     krb5_lock_mode;
    DB     *db;
    krb5_error_code retval;
    time_t  mod_time;
    int     mode, gotlock, tries;

    switch (in_mode) {
    case KRB5_DB_LOCKMODE_PERMANENT:
        mode = KRB5_DB_LOCKMODE_EXCLUSIVE;
        break;
    case KRB5_DB_LOCKMODE_EXCLUSIVE:
        mode = KRB5_LOCKMODE_EXCLUSIVE;
        break;

    case KRB5_DB_LOCKMODE_SHARED:
        mode = KRB5_LOCKMODE_SHARED;
        break;
    default:
        return EINVAL;
    }

    if (!k5db2_inited(context))
        return KRB5_KDB_DBNOTINITED;

    db_ctx = context->dal_handle->db_context;
    if (db_ctx->db_locks_held && (db_ctx->db_lock_mode >= mode)) {
        /* No need to upgrade lock, just return */
        db_ctx->db_locks_held++;
        goto policy_lock;
    }

    if ((mode != KRB5_LOCKMODE_SHARED) && (mode != KRB5_LOCKMODE_EXCLUSIVE))
        return KRB5_KDB_BADLOCKMODE;

    krb5_lock_mode = mode | KRB5_LOCKMODE_DONTBLOCK;
    for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
        retval = krb5_lock_file(context, db_ctx->db_lf_file, krb5_lock_mode);
        if (retval == 0) {
            gotlock++;
            break;
        } else if (retval == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
            /* tried to exclusive-lock something we don't have */
            /* write access to */
            return KRB5_KDB_CANTLOCK_DB;
        sleep(1);
    }
    if (retval == EACCES)
        return KRB5_KDB_CANTLOCK_DB;
    else if (retval == EAGAIN || retval == EWOULDBLOCK)
        return OSA_ADB_CANTLOCK_DB;
    else if (retval != 0)
        return retval;

    if ((retval = krb5_db2_get_age(context, NULL, &mod_time)))
        goto lock_error;

    db = k5db2_dbopen(db_ctx, db_ctx->db_name,
                      mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR, 0600, db_ctx->tempdb);
    if (db) {
        db_ctx->db_lf_time = mod_time;
        db_ctx->db = db;
    } else {
        retval = errno;
        db_ctx->db = NULL;
        goto lock_error;
    }

    db_ctx->db_lock_mode = mode;
    db_ctx->db_locks_held++;

policy_lock:
    if ((retval = osa_adb_get_lock(db_ctx->policy_db, in_mode))) {
        krb5_db2_unlock(context);
    }
    return retval;

lock_error:;
    db_ctx->db_lock_mode = 0;
    db_ctx->db_locks_held = 0;
    krb5_db2_unlock(context);
    return retval;
}
예제 #9
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
/*
 * "Atomically" rename the database in a way that locks out read
 * access in the middle of the rename.
 *
 * Not perfect; if we crash in the middle of an update, we don't
 * necessarily know to complete the transaction the rename, but...
 *
 * Since the rename operation happens outside the init/fini bracket, we
 * have to go through the same stuff that we went through up in db_destroy.
 */
krb5_error_code
krb5_db2_rename(krb5_context context, char *from, char *to, int merge_nra)
{
    char *fromok;
    krb5_error_code retval;
    krb5_db2_context *s_context, *db_ctx;
    kdb5_dal_handle *dal_handle = context->dal_handle;

    s_context = dal_handle->db_context;
    dal_handle->db_context = NULL;
    if ((retval = k5db2_init_context(context)))
        return retval;
    db_ctx = (krb5_db2_context *) dal_handle->db_context;

    /*
     * Create the database if it does not already exist; the
     * files must exist because krb5_db2_lock, called below,
     * will fail otherwise.
     */
    retval = create_db(context, to);
    if (retval != 0 && retval != EEXIST)
        goto errout;

    /*
     * Set the database to the target, so that other processes sharing
     * the target will stop their activity, and notice the new database.
     */
    db_ctx->db_name = strdup(to);
    if (db_ctx->db_name == NULL) {
        retval = ENOMEM;
        goto errout;
    }

    retval = check_openable(context);
    if (retval)
        goto errout;

    retval = krb5_db2_init(context);
    if (retval)
        goto errout;

    db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT);
    if (db_ctx->db_lf_name == NULL) {
        retval = ENOMEM;
        goto errout;
    }
    db_ctx->db_lf_file = open(db_ctx->db_lf_name, O_RDWR|O_CREAT, 0600);
    if (db_ctx->db_lf_file < 0) {
        retval = errno;
        goto errout;
    }
    set_cloexec_fd(db_ctx->db_lf_file);

    db_ctx->db_inited = 1;

    retval = krb5_db2_get_age(context, NULL, &db_ctx->db_lf_time);
    if (retval)
        goto errout;

    fromok = gen_dbsuffix(from, KDB2_LOCK_EXT);
    if (fromok == NULL) {
        retval = ENOMEM;
        goto errout;
    }

    if ((retval = krb5_db2_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
        goto errfromok;

    if ((retval = krb5_db2_start_update(context)))
        goto errfromok;

    if (merge_nra) {
        if ((retval = krb5_db2_begin_nra_merge(context, s_context, db_ctx)))
            goto errfromok;
    }

    if (rename(from, to)) {
        retval = errno;
        goto errfromok;
    }
    if (unlink(fromok)) {
        retval = errno;
        goto errfromok;
    }

    if (merge_nra) {
        krb5_db2_end_nra_merge(context, s_context, db_ctx);
    }

    retval = krb5_db2_end_update(context);
    if (retval)
        goto errfromok;

    {
        /* XXX moved so that NRA merge works */
        /* Ugly brute force hack.

           Should be going through nice friendly helper routines for
           this, but it's a mess of jumbled so-called interfaces right
           now.  */
        char    policy[2048], new_policy[2048];
        assert (strlen(db_ctx->db_name) < 2000);
        snprintf(policy, sizeof(policy), "%s.kadm5", db_ctx->db_name);
        snprintf(new_policy, sizeof(new_policy),
                 "%s~.kadm5", db_ctx->db_name);
        if (0 != rename(new_policy, policy)) {
            retval = errno;
            goto errfromok;
        }
        strlcat(new_policy, ".lock",sizeof(new_policy));
        (void) unlink(new_policy);
    }

errfromok:
    free_dbsuffix(fromok);
errout:
    if (dal_handle->db_context) {
        if (db_ctx->db_lf_file >= 0) {
            krb5_db2_unlock(context);
            close(db_ctx->db_lf_file);
        }
        k5db2_clear_context((krb5_db2_context *) dal_handle->db_context);
        free(dal_handle->db_context);
    }

    dal_handle->db_context = s_context;
    (void) krb5_db2_unlock(context); /* unlock saved context db */

    return retval;
}
예제 #10
0
파일: kdb_db2.c 프로젝트: Brainiarc7/pbis
krb5_error_code
krb5_db2_iterate_ext(krb5_context context,
                     krb5_error_code(*func) (krb5_pointer, krb5_db_entry *),
                     krb5_pointer func_arg, int backwards, int recursive)
{
    krb5_db2_context *db_ctx;
    DB     *db;
    DBT     key, contents;
    krb5_data contdata;
    krb5_db_entry *entry;
    krb5_error_code retval;
    int     dbret;
    void   *cookie;

    cookie = NULL;
    if (!k5db2_inited(context))
        return KRB5_KDB_DBNOTINITED;

    db_ctx = context->dal_handle->db_context;
    retval = krb5_db2_lock(context, KRB5_LOCKMODE_SHARED);

    if (retval)
        return retval;

    db = db_ctx->db;
    if (recursive && db->type != DB_BTREE) {
        (void) krb5_db2_unlock(context);
        return KRB5_KDB_UK_RERROR;      /* Not optimal, but close enough. */
    }

    if (!recursive) {
        dbret = (*db->seq) (db, &key, &contents, backwards ? R_LAST : R_FIRST);
    } else {
#ifdef HAVE_BT_RSEQ
        dbret = bt_rseq(db, &key, &contents, &cookie,
                        backwards ? R_LAST : R_FIRST);
#else
        (void) krb5_db2_unlock(context);
        return KRB5_KDB_UK_RERROR;      /* Not optimal, but close enough. */
#endif
    }
    while (dbret == 0) {
        krb5_error_code retval2;

        contdata.data = contents.data;
        contdata.length = contents.size;
        retval = krb5_decode_princ_entry(context, &contdata, &entry);
        if (retval)
            break;
        retval = k5_mutex_unlock(krb5_db2_mutex);
        if (retval)
            break;
        retval = (*func)(func_arg, entry);
        krb5_dbe_free(context, entry);
        retval2 = k5_mutex_lock(krb5_db2_mutex);
        /* Note: If re-locking fails, the wrapper in db2_exp.c will
           still try to unlock it again.  That would be a bug.  Fix
           when integrating the locking better.  */
        if (retval)
            break;
        if (retval2) {
            retval = retval2;
            break;
        }
        if (!recursive) {
            dbret = (*db->seq) (db, &key, &contents,
                                backwards ? R_PREV : R_NEXT);
        } else {
#ifdef HAVE_BT_RSEQ
            dbret = bt_rseq(db, &key, &contents, &cookie,
                            backwards ? R_PREV : R_NEXT);
#else
            (void) krb5_db2_unlock(context);
            return KRB5_KDB_UK_RERROR;  /* Not optimal, but close enough. */
#endif
        }
    }
    switch (dbret) {
    case 1:
    case 0:
        break;
    case -1:
    default:
        retval = errno;
    }
    (void) krb5_db2_unlock(context);
    return retval;
}
예제 #11
0
파일: kdb_db2.c 프로젝트: DirectXMan12/krb5
krb5_error_code
krb5_db2_promote_db(krb5_context context, char *conf_section, char **db_args)
{
    krb5_error_code retval;
    krb5_boolean merge_nra = FALSE, real_locked = FALSE;
    krb5_db2_context *dbc_temp, *dbc_real = NULL;
    char **db_argp;

    /* context must be initialized with an exclusively locked temp DB. */
    if (!inited(context))
        return KRB5_KDB_DBNOTINITED;
    dbc_temp = context->dal_handle->db_context;
    if (dbc_temp->db_lock_mode != KRB5_LOCKMODE_EXCLUSIVE)
        return KRB5_KDB_NOTLOCKED;
    if (!dbc_temp->tempdb)
        return EINVAL;

    /* Check db_args for whether we should merge non-replicated attributes. */
    for (db_argp = db_args; *db_argp; db_argp++) {
        if (!strcmp(*db_argp, "merge_nra")) {
            merge_nra = TRUE;
            break;
        }
    }

    /* Make a db2 context for the real DB. */
    dbc_real = k5alloc(sizeof(*dbc_real), &retval);
    if (dbc_real == NULL)
        return retval;
    ctx_clear(dbc_real);

    /* Try creating the real DB. */
    dbc_real->db_name = strdup(dbc_temp->db_name);
    if (dbc_real->db_name == NULL)
        goto cleanup;
    dbc_real->tempdb = FALSE;
    retval = ctx_create_db(context, dbc_real);
    if (retval == EEXIST) {
        /* The real database already exists, so open and lock it. */
        dbc_real->db_name = strdup(dbc_temp->db_name);
        if (dbc_real->db_name == NULL)
            goto cleanup;
        dbc_real->tempdb = FALSE;
        retval = ctx_init(dbc_real);
        if (retval)
            goto cleanup;
        retval = ctx_lock(context, dbc_real, KRB5_DB_LOCKMODE_EXCLUSIVE);
        if (retval)
            goto cleanup;
    } else if (retval)
        goto cleanup;
    real_locked = TRUE;

    if (merge_nra) {
        retval = ctx_merge_nra(context, dbc_temp, dbc_real);
        if (retval)
            goto cleanup;
    }

    /* Perform filesystem manipulations for the promotion. */
    retval = ctx_promote(context, dbc_temp, dbc_real);
    if (retval)
        goto cleanup;

    /* Unlock and finalize context since the temp DB is gone. */
    (void) krb5_db2_unlock(context);
    krb5_db2_fini(context);

cleanup:
    if (real_locked)
        (void) ctx_unlock(context, dbc_real);
    if (dbc_real)
        ctx_fini(dbc_real);
    return retval;
}