Blame src/lib/krad/attrset.c

Packit Service 99d1c0
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit Service 99d1c0
/* lib/krad/attrset.c - RADIUS attribute set functions for libkrad */
Packit Service 99d1c0
/*
Packit Service 99d1c0
 * Copyright 2013 Red Hat, Inc.  All rights reserved.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 * Redistribution and use in source and binary forms, with or without
Packit Service 99d1c0
 * modification, are permitted provided that the following conditions are met:
Packit Service 99d1c0
 *
Packit Service 99d1c0
 *    1. Redistributions of source code must retain the above copyright
Packit Service 99d1c0
 *       notice, this list of conditions and the following disclaimer.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 *    2. Redistributions in binary form must reproduce the above copyright
Packit Service 99d1c0
 *       notice, this list of conditions and the following disclaimer in
Packit Service 99d1c0
 *       the documentation and/or other materials provided with the
Packit Service 99d1c0
 *       distribution.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
Packit Service 99d1c0
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Packit Service 99d1c0
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit Service 99d1c0
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
Packit Service 99d1c0
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit Service 99d1c0
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit Service 99d1c0
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit Service 99d1c0
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit Service 99d1c0
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit Service 99d1c0
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit Service 99d1c0
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 99d1c0
 */
Packit Service 99d1c0
Packit Service 99d1c0
#include <k5-int.h>
Packit Service 99d1c0
#include <k5-queue.h>
Packit Service 99d1c0
#include "internal.h"
Packit Service 99d1c0
Packit Service 99d1c0
#include <string.h>
Packit Service 99d1c0
Packit Service 99d1c0
K5_TAILQ_HEAD(attr_head, attr_st);
Packit Service 99d1c0
Packit Service 99d1c0
typedef struct attr_st attr;
Packit Service 99d1c0
struct attr_st {
Packit Service 99d1c0
    K5_TAILQ_ENTRY(attr_st) list;
Packit Service 99d1c0
    krad_attr type;
Packit Service 99d1c0
    krb5_data attr;
Packit Service 99d1c0
    char buffer[MAX_ATTRSIZE];
Packit Service 99d1c0
};
Packit Service 99d1c0
Packit Service 99d1c0
struct krad_attrset_st {
Packit Service 99d1c0
    krb5_context ctx;
Packit Service 99d1c0
    struct attr_head list;
Packit Service 99d1c0
};
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krad_attrset_new(krb5_context ctx, krad_attrset **set)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krad_attrset *tmp;
Packit Service 99d1c0
Packit Service 99d1c0
    tmp = calloc(1, sizeof(krad_attrset));
Packit Service 99d1c0
    if (tmp == NULL)
Packit Service 99d1c0
        return ENOMEM;
Packit Service 99d1c0
    tmp->ctx = ctx;
Packit Service 99d1c0
    K5_TAILQ_INIT(&tmp->list);
Packit Service 99d1c0
Packit Service 99d1c0
    *set = tmp;
Packit Service 99d1c0
    return 0;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
void
Packit Service 99d1c0
krad_attrset_free(krad_attrset *set)
Packit Service 99d1c0
{
Packit Service 99d1c0
    attr *a;
Packit Service 99d1c0
Packit Service 99d1c0
    if (set == NULL)
Packit Service 99d1c0
        return;
Packit Service 99d1c0
Packit Service 99d1c0
    while (!K5_TAILQ_EMPTY(&set->list)) {
Packit Service 99d1c0
        a = K5_TAILQ_FIRST(&set->list);
Packit Service 99d1c0
        K5_TAILQ_REMOVE(&set->list, a, list);
Packit Service 99d1c0
        zap(a->buffer, sizeof(a->buffer));
Packit Service 99d1c0
        free(a);
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    free(set);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krad_attrset_add(krad_attrset *set, krad_attr type, const krb5_data *data)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_error_code retval;
Packit Service 99d1c0
    attr *tmp;
Packit Service 99d1c0
Packit Service 99d1c0
    retval = kr_attr_valid(type, data);
Packit Service 99d1c0
    if (retval != 0)
Packit Service 99d1c0
        return retval;
Packit Service 99d1c0
Packit Service 99d1c0
    tmp = calloc(1, sizeof(attr));
Packit Service 99d1c0
    if (tmp == NULL)
Packit Service 99d1c0
        return ENOMEM;
Packit Service 99d1c0
Packit Service 99d1c0
    tmp->type = type;
Packit Service 99d1c0
    tmp->attr = make_data(tmp->buffer, data->length);
Packit Service 99d1c0
    memcpy(tmp->attr.data, data->data, data->length);
Packit Service 99d1c0
Packit Service 99d1c0
    K5_TAILQ_INSERT_TAIL(&set->list, tmp, list);
Packit Service 99d1c0
    return 0;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krad_attrset_add_number(krad_attrset *set, krad_attr type, krb5_ui_4 num)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_data data;
Packit Service 99d1c0
Packit Service 99d1c0
    num = htonl(num);
Packit Service 99d1c0
    data = make_data(&num, sizeof(num));
Packit Service 99d1c0
    return krad_attrset_add(set, type, &data);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
void
Packit Service 99d1c0
krad_attrset_del(krad_attrset *set, krad_attr type, size_t indx)
Packit Service 99d1c0
{
Packit Service 99d1c0
    attr *a;
Packit Service 99d1c0
Packit Service 99d1c0
    K5_TAILQ_FOREACH(a, &set->list, list) {
Packit Service 99d1c0
        if (a->type == type && indx-- == 0) {
Packit Service 99d1c0
            K5_TAILQ_REMOVE(&set->list, a, list);
Packit Service 99d1c0
            zap(a->buffer, sizeof(a->buffer));
Packit Service 99d1c0
            free(a);
Packit Service 99d1c0
            return;
Packit Service 99d1c0
        }
Packit Service 99d1c0
    }
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
const krb5_data *
Packit Service 99d1c0
krad_attrset_get(const krad_attrset *set, krad_attr type, size_t indx)
Packit Service 99d1c0
{
Packit Service 99d1c0
    attr *a;
Packit Service 99d1c0
Packit Service 99d1c0
    K5_TAILQ_FOREACH(a, &set->list, list) {
Packit Service 99d1c0
        if (a->type == type && indx-- == 0)
Packit Service 99d1c0
            return &a->attr;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    return NULL;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_error_code retval;
Packit Service 99d1c0
    krad_attrset *tmp;
Packit Service 99d1c0
    attr *a;
Packit Service 99d1c0
Packit Service 99d1c0
    retval = krad_attrset_new(set->ctx, &tmp);
Packit Service 99d1c0
    if (retval != 0)
Packit Service 99d1c0
        return retval;
Packit Service 99d1c0
Packit Service 99d1c0
    K5_TAILQ_FOREACH(a, &set->list, list) {
Packit Service 99d1c0
        retval = krad_attrset_add(tmp, a->type, &a->attr);
Packit Service 99d1c0
        if (retval != 0) {
Packit Service 99d1c0
            krad_attrset_free(tmp);
Packit Service 99d1c0
            return retval;
Packit Service 99d1c0
        }
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    *copy = tmp;
Packit Service 99d1c0
    return 0;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
kr_attrset_encode(const krad_attrset *set, const char *secret,
Packit Service 99d1c0
                  const unsigned char *auth,
rpm-build 490d66
                  unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen,
rpm-build 490d66
                  krb5_boolean *is_fips)
Packit Service 99d1c0
{
Packit Service 99d1c0
    unsigned char buffer[MAX_ATTRSIZE];
Packit Service 99d1c0
    krb5_error_code retval;
Packit Service 99d1c0
    size_t i = 0, attrlen;
Packit Service 99d1c0
    attr *a;
Packit Service 99d1c0
Packit Service 99d1c0
    if (set == NULL) {
Packit Service 99d1c0
        *outlen = 0;
Packit Service 99d1c0
        return 0;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    K5_TAILQ_FOREACH(a, &set->list, list) {
Packit Service 99d1c0
        retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
rpm-build 490d66
                                buffer, &attrlen, is_fips);
Packit Service 99d1c0
        if (retval != 0)
Packit Service 99d1c0
            return retval;
Packit Service 99d1c0
Packit Service 99d1c0
        if (i + attrlen + 2 > MAX_ATTRSETSIZE)
Packit Service 99d1c0
            return EMSGSIZE;
Packit Service 99d1c0
Packit Service 99d1c0
        outbuf[i++] = a->type;
Packit Service 99d1c0
        outbuf[i++] = attrlen + 2;
Packit Service 99d1c0
        memcpy(&outbuf[i], buffer, attrlen);
Packit Service 99d1c0
        i += attrlen;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    *outlen = i;
Packit Service 99d1c0
    return 0;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret,
Packit Service 99d1c0
                  const unsigned char *auth, krad_attrset **set_out)
Packit Service 99d1c0
{
Packit Service 99d1c0
    unsigned char buffer[MAX_ATTRSIZE];
Packit Service 99d1c0
    krb5_data tmp;
Packit Service 99d1c0
    krb5_error_code retval;
Packit Service 99d1c0
    krad_attr type;
Packit Service 99d1c0
    krad_attrset *set;
Packit Service 99d1c0
    size_t i, len;
Packit Service 99d1c0
Packit Service 99d1c0
    *set_out = NULL;
Packit Service 99d1c0
Packit Service 99d1c0
    retval = krad_attrset_new(ctx, &set);
Packit Service 99d1c0
    if (retval != 0)
Packit Service 99d1c0
        return retval;
Packit Service 99d1c0
Packit Service 99d1c0
    for (i = 0; i + 2 < in->length; ) {
Packit Service 99d1c0
        type = in->data[i++];
Packit Service 99d1c0
        tmp = make_data(&in->data[i + 1], in->data[i] - 2);
Packit Service 99d1c0
        i += tmp.length + 1;
Packit Service 99d1c0
Packit Service 99d1c0
        retval = (in->length < i) ? EBADMSG : 0;
Packit Service 99d1c0
        if (retval != 0)
Packit Service 99d1c0
            goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
        retval = kr_attr_decode(ctx, secret, auth, type, &tmp, buffer, &len;;
Packit Service 99d1c0
        if (retval != 0)
Packit Service 99d1c0
            goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
        tmp = make_data(buffer, len);
Packit Service 99d1c0
        retval = krad_attrset_add(set, type, &tmp);
Packit Service 99d1c0
        if (retval != 0)
Packit Service 99d1c0
            goto cleanup;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    *set_out = set;
Packit Service 99d1c0
    set = NULL;
Packit Service 99d1c0
Packit Service 99d1c0
cleanup:
Packit Service 99d1c0
    zap(buffer, sizeof(buffer));
Packit Service 99d1c0
    krad_attrset_free(set);
Packit Service 99d1c0
    return retval;
Packit Service 99d1c0
}