summaryrefslogtreecommitdiff
path: root/source4/kdc
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2016-05-13 00:13:33 +0200
committerAndrew Bartlett <abartlet@samba.org>2016-07-22 23:34:22 +0200
commit54d32c262bcab2bbe82a30909c5820fbcfa7a444 (patch)
tree02f494c2f4e3424139739a1bf560b9929e146be3 /source4/kdc
parent8b1f5cad958a4022edc947b6abdb198ffad1a525 (diff)
downloadsamba-54d32c262bcab2bbe82a30909c5820fbcfa7a444.tar.gz
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>
Diffstat (limited to 'source4/kdc')
-rw-r--r--source4/kdc/pac-glue.c104
-rw-r--r--source4/kdc/pac-glue.h4
-rw-r--r--source4/kdc/wdc-samba4.c37
3 files changed, 139 insertions, 6 deletions
diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
index 0b9fd12b764..ff3f62a11c4 100644
--- a/source4/kdc/pac-glue.c
+++ b/source4/kdc/pac-glue.c
@@ -78,6 +78,42 @@ NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx,
}
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,
DATA_BLOB *cred_blob)
@@ -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;
@@ -345,6 +398,32 @@ krb5_error_code samba_make_krb5_pac(krb5_context context,
&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;
}
diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h
index 22f96c8d425..92a6bc78023 100644
--- a/source4/kdc/pac-glue.h
+++ b/source4/kdc/pac-glue.h
@@ -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);
diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c
index 3c0a012fb80..fddf342787f 100644
--- a/source4/kdc/wdc-samba4.c
+++ b/source4/kdc/wdc-samba4.c
@@ -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:
/*