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 /*****************************************************/
25 /* Additional RAP functionality */
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 */
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. */
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. */
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 */
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 */
61 /*****************************************************/
63 /*****************************************************/
65 /* cifsrap.c already includes support for: */
67 /* WshareEnum ( API number 0, level 1) */
68 /* NetServerEnum2 (API num 104, level 1) */
69 /* WWkstaUserLogon (132) */
70 /* SamOEMchgPasswordUser2_P (214) */
72 /* cifsprint.c already includes support for: */
74 /* WPrintJobEnum (API num 76, level 2) */
75 /* WPrintJobDel (API num 81) */
77 /*****************************************************/
84 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
85 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
86 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
87 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
88 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
89 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
90 #define GETRES(p) p ? SVAL(p,0) : -1
91 /* put string s at p with max len n and increment p past string */
92 #define PUTSTRING(p,s,n) do {\
93 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
94 p = skip_string(p,1);\
96 /* put string s and p, using fixed len l, and increment p by l */
97 #define PUTSTRINGF(p,s,l) do {\
98 push_ascii(p,s?s:"",l,STR_TERMINATE);\
101 /* put string pointer at p, supplying offset o from rdata r, store */
102 /* dword offset at p, increment p by 4 and o by length of s. This */
103 /* means on the first call, you must calc the offset yourself! */
104 #define PUTSTRINGP(p,s,r,o) do {\
106 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
109 } else PUTDWORD(p,0);\
111 /* get asciiz string s from p, increment p past string */
112 #define GETSTRING(p,s) do {\
113 pull_ascii_pstring(s,p);\
114 p = skip_string(p,1);\
116 /* get fixed length l string s from p, increment p by l */
117 #define GETSTRINGF(p,s,l) do {\
118 pull_ascii_pstring(s,p);\
121 /* get string s from offset (obtained at p) from rdata r - converter c */
122 #define GETSTRINGP(p,s,r,c) do {\
125 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
126 pull_ascii_pstring(s, off?(r+off-c):"");\
129 static char *make_header(char *param
, uint16 apinum
, const char *reqfmt
, const char *datafmt
)
131 PUTWORD(param
,apinum
);
133 PUTSTRING(param
,reqfmt
,0);
138 PUTSTRING(param
,datafmt
,0);
146 /****************************************************************************
147 call a NetGroupDelete - delete user group from remote server
148 ****************************************************************************/
149 int cli_NetGroupDelete(struct cli_state
*cli
, const char *group_name
)
154 unsigned int rdrcnt
,rprcnt
;
156 char param
[WORDSIZE
/* api number */
157 +sizeof(RAP_NetGroupDel_REQ
) /* parm string */
158 +1 /* no ret string */
159 +RAP_GROUPNAME_LEN
/* group to del */
160 +WORDSIZE
]; /* reserved word */
162 /* now send a SMBtrans command with api GroupDel */
163 p
= make_header(param
, RAP_WGroupDel
, RAP_NetGroupDel_REQ
, NULL
);
164 PUTSTRING(p
, group_name
, RAP_GROUPNAME_LEN
);
165 PUTWORD(p
,0); /* reserved word MBZ on input */
168 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
169 NULL
, 0, 200, /* data, length, maxlen */
170 &rparam
, &rprcnt
, /* return params, length */
171 &rdata
, &rdrcnt
)) /* return data, length */
173 res
= GETRES(rparam
);
178 else if ((res
== 5) || (res
== 65)) {
179 DEBUG(1, ("Access Denied\n"));
181 else if (res
== 2220) {
182 DEBUG (1, ("Group does not exist\n"));
185 DEBUG(4,("NetGroupDelete res=%d\n", res
));
189 DEBUG(4,("NetGroupDelete failed\n"));
198 /****************************************************************************
199 call a NetGroupAdd - add user group to remote server
200 ****************************************************************************/
201 int cli_NetGroupAdd(struct cli_state
*cli
, RAP_GROUP_INFO_1
* grinfo
)
206 unsigned int rdrcnt
,rprcnt
;
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 */
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 */
228 PUTSTRINGF(p
, grinfo
->group_name
, RAP_GROUPNAME_LEN
);
229 PUTBYTE(p
, 0); /* pad byte 0 */
230 PUTSTRINGP(p
, grinfo
->comment
, data
, soffset
);
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
);
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"));
249 DEBUG(4,("NetGroupAdd res=%d\n", res
));
253 DEBUG(4,("NetGroupAdd failed\n"));
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 */
275 unsigned int rprcnt
, rdrcnt
;
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 */
286 param
, PTR_DIFF(p
,param
),8,
287 NULL
, 0, 0xFFE0 /* data area size */,
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
));
300 if (res
== 0 || res
== ERRmoredata
) {
301 int i
, converter
, count
;
303 p
= rparam
+ WORDSIZE
; /* skip result */
304 GETWORD(p
, converter
);
307 for (i
=0,p
=rdata
;i
<count
;i
++) {
309 char groupname
[RAP_GROUPNAME_LEN
];
311 GETSTRINGF(p
, groupname
, RAP_GROUPNAME_LEN
);
313 GETSTRINGP(p
, comment
, rdata
, converter
);
315 fn(groupname
, comment
, cli
);
318 DEBUG(4,("NetGroupEnum res=%d\n", res
));
321 DEBUG(4,("NetGroupEnum no data returned\n"));
330 int cli_RNetGroupEnum0(struct cli_state
*cli
,
331 void (*fn
)(const char *, void *),
334 char param
[WORDSIZE
/* api number */
335 +sizeof(RAP_NetGroupEnum_REQ
) /* parm string */
336 +sizeof(RAP_GROUP_INFO_L0
) /* return string */
337 +WORDSIZE
/* info level */
338 +WORDSIZE
]; /* buffer size */
342 unsigned int rprcnt
, rdrcnt
;
346 memset(param
, '\0', sizeof(param
));
347 p
= make_header(param
, RAP_WGroupEnum
,
348 RAP_NetGroupEnum_REQ
, RAP_GROUP_INFO_L0
);
349 PUTWORD(p
,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
350 is the resume count, at least
351 that's what smbd believes... */
352 PUTWORD(p
,0xFFE0); /* Return buffer size */
355 param
, PTR_DIFF(p
,param
),8,
356 NULL
, 0, 0xFFE0 /* data area size */,
359 res
= GETRES(rparam
);
360 cli
->rap_error
= res
;
361 if(cli
->rap_error
== 234)
362 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
363 else if (cli
->rap_error
!= 0) {
364 DEBUG(1,("NetGroupEnum gave error %d\n", cli
->rap_error
));
369 if (res
== 0 || res
== ERRmoredata
) {
372 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
375 for (i
=0,p
=rdata
;i
<count
;i
++) {
376 char groupname
[RAP_GROUPNAME_LEN
];
377 GETSTRINGF(p
, groupname
, RAP_GROUPNAME_LEN
);
381 DEBUG(4,("NetGroupEnum res=%d\n", res
));
384 DEBUG(4,("NetGroupEnum no data returned\n"));
393 int cli_NetGroupDelUser(struct cli_state
* cli
, const char *group_name
, const char *user_name
)
398 unsigned int rdrcnt
,rprcnt
;
400 char param
[WORDSIZE
/* api number */
401 +sizeof(RAP_NetGroupDelUser_REQ
) /* parm string */
402 +1 /* no ret string */
403 +RAP_GROUPNAME_LEN
/* group name */
404 +RAP_USERNAME_LEN
]; /* user to del */
406 /* now send a SMBtrans command with api GroupMemberAdd */
407 p
= make_header(param
, RAP_WGroupDelUser
, RAP_NetGroupDelUser_REQ
, NULL
);
408 PUTSTRING(p
,group_name
,RAP_GROUPNAME_LEN
);
409 PUTSTRING(p
,user_name
,RAP_USERNAME_LEN
);
412 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
413 NULL
, 0, 200, /* data, length, maxlen */
414 &rparam
, &rprcnt
, /* return params, length */
415 &rdata
, &rdrcnt
)) /* return data, length */
417 res
= GETRES(rparam
);
424 DEBUG(1, ("Access Denied\n"));
427 DEBUG(1, ("Not supported by server\n"));
430 DEBUG(1, ("Group does not exist\n"));
433 DEBUG(1, ("User does not exist\n"));
436 DEBUG(1, ("User is not in group\n"));
439 DEBUG(4,("NetGroupDelUser res=%d\n", res
));
443 DEBUG(4,("NetGroupDelUser failed\n"));
452 int cli_NetGroupAddUser(struct cli_state
* cli
, const char *group_name
, const char *user_name
)
457 unsigned int rdrcnt
,rprcnt
;
459 char param
[WORDSIZE
/* api number */
460 +sizeof(RAP_NetGroupAddUser_REQ
) /* parm string */
461 +1 /* no ret string */
462 +RAP_GROUPNAME_LEN
/* group name */
463 +RAP_USERNAME_LEN
]; /* user to add */
465 /* now send a SMBtrans command with api GroupMemberAdd */
466 p
= make_header(param
, RAP_WGroupAddUser
, RAP_NetGroupAddUser_REQ
, NULL
);
467 PUTSTRING(p
,group_name
,RAP_GROUPNAME_LEN
);
468 PUTSTRING(p
,user_name
,RAP_USERNAME_LEN
);
471 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
472 NULL
, 0, 200, /* data, length, maxlen */
473 &rparam
, &rprcnt
, /* return params, length */
474 &rdata
, &rdrcnt
)) /* return data, length */
476 res
= GETRES(rparam
);
483 DEBUG(1, ("Access Denied\n"));
486 DEBUG(1, ("Not supported by server\n"));
489 DEBUG(1, ("Group does not exist\n"));
492 DEBUG(1, ("User does not exist\n"));
495 DEBUG(4,("NetGroupAddUser res=%d\n", res
));
499 DEBUG(4,("NetGroupAddUser failed\n"));
509 int cli_NetGroupGetUsers(struct cli_state
* cli
, const char *group_name
, void (*fn
)(const char *, void *), void *state
)
514 unsigned int rdrcnt
,rprcnt
;
516 char param
[WORDSIZE
/* api number */
517 +sizeof(RAP_NetGroupGetUsers_REQ
)/* parm string */
518 +sizeof(RAP_GROUP_USERS_INFO_0
) /* return string */
519 +RAP_GROUPNAME_LEN
/* group name */
520 +WORDSIZE
/* info level */
521 +WORDSIZE
]; /* buffer size */
523 /* now send a SMBtrans command with api GroupGetUsers */
524 p
= make_header(param
, RAP_WGroupGetUsers
,
525 RAP_NetGroupGetUsers_REQ
, RAP_GROUP_USERS_INFO_0
);
526 PUTSTRING(p
,group_name
,RAP_GROUPNAME_LEN
-1);
527 PUTWORD(p
,0); /* info level 0 */
528 PUTWORD(p
,0xFFE0); /* return buffer size */
531 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
532 NULL
, 0, CLI_BUFFER_SIZE
,
535 res
= GETRES(rparam
);
536 cli
->rap_error
= res
;
538 DEBUG(1,("NetGroupGetUsers gave error %d\n", res
));
542 if (res
== 0 || res
== ERRmoredata
) {
545 p
= rparam
+ WORDSIZE
+ WORDSIZE
;
548 for (i
=0,p
=rdata
; i
<count
; i
++) {
549 GETSTRINGF(p
, username
, RAP_USERNAME_LEN
);
553 DEBUG(4,("NetGroupGetUsers res=%d\n", res
));
556 DEBUG(4,("NetGroupGetUsers no data returned\n"));
563 int cli_NetUserGetGroups(struct cli_state
* cli
, const char *user_name
, void (*fn
)(const char *, void *), void *state
)
568 unsigned int rdrcnt
,rprcnt
;
570 char param
[WORDSIZE
/* api number */
571 +sizeof(RAP_NetUserGetGroups_REQ
)/* parm string */
572 +sizeof(RAP_GROUP_USERS_INFO_0
) /* return string */
573 +RAP_USERNAME_LEN
/* user name */
574 +WORDSIZE
/* info level */
575 +WORDSIZE
]; /* buffer size */
577 /* now send a SMBtrans command with api GroupGetUsers */
578 p
= make_header(param
, RAP_WUserGetGroups
,
579 RAP_NetUserGetGroups_REQ
, RAP_GROUP_USERS_INFO_0
);
580 PUTSTRING(p
,user_name
,RAP_USERNAME_LEN
-1);
581 PUTWORD(p
,0); /* info level 0 */
582 PUTWORD(p
,0xFFE0); /* return buffer size */
585 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
586 NULL
, 0, CLI_BUFFER_SIZE
,
589 res
= GETRES(rparam
);
590 cli
->rap_error
= res
;
592 DEBUG(1,("NetUserGetGroups gave error %d\n", res
));
596 if (res
== 0 || res
== ERRmoredata
) {
599 p
= rparam
+ WORDSIZE
+ WORDSIZE
;
602 for (i
=0,p
=rdata
; i
<count
; i
++) {
603 GETSTRINGF(p
, groupname
, RAP_USERNAME_LEN
);
604 fn(groupname
, state
);
607 DEBUG(4,("NetUserGetGroups res=%d\n", res
));
610 DEBUG(4,("NetUserGetGroups no data returned\n"));
618 /****************************************************************************
619 call a NetUserDelete - delete user from remote server
620 ****************************************************************************/
621 int cli_NetUserDelete(struct cli_state
*cli
, const char * user_name
)
626 unsigned int rdrcnt
,rprcnt
;
628 char param
[WORDSIZE
/* api number */
629 +sizeof(RAP_NetGroupDel_REQ
) /* parm string */
630 +1 /* no ret string */
631 +RAP_USERNAME_LEN
/* user to del */
632 +WORDSIZE
]; /* reserved word */
634 /* now send a SMBtrans command with api UserDel */
635 p
= make_header(param
, RAP_WUserDel
, RAP_NetGroupDel_REQ
, NULL
);
636 PUTSTRING(p
, user_name
, RAP_USERNAME_LEN
);
637 PUTWORD(p
,0); /* reserved word MBZ on input */
640 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
641 NULL
, 0, 200, /* data, length, maxlen */
642 &rparam
, &rprcnt
, /* return params, length */
643 &rdata
, &rdrcnt
)) /* return data, length */
645 res
= GETRES(rparam
);
650 else if ((res
== 5) || (res
== 65)) {
651 DEBUG(1, ("Access Denied\n"));
653 else if (res
== 2221) {
654 DEBUG (1, ("User does not exist\n"));
657 DEBUG(4,("NetUserDelete res=%d\n", res
));
661 DEBUG(4,("NetUserDelete failed\n"));
670 /****************************************************************************
671 call a NetUserAdd - add user to remote server
672 ****************************************************************************/
673 int cli_NetUserAdd(struct cli_state
*cli
, RAP_USER_INFO_1
* userinfo
)
681 unsigned int rdrcnt
,rprcnt
;
683 char param
[WORDSIZE
/* api number */
684 +sizeof(RAP_NetUserAdd2_REQ
) /* req string */
685 +sizeof(RAP_USER_INFO_L1
) /* data string */
686 +WORDSIZE
/* info level */
687 +WORDSIZE
/* buffer length */
688 +WORDSIZE
]; /* reserved */
691 /* offset into data of free format strings. Will be updated */
692 /* by PUTSTRINGP macro and end up with total data length. */
693 int soffset
=RAP_USERNAME_LEN
+1 /* user name + pad */
694 + RAP_UPASSWD_LEN
/* password */
695 + DWORDSIZE
/* password age */
696 + WORDSIZE
/* privilege */
697 + DWORDSIZE
/* home dir ptr */
698 + DWORDSIZE
/* comment ptr */
699 + WORDSIZE
/* flags */
700 + DWORDSIZE
; /* login script ptr*/
702 /* now send a SMBtrans command with api NetUserAdd */
703 p
= make_header(param
, RAP_WUserAdd2
,
704 RAP_NetUserAdd2_REQ
, RAP_USER_INFO_L1
);
705 PUTWORD(p
, 1); /* info level */
707 PUTWORD(p
, 0); /* pwencrypt */
708 if(userinfo
->passwrd
)
709 PUTWORD(p
,MIN(strlen(userinfo
->passwrd
), RAP_UPASSWD_LEN
));
711 PUTWORD(p
, 0); /* password length */
714 memset(data
, '\0', soffset
);
716 PUTSTRINGF(p
, userinfo
->user_name
, RAP_USERNAME_LEN
);
717 PUTBYTE(p
, 0); /* pad byte 0 */
718 PUTSTRINGF(p
, userinfo
->passwrd
, RAP_UPASSWD_LEN
);
719 PUTDWORD(p
, 0); /* pw age - n.a. on user add */
720 PUTWORD(p
, userinfo
->priv
);
721 PUTSTRINGP(p
, userinfo
->home_dir
, data
, soffset
);
722 PUTSTRINGP(p
, userinfo
->comment
, data
, soffset
);
723 PUTWORD(p
, userinfo
->userflags
);
724 PUTSTRINGP(p
, userinfo
->logon_script
, data
, soffset
);
727 param
, sizeof(param
), 1024, /* Param, length, maxlen */
728 data
, soffset
, sizeof(data
), /* data, length, maxlen */
729 &rparam
, &rprcnt
, /* return params, length */
730 &rdata
, &rdrcnt
)) /* return data, length */
732 res
= GETRES(rparam
);
737 else if ((res
== 5) || (res
== 65)) {
738 DEBUG(1, ("Access Denied\n"));
740 else if (res
== 2224) {
741 DEBUG (1, ("User already exists\n"));
744 DEBUG(4,("NetUserAdd res=%d\n", res
));
748 DEBUG(4,("NetUserAdd failed\n"));
757 /****************************************************************************
758 call a NetUserEnum - try and list users on a different host
759 ****************************************************************************/
760 int cli_RNetUserEnum(struct cli_state
*cli
, void (*fn
)(const char *, const char *, const char *, const char *, void *), void *state
)
762 char param
[WORDSIZE
/* api number */
763 +sizeof(RAP_NetUserEnum_REQ
) /* parm string */
764 +sizeof(RAP_USER_INFO_L1
) /* return string */
765 +WORDSIZE
/* info level */
766 +WORDSIZE
]; /* buffer size */
770 unsigned int rprcnt
, rdrcnt
;
774 memset(param
, '\0', sizeof(param
));
775 p
= make_header(param
, RAP_WUserEnum
,
776 RAP_NetUserEnum_REQ
, RAP_USER_INFO_L1
);
777 PUTWORD(p
,1); /* Info level 1 */
778 PUTWORD(p
,0xFF00); /* Return buffer size */
780 /* BB Fix handling of large numbers of users to be returned */
782 param
, PTR_DIFF(p
,param
),8,
783 NULL
, 0, CLI_BUFFER_SIZE
,
786 res
= GETRES(rparam
);
787 cli
->rap_error
= res
;
788 if (cli
->rap_error
!= 0) {
789 DEBUG(1,("NetUserEnum gave error %d\n", cli
->rap_error
));
793 if (res
== 0 || res
== ERRmoredata
) {
794 int i
, converter
, count
;
795 char username
[RAP_USERNAME_LEN
];
796 char userpw
[RAP_UPASSWD_LEN
];
797 pstring comment
, homedir
, logonscript
;
799 p
= rparam
+ WORDSIZE
; /* skip result */
800 GETWORD(p
, converter
);
803 for (i
=0,p
=rdata
;i
<count
;i
++) {
804 GETSTRINGF(p
, username
, RAP_USERNAME_LEN
);
806 GETSTRINGF(p
, userpw
, RAP_UPASSWD_LEN
);
807 p
+= DWORDSIZE
; /* skip password age */
808 p
+= WORDSIZE
; /* skip priv: 0=guest, 1=user, 2=admin */
809 GETSTRINGP(p
, homedir
, rdata
, converter
);
810 GETSTRINGP(p
, comment
, rdata
, converter
);
811 p
+= WORDSIZE
; /* skip flags */
812 GETSTRINGP(p
, logonscript
, rdata
, converter
);
814 fn(username
, comment
, homedir
, logonscript
, cli
);
817 DEBUG(4,("NetUserEnum res=%d\n", res
));
820 DEBUG(4,("NetUserEnum no data returned\n"));
829 int cli_RNetUserEnum0(struct cli_state
*cli
,
830 void (*fn
)(const char *, void *),
833 char param
[WORDSIZE
/* api number */
834 +sizeof(RAP_NetUserEnum_REQ
) /* parm string */
835 +sizeof(RAP_USER_INFO_L0
) /* return string */
836 +WORDSIZE
/* info level */
837 +WORDSIZE
]; /* buffer size */
841 unsigned int rprcnt
, rdrcnt
;
845 memset(param
, '\0', sizeof(param
));
846 p
= make_header(param
, RAP_WUserEnum
,
847 RAP_NetUserEnum_REQ
, RAP_USER_INFO_L0
);
848 PUTWORD(p
,0); /* Info level 1 */
849 PUTWORD(p
,0xFF00); /* Return buffer size */
851 /* BB Fix handling of large numbers of users to be returned */
853 param
, PTR_DIFF(p
,param
),8,
854 NULL
, 0, CLI_BUFFER_SIZE
,
857 res
= GETRES(rparam
);
858 cli
->rap_error
= res
;
859 if (cli
->rap_error
!= 0) {
860 DEBUG(1,("NetUserEnum gave error %d\n", cli
->rap_error
));
864 if (res
== 0 || res
== ERRmoredata
) {
866 char username
[RAP_USERNAME_LEN
];
868 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
871 for (i
=0,p
=rdata
;i
<count
;i
++) {
872 GETSTRINGF(p
, username
, RAP_USERNAME_LEN
);
876 DEBUG(4,("NetUserEnum res=%d\n", res
));
879 DEBUG(4,("NetUserEnum no data returned\n"));
888 /****************************************************************************
889 call a NetFileClose2 - close open file on another session to server
890 ****************************************************************************/
891 int cli_NetFileClose(struct cli_state
*cli
, uint32 file_id
)
896 unsigned int rdrcnt
,rprcnt
;
897 char param
[WORDSIZE
/* api number */
898 +sizeof(RAP_WFileClose2_REQ
) /* req string */
899 +1 /* no ret string */
900 +DWORDSIZE
]; /* file ID */
903 /* now send a SMBtrans command with api RNetShareEnum */
904 p
= make_header(param
, RAP_WFileClose2
, RAP_WFileClose2_REQ
, NULL
);
905 PUTDWORD(p
, file_id
);
908 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
909 NULL
, 0, 200, /* data, length, maxlen */
910 &rparam
, &rprcnt
, /* return params, length */
911 &rdata
, &rdrcnt
)) /* return data, length */
913 res
= GETRES(rparam
);
917 } else if (res
== 2314){
918 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
920 DEBUG(4,("NetFileClose2 res=%d\n", res
));
924 DEBUG(4,("NetFileClose2 failed\n"));
933 /****************************************************************************
934 call a NetFileGetInfo - get information about server file opened from other
936 ****************************************************************************/
937 int cli_NetFileGetInfo(struct cli_state
*cli
, uint32 file_id
, void (*fn
)(const char *, const char *, uint16
, uint16
, uint32
))
942 unsigned int rdrcnt
,rprcnt
;
944 char param
[WORDSIZE
/* api number */
945 +sizeof(RAP_WFileGetInfo2_REQ
) /* req string */
946 +sizeof(RAP_FILE_INFO_L3
) /* return string */
947 +DWORDSIZE
/* file ID */
948 +WORDSIZE
/* info level */
949 +WORDSIZE
]; /* buffer size */
951 /* now send a SMBtrans command with api RNetShareEnum */
952 p
= make_header(param
, RAP_WFileGetInfo2
,
953 RAP_WFileGetInfo2_REQ
, RAP_FILE_INFO_L3
);
954 PUTDWORD(p
, file_id
);
955 PUTWORD(p
, 3); /* info level */
956 PUTWORD(p
, 0x1000); /* buffer size */
958 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
959 NULL
, 0, 0x1000, /* data, length, maxlen */
960 &rparam
, &rprcnt
, /* return params, length */
961 &rdata
, &rdrcnt
)) /* return data, length */
963 res
= GETRES(rparam
);
964 if (res
== 0 || res
== ERRmoredata
) {
965 int converter
,id
, perms
, locks
;
966 pstring fpath
, fuser
;
968 p
= rparam
+ WORDSIZE
; /* skip result */
969 GETWORD(p
, converter
);
975 GETSTRINGP(p
, fpath
, rdata
, converter
);
976 GETSTRINGP(p
, fuser
, rdata
, converter
);
978 fn(fpath
, fuser
, perms
, locks
, id
);
980 DEBUG(4,("NetFileGetInfo2 res=%d\n", res
));
984 DEBUG(4,("NetFileGetInfo2 failed\n"));
993 /****************************************************************************
994 * Call a NetFileEnum2 - list open files on an SMB server
996 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
997 * server listing the files open via the network (and their
998 * corresponding open instance ids)
1000 * Dependencies: none
1003 * cli - pointer to cli_state structure
1004 * user - if present, return only files opened by this remote user
1005 * base_path - if present, return only files opened below this
1007 * fn - display function to invoke for each entry in the result
1014 ****************************************************************************/
1015 int cli_NetFileEnum(struct cli_state
*cli
, char * user
, char * base_path
, void (*fn
)(const char *, const char *, uint16
, uint16
, uint32
))
1017 char *rparam
= NULL
;
1020 unsigned int rdrcnt
,rprcnt
;
1021 char param
[WORDSIZE
/* api number */
1022 +sizeof(RAP_WFileEnum2_REQ
) /* req string */
1023 +sizeof(RAP_FILE_INFO_L3
) /* return string */
1024 +256 /* base path (opt) */
1025 +RAP_USERNAME_LEN
/* user name (opt) */
1026 +WORDSIZE
/* info level */
1027 +WORDSIZE
/* buffer size */
1028 +DWORDSIZE
/* resume key ? */
1029 +DWORDSIZE
]; /* resume key ? */
1032 /* now send a SMBtrans command with api RNetShareEnum */
1033 p
= make_header(param
, RAP_WFileEnum2
,
1034 RAP_WFileEnum2_REQ
, RAP_FILE_INFO_L3
);
1036 PUTSTRING(p
, base_path
, 256);
1037 PUTSTRING(p
, user
, RAP_USERNAME_LEN
);
1038 PUTWORD(p
, 3); /* info level */
1039 PUTWORD(p
, 0xFF00); /* buffer size */
1040 PUTDWORD(p
, 0); /* zero out the resume key */
1041 PUTDWORD(p
, 0); /* or is this one the resume key? */
1044 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
1045 NULL
, 0, 0xFF00, /* data, length, maxlen */
1046 &rparam
, &rprcnt
, /* return params, length */
1047 &rdata
, &rdrcnt
)) /* return data, length */
1049 int res
= GETRES(rparam
);
1051 if (res
== 0 || res
== ERRmoredata
) {
1054 p
= rparam
+ WORDSIZE
; /* skip result */
1055 GETWORD(p
, converter
);
1059 for (i
=0; i
<count
; i
++) {
1060 int id
, perms
, locks
;
1061 pstring fpath
, fuser
;
1066 GETSTRINGP(p
, fpath
, rdata
, converter
);
1067 GETSTRINGP(p
, fuser
, rdata
, converter
);
1069 fn(fpath
, fuser
, perms
, locks
, id
);
1070 } /* BB fix ERRmoredata case to send resume request */
1072 DEBUG(4,("NetFileEnum2 res=%d\n", res
));
1075 DEBUG(4,("NetFileEnum2 failed\n"));
1084 /****************************************************************************
1085 call a NetShareAdd - share/export directory on remote server
1086 ****************************************************************************/
1087 int cli_NetShareAdd(struct cli_state
*cli
, RAP_SHARE_INFO_2
* sinfo
)
1089 char *rparam
= NULL
;
1092 unsigned int rdrcnt
,rprcnt
;
1094 char param
[WORDSIZE
/* api number */
1095 +sizeof(RAP_WShareAdd_REQ
) /* req string */
1096 +sizeof(RAP_SHARE_INFO_L2
) /* return string */
1097 +WORDSIZE
/* info level */
1098 +WORDSIZE
]; /* reserved word */
1100 /* offset to free format string section following fixed length data. */
1101 /* will be updated by PUTSTRINGP macro and will end up with total len */
1102 int soffset
= RAP_SHARENAME_LEN
+ 1 /* share name + pad */
1103 + WORDSIZE
/* share type */
1104 + DWORDSIZE
/* comment pointer */
1105 + WORDSIZE
/* permissions */
1106 + WORDSIZE
/* max users */
1107 + WORDSIZE
/* active users */
1108 + DWORDSIZE
/* share path */
1109 + RAP_SPASSWD_LEN
+ 1; /* share password + pad */
1111 memset(param
,'\0',sizeof(param
));
1112 /* now send a SMBtrans command with api RNetShareAdd */
1113 p
= make_header(param
, RAP_WshareAdd
,
1114 RAP_WShareAdd_REQ
, RAP_SHARE_INFO_L2
);
1115 PUTWORD(p
, 2); /* info level */
1116 PUTWORD(p
, 0); /* reserved word 0 */
1119 PUTSTRINGF(p
, sinfo
->share_name
, RAP_SHARENAME_LEN
);
1120 PUTBYTE(p
, 0); /* pad byte 0 */
1122 PUTWORD(p
, sinfo
->share_type
);
1123 PUTSTRINGP(p
, sinfo
->comment
, data
, soffset
);
1124 PUTWORD(p
, sinfo
->perms
);
1125 PUTWORD(p
, sinfo
->maximum_users
);
1126 PUTWORD(p
, sinfo
->active_users
);
1127 PUTSTRINGP(p
, sinfo
->path
, data
, soffset
);
1128 PUTSTRINGF(p
, sinfo
->password
, RAP_SPASSWD_LEN
);
1129 SCVAL(p
,-1,0x0A); /* required 0x0A at end of password */
1132 param
, sizeof(param
), 1024, /* Param, length, maxlen */
1133 data
, soffset
, sizeof(data
), /* data, length, maxlen */
1134 &rparam
, &rprcnt
, /* return params, length */
1135 &rdata
, &rdrcnt
)) /* return data, length */
1137 res
= rparam
? SVAL(rparam
,0) : -1;
1143 DEBUG(4,("NetShareAdd res=%d\n", res
));
1147 DEBUG(4,("NetShareAdd failed\n"));
1155 /****************************************************************************
1156 call a NetShareDelete - unshare exported directory on remote server
1157 ****************************************************************************/
1158 int cli_NetShareDelete(struct cli_state
*cli
, const char * share_name
)
1160 char *rparam
= NULL
;
1163 unsigned int rdrcnt
,rprcnt
;
1165 char param
[WORDSIZE
/* api number */
1166 +sizeof(RAP_WShareDel_REQ
) /* req string */
1167 +1 /* no ret string */
1168 +RAP_SHARENAME_LEN
/* share to del */
1169 +WORDSIZE
]; /* reserved word */
1172 /* now send a SMBtrans command with api RNetShareDelete */
1173 p
= make_header(param
, RAP_WshareDel
, RAP_WShareDel_REQ
, NULL
);
1174 PUTSTRING(p
,share_name
,RAP_SHARENAME_LEN
);
1175 PUTWORD(p
,0); /* reserved word MBZ on input */
1178 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
1179 NULL
, 0, 200, /* data, length, maxlen */
1180 &rparam
, &rprcnt
, /* return params, length */
1181 &rdata
, &rdrcnt
)) /* return data, length */
1183 res
= GETRES(rparam
);
1189 DEBUG(4,("NetShareDelete res=%d\n", res
));
1193 DEBUG(4,("NetShareDelete failed\n"));
1201 /*************************************************************************
1203 * Function Name: cli_get_pdc_name
1205 * PURPOSE: Remotes a NetServerEnum API call to the current server
1206 * requesting the name of a server matching the server
1207 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1209 * Dependencies: none
1212 * cli - pointer to cli_state structure
1213 * workgroup - pointer to string containing name of domain
1214 * pdc_name - pointer to string that will contain PDC name
1215 * on successful return
1221 ************************************************************************/
1222 BOOL
cli_get_pdc_name(struct cli_state
*cli
, char *workgroup
, char *pdc_name
)
1224 char *rparam
= NULL
;
1226 unsigned int rdrcnt
,rprcnt
;
1228 char param
[WORDSIZE
/* api number */
1229 +sizeof(RAP_NetServerEnum2_REQ
) /* req string */
1230 +sizeof(RAP_SERVER_INFO_L1
) /* return string */
1231 +WORDSIZE
/* info level */
1232 +WORDSIZE
/* buffer size */
1233 +DWORDSIZE
/* server type */
1234 +RAP_MACHNAME_LEN
]; /* workgroup */
1239 /* send a SMBtrans command with api NetServerEnum */
1240 p
= make_header(param
, RAP_NetServerEnum2
,
1241 RAP_NetServerEnum2_REQ
, RAP_SERVER_INFO_L1
);
1242 PUTWORD(p
, 1); /* info level */
1243 PUTWORD(p
, CLI_BUFFER_SIZE
);
1244 PUTDWORD(p
, SV_TYPE_DOMAIN_CTRL
);
1245 PUTSTRING(p
, workgroup
, RAP_MACHNAME_LEN
);
1248 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1249 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1250 &rparam
, &rprcnt
, /* return params, return size */
1251 &rdata
, &rdrcnt
/* return data, return size */
1253 cli
->rap_error
= GETRES(rparam
);
1256 * We only really care to copy a name if the
1257 * API succeeded and we got back a name.
1259 if (cli
->rap_error
== 0) {
1260 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
1265 GETSTRING(p
, pdc_name
);
1268 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1269 "Error was : %s.\n", cli
->desthost
, cli_errstr(cli
) ));
1280 /*************************************************************************
1282 * Function Name: cli_get_server_domain
1284 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1285 * requesting wksta_info_10 level information to determine
1286 * the domain the server belongs to. On success, this
1287 * routine sets the server_domain field in the cli_state structure
1288 * to the server's domain name.
1290 * Dependencies: none
1293 * cli - pointer to cli_state structure
1299 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1301 ************************************************************************/
1302 BOOL
cli_get_server_domain(struct cli_state
*cli
)
1304 char *rparam
= NULL
;
1306 unsigned int rdrcnt
,rprcnt
;
1308 char param
[WORDSIZE
/* api number */
1309 +sizeof(RAP_WWkstaGetInfo_REQ
) /* req string */
1310 +sizeof(RAP_WKSTA_INFO_L10
) /* return string */
1311 +WORDSIZE
/* info level */
1312 +WORDSIZE
]; /* buffer size */
1315 /* send a SMBtrans command with api NetWkstaGetInfo */
1316 p
= make_header(param
, RAP_WWkstaGetInfo
,
1317 RAP_WWkstaGetInfo_REQ
, RAP_WKSTA_INFO_L10
);
1318 PUTWORD(p
, 10); /* info level */
1319 PUTWORD(p
, CLI_BUFFER_SIZE
);
1321 if (cli_api(cli
, param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1322 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1323 &rparam
, &rprcnt
, /* return params, return size */
1324 &rdata
, &rdrcnt
)) { /* return data, return size */
1325 res
= GETRES(rparam
);
1331 p
= rparam
+ WORDSIZE
;
1332 GETWORD(p
, converter
);
1334 p
= rdata
+ DWORDSIZE
+ DWORDSIZE
; /* skip computer & user names */
1335 GETSTRINGP(p
, cli
->server_domain
, rdata
, converter
);
1346 /*************************************************************************
1348 * Function Name: cli_get_server_type
1350 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1351 * requesting server_info_1 level information to retrieve
1354 * Dependencies: none
1357 * cli - pointer to cli_state structure
1358 * pstype - pointer to uint32 to contain returned server type
1364 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1366 ************************************************************************/
1367 BOOL
cli_get_server_type(struct cli_state
*cli
, uint32
*pstype
)
1369 char *rparam
= NULL
;
1371 unsigned int rdrcnt
,rprcnt
;
1373 char param
[WORDSIZE
/* api number */
1374 +sizeof(RAP_WserverGetInfo_REQ
) /* req string */
1375 +sizeof(RAP_SERVER_INFO_L1
) /* return string */
1376 +WORDSIZE
/* info level */
1377 +WORDSIZE
]; /* buffer size */
1380 /* send a SMBtrans command with api NetServerGetInfo */
1381 p
= make_header(param
, RAP_WserverGetInfo
,
1382 RAP_WserverGetInfo_REQ
, RAP_SERVER_INFO_L1
);
1383 PUTWORD(p
, 1); /* info level */
1384 PUTWORD(p
, CLI_BUFFER_SIZE
);
1387 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1388 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1389 &rparam
, &rprcnt
, /* return params, return size */
1390 &rdata
, &rdrcnt
/* return data, return size */
1393 res
= GETRES(rparam
);
1395 if (res
== 0 || res
== ERRmoredata
) {
1397 *pstype
= IVAL(p
,18) & ~SV_TYPE_LOCAL_LIST_ONLY
;
1404 return(res
== 0 || res
== ERRmoredata
);
1408 /*************************************************************************
1410 * Function Name: cli_ns_check_server_type
1412 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1413 * requesting server_info_0 level information of machines
1414 * matching the given server type. If the returned server
1415 * list contains the machine name contained in cli->desthost
1416 * then we conclude the server type checks out. This routine
1417 * is useful to retrieve list of server's of a certain
1418 * type when all you have is a null session connection and
1419 * can't remote API calls such as NetWkstaGetInfo or
1422 * Dependencies: none
1425 * cli - pointer to cli_state structure
1426 * workgroup - pointer to string containing domain
1427 * stype - server type
1433 ************************************************************************/
1434 BOOL
cli_ns_check_server_type(struct cli_state
*cli
, char *workgroup
, uint32 stype
)
1436 char *rparam
= NULL
;
1438 unsigned int rdrcnt
,rprcnt
;
1440 char param
[WORDSIZE
/* api number */
1441 +sizeof(RAP_NetServerEnum2_REQ
) /* req string */
1442 +sizeof(RAP_SERVER_INFO_L0
) /* return string */
1443 +WORDSIZE
/* info level */
1444 +WORDSIZE
/* buffer size */
1445 +DWORDSIZE
/* server type */
1446 +RAP_MACHNAME_LEN
]; /* workgroup */
1447 BOOL found_server
= False
;
1450 /* send a SMBtrans command with api NetServerEnum */
1451 p
= make_header(param
, RAP_NetServerEnum2
,
1452 RAP_NetServerEnum2_REQ
, RAP_SERVER_INFO_L0
);
1453 PUTWORD(p
, 0); /* info level 0 */
1454 PUTWORD(p
, CLI_BUFFER_SIZE
);
1456 PUTSTRING(p
, workgroup
, RAP_MACHNAME_LEN
);
1459 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1460 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1461 &rparam
, &rprcnt
, /* return params, return size */
1462 &rdata
, &rdrcnt
/* return data, return size */
1465 res
= GETRES(rparam
);
1466 cli
->rap_error
= res
;
1468 if (res
== 0 || res
== ERRmoredata
) {
1471 p
= rparam
+ WORDSIZE
+ WORDSIZE
;
1475 for (i
= 0;i
< count
;i
++, p
+= 16) {
1476 char ret_server
[RAP_MACHNAME_LEN
];
1478 GETSTRINGF(p
, ret_server
, RAP_MACHNAME_LEN
);
1479 if (strequal(ret_server
, cli
->desthost
)) {
1480 found_server
= True
;
1486 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1487 "Error was : %s.\n", cli
->desthost
, cli_errstr(cli
) ));
1494 return found_server
;
1498 /****************************************************************************
1499 perform a NetWkstaUserLogoff
1500 ****************************************************************************/
1501 BOOL
cli_NetWkstaUserLogoff(struct cli_state
*cli
,char *user
, char *workstation
)
1503 char *rparam
= NULL
;
1506 unsigned int rdrcnt
,rprcnt
;
1507 char param
[WORDSIZE
/* api number */
1508 +sizeof(RAP_NetWkstaUserLogoff_REQ
) /* req string */
1509 +sizeof(RAP_USER_LOGOFF_INFO_L1
) /* return string */
1510 +RAP_USERNAME_LEN
+1 /* user name+pad */
1511 +RAP_MACHNAME_LEN
/* wksta name */
1512 +WORDSIZE
/* buffer size */
1513 +WORDSIZE
]; /* buffer size? */
1516 memset(param
, 0, sizeof(param
));
1518 /* send a SMBtrans command with api NetWkstaUserLogoff */
1519 p
= make_header(param
, RAP_WWkstaUserLogoff
,
1520 RAP_NetWkstaUserLogoff_REQ
, RAP_USER_LOGOFF_INFO_L1
);
1521 PUTDWORD(p
, 0); /* Null pointer */
1522 PUTDWORD(p
, 0); /* Null pointer */
1523 fstrcpy(upperbuf
, user
);
1524 strupper_m(upperbuf
);
1525 PUTSTRINGF(p
, upperbuf
, RAP_USERNAME_LEN
);
1526 p
++; /* strange format, but ok */
1527 fstrcpy(upperbuf
, workstation
);
1528 strupper_m(upperbuf
);
1529 PUTSTRINGF(p
, upperbuf
, RAP_MACHNAME_LEN
);
1530 PUTWORD(p
, CLI_BUFFER_SIZE
);
1531 PUTWORD(p
, CLI_BUFFER_SIZE
);
1534 param
, PTR_DIFF(p
,param
),1024, /* param, length, max */
1535 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1536 &rparam
, &rprcnt
, /* return params, return size */
1537 &rdata
, &rdrcnt
/* return data, return size */
1539 cli
->rap_error
= GETRES(rparam
);
1541 if (cli
->rap_error
!= 0) {
1542 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli
->rap_error
));
1548 return (cli
->rap_error
== 0);
1551 int cli_NetPrintQEnum(struct cli_state
*cli
,
1552 void (*qfn
)(const char*,uint16
,uint16
,uint16
,const char*,const char*,const char*,const char*,const char*,uint16
,uint16
),
1553 void (*jfn
)(uint16
,const char*,const char*,const char*,const char*,uint16
,uint16
,const char*,uint
,uint
,const char*))
1555 char param
[WORDSIZE
/* api number */
1556 +sizeof(RAP_NetPrintQEnum_REQ
) /* req string */
1557 +sizeof(RAP_PRINTQ_INFO_L2
) /* return string */
1558 +WORDSIZE
/* info level */
1559 +WORDSIZE
/* buffer size */
1560 +sizeof(RAP_SMB_PRINT_JOB_L1
)]; /* more ret data */
1562 char *rparam
= NULL
;
1564 unsigned int rprcnt
, rdrcnt
;
1568 memset(param
, '\0',sizeof(param
));
1569 p
= make_header(param
, RAP_WPrintQEnum
,
1570 RAP_NetPrintQEnum_REQ
, RAP_PRINTQ_INFO_L2
);
1571 PUTWORD(p
,2); /* Info level 2 */
1572 PUTWORD(p
,0xFFE0); /* Return buffer size */
1573 PUTSTRING(p
, RAP_SMB_PRINT_JOB_L1
, 0);
1576 param
, PTR_DIFF(p
,param
),1024,
1577 NULL
, 0, CLI_BUFFER_SIZE
,
1580 res
= GETRES(rparam
);
1581 cli
->rap_error
= res
;
1583 DEBUG(1,("NetPrintQEnum gave error %d\n", res
));
1588 if (res
== 0 || res
== ERRmoredata
) {
1589 int i
, converter
, count
;
1591 p
= rparam
+ WORDSIZE
;
1592 GETWORD(p
, converter
);
1596 for (i
=0;i
<count
;i
++) {
1597 pstring qname
, sep_file
, print_proc
, dest
, parms
, comment
;
1598 uint16 jobcount
, priority
, start_time
, until_time
, status
;
1600 GETSTRINGF(p
, qname
, RAP_SHARENAME_LEN
);
1602 GETWORD(p
, priority
);
1603 GETWORD(p
, start_time
);
1604 GETWORD(p
, until_time
);
1605 GETSTRINGP(p
, sep_file
, rdata
, converter
);
1606 GETSTRINGP(p
, print_proc
, rdata
, converter
);
1607 GETSTRINGP(p
, dest
, rdata
, converter
);
1608 GETSTRINGP(p
, parms
, rdata
, converter
);
1609 GETSTRINGP(p
, parms
, comment
, converter
);
1611 GETWORD(p
, jobcount
);
1613 qfn(qname
, priority
, start_time
, until_time
, sep_file
, print_proc
,
1614 dest
, parms
, comment
, status
, jobcount
);
1618 for (j
=0;j
<jobcount
;j
++) {
1619 uint16 jid
, pos
, fsstatus
;
1620 pstring ownername
, notifyname
, datatype
, jparms
, jstatus
, jcomment
;
1621 unsigned int submitted
, jsize
;
1624 GETSTRINGF(p
, ownername
, RAP_USERNAME_LEN
);
1626 GETSTRINGF(p
, notifyname
, RAP_MACHNAME_LEN
);
1627 GETSTRINGF(p
, datatype
, RAP_DATATYPE_LEN
);
1628 GETSTRINGP(p
, jparms
, rdata
, converter
);
1630 GETWORD(p
, fsstatus
);
1631 GETSTRINGP(p
, jstatus
, rdata
, converter
);
1632 GETDWORD(p
, submitted
);
1634 GETSTRINGP(p
, jcomment
, rdata
, converter
);
1636 jfn(jid
, ownername
, notifyname
, datatype
, jparms
, pos
, fsstatus
,
1637 jstatus
, submitted
, jsize
, jcomment
);
1642 DEBUG(4,("NetPrintQEnum res=%d\n", res
));
1645 DEBUG(4,("NetPrintQEnum no data returned\n"));
1654 int cli_NetPrintQGetInfo(struct cli_state
*cli
, const char *printer
,
1655 void (*qfn
)(const char*,uint16
,uint16
,uint16
,const char*,const char*,const char*,const char*,const char*,uint16
,uint16
),
1656 void (*jfn
)(uint16
,const char*,const char*,const char*,const char*,uint16
,uint16
,const char*,uint
,uint
,const char*))
1658 char param
[WORDSIZE
/* api number */
1659 +sizeof(RAP_NetPrintQGetInfo_REQ
) /* req string */
1660 +sizeof(RAP_PRINTQ_INFO_L2
) /* return string */
1661 +RAP_SHARENAME_LEN
/* printer name */
1662 +WORDSIZE
/* info level */
1663 +WORDSIZE
/* buffer size */
1664 +sizeof(RAP_SMB_PRINT_JOB_L1
)]; /* more ret data */
1666 char *rparam
= NULL
;
1668 unsigned int rprcnt
, rdrcnt
;
1672 memset(param
, '\0',sizeof(param
));
1673 p
= make_header(param
, RAP_WPrintQGetInfo
,
1674 RAP_NetPrintQGetInfo_REQ
, RAP_PRINTQ_INFO_L2
);
1675 PUTSTRING(p
, printer
, RAP_SHARENAME_LEN
-1);
1676 PUTWORD(p
, 2); /* Info level 2 */
1677 PUTWORD(p
,0xFFE0); /* Return buffer size */
1678 PUTSTRING(p
, RAP_SMB_PRINT_JOB_L1
, 0);
1681 param
, PTR_DIFF(p
,param
),1024,
1682 NULL
, 0, CLI_BUFFER_SIZE
,
1685 res
= GETRES(rparam
);
1686 cli
->rap_error
= res
;
1688 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res
));
1693 if (res
== 0 || res
== ERRmoredata
) {
1694 int rsize
, converter
;
1695 pstring qname
, sep_file
, print_proc
, dest
, parms
, comment
;
1696 uint16 jobcount
, priority
, start_time
, until_time
, status
;
1698 p
= rparam
+ WORDSIZE
;
1699 GETWORD(p
, converter
);
1703 GETSTRINGF(p
, qname
, RAP_SHARENAME_LEN
);
1705 GETWORD(p
, priority
);
1706 GETWORD(p
, start_time
);
1707 GETWORD(p
, until_time
);
1708 GETSTRINGP(p
, sep_file
, rdata
, converter
);
1709 GETSTRINGP(p
, print_proc
, rdata
, converter
);
1710 GETSTRINGP(p
, dest
, rdata
, converter
);
1711 GETSTRINGP(p
, parms
, rdata
, converter
);
1712 GETSTRINGP(p
, comment
, rdata
, converter
);
1714 GETWORD(p
, jobcount
);
1715 qfn(qname
, priority
, start_time
, until_time
, sep_file
, print_proc
,
1716 dest
, parms
, comment
, status
, jobcount
);
1719 for (j
=0;(j
<jobcount
)&&(PTR_DIFF(p
,rdata
)< rsize
);j
++) {
1720 uint16 jid
, pos
, fsstatus
;
1721 pstring ownername
, notifyname
, datatype
, jparms
, jstatus
, jcomment
;
1722 unsigned int submitted
, jsize
;
1725 GETSTRINGF(p
, ownername
, RAP_USERNAME_LEN
);
1727 GETSTRINGF(p
, notifyname
, RAP_MACHNAME_LEN
);
1728 GETSTRINGF(p
, datatype
, RAP_DATATYPE_LEN
);
1729 GETSTRINGP(p
, jparms
, rdata
, converter
);
1731 GETWORD(p
, fsstatus
);
1732 GETSTRINGP(p
, jstatus
, rdata
, converter
);
1733 GETDWORD(p
, submitted
);
1735 GETSTRINGP(p
, jcomment
, rdata
, converter
);
1737 jfn(jid
, ownername
, notifyname
, datatype
, jparms
, pos
, fsstatus
,
1738 jstatus
, submitted
, jsize
, jcomment
);
1742 DEBUG(4,("NetPrintQGetInfo res=%d\n", res
));
1745 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1754 /****************************************************************************
1755 call a NetServiceEnum - list running services on a different host
1756 ****************************************************************************/
1757 int cli_RNetServiceEnum(struct cli_state
*cli
, void (*fn
)(const char *, const char *, void *), void *state
)
1759 char param
[WORDSIZE
/* api number */
1760 +sizeof(RAP_NetServiceEnum_REQ
) /* parm string */
1761 +sizeof(RAP_SERVICE_INFO_L2
) /* return string */
1762 +WORDSIZE
/* info level */
1763 +WORDSIZE
]; /* buffer size */
1765 char *rparam
= NULL
;
1767 unsigned int rprcnt
, rdrcnt
;
1771 memset(param
, '\0', sizeof(param
));
1772 p
= make_header(param
, RAP_WServiceEnum
,
1773 RAP_NetServiceEnum_REQ
, RAP_SERVICE_INFO_L2
);
1774 PUTWORD(p
,2); /* Info level 2 */
1775 PUTWORD(p
,0xFFE0); /* Return buffer size */
1778 param
, PTR_DIFF(p
,param
),8,
1779 NULL
, 0, 0xFFE0 /* data area size */,
1782 res
= GETRES(rparam
);
1783 cli
->rap_error
= res
;
1784 if(cli
->rap_error
== 234)
1785 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1786 else if (cli
->rap_error
!= 0) {
1787 DEBUG(1,("NetServiceEnum gave error %d\n", cli
->rap_error
));
1792 if (res
== 0 || res
== ERRmoredata
) {
1795 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
1798 for (i
=0,p
=rdata
;i
<count
;i
++) {
1800 char servicename
[RAP_SRVCNAME_LEN
];
1802 GETSTRINGF(p
, servicename
, RAP_SRVCNAME_LEN
);
1803 p
+=8; /* pass status words */
1804 GETSTRINGF(p
, comment
, RAP_SRVCCMNT_LEN
);
1806 fn(servicename
, comment
, cli
); /* BB add status too */
1809 DEBUG(4,("NetServiceEnum res=%d\n", res
));
1812 DEBUG(4,("NetServiceEnum no data returned\n"));
1822 /****************************************************************************
1823 call a NetSessionEnum - list workstations with sessions to an SMB server
1824 ****************************************************************************/
1825 int cli_NetSessionEnum(struct cli_state
*cli
, void (*fn
)(char *, char *, uint16
, uint16
, uint16
, uint
, uint
, uint
, char *))
1827 char param
[WORDSIZE
/* api number */
1828 +sizeof(RAP_NetSessionEnum_REQ
) /* parm string */
1829 +sizeof(RAP_SESSION_INFO_L2
) /* return string */
1830 +WORDSIZE
/* info level */
1831 +WORDSIZE
]; /* buffer size */
1833 char *rparam
= NULL
;
1835 unsigned int rprcnt
, rdrcnt
;
1838 memset(param
, '\0', sizeof(param
));
1839 p
= make_header(param
, RAP_WsessionEnum
,
1840 RAP_NetSessionEnum_REQ
, RAP_SESSION_INFO_L2
);
1841 PUTWORD(p
,2); /* Info level 2 */
1842 PUTWORD(p
,0xFF); /* Return buffer size */
1845 param
, PTR_DIFF(p
,param
),8,
1846 NULL
, 0, CLI_BUFFER_SIZE
,
1849 res
= GETRES(rparam
);
1850 cli
->rap_error
= res
;
1852 DEBUG(1,("NetSessionEnum gave error %d\n", res
));
1857 if (res
== 0 || res
== ERRmoredata
) {
1858 int i
, converter
, count
;
1860 p
= rparam
+ WORDSIZE
;
1861 GETWORD(p
, converter
);
1864 for (i
=0,p
=rdata
;i
<count
;i
++) {
1865 pstring wsname
, username
, clitype_name
;
1866 uint16 num_conns
, num_opens
, num_users
;
1867 unsigned int sess_time
, idle_time
, user_flags
;
1869 GETSTRINGP(p
, wsname
, rdata
, converter
);
1870 GETSTRINGP(p
, username
, rdata
, converter
);
1871 GETWORD(p
, num_conns
);
1872 GETWORD(p
, num_opens
);
1873 GETWORD(p
, num_users
);
1874 GETDWORD(p
, sess_time
);
1875 GETDWORD(p
, idle_time
);
1876 GETDWORD(p
, user_flags
);
1877 GETSTRINGP(p
, clitype_name
, rdata
, converter
);
1879 fn(wsname
, username
, num_conns
, num_opens
, num_users
, sess_time
,
1880 idle_time
, user_flags
, clitype_name
);
1884 DEBUG(4,("NetSessionEnum res=%d\n", res
));
1887 DEBUG(4,("NetSesssionEnum no data returned\n"));
1896 /****************************************************************************
1897 Call a NetSessionGetInfo - get information about other session to an SMB server.
1898 ****************************************************************************/
1900 int cli_NetSessionGetInfo(struct cli_state
*cli
, const char *workstation
, void (*fn
)(const char *, const char *, uint16
, uint16
, uint16
, uint
, uint
, uint
, const char *))
1902 char param
[WORDSIZE
/* api number */
1903 +sizeof(RAP_NetSessionGetInfo_REQ
) /* req string */
1904 +sizeof(RAP_SESSION_INFO_L2
) /* return string */
1905 +RAP_MACHNAME_LEN
/* wksta name */
1906 +WORDSIZE
/* info level */
1907 +WORDSIZE
]; /* buffer size */
1909 char *rparam
= NULL
;
1911 unsigned int rprcnt
, rdrcnt
;
1915 memset(param
, '\0', sizeof(param
));
1916 p
= make_header(param
, RAP_WsessionGetInfo
,
1917 RAP_NetSessionGetInfo_REQ
, RAP_SESSION_INFO_L2
);
1918 PUTSTRING(p
, workstation
, RAP_MACHNAME_LEN
-1);
1919 PUTWORD(p
,2); /* Info level 2 */
1920 PUTWORD(p
,0xFF); /* Return buffer size */
1923 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
1924 NULL
, 0, CLI_BUFFER_SIZE
,
1927 cli
->rap_error
= SVAL(rparam
,0);
1928 if (cli
->rap_error
!= 0) {
1929 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli
->rap_error
));
1934 res
= GETRES(rparam
);
1936 if (res
== 0 || res
== ERRmoredata
) {
1938 pstring wsname
, username
, clitype_name
;
1939 uint16 num_conns
, num_opens
, num_users
;
1940 unsigned int sess_time
, idle_time
, user_flags
;
1942 p
= rparam
+ WORDSIZE
;
1943 GETWORD(p
, converter
);
1944 p
+= WORDSIZE
; /* skip rsize */
1947 GETSTRINGP(p
, wsname
, rdata
, converter
);
1948 GETSTRINGP(p
, username
, rdata
, converter
);
1949 GETWORD(p
, num_conns
);
1950 GETWORD(p
, num_opens
);
1951 GETWORD(p
, num_users
);
1952 GETDWORD(p
, sess_time
);
1953 GETDWORD(p
, idle_time
);
1954 GETDWORD(p
, user_flags
);
1955 GETSTRINGP(p
, clitype_name
, rdata
, converter
);
1957 fn(wsname
, username
, num_conns
, num_opens
, num_users
, sess_time
,
1958 idle_time
, user_flags
, clitype_name
);
1960 DEBUG(4,("NetSessionGetInfo res=%d\n", res
));
1963 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1972 /****************************************************************************
1973 call a NetSessionDel - close a session to an SMB server
1974 ****************************************************************************/
1975 int cli_NetSessionDel(struct cli_state
*cli
, const char *workstation
)
1977 char param
[WORDSIZE
/* api number */
1978 +sizeof(RAP_NetSessionDel_REQ
) /* req string */
1979 +1 /* no return string */
1980 +RAP_MACHNAME_LEN
/* workstation name */
1981 +WORDSIZE
]; /* reserved (0) */
1983 char *rparam
= NULL
;
1985 unsigned int rprcnt
, rdrcnt
;
1988 memset(param
, '\0', sizeof(param
));
1989 p
= make_header(param
, RAP_WsessionDel
, RAP_NetSessionDel_REQ
, NULL
);
1990 PUTSTRING(p
, workstation
, RAP_MACHNAME_LEN
-1);
1991 PUTWORD(p
,0); /* reserved word of 0 */
1993 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
1994 NULL
, 0, 200, /* data, length, maxlen */
1995 &rparam
, &rprcnt
, /* return params, length */
1996 &rdata
, &rdrcnt
)) /* return data, length */
1998 res
= GETRES(rparam
);
1999 cli
->rap_error
= res
;
2005 DEBUG(4,("NetFileClose2 res=%d\n", res
));
2009 DEBUG(4,("NetFileClose2 failed\n"));
2019 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
))
2021 char param
[WORDSIZE
/* api number */
2022 +sizeof(RAP_NetConnectionEnum_REQ
) /* req string */
2023 +sizeof(RAP_CONNECTION_INFO_L1
) /* return string */
2024 +RAP_MACHNAME_LEN
/* wksta name */
2025 +WORDSIZE
/* info level */
2026 +WORDSIZE
]; /* buffer size */
2028 char *rparam
= NULL
;
2030 unsigned int rprcnt
, rdrcnt
;
2033 memset(param
, '\0', sizeof(param
));
2034 p
= make_header(param
, RAP_WconnectionEnum
,
2035 RAP_NetConnectionEnum_REQ
, RAP_CONNECTION_INFO_L1
);
2036 PUTSTRING(p
, qualifier
, RAP_MACHNAME_LEN
-1);/* Workstation name */
2037 PUTWORD(p
,1); /* Info level 1 */
2038 PUTWORD(p
,0xFFE0); /* Return buffer size */
2041 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
2042 NULL
, 0, CLI_BUFFER_SIZE
,
2045 res
= GETRES(rparam
);
2046 cli
->rap_error
= res
;
2048 DEBUG(1,("NetConnectionEnum gave error %d\n", res
));
2052 if (res
== 0 || res
== ERRmoredata
) {
2053 int i
, converter
, count
;
2055 p
= rparam
+ WORDSIZE
;
2056 GETWORD(p
, converter
);
2059 for (i
=0,p
=rdata
;i
<count
;i
++) {
2060 pstring netname
, username
;
2061 uint16 conn_id
, conn_type
, num_opens
, num_users
;
2062 unsigned int conn_time
;
2065 GETWORD(p
,conn_type
);
2066 GETWORD(p
,num_opens
);
2067 GETWORD(p
,num_users
);
2068 GETDWORD(p
,conn_time
);
2069 GETSTRINGP(p
, username
, rdata
, converter
);
2070 GETSTRINGP(p
, netname
, rdata
, converter
);
2072 fn(conn_id
, conn_type
, num_opens
, num_users
, conn_time
,
2077 DEBUG(4,("NetConnectionEnum res=%d\n", res
));
2080 DEBUG(4,("NetConnectionEnum no data returned\n"));