Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/kdb/lmdb/marshal.c
34914 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/kdb/kdb_xdr.c */
3
/*
4
* Copyright (C) 2018 by the Massachusetts Institute of Technology.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
*
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
*
14
* * Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in
16
* the documentation and/or other materials provided with the
17
* distribution.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30
* OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
#include "k5-int.h"
34
#include "k5-input.h"
35
#include <kdb.h>
36
#include "klmdb-int.h"
37
38
static void
39
put_tl_data(struct k5buf *buf, const krb5_tl_data *tl)
40
{
41
for (; tl != NULL; tl = tl->tl_data_next) {
42
k5_buf_add_uint16_le(buf, tl->tl_data_type);
43
k5_buf_add_uint16_le(buf, tl->tl_data_length);
44
k5_buf_add_len(buf, tl->tl_data_contents, tl->tl_data_length);
45
}
46
}
47
48
krb5_error_code
49
klmdb_encode_princ(krb5_context context, const krb5_db_entry *entry,
50
uint8_t **enc_out, size_t *len_out)
51
{
52
struct k5buf buf;
53
const krb5_key_data *kd;
54
int i, j;
55
56
*enc_out = NULL;
57
*len_out = 0;
58
59
k5_buf_init_dynamic(&buf);
60
61
k5_buf_add_uint32_le(&buf, entry->attributes);
62
k5_buf_add_uint32_le(&buf, entry->max_life);
63
k5_buf_add_uint32_le(&buf, entry->max_renewable_life);
64
k5_buf_add_uint32_le(&buf, entry->expiration);
65
k5_buf_add_uint32_le(&buf, entry->pw_expiration);
66
k5_buf_add_uint16_le(&buf, entry->n_tl_data);
67
k5_buf_add_uint16_le(&buf, entry->n_key_data);
68
put_tl_data(&buf, entry->tl_data);
69
for (i = 0; i < entry->n_key_data; i++) {
70
kd = &entry->key_data[i];
71
k5_buf_add_uint16_le(&buf, kd->key_data_ver);
72
k5_buf_add_uint16_le(&buf, kd->key_data_kvno);
73
for (j = 0; j < kd->key_data_ver; j++) {
74
k5_buf_add_uint16_le(&buf, kd->key_data_type[j]);
75
k5_buf_add_uint16_le(&buf, kd->key_data_length[j]);
76
if (kd->key_data_length[j] > 0) {
77
k5_buf_add_len(&buf, kd->key_data_contents[j],
78
kd->key_data_length[j]);
79
}
80
}
81
}
82
83
if (k5_buf_status(&buf) != 0)
84
return ENOMEM;
85
86
*enc_out = buf.data;
87
*len_out = buf.len;
88
return 0;
89
}
90
91
void
92
klmdb_encode_princ_lockout(krb5_context context, const krb5_db_entry *entry,
93
uint8_t buf[LOCKOUT_RECORD_LEN])
94
{
95
store_32_le(entry->last_success, buf);
96
store_32_le(entry->last_failed, buf + 4);
97
store_32_le(entry->fail_auth_count, buf + 8);
98
}
99
100
krb5_error_code
101
klmdb_encode_policy(krb5_context context, const osa_policy_ent_rec *pol,
102
uint8_t **enc_out, size_t *len_out)
103
{
104
struct k5buf buf;
105
106
*enc_out = NULL;
107
*len_out = 0;
108
109
k5_buf_init_dynamic(&buf);
110
k5_buf_add_uint32_le(&buf, pol->pw_min_life);
111
k5_buf_add_uint32_le(&buf, pol->pw_max_life);
112
k5_buf_add_uint32_le(&buf, pol->pw_min_length);
113
k5_buf_add_uint32_le(&buf, pol->pw_min_classes);
114
k5_buf_add_uint32_le(&buf, pol->pw_history_num);
115
k5_buf_add_uint32_le(&buf, pol->pw_max_fail);
116
k5_buf_add_uint32_le(&buf, pol->pw_failcnt_interval);
117
k5_buf_add_uint32_le(&buf, pol->pw_lockout_duration);
118
k5_buf_add_uint32_le(&buf, pol->attributes);
119
k5_buf_add_uint32_le(&buf, pol->max_life);
120
k5_buf_add_uint32_le(&buf, pol->max_renewable_life);
121
122
if (pol->allowed_keysalts == NULL) {
123
k5_buf_add_uint32_le(&buf, 0);
124
} else {
125
k5_buf_add_uint32_le(&buf, strlen(pol->allowed_keysalts));
126
k5_buf_add(&buf, pol->allowed_keysalts);
127
}
128
129
k5_buf_add_uint16_le(&buf, pol->n_tl_data);
130
put_tl_data(&buf, pol->tl_data);
131
132
if (k5_buf_status(&buf) != 0)
133
return ENOMEM;
134
135
*enc_out = buf.data;
136
*len_out = buf.len;
137
return 0;
138
}
139
140
static krb5_error_code
141
get_tl_data(struct k5input *in, size_t count, krb5_tl_data **tl)
142
{
143
krb5_error_code ret;
144
const uint8_t *contents;
145
size_t i, len;
146
147
for (i = 0; i < count; i++) {
148
*tl = k5alloc(sizeof(**tl), &ret);
149
if (*tl == NULL)
150
return ret;
151
(*tl)->tl_data_type = k5_input_get_uint16_le(in);
152
len = (*tl)->tl_data_length = k5_input_get_uint16_le(in);
153
contents = k5_input_get_bytes(in, len);
154
if (contents == NULL)
155
return KRB5_KDB_TRUNCATED_RECORD;
156
(*tl)->tl_data_contents = k5memdup(contents, len, &ret);
157
if ((*tl)->tl_data_contents == NULL)
158
return ret;
159
tl = &(*tl)->tl_data_next;
160
}
161
162
return 0;
163
}
164
165
krb5_error_code
166
klmdb_decode_princ(krb5_context context, const void *key, size_t key_len,
167
const void *enc, size_t enc_len, krb5_db_entry **entry_out)
168
{
169
krb5_error_code ret;
170
struct k5input in;
171
krb5_db_entry *entry = NULL;
172
char *princname = NULL;
173
const uint8_t *contents;
174
int i, j;
175
size_t len;
176
krb5_key_data *kd;
177
178
*entry_out = NULL;
179
180
entry = k5alloc(sizeof(*entry), &ret);
181
if (entry == NULL)
182
goto cleanup;
183
184
princname = k5memdup0(key, key_len, &ret);
185
if (princname == NULL)
186
goto cleanup;
187
ret = krb5_parse_name(context, princname, &entry->princ);
188
if (ret)
189
goto cleanup;
190
191
k5_input_init(&in, enc, enc_len);
192
entry->attributes = k5_input_get_uint32_le(&in);
193
entry->max_life = k5_input_get_uint32_le(&in);
194
entry->max_renewable_life = k5_input_get_uint32_le(&in);
195
entry->expiration = k5_input_get_uint32_le(&in);
196
entry->pw_expiration = k5_input_get_uint32_le(&in);
197
entry->n_tl_data = k5_input_get_uint16_le(&in);
198
entry->n_key_data = k5_input_get_uint16_le(&in);
199
if (entry->n_tl_data < 0 || entry->n_key_data < 0) {
200
ret = KRB5_KDB_TRUNCATED_RECORD;
201
goto cleanup;
202
}
203
204
ret = get_tl_data(&in, entry->n_tl_data, &entry->tl_data);
205
if (ret)
206
goto cleanup;
207
208
if (entry->n_key_data > 0) {
209
entry->key_data = k5calloc(entry->n_key_data, sizeof(*entry->key_data),
210
&ret);
211
if (entry->key_data == NULL)
212
goto cleanup;
213
}
214
for (i = 0; i < entry->n_key_data; i++) {
215
kd = &entry->key_data[i];
216
kd->key_data_ver = k5_input_get_uint16_le(&in);
217
kd->key_data_kvno = k5_input_get_uint16_le(&in);
218
if (kd->key_data_ver < 0 &&
219
kd->key_data_ver > KRB5_KDB_V1_KEY_DATA_ARRAY) {
220
ret = KRB5_KDB_BAD_VERSION;
221
goto cleanup;
222
}
223
for (j = 0; j < kd->key_data_ver; j++) {
224
kd->key_data_type[j] = k5_input_get_uint16_le(&in);
225
len = kd->key_data_length[j] = k5_input_get_uint16_le(&in);
226
contents = k5_input_get_bytes(&in, len);
227
if (contents == NULL) {
228
ret = KRB5_KDB_TRUNCATED_RECORD;
229
goto cleanup;
230
}
231
if (len > 0) {
232
kd->key_data_contents[j] = k5memdup(contents, len, &ret);
233
if (kd->key_data_contents[j] == NULL)
234
goto cleanup;
235
}
236
}
237
}
238
239
ret = in.status;
240
if (ret)
241
goto cleanup;
242
243
entry->len = KRB5_KDB_V1_BASE_LENGTH;
244
*entry_out = entry;
245
entry = NULL;
246
247
cleanup:
248
free(princname);
249
krb5_db_free_principal(context, entry);
250
return ret;
251
}
252
253
void
254
klmdb_decode_princ_lockout(krb5_context context, krb5_db_entry *entry,
255
const uint8_t buf[LOCKOUT_RECORD_LEN])
256
{
257
entry->last_success = load_32_le(buf);
258
entry->last_failed = load_32_le(buf + 4);
259
entry->fail_auth_count = load_32_le(buf + 8);
260
}
261
262
krb5_error_code
263
klmdb_decode_policy(krb5_context context, const void *key, size_t key_len,
264
const void *enc, size_t enc_len, osa_policy_ent_t *pol_out)
265
{
266
krb5_error_code ret;
267
osa_policy_ent_t pol = NULL;
268
struct k5input in;
269
const char *str;
270
size_t len;
271
272
*pol_out = NULL;
273
pol = k5alloc(sizeof(*pol), &ret);
274
if (pol == NULL)
275
goto error;
276
277
pol->name = k5memdup0(key, key_len, &ret);
278
if (pol->name == NULL)
279
goto error;
280
281
k5_input_init(&in, enc, enc_len);
282
pol->pw_min_life = k5_input_get_uint32_le(&in);
283
pol->pw_max_life = k5_input_get_uint32_le(&in);
284
pol->pw_min_length = k5_input_get_uint32_le(&in);
285
pol->pw_min_classes = k5_input_get_uint32_le(&in);
286
pol->pw_history_num = k5_input_get_uint32_le(&in);
287
pol->pw_max_fail = k5_input_get_uint32_le(&in);
288
pol->pw_failcnt_interval = k5_input_get_uint32_le(&in);
289
pol->pw_lockout_duration = k5_input_get_uint32_le(&in);
290
pol->attributes = k5_input_get_uint32_le(&in);
291
pol->max_life = k5_input_get_uint32_le(&in);
292
pol->max_renewable_life = k5_input_get_uint32_le(&in);
293
294
len = k5_input_get_uint32_le(&in);
295
if (len > 0) {
296
str = (char *)k5_input_get_bytes(&in, len);
297
if (str == NULL) {
298
ret = KRB5_KDB_TRUNCATED_RECORD;
299
goto error;
300
}
301
pol->allowed_keysalts = k5memdup0(str, len, &ret);
302
if (pol->allowed_keysalts == NULL)
303
goto error;
304
}
305
306
pol->n_tl_data = k5_input_get_uint16_le(&in);
307
ret = get_tl_data(&in, pol->n_tl_data, &pol->tl_data);
308
if (ret)
309
goto error;
310
311
ret = in.status;
312
if (ret)
313
goto error;
314
315
*pol_out = pol;
316
return 0;
317
318
error:
319
krb5_db_free_policy(context, pol);
320
return ret;
321
}
322
323