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 3 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, see <http://www.gnu.org/licenses/>.
22 /*****************************************************/
24 /* Additional RAP functionality */
26 /* RAP is the original SMB RPC, documented */
27 /* by Microsoft and X/Open in the 1990s and */
28 /* supported by most SMB/CIFS servers although */
29 /* it is unlikely that any one implementation */
30 /* supports all RAP command codes since some */
31 /* are quite obsolete and a few are specific */
32 /* to a particular network operating system */
34 /* Although it has largely been replaced */
35 /* for complex remote admistration and management */
36 /* (of servers) by the relatively newer */
37 /* DCE/RPC based remote API (which better handles */
38 /* large >64K data structures), there are many */
39 /* important administrative and resource location */
40 /* tasks and user tasks (e.g. password change) */
41 /* that are performed via RAP. */
43 /* Although a few of the RAP calls are implemented */
44 /* in the Samba client library already (clirap.c) */
45 /* the new ones are in clirap2.c for easy patching */
46 /* and integration and a corresponding header */
47 /* file, rap.h, has been created. */
49 /* This is based on data from the CIFS spec */
50 /* and the LAN Server and LAN Manager */
51 /* Programming Reference books and published */
52 /* RAP document and CIFS forum postings and */
53 /* lots of trial and error */
55 /* Function names changed from API_ (as they are */
56 /* in the CIFS specification) to RAP_ in order */
57 /* to avoid confusion with other API calls */
58 /* sent via DCE RPC */
60 /*****************************************************/
62 /*****************************************************/
64 /* cifsrap.c already includes support for: */
66 /* WshareEnum ( API number 0, level 1) */
67 /* NetServerEnum2 (API num 104, level 1) */
68 /* WWkstaUserLogon (132) */
69 /* SamOEMchgPasswordUser2_P (214) */
71 /* cifsprint.c already includes support for: */
73 /* WPrintJobEnum (API num 76, level 2) */
74 /* WPrintJobDel (API num 81) */
76 /*****************************************************/
83 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
84 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
85 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
86 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
87 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
88 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
89 #define GETRES(p) p ? SVAL(p,0) : -1
90 /* put string s at p with max len n and increment p past string */
91 #define PUTSTRING(p,s,n) do {\
92 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
93 p = push_skip_string(p);\
95 /* put string s and p, using fixed len l, and increment p by l */
96 #define PUTSTRINGF(p,s,l) do {\
97 push_ascii(p,s?s:"",l,STR_TERMINATE);\
100 /* put string pointer at p, supplying offset o from rdata r, store */
101 /* dword offset at p, increment p by 4 and o by length of s. This */
102 /* means on the first call, you must calc the offset yourself! */
103 #define PUTSTRINGP(p,s,r,o) do {\
105 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
108 } else PUTDWORD(p,0);\
110 /* get asciiz string s from p, increment p past string */
111 #define GETSTRING(p,s) do {\
112 pull_ascii_pstring(s,p);\
113 p = push_skip_string(p);\
115 /* get fixed length l string s from p, increment p by l */
116 #define GETSTRINGF(p,s,l) do {\
117 pull_ascii_pstring(s,p);\
120 /* get string s from offset (obtained at p) from rdata r - converter c */
121 #define GETSTRINGP(p,s,r,c) do {\
124 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
125 pull_ascii_pstring(s, off?(r+off-c):"");\
128 static char *make_header(char *param
, uint16 apinum
, const char *reqfmt
, const char *datafmt
)
130 PUTWORD(param
,apinum
);
132 PUTSTRING(param
,reqfmt
,0);
137 PUTSTRING(param
,datafmt
,0);
145 /****************************************************************************
146 call a NetGroupDelete - delete user group from remote server
147 ****************************************************************************/
148 int cli_NetGroupDelete(struct cli_state
*cli
, const char *group_name
)
153 unsigned int rdrcnt
,rprcnt
;
155 char param
[WORDSIZE
/* api number */
156 +sizeof(RAP_NetGroupDel_REQ
) /* parm string */
157 +1 /* no ret string */
158 +RAP_GROUPNAME_LEN
/* group to del */
159 +WORDSIZE
]; /* reserved word */
161 /* now send a SMBtrans command with api GroupDel */
162 p
= make_header(param
, RAP_WGroupDel
, RAP_NetGroupDel_REQ
, NULL
);
163 PUTSTRING(p
, group_name
, RAP_GROUPNAME_LEN
);
164 PUTWORD(p
,0); /* reserved word MBZ on input */
167 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
168 NULL
, 0, 200, /* data, length, maxlen */
169 &rparam
, &rprcnt
, /* return params, length */
170 &rdata
, &rdrcnt
)) /* return data, length */
172 res
= GETRES(rparam
);
177 else if ((res
== 5) || (res
== 65)) {
178 DEBUG(1, ("Access Denied\n"));
180 else if (res
== 2220) {
181 DEBUG (1, ("Group does not exist\n"));
184 DEBUG(4,("NetGroupDelete res=%d\n", res
));
188 DEBUG(4,("NetGroupDelete failed\n"));
197 /****************************************************************************
198 call a NetGroupAdd - add user group to remote server
199 ****************************************************************************/
200 int cli_NetGroupAdd(struct cli_state
*cli
, RAP_GROUP_INFO_1
* grinfo
)
205 unsigned int rdrcnt
,rprcnt
;
207 char param
[WORDSIZE
/* api number */
208 +sizeof(RAP_NetGroupAdd_REQ
) /* req string */
209 +sizeof(RAP_GROUP_INFO_L1
) /* return string */
210 +WORDSIZE
/* info level */
211 +WORDSIZE
]; /* reserved word */
213 /* offset into data of free format strings. Will be updated */
214 /* by PUTSTRINGP macro and end up with total data length. */
215 int soffset
= RAP_GROUPNAME_LEN
+ 1 + DWORDSIZE
;
220 data_size
= MAX(soffset
+ strlen(grinfo
->comment
) + 1, 1024);
222 data
= SMB_MALLOC_ARRAY(char, data_size
);
224 DEBUG (1, ("Malloc fail\n"));
228 /* now send a SMBtrans command with api WGroupAdd */
230 p
= make_header(param
, RAP_WGroupAdd
,
231 RAP_NetGroupAdd_REQ
, RAP_GROUP_INFO_L1
);
232 PUTWORD(p
, 1); /* info level */
233 PUTWORD(p
, 0); /* reserved word 0 */
236 PUTSTRINGF(p
, grinfo
->group_name
, RAP_GROUPNAME_LEN
);
237 PUTBYTE(p
, 0); /* pad byte 0 */
238 PUTSTRINGP(p
, grinfo
->comment
, data
, soffset
);
241 param
, sizeof(param
), 1024, /* Param, length, maxlen */
242 data
, soffset
, sizeof(data
), /* data, length, maxlen */
243 &rparam
, &rprcnt
, /* return params, length */
244 &rdata
, &rdrcnt
)) /* return data, length */
246 res
= GETRES(rparam
);
250 } else if ((res
== 5) || (res
== 65)) {
251 DEBUG(1, ("Access Denied\n"));
253 else if (res
== 2223) {
254 DEBUG (1, ("Group already exists\n"));
257 DEBUG(4,("NetGroupAdd res=%d\n", res
));
261 DEBUG(4,("NetGroupAdd failed\n"));
271 /****************************************************************************
272 call a NetGroupEnum - try and list user groups on a different host
273 ****************************************************************************/
274 int cli_RNetGroupEnum(struct cli_state
*cli
, void (*fn
)(const char *, const char *, void *), void *state
)
276 char param
[WORDSIZE
/* api number */
277 +sizeof(RAP_NetGroupEnum_REQ
) /* parm string */
278 +sizeof(RAP_GROUP_INFO_L1
) /* return string */
279 +WORDSIZE
/* info level */
280 +WORDSIZE
]; /* buffer size */
284 unsigned int rprcnt
, rdrcnt
;
288 memset(param
, '\0', sizeof(param
));
289 p
= make_header(param
, RAP_WGroupEnum
,
290 RAP_NetGroupEnum_REQ
, RAP_GROUP_INFO_L1
);
291 PUTWORD(p
,1); /* Info level 1 */ /* add level 0 */
292 PUTWORD(p
,0xFFE0); /* Return buffer size */
295 param
, PTR_DIFF(p
,param
),8,
296 NULL
, 0, 0xFFE0 /* data area size */,
299 res
= GETRES(rparam
);
300 cli
->rap_error
= res
;
301 if(cli
->rap_error
== 234)
302 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
303 else if (cli
->rap_error
!= 0) {
304 DEBUG(1,("NetGroupEnum gave error %d\n", cli
->rap_error
));
309 if (res
== 0 || res
== ERRmoredata
) {
310 int i
, converter
, count
;
312 p
= rparam
+ WORDSIZE
; /* skip result */
313 GETWORD(p
, converter
);
316 for (i
=0,p
=rdata
;i
<count
;i
++) {
318 char groupname
[RAP_GROUPNAME_LEN
];
320 GETSTRINGF(p
, groupname
, RAP_GROUPNAME_LEN
);
322 GETSTRINGP(p
, comment
, rdata
, converter
);
324 fn(groupname
, comment
, cli
);
327 DEBUG(4,("NetGroupEnum res=%d\n", res
));
330 DEBUG(4,("NetGroupEnum no data returned\n"));
339 int cli_RNetGroupEnum0(struct cli_state
*cli
,
340 void (*fn
)(const char *, void *),
343 char param
[WORDSIZE
/* api number */
344 +sizeof(RAP_NetGroupEnum_REQ
) /* parm string */
345 +sizeof(RAP_GROUP_INFO_L0
) /* return string */
346 +WORDSIZE
/* info level */
347 +WORDSIZE
]; /* buffer size */
351 unsigned int rprcnt
, rdrcnt
;
355 memset(param
, '\0', sizeof(param
));
356 p
= make_header(param
, RAP_WGroupEnum
,
357 RAP_NetGroupEnum_REQ
, RAP_GROUP_INFO_L0
);
358 PUTWORD(p
,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
359 is the resume count, at least
360 that's what smbd believes... */
361 PUTWORD(p
,0xFFE0); /* Return buffer size */
364 param
, PTR_DIFF(p
,param
),8,
365 NULL
, 0, 0xFFE0 /* data area size */,
368 res
= GETRES(rparam
);
369 cli
->rap_error
= res
;
370 if(cli
->rap_error
== 234)
371 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
372 else if (cli
->rap_error
!= 0) {
373 DEBUG(1,("NetGroupEnum gave error %d\n", cli
->rap_error
));
378 if (res
== 0 || res
== ERRmoredata
) {
381 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
384 for (i
=0,p
=rdata
;i
<count
;i
++) {
385 char groupname
[RAP_GROUPNAME_LEN
];
386 GETSTRINGF(p
, groupname
, RAP_GROUPNAME_LEN
);
390 DEBUG(4,("NetGroupEnum res=%d\n", res
));
393 DEBUG(4,("NetGroupEnum no data returned\n"));
402 int cli_NetGroupDelUser(struct cli_state
* cli
, const char *group_name
, const char *user_name
)
407 unsigned int rdrcnt
,rprcnt
;
409 char param
[WORDSIZE
/* api number */
410 +sizeof(RAP_NetGroupDelUser_REQ
) /* parm string */
411 +1 /* no ret string */
412 +RAP_GROUPNAME_LEN
/* group name */
413 +RAP_USERNAME_LEN
]; /* user to del */
415 /* now send a SMBtrans command with api GroupMemberAdd */
416 p
= make_header(param
, RAP_WGroupDelUser
, RAP_NetGroupDelUser_REQ
, NULL
);
417 PUTSTRING(p
,group_name
,RAP_GROUPNAME_LEN
);
418 PUTSTRING(p
,user_name
,RAP_USERNAME_LEN
);
421 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
422 NULL
, 0, 200, /* data, length, maxlen */
423 &rparam
, &rprcnt
, /* return params, length */
424 &rdata
, &rdrcnt
)) /* return data, length */
426 res
= GETRES(rparam
);
433 DEBUG(1, ("Access Denied\n"));
436 DEBUG(1, ("Not supported by server\n"));
439 DEBUG(1, ("Group does not exist\n"));
442 DEBUG(1, ("User does not exist\n"));
445 DEBUG(1, ("User is not in group\n"));
448 DEBUG(4,("NetGroupDelUser res=%d\n", res
));
452 DEBUG(4,("NetGroupDelUser failed\n"));
461 int cli_NetGroupAddUser(struct cli_state
* cli
, const char *group_name
, const char *user_name
)
466 unsigned int rdrcnt
,rprcnt
;
468 char param
[WORDSIZE
/* api number */
469 +sizeof(RAP_NetGroupAddUser_REQ
) /* parm string */
470 +1 /* no ret string */
471 +RAP_GROUPNAME_LEN
/* group name */
472 +RAP_USERNAME_LEN
]; /* user to add */
474 /* now send a SMBtrans command with api GroupMemberAdd */
475 p
= make_header(param
, RAP_WGroupAddUser
, RAP_NetGroupAddUser_REQ
, NULL
);
476 PUTSTRING(p
,group_name
,RAP_GROUPNAME_LEN
);
477 PUTSTRING(p
,user_name
,RAP_USERNAME_LEN
);
480 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
481 NULL
, 0, 200, /* data, length, maxlen */
482 &rparam
, &rprcnt
, /* return params, length */
483 &rdata
, &rdrcnt
)) /* return data, length */
485 res
= GETRES(rparam
);
492 DEBUG(1, ("Access Denied\n"));
495 DEBUG(1, ("Not supported by server\n"));
498 DEBUG(1, ("Group does not exist\n"));
501 DEBUG(1, ("User does not exist\n"));
504 DEBUG(4,("NetGroupAddUser res=%d\n", res
));
508 DEBUG(4,("NetGroupAddUser failed\n"));
518 int cli_NetGroupGetUsers(struct cli_state
* cli
, const char *group_name
, void (*fn
)(const char *, void *), void *state
)
523 unsigned int rdrcnt
,rprcnt
;
525 char param
[WORDSIZE
/* api number */
526 +sizeof(RAP_NetGroupGetUsers_REQ
)/* parm string */
527 +sizeof(RAP_GROUP_USERS_INFO_0
) /* return string */
528 +RAP_GROUPNAME_LEN
/* group name */
529 +WORDSIZE
/* info level */
530 +WORDSIZE
]; /* buffer size */
532 /* now send a SMBtrans command with api GroupGetUsers */
533 p
= make_header(param
, RAP_WGroupGetUsers
,
534 RAP_NetGroupGetUsers_REQ
, RAP_GROUP_USERS_INFO_0
);
535 PUTSTRING(p
,group_name
,RAP_GROUPNAME_LEN
-1);
536 PUTWORD(p
,0); /* info level 0 */
537 PUTWORD(p
,0xFFE0); /* return buffer size */
540 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
541 NULL
, 0, CLI_BUFFER_SIZE
,
544 res
= GETRES(rparam
);
545 cli
->rap_error
= res
;
547 DEBUG(1,("NetGroupGetUsers gave error %d\n", res
));
551 if (res
== 0 || res
== ERRmoredata
) {
554 p
= rparam
+ WORDSIZE
+ WORDSIZE
;
557 for (i
=0,p
=rdata
; i
<count
; i
++) {
558 GETSTRINGF(p
, username
, RAP_USERNAME_LEN
);
562 DEBUG(4,("NetGroupGetUsers res=%d\n", res
));
565 DEBUG(4,("NetGroupGetUsers no data returned\n"));
572 int cli_NetUserGetGroups(struct cli_state
* cli
, const char *user_name
, void (*fn
)(const char *, void *), void *state
)
577 unsigned int rdrcnt
,rprcnt
;
579 char param
[WORDSIZE
/* api number */
580 +sizeof(RAP_NetUserGetGroups_REQ
)/* parm string */
581 +sizeof(RAP_GROUP_USERS_INFO_0
) /* return string */
582 +RAP_USERNAME_LEN
/* user name */
583 +WORDSIZE
/* info level */
584 +WORDSIZE
]; /* buffer size */
586 /* now send a SMBtrans command with api GroupGetUsers */
587 p
= make_header(param
, RAP_WUserGetGroups
,
588 RAP_NetUserGetGroups_REQ
, RAP_GROUP_USERS_INFO_0
);
589 PUTSTRING(p
,user_name
,RAP_USERNAME_LEN
-1);
590 PUTWORD(p
,0); /* info level 0 */
591 PUTWORD(p
,0xFFE0); /* return buffer size */
594 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
595 NULL
, 0, CLI_BUFFER_SIZE
,
598 res
= GETRES(rparam
);
599 cli
->rap_error
= res
;
601 DEBUG(1,("NetUserGetGroups gave error %d\n", res
));
605 if (res
== 0 || res
== ERRmoredata
) {
608 p
= rparam
+ WORDSIZE
+ WORDSIZE
;
611 for (i
=0,p
=rdata
; i
<count
; i
++) {
612 GETSTRINGF(p
, groupname
, RAP_USERNAME_LEN
);
613 fn(groupname
, state
);
616 DEBUG(4,("NetUserGetGroups res=%d\n", res
));
619 DEBUG(4,("NetUserGetGroups no data returned\n"));
627 /****************************************************************************
628 call a NetUserDelete - delete user from remote server
629 ****************************************************************************/
630 int cli_NetUserDelete(struct cli_state
*cli
, const char * user_name
)
635 unsigned int rdrcnt
,rprcnt
;
637 char param
[WORDSIZE
/* api number */
638 +sizeof(RAP_NetGroupDel_REQ
) /* parm string */
639 +1 /* no ret string */
640 +RAP_USERNAME_LEN
/* user to del */
641 +WORDSIZE
]; /* reserved word */
643 /* now send a SMBtrans command with api UserDel */
644 p
= make_header(param
, RAP_WUserDel
, RAP_NetGroupDel_REQ
, NULL
);
645 PUTSTRING(p
, user_name
, RAP_USERNAME_LEN
);
646 PUTWORD(p
,0); /* reserved word MBZ on input */
649 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
650 NULL
, 0, 200, /* data, length, maxlen */
651 &rparam
, &rprcnt
, /* return params, length */
652 &rdata
, &rdrcnt
)) /* return data, length */
654 res
= GETRES(rparam
);
659 else if ((res
== 5) || (res
== 65)) {
660 DEBUG(1, ("Access Denied\n"));
662 else if (res
== 2221) {
663 DEBUG (1, ("User does not exist\n"));
666 DEBUG(4,("NetUserDelete res=%d\n", res
));
670 DEBUG(4,("NetUserDelete failed\n"));
679 /****************************************************************************
680 call a NetUserAdd - add user to remote server
681 ****************************************************************************/
682 int cli_NetUserAdd(struct cli_state
*cli
, RAP_USER_INFO_1
* userinfo
)
690 unsigned int rdrcnt
,rprcnt
;
692 char param
[WORDSIZE
/* api number */
693 +sizeof(RAP_NetUserAdd2_REQ
) /* req string */
694 +sizeof(RAP_USER_INFO_L1
) /* data string */
695 +WORDSIZE
/* info level */
696 +WORDSIZE
/* buffer length */
697 +WORDSIZE
]; /* reserved */
700 /* offset into data of free format strings. Will be updated */
701 /* by PUTSTRINGP macro and end up with total data length. */
702 int soffset
=RAP_USERNAME_LEN
+1 /* user name + pad */
703 + RAP_UPASSWD_LEN
/* password */
704 + DWORDSIZE
/* password age */
705 + WORDSIZE
/* privilege */
706 + DWORDSIZE
/* home dir ptr */
707 + DWORDSIZE
/* comment ptr */
708 + WORDSIZE
/* flags */
709 + DWORDSIZE
; /* login script ptr*/
711 /* now send a SMBtrans command with api NetUserAdd */
712 p
= make_header(param
, RAP_WUserAdd2
,
713 RAP_NetUserAdd2_REQ
, RAP_USER_INFO_L1
);
714 PUTWORD(p
, 1); /* info level */
716 PUTWORD(p
, 0); /* pwencrypt */
717 if(userinfo
->passwrd
)
718 PUTWORD(p
,MIN(strlen(userinfo
->passwrd
), RAP_UPASSWD_LEN
));
720 PUTWORD(p
, 0); /* password length */
723 memset(data
, '\0', soffset
);
725 PUTSTRINGF(p
, userinfo
->user_name
, RAP_USERNAME_LEN
);
726 PUTBYTE(p
, 0); /* pad byte 0 */
727 PUTSTRINGF(p
, userinfo
->passwrd
, RAP_UPASSWD_LEN
);
728 PUTDWORD(p
, 0); /* pw age - n.a. on user add */
729 PUTWORD(p
, userinfo
->priv
);
730 PUTSTRINGP(p
, userinfo
->home_dir
, data
, soffset
);
731 PUTSTRINGP(p
, userinfo
->comment
, data
, soffset
);
732 PUTWORD(p
, userinfo
->userflags
);
733 PUTSTRINGP(p
, userinfo
->logon_script
, data
, soffset
);
736 param
, sizeof(param
), 1024, /* Param, length, maxlen */
737 data
, soffset
, sizeof(data
), /* data, length, maxlen */
738 &rparam
, &rprcnt
, /* return params, length */
739 &rdata
, &rdrcnt
)) /* return data, length */
741 res
= GETRES(rparam
);
746 else if ((res
== 5) || (res
== 65)) {
747 DEBUG(1, ("Access Denied\n"));
749 else if (res
== 2224) {
750 DEBUG (1, ("User already exists\n"));
753 DEBUG(4,("NetUserAdd res=%d\n", res
));
757 DEBUG(4,("NetUserAdd failed\n"));
766 /****************************************************************************
767 call a NetUserEnum - try and list users on a different host
768 ****************************************************************************/
769 int cli_RNetUserEnum(struct cli_state
*cli
, void (*fn
)(const char *, const char *, const char *, const char *, void *), void *state
)
771 char param
[WORDSIZE
/* api number */
772 +sizeof(RAP_NetUserEnum_REQ
) /* parm string */
773 +sizeof(RAP_USER_INFO_L1
) /* return string */
774 +WORDSIZE
/* info level */
775 +WORDSIZE
]; /* buffer size */
779 unsigned int rprcnt
, rdrcnt
;
783 memset(param
, '\0', sizeof(param
));
784 p
= make_header(param
, RAP_WUserEnum
,
785 RAP_NetUserEnum_REQ
, RAP_USER_INFO_L1
);
786 PUTWORD(p
,1); /* Info level 1 */
787 PUTWORD(p
,0xFF00); /* Return buffer size */
789 /* BB Fix handling of large numbers of users to be returned */
791 param
, PTR_DIFF(p
,param
),8,
792 NULL
, 0, CLI_BUFFER_SIZE
,
795 res
= GETRES(rparam
);
796 cli
->rap_error
= res
;
797 if (cli
->rap_error
!= 0) {
798 DEBUG(1,("NetUserEnum gave error %d\n", cli
->rap_error
));
802 if (res
== 0 || res
== ERRmoredata
) {
803 int i
, converter
, count
;
804 char username
[RAP_USERNAME_LEN
];
805 char userpw
[RAP_UPASSWD_LEN
];
806 pstring comment
, homedir
, logonscript
;
808 p
= rparam
+ WORDSIZE
; /* skip result */
809 GETWORD(p
, converter
);
812 for (i
=0,p
=rdata
;i
<count
;i
++) {
813 GETSTRINGF(p
, username
, RAP_USERNAME_LEN
);
815 GETSTRINGF(p
, userpw
, RAP_UPASSWD_LEN
);
816 p
+= DWORDSIZE
; /* skip password age */
817 p
+= WORDSIZE
; /* skip priv: 0=guest, 1=user, 2=admin */
818 GETSTRINGP(p
, homedir
, rdata
, converter
);
819 GETSTRINGP(p
, comment
, rdata
, converter
);
820 p
+= WORDSIZE
; /* skip flags */
821 GETSTRINGP(p
, logonscript
, rdata
, converter
);
823 fn(username
, comment
, homedir
, logonscript
, cli
);
826 DEBUG(4,("NetUserEnum res=%d\n", res
));
829 DEBUG(4,("NetUserEnum no data returned\n"));
838 int cli_RNetUserEnum0(struct cli_state
*cli
,
839 void (*fn
)(const char *, void *),
842 char param
[WORDSIZE
/* api number */
843 +sizeof(RAP_NetUserEnum_REQ
) /* parm string */
844 +sizeof(RAP_USER_INFO_L0
) /* return string */
845 +WORDSIZE
/* info level */
846 +WORDSIZE
]; /* buffer size */
850 unsigned int rprcnt
, rdrcnt
;
854 memset(param
, '\0', sizeof(param
));
855 p
= make_header(param
, RAP_WUserEnum
,
856 RAP_NetUserEnum_REQ
, RAP_USER_INFO_L0
);
857 PUTWORD(p
,0); /* Info level 1 */
858 PUTWORD(p
,0xFF00); /* Return buffer size */
860 /* BB Fix handling of large numbers of users to be returned */
862 param
, PTR_DIFF(p
,param
),8,
863 NULL
, 0, CLI_BUFFER_SIZE
,
866 res
= GETRES(rparam
);
867 cli
->rap_error
= res
;
868 if (cli
->rap_error
!= 0) {
869 DEBUG(1,("NetUserEnum gave error %d\n", cli
->rap_error
));
873 if (res
== 0 || res
== ERRmoredata
) {
875 char username
[RAP_USERNAME_LEN
];
877 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
880 for (i
=0,p
=rdata
;i
<count
;i
++) {
881 GETSTRINGF(p
, username
, RAP_USERNAME_LEN
);
885 DEBUG(4,("NetUserEnum res=%d\n", res
));
888 DEBUG(4,("NetUserEnum no data returned\n"));
897 /****************************************************************************
898 call a NetFileClose2 - close open file on another session to server
899 ****************************************************************************/
900 int cli_NetFileClose(struct cli_state
*cli
, uint32 file_id
)
905 unsigned int rdrcnt
,rprcnt
;
906 char param
[WORDSIZE
/* api number */
907 +sizeof(RAP_WFileClose2_REQ
) /* req string */
908 +1 /* no ret string */
909 +DWORDSIZE
]; /* file ID */
912 /* now send a SMBtrans command with api RNetShareEnum */
913 p
= make_header(param
, RAP_WFileClose2
, RAP_WFileClose2_REQ
, NULL
);
914 PUTDWORD(p
, file_id
);
917 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
918 NULL
, 0, 200, /* data, length, maxlen */
919 &rparam
, &rprcnt
, /* return params, length */
920 &rdata
, &rdrcnt
)) /* return data, length */
922 res
= GETRES(rparam
);
926 } else if (res
== 2314){
927 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
929 DEBUG(4,("NetFileClose2 res=%d\n", res
));
933 DEBUG(4,("NetFileClose2 failed\n"));
942 /****************************************************************************
943 call a NetFileGetInfo - get information about server file opened from other
945 ****************************************************************************/
946 int cli_NetFileGetInfo(struct cli_state
*cli
, uint32 file_id
, void (*fn
)(const char *, const char *, uint16
, uint16
, uint32
))
951 unsigned int rdrcnt
,rprcnt
;
953 char param
[WORDSIZE
/* api number */
954 +sizeof(RAP_WFileGetInfo2_REQ
) /* req string */
955 +sizeof(RAP_FILE_INFO_L3
) /* return string */
956 +DWORDSIZE
/* file ID */
957 +WORDSIZE
/* info level */
958 +WORDSIZE
]; /* buffer size */
960 /* now send a SMBtrans command with api RNetShareEnum */
961 p
= make_header(param
, RAP_WFileGetInfo2
,
962 RAP_WFileGetInfo2_REQ
, RAP_FILE_INFO_L3
);
963 PUTDWORD(p
, file_id
);
964 PUTWORD(p
, 3); /* info level */
965 PUTWORD(p
, 0x1000); /* buffer size */
967 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
968 NULL
, 0, 0x1000, /* data, length, maxlen */
969 &rparam
, &rprcnt
, /* return params, length */
970 &rdata
, &rdrcnt
)) /* return data, length */
972 res
= GETRES(rparam
);
973 if (res
== 0 || res
== ERRmoredata
) {
974 int converter
,id
, perms
, locks
;
975 pstring fpath
, fuser
;
977 p
= rparam
+ WORDSIZE
; /* skip result */
978 GETWORD(p
, converter
);
984 GETSTRINGP(p
, fpath
, rdata
, converter
);
985 GETSTRINGP(p
, fuser
, rdata
, converter
);
987 fn(fpath
, fuser
, perms
, locks
, id
);
989 DEBUG(4,("NetFileGetInfo2 res=%d\n", res
));
993 DEBUG(4,("NetFileGetInfo2 failed\n"));
1002 /****************************************************************************
1003 * Call a NetFileEnum2 - list open files on an SMB server
1005 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
1006 * server listing the files open via the network (and their
1007 * corresponding open instance ids)
1009 * Dependencies: none
1012 * cli - pointer to cli_state structure
1013 * user - if present, return only files opened by this remote user
1014 * base_path - if present, return only files opened below this
1016 * fn - display function to invoke for each entry in the result
1023 ****************************************************************************/
1024 int cli_NetFileEnum(struct cli_state
*cli
, const char * user
,
1025 const char * base_path
,
1026 void (*fn
)(const char *, const char *, uint16
, uint16
,
1029 char *rparam
= NULL
;
1032 unsigned int rdrcnt
,rprcnt
;
1033 char param
[WORDSIZE
/* api number */
1034 +sizeof(RAP_WFileEnum2_REQ
) /* req string */
1035 +sizeof(RAP_FILE_INFO_L3
) /* return string */
1036 +256 /* base path (opt) */
1037 +RAP_USERNAME_LEN
/* user name (opt) */
1038 +WORDSIZE
/* info level */
1039 +WORDSIZE
/* buffer size */
1040 +DWORDSIZE
/* resume key ? */
1041 +DWORDSIZE
]; /* resume key ? */
1044 /* now send a SMBtrans command with api RNetShareEnum */
1045 p
= make_header(param
, RAP_WFileEnum2
,
1046 RAP_WFileEnum2_REQ
, RAP_FILE_INFO_L3
);
1048 PUTSTRING(p
, base_path
, 256);
1049 PUTSTRING(p
, user
, RAP_USERNAME_LEN
);
1050 PUTWORD(p
, 3); /* info level */
1051 PUTWORD(p
, 0xFF00); /* buffer size */
1052 PUTDWORD(p
, 0); /* zero out the resume key */
1053 PUTDWORD(p
, 0); /* or is this one the resume key? */
1056 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
1057 NULL
, 0, 0xFF00, /* data, length, maxlen */
1058 &rparam
, &rprcnt
, /* return params, length */
1059 &rdata
, &rdrcnt
)) /* return data, length */
1061 int res
= GETRES(rparam
);
1063 if (res
== 0 || res
== ERRmoredata
) {
1066 p
= rparam
+ WORDSIZE
; /* skip result */
1067 GETWORD(p
, converter
);
1071 for (i
=0; i
<count
; i
++) {
1072 int id
, perms
, locks
;
1073 pstring fpath
, fuser
;
1078 GETSTRINGP(p
, fpath
, rdata
, converter
);
1079 GETSTRINGP(p
, fuser
, rdata
, converter
);
1081 fn(fpath
, fuser
, perms
, locks
, id
);
1082 } /* BB fix ERRmoredata case to send resume request */
1084 DEBUG(4,("NetFileEnum2 res=%d\n", res
));
1087 DEBUG(4,("NetFileEnum2 failed\n"));
1096 /****************************************************************************
1097 call a NetShareAdd - share/export directory on remote server
1098 ****************************************************************************/
1099 int cli_NetShareAdd(struct cli_state
*cli
, RAP_SHARE_INFO_2
* sinfo
)
1101 char *rparam
= NULL
;
1104 unsigned int rdrcnt
,rprcnt
;
1106 char param
[WORDSIZE
/* api number */
1107 +sizeof(RAP_WShareAdd_REQ
) /* req string */
1108 +sizeof(RAP_SHARE_INFO_L2
) /* return string */
1109 +WORDSIZE
/* info level */
1110 +WORDSIZE
]; /* reserved word */
1112 /* offset to free format string section following fixed length data. */
1113 /* will be updated by PUTSTRINGP macro and will end up with total len */
1114 int soffset
= RAP_SHARENAME_LEN
+ 1 /* share name + pad */
1115 + WORDSIZE
/* share type */
1116 + DWORDSIZE
/* comment pointer */
1117 + WORDSIZE
/* permissions */
1118 + WORDSIZE
/* max users */
1119 + WORDSIZE
/* active users */
1120 + DWORDSIZE
/* share path */
1121 + RAP_SPASSWD_LEN
+ 1; /* share password + pad */
1123 memset(param
,'\0',sizeof(param
));
1124 /* now send a SMBtrans command with api RNetShareAdd */
1125 p
= make_header(param
, RAP_WshareAdd
,
1126 RAP_WShareAdd_REQ
, RAP_SHARE_INFO_L2
);
1127 PUTWORD(p
, 2); /* info level */
1128 PUTWORD(p
, 0); /* reserved word 0 */
1131 PUTSTRINGF(p
, sinfo
->share_name
, RAP_SHARENAME_LEN
);
1132 PUTBYTE(p
, 0); /* pad byte 0 */
1134 PUTWORD(p
, sinfo
->share_type
);
1135 PUTSTRINGP(p
, sinfo
->comment
, data
, soffset
);
1136 PUTWORD(p
, sinfo
->perms
);
1137 PUTWORD(p
, sinfo
->maximum_users
);
1138 PUTWORD(p
, sinfo
->active_users
);
1139 PUTSTRINGP(p
, sinfo
->path
, data
, soffset
);
1140 PUTSTRINGF(p
, sinfo
->password
, RAP_SPASSWD_LEN
);
1141 SCVAL(p
,-1,0x0A); /* required 0x0A at end of password */
1144 param
, sizeof(param
), 1024, /* Param, length, maxlen */
1145 data
, soffset
, sizeof(data
), /* data, length, maxlen */
1146 &rparam
, &rprcnt
, /* return params, length */
1147 &rdata
, &rdrcnt
)) /* return data, length */
1149 res
= rparam
? SVAL(rparam
,0) : -1;
1155 DEBUG(4,("NetShareAdd res=%d\n", res
));
1159 DEBUG(4,("NetShareAdd failed\n"));
1167 /****************************************************************************
1168 call a NetShareDelete - unshare exported directory on remote server
1169 ****************************************************************************/
1170 int cli_NetShareDelete(struct cli_state
*cli
, const char * share_name
)
1172 char *rparam
= NULL
;
1175 unsigned int rdrcnt
,rprcnt
;
1177 char param
[WORDSIZE
/* api number */
1178 +sizeof(RAP_WShareDel_REQ
) /* req string */
1179 +1 /* no ret string */
1180 +RAP_SHARENAME_LEN
/* share to del */
1181 +WORDSIZE
]; /* reserved word */
1184 /* now send a SMBtrans command with api RNetShareDelete */
1185 p
= make_header(param
, RAP_WshareDel
, RAP_WShareDel_REQ
, NULL
);
1186 PUTSTRING(p
,share_name
,RAP_SHARENAME_LEN
);
1187 PUTWORD(p
,0); /* reserved word MBZ on input */
1190 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
1191 NULL
, 0, 200, /* data, length, maxlen */
1192 &rparam
, &rprcnt
, /* return params, length */
1193 &rdata
, &rdrcnt
)) /* return data, length */
1195 res
= GETRES(rparam
);
1201 DEBUG(4,("NetShareDelete res=%d\n", res
));
1205 DEBUG(4,("NetShareDelete failed\n"));
1213 /*************************************************************************
1215 * Function Name: cli_get_pdc_name
1217 * PURPOSE: Remotes a NetServerEnum API call to the current server
1218 * requesting the name of a server matching the server
1219 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1221 * Dependencies: none
1224 * cli - pointer to cli_state structure
1225 * workgroup - pointer to string containing name of domain
1226 * pdc_name - pointer to string that will contain PDC name
1227 * on successful return
1233 ************************************************************************/
1234 BOOL
cli_get_pdc_name(struct cli_state
*cli
, char *workgroup
, char *pdc_name
)
1236 char *rparam
= NULL
;
1238 unsigned int rdrcnt
,rprcnt
;
1240 char param
[WORDSIZE
/* api number */
1241 +sizeof(RAP_NetServerEnum2_REQ
) /* req string */
1242 +sizeof(RAP_SERVER_INFO_L1
) /* return string */
1243 +WORDSIZE
/* info level */
1244 +WORDSIZE
/* buffer size */
1245 +DWORDSIZE
/* server type */
1246 +RAP_MACHNAME_LEN
]; /* workgroup */
1251 /* send a SMBtrans command with api NetServerEnum */
1252 p
= make_header(param
, RAP_NetServerEnum2
,
1253 RAP_NetServerEnum2_REQ
, RAP_SERVER_INFO_L1
);
1254 PUTWORD(p
, 1); /* info level */
1255 PUTWORD(p
, CLI_BUFFER_SIZE
);
1256 PUTDWORD(p
, SV_TYPE_DOMAIN_CTRL
);
1257 PUTSTRING(p
, workgroup
, RAP_MACHNAME_LEN
);
1260 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1261 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1262 &rparam
, &rprcnt
, /* return params, return size */
1263 &rdata
, &rdrcnt
/* return data, return size */
1265 cli
->rap_error
= GETRES(rparam
);
1268 * We only really care to copy a name if the
1269 * API succeeded and we got back a name.
1271 if (cli
->rap_error
== 0) {
1272 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
1277 GETSTRING(p
, pdc_name
);
1280 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1281 "Error was : %s.\n", cli
->desthost
, cli_errstr(cli
) ));
1292 /*************************************************************************
1294 * Function Name: cli_get_server_domain
1296 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1297 * requesting wksta_info_10 level information to determine
1298 * the domain the server belongs to. On success, this
1299 * routine sets the server_domain field in the cli_state structure
1300 * to the server's domain name.
1302 * Dependencies: none
1305 * cli - pointer to cli_state structure
1311 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1313 ************************************************************************/
1314 BOOL
cli_get_server_domain(struct cli_state
*cli
)
1316 char *rparam
= NULL
;
1318 unsigned int rdrcnt
,rprcnt
;
1320 char param
[WORDSIZE
/* api number */
1321 +sizeof(RAP_WWkstaGetInfo_REQ
) /* req string */
1322 +sizeof(RAP_WKSTA_INFO_L10
) /* return string */
1323 +WORDSIZE
/* info level */
1324 +WORDSIZE
]; /* buffer size */
1327 /* send a SMBtrans command with api NetWkstaGetInfo */
1328 p
= make_header(param
, RAP_WWkstaGetInfo
,
1329 RAP_WWkstaGetInfo_REQ
, RAP_WKSTA_INFO_L10
);
1330 PUTWORD(p
, 10); /* info level */
1331 PUTWORD(p
, CLI_BUFFER_SIZE
);
1333 if (cli_api(cli
, param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1334 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1335 &rparam
, &rprcnt
, /* return params, return size */
1336 &rdata
, &rdrcnt
)) { /* return data, return size */
1337 res
= GETRES(rparam
);
1343 p
= rparam
+ WORDSIZE
;
1344 GETWORD(p
, converter
);
1346 p
= rdata
+ DWORDSIZE
+ DWORDSIZE
; /* skip computer & user names */
1347 GETSTRINGP(p
, cli
->server_domain
, rdata
, converter
);
1358 /*************************************************************************
1360 * Function Name: cli_get_server_type
1362 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1363 * requesting server_info_1 level information to retrieve
1366 * Dependencies: none
1369 * cli - pointer to cli_state structure
1370 * pstype - pointer to uint32 to contain returned server type
1376 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1378 ************************************************************************/
1379 BOOL
cli_get_server_type(struct cli_state
*cli
, uint32
*pstype
)
1381 char *rparam
= NULL
;
1383 unsigned int rdrcnt
,rprcnt
;
1385 char param
[WORDSIZE
/* api number */
1386 +sizeof(RAP_WserverGetInfo_REQ
) /* req string */
1387 +sizeof(RAP_SERVER_INFO_L1
) /* return string */
1388 +WORDSIZE
/* info level */
1389 +WORDSIZE
]; /* buffer size */
1392 /* send a SMBtrans command with api NetServerGetInfo */
1393 p
= make_header(param
, RAP_WserverGetInfo
,
1394 RAP_WserverGetInfo_REQ
, RAP_SERVER_INFO_L1
);
1395 PUTWORD(p
, 1); /* info level */
1396 PUTWORD(p
, CLI_BUFFER_SIZE
);
1399 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1400 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1401 &rparam
, &rprcnt
, /* return params, return size */
1402 &rdata
, &rdrcnt
/* return data, return size */
1405 res
= GETRES(rparam
);
1407 if (res
== 0 || res
== ERRmoredata
) {
1409 *pstype
= IVAL(p
,18) & ~SV_TYPE_LOCAL_LIST_ONLY
;
1416 return(res
== 0 || res
== ERRmoredata
);
1419 BOOL
cli_get_server_name(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
1422 char *rparam
= NULL
;
1424 unsigned int rdrcnt
,rprcnt
;
1426 char param
[WORDSIZE
/* api number */
1427 +sizeof(RAP_WserverGetInfo_REQ
) /* req string */
1428 +sizeof(RAP_SERVER_INFO_L1
) /* return string */
1429 +WORDSIZE
/* info level */
1430 +WORDSIZE
]; /* buffer size */
1434 /* send a SMBtrans command with api NetServerGetInfo */
1435 p
= make_header(param
, RAP_WserverGetInfo
,
1436 RAP_WserverGetInfo_REQ
, RAP_SERVER_INFO_L1
);
1437 PUTWORD(p
, 1); /* info level */
1438 PUTWORD(p
, CLI_BUFFER_SIZE
);
1441 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1442 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1443 &rparam
, &rprcnt
, /* return params, return size */
1444 &rdata
, &rdrcnt
/* return data, return size */
1449 if (GETRES(rparam
) != 0) {
1454 DEBUG(10, ("invalid data count %d, expected >= 16\n", rdrcnt
));
1458 if (pull_ascii(tmp
, rdata
, sizeof(tmp
)-1, 16, STR_TERMINATE
) == -1) {
1459 DEBUG(10, ("pull_ascii failed\n"));
1463 if (!(*servername
= talloc_strdup(mem_ctx
, tmp
))) {
1464 DEBUG(1, ("talloc_strdup failed\n"));
1476 /*************************************************************************
1478 * Function Name: cli_ns_check_server_type
1480 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1481 * requesting server_info_0 level information of machines
1482 * matching the given server type. If the returned server
1483 * list contains the machine name contained in cli->desthost
1484 * then we conclude the server type checks out. This routine
1485 * is useful to retrieve list of server's of a certain
1486 * type when all you have is a null session connection and
1487 * can't remote API calls such as NetWkstaGetInfo or
1490 * Dependencies: none
1493 * cli - pointer to cli_state structure
1494 * workgroup - pointer to string containing domain
1495 * stype - server type
1501 ************************************************************************/
1502 BOOL
cli_ns_check_server_type(struct cli_state
*cli
, char *workgroup
, uint32 stype
)
1504 char *rparam
= NULL
;
1506 unsigned int rdrcnt
,rprcnt
;
1508 char param
[WORDSIZE
/* api number */
1509 +sizeof(RAP_NetServerEnum2_REQ
) /* req string */
1510 +sizeof(RAP_SERVER_INFO_L0
) /* return string */
1511 +WORDSIZE
/* info level */
1512 +WORDSIZE
/* buffer size */
1513 +DWORDSIZE
/* server type */
1514 +RAP_MACHNAME_LEN
]; /* workgroup */
1515 BOOL found_server
= False
;
1518 /* send a SMBtrans command with api NetServerEnum */
1519 p
= make_header(param
, RAP_NetServerEnum2
,
1520 RAP_NetServerEnum2_REQ
, RAP_SERVER_INFO_L0
);
1521 PUTWORD(p
, 0); /* info level 0 */
1522 PUTWORD(p
, CLI_BUFFER_SIZE
);
1524 PUTSTRING(p
, workgroup
, RAP_MACHNAME_LEN
);
1527 param
, PTR_DIFF(p
,param
), 8, /* params, length, max */
1528 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1529 &rparam
, &rprcnt
, /* return params, return size */
1530 &rdata
, &rdrcnt
/* return data, return size */
1533 res
= GETRES(rparam
);
1534 cli
->rap_error
= res
;
1536 if (res
== 0 || res
== ERRmoredata
) {
1539 p
= rparam
+ WORDSIZE
+ WORDSIZE
;
1543 for (i
= 0;i
< count
;i
++, p
+= 16) {
1544 char ret_server
[RAP_MACHNAME_LEN
];
1546 GETSTRINGF(p
, ret_server
, RAP_MACHNAME_LEN
);
1547 if (strequal(ret_server
, cli
->desthost
)) {
1548 found_server
= True
;
1554 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1555 "Error was : %s.\n", cli
->desthost
, cli_errstr(cli
) ));
1562 return found_server
;
1566 /****************************************************************************
1567 perform a NetWkstaUserLogoff
1568 ****************************************************************************/
1569 BOOL
cli_NetWkstaUserLogoff(struct cli_state
*cli
,char *user
, char *workstation
)
1571 char *rparam
= NULL
;
1574 unsigned int rdrcnt
,rprcnt
;
1575 char param
[WORDSIZE
/* api number */
1576 +sizeof(RAP_NetWkstaUserLogoff_REQ
) /* req string */
1577 +sizeof(RAP_USER_LOGOFF_INFO_L1
) /* return string */
1578 +RAP_USERNAME_LEN
+1 /* user name+pad */
1579 +RAP_MACHNAME_LEN
/* wksta name */
1580 +WORDSIZE
/* buffer size */
1581 +WORDSIZE
]; /* buffer size? */
1584 memset(param
, 0, sizeof(param
));
1586 /* send a SMBtrans command with api NetWkstaUserLogoff */
1587 p
= make_header(param
, RAP_WWkstaUserLogoff
,
1588 RAP_NetWkstaUserLogoff_REQ
, RAP_USER_LOGOFF_INFO_L1
);
1589 PUTDWORD(p
, 0); /* Null pointer */
1590 PUTDWORD(p
, 0); /* Null pointer */
1591 fstrcpy(upperbuf
, user
);
1592 strupper_m(upperbuf
);
1593 PUTSTRINGF(p
, upperbuf
, RAP_USERNAME_LEN
);
1594 p
++; /* strange format, but ok */
1595 fstrcpy(upperbuf
, workstation
);
1596 strupper_m(upperbuf
);
1597 PUTSTRINGF(p
, upperbuf
, RAP_MACHNAME_LEN
);
1598 PUTWORD(p
, CLI_BUFFER_SIZE
);
1599 PUTWORD(p
, CLI_BUFFER_SIZE
);
1602 param
, PTR_DIFF(p
,param
),1024, /* param, length, max */
1603 NULL
, 0, CLI_BUFFER_SIZE
, /* data, length, max */
1604 &rparam
, &rprcnt
, /* return params, return size */
1605 &rdata
, &rdrcnt
/* return data, return size */
1607 cli
->rap_error
= GETRES(rparam
);
1609 if (cli
->rap_error
!= 0) {
1610 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli
->rap_error
));
1616 return (cli
->rap_error
== 0);
1619 int cli_NetPrintQEnum(struct cli_state
*cli
,
1620 void (*qfn
)(const char*,uint16
,uint16
,uint16
,const char*,const char*,const char*,const char*,const char*,uint16
,uint16
),
1621 void (*jfn
)(uint16
,const char*,const char*,const char*,const char*,uint16
,uint16
,const char*,uint
,uint
,const char*))
1623 char param
[WORDSIZE
/* api number */
1624 +sizeof(RAP_NetPrintQEnum_REQ
) /* req string */
1625 +sizeof(RAP_PRINTQ_INFO_L2
) /* return string */
1626 +WORDSIZE
/* info level */
1627 +WORDSIZE
/* buffer size */
1628 +sizeof(RAP_SMB_PRINT_JOB_L1
)]; /* more ret data */
1630 char *rparam
= NULL
;
1632 unsigned int rprcnt
, rdrcnt
;
1636 memset(param
, '\0',sizeof(param
));
1637 p
= make_header(param
, RAP_WPrintQEnum
,
1638 RAP_NetPrintQEnum_REQ
, RAP_PRINTQ_INFO_L2
);
1639 PUTWORD(p
,2); /* Info level 2 */
1640 PUTWORD(p
,0xFFE0); /* Return buffer size */
1641 PUTSTRING(p
, RAP_SMB_PRINT_JOB_L1
, 0);
1644 param
, PTR_DIFF(p
,param
),1024,
1645 NULL
, 0, CLI_BUFFER_SIZE
,
1648 res
= GETRES(rparam
);
1649 cli
->rap_error
= res
;
1651 DEBUG(1,("NetPrintQEnum gave error %d\n", res
));
1656 if (res
== 0 || res
== ERRmoredata
) {
1657 int i
, converter
, count
;
1659 p
= rparam
+ WORDSIZE
;
1660 GETWORD(p
, converter
);
1664 for (i
=0;i
<count
;i
++) {
1665 pstring qname
, sep_file
, print_proc
, dest
, parms
, comment
;
1666 uint16 jobcount
, priority
, start_time
, until_time
, status
;
1668 GETSTRINGF(p
, qname
, RAP_SHARENAME_LEN
);
1670 GETWORD(p
, priority
);
1671 GETWORD(p
, start_time
);
1672 GETWORD(p
, until_time
);
1673 GETSTRINGP(p
, sep_file
, rdata
, converter
);
1674 GETSTRINGP(p
, print_proc
, rdata
, converter
);
1675 GETSTRINGP(p
, dest
, rdata
, converter
);
1676 GETSTRINGP(p
, parms
, rdata
, converter
);
1677 GETSTRINGP(p
, parms
, comment
, converter
);
1679 GETWORD(p
, jobcount
);
1681 qfn(qname
, priority
, start_time
, until_time
, sep_file
, print_proc
,
1682 dest
, parms
, comment
, status
, jobcount
);
1686 for (j
=0;j
<jobcount
;j
++) {
1687 uint16 jid
, pos
, fsstatus
;
1688 pstring ownername
, notifyname
, datatype
, jparms
, jstatus
, jcomment
;
1689 unsigned int submitted
, jsize
;
1692 GETSTRINGF(p
, ownername
, RAP_USERNAME_LEN
);
1694 GETSTRINGF(p
, notifyname
, RAP_MACHNAME_LEN
);
1695 GETSTRINGF(p
, datatype
, RAP_DATATYPE_LEN
);
1696 GETSTRINGP(p
, jparms
, rdata
, converter
);
1698 GETWORD(p
, fsstatus
);
1699 GETSTRINGP(p
, jstatus
, rdata
, converter
);
1700 GETDWORD(p
, submitted
);
1702 GETSTRINGP(p
, jcomment
, rdata
, converter
);
1704 jfn(jid
, ownername
, notifyname
, datatype
, jparms
, pos
, fsstatus
,
1705 jstatus
, submitted
, jsize
, jcomment
);
1710 DEBUG(4,("NetPrintQEnum res=%d\n", res
));
1713 DEBUG(4,("NetPrintQEnum no data returned\n"));
1722 int cli_NetPrintQGetInfo(struct cli_state
*cli
, const char *printer
,
1723 void (*qfn
)(const char*,uint16
,uint16
,uint16
,const char*,const char*,const char*,const char*,const char*,uint16
,uint16
),
1724 void (*jfn
)(uint16
,const char*,const char*,const char*,const char*,uint16
,uint16
,const char*,uint
,uint
,const char*))
1726 char param
[WORDSIZE
/* api number */
1727 +sizeof(RAP_NetPrintQGetInfo_REQ
) /* req string */
1728 +sizeof(RAP_PRINTQ_INFO_L2
) /* return string */
1729 +RAP_SHARENAME_LEN
/* printer name */
1730 +WORDSIZE
/* info level */
1731 +WORDSIZE
/* buffer size */
1732 +sizeof(RAP_SMB_PRINT_JOB_L1
)]; /* more ret data */
1734 char *rparam
= NULL
;
1736 unsigned int rprcnt
, rdrcnt
;
1740 memset(param
, '\0',sizeof(param
));
1741 p
= make_header(param
, RAP_WPrintQGetInfo
,
1742 RAP_NetPrintQGetInfo_REQ
, RAP_PRINTQ_INFO_L2
);
1743 PUTSTRING(p
, printer
, RAP_SHARENAME_LEN
-1);
1744 PUTWORD(p
, 2); /* Info level 2 */
1745 PUTWORD(p
,0xFFE0); /* Return buffer size */
1746 PUTSTRING(p
, RAP_SMB_PRINT_JOB_L1
, 0);
1749 param
, PTR_DIFF(p
,param
),1024,
1750 NULL
, 0, CLI_BUFFER_SIZE
,
1753 res
= GETRES(rparam
);
1754 cli
->rap_error
= res
;
1756 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res
));
1761 if (res
== 0 || res
== ERRmoredata
) {
1762 int rsize
, converter
;
1763 pstring qname
, sep_file
, print_proc
, dest
, parms
, comment
;
1764 uint16 jobcount
, priority
, start_time
, until_time
, status
;
1766 p
= rparam
+ WORDSIZE
;
1767 GETWORD(p
, converter
);
1771 GETSTRINGF(p
, qname
, RAP_SHARENAME_LEN
);
1773 GETWORD(p
, priority
);
1774 GETWORD(p
, start_time
);
1775 GETWORD(p
, until_time
);
1776 GETSTRINGP(p
, sep_file
, rdata
, converter
);
1777 GETSTRINGP(p
, print_proc
, rdata
, converter
);
1778 GETSTRINGP(p
, dest
, rdata
, converter
);
1779 GETSTRINGP(p
, parms
, rdata
, converter
);
1780 GETSTRINGP(p
, comment
, rdata
, converter
);
1782 GETWORD(p
, jobcount
);
1783 qfn(qname
, priority
, start_time
, until_time
, sep_file
, print_proc
,
1784 dest
, parms
, comment
, status
, jobcount
);
1787 for (j
=0;(j
<jobcount
)&&(PTR_DIFF(p
,rdata
)< rsize
);j
++) {
1788 uint16 jid
, pos
, fsstatus
;
1789 pstring ownername
, notifyname
, datatype
, jparms
, jstatus
, jcomment
;
1790 unsigned int submitted
, jsize
;
1793 GETSTRINGF(p
, ownername
, RAP_USERNAME_LEN
);
1795 GETSTRINGF(p
, notifyname
, RAP_MACHNAME_LEN
);
1796 GETSTRINGF(p
, datatype
, RAP_DATATYPE_LEN
);
1797 GETSTRINGP(p
, jparms
, rdata
, converter
);
1799 GETWORD(p
, fsstatus
);
1800 GETSTRINGP(p
, jstatus
, rdata
, converter
);
1801 GETDWORD(p
, submitted
);
1803 GETSTRINGP(p
, jcomment
, rdata
, converter
);
1805 jfn(jid
, ownername
, notifyname
, datatype
, jparms
, pos
, fsstatus
,
1806 jstatus
, submitted
, jsize
, jcomment
);
1810 DEBUG(4,("NetPrintQGetInfo res=%d\n", res
));
1813 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1822 /****************************************************************************
1823 call a NetServiceEnum - list running services on a different host
1824 ****************************************************************************/
1825 int cli_RNetServiceEnum(struct cli_state
*cli
, void (*fn
)(const char *, const char *, void *), void *state
)
1827 char param
[WORDSIZE
/* api number */
1828 +sizeof(RAP_NetServiceEnum_REQ
) /* parm string */
1829 +sizeof(RAP_SERVICE_INFO_L2
) /* return string */
1830 +WORDSIZE
/* info level */
1831 +WORDSIZE
]; /* buffer size */
1833 char *rparam
= NULL
;
1835 unsigned int rprcnt
, rdrcnt
;
1839 memset(param
, '\0', sizeof(param
));
1840 p
= make_header(param
, RAP_WServiceEnum
,
1841 RAP_NetServiceEnum_REQ
, RAP_SERVICE_INFO_L2
);
1842 PUTWORD(p
,2); /* Info level 2 */
1843 PUTWORD(p
,0xFFE0); /* Return buffer size */
1846 param
, PTR_DIFF(p
,param
),8,
1847 NULL
, 0, 0xFFE0 /* data area size */,
1850 res
= GETRES(rparam
);
1851 cli
->rap_error
= res
;
1852 if(cli
->rap_error
== 234)
1853 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1854 else if (cli
->rap_error
!= 0) {
1855 DEBUG(1,("NetServiceEnum gave error %d\n", cli
->rap_error
));
1860 if (res
== 0 || res
== ERRmoredata
) {
1863 p
= rparam
+ WORDSIZE
+ WORDSIZE
; /* skip result and converter */
1866 for (i
=0,p
=rdata
;i
<count
;i
++) {
1868 char servicename
[RAP_SRVCNAME_LEN
];
1870 GETSTRINGF(p
, servicename
, RAP_SRVCNAME_LEN
);
1871 p
+=8; /* pass status words */
1872 GETSTRINGF(p
, comment
, RAP_SRVCCMNT_LEN
);
1874 fn(servicename
, comment
, cli
); /* BB add status too */
1877 DEBUG(4,("NetServiceEnum res=%d\n", res
));
1880 DEBUG(4,("NetServiceEnum no data returned\n"));
1890 /****************************************************************************
1891 call a NetSessionEnum - list workstations with sessions to an SMB server
1892 ****************************************************************************/
1893 int cli_NetSessionEnum(struct cli_state
*cli
, void (*fn
)(char *, char *, uint16
, uint16
, uint16
, uint
, uint
, uint
, char *))
1895 char param
[WORDSIZE
/* api number */
1896 +sizeof(RAP_NetSessionEnum_REQ
) /* parm string */
1897 +sizeof(RAP_SESSION_INFO_L2
) /* return string */
1898 +WORDSIZE
/* info level */
1899 +WORDSIZE
]; /* buffer size */
1901 char *rparam
= NULL
;
1903 unsigned int rprcnt
, rdrcnt
;
1906 memset(param
, '\0', sizeof(param
));
1907 p
= make_header(param
, RAP_WsessionEnum
,
1908 RAP_NetSessionEnum_REQ
, RAP_SESSION_INFO_L2
);
1909 PUTWORD(p
,2); /* Info level 2 */
1910 PUTWORD(p
,0xFF); /* Return buffer size */
1913 param
, PTR_DIFF(p
,param
),8,
1914 NULL
, 0, CLI_BUFFER_SIZE
,
1917 res
= GETRES(rparam
);
1918 cli
->rap_error
= res
;
1920 DEBUG(1,("NetSessionEnum gave error %d\n", res
));
1925 if (res
== 0 || res
== ERRmoredata
) {
1926 int i
, converter
, count
;
1928 p
= rparam
+ WORDSIZE
;
1929 GETWORD(p
, converter
);
1932 for (i
=0,p
=rdata
;i
<count
;i
++) {
1933 pstring wsname
, username
, clitype_name
;
1934 uint16 num_conns
, num_opens
, num_users
;
1935 unsigned int sess_time
, idle_time
, user_flags
;
1937 GETSTRINGP(p
, wsname
, rdata
, converter
);
1938 GETSTRINGP(p
, username
, rdata
, converter
);
1939 GETWORD(p
, num_conns
);
1940 GETWORD(p
, num_opens
);
1941 GETWORD(p
, num_users
);
1942 GETDWORD(p
, sess_time
);
1943 GETDWORD(p
, idle_time
);
1944 GETDWORD(p
, user_flags
);
1945 GETSTRINGP(p
, clitype_name
, rdata
, converter
);
1947 fn(wsname
, username
, num_conns
, num_opens
, num_users
, sess_time
,
1948 idle_time
, user_flags
, clitype_name
);
1952 DEBUG(4,("NetSessionEnum res=%d\n", res
));
1955 DEBUG(4,("NetSesssionEnum no data returned\n"));
1964 /****************************************************************************
1965 Call a NetSessionGetInfo - get information about other session to an SMB server.
1966 ****************************************************************************/
1968 int cli_NetSessionGetInfo(struct cli_state
*cli
, const char *workstation
, void (*fn
)(const char *, const char *, uint16
, uint16
, uint16
, uint
, uint
, uint
, const char *))
1970 char param
[WORDSIZE
/* api number */
1971 +sizeof(RAP_NetSessionGetInfo_REQ
) /* req string */
1972 +sizeof(RAP_SESSION_INFO_L2
) /* return string */
1973 +RAP_MACHNAME_LEN
/* wksta name */
1974 +WORDSIZE
/* info level */
1975 +WORDSIZE
]; /* buffer size */
1977 char *rparam
= NULL
;
1979 unsigned int rprcnt
, rdrcnt
;
1983 memset(param
, '\0', sizeof(param
));
1984 p
= make_header(param
, RAP_WsessionGetInfo
,
1985 RAP_NetSessionGetInfo_REQ
, RAP_SESSION_INFO_L2
);
1986 PUTSTRING(p
, workstation
, RAP_MACHNAME_LEN
-1);
1987 PUTWORD(p
,2); /* Info level 2 */
1988 PUTWORD(p
,0xFF); /* Return buffer size */
1991 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
1992 NULL
, 0, CLI_BUFFER_SIZE
,
1995 cli
->rap_error
= SVAL(rparam
,0);
1996 if (cli
->rap_error
!= 0) {
1997 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli
->rap_error
));
2002 res
= GETRES(rparam
);
2004 if (res
== 0 || res
== ERRmoredata
) {
2006 pstring wsname
, username
, clitype_name
;
2007 uint16 num_conns
, num_opens
, num_users
;
2008 unsigned int sess_time
, idle_time
, user_flags
;
2010 p
= rparam
+ WORDSIZE
;
2011 GETWORD(p
, converter
);
2012 p
+= WORDSIZE
; /* skip rsize */
2015 GETSTRINGP(p
, wsname
, rdata
, converter
);
2016 GETSTRINGP(p
, username
, rdata
, converter
);
2017 GETWORD(p
, num_conns
);
2018 GETWORD(p
, num_opens
);
2019 GETWORD(p
, num_users
);
2020 GETDWORD(p
, sess_time
);
2021 GETDWORD(p
, idle_time
);
2022 GETDWORD(p
, user_flags
);
2023 GETSTRINGP(p
, clitype_name
, rdata
, converter
);
2025 fn(wsname
, username
, num_conns
, num_opens
, num_users
, sess_time
,
2026 idle_time
, user_flags
, clitype_name
);
2028 DEBUG(4,("NetSessionGetInfo res=%d\n", res
));
2031 DEBUG(4,("NetSessionGetInfo no data returned\n"));
2040 /****************************************************************************
2041 call a NetSessionDel - close a session to an SMB server
2042 ****************************************************************************/
2043 int cli_NetSessionDel(struct cli_state
*cli
, const char *workstation
)
2045 char param
[WORDSIZE
/* api number */
2046 +sizeof(RAP_NetSessionDel_REQ
) /* req string */
2047 +1 /* no return string */
2048 +RAP_MACHNAME_LEN
/* workstation name */
2049 +WORDSIZE
]; /* reserved (0) */
2051 char *rparam
= NULL
;
2053 unsigned int rprcnt
, rdrcnt
;
2056 memset(param
, '\0', sizeof(param
));
2057 p
= make_header(param
, RAP_WsessionDel
, RAP_NetSessionDel_REQ
, NULL
);
2058 PUTSTRING(p
, workstation
, RAP_MACHNAME_LEN
-1);
2059 PUTWORD(p
,0); /* reserved word of 0 */
2061 param
, PTR_DIFF(p
,param
), 1024, /* Param, length, maxlen */
2062 NULL
, 0, 200, /* data, length, maxlen */
2063 &rparam
, &rprcnt
, /* return params, length */
2064 &rdata
, &rdrcnt
)) /* return data, length */
2066 res
= GETRES(rparam
);
2067 cli
->rap_error
= res
;
2073 DEBUG(4,("NetFileClose2 res=%d\n", res
));
2077 DEBUG(4,("NetFileClose2 failed\n"));
2087 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
))
2089 char param
[WORDSIZE
/* api number */
2090 +sizeof(RAP_NetConnectionEnum_REQ
) /* req string */
2091 +sizeof(RAP_CONNECTION_INFO_L1
) /* return string */
2092 +RAP_MACHNAME_LEN
/* wksta name */
2093 +WORDSIZE
/* info level */
2094 +WORDSIZE
]; /* buffer size */
2096 char *rparam
= NULL
;
2098 unsigned int rprcnt
, rdrcnt
;
2101 memset(param
, '\0', sizeof(param
));
2102 p
= make_header(param
, RAP_WconnectionEnum
,
2103 RAP_NetConnectionEnum_REQ
, RAP_CONNECTION_INFO_L1
);
2104 PUTSTRING(p
, qualifier
, RAP_MACHNAME_LEN
-1);/* Workstation name */
2105 PUTWORD(p
,1); /* Info level 1 */
2106 PUTWORD(p
,0xFFE0); /* Return buffer size */
2109 param
, PTR_DIFF(p
,param
),PTR_DIFF(p
,param
),
2110 NULL
, 0, CLI_BUFFER_SIZE
,
2113 res
= GETRES(rparam
);
2114 cli
->rap_error
= res
;
2116 DEBUG(1,("NetConnectionEnum gave error %d\n", res
));
2120 if (res
== 0 || res
== ERRmoredata
) {
2121 int i
, converter
, count
;
2123 p
= rparam
+ WORDSIZE
;
2124 GETWORD(p
, converter
);
2127 for (i
=0,p
=rdata
;i
<count
;i
++) {
2128 pstring netname
, username
;
2129 uint16 conn_id
, conn_type
, num_opens
, num_users
;
2130 unsigned int conn_time
;
2133 GETWORD(p
,conn_type
);
2134 GETWORD(p
,num_opens
);
2135 GETWORD(p
,num_users
);
2136 GETDWORD(p
,conn_time
);
2137 GETSTRINGP(p
, username
, rdata
, converter
);
2138 GETSTRINGP(p
, netname
, rdata
, converter
);
2140 fn(conn_id
, conn_type
, num_opens
, num_users
, conn_time
,
2145 DEBUG(4,("NetConnectionEnum res=%d\n", res
));
2148 DEBUG(4,("NetConnectionEnum no data returned\n"));