mirror of
https://github.com/samba-team/samba.git
synced 2025-03-26 18:50:30 +03:00
s4:kdc: provide a PAC_UPN_DNS_INFO element for logons
Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
8b1f5cad95
commit
54d32c262b
@ -77,6 +77,42 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx,
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS samba_get_upn_info_pac_blob(TALLOC_CTX *mem_ctx,
|
||||
const struct auth_user_info_dc *info,
|
||||
DATA_BLOB *upn_data)
|
||||
{
|
||||
union PAC_INFO pac_upn;
|
||||
enum ndr_err_code ndr_err;
|
||||
NTSTATUS nt_status;
|
||||
|
||||
ZERO_STRUCT(pac_upn);
|
||||
|
||||
*upn_data = data_blob_null;
|
||||
|
||||
pac_upn.upn_dns_info.upn_name = info->info->user_principal_name;
|
||||
pac_upn.upn_dns_info.dns_domain_name = strupper_talloc(mem_ctx,
|
||||
info->info->dns_domain_name);
|
||||
if (pac_upn.upn_dns_info.dns_domain_name == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
if (info->info->user_principal_constructed) {
|
||||
pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_CONSTRUCTED;
|
||||
}
|
||||
|
||||
ndr_err = ndr_push_union_blob(upn_data, mem_ctx, &pac_upn,
|
||||
PAC_TYPE_UPN_DNS_INFO,
|
||||
(ndr_push_flags_fn_t)ndr_push_PAC_INFO);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
nt_status = ndr_map_error2ntstatus(ndr_err);
|
||||
DEBUG(1, ("PAC UPN_DNS_INFO (presig) push failed: %s\n",
|
||||
nt_errstr(nt_status)));
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS samba_get_cred_info_ndr_blob(TALLOC_CTX *mem_ctx,
|
||||
const struct ldb_message *msg,
|
||||
@ -277,11 +313,13 @@ krb5_error_code samba_kdc_encrypt_pac_credentials(krb5_context context,
|
||||
krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
const DATA_BLOB *logon_blob,
|
||||
const DATA_BLOB *cred_blob,
|
||||
const DATA_BLOB *upn_blob,
|
||||
const DATA_BLOB *deleg_blob,
|
||||
krb5_pac *pac)
|
||||
{
|
||||
krb5_data logon_data;
|
||||
krb5_data cred_data;
|
||||
krb5_data upn_data;
|
||||
krb5_data deleg_data;
|
||||
krb5_data null_data;
|
||||
krb5_error_code ret;
|
||||
@ -311,6 +349,18 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
}
|
||||
}
|
||||
|
||||
ZERO_STRUCT(upn_data);
|
||||
if (upn_blob != NULL) {
|
||||
ret = krb5_copy_data_contents(&upn_data,
|
||||
upn_blob->data,
|
||||
upn_blob->length);
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &logon_data);
|
||||
kerberos_free_data_contents(context, &cred_data);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ZERO_STRUCT(deleg_data);
|
||||
if (deleg_blob != NULL) {
|
||||
ret = krb5_copy_data_contents(&deleg_data,
|
||||
@ -319,6 +369,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &logon_data);
|
||||
kerberos_free_data_contents(context, &cred_data);
|
||||
kerberos_free_data_contents(context, &upn_data);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -327,6 +378,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &logon_data);
|
||||
kerberos_free_data_contents(context, &cred_data);
|
||||
kerberos_free_data_contents(context, &upn_data);
|
||||
kerberos_free_data_contents(context, &deleg_data);
|
||||
return ret;
|
||||
}
|
||||
@ -334,6 +386,7 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &logon_data);
|
||||
kerberos_free_data_contents(context, &logon_data);
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &upn_data);
|
||||
kerberos_free_data_contents(context, &cred_data);
|
||||
kerberos_free_data_contents(context, &deleg_data);
|
||||
return ret;
|
||||
@ -344,6 +397,32 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
PAC_TYPE_CREDENTIAL_INFO,
|
||||
&cred_data);
|
||||
kerberos_free_data_contents(context, &cred_data);
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &upn_data);
|
||||
kerberos_free_data_contents(context, &deleg_data);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* null_data will be filled by the generic KDC code in the caller
|
||||
* here we just add it in order to have it before
|
||||
* PAC_TYPE_UPN_DNS_INFO
|
||||
*/
|
||||
ret = krb5_pac_add_buffer(context, *pac,
|
||||
PAC_TYPE_LOGON_NAME,
|
||||
&null_data);
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &upn_data);
|
||||
kerberos_free_data_contents(context, &deleg_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (upn_blob != NULL) {
|
||||
ret = krb5_pac_add_buffer(context, *pac,
|
||||
PAC_TYPE_UPN_DNS_INFO,
|
||||
&upn_data);
|
||||
kerberos_free_data_contents(context, &upn_data);
|
||||
if (ret != 0) {
|
||||
kerberos_free_data_contents(context, &deleg_data);
|
||||
return ret;
|
||||
@ -451,17 +530,20 @@ int samba_krbtgt_is_in_db(struct samba_kdc_entry *p,
|
||||
NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx,
|
||||
struct samba_kdc_entry *p,
|
||||
DATA_BLOB **_logon_info_blob,
|
||||
DATA_BLOB **_cred_ndr_blob)
|
||||
DATA_BLOB **_cred_ndr_blob,
|
||||
DATA_BLOB **_upn_info_blob)
|
||||
{
|
||||
struct auth_user_info_dc *user_info_dc;
|
||||
DATA_BLOB *logon_blob = NULL;
|
||||
DATA_BLOB *cred_blob = NULL;
|
||||
DATA_BLOB *upn_blob = NULL;
|
||||
NTSTATUS nt_status;
|
||||
|
||||
*_logon_info_blob = NULL;
|
||||
if (_cred_ndr_blob != NULL) {
|
||||
*_cred_ndr_blob = NULL;
|
||||
}
|
||||
*_upn_info_blob = NULL;
|
||||
|
||||
/* The user account may be set not to want the PAC */
|
||||
if ( ! samba_princ_needs_pac(p)) {
|
||||
@ -480,6 +562,11 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
upn_blob = talloc_zero(mem_ctx, DATA_BLOB);
|
||||
if (upn_blob == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
nt_status = authsam_make_user_info_dc(mem_ctx, p->kdc_db_ctx->samdb,
|
||||
lpcfg_netbios_name(p->kdc_db_ctx->lp_ctx),
|
||||
lpcfg_sam_name(p->kdc_db_ctx->lp_ctx),
|
||||
@ -515,11 +602,21 @@ NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
nt_status = samba_get_upn_info_pac_blob(upn_blob,
|
||||
user_info_dc,
|
||||
upn_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(0, ("Building PAC UPN INFO failed: %s\n",
|
||||
nt_errstr(nt_status)));
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
TALLOC_FREE(user_info_dc);
|
||||
*_logon_info_blob = logon_blob;
|
||||
if (_cred_ndr_blob != NULL) {
|
||||
*_cred_ndr_blob = cred_blob;
|
||||
}
|
||||
*_upn_info_blob = upn_blob;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -528,14 +625,17 @@ NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx,
|
||||
DATA_BLOB **_logon_info_blob)
|
||||
{
|
||||
NTSTATUS nt_status;
|
||||
DATA_BLOB *upn_blob = NULL;
|
||||
|
||||
nt_status = samba_kdc_get_pac_blobs(mem_ctx, p,
|
||||
_logon_info_blob,
|
||||
NULL);
|
||||
NULL, /* cred_blob */
|
||||
&upn_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
TALLOC_FREE(upn_blob);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ krb5_error_code samba_kdc_encrypt_pac_credentials(krb5_context context,
|
||||
krb5_error_code samba_make_krb5_pac(krb5_context context,
|
||||
const DATA_BLOB *logon_blob,
|
||||
const DATA_BLOB *cred_blob,
|
||||
const DATA_BLOB *upn_blob,
|
||||
const DATA_BLOB *deleg_blob,
|
||||
krb5_pac *pac);
|
||||
|
||||
@ -42,7 +43,8 @@ int samba_krbtgt_is_in_db(struct samba_kdc_entry *skdc_entry,
|
||||
NTSTATUS samba_kdc_get_pac_blobs(TALLOC_CTX *mem_ctx,
|
||||
struct samba_kdc_entry *skdc_entry,
|
||||
DATA_BLOB **_logon_info_blob,
|
||||
DATA_BLOB **_cred_ndr_blob);
|
||||
DATA_BLOB **_cred_ndr_blob,
|
||||
DATA_BLOB **_upn_info_blob);
|
||||
NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx,
|
||||
struct samba_kdc_entry *skdc_entry,
|
||||
DATA_BLOB **_logon_info_blob);
|
||||
|
@ -42,6 +42,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
|
||||
DATA_BLOB **cred_ndr_ptr = NULL;
|
||||
DATA_BLOB _cred_blob = data_blob_null;
|
||||
DATA_BLOB *cred_blob = NULL;
|
||||
DATA_BLOB *upn_blob = NULL;
|
||||
krb5_error_code ret;
|
||||
NTSTATUS nt_status;
|
||||
struct samba_kdc_entry *skdc_entry =
|
||||
@ -59,7 +60,8 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
|
||||
|
||||
nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry,
|
||||
&logon_blob,
|
||||
cred_ndr_ptr);
|
||||
cred_ndr_ptr,
|
||||
&upn_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
@ -79,7 +81,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
|
||||
}
|
||||
|
||||
ret = samba_make_krb5_pac(context, logon_blob, cred_blob,
|
||||
NULL, pac);
|
||||
upn_blob, NULL, pac);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return ret;
|
||||
@ -111,6 +113,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context");
|
||||
krb5_pac new_pac = NULL;
|
||||
DATA_BLOB *pac_blob = NULL;
|
||||
DATA_BLOB *upn_blob = NULL;
|
||||
DATA_BLOB *deleg_blob = NULL;
|
||||
krb5_error_code ret;
|
||||
NTSTATUS nt_status;
|
||||
@ -124,6 +127,7 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
ssize_t logon_info_idx = -1;
|
||||
ssize_t delegation_idx = -1;
|
||||
ssize_t logon_name_idx = -1;
|
||||
ssize_t upn_dns_info_idx = -1;
|
||||
ssize_t srv_checksum_idx = -1;
|
||||
ssize_t kdc_checksum_idx = -1;
|
||||
|
||||
@ -156,7 +160,8 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
client_skdc_entry = talloc_get_type_abort(client->ctx,
|
||||
struct samba_kdc_entry);
|
||||
|
||||
nt_status = samba_kdc_get_pac_blob(mem_ctx, client_skdc_entry, &pac_blob);
|
||||
nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry,
|
||||
&pac_blob, NULL, &upn_blob);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
@ -266,6 +271,18 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
}
|
||||
logon_name_idx = i;
|
||||
break;
|
||||
case PAC_TYPE_UPN_DNS_INFO:
|
||||
if (upn_dns_info_idx != -1) {
|
||||
DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n",
|
||||
(int)types[i],
|
||||
(int)logon_info_idx,
|
||||
(int)i));
|
||||
SAFE_FREE(types);
|
||||
talloc_free(mem_ctx);
|
||||
return EINVAL;
|
||||
}
|
||||
upn_dns_info_idx = i;
|
||||
break;
|
||||
case PAC_TYPE_SRV_CHECKSUM:
|
||||
if (srv_checksum_idx != -1) {
|
||||
DEBUG(1, ("logon type[%d] twice [%d] and [%d]: \n",
|
||||
@ -377,6 +394,20 @@ static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
|
||||
* we just add a place holder here.
|
||||
*/
|
||||
type_blob = data_blob_const(&zero_byte, 1);
|
||||
|
||||
if (upn_dns_info_idx == -1 && upn_blob != NULL) {
|
||||
/* inject UPN_DNS_INFO behind */
|
||||
forced_next_type = PAC_TYPE_UPN_DNS_INFO;
|
||||
}
|
||||
break;
|
||||
case PAC_TYPE_UPN_DNS_INFO:
|
||||
/*
|
||||
* Replace in the RODC case, otherwise
|
||||
* upn_blob is NULL and we just copy.
|
||||
*/
|
||||
if (upn_blob != NULL) {
|
||||
type_blob = *upn_blob;
|
||||
}
|
||||
break;
|
||||
case PAC_TYPE_SRV_CHECKSUM:
|
||||
/*
|
||||
|
@ -133,7 +133,7 @@ static bool test_PACVerify(struct torture_context *tctx,
|
||||
{
|
||||
NTSTATUS status;
|
||||
bool pkinit_in_use = torture_setting_bool(tctx, "pkinit_in_use", false);
|
||||
bool expect_pac_upn_dns_info = torture_setting_bool(tctx, "expect_pac_upn_dns_info", false);
|
||||
bool expect_pac_upn_dns_info = torture_setting_bool(tctx, "expect_pac_upn_dns_info", true);
|
||||
size_t num_pac_buffers;
|
||||
|
||||
struct netr_LogonSamLogon r;
|
||||
|
Loading…
x
Reference in New Issue
Block a user