1
0
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:
Andrew Bartlett 2005-10-24 07:11:40 +00:00 committed by Gerald (Jerry) Carter
parent 7bc855359a
commit 11b1d78cc5
5 changed files with 114 additions and 91 deletions

View File

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

View File

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

View File

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

View File

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

View File

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