Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/plugins/kdb/db2/kdb_xdr.c
34914 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* plugins/kdb/db2/kdb_xdr.c */
3
/*
4
* Copyright 1995 by the Massachusetts Institute of Technology.
5
* All Rights Reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
27
#include "k5-int.h"
28
#include <string.h>
29
#include <stdio.h>
30
#include <errno.h>
31
#include "kdb_xdr.h"
32
33
krb5_error_code
34
krb5_encode_princ_dbkey(krb5_context context, krb5_data *key,
35
krb5_const_principal principal)
36
{
37
char *princ_name;
38
krb5_error_code retval;
39
40
if (!(retval = krb5_unparse_name(context, principal, &princ_name))) {
41
/* need to store the NULL for decoding */
42
key->length = strlen(princ_name)+1;
43
key->data = princ_name;
44
}
45
return(retval);
46
}
47
48
krb5_error_code
49
krb5_encode_princ_entry(krb5_context context, krb5_data *content,
50
krb5_db_entry *entry)
51
{
52
int i, j;
53
unsigned int unparse_princ_size;
54
char * unparse_princ;
55
unsigned char * nextloc;
56
krb5_tl_data * tl_data;
57
krb5_error_code retval;
58
krb5_int16 psize16;
59
60
/*
61
* Generate one lump of data from the krb5_db_entry.
62
* This data must be independent of byte order of the machine,
63
* compact and extensible.
64
*/
65
66
/*
67
* First allocate enough space for all the data.
68
* Need 2 bytes for the length of the base structure
69
* then 36 [ 8 * 4 + 2 * 2] bytes for the base information
70
* [ attributes, max_life, max_renewable_life, expiration,
71
* pw_expiration, last_success, last_failed, fail_auth_count ]
72
* [ n_key_data, n_tl_data ]
73
* then XX bytes [ e_length ] for the extra data [ e_data ]
74
* then XX bytes [ 2 for length + length for string ] for the principal,
75
* then (4 [type + length] + tl_data_length) bytes per tl_data
76
* then (4 + (4 + key_data_length) per key_data_contents) bytes per key_data
77
*/
78
content->length = entry->len + entry->e_length;
79
80
if ((retval = krb5_unparse_name(context, entry->princ, &unparse_princ)))
81
return(retval);
82
83
unparse_princ_size = strlen(unparse_princ) + 1;
84
content->length += unparse_princ_size;
85
content->length += 2;
86
87
i = 0;
88
/* tl_data is a linked list */
89
for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
90
content->length += tl_data->tl_data_length;
91
content->length += 4; /* type, length */
92
i++;
93
}
94
95
if (i != entry->n_tl_data) {
96
retval = KRB5_KDB_TRUNCATED_RECORD;
97
goto epc_error;
98
}
99
100
/* key_data is an array */
101
for (i = 0; i < entry->n_key_data; i++) {
102
content->length += 4; /* Version, KVNO */
103
for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
104
content->length += entry->key_data[i].key_data_length[j];
105
content->length += 4; /* type + length */
106
}
107
}
108
109
if ((content->data = malloc(content->length)) == NULL) {
110
retval = ENOMEM;
111
goto epc_error;
112
}
113
114
/*
115
* Now we go through entry again, this time copying data
116
* These first entries are always saved regardless of version
117
*/
118
nextloc = (unsigned char *)content->data;
119
120
/* Base Length */
121
krb5_kdb_encode_int16(entry->len, nextloc);
122
nextloc += 2;
123
124
/* Attributes */
125
krb5_kdb_encode_int32(entry->attributes, nextloc);
126
nextloc += 4;
127
128
/* Max Life */
129
krb5_kdb_encode_int32(entry->max_life, nextloc);
130
nextloc += 4;
131
132
/* Max Renewable Life */
133
krb5_kdb_encode_int32(entry->max_renewable_life, nextloc);
134
nextloc += 4;
135
136
/* When the client expires */
137
krb5_kdb_encode_int32(entry->expiration, nextloc);
138
nextloc += 4;
139
140
/* When its passwd expires */
141
krb5_kdb_encode_int32(entry->pw_expiration, nextloc);
142
nextloc += 4;
143
144
/* Last successful passwd */
145
krb5_kdb_encode_int32(entry->last_success, nextloc);
146
nextloc += 4;
147
148
/* Last failed passwd attempt */
149
krb5_kdb_encode_int32(entry->last_failed, nextloc);
150
nextloc += 4;
151
152
/* # of failed passwd attempt */
153
krb5_kdb_encode_int32(entry->fail_auth_count, nextloc);
154
nextloc += 4;
155
156
/* # tl_data structures */
157
krb5_kdb_encode_int16(entry->n_tl_data, nextloc);
158
nextloc += 2;
159
160
/* # key_data structures */
161
krb5_kdb_encode_int16(entry->n_key_data, nextloc);
162
nextloc += 2;
163
164
/* Put extended fields here */
165
if (entry->len != KRB5_KDB_V1_BASE_LENGTH)
166
abort();
167
168
/* Any extra data that this version doesn't understand. */
169
if (entry->e_length) {
170
memcpy(nextloc, entry->e_data, entry->e_length);
171
nextloc += entry->e_length;
172
}
173
174
/*
175
* Now we get to the principal.
176
* To squeze a few extra bytes out it is always assumed to come
177
* after the base type.
178
*/
179
psize16 = (krb5_int16) unparse_princ_size;
180
krb5_kdb_encode_int16(psize16, nextloc);
181
nextloc += 2;
182
(void) memcpy(nextloc, unparse_princ, unparse_princ_size);
183
nextloc += unparse_princ_size;
184
185
/* tl_data is a linked list, of type, length, contents */
186
for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
187
krb5_kdb_encode_int16(tl_data->tl_data_type, nextloc);
188
nextloc += 2;
189
krb5_kdb_encode_int16(tl_data->tl_data_length, nextloc);
190
nextloc += 2;
191
192
memcpy(nextloc, tl_data->tl_data_contents, tl_data->tl_data_length);
193
nextloc += tl_data->tl_data_length;
194
}
195
196
/* key_data is an array */
197
for (i = 0; i < entry->n_key_data; i++) {
198
krb5_kdb_encode_int16(entry->key_data[i].key_data_ver, nextloc);
199
nextloc += 2;
200
krb5_kdb_encode_int16(entry->key_data[i].key_data_kvno, nextloc);
201
nextloc += 2;
202
203
for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
204
krb5_int16 type = entry->key_data[i].key_data_type[j];
205
krb5_ui_2 length = entry->key_data[i].key_data_length[j];
206
207
krb5_kdb_encode_int16(type, nextloc);
208
nextloc += 2;
209
krb5_kdb_encode_int16(length, nextloc);
210
nextloc += 2;
211
212
if (length) {
213
memcpy(nextloc, entry->key_data[i].key_data_contents[j],length);
214
nextloc += length;
215
}
216
}
217
}
218
219
epc_error:;
220
free(unparse_princ);
221
return retval;
222
}
223
224
krb5_error_code
225
krb5_decode_princ_entry(krb5_context context, krb5_data *content,
226
krb5_db_entry **entry_ptr)
227
{
228
int sizeleft, i;
229
unsigned char * nextloc;
230
krb5_tl_data ** tl_data;
231
krb5_int16 i16;
232
krb5_db_entry * entry;
233
krb5_error_code retval;
234
235
*entry_ptr = NULL;
236
237
entry = k5alloc(sizeof(*entry), &retval);
238
if (entry == NULL)
239
return retval;
240
241
/*
242
* Reverse the encoding of encode_princ_entry.
243
*
244
* The first part is decoding the base type. If the base type is
245
* bigger than the original base type then the additional fields
246
* need to be filled in. If the base type is larger than any
247
* known base type the additional data goes in e_data.
248
*/
249
250
/* First do the easy stuff */
251
nextloc = (unsigned char *)content->data;
252
sizeleft = content->length;
253
if (sizeleft < KRB5_KDB_V1_BASE_LENGTH) {
254
retval = KRB5_KDB_TRUNCATED_RECORD;
255
goto error_out;
256
}
257
sizeleft -= KRB5_KDB_V1_BASE_LENGTH;
258
259
/* Base Length */
260
krb5_kdb_decode_int16(nextloc, entry->len);
261
nextloc += 2;
262
263
/* Attributes */
264
krb5_kdb_decode_int32(nextloc, entry->attributes);
265
nextloc += 4;
266
267
/* Max Life */
268
krb5_kdb_decode_int32(nextloc, entry->max_life);
269
nextloc += 4;
270
271
/* Max Renewable Life */
272
krb5_kdb_decode_int32(nextloc, entry->max_renewable_life);
273
nextloc += 4;
274
275
/* When the client expires */
276
krb5_kdb_decode_int32(nextloc, entry->expiration);
277
nextloc += 4;
278
279
/* When its passwd expires */
280
krb5_kdb_decode_int32(nextloc, entry->pw_expiration);
281
nextloc += 4;
282
283
/* Last successful passwd */
284
krb5_kdb_decode_int32(nextloc, entry->last_success);
285
nextloc += 4;
286
287
/* Last failed passwd attempt */
288
krb5_kdb_decode_int32(nextloc, entry->last_failed);
289
nextloc += 4;
290
291
/* # of failed passwd attempt */
292
krb5_kdb_decode_int32(nextloc, entry->fail_auth_count);
293
nextloc += 4;
294
295
/* # tl_data structures */
296
krb5_kdb_decode_int16(nextloc, entry->n_tl_data);
297
nextloc += 2;
298
299
if (entry->n_tl_data < 0) {
300
retval = KRB5_KDB_TRUNCATED_RECORD;
301
goto error_out;
302
}
303
304
/* # key_data structures */
305
krb5_kdb_decode_int16(nextloc, entry->n_key_data);
306
nextloc += 2;
307
308
if (entry->n_key_data < 0) {
309
retval = KRB5_KDB_TRUNCATED_RECORD;
310
goto error_out;
311
}
312
313
/* Check for extra data */
314
if (entry->len > KRB5_KDB_V1_BASE_LENGTH) {
315
entry->e_length = entry->len - KRB5_KDB_V1_BASE_LENGTH;
316
entry->e_data = k5memdup(nextloc, entry->e_length, &retval);
317
if (entry->e_data == NULL)
318
goto error_out;
319
nextloc += entry->e_length;
320
}
321
322
/*
323
* Get the principal name for the entry
324
* (stored as a string which gets unparsed.)
325
*/
326
if (sizeleft < 2) {
327
retval = KRB5_KDB_TRUNCATED_RECORD;
328
goto error_out;
329
}
330
sizeleft -= 2;
331
332
i = 0;
333
krb5_kdb_decode_int16(nextloc, i16);
334
i = (int) i16;
335
nextloc += 2;
336
if (i <= 0 || i > sizeleft || nextloc[i - 1] != '\0' ||
337
memchr((char *)nextloc, '\0', i - 1) != NULL) {
338
retval = KRB5_KDB_TRUNCATED_RECORD;
339
goto error_out;
340
}
341
342
if ((retval = krb5_parse_name(context, (char *)nextloc, &(entry->princ))))
343
goto error_out;
344
sizeleft -= i;
345
nextloc += i;
346
347
/* tl_data is a linked list */
348
tl_data = &entry->tl_data;
349
for (i = 0; i < entry->n_tl_data; i++) {
350
if (sizeleft < 4) {
351
retval = KRB5_KDB_TRUNCATED_RECORD;
352
goto error_out;
353
}
354
sizeleft -= 4;
355
if ((*tl_data = (krb5_tl_data *)
356
malloc(sizeof(krb5_tl_data))) == NULL) {
357
retval = ENOMEM;
358
goto error_out;
359
}
360
(*tl_data)->tl_data_next = NULL;
361
(*tl_data)->tl_data_contents = NULL;
362
krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_type);
363
nextloc += 2;
364
krb5_kdb_decode_int16(nextloc, (*tl_data)->tl_data_length);
365
nextloc += 2;
366
367
if ((*tl_data)->tl_data_length > sizeleft) {
368
retval = KRB5_KDB_TRUNCATED_RECORD;
369
goto error_out;
370
}
371
sizeleft -= (*tl_data)->tl_data_length;
372
(*tl_data)->tl_data_contents =
373
k5memdup(nextloc, (*tl_data)->tl_data_length, &retval);
374
if ((*tl_data)->tl_data_contents == NULL)
375
goto error_out;
376
nextloc += (*tl_data)->tl_data_length;
377
tl_data = &((*tl_data)->tl_data_next);
378
}
379
380
/* key_data is an array */
381
if (entry->n_key_data && ((entry->key_data = (krb5_key_data *)
382
malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL)) {
383
retval = ENOMEM;
384
goto error_out;
385
}
386
for (i = 0; i < entry->n_key_data; i++) {
387
krb5_key_data * key_data;
388
int j;
389
390
if (sizeleft < 4) {
391
retval = KRB5_KDB_TRUNCATED_RECORD;
392
goto error_out;
393
}
394
sizeleft -= 4;
395
key_data = entry->key_data + i;
396
memset(key_data, 0, sizeof(krb5_key_data));
397
krb5_kdb_decode_int16(nextloc, key_data->key_data_ver);
398
nextloc += 2;
399
krb5_kdb_decode_int16(nextloc, key_data->key_data_kvno);
400
nextloc += 2;
401
402
/* key_data_ver determines number of elements and how to unparse
403
* them. */
404
if (key_data->key_data_ver >= 0 &&
405
key_data->key_data_ver <= KRB5_KDB_V1_KEY_DATA_ARRAY) {
406
for (j = 0; j < key_data->key_data_ver; j++) {
407
if (sizeleft < 4) {
408
retval = KRB5_KDB_TRUNCATED_RECORD;
409
goto error_out;
410
}
411
sizeleft -= 4;
412
krb5_kdb_decode_int16(nextloc, key_data->key_data_type[j]);
413
nextloc += 2;
414
krb5_kdb_decode_int16(nextloc, key_data->key_data_length[j]);
415
nextloc += 2;
416
417
if (key_data->key_data_length[j] > sizeleft) {
418
retval = KRB5_KDB_TRUNCATED_RECORD;
419
goto error_out;
420
}
421
sizeleft -= key_data->key_data_length[j];
422
if (key_data->key_data_length[j]) {
423
key_data->key_data_contents[j] =
424
k5memdup(nextloc, key_data->key_data_length[j],
425
&retval);
426
if (key_data->key_data_contents[j] == NULL)
427
goto error_out;
428
nextloc += key_data->key_data_length[j];
429
}
430
}
431
} else {
432
retval = KRB5_KDB_BAD_VERSION;
433
goto error_out;
434
}
435
}
436
*entry_ptr = entry;
437
return 0;
438
439
error_out:
440
krb5_db_free_principal(context, entry);
441
return retval;
442
}
443
444