preparing for release of 3.0-alpha11
[Samba/ekacnet.git] / source / libsmb / clirap2.c
blob2fde0c70e501269f863f2b3ed3c7b150d1c88722
1 /*
2 Samba Unix/Linux SMB client library
3 Version 3.0
4 More client RAP (SMB Remote Procedure Calls) functions
5 Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
6 Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /*****************************************************/
25 /* */
26 /* Additional RAP functionality */
27 /* */
28 /* RAP is the original SMB RPC, documented */
29 /* by Microsoft and X/Open in the 1990s and */
30 /* supported by most SMB/CIFS servers although */
31 /* it is unlikely that any one implementation */
32 /* supports all RAP command codes since some */
33 /* are quite obsolete and a few are specific */
34 /* to a particular network operating system */
35 /* */
36 /* Although it has largely been replaced */
37 /* for complex remote admistration and management */
38 /* (of servers) by the relatively newer */
39 /* DCE/RPC based remote API (which better handles */
40 /* large >64K data structures), there are many */
41 /* important administrative and resource location */
42 /* tasks and user tasks (e.g. password change) */
43 /* that are performed via RAP. */
44 /* */
45 /* Although a few of the RAP calls are implemented */
46 /* in the Samba client library already (clirap.c) */
47 /* the new ones are in clirap2.c for easy patching */
48 /* and integration and a corresponding header */
49 /* file, rap.h, has been created. */
50 /* */
51 /* This is based on data from the CIFS spec */
52 /* and the LAN Server and LAN Manager */
53 /* Programming Reference books and published */
54 /* RAP document and CIFS forum postings and */
55 /* lots of trial and error */
56 /* */
57 /* Function names changed from API_ (as they are */
58 /* in the CIFS specification) to RAP_ in order */
59 /* to avoid confusion with other API calls */
60 /* sent via DCE RPC */
61 /* */
62 /*****************************************************/
64 /*****************************************************/
65 /* */
66 /* cifsrap.c already includes support for: */
67 /* */
68 /* WshareEnum ( API number 0, level 1) */
69 /* NetServerEnum2 (API num 104, level 1) */
70 /* WWkstaUserLogon (132) */
71 /* SamOEMchgPasswordUser2_P (214) */
72 /* */
73 /* cifsprint.c already includes support for: */
74 /* */
75 /* WPrintJobEnum (API num 76, level 2) */
76 /* WPrintJobDel (API num 81) */
77 /* */
78 /*****************************************************/
80 #define NO_SYSLOG
82 #include "includes.h"
84 #define WORDSIZE 2
85 #define DWORDSIZE 4
87 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
88 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
89 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
90 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
91 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
92 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
93 #define GETRES(p) p ? SVAL(p,0) : -1
94 /* put string s at p with max len n and increment p past string */
95 #define PUTSTRING(p,s,n) do {\
96 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
97 p = skip_string(p,1);\
98 } while(0)
99 /* put string s and p, using fixed len l, and increment p by l */
100 #define PUTSTRINGF(p,s,l) do {\
101 push_ascii(p,s?s:"",l,STR_TERMINATE);\
102 p += l;\
103 } while (0)
104 /* put string pointer at p, supplying offset o from rdata r, store */
105 /* dword offset at p, increment p by 4 and o by length of s. This */
106 /* means on the first call, you must calc the offset yourself! */
107 #define PUTSTRINGP(p,s,r,o) do {\
108 if (s) {\
109 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
110 PUTDWORD(p,o);\
111 o += strlen(s) + 1;\
112 } else PUTDWORD(p,0);\
113 }while(0);
114 /* get asciiz string s from p, increment p past string */
115 #define GETSTRING(p,s) do {\
116 pull_ascii_pstring(s,p);\
117 p = skip_string(p,1);\
118 } while(0)
119 /* get fixed length l string s from p, increment p by l */
120 #define GETSTRINGF(p,s,l) do {\
121 pull_ascii_pstring(s,p);\
122 p += l;\
123 } while(0)
124 /* get string s from offset (obtained at p) from rdata r - converter c */
125 #define GETSTRINGP(p,s,r,c) do {\
126 uint32 off;\
127 GETDWORD(p,off);\
128 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
129 pull_ascii_pstring(s, off?(r+off-c):"");\
130 } while(0)
132 static char *make_header(char *param, uint16 apinum, char *reqfmt, char *datafmt)
134 PUTWORD(param,apinum);
135 if (reqfmt)
136 PUTSTRING(param,reqfmt,0);
137 else
138 *param++ = (char) 0;
140 if (datafmt)
141 PUTSTRING(param,datafmt,0);
142 else
143 *param++ = (char) 0;
145 return param;
149 /****************************************************************************
150 call a NetGroupDelete - delete user group from remote server
151 ****************************************************************************/
152 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
154 char *rparam = NULL;
155 char *rdata = NULL;
156 char *p;
157 int rdrcnt,rprcnt, 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 int rdrcnt,rprcnt,res;
209 char param[WORDSIZE /* api number */
210 +sizeof(RAP_NetGroupAdd_REQ) /* req string */
211 +sizeof(RAP_GROUP_INFO_L1) /* return string */
212 +WORDSIZE /* info level */
213 +WORDSIZE]; /* reserved word */
215 char data[1024];
217 /* offset into data of free format strings. Will be updated */
218 /* by PUTSTRINGP macro and end up with total data length. */
219 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
221 /* now send a SMBtrans command with api WGroupAdd */
223 p = make_header(param, RAP_WGroupAdd,
224 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
225 PUTWORD(p, 1); /* info level */
226 PUTWORD(p, 0); /* reserved word 0 */
228 p = data;
229 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
230 PUTBYTE(p, 0); /* pad byte 0 */
231 PUTSTRINGP(p, grinfo->comment, data, soffset);
233 if (cli_api(cli,
234 param, sizeof(param), 1024, /* Param, length, maxlen */
235 data, soffset, sizeof(data), /* data, length, maxlen */
236 &rparam, &rprcnt, /* return params, length */
237 &rdata, &rdrcnt)) /* return data, length */
239 res = GETRES(rparam);
241 if (res == 0) {
242 /* nothing to do */
243 } else if ((res == 5) || (res == 65)) {
244 DEBUG(1, ("Access Denied\n"));
246 else if (res == 2223) {
247 DEBUG (1, ("Group already exists\n"));
249 else {
250 DEBUG(4,("NetGroupAdd res=%d\n", res));
252 } else {
253 res = -1;
254 DEBUG(4,("NetGroupAdd failed\n"));
257 SAFE_FREE(rparam);
258 SAFE_FREE(rdata);
260 return res;
263 /****************************************************************************
264 call a NetGroupEnum - try and list user groups on a different host
265 ****************************************************************************/
266 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
268 char param[WORDSIZE /* api number */
269 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
270 +sizeof(RAP_GROUP_INFO_L1) /* return string */
271 +WORDSIZE /* info level */
272 +WORDSIZE]; /* buffer size */
273 char *p;
274 char *rparam = NULL;
275 char *rdata = NULL;
276 int rprcnt, rdrcnt;
277 int res = -1;
280 memset(param, '\0', sizeof(param));
281 p = make_header(param, RAP_WGroupEnum,
282 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
283 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
284 PUTWORD(p,0xFFE0); /* Return buffer size */
286 if (cli_api(cli,
287 param, PTR_DIFF(p,param),8,
288 NULL, 0, 0xFFE0 /* data area size */,
289 &rparam, &rprcnt,
290 &rdata, &rdrcnt)) {
291 res = GETRES(rparam);
292 cli->rap_error = res;
293 if(cli->rap_error == 234)
294 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
295 else if (cli->rap_error != 0) {
296 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
300 if (rdata) {
301 if (res == 0 || res == ERRmoredata) {
302 int i, converter, count;
304 p = rparam + WORDSIZE; /* skip result */
305 GETWORD(p, converter);
306 GETWORD(p, count);
308 for (i=0,p=rdata;i<count;i++) {
309 pstring comment;
310 char groupname[RAP_GROUPNAME_LEN];
312 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
313 p++; /* pad byte */
314 GETSTRINGP(p, comment, rdata, converter);
316 fn(groupname, comment, cli);
318 } else {
319 DEBUG(4,("NetGroupEnum res=%d\n", res));
321 } else {
322 DEBUG(4,("NetGroupEnum no data returned\n"));
325 SAFE_FREE(rparam);
326 SAFE_FREE(rdata);
328 return res;
331 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
333 char *rparam = NULL;
334 char *rdata = NULL;
335 char *p;
336 int rdrcnt,rprcnt,res;
337 char param[WORDSIZE /* api number */
338 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
339 +1 /* no ret string */
340 +RAP_GROUPNAME_LEN /* group name */
341 +RAP_USERNAME_LEN]; /* user to del */
343 /* now send a SMBtrans command with api GroupMemberAdd */
344 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
345 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
346 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
348 if (cli_api(cli,
349 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
350 NULL, 0, 200, /* data, length, maxlen */
351 &rparam, &rprcnt, /* return params, length */
352 &rdata, &rdrcnt)) /* return data, length */
354 res = GETRES(rparam);
356 switch(res) {
357 case 0:
358 break;
359 case 5:
360 case 65:
361 DEBUG(1, ("Access Denied\n"));
362 break;
363 case 50:
364 DEBUG(1, ("Not supported by server\n"));
365 break;
366 case 2220:
367 DEBUG(1, ("Group does not exist\n"));
368 break;
369 case 2221:
370 DEBUG(1, ("User does not exist\n"));
371 break;
372 case 2237:
373 DEBUG(1, ("User is not in group\n"));
374 break;
375 default:
376 DEBUG(4,("NetGroupDelUser res=%d\n", res));
378 } else {
379 res = -1;
380 DEBUG(4,("NetGroupDelUser failed\n"));
383 SAFE_FREE(rparam);
384 SAFE_FREE(rdata);
386 return res;
389 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
391 char *rparam = NULL;
392 char *rdata = NULL;
393 char *p;
394 int rdrcnt,rprcnt,res;
395 char param[WORDSIZE /* api number */
396 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
397 +1 /* no ret string */
398 +RAP_GROUPNAME_LEN /* group name */
399 +RAP_USERNAME_LEN]; /* user to add */
401 /* now send a SMBtrans command with api GroupMemberAdd */
402 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
403 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
404 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
406 if (cli_api(cli,
407 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
408 NULL, 0, 200, /* data, length, maxlen */
409 &rparam, &rprcnt, /* return params, length */
410 &rdata, &rdrcnt)) /* return data, length */
412 res = GETRES(rparam);
414 switch(res) {
415 case 0:
416 break;
417 case 5:
418 case 65:
419 DEBUG(1, ("Access Denied\n"));
420 break;
421 case 50:
422 DEBUG(1, ("Not supported by server\n"));
423 break;
424 case 2220:
425 DEBUG(1, ("Group does not exist\n"));
426 break;
427 case 2221:
428 DEBUG(1, ("User does not exist\n"));
429 break;
430 default:
431 DEBUG(4,("NetGroupAddUser res=%d\n", res));
433 } else {
434 res = -1;
435 DEBUG(4,("NetGroupAddUser failed\n"));
438 SAFE_FREE(rparam);
439 SAFE_FREE(rdata);
441 return res;
445 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
447 char *rparam = NULL;
448 char *rdata = NULL;
449 char *p;
450 int rdrcnt,rprcnt;
451 int res = -1;
452 char param[WORDSIZE /* api number */
453 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
454 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
455 +RAP_GROUPNAME_LEN /* group name */
456 +WORDSIZE /* info level */
457 +WORDSIZE]; /* buffer size */
459 /* now send a SMBtrans command with api GroupGetUsers */
460 p = make_header(param, RAP_WGroupGetUsers,
461 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
462 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
463 PUTWORD(p,0); /* info level 0 */
464 PUTWORD(p,0xFFE0); /* return buffer size */
466 if (cli_api(cli,
467 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
468 NULL, 0, CLI_BUFFER_SIZE,
469 &rparam, &rprcnt,
470 &rdata, &rdrcnt)) {
471 res = GETRES(rparam);
472 cli->rap_error = res;
473 if (res != 0) {
474 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
477 if (rdata) {
478 if (res == 0 || res == ERRmoredata) {
479 int i, converter, count;
480 fstring username;
481 p = rparam +WORDSIZE;
482 GETWORD(p, converter);
483 GETWORD(p, count);
485 for (i=0,p=rdata; i<count; i++) {
486 GETSTRINGF(p, username, RAP_USERNAME_LEN);
487 fn(username, state);
489 } else {
490 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
492 } else {
493 DEBUG(4,("NetGroupGetUsers no data returned\n"));
495 SAFE_FREE(rdata);
496 SAFE_FREE(rparam);
497 return res;
500 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
502 char *rparam = NULL;
503 char *rdata = NULL;
504 char *p;
505 int rdrcnt,rprcnt;
506 int res = -1;
507 char param[WORDSIZE /* api number */
508 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
509 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
510 +RAP_USERNAME_LEN /* user name */
511 +WORDSIZE /* info level */
512 +WORDSIZE]; /* buffer size */
514 /* now send a SMBtrans command with api GroupGetUsers */
515 p = make_header(param, RAP_WUserGetGroups,
516 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
517 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
518 PUTWORD(p,0); /* info level 0 */
519 PUTWORD(p,0xFFE0); /* return buffer size */
521 if (cli_api(cli,
522 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
523 NULL, 0, CLI_BUFFER_SIZE,
524 &rparam, &rprcnt,
525 &rdata, &rdrcnt)) {
526 res = GETRES(rparam);
527 cli->rap_error = res;
528 if (res != 0) {
529 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
532 if (rdata) {
533 if (res == 0 || res == ERRmoredata) {
534 int i, converter, count;
535 fstring groupname;
536 p = rparam +WORDSIZE;
537 GETWORD(p, converter);
538 GETWORD(p, count);
540 for (i=0,p=rdata; i<count; i++) {
541 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
542 fn(groupname, state);
544 } else {
545 DEBUG(4,("NetUserGetGroups res=%d\n", res));
547 } else {
548 DEBUG(4,("NetUserGetGroups no data returned\n"));
550 SAFE_FREE(rdata);
551 SAFE_FREE(rparam);
552 return res;
556 /****************************************************************************
557 call a NetUserDelete - delete user from remote server
558 ****************************************************************************/
559 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
561 char *rparam = NULL;
562 char *rdata = NULL;
563 char *p;
564 int rdrcnt,rprcnt, res;
565 char param[WORDSIZE /* api number */
566 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
567 +1 /* no ret string */
568 +RAP_USERNAME_LEN /* user to del */
569 +WORDSIZE]; /* reserved word */
571 /* now send a SMBtrans command with api UserDel */
572 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
573 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
574 PUTWORD(p,0); /* reserved word MBZ on input */
576 if (cli_api(cli,
577 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
578 NULL, 0, 200, /* data, length, maxlen */
579 &rparam, &rprcnt, /* return params, length */
580 &rdata, &rdrcnt)) /* return data, length */
582 res = GETRES(rparam);
584 if (res == 0) {
585 /* nothing to do */
587 else if ((res == 5) || (res == 65)) {
588 DEBUG(1, ("Access Denied\n"));
590 else if (res == 2221) {
591 DEBUG (1, ("User does not exist\n"));
593 else {
594 DEBUG(4,("NetUserDelete res=%d\n", res));
596 } else {
597 res = -1;
598 DEBUG(4,("NetUserDelete failed\n"));
601 SAFE_FREE(rparam);
602 SAFE_FREE(rdata);
604 return res;
607 /****************************************************************************
608 call a NetUserAdd - add user to remote server
609 ****************************************************************************/
610 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
615 char *rparam = NULL;
616 char *rdata = NULL;
617 char *p;
618 int rdrcnt,rprcnt,res;
619 char param[WORDSIZE /* api number */
620 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
621 +sizeof(RAP_USER_INFO_L1) /* data string */
622 +WORDSIZE /* info level */
623 +WORDSIZE /* buffer length */
624 +WORDSIZE]; /* reserved */
626 char data[1024];
627 /* offset into data of free format strings. Will be updated */
628 /* by PUTSTRINGP macro and end up with total data length. */
629 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
630 + RAP_UPASSWD_LEN /* password */
631 + DWORDSIZE /* password age */
632 + WORDSIZE /* privilege */
633 + DWORDSIZE /* home dir ptr */
634 + DWORDSIZE /* comment ptr */
635 + WORDSIZE /* flags */
636 + DWORDSIZE; /* login script ptr*/
638 /* now send a SMBtrans command with api NetUserAdd */
639 p = make_header(param, RAP_WUserAdd2,
640 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
641 PUTWORD(p, 1); /* info level */
643 PUTWORD(p, 0); /* pwencrypt */
644 if(userinfo->passwrd)
645 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
646 else
647 PUTWORD(p, 0); /* password length */
649 p = data;
650 memset(data, '\0', soffset);
652 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
653 PUTBYTE(p, 0); /* pad byte 0 */
654 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
655 PUTDWORD(p, 0); /* pw age - n.a. on user add */
656 PUTWORD(p, userinfo->priv);
657 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
658 PUTSTRINGP(p, userinfo->comment, data, soffset);
659 PUTWORD(p, userinfo->userflags);
660 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
662 if (cli_api(cli,
663 param, sizeof(param), 1024, /* Param, length, maxlen */
664 data, soffset, sizeof(data), /* data, length, maxlen */
665 &rparam, &rprcnt, /* return params, length */
666 &rdata, &rdrcnt)) /* return data, length */
668 res = GETRES(rparam);
670 if (res == 0) {
671 /* nothing to do */
673 else if ((res == 5) || (res == 65)) {
674 DEBUG(1, ("Access Denied\n"));
676 else if (res == 2224) {
677 DEBUG (1, ("User already exists\n"));
679 else {
680 DEBUG(4,("NetUserAdd res=%d\n", res));
682 } else {
683 res = -1;
684 DEBUG(4,("NetUserAdd failed\n"));
687 SAFE_FREE(rparam);
688 SAFE_FREE(rdata);
690 return res;
693 /****************************************************************************
694 call a NetUserEnum - try and list users on a different host
695 ****************************************************************************/
696 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
698 char param[WORDSIZE /* api number */
699 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
700 +sizeof(RAP_USER_INFO_L1) /* return string */
701 +WORDSIZE /* info level */
702 +WORDSIZE]; /* buffer size */
703 char *p;
704 char *rparam = NULL;
705 char *rdata = NULL;
706 int rprcnt, rdrcnt;
707 int res = -1;
710 memset(param, '\0', sizeof(param));
711 p = make_header(param, RAP_WUserEnum,
712 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
713 PUTWORD(p,1); /* Info level 1 */
714 PUTWORD(p,0xFF00); /* Return buffer size */
716 /* BB Fix handling of large numbers of users to be returned */
717 if (cli_api(cli,
718 param, PTR_DIFF(p,param),8,
719 NULL, 0, CLI_BUFFER_SIZE,
720 &rparam, &rprcnt,
721 &rdata, &rdrcnt)) {
722 res = GETRES(rparam);
723 cli->rap_error = res;
724 if (cli->rap_error != 0) {
725 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
728 if (rdata) {
729 if (res == 0 || res == ERRmoredata) {
730 int i, converter, count;
731 char username[RAP_USERNAME_LEN];
732 char userpw[RAP_UPASSWD_LEN];
733 pstring comment, homedir, logonscript;
734 int pwage, priv, flags;
736 p = rparam + WORDSIZE; /* skip result */
737 GETWORD(p, converter);
738 GETWORD(p, count);
740 for (i=0,p=rdata;i<count;i++) {
741 GETSTRINGF(p, username, RAP_USERNAME_LEN);
742 p++; /* pad byte */
743 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
744 GETDWORD(p, pwage); /* password age */
745 GETWORD(p, priv); /* 0=guest, 1=user, 2=admin */
746 GETSTRINGP(p, homedir, rdata, converter);
747 GETSTRINGP(p, comment, rdata, converter);
748 GETWORD(p, flags);
749 GETSTRINGP(p, logonscript, rdata, converter);
751 fn(username, comment, homedir, logonscript, cli);
753 } else {
754 DEBUG(4,("NetUserEnum res=%d\n", res));
756 } else {
757 DEBUG(4,("NetUserEnum no data returned\n"));
760 SAFE_FREE(rparam);
761 SAFE_FREE(rdata);
763 return res;
766 /****************************************************************************
767 call a NetFileClose2 - close open file on another session to server
768 ****************************************************************************/
769 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
771 char *rparam = NULL;
772 char *rdata = NULL;
773 char *p;
774 int rdrcnt,rprcnt;
775 char param[WORDSIZE /* api number */
776 +sizeof(RAP_WFileClose2_REQ) /* req string */
777 +1 /* no ret string */
778 +DWORDSIZE]; /* file ID */
779 int res = -1;
781 /* now send a SMBtrans command with api RNetShareEnum */
782 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
783 PUTDWORD(p, file_id);
785 if (cli_api(cli,
786 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
787 NULL, 0, 200, /* data, length, maxlen */
788 &rparam, &rprcnt, /* return params, length */
789 &rdata, &rdrcnt)) /* return data, length */
791 res = GETRES(rparam);
793 if (res == 0) {
794 /* nothing to do */
795 } else if (res == 2314){
796 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
797 } else {
798 DEBUG(4,("NetFileClose2 res=%d\n", res));
800 } else {
801 res = -1;
802 DEBUG(4,("NetFileClose2 failed\n"));
805 SAFE_FREE(rparam);
806 SAFE_FREE(rdata);
808 return res;
811 /****************************************************************************
812 call a NetFileGetInfo - get information about server file opened from other
813 workstation
814 ****************************************************************************/
815 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
817 char *rparam = NULL;
818 char *rdata = NULL;
819 char *p;
820 int rdrcnt,rprcnt, res;
821 char param[WORDSIZE /* api number */
822 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
823 +sizeof(RAP_FILE_INFO_L3) /* return string */
824 +DWORDSIZE /* file ID */
825 +WORDSIZE /* info level */
826 +WORDSIZE]; /* buffer size */
828 /* now send a SMBtrans command with api RNetShareEnum */
829 p = make_header(param, RAP_WFileGetInfo2,
830 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
831 PUTDWORD(p, file_id);
832 PUTWORD(p, 3); /* info level */
833 PUTWORD(p, 0x1000); /* buffer size */
834 if (cli_api(cli,
835 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
836 NULL, 0, 0x1000, /* data, length, maxlen */
837 &rparam, &rprcnt, /* return params, length */
838 &rdata, &rdrcnt)) /* return data, length */
840 res = GETRES(rparam);
841 if (res == 0 || res == ERRmoredata) {
842 int converter,id, perms, locks;
843 pstring fpath, fuser;
845 p = rparam + WORDSIZE; /* skip result */
846 GETWORD(p, converter);
848 p = rdata;
849 GETDWORD(p, id);
850 GETWORD(p, perms);
851 GETWORD(p, locks);
852 GETSTRINGP(p, fpath, rdata, converter);
853 GETSTRINGP(p, fuser, rdata, converter);
855 fn(fpath, fuser, perms, locks, id);
856 } else {
857 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
859 } else {
860 res = -1;
861 DEBUG(4,("NetFileGetInfo2 failed\n"));
864 SAFE_FREE(rparam);
865 SAFE_FREE(rdata);
867 return res;
870 /****************************************************************************
871 * Call a NetFileEnum2 - list open files on an SMB server
873 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
874 * server listing the files open via the network (and their
875 * corresponding open instance ids)
877 * Dependencies: none
879 * Parameters:
880 * cli - pointer to cli_state structure
881 * user - if present, return only files opened by this remote user
882 * base_path - if present, return only files opened below this
883 * base path
884 * fn - display function to invoke for each entry in the result
887 * Returns:
888 * True - success
889 * False - failure
891 ****************************************************************************/
892 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
894 char *rparam = NULL;
895 char *rdata = NULL;
896 char *p;
897 int rdrcnt,rprcnt;
898 char param[WORDSIZE /* api number */
899 +sizeof(RAP_WFileEnum2_REQ) /* req string */
900 +sizeof(RAP_FILE_INFO_L3) /* return string */
901 +256 /* base path (opt) */
902 +RAP_USERNAME_LEN /* user name (opt) */
903 +WORDSIZE /* info level */
904 +WORDSIZE /* buffer size */
905 +DWORDSIZE /* resume key ? */
906 +DWORDSIZE]; /* resume key ? */
907 int count = -1;
909 /* now send a SMBtrans command with api RNetShareEnum */
910 p = make_header(param, RAP_WFileEnum2,
911 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
913 PUTSTRING(p, base_path, 256);
914 PUTSTRING(p, user, RAP_USERNAME_LEN);
915 PUTWORD(p, 3); /* info level */
916 PUTWORD(p, 0xFF00); /* buffer size */
917 PUTDWORD(p, 0); /* zero out the resume key */
918 PUTDWORD(p, 0); /* or is this one the resume key? */
920 if (cli_api(cli,
921 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
922 NULL, 0, 0xFF00, /* data, length, maxlen */
923 &rparam, &rprcnt, /* return params, length */
924 &rdata, &rdrcnt)) /* return data, length */
926 int res = GETRES(rparam);
928 if (res == 0 || res == ERRmoredata) {
929 int converter, i;
931 p = rparam + WORDSIZE; /* skip result */
932 GETWORD(p, converter);
933 GETWORD(p, count);
935 p = rdata;
936 for (i=0; i<count; i++) {
937 int id, perms, locks;
938 pstring fpath, fuser;
940 GETDWORD(p, id);
941 GETWORD(p, perms);
942 GETWORD(p, locks);
943 GETSTRINGP(p, fpath, rdata, converter);
944 GETSTRINGP(p, fuser, rdata, converter);
946 fn(fpath, fuser, perms, locks, id);
947 } /* BB fix ERRmoredata case to send resume request */
948 } else {
949 DEBUG(4,("NetFileEnum2 res=%d\n", res));
951 } else {
952 DEBUG(4,("NetFileEnum2 failed\n"));
955 SAFE_FREE(rparam);
956 SAFE_FREE(rdata);
958 return count;
961 /****************************************************************************
962 call a NetShareAdd - share/export directory on remote server
963 ****************************************************************************/
964 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
966 char *rparam = NULL;
967 char *rdata = NULL;
968 char *p;
969 int rdrcnt,rprcnt,res;
970 char param[WORDSIZE /* api number */
971 +sizeof(RAP_WShareAdd_REQ) /* req string */
972 +sizeof(RAP_SHARE_INFO_L2) /* return string */
973 +WORDSIZE /* info level */
974 +WORDSIZE]; /* reserved word */
975 char data[1024];
976 /* offset to free format string section following fixed length data. */
977 /* will be updated by PUTSTRINGP macro and will end up with total len */
978 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
979 + WORDSIZE /* share type */
980 + DWORDSIZE /* comment pointer */
981 + WORDSIZE /* permissions */
982 + WORDSIZE /* max users */
983 + WORDSIZE /* active users */
984 + DWORDSIZE /* share path */
985 + RAP_SPASSWD_LEN + 1; /* share password + pad */
987 memset(param,'\0',sizeof(param));
988 /* now send a SMBtrans command with api RNetShareAdd */
989 p = make_header(param, RAP_WshareAdd,
990 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
991 PUTWORD(p, 2); /* info level */
992 PUTWORD(p, 0); /* reserved word 0 */
994 p = data;
995 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
996 PUTBYTE(p, 0); /* pad byte 0 */
998 PUTWORD(p, sinfo->share_type);
999 PUTSTRINGP(p, sinfo->comment, data, soffset);
1000 PUTWORD(p, sinfo->perms);
1001 PUTWORD(p, sinfo->maximum_users);
1002 PUTWORD(p, sinfo->active_users);
1003 PUTSTRINGP(p, sinfo->path, data, soffset);
1004 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1005 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1007 if (cli_api(cli,
1008 param, sizeof(param), 1024, /* Param, length, maxlen */
1009 data, soffset, sizeof(data), /* data, length, maxlen */
1010 &rparam, &rprcnt, /* return params, length */
1011 &rdata, &rdrcnt)) /* return data, length */
1013 res = rparam? SVAL(rparam,0) : -1;
1015 if (res == 0) {
1016 /* nothing to do */
1018 else {
1019 DEBUG(4,("NetShareAdd res=%d\n", res));
1021 } else {
1022 res = -1;
1023 DEBUG(4,("NetShareAdd failed\n"));
1026 SAFE_FREE(rparam);
1027 SAFE_FREE(rdata);
1029 return res;
1031 /****************************************************************************
1032 call a NetShareDelete - unshare exported directory on remote server
1033 ****************************************************************************/
1034 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1036 char *rparam = NULL;
1037 char *rdata = NULL;
1038 char *p;
1039 int rdrcnt,rprcnt, res;
1040 char param[WORDSIZE /* api number */
1041 +sizeof(RAP_WShareDel_REQ) /* req string */
1042 +1 /* no ret string */
1043 +RAP_SHARENAME_LEN /* share to del */
1044 +WORDSIZE]; /* reserved word */
1047 /* now send a SMBtrans command with api RNetShareDelete */
1048 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1049 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1050 PUTWORD(p,0); /* reserved word MBZ on input */
1052 if (cli_api(cli,
1053 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1054 NULL, 0, 200, /* data, length, maxlen */
1055 &rparam, &rprcnt, /* return params, length */
1056 &rdata, &rdrcnt)) /* return data, length */
1058 res = GETRES(rparam);
1060 if (res == 0) {
1061 /* nothing to do */
1063 else {
1064 DEBUG(4,("NetShareDelete res=%d\n", res));
1066 } else {
1067 res = -1;
1068 DEBUG(4,("NetShareDelete failed\n"));
1071 SAFE_FREE(rparam);
1072 SAFE_FREE(rdata);
1074 return res;
1076 /*************************************************************************
1078 * Function Name: cli_get_pdc_name
1080 * PURPOSE: Remotes a NetServerEnum API call to the current server
1081 * requesting the name of a server matching the server
1082 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1084 * Dependencies: none
1086 * Parameters:
1087 * cli - pointer to cli_state structure
1088 * workgroup - pointer to string containing name of domain
1089 * pdc_name - pointer to string that will contain PDC name
1090 * on successful return
1092 * Returns:
1093 * True - success
1094 * False - failure
1096 ************************************************************************/
1097 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1099 char *rparam = NULL;
1100 char *rdata = NULL;
1101 int rdrcnt,rprcnt;
1102 char *p;
1103 char param[WORDSIZE /* api number */
1104 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1105 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1106 +WORDSIZE /* info level */
1107 +WORDSIZE /* buffer size */
1108 +DWORDSIZE /* server type */
1109 +RAP_MACHNAME_LEN]; /* workgroup */
1110 int count = -1;
1112 *pdc_name = '\0';
1114 /* send a SMBtrans command with api NetServerEnum */
1115 p = make_header(param, RAP_NetServerEnum2,
1116 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1117 PUTWORD(p, 1); /* info level */
1118 PUTWORD(p, CLI_BUFFER_SIZE);
1119 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1120 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1122 if (cli_api(cli,
1123 param, PTR_DIFF(p,param), 8, /* params, length, max */
1124 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1125 &rparam, &rprcnt, /* return params, return size */
1126 &rdata, &rdrcnt /* return data, return size */
1127 )) {
1128 cli->rap_error = GETRES(rparam);
1131 * We only really care to copy a name if the
1132 * API succeeded and we got back a name.
1134 if (cli->rap_error == 0) {
1135 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1136 GETWORD(p, count);
1137 p = rdata;
1139 if (count > 0)
1140 GETSTRING(p, pdc_name);
1142 else {
1143 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1144 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1148 SAFE_FREE(rparam);
1149 SAFE_FREE(rdata);
1151 return(count > 0);
1155 /*************************************************************************
1157 * Function Name: cli_get_server_domain
1159 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1160 * requesting wksta_info_10 level information to determine
1161 * the domain the server belongs to. On success, this
1162 * routine sets the server_domain field in the cli_state structure
1163 * to the server's domain name.
1165 * Dependencies: none
1167 * Parameters:
1168 * cli - pointer to cli_state structure
1170 * Returns:
1171 * True - success
1172 * False - failure
1174 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1176 ************************************************************************/
1177 BOOL cli_get_server_domain(struct cli_state *cli)
1179 char *rparam = NULL;
1180 char *rdata = NULL;
1181 int rdrcnt,rprcnt;
1182 char *p;
1183 char param[WORDSIZE /* api number */
1184 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1185 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1186 +WORDSIZE /* info level */
1187 +WORDSIZE]; /* buffer size */
1188 int res = -1;
1190 /* send a SMBtrans command with api NetWkstaGetInfo */
1191 p = make_header(param, RAP_WWkstaGetInfo,
1192 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1193 PUTWORD(p, 10); /* info level */
1194 PUTWORD(p, CLI_BUFFER_SIZE);
1196 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1197 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1198 &rparam, &rprcnt, /* return params, return size */
1199 &rdata, &rdrcnt)) { /* return data, return size */
1200 res = GETRES(rparam);
1201 p = rdata;
1203 if (res == 0) {
1204 int converter;
1206 p = rparam + WORDSIZE;
1207 GETWORD(p, converter);
1209 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1210 GETSTRINGP(p, cli->server_domain, rdata, converter);
1214 SAFE_FREE(rparam);
1215 SAFE_FREE(rdata);
1217 return(res == 0);
1221 /*************************************************************************
1223 * Function Name: cli_get_server_type
1225 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1226 * requesting server_info_1 level information to retrieve
1227 * the server type.
1229 * Dependencies: none
1231 * Parameters:
1232 * cli - pointer to cli_state structure
1233 * pstype - pointer to uint32 to contain returned server type
1235 * Returns:
1236 * True - success
1237 * False - failure
1239 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1241 ************************************************************************/
1242 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1244 char *rparam = NULL;
1245 char *rdata = NULL;
1246 int rdrcnt,rprcnt;
1247 char *p;
1248 char param[WORDSIZE /* api number */
1249 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1250 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1251 +WORDSIZE /* info level */
1252 +WORDSIZE]; /* buffer size */
1253 int res = -1;
1255 /* send a SMBtrans command with api NetServerGetInfo */
1256 p = make_header(param, RAP_WserverGetInfo,
1257 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1258 PUTWORD(p, 1); /* info level */
1259 PUTWORD(p, CLI_BUFFER_SIZE);
1261 if (cli_api(cli,
1262 param, PTR_DIFF(p,param), 8, /* params, length, max */
1263 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1264 &rparam, &rprcnt, /* return params, return size */
1265 &rdata, &rdrcnt /* return data, return size */
1266 )) {
1268 res = GETRES(rparam);
1270 if (res == 0 || res == ERRmoredata) {
1271 p = rdata;
1272 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1276 SAFE_FREE(rparam);
1277 SAFE_FREE(rdata);
1279 return(res == 0 || res == ERRmoredata);
1283 /*************************************************************************
1285 * Function Name: cli_ns_check_server_type
1287 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1288 * requesting server_info_0 level information of machines
1289 * matching the given server type. If the returned server
1290 * list contains the machine name contained in cli->desthost
1291 * then we conclude the server type checks out. This routine
1292 * is useful to retrieve list of server's of a certain
1293 * type when all you have is a null session connection and
1294 * can't remote API calls such as NetWkstaGetInfo or
1295 * NetServerGetInfo.
1297 * Dependencies: none
1299 * Parameters:
1300 * cli - pointer to cli_state structure
1301 * workgroup - pointer to string containing domain
1302 * stype - server type
1304 * Returns:
1305 * True - success
1306 * False - failure
1308 ************************************************************************/
1309 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1311 char *rparam = NULL;
1312 char *rdata = NULL;
1313 int rdrcnt,rprcnt;
1314 char *p;
1315 char param[WORDSIZE /* api number */
1316 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1317 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1318 +WORDSIZE /* info level */
1319 +WORDSIZE /* buffer size */
1320 +DWORDSIZE /* server type */
1321 +RAP_MACHNAME_LEN]; /* workgroup */
1322 BOOL found_server = False;
1323 int res = -1;
1325 /* send a SMBtrans command with api NetServerEnum */
1326 p = make_header(param, RAP_NetServerEnum2,
1327 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1328 PUTWORD(p, 0); /* info level 0 */
1329 PUTWORD(p, CLI_BUFFER_SIZE);
1330 PUTDWORD(p, stype);
1331 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1333 if (cli_api(cli,
1334 param, PTR_DIFF(p,param), 8, /* params, length, max */
1335 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1336 &rparam, &rprcnt, /* return params, return size */
1337 &rdata, &rdrcnt /* return data, return size */
1338 )) {
1340 res = GETRES(rparam);
1341 cli->rap_error = res;
1343 if (res == 0 || res == ERRmoredata) {
1344 int i, converter, count;
1346 p = rparam + WORDSIZE;
1347 GETWORD(p, converter);
1348 GETWORD(p, count);
1350 p = rdata;
1351 for (i = 0;i < count;i++, p += 16) {
1352 char ret_server[RAP_MACHNAME_LEN];
1354 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1355 if (strequal(ret_server, cli->desthost)) {
1356 found_server = True;
1357 break;
1361 else {
1362 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1363 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1367 SAFE_FREE(rparam);
1368 SAFE_FREE(rdata);
1370 return found_server;
1374 /****************************************************************************
1375 perform a NetWkstaUserLogoff
1376 ****************************************************************************/
1377 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1379 char *rparam = NULL;
1380 char *rdata = NULL;
1381 char *p;
1382 int rdrcnt,rprcnt;
1383 char param[WORDSIZE /* api number */
1384 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1385 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1386 +RAP_USERNAME_LEN+1 /* user name+pad */
1387 +RAP_MACHNAME_LEN /* wksta name */
1388 +WORDSIZE /* buffer size */
1389 +WORDSIZE]; /* buffer size? */
1390 fstring upperbuf;
1392 memset(param, 0, sizeof(param));
1394 /* send a SMBtrans command with api NetWkstaUserLogoff */
1395 p = make_header(param, RAP_WWkstaUserLogoff,
1396 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1397 PUTDWORD(p, 0); /* Null pointer */
1398 PUTDWORD(p, 0); /* Null pointer */
1399 fstrcpy(upperbuf, user);
1400 strupper(upperbuf);
1401 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1402 p++; /* strange format, but ok */
1403 fstrcpy(upperbuf, workstation);
1404 strupper(upperbuf);
1405 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1406 PUTWORD(p, CLI_BUFFER_SIZE);
1407 PUTWORD(p, CLI_BUFFER_SIZE);
1409 if (cli_api(cli,
1410 param, PTR_DIFF(p,param),1024, /* param, length, max */
1411 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1412 &rparam, &rprcnt, /* return params, return size */
1413 &rdata, &rdrcnt /* return data, return size */
1414 )) {
1415 cli->rap_error = GETRES(rparam);
1417 if (cli->rap_error != 0) {
1418 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1422 SAFE_FREE(rparam);
1423 SAFE_FREE(rdata);
1424 return (cli->rap_error == 0);
1427 int cli_NetPrintQEnum(struct cli_state *cli,
1428 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1429 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1431 char param[WORDSIZE /* api number */
1432 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1433 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1434 +WORDSIZE /* info level */
1435 +WORDSIZE /* buffer size */
1436 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1437 char *p;
1438 char *rparam = NULL;
1439 char *rdata = NULL;
1440 int rprcnt, rdrcnt;
1441 int res = -1;
1444 memset(param, '\0',sizeof(param));
1445 p = make_header(param, RAP_WPrintQEnum,
1446 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1447 PUTWORD(p,2); /* Info level 2 */
1448 PUTWORD(p,0xFFE0); /* Return buffer size */
1449 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1451 if (cli_api(cli,
1452 param, PTR_DIFF(p,param),1024,
1453 NULL, 0, CLI_BUFFER_SIZE,
1454 &rparam, &rprcnt,
1455 &rdata, &rdrcnt)) {
1456 res = GETRES(rparam);
1457 cli->rap_error = res;
1458 if (res != 0) {
1459 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1463 if (rdata) {
1464 if (res == 0 || res == ERRmoredata) {
1465 int i, converter, count;
1467 p = rparam + WORDSIZE;
1468 GETWORD(p, converter);
1469 GETWORD(p, count);
1471 p = rdata;
1472 for (i=0;i<count;i++) {
1473 pstring qname, sep_file, print_proc, dest, parms, comment;
1474 uint16 jobcount, priority, start_time, until_time, status;
1476 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1477 p++; /* pad */
1478 GETWORD(p, priority);
1479 GETWORD(p, start_time);
1480 GETWORD(p, until_time);
1481 GETSTRINGP(p, sep_file, rdata, converter);
1482 GETSTRINGP(p, print_proc, rdata, converter);
1483 GETSTRINGP(p, dest, rdata, converter);
1484 GETSTRINGP(p, parms, rdata, converter);
1485 GETSTRINGP(p, parms, comment, converter);
1486 GETWORD(p, status);
1487 GETWORD(p, jobcount);
1489 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1490 dest, parms, comment, status, jobcount);
1492 if (jobcount) {
1493 int j;
1494 for (j=0;j<jobcount;j++) {
1495 uint16 jid, pos, fsstatus;
1496 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1497 uint submitted, jsize;
1499 GETWORD(p, jid);
1500 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1501 p++; /* pad byte */
1502 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1503 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1504 GETSTRINGP(p, jparms, rdata, converter);
1505 GETWORD(p, pos);
1506 GETWORD(p, fsstatus);
1507 GETSTRINGP(p, jstatus, rdata, converter);
1508 GETDWORD(p, submitted);
1509 GETDWORD(p, jsize);
1510 GETSTRINGP(p, jcomment, rdata, converter);
1512 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1513 jstatus, submitted, jsize, jcomment);
1517 } else {
1518 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1520 } else {
1521 DEBUG(4,("NetPrintQEnum no data returned\n"));
1524 SAFE_FREE(rparam);
1525 SAFE_FREE(rdata);
1527 return res;
1530 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1531 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1532 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1534 char param[WORDSIZE /* api number */
1535 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1536 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1537 +RAP_SHARENAME_LEN /* printer name */
1538 +WORDSIZE /* info level */
1539 +WORDSIZE /* buffer size */
1540 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1541 char *p;
1542 char *rparam = NULL;
1543 char *rdata = NULL;
1544 int rprcnt, rdrcnt;
1545 int res = -1;
1548 memset(param, '\0',sizeof(param));
1549 p = make_header(param, RAP_WPrintQGetInfo,
1550 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1551 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1552 PUTWORD(p, 2); /* Info level 2 */
1553 PUTWORD(p,0xFFE0); /* Return buffer size */
1554 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1556 if (cli_api(cli,
1557 param, PTR_DIFF(p,param),1024,
1558 NULL, 0, CLI_BUFFER_SIZE,
1559 &rparam, &rprcnt,
1560 &rdata, &rdrcnt)) {
1561 res = GETRES(rparam);
1562 cli->rap_error = res;
1563 if (res != 0) {
1564 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1568 if (rdata) {
1569 if (res == 0 || res == ERRmoredata) {
1570 int rsize, converter;
1571 pstring qname, sep_file, print_proc, dest, parms, comment;
1572 uint16 jobcount, priority, start_time, until_time, status;
1574 p = rparam + WORDSIZE;
1575 GETWORD(p, converter);
1576 GETWORD(p, rsize);
1578 p = rdata;
1579 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1580 p++; /* pad */
1581 GETWORD(p, priority);
1582 GETWORD(p, start_time);
1583 GETWORD(p, until_time);
1584 GETSTRINGP(p, sep_file, rdata, converter);
1585 GETSTRINGP(p, print_proc, rdata, converter);
1586 GETSTRINGP(p, dest, rdata, converter);
1587 GETSTRINGP(p, parms, rdata, converter);
1588 GETSTRINGP(p, comment, rdata, converter);
1589 GETWORD(p, status);
1590 GETWORD(p, jobcount);
1591 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1592 dest, parms, comment, status, jobcount);
1593 if (jobcount) {
1594 int j;
1595 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1596 uint16 jid, pos, fsstatus;
1597 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1598 uint submitted, jsize;
1600 GETWORD(p, jid);
1601 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1602 p++; /* pad byte */
1603 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1604 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1605 GETSTRINGP(p, jparms, rdata, converter);
1606 GETWORD(p, pos);
1607 GETWORD(p, fsstatus);
1608 GETSTRINGP(p, jstatus, rdata, converter);
1609 GETDWORD(p, submitted);
1610 GETDWORD(p, jsize);
1611 GETSTRINGP(p, jcomment, rdata, converter);
1613 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1614 jstatus, submitted, jsize, jcomment);
1617 } else {
1618 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1620 } else {
1621 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1624 SAFE_FREE(rparam);
1625 SAFE_FREE(rdata);
1627 return res;
1630 /****************************************************************************
1631 call a NetServiceEnum - list running services on a different host
1632 ****************************************************************************/
1633 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1635 char param[WORDSIZE /* api number */
1636 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1637 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1638 +WORDSIZE /* info level */
1639 +WORDSIZE]; /* buffer size */
1640 char *p;
1641 char *rparam = NULL;
1642 char *rdata = NULL;
1643 int rprcnt, rdrcnt;
1644 int res = -1;
1647 memset(param, '\0', sizeof(param));
1648 p = make_header(param, RAP_WServiceEnum,
1649 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1650 PUTWORD(p,2); /* Info level 2 */
1651 PUTWORD(p,0xFFE0); /* Return buffer size */
1653 if (cli_api(cli,
1654 param, PTR_DIFF(p,param),8,
1655 NULL, 0, 0xFFE0 /* data area size */,
1656 &rparam, &rprcnt,
1657 &rdata, &rdrcnt)) {
1658 res = GETRES(rparam);
1659 cli->rap_error = res;
1660 if(cli->rap_error == 234)
1661 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1662 else if (cli->rap_error != 0) {
1663 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1667 if (rdata) {
1668 if (res == 0 || res == ERRmoredata) {
1669 int i, converter, count;
1671 p = rparam + WORDSIZE; /* skip result */
1672 GETWORD(p, converter);
1673 GETWORD(p, count);
1675 for (i=0,p=rdata;i<count;i++) {
1676 pstring comment;
1677 char servicename[RAP_SRVCNAME_LEN];
1679 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1680 p+=8; /* pass status words */
1681 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1683 fn(servicename, comment, cli); /* BB add status too */
1685 } else {
1686 DEBUG(4,("NetServiceEnum res=%d\n", res));
1688 } else {
1689 DEBUG(4,("NetServiceEnum no data returned\n"));
1692 SAFE_FREE(rparam);
1693 SAFE_FREE(rdata);
1695 return res;
1699 /****************************************************************************
1700 call a NetSessionEnum - list workstations with sessions to an SMB server
1701 ****************************************************************************/
1702 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1704 char param[WORDSIZE /* api number */
1705 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1706 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1707 +WORDSIZE /* info level */
1708 +WORDSIZE]; /* buffer size */
1709 char *p;
1710 char *rparam = NULL;
1711 char *rdata = NULL;
1712 int rprcnt, rdrcnt;
1713 int res = -1;
1715 memset(param, '\0', sizeof(param));
1716 p = make_header(param, RAP_WsessionEnum,
1717 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1718 PUTWORD(p,2); /* Info level 2 */
1719 PUTWORD(p,0xFF); /* Return buffer size */
1721 if (cli_api(cli,
1722 param, PTR_DIFF(p,param),8,
1723 NULL, 0, CLI_BUFFER_SIZE,
1724 &rparam, &rprcnt,
1725 &rdata, &rdrcnt)) {
1726 res = GETRES(rparam);
1727 cli->rap_error = res;
1728 if (res != 0) {
1729 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1733 if (rdata) {
1734 if (res == 0 || res == ERRmoredata) {
1735 int i, converter, count;
1737 p = rparam + WORDSIZE;
1738 GETWORD(p, converter);
1739 GETWORD(p, count);
1741 for (i=0,p=rdata;i<count;i++) {
1742 pstring wsname, username, clitype_name;
1743 uint16 num_conns, num_opens, num_users;
1744 uint sess_time, idle_time, user_flags;
1746 GETSTRINGP(p, wsname, rdata, converter);
1747 GETSTRINGP(p, username, rdata, converter);
1748 GETWORD(p, num_conns);
1749 GETWORD(p, num_opens);
1750 GETWORD(p, num_users);
1751 GETDWORD(p, sess_time);
1752 GETDWORD(p, idle_time);
1753 GETDWORD(p, user_flags);
1754 GETSTRINGP(p, clitype_name, rdata, converter);
1756 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1757 idle_time, user_flags, clitype_name);
1760 } else {
1761 DEBUG(4,("NetSessionEnum res=%d\n", res));
1763 } else {
1764 DEBUG(4,("NetSesssionEnum no data returned\n"));
1767 SAFE_FREE(rparam);
1768 SAFE_FREE(rdata);
1770 return res;
1773 /****************************************************************************
1774 Call a NetSessionGetInfo - get information about other session to an SMB server.
1775 ****************************************************************************/
1777 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1779 char param[WORDSIZE /* api number */
1780 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1781 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1782 +RAP_MACHNAME_LEN /* wksta name */
1783 +WORDSIZE /* info level */
1784 +WORDSIZE]; /* buffer size */
1785 char *p;
1786 char *rparam = NULL;
1787 char *rdata = NULL;
1788 int rprcnt, rdrcnt;
1789 int res = -1;
1792 memset(param, '\0', sizeof(param));
1793 p = make_header(param, RAP_WsessionGetInfo,
1794 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1795 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1796 PUTWORD(p,2); /* Info level 2 */
1797 PUTWORD(p,0xFF); /* Return buffer size */
1799 if (cli_api(cli,
1800 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1801 NULL, 0, CLI_BUFFER_SIZE,
1802 &rparam, &rprcnt,
1803 &rdata, &rdrcnt)) {
1804 cli->rap_error = SVAL(rparam,0);
1805 if (cli->rap_error != 0) {
1806 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1810 if (rdata) {
1811 res = GETRES(rparam);
1813 if (res == 0 || res == ERRmoredata) {
1814 int rsize, converter;
1815 pstring wsname, username, clitype_name;
1816 uint16 num_conns, num_opens, num_users;
1817 uint sess_time, idle_time, user_flags;
1819 p = rparam + WORDSIZE;
1820 GETWORD(p, converter);
1821 GETWORD(p, rsize);
1823 p = rdata;
1824 GETSTRINGP(p, wsname, rdata, converter);
1825 GETSTRINGP(p, username, rdata, converter);
1826 GETWORD(p, num_conns);
1827 GETWORD(p, num_opens);
1828 GETWORD(p, num_users);
1829 GETDWORD(p, sess_time);
1830 GETDWORD(p, idle_time);
1831 GETDWORD(p, user_flags);
1832 GETSTRINGP(p, clitype_name, rdata, converter);
1834 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1835 idle_time, user_flags, clitype_name);
1836 } else {
1837 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1839 } else {
1840 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1843 SAFE_FREE(rparam);
1844 SAFE_FREE(rdata);
1846 return res;
1849 /****************************************************************************
1850 call a NetSessionDel - close a session to an SMB server
1851 ****************************************************************************/
1852 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1854 char param[WORDSIZE /* api number */
1855 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1856 +1 /* no return string */
1857 +RAP_MACHNAME_LEN /* workstation name */
1858 +WORDSIZE]; /* reserved (0) */
1859 char *p;
1860 char *rparam = NULL;
1861 char *rdata = NULL;
1862 int rprcnt, rdrcnt;
1863 int res;
1865 memset(param, '\0', sizeof(param));
1866 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1867 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1868 PUTWORD(p,0); /* reserved word of 0 */
1869 if (cli_api(cli,
1870 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1871 NULL, 0, 200, /* data, length, maxlen */
1872 &rparam, &rprcnt, /* return params, length */
1873 &rdata, &rdrcnt)) /* return data, length */
1875 res = GETRES(rparam);
1876 cli->rap_error = res;
1878 if (res == 0) {
1879 /* nothing to do */
1881 else {
1882 DEBUG(4,("NetFileClose2 res=%d\n", res));
1884 } else {
1885 res = -1;
1886 DEBUG(4,("NetFileClose2 failed\n"));
1889 SAFE_FREE(rparam);
1890 SAFE_FREE(rdata);
1892 return res;
1896 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))
1898 char param[WORDSIZE /* api number */
1899 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
1900 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
1901 +RAP_MACHNAME_LEN /* wksta name */
1902 +WORDSIZE /* info level */
1903 +WORDSIZE]; /* buffer size */
1904 char *p;
1905 char *rparam = NULL;
1906 char *rdata = NULL;
1907 int rprcnt, rdrcnt;
1908 int res = -1;
1910 memset(param, '\0', sizeof(param));
1911 p = make_header(param, RAP_WconnectionEnum,
1912 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
1913 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
1914 PUTWORD(p,1); /* Info level 1 */
1915 PUTWORD(p,0xFFE0); /* Return buffer size */
1917 if (cli_api(cli,
1918 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1919 NULL, 0, CLI_BUFFER_SIZE,
1920 &rparam, &rprcnt,
1921 &rdata, &rdrcnt)) {
1922 res = GETRES(rparam);
1923 cli->rap_error = res;
1924 if (res != 0) {
1925 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
1928 if (rdata) {
1929 if (res == 0 || res == ERRmoredata) {
1930 int i, converter, count;
1932 p = rparam + WORDSIZE;
1933 GETWORD(p, converter);
1934 GETWORD(p, count);
1936 for (i=0,p=rdata;i<count;i++) {
1937 pstring netname, username;
1938 uint16 conn_id, conn_type, num_opens, num_users;
1939 uint conn_time;
1941 GETWORD(p,conn_id);
1942 GETWORD(p,conn_type);
1943 GETWORD(p,num_opens);
1944 GETWORD(p,num_users);
1945 GETDWORD(p,conn_time);
1946 GETSTRINGP(p, username, rdata, converter);
1947 GETSTRINGP(p, netname, rdata, converter);
1949 fn(conn_id, conn_type, num_opens, num_users, conn_time,
1950 username, netname);
1953 } else {
1954 DEBUG(4,("NetConnectionEnum res=%d\n", res));
1956 } else {
1957 DEBUG(4,("NetConnectionEnum no data returned\n"));
1959 SAFE_FREE(rdata);
1960 SAFE_FREE(rparam);
1961 return res;