Bug Summary

File:util/ipa_krb5.c
Warning:line 647, column 9
Value stored to 'krberr' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ipa_krb5.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/10.0.0 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/nss3 -I /usr/include/nspr4 -I /usr/include/nspr4 -I /usr/include/nss3 -I /usr/include/nspr4 -D __STDC_WANT_LIB_EXT1__=1 -D _DEFAULT_SOURCE=1 -D _POSIX_C_SOURCE=200809L -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/10.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/heimes/redhat/freeipa/util -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -faddrsig -o /home/heimes/redhat/freeipa/report/2020-06-05-101548-295465-1 -x c ipa_krb5.c
1/*
2 * Kerberos related utils for FreeIPA
3 *
4 * Authors: Simo Sorce <ssorce@redhat.com>
5 *
6 * Copyright (C) 2011 Simo Sorce, Red Hat
7 * see file 'COPYING' for use and warranty information
8 *
9 * This program is free software you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <string.h>
24#include <stdlib.h>
25#include <errno(*__errno_location ()).h>
26#include <lber.h>
27#include <errno(*__errno_location ()).h>
28
29#include <libintl.h>
30#define _(STRING)gettext(STRING) gettext(STRING)
31
32#include "ipa_krb5.h"
33
34#define TOSTR(x)"x" STR(x)"x"
35#define STR(x)"x" #x
36const char *ipapwd_password_max_len_errmsg = \
37 "clear-text password is too long (max " \
38 TOSTR(IPAPWD_PASSWORD_MAX_LEN)"1000" \
39 " chars)!";
40
41/* Salt types */
42#define KRB5P_SALT_SIZE16 16
43
44static krb5_error_code ipa_get_random_salt(krb5_context krbctx,
45 krb5_data *salt)
46{
47 krb5_error_code kerr;
48 int i, v;
49
50 /* make random salt */
51 salt->length = KRB5P_SALT_SIZE16;
52 salt->data = malloc(KRB5P_SALT_SIZE16);
53 if (!salt->data) {
54 return ENOMEM12;
55 }
56 kerr = krb5_c_random_make_octets(krbctx, salt);
57 if (kerr) {
58 return kerr;
59 }
60
61 /* Windows treats the salt as a string.
62 * To avoid any compatibility issue, limits octects only to
63 * the ASCII printable range, or 0x20 <= val <= 0x7E */
64 for (i = 0; i < salt->length; i++) {
65 v = (unsigned char)salt->data[i];
66 v %= 0x5E; /* 7E - 20 */
67 v += 0x20; /* add base */
68 salt->data[i] = v;
69 }
70
71 return 0;
72}
73
74void
75ipa_krb5_free_ktypes(krb5_context context, krb5_enctype *val)
76{
77 free(val);
78}
79
80/*
81 * Convert a krb5_principal into the default salt for that principal.
82 */
83krb5_error_code ipa_krb5_principal2salt_norealm(krb5_context context,
84 krb5_const_principal pr,
85 krb5_data *ret)
86{
87 unsigned int size = 0, offset=0;
88 krb5_int32 nelem;
89 register int i;
90
91 if (pr == NULL((void*)0)) {
92 ret->length = 0;
93 ret->data = NULL((void*)0);
94 return 0;
95 }
96
97 nelem = krb5_princ_size(context, pr)(pr)->length;
98
99 for (i = 0; i < (int) nelem; i++)
100 size += krb5_princ_component(context, pr, i)(((i) < (pr)->length) ? (pr)->data + (i) : ((void*)0
))
->length;
101
102 ret->length = size;
103 if (!(ret->data = malloc (size)))
104 return ENOMEM12;
105
106 for (i = 0; i < (int) nelem; i++) {
107 memcpy(&ret->data[offset], krb5_princ_component(context, pr, i)(((i) < (pr)->length) ? (pr)->data + (i) : ((void*)0
))
->data,
108 krb5_princ_component(context, pr, i)(((i) < (pr)->length) ? (pr)->data + (i) : ((void*)0
))
->length);
109 offset += krb5_princ_component(context, pr, i)(((i) < (pr)->length) ? (pr)->data + (i) : ((void*)0
))
->length;
110 }
111 return 0;
112}
113
114void krb5int_c_free_keyblock_contents(krb5_context context,
115 register krb5_keyblock *key);
116
117/*
118 * Generate a krb5_key_data set by encrypting keys according to
119 * enctype/salttype preferences
120 */
121krb5_error_code ipa_krb5_generate_key_data(krb5_context krbctx,
122 krb5_principal principal,
123 krb5_data pwd, int kvno,
124 krb5_keyblock *kmkey,
125 int num_encsalts,
126 krb5_key_salt_tuple *encsalts,
127 int *_num_keys,
128 krb5_key_data **_keys)
129{
130 krb5_error_code kerr;
131 krb5_key_data *keys;
132 int num_keys;
133 int i;
134
135 if ((pwd.data != NULL((void*)0)) && (pwd.length > IPAPWD_PASSWORD_MAX_LEN1000)) {
136 kerr = E2BIG7;
137 krb5_set_error_message(krbctx, kerr, "%s",
138 ipapwd_password_max_len_errmsg);
139 return kerr;
140 }
141
142 num_keys = num_encsalts;
143 keys = calloc(num_keys, sizeof(krb5_key_data));
144 if (!keys) {
145 return ENOMEM12;
146 }
147
148 for (i = 0; i < num_keys; i++) {
149 krb5_keyblock key;
150 krb5_data salt;
151 krb5_octet *ptr;
152 krb5_data plain;
153 krb5_enc_data cipher;
154 krb5_int16 t;
155 size_t len;
156
157 salt.data = NULL((void*)0);
158
159 keys[i].key_data_ver = 2; /* we always have a salt */
160 keys[i].key_data_kvno = kvno;
161
162 switch (encsalts[i].ks_salttype) {
163
164 case KRB5_KDB_SALTTYPE_ONLYREALM3:
165
166 if (!principal->realm.data) {
167 kerr = EINVAL22;
168 goto done;
169 }
170 salt.length = principal->realm.length;
171 salt.data = malloc(salt.length);
172 if (!salt.data) {
173 kerr = ENOMEM12;
174 goto done;
175 }
176 memcpy(salt.data, principal->realm.data, salt.length);
177 break;
178
179 case KRB5_KDB_SALTTYPE_NOREALM2:
180
181 kerr = ipa_krb5_principal2salt_norealm(krbctx, principal, &salt);
182 if (kerr) {
183 goto done;
184 }
185 break;
186
187 case KRB5_KDB_SALTTYPE_NORMAL0:
188
189 kerr = krb5_principal2salt(krbctx, principal, &salt);
190 if (kerr) {
191 goto done;
192 }
193 break;
194
195 case KRB5_KDB_SALTTYPE_SPECIAL4:
196
197 kerr = ipa_get_random_salt(krbctx, &salt);
198 if (kerr) {
199 goto done;
200 }
201 break;
202
203 case KRB5_KDB_SALTTYPE_V41:
204 salt.length = 0;
205 break;
206
207 case KRB5_KDB_SALTTYPE_AFS35:
208
209 if (!principal->realm.data) {
210 kerr = EINVAL22;
211 goto done;
212 }
213 salt.data = strndup((char *)principal->realm.data,
214 principal->realm.length);
215 if (!salt.data) {
216 kerr = ENOMEM12;
217 goto done;
218 }
219 salt.length = SALT_TYPE_AFS_LENGTH(2147483647 *2U +1U); /* special value */
220 break;
221
222 default:
223 kerr = EINVAL22;
224 goto done;
225 }
226
227 /* need to build the key now to manage the AFS salt.length
228 * special case */
229 if (pwd.data == NULL((void*)0)) {
230 kerr = krb5_c_make_random_key(krbctx,
231 encsalts[i].ks_enctype,
232 &key);
233 } else {
234 kerr = krb5_c_string_to_key(krbctx,
235 encsalts[i].ks_enctype,
236 &pwd, &salt, &key);
237 }
238 if (kerr) {
239 krb5_free_data_contents(krbctx, &salt);
240 goto done;
241 }
242 if (salt.length == SALT_TYPE_AFS_LENGTH(2147483647 *2U +1U)) {
243 salt.length = strlen(salt.data);
244 }
245
246 kerr = krb5_c_encrypt_length(krbctx,
247 kmkey->enctype, key.length, &len);
248 if (kerr) {
249 krb5int_c_free_keyblock_contents(krbctx, &key);
250 krb5_free_data_contents(krbctx, &salt);
251 goto done;
252 }
253
254 if ((ptr = (krb5_octet *) malloc(2 + len)) == NULL((void*)0)) {
255 kerr = ENOMEM12;
256 krb5int_c_free_keyblock_contents(krbctx, &key);
257 krb5_free_data_contents(krbctx, &salt);
258 goto done;
259 }
260
261 t = htole16(key.length)__uint16_identity (key.length);
262 memcpy(ptr, &t, 2);
263
264 plain.length = key.length;
265 plain.data = (char *)key.contents;
266
267 cipher.ciphertext.length = len;
268 cipher.ciphertext.data = (char *)ptr+2;
269
270 kerr = krb5_c_encrypt(krbctx, kmkey, 0, 0, &plain, &cipher);
271 if (kerr) {
272 krb5int_c_free_keyblock_contents(krbctx, &key);
273 krb5_free_data_contents(krbctx, &salt);
274 free(ptr);
275 goto done;
276 }
277
278 /* KrbSalt */
279 keys[i].key_data_type[1] = encsalts[i].ks_salttype;
280
281 if (salt.length) {
282 keys[i].key_data_length[1] = salt.length;
283 keys[i].key_data_contents[1] = (krb5_octet *)salt.data;
284 }
285
286 /* EncryptionKey */
287 keys[i].key_data_type[0] = key.enctype;
288 keys[i].key_data_length[0] = len + 2;
289 keys[i].key_data_contents[0] = malloc(len + 2);
290 if (!keys[i].key_data_contents[0]) {
291 kerr = ENOMEM12;
292 krb5int_c_free_keyblock_contents(krbctx, &key);
293 free(ptr);
294 goto done;
295 }
296 memcpy(keys[i].key_data_contents[0], ptr, len + 2);
297
298 /* make sure we free the memory used now that we are done with it */
299 krb5int_c_free_keyblock_contents(krbctx, &key);
300 free(ptr);
301 }
302
303 *_num_keys = num_keys;
304 *_keys = keys;
305 kerr = 0;
306
307done:
308 if (kerr) {
309 ipa_krb5_free_key_data(keys, num_keys);
310 }
311
312 return kerr;
313}
314
315void ipa_krb5_free_key_data(krb5_key_data *keys, int num_keys)
316{
317 int i;
318
319 if (keys == NULL((void*)0))
320 return;
321
322 for (i = 0; i < num_keys; i++) {
323 /* try to wipe key from memory,
324 * hopefully the compiler will not optimize it away */
325 if (keys[i].key_data_length[0]) {
326 memset(keys[i].key_data_contents[0],
327 0, keys[i].key_data_length[0]);
328 }
329 free(keys[i].key_data_contents[0]);
330 free(keys[i].key_data_contents[1]);
331 }
332 free(keys);
333}
334
335/* Novell key-format scheme:
336
337 KrbKeySet ::= SEQUENCE {
338 attribute-major-vno [0] UInt16,
339 attribute-minor-vno [1] UInt16,
340 kvno [2] UInt32,
341 mkvno [3] UInt32 OPTIONAL,
342 keys [4] SEQUENCE OF KrbKey,
343 ...
344 }
345
346 KrbKey ::= SEQUENCE {
347 salt [0] KrbSalt OPTIONAL,
348 key [1] EncryptionKey,
349 s2kparams [2] OCTET STRING OPTIONAL,
350 ...
351 }
352
353 KrbSalt ::= SEQUENCE {
354 type [0] Int32,
355 salt [1] OCTET STRING OPTIONAL
356 }
357
358 EncryptionKey ::= SEQUENCE {
359 keytype [0] Int32,
360 keyvalue [1] OCTET STRING
361 }
362
363 */
364
365int ber_encode_krb5_key_data(krb5_key_data *data,
366 int numk, int mkvno,
367 struct berval **encoded)
368{
369 BerElement *be = NULL((void*)0);
370 ber_tag_t tag;
371 int ret, i;
372
373 be = ber_alloc_t(LBER_USE_DER0x01);
374 if (!be) {
375 return ENOMEM12;
376 }
377
378 tag = LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U);
379
380 ret = ber_printf(be, "{t[i]t[i]t[i]t[i]t[{",
381 tag | 0, 1, tag | 1, 1,
382 tag | 2, (ber_int_t)data[0].key_data_kvno,
383 tag | 3, (ber_int_t)mkvno, tag | 4);
384 if (ret == -1) {
385 ret = EFAULT14;
386 goto done;
387 }
388
389 for (i = 0; i < numk; i++) {
390
391 ret = ber_printf(be, "{");
392 if (ret == -1) {
393 ret = EFAULT14;
394 goto done;
395 }
396
397 if (data[i].key_data_length[1] != 0) {
398 ret = ber_printf(be, "t[{t[i]",
399 tag | 0,
400 tag | 0,
401 (ber_int_t)data[i].key_data_type[1]);
402 if (ret != -1) {
403 ret = ber_printf(be, "t[o]",
404 tag | 1,
405 data[i].key_data_contents[1],
406 (ber_len_t)data[i].key_data_length[1]);
407 }
408 if (ret != -1) {
409 ret = ber_printf(be, "}]");
410 }
411 if (ret == -1) {
412 ret = EFAULT14;
413 goto done;
414 }
415 }
416
417 ret = ber_printf(be, "t[{t[i]t[o]}]",
418 tag | 1,
419 tag | 0,
420 (ber_int_t)data[i].key_data_type[0],
421 tag | 1,
422 data[i].key_data_contents[0],
423 (ber_len_t)data[i].key_data_length[0]);
424 if (ret == -1) {
425 ret = EFAULT14;
426 goto done;
427 }
428
429 ret = ber_printf(be, "}");
430 if (ret == -1) {
431 ret = EFAULT14;
432 goto done;
433 }
434 }
435
436 ret = ber_printf(be, "}]}");
437 if (ret == -1) {
438 ret = EFAULT14;
439 goto done;
440 }
441
442 ret = ber_flatten(be, encoded);
443 if (ret == -1) {
444 ret = EFAULT14;
445 goto done;
446 }
447
448done:
449 ber_free(be, 1);
450 return ret;
451}
452
453int ber_decode_krb5_key_data(struct berval *encoded, int *m_kvno,
454 int *numk, krb5_key_data **data)
455{
456 krb5_key_data *keys = NULL((void*)0);
457 BerElement *be = NULL((void*)0);
458 void *tmp;
459 int i = 0;
460 ber_tag_t tag;
461 ber_int_t major_vno;
462 ber_int_t minor_vno;
463 ber_int_t kvno;
464 ber_int_t mkvno;
465 ber_int_t type;
466 ber_tag_t seqtag;
467 ber_len_t seqlen;
468 ber_len_t setlen;
469 ber_tag_t retag;
470 ber_tag_t opttag;
471 struct berval tval;
472 int ret;
473
474 be = ber_alloc_t(LBER_USE_DER0x01);
475 if (!be) {
476 return ENOMEM12;
477 }
478
479 /* reinit the ber element with the new val */
480 ber_init2(be, encoded, LBER_USE_DER0x01);
481
482 /* fill key_data struct with the data */
483 retag = ber_scanf(be, "{t[i]t[i]t[i]t[i]t[{",
484 &tag, &major_vno,
485 &tag, &minor_vno,
486 &tag, &kvno,
487 &tag, &mkvno,
488 &seqtag);
489 if (retag == LBER_ERROR((ber_tag_t) -1) ||
490 major_vno != 1 ||
491 minor_vno != 1 ||
492 seqtag != (LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 4)) {
493 ret = EINVAL22;
494 goto done;
495 }
496
497 retag = ber_skip_tag(be, &seqlen);
498
499 /* sequence of keys */
500 for (i = 0; retag == LBER_SEQUENCE((ber_tag_t) 0x30UL); i++) {
501
502 tmp = realloc(keys, (i + 1) * sizeof(krb5_key_data));
503 if (!tmp) {
504 ret = ENOMEM12;
505 goto done;
506 }
507 keys = tmp;
508
509 memset(&keys[i], 0, sizeof(krb5_key_data));
510
511 keys[i].key_data_kvno = kvno;
512
513 /* do we have a salt type ? (optional) */
514 retag = ber_scanf(be, "t", &opttag);
515 if (retag == LBER_ERROR((ber_tag_t) -1)) {
516 ret = EINVAL22;
517 goto done;
518 }
519 if (opttag == (LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 0)) {
520 keys[i].key_data_ver = 2;
521
522 retag = ber_scanf(be, "[l{tl[i]",
523 &seqlen, &tag, &setlen, &type);
524 if (tag != (LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 0)) {
525 ret = EINVAL22;
526 goto done;
527 }
528 keys[i].key_data_type[1] = type;
529
530 /* do we have salt data ? (optional) */
531 if (seqlen > setlen + 2) {
532 retag = ber_scanf(be, "t[o]", &tag, &tval);
533 if (retag == LBER_ERROR((ber_tag_t) -1) ||
534 tag != (LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 1)) {
535 ret = EINVAL22;
536 goto done;
537 }
538 keys[i].key_data_length[1] = tval.bv_len;
539 keys[i].key_data_contents[1] = (krb5_octet *)tval.bv_val;
540 }
541
542 retag = ber_scanf(be, "}]t", &opttag);
543 if (retag == LBER_ERROR((ber_tag_t) -1)) {
544 ret = EINVAL22;
545 goto done;
546 }
547
548 } else {
549 keys[i].key_data_ver = 1;
550 }
551
552 if (opttag != (LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 1)) {
553 ret = EINVAL22;
554 goto done;
555 }
556
557 /* get the key */
558 retag = ber_scanf(be, "[{t[i]t[o]}]", &tag, &type, &tag, &tval);
559 if (retag == LBER_ERROR((ber_tag_t) -1)) {
560 ret = EINVAL22;
561 goto done;
562 }
563 keys[i].key_data_type[0] = type;
564 keys[i].key_data_length[0] = tval.bv_len;
565 keys[i].key_data_contents[0] = (krb5_octet *)tval.bv_val;
566
567 /* check for sk2params */
568 retag = ber_peek_tag(be, &setlen);
569 if (retag == (LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 2)) {
570 /* not supported yet, skip */
571 retag = ber_scanf(be, "t[x]}", &tag);
572 } else {
573 retag = ber_scanf(be, "}");
574 }
575 if (retag == LBER_ERROR((ber_tag_t) -1)) {
576 ret = EINVAL22;
577 goto done;
578 }
579
580 retag = ber_skip_tag(be, &seqlen);
581 }
582
583 ret = 0;
584
585done:
586 ber_free(be, 0); /* internal buffer is 'encoded' */
587 if (ret) {
588 for (i -= 1; keys && i >= 0; i--) {
589 free(keys[i].key_data_contents[0]);
590 free(keys[i].key_data_contents[1]);
591 }
592 free(keys);
593 keys = NULL((void*)0);
594 mkvno = 0;
595 }
596 *m_kvno = mkvno;
597 *numk = i;
598 *data = keys;
599 return ret;
600}
601
602
603krb5_error_code parse_bval_key_salt_tuples(krb5_context kcontext,
604 const char * const *vals,
605 int n_vals,
606 krb5_key_salt_tuple **kst,
607 int *n_kst)
608{
609 krb5_error_code kerr;
610 krb5_key_salt_tuple *ks;
611 int n_ks;
612 int i;
613
614 ks = calloc(n_vals + 1, sizeof(krb5_key_salt_tuple));
615 if (!ks) {
616 return ENOMEM12;
617 }
618
619 for (i = 0, n_ks = 0; i < n_vals; i++) {
620 char *enc, *salt;
621 krb5_int32 tmpsalt;
622 krb5_enctype tmpenc;
623 krb5_boolean similar;
624 krb5_error_code krberr;
625 int j;
626
627 enc = strdup(vals[i]);
628 if (!enc) {
629 kerr = ENOMEM12;
630 goto fail;
631 }
632
633 salt = strchr(enc, ':');
634 if (!salt) {
635 free(enc);
636 continue;
637 }
638 *salt = '\0'; /* null terminate the enc type */
639 salt++; /* skip : */
640
641 krberr = krb5_string_to_enctype(enc, &tmpenc);
642 if (krberr) {
643 free(enc);
644 continue;
645 }
646
647 krberr = krb5_string_to_salttype(salt, &tmpsalt);
Value stored to 'krberr' is never read
648 for (j = 0; j < n_ks; j++) {
649 krb5_c_enctype_compare(kcontext,
650 ks[j].ks_enctype, tmpenc, &similar);
651 if (similar && (ks[j].ks_salttype == tmpsalt)) {
652 break;
653 }
654 }
655
656 if (j == n_ks) {
657 /* not found */
658 ks[j].ks_enctype = tmpenc;
659 ks[j].ks_salttype = tmpsalt;
660 n_ks++;
661 }
662
663 free(enc);
664 }
665
666 *kst = ks;
667 *n_kst = n_ks;
668
669 return 0;
670
671fail:
672 free(ks);
673 return kerr;
674}
675
676krb5_error_code filter_key_salt_tuples(krb5_context context,
677 krb5_key_salt_tuple *req, int n_req,
678 krb5_key_salt_tuple *supp, int n_supp,
679 krb5_key_salt_tuple **res, int *n_res)
680{
681 krb5_key_salt_tuple *ks = NULL((void*)0);
682 int n_ks;
683 int i, j;
684
685 ks = calloc(n_req, sizeof(krb5_key_salt_tuple));
686 if (!ks) {
687 return ENOMEM12;
688 }
689 n_ks = 0;
690
691 for (i = 0; i < n_req; i++) {
692 for (j = 0; j < n_supp; j++) {
693 if (req[i].ks_enctype == supp[j].ks_enctype &&
694 req[i].ks_salttype == supp[j].ks_salttype) {
695 break;
696 }
697 }
698 if (j < n_supp) {
699 ks[n_ks] = req[i];
700 n_ks++;
701 }
702 }
703
704 *res = ks;
705 *n_res = n_ks;
706 return 0;
707}
708
709struct berval *create_key_control(struct keys_container *keys,
710 const char *principalName)
711{
712 struct krb_key_salt *ksdata;
713 struct berval *bval;
714 BerElement *be;
715 int ret, i;
716
717 be = ber_alloc_t(LBER_USE_DER0x01);
718 if (!be) {
719 return NULL((void*)0);
720 }
721
722 ret = ber_printf(be, "{s{", principalName);
723 if (ret == -1) {
724 ber_free(be, 1);
725 return NULL((void*)0);
726 }
727
728 ksdata = keys->ksdata;
729 for (i = 0; i < keys->nkeys; i++) {
730
731 /* we set only the EncryptionKey and salt, no s2kparams */
732
733 ret = ber_printf(be, "{t[{t[i]t[o]}]",
734 (ber_tag_t)(LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 0),
735 (ber_tag_t)(LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 0),
736 (ber_int_t)ksdata[i].enctype,
737 (ber_tag_t)(LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 1),
738 (char *)ksdata[i].key.contents, (ber_len_t)ksdata[i].key.length);
739
740 if (ret == -1) {
741 ber_free(be, 1);
742 return NULL((void*)0);
743 }
744
745 if (ksdata[i].salttype == NO_SALT-1) {
746 ret = ber_printf(be, "}");
747 if (ret == -1) {
748 ber_free(be, 1);
749 return NULL((void*)0);
750 }
751 continue;
752 }
753
754 /* we have to pass a salt structure */
755 ret = ber_printf(be, "t[{t[i]t[o]}]}",
756 (ber_tag_t)(LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 1),
757 (ber_tag_t)(LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 0),
758 (ber_int_t)ksdata[i].salttype,
759 (ber_tag_t)(LBER_CONSTRUCTED((ber_tag_t) 0x20U) | LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | 1),
760 (char *)ksdata[i].salt.data, (ber_len_t)ksdata[i].salt.length);
761
762 if (ret == -1) {
763 ber_free(be, 1);
764 return NULL((void*)0);
765 }
766 }
767
768 ret = ber_printf(be, "}}");
769 if (ret == -1) {
770 ber_free(be, 1);
771 return NULL((void*)0);
772 }
773
774 ret = ber_flatten(be, &bval);
775 if (ret == -1) {
776 ber_free(be, 1);
777 return NULL((void*)0);
778 }
779
780 ber_free(be, 1);
781 return bval;
782}
783
784void free_keys_contents(krb5_context krbctx, struct keys_container *keys)
785{
786 struct krb_key_salt *ksdata;
787 int i;
788
789 ksdata = keys->ksdata;
790 for (i = 0; i < keys->nkeys; i++) {
791 krb5_free_keyblock_contents(krbctx, &ksdata[i].key);
792 krb5_free_data_contents(krbctx, &ksdata[i].salt);
793 }
794 free(ksdata);
795
796 keys->ksdata = NULL((void*)0);
797 keys->nkeys = 0;
798}
799
800int ipa_string_to_enctypes(const char *str, struct krb_key_salt **encsalts,
801 int *num_encsalts, char **err_msg)
802{
803 struct krb_key_salt *ksdata;
804 krb5_error_code krberr;
805 char *tmp, *t;
806 int count;
807 int num;
808
809 *err_msg = NULL((void*)0);
810
811 tmp = strdup(str);
812 if (!tmp) {
813 *err_msg = _("Out of memory\n")gettext("Out of memory\n");
814 return ENOMEM12;
815 }
816
817 /* count */
818 count = 0;
819 for (t = tmp; t; t = strchr(t, ',')) {
820 count++;
821 t++;
822 }
823 count++; /* count the last one that is 0 terminated instead */
824
825 /* at the end we will have at most count entries + 1 terminating */
826 ksdata = calloc(count + 1, sizeof(struct krb_key_salt));
827 if (!ksdata) {
828 *err_msg = _("Out of memory\n")gettext("Out of memory\n");
829 free(tmp);
830 return ENOMEM12;
831 }
832
833 num = 0;
834 t = tmp;
835 for (int i = 0; i < count; i++) {
836 char *p, *q;
837
838 p = strchr(t, ',');
839 if (p) *p = '\0';
840
841 q = strchr(t, ':');
842 if (q) *q++ = '\0';
843
844 krberr = krb5_string_to_enctype(t, &ksdata[num].enctype);
845 if (krberr) {
846 *err_msg = _("Warning unrecognized encryption type.\n")gettext("Warning unrecognized encryption type.\n");
847 if (p) t = p + 1;
848 continue;
849 }
850 if (p) t = p + 1;
851
852 if (!q) {
853 ksdata[num].salttype = KRB5_KDB_SALTTYPE_NORMAL0;
854 num++;
855 continue;
856 }
857
858 krberr = krb5_string_to_salttype(q, &ksdata[num].salttype);
859 if (krberr) {
860 *err_msg = _("Warning unrecognized salt type.\n")gettext("Warning unrecognized salt type.\n");
861 continue;
862 }
863
864 num++;
865 }
866
867 *num_encsalts = num;
868 *encsalts = ksdata;
869 free(tmp);
870 return 0;
871}
872
873/* Determines Encryption and Salt types,
874 * allocates key_salt data storage,
875 * filters out equivalent encodings,
876 * returns 0 if no enctypes available, >0 if enctypes are available */
877static int prep_ksdata(krb5_context krbctx, const char *str,
878 struct keys_container *keys,
879 char **err_msg)
880{
881 struct krb_key_salt *ksdata;
882 krb5_error_code krberr;
883 int n, i, j, nkeys;
884
885 *err_msg = NULL((void*)0);
886
887 if (str == NULL((void*)0)) {
888 krb5_enctype *ktypes;
889
890 krberr = krb5_get_permitted_enctypes(krbctx, &ktypes);
891 if (krberr) {
892 *err_msg = _("No system preferred enctypes ?!\n")gettext("No system preferred enctypes ?!\n");
893 return 0;
894 }
895
896 for (n = 0; ktypes[n]; n++) /* count */ ;
897
898 ksdata = calloc(n + 1, sizeof(struct krb_key_salt));
899 if (NULL((void*)0) == ksdata) {
900 *err_msg = _("Out of memory!?\n")gettext("Out of memory!?\n");
901 return 0;
902 }
903
904 for (i = 0; i < n; i++) {
905 ksdata[i].enctype = ktypes[i];
906 ksdata[i].salttype = KRB5_KDB_SALTTYPE_NORMAL0;
907 }
908
909 ipa_krb5_free_ktypes(krbctx, ktypes);
910
911 nkeys = i;
912
913 } else {
914 krberr = ipa_string_to_enctypes(str, &ksdata, &nkeys, err_msg);
915 if (krberr) {
916 return 0;
917 }
918 }
919
920 /* Check we don't already have a key with a similar encoding,
921 * it would just produce redundant data and this is what the
922 * MIT code do anyway */
923
924 for (i = 0, n = 0; i < nkeys; i++ ) {
925 krb5_boolean similar = 0;
926
927 for (j = 0; j < i; j++) {
928 krberr = krb5_c_enctype_compare(krbctx,
929 ksdata[j].enctype,
930 ksdata[i].enctype,
931 &similar);
932 if (krberr) {
933 free_keys_contents(krbctx, keys);
934 free(ksdata);
935 *err_msg = _("Enctype comparison failed!\n")gettext("Enctype comparison failed!\n");
936 return 0;
937 }
938 if (similar &&
939 (ksdata[j].salttype == ksdata[i].salttype)) {
940 break;
941 }
942 }
943 if (j < i) {
944 /* redundant encoding, remove it, and shift others */
945 int x;
946 for (x = i; x < nkeys-1; x++) {
947 ksdata[x].enctype = ksdata[x+1].enctype;
948 ksdata[x].salttype = ksdata[x+1].salttype;
949 }
950 continue;
951 }
952 /* count only confirmed enc/salt tuples */
953 n++;
954 }
955
956 keys->nkeys = n;
957 keys->ksdata = ksdata;
958
959 return n;
960}
961
962int create_keys(krb5_context krbctx,
963 krb5_principal princ,
964 char *password,
965 const char *enctypes_string,
966 struct keys_container *keys,
967 char **err_msg)
968{
969 struct krb_key_salt *ksdata;
970 krb5_error_code krberr;
971 krb5_data key_password;
972 krb5_data *realm = NULL((void*)0);
973 int i, nkeys;
974 int ret;
975
976 *err_msg = NULL((void*)0);
977
978 ret = prep_ksdata(krbctx, enctypes_string, keys, err_msg);
979 if (ret == 0) return 0;
980
981 ksdata = keys->ksdata;
982 nkeys = keys->nkeys;
983
984 if (password) {
985 key_password.data = password;
986 key_password.length = strlen(password);
987 if (key_password.length > IPAPWD_PASSWORD_MAX_LEN1000) {
988 *err_msg = _("Password is too long!\n")gettext("Password is too long!\n");
989 return 0;
990 }
991
992 realm = krb5_princ_realm(krbctx, princ)(&(princ)->realm);
993 }
994
995 for (i = 0; i < nkeys; i++) {
996 krb5_data *salt;
997
998 if (!password) {
999 /* cool, random keys */
1000 krberr = krb5_c_make_random_key(krbctx,
1001 ksdata[i].enctype,
1002 &ksdata[i].key);
1003 if (krberr) {
1004 *err_msg = _("Failed to create random key!\n")gettext("Failed to create random key!\n");
1005 return 0;
1006 }
1007 /* set the salt to NO_SALT as the key was random */
1008 ksdata[i].salttype = NO_SALT-1;
1009 continue;
1010 }
1011
1012 /* Make keys using password and required salt */
1013 switch (ksdata[i].salttype) {
1014 case KRB5_KDB_SALTTYPE_ONLYREALM3:
1015 krberr = krb5_copy_data(krbctx, realm, &salt);
1016 if (krberr) {
1017 *err_msg = _("Failed to create key!\n")gettext("Failed to create key!\n");
1018 return 0;
1019 }
1020
1021 ksdata[i].salt.length = salt->length;
1022 ksdata[i].salt.data = malloc(salt->length);
1023 if (!ksdata[i].salt.data) {
1024 *err_msg = _("Out of memory!\n")gettext("Out of memory!\n");
1025 return 0;
1026 }
1027 memcpy(ksdata[i].salt.data, salt->data, salt->length);
1028 krb5_free_data(krbctx, salt);
1029 break;
1030
1031 case KRB5_KDB_SALTTYPE_NOREALM2:
1032 krberr = ipa_krb5_principal2salt_norealm(krbctx, princ,
1033 &ksdata[i].salt);
1034 if (krberr) {
1035 *err_msg = _("Failed to create key!\n")gettext("Failed to create key!\n");
1036 return 0;
1037 }
1038 break;
1039
1040 case KRB5_KDB_SALTTYPE_NORMAL0:
1041 krberr = krb5_principal2salt(krbctx, princ, &ksdata[i].salt);
1042 if (krberr) {
1043 *err_msg = _("Failed to create key!\n")gettext("Failed to create key!\n");
1044 return 0;
1045 }
1046 break;
1047
1048 /* no KRB5_KDB_SALTTYPE_V4, we do not support krb v4 */
1049
1050 case KRB5_KDB_SALTTYPE_AFS35:
1051 /* Comment from MIT sources:
1052 * * Why do we do this? Well, the afs_mit_string_to_key
1053 * * needs to use strlen, and the realm is not NULL
1054 * * terminated....
1055 */
1056 ksdata[i].salt.data = (char *)malloc(realm->length + 1);
1057 if (NULL((void*)0) == ksdata[i].salt.data) {
1058 *err_msg = _("Out of memory!\n")gettext("Out of memory!\n");
1059 return 0;
1060 }
1061 memcpy((char *)ksdata[i].salt.data,
1062 (char *)realm->data, realm->length);
1063 ksdata[i].salt.data[realm->length] = '\0';
1064 /* AFS uses a special length (UGLY) */
1065 ksdata[i].salt.length = SALT_TYPE_AFS_LENGTH(2147483647 *2U +1U);
1066 break;
1067
1068 default:
1069 *err_msg = _("Bad or unsupported salt type.\n")gettext("Bad or unsupported salt type.\n");
1070/* FIXME:
1071 fprintf(stderr, _("Bad or unsupported salt type (%d)!\n"),
1072 ksdata[i].salttype);
1073*/
1074 return 0;
1075 }
1076
1077 krberr = krb5_c_string_to_key(krbctx,
1078 ksdata[i].enctype,
1079 &key_password,
1080 &ksdata[i].salt,
1081 &ksdata[i].key);
1082 if (krberr) {
1083 *err_msg = _("Failed to create key!\n")gettext("Failed to create key!\n");
1084 return 0;
1085 }
1086
1087 /* set back salt length to real value if AFS3 */
1088 if (ksdata[i].salttype == KRB5_KDB_SALTTYPE_AFS35) {
1089 ksdata[i].salt.length = realm->length;
1090 }
1091 }
1092
1093 return nkeys;
1094}
1095
1096/* in older versions of libkrb5 the krb5_salttype_to_string() function is
1097 * faulty and returns strings that do not match the expected format.
1098 * Later version of krb5 were fixed to return the proper string.
1099 * Do lazy detection the first time the function is invoked to determine
1100 * if we can use the library provided function or if we have to use a
1101 * fallback map which includes the salt types known up to krb5 1.12 (the
1102 * fault is fixed upstream in 1.13). */
1103static int ipa_salttype_to_string(krb5_int32 salttype,
1104 char *buffer, size_t buflen)
1105{
1106 static int faulty_function = -1;
1107
1108 static const struct {
1109 krb5_int32 salttype;
1110 const char *name;
1111 } fallback_map[] = {
1112 { KRB5_KDB_SALTTYPE_NORMAL0, "normal" },
1113 { KRB5_KDB_SALTTYPE_V41, "v4" },
1114 { KRB5_KDB_SALTTYPE_NOREALM2, "norealm" },
1115 { KRB5_KDB_SALTTYPE_ONLYREALM3, "onlyrealm" },
1116 { KRB5_KDB_SALTTYPE_SPECIAL4, "special" },
1117 { KRB5_KDB_SALTTYPE_AFS35, "afs3" },
1118 { -1, NULL((void*)0) }
1119 };
1120
1121 if (faulty_function == -1) {
1122 /* haven't checked yet, let's find out */
1123 char testbuf[100];
1124 size_t len = 100;
1125 int ret;
1126
1127 ret = krb5_salttype_to_string(KRB5_KDB_SALTTYPE_NORMAL0, testbuf, len);
1128 if (ret) return ret;
1129
1130 if (strcmp(buffer, "normal") == 0) {
1131 faulty_function = 0;
1132 } else {
1133 faulty_function = 1;
1134 }
1135 }
1136
1137 if (faulty_function == 0) {
1138 return krb5_salttype_to_string(salttype, buffer, buflen);
1139 } else {
1140 size_t len;
1141 int i;
1142 for (i = 0; fallback_map[i].name != NULL((void*)0); i++) {
1143 if (salttype == fallback_map[i].salttype) break;
1144 }
1145 if (fallback_map[i].name == NULL((void*)0)) return EINVAL22;
1146
1147 len = strlen(fallback_map[i].name);
1148 if (len >= buflen) return ENOMEM12;
1149
1150 memcpy(buffer, fallback_map[i].name, len + 1);
1151 return 0;
1152 }
1153}
1154
1155int ipa_kstuples_to_string(krb5_key_salt_tuple *kst, int n_kst, char **str)
1156{
1157 char *buf = NULL((void*)0);
1158 char *tmp;
1159 int buf_avail;
1160 int buf_size;
1161 int buf_cur;
1162 int len;
1163 int ret = 0;
1164 int i;
1165
1166 buf_size = 512; /* should be enough for the default supported enctypes */
1167 buf = malloc(buf_size);
1168 if (!buf) {
1169 ret = ENOMEM12;
1170 goto done;
1171 }
1172
1173 buf_cur = 0;
1174 for (i = 0; i < n_kst; i++) {
1175 /* grow if too tight */
1176 if (ret == ENOMEM12) {
1177 buf_size *= 2;
1178 /* hard limit at 8k, do not eat all memory by mistake */
1179 if (buf_size > 8192) goto done;
1180 tmp = realloc(buf, buf_size);
1181 if (!tmp) {
1182 ret = ENOMEM12;
1183 goto done;
1184 }
1185 buf = tmp;
1186 }
1187
1188 buf_avail = buf_size - buf_cur;
1189 len = 0;
1190
1191 /* append separator if necessary */
1192 if (buf_cur > 0) {
1193 buf[buf_cur] = ',';
1194 len++;
1195 }
1196
1197 ret = krb5_enctype_to_name(kst[i].ks_enctype, 0,
1198 &buf[buf_cur + len], buf_avail - len);
1199 if (ret == ENOMEM12) {
1200 i--;
1201 continue;
1202 } else if (ret != 0) {
1203 goto done;
1204 }
1205
1206 len += strlen(&buf[buf_cur + len]);
1207 buf[buf_cur + len] = ':';
1208 len++;
1209
1210 ret = ipa_salttype_to_string(kst[i].ks_salttype,
1211 &buf[buf_cur + len], buf_avail - len);
1212 if (ret == ENOMEM12) {
1213 i--;
1214 continue;
1215 } else if (ret != 0) {
1216 goto done;
1217 }
1218
1219 len += strlen(&buf[buf_cur + len]);
1220
1221 if (buf_avail - len < 2) {
1222 ret = ENOMEM12;
1223 i--;
1224 continue;
1225 }
1226
1227 buf_cur += len;
1228 }
1229
1230 buf[buf_cur] = '\0';
1231 *str = buf;
1232 ret = 0;
1233
1234done:
1235 if (ret) {
1236 free(buf);
1237 }
1238 return ret;
1239}