1189251Ssam/* 2214734Srpaulo * RADIUS message processing 3337817Scy * Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#ifndef RADIUS_H 10189251Ssam#define RADIUS_H 11189251Ssam 12189251Ssam/* RFC 2865 - RADIUS */ 13189251Ssam 14189251Ssam#ifdef _MSC_VER 15189251Ssam#pragma pack(push, 1) 16189251Ssam#endif /* _MSC_VER */ 17189251Ssam 18189251Ssamstruct radius_hdr { 19189251Ssam u8 code; 20189251Ssam u8 identifier; 21252726Srpaulo be16 length; /* including this header */ 22189251Ssam u8 authenticator[16]; 23189251Ssam /* followed by length-20 octets of attributes */ 24189251Ssam} STRUCT_PACKED; 25189251Ssam 26189251Ssamenum { RADIUS_CODE_ACCESS_REQUEST = 1, 27189251Ssam RADIUS_CODE_ACCESS_ACCEPT = 2, 28189251Ssam RADIUS_CODE_ACCESS_REJECT = 3, 29189251Ssam RADIUS_CODE_ACCOUNTING_REQUEST = 4, 30189251Ssam RADIUS_CODE_ACCOUNTING_RESPONSE = 5, 31189251Ssam RADIUS_CODE_ACCESS_CHALLENGE = 11, 32189251Ssam RADIUS_CODE_STATUS_SERVER = 12, 33189251Ssam RADIUS_CODE_STATUS_CLIENT = 13, 34252726Srpaulo RADIUS_CODE_DISCONNECT_REQUEST = 40, 35252726Srpaulo RADIUS_CODE_DISCONNECT_ACK = 41, 36252726Srpaulo RADIUS_CODE_DISCONNECT_NAK = 42, 37252726Srpaulo RADIUS_CODE_COA_REQUEST = 43, 38252726Srpaulo RADIUS_CODE_COA_ACK = 44, 39252726Srpaulo RADIUS_CODE_COA_NAK = 45, 40189251Ssam RADIUS_CODE_RESERVED = 255 41189251Ssam}; 42189251Ssam 43189251Ssamstruct radius_attr_hdr { 44189251Ssam u8 type; 45189251Ssam u8 length; /* including this header */ 46189251Ssam /* followed by length-2 octets of attribute value */ 47189251Ssam} STRUCT_PACKED; 48189251Ssam 49189251Ssam#define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr)) 50189251Ssam 51189251Ssamenum { RADIUS_ATTR_USER_NAME = 1, 52189251Ssam RADIUS_ATTR_USER_PASSWORD = 2, 53189251Ssam RADIUS_ATTR_NAS_IP_ADDRESS = 4, 54189251Ssam RADIUS_ATTR_NAS_PORT = 5, 55337817Scy RADIUS_ATTR_SERVICE_TYPE = 6, 56337817Scy RADIUS_ATTR_FRAMED_IP_ADDRESS = 8, 57189251Ssam RADIUS_ATTR_FRAMED_MTU = 12, 58189251Ssam RADIUS_ATTR_REPLY_MESSAGE = 18, 59189251Ssam RADIUS_ATTR_STATE = 24, 60189251Ssam RADIUS_ATTR_CLASS = 25, 61189251Ssam RADIUS_ATTR_VENDOR_SPECIFIC = 26, 62189251Ssam RADIUS_ATTR_SESSION_TIMEOUT = 27, 63189251Ssam RADIUS_ATTR_IDLE_TIMEOUT = 28, 64189251Ssam RADIUS_ATTR_TERMINATION_ACTION = 29, 65189251Ssam RADIUS_ATTR_CALLED_STATION_ID = 30, 66189251Ssam RADIUS_ATTR_CALLING_STATION_ID = 31, 67189251Ssam RADIUS_ATTR_NAS_IDENTIFIER = 32, 68189251Ssam RADIUS_ATTR_PROXY_STATE = 33, 69189251Ssam RADIUS_ATTR_ACCT_STATUS_TYPE = 40, 70189251Ssam RADIUS_ATTR_ACCT_DELAY_TIME = 41, 71189251Ssam RADIUS_ATTR_ACCT_INPUT_OCTETS = 42, 72189251Ssam RADIUS_ATTR_ACCT_OUTPUT_OCTETS = 43, 73189251Ssam RADIUS_ATTR_ACCT_SESSION_ID = 44, 74189251Ssam RADIUS_ATTR_ACCT_AUTHENTIC = 45, 75189251Ssam RADIUS_ATTR_ACCT_SESSION_TIME = 46, 76189251Ssam RADIUS_ATTR_ACCT_INPUT_PACKETS = 47, 77189251Ssam RADIUS_ATTR_ACCT_OUTPUT_PACKETS = 48, 78189251Ssam RADIUS_ATTR_ACCT_TERMINATE_CAUSE = 49, 79189251Ssam RADIUS_ATTR_ACCT_MULTI_SESSION_ID = 50, 80189251Ssam RADIUS_ATTR_ACCT_LINK_COUNT = 51, 81189251Ssam RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52, 82189251Ssam RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53, 83189251Ssam RADIUS_ATTR_EVENT_TIMESTAMP = 55, 84337817Scy RADIUS_ATTR_EGRESS_VLANID = 56, 85189251Ssam RADIUS_ATTR_NAS_PORT_TYPE = 61, 86189251Ssam RADIUS_ATTR_TUNNEL_TYPE = 64, 87189251Ssam RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65, 88252726Srpaulo RADIUS_ATTR_TUNNEL_PASSWORD = 69, 89189251Ssam RADIUS_ATTR_CONNECT_INFO = 77, 90189251Ssam RADIUS_ATTR_EAP_MESSAGE = 79, 91189251Ssam RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80, 92189251Ssam RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID = 81, 93189251Ssam RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85, 94189251Ssam RADIUS_ATTR_CHARGEABLE_USER_IDENTITY = 89, 95252726Srpaulo RADIUS_ATTR_NAS_IPV6_ADDRESS = 95, 96281806Srpaulo RADIUS_ATTR_ERROR_CAUSE = 101, 97281806Srpaulo RADIUS_ATTR_EAP_KEY_NAME = 102, 98281806Srpaulo RADIUS_ATTR_OPERATOR_NAME = 126, 99281806Srpaulo RADIUS_ATTR_LOCATION_INFO = 127, 100281806Srpaulo RADIUS_ATTR_LOCATION_DATA = 128, 101281806Srpaulo RADIUS_ATTR_BASIC_LOCATION_POLICY_RULES = 129, 102281806Srpaulo RADIUS_ATTR_EXTENDED_LOCATION_POLICY_RULES = 130, 103281806Srpaulo RADIUS_ATTR_LOCATION_CAPABLE = 131, 104281806Srpaulo RADIUS_ATTR_REQUESTED_LOCATION_INFO = 132, 105346981Scy RADIUS_ATTR_GSS_ACCEPTOR_SERVICE_NAME = 164, 106346981Scy RADIUS_ATTR_GSS_ACCEPTOR_HOST_NAME = 165, 107346981Scy RADIUS_ATTR_GSS_ACCEPTOR_SERVICE_SPECIFICS = 166, 108346981Scy RADIUS_ATTR_GSS_ACCEPTOR_REALM_NAME = 167, 109281806Srpaulo RADIUS_ATTR_MOBILITY_DOMAIN_ID = 177, 110281806Srpaulo RADIUS_ATTR_WLAN_HESSID = 181, 111346981Scy RADIUS_ATTR_WLAN_REASON_CODE = 185, 112281806Srpaulo RADIUS_ATTR_WLAN_PAIRWISE_CIPHER = 186, 113281806Srpaulo RADIUS_ATTR_WLAN_GROUP_CIPHER = 187, 114281806Srpaulo RADIUS_ATTR_WLAN_AKM_SUITE = 188, 115281806Srpaulo RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER = 189, 116189251Ssam}; 117189251Ssam 118189251Ssam 119337817Scy/* Service-Type values (RFC 2865, 5.6) */ 120337817Scy#define RADIUS_SERVICE_TYPE_FRAMED 2 121337817Scy 122189251Ssam/* Termination-Action */ 123189251Ssam#define RADIUS_TERMINATION_ACTION_DEFAULT 0 124189251Ssam#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1 125189251Ssam 126189251Ssam/* NAS-Port-Type */ 127189251Ssam#define RADIUS_NAS_PORT_TYPE_IEEE_802_11 19 128189251Ssam 129189251Ssam/* Acct-Status-Type */ 130189251Ssam#define RADIUS_ACCT_STATUS_TYPE_START 1 131189251Ssam#define RADIUS_ACCT_STATUS_TYPE_STOP 2 132189251Ssam#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3 133189251Ssam#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON 7 134189251Ssam#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF 8 135189251Ssam 136189251Ssam/* Acct-Authentic */ 137189251Ssam#define RADIUS_ACCT_AUTHENTIC_RADIUS 1 138189251Ssam#define RADIUS_ACCT_AUTHENTIC_LOCAL 2 139189251Ssam#define RADIUS_ACCT_AUTHENTIC_REMOTE 3 140189251Ssam 141189251Ssam/* Acct-Terminate-Cause */ 142189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST 1 143189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_CARRIER 2 144189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_SERVICE 3 145189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT 4 146189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT 5 147189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET 6 148189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT 7 149189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_ERROR 8 150189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_ERROR 9 151189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REQUEST 10 152189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT 11 153189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_UNNEEDED 12 154189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_PREEMPTED 13 155189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_SUSPENDED 14 156189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE 15 157189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_CALLBACK 16 158189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_USER_ERROR 17 159189251Ssam#define RADIUS_ACCT_TERMINATE_CAUSE_HOST_REQUEST 18 160189251Ssam 161189251Ssam#define RADIUS_TUNNEL_TAGS 32 162189251Ssam 163189251Ssam/* Tunnel-Type */ 164189251Ssam#define RADIUS_TUNNEL_TYPE_PPTP 1 165189251Ssam#define RADIUS_TUNNEL_TYPE_L2TP 3 166189251Ssam#define RADIUS_TUNNEL_TYPE_IPIP 7 167189251Ssam#define RADIUS_TUNNEL_TYPE_GRE 10 168189251Ssam#define RADIUS_TUNNEL_TYPE_VLAN 13 169189251Ssam 170189251Ssam/* Tunnel-Medium-Type */ 171189251Ssam#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV4 1 172189251Ssam#define RADIUS_TUNNEL_MEDIUM_TYPE_IPV6 2 173189251Ssam#define RADIUS_TUNNEL_MEDIUM_TYPE_802 6 174189251Ssam 175189251Ssam 176189251Ssamstruct radius_attr_vendor { 177189251Ssam u8 vendor_type; 178189251Ssam u8 vendor_length; 179189251Ssam} STRUCT_PACKED; 180189251Ssam 181189251Ssam#define RADIUS_VENDOR_ID_CISCO 9 182189251Ssam#define RADIUS_CISCO_AV_PAIR 1 183189251Ssam 184189251Ssam/* RFC 2548 - Microsoft Vendor-specific RADIUS Attributes */ 185189251Ssam#define RADIUS_VENDOR_ID_MICROSOFT 311 186189251Ssam 187189251Ssamenum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16, 188189251Ssam RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17 189189251Ssam}; 190189251Ssam 191281806Srpaulo 192281806Srpaulo/* Hotspot 2.0 - WFA Vendor-specific RADIUS Attributes */ 193281806Srpaulo#define RADIUS_VENDOR_ID_WFA 40808 194281806Srpaulo 195281806Srpauloenum { 196281806Srpaulo RADIUS_VENDOR_ATTR_WFA_HS20_SUBSCR_REMEDIATION = 1, 197281806Srpaulo RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION = 2, 198281806Srpaulo RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION = 3, 199281806Srpaulo RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ = 4, 200281806Srpaulo RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL = 5, 201346981Scy RADIUS_VENDOR_ATTR_WFA_HS20_ROAMING_CONSORTIUM = 6, 202346981Scy RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME = 7, 203346981Scy RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP = 8, 204346981Scy RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING = 9, 205346981Scy RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10, 206281806Srpaulo}; 207281806Srpaulo 208189251Ssam#ifdef _MSC_VER 209189251Ssam#pragma pack(pop) 210189251Ssam#endif /* _MSC_VER */ 211189251Ssam 212189251Ssamstruct radius_ms_mppe_keys { 213189251Ssam u8 *send; 214189251Ssam size_t send_len; 215189251Ssam u8 *recv; 216189251Ssam size_t recv_len; 217189251Ssam}; 218189251Ssam 219189251Ssam 220214734Srpaulostruct radius_msg; 221189251Ssam 222189251Ssam/* Default size to be allocated for new RADIUS messages */ 223189251Ssam#define RADIUS_DEFAULT_MSG_SIZE 1024 224189251Ssam 225189251Ssam/* Default size to be allocated for attribute array */ 226189251Ssam#define RADIUS_DEFAULT_ATTR_COUNT 16 227189251Ssam 228189251Ssam 229189251Ssam/* MAC address ASCII format for IEEE 802.1X use 230189251Ssam * (draft-congdon-radius-8021x-20.txt) */ 231189251Ssam#define RADIUS_802_1X_ADDR_FORMAT "%02X-%02X-%02X-%02X-%02X-%02X" 232189251Ssam/* MAC address ASCII format for non-802.1X use */ 233189251Ssam#define RADIUS_ADDR_FORMAT "%02x%02x%02x%02x%02x%02x" 234189251Ssam 235214734Srpaulostruct radius_hdr * radius_msg_get_hdr(struct radius_msg *msg); 236214734Srpaulostruct wpabuf * radius_msg_get_buf(struct radius_msg *msg); 237214734Srpaulostruct radius_msg * radius_msg_new(u8 code, u8 identifier); 238189251Ssamvoid radius_msg_free(struct radius_msg *msg); 239189251Ssamvoid radius_msg_dump(struct radius_msg *msg); 240189251Ssamint radius_msg_finish(struct radius_msg *msg, const u8 *secret, 241189251Ssam size_t secret_len); 242189251Ssamint radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, 243189251Ssam size_t secret_len, const u8 *req_authenticator); 244252726Srpauloint radius_msg_finish_das_resp(struct radius_msg *msg, const u8 *secret, 245252726Srpaulo size_t secret_len, 246252726Srpaulo const struct radius_hdr *req_hdr); 247189251Ssamvoid radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret, 248189251Ssam size_t secret_len); 249281806Srpaulovoid radius_msg_finish_acct_resp(struct radius_msg *msg, const u8 *secret, 250281806Srpaulo size_t secret_len, 251281806Srpaulo const u8 *req_authenticator); 252252726Srpauloint radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret, 253252726Srpaulo size_t secret_len); 254252726Srpauloint radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret, 255337817Scy size_t secret_len, 256337817Scy int require_message_authenticator); 257214734Srpaulostruct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type, 258214734Srpaulo const u8 *data, size_t data_len); 259214734Srpaulostruct radius_msg * radius_msg_parse(const u8 *data, size_t len); 260189251Ssamint radius_msg_add_eap(struct radius_msg *msg, const u8 *data, 261189251Ssam size_t data_len); 262252726Srpaulostruct wpabuf * radius_msg_get_eap(struct radius_msg *msg); 263189251Ssamint radius_msg_verify(struct radius_msg *msg, const u8 *secret, 264189251Ssam size_t secret_len, struct radius_msg *sent_msg, 265189251Ssam int auth); 266189251Ssamint radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, 267189251Ssam size_t secret_len, const u8 *req_auth); 268189251Ssamint radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, 269189251Ssam u8 type); 270337817Scyint radius_msg_make_authenticator(struct radius_msg *msg); 271189251Ssamstruct radius_ms_mppe_keys * 272189251Ssamradius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, 273189251Ssam const u8 *secret, size_t secret_len); 274189251Ssamstruct radius_ms_mppe_keys * 275189251Ssamradius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, 276189251Ssam const u8 *secret, size_t secret_len); 277189251Ssamint radius_msg_add_mppe_keys(struct radius_msg *msg, 278189251Ssam const u8 *req_authenticator, 279189251Ssam const u8 *secret, size_t secret_len, 280189251Ssam const u8 *send_key, size_t send_key_len, 281189251Ssam const u8 *recv_key, size_t recv_key_len); 282281806Srpauloint radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data, 283281806Srpaulo size_t len); 284281806Srpauloint radius_user_password_hide(struct radius_msg *msg, 285281806Srpaulo const u8 *data, size_t data_len, 286281806Srpaulo const u8 *secret, size_t secret_len, 287281806Srpaulo u8 *buf, size_t buf_len); 288189251Ssamstruct radius_attr_hdr * 289189251Ssamradius_msg_add_attr_user_password(struct radius_msg *msg, 290189251Ssam const u8 *data, size_t data_len, 291189251Ssam const u8 *secret, size_t secret_len); 292189251Ssamint radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); 293337817Scyint radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged, 294337817Scy int *tagged); 295252726Srpaulochar * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, 296252726Srpaulo const u8 *secret, size_t secret_len, 297252726Srpaulo struct radius_msg *sent_msg, size_t n); 298189251Ssam 299189251Ssamstatic inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, 300189251Ssam u32 value) 301189251Ssam{ 302189251Ssam u32 val = htonl(value); 303189251Ssam return radius_msg_add_attr(msg, type, (u8 *) &val, 4) != NULL; 304189251Ssam} 305189251Ssam 306189251Ssamstatic inline int radius_msg_get_attr_int32(struct radius_msg *msg, u8 type, 307189251Ssam u32 *value) 308189251Ssam{ 309189251Ssam u32 val; 310189251Ssam int res; 311189251Ssam res = radius_msg_get_attr(msg, type, (u8 *) &val, 4); 312189251Ssam if (res != 4) 313189251Ssam return -1; 314189251Ssam 315189251Ssam *value = ntohl(val); 316189251Ssam return 0; 317189251Ssam} 318189251Ssamint radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, 319189251Ssam size_t *len, const u8 *start); 320189251Ssamint radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len); 321189251Ssam 322214734Srpaulo 323214734Srpaulostruct radius_attr_data { 324214734Srpaulo u8 *data; 325214734Srpaulo size_t len; 326214734Srpaulo}; 327214734Srpaulo 328214734Srpaulostruct radius_class_data { 329214734Srpaulo struct radius_attr_data *attr; 330214734Srpaulo size_t count; 331214734Srpaulo}; 332214734Srpaulo 333214734Srpaulovoid radius_free_class(struct radius_class_data *c); 334214734Srpauloint radius_copy_class(struct radius_class_data *dst, 335214734Srpaulo const struct radius_class_data *src); 336214734Srpaulo 337252726Srpaulou8 radius_msg_find_unlisted_attr(struct radius_msg *msg, u8 *attrs); 338252726Srpaulo 339337817Scyint radius_gen_session_id(u8 *id, size_t len); 340337817Scy 341189251Ssam#endif /* RADIUS_H */ 342