Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 01 May 2026 00:11:37 +0000
From:      Cy Schubert <cy@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 736e411a737b - main - krb5: import MIT 1.22.2
Message-ID:  <69f3efb9.308ec.599addf5@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by cy:

URL: https://cgit.FreeBSD.org/src/commit/?id=736e411a737b9f57c1303e6d15c5afd4f63af0d3

commit 736e411a737b9f57c1303e6d15c5afd4f63af0d3
Merge: 6a0610cb5018 90c687295e2d
Author:     Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2026-04-30 19:24:20 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2026-05-01 00:10:53 +0000

    krb5: import MIT 1.22.2
    
    Merge commit '90c687295e2d62f9411fc5b571f5af4e8ee187a7'

 crypto/krb5/NOTICE                              |  2 +-
 crypto/krb5/README                              | 24 +++++++++++++++-
 crypto/krb5/src/configure                       | 20 ++++++-------
 crypto/krb5/src/lib/gssapi/krb5/acquire_cred.c  |  1 +
 crypto/krb5/src/lib/gssapi/krb5/iakerb.c        |  1 +
 crypto/krb5/src/lib/gssapi/spnego/spnego_mech.c |  2 +-
 crypto/krb5/src/lib/krad/packet.c               |  2 +-
 crypto/krb5/src/lib/krb5/ccache/cc_file.c       |  8 ++++++
 crypto/krb5/src/lib/krb5/ccache/cc_mslsa.c      | 37 ++++++++++---------------
 crypto/krb5/src/man/k5identity.man              |  4 +--
 crypto/krb5/src/man/k5login.man                 |  4 +--
 crypto/krb5/src/man/k5srvutil.man               |  4 +--
 crypto/krb5/src/man/kadm5.acl.man               |  4 +--
 crypto/krb5/src/man/kadmin.man                  |  4 +--
 crypto/krb5/src/man/kadmind.man                 |  4 +--
 crypto/krb5/src/man/kdb5_ldap_util.man          |  4 +--
 crypto/krb5/src/man/kdb5_util.man               |  4 +--
 crypto/krb5/src/man/kdc.conf.man                |  4 +--
 crypto/krb5/src/man/kdestroy.man                |  4 +--
 crypto/krb5/src/man/kerberos.man                |  4 +--
 crypto/krb5/src/man/kinit.man                   |  4 +--
 crypto/krb5/src/man/klist.man                   |  4 +--
 crypto/krb5/src/man/kpasswd.man                 |  4 +--
 crypto/krb5/src/man/kprop.man                   |  4 +--
 crypto/krb5/src/man/kpropd.man                  |  4 +--
 crypto/krb5/src/man/kproplog.man                |  4 +--
 crypto/krb5/src/man/krb5-config.man             |  4 +--
 crypto/krb5/src/man/krb5.conf.man               |  4 +--
 crypto/krb5/src/man/krb5kdc.man                 |  4 +--
 crypto/krb5/src/man/ksu.man                     |  4 +--
 crypto/krb5/src/man/kswitch.man                 |  4 +--
 crypto/krb5/src/man/ktutil.man                  |  4 +--
 crypto/krb5/src/man/kvno.man                    |  4 +--
 crypto/krb5/src/man/sclient.man                 |  4 +--
 crypto/krb5/src/man/sserver.man                 |  4 +--
 crypto/krb5/src/patchlevel.h                    |  6 ++--
 crypto/krb5/src/po/mit-krb5.pot                 |  4 +--
 crypto/krb5/src/prototype/prototype.c           |  2 +-
 crypto/krb5/src/prototype/prototype.h           |  2 +-
 crypto/krb5/src/windows/version.rc              |  2 +-
 40 files changed, 120 insertions(+), 97 deletions(-)

diff --cc crypto/krb5/src/lib/krad/packet.c
index ed19385f71a6,000000000000..22128350428c
mode 100644,000000..100644
--- a/crypto/krb5/src/lib/krad/packet.c
+++ b/crypto/krb5/src/lib/krad/packet.c
@@@ -1,645 -1,0 +1,645 @@@
 +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 +/* lib/krad/packet.c - Packet functions for libkrad */
 +/*
 + * Copyright 2013 Red Hat, Inc.  All rights reserved.
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions are met:
 + *
 + *    1. Redistributions of source code must retain the above copyright
 + *       notice, this list of conditions and the following disclaimer.
 + *
 + *    2. Redistributions in binary form must reproduce the above copyright
 + *       notice, this list of conditions and the following disclaimer in
 + *       the documentation and/or other materials provided with the
 + *       distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#include "internal.h"
 +
 +#include <string.h>
 +
 +#include <arpa/inet.h>
 +
 +typedef unsigned char uchar;
 +
 +/* RFC 2865 */
 +#define MSGAUTH_SIZE (2 + MD5_DIGEST_SIZE)
 +#define OFFSET_CODE 0
 +#define OFFSET_ID 1
 +#define OFFSET_LENGTH 2
 +#define OFFSET_AUTH 4
 +#define OFFSET_ATTR 20
 +#define AUTH_FIELD_SIZE (OFFSET_ATTR - OFFSET_AUTH)
 +
 +#define offset(d, o) (&(d)->data[o])
 +#define pkt_code_get(p) (*(krad_code *)offset(&(p)->pkt, OFFSET_CODE))
 +#define pkt_code_set(p, v) (*(krad_code *)offset(&(p)->pkt, OFFSET_CODE)) = v
 +#define pkt_id_get(p) (*(uchar *)offset(&(p)->pkt, OFFSET_ID))
 +#define pkt_id_set(p, v) (*(uchar *)offset(&(p)->pkt, OFFSET_ID)) = v
 +#define pkt_len_get(p)  load_16_be(offset(&(p)->pkt, OFFSET_LENGTH))
 +#define pkt_len_set(p, v)  store_16_be(v, offset(&(p)->pkt, OFFSET_LENGTH))
 +#define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH))
 +#define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR))
 +
 +struct krad_packet_st {
 +    char buffer[KRAD_PACKET_SIZE_MAX];
 +    krad_attrset *attrset;
 +    krb5_data pkt;
 +};
 +
 +typedef struct {
 +    uchar x[(UCHAR_MAX + 1) / 8];
 +} idmap;
 +
 +/* Ensure the map is empty. */
 +static inline void
 +idmap_init(idmap *map)
 +{
 +    memset(map, 0, sizeof(*map));
 +}
 +
 +/* Set an id as already allocated. */
 +static inline void
 +idmap_set(idmap *map, uchar id)
 +{
 +    map->x[id / 8] |= 1 << (id % 8);
 +}
 +
 +/* Determine whether or not an id is used. */
 +static inline krb5_boolean
 +idmap_isset(const idmap *map, uchar id)
 +{
 +    return (map->x[id / 8] & (1 << (id % 8))) != 0;
 +}
 +
 +/* Find an unused id starting the search at the value specified in id.
 + * NOTE: For optimal security, the initial value of id should be random. */
 +static inline krb5_error_code
 +idmap_find(const idmap *map, uchar *id)
 +{
 +    krb5_int16 i;
 +
 +    for (i = *id; i >= 0 && i <= UCHAR_MAX; (*id % 2 == 0) ? i++ : i--) {
 +        if (!idmap_isset(map, i))
 +            goto success;
 +    }
 +
 +    for (i = *id; i >= 0 && i <= UCHAR_MAX; (*id % 2 == 1) ? i++ : i--) {
 +        if (!idmap_isset(map, i))
 +            goto success;
 +    }
 +
 +    return ERANGE;
 +
 +success:
 +    *id = i;
 +    return 0;
 +}
 +
 +/* Generate size bytes of random data into the buffer. */
 +static inline krb5_error_code
 +randomize(krb5_context ctx, void *buffer, unsigned int size)
 +{
 +    krb5_data rdata = make_data(buffer, size);
 +    return krb5_c_random_make_octets(ctx, &rdata);
 +}
 +
 +/* Generate a radius packet id. */
 +static krb5_error_code
 +id_generate(krb5_context ctx, krad_packet_iter_cb cb, void *data, uchar *id)
 +{
 +    krb5_error_code retval;
 +    const krad_packet *tmp;
 +    idmap used;
 +    uchar i;
 +
 +    retval = randomize(ctx, &i, sizeof(i));
 +    if (retval != 0) {
 +        if (cb != NULL)
 +            (*cb)(data, TRUE);
 +        return retval;
 +    }
 +
 +    if (cb != NULL) {
 +        idmap_init(&used);
 +        for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE))
 +            idmap_set(&used, tmp->pkt.data[1]);
 +
 +        retval = idmap_find(&used, &i);
 +        if (retval != 0)
 +            return retval;
 +    }
 +
 +    *id = i;
 +    return 0;
 +}
 +
 +/* Generate a random authenticator field. */
 +static krb5_error_code
 +auth_generate_random(krb5_context ctx, uchar *rauth)
 +{
 +    krb5_ui_4 trunctime;
 +    time_t currtime;
 +
 +    /* Get the least-significant four bytes of the current time. */
 +    currtime = time(NULL);
 +    if (currtime == (time_t)-1)
 +        return errno;
 +    trunctime = (krb5_ui_4)currtime;
 +    memcpy(rauth, &trunctime, sizeof(trunctime));
 +
 +    /* Randomize the rest of the buffer. */
 +    return randomize(ctx, rauth + sizeof(trunctime),
 +                     AUTH_FIELD_SIZE - sizeof(trunctime));
 +}
 +
 +/* Generate a response authenticator field. */
 +static krb5_error_code
 +auth_generate_response(krb5_context ctx, const char *secret,
 +                       const krad_packet *response, const uchar *auth,
 +                       uchar *rauth)
 +{
 +    krb5_error_code retval;
 +    krb5_checksum hash;
 +    krb5_data data;
 +
 +    /* Allocate the temporary buffer. */
 +    retval = alloc_data(&data, response->pkt.length + strlen(secret));
 +    if (retval != 0)
 +        return retval;
 +
 +    /* Encoded RADIUS packet with the request's
 +     * authenticator and the secret at the end. */
 +    memcpy(data.data, response->pkt.data, response->pkt.length);
 +    memcpy(data.data + OFFSET_AUTH, auth, AUTH_FIELD_SIZE);
 +    memcpy(data.data + response->pkt.length, secret, strlen(secret));
 +
 +    /* Hash it. */
 +    retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data,
 +                                  &hash);
 +    free(data.data);
 +    if (retval != 0)
 +        return retval;
 +
 +    memcpy(rauth, hash.contents, AUTH_FIELD_SIZE);
 +    krb5_free_checksum_contents(ctx, &hash);
 +    return 0;
 +}
 +
 +/* Create a new packet. */
 +static krad_packet *
 +packet_new(void)
 +{
 +    krad_packet *pkt;
 +
 +    pkt = calloc(1, sizeof(krad_packet));
 +    if (pkt == NULL)
 +        return NULL;
 +    pkt->pkt = make_data(pkt->buffer, sizeof(pkt->buffer));
 +
 +    return pkt;
 +}
 +
 +/* Set the attrset object by decoding the packet. */
 +static krb5_error_code
 +packet_set_attrset(krb5_context ctx, const char *secret, krad_packet *pkt)
 +{
 +    krb5_data tmp;
 +
 +    tmp = make_data(pkt_attr(pkt), pkt->pkt.length - OFFSET_ATTR);
 +    return kr_attrset_decode(ctx, &tmp, secret, pkt_auth(pkt), &pkt->attrset);
 +}
 +
 +/* Determine if a packet requires a Message-Authenticator attribute. */
 +static inline krb5_boolean
 +requires_msgauth(const char *secret, krad_code code)
 +{
 +    /* If no secret is provided, assume that the transport is a UNIX socket.
 +     * Message-Authenticator is required only on UDP and TCP connections. */
 +    if (*secret == '\0')
 +        return FALSE;
 +
 +    /*
 +     * Per draft-ietf-radext-deprecating-radius-03 sections 5.2.1 and 5.2.4,
 +     * Message-Authenticator is required in Access-Request packets and all
 +     * potential responses when UDP or TCP transport is used.
 +     */
 +    return code == KRAD_CODE_ACCESS_REQUEST ||
 +        code == KRAD_CODE_ACCESS_ACCEPT || code == KRAD_CODE_ACCESS_REJECT ||
 +        code == KRAD_CODE_ACCESS_CHALLENGE;
 +}
 +
 +/* Check if the packet has a Message-Authenticator attribute. */
 +static inline krb5_boolean
 +has_pkt_msgauth(const krad_packet *pkt)
 +{
 +    return krad_attrset_get(pkt->attrset, KRAD_ATTR_MESSAGE_AUTHENTICATOR,
 +                            0) != NULL;
 +}
 +
 +/* Return the beginning of the Message-Authenticator attribute in pkt, or NULL
 + * if no such attribute is present. */
 +static const uint8_t *
 +lookup_msgauth_addr(const krad_packet *pkt)
 +{
 +    size_t i;
 +    uint8_t *p;
 +
 +    i = OFFSET_ATTR;
 +    while (i + 2 < pkt->pkt.length) {
 +        p = (uint8_t *)offset(&pkt->pkt, i);
 +        if (*p == KRAD_ATTR_MESSAGE_AUTHENTICATOR)
 +            return p;
 +        i += p[1];
 +    }
 +
 +    return NULL;
 +}
 +
 +/*
 + * Calculate the message authenticator MAC for pkt as specified in RFC 2869
 + * section 5.14, placing the result in mac_out.  Use the provided authenticator
 + * auth, which may be from pkt or from a corresponding request.
 + */
 +static krb5_error_code
 +calculate_mac(const char *secret, const krad_packet *pkt,
 +              const uint8_t auth[AUTH_FIELD_SIZE],
 +              uint8_t mac_out[MD5_DIGEST_SIZE])
 +{
 +    const uint8_t *msgauth_attr, *msgauth_end, *pkt_end;
 +    krb5_crypto_iov input[5];
 +    krb5_data ksecr, mac;
 +    static const uint8_t zeroed_msgauth[MSGAUTH_SIZE] = {
 +        KRAD_ATTR_MESSAGE_AUTHENTICATOR, MSGAUTH_SIZE
 +    };
 +
 +    msgauth_attr = lookup_msgauth_addr(pkt);
 +    if (msgauth_attr == NULL)
 +        return EINVAL;
 +    msgauth_end = msgauth_attr + MSGAUTH_SIZE;
 +    pkt_end = (const uint8_t *)pkt->pkt.data + pkt->pkt.length;
 +
 +    /* Read code, id, and length from the packet. */
 +    input[0].flags = KRB5_CRYPTO_TYPE_DATA;
 +    input[0].data = make_data(pkt->pkt.data, OFFSET_AUTH);
 +
 +    /* Read the provided authenticator. */
 +    input[1].flags = KRB5_CRYPTO_TYPE_DATA;
 +    input[1].data = make_data((uint8_t *)auth, AUTH_FIELD_SIZE);
 +
 +    /* Read any attributes before Message-Authenticator. */
 +    input[2].flags = KRB5_CRYPTO_TYPE_DATA;
 +    input[2].data = make_data(pkt_attr(pkt), msgauth_attr - pkt_attr(pkt));
 +
 +    /* Read Message-Authenticator with the data bytes all set to zero, per RFC
 +     * 2869 section 5.14. */
 +    input[3].flags = KRB5_CRYPTO_TYPE_DATA;
 +    input[3].data = make_data((uint8_t *)zeroed_msgauth, MSGAUTH_SIZE);
 +
 +    /* Read any attributes after Message-Authenticator. */
 +    input[4].flags = KRB5_CRYPTO_TYPE_DATA;
 +    input[4].data = make_data((uint8_t *)msgauth_end, pkt_end - msgauth_end);
 +
 +    mac = make_data(mac_out, MD5_DIGEST_SIZE);
 +    ksecr = string2data((char *)secret);
 +    return k5_hmac_md5(&ksecr, input, 5, &mac);
 +}
 +
 +ssize_t
 +krad_packet_bytes_needed(const krb5_data *buffer)
 +{
 +    size_t len;
 +
 +    if (buffer->length < OFFSET_AUTH)
 +        return OFFSET_AUTH - buffer->length;
 +
 +    len = load_16_be(offset(buffer, OFFSET_LENGTH));
 +    if (len > KRAD_PACKET_SIZE_MAX)
 +        return -1;
 +
 +    return (buffer->length > len) ? 0 : len - buffer->length;
 +}
 +
 +void
 +krad_packet_free(krad_packet *pkt)
 +{
 +    if (pkt)
 +        krad_attrset_free(pkt->attrset);
 +    free(pkt);
 +}
 +
 +/* Create a new request packet. */
 +krb5_error_code
 +krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
 +                        const krad_attrset *set, krad_packet_iter_cb cb,
 +                        void *data, krad_packet **request)
 +{
 +    krb5_error_code retval;
 +    krad_packet *pkt;
 +    uchar id;
 +    size_t attrset_len;
 +    krb5_boolean msgauth_required;
 +
 +    pkt = packet_new();
 +    if (pkt == NULL) {
 +        if (cb != NULL)
 +            (*cb)(data, TRUE);
 +        return ENOMEM;
 +    }
 +
 +    /* Generate the ID. */
 +    retval = id_generate(ctx, cb, data, &id);
 +    if (retval != 0)
 +        goto error;
 +    pkt_id_set(pkt, id);
 +
 +    /* Generate the authenticator. */
 +    retval = auth_generate_random(ctx, pkt_auth(pkt));
 +    if (retval != 0)
 +        goto error;
 +
 +    /* Determine if Message-Authenticator is required. */
 +    msgauth_required = (*secret != '\0' && code == KRAD_CODE_ACCESS_REQUEST);
 +
 +    /* Encode the attributes. */
 +    retval = kr_attrset_encode(set, secret, pkt_auth(pkt), msgauth_required,
 +                               pkt_attr(pkt), &attrset_len);
 +    if (retval != 0)
 +        goto error;
 +
 +    /* Set the code, ID and length. */
 +    pkt->pkt.length = attrset_len + OFFSET_ATTR;
 +    pkt_code_set(pkt, code);
 +    pkt_len_set(pkt, pkt->pkt.length);
 +
 +    if (msgauth_required) {
 +        /* Calculate and set the Message-Authenticator MAC. */
 +        retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
 +        if (retval != 0)
 +            goto error;
 +    }
 +
 +    /* Copy the attrset for future use. */
 +    retval = packet_set_attrset(ctx, secret, pkt);
 +    if (retval != 0)
 +        goto error;
 +
 +    *request = pkt;
 +    return 0;
 +
 +error:
 +    free(pkt);
 +    return retval;
 +}
 +
 +/* Create a new request packet. */
 +krb5_error_code
 +krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
 +                         const krad_attrset *set, const krad_packet *request,
 +                         krad_packet **response)
 +{
 +    krb5_error_code retval;
 +    krad_packet *pkt;
 +    size_t attrset_len;
 +    krb5_boolean msgauth_required;
 +
 +    pkt = packet_new();
 +    if (pkt == NULL)
 +        return ENOMEM;
 +
 +    /* Determine if Message-Authenticator is required. */
 +    msgauth_required = requires_msgauth(secret, code);
 +
 +    /* Encode the attributes. */
 +    retval = kr_attrset_encode(set, secret, pkt_auth(request),
 +                               msgauth_required, pkt_attr(pkt), &attrset_len);
 +    if (retval != 0)
 +        goto error;
 +
 +    /* Set the code, ID and length. */
 +    pkt->pkt.length = attrset_len + OFFSET_ATTR;
 +    pkt_code_set(pkt, code);
 +    pkt_id_set(pkt, pkt_id_get(request));
 +    pkt_len_set(pkt, pkt->pkt.length);
 +
 +    /* Generate the authenticator. */
 +    retval = auth_generate_response(ctx, secret, pkt, pkt_auth(request),
 +                                    pkt_auth(pkt));
 +    if (retval != 0)
 +        goto error;
 +
 +    if (msgauth_required) {
 +        /*
 +         * Calculate and replace the Message-Authenticator MAC.  Per RFC 2869
 +         * section 5.14, use the authenticator from the request, not from the
 +         * response.
 +         */
 +        retval = calculate_mac(secret, pkt, pkt_auth(request),
 +                               pkt_attr(pkt) + 2);
 +        if (retval != 0)
 +            goto error;
 +    }
 +
 +    /* Copy the attrset for future use. */
 +    retval = packet_set_attrset(ctx, secret, pkt);
 +    if (retval != 0)
 +        goto error;
 +
 +    *response = pkt;
 +    return 0;
 +
 +error:
 +    free(pkt);
 +    return retval;
 +}
 +
 +/* Verify the Message-Authenticator value in pkt, using the provided
 + * authenticator (which may be from pkt or from a corresponding request). */
 +static krb5_error_code
 +verify_msgauth(const char *secret, const krad_packet *pkt,
 +               const uint8_t auth[AUTH_FIELD_SIZE])
 +{
 +    uint8_t mac[MD5_DIGEST_SIZE];
 +    const krb5_data *msgauth;
 +    krb5_error_code retval;
 +
 +    msgauth = krad_packet_get_attr(pkt, KRAD_ATTR_MESSAGE_AUTHENTICATOR, 0);
 +/* XXX ENODATA does not exist in FreeBSD. The closest thing we have to */
 +/* XXX ENODATA is ENOATTR. We use that instead. */
 +#define ENODATA ENOATTR
 +    if (msgauth == NULL)
 +        return ENODATA;
 +
 +    retval = calculate_mac(secret, pkt, auth, mac);
 +    if (retval)
 +        return retval;
 +
 +    if (msgauth->length != MD5_DIGEST_SIZE)
 +        return EMSGSIZE;
 +
 +    if (k5_bcmp(mac, msgauth->data, MD5_DIGEST_SIZE) != 0)
 +        return EBADMSG;
 +
 +    return 0;
 +}
 +
 +/* Decode a packet. */
 +static krb5_error_code
 +decode_packet(krb5_context ctx, const char *secret, const krb5_data *buffer,
 +              krad_packet **pkt)
 +{
 +    krb5_error_code retval;
 +    krad_packet *tmp;
 +    krb5_ui_2 len;
 +
 +    tmp = packet_new();
 +    if (tmp == NULL) {
 +        retval = ENOMEM;
 +        goto error;
 +    }
 +
 +    /* Ensure a proper message length. */
 +    retval = (buffer->length < OFFSET_ATTR) ? EMSGSIZE : 0;
 +    if (retval != 0)
 +        goto error;
 +    len = load_16_be(offset(buffer, OFFSET_LENGTH));
 +    retval = (len < OFFSET_ATTR) ? EBADMSG : 0;
 +    if (retval != 0)
 +        goto error;
 +    retval = (len > buffer->length || len > tmp->pkt.length) ? EBADMSG : 0;
 +    if (retval != 0)
 +        goto error;
 +
 +    /* Copy over the buffer. */
 +    tmp->pkt.length = len;
 +    memcpy(tmp->pkt.data, buffer->data, len);
 +
 +    /* Parse the packet to ensure it is well-formed. */
 +    retval = packet_set_attrset(ctx, secret, tmp);
 +    if (retval != 0)
 +        goto error;
 +
 +    *pkt = tmp;
 +    return 0;
 +
 +error:
 +    krad_packet_free(tmp);
 +    return retval;
 +}
 +
 +krb5_error_code
 +krad_packet_decode_request(krb5_context ctx, const char *secret,
 +                           const krb5_data *buffer, krad_packet_iter_cb cb,
 +                           void *data, const krad_packet **duppkt,
 +                           krad_packet **reqpkt)
 +{
 +    const krad_packet *tmp = NULL;
 +    krad_packet *req;
 +    krb5_error_code retval;
 +
 +    retval = decode_packet(ctx, secret, buffer, &req);
 +    if (retval)
 +        return retval;
 +
 +    /* Verify Message-Authenticator if present. */
 +    if (has_pkt_msgauth(req)) {
 +        retval = verify_msgauth(secret, req, pkt_auth(req));
 +        if (retval) {
 +            krad_packet_free(req);
 +            return retval;
 +        }
 +    }
 +
 +    if (cb != NULL) {
 +        for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) {
-             if (pkt_id_get(*reqpkt) == pkt_id_get(tmp))
++            if (pkt_id_get(req) == pkt_id_get(tmp))
 +                break;
 +        }
 +
 +        if (tmp != NULL)
 +            (*cb)(data, TRUE);
 +    }
 +
 +    *reqpkt = req;
 +    *duppkt = tmp;
 +    return 0;
 +}
 +
 +krb5_error_code
 +krad_packet_decode_response(krb5_context ctx, const char *secret,
 +                            const krb5_data *buffer, krad_packet_iter_cb cb,
 +                            void *data, const krad_packet **reqpkt,
 +                            krad_packet **rsppkt)
 +{
 +    uchar auth[AUTH_FIELD_SIZE];
 +    const krad_packet *tmp = NULL;
 +    krb5_error_code retval;
 +
 +    retval = decode_packet(ctx, secret, buffer, rsppkt);
 +    if (cb != NULL && retval == 0) {
 +        for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) {
 +            if (pkt_id_get(*rsppkt) != pkt_id_get(tmp))
 +                continue;
 +
 +            /* Response */
 +            retval = auth_generate_response(ctx, secret, *rsppkt,
 +                                            pkt_auth(tmp), auth);
 +            if (retval != 0) {
 +                krad_packet_free(*rsppkt);
 +                break;
 +            }
 +
 +            /* Verify the response authenticator. */
 +            if (k5_bcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) != 0)
 +                continue;
 +
 +            /* Verify Message-Authenticator if present. */
 +            if (has_pkt_msgauth(*rsppkt)) {
 +                if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
 +                    continue;
 +            }
 +
 +            break;
 +        }
 +    }
 +
 +    if (cb != NULL && (retval != 0 || tmp != NULL))
 +        (*cb)(data, TRUE);
 +
 +    *reqpkt = tmp;
 +    return retval;
 +}
 +
 +const krb5_data *
 +krad_packet_encode(const krad_packet *pkt)
 +{
 +    return &pkt->pkt;
 +}
 +
 +krad_code
 +krad_packet_get_code(const krad_packet *pkt)
 +{
 +    if (pkt == NULL)
 +        return 0;
 +
 +    return pkt_code_get(pkt);
 +}
 +
 +const krb5_data *
 +krad_packet_get_attr(const krad_packet *pkt, krad_attr type, size_t indx)
 +{
 +    return krad_attrset_get(pkt->attrset, type, indx);
 +}


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f3efb9.308ec.599addf5>