Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/krad/attrset.c
39537 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/krad/attrset.c - RADIUS attribute set functions for libkrad */
3
/*
4
* Copyright 2013 Red Hat, Inc. All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions are met:
8
*
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
*
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in
14
* the documentation and/or other materials provided with the
15
* distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <k5-int.h>
31
#include <k5-queue.h>
32
#include "internal.h"
33
34
#include <string.h>
35
36
K5_TAILQ_HEAD(attr_head, attr_st);
37
38
typedef struct attr_st attr;
39
struct attr_st {
40
K5_TAILQ_ENTRY(attr_st) list;
41
krad_attr type;
42
krb5_data attr;
43
char buffer[MAX_ATTRSIZE];
44
};
45
46
struct krad_attrset_st {
47
krb5_context ctx;
48
struct attr_head list;
49
};
50
51
krb5_error_code
52
krad_attrset_new(krb5_context ctx, krad_attrset **set)
53
{
54
krad_attrset *tmp;
55
56
tmp = calloc(1, sizeof(krad_attrset));
57
if (tmp == NULL)
58
return ENOMEM;
59
tmp->ctx = ctx;
60
K5_TAILQ_INIT(&tmp->list);
61
62
*set = tmp;
63
return 0;
64
}
65
66
void
67
krad_attrset_free(krad_attrset *set)
68
{
69
attr *a;
70
71
if (set == NULL)
72
return;
73
74
while (!K5_TAILQ_EMPTY(&set->list)) {
75
a = K5_TAILQ_FIRST(&set->list);
76
K5_TAILQ_REMOVE(&set->list, a, list);
77
zap(a->buffer, sizeof(a->buffer));
78
free(a);
79
}
80
81
free(set);
82
}
83
84
krb5_error_code
85
krad_attrset_add(krad_attrset *set, krad_attr type, const krb5_data *data)
86
{
87
krb5_error_code retval;
88
attr *tmp;
89
90
retval = kr_attr_valid(type, data);
91
if (retval != 0)
92
return retval;
93
94
tmp = calloc(1, sizeof(attr));
95
if (tmp == NULL)
96
return ENOMEM;
97
98
tmp->type = type;
99
tmp->attr = make_data(tmp->buffer, data->length);
100
memcpy(tmp->attr.data, data->data, data->length);
101
102
K5_TAILQ_INSERT_TAIL(&set->list, tmp, list);
103
return 0;
104
}
105
106
krb5_error_code
107
krad_attrset_add_number(krad_attrset *set, krad_attr type, krb5_ui_4 num)
108
{
109
krb5_data data;
110
111
num = htonl(num);
112
data = make_data(&num, sizeof(num));
113
return krad_attrset_add(set, type, &data);
114
}
115
116
void
117
krad_attrset_del(krad_attrset *set, krad_attr type, size_t indx)
118
{
119
attr *a;
120
121
K5_TAILQ_FOREACH(a, &set->list, list) {
122
if (a->type == type && indx-- == 0) {
123
K5_TAILQ_REMOVE(&set->list, a, list);
124
zap(a->buffer, sizeof(a->buffer));
125
free(a);
126
return;
127
}
128
}
129
}
130
131
const krb5_data *
132
krad_attrset_get(const krad_attrset *set, krad_attr type, size_t indx)
133
{
134
attr *a;
135
136
K5_TAILQ_FOREACH(a, &set->list, list) {
137
if (a->type == type && indx-- == 0)
138
return &a->attr;
139
}
140
141
return NULL;
142
}
143
144
krb5_error_code
145
krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
146
{
147
krb5_error_code retval;
148
krad_attrset *tmp;
149
attr *a;
150
151
retval = krad_attrset_new(set->ctx, &tmp);
152
if (retval != 0)
153
return retval;
154
155
K5_TAILQ_FOREACH(a, &set->list, list) {
156
retval = krad_attrset_add(tmp, a->type, &a->attr);
157
if (retval != 0) {
158
krad_attrset_free(tmp);
159
return retval;
160
}
161
}
162
163
*copy = tmp;
164
return 0;
165
}
166
167
/* Place an encoded attributes into outbuf at position *i. Increment *i by the
168
* length of the encoding. */
169
static krb5_error_code
170
append_attr(krb5_context ctx, const char *secret,
171
const uint8_t *auth, krad_attr type, const krb5_data *data,
172
uint8_t outbuf[MAX_ATTRSETSIZE], size_t *i)
173
{
174
uint8_t buffer[MAX_ATTRSIZE];
175
size_t attrlen;
176
krb5_error_code retval;
177
178
retval = kr_attr_encode(ctx, secret, auth, type, data, buffer, &attrlen);
179
if (retval)
180
return retval;
181
182
if (attrlen > MAX_ATTRSETSIZE - *i - 2)
183
return EMSGSIZE;
184
185
outbuf[(*i)++] = type;
186
outbuf[(*i)++] = attrlen + 2;
187
memcpy(outbuf + *i, buffer, attrlen);
188
*i += attrlen;
189
190
return 0;
191
}
192
193
krb5_error_code
194
kr_attrset_encode(const krad_attrset *set, const char *secret,
195
const uint8_t *auth, krb5_boolean add_msgauth,
196
unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
197
{
198
krb5_error_code retval;
199
const uint8_t zeroes[MD5_DIGEST_SIZE] = { 0 };
200
krb5_data zerodata;
201
size_t i = 0;
202
attr *a;
203
204
if (set == NULL) {
205
*outlen = 0;
206
return 0;
207
}
208
209
if (add_msgauth) {
210
/* Encode Message-Authenticator as the first attribute, per
211
* draft-ietf-radext-deprecating-radius-03 section 5.2. */
212
zerodata = make_data((uint8_t *)zeroes, MD5_DIGEST_SIZE);
213
retval = append_attr(set->ctx, secret, auth,
214
KRAD_ATTR_MESSAGE_AUTHENTICATOR, &zerodata,
215
outbuf, &i);
216
if (retval)
217
return retval;
218
}
219
220
K5_TAILQ_FOREACH(a, &set->list, list) {
221
retval = append_attr(set->ctx, secret, auth, a->type, &a->attr,
222
outbuf, &i);
223
if (retval)
224
return retval;
225
}
226
227
*outlen = i;
228
return 0;
229
}
230
231
krb5_error_code
232
kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret,
233
const unsigned char *auth, krad_attrset **set_out)
234
{
235
unsigned char buffer[MAX_ATTRSIZE];
236
krb5_data tmp;
237
krb5_error_code retval;
238
krad_attr type;
239
krad_attrset *set;
240
size_t i, len;
241
242
*set_out = NULL;
243
244
retval = krad_attrset_new(ctx, &set);
245
if (retval != 0)
246
return retval;
247
248
for (i = 0; i + 2 < in->length; ) {
249
type = in->data[i++];
250
tmp = make_data(&in->data[i + 1], (uint8_t)in->data[i] - 2);
251
i += tmp.length + 1;
252
253
retval = (in->length < i) ? EBADMSG : 0;
254
if (retval != 0)
255
goto cleanup;
256
257
retval = kr_attr_decode(ctx, secret, auth, type, &tmp, buffer, &len);
258
if (retval != 0)
259
goto cleanup;
260
261
tmp = make_data(buffer, len);
262
retval = krad_attrset_add(set, type, &tmp);
263
if (retval != 0)
264
goto cleanup;
265
}
266
267
*set_out = set;
268
set = NULL;
269
270
cleanup:
271
zap(buffer, sizeof(buffer));
272
krad_attrset_free(set);
273
return retval;
274
}
275
276