httpkadmind: Support ok-as-delegate and such
Add support for configuring the attributes of new principals created via httpkadmind. This can be done via virtual host-based service namespaces, which will provide default attributes even if disabled (but the created principals will not be disabled, naturally), or via krb5.conf.
This commit is contained in:
@@ -140,6 +140,11 @@ If the named principal(s) is (are) virtual, this will cause it
|
|||||||
.It Ar create=true
|
.It Ar create=true
|
||||||
If the named principal(s) does not (do not) exist, this will
|
If the named principal(s) does not (do not) exist, this will
|
||||||
cause it (them) to be created.
|
cause it (them) to be created.
|
||||||
|
The default attributes for new principals created this way will
|
||||||
|
be taken from any containing virtual host-based service principal
|
||||||
|
namespace (not including the disabled attribute), or from
|
||||||
|
.Nm krb5.conf(5)
|
||||||
|
(see the CONFIGURATION section).
|
||||||
.It Ar rotate=true
|
.It Ar rotate=true
|
||||||
This will cause the keys of concrete principals to be rotated.
|
This will cause the keys of concrete principals to be rotated.
|
||||||
.It Ar revoke=true
|
.It Ar revoke=true
|
||||||
@@ -150,6 +155,31 @@ the target will not be able to be decrypted by the caller as it
|
|||||||
will not have the necessary keys.
|
will not have the necessary keys.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
The HTTP
|
||||||
|
.Nm Cache-Control
|
||||||
|
header will be set on
|
||||||
|
.Nm get-keys
|
||||||
|
responses to
|
||||||
|
.Dq Nm no-store ,
|
||||||
|
and the
|
||||||
|
.Nm max-age
|
||||||
|
cache control parameter will be set to the least number of
|
||||||
|
seconds until before any of the requested principal's keys could
|
||||||
|
change.
|
||||||
|
For virtual principals this will be either the time left until a
|
||||||
|
quarter of the rotation period before the next rotation, or the
|
||||||
|
time left until a
|
||||||
|
quarter of the rotation period after the next rotation.
|
||||||
|
For concrete principals this will be the time left to the first
|
||||||
|
such principal's password expiration, or, if none of them have a
|
||||||
|
configured password expiration time, then half of the
|
||||||
|
.Nm new_service_key_delay
|
||||||
|
configured in the
|
||||||
|
.Nm [hdb]
|
||||||
|
section of the
|
||||||
|
.Nm krb5.conf(5)
|
||||||
|
file.
|
||||||
|
.Pp
|
||||||
Authorization is handled via the same mechanism as in
|
Authorization is handled via the same mechanism as in
|
||||||
.Nm bx509d(8)
|
.Nm bx509d(8)
|
||||||
which was originally intended to authorize certification requests
|
which was originally intended to authorize certification requests
|
||||||
@@ -160,9 +190,10 @@ but using
|
|||||||
.Nm [ext_keytab]
|
.Nm [ext_keytab]
|
||||||
as the
|
as the
|
||||||
.Nm krb5.conf(5) section.
|
.Nm krb5.conf(5) section.
|
||||||
Clients with host-based principals for the the host service can
|
Clients with host-based principals for the
|
||||||
create and extract keys for their own service name, but otherwise
|
.Dq host
|
||||||
a number of service names are not denied:
|
service can create and extract keys for their own service name,
|
||||||
|
but otherwise a number of service names are denied:
|
||||||
.Bl -tag -width Ds -offset indent
|
.Bl -tag -width Ds -offset indent
|
||||||
.It Dq host
|
.It Dq host
|
||||||
.It Dq root
|
.It Dq root
|
||||||
@@ -361,11 +392,58 @@ Authorizer configuration goes in
|
|||||||
in
|
in
|
||||||
.Nm krb5.conf(5). For example:
|
.Nm krb5.conf(5). For example:
|
||||||
.Pp
|
.Pp
|
||||||
|
.Bd -literal -offset indent
|
||||||
[ext_keytab]
|
[ext_keytab]
|
||||||
simple_csr_authorizer_directory = /etc/krb5/simple_csr_authz
|
simple_csr_authorizer_directory = /etc/krb5/simple_csr_authz
|
||||||
ipc_csr_authorizer = {
|
ipc_csr_authorizer = {
|
||||||
service = UNIX:/var/heimdal/csr_authorizer_sock
|
service = UNIX:/var/heimdal/csr_authorizer_sock
|
||||||
}
|
}
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Configuration parameters specific to
|
||||||
|
.Nm httpkadmind :
|
||||||
|
.Bl -tag -width Ds -offset indent
|
||||||
|
.It csr_authorizer_handles_svc_names = BOOL
|
||||||
|
.It new_hostbased_service_principal_attributes = ...
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Nm [ext_keytab]
|
||||||
|
.Nm new_hostbased_service_principal_attributes
|
||||||
|
parameter may be used instead of virtual host-based service
|
||||||
|
namespace principals to specify the attributes of new principals
|
||||||
|
created by
|
||||||
|
.Nm httpkadmind ,
|
||||||
|
and its value is a hive with a service name then a hostname or
|
||||||
|
namespace, and whose value is a set of attributes as given in the
|
||||||
|
.Nm kadmin(1) modify
|
||||||
|
command.
|
||||||
|
For example:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
[ext_keytab]
|
||||||
|
new_hostbased_service_principal_attributes = {
|
||||||
|
host = {
|
||||||
|
a-particular-hostname.test.h5l.se = ok-as-delegate
|
||||||
|
.prod.test.h5l.se = ok-as-delegate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
which means that
|
||||||
|
.Dq host/a-particular-hostname.test.h5l.se ,
|
||||||
|
if created via
|
||||||
|
.Nm httpkadmind ,
|
||||||
|
will be allowed to get delegated credentials (ticket forwarding),
|
||||||
|
and that hostnames matching the glob pattern
|
||||||
|
.Dq host/*.prod.test.h5l.se ,
|
||||||
|
if created via
|
||||||
|
.Nm httpkadmind ,
|
||||||
|
will also allowed to get delegated credentials.
|
||||||
|
All host-based service principals created via
|
||||||
|
.Nm httpkadmind
|
||||||
|
not matchining any
|
||||||
|
.Nm new_hostbased_service_principal_attributes
|
||||||
|
service namespaces will have the empty attribute set.
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
To start
|
To start
|
||||||
.Nm httpkadmind
|
.Nm httpkadmind
|
||||||
|
@@ -177,6 +177,7 @@ typedef struct kadmin_request_desc {
|
|||||||
char *freeme1;
|
char *freeme1;
|
||||||
char *enctypes;
|
char *enctypes;
|
||||||
const char *method;
|
const char *method;
|
||||||
|
krb5_timestamp pw_end;
|
||||||
unsigned int response_set:1;
|
unsigned int response_set:1;
|
||||||
unsigned int materialize:1;
|
unsigned int materialize:1;
|
||||||
unsigned int rotate_now:1;
|
unsigned int rotate_now:1;
|
||||||
@@ -657,8 +658,36 @@ resp(kadmin_request_desc r,
|
|||||||
rmmode);
|
rmmode);
|
||||||
if (response == NULL)
|
if (response == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
mret = MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL,
|
mret = MHD_add_response_header(response, MHD_HTTP_HEADER_AGE, "0");
|
||||||
"no-store, max-age=0");
|
if (mret == MHD_YES && http_status_code == MHD_HTTP_OK) {
|
||||||
|
static HEIMDAL_THREAD_LOCAL char *cache_control = NULL;
|
||||||
|
krb5_timestamp now;
|
||||||
|
|
||||||
|
free(cache_control);
|
||||||
|
cache_control = NULL;
|
||||||
|
krb5_timeofday(r->context, &now);
|
||||||
|
if (r->pw_end && r->pw_end > now) {
|
||||||
|
if (asprintf(&cache_control, "no-store, max-age=%lld",
|
||||||
|
(long long)r->pw_end - now) == -1 ||
|
||||||
|
cache_control == NULL)
|
||||||
|
/* Soft handling of ENOMEM here */
|
||||||
|
mret = MHD_add_response_header(response,
|
||||||
|
MHD_HTTP_HEADER_CACHE_CONTROL,
|
||||||
|
"no-store, max-age=3600");
|
||||||
|
else
|
||||||
|
mret = MHD_add_response_header(response,
|
||||||
|
MHD_HTTP_HEADER_CACHE_CONTROL,
|
||||||
|
cache_control);
|
||||||
|
|
||||||
|
} else
|
||||||
|
mret = MHD_add_response_header(response,
|
||||||
|
MHD_HTTP_HEADER_CACHE_CONTROL,
|
||||||
|
"no-store, max-age=0");
|
||||||
|
} else {
|
||||||
|
/* Shouldn't happen */
|
||||||
|
mret = MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL,
|
||||||
|
"no-store, max-age=0");
|
||||||
|
}
|
||||||
if (mret == MHD_YES && http_status_code == MHD_HTTP_UNAUTHORIZED) {
|
if (mret == MHD_YES && http_status_code == MHD_HTTP_UNAUTHORIZED) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@@ -1215,6 +1244,93 @@ make_kstuple(krb5_context context,
|
|||||||
return *kstuple ? 0 :krb5_enomem(context);
|
return *kstuple ? 0 :krb5_enomem(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copied from kadmin/util.c */
|
||||||
|
struct units kdb_attrs[] = {
|
||||||
|
{ "no-auth-data-reqd", KRB5_KDB_NO_AUTH_DATA_REQUIRED },
|
||||||
|
{ "disallow-client", KRB5_KDB_DISALLOW_CLIENT },
|
||||||
|
{ "virtual", KRB5_KDB_VIRTUAL },
|
||||||
|
{ "virtual-keys", KRB5_KDB_VIRTUAL_KEYS },
|
||||||
|
{ "allow-digest", KRB5_KDB_ALLOW_DIGEST },
|
||||||
|
{ "allow-kerberos4", KRB5_KDB_ALLOW_KERBEROS4 },
|
||||||
|
{ "trusted-for-delegation", KRB5_KDB_TRUSTED_FOR_DELEGATION },
|
||||||
|
{ "ok-as-delegate", KRB5_KDB_OK_AS_DELEGATE },
|
||||||
|
{ "new-princ", KRB5_KDB_NEW_PRINC },
|
||||||
|
{ "support-desmd5", KRB5_KDB_SUPPORT_DESMD5 },
|
||||||
|
{ "pwchange-service", KRB5_KDB_PWCHANGE_SERVICE },
|
||||||
|
{ "disallow-svr", KRB5_KDB_DISALLOW_SVR },
|
||||||
|
{ "requires-pw-change", KRB5_KDB_REQUIRES_PWCHANGE },
|
||||||
|
{ "requires-hw-auth", KRB5_KDB_REQUIRES_HW_AUTH },
|
||||||
|
{ "requires-pre-auth", KRB5_KDB_REQUIRES_PRE_AUTH },
|
||||||
|
{ "disallow-all-tix", KRB5_KDB_DISALLOW_ALL_TIX },
|
||||||
|
{ "disallow-dup-skey", KRB5_KDB_DISALLOW_DUP_SKEY },
|
||||||
|
{ "disallow-proxiable", KRB5_KDB_DISALLOW_PROXIABLE },
|
||||||
|
{ "disallow-renewable", KRB5_KDB_DISALLOW_RENEWABLE },
|
||||||
|
{ "disallow-tgt-based", KRB5_KDB_DISALLOW_TGT_BASED },
|
||||||
|
{ "disallow-forwardable", KRB5_KDB_DISALLOW_FORWARDABLE },
|
||||||
|
{ "disallow-postdated", KRB5_KDB_DISALLOW_POSTDATED },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the default/allowed attributes for some new principal.
|
||||||
|
*/
|
||||||
|
static krb5_flags
|
||||||
|
create_attributes(kadmin_request_desc r, krb5_const_principal p)
|
||||||
|
{
|
||||||
|
krb5_error_code ret;
|
||||||
|
const char *srealm = krb5_principal_get_realm(r->context, p);
|
||||||
|
const char *svc;
|
||||||
|
const char *hn;
|
||||||
|
|
||||||
|
/* Has to be a host-based service principal (for now) */
|
||||||
|
if (krb5_principal_get_num_comp(r->context, p) != 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hn = krb5_principal_get_comp_string(r->context, p, 1);
|
||||||
|
svc = krb5_principal_get_comp_string(r->context, p, 0);
|
||||||
|
|
||||||
|
while (hn && strchr(hn, '.') != NULL) {
|
||||||
|
kadm5_principal_ent_rec nsprinc;
|
||||||
|
krb5_principal nsp;
|
||||||
|
uint64_t a = 0;
|
||||||
|
const char *as;
|
||||||
|
|
||||||
|
/* Try finding a virtual host-based service principal namespace */
|
||||||
|
memset(&nsprinc, 0, sizeof(nsprinc));
|
||||||
|
ret = krb5_make_principal(r->context, &nsp, srealm,
|
||||||
|
KRB5_WELLKNOWN_NAME, HDB_WK_NAMESPACE,
|
||||||
|
svc, hn, NULL);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = kadm5_get_principal(r->kadm_handle, nsp, &nsprinc,
|
||||||
|
KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
|
||||||
|
krb5_free_principal(r->context, nsp);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* Found one; use it even if disabled, but drop that attribute */
|
||||||
|
a = nsprinc.attributes & ~KRB5_KDB_DISALLOW_ALL_TIX;
|
||||||
|
kadm5_free_principal_ent(r->kadm_handle, &nsprinc);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback on krb5.conf */
|
||||||
|
as = krb5_config_get_string(r->context, NULL, "ext_keytab",
|
||||||
|
"new_hostbased_service_principal_attributes",
|
||||||
|
svc, hn, NULL);
|
||||||
|
if (as) {
|
||||||
|
a = parse_flags(as, kdb_attrs, 0);
|
||||||
|
if (a == (uint64_t)-1) {
|
||||||
|
krb5_warnx(r->context, "Invalid value for [ext_keytab] "
|
||||||
|
"new_hostbased_service_principal_attributes");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
hn = strchr(hn + 1, '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get keys for one principal.
|
* Get keys for one principal.
|
||||||
*
|
*
|
||||||
@@ -1229,7 +1345,8 @@ get_keys1(kadmin_request_desc r, const char *pname)
|
|||||||
krb5_principal p = NULL;
|
krb5_principal p = NULL;
|
||||||
uint32_t mask =
|
uint32_t mask =
|
||||||
KADM5_PRINCIPAL | KADM5_KVNO | KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
|
KADM5_PRINCIPAL | KADM5_KVNO | KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
|
||||||
KADM5_ATTRIBUTES | KADM5_KEY_DATA | KADM5_TL_DATA;
|
KADM5_PW_EXPIRATION | KADM5_ATTRIBUTES | KADM5_KEY_DATA |
|
||||||
|
KADM5_TL_DATA;
|
||||||
uint32_t create_mask = mask & ~(KADM5_KEY_DATA | KADM5_TL_DATA);
|
uint32_t create_mask = mask & ~(KADM5_KEY_DATA | KADM5_TL_DATA);
|
||||||
size_t nkstuple = 0;
|
size_t nkstuple = 0;
|
||||||
int change = 0;
|
int change = 0;
|
||||||
@@ -1270,6 +1387,9 @@ get_keys1(kadmin_request_desc r, const char *pname)
|
|||||||
if (ret == KADM5_UNK_PRINC && r->create) {
|
if (ret == KADM5_UNK_PRINC && r->create) {
|
||||||
char pw[128];
|
char pw[128];
|
||||||
|
|
||||||
|
memset(&princ, 0, sizeof(princ));
|
||||||
|
princ.attributes = create_attributes(r, p);
|
||||||
|
|
||||||
if (read_only)
|
if (read_only)
|
||||||
ret = KADM5_READ_ONLY;
|
ret = KADM5_READ_ONLY;
|
||||||
else
|
else
|
||||||
@@ -1281,7 +1401,6 @@ get_keys1(kadmin_request_desc r, const char *pname)
|
|||||||
ret = get_kadm_handle(r->context, r->realm, 1 /* want_write */,
|
ret = get_kadm_handle(r->context, r->realm, 1 /* want_write */,
|
||||||
&r->kadm_handle);
|
&r->kadm_handle);
|
||||||
}
|
}
|
||||||
memset(&princ, 0, sizeof(princ));
|
|
||||||
/*
|
/*
|
||||||
* Some software is allergic to kvno 1, assuming that kvno 1 implies
|
* Some software is allergic to kvno 1, assuming that kvno 1 implies
|
||||||
* half-baked service principal. We've some vague recollection of
|
* half-baked service principal. We've some vague recollection of
|
||||||
@@ -1384,6 +1503,36 @@ get_keys1(kadmin_request_desc r, const char *pname)
|
|||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = write_keytab(r, &princ, pname);
|
ret = write_keytab(r, &princ, pname);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/*
|
||||||
|
* We will use the principal's password expiration to work out the
|
||||||
|
* value for the max-age Cache-Control.
|
||||||
|
*
|
||||||
|
* Virtual service principals will have their `pw_expiration' set to a
|
||||||
|
* time when the client should refetch keys.
|
||||||
|
*
|
||||||
|
* Concrete service principals will generally not have a non-zero
|
||||||
|
* `pw_expiration', but if we have a new_service_key_delay, then we'll
|
||||||
|
* use half of it as the max-age Cache-Control.
|
||||||
|
*/
|
||||||
|
if (princ.pw_expiration == 0) {
|
||||||
|
krb5_timestamp nskd =
|
||||||
|
krb5_config_get_time_default(r->context, NULL, 0, "hdb",
|
||||||
|
"new_service_key_delay", NULL);
|
||||||
|
if (nskd)
|
||||||
|
princ.pw_expiration = time(NULL) + (nskd >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This service can be used to fetch more than one principal's keys, so
|
||||||
|
* the max-age Cache-Control should be derived from the soonest-
|
||||||
|
* "expiring" principal.
|
||||||
|
*/
|
||||||
|
if (r->pw_end == 0 ||
|
||||||
|
(princ.pw_expiration < r->pw_end && princ.pw_expiration > time(NULL)))
|
||||||
|
r->pw_end = princ.pw_expiration;
|
||||||
|
}
|
||||||
if (freeit)
|
if (freeit)
|
||||||
kadm5_free_principal_ent(r->kadm_handle, &princ);
|
kadm5_free_principal_ent(r->kadm_handle, &princ);
|
||||||
krb5_free_principal(r->context, p);
|
krb5_free_principal(r->context, p);
|
||||||
|
@@ -133,9 +133,11 @@ fi
|
|||||||
|
|
||||||
# HTTP curl-opts
|
# HTTP curl-opts
|
||||||
HTTP() {
|
HTTP() {
|
||||||
curl -g --resolve ${server}:${restport2}:127.0.0.1 \
|
curl -g --resolve ${server}:${restport2}:127.0.0.1 \
|
||||||
--resolve ${server}:${restport}:127.0.0.1 \
|
--resolve ${server}:${restport}:127.0.0.1 \
|
||||||
-u: --negotiate $verbose "$@"
|
-u: --negotiate $verbose \
|
||||||
|
-D response-headers \
|
||||||
|
"$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# get_config QPARAMS curl-opts
|
# get_config QPARAMS curl-opts
|
||||||
@@ -145,6 +147,23 @@ get_config() {
|
|||||||
HTTP $verbose "$@" "$url"
|
HTTP $verbose "$@" "$url"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_age() {
|
||||||
|
set -- $(grep -i ^Cache-Control: response-headers)
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
for param in "$@"; do
|
||||||
|
case "$param" in
|
||||||
|
no-store) true;;
|
||||||
|
max-age=0) return 1;;
|
||||||
|
max-age=*) true;;
|
||||||
|
*) return 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
# get_keytab QPARAMS curl-opts
|
# get_keytab QPARAMS curl-opts
|
||||||
get_keytab() {
|
get_keytab() {
|
||||||
url="http://${server}:${restport}/get-keys?$1"
|
url="http://${server}:${restport}/get-keys?$1"
|
||||||
@@ -163,9 +182,9 @@ get_keytab_POST() {
|
|||||||
|
|
||||||
get_keytab "$q" -X POST --data-binary @/dev/null -f "$@" &&
|
get_keytab "$q" -X POST --data-binary @/dev/null -f "$@" &&
|
||||||
{ echo "POST succeeded w/o CSRF token!"; return 1; }
|
{ echo "POST succeeded w/o CSRF token!"; return 1; }
|
||||||
get_keytab "$q" -X POST --data-binary @/dev/null -D response-headers "$@"
|
get_keytab "$q" -X POST --data-binary @/dev/null "$@"
|
||||||
grep ^X-CSRF-Token: response-headers >/dev/null || return 1
|
grep ^X-CSRF-Token: response-headers >/dev/null || return 1
|
||||||
get_keytab "$q" -X POST --data-binary @/dev/null -D response-headers \
|
get_keytab "$q" -X POST --data-binary @/dev/null \
|
||||||
-H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" "$@"
|
-H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" "$@"
|
||||||
grep '^HTTP/1.1 200' response-headers >/dev/null || return $?
|
grep '^HTTP/1.1 200' response-headers >/dev/null || return $?
|
||||||
return 0
|
return 0
|
||||||
@@ -174,7 +193,7 @@ get_keytab_POST() {
|
|||||||
get_keytab_POST_redir() {
|
get_keytab_POST_redir() {
|
||||||
url="http://${server}:${restport}/get-keys?$1"
|
url="http://${server}:${restport}/get-keys?$1"
|
||||||
shift
|
shift
|
||||||
HTTP -X POST --data-binary @/dev/null -D response-headers "$@" "$url"
|
HTTP -X POST --data-binary @/dev/null "$@" "$url"
|
||||||
grep ^X-CSRF-Token: response-headers >/dev/null ||
|
grep ^X-CSRF-Token: response-headers >/dev/null ||
|
||||||
{ echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; }
|
{ echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; }
|
||||||
HTTP -X POST --data-binary @/dev/null -f \
|
HTTP -X POST --data-binary @/dev/null -f \
|
||||||
@@ -292,6 +311,8 @@ ${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin
|
|||||||
{ echo "Failed to list keytab for $p"; exit 1; }
|
{ echo "Failed to list keytab for $p"; exit 1; }
|
||||||
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
|
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
|
||||||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
|
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
|
||||||
|
check_age
|
||||||
|
grep -i ^Cache-Control response-headers
|
||||||
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
|
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
|
||||||
{ echo "Failed to list keytab for $p"; exit 1; }
|
{ echo "Failed to list keytab for $p"; exit 1; }
|
||||||
cmp extracted_keytab.kadmin extracted_keytab.rest ||
|
cmp extracted_keytab.kadmin extracted_keytab.rest ||
|
||||||
|
Reference in New Issue
Block a user