summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2013-05-28 17:21:45 -0400
committerNalin Dahyabhai <nalin@redhat.com>2013-05-28 17:21:45 -0400
commit827a48f7cc301b20172f12b625f9a40ff838a4a4 (patch)
treeb7f8d1a68226ca7136c6b054a54d2905a6e3f67b
parent2fdc61e398ea4a9d89cbc2c5816faad6babb1925 (diff)
downloadkrb5-827a48f7cc301b20172f12b625f9a40ff838a4a4.tar.gz
krb5-827a48f7cc301b20172f12b625f9a40ff838a4a4.tar.xz
krb5-827a48f7cc301b20172f12b625f9a40ff838a4a4.zip
Fix handling of empty passwords in get-init-creds
-rw-r--r--krb5-1.11.2-arcfour_short.patch122
-rw-r--r--krb5-1.11.2-empty_passwords.patch492
-rw-r--r--krb5.spec6
3 files changed, 620 insertions, 0 deletions
diff --git a/krb5-1.11.2-arcfour_short.patch b/krb5-1.11.2-arcfour_short.patch
new file mode 100644
index 0000000..2f67ae3
--- /dev/null
+++ b/krb5-1.11.2-arcfour_short.patch
@@ -0,0 +1,122 @@
+Needed by tests for empty-password cases.
+
+commit 1e123231769fe640f446442cb210664d280ccbac
+Author: Greg Hudson <ghudson@mit.edu>
+Date: Fri May 24 13:16:52 2013 -0400
+
+ Fix rc4 string-to-key on unterminated inputs
+
+ The internal UTF-8 to UCS-2 conversion functions did not properly
+ respect their length arguments, instead assuming that the input string
+ is terminated with a zero bytes. As a result,
+ krb5int_arcfour_string_to_key could fail on unterminated inputs. Fix
+ the underlying support functions to read their inputs only up to the
+ specified length.
+
+ ticket: 7643 (new)
+
+diff --git a/src/util/support/utf8_conv.c b/src/util/support/utf8_conv.c
+index d580bbc..b8bf989 100644
+--- a/src/util/support/utf8_conv.c
++++ b/src/util/support/utf8_conv.c
+@@ -78,7 +78,8 @@ k5_utf8s_to_ucs2s(krb5_ucs2 *ucs2str,
+
+ /* If input ptr is NULL or empty... */
+ if (utf8str == NULL || *utf8str == '\0') {
+- *ucs2str = 0;
++ if (ucs2str != NULL)
++ *ucs2str = 0;
+
+ return 0;
+ }
+@@ -119,9 +120,7 @@ k5_utf8s_to_ucs2s(krb5_ucs2 *ucs2str,
+ ucs2len++; /* Count number of wide chars stored/required */
+ }
+
+- assert(ucs2len < count);
+-
+- if (ucs2str != NULL) {
++ if (ucs2str != NULL && ucs2len < count) {
+ /* Add null terminator if there's room in the buffer. */
+ ucs2str[ucs2len] = 0;
+ }
+@@ -172,12 +171,13 @@ krb5int_utf8cs_to_ucs2s(const char *utf8s,
+ return ENOMEM;
+ }
+
+- len = k5_utf8s_to_ucs2s(*ucs2s, utf8s, chars + 1, 0);
++ len = k5_utf8s_to_ucs2s(*ucs2s, utf8s, chars, 0);
+ if (len < 0) {
+ free(*ucs2s);
+ *ucs2s = NULL;
+ return EINVAL;
+ }
++ (*ucs2s)[chars] = 0;
+
+ if (ucs2chars != NULL) {
+ *ucs2chars = chars;
+@@ -223,21 +223,23 @@ krb5int_utf8cs_to_ucs2les(const char *utf8s,
+ {
+ ssize_t len;
+ size_t chars;
++ krb5_ucs2 *ucs2s;
+
+- chars = krb5int_utf8c_chars(utf8s, utf8slen);
++ *ucs2les = NULL;
+
+- *ucs2les = (unsigned char *)malloc((chars + 1) * sizeof(krb5_ucs2));
+- if (*ucs2les == NULL) {
++ chars = krb5int_utf8c_chars(utf8s, utf8slen);
++ ucs2s = malloc((chars + 1) * sizeof(krb5_ucs2));
++ if (ucs2s == NULL)
+ return ENOMEM;
+- }
+
+- len = k5_utf8s_to_ucs2s((krb5_ucs2 *)*ucs2les, utf8s, chars + 1, 1);
++ len = k5_utf8s_to_ucs2s(ucs2s, utf8s, chars, 1);
+ if (len < 0) {
+- free(*ucs2les);
+- *ucs2les = NULL;
++ free(ucs2s);
+ return EINVAL;
+ }
++ ucs2s[chars] = 0;
+
++ *ucs2les = (unsigned char *)ucs2s;
+ if (ucs2leslen != NULL) {
+ *ucs2leslen = chars * sizeof(krb5_ucs2);
+ }
+@@ -402,13 +404,14 @@ krb5int_ucs2cs_to_utf8s(const krb5_ucs2 *ucs2s,
+ return ENOMEM;
+ }
+
+- len = k5_ucs2s_to_utf8s(*utf8s, (krb5_ucs2 *)ucs2s,
+- (size_t)len + 1, (ssize_t)ucs2slen, 0);
++ len = k5_ucs2s_to_utf8s(*utf8s, (krb5_ucs2 *)ucs2s, (size_t)len,
++ (ssize_t)ucs2slen, 0);
+ if (len < 0) {
+ free(*utf8s);
+ *utf8s = NULL;
+ return EINVAL;
+ }
++ (*utf8s)[len] = '\0';
+
+ if (utf8slen != NULL) {
+ *utf8slen = len;
+@@ -438,13 +441,14 @@ krb5int_ucs2lecs_to_utf8s(const unsigned char *ucs2les,
+ return ENOMEM;
+ }
+
+- len = k5_ucs2s_to_utf8s(*utf8s, (krb5_ucs2 *)ucs2les,
+- (size_t)len + 1, (ssize_t)ucs2leslen, 1);
++ len = k5_ucs2s_to_utf8s(*utf8s, (krb5_ucs2 *)ucs2les, (size_t)len,
++ (ssize_t)ucs2leslen, 1);
+ if (len < 0) {
+ free(*utf8s);
+ *utf8s = NULL;
+ return EINVAL;
+ }
++ (*utf8s)[len] = '\0';
+
+ if (utf8slen != NULL) {
+ *utf8slen = len;
diff --git a/krb5-1.11.2-empty_passwords.patch b/krb5-1.11.2-empty_passwords.patch
new file mode 100644
index 0000000..3941084
--- /dev/null
+++ b/krb5-1.11.2-empty_passwords.patch
@@ -0,0 +1,492 @@
+Should fix #960001. Adjusted to apply to 1.11.2, which didn't yet include
+some other developments, renames, reformatting, and fewer tests.
+
+commit f3458ed803ae97b6c6c7c63baeb82b26c4943d4c
+Author: Greg Hudson <ghudson@mit.edu>
+Date: Thu May 23 15:33:58 2013 -0400
+
+ Make empty passwords work via init_creds APIs
+
+ In the gak_data value used by krb5_get_as_key_password, separate the
+ already-known password from the storage we might have allocated to put
+ it in, so that we no longer use an empty data buffer to determine
+ whether we know the password. This allows empty passwords to work via
+ the API.
+
+ Remove the kadm5 test which explicitly uses an empty password.
+
+ Based on a patch from Stef Walter.
+
+ ticket: 7642
+
+diff --git a/src/lib/kadm5/unit-test/api.current/init.exp b/src/lib/kadm5/unit-test/api.current/init.exp
+index b324df8..d9ae3fb 100644
+--- a/src/lib/kadm5/unit-test/api.current/init.exp
++++ b/src/lib/kadm5/unit-test/api.current/init.exp
+@@ -99,33 +99,6 @@ proc test6 {} {
+ }
+ if { $RPC } { test6 }
+
+-test "init 7"
+-proc test7 {} {
+- global test
+-
+- send "kadm5_init admin \"\" \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_3 server_handle\n"
+-
+- expect {
+- -re "assword\[^\r\n\]*:" { }
+- -re "key:$" { }
+- eof {
+- fail "$test: eof instead of password prompt"
+- api_exit
+- api_start
+- return
+- }
+- timeout {
+- fail "$test: timeout instead of password prompt"
+- return
+- }
+- }
+- one_line_succeed_test "admin"
+- if {! [cmd {kadm5_destroy $server_handle}]} {
+- error_and_restart "$test: couldn't close database"
+- }
+-}
+-if { $RPC } { test7 }
+-
+ test "init 8"
+
+ proc test8 {} {
+diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
+index 59614e7..20bc689 100644
+--- a/src/lib/krb5/krb/get_in_tkt.c
++++ b/src/lib/krb5/krb/get_in_tkt.c
+@@ -493,8 +493,7 @@ krb5_init_creds_free(krb5_context context,
+ }
+ k5_response_items_free(ctx->rctx.items);
+ free(ctx->in_tkt_service);
+- zap(ctx->password.data, ctx->password.length);
+- krb5_free_data_contents(context, &ctx->password);
++ zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length);
+ krb5_free_error(context, ctx->err_reply);
+ krb5_free_pa_data(context, ctx->err_padata);
+ krb5_free_cred_contents(context, &ctx->cred);
+@@ -788,7 +787,7 @@ krb5_init_creds_init(krb5_context context,
+ ctx->prompter = prompter;
+ ctx->prompter_data = data;
+ ctx->gak_fct = krb5_get_as_key_password;
+- ctx->gak_data = &ctx->password;
++ ctx->gak_data = &ctx->gakpw;
+
+ ctx->request_time = 0; /* filled in later */
+ ctx->start_time = start_time;
+diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c
+index 22db2b5..a97823f 100644
+--- a/src/lib/krb5/krb/gic_pwd.c
++++ b/src/lib/krb5/krb/gic_pwd.c
+@@ -17,22 +17,19 @@ krb5_get_as_key_password(krb5_context context,
+ void *gak_data,
+ k5_response_items *ritems)
+ {
+- krb5_data *password;
++ struct gak_password *gp = gak_data;
+ krb5_error_code ret;
+ krb5_data defsalt;
+ char *clientstr;
+- char promptstr[1024];
++ char promptstr[1024], pwbuf[1024];
++ krb5_data pw;
+ krb5_prompt prompt;
+ krb5_prompt_type prompt_type;
+ const char *rpass;
+
+- password = (krb5_data *) gak_data;
+- assert(password->length > 0);
+-
+ /* If we need to get the AS key via the responder, ask for it. */
+ if (as_key == NULL) {
+- /* However, if we already have a password, don't ask. */
+- if (password->data[0] != '\0')
++ if (gp->password != NULL)
+ return 0;
+
+ return k5_response_items_ask_question(ritems,
+@@ -55,17 +52,20 @@ krb5_get_as_key_password(krb5_context context,
+ }
+ }
+
+- if (password->data[0] == '\0') {
++ if (gp->password == NULL) {
+ /* Check the responder for the password. */
+ rpass = k5_response_items_get_answer(ritems,
+ KRB5_RESPONDER_QUESTION_PASSWORD);
+ if (rpass != NULL) {
+- strlcpy(password->data, rpass, password->length);
+- password->length = strlen(password->data);
++ ret = alloc_data(&gp->storage, strlen(rpass));
++ if (ret)
++ return ret;
++ memcpy(gp->storage.data, rpass, strlen(rpass));
++ gp->password = &gp->storage;
+ }
+ }
+
+- if (password->data[0] == '\0') {
++ if (gp->password == NULL) {
+ if (prompter == NULL)
+ return(EIO);
+
+@@ -76,9 +76,10 @@ krb5_get_as_key_password(krb5_context context,
+ clientstr);
+ free(clientstr);
+
++ pw = make_data(pwbuf, sizeof(pwbuf));
+ prompt.prompt = promptstr;
+ prompt.hidden = 1;
+- prompt.reply = password;
++ prompt.reply = &pw;
+ prompt_type = KRB5_PROMPT_TYPE_PASSWORD;
+
+ /* PROMPTER_INVOCATION */
+@@ -87,6 +88,12 @@ krb5_get_as_key_password(krb5_context context,
+ krb5int_set_prompt_types(context, 0);
+ if (ret)
+ return(ret);
++
++ ret = krb5int_copy_data_contents(context, &pw, &gp->storage);
++ zap(pw.data, pw.length);
++ if (ret)
++ return ret;
++ gp->password = &gp->storage;
+ }
+
+ if (salt == NULL) {
+@@ -98,7 +105,7 @@ krb5_get_as_key_password(krb5_context context,
+ defsalt.length = 0;
+ }
+
+- ret = krb5_c_string_to_key_with_params(context, etype, password, salt,
++ ret = krb5_c_string_to_key_with_params(context, etype, gp->password, salt,
+ params->data?params:NULL, as_key);
+
+ if (defsalt.length)
+@@ -118,16 +125,11 @@ krb5_init_creds_set_password(krb5_context context,
+ if (s == NULL)
+ return ENOMEM;
+
+- if (ctx->password.data != NULL) {
+- zap(ctx->password.data, ctx->password.length);
+- krb5_free_data_contents(context, &ctx->password);
+- }
+-
+- ctx->password.data = s;
+- ctx->password.length = strlen(s);
++ zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length);
++ ctx->gakpw.storage = string2data(s);
++ ctx->gakpw.password = &ctx->gakpw.storage;
+ ctx->gak_fct = krb5_get_as_key_password;
+- ctx->gak_data = &ctx->password;
+-
++ ctx->gak_data = &ctx->gakpw;
+ return 0;
+ }
+
+@@ -257,6 +259,7 @@ krb5_get_init_creds_password(krb5_context context,
+ int tries;
+ krb5_creds chpw_creds;
+ krb5_get_init_creds_opt *chpw_opts = NULL;
++ struct gak_password gakpw;
+ krb5_data pw0, pw1;
+ char banner[1024], pw0array[1024], pw1array[1024];
+ krb5_prompt prompt[2];
+@@ -267,29 +270,18 @@ krb5_get_init_creds_password(krb5_context context,
+ use_master = 0;
+ as_reply = NULL;
+ memset(&chpw_creds, 0, sizeof(chpw_creds));
++ memset(&gakpw, 0, sizeof(gakpw));
+
+- pw0.data = pw0array;
+-
+- if (password && password[0]) {
+- if (strlcpy(pw0.data, password, sizeof(pw0array)) >= sizeof(pw0array)) {
+- ret = EINVAL;
+- goto cleanup;
+- }
+- pw0.length = strlen(password);
+- } else {
+- pw0.data[0] = '\0';
+- pw0.length = sizeof(pw0array);
++ if (password != NULL) {
++ pw0 = string2data((char *)password);
++ gakpw.password = &pw0;
+ }
+
+- pw1.data = pw1array;
+- pw1.data[0] = '\0';
+- pw1.length = sizeof(pw1array);
+-
+ /* first try: get the requested tkt from any kdc */
+
+ ret = krb5int_get_init_creds(context, creds, client, prompter, data,
+ start_time, in_tkt_service, options,
+- krb5_get_as_key_password, (void *) &pw0,
++ krb5_get_as_key_password, &gakpw,
+ &use_master, &as_reply);
+
+ /* check for success */
+@@ -318,7 +310,7 @@ krb5_get_init_creds_password(krb5_context context,
+ }
+ ret2 = krb5int_get_init_creds(context, creds, client, prompter, data,
+ start_time, in_tkt_service, options,
+- krb5_get_as_key_password, (void *) &pw0,
++ krb5_get_as_key_password, &gakpw,
+ &use_master, &as_reply);
+
+ if (ret2 == 0) {
+@@ -365,15 +357,21 @@ krb5_get_init_creds_password(krb5_context context,
+ if ((ret = krb5int_get_init_creds(context, &chpw_creds, client,
+ prompter, data,
+ start_time, "kadmin/changepw", chpw_opts,
+- krb5_get_as_key_password, (void *) &pw0,
++ krb5_get_as_key_password, &gakpw,
+ &use_master, NULL)))
+ goto cleanup;
+
++ pw0.data = pw0array;
++ pw0.data[0] = '\0';
++ pw0.length = sizeof(pw0array);
+ prompt[0].prompt = _("Enter new password");
+ prompt[0].hidden = 1;
+ prompt[0].reply = &pw0;
+ prompt_types[0] = KRB5_PROMPT_TYPE_NEW_PASSWORD;
+
++ pw1.data = pw1array;
++ pw1.data[0] = '\0';
++ pw1.length = sizeof(pw1array);
+ prompt[1].prompt = _("Enter it again");
+ prompt[1].hidden = 1;
+ prompt[1].reply = &pw1;
+@@ -460,10 +458,11 @@ krb5_get_init_creds_password(krb5_context context,
+ is final. */
+
+ TRACE_GIC_PWD_CHANGED(context);
++ gakpw.password = &pw0;
+ ret = krb5int_get_init_creds(context, creds, client, prompter, data,
+ start_time, in_tkt_service, options,
+- krb5_get_as_key_password, (void *) &pw0,
++ krb5_get_as_key_password, &gakpw,
+ &use_master, &as_reply);
+ if (ret)
+ goto cleanup;
+
+@@ -474,6 +473,7 @@ cleanup:
+
+ if (chpw_opts)
+ krb5_get_init_creds_opt_free(context, chpw_opts);
++ zapfree(gakpw.storage.data, gakpw.storage.length);
+ memset(pw0array, 0, sizeof(pw0array));
+ memset(pw1array, 0, sizeof(pw1array));
+ krb5_free_cred_contents(context, &chpw_creds);
+@@ -512,21 +512,17 @@ krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
+ krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+ {
+ krb5_error_code retval;
+- krb5_data pw0;
+- char pw0array[1024];
++ struct gak_password gakpw;
++ krb5_data pw;
+ char * server;
+ krb5_principal server_princ, client_princ;
+ int use_master = 0;
+ krb5_get_init_creds_opt *opts = NULL;
+
+- pw0.data = pw0array;
+- if (password && password[0]) {
+- if (strlcpy(pw0.data, password, sizeof(pw0array)) >= sizeof(pw0array))
+- return EINVAL;
+- pw0.length = strlen(password);
+- } else {
+- pw0.data[0] = '\0';
+- pw0.length = sizeof(pw0array);
++ memset(&gakpw, 0, sizeof(gakpw));
++ if (password != NULL) {
++ pw = string2data((char *)password);
++ gakpw.password = &pw;
+ }
+ retval = krb5int_populate_gic_opt(context, &opts,
+ options, addrs, ktypes,
+@@ -544,10 +540,11 @@ krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
+ retval = krb5int_get_init_creds(context, creds, creds->client,
+ krb5_prompter_posix, NULL,
+ 0, server, opts,
+- krb5_get_as_key_password, &pw0,
++ krb5_get_as_key_password, &gakpw,
+ &use_master, ret_as_reply);
+ krb5_free_unparsed_name( context, server);
+ krb5_get_init_creds_opt_free(context, opts);
++ zapfree(gakpw.storage.data, gakpw.storage.length);
+ if (retval) {
+ return (retval);
+ }
+diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
+index d886c7a..4dbb0e9 100644
+--- a/src/lib/krb5/krb/init_creds_ctx.h
++++ b/src/lib/krb5/krb/init_creds_ctx.h
+@@ -10,6 +10,11 @@ struct krb5_clpreauth_rock_st {
+ k5_json_value *cc_config_out;
+ };
+
++struct gak_password {
++ krb5_data storage;
++ const krb5_data *password;
++};
++
+ struct _krb5_init_creds_context {
+ krb5_gic_opt_ext *opte;
+ char *in_tkt_service;
+@@ -23,7 +28,7 @@ struct _krb5_init_creds_context {
+ krb5_deltat renew_life;
+ krb5_boolean complete;
+ unsigned int loopcount;
+- krb5_data password;
++ struct gak_password gakpw;
+ krb5_error *err_reply;
+ krb5_pa_data **err_padata;
+ krb5_creds cred;
+diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
+index 2358c89..91f312e 100644
+--- a/src/tests/Makefile.in
++++ b/src/tests/Makefile.in
+@@ -28,6 +28,9 @@ kdbtest: kdbtest.o $(KDB5_DEPLIBS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+ KADMIN_OPTS= -d $(TEST_DB) -r $(TEST_REALM) -P $(TEST_MKEY)
+ KTEST_OPTS= $(KADMIN_OPTS) -p $(TEST_PREFIX) -n $(TEST_NUM) -D $(TEST_DEPTH)
+
++t_init_creds: t_init_creds.o $(KRB5_BASE_DEPLIBS)
++ $(CC_LINK) -o $@ t_init_creds.o $(KRB5_BASE_LIBS)
++
+ hist: hist.o $(KDB5_DEPLIBS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o $@ hist.o $(KDB5_LIBS) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS)
+
+@@ -73,7 +76,7 @@ kdb_check: kdc.conf krb5.conf
+ $(RUN_SETUP) $(VALGRIND) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f
+ $(RM) $(TEST_DB)* stash_file
+
+-check-pytests:: hist
++check-pytests:: hist t_init_creds
+ $(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS)
+ $(RUNPYTEST) $(srcdir)/t_iprop.py $(PYTESTFLAGS)
+ $(RUNPYTEST) $(srcdir)/t_anonpkinit.py $(PYTESTFLAGS)
+diff --git a/src/tests/t_general.py b/src/tests/t_general.py
+index bb7a543..98e77a2 100755
+--- a/src/tests/t_general.py
++++ b/src/tests/t_general.py
+@@ -22,6 +22,15 @@ for realm in multipass_realms(create_host=False):
+ # Test kinit against kdb keytab
+ realm.run_as_master([kinit, "-k", "-t", "KDB:", realm.user_princ])
+
++# Test that we can get initial creds with an empty password via the
++# API. We have to disable the "empty" pwqual module to create a
++# principal with an empty password. (Regression test for #7642.)
++conf={'master':{'plugins': {'pwqual': {'disable': 'empty'}}}}
++realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf)
++realm.run_kadminl('addprinc -pw "" user')
++realm.run_as_client(['./t_init_creds', 'user', ''])
++realm.stop()
++
+ realm = K5Realm(create_host=False)
+
+ # Create a policy and see if it survives a dump/load.
+diff --git a/src/tests/t_init_creds.c b/src/tests/t_init_creds.c
+new file mode 100644
+index 0000000..6be8340
+--- /dev/null
++++ b/src/tests/t_init_creds.c
+@@ -0,0 +1,88 @@
++/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/* tests/t_init_creds.c - test harness for getting initial creds */
++/*
++ * Copyright (C) 2013 by the Massachusetts Institute of Technology.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
++ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++/*
++ * This program exercises the init_creds APIs in ways kinit doesn't. Right now
++ * it is very simplistic, but it can be extended as needed.
++ */
++
++#include <krb5.h>
++#include <stdio.h>
++
++static krb5_context ctx;
++
++static void
++check(krb5_error_code code)
++{
++ const char *errmsg;
++
++ if (code) {
++ errmsg = krb5_get_error_message(ctx, code);
++ fprintf(stderr, "%s\n", errmsg);
++ krb5_free_error_message(ctx, errmsg);
++ exit(1);
++ }
++}
++
++int
++main(int argc, char **argv)
++{
++ const char *princstr, *password;
++ krb5_principal client;
++ krb5_init_creds_context icc;
++ krb5_creds creds;
++
++ if (argc != 3) {
++ fprintf(stderr, "Usage: t_init_creds princname password\n");
++ exit(1);
++ }
++ princstr = argv[1];
++ password = argv[2];
++
++ check(krb5_init_context(&ctx));
++ check(krb5_parse_name(ctx, princstr, &client));
++
++ /* Try once with the traditional interface. */
++ check(krb5_get_init_creds_password(ctx, &creds, client, password, NULL,
++ NULL, 0, NULL, NULL));
++ krb5_free_cred_contents(ctx, &creds);
++
++ /* Try again with the step interface. */
++ check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, &icc));
++ check(krb5_init_creds_set_password(ctx, icc, password));
++ check(krb5_init_creds_get(ctx, icc));
++ krb5_init_creds_free(ctx, icc);
++
++ krb5_free_principal(ctx, client);
++ krb5_free_context(ctx);
++ return 0;
++}
diff --git a/krb5.spec b/krb5.spec
index 2033e47..a56d346 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -80,6 +80,8 @@ Patch119: krb5-fast-msg_type.patch
Patch120: krb5-1.11.2-kpasswd_pingpong.patch
Patch121: krb5-cccol-primary.patch
Patch122: krb5-1.11.2-gss_transited.patch
+Patch123: krb5-1.11.2-empty_passwords.patch
+Patch124: krb5-1.11.2-arcfour_short.patch
# Patches for otp plugin backport
Patch201: krb5-1.11.2-keycheck.patch
@@ -302,6 +304,8 @@ ln -s NOTICE LICENSE
%patch120 -p1 -b .kpasswd_pingpong
%patch121 -p1 -b .cccol-primary
%patch122 -p1 -b .gss_transited
+%patch123 -p1 -b .empty_passwords
+%patch124 -p1 -b .arcfour_short
%patch201 -p1 -b .keycheck
%patch202 -p1 -b .otp
@@ -830,6 +834,8 @@ exit 0
* Tue May 28 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-7
- backport fix for not being able to verify the list of transited realms
in GSS acceptors (RT#7639, #959685)
+- backport fix for not being able to pass an empty password to the
+ get-init-creds APIs and have them actually use it (RT#7642, #960001)
* Tue May 21 2013 Nalin Dahyabhai <nalin@redhat.com> 1.11.2-6
- pull in upstream fix to start treating a KRB5CCNAME value that begins