Exemple #1
0
/* Run one invocation of the callback, unlocking the mutex and possibly the DB
 * around the invocation. */
static krb5_error_code
curs_run_cb(iter_curs *curs, ctx_iterate_cb func, krb5_pointer func_arg)
{
    krb5_db2_context *dbc = curs->dbc;
    krb5_error_code retval, lockerr;
    krb5_db_entry *entry;
    krb5_context ctx = curs->ctx;
    krb5_data contdata;

    contdata = make_data(curs->data.data, curs->data.size);
    retval = krb5_decode_princ_entry(ctx, &contdata, &entry);
    if (retval)
        return retval;
    /* Save libdb key across possible DB closure. */
    retval = curs_save(curs);
    if (retval)
        return retval;

    if (dbc->unlockiter)
        curs_unlock(curs);

    k5_mutex_unlock(krb5_db2_mutex);
    retval = (*func)(func_arg, entry);
    krb5_db2_free(ctx, entry);
    k5_mutex_lock(krb5_db2_mutex);
    if (dbc->unlockiter) {
        lockerr = curs_lock(curs);
        if (lockerr)
            return lockerr;
    }
    return retval;
}
Exemple #2
0
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;
}
Exemple #3
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}