Exemple #1
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 #2
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 #3
0
/* Free an entry returned by krb5_db2_get_principal. */
void
krb5_db2_free_principal(krb5_context context, krb5_db_entry *entry)
{
    krb5_dbe_free(context, entry);
}
Exemple #4
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;
}
Exemple #5
0
krb5_error_code
krb5_decode_princ_entry(krb5_context context, krb5_data *content,
                        krb5_db_entry **entry_ptr)
{
    int                   sizeleft, i;
    unsigned char       * nextloc;
    krb5_tl_data       ** tl_data;
    krb5_int16            i16;
    krb5_db_entry       * entry;
    krb5_error_code retval;

    *entry_ptr = NULL;

    entry = k5alloc(sizeof(*entry), &retval);
    if (entry == NULL)
        return retval;

    /*
     * Reverse the encoding of encode_princ_entry.
     *
     * The first part is decoding the base type. If the base type is
     * bigger than the original base type then the additional fields
     * need to be filled in. If the base type is larger than any
     * known base type the additional data goes in e_data.
     */

    /* First do the easy stuff */
    nextloc = (unsigned char *)content->data;
    sizeleft = content->length;
    if ((sizeleft -= KRB5_KDB_V1_BASE_LENGTH) < 0) {
        retval = KRB5_KDB_TRUNCATED_RECORD;
        goto error_out;
    }

    /* Base Length */
    krb5_kdb_decode_int16(nextloc, entry->len);
    nextloc += 2;

    /* Attributes */
    krb5_kdb_decode_int32(nextloc, entry->attributes);
    nextloc += 4;

    /* Max Life */
    krb5_kdb_decode_int32(nextloc, entry->max_life);
    nextloc += 4;

    /* Max Renewable Life */
    krb5_kdb_decode_int32(nextloc, entry->max_renewable_life);
    nextloc += 4;

    /* When the client expires */
    krb5_kdb_decode_int32(nextloc, entry->expiration);
    nextloc += 4;

    /* When its passwd expires */
    krb5_kdb_decode_int32(nextloc, entry->pw_expiration);
    nextloc += 4;

    /* Last successful passwd */
    krb5_kdb_decode_int32(nextloc, entry->last_success);
    nextloc += 4;

    /* Last failed passwd attempt */
    krb5_kdb_decode_int32(nextloc, entry->last_failed);
    nextloc += 4;

    /* # of failed passwd attempt */
    krb5_kdb_decode_int32(nextloc, entry->fail_auth_count);
    nextloc += 4;

    /* # tl_data strutures */
    krb5_kdb_decode_int16(nextloc, entry->n_tl_data);
    nextloc += 2;

    if (entry->n_tl_data < 0) {
        retval = KRB5_KDB_TRUNCATED_RECORD;
        goto error_out;
    }

    /* # key_data strutures */
    krb5_kdb_decode_int16(nextloc, entry->n_key_data);
    nextloc += 2;

    if (entry->n_key_data < 0) {
        retval = KRB5_KDB_TRUNCATED_RECORD;
        goto error_out;
    }

    /* Check for extra data */
    if (entry->len > KRB5_KDB_V1_BASE_LENGTH) {
        entry->e_length = entry->len - KRB5_KDB_V1_BASE_LENGTH;
        entry->e_data = k5memdup(nextloc, entry->e_length, &retval);
        if (entry->e_data == NULL)
            goto error_out;
        nextloc += entry->e_length;
    }

    /*
     * Get the principal name for the entry
     * (stored as a string which gets unparsed.)
     */
    if ((sizeleft -= 2) < 0) {
        retval = KRB5_KDB_TRUNCATED_RECORD;
        goto error_out;
    }

    i = 0;
    krb5_kdb_decode_int16(nextloc, i16);
    i = (int) i16;
    nextloc += 2;

    if ((retval = krb5_parse_name(context, (char *)nextloc, &(entry->princ))))
        goto error_out;
    if (((size_t) i != (strlen((char *)nextloc) + 1)) || (sizeleft < i)) {
        retval = KRB5_KDB_TRUNCATED_RECORD;
        goto error_out;
    }
    sizeleft -= i;
    nextloc += i;

    /* tl_data is a linked list */
    tl_data = &entry->tl_data;
    for (i = 0; i < entry->n_tl_data; i++) {
        if ((sizeleft -= 4) < 0) {
            retval = KRB5_KDB_TRUNCATED_RECORD;
            goto error_out;
        }
        if ((*tl_data = (krb5_tl_data *)
             malloc(sizeof(krb5_tl_data))) == NULL) {
            retval = ENOMEM;
            goto error_out;
        }
        (*tl_data)->tl_data_next = NULL;
        (*tl_data)->tl_data_contents = NULL;
        krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_type);
        nextloc += 2;
        krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_length);
        nextloc += 2;

        if ((sizeleft -= (*tl_data)->tl_data_length) < 0) {
            retval = KRB5_KDB_TRUNCATED_RECORD;
            goto error_out;
        }
        (*tl_data)->tl_data_contents =
            k5memdup(nextloc, (*tl_data)->tl_data_length, &retval);
        if ((*tl_data)->tl_data_contents == NULL)
            goto error_out;
        nextloc += (*tl_data)->tl_data_length;
        tl_data = &((*tl_data)->tl_data_next);
    }

    /* key_data is an array */
    if (entry->n_key_data && ((entry->key_data = (krb5_key_data *)
                               malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL)) {
        retval = ENOMEM;
        goto error_out;
    }
    for (i = 0; i < entry->n_key_data; i++) {
        krb5_key_data * key_data;
        int j;

        if ((sizeleft -= 4) < 0) {
            retval = KRB5_KDB_TRUNCATED_RECORD;
            goto error_out;
        }
        key_data = entry->key_data + i;
        memset(key_data, 0, sizeof(krb5_key_data));
        krb5_kdb_decode_int16(nextloc, key_data->key_data_ver);
        nextloc += 2;
        krb5_kdb_decode_int16(nextloc, key_data->key_data_kvno);
        nextloc += 2;

        /* key_data_ver determins number of elements and how to unparse them. */
        if (key_data->key_data_ver <= KRB5_KDB_V1_KEY_DATA_ARRAY) {
            for (j = 0; j < key_data->key_data_ver; j++) {
                if ((sizeleft -= 4) < 0) {
                    retval = KRB5_KDB_TRUNCATED_RECORD;
                    goto error_out;
                }
                krb5_kdb_decode_int16(nextloc, key_data->key_data_type[j]);
                nextloc += 2;
                krb5_kdb_decode_int16(nextloc, key_data->key_data_length[j]);
                nextloc += 2;

                if ((sizeleft -= key_data->key_data_length[j]) < 0) {
                    retval = KRB5_KDB_TRUNCATED_RECORD;
                    goto error_out;
                }
                if (key_data->key_data_length[j]) {
                    key_data->key_data_contents[j] =
                        k5memdup(nextloc, key_data->key_data_length[j],
                                 &retval);
                    if (key_data->key_data_contents[j] == NULL)
                        goto error_out;
                    nextloc += key_data->key_data_length[j];
                }
            }
        } else {
            /* This isn't right. I'll fix it later */
            abort();
        }
    }
    *entry_ptr = entry;
    return 0;

error_out:
    krb5_dbe_free(context, entry);
    return retval;
}