From 0f1713068f597fddb88faf616eeb9382029c3d58 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 3 Dec 2000 02:18:14 +0000 Subject: [PATCH] - added client support for nttrans calls - added a cli_ function for querying a security descriptor on a remote file (This used to be commit e21994ff9d512d1c9d6d360e930809b135df4cf7) --- source3/libsmb/clisecdesc.c | 82 +++++++++++++++ source3/libsmb/clitrans.c | 200 ++++++++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 source3/libsmb/clisecdesc.c diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c new file mode 100644 index 00000000000..7667938f025 --- /dev/null +++ b/source3/libsmb/clisecdesc.c @@ -0,0 +1,82 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + client security descriptor functions + Copyright (C) Andrew Tridgell 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. +*/ + +#define NO_SYSLOG + +#include "includes.h" + + + +/**************************************************************************** + query the security descriptor for a open file + ****************************************************************************/ +SEC_DESC *cli_query_secdesc(struct cli_state *cli,int fd) +{ + char param[8]; + char *rparam=NULL, *rdata=NULL; + int rparam_count=0, rdata_count=0; + TALLOC_CTX *mem_ctx; + prs_struct pd; + SEC_DESC *psd = NULL; + SEC_DESC *ret; + + SIVAL(param, 0, fd); + SSVAL(param, 4, 7); + + if (!cli_send_nt_trans(cli, + NT_TRANSACT_QUERY_SECURITY_DESC, + 0, + NULL, 0, 0, + param, 8, 4, + NULL, 0, 0x10000)) { + DEBUG(1,("Failed to send NT_TRANSACT_QUERY_SECURITY_DESC\n")); + return NULL; + } + + + if (!cli_receive_nt_trans(cli, + &rparam, &rparam_count, + &rdata, &rdata_count)) { + DEBUG(1,("Failed to recv NT_TRANSACT_QUERY_SECURITY_DESC\n")); + return NULL; + } + + if ((mem_ctx = talloc_init()) == NULL) { + DEBUG(0,("talloc_init failed.\n")); + return NULL; + } + + prs_init(&pd, rdata_count, 4, mem_ctx, UNMARSHALL); + prs_append_data(&pd, rdata, rdata_count); + pd.data_offset = 0; + + if (!sec_io_desc("sd data", &psd, &pd, 1)) { + DEBUG(1,("Failed to parse secdesc\n")); + return NULL; + } + + ret = dup_sec_desc(psd); + talloc_destroy(mem_ctx); + return ret; +} + + + diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 76758a0dd63..50ed68ee165 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -231,3 +231,203 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, return(True); } + + + + +/**************************************************************************** + send a SMB nttrans request + ****************************************************************************/ +BOOL cli_send_nt_trans(struct cli_state *cli, + int function, + int flags, + uint16 *setup, int lsetup, int msetup, + char *param, int lparam, int mparam, + char *data, int ldata, int mdata) +{ + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + char *outdata,*outparam; + + this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */ + this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam)); + + memset(cli->outbuf,'\0',smb_size); + set_message(cli->outbuf,19+lsetup,0,True); + CVAL(cli->outbuf,smb_com) = SMBnttrans; + SSVAL(cli->outbuf,smb_tid, cli->cnum); + cli_setup_packet(cli); + + outparam = smb_buf(cli->outbuf)+3; + outdata = outparam+this_lparam; + + /* primary request */ + SCVAL(cli->outbuf,smb_nt_MaxSetupCount,msetup); + SCVAL(cli->outbuf,smb_nt_Flags,flags); + SIVAL(cli->outbuf,smb_nt_TotalParameterCount, lparam); + SIVAL(cli->outbuf,smb_nt_TotalDataCount, ldata); + SIVAL(cli->outbuf,smb_nt_MaxParameterCount, mparam); + SIVAL(cli->outbuf,smb_nt_MaxDataCount, mdata); + SIVAL(cli->outbuf,smb_nt_ParameterCount, this_lparam); + SIVAL(cli->outbuf,smb_nt_ParameterOffset, smb_offset(outparam,cli->outbuf)); + SIVAL(cli->outbuf,smb_nt_DataCount, this_ldata); + SIVAL(cli->outbuf,smb_nt_DataOffset, smb_offset(outdata,cli->outbuf)); + SIVAL(cli->outbuf,smb_nt_SetupCount, lsetup); + SIVAL(cli->outbuf,smb_nt_Function, function); + for (i=0;ioutbuf,smb_nt_SetupStart+i*2,setup[i]); + + if (this_lparam) /* param[] */ + memcpy(outparam,param,this_lparam); + if (this_ldata) /* data[] */ + memcpy(outdata,data,this_ldata); + + set_message(cli->outbuf,19+lsetup, /* wcnt, bcc */ + PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + + show_msg(cli->outbuf); + cli_send_smb(cli); + + if (this_ldata < ldata || this_lparam < lparam) { + /* receive interim response */ + if (!cli_receive_smb(cli) || + CVAL(cli->inbuf,smb_rcls) != 0) { + return(False); + } + + tot_data = this_ldata; + tot_param = this_lparam; + + while (tot_data < ldata || tot_param < lparam) { + this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */ + this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam)); + + set_message(cli->outbuf,18,0,True); + CVAL(cli->outbuf,smb_com) = SMBnttranss; + + /* XXX - these should probably be aligned */ + outparam = smb_buf(cli->outbuf); + outdata = outparam+this_lparam; + + /* secondary request */ + SIVAL(cli->outbuf,smb_nts_TotalParameterCount,lparam); + SIVAL(cli->outbuf,smb_nts_TotalDataCount,ldata); + SIVAL(cli->outbuf,smb_nts_ParameterCount,this_lparam); + SIVAL(cli->outbuf,smb_nts_ParameterOffset,smb_offset(outparam,cli->outbuf)); + SIVAL(cli->outbuf,smb_nts_ParameterDisplacement,tot_param); + SIVAL(cli->outbuf,smb_nts_DataCount,this_ldata); + SIVAL(cli->outbuf,smb_nts_DataOffset,smb_offset(outdata,cli->outbuf)); + SIVAL(cli->outbuf,smb_nts_DataDisplacement,tot_data); + if (this_lparam) /* param[] */ + memcpy(outparam,param+tot_param,this_lparam); + if (this_ldata) /* data[] */ + memcpy(outdata,data+tot_data,this_ldata); + set_message(cli->outbuf,18, + PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False); + + show_msg(cli->outbuf); + cli_send_smb(cli); + + tot_data += this_ldata; + tot_param += this_lparam; + } + } + + return(True); +} + + + +/**************************************************************************** + receive a SMB nttrans response allocating the necessary memory + ****************************************************************************/ +BOOL cli_receive_nt_trans(struct cli_state *cli, + char **param, int *param_len, + char **data, int *data_len) +{ + int total_data=0; + int total_param=0; + int this_data,this_param; + uint8 eclass; + uint32 ecode; + + *data_len = *param_len = 0; + + if (!cli_receive_smb(cli)) + return False; + + show_msg(cli->inbuf); + + /* sanity check */ + if (CVAL(cli->inbuf,smb_com) != SMBnttrans) { + DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n", + CVAL(cli->inbuf,smb_com))); + return(False); + } + + /* + * An NT RPC pipe call can return ERRDOS, ERRmoredata + * to a trans call. This is not an error and should not + * be treated as such. + */ + if (cli_error(cli, &eclass, &ecode, NULL)) { + if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) + return(False); + } + + /* parse out the lengths */ + total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount); + total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount); + + /* allocate it */ + *data = Realloc(*data,total_data); + *param = Realloc(*param,total_param); + + while (1) { + this_data = SVAL(cli->inbuf,smb_ntr_DataCount); + this_param = SVAL(cli->inbuf,smb_ntr_ParameterCount); + + if (this_data + *data_len > total_data || + this_param + *param_len > total_param) { + DEBUG(1,("Data overflow in cli_receive_trans\n")); + return False; + } + + if (this_data) + memcpy(*data + SVAL(cli->inbuf,smb_ntr_DataDisplacement), + smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_ntr_DataOffset), + this_data); + if (this_param) + memcpy(*param + SVAL(cli->inbuf,smb_ntr_ParameterDisplacement), + smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_ntr_ParameterOffset), + this_param); + *data_len += this_data; + *param_len += this_param; + + /* parse out the total lengths again - they can shrink! */ + total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount); + total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount); + + if (total_data <= *data_len && total_param <= *param_len) + break; + + if (!cli_receive_smb(cli)) + return False; + + show_msg(cli->inbuf); + + /* sanity check */ + if (CVAL(cli->inbuf,smb_com) != SMBnttrans) { + DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n", + CVAL(cli->inbuf,smb_com))); + return(False); + } + if (cli_error(cli, &eclass, &ecode, NULL)) { + if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) + return(False); + } + } + + return(True); +}