1/* 2 Unix SMB/CIFS implementation. 3 client RAP calls 4 Copyright (C) Andrew Tridgell 1994-1998 5 Copyright (C) Gerald (Jerry) Carter 2004 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20*/ 21 22#define NO_SYSLOG 23 24#include "includes.h" 25 26 27/**************************************************************************** 28Call a remote api on an arbitrary pipe. takes param, data and setup buffers. 29****************************************************************************/ 30BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name, 31 uint16 *setup, uint32 setup_count, uint32 max_setup_count, 32 char *params, uint32 param_count, uint32 max_param_count, 33 char *data, uint32 data_count, uint32 max_data_count, 34 char **rparam, uint32 *rparam_count, 35 char **rdata, uint32 *rdata_count) 36{ 37 cli_send_trans(cli, SMBtrans, 38 pipe_name, 39 0,0, /* fid, flags */ 40 setup, setup_count, max_setup_count, 41 params, param_count, max_param_count, 42 data, data_count, max_data_count); 43 44 return (cli_receive_trans(cli, SMBtrans, 45 rparam, (unsigned int *)rparam_count, 46 rdata, (unsigned int *)rdata_count)); 47} 48 49/**************************************************************************** 50call a remote api 51****************************************************************************/ 52BOOL cli_api(struct cli_state *cli, 53 char *param, int prcnt, int mprcnt, 54 char *data, int drcnt, int mdrcnt, 55 char **rparam, unsigned int *rprcnt, 56 char **rdata, unsigned int *rdrcnt) 57{ 58 cli_send_trans(cli,SMBtrans, 59 PIPE_LANMAN, /* Name */ 60 0,0, /* fid, flags */ 61 NULL,0,0, /* Setup, length, max */ 62 param, prcnt, mprcnt, /* Params, length, max */ 63 data, drcnt, mdrcnt /* Data, length, max */ 64 ); 65 66 return (cli_receive_trans(cli,SMBtrans, 67 rparam, rprcnt, 68 rdata, rdrcnt)); 69} 70 71 72/**************************************************************************** 73perform a NetWkstaUserLogon 74****************************************************************************/ 75BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) 76{ 77 char *rparam = NULL; 78 char *rdata = NULL; 79 char *p; 80 unsigned int rdrcnt,rprcnt; 81 pstring param; 82 83 memset(param, 0, sizeof(param)); 84 85 /* send a SMBtrans command with api NetWkstaUserLogon */ 86 p = param; 87 SSVAL(p,0,132); /* api number */ 88 p += 2; 89 pstrcpy_base(p,"OOWb54WrLh",param); 90 p = skip_string(p,1); 91 pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param); 92 p = skip_string(p,1); 93 SSVAL(p,0,1); 94 p += 2; 95 pstrcpy_base(p,user,param); 96 strupper_m(p); 97 p += 21; 98 p++; 99 p += 15; 100 p++; 101 pstrcpy_base(p, workstation, param); 102 strupper_m(p); 103 p += 16; 104 SSVAL(p, 0, CLI_BUFFER_SIZE); 105 p += 2; 106 SSVAL(p, 0, CLI_BUFFER_SIZE); 107 p += 2; 108 109 if (cli_api(cli, 110 param, PTR_DIFF(p,param),1024, /* param, length, max */ 111 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 112 &rparam, &rprcnt, /* return params, return size */ 113 &rdata, &rdrcnt /* return data, return size */ 114 )) { 115 cli->rap_error = rparam? SVAL(rparam,0) : -1; 116 p = rdata; 117 118 if (cli->rap_error == 0) { 119 DEBUG(4,("NetWkstaUserLogon success\n")); 120 cli->privileges = SVAL(p, 24); 121 /* The cli->eff_name field used to be set here 122 but it wasn't used anywhere else. */ 123 } else { 124 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error)); 125 } 126 } 127 128 SAFE_FREE(rparam); 129 SAFE_FREE(rdata); 130 return (cli->rap_error == 0); 131} 132 133/**************************************************************************** 134call a NetShareEnum - try and browse available connections on a host 135****************************************************************************/ 136int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state) 137{ 138 char *rparam = NULL; 139 char *rdata = NULL; 140 char *p; 141 unsigned int rdrcnt,rprcnt; 142 pstring param; 143 int count = -1; 144 145 /* now send a SMBtrans command with api RNetShareEnum */ 146 p = param; 147 SSVAL(p,0,0); /* api number */ 148 p += 2; 149 pstrcpy_base(p,"WrLeh",param); 150 p = skip_string(p,1); 151 pstrcpy_base(p,"B13BWz",param); 152 p = skip_string(p,1); 153 SSVAL(p,0,1); 154 /* 155 * Win2k needs a *smaller* buffer than 0xFFFF here - 156 * it returns "out of server memory" with 0xFFFF !!! JRA. 157 */ 158 SSVAL(p,2,0xFFE0); 159 p += 4; 160 161 if (cli_api(cli, 162 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 163 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */ 164 &rparam, &rprcnt, /* return params, length */ 165 &rdata, &rdrcnt)) /* return data, length */ 166 { 167 int res = rparam? SVAL(rparam,0) : -1; 168 169 if (res == 0 || res == ERRmoredata) { 170 int converter=SVAL(rparam,2); 171 int i; 172 173 count=SVAL(rparam,4); 174 p = rdata; 175 176 for (i=0;i<count;i++,p+=20) { 177 char *sname = p; 178 int type = SVAL(p,14); 179 int comment_offset = IVAL(p,16) & 0xFFFF; 180 const char *cmnt = comment_offset?(rdata+comment_offset-converter):""; 181 pstring s1, s2; 182 183 pull_ascii_pstring(s1, sname); 184 pull_ascii_pstring(s2, cmnt); 185 186 fn(s1, type, s2, state); 187 } 188 } else { 189 DEBUG(4,("NetShareEnum res=%d\n", res)); 190 } 191 } else { 192 DEBUG(4,("NetShareEnum failed\n")); 193 } 194 195 SAFE_FREE(rparam); 196 SAFE_FREE(rdata); 197 198 return count; 199} 200 201 202/**************************************************************************** 203call a NetServerEnum for the specified workgroup and servertype mask. This 204function then calls the specified callback function for each name returned. 205 206The callback function takes 4 arguments: the machine name, the server type, 207the comment and a state pointer. 208****************************************************************************/ 209BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, 210 void (*fn)(const char *, uint32, const char *, void *), 211 void *state) 212{ 213 char *rparam = NULL; 214 char *rdata = NULL; 215 unsigned int rdrcnt,rprcnt; 216 char *p; 217 pstring param; 218 int uLevel = 1; 219 int count = -1; 220 221 errno = 0; /* reset */ 222 223 /* send a SMBtrans command with api NetServerEnum */ 224 p = param; 225 SSVAL(p,0,0x68); /* api number */ 226 p += 2; 227 pstrcpy_base(p,"WrLehDz", param); 228 p = skip_string(p,1); 229 230 pstrcpy_base(p,"B16BBDz", param); 231 232 p = skip_string(p,1); 233 SSVAL(p,0,uLevel); 234 SSVAL(p,2,CLI_BUFFER_SIZE); 235 p += 4; 236 SIVAL(p,0,stype); 237 p += 4; 238 239 p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER); 240 241 if (cli_api(cli, 242 param, PTR_DIFF(p,param), 8, /* params, length, max */ 243 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 244 &rparam, &rprcnt, /* return params, return size */ 245 &rdata, &rdrcnt /* return data, return size */ 246 )) { 247 int res = rparam? SVAL(rparam,0) : -1; 248 249 if (res == 0 || res == ERRmoredata) { 250 int i; 251 int converter=SVAL(rparam,2); 252 253 count=SVAL(rparam,4); 254 p = rdata; 255 256 for (i = 0;i < count;i++, p += 26) { 257 char *sname = p; 258 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter; 259 const char *cmnt = comment_offset?(rdata+comment_offset):""; 260 pstring s1, s2; 261 262 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue; 263 264 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; 265 266 pull_ascii_pstring(s1, sname); 267 pull_ascii_pstring(s2, cmnt); 268 fn(s1, stype, s2, state); 269 } 270 } 271 } 272 273 SAFE_FREE(rparam); 274 SAFE_FREE(rdata); 275 276 if (count < 0) { 277 errno = cli_errno(cli); 278 } else { 279 if (!count) { 280 /* this is a very special case, when the domain master for the 281 work group isn't part of the work group itself, there is something 282 wild going on */ 283 errno = ENOENT; 284 } 285 } 286 287 return(count > 0); 288} 289 290 291 292/**************************************************************************** 293Send a SamOEMChangePassword command 294****************************************************************************/ 295BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password, 296 const char *old_password) 297{ 298 pstring param; 299 char data[532]; 300 char *p = param; 301 unsigned char old_pw_hash[16]; 302 unsigned char new_pw_hash[16]; 303 unsigned int data_len; 304 unsigned int param_len = 0; 305 char *rparam = NULL; 306 char *rdata = NULL; 307 unsigned int rprcnt, rdrcnt; 308 309 if (strlen(user) >= sizeof(fstring)-1) { 310 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user)); 311 return False; 312 } 313 314 SSVAL(p,0,214); /* SamOEMChangePassword command. */ 315 p += 2; 316 pstrcpy_base(p, "zsT", param); 317 p = skip_string(p,1); 318 pstrcpy_base(p, "B516B16", param); 319 p = skip_string(p,1); 320 pstrcpy_base(p,user, param); 321 p = skip_string(p,1); 322 SSVAL(p,0,532); 323 p += 2; 324 325 param_len = PTR_DIFF(p,param); 326 327 /* 328 * Get the Lanman hash of the old password, we 329 * use this as the key to make_oem_passwd_hash(). 330 */ 331 E_deshash(old_password, old_pw_hash); 332 333 encode_pw_buffer(data, new_password, STR_ASCII); 334 335#ifdef DEBUG_PASSWORD 336 DEBUG(100,("make_oem_passwd_hash\n")); 337 dump_data(100, data, 516); 338#endif 339 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516); 340 341 /* 342 * Now place the old password hash in the data. 343 */ 344 E_deshash(new_password, new_pw_hash); 345 346 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]); 347 348 data_len = 532; 349 350 if (cli_send_trans(cli,SMBtrans, 351 PIPE_LANMAN, /* name */ 352 0,0, /* fid, flags */ 353 NULL,0,0, /* setup, length, max */ 354 param,param_len,2, /* param, length, max */ 355 data,data_len,0 /* data, length, max */ 356 ) == False) { 357 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n", 358 user )); 359 return False; 360 } 361 362 if (!cli_receive_trans(cli,SMBtrans, 363 &rparam, &rprcnt, 364 &rdata, &rdrcnt)) { 365 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n", 366 user )); 367 return False; 368 } 369 370 if (rparam) 371 cli->rap_error = SVAL(rparam,0); 372 373 SAFE_FREE(rparam); 374 SAFE_FREE(rdata); 375 376 return (cli->rap_error == 0); 377} 378 379 380/**************************************************************************** 381send a qpathinfo call 382****************************************************************************/ 383BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 384 time_t *c_time, time_t *a_time, time_t *m_time, 385 size_t *size, uint16 *mode) 386{ 387 unsigned int data_len = 0; 388 unsigned int param_len = 0; 389 unsigned int rparam_len, rdata_len; 390 uint16 setup = TRANSACT2_QPATHINFO; 391 pstring param; 392 char *rparam=NULL, *rdata=NULL; 393 int count=8; 394 BOOL ret; 395 time_t (*date_fn)(void *); 396 char *p; 397 398 p = param; 399 memset(p, 0, 6); 400 SSVAL(p, 0, SMB_INFO_STANDARD); 401 p += 6; 402 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE); 403 404 param_len = PTR_DIFF(p, param); 405 406 do { 407 ret = (cli_send_trans(cli, SMBtrans2, 408 NULL, /* Name */ 409 -1, 0, /* fid, flags */ 410 &setup, 1, 0, /* setup, length, max */ 411 param, param_len, 10, /* param, length, max */ 412 NULL, data_len, cli->max_xmit /* data, length, max */ 413 ) && 414 cli_receive_trans(cli, SMBtrans2, 415 &rparam, &rparam_len, 416 &rdata, &rdata_len)); 417 if (!cli_is_dos_error(cli)) break; 418 if (!ret) { 419 /* we need to work around a Win95 bug - sometimes 420 it gives ERRSRV/ERRerror temprarily */ 421 uint8 eclass; 422 uint32 ecode; 423 cli_dos_error(cli, &eclass, &ecode); 424 if (eclass != ERRSRV || ecode != ERRerror) break; 425 smb_msleep(100); 426 } 427 } while (count-- && ret==False); 428 429 if (!ret || !rdata || rdata_len < 22) { 430 return False; 431 } 432 433 if (cli->win95) { 434 date_fn = make_unix_date; 435 } else { 436 date_fn = make_unix_date2; 437 } 438 439 if (c_time) { 440 *c_time = date_fn(rdata+0); 441 } 442 if (a_time) { 443 *a_time = date_fn(rdata+4); 444 } 445 if (m_time) { 446 *m_time = date_fn(rdata+8); 447 } 448 if (size) { 449 *size = IVAL(rdata, 12); 450 } 451 if (mode) { 452 *mode = SVAL(rdata,l1_attrFile); 453 } 454 455 SAFE_FREE(rdata); 456 SAFE_FREE(rparam); 457 return True; 458} 459 460/**************************************************************************** 461send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level 462****************************************************************************/ 463BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 464 time_t *c_time, time_t *a_time, time_t *m_time, 465 time_t *w_time, size_t *size, uint16 *mode, 466 SMB_INO_T *ino) 467{ 468 unsigned int data_len = 0; 469 unsigned int param_len = 0; 470 uint16 setup = TRANSACT2_QPATHINFO; 471 pstring param; 472 char *rparam=NULL, *rdata=NULL; 473 char *p; 474 475 p = param; 476 memset(p, 0, 6); 477 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO); 478 p += 6; 479 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE); 480 481 param_len = PTR_DIFF(p, param); 482 483 if (!cli_send_trans(cli, SMBtrans2, 484 NULL, /* name */ 485 -1, 0, /* fid, flags */ 486 &setup, 1, 0, /* setup, length, max */ 487 param, param_len, 10, /* param, length, max */ 488 NULL, data_len, cli->max_xmit /* data, length, max */ 489 )) { 490 return False; 491 } 492 493 if (!cli_receive_trans(cli, SMBtrans2, 494 &rparam, ¶m_len, 495 &rdata, &data_len)) { 496 return False; 497 } 498 499 if (!rdata || data_len < 22) { 500 return False; 501 } 502 503 if (c_time) { 504 *c_time = interpret_long_date(rdata+0) - cli->serverzone; 505 } 506 if (a_time) { 507 *a_time = interpret_long_date(rdata+8) - cli->serverzone; 508 } 509 if (m_time) { 510 *m_time = interpret_long_date(rdata+16) - cli->serverzone; 511 } 512 if (w_time) { 513 *w_time = interpret_long_date(rdata+24) - cli->serverzone; 514 } 515 if (mode) { 516 *mode = SVAL(rdata, 32); 517 } 518 if (size) { 519 *size = IVAL(rdata, 48); 520 } 521 if (ino) { 522 *ino = IVAL(rdata, 64); 523 } 524 525 SAFE_FREE(rdata); 526 SAFE_FREE(rparam); 527 return True; 528} 529 530 531/**************************************************************************** 532send a qfileinfo QUERY_FILE_NAME_INFO call 533****************************************************************************/ 534BOOL cli_qfilename(struct cli_state *cli, int fnum, 535 pstring name) 536{ 537 unsigned int data_len = 0; 538 unsigned int param_len = 0; 539 uint16 setup = TRANSACT2_QFILEINFO; 540 pstring param; 541 char *rparam=NULL, *rdata=NULL; 542 543 param_len = 4; 544 memset(param, 0, param_len); 545 SSVAL(param, 0, fnum); 546 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO); 547 548 if (!cli_send_trans(cli, SMBtrans2, 549 NULL, /* name */ 550 -1, 0, /* fid, flags */ 551 &setup, 1, 0, /* setup, length, max */ 552 param, param_len, 2, /* param, length, max */ 553 NULL, data_len, cli->max_xmit /* data, length, max */ 554 )) { 555 return False; 556 } 557 558 if (!cli_receive_trans(cli, SMBtrans2, 559 &rparam, ¶m_len, 560 &rdata, &data_len)) { 561 return False; 562 } 563 564 if (!rdata || data_len < 4) { 565 return False; 566 } 567 568 clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE); 569 570 return True; 571} 572 573 574/**************************************************************************** 575send a qfileinfo call 576****************************************************************************/ 577BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 578 uint16 *mode, size_t *size, 579 time_t *c_time, time_t *a_time, time_t *m_time, 580 time_t *w_time, SMB_INO_T *ino) 581{ 582 unsigned int data_len = 0; 583 unsigned int param_len = 0; 584 uint16 setup = TRANSACT2_QFILEINFO; 585 pstring param; 586 char *rparam=NULL, *rdata=NULL; 587 588 /* if its a win95 server then fail this - win95 totally screws it 589 up */ 590 if (cli->win95) return False; 591 592 param_len = 4; 593 594 memset(param, 0, param_len); 595 SSVAL(param, 0, fnum); 596 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO); 597 598 if (!cli_send_trans(cli, SMBtrans2, 599 NULL, /* name */ 600 -1, 0, /* fid, flags */ 601 &setup, 1, 0, /* setup, length, max */ 602 param, param_len, 2, /* param, length, max */ 603 NULL, data_len, cli->max_xmit /* data, length, max */ 604 )) { 605 return False; 606 } 607 608 if (!cli_receive_trans(cli, SMBtrans2, 609 &rparam, ¶m_len, 610 &rdata, &data_len)) { 611 return False; 612 } 613 614 if (!rdata || data_len < 68) { 615 return False; 616 } 617 618 if (c_time) { 619 *c_time = interpret_long_date(rdata+0) - cli->serverzone; 620 } 621 if (a_time) { 622 *a_time = interpret_long_date(rdata+8) - cli->serverzone; 623 } 624 if (m_time) { 625 *m_time = interpret_long_date(rdata+16) - cli->serverzone; 626 } 627 if (w_time) { 628 *w_time = interpret_long_date(rdata+24) - cli->serverzone; 629 } 630 if (mode) { 631 *mode = SVAL(rdata, 32); 632 } 633 if (size) { 634 *size = IVAL(rdata, 48); 635 } 636 if (ino) { 637 *ino = IVAL(rdata, 64); 638 } 639 640 SAFE_FREE(rdata); 641 SAFE_FREE(rparam); 642 return True; 643} 644 645 646/**************************************************************************** 647send a qpathinfo BASIC_INFO call 648****************************************************************************/ 649BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name, 650 SMB_STRUCT_STAT *sbuf, uint32 *attributes ) 651{ 652 unsigned int param_len = 0; 653 unsigned int data_len = 0; 654 uint16 setup = TRANSACT2_QPATHINFO; 655 char param[sizeof(pstring)+6]; 656 char *rparam=NULL, *rdata=NULL; 657 char *p; 658 pstring path; 659 int len; 660 661 /* send full paths to dfs root shares */ 662 663 if ( cli->dfsroot ) 664 pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name ); 665 else 666 pstrcpy( path, name ); 667 668 /* cleanup */ 669 670 len = strlen( path ); 671 if ( path[len] == '\\' ) 672 path[len] = '\0'; 673 674 p = param; 675 memset(p, 0, 6); 676 SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO); 677 p += 6; 678 p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE); 679 param_len = PTR_DIFF(p, param); 680 681 if (!cli_send_trans(cli, SMBtrans2, 682 NULL, /* name */ 683 -1, 0, /* fid, flags */ 684 &setup, 1, 0, /* setup, length, max */ 685 param, param_len, 2, /* param, length, max */ 686 NULL, 0, cli->max_xmit /* data, length, max */ 687 )) { 688 return False; 689 } 690 691 if (!cli_receive_trans(cli, SMBtrans2, 692 &rparam, ¶m_len, 693 &rdata, &data_len)) { 694 return False; 695 } 696 697 if (data_len < 36) { 698 SAFE_FREE(rdata); 699 SAFE_FREE(rparam); 700 return False; 701 } 702 703 sbuf->st_atime = interpret_long_date( rdata+8 ); 704 sbuf->st_mtime = interpret_long_date( rdata+16 ); 705 sbuf->st_ctime = interpret_long_date( rdata+24 ); 706 707 *attributes = IVAL( rdata, 32 ); 708 709 SAFE_FREE(rparam); 710 SAFE_FREE(rdata); 711 712 return True; 713} 714 715/**************************************************************************** 716send a qfileinfo call 717****************************************************************************/ 718 719BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen) 720{ 721 unsigned int data_len = 0; 722 unsigned int param_len = 0; 723 uint16 setup = TRANSACT2_QFILEINFO; 724 pstring param; 725 char *rparam=NULL, *rdata=NULL; 726 727 *poutdata = NULL; 728 *poutlen = 0; 729 730 /* if its a win95 server then fail this - win95 totally screws it 731 up */ 732 if (cli->win95) 733 return False; 734 735 param_len = 4; 736 737 memset(param, 0, param_len); 738 SSVAL(param, 0, fnum); 739 SSVAL(param, 2, level); 740 741 if (!cli_send_trans(cli, SMBtrans2, 742 NULL, /* name */ 743 -1, 0, /* fid, flags */ 744 &setup, 1, 0, /* setup, length, max */ 745 param, param_len, 2, /* param, length, max */ 746 NULL, data_len, cli->max_xmit /* data, length, max */ 747 )) { 748 return False; 749 } 750 751 if (!cli_receive_trans(cli, SMBtrans2, 752 &rparam, ¶m_len, 753 &rdata, &data_len)) { 754 return False; 755 } 756 757 *poutdata = memdup(rdata, data_len); 758 *poutlen = data_len; 759 760 SAFE_FREE(rdata); 761 SAFE_FREE(rparam); 762 return True; 763} 764 765 766 767/**************************************************************************** 768send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call 769****************************************************************************/ 770NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name) 771{ 772 unsigned int data_len = 0; 773 unsigned int param_len = 0; 774 uint16 setup = TRANSACT2_QPATHINFO; 775 pstring param; 776 char *rparam=NULL, *rdata=NULL; 777 int count=8; 778 char *p; 779 BOOL ret; 780 unsigned int len; 781 782 p = param; 783 memset(p, 0, 6); 784 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO); 785 p += 6; 786 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE); 787 788 param_len = PTR_DIFF(p, param); 789 790 do { 791 ret = (cli_send_trans(cli, SMBtrans2, 792 NULL, /* Name */ 793 -1, 0, /* fid, flags */ 794 &setup, 1, 0, /* setup, length, max */ 795 param, param_len, 10, /* param, length, max */ 796 NULL, data_len, cli->max_xmit /* data, length, max */ 797 ) && 798 cli_receive_trans(cli, SMBtrans2, 799 &rparam, ¶m_len, 800 &rdata, &data_len)); 801 if (!ret && cli_is_dos_error(cli)) { 802 /* we need to work around a Win95 bug - sometimes 803 it gives ERRSRV/ERRerror temprarily */ 804 uint8 eclass; 805 uint32 ecode; 806 cli_dos_error(cli, &eclass, &ecode); 807 if (eclass != ERRSRV || ecode != ERRerror) break; 808 smb_msleep(100); 809 } 810 } while (count-- && ret==False); 811 812 if (!ret || !rdata || data_len < 4) { 813 return NT_STATUS_UNSUCCESSFUL; 814 } 815 816 len = IVAL(rdata, 0); 817 818 if (len > data_len - 4) { 819 return NT_STATUS_INVALID_NETWORK_RESPONSE; 820 } 821 822 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE); 823 824 SAFE_FREE(rdata); 825 SAFE_FREE(rparam); 826 827 return NT_STATUS_OK; 828} 829