root/source3/libsmb/clirap2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rap_getstring
  2. rap_getstringf
  3. rap_getstringp
  4. make_header
  5. cli_NetGroupDelete
  6. cli_NetGroupAdd
  7. cli_RNetGroupEnum
  8. cli_RNetGroupEnum0
  9. cli_NetGroupDelUser
  10. cli_NetGroupAddUser
  11. cli_NetGroupGetUsers
  12. cli_NetUserGetGroups
  13. cli_NetUserDelete
  14. cli_NetUserAdd
  15. cli_RNetUserEnum
  16. cli_RNetUserEnum0
  17. cli_NetFileClose
  18. cli_NetFileGetInfo
  19. cli_NetFileEnum
  20. cli_NetShareAdd
  21. cli_NetShareDelete
  22. cli_get_pdc_name
  23. cli_get_server_domain
  24. cli_get_server_type
  25. cli_get_server_name
  26. cli_ns_check_server_type
  27. cli_NetWkstaUserLogoff
  28. cli_NetPrintQEnum
  29. cli_NetPrintQGetInfo
  30. cli_RNetServiceEnum
  31. cli_NetSessionEnum
  32. cli_NetSessionGetInfo
  33. cli_NetSessionDel
  34. cli_NetConnectionEnum

   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    Copyright (C) 2007 Jeremy Allison. jra@samba.org
   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 3 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, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 /*****************************************************/
  23 /*                                                   */
  24 /*   Additional RAP functionality                    */
  25 /*                                                   */
  26 /*   RAP is the original SMB RPC, documented         */
  27 /*   by Microsoft and X/Open in the 1990s and        */
  28 /*   supported by most SMB/CIFS servers although     */
  29 /*   it is unlikely that any one implementation      */
  30 /*   supports all RAP command codes since some       */
  31 /*   are quite obsolete and a few are specific       */
  32 /*   to a particular network operating system        */
  33 /*                                                   */
  34 /*   Although it has largely been replaced           */
  35 /*   for complex remote admistration and management  */
  36 /*   (of servers) by the relatively newer            */
  37 /*   DCE/RPC based remote API (which better handles  */
  38 /*   large >64K data structures), there are many     */
  39 /*   important administrative and resource location  */
  40 /*   tasks and user tasks (e.g. password change)     */
  41 /*   that are performed via RAP.                     */
  42 /*                                                   */
  43 /*   Although a few of the RAP calls are implemented */
  44 /*   in the Samba client library already (clirap.c)  */
  45 /*   the new ones are in clirap2.c for easy patching */
  46 /*   and integration and a corresponding header      */
  47 /*   file, rap.h, has been created.                  */
  48 /*                                                   */
  49 /*   This is based on data from the CIFS spec        */
  50 /*   and the LAN Server and LAN Manager              */
  51 /*   Programming Reference books and published       */
  52 /*   RAP document and CIFS forum postings and        */
  53 /*   lots of trial and error                         */
  54 /*                                                   */
  55 /*   Function names changed from API_ (as they are   */
  56 /*   in the CIFS specification) to RAP_ in order     */
  57 /*   to avoid confusion with other API calls         */
  58 /*   sent via DCE RPC                                */
  59 /*                                                   */
  60 /*****************************************************/
  61 
  62 /*****************************************************/
  63 /*                                                   */
  64 /* cifsrap.c already includes support for:           */
  65 /*                                                   */
  66 /* WshareEnum ( API number 0, level 1)               */
  67 /* NetServerEnum2 (API num 104, level 1)             */
  68 /* WWkstaUserLogon (132)                             */
  69 /* SamOEMchgPasswordUser2_P (214)                    */
  70 /*                                                   */
  71 /* cifsprint.c already includes support for:         */
  72 /*                                                   */
  73 /* WPrintJobEnum (API num 76, level 2)               */
  74 /* WPrintJobDel  (API num 81)                        */
  75 /*                                                   */
  76 /*****************************************************/
  77 
  78 #include "includes.h"
  79 
  80 #define WORDSIZE 2
  81 #define DWORDSIZE 4
  82 
  83 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
  84 
  85 #define GETBYTE(p,b,endp) \
  86         do {\
  87                 if (p+1 < endp) {\
  88                         b = CVAL(p,0);\
  89                 }\
  90                 p++;\
  91         } while(0)
  92 
  93 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
  94 
  95 #define GETWORD(p,w,endp) \
  96         do {\
  97                 if (p+WORDSIZE < endp) {\
  98                         w = SVAL(p,0);\
  99                 }\
 100                 p += WORDSIZE;\
 101         } while(0)
 102 
 103 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
 104 
 105 #define GETDWORD(p,d,endp) \
 106         do {\
 107                 if (p+DWORDSIZE < endp) {\
 108                         d = IVAL(p,0);\
 109                 }\
 110                 p += DWORDSIZE;\
 111         } while(0)
 112 
 113 #define GETRES(p,endp) ((p && p+2 < endp) ? SVAL(p,0) : -1)
 114 
 115 /* put string s at p with max len n and increment p past string */
 116 #define PUTSTRING(p,s,n) \
 117         do {\
 118                 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
 119                 p = push_skip_string(p);\
 120         } while(0)
 121 
 122 /* put string s and p, using fixed len l, and increment p by l */
 123 #define PUTSTRINGF(p,s,l) \
 124         do {\
 125                 push_ascii(p,s?s:"",l,STR_TERMINATE);\
 126                 p += l;\
 127         } while (0)
 128 
 129 /* put string pointer at p, supplying offset o from rdata r, store   */
 130 /* dword offset at p, increment p by 4 and o by length of s.  This   */
 131 /* means on the first call, you must calc the offset yourself!       */
 132 
 133 #define PUTSTRINGP(p,s,r,o) \
 134         do {\
 135                 if (s) {\
 136                         push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
 137                         PUTDWORD(p,o);\
 138                         o += strlen(s) + 1;\
 139                 } else {\
 140                         PUTDWORD(p,0);\
 141                 }\
 142         }while(0);
 143 
 144 /* get asciiz string dest from src, return increment past string */
 145 
 146 static size_t rap_getstring(TALLOC_CTX *ctx, char *src, char **dest, const char *endp)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         char *p1;
 149         size_t len;
 150 
 151         *dest = NULL;
 152         for (p1 = src, len = 0; *p1 && p1 < endp; len++)
 153                 p1++;
 154         if (!*p1) {
 155                 len++;
 156         }
 157         pull_string_talloc(ctx,src,0,dest,src,len,STR_ASCII);
 158         return len;
 159 }
 160 
 161 /* get fixed length l string dest from src, return increment for src */
 162 
 163 static size_t rap_getstringf(char *src, char *dest, size_t l, size_t dlen, char *endp)
     /* [<][>][^][v][top][bottom][index][help] */
 164 {
 165         char *p1;
 166         size_t len;
 167 
 168         if (dlen) {
 169                 dest[0] = '\0';
 170         }
 171         for (p1 = src, len = 0; *p1 && p1 < endp; len++) {
 172                 p1++;
 173         }
 174         if (!*p1) {
 175                 len++;
 176         }
 177         if (len > l) {
 178                 len = l;
 179         }
 180         if (len) {
 181                 pull_ascii(dest,src,len,len,STR_ASCII);
 182         }
 183         return l;
 184 }
 185 
 186 /* get string dest from offset (obtained at p) from rdata r - converter c */
 187 static size_t rap_getstringp(TALLOC_CTX *ctx, char *p, char **dest, char *r, uint16_t c, char *endp)
     /* [<][>][^][v][top][bottom][index][help] */
 188 {
 189         uint32_t off = 0;
 190         const char *src;
 191         size_t len=0;
 192 
 193         *dest = NULL;
 194         if (p+4 < endp) {
 195                 GETDWORD(p,off,endp);
 196                 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */
 197                 off -= c;
 198         }
 199         if (r+off > endp || r+off < r) {
 200                 src="";
 201                 len=1;
 202         } else {
 203                 const char *p1;
 204                 src=r+off;
 205                 for (p1 = src, len = 0; *p1 && p1 < endp; len++) {
 206                         p1++;
 207                 }
 208                 if (!*p1) {
 209                         len++;
 210                 }
 211         }
 212         pull_string_talloc(ctx,src,0,dest,src,len,STR_ASCII);
 213         return len;
 214 }
 215 
 216 static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
     /* [<][>][^][v][top][bottom][index][help] */
 217 {
 218         PUTWORD(param,apinum);
 219         if (reqfmt)
 220                 PUTSTRING(param,reqfmt,0);
 221         else
 222                 *param++ = (char) 0;
 223 
 224         if (datafmt)
 225                 PUTSTRING(param,datafmt,0);
 226         else
 227                 *param++ = (char) 0;
 228 
 229         return param;
 230 }
 231 
 232 /****************************************************************************
 233  call a NetGroupDelete - delete user group from remote server
 234 ****************************************************************************/
 235 
 236 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name)
     /* [<][>][^][v][top][bottom][index][help] */
 237 {
 238         char *rparam = NULL;
 239         char *rdata = NULL;
 240         char *p;
 241         unsigned int rdrcnt,rprcnt;
 242         int res = -1;
 243         char param[WORDSIZE                    /* api number    */
 244             +sizeof(RAP_NetGroupDel_REQ) /* parm string   */
 245             +1                           /* no ret string */
 246             +RAP_GROUPNAME_LEN           /* group to del  */
 247             +WORDSIZE];                  /* reserved word */
 248 
 249         /* now send a SMBtrans command with api GroupDel */
 250         p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);
 251         PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
 252         PUTWORD(p,0);  /* reserved word MBZ on input */
 253 
 254         if (cli_api(cli,
 255               param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
 256               NULL, 0, 200,       /* data, length, maxlen */
 257               &rparam, &rprcnt,   /* return params, length */
 258               &rdata, &rdrcnt))   /* return data, length */
 259         {
 260                 char *endp = rparam + rprcnt;
 261                 res = GETRES(rparam,endp);
 262 
 263                 if (res == 0) {
 264                         /* nothing to do */
 265                 } else if ((res == 5) || (res == 65)) {
 266                         DEBUG(1, ("Access Denied\n"));
 267                 } else if (res == 2220) {
 268                         DEBUG (1, ("Group does not exist\n"));
 269                 } else {
 270                         DEBUG(4,("NetGroupDelete res=%d\n", res));
 271                 }
 272         } else {
 273                 res = -1;
 274                 DEBUG(4,("NetGroupDelete failed\n"));
 275         }
 276 
 277         SAFE_FREE(rparam);
 278         SAFE_FREE(rdata);
 279 
 280         return res;
 281 }
 282 
 283 /****************************************************************************
 284  call a NetGroupAdd - add user group to remote server
 285 ****************************************************************************/
 286 
 287 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 *grinfo)
     /* [<][>][^][v][top][bottom][index][help] */
 288 {
 289         char *rparam = NULL;
 290         char *rdata = NULL;
 291         char *p;
 292         unsigned int rdrcnt,rprcnt;
 293         int res = -1;
 294         char param[WORDSIZE                    /* api number    */
 295             +sizeof(RAP_NetGroupAdd_REQ) /* req string    */
 296             +sizeof(RAP_GROUP_INFO_L1)   /* return string */
 297             +WORDSIZE                    /* info level    */
 298             +WORDSIZE];                  /* reserved word */
 299 
 300         /* offset into data of free format strings.  Will be updated */
 301         /* by PUTSTRINGP macro and end up with total data length.    */
 302         int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
 303         char *data;
 304         size_t data_size;
 305 
 306         /* Allocate data. */
 307         data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
 308 
 309         data = SMB_MALLOC_ARRAY(char, data_size);
 310         if (!data) {
 311                 DEBUG (1, ("Malloc fail\n"));
 312                 return -1;
 313         }
 314 
 315         /* now send a SMBtrans command with api WGroupAdd */
 316 
 317         p = make_header(param, RAP_WGroupAdd,
 318                         RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
 319         PUTWORD(p, 1); /* info level */
 320         PUTWORD(p, 0); /* reserved word 0 */
 321 
 322         p = data;
 323         PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
 324         PUTBYTE(p, 0); /* pad byte 0 */
 325         PUTSTRINGP(p, grinfo->comment, data, soffset);
 326 
 327         if (cli_api(cli,
 328               param, sizeof(param), 1024, /* Param, length, maxlen */
 329               data, soffset, sizeof(data), /* data, length, maxlen */
 330               &rparam, &rprcnt,   /* return params, length */
 331               &rdata, &rdrcnt))   /* return data, length */
 332         {
 333                 char *endp = rparam + rprcnt;
 334                 res = GETRES(rparam, endp);
 335 
 336                 if (res == 0) {
 337                         /* nothing to do */
 338                 } else if ((res == 5) || (res == 65)) {
 339                         DEBUG(1, ("Access Denied\n"));
 340                 } else if (res == 2223) {
 341                         DEBUG (1, ("Group already exists\n"));
 342                 } else {
 343                         DEBUG(4,("NetGroupAdd res=%d\n", res));
 344                 }
 345         } else {
 346                 res = -1;
 347                 DEBUG(4,("NetGroupAdd failed\n"));
 348         }
 349 
 350         SAFE_FREE(data);
 351         SAFE_FREE(rparam);
 352         SAFE_FREE(rdata);
 353 
 354         return res;
 355 }
 356 
 357 /****************************************************************************
 358  Call a NetGroupEnum - try and list user groups on a different host.
 359 ****************************************************************************/
 360 
 361 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
     /* [<][>][^][v][top][bottom][index][help] */
 362 {
 363         char param[WORDSIZE                     /* api number    */
 364             +sizeof(RAP_NetGroupEnum_REQ) /* parm string   */
 365             +sizeof(RAP_GROUP_INFO_L1)    /* return string */
 366             +WORDSIZE                     /* info level    */
 367             +WORDSIZE];                   /* buffer size   */
 368         char *p;
 369         char *rparam = NULL;
 370         char *rdata = NULL;
 371         unsigned int rprcnt, rdrcnt;
 372         int res = -1;
 373 
 374         memset(param, '\0', sizeof(param));
 375         p = make_header(param, RAP_WGroupEnum,
 376                   RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
 377         PUTWORD(p,1); /* Info level 1 */  /* add level 0 */
 378         PUTWORD(p,0xFFE0); /* Return buffer size */
 379 
 380         if (cli_api(cli,
 381               param, PTR_DIFF(p,param),8,
 382               NULL, 0, 0xFFE0 /* data area size */,
 383               &rparam, &rprcnt,
 384               &rdata, &rdrcnt)) {
 385                 char *endp = rparam + rdrcnt;
 386 
 387                 res = GETRES(rparam, endp);
 388                 cli->rap_error = res;
 389                 if(cli->rap_error == 234) {
 390                         DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
 391                 } else if (cli->rap_error != 0) {
 392                         DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
 393                 }
 394         }
 395 
 396         if (!rdata) {
 397                 DEBUG(4,("NetGroupEnum no data returned\n"));
 398                 goto out;
 399         }
 400 
 401         if (res == 0 || res == ERRmoredata) {
 402                 char *endp = rparam + rprcnt;
 403                 int i, converter = 0, count = 0;
 404                 TALLOC_CTX *frame = talloc_stackframe();
 405 
 406                 p = rparam + WORDSIZE; /* skip result */
 407                 GETWORD(p, converter, endp);
 408                 GETWORD(p, count, endp);
 409 
 410                 endp = rdata + rdrcnt;
 411                 for (i=0,p=rdata; i<count && p < endp;i++) {
 412                         char *comment = NULL;
 413                         char groupname[RAP_GROUPNAME_LEN];
 414 
 415                         p += rap_getstringf(p,
 416                                         groupname,
 417                                         RAP_GROUPNAME_LEN,
 418                                         RAP_GROUPNAME_LEN,
 419                                         endp);
 420                         p++; /* pad byte */
 421                         p += rap_getstringp(frame,
 422                                         p,
 423                                         &comment,
 424                                         rdata,
 425                                         converter,
 426                                         endp);
 427 
 428                         if (!comment || !groupname[0]) {
 429                                 break;
 430                         }
 431 
 432                         fn(groupname, comment, cli);
 433                 }
 434                 TALLOC_FREE(frame);
 435         } else {
 436                 DEBUG(4,("NetGroupEnum res=%d\n", res));
 437         }
 438 
 439   out:
 440 
 441         SAFE_FREE(rparam);
 442         SAFE_FREE(rdata);
 443 
 444         return res;
 445 }
 446 
 447 int cli_RNetGroupEnum0(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 448                        void (*fn)(const char *, void *),
 449                        void *state)
 450 {
 451         char param[WORDSIZE                     /* api number    */
 452                 +sizeof(RAP_NetGroupEnum_REQ) /* parm string   */
 453                 +sizeof(RAP_GROUP_INFO_L0)    /* return string */
 454                 +WORDSIZE                     /* info level    */
 455                 +WORDSIZE];                   /* buffer size   */
 456         char *p;
 457         char *rparam = NULL;
 458         char *rdata = NULL;
 459         unsigned int rprcnt, rdrcnt;
 460         int res = -1;
 461 
 462         memset(param, '\0', sizeof(param));
 463         p = make_header(param, RAP_WGroupEnum,
 464                 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0);
 465         PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
 466                                       is the resume count, at least
 467                                       that's what smbd believes... */
 468         PUTWORD(p,0xFFE0); /* Return buffer size */
 469 
 470         if (cli_api(cli,
 471                         param, PTR_DIFF(p,param),8,
 472                         NULL, 0, 0xFFE0 /* data area size */,
 473                         &rparam, &rprcnt,
 474                         &rdata, &rdrcnt)) {
 475                 char *endp = rparam+rprcnt;
 476                 res = GETRES(rparam,endp);
 477                 cli->rap_error = res;
 478                 if(cli->rap_error == 234) {
 479                         DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
 480                 } else if (cli->rap_error != 0) {
 481                         DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
 482                 }
 483         }
 484 
 485         if (!rdata) {
 486                 DEBUG(4,("NetGroupEnum no data returned\n"));
 487                 goto out;
 488         }
 489 
 490         if (res == 0 || res == ERRmoredata) {
 491                 char *endp = rparam + rprcnt;
 492                 int i, count = 0;
 493 
 494                 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
 495                 GETWORD(p, count, endp);
 496 
 497                 endp = rdata + rdrcnt;
 498                 for (i=0,p=rdata; i<count && p < endp;i++) {
 499                         char groupname[RAP_GROUPNAME_LEN];
 500 
 501                         p += rap_getstringf(p,
 502                                         groupname,
 503                                         RAP_GROUPNAME_LEN,
 504                                         RAP_GROUPNAME_LEN,
 505                                         endp);
 506                         if (groupname[0]) {
 507                                 fn(groupname, cli);
 508                         }
 509                 }
 510         } else {
 511                 DEBUG(4,("NetGroupEnum res=%d\n", res));
 512         }
 513 
 514   out:
 515 
 516         SAFE_FREE(rparam);
 517         SAFE_FREE(rdata);
 518 
 519         return res;
 520 }
 521 
 522 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
     /* [<][>][^][v][top][bottom][index][help] */
 523 {
 524         char *rparam = NULL;
 525         char *rdata = NULL;
 526         char *p;
 527         unsigned int rdrcnt,rprcnt;
 528         int res = -1;
 529         char param[WORDSIZE                        /* api number    */
 530                 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string   */
 531                 +1                               /* no ret string */
 532                 +RAP_GROUPNAME_LEN               /* group name    */
 533                 +RAP_USERNAME_LEN];              /* user to del   */
 534 
 535         /* now send a SMBtrans command with api GroupMemberAdd */
 536         p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
 537         PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
 538         PUTSTRING(p,user_name,RAP_USERNAME_LEN);
 539 
 540         if (cli_api(cli,
 541                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
 542                         NULL, 0, 200,       /* data, length, maxlen */
 543                         &rparam, &rprcnt,   /* return params, length */
 544                         &rdata, &rdrcnt))   /* return data, length */
 545         {
 546                 char *endp = rparam + rprcnt;
 547                 res = GETRES(rparam,endp);
 548 
 549                 switch(res) {
 550                 case 0:
 551                         break;
 552                 case 5:
 553                 case 65:
 554                         DEBUG(1, ("Access Denied\n"));
 555                         break;
 556                 case 50:
 557                         DEBUG(1, ("Not supported by server\n"));
 558                         break;
 559                 case 2220:
 560                         DEBUG(1, ("Group does not exist\n"));
 561                         break;
 562                 case 2221:
 563                         DEBUG(1, ("User does not exist\n"));
 564                         break;
 565                 case 2237:
 566                         DEBUG(1, ("User is not in group\n"));
 567                         break;
 568                 default:
 569                         DEBUG(4,("NetGroupDelUser res=%d\n", res));
 570                 }
 571         } else {
 572                 res = -1;
 573                 DEBUG(4,("NetGroupDelUser failed\n"));
 574         }
 575 
 576         SAFE_FREE(rparam);
 577         SAFE_FREE(rdata);
 578 
 579         return res;
 580 }
 581 
 582 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
     /* [<][>][^][v][top][bottom][index][help] */
 583 {
 584         char *rparam = NULL;
 585         char *rdata = NULL;
 586         char *p;
 587         unsigned int rdrcnt,rprcnt;
 588         int res = -1;
 589         char param[WORDSIZE                        /* api number    */
 590                 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string   */
 591                 +1                               /* no ret string */
 592                 +RAP_GROUPNAME_LEN               /* group name    */
 593                 +RAP_USERNAME_LEN];              /* user to add   */
 594 
 595         /* now send a SMBtrans command with api GroupMemberAdd */
 596         p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
 597         PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
 598         PUTSTRING(p,user_name,RAP_USERNAME_LEN);
 599 
 600         if (cli_api(cli,
 601                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
 602                         NULL, 0, 200,       /* data, length, maxlen */
 603                         &rparam, &rprcnt,   /* return params, length */
 604                         &rdata, &rdrcnt))   /* return data, length */
 605         {
 606                 char *endp = rparam + rprcnt;
 607                 res = GETRES(rparam,endp);
 608 
 609                 switch(res) {
 610                 case 0:
 611                         break;
 612                 case 5:
 613                 case 65:
 614                         DEBUG(1, ("Access Denied\n"));
 615                         break;
 616                 case 50:
 617                         DEBUG(1, ("Not supported by server\n"));
 618                         break;
 619                 case 2220:
 620                         DEBUG(1, ("Group does not exist\n"));
 621                         break;
 622                 case 2221:
 623                         DEBUG(1, ("User does not exist\n"));
 624                         break;
 625                 default:
 626                         DEBUG(4,("NetGroupAddUser res=%d\n", res));
 627                 }
 628         } else {
 629                 res = -1;
 630                 DEBUG(4,("NetGroupAddUser failed\n"));
 631         }
 632 
 633         SAFE_FREE(rparam);
 634         SAFE_FREE(rdata);
 635 
 636         return res;
 637 }
 638 
 639 
 640 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
     /* [<][>][^][v][top][bottom][index][help] */
 641 {
 642         char *rparam = NULL;
 643         char *rdata = NULL;
 644         char *p;
 645         unsigned int rdrcnt,rprcnt;
 646         int res = -1;
 647         char param[WORDSIZE                        /* api number    */
 648                 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string   */
 649                 +sizeof(RAP_GROUP_USERS_INFO_0)  /* return string */
 650                 +RAP_GROUPNAME_LEN               /* group name    */
 651                 +WORDSIZE                        /* info level    */
 652                 +WORDSIZE];                      /* buffer size   */
 653 
 654         /* now send a SMBtrans command with api GroupGetUsers */
 655         p = make_header(param, RAP_WGroupGetUsers,
 656                 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
 657         PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
 658         PUTWORD(p,0); /* info level 0 */
 659         PUTWORD(p,0xFFE0); /* return buffer size */
 660 
 661         if (cli_api(cli,
 662                         param, PTR_DIFF(p,param),PTR_DIFF(p,param),
 663                         NULL, 0, CLI_BUFFER_SIZE,
 664                         &rparam, &rprcnt,
 665                         &rdata, &rdrcnt)) {
 666                 char *endp = rparam + rprcnt;
 667                 res = GETRES(rparam,endp);
 668                 cli->rap_error = res;
 669                 if (res != 0) {
 670                         DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
 671                 }
 672         }
 673 
 674         if (!rdata) {
 675                 DEBUG(4,("NetGroupGetUsers no data returned\n"));
 676                 goto out;
 677         }
 678 
 679         if (res == 0 || res == ERRmoredata) {
 680                 char *endp = rparam + rprcnt;
 681                 int i, count = 0;
 682                 char username[RAP_USERNAME_LEN];
 683 
 684                 p = rparam + WORDSIZE + WORDSIZE;
 685                 GETWORD(p, count, endp);
 686 
 687                 endp = rdata + rdrcnt;
 688                 for (i=0,p=rdata; i<count && p < endp; i++) {
 689                         p += rap_getstringf(p,
 690                                         username,
 691                                         RAP_USERNAME_LEN,
 692                                         RAP_USERNAME_LEN,
 693                                         endp);
 694                         if (username[0]) {
 695                                 fn(username, state);
 696                         }
 697                 }
 698         } else {
 699                 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
 700         }
 701 
 702   out:
 703 
 704         SAFE_FREE(rdata);
 705         SAFE_FREE(rparam);
 706         return res;
 707 }
 708 
 709 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
     /* [<][>][^][v][top][bottom][index][help] */
 710 {
 711         char *rparam = NULL;
 712         char *rdata = NULL;
 713         char *p;
 714         unsigned int rdrcnt,rprcnt;
 715         int res = -1;
 716         char param[WORDSIZE                        /* api number    */
 717                 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string   */
 718                 +sizeof(RAP_GROUP_USERS_INFO_0)  /* return string */
 719                 +RAP_USERNAME_LEN               /* user name    */
 720                 +WORDSIZE                        /* info level    */
 721                 +WORDSIZE];                      /* buffer size   */
 722 
 723         /* now send a SMBtrans command with api GroupGetUsers */
 724         p = make_header(param, RAP_WUserGetGroups,
 725                 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
 726         PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
 727         PUTWORD(p,0); /* info level 0 */
 728         PUTWORD(p,0xFFE0); /* return buffer size */
 729 
 730         if (cli_api(cli,
 731                         param, PTR_DIFF(p,param),PTR_DIFF(p,param),
 732                         NULL, 0, CLI_BUFFER_SIZE,
 733                         &rparam, &rprcnt,
 734                         &rdata, &rdrcnt)) {
 735                 char *endp = rparam + rprcnt;
 736                 res = GETRES(rparam,endp);
 737                 cli->rap_error = res;
 738                 if (res != 0) {
 739                         DEBUG(1,("NetUserGetGroups gave error %d\n", res));
 740                 }
 741         }
 742 
 743         if (!rdata) {
 744                 DEBUG(4,("NetUserGetGroups no data returned\n"));
 745                 goto out;
 746         }
 747 
 748         if (res == 0 || res == ERRmoredata) {
 749                 char *endp = rparam + rprcnt;
 750                 int i, count = 0;
 751                 char groupname[RAP_GROUPNAME_LEN];
 752 
 753                 p = rparam + WORDSIZE + WORDSIZE;
 754                 GETWORD(p, count, endp);
 755 
 756                 endp = rdata + rdrcnt;
 757                 for (i=0,p=rdata; i<count && p < endp; i++) {
 758                         p += rap_getstringf(p,
 759                                         groupname,
 760                                         RAP_GROUPNAME_LEN,
 761                                         RAP_GROUPNAME_LEN,
 762                                         endp);
 763                         if (groupname[0]) {
 764                                 fn(groupname, state);
 765                         }
 766                 }
 767         } else {
 768                 DEBUG(4,("NetUserGetGroups res=%d\n", res));
 769         }
 770 
 771   out:
 772 
 773         SAFE_FREE(rdata);
 774         SAFE_FREE(rparam);
 775         return res;
 776 }
 777 
 778 /****************************************************************************
 779  Call a NetUserDelete - delete user from remote server.
 780 ****************************************************************************/
 781 
 782 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
     /* [<][>][^][v][top][bottom][index][help] */
 783 {
 784         char *rparam = NULL;
 785         char *rdata = NULL;
 786         char *p;
 787         unsigned int rdrcnt,rprcnt;
 788         int res = -1;
 789         char param[WORDSIZE                    /* api number    */
 790                 +sizeof(RAP_NetGroupDel_REQ) /* parm string   */
 791                 +1                           /* no ret string */
 792                 +RAP_USERNAME_LEN            /* user to del   */
 793                 +WORDSIZE];                  /* reserved word */
 794 
 795         /* now send a SMBtrans command with api UserDel */
 796         p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
 797         PUTSTRING(p, user_name, RAP_USERNAME_LEN);
 798         PUTWORD(p,0);  /* reserved word MBZ on input */
 799 
 800         if (cli_api(cli,
 801                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
 802                         NULL, 0, 200,       /* data, length, maxlen */
 803                         &rparam, &rprcnt,   /* return params, length */
 804                         &rdata, &rdrcnt))   /* return data, length */
 805         {
 806                 char *endp = rparam + rprcnt;
 807                 res = GETRES(rparam,endp);
 808 
 809                 if (res == 0) {
 810                         /* nothing to do */
 811                 } else if ((res == 5) || (res == 65)) {
 812                         DEBUG(1, ("Access Denied\n"));
 813                 } else if (res == 2221) {
 814                         DEBUG (1, ("User does not exist\n"));
 815                 } else {
 816                         DEBUG(4,("NetUserDelete res=%d\n", res));
 817                 }
 818         } else {
 819                 res = -1;
 820                 DEBUG(4,("NetUserDelete failed\n"));
 821         }
 822 
 823         SAFE_FREE(rparam);
 824         SAFE_FREE(rdata);
 825 
 826         return res;
 827 }
 828 
 829 /****************************************************************************
 830  Call a NetUserAdd - add user to remote server.
 831 ****************************************************************************/
 832 
 833 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
     /* [<][>][^][v][top][bottom][index][help] */
 834 {
 835         char *rparam = NULL;
 836         char *rdata = NULL;
 837         char *p;
 838         unsigned int rdrcnt,rprcnt;
 839         int res = -1;
 840         char param[WORDSIZE                    /* api number    */
 841                 +sizeof(RAP_NetUserAdd2_REQ) /* req string    */
 842                 +sizeof(RAP_USER_INFO_L1)    /* data string   */
 843                 +WORDSIZE                    /* info level    */
 844                 +WORDSIZE                    /* buffer length */
 845                 +WORDSIZE];                  /* reserved      */
 846 
 847         char data[1024];
 848                 /* offset into data of free format strings.  Will be updated */
 849                 /* by PUTSTRINGP macro and end up with total data length.    */
 850         int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
 851                 + RAP_UPASSWD_LEN            /* password        */
 852                 + DWORDSIZE                  /* password age    */
 853                 + WORDSIZE                   /* privilege       */
 854                 + DWORDSIZE                  /* home dir ptr    */
 855                 + DWORDSIZE                  /* comment ptr     */
 856                 + WORDSIZE                   /* flags           */
 857                 + DWORDSIZE;                 /* login script ptr*/
 858 
 859         /* now send a SMBtrans command with api NetUserAdd */
 860         p = make_header(param, RAP_WUserAdd2,
 861                 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
 862 
 863         PUTWORD(p, 1); /* info level */
 864         PUTWORD(p, 0); /* pwencrypt */
 865         if(userinfo->passwrd)
 866                 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
 867         else
 868                 PUTWORD(p, 0); /* password length */
 869 
 870         p = data;
 871         memset(data, '\0', soffset);
 872 
 873         PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
 874         PUTBYTE(p, 0); /* pad byte 0 */
 875         PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
 876         PUTDWORD(p, 0); /* pw age - n.a. on user add */
 877         PUTWORD(p, userinfo->priv);
 878         PUTSTRINGP(p, userinfo->home_dir, data, soffset);
 879         PUTSTRINGP(p, userinfo->comment, data, soffset);
 880         PUTWORD(p, userinfo->userflags);
 881         PUTSTRINGP(p, userinfo->logon_script, data, soffset);
 882 
 883         if (cli_api(cli,
 884                       param, sizeof(param), 1024, /* Param, length, maxlen */
 885                       data, soffset, sizeof(data), /* data, length, maxlen */
 886                       &rparam, &rprcnt,   /* return params, length */
 887                       &rdata, &rdrcnt))   /* return data, length */
 888         {
 889                 char *endp = rparam + rprcnt;
 890                 res = GETRES(rparam, endp);
 891 
 892                 if (res == 0) {
 893                         /* nothing to do */
 894                 } else if ((res == 5) || (res == 65)) {
 895                         DEBUG(1, ("Access Denied\n"));
 896                 } else if (res == 2224) {
 897                         DEBUG (1, ("User already exists\n"));
 898                 } else {
 899                         DEBUG(4,("NetUserAdd res=%d\n", res));
 900                 }
 901         } else {
 902                 res = -1;
 903                 DEBUG(4,("NetUserAdd failed\n"));
 904         }
 905 
 906         SAFE_FREE(rparam);
 907         SAFE_FREE(rdata);
 908 
 909         return res;
 910 }
 911 
 912 /****************************************************************************
 913 call a NetUserEnum - try and list users on a different host
 914 ****************************************************************************/
 915 
 916 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
     /* [<][>][^][v][top][bottom][index][help] */
 917 {
 918         char param[WORDSIZE                 /* api number    */
 919                 +sizeof(RAP_NetUserEnum_REQ) /* parm string   */
 920                 +sizeof(RAP_USER_INFO_L1)    /* return string */
 921                 +WORDSIZE                 /* info level    */
 922                 +WORDSIZE];               /* buffer size   */
 923         char *p;
 924         char *rparam = NULL;
 925         char *rdata = NULL;
 926         unsigned int rprcnt, rdrcnt;
 927         int res = -1;
 928 
 929         memset(param, '\0', sizeof(param));
 930         p = make_header(param, RAP_WUserEnum,
 931                 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
 932         PUTWORD(p,1); /* Info level 1 */
 933         PUTWORD(p,0xFF00); /* Return buffer size */
 934 
 935         /* BB Fix handling of large numbers of users to be returned */
 936         if (cli_api(cli,
 937                         param, PTR_DIFF(p,param),8,
 938                         NULL, 0, CLI_BUFFER_SIZE,
 939                         &rparam, &rprcnt,
 940                         &rdata, &rdrcnt)) {
 941                 char *endp = rparam + rprcnt;
 942                 res = GETRES(rparam,endp);
 943                 cli->rap_error = res;
 944                 if (cli->rap_error != 0) {
 945                         DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
 946                 }
 947         }
 948 
 949         if (!rdata) {
 950                 DEBUG(4,("NetUserEnum no data returned\n"));
 951                 goto out;
 952         }
 953 
 954         if (res == 0 || res == ERRmoredata) {
 955                 int i, converter = 0, count = 0;
 956                 char username[RAP_USERNAME_LEN];
 957                 char userpw[RAP_UPASSWD_LEN];
 958                 char *endp = rparam + rprcnt;
 959                 char *comment, *homedir, *logonscript;
 960                 TALLOC_CTX *frame = talloc_stackframe();
 961 
 962                 p = rparam + WORDSIZE; /* skip result */
 963                 GETWORD(p, converter, endp);
 964                 GETWORD(p, count, endp);
 965 
 966                 endp = rdata + rdrcnt;
 967                 for (i=0,p=rdata;i<count && p < endp;i++) {
 968                         p += rap_getstringf(p,
 969                                         username,
 970                                         RAP_USERNAME_LEN,
 971                                         RAP_USERNAME_LEN,
 972                                         endp);
 973                         p++; /* pad byte */
 974                         p += rap_getstringf(p,
 975                                         userpw,
 976                                         RAP_UPASSWD_LEN,
 977                                         RAP_UPASSWD_LEN,
 978                                         endp);
 979                         p += DWORDSIZE; /* skip password age */
 980                         p += WORDSIZE;  /* skip priv: 0=guest, 1=user, 2=admin */
 981                         p += rap_getstringp(frame,
 982                                         p,
 983                                         &homedir,
 984                                         rdata,
 985                                         converter,
 986                                         endp);
 987                         p += rap_getstringp(frame,
 988                                         p,
 989                                         &comment,
 990                                         rdata,
 991                                         converter,
 992                                         endp);
 993                         p += WORDSIZE;  /* skip flags */
 994                         p += rap_getstringp(frame,
 995                                         p,
 996                                         &logonscript,
 997                                         rdata,
 998                                         converter,
 999                                         endp);
1000                         if (username[0] && comment &&
1001                                         homedir && logonscript) {
1002                                 fn(username,
1003                                         comment,
1004                                         homedir,
1005                                         logonscript,
1006                                         cli);
1007                         }
1008                 }
1009                 TALLOC_FREE(frame);
1010         } else {
1011                 DEBUG(4,("NetUserEnum res=%d\n", res));
1012         }
1013 
1014   out:
1015 
1016         SAFE_FREE(rparam);
1017         SAFE_FREE(rdata);
1018 
1019         return res;
1020 }
1021 
1022 int cli_RNetUserEnum0(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1023                       void (*fn)(const char *, void *),
1024                       void *state)
1025 {
1026         char param[WORDSIZE                 /* api number    */
1027                 +sizeof(RAP_NetUserEnum_REQ) /* parm string   */
1028                 +sizeof(RAP_USER_INFO_L0)    /* return string */
1029                 +WORDSIZE                 /* info level    */
1030                 +WORDSIZE];               /* buffer size   */
1031         char *p;
1032         char *rparam = NULL;
1033         char *rdata = NULL;
1034         unsigned int rprcnt, rdrcnt;
1035         int res = -1;
1036 
1037         memset(param, '\0', sizeof(param));
1038         p = make_header(param, RAP_WUserEnum,
1039                 RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
1040         PUTWORD(p,0); /* Info level 1 */
1041         PUTWORD(p,0xFF00); /* Return buffer size */
1042 
1043         /* BB Fix handling of large numbers of users to be returned */
1044         if (cli_api(cli,
1045                         param, PTR_DIFF(p,param),8,
1046                         NULL, 0, CLI_BUFFER_SIZE,
1047                         &rparam, &rprcnt,
1048                         &rdata, &rdrcnt)) {
1049                 char *endp = rparam + rprcnt;
1050                 res = GETRES(rparam,endp);
1051                 cli->rap_error = res;
1052                 if (cli->rap_error != 0) {
1053                         DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
1054                 }
1055         }
1056 
1057         if (!rdata) {
1058                 DEBUG(4,("NetUserEnum no data returned\n"));
1059                 goto out;
1060         }
1061 
1062         if (res == 0 || res == ERRmoredata) {
1063                 int i, count = 0;
1064                 char *endp = rparam + rprcnt;
1065                 char username[RAP_USERNAME_LEN];
1066 
1067                 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1068                 GETWORD(p, count, endp);
1069 
1070                 endp = rdata + rdrcnt;
1071                 for (i=0,p=rdata;i<count && p < endp;i++) {
1072                         p += rap_getstringf(p,
1073                                         username,
1074                                         RAP_USERNAME_LEN,
1075                                         RAP_USERNAME_LEN,
1076                                         endp);
1077                         if (username[0]) {
1078                                 fn(username, cli);
1079                         }
1080                 }
1081         } else {
1082                 DEBUG(4,("NetUserEnum res=%d\n", res));
1083         }
1084 
1085   out:
1086 
1087         SAFE_FREE(rparam);
1088         SAFE_FREE(rdata);
1089 
1090         return res;
1091 }
1092 
1093 /****************************************************************************
1094  Call a NetFileClose2 - close open file on another session to server.
1095 ****************************************************************************/
1096 
1097 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
     /* [<][>][^][v][top][bottom][index][help] */
1098 {
1099         char *rparam = NULL;
1100         char *rdata = NULL;
1101         char *p;
1102         unsigned int rdrcnt,rprcnt;
1103         char param[WORDSIZE                    /* api number    */
1104                 +sizeof(RAP_WFileClose2_REQ) /* req string    */
1105                 +1                           /* no ret string */
1106                 +DWORDSIZE];                 /* file ID          */
1107         int res = -1;
1108 
1109         /* now send a SMBtrans command with api RNetShareEnum */
1110         p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
1111         PUTDWORD(p, file_id);
1112 
1113         if (cli_api(cli,
1114                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1115                         NULL, 0, 200,       /* data, length, maxlen */
1116                         &rparam, &rprcnt,   /* return params, length */
1117                         &rdata, &rdrcnt))   /* return data, length */
1118         {
1119                 char *endp = rparam + rprcnt;
1120                 res = GETRES(rparam, endp);
1121 
1122                 if (res == 0) {
1123                         /* nothing to do */
1124                 } else if (res == 2314){
1125                         DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
1126                 } else {
1127                         DEBUG(4,("NetFileClose2 res=%d\n", res));
1128                 }
1129         } else {
1130                 res = -1;
1131                 DEBUG(4,("NetFileClose2 failed\n"));
1132         }
1133 
1134         SAFE_FREE(rparam);
1135         SAFE_FREE(rdata);
1136 
1137         return res;
1138 }
1139 
1140 /****************************************************************************
1141  Call a NetFileGetInfo - get information about server file opened from other
1142  workstation.
1143 ****************************************************************************/
1144 
1145 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
     /* [<][>][^][v][top][bottom][index][help] */
1146 {
1147         char *rparam = NULL;
1148         char *rdata = NULL;
1149         char *p;
1150         unsigned int rdrcnt,rprcnt;
1151         int res = -1;
1152         char param[WORDSIZE                      /* api number      */
1153                 +sizeof(RAP_WFileGetInfo2_REQ) /* req string      */
1154                 +sizeof(RAP_FILE_INFO_L3)      /* return string   */
1155                 +DWORDSIZE                     /* file ID          */
1156                 +WORDSIZE                      /* info level      */
1157                 +WORDSIZE];                    /* buffer size     */
1158 
1159         /* now send a SMBtrans command with api RNetShareEnum */
1160         p = make_header(param, RAP_WFileGetInfo2,
1161                 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
1162         PUTDWORD(p, file_id);
1163         PUTWORD(p, 3);  /* info level */
1164         PUTWORD(p, 0x1000);   /* buffer size */
1165         if (cli_api(cli,
1166                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1167                         NULL, 0, 0x1000,  /* data, length, maxlen */
1168                         &rparam, &rprcnt,               /* return params, length */
1169                         &rdata, &rdrcnt))               /* return data, length */
1170         {
1171                 char *endp = rparam + rprcnt;
1172                 res = GETRES(rparam,endp);
1173                 if (res == 0 || res == ERRmoredata) {
1174                         TALLOC_CTX *frame = talloc_stackframe();
1175                         int converter = 0,id = 0, perms = 0, locks = 0;
1176                         char *fpath, *fuser;
1177 
1178                         p = rparam + WORDSIZE; /* skip result */
1179                         GETWORD(p, converter, endp);
1180 
1181                         p = rdata;
1182                         endp = rdata + rdrcnt;
1183 
1184                         GETDWORD(p, id, endp);
1185                         GETWORD(p, perms, endp);
1186                         GETWORD(p, locks, endp);
1187 
1188                         p += rap_getstringp(frame,
1189                                         p,
1190                                         &fpath,
1191                                         rdata,
1192                                         converter,
1193                                         endp);
1194                         p += rap_getstringp(frame,
1195                                         p,
1196                                         &fuser,
1197                                         rdata,
1198                                         converter,
1199                                         endp);
1200 
1201                         if (fpath && fuser) {
1202                                 fn(fpath, fuser, perms, locks, id);
1203                         }
1204 
1205                         TALLOC_FREE(frame);
1206                 } else {
1207                         DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
1208                 }
1209         } else {
1210                 res = -1;
1211                 DEBUG(4,("NetFileGetInfo2 failed\n"));
1212         }
1213 
1214         SAFE_FREE(rparam);
1215         SAFE_FREE(rdata);
1216 
1217         return res;
1218 }
1219 
1220 /****************************************************************************
1221 * Call a NetFileEnum2 - list open files on an SMB server
1222 *
1223 * PURPOSE:  Remotes a NetFileEnum API call to the current server or target
1224 *           server listing the files open via the network (and their
1225 *           corresponding open instance ids)
1226 *
1227 * Dependencies: none
1228 *
1229 * Parameters:
1230 *             cli    - pointer to cli_state structure
1231 *             user   - if present, return only files opened by this remote user
1232 *             base_path - if present, return only files opened below this
1233 *                         base path
1234 *             fn     - display function to invoke for each entry in the result
1235 *
1236 *
1237 * Returns:
1238 *             True      - success
1239 *             False     - failure
1240 *
1241 ****************************************************************************/
1242 
1243 int cli_NetFileEnum(struct cli_state *cli, const char * user,
     /* [<][>][^][v][top][bottom][index][help] */
1244                     const char * base_path,
1245                     void (*fn)(const char *, const char *, uint16, uint16,
1246                                uint32))
1247 {
1248         char *rparam = NULL;
1249         char *rdata = NULL;
1250         char *p;
1251         unsigned int rdrcnt,rprcnt;
1252         char param[WORDSIZE                   /* api number      */
1253                 +sizeof(RAP_WFileEnum2_REQ) /* req string      */
1254                 +sizeof(RAP_FILE_INFO_L3)   /* return string   */
1255                 +1024                        /* base path (opt) */
1256                 +RAP_USERNAME_LEN           /* user name (opt) */
1257                 +WORDSIZE                   /* info level      */
1258                 +WORDSIZE                   /* buffer size     */
1259                 +DWORDSIZE                  /* resume key ?    */
1260                 +DWORDSIZE];                /* resume key ?    */
1261         int count = -1;
1262         int res = -1;
1263 
1264         /* now send a SMBtrans command with api RNetShareEnum */
1265         p = make_header(param, RAP_WFileEnum2,
1266                 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
1267 
1268         PUTSTRING(p, base_path, 1024);
1269         PUTSTRING(p, user, RAP_USERNAME_LEN);
1270         PUTWORD(p, 3); /* info level */
1271         PUTWORD(p, 0xFF00);  /* buffer size */
1272         PUTDWORD(p, 0);  /* zero out the resume key */
1273         PUTDWORD(p, 0);  /* or is this one the resume key? */
1274 
1275         if (cli_api(cli,
1276                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1277                         NULL, 0, 0xFF00,  /* data, length, maxlen */
1278                         &rparam, &rprcnt,               /* return params, length */
1279                         &rdata, &rdrcnt))               /* return data, length */
1280         {
1281                 char *endp = rparam + rprcnt;
1282                 res = GETRES(rparam, endp);
1283 
1284                 if (res == 0 || res == ERRmoredata) {
1285                         TALLOC_CTX *frame = talloc_stackframe();
1286                         int converter = 0, i;
1287 
1288                         p = rparam + WORDSIZE; /* skip result */
1289                         GETWORD(p, converter, endp);
1290                         GETWORD(p, count, endp);
1291 
1292                         p = rdata;
1293                         endp = rdata + rdrcnt;
1294                         for (i=0; i<count && p < endp; i++) {
1295                                 int id = 0, perms = 0, locks = 0;
1296                                 char *fpath, *fuser;
1297 
1298                                 GETDWORD(p, id, endp);
1299                                 GETWORD(p, perms, endp);
1300                                 GETWORD(p, locks, endp);
1301                                 p += rap_getstringp(frame,
1302                                         p,
1303                                         &fpath,
1304                                         rdata,
1305                                         converter,
1306                                         endp);
1307                                 p += rap_getstringp(frame,
1308                                         p,
1309                                         &fuser,
1310                                         rdata,
1311                                         converter,
1312                                         endp);
1313 
1314                                 if (fpath && fuser) {
1315                                         fn(fpath, fuser, perms, locks, id);
1316                                 }
1317                         }  /* BB fix ERRmoredata case to send resume request */
1318                         TALLOC_FREE(frame);
1319                 } else {
1320                         DEBUG(4,("NetFileEnum2 res=%d\n", res));
1321                 }
1322         } else {
1323                 DEBUG(4,("NetFileEnum2 failed\n"));
1324         }
1325 
1326         SAFE_FREE(rparam);
1327         SAFE_FREE(rdata);
1328 
1329         return count;
1330 }
1331 
1332 /****************************************************************************
1333  Call a NetShareAdd - share/export directory on remote server.
1334 ****************************************************************************/
1335 
1336 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
     /* [<][>][^][v][top][bottom][index][help] */
1337 {
1338         char *rparam = NULL;
1339         char *rdata = NULL;
1340         char *p;
1341         unsigned int rdrcnt,rprcnt;
1342         int res = -1;
1343         char param[WORDSIZE                  /* api number    */
1344                 +sizeof(RAP_WShareAdd_REQ) /* req string    */
1345                 +sizeof(RAP_SHARE_INFO_L2) /* return string */
1346                 +WORDSIZE                  /* info level    */
1347                 +WORDSIZE];                /* reserved word */
1348         char data[1024];
1349         /* offset to free format string section following fixed length data.  */
1350         /* will be updated by PUTSTRINGP macro and will end up with total len */
1351         int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad   */
1352                 + WORDSIZE                        /* share type    */
1353                 + DWORDSIZE                       /* comment pointer */
1354                 + WORDSIZE                        /* permissions */
1355                 + WORDSIZE                        /* max users */
1356                 + WORDSIZE                        /* active users */
1357                 + DWORDSIZE                       /* share path */
1358                 + RAP_SPASSWD_LEN + 1;            /* share password + pad */
1359 
1360         memset(param,'\0',sizeof(param));
1361         /* now send a SMBtrans command with api RNetShareAdd */
1362         p = make_header(param, RAP_WshareAdd,
1363                 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
1364         PUTWORD(p, 2); /* info level */
1365         PUTWORD(p, 0); /* reserved word 0 */
1366 
1367         p = data;
1368         PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1369         PUTBYTE(p, 0); /* pad byte 0 */
1370 
1371         PUTWORD(p, sinfo->share_type);
1372         PUTSTRINGP(p, sinfo->comment, data, soffset);
1373         PUTWORD(p, sinfo->perms);
1374         PUTWORD(p, sinfo->maximum_users);
1375         PUTWORD(p, sinfo->active_users);
1376         PUTSTRINGP(p, sinfo->path, data, soffset);
1377         PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1378         SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1379 
1380         if (cli_api(cli,
1381                         param, sizeof(param), 1024, /* Param, length, maxlen */
1382                         data, soffset, sizeof(data), /* data, length, maxlen */
1383                         &rparam, &rprcnt,   /* return params, length */
1384                         &rdata, &rdrcnt))   /* return data, length */
1385         {
1386                 char *endp = rparam + rprcnt;
1387                 res = GETRES(rparam, endp);
1388 
1389                 if (res == 0) {
1390                         /* nothing to do */
1391                 } else {
1392                         DEBUG(4,("NetShareAdd res=%d\n", res));
1393                 }
1394         } else {
1395                 DEBUG(4,("NetShareAdd failed\n"));
1396         }
1397 
1398         SAFE_FREE(rparam);
1399         SAFE_FREE(rdata);
1400 
1401         return res;
1402 }
1403 
1404 /****************************************************************************
1405  Call a NetShareDelete - unshare exported directory on remote server.
1406 ****************************************************************************/
1407 
1408 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
     /* [<][>][^][v][top][bottom][index][help] */
1409 {
1410         char *rparam = NULL;
1411         char *rdata = NULL;
1412         char *p;
1413         unsigned int rdrcnt,rprcnt;
1414         int res = -1;
1415         char param[WORDSIZE                  /* api number    */
1416                 +sizeof(RAP_WShareDel_REQ) /* req string    */
1417                 +1                         /* no ret string */
1418                 +RAP_SHARENAME_LEN         /* share to del  */
1419                 +WORDSIZE];                /* reserved word */
1420 
1421         /* now send a SMBtrans command with api RNetShareDelete */
1422         p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1423         PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1424         PUTWORD(p,0);  /* reserved word MBZ on input */
1425 
1426         if (cli_api(cli,
1427                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1428                         NULL, 0, 200,       /* data, length, maxlen */
1429                         &rparam, &rprcnt,   /* return params, length */
1430                         &rdata, &rdrcnt))   /* return data, length */
1431         {
1432                 char *endp = rparam + rprcnt;
1433                 res = GETRES(rparam, endp);
1434 
1435                 if (res == 0) {
1436                         /* nothing to do */
1437                 } else {
1438                         DEBUG(4,("NetShareDelete res=%d\n", res));
1439                 }
1440         } else {
1441                 DEBUG(4,("NetShareDelete failed\n"));
1442         }
1443 
1444         SAFE_FREE(rparam);
1445         SAFE_FREE(rdata);
1446 
1447         return res;
1448 }
1449 
1450 /*************************************************************************
1451 *
1452 * Function Name:  cli_get_pdc_name
1453 *
1454 * PURPOSE:  Remotes a NetServerEnum API call to the current server
1455 *           requesting the name of a server matching the server
1456 *           type of SV_TYPE_DOMAIN_CTRL (PDC).
1457 *
1458 * Dependencies: none
1459 *
1460 * Parameters:
1461 *             cli       - pointer to cli_state structure
1462 *             workgroup - pointer to string containing name of domain
1463 *             pdc_name  - pointer to string that will contain PDC name
1464 *                         on successful return
1465 *
1466 * Returns:
1467 *             True      - success
1468 *             False     - failure
1469 *
1470 ************************************************************************/
1471 
1472 bool cli_get_pdc_name(struct cli_state *cli, const char *workgroup, char **pdc_name)
     /* [<][>][^][v][top][bottom][index][help] */
1473 {
1474         char *rparam = NULL;
1475         char *rdata = NULL;
1476         unsigned int rdrcnt,rprcnt;
1477         char *p;
1478         char param[WORDSIZE                       /* api number    */
1479                 +sizeof(RAP_NetServerEnum2_REQ) /* req string    */
1480                 +sizeof(RAP_SERVER_INFO_L1)     /* return string */
1481                 +WORDSIZE                       /* info level    */
1482                 +WORDSIZE                       /* buffer size   */
1483                 +DWORDSIZE                      /* server type   */
1484                 +RAP_MACHNAME_LEN];             /* workgroup     */
1485         int count = -1;
1486         int res = -1;
1487 
1488         *pdc_name = NULL;
1489 
1490         /* send a SMBtrans command with api NetServerEnum */
1491         p = make_header(param, RAP_NetServerEnum2,
1492                 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1493         PUTWORD(p, 1); /* info level */
1494         PUTWORD(p, CLI_BUFFER_SIZE);
1495         PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1496         PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1497 
1498         if (cli_api(cli,
1499                         param, PTR_DIFF(p,param), 8,        /* params, length, max */
1500                         NULL, 0, CLI_BUFFER_SIZE,               /* data, length, max */
1501                         &rparam, &rprcnt,                   /* return params, return size */
1502                         &rdata, &rdrcnt                     /* return data, return size */
1503                         )) {
1504 
1505                 char *endp = rparam + rprcnt;
1506                 res = GETRES(rparam, endp);
1507                 cli->rap_error = res;
1508 
1509                 /*
1510                  * We only really care to copy a name if the
1511                  * API succeeded and we got back a name.
1512                  */
1513                 if (cli->rap_error == 0) {
1514                         p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1515                         GETWORD(p, count, endp);
1516                         p = rdata;
1517                         endp = rdata + rdrcnt;
1518 
1519                         if (count > 0) {
1520                                 TALLOC_CTX *frame = talloc_stackframe();
1521                                 char *dcname;
1522                                 p += rap_getstring(frame,
1523                                         p,
1524                                         &dcname,
1525                                         endp);
1526                                 if (dcname) {
1527                                         *pdc_name = SMB_STRDUP(dcname);
1528                                 }
1529                                 TALLOC_FREE(frame);
1530                         }
1531                 } else {
1532                         DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1533                                 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1534                 }
1535         }
1536 
1537         SAFE_FREE(rparam);
1538         SAFE_FREE(rdata);
1539 
1540         return(count > 0);
1541 }
1542 
1543 /*************************************************************************
1544 *
1545 * Function Name:  cli_get_server_domain
1546 *
1547 * PURPOSE:  Remotes a NetWkstaGetInfo API call to the current server
1548 *           requesting wksta_info_10 level information to determine
1549 *           the domain the server belongs to. On success, this
1550 *           routine sets the server_domain field in the cli_state structure
1551 *           to the server's domain name.
1552 *
1553 * Dependencies: none
1554 *
1555 * Parameters:
1556 *             cli       - pointer to cli_state structure
1557 *
1558 * Returns:
1559 *             True      - success
1560 *             False     - failure
1561 *
1562 * Origins:  samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1563 *
1564 ************************************************************************/
1565 
1566 bool cli_get_server_domain(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
1567 {
1568         char *rparam = NULL;
1569         char *rdata = NULL;
1570         unsigned int rdrcnt,rprcnt;
1571         char *p;
1572         char param[WORDSIZE                      /* api number    */
1573                         +sizeof(RAP_WWkstaGetInfo_REQ) /* req string    */
1574                         +sizeof(RAP_WKSTA_INFO_L10)    /* return string */
1575                         +WORDSIZE                      /* info level    */
1576                         +WORDSIZE];                    /* buffer size   */
1577         int res = -1;
1578 
1579         /* send a SMBtrans command with api NetWkstaGetInfo */
1580         p = make_header(param, RAP_WWkstaGetInfo,
1581                 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1582         PUTWORD(p, 10); /* info level */
1583         PUTWORD(p, CLI_BUFFER_SIZE);
1584 
1585         if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1586                         NULL, 0, CLI_BUFFER_SIZE,         /* data, length, max */
1587                         &rparam, &rprcnt,         /* return params, return size */
1588                         &rdata, &rdrcnt)) {       /* return data, return size */
1589                 char *endp = rparam + rprcnt;
1590                 res = GETRES(rparam, endp);
1591 
1592                 if (res == 0) {
1593                         TALLOC_CTX *frame = talloc_stackframe();
1594                         char *server_domain;
1595                         int converter = 0;
1596 
1597                         p = rparam + WORDSIZE;
1598                         GETWORD(p, converter, endp);
1599 
1600                         p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1601                         endp = rdata + rdrcnt;
1602                         p += rap_getstringp(frame,
1603                                 p,
1604                                 &server_domain,
1605                                 rdata,
1606                                 converter,
1607                                 endp);
1608 
1609                         if (server_domain) {
1610                                 fstrcpy(cli->server_domain, server_domain);
1611                         }
1612                         TALLOC_FREE(frame);
1613                 }
1614         }
1615 
1616         SAFE_FREE(rparam);
1617         SAFE_FREE(rdata);
1618 
1619         return(res == 0);
1620 }
1621 
1622 /*************************************************************************
1623 *
1624 * Function Name:  cli_get_server_type
1625 *
1626 * PURPOSE:  Remotes a NetServerGetInfo API call to the current server
1627 *           requesting server_info_1 level information to retrieve
1628 *           the server type.
1629 *
1630 * Dependencies: none
1631 *
1632 * Parameters:
1633 *             cli       - pointer to cli_state structure
1634 *             pstype    - pointer to uint32 to contain returned server type
1635 *
1636 * Returns:
1637 *             True      - success
1638 *             False     - failure
1639 *
1640 * Origins:  samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1641 *
1642 ************************************************************************/
1643 
1644 bool cli_get_server_type(struct cli_state *cli, uint32 *pstype)
     /* [<][>][^][v][top][bottom][index][help] */
1645 {
1646         char *rparam = NULL;
1647         char *rdata = NULL;
1648         unsigned int rdrcnt,rprcnt;
1649         char *p;
1650         char param[WORDSIZE                       /* api number    */
1651                 +sizeof(RAP_WserverGetInfo_REQ) /* req string    */
1652                 +sizeof(RAP_SERVER_INFO_L1)     /* return string */
1653                 +WORDSIZE                       /* info level    */
1654                 +WORDSIZE];                     /* buffer size   */
1655         int res = -1;
1656 
1657         /* send a SMBtrans command with api NetServerGetInfo */
1658         p = make_header(param, RAP_WserverGetInfo,
1659                 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1660         PUTWORD(p, 1); /* info level */
1661         PUTWORD(p, CLI_BUFFER_SIZE);
1662 
1663         if (cli_api(cli,
1664                         param, PTR_DIFF(p,param), 8, /* params, length, max */
1665                         NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1666                         &rparam, &rprcnt,         /* return params, return size */
1667                         &rdata, &rdrcnt           /* return data, return size */
1668                         )) {
1669                 char *endp = rparam + rprcnt;
1670                 res = GETRES(rparam,endp);
1671 
1672                 if (res == 0 || res == ERRmoredata) {
1673                         p = rdata;
1674                         endp = rparam + rprcnt;
1675                         p += 18;
1676                         GETDWORD(p,*pstype,endp);
1677                         *pstype &= ~SV_TYPE_LOCAL_LIST_ONLY;
1678                 }
1679         }
1680 
1681         SAFE_FREE(rparam);
1682         SAFE_FREE(rdata);
1683 
1684         return(res == 0 || res == ERRmoredata);
1685 }
1686 
1687 bool cli_get_server_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1688                          char **servername)
1689 {
1690         char *rparam = NULL;
1691         char *rdata = NULL;
1692         unsigned int rdrcnt,rprcnt;
1693         char *p;
1694         char param[WORDSIZE                       /* api number    */
1695                    +sizeof(RAP_WserverGetInfo_REQ) /* req string    */
1696                    +sizeof(RAP_SERVER_INFO_L1)     /* return string */
1697                    +WORDSIZE                       /* info level    */
1698                    +WORDSIZE];                     /* buffer size   */
1699         bool res = false;
1700         char *endp;
1701         fstring tmp;
1702 
1703         /* send a SMBtrans command with api NetServerGetInfo */
1704         p = make_header(param, RAP_WserverGetInfo,
1705                         RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1706         PUTWORD(p, 1); /* info level */
1707         PUTWORD(p, CLI_BUFFER_SIZE);
1708 
1709         if (!cli_api(cli,
1710                      param, PTR_DIFF(p,param), 8, /* params, length, max */
1711                      NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1712                      &rparam, &rprcnt,         /* return params, return size */
1713                      &rdata, &rdrcnt           /* return data, return size */
1714                     )) {
1715                 goto failed;
1716         }
1717 
1718         endp = rparam + rprcnt;
1719         if (GETRES(rparam, endp) != 0) {
1720                 goto failed;
1721         }
1722 
1723         if (rdrcnt < 16) {
1724                 DEBUG(10, ("invalid data count %d, expected >= 16\n", rdrcnt));
1725                 goto failed;
1726         }
1727 
1728         if (pull_ascii(tmp, rdata, sizeof(tmp)-1, 16, STR_TERMINATE) == -1) {
1729                 DEBUG(10, ("pull_ascii failed\n"));
1730                 goto failed;
1731         }
1732 
1733         if (!(*servername = talloc_strdup(mem_ctx, tmp))) {
1734                 DEBUG(1, ("talloc_strdup failed\n"));
1735                 goto failed;
1736         }
1737 
1738         res = true;
1739 
1740  failed:
1741         SAFE_FREE(rparam);
1742         SAFE_FREE(rdata);
1743         return res;
1744 }
1745 
1746 /*************************************************************************
1747 *
1748 * Function Name:  cli_ns_check_server_type
1749 *
1750 * PURPOSE:  Remotes a NetServerEnum2 API call to the current server
1751 *           requesting server_info_0 level information of machines
1752 *           matching the given server type. If the returned server
1753 *           list contains the machine name contained in cli->desthost
1754 *           then we conclude the server type checks out. This routine
1755 *           is useful to retrieve list of server's of a certain
1756 *           type when all you have is a null session connection and
1757 *           can't remote API calls such as NetWkstaGetInfo or
1758 *           NetServerGetInfo.
1759 *
1760 * Dependencies: none
1761 *
1762 * Parameters:
1763 *             cli       - pointer to cli_state structure
1764 *             workgroup - pointer to string containing domain
1765 *             stype     - server type
1766 *
1767 * Returns:
1768 *             True      - success
1769 *             False     - failure
1770 *
1771 ************************************************************************/
1772 
1773 bool cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
     /* [<][>][^][v][top][bottom][index][help] */
1774 {
1775         char *rparam = NULL;
1776         char *rdata = NULL;
1777         unsigned int rdrcnt,rprcnt;
1778         char *p;
1779         char param[WORDSIZE                       /* api number    */
1780                 +sizeof(RAP_NetServerEnum2_REQ) /* req string    */
1781                 +sizeof(RAP_SERVER_INFO_L0)     /* return string */
1782                 +WORDSIZE                       /* info level    */
1783                 +WORDSIZE                       /* buffer size   */
1784                 +DWORDSIZE                      /* server type   */
1785                 +RAP_MACHNAME_LEN];             /* workgroup     */
1786         bool found_server = false;
1787         int res = -1;
1788 
1789         /* send a SMBtrans command with api NetServerEnum */
1790         p = make_header(param, RAP_NetServerEnum2,
1791                         RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1792         PUTWORD(p, 0); /* info level 0 */
1793         PUTWORD(p, CLI_BUFFER_SIZE);
1794         PUTDWORD(p, stype);
1795         PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1796 
1797         if (cli_api(cli,
1798                         param, PTR_DIFF(p,param), 8, /* params, length, max */
1799                         NULL, 0, CLI_BUFFER_SIZE,  /* data, length, max */
1800                         &rparam, &rprcnt,          /* return params, return size */
1801                         &rdata, &rdrcnt            /* return data, return size */
1802                         )) {
1803                 char *endp = rparam + rprcnt;
1804                 res = GETRES(rparam,endp);
1805                 cli->rap_error = res;
1806 
1807                 if (res == 0 || res == ERRmoredata) {
1808                         int i, count = 0;
1809 
1810                         p = rparam + WORDSIZE + WORDSIZE;
1811                         GETWORD(p, count,endp);
1812 
1813                         p = rdata;
1814                         endp = rdata + rdrcnt;
1815                         for (i = 0;i < count && p < endp;i++, p += 16) {
1816                                 char ret_server[RAP_MACHNAME_LEN];
1817 
1818                                 p += rap_getstringf(p,
1819                                                 ret_server,
1820                                                 RAP_MACHNAME_LEN,
1821                                                 RAP_MACHNAME_LEN,
1822                                                 endp);
1823                                 if (strequal(ret_server, cli->desthost)) {
1824                                         found_server = true;
1825                                         break;
1826                                 }
1827                         }
1828                 } else {
1829                         DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1830                                 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1831                 }
1832         }
1833 
1834         SAFE_FREE(rparam);
1835         SAFE_FREE(rdata);
1836 
1837         return found_server;
1838 }
1839 
1840 /****************************************************************************
1841  Perform a NetWkstaUserLogoff.
1842 ****************************************************************************/
1843 
1844 bool cli_NetWkstaUserLogoff(struct cli_state *cli, const char *user, const char *workstation)
     /* [<][>][^][v][top][bottom][index][help] */
1845 {
1846         char *rparam = NULL;
1847         char *rdata = NULL;
1848         char *p;
1849         unsigned int rdrcnt,rprcnt;
1850         char param[WORDSIZE                           /* api number    */
1851                         +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string    */
1852                         +sizeof(RAP_USER_LOGOFF_INFO_L1)    /* return string */
1853                         +RAP_USERNAME_LEN+1                 /* user name+pad */
1854                         +RAP_MACHNAME_LEN                   /* wksta name    */
1855                         +WORDSIZE                           /* buffer size   */
1856                         +WORDSIZE];                         /* buffer size?  */
1857         char upperbuf[MAX(RAP_USERNAME_LEN,RAP_MACHNAME_LEN)];
1858         int res = -1;
1859         char *tmp = NULL;
1860 
1861         memset(param, 0, sizeof(param));
1862 
1863         /* send a SMBtrans command with api NetWkstaUserLogoff */
1864         p = make_header(param, RAP_WWkstaUserLogoff,
1865                 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1866         PUTDWORD(p, 0); /* Null pointer */
1867         PUTDWORD(p, 0); /* Null pointer */
1868         strlcpy(upperbuf, user, sizeof(upperbuf));
1869         strupper_m(upperbuf);
1870         tmp = upperbuf;
1871         PUTSTRINGF(p, tmp, RAP_USERNAME_LEN);
1872         p++; /* strange format, but ok */
1873         strlcpy(upperbuf, workstation, sizeof(upperbuf));
1874         strupper_m(upperbuf);
1875         tmp = upperbuf;
1876         PUTSTRINGF(p, tmp, RAP_MACHNAME_LEN);
1877         PUTWORD(p, CLI_BUFFER_SIZE);
1878         PUTWORD(p, CLI_BUFFER_SIZE);
1879 
1880         if (cli_api(cli,
1881                         param, PTR_DIFF(p,param),1024,  /* param, length, max */
1882                         NULL, 0, CLI_BUFFER_SIZE,       /* data, length, max */
1883                         &rparam, &rprcnt,               /* return params, return size */
1884                         &rdata, &rdrcnt                 /* return data, return size */
1885                         )) {
1886                 char *endp = rparam + rprcnt;
1887                 res = GETRES(rparam,endp);
1888                 cli->rap_error = res;
1889 
1890                 if (cli->rap_error != 0) {
1891                         DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1892                 }
1893         }
1894 
1895         SAFE_FREE(rparam);
1896         SAFE_FREE(rdata);
1897         return (cli->rap_error == 0);
1898 }
1899 
1900 int cli_NetPrintQEnum(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
1901                 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1902                 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint_t,uint_t,const char*))
1903 {
1904         char param[WORDSIZE                         /* api number    */
1905                 +sizeof(RAP_NetPrintQEnum_REQ)    /* req string    */
1906                 +sizeof(RAP_PRINTQ_INFO_L2)       /* return string */
1907                 +WORDSIZE                         /* info level    */
1908                 +WORDSIZE                         /* buffer size   */
1909                 +sizeof(RAP_SMB_PRINT_JOB_L1)];   /* more ret data */
1910         char *p;
1911         char *rparam = NULL;
1912         char *rdata = NULL;
1913         unsigned int rprcnt, rdrcnt;
1914         int res = -1;
1915 
1916         memset(param, '\0',sizeof(param));
1917         p = make_header(param, RAP_WPrintQEnum,
1918                 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1919         PUTWORD(p,2); /* Info level 2 */
1920         PUTWORD(p,0xFFE0); /* Return buffer size */
1921         PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1922 
1923         if (cli_api(cli,
1924                         param, PTR_DIFF(p,param),1024,
1925                         NULL, 0, CLI_BUFFER_SIZE,
1926                         &rparam, &rprcnt,
1927                         &rdata, &rdrcnt)) {
1928                 char *endp = rparam + rprcnt;
1929                 res = GETRES(rparam, endp);
1930                 cli->rap_error = res;
1931                 if (res != 0) {
1932                         DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1933                 }
1934         }
1935 
1936         if (!rdata) {
1937                 DEBUG(4,("NetPrintQEnum no data returned\n"));
1938                 goto out;
1939         }
1940 
1941         if (res == 0 || res == ERRmoredata) {
1942                 TALLOC_CTX *frame = talloc_stackframe();
1943                 char *endp = rparam + rprcnt;
1944                 int i, converter = 0, count = 0;
1945 
1946                 p = rparam + WORDSIZE;
1947                 GETWORD(p, converter, endp);
1948                 GETWORD(p, count, endp);
1949 
1950                 p = rdata;
1951                 endp = rdata + rdrcnt;
1952                 for (i=0;i<count && p < endp;i++) {
1953                         char qname[RAP_SHARENAME_LEN];
1954                         char *sep_file, *print_proc, *dest, *parms, *comment;
1955                         uint16_t jobcount = 0, priority = 0;
1956                         uint16_t start_time = 0, until_time = 0, status = 0;
1957 
1958                         p += rap_getstringf(p,
1959                                         qname,
1960                                         RAP_SHARENAME_LEN,
1961                                         RAP_SHARENAME_LEN,
1962                                         endp);
1963                         p++; /* pad */
1964                         GETWORD(p, priority, endp);
1965                         GETWORD(p, start_time, endp);
1966                         GETWORD(p, until_time, endp);
1967                         p += rap_getstringp(frame,
1968                                         p,
1969                                         &sep_file,
1970                                         rdata,
1971                                         converter,
1972                                         endp);
1973                         p += rap_getstringp(frame,
1974                                         p,
1975                                         &print_proc,
1976                                         rdata,
1977                                         converter,
1978                                         endp);
1979                         p += rap_getstringp(frame,
1980                                         p,
1981                                         &dest,
1982                                         rdata,
1983                                         converter,
1984                                         endp);
1985                         p += rap_getstringp(frame,
1986                                         p,
1987                                         &parms,
1988                                         rdata,
1989                                         converter,
1990                                         endp);
1991                         p += rap_getstringp(frame,
1992                                         p,
1993                                         &comment,
1994                                         rdata,
1995                                         converter,
1996                                         endp);
1997                         GETWORD(p, status, endp);
1998                         GETWORD(p, jobcount, endp);
1999 
2000                         if (sep_file && print_proc && dest && parms &&
2001                                         comment) {
2002                                 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
2003                                         dest, parms, comment, status, jobcount);
2004                         }
2005 
2006                         if (jobcount) {
2007                                 int j;
2008                                 for (j=0;j<jobcount;j++) {
2009                                         uint16 jid = 0, pos = 0, fsstatus = 0;
2010                                         char ownername[RAP_USERNAME_LEN];
2011                                         char notifyname[RAP_MACHNAME_LEN];
2012                                         char datatype[RAP_DATATYPE_LEN];
2013                                         char *jparms, *jstatus, *jcomment;
2014                                         unsigned int submitted = 0, jsize = 0;
2015 
2016                                         GETWORD(p, jid, endp);
2017                                         p += rap_getstringf(p,
2018                                                         ownername,
2019                                                         RAP_USERNAME_LEN,
2020                                                         RAP_USERNAME_LEN,
2021                                                         endp);
2022                                         p++; /* pad byte */
2023                                         p += rap_getstringf(p,
2024                                                         notifyname,
2025                                                         RAP_MACHNAME_LEN,
2026                                                         RAP_MACHNAME_LEN,
2027                                                         endp);
2028                                         p += rap_getstringf(p,
2029                                                         datatype,
2030                                                         RAP_DATATYPE_LEN,
2031                                                         RAP_DATATYPE_LEN,
2032                                                         endp);
2033                                         p += rap_getstringp(frame,
2034                                                         p,
2035                                                         &jparms,
2036                                                         rdata,
2037                                                         converter,
2038                                                         endp);
2039                                         GETWORD(p, pos, endp);
2040                                         GETWORD(p, fsstatus, endp);
2041                                         p += rap_getstringp(frame,
2042                                                         p,
2043                                                         &jstatus,
2044                                                         rdata,
2045                                                         converter,
2046                                                         endp);
2047                                         GETDWORD(p, submitted, endp);
2048                                         GETDWORD(p, jsize, endp);
2049                                         p += rap_getstringp(frame,
2050                                                         p,
2051                                                         &jcomment,
2052                                                         rdata,
2053                                                         converter,
2054                                                         endp);
2055 
2056                                         if (jparms && jstatus && jcomment) {
2057                                                 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
2058                                                         jstatus, submitted, jsize, jcomment);
2059                                         }
2060                                 }
2061                         }
2062                 }
2063                 TALLOC_FREE(frame);
2064         } else {
2065                 DEBUG(4,("NetPrintQEnum res=%d\n", res));
2066         }
2067 
2068   out:
2069 
2070         SAFE_FREE(rparam);
2071         SAFE_FREE(rdata);
2072 
2073         return res;
2074 }
2075 
2076 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
     /* [<][>][^][v][top][bottom][index][help] */
2077         void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
2078         void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint_t,uint_t,const char*))
2079 {
2080         char param[WORDSIZE                         /* api number    */
2081                 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string    */
2082                 +sizeof(RAP_PRINTQ_INFO_L2)       /* return string */
2083                 +RAP_SHARENAME_LEN                /* printer name  */
2084                 +WORDSIZE                         /* info level    */
2085                 +WORDSIZE                         /* buffer size   */
2086                 +sizeof(RAP_SMB_PRINT_JOB_L1)];   /* more ret data */
2087         char *p;
2088         char *rparam = NULL;
2089         char *rdata = NULL;
2090         unsigned int rprcnt, rdrcnt;
2091         int res = -1;
2092 
2093         memset(param, '\0',sizeof(param));
2094         p = make_header(param, RAP_WPrintQGetInfo,
2095                 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
2096         PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
2097         PUTWORD(p, 2);     /* Info level 2 */
2098         PUTWORD(p,0xFFE0); /* Return buffer size */
2099         PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
2100 
2101         if (cli_api(cli,
2102                         param, PTR_DIFF(p,param),1024,
2103                         NULL, 0, CLI_BUFFER_SIZE,
2104                         &rparam, &rprcnt,
2105                         &rdata, &rdrcnt)) {
2106                 char *endp = rparam + rprcnt;
2107                 res = GETRES(rparam, endp);
2108                 cli->rap_error = res;
2109                 if (res != 0) {
2110                         DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
2111                 }
2112         }
2113 
2114         if (!rdata) {
2115                 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
2116                 goto out;
2117         }
2118 
2119         if (res == 0 || res == ERRmoredata) {
2120                 TALLOC_CTX *frame = talloc_stackframe();
2121                 char *endp = rparam + rprcnt;
2122                 int rsize = 0, converter = 0;
2123                 char qname[RAP_SHARENAME_LEN];
2124                 char *sep_file, *print_proc, *dest, *parms, *comment;
2125                 uint16_t jobcount = 0, priority = 0;
2126                 uint16_t start_time = 0, until_time = 0, status = 0;
2127 
2128                 p = rparam + WORDSIZE;
2129                 GETWORD(p, converter, endp);
2130                 GETWORD(p, rsize, endp);
2131 
2132                 p = rdata;
2133                 endp = rdata + rdrcnt;
2134                 p += rap_getstringf(p,
2135                                 qname,
2136                                 RAP_SHARENAME_LEN,
2137                                 RAP_SHARENAME_LEN,
2138                                 endp);
2139                 p++; /* pad */
2140                 GETWORD(p, priority, endp);
2141                 GETWORD(p, start_time, endp);
2142                 GETWORD(p, until_time, endp);
2143                 p += rap_getstringp(frame,
2144                                 p,
2145                                 &sep_file,
2146                                 rdata,
2147                                 converter,
2148                                 endp);
2149                 p += rap_getstringp(frame,
2150                                 p,
2151                                 &print_proc,
2152                                 rdata,
2153                                 converter,
2154                                 endp);
2155                 p += rap_getstringp(frame,
2156                                 p,
2157                                 &dest,
2158                                 rdata,
2159                                 converter,
2160                                 endp);
2161                 p += rap_getstringp(frame,
2162                                 p,
2163                                 &parms,
2164                                 rdata,
2165                                 converter,
2166                                 endp);
2167                 p += rap_getstringp(frame,
2168                                 p,
2169                                 &comment,
2170                                 rdata,
2171                                 converter,
2172                                 endp);
2173                 GETWORD(p, status, endp);
2174                 GETWORD(p, jobcount, endp);
2175 
2176                 if (sep_file && print_proc && dest &&
2177                                 parms && comment) {
2178                         qfn(qname, priority, start_time, until_time, sep_file, print_proc,
2179                                 dest, parms, comment, status, jobcount);
2180                 }
2181                 if (jobcount) {
2182                         int j;
2183                         for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize)&&
2184                                         p<endp;j++) {
2185                                 uint16_t jid = 0, pos = 0, fsstatus = 0;
2186                                 char ownername[RAP_USERNAME_LEN];
2187                                 char notifyname[RAP_MACHNAME_LEN];
2188                                 char datatype[RAP_DATATYPE_LEN];
2189                                 char *jparms, *jstatus, *jcomment;
2190                                 unsigned int submitted = 0, jsize = 0;
2191 
2192                                 GETWORD(p, jid, endp);
2193                                 p += rap_getstringf(p,
2194                                                 ownername,
2195                                                 RAP_USERNAME_LEN,
2196                                                 RAP_USERNAME_LEN,
2197                                                 endp);
2198                                 p++; /* pad byte */
2199                                 p += rap_getstringf(p,
2200                                                 notifyname,
2201                                                 RAP_MACHNAME_LEN,
2202                                                 RAP_MACHNAME_LEN,
2203                                                 endp);
2204                                 p += rap_getstringf(p,
2205                                                 datatype,
2206                                                 RAP_DATATYPE_LEN,
2207                                                 RAP_DATATYPE_LEN,
2208                                                 endp);
2209                                 p += rap_getstringp(frame,
2210                                                 p,
2211                                                 &jparms,
2212                                                 rdata,
2213                                                 converter,
2214                                                 endp);
2215                                 GETWORD(p, pos,endp);
2216                                 GETWORD(p, fsstatus,endp);
2217                                 p += rap_getstringp(frame,
2218                                                 p,
2219                                                 &jstatus,
2220                                                 rdata,
2221                                                 converter,
2222                                                 endp);
2223                                 GETDWORD(p, submitted,endp);
2224                                 GETDWORD(p, jsize,endp);
2225                                 p += rap_getstringp(frame,
2226                                                 p,
2227                                                 &jcomment,
2228                                                 rdata,
2229                                                 converter,
2230                                                 endp);
2231 
2232                                 if (jparms && jstatus && jcomment) {
2233                                         jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
2234                                                 jstatus, submitted, jsize, jcomment);
2235                                 }
2236                         }
2237                 }
2238                 TALLOC_FREE(frame);
2239         } else {
2240                 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
2241         }
2242 
2243   out:
2244 
2245         SAFE_FREE(rparam);
2246         SAFE_FREE(rdata);
2247 
2248         return res;
2249 }
2250 
2251 /****************************************************************************
2252  Call a NetServiceEnum - list running services on a different host.
2253 ****************************************************************************/
2254 
2255 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
     /* [<][>][^][v][top][bottom][index][help] */
2256 {
2257         char param[WORDSIZE                     /* api number    */
2258                 +sizeof(RAP_NetServiceEnum_REQ) /* parm string   */
2259                 +sizeof(RAP_SERVICE_INFO_L2)    /* return string */
2260                 +WORDSIZE                     /* info level    */
2261                 +WORDSIZE];                   /* buffer size   */
2262         char *p;
2263         char *rparam = NULL;
2264         char *rdata = NULL;
2265         unsigned int rprcnt, rdrcnt;
2266         int res = -1;
2267 
2268         memset(param, '\0', sizeof(param));
2269         p = make_header(param, RAP_WServiceEnum,
2270                 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
2271         PUTWORD(p,2); /* Info level 2 */
2272         PUTWORD(p,0xFFE0); /* Return buffer size */
2273 
2274         if (cli_api(cli,
2275                         param, PTR_DIFF(p,param),8,
2276                         NULL, 0, 0xFFE0 /* data area size */,
2277                         &rparam, &rprcnt,
2278                         &rdata, &rdrcnt)) {
2279                 char *endp = rparam + rprcnt;
2280                 res = GETRES(rparam, endp);
2281                 cli->rap_error = res;
2282                 if(cli->rap_error == 234) {
2283                         DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
2284                 } else if (cli->rap_error != 0) {
2285                         DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
2286                 }
2287         }
2288 
2289         if (!rdata) {
2290                 DEBUG(4,("NetServiceEnum no data returned\n"));
2291                 goto out;
2292         }
2293 
2294         if (res == 0 || res == ERRmoredata) {
2295                 char *endp = rparam + rprcnt;
2296                 int i, count = 0;
2297 
2298                 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
2299                 GETWORD(p, count,endp);
2300 
2301                 endp = rdata + rdrcnt;
2302                 for (i=0,p=rdata;i<count && p < endp;i++) {
2303                         char comment[RAP_SRVCCMNT_LEN];
2304                         char servicename[RAP_SRVCNAME_LEN];
2305 
2306                         p += rap_getstringf(p,
2307                                         servicename,
2308                                         RAP_SRVCNAME_LEN,
2309                                         RAP_SRVCNAME_LEN,
2310                                         endp);
2311                         p+=8; /* pass status words */
2312                         p += rap_getstringf(p,
2313                                         comment,
2314                                         RAP_SRVCCMNT_LEN,
2315                                         RAP_SRVCCMNT_LEN,
2316                                         endp);
2317 
2318                         if (servicename[0]) {
2319                                 fn(servicename, comment, cli);  /* BB add status too */
2320                         }
2321                 }
2322         } else {
2323                 DEBUG(4,("NetServiceEnum res=%d\n", res));
2324         }
2325 
2326   out:
2327 
2328         SAFE_FREE(rparam);
2329         SAFE_FREE(rdata);
2330 
2331         return res;
2332 }
2333 
2334 /****************************************************************************
2335  Call a NetSessionEnum - list workstations with sessions to an SMB server.
2336 ****************************************************************************/
2337 
2338 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint_t, uint_t, uint_t, char *))
     /* [<][>][^][v][top][bottom][index][help] */
2339 {
2340         char param[WORDSIZE                       /* api number    */
2341                 +sizeof(RAP_NetSessionEnum_REQ) /* parm string   */
2342                 +sizeof(RAP_SESSION_INFO_L2)    /* return string */
2343                 +WORDSIZE                       /* info level    */
2344                 +WORDSIZE];                     /* buffer size   */
2345         char *p;
2346         char *rparam = NULL;
2347         char *rdata = NULL;
2348         unsigned int rprcnt, rdrcnt;
2349         int res = -1;
2350 
2351         memset(param, '\0', sizeof(param));
2352         p = make_header(param, RAP_WsessionEnum,
2353                         RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
2354         PUTWORD(p,2);    /* Info level 2 */
2355         PUTWORD(p,0xFF); /* Return buffer size */
2356 
2357         if (cli_api(cli,
2358                         param, PTR_DIFF(p,param),8,
2359                         NULL, 0, CLI_BUFFER_SIZE,
2360                         &rparam, &rprcnt,
2361                         &rdata, &rdrcnt)) {
2362                 char *endp = rparam + rprcnt;
2363                 res = GETRES(rparam, endp);
2364                 cli->rap_error = res;
2365                 if (res != 0) {
2366                         DEBUG(1,("NetSessionEnum gave error %d\n", res));
2367                 }
2368         }
2369 
2370         if (!rdata) {
2371                 DEBUG(4,("NetSesssionEnum no data returned\n"));
2372                 goto out;
2373         }
2374 
2375         if (res == 0 || res == ERRmoredata) {
2376                 TALLOC_CTX *frame = talloc_stackframe();
2377                 char *endp = rparam + rprcnt;
2378                 int i, converter = 0, count = 0;
2379 
2380                 p = rparam + WORDSIZE;
2381                 GETWORD(p, converter, endp);
2382                 GETWORD(p, count, endp);
2383 
2384                 endp = rdata + rdrcnt;
2385                 for (i=0,p=rdata;i<count && p < endp;i++) {
2386                         char *wsname, *username, *clitype_name;
2387                         uint16_t num_conns = 0, num_opens = 0, num_users = 0;
2388                         unsigned int sess_time = 0, idle_time = 0, user_flags = 0;
2389 
2390                         p += rap_getstringp(frame,
2391                                         p,
2392                                         &wsname,
2393                                         rdata,
2394                                         converter,
2395                                         endp);
2396                         p += rap_getstringp(frame,
2397                                         p,
2398                                         &username,
2399                                         rdata,
2400                                         converter,
2401                                         endp);
2402                         GETWORD(p, num_conns, endp);
2403                         GETWORD(p, num_opens, endp);
2404                         GETWORD(p, num_users, endp);
2405                         GETDWORD(p, sess_time, endp);
2406                         GETDWORD(p, idle_time, endp);
2407                         GETDWORD(p, user_flags, endp);
2408                         p += rap_getstringp(frame,
2409                                         p,
2410                                         &clitype_name,
2411                                         rdata,
2412                                         converter,
2413                                         endp);
2414 
2415                         if (wsname && username && clitype_name) {
2416                                 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
2417                                         idle_time, user_flags, clitype_name);
2418                         }
2419                 }
2420                 TALLOC_FREE(frame);
2421         } else {
2422                 DEBUG(4,("NetSessionEnum res=%d\n", res));
2423         }
2424 
2425   out:
2426 
2427         SAFE_FREE(rparam);
2428         SAFE_FREE(rdata);
2429 
2430         return res;
2431 }
2432 
2433 /****************************************************************************
2434  Call a NetSessionGetInfo - get information about other session to an SMB server.
2435 ****************************************************************************/
2436 
2437 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation,
     /* [<][>][^][v][top][bottom][index][help] */
2438                 void (*fn)(const char *, const char *, uint16, uint16, uint16, uint_t, uint_t, uint_t, const char *))
2439 {
2440         char param[WORDSIZE                          /* api number    */
2441                 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string    */
2442                 +sizeof(RAP_SESSION_INFO_L2)       /* return string */
2443                 +RAP_MACHNAME_LEN                  /* wksta name    */
2444                 +WORDSIZE                          /* info level    */
2445                 +WORDSIZE];                        /* buffer size   */
2446         char *p;
2447         char *rparam = NULL;
2448         char *rdata = NULL;
2449         unsigned int rprcnt, rdrcnt;
2450         char *endp;
2451         int res = -1;
2452 
2453         memset(param, '\0', sizeof(param));
2454         p = make_header(param, RAP_WsessionGetInfo,
2455                         RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
2456         PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
2457         PUTWORD(p,2); /* Info level 2 */
2458         PUTWORD(p,0xFF); /* Return buffer size */
2459 
2460         if (cli_api(cli,
2461                         param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2462                         NULL, 0, CLI_BUFFER_SIZE,
2463                         &rparam, &rprcnt,
2464                         &rdata, &rdrcnt)) {
2465                 endp = rparam + rprcnt;
2466                 res = GETRES(rparam, endp);
2467                 cli->rap_error = res;
2468                 if (cli->rap_error != 0) {
2469                         DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
2470                 }
2471         }
2472 
2473         if (!rdata) {
2474                 DEBUG(4,("NetSessionGetInfo no data returned\n"));
2475                 goto out;
2476         }
2477 
2478         endp = rparam + rprcnt;
2479         res = GETRES(rparam, endp);
2480 
2481         if (res == 0 || res == ERRmoredata) {
2482                 TALLOC_CTX *frame = talloc_stackframe();
2483                 int converter = 0;
2484                 char *wsname, *username, *clitype_name;
2485                 uint16_t num_conns = 0, num_opens = 0, num_users = 0;
2486                 unsigned int sess_time = 0, idle_time = 0, user_flags = 0;
2487 
2488                 p = rparam + WORDSIZE;
2489                 GETWORD(p, converter,endp);
2490                 p += WORDSIZE;            /* skip rsize */
2491 
2492                 p = rdata;
2493                 endp = rdata + rdrcnt;
2494                 p += rap_getstringp(frame,
2495                                 p,
2496                                 &wsname,
2497                                 rdata,
2498                                 converter,
2499                                 endp);
2500                 p += rap_getstringp(frame,
2501                                 p,
2502                                 &username,
2503                                 rdata,
2504                                 converter,
2505                                 endp);
2506                 GETWORD(p, num_conns, endp);
2507                 GETWORD(p, num_opens, endp);
2508                 GETWORD(p, num_users, endp);
2509                 GETDWORD(p, sess_time, endp);
2510                 GETDWORD(p, idle_time, endp);
2511                 GETDWORD(p, user_flags, endp);
2512                 p += rap_getstringp(frame,
2513                                 p,
2514                                 &clitype_name,
2515                                 rdata,
2516                                 converter,
2517                                 endp);
2518 
2519                 if (wsname && username && clitype_name) {
2520                         fn(wsname, username, num_conns, num_opens, num_users, sess_time,
2521                                 idle_time, user_flags, clitype_name);
2522                 }
2523                 TALLOC_FREE(frame);
2524         } else {
2525                 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
2526         }
2527 
2528   out:
2529 
2530         SAFE_FREE(rparam);
2531         SAFE_FREE(rdata);
2532 
2533         return res;
2534 }
2535 
2536 /****************************************************************************
2537  Call a NetSessionDel - close a session to an SMB server.
2538 ****************************************************************************/
2539 
2540 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
     /* [<][>][^][v][top][bottom][index][help] */
2541 {
2542         char param[WORDSIZE                      /* api number       */
2543                 +sizeof(RAP_NetSessionDel_REQ) /* req string       */
2544                 +1                             /* no return string */
2545                 +RAP_MACHNAME_LEN              /* workstation name */
2546                 +WORDSIZE];                    /* reserved (0)     */
2547         char *p;
2548         char *rparam = NULL;
2549         char *rdata = NULL;
2550         unsigned int rprcnt, rdrcnt;
2551         int res = -1;
2552 
2553         memset(param, '\0', sizeof(param));
2554         p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
2555         PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
2556         PUTWORD(p,0); /* reserved word of 0 */
2557 
2558         if (cli_api(cli,
2559                         param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2560                         NULL, 0, 200,       /* data, length, maxlen */
2561                         &rparam, &rprcnt,   /* return params, length */
2562                         &rdata, &rdrcnt))   /* return data, length */
2563         {
2564                 char *endp = rparam + rprcnt;
2565                 res = GETRES(rparam, endp);
2566                 cli->rap_error = res;
2567 
2568                 if (res == 0) {
2569                         /* nothing to do */
2570                 } else {
2571                         DEBUG(4,("NetFileClose2 res=%d\n", res));
2572                 }
2573         } else {
2574                 res = -1;
2575                 DEBUG(4,("NetFileClose2 failed\n"));
2576         }
2577 
2578         SAFE_FREE(rparam);
2579         SAFE_FREE(rdata);
2580 
2581         return res;
2582 }
2583 
2584 int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier,
     /* [<][>][^][v][top][bottom][index][help] */
2585                         void (*fn)(uint16_t conid, uint16_t contype,
2586                                 uint16_t numopens, uint16_t numusers,
2587                                 uint32_t contime, const char *username,
2588                                 const char *netname))
2589 {
2590         char param[WORDSIZE                          /* api number    */
2591                 +sizeof(RAP_NetConnectionEnum_REQ) /* req string    */
2592                 +sizeof(RAP_CONNECTION_INFO_L1)    /* return string */
2593                 +RAP_MACHNAME_LEN                  /* wksta name    */
2594                 +WORDSIZE                          /* info level    */
2595                 +WORDSIZE];                        /* buffer size   */
2596         char *p;
2597         char *rparam = NULL;
2598         char *rdata = NULL;
2599         unsigned int rprcnt, rdrcnt;
2600         int res = -1;
2601 
2602         memset(param, '\0', sizeof(param));
2603         p = make_header(param, RAP_WconnectionEnum,
2604                 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2605         PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2606         PUTWORD(p,1);            /* Info level 1 */
2607         PUTWORD(p,0xFFE0);       /* Return buffer size */
2608 
2609         if (cli_api(cli,
2610                         param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2611                         NULL, 0, CLI_BUFFER_SIZE,
2612                         &rparam, &rprcnt,
2613                         &rdata, &rdrcnt)) {
2614                 char *endp = rparam + rprcnt;
2615                 res = GETRES(rparam, endp);
2616                 cli->rap_error = res;
2617                 if (res != 0) {
2618                         DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2619                 }
2620         }
2621 
2622         if (!rdata) {
2623                 DEBUG(4,("NetConnectionEnum no data returned\n"));
2624                 goto out;
2625         }
2626 
2627         if (res == 0 || res == ERRmoredata) {
2628                 TALLOC_CTX *frame = talloc_stackframe();
2629                 char *endp = rparam + rprcnt;
2630                 int i, converter = 0, count = 0;
2631 
2632                 p = rparam + WORDSIZE;
2633                 GETWORD(p, converter, endp);
2634                 GETWORD(p, count, endp);
2635 
2636                 endp = rdata + rdrcnt;
2637                 for (i=0,p=rdata;i<count && p < endp;i++) {
2638                         char *netname, *username;
2639                         uint16_t conn_id = 0, conn_type = 0, num_opens = 0, num_users = 0;
2640                         unsigned int conn_time = 0;
2641 
2642                         GETWORD(p,conn_id, endp);
2643                         GETWORD(p,conn_type, endp);
2644                         GETWORD(p,num_opens, endp);
2645                         GETWORD(p,num_users, endp);
2646                         GETDWORD(p,conn_time, endp);
2647                         p += rap_getstringp(frame,
2648                                         p,
2649                                         &username,
2650                                         rdata,
2651                                         converter,
2652                                         endp);
2653                         p += rap_getstringp(frame,
2654                                         p,
2655                                         &netname,
2656                                         rdata,
2657                                         converter,
2658                                         endp);
2659 
2660                         if (username && netname) {
2661                                 fn(conn_id, conn_type, num_opens, num_users, conn_time,
2662                                         username, netname);
2663                         }
2664                 }
2665                 TALLOC_FREE(frame);
2666         } else {
2667                 DEBUG(4,("NetConnectionEnum res=%d\n", res));
2668         }
2669 
2670   out:
2671 
2672         SAFE_FREE(rdata);
2673         SAFE_FREE(rparam);
2674         return res;
2675 }

/* [<][>][^][v][top][bottom][index][help] */