1
0
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:
Stefan Metzmacher 2016-05-13 00:13:33 +02:00 committed by Andrew Bartlett
parent 8b1f5cad95
commit 54d32c262b
4 changed files with 140 additions and 7 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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:
/*

View File

@ -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;