static errno_t find_ipa_ext_memberships(TALLOC_CTX *mem_ctx,
                                        const char *user_name,
                                        struct sss_domain_info *user_dom,
                                        hash_table_t *ext_group_hash,
                                        struct ldb_dn **_user_dn,
                                        char ***_groups)
{
    int ret;
    TALLOC_CTX *tmp_ctx = NULL;
    struct ldb_result *result;
    char **groups = NULL;
    size_t c;
    const char *sid;
    hash_key_t key;
    hash_value_t value;
    hash_entry_t *entry;
    struct hash_iter_context_t *iter;
    hash_table_t *group_hash;
    size_t g_count;
    struct ldb_dn *user_dn = NULL;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        return ENOMEM;
    }

    ret = sysdb_initgroups(tmp_ctx, user_dom, user_name, &result);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "sysdb_initgroups failed.\n");
        goto done;
    }

    if (result->count == 0) {
        DEBUG(SSSDBG_MINOR_FAILURE, "User [%s] not found in cache.\n",
                                     user_name);
        ret = EOK;
        goto done;
    }

    ret = sss_hash_create(tmp_ctx, 10, &group_hash);
    if (ret != HASH_SUCCESS) {
        DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n");
        goto done;
    }

    key.type = HASH_KEY_STRING;

    /* The IPA external domains can have references to group and user SIDs.
     * This means that we not only want to look up the group SIDs but the SID
     * of the user (first element of result) as well. */
    for (c = 0; c < result->count; c++) {
        sid = ldb_msg_find_attr_as_string(result->msgs[c], SYSDB_SID_STR,
                                          NULL);
        if (sid == NULL) {
            DEBUG(SSSDBG_MINOR_FAILURE, "Group [%s] does not have a SID.\n",
                  ldb_dn_get_linearized(result->msgs[c]->dn));
            continue;
        }

        key.str = discard_const(sid);
        ret = hash_lookup(ext_group_hash, &key, &value);
        if (ret == HASH_ERROR_KEY_NOT_FOUND) {
            DEBUG(SSSDBG_TRACE_ALL, "SID [%s] not found in ext group hash.\n",
                                     sid);
        } else if (ret == HASH_SUCCESS) {
            iter = new_hash_iter_context(value.ptr);
            if (iter == NULL) {
                DEBUG(SSSDBG_OP_FAILURE, "new_hash_iter_context failed.\n");
                ret = EINVAL;
                goto done;
            }

            while ((entry = iter->next(iter)) != NULL) {
                ret = hash_enter(group_hash, &entry->key, &entry->value);
                if (ret != HASH_SUCCESS) {
                    DEBUG(SSSDBG_OP_FAILURE, "Failed to add group [%s].\n",
                                              entry->key.str);
                }
            }

            talloc_free(iter);
        } else {
            DEBUG(SSSDBG_OP_FAILURE, "hash_lookup failed for SID [%s].\n",
                                      sid);
        }
    }

    g_count = hash_count(group_hash);
    if (g_count == 0) {
        DEBUG(SSSDBG_TRACE_FUNC, "No external groupmemberships found.\n");
        ret = EOK;
        goto done;
    }

    groups = talloc_zero_array(mem_ctx, char *, g_count + 1);
    if (groups == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
        ret = ENOMEM;
        goto done;
    }

    iter = new_hash_iter_context(group_hash);
    if (iter == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "new_hash_iter_context failed.\n");
        ret = EINVAL;
        goto done;
    }

    c = 0;
    while ((entry = iter->next(iter)) != NULL) {
        groups[c] = talloc_strdup(groups, entry->key.str);
        if (groups[c] == NULL) {
            DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
            ret = ENOMEM;
            goto done;
        }
        c++;
    }

    user_dn = ldb_dn_copy(mem_ctx, result->msgs[0]->dn);
    if (user_dn == NULL) {
        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_copy failed.\n");
        ret = ENOMEM;
        goto done;
    }

    ret = EOK;
done:
    *_user_dn = user_dn;
    *_groups = groups;

    talloc_free(tmp_ctx);

    return ret;
}
示例#2
0
int main(int argc, char **argv)
{
    static hash_table_t *table = NULL;
    hash_key_t key, *keys;
    hash_value_t value;
    struct hash_iter_context_t *iter;
    hash_entry_t *entry;
    unsigned long i, n_entries;
    int error;
    struct my_data_t *my_data = new_data(1024, "Hello World!");
    unsigned long count;

    /* Create a hash table */
    error = hash_create(10, &table, delete_callback,  NULL);
    if (error != HASH_SUCCESS) {
        fprintf(stderr, "cannot create hash table (%s)\n", hash_error_string(error));
        return error;
    }

    /* Enter a key named "My Data" and specify it's value as a pointer to my_data */
    key.type = HASH_KEY_STRING;
    key.str = strdup("My Data");
    value.type = HASH_VALUE_PTR;
    value.ptr = my_data;

    if ((error = hash_enter(table, &key, &value)) != HASH_SUCCESS) {
        fprintf(stderr, "cannot add to table \"%s\" (%s)\n", key.str, hash_error_string(error));
        return error;
    }
    free(key.str);

    /* Get a list of keys and print them out, free the list when we're done */
    if ((error = hash_keys(table, &count, &keys)) != HASH_SUCCESS) {
        fprintf(stderr, "cannot get key list (%s)\n", hash_error_string(error));
        return error;
    }

    for (i = 0; i < count; i++)
        printf("key: %s\n", keys[i].str);
    free(keys);

    /* Lookup the key named "My Data" */
    key.type = HASH_KEY_STRING;
    key.str = strdup("My Data");
    if ((error = hash_lookup(table, &key, &value)) != HASH_SUCCESS) {
        fprintf(stderr, "cannot find key \"%s\" (%s)\n", key.str, hash_error_string(error));
    }
    free(key.str);

    /* Visit each entry in the table, callback will increment count on each visit */
    printf("Iterate using callback\n");
    count = 0;
    hash_iterate(table, visit_callback, &count);

    /* Assure number of visits equal the table size */
    assert(count == hash_count(table));

    /* Visit each entry using iterator object */
    printf("Iterate using iterator\n");
    n_entries = 0;
    iter = new_hash_iter_context(table);
    while ((entry = iter->next(iter)) != NULL) {
        struct my_data_t *data = (struct my_data_t *) entry->value.ptr;

        printf("%s = [foo=%d bar=%s]\n", entry->key.str, data->foo, data->bar);
        n_entries++;
    }
    free(iter);
    /* Assure number of visits equal the table size */
    assert(n_entries == hash_count(table));

    /* Remove the entry, deletion callback will be invoked */
    key.type = HASH_KEY_STRING;
    key.str = strdup("My Data");
    if ((error = hash_delete(table, &key)) != HASH_SUCCESS) {
        fprintf(stderr, "cannot delete from table (%s)\n", hash_error_string(error));
    }

    /* Assure key is no longer in table */
    assert (!hash_has_key(table, &key));
    free(key.str);

    /* Free the table */
    hash_destroy(table);

    return 0;
}