krb5: fail krb5_verify_user() early if service key missing
Fixes #1157.
This commit is contained in:
committed by
Nico Williams
parent
73bab3fea5
commit
3ff4191ba9
@@ -63,6 +63,89 @@ test_empty_keytab(krb5_context context, const char *keytab)
|
||||
krb5_err(context, 1, ret, "krb5_kt_close");
|
||||
}
|
||||
|
||||
static void
|
||||
test_verify_user_empty_keytab(krb5_context context, const char *keytab)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_keytab id;
|
||||
krb5_principal principal;
|
||||
krb5_verify_opt opt;
|
||||
|
||||
ret = krb5_kt_resolve(context, keytab, &id);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_kt_resolve");
|
||||
|
||||
ret = krb5_parse_name(context, "lha@SU.SE", &principal);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_parse_name");
|
||||
|
||||
krb5_verify_opt_init(&opt);
|
||||
krb5_verify_opt_set_keytab(&opt, id);
|
||||
|
||||
ret = krb5_verify_user_opt(context, principal, "password", &opt);
|
||||
if (ret != KRB5_KT_NOTFOUND)
|
||||
krb5_errx(context, 1,
|
||||
"krb5_verify_user_opt returned %d, expected %d",
|
||||
(int)ret, (int)KRB5_KT_NOTFOUND);
|
||||
|
||||
krb5_free_principal(context, principal);
|
||||
|
||||
ret = krb5_kt_close(context, id);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_kt_close");
|
||||
}
|
||||
|
||||
static void
|
||||
test_verify_user_wrong_keytab(krb5_context context, const char *keytab)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_keytab id;
|
||||
krb5_keytab_entry entry;
|
||||
krb5_principal principal;
|
||||
krb5_verify_opt opt;
|
||||
|
||||
ret = krb5_kt_resolve(context, keytab, &id);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_kt_resolve");
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
ret = krb5_parse_name(context, "not-host/foo@SU.SE", &entry.principal);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_parse_name");
|
||||
entry.vno = 1;
|
||||
ret = krb5_generate_random_keyblock(context,
|
||||
ETYPE_AES256_CTS_HMAC_SHA1_96,
|
||||
&entry.keyblock);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_generate_random_keyblock");
|
||||
|
||||
ret = krb5_kt_add_entry(context, id, &entry);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_kt_add_entry");
|
||||
|
||||
ret = krb5_parse_name(context, "lha@SU.SE", &principal);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_parse_name");
|
||||
|
||||
krb5_verify_opt_init(&opt);
|
||||
krb5_verify_opt_set_keytab(&opt, id);
|
||||
|
||||
ret = krb5_verify_user_opt(context, principal, "password", &opt);
|
||||
if (ret != KRB5_KT_NOTFOUND)
|
||||
krb5_errx(context, 1,
|
||||
"krb5_verify_user_opt returned %d, expected %d",
|
||||
(int)ret, (int)KRB5_KT_NOTFOUND);
|
||||
|
||||
krb5_free_principal(context, principal);
|
||||
krb5_kt_remove_entry(context, id, &entry);
|
||||
krb5_free_principal(context, entry.principal);
|
||||
krb5_free_keyblock_contents(context, &entry.keyblock);
|
||||
|
||||
ret = krb5_kt_close(context, id);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_kt_close");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that memory keytab are refcounted.
|
||||
*/
|
||||
@@ -281,6 +364,13 @@ main(int argc, char **argv)
|
||||
test_empty_keytab(context, "MEMORY:foo");
|
||||
test_empty_keytab(context, "FILE:foo");
|
||||
|
||||
ret = krb5_set_default_realm(context, "SU.SE");
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "krb5_set_default_realm");
|
||||
|
||||
test_verify_user_empty_keytab(context, "MEMORY:verify-user-empty");
|
||||
test_verify_user_wrong_keytab(context, "MEMORY:verify-user-wrong");
|
||||
|
||||
test_memory_keytab(context, "MEMORY:foo", "MEMORY:foo2");
|
||||
|
||||
}
|
||||
|
||||
+44
-1
@@ -33,6 +33,40 @@
|
||||
|
||||
#include "krb5_locl.h"
|
||||
|
||||
static krb5_error_code
|
||||
check_server_keytab(krb5_context context, krb5_keytab keytab,
|
||||
const char *service)
|
||||
{
|
||||
krb5_error_code ret, ret2;
|
||||
krb5_keytab_entry entry;
|
||||
krb5_keytab kt = keytab;
|
||||
krb5_principal server;
|
||||
|
||||
ret = krb5_sname_to_principal(context, NULL, service, KRB5_NT_SRV_HST,
|
||||
&server);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (kt == NULL) {
|
||||
ret = krb5_kt_default(context, &kt);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = krb5_kt_get_entry(context, kt, server, 0, 0, &entry);
|
||||
if (ret == 0)
|
||||
krb5_kt_free_entry(context, &entry);
|
||||
if (keytab == NULL) {
|
||||
ret2 = krb5_kt_close(context, kt);
|
||||
if (ret == 0)
|
||||
ret = ret2;
|
||||
}
|
||||
|
||||
out:
|
||||
krb5_free_principal(context, server);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
verify_common (krb5_context context,
|
||||
krb5_principal principal,
|
||||
@@ -185,7 +219,16 @@ krb5_verify_user_opt(krb5_context context,
|
||||
const char *password,
|
||||
krb5_verify_opt *opt)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_error_code ret = 0;
|
||||
|
||||
#define OPT(V, D) ((opt && (opt->V)) ? (opt->V) : (D))
|
||||
if (opt == NULL || opt->secure) {
|
||||
ret = check_server_keytab(context, OPT(keytab, NULL),
|
||||
OPT(service, "host"));
|
||||
}
|
||||
#undef OPT
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if(opt && (opt->flags & KRB5_VERIFY_LREALMS)) {
|
||||
krb5_realm *realms, *r;
|
||||
|
||||
Reference in New Issue
Block a user