r19263: Be more accurate in telling what the sitename problem is in this DEBUG
[Samba.git] / source3 / libsmb / clirap2.c
blobd6a44f4ea223fdcc531884ce33927d5f73468766
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)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /*****************************************************/
24 /* */
25 /* Additional RAP functionality */
26 /* */
27 /* RAP is the original SMB RPC, documented */
28 /* by Microsoft and X/Open in the 1990s and */
29 /* supported by most SMB/CIFS servers although */
30 /* it is unlikely that any one implementation */
31 /* supports all RAP command codes since some */
32 /* are quite obsolete and a few are specific */
33 /* to a particular network operating system */
34 /* */
35 /* Although it has largely been replaced */
36 /* for complex remote admistration and management */
37 /* (of servers) by the relatively newer */
38 /* DCE/RPC based remote API (which better handles */
39 /* large >64K data structures), there are many */
40 /* important administrative and resource location */
41 /* tasks and user tasks (e.g. password change) */
42 /* that are performed via RAP. */
43 /* */
44 /* Although a few of the RAP calls are implemented */
45 /* in the Samba client library already (clirap.c) */
46 /* the new ones are in clirap2.c for easy patching */
47 /* and integration and a corresponding header */
48 /* file, rap.h, has been created. */
49 /* */
50 /* This is based on data from the CIFS spec */
51 /* and the LAN Server and LAN Manager */
52 /* Programming Reference books and published */
53 /* RAP document and CIFS forum postings and */
54 /* lots of trial and error */
55 /* */
56 /* Function names changed from API_ (as they are */
57 /* in the CIFS specification) to RAP_ in order */
58 /* to avoid confusion with other API calls */
59 /* sent via DCE RPC */
60 /* */
61 /*****************************************************/
63 /*****************************************************/
64 /* */
65 /* cifsrap.c already includes support for: */
66 /* */
67 /* WshareEnum ( API number 0, level 1) */
68 /* NetServerEnum2 (API num 104, level 1) */
69 /* WWkstaUserLogon (132) */
70 /* SamOEMchgPasswordUser2_P (214) */
71 /* */
72 /* cifsprint.c already includes support for: */
73 /* */
74 /* WPrintJobEnum (API num 76, level 2) */
75 /* WPrintJobDel (API num 81) */
76 /* */
77 /*****************************************************/
79 #include "includes.h"
81 #define WORDSIZE 2
82 #define DWORDSIZE 4
84 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
85 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
86 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
87 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
88 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
89 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
90 #define GETRES(p) p ? SVAL(p,0) : -1
91 /* put string s at p with max len n and increment p past string */
92 #define PUTSTRING(p,s,n) do {\
93 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
94 p = skip_string(p,1);\
95 } while(0)
96 /* put string s and p, using fixed len l, and increment p by l */
97 #define PUTSTRINGF(p,s,l) do {\
98 push_ascii(p,s?s:"",l,STR_TERMINATE);\
99 p += l;\
100 } while (0)
101 /* put string pointer at p, supplying offset o from rdata r, store */
102 /* dword offset at p, increment p by 4 and o by length of s. This */
103 /* means on the first call, you must calc the offset yourself! */
104 #define PUTSTRINGP(p,s,r,o) do {\
105 if (s) {\
106 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
107 PUTDWORD(p,o);\
108 o += strlen(s) + 1;\
109 } else PUTDWORD(p,0);\
110 }while(0);
111 /* get asciiz string s from p, increment p past string */
112 #define GETSTRING(p,s) do {\
113 pull_ascii_pstring(s,p);\
114 p = skip_string(p,1);\
115 } while(0)
116 /* get fixed length l string s from p, increment p by l */
117 #define GETSTRINGF(p,s,l) do {\
118 pull_ascii_pstring(s,p);\
119 p += l;\
120 } while(0)
121 /* get string s from offset (obtained at p) from rdata r - converter c */
122 #define GETSTRINGP(p,s,r,c) do {\
123 uint32 off;\
124 GETDWORD(p,off);\
125 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
126 pull_ascii_pstring(s, off?(r+off-c):"");\
127 } while(0)
129 static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
131 PUTWORD(param,apinum);
132 if (reqfmt)
133 PUTSTRING(param,reqfmt,0);
134 else
135 *param++ = (char) 0;
137 if (datafmt)
138 PUTSTRING(param,datafmt,0);
139 else
140 *param++ = (char) 0;
142 return param;
146 /****************************************************************************
147 call a NetGroupDelete - delete user group from remote server
148 ****************************************************************************/
149 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
151 char *rparam = NULL;
152 char *rdata = NULL;
153 char *p;
154 unsigned int rdrcnt,rprcnt;
155 int res;
156 char param[WORDSIZE /* api number */
157 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
158 +1 /* no ret string */
159 +RAP_GROUPNAME_LEN /* group to del */
160 +WORDSIZE]; /* reserved word */
162 /* now send a SMBtrans command with api GroupDel */
163 p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);
164 PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
165 PUTWORD(p,0); /* reserved word MBZ on input */
167 if (cli_api(cli,
168 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
169 NULL, 0, 200, /* data, length, maxlen */
170 &rparam, &rprcnt, /* return params, length */
171 &rdata, &rdrcnt)) /* return data, length */
173 res = GETRES(rparam);
175 if (res == 0) {
176 /* nothing to do */
178 else if ((res == 5) || (res == 65)) {
179 DEBUG(1, ("Access Denied\n"));
181 else if (res == 2220) {
182 DEBUG (1, ("Group does not exist\n"));
184 else {
185 DEBUG(4,("NetGroupDelete res=%d\n", res));
187 } else {
188 res = -1;
189 DEBUG(4,("NetGroupDelete failed\n"));
192 SAFE_FREE(rparam);
193 SAFE_FREE(rdata);
195 return res;
198 /****************************************************************************
199 call a NetGroupAdd - add user group to remote server
200 ****************************************************************************/
201 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
203 char *rparam = NULL;
204 char *rdata = NULL;
205 char *p;
206 unsigned int rdrcnt,rprcnt;
207 int res;
208 char param[WORDSIZE /* api number */
209 +sizeof(RAP_NetGroupAdd_REQ) /* req string */
210 +sizeof(RAP_GROUP_INFO_L1) /* return string */
211 +WORDSIZE /* info level */
212 +WORDSIZE]; /* reserved word */
214 /* offset into data of free format strings. Will be updated */
215 /* by PUTSTRINGP macro and end up with total data length. */
216 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
217 char *data;
218 size_t data_size;
220 /* Allocate data. */
221 data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
223 data = SMB_MALLOC_ARRAY(char, data_size);
224 if (!data) {
225 DEBUG (1, ("Malloc fail\n"));
226 return -1;
229 /* now send a SMBtrans command with api WGroupAdd */
231 p = make_header(param, RAP_WGroupAdd,
232 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
233 PUTWORD(p, 1); /* info level */
234 PUTWORD(p, 0); /* reserved word 0 */
236 p = data;
237 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
238 PUTBYTE(p, 0); /* pad byte 0 */
239 PUTSTRINGP(p, grinfo->comment, data, soffset);
241 if (cli_api(cli,
242 param, sizeof(param), 1024, /* Param, length, maxlen */
243 data, soffset, sizeof(data), /* data, length, maxlen */
244 &rparam, &rprcnt, /* return params, length */
245 &rdata, &rdrcnt)) /* return data, length */
247 res = GETRES(rparam);
249 if (res == 0) {
250 /* nothing to do */
251 } else if ((res == 5) || (res == 65)) {
252 DEBUG(1, ("Access Denied\n"));
254 else if (res == 2223) {
255 DEBUG (1, ("Group already exists\n"));
257 else {
258 DEBUG(4,("NetGroupAdd res=%d\n", res));
260 } else {
261 res = -1;
262 DEBUG(4,("NetGroupAdd failed\n"));
265 SAFE_FREE(data);
266 SAFE_FREE(rparam);
267 SAFE_FREE(rdata);
269 return res;
272 /****************************************************************************
273 call a NetGroupEnum - try and list user groups on a different host
274 ****************************************************************************/
275 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
277 char param[WORDSIZE /* api number */
278 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
279 +sizeof(RAP_GROUP_INFO_L1) /* return string */
280 +WORDSIZE /* info level */
281 +WORDSIZE]; /* buffer size */
282 char *p;
283 char *rparam = NULL;
284 char *rdata = NULL;
285 unsigned int rprcnt, rdrcnt;
286 int res = -1;
289 memset(param, '\0', sizeof(param));
290 p = make_header(param, RAP_WGroupEnum,
291 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
292 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
293 PUTWORD(p,0xFFE0); /* Return buffer size */
295 if (cli_api(cli,
296 param, PTR_DIFF(p,param),8,
297 NULL, 0, 0xFFE0 /* data area size */,
298 &rparam, &rprcnt,
299 &rdata, &rdrcnt)) {
300 res = GETRES(rparam);
301 cli->rap_error = res;
302 if(cli->rap_error == 234)
303 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
304 else if (cli->rap_error != 0) {
305 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
309 if (rdata) {
310 if (res == 0 || res == ERRmoredata) {
311 int i, converter, count;
313 p = rparam + WORDSIZE; /* skip result */
314 GETWORD(p, converter);
315 GETWORD(p, count);
317 for (i=0,p=rdata;i<count;i++) {
318 pstring comment;
319 char groupname[RAP_GROUPNAME_LEN];
321 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
322 p++; /* pad byte */
323 GETSTRINGP(p, comment, rdata, converter);
325 fn(groupname, comment, cli);
327 } else {
328 DEBUG(4,("NetGroupEnum res=%d\n", res));
330 } else {
331 DEBUG(4,("NetGroupEnum no data returned\n"));
334 SAFE_FREE(rparam);
335 SAFE_FREE(rdata);
337 return res;
340 int cli_RNetGroupEnum0(struct cli_state *cli,
341 void (*fn)(const char *, void *),
342 void *state)
344 char param[WORDSIZE /* api number */
345 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
346 +sizeof(RAP_GROUP_INFO_L0) /* return string */
347 +WORDSIZE /* info level */
348 +WORDSIZE]; /* buffer size */
349 char *p;
350 char *rparam = NULL;
351 char *rdata = NULL;
352 unsigned int rprcnt, rdrcnt;
353 int res = -1;
356 memset(param, '\0', sizeof(param));
357 p = make_header(param, RAP_WGroupEnum,
358 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0);
359 PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
360 is the resume count, at least
361 that's what smbd believes... */
362 PUTWORD(p,0xFFE0); /* Return buffer size */
364 if (cli_api(cli,
365 param, PTR_DIFF(p,param),8,
366 NULL, 0, 0xFFE0 /* data area size */,
367 &rparam, &rprcnt,
368 &rdata, &rdrcnt)) {
369 res = GETRES(rparam);
370 cli->rap_error = res;
371 if(cli->rap_error == 234)
372 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
373 else if (cli->rap_error != 0) {
374 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
378 if (rdata) {
379 if (res == 0 || res == ERRmoredata) {
380 int i, count;
382 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
383 GETWORD(p, count);
385 for (i=0,p=rdata;i<count;i++) {
386 char groupname[RAP_GROUPNAME_LEN];
387 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
388 fn(groupname, cli);
390 } else {
391 DEBUG(4,("NetGroupEnum res=%d\n", res));
393 } else {
394 DEBUG(4,("NetGroupEnum no data returned\n"));
397 SAFE_FREE(rparam);
398 SAFE_FREE(rdata);
400 return res;
403 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
405 char *rparam = NULL;
406 char *rdata = NULL;
407 char *p;
408 unsigned int rdrcnt,rprcnt;
409 int res;
410 char param[WORDSIZE /* api number */
411 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
412 +1 /* no ret string */
413 +RAP_GROUPNAME_LEN /* group name */
414 +RAP_USERNAME_LEN]; /* user to del */
416 /* now send a SMBtrans command with api GroupMemberAdd */
417 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
418 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
419 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
421 if (cli_api(cli,
422 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
423 NULL, 0, 200, /* data, length, maxlen */
424 &rparam, &rprcnt, /* return params, length */
425 &rdata, &rdrcnt)) /* return data, length */
427 res = GETRES(rparam);
429 switch(res) {
430 case 0:
431 break;
432 case 5:
433 case 65:
434 DEBUG(1, ("Access Denied\n"));
435 break;
436 case 50:
437 DEBUG(1, ("Not supported by server\n"));
438 break;
439 case 2220:
440 DEBUG(1, ("Group does not exist\n"));
441 break;
442 case 2221:
443 DEBUG(1, ("User does not exist\n"));
444 break;
445 case 2237:
446 DEBUG(1, ("User is not in group\n"));
447 break;
448 default:
449 DEBUG(4,("NetGroupDelUser res=%d\n", res));
451 } else {
452 res = -1;
453 DEBUG(4,("NetGroupDelUser failed\n"));
456 SAFE_FREE(rparam);
457 SAFE_FREE(rdata);
459 return res;
462 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
464 char *rparam = NULL;
465 char *rdata = NULL;
466 char *p;
467 unsigned int rdrcnt,rprcnt;
468 int res;
469 char param[WORDSIZE /* api number */
470 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
471 +1 /* no ret string */
472 +RAP_GROUPNAME_LEN /* group name */
473 +RAP_USERNAME_LEN]; /* user to add */
475 /* now send a SMBtrans command with api GroupMemberAdd */
476 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
477 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
478 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
480 if (cli_api(cli,
481 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
482 NULL, 0, 200, /* data, length, maxlen */
483 &rparam, &rprcnt, /* return params, length */
484 &rdata, &rdrcnt)) /* return data, length */
486 res = GETRES(rparam);
488 switch(res) {
489 case 0:
490 break;
491 case 5:
492 case 65:
493 DEBUG(1, ("Access Denied\n"));
494 break;
495 case 50:
496 DEBUG(1, ("Not supported by server\n"));
497 break;
498 case 2220:
499 DEBUG(1, ("Group does not exist\n"));
500 break;
501 case 2221:
502 DEBUG(1, ("User does not exist\n"));
503 break;
504 default:
505 DEBUG(4,("NetGroupAddUser res=%d\n", res));
507 } else {
508 res = -1;
509 DEBUG(4,("NetGroupAddUser failed\n"));
512 SAFE_FREE(rparam);
513 SAFE_FREE(rdata);
515 return res;
519 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
521 char *rparam = NULL;
522 char *rdata = NULL;
523 char *p;
524 unsigned int rdrcnt,rprcnt;
525 int res = -1;
526 char param[WORDSIZE /* api number */
527 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
528 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
529 +RAP_GROUPNAME_LEN /* group name */
530 +WORDSIZE /* info level */
531 +WORDSIZE]; /* buffer size */
533 /* now send a SMBtrans command with api GroupGetUsers */
534 p = make_header(param, RAP_WGroupGetUsers,
535 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
536 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
537 PUTWORD(p,0); /* info level 0 */
538 PUTWORD(p,0xFFE0); /* return buffer size */
540 if (cli_api(cli,
541 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
542 NULL, 0, CLI_BUFFER_SIZE,
543 &rparam, &rprcnt,
544 &rdata, &rdrcnt)) {
545 res = GETRES(rparam);
546 cli->rap_error = res;
547 if (res != 0) {
548 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
551 if (rdata) {
552 if (res == 0 || res == ERRmoredata) {
553 int i, count;
554 fstring username;
555 p = rparam + WORDSIZE + WORDSIZE;
556 GETWORD(p, count);
558 for (i=0,p=rdata; i<count; i++) {
559 GETSTRINGF(p, username, RAP_USERNAME_LEN);
560 fn(username, state);
562 } else {
563 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
565 } else {
566 DEBUG(4,("NetGroupGetUsers no data returned\n"));
568 SAFE_FREE(rdata);
569 SAFE_FREE(rparam);
570 return res;
573 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
575 char *rparam = NULL;
576 char *rdata = NULL;
577 char *p;
578 unsigned int rdrcnt,rprcnt;
579 int res = -1;
580 char param[WORDSIZE /* api number */
581 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
582 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
583 +RAP_USERNAME_LEN /* user name */
584 +WORDSIZE /* info level */
585 +WORDSIZE]; /* buffer size */
587 /* now send a SMBtrans command with api GroupGetUsers */
588 p = make_header(param, RAP_WUserGetGroups,
589 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
590 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
591 PUTWORD(p,0); /* info level 0 */
592 PUTWORD(p,0xFFE0); /* return buffer size */
594 if (cli_api(cli,
595 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
596 NULL, 0, CLI_BUFFER_SIZE,
597 &rparam, &rprcnt,
598 &rdata, &rdrcnt)) {
599 res = GETRES(rparam);
600 cli->rap_error = res;
601 if (res != 0) {
602 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
605 if (rdata) {
606 if (res == 0 || res == ERRmoredata) {
607 int i, count;
608 fstring groupname;
609 p = rparam + WORDSIZE + WORDSIZE;
610 GETWORD(p, count);
612 for (i=0,p=rdata; i<count; i++) {
613 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
614 fn(groupname, state);
616 } else {
617 DEBUG(4,("NetUserGetGroups res=%d\n", res));
619 } else {
620 DEBUG(4,("NetUserGetGroups no data returned\n"));
622 SAFE_FREE(rdata);
623 SAFE_FREE(rparam);
624 return res;
628 /****************************************************************************
629 call a NetUserDelete - delete user from remote server
630 ****************************************************************************/
631 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
633 char *rparam = NULL;
634 char *rdata = NULL;
635 char *p;
636 unsigned int rdrcnt,rprcnt;
637 int res;
638 char param[WORDSIZE /* api number */
639 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
640 +1 /* no ret string */
641 +RAP_USERNAME_LEN /* user to del */
642 +WORDSIZE]; /* reserved word */
644 /* now send a SMBtrans command with api UserDel */
645 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
646 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
647 PUTWORD(p,0); /* reserved word MBZ on input */
649 if (cli_api(cli,
650 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
651 NULL, 0, 200, /* data, length, maxlen */
652 &rparam, &rprcnt, /* return params, length */
653 &rdata, &rdrcnt)) /* return data, length */
655 res = GETRES(rparam);
657 if (res == 0) {
658 /* nothing to do */
660 else if ((res == 5) || (res == 65)) {
661 DEBUG(1, ("Access Denied\n"));
663 else if (res == 2221) {
664 DEBUG (1, ("User does not exist\n"));
666 else {
667 DEBUG(4,("NetUserDelete res=%d\n", res));
669 } else {
670 res = -1;
671 DEBUG(4,("NetUserDelete failed\n"));
674 SAFE_FREE(rparam);
675 SAFE_FREE(rdata);
677 return res;
680 /****************************************************************************
681 call a NetUserAdd - add user to remote server
682 ****************************************************************************/
683 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
688 char *rparam = NULL;
689 char *rdata = NULL;
690 char *p;
691 unsigned int rdrcnt,rprcnt;
692 int res;
693 char param[WORDSIZE /* api number */
694 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
695 +sizeof(RAP_USER_INFO_L1) /* data string */
696 +WORDSIZE /* info level */
697 +WORDSIZE /* buffer length */
698 +WORDSIZE]; /* reserved */
700 char data[1024];
701 /* offset into data of free format strings. Will be updated */
702 /* by PUTSTRINGP macro and end up with total data length. */
703 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
704 + RAP_UPASSWD_LEN /* password */
705 + DWORDSIZE /* password age */
706 + WORDSIZE /* privilege */
707 + DWORDSIZE /* home dir ptr */
708 + DWORDSIZE /* comment ptr */
709 + WORDSIZE /* flags */
710 + DWORDSIZE; /* login script ptr*/
712 /* now send a SMBtrans command with api NetUserAdd */
713 p = make_header(param, RAP_WUserAdd2,
714 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
715 PUTWORD(p, 1); /* info level */
717 PUTWORD(p, 0); /* pwencrypt */
718 if(userinfo->passwrd)
719 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
720 else
721 PUTWORD(p, 0); /* password length */
723 p = data;
724 memset(data, '\0', soffset);
726 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
727 PUTBYTE(p, 0); /* pad byte 0 */
728 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
729 PUTDWORD(p, 0); /* pw age - n.a. on user add */
730 PUTWORD(p, userinfo->priv);
731 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
732 PUTSTRINGP(p, userinfo->comment, data, soffset);
733 PUTWORD(p, userinfo->userflags);
734 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
736 if (cli_api(cli,
737 param, sizeof(param), 1024, /* Param, length, maxlen */
738 data, soffset, sizeof(data), /* data, length, maxlen */
739 &rparam, &rprcnt, /* return params, length */
740 &rdata, &rdrcnt)) /* return data, length */
742 res = GETRES(rparam);
744 if (res == 0) {
745 /* nothing to do */
747 else if ((res == 5) || (res == 65)) {
748 DEBUG(1, ("Access Denied\n"));
750 else if (res == 2224) {
751 DEBUG (1, ("User already exists\n"));
753 else {
754 DEBUG(4,("NetUserAdd res=%d\n", res));
756 } else {
757 res = -1;
758 DEBUG(4,("NetUserAdd failed\n"));
761 SAFE_FREE(rparam);
762 SAFE_FREE(rdata);
764 return res;
767 /****************************************************************************
768 call a NetUserEnum - try and list users on a different host
769 ****************************************************************************/
770 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
772 char param[WORDSIZE /* api number */
773 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
774 +sizeof(RAP_USER_INFO_L1) /* return string */
775 +WORDSIZE /* info level */
776 +WORDSIZE]; /* buffer size */
777 char *p;
778 char *rparam = NULL;
779 char *rdata = NULL;
780 unsigned int rprcnt, rdrcnt;
781 int res = -1;
784 memset(param, '\0', sizeof(param));
785 p = make_header(param, RAP_WUserEnum,
786 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
787 PUTWORD(p,1); /* Info level 1 */
788 PUTWORD(p,0xFF00); /* Return buffer size */
790 /* BB Fix handling of large numbers of users to be returned */
791 if (cli_api(cli,
792 param, PTR_DIFF(p,param),8,
793 NULL, 0, CLI_BUFFER_SIZE,
794 &rparam, &rprcnt,
795 &rdata, &rdrcnt)) {
796 res = GETRES(rparam);
797 cli->rap_error = res;
798 if (cli->rap_error != 0) {
799 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
802 if (rdata) {
803 if (res == 0 || res == ERRmoredata) {
804 int i, converter, count;
805 char username[RAP_USERNAME_LEN];
806 char userpw[RAP_UPASSWD_LEN];
807 pstring comment, homedir, logonscript;
809 p = rparam + WORDSIZE; /* skip result */
810 GETWORD(p, converter);
811 GETWORD(p, count);
813 for (i=0,p=rdata;i<count;i++) {
814 GETSTRINGF(p, username, RAP_USERNAME_LEN);
815 p++; /* pad byte */
816 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
817 p += DWORDSIZE; /* skip password age */
818 p += WORDSIZE; /* skip priv: 0=guest, 1=user, 2=admin */
819 GETSTRINGP(p, homedir, rdata, converter);
820 GETSTRINGP(p, comment, rdata, converter);
821 p += WORDSIZE; /* skip flags */
822 GETSTRINGP(p, logonscript, rdata, converter);
824 fn(username, comment, homedir, logonscript, cli);
826 } else {
827 DEBUG(4,("NetUserEnum res=%d\n", res));
829 } else {
830 DEBUG(4,("NetUserEnum no data returned\n"));
833 SAFE_FREE(rparam);
834 SAFE_FREE(rdata);
836 return res;
839 int cli_RNetUserEnum0(struct cli_state *cli,
840 void (*fn)(const char *, void *),
841 void *state)
843 char param[WORDSIZE /* api number */
844 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
845 +sizeof(RAP_USER_INFO_L0) /* return string */
846 +WORDSIZE /* info level */
847 +WORDSIZE]; /* buffer size */
848 char *p;
849 char *rparam = NULL;
850 char *rdata = NULL;
851 unsigned int rprcnt, rdrcnt;
852 int res = -1;
855 memset(param, '\0', sizeof(param));
856 p = make_header(param, RAP_WUserEnum,
857 RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
858 PUTWORD(p,0); /* Info level 1 */
859 PUTWORD(p,0xFF00); /* Return buffer size */
861 /* BB Fix handling of large numbers of users to be returned */
862 if (cli_api(cli,
863 param, PTR_DIFF(p,param),8,
864 NULL, 0, CLI_BUFFER_SIZE,
865 &rparam, &rprcnt,
866 &rdata, &rdrcnt)) {
867 res = GETRES(rparam);
868 cli->rap_error = res;
869 if (cli->rap_error != 0) {
870 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
873 if (rdata) {
874 if (res == 0 || res == ERRmoredata) {
875 int i, count;
876 char username[RAP_USERNAME_LEN];
878 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
879 GETWORD(p, count);
881 for (i=0,p=rdata;i<count;i++) {
882 GETSTRINGF(p, username, RAP_USERNAME_LEN);
883 fn(username, cli);
885 } else {
886 DEBUG(4,("NetUserEnum res=%d\n", res));
888 } else {
889 DEBUG(4,("NetUserEnum no data returned\n"));
892 SAFE_FREE(rparam);
893 SAFE_FREE(rdata);
895 return res;
898 /****************************************************************************
899 call a NetFileClose2 - close open file on another session to server
900 ****************************************************************************/
901 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
903 char *rparam = NULL;
904 char *rdata = NULL;
905 char *p;
906 unsigned int rdrcnt,rprcnt;
907 char param[WORDSIZE /* api number */
908 +sizeof(RAP_WFileClose2_REQ) /* req string */
909 +1 /* no ret string */
910 +DWORDSIZE]; /* file ID */
911 int res = -1;
913 /* now send a SMBtrans command with api RNetShareEnum */
914 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
915 PUTDWORD(p, file_id);
917 if (cli_api(cli,
918 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
919 NULL, 0, 200, /* data, length, maxlen */
920 &rparam, &rprcnt, /* return params, length */
921 &rdata, &rdrcnt)) /* return data, length */
923 res = GETRES(rparam);
925 if (res == 0) {
926 /* nothing to do */
927 } else if (res == 2314){
928 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
929 } else {
930 DEBUG(4,("NetFileClose2 res=%d\n", res));
932 } else {
933 res = -1;
934 DEBUG(4,("NetFileClose2 failed\n"));
937 SAFE_FREE(rparam);
938 SAFE_FREE(rdata);
940 return res;
943 /****************************************************************************
944 call a NetFileGetInfo - get information about server file opened from other
945 workstation
946 ****************************************************************************/
947 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
949 char *rparam = NULL;
950 char *rdata = NULL;
951 char *p;
952 unsigned int rdrcnt,rprcnt;
953 int res;
954 char param[WORDSIZE /* api number */
955 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
956 +sizeof(RAP_FILE_INFO_L3) /* return string */
957 +DWORDSIZE /* file ID */
958 +WORDSIZE /* info level */
959 +WORDSIZE]; /* buffer size */
961 /* now send a SMBtrans command with api RNetShareEnum */
962 p = make_header(param, RAP_WFileGetInfo2,
963 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
964 PUTDWORD(p, file_id);
965 PUTWORD(p, 3); /* info level */
966 PUTWORD(p, 0x1000); /* buffer size */
967 if (cli_api(cli,
968 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
969 NULL, 0, 0x1000, /* data, length, maxlen */
970 &rparam, &rprcnt, /* return params, length */
971 &rdata, &rdrcnt)) /* return data, length */
973 res = GETRES(rparam);
974 if (res == 0 || res == ERRmoredata) {
975 int converter,id, perms, locks;
976 pstring fpath, fuser;
978 p = rparam + WORDSIZE; /* skip result */
979 GETWORD(p, converter);
981 p = rdata;
982 GETDWORD(p, id);
983 GETWORD(p, perms);
984 GETWORD(p, locks);
985 GETSTRINGP(p, fpath, rdata, converter);
986 GETSTRINGP(p, fuser, rdata, converter);
988 fn(fpath, fuser, perms, locks, id);
989 } else {
990 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
992 } else {
993 res = -1;
994 DEBUG(4,("NetFileGetInfo2 failed\n"));
997 SAFE_FREE(rparam);
998 SAFE_FREE(rdata);
1000 return res;
1003 /****************************************************************************
1004 * Call a NetFileEnum2 - list open files on an SMB server
1006 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
1007 * server listing the files open via the network (and their
1008 * corresponding open instance ids)
1010 * Dependencies: none
1012 * Parameters:
1013 * cli - pointer to cli_state structure
1014 * user - if present, return only files opened by this remote user
1015 * base_path - if present, return only files opened below this
1016 * base path
1017 * fn - display function to invoke for each entry in the result
1020 * Returns:
1021 * True - success
1022 * False - failure
1024 ****************************************************************************/
1025 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
1027 char *rparam = NULL;
1028 char *rdata = NULL;
1029 char *p;
1030 unsigned int rdrcnt,rprcnt;
1031 char param[WORDSIZE /* api number */
1032 +sizeof(RAP_WFileEnum2_REQ) /* req string */
1033 +sizeof(RAP_FILE_INFO_L3) /* return string */
1034 +256 /* base path (opt) */
1035 +RAP_USERNAME_LEN /* user name (opt) */
1036 +WORDSIZE /* info level */
1037 +WORDSIZE /* buffer size */
1038 +DWORDSIZE /* resume key ? */
1039 +DWORDSIZE]; /* resume key ? */
1040 int count = -1;
1042 /* now send a SMBtrans command with api RNetShareEnum */
1043 p = make_header(param, RAP_WFileEnum2,
1044 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
1046 PUTSTRING(p, base_path, 256);
1047 PUTSTRING(p, user, RAP_USERNAME_LEN);
1048 PUTWORD(p, 3); /* info level */
1049 PUTWORD(p, 0xFF00); /* buffer size */
1050 PUTDWORD(p, 0); /* zero out the resume key */
1051 PUTDWORD(p, 0); /* or is this one the resume key? */
1053 if (cli_api(cli,
1054 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1055 NULL, 0, 0xFF00, /* data, length, maxlen */
1056 &rparam, &rprcnt, /* return params, length */
1057 &rdata, &rdrcnt)) /* return data, length */
1059 int res = GETRES(rparam);
1061 if (res == 0 || res == ERRmoredata) {
1062 int converter, i;
1064 p = rparam + WORDSIZE; /* skip result */
1065 GETWORD(p, converter);
1066 GETWORD(p, count);
1068 p = rdata;
1069 for (i=0; i<count; i++) {
1070 int id, perms, locks;
1071 pstring fpath, fuser;
1073 GETDWORD(p, id);
1074 GETWORD(p, perms);
1075 GETWORD(p, locks);
1076 GETSTRINGP(p, fpath, rdata, converter);
1077 GETSTRINGP(p, fuser, rdata, converter);
1079 fn(fpath, fuser, perms, locks, id);
1080 } /* BB fix ERRmoredata case to send resume request */
1081 } else {
1082 DEBUG(4,("NetFileEnum2 res=%d\n", res));
1084 } else {
1085 DEBUG(4,("NetFileEnum2 failed\n"));
1088 SAFE_FREE(rparam);
1089 SAFE_FREE(rdata);
1091 return count;
1094 /****************************************************************************
1095 call a NetShareAdd - share/export directory on remote server
1096 ****************************************************************************/
1097 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
1099 char *rparam = NULL;
1100 char *rdata = NULL;
1101 char *p;
1102 unsigned int rdrcnt,rprcnt;
1103 int res;
1104 char param[WORDSIZE /* api number */
1105 +sizeof(RAP_WShareAdd_REQ) /* req string */
1106 +sizeof(RAP_SHARE_INFO_L2) /* return string */
1107 +WORDSIZE /* info level */
1108 +WORDSIZE]; /* reserved word */
1109 char data[1024];
1110 /* offset to free format string section following fixed length data. */
1111 /* will be updated by PUTSTRINGP macro and will end up with total len */
1112 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
1113 + WORDSIZE /* share type */
1114 + DWORDSIZE /* comment pointer */
1115 + WORDSIZE /* permissions */
1116 + WORDSIZE /* max users */
1117 + WORDSIZE /* active users */
1118 + DWORDSIZE /* share path */
1119 + RAP_SPASSWD_LEN + 1; /* share password + pad */
1121 memset(param,'\0',sizeof(param));
1122 /* now send a SMBtrans command with api RNetShareAdd */
1123 p = make_header(param, RAP_WshareAdd,
1124 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
1125 PUTWORD(p, 2); /* info level */
1126 PUTWORD(p, 0); /* reserved word 0 */
1128 p = data;
1129 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1130 PUTBYTE(p, 0); /* pad byte 0 */
1132 PUTWORD(p, sinfo->share_type);
1133 PUTSTRINGP(p, sinfo->comment, data, soffset);
1134 PUTWORD(p, sinfo->perms);
1135 PUTWORD(p, sinfo->maximum_users);
1136 PUTWORD(p, sinfo->active_users);
1137 PUTSTRINGP(p, sinfo->path, data, soffset);
1138 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1139 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1141 if (cli_api(cli,
1142 param, sizeof(param), 1024, /* Param, length, maxlen */
1143 data, soffset, sizeof(data), /* data, length, maxlen */
1144 &rparam, &rprcnt, /* return params, length */
1145 &rdata, &rdrcnt)) /* return data, length */
1147 res = rparam? SVAL(rparam,0) : -1;
1149 if (res == 0) {
1150 /* nothing to do */
1152 else {
1153 DEBUG(4,("NetShareAdd res=%d\n", res));
1155 } else {
1156 res = -1;
1157 DEBUG(4,("NetShareAdd failed\n"));
1160 SAFE_FREE(rparam);
1161 SAFE_FREE(rdata);
1163 return res;
1165 /****************************************************************************
1166 call a NetShareDelete - unshare exported directory on remote server
1167 ****************************************************************************/
1168 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1170 char *rparam = NULL;
1171 char *rdata = NULL;
1172 char *p;
1173 unsigned int rdrcnt,rprcnt;
1174 int res;
1175 char param[WORDSIZE /* api number */
1176 +sizeof(RAP_WShareDel_REQ) /* req string */
1177 +1 /* no ret string */
1178 +RAP_SHARENAME_LEN /* share to del */
1179 +WORDSIZE]; /* reserved word */
1182 /* now send a SMBtrans command with api RNetShareDelete */
1183 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1184 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1185 PUTWORD(p,0); /* reserved word MBZ on input */
1187 if (cli_api(cli,
1188 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1189 NULL, 0, 200, /* data, length, maxlen */
1190 &rparam, &rprcnt, /* return params, length */
1191 &rdata, &rdrcnt)) /* return data, length */
1193 res = GETRES(rparam);
1195 if (res == 0) {
1196 /* nothing to do */
1198 else {
1199 DEBUG(4,("NetShareDelete res=%d\n", res));
1201 } else {
1202 res = -1;
1203 DEBUG(4,("NetShareDelete failed\n"));
1206 SAFE_FREE(rparam);
1207 SAFE_FREE(rdata);
1209 return res;
1211 /*************************************************************************
1213 * Function Name: cli_get_pdc_name
1215 * PURPOSE: Remotes a NetServerEnum API call to the current server
1216 * requesting the name of a server matching the server
1217 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1219 * Dependencies: none
1221 * Parameters:
1222 * cli - pointer to cli_state structure
1223 * workgroup - pointer to string containing name of domain
1224 * pdc_name - pointer to string that will contain PDC name
1225 * on successful return
1227 * Returns:
1228 * True - success
1229 * False - failure
1231 ************************************************************************/
1232 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1234 char *rparam = NULL;
1235 char *rdata = NULL;
1236 unsigned int rdrcnt,rprcnt;
1237 char *p;
1238 char param[WORDSIZE /* api number */
1239 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1240 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1241 +WORDSIZE /* info level */
1242 +WORDSIZE /* buffer size */
1243 +DWORDSIZE /* server type */
1244 +RAP_MACHNAME_LEN]; /* workgroup */
1245 int count = -1;
1247 *pdc_name = '\0';
1249 /* send a SMBtrans command with api NetServerEnum */
1250 p = make_header(param, RAP_NetServerEnum2,
1251 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1252 PUTWORD(p, 1); /* info level */
1253 PUTWORD(p, CLI_BUFFER_SIZE);
1254 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1255 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1257 if (cli_api(cli,
1258 param, PTR_DIFF(p,param), 8, /* params, length, max */
1259 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1260 &rparam, &rprcnt, /* return params, return size */
1261 &rdata, &rdrcnt /* return data, return size */
1262 )) {
1263 cli->rap_error = GETRES(rparam);
1266 * We only really care to copy a name if the
1267 * API succeeded and we got back a name.
1269 if (cli->rap_error == 0) {
1270 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1271 GETWORD(p, count);
1272 p = rdata;
1274 if (count > 0)
1275 GETSTRING(p, pdc_name);
1277 else {
1278 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1279 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1283 SAFE_FREE(rparam);
1284 SAFE_FREE(rdata);
1286 return(count > 0);
1290 /*************************************************************************
1292 * Function Name: cli_get_server_domain
1294 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1295 * requesting wksta_info_10 level information to determine
1296 * the domain the server belongs to. On success, this
1297 * routine sets the server_domain field in the cli_state structure
1298 * to the server's domain name.
1300 * Dependencies: none
1302 * Parameters:
1303 * cli - pointer to cli_state structure
1305 * Returns:
1306 * True - success
1307 * False - failure
1309 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1311 ************************************************************************/
1312 BOOL cli_get_server_domain(struct cli_state *cli)
1314 char *rparam = NULL;
1315 char *rdata = NULL;
1316 unsigned int rdrcnt,rprcnt;
1317 char *p;
1318 char param[WORDSIZE /* api number */
1319 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1320 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1321 +WORDSIZE /* info level */
1322 +WORDSIZE]; /* buffer size */
1323 int res = -1;
1325 /* send a SMBtrans command with api NetWkstaGetInfo */
1326 p = make_header(param, RAP_WWkstaGetInfo,
1327 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1328 PUTWORD(p, 10); /* info level */
1329 PUTWORD(p, CLI_BUFFER_SIZE);
1331 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1332 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1333 &rparam, &rprcnt, /* return params, return size */
1334 &rdata, &rdrcnt)) { /* return data, return size */
1335 res = GETRES(rparam);
1336 p = rdata;
1338 if (res == 0) {
1339 int converter;
1341 p = rparam + WORDSIZE;
1342 GETWORD(p, converter);
1344 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1345 GETSTRINGP(p, cli->server_domain, rdata, converter);
1349 SAFE_FREE(rparam);
1350 SAFE_FREE(rdata);
1352 return(res == 0);
1356 /*************************************************************************
1358 * Function Name: cli_get_server_type
1360 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1361 * requesting server_info_1 level information to retrieve
1362 * the server type.
1364 * Dependencies: none
1366 * Parameters:
1367 * cli - pointer to cli_state structure
1368 * pstype - pointer to uint32 to contain returned server type
1370 * Returns:
1371 * True - success
1372 * False - failure
1374 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1376 ************************************************************************/
1377 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1379 char *rparam = NULL;
1380 char *rdata = NULL;
1381 unsigned int rdrcnt,rprcnt;
1382 char *p;
1383 char param[WORDSIZE /* api number */
1384 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1385 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1386 +WORDSIZE /* info level */
1387 +WORDSIZE]; /* buffer size */
1388 int res = -1;
1390 /* send a SMBtrans command with api NetServerGetInfo */
1391 p = make_header(param, RAP_WserverGetInfo,
1392 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1393 PUTWORD(p, 1); /* info level */
1394 PUTWORD(p, CLI_BUFFER_SIZE);
1396 if (cli_api(cli,
1397 param, PTR_DIFF(p,param), 8, /* params, length, max */
1398 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1399 &rparam, &rprcnt, /* return params, return size */
1400 &rdata, &rdrcnt /* return data, return size */
1401 )) {
1403 res = GETRES(rparam);
1405 if (res == 0 || res == ERRmoredata) {
1406 p = rdata;
1407 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1411 SAFE_FREE(rparam);
1412 SAFE_FREE(rdata);
1414 return(res == 0 || res == ERRmoredata);
1417 BOOL cli_get_server_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
1418 char **servername)
1420 char *rparam = NULL;
1421 char *rdata = NULL;
1422 unsigned int rdrcnt,rprcnt;
1423 char *p;
1424 char param[WORDSIZE /* api number */
1425 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1426 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1427 +WORDSIZE /* info level */
1428 +WORDSIZE]; /* buffer size */
1429 BOOL res = False;
1430 fstring tmp;
1432 /* send a SMBtrans command with api NetServerGetInfo */
1433 p = make_header(param, RAP_WserverGetInfo,
1434 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1435 PUTWORD(p, 1); /* info level */
1436 PUTWORD(p, CLI_BUFFER_SIZE);
1438 if (!cli_api(cli,
1439 param, PTR_DIFF(p,param), 8, /* params, length, max */
1440 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1441 &rparam, &rprcnt, /* return params, return size */
1442 &rdata, &rdrcnt /* return data, return size */
1443 )) {
1444 goto failed;
1447 if (GETRES(rparam) != 0) {
1448 goto failed;
1451 if (rdrcnt < 16) {
1452 DEBUG(10, ("invalid data count %d, expected >= 16\n", rdrcnt));
1453 goto failed;
1456 if (pull_ascii(tmp, rdata, sizeof(tmp)-1, 16, STR_TERMINATE) == -1) {
1457 DEBUG(10, ("pull_ascii failed\n"));
1458 goto failed;
1461 if (!(*servername = talloc_strdup(mem_ctx, tmp))) {
1462 DEBUG(1, ("talloc_strdup failed\n"));
1463 goto failed;
1466 res = True;
1468 failed:
1469 SAFE_FREE(rparam);
1470 SAFE_FREE(rdata);
1471 return res;
1474 /*************************************************************************
1476 * Function Name: cli_ns_check_server_type
1478 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1479 * requesting server_info_0 level information of machines
1480 * matching the given server type. If the returned server
1481 * list contains the machine name contained in cli->desthost
1482 * then we conclude the server type checks out. This routine
1483 * is useful to retrieve list of server's of a certain
1484 * type when all you have is a null session connection and
1485 * can't remote API calls such as NetWkstaGetInfo or
1486 * NetServerGetInfo.
1488 * Dependencies: none
1490 * Parameters:
1491 * cli - pointer to cli_state structure
1492 * workgroup - pointer to string containing domain
1493 * stype - server type
1495 * Returns:
1496 * True - success
1497 * False - failure
1499 ************************************************************************/
1500 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1502 char *rparam = NULL;
1503 char *rdata = NULL;
1504 unsigned int rdrcnt,rprcnt;
1505 char *p;
1506 char param[WORDSIZE /* api number */
1507 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1508 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1509 +WORDSIZE /* info level */
1510 +WORDSIZE /* buffer size */
1511 +DWORDSIZE /* server type */
1512 +RAP_MACHNAME_LEN]; /* workgroup */
1513 BOOL found_server = False;
1514 int res = -1;
1516 /* send a SMBtrans command with api NetServerEnum */
1517 p = make_header(param, RAP_NetServerEnum2,
1518 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1519 PUTWORD(p, 0); /* info level 0 */
1520 PUTWORD(p, CLI_BUFFER_SIZE);
1521 PUTDWORD(p, stype);
1522 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1524 if (cli_api(cli,
1525 param, PTR_DIFF(p,param), 8, /* params, length, max */
1526 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1527 &rparam, &rprcnt, /* return params, return size */
1528 &rdata, &rdrcnt /* return data, return size */
1529 )) {
1531 res = GETRES(rparam);
1532 cli->rap_error = res;
1534 if (res == 0 || res == ERRmoredata) {
1535 int i, count;
1537 p = rparam + WORDSIZE + WORDSIZE;
1538 GETWORD(p, count);
1540 p = rdata;
1541 for (i = 0;i < count;i++, p += 16) {
1542 char ret_server[RAP_MACHNAME_LEN];
1544 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1545 if (strequal(ret_server, cli->desthost)) {
1546 found_server = True;
1547 break;
1551 else {
1552 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1553 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1557 SAFE_FREE(rparam);
1558 SAFE_FREE(rdata);
1560 return found_server;
1564 /****************************************************************************
1565 perform a NetWkstaUserLogoff
1566 ****************************************************************************/
1567 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1569 char *rparam = NULL;
1570 char *rdata = NULL;
1571 char *p;
1572 unsigned int rdrcnt,rprcnt;
1573 char param[WORDSIZE /* api number */
1574 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1575 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1576 +RAP_USERNAME_LEN+1 /* user name+pad */
1577 +RAP_MACHNAME_LEN /* wksta name */
1578 +WORDSIZE /* buffer size */
1579 +WORDSIZE]; /* buffer size? */
1580 fstring upperbuf;
1582 memset(param, 0, sizeof(param));
1584 /* send a SMBtrans command with api NetWkstaUserLogoff */
1585 p = make_header(param, RAP_WWkstaUserLogoff,
1586 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1587 PUTDWORD(p, 0); /* Null pointer */
1588 PUTDWORD(p, 0); /* Null pointer */
1589 fstrcpy(upperbuf, user);
1590 strupper_m(upperbuf);
1591 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1592 p++; /* strange format, but ok */
1593 fstrcpy(upperbuf, workstation);
1594 strupper_m(upperbuf);
1595 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1596 PUTWORD(p, CLI_BUFFER_SIZE);
1597 PUTWORD(p, CLI_BUFFER_SIZE);
1599 if (cli_api(cli,
1600 param, PTR_DIFF(p,param),1024, /* param, length, max */
1601 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1602 &rparam, &rprcnt, /* return params, return size */
1603 &rdata, &rdrcnt /* return data, return size */
1604 )) {
1605 cli->rap_error = GETRES(rparam);
1607 if (cli->rap_error != 0) {
1608 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1612 SAFE_FREE(rparam);
1613 SAFE_FREE(rdata);
1614 return (cli->rap_error == 0);
1617 int cli_NetPrintQEnum(struct cli_state *cli,
1618 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1619 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1621 char param[WORDSIZE /* api number */
1622 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1623 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1624 +WORDSIZE /* info level */
1625 +WORDSIZE /* buffer size */
1626 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1627 char *p;
1628 char *rparam = NULL;
1629 char *rdata = NULL;
1630 unsigned int rprcnt, rdrcnt;
1631 int res = -1;
1634 memset(param, '\0',sizeof(param));
1635 p = make_header(param, RAP_WPrintQEnum,
1636 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1637 PUTWORD(p,2); /* Info level 2 */
1638 PUTWORD(p,0xFFE0); /* Return buffer size */
1639 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1641 if (cli_api(cli,
1642 param, PTR_DIFF(p,param),1024,
1643 NULL, 0, CLI_BUFFER_SIZE,
1644 &rparam, &rprcnt,
1645 &rdata, &rdrcnt)) {
1646 res = GETRES(rparam);
1647 cli->rap_error = res;
1648 if (res != 0) {
1649 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1653 if (rdata) {
1654 if (res == 0 || res == ERRmoredata) {
1655 int i, converter, count;
1657 p = rparam + WORDSIZE;
1658 GETWORD(p, converter);
1659 GETWORD(p, count);
1661 p = rdata;
1662 for (i=0;i<count;i++) {
1663 pstring qname, sep_file, print_proc, dest, parms, comment;
1664 uint16 jobcount, priority, start_time, until_time, status;
1666 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1667 p++; /* pad */
1668 GETWORD(p, priority);
1669 GETWORD(p, start_time);
1670 GETWORD(p, until_time);
1671 GETSTRINGP(p, sep_file, rdata, converter);
1672 GETSTRINGP(p, print_proc, rdata, converter);
1673 GETSTRINGP(p, dest, rdata, converter);
1674 GETSTRINGP(p, parms, rdata, converter);
1675 GETSTRINGP(p, parms, comment, converter);
1676 GETWORD(p, status);
1677 GETWORD(p, jobcount);
1679 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1680 dest, parms, comment, status, jobcount);
1682 if (jobcount) {
1683 int j;
1684 for (j=0;j<jobcount;j++) {
1685 uint16 jid, pos, fsstatus;
1686 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1687 unsigned int submitted, jsize;
1689 GETWORD(p, jid);
1690 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1691 p++; /* pad byte */
1692 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1693 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1694 GETSTRINGP(p, jparms, rdata, converter);
1695 GETWORD(p, pos);
1696 GETWORD(p, fsstatus);
1697 GETSTRINGP(p, jstatus, rdata, converter);
1698 GETDWORD(p, submitted);
1699 GETDWORD(p, jsize);
1700 GETSTRINGP(p, jcomment, rdata, converter);
1702 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1703 jstatus, submitted, jsize, jcomment);
1707 } else {
1708 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1710 } else {
1711 DEBUG(4,("NetPrintQEnum no data returned\n"));
1714 SAFE_FREE(rparam);
1715 SAFE_FREE(rdata);
1717 return res;
1720 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1721 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1722 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1724 char param[WORDSIZE /* api number */
1725 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1726 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1727 +RAP_SHARENAME_LEN /* printer name */
1728 +WORDSIZE /* info level */
1729 +WORDSIZE /* buffer size */
1730 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1731 char *p;
1732 char *rparam = NULL;
1733 char *rdata = NULL;
1734 unsigned int rprcnt, rdrcnt;
1735 int res = -1;
1738 memset(param, '\0',sizeof(param));
1739 p = make_header(param, RAP_WPrintQGetInfo,
1740 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1741 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1742 PUTWORD(p, 2); /* Info level 2 */
1743 PUTWORD(p,0xFFE0); /* Return buffer size */
1744 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1746 if (cli_api(cli,
1747 param, PTR_DIFF(p,param),1024,
1748 NULL, 0, CLI_BUFFER_SIZE,
1749 &rparam, &rprcnt,
1750 &rdata, &rdrcnt)) {
1751 res = GETRES(rparam);
1752 cli->rap_error = res;
1753 if (res != 0) {
1754 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1758 if (rdata) {
1759 if (res == 0 || res == ERRmoredata) {
1760 int rsize, converter;
1761 pstring qname, sep_file, print_proc, dest, parms, comment;
1762 uint16 jobcount, priority, start_time, until_time, status;
1764 p = rparam + WORDSIZE;
1765 GETWORD(p, converter);
1766 GETWORD(p, rsize);
1768 p = rdata;
1769 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1770 p++; /* pad */
1771 GETWORD(p, priority);
1772 GETWORD(p, start_time);
1773 GETWORD(p, until_time);
1774 GETSTRINGP(p, sep_file, rdata, converter);
1775 GETSTRINGP(p, print_proc, rdata, converter);
1776 GETSTRINGP(p, dest, rdata, converter);
1777 GETSTRINGP(p, parms, rdata, converter);
1778 GETSTRINGP(p, comment, rdata, converter);
1779 GETWORD(p, status);
1780 GETWORD(p, jobcount);
1781 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1782 dest, parms, comment, status, jobcount);
1783 if (jobcount) {
1784 int j;
1785 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1786 uint16 jid, pos, fsstatus;
1787 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1788 unsigned int submitted, jsize;
1790 GETWORD(p, jid);
1791 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1792 p++; /* pad byte */
1793 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1794 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1795 GETSTRINGP(p, jparms, rdata, converter);
1796 GETWORD(p, pos);
1797 GETWORD(p, fsstatus);
1798 GETSTRINGP(p, jstatus, rdata, converter);
1799 GETDWORD(p, submitted);
1800 GETDWORD(p, jsize);
1801 GETSTRINGP(p, jcomment, rdata, converter);
1803 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1804 jstatus, submitted, jsize, jcomment);
1807 } else {
1808 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1810 } else {
1811 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1814 SAFE_FREE(rparam);
1815 SAFE_FREE(rdata);
1817 return res;
1820 /****************************************************************************
1821 call a NetServiceEnum - list running services on a different host
1822 ****************************************************************************/
1823 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1825 char param[WORDSIZE /* api number */
1826 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1827 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1828 +WORDSIZE /* info level */
1829 +WORDSIZE]; /* buffer size */
1830 char *p;
1831 char *rparam = NULL;
1832 char *rdata = NULL;
1833 unsigned int rprcnt, rdrcnt;
1834 int res = -1;
1837 memset(param, '\0', sizeof(param));
1838 p = make_header(param, RAP_WServiceEnum,
1839 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1840 PUTWORD(p,2); /* Info level 2 */
1841 PUTWORD(p,0xFFE0); /* Return buffer size */
1843 if (cli_api(cli,
1844 param, PTR_DIFF(p,param),8,
1845 NULL, 0, 0xFFE0 /* data area size */,
1846 &rparam, &rprcnt,
1847 &rdata, &rdrcnt)) {
1848 res = GETRES(rparam);
1849 cli->rap_error = res;
1850 if(cli->rap_error == 234)
1851 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1852 else if (cli->rap_error != 0) {
1853 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1857 if (rdata) {
1858 if (res == 0 || res == ERRmoredata) {
1859 int i, count;
1861 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1862 GETWORD(p, count);
1864 for (i=0,p=rdata;i<count;i++) {
1865 pstring comment;
1866 char servicename[RAP_SRVCNAME_LEN];
1868 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1869 p+=8; /* pass status words */
1870 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1872 fn(servicename, comment, cli); /* BB add status too */
1874 } else {
1875 DEBUG(4,("NetServiceEnum res=%d\n", res));
1877 } else {
1878 DEBUG(4,("NetServiceEnum no data returned\n"));
1881 SAFE_FREE(rparam);
1882 SAFE_FREE(rdata);
1884 return res;
1888 /****************************************************************************
1889 call a NetSessionEnum - list workstations with sessions to an SMB server
1890 ****************************************************************************/
1891 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1893 char param[WORDSIZE /* api number */
1894 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1895 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1896 +WORDSIZE /* info level */
1897 +WORDSIZE]; /* buffer size */
1898 char *p;
1899 char *rparam = NULL;
1900 char *rdata = NULL;
1901 unsigned int rprcnt, rdrcnt;
1902 int res = -1;
1904 memset(param, '\0', sizeof(param));
1905 p = make_header(param, RAP_WsessionEnum,
1906 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1907 PUTWORD(p,2); /* Info level 2 */
1908 PUTWORD(p,0xFF); /* Return buffer size */
1910 if (cli_api(cli,
1911 param, PTR_DIFF(p,param),8,
1912 NULL, 0, CLI_BUFFER_SIZE,
1913 &rparam, &rprcnt,
1914 &rdata, &rdrcnt)) {
1915 res = GETRES(rparam);
1916 cli->rap_error = res;
1917 if (res != 0) {
1918 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1922 if (rdata) {
1923 if (res == 0 || res == ERRmoredata) {
1924 int i, converter, count;
1926 p = rparam + WORDSIZE;
1927 GETWORD(p, converter);
1928 GETWORD(p, count);
1930 for (i=0,p=rdata;i<count;i++) {
1931 pstring wsname, username, clitype_name;
1932 uint16 num_conns, num_opens, num_users;
1933 unsigned int sess_time, idle_time, user_flags;
1935 GETSTRINGP(p, wsname, rdata, converter);
1936 GETSTRINGP(p, username, rdata, converter);
1937 GETWORD(p, num_conns);
1938 GETWORD(p, num_opens);
1939 GETWORD(p, num_users);
1940 GETDWORD(p, sess_time);
1941 GETDWORD(p, idle_time);
1942 GETDWORD(p, user_flags);
1943 GETSTRINGP(p, clitype_name, rdata, converter);
1945 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1946 idle_time, user_flags, clitype_name);
1949 } else {
1950 DEBUG(4,("NetSessionEnum res=%d\n", res));
1952 } else {
1953 DEBUG(4,("NetSesssionEnum no data returned\n"));
1956 SAFE_FREE(rparam);
1957 SAFE_FREE(rdata);
1959 return res;
1962 /****************************************************************************
1963 Call a NetSessionGetInfo - get information about other session to an SMB server.
1964 ****************************************************************************/
1966 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1968 char param[WORDSIZE /* api number */
1969 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1970 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1971 +RAP_MACHNAME_LEN /* wksta name */
1972 +WORDSIZE /* info level */
1973 +WORDSIZE]; /* buffer size */
1974 char *p;
1975 char *rparam = NULL;
1976 char *rdata = NULL;
1977 unsigned int rprcnt, rdrcnt;
1978 int res = -1;
1981 memset(param, '\0', sizeof(param));
1982 p = make_header(param, RAP_WsessionGetInfo,
1983 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1984 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1985 PUTWORD(p,2); /* Info level 2 */
1986 PUTWORD(p,0xFF); /* Return buffer size */
1988 if (cli_api(cli,
1989 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1990 NULL, 0, CLI_BUFFER_SIZE,
1991 &rparam, &rprcnt,
1992 &rdata, &rdrcnt)) {
1993 cli->rap_error = SVAL(rparam,0);
1994 if (cli->rap_error != 0) {
1995 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1999 if (rdata) {
2000 res = GETRES(rparam);
2002 if (res == 0 || res == ERRmoredata) {
2003 int converter;
2004 pstring wsname, username, clitype_name;
2005 uint16 num_conns, num_opens, num_users;
2006 unsigned int sess_time, idle_time, user_flags;
2008 p = rparam + WORDSIZE;
2009 GETWORD(p, converter);
2010 p += WORDSIZE; /* skip rsize */
2012 p = rdata;
2013 GETSTRINGP(p, wsname, rdata, converter);
2014 GETSTRINGP(p, username, rdata, converter);
2015 GETWORD(p, num_conns);
2016 GETWORD(p, num_opens);
2017 GETWORD(p, num_users);
2018 GETDWORD(p, sess_time);
2019 GETDWORD(p, idle_time);
2020 GETDWORD(p, user_flags);
2021 GETSTRINGP(p, clitype_name, rdata, converter);
2023 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
2024 idle_time, user_flags, clitype_name);
2025 } else {
2026 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
2028 } else {
2029 DEBUG(4,("NetSessionGetInfo no data returned\n"));
2032 SAFE_FREE(rparam);
2033 SAFE_FREE(rdata);
2035 return res;
2038 /****************************************************************************
2039 call a NetSessionDel - close a session to an SMB server
2040 ****************************************************************************/
2041 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
2043 char param[WORDSIZE /* api number */
2044 +sizeof(RAP_NetSessionDel_REQ) /* req string */
2045 +1 /* no return string */
2046 +RAP_MACHNAME_LEN /* workstation name */
2047 +WORDSIZE]; /* reserved (0) */
2048 char *p;
2049 char *rparam = NULL;
2050 char *rdata = NULL;
2051 unsigned int rprcnt, rdrcnt;
2052 int res;
2054 memset(param, '\0', sizeof(param));
2055 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
2056 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
2057 PUTWORD(p,0); /* reserved word of 0 */
2058 if (cli_api(cli,
2059 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2060 NULL, 0, 200, /* data, length, maxlen */
2061 &rparam, &rprcnt, /* return params, length */
2062 &rdata, &rdrcnt)) /* return data, length */
2064 res = GETRES(rparam);
2065 cli->rap_error = res;
2067 if (res == 0) {
2068 /* nothing to do */
2070 else {
2071 DEBUG(4,("NetFileClose2 res=%d\n", res));
2073 } else {
2074 res = -1;
2075 DEBUG(4,("NetFileClose2 failed\n"));
2078 SAFE_FREE(rparam);
2079 SAFE_FREE(rdata);
2081 return res;
2085 int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*fn)(uint16 conid, uint16 contype, uint16 numopens, uint16 numusers, uint32 contime, const char *username, const char *netname))
2087 char param[WORDSIZE /* api number */
2088 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
2089 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
2090 +RAP_MACHNAME_LEN /* wksta name */
2091 +WORDSIZE /* info level */
2092 +WORDSIZE]; /* buffer size */
2093 char *p;
2094 char *rparam = NULL;
2095 char *rdata = NULL;
2096 unsigned int rprcnt, rdrcnt;
2097 int res = -1;
2099 memset(param, '\0', sizeof(param));
2100 p = make_header(param, RAP_WconnectionEnum,
2101 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2102 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2103 PUTWORD(p,1); /* Info level 1 */
2104 PUTWORD(p,0xFFE0); /* Return buffer size */
2106 if (cli_api(cli,
2107 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2108 NULL, 0, CLI_BUFFER_SIZE,
2109 &rparam, &rprcnt,
2110 &rdata, &rdrcnt)) {
2111 res = GETRES(rparam);
2112 cli->rap_error = res;
2113 if (res != 0) {
2114 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2117 if (rdata) {
2118 if (res == 0 || res == ERRmoredata) {
2119 int i, converter, count;
2121 p = rparam + WORDSIZE;
2122 GETWORD(p, converter);
2123 GETWORD(p, count);
2125 for (i=0,p=rdata;i<count;i++) {
2126 pstring netname, username;
2127 uint16 conn_id, conn_type, num_opens, num_users;
2128 unsigned int conn_time;
2130 GETWORD(p,conn_id);
2131 GETWORD(p,conn_type);
2132 GETWORD(p,num_opens);
2133 GETWORD(p,num_users);
2134 GETDWORD(p,conn_time);
2135 GETSTRINGP(p, username, rdata, converter);
2136 GETSTRINGP(p, netname, rdata, converter);
2138 fn(conn_id, conn_type, num_opens, num_users, conn_time,
2139 username, netname);
2142 } else {
2143 DEBUG(4,("NetConnectionEnum res=%d\n", res));
2145 } else {
2146 DEBUG(4,("NetConnectionEnum no data returned\n"));
2148 SAFE_FREE(rdata);
2149 SAFE_FREE(rparam);
2150 return res;