1 /* Copyright (c) 2007-2009, UNINETT AS */
2 /* See LICENSE for licensing information. */
3
4 #ifdef SYS_SOLARIS9
5 #include <sys/inttypes.h>
6 #else
7 #include <stdint.h>
8 #endif
9 #include <stdlib.h>
10 #include <string.h>
11 #include <arpa/inet.h>
12 #include "list.h"
13 #include "radmsg.h"
14 #include "debug.h"
15 #include <pthread.h>
16 #include <nettle/hmac.h>
17 #include <openssl/rand.h>
18
19 #define RADLEN(x) ntohs(((uint16_t *)(x))[1])
20
radmsg_free(struct radmsg * msg)21 void radmsg_free(struct radmsg *msg) {
22 if (msg) {
23 freetlvlist(msg->attrs);
24 free(msg);
25 }
26 }
27
radmsg_init(uint8_t code,uint8_t id,uint8_t * auth)28 struct radmsg *radmsg_init(uint8_t code, uint8_t id, uint8_t *auth) {
29 struct radmsg *msg;
30
31 msg = malloc(sizeof(struct radmsg));
32 if (!msg)
33 return NULL;
34 memset(msg, 0, sizeof(struct radmsg));
35 msg->attrs = list_create();
36 if (!msg->attrs) {
37 free(msg);
38 return NULL;
39 }
40 msg->code = code;
41 msg->id = id;
42 if (auth)
43 memcpy(msg->auth, auth, 16);
44 else if (!RAND_bytes(msg->auth, 16)) {
45 free(msg);
46 return NULL;
47 }
48 return msg;
49 }
50
radmsg_add(struct radmsg * msg,struct tlv * attr)51 int radmsg_add(struct radmsg *msg, struct tlv *attr) {
52 if (!msg || !msg->attrs)
53 return 1;
54 if (!attr || attr->l > RAD_Max_Attr_Value_Length)
55 return 0;
56 return list_push(msg->attrs, attr);
57 }
58
59 /** Return a new list with all tlv's in \a msg of type \a type. The
60 * caller is responsible for freeing the list by calling \a
61 * list_free(). */
62 struct list *
radmsg_getalltype(const struct radmsg * msg,uint8_t type)63 radmsg_getalltype(const struct radmsg *msg, uint8_t type)
64 {
65 struct list *list = NULL;
66 struct list_node *node = NULL;
67
68 if (!msg || !msg->attrs)
69 return NULL;
70 list = list_create();
71 if (!list)
72 return NULL;
73
74 for (node = list_first(msg->attrs); node; node = list_next(node))
75 if (((struct tlv *) node->data)->t == type)
76 if (list_push(list, node->data) != 1) {
77 list_free(list);
78 return NULL;
79 }
80 return list;
81 }
82
83 /* returns first tlv of the given type */
radmsg_gettype(struct radmsg * msg,uint8_t type)84 struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) {
85 struct list_node *node;
86 struct tlv *tlv;
87
88 if (!msg)
89 return NULL;
90 for (node = list_first(msg->attrs); node; node = list_next(node)) {
91 tlv = (struct tlv *)node->data;
92 if (tlv->t == type)
93 return tlv;
94 }
95 return NULL;
96 }
97
98 /** Copy all attributes of type \a type from \a src to \a dst.
99 *
100 * If all attributes were copied successfully, the number of
101 * attributes copied is returned.
102 *
103 * If copying failed, a negative number is returned. */
radmsg_copy_attrs(struct radmsg * dst,const struct radmsg * src,uint8_t type)104 int radmsg_copy_attrs(struct radmsg *dst,
105 const struct radmsg *src,
106 uint8_t type)
107 {
108 struct list_node *node = NULL;
109 struct list *list = radmsg_getalltype(src, type);
110 int n = 0;
111
112 for (node = list_first(list); node; node = list_next(node)) {
113 if (radmsg_add(dst, copytlv((struct tlv *) node->data)) != 1) {
114 n = -1;
115 break;
116 }
117 n++;
118 }
119 list_free(list);
120 return n;
121 }
122
_checkmsgauth(unsigned char * rad,uint8_t * authattr,uint8_t * secret,int secret_len)123 int _checkmsgauth(unsigned char *rad, uint8_t *authattr, uint8_t *secret, int secret_len) {
124 int result = 0; /* Fail. */
125 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
126 struct hmac_md5_ctx hmacctx;
127 uint8_t auth[16], hash[MD5_DIGEST_SIZE];
128
129 pthread_mutex_lock(&lock);
130
131 /* FIXME: Why clearing authattr during hashing? */
132 memcpy(auth, authattr, 16);
133 memset(authattr, 0, 16);
134
135 hmac_md5_set_key(&hmacctx, secret_len, secret);
136 hmac_md5_update(&hmacctx, RADLEN(rad), rad);
137 hmac_md5_digest(&hmacctx, sizeof(hash), hash);
138
139 memcpy(authattr, auth, 16);
140
141 if (memcmp(auth, hash, 16)) {
142 debug(DBG_WARN, "message authenticator, wrong value");
143 goto out;
144 }
145 result = 1; /* Success. */
146
147 out:
148 pthread_mutex_unlock(&lock);
149 return result;
150 }
151
_validauth(unsigned char * rad,unsigned char * reqauth,unsigned char * sec,int sec_len)152 int _validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec, int sec_len) {
153 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
154 struct md5_ctx mdctx;
155 unsigned char hash[MD5_DIGEST_SIZE];
156 const unsigned int len = RADLEN(rad);
157 int result = 0; /* Fail. */
158
159 pthread_mutex_lock(&lock);
160 md5_init(&mdctx);
161
162 md5_update(&mdctx, 4, rad);
163 md5_update(&mdctx, 16, reqauth);
164 if (len > 20)
165 md5_update(&mdctx, len - 20, rad + 20);
166 md5_update(&mdctx, sec_len, sec);
167 md5_digest(&mdctx, sizeof(hash), hash);
168
169 result = !memcmp(hash, rad + 4, 16);
170
171 pthread_mutex_unlock(&lock);
172 return result;
173 }
174
_createmessageauth(unsigned char * rad,unsigned char * authattrval,uint8_t * secret,int secret_len)175 int _createmessageauth(unsigned char *rad, unsigned char *authattrval, uint8_t *secret, int secret_len) {
176 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
177 struct hmac_md5_ctx hmacctx;
178
179 if (!authattrval)
180 return 1;
181
182 pthread_mutex_lock(&lock);
183
184 memset(authattrval, 0, 16);
185 hmac_md5_set_key(&hmacctx, secret_len, secret);
186 hmac_md5_update(&hmacctx, RADLEN(rad), rad);
187 hmac_md5_digest(&hmacctx, MD5_DIGEST_SIZE, authattrval);
188
189 pthread_mutex_unlock(&lock);
190 return 1;
191 }
192
_radsign(unsigned char * rad,unsigned char * sec,int sec_len)193 int _radsign(unsigned char *rad, unsigned char *sec, int sec_len) {
194 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
195 struct md5_ctx mdctx;
196
197 pthread_mutex_lock(&lock);
198
199 md5_init(&mdctx);
200 md5_update(&mdctx, RADLEN(rad), rad);
201 md5_update(&mdctx, sec_len, sec);
202 md5_digest(&mdctx, MD5_DIGEST_SIZE, rad + 4);
203
204 pthread_mutex_unlock(&lock);
205 return 1;
206 }
207
tlv2buf(uint8_t * p,const struct tlv * tlv)208 uint8_t *tlv2buf(uint8_t *p, const struct tlv *tlv) {
209 p[0] = tlv->t;
210 p[1] = tlv->l+2;
211 if (tlv->l) {
212 if (tlv->v)
213 memcpy(p+2, tlv->v, tlv->l);
214 else
215 memset(p+2, 0, tlv->l);
216 }
217 return p;
218 }
219
radmsg2buf(struct radmsg * msg,uint8_t * secret,int secret_len)220 uint8_t *radmsg2buf(struct radmsg *msg, uint8_t *secret, int secret_len) {
221 struct list_node *node;
222 struct tlv *tlv;
223 int size;
224 uint8_t *buf, *p, *msgauth = NULL;
225
226 if (!msg || !msg->attrs)
227 return NULL;
228 size = 20;
229 for (node = list_first(msg->attrs); node; node = list_next(node))
230 size += 2 + ((struct tlv *)node->data)->l;
231 if (size > 65535)
232 return NULL;
233 buf = malloc(size);
234 if (!buf)
235 return NULL;
236
237 p = buf;
238 *p++ = msg->code;
239 *p++ = msg->id;
240 *(uint16_t *)p = htons(size);
241 p += 2;
242 memcpy(p, msg->auth, 16);
243 p += 16;
244
245 for (node = list_first(msg->attrs); node; node = list_next(node)) {
246 tlv = (struct tlv *)node->data;
247 p = tlv2buf(p, tlv);
248 if (tlv->t == RAD_Attr_Message_Authenticator && secret)
249 msgauth = ATTRVAL(p);
250 p += tlv->l + 2;
251 }
252 if (msgauth && !_createmessageauth(buf, msgauth, secret, secret_len)) {
253 free(buf);
254 return NULL;
255 }
256 if (secret) {
257 if ((msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Access_Challenge || msg->code == RAD_Accounting_Response || msg->code == RAD_Accounting_Request) && !_radsign(buf, secret, secret_len)) {
258 free(buf);
259 return NULL;
260 }
261 if (msg->code == RAD_Accounting_Request)
262 memcpy(msg->auth, buf + 4, 16);
263 }
264 return buf;
265 }
266
267 /* if secret set we also validate message authenticator if present */
buf2radmsg(uint8_t * buf,uint8_t * secret,int secret_len,uint8_t * rqauth)268 struct radmsg *buf2radmsg(uint8_t *buf, uint8_t *secret, int secret_len, uint8_t *rqauth) {
269 struct radmsg *msg;
270 uint8_t t, l, *v = NULL, *p, auth[16];
271 uint16_t len;
272 struct tlv *attr;
273
274 len = RADLEN(buf);
275 if (len < 20)
276 return NULL;
277
278 if (secret && buf[0] == RAD_Accounting_Request) {
279 memset(auth, 0, 16);
280 if (!_validauth(buf, auth, secret, secret_len)) {
281 debug(DBG_WARN, "buf2radmsg: Accounting-Request message authentication failed");
282 return NULL;
283 }
284 }
285
286 if (rqauth && secret && !_validauth(buf, rqauth, secret, secret_len)) {
287 debug(DBG_WARN, "buf2radmsg: Invalid auth, ignoring reply");
288 return NULL;
289 }
290
291 msg = radmsg_init(buf[0], buf[1], (uint8_t *)buf + 4);
292 if (!msg)
293 return NULL;
294
295 p = buf + 20;
296 while (p - buf + 2 <= len) {
297 t = *p++;
298 l = *p++;
299 if (l < 2 || l > 255) {
300 debug(DBG_WARN, "buf2radmsg: invalid attribute length %d", l);
301 radmsg_free(msg);
302 return NULL;
303 }
304 l -= 2;
305 if (l) {
306 if (p - buf + l > len) {
307 debug(DBG_WARN, "buf2radmsg: attribute length %d exceeds packet length", l + 2);
308 radmsg_free(msg);
309 return NULL;
310 }
311 v = p;
312 p += l;
313 }
314
315 if (t == RAD_Attr_Message_Authenticator && secret) {
316 if (rqauth)
317 memcpy(buf + 4, rqauth, 16);
318 if (l != 16 || !_checkmsgauth(buf, v, secret, secret_len)) {
319 debug(DBG_WARN, "buf2radmsg: message authentication failed");
320 if (rqauth)
321 memcpy(buf + 4, msg->auth, 16);
322 radmsg_free(msg);
323 return NULL;
324 }
325 if (rqauth)
326 memcpy(buf + 4, msg->auth, 16);
327 debug(DBG_DBG, "buf2radmsg: message auth ok");
328 }
329
330 attr = maketlv(t, l, v);
331 if (!attr || !radmsg_add(msg, attr)) {
332 freetlv(attr);
333 radmsg_free(msg);
334 return NULL;
335 }
336 }
337 return msg;
338 }
339
340 /* should accept both names and numeric values, only numeric right now */
attrname2val(char * attrname)341 uint8_t attrname2val(char *attrname) {
342 int val = 0;
343
344 val = atoi(attrname);
345 return val > 0 && val < 256 ? val : 0;
346 }
347
348 /* ATTRNAME is on the form vendor[:type].
349 If only vendor is found, TYPE is set to 256 and 1 is returned.
350 If type is >= 256, 1 is returned.
351 Otherwise, 0 is returned.
352 */
353 /* should accept both names and numeric values, only numeric right now */
vattrname2val(char * attrname,uint32_t * vendor,uint32_t * type)354 int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) {
355 char *s;
356
357 *vendor = atoi(attrname);
358 s = strchr(attrname, ':');
359 if (!s) { /* Only vendor was found. */
360 *type = 256;
361 return 1;
362 }
363 *type = atoi(s + 1);
364 return *type < 256;
365 }
366
attrvalidate(unsigned char * attrs,int length)367 int attrvalidate(unsigned char *attrs, int length) {
368 while (length > 1) {
369 if (ATTRLEN(attrs) < 2) {
370 debug(DBG_INFO, "attrvalidate: invalid attribute length %d", ATTRLEN(attrs));
371 return 0;
372 }
373 length -= ATTRLEN(attrs);
374 if (length < 0) {
375 debug(DBG_INFO, "attrvalidate: attribute length %d exceeds packet length", ATTRLEN(attrs));
376 return 0;
377 }
378 attrs += ATTRLEN(attrs);
379 }
380 if (length)
381 debug(DBG_INFO, "attrvalidate: malformed packet? remaining byte after last attribute");
382 return 1;
383 }
384
385 /** Create vendor specific tlv with ATTR. ATTR is consumed (freed) if
386 * all is well with the new tlv, i.e. if the function returns
387 * !NULL. */
makevendortlv(uint32_t vendor,struct tlv * attr)388 struct tlv *makevendortlv(uint32_t vendor, struct tlv *attr){
389 struct tlv *newtlv = NULL;
390 uint8_t l, *v;
391
392 if (!attr || attr->l > (RAD_Max_Attr_Value_Length - 6))
393 return NULL;
394 l = attr->l + 2 + 4;
395 v = malloc(l);
396 if (v) {
397 vendor = htonl(vendor & 0x00ffffff); /* MSB=0 according to RFC 2865. */
398 memcpy(v, &vendor, 4);
399 tlv2buf(v + 4, attr);
400 newtlv = maketlv(RAD_Attr_Vendor_Specific, l, v);
401 free(v);
402 if (newtlv)
403 freetlv(attr);
404 }
405 return newtlv;
406 }
407
resizeattr(struct tlv * attr,uint8_t newlen)408 int resizeattr(struct tlv *attr, uint8_t newlen) {
409 if (newlen > RAD_Max_Attr_Value_Length)
410 return 0;
411
412 if (resizetlv(attr, newlen))
413 return 1;
414 return 0;
415 }
416
417 /* Local Variables: */
418 /* c-file-style: "stroustrup" */
419 /* End: */
420