summaryrefslogtreecommitdiff
path: root/source4/kdc
diff options
context:
space:
mode:
Diffstat (limited to 'source4/kdc')
-rw-r--r--source4/kdc/hdb-ldb.c131
-rw-r--r--source4/kdc/pac-glue.c317
-rw-r--r--source4/kdc/pac-glue.h52
3 files changed, 390 insertions, 110 deletions
diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c
index 87e8273898..8b61914dae 100644
--- a/source4/kdc/hdb-ldb.c
+++ b/source4/kdc/hdb-ldb.c
@@ -73,12 +73,6 @@ static const char *realm_ref_attrs[] = {
NULL
};
-struct hdb_ldb_private {
- struct ldb_context *samdb;
- struct ldb_message **msg;
- struct ldb_message **realm_ref_msg;
-};
-
static KerberosTime ldb_msg_find_krb5time_ldap_time(struct ldb_message *msg, const char *attr, KerberosTime default_val)
{
const char *tmp;
@@ -177,13 +171,10 @@ static HDBFlags uf2HDBFlags(krb5_context context, int userAccountControl, enum h
if (userAccountControl & UF_SMARTCARD_REQUIRED) {
flags.require_hwauth = 1;
}
- if (flags.server && (userAccountControl & UF_TRUSTED_FOR_DELEGATION)) {
- flags.forwardable = 1;
- flags.proxiable = 1;
- } else if (flags.client && (userAccountControl & UF_NOT_DELEGATED)) {
- flags.forwardable = 0;
- flags.proxiable = 0;
- } else {
+ if (userAccountControl & UF_TRUSTED_FOR_DELEGATION) {
+ flags.ok_as_delegate = 1;
+ }
+ if (!(userAccountControl & UF_NOT_DELEGATED)) {
flags.forwardable = 1;
flags.proxiable = 1;
}
@@ -205,6 +196,12 @@ static HDBFlags uf2HDBFlags(krb5_context context, int userAccountControl, enum h
return flags;
}
+static krb5_error_code hdb_ldb_free_private(krb5_context context, hdb_entry_ex *entry_ex)
+{
+ talloc_free(entry_ex->private);
+ return 0;
+}
+
/*
* Construct an hdb_entry from a directory entry.
*/
@@ -213,15 +210,17 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
enum hdb_ldb_ent_type ent_type,
struct ldb_message *msg,
struct ldb_message *realm_ref_msg,
- hdb_entry *ent)
+ hdb_entry_ex *entry_ex)
{
const char *unicodePwd;
- int userAccountControl;
+ unsigned int userAccountControl;
int i;
krb5_error_code ret = 0;
const char *dnsdomain = ldb_msg_find_string(realm_ref_msg, "dnsRoot", NULL);
char *realm = strupper_talloc(mem_ctx, dnsdomain);
+ struct hdb_ldb_private *private;
+ hdb_entry *ent = &entry_ex->entry;
memset(ent, 0, sizeof(*ent));
@@ -233,7 +232,7 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
goto out;
}
- userAccountControl = ldb_msg_find_int(msg, "userAccountControl", 0);
+ userAccountControl = ldb_msg_find_uint(msg, "userAccountControl", 0);
ent->principal = malloc(sizeof(*(ent->principal)));
if (ent_type == HDB_LDB_ENT_TYPE_ANY && principal == NULL) {
@@ -279,6 +278,7 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
if (ent_type == HDB_LDB_ENT_TYPE_KRBTGT) {
ent->flags.invalid = 0;
ent->flags.server = 1;
+ ent->flags.forwardable = 1;
}
if (lp_parm_bool(-1, "kdc", "require spn for service", True)) {
@@ -399,7 +399,7 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
} else {
ret = krb5_data_alloc (&keyvalue, 16);
if (ret) {
- krb5_set_error_string(context, "malloc: out of memory");
+ krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
@@ -409,7 +409,7 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
ent->keys.val = malloc(sizeof(ent->keys.val[0]));
if (ent->keys.val == NULL) {
krb5_data_free(&keyvalue);
- krb5_set_error_string(context, "malloc: out of memory");
+ krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
@@ -425,14 +425,14 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
ent->etypes = malloc(sizeof(*(ent->etypes)));
if (ent->etypes == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
+ krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
ent->etypes->len = ent->keys.len;
ent->etypes->val = calloc(ent->etypes->len, sizeof(int));
if (ent->etypes->val == NULL) {
- krb5_set_error_string(context, "malloc: out of memory");
+ krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
@@ -440,10 +440,27 @@ static krb5_error_code LDB_message2entry(krb5_context context, HDB *db,
ent->etypes->val[i] = ent->keys.val[i].key.keytype;
}
+
+ private = talloc(db, struct hdb_ldb_private);
+ if (!private) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ private->msg = talloc_steal(private, msg);
+ private->realm_ref_msg = talloc_steal(private, realm_ref_msg);
+ private->samdb = (struct ldb_context *)db->hdb_db;
+
+ entry_ex->private = private;
+ entry_ex->free_private = hdb_ldb_free_private;
+ entry_ex->check_client_access = hdb_ldb_check_client_access;
+ entry_ex->authz_data_tgs_req = hdb_ldb_authz_data_tgs_req;
+ entry_ex->authz_data_as_req = hdb_ldb_authz_data_as_req;
+
out:
if (ret != 0) {
- /* I don't think this frees ent itself. */
- hdb_free_entry(context, ent);
+ /* This doesn't free ent itself, that is for the eventual caller to do */
+ hdb_free_entry(context, &entry_ex->entry);
}
return ret;
@@ -618,44 +635,6 @@ static krb5_error_code LDB_rename(krb5_context context, HDB *db, const char *new
return HDB_ERR_DB_INUSE;
}
-static krb5_error_code hdb_ldb_free_private(krb5_context context, hdb_entry_ex *entry_ex)
-{
- talloc_free(entry_ex->private);
- return 0;
-}
-
-static krb5_error_code hdb_ldb_check_client_access(krb5_context context, hdb_entry_ex *entry_ex,
- HostAddresses *addresses)
-{
- krb5_error_code ret;
- NTSTATUS nt_status;
- TALLOC_CTX *tmp_ctx = talloc_new(entry_ex->private);
- struct hdb_ldb_private *private = entry_ex->private;
- char *name, *workstation = NULL;
- if (!tmp_ctx) {
- return ENOMEM;
- }
-
- ret = krb5_unparse_name(context, entry_ex->entry.principal, &name);
- if (ret != 0) {
- talloc_free(tmp_ctx);
- }
- nt_status = authsam_account_ok(tmp_ctx,
- private->samdb,
- MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
- private->msg,
- private->realm_ref_msg,
- workstation,
- name);
- free(name);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return KRB5KDC_ERR_POLICY;
- }
- return 0;
-}
-
-
static krb5_error_code LDB_fetch_ex(krb5_context context, HDB *db, unsigned flags,
krb5_const_principal principal,
enum hdb_ent_type ent_type,
@@ -703,22 +682,7 @@ static krb5_error_code LDB_fetch_ex(krb5_context context, HDB *db, unsigned flag
ret = LDB_message2entry(context, db, mem_ctx,
principal, ldb_ent_type,
- msg[0], realm_ref_msg[0], &entry_ex->entry);
-
- if (ret == 0) {
- struct hdb_ldb_private *private = talloc(db, struct hdb_ldb_private);
- if (!private) {
- hdb_free_entry(context, &entry_ex->entry);
- ret = ENOMEM;
- }
- private->msg = talloc_steal(private, msg);
- private->realm_ref_msg = talloc_steal(private, realm_ref_msg);
- private->samdb = (struct ldb_context *)db->hdb_db;
-
- entry_ex->private = private;
- entry_ex->free_private = hdb_ldb_free_private;
- entry_ex->check_client_access = hdb_ldb_check_client_access;
- }
+ msg[0], realm_ref_msg[0], entry_ex);
talloc_free(mem_ctx);
return ret;
@@ -802,7 +766,7 @@ static krb5_error_code LDB_fetch_ex(krb5_context context, HDB *db, unsigned flag
ret = LDB_message2entry(context, db, mem_ctx,
principal, ldb_ent_type,
- msg[0], realm_ref_msg[0], &entry_ex->entry);
+ msg[0], realm_ref_msg[0], entry_ex);
talloc_free(mem_ctx);
return ret;
@@ -845,7 +809,7 @@ static krb5_error_code LDB_fetch_ex(krb5_context context, HDB *db, unsigned flag
} else {
ret = LDB_message2entry(context, db, mem_ctx,
principal, ldb_ent_type,
- msg[0], realm_ref_msg[0], &entry_ex->entry);
+ msg[0], realm_ref_msg[0], entry_ex);
if (ret != 0) {
krb5_warnx(context, "LDB_fetch: message2entry failed\n");
}
@@ -898,6 +862,9 @@ static krb5_error_code LDB_seq(krb5_context context, HDB *db, unsigned flags, hd
krb5_error_code ret;
struct hdb_ldb_seq *priv = (struct hdb_ldb_seq *)db->hdb_openp;
TALLOC_CTX *mem_ctx;
+ hdb_entry_ex entry_ex;
+ memset(&entry_ex, '\0', sizeof(entry_ex));
+
if (!priv) {
return HDB_ERR_NOENTRY;
}
@@ -913,7 +880,13 @@ static krb5_error_code LDB_seq(krb5_context context, HDB *db, unsigned flags, hd
ret = LDB_message2entry(context, db, mem_ctx,
NULL, HDB_LDB_ENT_TYPE_ANY,
priv->msgs[priv->index++],
- priv->realm_ref_msgs[0], entry);
+ priv->realm_ref_msgs[0], &entry_ex);
+ if (ret == 0) {
+ if (entry_ex.free_private) {
+ entry_ex.free_private(context, &entry_ex);
+ }
+ *entry = entry_ex.entry;
+ }
} else {
ret = HDB_ERR_NOENTRY;
}
diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
index ae306b4062..03b53fa3af 100644
--- a/source4/kdc/pac-glue.c
+++ b/source4/kdc/pac-glue.c
@@ -23,42 +23,41 @@
#include "includes.h"
#include "kdc/kdc.h"
-#include "kdc/pac-glue.h" /* Ensure we don't get this prototype wrong, as that could be painful */
-
- krb5_error_code samba_get_pac(krb5_context context,
- struct krb5_kdc_configuration *config,
- krb5_principal client,
- krb5_keyblock *krbtgt_keyblock,
- krb5_keyblock *server_keyblock,
- time_t tgs_authtime,
- krb5_data *pac)
+#include "include/ads.h"
+#include "lib/ldb/include/ldb.h"
+#include "heimdal/lib/krb5/krb5_locl.h"
+#include "librpc/gen_ndr/krb5pac.h"
+#include "auth/auth.h"
+
+/* Given the right private pointer from hdb_ldb, get a PAC from the attached ldb messages */
+static krb5_error_code samba_get_pac(krb5_context context,
+ struct hdb_ldb_private *private,
+ krb5_principal client,
+ krb5_keyblock *krbtgt_keyblock,
+ krb5_keyblock *server_keyblock,
+ time_t tgs_authtime,
+ krb5_data *pac)
{
krb5_error_code ret;
NTSTATUS nt_status;
struct auth_serversupplied_info *server_info;
DATA_BLOB tmp_blob;
- char *principal_string;
- TALLOC_CTX *mem_ctx = talloc_named(config, 0, "samba_get_pac context");
+ TALLOC_CTX *mem_ctx = talloc_named(private, 0, "samba_get_pac context");
+
if (!mem_ctx) {
return ENOMEM;
}
- ret = krb5_unparse_name(context, client, &principal_string);
-
- if (ret != 0) {
- krb5_set_error_string(context, "get pac: could not unparse principal");
- krb5_warnx(context, "get pac: could not unparse principal");
- talloc_free(mem_ctx);
- return ret;
- }
-
- nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
- &server_info);
- free(principal_string);
+ nt_status = authsam_make_server_info(mem_ctx, private->samdb,
+ private->msg,
+ private->realm_ref_msg,
+ data_blob(NULL, 0),
+ data_blob(NULL, 0),
+ &server_info);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("Getting user info for PAC failed: %s\n",
nt_errstr(nt_status)));
- return EINVAL;
+ return ENOMEM;
}
ret = kerberos_create_pac(mem_ctx, server_info,
@@ -80,3 +79,273 @@
talloc_free(mem_ctx);
return ret;
}
+
+/* Wrap the PAC in the right ASN.1. Will always free 'pac', on success or failure */
+krb5_error_code wrap_pac(krb5_context context, krb5_data *pac, AuthorizationData **out)
+{
+ krb5_error_code ret;
+
+ unsigned char *buf;
+ size_t buf_size;
+ size_t len;
+
+ AD_IF_RELEVANT if_relevant;
+ AuthorizationData *auth_data;
+
+ if_relevant.len = 1;
+ if_relevant.val = malloc(sizeof(*if_relevant.val));
+ if (!if_relevant.val) {
+ krb5_data_free(pac);
+ *out = NULL;
+ return ENOMEM;
+ }
+
+ if_relevant.val[0].ad_type = KRB5_AUTHDATA_WIN2K_PAC;
+ if_relevant.val[0].ad_data.data = NULL;
+ if_relevant.val[0].ad_data.length = 0;
+
+ /* pac.data will be freed with this */
+ if_relevant.val[0].ad_data.data = pac->data;
+ if_relevant.val[0].ad_data.length = pac->length;
+
+ ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, &if_relevant, &len, ret);
+ free_AuthorizationData(&if_relevant);
+ if (ret) {
+ *out = NULL;
+ return ret;
+ }
+
+ auth_data = malloc(sizeof(*auth_data));
+ if (!auth_data) {
+ free(buf);
+ *out = NULL;
+ return ret;
+ }
+ auth_data->len = 1;
+ auth_data->val = malloc(sizeof(*auth_data->val));
+ if (!auth_data->val) {
+ free(buf);
+ free(auth_data);
+ *out = NULL;
+ return ret;
+ }
+ auth_data->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+ auth_data->val[0].ad_data.length = len;
+ auth_data->val[0].ad_data.data = buf;
+
+ *out = auth_data;
+ return 0;
+}
+
+
+/* Given a hdb_entry, create a PAC out of the private data
+
+ Don't create it if the client has the UF_NO_AUTH_DATA_REQUIRED bit
+ set, or if they specificaly asked not to get it.
+*/
+
+ krb5_error_code hdb_ldb_authz_data_as_req(krb5_context context, struct hdb_entry_ex *entry_ex,
+ METHOD_DATA* pa_data_seq,
+ time_t authtime,
+ EncryptionKey *tgtkey,
+ EncryptionKey *sessionkey,
+ AuthorizationData **out)
+{
+ krb5_error_code ret;
+ int i;
+ krb5_data pac;
+ krb5_boolean pac_wanted = TRUE;
+ unsigned int userAccountControl;
+ struct PA_PAC_REQUEST pac_request;
+ struct hdb_ldb_private *private = talloc_get_type(entry_ex->private, struct hdb_ldb_private);
+
+ /* The user account may be set not to want the PAC */
+ userAccountControl = ldb_msg_find_uint(private->msg, "userAccountControl", 0);
+ if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
+ *out = NULL;
+ return 0;
+ }
+
+ /* The user may not want a PAC */
+ for (i=0; i<pa_data_seq->len; i++) {
+ if (pa_data_seq->val[i].padata_type == KRB5_PADATA_PA_PAC_REQUEST) {
+ ret = decode_PA_PAC_REQUEST(pa_data_seq->val[i].padata_value.data,
+ pa_data_seq->val[i].padata_value.length,
+ &pac_request, NULL);
+ if (ret == 0) {
+ pac_wanted = !!pac_request.include_pac;
+ }
+ free_PA_PAC_REQUEST(&pac_request);
+ break;
+ }
+ }
+
+ if (!pac_wanted) {
+ *out = NULL;
+ return 0;
+ }
+
+ /* Get PAC from Samba */
+ ret = samba_get_pac(context,
+ private,
+ entry_ex->entry.principal,
+ tgtkey,
+ tgtkey,
+ authtime,
+ &pac);
+
+ if (ret) {
+ *out = NULL;
+ return ret;
+ }
+
+ return wrap_pac(context, &pac, out);
+}
+
+/* Resign (and reform, including possibly new groups) a PAC */
+
+ krb5_error_code hdb_ldb_authz_data_tgs_req(krb5_context context, struct hdb_entry_ex *entry_ex,
+ krb5_principal client,
+ AuthorizationData *in,
+ time_t authtime,
+ EncryptionKey *tgtkey,
+ EncryptionKey *servicekey,
+ EncryptionKey *sessionkey,
+ AuthorizationData **out)
+{
+ NTSTATUS nt_status;
+ krb5_error_code ret;
+
+ unsigned int userAccountControl;
+
+ struct hdb_ldb_private *private = talloc_get_type(entry_ex->private, struct hdb_ldb_private);
+ krb5_data k5pac_in, k5pac_out;
+ DATA_BLOB pac_in, pac_out;
+
+ struct PAC_LOGON_INFO *logon_info;
+ union netr_Validation validation;
+ struct auth_serversupplied_info *server_info_out;
+
+ krb5_boolean found = FALSE;
+ TALLOC_CTX *mem_ctx;
+
+ /* The service account may be set not to want the PAC */
+ userAccountControl = ldb_msg_find_uint(private->msg, "userAccountControl", 0);
+ if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
+ *out = NULL;
+ return 0;
+ }
+
+ ret = _krb5_find_type_in_ad(context, KRB5_AUTHDATA_WIN2K_PAC,
+ &k5pac_in, &found, sessionkey, in);
+ if (ret || !found) {
+ *out = NULL;
+ return 0;
+ }
+
+ mem_ctx = talloc_new(private);
+ if (!mem_ctx) {
+ krb5_data_free(&k5pac_in);
+ *out = NULL;
+ return ENOMEM;
+ }
+
+ pac_in = data_blob_talloc(mem_ctx, k5pac_in.data, k5pac_in.length);
+ krb5_data_free(&k5pac_in);
+ if (!pac_in.data) {
+ talloc_free(mem_ctx);
+ *out = NULL;
+ return ENOMEM;
+ }
+
+ /* Parse the PAC again, for the logon info */
+ nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info,
+ pac_in,
+ context,
+ tgtkey,
+ tgtkey,
+ client, authtime,
+ &ret);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(1, ("Failed to parse PAC in TGT: %s/%s\n",
+ nt_errstr(nt_status), error_message(ret)));
+ talloc_free(mem_ctx);
+ *out = NULL;
+ return ret;
+ }
+
+ /* Pull this right into the normal auth sysstem structures */
+ validation.sam3 = &logon_info->info3;
+ nt_status = make_server_info_netlogon_validation(mem_ctx,
+ "",
+ 3, &validation,
+ &server_info_out);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ *out = NULL;
+ return ENOMEM;
+ }
+
+ /* And make a new PAC, possibly containing new groups */
+ ret = kerberos_create_pac(mem_ctx,
+ server_info_out,
+ context,
+ tgtkey,
+ servicekey,
+ client,
+ authtime,
+ &pac_out);
+
+ if (ret != 0) {
+ talloc_free(mem_ctx);
+ *out = NULL;
+ return ret;
+ }
+
+ ret = krb5_data_copy(&k5pac_out, pac_out.data, pac_out.length);
+ if (ret != 0) {
+ talloc_free(mem_ctx);
+ *out = NULL;
+ return ret;
+ }
+
+ return wrap_pac(context, &k5pac_out, out);
+}
+
+/* Given an hdb entry (and in particular it's private member), consult
+ * the account_ok routine in auth/auth_sam.c for consistancy */
+
+ krb5_error_code hdb_ldb_check_client_access(krb5_context context, hdb_entry_ex *entry_ex,
+ HostAddresses *addresses)
+{
+ krb5_error_code ret;
+ NTSTATUS nt_status;
+ TALLOC_CTX *tmp_ctx = talloc_new(entry_ex->private);
+ struct hdb_ldb_private *private = talloc_get_type(entry_ex->private, struct hdb_ldb_private);
+ char *name, *workstation = NULL;
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ ret = krb5_unparse_name(context, entry_ex->entry.principal, &name);
+ if (ret != 0) {
+ talloc_free(tmp_ctx);
+ }
+ nt_status = authsam_account_ok(tmp_ctx,
+ private->samdb,
+ MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
+ private->msg,
+ private->realm_ref_msg,
+ workstation,
+ name);
+ free(name);
+
+ /* TODO: Need a more complete mapping of NTSTATUS to krb5kdc errors */
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return KRB5KDC_ERR_POLICY;
+ }
+ return 0;
+}
+
diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h
index 69490bb7f3..953ddae815 100644
--- a/source4/kdc/pac-glue.h
+++ b/source4/kdc/pac-glue.h
@@ -1,8 +1,46 @@
+/*
+ Unix SMB/CIFS implementation.
- krb5_error_code samba_get_pac(krb5_context context,
- struct krb5_kdc_configuration *config,
- krb5_principal client,
- krb5_keyblock *krbtgt_keyblock,
- krb5_keyblock *server_keyblock,
- time_t tgs_authtime,
- krb5_data *pac);
+ PAC Glue between Samba and the KDC
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+ struct hdb_ldb_private {
+ struct ldb_context *samdb;
+ struct ldb_message *msg;
+ struct ldb_message *realm_ref_msg;
+ };
+
+ krb5_error_code hdb_ldb_authz_data_as_req(krb5_context context, struct hdb_entry_ex *entry_ex,
+ METHOD_DATA* pa_data_seq,
+ time_t authtime,
+ EncryptionKey *tgtkey,
+ EncryptionKey *sessionkey,
+ AuthorizationData **out);
+
+ krb5_error_code hdb_ldb_authz_data_tgs_req(krb5_context context, struct hdb_entry_ex *entry_ex,
+ krb5_principal client,
+ AuthorizationData *in,
+ time_t authtime,
+ EncryptionKey *tgtkey,
+ EncryptionKey *servicekey,
+ EncryptionKey *sessionkey,
+ AuthorizationData **out);
+ krb5_error_code hdb_ldb_check_client_access(krb5_context context, hdb_entry_ex *entry_ex,
+ HostAddresses *addresses);