segfault in krb5_c_string_to_key()

John Hascall john at iastate.edu
Mon Jan 19 14:22:51 EST 2004



Q: Is this fixed in a later version?


In Krb5 1.2.6 when calling krb5_get_init_creds_password()
with krb5_prompter_posix() and you enter no password (just
press enter) you get a segfault in krb5_c_string_to_key()
because when it does:

    if ((ret = ((*(krb5_enctypes_list[i].str2key))(enc, string, salt, key)))) {
        memset(key->contents, 0, keylength);
        free(key->contents);
    }

key->contents is NULL, because when it called krb5_des_string_to_key(),
it in turn called mit_des_string_to_key_int() which did:

	...
    length = data->length + salt->length;	/* 0 + 0 */
	...

    copystr = malloc((size_t) length);		/* returns NULL on some O.S. */
    if (!copystr) {
        free(keyblock->contents);		/* already freed and */
        keyblock->contents = 0;			/* <=== made NULL here */
        return ENOMEM;
    }


Resulting in:


Segmentation fault at >*[_OtsFill, 0x3ff800d7808]        stq     r18, 0(r16)
(dbx) where
>  0 _OtsFill(0x120065854, 0x11fffd868, 0x11fffd880, 0x11fffda08, 0x14000c020)
	[0x3ff800d7808]
   1 krb5_c_string_to_key(context = 0x14001ed00, enctype = 1,
	string = 0x11fffda08, salt = 0x11fffd880, key = 0x11fffd868)
	["string_to_key.c":63, 0x120065878]
   2 krb5_get_as_key_password(context = 0x14001ed00, client = 0x1400215a0,
	etype = 1, prompter = 0x120022e98, prompter_data = (nil),
	salt = 0x11fffd880, as_key = 0x11fffd868, gak_data = 0x11fffda08)
	["gic_pwd.c":77, 0x120023824]
   3 krb5_get_init_creds(context = 0x14001ed00, creds = 0x11fffe7e0,
	client = 0x1400215a0, prompter = 0x120022e98, prompter_data = (nil),
	start_time = 0, in_tkt_service = (nil), options = 0x11fffe798,
	gak_fct = 0x1200235e0, gak_data = 0x11fffda08, use_master = 0,
	as_reply = 0x11fffda18) ["get_in_tkt.c":1010, 0x12002aa38]
   4 krb5_get_init_creds_password(context = 0x14001ed00, creds = 0x11fffe7e0,
	client = 0x1400215a0, password = (nil), prompter = 0x120022e98,
	data = (nil), start_time = 0, in_tkt_service = (nil),
	options = 0x11fffe798) ["gic_pwd.c":132, 0x1200239b4]

If a fix has not already happened, this is probably most portable:

    if ((ret = ((*(krb5_enctypes_list[i].str2key))(enc, string, salt, key)))) {
        if (key->contents) {				/* ADD ME */
            memset(key->contents, 0, keylength);
            free(key->contents);			/* ADD ME */
        }
    }

Although returning ENOMEM all the way back might be a little confusing
to callers, so I also changed the malloc line shown above to this:

    copystr = malloc((size_t) (length ? length : 1));

But this caused a silly double password prompt, so in
krb5_get_init_creds_password() right after:

   if ((ret == KRB5_KDC_UNREACH) ||
       (ret == KRB5_LIBOS_PWDINTR) ||
           (ret == KRB5_REALM_CANT_RESOLVE))
      goto cleanup;

I added:

   if ((ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) && (pw0.length == 0))
      goto cleanup;

Although perhaps just the test for length of zero would be good enough.


FWIW,
John


More information about the krbdev mailing list