1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r8148: - make the PAC generation code a bit more readable and add some outof memory checks

- move to handmodified pull/push code for PAC_BUFFER
  to get the _ndr_size field and the subcontext size right

- after looking closely to the sample w2k3 PAC in our torture test (and some more in my archive)
  I found out that the first uint32 before the netr_SamInfo3 was also a pointer,
  (and we passed a NULL pointer there before, so I think that was the reason why the windows clients doesn't want our PAC)

  w2k3 uses this for unique pointers:

  ptr = ndr->ptr_count * 4;
  ptr |= 0x00020000;
  ndr->ptr_count;

- do one more pull/push round with the sample PAC

metze
This commit is contained in:
Stefan Metzmacher 2005-07-04 15:42:08 +00:00 committed by Gerald (Jerry) Carter
parent 5fcaa21d67
commit 0eee179415
7 changed files with 277 additions and 78 deletions

View File

@ -111,7 +111,7 @@ static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx,
if (!pac_data.buffers[i].info) {
break;
}
logon_info = &pac_data.buffers[i].info->logon_info;
logon_info = pac_data.buffers[i].info->logon_info.i;
break;
case PAC_TYPE_SRV_CHECKSUM:
if (!pac_data.buffers[i].info) {
@ -230,9 +230,17 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
struct netr_SamBaseInfo *sam;
struct timeval tv = timeval_current();
union PAC_INFO *u_LOGON_INFO;
struct PAC_LOGON_INFO *LOGON_INFO;
union PAC_INFO *u_LOGON_NAME;
struct PAC_LOGON_NAME *LOGON_NAME;
union PAC_INFO *u_KDC_CHECKSUM;
struct PAC_SIGNATURE_DATA *KDC_CHECKSUM;
union PAC_INFO *u_SRV_CHECKSUM;
struct PAC_SIGNATURE_DATA *SRV_CHECKSUM;
enum {
PAC_BUF_LOGON_TYPE = 0,
PAC_BUF_LOGON_INFO = 0,
PAC_BUF_LOGON_NAME = 1,
PAC_BUF_KDC_CHECKSUM = 2,
PAC_BUF_SRV_CHECKSUM = 3,
@ -249,52 +257,78 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
pac_data->buffers = talloc_array(pac_data,
struct PAC_BUFFER,
pac_data->num_buffers);
if (!pac_data->buffers) {
talloc_free(pac_data);
return ENOMEM;
}
pac_data->buffers[PAC_BUF_LOGON_TYPE].type = PAC_TYPE_LOGON_INFO;
pac_data->buffers[PAC_BUF_LOGON_TYPE].info = talloc_zero(pac_data->buffers,
union PAC_INFO);
/* LOGON_INFO */
u_LOGON_INFO = talloc_zero(pac_data->buffers, union PAC_INFO);
if (!u_LOGON_INFO) {
talloc_free(pac_data);
return ENOMEM;
}
pac_data->buffers[PAC_BUF_LOGON_INFO].type = PAC_TYPE_LOGON_INFO;
pac_data->buffers[PAC_BUF_LOGON_INFO].info = u_LOGON_INFO;
nt_status = auth_convert_server_info_sambaseinfo(pac_data->buffers[0].info,
server_info, &sam);
/* LOGON_NAME */
u_LOGON_NAME = talloc_zero(pac_data->buffers, union PAC_INFO);
if (!u_LOGON_NAME) {
talloc_free(pac_data);
return ENOMEM;
}
pac_data->buffers[PAC_BUF_LOGON_NAME].type = PAC_TYPE_LOGON_NAME;
pac_data->buffers[PAC_BUF_LOGON_NAME].info = u_LOGON_NAME;
LOGON_NAME = &u_LOGON_NAME->logon_name;
/* KDC_CHECKSUM */
u_KDC_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
if (!u_KDC_CHECKSUM) {
talloc_free(pac_data);
return ENOMEM;
}
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = u_KDC_CHECKSUM;
KDC_CHECKSUM = &u_KDC_CHECKSUM->kdc_cksum;
/* SRV_CHECKSUM */
u_SRV_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
if (!u_SRV_CHECKSUM) {
talloc_free(pac_data);
return ENOMEM;
}
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = u_SRV_CHECKSUM;
SRV_CHECKSUM = &u_SRV_CHECKSUM->srv_cksum;
/* now the real work begins... */
LOGON_INFO = talloc_zero(u_LOGON_INFO, struct PAC_LOGON_INFO);
if (!LOGON_INFO) {
talloc_free(pac_data);
return ENOMEM;
}
nt_status = auth_convert_server_info_sambaseinfo(LOGON_INFO, server_info, &sam);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status)));
talloc_free(pac_data);
return EINVAL;
}
pac_data->buffers[PAC_BUF_LOGON_TYPE].info->logon_info.info3.base = *sam;
pac_data->buffers[PAC_BUF_LOGON_TYPE].size
= ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_LOGON_TYPE].info,
pac_data->buffers[PAC_BUF_LOGON_TYPE].type,
0);
pac_data->buffers[PAC_BUF_LOGON_TYPE]._pad = 0;
pac_data->buffers[PAC_BUF_LOGON_NAME].type = PAC_TYPE_LOGON_NAME;
pac_data->buffers[PAC_BUF_LOGON_NAME].info = talloc_zero(pac_data->buffers,
union PAC_INFO);
pac_data->buffers[PAC_BUF_LOGON_NAME].info->logon_name.account_name
= server_info->account_name;
pac_data->buffers[PAC_BUF_LOGON_NAME].info->logon_name.logon_time
= timeval_to_nttime(&tv);
pac_data->buffers[PAC_BUF_LOGON_NAME].size
= ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_LOGON_NAME].info,
pac_data->buffers[PAC_BUF_LOGON_NAME].type,
0);
pac_data->buffers[PAC_BUF_LOGON_NAME]._pad = 0;
u_LOGON_INFO->logon_info.unknown[0] = 0x00081001;
u_LOGON_INFO->logon_info.unknown[1] = 0xCCCCCCCC;
u_LOGON_INFO->logon_info.unknown[2] = 0x000001C8;
u_LOGON_INFO->logon_info.unknown[3] = 0x00000000;
u_LOGON_INFO->logon_info.i = LOGON_INFO;
LOGON_INFO->info3.base = *sam;
LOGON_NAME->account_name = server_info->account_name;
LOGON_NAME->logon_time = timeval_to_nttime(&tv);
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = talloc_zero(pac_data->buffers,
union PAC_INFO);
/* First, just get the keytypes filled in (and lengths right, eventually) */
ret = make_pac_checksum(mem_ctx, zero_blob,
&pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info->kdc_cksum,
context, krbtgt_keyblock);
ret = make_pac_checksum(mem_ctx, zero_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
if (ret) {
DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
@ -302,19 +336,7 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
return ret;
}
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].size
= ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info,
pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type,
0);
pac_data->buffers[PAC_BUF_KDC_CHECKSUM]._pad = 0;
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = talloc_zero(pac_data->buffers,
union PAC_INFO);
ret = make_pac_checksum(mem_ctx, zero_blob,
&pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info->srv_cksum,
context, server_keyblock);
ret = make_pac_checksum(mem_ctx, zero_blob, SRV_CHECKSUM, context, server_keyblock);
if (ret) {
DEBUG(2, ("making server PAC checksum failed: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
@ -322,16 +344,10 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
return ret;
}
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].size
= ndr_size_PAC_INFO(pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info,
pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type,
0);
pac_data->buffers[PAC_BUF_SRV_CHECKSUM]._pad = 0;
/* But wipe out the actual signatures */
ZERO_STRUCT(pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info->kdc_cksum.signature);
ZERO_STRUCT(pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info->srv_cksum.signature);
ZERO_STRUCT(KDC_CHECKSUM->signature);
ZERO_STRUCT(SRV_CHECKSUM->signature);
nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,
(ndr_push_flags_fn_t)ndr_push_PAC_DATA);
if (!NT_STATUS_IS_OK(nt_status)) {
@ -341,12 +357,11 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
}
/* Then sign the result of the previous push, where the sig was zero'ed out */
ret = make_pac_checksum(mem_ctx, tmp_blob, &pac_data->buffers[3].info->srv_cksum,
ret = make_pac_checksum(mem_ctx, tmp_blob, SRV_CHECKSUM,
context, server_keyblock);
/* Push the Server checksum out */
nt_status = ndr_push_struct_blob(&server_checksum_blob, mem_ctx,
&pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info->srv_cksum,
nt_status = ndr_push_struct_blob(&server_checksum_blob, mem_ctx, SRV_CHECKSUM,
(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(1, ("PAC_SIGNATURE push failed: %s\n", nt_errstr(nt_status)));
@ -354,10 +369,14 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
return EINVAL;
}
/* Then sign the result of the previous push, where the sig was zero'ed out */
ret = make_pac_checksum(mem_ctx, server_checksum_blob,
&pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info->kdc_cksum,
context, krbtgt_keyblock);
/* Then sign Server checksum */
ret = make_pac_checksum(mem_ctx, server_checksum_blob, KDC_CHECKSUM, context, krbtgt_keyblock);
if (ret) {
DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
smb_get_krb5_error_message(context, ret, mem_ctx)));
talloc_free(pac_data);
return ret;
}
/* And push it out again, this time to the world. This relies on determanistic pointer values */
nt_status = ndr_push_struct_blob(&tmp_blob, mem_ctx, pac_data,

View File

@ -89,6 +89,8 @@ struct epm_tower;
struct drsuapi_DsCrackNames;
struct PAC_BUFFER;
struct samr_ChangePasswordUser;
struct samr_OemChangePasswordUser2;
struct samr_ChangePasswordUser3;

View File

@ -308,7 +308,10 @@ REQUIRED_SUBSYSTEMS = NDR_RAW
INIT_FUNCTION = dcerpc_krb5pac_init
INIT_OBJ_FILES = librpc/gen_ndr/ndr_krb5pac.o
NOPROTO = YES
REQUIRED_SUBSYSTEMS = NDR_RAW
REQUIRED_SUBSYSTEMS = NDR_RAW NDR_KRB5PAC_UTIL
[SUBSYSTEM::NDR_KRB5PAC_UTIL]
INIT_OBJ_FILES = librpc/ndr/ndr_krb5pac.o
[SUBSYSTEM::NDR_XATTR]
INIT_FUNCTION = dcerpc_xattr_init

View File

@ -5,7 +5,7 @@
#include "idl_types.h"
[
uuid("46746756-7567-7567-5677-756756756756"),
uuid("1-2-3-4"),
version(0.0),
pointer_default(unique),
pointer_default_top(unique),
@ -24,29 +24,35 @@ interface krb5pac
} PAC_SIGNATURE_DATA;
typedef struct {
uint32 unknown[5];
netr_SamInfo3 info3;
dom_sid2 *res_group_dom_sid;
samr_RidWithAttributeArray res_groups;
} PAC_LOGON_INFO;
const uint8 PAC_TYPE_LOGON_INFO = 1;
const uint8 PAC_TYPE_SRV_CHECKSUM = 6;
const uint8 PAC_TYPE_KDC_CHECKSUM = 7;
const uint8 PAC_TYPE_LOGON_NAME = 10;
typedef struct {
uint32 unknown[4];
PAC_LOGON_INFO *i;
} PAC_LOGON_INFO_CTR;
typedef [nodiscriminant,gensize] union {
[case(PAC_TYPE_LOGON_INFO)] PAC_LOGON_INFO logon_info;
typedef [public,v1_enum] enum {
PAC_TYPE_LOGON_INFO = 1,
PAC_TYPE_SRV_CHECKSUM = 6,
PAC_TYPE_KDC_CHECKSUM = 7,
PAC_TYPE_LOGON_NAME = 10
} PAC_TYPE;
typedef [public,nodiscriminant,gensize] union {
[case(PAC_TYPE_LOGON_INFO)] PAC_LOGON_INFO_CTR logon_info;
[case(PAC_TYPE_SRV_CHECKSUM)] PAC_SIGNATURE_DATA srv_cksum;
[case(PAC_TYPE_KDC_CHECKSUM)] PAC_SIGNATURE_DATA kdc_cksum;
[case(PAC_TYPE_LOGON_NAME)] PAC_LOGON_NAME logon_name;
} PAC_INFO;
typedef struct {
uint32 type;
uint32 size;
[relative,switch_is(type),subcontext(0),subcontext_size(size),pad8] PAC_INFO *info;
uint32 _pad; /* Top half of a 64 bit pointer? */
typedef [public,nopush,nopull,noprint] struct {
PAC_TYPE type;
[value(_ndr_size_PAC_INFO(info, type, 0))] uint32 _ndr_size;
[relative,switch_is(type),subcontext(0),subcontext_size(_subcontext_size_PAC_INFO(r, ndr->flags)),flag(NDR_ALIGN8)] PAC_INFO *info;
[value(0)] uint32 _pad; /* Top half of a 64 bit pointer? */
} PAC_BUFFER;
typedef [public] struct {

View File

@ -191,6 +191,8 @@ enum ndr_compression_alg {
#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n)
#define NDR_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
#define NDR_PULL_ALIGN(ndr, n) do { \
if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
if (ndr->flags & LIBNDR_FLAG_PAD_CHECK) { \

View File

@ -0,0 +1,143 @@
/*
Unix SMB/CIFS implementation.
routines for marshalling/unmarshalling spoolss subcontext buffer structures
Copyright (C) Stefan Metzmacher 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.
*/
#include "includes.h"
#include "librpc/gen_ndr/ndr_krb5pac.h"
size_t _ndr_size_PAC_INFO(const union PAC_INFO *r, uint32_t level, int flags)
{
size_t s = ndr_size_PAC_INFO(r, level, flags);
switch (level) {
case PAC_TYPE_LOGON_INFO:
return NDR_ROUND(s,8);
default:
return s;
}
}
size_t _subcontext_size_PAC_INFO(const union PAC_INFO *r, uint32_t level, int flags)
{
size_t s = ndr_size_PAC_INFO(r, level, flags);
return NDR_ROUND(s,8);
}
NTSTATUS ndr_push_PAC_BUFFER(struct ndr_push *ndr, int ndr_flags, const struct PAC_BUFFER *r)
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_align(ndr, 4));
NDR_CHECK(ndr_push_PAC_TYPE(ndr, NDR_SCALARS, r->type));
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, _ndr_size_PAC_INFO(r->info,r->type,0)));
{
uint32_t _flags_save_PAC_INFO = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
NDR_CHECK(ndr_push_relative_ptr1(ndr, r->info));
ndr->flags = _flags_save_PAC_INFO;
}
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
}
if (ndr_flags & NDR_BUFFERS) {
{
uint32_t _flags_save_PAC_INFO = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
if (r->info) {
NDR_CHECK(ndr_push_relative_ptr2(ndr, r->info));
{
struct ndr_push *_ndr_info;
_ndr_info = ndr_push_init_ctx(ndr);
if (!_ndr_info) return NT_STATUS_NO_MEMORY;
_ndr_info->flags = ndr->flags;
NDR_CHECK(ndr_push_set_switch_value(_ndr_info, r->info, r->type));
NDR_CHECK(ndr_push_PAC_INFO(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->info));
NDR_CHECK(ndr_push_subcontext_header(ndr, 0, _subcontext_size_PAC_INFO(r->info,r->type,0), _ndr_info));
NDR_CHECK(ndr_push_bytes(ndr, _ndr_info->data, _ndr_info->offset));
}
}
ndr->flags = _flags_save_PAC_INFO;
}
}
return NT_STATUS_OK;
}
NTSTATUS ndr_pull_PAC_BUFFER(struct ndr_pull *ndr, int ndr_flags, struct PAC_BUFFER *r)
{
uint32_t _ptr_info;
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_pull_align(ndr, 4));
NDR_CHECK(ndr_pull_PAC_TYPE(ndr, NDR_SCALARS, &r->type));
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_ndr_size));
{
uint32_t _flags_save_PAC_INFO = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_info));
if (_ptr_info) {
NDR_ALLOC(ndr, r->info);
NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->info, _ptr_info));
} else {
r->info = NULL;
}
ndr->flags = _flags_save_PAC_INFO;
}
NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
}
if (ndr_flags & NDR_BUFFERS) {
{
uint32_t _flags_save_PAC_INFO = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8);
if (r->info) {
struct ndr_pull_save _relative_save;
ndr_pull_save(ndr, &_relative_save);
NDR_CHECK(ndr_pull_relative_ptr2(ndr, r->info));
{
struct ndr_pull *_ndr_info;
NDR_ALLOC(ndr, _ndr_info);
NDR_CHECK(ndr_pull_subcontext_header(ndr, 0, r->_ndr_size, _ndr_info));
NDR_CHECK(ndr_pull_set_switch_value(_ndr_info, r->info, r->type));
NDR_CHECK(ndr_pull_PAC_INFO(_ndr_info, NDR_SCALARS|NDR_BUFFERS, r->info));
NDR_CHECK(ndr_pull_advance(ndr, r->_ndr_size));
}
ndr_pull_restore(ndr, &_relative_save);
}
ndr->flags = _flags_save_PAC_INFO;
}
}
return NT_STATUS_OK;
}
void ndr_print_PAC_BUFFER(struct ndr_print *ndr, const char *name, const struct PAC_BUFFER *r)
{
ndr_print_struct(ndr, name, "PAC_BUFFER");
ndr->depth++;
ndr_print_PAC_TYPE(ndr, "type", r->type);
ndr_print_uint32(ndr, "_ndr_size", (ndr->flags & LIBNDR_PRINT_SET_VALUES)?_ndr_size_PAC_INFO(r->info,r->type,0):r->_ndr_size);
ndr_print_ptr(ndr, "info", r->info);
ndr->depth++;
if (r->info) {
ndr_print_set_switch_value(ndr, r->info, r->type);
ndr_print_PAC_INFO(ndr, "info", r->info);
}
ndr->depth--;
ndr_print_uint32(ndr, "_pad", r->_pad);
ndr->depth--;
}

View File

@ -118,7 +118,9 @@ static BOOL torture_pac_self_check(void)
talloc_free(mem_ctx);
return False;
}
/* dump_data(0,tmp_blob.data,tmp_blob.length); */
/* Now check that we can read it back */
nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
tmp_blob,
@ -190,8 +192,9 @@ static BOOL torture_pac_saved_check(void)
{
NTSTATUS nt_status;
TALLOC_CTX *mem_ctx = talloc_named(NULL, 0, "PAC saved check");
DATA_BLOB tmp_blob;
DATA_BLOB tmp_blob, validate_blob;
struct PAC_LOGON_INFO *pac_info;
struct PAC_DATA pac_data;
krb5_keyblock server_keyblock;
uint8_t server_bytes[16];
@ -225,6 +228,10 @@ static BOOL torture_pac_saved_check(void)
tmp_blob = data_blob_const(saved_pac, sizeof(saved_pac));
/*tmp_blob.data = file_load(lp_parm_string(-1,"torture","pac_file"), &tmp_blob.length);*/
/*dump_data(0,tmp_blob.data,tmp_blob.length);*/
/* Decode and verify the signaure on the PAC */
nt_status = kerberos_decode_pac(mem_ctx, &pac_info,
tmp_blob,
@ -239,6 +246,23 @@ static BOOL torture_pac_saved_check(void)
talloc_free(mem_ctx);
return False;
}
nt_status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("can't parse the PAC\n"));
return False;
}
nt_status = ndr_push_struct_blob(&validate_blob, mem_ctx, &pac_data,
(ndr_push_flags_fn_t)ndr_push_PAC_DATA);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("PAC push failed: %s\n", nt_errstr(nt_status)));
return False;
}
/* dump_data(0,validate_blob.data,validate_blob.length); */
talloc_free(mem_ctx);
return True;
}