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