summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/auth_sam.c70
-rw-r--r--source4/auth/gensec/gensec_gssapi.c2
-rw-r--r--source4/auth/gensec/gensec_krb5.c2
-rw-r--r--source4/auth/kerberos/kerberos.h6
-rw-r--r--source4/auth/kerberos/kerberos_pac.c32
-rw-r--r--source4/heimdal/kdc/kerberos5.c108
-rw-r--r--source4/heimdal/lib/hdb/hdb.h11
-rw-r--r--source4/heimdal/lib/krb5/krb5-private.h8
-rw-r--r--source4/heimdal/lib/krb5/mk_req.c2
-rw-r--r--source4/heimdal/lib/krb5/ticket.c27
-rw-r--r--source4/kdc/hdb-ldb.c131
-rw-r--r--source4/kdc/pac-glue.c317
-rw-r--r--source4/kdc/pac-glue.h52
-rw-r--r--source4/torture/auth/pac.c15
14 files changed, 545 insertions, 238 deletions
diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c
index 58adb60a5f..56e61ea2a3 100644
--- a/source4/auth/auth_sam.c
+++ b/source4/auth/auth_sam.c
@@ -151,8 +151,8 @@ static NTSTATUS authsam_password_ok(struct auth_context *auth_context,
NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
struct ldb_context *sam_ctx,
uint32_t logon_parameters,
- struct ldb_message **msgs,
- struct ldb_message **msgs_domain_ref,
+ struct ldb_message *msg,
+ struct ldb_message *msg_domain_ref,
const char *logon_workstation,
const char *name_for_logs)
{
@@ -162,20 +162,20 @@ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
NTTIME must_change_time;
NTTIME last_set_time;
- struct ldb_dn *domain_dn = samdb_result_dn(mem_ctx, msgs_domain_ref[0], "nCName", ldb_dn_new(mem_ctx));
+ struct ldb_dn *domain_dn = samdb_result_dn(mem_ctx, msg_domain_ref, "nCName", ldb_dn_new(mem_ctx));
NTTIME now;
DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", name_for_logs));
- acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl");
+ acct_flags = samdb_result_acct_flags(msg, "userAccountControl");
- acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
+ acct_expiry = samdb_result_nttime(msg, "accountExpires", 0);
must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx,
- domain_dn, msgs[0],
+ domain_dn, msg,
"pwdLastSet");
- last_set_time = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
+ last_set_time = samdb_result_nttime(msg, "pwdLastSet", 0);
- workstation_list = samdb_result_string(msgs[0], "userWorkstations", NULL);
+ workstation_list = samdb_result_string(msg, "userWorkstations", NULL);
/* Quit if the account was disabled. */
if (acct_flags & ACB_DISABLED) {
@@ -412,17 +412,17 @@ static NTSTATUS authsam_authenticate(struct auth_context *auth_context,
nt_status = authsam_account_ok(mem_ctx, sam_ctx,
user_info->logon_parameters,
- msgs,
- msgs_domain_ref,
+ msgs[0],
+ msgs_domain_ref[0],
user_info->workstation_name,
user_info->mapped.account_name);
return nt_status;
}
-static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx,
- struct ldb_message **msgs,
- struct ldb_message **msgs_domain,
+NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx,
+ struct ldb_message *msg,
+ struct ldb_message *msg_domain_ref,
DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
struct auth_serversupplied_info **_server_info)
{
@@ -443,7 +443,7 @@ static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context
group_ret = gendb_search(sam_ctx,
tmp_ctx, NULL, &group_msgs, group_attrs,
"(&(member=%s)(sAMAccountType=*))",
- ldb_dn_linearize(tmp_ctx, msgs[0]->dn));
+ ldb_dn_linearize(tmp_ctx, msg->dn));
if (group_ret == -1) {
talloc_free(tmp_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
@@ -466,13 +466,13 @@ static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context
talloc_free(tmp_ctx);
- account_sid = samdb_result_dom_sid(server_info, msgs[0], "objectSid");
+ account_sid = samdb_result_dom_sid(server_info, msg, "objectSid");
NT_STATUS_HAVE_NO_MEMORY(account_sid);
primary_group_sid = dom_sid_dup(server_info, account_sid);
NT_STATUS_HAVE_NO_MEMORY(primary_group_sid);
- rid = samdb_result_uint(msgs[0], "primaryGroupID", ~0);
+ rid = samdb_result_uint(msg, "primaryGroupID", ~0);
if (rid == ~0) {
if (group_ret > 0) {
primary_group_sid = groupSIDs[0];
@@ -489,49 +489,49 @@ static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context
server_info->n_domain_groups = group_ret;
server_info->domain_groups = groupSIDs;
- server_info->account_name = talloc_steal(server_info, samdb_result_string(msgs[0], "sAMAccountName", NULL));
+ server_info->account_name = talloc_steal(server_info, samdb_result_string(msg, "sAMAccountName", NULL));
- server_info->domain_name = talloc_steal(server_info, samdb_result_string(msgs_domain[0], "nETBIOSName", NULL));
+ server_info->domain_name = talloc_steal(server_info, samdb_result_string(msg_domain_ref, "nETBIOSName", NULL));
- str = samdb_result_string(msgs[0], "displayName", "");
+ str = samdb_result_string(msg, "displayName", "");
server_info->full_name = talloc_strdup(server_info, str);
NT_STATUS_HAVE_NO_MEMORY(server_info->full_name);
- str = samdb_result_string(msgs[0], "scriptPath", "");
+ str = samdb_result_string(msg, "scriptPath", "");
server_info->logon_script = talloc_strdup(server_info, str);
NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script);
- str = samdb_result_string(msgs[0], "profilePath", "");
+ str = samdb_result_string(msg, "profilePath", "");
server_info->profile_path = talloc_strdup(server_info, str);
NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path);
- str = samdb_result_string(msgs[0], "homeDirectory", "");
+ str = samdb_result_string(msg, "homeDirectory", "");
server_info->home_directory = talloc_strdup(server_info, str);
NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory);
- str = samdb_result_string(msgs[0], "homeDrive", "");
+ str = samdb_result_string(msg, "homeDrive", "");
server_info->home_drive = talloc_strdup(server_info, str);
NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive);
server_info->logon_server = talloc_strdup(server_info, lp_netbios_name());
NT_STATUS_HAVE_NO_MEMORY(server_info->logon_server);
- server_info->last_logon = samdb_result_nttime(msgs[0], "lastLogon", 0);
- server_info->last_logoff = samdb_result_nttime(msgs[0], "lastLogoff", 0);
- server_info->acct_expiry = samdb_result_nttime(msgs[0], "accountExpires", 0);
- server_info->last_password_change = samdb_result_nttime(msgs[0], "pwdLastSet", 0);
+ server_info->last_logon = samdb_result_nttime(msg, "lastLogon", 0);
+ server_info->last_logoff = samdb_result_nttime(msg, "lastLogoff", 0);
+ server_info->acct_expiry = samdb_result_nttime(msg, "accountExpires", 0);
+ server_info->last_password_change = samdb_result_nttime(msg, "pwdLastSet", 0);
- ncname = samdb_result_dn(mem_ctx, msgs_domain[0], "nCName", ldb_dn_new(mem_ctx));
+ ncname = samdb_result_dn(mem_ctx, msg_domain_ref, "nCName", ldb_dn_new(mem_ctx));
server_info->allow_password_change = samdb_result_allow_password_change(sam_ctx, mem_ctx,
- ncname, msgs[0], "pwdLastSet");
+ ncname, msg, "pwdLastSet");
server_info->force_password_change = samdb_result_force_password_change(sam_ctx, mem_ctx,
- ncname, msgs[0], "pwdLastSet");
+ ncname, msg, "pwdLastSet");
- server_info->logon_count = samdb_result_uint(msgs[0], "logonCount", 0);
- server_info->bad_password_count = samdb_result_uint(msgs[0], "badPwdCount", 0);
+ server_info->logon_count = samdb_result_uint(msg, "logonCount", 0);
+ server_info->bad_password_count = samdb_result_uint(msg, "badPwdCount", 0);
- server_info->acct_flags = samdb_result_acct_flags(msgs[0], "userAccountControl");
+ server_info->acct_flags = samdb_result_acct_flags(msg, "userAccountControl");
server_info->user_session_key = user_sess_key;
server_info->lm_session_key = lm_sess_key;
@@ -614,7 +614,7 @@ NTSTATUS sam_get_server_info_principal(TALLOC_CTX *mem_ctx, const char *principa
return nt_status;
}
- nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, msgs_domain_ref,
+ nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs[0], msgs_domain_ref[0],
user_sess_key, lm_sess_key,
server_info);
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -654,7 +654,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx
&user_sess_key, &lm_sess_key);
NT_STATUS_NOT_OK_RETURN(nt_status);
- nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_ref_msgs,
+ nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs[0], domain_ref_msgs[0],
user_sess_key, lm_sess_key,
server_info);
NT_STATUS_NOT_OK_RETURN(nt_status);
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 08e2298c1a..c8a57234e3 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -891,7 +891,7 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
/* decode and verify the pac */
nt_status = kerberos_pac_logon_info(mem_ctx, &logon_info, pac_blob,
gensec_gssapi_state->smb_krb5_context->krb5_context,
- NULL, keyblock, principal, authtime);
+ NULL, keyblock, principal, authtime, NULL);
krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal);
if (NT_STATUS_IS_OK(nt_status)) {
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index d5a2fd9a8f..c8640dde8c 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -521,7 +521,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
gensec_krb5_state->smb_krb5_context->krb5_context,
NULL, gensec_krb5_state->keyblock,
client_principal,
- gensec_krb5_state->ticket->ticket.authtime);
+ gensec_krb5_state->ticket->ticket.authtime, NULL);
krb5_free_principal(context, client_principal);
if (NT_STATUS_IS_OK(nt_status)) {
diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h
index 9813290650..46bf300229 100644
--- a/source4/auth/kerberos/kerberos.h
+++ b/source4/auth/kerberos/kerberos.h
@@ -137,7 +137,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *service_keyblock,
krb5_const_principal client_principal,
- time_t tgs_authtime);
+ time_t tgs_authtime,
+ krb5_error_code *k5ret);
NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx,
struct PAC_LOGON_INFO **logon_info,
DATA_BLOB blob,
@@ -145,7 +146,8 @@ NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *service_keyblock,
krb5_const_principal client_principal,
- time_t tgs_authtime);
+ time_t tgs_authtime,
+ krb5_error_code *k5ret);
krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
struct PAC_DATA *pac_data,
krb5_context context,
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
index 9be9df133a..55805f0c4a 100644
--- a/source4/auth/kerberos/kerberos_pac.c
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -74,7 +74,8 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *service_keyblock,
krb5_const_principal client_principal,
- time_t tgs_authtime)
+ time_t tgs_authtime,
+ krb5_error_code *k5ret)
{
krb5_error_code ret;
NTSTATUS status;
@@ -87,19 +88,28 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
struct PAC_DATA *pac_data;
struct PAC_DATA_RAW *pac_data_raw;
- DATA_BLOB *srv_sig_blob;
- DATA_BLOB *kdc_sig_blob;
+ DATA_BLOB *srv_sig_blob = NULL;
+ DATA_BLOB *kdc_sig_blob = NULL;
DATA_BLOB modified_pac_blob;
NTTIME tgs_authtime_nttime;
krb5_principal client_principal_pac;
int i;
+ krb5_clear_error_string(context);
+
+ if (k5ret) {
+ *k5ret = KRB5_PARSE_MALFORMED;
+ }
+
pac_data = talloc(mem_ctx, struct PAC_DATA);
pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
+ if (k5ret) {
+ *k5ret = ENOMEM;
+ }
return NT_STATUS_NO_MEMORY;
}
@@ -242,6 +252,9 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
if (ret) {
DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
+ if (k5ret) {
+ *k5ret = ret;
+ }
return NT_STATUS_ACCESS_DENIED;
}
@@ -252,6 +265,9 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
if (ret) {
DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
+ if (k5ret) {
+ *k5ret = ret;
+ }
return NT_STATUS_ACCESS_DENIED;
}
}
@@ -271,6 +287,9 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
logon_name->account_name,
smb_get_krb5_error_message(context, ret, mem_ctx)));
+ if (k5ret) {
+ *k5ret = ret;
+ }
return NT_STATUS_INVALID_PARAMETER;
}
@@ -302,19 +321,20 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
krb5_keyblock *krbtgt_keyblock,
krb5_keyblock *service_keyblock,
krb5_const_principal client_principal,
- time_t tgs_authtime)
+ time_t tgs_authtime,
+ krb5_error_code *k5ret)
{
NTSTATUS nt_status;
struct PAC_DATA *pac_data;
int i;
-
nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
blob,
context,
krbtgt_keyblock,
service_keyblock,
client_principal,
- tgs_authtime);
+ tgs_authtime,
+ k5ret);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c
index 0df090eef3..a1a607329a 100644
--- a/source4/heimdal/kdc/kerberos5.c
+++ b/source4/heimdal/kdc/kerberos5.c
@@ -32,9 +32,6 @@
*/
#include "kdc_locl.h"
-#ifdef _SAMBA_BUILD_
-#include "kdc/pac-glue.h"
-#endif
RCSID("$Id: kerberos5.c,v 1.177 2005/06/15 11:34:53 lha Exp $");
@@ -1355,6 +1352,18 @@ _kdc_as_rep(krb5_context context,
rep.padata = NULL;
}
+ /* Add the PAC, via a HDB abstraction */
+ if (client->authz_data_as_req) {
+ ret = client->authz_data_as_req(context, client,
+ req->padata,
+ et.authtime,
+ &skey->key,
+ &et.key,
+ &et.authorization_data);
+ if (ret)
+ goto out;
+ }
+
log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
et.endtime, et.renew_till);
@@ -1640,7 +1649,7 @@ tgs_make_reply(krb5_context context,
EncTicketPart *adtkt,
AuthorizationData *auth_data,
krb5_ticket *tgs_ticket,
- hdb_entry *server,
+ hdb_entry_ex *server,
hdb_entry *client,
krb5_principal client_principal,
hdb_entry *krbtgt,
@@ -1657,6 +1666,7 @@ tgs_make_reply(krb5_context context,
krb5_enctype etype;
Key *skey;
EncryptionKey *ekey;
+ AuthorizationData *new_auth_data = NULL;
if(adtkt) {
int i;
@@ -1674,7 +1684,7 @@ tgs_make_reply(krb5_context context,
etype = b->etype.val[i];
}else{
ret = find_keys(context, config,
- NULL, server, NULL, NULL, &skey, &etype,
+ NULL, &server->entry, NULL, NULL, &skey, &etype,
b->etype.val, b->etype.len);
if(ret) {
kdc_log(context, config, 0, "Server has no support for etypes");
@@ -1728,14 +1738,14 @@ tgs_make_reply(krb5_context context,
GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
&tgt->transited, &et,
*krb5_princ_realm(context, client_principal),
- *krb5_princ_realm(context, server->principal),
+ *krb5_princ_realm(context, server->entry.principal),
*krb5_princ_realm(context, krbtgt->principal));
if(ret)
goto out;
- copy_Realm(krb5_princ_realm(context, server->principal),
+ copy_Realm(krb5_princ_realm(context, server->entry.principal),
&rep.ticket.realm);
- _krb5_principal2principalname(&rep.ticket.sname, server->principal);
+ _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);
copy_Realm(&tgt->crealm, &rep.crealm);
if (f.request_anonymous)
make_anonymous_principalname (&tgt->cname);
@@ -1752,8 +1762,8 @@ tgs_make_reply(krb5_context context,
life = et.endtime - *et.starttime;
if(client && client->max_life)
life = min(life, *client->max_life);
- if(server->max_life)
- life = min(life, *server->max_life);
+ if(server->entry.max_life)
+ life = min(life, *server->entry.max_life);
et.endtime = *et.starttime + life;
}
if(f.renewable_ok && tgt->flags.renewable &&
@@ -1767,8 +1777,8 @@ tgs_make_reply(krb5_context context,
renew = *et.renew_till - et.authtime;
if(client && client->max_renew)
renew = min(renew, *client->max_renew);
- if(server->max_renew)
- renew = min(renew, *server->max_renew);
+ if(server->entry.max_renew)
+ renew = min(renew, *server->entry.max_renew);
*et.renew_till = et.authtime + renew;
}
@@ -1793,61 +1803,28 @@ tgs_make_reply(krb5_context context,
et.flags.pre_authent = tgt->flags.pre_authent;
et.flags.hw_authent = tgt->flags.hw_authent;
et.flags.anonymous = tgt->flags.anonymous;
- et.flags.ok_as_delegate = server->flags.ok_as_delegate;
+ et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
-#ifdef _SAMBA_BUILD_
-
- {
-
- unsigned char *buf;
- size_t buf_size;
- size_t len;
-
- krb5_data pac;
- AD_IF_RELEVANT *if_relevant;
- ALLOC(if_relevant);
- if_relevant->len = 1;
- if_relevant->val = malloc(sizeof(*if_relevant->val));
- 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;
-
- /* Get PAC from Samba */
- ret = samba_get_pac(context, config,
- client->principal,
- tgtkey,
- ekey,
- tgs_ticket->ticket.authtime,
- &pac);
- if (ret) {
- free_AuthorizationData(if_relevant);
- goto out;
- }
-
- /* 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;
+
+ krb5_generate_random_keyblock(context, etype, &et.key);
- ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, if_relevant, &len, ret);
- free_AuthorizationData(if_relevant);
-
- auth_data = NULL;
- ALLOC(auth_data);
- auth_data->len = 1;
- auth_data->val = malloc(sizeof(*auth_data->val));
- 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;
+ if (server->authz_data_tgs_req) {
+ ret = server->authz_data_tgs_req(context, server,
+ client_principal,
+ tgs_ticket->ticket.authorization_data,
+ tgs_ticket->ticket.authtime,
+ tgtkey,
+ ekey,
+ &et.key,
+ &new_auth_data);
if (ret) {
- goto out;
+ new_auth_data = NULL;
}
}
-#endif
/* XXX Check enc-authorization-data */
- et.authorization_data = auth_data;
+ et.authorization_data = new_auth_data;
- krb5_generate_random_keyblock(context, etype, &et.key);
et.crealm = tgt->crealm;
et.cname = tgt->cname;
@@ -1878,7 +1855,7 @@ tgs_make_reply(krb5_context context,
etype list, even if we don't want a session key with
DES3? */
ret = encode_reply(context, config,
- &rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
+ &rep, &et, &ek, etype, adtkt ? 0 : server->entry.kvno, ekey,
0, &tgt->key, e_text, reply);
out:
free_TGS_REP(&rep);
@@ -2228,7 +2205,8 @@ tgs_rep2(krb5_context context,
PrincipalName *s;
Realm r;
char *spn = NULL, *cpn = NULL;
- hdb_entry *server = NULL, *client = NULL;
+ hdb_entry_ex *server = NULL;
+ hdb_entry *client = NULL;
int nloop = 0;
EncTicketPart adtkt;
char opt_str[128];
@@ -2295,7 +2273,7 @@ tgs_rep2(krb5_context context,
kdc_log(context, config, 0,
"TGS-REQ %s from %s for %s", cpn, from, spn);
server_lookup:
- ret = _kdc_db_fetch(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
+ ret = _kdc_db_fetch_ex(context, config, sp, HDB_ENT_TYPE_SERVER, &server);
if(ret){
const char *new_rlm;
@@ -2376,7 +2354,7 @@ tgs_rep2(krb5_context context,
ret = _kdc_check_flags(context, config,
client, cpn,
- server, spn,
+ &server->entry, spn,
FALSE);
if(ret)
goto out;
@@ -2384,7 +2362,7 @@ tgs_rep2(krb5_context context,
if((b->kdc_options.validate || b->kdc_options.renew) &&
!krb5_principal_compare(context,
krbtgt->principal,
- server->principal)){
+ server->entry.principal)){
kdc_log(context, config, 0, "Inconsistent request.");
ret = KRB5KDC_ERR_SERVER_NOMATCH;
goto out;
@@ -2417,7 +2395,7 @@ tgs_rep2(krb5_context context,
free(cpn);
if(server)
- _kdc_free_ent(context, server);
+ _kdc_free_ent_ex(context, server);
if(client)
_kdc_free_ent(context, client);
}
diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h
index 41cc03cf36..45ea5a9f30 100644
--- a/source4/heimdal/lib/hdb/hdb.h
+++ b/source4/heimdal/lib/hdb/hdb.h
@@ -61,14 +61,19 @@ typedef struct hdb_entry_ex {
krb5_error_code (*free_private)(krb5_context, struct hdb_entry_ex *);
krb5_error_code (*check_client_access)(krb5_context, struct hdb_entry_ex *, HostAddresses *);
krb5_error_code (*authz_data_as_req)(krb5_context, struct hdb_entry_ex *,
- AuthorizationData *in,
+ METHOD_DATA* pa_data_seq,
+ time_t authtime,
EncryptionKey *tgtkey,
- AuthorizationData *out);
+ EncryptionKey *sessionkey,
+ AuthorizationData **out);
krb5_error_code (*authz_data_tgs_req)(krb5_context, struct hdb_entry_ex *,
+ krb5_principal client,
AuthorizationData *in,
+ time_t authtime,
EncryptionKey *tgtkey,
EncryptionKey *servicekey,
- AuthorizationData *out);
+ EncryptionKey *sessionkey,
+ AuthorizationData **out);
} hdb_entry_ex;
typedef struct HDB{
diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h
index 07d9329337..2645c29fe7 100644
--- a/source4/heimdal/lib/krb5/krb5-private.h
+++ b/source4/heimdal/lib/krb5/krb5-private.h
@@ -399,4 +399,12 @@ _krb5_xunlock (
krb5_context /*context*/,
int /*fd*/);
+int
+_krb5_find_type_in_ad(krb5_context context,
+ int type,
+ krb5_data *data,
+ int *found,
+ krb5_keyblock *sessionkey,
+ const AuthorizationData *ad);
+
#endif /* __krb5_private_h__ */
diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c
index adc077e13f..44e5d9c222 100644
--- a/source4/heimdal/lib/krb5/mk_req.c
+++ b/source4/heimdal/lib/krb5/mk_req.c
@@ -64,7 +64,9 @@ krb5_mk_req_exact(krb5_context context,
if (auth_context && *auth_context && (*auth_context)->keytype)
this_cred.session.keytype = (*auth_context)->keytype;
+ /* This is the network contact with the KDC */
ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred);
+
krb5_free_cred_contents(context, &this_cred);
if (ret)
return ret;
diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c
index 7dae26acf2..b3efeb39d3 100644
--- a/source4/heimdal/lib/krb5/ticket.c
+++ b/source4/heimdal/lib/krb5/ticket.c
@@ -101,8 +101,8 @@ static int
find_type_in_ad(krb5_context context,
int type,
krb5_data *data,
- int *found,
- int failp,
+ krb5_boolean *found,
+ krb5_boolean failp,
krb5_keyblock *sessionkey,
const AuthorizationData *ad,
int level)
@@ -129,7 +129,7 @@ find_type_in_ad(krb5_context context,
krb5_set_error_string(context, "malloc - out of memory");
goto out;
}
- *found = 1;
+ *found = TRUE;
continue;
}
switch (ad->val[i].ad_type) {
@@ -228,6 +228,19 @@ out:
return ret;
}
+int
+_krb5_find_type_in_ad(krb5_context context,
+ int type,
+ krb5_data *data,
+ krb5_boolean *found,
+ krb5_keyblock *sessionkey,
+ const AuthorizationData *ad)
+{
+ krb5_data_zero(data);
+ return find_type_in_ad(context, type, data, found, TRUE, sessionkey, ad, 0);
+}
+
+
/*
* Extract the authorization data type of `type' from the
* 'ticket'. Store the field in `data'. This function is to use for
@@ -242,9 +255,7 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
{
AuthorizationData *ad;
krb5_error_code ret;
- int found = 0;
-
- krb5_data_zero(data);
+ krb5_boolean found = 0;
ad = ticket->ticket.authorization_data;
if (ticket->ticket.authorization_data == NULL) {
@@ -252,8 +263,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
return ENOENT; /* XXX */
}
- ret = find_type_in_ad(context, type, data, &found, 1, &ticket->ticket.key,
- ticket->ticket.authorization_data, 0);
+ ret = _krb5_find_type_in_ad(context, type, data, &found, &ticket->ticket.key,
+ ticket->ticket.authorization_data);
if (ret)
return ret;
if (!found) {
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);
diff --git a/source4/torture/auth/pac.c b/source4/torture/auth/pac.c
index 221454280e..0674d55574 100644
--- a/source4/torture/auth/pac.c
+++ b/source4/torture/auth/pac.c
@@ -147,7 +147,7 @@ static BOOL torture_pac_self_check(void)
&krbtgt_keyblock,
&server_keyblock,
client_principal,
- logon_time);
+ logon_time, NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -170,7 +170,8 @@ static BOOL torture_pac_self_check(void)
&krbtgt_keyblock,
&server_keyblock,
client_principal,
- logon_time);
+ logon_time,
+ NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -398,7 +399,7 @@ static BOOL torture_pac_saved_check(void)
smb_krb5_context->krb5_context,
&krbtgt_keyblock,
&server_keyblock,
- client_principal, authtime);
+ client_principal, authtime, NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("(saved test) PAC decoding failed: %s\n",
nt_errstr(nt_status)));
@@ -419,7 +420,7 @@ static BOOL torture_pac_saved_check(void)
smb_krb5_context->krb5_context,
&krbtgt_keyblock,
&server_keyblock,
- client_principal, authtime);
+ client_principal, authtime, NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
@@ -612,7 +613,7 @@ static BOOL torture_pac_saved_check(void)
&krbtgt_keyblock,
&server_keyblock,
client_principal,
- authtime + 1);
+ authtime + 1, NULL);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("(saved test) PAC decoding DID NOT fail on broken auth time (time + 1)\n"));
@@ -648,7 +649,7 @@ static BOOL torture_pac_saved_check(void)
&krbtgt_keyblock,
&server_keyblock,
client_principal,
- authtime);
+ authtime, NULL);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("(saved test) PAC decoding DID NOT fail on modified principal\n"));
@@ -669,7 +670,7 @@ static BOOL torture_pac_saved_check(void)
&krbtgt_keyblock,
&server_keyblock,
client_principal,
- authtime);
+ authtime, NULL);
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("(saved test) PAC decoding DID NOT fail on broken checksum\n"));