* fix to display correct form information in REG_BINARY information
[Samba.git] / source / libsmb / clirap2.c
blob9c3ec212d52eba63f4103dd7bc08fe926eaba1ad
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, char *reqfmt, 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 int rdrcnt,rprcnt, res;
157 char param[WORDSIZE /* api number */
158 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
159 +1 /* no ret string */
160 +RAP_GROUPNAME_LEN /* group to del */
161 +WORDSIZE]; /* reserved word */
163 /* now send a SMBtrans command with api GroupDel */
164 p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);
165 PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
166 PUTWORD(p,0); /* reserved word MBZ on input */
168 if (cli_api(cli,
169 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
170 NULL, 0, 200, /* data, length, maxlen */
171 &rparam, &rprcnt, /* return params, length */
172 &rdata, &rdrcnt)) /* return data, length */
174 res = GETRES(rparam);
176 if (res == 0) {
177 /* nothing to do */
179 else if ((res == 5) || (res == 65)) {
180 DEBUG(1, ("Access Denied\n"));
182 else if (res == 2220) {
183 DEBUG (1, ("Group does not exist\n"));
185 else {
186 DEBUG(4,("NetGroupDelete res=%d\n", res));
188 } else {
189 res = -1;
190 DEBUG(4,("NetGroupDelete failed\n"));
193 SAFE_FREE(rparam);
194 SAFE_FREE(rdata);
196 return res;
199 /****************************************************************************
200 call a NetGroupAdd - add user group to remote server
201 ****************************************************************************/
202 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
204 char *rparam = NULL;
205 char *rdata = NULL;
206 char *p;
207 int rdrcnt,rprcnt,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 char data[1024];
216 /* offset into data of free format strings. Will be updated */
217 /* by PUTSTRINGP macro and end up with total data length. */
218 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
220 /* now send a SMBtrans command with api WGroupAdd */
222 p = make_header(param, RAP_WGroupAdd,
223 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
224 PUTWORD(p, 1); /* info level */
225 PUTWORD(p, 0); /* reserved word 0 */
227 p = data;
228 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
229 PUTBYTE(p, 0); /* pad byte 0 */
230 PUTSTRINGP(p, grinfo->comment, data, soffset);
232 if (cli_api(cli,
233 param, sizeof(param), 1024, /* Param, length, maxlen */
234 data, soffset, sizeof(data), /* data, length, maxlen */
235 &rparam, &rprcnt, /* return params, length */
236 &rdata, &rdrcnt)) /* return data, length */
238 res = GETRES(rparam);
240 if (res == 0) {
241 /* nothing to do */
242 } else if ((res == 5) || (res == 65)) {
243 DEBUG(1, ("Access Denied\n"));
245 else if (res == 2223) {
246 DEBUG (1, ("Group already exists\n"));
248 else {
249 DEBUG(4,("NetGroupAdd res=%d\n", res));
251 } else {
252 res = -1;
253 DEBUG(4,("NetGroupAdd failed\n"));
256 SAFE_FREE(rparam);
257 SAFE_FREE(rdata);
259 return res;
262 /****************************************************************************
263 call a NetGroupEnum - try and list user groups on a different host
264 ****************************************************************************/
265 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
267 char param[WORDSIZE /* api number */
268 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
269 +sizeof(RAP_GROUP_INFO_L1) /* return string */
270 +WORDSIZE /* info level */
271 +WORDSIZE]; /* buffer size */
272 char *p;
273 char *rparam = NULL;
274 char *rdata = NULL;
275 int rprcnt, rdrcnt;
276 int res = -1;
279 memset(param, '\0', sizeof(param));
280 p = make_header(param, RAP_WGroupEnum,
281 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
282 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
283 PUTWORD(p,0xFFE0); /* Return buffer size */
285 if (cli_api(cli,
286 param, PTR_DIFF(p,param),8,
287 NULL, 0, 0xFFE0 /* data area size */,
288 &rparam, &rprcnt,
289 &rdata, &rdrcnt)) {
290 res = GETRES(rparam);
291 cli->rap_error = res;
292 if(cli->rap_error == 234)
293 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
294 else if (cli->rap_error != 0) {
295 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
299 if (rdata) {
300 if (res == 0 || res == ERRmoredata) {
301 int i, converter, count;
303 p = rparam + WORDSIZE; /* skip result */
304 GETWORD(p, converter);
305 GETWORD(p, count);
307 for (i=0,p=rdata;i<count;i++) {
308 pstring comment;
309 char groupname[RAP_GROUPNAME_LEN];
311 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
312 p++; /* pad byte */
313 GETSTRINGP(p, comment, rdata, converter);
315 fn(groupname, comment, cli);
317 } else {
318 DEBUG(4,("NetGroupEnum res=%d\n", res));
320 } else {
321 DEBUG(4,("NetGroupEnum no data returned\n"));
324 SAFE_FREE(rparam);
325 SAFE_FREE(rdata);
327 return res;
330 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
332 char *rparam = NULL;
333 char *rdata = NULL;
334 char *p;
335 int rdrcnt,rprcnt,res;
336 char param[WORDSIZE /* api number */
337 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
338 +1 /* no ret string */
339 +RAP_GROUPNAME_LEN /* group name */
340 +RAP_USERNAME_LEN]; /* user to del */
342 /* now send a SMBtrans command with api GroupMemberAdd */
343 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
344 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
345 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
347 if (cli_api(cli,
348 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
349 NULL, 0, 200, /* data, length, maxlen */
350 &rparam, &rprcnt, /* return params, length */
351 &rdata, &rdrcnt)) /* return data, length */
353 res = GETRES(rparam);
355 switch(res) {
356 case 0:
357 break;
358 case 5:
359 case 65:
360 DEBUG(1, ("Access Denied\n"));
361 break;
362 case 50:
363 DEBUG(1, ("Not supported by server\n"));
364 break;
365 case 2220:
366 DEBUG(1, ("Group does not exist\n"));
367 break;
368 case 2221:
369 DEBUG(1, ("User does not exist\n"));
370 break;
371 case 2237:
372 DEBUG(1, ("User is not in group\n"));
373 break;
374 default:
375 DEBUG(4,("NetGroupDelUser res=%d\n", res));
377 } else {
378 res = -1;
379 DEBUG(4,("NetGroupDelUser failed\n"));
382 SAFE_FREE(rparam);
383 SAFE_FREE(rdata);
385 return res;
388 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
390 char *rparam = NULL;
391 char *rdata = NULL;
392 char *p;
393 int rdrcnt,rprcnt,res;
394 char param[WORDSIZE /* api number */
395 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
396 +1 /* no ret string */
397 +RAP_GROUPNAME_LEN /* group name */
398 +RAP_USERNAME_LEN]; /* user to add */
400 /* now send a SMBtrans command with api GroupMemberAdd */
401 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
402 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
403 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
405 if (cli_api(cli,
406 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
407 NULL, 0, 200, /* data, length, maxlen */
408 &rparam, &rprcnt, /* return params, length */
409 &rdata, &rdrcnt)) /* return data, length */
411 res = GETRES(rparam);
413 switch(res) {
414 case 0:
415 break;
416 case 5:
417 case 65:
418 DEBUG(1, ("Access Denied\n"));
419 break;
420 case 50:
421 DEBUG(1, ("Not supported by server\n"));
422 break;
423 case 2220:
424 DEBUG(1, ("Group does not exist\n"));
425 break;
426 case 2221:
427 DEBUG(1, ("User does not exist\n"));
428 break;
429 default:
430 DEBUG(4,("NetGroupAddUser res=%d\n", res));
432 } else {
433 res = -1;
434 DEBUG(4,("NetGroupAddUser failed\n"));
437 SAFE_FREE(rparam);
438 SAFE_FREE(rdata);
440 return res;
444 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
446 char *rparam = NULL;
447 char *rdata = NULL;
448 char *p;
449 int rdrcnt,rprcnt;
450 int res = -1;
451 char param[WORDSIZE /* api number */
452 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
453 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
454 +RAP_GROUPNAME_LEN /* group name */
455 +WORDSIZE /* info level */
456 +WORDSIZE]; /* buffer size */
458 /* now send a SMBtrans command with api GroupGetUsers */
459 p = make_header(param, RAP_WGroupGetUsers,
460 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
461 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
462 PUTWORD(p,0); /* info level 0 */
463 PUTWORD(p,0xFFE0); /* return buffer size */
465 if (cli_api(cli,
466 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
467 NULL, 0, CLI_BUFFER_SIZE,
468 &rparam, &rprcnt,
469 &rdata, &rdrcnt)) {
470 res = GETRES(rparam);
471 cli->rap_error = res;
472 if (res != 0) {
473 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
476 if (rdata) {
477 if (res == 0 || res == ERRmoredata) {
478 int i, converter, count;
479 fstring username;
480 p = rparam +WORDSIZE;
481 GETWORD(p, converter);
482 GETWORD(p, count);
484 for (i=0,p=rdata; i<count; i++) {
485 GETSTRINGF(p, username, RAP_USERNAME_LEN);
486 fn(username, state);
488 } else {
489 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
491 } else {
492 DEBUG(4,("NetGroupGetUsers no data returned\n"));
494 SAFE_FREE(rdata);
495 SAFE_FREE(rparam);
496 return res;
499 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
501 char *rparam = NULL;
502 char *rdata = NULL;
503 char *p;
504 int rdrcnt,rprcnt;
505 int res = -1;
506 char param[WORDSIZE /* api number */
507 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
508 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
509 +RAP_USERNAME_LEN /* user name */
510 +WORDSIZE /* info level */
511 +WORDSIZE]; /* buffer size */
513 /* now send a SMBtrans command with api GroupGetUsers */
514 p = make_header(param, RAP_WUserGetGroups,
515 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
516 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
517 PUTWORD(p,0); /* info level 0 */
518 PUTWORD(p,0xFFE0); /* return buffer size */
520 if (cli_api(cli,
521 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
522 NULL, 0, CLI_BUFFER_SIZE,
523 &rparam, &rprcnt,
524 &rdata, &rdrcnt)) {
525 res = GETRES(rparam);
526 cli->rap_error = res;
527 if (res != 0) {
528 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
531 if (rdata) {
532 if (res == 0 || res == ERRmoredata) {
533 int i, converter, count;
534 fstring groupname;
535 p = rparam +WORDSIZE;
536 GETWORD(p, converter);
537 GETWORD(p, count);
539 for (i=0,p=rdata; i<count; i++) {
540 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
541 fn(groupname, state);
543 } else {
544 DEBUG(4,("NetUserGetGroups res=%d\n", res));
546 } else {
547 DEBUG(4,("NetUserGetGroups no data returned\n"));
549 SAFE_FREE(rdata);
550 SAFE_FREE(rparam);
551 return res;
555 /****************************************************************************
556 call a NetUserDelete - delete user from remote server
557 ****************************************************************************/
558 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
560 char *rparam = NULL;
561 char *rdata = NULL;
562 char *p;
563 int rdrcnt,rprcnt, res;
564 char param[WORDSIZE /* api number */
565 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
566 +1 /* no ret string */
567 +RAP_USERNAME_LEN /* user to del */
568 +WORDSIZE]; /* reserved word */
570 /* now send a SMBtrans command with api UserDel */
571 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
572 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
573 PUTWORD(p,0); /* reserved word MBZ on input */
575 if (cli_api(cli,
576 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
577 NULL, 0, 200, /* data, length, maxlen */
578 &rparam, &rprcnt, /* return params, length */
579 &rdata, &rdrcnt)) /* return data, length */
581 res = GETRES(rparam);
583 if (res == 0) {
584 /* nothing to do */
586 else if ((res == 5) || (res == 65)) {
587 DEBUG(1, ("Access Denied\n"));
589 else if (res == 2221) {
590 DEBUG (1, ("User does not exist\n"));
592 else {
593 DEBUG(4,("NetUserDelete res=%d\n", res));
595 } else {
596 res = -1;
597 DEBUG(4,("NetUserDelete failed\n"));
600 SAFE_FREE(rparam);
601 SAFE_FREE(rdata);
603 return res;
606 /****************************************************************************
607 call a NetUserAdd - add user to remote server
608 ****************************************************************************/
609 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
614 char *rparam = NULL;
615 char *rdata = NULL;
616 char *p;
617 int rdrcnt,rprcnt,res;
618 char param[WORDSIZE /* api number */
619 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
620 +sizeof(RAP_USER_INFO_L1) /* data string */
621 +WORDSIZE /* info level */
622 +WORDSIZE /* buffer length */
623 +WORDSIZE]; /* reserved */
625 char data[1024];
626 /* offset into data of free format strings. Will be updated */
627 /* by PUTSTRINGP macro and end up with total data length. */
628 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
629 + RAP_UPASSWD_LEN /* password */
630 + DWORDSIZE /* password age */
631 + WORDSIZE /* privilege */
632 + DWORDSIZE /* home dir ptr */
633 + DWORDSIZE /* comment ptr */
634 + WORDSIZE /* flags */
635 + DWORDSIZE; /* login script ptr*/
637 /* now send a SMBtrans command with api NetUserAdd */
638 p = make_header(param, RAP_WUserAdd2,
639 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
640 PUTWORD(p, 1); /* info level */
642 PUTWORD(p, 0); /* pwencrypt */
643 if(userinfo->passwrd)
644 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
645 else
646 PUTWORD(p, 0); /* password length */
648 p = data;
649 memset(data, '\0', soffset);
651 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
652 PUTBYTE(p, 0); /* pad byte 0 */
653 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
654 PUTDWORD(p, 0); /* pw age - n.a. on user add */
655 PUTWORD(p, userinfo->priv);
656 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
657 PUTSTRINGP(p, userinfo->comment, data, soffset);
658 PUTWORD(p, userinfo->userflags);
659 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
661 if (cli_api(cli,
662 param, sizeof(param), 1024, /* Param, length, maxlen */
663 data, soffset, sizeof(data), /* data, length, maxlen */
664 &rparam, &rprcnt, /* return params, length */
665 &rdata, &rdrcnt)) /* return data, length */
667 res = GETRES(rparam);
669 if (res == 0) {
670 /* nothing to do */
672 else if ((res == 5) || (res == 65)) {
673 DEBUG(1, ("Access Denied\n"));
675 else if (res == 2224) {
676 DEBUG (1, ("User already exists\n"));
678 else {
679 DEBUG(4,("NetUserAdd res=%d\n", res));
681 } else {
682 res = -1;
683 DEBUG(4,("NetUserAdd failed\n"));
686 SAFE_FREE(rparam);
687 SAFE_FREE(rdata);
689 return res;
692 /****************************************************************************
693 call a NetUserEnum - try and list users on a different host
694 ****************************************************************************/
695 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
697 char param[WORDSIZE /* api number */
698 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
699 +sizeof(RAP_USER_INFO_L1) /* return string */
700 +WORDSIZE /* info level */
701 +WORDSIZE]; /* buffer size */
702 char *p;
703 char *rparam = NULL;
704 char *rdata = NULL;
705 int rprcnt, rdrcnt;
706 int res = -1;
709 memset(param, '\0', sizeof(param));
710 p = make_header(param, RAP_WUserEnum,
711 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
712 PUTWORD(p,1); /* Info level 1 */
713 PUTWORD(p,0xFF00); /* Return buffer size */
715 /* BB Fix handling of large numbers of users to be returned */
716 if (cli_api(cli,
717 param, PTR_DIFF(p,param),8,
718 NULL, 0, CLI_BUFFER_SIZE,
719 &rparam, &rprcnt,
720 &rdata, &rdrcnt)) {
721 res = GETRES(rparam);
722 cli->rap_error = res;
723 if (cli->rap_error != 0) {
724 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
727 if (rdata) {
728 if (res == 0 || res == ERRmoredata) {
729 int i, converter, count;
730 char username[RAP_USERNAME_LEN];
731 char userpw[RAP_UPASSWD_LEN];
732 pstring comment, homedir, logonscript;
733 int pwage, priv, flags;
735 p = rparam + WORDSIZE; /* skip result */
736 GETWORD(p, converter);
737 GETWORD(p, count);
739 for (i=0,p=rdata;i<count;i++) {
740 GETSTRINGF(p, username, RAP_USERNAME_LEN);
741 p++; /* pad byte */
742 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
743 GETDWORD(p, pwage); /* password age */
744 GETWORD(p, priv); /* 0=guest, 1=user, 2=admin */
745 GETSTRINGP(p, homedir, rdata, converter);
746 GETSTRINGP(p, comment, rdata, converter);
747 GETWORD(p, flags);
748 GETSTRINGP(p, logonscript, rdata, converter);
750 fn(username, comment, homedir, logonscript, cli);
752 } else {
753 DEBUG(4,("NetUserEnum res=%d\n", res));
755 } else {
756 DEBUG(4,("NetUserEnum no data returned\n"));
759 SAFE_FREE(rparam);
760 SAFE_FREE(rdata);
762 return res;
765 /****************************************************************************
766 call a NetFileClose2 - close open file on another session to server
767 ****************************************************************************/
768 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
770 char *rparam = NULL;
771 char *rdata = NULL;
772 char *p;
773 int rdrcnt,rprcnt;
774 char param[WORDSIZE /* api number */
775 +sizeof(RAP_WFileClose2_REQ) /* req string */
776 +1 /* no ret string */
777 +DWORDSIZE]; /* file ID */
778 int res = -1;
780 /* now send a SMBtrans command with api RNetShareEnum */
781 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
782 PUTDWORD(p, file_id);
784 if (cli_api(cli,
785 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
786 NULL, 0, 200, /* data, length, maxlen */
787 &rparam, &rprcnt, /* return params, length */
788 &rdata, &rdrcnt)) /* return data, length */
790 res = GETRES(rparam);
792 if (res == 0) {
793 /* nothing to do */
794 } else if (res == 2314){
795 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
796 } else {
797 DEBUG(4,("NetFileClose2 res=%d\n", res));
799 } else {
800 res = -1;
801 DEBUG(4,("NetFileClose2 failed\n"));
804 SAFE_FREE(rparam);
805 SAFE_FREE(rdata);
807 return res;
810 /****************************************************************************
811 call a NetFileGetInfo - get information about server file opened from other
812 workstation
813 ****************************************************************************/
814 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
816 char *rparam = NULL;
817 char *rdata = NULL;
818 char *p;
819 int rdrcnt,rprcnt, res;
820 char param[WORDSIZE /* api number */
821 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
822 +sizeof(RAP_FILE_INFO_L3) /* return string */
823 +DWORDSIZE /* file ID */
824 +WORDSIZE /* info level */
825 +WORDSIZE]; /* buffer size */
827 /* now send a SMBtrans command with api RNetShareEnum */
828 p = make_header(param, RAP_WFileGetInfo2,
829 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
830 PUTDWORD(p, file_id);
831 PUTWORD(p, 3); /* info level */
832 PUTWORD(p, 0x1000); /* buffer size */
833 if (cli_api(cli,
834 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
835 NULL, 0, 0x1000, /* data, length, maxlen */
836 &rparam, &rprcnt, /* return params, length */
837 &rdata, &rdrcnt)) /* return data, length */
839 res = GETRES(rparam);
840 if (res == 0 || res == ERRmoredata) {
841 int converter,id, perms, locks;
842 pstring fpath, fuser;
844 p = rparam + WORDSIZE; /* skip result */
845 GETWORD(p, converter);
847 p = rdata;
848 GETDWORD(p, id);
849 GETWORD(p, perms);
850 GETWORD(p, locks);
851 GETSTRINGP(p, fpath, rdata, converter);
852 GETSTRINGP(p, fuser, rdata, converter);
854 fn(fpath, fuser, perms, locks, id);
855 } else {
856 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
858 } else {
859 res = -1;
860 DEBUG(4,("NetFileGetInfo2 failed\n"));
863 SAFE_FREE(rparam);
864 SAFE_FREE(rdata);
866 return res;
869 /****************************************************************************
870 * Call a NetFileEnum2 - list open files on an SMB server
872 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
873 * server listing the files open via the network (and their
874 * corresponding open instance ids)
876 * Dependencies: none
878 * Parameters:
879 * cli - pointer to cli_state structure
880 * user - if present, return only files opened by this remote user
881 * base_path - if present, return only files opened below this
882 * base path
883 * fn - display function to invoke for each entry in the result
886 * Returns:
887 * True - success
888 * False - failure
890 ****************************************************************************/
891 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
893 char *rparam = NULL;
894 char *rdata = NULL;
895 char *p;
896 int rdrcnt,rprcnt;
897 char param[WORDSIZE /* api number */
898 +sizeof(RAP_WFileEnum2_REQ) /* req string */
899 +sizeof(RAP_FILE_INFO_L3) /* return string */
900 +256 /* base path (opt) */
901 +RAP_USERNAME_LEN /* user name (opt) */
902 +WORDSIZE /* info level */
903 +WORDSIZE /* buffer size */
904 +DWORDSIZE /* resume key ? */
905 +DWORDSIZE]; /* resume key ? */
906 int count = -1;
908 /* now send a SMBtrans command with api RNetShareEnum */
909 p = make_header(param, RAP_WFileEnum2,
910 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
912 PUTSTRING(p, base_path, 256);
913 PUTSTRING(p, user, RAP_USERNAME_LEN);
914 PUTWORD(p, 3); /* info level */
915 PUTWORD(p, 0xFF00); /* buffer size */
916 PUTDWORD(p, 0); /* zero out the resume key */
917 PUTDWORD(p, 0); /* or is this one the resume key? */
919 if (cli_api(cli,
920 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
921 NULL, 0, 0xFF00, /* data, length, maxlen */
922 &rparam, &rprcnt, /* return params, length */
923 &rdata, &rdrcnt)) /* return data, length */
925 int res = GETRES(rparam);
927 if (res == 0 || res == ERRmoredata) {
928 int converter, i;
930 p = rparam + WORDSIZE; /* skip result */
931 GETWORD(p, converter);
932 GETWORD(p, count);
934 p = rdata;
935 for (i=0; i<count; i++) {
936 int id, perms, locks;
937 pstring fpath, fuser;
939 GETDWORD(p, id);
940 GETWORD(p, perms);
941 GETWORD(p, locks);
942 GETSTRINGP(p, fpath, rdata, converter);
943 GETSTRINGP(p, fuser, rdata, converter);
945 fn(fpath, fuser, perms, locks, id);
946 } /* BB fix ERRmoredata case to send resume request */
947 } else {
948 DEBUG(4,("NetFileEnum2 res=%d\n", res));
950 } else {
951 DEBUG(4,("NetFileEnum2 failed\n"));
954 SAFE_FREE(rparam);
955 SAFE_FREE(rdata);
957 return count;
960 /****************************************************************************
961 call a NetShareAdd - share/export directory on remote server
962 ****************************************************************************/
963 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
965 char *rparam = NULL;
966 char *rdata = NULL;
967 char *p;
968 int rdrcnt,rprcnt,res;
969 char param[WORDSIZE /* api number */
970 +sizeof(RAP_WShareAdd_REQ) /* req string */
971 +sizeof(RAP_SHARE_INFO_L2) /* return string */
972 +WORDSIZE /* info level */
973 +WORDSIZE]; /* reserved word */
974 char data[1024];
975 /* offset to free format string section following fixed length data. */
976 /* will be updated by PUTSTRINGP macro and will end up with total len */
977 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
978 + WORDSIZE /* share type */
979 + DWORDSIZE /* comment pointer */
980 + WORDSIZE /* permissions */
981 + WORDSIZE /* max users */
982 + WORDSIZE /* active users */
983 + DWORDSIZE /* share path */
984 + RAP_SPASSWD_LEN + 1; /* share password + pad */
986 memset(param,'\0',sizeof(param));
987 /* now send a SMBtrans command with api RNetShareAdd */
988 p = make_header(param, RAP_WshareAdd,
989 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
990 PUTWORD(p, 2); /* info level */
991 PUTWORD(p, 0); /* reserved word 0 */
993 p = data;
994 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
995 PUTBYTE(p, 0); /* pad byte 0 */
997 PUTWORD(p, sinfo->share_type);
998 PUTSTRINGP(p, sinfo->comment, data, soffset);
999 PUTWORD(p, sinfo->perms);
1000 PUTWORD(p, sinfo->maximum_users);
1001 PUTWORD(p, sinfo->active_users);
1002 PUTSTRINGP(p, sinfo->path, data, soffset);
1003 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1004 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1006 if (cli_api(cli,
1007 param, sizeof(param), 1024, /* Param, length, maxlen */
1008 data, soffset, sizeof(data), /* data, length, maxlen */
1009 &rparam, &rprcnt, /* return params, length */
1010 &rdata, &rdrcnt)) /* return data, length */
1012 res = rparam? SVAL(rparam,0) : -1;
1014 if (res == 0) {
1015 /* nothing to do */
1017 else {
1018 DEBUG(4,("NetShareAdd res=%d\n", res));
1020 } else {
1021 res = -1;
1022 DEBUG(4,("NetShareAdd failed\n"));
1025 SAFE_FREE(rparam);
1026 SAFE_FREE(rdata);
1028 return res;
1030 /****************************************************************************
1031 call a NetShareDelete - unshare exported directory on remote server
1032 ****************************************************************************/
1033 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1035 char *rparam = NULL;
1036 char *rdata = NULL;
1037 char *p;
1038 int rdrcnt,rprcnt, res;
1039 char param[WORDSIZE /* api number */
1040 +sizeof(RAP_WShareDel_REQ) /* req string */
1041 +1 /* no ret string */
1042 +RAP_SHARENAME_LEN /* share to del */
1043 +WORDSIZE]; /* reserved word */
1046 /* now send a SMBtrans command with api RNetShareDelete */
1047 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1048 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1049 PUTWORD(p,0); /* reserved word MBZ on input */
1051 if (cli_api(cli,
1052 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1053 NULL, 0, 200, /* data, length, maxlen */
1054 &rparam, &rprcnt, /* return params, length */
1055 &rdata, &rdrcnt)) /* return data, length */
1057 res = GETRES(rparam);
1059 if (res == 0) {
1060 /* nothing to do */
1062 else {
1063 DEBUG(4,("NetShareDelete res=%d\n", res));
1065 } else {
1066 res = -1;
1067 DEBUG(4,("NetShareDelete failed\n"));
1070 SAFE_FREE(rparam);
1071 SAFE_FREE(rdata);
1073 return res;
1075 /*************************************************************************
1077 * Function Name: cli_get_pdc_name
1079 * PURPOSE: Remotes a NetServerEnum API call to the current server
1080 * requesting the name of a server matching the server
1081 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1083 * Dependencies: none
1085 * Parameters:
1086 * cli - pointer to cli_state structure
1087 * workgroup - pointer to string containing name of domain
1088 * pdc_name - pointer to string that will contain PDC name
1089 * on successful return
1091 * Returns:
1092 * True - success
1093 * False - failure
1095 ************************************************************************/
1096 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1098 char *rparam = NULL;
1099 char *rdata = NULL;
1100 int rdrcnt,rprcnt;
1101 char *p;
1102 char param[WORDSIZE /* api number */
1103 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1104 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1105 +WORDSIZE /* info level */
1106 +WORDSIZE /* buffer size */
1107 +DWORDSIZE /* server type */
1108 +RAP_MACHNAME_LEN]; /* workgroup */
1109 int count = -1;
1111 *pdc_name = '\0';
1113 /* send a SMBtrans command with api NetServerEnum */
1114 p = make_header(param, RAP_NetServerEnum2,
1115 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1116 PUTWORD(p, 1); /* info level */
1117 PUTWORD(p, CLI_BUFFER_SIZE);
1118 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1119 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1121 if (cli_api(cli,
1122 param, PTR_DIFF(p,param), 8, /* params, length, max */
1123 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1124 &rparam, &rprcnt, /* return params, return size */
1125 &rdata, &rdrcnt /* return data, return size */
1126 )) {
1127 cli->rap_error = GETRES(rparam);
1130 * We only really care to copy a name if the
1131 * API succeeded and we got back a name.
1133 if (cli->rap_error == 0) {
1134 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1135 GETWORD(p, count);
1136 p = rdata;
1138 if (count > 0)
1139 GETSTRING(p, pdc_name);
1141 else {
1142 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1143 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1147 SAFE_FREE(rparam);
1148 SAFE_FREE(rdata);
1150 return(count > 0);
1154 /*************************************************************************
1156 * Function Name: cli_get_server_domain
1158 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1159 * requesting wksta_info_10 level information to determine
1160 * the domain the server belongs to. On success, this
1161 * routine sets the server_domain field in the cli_state structure
1162 * to the server's domain name.
1164 * Dependencies: none
1166 * Parameters:
1167 * cli - pointer to cli_state structure
1169 * Returns:
1170 * True - success
1171 * False - failure
1173 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1175 ************************************************************************/
1176 BOOL cli_get_server_domain(struct cli_state *cli)
1178 char *rparam = NULL;
1179 char *rdata = NULL;
1180 int rdrcnt,rprcnt;
1181 char *p;
1182 char param[WORDSIZE /* api number */
1183 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1184 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1185 +WORDSIZE /* info level */
1186 +WORDSIZE]; /* buffer size */
1187 int res = -1;
1189 /* send a SMBtrans command with api NetWkstaGetInfo */
1190 p = make_header(param, RAP_WWkstaGetInfo,
1191 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1192 PUTWORD(p, 10); /* info level */
1193 PUTWORD(p, CLI_BUFFER_SIZE);
1195 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1196 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1197 &rparam, &rprcnt, /* return params, return size */
1198 &rdata, &rdrcnt)) { /* return data, return size */
1199 res = GETRES(rparam);
1200 p = rdata;
1202 if (res == 0) {
1203 int converter;
1205 p = rparam + WORDSIZE;
1206 GETWORD(p, converter);
1208 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1209 GETSTRINGP(p, cli->server_domain, rdata, converter);
1213 SAFE_FREE(rparam);
1214 SAFE_FREE(rdata);
1216 return(res == 0);
1220 /*************************************************************************
1222 * Function Name: cli_get_server_type
1224 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1225 * requesting server_info_1 level information to retrieve
1226 * the server type.
1228 * Dependencies: none
1230 * Parameters:
1231 * cli - pointer to cli_state structure
1232 * pstype - pointer to uint32 to contain returned server type
1234 * Returns:
1235 * True - success
1236 * False - failure
1238 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1240 ************************************************************************/
1241 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1243 char *rparam = NULL;
1244 char *rdata = NULL;
1245 int rdrcnt,rprcnt;
1246 char *p;
1247 char param[WORDSIZE /* api number */
1248 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1249 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1250 +WORDSIZE /* info level */
1251 +WORDSIZE]; /* buffer size */
1252 int res = -1;
1254 /* send a SMBtrans command with api NetServerGetInfo */
1255 p = make_header(param, RAP_WserverGetInfo,
1256 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1257 PUTWORD(p, 1); /* info level */
1258 PUTWORD(p, CLI_BUFFER_SIZE);
1260 if (cli_api(cli,
1261 param, PTR_DIFF(p,param), 8, /* params, length, max */
1262 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1263 &rparam, &rprcnt, /* return params, return size */
1264 &rdata, &rdrcnt /* return data, return size */
1265 )) {
1267 res = GETRES(rparam);
1269 if (res == 0 || res == ERRmoredata) {
1270 p = rdata;
1271 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1275 SAFE_FREE(rparam);
1276 SAFE_FREE(rdata);
1278 return(res == 0 || res == ERRmoredata);
1282 /*************************************************************************
1284 * Function Name: cli_ns_check_server_type
1286 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1287 * requesting server_info_0 level information of machines
1288 * matching the given server type. If the returned server
1289 * list contains the machine name contained in cli->desthost
1290 * then we conclude the server type checks out. This routine
1291 * is useful to retrieve list of server's of a certain
1292 * type when all you have is a null session connection and
1293 * can't remote API calls such as NetWkstaGetInfo or
1294 * NetServerGetInfo.
1296 * Dependencies: none
1298 * Parameters:
1299 * cli - pointer to cli_state structure
1300 * workgroup - pointer to string containing domain
1301 * stype - server type
1303 * Returns:
1304 * True - success
1305 * False - failure
1307 ************************************************************************/
1308 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1310 char *rparam = NULL;
1311 char *rdata = NULL;
1312 int rdrcnt,rprcnt;
1313 char *p;
1314 char param[WORDSIZE /* api number */
1315 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1316 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1317 +WORDSIZE /* info level */
1318 +WORDSIZE /* buffer size */
1319 +DWORDSIZE /* server type */
1320 +RAP_MACHNAME_LEN]; /* workgroup */
1321 BOOL found_server = False;
1322 int res = -1;
1324 /* send a SMBtrans command with api NetServerEnum */
1325 p = make_header(param, RAP_NetServerEnum2,
1326 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1327 PUTWORD(p, 0); /* info level 0 */
1328 PUTWORD(p, CLI_BUFFER_SIZE);
1329 PUTDWORD(p, stype);
1330 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1332 if (cli_api(cli,
1333 param, PTR_DIFF(p,param), 8, /* params, length, max */
1334 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1335 &rparam, &rprcnt, /* return params, return size */
1336 &rdata, &rdrcnt /* return data, return size */
1337 )) {
1339 res = GETRES(rparam);
1340 cli->rap_error = res;
1342 if (res == 0 || res == ERRmoredata) {
1343 int i, converter, count;
1345 p = rparam + WORDSIZE;
1346 GETWORD(p, converter);
1347 GETWORD(p, count);
1349 p = rdata;
1350 for (i = 0;i < count;i++, p += 16) {
1351 char ret_server[RAP_MACHNAME_LEN];
1353 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1354 if (strequal(ret_server, cli->desthost)) {
1355 found_server = True;
1356 break;
1360 else {
1361 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1362 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1366 SAFE_FREE(rparam);
1367 SAFE_FREE(rdata);
1369 return found_server;
1373 /****************************************************************************
1374 perform a NetWkstaUserLogoff
1375 ****************************************************************************/
1376 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1378 char *rparam = NULL;
1379 char *rdata = NULL;
1380 char *p;
1381 int rdrcnt,rprcnt;
1382 char param[WORDSIZE /* api number */
1383 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1384 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1385 +RAP_USERNAME_LEN+1 /* user name+pad */
1386 +RAP_MACHNAME_LEN /* wksta name */
1387 +WORDSIZE /* buffer size */
1388 +WORDSIZE]; /* buffer size? */
1389 fstring upperbuf;
1391 memset(param, 0, sizeof(param));
1393 /* send a SMBtrans command with api NetWkstaUserLogoff */
1394 p = make_header(param, RAP_WWkstaUserLogoff,
1395 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1396 PUTDWORD(p, 0); /* Null pointer */
1397 PUTDWORD(p, 0); /* Null pointer */
1398 fstrcpy(upperbuf, user);
1399 strupper(upperbuf);
1400 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1401 p++; /* strange format, but ok */
1402 fstrcpy(upperbuf, workstation);
1403 strupper(upperbuf);
1404 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1405 PUTWORD(p, CLI_BUFFER_SIZE);
1406 PUTWORD(p, CLI_BUFFER_SIZE);
1408 if (cli_api(cli,
1409 param, PTR_DIFF(p,param),1024, /* param, length, max */
1410 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1411 &rparam, &rprcnt, /* return params, return size */
1412 &rdata, &rdrcnt /* return data, return size */
1413 )) {
1414 cli->rap_error = GETRES(rparam);
1416 if (cli->rap_error != 0) {
1417 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1421 SAFE_FREE(rparam);
1422 SAFE_FREE(rdata);
1423 return (cli->rap_error == 0);
1426 int cli_NetPrintQEnum(struct cli_state *cli,
1427 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1428 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1430 char param[WORDSIZE /* api number */
1431 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1432 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1433 +WORDSIZE /* info level */
1434 +WORDSIZE /* buffer size */
1435 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1436 char *p;
1437 char *rparam = NULL;
1438 char *rdata = NULL;
1439 int rprcnt, rdrcnt;
1440 int res = -1;
1443 memset(param, '\0',sizeof(param));
1444 p = make_header(param, RAP_WPrintQEnum,
1445 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1446 PUTWORD(p,2); /* Info level 2 */
1447 PUTWORD(p,0xFFE0); /* Return buffer size */
1448 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1450 if (cli_api(cli,
1451 param, PTR_DIFF(p,param),1024,
1452 NULL, 0, CLI_BUFFER_SIZE,
1453 &rparam, &rprcnt,
1454 &rdata, &rdrcnt)) {
1455 res = GETRES(rparam);
1456 cli->rap_error = res;
1457 if (res != 0) {
1458 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1462 if (rdata) {
1463 if (res == 0 || res == ERRmoredata) {
1464 int i, converter, count;
1466 p = rparam + WORDSIZE;
1467 GETWORD(p, converter);
1468 GETWORD(p, count);
1470 p = rdata;
1471 for (i=0;i<count;i++) {
1472 pstring qname, sep_file, print_proc, dest, parms, comment;
1473 uint16 jobcount, priority, start_time, until_time, status;
1475 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1476 p++; /* pad */
1477 GETWORD(p, priority);
1478 GETWORD(p, start_time);
1479 GETWORD(p, until_time);
1480 GETSTRINGP(p, sep_file, rdata, converter);
1481 GETSTRINGP(p, print_proc, rdata, converter);
1482 GETSTRINGP(p, dest, rdata, converter);
1483 GETSTRINGP(p, parms, rdata, converter);
1484 GETSTRINGP(p, parms, comment, converter);
1485 GETWORD(p, status);
1486 GETWORD(p, jobcount);
1488 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1489 dest, parms, comment, status, jobcount);
1491 if (jobcount) {
1492 int j;
1493 for (j=0;j<jobcount;j++) {
1494 uint16 jid, pos, fsstatus;
1495 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1496 unsigned int submitted, jsize;
1498 GETWORD(p, jid);
1499 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1500 p++; /* pad byte */
1501 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1502 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1503 GETSTRINGP(p, jparms, rdata, converter);
1504 GETWORD(p, pos);
1505 GETWORD(p, fsstatus);
1506 GETSTRINGP(p, jstatus, rdata, converter);
1507 GETDWORD(p, submitted);
1508 GETDWORD(p, jsize);
1509 GETSTRINGP(p, jcomment, rdata, converter);
1511 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1512 jstatus, submitted, jsize, jcomment);
1516 } else {
1517 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1519 } else {
1520 DEBUG(4,("NetPrintQEnum no data returned\n"));
1523 SAFE_FREE(rparam);
1524 SAFE_FREE(rdata);
1526 return res;
1529 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1530 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1531 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1533 char param[WORDSIZE /* api number */
1534 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1535 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1536 +RAP_SHARENAME_LEN /* printer name */
1537 +WORDSIZE /* info level */
1538 +WORDSIZE /* buffer size */
1539 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1540 char *p;
1541 char *rparam = NULL;
1542 char *rdata = NULL;
1543 int rprcnt, rdrcnt;
1544 int res = -1;
1547 memset(param, '\0',sizeof(param));
1548 p = make_header(param, RAP_WPrintQGetInfo,
1549 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1550 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1551 PUTWORD(p, 2); /* Info level 2 */
1552 PUTWORD(p,0xFFE0); /* Return buffer size */
1553 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1555 if (cli_api(cli,
1556 param, PTR_DIFF(p,param),1024,
1557 NULL, 0, CLI_BUFFER_SIZE,
1558 &rparam, &rprcnt,
1559 &rdata, &rdrcnt)) {
1560 res = GETRES(rparam);
1561 cli->rap_error = res;
1562 if (res != 0) {
1563 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1567 if (rdata) {
1568 if (res == 0 || res == ERRmoredata) {
1569 int rsize, converter;
1570 pstring qname, sep_file, print_proc, dest, parms, comment;
1571 uint16 jobcount, priority, start_time, until_time, status;
1573 p = rparam + WORDSIZE;
1574 GETWORD(p, converter);
1575 GETWORD(p, rsize);
1577 p = rdata;
1578 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1579 p++; /* pad */
1580 GETWORD(p, priority);
1581 GETWORD(p, start_time);
1582 GETWORD(p, until_time);
1583 GETSTRINGP(p, sep_file, rdata, converter);
1584 GETSTRINGP(p, print_proc, rdata, converter);
1585 GETSTRINGP(p, dest, rdata, converter);
1586 GETSTRINGP(p, parms, rdata, converter);
1587 GETSTRINGP(p, comment, rdata, converter);
1588 GETWORD(p, status);
1589 GETWORD(p, jobcount);
1590 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1591 dest, parms, comment, status, jobcount);
1592 if (jobcount) {
1593 int j;
1594 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1595 uint16 jid, pos, fsstatus;
1596 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1597 unsigned int submitted, jsize;
1599 GETWORD(p, jid);
1600 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1601 p++; /* pad byte */
1602 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1603 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1604 GETSTRINGP(p, jparms, rdata, converter);
1605 GETWORD(p, pos);
1606 GETWORD(p, fsstatus);
1607 GETSTRINGP(p, jstatus, rdata, converter);
1608 GETDWORD(p, submitted);
1609 GETDWORD(p, jsize);
1610 GETSTRINGP(p, jcomment, rdata, converter);
1612 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1613 jstatus, submitted, jsize, jcomment);
1616 } else {
1617 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1619 } else {
1620 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1623 SAFE_FREE(rparam);
1624 SAFE_FREE(rdata);
1626 return res;
1629 /****************************************************************************
1630 call a NetServiceEnum - list running services on a different host
1631 ****************************************************************************/
1632 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1634 char param[WORDSIZE /* api number */
1635 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1636 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1637 +WORDSIZE /* info level */
1638 +WORDSIZE]; /* buffer size */
1639 char *p;
1640 char *rparam = NULL;
1641 char *rdata = NULL;
1642 int rprcnt, rdrcnt;
1643 int res = -1;
1646 memset(param, '\0', sizeof(param));
1647 p = make_header(param, RAP_WServiceEnum,
1648 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1649 PUTWORD(p,2); /* Info level 2 */
1650 PUTWORD(p,0xFFE0); /* Return buffer size */
1652 if (cli_api(cli,
1653 param, PTR_DIFF(p,param),8,
1654 NULL, 0, 0xFFE0 /* data area size */,
1655 &rparam, &rprcnt,
1656 &rdata, &rdrcnt)) {
1657 res = GETRES(rparam);
1658 cli->rap_error = res;
1659 if(cli->rap_error == 234)
1660 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1661 else if (cli->rap_error != 0) {
1662 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1666 if (rdata) {
1667 if (res == 0 || res == ERRmoredata) {
1668 int i, converter, count;
1670 p = rparam + WORDSIZE; /* skip result */
1671 GETWORD(p, converter);
1672 GETWORD(p, count);
1674 for (i=0,p=rdata;i<count;i++) {
1675 pstring comment;
1676 char servicename[RAP_SRVCNAME_LEN];
1678 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1679 p+=8; /* pass status words */
1680 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1682 fn(servicename, comment, cli); /* BB add status too */
1684 } else {
1685 DEBUG(4,("NetServiceEnum res=%d\n", res));
1687 } else {
1688 DEBUG(4,("NetServiceEnum no data returned\n"));
1691 SAFE_FREE(rparam);
1692 SAFE_FREE(rdata);
1694 return res;
1698 /****************************************************************************
1699 call a NetSessionEnum - list workstations with sessions to an SMB server
1700 ****************************************************************************/
1701 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1703 char param[WORDSIZE /* api number */
1704 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1705 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1706 +WORDSIZE /* info level */
1707 +WORDSIZE]; /* buffer size */
1708 char *p;
1709 char *rparam = NULL;
1710 char *rdata = NULL;
1711 int rprcnt, rdrcnt;
1712 int res = -1;
1714 memset(param, '\0', sizeof(param));
1715 p = make_header(param, RAP_WsessionEnum,
1716 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1717 PUTWORD(p,2); /* Info level 2 */
1718 PUTWORD(p,0xFF); /* Return buffer size */
1720 if (cli_api(cli,
1721 param, PTR_DIFF(p,param),8,
1722 NULL, 0, CLI_BUFFER_SIZE,
1723 &rparam, &rprcnt,
1724 &rdata, &rdrcnt)) {
1725 res = GETRES(rparam);
1726 cli->rap_error = res;
1727 if (res != 0) {
1728 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1732 if (rdata) {
1733 if (res == 0 || res == ERRmoredata) {
1734 int i, converter, count;
1736 p = rparam + WORDSIZE;
1737 GETWORD(p, converter);
1738 GETWORD(p, count);
1740 for (i=0,p=rdata;i<count;i++) {
1741 pstring wsname, username, clitype_name;
1742 uint16 num_conns, num_opens, num_users;
1743 unsigned int sess_time, idle_time, user_flags;
1745 GETSTRINGP(p, wsname, rdata, converter);
1746 GETSTRINGP(p, username, rdata, converter);
1747 GETWORD(p, num_conns);
1748 GETWORD(p, num_opens);
1749 GETWORD(p, num_users);
1750 GETDWORD(p, sess_time);
1751 GETDWORD(p, idle_time);
1752 GETDWORD(p, user_flags);
1753 GETSTRINGP(p, clitype_name, rdata, converter);
1755 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1756 idle_time, user_flags, clitype_name);
1759 } else {
1760 DEBUG(4,("NetSessionEnum res=%d\n", res));
1762 } else {
1763 DEBUG(4,("NetSesssionEnum no data returned\n"));
1766 SAFE_FREE(rparam);
1767 SAFE_FREE(rdata);
1769 return res;
1772 /****************************************************************************
1773 Call a NetSessionGetInfo - get information about other session to an SMB server.
1774 ****************************************************************************/
1776 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1778 char param[WORDSIZE /* api number */
1779 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1780 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1781 +RAP_MACHNAME_LEN /* wksta name */
1782 +WORDSIZE /* info level */
1783 +WORDSIZE]; /* buffer size */
1784 char *p;
1785 char *rparam = NULL;
1786 char *rdata = NULL;
1787 int rprcnt, rdrcnt;
1788 int res = -1;
1791 memset(param, '\0', sizeof(param));
1792 p = make_header(param, RAP_WsessionGetInfo,
1793 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1794 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1795 PUTWORD(p,2); /* Info level 2 */
1796 PUTWORD(p,0xFF); /* Return buffer size */
1798 if (cli_api(cli,
1799 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1800 NULL, 0, CLI_BUFFER_SIZE,
1801 &rparam, &rprcnt,
1802 &rdata, &rdrcnt)) {
1803 cli->rap_error = SVAL(rparam,0);
1804 if (cli->rap_error != 0) {
1805 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1809 if (rdata) {
1810 res = GETRES(rparam);
1812 if (res == 0 || res == ERRmoredata) {
1813 int rsize, converter;
1814 pstring wsname, username, clitype_name;
1815 uint16 num_conns, num_opens, num_users;
1816 unsigned int sess_time, idle_time, user_flags;
1818 p = rparam + WORDSIZE;
1819 GETWORD(p, converter);
1820 GETWORD(p, rsize);
1822 p = rdata;
1823 GETSTRINGP(p, wsname, rdata, converter);
1824 GETSTRINGP(p, username, rdata, converter);
1825 GETWORD(p, num_conns);
1826 GETWORD(p, num_opens);
1827 GETWORD(p, num_users);
1828 GETDWORD(p, sess_time);
1829 GETDWORD(p, idle_time);
1830 GETDWORD(p, user_flags);
1831 GETSTRINGP(p, clitype_name, rdata, converter);
1833 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1834 idle_time, user_flags, clitype_name);
1835 } else {
1836 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1838 } else {
1839 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1842 SAFE_FREE(rparam);
1843 SAFE_FREE(rdata);
1845 return res;
1848 /****************************************************************************
1849 call a NetSessionDel - close a session to an SMB server
1850 ****************************************************************************/
1851 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1853 char param[WORDSIZE /* api number */
1854 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1855 +1 /* no return string */
1856 +RAP_MACHNAME_LEN /* workstation name */
1857 +WORDSIZE]; /* reserved (0) */
1858 char *p;
1859 char *rparam = NULL;
1860 char *rdata = NULL;
1861 int rprcnt, rdrcnt;
1862 int res;
1864 memset(param, '\0', sizeof(param));
1865 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1866 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1867 PUTWORD(p,0); /* reserved word of 0 */
1868 if (cli_api(cli,
1869 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1870 NULL, 0, 200, /* data, length, maxlen */
1871 &rparam, &rprcnt, /* return params, length */
1872 &rdata, &rdrcnt)) /* return data, length */
1874 res = GETRES(rparam);
1875 cli->rap_error = res;
1877 if (res == 0) {
1878 /* nothing to do */
1880 else {
1881 DEBUG(4,("NetFileClose2 res=%d\n", res));
1883 } else {
1884 res = -1;
1885 DEBUG(4,("NetFileClose2 failed\n"));
1888 SAFE_FREE(rparam);
1889 SAFE_FREE(rdata);
1891 return res;
1895 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))
1897 char param[WORDSIZE /* api number */
1898 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
1899 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
1900 +RAP_MACHNAME_LEN /* wksta name */
1901 +WORDSIZE /* info level */
1902 +WORDSIZE]; /* buffer size */
1903 char *p;
1904 char *rparam = NULL;
1905 char *rdata = NULL;
1906 int rprcnt, rdrcnt;
1907 int res = -1;
1909 memset(param, '\0', sizeof(param));
1910 p = make_header(param, RAP_WconnectionEnum,
1911 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
1912 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
1913 PUTWORD(p,1); /* Info level 1 */
1914 PUTWORD(p,0xFFE0); /* Return buffer size */
1916 if (cli_api(cli,
1917 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1918 NULL, 0, CLI_BUFFER_SIZE,
1919 &rparam, &rprcnt,
1920 &rdata, &rdrcnt)) {
1921 res = GETRES(rparam);
1922 cli->rap_error = res;
1923 if (res != 0) {
1924 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
1927 if (rdata) {
1928 if (res == 0 || res == ERRmoredata) {
1929 int i, converter, count;
1931 p = rparam + WORDSIZE;
1932 GETWORD(p, converter);
1933 GETWORD(p, count);
1935 for (i=0,p=rdata;i<count;i++) {
1936 pstring netname, username;
1937 uint16 conn_id, conn_type, num_opens, num_users;
1938 unsigned int conn_time;
1940 GETWORD(p,conn_id);
1941 GETWORD(p,conn_type);
1942 GETWORD(p,num_opens);
1943 GETWORD(p,num_users);
1944 GETDWORD(p,conn_time);
1945 GETSTRINGP(p, username, rdata, converter);
1946 GETSTRINGP(p, netname, rdata, converter);
1948 fn(conn_id, conn_type, num_opens, num_users, conn_time,
1949 username, netname);
1952 } else {
1953 DEBUG(4,("NetConnectionEnum res=%d\n", res));
1955 } else {
1956 DEBUG(4,("NetConnectionEnum no data returned\n"));
1958 SAFE_FREE(rdata);
1959 SAFE_FREE(rparam);
1960 return res;