diff options
-rw-r--r-- | source4/auth/auth_sam.c | 70 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 2 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 2 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos.h | 6 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_pac.c | 32 | ||||
-rw-r--r-- | source4/heimdal/kdc/kerberos5.c | 108 | ||||
-rw-r--r-- | source4/heimdal/lib/hdb/hdb.h | 11 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/krb5-private.h | 8 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/mk_req.c | 2 | ||||
-rw-r--r-- | source4/heimdal/lib/krb5/ticket.c | 27 | ||||
-rw-r--r-- | source4/kdc/hdb-ldb.c | 131 | ||||
-rw-r--r-- | source4/kdc/pac-glue.c | 317 | ||||
-rw-r--r-- | source4/kdc/pac-glue.h | 52 | ||||
-rw-r--r-- | source4/torture/auth/pac.c | 15 |
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")); |