Пример #1
0
krb5_error_code
osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
{
    int ret;

    ret = osa_adb_get_lock(db, locktype);
    if (ret != OSA_ADB_OK)
        return ret;
    if (db->opencnt)
        goto open_ok;

    db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo);
    if (db->db != NULL)
        goto open_ok;
    if (IS_EFTYPE(errno)) {
        db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
        if (db->db != NULL)
            goto open_ok;
    } else {
        (void) osa_adb_release_lock(db);
        if (errno == EINVAL)
            return OSA_ADB_BAD_DB;
        return errno;
    }
open_ok:
    db->opencnt++;
    return OSA_ADB_OK;
}
Пример #2
0
krb5_error_code
osa_adb_rename_db(char *filefrom, char *lockfrom, char *fileto, char *lockto,
                  int magic)
{
    osa_adb_db_t fromdb, todb;
    krb5_error_code ret;

    /* make sure todb exists */
    if ((ret = osa_adb_create_db(fileto, lockto, magic)) &&
            ret != EEXIST)
        return ret;

    if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic)))
        return ret;
    if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) {
        (void) osa_adb_fini_db(fromdb, magic);
        return ret;
    }
    if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) {
        (void) osa_adb_fini_db(fromdb, magic);
        (void) osa_adb_fini_db(todb, magic);
        return ret;
    }
    if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) {
        (void) osa_adb_fini_db(fromdb, magic);
        (void) osa_adb_fini_db(todb, magic);
        return ret;
    }
    if ((rename(filefrom, fileto) < 0)) {
        (void) osa_adb_fini_db(fromdb, magic);
        (void) osa_adb_fini_db(todb, magic);
        return errno;
    }
    /*
     * Do not release the lock on fromdb because it is being renamed
     * out of existence; no one can ever use it again.
     */
    if ((ret = osa_adb_release_lock(todb))) {
        (void) osa_adb_fini_db(fromdb, magic);
        (void) osa_adb_fini_db(todb, magic);
        return ret;
    }

    (void) osa_adb_fini_db(fromdb, magic);
    (void) osa_adb_fini_db(todb, magic);
    return 0;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
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;
}
Пример #6
0
/* Initialize dbc by locking and creating the DB.  If the DB already exists,
 * clear it out if dbc->tempdb is set; otherwise return EEXIST. */
static krb5_error_code
ctx_create_db(krb5_context context, krb5_db2_context *dbc)
{
    krb5_error_code retval = 0;
    char *dbname = NULL, *polname = NULL, *plockname = NULL;

    retval = ctx_allfiles(dbc, &dbname, &dbc->db_lf_name, &polname,
                          &plockname);
    if (retval)
        return retval;

    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
                           0600);
    if (dbc->db_lf_file < 0) {
        retval = errno;
        goto cleanup;
    }
    retval = krb5_lock_file(context, dbc->db_lf_file,
                            KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
    if (retval != 0)
        goto cleanup;
    set_cloexec_fd(dbc->db_lf_file);
    dbc->db_lock_mode = KRB5_LOCKMODE_EXCLUSIVE;
    dbc->db_locks_held = 1;

    if (dbc->tempdb) {
        /* Temporary DBs are locked for their whole lifetime.  Since we have
         * the lock, any remnant files can be safely destroyed. */
        (void) destroy_file(dbname);
        (void) unlink(polname);
        (void) unlink(plockname);
    }

    dbc->db = open_db(dbc, O_RDWR | O_CREAT | O_EXCL, 0600);
    if (dbc->db == NULL) {
        retval = errno;
        goto cleanup;
    }

    /* Create the policy database, initialize a handle to it, and lock it. */
    retval = osa_adb_create_db(polname, plockname, OSA_ADB_POLICY_DB_MAGIC);
    if (retval)
        goto cleanup;
    retval = osa_adb_init_db(&dbc->policy_db, polname, plockname,
                             OSA_ADB_POLICY_DB_MAGIC);
    if (retval)
        goto cleanup;
    retval = osa_adb_get_lock(dbc->policy_db, KRB5_DB_LOCKMODE_EXCLUSIVE);
    if (retval)
        goto cleanup;

    dbc->db_inited = 1;

cleanup:
    if (retval) {
        if (dbc->db != NULL)
            dbc->db->close(dbc->db);
        if (dbc->db_locks_held > 0) {
            (void) krb5_lock_file(context, dbc->db_lf_file,
                                  KRB5_LOCKMODE_UNLOCK);
        }
        if (dbc->db_lf_file >= 0)
            close(dbc->db_lf_file);
        ctx_clear(dbc);
    }
    free(dbname);
    free(polname);
    free(plockname);
    return retval;
}