fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * or http://www.opensolaris.org/os/licensing.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
5df5713f81d69c1a0797f99b13e95e220da00ef9bing zhao - Sun Microsystems - Beijing China * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "iscsi.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/scsi/adapters/iscsi_if.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "radius_packet.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include "radius_protocol.h"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/int_types.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/socket.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/types.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#include <sys/sunddi.h>
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void encode_chap_password(int identifier, int chap_passwd_len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *chap_passwd, uint8_t *result);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See radius_packet.h.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteint
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortesnd_radius_request(void *socket, iscsi_ipaddr_t rsvr_ip_addr,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t rsvr_port, radius_packet_data_t *req_data)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int i; /* Loop counter. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ushort_t total_length; /* Has to be 2 octets in size */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *ptr; /* Pointer to RADIUS packet data */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *length_ptr; /* Points to the Length field of the */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* packet. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *data; /* RADIUS data to be sent */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte radius_attr_t *req_attr; /* Request attributes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte radius_packet_t *packet; /* Outbound RADIUS packet */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte union {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct sockaddr_in s_in4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct sockaddr_in6 s_in6;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } sa_rsvr; /* Socket address of the server */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct nmsghdr msg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct iovec iov[1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Create a RADIUS packet with minimal length for now.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_length = MIN_RAD_PACKET_LEN;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte data = kmem_zalloc(MAX_RAD_PACKET_LEN, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte packet = (radius_packet_t *)data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte packet->code = req_data->code;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte packet->identifier = req_data->identifier;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(req_data->authenticator, packet->authenticator,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RAD_AUTHENTICATOR_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ptr = packet->data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Loop over all attributes of the request. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < req_data->num_of_attrs; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (total_length > MAX_RAD_PACKET_LEN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* The packet has exceed its maximum size. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req_attr = &req_data->attrs[i];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ptr++ = (req_attr->attr_type_code & 0xFF);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte length_ptr = ptr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Length is 2 octets - RFC 2865 section 3 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *ptr++ = 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_length += 2;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* If the attribute is CHAP-Password, encode it. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (req_attr->attr_type_code == RAD_CHAP_PASSWORD) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Identifier plus CHAP response. RFC 2865
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * section 5.3.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t encoded_chap_passwd[RAD_CHAP_PASSWD_STR_LEN +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RAD_IDENTIFIER_LEN + 1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte encode_chap_password
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (req_data->identifier,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req_attr->attr_value_len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req_attr->attr_value,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte encoded_chap_passwd);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req_attr->attr_value_len = RAD_CHAP_PASSWD_STR_LEN +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RAD_IDENTIFIER_LEN;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(encoded_chap_passwd,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req_attr->attr_value,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte req_attr->attr_value_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte len = req_attr->attr_value_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *length_ptr += len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(req_attr->attr_value, ptr, req_attr->attr_value_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ptr += req_attr->attr_value_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_length += len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } /* Done looping over all attributes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte data_len = total_length;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte total_length = htons(total_length);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(&total_length, packet->length, sizeof (ushort_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Send the packet to the RADIUS server.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero((char *)&sa_rsvr, sizeof (sa_rsvr));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rsvr_ip_addr.i_insize == sizeof (in_addr_t)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int recv_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* IPv4 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sa_rsvr.s_in4.sin_family = AF_INET;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sa_rsvr.s_in4.sin_addr.s_addr =
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rsvr_ip_addr.i_addr.in4.s_addr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sa_rsvr.s_in4.sin_port = htons((ushort_t)rsvr_port);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_base = (char *)data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_len = data_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&msg, sizeof (msg));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_name = (struct sockaddr *)&sa_rsvr.s_in4;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_namelen = sizeof (struct sockaddr_in);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iov = iov;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iovlen = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte recv_len = iscsi_net->sendmsg(socket, &msg);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (recv_len == data_len ? 0 : -1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (rsvr_ip_addr.i_insize == sizeof (in6_addr_t)) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* No IPv6 support for now. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Invalid IP address for RADIUS server. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (-1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See radius_packet.h.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteint
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortercv_radius_response(void *socket, uint8_t *shared_secret,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint32_t shared_secret_len, uint8_t *req_authenticator,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte radius_packet_data_t *resp_data)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rcv_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte radius_packet_t *packet;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5_CTX context;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *tmp_data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t md5_digest[16]; /* MD5 Digest Length 16 */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint16_t declared_len = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ushort_t len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct nmsghdr msg;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte struct iovec iov[1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte tmp_data = kmem_zalloc(MAX_RAD_PACKET_LEN, KM_SLEEP);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_base = (char *)tmp_data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte iov[0].iov_len = MAX_RAD_PACKET_LEN;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&msg, sizeof (msg));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_name = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_namelen = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_control = NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_controllen = 0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_flags = MSG_WAITALL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iov = iov;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte msg.msg_iovlen = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rcv_len = iscsi_net->recvmsg(socket, &msg, RAD_RCV_TIMEOUT);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rcv_len == 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_NO_DATA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE1(rcv_rad_resp_summary, int, rcv_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte packet = (radius_packet_t *)tmp_data;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(packet->length, &len, sizeof (ushort_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte declared_len = ntohs(len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte DTRACE_PROBE1(rcv_rad_resp_data, uint16_t, declared_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check if the received packet length is within allowable range.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * RFC 2865 section 3.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rcv_len < MIN_RAD_PACKET_LEN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_PROTOCOL_ERR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (rcv_len > MAX_RAD_PACKET_LEN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_PROTOCOL_ERR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Check if the declared packet length is within allowable range.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * RFC 2865 section 3.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (declared_len < MIN_RAD_PACKET_LEN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_PROTOCOL_ERR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (declared_len > MAX_RAD_PACKET_LEN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_PROTOCOL_ERR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Discard packet with received length shorter than declared
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * length. RFC 2865 section 3.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rcv_len < declared_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_PROTOCOL_ERR);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Authenticate the incoming packet, using the following algorithm
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (RFC 2865 section 3):
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * MD5(Code+ID+Length+RequestAuth+Attributes+Secret)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Code = RADIUS packet code
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ID = RADIUS packet identifier
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Length = Declared length of the packet
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * RequestAuth = The request authenticator
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Attributes = The response attributes
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Secret = The shared secret
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Init(&context);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(&md5_digest, 16);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Update(&context, &packet->code, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Update(&context, &packet->identifier, 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Update(&context, packet->length, 2);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Update(&context, req_authenticator, RAD_AUTHENTICATOR_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Include response attributes only if there is a payload */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (declared_len > RAD_PACKET_HDR_LEN) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Response Attributes */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Update(&context, packet->data,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte declared_len - RAD_PACKET_HDR_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Update(&context, shared_secret, shared_secret_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte MD5Final(md5_digest, &context);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (bcmp(md5_digest, packet->authenticator, RAD_AUTHENTICATOR_LEN)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte != 0) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_AUTH_FAILED);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If the received length is greater than the declared length,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * trust the declared length and shorten the packet (i.e., to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * treat the octets outside the range of the Length field as
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * padding - RFC 2865 section 3).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (rcv_len > declared_len) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Clear the padding data. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bzero(tmp_data + declared_len, rcv_len - declared_len);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rcv_len = declared_len;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Annotate the RADIUS packet data with the data we received from
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the server.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte resp_data->code = packet->code;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte resp_data->identifier = packet->identifier;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte kmem_free(tmp_data, MAX_RAD_PACKET_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return (RAD_RSP_RCVD_SUCCESS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * encode_chap_password -
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Encode a CHAP-Password attribute. This function basically prepends
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * the identifier in front of chap_passwd and copy the results to
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * *result.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteencode_chap_password(int identifier, int chap_passwd_len,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *chap_passwd, uint8_t *result)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte{
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int i;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t *p;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte uint8_t tmp_result[RAD_CHAP_PASSWD_STR_LEN +
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RAD_IDENTIFIER_LEN + 1];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p = tmp_result;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *p = identifier; /* Identifier is 1 octet */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < chap_passwd_len; i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte *p = chap_passwd[i];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte p++;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte }
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte bcopy(tmp_result, result,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RAD_CHAP_PASSWD_STR_LEN + RAD_IDENTIFIER_LEN);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte}