mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
r11272: In trying to track down why Win2k3 is again rejecting our PAC, ensure
we can round-trip all the way back to a server_info structure, not just a filled in PAC_DATA. (I was worried about generated fields being incorrect, or some other logical flaw). Andrew Bartlett
This commit is contained in:
parent
7bc855359a
commit
11b1d78cc5
@ -94,6 +94,7 @@ struct auth_serversupplied_info
|
||||
const char *profile_path;
|
||||
const char *home_directory;
|
||||
const char *home_drive;
|
||||
const char *logon_server;
|
||||
|
||||
NTTIME last_logon;
|
||||
NTTIME last_logoff;
|
||||
|
@ -36,6 +36,10 @@ NTSTATUS auth_convert_server_info_sambaseinfo(TALLOC_CTX *mem_ctx,
|
||||
struct netr_SamBaseInfo *sam = talloc_zero(mem_ctx, struct netr_SamBaseInfo);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam);
|
||||
|
||||
sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid);
|
||||
sam->domain_sid->num_auths--;
|
||||
|
||||
sam->last_logon = server_info->last_logon;
|
||||
sam->last_logoff = server_info->last_logoff;
|
||||
sam->acct_expiry = server_info->acct_expiry;
|
||||
@ -67,8 +71,11 @@ NTSTATUS auth_convert_server_info_sambaseinfo(TALLOC_CTX *mem_ctx,
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
|
||||
for (i=0; i<server_info->n_domain_groups; i++) {
|
||||
|
||||
struct dom_sid *group_sid = server_info->domain_groups[i];
|
||||
if (!dom_sid_in_domain(sam->domain_sid, group_sid)) {
|
||||
/* We handle this elsewhere */
|
||||
continue;
|
||||
}
|
||||
sam->groups.rids[sam->groups.count].rid =
|
||||
group_sid->sub_auths[group_sid->num_auths-1];
|
||||
|
||||
@ -82,13 +89,9 @@ NTSTATUS auth_convert_server_info_sambaseinfo(TALLOC_CTX *mem_ctx,
|
||||
* as extra sids (PAC doc) but what is
|
||||
* 0x100? */
|
||||
sam->acct_flags = server_info->acct_flags;
|
||||
sam->logon_server.string = lp_netbios_name();
|
||||
sam->logon_server.string = server_info->logon_server;
|
||||
sam->domain.string = server_info->domain_name;
|
||||
|
||||
sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid);
|
||||
sam->domain_sid->num_auths--;
|
||||
|
||||
ZERO_STRUCT(sam->unknown);
|
||||
|
||||
ZERO_STRUCT(sam->key);
|
||||
@ -113,81 +116,19 @@ NTSTATUS auth_convert_server_info_saminfo3(TALLOC_CTX *mem_ctx,
|
||||
{
|
||||
struct netr_SamBaseInfo *sam;
|
||||
struct netr_SamInfo3 *sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam3);
|
||||
|
||||
sam = &sam3->base;
|
||||
|
||||
sam->domain_sid = dom_sid_dup(mem_ctx, server_info->account_sid);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam->domain_sid);
|
||||
sam->domain_sid->num_auths--;
|
||||
|
||||
sam->last_logon = server_info->last_logon;
|
||||
sam->last_logoff = server_info->last_logoff;
|
||||
sam->acct_expiry = server_info->acct_expiry;
|
||||
sam->last_password_change = server_info->last_password_change;
|
||||
sam->allow_password_change = server_info->allow_password_change;
|
||||
sam->force_password_change = server_info->force_password_change;
|
||||
|
||||
sam->account_name.string = server_info->account_name;
|
||||
sam->full_name.string = server_info->full_name;
|
||||
sam->logon_script.string = server_info->logon_script;
|
||||
sam->profile_path.string = server_info->profile_path;
|
||||
sam->home_directory.string = server_info->home_directory;
|
||||
sam->home_drive.string = server_info->home_drive;
|
||||
|
||||
sam->logon_count = server_info->logon_count;
|
||||
sam->bad_password_count = sam->bad_password_count;
|
||||
sam->rid = server_info->account_sid->sub_auths[server_info->account_sid->num_auths-1];
|
||||
sam->primary_gid = server_info->primary_group_sid->sub_auths[server_info->primary_group_sid->num_auths-1];
|
||||
|
||||
sam->groups.count = 0;
|
||||
sam->groups.rids = NULL;
|
||||
|
||||
if (server_info->n_domain_groups > 0) {
|
||||
int i;
|
||||
sam->groups.rids = talloc_array(sam, struct samr_RidWithAttribute,
|
||||
server_info->n_domain_groups);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam->groups.rids);
|
||||
|
||||
for (i=0; i<server_info->n_domain_groups; i++) {
|
||||
struct dom_sid *group_sid = server_info->domain_groups[i];
|
||||
|
||||
if (!dom_sid_in_domain(sam->domain_sid, group_sid)) {
|
||||
continue;
|
||||
status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
sam->groups.rids[sam->groups.count].rid = group_sid->sub_auths[group_sid->num_auths-1];
|
||||
sam->groups.rids[sam->groups.count].attributes =
|
||||
SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
|
||||
sam->groups.count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
sam->user_flags = 0x20; /* TODO: w2k3 uses 0x120. We know 0x20
|
||||
* as extra sids (PAC doc) but what is
|
||||
* 0x100? */
|
||||
sam->acct_flags = server_info->acct_flags;
|
||||
sam->logon_server.string = lp_netbios_name();
|
||||
sam->domain.string = server_info->domain_name;
|
||||
|
||||
ZERO_STRUCT(sam->unknown);
|
||||
|
||||
ZERO_STRUCT(sam->key);
|
||||
if (server_info->user_session_key.length == sizeof(sam->key.key)) {
|
||||
memcpy(sam->key.key, server_info->user_session_key.data, sizeof(sam->key.key));
|
||||
}
|
||||
|
||||
ZERO_STRUCT(sam->LMSessKey);
|
||||
if (server_info->lm_session_key.length == sizeof(sam->LMSessKey.key)) {
|
||||
memcpy(sam->LMSessKey.key, server_info->lm_session_key.data,
|
||||
sizeof(sam->LMSessKey.key));
|
||||
}
|
||||
|
||||
sam3->base = *sam;
|
||||
sam3->sidcount = 0;
|
||||
sam3->sids = NULL;
|
||||
#if 0
|
||||
if (server_info->n_domain_groups > 0) {
|
||||
int i;
|
||||
|
||||
|
||||
sam3->sids = talloc_array(sam, struct netr_SidAttr,
|
||||
server_info->n_domain_groups);
|
||||
NT_STATUS_HAVE_NO_MEMORY(sam3->sids);
|
||||
@ -201,8 +142,11 @@ NTSTATUS auth_convert_server_info_saminfo3(TALLOC_CTX *mem_ctx,
|
||||
SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
|
||||
sam3->sidcount += 1;
|
||||
}
|
||||
if (sam3->sidcount) {
|
||||
sam3->base.user_flags |= NETLOGON_EXTRA_SIDS;
|
||||
} else {
|
||||
sam3->sids = NULL;
|
||||
}
|
||||
#endif
|
||||
*_sam3 = sam3;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
|
@ -327,6 +327,7 @@ NTSTATUS make_server_info_netlogon_validation(TALLOC_CTX *mem_ctx,
|
||||
server_info->profile_path = talloc_reference(server_info, base->profile_path.string);
|
||||
server_info->home_directory = talloc_reference(server_info, base->home_directory.string);
|
||||
server_info->home_drive = talloc_reference(server_info, base->home_drive.string);
|
||||
server_info->logon_server = talloc_reference(server_info, base->logon_server.string);
|
||||
server_info->last_logon = base->last_logon;
|
||||
server_info->last_logoff = base->last_logoff;
|
||||
server_info->acct_expiry = base->acct_expiry;
|
||||
|
@ -487,7 +487,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
|
||||
krb5_error_code ret;
|
||||
struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
|
||||
struct netr_SamInfo3 *sam3;
|
||||
struct timeval tv = timeval_current();
|
||||
union PAC_INFO *u_LOGON_INFO;
|
||||
struct PAC_LOGON_INFO *LOGON_INFO;
|
||||
union PAC_INFO *u_LOGON_NAME;
|
||||
@ -573,7 +572,6 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx,
|
||||
|
||||
u_LOGON_INFO->logon_info.info = LOGON_INFO;
|
||||
LOGON_INFO->info3 = *sam3;
|
||||
LOGON_INFO->info3.base.last_logon = timeval_to_nttime(&tv);
|
||||
|
||||
ret = krb5_unparse_name_norealm(context, client_principal, &name);
|
||||
if (ret) {
|
||||
|
@ -272,7 +272,7 @@ 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, validate_blob;
|
||||
struct PAC_DATA *pac_data;
|
||||
struct PAC_DATA *pac_data, pac_data2;
|
||||
struct PAC_LOGON_INFO *logon_info;
|
||||
union netr_Validation validation;
|
||||
const char *pac_file, *pac_kdc_key, *pac_member_key;
|
||||
@ -526,6 +526,85 @@ static BOOL torture_pac_saved_check(void)
|
||||
return False;
|
||||
}
|
||||
|
||||
ret = kerberos_create_pac(mem_ctx,
|
||||
server_info_out,
|
||||
smb_krb5_context->krb5_context,
|
||||
&krbtgt_keyblock,
|
||||
&server_keyblock,
|
||||
client_principal, authtime,
|
||||
&validate_blob);
|
||||
|
||||
if (ret != 0) {
|
||||
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
|
||||
&krbtgt_keyblock);
|
||||
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
|
||||
&server_keyblock);
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
|
||||
|
||||
DEBUG(0, ("(saved test) regnerated PAC create failed\n"));
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
dump_data(10,validate_blob.data,validate_blob.length);
|
||||
|
||||
/* compare both the length and the data bytes after a
|
||||
* pull/push cycle. This ensures we use the exact same
|
||||
* pointer, padding etc algorithms as win2k3.
|
||||
*/
|
||||
if (tmp_blob.length != validate_blob.length) {
|
||||
nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
|
||||
(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;
|
||||
}
|
||||
|
||||
NDR_PRINT_DEBUG(PAC_DATA, pac_data);
|
||||
|
||||
NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
|
||||
|
||||
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
|
||||
&krbtgt_keyblock);
|
||||
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
|
||||
&server_keyblock);
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
|
||||
|
||||
DEBUG(0, ("(saved test) PAC regenerate failed: original buffer length[%u] != created buffer length[%u]\n",
|
||||
(unsigned)tmp_blob.length, (unsigned)validate_blob.length));
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
if (memcmp(tmp_blob.data, validate_blob.data, tmp_blob.length) != 0) {
|
||||
nt_status = ndr_pull_struct_blob(&validate_blob, mem_ctx, &pac_data2,
|
||||
(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;
|
||||
}
|
||||
|
||||
NDR_PRINT_DEBUG(PAC_DATA, pac_data);
|
||||
|
||||
NDR_PRINT_DEBUG(PAC_DATA, &pac_data2);
|
||||
|
||||
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
|
||||
&krbtgt_keyblock);
|
||||
krb5_free_keyblock_contents(smb_krb5_context->krb5_context,
|
||||
&server_keyblock);
|
||||
krb5_free_principal(smb_krb5_context->krb5_context, client_principal);
|
||||
|
||||
DEBUG(0, ("(saved test) PAC regenerate failed: length[%u] matches, but data does not\n",
|
||||
(unsigned)tmp_blob.length));
|
||||
DEBUG(0, ("tmp_data:\n"));
|
||||
dump_data(0, tmp_blob.data, tmp_blob.length);
|
||||
DEBUG(0, ("validate_blob:\n"));
|
||||
dump_data(0, validate_blob.data, validate_blob.length);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Break the auth time, to ensure we check this vital detail (not setting this caused all the pain in the first place... */
|
||||
nt_status = kerberos_decode_pac(mem_ctx, &pac_data,
|
||||
tmp_blob,
|
||||
|
Loading…
Reference in New Issue
Block a user