From 111f62c00c31ac98d50c0a01e31cb1d44082be29 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 20 Dec 2004 12:52:33 +0000 Subject: r4287: Vampire SAM_DELTA_DOMAIN_INFO. Based on samba4-idl. The decoding of account-lockout-string is somewhat experimental though. Guenther (This used to be commit 721bf50d7446b8ce18bc1d45e17d4214d5a43d26) --- source3/include/rpc_misc.h | 9 ++++ source3/include/rpc_netlogon.h | 47 +++++++++++++++-- source3/rpc_parse/parse_misc.c | 62 ++++++++++++++++++++++ source3/rpc_parse/parse_net.c | 46 +++++++++++----- source3/utils/net_rpc_samsync.c | 114 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 259 insertions(+), 19 deletions(-) diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index 0c6eee3650..ee8208e90e 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -395,6 +395,15 @@ typedef struct bufhdr2_info } BUFHDR2; +/* BUFHDR4 - another buffer header */ +typedef struct bufhdr4_info +{ + uint32 size; + uint32 buffer; + +} +BUFHDR4; + /* BUFFER4 - simple length and buffer */ typedef struct buffer4_info { diff --git a/source3/include/rpc_netlogon.h b/source3/include/rpc_netlogon.h index 97b2523d72..b865d05b34 100644 --- a/source3/include/rpc_netlogon.h +++ b/source3/include/rpc_netlogon.h @@ -597,6 +597,27 @@ typedef struct sam_delta_hdr_info } SAM_DELTA_HDR; +/* LOCKOUT_STRING */ +typedef struct account_lockout_string { + uint32 array_size; + uint32 offset; + uint32 length; +/* uint16 *bindata; */ + UINT64_S lockout_duration; + UINT64_S reset_count; + uint32 bad_attempt_lockout; + uint32 dummy; + +} LOCKOUT_STRING; + +/* HDR_LOCKOUT_STRING */ +typedef struct hdr_account_lockout_string { + uint16 size; + uint16 length; + uint32 buffer; + +} HDR_LOCKOUT_STRING; + /* SAM_DOMAIN_INFO (0x1) */ typedef struct sam_domain_info_info { @@ -610,16 +631,32 @@ typedef struct sam_domain_info_info UINT64_S min_pwd_age; UINT64_S dom_mod_count; NTTIME creation_time; + uint32 security_information; - BUFHDR2 hdr_sec_desc; /* security descriptor */ - UNIHDR hdr_unknown; - uint8 reserved[40]; + BUFHDR4 hdr_sec_desc; /* security descriptor */ + + HDR_LOCKOUT_STRING hdr_account_lockout; + + UNIHDR hdr_unknown2; + UNIHDR hdr_unknown3; + UNIHDR hdr_unknown4; UNISTR2 uni_dom_name; - UNISTR2 buf_oem_info; /* never seen */ + UNISTR2 buf_oem_info; BUFFER4 buf_sec_desc; - UNISTR2 buf_unknown; + + LOCKOUT_STRING account_lockout; + + UNISTR2 buf_unknown2; + UNISTR2 buf_unknown3; + UNISTR2 buf_unknown4; + + uint32 logon_chgpass; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } SAM_DOMAIN_INFO; diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 17a8f624ae..0ebc16581b 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -1109,6 +1109,53 @@ BOOL init_unistr2_array(UNISTR2_ARRAY *array, return True; } +BOOL smb_io_lockout_string_hdr(const char *desc, HDR_LOCKOUT_STRING *hdr_account_lockout, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "smb_io_lockout_string_hdr"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint16("size", ps, depth, &hdr_account_lockout->size)) + return False; + if(!prs_uint16("length", ps, depth, &hdr_account_lockout->length)) + return False; + if(!prs_uint32("buffer", ps, depth, &hdr_account_lockout->buffer)) + return False; + + return True; +} + +BOOL smb_io_account_lockout_str(const char *desc, LOCKOUT_STRING *account_lockout, uint32 buffer, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "smb_io_account_lockout_string"); + depth++; + + if(!prs_uint32("array_size", ps, depth, &account_lockout->array_size)) + return False; + + if(!prs_uint32("offset", ps, depth, &account_lockout->offset)) + return False; + if(!prs_uint32("length", ps, depth, &account_lockout->length)) + return False; + + if (!prs_uint64("lockout_duration", ps, depth, &account_lockout->lockout_duration)) + return False; + if (!prs_uint64("reset_count", ps, depth, &account_lockout->reset_count)) + return False; + if (!prs_uint32("bad_attempt_lockout", ps, depth, &account_lockout->bad_attempt_lockout)) + return False; + if (!prs_uint32("dummy", ps, depth, &account_lockout->dummy)) + return False; +#if 0 + if(!prs_uint16s (False, "bindata", ps, depth, &account_lockout->bindata, length)) + return False; +#endif + + return True; +} + /******************************************************************* Reads or writes a UNISTR2_ARRAY structure. ********************************************************************/ @@ -1694,6 +1741,21 @@ BOOL smb_io_bufhdr2(const char *desc, BUFHDR2 *hdr, prs_struct *ps, int depth) return True; } +/******************************************************************* +reads or writes a BUFHDR4 structure. +********************************************************************/ +BOOL smb_io_bufhdr4(const char *desc, BUFHDR4 *hdr, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "smb_io_bufhdr4"); + depth++; + + prs_align(ps); + prs_uint32("size", ps, depth, &(hdr->size)); + prs_uint32("buffer", ps, depth, &(hdr->buffer)); + + return True; +} + /******************************************************************* reads or writes a BUFFER4 structure. ********************************************************************/ diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index 7e5eec3e6d..5f1d4b622e 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -1937,15 +1937,26 @@ static BOOL net_io_sam_domain_info(const char *desc, SAM_DOMAIN_INFO * info, return False; if (!smb_io_time("creation_time", &info->creation_time, ps, depth)) return False; - - if (!smb_io_bufhdr2("hdr_sec_desc", &info->hdr_sec_desc, ps, depth)) - return False; - if (!smb_io_unihdr("hdr_unknown", &info->hdr_unknown, ps, depth)) - return False; - - if (ps->data_offset + 40 > ps->buffer_size) - return False; - ps->data_offset += 40; + if (!prs_uint32("security_information", ps, depth, &info->security_information)) + return False; + if (!smb_io_bufhdr4("hdr_sec_desc", &info->hdr_sec_desc, ps, depth)) + return False; + if (!smb_io_lockout_string_hdr("hdr_account_lockout_string", &info->hdr_account_lockout, ps, depth)) + return False; + if (!smb_io_unihdr("hdr_unknown2", &info->hdr_unknown2, ps, depth)) + return False; + if (!smb_io_unihdr("hdr_unknown3", &info->hdr_unknown3, ps, depth)) + return False; + if (!smb_io_unihdr("hdr_unknown4", &info->hdr_unknown4, ps, depth)) + return False; + if (!prs_uint32("logon_chgpass", ps, depth, &info->logon_chgpass)) + return False; + if (!prs_uint32("unknown6", ps, depth, &info->unknown6)) + return False; + if (!prs_uint32("unknown7", ps, depth, &info->unknown7)) + return False; + if (!prs_uint32("unknown8", ps, depth, &info->unknown8)) + return False; if (!smb_io_unistr2("uni_dom_name", &info->uni_dom_name, info->hdr_dom_name.buffer, ps, depth)) @@ -1957,9 +1968,20 @@ static BOOL net_io_sam_domain_info(const char *desc, SAM_DOMAIN_INFO * info, if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, info->hdr_sec_desc.buffer, ps, depth)) return False; - if (!smb_io_unistr2("buf_unknown", &info->buf_unknown, - info->hdr_unknown.buffer, ps, depth)) - return False; + + if (!smb_io_account_lockout_str("account_lockout", &info->account_lockout, + info->hdr_account_lockout.buffer, ps, depth)) + return False; + + if (!smb_io_unistr2("buf_unknown2", &info->buf_unknown2, + info->hdr_unknown2.buffer, ps, depth)) + return False; + if (!smb_io_unistr2("buf_unknown3", &info->buf_unknown3, + info->hdr_unknown3.buffer, ps, depth)) + return False; + if (!smb_io_unistr2("buf_unknown4", &info->buf_unknown4, + info->hdr_unknown4.buffer, ps, depth)) + return False; return True; } diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index d7af528ff1..3c98ec9e71 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -36,6 +36,45 @@ static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g) d_printf("\n"); } + +static const char *display_time(NTTIME *nttime) +{ + static fstring string; + + float high; + float low; + int sec; + int days, hours, mins, secs; + int offset = 1; + + if (nttime->high==0 && nttime->low==0) + return "Now"; + + if (nttime->high==0x80000000 && nttime->low==0) + return "Never"; + + high = 65536; + high = high/10000; + high = high*65536; + high = high/1000; + high = high * (~nttime->high); + + low = ~nttime->low; + low = low/(1000*1000*10); + + sec=high+low; + sec+=offset; + + days=sec/(60*60*24); + hours=(sec - (days*60*60*24)) / (60*60); + mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60; + secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60); + + fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs); + return (string); +} + + static void display_alias_info(uint32 rid, SAM_ALIAS_INFO *a) { d_printf("Alias '%s' ", unistr2_static(&a->uni_als_name)); @@ -81,7 +120,25 @@ static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a) static void display_domain_info(SAM_DOMAIN_INFO *a) { + time_t u_logout; + + u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff); + d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name)); + + d_printf("Minimal Password Length: %d\n", a->min_pwd_len); + d_printf("Password History Length: %d\n", a->pwd_history_len); + + d_printf("Force Logoff: %d\n", (int)u_logout); + + d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age)); + d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age)); + + d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration)); + d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count)); + + d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout); + d_printf("User must logon to change password: %d\n", a->logon_chgpass); } static void display_group_info(uint32 rid, SAM_GROUP_INFO *a) @@ -897,6 +954,58 @@ fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid) return NT_STATUS_OK; } +static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta) +{ + time_t u_max_age, u_min_age, u_logout, u_lockoutreset, u_lockouttime; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + pstring domname; + + u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age); + u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age); + u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff); + u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count); + u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration); + + unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1); + + /* we don't handle BUILTIN account policies */ + if (!strequal(domname, get_global_sam_name())) { + printf("skipping SAM_DOMAIN_INFO delta for '%s' (is not my domain)\n", domname); + return NT_STATUS_OK; + } + + + if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len)) + return nt_status; + + if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len)) + return nt_status; + + if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age)) + return nt_status; + + if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age)) + return nt_status; + + if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout)) + return nt_status; + + if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout)) + return nt_status; + + if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60)) + return nt_status; + + if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime/60)) + return nt_status; + + if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass)) + return nt_status; + + return NT_STATUS_OK; +} + + static void fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, DOM_SID dom_sid) @@ -922,10 +1031,11 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, fetch_alias_mem(hdr_delta->target_rid, &delta->als_mem_info, dom_sid); break; - /* The following types are recognised but not handled */ case SAM_DELTA_DOMAIN_INFO: - d_printf("SAM_DELTA_DOMAIN_INFO not handled\n"); + fetch_domain_info(hdr_delta->target_rid, + &delta->domain_info); break; + /* The following types are recognised but not handled */ case SAM_DELTA_RENAME_GROUP: d_printf("SAM_DELTA_RENAME_GROUP not handled\n"); break; -- cgit