1 |
/* This file is part of GNU RADIUS. |
/* This file is part of GNU Radius. |
2 |
Copyright (C) 2000, Sergey Poznyakoff |
Copyright (C) 2002,2003 Sergey Poznyakoff |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
GNU Radius is free software; you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
7 |
(at your option) any later version. |
(at your option) any later version. |
8 |
|
|
9 |
This program is distributed in the hope that it will be useful, |
GNU Radius is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
GNU General Public License for more details. |
13 |
|
|
14 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
15 |
along with this program; if not, write to the Free Software Foundation, |
along with GNU Radius; if not, write to the Free Software Foundation, |
16 |
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
17 |
|
|
18 |
#define RADIUS_MODULE_RADPDU_C |
#define RADIUS_MODULE_RADPDU_C |
|
#ifndef lint |
|
|
static char rcsid[] = |
|
|
"@(#) $Id$"; |
|
|
#endif |
|
19 |
|
|
20 |
#ifdef HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
21 |
# include <config.h> |
# include <config.h> |
49 |
u_char data[AUTH_STRING_LEN]; |
u_char data[AUTH_STRING_LEN]; |
50 |
}; |
}; |
51 |
|
|
|
static void rad_pdu_init(struct radius_pdu *pdu); |
|
|
static VALUE_PAIR *rad_decode_pair(int attrno, char *ptr, int attrlen); |
|
|
size_t rad_pdu_finish_reply(void **ptr, struct radius_pdu *pdu, int code, |
|
|
int id, u_char *vector, u_char *secret); |
|
|
size_t rad_pdu_finish_request(void **ptr, struct radius_pdu *pdu, |
|
|
int code, int id, u_char *vector, |
|
|
u_char *secret); |
|
|
|
|
52 |
void rad_pdu_destroy(struct radius_pdu *pdu); |
void rad_pdu_destroy(struct radius_pdu *pdu); |
53 |
int rad_attr_write(struct radius_attr *ap, void *data, size_t size); |
int rad_attr_write(struct radius_attr *ap, void *data, size_t size); |
54 |
int rad_encode_pair(struct radius_attr *ap, VALUE_PAIR *pair); |
int rad_encode_pair(struct radius_attr *ap, VALUE_PAIR *pair); |
55 |
|
|
56 |
|
|
57 |
/* Initialize a PDU */ |
/* Initialize a PDU */ |
58 |
void |
static void |
59 |
rad_pdu_init(pdu) |
rad_pdu_init(struct radius_pdu *pdu) |
|
struct radius_pdu *pdu; |
|
60 |
{ |
{ |
61 |
pdu->size = 0; |
pdu->size = 0; |
62 |
obstack_init(&pdu->st); |
obstack_init(&pdu->st); |
70 |
Output: |
Output: |
71 |
*ptr -- Radius reply. |
*ptr -- Radius reply. |
72 |
Return value: length of the data on *ptr. */ |
Return value: length of the data on *ptr. */ |
73 |
size_t |
static size_t |
74 |
rad_pdu_finish(ptr, pdu, code, id, vector, secret) |
rad_pdu_finish(void **ptr, struct radius_pdu *pdu, |
75 |
void **ptr; |
int code, int id, u_char *vector, u_char *secret) |
|
struct radius_pdu *pdu; |
|
|
int code; |
|
|
int id; |
|
|
u_char *vector; |
|
|
u_char *secret; |
|
76 |
{ |
{ |
77 |
AUTH_HDR *hdr; |
AUTH_HDR *hdr; |
78 |
void *p; |
void *p; |
132 |
|
|
133 |
/* Destroy the PDU */ |
/* Destroy the PDU */ |
134 |
void |
void |
135 |
rad_pdu_destroy(pdu) |
rad_pdu_destroy(struct radius_pdu *pdu) |
|
struct radius_pdu *pdu; |
|
136 |
{ |
{ |
137 |
obstack_free(&pdu->st, NULL); |
obstack_free(&pdu->st, NULL); |
138 |
} |
} |
147 |
|
|
148 |
/* Append SIZE bytes from DATA to radius_attr AP. */ |
/* Append SIZE bytes from DATA to radius_attr AP. */ |
149 |
int |
int |
150 |
rad_attr_write(ap, data, size) |
rad_attr_write(struct radius_attr *ap, void *data, size_t size) |
|
struct radius_attr *ap; |
|
|
void *data; |
|
|
size_t size; |
|
151 |
{ |
{ |
152 |
if (sizeof(ap->data) - ap->length + 2 < size) |
if (sizeof(ap->data) - ap->length + 2 < size) |
153 |
return 0; |
return 0; |
162 |
Return value: length of the encoded data or 0 if an error occurred */ |
Return value: length of the encoded data or 0 if an error occurred */ |
163 |
|
|
164 |
int |
int |
165 |
rad_encode_pair(ap, pair) |
rad_encode_pair(struct radius_attr *ap, VALUE_PAIR *pair) |
|
struct radius_attr *ap; |
|
|
VALUE_PAIR *pair; |
|
166 |
{ |
{ |
167 |
UINT4 lval; |
UINT4 lval; |
168 |
size_t len; |
size_t len; |
201 |
Return value: lenght of the data in *rptr. 0 on error */ |
Return value: lenght of the data in *rptr. 0 on error */ |
202 |
|
|
203 |
size_t |
size_t |
204 |
rad_create_pdu(rptr, code, id, vector, secret, pairlist, msg) |
rad_create_pdu(void **rptr, int code, int id, u_char *vector, |
205 |
void **rptr; |
u_char *secret, VALUE_PAIR *pairlist, char *msg) |
|
int code; |
|
|
int id; |
|
|
u_char *vector; |
|
|
u_char *secret; |
|
|
VALUE_PAIR *pairlist; |
|
|
char *msg; |
|
206 |
{ |
{ |
207 |
struct radius_pdu pdu; |
struct radius_pdu pdu; |
208 |
size_t attrlen = 0; |
size_t attrlen = 0; |
243 |
attr.attrno = pair->attribute; |
attr.attrno = pair->attribute; |
244 |
attrlen = rad_encode_pair(&attr, pair); |
attrlen = rad_encode_pair(&attr, pair); |
245 |
} |
} |
246 |
if (attrlen <= 0) { |
if (attrlen < 0) { |
247 |
radlog(L_ERR, "attrlen = %d", attrlen); |
radlog(L_ERR, "attrlen = %d", attrlen); |
248 |
status = 1; |
status = 1; |
249 |
break; |
break; |
288 |
return attrlen; |
return attrlen; |
289 |
} |
} |
290 |
|
|
291 |
|
static VALUE_PAIR * |
292 |
|
rad_decode_pair(int attrno, char *ptr, int attrlen) |
293 |
|
{ |
294 |
|
DICT_ATTR *attr; |
295 |
|
VALUE_PAIR *pair; |
296 |
|
UINT4 lval; |
297 |
|
|
298 |
|
if ((attr = attr_number_to_dict(attrno)) == NULL) { |
299 |
|
debug(1, ("Received unknown attribute %d", attrno)); |
300 |
|
return NULL; |
301 |
|
} |
302 |
|
|
303 |
|
if ( attrlen > AUTH_STRING_LEN ) { |
304 |
|
debug(1, ("attribute %d too long, %d >= %d", attrno, |
305 |
|
attrlen, AUTH_STRING_LEN)); |
306 |
|
return NULL; |
307 |
|
} |
308 |
|
|
309 |
|
pair = avp_alloc(); |
310 |
|
|
311 |
|
pair->name = attr->name; |
312 |
|
pair->attribute = attr->value; |
313 |
|
pair->type = attr->type; |
314 |
|
pair->prop = attr->prop; |
315 |
|
pair->next = NULL; |
316 |
|
|
317 |
|
switch (attr->type) { |
318 |
|
|
319 |
|
case TYPE_STRING: |
320 |
|
/* attrlen always <= AUTH_STRING_LEN */ |
321 |
|
pair->avp_strlength = attrlen; |
322 |
|
pair->avp_strvalue = string_alloc(attrlen + 1); |
323 |
|
memcpy(pair->avp_strvalue, ptr, attrlen); |
324 |
|
pair->avp_strvalue[attrlen] = 0; |
325 |
|
|
326 |
|
if (debug_on(10)) { |
327 |
|
char *save; |
328 |
|
radlog(L_DEBUG, "recv: %s", |
329 |
|
format_pair(pair, &save)); |
330 |
|
free(save); |
331 |
|
} |
332 |
|
|
333 |
|
break; |
334 |
|
|
335 |
|
case TYPE_INTEGER: |
336 |
|
case TYPE_IPADDR: |
337 |
|
memcpy(&lval, ptr, sizeof(UINT4)); |
338 |
|
pair->avp_lvalue = ntohl(lval); |
339 |
|
|
340 |
|
if (debug_on(10)) { |
341 |
|
char *save; |
342 |
|
radlog(L_DEBUG, |
343 |
|
"recv: %s", |
344 |
|
format_pair(pair, &save)); |
345 |
|
free(save); |
346 |
|
} |
347 |
|
break; |
348 |
|
|
349 |
|
default: |
350 |
|
debug(1, (" %s (Unknown Type %d)", |
351 |
|
attr->name,attr->type)); |
352 |
|
avp_free(pair); |
353 |
|
pair = NULL; |
354 |
|
break; |
355 |
|
} |
356 |
|
|
357 |
|
return pair; |
358 |
|
} |
359 |
|
|
360 |
/* Receive UDP client requests, build an authorization request |
/* Receive UDP client requests, build an authorization request |
361 |
structure, and attach attribute-value pairs contained in the request |
structure, and attach attribute-value pairs contained in the request |
362 |
to the new structure. */ |
to the new structure. */ |
363 |
|
|
364 |
RADIUS_REQ * |
RADIUS_REQ * |
365 |
rad_decode_pdu(host, udp_port, buffer, length) |
rad_decode_pdu(UINT4 host, u_short udp_port, u_char *buffer, int length) |
|
UINT4 host; |
|
|
u_short udp_port; |
|
|
u_char *buffer; |
|
|
int length; |
|
366 |
{ |
{ |
367 |
u_char *ptr; |
u_char *ptr; |
368 |
AUTH_HDR *auth; |
AUTH_HDR *auth; |
398 |
radreq->id = auth->id; |
radreq->id = auth->id; |
399 |
radreq->code = auth->code; |
radreq->code = auth->code; |
400 |
memcpy(radreq->vector, auth->vector, AUTH_VECTOR_LEN); |
memcpy(radreq->vector, auth->vector, AUTH_VECTOR_LEN); |
|
radreq->data = buffer; |
|
|
radreq->data_len = length; |
|
401 |
|
|
402 |
/* Extract attribute-value pairs */ |
/* Extract attribute-value pairs */ |
403 |
ptr = (u_char*) (auth + 1); |
ptr = (u_char*) (auth + 1); |
493 |
return radreq; |
return radreq; |
494 |
} |
} |
495 |
|
|
|
VALUE_PAIR * |
|
|
rad_decode_pair(attrno, ptr, attrlen) |
|
|
int attrno; |
|
|
char *ptr; |
|
|
int attrlen; |
|
|
{ |
|
|
DICT_ATTR *attr; |
|
|
VALUE_PAIR *pair; |
|
|
UINT4 lval; |
|
|
|
|
|
if ((attr = attr_number_to_dict(attrno)) == NULL) { |
|
|
debug(1, ("Received unknown attribute %d", attrno)); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
if ( attrlen > AUTH_STRING_LEN ) { |
|
|
debug(1, ("attribute %d too long, %d >= %d", attrno, |
|
|
attrlen, AUTH_STRING_LEN)); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
pair = avp_alloc(); |
|
|
|
|
|
pair->name = attr->name; |
|
|
pair->attribute = attr->value; |
|
|
pair->type = attr->type; |
|
|
pair->prop = attr->prop; |
|
|
pair->next = NULL; |
|
|
|
|
|
switch (attr->type) { |
|
|
|
|
|
case TYPE_STRING: |
|
|
/* attrlen always <= AUTH_STRING_LEN */ |
|
|
pair->avp_strlength = attrlen; |
|
|
pair->avp_strvalue = string_alloc(attrlen + 1); |
|
|
memcpy(pair->avp_strvalue, ptr, attrlen); |
|
|
pair->avp_strvalue[attrlen] = 0; |
|
|
|
|
|
if (debug_on(10)) { |
|
|
char *save; |
|
|
radlog(L_DEBUG, "recv: %s", |
|
|
format_pair(pair, &save)); |
|
|
free(save); |
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case TYPE_INTEGER: |
|
|
case TYPE_IPADDR: |
|
|
memcpy(&lval, ptr, sizeof(UINT4)); |
|
|
pair->avp_lvalue = ntohl(lval); |
|
|
|
|
|
if (debug_on(10)) { |
|
|
char *save; |
|
|
radlog(L_DEBUG, |
|
|
"recv: %s", |
|
|
format_pair(pair, &save)); |
|
|
free(save); |
|
|
} |
|
|
break; |
|
|
|
|
|
default: |
|
|
debug(1, (" %s (Unknown Type %d)", |
|
|
attr->name,attr->type)); |
|
|
avp_free(pair); |
|
|
pair = NULL; |
|
|
break; |
|
|
} |
|
|
|
|
|
return pair; |
|
|
} |
|