Enable tls psk
[libradsec.git] / avp.c
1 /* Copyright 2011 JANET(UK). All rights reserved.
2    See LICENSE for licensing information. */
3
4 #if defined HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <assert.h>
13
14 #include <radsec/radsec.h>
15 #include <radius/client.h>
16
17 #define RS_ERR(err) ((err) < 0 ? -err : RSE_OK)
18
19 void
20 rs_avp_free (rs_avp **vps)
21 {
22   nr_vp_free (vps);
23 }
24
25 size_t
26 rs_avp_length (rs_const_avp *vp)
27 {
28   if (vp == NULL)
29     return 0;
30
31   return vp->length;
32 }
33
34 rs_attr_type_t
35 rs_avp_typeof (rs_const_avp *vp)
36 {
37   if (vp == NULL)
38     return RS_TYPE_INVALID;
39
40   return vp->da->type;
41 }
42
43 void
44 rs_avp_attrid (rs_const_avp *vp,
45                unsigned int *attr,
46                unsigned int *vendor)
47 {
48   assert (vp != NULL);
49
50   *attr = vp->da->attr;
51   *vendor = vp->da->vendor;
52 }
53
54 const char *
55 rs_avp_name (rs_const_avp *vp)
56 {
57   return (vp != NULL) ? vp->da->name : NULL;
58 }
59
60 void
61 rs_avp_append (rs_avp **head, rs_avp *tail)
62 {
63   nr_vps_append (head, tail);
64 }
65
66 rs_avp *
67 rs_avp_find (rs_avp *vp, unsigned int attr, unsigned int vendor)
68 {
69   if (vp == NULL)
70     return NULL;
71
72   return nr_vps_find (vp, attr, vendor);
73 }
74
75 rs_const_avp *
76 rs_avp_find_const (rs_const_avp *vp,
77                    unsigned int attr, unsigned int vendor)
78 {
79   if (vp == NULL)
80     return NULL;
81
82   return nr_vps_find ((rs_avp *)vp, attr, vendor);
83 }
84
85 rs_avp *
86 rs_avp_alloc (unsigned int attr, unsigned int vendor)
87 {
88   const DICT_ATTR *da;
89   VALUE_PAIR *vp;
90
91   da = nr_dict_attr_byvalue (attr, vendor);
92   if (da == NULL) {
93     vp = nr_vp_alloc_raw (attr, vendor);
94   } else {
95     vp = nr_vp_alloc (da);
96   }
97
98   if (vp == NULL)
99     return NULL;
100
101   return vp;
102 }
103
104 rs_avp *
105 rs_avp_dup (rs_const_avp *vp)
106 {
107   rs_avp *vp2;
108
109   if (vp->da->flags.unknown)
110     vp2 = nr_vp_alloc_raw (vp->da->attr, vp->da->vendor);
111   else
112     vp2 = nr_vp_alloc (vp->da);
113   if (vp2 == NULL)
114     return NULL;
115
116   vp2->length = vp->length;
117   vp2->tag = vp->tag;
118   vp2->next = NULL;
119
120 #ifdef RS_TYPE_TLV
121   if (rs_avp_is_tlv (vp)) {
122     vp2->vp_tlv = malloc (vp->length);
123     if (vp2->vp_tlv == NULL) {
124       rs_avp_free (vp2);
125       return NULL;
126     }
127     memcpy (vp2->vp_tlv, vp->vp_tlv, vp->length);
128     return vp2;
129   }
130 #endif
131
132   memcpy (vp2->vp_strvalue, vp->vp_strvalue, vp->length);
133   if (rs_avp_is_string (vp))
134     vp2->vp_strvalue[vp->length] = '\0';
135
136   return vp2;
137 }
138
139 rs_avp *
140 rs_avp_next (rs_avp *vp)
141 {
142   return (vp != NULL) ? vp->next : NULL;
143 }
144
145 rs_const_avp *
146 rs_avp_next_const (rs_const_avp *vp)
147 {
148   return (vp != NULL) ? vp->next : NULL;
149 }
150
151 int
152 rs_avp_delete (rs_avp **first,
153                unsigned int attr, unsigned int vendor)
154 {
155   int found = 0;
156   rs_avp **p;
157
158   for (p = first; *p != NULL; p++) {
159     if ((*p)->da->attr == attr &&
160         (*p)->da->vendor == vendor) {
161       rs_avp *next = (*p)->next;
162
163       (*p)->next = NULL;
164       rs_avp_free (p);
165
166       *p = next;
167       found++;
168     }
169   }
170
171   return found ? RSE_OK : RSE_ATTR_UNKNOWN;
172 }
173
174 const char *
175 rs_avp_string_value (rs_const_avp *vp)
176 {
177   if (!rs_avp_is_string (vp))
178     return NULL;
179
180   return vp->vp_strvalue;
181 }
182
183 int
184 rs_avp_string_set (rs_avp *vp, const char *str)
185 {
186   int err;
187
188   if (vp == NULL)
189     return RSE_INVAL;
190   if (!rs_avp_is_string (vp))
191     return RSE_ATTR_INVALID;
192
193   err = nr_vp_set_data (vp, str, strlen (str));
194   return RS_ERR(err);
195 }
196
197 uint32_t
198 rs_avp_integer_value (rs_const_avp *vp)
199 {
200   if (!rs_avp_is_integer (vp))
201     return 0;
202   return vp->vp_integer;
203 }
204
205 int
206 rs_avp_integer_set (rs_avp *vp, uint32_t val)
207 {
208   int err;
209
210   if (vp == NULL)
211     return RSE_INVAL;
212   if (!rs_avp_is_integer (vp))
213     return RSE_ATTR_INVALID;
214
215   err = nr_vp_set_data (vp, &val, sizeof (val));
216   return RS_ERR(err);
217 }
218
219 uint32_t
220 rs_avp_ipaddr_value (rs_const_avp *vp)
221 {
222   if (!rs_avp_is_ipaddr (vp))
223     return 0;
224   return vp->vp_ipaddr;
225 }
226
227 int
228 rs_avp_ipaddr_set (rs_avp *vp, struct in_addr in)
229 {
230   int err;
231
232   if (vp == NULL)
233     return RSE_INVAL;
234   if (!rs_avp_is_ipaddr (vp))
235     return RSE_ATTR_INVALID;
236
237   err = nr_vp_set_data (vp, &in, sizeof (in));
238   return RS_ERR(err);
239 }
240
241 time_t
242 rs_avp_date_value (rs_const_avp *vp)
243 {
244   if (!rs_avp_is_date (vp))
245     return 0;
246   return vp->vp_date;
247 }
248
249 int
250 rs_avp_date_set (rs_avp *vp, time_t date)
251 {
252   uint32_t date32;
253   int err;
254
255   if (vp == NULL)
256     return RSE_INVAL;
257   if (!rs_avp_is_date (vp))
258     return RSE_ATTR_INVALID;
259   if (date > 0xFFFFFFFF)
260     return RSE_ATTR_INVALID;
261
262   date32 = (uint32_t)date;
263   err = nr_vp_set_data (vp, &date32, sizeof (date32));
264
265   return RS_ERR(err);
266 }
267
268 const unsigned char *
269 rs_avp_octets_value_const_ptr (rs_const_avp *vp)
270 {
271   return rs_avp_octets_value_ptr ((rs_avp *)vp);
272 }
273
274 unsigned char *
275 rs_avp_octets_value_ptr (rs_avp *vp)
276 {
277   if (vp == NULL)
278     return NULL;
279
280 #ifdef RS_TYPE_TLV
281   if (rs_avp_is_tlv (vp))
282     return vp->vp_tlv;
283 #endif
284
285   return vp->vp_octets;
286 }
287
288 int
289 rs_avp_octets_value_byref (rs_avp *vp,
290                            unsigned char **p,
291                            size_t *len)
292 {
293   if (vp == NULL)
294     return RSE_INVAL;
295
296   *len = vp->length;
297   *p = (unsigned char *)rs_avp_octets_value_ptr (vp);
298
299   return RSE_OK;
300 }
301
302 int
303 rs_avp_octets_value (rs_const_avp *vp,
304                      unsigned char *buf,
305                      size_t *len)
306 {
307   if (vp == NULL)
308     return RSE_INVAL;
309
310   if (vp->length > *len) {
311     *len = vp->length;
312     return RSE_ATTR_TOO_SMALL;
313   }
314
315   *len = vp->length;
316
317 #ifdef RS_TYPE_TLV
318   if (rs_avp_is_tlv (vp))
319     memcpy (buf, vp->vp_tlv, vp->length);
320   else
321 #endif
322     memcpy (buf, vp->vp_octets, vp->length);
323
324   return RSE_OK;
325 }
326
327 int
328 rs_avp_fragmented_value (rs_const_avp *vps,
329                          unsigned char *buf,
330                          size_t *len)
331 {
332   size_t total_len = 0;
333   unsigned char *p;
334   rs_const_avp *vp;
335
336   if (vps == NULL)
337     return RSE_INVAL;
338
339   if (!rs_avp_is_octets (vps) &&
340       !rs_avp_is_string (vps))
341     return RSE_ATTR_INVALID;
342
343   for (vp = vps;
344        vp != NULL;
345        vp = rs_avp_find_const (vp->next, vp->da->attr, vp->da->vendor))
346     total_len += vp->length;
347
348   if (*len < total_len) {
349     *len = total_len;
350     return RSE_ATTR_TOO_SMALL;
351   }
352
353   for (vp = vps, p = buf;
354        vp != NULL;
355        vp = rs_avp_find_const (vp->next, vp->da->attr, vp->da->vendor)) {
356     memcpy (p, vp->vp_octets, vp->length);
357     p += vp->length;
358   }
359
360   *len = total_len;
361
362   return RSE_OK;
363 }
364
365 int
366 rs_avp_octets_set (rs_avp *vp,
367                    const unsigned char *buf,
368                    size_t len)
369 {
370   int err;
371
372   if (!rs_avp_is_octets (vp))
373     return RSE_ATTR_INVALID;
374
375   err = nr_vp_set_data (vp, buf, len);
376
377   return RS_ERR(err);
378 }
379
380 int
381 rs_avp_ifid_value (rs_const_avp *vp, uint8_t val[8])
382 {
383   if (!rs_avp_is_ifid (vp))
384     return RSE_ATTR_INVALID;
385
386   memcpy (val, vp->vp_ifid, 8);
387
388   return RSE_OK;
389 }
390
391 int
392 rs_avp_ifid_set (rs_avp *vp, const uint8_t val[8])
393 {
394   int err;
395
396   if (!rs_avp_is_ifid (vp))
397     return RSE_ATTR_INVALID;
398
399   err = nr_vp_set_data (vp, val, 8);
400   return RS_ERR(err);
401 }
402
403 uint8_t
404 rs_avp_byte_value (rs_const_avp *vp)
405 {
406   if (!rs_avp_is_byte (vp))
407     return 0;
408   return vp->vp_integer;
409 }
410
411 int
412 rs_avp_byte_set (rs_avp *vp, uint8_t val)
413 {
414   int err;
415
416   if (!rs_avp_is_byte (vp))
417     return RSE_ATTR_INVALID;
418
419   err = nr_vp_set_data (vp, &val, sizeof (val));
420   return RS_ERR(err);
421 }
422
423 uint16_t
424 rs_avp_short_value (rs_const_avp *vp)
425 {
426   if (!rs_avp_is_short (vp))
427     return 0;
428   return vp->vp_integer;
429 }
430
431 int
432 rs_avp_short_set (rs_avp *vp, uint16_t val)
433 {
434   int err;
435
436   if (!rs_avp_is_short (vp))
437     return RSE_ATTR_INVALID;
438
439   err = nr_vp_set_data (vp, &val, sizeof (val));
440   return RS_ERR(err);
441 }
442
443 int
444 rs_attr_find (const char *name,
445               unsigned int *attr,
446               unsigned int *vendor)
447 {
448   const DICT_ATTR *da;
449
450   da = nr_dict_attr_byname (name);
451   if (da == NULL)
452     return RSE_ATTR_UNKNOWN;
453
454   *attr = da->attr;
455   *vendor = da->vendor;
456
457   return RSE_OK;
458 }
459
460 int
461 rs_attr_display_name (unsigned int attr,
462                       unsigned int vendor,
463                       char *buffer,
464                       size_t bufsize,
465                       int canonical)
466 {
467   const DICT_ATTR *da = NULL;
468   DICT_ATTR da2;
469   int err;
470
471   if (!canonical) {
472     da = nr_dict_attr_byvalue (attr, vendor);
473   }
474   if (da == NULL) {
475     err = nr_dict_attr_2struct(&da2, attr, vendor,
476                                buffer, bufsize);
477     if (err < 0)
478       return -err;
479   } else {
480     snprintf(buffer, bufsize, "%s", da->name);
481   }
482
483   return RSE_OK;
484 }
485
486 int
487 rs_attr_parse_name (const char *name,
488                     unsigned int *attr,
489                     unsigned int *vendor)
490 {
491   const DICT_ATTR *da;
492
493   if (strncmp(name, "Attr-", 5) == 0) {
494     char *s = (char *)&name[5];
495     unsigned int tmp;
496
497     tmp = strtoul(s, &s, 10);
498     if (*s == '.') {
499       s++;
500
501       switch (tmp) {
502       case PW_VENDOR_SPECIFIC:
503         *vendor = strtoul(s, &s, 10);
504         if (*s != '.')
505           return RSE_ATTR_BAD_NAME;
506
507         s++;
508
509         *attr = strtoul(s, &s, 10);
510         if (*s != '\0')
511           return RSE_ATTR_BAD_NAME;
512
513         break;
514       default:
515         return RSE_ATTR_BAD_NAME;
516       }
517     } else {
518       *attr = tmp;
519       *vendor = 0;
520     }
521   } else {
522     da = nr_dict_attr_byname (name);
523     if (da == NULL)
524       return RSE_ATTR_UNKNOWN;
525
526     *attr = da->attr;
527     *vendor = da->vendor;
528   }
529
530   return RSE_OK;
531 }
532
533 size_t
534 rs_avp_display_value (rs_const_avp *vp,
535                       char *buffer,
536                       size_t buflen)
537 {
538   return nr_vp_snprintf_value (buffer, buflen, vp);
539 }
540