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