OpenSolaris_b135/cmd/iscsi/iscsitgtd/radius.h

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_RADIUS_H
#define	_RADIUS_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef __cplusplus
extern "C" {
#endif

#include <netinet/in.h>
#include <sys/int_types.h>

/* Packet type. RFC 2865 section 4. */
#define	RAD_ACCESS_REQ		1	/* Authentication Request */
#define	RAD_ACCESS_ACPT		2	/* Authentication Accepted */
#define	RAD_ACCESS_REJ		3	/* Authentication Rejected */

/* RADIUS Attribute Types. RFC 2865 section 5. */
#define	RAD_USER_NAME		1
#define	RAD_CHAP_PASSWORD	3
#define	RAD_CHAP_CHALLENGE	60

/* RFC 2865 Section 3. The Identifier field is one octet. */
#define	RAD_IDENTIFIER_LEN	1

/* RFC 2865 Section 5.3. The String field is 16 octets. */
#define	RAD_CHAP_PASSWD_STR_LEN	16

/* RFC 2865 Section 3. Authenticator field is 16 octets. */
#define	RAD_AUTHENTICATOR_LEN	16

/* RFC 2865 Section 5: 1-253 octets */
#define	MAX_RAD_ATTR_VALUE_LEN	253

/* RFC 2865 Section 3. Minimum length 20 octets. */
#define	MIN_RAD_PACKET_LEN	20

/* RFC 2865 Section 3. Maximum length 4096 octets. */
#define	MAX_RAD_PACKET_LEN	4096

/* Maximum RADIUS shared secret length (in fact there is no defined limit) */
#define	MAX_RAD_SHARED_SECRET_LEN	128

/* RFC 2865 Section 3. Minimum RADIUS shared secret length */
#define	MIN_RAD_SHARED_SECRET_LEN	16

/* Raw RADIUS packet. RFC 2865 section 3. */
typedef struct radius_packet {
	uint8_t	code;		/* RADIUS code, section 3, RFC 2865 */
	uint8_t	identifier;	/* 1 octet in length. RFC 2865 section 3 */
	uint8_t	length[2];	/* 2 octets, or sizeof (u_short) */
	uint8_t	authenticator[RAD_AUTHENTICATOR_LEN];
	uint8_t	data[1];
} radius_packet_t;

/* Length of a RADIUS packet minus the payload */
#define	RAD_PACKET_HDR_LEN		20


typedef enum chap_validation_status_type {
	CHAP_VALIDATION_PASSED,			/* CHAP validation passed */
	CHAP_VALIDATION_INVALID_RESPONSE,	/* Invalid CHAP response */
	CHAP_VALIDATION_DUP_SECRET,		/* Same CHAP secret used */
						/* for authentication in the */
						/* other direction */
	CHAP_VALIDATION_UNKNOWN_AUTH_METHOD,	/* Unknown authentication */
						/*   method */
	CHAP_VALIDATION_INTERNAL_ERROR,		/* MISC internal error */
	CHAP_VALIDATION_RADIUS_ACCESS_ERROR,	/* Problem accessing RADIUS */
	CHAP_VALIDATION_BAD_RADIUS_SECRET,	/* Invalid RADIUS shared */
						/*   secret */
	CHAP_VALIDATION_UNKNOWN_RADIUS_CODE	/* Irrelevant or unknown */
						/*   RADIUS packet code */
						/*   returned */
} chap_validation_status_type;

typedef enum authentication_method_type {
	RADIUS_AUTHENTICATION,
	DIRECT_AUTHENTICATION
} authentication_method_type;

typedef struct  _IPAddress {
	union {
		struct in_addr	in4;
		struct in6_addr	in6;
	} i_addr;
	/* i_insize determines which is valid in the union above */
	int			i_insize;
} iscsi_ipaddr_t;

typedef struct radius_config {
	iscsi_ipaddr_t	rad_svr_addr;	/* IPv6 enabled */
	uint32_t	rad_svr_port;
	uint8_t		rad_svr_shared_secret[MAX_RAD_SHARED_SECRET_LEN];
	uint32_t	rad_svr_shared_secret_len;
} RADIUS_CONFIG;

/* A total of RAD_RCV_TIMEOUT * RAD_RETRY_MAX seconds timeout. */
#define	RAD_RCV_TIMEOUT 5	/* Timeout for receiving RADIUS packet in */
				/*   sec. */
#define	RAD_RETRY_MAX   2	/* Max. # of times to retry receiving */
				/*   packet. */

/* Describes a RADIUS attribute */
typedef struct radius_attr {
	int	attr_type_code; /* RADIUS attribute type code, */
				/*   e.g. RAD_USER_PASSWORD, etc. */
	int	attr_value_len;
	uint8_t	attr_value[MAX_RAD_ATTR_VALUE_LEN];
} radius_attr_t;

/* Describes data fields of a RADIUS packet. */
typedef struct radius_packet_data {
	uint8_t		code;	/* RADIUS code, section 3, RFC 2865. */
	uint8_t		identifier;
	uint8_t		authenticator[RAD_AUTHENTICATOR_LEN];
	int		num_of_attrs;
	radius_attr_t attrs[4]; /* For this implementation each */
				/*   outbound RADIUS packet will only */
				/*   have 3 attributes associated with */
				/*   it thus the chosen size should be */
				/*   good enough. */
} radius_packet_data_t;

/*
 * Data in this structure is set by the user agent and consumed by
 * the driver.
 */
#define	MAX_RAD_SHARED_SECRET_LEN 128
typedef struct radius_props {
	uint32_t		r_vers;
	uint32_t		r_oid;
	union {
		struct in_addr	u_in4;
		struct in6_addr	u_in6;
	} r_addr;
	/*
	 * r_insize indicates which of the previous structs is valid.
	 */
	int			r_insize;

	uint32_t		r_port;
	uint8_t			r_shared_secret[MAX_RAD_SHARED_SECRET_LEN];
	boolean_t		r_radius_access;
	boolean_t		r_radius_config_valid;
	uint32_t		r_shared_secret_len;
} iscsi_radius_props_t;

/*
 * Send a request to a RADIUS server.
 *
 * Returns > 0 on success, <= 0 on failure .
 *
 */
int
snd_radius_request(int sd,
    iscsi_ipaddr_t rsvr_ip_addr,
    uint32_t rsvr_port,
    radius_packet_data_t *packet_data);

#define	RAD_RSP_RCVD_SUCCESS		0
#define	RAD_RSP_RCVD_NO_DATA		1
#define	RAD_RSP_RCVD_TIMEOUT		2
#define	RAD_RSP_RCVD_PROTOCOL_ERR	3
#define	RAD_RSP_RCVD_AUTH_FAILED	4
/*
 * Receives a response from a RADIUS server.
 *
 * Return receive status.
 */
int
rcv_radius_response(int sd,
    uint8_t *shared_secret,
    uint32_t shared_secret_len,
    uint8_t *req_authenticator,
    radius_packet_data_t *resp_data);

/*
 * Function: radius_chap_validate
 *
 * Description: To validate a target response given the
 *              associated challenge via the specified
 *              RADIUS server.
 *
 * Arguments:
 *   target_chap_name - The CHAP name of the target being authenticated.
 *   initiator_chap_name - The CHAP name of the authenticating initiator.
 *   challenge - The CHAP challenge to which the target responded.
 *   target_response - The target's CHAP response to be validated.
 *   identifier - The identifier associated with the CHAP challenge.
 *   radius_server_ip_address - The IP address of the RADIUS server.
 *   radius_server_port - The port number of the RADIUS server.
 *   radius_shared_secret - The shared secret for accessing the RADIUS server.
 *   radius_shared_secret_len - The length of the shared secret.
 *
 * Return: See chap_validation_status_type.
 */
chap_validation_status_type
radius_chap_validate(char *target_chap_name,
		char *initiator_chap_name,
		uint8_t *challenge,
		uint32_t challengeLength,
		uint8_t *target_response,
		uint32_t responseLength,
		uint8_t identifier,
		iscsi_ipaddr_t rad_svr_ip_addr,
		uint32_t rad_svr_port,
		uint8_t *rad_svr_shared_secret,
		uint32_t rad_svr_shared_secret_len);



#ifdef __cplusplus
}
#endif

#endif /* _RADIUS_H */