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