/**************************************************************************** reply to a read and X This code is basically stolen from reply_read_and_X with some wrinkles to handle pipes. ****************************************************************************/ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); int nread = -1; char *data; /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of data on the pipe */ #if 0 uint32 smb_offs = IVAL(inbuf,smb_vwv3); #endif if (!p) return(ERROR(ERRDOS,ERRbadfid)); set_message(outbuf,12,0,True); data = smb_buf(outbuf); nread = (int)read_from_pipe(p, data, (size_t)smb_maxcnt); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); return chain_reply(inbuf,outbuf,length,bufsize); }
void reply_pipe_read_and_X(struct smb_request *req) { smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2)); int smb_maxcnt = SVAL(req->inbuf,smb_vwv5); int smb_mincnt = SVAL(req->inbuf,smb_vwv6); int nread = -1; char *data; bool unused; /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of data on the pipe */ #if 0 uint32 smb_offs = IVAL(req->inbuf,smb_vwv3); #endif if (!p) { reply_doserror(req, ERRDOS, ERRbadfid); return; } reply_outbuf(req, 12, smb_maxcnt); data = smb_buf(req->outbuf); nread = read_from_pipe(p, data, smb_maxcnt, &unused); if (nread < 0) { reply_doserror(req, ERRDOS, ERRnoaccess); return; } srv_set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); SSVAL(smb_buf(req->outbuf),-2,nread); DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); chain_reply(req); }
void send_trans_reply(connection_struct *conn, struct smb_request *req, char *rparam, int rparam_len, char *rdata, int rdata_len, bool buffer_too_large) { int this_ldata,this_lparam; int tot_data_sent = 0; int tot_param_sent = 0; int align; int ldata = rdata ? rdata_len : 0; int lparam = rparam ? rparam_len : 0; struct smbd_server_connection *sconn = req->sconn; int max_send = sconn->smb1.sessions.max_send; if (buffer_too_large) DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata )); this_lparam = MIN(lparam,max_send - 500); /* hack */ this_ldata = MIN(ldata,max_send - (500+this_lparam)); align = ((this_lparam)%4); reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); /* * We might have SMBtranss in req which was transferred to the outbuf, * fix that. */ SCVAL(req->outbuf, smb_com, SMBtrans); copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); SSVAL(req->outbuf,smb_vwv0,lparam); SSVAL(req->outbuf,smb_vwv1,ldata); SSVAL(req->outbuf,smb_vwv3,this_lparam); SSVAL(req->outbuf,smb_vwv4, smb_offset(smb_buf(req->outbuf)+1, req->outbuf)); SSVAL(req->outbuf,smb_vwv5,0); SSVAL(req->outbuf,smb_vwv6,this_ldata); SSVAL(req->outbuf,smb_vwv7, smb_offset(smb_buf(req->outbuf)+1+this_lparam+align, req->outbuf)); SSVAL(req->outbuf,smb_vwv8,0); SSVAL(req->outbuf,smb_vwv9,0); if (buffer_too_large) { error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } show_msg((char *)req->outbuf); if (!srv_send_smb(sconn, (char *)req->outbuf, true, req->seqnum+1, IS_CONN_ENCRYPTED(conn), &req->pcd)) { exit_server_cleanly("send_trans_reply: srv_send_smb failed."); } TALLOC_FREE(req->outbuf); tot_data_sent = this_ldata; tot_param_sent = this_lparam; while (tot_data_sent < ldata || tot_param_sent < lparam) { this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */ this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam)); if(this_lparam < 0) this_lparam = 0; if(this_ldata < 0) this_ldata = 0; align = (this_lparam%4); reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); /* * We might have SMBtranss in req which was transferred to the * outbuf, fix that. */ SCVAL(req->outbuf, smb_com, SMBtrans); copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); SSVAL(req->outbuf,smb_vwv0,lparam); SSVAL(req->outbuf,smb_vwv1,ldata); SSVAL(req->outbuf,smb_vwv3,this_lparam); SSVAL(req->outbuf,smb_vwv4, smb_offset(smb_buf(req->outbuf)+1,req->outbuf)); SSVAL(req->outbuf,smb_vwv5,tot_param_sent); SSVAL(req->outbuf,smb_vwv6,this_ldata); SSVAL(req->outbuf,smb_vwv7, smb_offset(smb_buf(req->outbuf)+1+this_lparam+align, req->outbuf)); SSVAL(req->outbuf,smb_vwv8,tot_data_sent); SSVAL(req->outbuf,smb_vwv9,0); if (buffer_too_large) { error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } show_msg((char *)req->outbuf); if (!srv_send_smb(sconn, (char *)req->outbuf, true, req->seqnum+1, IS_CONN_ENCRYPTED(conn), &req->pcd)) exit_server_cleanly("send_trans_reply: srv_send_smb " "failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; TALLOC_FREE(req->outbuf); } }
bool cli_send_nt_trans(struct cli_state *cli, int function, int flags, uint16 *setup, unsigned int lsetup, unsigned int msetup, char *param, unsigned int lparam, unsigned int mparam, char *data, unsigned int ldata, unsigned int mdata) { unsigned int i; unsigned int this_ldata,this_lparam; unsigned int tot_data=0,tot_param=0; uint16 mid; 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); cli_set_message(cli->outbuf,19+lsetup,0,True); SCVAL(cli->outbuf,smb_com,SMBnttrans); SSVAL(cli->outbuf,smb_tid, cli->cnum); cli_setup_packet(cli); /* * Save the mid we're using. We need this for finding * signing replies. */ mid = cli->mid; 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;i<lsetup;i++) /* setup[] */ SSVAL(cli->outbuf,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); cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); if (!cli_send_smb(cli)) { return False; } cli_state_seqnum_persistent(cli, mid); if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { cli_state_seqnum_remove(cli, mid); 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)); cli_set_message(cli->outbuf,18,0,True); SCVAL(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); cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli->mid = mid; if (!cli_send_smb(cli)) { cli_state_seqnum_remove(cli, mid); return False; } tot_data += this_ldata; tot_param += this_lparam; } } return(True); }
bool cli_send_trans(struct cli_state *cli, int trans, const char *pipe_name, int fid, int flags, uint16 *setup, unsigned int lsetup, unsigned int msetup, const char *param, unsigned int lparam, unsigned int mparam, const char *data, unsigned int ldata, unsigned int mdata) { unsigned int i; unsigned int this_ldata,this_lparam; unsigned int tot_data=0,tot_param=0; char *outdata,*outparam; char *p; int pipe_name_len=0; uint16 mid; 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); cli_set_message(cli->outbuf,14+lsetup,0,True); SCVAL(cli->outbuf,smb_com,trans); SSVAL(cli->outbuf,smb_tid, cli->cnum); cli_setup_packet(cli); /* * Save the mid we're using. We need this for finding * signing replies. */ mid = cli->mid; if (pipe_name) { pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE); } outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len : 3); outdata = outparam+this_lparam; /* primary request */ SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */ SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */ SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */ SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */ SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */ SSVAL(cli->outbuf,smb_flags,flags); /* flags */ SIVAL(cli->outbuf,smb_timeout,0); /* timeout */ SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */ SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */ SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */ SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */ SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */ for (i=0;i<lsetup;i++) /* setup[] */ SSVAL(cli->outbuf,smb_setup+i*2,setup[i]); p = smb_buf(cli->outbuf); if (trans != SMBtrans) { *p++ = 0; /* put in a null smb_name */ *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */ } if (this_lparam) /* param[] */ memcpy(outparam,param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data,this_ldata); cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); if (!cli_send_smb(cli)) { return False; } cli_state_seqnum_persistent(cli, mid); if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { cli_state_seqnum_remove(cli, mid); 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)); cli_set_message(cli->outbuf,trans==SMBtrans?8:9,0,True); SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2)); outparam = smb_buf(cli->outbuf); outdata = outparam+this_lparam; /* secondary request */ SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */ SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */ SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */ SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */ SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */ SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */ SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */ SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */ if (trans==SMBtrans2) SSVALS(cli->outbuf,smb_sfid,fid); /* fid */ if (this_lparam) /* param[] */ memcpy(outparam,param+tot_param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data+tot_data,this_ldata); cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli->mid = mid; if (!cli_send_smb(cli)) { cli_state_seqnum_remove(cli, mid); return False; } tot_data += this_ldata; tot_param += this_lparam; } } return(True); }