diff options
-rw-r--r-- | source3/include/rpc_misc.h | 19 | ||||
-rw-r--r-- | source3/libsmb/cli_netlogon.c | 145 | ||||
-rw-r--r-- | source3/rpc_parse/parse_misc.c | 64 | ||||
-rw-r--r-- | source3/rpc_parse/parse_net.c | 834 | ||||
-rw-r--r-- | source3/rpcclient/cmd_netlogon.c | 220 |
5 files changed, 1276 insertions, 6 deletions
diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index 428db938de..558c28459e 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -348,5 +348,24 @@ typedef struct uint64_s uint32 high; } UINT64_S; +/* BUFHDR2 - another buffer header, with info level */ +typedef struct bufhdr2_info +{ + uint32 info_level; + uint32 length; /* uint8 chars */ + uint32 buffer; + +} +BUFHDR2; + +/* BUFFER4 - simple length and buffer */ +typedef struct buffer4_info +{ + uint32 buf_len; + uint8 buffer[MAX_BUFFERLEN]; + +} +BUFFER4; + #endif /* _RPC_MISC_H */ diff --git a/source3/libsmb/cli_netlogon.c b/source3/libsmb/cli_netlogon.c index 63a2f4a5b1..b608398aa3 100644 --- a/source3/libsmb/cli_netlogon.c +++ b/source3/libsmb/cli_netlogon.c @@ -34,13 +34,13 @@ struct cli_state *cli_netlogon_initialise(struct cli_state *cli, /* Logon Control 2 */ -uint32 cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx, - uint32 query_level) +NTSTATUS cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 query_level) { prs_struct qbuf, rbuf; NET_Q_LOGON_CTRL2 q; NET_R_LOGON_CTRL2 r; - uint32 result = NT_STATUS_UNSUCCESSFUL; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -77,3 +77,142 @@ uint32 cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } + +/**************************************************************************** +Generate the next creds to use. Yuck - this is a cut&paste from another +file. They should be combined at some stage. )-: +****************************************************************************/ + +static void gen_next_creds( struct cli_state *cli, DOM_CRED *new_clnt_cred) +{ + /* + * Create the new client credentials. + */ + + cli->clnt_cred.timestamp.time = time(NULL); + + memcpy(new_clnt_cred, &cli->clnt_cred, sizeof(*new_clnt_cred)); + + /* Calculate the new credentials. */ + cred_create(cli->sess_key, &(cli->clnt_cred.challenge), + new_clnt_cred->timestamp, &(new_clnt_cred->challenge)); + +} + +/* Sam synchronisation */ + +NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 database_id, uint32 *num_deltas, + SAM_DELTA_HDR **hdr_deltas, + SAM_DELTA_CTR **deltas) +{ + prs_struct qbuf, rbuf; + NET_Q_SAM_SYNC q; + NET_R_SAM_SYNC r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED clnt_creds; + char sess_key[16]; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + gen_next_creds(cli, &clnt_creds); + + init_net_q_sam_sync(&q, cli->srv_name_slash, cli->clnt_name_slash + 2, + &clnt_creds, database_id); + + /* Marshall data and send request */ + + if (!net_io_q_sam_sync("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_SAM_SYNC, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!net_io_r_sam_sync("", sess_key, &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Return results */ + + result = r.status; + *num_deltas = r.num_deltas2; + *hdr_deltas = r.hdr_deltas; + *deltas = r.deltas; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Sam synchronisation */ + +NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 database_id, UINT64_S seqnum, + uint32 *num_deltas, + SAM_DELTA_HDR **hdr_deltas, + SAM_DELTA_CTR **deltas) +{ + prs_struct qbuf, rbuf; + NET_Q_SAM_DELTAS q; + NET_R_SAM_DELTAS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED clnt_creds; + char sess_key[16]; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + gen_next_creds(cli, &clnt_creds); + + init_net_q_sam_deltas(&q, cli->srv_name_slash, + cli->clnt_name_slash + 2, &clnt_creds, + database_id, seqnum); + + /* Marshall data and send request */ + + if (!net_io_q_sam_deltas("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_SAM_DELTAS, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!net_io_r_sam_deltas("", sess_key, &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Return results */ + + result = r.status; + *num_deltas = r.num_deltas2; + *hdr_deltas = r.hdr_deltas; + *deltas = r.deltas; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 1a30d3d7a1..2a6560f8ce 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -1528,4 +1528,68 @@ BOOL prs_uint64(char *name, prs_struct *ps, int depth, UINT64_S *data64) prs_uint32(name, ps, depth+1, &data64->high); } +/******************************************************************* +reads or writes a BUFHDR2 structure. +********************************************************************/ +BOOL smb_io_bufhdr2(char *desc, BUFHDR2 *hdr, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "smb_io_bufhdr2"); + depth++; + + prs_align(ps); + prs_uint32("info_level", ps, depth, &(hdr->info_level)); + prs_uint32("length ", ps, depth, &(hdr->length )); + prs_uint32("buffer ", ps, depth, &(hdr->buffer )); + + return True; +} + +/******************************************************************* +reads or writes a BUFFER4 structure. +********************************************************************/ +BOOL smb_io_buffer4(char *desc, BUFFER4 *buf4, uint32 buffer, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "smb_io_buffer4"); + depth++; + + prs_align(ps); + prs_uint32("buf_len", ps, depth, &(buf4->buf_len)); + + if (buf4->buf_len > MAX_BUFFERLEN) + { + buf4->buf_len = MAX_BUFFERLEN; + } + + prs_uint8s(True, "buffer", ps, depth, buf4->buffer, buf4->buf_len); + + return True; +} + +/******************************************************************* +creates a UNIHDR structure. +********************************************************************/ + +BOOL make_uni_hdr(UNIHDR *hdr, int len) +{ + if (hdr == NULL) + { + return False; + } + hdr->uni_str_len = 2 * len; + hdr->uni_max_len = 2 * len; + hdr->buffer = len != 0 ? 1 : 0; + + return True; +} +/******************************************************************* +creates a BUFHDR2 structure. +********************************************************************/ +BOOL make_bufhdr2(BUFHDR2 *hdr, uint32 info_level, uint32 length, uint32 buffer) +{ + hdr->info_level = info_level; + hdr->length = length; + hdr->buffer = buffer; + + return True; +} diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index e8f0c02a52..37bf6755b7 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -1589,3 +1589,837 @@ BOOL net_io_r_sam_logoff(char *desc, NET_R_SAM_LOGOFF *r_l, prs_struct *ps, int return True; } + +/******************************************************************* +makes a NET_Q_SAM_SYNC structure. +********************************************************************/ +BOOL init_net_q_sam_sync(NET_Q_SAM_SYNC * q_s, const char *srv_name, + const char *cli_name, DOM_CRED * cli_creds, + uint32 database_id) +{ + DEBUG(5, ("init_q_sam_sync\n")); + + init_unistr2(&q_s->uni_srv_name, srv_name, strlen(srv_name) + 1); + init_unistr2(&q_s->uni_cli_name, cli_name, strlen(cli_name) + 1); + + if (cli_creds) { + memcpy(&q_s->cli_creds, cli_creds, sizeof(q_s->cli_creds)); + memset(&q_s->ret_creds, 0, sizeof(q_s->ret_creds)); + } + + q_s->database_id = database_id; + q_s->restart_state = 0; + q_s->sync_context = 0; + q_s->max_size = 0xffff; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL net_io_q_sam_sync(char *desc, NET_Q_SAM_SYNC * q_s, prs_struct *ps, + int depth) +{ + prs_debug(ps, depth, desc, "net_io_q_sam_sync"); + depth++; + + smb_io_unistr2("", &(q_s->uni_srv_name), True, ps, depth); + smb_io_unistr2("", &(q_s->uni_cli_name), True, ps, depth); + + smb_io_cred("", &(q_s->cli_creds), ps, depth); + smb_io_cred("", &(q_s->ret_creds), ps, depth); + + prs_uint32("database_id ", ps, depth, &(q_s->database_id)); + prs_uint32("restart_state", ps, depth, &(q_s->restart_state)); + prs_uint32("sync_context ", ps, depth, &(q_s->sync_context)); + + prs_uint32("max_size", ps, depth, &(q_s->max_size)); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_delta_hdr(char *desc, SAM_DELTA_HDR * delta, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_delta_hdr"); + depth++; + + prs_uint16("type", ps, depth, &(delta->type)); + prs_uint16("type2", ps, depth, &(delta->type2)); + prs_uint32("target_rid", ps, depth, &(delta->target_rid)); + + prs_uint32("type3", ps, depth, &(delta->type3)); + + /* Not sure why we need this but it seems to be necessary to get + sam deltas working. */ + + if (delta->type != 0x16) + prs_uint32("ptr_delta", ps, depth, &(delta->ptr_delta)); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_delta_hdr2(char *desc, SAM_DELTA_HDR *delta, + prs_struct *ps, int depth) +{ + uint32 unk; + + prs_debug(ps, depth, desc, "net_io_sam_delta_stamp"); + depth++; + + prs_uint16("type", ps, depth, &(delta->type)); + prs_uint16("type2", ps, depth, &(delta->type2)); + prs_uint32("rid", ps, depth, &unk); + + + prs_uint32("unknown_ptr", ps, depth, &unk); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_delta_stamp(char *desc, SAM_DELTA_STAMP *info, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_delta_stamp"); + depth++; + + prs_uint32("seqnum", ps, depth, &info->seqnum); + prs_uint32("dom_mod_count_ptr", ps, depth, &info->dom_mod_count_ptr); + if (info->dom_mod_count_ptr) + prs_uint64("dom_mod_count", ps, depth, &info->dom_mod_count); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_domain_info(char *desc, SAM_DOMAIN_INFO * info, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_domain_info"); + depth++; + + smb_io_unihdr("hdr_dom_name", &(info->hdr_dom_name), ps, depth); + smb_io_unihdr("hdr_oem_info", &(info->hdr_oem_info), ps, depth); + + prs_uint64("force_logoff", ps, depth, &info->force_logoff); + prs_uint16("min_pwd_len", ps, depth, &(info->min_pwd_len)); + prs_uint16("pwd_history_len", ps, depth, &info->pwd_history_len); + prs_uint64("max_pwd_age", ps, depth, &info->max_pwd_age); + prs_uint64("min_pwd_age", ps, depth, &info->min_pwd_age); + prs_uint64("dom_mod_count", ps, depth, &info->dom_mod_count); + smb_io_time("creation_time", &info->creation_time, ps, depth); + + smb_io_bufhdr2("hdr_sec_desc", &(info->hdr_sec_desc), ps, depth); + smb_io_unihdr("hdr_unknown", &(info->hdr_unknown), ps, depth); + ps->data_offset += 40; + + smb_io_unistr2("uni_dom_name", &(info->uni_dom_name), + info->hdr_dom_name.buffer, ps, depth); + smb_io_unistr2("buf_oem_info", &(info->buf_oem_info), + info->hdr_oem_info.buffer, ps, depth); + + smb_io_buffer4("buf_sec_desc", &(info->buf_sec_desc), + info->hdr_sec_desc.buffer, ps, depth); + smb_io_unistr2("buf_unknown", &(info->buf_unknown), + info->hdr_unknown.buffer, ps, depth); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_group_info(char *desc, SAM_GROUP_INFO * info, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_group_info"); + depth++; + + smb_io_unihdr("hdr_grp_name", &(info->hdr_grp_name), ps, depth); + smb_io_gid("gid", &(info->gid), ps, depth); + smb_io_unihdr("hdr_grp_desc", &(info->hdr_grp_desc), ps, depth); + smb_io_bufhdr2("hdr_sec_desc", &(info->hdr_sec_desc), ps, depth); + ps->data_offset += 48; + + smb_io_unistr2("uni_grp_name", &(info->uni_grp_name), + info->hdr_grp_name.buffer, ps, depth); + smb_io_unistr2("uni_grp_desc", &(info->uni_grp_desc), + info->hdr_grp_desc.buffer, ps, depth); + smb_io_buffer4("buf_sec_desc", &(info->buf_sec_desc), + info->hdr_sec_desc.buffer, ps, depth); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_passwd_info(char *desc, SAM_PWD * pwd, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_passwd_info"); + depth++; + + prs_uint32("unk_0 ", ps, depth, &(pwd->unk_0)); + + smb_io_unihdr("hdr_lm_pwd", &(pwd->hdr_lm_pwd), ps, depth); + prs_uint8s(False, "buf_lm_pwd", ps, depth, pwd->buf_lm_pwd, 16); + + smb_io_unihdr("hdr_nt_pwd", &(pwd->hdr_nt_pwd), ps, depth); + prs_uint8s(False, "buf_nt_pwd", ps, depth, pwd->buf_nt_pwd, 16); + + smb_io_unihdr("", &(pwd->hdr_empty_lm), ps, depth); + smb_io_unihdr("", &(pwd->hdr_empty_nt), ps, depth); + + return True; +} + +/******************************************************************* +makes a SAM_ACCOUNT_INFO structure. +********************************************************************/ +BOOL make_sam_account_info(SAM_ACCOUNT_INFO * info, + const UNISTR2 *user_name, + const UNISTR2 *full_name, + uint32 user_rid, uint32 group_rid, + const UNISTR2 *home_dir, + const UNISTR2 *dir_drive, + const UNISTR2 *log_scr, + const UNISTR2 *desc, + uint32 acb_info, + const UNISTR2 *prof_path, + const UNISTR2 *wkstas, + const UNISTR2 *unk_str, const UNISTR2 *mung_dial) +{ + int len_user_name = user_name != NULL ? user_name->uni_str_len : 0; + int len_full_name = full_name != NULL ? full_name->uni_str_len : 0; + int len_home_dir = home_dir != NULL ? home_dir->uni_str_len : 0; + int len_dir_drive = dir_drive != NULL ? dir_drive->uni_str_len : 0; + int len_logon_script = log_scr != NULL ? log_scr->uni_str_len : 0; + int len_profile_path = prof_path != NULL ? prof_path->uni_str_len : 0; + int len_description = desc != NULL ? desc->uni_str_len : 0; + int len_workstations = wkstas != NULL ? wkstas->uni_str_len : 0; + int len_unknown_str = unk_str != NULL ? unk_str->uni_str_len : 0; + int len_munged_dial = mung_dial != NULL ? mung_dial->uni_str_len : 0; + + DEBUG(5, ("make_sam_account_info\n")); + + make_uni_hdr(&(info->hdr_acct_name), len_user_name); + make_uni_hdr(&(info->hdr_full_name), len_full_name); + make_uni_hdr(&(info->hdr_home_dir), len_home_dir); + make_uni_hdr(&(info->hdr_dir_drive), len_dir_drive); + make_uni_hdr(&(info->hdr_logon_script), len_logon_script); + make_uni_hdr(&(info->hdr_profile), len_profile_path); + make_uni_hdr(&(info->hdr_acct_desc), len_description); + make_uni_hdr(&(info->hdr_workstations), len_workstations); + make_uni_hdr(&(info->hdr_comment), len_unknown_str); + make_uni_hdr(&(info->hdr_parameters), len_munged_dial); + + /* not present */ + make_bufhdr2(&(info->hdr_sec_desc), 0, 0, 0); + + info->user_rid = user_rid; + info->group_rid = group_rid; + + init_nt_time(&(info->logon_time)); + init_nt_time(&(info->logoff_time)); + init_nt_time(&(info->pwd_last_set_time)); + init_nt_time(&(info->acct_expiry_time)); + + info->logon_divs = 0xA8; + info->ptr_logon_hrs = 0; /* Don't care right now */ + + info->bad_pwd_count = 0; + info->logon_count = 0; + info->acb_info = acb_info; + info->nt_pwd_present = 0; + info->lm_pwd_present = 0; + info->pwd_expired = 0; + info->country = 0; + info->codepage = 0; + + info->unknown1 = 0x4EC; + info->unknown2 = 0; + + copy_unistr2(&(info->uni_acct_name), user_name); + copy_unistr2(&(info->uni_full_name), full_name); + copy_unistr2(&(info->uni_home_dir), home_dir); + copy_unistr2(&(info->uni_dir_drive), dir_drive); + copy_unistr2(&(info->uni_logon_script), log_scr); + copy_unistr2(&(info->uni_profile), prof_path); + copy_unistr2(&(info->uni_acct_desc), desc); + copy_unistr2(&(info->uni_workstations), wkstas); + copy_unistr2(&(info->uni_comment), unk_str); + copy_unistr2(&(info->uni_parameters), mung_dial); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_account_info(char *desc, uint8 sess_key[16], + SAM_ACCOUNT_INFO * info, prs_struct *ps, + int depth) +{ + BUFHDR2 hdr_priv_data; + uint32 i; + + prs_debug(ps, depth, desc, "net_io_sam_account_info"); + depth++; + + smb_io_unihdr("hdr_acct_name", &(info->hdr_acct_name), ps, depth); + smb_io_unihdr("hdr_full_name", &(info->hdr_full_name), ps, depth); + + prs_uint32("user_rid ", ps, depth, &(info->user_rid)); + prs_uint32("group_rid", ps, depth, &(info->group_rid)); + + smb_io_unihdr("hdr_home_dir ", &(info->hdr_home_dir), ps, depth); + smb_io_unihdr("hdr_dir_drive", &(info->hdr_dir_drive), ps, depth); + smb_io_unihdr("hdr_logon_script", &(info->hdr_logon_script), ps, + depth); + smb_io_unihdr("hdr_acct_desc", &(info->hdr_acct_desc), ps, depth); + smb_io_unihdr("hdr_workstations", &(info->hdr_workstations), ps, + depth); + + smb_io_time("logon_time", &(info->logon_time), ps, depth); + smb_io_time("logoff_time", &(info->logoff_time), ps, depth); + + prs_uint32("logon_divs ", ps, depth, &(info->logon_divs)); + prs_uint32("ptr_logon_hrs", ps, depth, &(info->ptr_logon_hrs)); + + prs_uint16("bad_pwd_count", ps, depth, &(info->bad_pwd_count)); + prs_uint16("logon_count", ps, depth, &(info->logon_count)); + smb_io_time("pwd_last_set_time", &(info->pwd_last_set_time), ps, + depth); + smb_io_time("acct_expiry_time", &(info->acct_expiry_time), ps, depth); + + prs_uint32("acb_info", ps, depth, &(info->acb_info)); + prs_uint8s(False, "nt_pwd", ps, depth, info->nt_pwd, 16); + prs_uint8s(False, "lm_pwd", ps, depth, info->lm_pwd, 16); + prs_uint8("lm_pwd_present", ps, depth, &(info->lm_pwd_present)); + prs_uint8("nt_pwd_present", ps, depth, &(info->nt_pwd_present)); + prs_uint8("pwd_expired", ps, depth, &(info->pwd_expired)); + + smb_io_unihdr("hdr_comment", &(info->hdr_comment), ps, depth); + smb_io_unihdr("hdr_parameters", &(info->hdr_parameters), ps, depth); + prs_uint16("country", ps, depth, &(info->country)); + prs_uint16("codepage", ps, depth, &(info->codepage)); + + smb_io_bufhdr2("hdr_priv_data", &(hdr_priv_data), ps, depth); + smb_io_bufhdr2("hdr_sec_desc", &(info->hdr_sec_desc), ps, depth); + smb_io_unihdr("hdr_profile", &(info->hdr_profile), ps, depth); + + for (i = 0; i < 3; i++) + { + smb_io_unihdr("hdr_reserved", &(info->hdr_reserved[i]), ps, + depth); + } + + for (i = 0; i < 4; i++) + { + prs_uint32("dw_reserved", ps, depth, &(info->dw_reserved[i])); + } + + smb_io_unistr2("uni_acct_name", &(info->uni_acct_name), + info->hdr_acct_name.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_full_name", &(info->uni_full_name), + info->hdr_full_name.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_home_dir ", &(info->uni_home_dir), + info->hdr_home_dir.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_dir_drive", &(info->uni_dir_drive), + info->hdr_dir_drive.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_logon_script", &(info->uni_logon_script), + info->hdr_logon_script.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_acct_desc", &(info->uni_acct_desc), + info->hdr_acct_desc.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_workstations", &(info->uni_workstations), + info->hdr_workstations.buffer, ps, depth); + prs_align(ps); + + prs_uint32("unknown1", ps, depth, &(info->unknown1)); + prs_uint32("unknown2", ps, depth, &(info->unknown2)); + + smb_io_buffer4("buf_logon_hrs", &(info->buf_logon_hrs), + info->ptr_logon_hrs, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_comment", &(info->uni_comment), + info->hdr_comment.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_parameters", &(info->uni_parameters), + info->hdr_parameters.buffer, ps, depth); + prs_align(ps); + if (hdr_priv_data.buffer != 0) + { + int old_offset = 0; + uint32 len = 0x44; + prs_uint32("pwd_len", ps, depth, &len); + old_offset = ps->data_offset; + if (len == 0x44) + { + if (ps->io) + { + /* reading */ +// FIXME prs_hash1(ps, ps->offset, sess_key); + } + net_io_sam_passwd_info("pass", &(info->pass), ps, + depth); + if (!ps->io) + { + /* writing */ +// FIXME TOO prs_hash1(ps, old_offset, sess_key); + } + } + ps->data_offset = old_offset + len; + } + smb_io_buffer4("buf_sec_desc", &(info->buf_sec_desc), + info->hdr_sec_desc.buffer, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_profile", &(info->uni_profile), + info->hdr_profile.buffer, ps, depth); + prs_align(ps); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_group_mem_info(char *desc, SAM_GROUP_MEM_INFO * info, + prs_struct *ps, int depth) +{ + uint32 i; + fstring tmp; + + prs_debug(ps, depth, desc, "net_io_sam_group_mem_info"); + depth++; + + prs_align(ps); + prs_uint32("ptr_rids ", ps, depth, &(info->ptr_rids)); + prs_uint32("ptr_attribs", ps, depth, &(info->ptr_attribs)); + prs_uint32("num_members", ps, depth, &(info->num_members)); + ps->data_offset += 16; + + if (info->ptr_rids != 0) + { + prs_uint32("num_members2", ps, depth, &(info->num_members2)); + if (info->num_members2 != info->num_members) + { + /* RPC fault */ + return False; + } + + info->rids = talloc(ps->mem_ctx, sizeof(uint32) * + info->num_members2); + + if (info->rids == NULL) { + DEBUG(0, ("out of memory allocating %d rids\n", + info->num_members2)); + return False; + } + + for (i = 0; i < info->num_members2; i++) + { + slprintf(tmp, sizeof(tmp) - 1, "rids[%02d]", i); + prs_uint32(tmp, ps, depth, &(info->rids[i])); + } + } + + if (info->ptr_attribs != 0) + { + prs_uint32("num_members3", ps, depth, &(info->num_members3)); + if (info->num_members3 != info->num_members) + { + /* RPC fault */ + return False; + } + + info->attribs = talloc(ps->mem_ctx, sizeof(uint32) * + info->num_members3); + + if (info->attribs == NULL) { + DEBUG(0, ("out of memory allocating %d attribs\n", + info->num_members3)); + return False; + } + + for (i = 0; i < info->num_members3; i++) + { + slprintf(tmp, sizeof(tmp) - 1, "attribs[%02d]", i); + prs_uint32(tmp, ps, depth, &(info->attribs[i])); + } + } + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_alias_info(char *desc, SAM_ALIAS_INFO * info, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_alias_info"); + depth++; + + smb_io_unihdr("hdr_als_name", &(info->hdr_als_name), ps, depth); + prs_uint32("als_rid", ps, depth, &(info->als_rid)); + smb_io_bufhdr2("hdr_sec_desc", &(info->hdr_sec_desc), ps, depth); + smb_io_unihdr("hdr_als_desc", &(info->hdr_als_desc), ps, depth); + ps->data_offset += 40; + + smb_io_unistr2("uni_als_name", &(info->uni_als_name), + info->hdr_als_name.buffer, ps, depth); + smb_io_buffer4("buf_sec_desc", &(info->buf_sec_desc), + info->hdr_sec_desc.buffer, ps, depth); + smb_io_unistr2("uni_als_desc", &(info->uni_als_desc), + info->hdr_als_name.buffer, ps, depth); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_alias_mem_info(char *desc, SAM_ALIAS_MEM_INFO * info, + prs_struct *ps, int depth) +{ + uint32 i; + fstring tmp; + + prs_debug(ps, depth, desc, "net_io_sam_alias_mem_info"); + depth++; + + prs_align(ps); + prs_uint32("num_members", ps, depth, &(info->num_members)); + prs_uint32("ptr_members", ps, depth, &(info->ptr_members)); + ps->data_offset += 16; + + if (info->ptr_members != 0) + { + prs_uint32("num_sids", ps, depth, &(info->num_sids)); + if (info->num_sids != info->num_members) + { + /* RPC fault */ + return False; + } + + info->ptr_sids = talloc(ps->mem_ctx, sizeof(uint32) * + info->num_sids); + + if (info->ptr_sids == NULL) { + DEBUG(0, ("out of memory allocating %d ptr_sids\n", + info->num_sids)); + return False; + } + + for (i = 0; i < info->num_sids; i++) + { + slprintf(tmp, sizeof(tmp) - 1, "ptr_sids[%02d]", i); + prs_uint32(tmp, ps, depth, &(info->ptr_sids[i])); + } + + info->sids = talloc(ps->mem_ctx, sizeof(DOM_SID2) * + info->num_sids); + + if (info->sids == NULL) { + DEBUG(0, ("error allocating %d sids\n", + info->num_sids)); + return False; + } + + for (i = 0; i < info->num_sids; i++) + { + if (info->ptr_sids[i] != 0) + { + slprintf(tmp, sizeof(tmp) - 1, "sids[%02d]", + i); + smb_io_dom_sid2(tmp, &(info->sids[i]), ps, + depth); + } + } + } + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +static BOOL net_io_sam_delta_ctr(char *desc, uint8 sess_key[16], + SAM_DELTA_CTR * delta, uint16 type, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "net_io_sam_delta_ctr"); + depth++; + + switch (type) + { + /* Seen in sam deltas */ + + case SAM_DELTA_SAM_STAMP: + { + net_io_sam_delta_stamp("", &delta->stamp, + ps, depth); + break; + } + + case SAM_DELTA_DOMAIN_INFO: + { + net_io_sam_domain_info("", &delta->domain_info, + ps, depth); + break; + } + case SAM_DELTA_GROUP_INFO: + { + net_io_sam_group_info("", &delta->group_info, + ps, depth); + break; + } + case SAM_DELTA_ACCOUNT_INFO: + { + net_io_sam_account_info("", sess_key, + &delta->account_info, + ps, depth); + break; + } + case SAM_DELTA_GROUP_MEM: + { + net_io_sam_group_mem_info("", &delta->grp_mem_info, + ps, depth); + break; + } + case SAM_DELTA_ALIAS_INFO: + { + net_io_sam_alias_info("", &delta->alias_info, + ps, depth); + break; + } + case SAM_DELTA_ALIAS_MEM: + { + net_io_sam_alias_mem_info("", &delta->als_mem_info, + ps, depth); + break; + } + default: + { + DEBUG(0, + ("Replication error: Unknown delta type 0x%x\n", + type)); + break; + } + } + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL net_io_r_sam_sync(char *desc, uint8 sess_key[16], + NET_R_SAM_SYNC * r_s, prs_struct *ps, int depth) +{ + uint32 i; + + prs_debug(ps, depth, desc, "net_io_r_sam_sync"); + depth++; + + smb_io_cred("srv_creds", &(r_s->srv_creds), ps, depth); + prs_uint32("sync_context", ps, depth, &(r_s->sync_context)); + + prs_uint32("ptr_deltas", ps, depth, &(r_s->ptr_deltas)); + if (r_s->ptr_deltas != 0) + { + prs_uint32("num_deltas ", ps, depth, &(r_s->num_deltas)); + prs_uint32("ptr_deltas2", ps, depth, &(r_s->ptr_deltas2)); + if (r_s->ptr_deltas2 != 0) + { + prs_uint32("num_deltas2", ps, depth, + &(r_s->num_deltas2)); + + if (r_s->num_deltas2 != r_s->num_deltas) + { + /* RPC fault */ + return False; + } + + if (r_s->num_deltas2 > 0) { + r_s->hdr_deltas = (SAM_DELTA_HDR *) + talloc(ps->mem_ctx, r_s->num_deltas2 * + sizeof(SAM_DELTA_HDR)); + + if (r_s->hdr_deltas == NULL) { + DEBUG(0, ("error tallocating memory " + "for %d delta headers\n", + r_s->num_deltas2)); + return False; + } + } + + for (i = 0; i < r_s->num_deltas2; i++) + { + net_io_sam_delta_hdr("", &r_s->hdr_deltas[i], + ps, depth); + } + + if (r_s->num_deltas2 > 0) { + r_s->deltas = (SAM_DELTA_CTR *) + talloc(ps->mem_ctx, r_s->num_deltas2 * + sizeof(SAM_DELTA_CTR)); + + if (r_s->deltas == NULL) { + DEBUG(0, ("error tallocating memory " + "for %d deltas\n", + r_s->num_deltas2)); + return False; + } + } + + for (i = 0; i < r_s->num_deltas2; i++) + { + net_io_sam_delta_ctr("", sess_key, + &r_s->deltas[i], + r_s->hdr_deltas[i].type3, + ps, depth); + } + } + } + + prs_align(ps); + prs_uint32("status", ps, depth, &(r_s->status)); + + return True; +} + +/******************************************************************* +makes a NET_Q_SAM_DELTAS structure. +********************************************************************/ +BOOL init_net_q_sam_deltas(NET_Q_SAM_DELTAS *q_s, const char *srv_name, + const char *cli_name, DOM_CRED *cli_creds, + uint32 database_id, UINT64_S dom_mod_count) +{ + DEBUG(5, ("init_net_q_sam_deltas\n")); + + init_unistr2(&q_s->uni_srv_name, srv_name, strlen(srv_name) + 1); + init_unistr2(&q_s->uni_cli_name, cli_name, strlen(cli_name) + 1); + + memcpy(&q_s->cli_creds, cli_creds, sizeof(q_s->cli_creds)); + memset(&q_s->ret_creds, 0, sizeof(q_s->ret_creds)); + + q_s->database_id = database_id; + q_s->dom_mod_count.low = dom_mod_count.low; + q_s->dom_mod_count.high = dom_mod_count.high; + q_s->max_size = 0xffff; + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL net_io_q_sam_deltas(char *desc, NET_Q_SAM_DELTAS *q_s, prs_struct *ps, + int depth) +{ + prs_debug(ps, depth, desc, "net_io_q_sam_deltas"); + depth++; + + smb_io_unistr2("", &q_s->uni_srv_name, True, ps, depth); + smb_io_unistr2("", &q_s->uni_cli_name, True, ps, depth); + + smb_io_cred("", &q_s->cli_creds, ps, depth); + smb_io_cred("", &q_s->ret_creds, ps, depth); + + prs_uint32("database_id ", ps, depth, &q_s->database_id); + prs_uint64("dom_mod_count", ps, depth, &q_s->dom_mod_count); + prs_uint32("max_size", ps, depth, &q_s->max_size); + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL net_io_r_sam_deltas(char *desc, uint8 sess_key[16], + NET_R_SAM_DELTAS *r_s, prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "net_io_r_sam_deltas"); + depth++; + + smb_io_cred("srv_creds", &r_s->srv_creds, ps, depth); + prs_uint64("dom_mod_count", ps, depth, &r_s->dom_mod_count); + + prs_uint32("ptr_deltas", ps, depth, &r_s->ptr_deltas); + prs_uint32("num_deltas", ps, depth, &r_s->num_deltas); + prs_uint32("ptr_deltas2", ps, depth, &r_s->num_deltas2); + + if (r_s->num_deltas2 != 0) + { + prs_uint32("num_deltas2 ", ps, depth, &(r_s->num_deltas2)); + + if (r_s->ptr_deltas != 0) + { + if (r_s->num_deltas > 0) { + r_s->hdr_deltas = (SAM_DELTA_HDR *) + talloc(ps->mem_ctx, r_s->num_deltas * + sizeof(SAM_DELTA_HDR)); + if (r_s->hdr_deltas == NULL) { + DEBUG(0, ("error tallocating memory " + "for %d delta headers\n", + r_s->num_deltas)); + return False; + } + } + + for (i = 0; i < r_s->num_deltas; i++) + { + net_io_sam_delta_hdr("", &r_s->hdr_deltas[i], + ps, depth); + } + + if (r_s->num_deltas > 0) { + r_s->deltas = (SAM_DELTA_CTR *) + talloc(ps->mem_ctx, r_s->num_deltas * + sizeof(SAM_DELTA_CTR)); + + if (r_s->deltas == NULL) { + DEBUG(0, ("error tallocating memory " + "for %d deltas\n", + r_s->num_deltas)); + return False; + } + } + + for (i = 0; i < r_s->num_deltas; i++) + { + net_io_sam_delta_ctr("", sess_key, + &r_s->deltas[i], + r_s->hdr_deltas[i].type2, + ps, depth); + } + } + } + + prs_align(ps); + prs_uint32("status", ps, depth, &(r_s->status)); + + return True; +} diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 410fd7fb0a..1b49387558 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -81,7 +81,7 @@ static uint32 cmd_netlogon_logon_ctrl(struct cli_state *cli, int argc, /* Initialise RPC connection */ if (!cli_nt_session_open (cli, PIPE_NETLOGON)) { - DEBUG(0, ("Could not initialize srvsvc pipe!\n")); + DEBUG(0, ("Could not initialize netlogon pipe!\n")); goto done; } @@ -98,14 +98,228 @@ static uint32 cmd_netlogon_logon_ctrl(struct cli_state *cli, int argc, return result; } +/* Display sam synchronisation information */ + +static void display_sam_sync(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas, + SAM_DELTA_CTR *deltas) +{ + fstring name; + uint32 i, j; + + for (i = 0; i < num_deltas; i++) { + switch (hdr_deltas[i].type) { + case SAM_DELTA_DOMAIN_INFO: + unistr2_to_ascii(name, + &deltas[i].domain_info.uni_dom_name, + sizeof(name) - 1); + DEBUG(0, ("Domain: %s\n", name)); + break; + case SAM_DELTA_GROUP_INFO: + unistr2_to_ascii(name, + &deltas[i].group_info.uni_grp_name, + sizeof(name) - 1); + DEBUG(0, ("Group: %s\n", name)); + break; + case SAM_DELTA_ACCOUNT_INFO: + unistr2_to_ascii(name, + &deltas[i].account_info.uni_acct_name, + sizeof(name) - 1); + DEBUG(0, ("Account: %s\n", name)); + break; + case SAM_DELTA_ALIAS_INFO: + unistr2_to_ascii(name, + &deltas[i].alias_info.uni_als_name, + sizeof(name) - 1); + DEBUG(0, ("Alias: %s\n", name)); + break; + case SAM_DELTA_ALIAS_MEM: { + SAM_ALIAS_MEM_INFO *alias = &deltas[i].als_mem_info; + + for (j = 0; j < alias->num_members; j++) { + fstring sid_str; + + sid_to_string(sid_str, &alias->sids[j].sid); + + DEBUG(0, ("%s\n", sid_str)); + } + break; + } + case SAM_DELTA_GROUP_MEM: { + SAM_GROUP_MEM_INFO *group = &deltas[i].grp_mem_info; + + for (j = 0; j < group->num_members; j++) + DEBUG(0, ("rid 0x%x, attrib 0x%08x\n", + group->rids[j], group->attribs[j])); + break; + } + case SAM_DELTA_SAM_STAMP: { + SAM_DELTA_STAMP *stamp = &deltas[i].stamp; + + DEBUG(0, ("sam sequence update: 0x%04x\n", + stamp->seqnum)); + break; + } + default: + DEBUG(0, ("unknown delta type 0x%02x\n", + hdr_deltas[i].type)); + break; + } + } +} + +/* Perform sam synchronisation */ + +static uint32 cmd_netlogon_sam_sync(struct cli_state *cli, int argc, + char **argv) +{ + uint32 result = NT_STATUS_UNSUCCESSFUL; + unsigned char trust_passwd[16]; + TALLOC_CTX *mem_ctx; + uint32 database_id = 0, num_deltas; + SAM_DELTA_HDR *hdr_deltas; + SAM_DELTA_CTR *deltas; + + if (argc > 2) { + printf("Usage: %s [database_id]\n", argv[0]); + return 0; + } + + if (argc == 2) + database_id = atoi(argv[1]); + + if (!secrets_init()) { + DEBUG(0, ("Unable to initialise secrets database\n")); + return result; + } + + if (!(mem_ctx = talloc_init())) { + DEBUG(0,("talloc_init failed\n")); + return result; + } + + /* Initialise RPC connection */ + + if (!cli_nt_session_open (cli, PIPE_NETLOGON)) { + DEBUG(0, ("Could not initialize netlogon pipe!\n")); + goto done; + } + + /* Initialise session credentials */ + + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, + NULL)) { + DEBUG(0, ("could not fetch trust account password\n")); + goto done; + } + + if (!cli_nt_setup_creds(cli, trust_passwd)) { + DEBUG(0, ("Error initialising session creds\n")); + goto done; + } + + /* Synchronise sam database */ + + if ((result = cli_netlogon_sam_sync(cli, mem_ctx, database_id, + &num_deltas, &hdr_deltas, &deltas)) + != NT_STATUS_OK) { + goto done; + } + + /* Display results */ + + display_sam_sync(num_deltas, hdr_deltas, deltas); + + done: + cli_nt_session_close(cli); + talloc_destroy(mem_ctx); + + return result; +} + +/* Perform sam delta synchronisation */ + +static uint32 cmd_netlogon_sam_deltas(struct cli_state *cli, int argc, + char **argv) +{ + uint32 result = NT_STATUS_UNSUCCESSFUL; + unsigned char trust_passwd[16]; + TALLOC_CTX *mem_ctx = NULL; + uint32 database_id, num_deltas, tmp; + SAM_DELTA_HDR *hdr_deltas; + SAM_DELTA_CTR *deltas; + UINT64_S seqnum; + + if (argc != 3) { + printf("Usage: %s database_id seqnum\n", argv[0]); + return 0; + } + + database_id = atoi(argv[1]); + tmp = atoi(argv[2]); + + seqnum.low = tmp & 0xffff; + seqnum.high = 0; + + if (!secrets_init()) { + DEBUG(0, ("Unable to initialise secrets database\n")); + goto done; + } + + if (!(mem_ctx = talloc_init())) { + DEBUG(0,("talloc_init failed\n")); + goto done; + } + + /* Initialise RPC connection */ + + if (!cli_nt_session_open (cli, PIPE_NETLOGON)) { + DEBUG(0, ("Could not initialize netlogon pipe!\n")); + goto done; + } + + /* Initialise session credentials */ + + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, + NULL)) { + DEBUG(0, ("could not fetch trust account password\n")); + goto done; + } + + if (!cli_nt_setup_creds(cli, trust_passwd)) { + DEBUG(0, ("Error initialising session creds\n")); + goto done; + } + + /* Synchronise sam database */ + + if ((result = cli_netlogon_sam_deltas(cli, mem_ctx, database_id, + seqnum, &num_deltas, + &hdr_deltas, &deltas)) + != NT_STATUS_OK) { + goto done; + } + + /* Display results */ + + display_sam_sync(num_deltas, hdr_deltas, deltas); + + done: + cli_nt_session_close(cli); + talloc_destroy(mem_ctx); + + return result; +} + /* List of commands exported by this module */ struct cmd_set netlogon_commands[] = { { "NETLOGON" }, - { "logonctrl2", cmd_netlogon_logon_ctrl2, "Logon Control 2", "" }, - { "logonctrl", cmd_netlogon_logon_ctrl, "Logon Control", "" }, + { "logonctrl2", cmd_netlogon_logon_ctrl2, "Logon Control 2", "" }, + { "logonctrl", cmd_netlogon_logon_ctrl, "Logon Control", "" }, + { "samsync", cmd_netlogon_sam_sync, "Sam Synchronisation", "" }, + { "samdeltas", cmd_netlogon_sam_deltas, "Query Sam Deltas", "" }, { NULL } }; |