Exemplo n.º 1
0
krb5_error_code
krb5_db2_unlock(krb5_context context)
{
    if (!inited(context))
        return KRB5_KDB_DBNOTINITED;
    return ctx_unlock(context, context->dal_handle->db_context);
}
Exemplo n.º 2
0
static krb5_error_code
ctx_lock(krb5_context context, krb5_db2_context *dbc, int lockmode)
{
    krb5_error_code retval;
    int kmode, tries;

    if (lockmode == KRB5_DB_LOCKMODE_PERMANENT ||
        lockmode == KRB5_DB_LOCKMODE_EXCLUSIVE)
        kmode = KRB5_LOCKMODE_EXCLUSIVE;
    else if (lockmode == KRB5_DB_LOCKMODE_SHARED)
        kmode = KRB5_LOCKMODE_SHARED;
    else
        return EINVAL;

    if (dbc->db_locks_held == 0 || dbc->db_lock_mode < kmode) {
        /* Acquire or upgrade the lock. */
        for (tries = 0; tries < MAX_LOCK_TRIES; tries++) {
            retval = krb5_lock_file(context, dbc->db_lf_file,
                                    kmode | KRB5_LOCKMODE_DONTBLOCK);
            if (retval == 0)
                break;
            if (retval == EBADF && kmode == KRB5_LOCKMODE_EXCLUSIVE)
                /* Tried to 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)
            return retval;

        /* Open the DB (or re-open it for read/write). */
        if (dbc->db != NULL)
            dbc->db->close(dbc->db);
        dbc->db = open_db(dbc,
                          kmode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR,
                          0600);
        if (dbc->db == NULL) {
            retval = errno;
            dbc->db_locks_held = 0;
            dbc->db_lock_mode = 0;
            (void) osa_adb_release_lock(dbc->policy_db);
            (void) krb5_lock_file(context, dbc->db_lf_file,
                                  KRB5_LOCKMODE_UNLOCK);
            return retval;
        }

        dbc->db_lock_mode = kmode;
    }
    dbc->db_locks_held++;

    /* Acquire or upgrade the policy lock. */
    retval = osa_adb_get_lock(dbc->policy_db, lockmode);
    if (retval)
        (void) ctx_unlock(context, dbc);
    return retval;
}
Exemplo n.º 3
0
static krb5_error_code
ctx_lock(krb5_context context, krb5_db2_context *dbc, int lockmode)
{
    krb5_error_code retval;
    int kmode;

    if (lockmode == KRB5_DB_LOCKMODE_PERMANENT ||
        lockmode == KRB5_DB_LOCKMODE_EXCLUSIVE)
        kmode = KRB5_LOCKMODE_EXCLUSIVE;
    else if (lockmode == KRB5_DB_LOCKMODE_SHARED)
        kmode = KRB5_LOCKMODE_SHARED;
    else
        return EINVAL;

    if (dbc->db_locks_held == 0 || dbc->db_lock_mode < kmode) {
        /* Acquire or upgrade the lock. */
        retval = krb5_lock_file(context, dbc->db_lf_file, kmode);
        /* Check if we tried to lock something not open for write. */
        if (retval == EBADF && kmode == KRB5_LOCKMODE_EXCLUSIVE)
            return KRB5_KDB_CANTLOCK_DB;
        else if (retval == EACCES || retval == EAGAIN || retval == EWOULDBLOCK)
            return KRB5_KDB_CANTLOCK_DB;
        else if (retval)
            return retval;

        /* Open the DB (or re-open it for read/write). */
        if (dbc->db != NULL)
            dbc->db->close(dbc->db);
        dbc->db = open_db(dbc,
                          kmode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR,
                          0600);
        if (dbc->db == NULL) {
            retval = errno;
            dbc->db_locks_held = 0;
            dbc->db_lock_mode = 0;
            (void) osa_adb_release_lock(dbc->policy_db);
            (void) krb5_lock_file(context, dbc->db_lf_file,
                                  KRB5_LOCKMODE_UNLOCK);
            return retval;
        }

        dbc->db_lock_mode = kmode;
    }
    dbc->db_locks_held++;

    /* Acquire or upgrade the policy lock. */
    retval = osa_adb_get_lock(dbc->policy_db, lockmode);
    if (retval) {
        (void) ctx_unlock(context, dbc);
        if (retval == OSA_ADB_NOEXCL_PERM || retval == OSA_ADB_CANTLOCK_DB ||
            retval == OSA_ADB_NOLOCKFILE)
            retval = KRB5_KDB_CANTLOCK_DB;
    }
    return retval;
}
Exemplo n.º 4
0
static krb5_error_code
ctx_iterate(krb5_context context, krb5_db2_context *dbc,
            krb5_error_code (*func)(krb5_pointer, krb5_db_entry *),
            krb5_pointer func_arg)
{
    DB *db;
    DBT key, contents;
    krb5_data contdata;
    krb5_db_entry *entry;
    krb5_error_code retval, retval2;
    int dbret;

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

    db = dbc->db;
    dbret = db->seq(db, &key, &contents, R_FIRST);
    while (dbret == 0) {
        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;
        }
        dbret = db->seq(db, &key, &contents, R_NEXT);
    }
    switch (dbret) {
    case 1:
    case 0:
        break;
    case -1:
    default:
        retval = errno;
    }
    (void) ctx_unlock(context, dbc);
    return retval;
}
Exemplo n.º 5
0
/* Unlock DB handle of curs, updating curs->islocked. */
static void
curs_unlock(iter_curs *curs)
{
    ctx_unlock(curs->ctx, curs->dbc);
    curs->islocked = FALSE;
}
Exemplo n.º 6
0
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;
}