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