From fdeea341ed1bae670382e45eb731db1b5838ad21 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Mar 1998 21:11:04 +0000 Subject: [PATCH] "For I have laboured mightily on Luke's code, and hath broken all I saw" - the book of Jeremy, chapter 1 :-). So here is the mega-merge of the NTDOM branch server code. It doesn't include the new client side pieces, we'll look at that later. This should give the same functionality, server wise, as the NTDOM branch does, only merged into the main branch. Any fixes to domain controler functionality should be added to the main branch, not the NTDOM branch. This code compiles without warnings on gcc2.8, but will need further testing before we are sure all the working functionality of the NTDOM server branch has been correctly carried over. I hereby declare the server side of the NTDOM branch dead (and all who sail in her :-). Jeremy. (This used to be commit 118ba4d77a33248e762a2cf843fb7cbc906ee6e7) --- source3/client/ntclient.c | 6 +- source3/include/ntdomain.h | 127 ++ source3/include/nterr.h | 1 + source3/include/proto.h | 960 +++++++--- source3/include/rpc_dce.h | 211 +++ source3/include/rpc_lsa.h | 288 +++ source3/include/rpc_misc.h | 272 +++ source3/include/rpc_netlogon.h | 372 ++++ source3/include/rpc_reg.h | 141 ++ source3/include/rpc_samr.h | 1023 ++++++++++ source3/include/rpc_srvsvc.h | 540 ++++++ source3/include/rpc_wkssvc.h | 73 + source3/include/smb.h | 1114 +---------- source3/lib/membuffer.c | 370 ++++ source3/lib/util.c | 25 + source3/lib/util_hnd.c | 316 ++++ source3/lsarpcd/srv_lsa.c | 444 +++++ source3/nmbd/nmbd_processlogon.c | 10 +- source3/nmbd/nmbd_subnetdb.c | 2 + source3/nmbd/nmbd_winsserver.c | 7 +- source3/param/loadparm.c | 6 +- source3/passdb/smbpass.c | 1558 ++++++++-------- source3/rpc_client/cli_login.c | 395 ++++ source3/rpc_client/cli_lsarpc.c | 255 +++ source3/rpc_client/cli_netlogon.c | 461 +++++ source3/rpc_client/cli_pipe.c | 683 +++++++ source3/rpc_client/cli_samr.c | 695 +++++++ source3/rpc_client/cli_srvsvc.c | 411 ++++ source3/rpc_client/cli_wkssvc.c | 90 + source3/rpc_client/ntclienttrust.c | 167 ++ source3/rpc_parse/parse_lsa.c | 567 ++++++ source3/rpc_parse/parse_misc.c | 981 ++++++++++ source3/rpc_parse/parse_net.c | 1147 ++++++++++++ source3/rpc_parse/parse_prs.c | 290 +++ source3/rpc_parse/parse_reg.c | 335 ++++ source3/rpc_parse/parse_rpc.c | 528 ++++++ source3/rpc_parse/parse_samr.c | 2796 ++++++++++++++++++++++++++++ source3/rpc_parse/parse_srv.c | 1528 +++++++++++++++ source3/rpc_parse/parse_wks.c | 146 ++ source3/rpc_server/srv_lsa.c | 444 +++++ source3/rpc_server/srv_lsa_hnd.c | 316 ++++ source3/rpc_server/srv_netlog.c | 832 +++++++++ source3/rpc_server/srv_pipe_hnd.c | 315 ++++ source3/rpc_server/srv_reg.c | 240 +++ source3/rpc_server/srv_samr.c | 1352 ++++++++++++++ source3/rpc_server/srv_srvsvc.c | 1015 ++++++++++ source3/rpc_server/srv_util.c | 477 +++++ source3/rpc_server/srv_wkssvc.c | 113 ++ source3/script/mkproto.awk | 2 +- source3/smbd/chgpasswd.c | 12 + source3/smbd/ipc.c | 669 ++++--- source3/smbd/password.c | 103 +- source3/smbd/pipes.c | 242 +-- source3/smbd/reply.c | 116 +- source3/smbd/server.c | 4 +- source3/utils/smbpasswd.c | 2 +- 56 files changed, 22969 insertions(+), 2626 deletions(-) create mode 100644 source3/include/ntdomain.h create mode 100644 source3/include/rpc_dce.h create mode 100644 source3/include/rpc_lsa.h create mode 100644 source3/include/rpc_misc.h create mode 100644 source3/include/rpc_netlogon.h create mode 100644 source3/include/rpc_reg.h create mode 100644 source3/include/rpc_samr.h create mode 100644 source3/include/rpc_srvsvc.h create mode 100644 source3/include/rpc_wkssvc.h create mode 100644 source3/lib/membuffer.c create mode 100644 source3/lib/util_hnd.c create mode 100644 source3/lsarpcd/srv_lsa.c create mode 100644 source3/rpc_client/cli_login.c create mode 100644 source3/rpc_client/cli_lsarpc.c create mode 100644 source3/rpc_client/cli_netlogon.c create mode 100644 source3/rpc_client/cli_pipe.c create mode 100644 source3/rpc_client/cli_samr.c create mode 100644 source3/rpc_client/cli_srvsvc.c create mode 100644 source3/rpc_client/cli_wkssvc.c create mode 100644 source3/rpc_client/ntclienttrust.c create mode 100644 source3/rpc_parse/parse_lsa.c create mode 100644 source3/rpc_parse/parse_misc.c create mode 100644 source3/rpc_parse/parse_net.c create mode 100644 source3/rpc_parse/parse_prs.c create mode 100644 source3/rpc_parse/parse_reg.c create mode 100644 source3/rpc_parse/parse_rpc.c create mode 100644 source3/rpc_parse/parse_samr.c create mode 100644 source3/rpc_parse/parse_srv.c create mode 100644 source3/rpc_parse/parse_wks.c create mode 100644 source3/rpc_server/srv_lsa.c create mode 100644 source3/rpc_server/srv_lsa_hnd.c create mode 100644 source3/rpc_server/srv_netlog.c create mode 100644 source3/rpc_server/srv_pipe_hnd.c create mode 100644 source3/rpc_server/srv_reg.c create mode 100644 source3/rpc_server/srv_samr.c create mode 100644 source3/rpc_server/srv_srvsvc.c create mode 100644 source3/rpc_server/srv_util.c create mode 100644 source3/rpc_server/srv_wkssvc.c diff --git a/source3/client/ntclient.c b/source3/client/ntclient.c index 54ab49e3a65..bd0d0ccd5a6 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 00000000000..32812aa8b16 --- /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 92f02612dbc..643d93bc93a 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 f0591743c0a..19274157c6e 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 00000000000..9aacaaab87c --- /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 00000000000..008f8866c0f --- /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 00000000000..5d4e3858757 --- /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 00000000000..18086493289 --- /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 00000000000..28d11710cdf --- /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 00000000000..bcce64b6bea --- /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 00000000000..4d11b915e40 --- /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 00000000000..1483997acb3 --- /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 ccb3b0424a6..a60b74a8358 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 00000000000..0665b19ead3 --- /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 5af41cc06cd..19fa42592fd 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 00000000000..c8eabf35b41 --- /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 00000000000..60b74cf5991 --- /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 64f66038e03..f881b867c0f 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 07692cc82c2..e10ddc2c6ac 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 134b758c293..afc8741366f 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 39f6de0e1ec..2768a9da72f 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 fbda8949bcb..b51f6753065 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 00000000000..2033ea437ea --- /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 00000000000..6570903e795 --- /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 00000000000..aafde8d775d --- /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 00000000000..625b7741673 --- /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 00000000000..7a04d8ec356 --- /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 00000000000..dcedeb3a546 --- /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 00000000000..f5a4c203e08 --- /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 00000000000..38cbedae788 --- /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 00000000000..6eb42fc7493 --- /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 00000000000..225754903fb --- /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 00000000000..69d6ac08ede --- /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 00000000000..799bd1cc949 --- /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 00000000000..d278b75f5d9 --- /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 00000000000..b025d3f1c8e --- /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 00000000000..a72769d9c02 --- /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 00000000000..959a6096aa5 --- /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 00000000000..694acb5eec7 --- /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 00000000000..60b74cf5991 --- /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 00000000000..c8eabf35b41 --- /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 00000000000..94d6faa9925 --- /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 00000000000..e4893fee896 --- /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 00000000000..fa856f6983a --- /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 00000000000..02c8cb0ffec --- /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, + "", + 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 , ""); + 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 , ""); + 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 00000000000..285ea896574 --- /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 00000000000..7be259029ab --- /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 00000000000..3dd273f784a --- /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 1ccf2fb2b0a..bbbbc9029e1 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 fb795e973e5..c83ff1911c7 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 048dab8b3e4..bbeeb21e963 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;iuid, 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 a51e5f639fc..b422dda36c5 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -876,6 +876,68 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha return (memcmp(p24, password, 24) == 0); } +/**************************************************************************** + 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 ****************************************************************************/ @@ -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 b5f9700f339..4d425cc2c05 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 38380180f9f..74cfd797c3a 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 e290027d0a4..774e5c10b91 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 598944baa5e..7ab8d8a0dbf 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); -- 2.34.1