[krb5] Fix handling of empty passwords in get-init-creds

Nalin Dahyabhai nalin at fedoraproject.org
Tue May 28 22:22:22 UTC 2013


commit 827a48f7cc301b20172f12b625f9a40ff838a4a4
Author: Nalin Dahyabhai <nalin at redhat.com>
Date:   Tue May 28 17:21:45 2013 -0400

    Fix handling of empty passwords in get-init-creds

 krb5-1.11.2-arcfour_short.patch   |  122 +++++++++
 krb5-1.11.2-empty_passwords.patch |  492 +++++++++++++++++++++++++++++++++++++
 krb5.spec                         |    6 +
 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 at 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 at 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 at 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 at redhat.com> 1.11.2-6
 - pull in upstream fix to start treating a KRB5CCNAME value that begins


More information about the scm-commits mailing list