diff options
56 files changed, 22969 insertions, 2626 deletions
diff --git a/source3/client/ntclient.c b/source3/client/ntclient.c index 54ab49e3a6..bd0d0ccd5a 100644 --- a/source3/client/ntclient.c +++ b/source3/client/ntclient.c @@ -33,13 +33,10 @@ extern pstring workgroup; #define CLIENT_TIMEOUT (30*1000) -#ifdef NTDOMAIN - - /**************************************************************************** experimental nt login. ****************************************************************************/ -BOOL do_nt_login(char *desthost, char *myhostname, +BOOL client_do_nt_login(char *desthost, char *myhostname, int Client, int cnum) { DOM_CHAL clnt_chal; @@ -351,4 +348,3 @@ BOOL do_nt_login(char *desthost, char *myhostname, return True; } -#endif /* NTDOMAIN */ diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h new file mode 100644 index 0000000000..32812aa8b1 --- /dev/null +++ b/source3/include/ntdomain.h @@ -0,0 +1,127 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */ +#define _NT_DOMAIN_H + + +/* dce/rpc support */ +#include "lib/rpc/include/rpc_dce.h" + +/* miscellaneous structures / defines */ +#include "lib/rpc/include/rpc_misc.h" + +/* different dce/rpc pipes */ +#include "lib/rpc/include/rpc_lsa.h" +#include "lib/rpc/include/rpc_netlogon.h" +#include "lib/rpc/include/rpc_reg.h" +#include "lib/rpc/include/rpc_samr.h" +#include "lib/rpc/include/rpc_srvsvc.h" +#include "lib/rpc/include/rpc_wkssvc.h" + +/* + * A bunch of stuff that was put into smb.h + * in the NTDOM branch - it didn't belong there. + */ + +typedef struct +{ + struct mem_buf *data; /* memory buffer */ + uint32 offset; /* offset currently being accessed in memory buffer */ + uint8 align; /* data alignment */ + BOOL io; /* parsing in or out of data stream */ + +} prs_struct; + +typedef struct +{ + int cnum; + int uid; + BOOL open; /* open connection */ + uint16 device_state; + fstring name; + fstring pipe_srv_name; + + prs_struct rhdr; /* output header */ + prs_struct rdata; /* output data */ + prs_struct rauth; /* output authentication verifier */ + + RPC_HDR hdr; + RPC_HDR_BA hdr_ba; + RPC_HDR_RB hdr_rb; + RPC_HDR_RR hdr_rr; + + RPC_AUTH_NTLMSSP_REQ ntlmssp_req; + RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; + + uint32 max_rdata_len; + uint32 hdr_offsets; + +} pipes_struct; + +struct acct_info +{ + fstring acct_name; /* account name */ + uint32 smb_userid; /* domain-relative RID */ +}; + +struct api_struct +{ + char *name; + uint8 opnum; + void (*fn) (int uid, prs_struct*, prs_struct*); +}; + +struct mem_desc +{ + /* array memory offsets */ + uint32 start; + uint32 end; +}; + +struct mem_buf +{ + BOOL dynamic; /* True iff data has been dynamically allocated + (and therefore can be freed) */ + char *data; + uint32 data_size; + uint32 data_used; + + uint32 margin; /* safety margin when reallocing. */ + /* this can be abused quite nicely */ + uint8 align; /* alignment of data structures (smb, dce/rpc, udp etc) */ + + struct mem_desc offset; + + struct mem_buf *next; +}; + +typedef struct +{ + uint32 rid; + char *name; + +} rid_name; + +#endif /* _NT_DOMAIN_H */ + diff --git a/source3/include/nterr.h b/source3/include/nterr.h index 92f02612db..643d93bc93 100644 --- a/source3/include/nterr.h +++ b/source3/include/nterr.h @@ -7,6 +7,7 @@ #define NT_STATUS_INVALID_INFO_CLASS (3) #define NT_STATUS_INFO_LENGTH_MISMATCH (4) #define NT_STATUS_ACCESS_VIOLATION (5) +#define STATUS_BUFFER_OVERFLOW (5) #define NT_STATUS_IN_PAGE_ERROR (6) #define NT_STATUS_PAGEFILE_QUOTA (7) #define NT_STATUS_INVALID_HANDLE (8) diff --git a/source3/include/proto.h b/source3/include/proto.h index f0591743c0..19274157c6 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -212,6 +212,651 @@ int reply_trans(char *inbuf,char *outbuf, int size, int bufsize); void interpret_coding_system(char *str); void initialize_multibyte_vectors( int client_codepage); +/*The following definitions come from lib/rpc/parse/parse_lsa.c */ + +void make_lsa_trans_name(LSA_TRANS_NAME *trn, uint32 sid_name_use, char *name, uint32 idx); +void lsa_io_trans_name(char *desc, LSA_TRANS_NAME *trn, prs_struct *ps, int depth); +void lsa_io_dom_r_ref(char *desc, DOM_R_REF *r_r, prs_struct *ps, int depth); +void make_lsa_obj_attr(LSA_OBJ_ATTR *attr, uint32 attributes, uint32 sec_qos); +void lsa_io_obj_attr(char *desc, LSA_OBJ_ATTR *attr, prs_struct *ps, int depth); +void make_q_open_pol(LSA_Q_OPEN_POL *r_q, char *server_name, + uint32 attributes, uint32 sec_qos, + uint32 desired_access); +void lsa_io_q_open_pol(char *desc, LSA_Q_OPEN_POL *r_q, prs_struct *ps, int depth); +void lsa_io_r_open_pol(char *desc, LSA_R_OPEN_POL *r_p, prs_struct *ps, int depth); +void make_q_query(LSA_Q_QUERY_INFO *q_q, POLICY_HND *hnd, uint16 info_class); +void lsa_io_q_query(char *desc, LSA_Q_QUERY_INFO *q_q, prs_struct *ps, int depth); +void lsa_io_q_enum_trust_dom(char *desc, LSA_Q_ENUM_TRUST_DOM *q_e, prs_struct *ps, int depth); +void make_r_enum_trust_dom(LSA_R_ENUM_TRUST_DOM *r_e, + uint32 enum_context, char *domain_name, char *domain_sid, + uint32 status); +void lsa_io_r_enum_trust_dom(char *desc, LSA_R_ENUM_TRUST_DOM *r_e, prs_struct *ps, int depth); +void make_lsa_q_close(LSA_Q_CLOSE *q_c, POLICY_HND *hnd); +void lsa_io_q_close(char *desc, LSA_Q_CLOSE *q_c, prs_struct *ps, int depth); +void make_lsa_r_close(LSA_R_CLOSE *q_r, POLICY_HND *hnd); +void lsa_io_r_close(char *desc, LSA_R_CLOSE *r_c, prs_struct *ps, int depth); +void lsa_io_r_query(char *desc, LSA_R_QUERY_INFO *r_q, prs_struct *ps, int depth); +void lsa_io_sid_enum(char *desc, LSA_SID_ENUM *sen, prs_struct *ps, int depth); +void lsa_io_q_lookup_sids(char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct *ps, int depth); +void lsa_io_trans_names(char *desc, LSA_TRANS_NAME_ENUM *trn, prs_struct *ps, int depth); +void lsa_io_r_lookup_sids(char *desc, LSA_R_LOOKUP_SIDS *r_s, prs_struct *ps, int depth); +void lsa_io_q_lookup_rids(char *desc, LSA_Q_LOOKUP_RIDS *q_r, prs_struct *ps, int depth); +void lsa_io_r_lookup_rids(char *desc, LSA_R_LOOKUP_RIDS *r_r, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_misc.c */ + +void smb_io_utime(char *desc, UTIME *t, prs_struct *ps, int depth); +void smb_io_time(char *desc, NTTIME *nttime, prs_struct *ps, int depth); +void smb_io_lookup_level(char *desc, LOOKUP_LEVEL *level, prs_struct *ps, int depth); +uint32 get_enum_hnd(ENUM_HND *enh); +void make_enum_hnd(ENUM_HND *enh, uint32 hnd); +void smb_io_enum_hnd(char *desc, ENUM_HND *hnd, prs_struct *ps, int depth); +void make_dom_sid(DOM_SID *sid, char *str_sid); +void smb_io_dom_sid(char *desc, DOM_SID *sid, prs_struct *ps, int depth); +void make_dom_sid2(DOM_SID2 *sid, char *str_sid); +void smb_io_dom_sid2(char *desc, DOM_SID2 *sid, prs_struct *ps, int depth); +void make_str_hdr(STRHDR *hdr, int max_len, int len, uint32 buffer); +void smb_io_strhdr(char *desc, STRHDR *hdr, prs_struct *ps, int depth); +void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint32 buffer); +void smb_io_unihdr(char *desc, UNIHDR *hdr, prs_struct *ps, int depth); +void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate); +void smb_io_unihdr2(char *desc, UNIHDR2 *hdr2, prs_struct *ps, int depth); +void make_unistr(UNISTR *str, char *buf); +void smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth); +void make_uninotstr2(UNINOTSTR2 *str, char *buf, int len); +void smb_io_uninotstr2(char *desc, UNINOTSTR2 *uni2, uint32 buffer, prs_struct *ps, int depth); +void make_buf_unistr2(UNISTR2 *str, uint32 *ptr, char *buf); +void copy_unistr2(UNISTR2 *str, UNISTR2 *from); +void make_string2(STRING2 *str, char *buf, int len); +void smb_io_string2(char *desc, STRING2 *str2, uint32 buffer, prs_struct *ps, int depth); +void make_unistr2(UNISTR2 *str, char *buf, int len); +void smb_io_unistr2(char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct *ps, int depth); +void make_dom_rid2(DOM_RID2 *rid2, uint32 rid); +void smb_io_dom_rid2(char *desc, DOM_RID2 *rid2, prs_struct *ps, int depth); +void make_dom_rid3(DOM_RID3 *rid3, uint32 rid); +void smb_io_dom_rid3(char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth); +void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid); +void smb_io_dom_rid4(char *desc, DOM_RID4 *rid4, prs_struct *ps, int depth); +void make_clnt_srv(DOM_CLNT_SRV *log, char *logon_srv, char *comp_name); +void smb_io_clnt_srv(char *desc, DOM_CLNT_SRV *log, prs_struct *ps, int depth); +void make_log_info(DOM_LOG_INFO *log, char *logon_srv, char *acct_name, + uint16 sec_chan, char *comp_name); +void smb_io_log_info(char *desc, DOM_LOG_INFO *log, prs_struct *ps, int depth); +void smb_io_chal(char *desc, DOM_CHAL *chal, prs_struct *ps, int depth); +void smb_io_cred(char *desc, DOM_CRED *cred, prs_struct *ps, int depth); +void make_clnt_info2(DOM_CLNT_INFO2 *clnt, + char *logon_srv, char *comp_name, + DOM_CRED *clnt_cred); +void smb_io_clnt_info2(char *desc, DOM_CLNT_INFO2 *clnt, prs_struct *ps, int depth); +void make_clnt_info(DOM_CLNT_INFO *clnt, + char *logon_srv, char *acct_name, + uint16 sec_chan, char *comp_name, + DOM_CRED *cred); +void smb_io_clnt_info(char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, int depth); +void make_logon_id(DOM_LOGON_ID *log, uint32 log_id_low, uint32 log_id_high); +void smb_io_logon_id(char *desc, DOM_LOGON_ID *log, prs_struct *ps, int depth); +void make_arc4_owf(ARC4_OWF *hash, uint8 data[16]); +void smb_io_arc4_owf(char *desc, ARC4_OWF *hash, prs_struct *ps, int depth); +void smb_io_gid(char *desc, DOM_GID *gid, prs_struct *ps, int depth); +void smb_io_pol_hnd(char *desc, POLICY_HND *pol, prs_struct *ps, int depth); +void smb_io_dom_query_3(char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth); +void smb_io_dom_query_5(char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth); +void smb_io_dom_query(char *desc, DOM_QUERY *d_q, prs_struct *ps, int depth); +void smb_io_dom_name(char *desc, DOM_NAME *name, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_net.c */ + +void net_io_neg_flags(char *desc, NEG_FLAGS *neg, prs_struct *ps, int depth); +void make_netinfo_3(NETLOGON_INFO_3 *info, uint32 flags, uint32 logon_attempts); +void net_io_netinfo_3(char *desc, NETLOGON_INFO_3 *info, prs_struct *ps, int depth); +void make_netinfo_1(NETLOGON_INFO_1 *info, uint32 flags, uint32 pdc_status); +void net_io_netinfo_1(char *desc, NETLOGON_INFO_1 *info, prs_struct *ps, int depth); +void make_netinfo_2(NETLOGON_INFO_2 *info, uint32 flags, uint32 pdc_status, + uint32 tc_status, char *trusted_dc_name); +void net_io_netinfo_2(char *desc, NETLOGON_INFO_2 *info, prs_struct *ps, int depth); +void make_q_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, char *server_name, + uint32 function_code); +void net_io_q_logon_ctrl2(char *desc, NET_Q_LOGON_CTRL2 *q_l, prs_struct *ps, int depth); +void make_r_logon_ctrl2(NET_R_LOGON_CTRL2 *r_l, uint32 query_level, + uint32 flags, uint32 pdc_status, uint32 logon_attempts, + uint32 tc_status, char *trusted_domain_name); +void net_io_r_logon_ctrl2(char *desc, NET_R_LOGON_CTRL2 *r_l, prs_struct *ps, int depth); +void make_r_trust_dom(NET_R_TRUST_DOM_LIST *r_t, + uint32 num_doms, char *dom_name); +void net_io_r_trust_dom(char *desc, NET_R_TRUST_DOM_LIST *r_t, prs_struct *ps, int depth); +void make_q_trust_dom(NET_Q_TRUST_DOM_LIST *q_l, char *server_name, + uint32 function_code); +void net_io_q_trust_dom(char *desc, NET_Q_TRUST_DOM_LIST *q_l, prs_struct *ps, int depth); +void make_q_req_chal(NET_Q_REQ_CHAL *q_c, + char *logon_srv, char *logon_clnt, + DOM_CHAL *clnt_chal); +void net_io_q_req_chal(char *desc, NET_Q_REQ_CHAL *q_c, prs_struct *ps, int depth); +void net_io_r_req_chal(char *desc, NET_R_REQ_CHAL *r_c, prs_struct *ps, int depth); +void make_q_auth_2(NET_Q_AUTH_2 *q_a, + char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, + DOM_CHAL *clnt_chal, uint32 clnt_flgs); +void net_io_q_auth_2(char *desc, NET_Q_AUTH_2 *q_a, prs_struct *ps, int depth); +void net_io_r_auth_2(char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int depth); +void make_q_srv_pwset(NET_Q_SRV_PWSET *q_s, char sess_key[16], + char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, + DOM_CRED *cred, char nt_cypher[16]); +void net_io_q_srv_pwset(char *desc, NET_Q_SRV_PWSET *q_s, prs_struct *ps, int depth); +void net_io_r_srv_pwset(char *desc, NET_R_SRV_PWSET *r_s, prs_struct *ps, int depth); +void make_id_info1(NET_ID_INFO_1 *id, char *domain_name, + uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high, + char *user_name, char *wksta_name, + char sess_key[16], + unsigned char lm_cypher[16], unsigned char nt_cypher[16]); +void net_io_id_info1(char *desc, NET_ID_INFO_1 *id, prs_struct *ps, int depth); +void make_id_info2(NET_ID_INFO_2 *id, char *domain_name, + uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high, + char *user_name, char *wksta_name, + unsigned char lm_challenge[8], + unsigned char lm_chal_resp[24], + unsigned char nt_chal_resp[24]); +void net_io_id_info2(char *desc, NET_ID_INFO_2 *id, prs_struct *ps, int depth); +void make_sam_info(DOM_SAM_INFO *sam, + char *logon_srv, char *comp_name, DOM_CRED *clnt_cred, + DOM_CRED *rtn_cred, uint16 logon_level, + NET_ID_INFO_CTR *ctr, uint16 validation_level); +void net_io_id_info_ctr(char *desc, NET_ID_INFO_CTR *ctr, prs_struct *ps, int depth); +void smb_io_sam_info(char *desc, DOM_SAM_INFO *sam, prs_struct *ps, int depth); +void make_net_user_info3(NET_USER_INFO_3 *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *logon_script, + char *profile_path, + char *home_dir, + char *dir_drive, + + uint16 logon_count, + uint16 bad_pw_count, + + uint32 user_id, + uint32 group_id, + uint32 num_groups, + DOM_GID *gids, + uint32 user_flgs, + + char sess_key[16], + + char *logon_srv, + char *logon_dom, + + char *dom_sid, + char *other_sids); +void net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, int depth); +void net_io_q_sam_logon(char *desc, NET_Q_SAM_LOGON *q_l, prs_struct *ps, int depth); +void net_io_r_sam_logon(char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps, int depth); +void net_io_q_sam_logoff(char *desc, NET_Q_SAM_LOGOFF *q_l, prs_struct *ps, int depth); +void net_io_r_sam_logoff(char *desc, NET_R_SAM_LOGOFF *r_l, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_prs.c */ + +void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name); +void prs_init(prs_struct *ps, uint32 size, + uint8 align, uint32 margin, + BOOL io); +void prs_mem_free(prs_struct *ps); +void prs_align(prs_struct *ps); +BOOL prs_grow(prs_struct *ps); +BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8); +BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16); +BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32); +BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len); +BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len); +BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len); +BOOL prs_uninotstr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNINOTSTR2 *str); +BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str); +BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str); +BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str); +BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len); + +/*The following definitions come from lib/rpc/parse/parse_reg.c */ + +void make_reg_q_open_policy(REG_Q_OPEN_POLICY *r_q, + uint16 unknown_0, uint32 level, uint16 unknown_1); +void reg_io_q_open_policy(char *desc, REG_Q_OPEN_POLICY *r_q, prs_struct *ps, int depth); +void make_reg_r_open_policy(REG_R_OPEN_POLICY *r_r, + POLICY_HND *pol, uint32 status); +void reg_io_r_open_policy(char *desc, REG_R_OPEN_POLICY *r_r, prs_struct *ps, int depth); +void reg_io_q_close(char *desc, REG_Q_CLOSE *q_u, prs_struct *ps, int depth); +void reg_io_r_close(char *desc, REG_R_CLOSE *r_u, prs_struct *ps, int depth); +void make_reg_q_info(REG_Q_INFO *r_q, + POLICY_HND *pol, char *product_type, + NTTIME *prod_time, uint8 major_version, uint8 minor_version, + uint32 unknown); +void reg_io_q_info(char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth); +void make_reg_r_info(REG_R_INFO *r_r, + uint32 level, char *os_type, + uint32 unknown_0, uint32 unknown_1, + uint32 status); +void reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth); +void make_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q, + POLICY_HND *pol, char *name, + uint32 unknown_0, uint32 unknown_1, uint16 unknown_2); +void reg_io_q_open_entry(char *desc, REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int depth); +void make_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r, + POLICY_HND *pol, uint32 status); +void reg_io_r_open_entry(char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_rpc.c */ + +void make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 flags, + uint32 call_id, int data_len, int auth_len); +void smb_io_rpc_hdr(char *desc, RPC_HDR *rpc, prs_struct *ps, int depth); +void make_rpc_iface(RPC_IFACE *ifc, char data[16], uint32 version); +void smb_io_rpc_iface(char *desc, RPC_IFACE *ifc, prs_struct *ps, int depth); +void make_rpc_addr_str(RPC_ADDR_STR *str, char *name); +void smb_io_rpc_addr_str(char *desc, RPC_ADDR_STR *str, prs_struct *ps, int depth); +void make_rpc_hdr_bba(RPC_HDR_BBA *bba, uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid); +void smb_io_rpc_hdr_bba(char *desc, RPC_HDR_BBA *rpc, prs_struct *ps, int depth); +void make_rpc_hdr_rb(RPC_HDR_RB *rpc, + uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, + uint32 num_elements, uint16 context_id, uint8 num_syntaxes, + RPC_IFACE *abstract, RPC_IFACE *transfer); +void smb_io_rpc_hdr_rb(char *desc, RPC_HDR_RB *rpc, prs_struct *ps, int depth); +void make_rpc_results(RPC_RESULTS *res, + uint8 num_results, uint16 result, uint16 reason); +void smb_io_rpc_results(char *desc, RPC_RESULTS *res, prs_struct *ps, int depth); +void make_rpc_hdr_ba(RPC_HDR_BA *rpc, + uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, + char *pipe_addr, + uint8 num_results, uint16 result, uint16 reason, + RPC_IFACE *transfer); +void smb_io_rpc_hdr_ba(char *desc, RPC_HDR_BA *rpc, prs_struct *ps, int depth); +void make_rpc_hdr_rr(RPC_HDR_RR *hdr, uint32 data_len, uint8 opnum); +void smb_io_rpc_hdr_rr(char *desc, RPC_HDR_RR *rpc, prs_struct *ps, int depth); +void make_rpc_auth_ntlmssp_req(RPC_AUTH_NTLMSSP_REQ *req, + fstring ntlmssp_str, uint32 ntlmssp_ver, + uint32 unknown_0, fstring myname, fstring domain); +void smb_io_rpc_auth_ntlmssp_req(char *desc, RPC_AUTH_NTLMSSP_REQ *req, prs_struct *ps, int depth); +void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp, + uint8 auth_type, uint8 auth_level, uint8 stub_type_len, + fstring ntlmssp_str, uint32 ntlmssp_ver, + uint32 unknown_1, uint32 unknown_2, uint32 unknown_3, + uint8 data[16]); +void smb_io_rpc_auth_ntlmssp_resp(char *desc, RPC_AUTH_NTLMSSP_RESP *rsp, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_samr.c */ + +void make_samr_q_close_hnd(SAMR_Q_CLOSE_HND *q_c, POLICY_HND *hnd); +void samr_io_q_close_hnd(char *desc, SAMR_Q_CLOSE_HND *q_u, prs_struct *ps, int depth); +void samr_io_r_close_hnd(char *desc, SAMR_R_CLOSE_HND *r_u, prs_struct *ps, int depth); +void make_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN *q_u, + POLICY_HND *connect_pol, uint32 rid, char *sid); +void samr_io_q_open_domain(char *desc, SAMR_Q_OPEN_DOMAIN *q_u, prs_struct *ps, int depth); +void samr_io_r_open_domain(char *desc, SAMR_R_OPEN_DOMAIN *r_u, prs_struct *ps, int depth); +void make_samr_q_unknown_8(SAMR_Q_UNKNOWN_8 *q_u, + POLICY_HND *domain_pol, uint16 switch_value); +void samr_io_q_unknown_8(char *desc, SAMR_Q_UNKNOWN_8 *q_u, prs_struct *ps, int depth); +void make_samr_q_unknown_3(SAMR_Q_UNKNOWN_3 *q_u, + POLICY_HND *user_pol, uint16 switch_value); +void samr_io_q_unknown_3(char *desc, SAMR_Q_UNKNOWN_3 *q_u, prs_struct *ps, int depth); +void make_dom_sid3(DOM_SID3 *sid3, uint16 unk_0, uint16 unk_1, char *sid); +void sam_io_dom_sid3(char *desc, DOM_SID3 *sid3, prs_struct *ps, int depth); +void make_sam_sid_stuff(SAM_SID_STUFF *stf, + uint16 unknown_2, uint16 unknown_3, + uint32 unknown_4, uint16 unknown_6, uint16 unknown_7, + int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS]); +void sam_io_sid_stuff(char *desc, SAM_SID_STUFF *stf, prs_struct *ps, int depth); +void make_samr_r_unknown_3(SAMR_R_UNKNOWN_3 *r_u, + uint16 unknown_2, uint16 unknown_3, + uint32 unknown_4, uint16 unknown_6, uint16 unknown_7, + int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS], + uint32 status); +void samr_io_r_unknown_3(char *desc, SAMR_R_UNKNOWN_3 *r_u, prs_struct *ps, int depth); +void make_sam_str1(SAM_STR1 *sam, char *sam_acct, char *sam_name, char *sam_desc); +void sam_io_sam_str1(char *desc, SAM_STR1 *sam, uint32 acct_buf, uint32 name_buf, uint32 desc_buf, prs_struct *ps, int depth); +void make_sam_entry1(SAM_ENTRY1 *sam, uint32 user_idx, + uint32 len_sam_name, uint32 len_sam_full, uint32 len_sam_desc, + uint32 rid_user, uint16 acb_info); +void sam_io_sam_entry1(char *desc, SAM_ENTRY1 *sam, prs_struct *ps, int depth); +void make_sam_str2(SAM_STR2 *sam, char *sam_acct, char *sam_desc); +void sam_io_sam_str2(char *desc, SAM_STR2 *sam, uint32 acct_buf, uint32 desc_buf, prs_struct *ps, int depth); +void make_sam_entry2(SAM_ENTRY2 *sam, uint32 user_idx, + uint32 len_sam_name, uint32 len_sam_desc, + uint32 rid_user, uint16 acb_info); +void sam_io_sam_entry2(char *desc, SAM_ENTRY2 *sam, prs_struct *ps, int depth); +void make_sam_str3(SAM_STR3 *sam, char *grp_acct, char *grp_desc); +void sam_io_sam_str3(char *desc, SAM_STR3 *sam, uint32 acct_buf, uint32 desc_buf, prs_struct *ps, int depth); +void make_sam_entry3(SAM_ENTRY3 *sam, uint32 grp_idx, + uint32 len_grp_name, uint32 len_grp_desc, uint32 rid_grp); +void sam_io_sam_entry3(char *desc, SAM_ENTRY3 *sam, prs_struct *ps, int depth); +void make_sam_entry(SAM_ENTRY *sam, uint32 len_sam_name, uint32 rid); +void sam_io_sam_entry(char *desc, SAM_ENTRY *sam, prs_struct *ps, int depth); +void make_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_e, POLICY_HND *pol, + uint16 req_num_entries, uint16 unk_0, + uint16 acb_mask, uint16 unk_1, uint32 size); +void samr_io_q_enum_dom_users(char *desc, SAMR_Q_ENUM_DOM_USERS *q_e, prs_struct *ps, int depth); +void make_samr_r_enum_dom_users(SAMR_R_ENUM_DOM_USERS *r_u, + uint16 total_num_entries, uint16 unk_0, + uint32 num_sam_entries, SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], uint32 status); +void samr_io_r_enum_dom_users(char *desc, SAMR_R_ENUM_DOM_USERS *r_u, prs_struct *ps, int depth); +void make_samr_q_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_e, POLICY_HND *pol, uint32 size); +void samr_io_q_enum_dom_aliases(char *desc, SAMR_Q_ENUM_DOM_ALIASES *q_e, prs_struct *ps, int depth); +void make_samr_r_enum_dom_aliases(SAMR_R_ENUM_DOM_ALIASES *r_u, + uint32 num_sam_entries, SAM_USER_INFO_21 grps[MAX_SAM_ENTRIES], + uint32 status); +void samr_io_r_enum_dom_aliases(char *desc, SAMR_R_ENUM_DOM_ALIASES *r_u, prs_struct *ps, int depth); +void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol, + uint16 switch_level, uint32 start_idx, uint32 size); +void samr_io_q_query_dispinfo(char *desc, SAMR_Q_QUERY_DISPINFO *q_e, prs_struct *ps, int depth); +void make_sam_info_2(SAM_INFO_2 *sam, uint32 acb_mask, + uint32 start_idx, uint32 num_sam_entries, + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]); +void sam_io_sam_info_2(char *desc, SAM_INFO_2 *sam, prs_struct *ps, int depth); +void make_sam_info_1(SAM_INFO_1 *sam, uint32 acb_mask, + uint32 start_idx, uint32 num_sam_entries, + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]); +void sam_io_sam_info_1(char *desc, SAM_INFO_1 *sam, prs_struct *ps, int depth); +void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u, + uint16 switch_level, SAM_INFO_CTR *ctr, uint32 status); +void samr_io_r_query_dispinfo(char *desc, SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth); +void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol, + uint16 switch_level, uint32 start_idx, uint32 size); +void samr_io_q_enum_dom_groups(char *desc, SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth); +void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u, + uint32 start_idx, uint32 num_sam_entries, + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], + uint32 status); +void samr_io_r_enum_dom_groups(char *desc, SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth); +void make_samr_q_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_e, + POLICY_HND *pol, + uint16 switch_level); +void samr_io_q_query_aliasinfo(char *desc, SAMR_Q_QUERY_ALIASINFO *q_e, prs_struct *ps, int depth); +void make_samr_r_query_aliasinfo(SAMR_R_QUERY_ALIASINFO *r_u, + uint16 switch_value, char *acct_desc, + uint32 status); +void samr_io_r_query_aliasinfo(char *desc, SAMR_R_QUERY_ALIASINFO *r_u, prs_struct *ps, int depth); +void samr_io_q_lookup_ids(char *desc, SAMR_Q_LOOKUP_IDS *q_u, prs_struct *ps, int depth); +void make_samr_r_lookup_ids(SAMR_R_LOOKUP_IDS *r_u, + uint32 num_rids, uint32 *rid, uint32 status); +void samr_io_r_lookup_ids(char *desc, SAMR_R_LOOKUP_IDS *r_u, prs_struct *ps, int depth); +void samr_io_q_lookup_names(char *desc, SAMR_Q_LOOKUP_NAMES *q_u, prs_struct *ps, int depth); +void make_samr_r_lookup_names(SAMR_R_LOOKUP_NAMES *r_u, + uint32 num_rids, uint32 *rid, uint32 status); +void samr_io_r_lookup_names(char *desc, SAMR_R_LOOKUP_NAMES *r_u, prs_struct *ps, int depth); +void make_samr_q_unknown_12(SAMR_Q_UNKNOWN_12 *q_u, + POLICY_HND *pol, uint32 rid, + uint32 num_gids, uint32 *gid); +void samr_io_q_unknown_12(char *desc, SAMR_Q_UNKNOWN_12 *q_u, prs_struct *ps, int depth); +void make_samr_r_unknown_12(SAMR_R_UNKNOWN_12 *r_u, + uint32 num_aliases, fstring *als_name, uint32 *num_als_usrs, + uint32 status); +void samr_io_r_unknown_12(char *desc, SAMR_R_UNKNOWN_12 *r_u, prs_struct *ps, int depth); +void make_samr_q_open_user(SAMR_Q_OPEN_USER *q_u, + POLICY_HND *pol, + uint32 unk_0, uint32 rid); +void samr_io_q_open_user(char *desc, SAMR_Q_OPEN_USER *q_u, prs_struct *ps, int depth); +void samr_io_r_open_user(char *desc, SAMR_R_OPEN_USER *r_u, prs_struct *ps, int depth); +void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u, + POLICY_HND *hnd); +void samr_io_q_query_usergroups(char *desc, SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth); +void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u, + uint32 num_gids, DOM_GID *gid, uint32 status); +void samr_io_r_query_usergroups(char *desc, SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth); +void make_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, + POLICY_HND *hnd, uint16 switch_value); +void samr_io_q_query_userinfo(char *desc, SAMR_Q_QUERY_USERINFO *q_u, prs_struct *ps, int depth); +void sam_io_logon_hrs(char *desc, LOGON_HRS *hrs, prs_struct *ps, int depth); +void make_sam_user_info11(SAM_USER_INFO_11 *usr, + NTTIME *expiry, + char *mach_acct, + uint32 rid_user, + uint32 rid_group, + uint16 acct_ctrl); +void sam_io_user_info11(char *desc, SAM_USER_INFO_11 *usr, prs_struct *ps, int depth); +void make_sam_user_info21(SAM_USER_INFO_21 *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *home_dir, + char *dir_drive, + char *logon_script, + char *profile_path, + char *description, + char *workstations, + char *unknown_str, + char *munged_dial, + + uint32 user_rid, + uint32 group_rid, + uint16 acb_info, + + uint32 unknown_3, + uint16 logon_divs, + LOGON_HRS *hrs, + uint32 unknown_5, + uint32 unknown_6); +void sam_io_user_info21(char *desc, SAM_USER_INFO_21 *usr, prs_struct *ps, int depth); +void make_samr_r_query_userinfo(SAMR_R_QUERY_USERINFO *r_u, + uint16 switch_value, void *info, uint32 status); +void samr_io_r_query_userinfo(char *desc, SAMR_R_QUERY_USERINFO *r_u, prs_struct *ps, int depth); +void make_samr_q_unknown_21(SAMR_Q_UNKNOWN_21 *q_c, + POLICY_HND *hnd, uint16 unk_1, uint16 unk_2); +void samr_io_q_unknown_21(char *desc, SAMR_Q_UNKNOWN_21 *q_u, prs_struct *ps, int depth); +void make_samr_q_unknown_13(SAMR_Q_UNKNOWN_13 *q_c, + POLICY_HND *hnd, uint16 unk_1, uint16 unk_2); +void samr_io_q_unknown_13(char *desc, SAMR_Q_UNKNOWN_13 *q_u, prs_struct *ps, int depth); +void samr_io_q_unknown_32(char *desc, SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth); +void samr_io_r_unknown_32(char *desc, SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth); +void make_samr_q_connect(SAMR_Q_CONNECT *q_u, + char *srv_name, uint32 unknown_0); +void samr_io_q_connect(char *desc, SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth); +void samr_io_r_connect(char *desc, SAMR_R_CONNECT *r_u, prs_struct *ps, int depth); +void make_samr_q_open_alias(SAMR_Q_OPEN_ALIAS *q_u, + uint32 unknown_0, uint32 rid); +void samr_io_q_open_alias(char *desc, SAMR_Q_OPEN_ALIAS *q_u, prs_struct *ps, int depth); +void samr_io_r_open_alias(char *desc, SAMR_R_OPEN_ALIAS *r_u, prs_struct *ps, int depth); +void make_samr_q_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, char *srv_name); +void samr_io_q_unknown_38(char *desc, SAMR_Q_UNKNOWN_38 *q_u, prs_struct *ps, int depth); +void make_samr_r_unknown_38(SAMR_R_UNKNOWN_38 *r_u, + uint16 level, uint32 status); +void samr_io_r_unknown_38(char *desc, SAMR_R_UNKNOWN_38 *r_u, prs_struct *ps, int depth); +void samr_io_enc_passwd(char *desc, SAMR_ENC_PASSWD *pwd, prs_struct *ps, int depth); +void samr_io_enc_hash(char *desc, SAMR_ENC_HASH *hsh, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_srv.c */ + +void make_srv_share_info1_str(SH_INFO_1_STR *sh1, char *net_name, char *remark); +void srv_io_share_info1_str(char *desc, SH_INFO_1_STR *sh1, prs_struct *ps, int depth); +void make_srv_share_info1(SH_INFO_1 *sh1, char *net_name, uint32 type, char *remark); +void srv_io_share_info1(char *desc, SH_INFO_1 *sh1, prs_struct *ps, int depth); +void srv_io_srv_share_info_1(char *desc, SRV_SHARE_INFO_1 *ctr, prs_struct *ps, int depth); +void make_srv_share_info2_str(SH_INFO_2_STR *sh2, + char *net_name, char *remark, + char *path, char *passwd); +void srv_io_share_info2_str(char *desc, SH_INFO_2_STR *sh2, prs_struct *ps, int depth); +void make_srv_share_info2(SH_INFO_2 *sh2, + char *net_name, uint32 type, char *remark, + uint32 perms, uint32 max_uses, uint32 num_uses, + char *path, char *passwd); +void srv_io_share_info2(char *desc, SH_INFO_2 *sh2, prs_struct *ps, int depth); +void srv_io_srv_share_info_2(char *desc, SRV_SHARE_INFO_2 *ctr, prs_struct *ps, int depth); +void srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct *ps, int depth); +void make_srv_q_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, + char *srv_name, + uint32 share_level, SRV_SHARE_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd); +void srv_io_q_net_share_enum(char *desc, SRV_Q_NET_SHARE_ENUM *q_n, prs_struct *ps, int depth); +void srv_io_r_net_share_enum(char *desc, SRV_R_NET_SHARE_ENUM *r_n, prs_struct *ps, int depth); +void make_srv_sess_info0_str(SESS_INFO_0_STR *ss0, char *name); +void srv_io_sess_info0_str(char *desc, SESS_INFO_0_STR *ss0, prs_struct *ps, int depth); +void make_srv_sess_info0(SESS_INFO_0 *ss0, char *name); +void srv_io_sess_info0(char *desc, SESS_INFO_0 *ss0, prs_struct *ps, int depth); +void srv_io_srv_sess_info_0(char *desc, SRV_SESS_INFO_0 *ss0, prs_struct *ps, int depth); +void make_srv_sess_info1_str(SESS_INFO_1_STR *ss1, char *name, char *user); +void srv_io_sess_info1_str(char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth); +void make_srv_sess_info1(SESS_INFO_1 *ss1, + char *name, char *user, + uint32 num_opens, uint32 open_time, uint32 idle_time, + uint32 user_flags); +void srv_io_sess_info1(char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth); +void srv_io_srv_sess_info_1(char *desc, SRV_SESS_INFO_1 *ss1, prs_struct *ps, int depth); +void srv_io_srv_sess_ctr(char *desc, SRV_SESS_INFO_CTR *ctr, prs_struct *ps, int depth); +void make_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, + char *srv_name, char *qual_name, + uint32 sess_level, SRV_SESS_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd); +void srv_io_q_net_sess_enum(char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth); +void srv_io_r_net_sess_enum(char *desc, SRV_R_NET_SESS_ENUM *r_n, prs_struct *ps, int depth); +void make_srv_conn_info0(CONN_INFO_0 *ss0, uint32 id); +void srv_io_conn_info0(char *desc, CONN_INFO_0 *ss0, prs_struct *ps, int depth); +void srv_io_srv_conn_info_0(char *desc, SRV_CONN_INFO_0 *ss0, prs_struct *ps, int depth); +void make_srv_conn_info1_str(CONN_INFO_1_STR *ss1, char *usr_name, char *net_name); +void srv_io_conn_info1_str(char *desc, CONN_INFO_1_STR *ss1, prs_struct *ps, int depth); +void make_srv_conn_info1(CONN_INFO_1 *ss1, + uint32 id, uint32 type, + uint32 num_opens, uint32 num_users, uint32 open_time, + char *usr_name, char *net_name); +void srv_io_conn_info1(char *desc, CONN_INFO_1 *ss1, prs_struct *ps, int depth); +void srv_io_srv_conn_info_1(char *desc, SRV_CONN_INFO_1 *ss1, prs_struct *ps, int depth); +void srv_io_srv_conn_ctr(char *desc, SRV_CONN_INFO_CTR *ctr, prs_struct *ps, int depth); +void make_srv_q_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, + char *srv_name, char *qual_name, + uint32 conn_level, SRV_CONN_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd); +void srv_io_q_net_conn_enum(char *desc, SRV_Q_NET_CONN_ENUM *q_n, prs_struct *ps, int depth); +void srv_io_r_net_conn_enum(char *desc, SRV_R_NET_CONN_ENUM *r_n, prs_struct *ps, int depth); +void make_srv_file_info3_str(FILE_INFO_3_STR *fi3, char *user_name, char *path_name); +void srv_io_file_info3_str(char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth); +void make_srv_file_info3(FILE_INFO_3 *fl3, + uint32 id, uint32 perms, uint32 num_locks, + char *path_name, char *user_name); +void srv_io_file_info3(char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth); +void srv_io_srv_file_info_3(char *desc, SRV_FILE_INFO_3 *fl3, prs_struct *ps, int depth); +void srv_io_srv_file_ctr(char *desc, SRV_FILE_INFO_CTR *ctr, prs_struct *ps, int depth); +void make_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, + char *srv_name, char *qual_name, + uint32 file_level, SRV_FILE_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd); +void srv_io_q_net_file_enum(char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth); +void srv_io_r_net_file_enum(char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_struct *ps, int depth); +void make_srv_info_101(SRV_INFO_101 *sv101, uint32 platform_id, char *name, + uint32 ver_major, uint32 ver_minor, + uint32 srv_type, char *comment); +void srv_io_info_101(char *desc, SRV_INFO_101 *sv101, prs_struct *ps, int depth); +void make_srv_info_102(SRV_INFO_102 *sv102, uint32 platform_id, char *name, + char *comment, uint32 ver_major, uint32 ver_minor, + uint32 srv_type, uint32 users, uint32 disc, uint32 hidden, + uint32 announce, uint32 ann_delta, uint32 licenses, + char *usr_path); +void srv_io_info_102(char *desc, SRV_INFO_102 *sv102, prs_struct *ps, int depth); +void srv_io_info_ctr(char *desc, SRV_INFO_CTR *ctr, prs_struct *ps, int depth); +void make_srv_q_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *srv, + char *server_name, uint32 switch_value); +void srv_io_q_net_srv_get_info(char *desc, SRV_Q_NET_SRV_GET_INFO *q_n, prs_struct *ps, int depth); +void make_srv_r_net_srv_get_info(SRV_R_NET_SRV_GET_INFO *srv, + uint32 switch_value, SRV_INFO_CTR *ctr, uint32 status); +void srv_io_r_net_srv_get_info(char *desc, SRV_R_NET_SRV_GET_INFO *r_n, prs_struct *ps, int depth); +void make_srv_q_net_srv_set_info(SRV_Q_NET_SRV_SET_INFO *srv, + uint32 switch_value, SRV_INFO_CTR *ctr); +void srv_io_q_net_srv_set_info(char *desc, SRV_Q_NET_SRV_SET_INFO *q_n, prs_struct *ps, int depth); +void make_srv_r_net_srv_set_info(SRV_R_NET_SRV_SET_INFO *srv, + uint32 switch_value, SRV_INFO_CTR *ctr, uint32 status); +void srv_io_r_net_srv_set_info(char *desc, SRV_R_NET_SRV_SET_INFO *r_n, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/parse/parse_wks.c */ + +void make_wks_q_query_info(WKS_Q_QUERY_INFO *q_u, + char *server, uint16 switch_value) ; +void wks_io_q_query_info(char *desc, WKS_Q_QUERY_INFO *q_u, prs_struct *ps, int depth); +void make_wks_info_100(WKS_INFO_100 *inf, + uint32 platform_id, uint32 ver_major, uint32 ver_minor, + char *my_name, char *domain_name); +void wks_io_wks_info_100(char *desc, WKS_INFO_100 *inf, prs_struct *ps, int depth); +void make_wks_r_query_info(WKS_R_QUERY_INFO *r_u, + uint32 switch_value, WKS_INFO_100 *wks100, + int status) ; +void wks_io_r_query_info(char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth); + +/*The following definitions come from lib/rpc/server/srv_lsa.c */ + +BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data); + +/*The following definitions come from lib/rpc/server/srv_lsa_hnd.c */ + +void create_pol_hnd(POLICY_HND *hnd); +void init_lsa_policy_hnd(void); +BOOL open_lsa_policy_hnd(POLICY_HND *hnd); +int find_lsa_policy_by_hnd(POLICY_HND *hnd); +BOOL set_lsa_policy_samr_rid(POLICY_HND *hnd, uint32 rid); +BOOL set_lsa_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status); +BOOL set_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid); +uint32 get_lsa_policy_samr_rid(POLICY_HND *hnd); +BOOL set_lsa_policy_reg_name(POLICY_HND *hnd, fstring name); +BOOL get_lsa_policy_reg_name(POLICY_HND *hnd, fstring name); +BOOL close_lsa_policy_hnd(POLICY_HND *hnd); + +/*The following definitions come from lib/rpc/server/srv_netlog.c */ + +BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data); + +/*The following definitions come from lib/rpc/server/srv_pipe_hnd.c */ + +void reset_chain_pnum(void); +void set_chain_pnum(int new_pnum); +void init_rpc_pipe_hnd(void); +int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid); +int read_pipe(uint16 pnum, char *data, uint32 pos, int n); +BOOL get_rpc_pipe(int pnum, pipes_struct **p); +char *get_rpc_pipe_hnd_name(int pnum); +BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state); +BOOL close_rpc_pipe_hnd(int pnum, int cnum); +int get_rpc_pipe_num(char *buf, int where); + +/*The following definitions come from lib/rpc/server/srv_reg.c */ + +BOOL api_reg_rpc(pipes_struct *p, prs_struct *data); + +/*The following definitions come from lib/rpc/server/srv_samr.c */ + +BOOL api_samr_rpc(pipes_struct *p, prs_struct *data); + +/*The following definitions come from lib/rpc/server/srv_srvsvc.c */ + +BOOL api_srvsvc_rpc(pipes_struct *p, prs_struct *data); + +/*The following definitions come from lib/rpc/server/srv_util.c */ + +int make_dom_gids(char *gids_str, DOM_GID *gids); +void get_domain_user_groups(char *domain_groups, char *user); +BOOL create_rpc_reply(pipes_struct *p, + uint32 data_start, uint32 data_end); +BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds, + prs_struct *data); +uint32 lookup_group_name(uint32 rid, char *group_name, uint32 *type); +uint32 lookup_alias_name(uint32 rid, char *alias_name, uint32 *type); +uint32 lookup_user_name(uint32 rid, char *user_name, uint32 *type); +uint32 lookup_group_rid(char *group_name, uint32 *rid); +uint32 lookup_alias_rid(char *alias_name, uint32 *rid); +uint32 lookup_user_rid(char *user_name, uint32 *rid); +BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid); + +/*The following definitions come from lib/rpc/server/srv_wkssvc.c */ + +BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data); + /*The following definitions come from loadparm.c */ char *lp_string(char *s); @@ -455,6 +1100,24 @@ void smb_mem_write_errors(FILE *outfile); void smb_mem_set_multiplier(int multiplier); void *smb_mem_resize(void *ptr,size_t newsize); +/*The following definitions come from membuffer.c */ + +void mem_init(struct mem_buf *buf, int margin); +void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dynamic); +void mem_take(struct mem_buf *mem_to, struct mem_buf *mem_from); +BOOL mem_alloc_data(struct mem_buf *buf, int size); +BOOL mem_buf_copy(char *copy_into, struct mem_buf *buf, + uint32 offset, uint32 len); +BOOL mem_buf_init(struct mem_buf **buf, uint32 margin); +void mem_buf_free(struct mem_buf **buf); +void mem_free_chain(struct mem_buf **buf); +void mem_free_data(struct mem_buf *buf); +BOOL mem_realloc_data(struct mem_buf *buf, int new_size); +BOOL mem_grow_data(struct mem_buf **buf, BOOL io, int new_size); +BOOL mem_find(struct mem_buf **buf, uint32 offset); +uint32 mem_buf_len(struct mem_buf *buf); +char *mem_data(struct mem_buf **buf, uint32 offset); + /*The following definitions come from message.c */ int reply_sends(char *inbuf,char *outbuf); @@ -796,11 +1459,6 @@ BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2); BOOL send_packet(struct packet_struct *p); struct packet_struct *receive_packet(int fd,enum packet_type type,int t); -/*The following definitions come from ntclient.c */ - -BOOL do_nt_login(char *desthost, char *myhostname, - int Client, int cnum); - /*The following definitions come from params.c */ BOOL pm_process( char *FileName, @@ -820,6 +1478,8 @@ void add_session_user(char *user); void dfs_unlogin(void); BOOL password_check(char *password); BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8); +BOOL smb_password_ok(struct smb_passwd *smb_pass, + uchar lm_pass[24], uchar nt_pass[24]); BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd); BOOL user_ok(char *user,int snum); BOOL authorise_login(int snum,char *user,char *password, int pwlen, @@ -839,12 +1499,8 @@ void pcap_printer_fn(void (*fn)()); /*The following definitions come from pipes.c */ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize); +int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize); int reply_pipe_close(char *inbuf,char *outbuf); -BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param); -BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); /*The following definitions come from predict.c */ @@ -937,281 +1593,6 @@ int reply_writebs(char *inbuf,char *outbuf); int reply_setattrE(char *inbuf,char *outbuf); int reply_getattrE(char *inbuf,char *outbuf); -/*The following definitions come from rpc_pipes/lsa_hnd.c */ - -void init_lsa_policy_hnd(void); -BOOL open_lsa_policy_hnd(LSA_POL_HND *hnd); -BOOL set_lsa_policy_samr_rid(LSA_POL_HND *hnd, uint32 rid); -BOOL set_lsa_policy_samr_pol_status(LSA_POL_HND *hnd, uint32 pol_status); -BOOL set_lsa_policy_samr_sid(LSA_POL_HND *hnd, DOM_SID *sid); -uint32 get_lsa_policy_samr_rid(LSA_POL_HND *hnd); -BOOL close_lsa_policy_hnd(LSA_POL_HND *hnd); - -/*The following definitions come from rpc_pipes/lsaparse.c */ - -void make_q_open_pol(LSA_Q_OPEN_POL *r_q, char *server_name, - uint32 attributes, uint32 sec_qos, - uint16 desired_access); -char* lsa_io_q_open_pol(BOOL io, LSA_Q_OPEN_POL *r_q, char *q, char *base, int align, int depth); -char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align, int depth); -void make_q_query(LSA_Q_QUERY_INFO *q_q, LSA_POL_HND *hnd, uint16 info_class); -char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align, int depth); -char* lsa_io_q_enum_trust_dom(BOOL io, LSA_Q_ENUM_TRUST_DOM *q_e, char *q, char *base, int align, int depth); -void make_r_enum_trust_dom(LSA_R_ENUM_TRUST_DOM *r_e, LSA_POL_HND *hnd, uint32 status); -char* lsa_io_r_enum_trust_dom(BOOL io, LSA_R_ENUM_TRUST_DOM *r_e, char *q, char *base, int align, int depth); -void make_q_close(LSA_Q_CLOSE *q_c, LSA_POL_HND *hnd); -char* lsa_io_q_close(BOOL io, LSA_Q_CLOSE *q_c, char *q, char *base, int align, int depth); -void make_r_close(LSA_R_CLOSE *q_r, LSA_POL_HND *hnd); -char* lsa_io_r_close(BOOL io, LSA_R_CLOSE *r_c, char *q, char *base, int align, int depth); -char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align, int depth); -char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align, int depth); -char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align, int depth); -char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align, int depth); -char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align, int depth); -void make_q_req_chal(LSA_Q_REQ_CHAL *q_c, - char *logon_srv, char *logon_clnt, - DOM_CHAL *clnt_chal); -char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align, int depth); -char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align, int depth); -void make_q_auth_2(LSA_Q_AUTH_2 *q_a, - char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, - DOM_CHAL *clnt_chal, uint32 clnt_flgs); -char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align, int depth); -char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align, int depth); -void make_q_srv_pwset(LSA_Q_SRV_PWSET *q_s, char sess_key[8], - char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, - DOM_CRED *cred, char nt_cypher[16]); -char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align, int depth); -char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align, int depth); -char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align, int depth); -char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align, int depth); -char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align, int depth); -char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align, int depth); -char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align, int depth); - -/*The following definitions come from rpc_pipes/ntclientlsa.c */ - -BOOL do_lsa_open_policy(uint16 fnum, uint32 call_id, - char *server_name, LSA_POL_HND *hnd); -BOOL do_lsa_query_info_pol(uint16 fnum, uint32 call_id, - LSA_POL_HND *hnd, uint16 info_class, - fstring domain_name, pstring domain_sid); -BOOL do_lsa_close(uint16 fnum, uint32 call_id, - LSA_POL_HND *hnd); - -/*The following definitions come from rpc_pipes/ntclientnet.c */ - -BOOL do_lsa_req_chal(uint16 fnum, uint32 call_id, - char *desthost, char *myhostname, - DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal); -BOOL do_lsa_auth2(uint16 fnum, uint32 call_id, - char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, - DOM_CHAL *clnt_chal, uint32 neg_flags, DOM_CHAL *srv_chal); -BOOL do_lsa_srv_pwset(uint16 fnum, uint32 call_id, - uchar sess_key[8], - char *logon_srv, char *mach_acct, uint16 sec_chan_type, char *comp_name, - DOM_CRED *clnt_cred, DOM_CRED *srv_cred, - char nt_owf_new_mach_pwd[16]); -BOOL do_lsa_sam_logon(uint16 fnum, uint32 call_id, - uchar sess_key[8], DOM_CRED *sto_clnt_cred, - char *logon_srv, char *comp_name, - DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, - uint16 logon_level, uint16 switch_value, DOM_ID_INFO_1 *id1, - LSA_USER_INFO *user_info, - DOM_CRED *srv_cred); -BOOL do_lsa_sam_logoff(uint16 fnum, uint32 call_id, - uchar sess_key[8], DOM_CRED *sto_clnt_cred, - char *logon_srv, char *comp_name, - DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, - uint16 logon_level, uint16 switch_value, DOM_ID_INFO_1 *id1, - DOM_CRED *srv_cred); - -/*The following definitions come from rpc_pipes/ntclientpipe.c */ - -uint16 rpc_pipe_open(char *inbuf, char *outbuf, char *rname, int Client, int cnum); -BOOL rpc_pipe_set_hnd_state(char *pipe_name, uint16 fnum, uint16 device_state); -BOOL rpc_pipe_bind(char *pipe_name, uint16 fnum, uint32 call_id, - RPC_IFACE *abstract, RPC_IFACE *transfer); - -/*The following definitions come from rpc_pipes/pipe_hnd.c */ - -void reset_chain_pnum(void); -void init_rpc_pipe_hnd(void); -int open_rpc_pipe_hnd(char *pipe_name, int cnum); -char *get_rpc_pipe_hnd_name(int pnum); -BOOL set_rpc_pipe_hnd_state(int pnum, int cnum, uint16 device_state); -BOOL close_rpc_pipe_hnd(int pnum, int cnum); -int get_rpc_pipe_num(char *buf, int where); - -/*The following definitions come from rpc_pipes/pipenetlog.c */ - -BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - -/*The following definitions come from rpc_pipes/pipentlsa.c */ - -BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - -/*The following definitions come from rpc_pipes/pipesamr.c */ - -BOOL api_samrTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - -/*The following definitions come from rpc_pipes/pipesrvsvc.c */ - -BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - -/*The following definitions come from rpc_pipes/pipeutil.c */ - -void initrpcreply(char *inbuf, char *q); -void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen); -BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid); -char *dom_sid_to_string(DOM_SID *sid); -int make_dom_sids(char *sids_str, DOM_SID *sids, int max_sids); -int make_dom_gids(char *gids_str, DOM_GID *gids); -int create_rpc_request(uint32 call_id, uint8 op_num, char *q, int data_len); -int create_rpc_reply(uint32 call_id, char *q, int data_len); - -/*The following definitions come from rpc_pipes/pipewkssvc.c */ - -BOOL api_wkssvcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - -/*The following definitions come from rpc_pipes/samrparse.c */ - -char* samr_io_q_close(BOOL io, SAMR_Q_CLOSE *q_u, char *q, char *base, int align, int depth); -char* samr_io_r_close(BOOL io, SAMR_R_CLOSE *r_u, char *q, char *base, int align, int depth); -char* samr_io_q_open_secret(BOOL io, SAMR_Q_OPEN_SECRET *q_u, char *q, char *base, int align, int depth); -char* samr_io_r_open_secret(BOOL io, SAMR_R_OPEN_SECRET *r_u, char *q, char *base, int align, int depth); -char* samr_io_q_lookup_rids(BOOL io, SAMR_Q_LOOKUP_RIDS *q_u, char *q, char *base, int align, int depth); -void make_samr_r_lookup_rids(SAMR_R_LOOKUP_RIDS *r_u, - uint32 num_rids, uint32 rid, uint32 status); -char* samr_io_r_lookup_rids(BOOL io, SAMR_R_LOOKUP_RIDS *r_u, char *q, char *base, int align, int depth); -char* samr_io_q_unknown_22(BOOL io, SAMR_Q_UNKNOWN_22 *q_u, char *q, char *base, int align, int depth); -char* samr_io_r_unknown_22(BOOL io, SAMR_R_UNKNOWN_22 *r_u, char *q, char *base, int align, int depth); -char* samr_io_q_unknown_24(BOOL io, SAMR_Q_UNKNOWN_24 *q_u, char *q, char *base, int align, int depth); -void make_samr_r_unknown_24(SAMR_R_UNKNOWN_24 *r_u, - uint16 unknown_0, NTTIME *expiry, char *mach_acct, - uint32 unknown_id_0, uint32 status); -char* samr_io_r_unknown_24(BOOL io, SAMR_R_UNKNOWN_24 *r_u, char *q, char *base, int align, int depth); -char* samr_io_q_unknown_32(BOOL io, SAMR_Q_UNKNOWN_32 *q_u, char *q, char *base, int align, int depth); -char* samr_io_r_unknown_32(BOOL io, SAMR_R_UNKNOWN_32 *r_u, char *q, char *base, int align, int depth); -char* samr_io_q_open_policy(BOOL io, SAMR_Q_OPEN_POLICY *q_u, char *q, char *base, int align, int depth); -char* samr_io_r_open_policy(BOOL io, SAMR_R_OPEN_POLICY *r_u, char *q, char *base, int align, int depth); - -/*The following definitions come from rpc_pipes/smbparse.c */ - -char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align, int depth); -char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align, int depth); -void make_dom_sid(DOM_SID *sid, char *domsid); -char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int depth); -void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate); -char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int depth); -void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate); -char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align, int depth); -void make_unistr(UNISTR *str, char *buf); -char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align, int depth); -void make_unistr2(UNISTR2 *str, char *buf, int len); -char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int depth); -void make_dom_sid2(DOM_SID2 *sid2, char *sid_str); -char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align, int depth); -void make_dom_rid2(DOM_RID2 *rid2, uint32 rid); -char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, int depth); -void make_dom_rid3(DOM_RID3 *rid3, uint32 rid); -char* smb_io_dom_rid3(BOOL io, DOM_RID3 *rid3, char *q, char *base, int align, int depth); -void make_clnt_srv(DOM_CLNT_SRV *log, char *logon_srv, char *comp_name); -char* smb_io_clnt_srv(BOOL io, DOM_CLNT_SRV *log, char *q, char *base, int align, int depth); -void make_log_info(DOM_LOG_INFO *log, char *logon_srv, char *acct_name, - uint16 sec_chan, char *comp_name); -char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align, int depth); -char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align, int depth); -char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align, int depth); -void make_clnt_info2(DOM_CLNT_INFO2 *clnt, - char *logon_srv, char *comp_name, - DOM_CRED *clnt_cred); -char* smb_io_clnt_info2(BOOL io, DOM_CLNT_INFO2 *clnt, char *q, char *base, int align, int depth); -char* make_clnt_info(DOM_CLNT_INFO *clnt, - char *logon_srv, char *acct_name, - uint16 sec_chan, char *comp_name, - DOM_CRED *cred); -char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align, int depth); -void make_logon_id(DOM_LOGON_ID *log, uint32 log_id_low, uint32 log_id_high); -char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align, int depth); -void make_arc4_owf(ARC4_OWF *hash, char data[16]); -char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align, int depth); -void make_id_info1(DOM_ID_INFO_1 *id, char *domain_name, - uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high, - char *user_name, char *wksta_name, - char *sess_key, - unsigned char lm_cypher[16], unsigned char nt_cypher[16]); -char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align, int depth); -void make_sam_info(DOM_SAM_INFO *sam, - char *logon_srv, char *comp_name, DOM_CRED *clnt_cred, - DOM_CRED *rtn_cred, uint16 logon_level, uint16 switch_value, - DOM_ID_INFO_1 *id1); -char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align, int depth); -char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align, int depth); -void make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 frag, - uint32 call_id, int data_len); -char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align, int depth); -void make_rpc_iface(RPC_IFACE *ifc, char data[16], uint32 version); -char* smb_io_rpc_iface(BOOL io, RPC_IFACE *ifc, char *q, char *base, int align, int depth); -void make_rpc_addr_str(RPC_ADDR_STR *str, char *name); -char* smb_io_rpc_addr_str(BOOL io, RPC_ADDR_STR *str, char *q, char *base, int align, int depth); -void make_rpc_hdr_bba(RPC_HDR_BBA *bba, uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid); -char* smb_io_rpc_hdr_bba(BOOL io, RPC_HDR_BBA *rpc, char *q, char *base, int align, int depth); -void make_rpc_hdr_rb(RPC_HDR_RB *rpc, - uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, - uint32 num_elements, uint16 context_id, uint8 num_syntaxes, - RPC_IFACE *abstract, RPC_IFACE *transfer); -char* smb_io_rpc_hdr_rb(BOOL io, RPC_HDR_RB *rpc, char *q, char *base, int align, int depth); -void make_rpc_results(RPC_RESULTS *res, - uint8 num_results, uint16 result, uint16 reason); -char* smb_io_rpc_results(BOOL io, RPC_RESULTS *res, char *q, char *base, int align, int depth); -void make_rpc_hdr_ba(RPC_HDR_BA *rpc, - uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, - char *pipe_addr, - uint8 num_results, uint16 result, uint16 reason, - RPC_IFACE *transfer); -char* smb_io_rpc_hdr_ba(BOOL io, RPC_HDR_BA *rpc, char *q, char *base, int align, int depth); -void make_obj_attr(LSA_OBJ_ATTR *attr, uint32 attributes, uint32 sec_qos); -char* smb_io_obj_attr(BOOL io, LSA_OBJ_ATTR *attr, char *q, char *base, int align, int depth); -void make_rpc_hdr_rr(RPC_HDR_RR *hdr, enum RPC_PKT_TYPE pkt_type, - uint32 call_id, int data_len, uint8 opnum); -char* smb_io_rpc_hdr_rr(BOOL io, RPC_HDR_RR *rpc, char *q, char *base, int align, int depth); -char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, int depth); -char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth); -char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth); -char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align, int depth); -char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align, int depth); -char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align, int depth); -char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align, int depth); - -/*The following definitions come from rpc_pipes/srvparse.c */ - -char* srv_io_share_info1_str(BOOL io, SH_INFO_1_STR *sh1, char *q, char *base, int align, int depth); -char* srv_io_share_info1(BOOL io, SH_INFO_1 *sh1, char *q, char *base, int align, int depth); -char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, int align, int depth); -char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth); -char* srv_io_r_net_share_enum(BOOL io, SRV_R_NET_SHARE_ENUM *r_n, char *q, char *base, int align, int depth); - -/*The following definitions come from rpc_pipes/wksparse.c */ - -char* wks_io_q_unknown_0(BOOL io, WKS_Q_UNKNOWN_0 *q_u, char *q, char *base, int align, int depth); -char* wks_io_r_unknown_0(BOOL io, WKS_R_UNKNOWN_0 *r_u, char *q, char *base, int align, int depth); - /*The following definitions come from server.c */ void *dflt_sig(void); @@ -1294,10 +1675,13 @@ char *smb_errstr(char *inbuf); /*The following definitions come from smbpass.c */ -int pw_file_lock(char *name, int type, int secs); +int pw_file_lock(int fd, int type, int secs); int pw_file_unlock(int fd); +FILE *startsmbpwent(BOOL update); +void endsmbpwent(FILE *fp); +struct smb_passwd *getsmbpwent(FILE *fp); struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid); -BOOL add_smbpwd_entry(struct smb_passwd* pwd); +BOOL add_smbpwd_entry(struct smb_passwd *newpwd); BOOL mod_smbpwd_entry(struct smb_passwd* pwd); /*The following definitions come from status.c */ @@ -1343,6 +1727,7 @@ void put_dos_date3(char *buf,int offset,time_t unixdate); time_t make_unix_date(void *date_ptr); time_t make_unix_date2(void *date_ptr); time_t make_unix_date3(void *date_ptr); +char *http_timestring(time_t t); char *timestring(void ); time_t get_create_time(struct stat *st); @@ -1523,3 +1908,4 @@ char *align_offset(char *q, char *base, int align_offset_len); void print_asc(int level, unsigned char *buf,int len); void dump_data(int level,char *buf1,int len); char *tab_depth(int depth); +char *dom_sid_to_string(DOM_SID *sid); diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h new file mode 100644 index 0000000000..9aacaaab87 --- /dev/null +++ b/source3/include/rpc_dce.h @@ -0,0 +1,211 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _DCE_RPC_H /* _DCE_RPC_H */ +#define _DCE_RPC_H + +#include "rpc_misc.h" /* this only pulls in STRHDR */ + + +/* DCE/RPC packet types */ + +enum RPC_PKT_TYPE +{ + RPC_REQUEST = 0x00, + RPC_RESPONSE = 0x02, + RPC_BIND = 0x0B, + RPC_BINDACK = 0x0C +}; + +/* DCE/RPC flags */ +#define RPC_FLG_FIRST 0x01 +#define RPC_FLG_LAST 0x02 + + +/* RPC_IFACE */ +typedef struct rpc_iface_info +{ + uint8 data[16]; /* 16 bytes of rpc interface identification */ + uint32 version; /* the interface version number */ + +} RPC_IFACE; + +struct pipe_id_info +{ + /* the names appear not to matter: the syntaxes _do_ matter */ + + char *client_pipe; + RPC_IFACE abstr_syntax; /* this one is the abstract syntax id */ + + char *server_pipe; /* this one is the secondary syntax name */ + RPC_IFACE trans_syntax; /* this one is the primary syntax id */ +}; + +/* RPC_HDR - dce rpc header */ +typedef struct rpc_hdr_info +{ + uint8 major; /* 5 - RPC major version */ + uint8 minor; /* 0 - RPC minor version */ + uint8 pkt_type; /* RPC_PKT_TYPE - RPC response packet */ + uint8 flags; /* DCE/RPC flags */ + uint32 pack_type; /* 0x1000 0000 - packed data representation */ + uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */ + uint16 auth_len; /* 0 - authentication length */ + uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */ + +} RPC_HDR; + +/* RPC_HDR_RR - ms request / response rpc header */ +typedef struct rpc_hdr_rr_info +{ + uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */ + uint8 context_id; /* 0 - presentation context identifier */ + uint8 cancel_count; /* 0 - cancel count */ + uint8 opnum; /* opnum */ + uint8 reserved; /* 0 - reserved. */ + +} RPC_HDR_RR; + +/* this seems to be the same string name depending on the name of the pipe, + * but is more likely to be linked to the interface name + * "srvsvc", "\\PIPE\\ntsvcs" + * "samr", "\\PIPE\\lsass" + * "wkssvc", "\\PIPE\\wksvcs" + * "NETLOGON", "\\PIPE\\NETLOGON" + */ +/* RPC_ADDR_STR */ +typedef struct rpc_addr_info +{ + uint16 len; /* length of the string including null terminator */ + fstring str; /* the string above in single byte, null terminated form */ + +} RPC_ADDR_STR; + +/* RPC_HDR_BBA */ +typedef struct rpc_hdr_bba_info +{ + uint16 max_tsize; /* maximum transmission fragment size (0x1630) */ + uint16 max_rsize; /* max receive fragment size (0x1630) */ + uint32 assoc_gid; /* associated group id (0x0) */ + +} RPC_HDR_BBA; + +/* RPC_BIND_REQ - ms req bind */ +typedef struct rpc_bind_req_info +{ + RPC_HDR_BBA bba; + + uint32 num_elements; /* the number of elements (0x1) */ + uint16 context_id; /* presentation context identifier (0x0) */ + uint8 num_syntaxes; /* the number of syntaxes (has always been 1?)(0x1) */ + + RPC_IFACE abstract; /* num and vers. of interface client is using */ + RPC_IFACE transfer; /* num and vers. of interface to use for replies */ + +} RPC_HDR_RB; + +/* RPC_RESULTS - can only cope with one reason, right now... */ +typedef struct rpc_results_info +{ +/* uint8[] # 4-byte alignment padding, against SMB header */ + + uint8 num_results; /* the number of results (0x01) */ + +/* uint8[] # 4-byte alignment padding, against SMB header */ + + uint16 result; /* result (0x00 = accept) */ + uint16 reason; /* reason (0x00 = no reason specified) */ + +} RPC_RESULTS; + +/* RPC_HDR_BA */ +typedef struct rpc_hdr_ba_info +{ + RPC_HDR_BBA bba; + + RPC_ADDR_STR addr ; /* the secondary address string, as described earlier */ + RPC_RESULTS res ; /* results and reasons */ + RPC_IFACE transfer; /* the transfer syntax from the request */ + +} RPC_HDR_BA; + +/* this is TEMPORARY */ +/* RPC_AUTH_VERIFIER */ +typedef struct rpc_auth_verif_info +{ + fstring ssp_str; + uint32 ssp_ver; + +} RPC_AUTH_VERIFIER; + +/* this is TEMPORARILY coded up as a specific structure */ +/* this structure comes after the bind request */ +/* RPC_AUTH_NTLMSSP_REQ */ +typedef struct rpc_auth_ntlmssp_req_info +{ + fstring ntlmssp_str; /* "NTLMSSP" */ + uint32 ntlmssp_ver; /* 0x0000 0001 */ + + uint32 unknown_0; /* 0x00b2b3 */ + STRHDR hdr_myname; /* offset is against START of this structure */ + STRHDR hdr_domain; /* offset is against START of this structure */ + + fstring myname; /* calling workstation's name */ + fstring domain; /* calling workstations's domain */ + +} RPC_AUTH_NTLMSSP_REQ; + +/* this is TEMPORARILY coded up as a specific structure */ +/* this structure comes after the bind acknowledgement */ +/* RPC_AUTH_NTLMSSP_RESP */ +typedef struct rpc_auth_ntlmssp_resp_info +{ + uint8 auth_type; /* 0x0a */ + uint8 auth_level; /* 0x06 */ + uint8 stub_type_len; /* don't know */ + uint8 padding; /* padding */ + + uint32 ptr_0; /* non-zero pointer to something */ + + fstring ntlmssp_str; /* "NTLMSSP" */ + uint32 ntlmssp_ver; /* 0x0000 0002 */ + + uint32 unknown_1; /* 0x0000 0000 */ + uint32 unknown_2; /* 0x00b2b3 */ + uint32 unknown_3; /* 0x0082b1 */ + + uint8 data[16]; /* 0x10 bytes of something */ + +} RPC_AUTH_NTLMSSP_RESP; + +/* attached to the end of encrypted rpc requests and responses */ +/* RPC_AUTH_NTLMSSP_CHK */ +typedef struct rpc_auth_ntlmssp_chk_info +{ + uint32 ver; /* 0x1 */ + uint8 data[12]; + +} RPC_AUTH_NTLMSSP_CHK; + +#endif /* _DCE_RPC_H */ + diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h new file mode 100644 index 0000000000..008f8866c0 --- /dev/null +++ b/source3/include/rpc_lsa.h @@ -0,0 +1,288 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_LSA_H /* _RPC_LSA_H */ +#define _RPC_LSA_H + +#include "rpc_misc.h" + +enum SID_NAME_USE +{ + SID_NAME_USER = 1, + SID_NAME_DOM_GRP = 2, /* domain group */ + SID_NAME_WKN_GRP = 5 /* well-known group */ +}; + +/* ntlsa pipe */ +#define LSA_OPENPOLICY 0x2c +#define LSA_QUERYINFOPOLICY 0x07 +#define LSA_ENUMTRUSTDOM 0x0d +#define LSA_CLOSE 0x00 +#define LSA_OPENSECRET 0x1C +#define LSA_LOOKUPSIDS 0x0f + +/* XXXX these are here to get a compile! */ +#define LSA_LOOKUPRIDS 0xFD +#define LSA_LOOKUPNAMES 0xFC + +#define LSA_MAX_GROUPS 32 +#define LSA_MAX_SIDS 32 + +/* DOM_QUERY - info class 3 and 5 LSA Query response */ +typedef struct dom_query_info +{ + uint16 uni_dom_max_len; /* domain name string length * 2 */ + uint16 uni_dom_str_len; /* domain name string length * 2 */ + uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */ + uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */ + UNISTR2 uni_domain_name; /* domain name (unicode string) */ + DOM_SID2 dom_sid; /* domain SID */ + +} DOM_QUERY; + +/* level 5 is same as level 3. we hope. */ +typedef DOM_QUERY DOM_QUERY_3; +typedef DOM_QUERY DOM_QUERY_5; + + +typedef struct obj_attr_info +{ + uint32 len; /* 0x18 - length (in bytes) inc. the length field. */ + uint32 ptr_root_dir; /* 0 - root directory (pointer) */ + uint32 ptr_obj_name; /* 0 - object name (pointer) */ + uint32 attributes; /* 0 - attributes (undocumented) */ + uint32 ptr_sec_desc; /* 0 - security descriptior (pointer) */ + uint32 sec_qos; /* 0 - security quality of service */ + +} LSA_OBJ_ATTR; + +/* LSA_Q_OPEN_POL - LSA Query Open Policy */ +typedef struct lsa_q_open_pol_info +{ + uint32 ptr; /* undocumented buffer pointer */ + UNISTR2 uni_server_name; /* server name, starting with two '\'s */ + LSA_OBJ_ATTR attr ; /* object attributes */ + + uint32 des_access; /* desired access attributes */ + +} LSA_Q_OPEN_POL; + +/* LSA_R_OPEN_POL - response to LSA Open Policy */ +typedef struct lsa_r_open_pol_info +{ + POLICY_HND pol; /* policy handle */ + uint32 status; /* return code */ + +} LSA_R_OPEN_POL; + +/* LSA_Q_QUERY_INFO - LSA query info policy */ +typedef struct lsa_query_info +{ + POLICY_HND pol; /* policy handle */ + uint16 info_class; /* info class */ + +} LSA_Q_QUERY_INFO; + +/* LSA_R_QUERY_INFO - response to LSA query info policy */ +typedef struct lsa_r_query_info +{ + uint32 undoc_buffer; /* undocumented buffer pointer */ + uint16 info_class; /* info class (same as info class in request) */ + + union + { + DOM_QUERY_3 id3; + DOM_QUERY_5 id5; + + } dom; + + uint32 status; /* return code */ + +} LSA_R_QUERY_INFO; + +/* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */ +typedef struct lsa_enum_trust_dom_info +{ + POLICY_HND pol; /* policy handle */ + uint32 enum_context; /* enumeration context handle */ + uint32 preferred_len; /* preferred maximum length */ + +} LSA_Q_ENUM_TRUST_DOM; + +/* LSA_R_ENUM_TRUST_DOM - response to LSA enumerate trusted domains */ +typedef struct lsa_r_enum_trust_dom_info +{ + uint32 enum_context; /* enumeration context handle */ + uint32 num_domains; /* number of domains */ + uint32 ptr_enum_domains; /* buffer pointer to num domains */ + + /* this lot is only added if ptr_enum_domains is non-NULL */ + uint32 num_domains2; /* number of domains */ + UNIHDR2 hdr_domain_name; + UNISTR2 uni_domain_name; + DOM_SID2 other_domain_sid; + + uint32 status; /* return code */ + +} LSA_R_ENUM_TRUST_DOM; + +/* LSA_Q_CLOSE */ +typedef struct lsa_q_close_info +{ + POLICY_HND pol; /* policy handle */ + +} LSA_Q_CLOSE; + +/* LSA_R_CLOSE */ +typedef struct lsa_r_close_info +{ + POLICY_HND pol; /* policy handle. should be all zeros. */ + + uint32 status; /* return code */ + +} LSA_R_CLOSE; + + +#define MAX_REF_DOMAINS 10 + +/* DOM_R_REF */ +typedef struct dom_ref_info +{ + uint32 undoc_buffer; /* undocumented buffer pointer. */ + uint32 num_ref_doms_1; /* num referenced domains? */ + uint32 buffer_dom_name; /* undocumented domain name buffer pointer. */ + uint32 max_entries; /* 32 - max number of entries */ + uint32 num_ref_doms_2; /* 4 - num referenced domains? */ + + UNIHDR2 hdr_dom_name; /* domain name unicode string header */ + UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */ + + UNISTR uni_dom_name; /* domain name unicode string */ + DOM_SID2 ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */ + +} DOM_R_REF; + +/* LSA_TRANS_NAME - translated name */ +typedef struct lsa_trans_name_info +{ + uint32 sid_name_use; /* value is 5 for a well-known group; 2 for a domain group; 1 for a user... */ + + UNIHDR hdr_name; + UNISTR2 uni_name; + + uint32 domain_idx; + +} LSA_TRANS_NAME; + +#define MAX_LOOKUP_SIDS 10 + +/* LSA_TRANS_NAME_ENUM - LSA Translated Name Enumeration container */ +typedef struct lsa_trans_name_enum_info +{ + uint32 num_entries; + uint32 ptr_trans_names; + uint32 num_entries2; + + uint32 ptr_name[MAX_LOOKUP_SIDS]; /* translated name pointers */ + LSA_TRANS_NAME name [MAX_LOOKUP_SIDS]; /* translated names */ + +} LSA_TRANS_NAME_ENUM; + +/* LSA_SID_ENUM - LSA SID enumeration container */ +typedef struct lsa_sid_enum_info +{ + uint32 num_entries; + uint32 ptr_sid_enum; + uint32 num_entries2; + + uint32 ptr_sid[MAX_LOOKUP_SIDS]; /* domain SID pointers to be looked up. */ + DOM_SID2 sid [MAX_LOOKUP_SIDS]; /* domain SIDs to be looked up. */ + +} LSA_SID_ENUM; + +/* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */ +typedef struct lsa_q_lookup_sids +{ + POLICY_HND pol_hnd; /* policy handle */ + LSA_SID_ENUM sids; + LSA_TRANS_NAME_ENUM names; + LOOKUP_LEVEL level; + uint32 mapped_count; + +} LSA_Q_LOOKUP_SIDS; + +/* LSA_R_LOOKUP_SIDS - response to LSA Lookup SIDs */ +typedef struct lsa_r_lookup_sids +{ + DOM_R_REF *dom_ref; /* domain reference info */ + LSA_TRANS_NAME_ENUM *names; + uint32 mapped_count; + + uint32 status; /* return code */ + +} LSA_R_LOOKUP_SIDS; + +/* DOM_NAME - XXXX not sure about this structure */ +typedef struct dom_name_info +{ + uint32 uni_str_len; + UNISTR str; + +} DOM_NAME; + + +#define UNKNOWN_LEN 1 + +/* LSA_Q_LOOKUP_RIDS - LSA Lookup RIDs */ +typedef struct lsa_q_lookup_rids +{ + POLICY_HND pol_hnd; /* policy handle */ + uint32 num_entries; + uint32 num_entries2; + uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ + uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ + DOM_NAME lookup_name[MAX_LOOKUP_SIDS]; /* names to be looked up */ + uint8 undoc[UNKNOWN_LEN]; /* completely undocumented bytes of unknown length */ + +} LSA_Q_LOOKUP_RIDS; + +/* LSA_R_LOOKUP_RIDS - response to LSA Lookup RIDs by name */ +typedef struct lsa_r_lookup_rids +{ + DOM_R_REF dom_ref; /* domain reference info */ + + uint32 num_entries; + uint32 undoc_buffer; /* undocumented buffer pointer */ + + uint32 num_entries2; + DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ + + uint32 num_entries3; + + uint32 status; /* return code */ + +} LSA_R_LOOKUP_RIDS; + + +#endif /* _RPC_LSA_H */ + diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h new file mode 100644 index 0000000000..5d4e385875 --- /dev/null +++ b/source3/include/rpc_misc.h @@ -0,0 +1,272 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_MISC_H /* _RPC_MISC_H */ +#define _RPC_MISC_H + + +#include "rpc_dce.h" + +/* pipe string names */ +#define PIPE_SRVSVC "\\PIPE\\srvsvc" +#define PIPE_SAMR "\\PIPE\\samr" +#define PIPE_WINREG "\\PIPE\\winreg" +#define PIPE_WKSSVC "\\PIPE\\wkssvc" +#define PIPE_NETLOGON "\\PIPE\\NETLOGON" +#define PIPE_NTLSA "\\PIPE\\ntlsa" +#define PIPE_NTSVCS "\\PIPE\\ntsvcs" +#define PIPE_LSASS "\\PIPE\\lsass" +#define PIPE_LSARPC "\\PIPE\\lsarpc" + +/* well-known RIDs - Relative IDs */ + +/* RIDs - Well-known users ... */ +#define DOMAIN_USER_RID_ADMIN (0x000001F4L) +#define DOMAIN_USER_RID_GUEST (0x000001F5L) + +/* RIDs - well-known groups ... */ +#define DOMAIN_GROUP_RID_ADMINS (0x00000200L) +#define DOMAIN_GROUP_RID_USERS (0x00000201L) +#define DOMAIN_GROUP_RID_GUESTS (0x00000202L) + +/* RIDs - well-known aliases ... */ +#define DOMAIN_ALIAS_RID_ADMINS (0x00000220L) +#define DOMAIN_ALIAS_RID_USERS (0x00000221L) +#define DOMAIN_ALIAS_RID_GUESTS (0x00000222L) +#define DOMAIN_ALIAS_RID_POWER_USERS (0x00000223L) + +#define DOMAIN_ALIAS_RID_ACCOUNT_OPS (0x00000224L) +#define DOMAIN_ALIAS_RID_SYSTEM_OPS (0x00000225L) +#define DOMAIN_ALIAS_RID_PRINT_OPS (0x00000226L) +#define DOMAIN_ALIAS_RID_BACKUP_OPS (0x00000227L) + +#define DOMAIN_ALIAS_RID_REPLICATOR (0x00000228L) + +/* ENUM_HND */ +typedef struct enum_hnd_info +{ + uint32 ptr_hnd; /* pointer to enumeration handle */ + uint32 handle; /* enumeration handle */ + +} ENUM_HND; + +/* LOOKUP_LEVEL - switch value */ +typedef struct lookup_level_info +{ + uint16 value; + +} LOOKUP_LEVEL; + +#define MAXSUBAUTHS 15 /* max sub authorities in a SID */ + +/* DOM_SID - security id */ +typedef struct sid_info +{ + uint8 sid_rev_num; /* SID revision number */ + uint8 num_auths; /* number of sub-authorities */ + uint8 id_auth[6]; /* Identifier Authority */ + uint32 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */ + +} DOM_SID; + +/* DOM_SID2 - security id */ +typedef struct sid_info_2 +{ + uint32 num_auths; /* length, bytes, including length of len :-) */ + + DOM_SID sid; + +} DOM_SID2; + +/* STRHDR - string header */ +typedef struct header_info +{ + uint16 str_max_len; + uint16 str_str_len; + uint32 buffer; /* non-zero */ + +} STRHDR; + +/* UNIHDR - unicode string header */ +typedef struct unihdr_info +{ + uint16 uni_max_len; + uint16 uni_str_len; + uint32 buffer; /* usually has a value of 4 */ + +} UNIHDR; + +/* UNIHDR2 - unicode string header and undocumented buffer */ +typedef struct unihdr2_info +{ + UNIHDR unihdr; + uint32 buffer; /* 32 bit buffer pointer */ + +} UNIHDR2; + +/* clueless as to what maximum length should be */ +#define MAX_UNISTRLEN 256 +#define MAX_STRINGLEN 256 + +/* UNISTR - unicode string size and buffer */ +typedef struct unistr_info +{ + uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. ***MUST*** be null-terminated */ + +} UNISTR; + +/* UNINOTSTR2 - unicode string, size (in uint8 ascii chars) and buffer */ +/* pathetic. some stupid team of \PIPE\winreg writers got the concept */ +/* of a unicode string different from the other \PIPE\ writers */ +typedef struct uninotstr2_info +{ + uint32 uni_max_len; + uint32 undoc; + uint32 uni_buf_len; + uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */ + +} UNINOTSTR2; + +/* UNISTR2 - unicode string size (in uint16 unicode chars) and buffer */ +typedef struct unistr2_info +{ + uint32 uni_max_len; + uint32 undoc; + uint32 uni_str_len; + uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */ + +} UNISTR2; + +/* STRING2 - string size (in uint8 chars) and buffer */ +typedef struct string2_info +{ + uint32 str_max_len; + uint32 undoc; + uint32 str_str_len; + uint8 buffer[MAX_STRINGLEN]; /* uint8 characters. **NOT** necessarily null-terminated */ + +} STRING2; + + +/* DOM_RID2 - domain RID structure for ntlsa pipe */ +typedef struct domrid2_info +{ + uint32 type; /* value is 5 */ + uint32 undoc; /* value is non-zero */ + uint32 rid; + uint32 rid_idx; /* don't know what this is */ + +} DOM_RID2; + +/* DOM_RID3 - domain RID structure for samr pipe */ +typedef struct domrid3_info +{ + uint32 rid; /* domain-relative (to a SID) id */ + uint32 type1; /* value is 0x1 */ + uint32 ptr_type; /* undocumented pointer */ + uint32 type2; /* value is 0x1 */ + +} DOM_RID3; + +/* DOM_RID4 - rid + user attributes */ +typedef struct domrid4_info +{ + uint32 unknown; + uint16 attr; + uint32 rid; /* user RID */ + +} DOM_RID4; + +/* DOM_CLNT_SRV - client / server names */ +typedef struct clnt_srv_info +{ + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server name */ + uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_comp_name; /* client machine name */ + +} DOM_CLNT_SRV; + +/* DOM_LOG_INFO - login info */ +typedef struct log_info +{ + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server name */ + UNISTR2 uni_acct_name; /* account name */ + uint16 sec_chan; /* secure channel type */ + UNISTR2 uni_comp_name; /* client machine name */ + +} DOM_LOG_INFO; + +/* DOM_CLNT_INFO - client info */ +typedef struct clnt_info +{ + DOM_LOG_INFO login; + DOM_CRED cred; + +} DOM_CLNT_INFO; + +/* DOM_CLNT_INFO2 - client info */ +typedef struct clnt_info2 +{ + DOM_CLNT_SRV login; + uint32 ptr_cred; + DOM_CRED cred; + +} DOM_CLNT_INFO2; + +/* DOM_LOGON_ID - logon id */ +typedef struct logon_info +{ + uint32 low; + uint32 high; + +} DOM_LOGON_ID; + +/* ARC4_OWF */ +typedef struct arc4_owf_info +{ + uint8 data[16]; + +} ARC4_OWF; + + +/* DOM_GID - group id + user attributes */ +typedef struct gid_info +{ + uint32 g_rid; /* a group RID */ + uint32 attr; + +} DOM_GID; + +#define POL_HND_SIZE 20 + +/* POLICY_HND */ +typedef struct lsa_policy_info +{ + uint8 data[POL_HND_SIZE]; /* policy handle */ + +} POLICY_HND; + +#endif /* _RPC_MISC_H */ + diff --git a/source3/include/rpc_netlogon.h b/source3/include/rpc_netlogon.h new file mode 100644 index 0000000000..1808649328 --- /dev/null +++ b/source3/include/rpc_netlogon.h @@ -0,0 +1,372 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_NETLOGON_H /* _RPC_NETLOGON_H */ +#define _RPC_NETLOGON_H + + +/* NETLOGON pipe */ +#define NET_REQCHAL 0x04 +#define NET_SRVPWSET 0x06 +#define NET_SAMLOGON 0x02 +#define NET_SAMLOGOFF 0x03 +#define NET_AUTH2 0x0f +#define NET_LOGON_CTRL2 0x0e +#define NET_TRUST_DOM_LIST 0x13 + +/* Secure Channel types. used in NetrServerAuthenticate negotiation */ +#define SEC_CHAN_WKSTA 2 +#define SEC_CHAN_DOMAIN 4 + + +/* NET_USER_INFO_3 */ +typedef struct net_user_info_3 +{ + uint32 ptr_user_info; + + NTTIME logon_time; /* logon time */ + NTTIME logoff_time; /* logoff time */ + NTTIME kickoff_time; /* kickoff time */ + NTTIME pass_last_set_time; /* password last set time */ + NTTIME pass_can_change_time; /* password can change time */ + NTTIME pass_must_change_time; /* password must change time */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNIHDR hdr_full_name; /* user's full name unicode string header */ + UNIHDR hdr_logon_script; /* logon script unicode string header */ + UNIHDR hdr_profile_path; /* profile path unicode string header */ + UNIHDR hdr_home_dir; /* home directory unicode string header */ + UNIHDR hdr_dir_drive; /* home directory drive unicode string header */ + + uint16 logon_count; /* logon count */ + uint16 bad_pw_count; /* bad password count */ + + uint32 user_id; /* User ID */ + uint32 group_id; /* Group ID */ + uint32 num_groups; /* num groups */ + uint32 buffer_groups; /* undocumented buffer pointer to groups. */ + uint32 user_flgs; /* user flags */ + + uint8 user_sess_key[16]; /* unused user session key */ + + UNIHDR hdr_logon_srv; /* logon server unicode string header */ + UNIHDR hdr_logon_dom; /* logon domain unicode string header */ + + uint32 buffer_dom_id; /* undocumented logon domain id pointer */ + uint8 padding[40]; /* unused padding bytes. expansion room */ + + uint32 num_other_sids; /* 0 - num_sids */ + uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */ + + UNISTR2 uni_user_name; /* username unicode string */ + UNISTR2 uni_full_name; /* user's full name unicode string */ + UNISTR2 uni_logon_script; /* logon script unicode string */ + UNISTR2 uni_profile_path; /* profile path unicode string */ + UNISTR2 uni_home_dir; /* home directory unicode string */ + UNISTR2 uni_dir_drive; /* home directory drive unicode string */ + + uint32 num_groups2; /* num groups */ + DOM_GID gids[LSA_MAX_GROUPS]; /* group info */ + + UNISTR2 uni_logon_srv; /* logon server unicode string */ + UNISTR2 uni_logon_dom; /* logon domain unicode string */ + + DOM_SID2 dom_sid; /* domain SID */ + DOM_SID2 other_sids[LSA_MAX_SIDS]; /* undocumented - domain SIDs */ + +} NET_USER_INFO_3; + + +/******************************************************** + Logon Control Query + + query_level 0x1 - pdc status + query_level 0x3 - number of logon attempts. + + ********************************************************/ +/* NET_Q_LOGON_CTRL2 - LSA Netr Logon Control 2*/ +typedef struct net_q_logon_ctrl2_info +{ + uint32 ptr; /* undocumented buffer pointer */ + UNISTR2 uni_server_name; /* server name, starting with two '\'s */ + + uint32 function_code; /* 0x1 */ + uint32 query_level; /* 0x1, 0x3 */ + uint32 switch_value; /* 0x1 */ + +} NET_Q_LOGON_CTRL2; + +/* NETLOGON_INFO_1 - pdc status info, i presume */ +typedef struct netlogon_1_info +{ + uint32 flags; /* 0x0 - undocumented */ + uint32 pdc_status; /* 0x0 - undocumented */ + +} NETLOGON_INFO_1; + +/* NETLOGON_INFO_2 - pdc status info, plus trusted domain info */ +typedef struct netlogon_2_info +{ + uint32 flags; /* 0x0 - undocumented */ + uint32 pdc_status; /* 0x0 - undocumented */ + uint32 ptr_trusted_dc_name; /* pointer to trusted domain controller name */ + uint32 tc_status; /* 0x051f - ERROR_NO_LOGON_SERVERS */ + UNISTR2 uni_trusted_dc_name; /* unicode string - trusted dc name */ + +} NETLOGON_INFO_2; + +/* NETLOGON_INFO_3 - logon status info, i presume */ +typedef struct netlogon_3_info +{ + uint32 flags; /* 0x0 - undocumented */ + uint32 logon_attempts; /* number of logon attempts */ + uint32 reserved_1; /* 0x0 - undocumented */ + uint32 reserved_2; /* 0x0 - undocumented */ + uint32 reserved_3; /* 0x0 - undocumented */ + uint32 reserved_4; /* 0x0 - undocumented */ + uint32 reserved_5; /* 0x0 - undocumented */ + +} NETLOGON_INFO_3; + +/******************************************************* + Logon Control Response + + switch_value is same as query_level in request + *******************************************************/ + +/* NET_R_LOGON_CTRL2 - response to LSA Logon Control2 */ +typedef struct net_r_logon_ctrl2_info +{ + uint32 switch_value; /* 0x1, 0x3 */ + uint32 ptr; + + union + { + NETLOGON_INFO_1 info1; + NETLOGON_INFO_2 info2; + NETLOGON_INFO_3 info3; + + } logon; + + uint32 status; /* return code */ + +} NET_R_LOGON_CTRL2; + +/* NET_Q_TRUST_DOM_LIST - LSA Query Trusted Domains */ +typedef struct net_q_trust_dom_info +{ + uint32 ptr; /* undocumented buffer pointer */ + UNISTR2 uni_server_name; /* server name, starting with two '\'s */ + + uint32 function_code; /* 0x31 */ + +} NET_Q_TRUST_DOM_LIST; + +#define MAX_TRUST_DOMS 1 + +/* NET_R_TRUST_DOM_LIST - response to LSA Trusted Domains */ +typedef struct net_r_trust_dom_info +{ + UNISTR2 uni_trust_dom_name[MAX_TRUST_DOMS]; + + uint32 status; /* return code */ + +} NET_R_TRUST_DOM_LIST; + + +/* NEG_FLAGS */ +typedef struct neg_flags_info +{ + uint32 neg_flags; /* negotiated flags */ + +} NEG_FLAGS; + + +/* NET_Q_REQ_CHAL */ +typedef struct net_q_req_chal_info +{ + uint32 undoc_buffer; /* undocumented buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server unicode string */ + UNISTR2 uni_logon_clnt; /* logon client unicode string */ + DOM_CHAL clnt_chal; /* client challenge */ + +} NET_Q_REQ_CHAL; + + +/* NET_R_REQ_CHAL */ +typedef struct net_r_req_chal_info +{ + DOM_CHAL srv_chal; /* server challenge */ + + uint32 status; /* return code */ + +} NET_R_REQ_CHAL; + + + +/* NET_Q_AUTH_2 */ +typedef struct net_q_auth2_info +{ + DOM_LOG_INFO clnt_id; /* client identification info */ + DOM_CHAL clnt_chal; /* client-calculated credentials */ + + NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */ + +} NET_Q_AUTH_2; + + +/* NET_R_AUTH_2 */ +typedef struct net_r_auth2_info +{ + DOM_CHAL srv_chal; /* server-calculated credentials */ + NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */ + + uint32 status; /* return code */ + +} NET_R_AUTH_2; + + +/* NET_Q_SRV_PWSET */ +typedef struct net_q_srv_pwset_info +{ + DOM_CLNT_INFO clnt_id; /* client identification/authentication info */ + uint8 pwd[16]; /* new password - undocumented. */ + +} NET_Q_SRV_PWSET; + +/* NET_R_SRV_PWSET */ +typedef struct net_r_srv_pwset_info +{ + DOM_CRED srv_cred; /* server-calculated credentials */ + + uint32 status; /* return code */ + +} NET_R_SRV_PWSET; + +/* NET_ID_INFO_2 */ +typedef struct net_network_info_2 +{ + uint32 ptr_id_info2; /* pointer to id_info_2 */ + UNIHDR hdr_domain_name; /* domain name unicode header */ + uint32 param_ctrl; /* param control (0x2) */ + DOM_LOGON_ID logon_id; /* logon ID */ + UNIHDR hdr_user_name; /* user name unicode header */ + UNIHDR hdr_wksta_name; /* workstation name unicode header */ + uint8 lm_chal[8]; /* lan manager 8 byte challenge */ + STRHDR hdr_nt_chal_resp; /* nt challenge response */ + STRHDR hdr_lm_chal_resp; /* lm challenge response */ + + UNISTR2 uni_domain_name; /* domain name unicode string */ + UNISTR2 uni_user_name; /* user name unicode string */ + UNISTR2 uni_wksta_name; /* workgroup name unicode string */ + STRING2 nt_chal_resp; /* nt challenge response */ + STRING2 lm_chal_resp; /* lm challenge response */ + +} NET_ID_INFO_2; + +/* NET_ID_INFO_1 */ +typedef struct id_info_1 +{ + uint32 ptr_id_info1; /* pointer to id_info_1 */ + UNIHDR hdr_domain_name; /* domain name unicode header */ + uint32 param_ctrl; /* param control */ + DOM_LOGON_ID logon_id; /* logon ID */ + UNIHDR hdr_user_name; /* user name unicode header */ + UNIHDR hdr_wksta_name; /* workstation name unicode header */ + ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */ + ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */ + UNISTR2 uni_domain_name; /* domain name unicode string */ + UNISTR2 uni_user_name; /* user name unicode string */ + UNISTR2 uni_wksta_name; /* workgroup name unicode string */ + +} NET_ID_INFO_1; + +/* NET_ID_INFO_CTR */ +typedef struct net_id_info_ctr_info +{ + uint16 switch_value; + + union + { + NET_ID_INFO_1 id1; /* auth-level 1 - interactive user login */ + NET_ID_INFO_2 id2; /* auth-level 2 - workstation referred login */ + + } auth; + +} NET_ID_INFO_CTR; + +/* SAM_INFO - sam logon/off id structure */ +typedef struct sam_info +{ + DOM_CLNT_INFO2 client; + uint32 ptr_rtn_cred; /* pointer to return credentials */ + DOM_CRED rtn_cred; /* return credentials */ + uint16 logon_level; + NET_ID_INFO_CTR *ctr; + uint16 validation_level; + +} DOM_SAM_INFO; + +/* NET_Q_SAM_LOGON */ +typedef struct net_q_sam_logon_info +{ + DOM_SAM_INFO sam_id; + +} NET_Q_SAM_LOGON; + +/* NET_R_SAM_LOGON */ +typedef struct net_r_sam_logon_info +{ + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + + uint16 switch_value; /* 3 - indicates type of USER INFO */ + NET_USER_INFO_3 *user; + + uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + + uint32 status; /* return code */ + +} NET_R_SAM_LOGON; + + +/* NET_Q_SAM_LOGOFF */ +typedef struct net_q_sam_logoff_info +{ + DOM_SAM_INFO sam_id; + +} NET_Q_SAM_LOGOFF; + +/* NET_R_SAM_LOGOFF */ +typedef struct net_r_sam_logoff_info +{ + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + + uint32 status; /* return code */ + +} NET_R_SAM_LOGOFF; + + +#endif /* _RPC_NETLOGON_H */ + diff --git a/source3/include/rpc_reg.h b/source3/include/rpc_reg.h new file mode 100644 index 0000000000..28d11710cd --- /dev/null +++ b/source3/include/rpc_reg.h @@ -0,0 +1,141 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_REG_H /* _RPC_REG_H */ +#define _RPC_REG_H + + +/* winreg pipe defines */ +#define REG_OPEN_POLICY 0x02 +#define REG_OPEN_ENTRY 0x0f +#define REG_INFO 0x11 +#define REG_CLOSE 0x05 + +/* REG_Q_OPEN_POLICY */ +typedef struct q_reg_open_policy_info +{ + uint32 ptr; + uint16 unknown_0; /* 0x5da0 - 16 bit unknown */ + uint32 level; /* 0x0000 0001 - 32 bit unknown */ + uint16 unknown_1; /* 0x0200 - 16 bit unknown */ + +} REG_Q_OPEN_POLICY; + +/* REG_R_OPEN_POLICY */ +typedef struct r_reg_open_policy_info +{ + POLICY_HND pol; /* policy handle */ + uint32 status; /* return status */ + +} REG_R_OPEN_POLICY; + + +/* REG_Q_CLOSE */ +typedef struct reg_q_close_info +{ + POLICY_HND pol; /* policy handle */ + +} REG_Q_CLOSE; + +/* REG_R_CLOSE */ +typedef struct reg_r_close_info +{ + POLICY_HND pol; /* policy handle. should be all zeros. */ + + uint32 status; /* return code */ + +} REG_R_CLOSE; + + +/* REG_Q_INFO */ +typedef struct q_reg_info_info +{ + POLICY_HND pol; /* policy handle */ + + UNIHDR hdr_type; /* unicode product type header */ + UNISTR2 uni_type; /* unicode product type - "ProductType" */ + + uint32 ptr1; /* pointer */ + NTTIME time; /* current time? */ + uint8 major_version1; /* 0x4 - os major version? */ + uint8 minor_version1; /* 0x1 - os minor version? */ + uint8 pad1[10]; /* padding - zeros */ + + uint32 ptr2; /* pointer */ + uint8 major_version2; /* 0x4 - os major version? */ + uint8 minor_version2; /* 0x1 - os minor version? */ + uint8 pad2[2]; /* padding - zeros */ + + uint32 ptr3; /* pointer */ + uint32 unknown; /* 0x0000 0000 */ + +} REG_Q_INFO; + +/* REG_R_INFO */ +typedef struct r_reg_info_info +{ + uint32 ptr1; /* buffer pointer */ + uint32 level; /* 0x1 - info level? */ + + uint32 ptr_type; /* pointer to o/s type */ + UNINOTSTR2 uni_type; /* unicode string o/s type - "LanmanNT" */ + + uint32 ptr2; /* pointer to unknown_0 */ + uint32 unknown_0; /* 0x12 */ + + uint32 ptr3; /* pointer to unknown_1 */ + uint32 unknown_1; /* 0x12 */ + + uint32 status; /* return status */ + +} REG_R_INFO; + + +/* REG_Q_OPEN_ENTRY */ +typedef struct q_reg_open_entry_info +{ + POLICY_HND pol; /* policy handle */ + + UNIHDR hdr_name; /* unicode registry string header */ + UNISTR2 uni_name; /* unicode registry string name */ + + uint32 unknown_0; /* 32 bit unknown - 0x0000 0000 */ + uint16 unknown_1; /* 16 bit unknown - 0x0000 */ + uint16 unknown_2; /* 16 bit unknown - 0x0200 */ + +} REG_Q_OPEN_ENTRY; + + + +/* REG_R_OPEN_ENTRY */ +typedef struct r_reg_open_entry_info +{ + POLICY_HND pol; /* policy handle */ + uint32 status; /* return status */ + +} REG_R_OPEN_ENTRY; + + + +#endif /* _RPC_REG_H */ + diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h new file mode 100644 index 0000000000..bcce64b6be --- /dev/null +++ b/source3/include/rpc_samr.h @@ -0,0 +1,1023 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_SAMR_H /* _RPC_SAMR_H */ +#define _RPC_SAMR_H + + +#include "rpc_misc.h" + + +/******************************************************************* + the following information comes from a QuickView on samsrv.dll, + and gives an idea of exactly what is needed: + +SamrAddMemberToAlias +SamrAddMemberToGroup +SamrAddMultipleMembersToAlias +SamrChangePasswordUser +x SamrCloseHandle +x SamrConnect +SamrCreateAliasInDomain +SamrCreateGroupInDomain +SamrCreateUserInDomain +SamrDeleteAlias +SamrDeleteGroup +SamrDeleteUser +x SamrEnumerateAliasesInDomain +SamrEnumerateDomainsInSamServer +x SamrEnumerateGroupsInDomain +x SamrEnumerateUsersInDomain +SamrGetUserDomainPasswordInformation +SamrLookupDomainInSamServer +? SamrLookupIdsInDomain +x SamrLookupNamesInDomain +x SamrOpenAlias +x SamrOpenDomain +SamrOpenGroup +x SamrOpenUser +x SamrQueryDisplayInformation +x SamrQueryInformationAlias +SamrQueryInformationDomain +? SamrQueryInformationUser +SamrQuerySecurityObject +SamrRemoveMemberFromAlias +SamrRemoveMemberFromForiegnDomain +SamrRemoveMemberFromGroup +SamrRemoveMultipleMembersFromAlias +SamrSetInformationAlias +SamrSetInformationDomain +SamrSetInformationGroup +SamrSetInformationUser +SamrSetMemberAttributesOfGroup +SamrSetSecurityObject +SamrShutdownSamServer +SamrTestPrivateFunctionsDomain +SamrTestPrivateFunctionsUser + +********************************************************************/ + +#define SAMR_CLOSE_HND 0x01 +#define SAMR_OPEN_DOMAIN 0x07 +#define SAMR_UNKNOWN_8 0x08 +#define SAMR_LOOKUP_IDS 0x10 +#define SAMR_LOOKUP_NAMES 0x11 +#define SAMR_UNKNOWN_3 0x03 +#define SAMR_QUERY_DISPINFO 0x28 +#define SAMR_OPEN_USER 0x22 +#define SAMR_QUERY_USERINFO 0x24 +#define SAMR_QUERY_USERGROUPS 0x27 +#define SAMR_UNKNOWN_12 0x12 +#define SAMR_UNKNOWN_21 0x21 +#define SAMR_UNKNOWN_32 0x32 +#define SAMR_UNKNOWN_34 0x34 +#define SAMR_CONNECT 0x39 +#define SAMR_OPEN_ALIAS 0x1b +#define SAMR_QUERY_ALIASINFO 0x1c +#define SAMR_ENUM_DOM_USERS 0x0d +#define SAMR_ENUM_DOM_ALIASES 0x0f +#define SAMR_ENUM_DOM_GROUPS 0x30 + + +typedef struct logon_hours_info +{ + uint32 len; /* normally 21 bytes */ + uint8 hours[32]; + +} LOGON_HRS; + +/* SAM_USER_INFO_21 */ +typedef struct sam_user_info_21 +{ + NTTIME logon_time; /* logon time */ + NTTIME logoff_time; /* logoff time */ + NTTIME kickoff_time; /* kickoff time */ + NTTIME pass_last_set_time; /* password last set time */ + NTTIME pass_can_change_time; /* password can change time */ + NTTIME pass_must_change_time; /* password must change time */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNIHDR hdr_full_name; /* user's full name unicode string header */ + UNIHDR hdr_home_dir; /* home directory unicode string header */ + UNIHDR hdr_dir_drive; /* home drive unicode string header */ + UNIHDR hdr_logon_script; /* logon script unicode string header */ + UNIHDR hdr_profile_path; /* profile path unicode string header */ + UNIHDR hdr_acct_desc ; /* user description */ + UNIHDR hdr_workstations; /* comma-separated workstations user can log in from */ + UNIHDR hdr_unknown_str ; /* don't know what this is, yet. */ + UNIHDR hdr_munged_dial ; /* munged path name and dial-back tel number */ + + uint8 lm_pwd[16]; /* lm user passwords */ + uint8 nt_pwd[16]; /* nt user passwords */ + + uint32 user_rid; /* Primary User ID */ + uint32 group_rid; /* Primary Group ID */ + + uint16 acb_info; /* account info (ACB_xxxx bit-mask) */ + /* uint8 pad[2] */ + + uint32 unknown_3; /* 0x00ff ffff */ + + uint16 logon_divs; /* 0x0000 00a8 which is 168 which is num hrs in a week */ + /* uint8 pad[2] */ + uint32 ptr_logon_hrs; /* unknown pointer */ + + uint32 unknown_5; /* 0x0002 0000 */ + + uint8 padding1[8]; + + UNISTR2 uni_user_name; /* username unicode string */ + UNISTR2 uni_full_name; /* user's full name unicode string */ + UNISTR2 uni_home_dir; /* home directory unicode string */ + UNISTR2 uni_dir_drive; /* home directory drive unicode string */ + UNISTR2 uni_logon_script; /* logon script unicode string */ + UNISTR2 uni_profile_path; /* profile path unicode string */ + UNISTR2 uni_acct_desc ; /* user description unicode string */ + UNISTR2 uni_workstations; /* login from workstations unicode string */ + UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */ + UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */ + + uint32 unknown_6; /* 0x0000 04ec */ + uint32 padding4; + + LOGON_HRS logon_hrs; + +} SAM_USER_INFO_21; + + +/* SAM_USER_INFO_11 */ +typedef struct sam_user_info_11 +{ + uint8 padding_0[16]; /* 0 - padding 16 bytes */ + NTTIME expiry; /* expiry time or something? */ + uint8 padding_1[24]; /* 0 - padding 24 bytes */ + + UNIHDR hdr_mach_acct; /* unicode header for machine account */ + uint32 padding_2; /* 0 - padding 4 bytes */ + + uint32 ptr_1; /* pointer */ + uint8 padding_3[32]; /* 0 - padding 32 bytes */ + uint32 padding_4; /* 0 - padding 4 bytes */ + + uint32 ptr_2; /* pointer */ + uint32 padding_5; /* 0 - padding 4 bytes */ + + uint32 ptr_3; /* pointer */ + uint8 padding_6[32]; /* 0 - padding 32 bytes */ + + uint32 rid_user; /* user RID */ + uint32 rid_group; /* group RID */ + + uint16 acct_ctrl; /* 0080 - ACB_XXXX */ + uint16 unknown_3; /* 16 bit padding */ + + uint16 unknown_4; /* 0x003f - 16 bit unknown */ + uint16 unknown_5; /* 0x003c - 16 bit unknown */ + + uint8 padding_7[16]; /* 0 - padding 16 bytes */ + uint32 padding_8; /* 0 - padding 4 bytes */ + + UNISTR2 uni_mach_acct; /* unicode string for machine account */ + + uint8 padding_9[48]; /* 0 - padding 48 bytes */ + +} SAM_USER_INFO_11; + + +/* SAM_USER_INFO_10 */ +typedef struct sam_user_info_10 +{ + uint32 rid_group; + +} SAM_USER_INFO_10; + + + +/* SAMR_Q_CLOSE_HND - probably a policy handle close */ +typedef struct q_samr_close_hnd_info +{ + POLICY_HND pol; /* policy handle */ + +} SAMR_Q_CLOSE_HND; + + +/* SAMR_R_CLOSE_HND - probably a policy handle close */ +typedef struct r_samr_close_hnd_info +{ + POLICY_HND pol; /* policy handle */ + uint32 status; /* return status */ + +} SAMR_R_CLOSE_HND; + + +/**************************************************************************** +SAMR_Q_UNKNOWN_3 - info level 4. returns SIDs. +*****************************************************************************/ + +/* SAMR_Q_UNKNOWN_3 - probably get domain info... */ +typedef struct q_samr_unknown_3_info +{ + POLICY_HND user_pol; /* policy handle */ + uint16 switch_value; /* 0x0000 0004 */ + /* uint8 pad[2] */ + +} SAMR_Q_UNKNOWN_3; + +/* DOM_SID3 example: + 0x14 0x035b 0x0002 S-1-1 + 0x18 0x07ff 0x000f S-1-5-20-DOMAIN_ALIAS_RID_ADMINS + 0x18 0x07ff 0x000f S-1-5-20-DOMAIN_ALIAS_RID_ACCOUNT_OPS + 0x24 0x0044 0x0002 S-1-5-21-nnn-nnn-nnn-0x03f1 + */ + +/* DOM_SID3 example: + 0x24 0x0044 0x0002 S-1-5-21-nnn-nnn-nnn-0x03ee + 0x18 0x07ff 0x000f S-1-5-20-DOMAIN_ALIAS_RID_ADMINS + 0x14 0x035b 0x0002 S-1-1 + */ + +/* DOM_SID3 - security id */ +typedef struct sid_info_3 +{ + uint16 len; /* length, bytes, including length of len :-) */ + /* uint8 pad[2]; */ + + DOM_SID sid; + +} DOM_SID3; + + +#define MAX_SAM_SIDS 15 + +/* SAM_SID_STUFF */ +typedef struct sid_stuff_info +{ + uint16 unknown_2; /* 0x0001 */ + uint16 unknown_3; /* 0x8004 */ + + uint8 padding1[8]; + + uint32 unknown_4; /* 0x0000 0014 */ + uint32 unknown_5; /* 0x0000 0014 */ + + uint16 unknown_6; /* 0x0002 */ + uint16 unknown_7; /* 0x5800 */ + + uint32 num_sids; + + uint16 padding2; + + DOM_SID3 sid[MAX_SAM_SIDS]; + +} SAM_SID_STUFF; + +/* SAMR_R_UNKNOWN_3 - probably an open */ +typedef struct r_samr_unknown_3_info +{ + uint32 ptr_0; + uint32 sid_stuff_len0; + + uint32 ptr_1; + uint32 sid_stuff_len1; + + SAM_SID_STUFF sid_stuff; + + uint32 status; /* return status */ + +} SAMR_R_UNKNOWN_3; + + +/**************************************************************************** +SAMR_Q_UNKNOWN_8 - probably a query on domain group info. +*****************************************************************************/ + +/* SAMR_Q_UNKNOWN_8 - */ +typedef struct q_samr_unknown_8_info +{ + POLICY_HND domain_pol; /* policy handle */ + uint16 switch_value; /* 0x0002 */ + +} SAMR_Q_UNKNOWN_8; + +typedef struct sam_unkown_info_2_info +{ + uint32 unknown_0; /* 0x0000 0000 */ + uint32 unknown_1; /* 0x0000 0000 */ + uint32 unknown_2; /* 0x8000 0000 */ + uint32 unknown_3; /* 0x0000 0000 */ + + uint32 ptr_0; /* pointer to unknown structure */ + UNIHDR hdr_domain; /* domain name unicode header */ + UNIHDR hdr_server; /* server name unicode header */ + + /* put all the data in here, at the moment, including what the above + pointer is referring to + */ + + uint32 unknown_4; /* 0x0000 0099 */ + uint32 unknown_5; /* 0x0000 0000 */ + + uint32 unknown_6 ; /* 0x0000 0001 */ + uint32 unknown_7 ; /* 0x0000 0003 */ + uint32 unknown_8 ; /* 0x0000 0001 */ + uint32 unknown_9 ; /* 0x0000 0008 */ + uint32 unknown_10; /* 0x0000 0003 */ + + uint8 padding[16]; /* 16 bytes zeros */ + + UNISTR2 uni_domain; /* domain name unicode string */ + UNISTR2 uni_server; /* server name unicode string */ + +} SAM_UNK_INFO_2; + + +typedef struct sam_unknown_ctr_info +{ + union + { + SAM_UNK_INFO_2 inf2; + + } info; + +} SAM_UNK_CTR; + + +/* SAMR_R_UNKNOWN_8 - */ +typedef struct r_samr_unknown_8_info +{ + uint32 ptr_1; + uint16 switch_value; /* same as in query */ + + SAM_UNK_CTR *ctr; + + uint32 status; /* return status */ + +} SAMR_R_UNKNOWN_8; + + +/**************************************************************************** +SAMR_Q_OPEN_DOMAIN - unknown_0 values seen associated with SIDs: + +0x0000 03f1 and a specific domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0 +0x0000 0200 and a specific domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0 +*****************************************************************************/ + +/* SAMR_Q_OPEN_DOMAIN */ +typedef struct q_samr_open_domain_info +{ + POLICY_HND connect_pol; /* policy handle */ + uint32 rid; /* 0x2000 0000; 0x0000 0211; 0x0000 0280; 0x0000 0200 - a RID? */ + DOM_SID2 dom_sid; /* domain SID */ + +} SAMR_Q_OPEN_DOMAIN; + + +/* SAMR_R_OPEN_DOMAIN - probably an open */ +typedef struct r_samr_open_domain_info +{ + POLICY_HND domain_pol; /* policy handle associated with the SID */ + uint32 status; /* return status */ + +} SAMR_R_OPEN_DOMAIN; + + +#define MAX_SAM_ENTRIES 250 + +typedef struct samr_entry_info +{ + uint32 rid; + UNIHDR hdr_name; + +} SAM_ENTRY; + +/* SAMR_Q_ENUM_DOM_USERS - SAM rids and names */ +typedef struct q_samr_enum_dom_users_info +{ + POLICY_HND pol; /* policy handle */ + + uint16 req_num_entries; /* number of values (0 indicates unlimited?) */ + uint16 unknown_0; /* enumeration context? */ + uint16 acb_mask; /* 0x0000 indicates all */ + uint16 unknown_1; /* 0x0000 */ + + uint32 max_size; /* 0x0000 ffff */ + +} SAMR_Q_ENUM_DOM_USERS; + + +/* SAMR_R_ENUM_DOM_USERS - SAM rids and names */ +typedef struct r_samr_enum_dom_users_info +{ + uint16 total_num_entries; /* number of entries that match without the acb mask */ + uint16 unknown_0; /* same as unknown_0 (enum context?) in request */ + uint32 ptr_entries1; /* actual number of entries to follow, having masked some out */ + + uint32 num_entries2; + uint32 ptr_entries2; + + uint32 num_entries3; + + SAM_ENTRY sam[MAX_SAM_ENTRIES]; + UNISTR2 uni_acct_name[MAX_SAM_ENTRIES]; + + uint32 num_entries4; + + uint32 status; + +} SAMR_R_ENUM_DOM_USERS; + + +typedef struct samr_entry_info3 +{ + uint32 grp_idx; + + uint32 rid_grp; + uint32 attr; + + UNIHDR hdr_grp_name; + UNIHDR hdr_grp_desc; + +} SAM_ENTRY3; + +typedef struct samr_str_entry_info3 +{ + UNISTR2 uni_grp_name; + UNISTR2 uni_grp_desc; + +} SAM_STR3; + +/* SAMR_Q_ENUM_DOM_GROUPS - SAM rids and names */ +typedef struct q_samr_enum_dom_groups_info +{ + POLICY_HND pol; /* policy handle */ + + /* these are possibly an enumeration context handle... */ + uint16 switch_level; /* 0x0003 */ + uint16 unknown_0; /* 0x0000 */ + uint32 start_idx; /* presumably the start enumeration index */ + uint32 unknown_1; /* 0x0000 07d0 */ + + uint32 max_size; /* 0x0000 7fff */ + +} SAMR_Q_ENUM_DOM_GROUPS; + + +/* SAMR_R_ENUM_DOM_GROUPS - SAM rids and names */ +typedef struct r_samr_enum_dom_groups_info +{ + uint32 unknown_0; /* 0x0000 0492 or 0x0000 00be */ + uint32 unknown_1; /* 0x0000 049a or 0x0000 00be */ + uint32 switch_level; /* 0x0000 0003 */ + + uint32 num_entries; + uint32 ptr_entries; + + uint32 num_entries2; + + SAM_ENTRY3 sam[MAX_SAM_ENTRIES]; + SAM_STR3 str[MAX_SAM_ENTRIES]; + + uint32 status; + +} SAMR_R_ENUM_DOM_GROUPS; + + + +/* SAMR_Q_ENUM_DOM_ALIASES - SAM rids and names */ +typedef struct q_samr_enum_dom_aliases_info +{ + POLICY_HND pol; /* policy handle */ + + /* this is possibly an enumeration context handle... */ + uint32 unknown_0; /* 0x0000 0000 */ + + uint32 max_size; /* 0x0000 ffff */ + +} SAMR_Q_ENUM_DOM_ALIASES; + +/* SAMR_R_ENUM_DOM_ALIASES - SAM rids and names */ +typedef struct r_samr_enum_dom_aliases_info +{ + uint32 num_entries; + uint32 ptr_entries; + + uint32 num_entries2; + uint32 ptr_entries2; + + uint32 num_entries3; + + SAM_ENTRY sam[MAX_SAM_ENTRIES]; + UNISTR2 uni_grp_name[MAX_SAM_ENTRIES]; + + uint32 num_entries4; + + uint32 status; + +} SAMR_R_ENUM_DOM_ALIASES; + + + +/* SAMR_Q_QUERY_DISPINFO - SAM rids, names and descriptions */ +typedef struct q_samr_query_disp_info +{ + POLICY_HND pol; /* policy handle */ + + uint16 switch_level; /* 0x0001 and 0x0002 seen */ + uint16 unknown_0; /* 0x0000 and 0x2000 seen */ + uint32 start_idx; /* presumably the start enumeration index */ + uint32 unknown_1; /* 0x0000 07d0, 0x0000 0400 and 0x0000 0200 seen */ + + uint32 max_size; /* 0x0000 7fff, 0x0000 7ffe and 0x0000 3fff seen*/ + +} SAMR_Q_QUERY_DISPINFO; + +typedef struct samr_entry_info1 +{ + uint32 user_idx; + + uint32 rid_user; + uint16 acb_info; + uint16 pad; + + UNIHDR hdr_acct_name; + UNIHDR hdr_user_name; + UNIHDR hdr_user_desc; + +} SAM_ENTRY1; + +typedef struct samr_str_entry_info1 +{ + UNISTR2 uni_acct_name; + UNISTR2 uni_full_name; + UNISTR2 uni_acct_desc; + +} SAM_STR1; + +typedef struct sam_entry_info_1 +{ + uint32 num_entries; + uint32 ptr_entries; + uint32 num_entries2; + + SAM_ENTRY1 sam[MAX_SAM_ENTRIES]; + SAM_STR1 str[MAX_SAM_ENTRIES]; + + +} SAM_INFO_1; + +typedef struct samr_entry_info2 +{ + uint32 user_idx; + + uint32 rid_user; + uint16 acb_info; + uint16 pad; + + UNIHDR hdr_srv_name; + UNIHDR hdr_srv_desc; + +} SAM_ENTRY2; + +typedef struct samr_str_entry_info2 +{ + UNISTR2 uni_srv_name; + UNISTR2 uni_srv_desc; + +} SAM_STR2; + +typedef struct sam_entry_info_2 +{ + uint32 num_entries; + uint32 ptr_entries; + uint32 num_entries2; + + SAM_ENTRY2 sam[MAX_SAM_ENTRIES]; + SAM_STR2 str[MAX_SAM_ENTRIES]; + +} SAM_INFO_2; + +typedef struct sam_info_ctr_info +{ + union + { + SAM_INFO_1 *info1; /* server info */ + SAM_INFO_2 *info2; /* user info */ + void *info; /* allows assignment without typecasting, */ + + } sam; + +} SAM_INFO_CTR; + +/* SAMR_R_QUERY_DISPINFO - SAM rids, names and descriptions */ +typedef struct r_samr_query_dispinfo_info +{ + uint32 unknown_0; /* container length? 0x0000 0492 or 0x0000 00be */ + uint32 unknown_1; /* container length? 0x0000 049a or 0x0000 00be */ + uint16 switch_level; /* 0x0001 or 0x0002 */ + /*uint8 pad[2] */ + + SAM_INFO_CTR *ctr; + + uint32 status; + +} SAMR_R_QUERY_DISPINFO; + + + +/* SAMR_Q_QUERY_ALIASINFO - SAM Alias Info */ +typedef struct q_samr_enum_alias_info +{ + POLICY_HND pol; /* policy handle */ + + uint16 switch_level; /* 0x0003 seen */ + +} SAMR_Q_QUERY_ALIASINFO; + +typedef struct samr_alias_info3 +{ + UNIHDR hdr_acct_desc; + UNISTR2 uni_acct_desc; + +} ALIAS_INFO3; + +/* SAMR_R_QUERY_ALIASINFO - SAM rids, names and descriptions */ +typedef struct r_samr_query_aliasinfo_info +{ + uint32 ptr; + uint16 switch_value; /* 0x0003 */ + /* uint8[2] padding */ + + union + { + ALIAS_INFO3 info3; + + } alias; + + uint32 status; + +} SAMR_R_QUERY_ALIASINFO; + + +/* SAMR_Q_QUERY_USERGROUPS - */ +typedef struct q_samr_query_usergroup_info +{ + POLICY_HND pol; /* policy handle associated with unknown id */ + +} SAMR_Q_QUERY_USERGROUPS; + +/* SAMR_R_QUERY_USERGROUPS - probably a get sam info */ +typedef struct r_samr_query_usergroup_info +{ + uint32 ptr_0; /* pointer */ + uint32 num_entries; /* number of RID groups */ + uint32 ptr_1; /* pointer */ + uint32 num_entries2; /* number of RID groups */ + + DOM_GID *gid; /* group info */ + + uint32 status; /* return status */ + +} SAMR_R_QUERY_USERGROUPS; + + +/* SAMR_Q_QUERY_USERINFO - probably a get sam info */ +typedef struct q_samr_query_user_info +{ + POLICY_HND pol; /* policy handle associated with unknown id */ + uint16 switch_value; /* 0x0015, 0x0011 or 0x0010 - 16 bit unknown */ + +} SAMR_Q_QUERY_USERINFO; + +/* SAMR_R_QUERY_USERINFO - probably a get sam info */ +typedef struct r_samr_query_user_info +{ + uint32 ptr; /* pointer */ + uint16 switch_value; /* 0x0015, 0x0011 or 0x0010 - same as in query */ + /* uint8[2] padding. */ + + union + { + SAM_USER_INFO_10 *id10; /* auth-level 0x10 */ + SAM_USER_INFO_11 *id11; /* auth-level 0x11 */ + SAM_USER_INFO_21 *id21; /* auth-level 21 */ + void* id; /* to make typecasting easy */ + + } info; + + uint32 status; /* return status */ + +} SAMR_R_QUERY_USERINFO; + + +/**************************************************************************** +SAMR_Q_LOOKUP_IDS - do a conversion from name to RID. + +the policy handle allocated by an "samr open secret" call is associated +with a SID. this policy handle is what is queried here, *not* the SID +itself. the response to the lookup rids is relative to this SID. +*****************************************************************************/ +/* SAMR_Q_LOOKUP_IDS */ +typedef struct q_samr_lookup_ids_info +{ + POLICY_HND pol; /* policy handle */ + + uint32 num_sids1; /* number of rids being looked up */ + uint32 ptr; /* buffer pointer */ + uint32 num_sids2; /* number of rids being looked up */ + + uint32 ptr_sid[MAX_LOOKUP_SIDS]; /* pointers to sids to be looked up */ + DOM_SID2 sid [MAX_LOOKUP_SIDS]; /* sids to be looked up. */ + +} SAMR_Q_LOOKUP_IDS; + + +/* SAMR_R_LOOKUP_IDS */ +typedef struct r_samr_lookup_ids_info +{ + uint32 num_entries; + uint32 ptr; /* undocumented buffer pointer */ + + uint32 num_entries2; + uint32 rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ + + uint32 status; /* return code */ + +} SAMR_R_LOOKUP_IDS; + + +/**************************************************************************** +SAMR_Q_LOOKUP_NAMES - do a conversion from SID to RID. + +the policy handle allocated by an "samr open secret" call is associated +with a SID. this policy handle is what is queried here, *not* the SID +itself. the response to the lookup rids is relative to this SID. +*****************************************************************************/ +/* SAMR_Q_LOOKUP_NAMES */ +typedef struct q_samr_lookup_names_info +{ + POLICY_HND pol; /* policy handle */ + + uint32 num_rids1; /* number of rids being looked up */ + uint32 rid; /* 0x0000 03e8 - RID of the server doing the query? */ + uint32 ptr; /* 0x0000 0000 - 32 bit unknown */ + uint32 num_rids2; /* number of rids being looked up */ + + UNIHDR hdr_user_name[MAX_LOOKUP_SIDS]; /* unicode account name header */ + UNISTR2 uni_user_name[MAX_LOOKUP_SIDS]; /* unicode account name string */ + +} SAMR_Q_LOOKUP_NAMES; + + +/* SAMR_R_LOOKUP_NAMES */ +typedef struct r_samr_lookup_names_info +{ + uint32 num_entries; + uint32 undoc_buffer; /* undocumented buffer pointer */ + + uint32 num_entries2; + DOM_RID3 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ + + uint32 num_entries3; + + uint32 status; /* return code */ + +} SAMR_R_LOOKUP_NAMES; + + +/**************************************************************************** +SAMR_Q_UNKNOWN_12 - do a conversion from RID groups to something. + +called to resolve domain RID groups. +*****************************************************************************/ +/* SAMR_Q_UNKNOWN_12 */ +typedef struct q_samr_unknown_12_info +{ + POLICY_HND pol; /* policy handle */ + + uint32 num_gids1; /* number of rids being looked up */ + uint32 rid; /* 0x0000 03e8 - RID of the server doing the query? */ + uint32 ptr; /* 0x0000 0000 - 32 bit unknown */ + uint32 num_gids2; /* number of rids being looked up */ + + uint32 gid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ + +} SAMR_Q_UNKNOWN_12; + + +/**************************************************************************** +SAMR_R_UNKNOWN_12 - do a conversion from group RID to names + +*****************************************************************************/ +/* SAMR_R_UNKNOWN_12 */ +typedef struct r_samr_unknown_12_info +{ + POLICY_HND pol; /* policy handle */ + + uint32 num_aliases1; /* number of aliases being looked up */ + uint32 ptr_aliases; /* pointer to aliases */ + uint32 num_aliases2; /* number of aliases being looked up */ + + UNIHDR hdr_als_name[MAX_LOOKUP_SIDS]; /* unicode account name header */ + UNISTR2 uni_als_name[MAX_LOOKUP_SIDS]; /* unicode account name string */ + + uint32 num_als_usrs1; /* number of users in aliases being looked up */ + uint32 ptr_als_usrs; /* pointer to users in aliases */ + uint32 num_als_usrs2; /* number of users in aliases being looked up */ + + uint32 num_als_usrs[MAX_LOOKUP_SIDS]; /* number of users per group */ + + uint32 status; + +} SAMR_R_UNKNOWN_12; + + +/* SAMR_Q_OPEN_USER - probably an open */ +typedef struct q_samr_open_user_info +{ + POLICY_HND domain_pol; /* policy handle */ + uint32 unknown_0; /* 32 bit unknown - 0x02011b */ + uint32 user_rid; /* user RID */ + +} SAMR_Q_OPEN_USER; + + +/* SAMR_R_OPEN_USER - probably an open */ +typedef struct r_samr_open_user_info +{ + POLICY_HND user_pol; /* policy handle associated with unknown id */ + uint32 status; /* return status */ + +} SAMR_R_OPEN_USER; + + +/* SAMR_Q_UNKNOWN_13 - probably an open alias in domain */ +typedef struct q_samr_unknown_13_info +{ + POLICY_HND alias_pol; /* policy handle */ + + uint16 unknown_1; /* 16 bit unknown - 0x0200 */ + uint16 unknown_2; /* 16 bit unknown - 0x0000 */ + +} SAMR_Q_UNKNOWN_13; + + +/* SAMR_Q_UNKNOWN_21 - probably an open group in domain */ +typedef struct q_samr_unknown_21_info +{ + POLICY_HND group_pol; /* policy handle */ + + uint16 unknown_1; /* 16 bit unknown - 0x0477 */ + uint16 unknown_2; /* 16 bit unknown - 0x0000 */ + +} SAMR_Q_UNKNOWN_21; + + +/* SAMR_Q_UNKNOWN_32 - probably a "create SAM entry" */ +typedef struct q_samr_unknown_32_info +{ + POLICY_HND pol; /* policy handle */ + + UNIHDR hdr_mach_acct; /* unicode machine account name header */ + UNISTR2 uni_mach_acct; /* unicode machine account name */ + + uint32 acct_ctrl; /* 32 bit ACB_XXXX */ + uint16 unknown_1; /* 16 bit unknown - 0x00B0 */ + uint16 unknown_2; /* 16 bit unknown - 0xe005 */ + +} SAMR_Q_UNKNOWN_32; + + +/* SAMR_R_UNKNOWN_32 - probably a "create SAM entry" */ +typedef struct r_samr_unknown_32_info +{ + POLICY_HND pol; /* policy handle */ + + /* rid4.unknown - fail: 0030 success: 0x03ff */ + DOM_RID4 rid4; /* rid and attributes */ + + uint32 status; /* return status - fail: 0xC000 0099: user exists */ + +} SAMR_R_UNKNOWN_32; + + +/* SAMR_Q_OPEN_ALIAS - probably an open */ +typedef struct q_samr_open_alias_info +{ + uint32 unknown_0; /* 0x0000 0008 */ + uint32 rid_alias; /* rid */ + +} SAMR_Q_OPEN_ALIAS; + + +/* SAMR_R_OPEN_ALIAS - probably an open */ +typedef struct r_samr_open_alias_info +{ + POLICY_HND pol; /* policy handle */ + uint32 status; /* return status */ + +} SAMR_R_OPEN_ALIAS; + + +/* SAMR_Q_CONNECT - probably an open */ +typedef struct q_samr_connect_info +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */ + + uint32 unknown_0; /* 32 bit unknown */ + +} SAMR_Q_CONNECT; + + +/* SAMR_R_CONNECT - probably an open */ +typedef struct r_samr_connect_info +{ + POLICY_HND connect_pol; /* policy handle */ + uint32 status; /* return status */ + +} SAMR_R_CONNECT; + +/* SAMR_Q_UNKNOWN_38 */ +typedef struct q_samr_unknown_38 +{ + uint32 ptr; + UNIHDR hdr_srv_name; + UNISTR2 uni_srv_name; + +} SAMR_Q_UNKNOWN_38; + +/* SAMR_R_UNKNOWN_38 */ +typedef struct r_samr_unknown_38 +{ + LOOKUP_LEVEL level; /* 0x0006 */ + uint32 ptr_0; /* 0x0000 0000 */ + uint32 status; + +} SAMR_R_UNKNOWN_38; + +/* SAMR_ENC_PASSWD */ +typedef struct enc_passwd_info +{ + uint32 ptr; + uint8 pass[516]; + +} SAMR_ENC_PASSWD; + +/* SAMR_ENC_HASH */ +typedef struct enc_hash_info +{ + uint32 ptr; + uint8 hash[16]; + +} SAMR_ENC_HASH; + +/* SAMR_Q_CHGPASSWD_USER */ +typedef struct q_samr_chgpasswd_user_info +{ + uint32 ptr_0; + + UNIHDR hdr_server; /* server name unicode header */ + UNISTR2 uni_server; /* server name unicode string */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNISTR2 uni_user_name; /* username unicode string */ + + SAMR_ENC_PASSWD nt_newpass; + SAMR_ENC_HASH nt_oldhash; + + uint32 unknown_1; /* seems to always contain 0001 */ + + SAMR_ENC_PASSWD lm_newpass; + SAMR_ENC_HASH lm_oldhash; + +} SAMR_Q_CHGPASSWD_USER; + +/* SAMR_R_CHGPASSWD_USER */ +typedef struct r_samr_chgpasswd_user_info +{ + uint32 result; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */ + +} SAMR_R_CHGPASSWD_USER; + +#endif /* _RPC_SAMR_H */ + diff --git a/source3/include/rpc_srvsvc.h b/source3/include/rpc_srvsvc.h new file mode 100644 index 0000000000..4d11b915e4 --- /dev/null +++ b/source3/include/rpc_srvsvc.h @@ -0,0 +1,540 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_SRVSVC_H /* _RPC_SRVSVC_H */ +#define _RPC_SRVSVC_H + + +/* srvsvc pipe */ +#define SRV_NETCONNENUM 0x08 +#define SRV_NETFILEENUM 0x09 +#define SRV_NETSESSENUM 0x0c +#define SRV_NETSHAREENUM 0x0f +#define SRV_NET_SRV_GET_INFO 0x15 +#define SRV_NET_SRV_SET_INFO 0x16 + + +/* SESS_INFO_0 (pointers to level 0 session info strings) */ +typedef struct ptr_sess_info0 +{ + uint32 ptr_name; /* pointer to name. */ + +} SESS_INFO_0; + +/* SESS_INFO_0_STR (level 0 session info strings) */ +typedef struct str_sess_info0 +{ + UNISTR2 uni_name; /* unicode string of name */ + +} SESS_INFO_0_STR; + +/* oops - this is going to take up a *massive* amount of stack. */ +/* the UNISTR2s already have 1024 uint16 chars in them... */ +#define MAX_SESS_ENTRIES 32 + +/* SRV_SESS_INFO_0 */ +typedef struct srv_sess_info_0_info +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_sess_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ + + SESS_INFO_0 info_0 [MAX_SESS_ENTRIES]; /* session entry pointers */ + SESS_INFO_0_STR info_0_str[MAX_SESS_ENTRIES]; /* session entry strings */ + +} SRV_SESS_INFO_0; + +/* SESS_INFO_1 (pointers to level 1 session info strings) */ +typedef struct ptr_sess_info1 +{ + uint32 ptr_name; /* pointer to name. */ + uint32 ptr_user; /* pointer to user name. */ + + uint32 num_opens; + uint32 open_time; + uint32 idle_time; + uint32 user_flags; + +} SESS_INFO_1; + +/* SESS_INFO_1_STR (level 1 session info strings) */ +typedef struct str_sess_info1 +{ + UNISTR2 uni_name; /* unicode string of name */ + UNISTR2 uni_user; /* unicode string of user */ + +} SESS_INFO_1_STR; + +/* SRV_SESS_INFO_1 */ +typedef struct srv_sess_info_1_info +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_sess_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ + + SESS_INFO_1 info_1 [MAX_SESS_ENTRIES]; /* session entry pointers */ + SESS_INFO_1_STR info_1_str[MAX_SESS_ENTRIES]; /* session entry strings */ + +} SRV_SESS_INFO_1; + +/* SRV_SESS_INFO_CTR */ +typedef struct srv_sess_info_ctr_info +{ + uint32 switch_value; /* switch value */ + uint32 ptr_sess_ctr; /* pointer to sess info union */ + union + { + SRV_SESS_INFO_0 info0; /* session info level 0 */ + SRV_SESS_INFO_1 info1; /* session info level 1 */ + + } sess; + +} SRV_SESS_INFO_CTR; + + +/* SRV_Q_NET_SESS_ENUM */ +typedef struct q_net_sess_enum_info +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* server name */ + + uint32 ptr_qual_name; /* pointer (to qualifier name) */ + UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */ + + uint32 sess_level; /* session level */ + + SRV_SESS_INFO_CTR *ctr; + + uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + ENUM_HND enum_hnd; + +} SRV_Q_NET_SESS_ENUM; + +/* SRV_R_NET_SESS_ENUM */ +typedef struct r_net_sess_enum_info +{ + uint32 sess_level; /* share level */ + + SRV_SESS_INFO_CTR *ctr; + + uint32 total_entries; /* total number of entries */ + ENUM_HND enum_hnd; + + uint32 status; /* return status */ + +} SRV_R_NET_SESS_ENUM; + +/* CONN_INFO_0 (pointers to level 0 connection info strings) */ +typedef struct ptr_conn_info0 +{ + uint32 id; /* connection id. */ + +} CONN_INFO_0; + +/* oops - this is going to take up a *massive* amount of stack. */ +/* the UNISTR2s already have 1024 uint16 chars in them... */ +#define MAX_CONN_ENTRIES 32 + +/* SRV_CONN_INFO_0 */ +typedef struct srv_conn_info_0_info +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_conn_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ + + CONN_INFO_0 info_0 [MAX_CONN_ENTRIES]; /* connection entry pointers */ + +} SRV_CONN_INFO_0; + +/* CONN_INFO_1 (pointers to level 1 connection info strings) */ +typedef struct ptr_conn_info1 +{ + uint32 id; /* connection id */ + uint32 type; /* 0x3 */ + uint32 num_opens; + uint32 num_users; + uint32 open_time; + + uint32 ptr_usr_name; /* pointer to user name. */ + uint32 ptr_net_name; /* pointer to network name (e.g IPC$). */ + +} CONN_INFO_1; + +/* CONN_INFO_1_STR (level 1 connection info strings) */ +typedef struct str_conn_info1 +{ + UNISTR2 uni_usr_name; /* unicode string of user */ + UNISTR2 uni_net_name; /* unicode string of name */ + +} CONN_INFO_1_STR; + +/* SRV_CONN_INFO_1 */ +typedef struct srv_conn_info_1_info +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_conn_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ + + CONN_INFO_1 info_1 [MAX_CONN_ENTRIES]; /* connection entry pointers */ + CONN_INFO_1_STR info_1_str[MAX_CONN_ENTRIES]; /* connection entry strings */ + +} SRV_CONN_INFO_1; + +/* SRV_CONN_INFO_CTR */ +typedef struct srv_conn_info_ctr_info +{ + uint32 switch_value; /* switch value */ + uint32 ptr_conn_ctr; /* pointer to conn info union */ + union + { + SRV_CONN_INFO_0 info0; /* connection info level 0 */ + SRV_CONN_INFO_1 info1; /* connection info level 1 */ + + } conn; + +} SRV_CONN_INFO_CTR; + + +/* SRV_Q_NET_CONN_ENUM */ +typedef struct q_net_conn_enum_info +{ + uint32 ptr_srv_name; /* pointer (to server name) */ + UNISTR2 uni_srv_name; /* server name "\\server" */ + + uint32 ptr_qual_name; /* pointer (to qualifier name) */ + UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */ + + uint32 conn_level; /* connection level */ + + SRV_CONN_INFO_CTR *ctr; + + uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + ENUM_HND enum_hnd; + +} SRV_Q_NET_CONN_ENUM; + +/* SRV_R_NET_CONN_ENUM */ +typedef struct r_net_conn_enum_info +{ + uint32 conn_level; /* share level */ + + SRV_CONN_INFO_CTR *ctr; + + uint32 total_entries; /* total number of entries */ + ENUM_HND enum_hnd; + + uint32 status; /* return status */ + +} SRV_R_NET_CONN_ENUM; + +/* oops - this is going to take up a *massive* amount of stack. */ +/* the UNISTR2s already have 1024 uint16 chars in them... */ +#define MAX_SHARE_ENTRIES 32 + +/* SH_INFO_1 (pointers to level 1 share info strings) */ +typedef struct ptr_share_info1 +{ + uint32 ptr_netname; /* pointer to net name. */ + uint32 type; /* ipc, print, disk ... */ + uint32 ptr_remark; /* pointer to comment. */ + +} SH_INFO_1; + +/* SH_INFO_1_STR (level 1 share info strings) */ +typedef struct str_share_info1 +{ + UNISTR2 uni_netname; /* unicode string of net name */ + UNISTR2 uni_remark; /* unicode string of comment */ + +} SH_INFO_1_STR; + +/* SRV_SHARE_INFO_1 */ +typedef struct share_info_1_info +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_share_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ + + SH_INFO_1 info_1 [MAX_SHARE_ENTRIES]; /* share entry pointers */ + SH_INFO_1_STR info_1_str[MAX_SHARE_ENTRIES]; /* share entry strings */ + +} SRV_SHARE_INFO_1; + +/* SH_INFO_2 (pointers to level 2 share info strings) */ +typedef struct ptr_share_info2 +{ + uint32 ptr_netname; /* pointer to net name. */ + uint32 type; /* ipc, print, disk ... */ + uint32 ptr_remark; /* pointer to comment. */ + uint32 perms; /* permissions */ + uint32 max_uses; /* maximum uses */ + uint32 num_uses; /* current uses */ + uint32 ptr_path; /* pointer to path name */ + uint32 ptr_passwd; /* pointer to password */ + +} SH_INFO_2; + +/* SH_INFO_2_STR (level 2 share info strings) */ +typedef struct str_share_info2 +{ + UNISTR2 uni_netname; /* unicode string of net name (e.g NETLOGON) */ + UNISTR2 uni_remark; /* unicode string of comment (e.g "Logon server share") */ + UNISTR2 uni_path; /* unicode string of local path (e.g c:\winnt\system32\repl\import\scripts) */ + UNISTR2 uni_passwd; /* unicode string of password - presumably for share level security (e.g NULL) */ + +} SH_INFO_2_STR; + +/* SRV_SHARE_INFO_2 */ +typedef struct share_info_2_info +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_share_info; /* Buffer */ + uint32 num_entries_read2; /* EntriesRead */ + + SH_INFO_2 info_2 [MAX_SHARE_ENTRIES]; /* share entry pointers */ + SH_INFO_2_STR info_2_str[MAX_SHARE_ENTRIES]; /* share entry strings */ + +} SRV_SHARE_INFO_2; + +/* SRV_SHARE_INFO_CTR */ +typedef struct srv_share_info_1_info +{ + uint32 switch_value; /* switch value */ + uint32 ptr_share_ctr; /* pointer to share info union */ + union + { + SRV_SHARE_INFO_1 info1; /* share info level 1 */ + SRV_SHARE_INFO_2 info2; /* share info level 2 */ + + } share; + +} SRV_SHARE_INFO_CTR; + +/* SRV_Q_NET_SHARE_ENUM */ +typedef struct q_net_share_enum_info +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* server name */ + + uint32 share_level; /* share level */ + + SRV_SHARE_INFO_CTR *ctr; /* share info container */ + + uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + + ENUM_HND enum_hnd; + +} SRV_Q_NET_SHARE_ENUM; + + +/* SRV_R_NET_SHARE_ENUM */ +typedef struct r_net_share_enum_info +{ + uint32 share_level; /* share level */ + SRV_SHARE_INFO_CTR *ctr; /* share info container */ + + uint32 total_entries; /* total number of entries */ + ENUM_HND enum_hnd; + + uint32 status; /* return status */ + +} SRV_R_NET_SHARE_ENUM; + +/* FILE_INFO_3 (level 3 file info strings) */ +typedef struct file_info3_info +{ + uint32 id; /* file index */ + uint32 perms; /* file permissions. don't know what format */ + uint32 num_locks; /* file locks */ + uint32 ptr_path_name; /* file name */ + uint32 ptr_user_name; /* file owner */ + +} FILE_INFO_3; + +/* FILE_INFO_3_STR (level 3 file info strings) */ +typedef struct str_file_info3_info +{ + UNISTR2 uni_path_name; /* unicode string of file name */ + UNISTR2 uni_user_name; /* unicode string of file owner. */ + +} FILE_INFO_3_STR; + +/* oops - this is going to take up a *massive* amount of stack. */ +/* the UNISTR2s already have 1024 uint16 chars in them... */ +#define MAX_FILE_ENTRIES 32 + +/* SRV_FILE_INFO_3 */ +typedef struct srv_file_info_3 +{ + uint32 num_entries_read; /* EntriesRead */ + uint32 ptr_file_info; /* Buffer */ + + uint32 num_entries_read2; /* EntriesRead */ + + FILE_INFO_3 info_3 [MAX_FILE_ENTRIES]; /* file entry details */ + FILE_INFO_3_STR info_3_str[MAX_FILE_ENTRIES]; /* file entry strings */ + +} SRV_FILE_INFO_3; + +/* SRV_FILE_INFO_CTR */ +typedef struct srv_file_info_3_info +{ + uint32 switch_value; /* switch value */ + uint32 ptr_file_ctr; /* pointer to file info union */ + union + { + SRV_FILE_INFO_3 info3; /* file info with 0 entries */ + + } file; + +} SRV_FILE_INFO_CTR; + + +/* SRV_Q_NET_FILE_ENUM */ +typedef struct q_net_file_enum_info +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* server name */ + + uint32 ptr_qual_name; /* pointer (to qualifier name) */ + UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */ + + uint32 file_level; /* file level */ + + SRV_FILE_INFO_CTR *ctr; + + uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ + ENUM_HND enum_hnd; + +} SRV_Q_NET_FILE_ENUM; + + +/* SRV_R_NET_FILE_ENUM */ +typedef struct r_net_file_enum_info +{ + uint32 file_level; /* file level */ + + SRV_FILE_INFO_CTR *ctr; + + uint32 total_entries; /* total number of files */ + ENUM_HND enum_hnd; + + uint32 status; /* return status */ + +} SRV_R_NET_FILE_ENUM; + +/* SRV_INFO_101 */ +typedef struct srv_info_101_info +{ + uint32 platform_id; /* 0x500 */ + uint32 ptr_name; /* pointer to server name */ + uint32 ver_major; /* 0x4 */ + uint32 ver_minor; /* 0x2 */ + uint32 srv_type; /* browse etc type */ + uint32 ptr_comment; /* pointer to server comment */ + + UNISTR2 uni_name; /* server name "server" */ + UNISTR2 uni_comment; /* server comment "samba x.x.x blah" */ + +} SRV_INFO_101; + +/* SRV_INFO_102 */ +typedef struct srv_info_102_info +{ + uint32 platform_id; /* 0x500 */ + uint32 ptr_name; /* pointer to server name */ + uint32 ver_major; /* 0x4 */ + uint32 ver_minor; /* 0x2 */ + uint32 srv_type; /* browse etc type */ + uint32 ptr_comment; /* pointer to server comment */ + uint32 users; /* 0xffff ffff*/ + uint32 disc; /* 0xf */ + uint32 hidden; /* 0x0 */ + uint32 announce; /* 240 */ + uint32 ann_delta; /* 3000 */ + uint32 licenses; /* 0 */ + uint32 ptr_usr_path; /* pointer to user path */ + + UNISTR2 uni_name; /* server name "server" */ + UNISTR2 uni_comment; /* server comment "samba x.x.x blah" */ + UNISTR2 uni_usr_path; /* "c:\" (eh?) */ + +} SRV_INFO_102; + + +/* SRV_INFO_CTR */ +typedef struct srv_info_ctr_info +{ + uint32 switch_value; /* switch value */ + uint32 ptr_srv_ctr; /* pointer to server info */ + union + { + SRV_INFO_102 sv102; /* server info level 102 */ + SRV_INFO_101 sv101; /* server info level 101 */ + + } srv; + +} SRV_INFO_CTR; + +/* SRV_Q_NET_SRV_GET_INFO */ +typedef struct q_net_srv_get_info +{ + uint32 ptr_srv_name; + UNISTR2 uni_srv_name; /* "\\server" */ + uint32 switch_value; + +} SRV_Q_NET_SRV_GET_INFO; + +/* SRV_R_NET_SRV_GET_INFO */ +typedef struct r_net_srv_get_info +{ + SRV_INFO_CTR *ctr; + + uint32 status; /* return status */ + +} SRV_R_NET_SRV_GET_INFO; + +/* SRV_Q_NET_SRV_SET_INFO */ +typedef struct q_net_srv_set_info +{ + uint32 ptr_srv_name; + UNISTR2 uni_srv_name; /* "\\server" */ + uint32 switch_value; + + SRV_INFO_CTR *ctr; + +} SRV_Q_NET_SRV_SET_INFO; + + +/* SRV_R_NET_SRV_SET_INFO */ +typedef struct r_net_srv_set_info +{ + uint32 switch_value; /* switch value */ + + uint32 status; /* return status */ + +} SRV_R_NET_SRV_SET_INFO; + + +#endif /* _RPC_SRVSVC_H */ + diff --git a/source3/include/rpc_wkssvc.h b/source3/include/rpc_wkssvc.h new file mode 100644 index 0000000000..1483997acb --- /dev/null +++ b/source3/include/rpc_wkssvc.h @@ -0,0 +1,73 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + + 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. +*/ + +#ifndef _RPC_WKS_H /* _RPC_WKS_H */ +#define _RPC_WKS_H + + +/* wkssvc pipe */ +#define WKS_QUERY_INFO 0x00 + + +/* WKS_Q_QUERY_INFO - probably a capabilities request */ +typedef struct q_wks_query_info_info +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */ + + uint16 switch_value; /* info level 100 (0x64) */ + +} WKS_Q_QUERY_INFO; + + +/* WKS_INFO_100 - level 100 info */ +typedef struct wks_info_100_info +{ + uint32 platform_id; /* 0x0000 01f4 - unknown */ + uint32 ptr_compname; /* pointer to server name */ + uint32 ptr_lan_grp ; /* pointer to domain name */ + uint32 ver_major; /* 4 - unknown */ + uint32 ver_minor; /* 0 - unknown */ + + UNISTR2 uni_compname; /* unicode server name */ + UNISTR2 uni_lan_grp ; /* unicode domain name */ + +} WKS_INFO_100; + + +/* WKS_R_QUERY_INFO - probably a capabilities request */ +typedef struct r_wks_query_info_info +{ + uint16 switch_value; /* 100 (0x64) - switch value */ + + /* for now, only level 100 is supported. this should be an enum container */ + uint32 ptr_1; /* pointer 1 */ + WKS_INFO_100 *wks100; /* workstation info level 100 */ + + uint32 status; /* return status */ + +} WKS_R_QUERY_INFO; + + +#endif /* _RPC_WKS_H */ + diff --git a/source3/include/smb.h b/source3/include/smb.h index ccb3b0424a..a60b74a835 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -36,6 +36,11 @@ #define BOOLSTR(b) ((b) ? "Yes" : "No") #define BITSETB(ptr,bit) ((((char *)ptr)[0] & (1<<(bit)))!=0) #define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0) + +#define IS_BITS_SET_ALL(var,bit) (((var)&(bit))==(bit)) +#define IS_BITS_SET_SOME(var,bit) (((var)&(bit))!=0) +#define IS_BITS_CLR_ALL(var,bit) (((var)&(~(bit)))==0) + #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2))) typedef int BOOL; @@ -246,90 +251,6 @@ typedef fstring string; #define PIPE_LSASS "\\PIPE\\lsass" #define PIPE_LSARPC "\\PIPE\\lsarpc" -/* NETLOGON opcodes and data structures */ - -enum RPC_PKT_TYPE -{ - RPC_REQUEST = 0x00, - RPC_RESPONSE = 0x02, - RPC_BIND = 0x0B, - RPC_BINDACK = 0x0C -}; - -#define NET_QUERYFORPDC 7 /* Query for PDC */ -#define NET_QUERYFORPDC_R 12 /* Response to Query for PDC */ -#define NET_SAMLOGON 18 -#define NET_SAMLOGON_R 19 - -/* Allowable account control bits */ -#define ACB_DISABLED 1 /* 1 = User account disabled */ -#define ACB_HOMDIRREQ 2 /* 1 = Home directory required */ -#define ACB_PWNOTREQ 4 /* 1 = User password not required */ -#define ACB_TEMPDUP /* 1 = Temporary duplicate account */ -#define ACB_NORMAL /* 1 = Normal user account */ -#define ACB_MNS /* 1 = MNS logon user account */ -#define ACB_DOMTRUST /* 1 = Interdomain trust account */ -#define ACB_WSTRUST /* 1 = Workstation trust account */ -#define ACB_SVRTRUST /* 1 = Server trust account */ -#define ACB_PWNOEXP /* 1 = User password does not expire */ -#define ACB_AUTOLOCK /* 1 = Account auto locked */ - -#define SAMR_CLOSE 0x01 -#define SAMR_OPEN_SECRET 0x07 -#define SAMR_LOOKUP_RIDS 0x11 -#define SAMR_UNKNOWN_3 0x03 -#define SAMR_UNKNOWN_22 0x22 -#define SAMR_UNKNOWN_24 0x24 -#define SAMR_UNKNOWN_34 0x34 -#define SAMR_OPEN_POLICY 0x39 - -#define LSA_OPENPOLICY 0x2c -#define LSA_QUERYINFOPOLICY 0x07 -#define LSA_ENUMTRUSTDOM 0x0d -#define LSA_REQCHAL 0x04 -#define LSA_SRVPWSET 0x06 -#define LSA_SAMLOGON 0x02 -#define LSA_SAMLOGOFF 0x03 -#define LSA_AUTH2 0x0f -#define LSA_CLOSE 0x00 - -/* XXXX these are here to get a compile! */ - -#define LSA_OPENSECRET 0xFF -#define LSA_LOOKUPSIDS 0xFE -#define LSA_LOOKUPRIDS 0xFD -#define LSA_LOOKUPNAMES 0xFC - -/* srvsvc pipe */ -#define NETSERVERGETINFO 0x15 -#define NETSHAREENUM 0x0f - -/* well-known RIDs - Relative IDs */ - -/* RIDs - Well-known users ... */ -#define DOMAIN_USER_RID_ADMIN (0x000001F4L) -#define DOMAIN_USER_RID_GUEST (0x000001F5L) - -/* RIDs - well-known groups ... */ -#define DOMAIN_GROUP_RID_ADMINS (0x00000200L) -#define DOMAIN_GROUP_RID_USERS (0x00000201L) -#define DOMAIN_GROUP_RID_GUESTS (0x00000202L) - -/* RIDs - well-known aliases ... */ -#define DOMAIN_ALIAS_RID_ADMINS (0x00000220L) -#define DOMAIN_ALIAS_RID_USERS (0x00000221L) -#define DOMAIN_ALIAS_RID_GUESTS (0x00000222L) -#define DOMAIN_ALIAS_RID_POWER_USERS (0x00000223L) - -#define DOMAIN_ALIAS_RID_ACCOUNT_OPS (0x00000224L) -#define DOMAIN_ALIAS_RID_SYSTEM_OPS (0x00000225L) -#define DOMAIN_ALIAS_RID_PRINT_OPS (0x00000226L) -#define DOMAIN_ALIAS_RID_BACKUP_OPS (0x00000227L) - -#define DOMAIN_ALIAS_RID_REPLICATOR (0x00000228L) - - - /* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ typedef struct time_info { @@ -344,990 +265,20 @@ typedef struct nttime_info uint32 high; } NTTIME; - - -#define MAXSUBAUTHS 15 /* max sub authorities in a SID */ - -/* DOM_SID - security id */ -typedef struct sid_info -{ - uint8 sid_rev_num; /* SID revision number */ - uint8 num_auths; /* number of sub-authorities */ - uint8 id_auth[6]; /* Identifier Authority */ - uint32 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */ - -} DOM_SID; - -/* UNIHDR - unicode string header */ -typedef struct unihdr_info -{ - uint16 uni_max_len; - uint16 uni_str_len; - uint32 undoc; /* usually has a value of 4 */ - -} UNIHDR; - -/* UNIHDR2 - unicode string header and undocumented buffer */ -typedef struct unihdr2_info -{ - UNIHDR unihdr; - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - -} UNIHDR2; - -/* clueless as to what maximum length should be */ -#define MAX_UNISTRLEN 1024 - -/* UNISTR - unicode string size and buffer */ -typedef struct unistr_info -{ - uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. ***MUST*** be null-terminated */ - -} UNISTR; - -/* UNISTR2 - unicode string size and buffer */ -typedef struct unistr2_info -{ - uint32 uni_max_len; - uint32 undoc; - uint32 uni_str_len; - uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */ - -} UNISTR2; - -/* DOM_SID2 - domain SID structure - SIDs stored in unicode */ -typedef struct domsid2_info -{ - uint32 type; /* value is 5 */ - uint32 undoc; /* value is 0 */ - - UNIHDR2 hdr; /* XXXX conflict between hdr and str for length */ - UNISTR str; /* XXXX conflict between hdr and str for length */ - -} DOM_SID2; - -/* DOM_RID2 - domain RID structure for ntlsa pipe */ -typedef struct domrid2_info -{ - uint32 type; /* value is 5 */ - uint32 undoc; /* value is non-zero */ - uint32 rid; - uint32 rid_idx; /* don't know what this is */ - -} DOM_RID2; - -/* DOM_RID3 - domain RID structure for samr pipe */ -typedef struct domrid3_info -{ - uint32 rid; /* domain-relative (to a SID) id */ - uint32 type1; /* value is 0x1 */ - uint32 ptr_type; /* undocumented pointer */ - uint32 type2; /* value is 0x1 */ - -} DOM_RID3; - -/* DOM_CLNT_SRV - client / server names */ -typedef struct clnt_srv_info -{ - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_comp_name; /* client machine name */ - -} DOM_CLNT_SRV; - -/* DOM_LOG_INFO - login info */ -typedef struct log_info -{ - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - UNISTR2 uni_acct_name; /* account name */ - uint16 sec_chan; /* secure channel type */ - UNISTR2 uni_comp_name; /* client machine name */ - -} DOM_LOG_INFO; - -/* DOM_CHAL - challenge info */ -typedef struct chal_info -{ - uchar data[8]; /* credentials */ -} DOM_CHAL; - -/* DOM_CREDs - timestamped client or server credentials */ -typedef struct cred_info -{ - DOM_CHAL challenge; /* credentials */ - UTIME timestamp; /* credential time-stamp */ - -} DOM_CRED; - -/* DOM_CLNT_INFO - client info */ -typedef struct clnt_info -{ - DOM_LOG_INFO login; - DOM_CRED cred; - -} DOM_CLNT_INFO; - -/* DOM_CLNT_INFO2 - client info */ -typedef struct clnt_info2 -{ - DOM_CLNT_SRV login; - uint32 ptr_cred; - DOM_CRED cred; - -} DOM_CLNT_INFO2; - -/* DOM_LOGON_ID - logon id */ -typedef struct logon_info -{ - uint32 low; - uint32 high; - -} DOM_LOGON_ID; - -/* ARC4_OWF */ -typedef struct arc4_owf_info -{ - uint8 data[16]; - -} ARC4_OWF; - - -/* DOM_ID_INFO_1 */ -typedef struct id_info_1 -{ - uint32 ptr_id_info1; /* pointer to id_info_1 */ - UNIHDR hdr_domain_name; /* domain name unicode header */ - uint32 param_ctrl; /* param control */ - DOM_LOGON_ID logon_id; /* logon ID */ - UNIHDR hdr_user_name; /* user name unicode header */ - UNIHDR hdr_wksta_name; /* workgroup name unicode header */ - ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */ - ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */ - UNISTR2 uni_domain_name; /* domain name unicode string */ - UNISTR2 uni_user_name; /* user name unicode string */ - UNISTR2 uni_wksta_name; /* workgroup name unicode string */ - -} DOM_ID_INFO_1; - -/* SAM_INFO - sam logon/off id structure */ -typedef struct sam_info -{ - DOM_CLNT_INFO2 client; - uint32 ptr_rtn_cred; /* pointer to return credentials */ - DOM_CRED rtn_cred; /* return credentials */ - uint16 logon_level; - uint16 switch_value; - - union - { - DOM_ID_INFO_1 *id1; /* auth-level 1 */ - - } auth; - -} DOM_SAM_INFO; - -/* DOM_GID - group id + user attributes */ -typedef struct gid_info -{ - uint32 g_rid; /* a group RID */ - uint32 attr; - -} DOM_GID; - -/* RPC_HDR - ms rpc header */ -typedef struct rpc_hdr_info -{ - uint8 major; /* 5 - RPC major version */ - uint8 minor; /* 0 - RPC minor version */ - uint8 pkt_type; /* 2 - RPC response packet */ - uint8 frag; /* 3 - first frag + last frag */ - uint32 pack_type; /* 0x1000 0000 - packed data representation */ - uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */ - uint16 auth_len; /* 0 - authentication length */ - uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */ - -} RPC_HDR; - -/* RPC_HDR_RR - ms request / response rpc header */ -typedef struct rpc_hdr_rr_info -{ - RPC_HDR hdr; - - uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */ - uint16 context_id; /* 0 - presentation context identifier */ - uint8 cancel_count; /* 0 - cancel count */ - uint8 opnum; /* request: 0 - reserved. response: opnum */ - -} RPC_HDR_RR; - -/* the interfaces are numbered. as yet I haven't seen more than one interface - * used on the same pipe name - * srvsvc - * abstract (0x4B324FC8, 0x01D31670, 0x475A7812, 0x88E16EBF, 0x00000003) - * transfer (0x8A885D04, 0x11C91CEB, 0x0008E89F, 0x6048102B, 0x00000002) - */ -/* RPC_IFACE */ -typedef struct rpc_iface_info -{ - uint8 data[16]; /* 16 bytes of number */ - uint32 version; /* the interface number */ - -} RPC_IFACE; - - -/* this seems to be the same string name depending on the name of the pipe, - * but is more likely to be linked to the interface name - * "srvsvc", "\\PIPE\\ntsvcs" - * "samr", "\\PIPE\\lsass" - * "wkssvc", "\\PIPE\\wksvcs" - * "NETLOGON", "\\PIPE\\NETLOGON" - */ -/* RPC_ADDR_STR */ -typedef struct rpc_addr_info -{ - uint16 len; /* length of the string including null terminator */ - fstring str; /* the string above in single byte, null terminated form */ - -} RPC_ADDR_STR; - -/* RPC_HDR_BBA */ -typedef struct rpc_hdr_bba_info -{ - uint16 max_tsize; /* maximum transmission fragment size (0x1630) */ - uint16 max_rsize; /* max receive fragment size (0x1630) */ - uint32 assoc_gid; /* associated group id (0x0) */ - -} RPC_HDR_BBA; - -/* RPC_BIND_REQ - ms req bind */ -typedef struct rpc_bind_req_info -{ - RPC_HDR_BBA bba; - - uint32 num_elements; /* the number of elements (0x1) */ - uint16 context_id; /* presentation context identifier (0x0) */ - uint8 num_syntaxes; /* the number of syntaxes (has always been 1?)(0x1) */ - - RPC_IFACE abstract; /* num and vers. of interface client is using */ - RPC_IFACE transfer; /* num and vers. of interface to use for replies */ - -} RPC_HDR_RB; - -/* RPC_RESULTS - can only cope with one reason, right now... */ -typedef struct rpc_results_info -{ -/* uint8[] # 4-byte alignment padding, against SMB header */ - - uint8 num_results; /* the number of results (0x01) */ - -/* uint8[] # 4-byte alignment padding, against SMB header */ - - uint16 result; /* result (0x00 = accept) */ - uint16 reason; /* reason (0x00 = no reason specified) */ - -} RPC_RESULTS; - -/* RPC_HDR_BA */ -typedef struct rpc_hdr_ba_info -{ - RPC_HDR_BBA bba; - - RPC_ADDR_STR addr ; /* the secondary address string, as described earlier */ - RPC_RESULTS res ; /* results and reasons */ - RPC_IFACE transfer; /* the transfer syntax from the request */ - -} RPC_HDR_BA; - - -/* DOM_QUERY - info class 3 and 5 LSA Query response */ -typedef struct dom_query_info -{ - uint16 uni_dom_max_len; /* domain name string length * 2 */ - uint16 uni_dom_str_len; /* domain name string length * 2 */ - uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */ - uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */ - UNISTR2 uni_domain_name; /* domain name (unicode string) */ - DOM_SID dom_sid; /* domain SID */ - -} DOM_QUERY; - -/* level 5 is same as level 3. we hope. */ -typedef DOM_QUERY DOM_QUERY_3; -typedef DOM_QUERY DOM_QUERY_5; - -#define POL_HND_SIZE 20 - -/* LSA_POL_HND */ -typedef struct lsa_policy_info -{ - uint8 data[POL_HND_SIZE]; /* policy handle */ - -} LSA_POL_HND; - -/* OBJ_ATTR (object attributes) */ -typedef struct object_attributes_info -{ - uint32 len; /* 0x18 - length (in bytes) inc. the length field. */ - uint32 ptr_root_dir; /* 0 - root directory (pointer) */ - uint32 ptr_obj_name; /* 0 - object name (pointer) */ - uint32 attributes; /* 0 - attributes (undocumented) */ - uint32 ptr_sec_desc; /* 0 - security descriptior (pointer) */ - uint32 sec_qos; /* 0 - security quality of service */ - -} LSA_OBJ_ATTR; - -/* LSA_Q_OPEN_POL - LSA Query Open Policy */ -typedef struct lsa_q_open_pol_info -{ - uint32 ptr; /* undocumented buffer pointer */ - UNISTR2 uni_server_name; /* server name, starting with two '\'s */ - LSA_OBJ_ATTR attr ; /* object attributes */ - - uint32 des_access; /* desired access attributes */ - -} LSA_Q_OPEN_POL; - -/* LSA_R_OPEN_POL - response to LSA Open Policy */ -typedef struct lsa_r_open_pol_info -{ - LSA_POL_HND pol; /* policy handle */ - - uint32 status; /* return code */ - -} LSA_R_OPEN_POL; - -/* LSA_Q_QUERY_INFO - LSA query info policy */ -typedef struct lsa_query_info -{ - LSA_POL_HND pol; /* policy handle */ - uint16 info_class; /* info class */ - -} LSA_Q_QUERY_INFO; - -/* LSA_R_QUERY_INFO - response to LSA query info policy */ -typedef struct lsa_r_query_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer */ - uint16 info_class; /* info class (same as info class in request) */ - - union - { - DOM_QUERY_3 id3; - DOM_QUERY_5 id5; - - } dom; - - uint32 status; /* return code */ - -} LSA_R_QUERY_INFO; - -/* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */ -typedef struct lsa_enum_trust_dom_info -{ - LSA_POL_HND pol; /* policy handle */ - uint32 enum_context; /* enumeration context handle */ - uint32 preferred_len; /* preferred maximum length */ - -} LSA_Q_ENUM_TRUST_DOM; - -/* LSA_R_ENUM_TRUST_DOM - response to LSA enumerate trusted domains */ -typedef struct lsa_r_enum_trust_dom_info -{ - LSA_POL_HND pol; /* policy handle */ - - uint32 status; /* return code */ - -} LSA_R_ENUM_TRUST_DOM; - -/* LSA_Q_CLOSE */ -typedef struct lsa_q_close_info -{ - LSA_POL_HND pol; /* policy handle */ - -} LSA_Q_CLOSE; - -/* LSA_R_CLOSE */ -typedef struct lsa_r_close_info -{ - LSA_POL_HND pol; /* policy handle. should be all zeros. */ - - uint32 status; /* return code */ - -} LSA_R_CLOSE; - - -#define MAX_REF_DOMAINS 10 - -/* DOM_R_REF */ -typedef struct dom_ref_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer. */ - uint32 num_ref_doms_1; /* num referenced domains? */ - uint32 buffer_dom_name; /* undocumented domain name buffer pointer. */ - uint32 max_entries; /* 32 - max number of entries */ - uint32 num_ref_doms_2; /* 4 - num referenced domains? */ - - UNIHDR2 hdr_dom_name; /* domain name unicode string header */ - UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */ - - UNISTR uni_dom_name; /* domain name unicode string */ - DOM_SID ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */ - -} DOM_R_REF; - -#define MAX_LOOKUP_SIDS 10 - -/* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */ -typedef struct lsa_q_lookup_sids -{ - LSA_POL_HND pol_hnd; /* policy handle */ - uint32 num_entries; - uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ - uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ - uint32 buffer_lookup_sids[MAX_LOOKUP_SIDS]; /* undocumented domain SID pointers to be looked up. */ - DOM_SID dom_sids[MAX_LOOKUP_SIDS]; /* domain SIDs to be looked up. */ - uint8 undoc[16]; /* completely undocumented 16 bytes */ - -} LSA_Q_LOOKUP_SIDS; - -/* LSA_R_LOOKUP_SIDS - response to LSA Lookup SIDs */ -typedef struct lsa_r_lookup_sids -{ - DOM_R_REF dom_ref; /* domain reference info */ - - uint32 num_entries; - uint32 undoc_buffer; /* undocumented buffer pointer */ - uint32 num_entries2; - - DOM_SID2 dom_sid[MAX_LOOKUP_SIDS]; /* domain SIDs being looked up */ - - uint32 num_entries3; - - uint32 status; /* return code */ - -} LSA_R_LOOKUP_SIDS; - -/* DOM_NAME - XXXX not sure about this structure */ -typedef struct dom_name_info -{ - uint32 uni_str_len; - UNISTR str; - -} DOM_NAME; - - -#define UNKNOWN_LEN 1 - -/* LSA_Q_LOOKUP_RIDS - LSA Lookup RIDs */ -typedef struct lsa_q_lookup_rids -{ - - LSA_POL_HND pol_hnd; /* policy handle */ - uint32 num_entries; - uint32 num_entries2; - uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ - uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ - DOM_NAME lookup_name[MAX_LOOKUP_SIDS]; /* names to be looked up */ - uint8 undoc[UNKNOWN_LEN]; /* completely undocumented bytes of unknown length */ - -} LSA_Q_LOOKUP_RIDS; - -/* LSA_R_LOOKUP_RIDS - response to LSA Lookup RIDs by name */ -typedef struct lsa_r_lookup_rids -{ - DOM_R_REF dom_ref; /* domain reference info */ - - uint32 num_entries; - uint32 undoc_buffer; /* undocumented buffer pointer */ - - uint32 num_entries2; - DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ - - uint32 num_entries3; - - uint32 status; /* return code */ - -} LSA_R_LOOKUP_RIDS; - - - -/* NEG_FLAGS */ -typedef struct lsa_neg_flags_info -{ - uint32 neg_flags; /* negotiated flags */ - -} NEG_FLAGS; - - -/* LSA_Q_REQ_CHAL */ -typedef struct lsa_q_req_chal_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server unicode string */ - UNISTR2 uni_logon_clnt; /* logon client unicode string */ - DOM_CHAL clnt_chal; /* client challenge */ - -} LSA_Q_REQ_CHAL; - - -/* LSA_R_REQ_CHAL */ -typedef struct lsa_r_req_chal_info -{ - DOM_CHAL srv_chal; /* server challenge */ - - uint32 status; /* return code */ - -} LSA_R_REQ_CHAL; - - - -/* LSA_Q_AUTH_2 */ -typedef struct lsa_q_auth2_info -{ - DOM_LOG_INFO clnt_id; /* client identification info */ - DOM_CHAL clnt_chal; /* client-calculated credentials */ - - NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */ - -} LSA_Q_AUTH_2; - - -/* LSA_R_AUTH_2 */ -typedef struct lsa_r_auth2_info -{ - DOM_CHAL srv_chal; /* server-calculated credentials */ - NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */ - - uint32 status; /* return code */ - -} LSA_R_AUTH_2; - - -/* LSA_Q_SRV_PWSET */ -typedef struct lsa_q_srv_pwset_info -{ - DOM_CLNT_INFO clnt_id; /* client identification/authentication info */ - char pwd[16]; /* new password - undocumented. */ - -} LSA_Q_SRV_PWSET; - -/* LSA_R_SRV_PWSET */ -typedef struct lsa_r_srv_pwset_info -{ - DOM_CRED srv_cred; /* server-calculated credentials */ - - uint32 status; /* return code */ - -} LSA_R_SRV_PWSET; - -#define LSA_MAX_GROUPS 32 -#define LSA_MAX_SIDS 32 - -/* LSA_USER_INFO */ -typedef struct lsa_q_user_info -{ - uint32 ptr_user_info; - - NTTIME logon_time; /* logon time */ - NTTIME logoff_time; /* logoff time */ - NTTIME kickoff_time; /* kickoff time */ - NTTIME pass_last_set_time; /* password last set time */ - NTTIME pass_can_change_time; /* password can change time */ - NTTIME pass_must_change_time; /* password must change time */ - - UNIHDR hdr_user_name; /* username unicode string header */ - UNIHDR hdr_full_name; /* user's full name unicode string header */ - UNIHDR hdr_logon_script; /* logon script unicode string header */ - UNIHDR hdr_profile_path; /* profile path unicode string header */ - UNIHDR hdr_home_dir; /* home directory unicode string header */ - UNIHDR hdr_dir_drive; /* home directory drive unicode string header */ - - uint16 logon_count; /* logon count */ - uint16 bad_pw_count; /* bad password count */ - - uint32 user_id; /* User ID */ - uint32 group_id; /* Group ID */ - uint32 num_groups; /* num groups */ - uint32 buffer_groups; /* undocumented buffer pointer to groups. */ - uint32 user_flgs; /* user flags */ - - char user_sess_key[16]; /* unused user session key */ - - UNIHDR hdr_logon_srv; /* logon server unicode string header */ - UNIHDR hdr_logon_dom; /* logon domain unicode string header */ - - uint32 buffer_dom_id; /* undocumented logon domain id pointer */ - char padding[40]; /* unused padding bytes. expansion room */ - - uint32 num_other_sids; /* 0 - num_sids */ - uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */ - - UNISTR2 uni_user_name; /* username unicode string */ - UNISTR2 uni_full_name; /* user's full name unicode string */ - UNISTR2 uni_logon_script; /* logon script unicode string */ - UNISTR2 uni_profile_path; /* profile path unicode string */ - UNISTR2 uni_home_dir; /* home directory unicode string */ - UNISTR2 uni_dir_drive; /* home directory drive unicode string */ - - uint32 num_groups2; /* num groups */ - DOM_GID gids[LSA_MAX_GROUPS]; /* group info */ - - UNISTR2 uni_logon_srv; /* logon server unicode string */ - UNISTR2 uni_logon_dom; /* logon domain unicode string */ - - DOM_SID dom_sid; /* domain SID */ - DOM_SID other_sids[LSA_MAX_SIDS]; /* undocumented - domain SIDs */ - -} LSA_USER_INFO; - - -/* LSA_Q_SAM_LOGON */ -typedef struct lsa_q_sam_logon_info -{ - DOM_SAM_INFO sam_id; - -} LSA_Q_SAM_LOGON; - -/* LSA_R_SAM_LOGON */ -typedef struct lsa_r_sam_logon_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - - uint16 switch_value; /* 3 - indicates type of USER INFO */ - LSA_USER_INFO *user; - - uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ - - uint32 status; /* return code */ - -} LSA_R_SAM_LOGON; - - -/* LSA_Q_SAM_LOGOFF */ -typedef struct lsa_q_sam_logoff_info -{ - DOM_SAM_INFO sam_id; - -} LSA_Q_SAM_LOGOFF; - -/* LSA_R_SAM_LOGOFF */ -typedef struct lsa_r_sam_logoff_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - - uint32 status; /* return code */ - -} LSA_R_SAM_LOGOFF; - - -/* SH_INFO_1 (pointers to level 1 share info strings) */ -typedef struct ptr_share_info1 -{ - uint32 ptr_netname; /* pointer to net name. */ - uint32 type; /* type of share. 0 - undocumented. */ - uint32 ptr_remark; /* pointer to comment. */ - -} SH_INFO_1; - -/* SH_INFO_1_STR (level 1 share info strings) */ -typedef struct str_share_info1 -{ - UNISTR2 uni_netname; /* unicode string of net name */ - UNISTR2 uni_remark; /* unicode string of comment. */ - -} SH_INFO_1_STR; - -/* oops - this is going to take up a *massive* amount of stack. */ -/* the UNISTR2s already have 1024 uint16 chars in them... */ -#define MAX_SHARE_ENTRIES 32 - -/* SHARE_INFO_1_CONTAINER */ -typedef struct share_info_ctr -{ - uint32 num_entries_read; /* EntriesRead */ - uint32 ptr_share_info; /* Buffer */ - uint32 num_entries_read2; /* EntriesRead */ - SH_INFO_1 info_1 [MAX_SHARE_ENTRIES]; /* share entry pointers */ - SH_INFO_1_STR info_1_str[MAX_SHARE_ENTRIES]; /* share entry strings */ - uint32 num_entries_read3; /* EntriesRead2 */ - uint32 padding; /* padding */ - -} SHARE_INFO_1_CTR; - - -/* SRV_Q_NET_SHARE_ENUM */ -typedef struct q_net_share_enum_info -{ - uint32 ptr_srv_name; /* pointer (to server name?) */ - UNISTR2 uni_srv_name; /* server name */ - - uint32 share_level; /* share level */ - uint32 switch_value; /* switch value */ - - uint32 ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ - - union - { - SHARE_INFO_1_CTR info1; /* share info with 0 entries */ - - } share; - - uint32 preferred_len; /* preferred maximum length (0xffff ffff) */ - -} SRV_Q_NET_SHARE_ENUM; - - -/* SRV_R_NET_SHARE_ENUM */ -typedef struct r_net_share_enum_info -{ - uint32 share_level; /* share level */ - uint32 switch_value; /* switch value */ - - uint32 ptr_share_info; /* pointer to SHARE_INFO_1_CTR */ - union - { - SHARE_INFO_1_CTR info1; /* share info container */ - - } share; - - uint32 status; /* return status */ - -} SRV_R_NET_SHARE_ENUM; - - -/* SAMR_Q_CLOSE - probably a policy handle close */ -typedef struct q_samr_close_info -{ - LSA_POL_HND pol; /* policy handle */ - -} SAMR_Q_CLOSE; - - -/* SAMR_R_CLOSE - probably a policy handle close */ -typedef struct r_samr_close_info -{ - LSA_POL_HND pol; /* policy handle */ - uint32 status; /* return status */ - -} SAMR_R_CLOSE; - - -/**************************************************************************** -SAMR_Q_OPEN_SECRET - unknown_0 values seen associated with SIDs: - -0x0000 0200 and a specific domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0 -0x0000 0280 and a well-known domain sid - S-1-5-20 -0x2000 0000 and a well-known domain sid - S-1-5-20 -0x2000 0000 and a specific domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0 -*****************************************************************************/ - -/* SAMR_Q_OPEN_SECRET - probably an open secret */ -typedef struct q_samr_open_secret_info -{ - LSA_POL_HND pol; /* policy handle */ - uint32 unknown_0; /* 0x2000 0000; 0x0000 0211; 0x0000 0280; 0x0000 0200 - unknown */ - DOM_SID dom_sid; /* domain SID */ - -} SAMR_Q_OPEN_SECRET; - - -/* SAMR_R_OPEN_SECRET - probably an open */ -typedef struct r_samr_open_secret_info -{ - LSA_POL_HND pol; /* policy handle associated with the SID */ - uint32 status; /* return status */ - -} SAMR_R_OPEN_SECRET; - - -/**************************************************************************** -SAMR_Q_LOOKUP_RIDS - do a conversion (only one!) from name to RID. - -the policy handle allocated by an "samr open secret" call is associated -with a SID. this policy handle is what is queried here, *not* the SID -itself. the response to the lookup rids is relative to this SID. -*****************************************************************************/ -/* SAMR_Q_LOOKUP_RIDS - probably a "read SAM entry" */ -typedef struct q_samr_lookup_names_info -{ - LSA_POL_HND pol; /* policy handle */ - - uint32 num_rids1; /* 1 - number of rids being looked up */ - uint32 rid; /* 0000 03e8 - RID of the server being queried? */ - uint32 ptr; /* 0 - 32 bit unknown */ - uint32 num_rids2; /* 1 - number of rids being looked up */ - - UNIHDR hdr_mach_acct; /* unicode machine account name header */ - UNISTR2 uni_mach_acct; /* unicode machine account name */ - -} SAMR_Q_LOOKUP_RIDS; - - -/* SAMR_R_LOOKUP_RIDS - probably an open */ -typedef struct r_samr_lookup_names_info -{ - uint32 num_entries; - uint32 undoc_buffer; /* undocumented buffer pointer */ - - uint32 num_entries2; - DOM_RID3 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ - - uint32 num_entries3; - - uint32 status; /* return code */ - -} SAMR_R_LOOKUP_RIDS; - - -/* SAMR_Q_UNKNOWN_22 - probably an open */ -typedef struct q_samr_unknown_22_info -{ - LSA_POL_HND pol; /* policy handle */ - uint32 unknown_id_0; /* 0x0000 03E8 - 32 bit unknown id */ - -} SAMR_Q_UNKNOWN_22; - - -/* SAMR_R_UNKNOWN_22 - probably an open */ -typedef struct r_samr_unknown_22_info -{ - LSA_POL_HND pol; /* policy handle associated with unknown id */ - uint32 status; /* return status */ - -} SAMR_R_UNKNOWN_22; - - -/* SAMR_Q_UNKNOWN_24 - probably a get sam info */ -typedef struct q_samr_unknown_24_info -{ - LSA_POL_HND pol; /* policy handle associated with unknown id */ - uint16 unknown_0; /* 0x0015 or 0x0011 - 16 bit unknown */ - -} SAMR_Q_UNKNOWN_24; - - -/* SAMR_R_UNKNOWN_24 - probably a get sam info */ -typedef struct r_samr_unknown_24_info -{ - uint32 ptr; /* pointer */ - uint16 unknown_0; /* 0x0015 or 0x0011 - 16 bit unknown (same as above) */ - uint16 unknown_1; /* 0x8b73 - 16 bit unknown */ - uint8 padding_0[16]; /* 0 - padding 16 bytes */ - NTTIME expiry; /* expiry time or something? */ - uint8 padding_1[24]; /* 0 - padding 24 bytes */ - - UNIHDR hdr_mach_acct; /* unicode header for machine account */ - uint32 padding_2; /* 0 - padding 4 bytes */ - - uint32 ptr_1; /* pointer */ - uint8 padding_3[32]; /* 0 - padding 32 bytes */ - uint32 padding_4; /* 0 - padding 4 bytes */ - - uint32 ptr_2; /* pointer */ - uint32 padding_5; /* 0 - padding 4 bytes */ - - uint32 ptr_3; /* pointer */ - uint8 padding_6[32]; /* 0 - padding 32 bytes */ - - uint32 unknown_id_0; /* unknown id associated with policy handle */ - uint16 unknown_2; /* 0x0201 - 16 bit unknown */ - uint32 unknown_3; /* 0x0000 0080 - 32 bit unknown */ - uint16 unknown_4; /* 0x003f - 16 bit unknown */ - uint16 unknown_5; /* 0x003c - 16 bit unknown */ - - uint8 padding_7[16]; /* 0 - padding 16 bytes */ - uint32 padding_8; /* 0 - padding 4 bytes */ - - UNISTR2 uni_mach_acct; /* unicode string for machine account */ - - uint8 padding_9[48]; /* 0 - padding 48 bytes */ - - uint32 status; /* return status */ - -} SAMR_R_UNKNOWN_24; - - -/* SAMR_Q_UNKNOWN_32 - probably a "create SAM entry" */ -typedef struct q_samr_unknown_32_info -{ - LSA_POL_HND pol; /* policy handle */ - - UNIHDR hdr_mach_acct; /* unicode machine account name header */ - UNISTR2 uni_mach_acct; /* unicode machine account name */ - - uint32 unknown_0; /* 32 bit unknown */ - uint16 unknown_1; /* 16 bit unknown */ - uint16 unknown_2; /* 16 bit unknown */ - -} SAMR_Q_UNKNOWN_32; - - -/* SAMR_R_UNKNOWN_32 - probably a "create SAM entry" */ -typedef struct r_samr_unknown_32_info -{ - LSA_POL_HND pol; /* policy handle */ - uint32 unknown_0; /* 0x0000 0030 - 32 bit unknown */ - uint32 padding; /* 0 - 4 byte padding */ - - uint32 status; /* return status - 0xC000 0099: user exists */ - -} SAMR_R_UNKNOWN_32; - - -/* SAMR_Q_OPEN_POLICY - probably an open */ -typedef struct q_samr_open_policy_info -{ - uint32 ptr_srv_name; /* pointer (to server name?) */ - UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */ - - uint32 unknown_0; /* 32 bit unknown */ - -} SAMR_Q_OPEN_POLICY; - - -/* SAMR_R_OPEN_POLICY - probably an open */ -typedef struct r_samr_open_policy_info -{ - LSA_POL_HND pol; /* policy handle */ - uint32 status; /* return status */ - -} SAMR_R_OPEN_POLICY; - - -/* WKS_Q_UNKNOWN_0 - probably a capabilities request */ -typedef struct q_wks_unknown_0_info -{ - uint32 ptr_srv_name; /* pointer (to server name?) */ - UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */ - - uint32 unknown_0; /* 0x64 - 32 bit unknown */ - uint16 unknown_1; /* 16 bit unknown */ - -} WKS_Q_UNKNOWN_0; - - -/* WKS_R_UNKNOWN_0 - probably a capabilities request */ -typedef struct r_wks_unknown_0_info -{ - uint32 unknown_0; /* 64 - unknown */ - uint32 ptr_1; /* pointer 1 */ - uint32 unknown_1; /* 0x0000 01f4 - unknown */ - uint32 ptr_srv_name; /* pointer to server name */ - uint32 ptr_dom_name; /* pointer to domain name */ - uint32 unknown_2; /* 4 - unknown */ - uint32 unknown_3; /* 0 - unknown */ - - UNISTR2 uni_srv_name; /* unicode server name */ - UNISTR2 uni_dom_name; /* unicode domainn name */ - uint32 status; /* return status */ - -} WKS_R_UNKNOWN_0; - +/* Allowable account control bits */ +#define ACB_DISABLED 0x0001 /* 1 = User account disabled */ +#define ACB_HOMDIRREQ 0x0002 /* 1 = Home directory required */ +#define ACB_PWNOTREQ 0x0004 /* 1 = User password not required */ +#define ACB_TEMPDUP 0x0008 /* 1 = Temporary duplicate account */ +#define ACB_NORMAL 0x0010 /* 1 = Normal user account */ +#define ACB_MNS 0x0020 /* 1 = MNS logon user account */ +#define ACB_DOMTRUST 0x0040 /* 1 = Interdomain trust account */ +#define ACB_WSTRUST 0x0080 /* 1 = Workstation trust account */ +#define ACB_SVRTRUST 0x0100 /* 1 = Server trust account */ +#define ACB_PWNOEXP 0x0200 /* 1 = User password does not expire */ +#define ACB_AUTOLOCK 0x0400 /* 1 = Account auto locked */ + struct smb_passwd { int smb_userid; @@ -1335,6 +286,7 @@ struct smb_passwd unsigned char *smb_passwd; /* Null if no password */ unsigned char *smb_nt_passwd; /* Null if no password */ /* Other fields / flags may be added later */ + uint16 acct_ctrl; }; struct cli_state { @@ -1491,6 +443,20 @@ typedef struct } connection_struct; +/* DOM_CHAL - challenge info */ +typedef struct chal_info +{ + uchar data[8]; /* credentials */ +} DOM_CHAL; + +/* DOM_CREDs - timestamped client or server credentials */ +typedef struct cred_info +{ + DOM_CHAL challenge; /* credentials */ + UTIME timestamp; /* credential time-stamp */ + +} DOM_CRED; + /* Domain controller authentication protocol info */ struct dcinfo { @@ -2058,6 +1024,14 @@ char *Strstr(char *s, char *p); #define BROWSER_ELECTION_VERSION 0x010f #define BROWSER_CONSTANT 0xaa55 +/* NT Flags2 bits - cifs6.txt section 3.1.2 */ + +#define FLAGS2_LONG_PATH_COMPONENTS 0x0001 +#define FLAGS2_EXTENDED_ATTRIBUTES 0x0002 +#define FLAGS2_DFS_PATHNAMES 0x1000 +#define FLAGS2_READ_PERMIT_NO_EXECUTE 0x2000 +#define FLAGS2_32_BIT_ERROR_CODES 0x4000 +#define FLAGS2_UNICODE_STRINGS 0x8000 /* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */ @@ -2129,8 +1103,6 @@ enum case_handling {CASE_LOWER,CASE_UPPER}; #define UID_FIELD_INVALID 0 #define VUID_OFFSET 100 /* Amount to bias returned vuid numbers */ -#endif - /* Defines needed for multi-codepage support. */ #define MSDOS_LATIN_1_CODEPAGE 850 #define KANJI_CODEPAGE 932 @@ -2227,4 +1199,8 @@ extern int unix_ERR_code; #define CMD_REPLY 0x8000 +#endif /* _SMB_H */ + +#include "ntdomain.h" + /* _SMB_H */ diff --git a/source3/lib/membuffer.c b/source3/lib/membuffer.c new file mode 100644 index 0000000000..0665b19ead --- /dev/null +++ b/source3/lib/membuffer.c @@ -0,0 +1,370 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba memory buffer functions + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + + 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. +*/ + +/******************************************************************* + * + * Description: memory buffer / stream management. + * Author : Luke K C Leighton + * Created : Dec 1997 + * + + * this module is intended for use in streaming data in and out of + * buffers. it is intended that a single data stream be subdivided + * into manageable sections. + + * for example, an rpc header contains a length field, but until the + * data has been created, the length is unknown. using this module, + * the header section can be tacked onto the front of the data memory + * list once the size of the data section preceding it is known. + + * the "margin" can be used to over-run and retrospectively lengthen + * the buffer. this is to save time in some of the loops, where it is + * not particularly desirable to realloc data by 1, 2 or 4 bytes + * repetitively... + + * each memory buffer contains a start and end offset. the end of + * one buffer should equal to the start of the next in the chain. + * (end - start = len, instead of end - start + 1 = len) + + * the debug log levels are very high in some of the routines: you + * have no idea how boring it gets staring at debug output from these + + ********************************************************************/ + + +#include "includes.h" + +extern int DEBUGLEVEL; + +/******************************************************************* + initialise a memory buffer. + ********************************************************************/ +void mem_init(struct mem_buf *buf, int margin) +{ + buf->dynamic = True; + buf->data = NULL; + buf->data_size = 0; + buf->data_used = 0; + + buf->margin = margin; + + buf->next = NULL; + + buf->offset.start = 0; + buf->offset.end = 0; +} + +/******************************************************************* + initialise a memory buffer. + + dynamic indicates memory has been dynamically allocated. + if mem_free is called, the memory will be freed. + ********************************************************************/ +void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dynamic) +{ + buf->dynamic = dynamic; + buf->data = data; + buf->data_size = size; + buf->data_used = size; + + buf->margin = margin; + + buf->next = NULL; + + buf->offset.start = 0; + buf->offset.end = size; +} + +/******************************************************************* + takes a memory buffer out of one structure: puts it in the other. + NULLs the one that the buffer is being stolen from. + ********************************************************************/ +void mem_take(struct mem_buf *mem_to, struct mem_buf *mem_from) +{ + memcpy(mem_to, mem_from, sizeof(*mem_to)); + + mem_init(mem_from, mem_from->margin); +} + +/******************************************************************* + allocate a memory buffer. assume it's empty + ********************************************************************/ +BOOL mem_alloc_data(struct mem_buf *buf, int size) +{ + if (!buf->dynamic) + { + DEBUG(3,("mem_alloc_data: warning - memory buffer type is set to static\n")); + } + + buf->data_size = size + buf->margin; + buf->data_used = size; + + buf->data = malloc(buf->data_size); + + if (buf->data == NULL) + { + DEBUG(3,("mem_alloc: could not malloc size %d\n", + buf->data_size)); + mem_init(buf, buf->margin); + + return False; + } + + bzero(buf->data, buf->data_size); + + return True; +} + +/******************************************************************* + allocates a memory buffer structure + ********************************************************************/ +BOOL mem_buf_copy(char *copy_into, struct mem_buf *buf, + uint32 offset, uint32 len) +{ + uint32 end = offset + len; + char *q = NULL; + uint32 data_len = mem_buf_len(buf); + uint32 start_offset = offset; + struct mem_buf **bcp = &buf; + + if (buf == NULL || copy_into == NULL) return False; + + DEBUG(200,("mem_buf_copy: data[%d..%d] offset %d len %d\n", + buf->offset.start, data_len, offset, len)); + + /* there's probably an off-by-one bug, here, and i haven't even tested the code :-) */ + while (offset < end && ((q = mem_data(bcp, offset)) != NULL)) + { + uint32 copy_len = (*bcp)->offset.end - offset; + + DEBUG(200,("\tdata[%d..%d] - offset %d len %d\n", + (*bcp)->offset.start, (*bcp)->offset.end, + offset, copy_len)); + + memcpy(copy_into, q, copy_len); + + offset += copy_len; + copy_into += copy_len; + } + + if ((*bcp) != NULL) + { + DEBUG(200,("mem_buf_copy: copied %d bytes\n", offset - start_offset)); + } + else + { + DEBUG(200,("mem_buf_copy: failed\n")); + } + + return buf != NULL; +} + +/******************************************************************* + allocates a memory buffer structure + ********************************************************************/ +BOOL mem_buf_init(struct mem_buf **buf, uint32 margin) +{ + if (buf == NULL) return False; + + if ((*buf) == NULL) + { + (*buf) = malloc(sizeof(**buf)); + if ((*buf) != NULL) + { + mem_init((*buf), margin); + return True; + } + } + else + { + (*buf)->margin = margin; + return True; + } + return False; +} + +/******************************************************************* + frees up a memory buffer. + ********************************************************************/ +void mem_buf_free(struct mem_buf **buf) +{ + if (buf == NULL) return; + if ((*buf) == NULL) return; + + mem_free_data(*buf); /* delete memory data */ + free(*buf); /* delete item */ + (*buf) = NULL; +} + +/******************************************************************* + frees a memory buffer chain. assumes that all items are malloced. + ********************************************************************/ +void mem_free_chain(struct mem_buf **buf) +{ + if (buf == NULL) return; + if ((*buf) == NULL) return; + + if ((*buf)->next != NULL) + { + mem_free_chain(&((*buf)->next)); /* delete all other items in chain */ + } + mem_buf_free(buf); +} + +/******************************************************************* + frees a memory buffer. + ********************************************************************/ +void mem_free_data(struct mem_buf *buf) +{ + if (buf == NULL) return; + + if (buf->data != NULL && buf->dynamic) + { + free(buf->data); /* delete data in this structure */ + } + mem_init(buf, buf->margin); +} + +/******************************************************************* + reallocate a memory buffer, including a safety margin + ********************************************************************/ +BOOL mem_realloc_data(struct mem_buf *buf, int new_size) +{ + char *new_data; + + if (!buf->dynamic) + { + DEBUG(3,("mem_realloc_data: memory buffer has not been dynamically allocated!\n")); + return False; + } + + if (new_size == 0) + { + mem_free_data(buf); + return True; + } + + new_data = Realloc(buf->data, new_size + buf->margin); + + if (new_data != NULL) + { + buf->data = new_data; + buf->data_size = new_size + buf->margin; + buf->data_used = new_size; + } + else if (buf->data_size <= new_size) + { + DEBUG(3,("mem_realloc: warning - could not realloc to %d(+%d)\n", + new_size, buf->margin)); + + buf->data_used = new_size; + } + else + { + DEBUG(3,("mem_realloc: error - could not realloc to %d\n", + new_size)); + + mem_free_data(buf); + return False; + } + + return True; +} + +/******************************************************************* + reallocate a memory buffer, retrospectively :-) + ********************************************************************/ +BOOL mem_grow_data(struct mem_buf **buf, BOOL io, int new_size) +{ + if (new_size + (*buf)->margin >= (*buf)->data_size) + { + if (io) + { + DEBUG(3,("mem_grow_data: cannot resize when reading from a data stream\n")); + } + else + { + return mem_realloc_data((*buf), new_size); + return False; + } + } + return True; +} + +/******************************************************************* + search for a memory buffer that falls within the specified offset + ********************************************************************/ +BOOL mem_find(struct mem_buf **buf, uint32 offset) +{ + struct mem_buf *f; + if (buf == NULL) return False; + + f = *buf; + + DEBUG(200,("mem_find: data[%d..%d] offset: %d\n", + f->offset.start, f->offset.end, offset)); + + while (f != NULL && offset >= f->offset.end) + { + f = f->next; + + DEBUG(200,("mem_find: next[%d..%d]\n", + f->offset.start, f->offset.end)); + } + + (*buf) = f; + + DEBUG(200,("mem_find: found data[%d..%d]\n", + (*buf)->offset.start,(*buf)->offset.end)); + + return f != NULL; +} + + +/******************************************************************* + add up the lengths of all sections. + ********************************************************************/ +uint32 mem_buf_len(struct mem_buf *buf) +{ + int len = 0; + while (buf != NULL) + { + len += buf->offset.end - buf->offset.start; + buf = buf->next; + } + return len; +} + + +/******************************************************************* + return the memory location specified by offset. may return NULL. + ********************************************************************/ +char *mem_data(struct mem_buf **buf, uint32 offset) +{ + if (mem_find(buf, offset)) + { + return &((*buf)->data[offset - (*buf)->offset.start]); + } + return NULL; +} + + diff --git a/source3/lib/util.c b/source3/lib/util.c index 5af41cc06c..19fa42592f 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -4848,4 +4848,29 @@ char *tab_depth(int depth) return spaces; } +/***************************************************************** + Convert a domain SID to an ascii string. (non-reentrant). +*****************************************************************/ +/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ +char *dom_sid_to_string(DOM_SID *sid) +{ + static pstring sidstr; + char subauth[16]; + int i; + uint32 ia = (sid->id_auth[5]) + + (sid->id_auth[4] << 8 ) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + sprintf(sidstr, "S-%d-%d", sid->sid_rev_num, ia); + + for (i = 0; i < sid->num_auths; i++) + { + sprintf(subauth, "-%d", sid->sub_auths[i]); + strcat(sidstr, subauth); + } + + DEBUG(7,("dom_sid_to_string returning %s\n", sidstr)); + return sidstr; +} diff --git a/source3/lib/util_hnd.c b/source3/lib/util_hnd.c new file mode 100644 index 0000000000..c8eabf35b4 --- /dev/null +++ b/source3/lib/util_hnd.c @@ -0,0 +1,316 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * + * 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" + + +extern int DEBUGLEVEL; + +#ifndef MAX_OPEN_POLS +#define MAX_OPEN_POLS 50 +#endif + +struct reg_info +{ + /* for use by \PIPE\winreg */ + fstring name; /* name of registry key */ +}; + +struct samr_info +{ + /* for use by the \PIPE\samr policy */ + DOM_SID sid; + uint32 rid; /* relative id associated with the pol_hnd */ + uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ +}; + +static struct +{ + BOOL open; + POLICY_HND pol_hnd; + + union + { + struct samr_info samr; + struct reg_info reg; + + } dev; + +} Policy[MAX_OPEN_POLS]; + + +#define VALID_POL(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_POLS)) +#define OPEN_POL(pnum) (VALID_POL(pnum) && Policy[pnum].open) + +/**************************************************************************** + create a unique policy handle +****************************************************************************/ +void create_pol_hnd(POLICY_HND *hnd) +{ + static uint32 pol_hnd_low = 0; + static uint32 pol_hnd_high = 0; + + if (hnd == NULL) return; + + /* i severely doubt that pol_hnd_high will ever be non-zero... */ + pol_hnd_low++; + if (pol_hnd_low == 0) pol_hnd_high++; + + SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */ + SIVAL(hnd->data, 4 , pol_hnd_low ); /* second bit is incrementing */ + SIVAL(hnd->data, 8 , pol_hnd_high); /* second bit is incrementing */ + SIVAL(hnd->data, 12, time(NULL)); /* something random */ + SIVAL(hnd->data, 16, getpid()); /* something more random */ +} + +/**************************************************************************** + initialise policy handle states... +****************************************************************************/ +void init_lsa_policy_hnd(void) +{ + int i; + for (i = 0; i < MAX_OPEN_POLS; i++) + { + Policy[i].open = False; + } + + return; +} + +/**************************************************************************** + find first available policy slot. creates a policy handle for you. +****************************************************************************/ +BOOL open_lsa_policy_hnd(POLICY_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_POLS; i++) + { + if (!Policy[i].open) + { + Policy[i].open = True; + + create_pol_hnd(hnd); + memcpy(&(Policy[i].pol_hnd), hnd, sizeof(*hnd)); + + DEBUG(4,("Opened policy hnd[%x] ", i)); + dump_data(4, hnd->data, sizeof(hnd->data)); + + return True; + } + } + + /* i love obscure error messages. */ +#if TERRY_PRATCHET_INTERESTING_TIMES + DEBUG(1,("+++ OUT OF CHEESE ERROR +++ REDO FROM START ... @?!*@@\n")); +#else + DEBUG(1,("ERROR - open_lsa_policy_hnd: out of Policy Handles!\n")); +#endif + + return False; +} + +/**************************************************************************** + find policy index by handle +****************************************************************************/ +int find_lsa_policy_by_hnd(POLICY_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_POLS; i++) + { + if (memcmp(&(Policy[i].pol_hnd), hnd, sizeof(*hnd)) == 0) + { + DEBUG(4,("Found policy hnd[%x] ", i)); + dump_data(4, hnd->data, sizeof(hnd->data)); + + return i; + } + } + + DEBUG(4,("Policy not found: ")); + dump_data(4, hnd->data, sizeof(hnd->data)); + + return -1; +} + +/**************************************************************************** + set samr rid +****************************************************************************/ +BOOL set_lsa_policy_samr_rid(POLICY_HND *hnd, uint32 rid) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy device rid=%x pnum=%x\n", + timestring(), rid, pnum)); + + Policy[pnum].dev.samr.rid = rid; + return True; + } + else + { + DEBUG(3,("%s Error setting policy rid=%x (pnum=%x)\n", + timestring(), rid, pnum)); + return False; + } +} + +/**************************************************************************** + set samr pol status. absolutely no idea what this is. +****************************************************************************/ +BOOL set_lsa_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy status=%x pnum=%x\n", + timestring(), pol_status, pnum)); + + Policy[pnum].dev.samr.status = pol_status; + return True; + } + else + { + DEBUG(3,("%s Error setting policy status=%x (pnum=%x)\n", + timestring(), pol_status, pnum)); + return False; + } +} + +/**************************************************************************** + set samr sid +****************************************************************************/ +BOOL set_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy sid=%s pnum=%x\n", + timestring(), dom_sid_to_string(sid), pnum)); + + memcpy(&(Policy[pnum].dev.samr.sid), sid, sizeof(*sid)); + return True; + } + else + { + DEBUG(3,("%s Error setting policy sid=%s (pnum=%x)\n", + timestring(), dom_sid_to_string(sid), pnum)); + return False; + } +} + +/**************************************************************************** + set samr rid +****************************************************************************/ +uint32 get_lsa_policy_samr_rid(POLICY_HND *hnd) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + uint32 rid = Policy[pnum].dev.samr.rid; + DEBUG(3,("%s Getting policy device rid=%x pnum=%x\n", + timestring(), rid, pnum)); + + return rid; + } + else + { + DEBUG(3,("%s Error getting policy (pnum=%x)\n", + timestring(), pnum)); + return 0xffffffff; + } +} + +/**************************************************************************** + set reg name +****************************************************************************/ +BOOL set_lsa_policy_reg_name(POLICY_HND *hnd, fstring name) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy pnum=%x name=%s\n", + timestring(), pnum, name)); + + fstrcpy(Policy[pnum].dev.reg.name, name); + return True; + } + else + { + DEBUG(3,("%s Error setting policy (pnum=%x) name=%s\n", + timestring(), pnum, name)); + return False; + } +} + +/**************************************************************************** + get reg name +****************************************************************************/ +BOOL get_lsa_policy_reg_name(POLICY_HND *hnd, fstring name) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + fstrcpy(name, Policy[pnum].dev.reg.name); + + DEBUG(3,("%s Getting policy pnum=%x name=%s\n", + timestring(), pnum, name)); + + return True; + } + else + { + DEBUG(3,("%s Error getting policy (pnum=%x)\n", + timestring(), pnum)); + return False; + } +} + +/**************************************************************************** + close an lsa policy +****************************************************************************/ +BOOL close_lsa_policy_hnd(POLICY_HND *hnd) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Closed policy name pnum=%x\n", timestring(), pnum)); + Policy[pnum].open = False; + return True; + } + else + { + DEBUG(3,("%s Error closing policy pnum=%x\n", timestring(), pnum)); + return False; + } +} + diff --git a/source3/lsarpcd/srv_lsa.c b/source3/lsarpcd/srv_lsa.c new file mode 100644 index 0000000000..60b74cf599 --- /dev/null +++ b/source3/lsarpcd/srv_lsa.c @@ -0,0 +1,444 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + + +/*************************************************************************** +lsa_reply_open_policy + ***************************************************************************/ +static void lsa_reply_open_policy(prs_struct *rdata) +{ + int i; + LSA_R_OPEN_POL r_o; + + /* set up the LSA QUERY INFO response */ + bzero(&(r_o.pol.data), POL_HND_SIZE); + for (i = 4; i < POL_HND_SIZE; i++) + { + r_o.pol.data[i] = i; + } + r_o.status = 0x0; + + /* store the response in the SMB stream */ + lsa_io_r_open_pol("", &r_o, rdata, 0); +} + +/*************************************************************************** +make_dom_query + ***************************************************************************/ +static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +{ + int domlen = strlen(dom_name); + + d_q->uni_dom_max_len = domlen * 2; + d_q->uni_dom_str_len = domlen * 2; + + d_q->buffer_dom_name = 4; /* domain buffer pointer */ + d_q->buffer_dom_sid = 2; /* domain sid pointer */ + + /* this string is supposed to be character short */ + make_unistr2(&(d_q->uni_domain_name), dom_name, domlen); + + make_dom_sid2(&(d_q->dom_sid), dom_sid); +} + +/*************************************************************************** +lsa_reply_query_info + ***************************************************************************/ +static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e, + prs_struct *rdata, + uint32 enum_context, char *dom_name, char *dom_sid) +{ + LSA_R_ENUM_TRUST_DOM r_e; + + /* set up the LSA QUERY INFO response */ + make_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid, + dom_name != NULL ? 0x0 : 0x80000000 | NT_STATUS_UNABLE_TO_FREE_VM); + + /* store the response in the SMB stream */ + lsa_io_r_enum_trust_dom("", &r_e, rdata, 0); +} + +/*************************************************************************** +lsa_reply_query_info + ***************************************************************************/ +static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata, + char *dom_name, char *dom_sid) +{ + LSA_R_QUERY_INFO r_q; + + /* set up the LSA QUERY INFO response */ + + r_q.undoc_buffer = 0x22000000; /* bizarre */ + r_q.info_class = q_q->info_class; + + make_dom_query(&r_q.dom.id5, dom_name, dom_sid); + + r_q.status = 0x0; + + /* store the response in the SMB stream */ + lsa_io_r_query("", &r_q, rdata, 0); +} + +/*************************************************************************** +make_dom_ref + + pretty much hard-coded choice of "other" sids, unfortunately... + + ***************************************************************************/ +static void make_dom_ref(DOM_R_REF *ref, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int len_dom_name = strlen(dom_name); + int len_other_sid1 = strlen(other_sid1); + int len_other_sid2 = strlen(other_sid2); + int len_other_sid3 = strlen(other_sid3); + + ref->undoc_buffer = 1; + ref->num_ref_doms_1 = 4; + ref->buffer_dom_name = 1; + ref->max_entries = 32; + ref->num_ref_doms_2 = 4; + + make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); + make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); + + if (dom_name != NULL) + { + make_unistr(&(ref->uni_dom_name), dom_name); + } + + make_dom_sid2(&(ref->ref_dom[0]), dom_sid ); + make_dom_sid2(&(ref->ref_dom[1]), other_sid1); + make_dom_sid2(&(ref->ref_dom[2]), other_sid2); + make_dom_sid2(&(ref->ref_dom[3]), other_sid3); +} + +/*************************************************************************** +make_reply_lookup_rids + ***************************************************************************/ +static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); + } + + r_l->num_entries3 = num_entries; +} + +/*************************************************************************** +make_lsa_trans_names + ***************************************************************************/ +static void make_lsa_trans_names(LSA_TRANS_NAME_ENUM *trn, + int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], + uint32 *total) +{ + uint32 status = 0x0; + int i; + (*total) = 0; + + for (i = 0; i < num_entries; i++) + { + uint32 rid = 0xffffffff; + uint8 num_auths = sid[i].sid.num_auths; + fstring name; + uint32 type; + + trn->ptr_name[i] = 0; + trn->ptr_name[(*total)] = 0; + + /* find the rid to look up */ + if (num_auths != 0) + { + rid = sid[i].sid.sub_auths[num_auths-1]; + + status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + + status = (status != 0x0) ? lookup_user_name (rid, name, &type) : status; + status = (status != 0x0) ? lookup_group_name(rid, name, &type) : status; + status = (status != 0x0) ? lookup_alias_name(rid, name, &type) : status; + } + + if (status == 0x0) + { + trn->ptr_name[i] = 1; + make_lsa_trans_name(&(trn->name[(*total)]), type, name, (*total)); + (*total)++; + } + } + + trn->num_entries = (*total); + trn->ptr_trans_names = 1; + trn->num_entries2 = (*total); +} + +/*************************************************************************** +make_reply_lookup_sids + ***************************************************************************/ +static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, + DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names, + uint32 mapped_count, uint32 status) +{ + r_l->dom_ref = ref; + r_l->names = names; + r_l->mapped_count = mapped_count; + r_l->status = status; +} + +/*************************************************************************** +lsa_reply_lookup_sids + ***************************************************************************/ +static void lsa_reply_lookup_sids(prs_struct *rdata, + int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + LSA_R_LOOKUP_SIDS r_l; + DOM_R_REF ref; + LSA_TRANS_NAME_ENUM names; + uint32 mapped_count = 0; + + /* set up the LSA Lookup SIDs response */ + make_dom_ref(&ref, dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + make_lsa_trans_names(&names, num_entries, sid, &mapped_count); + make_reply_lookup_sids(&r_l, &ref, &names, mapped_count, 0x0); + + /* store the response in the SMB stream */ + lsa_io_r_lookup_sids("", &r_l, rdata, 0); +} + +/*************************************************************************** +lsa_reply_lookup_rids + ***************************************************************************/ +static void lsa_reply_lookup_rids(prs_struct *rdata, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + LSA_R_LOOKUP_RIDS r_l; + + /* set up the LSA Lookup RIDs response */ + make_reply_lookup_rids(&r_l, num_entries, dom_rids, + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + lsa_io_r_lookup_rids("", &r_l, rdata, 0); +} + +/*************************************************************************** +api_lsa_open_policy + ***************************************************************************/ +static void api_lsa_open_policy( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_OPEN_POL q_o; + + /* grab the server, object attributes and desired access flag...*/ + lsa_io_q_open_pol("", &q_o, data, 0); + + /* lkclXXXX having decoded it, ignore all fields in the open policy! */ + + /* return a 20 byte policy handle */ + lsa_reply_open_policy(rdata); +} + +/*************************************************************************** +api_lsa_enum_trust_dom + ***************************************************************************/ +static void api_lsa_enum_trust_dom( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_ENUM_TRUST_DOM q_e; + + /* grab the enum trust domain context etc. */ + lsa_io_q_enum_trust_dom("", &q_e, data, 0); + + /* construct reply. return status is always 0x0 */ + lsa_reply_enum_trust_dom(&q_e, rdata, + 0, NULL, NULL); +} + +/*************************************************************************** +api_lsa_query_info + ***************************************************************************/ +static void api_lsa_query_info( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_QUERY_INFO q_i; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_query("", &q_i, data, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domain_sid()); + + /* construct reply. return status is always 0x0 */ + lsa_reply_query_info(&q_i, rdata, dom_name, dom_sid); +} + +/*************************************************************************** +api_lsa_lookup_sids + ***************************************************************************/ +static void api_lsa_lookup_sids( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_LOOKUP_SIDS q_l; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_sids("", &q_l, data, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domain_sid()); + + /* construct reply. return status is always 0x0 */ + lsa_reply_lookup_sids(rdata, + q_l.sids.num_entries, q_l.sids.sid, /* SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ +} + +/*************************************************************************** +api_lsa_lookup_names + ***************************************************************************/ +static void api_lsa_lookup_names( int uid, prs_struct *data, + prs_struct *rdata ) +{ + int i; + LSA_Q_LOOKUP_RIDS q_l; + pstring dom_name; + pstring dom_sid; + uint32 dom_rids[MAX_LOOKUP_SIDS]; + uint32 dummy_g_rid; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_rids("", &q_l, data, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domain_sid()); + + /* convert received RIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + char *user_name = unistr2(q_l.lookup_name[i].str.buffer); + if (!name_to_rid(user_name, &dom_rids[i], &dummy_g_rid)) + { + /* WHOOPS! we should really do something about this... */ + dom_rids[i] = 0; + } + } + + /* construct reply. return status is always 0x0 */ + lsa_reply_lookup_rids(rdata, + q_l.num_entries, dom_rids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ +} + +/*************************************************************************** + api_lsa_close + ***************************************************************************/ +static void api_lsa_close( int uid, prs_struct *data, + prs_struct *rdata) +{ + /* XXXX this is NOT good */ + char *q = mem_data(&(rdata->data), rdata->offset); + + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + + rdata->offset += 24; +} + +/*************************************************************************** + api_lsa_open_secret + ***************************************************************************/ +static void api_lsa_open_secret( int uid, prs_struct *data, + prs_struct *rdata) +{ + /* XXXX this is NOT good */ + char *q = mem_data(&(rdata->data), rdata->offset); + + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND); q += 4; + + rdata->offset += 24; +} + +/*************************************************************************** + \PIPE\ntlsa commands + ***************************************************************************/ +static struct api_struct api_lsa_cmds[] = +{ + { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, + { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info }, + { "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom }, + { "LSA_CLOSE" , LSA_CLOSE , api_lsa_close }, + { "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret }, + { "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids }, + { "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names }, + { NULL , 0 , NULL } +}; + +/*************************************************************************** + api_ntLsarpcTNP + ***************************************************************************/ +BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_ntlsa_rpc", api_lsa_cmds, data); +} + diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index 64f66038e0..f881b867c0 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -195,7 +195,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", * Let's ignore the SID. */ - strcpy(ascuser, unistr(uniuser)); + pstrcpy(ascuser, unistr(uniuser)); DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); strcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */ @@ -203,12 +203,18 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", smb_pass = get_smbpwd_entry(ascuser, 0); - if(!smb_pass) + if(!smb_pass ) { DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, not in password file\n", unistr(unicomp),inet_ntoa(p->ip), ascuser)); return; } + else if(smb_pass->acct_ctrl & ACB_DISABLED) + { + DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, accound disabled.\n", + unistr(unicomp),inet_ntoa(p->ip), ascuser)); + return; + } else { DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c index 07692cc82c..e10ddc2c6a 100644 --- a/source3/nmbd/nmbd_subnetdb.c +++ b/source3/nmbd/nmbd_subnetdb.c @@ -300,10 +300,12 @@ struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec) { if(subrec == unicast_subnet) + { if(wins_server_subnet) return wins_server_subnet; else return NULL; + } if(wins_server_subnet && subrec == wins_server_subnet) return NULL; diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index 134b758c29..afc8741366 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -1260,12 +1260,13 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p, } } - for(; i < namerec->num_ips; i++) + for(j = 0; j < namerec->num_ips; j++) { - if(i == same_net_index) + if(j == same_net_index) continue; set_nb_flags(&prdata[i*6],namerec->nb_flags); - putip((char *)&prdata[2+(i*6)], &namerec->ip[i]); + putip((char *)&prdata[2+(i*6)], &namerec->ip[j]); + i++; } reply_data_len = namerec->num_ips * 6; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 39f6de0e1e..2768a9da72 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -461,7 +461,7 @@ static struct parm_struct parm_table[] = {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, 0}, {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars, NULL, 0}, {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL, NULL, FLAG_BASIC}, -#ifdef NTDOMAIN + {"domain sid", P_USTRING, P_GLOBAL, &Globals.szDomainSID, NULL, NULL, 0}, {"domain other sids",P_STRING, P_GLOBAL, &Globals.szDomainOtherSIDs, NULL, NULL, 0}, {"domain groups", P_STRING, P_GLOBAL, &Globals.szDomainGroups, NULL, NULL, 0}, @@ -472,7 +472,7 @@ static struct parm_struct parm_table[] = {"domain allow hosts",P_STRING, P_GLOBAL, &Globals.szDomainHostsallow, NULL, NULL, 0}, {"domain hosts deny", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL, 0}, {"domain deny hosts", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL, 0}, -#endif /* NTDOMAIN */ + {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, 0}, {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set, NULL, 0}, {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, 0}, @@ -898,7 +898,6 @@ FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion) FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases) FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile) -#ifdef NTDOMAIN FN_GLOBAL_STRING(lp_domain_sid,&Globals.szDomainSID) FN_GLOBAL_STRING(lp_domain_other_sids,&Globals.szDomainOtherSIDs) FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups) @@ -906,7 +905,6 @@ FN_GLOBAL_STRING(lp_domain_admin_users,&Globals.szDomainAdminUsers) FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers) FN_GLOBAL_STRING(lp_domain_hostsallow,&Globals.szDomainHostsallow) FN_GLOBAL_STRING(lp_domain_hostsdeny,&Globals.szDomainHostsdeny) -#endif /* NTDOMAIN */ FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy) FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c index fbda8949bc..b51f675306 100644 --- a/source3/passdb/smbpass.c +++ b/source3/passdb/smbpass.c @@ -19,854 +19,844 @@ #include "includes.h" -extern int DEBUGLEVEL; +extern int DEBUGLEVEL; -int gotalarm; +static int gotalarm; +static char s_readbuf[16 * 1024]; -void -gotalarm_sig() +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig() { - gotalarm = 1; + gotalarm = 1; } -int -do_pw_lock(int fd, int waitsecs, int type) +/*************************************************************** + Lock or unlock a fd for a known lock type. Abandon after waitsecs + seconds. +****************************************************************/ + +static int do_pw_lock(int fd, int waitsecs, int type) { - struct flock lock; - int ret; - - gotalarm = 0; - signal(SIGALRM, SIGNAL_CAST gotalarm_sig); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - lock.l_pid = 0; - - alarm(5); - ret = fcntl(fd, F_SETLKW, &lock); - alarm(0); - signal(SIGALRM, SIGNAL_CAST SIG_DFL); - - if (gotalarm) { - DEBUG(0, ("do_pw_lock: failed to %s SMB passwd file.\n", - type == F_UNLCK ? "unlock" : "lock")); - return -1; - } - return ret; + struct flock lock; + int ret; + + gotalarm = 0; + signal(SIGALRM, SIGNAL_CAST gotalarm_sig); + + lock.l_type = type; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 1; + lock.l_pid = 0; + + alarm(5); + ret = fcntl(fd, F_SETLKW, &lock); + alarm(0); + signal(SIGALRM, SIGNAL_CAST SIG_DFL); + + if (gotalarm) { + DEBUG(0, ("do_pw_lock: failed to %s SMB passwd file.\n", + type == F_UNLCK ? "unlock" : "lock")); + return -1; + } + return ret; } -int pw_file_lock(char *name, int type, int secs) +/*************************************************************** + Lock an fd. Abandon after waitsecs seconds. +****************************************************************/ + +int pw_file_lock(int fd, int type, int secs) { - int fd = open(name, O_RDWR | O_CREAT, 0600); - if (fd < 0) - return (-1); - if (do_pw_lock(fd, secs, type)) { - close(fd); - return -1; - } - return fd; + if (fd < 0) + return (-1); + if (do_pw_lock(fd, secs, type)) { + return -1; + } + return fd; } +/*************************************************************** + Unlock an fd. Abandon after waitsecs seconds. +****************************************************************/ + int pw_file_unlock(int fd) { - do_pw_lock(fd, 5, F_UNLCK); - return close(fd); + return do_pw_lock(fd, 5, F_UNLCK); } -/* - * Routine to get the next 32 hex characters and turn them - * into a 16 byte array. - */ +/*************************************************************** + Open the smbpasswd file - get ready to enumerate it. +****************************************************************/ + +FILE *startsmbpwent(BOOL update) +{ + FILE *fp = NULL; + char *pfile = lp_smb_passwd_file(); + + if (!*pfile) { + DEBUG(0, ("startsmbpwent: No SMB password file set\n")); + return (NULL); + } + DEBUG(10, ("startsmbpwent: opening file %s\n", pfile)); + + fp = fopen(pfile, update ? "r+b" : "rb"); + + if (fp == NULL) { + DEBUG(0, ("startsmbpwent: unable to open file %s\n", pfile)); + return NULL; + } + + /* Set a 16k buffer to do more efficient reads */ + setvbuf(fp, s_readbuf, _IOFBF, sizeof(s_readbuf)); + + if ((pw_file_lock(fileno(fp), F_RDLCK | (update ? F_WRLCK : 0), 5)) < 0) { + DEBUG(0, ("startsmbpwent: unable to lock file %s\n", pfile)); + fclose(fp); + return NULL; + } + + /* Make sure it is only rw by the owner */ + chmod(pfile, 0600); + + /* We have a lock on the file. */ + return fp; +} + +/*************************************************************** + Close the smbpasswd file - end enumeration. +****************************************************************/ + +void endsmbpwent(FILE *fp) +{ + pw_file_unlock(fileno(fp)); + fclose(fp); + DEBUG(7, ("endsmbpwent: closed password file.\n")); +} + +/************************************************************* + Routine to get the next 32 hex characters and turn them + into a 16 byte array. +**************************************************************/ static int gethexpwd(char *p, char *pwd) { - int i; - unsigned char lonybble, hinybble; - char *hexchars = "0123456789ABCDEF"; - char *p1, *p2; - - for (i = 0; i < 32; i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); + int i; + unsigned char lonybble, hinybble; + char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; + + for (i = 0; i < 32; i += 2) { + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); - p1 = strchr(hexchars, hinybble); - p2 = strchr(hexchars, lonybble); - if (!p1 || !p2) - return (False); - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); + p1 = strchr(hexchars, hinybble); + p2 = strchr(hexchars, lonybble); + if (!p1 || !p2) + return (False); + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); - pwd[i / 2] = (hinybble << 4) | lonybble; - } - return (True); + pwd[i / 2] = (hinybble << 4) | lonybble; + } + return (True); } /************************************************************************* - Routine to search the smbpasswd file for an entry matching the username - or user id. if the name is NULL, then the smb_uid is used instead. + Routine to return the next entry in the smbpasswd file. *************************************************************************/ -struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid) + +struct smb_passwd *getsmbpwent(FILE *fp) { - /* Static buffers we will return. */ - static struct smb_passwd pw_buf; - static pstring user_name; - static unsigned char smbpwd[16]; - static unsigned char smbntpwd[16]; - char linebuf[256]; - char readbuf[16 * 1024]; - unsigned char c; - unsigned char *p; - long uidval; - long linebuf_len; - FILE *fp; - int lockfd; - char *pfile = lp_smb_passwd_file(); - - if (!*pfile) { - DEBUG(0, ("No SMB password file set\n")); - return (NULL); - } - DEBUG(10, ("get_smbpwd_entry: opening file %s\n", pfile)); - - if (name != NULL) - { - DEBUG(10, ("get_smbpwd_entry: search by name: %s\n", name)); - } - else - { - DEBUG(10, ("get_smbpwd_entry: search by smb_userid: %x\n", smb_userid)); - } - - fp = fopen(pfile, "r"); - - if (fp == NULL) { - DEBUG(0, ("get_smbpwd_entry: unable to open file %s\n", pfile)); - return NULL; - } - /* Set a 16k buffer to do more efficient reads */ - setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - - if ((lockfd = pw_file_lock(pfile, F_RDLCK, 5)) < 0) { - DEBUG(0, ("get_smbpwd_entry: unable to lock file %s\n", pfile)); - fclose(fp); - return NULL; - } - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* We have a read lock on the file. */ - /* - * Scan the file, a line at a time and check if the name matches. - */ - while (!feof(fp)) { - linebuf[0] = '\0'; - - fgets(linebuf, 256, fp); - if (ferror(fp)) { - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - linebuf_len = strlen(linebuf); - if (linebuf[linebuf_len - 1] != '\n') { - c = '\0'; - while (!ferror(fp) && !feof(fp)) { - c = fgetc(fp); - if (c == '\n') - break; - } - } else - linebuf[linebuf_len - 1] = '\0'; + /* Static buffers we will return. */ + static struct smb_passwd pw_buf; + static pstring user_name; + static unsigned char smbpwd[16]; + static unsigned char smbntpwd[16]; + char linebuf[256]; + unsigned char c; + unsigned char *p; + long uidval; + long linebuf_len; + + if(fp == NULL) { + DEBUG(0,("getsmbpwent: Bad password file pointer.\n")); + return NULL; + } + + /* + * Scan the file, a line at a time and check if the name matches. + */ + while (!feof(fp)) { + linebuf[0] = '\0'; + + fgets(linebuf, 256, fp); + if (ferror(fp)) { + return NULL; + } + + /* + * Check if the string is terminated with a newline - if not + * then we must keep reading and discard until we get one. + */ + linebuf_len = strlen(linebuf); + if (linebuf[linebuf_len - 1] != '\n') { + c = '\0'; + while (!ferror(fp) && !feof(fp)) { + c = fgetc(fp); + if (c == '\n') + break; + } + } else + linebuf[linebuf_len - 1] = '\0'; #ifdef DEBUG_PASSWORD - DEBUG(100, ("get_smbpwd_entry: got line |%s|\n", linebuf)); + DEBUG(100, ("getsmbpwent: got line |%s|\n", linebuf)); #endif - if ((linebuf[0] == 0) && feof(fp)) { - DEBUG(4, ("get_smbpwd_entry: end of file reached\n")); - break; - } - /* - * The line we have should be of the form :- - * - * username:uid:[32hex bytes]:....other flags presently - * ignored.... - * - * or, - * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... - * - * if Windows NT compatible passwords are also present. - */ - - if (linebuf[0] == '#' || linebuf[0] == '\0') { - DEBUG(6, ("get_smbpwd_entry: skipping comment or blank line\n")); - continue; - } - p = (unsigned char *) strchr(linebuf, ':'); - if (p == NULL) { - DEBUG(0, ("get_smbpwd_entry: malformed password entry (no :)\n")); - continue; - } - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); - user_name[PTR_DIFF(p, linebuf)] = '\0'; - - /* get smb uid */ - - p++; /* Go past ':' */ - if (!isdigit(*p)) { - DEBUG(0, ("get_smbpwd_entry: malformed password entry (uid not number)\n")); - continue; - } - - uidval = atoi((char *) p); - - while (*p && isdigit(*p)) - { - p++; - } - - if (*p != ':') - { - DEBUG(0, ("get_smbpwd_entry: malformed password entry (no : after uid)\n")); - continue; - } - - if (name != NULL) - { - /* search is by user name */ - if (!strequal(user_name, name)) continue; - DEBUG(10, ("get_smbpwd_entry: found by name: %s\n", user_name)); - } - else - { - /* search is by user id */ - if (uidval != smb_userid) continue; - DEBUG(10, ("get_smbpwd_entry: found by smb_userid: %x\n", uidval)); - } - - /* if we're here, the entry has been found (either by name or uid) */ - - /* - * Now get the password value - this should be 32 hex digits - * which are the ascii representations of a 16 byte string. - * Get two at a time and put them into the password. - */ - - /* skip the ':' */ - p++; - - if (*p == '*' || *p == 'X') - { - /* Password deliberately invalid - end here. */ - DEBUG(10, ("get_smbpwd_entry: entry invalidated for user %s\n", user_name)); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) - { - DEBUG(0, ("get_smbpwd_entry: malformed password entry (passwd too short)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return (False); - } - - if (p[32] != ':') - { - DEBUG(0, ("get_smbpwd_entry: malformed password entry (no terminating :)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - - if (!strncasecmp((char *) p, "NO PASSWORD", 11)) - { - pw_buf.smb_passwd = NULL; - } - else - { - if (!gethexpwd((char *)p, (char *)smbpwd)) - { - DEBUG(0, ("Malformed Lanman password entry (non hex chars)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - pw_buf.smb_passwd = smbpwd; - } - - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; - pw_buf.smb_nt_passwd = NULL; - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { - if (*p != '*' && *p != 'X') { - if(gethexpwd((char *)p,(char *)smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; - } - } - - fclose(fp); - pw_file_unlock(lockfd); - DEBUG(5, ("get_smbpwd_entrye: returning passwd entry for user %s, uid %d\n", + if ((linebuf[0] == 0) && feof(fp)) { + DEBUG(4, ("getsmbpwent: end of file reached\n")); + break; + } + /* + * The line we have should be of the form :- + * + * username:uid:[32hex bytes]:....other flags presently + * ignored.... + * + * or, + * + * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... + * + * if Windows NT compatible passwords are also present. + */ + + if (linebuf[0] == '#' || linebuf[0] == '\0') { + DEBUG(6, ("getsmbpwent: skipping comment or blank line\n")); + continue; + } + p = (unsigned char *) strchr(linebuf, ':'); + if (p == NULL) { + DEBUG(0, ("getsmbpwent: malformed password entry (no :)\n")); + continue; + } + /* + * As 256 is shorter than a pstring we don't need to check + * length here - if this ever changes.... + */ + strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); + user_name[PTR_DIFF(p, linebuf)] = '\0'; + + /* Get smb uid. */ + + p++; /* Go past ':' */ + if (!isdigit(*p)) { + DEBUG(0, ("getsmbpwent: malformed password entry (uid not number)\n")); + continue; + } + + uidval = atoi((char *) p); + + while (*p && isdigit(*p)) + p++; + + if (*p != ':') { + DEBUG(0, ("getsmbpwent: malformed password entry (no : after uid)\n")); + continue; + } + + pw_buf.smb_name = user_name; + pw_buf.smb_userid = uidval; + + /* + * Now get the password value - this should be 32 hex digits + * which are the ascii representations of a 16 byte string. + * Get two at a time and put them into the password. + */ + + /* Skip the ':' */ + p++; + + if (*p == '*' || *p == 'X') { + /* Password deliberately invalid - end here. */ + DEBUG(10, ("getsmbpwent: entry invalidated for user %s\n", user_name)); + pw_buf.smb_nt_passwd = NULL; + pw_buf.smb_passwd = NULL; + pw_buf.acct_ctrl |= ACB_DISABLED; + return &pw_buf; + } + + if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { + DEBUG(0, ("getsmbpwent: malformed password entry (passwd too short)\n")); + continue; + } + + if (p[32] != ':') { + DEBUG(0, ("getsmbpwent: malformed password entry (no terminating :)\n")); + continue; + } + + if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { + pw_buf.smb_passwd = NULL; + pw_buf.acct_ctrl |= ACB_PWNOTREQ; + } else { + if (!gethexpwd((char *)p, (char *)smbpwd)) { + DEBUG(0, ("getsmbpwent: Malformed Lanman password entry (non hex chars)\n")); + continue; + } + pw_buf.smb_passwd = smbpwd; + } + + /* + * Now check if the NT compatible password is + * available. + */ + pw_buf.smb_nt_passwd = NULL; + + p += 33; /* Move to the first character of the line after + the lanman password. */ + if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { + if (*p != '*' && *p != 'X') { + if(gethexpwd((char *)p,(char *)smbntpwd)) + pw_buf.smb_nt_passwd = smbntpwd; + } + p += 33; /* Move to the first character of the line after + the NT password. */ + } + + DEBUG(5, ("getsmbpwent: returning passwd entry for user %s, uid %d\n", user_name, uidval)); - return &pw_buf; - } - fclose(fp); - pw_file_unlock(lockfd); - return NULL; + /* + * Check if the account type bits have been encoded after the + * NT password (in the form [NDHTUWSLXI]). + */ + + if (*p == '[') { + BOOL finished = False; + + pw_buf.acct_ctrl = 0; + + for(p++;*p && !finished; p++) { + switch (*p) { + case 'N': + /* 'N'o password. */ + pw_buf.acct_ctrl |= ACB_PWNOTREQ; + break; + case 'D': + /* 'D'isabled. */ + pw_buf.acct_ctrl |= ACB_DISABLED; + break; + case 'H': + /* 'H'omedir required. */ + pw_buf.acct_ctrl |= ACB_HOMDIRREQ; + break; + case 'T': + /* 'T'emp account. */ + pw_buf.acct_ctrl |= ACB_TEMPDUP; + break; + case 'U': + /* 'U'ser account (normal). */ + pw_buf.acct_ctrl |= ACB_NORMAL; + break; + case 'M': + /* 'M'NS logon user account. What is this ? */ + pw_buf.acct_ctrl |= ACB_MNS; + break; + case 'W': + /* 'W'orkstation account. */ + pw_buf.acct_ctrl |= ACB_WSTRUST; + break; + case 'S': + /* 'S'erver account. */ + pw_buf.acct_ctrl |= ACB_SVRTRUST; + break; + case 'L': + /* 'L'ocked account. */ + pw_buf.acct_ctrl |= ACB_AUTOLOCK; + break; + case 'X': + /* No 'X'piry. */ + pw_buf.acct_ctrl |= ACB_PWNOEXP; + break; + case 'I': + /* 'I'nterdomain trust account. */ + pw_buf.acct_ctrl |= ACB_DOMTRUST; + break; + + case ':': + case '\n': + case '\0': + case ']': + default: + finished = True; + } + } + + /* Must have some account type set. */ + if(pw_buf.acct_ctrl == 0) + pw_buf.acct_ctrl = ACB_NORMAL; + + } else { + /* 'Old' style file. Fake up based on user name. */ + /* + * Currently machine accounts are kept in the same + * password file as 'normal accounts'. If this changes + * we will have to fix this code. JRA. + */ + if(pw_buf.smb_name[strlen(pw_buf.smb_name) - 1] == '$') + pw_buf.acct_ctrl = ACB_WSTRUST; + else + pw_buf.acct_ctrl = ACB_NORMAL; + } + + return &pw_buf; + } + + DEBUG(5,("getsmbpwent: end of file reached.\n")); + return NULL; } -/* - * Routine to search the smbpasswd file for an entry matching the username. - */ -BOOL add_smbpwd_entry(struct smb_passwd* pwd) +/************************************************************************* + Routine to search the smbpasswd file for an entry matching the username + or user id. if the name is NULL, then the smb_uid is used instead. + *************************************************************************/ + +struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid) { - /* Static buffers we will return. */ - static pstring user_name; - - char linebuf[256]; - char readbuf[16 * 1024]; - unsigned char c; - unsigned char *p; - long linebuf_len; - FILE *fp; - int lockfd; - char *pfile = lp_smb_passwd_file(); - - int i; - int wr_len; - - int fd; - int new_entry_length; - char *new_entry; - long offpos; - - if (!*pfile) - { - DEBUG(0, ("No SMB password file set\n")); - return False; - } - DEBUG(10, ("add_smbpwd_entry: opening file %s\n", pfile)); - - fp = fopen(pfile, "r+"); - - if (fp == NULL) - { - DEBUG(0, ("add_smbpwd_entry: unable to open file %s\n", pfile)); - return False; - } - /* Set a 16k buffer to do more efficient reads */ - setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - - if ((lockfd = pw_file_lock(pfile, F_RDLCK | F_WRLCK, 5)) < 0) - { - DEBUG(0, ("add_smbpwd_entry: unable to lock file %s\n", pfile)); - fclose(fp); - return False; - } - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* We have a write lock on the file. */ - /* - * Scan the file, a line at a time and check if the name matches. - */ - while (!feof(fp)) - { - linebuf[0] = '\0'; - - fgets(linebuf, 256, fp); - if (ferror(fp)) - { - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - linebuf_len = strlen(linebuf); - if (linebuf[linebuf_len - 1] != '\n') - { - c = '\0'; - while (!ferror(fp) && !feof(fp)) - { - c = fgetc(fp); - if (c == '\n') - { - break; - } - } - } - else - { - linebuf[linebuf_len - 1] = '\0'; - } + struct smb_passwd *pwd = NULL; + FILE *fp = NULL; + + if (name != NULL) { + DEBUG(10, ("get_smbpwd_entry: search by name: %s\n", name)); + } else { + DEBUG(10, ("get_smbpwd_entry: search by smb_userid: %x\n", smb_userid)); + } + + /* Open the smbpassword file - not for update. */ + fp = startsmbpwent(False); + + if (fp == NULL) { + DEBUG(0, ("get_smbpwd_entry: unable to open password file.\n")); + return NULL; + } + + /* + * Scan the file, a line at a time and check if the name + * or uid matches. + */ + + while ((pwd = getsmbpwent(fp)) != NULL) { + if (name != NULL) { + /* Search is by user name */ + if (!strequal(pwd->smb_name, name)) + continue; + DEBUG(10, ("get_smbpwd_entry: found by name: %s\n", name)); + break; + } else { + /* Search is by user id */ + if (pwd->smb_userid != smb_userid) + continue; + DEBUG(10, ("get_smbpwd_entry: found by smb_userid: %x\n", smb_userid)); + break; + } + } + + endsmbpwent(fp); + return pwd; +} -#ifdef DEBUG_PASSWORD - DEBUG(100, ("add_smbpwd_entry: got line |%s|\n", linebuf)); -#endif +/************************************************************************ + Routine to add an entry to the smbpasswd file. +*************************************************************************/ - if ((linebuf[0] == 0) && feof(fp)) - { - DEBUG(4, ("add_smbpwd_entry: end of file reached\n")); - break; - } - - /* - * The line we have should be of the form :- - * - * username:uid:[32hex bytes]:....other flags presently - * ignored.... - * - * or, - * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... - * - * if Windows NT compatible passwords are also present. - */ - - if (linebuf[0] == '#' || linebuf[0] == '\0') - { - DEBUG(6, ("add_smbpwd_entry: skipping comment or blank line\n")); - continue; - } - - p = (unsigned char *) strchr(linebuf, ':'); - - if (p == NULL) - { - DEBUG(0, ("add_smbpwd_entry: malformed password entry (no :)\n")); - continue; - } - - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); - user_name[PTR_DIFF(p, linebuf)] = '\0'; - if (strequal(user_name, pwd->smb_name)) - { - DEBUG(6, ("add_smbpwd_entry: entry already exists\n")); - return False; - } - } - - /* ok - entry doesn't exist. we can add it */ - - /* Create a new smb passwd entry and set it to the given password. */ - /* The add user write needs to be atomic - so get the fd from - the fp and do a raw write() call. - */ - fd = fileno(fp); - - if((offpos = lseek(fd, 0, SEEK_END)) == -1) - { - DEBUG(0, ("add_smbpwd_entry(lseek): Failed to add entry for user %s to file %s. \ +BOOL add_smbpwd_entry(struct smb_passwd *newpwd) +{ + char *pfile = lp_smb_passwd_file(); + struct smb_passwd *pwd = NULL; + FILE *fp = NULL; + + int i; + int wr_len; + + int fd; + int new_entry_length; + char *new_entry; + long offpos; + unsigned char *p; + + /* Open the smbpassword file - for update. */ + fp = startsmbpwent(True); + + if (fp == NULL) { + DEBUG(0, ("add_smbpwd_entry: unable to open file.\n")); + return False; + } + + /* + * Scan the file, a line at a time and check if the name matches. + */ + + while ((pwd = getsmbpwent(fp)) != NULL) { + if (strequal(newpwd->smb_name, pwd->smb_name)) { + DEBUG(0, ("add_smbpwd_entry: entry with name %s already exists\n", pwd->smb_name)); + endsmbpwent(fp); + return False; + } + } + + /* Ok - entry doesn't exist. We can add it */ + + /* Create a new smb passwd entry and set it to the given password. */ + /* + * The add user write needs to be atomic - so get the fd from + * the fp and do a raw write() call. + */ + fd = fileno(fp); + + if((offpos = lseek(fd, 0, SEEK_END)) == -1) { + DEBUG(0, ("add_smbpwd_entry(lseek): Failed to add entry for user %s to file %s. \ Error was %s\n", pwd->smb_name, pfile, strerror(errno))); + endsmbpwent(fp); + return False; + } - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - new_entry_length = strlen(pwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 2; + new_entry_length = strlen(pwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 2; - if((new_entry = (char *)malloc( new_entry_length )) == 0) - { - DEBUG(0, ("add_smbpwd_entry(malloc): Failed to add entry for user %s to file %s. \ -Error was %s\n", - pwd->smb_name, pfile, strerror(errno))); + if((new_entry = (char *)malloc( new_entry_length )) == NULL) { + DEBUG(0, ("add_smbpwd_entry(malloc): Failed to add entry for user %s to file %s. \ +Error was %s\n", pwd->smb_name, pfile, strerror(errno))); + endsmbpwent(fp); + return False; + } - fclose(fp); - pw_file_unlock(lockfd); - return False; - } + sprintf(new_entry, "%s:%u:", pwd->smb_name, (unsigned)pwd->smb_userid); + p = (unsigned char *)&new_entry[strlen(new_entry)]; - sprintf(new_entry, "%s:%u:", pwd->smb_name, (unsigned)pwd->smb_userid); - p = (unsigned char *)&new_entry[strlen(new_entry)]; + for( i = 0; i < 16; i++) { + sprintf((char *)&p[i*2], "%02X", pwd->smb_passwd[i]); + } - for( i = 0; i < 16; i++) - { - sprintf((char *)&p[i*2], "%02X", pwd->smb_passwd[i]); - } - p += 32; + p += 32; - *p++ = ':'; + *p++ = ':'; - for( i = 0; i < 16; i++) - { - sprintf((char *)&p[i*2], "%02X", pwd->smb_nt_passwd[i]); - } - p += 32; + for( i = 0; i < 16; i++) { + sprintf((char *)&p[i*2], "%02X", pwd->smb_nt_passwd[i]); + } + p += 32; - *p++ = ':'; - sprintf((char *)p,"\n"); + *p++ = ':'; + sprintf((char *)p,"\n"); #ifdef DEBUG_PASSWORD - DEBUG(100, ("add_smbpwd_entry(%d): new_entry_len %d entry_len %d made line |%s|\n", + DEBUG(100, ("add_smbpwd_entry(%d): new_entry_len %d entry_len %d made line |%s|\n", fd, new_entry_length, strlen(new_entry), new_entry)); #endif - if ((wr_len = write(fd, new_entry, strlen(new_entry))) != strlen(new_entry)) - { - DEBUG(0, ("add_smbpwd_entry(write): %d Failed to add entry for user %s to file %s. \ + if ((wr_len = write(fd, new_entry, strlen(new_entry))) != strlen(new_entry)) { + DEBUG(0, ("add_smbpwd_entry(write): %d Failed to add entry for user %s to file %s. \ Error was %s\n", wr_len, pwd->smb_name, pfile, strerror(errno))); - /* Remove the entry we just wrote. */ - if(ftruncate(fd, offpos) == -1) - { - DEBUG(0, ("add_smbpwd_entry: ERROR failed to ftruncate file %s. \ + /* Remove the entry we just wrote. */ + if(ftruncate(fd, offpos) == -1) { + DEBUG(0, ("add_smbpwd_entry: ERROR failed to ftruncate file %s. \ Error was %s. Password file may be corrupt ! Please examine by hand !\n", - pwd->smb_name, strerror(errno))); - } + pwd->smb_name, strerror(errno))); + } - fclose(fp); - pw_file_unlock(lockfd); - return False; - } + endsmbpwent(fp); + return False; + } - fclose(fp); - pw_file_unlock(lockfd); - return True; + endsmbpwent(fp); + return True; } -/* - * Routine to search the smbpasswd file for an entry matching the username. - * and then modify its password entry - */ + +/************************************************************************ + Routine to search the smbpasswd file for an entry matching the username. + and then modify its password entry. We can't use the startsmbpwent()/ + getsmbpwent()/endsmbpwent() interfaces here as we depend on looking + in the actual file to decide how much room we have to write data. +************************************************************************/ + BOOL mod_smbpwd_entry(struct smb_passwd* pwd) { - /* Static buffers we will return. */ - static pstring user_name; - - char linebuf[256]; - char readbuf[16 * 1024]; - unsigned char c; - char ascii_p16[66]; - unsigned char *p = NULL; - long linebuf_len = 0; - FILE *fp; - int lockfd; - char *pfile = lp_smb_passwd_file(); - BOOL found_entry = False; - - long pwd_seekpos = 0; - - int i; - int wr_len; - int fd; - - if (!*pfile) - { - DEBUG(0, ("No SMB password file set\n")); - return False; - } - DEBUG(10, ("mod_smbpwd_entry: opening file %s\n", pfile)); - - fp = fopen(pfile, "r+"); - - if (fp == NULL) - { - DEBUG(0, ("mod_smbpwd_entry: unable to open file %s\n", pfile)); - return False; - } - /* Set a 16k buffer to do more efficient reads */ - setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - - if ((lockfd = pw_file_lock(pfile, F_RDLCK | F_WRLCK, 5)) < 0) - { - DEBUG(0, ("mod_smbpwd_entry: unable to lock file %s\n", pfile)); - fclose(fp); - return False; - } - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* We have a write lock on the file. */ - /* - * Scan the file, a line at a time and check if the name matches. - */ - while (!feof(fp)) - { - pwd_seekpos = ftell(fp); - - linebuf[0] = '\0'; - - fgets(linebuf, 256, fp); - if (ferror(fp)) - { - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - linebuf_len = strlen(linebuf); - if (linebuf[linebuf_len - 1] != '\n') - { - c = '\0'; - while (!ferror(fp) && !feof(fp)) - { - c = fgetc(fp); - if (c == '\n') - { - break; - } - } - } - else - { - linebuf[linebuf_len - 1] = '\0'; - } + /* Static buffers we will return. */ + static pstring user_name; + + char linebuf[256]; + char readbuf[16 * 1024]; + unsigned char c; + char ascii_p16[66]; + unsigned char *p = NULL; + long linebuf_len = 0; + FILE *fp; + int lockfd; + char *pfile = lp_smb_passwd_file(); + BOOL found_entry = False; + + long pwd_seekpos = 0; + + int i; + int wr_len; + int fd; + + if (!*pfile) { + DEBUG(0, ("No SMB password file set\n")); + return False; + } + DEBUG(10, ("mod_smbpwd_entry: opening file %s\n", pfile)); + + fp = fopen(pfile, "r+"); + + if (fp == NULL) { + DEBUG(0, ("mod_smbpwd_entry: unable to open file %s\n", pfile)); + return False; + } + /* Set a 16k buffer to do more efficient reads */ + setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); + + if ((lockfd = pw_file_lock(fileno(fp), F_RDLCK | F_WRLCK, 5)) < 0) { + DEBUG(0, ("mod_smbpwd_entry: unable to lock file %s\n", pfile)); + fclose(fp); + return False; + } + + /* Make sure it is only rw by the owner */ + chmod(pfile, 0600); + + /* We have a write lock on the file. */ + /* + * Scan the file, a line at a time and check if the name matches. + */ + while (!feof(fp)) { + pwd_seekpos = ftell(fp); + + linebuf[0] = '\0'; + + fgets(linebuf, 256, fp); + if (ferror(fp)) { + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + /* + * Check if the string is terminated with a newline - if not + * then we must keep reading and discard until we get one. + */ + linebuf_len = strlen(linebuf); + if (linebuf[linebuf_len - 1] != '\n') { + c = '\0'; + while (!ferror(fp) && !feof(fp)) { + c = fgetc(fp); + if (c == '\n') { + break; + } + } + } else { + linebuf[linebuf_len - 1] = '\0'; + } #ifdef DEBUG_PASSWORD - DEBUG(100, ("mod_smbpwd_entry: got line |%s|\n", linebuf)); + DEBUG(100, ("mod_smbpwd_entry: got line |%s|\n", linebuf)); #endif - if ((linebuf[0] == 0) && feof(fp)) - { - DEBUG(4, ("mod_smbpwd_entry: end of file reached\n")); - break; - } - - /* - * The line we have should be of the form :- - * - * username:uid:[32hex bytes]:....other flags presently - * ignored.... - * - * or, - * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... - * - * if Windows NT compatible passwords are also present. - */ - - if (linebuf[0] == '#' || linebuf[0] == '\0') - { - DEBUG(6, ("mod_smbpwd_entry: skipping comment or blank line\n")); - continue; - } - - p = (unsigned char *) strchr(linebuf, ':'); - - if (p == NULL) - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no :)\n")); - continue; - } - - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); - user_name[PTR_DIFF(p, linebuf)] = '\0'; - if (strequal(user_name, pwd->smb_name)) - { - found_entry = True; - break; - } - } - - if (!found_entry) return False; - - DEBUG(6, ("mod_smbpwd_entry: entry exists\n")); - - /* User name matches - get uid and password */ - p++; /* Go past ':' */ - - if (!isdigit(*p)) - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (uid not number)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - while (*p && isdigit(*p)) - p++; - if (*p != ':') - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no : after uid)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - /* - * Now get the password value - this should be 32 hex digits - * which are the ascii representations of a 16 byte string. - * Get two at a time and put them into the password. - */ - p++; - - /* record exact password position */ - pwd_seekpos += PTR_DIFF(p, linebuf); - - if (*p == '*' || *p == 'X') - { - /* Password deliberately invalid - end here. */ - DEBUG(10, ("get_smbpwd_entry: entry invalidated for user %s\n", user_name)); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (passwd too short)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return (False); - } - - if (p[32] != ':') - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no terminating :)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - if (*p == '*' || *p == 'X') - { - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - if (!strncasecmp((char *) p, "NO PASSWORD", 11)) - { - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (passwd too short)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return (False); - } - - if (p[32] != ':') - { - DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no terminating :)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - /* The following check is wrong - the NT hash is optional. */ -#if 0 - if (*p == '*' || *p == 'X') - { - fclose(fp); - pw_file_unlock(lockfd); - return False; - } -#endif - - /* whew. entry is correctly formed. */ - - /* - * Do an atomic write into the file at the position defined by - * seekpos. - */ - - /* The mod user write needs to be atomic - so get the fd from - the fp and do a raw write() call. - */ - - fd = fileno(fp); - - if (lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) - { - DEBUG(1, ("mod_smbpwd_entry: seek fail on file %s.\n", pfile)); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - /* Sanity check - ensure the character is a ':' */ - if (read(fd, &c, 1) != 1) - { - DEBUG(1, ("mod_smbpwd_entry: read fail on file %s.\n", pfile)); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - if (c != ':') - { - DEBUG(1, ("mod_smbpwd_entry: check on passwd file %s failed.\n", pfile)); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } + if ((linebuf[0] == 0) && feof(fp)) { + DEBUG(4, ("mod_smbpwd_entry: end of file reached\n")); + break; + } + + /* + * The line we have should be of the form :- + * + * username:uid:[32hex bytes]:....other flags presently + * ignored.... + * + * or, + * + * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... + * + * if Windows NT compatible passwords are also present. + */ + + if (linebuf[0] == '#' || linebuf[0] == '\0') { + DEBUG(6, ("mod_smbpwd_entry: skipping comment or blank line\n")); + continue; + } + + p = (unsigned char *) strchr(linebuf, ':'); + + if (p == NULL) { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no :)\n")); + continue; + } + + /* + * As 256 is shorter than a pstring we don't need to check + * length here - if this ever changes.... + */ + strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); + user_name[PTR_DIFF(p, linebuf)] = '\0'; + if (strequal(user_name, pwd->smb_name)) { + found_entry = True; + break; + } + } + + if (!found_entry) return False; + + DEBUG(6, ("mod_smbpwd_entry: entry exists\n")); + + /* User name matches - get uid and password */ + p++; /* Go past ':' */ + + if (!isdigit(*p)) { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (uid not number)\n")); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + while (*p && isdigit(*p)) + p++; + if (*p != ':') { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no : after uid)\n")); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + /* + * Now get the password value - this should be 32 hex digits + * which are the ascii representations of a 16 byte string. + * Get two at a time and put them into the password. + */ + p++; + + /* Record exact password position */ + pwd_seekpos += PTR_DIFF(p, linebuf); + + if (*p == '*' || *p == 'X') { + /* Password deliberately invalid - end here. */ + DEBUG(10, ("get_smbpwd_entry: entry invalidated for user %s\n", user_name)); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (passwd too short)\n")); + fclose(fp); + pw_file_unlock(lockfd); + return (False); + } + + if (p[32] != ':') { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no terminating :)\n")); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + if (*p == '*' || *p == 'X') { + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + /* Now check if the NT compatible password is + available. */ + p += 33; /* Move to the first character of the line after + the lanman password. */ + if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (passwd too short)\n")); + fclose(fp); + pw_file_unlock(lockfd); + return (False); + } + + if (p[32] != ':') { + DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no terminating :)\n")); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + /* Entry is correctly formed. */ + + /* + * Do an atomic write into the file at the position defined by + * seekpos. + */ + + /* The mod user write needs to be atomic - so get the fd from + the fp and do a raw write() call. + */ + + fd = fileno(fp); + + if (lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) { + DEBUG(0, ("mod_smbpwd_entry: seek fail on file %s.\n", pfile)); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + /* Sanity check - ensure the character is a ':' */ + if (read(fd, &c, 1) != 1) { + DEBUG(0, ("mod_smbpwd_entry: read fail on file %s.\n", pfile)); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + if (c != ':') { + DEBUG(0, ("mod_smbpwd_entry: check on passwd file %s failed.\n", pfile)); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } - /* Create the 32 byte representation of the new p16 */ - for (i = 0; i < 16; i++) - { - sprintf(&ascii_p16[i*2], "%02X", (uchar) pwd->smb_passwd[i]); - } - /* Add on the NT md4 hash */ - ascii_p16[32] = ':'; - wr_len = 65; - if (pwd->smb_nt_passwd != NULL) - { - for (i = 0; i < 16; i++) - { - sprintf(&ascii_p16[(i*2)+33], "%02X", (uchar) pwd->smb_nt_passwd[i]); - } - } - else - { - /* No NT hash - write out an 'invalid' string. */ - strcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); - } + /* Create the 32 byte representation of the new p16 */ + for (i = 0; i < 16; i++) { + sprintf(&ascii_p16[i*2], "%02X", (uchar) pwd->smb_passwd[i]); + } + + /* Add on the NT md4 hash */ + ascii_p16[32] = ':'; + wr_len = 65; + if (pwd->smb_nt_passwd != NULL) { + for (i = 0; i < 16; i++) { + sprintf(&ascii_p16[(i*2)+33], "%02X", (uchar) pwd->smb_nt_passwd[i]); + } + } else { + /* No NT hash - write out an 'invalid' string. */ + strcpy(&ascii_p16[33], "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); + } #ifdef DEBUG_PASSWORD - DEBUG(100,("mod_smbpwd_entry: ")); - dump_data(100, ascii_p16, wr_len); + DEBUG(100,("mod_smbpwd_entry: ")); + dump_data(100, ascii_p16, wr_len); #endif - if (write(fd, ascii_p16, wr_len) != wr_len) - { - DEBUG(1, ("mod_smbpwd_entry: write failed in passwd file %s\n", pfile)); - fclose(fp); - pw_file_unlock(lockfd); - return False; - } - - fclose(fp); - pw_file_unlock(lockfd); - return True; + if (write(fd, ascii_p16, wr_len) != wr_len) { + DEBUG(0, ("mod_smbpwd_entry: write failed in passwd file %s\n", pfile)); + fclose(fp); + pw_file_unlock(lockfd); + return False; + } + + fclose(fp); + pw_file_unlock(lockfd); + return True; } diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c new file mode 100644 index 0000000000..2033ea437e --- /dev/null +++ b/source3/rpc_client/cli_login.c @@ -0,0 +1,395 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1994-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + + 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. +*/ + + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + + +#if 0 + if (!cli_initialise(cli, t_idx)) + { + DEBUG(1,("do_nt_session_open: cli_initialise failed\n")); + return False; + } + + DEBUG(1,("do_nt_session_open: server connect initialisation\n")); + + if (!server_connect_init(cli, t_idx, myhostname, dest_ip, dest_host)) + { + uint8 err_cls; + uint32 err_num; + cli_error(cli, t_idx, &err_cls, &err_num); + DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(cli, t_idx))); + + return False; + } + + DEBUG(1,("do_nt_session_open: server connect initialisation succeeded\n")); + + if (!cli_session_setup(cli, t_idx, "", "", 1, NULL, 0, workgroup)) + { + uint8 err_cls; + uint32 err_num; + cli_error(cli, t_idx, &err_cls, &err_num); + DEBUG(1,("session setup failed (%s)\n", cli_errstr(cli, t_idx))); + + return False; + } + + DEBUG(1,("do_nt_session_open: server session setup succeeded\n")); + + if (!cli_send_tconX(cli, t_idx, "IPC$", "IPC", "", 1)) + { + uint8 err_cls; + uint32 err_num; + cli_error(cli, t_idx, &err_cls, &err_num); + DEBUG(1,("cli_send_tconX failed (%s)\n", cli_errstr(cli, t_idx))); + + return False; + } + + DEBUG(1,("do_nt_session_open: server IPC$ connection succeeded\n")); +#endif + + +/**************************************************************************** +experimental nt login. + +****************************************************************************/ +BOOL do_nt_session_open(struct cli_state *cli, int t_idx, uint16 *fnum, + char *dest_host, char *myhostname, + char *mach_acct, + char *username, char *workgroup, + uchar sess_key[16], DOM_CRED *clnt_cred) +{ + DOM_CHAL clnt_chal; + DOM_CHAL srv_chal; + + DOM_CHAL auth2_srv_chal; + + UTIME zerotime; + + char nt_owf_mach_pwd[16]; + char nt_owf_prev_mpd[16]; + + RPC_IFACE abstract; + RPC_IFACE transfer; + + fstring mach_pwd; + fstring prev_mpd; + fstring dest_srv; + + /******************** initialise ********************************/ + + zerotime.time = 0; + + DEBUG(1,("do_nt_session_open: %d\n", __LINE__)); + + /******************* open the \PIPE\NETLOGON file *****************/ + + if (((*fnum) = cli_open(cli, t_idx, PIPE_NETLOGON, O_CREAT, DENY_NONE, + NULL, NULL, NULL)) == 0xffff) + { + DEBUG(1,("do_nt_session_open: cli_open failed\n")); + return False; + } + + /**************** Set Named Pipe State ***************/ + if (!rpc_pipe_set_hnd_state(cli, t_idx, PIPE_NETLOGON, *fnum, 0x4300)) + { + DEBUG(1,("do_nt_session_open: pipe hnd state failed\n")); + return False; + } + + /******************* bind request on \PIPE\NETLOGON *****************/ + + if (!rpc_pipe_bind(cli, t_idx, PIPE_NETLOGON, *fnum, + &abstract, &transfer, + False, NULL, NULL)) + { + DEBUG(1,("do_nt_session_open: rpc bind failed\n")); + return False; + } + + /************ Check workstation trust account *******************/ + + /* default machine password is lower-case machine name (really secure) */ + fstrcpy(mach_pwd, myhostname); + strlower(mach_pwd); + + /* default machine password is lower-case machine name (really secure) */ + fstrcpy(prev_mpd, myhostname); + strlower(prev_mpd); + + /******************* Request Challenge ********************/ + + SIVAL(clnt_chal.data, 0, 0x11111111); + SIVAL(clnt_chal.data, 4, 0x22222222); + + strcpy(dest_srv, "\\\\"); + strcat(dest_srv, dest_host); + strupper(dest_srv); + + /* send a client challenge; receive a server challenge */ + if (!do_net_req_chal(cli, t_idx, *fnum, dest_srv, myhostname, &clnt_chal, &srv_chal)) + { + DEBUG(1,("do_nt_session_open: request challenge failed\n")); + return False; + } + + /**************** Long-term Session key **************/ + +#ifdef DEBUG_PASSWORD + DEBUG(100,("generating nt owf from initial machine pwd: %s\n", mach_pwd)); +#endif + nt_owf_gen( mach_pwd, nt_owf_mach_pwd); + +#ifdef DEBUG_PASSWORD + dump_data(6, nt_owf_mach_pwd, 16); +#endif + +#ifdef DEBUG_PASSWORD + DEBUG(100,("generating nt owf from previous machine pwd: %s\n", prev_mpd)); +#endif + nt_owf_gen( mach_pwd, nt_owf_prev_mpd); + +#ifdef DEBUG_PASSWORD + dump_data(6, nt_owf_prev_mpd, 16); +#endif + + /* calculate the session key */ + cred_session_key(&clnt_chal, &srv_chal, nt_owf_mach_pwd, sess_key); +#if 0 + cred_session_key(&clnt_chal, &srv_chal, nt_owf_prev_mpd, sess_key+8); +#else + bzero(sess_key+8, 8); +#endif + + /******************* Authenticate 2 ********************/ + + /* calculate auth-2 credentials */ + cred_create(sess_key, &clnt_chal, zerotime, &(clnt_cred->challenge)); + + /* send client auth-2 challenge; receive an auth-2 challenge */ + if (!do_net_auth2(cli, t_idx, *fnum, + dest_srv, mach_acct, + SEC_CHAN_WKSTA, myhostname, + &(clnt_cred->challenge), 0x000001ff, &auth2_srv_chal)) + { + DEBUG(1,("do_nt_session_open: request challenge failed\n")); + return False; + } + + return True; +} + +/**************************************************************************** + server password set + ****************************************************************************/ +BOOL do_nt_srv_pwset(struct cli_state *cli, int t_idx, uint16 fnum, + uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, + char *new_mach_pwd, + char *dest_host, char *mach_acct, char *myhostname) +{ + /**************** Net Server Password Set **************/ + + DOM_CRED cred; + char nt_cypher[16]; + uint8 mode = 1; + char nt_owf_new_mach_pwd[16]; + +#ifdef DEBUG_PASSWORD + DEBUG(100,("generating nt owf from new machine pwd: %s\n", new_mach_pwd)); +#endif + nt_owf_gen(new_mach_pwd, nt_owf_new_mach_pwd); + +#ifdef DEBUG_PASSWORD +dump_data(6, nt_owf_new_mach_pwd, 16); +#endif + + if (!obfuscate_pwd(nt_cypher, nt_owf_new_mach_pwd, mode)) + { + DEBUG(5,("do_nt_srv_pwset: encrypt mach pwd failed\n")); + return False; + } + + clnt_cred->timestamp.time = time(NULL); + + memcpy(&cred, clnt_cred, sizeof(cred)); + + /* calculate credentials */ + cred_create(sess_key, &(clnt_cred->challenge), + cred.timestamp, + &(cred.challenge)); + + /* send client srv_pwset challenge */ + return do_net_srv_pwset(cli, t_idx, fnum, sess_key, clnt_cred, + dest_host, mach_acct, 2, myhostname, + &cred, rtn_cred, + nt_cypher); +} + +/**************************************************************************** + make interactive sam login info + ****************************************************************************/ +void make_nt_login_interactive(NET_ID_INFO_CTR *ctr, + uchar sess_key[16], + char *workgroup, char *myhostname, + uint32 smb_userid, char *username) +{ + /****************** SAM Info Preparation *******************/ + + char *smb_user_passwd = getpass("Enter NT Login Password:"); + + char lm_owf_user_pwd[16]; + char nt_owf_user_pwd[16]; + + nt_lm_owf_gen(smb_user_passwd, nt_owf_user_pwd, lm_owf_user_pwd); + +#ifdef DEBUG_PASSWORD + + DEBUG(100,("nt owf of user password: ")); + dump_data(100, lm_owf_user_pwd, 16); + + DEBUG(100,("nt owf of user password: ")); + dump_data(100, nt_owf_user_pwd, 16); + +#endif + + /* indicate an "interactive" login */ + ctr->switch_value = 1; + + /* this is used in both the SAM Logon and the SAM Logoff */ + make_id_info1(&ctr->auth.id1, workgroup, 0, + smb_userid, 0, + username, myhostname, + sess_key, lm_owf_user_pwd, nt_owf_user_pwd); +} + +/**************************************************************************** +experimental nt login. +****************************************************************************/ +BOOL do_nt_login(struct cli_state *cli, int t_idx, uint16 fnum, + uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, + NET_ID_INFO_CTR *ctr, char *dest_host, char *myhostname, + NET_USER_INFO_3 *user_info3) +{ + DOM_CRED sam_logon_rtn_cred; + DOM_CRED cred; + fstring dest_srv; + fstring my_host_name; + + DEBUG(5,("do_nt_login: %d\n", __LINE__)); + + /*********************** SAM Logon **********************/ + + clnt_cred->timestamp.time = time(NULL); + + memcpy(&cred, clnt_cred, sizeof(cred)); + + /* calculate sam logon credentials */ + cred_create(sess_key, &(clnt_cred->challenge), + cred.timestamp, + &(cred.challenge)); + + strcpy(dest_srv, "\\\\"); + strcat(dest_srv, dest_host); + strupper(dest_srv); + + fstrcpy(my_host_name, myhostname); + strupper(my_host_name); + + /* send client sam-logon challenge */ + return do_net_sam_logon(cli, t_idx, fnum, sess_key, clnt_cred, + dest_srv, my_host_name, + &cred, &sam_logon_rtn_cred, + ctr->switch_value, ctr, 3, user_info3, + rtn_cred); +} + +/**************************************************************************** +nt sam logoff +****************************************************************************/ +BOOL do_nt_logoff(struct cli_state *cli, int t_idx, uint16 fnum, + uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, + NET_ID_INFO_CTR *ctr, char *dest_host, char *myhostname) +{ + DOM_CRED sam_logoff_rtn_cred; + DOM_CRED cred; + fstring dest_srv; + fstring my_host_name; + + DEBUG(5,("do_nt_logoff: %d\n", __LINE__)); + + /*********************** SAM Logoff *********************/ + + clnt_cred->timestamp.time = time(NULL); + + memcpy(&cred, clnt_cred, sizeof(cred)); + + /* calculate sam logoff credentials */ + cred_create(sess_key, &(clnt_cred->challenge), + cred.timestamp, + &(cred.challenge)); + + strcpy(dest_srv, "\\\\"); + strcat(dest_srv, dest_host); + strupper(dest_srv); + + fstrcpy(my_host_name, myhostname); + strupper(my_host_name); + + /* send client sam-logoff challenge; receive a sam-logoff challenge */ + return do_net_sam_logoff(cli, t_idx, fnum, sess_key, clnt_cred, + dest_srv, my_host_name, + &cred, &sam_logoff_rtn_cred, + ctr->switch_value, ctr, 3, + rtn_cred); +} + +#if 0 + /* free memory used in all rpc transactions, above */ + cli_shutdown(cli, t_idx); +#endif + +/**************************************************************************** +experimental nt login. +****************************************************************************/ +void do_nt_session_close(struct cli_state *cli, int t_idx, uint16 fnum) +{ + /******************** close the \PIPE\NETLOGON file **************/ + if (fnum != 0xffff) + { + cli_close(cli, t_idx, fnum, 0); + } + +} + + diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c new file mode 100644 index 0000000000..6570903e79 --- /dev/null +++ b/source3/rpc_client/cli_lsarpc.c @@ -0,0 +1,255 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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. + */ + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +extern int DEBUGLEVEL; + + +/**************************************************************************** +do a LSA Open Policy +****************************************************************************/ +BOOL do_lsa_open_policy(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, POLICY_HND *hnd) +{ + prs_struct rbuf; + prs_struct buf; + LSA_Q_OPEN_POL q_o; + BOOL valid_pol = False; + + if (hnd == NULL) return False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api LSA_OPENPOLICY */ + + DEBUG(4,("LSA Open Policy\n")); + + /* store the parameters */ + make_q_open_pol(&q_o, server_name, 0, 0, 0x1); + + /* turn parameters into data stream */ + lsa_io_q_open_pol("", &q_o, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_OPENPOLICY, &buf, &rbuf)) + { + LSA_R_OPEN_POL r_o; + BOOL p; + + lsa_io_r_open_pol("", &r_o, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("LSA_OPENPOLICY: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p) + { + /* ok, at last: we're happy. return the policy handle */ + memcpy(hnd, r_o.pol.data, sizeof(hnd->data)); + valid_pol = True; + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + return valid_pol; +} + +/**************************************************************************** +do a LSA Query Info Policy +****************************************************************************/ +BOOL do_lsa_query_info_pol(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *hnd, uint16 info_class, + fstring domain_name, fstring domain_sid) +{ + prs_struct rbuf; + prs_struct buf; + LSA_Q_QUERY_INFO q_q; + BOOL valid_response = False; + + if (hnd == NULL || domain_name == NULL || domain_sid == NULL) return False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api LSA_QUERYINFOPOLICY */ + + DEBUG(4,("LSA Query Info Policy\n")); + + /* store the parameters */ + make_q_query(&q_q, hnd, info_class); + + /* turn parameters into data stream */ + lsa_io_q_query("", &q_q, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_QUERYINFOPOLICY, &buf, &rbuf)) + { + LSA_R_QUERY_INFO r_q; + BOOL p; + + lsa_io_r_query("", &r_q, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_q.status != 0) + { + /* report error code */ + DEBUG(0,("LSA_QUERYINFOPOLICY: %s\n", get_nt_error_msg(r_q.status))); + p = False; + } + + if (p && r_q.info_class != q_q.info_class) + { + /* report different info classes */ + DEBUG(0,("LSA_QUERYINFOPOLICY: error info_class (q,r) differ - (%x,%x)\n", + q_q.info_class, r_q.info_class)); + p = False; + } + + if (p) + { + /* ok, at last: we're happy. */ + switch (r_q.info_class) + { + case 3: + { + char *dom_name = unistrn2(r_q.dom.id3.uni_domain_name.buffer, + r_q.dom.id3.uni_domain_name.uni_str_len); + char *dom_sid = dom_sid_to_string(&(r_q.dom.id3.dom_sid.sid)); + fstrcpy(domain_name, dom_name); + pstrcpy(domain_sid , dom_sid); + + valid_response = True; + break; + } + case 5: + { + char *dom_name = unistrn2(r_q.dom.id5.uni_domain_name.buffer, + r_q.dom.id5.uni_domain_name.uni_str_len); + char *dom_sid = dom_sid_to_string(&(r_q.dom.id5.dom_sid.sid)); + fstrcpy(domain_name, dom_name); + pstrcpy(domain_sid , dom_sid); + + valid_response = True; + break; + } + default: + { + DEBUG(3,("LSA_QUERYINFOPOLICY: unknown info class\n")); + domain_name[0] = 0; + domain_sid [0] = 0; + + break; + } + } + DEBUG(3,("LSA_QUERYINFOPOLICY (level %x): domain:%s domain sid:%s\n", + r_q.info_class, domain_name, domain_sid)); + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + return valid_response; +} + +/**************************************************************************** +do a LSA Close +****************************************************************************/ +BOOL do_lsa_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd) +{ + prs_struct rbuf; + prs_struct buf; + LSA_Q_CLOSE q_c; + BOOL valid_close = False; + + if (hnd == NULL) return False; + + /* create and send a MSRPC command with api LSA_OPENPOLICY */ + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("LSA Close\n")); + + /* store the parameters */ + make_lsa_q_close(&q_c, hnd); + + /* turn parameters into data stream */ + lsa_io_q_close("", &q_c, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_CLOSE, &buf, &rbuf)) + { + LSA_R_CLOSE r_c; + BOOL p; + + lsa_io_r_close("", &r_c, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_c.status != 0) + { + /* report error code */ + DEBUG(0,("LSA_CLOSE: %s\n", get_nt_error_msg(r_c.status))); + p = False; + } + + if (p) + { + /* check that the returned policy handle is all zeros */ + int i; + valid_close = True; + + for (i = 0; i < sizeof(r_c.pol.data); i++) + { + if (r_c.pol.data[i] != 0) + { + valid_close = False; + break; + } + } + if (!valid_close) + { + DEBUG(0,("LSA_CLOSE: non-zero handle returned\n")); + } + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + return valid_close; +} diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c new file mode 100644 index 0000000000..aafde8d775 --- /dev/null +++ b/source3/rpc_client/cli_netlogon.c @@ -0,0 +1,461 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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. + */ + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +extern int DEBUGLEVEL; +extern pstring username; +extern pstring workgroup; + +#define CLIENT_TIMEOUT (30*1000) + + +/**************************************************************************** +do a LSA Logon Control2 +****************************************************************************/ +BOOL do_net_logon_ctrl2(struct cli_state *cli, int t_idx, uint16 fnum, + char *host_name, uint32 status_level) +{ + prs_struct rbuf; + prs_struct buf; + NET_Q_LOGON_CTRL2 q_l; + BOOL valid_ctrl2 = False; + fstring acct_name; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True ); + + if (host_name == NULL) return False; + + strcpy(acct_name, "\\\\"); + strcat(acct_name, host_name); + + /* create and send a MSRPC command with api NET_LOGON_CTRL2 */ + + DEBUG(4,("LSA Logon Control2 from %s status level:%x\n", + host_name, status_level)); + + /* store the parameters */ + make_q_logon_ctrl2(&q_l, acct_name, status_level); + + /* turn parameters into data stream */ + net_io_q_logon_ctrl2("", &q_l, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, NET_LOGON_CTRL2, &buf, &rbuf)) + { + NET_R_LOGON_CTRL2 r_l; + BOOL p; + + net_io_r_logon_ctrl2("", &r_l, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_l.status != 0) + { + /* report error code */ + DEBUG(0,("NET_R_LOGON_CTRL: %s\n", get_nt_error_msg(r_l.status))); + p = False; + } + + if (p) + { + valid_ctrl2 = True; + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + + return valid_ctrl2; +} + +/**************************************************************************** +do a LSA Authenticate 2 +****************************************************************************/ +BOOL do_net_auth2(struct cli_state *cli, int t_idx, uint16 fnum, + char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, + DOM_CHAL *clnt_chal, uint32 neg_flags, DOM_CHAL *srv_chal) +{ + prs_struct rbuf; + prs_struct buf; + NET_Q_AUTH_2 q_a; + BOOL valid_chal = False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True ); + + if (srv_chal == NULL || clnt_chal == NULL) return False; + + /* create and send a MSRPC command with api NET_AUTH2 */ + + DEBUG(4,("LSA Authenticate 2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %lx\n", + logon_srv, acct_name, sec_chan, comp_name, + credstr(clnt_chal->data), neg_flags)); + + /* store the parameters */ + make_q_auth_2(&q_a, logon_srv, acct_name, sec_chan, comp_name, + clnt_chal, neg_flags); + + /* turn parameters into data stream */ + net_io_q_auth_2("", &q_a, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, NET_AUTH2, &buf, &rbuf)) + { + NET_R_AUTH_2 r_a; + BOOL p; + + net_io_r_auth_2("", &r_a, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_a.status != 0) + { + /* report error code */ + DEBUG(0,("NET_AUTH2: %s\n", get_nt_error_msg(r_a.status))); + p = False; + } + + if (p && r_a.srv_flgs.neg_flags != q_a.clnt_flgs.neg_flags) + { + /* report different neg_flags */ + DEBUG(0,("NET_AUTH2: error neg_flags (q,r) differ - (%lx,%lx)\n", + q_a.clnt_flgs.neg_flags, r_a.srv_flgs.neg_flags)); + p = False; + } + + if (p) + { + /* ok, at last: we're happy. return the challenge */ + memcpy(srv_chal, r_a.srv_chal.data, sizeof(srv_chal->data)); + valid_chal = True; + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + + return valid_chal; +} + +/**************************************************************************** +do a LSA Request Challenge +****************************************************************************/ +BOOL do_net_req_chal(struct cli_state *cli, int t_idx, uint16 fnum, + char *desthost, char *myhostname, + DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal) +{ + prs_struct rbuf; + prs_struct buf; + NET_Q_REQ_CHAL q_c; + BOOL valid_chal = False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True ); + + if (srv_chal == NULL || clnt_chal == NULL) return False; + + /* create and send a MSRPC command with api NET_REQCHAL */ + + DEBUG(4,("LSA Request Challenge from %s to %s: %s\n", + desthost, myhostname, credstr(clnt_chal->data))); + + /* store the parameters */ + make_q_req_chal(&q_c, desthost, myhostname, clnt_chal); + + /* turn parameters into data stream */ + net_io_q_req_chal("", &q_c, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, NET_REQCHAL, &buf, &rbuf)) + { + NET_R_REQ_CHAL r_c; + BOOL p; + + net_io_r_req_chal("", &r_c, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_c.status != 0) + { + /* report error code */ + DEBUG(0,("NET_REQ_CHAL: %s\n", get_nt_error_msg(r_c.status))); + p = False; + } + + if (p) + { + /* ok, at last: we're happy. return the challenge */ + memcpy(srv_chal, r_c.srv_chal.data, sizeof(srv_chal->data)); + valid_chal = True; + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + + return valid_chal; +} + +/*************************************************************************** +do a LSA Server Password Set +****************************************************************************/ +BOOL do_net_srv_pwset(struct cli_state *cli, int t_idx, uint16 fnum, + uchar sess_key[16], DOM_CRED *sto_clnt_cred, + char *logon_srv, char *mach_acct, uint16 sec_chan_type, char *comp_name, + DOM_CRED *clnt_cred, DOM_CRED *srv_cred, + uint8 nt_owf_new_mach_pwd[16]) +{ + prs_struct rbuf; + prs_struct buf; + NET_Q_SRV_PWSET q_s; + BOOL valid_cred = False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True ); + + if (srv_cred == NULL || clnt_cred == NULL) return False; + + /* create and send a MSRPC command with api NET_SRV_PWSET */ + + DEBUG(4,("LSA Server Password Set: srv:%s acct:%s sc: %d mc: %s clnt %s %lx\n", + logon_srv, mach_acct, sec_chan_type, comp_name, + credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time)); + + /* store the parameters */ + make_q_srv_pwset(&q_s, + sess_key, + logon_srv, mach_acct, sec_chan_type, comp_name, + clnt_cred, + nt_owf_new_mach_pwd); + + /* turn parameters into data stream */ + net_io_q_srv_pwset("", &q_s, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SRVPWSET, &buf, &rbuf)) + { + NET_R_SRV_PWSET r_s; + BOOL p; + + net_io_r_srv_pwset("", &r_s, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_s.status != 0) + { + /* report error code */ + DEBUG(0,("NET_R_SRV_PWSET: %s\n", get_nt_error_msg(r_s.status))); + p = False; + } + + if (p) + { + if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_cred))) + { + DEBUG(5, ("do_net_srv_pwset: server credential check OK\n")); + /* ok, at last: we're happy. return the challenge */ + memcpy(srv_cred, &(r_s.srv_cred), sizeof(r_s.srv_cred)); + valid_cred = True; + } + else + { + DEBUG(5, ("do_net_srv_pwset: server credential check failed\n")); + } + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + + return valid_cred; +} + +/*************************************************************************** +do a LSA SAM Logon +****************************************************************************/ +BOOL do_net_sam_logon(struct cli_state *cli, int t_idx, uint16 fnum, + uchar sess_key[8], DOM_CRED *sto_clnt_cred, + char *logon_srv, char *comp_name, + DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, + uint16 logon_level, NET_ID_INFO_CTR *ctr, uint16 validation_level, + NET_USER_INFO_3 *user_info3, + DOM_CRED *srv_cred) +{ + prs_struct rbuf; + prs_struct buf; + NET_Q_SAM_LOGON q_s; + BOOL valid_cred = False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True ); + + if (srv_cred == NULL || clnt_cred == NULL || rtn_cred == NULL || user_info3 == NULL) return False; + + /* create and send a MSRPC command with api NET_SAMLOGON */ + + DEBUG(4,("LSA SAM Logon: srv:%s mc:%s clnt %s %lx rtn: %s %lx ll: %d\n", + logon_srv, comp_name, + credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time, + credstr(rtn_cred->challenge.data), rtn_cred ->timestamp.time, + logon_level)); + + /* store the parameters */ + make_sam_info(&(q_s.sam_id), logon_srv, comp_name, + clnt_cred, rtn_cred, + logon_level, ctr, validation_level); + + /* turn parameters into data stream */ + net_io_q_sam_logon("", &q_s, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SAMLOGON, &buf, &rbuf)) + { + NET_R_SAM_LOGON r_s; + BOOL p; + + r_s.user = user_info3; + + net_io_r_sam_logon("", &r_s, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_s.status != 0) + { + /* report error code */ + DEBUG(0,("NET_SAMLOGON: %s\n", get_nt_error_msg(r_s.status))); + p = False; + } + + if (p && r_s.switch_value != 3) + { + /* report different switch_value */ + DEBUG(0,("NET_SAMLOGON: switch_value of 3 expected %x\n", + r_s.switch_value)); + p = False; + } + + if (p) + { + if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_creds))) + { + DEBUG(5, ("do_net_sam_logon: server credential check OK\n")); + /* ok, at last: we're happy. return the challenge */ + memcpy(srv_cred, &(r_s.srv_creds), sizeof(r_s.srv_creds)); + valid_cred = True; + } + else + { + DEBUG(5, ("do_net_sam_logon: server credential check failed\n")); + } + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + return valid_cred; +} + +/*************************************************************************** +do a LSA SAM Logoff +****************************************************************************/ +BOOL do_net_sam_logoff(struct cli_state *cli, int t_idx, uint16 fnum, + uchar sess_key[8], DOM_CRED *sto_clnt_cred, + char *logon_srv, char *comp_name, + DOM_CRED *clnt_cred, DOM_CRED *rtn_cred, + uint16 logon_level, NET_ID_INFO_CTR *ctr, uint16 validation_level, + DOM_CRED *srv_cred) +{ + prs_struct rbuf; + prs_struct buf; + NET_Q_SAM_LOGOFF q_s; + BOOL valid_cred = False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True ); + + if (srv_cred == NULL || clnt_cred == NULL || rtn_cred == NULL) return False; + + /* create and send a MSRPC command with api NET_SAMLOGON */ + + DEBUG(4,("LSA SAM Logoff: srv:%s mc:%s clnt %s %lx rtn: %s %lx ll: %d\n", + logon_srv, comp_name, + credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time, + credstr(rtn_cred->challenge.data), rtn_cred ->timestamp.time, + logon_level)); + + /* store the parameters */ + make_sam_info(&(q_s.sam_id), logon_srv, comp_name, + clnt_cred, rtn_cred, + logon_level, ctr, validation_level); + + /* turn parameters into data stream */ + net_io_q_sam_logoff("", &q_s, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SAMLOGOFF, &buf, &rbuf)) + { + NET_R_SAM_LOGOFF r_s; + BOOL p; + + net_io_r_sam_logoff("", &r_s, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_s.status != 0) + { + /* report error code */ + DEBUG(0,("NET_SAMLOGOFF: %s\n", get_nt_error_msg(r_s.status))); + p = False; + } + + if (p) + { + if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_creds))) + { + DEBUG(5, ("do_net_sam_logoff: server credential check OK\n")); + /* ok, at last: we're happy. return the challenge */ + memcpy(srv_cred, &(r_s.srv_creds), sizeof(r_s.srv_creds)); + valid_cred = True; + } + else + { + DEBUG(5, ("do_net_sam_logoff: server credential check failed\n")); + } + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + + return valid_cred; +} + + diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c new file mode 100644 index 0000000000..625b774167 --- /dev/null +++ b/source3/rpc_client/cli_pipe.c @@ -0,0 +1,683 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1998. + * + * 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. + */ + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +extern int DEBUGLEVEL; + + +extern struct pipe_id_info pipe_names[]; + +/******************************************************************** + rpc pipe call id + ********************************************************************/ +uint32 get_rpc_call_id(void) +{ + static uint32 call_id = 1; + return ++call_id; +} + +/******************************************************************* + uses SMBreadX to get rest of rpc data + ********************************************************************/ +static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum, + prs_struct *rdata, uint32 data_to_read) +{ + uint32 data_offset = rdata->data->data_used; + int size = 512; + int num_read; + char *data = rdata->data->data; + uint32 err; + data += rdata->data->data_used; + + if (data_offset + data_to_read > rdata->data->data_size) + { + mem_grow_data(&rdata->data, True, rdata->data->data_used + data_to_read); + DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used)); + } + + do /* read data using SMBreadX */ + { + if (size > data_to_read) size = data_to_read; + + if (data_offset + size > rdata->data->data_size) + { + mem_grow_data(&rdata->data, True, rdata->data->data_used + size); + DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used)); + } + + num_read = cli_readx(cli, t_idx, fnum, data, data_offset, size); + + DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n", + data_offset, num_read, data_to_read)); + + data_to_read -= num_read; + data_offset += num_read; + data += num_read; + + if (cli_error(cli, NULL, &err)) return False; + + } while (num_read > 0 && data_to_read > 0); /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */ + + mem_realloc_data(rdata->data, rdata->data->data_used); + rdata->data->offset.end = rdata->data->data_used; + + DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read)); + + return data_to_read == 0; +} + +/**************************************************************************** + checks the header + ****************************************************************************/ +static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type, + BOOL *first, BOOL *last, uint32 *len) +{ + RPC_HDR rhdr; + + smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0); + + if (!rdata->offset || rdata->offset != 0x10) + { + DEBUG(5,("cli_pipe: error in rpc header\n")); + return False; + } + + (*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST); + (*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST ); + (*len ) = rhdr.frag_len - rdata->data->data_used; + (*pkt_type) = rhdr.pkt_type; + + return True; +} + +/**************************************************************************** + send data on an rpc pipe, which *must* be in one fragment. + receive response data from an rpc pipe, which may be large... + + read the first fragment: unfortunately have to use SMBtrans for the first + bit, then SMBreadX for subsequent bits. + + if first fragment received also wasn't the last fragment, continue + getting fragments until we _do_ receive the last fragment. + + [note: from a data abstraction viewpoint, this function is marginally + complicated by the return side of cli_api_pipe getting in the way + (i.e, the SMB header stuff). the proper way to do this is to split + cli_api_pipe down into receive / transmit. oh, and split cli_readx + down. in other words, state-based (kernel) techniques...] + + ****************************************************************************/ +BOOL rpc_api_pipe(struct cli_state *cli, int t_idx, + uint16 cmd, uint16 fnum, + prs_struct *param , prs_struct *data, + prs_struct *rparam, prs_struct *rdata) +{ + uint32 len; + + uint16 setup[2]; /* only need 2 uint16 setup parameters */ + uint32 err; + uint8 pkt_type = 0xff; + BOOL first = True; + BOOL last = True; + + /* prepare return data and params */ + + /* create setup parameters. */ + setup[0] = cmd; + setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */ + + /* send the data: receive a response. */ + if (!cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8, + + param != NULL ? param->data->data_used : 0, + data != NULL ? data ->data->data_used : 0, + 2, + + 0, + data != NULL ? 1024 : 0 , + + param != NULL ? param->data->data : NULL, + data != NULL ? data ->data->data : NULL, + setup, + + rparam != NULL ? rparam->data : NULL, + rdata != NULL ? rdata ->data : NULL)) + { + DEBUG(5, ("cli_pipe: return critical error\n")); + return False; + } + + if (cli_error(cli, NULL, &err)) return False; + + if (rdata->data->data == NULL) return False; + + /**** parse the header: check it's a response record */ + + rdata->data->offset.start = 0; + rdata->data->offset.end = rdata->data->data_used; + rdata->offset = 0; + + if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len)) return False; + + if (pkt_type == RPC_RESPONSE) + { + RPC_HDR_RR rhdr_rr; + smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, rdata, 0); + } + + if (first && last) + { + DEBUG(6,("rpc_api_pipe: fragment first and last both set\n")); + return True; + } + + /* check if data to be sent back was too large for one SMB. */ + /* err status is only informational: the _real_ check is on the length */ + if (len < rdata->data->data_used) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */ + { + if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False; + } + + /* only one rpc fragment, and it has been read */ + if (first && last) return True; + + while (!last) /* read more fragments until we get the last one */ + { + RPC_HDR rhdr; + RPC_HDR_RR rhdr_rr; + int num_read; + prs_struct hps; + + prs_init(&hps, 0x18, 4, 0, True); + + num_read = cli_readx(cli, t_idx, fnum, hps.data->data, 0, 0x18); + DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read)); + + if (num_read != 0x18) return False; + + smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0); + smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, &hps, 0); + + prs_mem_free(&hps); + + if (cli_error(cli, NULL, &err)) return False; + + first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST); + last = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST ); + + if (first) + { + DEBUG(4,("rpc_api_pipe: wierd rpc header received\n")); + return False; + } + + len = rhdr.frag_len - hps.offset; + if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False; + } + + return True; +} + +/******************************************************************* + creates a DCE/RPC bind request + + - initialises the parse structure. + - dynamically allocates the header data structure + - caller is expected to free the header data structure once used. + + ********************************************************************/ +static BOOL create_rpc_bind_req(prs_struct *rhdr, + prs_struct *rhdr_rb, + prs_struct *auth_req, + RPC_IFACE *abstract, RPC_IFACE *transfer, + char *my_name, char *domain) +{ + RPC_HDR_RB hdr_rb; + RPC_HDR hdr; + RPC_AUTH_NTLMSSP_REQ ntlmssp_req; + + /* create the bind request RPC_HDR_RB */ + make_rpc_hdr_rb(&hdr_rb, + 0x1630, 0x1630, 0x0, + 0x1, 0x0, 0x1, + abstract, transfer); + + /* stream the bind request data */ + smb_io_rpc_hdr_rb("", &hdr_rb, rhdr_rb, 0); + mem_realloc_data(rhdr_rb->data, rhdr_rb->offset); + + if (auth_req != NULL) + { + make_rpc_auth_ntlmssp_req(&ntlmssp_req, + "NTLMSSP", 0x1, + 0x0000b2b3, + my_name, domain); + smb_io_rpc_auth_ntlmssp_req("", &ntlmssp_req, auth_req, 0); + mem_realloc_data(auth_req->data, auth_req->offset); + } + + /* create the request RPC_HDR */ + make_rpc_hdr(&hdr, RPC_BIND, 0x0, get_rpc_call_id(), + rhdr_rb->offset, + auth_req != NULL ? auth_req->offset : 0); + + smb_io_rpc_hdr("hdr" , &hdr , rhdr, 0); + mem_realloc_data(rhdr->data, rhdr->offset); + + if (rhdr->data == NULL || rhdr_rb->data == NULL) return False; + + /***/ + /*** link rpc header, bind acknowledgment and authentication responses ***/ + /***/ + + rhdr->data->offset.start = 0; + rhdr->data->offset.end = rhdr->offset; + rhdr->data->next = rhdr_rb->data; + + if (auth_req != NULL) + { + rhdr_rb->data->offset.start = rhdr->offset; + rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset; + rhdr_rb->data->next = auth_req->data; + + auth_req->data->offset.start = rhdr->offset + rhdr_rb->offset; + auth_req->data->offset.end = rhdr->offset + auth_req->offset + rhdr_rb->offset; + auth_req->data->next = NULL; + } + else + { + rhdr_rb->data->offset.start = rhdr->offset; + rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset; + rhdr_rb->data->next = NULL; + } + + return True; +} + + +/******************************************************************* + creates a DCE/RPC bind request + + - initialises the parse structure. + - dynamically allocates the header data structure + - caller is expected to free the header data structure once used. + + ********************************************************************/ +static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len) +{ + RPC_HDR_RR hdr_rr; + RPC_HDR hdr; + + DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n", + op_num, data_len)); + + /* create the rpc header RPC_HDR */ + make_rpc_hdr (&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST, + get_rpc_call_id(), data_len + 0x18, 0); + + /* create the rpc request RPC_HDR_RR */ + make_rpc_hdr_rr(&hdr_rr, data_len, op_num); + + /* stream-time... */ + smb_io_rpc_hdr ("hdr" , &hdr , rhdr, 0); + smb_io_rpc_hdr_rr("hdr_rr", &hdr_rr, rhdr, 0); + + if (rhdr->data == NULL || rhdr->offset != 0x18) return False; + + rhdr->data->offset.start = 0; + rhdr->data->offset.end = rhdr->offset; + + return True; +} + + +/**************************************************************************** + send a request on an rpc pipe. + ****************************************************************************/ +BOOL rpc_api_pipe_req(struct cli_state *cli, int t_idx, uint16 fnum, + uint8 op_num, + prs_struct *data, prs_struct *rdata) +{ + /* fudge this, at the moment: create the header; memcpy the data. oops. */ + prs_struct rparam; + prs_struct hdr; + int data_len; + BOOL ret; + + data_len = data->offset + 0x18; + data->data->offset.end = data->offset; + + prs_init(&hdr , data_len, 4, SAFETY_MARGIN, False); + prs_init(&rparam, 0 , 4, 0 , True ); + + create_rpc_request(&hdr, op_num, data_len); + + mem_realloc_data(hdr.data, data_len); + hdr.data->offset.end = data_len; + mem_buf_copy(mem_data(&(hdr.data), 0x18), data->data, 0, data->offset); + + ret = rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &hdr, &rparam, rdata); + + prs_mem_free(&rparam); + prs_mem_free(&hdr); + + return ret; +} + + +/**************************************************************************** +do an rpc bind +****************************************************************************/ +BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, int t_idx, + char *pipe_name, uint16 fnum, uint16 device_state) +{ + prs_struct param; + prs_struct rdata; + prs_struct rparam; + BOOL state_set = False; + uint16 setup[2]; /* only need 2 uint16 setup parameters */ + + if (pipe_name == NULL) return False; + + prs_init(¶m , 2, 4, 0 , False); + prs_init(&rdata , 0, 4, SAFETY_MARGIN, True ); + prs_init(&rparam, 0, 4, SAFETY_MARGIN, True ); + + param.data->offset.start = 0; + param.data->offset.end = 2; + + DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n", + fnum, pipe_name, device_state)); + + /* create data parameters: device state */ + SSVAL(param.data->data, 0, device_state); + + /* create setup parameters. */ + setup[0] = 0x0001; + setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */ + + /* send the data on \PIPE\ */ + if (cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8, + + 2, 0, 2, + + 0, 1024, + + param.data->data, NULL, setup, + + rparam.data, rdata.data)) + { + DEBUG(5, ("Set Handle state: return OK\n")); + state_set = True; + } + + prs_mem_free(¶m ); + prs_mem_free(&rparam); + prs_mem_free(&rdata ); + + return state_set; +} + +/**************************************************************************** + check the rpc bind acknowledge response +****************************************************************************/ +static BOOL valid_pipe_name(char *pipe_name, + RPC_IFACE *abstract, RPC_IFACE *transfer) +{ + int pipe_idx = 0; + + while (pipe_names[pipe_idx].client_pipe != NULL) + { + if (strcmp(pipe_name, pipe_names[pipe_idx].client_pipe ) == 0) + { + DEBUG(5,("Bind Abstract Syntax: ")); + dump_data(5, (uchar*)&(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax)); + DEBUG(5,("Bind Transfer Syntax: ")); + dump_data(5, (uchar*)&(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax)); + + /* copy the required syntaxes out so we can do the right bind */ + memcpy(transfer, &(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax)); + memcpy(abstract, &(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax)); + + return True; + } + pipe_idx++; + }; + + DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name)); + return False; +} + +/**************************************************************************** + check the rpc bind acknowledge response +****************************************************************************/ +static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer) +{ + int i = 0; + + while ((pipe_names[i].client_pipe != NULL)) + { + DEBUG(6,("bind_rpc_pipe: searching pipe name: client:%s server:%s\n", + pipe_names[i].client_pipe , pipe_names[i].server_pipe )); + + if ((strcmp(pipe_name, pipe_names[i].client_pipe ) == 0)) + { + if (strcmp(hdr_ba->addr.str, pipe_names[i].server_pipe ) == 0) + { + DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n", + pipe_names[i].server_pipe )); + break; + } + else + { + DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n", + pipe_names[i].server_pipe , hdr_ba->addr.str)); + return False; + } + } + else + { + i++; + } + } + + if (pipe_names[i].server_pipe == NULL) + { + DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str)); + return False; + } + + /* check the transfer syntax */ + if (!((hdr_ba->transfer.version == transfer->version) && + (memcmp(hdr_ba->transfer.data, transfer->data, + sizeof(transfer->version)) ==0))) + { + DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n")); + return False; + } + + /* lkclXXXX only accept one result: check the result(s) */ + if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) + { + DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n", + hdr_ba->res.num_results, + hdr_ba->res.reason)); + } + + DEBUG(5,("bind_rpc_pipe: accepted!\n")); + return True; +} + +/**************************************************************************** +do an rpc bind +****************************************************************************/ +BOOL rpc_pipe_bind(struct cli_state *cli, int t_idx, char *pipe_name, uint16 fnum, + RPC_IFACE *abstract, RPC_IFACE *transfer, BOOL ntlmssp_auth, + char *my_name, char *domain) +{ + prs_struct hdr; + prs_struct hdr_rb; + prs_struct auth_req; + prs_struct data; + prs_struct rdata; + prs_struct rparam; + + BOOL valid_ack = False; + + if (pipe_name == NULL || abstract == NULL || transfer == NULL) return False; + + DEBUG(5,("Bind RPC Pipe[%x]: %s\n", fnum, pipe_name)); + + if (!valid_pipe_name(pipe_name, abstract, transfer)) return False; + + prs_init(&hdr , 0x10 , 4, 0x0 , False); + prs_init(&hdr_rb , 1024 , 4, SAFETY_MARGIN, False); + prs_init(&auth_req, ntlmssp_auth ? 1024 : 0, 4, SAFETY_MARGIN, False); + + prs_init(&rdata , 0 , 4, SAFETY_MARGIN, True ); + prs_init(&rparam, 0 , 4, SAFETY_MARGIN, True ); + + create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL, + abstract, transfer, + my_name, domain); + + /* this is a hack due to limitations in rpc_api_pipe */ + prs_init(&data, mem_buf_len(hdr.data), 4, 0x0, False); + mem_buf_copy(data.data->data, hdr.data, 0, mem_buf_len(hdr.data)); + + /* send data on \PIPE\. receive a response */ + if (rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &data, &rparam, &rdata)) + { + RPC_HDR_BA hdr_ba; + + DEBUG(5, ("rpc_api_pipe: return OK\n")); + + smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0); + + if (rdata.offset != 0) valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer); + } + + prs_mem_free(&data ); + prs_mem_free(&hdr ); + prs_mem_free(&hdr_rb ); + prs_mem_free(&auth_req); + prs_mem_free(&rdata ); + prs_mem_free(&rparam ); + + return valid_ack; +} + +/**************************************************************************** + open a session + ****************************************************************************/ +BOOL do_session_open(struct cli_state *cli, int t_idx, + char *pipe_name, uint16 *fnum) +{ + RPC_IFACE abstract; + RPC_IFACE transfer; + + + /******************* open the pipe *****************/ + if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE, + NULL, NULL, NULL)) == 0xffff) + { + DEBUG(1,("do_session_open: cli_open failed\n")); + return False; + } + + /**************** Set Named Pipe State ***************/ + if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300)) + { + DEBUG(1,("do_session_open: pipe hnd state failed\n")); + return False; + } + + /******************* bind request on pipe *****************/ + if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum), + &abstract, &transfer, + False, NULL, NULL)) + { + DEBUG(1,("do_session_open: rpc bind failed\n")); + return False; + } + + return True; +} + + +/**************************************************************************** + open an encrypted session + ****************************************************************************/ +BOOL do_ntlm_session_open(struct cli_state *cli, int t_idx, + char *pipe_name, uint16 *fnum, + char *my_name, char *domain) +{ + RPC_IFACE abstract; + RPC_IFACE transfer; + + /******************* open the pipe *****************/ + if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE, + NULL, NULL, NULL)) == 0xffff) + { + DEBUG(1,("do_ntlm_session_open: cli_open failed\n")); + return False; + } + + /**************** Set Named Pipe State ***************/ + if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300)) + { + DEBUG(1,("do_ntlm_session_open: pipe hnd state failed\n")); + return False; + } + + /******************* bind request on pipe *****************/ + if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum), + &abstract, &transfer, + True, my_name, domain)) + { + DEBUG(1,("do_ntlm_session_open: rpc bind failed\n")); + return False; + } + + return True; +} + + +/**************************************************************************** +close the session +****************************************************************************/ +void do_session_close(struct cli_state *cli, int t_idx, uint16 fnum) +{ + if (fnum != 0xffff) + { + cli_close(cli, t_idx, fnum, 0); + } +} + diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c new file mode 100644 index 0000000000..7a04d8ec35 --- /dev/null +++ b/source3/rpc_client/cli_samr.c @@ -0,0 +1,695 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1994-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + + 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. +*/ + + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + + + +/**************************************************************************** +do a SAMR query user groups +****************************************************************************/ +BOOL get_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol_open_domain, uint32 user_rid, + uint32 *num_groups, DOM_GID *gid) +{ + POLICY_HND pol_open_user; + if (pol_open_domain == NULL || num_groups == NULL || gid == NULL) return False; + + /* send open domain (on user sid) */ + if (!do_samr_open_user(cli, t_idx, fnum, + pol_open_domain, + 0x02011b, user_rid, + &pol_open_user)) + { + return False; + } + + /* send user groups query */ + if (!do_samr_query_usergroups(cli, t_idx, fnum, + &pol_open_user, + num_groups, gid)) + { + DEBUG(5,("do_samr_query_usergroups: error in query user groups\n")); + } + + return do_samr_close(cli, t_idx, fnum, &pol_open_user); +} + +/**************************************************************************** +do a SAMR query user info +****************************************************************************/ +BOOL get_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol_open_domain, + uint32 info_level, + uint32 user_rid, SAM_USER_INFO_21 *usr) +{ + POLICY_HND pol_open_user; + if (pol_open_domain == NULL || usr == NULL) return False; + + bzero(usr, sizeof(*usr)); + + /* send open domain (on user sid) */ + if (!do_samr_open_user(cli, t_idx, fnum, + pol_open_domain, + 0x02011b, user_rid, + &pol_open_user)) + { + return False; + } + + /* send user info query */ + if (!do_samr_query_userinfo(cli, t_idx, fnum, + &pol_open_user, + info_level, (void*)usr)) + { + DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n", + info_level)); + } + + return do_samr_close(cli, t_idx, fnum, &pol_open_user); +} + +/**************************************************************************** +do a SAMR unknown 0x8 command +****************************************************************************/ +BOOL do_samr_unknown_8(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *domain_pol, uint16 switch_value) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_UNKNOWN_8 q_e; + BOOL valid_un8 = False; + + /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value)); + + if (domain_pol == NULL || fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_unknown_8(&q_e, domain_pol, switch_value); + + /* turn parameters into data stream */ + samr_io_q_unknown_8("", &q_e, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_8, &data, &rdata)) + { +#if 0 + + SAMR_R_UNKNOWN_8 r_e; + BOOL p; + + samr_io_r_unknown_8("", &r_e, &rdata, 0); + + p = rdata.offset != 0; + if (p && r_e.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_UNKNOWN_8: %s\n", get_nt_error_msg(r_e.status))); + p = False; + } + + if (p) + { + valid_un8 = True; + } +#endif + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_un8; +} + +/**************************************************************************** +do a SAMR enumerate users +****************************************************************************/ +BOOL do_samr_enum_dom_users(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol, uint16 num_entries, uint16 unk_0, + uint16 acb_mask, uint16 unk_1, uint32 size, + struct acct_info sam[MAX_SAM_ENTRIES], + int *num_sam_users) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_ENUM_DOM_USERS q_e; + BOOL valid_pol = False; + + /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size)); + + if (pol == NULL || sam == NULL || num_sam_users == NULL || fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_enum_dom_users(&q_e, pol, + num_entries, unk_0, + acb_mask, unk_1, size); + + /* turn parameters into data stream */ + samr_io_q_enum_dom_users("", &q_e, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_ENUM_DOM_USERS, &data, &rdata)) + { + SAMR_R_ENUM_DOM_USERS r_e; + BOOL p; + + samr_io_r_enum_dom_users("", &r_e, &rdata, 0); + + p = rdata.offset != 0; + if (p && r_e.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status))); + p = False; + } + + if (p) + { + int i; + int name_idx = 0; + + *num_sam_users = r_e.num_entries2; + if (*num_sam_users > MAX_SAM_ENTRIES) + { + *num_sam_users = MAX_SAM_ENTRIES; + DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n", + *num_sam_users)); + } + for (i = 0; i < *num_sam_users; i++) + { + sam[i].smb_userid = r_e.sam[i].rid; + if (r_e.sam[i].hdr_name.buffer) + { + char *acct_name = unistrn2(r_e.uni_acct_name[name_idx].buffer, + r_e.uni_acct_name[name_idx].uni_str_len); + fstrcpy(sam[i].acct_name, acct_name); + name_idx++; + } + else + { + bzero(sam[i].acct_name, sizeof(sam[i].acct_name)); + } + DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n", + i, sam[i].smb_userid, sam[i].acct_name)); + } + valid_pol = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_pol; +} + +/**************************************************************************** +do a SAMR Connect +****************************************************************************/ +BOOL do_samr_connect(struct cli_state *cli, int t_idx, uint16 fnum, + char *srv_name, uint32 unknown_0, + POLICY_HND *connect_pol) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_CONNECT q_o; + BOOL valid_pol = False; + + /* create and send a MSRPC command with api SAMR_CONNECT */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n", + srv_name, unknown_0)); + + if (srv_name == NULL || connect_pol == NULL || fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_connect(&q_o, srv_name, unknown_0); + + /* turn parameters into data stream */ + samr_io_q_connect("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CONNECT, &data, &rdata)) + { + SAMR_R_CONNECT r_o; + BOOL p; + + samr_io_r_connect("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p) + { + memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol)); + valid_pol = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_pol; +} + +/**************************************************************************** +do a SAMR Open User +****************************************************************************/ +BOOL do_samr_open_user(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol, uint32 unk_0, uint32 rid, + POLICY_HND *user_pol) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_OPEN_USER q_o; + BOOL valid_pol = False; + + /* create and send a MSRPC command with api SAMR_OPEN_USER */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Open User. unk_0: %08x RID:%x\n", + unk_0, rid)); + + if (pol == NULL || user_pol == NULL || fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_open_user(&q_o, pol, unk_0, rid); + + /* turn parameters into data stream */ + samr_io_q_open_user("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_USER, &data, &rdata)) + { + SAMR_R_OPEN_USER r_o; + BOOL p; + + samr_io_r_open_user("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p) + { + memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol)); + valid_pol = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_pol; +} + +/**************************************************************************** +do a SAMR Open Domain +****************************************************************************/ +BOOL do_samr_open_domain(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *connect_pol, uint32 rid, char *sid, + POLICY_HND *domain_pol) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_OPEN_DOMAIN q_o; + BOOL valid_pol = False; + + /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Open Domain. SID:%s RID:%x\n", sid, rid)); + + if (connect_pol == NULL || sid == NULL || domain_pol == NULL || fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_open_domain(&q_o, connect_pol, rid, sid); + + /* turn parameters into data stream */ + samr_io_q_open_domain("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_DOMAIN, &data, &rdata)) + { + SAMR_R_OPEN_DOMAIN r_o; + BOOL p; + + samr_io_r_open_domain("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p) + { + memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol)); + valid_pol = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_pol; +} + +/**************************************************************************** +do a SAMR Query Unknown 12 +****************************************************************************/ +BOOL do_samr_query_unknown_12(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids, + uint32 *num_aliases, + fstring als_names [MAX_LOOKUP_SIDS], + uint32 num_als_users[MAX_LOOKUP_SIDS]) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_UNKNOWN_12 q_o; + BOOL valid_query = False; + + /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Query Unknown 12.\n")); + + if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL || + num_aliases == NULL || als_names == NULL || num_als_users == NULL || + fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_unknown_12(&q_o, pol, rid, num_gids, gids); + + /* turn parameters into data stream */ + samr_io_q_unknown_12("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_12, &data, &rdata)) + { + SAMR_R_UNKNOWN_12 r_o; + BOOL p; + + samr_io_r_unknown_12("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p) + { + if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 && + r_o.num_als_usrs1 == r_o.num_aliases1) + { + int i; + + valid_query = True; + *num_aliases = r_o.num_aliases1; + + for (i = 0; i < r_o.num_aliases1; i++) + { + fstrcpy(als_names[i], unistrn2(r_o.uni_als_name[i].buffer, r_o.uni_als_name[i].uni_str_len)); + } + for (i = 0; i < r_o.num_als_usrs1; i++) + { + num_als_users[i] = r_o.num_als_usrs[i]; + } + } + else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0) + { + valid_query = True; + *num_aliases = 0; + } + else + { + p = False; + } + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_query; +} + +/**************************************************************************** +do a SAMR Query User Groups +****************************************************************************/ +BOOL do_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_QUERY_USERGROUPS q_o; + BOOL valid_query = False; + + /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Query User Groups.\n")); + + if (pol == NULL || gid == NULL || num_groups == 0|| fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_query_usergroups(&q_o, pol); + + /* turn parameters into data stream */ + samr_io_q_query_usergroups("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERGROUPS, &data, &rdata)) + { + SAMR_R_QUERY_USERGROUPS r_o; + BOOL p; + + /* get user info */ + r_o.gid = gid; + + samr_io_r_query_usergroups("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p && r_o.ptr_0 != 0) + { + valid_query = True; + *num_groups = r_o.num_entries; + } + + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_query; +} + +/**************************************************************************** +do a SAMR Query User Info +****************************************************************************/ +BOOL do_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum, + POLICY_HND *pol, uint16 switch_value, void* usr) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_QUERY_USERINFO q_o; + BOOL valid_query = False; + + /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */ + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + DEBUG(4,("SAMR Query User Info. level: %d\n", switch_value)); + + if (pol == NULL || usr == NULL || switch_value == 0|| fnum == 0xffff) return False; + + /* store the parameters */ + make_samr_q_query_userinfo(&q_o, pol, switch_value); + + /* turn parameters into data stream */ + samr_io_q_query_userinfo("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERINFO, &data, &rdata)) + { + SAMR_R_QUERY_USERINFO r_o; + BOOL p; + + /* get user info */ + r_o.info.id = usr; + + samr_io_r_query_userinfo("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p && r_o.switch_value != switch_value) + { + DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n", + r_o.switch_value)); + } + + if (p && r_o.ptr != 0) + { + valid_query = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_query; +} + +/**************************************************************************** +do a SAMR Close +****************************************************************************/ +BOOL do_samr_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd) +{ + prs_struct data; + prs_struct rdata; + + SAMR_Q_CLOSE_HND q_c; + BOOL valid_close = False; + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + if (hnd == NULL) return False; + + /* create and send a MSRPC command with api SAMR_CLOSE_HND */ + + DEBUG(4,("SAMR Close\n")); + + /* store the parameters */ + make_samr_q_close_hnd(&q_c, hnd); + + /* turn parameters into data stream */ + samr_io_q_close_hnd("", &q_c, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CLOSE_HND, &data, &rdata)) + { + SAMR_R_CLOSE_HND r_c; + BOOL p; + + samr_io_r_close_hnd("", &r_c, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_c.status != 0) + { + /* report error code */ + DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status))); + p = False; + } + + if (p) + { + /* check that the returned policy handle is all zeros */ + int i; + valid_close = True; + + for (i = 0; i < sizeof(r_c.pol.data); i++) + { + if (r_c.pol.data[i] != 0) + { + valid_close = False; + break; + } + } + if (!valid_close) + { + DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n")); + } + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_close; +} + diff --git a/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c new file mode 100644 index 0000000000..dcedeb3a54 --- /dev/null +++ b/source3/rpc_client/cli_srvsvc.c @@ -0,0 +1,411 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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. + */ + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +extern int DEBUGLEVEL; + +/**************************************************************************** +do a server net conn enum +****************************************************************************/ +BOOL do_srv_net_srv_conn_enum(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, char *qual_name, + uint32 switch_value, SRV_CONN_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + prs_struct data; + prs_struct rdata; + SRV_Q_NET_CONN_ENUM q_o; + BOOL valid_enum = False; + + if (server_name == NULL || ctr == NULL || preferred_len == 0) return False; + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api SRV_NETCONNENUM */ + + DEBUG(4,("SRV Net Server Connection Enum(%s, %s), level %d, enum:%8x\n", + server_name, qual_name, switch_value, get_enum_hnd(hnd))); + + ctr->switch_value = switch_value; + ctr->ptr_conn_ctr = 1; + ctr->conn.info0.num_entries_read = 0; + ctr->conn.info0.ptr_conn_info = 1; + + /* store the parameters */ + make_srv_q_net_conn_enum(&q_o, server_name, qual_name, + switch_value, ctr, + preferred_len, + hnd); + + /* turn parameters into data stream */ + srv_io_q_net_conn_enum("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETCONNENUM, &data, &rdata)) + { + SRV_R_NET_CONN_ENUM r_o; + BOOL p; + + r_o.ctr = ctr; + + srv_io_r_net_conn_enum("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status))); + p = 0; + } + + if (p && r_o.ctr->switch_value != switch_value) + { + /* different switch levels. oops. */ + DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: info class %d does not match request %d\n", + r_o.ctr->switch_value, switch_value)); + p = 0; + } + + if (p) + { + /* ok, at last: we're happy. */ + valid_enum = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_enum; +} + +/**************************************************************************** +do a server net sess enum +****************************************************************************/ +BOOL do_srv_net_srv_sess_enum(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, char *qual_name, + uint32 switch_value, SRV_SESS_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + prs_struct data; + prs_struct rdata; + SRV_Q_NET_SESS_ENUM q_o; + BOOL valid_enum = False; + + if (server_name == NULL || ctr == NULL || preferred_len == 0) return False; + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api SRV_NETSESSENUM */ + + DEBUG(4,("SRV Net Session Enum (%s), level %d, enum:%8x\n", + server_name, switch_value, get_enum_hnd(hnd))); + + ctr->switch_value = switch_value; + ctr->ptr_sess_ctr = 1; + ctr->sess.info0.num_entries_read = 0; + ctr->sess.info0.ptr_sess_info = 1; + + /* store the parameters */ + make_srv_q_net_sess_enum(&q_o, server_name, qual_name, + switch_value, ctr, + preferred_len, + hnd); + + /* turn parameters into data stream */ + srv_io_q_net_sess_enum("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETSESSENUM, &data, &rdata)) + { + SRV_R_NET_SESS_ENUM r_o; + BOOL p; + + r_o.ctr = ctr; + + srv_io_r_net_sess_enum("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status))); + p = 0; + } + + if (p && r_o.ctr->switch_value != switch_value) + { + /* different switch levels. oops. */ + DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: info class %d does not match request %d\n", + r_o.ctr->switch_value, switch_value)); + p = 0; + } + + if (p) + { + /* ok, at last: we're happy. */ + valid_enum = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_enum; +} + +/**************************************************************************** +do a server net share enum +****************************************************************************/ +BOOL do_srv_net_srv_share_enum(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, + uint32 switch_value, SRV_SHARE_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + prs_struct data; + prs_struct rdata; + SRV_Q_NET_SHARE_ENUM q_o; + BOOL valid_enum = False; + + if (server_name == NULL || ctr == NULL || preferred_len == 0) return False; + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api SRV_NETSHAREENUM */ + + DEBUG(4,("SRV Get Share Info (%s), level %d, enum:%8x\n", + server_name, switch_value, get_enum_hnd(hnd))); + + q_o.share_level = switch_value; + + ctr->switch_value = switch_value; + ctr->ptr_share_ctr = 1; + ctr->share.info1.num_entries_read = 0; + ctr->share.info1.ptr_share_info = 1; + + /* store the parameters */ + make_srv_q_net_share_enum(&q_o, server_name, + switch_value, ctr, + preferred_len, + hnd); + + /* turn parameters into data stream */ + srv_io_q_net_share_enum("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETSHAREENUM, &data, &rdata)) + { + SRV_R_NET_SHARE_ENUM r_o; + BOOL p; + + r_o.ctr = ctr; + + srv_io_r_net_share_enum("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status))); + p = 0; + } + + if (p && r_o.ctr->switch_value != switch_value) + { + /* different switch levels. oops. */ + DEBUG(0,("SRV_R_NET_SRV_SHARE_ENUM: info class %d does not match request %d\n", + r_o.ctr->switch_value, switch_value)); + p = 0; + } + + if (p) + { + /* ok, at last: we're happy. */ + valid_enum = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_enum; +} + +/**************************************************************************** +do a server net file enum +****************************************************************************/ +BOOL do_srv_net_srv_file_enum(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, char *qual_name, + uint32 switch_value, SRV_FILE_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + prs_struct data; + prs_struct rdata; + SRV_Q_NET_FILE_ENUM q_o; + BOOL valid_enum = False; + + if (server_name == NULL || ctr == NULL || preferred_len == 0) return False; + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api SRV_NETFILEENUM */ + + DEBUG(4,("SRV Get File Info (%s), level %d, enum:%8x\n", + server_name, switch_value, get_enum_hnd(hnd))); + + q_o.file_level = switch_value; + + ctr->switch_value = switch_value; + ctr->ptr_file_ctr = 1; + ctr->file.info3.num_entries_read = 0; + ctr->file.info3.ptr_file_info = 1; + + /* store the parameters */ + make_srv_q_net_file_enum(&q_o, server_name, qual_name, + switch_value, ctr, + preferred_len, + hnd); + + /* turn parameters into data stream */ + srv_io_q_net_file_enum("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETFILEENUM, &data, &rdata)) + { + SRV_R_NET_FILE_ENUM r_o; + BOOL p; + + r_o.ctr = ctr; + + srv_io_r_net_file_enum("", &r_o, &rdata, 0); + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status))); + p = 0; + } + + if (p && r_o.ctr->switch_value != switch_value) + { + /* different switch levels. oops. */ + DEBUG(0,("SRV_R_NET_SRV_FILE_ENUM: info class %d does not match request %d\n", + r_o.ctr->switch_value, switch_value)); + p = 0; + } + + if (p) + { + /* ok, at last: we're happy. */ + valid_enum = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_enum; +} + +/**************************************************************************** +do a server get info +****************************************************************************/ +BOOL do_srv_net_srv_get_info(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr) +{ + prs_struct data; + prs_struct rdata; + SRV_Q_NET_SRV_GET_INFO q_o; + BOOL valid_info = False; + + if (server_name == NULL || switch_value == 0 || ctr == NULL) return False; + + prs_init(&data , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api SRV_NET_SRV_GET_INFO */ + + DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value)); + + /* store the parameters */ + make_srv_q_net_srv_get_info(&q_o, server_name, switch_value); + + /* turn parameters into data stream */ + srv_io_q_net_srv_get_info("", &q_o, &data, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NET_SRV_GET_INFO, &data, &rdata)) + { + SRV_R_NET_SRV_GET_INFO r_o; + BOOL p; + + r_o.ctr = ctr; + + srv_io_r_net_srv_get_info("", &r_o, &rdata, 0); + p = rdata.offset != 0; + p = rdata.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status))); + p = 0; + } + + if (p && r_o.ctr->switch_value != q_o.switch_value) + { + /* different switch levels. oops. */ + DEBUG(0,("SRV_R_NET_SRV_GET_INFO: info class %d does not match request %d\n", + r_o.ctr->switch_value, q_o.switch_value)); + p = 0; + } + + if (p) + { + /* ok, at last: we're happy. */ + valid_info = True; + } + } + + prs_mem_free(&data ); + prs_mem_free(&rdata ); + + return valid_info; +} + diff --git a/source3/rpc_client/cli_wkssvc.c b/source3/rpc_client/cli_wkssvc.c new file mode 100644 index 0000000000..f5a4c203e0 --- /dev/null +++ b/source3/rpc_client/cli_wkssvc.c @@ -0,0 +1,90 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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. + */ + + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +extern int DEBUGLEVEL; + +/**************************************************************************** +do a WKS Open Policy +****************************************************************************/ +BOOL do_wks_query_info(struct cli_state *cli, int t_idx, uint16 fnum, + char *server_name, uint32 switch_value, + WKS_INFO_100 *wks100) +{ + prs_struct rbuf; + prs_struct buf; + WKS_Q_QUERY_INFO q_o; + BOOL valid_info = False; + + if (server_name == 0 || wks100 == NULL) return False; + + prs_init(&buf , 1024, 4, SAFETY_MARGIN, False); + prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True ); + + /* create and send a MSRPC command with api WKS_QUERY_INFO */ + + DEBUG(4,("WKS Query Info\n")); + + /* store the parameters */ + make_wks_q_query_info(&q_o, server_name, switch_value); + + /* turn parameters into data stream */ + wks_io_q_query_info("", &q_o, &buf, 0); + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, t_idx, fnum, WKS_QUERY_INFO, &buf, &rbuf)) + { + WKS_R_QUERY_INFO r_o; + BOOL p; + + r_o.wks100 = wks100; + + wks_io_r_query_info("", &r_o, &rbuf, 0); + p = rbuf.offset != 0; + + if (p && r_o.status != 0) + { + /* report error code */ + DEBUG(0,("WKS_R_QUERY_INFO: %s\n", get_nt_error_msg(r_o.status))); + p = False; + } + + if (p) + { + valid_info = True; + } + } + + prs_mem_free(&rbuf); + prs_mem_free(&buf ); + + return valid_info; +} + diff --git a/source3/rpc_client/ntclienttrust.c b/source3/rpc_client/ntclienttrust.c new file mode 100644 index 0000000000..38cbedae78 --- /dev/null +++ b/source3/rpc_client/ntclienttrust.c @@ -0,0 +1,167 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1994-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + + 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. +*/ + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + + +/************************************************************************ + check workstation trust account status + ************************************************************************/ +BOOL trust_account_check(struct in_addr dest_ip, char *dest_host, + char *myhostname, char *domain, fstring mach_acct, + fstring new_mach_pwd) +{ + pstring tmp; + fstring mach_pwd; + struct cli_state cli_trust; + uchar lm_owf_mach_pwd[16]; + uchar nt_owf_mach_pwd[16]; + uchar lm_sess_pwd[24]; + uchar nt_sess_pwd[24]; + + BOOL right_error_code = False; + uint8 err_cls; + uint32 err_num; + + char *start_mach_pwd; + char *change_mach_pwd; + + /* initial machine password */ + fstrcpy(mach_pwd, myhostname); + strlower(mach_pwd); + + sprintf(tmp, "Enter Workstation Trust Account password for [%s].\nDefault is [%s].\nPassword:", + mach_acct, mach_pwd); + + start_mach_pwd = (char*)getpass(tmp); + + if (start_mach_pwd[0] != 0) + { + fstrcpy(mach_pwd, start_mach_pwd); + } + + sprintf(tmp, "Enter new Workstation Trust Account password for [%s]\nPress Return to leave at old value.\nNew Password:", + mach_acct); + + change_mach_pwd = (char*)getpass(tmp); + + if (change_mach_pwd[0] != 0) + { + fstrcpy(new_mach_pwd, change_mach_pwd); + } + else + { + DEBUG(1,("trust_account_check: password change not requested\n")); + change_mach_pwd[0] = 0; + } + + DEBUG(1,("initialise cli_trust connection\n")); + + if (!cli_initialise(&cli_trust)) + { + DEBUG(1,("cli_initialise failed for cli_trust\n")); + return False; + } + + DEBUG(1,("server connect for cli_trust\n")); + + if (!server_connect_init(&cli_trust, myhostname, dest_ip, dest_host)) + { + cli_error(&cli_trust, &err_cls, &err_num); + DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(&cli_trust))); + + cli_shutdown(&cli_trust); + return False; + } + + DEBUG(1,("server connect cli_trust succeeded\n")); + + nt_lm_owf_gen(mach_pwd, nt_owf_mach_pwd, lm_owf_mach_pwd); + + DEBUG(5,("generating nt owf from initial machine pwd: %s\n", mach_pwd)); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("client cryptkey: ")); + dump_data(100, cli_trust.cryptkey, sizeof(cli_trust.cryptkey)); +#endif + + SMBencrypt(nt_owf_mach_pwd, cli_trust.cryptkey, nt_sess_pwd); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("nt_owf_mach_pwd: ")); + dump_data(100, nt_owf_mach_pwd, sizeof(lm_owf_mach_pwd)); + DEBUG(100,("nt_sess_pwd: ")); + dump_data(100, nt_sess_pwd, sizeof(nt_sess_pwd)); +#endif + + SMBencrypt(lm_owf_mach_pwd, cli_trust.cryptkey, lm_sess_pwd); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("lm_owf_mach_pwd: ")); + dump_data(100, lm_owf_mach_pwd, sizeof(lm_owf_mach_pwd)); + DEBUG(100,("lm_sess_pwd: ")); + dump_data(100, lm_sess_pwd, sizeof(lm_sess_pwd)); +#endif + + right_error_code = False; + + if (cli_session_setup(&cli_trust, mach_acct, + nt_owf_mach_pwd, sizeof(nt_owf_mach_pwd), + nt_owf_mach_pwd, sizeof(nt_owf_mach_pwd), domain)) + { + DEBUG(0,("cli_session_setup: NO ERROR! AAAGH! BUG IN SERVER DETECTED!!!\n")); + cli_shutdown(&cli_trust); + + return False; + } + + cli_error(&cli_trust, &err_cls, &err_num); + + if (err_num == (0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)) + { + DEBUG(1,("cli_send_tconX: valid workstation trust account exists\n")); + right_error_code = True; + } + + if (err_num == (0xC0000000 | NT_STATUS_NO_SUCH_USER)) + { + DEBUG(1,("cli_send_tconX: workstation trust account does not exist\n")); + right_error_code = False; + } + + if (!right_error_code) + { + DEBUG(1,("server_validate failed (%s)\n", cli_errstr(&cli_trust))); + } + + cli_shutdown(&cli_trust); + return right_error_code; +} + + diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c new file mode 100644 index 0000000000..6eb42fc749 --- /dev/null +++ b/source3/rpc_parse/parse_lsa.c @@ -0,0 +1,567 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + + +/******************************************************************* +creates a LSA_TRANS_NAME structure. +********************************************************************/ +void make_lsa_trans_name(LSA_TRANS_NAME *trn, uint32 sid_name_use, char *name, uint32 idx) +{ + int len_name = strlen(name); + + trn->sid_name_use = sid_name_use; + make_uni_hdr(&(trn->hdr_name), len_name, len_name, len_name != 0); + make_unistr2(&(trn->uni_name), name, len_name); + trn->domain_idx = idx; +} + +/******************************************************************* +reads or writes a LSA_TRANS_NAME structure. +********************************************************************/ +void lsa_io_trans_name(char *desc, LSA_TRANS_NAME *trn, prs_struct *ps, int depth) +{ + if (trn == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_trans_name"); + depth++; + + prs_align(ps); + + prs_uint32("sid_name_use", ps, depth, &(trn->sid_name_use)); + + smb_io_unihdr ("hdr_name", &(trn->hdr_name), ps, depth); + smb_io_unistr2("uni_name", &(trn->uni_name), trn->hdr_name.buffer, ps, depth); + + prs_uint32("domain_idx ", ps, depth, &(trn->domain_idx )); +} + +/******************************************************************* +reads or writes a DOM_R_REF structure. +********************************************************************/ +void lsa_io_dom_r_ref(char *desc, DOM_R_REF *r_r, prs_struct *ps, int depth) +{ + int i; + + prs_debug(ps, depth, desc, "smb_io_dom_r_ref"); + depth++; + + if (r_r == NULL) return; + + prs_align(ps); + + prs_uint32("undoc_buffer ", ps, depth, &(r_r->undoc_buffer)); /* undocumented buffer pointer. */ + prs_uint32("num_ref_doms_1 ", ps, depth, &(r_r->num_ref_doms_1)); /* num referenced domains? */ + prs_uint32("buffer_dom_name", ps, depth, &(r_r->buffer_dom_name)); /* undocumented domain name buffer pointer. */ + prs_uint32("max_entries ", ps, depth, &(r_r->max_entries)); /* 32 - max number of entries */ + prs_uint32("num_ref_doms_2 ", ps, depth, &(r_r->num_ref_doms_2)); /* 4 - num referenced domains? */ + + smb_io_unihdr2("", &(r_r->hdr_dom_name), ps, depth); /* domain name unicode string header */ + + for (i = 0; i < r_r->num_ref_doms_1-1; i++) + { + smb_io_unihdr2("", &(r_r->hdr_ref_dom[i]), ps, depth); + } + + smb_io_unistr("", &(r_r->uni_dom_name), ps, depth); /* domain name unicode string */ + + for (i = 0; i < r_r->num_ref_doms_2; i++) + { + smb_io_dom_sid2("", &(r_r->ref_dom[i]), ps, depth); /* referenced domain SIDs */ + } +} + +/******************************************************************* +makes an LSA_OBJ_ATTR structure. +********************************************************************/ +void make_lsa_obj_attr(LSA_OBJ_ATTR *attr, uint32 attributes, uint32 sec_qos) +{ + if (attr == NULL) return; + + DEBUG(5,("make_lsa_obj_attr\n")); + + attr->len = 0x18; /* length of object attribute block, in bytes */ + attr->ptr_root_dir = 0; + attr->ptr_obj_name = 0; + attr->attributes = attributes; + attr->ptr_sec_desc = 0; + attr->sec_qos = sec_qos; +} + +/******************************************************************* +reads or writes an LSA_OBJ_ATTR structure. +********************************************************************/ +void lsa_io_obj_attr(char *desc, LSA_OBJ_ATTR *attr, prs_struct *ps, int depth) +{ + int start; + + if (attr == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_obj_attr"); + depth++; + + prs_align(ps); + + start = ps->offset; + + /* these pointers had _better_ be zero, because we don't know + what they point to! + */ + prs_uint32("len" , ps, depth, &(attr->len )); /* 0x18 - length (in bytes) inc. the length field. */ + prs_uint32("ptr_root_dir", ps, depth, &(attr->ptr_root_dir)); /* 0 - root directory (pointer) */ + prs_uint32("ptr_obj_name", ps, depth, &(attr->ptr_obj_name)); /* 0 - object name (pointer) */ + prs_uint32("attributes" , ps, depth, &(attr->attributes )); /* 0 - attributes (undocumented) */ + prs_uint32("ptr_sec_desc", ps, depth, &(attr->ptr_sec_desc)); /* 0 - security descriptior (pointer) */ + prs_uint32("sec_qos" , ps, depth, &(attr->sec_qos )); /* 0 - security quality of service */ + + if (attr->len != ps->offset - start) + { + DEBUG(3,("lsa_io_obj_attr: length %lx does not match size %lx\n", + attr->len, ps->offset - start)); + } +} +/******************************************************************* +makes an LSA_Q_OPEN_POL structure. +********************************************************************/ +void make_q_open_pol(LSA_Q_OPEN_POL *r_q, char *server_name, + uint32 attributes, uint32 sec_qos, + uint32 desired_access) +{ + if (r_q == NULL) return; + + DEBUG(5,("make_open_pol\n")); + + r_q->ptr = 1; /* undocumented pointer */ + + make_unistr2 (&(r_q->uni_server_name), server_name, strlen(server_name)); + make_lsa_obj_attr(&(r_q->attr ), attributes, sec_qos); + + r_q->des_access = desired_access; +} + +/******************************************************************* +reads or writes an LSA_Q_OPEN_POL structure. +********************************************************************/ +void lsa_io_q_open_pol(char *desc, LSA_Q_OPEN_POL *r_q, prs_struct *ps, int depth) +{ + if (r_q == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_q_open_pol"); + depth++; + + prs_uint32("ptr ", ps, depth, &(r_q->ptr )); + + smb_io_unistr2 ("", &(r_q->uni_server_name), r_q->ptr, ps, depth); + lsa_io_obj_attr("", &(r_q->attr ), ps, depth); + + prs_uint32("des_access", ps, depth, &(r_q->des_access)); +} + +/******************************************************************* +reads or writes an LSA_R_OPEN_POL structure. +********************************************************************/ +void lsa_io_r_open_pol(char *desc, LSA_R_OPEN_POL *r_p, prs_struct *ps, int depth) +{ + if (r_p == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_r_open_pol"); + depth++; + + + smb_io_pol_hnd("", &(r_p->pol), ps, depth); + + prs_uint32("status", ps, depth, &(r_p->status)); +} + +/******************************************************************* +makes an LSA_Q_QUERY_INFO structure. +********************************************************************/ +void make_q_query(LSA_Q_QUERY_INFO *q_q, POLICY_HND *hnd, uint16 info_class) +{ + if (q_q == NULL || hnd == NULL) return; + + DEBUG(5,("make_q_query\n")); + + memcpy(&(q_q->pol), hnd, sizeof(q_q->pol)); + + q_q->info_class = info_class; +} + +/******************************************************************* +reads or writes an LSA_Q_QUERY_INFO structure. +********************************************************************/ +void lsa_io_q_query(char *desc, LSA_Q_QUERY_INFO *q_q, prs_struct *ps, int depth) +{ + if (q_q == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_q_query"); + depth++; + + smb_io_pol_hnd("", &(q_q->pol), ps, depth); + + prs_uint16("info_class", ps, depth, &(q_q->info_class)); +} + +/******************************************************************* +reads or writes an LSA_Q_ENUM_TRUST_DOM structure. +********************************************************************/ +void lsa_io_q_enum_trust_dom(char *desc, LSA_Q_ENUM_TRUST_DOM *q_e, prs_struct *ps, int depth) +{ + if (q_e == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_q_enum_trust_dom"); + depth++; + + + smb_io_pol_hnd("", &(q_e->pol), ps, depth); + + prs_uint32("enum_context ", ps, depth, &(q_e->enum_context )); + prs_uint32("preferred_len", ps, depth, &(q_e->preferred_len)); +} + +/******************************************************************* +makes an LSA_R_ENUM_TRUST_DOM structure. +********************************************************************/ +void make_r_enum_trust_dom(LSA_R_ENUM_TRUST_DOM *r_e, + uint32 enum_context, char *domain_name, char *domain_sid, + uint32 status) +{ + if (r_e == NULL) return; + + DEBUG(5,("make_r_enum_trust_dom\n")); + + r_e->enum_context = enum_context; + + if (status == 0) + { + int len_domain_name = strlen(domain_name); + + r_e->num_domains = 1; + r_e->ptr_enum_domains = 1; + r_e->num_domains2 = 1; + + make_uni_hdr2(&(r_e->hdr_domain_name ), len_domain_name, len_domain_name, 4); + make_unistr2 (&(r_e->uni_domain_name ), domain_name, len_domain_name); + make_dom_sid2(&(r_e->other_domain_sid), domain_sid); + } + else + { + r_e->num_domains = 0; + r_e->ptr_enum_domains = 0; + } + + r_e->status = status; +} + +/******************************************************************* +reads or writes an LSA_R_ENUM_TRUST_DOM structure. +********************************************************************/ +void lsa_io_r_enum_trust_dom(char *desc, LSA_R_ENUM_TRUST_DOM *r_e, prs_struct *ps, int depth) +{ + if (r_e == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_r_enum_trust_dom"); + depth++; + + prs_uint32("enum_context ", ps, depth, &(r_e->enum_context )); + prs_uint32("num_domains ", ps, depth, &(r_e->num_domains )); + prs_uint32("ptr_enum_domains", ps, depth, &(r_e->ptr_enum_domains)); + + if (r_e->ptr_enum_domains != 0) + { + prs_uint32("num_domains2", ps, depth, &(r_e->num_domains2)); + smb_io_unihdr2 ("", &(r_e->hdr_domain_name ), ps, depth); + smb_io_unistr2 ("", &(r_e->uni_domain_name ), r_e->hdr_domain_name.buffer, ps, depth); + smb_io_dom_sid2("", &(r_e->other_domain_sid), ps, depth); + } + + prs_uint32("status", ps, depth, &(r_e->status)); +} + +/******************************************************************* +makes an LSA_Q_CLOSE structure. +********************************************************************/ +void make_lsa_q_close(LSA_Q_CLOSE *q_c, POLICY_HND *hnd) +{ + if (q_c == NULL || hnd == NULL) return; + + DEBUG(5,("make_lsa_q_close\n")); + + memcpy(&(q_c->pol), hnd, sizeof(q_c->pol)); +} + + +/******************************************************************* +reads or writes an LSA_Q_CLOSE structure. +********************************************************************/ +void lsa_io_q_close(char *desc, LSA_Q_CLOSE *q_c, prs_struct *ps, int depth) +{ + if (q_c == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_q_close"); + depth++; + + smb_io_pol_hnd("", &(q_c->pol), ps, depth); +} + +/******************************************************************* +makes an LSA_R_CLOSE structure. +********************************************************************/ +void make_lsa_r_close(LSA_R_CLOSE *q_r, POLICY_HND *hnd) +{ + if (q_r == NULL || hnd == NULL) return; + + DEBUG(5,("make_lsa_r_close\n")); + + memcpy(&(q_r->pol), hnd, sizeof(q_r->pol)); +} + + +/******************************************************************* +reads or writes an LSA_R_CLOSE structure. +********************************************************************/ +void lsa_io_r_close(char *desc, LSA_R_CLOSE *r_c, prs_struct *ps, int depth) +{ + if (r_c == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_r_close"); + depth++; + + smb_io_pol_hnd("", &(r_c->pol), ps, depth); + + prs_uint32("status", ps, depth, &(r_c->status)); +} + +/******************************************************************* +reads or writes an LSA_Q_QUERY_INFO structure. +********************************************************************/ +void lsa_io_r_query(char *desc, LSA_R_QUERY_INFO *r_q, prs_struct *ps, int depth) +{ + if (r_q == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_r_query"); + depth++; + + prs_uint32("undoc_buffer", ps, depth, &(r_q->undoc_buffer)); + + if (r_q->undoc_buffer != 0) + { + prs_uint16("info_class", ps, depth, &(r_q->info_class)); + + switch (r_q->info_class) + { + case 3: + { + smb_io_dom_query_3("", &(r_q->dom.id3), ps, depth); + break; + } + case 5: + { + smb_io_dom_query_5("", &(r_q->dom.id3), ps, depth); + break; + } + default: + { + /* PANIC! */ + break; + } + } + } + + prs_uint32("status", ps, depth, &(r_q->status)); +} + +/******************************************************************* +reads or writes a LSA_SID_ENUM structure. +********************************************************************/ +void lsa_io_sid_enum(char *desc, LSA_SID_ENUM *sen, prs_struct *ps, int depth) +{ + int i; + + if (sen == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_sid_enum"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries ", ps, depth, &(sen->num_entries)); + prs_uint32("ptr_sid_enum", ps, depth, &(sen->ptr_sid_enum)); + prs_uint32("num_entries2", ps, depth, &(sen->num_entries2)); + + for (i = 0; i < sen->num_entries; i++) + { + fstring temp; + sprintf(temp, "ptr_sid[%d]", i); + prs_uint32(temp, ps, depth, &(sen->ptr_sid[i])); /* domain SID pointers to be looked up. */ + } + + for (i = 0; i < sen->num_entries; i++) + { + fstring temp; + sprintf(temp, "sid[%d]", i); + smb_io_dom_sid2(temp, &(sen->sid[i]), ps, depth); /* domain SIDs to be looked up. */ + } +} + +/******************************************************************* +reads or writes a LSA_Q_LOOKUP_SIDS structure. +********************************************************************/ +void lsa_io_q_lookup_sids(char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct *ps, int depth) +{ + if (q_s == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_q_lookup_sids"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd ("pol_hnd", &(q_s->pol_hnd), ps, depth); /* policy handle */ + lsa_io_sid_enum ("sids ", &(q_s->sids ), ps, depth); /* sids to be looked up */ + lsa_io_trans_names ("names ", &(q_s->names ), ps, depth); /* translated names */ + smb_io_lookup_level("switch ", &(q_s->level ), ps, depth); /* lookup level */ + + prs_uint32("mapped_count", ps, depth, &(q_s->mapped_count)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void lsa_io_trans_names(char *desc, LSA_TRANS_NAME_ENUM *trn, prs_struct *ps, int depth) +{ + int i; + int i2; + + if (trn == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_trans_names"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries ", ps, depth, &(trn->num_entries)); + prs_uint32("ptr_trans_names", ps, depth, &(trn->ptr_trans_names)); + prs_uint32("num_entries2 ", ps, depth, &(trn->num_entries2)); + + for (i = 0; i < trn->num_entries; i++) + { + fstring temp; + sprintf(temp, "ptr_name[%d] ", i); + prs_uint32(temp, ps, depth, &(trn->ptr_name[i])); /* pointer to translated name */ + } + + for (i = 0; i < trn->num_entries2; i++) + { + if (trn->ptr_name[i] != 0) + { + fstring temp; + sprintf(temp, "name[%d] ", i); + lsa_io_trans_name(temp, &(trn->name[i2]), ps, depth); /* translated name */ + i2++; + } + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void lsa_io_r_lookup_sids(char *desc, LSA_R_LOOKUP_SIDS *r_s, prs_struct *ps, int depth) +{ + if (r_s == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_r_lookup_sids"); + depth++; + + prs_align(ps); + + lsa_io_dom_r_ref ("dom_ref", r_s->dom_ref, ps, depth); /* domain reference info */ + lsa_io_trans_names("names ", r_s->names , ps, depth); /* translated names */ + + prs_uint32("mapped_count", ps, depth, &(r_s->mapped_count)); + + prs_uint32("status ", ps, depth, &(r_s->status)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void lsa_io_q_lookup_rids(char *desc, LSA_Q_LOOKUP_RIDS *q_r, prs_struct *ps, int depth) +{ + int i; + + if (q_r == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_q_lookup_rids"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(q_r->pol_hnd), ps, depth); /* policy handle */ + + prs_uint32("num_entries ", ps, depth, &(q_r->num_entries)); + prs_uint32("num_entries2 ", ps, depth, &(q_r->num_entries2)); + prs_uint32("buffer_dom_sid ", ps, depth, &(q_r->buffer_dom_sid)); /* undocumented domain SID buffer pointer */ + prs_uint32("buffer_dom_name", ps, depth, &(q_r->buffer_dom_name)); /* undocumented domain name buffer pointer */ + + for (i = 0; i < q_r->num_entries; i++) + { + smb_io_dom_name("", &(q_r->lookup_name[i]), ps, depth); /* names to be looked up */ + } + + prs_uint8s (False, "undoc ", ps, depth, q_r->undoc, UNKNOWN_LEN); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void lsa_io_r_lookup_rids(char *desc, LSA_R_LOOKUP_RIDS *r_r, prs_struct *ps, int depth) +{ + int i; + + if (r_r == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_r_lookup_rids"); + depth++; + + prs_align(ps); + + lsa_io_dom_r_ref("", &(r_r->dom_ref), ps, depth); /* domain reference info */ + + prs_uint32("num_entries ", ps, depth, &(r_r->num_entries)); + prs_uint32("undoc_buffer", ps, depth, &(r_r->undoc_buffer)); + prs_uint32("num_entries2", ps, depth, &(r_r->num_entries2)); + + for (i = 0; i < r_r->num_entries2; i++) + { + smb_io_dom_rid2("", &(r_r->dom_rid[i]), ps, depth); /* domain RIDs being looked up */ + } + + prs_uint32("num_entries3", ps, depth, &(r_r->num_entries3)); + + prs_uint32("status ", ps, depth, &(r_r->status)); +} + diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c new file mode 100644 index 0000000000..225754903f --- /dev/null +++ b/source3/rpc_parse/parse_misc.c @@ -0,0 +1,981 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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" + +extern int DEBUGLEVEL; + + + +/******************************************************************* +reads or writes a UTIME type. +********************************************************************/ +void smb_io_utime(char *desc, UTIME *t, prs_struct *ps, int depth) +{ + if (t == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_utime"); + depth++; + + prs_align(ps); + + prs_uint32 ("time", ps, depth, &(t->time)); +} + +/******************************************************************* +reads or writes an NTTIME structure. +********************************************************************/ +void smb_io_time(char *desc, NTTIME *nttime, prs_struct *ps, int depth) +{ + if (nttime == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_time"); + depth++; + + prs_align(ps); + + prs_uint32("low ", ps, depth, &(nttime->low )); /* low part */ + prs_uint32("high", ps, depth, &(nttime->high)); /* high part */ +} + +/******************************************************************* +reads or writes a LOOKUP_LEVEL structure. +********************************************************************/ +void smb_io_lookup_level(char *desc, LOOKUP_LEVEL *level, prs_struct *ps, int depth) +{ + if (level == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_lookup_level"); + depth++; + + prs_align(ps); + prs_uint16("value", ps, depth, &(level->value)); + prs_align(ps); +} + +/******************************************************************* +gets an enumeration handle from an ENUM_HND structure. +********************************************************************/ +uint32 get_enum_hnd(ENUM_HND *enh) +{ + return (enh && enh->ptr_hnd != 0) ? enh->handle : 0; +} + +/******************************************************************* +makes an ENUM_HND structure. +********************************************************************/ +void make_enum_hnd(ENUM_HND *enh, uint32 hnd) +{ + if (enh == NULL) return; + + DEBUG(5,("smb_io_enum_hnd\n")); + + enh->ptr_hnd = (hnd != 0) ? 1 : 0; + enh->handle = hnd; +} + +/******************************************************************* +reads or writes an ENUM_HND structure. +********************************************************************/ +void smb_io_enum_hnd(char *desc, ENUM_HND *hnd, prs_struct *ps, int depth) +{ + if (hnd == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_enum_hnd"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_hnd", ps, depth, &(hnd->ptr_hnd)); /* pointer */ + if (hnd->ptr_hnd != 0) + { + prs_uint32("handle ", ps, depth, &(hnd->handle )); /* enum handle */ + } +} + +/******************************************************************* +creates a DOM_SID structure. + +BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 +identauth >= 2^32 can be detected because it will be specified in hex + +********************************************************************/ +void make_dom_sid(DOM_SID *sid, char *str_sid) +{ + pstring domsid; + int identauth; + char *p; + + if (sid == NULL) return; + + if (domsid == NULL) + { + DEBUG(4,("netlogon domain SID: none\n")); + sid->sid_rev_num = 0; + sid->num_auths = 0; + return; + } + + pstrcpy(domsid, str_sid); + + DEBUG(4,("make_dom_sid %d SID: %s\n", __LINE__, domsid)); + + /* assume, but should check, that domsid starts "S-" */ + p = strtok(domsid+2,"-"); + sid->sid_rev_num = atoi(p); + + /* identauth in decimal should be < 2^32 */ + /* identauth in hex should be >= 2^32 */ + identauth = atoi(strtok(0,"-")); + + DEBUG(4,("netlogon rev %d\n", sid->sid_rev_num)); + DEBUG(4,("netlogon %s ia %d\n", p, identauth)); + + sid->id_auth[0] = 0; + sid->id_auth[1] = 0; + sid->id_auth[2] = (identauth & 0xff000000) >> 24; + sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; + sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; + sid->id_auth[5] = (identauth & 0x000000ff); + + sid->num_auths = 0; + + while ((p = strtok(0, "-")) != NULL && sid->num_auths < MAXSUBAUTHS) + { + sid->sub_auths[sid->num_auths++] = atoi(p); + } + + DEBUG(4,("make_dom_sid: %d SID: %s\n", __LINE__, domsid)); +} + +/******************************************************************* +reads or writes a DOM_SID structure. +********************************************************************/ +void smb_io_dom_sid(char *desc, DOM_SID *sid, prs_struct *ps, int depth) +{ + int i; + + if (sid == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_sid"); + depth++; + + prs_align(ps); + + prs_uint8 ("sid_rev_num", ps, depth, &(sid->sid_rev_num)); + prs_uint8 ("num_auths ", ps, depth, &(sid->num_auths)); + + for (i = 0; i < 6; i++) + { + fstring tmp; + sprintf(tmp, "id_auth[%d] ", i); + prs_uint8 (tmp, ps, depth, &(sid->id_auth[i])); + } + + /* oops! XXXX should really issue a warning here... */ + if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS; + + prs_uint32s(False, "sub_auths ", ps, depth, sid->sub_auths, sid->num_auths); +} + +/******************************************************************* +creates a DOM_SID2 structure. +********************************************************************/ +void make_dom_sid2(DOM_SID2 *sid, char *str_sid) +{ + make_dom_sid(&(sid->sid), str_sid); + sid->num_auths = sid->sid.num_auths; +} + +/******************************************************************* +reads or writes a DOM_SID2 structure. +********************************************************************/ +void smb_io_dom_sid2(char *desc, DOM_SID2 *sid, prs_struct *ps, int depth) +{ + if (sid == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_sid2"); + depth++; + + prs_align(ps); + + prs_uint32("num_auths", ps, depth, &(sid->num_auths)); + + smb_io_dom_sid("sid", &(sid->sid), ps, depth); +} + +/******************************************************************* +creates a STRHDR structure. +********************************************************************/ +void make_str_hdr(STRHDR *hdr, int max_len, int len, uint32 buffer) +{ + hdr->str_max_len = max_len; + hdr->str_str_len = len; + hdr->buffer = buffer; +} + +/******************************************************************* +reads or writes a STRHDR structure. +********************************************************************/ +void smb_io_strhdr(char *desc, STRHDR *hdr, prs_struct *ps, int depth) +{ + if (hdr == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_strhdr"); + depth++; + + prs_align(ps); + + prs_uint16("str_str_len", ps, depth, &(hdr->str_str_len)); + prs_uint16("str_max_len", ps, depth, &(hdr->str_max_len)); + prs_uint32("buffer ", ps, depth, &(hdr->buffer )); + + /* oops! XXXX maybe issue a warning that this is happening... */ + if (hdr->str_max_len > MAX_STRINGLEN) hdr->str_max_len = MAX_STRINGLEN; + if (hdr->str_str_len > MAX_STRINGLEN) hdr->str_str_len = MAX_STRINGLEN; +} + +/******************************************************************* +creates a UNIHDR structure. +********************************************************************/ +void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint32 buffer) +{ + hdr->uni_max_len = 2 * max_len; + hdr->uni_str_len = 2 * len; + hdr->buffer = buffer; +} + +/******************************************************************* +reads or writes a UNIHDR structure. +********************************************************************/ +void smb_io_unihdr(char *desc, UNIHDR *hdr, prs_struct *ps, int depth) +{ + if (hdr == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_unihdr"); + depth++; + + prs_align(ps); + + prs_uint16("uni_str_len", ps, depth, &(hdr->uni_str_len)); + prs_uint16("uni_max_len", ps, depth, &(hdr->uni_max_len)); + prs_uint32("buffer ", ps, depth, &(hdr->buffer )); + + /* oops! XXXX maybe issue a warning that this is happening... */ + if (hdr->uni_max_len > MAX_UNISTRLEN) hdr->uni_max_len = MAX_UNISTRLEN; + if (hdr->uni_str_len > MAX_UNISTRLEN) hdr->uni_str_len = MAX_UNISTRLEN; +} + +/******************************************************************* +creates a UNIHDR2 structure. +********************************************************************/ +void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) +{ + make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); + hdr->buffer = len > 0 ? 1 : 0; +} + +/******************************************************************* +reads or writes a UNIHDR2 structure. +********************************************************************/ +void smb_io_unihdr2(char *desc, UNIHDR2 *hdr2, prs_struct *ps, int depth) +{ + if (hdr2 == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_unihdr2"); + depth++; + + prs_align(ps); + + smb_io_unihdr("hdr", &(hdr2->unihdr), ps, depth); + prs_uint32("buffer", ps, depth, &(hdr2->buffer)); +} + +/******************************************************************* +creates a UNISTR structure. +********************************************************************/ +void make_unistr(UNISTR *str, char *buf) +{ + /* store the string (null-terminated copy) */ + struni2(str->buffer, buf); +} + +/******************************************************************* +reads or writes a UNISTR structure. +XXXX NOTE: UNISTR structures NEED to be null-terminated. +********************************************************************/ +void smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth) +{ + if (uni == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_unistr"); + depth++; + + prs_align(ps); + prs_unistr("unistr", ps, depth, uni); +} + +/******************************************************************* +creates a UNINOTSTR2 structure. +********************************************************************/ +void make_uninotstr2(UNINOTSTR2 *str, char *buf, int len) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->uni_max_len = (len+1)*2; + str->undoc = 0; + str->uni_buf_len = (len+1)*2; + + /* store the string (null-terminated copy) */ + struni2(str->buffer, buf); +} + +/******************************************************************* +reads or writes a UNINOTSTR2 structure. +XXXX NOTE: UNISTR2 structures need NOT be null-terminated. + the uni_str_len member tells you how long the string is; + the uni_max_len member tells you how large the buffer is. +********************************************************************/ +void smb_io_uninotstr2(char *desc, UNINOTSTR2 *uni2, uint32 buffer, prs_struct *ps, int depth) +{ + if (uni2 == NULL) return; + + if (buffer) + { + prs_debug(ps, depth, desc, "smb_io_uninotstr2"); + depth++; + + prs_align(ps); + + prs_uint32("uni_max_len", ps, depth, &(uni2->uni_max_len)); + prs_uint32("undoc ", ps, depth, &(uni2->undoc )); + prs_uint32("uni_buf_len", ps, depth, &(uni2->uni_buf_len)); + + /* oops! XXXX maybe issue a warning that this is happening... */ + if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN; + if (uni2->uni_buf_len > MAX_UNISTRLEN) uni2->uni_buf_len = MAX_UNISTRLEN; + + /* buffer advanced by indicated length of string + NOT by searching for null-termination */ + prs_uninotstr2(True, "buffer ", ps, depth, uni2); + } + else + { + prs_debug(ps, depth, desc, "smb_io_uninotstr2 - NULL"); + depth++; + bzero(uni2, sizeof(*uni2)); + } +} + +/******************************************************************* +creates a UNISTR2 structure: sets up the buffer, too +********************************************************************/ +void make_buf_unistr2(UNISTR2 *str, uint32 *ptr, char *buf) +{ + if (buf != NULL) + { + *ptr = 1; + make_unistr2(str, buf, strlen(buf)); + } + else + { + *ptr = 0; + make_unistr2(str, "", 0); + } +} + +/******************************************************************* +copies a UNISTR2 structure. +********************************************************************/ +void copy_unistr2(UNISTR2 *str, UNISTR2 *from) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->uni_max_len = from->uni_max_len; + str->undoc = from->undoc; + str->uni_str_len = from->uni_str_len; + + /* copy the string */ + memcpy(str->buffer, from->buffer, sizeof(from->buffer)); +} + +/******************************************************************* +creates a STRING2 structure. +********************************************************************/ +void make_string2(STRING2 *str, char *buf, int len) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->str_max_len = len+1; + str->undoc = 0; + str->str_str_len = len+1; + + /* store the string */ + memcpy(str->buffer, buf, len); +} + +/******************************************************************* +reads or writes a STRING2 structure. +XXXX NOTE: STRING2 structures need NOT be null-terminated. + the str_str_len member tells you how long the string is; + the str_max_len member tells you how large the buffer is. +********************************************************************/ +void smb_io_string2(char *desc, STRING2 *str2, uint32 buffer, prs_struct *ps, int depth) +{ + if (str2 == NULL) return; + + if (buffer) + { + prs_debug(ps, depth, desc, "smb_io_string2"); + depth++; + + prs_align(ps); + + prs_uint32("str_max_len", ps, depth, &(str2->str_max_len)); + prs_uint32("undoc ", ps, depth, &(str2->undoc )); + prs_uint32("str_str_len", ps, depth, &(str2->str_str_len)); + + /* oops! XXXX maybe issue a warning that this is happening... */ + if (str2->str_max_len > MAX_STRINGLEN) str2->str_max_len = MAX_STRINGLEN; + if (str2->str_str_len > MAX_STRINGLEN) str2->str_str_len = MAX_STRINGLEN; + + /* buffer advanced by indicated length of string + NOT by searching for null-termination */ + prs_string2(True, "buffer ", ps, depth, str2); + } + else + { + prs_debug(ps, depth, desc, "smb_io_string2 - NULL"); + depth++; + bzero(str2, sizeof(*str2)); + } +} + +/******************************************************************* +creates a UNISTR2 structure. +********************************************************************/ +void make_unistr2(UNISTR2 *str, char *buf, int len) +{ + /* set up string lengths. add one if string is not null-terminated */ + str->uni_max_len = len+1; + str->undoc = 0; + str->uni_str_len = len+1; + + /* store the string (null-terminated 8 bit chars into 16 bit chars) */ + struni2(str->buffer, buf); +} + +/******************************************************************* +reads or writes a UNISTR2 structure. +XXXX NOTE: UNISTR2 structures need NOT be null-terminated. + the uni_str_len member tells you how long the string is; + the uni_max_len member tells you how large the buffer is. +********************************************************************/ +void smb_io_unistr2(char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct *ps, int depth) +{ + if (uni2 == NULL) return; + + if (buffer) + { + prs_debug(ps, depth, desc, "smb_io_unistr2"); + depth++; + + prs_align(ps); + + prs_uint32("uni_max_len", ps, depth, &(uni2->uni_max_len)); + prs_uint32("undoc ", ps, depth, &(uni2->undoc )); + prs_uint32("uni_str_len", ps, depth, &(uni2->uni_str_len)); + + /* oops! XXXX maybe issue a warning that this is happening... */ + if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN; + if (uni2->uni_str_len > MAX_UNISTRLEN) uni2->uni_str_len = MAX_UNISTRLEN; + + /* buffer advanced by indicated length of string + NOT by searching for null-termination */ + prs_unistr2(True, "buffer ", ps, depth, uni2); + } + else + { + prs_debug(ps, depth, desc, "smb_io_unistr2 - NULL"); + depth++; + bzero(uni2, sizeof(*uni2)); + } +} + +/******************************************************************* +creates a DOM_RID2 structure. +********************************************************************/ +void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) +{ + rid2->type = 0x5; + rid2->undoc = 0x5; + rid2->rid = rid; + rid2->rid_idx = 0; +} + +/******************************************************************* +reads or writes a DOM_RID2 structure. +********************************************************************/ +void smb_io_dom_rid2(char *desc, DOM_RID2 *rid2, prs_struct *ps, int depth) +{ + if (rid2 == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_rid2"); + depth++; + + prs_align(ps); + + /* should be value 5, so enforce it */ + rid2->type = 5; + + /* should be value 5, so enforce it */ + rid2->undoc = 5; + + prs_uint32("type ", ps, depth, &(rid2->type)); + prs_uint32("undoc ", ps, depth, &(rid2->undoc )); + prs_uint32("rid ", ps, depth, &(rid2->rid )); + prs_uint32("rid_idx", ps, depth, &(rid2->rid_idx )); +} + +/******************************************************************* +creates a DOM_RID3 structure. +********************************************************************/ +void make_dom_rid3(DOM_RID3 *rid3, uint32 rid) +{ + rid3->rid = rid; + rid3->type1 = 0x1; + rid3->ptr_type = 0x1; /* non-zero, basically. */ + rid3->type2 = 0x1; +} + +/******************************************************************* +reads or writes a DOM_RID3 structure. +********************************************************************/ +void smb_io_dom_rid3(char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth) +{ + if (rid3 == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_rid3"); + depth++; + + prs_align(ps); + + prs_uint32("rid ", ps, depth, &(rid3->rid )); + prs_uint32("type1 ", ps, depth, &(rid3->type1 )); + prs_uint32("ptr_type", ps, depth, &(rid3->ptr_type)); + prs_uint32("type2 ", ps, depth, &(rid3->type2 )); +} + +/******************************************************************* +creates a DOM_RID4 structure. +********************************************************************/ +void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid) +{ + rid4->unknown = unknown; + rid4->attr = attr; + rid4->rid = rid; +} + +/******************************************************************* +reads or writes a DOM_RID4 structure. +********************************************************************/ +void smb_io_dom_rid4(char *desc, DOM_RID4 *rid4, prs_struct *ps, int depth) +{ + if (rid4 == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_rid4. XXXX !check size of unknown! XXXX"); + depth++; + + prs_align(ps); + + prs_uint32("unknown", ps, depth, &(rid4->unknown)); + prs_uint16("attr ", ps, depth, &(rid4->attr )); + prs_uint32("rid ", ps, depth, &(rid4->rid )); +} + +/******************************************************************* +makes a DOM_CLNT_SRV structure. +********************************************************************/ +void make_clnt_srv(DOM_CLNT_SRV *log, char *logon_srv, char *comp_name) +{ + if (log == NULL) return; + + DEBUG(5,("make_clnt_srv: %d\n", __LINE__)); + + if (logon_srv != NULL) + { + log->undoc_buffer = 1; + make_unistr2(&(log->uni_logon_srv), logon_srv, strlen(logon_srv)); + } + else + { + log->undoc_buffer = 0; + } + + if (comp_name != NULL) + { + log->undoc_buffer2 = 1; + make_unistr2(&(log->uni_comp_name), comp_name, strlen(comp_name)); + } + else + { + log->undoc_buffer2 = 0; + } +} + +/******************************************************************* +reads or writes a DOM_CLNT_SRV structure. +********************************************************************/ +void smb_io_clnt_srv(char *desc, DOM_CLNT_SRV *log, prs_struct *ps, int depth) +{ + if (log == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_clnt_srv"); + depth++; + + prs_align(ps); + + prs_uint32("undoc_buffer ", ps, depth, &(log->undoc_buffer )); + if (log->undoc_buffer != 0) + { + smb_io_unistr2("unistr2", &(log->uni_logon_srv), log->undoc_buffer, ps, depth); + } + + prs_align(ps); + + prs_uint32("undoc_buffer2", ps, depth, &(log->undoc_buffer2)); + if (log->undoc_buffer2 != 0) + { + smb_io_unistr2("unistr2", &(log->uni_comp_name), log->undoc_buffer2, ps, depth); + } +} + +/******************************************************************* +makes a DOM_LOG_INFO structure. +********************************************************************/ +void make_log_info(DOM_LOG_INFO *log, char *logon_srv, char *acct_name, + uint16 sec_chan, char *comp_name) +{ + if (log == NULL) return; + + DEBUG(5,("make_log_info %d\n", __LINE__)); + + log->undoc_buffer = 1; + + make_unistr2(&(log->uni_logon_srv), logon_srv, strlen(logon_srv)); + make_unistr2(&(log->uni_acct_name), acct_name, strlen(acct_name)); + + log->sec_chan = sec_chan; + + make_unistr2(&(log->uni_comp_name), comp_name, strlen(comp_name)); +} + +/******************************************************************* +reads or writes a DOM_LOG_INFO structure. +********************************************************************/ +void smb_io_log_info(char *desc, DOM_LOG_INFO *log, prs_struct *ps, int depth) +{ + if (log == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_log_info"); + depth++; + + prs_align(ps); + + prs_uint32("undoc_buffer", ps, depth, &(log->undoc_buffer)); + + smb_io_unistr2("unistr2", &(log->uni_logon_srv), True, ps, depth); + smb_io_unistr2("unistr2", &(log->uni_acct_name), True, ps, depth); + + prs_uint16("sec_chan", ps, depth, &(log->sec_chan)); + + smb_io_unistr2("unistr2", &(log->uni_comp_name), True, ps, depth); +} + +/******************************************************************* +reads or writes a DOM_CHAL structure. +********************************************************************/ +void smb_io_chal(char *desc, DOM_CHAL *chal, prs_struct *ps, int depth) +{ + if (chal == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_chal"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "data", ps, depth, chal->data, 8); +} + +/******************************************************************* +reads or writes a DOM_CRED structure. +********************************************************************/ +void smb_io_cred(char *desc, DOM_CRED *cred, prs_struct *ps, int depth) +{ + if (cred == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_cred"); + depth++; + + prs_align(ps); + + smb_io_chal ("", &(cred->challenge), ps, depth); + smb_io_utime("", &(cred->timestamp), ps, depth); +} + +/******************************************************************* +makes a DOM_CLNT_INFO2 structure. +********************************************************************/ +void make_clnt_info2(DOM_CLNT_INFO2 *clnt, + char *logon_srv, char *comp_name, + DOM_CRED *clnt_cred) +{ + if (clnt == NULL) return; + + DEBUG(5,("make_clnt_info: %d\n", __LINE__)); + + make_clnt_srv(&(clnt->login), logon_srv, comp_name); + + if (clnt_cred != NULL) + { + clnt->ptr_cred = 1; + memcpy(&(clnt->cred), clnt_cred, sizeof(clnt->cred)); + } + else + { + clnt->ptr_cred = 0; + } +} + +/******************************************************************* +reads or writes a DOM_CLNT_INFO2 structure. +********************************************************************/ +void smb_io_clnt_info2(char *desc, DOM_CLNT_INFO2 *clnt, prs_struct *ps, int depth) +{ + if (clnt == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_clnt_info2"); + depth++; + + prs_align(ps); + + smb_io_clnt_srv("", &(clnt->login), ps, depth); + + prs_align(ps); + + prs_uint32("ptr_cred", ps, depth, &(clnt->ptr_cred)); + smb_io_cred ("", &(clnt->cred ), ps, depth); +} + +/******************************************************************* +makes a DOM_CLNT_INFO structure. +********************************************************************/ +void make_clnt_info(DOM_CLNT_INFO *clnt, + char *logon_srv, char *acct_name, + uint16 sec_chan, char *comp_name, + DOM_CRED *cred) +{ + if (clnt == NULL || cred == NULL) return; + + DEBUG(5,("make_clnt_info\n")); + + make_log_info(&(clnt->login), logon_srv, acct_name, sec_chan, comp_name); + memcpy(&(clnt->cred), cred, sizeof(clnt->cred)); +} + +/******************************************************************* +reads or writes a DOM_CLNT_INFO structure. +********************************************************************/ +void smb_io_clnt_info(char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, int depth) +{ + if (clnt == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_clnt_info"); + depth++; + + prs_align(ps); + + smb_io_log_info("", &(clnt->login), ps, depth); + smb_io_cred ("", &(clnt->cred ), ps, depth); +} + +/******************************************************************* +makes a DOM_LOGON_ID structure. +********************************************************************/ +void make_logon_id(DOM_LOGON_ID *log, uint32 log_id_low, uint32 log_id_high) +{ + if (log == NULL) return; + + DEBUG(5,("make_logon_id: %d\n", __LINE__)); + + log->low = log_id_low; + log->high = log_id_high; +} + +/******************************************************************* +reads or writes a DOM_LOGON_ID structure. +********************************************************************/ +void smb_io_logon_id(char *desc, DOM_LOGON_ID *log, prs_struct *ps, int depth) +{ + if (log == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_logon_id"); + depth++; + + prs_align(ps); + + prs_uint32("low ", ps, depth, &(log->low )); + prs_uint32("high", ps, depth, &(log->high)); +} + +/******************************************************************* +makes an ARC4_OWF structure. +********************************************************************/ +void make_arc4_owf(ARC4_OWF *hash, uint8 data[16]) +{ + if (hash == NULL) return; + + DEBUG(5,("make_arc4_owf: %d\n", __LINE__)); + + if (data != NULL) + { + memcpy(hash->data, data, sizeof(hash->data)); + } + else + { + bzero(hash->data, sizeof(hash->data)); + } +} + +/******************************************************************* +reads or writes an ARC4_OWF structure. +********************************************************************/ +void smb_io_arc4_owf(char *desc, ARC4_OWF *hash, prs_struct *ps, int depth) +{ + if (hash == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_arc4_owf"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "data", ps, depth, hash->data, 16); +} + +/******************************************************************* +reads or writes a DOM_GID structure. +********************************************************************/ +void smb_io_gid(char *desc, DOM_GID *gid, prs_struct *ps, int depth) +{ + if (gid == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_gid"); + depth++; + + prs_align(ps); + + prs_uint32("g_rid", ps, depth, &(gid->g_rid)); + prs_uint32("attr ", ps, depth, &(gid->attr )); +} + +/******************************************************************* +reads or writes an POLICY_HND structure. +********************************************************************/ +void smb_io_pol_hnd(char *desc, POLICY_HND *pol, prs_struct *ps, int depth) +{ + if (pol == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_pol_hnd"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "data", ps, depth, pol->data, POL_HND_SIZE); +} + +/******************************************************************* +reads or writes a dom query structure. +********************************************************************/ +void smb_io_dom_query_3(char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth) +{ + smb_io_dom_query("", d_q, ps, depth); +} + +/******************************************************************* +reads or writes a dom query structure. +********************************************************************/ +void smb_io_dom_query_5(char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth) +{ + smb_io_dom_query("", d_q, ps, depth); +} + +/******************************************************************* +reads or writes a dom query structure. +********************************************************************/ +void smb_io_dom_query(char *desc, DOM_QUERY *d_q, prs_struct *ps, int depth) +{ + if (d_q == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_query"); + depth++; + + prs_align(ps); + + prs_uint16("uni_dom_max_len", ps, depth, &(d_q->uni_dom_max_len)); /* domain name string length * 2 */ + prs_uint16("uni_dom_str_len", ps, depth, &(d_q->uni_dom_str_len)); /* domain name string length * 2 */ + + prs_uint32("buffer_dom_name", ps, depth, &(d_q->buffer_dom_name)); /* undocumented domain name string buffer pointer */ + prs_uint32("buffer_dom_sid ", ps, depth, &(d_q->buffer_dom_sid )); /* undocumented domain SID string buffer pointer */ + + smb_io_unistr2("unistr2", &(d_q->uni_domain_name), d_q->buffer_dom_name, ps, depth); /* domain name (unicode string) */ + + if (d_q->buffer_dom_sid != 0) + { + smb_io_dom_sid2("", &(d_q->dom_sid), ps, depth); /* domain SID */ + } + else + { + bzero(&(d_q->dom_sid), sizeof(d_q->dom_sid)); + } +} + +/******************************************************************* +reads or writes a DOM_NAME structure. +********************************************************************/ +void smb_io_dom_name(char *desc, DOM_NAME *name, prs_struct *ps, int depth) +{ + if (name == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_dom_name"); + depth++; + + prs_align(ps); + + prs_uint32("uni_str_len", ps, depth, &(name->uni_str_len)); + + /* don't know if len is specified by uni_str_len member... */ + /* assume unicode string is unicode-null-terminated, instead */ + + smb_io_unistr("", &(name->str), ps, depth); +} + + diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c new file mode 100644 index 0000000000..69d6ac08ed --- /dev/null +++ b/source3/rpc_parse/parse_net.c @@ -0,0 +1,1147 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_neg_flags(char *desc, NEG_FLAGS *neg, prs_struct *ps, int depth) +{ + if (neg == NULL) return; + + prs_debug(ps, depth, desc, "net_io_neg_flags"); + depth++; + + prs_align(ps); + + prs_uint32("neg_flags", ps, depth, &(neg->neg_flags)); +} + +/******************************************************************* +creates a NETLOGON_INFO_3 structure. +********************************************************************/ +void make_netinfo_3(NETLOGON_INFO_3 *info, uint32 flags, uint32 logon_attempts) +{ + info->flags = flags; + info->logon_attempts = logon_attempts; + info->reserved_1 = 0x0; + info->reserved_2 = 0x0; + info->reserved_3 = 0x0; + info->reserved_4 = 0x0; + info->reserved_5 = 0x0; +} + +/******************************************************************* +reads or writes a NETLOGON_INFO_3 structure. +********************************************************************/ +void net_io_netinfo_3(char *desc, NETLOGON_INFO_3 *info, prs_struct *ps, int depth) +{ + if (info == NULL) return; + + prs_debug(ps, depth, desc, "net_io_netinfo_3"); + depth++; + + prs_align(ps); + + prs_uint32("flags ", ps, depth, &(info->flags )); + prs_uint32("logon_attempts", ps, depth, &(info->logon_attempts)); + prs_uint32("reserved_1 ", ps, depth, &(info->reserved_1 )); + prs_uint32("reserved_2 ", ps, depth, &(info->reserved_2 )); + prs_uint32("reserved_3 ", ps, depth, &(info->reserved_3 )); + prs_uint32("reserved_4 ", ps, depth, &(info->reserved_4 )); + prs_uint32("reserved_5 ", ps, depth, &(info->reserved_5 )); +} + + +/******************************************************************* +creates a NETLOGON_INFO_1 structure. +********************************************************************/ +void make_netinfo_1(NETLOGON_INFO_1 *info, uint32 flags, uint32 pdc_status) +{ + info->flags = flags; + info->pdc_status = pdc_status; +} + +/******************************************************************* +reads or writes a NETLOGON_INFO_1 structure. +********************************************************************/ +void net_io_netinfo_1(char *desc, NETLOGON_INFO_1 *info, prs_struct *ps, int depth) +{ + if (info == NULL) return; + + prs_debug(ps, depth, desc, "net_io_netinfo_1"); + depth++; + + prs_align(ps); + + prs_uint32("flags ", ps, depth, &(info->flags )); + prs_uint32("pdc_status", ps, depth, &(info->pdc_status)); +} + +/******************************************************************* +creates a NETLOGON_INFO_2 structure. +********************************************************************/ +void make_netinfo_2(NETLOGON_INFO_2 *info, uint32 flags, uint32 pdc_status, + uint32 tc_status, char *trusted_dc_name) +{ + int len_dc_name = strlen(trusted_dc_name); + info->flags = flags; + info->pdc_status = pdc_status; + info->ptr_trusted_dc_name = 1; + info->tc_status = tc_status; + + if (trusted_dc_name != NULL) + { + make_unistr2(&(info->uni_trusted_dc_name), trusted_dc_name, len_dc_name); + } + else + { + make_unistr2(&(info->uni_trusted_dc_name), "", 1); + } +} + +/******************************************************************* +reads or writes a NETLOGON_INFO_2 structure. +********************************************************************/ +void net_io_netinfo_2(char *desc, NETLOGON_INFO_2 *info, prs_struct *ps, int depth) +{ + if (info == NULL) return; + + prs_debug(ps, depth, desc, "net_io_netinfo_2"); + depth++; + + prs_align(ps); + + prs_uint32("flags ", ps, depth, &(info->flags )); + prs_uint32("pdc_status ", ps, depth, &(info->pdc_status )); + prs_uint32("ptr_trusted_dc_name", ps, depth, &(info->ptr_trusted_dc_name)); + prs_uint32("tc_status ", ps, depth, &(info->tc_status )); + + if (info->ptr_trusted_dc_name != 0) + { + smb_io_unistr2("unistr2", &(info->uni_trusted_dc_name), info->ptr_trusted_dc_name, ps, depth); + } + + prs_align(ps); +} + +/******************************************************************* +makes an NET_Q_LOGON_CTRL2 structure. +********************************************************************/ +void make_q_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, char *server_name, + uint32 function_code) +{ + if (q_l == NULL) return; + + DEBUG(5,("make_q_logon_ctrl2\n")); + + q_l->ptr = 1; /* undocumented pointer */ + make_unistr2 (&(q_l->uni_server_name), server_name, strlen(server_name)); + + q_l->function_code = function_code; /* should only be 0x1 */ + q_l->query_level = function_code; /* should only be 0x1 */ + q_l->switch_value = function_code; /* should only be 0x1 */ +} + +/******************************************************************* +reads or writes an NET_Q_LOGON_CTRL2 structure. +********************************************************************/ +void net_io_q_logon_ctrl2(char *desc, NET_Q_LOGON_CTRL2 *q_l, prs_struct *ps, int depth) +{ + if (q_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_logon_ctrl2"); + depth++; + + prs_align(ps); + + prs_uint32("ptr ", ps, depth, &(q_l->ptr )); + + smb_io_unistr2 ("", &(q_l->uni_server_name), q_l->ptr, ps, depth); + + prs_align(ps); + + prs_uint32("function_code", ps, depth, &(q_l->function_code)); + prs_uint32("query_level ", ps, depth, &(q_l->query_level )); + prs_uint32("switch_value ", ps, depth, &(q_l->switch_value )); +} + +/******************************************************************* +makes an NET_R_LOGON_CTRL2 structure. +********************************************************************/ +void make_r_logon_ctrl2(NET_R_LOGON_CTRL2 *r_l, uint32 query_level, + uint32 flags, uint32 pdc_status, uint32 logon_attempts, + uint32 tc_status, char *trusted_domain_name) +{ + if (r_l == NULL) return; + + DEBUG(5,("make_r_logon_ctrl2\n")); + + r_l->switch_value = query_level; /* should only be 0x1 */ + + switch (query_level) + { + case 1: + { + r_l->ptr = 1; /* undocumented pointer */ + make_netinfo_1(&(r_l->logon.info1), flags, pdc_status); + r_l->status = 0; + + break; + } + case 2: + { + r_l->ptr = 1; /* undocumented pointer */ + make_netinfo_2(&(r_l->logon.info2), flags, pdc_status, + tc_status, trusted_domain_name); + r_l->status = 0; + + break; + } + case 3: + { + r_l->ptr = 1; /* undocumented pointer */ + make_netinfo_3(&(r_l->logon.info3), flags, logon_attempts); + r_l->status = 0; + + break; + } + default: + { + DEBUG(2,("make_r_logon_ctrl2: unsupported switch value %d\n", + r_l->switch_value)); + r_l->ptr = 0; /* undocumented pointer */ + + /* take a guess at an error code... */ + r_l->status = NT_STATUS_INVALID_INFO_CLASS; + + break; + } + } +} + +/******************************************************************* +reads or writes an NET_R_LOGON_CTRL2 structure. +********************************************************************/ +void net_io_r_logon_ctrl2(char *desc, NET_R_LOGON_CTRL2 *r_l, prs_struct *ps, int depth) +{ + if (r_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_logon_ctrl2"); + depth++; + + prs_uint32("switch_value ", ps, depth, &(r_l->switch_value )); + prs_uint32("ptr ", ps, depth, &(r_l->ptr )); + + if (r_l->ptr != 0) + { + switch (r_l->switch_value) + { + case 1: + { + net_io_netinfo_1("", &(r_l->logon.info1), ps, depth); + break; + } + case 2: + { + net_io_netinfo_2("", &(r_l->logon.info2), ps, depth); + break; + } + case 3: + { + net_io_netinfo_3("", &(r_l->logon.info3), ps, depth); + break; + } + default: + { + DEBUG(2,("net_io_r_logon_ctrl2: unsupported switch value %d\n", + r_l->switch_value)); + break; + } + } + } + + prs_uint32("status ", ps, depth, &(r_l->status )); +} + +/******************************************************************* +makes an NET_R_TRUST_DOM_LIST structure. +********************************************************************/ +void make_r_trust_dom(NET_R_TRUST_DOM_LIST *r_t, + uint32 num_doms, char *dom_name) +{ + int i = 0; + + if (r_t == NULL) return; + + DEBUG(5,("make_r_trust_dom\n")); + + for (i = 0; i < MAX_TRUST_DOMS; i++) + { + r_t->uni_trust_dom_name[i].uni_str_len = 0; + r_t->uni_trust_dom_name[i].uni_max_len = 0; + } + if (num_doms > MAX_TRUST_DOMS) num_doms = MAX_TRUST_DOMS; + + for (i = 0; i < num_doms; i++) + { + fstring domain_name; + fstrcpy(domain_name, dom_name); + strupper(domain_name); + make_unistr2(&(r_t->uni_trust_dom_name[i]), domain_name, strlen(domain_name)); + /* the use of UNISTR2 here is non-standard. */ + r_t->uni_trust_dom_name[i].undoc = 0x1; + } + + r_t->status = 0; +} + +/******************************************************************* +reads or writes an NET_R_TRUST_DOM_LIST structure. +********************************************************************/ +void net_io_r_trust_dom(char *desc, NET_R_TRUST_DOM_LIST *r_t, prs_struct *ps, int depth) +{ + int i; + if (r_t == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_trust_dom"); + depth++; + + for (i = 0; i < MAX_TRUST_DOMS; i++) + { + if (r_t->uni_trust_dom_name[i].uni_str_len == 0) break; + smb_io_unistr2("", &(r_t->uni_trust_dom_name[i]), True, ps, depth); + } + + prs_uint32("status", ps, depth, &(r_t->status)); +} + +/******************************************************************* +makes an NET_Q_TRUST_DOM_LIST structure. +********************************************************************/ +void make_q_trust_dom(NET_Q_TRUST_DOM_LIST *q_l, char *server_name, + uint32 function_code) +{ + if (q_l == NULL) return; + + DEBUG(5,("make_q_trust_dom\n")); + + make_unistr2 (&(q_l->uni_server_name), server_name, strlen(server_name)); + + q_l->function_code = function_code; /* should only be 0x31 */ +} + +/******************************************************************* +reads or writes an NET_Q_TRUST_DOM_LIST structure. +********************************************************************/ +void net_io_q_trust_dom(char *desc, NET_Q_TRUST_DOM_LIST *q_l, prs_struct *ps, int depth) +{ + if (q_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_trust_dom"); + depth++; + + prs_uint32("ptr ", ps, depth, &(q_l->ptr )); + smb_io_unistr2 ("", &(q_l->uni_server_name), q_l->ptr, ps, depth); + + prs_align(ps); + + prs_uint32("function_code", ps, depth, &(q_l->function_code)); +} + +/******************************************************************* +makes an NET_Q_REQ_CHAL structure. +********************************************************************/ +void make_q_req_chal(NET_Q_REQ_CHAL *q_c, + char *logon_srv, char *logon_clnt, + DOM_CHAL *clnt_chal) +{ + if (q_c == NULL) return; + + DEBUG(5,("make_q_req_chal: %d\n", __LINE__)); + + q_c->undoc_buffer = 1; /* don't know what this buffer is */ + + make_unistr2(&(q_c->uni_logon_srv ), logon_srv , strlen(logon_srv )); + make_unistr2(&(q_c->uni_logon_clnt), logon_clnt, strlen(logon_clnt)); + + memcpy(q_c->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + + DEBUG(5,("make_q_req_chal: %d\n", __LINE__)); +} + +/******************************************************************* +reads or writes an NET_Q_REQ_CHAL structure. +********************************************************************/ +void net_io_q_req_chal(char *desc, NET_Q_REQ_CHAL *q_c, prs_struct *ps, int depth) +{ + int old_align; + if (q_c == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_req_chal"); + depth++; + + prs_align(ps); + + prs_uint32("undoc_buffer", ps, depth, &(q_c->undoc_buffer)); + + smb_io_unistr2("", &(q_c->uni_logon_srv), True, ps, depth); /* logon server unicode string */ + smb_io_unistr2("", &(q_c->uni_logon_clnt), True, ps, depth); /* logon client unicode string */ + + old_align = ps->align; + ps->align = 0; + /* client challenge is _not_ aligned after the unicode strings */ + smb_io_chal("", &(q_c->clnt_chal), ps, depth); /* client challenge */ + ps->align = old_align; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_r_req_chal(char *desc, NET_R_REQ_CHAL *r_c, prs_struct *ps, int depth) +{ + if (r_c == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_req_chal"); + depth++; + + prs_align(ps); + + smb_io_chal("", &(r_c->srv_chal), ps, depth); /* server challenge */ + + prs_uint32("status", ps, depth, &(r_c->status)); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_q_auth_2(NET_Q_AUTH_2 *q_a, + char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, + DOM_CHAL *clnt_chal, uint32 clnt_flgs) +{ + if (q_a == NULL) return; + + DEBUG(5,("make_q_auth_2: %d\n", __LINE__)); + + make_log_info(&(q_a->clnt_id), logon_srv, acct_name, sec_chan, comp_name); + memcpy(q_a->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); + q_a->clnt_flgs.neg_flags = clnt_flgs; + + DEBUG(5,("make_q_auth_2: %d\n", __LINE__)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_q_auth_2(char *desc, NET_Q_AUTH_2 *q_a, prs_struct *ps, int depth) +{ + int old_align; + if (q_a == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_auth_2"); + depth++; + + prs_align(ps); + + smb_io_log_info ("", &(q_a->clnt_id), ps, depth); /* client identification info */ + /* client challenge is _not_ aligned */ + old_align = ps->align; + ps->align = 0; + smb_io_chal ("", &(q_a->clnt_chal), ps, depth); /* client-calculated credentials */ + ps->align = old_align; + net_io_neg_flags("", &(q_a->clnt_flgs), ps, depth); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_r_auth_2(char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int depth) +{ + if (r_a == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_auth_2"); + depth++; + + prs_align(ps); + + smb_io_chal ("", &(r_a->srv_chal), ps, depth); /* server challenge */ + net_io_neg_flags("", &(r_a->srv_flgs), ps, depth); + + prs_uint32("status", ps, depth, &(r_a->status)); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_q_srv_pwset(NET_Q_SRV_PWSET *q_s, char sess_key[16], + char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name, + DOM_CRED *cred, char nt_cypher[16]) +{ + if (q_s == NULL || cred == NULL) return; + + DEBUG(5,("make_q_srv_pwset\n")); + + make_clnt_info(&(q_s->clnt_id), logon_srv, acct_name, sec_chan, comp_name, cred); + + memcpy(q_s->pwd, nt_cypher, sizeof(q_s->pwd)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_q_srv_pwset(char *desc, NET_Q_SRV_PWSET *q_s, prs_struct *ps, int depth) +{ + if (q_s == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_srv_pwset"); + depth++; + + prs_align(ps); + + smb_io_clnt_info("", &(q_s->clnt_id), ps, depth); /* client identification/authentication info */ + prs_uint8s (False, "pwd", ps, depth, q_s->pwd, 16); /* new password - undocumented */ +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_r_srv_pwset(char *desc, NET_R_SRV_PWSET *r_s, prs_struct *ps, int depth) +{ + if (r_s == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_srv_pwset"); + depth++; + + prs_align(ps); + + smb_io_cred("", &(r_s->srv_cred), ps, depth); /* server challenge */ + + prs_uint32("status", ps, depth, &(r_s->status)); +} + + +/************************************************************************* + make DOM_SID2 array from a string containing multiple sids + *************************************************************************/ +static int make_dom_sid2s(char *sids_str, DOM_SID2 *sids, int max_sids) +{ + char *ptr; + pstring s2; + int count; + + DEBUG(4,("make_dom_sid2s: %s\n", sids_str)); + + if (sids_str == NULL || *sids_str == 0) return 0; + + for (count = 0, ptr = sids_str; next_token(&ptr, s2, NULL) && count < max_sids; count++) + { + make_dom_sid2(&sids[count], s2); + } + + return count; +} + +/******************************************************************* +makes a NET_ID_INFO_1 structure. +********************************************************************/ +void make_id_info1(NET_ID_INFO_1 *id, char *domain_name, + uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high, + char *user_name, char *wksta_name, + char sess_key[16], + unsigned char lm_cypher[16], unsigned char nt_cypher[16]) +{ + int len_domain_name = strlen(domain_name); + int len_user_name = strlen(user_name ); + int len_wksta_name = strlen(wksta_name ); + + unsigned char arc4_lm_owf[16]; + unsigned char arc4_nt_owf[16]; + + if (id == NULL) return; + + DEBUG(5,("make_id_info1: %d\n", __LINE__)); + + id->ptr_id_info1 = 1; + + make_uni_hdr(&(id->hdr_domain_name), len_domain_name, len_domain_name, 4); + + id->param_ctrl = param_ctrl; + make_logon_id(&(id->logon_id), log_id_low, log_id_high); + + make_uni_hdr(&(id->hdr_user_name ), len_user_name , len_user_name , 4); + make_uni_hdr(&(id->hdr_wksta_name ), len_wksta_name , len_wksta_name , 4); + +#ifdef USE_ARCFOUR + + if (lm_cypher && nt_cypher) + { + void arcfour(uint8 key[16], uint8 out[16], uint8 in[16]); + unsigned char arc4_key[16]; +#ifdef DEBUG_PASSWORD + DEBUG(100,("lm cypher:")); + dump_data(100, lm_cypher, 16); + + DEBUG(100,("nt cypher:")); + dump_data(100, nt_cypher, 16); +#endif + + memset(arc4_key, 0, 16); + memcpy(arc4_key, sess_key, 16); + + arcfour(arc4_key, arc4_lm_owf, lm_cypher); + arcfour(arc4_key, arc4_nt_owf, nt_cypher); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("arcfour encrypt of lm owf password:")); + dump_data(100, arc4_lm_owf, 16); + + DEBUG(100,("arcfour encrypt of nt owf password:")); + dump_data(100, arc4_nt_owf, 16); +#endif + /* set up pointers to cypher blocks */ + lm_cypher = arc4_lm_owf; + nt_cypher = arc4_nt_owf; + } + +#else + + if (lm_cypher) + { + /* oops. can only send what-ever-it-is direct */ + memcpy(arc4_lm_owf, lm_cypher, 16); + lm_cypher = arc4_lm_owf; + } + if (nt_cypher) + { + /* oops. can only send what-ever-it-is direct */ + memcpy(arc4_nt_owf, nt_cypher, 16); + nt_cypher = arc4_nt_owf; + } + +#endif + + make_arc4_owf(&(id->arc4_lm_owf), lm_cypher); + make_arc4_owf(&(id->arc4_nt_owf), nt_cypher); + + make_unistr2(&(id->uni_domain_name), domain_name, len_domain_name); + make_unistr2(&(id->uni_user_name ), user_name , len_user_name ); + make_unistr2(&(id->uni_wksta_name ), wksta_name , len_wksta_name ); +} + +/******************************************************************* +reads or writes an NET_ID_INFO_1 structure. +********************************************************************/ +void net_io_id_info1(char *desc, NET_ID_INFO_1 *id, prs_struct *ps, int depth) +{ + if (id == NULL) return; + + prs_debug(ps, depth, desc, "net_io_id_info1"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_id_info1", ps, depth, &(id->ptr_id_info1)); + + if (id->ptr_id_info1 != 0) + { + smb_io_unihdr("unihdr", &(id->hdr_domain_name), ps, depth); + + prs_uint32("param_ctrl", ps, depth, &(id->param_ctrl)); + smb_io_logon_id("", &(id->logon_id), ps, depth); + + smb_io_unihdr("unihdr", &(id->hdr_user_name ), ps, depth); + smb_io_unihdr("unihdr", &(id->hdr_wksta_name ), ps, depth); + + smb_io_arc4_owf("", &(id->arc4_lm_owf), ps, depth); + smb_io_arc4_owf("", &(id->arc4_nt_owf), ps, depth); + + smb_io_unistr2("unistr2", &(id->uni_domain_name), id->hdr_domain_name.buffer, ps, depth); + smb_io_unistr2("unistr2", &(id->uni_user_name ), id->hdr_user_name.buffer, ps, depth); + smb_io_unistr2("unistr2", &(id->uni_wksta_name ), id->hdr_wksta_name.buffer, ps, depth); + } +} + +/******************************************************************* +makes a NET_ID_INFO_2 structure. +********************************************************************/ +void make_id_info2(NET_ID_INFO_2 *id, char *domain_name, + uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high, + char *user_name, char *wksta_name, + unsigned char lm_challenge[8], + unsigned char lm_chal_resp[24], + unsigned char nt_chal_resp[24]) +{ + int len_domain_name = strlen(domain_name); + int len_user_name = strlen(user_name ); + int len_wksta_name = strlen(wksta_name ); + + unsigned char arc4_lm_owf[24]; + unsigned char arc4_nt_owf[24]; + + if (id == NULL) return; + + DEBUG(5,("make_id_info2: %d\n", __LINE__)); + + id->ptr_id_info2 = 1; + + make_uni_hdr(&(id->hdr_domain_name), len_domain_name, len_domain_name, 4); + + id->param_ctrl = param_ctrl; + make_logon_id(&(id->logon_id), log_id_low, log_id_high); + + make_uni_hdr(&(id->hdr_user_name ), len_user_name , len_user_name , 4); + make_uni_hdr(&(id->hdr_wksta_name ), len_wksta_name , len_wksta_name , 4); + + if (nt_chal_resp) + { + /* oops. can only send what-ever-it-is direct */ + memcpy(arc4_nt_owf, nt_chal_resp, 24); + nt_chal_resp = arc4_nt_owf; + } + if (lm_chal_resp) + { + /* oops. can only send what-ever-it-is direct */ + memcpy(arc4_lm_owf, lm_chal_resp, 24); + lm_chal_resp = arc4_lm_owf; + } + + memcpy(&(id->lm_chal), lm_challenge, sizeof(id->lm_chal)); + make_str_hdr(&(id->hdr_nt_chal_resp), 24, 24, nt_chal_resp != NULL ? 1 : 0); + make_str_hdr(&(id->hdr_lm_chal_resp), 24, 24, lm_chal_resp != NULL ? 1 : 0); + + make_unistr2(&(id->uni_domain_name), domain_name, len_domain_name); + make_unistr2(&(id->uni_user_name ), user_name , len_user_name ); + make_unistr2(&(id->uni_wksta_name ), wksta_name , len_wksta_name ); + + make_string2(&(id->nt_chal_resp ), nt_chal_resp , nt_chal_resp != NULL ? 24 : 0); + make_string2(&(id->lm_chal_resp ), lm_chal_resp , lm_chal_resp != NULL ? 24 : 0); +} + +/******************************************************************* +reads or writes an NET_ID_INFO_1 structure. +********************************************************************/ +void net_io_id_info2(char *desc, NET_ID_INFO_2 *id, prs_struct *ps, int depth) +{ + if (id == NULL) return; + + prs_debug(ps, depth, desc, "net_io_id_info2"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_id_info2", ps, depth, &(id->ptr_id_info2)); + + if (id->ptr_id_info2 != 0) + { + smb_io_unihdr("unihdr", &(id->hdr_domain_name), ps, depth); + + prs_uint32("param_ctrl", ps, depth, &(id->param_ctrl)); + smb_io_logon_id("", &(id->logon_id), ps, depth); + + smb_io_unihdr("unihdr", &(id->hdr_user_name ), ps, depth); + smb_io_unihdr("unihdr", &(id->hdr_wksta_name ), ps, depth); + + prs_uint8s (False, "lm_chal", ps, depth, id->lm_chal, 8); /* lm 8 byte challenge */ + + smb_io_strhdr("hdr_nt_chal_resp", &(id->hdr_nt_chal_resp ), ps, depth); + smb_io_strhdr("hdr_lm_chal_resp", &(id->hdr_lm_chal_resp ), ps, depth); + + smb_io_unistr2("uni_domain_name", &(id->uni_domain_name), id->hdr_domain_name .buffer, ps, depth); + smb_io_unistr2("uni_user_name ", &(id->uni_user_name ), id->hdr_user_name .buffer, ps, depth); + smb_io_unistr2("uni_wksta_name ", &(id->uni_wksta_name ), id->hdr_wksta_name .buffer, ps, depth); + smb_io_string2("nt_chal_resp" , &(id->nt_chal_resp) , id->hdr_nt_chal_resp.buffer, ps, depth); + smb_io_string2("lm_chal_resp" , &(id->lm_chal_resp) , id->hdr_lm_chal_resp.buffer, ps, depth); + } +} + + +/******************************************************************* +makes a DOM_SAM_INFO structure. +********************************************************************/ +void make_sam_info(DOM_SAM_INFO *sam, + char *logon_srv, char *comp_name, DOM_CRED *clnt_cred, + DOM_CRED *rtn_cred, uint16 logon_level, + NET_ID_INFO_CTR *ctr, uint16 validation_level) +{ + if (sam == NULL) return; + + DEBUG(5,("make_sam_info: %d\n", __LINE__)); + + make_clnt_info2(&(sam->client), logon_srv, comp_name, clnt_cred); + + if (rtn_cred != NULL) + { + sam->ptr_rtn_cred = 1; + memcpy(&(sam->rtn_cred), rtn_cred, sizeof(sam->rtn_cred)); + } + else + { + sam->ptr_rtn_cred = 0; + } + + sam->logon_level = logon_level; + sam->ctr = ctr; + sam->validation_level = validation_level; +} + +/******************************************************************* +reads or writes a DOM_SAM_INFO structure. +********************************************************************/ +void net_io_id_info_ctr(char *desc, NET_ID_INFO_CTR *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_sam_info"); + depth++; + + /* don't 4-byte align here! */ + + prs_uint16("switch_value ", ps, depth, &(ctr->switch_value)); + + switch (ctr->switch_value) + { + case 1: + { + net_io_id_info1("", &(ctr->auth.id1), ps, depth); + break; + } + case 2: + { + net_io_id_info2("", &(ctr->auth.id2), ps, depth); + break; + } + default: + { + /* PANIC! */ + DEBUG(4,("smb_io_sam_info: unknown switch_value!\n")); + break; + } + } +} + +/******************************************************************* +reads or writes a DOM_SAM_INFO structure. +********************************************************************/ +void smb_io_sam_info(char *desc, DOM_SAM_INFO *sam, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_sam_info"); + depth++; + + prs_align(ps); + + smb_io_clnt_info2("", &(sam->client ), ps, depth); + + prs_uint32("ptr_rtn_cred ", ps, depth, &(sam->ptr_rtn_cred)); + smb_io_cred ("", &(sam->rtn_cred), ps, depth); + + prs_uint16("logon_level ", ps, depth, &(sam->logon_level )); + + if (sam->logon_level != 0 && sam->ctr != NULL) + { + net_io_id_info_ctr("logon_info", sam->ctr, ps, depth); + } + + prs_uint16("validation_level", ps, depth, &(sam->validation_level)); +} + +/************************************************************************* + make_net_user_info3 + *************************************************************************/ +void make_net_user_info3(NET_USER_INFO_3 *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *logon_script, + char *profile_path, + char *home_dir, + char *dir_drive, + + uint16 logon_count, + uint16 bad_pw_count, + + uint32 user_id, + uint32 group_id, + uint32 num_groups, + DOM_GID *gids, + uint32 user_flgs, + + char sess_key[16], + + char *logon_srv, + char *logon_dom, + + char *dom_sid, + char *other_sids) +{ + /* only cope with one "other" sid, right now. */ + /* need to count the number of space-delimited sids */ + int i; + int num_other_sids = 0; + + int len_user_name = strlen(user_name ); + int len_full_name = strlen(full_name ); + int len_logon_script = strlen(logon_script); + int len_profile_path = strlen(profile_path); + int len_home_dir = strlen(home_dir ); + int len_dir_drive = strlen(dir_drive ); + + int len_logon_srv = strlen(logon_srv); + int len_logon_dom = strlen(logon_dom); + + usr->ptr_user_info = 1; /* yes, we're bothering to put USER_INFO data here */ + + usr->logon_time = *logon_time; + usr->logoff_time = *logoff_time; + usr->kickoff_time = *kickoff_time; + usr->pass_last_set_time = *pass_last_set_time; + usr->pass_can_change_time = *pass_can_change_time; + usr->pass_must_change_time = *pass_must_change_time; + + make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); + make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); + make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); + make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); + make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); + make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); + + usr->logon_count = logon_count; + usr->bad_pw_count = bad_pw_count; + + usr->user_id = user_id; + usr->group_id = group_id; + usr->num_groups = num_groups; + usr->buffer_groups = 1; /* indicates fill in groups, below, even if there are none */ + usr->user_flgs = user_flgs; + + if (sess_key != NULL) + { + memcpy(usr->user_sess_key, sess_key, sizeof(usr->user_sess_key)); + } + else + { + bzero(usr->user_sess_key, sizeof(usr->user_sess_key)); + } + + make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); + make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); + + usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ + + bzero(usr->padding, sizeof(usr->padding)); + + num_other_sids = make_dom_sid2s(other_sids, usr->other_sids, LSA_MAX_SIDS); + + usr->num_other_sids = num_other_sids; + usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; + + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name ); + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name ); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir ); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive ); + + usr->num_groups2 = num_groups; + for (i = 0; i < num_groups; i++) + { + usr->gids[i] = gids[i]; + } + + make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv); + make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom); + + make_dom_sid2(&(usr->dom_sid), dom_sid); + /* "other" sids are set up above */ +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_user_info3(char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, int depth) +{ + int i; + + if (usr == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_lsa_user_info"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_user_info ", ps, depth, &(usr->ptr_user_info)); + + if (usr->ptr_user_info != 0) + { + smb_io_time("time", &(usr->logon_time) , ps, depth); /* logon time */ + smb_io_time("time", &(usr->logoff_time) , ps, depth); /* logoff time */ + smb_io_time("time", &(usr->kickoff_time) , ps, depth); /* kickoff time */ + smb_io_time("time", &(usr->pass_last_set_time) , ps, depth); /* password last set time */ + smb_io_time("time", &(usr->pass_can_change_time) , ps, depth); /* password can change time */ + smb_io_time("time", &(usr->pass_must_change_time), ps, depth); /* password must change time */ + + smb_io_unihdr("unihdr", &(usr->hdr_user_name) , ps, depth); /* username unicode string header */ + smb_io_unihdr("unihdr", &(usr->hdr_full_name) , ps, depth); /* user's full name unicode string header */ + smb_io_unihdr("unihdr", &(usr->hdr_logon_script), ps, depth); /* logon script unicode string header */ + smb_io_unihdr("unihdr", &(usr->hdr_profile_path), ps, depth); /* profile path unicode string header */ + smb_io_unihdr("unihdr", &(usr->hdr_home_dir) , ps, depth); /* home directory unicode string header */ + smb_io_unihdr("unihdr", &(usr->hdr_dir_drive) , ps, depth); /* home directory drive unicode string header */ + + prs_uint16("logon_count ", ps, depth, &(usr->logon_count )); /* logon count */ + prs_uint16("bad_pw_count ", ps, depth, &(usr->bad_pw_count)); /* bad password count */ + + prs_uint32("user_id ", ps, depth, &(usr->user_id )); /* User ID */ + prs_uint32("group_id ", ps, depth, &(usr->group_id )); /* Group ID */ + prs_uint32("num_groups ", ps, depth, &(usr->num_groups )); /* num groups */ + prs_uint32("buffer_groups ", ps, depth, &(usr->buffer_groups)); /* undocumented buffer pointer to groups. */ + prs_uint32("user_flgs ", ps, depth, &(usr->user_flgs )); /* user flags */ + + prs_uint8s (False, "user_sess_key", ps, depth, usr->user_sess_key, 16); /* unused user session key */ + + smb_io_unihdr("unihdr", &(usr->hdr_logon_srv), ps, depth); /* logon server unicode string header */ + smb_io_unihdr("unihdr", &(usr->hdr_logon_dom), ps, depth); /* logon domain unicode string header */ + + prs_uint32("buffer_dom_id ", ps, depth, &(usr->buffer_dom_id)); /* undocumented logon domain id pointer */ + prs_uint8s (False, "padding ", ps, depth, usr->padding, 40); /* unused padding bytes? */ + + prs_uint32("num_other_sids", ps, depth, &(usr->num_other_sids)); /* 0 - num_sids */ + prs_uint32("buffer_other_sids", ps, depth, &(usr->buffer_other_sids)); /* NULL - undocumented pointer to SIDs. */ + + smb_io_unistr2("unistr2", &(usr->uni_user_name) , usr->hdr_user_name .buffer, ps, depth); /* username unicode string */ + smb_io_unistr2("unistr2", &(usr->uni_full_name) , usr->hdr_full_name .buffer, ps, depth); /* user's full name unicode string */ + smb_io_unistr2("unistr2", &(usr->uni_logon_script), usr->hdr_logon_script.buffer, ps, depth); /* logon script unicode string */ + smb_io_unistr2("unistr2", &(usr->uni_profile_path), usr->hdr_profile_path.buffer, ps, depth); /* profile path unicode string */ + smb_io_unistr2("unistr2", &(usr->uni_home_dir) , usr->hdr_home_dir .buffer, ps, depth); /* home directory unicode string */ + smb_io_unistr2("unistr2", &(usr->uni_dir_drive) , usr->hdr_dir_drive .buffer, ps, depth); /* home directory drive unicode string */ + + prs_align(ps); + prs_uint32("num_groups2 ", ps, depth, &(usr->num_groups2)); /* num groups */ + for (i = 0; i < usr->num_groups2; i++) + { + smb_io_gid("", &(usr->gids[i]), ps, depth); /* group info */ + } + + smb_io_unistr2("unistr2", &( usr->uni_logon_srv), usr->hdr_logon_srv.buffer, ps, depth); /* logon server unicode string */ + smb_io_unistr2("unistr2", &( usr->uni_logon_dom), usr->hdr_logon_srv.buffer, ps, depth); /* logon domain unicode string */ + + smb_io_dom_sid2("", &(usr->dom_sid), ps, depth); /* domain SID */ + + for (i = 0; i < usr->num_other_sids; i++) + { + smb_io_dom_sid2("", &(usr->other_sids[i]), ps, depth); /* other domain SIDs */ + } + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_q_sam_logon(char *desc, NET_Q_SAM_LOGON *q_l, prs_struct *ps, int depth) +{ + if (q_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_sam_logon"); + depth++; + + prs_align(ps); + + smb_io_sam_info("", &(q_l->sam_id), ps, depth); /* domain SID */ +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_r_sam_logon(char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps, int depth) +{ + if (r_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_sam_logon"); + depth++; + + prs_uint32("buffer_creds", ps, depth, &(r_l->buffer_creds)); /* undocumented buffer pointer */ + smb_io_cred("", &(r_l->srv_creds), ps, depth); /* server credentials. server time stamp appears to be ignored. */ + + prs_uint16("switch_value", ps, depth, &(r_l->switch_value)); + prs_align(ps); + + if (r_l->switch_value != 0) + { + net_io_user_info3("", r_l->user, ps, depth); + } + + prs_uint32("auth_resp ", ps, depth, &(r_l->auth_resp)); /* 1 - Authoritative response; 0 - Non-Auth? */ + + prs_uint32("status ", ps, depth, &(r_l->status)); + + prs_align(ps); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_q_sam_logoff(char *desc, NET_Q_SAM_LOGOFF *q_l, prs_struct *ps, int depth) +{ + if (q_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_q_sam_logoff"); + depth++; + + prs_align(ps); + + smb_io_sam_info("", &(q_l->sam_id), ps, depth); /* domain SID */ +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void net_io_r_sam_logoff(char *desc, NET_R_SAM_LOGOFF *r_l, prs_struct *ps, int depth) +{ + if (r_l == NULL) return; + + prs_debug(ps, depth, desc, "net_io_r_sam_logoff"); + depth++; + + prs_align(ps); + + prs_uint32("buffer_creds", ps, depth, &(r_l->buffer_creds)); /* undocumented buffer pointer */ + smb_io_cred("", &(r_l->srv_creds), ps, depth); /* server credentials. server time stamp appears to be ignored. */ + + prs_uint32("status ", ps, depth, &(r_l->status)); +} + + diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c new file mode 100644 index 0000000000..799bd1cc94 --- /dev/null +++ b/source3/rpc_parse/parse_prs.c @@ -0,0 +1,290 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + Samba memory buffer functions + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + + 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. +*/ + +extern int DEBUGLEVEL; + +#include "includes.h" + + +/******************************************************************* + debug output for parsing info. + + XXXX side-effect of this function is to increase the debug depth XXXX + + ********************************************************************/ +void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name) +{ + DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->offset, fn_name, desc)); +} + +/******************************************************************* + initialise a parse structure + ********************************************************************/ +void prs_init(prs_struct *ps, uint32 size, + uint8 align, uint32 margin, + BOOL io) +{ + ps->io = io; + ps->align = align; + ps->offset = 0; + + ps->data = NULL; + mem_buf_init(&(ps->data), margin); + + if (size != 0) + { + mem_alloc_data(ps->data, size); + ps->data->offset.start = 0; + ps->data->offset.end = 0xffffffff; + } +} + +/******************************************************************* + initialise a parse structure + ********************************************************************/ +void prs_mem_free(prs_struct *ps) +{ + mem_buf_free(&(ps->data)); +} + +/******************************************************************* + align a pointer to a multiple of align_offset bytes. looks like it + will work for offsets of 0, 2 and 4... + ********************************************************************/ +void prs_align(prs_struct *ps) +{ + int mod = ps->offset & (ps->align-1); + if (ps->align != 0 && mod != 0) + { + ps->offset += ps->align - mod; + } +} + +/******************************************************************* + attempt, if appropriate, to grow a data buffer. + + depends on the data stream mode (io) + ********************************************************************/ +BOOL prs_grow(prs_struct *ps) +{ + return mem_grow_data(&(ps->data), ps->io, ps->offset); +} + + +/******************************************************************* + stream a uint8 + ********************************************************************/ +BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_CVAL(name, depth, ps->offset, ps->io, q, *data8) + ps->offset += 1; + + return True; +} + +/******************************************************************* + stream a uint16 + ********************************************************************/ +BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_SVAL(name, depth, ps->offset, ps->io, q, *data16) + ps->offset += 2; + + return True; +} + +/******************************************************************* + stream a uint32 + ********************************************************************/ +BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_IVAL(name, depth, ps->offset, ps->io, q, *data32) + ps->offset += 4; + + return True; +} + + +/****************************************************************** + stream an array of uint8s. length is number of uint8s + ********************************************************************/ +BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, data8s, len) + ps->offset += len; + + return True; +} + +/****************************************************************** + stream an array of uint16s. length is number of uint16s + ********************************************************************/ +BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, data16s, len) + ps->offset += len * sizeof(uint16); + + return True; +} + +/****************************************************************** + stream an array of uint32s. length is number of uint32s + ********************************************************************/ +BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_PIVAL(charmode, name, depth, ps->offset, ps->io, q, data32s, len) + ps->offset += len * sizeof(uint32); + + return True; +} + +/****************************************************************** + stream a "not" unicode string, length/buffer specified separately, + in byte chars + ********************************************************************/ +BOOL prs_uninotstr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNINOTSTR2 *str) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_max_len) + ps->offset += str->uni_buf_len; + + return True; +} + +/****************************************************************** + stream a string, length/buffer specified separately, + in uint8 chars. + ********************************************************************/ +BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->str_max_len) + ps->offset += str->str_str_len * sizeof(uint8); + + return True; +} + +/****************************************************************** + stream a unicode string, length/buffer specified separately, + in uint16 chars. + ********************************************************************/ +BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str) +{ + char *q = mem_data(&(ps->data), ps->offset); + if (q == NULL) return False; + + DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_max_len) + ps->offset += str->uni_str_len * sizeof(uint16); + + return True; +} + +/******************************************************************* + stream a unicode null-terminated string + ********************************************************************/ +BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str) +{ + char *q = mem_data(&(ps->data), ps->offset); + int i = 0; + uint8 *start = (uint8*)q; + + if (q == NULL) return False; + + do + { + RW_SVAL(ps->io, q, str->buffer[i],0); + q += 2; + i++; + + } while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) && + (str->buffer[i] != 0)); + + ps->offset += i*2; + + dump_data(5+depth, start, ps->offset); + + return True; +} + +/******************************************************************* + stream a null-terminated string. len is strlen, and therefore does + not include the null-termination character. + + len == 0 indicates variable length string + (up to max size of pstring - 1024 chars). + + ********************************************************************/ +BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len) +{ + char *q = mem_data(&(ps->data), ps->offset); + uint8 *start = (uint8*)q; + int i = -1; /* start off at zero after 1st i++ */ + + if (q == NULL) return False; + + do + { + i++; + + if (i < len || len == 0) + { + RW_CVAL(ps->io, q, str[i],0); + } + else + { + uint8 dummy = 0; + RW_CVAL(ps->io, q, dummy,0); + } + + q++; + + } while (i < sizeof(pstring) && (len == 0 ? str[i] != 0 : i < len) ); + + ps->offset += i+1; + + dump_data(5+depth, start, ps->offset); + + return True; +} + diff --git a/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c new file mode 100644 index 0000000000..d278b75f5d --- /dev/null +++ b/source3/rpc_parse/parse_reg.c @@ -0,0 +1,335 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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" + +extern int DEBUGLEVEL; + + +/******************************************************************* +creates a structure. +********************************************************************/ +void make_reg_q_open_policy(REG_Q_OPEN_POLICY *r_q, + uint16 unknown_0, uint32 level, uint16 unknown_1) +{ + r_q->ptr = 1; + r_q->unknown_0 = unknown_0; + r_q->level = level; + r_q->unknown_1 = unknown_1; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_q_open_policy(char *desc, REG_Q_OPEN_POLICY *r_q, prs_struct *ps, int depth) +{ + if (r_q == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_q_open_policy"); + depth++; + + prs_align(ps); + + prs_uint32("ptr ", ps, depth, &(r_q->ptr )); + if (r_q->ptr != 0) + { + prs_uint16("unknown_0", ps, depth, &(r_q->unknown_0)); + prs_uint32("level ", ps, depth, &(r_q->level )); + prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1)); + } +} + + +/******************************************************************* +creates a structure. +********************************************************************/ +void make_reg_r_open_policy(REG_R_OPEN_POLICY *r_r, + POLICY_HND *pol, uint32 status) +{ + if (r_r == NULL) return; + + memcpy(&(r_r->pol), pol, sizeof(r_r->pol)); + r_r->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_r_open_policy(char *desc, REG_R_OPEN_POLICY *r_r, prs_struct *ps, int depth) +{ + if (r_r == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_r_open_policy"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(r_r->pol), ps, depth); + + prs_uint32("status", ps, depth, &(r_r->status)); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_q_close(char *desc, REG_Q_CLOSE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_q_unknown_1"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(q_u->pol), ps, depth); + prs_align(ps); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_r_close(char *desc, REG_R_CLOSE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_r_unknown_1"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(r_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} +/******************************************************************* +creates a structure. +********************************************************************/ +void make_reg_q_info(REG_Q_INFO *r_q, + POLICY_HND *pol, char *product_type, + NTTIME *prod_time, uint8 major_version, uint8 minor_version, + uint32 unknown) +{ + int type_len = strlen(product_type); + + memcpy(&(r_q->pol), pol, sizeof(r_q->pol)); + make_uni_hdr(&(r_q->hdr_type), type_len, type_len, 1); + make_unistr2(&(r_q->uni_type), product_type, type_len); + + r_q->ptr1 = 1; + memcpy(&(r_q->time), prod_time, sizeof(r_q->time)); + r_q->major_version1 = major_version; + r_q->minor_version1 = minor_version; + bzero(&(r_q->pad1), sizeof(r_q->pad1)); + + r_q->ptr2 = 1; + r_q->major_version2 = major_version; + r_q->minor_version2 = minor_version; + bzero(&(r_q->pad2), sizeof(r_q->pad2)); + + r_q->ptr3 = 1; + r_q->unknown = unknown; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_q_info(char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth) +{ + if (r_q == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_q_info"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(r_q->pol), ps, depth); + smb_io_unihdr ("", &(r_q->hdr_type), ps, depth); + smb_io_unistr2("", &(r_q->uni_type), r_q->hdr_type.buffer, ps, depth); + + prs_uint32("ptr1", ps, depth, &(r_q->ptr1)); + + if (r_q->ptr1 != 0) + { + smb_io_time("", &(r_q->time), ps, depth); + prs_uint8 ("major_version1", ps, depth, &(r_q->major_version1)); + prs_uint8 ("minor_version1", ps, depth, &(r_q->minor_version1)); + prs_uint8s(False, "pad1", ps, depth, r_q->pad1, sizeof(r_q->pad1)); + } + + prs_uint32("ptr2", ps, depth, &(r_q->ptr2)); + + if (r_q->ptr2 != 0) + { + prs_uint8 ("major_version2", ps, depth, &(r_q->major_version2)); + prs_uint8 ("minor_version2", ps, depth, &(r_q->minor_version2)); + prs_uint8s(False, "pad2", ps, depth, r_q->pad2, sizeof(r_q->pad2)); + } + + prs_uint32("ptr3", ps, depth, &(r_q->ptr3)); + + if (r_q->ptr3 != 0) + { + prs_uint32("unknown", ps, depth, &(r_q->unknown)); + } +} + + +/******************************************************************* +creates a structure. +********************************************************************/ +void make_reg_r_info(REG_R_INFO *r_r, + uint32 level, char *os_type, + uint32 unknown_0, uint32 unknown_1, + uint32 status) +{ + int type_len = strlen(os_type); + + r_r->ptr1 = 1; + r_r->level = level; + + r_r->ptr_type = 1; + make_uninotstr2(&(r_r->uni_type), os_type, type_len); + + r_r->ptr2 = 1; + r_r->unknown_0 = unknown_0; + + r_r->ptr3 = 1; + r_r->unknown_1 = unknown_1; + + r_r->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth) +{ + if (r_r == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_r_info"); + depth++; + + prs_align(ps); + + prs_uint32("ptr1", ps, depth, &(r_r->ptr1)); + + if (r_r->ptr1 != 0) + { + prs_uint32("level", ps, depth, &(r_r->level)); + + prs_uint32("ptr_type", ps, depth, &(r_r->ptr_type)); + smb_io_uninotstr2("", &(r_r->uni_type), r_r->ptr_type, ps, depth); + prs_align(ps); + + prs_uint32("ptr2", ps, depth, &(r_r->ptr2)); + + if (r_r->ptr2 != 0) + { + prs_uint32("unknown_0", ps, depth, &(r_r->unknown_0)); + } + + prs_uint32("ptr3", ps, depth, &(r_r->ptr3)); + + if (r_r->ptr3 != 0) + { + prs_uint32("unknown_1", ps, depth, &(r_r->unknown_1)); + } + } + + prs_uint32("status", ps, depth, &(r_r->status)); +} + + +/******************************************************************* +creates a structure. +********************************************************************/ +void make_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q, + POLICY_HND *pol, char *name, + uint32 unknown_0, uint32 unknown_1, uint16 unknown_2) +{ + int len_name = strlen(name); + + memcpy(&(r_q->pol), pol, sizeof(r_q->pol)); + + make_uni_hdr(&(r_q->hdr_name), len_name, len_name, 1); + make_unistr2(&(r_q->uni_name), name, len_name); + + r_q->unknown_0 = unknown_0; + r_q->unknown_1 = unknown_1; + r_q->unknown_2 = unknown_2; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_q_open_entry(char *desc, REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int depth) +{ + if (r_q == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_q_entry"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(r_q->pol), ps, depth); + smb_io_unihdr ("", &(r_q->hdr_name), ps, depth); + smb_io_unistr2("", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth); + + prs_uint32("unknown_0", ps, depth, &(r_q->unknown_0)); + prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1)); + prs_uint16("unknown_2", ps, depth, &(r_q->unknown_2)); +} + + +/******************************************************************* +creates a structure. +********************************************************************/ +void make_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r, + POLICY_HND *pol, uint32 status) +{ + if (r_r == NULL) return; + + memcpy(&(r_r->pol), pol, sizeof(r_r->pol)); + r_r->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void reg_io_r_open_entry(char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *ps, int depth) +{ + if (r_r == NULL) return; + + prs_debug(ps, depth, desc, "reg_io_r_open_entry"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("", &(r_r->pol), ps, depth); + + prs_uint32("status", ps, depth, &(r_r->status)); +} + diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c new file mode 100644 index 0000000000..b025d3f1c8 --- /dev/null +++ b/source3/rpc_parse/parse_rpc.c @@ -0,0 +1,528 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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" + +extern int DEBUGLEVEL; + + +/******************************************************************* +interface/version dce/rpc pipe identification +********************************************************************/ + +#define TRANS_SYNT_V2 \ +{ \ + { \ + 0x04, 0x5d, 0x88, 0x8a, \ + 0xeb, 0x1c, 0xc9, 0x11, \ + 0x9f, 0xe8, 0x08, 0x00, \ + 0x2b, 0x10, 0x48, 0x60 \ + }, 0x02 \ +} \ + +#define SYNT_NETLOGON_V2 \ +{ \ + { \ + 0x04, 0x5d, 0x88, 0x8a, \ + 0xeb, 0x1c, 0xc9, 0x11, \ + 0x9f, 0xe8, 0x08, 0x00, \ + 0x2b, 0x10, 0x48, 0x60 \ + }, 0x02 \ +} \ + +#define SYNT_WKSSVC_V1 \ +{ \ + { \ + 0x98, 0xd0, 0xff, 0x6b, \ + 0x12, 0xa1, 0x10, 0x36, \ + 0x98, 0x33, 0x46, 0xc3, \ + 0xf8, 0x7e, 0x34, 0x5a \ + }, 0x01 \ +} \ + +#define SYNT_SRVSVC_V3 \ +{ \ + { \ + 0xc8, 0x4f, 0x32, 0x4b, \ + 0x70, 0x16, 0xd3, 0x01, \ + 0x12, 0x78, 0x5a, 0x47, \ + 0xbf, 0x6e, 0xe1, 0x88 \ + }, 0x03 \ +} \ + +#define SYNT_LSARPC_V0 \ +{ \ + { \ + 0x78, 0x57, 0x34, 0x12, \ + 0x34, 0x12, 0xcd, 0xab, \ + 0xef, 0x00, 0x01, 0x23, \ + 0x45, 0x67, 0x89, 0xab \ + }, 0x00 \ +} \ + +#define SYNT_SAMR_V1 \ +{ \ + { \ + 0x78, 0x57, 0x34, 0x12, \ + 0x34, 0x12, 0xcd, 0xab, \ + 0xef, 0x00, 0x01, 0x23, \ + 0x45, 0x67, 0x89, 0xac \ + }, 0x01 \ +} \ + +#define SYNT_NETLOGON_V1 \ +{ \ + { \ + 0x78, 0x56, 0x34, 0x12, \ + 0x34, 0x12, 0xcd, 0xab, \ + 0xef, 0x00, 0x01, 0x23, \ + 0x45, 0x67, 0xcf, 0xfb \ + }, 0x01 \ +} \ + +#define SYNT_WINREG_V1 \ +{ \ + { \ + 0x01, 0xd0, 0x8c, 0x33, \ + 0x44, 0x22, 0xf1, 0x31, \ + 0xaa, 0xaa, 0x90, 0x00, \ + 0x38, 0x00, 0x10, 0x03 \ + }, 0x01 \ +} \ + +#define SYNT_NONE_V0 \ +{ \ + { \ + 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00 \ + }, 0x00 \ +} \ + +/* pipe string names */ +#define PIPE_SRVSVC "\\PIPE\\srvsvc" +#define PIPE_SAMR "\\PIPE\\samr" +#define PIPE_WINREG "\\PIPE\\winreg" +#define PIPE_WKSSVC "\\PIPE\\wkssvc" +#define PIPE_NETLOGON "\\PIPE\\NETLOGON" +#define PIPE_NTLSA "\\PIPE\\ntlsa" +#define PIPE_NTSVCS "\\PIPE\\ntsvcs" +#define PIPE_LSASS "\\PIPE\\lsass" +#define PIPE_LSARPC "\\PIPE\\lsarpc" + +struct pipe_id_info pipe_names [] = +{ + /* client pipe , abstract syntax , server pipe , transfer syntax */ + { PIPE_LSARPC , SYNT_LSARPC_V0 , PIPE_LSASS , TRANS_SYNT_V2 }, + { PIPE_SAMR , SYNT_SAMR_V1 , PIPE_LSASS , TRANS_SYNT_V2 }, + { PIPE_NETLOGON, SYNT_NETLOGON_V1, PIPE_LSASS , TRANS_SYNT_V2 }, + { PIPE_SRVSVC , SYNT_SRVSVC_V3 , PIPE_NTSVCS , TRANS_SYNT_V2 }, + { PIPE_WKSSVC , SYNT_WKSSVC_V1 , PIPE_NTSVCS , TRANS_SYNT_V2 }, + { PIPE_WINREG , SYNT_WINREG_V1 , PIPE_WINREG , TRANS_SYNT_V2 }, + { NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 } +}; + +/******************************************************************* +creates an RPC_HDR structure. +********************************************************************/ +void make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 flags, + uint32 call_id, int data_len, int auth_len) +{ + if (hdr == NULL) return; + + hdr->major = 5; /* RPC version 5 */ + hdr->minor = 0; /* minor version 0 */ + hdr->pkt_type = pkt_type; /* RPC packet type */ + hdr->flags = flags; /* dce/rpc flags */ + hdr->pack_type = 0x10; /* packed data representation */ + hdr->frag_len = data_len; /* fragment length, fill in later */ + hdr->auth_len = auth_len; /* authentication length */ + hdr->call_id = call_id; /* call identifier - match incoming RPC */ +} + +/******************************************************************* +reads or writes an RPC_HDR structure. +********************************************************************/ +void smb_io_rpc_hdr(char *desc, RPC_HDR *rpc, prs_struct *ps, int depth) +{ + if (rpc == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_hdr"); + depth++; + + prs_uint8 ("major ", ps, depth, &(rpc->major)); + prs_uint8 ("minor ", ps, depth, &(rpc->minor)); + prs_uint8 ("pkt_type ", ps, depth, &(rpc->pkt_type)); + prs_uint8 ("flags ", ps, depth, &(rpc->flags)); + prs_uint32("pack_type ", ps, depth, &(rpc->pack_type)); + prs_uint16("frag_len ", ps, depth, &(rpc->frag_len)); + prs_uint16("auth_len ", ps, depth, &(rpc->auth_len)); + prs_uint32("call_id ", ps, depth, &(rpc->call_id)); +} + +/******************************************************************* +creates an RPC_IFACE structure. +********************************************************************/ +void make_rpc_iface(RPC_IFACE *ifc, char data[16], uint32 version) +{ + if (ifc == NULL || data == NULL) return; + + memcpy(ifc->data, data, sizeof(ifc->data)); /* 16 bytes of number */ + ifc->version = version; /* the interface number */ +} + +/******************************************************************* +reads or writes an RPC_IFACE structure. +********************************************************************/ +void smb_io_rpc_iface(char *desc, RPC_IFACE *ifc, prs_struct *ps, int depth) +{ + if (ifc == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_iface"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "data ", ps, depth, ifc->data, sizeof(ifc->data)); + prs_uint32 ( "version", ps, depth, &(ifc->version)); +} + +/******************************************************************* +creates an RPC_ADDR_STR structure. +********************************************************************/ +void make_rpc_addr_str(RPC_ADDR_STR *str, char *name) +{ + if (str == NULL || name == NULL) return; + + str->len = strlen(name) + 1; + fstrcpy(str->str, name); +} + +/******************************************************************* +reads or writes an RPC_ADDR_STR structure. +********************************************************************/ +void smb_io_rpc_addr_str(char *desc, RPC_ADDR_STR *str, prs_struct *ps, int depth) +{ + if (str == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_addr_str"); + depth++; + prs_align(ps); + + prs_uint16 ( "len", ps, depth, &(str->len)); + prs_uint8s (True, "str", ps, depth, (uchar*)str->str, str->len); +} + +/******************************************************************* +creates an RPC_HDR_BBA structure. +********************************************************************/ +void make_rpc_hdr_bba(RPC_HDR_BBA *bba, uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid) +{ + if (bba == NULL) return; + + bba->max_tsize = max_tsize; /* maximum transmission fragment size (0x1630) */ + bba->max_rsize = max_rsize; /* max receive fragment size (0x1630) */ + bba->assoc_gid = assoc_gid; /* associated group id (0x0) */ +} + +/******************************************************************* +reads or writes an RPC_HDR_BBA structure. +********************************************************************/ +void smb_io_rpc_hdr_bba(char *desc, RPC_HDR_BBA *rpc, prs_struct *ps, int depth) +{ + if (rpc == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_hdr_bba"); + depth++; + + prs_uint16("max_tsize", ps, depth, &(rpc->max_tsize)); + prs_uint16("max_rsize", ps, depth, &(rpc->max_rsize)); + prs_uint32("assoc_gid", ps, depth, &(rpc->assoc_gid)); +} + +/******************************************************************* +creates an RPC_HDR_RB structure. +********************************************************************/ +void make_rpc_hdr_rb(RPC_HDR_RB *rpc, + uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, + uint32 num_elements, uint16 context_id, uint8 num_syntaxes, + RPC_IFACE *abstract, RPC_IFACE *transfer) +{ + if (rpc == NULL) return; + + make_rpc_hdr_bba(&(rpc->bba), max_tsize, max_rsize, assoc_gid); + + rpc->num_elements = num_elements ; /* the number of elements (0x1) */ + rpc->context_id = context_id ; /* presentation context identifier (0x0) */ + rpc->num_syntaxes = num_syntaxes ; /* the number of syntaxes (has always been 1?)(0x1) */ + + /* num and vers. of interface client is using */ + memcpy(&(rpc->abstract), abstract, sizeof(rpc->abstract)); + + /* num and vers. of interface to use for replies */ + memcpy(&(rpc->transfer), transfer, sizeof(rpc->transfer)); +} + +/******************************************************************* +reads or writes an RPC_HDR_RB structure. +********************************************************************/ +void smb_io_rpc_hdr_rb(char *desc, RPC_HDR_RB *rpc, prs_struct *ps, int depth) +{ + if (rpc == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_hdr_rb"); + depth++; + + smb_io_rpc_hdr_bba("", &(rpc->bba), ps, depth); + + prs_uint32("num_elements", ps, depth, &(rpc->num_elements)); + prs_uint16("context_id ", ps, depth, &(rpc->context_id )); + prs_uint8 ("num_syntaxes", ps, depth, &(rpc->num_syntaxes)); + + smb_io_rpc_iface("", &(rpc->abstract), ps, depth); + smb_io_rpc_iface("", &(rpc->transfer), ps, depth); +} + +/******************************************************************* +creates an RPC_RESULTS structure. + +lkclXXXX only one reason at the moment! + +********************************************************************/ +void make_rpc_results(RPC_RESULTS *res, + uint8 num_results, uint16 result, uint16 reason) +{ + if (res == NULL) return; + + res->num_results = num_results; /* the number of results (0x01) */ + res->result = result ; /* result (0x00 = accept) */ + res->reason = reason ; /* reason (0x00 = no reason specified) */ +} + +/******************************************************************* +reads or writes an RPC_RESULTS structure. + +lkclXXXX only one reason at the moment! + +********************************************************************/ +void smb_io_rpc_results(char *desc, RPC_RESULTS *res, prs_struct *ps, int depth) +{ + if (res == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_results"); + depth++; + + prs_align(ps); + + prs_uint8 ("num_results", ps, depth, &(res->num_results)); + + prs_align(ps); + + prs_uint16("result ", ps, depth, &(res->result )); + prs_uint16("reason ", ps, depth, &(res->reason )); +} + +/******************************************************************* +creates an RPC_HDR_BA structure. + +lkclXXXX only one reason at the moment! + +********************************************************************/ +void make_rpc_hdr_ba(RPC_HDR_BA *rpc, + uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid, + char *pipe_addr, + uint8 num_results, uint16 result, uint16 reason, + RPC_IFACE *transfer) +{ + if (rpc == NULL || transfer == NULL || pipe_addr == NULL) return; + + make_rpc_hdr_bba (&(rpc->bba ), max_tsize, max_rsize, assoc_gid); + make_rpc_addr_str(&(rpc->addr), pipe_addr); + make_rpc_results (&(rpc->res ), num_results, result, reason); + + /* the transfer syntax from the request */ + memcpy(&(rpc->transfer), transfer, sizeof(rpc->transfer)); +} + +/******************************************************************* +reads or writes an RPC_HDR_BA structure. +********************************************************************/ +void smb_io_rpc_hdr_ba(char *desc, RPC_HDR_BA *rpc, prs_struct *ps, int depth) +{ + if (rpc == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_hdr_ba"); + depth++; + + smb_io_rpc_hdr_bba ("", &(rpc->bba) , ps, depth); + smb_io_rpc_addr_str("", &(rpc->addr) , ps, depth); + smb_io_rpc_results ("", &(rpc->res) , ps, depth); + smb_io_rpc_iface ("", &(rpc->transfer), ps, depth); +} + +/******************************************************************* +creates an RPC_HDR_RR structure. +********************************************************************/ +void make_rpc_hdr_rr(RPC_HDR_RR *hdr, uint32 data_len, uint8 opnum) +{ + if (hdr == NULL) return; + + hdr->alloc_hint = data_len - 0x18; /* allocation hint */ + hdr->context_id = 0; /* presentation context identifier */ + hdr->cancel_count = 0; /* cancel count */ + hdr->opnum = opnum; /* opnum */ + hdr->reserved = 0; /* 0 - reserved */ +} + +/******************************************************************* +reads or writes an RPC_HDR_RR structure. +********************************************************************/ +void smb_io_rpc_hdr_rr(char *desc, RPC_HDR_RR *rpc, prs_struct *ps, int depth) +{ + if (rpc == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_hdr_rr"); + depth++; + + prs_uint32("alloc_hint", ps, depth, &(rpc->alloc_hint)); + prs_uint8 ("context_id", ps, depth, &(rpc->context_id)); + prs_uint8 ("cancel_ct ", ps, depth, &(rpc->cancel_count)); + prs_uint8 ("opnum ", ps, depth, &(rpc->opnum)); + prs_uint8 ("reserved ", ps, depth, &(rpc->reserved)); +} + +/******************************************************************* +creates an RPC_AUTH_NTLMSSP_REQ structure. +********************************************************************/ +void make_rpc_auth_ntlmssp_req(RPC_AUTH_NTLMSSP_REQ *req, + fstring ntlmssp_str, uint32 ntlmssp_ver, + uint32 unknown_0, fstring myname, fstring domain) +{ + int len_myname = strlen(myname); + int len_domain = strlen(domain); + + if (req == NULL) return; + + fstrcpy(req->ntlmssp_str, ntlmssp_str); /* "NTLMSSP" */ + req->ntlmssp_ver = ntlmssp_ver; /* 0x0000 0001 */ + + req->unknown_0 = unknown_0 ; /* 0x00b2b3 */ + make_str_hdr(&req->hdr_myname, len_myname, len_myname, 1); + make_str_hdr(&req->hdr_domain, len_domain, len_domain, 1); + + fstrcpy(req->myname, myname); + fstrcpy(req->domain, domain); +} + +/******************************************************************* +reads or writes an RPC_AUTH_NTLMSSP_REQ structure. +********************************************************************/ +void smb_io_rpc_auth_ntlmssp_req(char *desc, RPC_AUTH_NTLMSSP_REQ *req, prs_struct *ps, int depth) +{ + if (req == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_req"); + depth++; + + prs_string("ntlmssp_str", ps, depth, req->ntlmssp_str, 0); /* "NTLMSSP" */ + prs_uint32("ntlmssp_ver", ps, depth, &(req->ntlmssp_ver )); + + prs_uint32("unknown_0 ", ps, depth, &(req->unknown_0 )); + smb_io_strhdr("hdr_myname", &(req->hdr_myname), ps, depth); + smb_io_strhdr("hdr_domain", &(req->hdr_domain), ps, depth); + + prs_string("myname", ps, depth, req->myname, req->hdr_myname.str_str_len); + prs_string("domain", ps, depth, req->domain, req->hdr_domain.str_str_len); +} + +/******************************************************************* +creates an RPC_AUTH_NTLMSSP_RESP structure. +********************************************************************/ +void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp, + uint8 auth_type, uint8 auth_level, uint8 stub_type_len, + fstring ntlmssp_str, uint32 ntlmssp_ver, + uint32 unknown_1, uint32 unknown_2, uint32 unknown_3, + uint8 data[16]) +{ + if (rsp == NULL) return; + + rsp->auth_type = auth_type; /* nt lm ssp 0x0a */ + rsp->auth_level = auth_level; /* 0x06 */ + rsp->stub_type_len = stub_type_len; /* dunno. */ + rsp->padding = 0; /* padding */ + + rsp->ptr_0 = 1; /* non-zero pointer to something */ + + fstrcpy(rsp->ntlmssp_str, ntlmssp_str); /* "NTLMSSP" */ + rsp->ntlmssp_ver = ntlmssp_ver; /* 0x0000 0002 */ + + rsp->unknown_1 = unknown_1; /* 0x0000 0000 */ + rsp->unknown_2 = unknown_2; /* 0x00b2b3 */ + rsp->unknown_3 = unknown_3; /* 0x0082b1 */ + + memcpy(rsp->data, data, sizeof(rsp->data)); /* 0x10 bytes of something, 8 of which are zeros */ +} + +/******************************************************************* +reads or writes an RPC_AUTH_NTLMSSP_RESP structure. +********************************************************************/ +void smb_io_rpc_auth_ntlmssp_resp(char *desc, RPC_AUTH_NTLMSSP_RESP *rsp, prs_struct *ps, int depth) +{ + if (rsp == NULL) return; + + prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_resp"); + depth++; + + prs_uint8("auth_type", ps, depth, &(rsp->auth_type)); /* nt lm ssp 0x0a */ + prs_uint8("auth_level", ps, depth, &(rsp->auth_level));/* 0x06 */ + prs_uint8("stub_type_len", ps, depth, &(rsp->stub_type_len)); + prs_uint8("padding", ps, depth, &(rsp->padding)); + + prs_uint32("ptr_0", ps, depth, &(rsp->ptr_0 )); /* non-zero pointer to something */ + + prs_string("ntlmssp_str", ps, depth, rsp->ntlmssp_str, 0); /* "NTLMSSP" */ + prs_uint32("ntlmssp_ver", ps, depth, &(rsp->ntlmssp_ver )); /* 0x0000 0002 */ + + prs_uint32("unknown_1", ps, depth, &(rsp->unknown_1)); /* 0x0000 0000 */ + prs_uint32("unknown_2", ps, depth, &(rsp->unknown_2)); /* 0x00b2b3 */ + prs_uint32("unknown_3", ps, depth, &(rsp->unknown_3)); /* 0x0082b1 */ + + prs_uint8s (False, "data", ps, depth, rsp->data, sizeof(rsp->data)); +} + +#if 0 + +/* attached to the end of encrypted rpc requests and responses */ +/* RPC_AUTH_NTLMSSP_CHK */ +typedef struct rpc_auth_ntlmssp_chk_info +{ + uint32 ver; /* 0x1 */ + uint8 data[12]; + +} RPC_AUTH_NTLMSSP_CHK; + +#endif /* 0 */ + diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c new file mode 100644 index 0000000000..a72769d9c0 --- /dev/null +++ b/source3/rpc_parse/parse_samr.c @@ -0,0 +1,2796 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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" + +extern int DEBUGLEVEL; + + +/******************************************************************* +makes a SAMR_Q_CLOSE_HND structure. +********************************************************************/ +void make_samr_q_close_hnd(SAMR_Q_CLOSE_HND *q_c, POLICY_HND *hnd) +{ + if (q_c == NULL || hnd == NULL) return; + + DEBUG(5,("make_samr_q_close_hnd\n")); + + memcpy(&(q_c->pol), hnd, sizeof(q_c->pol)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_close_hnd(char *desc, SAMR_Q_CLOSE_HND *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_close_hnd"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_close_hnd(char *desc, SAMR_R_CLOSE_HND *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_close_hnd"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_samr_q_open_domain(SAMR_Q_OPEN_DOMAIN *q_u, + POLICY_HND *connect_pol, uint32 rid, char *sid) +{ + if (q_u == NULL) return; + + DEBUG(5,("samr_make_q_open_domain\n")); + + memcpy(&q_u->connect_pol, connect_pol, sizeof(q_u->connect_pol)); + q_u->rid = rid; + make_dom_sid2(&(q_u->dom_sid), sid); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_open_domain(char *desc, SAMR_Q_OPEN_DOMAIN *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_open_domain"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("connect_pol", &(q_u->connect_pol), ps, depth); + prs_align(ps); + + prs_uint32("rid", ps, depth, &(q_u->rid)); + + smb_io_dom_sid2("sid", &(q_u->dom_sid), ps, depth); + prs_align(ps); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_open_domain(char *desc, SAMR_R_OPEN_DOMAIN *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_open_domain"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("domain_pol", &(r_u->domain_pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_samr_q_unknown_8(SAMR_Q_UNKNOWN_8 *q_u, + POLICY_HND *domain_pol, uint16 switch_value) +{ + if (q_u == NULL) return; + + DEBUG(5,("samr_make_q_unknown_8\n")); + + memcpy(&q_u->domain_pol, domain_pol, sizeof(q_u->domain_pol)); + q_u->switch_value = switch_value; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_8(char *desc, SAMR_Q_UNKNOWN_8 *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_8"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("domain_pol", &(q_u->domain_pol), ps, depth); + prs_align(ps); + + prs_uint16("switch_value", ps, depth, &(q_u->switch_value)); + prs_align(ps); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_samr_q_unknown_3(SAMR_Q_UNKNOWN_3 *q_u, + POLICY_HND *user_pol, uint16 switch_value) +{ + if (q_u == NULL) return; + + DEBUG(5,("samr_make_q_unknown_3\n")); + + memcpy(&q_u->user_pol, user_pol, sizeof(q_u->user_pol)); + q_u->switch_value = switch_value; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_3(char *desc, SAMR_Q_UNKNOWN_3 *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_3"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("user_pol", &(q_u->user_pol), ps, depth); + prs_align(ps); + + prs_uint16("switch_value", ps, depth, &(q_u->switch_value)); + prs_align(ps); +} + +/******************************************************************* + makes a DOM_SID3 structure. + + calculate length by adding up the size of the components. + ********************************************************************/ +void make_dom_sid3(DOM_SID3 *sid3, uint16 unk_0, uint16 unk_1, char *sid) +{ + if (sid3 == NULL) return; + + make_dom_sid(&(sid3->sid), sid); + sid3->len = 2 + 8 + sid3->sid.num_auths * 4; +} + +/******************************************************************* +reads or writes a SAM_SID3 structure. + +this one's odd, because the length (in bytes) is specified at the beginning. +the length _includes_ the length of the length, too :-) + +********************************************************************/ +void sam_io_dom_sid3(char *desc, DOM_SID3 *sid3, prs_struct *ps, int depth) +{ + if (sid3 == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_dom_sid3"); + depth++; + + prs_uint16("len", ps, depth, &(sid3->len)); + prs_align(ps); + smb_io_dom_sid("", &(sid3->sid), ps, depth); +} + +/******************************************************************* +makes a SAMR_R_UNKNOWN3 structure. + +unknown_2 : 0x0001 +unknown_3 : 0x8004 + +unknown_4,5 : 0x0000 0014 + +unknown_6 : 0x0002 +unknown_7 : 0x5800 or 0x0070 + +********************************************************************/ +void make_sam_sid_stuff(SAM_SID_STUFF *stf, + uint16 unknown_2, uint16 unknown_3, + uint32 unknown_4, uint16 unknown_6, uint16 unknown_7, + int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS]) +{ + stf->unknown_2 = unknown_2; + stf->unknown_3 = unknown_3; + + bzero(stf->padding1, sizeof(stf->padding1)); + + stf->unknown_4 = unknown_4; + stf->unknown_5 = unknown_4; + + stf->unknown_6 = unknown_6; + stf->unknown_7 = unknown_7; + + stf->num_sids = num_sid3s; + + stf->padding2 = 0x0000; + + memcpy(stf->sid, sid3, sizeof(DOM_SID3) * num_sid3s); +} + +/******************************************************************* +reads or writes a SAM_SID_STUFF structure. +********************************************************************/ +void sam_io_sid_stuff(char *desc, SAM_SID_STUFF *stf, prs_struct *ps, int depth) +{ + int i; + + if (stf == NULL) return; + + DEBUG(5,("make_sam_sid_stuff\n")); + + prs_uint16("unknown_2", ps, depth, &(stf->unknown_2)); + prs_uint16("unknown_3", ps, depth, &(stf->unknown_3)); + + prs_uint8s(False, "padding1", ps, depth, stf->padding1, sizeof(stf->padding1)); + + prs_uint32("unknown_4", ps, depth, &(stf->unknown_4)); + prs_uint32("unknown_5", ps, depth, &(stf->unknown_5)); + prs_uint16("unknown_6", ps, depth, &(stf->unknown_6)); + prs_uint16("unknown_7", ps, depth, &(stf->unknown_7)); + + prs_uint32("num_sids ", ps, depth, &(stf->num_sids )); + prs_uint16("padding2 ", ps, depth, &(stf->padding2 )); + + for (i = 0; i < stf->num_sids; i++) + { + sam_io_dom_sid3("", &(stf->sid[i]), ps, depth); + } +} + +/******************************************************************* +reads or writes a SAMR_R_UNKNOWN3 structure. +********************************************************************/ +void make_samr_r_unknown_3(SAMR_R_UNKNOWN_3 *r_u, + uint16 unknown_2, uint16 unknown_3, + uint32 unknown_4, uint16 unknown_6, uint16 unknown_7, + int num_sid3s, DOM_SID3 sid3[MAX_SAM_SIDS], + uint32 status) +{ + if (r_u == NULL) return; + + DEBUG(5,("samr_make_r_unknown_3\n")); + + r_u->ptr_0 = 0; + r_u->ptr_1 = 0; + + if (status == 0x0) + { + r_u->ptr_0 = 1; + r_u->ptr_1 = 1; + make_sam_sid_stuff(&(r_u->sid_stuff), unknown_2, unknown_3, + unknown_4, unknown_6, unknown_7, + num_sid3s, sid3); + } + + r_u->status = status; +} + + +/******************************************************************* +reads or writes a SAMR_R_UNKNOWN_3 structure. + +this one's odd, because the daft buggers use a different mechanism +for writing out the array of sids. they put the number of sids in +only one place: they've calculated the length of each sid and jumped +by that amount. then, retrospectively, the length of the whole buffer +is put at the beginning of the data stream. + +wierd. + +********************************************************************/ +void samr_io_r_unknown_3(char *desc, SAMR_R_UNKNOWN_3 *r_u, prs_struct *ps, int depth) +{ + int ptr_len0; + int ptr_len1; + int ptr_sid_stuff = 0; + + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_unknown_3"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_0 ", ps, depth, &(r_u->ptr_0 )); + + if (ps->io) + { + /* reading. do the length later */ + prs_uint32("sid_stuff_len0", ps, depth, &(r_u->sid_stuff_len0)); + } + else + { + /* storing */ + ptr_len0 = ps->offset; ps->offset += 4; + } + + if (r_u->ptr_0 != 0) + { + prs_uint32("ptr_1 ", ps, depth, &(r_u->ptr_1 )); + if (ps->io) + { + /* reading. do the length later */ + prs_uint32("sid_stuff_len1", ps, depth, &(r_u->sid_stuff_len1)); + } + else + { + /* storing */ + ptr_len1 = ps->offset; ps->offset += 4; + } + + if (r_u->ptr_1 != 0) + { + ptr_sid_stuff = ps->offset; + sam_io_sid_stuff("", &(r_u->sid_stuff), ps, depth); + } + } + + if (!(ps->io)) /* storing not reading. do the length, now. */ + { + if (ptr_sid_stuff != 0) + { + uint32 sid_stuff_len = ps->offset - ptr_sid_stuff; + int old_len = ps->offset; + + ps->offset = ptr_len0; + prs_uint32("sid_stuff_len0", ps, depth, &sid_stuff_len); + + ps->offset = ptr_len1; + prs_uint32("sid_stuff_len1", ps, depth, &sid_stuff_len); + + ps->offset = old_len; + } + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +makes a SAM_STR1 structure. +********************************************************************/ +void make_sam_str1(SAM_STR1 *sam, char *sam_acct, char *sam_name, char *sam_desc) +{ + int len_sam_acct = sam_acct != NULL ? strlen(sam_acct) : 0; + int len_sam_name = sam_name != NULL ? strlen(sam_name) : 0; + int len_sam_desc = sam_desc != NULL ? strlen(sam_desc) : 0; + + if (sam == NULL) return; + + DEBUG(5,("make_sam_str1: %d\n", __LINE__)); + + make_unistr2(&(sam->uni_acct_name), sam_acct, len_sam_acct); + make_unistr2(&(sam->uni_full_name), sam_name, len_sam_name); + make_unistr2(&(sam->uni_acct_desc), sam_desc, len_sam_desc); +} + +/******************************************************************* +reads or writes a SAM_STR1 structure. +********************************************************************/ +void sam_io_sam_str1(char *desc, SAM_STR1 *sam, uint32 acct_buf, uint32 name_buf, uint32 desc_buf, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_str1"); + depth++; + + prs_align(ps); + + smb_io_unistr2("unistr2", &(sam->uni_acct_name), acct_buf, ps, depth); /* account name unicode string */ + smb_io_unistr2("unistr2", &(sam->uni_full_name), name_buf, ps, depth); /* full name unicode string */ + smb_io_unistr2("unistr2", &(sam->uni_acct_desc), desc_buf, ps, depth); /* account description unicode string */ +} + +/******************************************************************* +makes a SAM_ENTRY1 structure. +********************************************************************/ +void make_sam_entry1(SAM_ENTRY1 *sam, uint32 user_idx, + uint32 len_sam_name, uint32 len_sam_full, uint32 len_sam_desc, + uint32 rid_user, uint16 acb_info) +{ + if (sam == NULL) return; + + DEBUG(5,("make_sam_entry2: %d\n", __LINE__)); + + sam->user_idx = user_idx; + sam->rid_user = rid_user; + sam->acb_info = acb_info; + sam->pad = 0; + + make_uni_hdr(&(sam->hdr_acct_name), len_sam_name, len_sam_name, len_sam_name != 0); + make_uni_hdr(&(sam->hdr_user_name), len_sam_full, len_sam_full, len_sam_full != 0); + make_uni_hdr(&(sam->hdr_user_desc), len_sam_desc, len_sam_desc, len_sam_desc != 0); +} + +/******************************************************************* +reads or writes a SAM_ENTRY1 structure. +********************************************************************/ +void sam_io_sam_entry1(char *desc, SAM_ENTRY1 *sam, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_entry2"); + depth++; + + prs_align(ps); + + prs_uint32("user_idx ", ps, depth, &(sam->user_idx )); + + prs_uint32("rid_user ", ps, depth, &(sam->rid_user )); + prs_uint16("acb_info ", ps, depth, &(sam->acb_info )); + prs_uint16("pad ", ps, depth, &(sam->pad )); + + smb_io_unihdr("unihdr", &(sam->hdr_acct_name), ps, depth); /* account name unicode string header */ + smb_io_unihdr("unihdr", &(sam->hdr_user_name), ps, depth); /* account name unicode string header */ + smb_io_unihdr("unihdr", &(sam->hdr_user_desc), ps, depth); /* account name unicode string header */ +} + +/******************************************************************* +makes a SAM_STR2 structure. +********************************************************************/ +void make_sam_str2(SAM_STR2 *sam, char *sam_acct, char *sam_desc) +{ + int len_sam_acct = sam_acct != NULL ? strlen(sam_acct) : 0; + int len_sam_desc = sam_desc != NULL ? strlen(sam_desc) : 0; + + if (sam == NULL) return; + + DEBUG(5,("make_sam_str2: %d\n", __LINE__)); + + make_unistr2(&(sam->uni_srv_name), sam_acct, len_sam_acct); + make_unistr2(&(sam->uni_srv_desc), sam_desc, len_sam_desc); +} + +/******************************************************************* +reads or writes a SAM_STR2 structure. +********************************************************************/ +void sam_io_sam_str2(char *desc, SAM_STR2 *sam, uint32 acct_buf, uint32 desc_buf, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_str2"); + depth++; + + prs_align(ps); + + smb_io_unistr2("unistr2", &(sam->uni_srv_name), acct_buf, ps, depth); /* account name unicode string */ + smb_io_unistr2("unistr2", &(sam->uni_srv_desc), desc_buf, ps, depth); /* account description unicode string */ +} + +/******************************************************************* +makes a SAM_ENTRY2 structure. +********************************************************************/ +void make_sam_entry2(SAM_ENTRY2 *sam, uint32 user_idx, + uint32 len_sam_name, uint32 len_sam_desc, + uint32 rid_user, uint16 acb_info) +{ + if (sam == NULL) return; + + DEBUG(5,("make_sam_entry2: %d\n", __LINE__)); + + sam->user_idx = user_idx; + sam->rid_user = rid_user; + sam->acb_info = acb_info; + sam->pad = 0; + + make_uni_hdr(&(sam->hdr_srv_name), len_sam_name, len_sam_name, len_sam_name != 0); + make_uni_hdr(&(sam->hdr_srv_desc), len_sam_desc, len_sam_desc, len_sam_desc != 0); +} + +/******************************************************************* +reads or writes a SAM_ENTRY2 structure. +********************************************************************/ +void sam_io_sam_entry2(char *desc, SAM_ENTRY2 *sam, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_entry2"); + depth++; + + prs_align(ps); + + prs_uint32("user_idx ", ps, depth, &(sam->user_idx )); + + prs_uint32("rid_user ", ps, depth, &(sam->rid_user )); + prs_uint16("acb_info ", ps, depth, &(sam->acb_info )); + prs_uint16("pad ", ps, depth, &(sam->pad )); + + smb_io_unihdr("unihdr", &(sam->hdr_srv_name), ps, depth); /* account name unicode string header */ + smb_io_unihdr("unihdr", &(sam->hdr_srv_desc), ps, depth); /* account name unicode string header */ +} + +/******************************************************************* +makes a SAM_STR3 structure. +********************************************************************/ +void make_sam_str3(SAM_STR3 *sam, char *grp_acct, char *grp_desc) +{ + int len_grp_acct = strlen(grp_acct); + int len_grp_desc = strlen(grp_desc); + + if (sam == NULL) return; + + DEBUG(5,("make_sam_str3: %d\n", __LINE__)); + + make_unistr2(&(sam->uni_grp_name), grp_acct, len_grp_acct); + make_unistr2(&(sam->uni_grp_desc), grp_desc, len_grp_desc); +} + +/******************************************************************* +reads or writes a SAM_STR3 structure. +********************************************************************/ +void sam_io_sam_str3(char *desc, SAM_STR3 *sam, uint32 acct_buf, uint32 desc_buf, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_str3"); + depth++; + + prs_align(ps); + + smb_io_unistr2("unistr2", &(sam->uni_grp_name), acct_buf, ps, depth); /* account name unicode string */ + smb_io_unistr2("unistr2", &(sam->uni_grp_desc), desc_buf, ps, depth); /* account description unicode string */ +} + +/******************************************************************* +makes a SAM_ENTRY3 structure. +********************************************************************/ +void make_sam_entry3(SAM_ENTRY3 *sam, uint32 grp_idx, + uint32 len_grp_name, uint32 len_grp_desc, uint32 rid_grp) +{ + if (sam == NULL) return; + + DEBUG(5,("make_sam_entry3: %d\n", __LINE__)); + + sam->grp_idx = grp_idx; + sam->rid_grp = rid_grp; + sam->attr = 0x07; /* group rid attributes - gets ignored by nt 4.0 */ + + make_uni_hdr(&(sam->hdr_grp_name), len_grp_name, len_grp_name, len_grp_name != 0); + make_uni_hdr(&(sam->hdr_grp_desc), len_grp_desc, len_grp_desc, len_grp_desc != 0); +} + +/******************************************************************* +reads or writes a SAM_ENTRY3 structure. +********************************************************************/ +void sam_io_sam_entry3(char *desc, SAM_ENTRY3 *sam, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_entry3"); + depth++; + + prs_align(ps); + + prs_uint32("grp_idx", ps, depth, &(sam->grp_idx)); + + prs_uint32("rid_grp", ps, depth, &(sam->rid_grp)); + prs_uint32("attr ", ps, depth, &(sam->attr )); + + smb_io_unihdr("unihdr", &(sam->hdr_grp_name), ps, depth); /* account name unicode string header */ + smb_io_unihdr("unihdr", &(sam->hdr_grp_desc), ps, depth); /* account name unicode string header */ +} + +/******************************************************************* +makes a SAM_ENTRY structure. +********************************************************************/ +void make_sam_entry(SAM_ENTRY *sam, uint32 len_sam_name, uint32 rid) +{ + if (sam == NULL) return; + + DEBUG(5,("make_sam_entry: %d\n", __LINE__)); + + sam->rid = rid; + make_uni_hdr(&(sam->hdr_name), len_sam_name, len_sam_name, len_sam_name != 0); +} + +/******************************************************************* +reads or writes a SAM_ENTRY structure. +********************************************************************/ +void sam_io_sam_entry(char *desc, SAM_ENTRY *sam, prs_struct *ps, int depth) +{ + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_entry"); + depth++; + + prs_align(ps); + prs_uint32("rid", ps, depth, &(sam->rid )); + smb_io_unihdr("unihdr", &(sam->hdr_name), ps, depth); /* account name unicode string header */ +} + +/******************************************************************* +makes a SAMR_Q_ENUM_DOM_USERS structure. +********************************************************************/ +void make_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_e, POLICY_HND *pol, + uint16 req_num_entries, uint16 unk_0, + uint16 acb_mask, uint16 unk_1, uint32 size) +{ + if (q_e == NULL || pol == NULL) return; + + DEBUG(5,("make_q_enum_dom_users\n")); + + memcpy(&(q_e->pol), pol, sizeof(*pol)); + + q_e->req_num_entries = req_num_entries; /* zero indicates lots */ + q_e->unknown_0 = unk_0; /* this gets returned in the response */ + q_e->acb_mask = acb_mask; + q_e->unknown_1 = unk_1; + q_e->max_size = size; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_enum_dom_users(char *desc, SAMR_Q_ENUM_DOM_USERS *q_e, prs_struct *ps, int depth) +{ + if (q_e == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_enum_dom_users"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); + prs_align(ps); + + prs_uint16("req_num_entries", ps, depth, &(q_e->req_num_entries)); + prs_uint16("unknown_0 ", ps, depth, &(q_e->unknown_0 )); + + prs_uint16("acb_mask ", ps, depth, &(q_e->acb_mask )); + prs_uint16("unknown_1 ", ps, depth, &(q_e->unknown_1 )); + + prs_uint32("max_size ", ps, depth, &(q_e->max_size )); + + prs_align(ps); +} + + +/******************************************************************* +makes a SAMR_R_ENUM_DOM_USERS structure. +********************************************************************/ +void make_samr_r_enum_dom_users(SAMR_R_ENUM_DOM_USERS *r_u, + uint16 total_num_entries, uint16 unk_0, + uint32 num_sam_entries, SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], uint32 status) +{ + int i; + + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_enum_dom_users\n")); + + if (num_sam_entries >= MAX_SAM_ENTRIES) + { + num_sam_entries = MAX_SAM_ENTRIES; + DEBUG(5,("limiting number of entries to %d %s\n", num_sam_entries)); + } + + r_u->total_num_entries = total_num_entries; + r_u->unknown_0 = unk_0; + + if (total_num_entries > 0) + { + r_u->ptr_entries1 = 1; + r_u->ptr_entries2 = 1; + r_u->num_entries2 = num_sam_entries; + r_u->num_entries3 = num_sam_entries; + + for (i = 0; i < num_sam_entries; i++) + { + make_sam_entry(&(r_u->sam[i]), + pass[i].uni_user_name.uni_str_len, + pass[i].user_rid); + + copy_unistr2(&(r_u->uni_acct_name[i]), &(pass[i].uni_user_name)); + } + + r_u->num_entries4 = num_sam_entries; + } + else + { + r_u->ptr_entries1 = 0; + r_u->num_entries2 = num_sam_entries; + r_u->ptr_entries2 = 1; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_enum_dom_users(char *desc, SAMR_R_ENUM_DOM_USERS *r_u, prs_struct *ps, int depth) +{ + int i; + + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_enum_dom_users"); + depth++; + + prs_align(ps); + + prs_uint16("total_num_entries", ps, depth, &(r_u->total_num_entries)); + prs_uint16("unknown_0 ", ps, depth, &(r_u->unknown_0 )); + prs_uint32("ptr_entries1", ps, depth, &(r_u->ptr_entries1)); + + if (r_u->total_num_entries != 0 && r_u->ptr_entries1 != 0) + { + prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2)); + prs_uint32("ptr_entries2", ps, depth, &(r_u->ptr_entries2)); + prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3)); + + for (i = 0; i < r_u->num_entries2; i++) + { + prs_grow(ps); + sam_io_sam_entry("", &(r_u->sam[i]), ps, depth); + } + + for (i = 0; i < r_u->num_entries2; i++) + { + prs_grow(ps); + smb_io_unistr2("", &(r_u->uni_acct_name[i]), r_u->sam[i].hdr_name.buffer, ps, depth); + } + + prs_align(ps); + + prs_uint32("num_entries4", ps, depth, &(r_u->num_entries4)); + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +makes a SAMR_Q_ENUM_DOM_ALIASES structure. +********************************************************************/ +void make_samr_q_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_e, POLICY_HND *pol, uint32 size) +{ + if (q_e == NULL || pol == NULL) return; + + DEBUG(5,("make_q_enum_dom_aliases\n")); + + memcpy(&(q_e->pol), pol, sizeof(*pol)); + + q_e->unknown_0 = 0; + q_e->max_size = size; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_enum_dom_aliases(char *desc, SAMR_Q_ENUM_DOM_ALIASES *q_e, prs_struct *ps, int depth) +{ + if (q_e == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_enum_dom_aliases"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); + prs_align(ps); + + prs_uint32("unknown_0", ps, depth, &(q_e->unknown_0)); + prs_uint32("max_size ", ps, depth, &(q_e->max_size )); + + prs_align(ps); +} + + +/******************************************************************* +makes a SAMR_R_ENUM_DOM_ALIASES structure. +********************************************************************/ +void make_samr_r_enum_dom_aliases(SAMR_R_ENUM_DOM_ALIASES *r_u, + uint32 num_sam_entries, SAM_USER_INFO_21 grps[MAX_SAM_ENTRIES], + uint32 status) +{ + int i; + + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_enum_dom_aliases\n")); + + if (num_sam_entries >= MAX_SAM_ENTRIES) + { + num_sam_entries = MAX_SAM_ENTRIES; + DEBUG(5,("limiting number of entries to %d %s\n", num_sam_entries)); + } + + r_u->num_entries = num_sam_entries; + + if (num_sam_entries > 0) + { + r_u->ptr_entries = 1; + r_u->num_entries2 = num_sam_entries; + r_u->ptr_entries2 = 1; + r_u->num_entries3 = num_sam_entries; + + for (i = 0; i < num_sam_entries; i++) + { + make_sam_entry(&(r_u->sam[i]), + grps[i].uni_user_name.uni_str_len, + grps[i].user_rid); + + copy_unistr2(&(r_u->uni_grp_name[i]), &(grps[i].uni_user_name)); + } + + r_u->num_entries4 = num_sam_entries; + } + else + { + r_u->ptr_entries = 0; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_enum_dom_aliases(char *desc, SAMR_R_ENUM_DOM_ALIASES *r_u, prs_struct *ps, int depth) +{ + int i; + + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_enum_dom_aliases"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries", ps, depth, &(r_u->num_entries)); + prs_uint32("ptr_entries", ps, depth, &(r_u->ptr_entries)); + + if (r_u->num_entries != 0 && r_u->ptr_entries != 0) + { + prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2)); + prs_uint32("ptr_entries2", ps, depth, &(r_u->ptr_entries2)); + prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3)); + + for (i = 0; i < r_u->num_entries; i++) + { + sam_io_sam_entry("", &(r_u->sam[i]), ps, depth); + } + + for (i = 0; i < r_u->num_entries; i++) + { + smb_io_unistr2("", &(r_u->uni_grp_name[i]), r_u->sam[i].hdr_name.buffer, ps, depth); + } + + prs_align(ps); + + prs_uint32("num_entries4", ps, depth, &(r_u->num_entries4)); + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +makes a SAMR_Q_QUERY_DISPINFO structure. +********************************************************************/ +void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol, + uint16 switch_level, uint32 start_idx, uint32 size) +{ + if (q_e == NULL || pol == NULL) return; + + DEBUG(5,("make_q_query_dispinfo\n")); + + memcpy(&(q_e->pol), pol, sizeof(*pol)); + + q_e->switch_level = switch_level; + + q_e->unknown_0 = 0; + q_e->start_idx = start_idx; + q_e->unknown_1 = 0x000007d0; + q_e->max_size = size; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_query_dispinfo(char *desc, SAMR_Q_QUERY_DISPINFO *q_e, prs_struct *ps, int depth) +{ + if (q_e == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_query_dispinfo"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); + prs_align(ps); + + prs_uint16("switch_level", ps, depth, &(q_e->switch_level)); + prs_uint16("unknown_0 ", ps, depth, &(q_e->unknown_0 )); + prs_uint32("start_idx ", ps, depth, &(q_e->start_idx )); + prs_uint32("unknown_1 ", ps, depth, &(q_e->unknown_1 )); + prs_uint32("max_size ", ps, depth, &(q_e->max_size )); + + prs_align(ps); +} + + +/******************************************************************* +makes a SAM_INFO_2 structure. +********************************************************************/ +void make_sam_info_2(SAM_INFO_2 *sam, uint32 acb_mask, + uint32 start_idx, uint32 num_sam_entries, + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]) +{ + int i; + int entries_added; + + if (sam == NULL) return; + + DEBUG(5,("make_sam_info_2\n")); + + if (num_sam_entries >= MAX_SAM_ENTRIES) + { + num_sam_entries = MAX_SAM_ENTRIES; + DEBUG(5,("limiting number of entries to %d %s\n", num_sam_entries)); + } + + for (i = start_idx, entries_added = 0; i < num_sam_entries; i++) + { + if (IS_BITS_SET_ALL(pass[i].acb_info, acb_mask)) + { + make_sam_entry2(&(sam->sam[entries_added]), + start_idx + entries_added + 1, + pass[i].uni_user_name.uni_str_len, + pass[i].uni_acct_desc.uni_str_len, + pass[i].user_rid, + pass[i].acb_info); + + copy_unistr2(&(sam->str[entries_added].uni_srv_name), &(pass[i].uni_user_name)); + copy_unistr2(&(sam->str[entries_added].uni_srv_desc), &(pass[i].uni_acct_desc)); + + entries_added++; + } + + sam->num_entries = entries_added; + sam->ptr_entries = 1; + sam->num_entries2 = entries_added; + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void sam_io_sam_info_2(char *desc, SAM_INFO_2 *sam, prs_struct *ps, int depth) +{ + int i; + + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_info_2"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries ", ps, depth, &(sam->num_entries )); + prs_uint32("ptr_entries ", ps, depth, &(sam->ptr_entries )); + + prs_uint32("num_entries2 ", ps, depth, &(sam->num_entries2 )); + + for (i = 0; i < sam->num_entries; i++) + { + sam_io_sam_entry2("", &(sam->sam[i]), ps, depth); + } + + for (i = 0; i < sam->num_entries; i++) + { + sam_io_sam_str2 ("", &(sam->str[i]), + sam->sam[i].hdr_srv_name.buffer, + sam->sam[i].hdr_srv_desc.buffer, + ps, depth); + } +} + + +/******************************************************************* +makes a SAM_INFO_1 structure. +********************************************************************/ +void make_sam_info_1(SAM_INFO_1 *sam, uint32 acb_mask, + uint32 start_idx, uint32 num_sam_entries, + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]) +{ + int i; + int entries_added; + + if (sam == NULL) return; + + DEBUG(5,("make_sam_info_1\n")); + + if (num_sam_entries >= MAX_SAM_ENTRIES) + { + num_sam_entries = MAX_SAM_ENTRIES; + DEBUG(5,("limiting number of entries to %d %s\n", num_sam_entries)); + } + + for (i = start_idx, entries_added = 0; i < num_sam_entries; i++) + { + if (IS_BITS_SET_ALL(pass[i].acb_info, acb_mask)) + { + make_sam_entry1(&(sam->sam[entries_added]), + start_idx + entries_added + 1, + pass[i].uni_user_name.uni_str_len, + pass[i].uni_full_name.uni_str_len, + pass[i].uni_acct_desc.uni_str_len, + pass[i].user_rid, + pass[i].acb_info); + + copy_unistr2(&(sam->str[entries_added].uni_acct_name), &(pass[i].uni_user_name)); + copy_unistr2(&(sam->str[entries_added].uni_full_name), &(pass[i].uni_full_name)); + copy_unistr2(&(sam->str[entries_added].uni_acct_desc), &(pass[i].uni_acct_desc)); + + entries_added++; + } + } + + sam->num_entries = entries_added; + sam->ptr_entries = 1; + sam->num_entries2 = entries_added; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void sam_io_sam_info_1(char *desc, SAM_INFO_1 *sam, prs_struct *ps, int depth) +{ + int i; + + if (sam == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_sam_info_1"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries ", ps, depth, &(sam->num_entries )); + prs_uint32("ptr_entries ", ps, depth, &(sam->ptr_entries )); + + prs_uint32("num_entries2 ", ps, depth, &(sam->num_entries2 )); + + for (i = 0; i < sam->num_entries; i++) + { + sam_io_sam_entry1("", &(sam->sam[i]), ps, depth); + } + + for (i = 0; i < sam->num_entries; i++) + { + sam_io_sam_str1 ("", &(sam->str[i]), + sam->sam[i].hdr_acct_name.buffer, + sam->sam[i].hdr_user_name.buffer, + sam->sam[i].hdr_user_desc.buffer, + ps, depth); + } +} + + +/******************************************************************* +makes a SAMR_R_QUERY_DISPINFO structure. +********************************************************************/ +void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u, + uint16 switch_level, SAM_INFO_CTR *ctr, uint32 status) +{ + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_query_dispinfo\n")); + + if (status == 0x0) + { + r_u->unknown_0 = 0x0000001; + r_u->unknown_1 = 0x0000001; + } + else + { + r_u->unknown_0 = 0x0; + r_u->unknown_1 = 0x0; + } + + r_u->switch_level = switch_level; + r_u->ctr = ctr; + r_u->status = status; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_query_dispinfo(char *desc, SAMR_R_QUERY_DISPINFO *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_query_dispinfo"); + depth++; + + prs_align(ps); + + prs_uint32("unknown_0 ", ps, depth, &(r_u->unknown_0 )); + prs_uint32("unknown_1 ", ps, depth, &(r_u->unknown_1 )); + prs_uint16("switch_level ", ps, depth, &(r_u->switch_level )); + + prs_align(ps); + + switch (r_u->switch_level) + { + case 0x1: + { + sam_io_sam_info_1("users", r_u->ctr->sam.info1, ps, depth); + break; + } + case 0x2: + { + sam_io_sam_info_2("servers", r_u->ctr->sam.info2, ps, depth); + break; + } + default: + { + DEBUG(5,("samr_io_r_query_dispinfo: unknown switch value\n")); + break; + } + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +makes a SAMR_Q_ENUM_DOM_GROUPS structure. +********************************************************************/ +void make_samr_q_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_e, POLICY_HND *pol, + uint16 switch_level, uint32 start_idx, uint32 size) +{ + if (q_e == NULL || pol == NULL) return; + + DEBUG(5,("make_q_enum_dom_groups\n")); + + memcpy(&(q_e->pol), pol, sizeof(*pol)); + + q_e->switch_level = switch_level; + + q_e->unknown_0 = 0; + q_e->start_idx = start_idx; + q_e->unknown_1 = 0x000007d0; + q_e->max_size = size; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_enum_dom_groups(char *desc, SAMR_Q_ENUM_DOM_GROUPS *q_e, prs_struct *ps, int depth) +{ + if (q_e == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_enum_dom_groups"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); + prs_align(ps); + + prs_uint16("switch_level", ps, depth, &(q_e->switch_level)); + prs_uint16("unknown_0 ", ps, depth, &(q_e->unknown_0 )); + prs_uint32("start_idx ", ps, depth, &(q_e->start_idx )); + prs_uint32("unknown_1 ", ps, depth, &(q_e->unknown_1 )); + prs_uint32("max_size ", ps, depth, &(q_e->max_size )); + + prs_align(ps); +} + + +/******************************************************************* +makes a SAMR_R_ENUM_DOM_GROUPS structure. +********************************************************************/ +void make_samr_r_enum_dom_groups(SAMR_R_ENUM_DOM_GROUPS *r_u, + uint32 start_idx, uint32 num_sam_entries, + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], + uint32 status) +{ + int i; + int entries_added; + + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_enum_dom_groups\n")); + + if (num_sam_entries >= MAX_SAM_ENTRIES) + { + num_sam_entries = MAX_SAM_ENTRIES; + DEBUG(5,("limiting number of entries to %d %s\n", num_sam_entries)); + } + + if (status == 0x0) + { + for (i = start_idx, entries_added = 0; i < num_sam_entries; i++) + { + make_sam_entry3(&(r_u->sam[entries_added]), + start_idx + entries_added + 1, + pass[i].uni_user_name.uni_str_len, + pass[i].uni_acct_desc.uni_str_len, + pass[i].user_rid); + + copy_unistr2(&(r_u->str[entries_added].uni_grp_name), &(pass[i].uni_user_name)); + copy_unistr2(&(r_u->str[entries_added].uni_grp_desc), &(pass[i].uni_acct_desc)); + + entries_added++; + } + + if (entries_added > 0) + { + r_u->unknown_0 = 0x0000492; + r_u->unknown_1 = 0x000049a; + } + else + { + r_u->unknown_0 = 0x0; + r_u->unknown_1 = 0x0; + } + r_u->switch_level = 3; + r_u->num_entries = entries_added; + r_u->ptr_entries = 1; + r_u->num_entries2 = entries_added; + } + else + { + r_u->switch_level = 0; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_enum_dom_groups(char *desc, SAMR_R_ENUM_DOM_GROUPS *r_u, prs_struct *ps, int depth) +{ + int i; + + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_enum_dom_groups"); + depth++; + + prs_align(ps); + + prs_uint32("unknown_0 ", ps, depth, &(r_u->unknown_0 )); + prs_uint32("unknown_1 ", ps, depth, &(r_u->unknown_1 )); + prs_uint32("switch_level ", ps, depth, &(r_u->switch_level )); + + if (r_u->switch_level != 0) + { + prs_uint32("num_entries ", ps, depth, &(r_u->num_entries )); + prs_uint32("ptr_entries ", ps, depth, &(r_u->ptr_entries )); + + prs_uint32("num_entries2 ", ps, depth, &(r_u->num_entries2 )); + + for (i = 0; i < r_u->num_entries; i++) + { + sam_io_sam_entry3("", &(r_u->sam[i]), ps, depth); + } + + for (i = 0; i < r_u->num_entries; i++) + { + sam_io_sam_str3 ("", &(r_u->str[i]), + r_u->sam[i].hdr_grp_name.buffer, + r_u->sam[i].hdr_grp_desc.buffer, + ps, depth); + } + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +makes a SAMR_Q_QUERY_ALIASINFO structure. +********************************************************************/ +void make_samr_q_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_e, + POLICY_HND *pol, + uint16 switch_level) +{ + if (q_e == NULL || pol == NULL) return; + + DEBUG(5,("make_q_query_aliasinfo\n")); + + memcpy(&(q_e->pol), pol, sizeof(*pol)); + + q_e->switch_level = switch_level; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_query_aliasinfo(char *desc, SAMR_Q_QUERY_ALIASINFO *q_e, prs_struct *ps, int depth) +{ + if (q_e == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_query_aliasinfo"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_e->pol), ps, depth); + prs_align(ps); + + prs_uint16("switch_level", ps, depth, &(q_e->switch_level)); +} + + +/******************************************************************* +makes a SAMR_R_QUERY_ALIASINFO structure. +********************************************************************/ +void make_samr_r_query_aliasinfo(SAMR_R_QUERY_ALIASINFO *r_u, + uint16 switch_value, char *acct_desc, + uint32 status) +{ + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_query_aliasinfo\n")); + + r_u->ptr = 0; + + if (status == 0) + { + r_u->switch_value = switch_value; + + switch (switch_value) + { + case 3: + { + int acct_len = acct_desc ? strlen(acct_desc) : 0; + + r_u->ptr = 1; + + make_uni_hdr(&(r_u->alias.info3.hdr_acct_desc), acct_len , acct_len, acct_desc ? 1 : 0); + make_unistr2(&(r_u->alias.info3.uni_acct_desc), acct_desc, acct_len); + + break; + } + + default: + { + DEBUG(4,("make_samr_r_query_aliasinfo: unsupported switch level\n")); + break; + } + } + } + + r_u->status = status; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_query_aliasinfo(char *desc, SAMR_R_QUERY_ALIASINFO *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_query_aliasinfo"); + depth++; + + prs_align(ps); + + prs_uint32("ptr ", ps, depth, &(r_u->ptr )); + + if (r_u->ptr != 0) + { + prs_uint16("switch_value", ps, depth, &(r_u->switch_value)); + prs_align(ps); + + if (r_u->switch_value != 0) + { + switch (r_u->switch_value) + { + case 3: + { + smb_io_unihdr ("", &(r_u->alias.info3.hdr_acct_desc), ps, depth); + smb_io_unistr2("", &(r_u->alias.info3.uni_acct_desc), r_u->alias.info3.hdr_acct_desc.buffer, ps, depth); + break; + } + default: + { + DEBUG(4,("samr_io_r_query_aliasinfo: unsupported switch level\n")); + break; + } + } + } + } + + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +reads or writes a SAMR_Q_LOOKUP_IDS structure. +********************************************************************/ +void samr_io_q_lookup_ids(char *desc, SAMR_Q_LOOKUP_IDS *q_u, prs_struct *ps, int depth) +{ + fstring tmp; + int i; + + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_lookup_ids"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("num_sids1", ps, depth, &(q_u->num_sids1)); + prs_uint32("ptr ", ps, depth, &(q_u->ptr )); + prs_uint32("num_sids2", ps, depth, &(q_u->num_sids2)); + + for (i = 0; i < q_u->num_sids2; i++) + { + sprintf(tmp, "ptr[%02d]", i); + prs_uint32(tmp, ps, depth, &(q_u->ptr_sid[i])); + } + + for (i = 0; i < q_u->num_sids2; i++) + { + if (q_u->ptr_sid[i] != 0) + { + sprintf(tmp, "sid[%02d]", i); + smb_io_dom_sid2(tmp, &(q_u->sid[i]), ps, depth); + } + } + + prs_align(ps); +} + + +/******************************************************************* +makes a SAMR_R_LOOKUP_IDS structure. +********************************************************************/ +void make_samr_r_lookup_ids(SAMR_R_LOOKUP_IDS *r_u, + uint32 num_rids, uint32 *rid, uint32 status) +{ + int i; + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_lookup_ids\n")); + + if (status == 0x0) + { + r_u->num_entries = num_rids; + r_u->ptr = 1; + r_u->num_entries2 = num_rids; + + for (i = 0; i < num_rids; i++) + { + r_u->rid[i] = rid[i]; + } + } + else + { + r_u->num_entries = 0; + r_u->ptr = 0; + r_u->num_entries2 = 0; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_lookup_ids(char *desc, SAMR_R_LOOKUP_IDS *r_u, prs_struct *ps, int depth) +{ + fstring tmp; + int i; + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_lookup_ids"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries", ps, depth, &(r_u->num_entries)); + prs_uint32("ptr ", ps, depth, &(r_u->ptr )); + prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2)); + + if (r_u->num_entries != 0) + { + + for (i = 0; i < r_u->num_entries2; i++) + { + sprintf(tmp, "rid[%02d]", i); + prs_uint32(tmp, ps, depth, &(r_u->rid[i])); + } + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_lookup_names(char *desc, SAMR_Q_LOOKUP_NAMES *q_u, prs_struct *ps, int depth) +{ + int i; + + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_lookup_names"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("num_rids1", ps, depth, &(q_u->num_rids1)); + prs_uint32("rid ", ps, depth, &(q_u->rid )); + prs_uint32("ptr ", ps, depth, &(q_u->ptr )); + prs_uint32("num_rids2", ps, depth, &(q_u->num_rids2)); + + for (i = 0; i < q_u->num_rids2; i++) + { + smb_io_unihdr ("", &(q_u->hdr_user_name[i]), ps, depth); + } + for (i = 0; i < q_u->num_rids2; i++) + { + smb_io_unistr2("", &(q_u->uni_user_name[i]), q_u->hdr_user_name[i].buffer, ps, depth); + } + + prs_align(ps); +} + + +/******************************************************************* +makes a SAMR_R_LOOKUP_NAMES structure. +********************************************************************/ +void make_samr_r_lookup_names(SAMR_R_LOOKUP_NAMES *r_u, + uint32 num_rids, uint32 *rid, uint32 status) +{ + int i; + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_lookup_names\n")); + + if (status == 0x0) + { + r_u->num_entries = num_rids; + r_u->undoc_buffer = 1; + r_u->num_entries2 = num_rids; + + for (i = 0; i < num_rids; i++) + { + make_dom_rid3(&(r_u->dom_rid[i]), rid[i]); + } + + r_u->num_entries3 = num_rids; + } + else + { + r_u->num_entries = 0; + r_u->undoc_buffer = 0; + r_u->num_entries2 = 0; + r_u->num_entries3 = 0; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_lookup_names(char *desc, SAMR_R_LOOKUP_NAMES *r_u, prs_struct *ps, int depth) +{ + int i; + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_lookup_names"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries ", ps, depth, &(r_u->num_entries )); + prs_uint32("undoc_buffer", ps, depth, &(r_u->undoc_buffer)); + prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2)); + + if (r_u->num_entries != 0) + { + for (i = 0; i < r_u->num_entries2; i++) + { + smb_io_dom_rid3("", &(r_u->dom_rid[i]), ps, depth); + } + + } + + prs_uint32("num_entries3", ps, depth, &(r_u->num_entries3)); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +makes a SAMR_Q_UNKNOWN_12 structure. +********************************************************************/ +void make_samr_q_unknown_12(SAMR_Q_UNKNOWN_12 *q_u, + POLICY_HND *pol, uint32 rid, + uint32 num_gids, uint32 *gid) +{ + int i; + if (q_u == NULL) return; + + DEBUG(5,("make_samr_r_unknwon_12\n")); + + memcpy(&(q_u->pol), pol, sizeof(*pol)); + + q_u->num_gids1 = num_gids; + q_u->rid = rid; + q_u->ptr = 0; + q_u->num_gids2 = num_gids; + + for (i = 0; i < num_gids; i++) + { + q_u->gid[i] = gid[i]; + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_12(char *desc, SAMR_Q_UNKNOWN_12 *q_u, prs_struct *ps, int depth) +{ + int i; + fstring tmp; + + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_12"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("num_gids1", ps, depth, &(q_u->num_gids1)); + prs_uint32("rid ", ps, depth, &(q_u->rid )); + prs_uint32("ptr ", ps, depth, &(q_u->ptr )); + prs_uint32("num_gids2", ps, depth, &(q_u->num_gids2)); + + for (i = 0; i < q_u->num_gids2; i++) + { + sprintf(tmp, "gid[%02d] ", i); + prs_uint32(tmp, ps, depth, &(q_u->gid[i])); + } + + prs_align(ps); +} + + +/******************************************************************* +makes a SAMR_R_UNKNOWN_12 structure. +********************************************************************/ +void make_samr_r_unknown_12(SAMR_R_UNKNOWN_12 *r_u, + uint32 num_aliases, fstring *als_name, uint32 *num_als_usrs, + uint32 status) +{ + int i; + if (r_u == NULL || als_name == NULL || num_als_usrs == NULL) return; + + DEBUG(5,("make_samr_r_unknown_12\n")); + + if (status == 0x0) + { + r_u->num_aliases1 = num_aliases; + r_u->ptr_aliases = 1; + r_u->num_aliases2 = num_aliases; + + r_u->num_als_usrs1 = num_aliases; + r_u->ptr_als_usrs = 1; + r_u->num_als_usrs2 = num_aliases; + + for (i = 0; i < num_aliases; i++) + { + int als_len = als_name[i] != NULL ? strlen(als_name[i]) : 0; + make_uni_hdr(&(r_u->hdr_als_name[i]), als_len , als_len, als_name[i] ? 1 : 0); + make_unistr2(&(r_u->uni_als_name[i]), als_name[i], als_len); + r_u->num_als_usrs[i] = num_als_usrs[i]; + } + } + else + { + r_u->num_aliases1 = num_aliases; + r_u->ptr_aliases = 0; + r_u->num_aliases2 = num_aliases; + + r_u->num_als_usrs1 = num_aliases; + r_u->ptr_als_usrs = 0; + r_u->num_als_usrs2 = num_aliases; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_unknown_12(char *desc, SAMR_R_UNKNOWN_12 *r_u, prs_struct *ps, int depth) +{ + int i; + fstring tmp; + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_unknown_12"); + depth++; + + prs_align(ps); + + prs_uint32("num_aliases1", ps, depth, &(r_u->num_aliases1)); + prs_uint32("ptr_aliases ", ps, depth, &(r_u->ptr_aliases )); + prs_uint32("num_aliases2", ps, depth, &(r_u->num_aliases2)); + + if (r_u->ptr_aliases != 0 && r_u->num_aliases1 != 0) + { + for (i = 0; i < r_u->num_aliases2; i++) + { + sprintf(tmp, "als_hdr[%02d] ", i); + smb_io_unihdr ("", &(r_u->hdr_als_name[i]), ps, depth); + } + for (i = 0; i < r_u->num_aliases2; i++) + { + sprintf(tmp, "als_str[%02d] ", i); + smb_io_unistr2("", &(r_u->uni_als_name[i]), r_u->hdr_als_name[i].buffer, ps, depth); + } + } + + prs_align(ps); + + prs_uint32("num_als_usrs1", ps, depth, &(r_u->num_als_usrs1)); + prs_uint32("ptr_als_usrs ", ps, depth, &(r_u->ptr_als_usrs )); + prs_uint32("num_als_usrs2", ps, depth, &(r_u->num_als_usrs2)); + + if (r_u->ptr_als_usrs != 0 && r_u->num_als_usrs1 != 0) + { + for (i = 0; i < r_u->num_als_usrs2; i++) + { + sprintf(tmp, "als_usrs[%02d] ", i); + prs_uint32(tmp, ps, depth, &(r_u->num_als_usrs[i])); + } + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_samr_q_open_user(SAMR_Q_OPEN_USER *q_u, + POLICY_HND *pol, + uint32 unk_0, uint32 rid) +{ + if (q_u == NULL) return; + + DEBUG(5,("samr_make_q_open_user\n")); + + memcpy(&q_u->domain_pol, pol, sizeof(q_u->domain_pol)); + + q_u->unknown_0 = unk_0; + q_u->user_rid = rid; +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_open_user(char *desc, SAMR_Q_OPEN_USER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_open_user"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("domain_pol", &(q_u->domain_pol), ps, depth); + prs_align(ps); + + prs_uint32("unknown_0", ps, depth, &(q_u->unknown_0)); + prs_uint32("user_rid ", ps, depth, &(q_u->user_rid )); + + prs_align(ps); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_open_user(char *desc, SAMR_R_OPEN_USER *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_open_user"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("user_pol", &(r_u->user_pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +makes a SAMR_Q_QUERY_USERGROUPS structure. +********************************************************************/ +void make_samr_q_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u, + POLICY_HND *hnd) +{ + if (q_u == NULL || hnd == NULL) return; + + DEBUG(5,("make_samr_q_query_usergroups\n")); + + memcpy(&(q_u->pol), hnd, sizeof(q_u->pol)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_query_usergroups(char *desc, SAMR_Q_QUERY_USERGROUPS *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_query_usergroups"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); +} + +/******************************************************************* +makes a SAMR_R_QUERY_USERGROUPS structure. +********************************************************************/ +void make_samr_r_query_usergroups(SAMR_R_QUERY_USERGROUPS *r_u, + uint32 num_gids, DOM_GID *gid, uint32 status) +{ + if (r_u == NULL) return; + + DEBUG(5,("make_samr_r_query_usergroups\n")); + + if (status == 0x0) + { + r_u->ptr_0 = 1; + r_u->num_entries = num_gids; + r_u->ptr_1 = 1; + r_u->num_entries2 = num_gids; + + r_u->gid = gid; + +#if 0 + int i; + for (i = 0; i < num_gids && i < LSA_MAX_GROUPS; i++) + { + r_u->gid[i].g_rid = gid[i].g_rid; + r_u->gid[i].attr = gid[i].attr ; + } +#endif + + } + else + { + r_u->ptr_0 = 0; + r_u->num_entries = 0; + r_u->ptr_1 = 0; + } + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_query_usergroups(char *desc, SAMR_R_QUERY_USERGROUPS *r_u, prs_struct *ps, int depth) +{ + int i; + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_query_usergroups"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_0 ", ps, depth, &(r_u->ptr_0 )); + + if (r_u->ptr_0 != 0) + { + prs_uint32("num_entries ", ps, depth, &(r_u->num_entries)); + prs_uint32("ptr_1 ", ps, depth, &(r_u->ptr_1 )); + + if (r_u->num_entries != 0) + { + prs_uint32("num_entries2", ps, depth, &(r_u->num_entries2)); + + for (i = 0; i < r_u->num_entries2; i++) + { + smb_io_gid("", &(r_u->gid[i]), ps, depth); + } + } + } + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +makes a SAMR_Q_QUERY_USERINFO structure. +********************************************************************/ +void make_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, + POLICY_HND *hnd, uint16 switch_value) +{ + if (q_u == NULL || hnd == NULL) return; + + DEBUG(5,("make_samr_q_query_userinfo\n")); + + memcpy(&(q_u->pol), hnd, sizeof(q_u->pol)); + q_u->switch_value = switch_value; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_query_userinfo(char *desc, SAMR_Q_QUERY_USERINFO *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_query_userinfo"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); + + prs_uint16("switch_value", ps, depth, &(q_u->switch_value)); /* 0x0015 or 0x0011 */ + + prs_align(ps); +} + +/******************************************************************* +reads or writes a LOGON_HRS structure. +********************************************************************/ +void sam_io_logon_hrs(char *desc, LOGON_HRS *hrs, prs_struct *ps, int depth) +{ + if (hrs == NULL) return; + + prs_debug(ps, depth, desc, "sam_io_logon_hrs"); + depth++; + + prs_align(ps); + + prs_uint32 ( "len ", ps, depth, &(hrs->len )); + + if (hrs->len > 64) + { + DEBUG(5,("sam_io_logon_hrs: truncating length\n")); + hrs->len = 64; + } + + prs_uint8s (False, "hours", ps, depth, hrs->hours, hrs->len); +} + +/******************************************************************* +makes a SAM_USER_INFO_11 structure. +********************************************************************/ +void make_sam_user_info11(SAM_USER_INFO_11 *usr, + NTTIME *expiry, + char *mach_acct, + uint32 rid_user, + uint32 rid_group, + uint16 acct_ctrl) + +{ + int len_mach_acct; + if (usr == NULL || expiry == NULL || mach_acct == NULL) return; + + DEBUG(5,("make_samr_r_unknown_24\n")); + + len_mach_acct = strlen(mach_acct); + + memcpy(&(usr->expiry),expiry, sizeof(usr->expiry)); /* expiry time or something? */ + bzero(usr->padding_1, sizeof(usr->padding_1)); /* 0 - padding 24 bytes */ + + make_uni_hdr(&(usr->hdr_mach_acct), len_mach_acct, len_mach_acct, 4); /* unicode header for machine account */ + usr->padding_2 = 0; /* 0 - padding 4 bytes */ + + usr->ptr_1 = 1; /* pointer */ + bzero(usr->padding_3, sizeof(usr->padding_3)); /* 0 - padding 32 bytes */ + usr->padding_4 = 0; /* 0 - padding 4 bytes */ + + usr->ptr_2 = 1; /* pointer */ + usr->padding_5 = 0; /* 0 - padding 4 bytes */ + + usr->ptr_3 = 1; /* pointer */ + bzero(usr->padding_6, sizeof(usr->padding_6)); /* 0 - padding 32 bytes */ + + usr->rid_user = rid_user; + usr->rid_group = rid_group; + + usr->acct_ctrl = acct_ctrl; + usr->unknown_3 = 0x0000; + + usr->unknown_4 = 0x003f; /* 0x003f - 16 bit unknown */ + usr->unknown_5 = 0x003c; /* 0x003c - 16 bit unknown */ + + bzero(usr->padding_7, sizeof(usr->padding_7)); /* 0 - padding 16 bytes */ + usr->padding_8 = 0; /* 0 - padding 4 bytes */ + + make_unistr2(&(usr->uni_mach_acct), mach_acct, len_mach_acct); /* unicode string for machine account */ + + bzero(usr->padding_9, sizeof(usr->padding_9)); /* 0 - padding 48 bytes */ +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void sam_io_user_info11(char *desc, SAM_USER_INFO_11 *usr, prs_struct *ps, int depth) +{ + if (usr == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_unknown_24"); + depth++; + + prs_align(ps); + + prs_uint8s (False, "padding_0", ps, depth, usr->padding_0, sizeof(usr->padding_0)); + + smb_io_time("time", &(usr->expiry), ps, depth); + + prs_uint8s (False, "padding_1", ps, depth, usr->padding_1, sizeof(usr->padding_1)); + + smb_io_unihdr ("unihdr", &(usr->hdr_mach_acct), ps, depth); + prs_uint32( "padding_2", ps, depth, &(usr->padding_2)); + + prs_uint32( "ptr_1 ", ps, depth, &(usr->ptr_1 )); + prs_uint8s (False, "padding_3", ps, depth, usr->padding_3, sizeof(usr->padding_3)); + prs_uint32( "padding_4", ps, depth, &(usr->padding_4)); + + prs_uint32( "ptr_2 ", ps, depth, &(usr->ptr_2 )); + prs_uint32( "padding_5", ps, depth, &(usr->padding_5)); + + prs_uint32( "ptr_3 ", ps, depth, &(usr->ptr_3 )); + prs_uint8s (False, "padding_6", ps, depth, usr->padding_6, sizeof(usr->padding_6)); + + prs_uint32( "rid_user ", ps, depth, &(usr->rid_user )); + prs_uint32( "rid_group", ps, depth, &(usr->rid_group)); + prs_uint16( "acct_ctrl", ps, depth, &(usr->acct_ctrl)); + prs_uint16( "unknown_3", ps, depth, &(usr->unknown_3)); + prs_uint16( "unknown_4", ps, depth, &(usr->unknown_4)); + prs_uint16( "unknown_5", ps, depth, &(usr->unknown_5)); + + prs_uint8s (False, "padding_7", ps, depth, usr->padding_7, sizeof(usr->padding_7)); + prs_uint32( "padding_8", ps, depth, &(usr->padding_8)); + + smb_io_unistr2("unistr2", &(usr->uni_mach_acct), True, ps, depth); + prs_align(ps); + + prs_uint8s (False, "padding_9", ps, depth, usr->padding_9, sizeof(usr->padding_9)); +} + +/************************************************************************* + make_sam_user_info21 + + unknown_3 = 0x00ff ffff + unknown_5 = 0x0002 0000 + unknown_6 = 0x0000 04ec + + *************************************************************************/ +void make_sam_user_info21(SAM_USER_INFO_21 *usr, + + NTTIME *logon_time, + NTTIME *logoff_time, + NTTIME *kickoff_time, + NTTIME *pass_last_set_time, + NTTIME *pass_can_change_time, + NTTIME *pass_must_change_time, + + char *user_name, + char *full_name, + char *home_dir, + char *dir_drive, + char *logon_script, + char *profile_path, + char *description, + char *workstations, + char *unknown_str, + char *munged_dial, + + uint32 user_rid, + uint32 group_rid, + uint16 acb_info, + + uint32 unknown_3, + uint16 logon_divs, + LOGON_HRS *hrs, + uint32 unknown_5, + uint32 unknown_6) +{ + int len_user_name = user_name != NULL ? strlen(user_name ) : 0; + int len_full_name = full_name != NULL ? strlen(full_name ) : 0; + int len_home_dir = home_dir != NULL ? strlen(home_dir ) : 0; + int len_dir_drive = dir_drive != NULL ? strlen(dir_drive ) : 0; + int len_logon_script = logon_script != NULL ? strlen(logon_script) : 0; + int len_profile_path = profile_path != NULL ? strlen(profile_path) : 0; + int len_description = description != NULL ? strlen(description ) : 0; + int len_workstations = workstations != NULL ? strlen(workstations) : 0; + int len_unknown_str = unknown_str != NULL ? strlen(unknown_str ) : 0; + int len_munged_dial = munged_dial != NULL ? strlen(munged_dial ) : 0; + + usr->logon_time = *logon_time; + usr->logoff_time = *logoff_time; + usr->kickoff_time = *kickoff_time; + usr->pass_last_set_time = *pass_last_set_time; + usr->pass_can_change_time = *pass_can_change_time; + usr->pass_must_change_time = *pass_must_change_time; + + make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , len_user_name != 0); + make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , len_full_name != 0); + make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , len_home_dir != 0); + make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , len_dir_drive != 0); + make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, len_logon_script != 0); + make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, len_profile_path != 0); + make_uni_hdr(&(usr->hdr_acct_desc ), len_description , len_description , len_description != 0); + make_uni_hdr(&(usr->hdr_workstations), len_workstations, len_workstations, len_workstations != 0); + make_uni_hdr(&(usr->hdr_unknown_str ), len_unknown_str , len_unknown_str , len_workstations != 0); + make_uni_hdr(&(usr->hdr_munged_dial ), len_munged_dial , len_munged_dial , len_workstations != 0); + + bzero(usr->nt_pwd, sizeof(usr->nt_pwd)); + bzero(usr->lm_pwd, sizeof(usr->lm_pwd)); + + usr->user_rid = user_rid; + usr->group_rid = group_rid; + usr->acb_info = acb_info; + usr->unknown_3 = unknown_3; /* 0x00ff ffff */ + + usr->logon_divs = logon_divs; /* should be 168 (hours/week) */ + usr->ptr_logon_hrs = hrs ? 1 : 0; + usr->unknown_5 = unknown_5; /* 0x0002 0000 */ + + bzero(usr->padding1, sizeof(usr->padding1)); + + make_unistr2(&(usr->uni_user_name ), user_name , len_user_name ); + make_unistr2(&(usr->uni_full_name ), full_name , len_full_name ); + make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir ); + make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive ); + make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script); + make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path); + make_unistr2(&(usr->uni_acct_desc ), description , len_description ); + make_unistr2(&(usr->uni_workstations), workstations, len_workstations); + make_unistr2(&(usr->uni_unknown_str ), unknown_str , len_unknown_str ); + make_unistr2(&(usr->uni_munged_dial ), munged_dial , len_munged_dial ); + + usr->unknown_6 = unknown_6; /* 0x0000 04ec */ + usr->padding4 = 0; + + if (hrs) + { + memcpy(&(usr->logon_hrs), hrs, sizeof(usr->logon_hrs)); + } + else + { + memset(&(usr->logon_hrs), 0xff, sizeof(usr->logon_hrs)); + } +} + + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void sam_io_user_info21(char *desc, SAM_USER_INFO_21 *usr, prs_struct *ps, int depth) +{ + if (usr == NULL) return; + + prs_debug(ps, depth, desc, "lsa_io_user_info"); + depth++; + + prs_align(ps); + + smb_io_time("logon_time ", &(usr->logon_time) , ps, depth); + smb_io_time("logoff_time ", &(usr->logoff_time) , ps, depth); + smb_io_time("kickoff_time ", &(usr->kickoff_time) , ps, depth); + smb_io_time("pass_last_set_time ", &(usr->pass_last_set_time) , ps, depth); + smb_io_time("pass_can_change_time ", &(usr->pass_can_change_time) , ps, depth); + smb_io_time("pass_must_change_time", &(usr->pass_must_change_time), ps, depth); + + smb_io_unihdr("hdr_user_name ", &(usr->hdr_user_name) , ps, depth); /* username unicode string header */ + smb_io_unihdr("hdr_full_name ", &(usr->hdr_full_name) , ps, depth); /* user's full name unicode string header */ + smb_io_unihdr("hdr_home_dir ", &(usr->hdr_home_dir) , ps, depth); /* home directory unicode string header */ + smb_io_unihdr("hdr_dir_drive ", &(usr->hdr_dir_drive) , ps, depth); /* home directory drive */ + smb_io_unihdr("hdr_logon_script", &(usr->hdr_logon_script), ps, depth); /* logon script unicode string header */ + smb_io_unihdr("hdr_profile_path", &(usr->hdr_profile_path), ps, depth); /* profile path unicode string header */ + smb_io_unihdr("hdr_acct_desc ", &(usr->hdr_acct_desc ) , ps, depth); /* account description */ + smb_io_unihdr("hdr_workstations", &(usr->hdr_workstations), ps, depth); /* workstations user can log on from */ + smb_io_unihdr("hdr_unknown_str ", &(usr->hdr_unknown_str ), ps, depth); /* unknown string */ + smb_io_unihdr("hdr_munged_dial ", &(usr->hdr_munged_dial ), ps, depth); /* workstations user can log on from */ + + prs_uint8s (False, "lm_pwd ", ps, depth, usr->lm_pwd , sizeof(usr->lm_pwd )); + prs_uint8s (False, "nt_pwd ", ps, depth, usr->nt_pwd , sizeof(usr->nt_pwd )); + + prs_uint32("user_rid ", ps, depth, &(usr->user_rid )); /* User ID */ + prs_uint32("group_rid ", ps, depth, &(usr->group_rid )); /* Group ID */ + prs_uint16("acb_info ", ps, depth, &(usr->acb_info )); /* Group ID */ + prs_align(ps); + + prs_uint32("unknown_3 ", ps, depth, &(usr->unknown_3 )); + prs_uint16("logon_divs ", ps, depth, &(usr->logon_divs )); /* logon divisions per week */ + prs_align(ps); + prs_uint32("ptr_logon_hrs ", ps, depth, &(usr->ptr_logon_hrs)); + prs_uint32("unknown_5 ", ps, depth, &(usr->unknown_5 )); + + prs_uint8s (False, "padding1 ", ps, depth, usr->padding1, sizeof(usr->padding1)); + + /* here begins pointed-to data */ + + smb_io_unistr2("uni_user_name ", &(usr->uni_user_name) , usr->hdr_user_name .buffer, ps, depth); /* username unicode string */ + smb_io_unistr2("uni_full_name ", &(usr->uni_full_name) , usr->hdr_full_name .buffer, ps, depth); /* user's full name unicode string */ + smb_io_unistr2("uni_home_dir ", &(usr->uni_home_dir) , usr->hdr_home_dir .buffer, ps, depth); /* home directory unicode string */ + smb_io_unistr2("uni_dir_drive ", &(usr->uni_dir_drive) , usr->hdr_dir_drive .buffer, ps, depth); /* home directory drive unicode string */ + smb_io_unistr2("uni_logon_script", &(usr->uni_logon_script), usr->hdr_logon_script.buffer, ps, depth); /* logon script unicode string */ + smb_io_unistr2("uni_profile_path", &(usr->uni_profile_path), usr->hdr_profile_path.buffer, ps, depth); /* profile path unicode string */ + smb_io_unistr2("uni_acct_desc ", &(usr->uni_acct_desc ), usr->hdr_acct_desc .buffer, ps, depth); /* user description unicode string */ + smb_io_unistr2("uni_workstations", &(usr->uni_workstations), usr->hdr_workstations.buffer, ps, depth); /* worksations user can log on from */ + smb_io_unistr2("uni_unknown_str ", &(usr->uni_unknown_str ), usr->hdr_unknown_str .buffer, ps, depth); /* unknown string */ + smb_io_unistr2("uni_munged_dial ", &(usr->uni_munged_dial ), usr->hdr_munged_dial .buffer, ps, depth); /* worksations user can log on from */ + + prs_uint32("unknown_6 ", ps, depth, &(usr->unknown_6 )); + prs_uint32("padding4 ", ps, depth, &(usr->padding4 )); + + if (usr->ptr_logon_hrs) + { + sam_io_logon_hrs("logon_hrs", &(usr->logon_hrs) , ps, depth); + } +} + + +/******************************************************************* +makes a SAMR_R_QUERY_USERINFO structure. +********************************************************************/ +void make_samr_r_query_userinfo(SAMR_R_QUERY_USERINFO *r_u, + uint16 switch_value, void *info, uint32 status) + +{ + if (r_u == NULL || info == NULL) return; + + DEBUG(5,("make_samr_r_query_userinfo\n")); + + r_u->ptr = 0; + r_u->switch_value = 0; + + if (status == 0) + { + r_u->switch_value = switch_value; + + switch (switch_value) + { + case 0x10: + { + r_u->ptr = 1; + r_u->info.id10 = (SAM_USER_INFO_10*)info; + + break; + } + + case 0x11: + { + r_u->ptr = 1; + r_u->info.id11 = (SAM_USER_INFO_11*)info; + + break; + } + + case 21: + { + r_u->ptr = 1; + r_u->info.id21 = (SAM_USER_INFO_21*)info; + + break; + } + + default: + { + DEBUG(4,("make_samr_r_query_aliasinfo: unsupported switch level\n")); + break; + } + } + } + + r_u->status = status; /* return status */ +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_query_userinfo(char *desc, SAMR_R_QUERY_USERINFO *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_query_userinfo"); + depth++; + + prs_align(ps); + + prs_uint32("ptr ", ps, depth, &(r_u->ptr )); + prs_uint16("switch_value", ps, depth, &(r_u->switch_value)); + prs_align(ps); + + if (r_u->ptr != 0 && r_u->switch_value != 0) + { + switch (r_u->switch_value) + { +/* + case 0x10: + { + if (r_u->info.id10 != NULL) + { + sam_io_user_info10("", r_u->info.id10, ps, depth); + } + else + { + DEBUG(2,("samr_io_r_query_userinfo: info pointer not initialised\n")); + return NULL; + } + break; + } + case 0x11: + { + if (r_u->info.id11 != NULL) + { + sam_io_user_info11("", r_u->info.id11, ps, depth); + } + else + { + DEBUG(2,("samr_io_r_query_userinfo: info pointer not initialised\n")); + return NULL; + } + break; + } +*/ + case 21: + { + if (r_u->info.id21 != NULL) + { + sam_io_user_info21("", r_u->info.id21, ps, depth); + } + else + { + DEBUG(2,("samr_io_r_query_userinfo: info pointer not initialised\n")); + return; + } + break; + } + default: + { + DEBUG(2,("samr_io_r_query_userinfo: unknown switch level\n")); + break; + } + + } + } + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +makes a SAMR_Q_UNKNOWN_21 structure. +********************************************************************/ +void make_samr_q_unknown_21(SAMR_Q_UNKNOWN_21 *q_c, + POLICY_HND *hnd, uint16 unk_1, uint16 unk_2) +{ + if (q_c == NULL || hnd == NULL) return; + + DEBUG(5,("make_samr_q_unknown_21\n")); + + memcpy(&(q_c->group_pol), hnd, sizeof(q_c->group_pol)); + q_c->unknown_1 = unk_1; + q_c->unknown_2 = unk_2; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_21(char *desc, SAMR_Q_UNKNOWN_21 *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_21"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("group_pol", &(q_u->group_pol), ps, depth); + prs_align(ps); + + prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1)); + prs_uint16("unknown_2", ps, depth, &(q_u->unknown_2)); +} + +/******************************************************************* +makes a SAMR_Q_UNKNOWN_13 structure. +********************************************************************/ +void make_samr_q_unknown_13(SAMR_Q_UNKNOWN_13 *q_c, + POLICY_HND *hnd, uint16 unk_1, uint16 unk_2) +{ + if (q_c == NULL || hnd == NULL) return; + + DEBUG(5,("make_samr_q_unknown_13\n")); + + memcpy(&(q_c->alias_pol), hnd, sizeof(q_c->alias_pol)); + q_c->unknown_1 = unk_1; + q_c->unknown_2 = unk_2; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_13(char *desc, SAMR_Q_UNKNOWN_13 *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_13"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("alias_pol", &(q_u->alias_pol), ps, depth); + prs_align(ps); + + prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1)); + prs_uint16("unknown_2", ps, depth, &(q_u->unknown_2)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_32(char *desc, SAMR_Q_UNKNOWN_32 *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_32"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(q_u->pol), ps, depth); + prs_align(ps); + + smb_io_unihdr ("", &(q_u->hdr_mach_acct), ps, depth); + smb_io_unistr2("", &(q_u->uni_mach_acct), q_u->hdr_mach_acct.buffer, ps, depth); + + prs_align(ps); + + prs_uint32("acct_ctrl", ps, depth, &(q_u->acct_ctrl)); + prs_uint16("unknown_1", ps, depth, &(q_u->unknown_1)); + prs_uint16("unknown_2", ps, depth, &(q_u->unknown_2)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_unknown_32(char *desc, SAMR_R_UNKNOWN_32 *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_unknown_32"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + + +/******************************************************************* +makes a SAMR_Q_CONNECT structure. +********************************************************************/ +void make_samr_q_connect(SAMR_Q_CONNECT *q_u, + char *srv_name, uint32 unknown_0) +{ + int len_srv_name = strlen(srv_name); + + if (q_u == NULL) return; + + DEBUG(5,("make_q_connect\n")); + + /* make PDC server name \\server */ + make_unistr2(&(q_u->uni_srv_name), srv_name, len_srv_name); + + /* example values: 0x0000 0002 */ + q_u->unknown_0 = unknown_0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_connect(char *desc, SAMR_Q_CONNECT *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_connect"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name", ps, depth, &(q_u->ptr_srv_name)); + smb_io_unistr2("", &(q_u->uni_srv_name), q_u->ptr_srv_name, ps, depth); + + prs_align(ps); + + prs_uint32("unknown_0 ", ps, depth, &(q_u->unknown_0 )); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_connect(char *desc, SAMR_R_CONNECT *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_connect"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("connect_pol", &(r_u->connect_pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +makes a SAMR_Q_OPEN_ALIAS structure. +********************************************************************/ +void make_samr_q_open_alias(SAMR_Q_OPEN_ALIAS *q_u, + uint32 unknown_0, uint32 rid) +{ + if (q_u == NULL) return; + + DEBUG(5,("make_q_open_alias\n")); + + /* example values: 0x0000 0008 */ + q_u->unknown_0 = unknown_0; + + q_u->rid_alias = rid; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_open_alias(char *desc, SAMR_Q_OPEN_ALIAS *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_open_alias"); + depth++; + + prs_align(ps); + + prs_uint32("unknown_0", ps, depth, &(q_u->unknown_0)); + prs_uint32("rid_alias", ps, depth, &(q_u->rid_alias)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_open_alias(char *desc, SAMR_R_OPEN_ALIAS *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_open_alias"); + depth++; + + prs_align(ps); + + smb_io_pol_hnd("pol", &(r_u->pol), ps, depth); + prs_align(ps); + + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +makes a SAMR_Q_UNKNOWN_38 structure. +********************************************************************/ +void make_samr_q_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, char *srv_name) +{ + int len_srv_name = strlen(srv_name); + + if (q_u == NULL) return; + + DEBUG(5,("make_q_unknown_38\n")); + + q_u->ptr = 1; + make_uni_hdr(&(q_u->hdr_srv_name), len_srv_name, len_srv_name, len_srv_name != 0); + make_unistr2(&(q_u->uni_srv_name), srv_name, len_srv_name); + +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_q_unknown_38(char *desc, SAMR_Q_UNKNOWN_38 *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_q_unknown_38"); + depth++; + + prs_align(ps); + + prs_uint32("ptr", ps, depth, &(q_u->ptr)); + if (q_u->ptr != 0) + { + smb_io_unihdr ("", &(q_u->hdr_srv_name), ps, depth); + smb_io_unistr2("", &(q_u->uni_srv_name), q_u->hdr_srv_name.buffer, ps, depth); + } +} + +/******************************************************************* +makes a SAMR_R_UNKNOWN_38 structure. +********************************************************************/ +void make_samr_r_unknown_38(SAMR_R_UNKNOWN_38 *r_u, + uint16 level, uint32 status) +{ + if (r_u == NULL) return; + + DEBUG(5,("make_r_unknown_38\n")); + + r_u->level.value = level; + r_u->ptr_0 = 0; + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void samr_io_r_unknown_38(char *desc, SAMR_R_UNKNOWN_38 *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_r_unknown_38"); + depth++; + + prs_align(ps); + + smb_io_lookup_level("level ", &(r_u->level), ps, depth); + prs_uint32("ptr_0 ", ps, depth, &(r_u->ptr_0 )); + prs_uint32("status", ps, depth, &(r_u->status)); +} + +/******************************************************************* +reads or writes a SAMR_ENC_PASSWD structure. +********************************************************************/ +void samr_io_enc_passwd(char *desc, SAMR_ENC_PASSWD *pwd, prs_struct *ps, int depth) +{ + if (pwd == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_enc_passwd"); + depth++; + + prs_align(ps); + + prs_uint32("ptr", ps, depth, &(pwd->ptr)); + prs_uint8s(False, "pwd", ps, depth, pwd->pass, sizeof(pwd->pass)); +} + +/******************************************************************* +reads or writes a SAMR_ENC_HASH structure. +********************************************************************/ +void samr_io_enc_hash(char *desc, SAMR_ENC_HASH *hsh, prs_struct *ps, int depth) +{ + if (hsh == NULL) return; + + prs_debug(ps, depth, desc, "samr_io_enc_hash"); + depth++; + + prs_align(ps); + + prs_uint32("ptr ", ps, depth, &(hsh->ptr)); + prs_uint8s(False, "hash", ps, depth, hsh->hash, sizeof(hsh->hash)); +} + +#if 0 +/* SAMR_Q_CHGPASSWD_USER */ +typedef struct q_samr_chgpasswd_user_info +{ + uint32 ptr_0; + + UNIHDR hdr_server; /* server name unicode header */ + UNISTR2 uni_server; /* server name unicode string */ + + UNIHDR hdr_user_name; /* username unicode string header */ + UNISTR2 uni_user_name; /* username unicode string */ + + SAMR_ENC_PASSWD nt_newpass; + SAMR_ENC_HASH nt_oldhash; + + uint32 unknown_1; /* seems to always contain 0001 */ + + SAMR_ENC_PASSWD lm_newpass; + SAMR_ENC_HASH lm_oldhash; + +} SAMR_Q_CHGPASSWD_USER; + +/* SAMR_R_CHGPASSWD_USER */ +typedef struct r_samr_chgpasswd_user_info +{ + uint32 result; /* 0 == OK, C000006A (NT_STATUS_WRONG_PASSWORD) */ + +} SAMR_R_CHGPASSWD_USER; + +#endif /* 0 */ + diff --git a/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c new file mode 100644 index 0000000000..959a6096aa --- /dev/null +++ b/source3/rpc_parse/parse_srv.c @@ -0,0 +1,1528 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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" + +extern int DEBUGLEVEL; + + +/******************************************************************* + makes a SH_INFO_1_STR structure +********************************************************************/ +void make_srv_share_info1_str(SH_INFO_1_STR *sh1, char *net_name, char *remark) +{ + if (sh1 == NULL) return; + + DEBUG(5,("make_srv_share_info1_str\n")); + + make_unistr2(&(sh1->uni_netname), net_name, strlen(net_name)+1); + make_unistr2(&(sh1->uni_remark ), remark , strlen(remark )+1); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_share_info1_str(char *desc, SH_INFO_1_STR *sh1, prs_struct *ps, int depth) +{ + if (sh1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_share_info1_str"); + depth++; + + prs_align(ps); + + smb_io_unistr2("", &(sh1->uni_netname), True, ps, depth); + smb_io_unistr2("", &(sh1->uni_remark ), True, ps, depth); +} + +/******************************************************************* + makes a SH_INFO_1 structure +********************************************************************/ +void make_srv_share_info1(SH_INFO_1 *sh1, char *net_name, uint32 type, char *remark) +{ + if (sh1 == NULL) return; + + DEBUG(5,("make_srv_share_info1: %s %8x %s\n", net_name, type, remark)); + + sh1->ptr_netname = net_name != NULL ? 1 : 0; + sh1->type = type; + sh1->ptr_remark = remark != NULL ? 1 : 0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_share_info1(char *desc, SH_INFO_1 *sh1, prs_struct *ps, int depth) +{ + if (sh1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_share_info1"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_netname", ps, depth, &(sh1->ptr_netname)); + prs_uint32("type ", ps, depth, &(sh1->type )); + prs_uint32("ptr_remark ", ps, depth, &(sh1->ptr_remark)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_share_info_1(char *desc, SRV_SHARE_INFO_1 *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_share_1_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(ctr->num_entries_read)); + prs_uint32("ptr_share_info", ps, depth, &(ctr->ptr_share_info)); + + if (ctr->ptr_share_info != 0) + { + int i; + int num_entries = ctr->num_entries_read; + if (num_entries > MAX_SHARE_ENTRIES) + { + num_entries = MAX_SHARE_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(ctr->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_share_info1("", &(ctr->info_1[i]), ps, depth); + } + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_share_info1_str("", &(ctr->info_1_str[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* + makes a SH_INFO_2_STR structure +********************************************************************/ +void make_srv_share_info2_str(SH_INFO_2_STR *sh2, + char *net_name, char *remark, + char *path, char *passwd) +{ + if (sh2 == NULL) return; + + DEBUG(5,("make_srv_share_info2_str\n")); + + make_unistr2(&(sh2->uni_netname), net_name, strlen(net_name)+1); + make_unistr2(&(sh2->uni_remark ), remark , strlen(remark )+1); + make_unistr2(&(sh2->uni_path ), path , strlen(path )+1); + make_unistr2(&(sh2->uni_passwd ), passwd , strlen(passwd )+1); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_share_info2_str(char *desc, SH_INFO_2_STR *sh2, prs_struct *ps, int depth) +{ + if (sh2 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_share_info2_str"); + depth++; + + prs_align(ps); + + smb_io_unistr2("", &(sh2->uni_netname), True, ps, depth); + smb_io_unistr2("", &(sh2->uni_remark ), True, ps, depth); + smb_io_unistr2("", &(sh2->uni_path ), True, ps, depth); + smb_io_unistr2("", &(sh2->uni_passwd ), True, ps, depth); +} + +/******************************************************************* + makes a SH_INFO_2 structure +********************************************************************/ +void make_srv_share_info2(SH_INFO_2 *sh2, + char *net_name, uint32 type, char *remark, + uint32 perms, uint32 max_uses, uint32 num_uses, + char *path, char *passwd) +{ + if (sh2 == NULL) return; + + DEBUG(5,("make_srv_share_info2: %s %8x %s\n", net_name, type, remark)); + + sh2->ptr_netname = net_name != NULL ? 1 : 0; + sh2->type = type; + sh2->ptr_remark = remark != NULL ? 1 : 0; + sh2->perms = perms; + sh2->max_uses = max_uses; + sh2->num_uses = num_uses; + sh2->type = type; + sh2->ptr_path = path != NULL ? 1 : 0; + sh2->ptr_passwd = passwd != NULL ? 1 : 0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_share_info2(char *desc, SH_INFO_2 *sh2, prs_struct *ps, int depth) +{ + if (sh2 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_share_info2"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_netname", ps, depth, &(sh2->ptr_netname)); + prs_uint32("type ", ps, depth, &(sh2->type )); + prs_uint32("ptr_remark ", ps, depth, &(sh2->ptr_remark )); + prs_uint32("perms ", ps, depth, &(sh2->perms )); + prs_uint32("max_uses ", ps, depth, &(sh2->max_uses )); + prs_uint32("num_uses ", ps, depth, &(sh2->num_uses )); + prs_uint32("ptr_path ", ps, depth, &(sh2->ptr_path )); + prs_uint32("ptr_passwd ", ps, depth, &(sh2->ptr_passwd )); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_share_info_2(char *desc, SRV_SHARE_INFO_2 *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_share_2_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(ctr->num_entries_read)); + prs_uint32("ptr_share_info", ps, depth, &(ctr->ptr_share_info)); + + if (ctr->ptr_share_info != 0) + { + int i; + int num_entries = ctr->num_entries_read; + if (num_entries > MAX_SHARE_ENTRIES) + { + num_entries = MAX_SHARE_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(ctr->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_share_info2("", &(ctr->info_2[i]), ps, depth); + } + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_share_info2_str("", &(ctr->info_2_str[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_share_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(ctr->switch_value)); + prs_uint32("ptr_share_ctr", ps, depth, &(ctr->ptr_share_ctr)); + + if (ctr->ptr_share_ctr != 0) + { + switch (ctr->switch_value) + { + case 2: + { + srv_io_srv_share_info_2("", &(ctr->share.info2), ps, depth); + break; + } + case 1: + { + srv_io_srv_share_info_1("", &(ctr->share.info1), ps, depth); + break; + } + default: + { + DEBUG(5,("%s no share info at switch_value %d\n", + tab_depth(depth), ctr->switch_value)); + break; + } + } + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_srv_q_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, + char *srv_name, + uint32 share_level, SRV_SHARE_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + if (q_n == NULL || ctr == NULL || hnd == NULL) return; + + q_n->ctr = ctr; + + DEBUG(5,("make_q_net_share_enum\n")); + + make_buf_unistr2(&(q_n->uni_srv_name), &(q_n->ptr_srv_name), srv_name); + + q_n->share_level = share_level; + q_n->preferred_len = preferred_len; + + memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_q_net_share_enum(char *desc, SRV_Q_NET_SHARE_ENUM *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_share_enum"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name", ps, depth, &(q_n->ptr_srv_name)); + smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); + + prs_align(ps); + + prs_uint32("share_level", ps, depth, &(q_n->share_level )); + + if (q_n->share_level != -1) + { + srv_io_srv_share_ctr("share_ctr", q_n->ctr, ps, depth); + } + + prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len)); + + smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_r_net_share_enum(char *desc, SRV_R_NET_SHARE_ENUM *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_r_net_share_enum"); + depth++; + + prs_align(ps); + + prs_uint32("share_level", ps, depth, &(r_n->share_level)); + + if (r_n->share_level != 0) + { + srv_io_srv_share_ctr("share_ctr", r_n->ctr, ps, depth); + } + + prs_uint32("total_entries", ps, depth, &(r_n->total_entries)); + smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); + prs_uint32("status ", ps, depth, &(r_n->status)); +} + +/******************************************************************* + makes a SESS_INFO_0_STR structure +********************************************************************/ +void make_srv_sess_info0_str(SESS_INFO_0_STR *ss0, char *name) +{ + if (ss0 == NULL) return; + + DEBUG(5,("make_srv_sess_info0_str\n")); + + make_unistr2(&(ss0->uni_name), name, strlen(name)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_sess_info0_str(char *desc, SESS_INFO_0_STR *ss0, prs_struct *ps, int depth) +{ + if (ss0 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_sess_info0_str"); + depth++; + + prs_align(ps); + + smb_io_unistr2("", &(ss0->uni_name), True, ps, depth); +} + +/******************************************************************* + makes a SESS_INFO_0 structure +********************************************************************/ +void make_srv_sess_info0(SESS_INFO_0 *ss0, char *name) +{ + if (ss0 == NULL) return; + + DEBUG(5,("make_srv_sess_info0: %s\n", name)); + + ss0->ptr_name = name != NULL ? 1 : 0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_sess_info0(char *desc, SESS_INFO_0 *ss0, prs_struct *ps, int depth) +{ + if (ss0 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_sess_info0"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_name", ps, depth, &(ss0->ptr_name)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_sess_info_0(char *desc, SRV_SESS_INFO_0 *ss0, prs_struct *ps, int depth) +{ + if (ss0 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_sess_info_0"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(ss0->num_entries_read)); + prs_uint32("ptr_sess_info", ps, depth, &(ss0->ptr_sess_info)); + + if (ss0->ptr_sess_info != 0) + { + int i; + int num_entries = ss0->num_entries_read; + if (num_entries > MAX_SESS_ENTRIES) + { + num_entries = MAX_SESS_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(ss0->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_sess_info0("", &(ss0->info_0[i]), ps, depth); + } + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_sess_info0_str("", &(ss0->info_0_str[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* + makes a SESS_INFO_1_STR structure +********************************************************************/ +void make_srv_sess_info1_str(SESS_INFO_1_STR *ss1, char *name, char *user) +{ + if (ss1 == NULL) return; + + DEBUG(5,("make_srv_sess_info1_str\n")); + + make_unistr2(&(ss1->uni_name), name, strlen(name)); + make_unistr2(&(ss1->uni_user), name, strlen(user)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_sess_info1_str(char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth) +{ + if (ss1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_sess_info1_str"); + depth++; + + prs_align(ps); + + smb_io_unistr2("", &(ss1->uni_name), True, ps, depth); + smb_io_unistr2("", &(ss1->uni_user), True, ps, depth); +} + +/******************************************************************* + makes a SESS_INFO_1 structure +********************************************************************/ +void make_srv_sess_info1(SESS_INFO_1 *ss1, + char *name, char *user, + uint32 num_opens, uint32 open_time, uint32 idle_time, + uint32 user_flags) +{ + if (ss1 == NULL) return; + + DEBUG(5,("make_srv_sess_info1: %s\n", name)); + + ss1->ptr_name = name != NULL ? 1 : 0; + ss1->ptr_user = user != NULL ? 1 : 0; + + ss1->num_opens = num_opens; + ss1->open_time = open_time; + ss1->idle_time = idle_time; + ss1->user_flags = user_flags; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_sess_info1(char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth) +{ + if (ss1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_sess_info1"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_name ", ps, depth, &(ss1->ptr_name )); + prs_uint32("ptr_user ", ps, depth, &(ss1->ptr_user )); + + prs_uint32("num_opens ", ps, depth, &(ss1->num_opens )); + prs_uint32("open_time ", ps, depth, &(ss1->open_time )); + prs_uint32("idle_time ", ps, depth, &(ss1->idle_time )); + prs_uint32("user_flags", ps, depth, &(ss1->user_flags)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_sess_info_1(char *desc, SRV_SESS_INFO_1 *ss1, prs_struct *ps, int depth) +{ + if (ss1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_sess_info_1"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(ss1->num_entries_read)); + prs_uint32("ptr_sess_info", ps, depth, &(ss1->ptr_sess_info)); + + if (ss1->ptr_sess_info != 0) + { + int i; + int num_entries = ss1->num_entries_read; + if (num_entries > MAX_SESS_ENTRIES) + { + num_entries = MAX_SESS_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(ss1->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_sess_info1("", &(ss1->info_1[i]), ps, depth); + } + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_sess_info1_str("", &(ss1->info_1_str[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_sess_ctr(char *desc, SRV_SESS_INFO_CTR *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_sess_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(ctr->switch_value)); + prs_uint32("ptr_sess_ctr", ps, depth, &(ctr->ptr_sess_ctr)); + + if (ctr->ptr_sess_ctr != 0) + { + switch (ctr->switch_value) + { + case 0: + { + srv_io_srv_sess_info_0("", &(ctr->sess.info0), ps, depth); + break; + } + case 1: + { + srv_io_srv_sess_info_1("", &(ctr->sess.info1), ps, depth); + break; + } + default: + { + DEBUG(5,("%s no session info at switch_value %d\n", + tab_depth(depth), ctr->switch_value)); + break; + } + } + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, + char *srv_name, char *qual_name, + uint32 sess_level, SRV_SESS_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + if (q_n == NULL || ctr == NULL || hnd == NULL) return; + + q_n->ctr = ctr; + + DEBUG(5,("make_q_net_sess_enum\n")); + + make_buf_unistr2(&(q_n->uni_srv_name), &(q_n->ptr_srv_name), srv_name); + make_buf_unistr2(&(q_n->uni_qual_name), &(q_n->ptr_qual_name), qual_name); + + q_n->sess_level = sess_level; + q_n->preferred_len = preferred_len; + + memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_q_net_sess_enum(char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name", ps, depth, &(q_n->ptr_srv_name)); + smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); + + prs_align(ps); + + prs_uint32("ptr_qual_name", ps, depth, &(q_n->ptr_qual_name)); + smb_io_unistr2("", &(q_n->uni_qual_name), True, ps, depth); + + prs_align(ps); + + prs_uint32("sess_level", ps, depth, &(q_n->sess_level )); + + if (q_n->sess_level != -1) + { + srv_io_srv_sess_ctr("sess_ctr", q_n->ctr, ps, depth); + } + + prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len)); + + smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_r_net_sess_enum(char *desc, SRV_R_NET_SESS_ENUM *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_r_net_sess_enum"); + depth++; + + prs_align(ps); + + prs_uint32("sess_level", ps, depth, &(r_n->sess_level)); + + if (r_n->sess_level != -1) + { + srv_io_srv_sess_ctr("sess_ctr", r_n->ctr, ps, depth); + } + + prs_uint32("total_entries", ps, depth, &(r_n->total_entries)); + smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); + prs_uint32("status ", ps, depth, &(r_n->status)); +} + +/******************************************************************* + makes a CONN_INFO_0 structure +********************************************************************/ +void make_srv_conn_info0(CONN_INFO_0 *ss0, uint32 id) +{ + if (ss0 == NULL) return; + + DEBUG(5,("make_srv_conn_info0\n")); + + ss0->id = id; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_conn_info0(char *desc, CONN_INFO_0 *ss0, prs_struct *ps, int depth) +{ + if (ss0 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_conn_info0"); + depth++; + + prs_align(ps); + + prs_uint32("id", ps, depth, &(ss0->id)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_conn_info_0(char *desc, SRV_CONN_INFO_0 *ss0, prs_struct *ps, int depth) +{ + if (ss0 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_conn_info_0"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(ss0->num_entries_read)); + prs_uint32("ptr_conn_info", ps, depth, &(ss0->ptr_conn_info)); + + if (ss0->ptr_conn_info != 0) + { + int i; + int num_entries = ss0->num_entries_read; + if (num_entries > MAX_CONN_ENTRIES) + { + num_entries = MAX_CONN_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(ss0->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_conn_info0("", &(ss0->info_0[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* + makes a CONN_INFO_1_STR structure +********************************************************************/ +void make_srv_conn_info1_str(CONN_INFO_1_STR *ss1, char *usr_name, char *net_name) +{ + if (ss1 == NULL) return; + + DEBUG(5,("make_srv_conn_info1_str\n")); + + make_unistr2(&(ss1->uni_usr_name), usr_name, strlen(usr_name)); + make_unistr2(&(ss1->uni_net_name), net_name, strlen(net_name)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_conn_info1_str(char *desc, CONN_INFO_1_STR *ss1, prs_struct *ps, int depth) +{ + if (ss1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_conn_info1_str"); + depth++; + + prs_align(ps); + + smb_io_unistr2("", &(ss1->uni_usr_name), True, ps, depth); + smb_io_unistr2("", &(ss1->uni_net_name), True, ps, depth); +} + +/******************************************************************* + makes a CONN_INFO_1 structure +********************************************************************/ +void make_srv_conn_info1(CONN_INFO_1 *ss1, + uint32 id, uint32 type, + uint32 num_opens, uint32 num_users, uint32 open_time, + char *usr_name, char *net_name) +{ + if (ss1 == NULL) return; + + DEBUG(5,("make_srv_conn_info1: %s %s\n", usr_name, net_name)); + + ss1->id = id ; + ss1->type = type ; + ss1->num_opens = num_opens ; + ss1->num_users = num_users; + ss1->open_time = open_time; + + ss1->ptr_usr_name = usr_name != NULL ? 1 : 0; + ss1->ptr_net_name = net_name != NULL ? 1 : 0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_conn_info1(char *desc, CONN_INFO_1 *ss1, prs_struct *ps, int depth) +{ + if (ss1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_conn_info1"); + depth++; + + prs_align(ps); + + prs_uint32("id ", ps, depth, &(ss1->id )); + prs_uint32("type ", ps, depth, &(ss1->type )); + prs_uint32("num_opens ", ps, depth, &(ss1->num_opens )); + prs_uint32("num_users ", ps, depth, &(ss1->num_users )); + prs_uint32("open_time ", ps, depth, &(ss1->open_time )); + + prs_uint32("ptr_usr_name", ps, depth, &(ss1->ptr_usr_name)); + prs_uint32("ptr_net_name", ps, depth, &(ss1->ptr_net_name)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_conn_info_1(char *desc, SRV_CONN_INFO_1 *ss1, prs_struct *ps, int depth) +{ + if (ss1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_conn_info_1"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(ss1->num_entries_read)); + prs_uint32("ptr_conn_info", ps, depth, &(ss1->ptr_conn_info)); + + if (ss1->ptr_conn_info != 0) + { + int i; + int num_entries = ss1->num_entries_read; + if (num_entries > MAX_CONN_ENTRIES) + { + num_entries = MAX_CONN_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(ss1->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_conn_info1("", &(ss1->info_1[i]), ps, depth); + } + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_conn_info1_str("", &(ss1->info_1_str[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_conn_ctr(char *desc, SRV_CONN_INFO_CTR *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_conn_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(ctr->switch_value)); + prs_uint32("ptr_conn_ctr", ps, depth, &(ctr->ptr_conn_ctr)); + + if (ctr->ptr_conn_ctr != 0) + { + switch (ctr->switch_value) + { + case 0: + { + srv_io_srv_conn_info_0("", &(ctr->conn.info0), ps, depth); + break; + } + case 1: + { + srv_io_srv_conn_info_1("", &(ctr->conn.info1), ps, depth); + break; + } + default: + { + DEBUG(5,("%s no connection info at switch_value %d\n", + tab_depth(depth), ctr->switch_value)); + break; + } + } + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_srv_q_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, + char *srv_name, char *qual_name, + uint32 conn_level, SRV_CONN_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + if (q_n == NULL || ctr == NULL || hnd == NULL) return; + + q_n->ctr = ctr; + + DEBUG(5,("make_q_net_conn_enum\n")); + + make_buf_unistr2(&(q_n->uni_srv_name ), &(q_n->ptr_srv_name ), srv_name ); + make_buf_unistr2(&(q_n->uni_qual_name), &(q_n->ptr_qual_name), qual_name); + + q_n->conn_level = conn_level; + q_n->preferred_len = preferred_len; + + memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_q_net_conn_enum(char *desc, SRV_Q_NET_CONN_ENUM *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_conn_enum"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name ", ps, depth, &(q_n->ptr_srv_name)); + smb_io_unistr2("", &(q_n->uni_srv_name), q_n->ptr_srv_name, ps, depth); + + prs_align(ps); + + prs_uint32("ptr_qual_name", ps, depth, &(q_n->ptr_qual_name)); + smb_io_unistr2("", &(q_n->uni_qual_name), q_n->ptr_qual_name, ps, depth); + + prs_align(ps); + + prs_uint32("conn_level", ps, depth, &(q_n->conn_level )); + + if (q_n->conn_level != -1) + { + srv_io_srv_conn_ctr("conn_ctr", q_n->ctr, ps, depth); + } + + prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len)); + + smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_r_net_conn_enum(char *desc, SRV_R_NET_CONN_ENUM *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_r_net_conn_enum"); + depth++; + + prs_align(ps); + + prs_uint32("conn_level", ps, depth, &(r_n->conn_level)); + + if (r_n->conn_level != -1) + { + srv_io_srv_conn_ctr("conn_ctr", r_n->ctr, ps, depth); + } + + prs_uint32("total_entries", ps, depth, &(r_n->total_entries)); + smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); + prs_uint32("status ", ps, depth, &(r_n->status)); +} + +/******************************************************************* + makes a FILE_INFO_3_STR structure +********************************************************************/ +void make_srv_file_info3_str(FILE_INFO_3_STR *fi3, char *user_name, char *path_name) +{ + if (fi3 == NULL) return; + + DEBUG(5,("make_srv_file_info3_str\n")); + + make_unistr2(&(fi3->uni_path_name), path_name, strlen(path_name)+1); + make_unistr2(&(fi3->uni_user_name), user_name, strlen(user_name)+1); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_file_info3_str(char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth) +{ + if (sh1 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_file_info3_str"); + depth++; + + prs_align(ps); + + smb_io_unistr2("", &(sh1->uni_path_name), True, ps, depth); + smb_io_unistr2("", &(sh1->uni_user_name), True, ps, depth); +} + +/******************************************************************* + makes a FILE_INFO_3 structure +********************************************************************/ +void make_srv_file_info3(FILE_INFO_3 *fl3, + uint32 id, uint32 perms, uint32 num_locks, + char *path_name, char *user_name) +{ + if (fl3 == NULL) return; + + DEBUG(5,("make_srv_file_info3: %s %s\n", path_name, user_name)); + + fl3->id = id; + fl3->perms = perms; + fl3->num_locks = num_locks; + + fl3->ptr_path_name = path_name != NULL ? 1 : 0; + fl3->ptr_user_name = user_name != NULL ? 1 : 0; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_file_info3(char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth) +{ + if (fl3 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_file_info3"); + depth++; + + prs_align(ps); + + prs_uint32("id ", ps, depth, &(fl3->id )); + prs_uint32("perms ", ps, depth, &(fl3->perms )); + prs_uint32("num_locks ", ps, depth, &(fl3->num_locks )); + prs_uint32("ptr_path_name", ps, depth, &(fl3->ptr_path_name)); + prs_uint32("ptr_user_name", ps, depth, &(fl3->ptr_user_name)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_file_info_3(char *desc, SRV_FILE_INFO_3 *fl3, prs_struct *ps, int depth) +{ + if (fl3 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_file_3_fl3"); + depth++; + + prs_align(ps); + + prs_uint32("num_entries_read", ps, depth, &(fl3->num_entries_read)); + prs_uint32("ptr_file_fl3", ps, depth, &(fl3->ptr_file_info)); + if (fl3->ptr_file_info != 0) + { + int i; + int num_entries = fl3->num_entries_read; + if (num_entries > MAX_FILE_ENTRIES) + { + num_entries = MAX_FILE_ENTRIES; /* report this! */ + } + + prs_uint32("num_entries_read2", ps, depth, &(fl3->num_entries_read2)); + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_file_info3("", &(fl3->info_3[i]), ps, depth); + } + + for (i = 0; i < num_entries; i++) + { + prs_grow(ps); + srv_io_file_info3_str("", &(fl3->info_3_str[i]), ps, depth); + } + + prs_align(ps); + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_srv_file_ctr(char *desc, SRV_FILE_INFO_CTR *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_srv_file_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(ctr->switch_value)); + prs_uint32("ptr_file_ctr", ps, depth, &(ctr->ptr_file_ctr)); + + if (ctr->ptr_file_ctr != 0) + { + switch (ctr->switch_value) + { + case 3: + { + srv_io_srv_file_info_3("", &(ctr->file.info3), ps, depth); + break; + } + default: + { + DEBUG(5,("%s no file info at switch_value %d\n", + tab_depth(depth), ctr->switch_value)); + break; + } + } + } +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void make_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, + char *srv_name, char *qual_name, + uint32 file_level, SRV_FILE_INFO_CTR *ctr, + uint32 preferred_len, + ENUM_HND *hnd) +{ + if (q_n == NULL || ctr == NULL || hnd == NULL) return; + + q_n->ctr = ctr; + + DEBUG(5,("make_q_net_file_enum\n")); + + make_buf_unistr2(&(q_n->uni_srv_name), &(q_n->ptr_srv_name), srv_name); + make_buf_unistr2(&(q_n->uni_qual_name), &(q_n->ptr_qual_name), qual_name); + + q_n->file_level = file_level; + q_n->preferred_len = preferred_len; + + memcpy(&(q_n->enum_hnd), hnd, sizeof(*hnd)); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_q_net_file_enum(char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_file_enum"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name", ps, depth, &(q_n->ptr_srv_name)); + smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); + + prs_align(ps); + + prs_uint32("ptr_qual_name", ps, depth, &(q_n->ptr_qual_name)); + smb_io_unistr2("", &(q_n->uni_qual_name), True, ps, depth); + + prs_align(ps); + + prs_uint32("file_level", ps, depth, &(q_n->file_level )); + + if (q_n->file_level != -1) + { + srv_io_srv_file_ctr("file_ctr", q_n->ctr, ps, depth); + } + + prs_uint32("preferred_len", ps, depth, &(q_n->preferred_len)); + + smb_io_enum_hnd("enum_hnd", &(q_n->enum_hnd), ps, depth); +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_r_net_file_enum(char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_r_net_file_enum"); + depth++; + + prs_align(ps); + + prs_uint32("file_level", ps, depth, &(r_n->file_level)); + + if (r_n->file_level != 0) + { + srv_io_srv_file_ctr("file_ctr", r_n->ctr, ps, depth); + } + + prs_uint32("total_entries", ps, depth, &(r_n->total_entries)); + smb_io_enum_hnd("enum_hnd", &(r_n->enum_hnd), ps, depth); + prs_uint32("status ", ps, depth, &(r_n->status)); +} + +/******************************************************************* + makes a SRV_INFO_101 structure. + ********************************************************************/ +void make_srv_info_101(SRV_INFO_101 *sv101, uint32 platform_id, char *name, + uint32 ver_major, uint32 ver_minor, + uint32 srv_type, char *comment) +{ + if (sv101 == NULL) return; + + DEBUG(5,("make_srv_info_101\n")); + + sv101->platform_id = platform_id; + make_buf_unistr2(&(sv101->uni_name ), &(sv101->ptr_name ) , name ); + sv101->ver_major = ver_major; + sv101->ver_minor = ver_minor; + sv101->srv_type = srv_type; + make_buf_unistr2(&(sv101->uni_comment ), &(sv101->ptr_comment) , comment ); +} + + +/******************************************************************* + reads or writes a SRV_INFO_101 structure. + ********************************************************************/ +void srv_io_info_101(char *desc, SRV_INFO_101 *sv101, prs_struct *ps, int depth) +{ + if (sv101 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_info_101"); + depth++; + + prs_align(ps); + + prs_uint32("platform_id ", ps, depth, &(sv101->platform_id )); + prs_uint32("ptr_name ", ps, depth, &(sv101->ptr_name )); + prs_uint32("ver_major ", ps, depth, &(sv101->ver_major )); + prs_uint32("ver_minor ", ps, depth, &(sv101->ver_minor )); + prs_uint32("srv_type ", ps, depth, &(sv101->srv_type )); + prs_uint32("ptr_comment ", ps, depth, &(sv101->ptr_comment )); + + prs_align(ps); + + smb_io_unistr2("uni_name ", &(sv101->uni_name ), True, ps, depth); + smb_io_unistr2("uni_comment ", &(sv101->uni_comment ), True, ps, depth); +} + +/******************************************************************* + makes a SRV_INFO_102 structure. + ********************************************************************/ +void make_srv_info_102(SRV_INFO_102 *sv102, uint32 platform_id, char *name, + char *comment, uint32 ver_major, uint32 ver_minor, + uint32 srv_type, uint32 users, uint32 disc, uint32 hidden, + uint32 announce, uint32 ann_delta, uint32 licenses, + char *usr_path) +{ + if (sv102 == NULL) return; + + DEBUG(5,("make_srv_info_102\n")); + + sv102->platform_id = platform_id; + make_buf_unistr2(&(sv102->uni_name ), &(sv102->ptr_name ), name ); + sv102->ver_major = ver_major; + sv102->ver_minor = ver_minor; + sv102->srv_type = srv_type; + make_buf_unistr2(&(sv102->uni_comment ), &(sv102->ptr_comment ), comment ); + + /* same as 101 up to here */ + + sv102->users = users; + sv102->disc = disc; + sv102->hidden = hidden; + sv102->announce = announce; + sv102->ann_delta =ann_delta; + sv102->licenses = licenses; + make_buf_unistr2(&(sv102->uni_usr_path), &(sv102->ptr_usr_path), usr_path); +} + + +/******************************************************************* + reads or writes a SRV_INFO_102 structure. + ********************************************************************/ +void srv_io_info_102(char *desc, SRV_INFO_102 *sv102, prs_struct *ps, int depth) +{ + if (sv102 == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_info102"); + depth++; + + prs_align(ps); + + prs_uint32("platform_id ", ps, depth, &(sv102->platform_id )); + prs_uint32("ptr_name ", ps, depth, &(sv102->ptr_name )); + prs_uint32("ver_major ", ps, depth, &(sv102->ver_major )); + prs_uint32("ver_minor ", ps, depth, &(sv102->ver_minor )); + prs_uint32("srv_type ", ps, depth, &(sv102->srv_type )); + prs_uint32("ptr_comment ", ps, depth, &(sv102->ptr_comment )); + + /* same as 101 up to here */ + + prs_uint32("users ", ps, depth, &(sv102->users )); + prs_uint32("disc ", ps, depth, &(sv102->disc )); + prs_uint32("hidden ", ps, depth, &(sv102->hidden )); + prs_uint32("announce ", ps, depth, &(sv102->announce )); + prs_uint32("ann_delta ", ps, depth, &(sv102->ann_delta )); + prs_uint32("licenses ", ps, depth, &(sv102->licenses )); + prs_uint32("ptr_usr_path", ps, depth, &(sv102->ptr_usr_path)); + + smb_io_unistr2("uni_name ", &(sv102->uni_name ), True, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_comment ", &(sv102->uni_comment ), True, ps, depth); + prs_align(ps); + smb_io_unistr2("uni_usr_path", &(sv102->uni_usr_path), True, ps, depth); +} + +/******************************************************************* + reads or writes a SRV_INFO_102 structure. + ********************************************************************/ +void srv_io_info_ctr(char *desc, SRV_INFO_CTR *ctr, prs_struct *ps, int depth) +{ + if (ctr == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_info_ctr"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(ctr->switch_value)); + prs_uint32("ptr_srv_ctr ", ps, depth, &(ctr->ptr_srv_ctr )); + + if (ctr->ptr_srv_ctr != 0 && ctr->switch_value != 0 && ctr != NULL) + { + switch (ctr->switch_value) + { + case 101: + { + srv_io_info_101("sv101", &(ctr->srv.sv101), ps, depth); + break; + } + case 102: + { + srv_io_info_102("sv102", &(ctr->srv.sv102), ps, depth); + break; + } + default: + { + DEBUG(5,("%s% no server info at switch_value %d\n", + tab_depth(depth), ctr->switch_value)); + break; + } + } + } +} + +/******************************************************************* + makes a SRV_Q_NET_SRV_GET_INFO structure. + ********************************************************************/ +void make_srv_q_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *srv, + char *server_name, uint32 switch_value) +{ + if (srv == NULL) return; + + DEBUG(5,("make_srv_q_net_srv_get_info\n")); + + make_buf_unistr2(&(srv->uni_srv_name), &(srv->ptr_srv_name), server_name); + + srv->switch_value = switch_value; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_q_net_srv_get_info(char *desc, SRV_Q_NET_SRV_GET_INFO *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_srv_get_info"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name ", ps, depth, &(q_n->ptr_srv_name)); + smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); + + prs_align(ps); + + prs_uint32("switch_value ", ps, depth, &(q_n->switch_value)); +} + +/******************************************************************* + makes a SRV_R_NET_SRV_GET_INFO structure. + ********************************************************************/ +void make_srv_r_net_srv_get_info(SRV_R_NET_SRV_GET_INFO *srv, + uint32 switch_value, SRV_INFO_CTR *ctr, uint32 status) +{ + if (srv == NULL) return; + + DEBUG(5,("make_srv_r_net_srv_get_info\n")); + + srv->ctr = ctr; + + if (status == 0x0) + { + srv->ctr->switch_value = switch_value; + srv->ctr->ptr_srv_ctr = 1; + } + else + { + srv->ctr->switch_value = 0; + srv->ctr->ptr_srv_ctr = 0; + } + + srv->status = status; +} + +/******************************************************************* + reads or writes a structure. + ********************************************************************/ +void srv_io_r_net_srv_get_info(char *desc, SRV_R_NET_SRV_GET_INFO *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_r_net_srv_get_info"); + depth++; + + prs_align(ps); + + srv_io_info_ctr("ctr", r_n->ctr, ps, depth); + + prs_uint32("status ", ps, depth, &(r_n->status )); +} + + +/******************************************************************* + makes a SRV_Q_NET_SRV_SET_INFO structure. + ********************************************************************/ +void make_srv_q_net_srv_set_info(SRV_Q_NET_SRV_SET_INFO *srv, + uint32 switch_value, SRV_INFO_CTR *ctr) +{ + if (srv == NULL) return; + + DEBUG(5,("make_srv_r_net_srv_set_info\n")); + + srv->ctr = ctr; + + srv->ctr->switch_value = switch_value; + srv->ctr->ptr_srv_ctr = 1; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void srv_io_q_net_srv_set_info(char *desc, SRV_Q_NET_SRV_SET_INFO *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_srv_set_info"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name ", ps, depth, &(q_n->ptr_srv_name)); + smb_io_unistr2("", &(q_n->uni_srv_name), True, ps, depth); + + prs_align(ps); + + srv_io_info_ctr("ctr", q_n->ctr, ps, depth); +} + +/******************************************************************* + makes a SRV_R_NET_SRV_SET_INFO structure. + ********************************************************************/ +void make_srv_r_net_srv_set_info(SRV_R_NET_SRV_SET_INFO *srv, + uint32 switch_value, SRV_INFO_CTR *ctr, uint32 status) +{ + if (srv == NULL) return; + + DEBUG(5,("make_srv_r_net_srv_set_info\n")); + + if (status == 0x0) + { + srv->switch_value = switch_value; + } + else + { + srv->switch_value = 0; + } + + srv->status = status; +} + +/******************************************************************* + reads or writes a structure. + ********************************************************************/ +void srv_io_r_net_srv_set_info(char *desc, SRV_R_NET_SRV_SET_INFO *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) return; + + prs_debug(ps, depth, desc, "srv_io_q_net_srv_set_info"); + depth++; + + prs_align(ps); + + prs_uint32("switch_value", ps, depth, &(r_n->switch_value)); + prs_uint32("status ", ps, depth, &(r_n->status )); +} + + diff --git a/source3/rpc_parse/parse_wks.c b/source3/rpc_parse/parse_wks.c new file mode 100644 index 0000000000..694acb5eec --- /dev/null +++ b/source3/rpc_parse/parse_wks.c @@ -0,0 +1,146 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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" + +extern int DEBUGLEVEL; + + +/******************************************************************* + make_wks_q_query_info + ********************************************************************/ +void make_wks_q_query_info(WKS_Q_QUERY_INFO *q_u, + char *server, uint16 switch_value) +{ + DEBUG(5,("make_wks_q_query_info: %d\n", __LINE__)); + + make_buf_unistr2(&(q_u->uni_srv_name), &(q_u->ptr_srv_name), server); + q_u->switch_value = switch_value; + +} + +/******************************************************************* +reads or writes a WKS_Q_QUERY_INFO structure. +********************************************************************/ +void wks_io_q_query_info(char *desc, WKS_Q_QUERY_INFO *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) return; + + prs_debug(ps, depth, desc, "wks_io_q_query_info"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_srv_name", ps, depth, &(q_u->ptr_srv_name)); + smb_io_unistr2("", &(q_u->uni_srv_name), q_u->ptr_srv_name, ps, depth); + prs_align(ps); + + prs_uint16("switch_value", ps, depth, &(q_u->switch_value)); + prs_align(ps); +} + +/******************************************************************* + wks_info_100 + ********************************************************************/ +void make_wks_info_100(WKS_INFO_100 *inf, + uint32 platform_id, uint32 ver_major, uint32 ver_minor, + char *my_name, char *domain_name) +{ + DEBUG(5,("WKS_INFO_100: %d\n", __LINE__)); + + inf->platform_id = platform_id; /* 0x0000 01f4 - unknown */ + inf->ver_major = ver_major; /* os major version */ + inf->ver_minor = ver_minor; /* os minor version */ + + make_buf_unistr2(&(inf->uni_compname), &(inf->ptr_compname), my_name ); + make_buf_unistr2(&(inf->uni_lan_grp ), &(inf->ptr_lan_grp ), domain_name); +} + +/******************************************************************* +reads or writes a WKS_INFO_100 structure. +********************************************************************/ +void wks_io_wks_info_100(char *desc, WKS_INFO_100 *inf, prs_struct *ps, int depth) +{ + if (inf == NULL) return; + + prs_debug(ps, depth, desc, "wks_io_wks_info_100"); + depth++; + + prs_align(ps); + + prs_uint32("platform_id ", ps, depth, &(inf->platform_id )); /* 0x0000 01f4 - unknown */ + prs_uint32("ptr_compname", ps, depth, &(inf->ptr_compname)); /* pointer to computer name */ + prs_uint32("ptr_lan_grp ", ps, depth, &(inf->ptr_lan_grp )); /* pointer to LAN group name */ + prs_uint32("ver_major ", ps, depth, &(inf->ver_major )); /* 4 - major os version */ + prs_uint32("ver_minor ", ps, depth, &(inf->ver_minor )); /* 0 - minor os version */ + + smb_io_unistr2("", &(inf->uni_compname), inf->ptr_compname, ps, depth); + prs_align(ps); + + smb_io_unistr2("", &(inf->uni_lan_grp ), inf->ptr_lan_grp , ps, depth); + prs_align(ps); +} + +/******************************************************************* + make_wks_r_query_info + + only supports info level 100 at the moment. + + ********************************************************************/ +void make_wks_r_query_info(WKS_R_QUERY_INFO *r_u, + uint32 switch_value, WKS_INFO_100 *wks100, + int status) +{ + DEBUG(5,("make_wks_r_unknown_0: %d\n", __LINE__)); + + r_u->switch_value = switch_value; /* same as in request */ + + r_u->ptr_1 = 1; /* pointer 1 */ + r_u->wks100 = wks100; + + r_u->status = status; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +void wks_io_r_query_info(char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) return; + + prs_debug(ps, depth, desc, "wks_io_r_query_info"); + depth++; + + prs_align(ps); + + prs_uint16("switch_value", ps, depth, &(r_u->switch_value)); /* level 100 (0x64) */ + prs_align(ps); + + prs_uint32("ptr_1 ", ps, depth, &(r_u->ptr_1 )); /* pointer 1 */ + wks_io_wks_info_100("inf", r_u->wks100, ps, depth); + + prs_uint32("status ", ps, depth, &(r_u->status)); +} + diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c new file mode 100644 index 0000000000..60b74cf599 --- /dev/null +++ b/source3/rpc_server/srv_lsa.c @@ -0,0 +1,444 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + + +/*************************************************************************** +lsa_reply_open_policy + ***************************************************************************/ +static void lsa_reply_open_policy(prs_struct *rdata) +{ + int i; + LSA_R_OPEN_POL r_o; + + /* set up the LSA QUERY INFO response */ + bzero(&(r_o.pol.data), POL_HND_SIZE); + for (i = 4; i < POL_HND_SIZE; i++) + { + r_o.pol.data[i] = i; + } + r_o.status = 0x0; + + /* store the response in the SMB stream */ + lsa_io_r_open_pol("", &r_o, rdata, 0); +} + +/*************************************************************************** +make_dom_query + ***************************************************************************/ +static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) +{ + int domlen = strlen(dom_name); + + d_q->uni_dom_max_len = domlen * 2; + d_q->uni_dom_str_len = domlen * 2; + + d_q->buffer_dom_name = 4; /* domain buffer pointer */ + d_q->buffer_dom_sid = 2; /* domain sid pointer */ + + /* this string is supposed to be character short */ + make_unistr2(&(d_q->uni_domain_name), dom_name, domlen); + + make_dom_sid2(&(d_q->dom_sid), dom_sid); +} + +/*************************************************************************** +lsa_reply_query_info + ***************************************************************************/ +static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e, + prs_struct *rdata, + uint32 enum_context, char *dom_name, char *dom_sid) +{ + LSA_R_ENUM_TRUST_DOM r_e; + + /* set up the LSA QUERY INFO response */ + make_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid, + dom_name != NULL ? 0x0 : 0x80000000 | NT_STATUS_UNABLE_TO_FREE_VM); + + /* store the response in the SMB stream */ + lsa_io_r_enum_trust_dom("", &r_e, rdata, 0); +} + +/*************************************************************************** +lsa_reply_query_info + ***************************************************************************/ +static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata, + char *dom_name, char *dom_sid) +{ + LSA_R_QUERY_INFO r_q; + + /* set up the LSA QUERY INFO response */ + + r_q.undoc_buffer = 0x22000000; /* bizarre */ + r_q.info_class = q_q->info_class; + + make_dom_query(&r_q.dom.id5, dom_name, dom_sid); + + r_q.status = 0x0; + + /* store the response in the SMB stream */ + lsa_io_r_query("", &r_q, rdata, 0); +} + +/*************************************************************************** +make_dom_ref + + pretty much hard-coded choice of "other" sids, unfortunately... + + ***************************************************************************/ +static void make_dom_ref(DOM_R_REF *ref, + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int len_dom_name = strlen(dom_name); + int len_other_sid1 = strlen(other_sid1); + int len_other_sid2 = strlen(other_sid2); + int len_other_sid3 = strlen(other_sid3); + + ref->undoc_buffer = 1; + ref->num_ref_doms_1 = 4; + ref->buffer_dom_name = 1; + ref->max_entries = 32; + ref->num_ref_doms_2 = 4; + + make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); + make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); + make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); + + if (dom_name != NULL) + { + make_unistr(&(ref->uni_dom_name), dom_name); + } + + make_dom_sid2(&(ref->ref_dom[0]), dom_sid ); + make_dom_sid2(&(ref->ref_dom[1]), other_sid1); + make_dom_sid2(&(ref->ref_dom[2]), other_sid2); + make_dom_sid2(&(ref->ref_dom[3]), other_sid3); +} + +/*************************************************************************** +make_reply_lookup_rids + ***************************************************************************/ +static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + int i; + + make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, + other_sid1, other_sid2, other_sid3); + + r_l->num_entries = num_entries; + r_l->undoc_buffer = 1; + r_l->num_entries2 = num_entries; + + for (i = 0; i < num_entries; i++) + { + make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); + } + + r_l->num_entries3 = num_entries; +} + +/*************************************************************************** +make_lsa_trans_names + ***************************************************************************/ +static void make_lsa_trans_names(LSA_TRANS_NAME_ENUM *trn, + int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], + uint32 *total) +{ + uint32 status = 0x0; + int i; + (*total) = 0; + + for (i = 0; i < num_entries; i++) + { + uint32 rid = 0xffffffff; + uint8 num_auths = sid[i].sid.num_auths; + fstring name; + uint32 type; + + trn->ptr_name[i] = 0; + trn->ptr_name[(*total)] = 0; + + /* find the rid to look up */ + if (num_auths != 0) + { + rid = sid[i].sid.sub_auths[num_auths-1]; + + status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + + status = (status != 0x0) ? lookup_user_name (rid, name, &type) : status; + status = (status != 0x0) ? lookup_group_name(rid, name, &type) : status; + status = (status != 0x0) ? lookup_alias_name(rid, name, &type) : status; + } + + if (status == 0x0) + { + trn->ptr_name[i] = 1; + make_lsa_trans_name(&(trn->name[(*total)]), type, name, (*total)); + (*total)++; + } + } + + trn->num_entries = (*total); + trn->ptr_trans_names = 1; + trn->num_entries2 = (*total); +} + +/*************************************************************************** +make_reply_lookup_sids + ***************************************************************************/ +static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, + DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names, + uint32 mapped_count, uint32 status) +{ + r_l->dom_ref = ref; + r_l->names = names; + r_l->mapped_count = mapped_count; + r_l->status = status; +} + +/*************************************************************************** +lsa_reply_lookup_sids + ***************************************************************************/ +static void lsa_reply_lookup_sids(prs_struct *rdata, + int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + LSA_R_LOOKUP_SIDS r_l; + DOM_R_REF ref; + LSA_TRANS_NAME_ENUM names; + uint32 mapped_count = 0; + + /* set up the LSA Lookup SIDs response */ + make_dom_ref(&ref, dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + make_lsa_trans_names(&names, num_entries, sid, &mapped_count); + make_reply_lookup_sids(&r_l, &ref, &names, mapped_count, 0x0); + + /* store the response in the SMB stream */ + lsa_io_r_lookup_sids("", &r_l, rdata, 0); +} + +/*************************************************************************** +lsa_reply_lookup_rids + ***************************************************************************/ +static void lsa_reply_lookup_rids(prs_struct *rdata, + int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], + char *dom_name, char *dom_sid, + char *other_sid1, char *other_sid2, char *other_sid3) +{ + LSA_R_LOOKUP_RIDS r_l; + + /* set up the LSA Lookup RIDs response */ + make_reply_lookup_rids(&r_l, num_entries, dom_rids, + dom_name, dom_sid, other_sid1, other_sid2, other_sid3); + r_l.status = 0x0; + + /* store the response in the SMB stream */ + lsa_io_r_lookup_rids("", &r_l, rdata, 0); +} + +/*************************************************************************** +api_lsa_open_policy + ***************************************************************************/ +static void api_lsa_open_policy( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_OPEN_POL q_o; + + /* grab the server, object attributes and desired access flag...*/ + lsa_io_q_open_pol("", &q_o, data, 0); + + /* lkclXXXX having decoded it, ignore all fields in the open policy! */ + + /* return a 20 byte policy handle */ + lsa_reply_open_policy(rdata); +} + +/*************************************************************************** +api_lsa_enum_trust_dom + ***************************************************************************/ +static void api_lsa_enum_trust_dom( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_ENUM_TRUST_DOM q_e; + + /* grab the enum trust domain context etc. */ + lsa_io_q_enum_trust_dom("", &q_e, data, 0); + + /* construct reply. return status is always 0x0 */ + lsa_reply_enum_trust_dom(&q_e, rdata, + 0, NULL, NULL); +} + +/*************************************************************************** +api_lsa_query_info + ***************************************************************************/ +static void api_lsa_query_info( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_QUERY_INFO q_i; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_query("", &q_i, data, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domain_sid()); + + /* construct reply. return status is always 0x0 */ + lsa_reply_query_info(&q_i, rdata, dom_name, dom_sid); +} + +/*************************************************************************** +api_lsa_lookup_sids + ***************************************************************************/ +static void api_lsa_lookup_sids( int uid, prs_struct *data, + prs_struct *rdata ) +{ + LSA_Q_LOOKUP_SIDS q_l; + pstring dom_name; + pstring dom_sid; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_sids("", &q_l, data, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domain_sid()); + + /* construct reply. return status is always 0x0 */ + lsa_reply_lookup_sids(rdata, + q_l.sids.num_entries, q_l.sids.sid, /* SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ +} + +/*************************************************************************** +api_lsa_lookup_names + ***************************************************************************/ +static void api_lsa_lookup_names( int uid, prs_struct *data, + prs_struct *rdata ) +{ + int i; + LSA_Q_LOOKUP_RIDS q_l; + pstring dom_name; + pstring dom_sid; + uint32 dom_rids[MAX_LOOKUP_SIDS]; + uint32 dummy_g_rid; + + /* grab the info class and policy handle */ + lsa_io_q_lookup_rids("", &q_l, data, 0); + + pstrcpy(dom_name, lp_workgroup()); + pstrcpy(dom_sid , lp_domain_sid()); + + /* convert received RIDs to strings, so we can do them. */ + for (i = 0; i < q_l.num_entries; i++) + { + char *user_name = unistr2(q_l.lookup_name[i].str.buffer); + if (!name_to_rid(user_name, &dom_rids[i], &dummy_g_rid)) + { + /* WHOOPS! we should really do something about this... */ + dom_rids[i] = 0; + } + } + + /* construct reply. return status is always 0x0 */ + lsa_reply_lookup_rids(rdata, + q_l.num_entries, dom_rids, /* text-converted SIDs */ + dom_name, dom_sid, /* domain name, domain SID */ + "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ +} + +/*************************************************************************** + api_lsa_close + ***************************************************************************/ +static void api_lsa_close( int uid, prs_struct *data, + prs_struct *rdata) +{ + /* XXXX this is NOT good */ + char *q = mem_data(&(rdata->data), rdata->offset); + + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + + rdata->offset += 24; +} + +/*************************************************************************** + api_lsa_open_secret + ***************************************************************************/ +static void api_lsa_open_secret( int uid, prs_struct *data, + prs_struct *rdata) +{ + /* XXXX this is NOT good */ + char *q = mem_data(&(rdata->data), rdata->offset); + + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0); q += 4; + SIVAL(q, 0, 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND); q += 4; + + rdata->offset += 24; +} + +/*************************************************************************** + \PIPE\ntlsa commands + ***************************************************************************/ +static struct api_struct api_lsa_cmds[] = +{ + { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, + { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info }, + { "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom }, + { "LSA_CLOSE" , LSA_CLOSE , api_lsa_close }, + { "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret }, + { "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids }, + { "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names }, + { NULL , 0 , NULL } +}; + +/*************************************************************************** + api_ntLsarpcTNP + ***************************************************************************/ +BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_ntlsa_rpc", api_lsa_cmds, data); +} + diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c new file mode 100644 index 0000000000..c8eabf35b4 --- /dev/null +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -0,0 +1,316 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * + * 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" + + +extern int DEBUGLEVEL; + +#ifndef MAX_OPEN_POLS +#define MAX_OPEN_POLS 50 +#endif + +struct reg_info +{ + /* for use by \PIPE\winreg */ + fstring name; /* name of registry key */ +}; + +struct samr_info +{ + /* for use by the \PIPE\samr policy */ + DOM_SID sid; + uint32 rid; /* relative id associated with the pol_hnd */ + uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */ +}; + +static struct +{ + BOOL open; + POLICY_HND pol_hnd; + + union + { + struct samr_info samr; + struct reg_info reg; + + } dev; + +} Policy[MAX_OPEN_POLS]; + + +#define VALID_POL(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_POLS)) +#define OPEN_POL(pnum) (VALID_POL(pnum) && Policy[pnum].open) + +/**************************************************************************** + create a unique policy handle +****************************************************************************/ +void create_pol_hnd(POLICY_HND *hnd) +{ + static uint32 pol_hnd_low = 0; + static uint32 pol_hnd_high = 0; + + if (hnd == NULL) return; + + /* i severely doubt that pol_hnd_high will ever be non-zero... */ + pol_hnd_low++; + if (pol_hnd_low == 0) pol_hnd_high++; + + SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */ + SIVAL(hnd->data, 4 , pol_hnd_low ); /* second bit is incrementing */ + SIVAL(hnd->data, 8 , pol_hnd_high); /* second bit is incrementing */ + SIVAL(hnd->data, 12, time(NULL)); /* something random */ + SIVAL(hnd->data, 16, getpid()); /* something more random */ +} + +/**************************************************************************** + initialise policy handle states... +****************************************************************************/ +void init_lsa_policy_hnd(void) +{ + int i; + for (i = 0; i < MAX_OPEN_POLS; i++) + { + Policy[i].open = False; + } + + return; +} + +/**************************************************************************** + find first available policy slot. creates a policy handle for you. +****************************************************************************/ +BOOL open_lsa_policy_hnd(POLICY_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_POLS; i++) + { + if (!Policy[i].open) + { + Policy[i].open = True; + + create_pol_hnd(hnd); + memcpy(&(Policy[i].pol_hnd), hnd, sizeof(*hnd)); + + DEBUG(4,("Opened policy hnd[%x] ", i)); + dump_data(4, hnd->data, sizeof(hnd->data)); + + return True; + } + } + + /* i love obscure error messages. */ +#if TERRY_PRATCHET_INTERESTING_TIMES + DEBUG(1,("+++ OUT OF CHEESE ERROR +++ REDO FROM START ... @?!*@@\n")); +#else + DEBUG(1,("ERROR - open_lsa_policy_hnd: out of Policy Handles!\n")); +#endif + + return False; +} + +/**************************************************************************** + find policy index by handle +****************************************************************************/ +int find_lsa_policy_by_hnd(POLICY_HND *hnd) +{ + int i; + + for (i = 0; i < MAX_OPEN_POLS; i++) + { + if (memcmp(&(Policy[i].pol_hnd), hnd, sizeof(*hnd)) == 0) + { + DEBUG(4,("Found policy hnd[%x] ", i)); + dump_data(4, hnd->data, sizeof(hnd->data)); + + return i; + } + } + + DEBUG(4,("Policy not found: ")); + dump_data(4, hnd->data, sizeof(hnd->data)); + + return -1; +} + +/**************************************************************************** + set samr rid +****************************************************************************/ +BOOL set_lsa_policy_samr_rid(POLICY_HND *hnd, uint32 rid) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy device rid=%x pnum=%x\n", + timestring(), rid, pnum)); + + Policy[pnum].dev.samr.rid = rid; + return True; + } + else + { + DEBUG(3,("%s Error setting policy rid=%x (pnum=%x)\n", + timestring(), rid, pnum)); + return False; + } +} + +/**************************************************************************** + set samr pol status. absolutely no idea what this is. +****************************************************************************/ +BOOL set_lsa_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy status=%x pnum=%x\n", + timestring(), pol_status, pnum)); + + Policy[pnum].dev.samr.status = pol_status; + return True; + } + else + { + DEBUG(3,("%s Error setting policy status=%x (pnum=%x)\n", + timestring(), pol_status, pnum)); + return False; + } +} + +/**************************************************************************** + set samr sid +****************************************************************************/ +BOOL set_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy sid=%s pnum=%x\n", + timestring(), dom_sid_to_string(sid), pnum)); + + memcpy(&(Policy[pnum].dev.samr.sid), sid, sizeof(*sid)); + return True; + } + else + { + DEBUG(3,("%s Error setting policy sid=%s (pnum=%x)\n", + timestring(), dom_sid_to_string(sid), pnum)); + return False; + } +} + +/**************************************************************************** + set samr rid +****************************************************************************/ +uint32 get_lsa_policy_samr_rid(POLICY_HND *hnd) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + uint32 rid = Policy[pnum].dev.samr.rid; + DEBUG(3,("%s Getting policy device rid=%x pnum=%x\n", + timestring(), rid, pnum)); + + return rid; + } + else + { + DEBUG(3,("%s Error getting policy (pnum=%x)\n", + timestring(), pnum)); + return 0xffffffff; + } +} + +/**************************************************************************** + set reg name +****************************************************************************/ +BOOL set_lsa_policy_reg_name(POLICY_HND *hnd, fstring name) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Setting policy pnum=%x name=%s\n", + timestring(), pnum, name)); + + fstrcpy(Policy[pnum].dev.reg.name, name); + return True; + } + else + { + DEBUG(3,("%s Error setting policy (pnum=%x) name=%s\n", + timestring(), pnum, name)); + return False; + } +} + +/**************************************************************************** + get reg name +****************************************************************************/ +BOOL get_lsa_policy_reg_name(POLICY_HND *hnd, fstring name) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + fstrcpy(name, Policy[pnum].dev.reg.name); + + DEBUG(3,("%s Getting policy pnum=%x name=%s\n", + timestring(), pnum, name)); + + return True; + } + else + { + DEBUG(3,("%s Error getting policy (pnum=%x)\n", + timestring(), pnum)); + return False; + } +} + +/**************************************************************************** + close an lsa policy +****************************************************************************/ +BOOL close_lsa_policy_hnd(POLICY_HND *hnd) +{ + int pnum = find_lsa_policy_by_hnd(hnd); + + if (OPEN_POL(pnum)) + { + DEBUG(3,("%s Closed policy name pnum=%x\n", timestring(), pnum)); + Policy[pnum].open = False; + return True; + } + else + { + DEBUG(3,("%s Error closing policy pnum=%x\n", timestring(), pnum)); + return False; + } +} + diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c new file mode 100644 index 0000000000..94d6faa992 --- /dev/null +++ b/source3/rpc_server/srv_netlog.c @@ -0,0 +1,832 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + +extern BOOL sam_logon_in_ssb; +extern pstring samlogon_user; + + + +/************************************************************************* + make_net_r_req_chal: + *************************************************************************/ +static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c, + DOM_CHAL *srv_chal, int status) +{ + DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__)); + memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data)); + r_c->status = status; +} + +/************************************************************************* + net_reply_req_chal: + *************************************************************************/ +static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata, + DOM_CHAL *srv_chal, uint32 srv_time) +{ + NET_R_REQ_CHAL r_c; + + DEBUG(6,("net_reply_req_chal: %d\n", __LINE__)); + + /* set up the LSA REQUEST CHALLENGE response */ + make_net_r_req_chal(&r_c, srv_chal, srv_time); + + /* store the response in the SMB stream */ + net_io_r_req_chal("", &r_c, rdata, 0); + + DEBUG(6,("net_reply_req_chal: %d\n", __LINE__)); + +} + +/************************************************************************* + net_reply_logon_ctrl2: + *************************************************************************/ +static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata, + uint32 flags, uint32 pdc_status, uint32 logon_attempts, + uint32 tc_status, char *trust_domain_name) +{ + NET_R_LOGON_CTRL2 r_l; + + DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__)); + + /* set up the Logon Control2 response */ + make_r_logon_ctrl2(&r_l, q_l->query_level, + flags, pdc_status, logon_attempts, + tc_status, trust_domain_name); + + /* store the response in the SMB stream */ + net_io_r_logon_ctrl2("", &r_l, rdata, 0); + + DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__)); + +} + +/************************************************************************* + net_reply_trust_dom_list: + *************************************************************************/ +static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata, + uint32 num_trust_domains, char *trust_domain_name) +{ + NET_R_TRUST_DOM_LIST r_t; + + DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__)); + + /* set up the Trusted Domain List response */ + make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name); + + /* store the response in the SMB stream */ + net_io_r_trust_dom("", &r_t, rdata, 0); + + DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__)); + +} + +/************************************************************************* + make_net_r_auth_2: + *************************************************************************/ +static void make_net_r_auth_2(NET_R_AUTH_2 *r_a, + DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status) +{ + memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data)); + memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs)); + r_a->status = status; +} + +/************************************************************************* + net_reply_auth_2: + *************************************************************************/ +static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata, + DOM_CHAL *resp_cred, int status) +{ + NET_R_AUTH_2 r_a; + + /* set up the LSA AUTH 2 response */ + + make_net_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); + + /* store the response in the SMB stream */ + net_io_r_auth_2("", &r_a, rdata, 0); + +} + +/*********************************************************************************** + make_net_r_srv_pwset: + ***********************************************************************************/ +static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s, + DOM_CRED *srv_cred, int status) +{ + DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__)); + + memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred)); + r_s->status = status; + + DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__)); +} + +/************************************************************************* + net_reply_srv_pwset: + *************************************************************************/ +static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata, + DOM_CRED *srv_cred, int status) +{ + NET_R_SRV_PWSET r_s; + + DEBUG(5,("net_srv_pwset: %d\n", __LINE__)); + + /* set up the LSA Server Password Set response */ + make_net_r_srv_pwset(&r_s, srv_cred, status); + + /* store the response in the SMB stream */ + net_io_r_srv_pwset("", &r_s, rdata, 0); + + DEBUG(5,("net_srv_pwset: %d\n", __LINE__)); + +} + +/************************************************************************* + net_reply_sam_logon: + *************************************************************************/ +static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata, + DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info, + uint32 status) +{ + NET_R_SAM_LOGON r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); + + /* store the user information, if there is any. */ + r_s.user = user_info; + if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0) + { + r_s.switch_value = 3; /* indicates type of validation user info */ + } + else + { + r_s.switch_value = 0; /* indicates no info */ + } + + r_s.status = status; + r_s.auth_resp = 1; /* authoritative response */ + + /* store the response in the SMB stream */ + net_io_r_sam_logon("", &r_s, rdata, 0); + +} + + +/************************************************************************* + net_reply_sam_logoff: + *************************************************************************/ +static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata, + DOM_CRED *srv_cred, + uint32 status) +{ + NET_R_SAM_LOGOFF r_s; + + /* XXXX maybe we want to say 'no', reject the client's credentials */ + r_s.buffer_creds = 1; /* yes, we have valid server credentials */ + memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds)); + + r_s.status = status; + + /* store the response in the SMB stream */ + net_io_r_sam_logoff("", &r_s, rdata, 0); + +} + +/****************************************************************** + gets a machine password entry. checks access rights of the host. + ******************************************************************/ +static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct) +{ + struct smb_passwd *smb_pass; + + if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(), + client_name(), client_addr())) + { + DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct)); + return False; + } + + become_root(True); + smb_pass = get_smbpwd_entry(mach_acct, 0); + unbecome_root(True); + + if (smb_pass != NULL) + { + memcpy(md4pw, smb_pass->smb_nt_passwd, 16); + dump_data(5, md4pw, 16); + + return True; + } + DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct)); + return False; +} + +/************************************************************************* + api_net_req_chal: + *************************************************************************/ +static void api_net_req_chal( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_REQ_CHAL q_r; + uint32 status = 0x0; + + fstring mach_acct; + fstring mach_name; + + user_struct *vuser; + + DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, uid)); + + if ((vuser = get_valid_user_struct(uid)) == NULL) return; + + /* grab the challenge... */ + net_io_q_req_chal("", &q_r, data, 0); + + fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer, + q_r.uni_logon_clnt.uni_str_len)); + + fstrcpy(mach_name, mach_acct); + strlower(mach_name); + + strcat(mach_acct, "$"); + + if (get_md4pw(vuser->dc.md4pw, mach_name, mach_acct)) + { + /* copy the client credentials */ + memcpy(vuser->dc.clnt_chal.data , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data)); + + /* create a server challenge for the client */ + /* PAXX: set these to random values. */ + /* lkcl: paul, you mentioned that it doesn't really matter much */ + SIVAL(vuser->dc.srv_chal.data, 0, 0x11111111); + SIVAL(vuser->dc.srv_chal.data, 4, 0x11111111); + memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8); + + bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key)); + + /* from client / server challenges and md4 password, generate sess key */ + cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal), + vuser->dc.md4pw, vuser->dc.sess_key); + } + else + { + /* lkclXXXX take a guess at a good error message to return :-) */ + status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; + } + + /* construct reply. */ + net_reply_req_chal(&q_r, rdata, + &(vuser->dc.srv_chal), status); + +} + +/************************************************************************* + api_net_auth_2: + *************************************************************************/ +static void api_net_auth_2( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_AUTH_2 q_a; + uint32 status = 0x0; + + DOM_CHAL srv_cred; + UTIME srv_time; + + user_struct *vuser; + + if ((vuser = get_valid_user_struct(uid)) == NULL) return; + + srv_time.time = 0; + + /* grab the challenge... */ + net_io_q_auth_2("", &q_a, data, 0); + + /* check that the client credentials are valid */ + if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key, + &(vuser->dc.clnt_cred.challenge), srv_time)) + { + + /* create server challenge for inclusion in the reply */ + cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred); + + /* copy the received client credentials for use next time */ + memcpy(vuser->dc.clnt_cred.challenge.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data)); + memcpy(vuser->dc.srv_cred.challenge.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data)); + } + else + { + status = NT_STATUS_ACCESS_DENIED | 0xC0000000; + } + + /* construct reply. */ + net_reply_auth_2(&q_a, rdata, &srv_cred, status); +} + + +/************************************************************************* + api_net_srv_pwset: + *************************************************************************/ +static void api_net_srv_pwset( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_SRV_PWSET q_a; + uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000; + DOM_CRED srv_cred; +#ifdef ALLOW_SRV_PWSET + pstring mach_acct; + struct smb_passwd *smb_pass; + BOOL ret; +#endif + user_struct *vuser; + + if ((vuser = get_valid_user_struct(uid)) == NULL) return; + + /* grab the challenge and encrypted password ... */ + net_io_q_srv_pwset("", &q_a, data, 0); + + /* checks and updates credentials. creates reply credentials */ + if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), + &(q_a.clnt_id.cred), &srv_cred)) + { + memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred)); + + DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__)); + +#ifdef ALLOW_SRV_PWSET + + pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer, + q_a.clnt_id.login.uni_acct_name.uni_str_len)); + + DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct)); + + become_root(True); + smb_pass = get_smbpwd_entry(mach_acct, 0); + unbecome_root(True); + + if (smb_pass != NULL) + { + unsigned char pwd[16]; + uint8 mode = 2; + + memcpy(pwd, q_a.pwd, 16); + + if (obfuscate_pwd(pwd, vuser->dc.sess_key, mode)) + { + /* lies! nt and lm passwords are _not_ the same: don't care */ + smb_pass->smb_passwd = pwd; + smb_pass->smb_nt_passwd = pwd; + smb_pass->acct_ctrl = ACB_WSTRUST; + + become_root(True); + ret = mod_smbpwd_entry(smb_pass); + unbecome_root(True); + + if (ret) + { + /* hooray! */ + status = 0x0; + } + } + } + + DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__)); +#else + DEBUG(5,("api_net_srv_pwset: server password set being denied\n")); +#endif + + } + else + { + /* lkclXXXX take a guess at a sensible error code to return... */ + status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT; + } + + /* construct reply. always indicate failure. nt keeps going... */ + net_reply_srv_pwset(&q_a, rdata, + &srv_cred, status); +} + + +/************************************************************************* + api_net_sam_logoff: + *************************************************************************/ +static void api_net_sam_logoff( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_SAM_LOGOFF q_l; + NET_ID_INFO_CTR ctr; + + DOM_CRED srv_cred; + + user_struct *vuser; + + if ((vuser = get_valid_user_struct(uid)) == NULL) return; + + /* the DOM_ID_INFO_1 structure is a bit big. plus we might want to + dynamically allocate it inside net_io_q_sam_logon, at some point */ + q_l.sam_id.ctr = &ctr; + + /* grab the challenge... */ + net_io_q_sam_logoff("", &q_l, data, 0); + + /* checks and updates credentials. creates reply credentials */ + deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), + &(q_l.sam_id.client.cred), &srv_cred); + memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred)); + + /* construct reply. always indicate success */ + net_reply_sam_logoff(&q_l, rdata, + &srv_cred, + 0x0); +} + +/************************************************************************* + net_login_interactive: + *************************************************************************/ +static uint32 net_login_interactive(NET_ID_INFO_1 *id1, + struct smb_passwd *smb_pass, + user_struct *vuser) +{ + uint32 status = 0x0; + +#ifdef USE_ARCFOUR + extern void arcfour(uint8 key[16], uint8 out[16], uint8 in[16]); + char nt_pwd[16]; + char lm_pwd[16]; + unsigned char arc4_key[16]; + memset(arc4_key, 0, 16); + memcpy(arc4_key, vuser->dc.sess_key, 8); + + arcfour(arc4_key, lm_pwd, id1->arc4_lm_owf.data); + arcfour(arc4_key, nt_pwd, id1->arc4_nt_owf.data); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("arcfour decrypt of lm owf password:")); + dump_data(100, lm_pwd, 16); + + DEBUG(100,("arcfour decrypt of nt owf password:")); + dump_data(100, nt_pwd, 16); +#endif + + if (memcmp(smb_pass->smb_passwd , lm_pwd, 16) != 0 && + memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0) + { + status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD; + } +#else +/* sorry. have to assume that the password is always ok. + this _is_ ok, because the LSA SAM Logon is nothing to do + with SMB connections to shares. + */ +DEBUG(3,("SAM Logon. Password not being checked\n")); +#endif + + return status; +} + +/************************************************************************* + net_login_network: + *************************************************************************/ +static uint32 net_login_network(NET_ID_INFO_2 *id2, + struct smb_passwd *smb_pass, + user_struct *vuser) +{ + if ((id2->lm_chal_resp.str_str_len == 24 || + id2->lm_chal_resp.str_str_len == 0) && + id2->nt_chal_resp.str_str_len == 24 && + (((smb_pass->smb_nt_passwd != NULL) && + smb_password_check(id2->nt_chal_resp.buffer, smb_pass->smb_nt_passwd, + id2->lm_chal)) || + smb_password_check(id2->lm_chal_resp.buffer, smb_pass->smb_passwd, + id2->lm_chal))) + { + return 0x0; + } + return 0xC0000000 | NT_STATUS_WRONG_PASSWORD; +} + +/************************************************************************* + api_net_sam_logon: + *************************************************************************/ +static void api_net_sam_logon( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_SAM_LOGON q_l; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 usr_info; + uint32 status = 0x0; + DOM_CRED srv_cred; + struct smb_passwd *smb_pass = NULL; + UNISTR2 *uni_samlogon_user = NULL; + + user_struct *vuser = NULL; + + if ((vuser = get_valid_user_struct(uid)) == NULL) return; + + q_l.sam_id.ctr = &ctr; + + net_io_q_sam_logon("", &q_l, data, 0); + + /* checks and updates credentials. creates reply credentials */ + if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), + &(q_l.sam_id.client.cred), &srv_cred)) + { + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + else + { + memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred)); + } + + /* find the username */ + + if (status == 0x0) + { + switch (q_l.sam_id.logon_level) + { + case 1: + { + uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name); + pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer, + uni_samlogon_user->uni_str_len)); + + DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. User:[%s]\n", + lp_workgroup(), samlogon_user)); + break; + } + case 2: + { + uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name); + pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer, + uni_samlogon_user->uni_str_len)); + + DEBUG(3,("SAM Logon (Network). Domain:[%s]. User:[%s]\n", + lp_workgroup(), samlogon_user)); + break; + } + default: + { + DEBUG(2,("SAM Logon: unsupported switch value\n")); + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } + } + } + + /* check username exists */ + + if (status == 0x0) + { + pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer, + uni_samlogon_user->uni_str_len)); + + become_root(True); + smb_pass = get_smbpwd_entry(samlogon_user, 0); + unbecome_root(True); + + if (smb_pass == NULL) + { + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + } + } + + /* validate password. */ + + if (status == 0x0) + { + switch (q_l.sam_id.logon_level) + { + case 1: + { + /* interactive login. passwords arcfour'd with session key */ + status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, + smb_pass, vuser); + break; + } + case 2: + { + /* network login. lm challenge and 24 byte responses */ + status = net_login_network(&q_l.sam_id.ctr->auth.id2, + smb_pass, vuser); + break; + } + } + } + + /* lkclXXXX this is the point at which, if the login was + successful, that the SAM Local Security Authority should + record that the user is logged in to the domain. + */ + + /* return the profile plus other bits :-) */ + + if (status == 0x0) + { + DOM_GID gids[LSA_MAX_GROUPS]; + int num_gids = 0; + NTTIME dummy_time; + pstring logon_script; + pstring profile_path; + pstring home_dir; + pstring home_drive; + pstring my_name; + pstring my_workgroup; + pstring domain_groups; + pstring dom_sid; + pstring other_sids; + extern pstring myname; + uint32 r_uid; + uint32 r_gid; + + /* set up pointer indicating user/password failed to be found */ + usr_info.ptr_user_info = 0; + + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; + + get_myname(myname, NULL); + + /* XXXX hack to get standard_sub_basic() to use sam logon username */ + /* possibly a better way would be to do a become_user() call */ + sam_logon_in_ssb = True; + + pstrcpy(logon_script, lp_logon_script ()); + pstrcpy(profile_path, lp_logon_path ()); + pstrcpy(dom_sid , lp_domain_sid ()); + pstrcpy(other_sids , lp_domain_other_sids()); + pstrcpy(my_workgroup, lp_workgroup ()); + + pstrcpy(home_drive , lp_logon_drive ()); + pstrcpy(home_dir , lp_logon_home ()); + + pstrcpy(my_name , myname ); + strupper(my_name); + + get_domain_user_groups(domain_groups, samlogon_user); + + num_gids = make_dom_gids(domain_groups, gids); + + sam_logon_in_ssb = False; + + if (name_to_rid(samlogon_user, &r_uid, &r_gid)) + { + make_net_user_info3(&usr_info, + + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ + + samlogon_user , /* user_name */ + vuser->real_name, /* full_name */ + logon_script , /* logon_script */ + profile_path , /* profile_path */ + home_dir , /* home_dir */ + home_drive , /* dir_drive */ + + 0, /* logon_count */ + 0, /* bad_pw_count */ + + r_uid , /* RID user_id */ + r_gid , /* RID group_id */ + num_gids, /* uint32 num_groups */ + gids , /* DOM_GID *gids */ + 0x20 , /* uint32 user_flgs (?) */ + + NULL, /* char sess_key[16] */ + + my_name , /* char *logon_srv */ + my_workgroup, /* char *logon_dom */ + + dom_sid, /* char *dom_sid */ + other_sids); /* char *other_sids */ + } + else + { + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + } + } + + net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status); +} + + +/************************************************************************* + api_net_trust_dom_list: + *************************************************************************/ +static void api_net_trust_dom_list( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_TRUST_DOM_LIST q_t; + + char *trusted_domain = "test_domain"; + + DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__)); + + /* grab the lsa trusted domain list query... */ + net_io_q_trust_dom("", &q_t, data, 0); + + /* construct reply. */ + net_reply_trust_dom_list(&q_t, rdata, + 1, trusted_domain); + + DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__)); +} + + +/************************************************************************* + error messages cropping up when using nltest.exe... + *************************************************************************/ +#define ERROR_NO_SUCH_DOMAIN 0x54b +#define ERROR_NO_LOGON_SERVERS 0x51f + +/************************************************************************* + api_net_logon_ctrl2: + *************************************************************************/ +static void api_net_logon_ctrl2( int uid, + prs_struct *data, + prs_struct *rdata) +{ + NET_Q_LOGON_CTRL2 q_l; + + /* lkclXXXX - guess what - absolutely no idea what these are! */ + uint32 flags = 0x0; + uint32 pdc_connection_status = 0x0; + uint32 logon_attempts = 0x0; + uint32 tc_status = ERROR_NO_LOGON_SERVERS; + char *trusted_domain = "test_domain"; + + DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__)); + + /* grab the lsa netlogon ctrl2 query... */ + net_io_q_logon_ctrl2("", &q_l, data, 0); + + /* construct reply. */ + net_reply_logon_ctrl2(&q_l, rdata, + flags, pdc_connection_status, logon_attempts, + tc_status, trusted_domain); + + DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__)); +} + +/******************************************************************* + array of \PIPE\NETLOGON operations + ********************************************************************/ +static struct api_struct api_net_cmds [] = +{ + { "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal }, + { "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 }, + { "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset }, + { "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon }, + { "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff }, + { "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 }, + { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list }, + { NULL , 0 , NULL } +}; + +/******************************************************************* + receives a netlogon pipe and responds. + ********************************************************************/ +BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data); +} diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c new file mode 100644 index 0000000000..e4893fee89 --- /dev/null +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -0,0 +1,315 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * + * 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" + + +#define PIPE "\\PIPE\\" +#define PIPELEN strlen(PIPE) + +extern int DEBUGLEVEL; +static int chain_pnum = -1; + +#ifndef MAX_OPEN_PIPES +#define MAX_OPEN_PIPES 50 +#endif + +#define PIPE_HANDLE_OFFSET 0x800 + +pipes_struct Pipes[MAX_OPEN_PIPES]; + +#define P_OPEN(p) ((p)->open) +#define P_OK(p,c) (P_OPEN(p) && (c)==((p)->cnum)) +#define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES)) +#define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && P_OPEN(&(Pipes[pnum]))) +#define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum) + + +/**************************************************************************** + reset pipe chain handle number +****************************************************************************/ +void reset_chain_pnum(void) +{ + chain_pnum = -1; +} + +/**************************************************************************** + sets chain pipe-file handle +****************************************************************************/ +void set_chain_pnum(int new_pnum) +{ + chain_pnum = new_pnum; +} + +/**************************************************************************** + initialise pipe handle states... +****************************************************************************/ +void init_rpc_pipe_hnd(void) +{ + int i; + /* we start at 1 here for an obscure reason I can't now remember, + but I think is important :-) */ + for (i = 1; i < MAX_OPEN_PIPES; i++) + { + Pipes[i].open = False; + Pipes[i].name[0] = 0; + Pipes[i].pipe_srv_name[0] = 0; + + Pipes[i].rhdr.data = NULL; + Pipes[i].rdata.data = NULL; + Pipes[i].rhdr.offset = 0; + Pipes[i].rdata.offset = 0; + + Pipes[i].max_rdata_len = 0; + Pipes[i].hdr_offsets = 0; + } + + return; +} + +/**************************************************************************** + find first available file slot +****************************************************************************/ +int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid) +{ + int i; + /* we start at 1 here for an obscure reason I can't now remember, + but I think is important :-) */ + for (i = 1; i < MAX_OPEN_PIPES; i++) + { + if (!Pipes[i].open) + { + Pipes[i].open = True; + Pipes[i].device_state = 0; + Pipes[i].cnum = cnum; + Pipes[i].uid = vuid; + + Pipes[i].rhdr.data = NULL; + Pipes[i].rdata.data = NULL; + Pipes[i].rhdr.offset = 0; + Pipes[i].rdata.offset = 0; + + Pipes[i].max_rdata_len = 0; + Pipes[i].hdr_offsets = 0; + + fstrcpy(Pipes[i].name, pipe_name); + + DEBUG(4,("Opened pipe %s with handle %x\n", + pipe_name, i + PIPE_HANDLE_OFFSET)); + + set_chain_pnum(i); + + return(i); + } + } + + DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n")); + + return(-1); +} + +/**************************************************************************** + reads data from a pipe. + + headers are interspersed with the data at regular intervals. by the time + this function is called, the start of the data could possibly have been + read by an SMBtrans (max_rdata_len != 0). + + calling create_rpc_request() here is a fudge. the data should already + have been prepared into arrays of headers + data stream sections. + + ****************************************************************************/ +int read_pipe(uint16 pnum, char *data, uint32 pos, int n) +{ + int data_pos = pos; + pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET]; + DEBUG(6,("read_pipe: %x", pnum)); + + if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + DEBUG(6,("name: %s cnum: %d open: %s data_pos: %lx len: %lx", + p->name, + p->cnum, + BOOLSTR(p->open), + data_pos, n)); + } + + if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + int num; + int len; + uint32 rpc_frag_pos; + + DEBUG(6,("OK\n")); + + if (p->rhdr.data == NULL || p->rhdr.data->data == NULL || + p->rhdr.data->data_used == 0) + { + return 0; + } + + /* the read request starts from where the SMBtrans2 left off. */ + data_pos += p->max_rdata_len; + + /* headers accumulate an offset */ + data_pos -= p->hdr_offsets; + + len = mem_buf_len(p->rhdr.data); + num = len - (int)data_pos; + + if (num > n) num = n; + + if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST)) + { + rpc_frag_pos = data_pos % p->hdr.frag_len; + + if (rpc_frag_pos == 0) + { + /* create and copy in a new header. */ + create_rpc_reply(p, data_pos, p->rdata.offset); + mem_buf_copy(data, p->rhdr.data, 0, 0x18); + + /* make room in data stream for header */ + p->hdr_offsets += 0x18; + } + } + + if (num > 0) + { + mem_buf_copy(data, p->rhdr.data, data_pos, num); + return num; + } + + return 0; + + } + else + { + DEBUG(6,("NOT\n")); + return -1; + } +} + +/**************************************************************************** + gets the name of a pipe +****************************************************************************/ +BOOL get_rpc_pipe(int pnum, pipes_struct **p) +{ + DEBUG(6,("get_rpc_pipe: ")); + + /* mapping is PIPE_HANDLE_OFFSET up... */ + + if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + DEBUG(6,("name: %s cnum: %d open: %s ", + Pipes[pnum - PIPE_HANDLE_OFFSET].name, + Pipes[pnum - PIPE_HANDLE_OFFSET].cnum, + BOOLSTR(Pipes[pnum - PIPE_HANDLE_OFFSET].open))); + } + if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET)) + { + DEBUG(6,("OK\n")); + (*p) = &(Pipes[pnum - PIPE_HANDLE_OFFSET]); + return True; + } + else + { + DEBUG(6,("NOT\n")); + return False; + } +} + +/**************************************************************************** + gets the name of a pipe +****************************************************************************/ +char *get_rpc_pipe_hnd_name(int pnum) +{ + pipes_struct *p = NULL; + get_rpc_pipe(pnum, &p); + return p != NULL ? p->name : NULL; +} + +/**************************************************************************** + set device state on a pipe. exactly what this is for is unknown... +****************************************************************************/ +BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state) +{ + if (p == NULL) return False; + + if (P_OPEN(p)) + { + DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s cnum=%d)\n", + timestring(), device_state, p->name, p->cnum)); + + p->device_state = device_state; + + return True; + } + else + { + DEBUG(3,("%s Error setting pipe device state=%x (name=%s cnum=%d)\n", + timestring(), device_state, p->name, p->cnum)); + return False; + } +} + +/**************************************************************************** + close an rpc pipe +****************************************************************************/ +BOOL close_rpc_pipe_hnd(int pnum, int cnum) +{ + pipes_struct *p = NULL; + get_rpc_pipe(pnum, &p); + /* mapping is PIPE_HANDLE_OFFSET up... */ + + if (p != NULL && P_OK(p, cnum)) + { + DEBUG(3,("%s Closed pipe name %s pnum=%x cnum=%d\n", + timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, pnum,cnum)); + + p->open = False; + + p->rdata.offset = 0; + p->rhdr.offset = 0; + mem_buf_free(&(p->rdata.data)); + mem_buf_free(&(p->rhdr .data)); + + return True; + } + else + { + DEBUG(3,("%s Error closing pipe pnum=%x cnum=%d\n", + timestring(),pnum, cnum)); + return False; + } +} + +/**************************************************************************** + close an rpc pipe +****************************************************************************/ +int get_rpc_pipe_num(char *buf, int where) +{ + return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where)); +} + diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c new file mode 100644 index 0000000000..fa856f6983 --- /dev/null +++ b/source3/rpc_server/srv_reg.c @@ -0,0 +1,240 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + + +/******************************************************************* + reg_reply_unknown_1 + ********************************************************************/ +static void reg_reply_close(REG_Q_CLOSE *q_r, + prs_struct *rdata) +{ + REG_R_CLOSE r_u; + + /* set up the REG unknown_1 response */ + bzero(&(r_u.pol.data), POL_HND_SIZE); + + /* close the policy handle */ + if (close_lsa_policy_hnd(&(q_r->pol))) + { + r_u.status = 0; + } + else + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID; + } + + DEBUG(5,("reg_unknown_1: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + reg_io_r_close("", &r_u, rdata, 0); + + DEBUG(5,("reg_unknown_1: %d\n", __LINE__)); +} + +/******************************************************************* + api_reg_close + ********************************************************************/ +static void api_reg_close( int uid, prs_struct *data, + prs_struct *rdata ) +{ + REG_Q_CLOSE q_r; + + /* grab the reg unknown 1 */ + reg_io_q_close("", &q_r, data, 0); + + /* construct reply. always indicate success */ + reg_reply_close(&q_r, rdata); +} + + +/******************************************************************* + reg_reply_open + ********************************************************************/ +static void reg_reply_open(REG_Q_OPEN_POLICY *q_r, + prs_struct *rdata) +{ + REG_R_OPEN_POLICY r_u; + + r_u.status = 0x0; + /* get a (unique) handle. open a policy on it. */ + if (r_u.status == 0x0 && !open_lsa_policy_hnd(&(r_u.pol))) + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + DEBUG(5,("reg_open: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + reg_io_r_open_policy("", &r_u, rdata, 0); + + DEBUG(5,("reg_open: %d\n", __LINE__)); +} + +/******************************************************************* + api_reg_open + ********************************************************************/ +static void api_reg_open( int uid, prs_struct *data, + prs_struct *rdata ) +{ + REG_Q_OPEN_POLICY q_u; + + /* grab the reg open */ + reg_io_q_open_policy("", &q_u, data, 0); + + /* construct reply. always indicate success */ + reg_reply_open(&q_u, rdata); +} + + +/******************************************************************* + reg_reply_open_entry + ********************************************************************/ +static void reg_reply_open_entry(REG_Q_OPEN_ENTRY *q_u, + prs_struct *rdata) +{ + uint32 status = 0; + POLICY_HND pol; + REG_R_OPEN_ENTRY r_u; + fstring name; + + DEBUG(5,("reg_open_entry: %d\n", __LINE__)); + + if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1) + { + status = 0xC000000 | NT_STATUS_INVALID_HANDLE; + } + + if (status == 0x0 && !open_lsa_policy_hnd(&pol)) + { + status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */ + } + + fstrcpy(name, unistrn2(q_u->uni_name.buffer, q_u->uni_name.uni_str_len)); + + if (status == 0x0) + { + DEBUG(5,("reg_open_entry: %s\n", name)); + /* lkcl XXXX do a check on the name, here */ + } + + if (status == 0x0 && !set_lsa_policy_reg_name(&pol, name)) + { + status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */ + } + + make_reg_r_open_entry(&r_u, &pol, status); + + /* store the response in the SMB stream */ + reg_io_r_open_entry("", &r_u, rdata, 0); + + DEBUG(5,("reg_open_entry: %d\n", __LINE__)); +} + +/******************************************************************* + api_reg_open_entry + ********************************************************************/ +static void api_reg_open_entry( int uid, prs_struct *data, + prs_struct *rdata ) +{ + REG_Q_OPEN_ENTRY q_u; + + /* grab the reg open entry */ + reg_io_q_open_entry("", &q_u, data, 0); + + /* construct reply. */ + reg_reply_open_entry(&q_u, rdata); +} + + +/******************************************************************* + reg_reply_info + ********************************************************************/ +static void reg_reply_info(REG_Q_INFO *q_u, + prs_struct *rdata) +{ + uint32 status = 0; + + REG_R_INFO r_u; + + DEBUG(5,("reg_info: %d\n", __LINE__)); + + if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1) + { + status = 0xC000000 | NT_STATUS_INVALID_HANDLE; + } + + if (status == 0) + { + } + + make_reg_r_info(&r_u, 1, "LanmanNT", 0x12, 0x12, status); + + /* store the response in the SMB stream */ + reg_io_r_info("", &r_u, rdata, 0); + + DEBUG(5,("reg_open_entry: %d\n", __LINE__)); +} + +/******************************************************************* + api_reg_info + ********************************************************************/ +static void api_reg_info( int uid, prs_struct *data, + prs_struct *rdata ) +{ + REG_Q_INFO q_u; + + /* grab the reg unknown 0x11*/ + reg_io_q_info("", &q_u, data, 0); + + /* construct reply. always indicate success */ + reg_reply_info(&q_u, rdata); +} + + +/******************************************************************* + array of \PIPE\reg operations + ********************************************************************/ +static struct api_struct api_reg_cmds[] = +{ + { "REG_CLOSE" , REG_CLOSE , api_reg_close }, + { "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry }, + { "REG_OPEN" , REG_OPEN_POLICY , api_reg_open }, + { "REG_INFO" , REG_INFO , api_reg_info }, + { NULL, 0 , NULL } +}; + +/******************************************************************* + receives a reg pipe and responds. + ********************************************************************/ +BOOL api_reg_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_reg_rpc", api_reg_cmds, data); +} + diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c new file mode 100644 index 0000000000..02c8cb0ffe --- /dev/null +++ b/source3/rpc_server/srv_samr.c @@ -0,0 +1,1352 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + +extern BOOL sam_logon_in_ssb; +extern pstring samlogon_user; +extern rid_name domain_group_rids[]; +extern rid_name domain_alias_rids[]; + +/******************************************************************* + This next function should be replaced with something that + dynamically returns the correct user info..... JRA. + ********************************************************************/ + +static BOOL get_smbpwd_entries(SAM_USER_INFO_21 *pw_buf, + int *total_entries, int *num_entries, + int max_num_entries, + uint16 acb_mask) +{ + FILE *fp = NULL; + struct smb_passwd *pwd = NULL; + + (*num_entries) = 0; + (*total_entries) = 0; + + if (pw_buf == NULL) return False; + + fp = startsmbpwent(False); + if (!fp) + { + DEBUG(0, ("get_smbpwd_entries: Unable to open SMB password file.\n")); + return False; + } + + while (((pwd = getsmbpwent(fp)) != NULL) && (*num_entries) < max_num_entries) + { + int user_name_len = strlen(pwd->smb_name); + make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len); + make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len, + user_name_len, 1); + pw_buf[(*num_entries)].user_rid = pwd->smb_userid; + bzero( pw_buf[(*num_entries)].nt_pwd , 16); + + /* Now check if the NT compatible password is available. */ + if (pwd->smb_nt_passwd != NULL) + { + memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16); + } + + pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl; + + DEBUG(5, ("get_smbpwd_entries: idx: %d user %s, uid %d, acb %x", + (*num_entries), pwd->smb_name, pwd->smb_userid, pwd->acct_ctrl)); + + if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask)) + { + DEBUG(5,(" acb_mask %x accepts\n", acb_mask)); + (*num_entries)++; + } + else + { + DEBUG(5,(" acb_mask %x rejects\n", acb_mask)); + } + + (*total_entries)++; + } + + endsmbpwent(fp); + + return (*num_entries) > 0; +} + +/******************************************************************* + samr_reply_unknown_1 + ********************************************************************/ +static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u, + prs_struct *rdata) +{ + SAMR_R_CLOSE_HND r_u; + + /* set up the SAMR unknown_1 response */ + bzero(&(r_u.pol.data), POL_HND_SIZE); + + /* close the policy handle */ + if (close_lsa_policy_hnd(&(q_u->pol))) + { + r_u.status = 0; + } + else + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID; + } + + DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_close_hnd("", &r_u, rdata, 0); + + DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_close_hnd + ********************************************************************/ +static void api_samr_close_hnd( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_CLOSE_HND q_u; + + /* grab the samr unknown 1 */ + samr_io_q_close_hnd("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_close_hnd(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_open_domain + ********************************************************************/ +static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u, + prs_struct *rdata) +{ + SAMR_R_OPEN_DOMAIN r_u; + BOOL pol_open = False; + int pol_idx; + + r_u.status = 0x0; + + /* find the connection policy handle. */ + if (r_u.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->connect_pol))) == -1)) + { + r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + /* get a (unique) handle. open a policy on it. */ + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol)))) + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* associate the domain SID with the (unique) handle. */ + if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid))) + { + /* oh, whoops. don't know what error message to return, here */ + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (r_u.status != 0 && pol_open) + { + close_lsa_policy_hnd(&(r_u.domain_pol)); + } + + DEBUG(5,("samr_open_domain: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_open_domain("", &r_u, rdata, 0); + + DEBUG(5,("samr_open_domain: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_open_domain + ********************************************************************/ +static void api_samr_open_domain( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_OPEN_DOMAIN q_u; + + /* grab the samr open */ + samr_io_q_open_domain("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_open_domain(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_unknown_3 + ********************************************************************/ +static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u, + prs_struct *rdata) +{ + SAMR_R_UNKNOWN_3 r_u; + DOM_SID3 sid[MAX_SAM_SIDS]; + fstring user_sid; + fstring user_rid; + int pol_idx; + uint32 rid; + uint32 status; + + status = 0x0; + + /* find the policy handle. open a policy on it. */ + if (status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->user_pol))) == -1)) + { + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + /* find the user's rid */ + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff) + { + status = NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (status == 0x0) + { + strcpy(user_sid, lp_domain_sid()); + sprintf(user_rid, "-%x", rid); + strcat(user_sid, user_rid); + + /* maybe need another 1 or 2 (S-1-5-20-0x220 and S-1-5-20-0x224) */ + /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */ + make_dom_sid3(&(sid[0]), 0x035b, 0x0002, "S-1-1"); + make_dom_sid3(&(sid[1]), 0x0044, 0x0002, user_sid); + } + + make_samr_r_unknown_3(&r_u, + 0x0001, 0x8004, + 0x00000014, 0x0002, 0x0070, + 2, sid, status); + + DEBUG(5,("samr_unknown_3: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_unknown_3("", &r_u, rdata, 0); + + DEBUG(5,("samr_unknown_3: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_unknown_3 + ********************************************************************/ +static void api_samr_unknown_3( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_UNKNOWN_3 q_u; + + /* grab the samr open */ + samr_io_q_unknown_3("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_unknown_3(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_enum_dom_users + ********************************************************************/ +static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u, + prs_struct *rdata) +{ + SAMR_R_ENUM_DOM_USERS r_e; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries; + int total_entries; + int pol_idx; + BOOL got_pwds; + + r_e.status = 0x0; + r_e.total_num_entries = 0; + + /* find the policy handle. open a policy on it. */ + if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__)); + + become_root(True); + got_pwds = get_smbpwd_entries(pass, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask); + unbecome_root(True); + + make_samr_r_enum_dom_users(&r_e, total_entries, + q_u->unknown_0, num_entries, + pass, r_e.status); + + /* store the response in the SMB stream */ + samr_io_r_enum_dom_users("", &r_e, rdata, 0); + + DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_enum_dom_users + ********************************************************************/ +static void api_samr_enum_dom_users( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_ENUM_DOM_USERS q_e; + + /* grab the samr open */ + samr_io_q_enum_dom_users("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_enum_dom_users(&q_e, rdata); +} + + +/******************************************************************* + samr_reply_enum_dom_groups + ********************************************************************/ +static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u, + prs_struct *rdata) +{ + SAMR_R_ENUM_DOM_GROUPS r_e; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries; + int pol_idx; + BOOL got_grps; + char *dummy_group = "Domain Admins"; + + r_e.status = 0x0; + r_e.num_entries = 0; + + /* find the policy handle. open a policy on it. */ + if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__)); + + got_grps = True; + num_entries = 1; + make_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group)); + pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS; + + if (r_e.status == 0 && got_grps) + { + make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status); + } + + /* store the response in the SMB stream */ + samr_io_r_enum_dom_groups("", &r_e, rdata, 0); + + DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_enum_dom_groups + ********************************************************************/ +static void api_samr_enum_dom_groups( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_ENUM_DOM_GROUPS q_e; + + /* grab the samr open */ + samr_io_q_enum_dom_groups("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_enum_dom_groups(&q_e, rdata); +} + + +/******************************************************************* + samr_reply_enum_dom_aliases + ********************************************************************/ +static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u, + prs_struct *rdata) +{ + SAMR_R_ENUM_DOM_ALIASES r_e; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries; + int pol_idx; + BOOL got_aliases; + char *dummy_alias = "admins"; + + r_e.status = 0x0; + r_e.num_entries = 0; + + /* find the policy handle. open a policy on it. */ + if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + DEBUG(5,("samr_reply_enum_dom_aliases: %d\n", __LINE__)); + + got_aliases = True; + num_entries = 1; + make_unistr2(&(pass[0].uni_user_name), dummy_alias, strlen(dummy_alias)); + pass[0].user_rid = DOMAIN_ALIAS_RID_ADMINS; + + if (r_e.status == 0 && got_aliases) + { + make_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status); + } + + /* store the response in the SMB stream */ + samr_io_r_enum_dom_aliases("", &r_e, rdata, 0); + + DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_enum_dom_aliases + ********************************************************************/ +static void api_samr_enum_dom_aliases( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_ENUM_DOM_ALIASES q_e; + + /* grab the samr open */ + samr_io_q_enum_dom_aliases("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_enum_dom_aliases(&q_e, rdata); +} + + +/******************************************************************* + samr_reply_query_dispinfo + ********************************************************************/ +static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, + prs_struct *rdata) +{ + SAMR_R_QUERY_DISPINFO r_e; + SAM_INFO_CTR ctr; + SAM_INFO_1 info1; + SAM_INFO_2 info2; + SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES]; + int num_entries; + int total_entries; + int pol_idx; + BOOL got_pwds; + uint16 switch_level = 0x0; + + r_e.status = 0x0; + + /* find the policy handle. open a policy on it. */ + if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__)); + + become_root(True); + + got_pwds = get_smbpwd_entries(pass, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0); + + unbecome_root(True); + + switch (q_u->switch_level) + { + case 0x1: + { + /* query disp info is for users */ + make_sam_info_1(&info1, ACB_NORMAL, + q_u->start_idx, num_entries, pass); + + ctr.sam.info1 = &info1; + switch_level = 0x1; + + break; + } + case 0x2: + { + /* query disp info is for servers */ + make_sam_info_2(&info2, ACB_WSTRUST, + q_u->start_idx, num_entries, pass); + + ctr.sam.info2 = &info2; + switch_level = 0x2; + + break; + } + } + + if (r_e.status == 0 && got_pwds) + { + make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status); + } + + /* store the response in the SMB stream */ + samr_io_r_query_dispinfo("", &r_e, rdata, 0); + + DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_query_dispinfo + ********************************************************************/ +static void api_samr_query_dispinfo( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_QUERY_DISPINFO q_e; + + /* grab the samr open */ + samr_io_q_query_dispinfo("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_query_dispinfo(&q_e, rdata); +} + + +/******************************************************************* + samr_reply_query_aliasinfo + ********************************************************************/ +static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u, + prs_struct *rdata) +{ + SAMR_R_QUERY_ALIASINFO r_e; + int pol_idx; + BOOL got_alias; + + r_e.status = 0x0; + r_e.ptr = 0; + + /* find the policy handle. open a policy on it. */ + if (r_e.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__)); + + if (r_e.status == 0x0) + { + if (q_u->switch_level != 3) + { + r_e.status = NT_STATUS_INVALID_INFO_CLASS; + } + } + + if (r_e.status == 0x0) + { + got_alias = True; + } + + make_samr_r_query_aliasinfo(&r_e, q_u->switch_level, + "<account description>", + r_e.status); + + /* store the response in the SMB stream */ + samr_io_r_query_aliasinfo("", &r_e, rdata, 0); + + DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_query_aliasinfo + ********************************************************************/ +static void api_samr_query_aliasinfo( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_QUERY_ALIASINFO q_e; + + /* grab the samr open */ + samr_io_q_query_aliasinfo("", &q_e, data, 0); + + /* construct reply. */ + samr_reply_query_aliasinfo(&q_e, rdata); +} + + +/******************************************************************* + samr_reply_lookup_ids + ********************************************************************/ +static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u, + prs_struct *rdata) +{ + uint32 rid[MAX_SAM_ENTRIES]; + uint32 status = 0; + int num_rids = q_u->num_sids1; + + SAMR_R_LOOKUP_IDS r_u; + + DEBUG(5,("samr_lookup_ids: %d\n", __LINE__)); + + if (num_rids > MAX_SAM_ENTRIES) + { + num_rids = MAX_SAM_ENTRIES; + DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids)); + } + +#if 0 + int i; + for (i = 0; i < num_rids && status == 0; i++) + { + struct smb_passwd *smb_pass; + fstring user_name; + + fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer, + q_u->uni_user_name[i].uni_str_len)); + + /* find the user account */ + become_root(True); + smb_pass = get_smbpwd_entry(user_name, 0); + unbecome_root(True); + + if (smb_pass == NULL) + { + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + rid[i] = 0; + } + else + { + /* lkclXXXX SHOULD use name_to_rid() here! */ + rid[i] = smb_pass->smb_userid; + } + } +#endif + + num_rids = 1; + rid[0] = DOMAIN_ALIAS_RID_USERS; + + make_samr_r_lookup_ids(&r_u, num_rids, rid, status); + + /* store the response in the SMB stream */ + samr_io_r_lookup_ids("", &r_u, rdata, 0); + + DEBUG(5,("samr_lookup_ids: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_lookup_ids + ********************************************************************/ +static void api_samr_lookup_ids( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_LOOKUP_IDS q_u; + + /* grab the samr 0x10 */ + samr_io_q_lookup_ids("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_lookup_ids(&q_u, rdata); +} + +/******************************************************************* + samr_reply_lookup_names + ********************************************************************/ +static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u, + prs_struct *rdata) +{ + uint32 rid[MAX_SAM_ENTRIES]; + uint32 status = 0; + int i; + int num_rids = q_u->num_rids1; + + SAMR_R_LOOKUP_NAMES r_u; + + DEBUG(5,("samr_lookup_names: %d\n", __LINE__)); + + if (num_rids > MAX_SAM_ENTRIES) + { + num_rids = MAX_SAM_ENTRIES; + DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids)); + } + + for (i = 0; i < num_rids && status == 0; i++) + { + fstring name; + + status = 0xC0000000 | NT_STATUS_NONE_MAPPED; + + fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len)); + + status = (status != 0x0) ? lookup_user_rid (name, &(rid[i])) : status; + status = (status != 0x0) ? lookup_group_rid(name, &(rid[i])) : status; + status = (status != 0x0) ? lookup_alias_rid(name, &(rid[i])) : status; + } + + make_samr_r_lookup_names(&r_u, num_rids, rid, status); + + /* store the response in the SMB stream */ + samr_io_r_lookup_names("", &r_u, rdata, 0); + + DEBUG(5,("samr_lookup_names: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_lookup_names + ********************************************************************/ +static void api_samr_lookup_names( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_LOOKUP_NAMES q_u; + + /* grab the samr lookup names */ + samr_io_q_lookup_names("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_lookup_names(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_unknown_12 + ********************************************************************/ +static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u, + prs_struct *rdata) +{ + fstring group_names[MAX_SAM_ENTRIES]; + uint32 group_attrs[MAX_SAM_ENTRIES]; + uint32 status = 0; + int num_gids = q_u->num_gids1; + uint32 pol_idx; + + SAMR_R_UNKNOWN_12 r_u; + + DEBUG(5,("samr_unknown_12: %d\n", __LINE__)); + + /* find the policy handle. open a policy on it. */ + if (status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + if (status == 0x0) + { + int i; + if (num_gids > MAX_SAM_ENTRIES) + { + num_gids = MAX_SAM_ENTRIES; + DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids)); + } + + for (i = 0; i < num_gids && status == 0; i++) + { + fstrcpy(group_names[i], "dummy group"); + group_attrs[i] = 0x2; + } + } + + make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status); + + /* store the response in the SMB stream */ + samr_io_r_unknown_12("", &r_u, rdata, 0); + + DEBUG(5,("samr_unknown_12: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_unknown_12 + ********************************************************************/ +static void api_samr_unknown_12( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_UNKNOWN_12 q_u; + + /* grab the samr lookup names */ + samr_io_q_unknown_12("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_unknown_12(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_open_user + ********************************************************************/ +static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u, + prs_struct *rdata, + int status) +{ + SAMR_R_OPEN_USER r_u; + struct smb_passwd *smb_pass; + int pol_idx; + BOOL pol_open = False; + + /* set up the SAMR open_user response */ + bzero(&(r_u.user_pol.data), POL_HND_SIZE); + + r_u.status = 0x0; + + /* find the policy handle. open a policy on it. */ + if (r_u.status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->domain_pol))) == -1)) + { + r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + /* get a (unique) handle. open a policy on it. */ + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol)))) + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + become_root(True); + smb_pass = get_smbpwd_entry(NULL, q_u->user_rid); + unbecome_root(True); + + /* check that the RID exists in our domain. */ + if (r_u.status == 0x0 && smb_pass == NULL) + { + r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + } + + /* associate the RID with the (unique) handle. */ + if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid)) + { + /* oh, whoops. don't know what error message to return, here */ + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (r_u.status != 0 && pol_open) + { + close_lsa_policy_hnd(&(r_u.user_pol)); + } + + DEBUG(5,("samr_open_user: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_open_user("", &r_u, rdata, 0); + + DEBUG(5,("samr_open_user: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_open_user + ********************************************************************/ +static void api_samr_open_user( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_OPEN_USER q_u; + + /* grab the samr unknown 22 */ + samr_io_q_open_user("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_open_user(&q_u, rdata, 0x0); +} + + +/************************************************************************* + get_user_info_21 + *************************************************************************/ +static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid) +{ + NTTIME dummy_time; + + pstring logon_script; + pstring profile_path; + pstring home_drive; + pstring home_dir; + pstring description; + pstring workstations; + pstring full_name; + pstring munged_dialin; + pstring unknown_str; + + uint32 r_uid; + uint32 r_gid; + + LOGON_HRS hrs; + int i; + + struct smb_passwd *smb_pass; + + become_root(True); + smb_pass = get_smbpwd_entry(NULL, rid); + unbecome_root(True); + + if (smb_pass == NULL) + { + return False; + } + + DEBUG(3,("User:[%s]\n", smb_pass->smb_name)); + + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; + + pstrcpy(samlogon_user, smb_pass->smb_name); + + if (samlogon_user[strlen(samlogon_user)-1] != '$') + { + if (!name_to_rid(samlogon_user, &r_uid, &r_gid)) + { + return False; + } + + /* XXXX hack to get standard_sub_basic() to use sam logon username */ + /* possibly a better way would be to do a become_user() call */ + sam_logon_in_ssb = True; + + pstrcpy(full_name , "<Full Name>"); + pstrcpy(logon_script , lp_logon_script ()); + pstrcpy(profile_path , lp_logon_path ()); + pstrcpy(home_drive , lp_logon_drive ()); + pstrcpy(home_dir , lp_logon_home ()); + pstrcpy(description , "<Description>"); + pstrcpy(workstations , ""); + pstrcpy(unknown_str , ""); + pstrcpy(munged_dialin, ""); + + sam_logon_in_ssb = False; + } + else + { + r_uid = smb_pass->smb_userid; + r_gid = DOMAIN_GROUP_RID_USERS; + + pstrcpy(samlogon_user, smb_pass->smb_name); + + pstrcpy(full_name , ""); + pstrcpy(logon_script , ""); + pstrcpy(profile_path , ""); + pstrcpy(home_drive , ""); + pstrcpy(home_dir , ""); + pstrcpy(description , ""); + pstrcpy(workstations , ""); + pstrcpy(unknown_str , ""); + pstrcpy(munged_dialin, ""); + } + + hrs.len = 21; + for (i = 0; i < hrs.len; i++) + { + hrs.hours[i] = 0xff; + } + make_sam_user_info21(id21, + + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ + + samlogon_user, /* user_name */ + full_name, /* full_name */ + home_dir, /* home_dir */ + home_drive, /* dir_drive */ + logon_script, /* logon_script */ + profile_path, /* profile_path */ + description, /* description */ + workstations, /* workstations user can log in from */ + unknown_str, /* don't know, yet */ + munged_dialin, /* dialin info. contains dialin path and tel no */ + + r_uid, /* RID user_id */ + r_gid, /* RID group_id */ + smb_pass->acct_ctrl, + + 0x00ffffff, /* unknown_3 */ + 168, /* divisions per week */ + &hrs, /* logon hours */ + 0x00020000, + 0x000004ec); + + return True; +} + +/******************************************************************* + samr_reply_query_userinfo + ********************************************************************/ +static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u, + prs_struct *rdata) +{ + SAMR_R_QUERY_USERINFO r_u; +#if 0 + SAM_USER_INFO_11 id11; +#endif + SAM_USER_INFO_21 id21; + void *info = NULL; + + uint32 status = 0x0; + uint32 rid; + int obj_idx; + + DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__)); + + /* search for the handle */ + if (status == 0x0 && (obj_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1) + { + status = NT_STATUS_INVALID_HANDLE; + } + + /* find the user's rid */ + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff) + { + status = NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + /* ok! user info levels (there are lots: see MSDEV help), off we go... */ + if (status == 0x0) + { + switch (q_u->switch_value) + { +#if 0 +/* whoops - got this wrong. i think. or don't understand what's happening. */ + case 0x11: + { + NTTIME expire; + info = (void*)&id11; + + expire.low = 0xffffffff; + expire.high = 0x7fffffff; + + make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080); + + break; + } +#endif + case 21: + { + info = (void*)&id21; + status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER; + + break; + } + + default: + { + status = NT_STATUS_INVALID_INFO_CLASS; + + break; + } + } + } + + make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status); + + /* store the response in the SMB stream */ + samr_io_r_query_userinfo("", &r_u, rdata, 0); + + DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_query_userinfo + ********************************************************************/ +static void api_samr_query_userinfo( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_QUERY_USERINFO q_u; + + /* grab the samr unknown 24 */ + samr_io_q_query_userinfo("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_query_userinfo(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_query_usergroups + ********************************************************************/ +static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u, + prs_struct *rdata) +{ + SAMR_R_QUERY_USERGROUPS r_u; + uint32 status = 0x0; + + struct smb_passwd *smb_pass; + DOM_GID gids[LSA_MAX_GROUPS]; + int num_groups = 0; + int pol_idx; + uint32 rid; + + DEBUG(5,("samr_query_usergroups: %d\n", __LINE__)); + + /* find the policy handle. open a policy on it. */ + if (status == 0x0 && ((pol_idx = find_lsa_policy_by_hnd(&(q_u->pol))) == -1)) + { + status = 0xC0000000 | NT_STATUS_INVALID_HANDLE; + } + + /* find the user's rid */ + if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff) + { + status = NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (status == 0x0) + { + become_root(True); + smb_pass = get_smbpwd_entry(NULL, rid); + unbecome_root(True); + + if (smb_pass == NULL) + { + status = 0xC0000000 | NT_STATUS_NO_SUCH_USER; + } + } + + if (status == 0x0) + { + pstring groups; + get_domain_user_groups(groups, smb_pass->smb_name); + num_groups = make_dom_gids(groups, gids); + } + + /* construct the response. lkclXXXX: gids are not copied! */ + make_samr_r_query_usergroups(&r_u, num_groups, gids, status); + + /* store the response in the SMB stream */ + samr_io_r_query_usergroups("", &r_u, rdata, 0); + + DEBUG(5,("samr_query_usergroups: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_query_usergroups + ********************************************************************/ +static void api_samr_query_usergroups( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_QUERY_USERGROUPS q_u; + /* grab the samr unknown 32 */ + samr_io_q_query_usergroups("", &q_u, data, 0); + + /* construct reply. */ + samr_reply_query_usergroups(&q_u, rdata); +} + + +/******************************************************************* + samr_reply_unknown_32 + ********************************************************************/ +static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u, + prs_struct *rdata, + int status) +{ + int i; + SAMR_R_UNKNOWN_32 r_u; + + /* set up the SAMR unknown_32 response */ + bzero(&(r_u.pol.data), POL_HND_SIZE); + if (status == 0) + { + for (i = 4; i < POL_HND_SIZE; i++) + { + r_u.pol.data[i] = i+1; + } + } + + make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0); + r_u.status = status; + + DEBUG(5,("samr_unknown_32: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_unknown_32("", &r_u, rdata, 0); + + DEBUG(5,("samr_unknown_32: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_unknown_32 + ********************************************************************/ +static void api_samr_unknown_32( int uid, prs_struct *data, prs_struct *rdata) +{ + uint32 status = 0; + struct smb_passwd *smb_pass; + fstring mach_acct; + + SAMR_Q_UNKNOWN_32 q_u; + + /* grab the samr unknown 32 */ + samr_io_q_unknown_32("", &q_u, data, 0); + + /* find the machine account: tell the caller if it exists. + lkclXXXX i have *no* idea if this is a problem or not + or even if you are supposed to construct a different + reply if the account already exists... + */ + + fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer, + q_u.uni_mach_acct.uni_str_len)); + + become_root(True); + smb_pass = get_smbpwd_entry(mach_acct, 0); + unbecome_root(True); + + if (smb_pass != NULL) + { + /* machine account exists: say so */ + status = 0xC0000000 | NT_STATUS_USER_EXISTS; + } + else + { + /* this could cause trouble... */ + status = 0; + } + + /* construct reply. */ + samr_reply_unknown_32(&q_u, rdata, status); +} + + +/******************************************************************* + samr_reply_connect + ********************************************************************/ +static void samr_reply_connect(SAMR_Q_CONNECT *q_u, + prs_struct *rdata) +{ + SAMR_R_CONNECT r_u; + BOOL pol_open = False; + + /* set up the SAMR connect response */ + + r_u.status = 0x0; + /* get a (unique) handle. open a policy on it. */ + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol)))) + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* associate the domain SID with the (unique) handle. */ + if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0)) + { + /* oh, whoops. don't know what error message to return, here */ + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (r_u.status != 0 && pol_open) + { + close_lsa_policy_hnd(&(r_u.connect_pol)); + } + + DEBUG(5,("samr_connect: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_connect("", &r_u, rdata, 0); + + DEBUG(5,("samr_connect: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_connect + ********************************************************************/ +static void api_samr_connect( int uid, prs_struct *data, prs_struct *rdata) +{ + SAMR_Q_CONNECT q_u; + + /* grab the samr open policy */ + samr_io_q_connect("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_connect(&q_u, rdata); +} + +/******************************************************************* + samr_reply_open_alias + ********************************************************************/ +static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, + prs_struct *rdata) +{ + SAMR_R_OPEN_ALIAS r_u; + BOOL pol_open = False; + + /* set up the SAMR open_alias response */ + + r_u.status = 0x0; + /* get a (unique) handle. open a policy on it. */ + if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol)))) + { + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* associate a RID with the (unique) handle. */ + if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias)) + { + /* oh, whoops. don't know what error message to return, here */ + r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + if (r_u.status != 0 && pol_open) + { + close_lsa_policy_hnd(&(r_u.pol)); + } + + DEBUG(5,("samr_open_alias: %d\n", __LINE__)); + + /* store the response in the SMB stream */ + samr_io_r_open_alias("", &r_u, rdata, 0); + + DEBUG(5,("samr_open_alias: %d\n", __LINE__)); + +} + +/******************************************************************* + api_samr_open_alias + ********************************************************************/ +static void api_samr_open_alias( int uid, prs_struct *data, prs_struct *rdata) + +{ + SAMR_Q_OPEN_ALIAS q_u; + + /* grab the samr open policy */ + samr_io_q_open_alias("", &q_u, data, 0); + + /* construct reply. always indicate success */ + samr_reply_open_alias(&q_u, rdata); +} + +/******************************************************************* + array of \PIPE\samr operations + ********************************************************************/ +static struct api_struct api_samr_cmds [] = +{ + { "SAMR_CLOSE_HND" , SAMR_CLOSE_HND , api_samr_close_hnd }, + { "SAMR_CONNECT" , SAMR_CONNECT , api_samr_connect }, + { "SAMR_ENUM_DOM_USERS" , SAMR_ENUM_DOM_USERS , api_samr_enum_dom_users }, + { "SAMR_ENUM_DOM_GROUPS" , SAMR_ENUM_DOM_GROUPS , api_samr_enum_dom_groups }, + { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases }, + { "SAMR_LOOKUP_IDS" , SAMR_LOOKUP_IDS , api_samr_lookup_ids }, + { "SAMR_LOOKUP_NAMES" , SAMR_LOOKUP_NAMES , api_samr_lookup_names }, + { "SAMR_OPEN_USER" , SAMR_OPEN_USER , api_samr_open_user }, + { "SAMR_QUERY_USERINFO" , SAMR_QUERY_USERINFO , api_samr_query_userinfo }, + { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups }, + { "SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo }, + { "SAMR_QUERY_ALIASINFO" , SAMR_QUERY_ALIASINFO , api_samr_query_aliasinfo }, + { "SAMR_0x32" , 0x32 , api_samr_unknown_32 }, + { "SAMR_UNKNOWN_12" , SAMR_UNKNOWN_12 , api_samr_unknown_12 }, + { "SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias }, + { "SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain }, + { "SAMR_UNKNOWN_3" , SAMR_UNKNOWN_3 , api_samr_unknown_3 }, + { NULL , 0 , NULL } +}; + +/******************************************************************* + receives a samr pipe and responds. + ********************************************************************/ +BOOL api_samr_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data); +} + diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c new file mode 100644 index 0000000000..285ea89657 --- /dev/null +++ b/source3/rpc_server/srv_srvsvc.c @@ -0,0 +1,1015 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + + +/******************************************************************* + fill in a share info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + see ipc.c:fill_share_info() + + ********************************************************************/ +static void make_srv_share_1_info(SH_INFO_1 *sh1, + SH_INFO_1_STR *str1, int snum) +{ + int len_net_name; + pstring net_name; + pstring remark; + uint32 type; + + pstrcpy(net_name, lp_servicename(snum)); + strupper(net_name); + pstrcpy(remark , lp_comment (snum)); + len_net_name = strlen(net_name); + + /* work out the share type */ + type = STYPE_DISKTREE; + + if (lp_print_ok(snum)) type = STYPE_PRINTQ; + if (strequal("IPC$", net_name)) type = STYPE_IPC; + if (net_name[len_net_name] == '$') type |= STYPE_HIDDEN; + + make_srv_share_info1 (sh1 , net_name, type, remark); + make_srv_share_info1_str(str1, net_name, remark); +} + +/******************************************************************* + fill in a share info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_share_info_1(SRV_SHARE_INFO_1 *sh1, uint32 *snum, uint32 *svcs) +{ + uint32 num_entries = 0; + (*svcs) = lp_numservices(); + + if (sh1 == NULL) + { + (*snum) = 0; + return; + } + + DEBUG(5,("make_srv_share_1_sh1\n")); + + for (; (*snum) < (*svcs) && num_entries < MAX_SHARE_ENTRIES; (*snum)++) + { + if (lp_browseable((*snum)) && lp_snum_ok((*snum))) + { + make_srv_share_1_info(&(sh1->info_1 [num_entries]), + &(sh1->info_1_str[num_entries]), (*snum)); + + /* move on to creating next share */ + num_entries++; + } + } + + sh1->num_entries_read = num_entries; + sh1->ptr_share_info = num_entries > 0 ? 1 : 0; + sh1->num_entries_read2 = num_entries; + + if ((*snum) >= (*svcs)) + { + (*snum) = 0; + } +} + +/******************************************************************* + fill in a share info level 2 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + see ipc.c:fill_share_info() + + ********************************************************************/ +static void make_srv_share_2_info(SH_INFO_2 *sh2, + SH_INFO_2_STR *str2, int snum) +{ + int len_net_name; + pstring net_name; + pstring remark; + pstring path; + pstring passwd; + uint32 type; + + pstrcpy(net_name, lp_servicename(snum)); + pstrcpy(remark , lp_comment (snum)); + pstrcpy(path , lp_pathname (snum)); + pstrcpy(passwd , ""); + len_net_name = strlen(net_name); + + /* work out the share type */ + type = STYPE_DISKTREE; + + if (lp_print_ok(snum)) type = STYPE_PRINTQ; + if (strequal("IPC$", net_name)) type = STYPE_IPC; + if (net_name[len_net_name] == '$') type |= STYPE_HIDDEN; + + make_srv_share_info2 (sh2 , net_name, type, remark, 0, 0xffffffff, 1, path, passwd); + make_srv_share_info2_str(str2, net_name, remark, path, passwd); +} + +/******************************************************************* + fill in a share info level 2 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_share_info_2(SRV_SHARE_INFO_2 *sh2, uint32 *snum, uint32 *svcs) +{ + uint32 num_entries = 0; + (*svcs) = lp_numservices(); + + if (sh2 == NULL) + { + (*snum) = 0; + return; + } + + DEBUG(5,("make_srv_share_2_sh1\n")); + + for (; (*snum) < (*svcs) && num_entries < MAX_SHARE_ENTRIES; (*snum)++) + { + if (lp_browseable((*snum)) && lp_snum_ok((*snum))) + { + make_srv_share_2_info(&(sh2->info_2 [num_entries]), + &(sh2->info_2_str[num_entries]), (*snum)); + + /* move on to creating next share */ + num_entries++; + } + } + + sh2->num_entries_read = num_entries; + sh2->ptr_share_info = num_entries > 0 ? 1 : 0; + sh2->num_entries_read2 = num_entries; + + if ((*snum) >= (*svcs)) + { + (*snum) = 0; + } +} + +/******************************************************************* + makes a SRV_R_NET_SHARE_ENUM structure. +********************************************************************/ +static uint32 make_srv_share_info_ctr(SRV_SHARE_INFO_CTR *ctr, + int switch_value, uint32 *resume_hnd, uint32 *total_entries) +{ + uint32 status = 0x0; + DEBUG(5,("make_srv_share_info_ctr: %d\n", __LINE__)); + + ctr->switch_value = switch_value; + + switch (switch_value) + { + case 1: + { + make_srv_share_info_1(&(ctr->share.info1), resume_hnd, total_entries); + ctr->ptr_share_ctr = 1; + break; + } + case 2: + { + make_srv_share_info_2(&(ctr->share.info2), resume_hnd, total_entries); + ctr->ptr_share_ctr = 2; + break; + } + default: + { + DEBUG(5,("make_srv_share_info_ctr: unsupported switch value %d\n", + switch_value)); + (*resume_hnd = 0); + (*total_entries) = 0; + ctr->ptr_share_ctr = 0; + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } + } + + return status; +} + +/******************************************************************* + makes a SRV_R_NET_SHARE_ENUM structure. +********************************************************************/ +static void make_srv_r_net_share_enum(SRV_R_NET_SHARE_ENUM *r_n, + uint32 resume_hnd, int share_level, int switch_value) +{ + DEBUG(5,("make_srv_r_net_share_enum: %d\n", __LINE__)); + + r_n->share_level = share_level; + if (share_level == 0) + { + r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + } + else + { + r_n->status = make_srv_share_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); + } + if (r_n->status != 0x0) + { + resume_hnd = 0; + } + make_enum_hnd(&(r_n->enum_hnd), resume_hnd); +} + +/******************************************************************* +net share enum +********************************************************************/ +static void srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, + prs_struct *rdata) +{ + SRV_R_NET_SHARE_ENUM r_n; + SRV_SHARE_INFO_CTR ctr; + + r_n.ctr = &ctr; + + DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); + + /* set up the */ + make_srv_r_net_share_enum(&r_n, + get_enum_hnd(&q_n->enum_hnd), + q_n->share_level, + q_n->ctr->switch_value); + + /* store the response in the SMB stream */ + srv_io_r_net_share_enum("", &r_n, rdata, 0); + + DEBUG(5,("srv_net_share_enum: %d\n", __LINE__)); +} + +/******************************************************************* + fill in a sess info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, + char *name) +{ + make_srv_sess_info0 (se0 , name); + make_srv_sess_info0_str(str0, name); +} + +/******************************************************************* + fill in a sess info level 0 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot) +{ + uint32 num_entries = 0; + (*stot) = 1; + + if (ss0 == NULL) + { + (*snum) = 0; + return; + } + + DEBUG(5,("make_srv_sess_0_ss0\n")); + + if (snum) + { + for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) + { + make_srv_sess_0_info(&(ss0->info_0 [num_entries]), + &(ss0->info_0_str[num_entries]), "MACHINE"); + + /* move on to creating next session */ + /* move on to creating next sess */ + num_entries++; + } + + ss0->num_entries_read = num_entries; + ss0->ptr_sess_info = num_entries > 0 ? 1 : 0; + ss0->num_entries_read2 = num_entries; + + if ((*snum) >= (*stot)) + { + (*snum) = 0; + } + } + else + { + ss0->num_entries_read = 0; + ss0->ptr_sess_info = 0; + ss0->num_entries_read2 = 0; + } +} + +/******************************************************************* + fill in a sess info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, + char *name, char *user, + uint32 num_opens, + uint32 open_time, uint32 idle_time, + uint32 usr_flgs) +{ + make_srv_sess_info1 (se1 , name, user, num_opens, open_time, idle_time, usr_flgs); + make_srv_sess_info1_str(str1, name, user); +} + +/******************************************************************* + fill in a sess info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot) +{ + uint32 num_entries = 0; + (*stot) = 1; + + if (ss1 == NULL) + { + (*snum) = 0; + return; + } + + DEBUG(5,("make_srv_sess_1_ss1\n")); + + if (snum) + { + for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) + { + make_srv_sess_1_info(&(ss1->info_1 [num_entries]), + &(ss1->info_1_str[num_entries]), + "MACHINE", "dummy_user", 1, 10, 5, 0); + + /* move on to creating next session */ + /* move on to creating next sess */ + num_entries++; + } + + ss1->num_entries_read = num_entries; + ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; + ss1->num_entries_read2 = num_entries; + + if ((*snum) >= (*stot)) + { + (*snum) = 0; + } + } + else + { + ss1->num_entries_read = 0; + ss1->ptr_sess_info = 0; + ss1->num_entries_read2 = 0; + + (*stot) = 0; + } +} + +/******************************************************************* + makes a SRV_R_NET_SESS_ENUM structure. +********************************************************************/ +static uint32 make_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr, + int switch_value, uint32 *resume_hnd, uint32 *total_entries) +{ + uint32 status = 0x0; + DEBUG(5,("make_srv_sess_info_ctr: %d\n", __LINE__)); + + ctr->switch_value = switch_value; + + switch (switch_value) + { + case 0: + { + make_srv_sess_info_0(&(ctr->sess.info0), resume_hnd, total_entries); + ctr->ptr_sess_ctr = 1; + break; + } + case 1: + { + make_srv_sess_info_1(&(ctr->sess.info1), resume_hnd, total_entries); + ctr->ptr_sess_ctr = 1; + break; + } + default: + { + DEBUG(5,("make_srv_sess_info_ctr: unsupported switch value %d\n", + switch_value)); + (*resume_hnd) = 0; + (*total_entries) = 0; + ctr->ptr_sess_ctr = 0; + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } + } + + return status; +} + +/******************************************************************* + makes a SRV_R_NET_SESS_ENUM structure. +********************************************************************/ +static void make_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n, + uint32 resume_hnd, int sess_level, int switch_value) +{ + DEBUG(5,("make_srv_r_net_sess_enum: %d\n", __LINE__)); + + r_n->sess_level = sess_level; + if (sess_level == -1) + { + r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + } + else + { + r_n->status = make_srv_sess_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries); + } + if (r_n->status != 0x0) + { + resume_hnd = 0; + } + make_enum_hnd(&(r_n->enum_hnd), resume_hnd); +} + +/******************************************************************* +net sess enum +********************************************************************/ +static void srv_reply_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, + prs_struct *rdata) +{ + SRV_R_NET_SESS_ENUM r_n; + SRV_SESS_INFO_CTR ctr; + + r_n.ctr = &ctr; + + DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__)); + + /* set up the */ + make_srv_r_net_sess_enum(&r_n, + get_enum_hnd(&q_n->enum_hnd), + q_n->sess_level, + q_n->ctr->switch_value); + + /* store the response in the SMB stream */ + srv_io_r_net_sess_enum("", &r_n, rdata, 0); + + DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__)); +} + +/******************************************************************* + fill in a conn info level 0 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *stot) +{ + uint32 num_entries = 0; + (*stot) = 1; + + if (ss0 == NULL) + { + (*snum) = 0; + return; + } + + DEBUG(5,("make_srv_conn_0_ss0\n")); + + if (snum) + { + for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++) + { + make_srv_conn_info0(&(ss0->info_0 [num_entries]), (*stot)); + + /* move on to creating next connection */ + /* move on to creating next conn */ + num_entries++; + } + + ss0->num_entries_read = num_entries; + ss0->ptr_conn_info = num_entries > 0 ? 1 : 0; + ss0->num_entries_read2 = num_entries; + + + + if ((*snum) >= (*stot)) + { + (*snum) = 0; + } + } + else + { + ss0->num_entries_read = 0; + ss0->ptr_conn_info = 0; + ss0->num_entries_read2 = 0; + + (*stot) = 0; + } +} + +/******************************************************************* + fill in a conn info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_conn_1_info(CONN_INFO_1 *se1, CONN_INFO_1_STR *str1, + uint32 id, uint32 type, + uint32 num_opens, uint32 num_users, uint32 open_time, + char *usr_name, char *net_name) +{ + make_srv_conn_info1 (se1 , id, type, num_opens, num_users, open_time, usr_name, net_name); + make_srv_conn_info1_str(str1, usr_name, net_name); +} + +/******************************************************************* + fill in a conn info level 1 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *stot) +{ + uint32 num_entries = 0; + (*stot) = 1; + + if (ss1 == NULL) + { + (*snum) = 0; + return; + } + + DEBUG(5,("make_srv_conn_1_ss1\n")); + + if (snum) + { + for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++) + { + make_srv_conn_1_info(&(ss1->info_1 [num_entries]), + &(ss1->info_1_str[num_entries]), + (*stot), 0x3, 1, 1, 3,"dummy_user", "IPC$"); + + /* move on to creating next connection */ + /* move on to creating next conn */ + num_entries++; + } + + ss1->num_entries_read = num_entries; + ss1->ptr_conn_info = num_entries > 0 ? 1 : 0; + ss1->num_entries_read2 = num_entries; + + + if ((*snum) >= (*stot)) + { + (*snum) = 0; + } + } + else + { + ss1->num_entries_read = 0; + ss1->ptr_conn_info = 0; + ss1->num_entries_read2 = 0; + + (*stot) = 0; + } +} + +/******************************************************************* + makes a SRV_R_NET_CONN_ENUM structure. +********************************************************************/ +static uint32 make_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr, + int switch_value, uint32 *resume_hnd, uint32 *total_entries) +{ + uint32 status = 0x0; + DEBUG(5,("make_srv_conn_info_ctr: %d\n", __LINE__)); + + ctr->switch_value = switch_value; + + switch (switch_value) + { + case 0: + { + make_srv_conn_info_0(&(ctr->conn.info0), resume_hnd, total_entries); + ctr->ptr_conn_ctr = 1; + break; + } + case 1: + { + make_srv_conn_info_1(&(ctr->conn.info1), resume_hnd, total_entries); + ctr->ptr_conn_ctr = 1; + break; + } + default: + { + DEBUG(5,("make_srv_conn_info_ctr: unsupported switch value %d\n", + switch_value)); + (*resume_hnd = 0); + (*total_entries) = 0; + ctr->ptr_conn_ctr = 0; + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } + } + + return status; +} + +/******************************************************************* + makes a SRV_R_NET_CONN_ENUM structure. +********************************************************************/ +static void make_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, + uint32 resume_hnd, int conn_level, int switch_value) +{ + DEBUG(5,("make_srv_r_net_conn_enum: %d\n", __LINE__)); + + r_n->conn_level = conn_level; + if (conn_level == -1) + { + r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + } + else + { + r_n->status = make_srv_conn_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries); + } + if (r_n->status != 0x0) + { + resume_hnd = 0; + } + make_enum_hnd(&(r_n->enum_hnd), resume_hnd); +} + +/******************************************************************* +net conn enum +********************************************************************/ +static void srv_reply_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n, + prs_struct *rdata) +{ + SRV_R_NET_CONN_ENUM r_n; + SRV_CONN_INFO_CTR ctr; + + r_n.ctr = &ctr; + + DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__)); + + /* set up the */ + make_srv_r_net_conn_enum(&r_n, + get_enum_hnd(&q_n->enum_hnd), + q_n->conn_level, + q_n->ctr->switch_value); + + /* store the response in the SMB stream */ + srv_io_r_net_conn_enum("", &r_n, rdata, 0); + + DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__)); +} + +/******************************************************************* + fill in a file info level 3 structure. + ********************************************************************/ +static void make_srv_file_3_info(FILE_INFO_3 *fl3, FILE_INFO_3_STR *str3, + uint32 fnum, uint32 perms, uint32 num_locks, + char *path_name, char *user_name) +{ + make_srv_file_info3 (fl3 , fnum, perms, num_locks, path_name, user_name); + make_srv_file_info3_str(str3, path_name, user_name); +} + +/******************************************************************* + fill in a file info level 3 structure. + + this function breaks the rule that i'd like to be in place, namely + it doesn't receive its data as arguments: it has to call lp_xxxx() + functions itself. yuck. + + ********************************************************************/ +static void make_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot) +{ + uint32 num_entries = 0; + (*ftot) = 1; + + if (fl3 == NULL) + { + (*fnum) = 0; + return; + } + + DEBUG(5,("make_srv_file_3_fl3\n")); + + for (; (*fnum) < (*ftot) && num_entries < MAX_FILE_ENTRIES; (*fnum)++) + { + make_srv_file_3_info(&(fl3->info_3 [num_entries]), + &(fl3->info_3_str[num_entries]), + (*fnum), 0x35, 0, "\\PIPE\\samr", "dummy user"); + + /* move on to creating next file */ + num_entries++; + } + + fl3->num_entries_read = num_entries; + fl3->ptr_file_info = num_entries > 0 ? 1 : 0; + fl3->num_entries_read2 = num_entries; + + if ((*fnum) >= (*ftot)) + { + (*fnum) = 0; + } +} + +/******************************************************************* + makes a SRV_R_NET_FILE_ENUM structure. +********************************************************************/ +static uint32 make_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr, + int switch_value, uint32 *resume_hnd, uint32 *total_entries) +{ + uint32 status = 0x0; + DEBUG(5,("make_srv_file_info_ctr: %d\n", __LINE__)); + + ctr->switch_value = switch_value; + + switch (switch_value) + { + case 3: + { + make_srv_file_info_3(&(ctr->file.info3), resume_hnd, total_entries); + ctr->ptr_file_ctr = 1; + break; + } + default: + { + DEBUG(5,("make_srv_file_info_ctr: unsupported switch value %d\n", + switch_value)); + (*resume_hnd = 0); + (*total_entries) = 0; + ctr->ptr_file_ctr = 0; + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } + } + + return status; +} + +/******************************************************************* + makes a SRV_R_NET_FILE_ENUM structure. +********************************************************************/ +static void make_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n, + uint32 resume_hnd, int file_level, int switch_value) +{ + DEBUG(5,("make_srv_r_net_file_enum: %d\n", __LINE__)); + + r_n->file_level = file_level; + if (file_level == 0) + { + r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + } + else + { + r_n->status = make_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries)); + } + if (r_n->status != 0x0) + { + resume_hnd = 0; + } + make_enum_hnd(&(r_n->enum_hnd), resume_hnd); +} + +/******************************************************************* +net file enum +********************************************************************/ +static void srv_reply_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n, + prs_struct *rdata) +{ + SRV_R_NET_FILE_ENUM r_n; + SRV_FILE_INFO_CTR ctr; + + r_n.ctr = &ctr; + + DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); + + /* set up the */ + make_srv_r_net_file_enum(&r_n, + get_enum_hnd(&q_n->enum_hnd), + q_n->file_level, + q_n->ctr->switch_value); + + /* store the response in the SMB stream */ + srv_io_r_net_file_enum("", &r_n, rdata, 0); + + DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); +} + +/******************************************************************* +net server get info +********************************************************************/ +static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n, + prs_struct *rdata) +{ + SRV_R_NET_SRV_GET_INFO r_n; + uint32 status = 0x0; + SRV_INFO_CTR ctr; + + extern pstring myname; + get_myname(myname,NULL); + + DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__)); + + switch (q_n->switch_value) + { + case 102: + { + make_srv_info_102(&ctr.srv.sv102, + 500, myname, lp_serverstring(), + 5, 4, /* major/minor version - NT 5.4 :-) */ + 0x4100b, /* browsing stuff SV_TYPE_XXXX */ + 0xffffffff, /* users */ + 0xf, /* disc */ + 0, /* hidden */ + 240, /* announce */ + 3000, /* announce delta */ + 100000, /* licenses */ + "c:\\"); /* user path */ + break; + } + case 101: + { + make_srv_info_101(&ctr.srv.sv101, + 500, myname, + 5, 4, /* major/minor version - NT 5.4 :-) */ + 0x4100b, /* browsing stuff SV_TYPE_XXXX */ + lp_serverstring()); + break; + } + default: + { + status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS; + break; + } + } + + /* set up the net server get info structure */ + make_srv_r_net_srv_get_info(&r_n, q_n->switch_value, &ctr, status); + + /* store the response in the SMB stream */ + srv_io_r_net_srv_get_info("", &r_n, rdata, 0); + + DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__)); +} + +/******************************************************************* +********************************************************************/ +static void api_srv_net_srv_get_info( int uid, prs_struct *data, + prs_struct *rdata ) +{ + SRV_Q_NET_SRV_GET_INFO q_n; + + /* grab the net server get info */ + srv_io_q_net_srv_get_info("", &q_n, data, 0); + + /* construct reply. always indicate success */ + srv_reply_net_srv_get_info(&q_n, rdata); +} + + +/******************************************************************* +********************************************************************/ +static void api_srv_net_file_enum( int uid, prs_struct *data, + prs_struct *rdata ) +{ + SRV_Q_NET_FILE_ENUM q_n; + SRV_FILE_INFO_CTR ctr; + + q_n.ctr = &ctr; + + /* grab the net file enum */ + srv_io_q_net_file_enum("", &q_n, data, 0); + + /* construct reply. always indicate success */ + srv_reply_net_file_enum(&q_n, rdata); +} + + +/******************************************************************* +********************************************************************/ +static void api_srv_net_conn_enum( int uid, prs_struct *data, + prs_struct *rdata ) +{ + SRV_Q_NET_CONN_ENUM q_n; + SRV_CONN_INFO_CTR ctr; + + q_n.ctr = &ctr; + + /* grab the net server get enum */ + srv_io_q_net_conn_enum("", &q_n, data, 0); + + /* construct reply. always indicate success */ + srv_reply_net_conn_enum(&q_n, rdata); +} + + +/******************************************************************* +********************************************************************/ +static void api_srv_net_sess_enum( int uid, prs_struct *data, + prs_struct *rdata ) +{ + SRV_Q_NET_SESS_ENUM q_n; + SRV_SESS_INFO_CTR ctr; + + q_n.ctr = &ctr; + + /* grab the net server get enum */ + srv_io_q_net_sess_enum("", &q_n, data, 0); + + /* construct reply. always indicate success */ + srv_reply_net_sess_enum(&q_n, rdata); +} + + +/******************************************************************* +********************************************************************/ +static void api_srv_net_share_enum( int uid, prs_struct *data, + prs_struct *rdata ) +{ + SRV_Q_NET_SHARE_ENUM q_n; + SRV_SHARE_INFO_CTR ctr; + + q_n.ctr = &ctr; + + /* grab the net server get enum */ + srv_io_q_net_share_enum("", &q_n, data, 0); + + /* construct reply. always indicate success */ + srv_reply_net_share_enum(&q_n, rdata); +} + + +/******************************************************************* +\PIPE\srvsvc commands +********************************************************************/ +struct api_struct api_srv_cmds[] = +{ + { "SRV_NETCONNENUM" , SRV_NETCONNENUM , api_srv_net_conn_enum }, + { "SRV_NETSESSENUM" , SRV_NETSESSENUM , api_srv_net_sess_enum }, + { "SRV_NETSHAREENUM" , SRV_NETSHAREENUM , api_srv_net_share_enum }, + { "SRV_NETFILEENUM" , SRV_NETFILEENUM , api_srv_net_file_enum }, + { "SRV_NET_SRV_GET_INFO", SRV_NET_SRV_GET_INFO, api_srv_net_srv_get_info }, + { NULL , 0 , NULL } +}; + +/******************************************************************* +receives a srvsvc pipe and responds. +********************************************************************/ +BOOL api_srvsvc_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_srvsvc_rpc", api_srv_cmds, data); +} + diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c new file mode 100644 index 0000000000..7be259029a --- /dev/null +++ b/source3/rpc_server/srv_util.c @@ -0,0 +1,477 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * 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. + */ + +/* this module apparently provides an implementation of DCE/RPC over a + * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC + * documentation are available (in on-line form) from the X-Open group. + * + * this module should provide a level of abstraction between SMB + * and DCE/RPC, while minimising the amount of mallocs, unnecessary + * data copies, and network traffic. + * + * in this version, which takes a "let's learn what's going on and + * get something running" approach, there is additional network + * traffic generated, but the code should be easier to understand... + * + * ... if you read the docs. or stare at packets for weeks on end. + * + */ + +#include "includes.h" +#include "nterr.h" + +extern int DEBUGLEVEL; + +/* array lookup of well-known RID aliases. the purpose of these escapes me.. */ +/* XXXX this structure should not have the well-known RID groups added to it, + i.e the DOMAIN_GROUP_RID_ADMIN/USER/GUEST. */ +rid_name domain_alias_rids[] = +{ + { DOMAIN_ALIAS_RID_ADMINS , "admins" }, + { DOMAIN_ALIAS_RID_USERS , "users" }, + { DOMAIN_ALIAS_RID_GUESTS , "guests" }, + { DOMAIN_ALIAS_RID_POWER_USERS , "power_users" }, + + { DOMAIN_ALIAS_RID_ACCOUNT_OPS , "account_ops" }, + { DOMAIN_ALIAS_RID_SYSTEM_OPS , "system_ops" }, + { DOMAIN_ALIAS_RID_PRINT_OPS , "print_ops" }, + { DOMAIN_ALIAS_RID_BACKUP_OPS , "backup_ops" }, + { DOMAIN_ALIAS_RID_REPLICATOR , "replicator" }, + { 0 , NULL } +}; + +/* array lookup of well-known Domain RID groups. */ +rid_name domain_group_rids[] = +{ + { DOMAIN_GROUP_RID_ADMINS , "domain admins" }, + { DOMAIN_GROUP_RID_USERS , "domain users" }, + { DOMAIN_GROUP_RID_GUESTS , "domain guests" }, + { 0 , NULL } +}; + + + +int make_dom_gids(char *gids_str, DOM_GID *gids) +{ + char *ptr; + pstring s2; + int count; + + DEBUG(4,("make_dom_gids: %s\n", gids_str)); + + if (gids_str == NULL || *gids_str == 0) return 0; + + for (count = 0, ptr = gids_str; next_token(&ptr, s2, NULL) && count < LSA_MAX_GROUPS; count++) + { + /* the entries are of the form GID/ATTR, ATTR being optional.*/ + char *attr; + uint32 rid = 0; + int i; + + attr = strchr(s2,'/'); + if (attr) *attr++ = 0; + if (!attr || !*attr) attr = "7"; /* default value for attribute is 7 */ + + /* look up the RID string and see if we can turn it into a rid number */ + for (i = 0; domain_alias_rids[i].name != NULL; i++) + { + if (strequal(domain_alias_rids[i].name, s2)) + { + rid = domain_alias_rids[i].rid; + break; + } + } + + if (rid == 0) rid = atoi(s2); + + if (rid == 0) + { + DEBUG(1,("make_dom_gids: unknown well-known alias RID %s/%s\n", + s2, attr)); + count--; + } + else + { + gids[count].g_rid = rid; + gids[count].attr = atoi(attr); + + DEBUG(5,("group id: %d attr: %d\n", + gids[count].g_rid, + gids[count].attr)); + } + } + + return count; +} + +/******************************************************************* + gets a domain user's groups + ********************************************************************/ +void get_domain_user_groups(char *domain_groups, char *user) +{ + pstring tmp; + + if (domain_groups == NULL || user == NULL) return; + + /* any additional groups this user is in. e.g power users */ + pstrcpy(domain_groups, lp_domain_groups()); + + /* can only be a user or a guest. cannot be guest _and_ admin */ + if (user_in_list(user, lp_domain_guest_users())) + { + sprintf(tmp, " %ld/7 ", DOMAIN_GROUP_RID_GUESTS); + strcat(domain_groups, tmp); + + DEBUG(3,("domain guest access %s granted\n", tmp)); + } + else + { + sprintf(tmp, " %ld/7 ", DOMAIN_GROUP_RID_USERS); + strcat(domain_groups, tmp); + + DEBUG(3,("domain user access %s granted\n", tmp)); + + if (user_in_list(user, lp_domain_admin_users())) + { + sprintf(tmp, " %ld/7 ", DOMAIN_GROUP_RID_ADMINS); + strcat(domain_groups, tmp); + + DEBUG(3,("domain admin access %s granted\n", tmp)); + } + } +} + + +/******************************************************************* + turns a DCE/RPC request into a DCE/RPC reply + + this is where the data really should be split up into an array of + headers and data sections. + + ********************************************************************/ +BOOL create_rpc_reply(pipes_struct *p, + uint32 data_start, uint32 data_end) +{ + mem_buf_init(&(p->rhdr.data), 0); + mem_alloc_data(p->rhdr.data, 0x18); + + p->rhdr.align = 4; + p->rhdr.io = False; + + p->hdr_rr.alloc_hint = data_end - data_start; /* calculate remaining data to be sent */ + p->hdr.pkt_type = RPC_RESPONSE; /* mark header as an rpc response */ + + /* set up rpc header (fragmentation issues) */ + if (data_start == 0) + { + p->hdr.flags = RPC_FLG_FIRST; + } + else + { + p->hdr.flags = 0; + } + + if (p->hdr_rr.alloc_hint + 0x18 <= p->hdr_ba.bba.max_tsize) + { + p->hdr.flags |= RPC_FLG_LAST; + p->hdr.frag_len = p->hdr_rr.alloc_hint + 0x18; + } + else + { + p->hdr.frag_len = p->hdr_ba.bba.max_tsize; + } + + p->rhdr.data->offset.start = 0; + p->rhdr.data->offset.end = 0x18; + + /* store the header in the data stream */ + p->rhdr.offset = 0; + smb_io_rpc_hdr ("hdr", &(p->hdr ), &(p->rhdr), 0); + smb_io_rpc_hdr_rr("rr" , &(p->hdr_rr), &(p->rhdr), 0); + + return p->rhdr.data != NULL && p->rhdr.offset == 0x18; +} + + +/******************************************************************* + receives a netlogon pipe and responds. + ********************************************************************/ +static BOOL api_rpc_command(pipes_struct *p, + char *rpc_name, struct api_struct *api_rpc_cmds, + prs_struct *data) +{ + int fn_num; + DEBUG(4,("api_rpc_command: %s op 0x%x - ", rpc_name, p->hdr_rr.opnum)); + + for (fn_num = 0; api_rpc_cmds[fn_num].name; fn_num++) + { + if (api_rpc_cmds[fn_num].opnum == p->hdr_rr.opnum && api_rpc_cmds[fn_num].fn != NULL) + { + DEBUG(3,("api_rpc_command: %s\n", api_rpc_cmds[fn_num].name)); + break; + } + } + + if (api_rpc_cmds[fn_num].name == NULL) + { + DEBUG(4, ("unknown\n")); + return False; + } + + /* start off with 1024 bytes, and a large safety margin too */ + mem_buf_init(&(p->rdata.data), SAFETY_MARGIN); + mem_alloc_data(p->rdata.data, 1024); + + p->rdata.io = False; + p->rdata.align = 4; + + p->rdata.data->offset.start = 0; + p->rdata.data->offset.end = 0xffffffff; + + /* do the actual command */ + p->rdata.offset = 0; + api_rpc_cmds[fn_num].fn(p->uid, data, &(p->rdata)); + + if (p->rdata.data == NULL || p->rdata.offset == 0) + { + mem_free_data(p->rdata.data); + return False; + } + + mem_realloc_data(p->rdata.data, p->rdata.offset); + + DEBUG(10,("called %s\n", rpc_name)); + + return True; +} + + +/******************************************************************* + receives a netlogon pipe and responds. + ********************************************************************/ +BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds, + prs_struct *data) +{ + if (data == NULL || data->data == NULL) + { + DEBUG(2,("%s: NULL data received\n", rpc_name)); + return False; + } + + /* read the rpc header */ + smb_io_rpc_hdr_rr("", &(p->hdr_rr), data, 0); + + /* interpret the command */ + if (!api_rpc_command(p, rpc_name, api_rpc_cmds, data)) + { + return False; + } + + /* create the rpc header */ + if (!create_rpc_reply(p, 0, p->rdata.offset)) + { + return False; + } + + /* set up the data chain */ + p->rhdr.data->offset.start = 0; + p->rhdr.data->offset.end = p->rhdr.offset; + p->rhdr.data->next = p->rdata.data; + + p->rdata.data->offset.start = p->rhdr.data->offset.end; + p->rdata.data->offset.end = p->rhdr.data->offset.end + p->rdata.offset; + p->rdata.data->next = NULL; + + return True; +} + +extern rid_name domain_group_rids[]; + +/******************************************************************* + lookup_group_name + ********************************************************************/ +uint32 lookup_group_name(uint32 rid, char *group_name, uint32 *type) +{ + int i = 0; + (*type) = SID_NAME_DOM_GRP; + + while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0) + { + i++; + } + + if (domain_group_rids[i].rid != 0) + { + fstrcpy(group_name, domain_group_rids[i].name); + return 0x0; + } + + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +extern rid_name domain_alias_rids[]; + +/******************************************************************* + lookup_alias_name + ********************************************************************/ +uint32 lookup_alias_name(uint32 rid, char *alias_name, uint32 *type) +{ + int i = 0; + (*type) = SID_NAME_WKN_GRP; + + while (domain_alias_rids[i].rid != rid && domain_alias_rids[i].rid != 0) + { + i++; + } + + if (domain_alias_rids[i].rid != 0) + { + fstrcpy(alias_name, domain_alias_rids[i].name); + return 0x0; + } + + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_user_name + ********************************************************************/ +uint32 lookup_user_name(uint32 rid, char *user_name, uint32 *type) +{ + struct smb_passwd *smb_pass; + (*type) = SID_NAME_USER; + + /* find the user account */ + become_root(True); + smb_pass = get_smbpwd_entry(NULL, rid); /* lkclXXXX SHOULD use rid mapping here! */ + unbecome_root(True); + + if (smb_pass != NULL) + { + fstrcpy(user_name, smb_pass->smb_name); + return 0x0; + } + + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_group_rid + ********************************************************************/ +uint32 lookup_group_rid(char *group_name, uint32 *rid) +{ + char *grp_name; + int i = -1; /* start do loop at -1 */ + + do /* find, if it exists, a group rid for the group name*/ + { + i++; + (*rid) = domain_group_rids[i].rid; + grp_name = domain_group_rids[i].name; + + } while (grp_name != NULL && !strequal(grp_name, group_name)); + + return (grp_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_alias_rid + ********************************************************************/ +uint32 lookup_alias_rid(char *alias_name, uint32 *rid) +{ + char *als_name; + int i = -1; /* start do loop at -1 */ + + do /* find, if it exists, a alias rid for the alias name*/ + { + i++; + (*rid) = domain_alias_rids[i].rid; + als_name = domain_alias_rids[i].name; + + } while (als_name != NULL && !strequal(als_name, alias_name)); + + return (als_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + lookup_user_rid + ********************************************************************/ +uint32 lookup_user_rid(char *user_name, uint32 *rid) +{ + struct smb_passwd *smb_pass; + (*rid) = 0; + + /* find the user account */ + become_root(True); + smb_pass = get_smbpwd_entry(user_name, 0); + unbecome_root(True); + + if (smb_pass != NULL) + { + /* lkclXXXX SHOULD use name_to_rid() here! */ + (*rid) = smb_pass->smb_userid; + return 0x0; + } + + return 0xC0000000 | NT_STATUS_NONE_MAPPED; +} + +/******************************************************************* + Group and User RID username mapping function + ********************************************************************/ +BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid) +{ + struct passwd *pw = Get_Pwnam(user_name, False); + + if (u_rid == NULL || g_rid == NULL || user_name == NULL) + { + return False; + } + + if (!pw) + { + DEBUG(1,("Username %s is invalid on this system\n", user_name)); + return False; + } + + if (user_in_list(user_name, lp_domain_guest_users())) + { + *u_rid = DOMAIN_USER_RID_GUEST; + } + else if (user_in_list(user_name, lp_domain_admin_users())) + { + *u_rid = DOMAIN_USER_RID_ADMIN; + } + else + { + /* turn the unix UID into a Domain RID. this is what the posix + sub-system does (adds 1000 to the uid) */ + *u_rid = (uint32)(pw->pw_uid + 1000); + } + + /* absolutely no idea what to do about the unix GID to Domain RID mapping */ + *g_rid = (uint32)(pw->pw_gid + 1000); + + return True; +} diff --git a/source3/rpc_server/srv_wkssvc.c b/source3/rpc_server/srv_wkssvc.c new file mode 100644 index 0000000000..3dd273f784 --- /dev/null +++ b/source3/rpc_server/srv_wkssvc.c @@ -0,0 +1,113 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Paul Ashton 1997. + * + * 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 "nterr.h" + +extern int DEBUGLEVEL; + + +/******************************************************************* + create_wks_info_100 + ********************************************************************/ +static void create_wks_info_100(WKS_INFO_100 *inf) +{ + extern pstring myname; + pstring my_name; + pstring domain; + + DEBUG(5,("create_wks_info_100: %d\n", __LINE__)); + + get_myname(myname, NULL); + pstrcpy (my_name, myname); + strupper(my_name); + + pstrcpy (domain , lp_workgroup()); + strupper(domain); + + make_wks_info_100(inf, + 0x000001f4, /* platform id info */ + lp_major_announce_version(), + lp_minor_announce_version(), + my_name, domain); +} + +/******************************************************************* + wks_reply_query_info + + only supports info level 100 at the moment. + + ********************************************************************/ +static void wks_reply_query_info(WKS_Q_QUERY_INFO *q_u, + prs_struct *rdata, + int status) +{ + WKS_R_QUERY_INFO r_u; + WKS_INFO_100 wks100; + + DEBUG(5,("wks_query_info: %d\n", __LINE__)); + + create_wks_info_100(&wks100); + make_wks_r_query_info(&r_u, q_u->switch_value, &wks100, status); + + /* store the response in the SMB stream */ + wks_io_r_query_info("", &r_u, rdata, 0); + + DEBUG(5,("wks_query_info: %d\n", __LINE__)); +} + +/******************************************************************* + api_wks_query_info + ********************************************************************/ +static void api_wks_query_info( int uid, prs_struct *data, + prs_struct *rdata ) +{ + WKS_Q_QUERY_INFO q_u; + + /* grab the net share enum */ + wks_io_q_query_info("", &q_u, data, 0); + + /* construct reply. always indicate success */ + wks_reply_query_info(&q_u, rdata, 0x0); +} + + +/******************************************************************* + \PIPE\wkssvc commands + ********************************************************************/ +struct api_struct api_wks_cmds[] = +{ + { "WKS_Q_QUERY_INFO", WKS_QUERY_INFO, api_wks_query_info }, + { NULL , 0 , NULL } +}; + +/******************************************************************* + receives a wkssvc pipe and responds. + ********************************************************************/ +BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_wkssvc_rpc", api_wks_cmds, data); +} + diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 1ccf2fb2b0..bbbbc9029e 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -64,7 +64,7 @@ BEGIN { next; } -!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|arc4_key/ { +!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|^arc4_key|^FILE/ { next; } diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index fb795e973e..c83ff1911c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -422,6 +422,12 @@ BOOL check_lanman_password(char *user, unsigned char *pass1, return False; } + if(smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0,("check_lanman_password: account %s disabled.\n", user)); + return False; + } + if(smbpw->smb_passwd == NULL) { DEBUG(0,("check_lanman_password: no lanman password !\n")); @@ -462,6 +468,12 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi return False; } + if(smbpw->acct_ctrl & ACB_DISABLED) + { + DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name)); + return False; + } + if(smbpw->smb_passwd == NULL) { DEBUG(0,("change_lanman_password: no lanman password !\n")); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 048dab8b3e..bbeeb21e96 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -27,6 +27,7 @@ */ #include "includes.h" +#include "nterr.h" #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -131,79 +132,128 @@ static BOOL prefix_ok(char *str,char *prefix) return(strncmp(str,prefix,strlen(prefix)) == 0); } +/******************************************************************* + copies parameters and data, as needed, into the smb buffer + + *both* the data and params sections should be aligned. this + is fudged in the rpc pipes by + at present, only the data section is. this may be a possible + cause of some of the ipc problems being experienced. lkcl26dec97 + + ******************************************************************/ +static void copy_trans_params_and_data(char *outbuf, int align, + struct mem_buf *rparam, struct mem_buf *rdata, + int param_offset, int data_offset, + int param_len, int data_len) +{ + char *copy_into = smb_buf(outbuf); + + DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n", + param_offset, param_offset + param_len, + data_offset , data_offset + data_len)); + + if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len); + copy_into += param_len + align; + if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len); +} /**************************************************************************** send a trans reply ****************************************************************************/ -static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup) +static void send_trans_reply(char *outbuf, + struct mem_buf *rdata, + struct mem_buf *rparam, + uint16 *setup, int lsetup, int max_data_ret) { - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - int align; + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + int align; + + int ldata = rdata ? mem_buf_len(rdata ) : 0; + int lparam = rparam ? mem_buf_len(rparam) : 0; - this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); + BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False; + + if (buffer_too_large) + { + DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret)); + ldata = max_data_ret; + } + + this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING - /* if you don't want Net Monitor to decode your packets, do this!!! */ - align = ((this_lparam+1)%4); + /* if you don't want Net Monitor to decode your packets, do this!!! */ + align = ((this_lparam+1)%4); #else - align = (this_lparam%4); + align = (this_lparam%4); #endif - set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); - if (this_lparam) - memcpy(smb_buf(outbuf),param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata); - - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,lsetup); - for (i=0;i<lsetup;i++) - SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data = this_ldata; - tot_param = this_lparam; - - while (tot_data < ldata || tot_param < lparam) - { - this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam)); + set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); - align = (this_lparam%4); + if (buffer_too_large) + { + /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */ + SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION); + } - set_message(outbuf,10,this_ldata+this_lparam+align,False); - if (this_lparam) - memcpy(smb_buf(outbuf),param+tot_param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata); + copy_trans_params_and_data(outbuf, align, + rparam , rdata, + tot_param , tot_data, + this_lparam, this_ldata); + + SSVAL(outbuf,smb_vwv0,lparam); + SSVAL(outbuf,smb_vwv1,ldata); + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv5,0); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,0); + SSVAL(outbuf,smb_vwv9,lsetup); + + for (i=0;i<lsetup;i++) + { + SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]); + } - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data); - SSVAL(outbuf,smb_vwv9,0); + show_msg(outbuf); + send_smb(Client,outbuf); - show_msg(outbuf); - send_smb(Client,outbuf); + tot_data = this_ldata; + tot_param = this_lparam; - tot_data += this_ldata; - tot_param += this_lparam; - } + while (tot_data < ldata || tot_param < lparam) + { + this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */ + this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam)); + + align = (this_lparam%4); + + set_message(outbuf,10,this_ldata+this_lparam+align,False); + + copy_trans_params_and_data(outbuf, align, + rparam , rdata, + tot_param , tot_data, + this_lparam, this_ldata); + + SSVAL(outbuf,smb_vwv3,this_lparam); + SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); + SSVAL(outbuf,smb_vwv5,tot_param); + SSVAL(outbuf,smb_vwv6,this_ldata); + SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); + SSVAL(outbuf,smb_vwv8,tot_data); + SSVAL(outbuf,smb_vwv9,0); + + show_msg(outbuf); + send_smb(Client,outbuf); + + tot_data += this_ldata; + tot_param += this_lparam; + } } struct pack_desc { @@ -1252,6 +1302,39 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, return(True); } +/**************************************************************************** + command 0x34 - suspected of being a "Lookup Names" stub api + ****************************************************************************/ +static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data, + int mdrcnt, int mprcnt, char **rdata, + char **rparam, int *rdata_len, int *rparam_len) +{ + char *str1 = param+2; + char *str2 = skip_string(str1,1); + char *p = skip_string(str2,1); + int uLevel = SVAL(p,0); + int buf_len = SVAL(p,2); + int counted=0; + int missed=0; + + DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", + str1, str2, p, uLevel, buf_len)); + + if (!prefix_ok(str1,"zWrLeh")) return False; + + *rdata_len = 0; + *rdata = NULL; + + *rparam_len = 8; + *rparam = REALLOC(*rparam,*rparam_len); + + SSVAL(*rparam,0,0x08AC); /* informational warning message */ + SSVAL(*rparam,2,0); + SSVAL(*rparam,4,counted); + SSVAL(*rparam,6,counted+missed); + + return(True); +} /**************************************************************************** get info about a share @@ -2185,8 +2268,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, char *p2; /* get NIS home of a previously validated user - simeon */ + /* With share level security vuid will always be zero. + Don't depend on vuser being non-null !!. JRA */ user_struct *vuser = get_valid_user_struct(vuid); - DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); + if(vuser != NULL) + DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); *rparam_len = 6; *rparam = REALLOC(*rparam,*rparam_len); @@ -2236,7 +2322,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, /* EEK! the cifsrap.txt doesn't have this in!!!! */ SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); } @@ -2292,7 +2378,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, { SIVAL(p,60,0); /* auth_flags */ SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,vuser->real_name); /* simeon */ + strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName)); p2 = skip_string(p2,1); SIVAL(p,68,0); /* urs_comment */ SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ @@ -2920,175 +3006,331 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, return(True); } - -struct +struct api_cmd { - char * name; char * pipe_clnt_name; -#ifdef NTDOMAIN char * pipe_srv_name; -#endif - int subcommand; - BOOL (*fn) (); -} api_fd_commands [] = - { -#ifdef NTDOMAIN - { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP }, - { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP }, - { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP }, - { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP }, - { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP }, - { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported } -#else - { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP }, - { NULL, NULL, -1, (BOOL (*)())api_Unsupported } -#endif - }; + BOOL (*fn) (pipes_struct *, prs_struct *); +}; -/**************************************************************************** - handle remote api calls delivered to a named pipe already opened. - ****************************************************************************/ -static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +static struct api_cmd api_fd_commands[] = { - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; + { "lsarpc", "lsass", api_ntlsa_rpc }, + { "samr", "lsass", api_samr_rpc }, + { "srvsvc", "ntsvcs", api_srvsvc_rpc }, + { "wkssvc", "ntsvcs", api_wkssvc_rpc }, + { "NETLOGON", "lsass", api_netlog_rpc }, + { "winreg", "winreg", api_reg_rpc }, + { NULL, NULL, NULL } +}; - BOOL reply = False; - BOOL bind_req = False; - BOOL set_nphs = False; +static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd) +{ + BOOL ntlmssp_auth = False; + fstring ack_pipe_name; + int i = 0; - int i; - int fd; - int subcommand; - char *pipe_name; - - DEBUG(5,("api_fd_reply\n")); - /* First find out the name of this file. */ - if (suwcnt != 2) - { - DEBUG(0,("Unexpected named pipe transaction.\n")); - return(-1); - } - - /* Get the file handle and hence the file name. */ - fd = setup[1]; - subcommand = setup[0]; - pipe_name = get_rpc_pipe_hnd_name(fd); + DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); - if (pipe_name == NULL) - { - DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd)); - } + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) + { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) + { + DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", + api_fd_commands[i].pipe_clnt_name, + api_fd_commands[i].pipe_srv_name)); + fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name); + break; + } + } - DEBUG(3,("Got API command %d on pipe %s (fd %x)", - subcommand, pipe_name, fd)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); - - for (i = 0; api_fd_commands[i].name; i++) - { - if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) && - api_fd_commands[i].subcommand == subcommand && - api_fd_commands[i].fn) - { - DEBUG(3,("Doing %s\n", api_fd_commands[i].name)); - break; - } - } - - rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024); - rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - -#ifdef NTDOMAIN - /* RPC Pipe command 0x26. */ - if (data != NULL && api_fd_commands[i].subcommand == 0x26) - { - RPC_HDR hdr; + if (api_fd_commands[i].fn == NULL) return False; - /* process the rpc header */ - char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0); - - /* bind request received */ - if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND)))) - { - RPC_HDR_RB hdr_rb; + /* decode the bind request */ + smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0); - /* decode the bind request */ - char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0); + if (pd->offset == 0) return False; - if ((bind_req = (p != NULL))) - { - RPC_HDR_BA hdr_ba; - fstring ack_pipe_name; + if (p->hdr.auth_len != 0) + { + /* decode the authentication verifier */ + smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0); - /* name has to be \PIPE\xxxxx */ - strcpy(ack_pipe_name, "\\PIPE\\"); - strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name); + if (pd->offset == 0) return False; - /* make a bind acknowledgement */ - make_rpc_hdr_ba(&hdr_ba, - hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid, - ack_pipe_name, - 0x1, 0x0, 0x0, - &(hdr_rb.transfer)); + /* ignore the version number for now */ + ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP"); + } - p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0); + /* name has to be \PIPE\xxxxx */ + strcpy(ack_pipe_name, "\\PIPE\\"); + strcat(ack_pipe_name, p->pipe_srv_name); - rdata_len = PTR_DIFF(p, rdata); + DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); - make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len); + prs_init(&(p->rdata), 1024, 4, 0, False); + prs_init(&(p->rhdr ), 0x10, 4, 0, False); + prs_init(&(p->rauth), 1024, 4, 0, False); - p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0); - - reply = (p != NULL); - } - } - } -#endif + /***/ + /*** do the bind ack first ***/ + /***/ - /* Set Named Pipe Handle state */ - if (subcommand == 0x1) - { - set_nphs = True; - reply = api_LsarpcSNPHS(fd, cnum, params); - } + make_rpc_hdr_ba(&p->hdr_ba, + p->hdr_rb.bba.max_tsize, + p->hdr_rb.bba.max_rsize, + p->hdr_rb.bba.assoc_gid, + ack_pipe_name, + 0x1, 0x0, 0x0, + &(p->hdr_rb.transfer)); - if (!bind_req && !set_nphs) - { - DEBUG(10,("calling api_fd_command\n")); + smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0); + mem_realloc_data(p->rdata.data, p->rdata.offset); - reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - DEBUG(10,("called api_fd_command\n")); - } + /***/ + /*** now the authentication ***/ + /***/ - if (rdata_len > mdrcnt || rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* if we get False back then it's actually unsupported */ - if (!reply) - { - api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - - if (rdata ) free(rdata ); - if (rparam) free(rparam); - - return(-1); + if (ntlmssp_auth) + { + uint8 data[16]; + bzero(data, sizeof(data)); /* first 8 bytes are non-zero */ + + make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp, + 0x0a, 0x06, 0, + "NTLMSSP", 2, + 0x00000000, 0x0000b2b3, 0x000082b1, + data); + smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0); + mem_realloc_data(p->rauth.data, p->rauth.offset); + } + + /***/ + /*** then do the header, now we know the length ***/ + /***/ + + make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, + p->rdata.offset + p->rauth.offset, + p->rauth.offset); + + smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0); + mem_realloc_data(p->rhdr.data, p->rdata.offset); + + /***/ + /*** link rpc header, bind acknowledgment and authentication responses ***/ + /***/ + + p->rhdr.data->offset.start = 0; + p->rhdr.data->offset.end = p->rhdr.offset; + p->rhdr.data->next = p->rdata.data; + + if (ntlmssp_auth) + { + p->rdata.data->offset.start = p->rhdr.offset; + p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; + p->rdata.data->next = p->rauth.data; + + p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset; + p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset; + p->rauth.data->next = NULL; + } + else + { + p->rdata.data->offset.start = p->rhdr.offset; + p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset; + p->rdata.data->next = NULL; + } + + return True; } +static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd) +{ + int i = 0; + + for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) + { + if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) && + api_fd_commands[i].fn != NULL) + { + DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name)); + return api_fd_commands[i].fn(p, pd); + } + } + return False; +} +static BOOL api_dce_rpc_command(char *outbuf, + pipes_struct *p, + prs_struct *pd) +{ + BOOL reply = False; + if (pd->data == NULL) return False; + + /* process the rpc header */ + smb_io_rpc_hdr("", &p->hdr, pd, 0); + + if (pd->offset == 0) return False; + + switch (p->hdr.pkt_type) + { + case RPC_BIND : + { + reply = api_pipe_bind_req(p, pd); + break; + } + case RPC_REQUEST: + { + reply = api_pipe_request (p, pd); + break; + } + } + + if (reply) + { + /* now send the reply */ + send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len); + + if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len) + { + /* all of data was sent: no need to wait for SMBreadX calls */ + mem_free_data(p->rhdr .data); + mem_free_data(p->rdata.data); + } + } + + return reply; +} + +/**************************************************************************** + SetNamedPipeHandleState +****************************************************************************/ +static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param) +{ + uint16 id; + + if (!param) return False; + + id = param[0] + (param[1] << 8); + DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id)); + + if (set_rpc_pipe_hnd_state(p, id)) + { + /* now send the reply */ + send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len); + + return True; + } + return False; +} + + +/**************************************************************************** + when no reply is generated, indicate unsupported. + ****************************************************************************/ +static BOOL api_no_reply(char *outbuf, int max_rdata_len) +{ + struct mem_buf rparam; + + mem_init(&rparam, 0); + mem_alloc_data(&rparam, 4); + + rparam.offset.start = 0; + rparam.offset.end = 4; + + /* unsupported */ + SSVAL(rparam.data,0,NERR_notsupported); + SSVAL(rparam.data,2,0); /* converter word */ + + DEBUG(3,("Unsupported API fd command\n")); + + /* now send the reply */ + send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len); + + mem_free_data(&rparam); + + return(-1); +} + +/**************************************************************************** + handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ +static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + BOOL reply = False; + + int pnum; + int subcommand; + pipes_struct *p = NULL; + prs_struct pd; + struct mem_buf data_buf; + + DEBUG(5,("api_fd_reply\n")); + + /* fake up a data buffer from the api_fd_reply data parameters */ + mem_create(&data_buf, data, tdscnt, 0, False); + data_buf.offset.start = 0; + data_buf.offset.end = tdscnt; + + /* fake up a parsing structure */ + pd.data = &data_buf; + pd.align = 4; + pd.io = True; + pd.offset = 0; + + /* First find out the name of this file. */ + if (suwcnt != 2) + { + DEBUG(0,("Unexpected named pipe transaction.\n")); + return(-1); + } + + /* Get the file handle and hence the file name. */ + pnum = setup[1]; + subcommand = setup[0]; + get_rpc_pipe(pnum, &p); + + if (p != NULL) + { + DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", + subcommand, p->name, pnum)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid)); + + /* record maximum data length that can be transmitted in an SMBtrans */ + p->max_rdata_len = mdrcnt; + + switch (subcommand) + { + case 0x26: + { + /* dce/rpc command */ + reply = api_dce_rpc_command(outbuf, p, &pd); + break; + } + case 0x01: + { + /* Set Named Pipe Handle state */ + reply = api_SNPHS(outbuf, p, params); + break; + } + } + } + else + { + DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum)); + } + + if (!reply) + { + return api_no_reply(outbuf, mdrcnt); + } + return -1; +} /**************************************************************************** the buffer was too small @@ -3145,6 +3387,7 @@ struct {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0}, {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0}, {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0}, + {"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0}, {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0}, {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0}, {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0}, @@ -3177,6 +3420,8 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, int tdscnt,int tpscnt,int mdrcnt,int mprcnt) { int api_command = SVAL(params,0); + struct mem_buf rdata_buf; + struct mem_buf rparam_buf; char *rdata = NULL; char *rparam = NULL; int rdata_len = 0; @@ -3216,14 +3461,20 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, &rdata,&rparam,&rdata_len,&rparam_len); + mem_create(&rdata_buf , rdata , rdata_len , 0, False); + mem_create(&rparam_buf, rparam, rparam_len, 0, False); + + rdata_buf.offset.start = 0; + rdata_buf.offset.end = rdata_len; + + rparam_buf.offset.start = 0; + rparam_buf.offset.end = rparam_len; /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); + send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0); - if (rdata) - free(rdata); - if (rparam) - free(rparam); + if (rdata ) free(rdata); + if (rparam) free(rparam); return(-1); } diff --git a/source3/smbd/password.c b/source3/smbd/password.c index a51e5f639f..b422dda36c 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -877,6 +877,68 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha } /**************************************************************************** + Do a specific test for an smb password being correct, given a smb_password and + the lanman and NT responses. +****************************************************************************/ + +BOOL smb_password_ok(struct smb_passwd *smb_pass, + uchar lm_pass[24], uchar nt_pass[24]) +{ + uchar challenge[8]; + + if (!lm_pass || !smb_pass) return(False); + + if(smb_pass->acct_ctrl & ACB_DISABLED) + { + DEBUG(3,("smb_password_ok: account for user %s was disabled.\n", smb_pass->smb_name)); + return(False); + } + + if (!last_challenge(challenge)) + { + DEBUG(1,("smb_password_ok: no challenge done - password failed\n")); + return False; + } + + DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n", smb_pass->smb_name)); + + if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL)) + { + /* We have the NT MD4 hash challenge available - see if we can + use it (ie. does it exist in the smbpasswd file). + */ + DEBUG(4,("smb_password_ok: Checking NT MD4 password\n")); + if (smb_password_check(nt_pass, smb_pass->smb_nt_passwd, challenge)) + { + DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n")); + return(True); + } + DEBUG(4,("smb_password_ok: NT MD4 password check failed\n")); + } + + /* Try against the lanman password. smb_pass->smb_passwd == NULL means + no password, allow access. */ + + DEBUG(4,("Checking LM MD4 password\n")); + + if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ)) + { + DEBUG(4,("smb_password_ok: no password required for user %s\n", smb_pass->smb_name)); + return True; + } + + if((smb_pass->smb_passwd != NULL) && smb_password_check(lm_pass, smb_pass->smb_passwd, challenge)) + { + DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n")); + return(True); + } + + DEBUG(4,("smb_password_ok: LM MD4 password check failed\n")); + + return False; +} + +/**************************************************************************** check if a username/password is OK ****************************************************************************/ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) @@ -940,6 +1002,13 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } + /* Quit if the account was disabled. */ + if(smb_pass->acct_ctrl & ACB_DISABLED) + { + DEBUG(3,("password_ok: account for user %s was disabled.\n", user)); + return(False); + } + /* Ensure the uid's match */ if (smb_pass->smb_userid != pass->pw_uid) { @@ -947,35 +1016,13 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) return(False); } - if (Protocol >= PROTOCOL_NT1) - { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - if (smb_pass->smb_nt_passwd != NULL) - { - DEBUG(4,("Checking NT MD4 password\n")); - if (smb_password_check(password, - smb_pass->smb_nt_passwd, - (unsigned char *)challenge)) - { - update_protected_database(user,True); - return(True); - } - DEBUG(4,("NT MD4 password check failed\n")); - } - } - - /* Try against the lanman password */ - - if (smb_password_check(password, - smb_pass->smb_passwd, - (unsigned char *)challenge)) { - update_protected_database(user,True); - return(True); - } + if(smb_password_ok( smb_pass, password, password)) + { + update_protected_database(user,True); + return(True); + } - DEBUG(3,("Error smb_password_check failed\n")); + DEBUG(3,("Error smb_password_check failed\n")); } DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index b5f9700f33..4d425cc2c0 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -51,17 +51,7 @@ extern fstring myworkgroup; a packet to ensure chaining works correctly */ #define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where)) -char * known_pipes [] = -{ - "lsarpc", -#if NTDOMAIN - "NETLOGON", - "srvsvc", - "wkssvc", - "samr", -#endif - NULL -}; +extern struct pipe_id_info pipe_names[]; /**************************************************************************** reply to an open and X on a named pipe @@ -72,7 +62,8 @@ char * known_pipes [] = int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; - int cnum = SVAL(inbuf,smb_tid); + uint16 cnum = SVAL(inbuf, smb_tid); + uint16 vuid = SVAL(inbuf, smb_uid); int pnum = -1; int smb_ofun = SVAL(inbuf,smb_vwv8); int size=0,fmode=0,mtime=0,rmode=0; @@ -89,23 +80,23 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(4,("Opening pipe %s.\n", fname)); - /* Strip \PIPE\ off the name. */ - pstrcpy(fname,smb_buf(inbuf) + PIPELEN); - /* See if it is one we want to handle. */ - for( i = 0; known_pipes[i] ; i++ ) - if( strcmp(fname,known_pipes[i]) == 0 ) + for( i = 0; pipe_names[i].client_pipe ; i++ ) + if( strcmp(fname,pipe_names[i].client_pipe) == 0 ) break; - if ( known_pipes[i] == NULL ) + if ( pipe_names[i].client_pipe == NULL ) return(ERROR(ERRSRV,ERRaccess)); + /* Strip \PIPE\ off the name. */ + pstrcpy(fname,smb_buf(inbuf) + PIPELEN); + /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); smb_ofun |= 0x10; /* Add Create it not exists flag */ - pnum = open_rpc_pipe_hnd(fname, cnum); + pnum = open_rpc_pipe_hnd(fname, cnum, vuid); if (pnum < 0) return(ERROR(ERRSRV,ERRnofids)); /* Prepare the reply */ @@ -133,190 +124,65 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) /**************************************************************************** - reply to a close -****************************************************************************/ -int reply_pipe_close(char *inbuf,char *outbuf) -{ - int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); - int cnum = SVAL(inbuf,smb_tid); - int outsize = set_message(outbuf,0,0,True); - - DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum)); - - if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); - - return(outsize); -} - - -/**************************************************************************** - api_LsarpcSNPHS + reply to a read and X - SetNamedPipeHandleState on \PIPE\lsarpc. + This code is basically stolen from reply_read_and_X with some + wrinkles to handle pipes. ****************************************************************************/ -BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param) +int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { - uint16 id; + int pnum = get_rpc_pipe_num(inbuf,smb_vwv2); + uint32 smb_offs = IVAL(inbuf,smb_vwv3); + int smb_maxcnt = SVAL(inbuf,smb_vwv5); + int smb_mincnt = SVAL(inbuf,smb_vwv6); + int cnum; + int nread = -1; + char *data; + BOOL ok = False; - if (!param) return False; + cnum = SVAL(inbuf,smb_tid); - id = param[0] + (param[1] << 8); - DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id)); - - return set_rpc_pipe_hnd_state(pnum, cnum, id); -} - - -/**************************************************************************** - api_LsarpcTNP - - TransactNamedPipe on \PIPE\lsarpc. -****************************************************************************/ -static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1, dword2; - char pname[] = "\\PIPE\\lsass"; +/* + CHECK_FNUM(fnum,cnum); + CHECK_READ(fnum); + CHECK_ERROR(fnum); +*/ - /* All kinds of mysterious numbers here */ - *rdata_len = 68; - *rdata = REALLOC(*rdata,*rdata_len); + set_message(outbuf,12,0,True); + data = smb_buf(outbuf); - dword1 = IVAL(data,0xC); - dword2 = IVAL(data,0x10); + nread = read_pipe(pnum, data, smb_offs, smb_maxcnt); - SIVAL(*rdata,0,0xc0005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x44); - SIVAL(*rdata,0xC,dword1); + ok = True; - SIVAL(*rdata,0x10,dword2); - SIVAL(*rdata,0x14,0x15); - SSVAL(*rdata,0x18,sizeof(pname)); - strcpy(*rdata + 0x1a,pname); - SIVAL(*rdata,0x28,1); - memcpy(*rdata + 0x30, data + 0x34, 0x14); -} - -static void LsarpcTNP2(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - - /* All kinds of mysterious numbers here */ - *rdata_len = 48; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x30); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x18); - SIVAL(*rdata,0x1c,0x44332211); - SIVAL(*rdata,0x20,0x88776655); - SIVAL(*rdata,0x24,0xCCBBAA99); - SIVAL(*rdata,0x28,0x11FFEEDD); -} - -static void LsarpcTNP3(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - uint16 word1; - char * workgroup = myworkgroup; - int wglen = strlen(workgroup); - int i; - - /* All kinds of mysterious numbers here */ - *rdata_len = 90 + 2 * wglen; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - word1 = SVAL(data,0x2C); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x60); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x48); - SSVAL(*rdata,0x18,0x5988); /* This changes */ - SSVAL(*rdata,0x1A,0x15); - SSVAL(*rdata,0x1C,word1); - SSVAL(*rdata,0x20,6); - SSVAL(*rdata,0x22,8); - SSVAL(*rdata,0x24,0x8E8); /* So does this */ - SSVAL(*rdata,0x26,0x15); - SSVAL(*rdata,0x28,0x4D48); /* And this */ - SSVAL(*rdata,0x2A,0x15); - SIVAL(*rdata,0x2C,4); - SIVAL(*rdata,0x34,wglen); - for ( i = 0 ; i < wglen ; i++ ) - (*rdata)[0x38 + i * 2] = workgroup[i]; - - /* Now fill in the rest */ - i = 0x38 + wglen * 2; - SSVAL(*rdata,i,0x648); - SIVAL(*rdata,i+2,4); - SIVAL(*rdata,i+6,0x401); - SSVAL(*rdata,i+0xC,0x500); - SIVAL(*rdata,i+0xE,0x15); - SIVAL(*rdata,i+0x12,0x2372FE1); - SIVAL(*rdata,i+0x16,0x7E831BEF); - SIVAL(*rdata,i+0x1A,0x4B454B2); -} - -static void LsarpcTNP4(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - - /* All kinds of mysterious numbers here */ - *rdata_len = 48; - *rdata = REALLOC(*rdata,*rdata_len); + if (nread < 0) + return(UNIXERROR(ERRDOS,ERRnoaccess)); + + SSVAL(outbuf,smb_vwv5,nread); + SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); + SSVAL(smb_buf(outbuf),-2,nread); + + DEBUG(3,("%s readX pnum=%04x cnum=%d min=%d max=%d nread=%d\n", + timestring(),pnum,cnum, + smb_mincnt,smb_maxcnt,nread)); - dword1 = IVAL(data,0xC); + set_chain_pnum(pnum); - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x30); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x18); + return chain_reply(inbuf,outbuf,length,bufsize); } - - -BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) +/**************************************************************************** + reply to a close +****************************************************************************/ +int reply_pipe_close(char *inbuf,char *outbuf) { - uint32 id,id2; + int pnum = get_rpc_pipe_num(inbuf,smb_vwv0); + int cnum = SVAL(inbuf,smb_tid); + int outsize = set_message(outbuf,0,0,True); - id = IVAL(data,0); + DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum)); - DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id)); - switch (id) - { - case 0xb0005: - LsarpcTNP1(data,rdata,rdata_len); - break; + if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid)); - case 0x03000005: - id2 = IVAL(data,8); - DEBUG(4,("\t- Suboperation %lx\n",id2)); - switch (id2 & 0xF) - { - case 8: - LsarpcTNP2(data,rdata,rdata_len); - break; - - case 0xC: - LsarpcTNP4(data,rdata,rdata_len); - break; - - case 0xE: - LsarpcTNP3(data,rdata,rdata_len); - break; - } - break; - } - return(True); + return(outsize); } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 38380180f9..74cfd797c3 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -366,6 +366,74 @@ int reply_ioctl(char *inbuf,char *outbuf) #endif } +/**************************************************************************** + always return an error: it's just a matter of which one... + ****************************************************************************/ +static int session_trust_account(char *inbuf, char *outbuf, char *user, + char *smb_passwd, int smb_passlen, + char *smb_nt_passwd, int smb_nt_passlen) +{ + struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */ + if (lp_security() == SEC_USER) + { + smb_trust_acct = get_smbpwd_entry(user, 0); + } + else + { + DEBUG(3,("Trust account %s only supported with security = user\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + if (smb_trust_acct == NULL) + { + /* lkclXXXX: workstation entry doesn't exist */ + DEBUG(4,("Trust account %s user doesn't exist\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER)); + } + else + { + if ((smb_passlen != 24) || (smb_nt_passlen != 24)) + { + DEBUG(4,("Trust account %s - password length wrong.\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd)) + { + DEBUG(4,("Trust Account %s - password failed\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); + } + + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST)) + { + DEBUG(4,("Domain trust account %s denied by server\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)); + } + + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST)) + { + DEBUG(4,("Server trust account %s denied by server\n",user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT)); + } + if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST)) + { + DEBUG(4,("Wksta trust account %s denied by server\n", user)); + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT)); + } + } + + /* don't know what to do: indicate logon failure */ + SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES); + return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE)); +} + /**************************************************************************** reply to a session setup command @@ -386,7 +454,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) BOOL valid_nt_password = False; pstring user; BOOL guest=False; - BOOL computer_id=False; static BOOL done_sesssetup = False; BOOL doencrypt = SMBENCRYPT(); char *domain = ""; @@ -496,48 +563,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* If name ends in $ then I think it's asking about whether a */ /* computer with that name (minus the $) has access. For now */ /* say yes to everything ending in $. */ - if (user[strlen(user) - 1] == '$') + if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) { -#ifdef NTDOMAIN - struct smb_passwd *smb_pass; /* To check if machine account exists */ -/* - PAXX: Ack. We don't want to do this. The workstation trust account - with a $ on the end should exist in the local password database - or be mapped to something generic, but not modified. For NT - domain support we must reject this used in certain circumstances - with a code to indicate to the client that it is an invalid use - of a workstation trust account. NTWKS needs this error to join - a domain. This may be the source of future bugs if we cannot - be sure whether to reject this or not. -*/ - /* non-null user name indicates search by username not by smb userid */ - smb_pass = get_smbpwd_entry(user, 0); - - if (!smb_pass) - { - /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */ - DEBUG(4,("Workstation trust account %s doesn't exist.",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */ - } - else - { - /* PAXX: This is the NO LOGON workstation trust account stuff */ - /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */ - DEBUG(4,("No Workstation trust account %s",user)); - SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */ - CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */ - return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */ - } - - computer_id = True; -#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */ - user[strlen(user) - 1] = '\0'; -#endif + return session_trust_account(inbuf, outbuf, user, + smb_apasswd, smb_apasslen, + smb_ntpasswd, smb_ntpasslen); } - /* If no username is sent use the guest account */ if (!*user) { @@ -583,7 +615,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) { - if (!computer_id && lp_security() >= SEC_USER) { + if (lp_security() >= SEC_USER) { #if (GUEST_SESSSETUP == 0) return(ERROR(ERRSRV,ERRbadpw)); #endif @@ -643,7 +675,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) uid = pw->pw_uid; } - if (guest && !computer_id) + if (guest) SSVAL(outbuf,smb_vwv2,1); /* register the name and uid as being validated, so further connections diff --git a/source3/smbd/server.c b/source3/smbd/server.c index e290027d0a..774e5c10b9 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -3955,7 +3955,7 @@ reply for the nt protocol int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ; + int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS; /* other valid capabilities which we may support at some time... CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; @@ -5190,10 +5190,8 @@ static void init_structs(void ) /* for RPC pipes */ init_rpc_pipe_hnd(); -#ifdef NTDOMAIN /* for LSA handles */ init_lsa_policy_hnd(); -#endif init_dptrs(); } diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 598944baa5..7ab8d8a0db 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -400,7 +400,7 @@ static void usage(char *name) chmod(pfile, 0600); /* Lock the smbpasswd file for write. */ - if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) { + if ((lockfd = pw_file_lock(fileno(fp), F_WRLCK, 5)) < 0) { err = errno; fprintf(stderr, "%s: Failed to lock password file %s.\n", argv[0], pfile); |