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