#
# KDC TGS PAC tests
#
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_no_pac_service_no_auth_data_required
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_request_no_pac
#
# KDC TGT tests
#
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_allowed
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed
#
-# PAC attributes tests
-#
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_none
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_true
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_none
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_true
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_none
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_none
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_true
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_true
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_false
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
-#
# PAC request tests
#
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_false
return NT_STATUS_OK;
}
+static
+NTSTATUS samba_get_pac_attrs_blob(TALLOC_CTX *mem_ctx,
+ const krb5_boolean *pac_request,
+ DATA_BLOB *pac_attrs_data)
+{
+ union PAC_INFO pac_attrs;
+ enum ndr_err_code ndr_err;
+ NTSTATUS nt_status;
+
+ ZERO_STRUCT(pac_attrs);
+
+ *pac_attrs_data = data_blob_null;
+
+ /* Set the length of the flags in bits. */
+ pac_attrs.attributes_info.flags_length = 2;
+
+ if (pac_request == NULL) {
+ pac_attrs.attributes_info.flags
+ |= PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY;
+ } else if (*pac_request) {
+ pac_attrs.attributes_info.flags
+ |= PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED;
+ }
+
+ ndr_err = ndr_push_union_blob(pac_attrs_data, mem_ctx, &pac_attrs,
+ PAC_TYPE_ATTRIBUTES_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 ATTRIBUTES_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,
const DATA_BLOB *logon_blob,
const DATA_BLOB *cred_blob,
const DATA_BLOB *upn_blob,
+ const DATA_BLOB *pac_attrs_blob,
const DATA_BLOB *deleg_blob,
krb5_pac *pac)
{
krb5_data logon_data;
krb5_data cred_data;
krb5_data upn_data;
+ krb5_data pac_attrs_data;
krb5_data deleg_data;
krb5_error_code ret;
#ifdef SAMBA4_USES_HEIMDAL
}
}
+ ZERO_STRUCT(pac_attrs_data);
+ if (pac_attrs_blob != NULL) {
+ ret = smb_krb5_copy_data_contents(&pac_attrs_data,
+ pac_attrs_blob->data,
+ pac_attrs_blob->length);
+ if (ret != 0) {
+ smb_krb5_free_data_contents(context, &logon_data);
+ smb_krb5_free_data_contents(context, &cred_data);
+ smb_krb5_free_data_contents(context, &upn_data);
+ return ret;
+ }
+ }
+
ZERO_STRUCT(deleg_data);
if (deleg_blob != NULL) {
ret = smb_krb5_copy_data_contents(&deleg_data,
smb_krb5_free_data_contents(context, &logon_data);
smb_krb5_free_data_contents(context, &cred_data);
smb_krb5_free_data_contents(context, &upn_data);
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
return ret;
}
}
smb_krb5_free_data_contents(context, &logon_data);
smb_krb5_free_data_contents(context, &cred_data);
smb_krb5_free_data_contents(context, &upn_data);
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
smb_krb5_free_data_contents(context, &deleg_data);
return ret;
}
ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &logon_data);
smb_krb5_free_data_contents(context, &logon_data);
if (ret != 0) {
- smb_krb5_free_data_contents(context, &upn_data);
smb_krb5_free_data_contents(context, &cred_data);
+ smb_krb5_free_data_contents(context, &upn_data);
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
smb_krb5_free_data_contents(context, &deleg_data);
return ret;
}
smb_krb5_free_data_contents(context, &cred_data);
if (ret != 0) {
smb_krb5_free_data_contents(context, &upn_data);
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
smb_krb5_free_data_contents(context, &deleg_data);
return ret;
}
&null_data);
if (ret != 0) {
smb_krb5_free_data_contents(context, &upn_data);
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
smb_krb5_free_data_contents(context, &deleg_data);
return ret;
}
PAC_TYPE_UPN_DNS_INFO,
&upn_data);
smb_krb5_free_data_contents(context, &upn_data);
+ if (ret != 0) {
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
+ smb_krb5_free_data_contents(context, &deleg_data);
+ return ret;
+ }
+ }
+
+ if (pac_attrs_blob != NULL) {
+ ret = krb5_pac_add_buffer(context, *pac,
+ PAC_TYPE_ATTRIBUTES_INFO,
+ &pac_attrs_data);
+ smb_krb5_free_data_contents(context, &pac_attrs_data);
if (ret != 0) {
smb_krb5_free_data_contents(context, &deleg_data);
return ret;
return true;
}
+int samba_client_requested_pac(krb5_context context,
+ krb5_pac *pac,
+ TALLOC_CTX *mem_ctx,
+ bool *requested_pac)
+{
+ enum ndr_err_code ndr_err;
+ krb5_data k5pac_attrs_in;
+ DATA_BLOB pac_attrs_in;
+ union PAC_INFO pac_attrs;
+ int ret;
+
+ *requested_pac = true;
+
+ ret = krb5_pac_get_buffer(context, *pac, PAC_TYPE_ATTRIBUTES_INFO,
+ &k5pac_attrs_in);
+ if (ret != 0) {
+ return ret == ENOENT ? 0 : ret;
+ }
+
+ pac_attrs_in = data_blob_const(k5pac_attrs_in.data,
+ k5pac_attrs_in.length);
+
+ ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs,
+ PAC_TYPE_ATTRIBUTES_INFO,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
+ smb_krb5_free_data_contents(context, &k5pac_attrs_in);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
+ DEBUG(0,("can't parse the PAC ATTRIBUTES_INFO: %s\n", nt_errstr(nt_status)));
+ return EINVAL;
+ }
+
+ if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY
+ | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) {
+ *requested_pac = true;
+ } else {
+ *requested_pac = false;
+ }
+
+ return 0;
+}
+
/* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */
int samba_krbtgt_is_in_db(struct samba_kdc_entry *p,
bool *is_in_db,
struct samba_kdc_entry *p,
DATA_BLOB **_logon_info_blob,
DATA_BLOB **_cred_ndr_blob,
- DATA_BLOB **_upn_info_blob)
+ DATA_BLOB **_upn_info_blob,
+ DATA_BLOB **_pac_attrs_blob,
+ const krb5_boolean *pac_request)
{
struct auth_user_info_dc *user_info_dc;
DATA_BLOB *logon_blob = NULL;
DATA_BLOB *cred_blob = NULL;
DATA_BLOB *upn_blob = NULL;
+ DATA_BLOB *pac_attrs_blob = NULL;
NTSTATUS nt_status;
*_logon_info_blob = NULL;
*_cred_ndr_blob = NULL;
}
*_upn_info_blob = NULL;
+ if (_pac_attrs_blob != NULL) {
+ *_pac_attrs_blob = NULL;
+ }
logon_blob = talloc_zero(mem_ctx, DATA_BLOB);
if (logon_blob == NULL) {
return NT_STATUS_NO_MEMORY;
}
+ if (_pac_attrs_blob != NULL) {
+ pac_attrs_blob = talloc_zero(mem_ctx, DATA_BLOB);
+ if (pac_attrs_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),
return nt_status;
}
+ if (pac_attrs_blob != NULL) {
+ nt_status = samba_get_pac_attrs_blob(pac_attrs_blob,
+ pac_request,
+ pac_attrs_blob);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0, ("Building PAC ATTRIBUTES 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;
+ if (_pac_attrs_blob != NULL) {
+ *_pac_attrs_blob = pac_attrs_blob;
+ }
return NT_STATUS_OK;
}
nt_status = samba_kdc_get_pac_blobs(mem_ctx, p,
_logon_info_blob,
NULL, /* cred_blob */
- &upn_blob);
+ &upn_blob,
+ NULL,
+ NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
struct hdb_entry_ex *client,
const krb5_keyblock *pk_reply_key,
+ const krb5_boolean *pac_request,
krb5_pac *pac)
{
TALLOC_CTX *mem_ctx;
DATA_BLOB _cred_blob = data_blob_null;
DATA_BLOB *cred_blob = NULL;
DATA_BLOB *upn_blob = NULL;
+ DATA_BLOB *pac_attrs_blob = NULL;
krb5_error_code ret;
NTSTATUS nt_status;
struct samba_kdc_entry *skdc_entry =
nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry,
&logon_blob,
cred_ndr_ptr,
- &upn_blob);
+ &upn_blob,
+ &pac_attrs_blob,
+ pac_request);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return EINVAL;
}
ret = samba_make_krb5_pac(context, logon_blob, cred_blob,
- upn_blob, NULL, pac);
+ upn_blob, pac_attrs_blob,
+ NULL, pac);
talloc_free(mem_ctx);
return ret;
static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context,
struct hdb_entry_ex *client,
+ const krb5_boolean *pac_request,
krb5_pac *pac)
{
- return samba_wdc_get_pac(priv, context, client, NULL, pac);
+ return samba_wdc_get_pac(priv, context, client, NULL, pac_request, pac);
}
static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
ssize_t srv_checksum_idx = -1;
ssize_t kdc_checksum_idx = -1;
ssize_t tkt_checksum_idx = -1;
+ ssize_t attrs_info_idx = -1;
if (!mem_ctx) {
return ENOMEM;
struct samba_kdc_entry);
nt_status = samba_kdc_get_pac_blobs(mem_ctx, client_skdc_entry,
- &pac_blob, NULL, &upn_blob);
+ &pac_blob, NULL, &upn_blob,
+ NULL, NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
talloc_free(mem_ctx);
return EINVAL;
}
tkt_checksum_idx = i;
break;
+ case PAC_TYPE_ATTRIBUTES_INFO:
+ if (attrs_info_idx != -1) {
+ DEBUG(1, ("attributes info type[%"PRIu32"] twice [%zd] and [%zu]: \n",
+ types[i],
+ attrs_info_idx,
+ i));
+ SAFE_FREE(types);
+ talloc_free(mem_ctx);
+ return EINVAL;
+ }
+ attrs_info_idx = i;
+ break;
default:
continue;
}
goto out;
}
+ if (!server_skdc_entry->is_krbtgt) {
+ /*
+ * The client may have requested no PAC when obtaining the
+ * TGT.
+ */
+ bool requested_pac;
+ ret = samba_client_requested_pac(context, pac, mem_ctx,
+ &requested_pac);
+ if (ret != 0 || !requested_pac) {
+ new_pac = NULL;
+ goto out;
+ }
+ }
+
/* Otherwise build an updated PAC */
ret = krb5_pac_init(context, &new_pac);
if (ret != 0) {
*/
type_blob = data_blob_const(&zero_byte, 1);
break;
+ case PAC_TYPE_ATTRIBUTES_INFO:
+ /* just copy... */
+ break;
default:
/* just copy... */
break;