00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023
00024
00025
00026
00027
00028 BOOL cli_send_trans(struct cli_state *cli, int trans,
00029 const char *pipe_name,
00030 int fid, int flags,
00031 uint16 *setup, unsigned int lsetup, unsigned int msetup,
00032 const char *param, unsigned int lparam, unsigned int mparam,
00033 const char *data, unsigned int ldata, unsigned int mdata)
00034 {
00035 unsigned int i;
00036 unsigned int this_ldata,this_lparam;
00037 unsigned int tot_data=0,tot_param=0;
00038 char *outdata,*outparam;
00039 char *p;
00040 int pipe_name_len=0;
00041 uint16 mid;
00042
00043 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2));
00044 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
00045
00046 memset(cli->outbuf,'\0',smb_size);
00047 set_message(cli->outbuf,14+lsetup,0,True);
00048 SCVAL(cli->outbuf,smb_com,trans);
00049 SSVAL(cli->outbuf,smb_tid, cli->cnum);
00050 cli_setup_packet(cli);
00051
00052
00053
00054
00055
00056
00057 mid = cli->mid;
00058
00059 if (pipe_name) {
00060 pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE);
00061 }
00062
00063 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len : 3);
00064 outdata = outparam+this_lparam;
00065
00066
00067 SSVAL(cli->outbuf,smb_tpscnt,lparam);
00068 SSVAL(cli->outbuf,smb_tdscnt,ldata);
00069 SSVAL(cli->outbuf,smb_mprcnt,mparam);
00070 SSVAL(cli->outbuf,smb_mdrcnt,mdata);
00071 SCVAL(cli->outbuf,smb_msrcnt,msetup);
00072 SSVAL(cli->outbuf,smb_flags,flags);
00073 SIVAL(cli->outbuf,smb_timeout,0);
00074 SSVAL(cli->outbuf,smb_pscnt,this_lparam);
00075 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf));
00076 SSVAL(cli->outbuf,smb_dscnt,this_ldata);
00077 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf));
00078 SCVAL(cli->outbuf,smb_suwcnt,lsetup);
00079 for (i=0;i<lsetup;i++)
00080 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
00081 p = smb_buf(cli->outbuf);
00082 if (trans != SMBtrans) {
00083 *p++ = 0;
00084 *p++ = 'D'; *p++ = ' ';
00085 }
00086 if (this_lparam)
00087 memcpy(outparam,param,this_lparam);
00088 if (this_ldata)
00089 memcpy(outdata,data,this_ldata);
00090 cli_setup_bcc(cli, outdata+this_ldata);
00091
00092 show_msg(cli->outbuf);
00093
00094 if (!cli_send_smb(cli)) {
00095 return False;
00096 }
00097
00098
00099
00100 client_set_trans_sign_state_on(cli, mid);
00101
00102 if (this_ldata < ldata || this_lparam < lparam) {
00103
00104 if (!cli_receive_smb(cli) || cli_is_error(cli)) {
00105 client_set_trans_sign_state_off(cli, mid);
00106 return(False);
00107 }
00108
00109 tot_data = this_ldata;
00110 tot_param = this_lparam;
00111
00112 while (tot_data < ldata || tot_param < lparam) {
00113 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500);
00114 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
00115
00116 client_set_trans_sign_state_off(cli, mid);
00117 client_set_trans_sign_state_on(cli, mid);
00118
00119 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
00120 SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2));
00121
00122 outparam = smb_buf(cli->outbuf);
00123 outdata = outparam+this_lparam;
00124
00125
00126 SSVAL(cli->outbuf,smb_tpscnt,lparam);
00127 SSVAL(cli->outbuf,smb_tdscnt,ldata);
00128 SSVAL(cli->outbuf,smb_spscnt,this_lparam);
00129 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf));
00130 SSVAL(cli->outbuf,smb_spsdisp,tot_param);
00131 SSVAL(cli->outbuf,smb_sdscnt,this_ldata);
00132 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf));
00133 SSVAL(cli->outbuf,smb_sdsdisp,tot_data);
00134 if (trans==SMBtrans2)
00135 SSVALS(cli->outbuf,smb_sfid,fid);
00136 if (this_lparam)
00137 memcpy(outparam,param+tot_param,this_lparam);
00138 if (this_ldata)
00139 memcpy(outdata,data+tot_data,this_ldata);
00140 cli_setup_bcc(cli, outdata+this_ldata);
00141
00142
00143
00144
00145
00146 mid = cli->mid;
00147
00148 show_msg(cli->outbuf);
00149 if (!cli_send_smb(cli)) {
00150 client_set_trans_sign_state_off(cli, mid);
00151 return False;
00152 }
00153
00154
00155 cli->mid = mid;
00156
00157 tot_data += this_ldata;
00158 tot_param += this_lparam;
00159 }
00160 }
00161
00162 return(True);
00163 }
00164
00165
00166
00167
00168
00169 BOOL cli_receive_trans(struct cli_state *cli,int trans,
00170 char **param, unsigned int *param_len,
00171 char **data, unsigned int *data_len)
00172 {
00173 unsigned int total_data=0;
00174 unsigned int total_param=0;
00175 unsigned int this_data,this_param;
00176 NTSTATUS status;
00177 BOOL ret = False;
00178
00179 *data_len = *param_len = 0;
00180
00181 if (!cli_receive_smb(cli)) {
00182 return False;
00183 }
00184
00185 show_msg(cli->inbuf);
00186
00187
00188 if (CVAL(cli->inbuf,smb_com) != trans) {
00189 DEBUG(0,("Expected %s response, got command 0x%02x\n",
00190 trans==SMBtrans?"SMBtrans":"SMBtrans2",
00191 CVAL(cli->inbuf,smb_com)));
00192 return False;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 status = cli_nt_error(cli);
00202
00203 if (NT_STATUS_IS_ERR(status) ||
00204 NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES) ||
00205 NT_STATUS_EQUAL(status,STATUS_INACCESSIBLE_SYSTEM_SHORTCUT)) {
00206 goto out;
00207 }
00208
00209
00210 total_data = SVAL(cli->inbuf,smb_tdrcnt);
00211 total_param = SVAL(cli->inbuf,smb_tprcnt);
00212
00213
00214 if (total_data!=0) {
00215 *data = (char *)SMB_REALLOC(*data,total_data);
00216 if (!(*data)) {
00217 DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
00218 goto out;
00219 }
00220 }
00221
00222 if (total_param!=0) {
00223 *param = (char *)SMB_REALLOC(*param,total_param);
00224 if (!(*param)) {
00225 DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
00226 goto out;
00227 }
00228 }
00229
00230 for (;;) {
00231 this_data = SVAL(cli->inbuf,smb_drcnt);
00232 this_param = SVAL(cli->inbuf,smb_prcnt);
00233
00234 if (this_data + *data_len > total_data ||
00235 this_param + *param_len > total_param) {
00236 DEBUG(1,("Data overflow in cli_receive_trans\n"));
00237 goto out;
00238 }
00239
00240 if (this_data + *data_len < this_data ||
00241 this_data + *data_len < *data_len ||
00242 this_param + *param_len < this_param ||
00243 this_param + *param_len < *param_len) {
00244 DEBUG(1,("Data overflow in cli_receive_trans\n"));
00245 goto out;
00246 }
00247
00248 if (this_data) {
00249 unsigned int data_offset_out = SVAL(cli->inbuf,smb_drdisp);
00250 unsigned int data_offset_in = SVAL(cli->inbuf,smb_droff);
00251
00252 if (data_offset_out > total_data ||
00253 data_offset_out + this_data > total_data ||
00254 data_offset_out + this_data < data_offset_out ||
00255 data_offset_out + this_data < this_data) {
00256 DEBUG(1,("Data overflow in cli_receive_trans\n"));
00257 goto out;
00258 }
00259 if (data_offset_in > cli->bufsize ||
00260 data_offset_in + this_data > cli->bufsize ||
00261 data_offset_in + this_data < data_offset_in ||
00262 data_offset_in + this_data < this_data) {
00263 DEBUG(1,("Data overflow in cli_receive_trans\n"));
00264 goto out;
00265 }
00266
00267 memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
00268 }
00269 if (this_param) {
00270 unsigned int param_offset_out = SVAL(cli->inbuf,smb_prdisp);
00271 unsigned int param_offset_in = SVAL(cli->inbuf,smb_proff);
00272
00273 if (param_offset_out > total_param ||
00274 param_offset_out + this_param > total_param ||
00275 param_offset_out + this_param < param_offset_out ||
00276 param_offset_out + this_param < this_param) {
00277 DEBUG(1,("Param overflow in cli_receive_trans\n"));
00278 goto out;
00279 }
00280 if (param_offset_in > cli->bufsize ||
00281 param_offset_in + this_param > cli->bufsize ||
00282 param_offset_in + this_param < param_offset_in ||
00283 param_offset_in + this_param < this_param) {
00284 DEBUG(1,("Param overflow in cli_receive_trans\n"));
00285 goto out;
00286 }
00287
00288 memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
00289 }
00290 *data_len += this_data;
00291 *param_len += this_param;
00292
00293 if (total_data <= *data_len && total_param <= *param_len) {
00294 ret = True;
00295 break;
00296 }
00297
00298 if (!cli_receive_smb(cli)) {
00299 goto out;
00300 }
00301
00302 show_msg(cli->inbuf);
00303
00304
00305 if (CVAL(cli->inbuf,smb_com) != trans) {
00306 DEBUG(0,("Expected %s response, got command 0x%02x\n",
00307 trans==SMBtrans?"SMBtrans":"SMBtrans2",
00308 CVAL(cli->inbuf,smb_com)));
00309 goto out;
00310 }
00311 if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
00312 goto out;
00313 }
00314
00315
00316 if (SVAL(cli->inbuf,smb_tdrcnt) < total_data)
00317 total_data = SVAL(cli->inbuf,smb_tdrcnt);
00318 if (SVAL(cli->inbuf,smb_tprcnt) < total_param)
00319 total_param = SVAL(cli->inbuf,smb_tprcnt);
00320
00321 if (total_data <= *data_len && total_param <= *param_len) {
00322 ret = True;
00323 break;
00324 }
00325 }
00326
00327 out:
00328
00329 client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid));
00330 return ret;
00331 }
00332
00333
00334
00335
00336
00337 BOOL cli_send_nt_trans(struct cli_state *cli,
00338 int function,
00339 int flags,
00340 uint16 *setup, unsigned int lsetup, unsigned int msetup,
00341 char *param, unsigned int lparam, unsigned int mparam,
00342 char *data, unsigned int ldata, unsigned int mdata)
00343 {
00344 unsigned int i;
00345 unsigned int this_ldata,this_lparam;
00346 unsigned int tot_data=0,tot_param=0;
00347 uint16 mid;
00348 char *outdata,*outparam;
00349
00350 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2));
00351 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
00352
00353 memset(cli->outbuf,'\0',smb_size);
00354 set_message(cli->outbuf,19+lsetup,0,True);
00355 SCVAL(cli->outbuf,smb_com,SMBnttrans);
00356 SSVAL(cli->outbuf,smb_tid, cli->cnum);
00357 cli_setup_packet(cli);
00358
00359
00360
00361
00362
00363
00364 mid = cli->mid;
00365
00366 outparam = smb_buf(cli->outbuf)+3;
00367 outdata = outparam+this_lparam;
00368
00369
00370 SCVAL(cli->outbuf,smb_nt_MaxSetupCount,msetup);
00371 SCVAL(cli->outbuf,smb_nt_Flags,flags);
00372 SIVAL(cli->outbuf,smb_nt_TotalParameterCount, lparam);
00373 SIVAL(cli->outbuf,smb_nt_TotalDataCount, ldata);
00374 SIVAL(cli->outbuf,smb_nt_MaxParameterCount, mparam);
00375 SIVAL(cli->outbuf,smb_nt_MaxDataCount, mdata);
00376 SIVAL(cli->outbuf,smb_nt_ParameterCount, this_lparam);
00377 SIVAL(cli->outbuf,smb_nt_ParameterOffset, smb_offset(outparam,cli->outbuf));
00378 SIVAL(cli->outbuf,smb_nt_DataCount, this_ldata);
00379 SIVAL(cli->outbuf,smb_nt_DataOffset, smb_offset(outdata,cli->outbuf));
00380 SIVAL(cli->outbuf,smb_nt_SetupCount, lsetup);
00381 SIVAL(cli->outbuf,smb_nt_Function, function);
00382 for (i=0;i<lsetup;i++)
00383 SSVAL(cli->outbuf,smb_nt_SetupStart+i*2,setup[i]);
00384
00385 if (this_lparam)
00386 memcpy(outparam,param,this_lparam);
00387 if (this_ldata)
00388 memcpy(outdata,data,this_ldata);
00389
00390 cli_setup_bcc(cli, outdata+this_ldata);
00391
00392 show_msg(cli->outbuf);
00393 if (!cli_send_smb(cli)) {
00394 return False;
00395 }
00396
00397
00398
00399 client_set_trans_sign_state_on(cli, mid);
00400
00401 if (this_ldata < ldata || this_lparam < lparam) {
00402
00403 if (!cli_receive_smb(cli) || cli_is_error(cli)) {
00404 client_set_trans_sign_state_off(cli, mid);
00405 return(False);
00406 }
00407
00408 tot_data = this_ldata;
00409 tot_param = this_lparam;
00410
00411 while (tot_data < ldata || tot_param < lparam) {
00412 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500);
00413 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
00414
00415 set_message(cli->outbuf,18,0,True);
00416 SCVAL(cli->outbuf,smb_com,SMBnttranss);
00417
00418
00419 outparam = smb_buf(cli->outbuf);
00420 outdata = outparam+this_lparam;
00421
00422
00423 SIVAL(cli->outbuf,smb_nts_TotalParameterCount,lparam);
00424 SIVAL(cli->outbuf,smb_nts_TotalDataCount,ldata);
00425 SIVAL(cli->outbuf,smb_nts_ParameterCount,this_lparam);
00426 SIVAL(cli->outbuf,smb_nts_ParameterOffset,smb_offset(outparam,cli->outbuf));
00427 SIVAL(cli->outbuf,smb_nts_ParameterDisplacement,tot_param);
00428 SIVAL(cli->outbuf,smb_nts_DataCount,this_ldata);
00429 SIVAL(cli->outbuf,smb_nts_DataOffset,smb_offset(outdata,cli->outbuf));
00430 SIVAL(cli->outbuf,smb_nts_DataDisplacement,tot_data);
00431 if (this_lparam)
00432 memcpy(outparam,param+tot_param,this_lparam);
00433 if (this_ldata)
00434 memcpy(outdata,data+tot_data,this_ldata);
00435 cli_setup_bcc(cli, outdata+this_ldata);
00436
00437
00438
00439
00440
00441 mid = cli->mid;
00442
00443 show_msg(cli->outbuf);
00444
00445 if (!cli_send_smb(cli)) {
00446 client_set_trans_sign_state_off(cli, mid);
00447 return False;
00448 }
00449
00450
00451 cli->mid = mid;
00452
00453 tot_data += this_ldata;
00454 tot_param += this_lparam;
00455 }
00456 }
00457
00458 return(True);
00459 }
00460
00461
00462
00463
00464
00465 BOOL cli_receive_nt_trans(struct cli_state *cli,
00466 char **param, unsigned int *param_len,
00467 char **data, unsigned int *data_len)
00468 {
00469 unsigned int total_data=0;
00470 unsigned int total_param=0;
00471 unsigned int this_data,this_param;
00472 uint8 eclass;
00473 uint32 ecode;
00474 BOOL ret = False;
00475
00476 *data_len = *param_len = 0;
00477
00478 if (!cli_receive_smb(cli)) {
00479 return False;
00480 }
00481
00482 show_msg(cli->inbuf);
00483
00484
00485 if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
00486 DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
00487 CVAL(cli->inbuf,smb_com)));
00488 return(False);
00489 }
00490
00491
00492
00493
00494
00495
00496 if (cli_is_dos_error(cli)) {
00497 cli_dos_error(cli, &eclass, &ecode);
00498 if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
00499 goto out;
00500 }
00501 }
00502
00503
00504
00505
00506 if (cli_is_nt_error(cli)) {
00507 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
00508 NT_STATUS_BUFFER_TOO_SMALL)) {
00509 goto out;
00510 }
00511 }
00512
00513
00514 total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount);
00515 total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount);
00516
00517
00518 if (total_data) {
00519 *data = (char *)SMB_REALLOC(*data,total_data);
00520 if (!(*data)) {
00521 DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
00522 goto out;
00523 }
00524 }
00525
00526 if (total_param) {
00527 *param = (char *)SMB_REALLOC(*param,total_param);
00528 if (!(*param)) {
00529 DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
00530 goto out;
00531 }
00532 }
00533
00534 while (1) {
00535 this_data = SVAL(cli->inbuf,smb_ntr_DataCount);
00536 this_param = SVAL(cli->inbuf,smb_ntr_ParameterCount);
00537
00538 if (this_data + *data_len > total_data ||
00539 this_param + *param_len > total_param) {
00540 DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
00541 goto out;
00542 }
00543
00544 if (this_data + *data_len < this_data ||
00545 this_data + *data_len < *data_len ||
00546 this_param + *param_len < this_param ||
00547 this_param + *param_len < *param_len) {
00548 DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
00549 goto out;
00550 }
00551
00552 if (this_data) {
00553 unsigned int data_offset_out = SVAL(cli->inbuf,smb_ntr_DataDisplacement);
00554 unsigned int data_offset_in = SVAL(cli->inbuf,smb_ntr_DataOffset);
00555
00556 if (data_offset_out > total_data ||
00557 data_offset_out + this_data > total_data ||
00558 data_offset_out + this_data < data_offset_out ||
00559 data_offset_out + this_data < this_data) {
00560 DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
00561 goto out;
00562 }
00563 if (data_offset_in > cli->bufsize ||
00564 data_offset_in + this_data > cli->bufsize ||
00565 data_offset_in + this_data < data_offset_in ||
00566 data_offset_in + this_data < this_data) {
00567 DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
00568 goto out;
00569 }
00570
00571 memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
00572 }
00573
00574 if (this_param) {
00575 unsigned int param_offset_out = SVAL(cli->inbuf,smb_ntr_ParameterDisplacement);
00576 unsigned int param_offset_in = SVAL(cli->inbuf,smb_ntr_ParameterOffset);
00577
00578 if (param_offset_out > total_param ||
00579 param_offset_out + this_param > total_param ||
00580 param_offset_out + this_param < param_offset_out ||
00581 param_offset_out + this_param < this_param) {
00582 DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
00583 goto out;
00584 }
00585 if (param_offset_in > cli->bufsize ||
00586 param_offset_in + this_param > cli->bufsize ||
00587 param_offset_in + this_param < param_offset_in ||
00588 param_offset_in + this_param < this_param) {
00589 DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
00590 goto out;
00591 }
00592
00593 memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
00594 }
00595
00596 *data_len += this_data;
00597 *param_len += this_param;
00598
00599 if (total_data <= *data_len && total_param <= *param_len) {
00600 ret = True;
00601 break;
00602 }
00603
00604 if (!cli_receive_smb(cli)) {
00605 goto out;
00606 }
00607
00608 show_msg(cli->inbuf);
00609
00610
00611 if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
00612 DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
00613 CVAL(cli->inbuf,smb_com)));
00614 goto out;
00615 }
00616 if (cli_is_dos_error(cli)) {
00617 cli_dos_error(cli, &eclass, &ecode);
00618 if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
00619 goto out;
00620 }
00621 }
00622
00623
00624
00625 if (cli_is_nt_error(cli)) {
00626 if (!NT_STATUS_EQUAL(cli_nt_error(cli),
00627 NT_STATUS_BUFFER_TOO_SMALL)) {
00628 goto out;
00629 }
00630 }
00631
00632
00633 if (SVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
00634 total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount);
00635 if (SVAL(cli->inbuf,smb_ntr_TotalParameterCount) < total_param)
00636 total_param = SVAL(cli->inbuf,smb_ntr_TotalParameterCount);
00637
00638 if (total_data <= *data_len && total_param <= *param_len) {
00639 ret = True;
00640 break;
00641 }
00642 }
00643
00644 out:
00645
00646 client_set_trans_sign_state_off(cli, SVAL(cli->inbuf,smb_mid));
00647 return ret;
00648 }