summaryrefslogtreecommitdiff
path: root/source3/rpc_client
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-03-11 21:11:04 +0000
committerJeremy Allison <jra@samba.org>1998-03-11 21:11:04 +0000
commitfdeea341ed1bae670382e45eb731db1b5838ad21 (patch)
treebdbc5138a9340bdbd5c12cee243e6acfb2e64daf /source3/rpc_client
parent4c6230afd2f144322c07c7e4c46147d3e5d2ddde (diff)
downloadsamba-fdeea341ed1bae670382e45eb731db1b5838ad21.tar.gz
samba-fdeea341ed1bae670382e45eb731db1b5838ad21.tar.bz2
samba-fdeea341ed1bae670382e45eb731db1b5838ad21.zip
"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)
Diffstat (limited to 'source3/rpc_client')
-rw-r--r--source3/rpc_client/cli_login.c395
-rw-r--r--source3/rpc_client/cli_lsarpc.c255
-rw-r--r--source3/rpc_client/cli_netlogon.c461
-rw-r--r--source3/rpc_client/cli_pipe.c683
-rw-r--r--source3/rpc_client/cli_samr.c695
-rw-r--r--source3/rpc_client/cli_srvsvc.c411
-rw-r--r--source3/rpc_client/cli_wkssvc.c90
-rw-r--r--source3/rpc_client/ntclienttrust.c167
8 files changed, 3157 insertions, 0 deletions
diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c
new file mode 100644
index 0000000000..2033ea437e
--- /dev/null
+++ b/source3/rpc_client/cli_login.c
@@ -0,0 +1,395 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NT Domain Authentication SMB / MSRPC client
+ Copyright (C) Andrew Tridgell 1994-1997
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+
+#if 0
+ if (!cli_initialise(cli, t_idx))
+ {
+ DEBUG(1,("do_nt_session_open: cli_initialise failed\n"));
+ return False;
+ }
+
+ DEBUG(1,("do_nt_session_open: server connect initialisation\n"));
+
+ if (!server_connect_init(cli, t_idx, myhostname, dest_ip, dest_host))
+ {
+ uint8 err_cls;
+ uint32 err_num;
+ cli_error(cli, t_idx, &err_cls, &err_num);
+ DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(cli, t_idx)));
+
+ return False;
+ }
+
+ DEBUG(1,("do_nt_session_open: server connect initialisation succeeded\n"));
+
+ if (!cli_session_setup(cli, t_idx, "", "", 1, NULL, 0, workgroup))
+ {
+ uint8 err_cls;
+ uint32 err_num;
+ cli_error(cli, t_idx, &err_cls, &err_num);
+ DEBUG(1,("session setup failed (%s)\n", cli_errstr(cli, t_idx)));
+
+ return False;
+ }
+
+ DEBUG(1,("do_nt_session_open: server session setup succeeded\n"));
+
+ if (!cli_send_tconX(cli, t_idx, "IPC$", "IPC", "", 1))
+ {
+ uint8 err_cls;
+ uint32 err_num;
+ cli_error(cli, t_idx, &err_cls, &err_num);
+ DEBUG(1,("cli_send_tconX failed (%s)\n", cli_errstr(cli, t_idx)));
+
+ return False;
+ }
+
+ DEBUG(1,("do_nt_session_open: server IPC$ connection succeeded\n"));
+#endif
+
+
+/****************************************************************************
+experimental nt login.
+
+****************************************************************************/
+BOOL do_nt_session_open(struct cli_state *cli, int t_idx, uint16 *fnum,
+ char *dest_host, char *myhostname,
+ char *mach_acct,
+ char *username, char *workgroup,
+ uchar sess_key[16], DOM_CRED *clnt_cred)
+{
+ DOM_CHAL clnt_chal;
+ DOM_CHAL srv_chal;
+
+ DOM_CHAL auth2_srv_chal;
+
+ UTIME zerotime;
+
+ char nt_owf_mach_pwd[16];
+ char nt_owf_prev_mpd[16];
+
+ RPC_IFACE abstract;
+ RPC_IFACE transfer;
+
+ fstring mach_pwd;
+ fstring prev_mpd;
+ fstring dest_srv;
+
+ /******************** initialise ********************************/
+
+ zerotime.time = 0;
+
+ DEBUG(1,("do_nt_session_open: %d\n", __LINE__));
+
+ /******************* open the \PIPE\NETLOGON file *****************/
+
+ if (((*fnum) = cli_open(cli, t_idx, PIPE_NETLOGON, O_CREAT, DENY_NONE,
+ NULL, NULL, NULL)) == 0xffff)
+ {
+ DEBUG(1,("do_nt_session_open: cli_open failed\n"));
+ return False;
+ }
+
+ /**************** Set Named Pipe State ***************/
+ if (!rpc_pipe_set_hnd_state(cli, t_idx, PIPE_NETLOGON, *fnum, 0x4300))
+ {
+ DEBUG(1,("do_nt_session_open: pipe hnd state failed\n"));
+ return False;
+ }
+
+ /******************* bind request on \PIPE\NETLOGON *****************/
+
+ if (!rpc_pipe_bind(cli, t_idx, PIPE_NETLOGON, *fnum,
+ &abstract, &transfer,
+ False, NULL, NULL))
+ {
+ DEBUG(1,("do_nt_session_open: rpc bind failed\n"));
+ return False;
+ }
+
+ /************ Check workstation trust account *******************/
+
+ /* default machine password is lower-case machine name (really secure) */
+ fstrcpy(mach_pwd, myhostname);
+ strlower(mach_pwd);
+
+ /* default machine password is lower-case machine name (really secure) */
+ fstrcpy(prev_mpd, myhostname);
+ strlower(prev_mpd);
+
+ /******************* Request Challenge ********************/
+
+ SIVAL(clnt_chal.data, 0, 0x11111111);
+ SIVAL(clnt_chal.data, 4, 0x22222222);
+
+ strcpy(dest_srv, "\\\\");
+ strcat(dest_srv, dest_host);
+ strupper(dest_srv);
+
+ /* send a client challenge; receive a server challenge */
+ if (!do_net_req_chal(cli, t_idx, *fnum, dest_srv, myhostname, &clnt_chal, &srv_chal))
+ {
+ DEBUG(1,("do_nt_session_open: request challenge failed\n"));
+ return False;
+ }
+
+ /**************** Long-term Session key **************/
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("generating nt owf from initial machine pwd: %s\n", mach_pwd));
+#endif
+ nt_owf_gen( mach_pwd, nt_owf_mach_pwd);
+
+#ifdef DEBUG_PASSWORD
+ dump_data(6, nt_owf_mach_pwd, 16);
+#endif
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("generating nt owf from previous machine pwd: %s\n", prev_mpd));
+#endif
+ nt_owf_gen( mach_pwd, nt_owf_prev_mpd);
+
+#ifdef DEBUG_PASSWORD
+ dump_data(6, nt_owf_prev_mpd, 16);
+#endif
+
+ /* calculate the session key */
+ cred_session_key(&clnt_chal, &srv_chal, nt_owf_mach_pwd, sess_key);
+#if 0
+ cred_session_key(&clnt_chal, &srv_chal, nt_owf_prev_mpd, sess_key+8);
+#else
+ bzero(sess_key+8, 8);
+#endif
+
+ /******************* Authenticate 2 ********************/
+
+ /* calculate auth-2 credentials */
+ cred_create(sess_key, &clnt_chal, zerotime, &(clnt_cred->challenge));
+
+ /* send client auth-2 challenge; receive an auth-2 challenge */
+ if (!do_net_auth2(cli, t_idx, *fnum,
+ dest_srv, mach_acct,
+ SEC_CHAN_WKSTA, myhostname,
+ &(clnt_cred->challenge), 0x000001ff, &auth2_srv_chal))
+ {
+ DEBUG(1,("do_nt_session_open: request challenge failed\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+ server password set
+ ****************************************************************************/
+BOOL do_nt_srv_pwset(struct cli_state *cli, int t_idx, uint16 fnum,
+ uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
+ char *new_mach_pwd,
+ char *dest_host, char *mach_acct, char *myhostname)
+{
+ /**************** Net Server Password Set **************/
+
+ DOM_CRED cred;
+ char nt_cypher[16];
+ uint8 mode = 1;
+ char nt_owf_new_mach_pwd[16];
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("generating nt owf from new machine pwd: %s\n", new_mach_pwd));
+#endif
+ nt_owf_gen(new_mach_pwd, nt_owf_new_mach_pwd);
+
+#ifdef DEBUG_PASSWORD
+dump_data(6, nt_owf_new_mach_pwd, 16);
+#endif
+
+ if (!obfuscate_pwd(nt_cypher, nt_owf_new_mach_pwd, mode))
+ {
+ DEBUG(5,("do_nt_srv_pwset: encrypt mach pwd failed\n"));
+ return False;
+ }
+
+ clnt_cred->timestamp.time = time(NULL);
+
+ memcpy(&cred, clnt_cred, sizeof(cred));
+
+ /* calculate credentials */
+ cred_create(sess_key, &(clnt_cred->challenge),
+ cred.timestamp,
+ &(cred.challenge));
+
+ /* send client srv_pwset challenge */
+ return do_net_srv_pwset(cli, t_idx, fnum, sess_key, clnt_cred,
+ dest_host, mach_acct, 2, myhostname,
+ &cred, rtn_cred,
+ nt_cypher);
+}
+
+/****************************************************************************
+ make interactive sam login info
+ ****************************************************************************/
+void make_nt_login_interactive(NET_ID_INFO_CTR *ctr,
+ uchar sess_key[16],
+ char *workgroup, char *myhostname,
+ uint32 smb_userid, char *username)
+{
+ /****************** SAM Info Preparation *******************/
+
+ char *smb_user_passwd = getpass("Enter NT Login Password:");
+
+ char lm_owf_user_pwd[16];
+ char nt_owf_user_pwd[16];
+
+ nt_lm_owf_gen(smb_user_passwd, nt_owf_user_pwd, lm_owf_user_pwd);
+
+#ifdef DEBUG_PASSWORD
+
+ DEBUG(100,("nt owf of user password: "));
+ dump_data(100, lm_owf_user_pwd, 16);
+
+ DEBUG(100,("nt owf of user password: "));
+ dump_data(100, nt_owf_user_pwd, 16);
+
+#endif
+
+ /* indicate an "interactive" login */
+ ctr->switch_value = 1;
+
+ /* this is used in both the SAM Logon and the SAM Logoff */
+ make_id_info1(&ctr->auth.id1, workgroup, 0,
+ smb_userid, 0,
+ username, myhostname,
+ sess_key, lm_owf_user_pwd, nt_owf_user_pwd);
+}
+
+/****************************************************************************
+experimental nt login.
+****************************************************************************/
+BOOL do_nt_login(struct cli_state *cli, int t_idx, uint16 fnum,
+ uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
+ NET_ID_INFO_CTR *ctr, char *dest_host, char *myhostname,
+ NET_USER_INFO_3 *user_info3)
+{
+ DOM_CRED sam_logon_rtn_cred;
+ DOM_CRED cred;
+ fstring dest_srv;
+ fstring my_host_name;
+
+ DEBUG(5,("do_nt_login: %d\n", __LINE__));
+
+ /*********************** SAM Logon **********************/
+
+ clnt_cred->timestamp.time = time(NULL);
+
+ memcpy(&cred, clnt_cred, sizeof(cred));
+
+ /* calculate sam logon credentials */
+ cred_create(sess_key, &(clnt_cred->challenge),
+ cred.timestamp,
+ &(cred.challenge));
+
+ strcpy(dest_srv, "\\\\");
+ strcat(dest_srv, dest_host);
+ strupper(dest_srv);
+
+ fstrcpy(my_host_name, myhostname);
+ strupper(my_host_name);
+
+ /* send client sam-logon challenge */
+ return do_net_sam_logon(cli, t_idx, fnum, sess_key, clnt_cred,
+ dest_srv, my_host_name,
+ &cred, &sam_logon_rtn_cred,
+ ctr->switch_value, ctr, 3, user_info3,
+ rtn_cred);
+}
+
+/****************************************************************************
+nt sam logoff
+****************************************************************************/
+BOOL do_nt_logoff(struct cli_state *cli, int t_idx, uint16 fnum,
+ uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
+ NET_ID_INFO_CTR *ctr, char *dest_host, char *myhostname)
+{
+ DOM_CRED sam_logoff_rtn_cred;
+ DOM_CRED cred;
+ fstring dest_srv;
+ fstring my_host_name;
+
+ DEBUG(5,("do_nt_logoff: %d\n", __LINE__));
+
+ /*********************** SAM Logoff *********************/
+
+ clnt_cred->timestamp.time = time(NULL);
+
+ memcpy(&cred, clnt_cred, sizeof(cred));
+
+ /* calculate sam logoff credentials */
+ cred_create(sess_key, &(clnt_cred->challenge),
+ cred.timestamp,
+ &(cred.challenge));
+
+ strcpy(dest_srv, "\\\\");
+ strcat(dest_srv, dest_host);
+ strupper(dest_srv);
+
+ fstrcpy(my_host_name, myhostname);
+ strupper(my_host_name);
+
+ /* send client sam-logoff challenge; receive a sam-logoff challenge */
+ return do_net_sam_logoff(cli, t_idx, fnum, sess_key, clnt_cred,
+ dest_srv, my_host_name,
+ &cred, &sam_logoff_rtn_cred,
+ ctr->switch_value, ctr, 3,
+ rtn_cred);
+}
+
+#if 0
+ /* free memory used in all rpc transactions, above */
+ cli_shutdown(cli, t_idx);
+#endif
+
+/****************************************************************************
+experimental nt login.
+****************************************************************************/
+void do_nt_session_close(struct cli_state *cli, int t_idx, uint16 fnum)
+{
+ /******************** close the \PIPE\NETLOGON file **************/
+ if (fnum != 0xffff)
+ {
+ cli_close(cli, t_idx, fnum, 0);
+ }
+
+}
+
+
diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
new file mode 100644
index 0000000000..6570903e79
--- /dev/null
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -0,0 +1,255 @@
+
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-1997,
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
+ * Copyright (C) Paul Ashton 1997.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+
+/****************************************************************************
+do a LSA Open Policy
+****************************************************************************/
+BOOL do_lsa_open_policy(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name, POLICY_HND *hnd)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ LSA_Q_OPEN_POL q_o;
+ BOOL valid_pol = False;
+
+ if (hnd == NULL) return False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api LSA_OPENPOLICY */
+
+ DEBUG(4,("LSA Open Policy\n"));
+
+ /* store the parameters */
+ make_q_open_pol(&q_o, server_name, 0, 0, 0x1);
+
+ /* turn parameters into data stream */
+ lsa_io_q_open_pol("", &q_o, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_OPENPOLICY, &buf, &rbuf))
+ {
+ LSA_R_OPEN_POL r_o;
+ BOOL p;
+
+ lsa_io_r_open_pol("", &r_o, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("LSA_OPENPOLICY: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. return the policy handle */
+ memcpy(hnd, r_o.pol.data, sizeof(hnd->data));
+ valid_pol = True;
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ return valid_pol;
+}
+
+/****************************************************************************
+do a LSA Query Info Policy
+****************************************************************************/
+BOOL do_lsa_query_info_pol(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *hnd, uint16 info_class,
+ fstring domain_name, fstring domain_sid)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ LSA_Q_QUERY_INFO q_q;
+ BOOL valid_response = False;
+
+ if (hnd == NULL || domain_name == NULL || domain_sid == NULL) return False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api LSA_QUERYINFOPOLICY */
+
+ DEBUG(4,("LSA Query Info Policy\n"));
+
+ /* store the parameters */
+ make_q_query(&q_q, hnd, info_class);
+
+ /* turn parameters into data stream */
+ lsa_io_q_query("", &q_q, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_QUERYINFOPOLICY, &buf, &rbuf))
+ {
+ LSA_R_QUERY_INFO r_q;
+ BOOL p;
+
+ lsa_io_r_query("", &r_q, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_q.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("LSA_QUERYINFOPOLICY: %s\n", get_nt_error_msg(r_q.status)));
+ p = False;
+ }
+
+ if (p && r_q.info_class != q_q.info_class)
+ {
+ /* report different info classes */
+ DEBUG(0,("LSA_QUERYINFOPOLICY: error info_class (q,r) differ - (%x,%x)\n",
+ q_q.info_class, r_q.info_class));
+ p = False;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. */
+ switch (r_q.info_class)
+ {
+ case 3:
+ {
+ char *dom_name = unistrn2(r_q.dom.id3.uni_domain_name.buffer,
+ r_q.dom.id3.uni_domain_name.uni_str_len);
+ char *dom_sid = dom_sid_to_string(&(r_q.dom.id3.dom_sid.sid));
+ fstrcpy(domain_name, dom_name);
+ pstrcpy(domain_sid , dom_sid);
+
+ valid_response = True;
+ break;
+ }
+ case 5:
+ {
+ char *dom_name = unistrn2(r_q.dom.id5.uni_domain_name.buffer,
+ r_q.dom.id5.uni_domain_name.uni_str_len);
+ char *dom_sid = dom_sid_to_string(&(r_q.dom.id5.dom_sid.sid));
+ fstrcpy(domain_name, dom_name);
+ pstrcpy(domain_sid , dom_sid);
+
+ valid_response = True;
+ break;
+ }
+ default:
+ {
+ DEBUG(3,("LSA_QUERYINFOPOLICY: unknown info class\n"));
+ domain_name[0] = 0;
+ domain_sid [0] = 0;
+
+ break;
+ }
+ }
+ DEBUG(3,("LSA_QUERYINFOPOLICY (level %x): domain:%s domain sid:%s\n",
+ r_q.info_class, domain_name, domain_sid));
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ return valid_response;
+}
+
+/****************************************************************************
+do a LSA Close
+****************************************************************************/
+BOOL do_lsa_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ LSA_Q_CLOSE q_c;
+ BOOL valid_close = False;
+
+ if (hnd == NULL) return False;
+
+ /* create and send a MSRPC command with api LSA_OPENPOLICY */
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("LSA Close\n"));
+
+ /* store the parameters */
+ make_lsa_q_close(&q_c, hnd);
+
+ /* turn parameters into data stream */
+ lsa_io_q_close("", &q_c, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_CLOSE, &buf, &rbuf))
+ {
+ LSA_R_CLOSE r_c;
+ BOOL p;
+
+ lsa_io_r_close("", &r_c, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_c.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("LSA_CLOSE: %s\n", get_nt_error_msg(r_c.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ /* check that the returned policy handle is all zeros */
+ int i;
+ valid_close = True;
+
+ for (i = 0; i < sizeof(r_c.pol.data); i++)
+ {
+ if (r_c.pol.data[i] != 0)
+ {
+ valid_close = False;
+ break;
+ }
+ }
+ if (!valid_close)
+ {
+ DEBUG(0,("LSA_CLOSE: non-zero handle returned\n"));
+ }
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ return valid_close;
+}
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
new file mode 100644
index 0000000000..aafde8d775
--- /dev/null
+++ b/source3/rpc_client/cli_netlogon.c
@@ -0,0 +1,461 @@
+
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-1997,
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
+ * Copyright (C) Paul Ashton 1997.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+extern pstring username;
+extern pstring workgroup;
+
+#define CLIENT_TIMEOUT (30*1000)
+
+
+/****************************************************************************
+do a LSA Logon Control2
+****************************************************************************/
+BOOL do_net_logon_ctrl2(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *host_name, uint32 status_level)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ NET_Q_LOGON_CTRL2 q_l;
+ BOOL valid_ctrl2 = False;
+ fstring acct_name;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
+
+ if (host_name == NULL) return False;
+
+ strcpy(acct_name, "\\\\");
+ strcat(acct_name, host_name);
+
+ /* create and send a MSRPC command with api NET_LOGON_CTRL2 */
+
+ DEBUG(4,("LSA Logon Control2 from %s status level:%x\n",
+ host_name, status_level));
+
+ /* store the parameters */
+ make_q_logon_ctrl2(&q_l, acct_name, status_level);
+
+ /* turn parameters into data stream */
+ net_io_q_logon_ctrl2("", &q_l, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, NET_LOGON_CTRL2, &buf, &rbuf))
+ {
+ NET_R_LOGON_CTRL2 r_l;
+ BOOL p;
+
+ net_io_r_logon_ctrl2("", &r_l, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_l.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("NET_R_LOGON_CTRL: %s\n", get_nt_error_msg(r_l.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ valid_ctrl2 = True;
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+
+ return valid_ctrl2;
+}
+
+/****************************************************************************
+do a LSA Authenticate 2
+****************************************************************************/
+BOOL do_net_auth2(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name,
+ DOM_CHAL *clnt_chal, uint32 neg_flags, DOM_CHAL *srv_chal)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ NET_Q_AUTH_2 q_a;
+ BOOL valid_chal = False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
+
+ if (srv_chal == NULL || clnt_chal == NULL) return False;
+
+ /* create and send a MSRPC command with api NET_AUTH2 */
+
+ DEBUG(4,("LSA Authenticate 2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %lx\n",
+ logon_srv, acct_name, sec_chan, comp_name,
+ credstr(clnt_chal->data), neg_flags));
+
+ /* store the parameters */
+ make_q_auth_2(&q_a, logon_srv, acct_name, sec_chan, comp_name,
+ clnt_chal, neg_flags);
+
+ /* turn parameters into data stream */
+ net_io_q_auth_2("", &q_a, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, NET_AUTH2, &buf, &rbuf))
+ {
+ NET_R_AUTH_2 r_a;
+ BOOL p;
+
+ net_io_r_auth_2("", &r_a, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_a.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("NET_AUTH2: %s\n", get_nt_error_msg(r_a.status)));
+ p = False;
+ }
+
+ if (p && r_a.srv_flgs.neg_flags != q_a.clnt_flgs.neg_flags)
+ {
+ /* report different neg_flags */
+ DEBUG(0,("NET_AUTH2: error neg_flags (q,r) differ - (%lx,%lx)\n",
+ q_a.clnt_flgs.neg_flags, r_a.srv_flgs.neg_flags));
+ p = False;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. return the challenge */
+ memcpy(srv_chal, r_a.srv_chal.data, sizeof(srv_chal->data));
+ valid_chal = True;
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+
+ return valid_chal;
+}
+
+/****************************************************************************
+do a LSA Request Challenge
+****************************************************************************/
+BOOL do_net_req_chal(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *desthost, char *myhostname,
+ DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ NET_Q_REQ_CHAL q_c;
+ BOOL valid_chal = False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
+
+ if (srv_chal == NULL || clnt_chal == NULL) return False;
+
+ /* create and send a MSRPC command with api NET_REQCHAL */
+
+ DEBUG(4,("LSA Request Challenge from %s to %s: %s\n",
+ desthost, myhostname, credstr(clnt_chal->data)));
+
+ /* store the parameters */
+ make_q_req_chal(&q_c, desthost, myhostname, clnt_chal);
+
+ /* turn parameters into data stream */
+ net_io_q_req_chal("", &q_c, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, NET_REQCHAL, &buf, &rbuf))
+ {
+ NET_R_REQ_CHAL r_c;
+ BOOL p;
+
+ net_io_r_req_chal("", &r_c, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_c.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("NET_REQ_CHAL: %s\n", get_nt_error_msg(r_c.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. return the challenge */
+ memcpy(srv_chal, r_c.srv_chal.data, sizeof(srv_chal->data));
+ valid_chal = True;
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+
+ return valid_chal;
+}
+
+/***************************************************************************
+do a LSA Server Password Set
+****************************************************************************/
+BOOL do_net_srv_pwset(struct cli_state *cli, int t_idx, uint16 fnum,
+ uchar sess_key[16], DOM_CRED *sto_clnt_cred,
+ char *logon_srv, char *mach_acct, uint16 sec_chan_type, char *comp_name,
+ DOM_CRED *clnt_cred, DOM_CRED *srv_cred,
+ uint8 nt_owf_new_mach_pwd[16])
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ NET_Q_SRV_PWSET q_s;
+ BOOL valid_cred = False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
+
+ if (srv_cred == NULL || clnt_cred == NULL) return False;
+
+ /* create and send a MSRPC command with api NET_SRV_PWSET */
+
+ DEBUG(4,("LSA Server Password Set: srv:%s acct:%s sc: %d mc: %s clnt %s %lx\n",
+ logon_srv, mach_acct, sec_chan_type, comp_name,
+ credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time));
+
+ /* store the parameters */
+ make_q_srv_pwset(&q_s,
+ sess_key,
+ logon_srv, mach_acct, sec_chan_type, comp_name,
+ clnt_cred,
+ nt_owf_new_mach_pwd);
+
+ /* turn parameters into data stream */
+ net_io_q_srv_pwset("", &q_s, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SRVPWSET, &buf, &rbuf))
+ {
+ NET_R_SRV_PWSET r_s;
+ BOOL p;
+
+ net_io_r_srv_pwset("", &r_s, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_s.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("NET_R_SRV_PWSET: %s\n", get_nt_error_msg(r_s.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_cred)))
+ {
+ DEBUG(5, ("do_net_srv_pwset: server credential check OK\n"));
+ /* ok, at last: we're happy. return the challenge */
+ memcpy(srv_cred, &(r_s.srv_cred), sizeof(r_s.srv_cred));
+ valid_cred = True;
+ }
+ else
+ {
+ DEBUG(5, ("do_net_srv_pwset: server credential check failed\n"));
+ }
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+
+ return valid_cred;
+}
+
+/***************************************************************************
+do a LSA SAM Logon
+****************************************************************************/
+BOOL do_net_sam_logon(struct cli_state *cli, int t_idx, uint16 fnum,
+ uchar sess_key[8], DOM_CRED *sto_clnt_cred,
+ char *logon_srv, char *comp_name,
+ DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
+ uint16 logon_level, NET_ID_INFO_CTR *ctr, uint16 validation_level,
+ NET_USER_INFO_3 *user_info3,
+ DOM_CRED *srv_cred)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ NET_Q_SAM_LOGON q_s;
+ BOOL valid_cred = False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
+
+ if (srv_cred == NULL || clnt_cred == NULL || rtn_cred == NULL || user_info3 == NULL) return False;
+
+ /* create and send a MSRPC command with api NET_SAMLOGON */
+
+ DEBUG(4,("LSA SAM Logon: srv:%s mc:%s clnt %s %lx rtn: %s %lx ll: %d\n",
+ logon_srv, comp_name,
+ credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time,
+ credstr(rtn_cred->challenge.data), rtn_cred ->timestamp.time,
+ logon_level));
+
+ /* store the parameters */
+ make_sam_info(&(q_s.sam_id), logon_srv, comp_name,
+ clnt_cred, rtn_cred,
+ logon_level, ctr, validation_level);
+
+ /* turn parameters into data stream */
+ net_io_q_sam_logon("", &q_s, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SAMLOGON, &buf, &rbuf))
+ {
+ NET_R_SAM_LOGON r_s;
+ BOOL p;
+
+ r_s.user = user_info3;
+
+ net_io_r_sam_logon("", &r_s, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_s.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("NET_SAMLOGON: %s\n", get_nt_error_msg(r_s.status)));
+ p = False;
+ }
+
+ if (p && r_s.switch_value != 3)
+ {
+ /* report different switch_value */
+ DEBUG(0,("NET_SAMLOGON: switch_value of 3 expected %x\n",
+ r_s.switch_value));
+ p = False;
+ }
+
+ if (p)
+ {
+ if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_creds)))
+ {
+ DEBUG(5, ("do_net_sam_logon: server credential check OK\n"));
+ /* ok, at last: we're happy. return the challenge */
+ memcpy(srv_cred, &(r_s.srv_creds), sizeof(r_s.srv_creds));
+ valid_cred = True;
+ }
+ else
+ {
+ DEBUG(5, ("do_net_sam_logon: server credential check failed\n"));
+ }
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ return valid_cred;
+}
+
+/***************************************************************************
+do a LSA SAM Logoff
+****************************************************************************/
+BOOL do_net_sam_logoff(struct cli_state *cli, int t_idx, uint16 fnum,
+ uchar sess_key[8], DOM_CRED *sto_clnt_cred,
+ char *logon_srv, char *comp_name,
+ DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
+ uint16 logon_level, NET_ID_INFO_CTR *ctr, uint16 validation_level,
+ DOM_CRED *srv_cred)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ NET_Q_SAM_LOGOFF q_s;
+ BOOL valid_cred = False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
+
+ if (srv_cred == NULL || clnt_cred == NULL || rtn_cred == NULL) return False;
+
+ /* create and send a MSRPC command with api NET_SAMLOGON */
+
+ DEBUG(4,("LSA SAM Logoff: srv:%s mc:%s clnt %s %lx rtn: %s %lx ll: %d\n",
+ logon_srv, comp_name,
+ credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time,
+ credstr(rtn_cred->challenge.data), rtn_cred ->timestamp.time,
+ logon_level));
+
+ /* store the parameters */
+ make_sam_info(&(q_s.sam_id), logon_srv, comp_name,
+ clnt_cred, rtn_cred,
+ logon_level, ctr, validation_level);
+
+ /* turn parameters into data stream */
+ net_io_q_sam_logoff("", &q_s, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SAMLOGOFF, &buf, &rbuf))
+ {
+ NET_R_SAM_LOGOFF r_s;
+ BOOL p;
+
+ net_io_r_sam_logoff("", &r_s, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_s.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("NET_SAMLOGOFF: %s\n", get_nt_error_msg(r_s.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_creds)))
+ {
+ DEBUG(5, ("do_net_sam_logoff: server credential check OK\n"));
+ /* ok, at last: we're happy. return the challenge */
+ memcpy(srv_cred, &(r_s.srv_creds), sizeof(r_s.srv_creds));
+ valid_cred = True;
+ }
+ else
+ {
+ DEBUG(5, ("do_net_sam_logoff: server credential check failed\n"));
+ }
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+
+ return valid_cred;
+}
+
+
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
new file mode 100644
index 0000000000..625b774167
--- /dev/null
+++ b/source3/rpc_client/cli_pipe.c
@@ -0,0 +1,683 @@
+
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-1998,
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
+ * Copyright (C) Paul Ashton 1998.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+
+extern struct pipe_id_info pipe_names[];
+
+/********************************************************************
+ rpc pipe call id
+ ********************************************************************/
+uint32 get_rpc_call_id(void)
+{
+ static uint32 call_id = 1;
+ return ++call_id;
+}
+
+/*******************************************************************
+ uses SMBreadX to get rest of rpc data
+ ********************************************************************/
+static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum,
+ prs_struct *rdata, uint32 data_to_read)
+{
+ uint32 data_offset = rdata->data->data_used;
+ int size = 512;
+ int num_read;
+ char *data = rdata->data->data;
+ uint32 err;
+ data += rdata->data->data_used;
+
+ if (data_offset + data_to_read > rdata->data->data_size)
+ {
+ mem_grow_data(&rdata->data, True, rdata->data->data_used + data_to_read);
+ DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
+ }
+
+ do /* read data using SMBreadX */
+ {
+ if (size > data_to_read) size = data_to_read;
+
+ if (data_offset + size > rdata->data->data_size)
+ {
+ mem_grow_data(&rdata->data, True, rdata->data->data_used + size);
+ DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
+ }
+
+ num_read = cli_readx(cli, t_idx, fnum, data, data_offset, size);
+
+ DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n",
+ data_offset, num_read, data_to_read));
+
+ data_to_read -= num_read;
+ data_offset += num_read;
+ data += num_read;
+
+ if (cli_error(cli, NULL, &err)) return False;
+
+ } while (num_read > 0 && data_to_read > 0); /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
+
+ mem_realloc_data(rdata->data, rdata->data->data_used);
+ rdata->data->offset.end = rdata->data->data_used;
+
+ DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read));
+
+ return data_to_read == 0;
+}
+
+/****************************************************************************
+ checks the header
+ ****************************************************************************/
+static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type,
+ BOOL *first, BOOL *last, uint32 *len)
+{
+ RPC_HDR rhdr;
+
+ smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0);
+
+ if (!rdata->offset || rdata->offset != 0x10)
+ {
+ DEBUG(5,("cli_pipe: error in rpc header\n"));
+ return False;
+ }
+
+ (*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
+ (*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
+ (*len ) = rhdr.frag_len - rdata->data->data_used;
+ (*pkt_type) = rhdr.pkt_type;
+
+ return True;
+}
+
+/****************************************************************************
+ send data on an rpc pipe, which *must* be in one fragment.
+ receive response data from an rpc pipe, which may be large...
+
+ read the first fragment: unfortunately have to use SMBtrans for the first
+ bit, then SMBreadX for subsequent bits.
+
+ if first fragment received also wasn't the last fragment, continue
+ getting fragments until we _do_ receive the last fragment.
+
+ [note: from a data abstraction viewpoint, this function is marginally
+ complicated by the return side of cli_api_pipe getting in the way
+ (i.e, the SMB header stuff). the proper way to do this is to split
+ cli_api_pipe down into receive / transmit. oh, and split cli_readx
+ down. in other words, state-based (kernel) techniques...]
+
+ ****************************************************************************/
+BOOL rpc_api_pipe(struct cli_state *cli, int t_idx,
+ uint16 cmd, uint16 fnum,
+ prs_struct *param , prs_struct *data,
+ prs_struct *rparam, prs_struct *rdata)
+{
+ uint32 len;
+
+ uint16 setup[2]; /* only need 2 uint16 setup parameters */
+ uint32 err;
+ uint8 pkt_type = 0xff;
+ BOOL first = True;
+ BOOL last = True;
+
+ /* prepare return data and params */
+
+ /* create setup parameters. */
+ setup[0] = cmd;
+ setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
+
+ /* send the data: receive a response. */
+ if (!cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8,
+
+ param != NULL ? param->data->data_used : 0,
+ data != NULL ? data ->data->data_used : 0,
+ 2,
+
+ 0,
+ data != NULL ? 1024 : 0 ,
+
+ param != NULL ? param->data->data : NULL,
+ data != NULL ? data ->data->data : NULL,
+ setup,
+
+ rparam != NULL ? rparam->data : NULL,
+ rdata != NULL ? rdata ->data : NULL))
+ {
+ DEBUG(5, ("cli_pipe: return critical error\n"));
+ return False;
+ }
+
+ if (cli_error(cli, NULL, &err)) return False;
+
+ if (rdata->data->data == NULL) return False;
+
+ /**** parse the header: check it's a response record */
+
+ rdata->data->offset.start = 0;
+ rdata->data->offset.end = rdata->data->data_used;
+ rdata->offset = 0;
+
+ if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len)) return False;
+
+ if (pkt_type == RPC_RESPONSE)
+ {
+ RPC_HDR_RR rhdr_rr;
+ smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, rdata, 0);
+ }
+
+ if (first && last)
+ {
+ DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
+ return True;
+ }
+
+ /* check if data to be sent back was too large for one SMB. */
+ /* err status is only informational: the _real_ check is on the length */
+ if (len < rdata->data->data_used) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */
+ {
+ if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False;
+ }
+
+ /* only one rpc fragment, and it has been read */
+ if (first && last) return True;
+
+ while (!last) /* read more fragments until we get the last one */
+ {
+ RPC_HDR rhdr;
+ RPC_HDR_RR rhdr_rr;
+ int num_read;
+ prs_struct hps;
+
+ prs_init(&hps, 0x18, 4, 0, True);
+
+ num_read = cli_readx(cli, t_idx, fnum, hps.data->data, 0, 0x18);
+ DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));
+
+ if (num_read != 0x18) return False;
+
+ smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0);
+ smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, &hps, 0);
+
+ prs_mem_free(&hps);
+
+ if (cli_error(cli, NULL, &err)) return False;
+
+ first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
+ last = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
+
+ if (first)
+ {
+ DEBUG(4,("rpc_api_pipe: wierd rpc header received\n"));
+ return False;
+ }
+
+ len = rhdr.frag_len - hps.offset;
+ if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
+ creates a DCE/RPC bind request
+
+ - initialises the parse structure.
+ - dynamically allocates the header data structure
+ - caller is expected to free the header data structure once used.
+
+ ********************************************************************/
+static BOOL create_rpc_bind_req(prs_struct *rhdr,
+ prs_struct *rhdr_rb,
+ prs_struct *auth_req,
+ RPC_IFACE *abstract, RPC_IFACE *transfer,
+ char *my_name, char *domain)
+{
+ RPC_HDR_RB hdr_rb;
+ RPC_HDR hdr;
+ RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
+
+ /* create the bind request RPC_HDR_RB */
+ make_rpc_hdr_rb(&hdr_rb,
+ 0x1630, 0x1630, 0x0,
+ 0x1, 0x0, 0x1,
+ abstract, transfer);
+
+ /* stream the bind request data */
+ smb_io_rpc_hdr_rb("", &hdr_rb, rhdr_rb, 0);
+ mem_realloc_data(rhdr_rb->data, rhdr_rb->offset);
+
+ if (auth_req != NULL)
+ {
+ make_rpc_auth_ntlmssp_req(&ntlmssp_req,
+ "NTLMSSP", 0x1,
+ 0x0000b2b3,
+ my_name, domain);
+ smb_io_rpc_auth_ntlmssp_req("", &ntlmssp_req, auth_req, 0);
+ mem_realloc_data(auth_req->data, auth_req->offset);
+ }
+
+ /* create the request RPC_HDR */
+ make_rpc_hdr(&hdr, RPC_BIND, 0x0, get_rpc_call_id(),
+ rhdr_rb->offset,
+ auth_req != NULL ? auth_req->offset : 0);
+
+ smb_io_rpc_hdr("hdr" , &hdr , rhdr, 0);
+ mem_realloc_data(rhdr->data, rhdr->offset);
+
+ if (rhdr->data == NULL || rhdr_rb->data == NULL) return False;
+
+ /***/
+ /*** link rpc header, bind acknowledgment and authentication responses ***/
+ /***/
+
+ rhdr->data->offset.start = 0;
+ rhdr->data->offset.end = rhdr->offset;
+ rhdr->data->next = rhdr_rb->data;
+
+ if (auth_req != NULL)
+ {
+ rhdr_rb->data->offset.start = rhdr->offset;
+ rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
+ rhdr_rb->data->next = auth_req->data;
+
+ auth_req->data->offset.start = rhdr->offset + rhdr_rb->offset;
+ auth_req->data->offset.end = rhdr->offset + auth_req->offset + rhdr_rb->offset;
+ auth_req->data->next = NULL;
+ }
+ else
+ {
+ rhdr_rb->data->offset.start = rhdr->offset;
+ rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
+ rhdr_rb->data->next = NULL;
+ }
+
+ return True;
+}
+
+
+/*******************************************************************
+ creates a DCE/RPC bind request
+
+ - initialises the parse structure.
+ - dynamically allocates the header data structure
+ - caller is expected to free the header data structure once used.
+
+ ********************************************************************/
+static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len)
+{
+ RPC_HDR_RR hdr_rr;
+ RPC_HDR hdr;
+
+ DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n",
+ op_num, data_len));
+
+ /* create the rpc header RPC_HDR */
+ make_rpc_hdr (&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST,
+ get_rpc_call_id(), data_len + 0x18, 0);
+
+ /* create the rpc request RPC_HDR_RR */
+ make_rpc_hdr_rr(&hdr_rr, data_len, op_num);
+
+ /* stream-time... */
+ smb_io_rpc_hdr ("hdr" , &hdr , rhdr, 0);
+ smb_io_rpc_hdr_rr("hdr_rr", &hdr_rr, rhdr, 0);
+
+ if (rhdr->data == NULL || rhdr->offset != 0x18) return False;
+
+ rhdr->data->offset.start = 0;
+ rhdr->data->offset.end = rhdr->offset;
+
+ return True;
+}
+
+
+/****************************************************************************
+ send a request on an rpc pipe.
+ ****************************************************************************/
+BOOL rpc_api_pipe_req(struct cli_state *cli, int t_idx, uint16 fnum,
+ uint8 op_num,
+ prs_struct *data, prs_struct *rdata)
+{
+ /* fudge this, at the moment: create the header; memcpy the data. oops. */
+ prs_struct rparam;
+ prs_struct hdr;
+ int data_len;
+ BOOL ret;
+
+ data_len = data->offset + 0x18;
+ data->data->offset.end = data->offset;
+
+ prs_init(&hdr , data_len, 4, SAFETY_MARGIN, False);
+ prs_init(&rparam, 0 , 4, 0 , True );
+
+ create_rpc_request(&hdr, op_num, data_len);
+
+ mem_realloc_data(hdr.data, data_len);
+ hdr.data->offset.end = data_len;
+ mem_buf_copy(mem_data(&(hdr.data), 0x18), data->data, 0, data->offset);
+
+ ret = rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &hdr, &rparam, rdata);
+
+ prs_mem_free(&rparam);
+ prs_mem_free(&hdr);
+
+ return ret;
+}
+
+
+/****************************************************************************
+do an rpc bind
+****************************************************************************/
+BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, int t_idx,
+ char *pipe_name, uint16 fnum, uint16 device_state)
+{
+ prs_struct param;
+ prs_struct rdata;
+ prs_struct rparam;
+ BOOL state_set = False;
+ uint16 setup[2]; /* only need 2 uint16 setup parameters */
+
+ if (pipe_name == NULL) return False;
+
+ prs_init(&param , 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(&param );
+ prs_mem_free(&rparam);
+ prs_mem_free(&rdata );
+
+ return state_set;
+}
+
+/****************************************************************************
+ check the rpc bind acknowledge response
+****************************************************************************/
+static BOOL valid_pipe_name(char *pipe_name,
+ RPC_IFACE *abstract, RPC_IFACE *transfer)
+{
+ int pipe_idx = 0;
+
+ while (pipe_names[pipe_idx].client_pipe != NULL)
+ {
+ if (strcmp(pipe_name, pipe_names[pipe_idx].client_pipe ) == 0)
+ {
+ DEBUG(5,("Bind Abstract Syntax: "));
+ dump_data(5, (uchar*)&(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax));
+ DEBUG(5,("Bind Transfer Syntax: "));
+ dump_data(5, (uchar*)&(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax));
+
+ /* copy the required syntaxes out so we can do the right bind */
+ memcpy(transfer, &(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax));
+ memcpy(abstract, &(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax));
+
+ return True;
+ }
+ pipe_idx++;
+ };
+
+ DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name));
+ return False;
+}
+
+/****************************************************************************
+ check the rpc bind acknowledge response
+****************************************************************************/
+static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer)
+{
+ int i = 0;
+
+ while ((pipe_names[i].client_pipe != NULL))
+ {
+ DEBUG(6,("bind_rpc_pipe: searching pipe name: client:%s server:%s\n",
+ pipe_names[i].client_pipe , pipe_names[i].server_pipe ));
+
+ if ((strcmp(pipe_name, pipe_names[i].client_pipe ) == 0))
+ {
+ if (strcmp(hdr_ba->addr.str, pipe_names[i].server_pipe ) == 0)
+ {
+ DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n",
+ pipe_names[i].server_pipe ));
+ break;
+ }
+ else
+ {
+ DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n",
+ pipe_names[i].server_pipe , hdr_ba->addr.str));
+ return False;
+ }
+ }
+ else
+ {
+ i++;
+ }
+ }
+
+ if (pipe_names[i].server_pipe == NULL)
+ {
+ DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
+ return False;
+ }
+
+ /* check the transfer syntax */
+ if (!((hdr_ba->transfer.version == transfer->version) &&
+ (memcmp(hdr_ba->transfer.data, transfer->data,
+ sizeof(transfer->version)) ==0)))
+ {
+ DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
+ return False;
+ }
+
+ /* lkclXXXX only accept one result: check the result(s) */
+ if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0)
+ {
+ DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
+ hdr_ba->res.num_results,
+ hdr_ba->res.reason));
+ }
+
+ DEBUG(5,("bind_rpc_pipe: accepted!\n"));
+ return True;
+}
+
+/****************************************************************************
+do an rpc bind
+****************************************************************************/
+BOOL rpc_pipe_bind(struct cli_state *cli, int t_idx, char *pipe_name, uint16 fnum,
+ RPC_IFACE *abstract, RPC_IFACE *transfer, BOOL ntlmssp_auth,
+ char *my_name, char *domain)
+{
+ prs_struct hdr;
+ prs_struct hdr_rb;
+ prs_struct auth_req;
+ prs_struct data;
+ prs_struct rdata;
+ prs_struct rparam;
+
+ BOOL valid_ack = False;
+
+ if (pipe_name == NULL || abstract == NULL || transfer == NULL) return False;
+
+ DEBUG(5,("Bind RPC Pipe[%x]: %s\n", fnum, pipe_name));
+
+ if (!valid_pipe_name(pipe_name, abstract, transfer)) return False;
+
+ prs_init(&hdr , 0x10 , 4, 0x0 , False);
+ prs_init(&hdr_rb , 1024 , 4, SAFETY_MARGIN, False);
+ prs_init(&auth_req, ntlmssp_auth ? 1024 : 0, 4, SAFETY_MARGIN, False);
+
+ prs_init(&rdata , 0 , 4, SAFETY_MARGIN, True );
+ prs_init(&rparam, 0 , 4, SAFETY_MARGIN, True );
+
+ create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL,
+ abstract, transfer,
+ my_name, domain);
+
+ /* this is a hack due to limitations in rpc_api_pipe */
+ prs_init(&data, mem_buf_len(hdr.data), 4, 0x0, False);
+ mem_buf_copy(data.data->data, hdr.data, 0, mem_buf_len(hdr.data));
+
+ /* send data on \PIPE\. receive a response */
+ if (rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &data, &rparam, &rdata))
+ {
+ RPC_HDR_BA hdr_ba;
+
+ DEBUG(5, ("rpc_api_pipe: return OK\n"));
+
+ smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0);
+
+ if (rdata.offset != 0) valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer);
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&hdr );
+ prs_mem_free(&hdr_rb );
+ prs_mem_free(&auth_req);
+ prs_mem_free(&rdata );
+ prs_mem_free(&rparam );
+
+ return valid_ack;
+}
+
+/****************************************************************************
+ open a session
+ ****************************************************************************/
+BOOL do_session_open(struct cli_state *cli, int t_idx,
+ char *pipe_name, uint16 *fnum)
+{
+ RPC_IFACE abstract;
+ RPC_IFACE transfer;
+
+
+ /******************* open the pipe *****************/
+ if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE,
+ NULL, NULL, NULL)) == 0xffff)
+ {
+ DEBUG(1,("do_session_open: cli_open failed\n"));
+ return False;
+ }
+
+ /**************** Set Named Pipe State ***************/
+ if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300))
+ {
+ DEBUG(1,("do_session_open: pipe hnd state failed\n"));
+ return False;
+ }
+
+ /******************* bind request on pipe *****************/
+ if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum),
+ &abstract, &transfer,
+ False, NULL, NULL))
+ {
+ DEBUG(1,("do_session_open: rpc bind failed\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+/****************************************************************************
+ open an encrypted session
+ ****************************************************************************/
+BOOL do_ntlm_session_open(struct cli_state *cli, int t_idx,
+ char *pipe_name, uint16 *fnum,
+ char *my_name, char *domain)
+{
+ RPC_IFACE abstract;
+ RPC_IFACE transfer;
+
+ /******************* open the pipe *****************/
+ if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE,
+ NULL, NULL, NULL)) == 0xffff)
+ {
+ DEBUG(1,("do_ntlm_session_open: cli_open failed\n"));
+ return False;
+ }
+
+ /**************** Set Named Pipe State ***************/
+ if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300))
+ {
+ DEBUG(1,("do_ntlm_session_open: pipe hnd state failed\n"));
+ return False;
+ }
+
+ /******************* bind request on pipe *****************/
+ if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum),
+ &abstract, &transfer,
+ True, my_name, domain))
+ {
+ DEBUG(1,("do_ntlm_session_open: rpc bind failed\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
+/****************************************************************************
+close the session
+****************************************************************************/
+void do_session_close(struct cli_state *cli, int t_idx, uint16 fnum)
+{
+ if (fnum != 0xffff)
+ {
+ cli_close(cli, t_idx, fnum, 0);
+ }
+}
+
diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c
new file mode 100644
index 0000000000..7a04d8ec35
--- /dev/null
+++ b/source3/rpc_client/cli_samr.c
@@ -0,0 +1,695 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NT Domain Authentication SMB / MSRPC client
+ Copyright (C) Andrew Tridgell 1994-1997
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+
+
+/****************************************************************************
+do a SAMR query user groups
+****************************************************************************/
+BOOL get_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol_open_domain, uint32 user_rid,
+ uint32 *num_groups, DOM_GID *gid)
+{
+ POLICY_HND pol_open_user;
+ if (pol_open_domain == NULL || num_groups == NULL || gid == NULL) return False;
+
+ /* send open domain (on user sid) */
+ if (!do_samr_open_user(cli, t_idx, fnum,
+ pol_open_domain,
+ 0x02011b, user_rid,
+ &pol_open_user))
+ {
+ return False;
+ }
+
+ /* send user groups query */
+ if (!do_samr_query_usergroups(cli, t_idx, fnum,
+ &pol_open_user,
+ num_groups, gid))
+ {
+ DEBUG(5,("do_samr_query_usergroups: error in query user groups\n"));
+ }
+
+ return do_samr_close(cli, t_idx, fnum, &pol_open_user);
+}
+
+/****************************************************************************
+do a SAMR query user info
+****************************************************************************/
+BOOL get_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol_open_domain,
+ uint32 info_level,
+ uint32 user_rid, SAM_USER_INFO_21 *usr)
+{
+ POLICY_HND pol_open_user;
+ if (pol_open_domain == NULL || usr == NULL) return False;
+
+ bzero(usr, sizeof(*usr));
+
+ /* send open domain (on user sid) */
+ if (!do_samr_open_user(cli, t_idx, fnum,
+ pol_open_domain,
+ 0x02011b, user_rid,
+ &pol_open_user))
+ {
+ return False;
+ }
+
+ /* send user info query */
+ if (!do_samr_query_userinfo(cli, t_idx, fnum,
+ &pol_open_user,
+ info_level, (void*)usr))
+ {
+ DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n",
+ info_level));
+ }
+
+ return do_samr_close(cli, t_idx, fnum, &pol_open_user);
+}
+
+/****************************************************************************
+do a SAMR unknown 0x8 command
+****************************************************************************/
+BOOL do_samr_unknown_8(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *domain_pol, uint16 switch_value)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_UNKNOWN_8 q_e;
+ BOOL valid_un8 = False;
+
+ /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value));
+
+ if (domain_pol == NULL || fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_unknown_8(&q_e, domain_pol, switch_value);
+
+ /* turn parameters into data stream */
+ samr_io_q_unknown_8("", &q_e, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_8, &data, &rdata))
+ {
+#if 0
+
+ SAMR_R_UNKNOWN_8 r_e;
+ BOOL p;
+
+ samr_io_r_unknown_8("", &r_e, &rdata, 0);
+
+ p = rdata.offset != 0;
+ if (p && r_e.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_UNKNOWN_8: %s\n", get_nt_error_msg(r_e.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ valid_un8 = True;
+ }
+#endif
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_un8;
+}
+
+/****************************************************************************
+do a SAMR enumerate users
+****************************************************************************/
+BOOL do_samr_enum_dom_users(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
+ uint16 acb_mask, uint16 unk_1, uint32 size,
+ struct acct_info sam[MAX_SAM_ENTRIES],
+ int *num_sam_users)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_ENUM_DOM_USERS q_e;
+ BOOL valid_pol = False;
+
+ /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
+
+ if (pol == NULL || sam == NULL || num_sam_users == NULL || fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_enum_dom_users(&q_e, pol,
+ num_entries, unk_0,
+ acb_mask, unk_1, size);
+
+ /* turn parameters into data stream */
+ samr_io_q_enum_dom_users("", &q_e, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_ENUM_DOM_USERS, &data, &rdata))
+ {
+ SAMR_R_ENUM_DOM_USERS r_e;
+ BOOL p;
+
+ samr_io_r_enum_dom_users("", &r_e, &rdata, 0);
+
+ p = rdata.offset != 0;
+ if (p && r_e.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ int i;
+ int name_idx = 0;
+
+ *num_sam_users = r_e.num_entries2;
+ if (*num_sam_users > MAX_SAM_ENTRIES)
+ {
+ *num_sam_users = MAX_SAM_ENTRIES;
+ DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n",
+ *num_sam_users));
+ }
+ for (i = 0; i < *num_sam_users; i++)
+ {
+ sam[i].smb_userid = r_e.sam[i].rid;
+ if (r_e.sam[i].hdr_name.buffer)
+ {
+ char *acct_name = unistrn2(r_e.uni_acct_name[name_idx].buffer,
+ r_e.uni_acct_name[name_idx].uni_str_len);
+ fstrcpy(sam[i].acct_name, acct_name);
+ name_idx++;
+ }
+ else
+ {
+ bzero(sam[i].acct_name, sizeof(sam[i].acct_name));
+ }
+ DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n",
+ i, sam[i].smb_userid, sam[i].acct_name));
+ }
+ valid_pol = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Connect
+****************************************************************************/
+BOOL do_samr_connect(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *srv_name, uint32 unknown_0,
+ POLICY_HND *connect_pol)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_CONNECT q_o;
+ BOOL valid_pol = False;
+
+ /* create and send a MSRPC command with api SAMR_CONNECT */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n",
+ srv_name, unknown_0));
+
+ if (srv_name == NULL || connect_pol == NULL || fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_connect(&q_o, srv_name, unknown_0);
+
+ /* turn parameters into data stream */
+ samr_io_q_connect("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CONNECT, &data, &rdata))
+ {
+ SAMR_R_CONNECT r_o;
+ BOOL p;
+
+ samr_io_r_connect("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol));
+ valid_pol = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Open User
+****************************************************************************/
+BOOL do_samr_open_user(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol, uint32 unk_0, uint32 rid,
+ POLICY_HND *user_pol)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_OPEN_USER q_o;
+ BOOL valid_pol = False;
+
+ /* create and send a MSRPC command with api SAMR_OPEN_USER */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Open User. unk_0: %08x RID:%x\n",
+ unk_0, rid));
+
+ if (pol == NULL || user_pol == NULL || fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_open_user(&q_o, pol, unk_0, rid);
+
+ /* turn parameters into data stream */
+ samr_io_q_open_user("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_USER, &data, &rdata))
+ {
+ SAMR_R_OPEN_USER r_o;
+ BOOL p;
+
+ samr_io_r_open_user("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol));
+ valid_pol = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Open Domain
+****************************************************************************/
+BOOL do_samr_open_domain(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *connect_pol, uint32 rid, char *sid,
+ POLICY_HND *domain_pol)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_OPEN_DOMAIN q_o;
+ BOOL valid_pol = False;
+
+ /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Open Domain. SID:%s RID:%x\n", sid, rid));
+
+ if (connect_pol == NULL || sid == NULL || domain_pol == NULL || fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_open_domain(&q_o, connect_pol, rid, sid);
+
+ /* turn parameters into data stream */
+ samr_io_q_open_domain("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_DOMAIN, &data, &rdata))
+ {
+ SAMR_R_OPEN_DOMAIN r_o;
+ BOOL p;
+
+ samr_io_r_open_domain("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol));
+ valid_pol = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_pol;
+}
+
+/****************************************************************************
+do a SAMR Query Unknown 12
+****************************************************************************/
+BOOL do_samr_query_unknown_12(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
+ uint32 *num_aliases,
+ fstring als_names [MAX_LOOKUP_SIDS],
+ uint32 num_als_users[MAX_LOOKUP_SIDS])
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_UNKNOWN_12 q_o;
+ BOOL valid_query = False;
+
+ /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Query Unknown 12.\n"));
+
+ if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL ||
+ num_aliases == NULL || als_names == NULL || num_als_users == NULL ||
+ fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_unknown_12(&q_o, pol, rid, num_gids, gids);
+
+ /* turn parameters into data stream */
+ samr_io_q_unknown_12("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_12, &data, &rdata))
+ {
+ SAMR_R_UNKNOWN_12 r_o;
+ BOOL p;
+
+ samr_io_r_unknown_12("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 &&
+ r_o.num_als_usrs1 == r_o.num_aliases1)
+ {
+ int i;
+
+ valid_query = True;
+ *num_aliases = r_o.num_aliases1;
+
+ for (i = 0; i < r_o.num_aliases1; i++)
+ {
+ fstrcpy(als_names[i], unistrn2(r_o.uni_als_name[i].buffer, r_o.uni_als_name[i].uni_str_len));
+ }
+ for (i = 0; i < r_o.num_als_usrs1; i++)
+ {
+ num_als_users[i] = r_o.num_als_usrs[i];
+ }
+ }
+ else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0)
+ {
+ valid_query = True;
+ *num_aliases = 0;
+ }
+ else
+ {
+ p = False;
+ }
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_query;
+}
+
+/****************************************************************************
+do a SAMR Query User Groups
+****************************************************************************/
+BOOL do_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_QUERY_USERGROUPS q_o;
+ BOOL valid_query = False;
+
+ /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Query User Groups.\n"));
+
+ if (pol == NULL || gid == NULL || num_groups == 0|| fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_query_usergroups(&q_o, pol);
+
+ /* turn parameters into data stream */
+ samr_io_q_query_usergroups("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERGROUPS, &data, &rdata))
+ {
+ SAMR_R_QUERY_USERGROUPS r_o;
+ BOOL p;
+
+ /* get user info */
+ r_o.gid = gid;
+
+ samr_io_r_query_usergroups("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p && r_o.ptr_0 != 0)
+ {
+ valid_query = True;
+ *num_groups = r_o.num_entries;
+ }
+
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_query;
+}
+
+/****************************************************************************
+do a SAMR Query User Info
+****************************************************************************/
+BOOL do_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum,
+ POLICY_HND *pol, uint16 switch_value, void* usr)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_QUERY_USERINFO q_o;
+ BOOL valid_query = False;
+
+ /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ DEBUG(4,("SAMR Query User Info. level: %d\n", switch_value));
+
+ if (pol == NULL || usr == NULL || switch_value == 0|| fnum == 0xffff) return False;
+
+ /* store the parameters */
+ make_samr_q_query_userinfo(&q_o, pol, switch_value);
+
+ /* turn parameters into data stream */
+ samr_io_q_query_userinfo("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERINFO, &data, &rdata))
+ {
+ SAMR_R_QUERY_USERINFO r_o;
+ BOOL p;
+
+ /* get user info */
+ r_o.info.id = usr;
+
+ samr_io_r_query_userinfo("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p && r_o.switch_value != switch_value)
+ {
+ DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n",
+ r_o.switch_value));
+ }
+
+ if (p && r_o.ptr != 0)
+ {
+ valid_query = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_query;
+}
+
+/****************************************************************************
+do a SAMR Close
+****************************************************************************/
+BOOL do_samr_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd)
+{
+ prs_struct data;
+ prs_struct rdata;
+
+ SAMR_Q_CLOSE_HND q_c;
+ BOOL valid_close = False;
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ if (hnd == NULL) return False;
+
+ /* create and send a MSRPC command with api SAMR_CLOSE_HND */
+
+ DEBUG(4,("SAMR Close\n"));
+
+ /* store the parameters */
+ make_samr_q_close_hnd(&q_c, hnd);
+
+ /* turn parameters into data stream */
+ samr_io_q_close_hnd("", &q_c, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CLOSE_HND, &data, &rdata))
+ {
+ SAMR_R_CLOSE_HND r_c;
+ BOOL p;
+
+ samr_io_r_close_hnd("", &r_c, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_c.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ /* check that the returned policy handle is all zeros */
+ int i;
+ valid_close = True;
+
+ for (i = 0; i < sizeof(r_c.pol.data); i++)
+ {
+ if (r_c.pol.data[i] != 0)
+ {
+ valid_close = False;
+ break;
+ }
+ }
+ if (!valid_close)
+ {
+ DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n"));
+ }
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_close;
+}
+
diff --git a/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c
new file mode 100644
index 0000000000..dcedeb3a54
--- /dev/null
+++ b/source3/rpc_client/cli_srvsvc.c
@@ -0,0 +1,411 @@
+
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-1997,
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
+ * Copyright (C) Paul Ashton 1997.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+do a server net conn enum
+****************************************************************************/
+BOOL do_srv_net_srv_conn_enum(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name, char *qual_name,
+ uint32 switch_value, SRV_CONN_INFO_CTR *ctr,
+ uint32 preferred_len,
+ ENUM_HND *hnd)
+{
+ prs_struct data;
+ prs_struct rdata;
+ SRV_Q_NET_CONN_ENUM q_o;
+ BOOL valid_enum = False;
+
+ if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api SRV_NETCONNENUM */
+
+ DEBUG(4,("SRV Net Server Connection Enum(%s, %s), level %d, enum:%8x\n",
+ server_name, qual_name, switch_value, get_enum_hnd(hnd)));
+
+ ctr->switch_value = switch_value;
+ ctr->ptr_conn_ctr = 1;
+ ctr->conn.info0.num_entries_read = 0;
+ ctr->conn.info0.ptr_conn_info = 1;
+
+ /* store the parameters */
+ make_srv_q_net_conn_enum(&q_o, server_name, qual_name,
+ switch_value, ctr,
+ preferred_len,
+ hnd);
+
+ /* turn parameters into data stream */
+ srv_io_q_net_conn_enum("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETCONNENUM, &data, &rdata))
+ {
+ SRV_R_NET_CONN_ENUM r_o;
+ BOOL p;
+
+ r_o.ctr = ctr;
+
+ srv_io_r_net_conn_enum("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = 0;
+ }
+
+ if (p && r_o.ctr->switch_value != switch_value)
+ {
+ /* different switch levels. oops. */
+ DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: info class %d does not match request %d\n",
+ r_o.ctr->switch_value, switch_value));
+ p = 0;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. */
+ valid_enum = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_enum;
+}
+
+/****************************************************************************
+do a server net sess enum
+****************************************************************************/
+BOOL do_srv_net_srv_sess_enum(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name, char *qual_name,
+ uint32 switch_value, SRV_SESS_INFO_CTR *ctr,
+ uint32 preferred_len,
+ ENUM_HND *hnd)
+{
+ prs_struct data;
+ prs_struct rdata;
+ SRV_Q_NET_SESS_ENUM q_o;
+ BOOL valid_enum = False;
+
+ if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api SRV_NETSESSENUM */
+
+ DEBUG(4,("SRV Net Session Enum (%s), level %d, enum:%8x\n",
+ server_name, switch_value, get_enum_hnd(hnd)));
+
+ ctr->switch_value = switch_value;
+ ctr->ptr_sess_ctr = 1;
+ ctr->sess.info0.num_entries_read = 0;
+ ctr->sess.info0.ptr_sess_info = 1;
+
+ /* store the parameters */
+ make_srv_q_net_sess_enum(&q_o, server_name, qual_name,
+ switch_value, ctr,
+ preferred_len,
+ hnd);
+
+ /* turn parameters into data stream */
+ srv_io_q_net_sess_enum("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETSESSENUM, &data, &rdata))
+ {
+ SRV_R_NET_SESS_ENUM r_o;
+ BOOL p;
+
+ r_o.ctr = ctr;
+
+ srv_io_r_net_sess_enum("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = 0;
+ }
+
+ if (p && r_o.ctr->switch_value != switch_value)
+ {
+ /* different switch levels. oops. */
+ DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: info class %d does not match request %d\n",
+ r_o.ctr->switch_value, switch_value));
+ p = 0;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. */
+ valid_enum = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_enum;
+}
+
+/****************************************************************************
+do a server net share enum
+****************************************************************************/
+BOOL do_srv_net_srv_share_enum(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name,
+ uint32 switch_value, SRV_SHARE_INFO_CTR *ctr,
+ uint32 preferred_len,
+ ENUM_HND *hnd)
+{
+ prs_struct data;
+ prs_struct rdata;
+ SRV_Q_NET_SHARE_ENUM q_o;
+ BOOL valid_enum = False;
+
+ if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api SRV_NETSHAREENUM */
+
+ DEBUG(4,("SRV Get Share Info (%s), level %d, enum:%8x\n",
+ server_name, switch_value, get_enum_hnd(hnd)));
+
+ q_o.share_level = switch_value;
+
+ ctr->switch_value = switch_value;
+ ctr->ptr_share_ctr = 1;
+ ctr->share.info1.num_entries_read = 0;
+ ctr->share.info1.ptr_share_info = 1;
+
+ /* store the parameters */
+ make_srv_q_net_share_enum(&q_o, server_name,
+ switch_value, ctr,
+ preferred_len,
+ hnd);
+
+ /* turn parameters into data stream */
+ srv_io_q_net_share_enum("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETSHAREENUM, &data, &rdata))
+ {
+ SRV_R_NET_SHARE_ENUM r_o;
+ BOOL p;
+
+ r_o.ctr = ctr;
+
+ srv_io_r_net_share_enum("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = 0;
+ }
+
+ if (p && r_o.ctr->switch_value != switch_value)
+ {
+ /* different switch levels. oops. */
+ DEBUG(0,("SRV_R_NET_SRV_SHARE_ENUM: info class %d does not match request %d\n",
+ r_o.ctr->switch_value, switch_value));
+ p = 0;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. */
+ valid_enum = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_enum;
+}
+
+/****************************************************************************
+do a server net file enum
+****************************************************************************/
+BOOL do_srv_net_srv_file_enum(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name, char *qual_name,
+ uint32 switch_value, SRV_FILE_INFO_CTR *ctr,
+ uint32 preferred_len,
+ ENUM_HND *hnd)
+{
+ prs_struct data;
+ prs_struct rdata;
+ SRV_Q_NET_FILE_ENUM q_o;
+ BOOL valid_enum = False;
+
+ if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api SRV_NETFILEENUM */
+
+ DEBUG(4,("SRV Get File Info (%s), level %d, enum:%8x\n",
+ server_name, switch_value, get_enum_hnd(hnd)));
+
+ q_o.file_level = switch_value;
+
+ ctr->switch_value = switch_value;
+ ctr->ptr_file_ctr = 1;
+ ctr->file.info3.num_entries_read = 0;
+ ctr->file.info3.ptr_file_info = 1;
+
+ /* store the parameters */
+ make_srv_q_net_file_enum(&q_o, server_name, qual_name,
+ switch_value, ctr,
+ preferred_len,
+ hnd);
+
+ /* turn parameters into data stream */
+ srv_io_q_net_file_enum("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETFILEENUM, &data, &rdata))
+ {
+ SRV_R_NET_FILE_ENUM r_o;
+ BOOL p;
+
+ r_o.ctr = ctr;
+
+ srv_io_r_net_file_enum("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = 0;
+ }
+
+ if (p && r_o.ctr->switch_value != switch_value)
+ {
+ /* different switch levels. oops. */
+ DEBUG(0,("SRV_R_NET_SRV_FILE_ENUM: info class %d does not match request %d\n",
+ r_o.ctr->switch_value, switch_value));
+ p = 0;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. */
+ valid_enum = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_enum;
+}
+
+/****************************************************************************
+do a server get info
+****************************************************************************/
+BOOL do_srv_net_srv_get_info(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr)
+{
+ prs_struct data;
+ prs_struct rdata;
+ SRV_Q_NET_SRV_GET_INFO q_o;
+ BOOL valid_info = False;
+
+ if (server_name == NULL || switch_value == 0 || ctr == NULL) return False;
+
+ prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api SRV_NET_SRV_GET_INFO */
+
+ DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value));
+
+ /* store the parameters */
+ make_srv_q_net_srv_get_info(&q_o, server_name, switch_value);
+
+ /* turn parameters into data stream */
+ srv_io_q_net_srv_get_info("", &q_o, &data, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NET_SRV_GET_INFO, &data, &rdata))
+ {
+ SRV_R_NET_SRV_GET_INFO r_o;
+ BOOL p;
+
+ r_o.ctr = ctr;
+
+ srv_io_r_net_srv_get_info("", &r_o, &rdata, 0);
+ p = rdata.offset != 0;
+ p = rdata.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = 0;
+ }
+
+ if (p && r_o.ctr->switch_value != q_o.switch_value)
+ {
+ /* different switch levels. oops. */
+ DEBUG(0,("SRV_R_NET_SRV_GET_INFO: info class %d does not match request %d\n",
+ r_o.ctr->switch_value, q_o.switch_value));
+ p = 0;
+ }
+
+ if (p)
+ {
+ /* ok, at last: we're happy. */
+ valid_info = True;
+ }
+ }
+
+ prs_mem_free(&data );
+ prs_mem_free(&rdata );
+
+ return valid_info;
+}
+
diff --git a/source3/rpc_client/cli_wkssvc.c b/source3/rpc_client/cli_wkssvc.c
new file mode 100644
index 0000000000..f5a4c203e0
--- /dev/null
+++ b/source3/rpc_client/cli_wkssvc.c
@@ -0,0 +1,90 @@
+
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9.
+ * RPC Pipe client / server routines
+ * Copyright (C) Andrew Tridgell 1992-1997,
+ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
+ * Copyright (C) Paul Ashton 1997.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+/****************************************************************************
+do a WKS Open Policy
+****************************************************************************/
+BOOL do_wks_query_info(struct cli_state *cli, int t_idx, uint16 fnum,
+ char *server_name, uint32 switch_value,
+ WKS_INFO_100 *wks100)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ WKS_Q_QUERY_INFO q_o;
+ BOOL valid_info = False;
+
+ if (server_name == 0 || wks100 == NULL) return False;
+
+ prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
+ prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
+
+ /* create and send a MSRPC command with api WKS_QUERY_INFO */
+
+ DEBUG(4,("WKS Query Info\n"));
+
+ /* store the parameters */
+ make_wks_q_query_info(&q_o, server_name, switch_value);
+
+ /* turn parameters into data stream */
+ wks_io_q_query_info("", &q_o, &buf, 0);
+
+ /* send the data on \PIPE\ */
+ if (rpc_api_pipe_req(cli, t_idx, fnum, WKS_QUERY_INFO, &buf, &rbuf))
+ {
+ WKS_R_QUERY_INFO r_o;
+ BOOL p;
+
+ r_o.wks100 = wks100;
+
+ wks_io_r_query_info("", &r_o, &rbuf, 0);
+ p = rbuf.offset != 0;
+
+ if (p && r_o.status != 0)
+ {
+ /* report error code */
+ DEBUG(0,("WKS_R_QUERY_INFO: %s\n", get_nt_error_msg(r_o.status)));
+ p = False;
+ }
+
+ if (p)
+ {
+ valid_info = True;
+ }
+ }
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+
+ return valid_info;
+}
+
diff --git a/source3/rpc_client/ntclienttrust.c b/source3/rpc_client/ntclienttrust.c
new file mode 100644
index 0000000000..38cbedae78
--- /dev/null
+++ b/source3/rpc_client/ntclienttrust.c
@@ -0,0 +1,167 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NT Domain Authentication SMB / MSRPC client
+ Copyright (C) Andrew Tridgell 1994-1997
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifdef SYSLOG
+#undef SYSLOG
+#endif
+
+#include "includes.h"
+#include "nterr.h"
+
+extern int DEBUGLEVEL;
+
+
+/************************************************************************
+ check workstation trust account status
+ ************************************************************************/
+BOOL trust_account_check(struct in_addr dest_ip, char *dest_host,
+ char *myhostname, char *domain, fstring mach_acct,
+ fstring new_mach_pwd)
+{
+ pstring tmp;
+ fstring mach_pwd;
+ struct cli_state cli_trust;
+ uchar lm_owf_mach_pwd[16];
+ uchar nt_owf_mach_pwd[16];
+ uchar lm_sess_pwd[24];
+ uchar nt_sess_pwd[24];
+
+ BOOL right_error_code = False;
+ uint8 err_cls;
+ uint32 err_num;
+
+ char *start_mach_pwd;
+ char *change_mach_pwd;
+
+ /* initial machine password */
+ fstrcpy(mach_pwd, myhostname);
+ strlower(mach_pwd);
+
+ sprintf(tmp, "Enter Workstation Trust Account password for [%s].\nDefault is [%s].\nPassword:",
+ mach_acct, mach_pwd);
+
+ start_mach_pwd = (char*)getpass(tmp);
+
+ if (start_mach_pwd[0] != 0)
+ {
+ fstrcpy(mach_pwd, start_mach_pwd);
+ }
+
+ sprintf(tmp, "Enter new Workstation Trust Account password for [%s]\nPress Return to leave at old value.\nNew Password:",
+ mach_acct);
+
+ change_mach_pwd = (char*)getpass(tmp);
+
+ if (change_mach_pwd[0] != 0)
+ {
+ fstrcpy(new_mach_pwd, change_mach_pwd);
+ }
+ else
+ {
+ DEBUG(1,("trust_account_check: password change not requested\n"));
+ change_mach_pwd[0] = 0;
+ }
+
+ DEBUG(1,("initialise cli_trust connection\n"));
+
+ if (!cli_initialise(&cli_trust))
+ {
+ DEBUG(1,("cli_initialise failed for cli_trust\n"));
+ return False;
+ }
+
+ DEBUG(1,("server connect for cli_trust\n"));
+
+ if (!server_connect_init(&cli_trust, myhostname, dest_ip, dest_host))
+ {
+ cli_error(&cli_trust, &err_cls, &err_num);
+ DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(&cli_trust)));
+
+ cli_shutdown(&cli_trust);
+ return False;
+ }
+
+ DEBUG(1,("server connect cli_trust succeeded\n"));
+
+ nt_lm_owf_gen(mach_pwd, nt_owf_mach_pwd, lm_owf_mach_pwd);
+
+ DEBUG(5,("generating nt owf from initial machine pwd: %s\n", mach_pwd));
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("client cryptkey: "));
+ dump_data(100, cli_trust.cryptkey, sizeof(cli_trust.cryptkey));
+#endif
+
+ SMBencrypt(nt_owf_mach_pwd, cli_trust.cryptkey, nt_sess_pwd);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("nt_owf_mach_pwd: "));
+ dump_data(100, nt_owf_mach_pwd, sizeof(lm_owf_mach_pwd));
+ DEBUG(100,("nt_sess_pwd: "));
+ dump_data(100, nt_sess_pwd, sizeof(nt_sess_pwd));
+#endif
+
+ SMBencrypt(lm_owf_mach_pwd, cli_trust.cryptkey, lm_sess_pwd);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("lm_owf_mach_pwd: "));
+ dump_data(100, lm_owf_mach_pwd, sizeof(lm_owf_mach_pwd));
+ DEBUG(100,("lm_sess_pwd: "));
+ dump_data(100, lm_sess_pwd, sizeof(lm_sess_pwd));
+#endif
+
+ right_error_code = False;
+
+ if (cli_session_setup(&cli_trust, mach_acct,
+ nt_owf_mach_pwd, sizeof(nt_owf_mach_pwd),
+ nt_owf_mach_pwd, sizeof(nt_owf_mach_pwd), domain))
+ {
+ DEBUG(0,("cli_session_setup: NO ERROR! AAAGH! BUG IN SERVER DETECTED!!!\n"));
+ cli_shutdown(&cli_trust);
+
+ return False;
+ }
+
+ cli_error(&cli_trust, &err_cls, &err_num);
+
+ if (err_num == (0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT))
+ {
+ DEBUG(1,("cli_send_tconX: valid workstation trust account exists\n"));
+ right_error_code = True;
+ }
+
+ if (err_num == (0xC0000000 | NT_STATUS_NO_SUCH_USER))
+ {
+ DEBUG(1,("cli_send_tconX: workstation trust account does not exist\n"));
+ right_error_code = False;
+ }
+
+ if (!right_error_code)
+ {
+ DEBUG(1,("server_validate failed (%s)\n", cli_errstr(&cli_trust)));
+ }
+
+ cli_shutdown(&cli_trust);
+ return right_error_code;
+}
+
+