1/* 2 Samba Unix/Linux SMB client library 3 More client RAP (SMB Remote Procedure Calls) functions 4 Copyright (C) 2001 Steve French (sfrench@us.ibm.com) 5 Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com) 6 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21*/ 22 23/*****************************************************/ 24/* */ 25/* Additional RAP functionality */ 26/* */ 27/* RAP is the original SMB RPC, documented */ 28/* by Microsoft and X/Open in the 1990s and */ 29/* supported by most SMB/CIFS servers although */ 30/* it is unlikely that any one implementation */ 31/* supports all RAP command codes since some */ 32/* are quite obsolete and a few are specific */ 33/* to a particular network operating system */ 34/* */ 35/* Although it has largely been replaced */ 36/* for complex remote admistration and management */ 37/* (of servers) by the relatively newer */ 38/* DCE/RPC based remote API (which better handles */ 39/* large >64K data structures), there are many */ 40/* important administrative and resource location */ 41/* tasks and user tasks (e.g. password change) */ 42/* that are performed via RAP. */ 43/* */ 44/* Although a few of the RAP calls are implemented */ 45/* in the Samba client library already (clirap.c) */ 46/* the new ones are in clirap2.c for easy patching */ 47/* and integration and a corresponding header */ 48/* file, rap.h, has been created. */ 49/* */ 50/* This is based on data from the CIFS spec */ 51/* and the LAN Server and LAN Manager */ 52/* Programming Reference books and published */ 53/* RAP document and CIFS forum postings and */ 54/* lots of trial and error */ 55/* */ 56/* Function names changed from API_ (as they are */ 57/* in the CIFS specification) to RAP_ in order */ 58/* to avoid confusion with other API calls */ 59/* sent via DCE RPC */ 60/* */ 61/*****************************************************/ 62 63/*****************************************************/ 64/* */ 65/* cifsrap.c already includes support for: */ 66/* */ 67/* WshareEnum ( API number 0, level 1) */ 68/* NetServerEnum2 (API num 104, level 1) */ 69/* WWkstaUserLogon (132) */ 70/* SamOEMchgPasswordUser2_P (214) */ 71/* */ 72/* cifsprint.c already includes support for: */ 73/* */ 74/* WPrintJobEnum (API num 76, level 2) */ 75/* WPrintJobDel (API num 81) */ 76/* */ 77/*****************************************************/ 78 79#define NO_SYSLOG 80 81#include "includes.h" 82 83#define WORDSIZE 2 84#define DWORDSIZE 4 85 86#define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0) 87#define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0) 88#define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0) 89#define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0) 90#define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0) 91#define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0) 92#define GETRES(p) p ? SVAL(p,0) : -1 93/* put string s at p with max len n and increment p past string */ 94#define PUTSTRING(p,s,n) do {\ 95 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\ 96 p = skip_string(p,1);\ 97 } while(0) 98/* put string s and p, using fixed len l, and increment p by l */ 99#define PUTSTRINGF(p,s,l) do {\ 100 push_ascii(p,s?s:"",l,STR_TERMINATE);\ 101 p += l;\ 102 } while (0) 103/* put string pointer at p, supplying offset o from rdata r, store */ 104/* dword offset at p, increment p by 4 and o by length of s. This */ 105/* means on the first call, you must calc the offset yourself! */ 106#define PUTSTRINGP(p,s,r,o) do {\ 107 if (s) {\ 108 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\ 109 PUTDWORD(p,o);\ 110 o += strlen(s) + 1;\ 111 } else PUTDWORD(p,0);\ 112 }while(0); 113/* get asciiz string s from p, increment p past string */ 114#define GETSTRING(p,s) do {\ 115 pull_ascii_pstring(s,p);\ 116 p = skip_string(p,1);\ 117 } while(0) 118/* get fixed length l string s from p, increment p by l */ 119#define GETSTRINGF(p,s,l) do {\ 120 pull_ascii_pstring(s,p);\ 121 p += l;\ 122 } while(0) 123/* get string s from offset (obtained at p) from rdata r - converter c */ 124#define GETSTRINGP(p,s,r,c) do {\ 125 uint32 off;\ 126 GETDWORD(p,off);\ 127 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \ 128 pull_ascii_pstring(s, off?(r+off-c):"");\ 129 } while(0) 130 131static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt) 132{ 133 PUTWORD(param,apinum); 134 if (reqfmt) 135 PUTSTRING(param,reqfmt,0); 136 else 137 *param++ = (char) 0; 138 139 if (datafmt) 140 PUTSTRING(param,datafmt,0); 141 else 142 *param++ = (char) 0; 143 144 return param; 145} 146 147 148/**************************************************************************** 149 call a NetGroupDelete - delete user group from remote server 150****************************************************************************/ 151int cli_NetGroupDelete(struct cli_state *cli, const char *group_name ) 152{ 153 char *rparam = NULL; 154 char *rdata = NULL; 155 char *p; 156 unsigned int rdrcnt,rprcnt; 157 int res; 158 char param[WORDSIZE /* api number */ 159 +sizeof(RAP_NetGroupDel_REQ) /* parm string */ 160 +1 /* no ret string */ 161 +RAP_GROUPNAME_LEN /* group to del */ 162 +WORDSIZE]; /* reserved word */ 163 164 /* now send a SMBtrans command with api GroupDel */ 165 p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL); 166 PUTSTRING(p, group_name, RAP_GROUPNAME_LEN); 167 PUTWORD(p,0); /* reserved word MBZ on input */ 168 169 if (cli_api(cli, 170 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 171 NULL, 0, 200, /* data, length, maxlen */ 172 &rparam, &rprcnt, /* return params, length */ 173 &rdata, &rdrcnt)) /* return data, length */ 174 { 175 res = GETRES(rparam); 176 177 if (res == 0) { 178 /* nothing to do */ 179 } 180 else if ((res == 5) || (res == 65)) { 181 DEBUG(1, ("Access Denied\n")); 182 } 183 else if (res == 2220) { 184 DEBUG (1, ("Group does not exist\n")); 185 } 186 else { 187 DEBUG(4,("NetGroupDelete res=%d\n", res)); 188 } 189 } else { 190 res = -1; 191 DEBUG(4,("NetGroupDelete failed\n")); 192 } 193 194 SAFE_FREE(rparam); 195 SAFE_FREE(rdata); 196 197 return res; 198} 199 200/**************************************************************************** 201 call a NetGroupAdd - add user group to remote server 202****************************************************************************/ 203int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo ) 204{ 205 char *rparam = NULL; 206 char *rdata = NULL; 207 char *p; 208 unsigned int rdrcnt,rprcnt; 209 int res; 210 char param[WORDSIZE /* api number */ 211 +sizeof(RAP_NetGroupAdd_REQ) /* req string */ 212 +sizeof(RAP_GROUP_INFO_L1) /* return string */ 213 +WORDSIZE /* info level */ 214 +WORDSIZE]; /* reserved word */ 215 216 char data[1024]; 217 218 /* offset into data of free format strings. Will be updated */ 219 /* by PUTSTRINGP macro and end up with total data length. */ 220 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE; 221 222 /* now send a SMBtrans command with api WGroupAdd */ 223 224 p = make_header(param, RAP_WGroupAdd, 225 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1); 226 PUTWORD(p, 1); /* info level */ 227 PUTWORD(p, 0); /* reserved word 0 */ 228 229 p = data; 230 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN); 231 PUTBYTE(p, 0); /* pad byte 0 */ 232 PUTSTRINGP(p, grinfo->comment, data, soffset); 233 234 if (cli_api(cli, 235 param, sizeof(param), 1024, /* Param, length, maxlen */ 236 data, soffset, sizeof(data), /* data, length, maxlen */ 237 &rparam, &rprcnt, /* return params, length */ 238 &rdata, &rdrcnt)) /* return data, length */ 239 { 240 res = GETRES(rparam); 241 242 if (res == 0) { 243 /* nothing to do */ 244 } else if ((res == 5) || (res == 65)) { 245 DEBUG(1, ("Access Denied\n")); 246 } 247 else if (res == 2223) { 248 DEBUG (1, ("Group already exists\n")); 249 } 250 else { 251 DEBUG(4,("NetGroupAdd res=%d\n", res)); 252 } 253 } else { 254 res = -1; 255 DEBUG(4,("NetGroupAdd failed\n")); 256 } 257 258 SAFE_FREE(rparam); 259 SAFE_FREE(rdata); 260 261 return res; 262} 263 264/**************************************************************************** 265call a NetGroupEnum - try and list user groups on a different host 266****************************************************************************/ 267int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state) 268{ 269 char param[WORDSIZE /* api number */ 270 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */ 271 +sizeof(RAP_GROUP_INFO_L1) /* return string */ 272 +WORDSIZE /* info level */ 273 +WORDSIZE]; /* buffer size */ 274 char *p; 275 char *rparam = NULL; 276 char *rdata = NULL; 277 unsigned int rprcnt, rdrcnt; 278 int res = -1; 279 280 281 memset(param, '\0', sizeof(param)); 282 p = make_header(param, RAP_WGroupEnum, 283 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1); 284 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */ 285 PUTWORD(p,0xFFE0); /* Return buffer size */ 286 287 if (cli_api(cli, 288 param, PTR_DIFF(p,param),8, 289 NULL, 0, 0xFFE0 /* data area size */, 290 &rparam, &rprcnt, 291 &rdata, &rdrcnt)) { 292 res = GETRES(rparam); 293 cli->rap_error = res; 294 if(cli->rap_error == 234) 295 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n")); 296 else if (cli->rap_error != 0) { 297 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error)); 298 } 299 } 300 301 if (rdata) { 302 if (res == 0 || res == ERRmoredata) { 303 int i, converter, count; 304 305 p = rparam + WORDSIZE; /* skip result */ 306 GETWORD(p, converter); 307 GETWORD(p, count); 308 309 for (i=0,p=rdata;i<count;i++) { 310 pstring comment; 311 char groupname[RAP_GROUPNAME_LEN]; 312 313 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN); 314 p++; /* pad byte */ 315 GETSTRINGP(p, comment, rdata, converter); 316 317 fn(groupname, comment, cli); 318 } 319 } else { 320 DEBUG(4,("NetGroupEnum res=%d\n", res)); 321 } 322 } else { 323 DEBUG(4,("NetGroupEnum no data returned\n")); 324 } 325 326 SAFE_FREE(rparam); 327 SAFE_FREE(rdata); 328 329 return res; 330} 331 332int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name) 333{ 334 char *rparam = NULL; 335 char *rdata = NULL; 336 char *p; 337 unsigned int rdrcnt,rprcnt; 338 int res; 339 char param[WORDSIZE /* api number */ 340 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */ 341 +1 /* no ret string */ 342 +RAP_GROUPNAME_LEN /* group name */ 343 +RAP_USERNAME_LEN]; /* user to del */ 344 345 /* now send a SMBtrans command with api GroupMemberAdd */ 346 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL); 347 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN); 348 PUTSTRING(p,user_name,RAP_USERNAME_LEN); 349 350 if (cli_api(cli, 351 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 352 NULL, 0, 200, /* data, length, maxlen */ 353 &rparam, &rprcnt, /* return params, length */ 354 &rdata, &rdrcnt)) /* return data, length */ 355 { 356 res = GETRES(rparam); 357 358 switch(res) { 359 case 0: 360 break; 361 case 5: 362 case 65: 363 DEBUG(1, ("Access Denied\n")); 364 break; 365 case 50: 366 DEBUG(1, ("Not supported by server\n")); 367 break; 368 case 2220: 369 DEBUG(1, ("Group does not exist\n")); 370 break; 371 case 2221: 372 DEBUG(1, ("User does not exist\n")); 373 break; 374 case 2237: 375 DEBUG(1, ("User is not in group\n")); 376 break; 377 default: 378 DEBUG(4,("NetGroupDelUser res=%d\n", res)); 379 } 380 } else { 381 res = -1; 382 DEBUG(4,("NetGroupDelUser failed\n")); 383 } 384 385 SAFE_FREE(rparam); 386 SAFE_FREE(rdata); 387 388 return res; 389} 390 391int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name) 392{ 393 char *rparam = NULL; 394 char *rdata = NULL; 395 char *p; 396 unsigned int rdrcnt,rprcnt; 397 int res; 398 char param[WORDSIZE /* api number */ 399 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */ 400 +1 /* no ret string */ 401 +RAP_GROUPNAME_LEN /* group name */ 402 +RAP_USERNAME_LEN]; /* user to add */ 403 404 /* now send a SMBtrans command with api GroupMemberAdd */ 405 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL); 406 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN); 407 PUTSTRING(p,user_name,RAP_USERNAME_LEN); 408 409 if (cli_api(cli, 410 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 411 NULL, 0, 200, /* data, length, maxlen */ 412 &rparam, &rprcnt, /* return params, length */ 413 &rdata, &rdrcnt)) /* return data, length */ 414 { 415 res = GETRES(rparam); 416 417 switch(res) { 418 case 0: 419 break; 420 case 5: 421 case 65: 422 DEBUG(1, ("Access Denied\n")); 423 break; 424 case 50: 425 DEBUG(1, ("Not supported by server\n")); 426 break; 427 case 2220: 428 DEBUG(1, ("Group does not exist\n")); 429 break; 430 case 2221: 431 DEBUG(1, ("User does not exist\n")); 432 break; 433 default: 434 DEBUG(4,("NetGroupAddUser res=%d\n", res)); 435 } 436 } else { 437 res = -1; 438 DEBUG(4,("NetGroupAddUser failed\n")); 439 } 440 441 SAFE_FREE(rparam); 442 SAFE_FREE(rdata); 443 444 return res; 445} 446 447 448int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state ) 449{ 450 char *rparam = NULL; 451 char *rdata = NULL; 452 char *p; 453 unsigned int rdrcnt,rprcnt; 454 int res = -1; 455 char param[WORDSIZE /* api number */ 456 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */ 457 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */ 458 +RAP_GROUPNAME_LEN /* group name */ 459 +WORDSIZE /* info level */ 460 +WORDSIZE]; /* buffer size */ 461 462 /* now send a SMBtrans command with api GroupGetUsers */ 463 p = make_header(param, RAP_WGroupGetUsers, 464 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0); 465 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1); 466 PUTWORD(p,0); /* info level 0 */ 467 PUTWORD(p,0xFFE0); /* return buffer size */ 468 469 if (cli_api(cli, 470 param, PTR_DIFF(p,param),PTR_DIFF(p,param), 471 NULL, 0, CLI_BUFFER_SIZE, 472 &rparam, &rprcnt, 473 &rdata, &rdrcnt)) { 474 res = GETRES(rparam); 475 cli->rap_error = res; 476 if (res != 0) { 477 DEBUG(1,("NetGroupGetUsers gave error %d\n", res)); 478 } 479 } 480 if (rdata) { 481 if (res == 0 || res == ERRmoredata) { 482 int i, converter, count; 483 fstring username; 484 p = rparam +WORDSIZE; 485 GETWORD(p, converter); 486 GETWORD(p, count); 487 488 for (i=0,p=rdata; i<count; i++) { 489 GETSTRINGF(p, username, RAP_USERNAME_LEN); 490 fn(username, state); 491 } 492 } else { 493 DEBUG(4,("NetGroupGetUsers res=%d\n", res)); 494 } 495 } else { 496 DEBUG(4,("NetGroupGetUsers no data returned\n")); 497 } 498 SAFE_FREE(rdata); 499 SAFE_FREE(rparam); 500 return res; 501} 502 503int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state ) 504{ 505 char *rparam = NULL; 506 char *rdata = NULL; 507 char *p; 508 unsigned int rdrcnt,rprcnt; 509 int res = -1; 510 char param[WORDSIZE /* api number */ 511 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */ 512 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */ 513 +RAP_USERNAME_LEN /* user name */ 514 +WORDSIZE /* info level */ 515 +WORDSIZE]; /* buffer size */ 516 517 /* now send a SMBtrans command with api GroupGetUsers */ 518 p = make_header(param, RAP_WUserGetGroups, 519 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0); 520 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1); 521 PUTWORD(p,0); /* info level 0 */ 522 PUTWORD(p,0xFFE0); /* return buffer size */ 523 524 if (cli_api(cli, 525 param, PTR_DIFF(p,param),PTR_DIFF(p,param), 526 NULL, 0, CLI_BUFFER_SIZE, 527 &rparam, &rprcnt, 528 &rdata, &rdrcnt)) { 529 res = GETRES(rparam); 530 cli->rap_error = res; 531 if (res != 0) { 532 DEBUG(1,("NetUserGetGroups gave error %d\n", res)); 533 } 534 } 535 if (rdata) { 536 if (res == 0 || res == ERRmoredata) { 537 int i, converter, count; 538 fstring groupname; 539 p = rparam +WORDSIZE; 540 GETWORD(p, converter); 541 GETWORD(p, count); 542 543 for (i=0,p=rdata; i<count; i++) { 544 GETSTRINGF(p, groupname, RAP_USERNAME_LEN); 545 fn(groupname, state); 546 } 547 } else { 548 DEBUG(4,("NetUserGetGroups res=%d\n", res)); 549 } 550 } else { 551 DEBUG(4,("NetUserGetGroups no data returned\n")); 552 } 553 SAFE_FREE(rdata); 554 SAFE_FREE(rparam); 555 return res; 556} 557 558 559/**************************************************************************** 560 call a NetUserDelete - delete user from remote server 561****************************************************************************/ 562int cli_NetUserDelete(struct cli_state *cli, const char * user_name ) 563{ 564 char *rparam = NULL; 565 char *rdata = NULL; 566 char *p; 567 unsigned int rdrcnt,rprcnt; 568 int res; 569 char param[WORDSIZE /* api number */ 570 +sizeof(RAP_NetGroupDel_REQ) /* parm string */ 571 +1 /* no ret string */ 572 +RAP_USERNAME_LEN /* user to del */ 573 +WORDSIZE]; /* reserved word */ 574 575 /* now send a SMBtrans command with api UserDel */ 576 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL); 577 PUTSTRING(p, user_name, RAP_USERNAME_LEN); 578 PUTWORD(p,0); /* reserved word MBZ on input */ 579 580 if (cli_api(cli, 581 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 582 NULL, 0, 200, /* data, length, maxlen */ 583 &rparam, &rprcnt, /* return params, length */ 584 &rdata, &rdrcnt)) /* return data, length */ 585 { 586 res = GETRES(rparam); 587 588 if (res == 0) { 589 /* nothing to do */ 590 } 591 else if ((res == 5) || (res == 65)) { 592 DEBUG(1, ("Access Denied\n")); 593 } 594 else if (res == 2221) { 595 DEBUG (1, ("User does not exist\n")); 596 } 597 else { 598 DEBUG(4,("NetUserDelete res=%d\n", res)); 599 } 600 } else { 601 res = -1; 602 DEBUG(4,("NetUserDelete failed\n")); 603 } 604 605 SAFE_FREE(rparam); 606 SAFE_FREE(rdata); 607 608 return res; 609} 610 611/**************************************************************************** 612 call a NetUserAdd - add user to remote server 613****************************************************************************/ 614int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo ) 615{ 616 617 618 619 char *rparam = NULL; 620 char *rdata = NULL; 621 char *p; 622 unsigned int rdrcnt,rprcnt; 623 int res; 624 char param[WORDSIZE /* api number */ 625 +sizeof(RAP_NetUserAdd2_REQ) /* req string */ 626 +sizeof(RAP_USER_INFO_L1) /* data string */ 627 +WORDSIZE /* info level */ 628 +WORDSIZE /* buffer length */ 629 +WORDSIZE]; /* reserved */ 630 631 char data[1024]; 632 /* offset into data of free format strings. Will be updated */ 633 /* by PUTSTRINGP macro and end up with total data length. */ 634 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */ 635 + RAP_UPASSWD_LEN /* password */ 636 + DWORDSIZE /* password age */ 637 + WORDSIZE /* privilege */ 638 + DWORDSIZE /* home dir ptr */ 639 + DWORDSIZE /* comment ptr */ 640 + WORDSIZE /* flags */ 641 + DWORDSIZE; /* login script ptr*/ 642 643 /* now send a SMBtrans command with api NetUserAdd */ 644 p = make_header(param, RAP_WUserAdd2, 645 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1); 646 PUTWORD(p, 1); /* info level */ 647 648 PUTWORD(p, 0); /* pwencrypt */ 649 if(userinfo->passwrd) 650 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN)); 651 else 652 PUTWORD(p, 0); /* password length */ 653 654 p = data; 655 memset(data, '\0', soffset); 656 657 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN); 658 PUTBYTE(p, 0); /* pad byte 0 */ 659 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN); 660 PUTDWORD(p, 0); /* pw age - n.a. on user add */ 661 PUTWORD(p, userinfo->priv); 662 PUTSTRINGP(p, userinfo->home_dir, data, soffset); 663 PUTSTRINGP(p, userinfo->comment, data, soffset); 664 PUTWORD(p, userinfo->userflags); 665 PUTSTRINGP(p, userinfo->logon_script, data, soffset); 666 667 if (cli_api(cli, 668 param, sizeof(param), 1024, /* Param, length, maxlen */ 669 data, soffset, sizeof(data), /* data, length, maxlen */ 670 &rparam, &rprcnt, /* return params, length */ 671 &rdata, &rdrcnt)) /* return data, length */ 672 { 673 res = GETRES(rparam); 674 675 if (res == 0) { 676 /* nothing to do */ 677 } 678 else if ((res == 5) || (res == 65)) { 679 DEBUG(1, ("Access Denied\n")); 680 } 681 else if (res == 2224) { 682 DEBUG (1, ("User already exists\n")); 683 } 684 else { 685 DEBUG(4,("NetUserAdd res=%d\n", res)); 686 } 687 } else { 688 res = -1; 689 DEBUG(4,("NetUserAdd failed\n")); 690 } 691 692 SAFE_FREE(rparam); 693 SAFE_FREE(rdata); 694 695 return res; 696} 697 698/**************************************************************************** 699call a NetUserEnum - try and list users on a different host 700****************************************************************************/ 701int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state) 702{ 703 char param[WORDSIZE /* api number */ 704 +sizeof(RAP_NetUserEnum_REQ) /* parm string */ 705 +sizeof(RAP_USER_INFO_L1) /* return string */ 706 +WORDSIZE /* info level */ 707 +WORDSIZE]; /* buffer size */ 708 char *p; 709 char *rparam = NULL; 710 char *rdata = NULL; 711 unsigned int rprcnt, rdrcnt; 712 int res = -1; 713 714 715 memset(param, '\0', sizeof(param)); 716 p = make_header(param, RAP_WUserEnum, 717 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1); 718 PUTWORD(p,1); /* Info level 1 */ 719 PUTWORD(p,0xFF00); /* Return buffer size */ 720 721/* BB Fix handling of large numbers of users to be returned */ 722 if (cli_api(cli, 723 param, PTR_DIFF(p,param),8, 724 NULL, 0, CLI_BUFFER_SIZE, 725 &rparam, &rprcnt, 726 &rdata, &rdrcnt)) { 727 res = GETRES(rparam); 728 cli->rap_error = res; 729 if (cli->rap_error != 0) { 730 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error)); 731 } 732 } 733 if (rdata) { 734 if (res == 0 || res == ERRmoredata) { 735 int i, converter, count; 736 char username[RAP_USERNAME_LEN]; 737 char userpw[RAP_UPASSWD_LEN]; 738 pstring comment, homedir, logonscript; 739 int pwage, priv, flags; 740 741 p = rparam + WORDSIZE; /* skip result */ 742 GETWORD(p, converter); 743 GETWORD(p, count); 744 745 for (i=0,p=rdata;i<count;i++) { 746 GETSTRINGF(p, username, RAP_USERNAME_LEN); 747 p++; /* pad byte */ 748 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN); 749 GETDWORD(p, pwage); /* password age */ 750 GETWORD(p, priv); /* 0=guest, 1=user, 2=admin */ 751 GETSTRINGP(p, homedir, rdata, converter); 752 GETSTRINGP(p, comment, rdata, converter); 753 GETWORD(p, flags); 754 GETSTRINGP(p, logonscript, rdata, converter); 755 756 fn(username, comment, homedir, logonscript, cli); 757 } 758 } else { 759 DEBUG(4,("NetUserEnum res=%d\n", res)); 760 } 761 } else { 762 DEBUG(4,("NetUserEnum no data returned\n")); 763 } 764 765 SAFE_FREE(rparam); 766 SAFE_FREE(rdata); 767 768 return res; 769} 770 771/**************************************************************************** 772 call a NetFileClose2 - close open file on another session to server 773****************************************************************************/ 774int cli_NetFileClose(struct cli_state *cli, uint32 file_id ) 775{ 776 char *rparam = NULL; 777 char *rdata = NULL; 778 char *p; 779 unsigned int rdrcnt,rprcnt; 780 char param[WORDSIZE /* api number */ 781 +sizeof(RAP_WFileClose2_REQ) /* req string */ 782 +1 /* no ret string */ 783 +DWORDSIZE]; /* file ID */ 784 int res = -1; 785 786 /* now send a SMBtrans command with api RNetShareEnum */ 787 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL); 788 PUTDWORD(p, file_id); 789 790 if (cli_api(cli, 791 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 792 NULL, 0, 200, /* data, length, maxlen */ 793 &rparam, &rprcnt, /* return params, length */ 794 &rdata, &rdrcnt)) /* return data, length */ 795 { 796 res = GETRES(rparam); 797 798 if (res == 0) { 799 /* nothing to do */ 800 } else if (res == 2314){ 801 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n")); 802 } else { 803 DEBUG(4,("NetFileClose2 res=%d\n", res)); 804 } 805 } else { 806 res = -1; 807 DEBUG(4,("NetFileClose2 failed\n")); 808 } 809 810 SAFE_FREE(rparam); 811 SAFE_FREE(rdata); 812 813 return res; 814} 815 816/**************************************************************************** 817call a NetFileGetInfo - get information about server file opened from other 818 workstation 819****************************************************************************/ 820int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32)) 821{ 822 char *rparam = NULL; 823 char *rdata = NULL; 824 char *p; 825 unsigned int rdrcnt,rprcnt; 826 int res; 827 char param[WORDSIZE /* api number */ 828 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */ 829 +sizeof(RAP_FILE_INFO_L3) /* return string */ 830 +DWORDSIZE /* file ID */ 831 +WORDSIZE /* info level */ 832 +WORDSIZE]; /* buffer size */ 833 834 /* now send a SMBtrans command with api RNetShareEnum */ 835 p = make_header(param, RAP_WFileGetInfo2, 836 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3); 837 PUTDWORD(p, file_id); 838 PUTWORD(p, 3); /* info level */ 839 PUTWORD(p, 0x1000); /* buffer size */ 840 if (cli_api(cli, 841 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 842 NULL, 0, 0x1000, /* data, length, maxlen */ 843 &rparam, &rprcnt, /* return params, length */ 844 &rdata, &rdrcnt)) /* return data, length */ 845 { 846 res = GETRES(rparam); 847 if (res == 0 || res == ERRmoredata) { 848 int converter,id, perms, locks; 849 pstring fpath, fuser; 850 851 p = rparam + WORDSIZE; /* skip result */ 852 GETWORD(p, converter); 853 854 p = rdata; 855 GETDWORD(p, id); 856 GETWORD(p, perms); 857 GETWORD(p, locks); 858 GETSTRINGP(p, fpath, rdata, converter); 859 GETSTRINGP(p, fuser, rdata, converter); 860 861 fn(fpath, fuser, perms, locks, id); 862 } else { 863 DEBUG(4,("NetFileGetInfo2 res=%d\n", res)); 864 } 865 } else { 866 res = -1; 867 DEBUG(4,("NetFileGetInfo2 failed\n")); 868 } 869 870 SAFE_FREE(rparam); 871 SAFE_FREE(rdata); 872 873 return res; 874} 875 876/**************************************************************************** 877* Call a NetFileEnum2 - list open files on an SMB server 878* 879* PURPOSE: Remotes a NetFileEnum API call to the current server or target 880* server listing the files open via the network (and their 881* corresponding open instance ids) 882* 883* Dependencies: none 884* 885* Parameters: 886* cli - pointer to cli_state structure 887* user - if present, return only files opened by this remote user 888* base_path - if present, return only files opened below this 889* base path 890* fn - display function to invoke for each entry in the result 891* 892* 893* Returns: 894* True - success 895* False - failure 896* 897****************************************************************************/ 898int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32)) 899{ 900 char *rparam = NULL; 901 char *rdata = NULL; 902 char *p; 903 unsigned int rdrcnt,rprcnt; 904 char param[WORDSIZE /* api number */ 905 +sizeof(RAP_WFileEnum2_REQ) /* req string */ 906 +sizeof(RAP_FILE_INFO_L3) /* return string */ 907 +256 /* base path (opt) */ 908 +RAP_USERNAME_LEN /* user name (opt) */ 909 +WORDSIZE /* info level */ 910 +WORDSIZE /* buffer size */ 911 +DWORDSIZE /* resume key ? */ 912 +DWORDSIZE]; /* resume key ? */ 913 int count = -1; 914 915 /* now send a SMBtrans command with api RNetShareEnum */ 916 p = make_header(param, RAP_WFileEnum2, 917 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3); 918 919 PUTSTRING(p, base_path, 256); 920 PUTSTRING(p, user, RAP_USERNAME_LEN); 921 PUTWORD(p, 3); /* info level */ 922 PUTWORD(p, 0xFF00); /* buffer size */ 923 PUTDWORD(p, 0); /* zero out the resume key */ 924 PUTDWORD(p, 0); /* or is this one the resume key? */ 925 926 if (cli_api(cli, 927 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 928 NULL, 0, 0xFF00, /* data, length, maxlen */ 929 &rparam, &rprcnt, /* return params, length */ 930 &rdata, &rdrcnt)) /* return data, length */ 931 { 932 int res = GETRES(rparam); 933 934 if (res == 0 || res == ERRmoredata) { 935 int converter, i; 936 937 p = rparam + WORDSIZE; /* skip result */ 938 GETWORD(p, converter); 939 GETWORD(p, count); 940 941 p = rdata; 942 for (i=0; i<count; i++) { 943 int id, perms, locks; 944 pstring fpath, fuser; 945 946 GETDWORD(p, id); 947 GETWORD(p, perms); 948 GETWORD(p, locks); 949 GETSTRINGP(p, fpath, rdata, converter); 950 GETSTRINGP(p, fuser, rdata, converter); 951 952 fn(fpath, fuser, perms, locks, id); 953 } /* BB fix ERRmoredata case to send resume request */ 954 } else { 955 DEBUG(4,("NetFileEnum2 res=%d\n", res)); 956 } 957 } else { 958 DEBUG(4,("NetFileEnum2 failed\n")); 959 } 960 961 SAFE_FREE(rparam); 962 SAFE_FREE(rdata); 963 964 return count; 965} 966 967/**************************************************************************** 968 call a NetShareAdd - share/export directory on remote server 969****************************************************************************/ 970int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo ) 971{ 972 char *rparam = NULL; 973 char *rdata = NULL; 974 char *p; 975 unsigned int rdrcnt,rprcnt; 976 int res; 977 char param[WORDSIZE /* api number */ 978 +sizeof(RAP_WShareAdd_REQ) /* req string */ 979 +sizeof(RAP_SHARE_INFO_L2) /* return string */ 980 +WORDSIZE /* info level */ 981 +WORDSIZE]; /* reserved word */ 982 char data[1024]; 983 /* offset to free format string section following fixed length data. */ 984 /* will be updated by PUTSTRINGP macro and will end up with total len */ 985 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */ 986 + WORDSIZE /* share type */ 987 + DWORDSIZE /* comment pointer */ 988 + WORDSIZE /* permissions */ 989 + WORDSIZE /* max users */ 990 + WORDSIZE /* active users */ 991 + DWORDSIZE /* share path */ 992 + RAP_SPASSWD_LEN + 1; /* share password + pad */ 993 994 memset(param,'\0',sizeof(param)); 995 /* now send a SMBtrans command with api RNetShareAdd */ 996 p = make_header(param, RAP_WshareAdd, 997 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2); 998 PUTWORD(p, 2); /* info level */ 999 PUTWORD(p, 0); /* reserved word 0 */ 1000 1001 p = data; 1002 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN); 1003 PUTBYTE(p, 0); /* pad byte 0 */ 1004 1005 PUTWORD(p, sinfo->share_type); 1006 PUTSTRINGP(p, sinfo->comment, data, soffset); 1007 PUTWORD(p, sinfo->perms); 1008 PUTWORD(p, sinfo->maximum_users); 1009 PUTWORD(p, sinfo->active_users); 1010 PUTSTRINGP(p, sinfo->path, data, soffset); 1011 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN); 1012 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */ 1013 1014 if (cli_api(cli, 1015 param, sizeof(param), 1024, /* Param, length, maxlen */ 1016 data, soffset, sizeof(data), /* data, length, maxlen */ 1017 &rparam, &rprcnt, /* return params, length */ 1018 &rdata, &rdrcnt)) /* return data, length */ 1019 { 1020 res = rparam? SVAL(rparam,0) : -1; 1021 1022 if (res == 0) { 1023 /* nothing to do */ 1024 } 1025 else { 1026 DEBUG(4,("NetShareAdd res=%d\n", res)); 1027 } 1028 } else { 1029 res = -1; 1030 DEBUG(4,("NetShareAdd failed\n")); 1031 } 1032 1033 SAFE_FREE(rparam); 1034 SAFE_FREE(rdata); 1035 1036 return res; 1037} 1038/**************************************************************************** 1039 call a NetShareDelete - unshare exported directory on remote server 1040****************************************************************************/ 1041int cli_NetShareDelete(struct cli_state *cli, const char * share_name ) 1042{ 1043 char *rparam = NULL; 1044 char *rdata = NULL; 1045 char *p; 1046 unsigned int rdrcnt,rprcnt; 1047 int res; 1048 char param[WORDSIZE /* api number */ 1049 +sizeof(RAP_WShareDel_REQ) /* req string */ 1050 +1 /* no ret string */ 1051 +RAP_SHARENAME_LEN /* share to del */ 1052 +WORDSIZE]; /* reserved word */ 1053 1054 1055 /* now send a SMBtrans command with api RNetShareDelete */ 1056 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL); 1057 PUTSTRING(p,share_name,RAP_SHARENAME_LEN); 1058 PUTWORD(p,0); /* reserved word MBZ on input */ 1059 1060 if (cli_api(cli, 1061 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 1062 NULL, 0, 200, /* data, length, maxlen */ 1063 &rparam, &rprcnt, /* return params, length */ 1064 &rdata, &rdrcnt)) /* return data, length */ 1065 { 1066 res = GETRES(rparam); 1067 1068 if (res == 0) { 1069 /* nothing to do */ 1070 } 1071 else { 1072 DEBUG(4,("NetShareDelete res=%d\n", res)); 1073 } 1074 } else { 1075 res = -1; 1076 DEBUG(4,("NetShareDelete failed\n")); 1077 } 1078 1079 SAFE_FREE(rparam); 1080 SAFE_FREE(rdata); 1081 1082 return res; 1083} 1084/************************************************************************* 1085* 1086* Function Name: cli_get_pdc_name 1087* 1088* PURPOSE: Remotes a NetServerEnum API call to the current server 1089* requesting the name of a server matching the server 1090* type of SV_TYPE_DOMAIN_CTRL (PDC). 1091* 1092* Dependencies: none 1093* 1094* Parameters: 1095* cli - pointer to cli_state structure 1096* workgroup - pointer to string containing name of domain 1097* pdc_name - pointer to string that will contain PDC name 1098* on successful return 1099* 1100* Returns: 1101* True - success 1102* False - failure 1103* 1104************************************************************************/ 1105BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name) 1106{ 1107 char *rparam = NULL; 1108 char *rdata = NULL; 1109 unsigned int rdrcnt,rprcnt; 1110 char *p; 1111 char param[WORDSIZE /* api number */ 1112 +sizeof(RAP_NetServerEnum2_REQ) /* req string */ 1113 +sizeof(RAP_SERVER_INFO_L1) /* return string */ 1114 +WORDSIZE /* info level */ 1115 +WORDSIZE /* buffer size */ 1116 +DWORDSIZE /* server type */ 1117 +RAP_MACHNAME_LEN]; /* workgroup */ 1118 int count = -1; 1119 1120 *pdc_name = '\0'; 1121 1122 /* send a SMBtrans command with api NetServerEnum */ 1123 p = make_header(param, RAP_NetServerEnum2, 1124 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1); 1125 PUTWORD(p, 1); /* info level */ 1126 PUTWORD(p, CLI_BUFFER_SIZE); 1127 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL); 1128 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN); 1129 1130 if (cli_api(cli, 1131 param, PTR_DIFF(p,param), 8, /* params, length, max */ 1132 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 1133 &rparam, &rprcnt, /* return params, return size */ 1134 &rdata, &rdrcnt /* return data, return size */ 1135 )) { 1136 cli->rap_error = GETRES(rparam); 1137 1138 /* 1139 * We only really care to copy a name if the 1140 * API succeeded and we got back a name. 1141 */ 1142 if (cli->rap_error == 0) { 1143 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */ 1144 GETWORD(p, count); 1145 p = rdata; 1146 1147 if (count > 0) 1148 GETSTRING(p, pdc_name); 1149 } 1150 else { 1151 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. " 1152 "Error was : %s.\n", cli->desthost, cli_errstr(cli) )); 1153 } 1154 } 1155 1156 SAFE_FREE(rparam); 1157 SAFE_FREE(rdata); 1158 1159 return(count > 0); 1160} 1161 1162 1163/************************************************************************* 1164* 1165* Function Name: cli_get_server_domain 1166* 1167* PURPOSE: Remotes a NetWkstaGetInfo API call to the current server 1168* requesting wksta_info_10 level information to determine 1169* the domain the server belongs to. On success, this 1170* routine sets the server_domain field in the cli_state structure 1171* to the server's domain name. 1172* 1173* Dependencies: none 1174* 1175* Parameters: 1176* cli - pointer to cli_state structure 1177* 1178* Returns: 1179* True - success 1180* False - failure 1181* 1182* Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum() 1183* 1184************************************************************************/ 1185BOOL cli_get_server_domain(struct cli_state *cli) 1186{ 1187 char *rparam = NULL; 1188 char *rdata = NULL; 1189 unsigned int rdrcnt,rprcnt; 1190 char *p; 1191 char param[WORDSIZE /* api number */ 1192 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */ 1193 +sizeof(RAP_WKSTA_INFO_L10) /* return string */ 1194 +WORDSIZE /* info level */ 1195 +WORDSIZE]; /* buffer size */ 1196 int res = -1; 1197 1198 /* send a SMBtrans command with api NetWkstaGetInfo */ 1199 p = make_header(param, RAP_WWkstaGetInfo, 1200 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10); 1201 PUTWORD(p, 10); /* info level */ 1202 PUTWORD(p, CLI_BUFFER_SIZE); 1203 1204 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */ 1205 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 1206 &rparam, &rprcnt, /* return params, return size */ 1207 &rdata, &rdrcnt)) { /* return data, return size */ 1208 res = GETRES(rparam); 1209 p = rdata; 1210 1211 if (res == 0) { 1212 int converter; 1213 1214 p = rparam + WORDSIZE; 1215 GETWORD(p, converter); 1216 1217 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */ 1218 GETSTRINGP(p, cli->server_domain, rdata, converter); 1219 } 1220 } 1221 1222 SAFE_FREE(rparam); 1223 SAFE_FREE(rdata); 1224 1225 return(res == 0); 1226} 1227 1228 1229/************************************************************************* 1230* 1231* Function Name: cli_get_server_type 1232* 1233* PURPOSE: Remotes a NetServerGetInfo API call to the current server 1234* requesting server_info_1 level information to retrieve 1235* the server type. 1236* 1237* Dependencies: none 1238* 1239* Parameters: 1240* cli - pointer to cli_state structure 1241* pstype - pointer to uint32 to contain returned server type 1242* 1243* Returns: 1244* True - success 1245* False - failure 1246* 1247* Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum() 1248* 1249************************************************************************/ 1250BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype) 1251{ 1252 char *rparam = NULL; 1253 char *rdata = NULL; 1254 unsigned int rdrcnt,rprcnt; 1255 char *p; 1256 char param[WORDSIZE /* api number */ 1257 +sizeof(RAP_WserverGetInfo_REQ) /* req string */ 1258 +sizeof(RAP_SERVER_INFO_L1) /* return string */ 1259 +WORDSIZE /* info level */ 1260 +WORDSIZE]; /* buffer size */ 1261 int res = -1; 1262 1263 /* send a SMBtrans command with api NetServerGetInfo */ 1264 p = make_header(param, RAP_WserverGetInfo, 1265 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1); 1266 PUTWORD(p, 1); /* info level */ 1267 PUTWORD(p, CLI_BUFFER_SIZE); 1268 1269 if (cli_api(cli, 1270 param, PTR_DIFF(p,param), 8, /* params, length, max */ 1271 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 1272 &rparam, &rprcnt, /* return params, return size */ 1273 &rdata, &rdrcnt /* return data, return size */ 1274 )) { 1275 1276 res = GETRES(rparam); 1277 1278 if (res == 0 || res == ERRmoredata) { 1279 p = rdata; 1280 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; 1281 } 1282 } 1283 1284 SAFE_FREE(rparam); 1285 SAFE_FREE(rdata); 1286 1287 return(res == 0 || res == ERRmoredata); 1288} 1289 1290 1291/************************************************************************* 1292* 1293* Function Name: cli_ns_check_server_type 1294* 1295* PURPOSE: Remotes a NetServerEnum2 API call to the current server 1296* requesting server_info_0 level information of machines 1297* matching the given server type. If the returned server 1298* list contains the machine name contained in cli->desthost 1299* then we conclude the server type checks out. This routine 1300* is useful to retrieve list of server's of a certain 1301* type when all you have is a null session connection and 1302* can't remote API calls such as NetWkstaGetInfo or 1303* NetServerGetInfo. 1304* 1305* Dependencies: none 1306* 1307* Parameters: 1308* cli - pointer to cli_state structure 1309* workgroup - pointer to string containing domain 1310* stype - server type 1311* 1312* Returns: 1313* True - success 1314* False - failure 1315* 1316************************************************************************/ 1317BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype) 1318{ 1319 char *rparam = NULL; 1320 char *rdata = NULL; 1321 unsigned int rdrcnt,rprcnt; 1322 char *p; 1323 char param[WORDSIZE /* api number */ 1324 +sizeof(RAP_NetServerEnum2_REQ) /* req string */ 1325 +sizeof(RAP_SERVER_INFO_L0) /* return string */ 1326 +WORDSIZE /* info level */ 1327 +WORDSIZE /* buffer size */ 1328 +DWORDSIZE /* server type */ 1329 +RAP_MACHNAME_LEN]; /* workgroup */ 1330 BOOL found_server = False; 1331 int res = -1; 1332 1333 /* send a SMBtrans command with api NetServerEnum */ 1334 p = make_header(param, RAP_NetServerEnum2, 1335 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0); 1336 PUTWORD(p, 0); /* info level 0 */ 1337 PUTWORD(p, CLI_BUFFER_SIZE); 1338 PUTDWORD(p, stype); 1339 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN); 1340 1341 if (cli_api(cli, 1342 param, PTR_DIFF(p,param), 8, /* params, length, max */ 1343 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 1344 &rparam, &rprcnt, /* return params, return size */ 1345 &rdata, &rdrcnt /* return data, return size */ 1346 )) { 1347 1348 res = GETRES(rparam); 1349 cli->rap_error = res; 1350 1351 if (res == 0 || res == ERRmoredata) { 1352 int i, converter, count; 1353 1354 p = rparam + WORDSIZE; 1355 GETWORD(p, converter); 1356 GETWORD(p, count); 1357 1358 p = rdata; 1359 for (i = 0;i < count;i++, p += 16) { 1360 char ret_server[RAP_MACHNAME_LEN]; 1361 1362 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN); 1363 if (strequal(ret_server, cli->desthost)) { 1364 found_server = True; 1365 break; 1366 } 1367 } 1368 } 1369 else { 1370 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. " 1371 "Error was : %s.\n", cli->desthost, cli_errstr(cli) )); 1372 } 1373 } 1374 1375 SAFE_FREE(rparam); 1376 SAFE_FREE(rdata); 1377 1378 return found_server; 1379 } 1380 1381 1382/**************************************************************************** 1383 perform a NetWkstaUserLogoff 1384****************************************************************************/ 1385BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation) 1386{ 1387 char *rparam = NULL; 1388 char *rdata = NULL; 1389 char *p; 1390 unsigned int rdrcnt,rprcnt; 1391 char param[WORDSIZE /* api number */ 1392 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */ 1393 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */ 1394 +RAP_USERNAME_LEN+1 /* user name+pad */ 1395 +RAP_MACHNAME_LEN /* wksta name */ 1396 +WORDSIZE /* buffer size */ 1397 +WORDSIZE]; /* buffer size? */ 1398 fstring upperbuf; 1399 1400 memset(param, 0, sizeof(param)); 1401 1402 /* send a SMBtrans command with api NetWkstaUserLogoff */ 1403 p = make_header(param, RAP_WWkstaUserLogoff, 1404 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1); 1405 PUTDWORD(p, 0); /* Null pointer */ 1406 PUTDWORD(p, 0); /* Null pointer */ 1407 fstrcpy(upperbuf, user); 1408 strupper_m(upperbuf); 1409 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN); 1410 p++; /* strange format, but ok */ 1411 fstrcpy(upperbuf, workstation); 1412 strupper_m(upperbuf); 1413 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN); 1414 PUTWORD(p, CLI_BUFFER_SIZE); 1415 PUTWORD(p, CLI_BUFFER_SIZE); 1416 1417 if (cli_api(cli, 1418 param, PTR_DIFF(p,param),1024, /* param, length, max */ 1419 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */ 1420 &rparam, &rprcnt, /* return params, return size */ 1421 &rdata, &rdrcnt /* return data, return size */ 1422 )) { 1423 cli->rap_error = GETRES(rparam); 1424 1425 if (cli->rap_error != 0) { 1426 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error)); 1427 } 1428 } 1429 1430 SAFE_FREE(rparam); 1431 SAFE_FREE(rdata); 1432 return (cli->rap_error == 0); 1433} 1434 1435int cli_NetPrintQEnum(struct cli_state *cli, 1436 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16), 1437 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*)) 1438{ 1439 char param[WORDSIZE /* api number */ 1440 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */ 1441 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */ 1442 +WORDSIZE /* info level */ 1443 +WORDSIZE /* buffer size */ 1444 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */ 1445 char *p; 1446 char *rparam = NULL; 1447 char *rdata = NULL; 1448 unsigned int rprcnt, rdrcnt; 1449 int res = -1; 1450 1451 1452 memset(param, '\0',sizeof(param)); 1453 p = make_header(param, RAP_WPrintQEnum, 1454 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2); 1455 PUTWORD(p,2); /* Info level 2 */ 1456 PUTWORD(p,0xFFE0); /* Return buffer size */ 1457 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0); 1458 1459 if (cli_api(cli, 1460 param, PTR_DIFF(p,param),1024, 1461 NULL, 0, CLI_BUFFER_SIZE, 1462 &rparam, &rprcnt, 1463 &rdata, &rdrcnt)) { 1464 res = GETRES(rparam); 1465 cli->rap_error = res; 1466 if (res != 0) { 1467 DEBUG(1,("NetPrintQEnum gave error %d\n", res)); 1468 } 1469 } 1470 1471 if (rdata) { 1472 if (res == 0 || res == ERRmoredata) { 1473 int i, converter, count; 1474 1475 p = rparam + WORDSIZE; 1476 GETWORD(p, converter); 1477 GETWORD(p, count); 1478 1479 p = rdata; 1480 for (i=0;i<count;i++) { 1481 pstring qname, sep_file, print_proc, dest, parms, comment; 1482 uint16 jobcount, priority, start_time, until_time, status; 1483 1484 GETSTRINGF(p, qname, RAP_SHARENAME_LEN); 1485 p++; /* pad */ 1486 GETWORD(p, priority); 1487 GETWORD(p, start_time); 1488 GETWORD(p, until_time); 1489 GETSTRINGP(p, sep_file, rdata, converter); 1490 GETSTRINGP(p, print_proc, rdata, converter); 1491 GETSTRINGP(p, dest, rdata, converter); 1492 GETSTRINGP(p, parms, rdata, converter); 1493 GETSTRINGP(p, parms, comment, converter); 1494 GETWORD(p, status); 1495 GETWORD(p, jobcount); 1496 1497 qfn(qname, priority, start_time, until_time, sep_file, print_proc, 1498 dest, parms, comment, status, jobcount); 1499 1500 if (jobcount) { 1501 int j; 1502 for (j=0;j<jobcount;j++) { 1503 uint16 jid, pos, fsstatus; 1504 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment; 1505 unsigned int submitted, jsize; 1506 1507 GETWORD(p, jid); 1508 GETSTRINGF(p, ownername, RAP_USERNAME_LEN); 1509 p++; /* pad byte */ 1510 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN); 1511 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN); 1512 GETSTRINGP(p, jparms, rdata, converter); 1513 GETWORD(p, pos); 1514 GETWORD(p, fsstatus); 1515 GETSTRINGP(p, jstatus, rdata, converter); 1516 GETDWORD(p, submitted); 1517 GETDWORD(p, jsize); 1518 GETSTRINGP(p, jcomment, rdata, converter); 1519 1520 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus, 1521 jstatus, submitted, jsize, jcomment); 1522 } 1523 } 1524 } 1525 } else { 1526 DEBUG(4,("NetPrintQEnum res=%d\n", res)); 1527 } 1528 } else { 1529 DEBUG(4,("NetPrintQEnum no data returned\n")); 1530 } 1531 1532 SAFE_FREE(rparam); 1533 SAFE_FREE(rdata); 1534 1535 return res; 1536} 1537 1538int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer, 1539 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16), 1540 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*)) 1541{ 1542 char param[WORDSIZE /* api number */ 1543 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */ 1544 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */ 1545 +RAP_SHARENAME_LEN /* printer name */ 1546 +WORDSIZE /* info level */ 1547 +WORDSIZE /* buffer size */ 1548 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */ 1549 char *p; 1550 char *rparam = NULL; 1551 char *rdata = NULL; 1552 unsigned int rprcnt, rdrcnt; 1553 int res = -1; 1554 1555 1556 memset(param, '\0',sizeof(param)); 1557 p = make_header(param, RAP_WPrintQGetInfo, 1558 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2); 1559 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1); 1560 PUTWORD(p, 2); /* Info level 2 */ 1561 PUTWORD(p,0xFFE0); /* Return buffer size */ 1562 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0); 1563 1564 if (cli_api(cli, 1565 param, PTR_DIFF(p,param),1024, 1566 NULL, 0, CLI_BUFFER_SIZE, 1567 &rparam, &rprcnt, 1568 &rdata, &rdrcnt)) { 1569 res = GETRES(rparam); 1570 cli->rap_error = res; 1571 if (res != 0) { 1572 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res)); 1573 } 1574 } 1575 1576 if (rdata) { 1577 if (res == 0 || res == ERRmoredata) { 1578 int rsize, converter; 1579 pstring qname, sep_file, print_proc, dest, parms, comment; 1580 uint16 jobcount, priority, start_time, until_time, status; 1581 1582 p = rparam + WORDSIZE; 1583 GETWORD(p, converter); 1584 GETWORD(p, rsize); 1585 1586 p = rdata; 1587 GETSTRINGF(p, qname, RAP_SHARENAME_LEN); 1588 p++; /* pad */ 1589 GETWORD(p, priority); 1590 GETWORD(p, start_time); 1591 GETWORD(p, until_time); 1592 GETSTRINGP(p, sep_file, rdata, converter); 1593 GETSTRINGP(p, print_proc, rdata, converter); 1594 GETSTRINGP(p, dest, rdata, converter); 1595 GETSTRINGP(p, parms, rdata, converter); 1596 GETSTRINGP(p, comment, rdata, converter); 1597 GETWORD(p, status); 1598 GETWORD(p, jobcount); 1599 qfn(qname, priority, start_time, until_time, sep_file, print_proc, 1600 dest, parms, comment, status, jobcount); 1601 if (jobcount) { 1602 int j; 1603 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) { 1604 uint16 jid, pos, fsstatus; 1605 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment; 1606 unsigned int submitted, jsize; 1607 1608 GETWORD(p, jid); 1609 GETSTRINGF(p, ownername, RAP_USERNAME_LEN); 1610 p++; /* pad byte */ 1611 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN); 1612 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN); 1613 GETSTRINGP(p, jparms, rdata, converter); 1614 GETWORD(p, pos); 1615 GETWORD(p, fsstatus); 1616 GETSTRINGP(p, jstatus, rdata, converter); 1617 GETDWORD(p, submitted); 1618 GETDWORD(p, jsize); 1619 GETSTRINGP(p, jcomment, rdata, converter); 1620 1621 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus, 1622 jstatus, submitted, jsize, jcomment); 1623 } 1624 } 1625 } else { 1626 DEBUG(4,("NetPrintQGetInfo res=%d\n", res)); 1627 } 1628 } else { 1629 DEBUG(4,("NetPrintQGetInfo no data returned\n")); 1630 } 1631 1632 SAFE_FREE(rparam); 1633 SAFE_FREE(rdata); 1634 1635 return res; 1636} 1637 1638/**************************************************************************** 1639call a NetServiceEnum - list running services on a different host 1640****************************************************************************/ 1641int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state) 1642{ 1643 char param[WORDSIZE /* api number */ 1644 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */ 1645 +sizeof(RAP_SERVICE_INFO_L2) /* return string */ 1646 +WORDSIZE /* info level */ 1647 +WORDSIZE]; /* buffer size */ 1648 char *p; 1649 char *rparam = NULL; 1650 char *rdata = NULL; 1651 unsigned int rprcnt, rdrcnt; 1652 int res = -1; 1653 1654 1655 memset(param, '\0', sizeof(param)); 1656 p = make_header(param, RAP_WServiceEnum, 1657 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2); 1658 PUTWORD(p,2); /* Info level 2 */ 1659 PUTWORD(p,0xFFE0); /* Return buffer size */ 1660 1661 if (cli_api(cli, 1662 param, PTR_DIFF(p,param),8, 1663 NULL, 0, 0xFFE0 /* data area size */, 1664 &rparam, &rprcnt, 1665 &rdata, &rdrcnt)) { 1666 res = GETRES(rparam); 1667 cli->rap_error = res; 1668 if(cli->rap_error == 234) 1669 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n")); 1670 else if (cli->rap_error != 0) { 1671 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error)); 1672 } 1673 } 1674 1675 if (rdata) { 1676 if (res == 0 || res == ERRmoredata) { 1677 int i, converter, count; 1678 1679 p = rparam + WORDSIZE; /* skip result */ 1680 GETWORD(p, converter); 1681 GETWORD(p, count); 1682 1683 for (i=0,p=rdata;i<count;i++) { 1684 pstring comment; 1685 char servicename[RAP_SRVCNAME_LEN]; 1686 1687 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN); 1688 p+=8; /* pass status words */ 1689 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN); 1690 1691 fn(servicename, comment, cli); /* BB add status too */ 1692 } 1693 } else { 1694 DEBUG(4,("NetServiceEnum res=%d\n", res)); 1695 } 1696 } else { 1697 DEBUG(4,("NetServiceEnum no data returned\n")); 1698 } 1699 1700 SAFE_FREE(rparam); 1701 SAFE_FREE(rdata); 1702 1703 return res; 1704} 1705 1706 1707/**************************************************************************** 1708call a NetSessionEnum - list workstations with sessions to an SMB server 1709****************************************************************************/ 1710int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *)) 1711{ 1712 char param[WORDSIZE /* api number */ 1713 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */ 1714 +sizeof(RAP_SESSION_INFO_L2) /* return string */ 1715 +WORDSIZE /* info level */ 1716 +WORDSIZE]; /* buffer size */ 1717 char *p; 1718 char *rparam = NULL; 1719 char *rdata = NULL; 1720 unsigned int rprcnt, rdrcnt; 1721 int res = -1; 1722 1723 memset(param, '\0', sizeof(param)); 1724 p = make_header(param, RAP_WsessionEnum, 1725 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2); 1726 PUTWORD(p,2); /* Info level 2 */ 1727 PUTWORD(p,0xFF); /* Return buffer size */ 1728 1729 if (cli_api(cli, 1730 param, PTR_DIFF(p,param),8, 1731 NULL, 0, CLI_BUFFER_SIZE, 1732 &rparam, &rprcnt, 1733 &rdata, &rdrcnt)) { 1734 res = GETRES(rparam); 1735 cli->rap_error = res; 1736 if (res != 0) { 1737 DEBUG(1,("NetSessionEnum gave error %d\n", res)); 1738 } 1739 } 1740 1741 if (rdata) { 1742 if (res == 0 || res == ERRmoredata) { 1743 int i, converter, count; 1744 1745 p = rparam + WORDSIZE; 1746 GETWORD(p, converter); 1747 GETWORD(p, count); 1748 1749 for (i=0,p=rdata;i<count;i++) { 1750 pstring wsname, username, clitype_name; 1751 uint16 num_conns, num_opens, num_users; 1752 unsigned int sess_time, idle_time, user_flags; 1753 1754 GETSTRINGP(p, wsname, rdata, converter); 1755 GETSTRINGP(p, username, rdata, converter); 1756 GETWORD(p, num_conns); 1757 GETWORD(p, num_opens); 1758 GETWORD(p, num_users); 1759 GETDWORD(p, sess_time); 1760 GETDWORD(p, idle_time); 1761 GETDWORD(p, user_flags); 1762 GETSTRINGP(p, clitype_name, rdata, converter); 1763 1764 fn(wsname, username, num_conns, num_opens, num_users, sess_time, 1765 idle_time, user_flags, clitype_name); 1766 } 1767 1768 } else { 1769 DEBUG(4,("NetSessionEnum res=%d\n", res)); 1770 } 1771 } else { 1772 DEBUG(4,("NetSesssionEnum no data returned\n")); 1773 } 1774 1775 SAFE_FREE(rparam); 1776 SAFE_FREE(rdata); 1777 1778 return res; 1779} 1780 1781/**************************************************************************** 1782 Call a NetSessionGetInfo - get information about other session to an SMB server. 1783****************************************************************************/ 1784 1785int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *)) 1786{ 1787 char param[WORDSIZE /* api number */ 1788 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */ 1789 +sizeof(RAP_SESSION_INFO_L2) /* return string */ 1790 +RAP_MACHNAME_LEN /* wksta name */ 1791 +WORDSIZE /* info level */ 1792 +WORDSIZE]; /* buffer size */ 1793 char *p; 1794 char *rparam = NULL; 1795 char *rdata = NULL; 1796 unsigned int rprcnt, rdrcnt; 1797 int res = -1; 1798 1799 1800 memset(param, '\0', sizeof(param)); 1801 p = make_header(param, RAP_WsessionGetInfo, 1802 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2); 1803 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1); 1804 PUTWORD(p,2); /* Info level 2 */ 1805 PUTWORD(p,0xFF); /* Return buffer size */ 1806 1807 if (cli_api(cli, 1808 param, PTR_DIFF(p,param),PTR_DIFF(p,param), 1809 NULL, 0, CLI_BUFFER_SIZE, 1810 &rparam, &rprcnt, 1811 &rdata, &rdrcnt)) { 1812 cli->rap_error = SVAL(rparam,0); 1813 if (cli->rap_error != 0) { 1814 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error)); 1815 } 1816 } 1817 1818 if (rdata) { 1819 res = GETRES(rparam); 1820 1821 if (res == 0 || res == ERRmoredata) { 1822 int rsize, converter; 1823 pstring wsname, username, clitype_name; 1824 uint16 num_conns, num_opens, num_users; 1825 unsigned int sess_time, idle_time, user_flags; 1826 1827 p = rparam + WORDSIZE; 1828 GETWORD(p, converter); 1829 GETWORD(p, rsize); 1830 1831 p = rdata; 1832 GETSTRINGP(p, wsname, rdata, converter); 1833 GETSTRINGP(p, username, rdata, converter); 1834 GETWORD(p, num_conns); 1835 GETWORD(p, num_opens); 1836 GETWORD(p, num_users); 1837 GETDWORD(p, sess_time); 1838 GETDWORD(p, idle_time); 1839 GETDWORD(p, user_flags); 1840 GETSTRINGP(p, clitype_name, rdata, converter); 1841 1842 fn(wsname, username, num_conns, num_opens, num_users, sess_time, 1843 idle_time, user_flags, clitype_name); 1844 } else { 1845 DEBUG(4,("NetSessionGetInfo res=%d\n", res)); 1846 } 1847 } else { 1848 DEBUG(4,("NetSessionGetInfo no data returned\n")); 1849 } 1850 1851 SAFE_FREE(rparam); 1852 SAFE_FREE(rdata); 1853 1854 return res; 1855} 1856 1857/**************************************************************************** 1858call a NetSessionDel - close a session to an SMB server 1859****************************************************************************/ 1860int cli_NetSessionDel(struct cli_state *cli, const char *workstation) 1861{ 1862 char param[WORDSIZE /* api number */ 1863 +sizeof(RAP_NetSessionDel_REQ) /* req string */ 1864 +1 /* no return string */ 1865 +RAP_MACHNAME_LEN /* workstation name */ 1866 +WORDSIZE]; /* reserved (0) */ 1867 char *p; 1868 char *rparam = NULL; 1869 char *rdata = NULL; 1870 unsigned int rprcnt, rdrcnt; 1871 int res; 1872 1873 memset(param, '\0', sizeof(param)); 1874 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL); 1875 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1); 1876 PUTWORD(p,0); /* reserved word of 0 */ 1877 if (cli_api(cli, 1878 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */ 1879 NULL, 0, 200, /* data, length, maxlen */ 1880 &rparam, &rprcnt, /* return params, length */ 1881 &rdata, &rdrcnt)) /* return data, length */ 1882 { 1883 res = GETRES(rparam); 1884 cli->rap_error = res; 1885 1886 if (res == 0) { 1887 /* nothing to do */ 1888 } 1889 else { 1890 DEBUG(4,("NetFileClose2 res=%d\n", res)); 1891 } 1892 } else { 1893 res = -1; 1894 DEBUG(4,("NetFileClose2 failed\n")); 1895 } 1896 1897 SAFE_FREE(rparam); 1898 SAFE_FREE(rdata); 1899 1900 return res; 1901} 1902 1903 1904int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*fn)(uint16 conid, uint16 contype, uint16 numopens, uint16 numusers, uint32 contime, const char *username, const char *netname)) 1905{ 1906 char param[WORDSIZE /* api number */ 1907 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */ 1908 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */ 1909 +RAP_MACHNAME_LEN /* wksta name */ 1910 +WORDSIZE /* info level */ 1911 +WORDSIZE]; /* buffer size */ 1912 char *p; 1913 char *rparam = NULL; 1914 char *rdata = NULL; 1915 unsigned int rprcnt, rdrcnt; 1916 int res = -1; 1917 1918 memset(param, '\0', sizeof(param)); 1919 p = make_header(param, RAP_WconnectionEnum, 1920 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1); 1921 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */ 1922 PUTWORD(p,1); /* Info level 1 */ 1923 PUTWORD(p,0xFFE0); /* Return buffer size */ 1924 1925 if (cli_api(cli, 1926 param, PTR_DIFF(p,param),PTR_DIFF(p,param), 1927 NULL, 0, CLI_BUFFER_SIZE, 1928 &rparam, &rprcnt, 1929 &rdata, &rdrcnt)) { 1930 res = GETRES(rparam); 1931 cli->rap_error = res; 1932 if (res != 0) { 1933 DEBUG(1,("NetConnectionEnum gave error %d\n", res)); 1934 } 1935 } 1936 if (rdata) { 1937 if (res == 0 || res == ERRmoredata) { 1938 int i, converter, count; 1939 1940 p = rparam + WORDSIZE; 1941 GETWORD(p, converter); 1942 GETWORD(p, count); 1943 1944 for (i=0,p=rdata;i<count;i++) { 1945 pstring netname, username; 1946 uint16 conn_id, conn_type, num_opens, num_users; 1947 unsigned int conn_time; 1948 1949 GETWORD(p,conn_id); 1950 GETWORD(p,conn_type); 1951 GETWORD(p,num_opens); 1952 GETWORD(p,num_users); 1953 GETDWORD(p,conn_time); 1954 GETSTRINGP(p, username, rdata, converter); 1955 GETSTRINGP(p, netname, rdata, converter); 1956 1957 fn(conn_id, conn_type, num_opens, num_users, conn_time, 1958 username, netname); 1959 } 1960 1961 } else { 1962 DEBUG(4,("NetConnectionEnum res=%d\n", res)); 1963 } 1964 } else { 1965 DEBUG(4,("NetConnectionEnum no data returned\n")); 1966 } 1967 SAFE_FREE(rdata); 1968 SAFE_FREE(rparam); 1969 return res; 1970} 1971