1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

Sync 3.0 branch with HEAD

(This used to be commit 3823a2ff5a3c6edf325e2ac31bab50175420f0b1)
This commit is contained in:
Jelmer Vernooij 2002-08-17 16:05:44 +00:00
parent d13dec7010
commit 1f7d18a99c
7 changed files with 4651 additions and 3615 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,260 +1,119 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Jean Francois Micouleau 1998-2000,
*
* 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.
*/
/*
Unix SMB/CIFS implementation.
RPC pipe client
Copyright (C) Gerald Carter 2001-2002,
Copyright (C) Tim Potter 2000-2002,
Copyright (C) Andrew Tridgell 1994-2000,
Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
Copyright (C) Jean-Francois Micouleau 1999-2000.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#if 0
#include "rpc_parse.h"
#include "nterr.h"
#endif
extern pstring global_myname;
struct msg_info_table {
uint32 msg;
uint32 field;
char* name;
void (*construct_fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
print_queue_struct *queue,
NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
};
struct msg_info_table msg_table[] = {
{ PRINTER_MESSAGE_DRIVER, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_MESSAGE_DRIVER", spoolss_notify_driver_name },
{ PRINTER_MESSAGE_ATTRIBUTES, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_MESSAGE_ATTRIBUTES", spoolss_notify_attributes },
{ PRINTER_MESSAGE_COMMENT, PRINTER_NOTIFY_COMMENT, "PRINTER_MESSAGE_COMMENT", spoolss_notify_comment },
{ PRINTER_MESSAGE_LOCATION, PRINTER_NOTIFY_LOCATION, "PRINTER_MESSAGE_LOCATION", spoolss_notify_location },
{ PRINTER_MESSAGE_PRINTERNAME, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_MESSAGE_PRINTERNAME", spoolss_notify_printer_name },
{ PRINTER_MESSAGE_SHARENAME, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_MESSAGE_SHARENAME", spoolss_notify_share_name },
{ PRINTER_MESSAGE_PORT, PRINTER_NOTIFY_PORT_NAME, "PRINTER_MESSAGE_PORT", spoolss_notify_port_name },
{ PRINTER_MESSAGE_CJOBS, PRINTER_NOTIFY_CJOBS, "PRINTER_MESSAGE_CJOBS", spoolss_notify_cjobs },
{ PRINTER_MESSAGE_SEPFILE, PRINTER_NOTIFY_SEPFILE, "PRINTER_MESSAGE_SEPFILE", spoolss_notify_sepfile },
{ PRINTER_MESSAGE_PARAMS, PRINTER_NOTIFY_PARAMETERS, "PRINTER_MESSAGE_PARAMETERS", spoolss_notify_parameters },
{ PRINTER_MESSAGE_DATATYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_MESSAGE_DATATYPE", spoolss_notify_datatype },
{ PRINTER_MESSAGE_NULL, 0x0, "", NULL },
};
/*********************************************************
Disconnect from the client machine.
**********************************************************/
BOOL spoolss_disconnect_from_client( struct cli_state *cli)
{
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
return True;
}
/*********************************************************
Connect to the client machine.
**********************************************************/
BOOL spoolss_connect_to_client( struct cli_state *cli, char *remote_machine)
{
ZERO_STRUCTP(cli);
if(cli_initialise(cli) == NULL) {
DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
return False;
}
if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) {
DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
cli_shutdown(cli);
return False;
}
if (ismyip(cli->dest_ip)) {
DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
cli_shutdown(cli);
return False;
}
if (!cli_connect(cli, remote_machine, &cli->dest_ip)) {
DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) {
DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
remote_machine));
return False;
}
cli->protocol = PROTOCOL_NT1;
if (!cli_negprot(cli)) {
DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
if (cli->protocol != PROTOCOL_NT1) {
DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
cli_shutdown(cli);
return False;
}
/*
* Do an anonymous session setup.
*/
if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
if (!(cli->sec_mode & 1)) {
DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
cli_shutdown(cli);
return False;
}
if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
/*
* Ok - we have an anonymous connection to the IPC$ share.
* Now start the NT Domain stuff :-).
*/
if(cli_nt_session_open(cli, PIPE_SPOOLSS) == False) {
DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli)));
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
return False;
}
return True;
}
/*
* SPOOLSS Client RPC's used by servers as the notification
* back channel
* back channel.
*/
/***************************************************************************
do a reply open printer
****************************************************************************/
/* Send a ReplyOpenPrinter request. This rpc is made by the printer
server to the printer client in response to a rffpcnex request.
The rrfpcnex request names a printer and a handle (the printerlocal
value) and this rpc establishes a back-channel over which printer
notifications are performed. */
WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
char *printer, uint32 localprinter, uint32 type,
POLICY_HND *handle)
char *printer, uint32 printerlocal, uint32 type,
POLICY_HND *handle)
{
prs_struct qbuf, rbuf;
SPOOL_Q_REPLYOPENPRINTER q;
SPOOL_R_REPLYOPENPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
prs_struct rbuf;
prs_struct buf;
/* Initialise input parameters */
SPOOL_Q_REPLYOPENPRINTER q_s;
SPOOL_R_REPLYOPENPRINTER r_s;
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
prs_init(&buf, 1024, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type);
/* create and send a MSRPC command with api SPOOLSS_REPLYOPENPRINTER */
/* Marshall data and send request */
if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) ||
!rpc_api_pipe_req (cli, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf))
goto done;
/* store the parameters */
make_spoolss_q_replyopenprinter(&q_s, printer, localprinter, type);
/* turn parameters into data stream */
if(!spoolss_io_q_replyopenprinter("", &q_s, &buf, 0)) {
DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to marshall SPOOL_Q_REPLYOPENPRINTER struct.\n"));
goto done;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYOPENPRINTER, &buf, &rbuf))
goto done;
/* turn data stream into parameters*/
if(!spoolss_io_r_replyopenprinter("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to unmarshall SPOOL_R_REPLYOPENPRINTER struct.\n"));
goto done;
}
/* Unmarshall response */
memcpy(handle, &r_s.handle, sizeof(r_s.handle));
result = r_s.status;
if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0))
goto done;
/* Return result */
memcpy(handle, &r.handle, sizeof(r.handle));
result = r.status;
done:
prs_mem_free(&buf);
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/***************************************************************************
do a reply open printer
****************************************************************************/
/* Close a back-channel notification connection */
WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *handle)
POLICY_HND *handle)
{
prs_struct qbuf, rbuf;
SPOOL_Q_REPLYCLOSEPRINTER q;
SPOOL_R_REPLYCLOSEPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
prs_struct rbuf;
prs_struct buf;
SPOOL_Q_REPLYCLOSEPRINTER q_s;
SPOOL_R_REPLYCLOSEPRINTER r_s;
/* Initialise input parameters */
prs_init(&buf, 1024, cli->mem_ctx, MARSHALL);
prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* create and send a MSRPC command with api */
make_spoolss_q_reply_closeprinter(&q, handle);
/* Marshall data and send request */
if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) ||
!rpc_api_pipe_req (cli, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf))
goto done;
/* store the parameters */
make_spoolss_q_reply_closeprinter(&q_s, handle);
/* turn parameters into data stream */
if(!spoolss_io_q_replycloseprinter("", &q_s, &buf, 0)) {
DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_Q_REPLY_CLOSEPRINTER struct.\n"));
goto done;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYCLOSEPRINTER, &buf, &rbuf))
goto done;
/* turn data stream into parameters*/
if(!spoolss_io_r_replycloseprinter("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_R_REPLY_CLOSEPRINTER struct.\n"));
goto done;
}
/* Unmarshall response */
if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0))
goto done;
/* Return result */
result = r_s.status;
result = r.status;
done:
prs_mem_free(&buf);
prs_mem_free(&rbuf);
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/*********************************************************************
This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
notification event when the registration **did not** use
@ -262,186 +121,147 @@ done:
Also see cli_spolss_reply_rrpcn()
*********************************************************************/
WERROR cli_spoolss_routerreplyprinter (struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 condition, uint32 changd_id)
WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 condition, uint32 change_id)
{
prs_struct qbuf, rbuf;
SPOOL_Q_ROUTERREPLYPRINTER q;
SPOOL_R_ROUTERREPLYPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise input parameters */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* write the request */
make_spoolss_q_routerreplyprinter(&q, pol, condition, changd_id);
make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id);
/* Marshall data and send request */
if (!spoolss_io_q_routerreplyprinter ("", &q, &qbuf, 0)) {
DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to marshall SPOOL_Q_ROUTERREPLYPRINTER!\n"));
goto done;
}
if (!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!spoolss_io_r_routerreplyprinter ("", &r, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to unmarshall SPOOL_R_ROUTERREPLYPRINTER!\n"));
if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) ||
!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0))
goto done;
}
/* Return output parameters */
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
prs_mem_free(&rbuf);
return result;
}
/**********************************************************************************
Build the SPOOL_NOTIFY_INFO_DATA entries based upon the flags which have been set
*********************************************************************************/
static int build_notify_data (TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, uint32 flags,
SPOOL_NOTIFY_INFO_DATA **notify_data)
{
SPOOL_NOTIFY_INFO_DATA *data;
uint32 idx = 0;
int i = 0;
while ((msg_table[i].msg != PRINTER_MESSAGE_NULL) && flags)
{
if (flags & msg_table[i].msg)
{
DEBUG(10,("build_notify_data: %s set on [%s][%d]\n", msg_table[i].name,
printer->info_2->printername, idx));
if ((data=Realloc(*notify_data, (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
DEBUG(0,("build_notify_data: Realloc() failed with size [%d]!\n",
(idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA)));
return -1;
}
*notify_data = data;
/* clear memory */
memset(*notify_data+idx, 0x0, sizeof(SPOOL_NOTIFY_INFO_DATA));
/*
* 'id' (last param here) is undefined when type == PRINTER_NOTIFY_TYPE
* See PRINTER_NOTIFY_INFO_DATA entries in MSDN
* --jerry
*/
construct_info_data(*notify_data+idx, PRINTER_NOTIFY_TYPE, msg_table[i].field, 0x00);
msg_table[i].construct_fn(-1, *notify_data+idx, NULL, printer, ctx);
idx++;
}
i++;
}
return idx;
}
/*********************************************************************
This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
This SPOOLSS_REPLY_RRPCN function is used to send a change
notification event when the registration **did** use
SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
Also see cli_spoolss_routereplyprinter()
*********************************************************************/
WERROR cli_spoolss_reply_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *handle, PRINTER_MESSAGE_INFO *info,
NT_PRINTER_INFO_LEVEL *printer)
WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 notify_data_len,
SPOOL_NOTIFY_INFO_DATA *notify_data,
uint32 change_low, uint32 change_high)
{
prs_struct rbuf;
prs_struct buf;
SPOOL_NOTIFY_INFO notify_info;
SPOOL_NOTIFY_INFO_DATA *notify_data = NULL;
uint32 data_len;
prs_struct qbuf, rbuf;
SPOOL_Q_REPLY_RRPCN q;
SPOOL_R_REPLY_RRPCN r;
WERROR result = W_ERROR(ERRgeneral);
SPOOL_NOTIFY_INFO notify_info;
SPOOL_Q_REPLY_RRPCN q_s;
SPOOL_R_REPLY_RRPCN r_s;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
if (!info) {
DEBUG(5,("cli_spoolss_reply_rrpcn: NULL printer message info pointer!\n"));
goto done;
}
prs_init(&buf, 1024, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
ZERO_STRUCT(notify_info);
/*
* See comments in _spoolss_setprinter() about PRINTER_CHANGE_XXX
* events. --jerry
*/
DEBUG(10,("cli_spoolss_reply_rrpcn: PRINTER_MESSAGE flags = 0x%8x\n", info->flags));
/* Initialise input parameters */
data_len = build_notify_data(mem_ctx, printer, info->flags, &notify_data);
if (info->flags && (data_len == -1)) {
DEBUG(0,("cli_spoolss_reply_rrpcn: Failed to build SPOOL_NOTIFY_INFO_DATA [flags == 0x%x] for printer [%s]\n",
info->flags, info->printer_name));
result = WERR_NOMEM;
goto done;
}
notify_info.version = 0x2;
notify_info.flags = 0x00020000; /* ?? */
notify_info.count = data_len;
notify_info.count = notify_data_len;
notify_info.data = notify_data;
/* create and send a MSRPC command with api */
/* store the parameters */
make_spoolss_q_reply_rrpcn(&q_s, handle, info->low, info->high, &notify_info);
make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high,
&notify_info);
/* turn parameters into data stream */
if(!spoolss_io_q_reply_rrpcn("", &q_s, &buf, 0)) {
DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to marshall SPOOL_Q_REPLY_RRPCN struct.\n"));
goto done;
}
/* Marshall data and send request */
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &buf, &rbuf))
if(!spoolss_io_q_reply_rrpcn("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
/* turn data stream into parameters*/
if(!spoolss_io_r_reply_rrpcn("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to unmarshall SPOOL_R_REPLY_RRPCN struct.\n"));
if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0))
goto done;
}
if (r_s.unknown0 == 0x00080000) {
if (r.unknown0 == 0x00080000)
DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
}
result = r_s.status;
result = r.status;
done:
prs_mem_free(&buf);
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
/*
* The memory allocated in this array is talloc'd so we only need
* free the array here. JRA.
*/
SAFE_FREE(notify_data);
return result;
}
WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 flags, uint32 options,
char *localmachine, uint32 printerlocal,
SPOOL_NOTIFY_OPTION *option)
{
prs_struct qbuf, rbuf;
SPOOL_Q_RFFPCNEX q;
SPOOL_R_RFFPCNEX r;
WERROR result = W_ERROR(ERRgeneral);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* Initialise input parameters */
make_spoolss_q_rffpcnex(
&q, pol, flags, options, localmachine, printerlocal,
option);
/* Marshall data and send request */
if(!spoolss_io_q_rffpcnex("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SPOOLSS_RFFPCNEX, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if(!spoolss_io_r_rffpcnex("", &r, &rbuf, 0))
goto done;
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}

View File

@ -1,404 +1,445 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
* Copyright (C) Jeremy Allison 1999.
*
* 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.
*/
Unix SMB/CIFS implementation.
NT Domain Authentication SMB / MSRPC client
Copyright (C) Andrew Tridgell 1994-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Copyright (C) Tim Potter 2001
Copyright (C) Jim McDonough 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_CLI
/****************************************************************************
do a server net conn enum
****************************************************************************/
BOOL do_srv_net_srv_conn_enum(struct cli_state *cli,
char *server_name, char *qual_name,
uint32 switch_value, SRV_CONN_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
NTSTATUS cli_srvsvc_net_srv_get_info(struct cli_state *cli,
TALLOC_CTX *mem_ctx,
uint32 switch_value, SRV_INFO_CTR *ctr)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_CONN_ENUM q_o;
SRV_R_NET_CONN_ENUM r_o;
prs_struct qbuf, rbuf;
SRV_Q_NET_SRV_GET_INFO q;
SRV_R_NET_SRV_GET_INFO r;
NTSTATUS result;
if (server_name == NULL || ctr == NULL || preferred_len == 0)
return False;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
/* Initialise parse structures */
/* create and send a MSRPC command with api SRV_NET_CONN_ENUM */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
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;
/* Initialise input parameters */
/* store the parameters */
init_srv_q_net_conn_enum(&q_o, server_name, qual_name,
switch_value, ctr,
preferred_len,
hnd);
init_srv_q_net_srv_get_info(&q, cli->srv_name_slash, switch_value);
/* turn parameters into data stream */
if(!srv_io_q_net_conn_enum("", &q_o, &data, 0)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
/* Marshall data and send request */
if (!srv_io_q_net_srv_get_info("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_SRV_GET_INFO, &qbuf, &rbuf)) {
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
/* send the data on \PIPE\ */
if(!rpc_api_pipe_req(cli, SRV_NET_CONN_ENUM, &data, &rdata)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
/* Unmarshall response */
r.ctr = ctr;
if (!srv_io_r_net_srv_get_info("", &r, &rbuf, 0)) {
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
prs_mem_free(&data);
result = werror_to_ntstatus(r.status);
r_o.ctr = ctr;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
if(!srv_io_r_net_conn_enum("", &r_o, &rdata, 0)) {
prs_mem_free(&rdata);
return False;
}
if (r_o.status != 0) {
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: %s\n", nt_errstr(r_o.status)));
prs_mem_free(&rdata);
return False;
}
if (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));
prs_mem_free(&rdata);
return False;
}
prs_mem_free(&rdata);
return True;
return result;
}
/****************************************************************************
do a server net sess enum
****************************************************************************/
BOOL do_srv_net_srv_sess_enum(struct cli_state *cli,
char *server_name, char *qual_name,
char *user_name,
uint32 switch_value, SRV_SESS_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
int preferred_len, ENUM_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_SESS_ENUM q_o;
SRV_R_NET_SESS_ENUM r_o;
prs_struct qbuf, rbuf;
SRV_Q_NET_SHARE_ENUM q;
SRV_R_NET_SHARE_ENUM r;
WERROR result = W_ERROR(ERRgeneral);
int i;
if (server_name == NULL || ctr == NULL || preferred_len == 0)
return False;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
/* Initialise parse structures */
/* create and send a MSRPC command with api SRV_NET_SESS_ENUM */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
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;
/* Initialise input parameters */
/* store the parameters */
init_srv_q_net_sess_enum(&q_o, server_name, qual_name, user_name,
switch_value, ctr,
preferred_len,
hnd);
init_srv_q_net_share_enum(
&q, cli->srv_name_slash, info_level, preferred_len, hnd);
/* turn parameters into data stream */
if(!srv_io_q_net_sess_enum("", &q_o, &data, 0)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
/* Marshall data and send request */
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SRV_NET_SESS_ENUM, &data, &rdata)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf))
goto done;
prs_mem_free(&data);
/* Unmarshall response */
r_o.ctr = ctr;
if (!srv_io_r_net_share_enum("", &r, &rbuf, 0))
goto done;
if(!srv_io_r_net_sess_enum("", &r_o, &rdata, 0)) {
prs_mem_free(&rdata);
return False;
}
result = r.status;
if (!W_ERROR_IS_OK(result))
goto done;
/* Oh yuck yuck yuck - we have to copy all the info out of the
SRV_SHARE_INFO_CTR in the SRV_R_NET_SHARE_ENUM as when we do a
prs_mem_free() it will all be invalidated. The various share
info structures suck badly too. This really is gross. */
ZERO_STRUCTP(ctr);
if (!r.ctr.num_entries)
goto done;
ctr->info_level = info_level;
ctr->num_entries = r.ctr.num_entries;
switch(info_level) {
case 1:
ctr->share.info1 = (SRV_SHARE_INFO_1 *)talloc(
mem_ctx, sizeof(SRV_SHARE_INFO_1) * ctr->num_entries);
if (r_o.status != 0) {
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: %s\n", nt_errstr(r_o.status)));
prs_mem_free(&rdata);
return False;
}
memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
if (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));
prs_mem_free(&rdata);
return False;
}
for (i = 0; i < ctr->num_entries; i++) {
SRV_SHARE_INFO_1 *info1 = &ctr->share.info1[i];
char *s;
/* Copy pointer crap */
prs_mem_free(&rdata);
return True;
}
memcpy(&info1->info_1, &r.ctr.share.info1[i].info_1,
sizeof(SH_INFO_1));
/****************************************************************************
do a server net share enum
****************************************************************************/
BOOL do_srv_net_srv_share_enum(struct cli_state *cli,
char *server_name,
uint32 switch_value, SRV_R_NET_SHARE_ENUM *r_o,
uint32 preferred_len, ENUM_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_SHARE_ENUM q_o;
/* Duplicate strings */
if (server_name == NULL || preferred_len == 0)
return False;
prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
/* create and send a MSRPC command with api SRV_NET_SHARE_ENUM */
DEBUG(4,("SRV Get Share Info (%s), level %d, enum:%8x\n",
server_name, switch_value, get_enum_hnd(hnd)));
/* store the parameters */
init_srv_q_net_share_enum(&q_o, server_name, switch_value,
preferred_len, hnd);
/* turn parameters into data stream */
if(!srv_io_q_net_share_enum("", &q_o, &data, 0)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SRV_NET_SHARE_ENUM, &data, &rdata)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
prs_mem_free(&data);
if(!srv_io_r_net_share_enum("", r_o, &rdata, 0)) {
prs_mem_free(&rdata);
return False;
}
s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname);
if (s)
init_unistr2(&info1->info_1_str.uni_netname, s, strlen(s) + 1);
if (r_o->status != 0) {
/* report error code */
DEBUG(0,("SRV_R_NET_SHARE_ENUM: %s\n", nt_errstr(r_o->status)));
prs_mem_free(&rdata);
return False;
}
s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_remark);
if (s)
init_unistr2(&info1->info_1_str.uni_remark, s, strlen(s) + 1);
if (r_o->ctr.switch_value != switch_value) {
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_SHARE_ENUM: info class %d does not match request %d\n",
r_o->ctr.switch_value, switch_value));
prs_mem_free(&rdata);
return False;
}
}
prs_mem_free(&rdata);
return True;
}
/****************************************************************************
do a server net file enum
****************************************************************************/
BOOL do_srv_net_srv_file_enum(struct cli_state *cli,
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;
SRV_R_NET_FILE_ENUM r_o;
if (server_name == NULL || ctr == NULL || preferred_len == 0)
return False;
prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
/* create and send a MSRPC command with api SRV_NET_FILE_ENUM */
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 */
init_srv_q_net_file_enum(&q_o, server_name, qual_name,
switch_value, ctr,
preferred_len,
hnd);
/* turn parameters into data stream */
if(!srv_io_q_net_file_enum("", &q_o, &data, 0)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &data, &rdata)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
prs_mem_free(&data);
r_o.ctr = ctr;
if(!srv_io_r_net_file_enum("", &r_o, &rdata, 0)) {
prs_mem_free(&rdata);
return False;
}
break;
case 2:
ctr->share.info2 = (SRV_SHARE_INFO_2 *)talloc(
mem_ctx, sizeof(SRV_SHARE_INFO_2) * ctr->num_entries);
if (r_o.status != 0) {
/* report error code */
DEBUG(0,("SRV_R_NET_FILE_ENUM: %s\n", nt_errstr(r_o.status)));
prs_mem_free(&rdata);
return False;
}
memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
if (r_o.ctr->switch_value != switch_value) {
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_FILE_ENUM: info class %d does not match request %d\n",
r_o.ctr->switch_value, switch_value));
prs_mem_free(&rdata);
return False;
}
for (i = 0; i < ctr->num_entries; i++) {
SRV_SHARE_INFO_2 *info2 = &ctr->share.info2[i];
char *s;
/* Copy pointer crap */
prs_mem_free(&rdata);
return True;
memcpy(&info2->info_2, &r.ctr.share.info2[i].info_2,
sizeof(SH_INFO_2));
/* Duplicate strings */
s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_netname);
if (s)
init_unistr2(&info2->info_2_str.uni_netname, s, strlen(s) + 1);
s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_remark);
if (s)
init_unistr2(&info2->info_2_str.uni_remark, s, strlen(s) + 1);
s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_path);
if (s)
init_unistr2(&info2->info_2_str.uni_path, s, strlen(s) + 1);
s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_passwd);
if (s)
init_unistr2(&info2->info_2_str.uni_passwd, s, strlen(s) + 1);
}
break;
}
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/****************************************************************************
do a server get info
****************************************************************************/
BOOL do_srv_net_srv_get_info(struct cli_state *cli,
char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr)
WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx,
const char *sharename)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_SRV_GET_INFO q_o;
SRV_R_NET_SRV_GET_INFO r_o;
prs_struct qbuf, rbuf;
SRV_Q_NET_SHARE_DEL q;
SRV_R_NET_SHARE_DEL r;
WERROR result = W_ERROR(ERRgeneral);
if (server_name == NULL || switch_value == 0 || ctr == NULL)
return False;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);
/* Initialise parse structures */
/* create and send a MSRPC command with api SRV_NET_SRV_GET_INFO */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value));
/* Initialise input parameters */
/* store the parameters */
init_srv_q_net_srv_get_info(&q_o, server_name, switch_value);
init_srv_q_net_share_del(&q, cli->srv_name_slash, sharename);
/* turn parameters into data stream */
if(!srv_io_q_net_srv_get_info("", &q_o, &data, 0)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
/* Marshall data and send request */
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SRV_NET_SRV_GET_INFO, &data, &rdata)) {
prs_mem_free(&data);
prs_mem_free(&rdata);
return False;
}
if (!srv_io_q_net_share_del("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_SHARE_DEL, &qbuf, &rbuf))
goto done;
prs_mem_free(&data);
/* Unmarshall response */
r_o.ctr = ctr;
if (!srv_io_r_net_share_del("", &r, &rbuf, 0))
goto done;
if(!srv_io_r_net_srv_get_info("", &r_o, &rdata, 0)) {
prs_mem_free(&rdata);
return False;
}
result = r.status;
if (r_o.status != 0) {
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", nt_errstr(r_o.status)));
prs_mem_free(&rdata);
return False;
}
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
if (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));
prs_mem_free(&rdata);
return False;
}
prs_mem_free(&rdata);
return True;
return result;
}
WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
char *netname, uint32 type, char *remark,
uint32 perms, uint32 max_uses, uint32 num_uses,
char *path, char *passwd)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_SHARE_ADD q;
SRV_R_NET_SHARE_ADD r;
WERROR result = W_ERROR(ERRgeneral);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
perms, max_uses, num_uses, path, passwd);
/* Marshall data and send request */
if (!srv_io_q_net_share_add("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_SHARE_ADD, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!srv_io_r_net_share_add("", &r, &rbuf, 0))
goto done;
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
WERROR cli_srvsvc_net_remote_tod(struct cli_state *cli, TALLOC_CTX *mem_ctx,
char *server, TIME_OF_DAY_INFO *tod)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_REMOTE_TOD q;
SRV_R_NET_REMOTE_TOD r;
WERROR result = W_ERROR(ERRgeneral);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* Initialise input parameters */
init_srv_q_net_remote_tod(&q, cli->srv_name_slash);
/* Marshall data and send request */
if (!srv_io_q_net_remote_tod("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_REMOTE_TOD, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
r.tod = tod;
if (!srv_io_r_net_remote_tod("", &r, &rbuf, 0))
goto done;
result = r.status;
if (!W_ERROR_IS_OK(result))
goto done;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
uint32 file_level, const char *user_name,
SRV_FILE_INFO_CTR *ctr, int preferred_len,
ENUM_HND *hnd)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_FILE_ENUM q;
SRV_R_NET_FILE_ENUM r;
WERROR result = W_ERROR(ERRgeneral);
int i;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* Initialise input parameters */
init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name,
file_level, ctr, preferred_len, hnd);
/* Marshall data and send request */
if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!srv_io_r_net_file_enum("", &r, &rbuf, 0))
goto done;
result = r.status;
if (!W_ERROR_IS_OK(result))
goto done;
/* copy the data over to the ctr */
ZERO_STRUCTP(ctr);
ctr->switch_value = file_level;
ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
switch(file_level) {
case 3:
ctr->file.info3 = (SRV_FILE_INFO_3 *)talloc(
mem_ctx, sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
memset(ctr->file.info3, 0,
sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
for (i = 0; i < r.ctr.num_entries; i++) {
SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
char *s;
/* Copy pointer crap */
memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3,
sizeof(FILE_INFO_3));
/* Duplicate strings */
s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
if (s)
init_unistr2(&info3->info_3_str.uni_path_name, s, strlen(s) + 1);
s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
if (s)
init_unistr2(&info3->info_3_str.uni_user_name, s, strlen(s) + 1);
}
break;
}
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
WERROR cli_srvsvc_net_file_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
uint32 file_id)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_FILE_CLOSE q;
SRV_R_NET_FILE_CLOSE r;
WERROR result = W_ERROR(ERRgeneral);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* Initialise input parameters */
init_srv_q_net_file_close(&q, cli->srv_name_slash, file_id);
/* Marshall data and send request */
if (!srv_io_q_net_file_close("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SRV_NET_FILE_CLOSE, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!srv_io_r_net_file_close("", &r, &rbuf, 0))
goto done;
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}

View File

@ -1,87 +1,93 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
* Copyright (C) Jeremy Allison 1999.
*
* 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.
*/
Unix SMB/CIFS implementation.
NT Domain Authentication SMB / MSRPC client
Copyright (C) Andrew Tridgell 1994-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Copyright (C) Tim Potter 2001
Copytight (C) Rafal Szczesniak 2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_CLI
/****************************************************************************
do a WKS Open Policy
****************************************************************************/
BOOL do_wks_query_info(struct cli_state *cli,
char *server_name, uint32 switch_value,
WKS_INFO_100 *wks100)
/**
* WksQueryInfo rpc call (like query for server's capabilities)
*
* @param initialised client structure with \PIPE\wkssvc opened
* @param mem_ctx memory context assigned to this rpc binding
* @param wks100 WksQueryInfo structure
*
* @return NTSTATUS of rpc call
*/
NTSTATUS cli_wks_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
WKS_INFO_100 *wks100)
{
prs_struct buf;
prs_struct rbuf;
prs_struct buf;
WKS_Q_QUERY_INFO q_o;
WKS_R_QUERY_INFO r_o;
if (server_name == 0 || wks100 == NULL)
return False;
if (cli == NULL || wks100 == NULL)
return NT_STATUS_UNSUCCESSFUL;
prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
/* init rpc parse structures */
prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* create and send a MSRPC command with api WKS_QUERY_INFO */
DEBUG(4,("WKS Query Info\n"));
/* store the parameters */
init_wks_q_query_info(&q_o, server_name, switch_value);
/* turn parameters into data stream */
if(!wks_io_q_query_info("", &q_o, &buf, 0)) {
DEBUG(4, ("WksQueryInfo\n"));
/* init query structure with rpc call arguments */
init_wks_q_query_info(&q_o, cli->desthost, 100);
/* marshall data */
if (!wks_io_q_query_info("", &q_o, &buf, 0)) {
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return False;
return NT_STATUS_UNSUCCESSFUL;
}
/* send the data on \PIPE\ */
/* actual rpc call over \PIPE\wkssvc */
if (!rpc_api_pipe_req(cli, WKS_QUERY_INFO, &buf, &rbuf)) {
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return False;
return NT_STATUS_UNSUCCESSFUL;
}
prs_mem_free(&buf);
r_o.wks100 = wks100;
if(!wks_io_r_query_info("", &r_o, &rbuf, 0)) {
/* get call results from response buffer */
if (!wks_io_r_query_info("", &r_o, &rbuf, 0)) {
prs_mem_free(&rbuf);
return False;
return NT_STATUS_UNSUCCESSFUL;
}
if (r_o.status != 0) {
/* report error code */
/* check returnet status code */
if (NT_STATUS_IS_ERR(r_o.status)) {
/* report the error */
DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r_o.status)));
prs_mem_free(&rbuf);
return False;
return r_o.status;
}
/* do clean up */
prs_mem_free(&rbuf);
return True;
return NT_STATUS_OK;
}