Enable tls psk
[libradsec.git] / radius / valuepair.c
1 /*
2 Copyright (c) 2011, Network RADIUS SARL
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the <organization> nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /** \file valuepair.c
29  *  \brief Functions to manipulate C structure versions of RADIUS attributes.
30  */
31
32 #include "client.h"
33
34 void nr_vp_free(VALUE_PAIR **head)
35 {
36         VALUE_PAIR      *next, *vp;
37
38         for (vp = *head; vp != NULL; vp = next) {
39                 next = vp->next;
40                 if (vp->da->flags.encrypt) {
41                         memset(vp, 0, sizeof(vp));
42                 }
43                 free(vp);
44         }
45
46         *head = NULL;
47 }
48
49
50 VALUE_PAIR *nr_vp_init(VALUE_PAIR *vp, const DICT_ATTR *da)
51 {
52         memset(vp, 0, sizeof(*vp));
53         
54         vp->da = da;
55         vp->length = da->flags.length;
56
57         return vp;
58 }
59
60
61 VALUE_PAIR *nr_vp_alloc(const DICT_ATTR *da)
62 {
63         VALUE_PAIR *vp = NULL;
64
65         if (!da) {
66                 nr_strerror_printf("Unknown attribute");
67                 return NULL;
68         }
69
70         vp = malloc(sizeof(*vp));
71         if (!vp) {
72                 nr_strerror_printf("Out of memory");
73                 return NULL;
74         }
75
76         return nr_vp_init(vp, da);
77 }
78
79 VALUE_PAIR *nr_vp_alloc_raw(unsigned int attr, unsigned int vendor)
80 {
81         VALUE_PAIR *vp = NULL;
82         DICT_ATTR *da;
83
84         vp = malloc(sizeof(*vp) + sizeof(*da) + 64);
85         if (!vp) {
86                 nr_strerror_printf("Out of memory");
87                 return NULL;
88         }
89         memset(vp, 0, sizeof(*vp));
90
91         da = (DICT_ATTR *) (vp + 1);
92
93         if (nr_dict_attr_2struct(da, attr, vendor, (char *) (da + 1), 64) < 0) {
94                 free(vp);
95                 return NULL;
96         }
97
98         vp->da = da;
99
100         return vp;
101 }
102
103 int nr_vp_set_data(VALUE_PAIR *vp, const void *data, size_t sizeof_data)
104 {
105         int rcode = 1;          /* OK */
106
107         if (!vp || !data || (sizeof_data == 0)) return -RSE_INVAL;
108
109         switch (vp->da->type) {
110         case RS_TYPE_BYTE:
111                 vp->vp_integer = *(const uint8_t *) data;
112                 break;
113                 
114         case RS_TYPE_SHORT:
115                 vp->vp_integer = *(const uint16_t *) data;
116                 break;
117                 
118         case RS_TYPE_INTEGER:
119         case RS_TYPE_DATE:
120         case RS_TYPE_IPADDR:
121                 vp->vp_integer = *(const uint32_t *) data;
122                 break;
123                 
124         case RS_TYPE_STRING:
125                 if (sizeof_data >= sizeof(vp->vp_strvalue)) {
126                         sizeof_data = sizeof(vp->vp_strvalue) - 1;
127                         rcode = 0; /* truncated */
128                 }
129
130                 memcpy(vp->vp_strvalue, (const char *) data, sizeof_data);
131                 vp->vp_strvalue[sizeof_data + 1] = '\0';
132                 vp->length = sizeof_data;
133                 break;
134                 
135         case RS_TYPE_OCTETS:
136                 if (sizeof_data > sizeof(vp->vp_octets)) {
137                         sizeof_data = sizeof(vp->vp_octets);
138                         rcode = 0; /* truncated */
139                 }
140                 memcpy(vp->vp_octets, data, sizeof_data);
141                 vp->length = sizeof_data;
142                 break;
143                 
144         default:
145                 return -RSE_ATTR_TYPE_UNKNOWN;
146         }
147
148         return rcode;
149 }
150
151 VALUE_PAIR *nr_vp_create(int attr, int vendor, const void *data, size_t data_len)
152 {
153         const DICT_ATTR *da;
154         VALUE_PAIR *vp;
155
156         da = nr_dict_attr_byvalue(attr, vendor);
157         if (!da) return NULL;
158
159         vp = nr_vp_alloc(da);
160         if (!vp) return NULL;
161         
162         if (nr_vp_set_data(vp, data, data_len) < 0) {
163                 nr_vp_free(&vp);
164                 return NULL;
165         }
166
167         return vp;
168 }
169
170 void nr_vps_append(VALUE_PAIR **head, VALUE_PAIR *tail)
171 {
172         if (!tail) return;
173
174         while (*head) {
175                 head = &((*head)->next);
176         }
177
178         *head = tail;
179 }
180
181 VALUE_PAIR *nr_vps_find(VALUE_PAIR *head,
182                      unsigned int attr, unsigned int vendor)
183 {
184         while (head) {
185                 if ((head->da->attr == attr) &&
186                     (head->da->vendor == vendor)) return head;
187                 head = head->next;
188         }
189
190         return NULL;
191 }