Bug Summary

File:client/ipa-getkeytab.c
Warning:line 982, column 11
2nd function call argument is an uninitialized value

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-getkeytab.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 static -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 . -I ../util -I ../asn1 -D PREFIX="/usr/local" -D BINDIR="/usr/local/bin" -D LIBDIR="/usr/local/lib" -D LIBEXECDIR="/usr/local/libexec" -D DATADIR="/usr/local/share" -D LOCALEDIR="/usr/local/share/locale" -D IPACONFFILE="/usr/local/etc/ipa/default.conf" -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 -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/client -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-getkeytab.c
1/* Authors: Simo Sorce <ssorce@redhat.com>
2 *
3 * Copyright (C) 2007 Red Hat
4 * see file 'COPYING' for use and warranty information
5 *
6 * This program is free software you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#define _GNU_SOURCE
21
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <fcntl.h>
25#include <sys/time.h>
26#include <unistd.h>
27#include <stdio.h>
28#include <stdarg.h>
29#include <stdlib.h>
30#include <stdint.h>
31#include <stdbool.h>
32#include <string.h>
33#include <errno(*__errno_location ()).h>
34#include <time.h>
35#include <krb5.h>
36#include <ldap.h>
37#include <sasl/sasl.h>
38#include <popt.h>
39#include <ini_configobj.h>
40
41#include "config.h"
42
43#include "ipa_krb5.h"
44#include "ipa_asn1.h"
45#include "ipa-client-common.h"
46#include "ipa_ldap.h"
47
48
49static int check_sasl_mech(const char *mech)
50{
51 int i;
52 int ret = 1;
53 const char *supported_sasl_mechs[] = {
54 LDAP_SASL_EXTERNAL"EXTERNAL",
55 LDAP_SASL_GSSAPI"GSSAPI",
56 NULL((void*)0)
57 };
58
59 for (i=0; NULL((void*)0) != supported_sasl_mechs[i]; i++) {
60 if (strcmp(mech, supported_sasl_mechs[i]) == 0) {
61 return 0;
62 }
63 }
64 return ret;
65}
66
67static int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
68{
69 sasl_interact_t *in = NULL((void*)0);
70 int ret = LDAP_OTHER0x50;
71 krb5_principal princ = (krb5_principal)priv_data;
72 krb5_context krbctx;
73 char *outname = NULL((void*)0);
74 krb5_error_code krberr;
75
76 if (!ld) return LDAP_PARAM_ERROR(-9);
77
78 for (in = sit; in && in->id != SASL_CB_LIST_END0; in++) {
79 switch(in->id) {
80 case SASL_CB_USER0x4001:
81 krberr = krb5_init_context(&krbctx);
82
83 if (krberr) {
84 fprintf(stderrstderr, _("Kerberos context initialization failed: %1$s (%2$d)\n")gettext("Kerberos context initialization failed: %1$s (%2$d)\n"
)
,
85 error_message(krberr), krberr);
86 in->result = NULL((void*)0);
87 in->len = 0;
88 ret = LDAP_LOCAL_ERROR(-2);
89 break;
90 }
91
92 krberr = krb5_unparse_name(krbctx, princ, &outname);
93
94 if (krberr) {
95 fprintf(stderrstderr, _("Unable to parse principal: %1$s (%2$d)\n")gettext("Unable to parse principal: %1$s (%2$d)\n"),
96 error_message(krberr), krberr);
97 in->result = NULL((void*)0);
98 in->len = 0;
99 ret = LDAP_LOCAL_ERROR(-2);
100 break;
101 }
102
103 in->result = outname;
104 in->len = strlen(outname);
105 ret = LDAP_SUCCESS0x00;
106
107 krb5_free_context(krbctx);
108
109 break;
110 case SASL_CB_GETREALM(0x4008):
111 in->result = princ->realm.data;
112 in->len = princ->realm.length;
113 ret = LDAP_SUCCESS0x00;
114 break;
115 default:
116 in->result = NULL((void*)0);
117 in->len = 0;
118 ret = LDAP_OTHER0x50;
119 }
120 }
121 return ret;
122}
123
124int filter_keys(krb5_context krbctx, struct keys_container *keys,
125 ber_int_t *enctypes)
126{
127 struct krb_key_salt *ksdata;
128 int i, j, n;
129
130 n = keys->nkeys;
131 ksdata = keys->ksdata;
132 for (i = 0; i < n; i++) {
133 if (ksdata[i].enctype == enctypes[i]) continue;
134 if (enctypes[i] == 0) {
135 /* remove unsupported one */
136 krb5_free_keyblock_contents(krbctx, &ksdata[i].key);
137 krb5_free_data_contents(krbctx, &ksdata[i].salt);
138 for (j = i; j < n-1; j++) {
139 ksdata[j] = ksdata[j + 1];
140 enctypes[j] = enctypes[j + 1];
141 }
142 n--;
143 /* new key has been moved to this position, make sure
144 * we do not skip it, by neutralizing next i increment */
145 i--;
146 }
147 }
148
149 if (n == 0) {
150 fprintf(stderrstderr, _("No keys accepted by KDC\n")gettext("No keys accepted by KDC\n"));
151 return 0;
152 }
153
154 keys->nkeys = n;
155 return n;
156}
157
158static int ipa_server_to_uri(const char *servername, const char *mech,
159 char **ldap_uri)
160{
161 char *url = NULL((void*)0);
162 int url_len = 0;
163 int port = 389;
164
165 url_len = asprintf(&url, "%s%s:%d", SCHEMA_LDAP"ldap://", servername, port);
166
167 if (url_len == -1) {
168 fprintf(stderrstderr, _("Out of memory \n")gettext("Out of memory \n"));
169 return LDAP_NO_MEMORY(-10);
170 }
171 *ldap_uri = url;
172 return 0;
173}
174
175static int ipa_ldap_bind(const char *ldap_uri, krb5_principal bind_princ,
176 const char *bind_dn, const char *bind_pw,
177 const char *mech, const char *ca_cert_file,
178 LDAP **_ld)
179{
180 struct berval bv;
181 LDAP *ld;
182 int ret;
183
184 /* TODO: support referrals ? */
185 ret = ipa_ldap_init(&ld, ldap_uri);
186 if (ret != LDAP_SUCCESS0x00) {
187 return ret;
188 }
189
190 if (ld == NULL((void*)0)) {
191 fprintf(stderrstderr, _("Unable to initialize ldap library!\n")gettext("Unable to initialize ldap library!\n"));
192 return LDAP_OPERATIONS_ERROR0x01;
193 }
194
195 ret = ipa_tls_ssl_init(ld, ldap_uri, ca_cert_file);
196 if (ret != LDAP_OPT_SUCCESS0) {
197 goto done;
198 }
199
200 if (bind_dn) {
201 bv.bv_val = discard_const(bind_pw)((void *)((uintptr_t)(bind_pw)));
202 bv.bv_len = strlen(bind_pw);
203
204 ret = ldap_sasl_bind_s(ld, bind_dn, LDAP_SASL_SIMPLE((char*)0),
205 &bv, NULL((void*)0), NULL((void*)0), NULL((void*)0));
206 if (ret != LDAP_SUCCESS0x00) {
207 ipa_ldap_error(ld, ret, _("Simple bind failed\n")gettext("Simple bind failed\n"));
208 goto done;
209 }
210 } else {
211 if (strcmp(mech, LDAP_SASL_EXTERNAL"EXTERNAL") == 0) {
212 ret = ldap_sasl_bind_s(ld, NULL((void*)0), LDAP_SASL_EXTERNAL"EXTERNAL",
213 NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
214 } else {
215 ret = ldap_sasl_interactive_bind_s(ld, NULL((void*)0), LDAP_SASL_GSSAPI"GSSAPI",
216 NULL((void*)0), NULL((void*)0), LDAP_SASL_QUIET2U,
217 ldap_sasl_interact, bind_princ);
218 }
219
220 if (ret != LDAP_SUCCESS0x00) {
221 ipa_ldap_error(ld, ret, _("SASL Bind failed\n")gettext("SASL Bind failed\n"));
222 goto done;
223 }
224 }
225
226 ret = LDAP_SUCCESS0x00;
227
228done:
229 if (ret != LDAP_SUCCESS0x00) {
230 if (ld) ldap_unbind_ext(ld, NULL((void*)0), NULL((void*)0));
231 } else {
232 *_ld = ld;
233 }
234 return ret;
235}
236
237static int ipa_ldap_extended_op(LDAP *ld, const char *reqoid,
238 struct berval *control,
239 LDAPControl ***srvctrl)
240{
241 struct berval *retdata = NULL((void*)0);
242 LDAPMessage *res = NULL((void*)0);
243 char *retoid = NULL((void*)0);
244 struct timeval tv;
245 char *err = NULL((void*)0);
246 int msgid;
247 int ret, rc;
248
249 ret = ldap_extended_operation(ld, reqoid, control,
250 NULL((void*)0), NULL((void*)0), &msgid);
251 if (ret != LDAP_SUCCESS0x00) {
252 fprintf(stderrstderr, _("Operation failed: %s\n")gettext("Operation failed: %s\n"), ldap_err2string(ret));
253 return ret;
254 }
255
256 /* wait max 100 secs for the answer */
257 tv.tv_sec = 100;
258 tv.tv_usec = 0;
259 ret = ldap_result(ld, msgid, 1, &tv, &res);
260 if (ret == -1) {
261 fprintf(stderrstderr, _("Failed to get result: %s\n")gettext("Failed to get result: %s\n"), ldap_err2string(ret));
262 goto done;
263 }
264 else if (res == NULL((void*)0)) {
265 fprintf(stderrstderr, _("Timeout exceeded.")gettext("Timeout exceeded."));
266 goto done;
267 }
268
269 ret = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
270 if (ret != LDAP_SUCCESS0x00) {
271 fprintf(stderrstderr, _("Failed to parse extended result: %s\n")gettext("Failed to parse extended result: %s\n"),
272 ldap_err2string(ret));
273 goto done;
274 }
275
276 ret = ldap_parse_result(ld, res, &rc, NULL((void*)0), &err, NULL((void*)0), srvctrl, 0);
277 if (ret != LDAP_SUCCESS0x00 || rc != LDAP_SUCCESS0x00) {
278 fprintf(stderrstderr, _("Failed to parse result: %s\n")gettext("Failed to parse result: %s\n"),
279 err ? err : ldap_err2string(ret));
280 if (ret == LDAP_SUCCESS0x00) ret = rc;
281 goto done;
282 }
283
284done:
285 if (err) ldap_memfree(err);
286 if (res) ldap_msgfree(res);
287 return ret;
288}
289
290static int find_control_data(LDAPControl **list, const char *repoid,
291 struct berval *data)
292{
293 LDAPControl *control = NULL((void*)0);
294 int i;
295
296 if (!list) {
297 fprintf(stderrstderr, _("Missing reply control list!\n")gettext("Missing reply control list!\n"));
298 return LDAP_OPERATIONS_ERROR0x01;
299 }
300
301 for (i = 0; list[i]; i++) {
302 if (strcmp(list[i]->ldctl_oid, repoid) == 0) {
303 control = list[i];
304 }
305 }
306 if (!control) {
307 fprintf(stderrstderr, _("Missing reply control!\n")gettext("Missing reply control!\n"));
308 return LDAP_OPERATIONS_ERROR0x01;
309 }
310
311 *data = control->ldctl_value;
312 return LDAP_SUCCESS0x00;
313}
314
315static BerElement *get_control_data(LDAPControl **list, const char *repoid)
316{
317 struct berval data;
318 int ret;
319
320 ret = find_control_data(list, repoid, &data);
321 if (ret != LDAP_SUCCESS0x00) return NULL((void*)0);
322
323 return ber_init(&data);
324}
325
326static int ldap_set_keytab(krb5_context krbctx,
327 const char *ldap_uri,
328 const char *principal_name,
329 krb5_principal princ,
330 const char *binddn,
331 const char *bindpw,
332 const char *mech,
333 const char *ca_cert_file,
334 struct keys_container *keys)
335{
336 LDAP *ld = NULL((void*)0);
337 BerElement *sctrl = NULL((void*)0);
338 struct berval *control = NULL((void*)0);
339 LDAPControl **srvctrl = NULL((void*)0);
340 int ret;
341 int kvno, i;
342 ber_tag_t rtag;
343 ber_int_t *encs = NULL((void*)0);
344 int successful_keys = 0;
345
346 /* cant' return more than nkeys, sometimes less */
347 encs = calloc(keys->nkeys + 1, sizeof(ber_int_t));
348 if (!encs) {
349 fprintf(stderrstderr, _("Out of Memory!\n")gettext("Out of Memory!\n"));
350 return 0;
351 }
352
353 /* build password change control */
354 control = create_key_control(keys, principal_name);
355 if (!control) {
356 fprintf(stderrstderr, _("Failed to create control!\n")gettext("Failed to create control!\n"));
357 goto error_out;
358 }
359
360 ret = ipa_ldap_bind(ldap_uri, princ, binddn, bindpw, mech, ca_cert_file, &ld);
361 if (ret != LDAP_SUCCESS0x00) {
362 fprintf(stderrstderr, _("Failed to bind to server!\n")gettext("Failed to bind to server!\n"));
363 goto error_out;
364 }
365
366 /* perform password change */
367 ret = ipa_ldap_extended_op(ld, KEYTAB_SET_OID"2.16.840.1.113730.3.8.10.1", control, &srvctrl);
368 if (ret != LDAP_SUCCESS0x00) {
369 fprintf(stderrstderr, _("Failed to get keytab!\n")gettext("Failed to get keytab!\n"));
370 goto error_out;
371 }
372
373 ber_bvfree(control);
374 control = NULL((void*)0);
375
376 sctrl = get_control_data(srvctrl, KEYTAB_RET_OID"2.16.840.1.113730.3.8.10.2");
377 if (!sctrl) {
378 fprintf(stderrstderr, _("ber_init() failed, Invalid control ?!\n")gettext("ber_init() failed, Invalid control ?!\n"));
379 goto error_out;
380 }
381
382 /* Format of response
383 *
384 * KeytabGetRequest ::= SEQUENCE {
385 * new_kvno Int32
386 * SEQUENCE OF KeyTypes
387 * }
388 *
389 * * List of accepted enctypes *
390 * KeyTypes ::= SEQUENCE {
391 * enctype Int32
392 * }
393 */
394
395 rtag = ber_scanf(sctrl, "{i{", &kvno);
396 if (rtag == LBER_ERROR((ber_tag_t) -1)) {
397 fprintf(stderrstderr, _("ber_scanf() failed, unable to find kvno ?!\n")gettext("ber_scanf() failed, unable to find kvno ?!\n"));
398 goto error_out;
399 }
400
401 for (i = 0; i < keys->nkeys; i++) {
402 ret = ber_scanf(sctrl, "{i}", &encs[i]);
403 if (ret == LBER_ERROR((ber_tag_t) -1)) {
404 char enc[79]; /* fit std terminal or truncate */
405 krb5_error_code krberr;
406 krberr = krb5_enctype_to_string(
407 keys->ksdata[i].enctype, enc, 79);
408 if (krberr) {
409 fprintf(stderrstderr, _("Failed to retrieve "gettext("Failed to retrieve " "encryption type type #%d\n")
410 "encryption type type #%d\n")gettext("Failed to retrieve " "encryption type type #%d\n"),
411 keys->ksdata[i].enctype);
412 } else {
413 fprintf(stderrstderr, _("Failed to retrieve "gettext("Failed to retrieve " "encryption type %1$s (#%2$d)\n"
)
414 "encryption type %1$s (#%2$d)\n")gettext("Failed to retrieve " "encryption type %1$s (#%2$d)\n"
)
,
415 enc, keys->ksdata[i].enctype);
416 }
417 } else {
418 successful_keys++;
419 }
420 }
421
422 if (successful_keys == 0) {
423 fprintf(stderrstderr, _("Failed to retrieve any keys")gettext("Failed to retrieve any keys"));
424 goto error_out;
425 }
426
427 ret = filter_keys(krbctx, keys, encs);
428 if (ret == 0) goto error_out;
429
430 ber_free(sctrl, 1);
431 ldap_controls_free(srvctrl);
432 ldap_unbind_ext(ld, NULL((void*)0), NULL((void*)0));
433 free(encs);
434 return kvno;
435
436error_out:
437 if (sctrl) ber_free(sctrl, 1);
438 if (srvctrl) ldap_controls_free(srvctrl);
439 if (ld) ldap_unbind_ext(ld, NULL((void*)0), NULL((void*)0));
440 if (control) ber_bvfree(control);
441 free(encs);
442 return -1;
443}
444
445/* use asn1c generated code to fill up control */
446static struct berval *create_getkeytab_control(const char *svc_princ, bool_Bool gen,
447 const char *password,
448 struct krb_key_salt *encsalts,
449 int num_encsalts)
450{
451 struct berval *result = NULL((void*)0);
452 void *buffer = NULL((void*)0);
453 size_t buflen;
454 long ets[num_encsalts];
455 bool_Bool ret;
456 int i;
457
458 if (gen) {
459 for (i = 0; i < num_encsalts; i++) {
460 ets[i] = encsalts[i].enctype;
461 }
462 }
463 ret = ipaasn1_enc_getkt(gen, svc_princ,
464 password, ets, num_encsalts,
465 &buffer, &buflen);
466 if (!ret) goto done;
467
468 result = malloc(sizeof(struct berval));
469 if (!result) goto done;
470
471 result->bv_val = buffer;
472 result->bv_len = buflen;
473
474done:
475 if (result == NULL((void*)0)) {
476 if (buffer) {
477 free(buffer);
478 }
479 }
480 return result;
481}
482
483#define GK_REPLY_TAG(((ber_tag_t) 0x80U) | ((ber_tag_t) 0x20U) | 2) (LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | LBER_CONSTRUCTED((ber_tag_t) 0x20U) | 2)
484#define GKREP_KEY_TAG(((ber_tag_t) 0x80U) | ((ber_tag_t) 0x20U) | 0) (LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | LBER_CONSTRUCTED((ber_tag_t) 0x20U) | 0)
485#define GKREP_SALT_TAG(((ber_tag_t) 0x80U) | ((ber_tag_t) 0x20U) | 1) (LBER_CLASS_CONTEXT((ber_tag_t) 0x80U) | LBER_CONSTRUCTED((ber_tag_t) 0x20U) | 1)
486
487static int ldap_get_keytab(krb5_context krbctx, bool_Bool generate, char *password,
488 const char *enctypes, const char *ldap_uri,
489 const char *svc_princ, krb5_principal bind_princ,
490 const char *bind_dn, const char *bind_pw,
491 const char *mech,
492 const char *ca_cert_file,
493 struct keys_container *keys, int *kvno,
494 char **err_msg)
495{
496 struct krb_key_salt *es = NULL((void*)0);
497 int num_es = 0;
498 struct berval *control = NULL((void*)0);
499 LDAP *ld = NULL((void*)0);
500 LDAPControl **srvctrl = NULL((void*)0);
501 struct berval data;
502 bool_Bool res;
503 int ret;
504
505 *err_msg = NULL((void*)0);
506
507 if (enctypes) {
508 ret = ipa_string_to_enctypes(enctypes, &es, &num_es, err_msg);
509 if (ret || num_es == 0) {
510 free(es);
511 return LDAP_OPERATIONS_ERROR0x01;
512 }
513 }
514
515 control = create_getkeytab_control(svc_princ, generate,
516 password, es, num_es);
517 if (!control) {
518 *err_msg = _("Failed to create control!\n")gettext("Failed to create control!\n");
519 ret = LDAP_OPERATIONS_ERROR0x01;
520 goto done;
521 }
522
523 ret = ipa_ldap_bind(ldap_uri, bind_princ, bind_dn, bind_pw, mech,
524 ca_cert_file, &ld);
525 if (ret != LDAP_SUCCESS0x00) {
526 *err_msg = _("Failed to bind to server!\n")gettext("Failed to bind to server!\n");
527 goto done;
528 }
529
530 /* perform extedned opt to get keytab */
531 ret = ipa_ldap_extended_op(ld, KEYTAB_GET_OID"2.16.840.1.113730.3.8.10.5", control, &srvctrl);
532 if (ret != LDAP_SUCCESS0x00) {
533 goto done;
534 }
535
536 ret = find_control_data(srvctrl, KEYTAB_GET_OID"2.16.840.1.113730.3.8.10.5", &data);
537 if (ret != LDAP_SUCCESS0x00) goto done;
538
539 res = ipaasn1_dec_getktreply(data.bv_val, data.bv_len, kvno, keys);
540 if (!res) {
541 *err_msg = _("Failed to decode control reply!\n")gettext("Failed to decode control reply!\n");
542 ret = LDAP_OPERATIONS_ERROR0x01;
543 goto done;
544 }
545
546 ret = LDAP_SUCCESS0x00;
547
548done:
549 if (ld) ldap_unbind_ext(ld, NULL((void*)0), NULL((void*)0));
550 if (control) ber_bvfree(control);
551 free(es);
552 if (ret) {
553 free_keys_contents(krbctx, keys);
554 }
555 return ret;
556}
557
558/* Prompt for either a password.
559 * This can be either asking for a new or existing password.
560 *
561 * To set a new password provide values for both prompt1 and prompt2 and
562 * set match=true to enforce that the two entered passwords match.
563 *
564 * To prompt for an existing password provide prompt1 and set match=false.
565 *
566 * Implementation details:
567 * krb5_prompter_posix() does not differentiate between too long entry or
568 * an entry exactly the size of a buffer. Thus, allocate a bigger buffer
569 * and do the check for a too long password afterwards.
570 */
571static char *ask_password(krb5_context krbctx, char *prompt1, char *prompt2,
572 bool_Bool match)
573{
574 krb5_prompt ap_prompts[2];
575 krb5_data k5d_pw0;
576 krb5_data k5d_pw1;
577#define MAX(a,b)(((a)>(b))?(a):(b)) (((a)>(b))?(a):(b))
578#define PWD_BUFFER_SIZE((((1000 + 2))>(1024))?((1000 + 2)):(1024)) MAX((IPAPWD_PASSWORD_MAX_LEN + 2), 1024)((((1000 + 2))>(1024))?((1000 + 2)):(1024))
579 char pw0[PWD_BUFFER_SIZE((((1000 + 2))>(1024))?((1000 + 2)):(1024))];
580 char pw1[PWD_BUFFER_SIZE((((1000 + 2))>(1024))?((1000 + 2)):(1024))];
581 char *password;
582 int num_prompts = match ? 2:1;
583
584 k5d_pw0.length = sizeof(pw0);
585 k5d_pw0.data = pw0;
586 ap_prompts[0].prompt = prompt1;
587 ap_prompts[0].hidden = 1;
588 ap_prompts[0].reply = &k5d_pw0;
589
590 if (match) {
591 k5d_pw1.length = sizeof(pw1);
592 k5d_pw1.data = pw1;
593 ap_prompts[1].prompt = prompt2;
594 ap_prompts[1].hidden = 1;
595 ap_prompts[1].reply = &k5d_pw1;
596 }
597
598 krb5_prompter_posix(krbctx, NULL((void*)0),
599 NULL((void*)0), NULL((void*)0),
600 num_prompts, ap_prompts);
601
602 if (match && (strcmp(pw0, pw1))) {
603 fprintf(stderrstderr, _("Passwords do not match!\n")gettext("Passwords do not match!\n"));
604 return NULL((void*)0);
605 }
606
607 if (k5d_pw0.length > IPAPWD_PASSWORD_MAX_LEN1000) {
608 fprintf(stderrstderr, "%s\n", ipapwd_password_max_len_errmsg);
609 return NULL((void*)0);
610 }
611
612 password = malloc(k5d_pw0.length + 1);
613 if (!password) return NULL((void*)0);
614 memcpy(password, pw0, k5d_pw0.length);
615 password[k5d_pw0.length] = '\0';
616
617 return password;
618}
619
620struct ipa_config {
621 const char *server_name;
622};
623
624static int config_from_file(struct ini_cfgobj *cfgctx)
625{
626 struct ini_cfgfile *fctx = NULL((void*)0);
627 char **errors = NULL((void*)0);
628 int ret;
629
630 ret = ini_config_file_open(IPACONFFILE"/usr/local/etc/ipa/default.conf", 0, &fctx);
631 if (ret) {
632 fprintf(stderrstderr, _("Failed to open config file %s\n")gettext("Failed to open config file %s\n"), IPACONFFILE"/usr/local/etc/ipa/default.conf");
633 return ret;
634 }
635
636 ret = ini_config_parse(fctx,
637 INI_STOP_ON_ANY,
638 INI_MS_MERGE0x0000 | INI_MV1S_ALLOW0x0003 | INI_MV2S_ALLOW0x0030,
639 INI_PARSE_NOWRAP0x0001,
640 cfgctx);
641 if (ret) {
642 fprintf(stderrstderr, _("Failed to parse config file %s\n")gettext("Failed to parse config file %s\n"), IPACONFFILE"/usr/local/etc/ipa/default.conf");
643 if (ini_config_error_count(cfgctx)) {
644 ini_config_get_errors(cfgctx, &errors);
645 if (errors) {
646 ini_config_print_errors(stderrstderr, errors);
647 ini_config_free_errors(errors);
648 }
649 }
650 ini_config_file_destroy(fctx);
651 return ret;
652 }
653
654 ini_config_file_destroy(fctx);
655 return 0;
656}
657
658int read_ipa_config(struct ipa_config **ipacfg)
659{
660 struct ini_cfgobj *cfgctx = NULL((void*)0);
661 struct value_obj *obj = NULL((void*)0);
662 int ret;
663
664 *ipacfg = calloc(1, sizeof(struct ipa_config));
665 if (!*ipacfg) {
666 return ENOMEM12;
667 }
668
669 ret = ini_config_create(&cfgctx);
670 if (ret) {
671 return ENOENT2;
672 }
673
674 ret = config_from_file(cfgctx);
675 if (ret) {
676 ini_config_destroy(cfgctx);
677 return EINVAL22;
678 }
679
680 ret = ini_get_config_valueobj("global", "server", cfgctx,
681 INI_GET_LAST_VALUE, &obj);
682 if (ret != 0 || obj == NULL((void*)0)) {
683 /* if called on an IPA server we need to look for 'host' instead */
684 ret = ini_get_config_valueobj("global", "host", cfgctx,
685 INI_GET_LAST_VALUE, &obj);
686 }
687
688 if (ret == 0 && obj != NULL((void*)0)) {
689 (*ipacfg)->server_name = ini_get_string_config_value(obj, &ret);
690 }
691
692 return 0;
693}
694
695static int resolve_ktname(const char *keytab, char **ktname, char **err_msg)
696{
697 char keytab_resolved[PATH_MAX4096 + 1];
698 struct stat st;
699 struct stat lst;
700 int ret;
701
702 *err_msg = NULL((void*)0);
703
704 /* Resolve keytab symlink to support dangling symlinks, see
705 * https://pagure.io/freeipa/issue/4607. To prevent symlink attacks,
706 * the symlink is only resolved owned by the current user or by
707 * root. For simplicity, only one level if indirection is resolved.
708 */
709 if ((stat(keytab, &st) == -1) &&
29
Assuming the condition is true
33
Taking true branch
710 (errno(*__errno_location ()) == ENOENT2) &&
30
Assuming the condition is true
711 (lstat(keytab, &lst) == 0) &&
31
Assuming the condition is true
712 (S_ISLNK(lst.st_mode)((((lst.st_mode)) & 0170000) == (0120000)))) {
32
Assuming the condition is true
713 /* keytab is a dangling symlink. */
714 if (((lst.st_uid == 0) && (lst.st_gid == 0)) ||
34
Assuming field 'st_uid' is not equal to 0
715 ((lst.st_uid == geteuid()) && (lst.st_gid == getegid()))) {
35
Assuming the condition is false
716 /* Either root or current user owns symlink, resolve symlink and
717 * return the resolved symlink. */
718 ret = readlink(keytab, keytab_resolved, PATH_MAX4096 + 1);
719 if ((ret == -1) || (ret > PATH_MAX4096)) {
720 *err_msg = _("Failed to resolve symlink to keytab.\n")gettext("Failed to resolve symlink to keytab.\n");
721 return ENOENT2;
722 }
723 keytab_resolved[ret] = '\0';
724 ret = asprintf(ktname, "WRFILE:%s", keytab_resolved);
725 if (ret == -1) {
726 *err_msg = strerror(errno(*__errno_location ()));
727 return ENOMEM12;
728 }
729 return 0;
730 } else {
731 *err_msg = _("keytab is a dangling symlink and owned by another "gettext("keytab is a dangling symlink and owned by another " "user.\n"
)
732 "user.\n")gettext("keytab is a dangling symlink and owned by another " "user.\n"
)
;
733 return EINVAL22;
36
Returning without writing to '*ktname'
734 }
735 } else {
736 ret = asprintf(ktname, "WRFILE:%s", keytab);
737 if (ret == -1) {
738 *err_msg = strerror(errno(*__errno_location ()));
739 return ENOMEM12;
740 }
741 return 0;
742 }
743}
744
745int main(int argc, const char *argv[])
746{
747 static const char *server = NULL((void*)0);
748 static const char *principal = NULL((void*)0);
749 static const char *keytab = NULL((void*)0);
750 static const char *enctypes_string = NULL((void*)0);
751 static const char *binddn = NULL((void*)0);
752 static const char *bindpw = NULL((void*)0);
753 char *ldap_uri = NULL((void*)0);
754 static const char *sasl_mech = NULL((void*)0);
755 static const char *ca_cert_file = NULL((void*)0);
756 int quiet = 0;
757 int askpass = 0;
758 int askbindpw = 0;
759 int permitted_enctypes = 0;
760 int retrieve = 0;
761 struct poptOption options[] = {
762 { "quiet", 'q', POPT_ARG_NONE0U, &quiet, 0,
763 _("Print as little as possible")gettext("Print as little as possible"), _("Output only on errors")gettext("Output only on errors")},
764 { "server", 's', POPT_ARG_STRING1U, &server, 0,
765 _("Contact this specific KDC Server")gettext("Contact this specific KDC Server"),
766 _("Server Name")gettext("Server Name") },
767 { "principal", 'p', POPT_ARG_STRING1U, &principal, 0,
768 _("The principal to get a keytab for (ex: ftp/ftp.example.com@EXAMPLE.COM)")gettext("The principal to get a keytab for (ex: ftp/ftp.example.com@EXAMPLE.COM)"
)
,
769 _("Kerberos Service Principal Name")gettext("Kerberos Service Principal Name") },
770 { "keytab", 'k', POPT_ARG_STRING1U, &keytab, 0,
771 _("The keytab file to append the new key to (will be "gettext("The keytab file to append the new key to (will be " "created if it does not exist)."
)
772 "created if it does not exist).")gettext("The keytab file to append the new key to (will be " "created if it does not exist)."
)
,
773 _("Keytab File Name")gettext("Keytab File Name") },
774 { "enctypes", 'e', POPT_ARG_STRING1U, &enctypes_string, 0,
775 _("Encryption types to request")gettext("Encryption types to request"),
776 _("Comma separated encryption types list")gettext("Comma separated encryption types list") },
777 { "permitted-enctypes", 0, POPT_ARG_NONE0U, &permitted_enctypes, 0,
778 _("Show the list of permitted encryption types and exit")gettext("Show the list of permitted encryption types and exit"
)
,
779 _("Permitted Encryption Types")gettext("Permitted Encryption Types") },
780 { "password", 'P', POPT_ARG_NONE0U, &askpass, 0,
781 _("Asks for a non-random password to use for the principal")gettext("Asks for a non-random password to use for the principal"
)
, NULL((void*)0) },
782 { "binddn", 'D', POPT_ARG_STRING1U, &binddn, 0,
783 _("LDAP DN")gettext("LDAP DN"), _("DN to bind as if not using kerberos")gettext("DN to bind as if not using kerberos") },
784 { "bindpw", 'w', POPT_ARG_STRING1U, &bindpw, 0,
785 _("LDAP password")gettext("LDAP password"), _("password to use if not using kerberos")gettext("password to use if not using kerberos") },
786 { NULL((void*)0), 'W', POPT_ARG_NONE0U, &askbindpw, 0,
787 _("Prompt for LDAP password")gettext("Prompt for LDAP password"), NULL((void*)0) },
788 { "cacert", 0, POPT_ARG_STRING1U, &ca_cert_file, 0,
789 _("Path to the IPA CA certificate")gettext("Path to the IPA CA certificate"), _("IPA CA certificate")gettext("IPA CA certificate")},
790 { "ldapuri", 'H', POPT_ARG_STRING1U, &ldap_uri, 0,
791 _("LDAP uri to connect to. Mutually exclusive with --server")gettext("LDAP uri to connect to. Mutually exclusive with --server"
)
,
792 _("url")gettext("url")},
793 { "mech", 'Y', POPT_ARG_STRING1U, &sasl_mech, 0,
794 _("LDAP SASL bind mechanism if no bindd/bindpw")gettext("LDAP SASL bind mechanism if no bindd/bindpw"),
795 _("GSSAPI|EXTERNAL")gettext("GSSAPI|EXTERNAL") },
796 { "retrieve", 'r', POPT_ARG_NONE0U, &retrieve, 0,
797 _("Retrieve current keys without changing them")gettext("Retrieve current keys without changing them"), NULL((void*)0) },
798 POPT_AUTOHELP{ ((void*)0), '\0', 4U, poptHelpOptions, 0, "Help options:", (
(void*)0) },
799 POPT_TABLEEND{ ((void*)0), '\0', 0, ((void*)0), 0, ((void*)0), ((void*)0) }
800 };
801 poptContext pc;
802 char *ktname;
1
'ktname' declared without an initial value
803 char *password = NULL((void*)0);
804 krb5_context krbctx;
805 krb5_ccache ccache;
806 krb5_principal uprinc = NULL((void*)0);
807 krb5_principal sprinc;
808 krb5_error_code krberr;
809 struct keys_container keys = { 0 };
810 krb5_keytab kt;
811 int kvno;
812 int i, ret;
813 char *err_msg;
814
815 ret = init_gettext();
816 if (ret) {
2
Assuming 'ret' is 0
3
Taking false branch
817 fprintf(stderrstderr, "Failed to load translations\n");
818 }
819
820 krberr = krb5_init_context(&krbctx);
821 if (krberr) {
4
Assuming 'krberr' is 0
5
Taking false branch
822 fprintf(stderrstderr, _("Kerberos context initialization failed\n")gettext("Kerberos context initialization failed\n"));
823 exit(1);
824 }
825
826 pc = poptGetContext("ipa-getkeytab", argc, (const char **)argv, options, 0);
827 ret = poptGetNextOpt(pc);
828 if (ret == -1 && permitted_enctypes &&
6
Assuming the condition is true
7
Assuming 'permitted_enctypes' is 0
829 !(server || principal || keytab || quiet)) {
830 krb5_enctype *ktypes;
831 char enc[79]; /* fit std terminal or truncate */
832
833 krberr = krb5_get_permitted_enctypes(krbctx, &ktypes);
834 if (krberr) {
835 fprintf(stderrstderr, _("No system preferred enctypes ?!\n")gettext("No system preferred enctypes ?!\n"));
836 exit(1);
837 }
838 fprintf(stdoutstdout, _("Supported encryption types:\n")gettext("Supported encryption types:\n"));
839 for (i = 0; ktypes[i]; i++) {
840 krberr = krb5_enctype_to_string(ktypes[i], enc, 79);
841 if (krberr) {
842 fprintf(stderrstderr, _("Warning: "gettext("Warning: " "failed to convert type (#%d)\n")
843 "failed to convert type (#%d)\n")gettext("Warning: " "failed to convert type (#%d)\n"), i);
844 continue;
845 }
846 fprintf(stdoutstdout, "%s\n", enc);
847 }
848 ipa_krb5_free_ktypes(krbctx, ktypes);
849 exit (0);
850 }
851
852 if (ret != -1 || !principal || !keytab || permitted_enctypes
9.1
'permitted_enctypes' is 0
) {
8
Assuming 'principal' is non-null
9
Assuming 'keytab' is non-null
10
Taking false branch
853 if (!quiet) {
854 poptPrintUsage(pc, stderrstderr, 0);
855 }
856 exit(2);
857 }
858
859 if (askbindpw && bindpw != NULL((void*)0)) {
11
Assuming 'askbindpw' is 0
860 fprintf(stderrstderr, _("Bind password already provided (-w).\n")gettext("Bind password already provided (-w).\n"));
861 if (!quiet) {
862 poptPrintUsage(pc, stderrstderr, 0);
863 }
864 exit(2);
865 }
866
867 if (askbindpw
11.1
'askbindpw' is 0
) {
12
Taking false branch
868 bindpw = ask_password(krbctx, _("Enter LDAP password")gettext("Enter LDAP password"), NULL((void*)0), false0);
869 if (!bindpw) {
870 exit(2);
871 }
872 }
873
874 if (NULL((void*)0)!=binddn && NULL((void*)0)==bindpw) {
13
Assuming 'binddn' is equal to NULL
875 fprintf(stderrstderr,
876 _("Bind password required when using a bind DN (-w or -W).\n")gettext("Bind password required when using a bind DN (-w or -W).\n"
)
);
877 if (!quiet)
878 poptPrintUsage(pc, stderrstderr, 0);
879 exit(10);
880 }
881
882 if (NULL((void*)0) != binddn
13.1
'binddn' is equal to NULL
&& NULL((void*)0) != sasl_mech) {
883 fprintf(stderrstderr, _("Cannot specify both SASL mechanism "gettext("Cannot specify both SASL mechanism " "and bind DN simultaneously.\n"
)
884 "and bind DN simultaneously.\n")gettext("Cannot specify both SASL mechanism " "and bind DN simultaneously.\n"
)
);
885 if (!quiet)
886 poptPrintUsage(pc, stderrstderr, 0);
887 exit(2);
888 }
889
890 if (sasl_mech && check_sasl_mech(sasl_mech)) {
14
Assuming 'sasl_mech' is null
891 fprintf(stderrstderr, _("Invalid SASL bind mechanism\n")gettext("Invalid SASL bind mechanism\n"));
892 if (!quiet)
893 poptPrintUsage(pc, stderrstderr, 0);
894 exit(2);
895 }
896
897 if (!binddn
14.1
'binddn' is null
&& !sasl_mech
14.2
'sasl_mech' is null
) {
15
Taking true branch
898 sasl_mech = LDAP_SASL_GSSAPI"GSSAPI";
899 }
900
901 if (server && ldap_uri) {
16
Assuming 'server' is null
902 fprintf(stderrstderr, _("Cannot specify server and LDAP uri "gettext("Cannot specify server and LDAP uri " "simultaneously.\n"
)
903 "simultaneously.\n")gettext("Cannot specify server and LDAP uri " "simultaneously.\n"
)
);
904 if (!quiet)
905 poptPrintUsage(pc, stderrstderr, 0);
906 exit(2);
907 }
908
909 if (!server
16.1
'server' is null
&& !ldap_uri) {
17
Assuming 'ldap_uri' is non-null
18
Taking false branch
910 struct ipa_config *ipacfg = NULL((void*)0);
911
912 ret = read_ipa_config(&ipacfg);
913 if (ret == 0) {
914 server = ipacfg->server_name;
915 ipacfg->server_name = NULL((void*)0);
916 }
917 free(ipacfg);
918 if (!server) {
919 fprintf(stderrstderr, _("Server name not provided and unavailable\n")gettext("Server name not provided and unavailable\n"));
920 exit(2);
921 }
922 }
923 if (server
18.1
'server' is null
) {
19
Taking false branch
924 ret = ipa_server_to_uri(server, sasl_mech, &ldap_uri);
925 if (ret) {
926 exit(ret);
927 }
928 }
929
930 if (!ca_cert_file) {
20
Assuming 'ca_cert_file' is non-null
21
Taking false branch
931 ca_cert_file = DEFAULT_CA_CERT_FILE"/etc/ipa/ca.crt";
932 }
933
934 if (askpass && retrieve) {
22
Assuming 'askpass' is 0
935 fprintf(stderrstderr, _("Incompatible options provided (-r and -P)\n")gettext("Incompatible options provided (-r and -P)\n"));
936 exit(2);
937 }
938
939 if (askpass
22.1
'askpass' is 0
) {
23
Taking false branch
940 password = ask_password(krbctx, _("New Principal Password")gettext("New Principal Password"),
941 _("Verify Principal Password")gettext("Verify Principal Password"), true1);
942 if (!password) {
943 exit(2);
944 }
945 } else if (enctypes_string && strchr(enctypes_string, ':')) {
24
Assuming 'enctypes_string' is null
946 if (!quiet) {
947 fprintf(stderrstderr, _("Warning: salt types are not honored"gettext("Warning: salt types are not honored" " with randomized passwords (see opt. -P)\n"
)
948 " with randomized passwords (see opt. -P)\n")gettext("Warning: salt types are not honored" " with randomized passwords (see opt. -P)\n"
)
);
949 }
950 }
951
952 krberr = krb5_parse_name(krbctx, principal, &sprinc);
953 if (krberr) {
25
Assuming 'krberr' is 0
26
Taking false branch
954 fprintf(stderrstderr, _("Invalid Service Principal Name\n")gettext("Invalid Service Principal Name\n"));
955 exit(4);
956 }
957
958 if (NULL((void*)0) == bindpw && strcmp(sasl_mech, LDAP_SASL_GSSAPI"GSSAPI") == 0) {
27
Assuming 'bindpw' is not equal to NULL
959 krberr = krb5_cc_default(krbctx, &ccache);
960 if (krberr) {
961 fprintf(stderrstderr,
962 _("Kerberos Credential Cache not found. "gettext("Kerberos Credential Cache not found. " "Do you have a Kerberos Ticket?\n"
)
963 "Do you have a Kerberos Ticket?\n")gettext("Kerberos Credential Cache not found. " "Do you have a Kerberos Ticket?\n"
)
);
964 exit(5);
965 }
966
967 krberr = krb5_cc_get_principal(krbctx, ccache, &uprinc);
968 if (krberr) {
969 fprintf(stderrstderr,
970 _("Kerberos User Principal not found. "gettext("Kerberos User Principal not found. " "Do you have a valid Credential Cache?\n"
)
971 "Do you have a valid Credential Cache?\n")gettext("Kerberos User Principal not found. " "Do you have a valid Credential Cache?\n"
)
);
972 exit(6);
973 }
974 }
975
976 ret = resolve_ktname(keytab, &ktname, &err_msg);
28
Calling 'resolve_ktname'
37
Returning from 'resolve_ktname'
977 if (krberr
37.1
'krberr' is 0
) {
38
Taking false branch
978 fprintf(stderrstderr, "%s", err_msg);
979 exit(ret);
980 }
981
982 krberr = krb5_kt_resolve(krbctx, ktname, &kt);
39
2nd function call argument is an uninitialized value
983 if (krberr) {
984 fprintf(stderrstderr, _("Failed to open Keytab\n")gettext("Failed to open Keytab\n"));
985 exit(7);
986 }
987
988 kvno = -1;
989 ret = ldap_get_keytab(krbctx, (retrieve == 0), password, enctypes_string,
990 ldap_uri, principal, uprinc, binddn, bindpw,
991 sasl_mech, ca_cert_file,
992 &keys, &kvno, &err_msg);
993 if (ret) {
994 if (!quiet && err_msg != NULL((void*)0)) {
995 fprintf(stderrstderr, "%s", err_msg);
996 }
997 }
998
999 if (retrieve == 0 && kvno == -1) {
1000 if (!quiet) {
1001 fprintf(stderrstderr,
1002 _("Retrying with pre-4.0 keytab retrieval method...\n")gettext("Retrying with pre-4.0 keytab retrieval method...\n"));
1003 }
1004
1005 /* create key material */
1006 ret = create_keys(krbctx, sprinc, password, enctypes_string, &keys, &err_msg);
1007 if (!ret) {
1008 if (err_msg != NULL((void*)0)) {
1009 fprintf(stderrstderr, "%s", err_msg);
1010 }
1011
1012 fprintf(stderrstderr, _("Failed to create key material\n")gettext("Failed to create key material\n"));
1013 free_keys_contents(krbctx, &keys);
1014 exit(8);
1015 }
1016
1017 kvno = ldap_set_keytab(krbctx, ldap_uri, principal, uprinc, binddn,
1018 bindpw, sasl_mech, ca_cert_file, &keys);
1019 }
1020
1021 if (kvno == -1) {
1022 fprintf(stderrstderr, _("Failed to get keytab\n")gettext("Failed to get keytab\n"));
1023 exit(9);
1024 }
1025
1026 for (i = 0; i < keys.nkeys; i++) {
1027 krb5_keytab_entry kt_entry;
1028 memset((char *)&kt_entry, 0, sizeof(kt_entry));
1029 kt_entry.principal = sprinc;
1030 kt_entry.key = keys.ksdata[i].key;
1031 kt_entry.vno = kvno;
1032
1033 krberr = krb5_kt_add_entry(krbctx, kt, &kt_entry);
1034 if (krberr) {
1035 fprintf(stderrstderr,
1036 _("Failed to add key to the keytab\n")gettext("Failed to add key to the keytab\n"));
1037 exit (11);
1038 }
1039 }
1040
1041 free_keys_contents(krbctx, &keys);
1042
1043 krberr = krb5_kt_close(krbctx, kt);
1044 if (krberr) {
1045 fprintf(stderrstderr, _("Failed to close the keytab\n")gettext("Failed to close the keytab\n"));
1046 exit (12);
1047 }
1048
1049 if (!quiet) {
1050 fprintf(stderrstderr,
1051 _("Keytab successfully retrieved and stored in: %s\n")gettext("Keytab successfully retrieved and stored in: %s\n"),
1052 keytab);
1053 }
1054 exit(0);
1055}