r38: Fix caching of name->sid lookups
[Samba/gebeck_regimport.git] / source3 / libsmb / clirap2.c
blob12a3d63aff35542b1e81fe621e9434509cda9836
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 #define NO_SYSLOG
81 #include "includes.h"
83 #define WORDSIZE 2
84 #define DWORDSIZE 4
86 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
87 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
88 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
89 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
90 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
91 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
92 #define GETRES(p) p ? SVAL(p,0) : -1
93 /* put string s at p with max len n and increment p past string */
94 #define PUTSTRING(p,s,n) do {\
95 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
96 p = skip_string(p,1);\
97 } while(0)
98 /* put string s and p, using fixed len l, and increment p by l */
99 #define PUTSTRINGF(p,s,l) do {\
100 push_ascii(p,s?s:"",l,STR_TERMINATE);\
101 p += l;\
102 } while (0)
103 /* put string pointer at p, supplying offset o from rdata r, store */
104 /* dword offset at p, increment p by 4 and o by length of s. This */
105 /* means on the first call, you must calc the offset yourself! */
106 #define PUTSTRINGP(p,s,r,o) do {\
107 if (s) {\
108 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
109 PUTDWORD(p,o);\
110 o += strlen(s) + 1;\
111 } else PUTDWORD(p,0);\
112 }while(0);
113 /* get asciiz string s from p, increment p past string */
114 #define GETSTRING(p,s) do {\
115 pull_ascii_pstring(s,p);\
116 p = skip_string(p,1);\
117 } while(0)
118 /* get fixed length l string s from p, increment p by l */
119 #define GETSTRINGF(p,s,l) do {\
120 pull_ascii_pstring(s,p);\
121 p += l;\
122 } while(0)
123 /* get string s from offset (obtained at p) from rdata r - converter c */
124 #define GETSTRINGP(p,s,r,c) do {\
125 uint32 off;\
126 GETDWORD(p,off);\
127 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
128 pull_ascii_pstring(s, off?(r+off-c):"");\
129 } while(0)
131 static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
133 PUTWORD(param,apinum);
134 if (reqfmt)
135 PUTSTRING(param,reqfmt,0);
136 else
137 *param++ = (char) 0;
139 if (datafmt)
140 PUTSTRING(param,datafmt,0);
141 else
142 *param++ = (char) 0;
144 return param;
148 /****************************************************************************
149 call a NetGroupDelete - delete user group from remote server
150 ****************************************************************************/
151 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
153 char *rparam = NULL;
154 char *rdata = NULL;
155 char *p;
156 unsigned int rdrcnt,rprcnt;
157 int res;
158 char param[WORDSIZE /* api number */
159 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
160 +1 /* no ret string */
161 +RAP_GROUPNAME_LEN /* group to del */
162 +WORDSIZE]; /* reserved word */
164 /* now send a SMBtrans command with api GroupDel */
165 p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);
166 PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
167 PUTWORD(p,0); /* reserved word MBZ on input */
169 if (cli_api(cli,
170 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
171 NULL, 0, 200, /* data, length, maxlen */
172 &rparam, &rprcnt, /* return params, length */
173 &rdata, &rdrcnt)) /* return data, length */
175 res = GETRES(rparam);
177 if (res == 0) {
178 /* nothing to do */
180 else if ((res == 5) || (res == 65)) {
181 DEBUG(1, ("Access Denied\n"));
183 else if (res == 2220) {
184 DEBUG (1, ("Group does not exist\n"));
186 else {
187 DEBUG(4,("NetGroupDelete res=%d\n", res));
189 } else {
190 res = -1;
191 DEBUG(4,("NetGroupDelete failed\n"));
194 SAFE_FREE(rparam);
195 SAFE_FREE(rdata);
197 return res;
200 /****************************************************************************
201 call a NetGroupAdd - add user group to remote server
202 ****************************************************************************/
203 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
205 char *rparam = NULL;
206 char *rdata = NULL;
207 char *p;
208 unsigned int rdrcnt,rprcnt;
209 int res;
210 char param[WORDSIZE /* api number */
211 +sizeof(RAP_NetGroupAdd_REQ) /* req string */
212 +sizeof(RAP_GROUP_INFO_L1) /* return string */
213 +WORDSIZE /* info level */
214 +WORDSIZE]; /* reserved word */
216 char data[1024];
218 /* offset into data of free format strings. Will be updated */
219 /* by PUTSTRINGP macro and end up with total data length. */
220 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
222 /* now send a SMBtrans command with api WGroupAdd */
224 p = make_header(param, RAP_WGroupAdd,
225 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
226 PUTWORD(p, 1); /* info level */
227 PUTWORD(p, 0); /* reserved word 0 */
229 p = data;
230 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
231 PUTBYTE(p, 0); /* pad byte 0 */
232 PUTSTRINGP(p, grinfo->comment, data, soffset);
234 if (cli_api(cli,
235 param, sizeof(param), 1024, /* Param, length, maxlen */
236 data, soffset, sizeof(data), /* data, length, maxlen */
237 &rparam, &rprcnt, /* return params, length */
238 &rdata, &rdrcnt)) /* return data, length */
240 res = GETRES(rparam);
242 if (res == 0) {
243 /* nothing to do */
244 } else if ((res == 5) || (res == 65)) {
245 DEBUG(1, ("Access Denied\n"));
247 else if (res == 2223) {
248 DEBUG (1, ("Group already exists\n"));
250 else {
251 DEBUG(4,("NetGroupAdd res=%d\n", res));
253 } else {
254 res = -1;
255 DEBUG(4,("NetGroupAdd failed\n"));
258 SAFE_FREE(rparam);
259 SAFE_FREE(rdata);
261 return res;
264 /****************************************************************************
265 call a NetGroupEnum - try and list user groups on a different host
266 ****************************************************************************/
267 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
269 char param[WORDSIZE /* api number */
270 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
271 +sizeof(RAP_GROUP_INFO_L1) /* return string */
272 +WORDSIZE /* info level */
273 +WORDSIZE]; /* buffer size */
274 char *p;
275 char *rparam = NULL;
276 char *rdata = NULL;
277 unsigned int rprcnt, rdrcnt;
278 int res = -1;
281 memset(param, '\0', sizeof(param));
282 p = make_header(param, RAP_WGroupEnum,
283 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
284 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
285 PUTWORD(p,0xFFE0); /* Return buffer size */
287 if (cli_api(cli,
288 param, PTR_DIFF(p,param),8,
289 NULL, 0, 0xFFE0 /* data area size */,
290 &rparam, &rprcnt,
291 &rdata, &rdrcnt)) {
292 res = GETRES(rparam);
293 cli->rap_error = res;
294 if(cli->rap_error == 234)
295 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
296 else if (cli->rap_error != 0) {
297 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
301 if (rdata) {
302 if (res == 0 || res == ERRmoredata) {
303 int i, converter, count;
305 p = rparam + WORDSIZE; /* skip result */
306 GETWORD(p, converter);
307 GETWORD(p, count);
309 for (i=0,p=rdata;i<count;i++) {
310 pstring comment;
311 char groupname[RAP_GROUPNAME_LEN];
313 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
314 p++; /* pad byte */
315 GETSTRINGP(p, comment, rdata, converter);
317 fn(groupname, comment, cli);
319 } else {
320 DEBUG(4,("NetGroupEnum res=%d\n", res));
322 } else {
323 DEBUG(4,("NetGroupEnum no data returned\n"));
326 SAFE_FREE(rparam);
327 SAFE_FREE(rdata);
329 return res;
332 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
334 char *rparam = NULL;
335 char *rdata = NULL;
336 char *p;
337 unsigned int rdrcnt,rprcnt;
338 int res;
339 char param[WORDSIZE /* api number */
340 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
341 +1 /* no ret string */
342 +RAP_GROUPNAME_LEN /* group name */
343 +RAP_USERNAME_LEN]; /* user to del */
345 /* now send a SMBtrans command with api GroupMemberAdd */
346 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
347 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
348 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
350 if (cli_api(cli,
351 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
352 NULL, 0, 200, /* data, length, maxlen */
353 &rparam, &rprcnt, /* return params, length */
354 &rdata, &rdrcnt)) /* return data, length */
356 res = GETRES(rparam);
358 switch(res) {
359 case 0:
360 break;
361 case 5:
362 case 65:
363 DEBUG(1, ("Access Denied\n"));
364 break;
365 case 50:
366 DEBUG(1, ("Not supported by server\n"));
367 break;
368 case 2220:
369 DEBUG(1, ("Group does not exist\n"));
370 break;
371 case 2221:
372 DEBUG(1, ("User does not exist\n"));
373 break;
374 case 2237:
375 DEBUG(1, ("User is not in group\n"));
376 break;
377 default:
378 DEBUG(4,("NetGroupDelUser res=%d\n", res));
380 } else {
381 res = -1;
382 DEBUG(4,("NetGroupDelUser failed\n"));
385 SAFE_FREE(rparam);
386 SAFE_FREE(rdata);
388 return res;
391 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
393 char *rparam = NULL;
394 char *rdata = NULL;
395 char *p;
396 unsigned int rdrcnt,rprcnt;
397 int res;
398 char param[WORDSIZE /* api number */
399 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
400 +1 /* no ret string */
401 +RAP_GROUPNAME_LEN /* group name */
402 +RAP_USERNAME_LEN]; /* user to add */
404 /* now send a SMBtrans command with api GroupMemberAdd */
405 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
406 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
407 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
409 if (cli_api(cli,
410 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
411 NULL, 0, 200, /* data, length, maxlen */
412 &rparam, &rprcnt, /* return params, length */
413 &rdata, &rdrcnt)) /* return data, length */
415 res = GETRES(rparam);
417 switch(res) {
418 case 0:
419 break;
420 case 5:
421 case 65:
422 DEBUG(1, ("Access Denied\n"));
423 break;
424 case 50:
425 DEBUG(1, ("Not supported by server\n"));
426 break;
427 case 2220:
428 DEBUG(1, ("Group does not exist\n"));
429 break;
430 case 2221:
431 DEBUG(1, ("User does not exist\n"));
432 break;
433 default:
434 DEBUG(4,("NetGroupAddUser res=%d\n", res));
436 } else {
437 res = -1;
438 DEBUG(4,("NetGroupAddUser failed\n"));
441 SAFE_FREE(rparam);
442 SAFE_FREE(rdata);
444 return res;
448 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
450 char *rparam = NULL;
451 char *rdata = NULL;
452 char *p;
453 unsigned int rdrcnt,rprcnt;
454 int res = -1;
455 char param[WORDSIZE /* api number */
456 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
457 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
458 +RAP_GROUPNAME_LEN /* group name */
459 +WORDSIZE /* info level */
460 +WORDSIZE]; /* buffer size */
462 /* now send a SMBtrans command with api GroupGetUsers */
463 p = make_header(param, RAP_WGroupGetUsers,
464 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
465 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
466 PUTWORD(p,0); /* info level 0 */
467 PUTWORD(p,0xFFE0); /* return buffer size */
469 if (cli_api(cli,
470 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
471 NULL, 0, CLI_BUFFER_SIZE,
472 &rparam, &rprcnt,
473 &rdata, &rdrcnt)) {
474 res = GETRES(rparam);
475 cli->rap_error = res;
476 if (res != 0) {
477 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
480 if (rdata) {
481 if (res == 0 || res == ERRmoredata) {
482 int i, converter, count;
483 fstring username;
484 p = rparam +WORDSIZE;
485 GETWORD(p, converter);
486 GETWORD(p, count);
488 for (i=0,p=rdata; i<count; i++) {
489 GETSTRINGF(p, username, RAP_USERNAME_LEN);
490 fn(username, state);
492 } else {
493 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
495 } else {
496 DEBUG(4,("NetGroupGetUsers no data returned\n"));
498 SAFE_FREE(rdata);
499 SAFE_FREE(rparam);
500 return res;
503 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
505 char *rparam = NULL;
506 char *rdata = NULL;
507 char *p;
508 unsigned int rdrcnt,rprcnt;
509 int res = -1;
510 char param[WORDSIZE /* api number */
511 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
512 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
513 +RAP_USERNAME_LEN /* user name */
514 +WORDSIZE /* info level */
515 +WORDSIZE]; /* buffer size */
517 /* now send a SMBtrans command with api GroupGetUsers */
518 p = make_header(param, RAP_WUserGetGroups,
519 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
520 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
521 PUTWORD(p,0); /* info level 0 */
522 PUTWORD(p,0xFFE0); /* return buffer size */
524 if (cli_api(cli,
525 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
526 NULL, 0, CLI_BUFFER_SIZE,
527 &rparam, &rprcnt,
528 &rdata, &rdrcnt)) {
529 res = GETRES(rparam);
530 cli->rap_error = res;
531 if (res != 0) {
532 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
535 if (rdata) {
536 if (res == 0 || res == ERRmoredata) {
537 int i, converter, count;
538 fstring groupname;
539 p = rparam +WORDSIZE;
540 GETWORD(p, converter);
541 GETWORD(p, count);
543 for (i=0,p=rdata; i<count; i++) {
544 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
545 fn(groupname, state);
547 } else {
548 DEBUG(4,("NetUserGetGroups res=%d\n", res));
550 } else {
551 DEBUG(4,("NetUserGetGroups no data returned\n"));
553 SAFE_FREE(rdata);
554 SAFE_FREE(rparam);
555 return res;
559 /****************************************************************************
560 call a NetUserDelete - delete user from remote server
561 ****************************************************************************/
562 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
564 char *rparam = NULL;
565 char *rdata = NULL;
566 char *p;
567 unsigned int rdrcnt,rprcnt;
568 int res;
569 char param[WORDSIZE /* api number */
570 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
571 +1 /* no ret string */
572 +RAP_USERNAME_LEN /* user to del */
573 +WORDSIZE]; /* reserved word */
575 /* now send a SMBtrans command with api UserDel */
576 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
577 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
578 PUTWORD(p,0); /* reserved word MBZ on input */
580 if (cli_api(cli,
581 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
582 NULL, 0, 200, /* data, length, maxlen */
583 &rparam, &rprcnt, /* return params, length */
584 &rdata, &rdrcnt)) /* return data, length */
586 res = GETRES(rparam);
588 if (res == 0) {
589 /* nothing to do */
591 else if ((res == 5) || (res == 65)) {
592 DEBUG(1, ("Access Denied\n"));
594 else if (res == 2221) {
595 DEBUG (1, ("User does not exist\n"));
597 else {
598 DEBUG(4,("NetUserDelete res=%d\n", res));
600 } else {
601 res = -1;
602 DEBUG(4,("NetUserDelete failed\n"));
605 SAFE_FREE(rparam);
606 SAFE_FREE(rdata);
608 return res;
611 /****************************************************************************
612 call a NetUserAdd - add user to remote server
613 ****************************************************************************/
614 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
619 char *rparam = NULL;
620 char *rdata = NULL;
621 char *p;
622 unsigned int rdrcnt,rprcnt;
623 int res;
624 char param[WORDSIZE /* api number */
625 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
626 +sizeof(RAP_USER_INFO_L1) /* data string */
627 +WORDSIZE /* info level */
628 +WORDSIZE /* buffer length */
629 +WORDSIZE]; /* reserved */
631 char data[1024];
632 /* offset into data of free format strings. Will be updated */
633 /* by PUTSTRINGP macro and end up with total data length. */
634 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
635 + RAP_UPASSWD_LEN /* password */
636 + DWORDSIZE /* password age */
637 + WORDSIZE /* privilege */
638 + DWORDSIZE /* home dir ptr */
639 + DWORDSIZE /* comment ptr */
640 + WORDSIZE /* flags */
641 + DWORDSIZE; /* login script ptr*/
643 /* now send a SMBtrans command with api NetUserAdd */
644 p = make_header(param, RAP_WUserAdd2,
645 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
646 PUTWORD(p, 1); /* info level */
648 PUTWORD(p, 0); /* pwencrypt */
649 if(userinfo->passwrd)
650 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
651 else
652 PUTWORD(p, 0); /* password length */
654 p = data;
655 memset(data, '\0', soffset);
657 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
658 PUTBYTE(p, 0); /* pad byte 0 */
659 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
660 PUTDWORD(p, 0); /* pw age - n.a. on user add */
661 PUTWORD(p, userinfo->priv);
662 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
663 PUTSTRINGP(p, userinfo->comment, data, soffset);
664 PUTWORD(p, userinfo->userflags);
665 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
667 if (cli_api(cli,
668 param, sizeof(param), 1024, /* Param, length, maxlen */
669 data, soffset, sizeof(data), /* data, length, maxlen */
670 &rparam, &rprcnt, /* return params, length */
671 &rdata, &rdrcnt)) /* return data, length */
673 res = GETRES(rparam);
675 if (res == 0) {
676 /* nothing to do */
678 else if ((res == 5) || (res == 65)) {
679 DEBUG(1, ("Access Denied\n"));
681 else if (res == 2224) {
682 DEBUG (1, ("User already exists\n"));
684 else {
685 DEBUG(4,("NetUserAdd res=%d\n", res));
687 } else {
688 res = -1;
689 DEBUG(4,("NetUserAdd failed\n"));
692 SAFE_FREE(rparam);
693 SAFE_FREE(rdata);
695 return res;
698 /****************************************************************************
699 call a NetUserEnum - try and list users on a different host
700 ****************************************************************************/
701 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
703 char param[WORDSIZE /* api number */
704 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
705 +sizeof(RAP_USER_INFO_L1) /* return string */
706 +WORDSIZE /* info level */
707 +WORDSIZE]; /* buffer size */
708 char *p;
709 char *rparam = NULL;
710 char *rdata = NULL;
711 unsigned int rprcnt, rdrcnt;
712 int res = -1;
715 memset(param, '\0', sizeof(param));
716 p = make_header(param, RAP_WUserEnum,
717 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
718 PUTWORD(p,1); /* Info level 1 */
719 PUTWORD(p,0xFF00); /* Return buffer size */
721 /* BB Fix handling of large numbers of users to be returned */
722 if (cli_api(cli,
723 param, PTR_DIFF(p,param),8,
724 NULL, 0, CLI_BUFFER_SIZE,
725 &rparam, &rprcnt,
726 &rdata, &rdrcnt)) {
727 res = GETRES(rparam);
728 cli->rap_error = res;
729 if (cli->rap_error != 0) {
730 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
733 if (rdata) {
734 if (res == 0 || res == ERRmoredata) {
735 int i, converter, count;
736 char username[RAP_USERNAME_LEN];
737 char userpw[RAP_UPASSWD_LEN];
738 pstring comment, homedir, logonscript;
739 int pwage, priv, flags;
741 p = rparam + WORDSIZE; /* skip result */
742 GETWORD(p, converter);
743 GETWORD(p, count);
745 for (i=0,p=rdata;i<count;i++) {
746 GETSTRINGF(p, username, RAP_USERNAME_LEN);
747 p++; /* pad byte */
748 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
749 GETDWORD(p, pwage); /* password age */
750 GETWORD(p, priv); /* 0=guest, 1=user, 2=admin */
751 GETSTRINGP(p, homedir, rdata, converter);
752 GETSTRINGP(p, comment, rdata, converter);
753 GETWORD(p, flags);
754 GETSTRINGP(p, logonscript, rdata, converter);
756 fn(username, comment, homedir, logonscript, cli);
758 } else {
759 DEBUG(4,("NetUserEnum res=%d\n", res));
761 } else {
762 DEBUG(4,("NetUserEnum no data returned\n"));
765 SAFE_FREE(rparam);
766 SAFE_FREE(rdata);
768 return res;
771 /****************************************************************************
772 call a NetFileClose2 - close open file on another session to server
773 ****************************************************************************/
774 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
776 char *rparam = NULL;
777 char *rdata = NULL;
778 char *p;
779 unsigned int rdrcnt,rprcnt;
780 char param[WORDSIZE /* api number */
781 +sizeof(RAP_WFileClose2_REQ) /* req string */
782 +1 /* no ret string */
783 +DWORDSIZE]; /* file ID */
784 int res = -1;
786 /* now send a SMBtrans command with api RNetShareEnum */
787 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
788 PUTDWORD(p, file_id);
790 if (cli_api(cli,
791 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
792 NULL, 0, 200, /* data, length, maxlen */
793 &rparam, &rprcnt, /* return params, length */
794 &rdata, &rdrcnt)) /* return data, length */
796 res = GETRES(rparam);
798 if (res == 0) {
799 /* nothing to do */
800 } else if (res == 2314){
801 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
802 } else {
803 DEBUG(4,("NetFileClose2 res=%d\n", res));
805 } else {
806 res = -1;
807 DEBUG(4,("NetFileClose2 failed\n"));
810 SAFE_FREE(rparam);
811 SAFE_FREE(rdata);
813 return res;
816 /****************************************************************************
817 call a NetFileGetInfo - get information about server file opened from other
818 workstation
819 ****************************************************************************/
820 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
822 char *rparam = NULL;
823 char *rdata = NULL;
824 char *p;
825 unsigned int rdrcnt,rprcnt;
826 int res;
827 char param[WORDSIZE /* api number */
828 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
829 +sizeof(RAP_FILE_INFO_L3) /* return string */
830 +DWORDSIZE /* file ID */
831 +WORDSIZE /* info level */
832 +WORDSIZE]; /* buffer size */
834 /* now send a SMBtrans command with api RNetShareEnum */
835 p = make_header(param, RAP_WFileGetInfo2,
836 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
837 PUTDWORD(p, file_id);
838 PUTWORD(p, 3); /* info level */
839 PUTWORD(p, 0x1000); /* buffer size */
840 if (cli_api(cli,
841 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
842 NULL, 0, 0x1000, /* data, length, maxlen */
843 &rparam, &rprcnt, /* return params, length */
844 &rdata, &rdrcnt)) /* return data, length */
846 res = GETRES(rparam);
847 if (res == 0 || res == ERRmoredata) {
848 int converter,id, perms, locks;
849 pstring fpath, fuser;
851 p = rparam + WORDSIZE; /* skip result */
852 GETWORD(p, converter);
854 p = rdata;
855 GETDWORD(p, id);
856 GETWORD(p, perms);
857 GETWORD(p, locks);
858 GETSTRINGP(p, fpath, rdata, converter);
859 GETSTRINGP(p, fuser, rdata, converter);
861 fn(fpath, fuser, perms, locks, id);
862 } else {
863 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
865 } else {
866 res = -1;
867 DEBUG(4,("NetFileGetInfo2 failed\n"));
870 SAFE_FREE(rparam);
871 SAFE_FREE(rdata);
873 return res;
876 /****************************************************************************
877 * Call a NetFileEnum2 - list open files on an SMB server
879 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
880 * server listing the files open via the network (and their
881 * corresponding open instance ids)
883 * Dependencies: none
885 * Parameters:
886 * cli - pointer to cli_state structure
887 * user - if present, return only files opened by this remote user
888 * base_path - if present, return only files opened below this
889 * base path
890 * fn - display function to invoke for each entry in the result
893 * Returns:
894 * True - success
895 * False - failure
897 ****************************************************************************/
898 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
900 char *rparam = NULL;
901 char *rdata = NULL;
902 char *p;
903 unsigned int rdrcnt,rprcnt;
904 char param[WORDSIZE /* api number */
905 +sizeof(RAP_WFileEnum2_REQ) /* req string */
906 +sizeof(RAP_FILE_INFO_L3) /* return string */
907 +256 /* base path (opt) */
908 +RAP_USERNAME_LEN /* user name (opt) */
909 +WORDSIZE /* info level */
910 +WORDSIZE /* buffer size */
911 +DWORDSIZE /* resume key ? */
912 +DWORDSIZE]; /* resume key ? */
913 int count = -1;
915 /* now send a SMBtrans command with api RNetShareEnum */
916 p = make_header(param, RAP_WFileEnum2,
917 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
919 PUTSTRING(p, base_path, 256);
920 PUTSTRING(p, user, RAP_USERNAME_LEN);
921 PUTWORD(p, 3); /* info level */
922 PUTWORD(p, 0xFF00); /* buffer size */
923 PUTDWORD(p, 0); /* zero out the resume key */
924 PUTDWORD(p, 0); /* or is this one the resume key? */
926 if (cli_api(cli,
927 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
928 NULL, 0, 0xFF00, /* data, length, maxlen */
929 &rparam, &rprcnt, /* return params, length */
930 &rdata, &rdrcnt)) /* return data, length */
932 int res = GETRES(rparam);
934 if (res == 0 || res == ERRmoredata) {
935 int converter, i;
937 p = rparam + WORDSIZE; /* skip result */
938 GETWORD(p, converter);
939 GETWORD(p, count);
941 p = rdata;
942 for (i=0; i<count; i++) {
943 int id, perms, locks;
944 pstring fpath, fuser;
946 GETDWORD(p, id);
947 GETWORD(p, perms);
948 GETWORD(p, locks);
949 GETSTRINGP(p, fpath, rdata, converter);
950 GETSTRINGP(p, fuser, rdata, converter);
952 fn(fpath, fuser, perms, locks, id);
953 } /* BB fix ERRmoredata case to send resume request */
954 } else {
955 DEBUG(4,("NetFileEnum2 res=%d\n", res));
957 } else {
958 DEBUG(4,("NetFileEnum2 failed\n"));
961 SAFE_FREE(rparam);
962 SAFE_FREE(rdata);
964 return count;
967 /****************************************************************************
968 call a NetShareAdd - share/export directory on remote server
969 ****************************************************************************/
970 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
972 char *rparam = NULL;
973 char *rdata = NULL;
974 char *p;
975 unsigned int rdrcnt,rprcnt;
976 int res;
977 char param[WORDSIZE /* api number */
978 +sizeof(RAP_WShareAdd_REQ) /* req string */
979 +sizeof(RAP_SHARE_INFO_L2) /* return string */
980 +WORDSIZE /* info level */
981 +WORDSIZE]; /* reserved word */
982 char data[1024];
983 /* offset to free format string section following fixed length data. */
984 /* will be updated by PUTSTRINGP macro and will end up with total len */
985 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
986 + WORDSIZE /* share type */
987 + DWORDSIZE /* comment pointer */
988 + WORDSIZE /* permissions */
989 + WORDSIZE /* max users */
990 + WORDSIZE /* active users */
991 + DWORDSIZE /* share path */
992 + RAP_SPASSWD_LEN + 1; /* share password + pad */
994 memset(param,'\0',sizeof(param));
995 /* now send a SMBtrans command with api RNetShareAdd */
996 p = make_header(param, RAP_WshareAdd,
997 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
998 PUTWORD(p, 2); /* info level */
999 PUTWORD(p, 0); /* reserved word 0 */
1001 p = data;
1002 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1003 PUTBYTE(p, 0); /* pad byte 0 */
1005 PUTWORD(p, sinfo->share_type);
1006 PUTSTRINGP(p, sinfo->comment, data, soffset);
1007 PUTWORD(p, sinfo->perms);
1008 PUTWORD(p, sinfo->maximum_users);
1009 PUTWORD(p, sinfo->active_users);
1010 PUTSTRINGP(p, sinfo->path, data, soffset);
1011 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1012 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1014 if (cli_api(cli,
1015 param, sizeof(param), 1024, /* Param, length, maxlen */
1016 data, soffset, sizeof(data), /* data, length, maxlen */
1017 &rparam, &rprcnt, /* return params, length */
1018 &rdata, &rdrcnt)) /* return data, length */
1020 res = rparam? SVAL(rparam,0) : -1;
1022 if (res == 0) {
1023 /* nothing to do */
1025 else {
1026 DEBUG(4,("NetShareAdd res=%d\n", res));
1028 } else {
1029 res = -1;
1030 DEBUG(4,("NetShareAdd failed\n"));
1033 SAFE_FREE(rparam);
1034 SAFE_FREE(rdata);
1036 return res;
1038 /****************************************************************************
1039 call a NetShareDelete - unshare exported directory on remote server
1040 ****************************************************************************/
1041 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1043 char *rparam = NULL;
1044 char *rdata = NULL;
1045 char *p;
1046 unsigned int rdrcnt,rprcnt;
1047 int res;
1048 char param[WORDSIZE /* api number */
1049 +sizeof(RAP_WShareDel_REQ) /* req string */
1050 +1 /* no ret string */
1051 +RAP_SHARENAME_LEN /* share to del */
1052 +WORDSIZE]; /* reserved word */
1055 /* now send a SMBtrans command with api RNetShareDelete */
1056 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1057 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1058 PUTWORD(p,0); /* reserved word MBZ on input */
1060 if (cli_api(cli,
1061 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1062 NULL, 0, 200, /* data, length, maxlen */
1063 &rparam, &rprcnt, /* return params, length */
1064 &rdata, &rdrcnt)) /* return data, length */
1066 res = GETRES(rparam);
1068 if (res == 0) {
1069 /* nothing to do */
1071 else {
1072 DEBUG(4,("NetShareDelete res=%d\n", res));
1074 } else {
1075 res = -1;
1076 DEBUG(4,("NetShareDelete failed\n"));
1079 SAFE_FREE(rparam);
1080 SAFE_FREE(rdata);
1082 return res;
1084 /*************************************************************************
1086 * Function Name: cli_get_pdc_name
1088 * PURPOSE: Remotes a NetServerEnum API call to the current server
1089 * requesting the name of a server matching the server
1090 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1092 * Dependencies: none
1094 * Parameters:
1095 * cli - pointer to cli_state structure
1096 * workgroup - pointer to string containing name of domain
1097 * pdc_name - pointer to string that will contain PDC name
1098 * on successful return
1100 * Returns:
1101 * True - success
1102 * False - failure
1104 ************************************************************************/
1105 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1107 char *rparam = NULL;
1108 char *rdata = NULL;
1109 unsigned int rdrcnt,rprcnt;
1110 char *p;
1111 char param[WORDSIZE /* api number */
1112 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1113 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1114 +WORDSIZE /* info level */
1115 +WORDSIZE /* buffer size */
1116 +DWORDSIZE /* server type */
1117 +RAP_MACHNAME_LEN]; /* workgroup */
1118 int count = -1;
1120 *pdc_name = '\0';
1122 /* send a SMBtrans command with api NetServerEnum */
1123 p = make_header(param, RAP_NetServerEnum2,
1124 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1125 PUTWORD(p, 1); /* info level */
1126 PUTWORD(p, CLI_BUFFER_SIZE);
1127 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1128 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1130 if (cli_api(cli,
1131 param, PTR_DIFF(p,param), 8, /* params, length, max */
1132 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1133 &rparam, &rprcnt, /* return params, return size */
1134 &rdata, &rdrcnt /* return data, return size */
1135 )) {
1136 cli->rap_error = GETRES(rparam);
1139 * We only really care to copy a name if the
1140 * API succeeded and we got back a name.
1142 if (cli->rap_error == 0) {
1143 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1144 GETWORD(p, count);
1145 p = rdata;
1147 if (count > 0)
1148 GETSTRING(p, pdc_name);
1150 else {
1151 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1152 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1156 SAFE_FREE(rparam);
1157 SAFE_FREE(rdata);
1159 return(count > 0);
1163 /*************************************************************************
1165 * Function Name: cli_get_server_domain
1167 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1168 * requesting wksta_info_10 level information to determine
1169 * the domain the server belongs to. On success, this
1170 * routine sets the server_domain field in the cli_state structure
1171 * to the server's domain name.
1173 * Dependencies: none
1175 * Parameters:
1176 * cli - pointer to cli_state structure
1178 * Returns:
1179 * True - success
1180 * False - failure
1182 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1184 ************************************************************************/
1185 BOOL cli_get_server_domain(struct cli_state *cli)
1187 char *rparam = NULL;
1188 char *rdata = NULL;
1189 unsigned int rdrcnt,rprcnt;
1190 char *p;
1191 char param[WORDSIZE /* api number */
1192 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1193 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1194 +WORDSIZE /* info level */
1195 +WORDSIZE]; /* buffer size */
1196 int res = -1;
1198 /* send a SMBtrans command with api NetWkstaGetInfo */
1199 p = make_header(param, RAP_WWkstaGetInfo,
1200 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1201 PUTWORD(p, 10); /* info level */
1202 PUTWORD(p, CLI_BUFFER_SIZE);
1204 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1205 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1206 &rparam, &rprcnt, /* return params, return size */
1207 &rdata, &rdrcnt)) { /* return data, return size */
1208 res = GETRES(rparam);
1209 p = rdata;
1211 if (res == 0) {
1212 int converter;
1214 p = rparam + WORDSIZE;
1215 GETWORD(p, converter);
1217 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1218 GETSTRINGP(p, cli->server_domain, rdata, converter);
1222 SAFE_FREE(rparam);
1223 SAFE_FREE(rdata);
1225 return(res == 0);
1229 /*************************************************************************
1231 * Function Name: cli_get_server_type
1233 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1234 * requesting server_info_1 level information to retrieve
1235 * the server type.
1237 * Dependencies: none
1239 * Parameters:
1240 * cli - pointer to cli_state structure
1241 * pstype - pointer to uint32 to contain returned server type
1243 * Returns:
1244 * True - success
1245 * False - failure
1247 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1249 ************************************************************************/
1250 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1252 char *rparam = NULL;
1253 char *rdata = NULL;
1254 unsigned int rdrcnt,rprcnt;
1255 char *p;
1256 char param[WORDSIZE /* api number */
1257 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1258 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1259 +WORDSIZE /* info level */
1260 +WORDSIZE]; /* buffer size */
1261 int res = -1;
1263 /* send a SMBtrans command with api NetServerGetInfo */
1264 p = make_header(param, RAP_WserverGetInfo,
1265 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1266 PUTWORD(p, 1); /* info level */
1267 PUTWORD(p, CLI_BUFFER_SIZE);
1269 if (cli_api(cli,
1270 param, PTR_DIFF(p,param), 8, /* params, length, max */
1271 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1272 &rparam, &rprcnt, /* return params, return size */
1273 &rdata, &rdrcnt /* return data, return size */
1274 )) {
1276 res = GETRES(rparam);
1278 if (res == 0 || res == ERRmoredata) {
1279 p = rdata;
1280 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1284 SAFE_FREE(rparam);
1285 SAFE_FREE(rdata);
1287 return(res == 0 || res == ERRmoredata);
1291 /*************************************************************************
1293 * Function Name: cli_ns_check_server_type
1295 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1296 * requesting server_info_0 level information of machines
1297 * matching the given server type. If the returned server
1298 * list contains the machine name contained in cli->desthost
1299 * then we conclude the server type checks out. This routine
1300 * is useful to retrieve list of server's of a certain
1301 * type when all you have is a null session connection and
1302 * can't remote API calls such as NetWkstaGetInfo or
1303 * NetServerGetInfo.
1305 * Dependencies: none
1307 * Parameters:
1308 * cli - pointer to cli_state structure
1309 * workgroup - pointer to string containing domain
1310 * stype - server type
1312 * Returns:
1313 * True - success
1314 * False - failure
1316 ************************************************************************/
1317 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1319 char *rparam = NULL;
1320 char *rdata = NULL;
1321 unsigned int rdrcnt,rprcnt;
1322 char *p;
1323 char param[WORDSIZE /* api number */
1324 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1325 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1326 +WORDSIZE /* info level */
1327 +WORDSIZE /* buffer size */
1328 +DWORDSIZE /* server type */
1329 +RAP_MACHNAME_LEN]; /* workgroup */
1330 BOOL found_server = False;
1331 int res = -1;
1333 /* send a SMBtrans command with api NetServerEnum */
1334 p = make_header(param, RAP_NetServerEnum2,
1335 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1336 PUTWORD(p, 0); /* info level 0 */
1337 PUTWORD(p, CLI_BUFFER_SIZE);
1338 PUTDWORD(p, stype);
1339 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1341 if (cli_api(cli,
1342 param, PTR_DIFF(p,param), 8, /* params, length, max */
1343 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1344 &rparam, &rprcnt, /* return params, return size */
1345 &rdata, &rdrcnt /* return data, return size */
1346 )) {
1348 res = GETRES(rparam);
1349 cli->rap_error = res;
1351 if (res == 0 || res == ERRmoredata) {
1352 int i, converter, count;
1354 p = rparam + WORDSIZE;
1355 GETWORD(p, converter);
1356 GETWORD(p, count);
1358 p = rdata;
1359 for (i = 0;i < count;i++, p += 16) {
1360 char ret_server[RAP_MACHNAME_LEN];
1362 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1363 if (strequal(ret_server, cli->desthost)) {
1364 found_server = True;
1365 break;
1369 else {
1370 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1371 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1375 SAFE_FREE(rparam);
1376 SAFE_FREE(rdata);
1378 return found_server;
1382 /****************************************************************************
1383 perform a NetWkstaUserLogoff
1384 ****************************************************************************/
1385 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1387 char *rparam = NULL;
1388 char *rdata = NULL;
1389 char *p;
1390 unsigned int rdrcnt,rprcnt;
1391 char param[WORDSIZE /* api number */
1392 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1393 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1394 +RAP_USERNAME_LEN+1 /* user name+pad */
1395 +RAP_MACHNAME_LEN /* wksta name */
1396 +WORDSIZE /* buffer size */
1397 +WORDSIZE]; /* buffer size? */
1398 fstring upperbuf;
1400 memset(param, 0, sizeof(param));
1402 /* send a SMBtrans command with api NetWkstaUserLogoff */
1403 p = make_header(param, RAP_WWkstaUserLogoff,
1404 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1405 PUTDWORD(p, 0); /* Null pointer */
1406 PUTDWORD(p, 0); /* Null pointer */
1407 fstrcpy(upperbuf, user);
1408 strupper_m(upperbuf);
1409 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1410 p++; /* strange format, but ok */
1411 fstrcpy(upperbuf, workstation);
1412 strupper_m(upperbuf);
1413 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1414 PUTWORD(p, CLI_BUFFER_SIZE);
1415 PUTWORD(p, CLI_BUFFER_SIZE);
1417 if (cli_api(cli,
1418 param, PTR_DIFF(p,param),1024, /* param, length, max */
1419 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1420 &rparam, &rprcnt, /* return params, return size */
1421 &rdata, &rdrcnt /* return data, return size */
1422 )) {
1423 cli->rap_error = GETRES(rparam);
1425 if (cli->rap_error != 0) {
1426 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1430 SAFE_FREE(rparam);
1431 SAFE_FREE(rdata);
1432 return (cli->rap_error == 0);
1435 int cli_NetPrintQEnum(struct cli_state *cli,
1436 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1437 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1439 char param[WORDSIZE /* api number */
1440 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1441 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1442 +WORDSIZE /* info level */
1443 +WORDSIZE /* buffer size */
1444 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1445 char *p;
1446 char *rparam = NULL;
1447 char *rdata = NULL;
1448 unsigned int rprcnt, rdrcnt;
1449 int res = -1;
1452 memset(param, '\0',sizeof(param));
1453 p = make_header(param, RAP_WPrintQEnum,
1454 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1455 PUTWORD(p,2); /* Info level 2 */
1456 PUTWORD(p,0xFFE0); /* Return buffer size */
1457 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1459 if (cli_api(cli,
1460 param, PTR_DIFF(p,param),1024,
1461 NULL, 0, CLI_BUFFER_SIZE,
1462 &rparam, &rprcnt,
1463 &rdata, &rdrcnt)) {
1464 res = GETRES(rparam);
1465 cli->rap_error = res;
1466 if (res != 0) {
1467 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1471 if (rdata) {
1472 if (res == 0 || res == ERRmoredata) {
1473 int i, converter, count;
1475 p = rparam + WORDSIZE;
1476 GETWORD(p, converter);
1477 GETWORD(p, count);
1479 p = rdata;
1480 for (i=0;i<count;i++) {
1481 pstring qname, sep_file, print_proc, dest, parms, comment;
1482 uint16 jobcount, priority, start_time, until_time, status;
1484 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1485 p++; /* pad */
1486 GETWORD(p, priority);
1487 GETWORD(p, start_time);
1488 GETWORD(p, until_time);
1489 GETSTRINGP(p, sep_file, rdata, converter);
1490 GETSTRINGP(p, print_proc, rdata, converter);
1491 GETSTRINGP(p, dest, rdata, converter);
1492 GETSTRINGP(p, parms, rdata, converter);
1493 GETSTRINGP(p, parms, comment, converter);
1494 GETWORD(p, status);
1495 GETWORD(p, jobcount);
1497 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1498 dest, parms, comment, status, jobcount);
1500 if (jobcount) {
1501 int j;
1502 for (j=0;j<jobcount;j++) {
1503 uint16 jid, pos, fsstatus;
1504 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1505 unsigned int submitted, jsize;
1507 GETWORD(p, jid);
1508 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1509 p++; /* pad byte */
1510 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1511 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1512 GETSTRINGP(p, jparms, rdata, converter);
1513 GETWORD(p, pos);
1514 GETWORD(p, fsstatus);
1515 GETSTRINGP(p, jstatus, rdata, converter);
1516 GETDWORD(p, submitted);
1517 GETDWORD(p, jsize);
1518 GETSTRINGP(p, jcomment, rdata, converter);
1520 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1521 jstatus, submitted, jsize, jcomment);
1525 } else {
1526 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1528 } else {
1529 DEBUG(4,("NetPrintQEnum no data returned\n"));
1532 SAFE_FREE(rparam);
1533 SAFE_FREE(rdata);
1535 return res;
1538 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1539 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1540 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1542 char param[WORDSIZE /* api number */
1543 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1544 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1545 +RAP_SHARENAME_LEN /* printer name */
1546 +WORDSIZE /* info level */
1547 +WORDSIZE /* buffer size */
1548 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1549 char *p;
1550 char *rparam = NULL;
1551 char *rdata = NULL;
1552 unsigned int rprcnt, rdrcnt;
1553 int res = -1;
1556 memset(param, '\0',sizeof(param));
1557 p = make_header(param, RAP_WPrintQGetInfo,
1558 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1559 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1560 PUTWORD(p, 2); /* Info level 2 */
1561 PUTWORD(p,0xFFE0); /* Return buffer size */
1562 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1564 if (cli_api(cli,
1565 param, PTR_DIFF(p,param),1024,
1566 NULL, 0, CLI_BUFFER_SIZE,
1567 &rparam, &rprcnt,
1568 &rdata, &rdrcnt)) {
1569 res = GETRES(rparam);
1570 cli->rap_error = res;
1571 if (res != 0) {
1572 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1576 if (rdata) {
1577 if (res == 0 || res == ERRmoredata) {
1578 int rsize, converter;
1579 pstring qname, sep_file, print_proc, dest, parms, comment;
1580 uint16 jobcount, priority, start_time, until_time, status;
1582 p = rparam + WORDSIZE;
1583 GETWORD(p, converter);
1584 GETWORD(p, rsize);
1586 p = rdata;
1587 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1588 p++; /* pad */
1589 GETWORD(p, priority);
1590 GETWORD(p, start_time);
1591 GETWORD(p, until_time);
1592 GETSTRINGP(p, sep_file, rdata, converter);
1593 GETSTRINGP(p, print_proc, rdata, converter);
1594 GETSTRINGP(p, dest, rdata, converter);
1595 GETSTRINGP(p, parms, rdata, converter);
1596 GETSTRINGP(p, comment, rdata, converter);
1597 GETWORD(p, status);
1598 GETWORD(p, jobcount);
1599 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1600 dest, parms, comment, status, jobcount);
1601 if (jobcount) {
1602 int j;
1603 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1604 uint16 jid, pos, fsstatus;
1605 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1606 unsigned int submitted, jsize;
1608 GETWORD(p, jid);
1609 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1610 p++; /* pad byte */
1611 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1612 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1613 GETSTRINGP(p, jparms, rdata, converter);
1614 GETWORD(p, pos);
1615 GETWORD(p, fsstatus);
1616 GETSTRINGP(p, jstatus, rdata, converter);
1617 GETDWORD(p, submitted);
1618 GETDWORD(p, jsize);
1619 GETSTRINGP(p, jcomment, rdata, converter);
1621 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1622 jstatus, submitted, jsize, jcomment);
1625 } else {
1626 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1628 } else {
1629 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1632 SAFE_FREE(rparam);
1633 SAFE_FREE(rdata);
1635 return res;
1638 /****************************************************************************
1639 call a NetServiceEnum - list running services on a different host
1640 ****************************************************************************/
1641 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1643 char param[WORDSIZE /* api number */
1644 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1645 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1646 +WORDSIZE /* info level */
1647 +WORDSIZE]; /* buffer size */
1648 char *p;
1649 char *rparam = NULL;
1650 char *rdata = NULL;
1651 unsigned int rprcnt, rdrcnt;
1652 int res = -1;
1655 memset(param, '\0', sizeof(param));
1656 p = make_header(param, RAP_WServiceEnum,
1657 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1658 PUTWORD(p,2); /* Info level 2 */
1659 PUTWORD(p,0xFFE0); /* Return buffer size */
1661 if (cli_api(cli,
1662 param, PTR_DIFF(p,param),8,
1663 NULL, 0, 0xFFE0 /* data area size */,
1664 &rparam, &rprcnt,
1665 &rdata, &rdrcnt)) {
1666 res = GETRES(rparam);
1667 cli->rap_error = res;
1668 if(cli->rap_error == 234)
1669 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1670 else if (cli->rap_error != 0) {
1671 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1675 if (rdata) {
1676 if (res == 0 || res == ERRmoredata) {
1677 int i, converter, count;
1679 p = rparam + WORDSIZE; /* skip result */
1680 GETWORD(p, converter);
1681 GETWORD(p, count);
1683 for (i=0,p=rdata;i<count;i++) {
1684 pstring comment;
1685 char servicename[RAP_SRVCNAME_LEN];
1687 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1688 p+=8; /* pass status words */
1689 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1691 fn(servicename, comment, cli); /* BB add status too */
1693 } else {
1694 DEBUG(4,("NetServiceEnum res=%d\n", res));
1696 } else {
1697 DEBUG(4,("NetServiceEnum no data returned\n"));
1700 SAFE_FREE(rparam);
1701 SAFE_FREE(rdata);
1703 return res;
1707 /****************************************************************************
1708 call a NetSessionEnum - list workstations with sessions to an SMB server
1709 ****************************************************************************/
1710 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1712 char param[WORDSIZE /* api number */
1713 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1714 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1715 +WORDSIZE /* info level */
1716 +WORDSIZE]; /* buffer size */
1717 char *p;
1718 char *rparam = NULL;
1719 char *rdata = NULL;
1720 unsigned int rprcnt, rdrcnt;
1721 int res = -1;
1723 memset(param, '\0', sizeof(param));
1724 p = make_header(param, RAP_WsessionEnum,
1725 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1726 PUTWORD(p,2); /* Info level 2 */
1727 PUTWORD(p,0xFF); /* Return buffer size */
1729 if (cli_api(cli,
1730 param, PTR_DIFF(p,param),8,
1731 NULL, 0, CLI_BUFFER_SIZE,
1732 &rparam, &rprcnt,
1733 &rdata, &rdrcnt)) {
1734 res = GETRES(rparam);
1735 cli->rap_error = res;
1736 if (res != 0) {
1737 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1741 if (rdata) {
1742 if (res == 0 || res == ERRmoredata) {
1743 int i, converter, count;
1745 p = rparam + WORDSIZE;
1746 GETWORD(p, converter);
1747 GETWORD(p, count);
1749 for (i=0,p=rdata;i<count;i++) {
1750 pstring wsname, username, clitype_name;
1751 uint16 num_conns, num_opens, num_users;
1752 unsigned int sess_time, idle_time, user_flags;
1754 GETSTRINGP(p, wsname, rdata, converter);
1755 GETSTRINGP(p, username, rdata, converter);
1756 GETWORD(p, num_conns);
1757 GETWORD(p, num_opens);
1758 GETWORD(p, num_users);
1759 GETDWORD(p, sess_time);
1760 GETDWORD(p, idle_time);
1761 GETDWORD(p, user_flags);
1762 GETSTRINGP(p, clitype_name, rdata, converter);
1764 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1765 idle_time, user_flags, clitype_name);
1768 } else {
1769 DEBUG(4,("NetSessionEnum res=%d\n", res));
1771 } else {
1772 DEBUG(4,("NetSesssionEnum no data returned\n"));
1775 SAFE_FREE(rparam);
1776 SAFE_FREE(rdata);
1778 return res;
1781 /****************************************************************************
1782 Call a NetSessionGetInfo - get information about other session to an SMB server.
1783 ****************************************************************************/
1785 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1787 char param[WORDSIZE /* api number */
1788 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1789 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1790 +RAP_MACHNAME_LEN /* wksta name */
1791 +WORDSIZE /* info level */
1792 +WORDSIZE]; /* buffer size */
1793 char *p;
1794 char *rparam = NULL;
1795 char *rdata = NULL;
1796 unsigned int rprcnt, rdrcnt;
1797 int res = -1;
1800 memset(param, '\0', sizeof(param));
1801 p = make_header(param, RAP_WsessionGetInfo,
1802 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1803 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1804 PUTWORD(p,2); /* Info level 2 */
1805 PUTWORD(p,0xFF); /* Return buffer size */
1807 if (cli_api(cli,
1808 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1809 NULL, 0, CLI_BUFFER_SIZE,
1810 &rparam, &rprcnt,
1811 &rdata, &rdrcnt)) {
1812 cli->rap_error = SVAL(rparam,0);
1813 if (cli->rap_error != 0) {
1814 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1818 if (rdata) {
1819 res = GETRES(rparam);
1821 if (res == 0 || res == ERRmoredata) {
1822 int rsize, converter;
1823 pstring wsname, username, clitype_name;
1824 uint16 num_conns, num_opens, num_users;
1825 unsigned int sess_time, idle_time, user_flags;
1827 p = rparam + WORDSIZE;
1828 GETWORD(p, converter);
1829 GETWORD(p, rsize);
1831 p = rdata;
1832 GETSTRINGP(p, wsname, rdata, converter);
1833 GETSTRINGP(p, username, rdata, converter);
1834 GETWORD(p, num_conns);
1835 GETWORD(p, num_opens);
1836 GETWORD(p, num_users);
1837 GETDWORD(p, sess_time);
1838 GETDWORD(p, idle_time);
1839 GETDWORD(p, user_flags);
1840 GETSTRINGP(p, clitype_name, rdata, converter);
1842 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1843 idle_time, user_flags, clitype_name);
1844 } else {
1845 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1847 } else {
1848 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1851 SAFE_FREE(rparam);
1852 SAFE_FREE(rdata);
1854 return res;
1857 /****************************************************************************
1858 call a NetSessionDel - close a session to an SMB server
1859 ****************************************************************************/
1860 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1862 char param[WORDSIZE /* api number */
1863 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1864 +1 /* no return string */
1865 +RAP_MACHNAME_LEN /* workstation name */
1866 +WORDSIZE]; /* reserved (0) */
1867 char *p;
1868 char *rparam = NULL;
1869 char *rdata = NULL;
1870 unsigned int rprcnt, rdrcnt;
1871 int res;
1873 memset(param, '\0', sizeof(param));
1874 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1875 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1876 PUTWORD(p,0); /* reserved word of 0 */
1877 if (cli_api(cli,
1878 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1879 NULL, 0, 200, /* data, length, maxlen */
1880 &rparam, &rprcnt, /* return params, length */
1881 &rdata, &rdrcnt)) /* return data, length */
1883 res = GETRES(rparam);
1884 cli->rap_error = res;
1886 if (res == 0) {
1887 /* nothing to do */
1889 else {
1890 DEBUG(4,("NetFileClose2 res=%d\n", res));
1892 } else {
1893 res = -1;
1894 DEBUG(4,("NetFileClose2 failed\n"));
1897 SAFE_FREE(rparam);
1898 SAFE_FREE(rdata);
1900 return res;
1904 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))
1906 char param[WORDSIZE /* api number */
1907 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
1908 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
1909 +RAP_MACHNAME_LEN /* wksta name */
1910 +WORDSIZE /* info level */
1911 +WORDSIZE]; /* buffer size */
1912 char *p;
1913 char *rparam = NULL;
1914 char *rdata = NULL;
1915 unsigned int rprcnt, rdrcnt;
1916 int res = -1;
1918 memset(param, '\0', sizeof(param));
1919 p = make_header(param, RAP_WconnectionEnum,
1920 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
1921 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
1922 PUTWORD(p,1); /* Info level 1 */
1923 PUTWORD(p,0xFFE0); /* Return buffer size */
1925 if (cli_api(cli,
1926 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1927 NULL, 0, CLI_BUFFER_SIZE,
1928 &rparam, &rprcnt,
1929 &rdata, &rdrcnt)) {
1930 res = GETRES(rparam);
1931 cli->rap_error = res;
1932 if (res != 0) {
1933 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
1936 if (rdata) {
1937 if (res == 0 || res == ERRmoredata) {
1938 int i, converter, count;
1940 p = rparam + WORDSIZE;
1941 GETWORD(p, converter);
1942 GETWORD(p, count);
1944 for (i=0,p=rdata;i<count;i++) {
1945 pstring netname, username;
1946 uint16 conn_id, conn_type, num_opens, num_users;
1947 unsigned int conn_time;
1949 GETWORD(p,conn_id);
1950 GETWORD(p,conn_type);
1951 GETWORD(p,num_opens);
1952 GETWORD(p,num_users);
1953 GETDWORD(p,conn_time);
1954 GETSTRINGP(p, username, rdata, converter);
1955 GETSTRINGP(p, netname, rdata, converter);
1957 fn(conn_id, conn_type, num_opens, num_users, conn_time,
1958 username, netname);
1961 } else {
1962 DEBUG(4,("NetConnectionEnum res=%d\n", res));
1964 } else {
1965 DEBUG(4,("NetConnectionEnum no data returned\n"));
1967 SAFE_FREE(rdata);
1968 SAFE_FREE(rparam);
1969 return res;