summaryrefslogtreecommitdiff
path: root/source3/rpc_client
diff options
context:
space:
mode:
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;
+}
+
+