1430b4c46SGordon Ross /*
2430b4c46SGordon Ross * CDDL HEADER START
3430b4c46SGordon Ross *
4430b4c46SGordon Ross * The contents of this file are subject to the terms of the
5430b4c46SGordon Ross * Common Development and Distribution License (the "License").
6430b4c46SGordon Ross * You may not use this file except in compliance with the License.
7430b4c46SGordon Ross *
8430b4c46SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9430b4c46SGordon Ross * or http://www.opensolaris.org/os/licensing.
10430b4c46SGordon Ross * See the License for the specific language governing permissions
11430b4c46SGordon Ross * and limitations under the License.
12430b4c46SGordon Ross *
13430b4c46SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14430b4c46SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15430b4c46SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16430b4c46SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17430b4c46SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18430b4c46SGordon Ross *
19430b4c46SGordon Ross * CDDL HEADER END
20430b4c46SGordon Ross */
21430b4c46SGordon Ross
22430b4c46SGordon Ross /*
23430b4c46SGordon Ross * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*8329232eSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25430b4c46SGordon Ross */
26430b4c46SGordon Ross
27430b4c46SGordon Ross /*
28430b4c46SGordon Ross * Test program for the smbfs named pipe API.
29430b4c46SGordon Ross */
30430b4c46SGordon Ross
31430b4c46SGordon Ross #include <sys/types.h>
32430b4c46SGordon Ross #include <errno.h>
33430b4c46SGordon Ross #include <fcntl.h>
34430b4c46SGordon Ross #include <stdio.h>
35430b4c46SGordon Ross #include <stdlib.h>
36430b4c46SGordon Ross #include <string.h>
37430b4c46SGordon Ross #include <unistd.h>
38430b4c46SGordon Ross #include <libintl.h>
39*8329232eSGordon Ross #include <ctype.h>
40430b4c46SGordon Ross
41*8329232eSGordon Ross #include <netsmb/smb_lib.h>
42430b4c46SGordon Ross
43430b4c46SGordon Ross /*
44430b4c46SGordon Ross * This is a quick hack for testing client-side named pipes.
45*8329232eSGordon Ross * Its purpose is to test SMB named-pipe interface separately
46*8329232eSGordon Ross * from the RPC implementation. It's a "hack" because it uses
47*8329232eSGordon Ross * hand-crafted RPC messages (extracted from network traffic).
48430b4c46SGordon Ross */
49430b4c46SGordon Ross
50430b4c46SGordon Ross /* This is a DCE/RPC bind call for "srvsvc". */
51430b4c46SGordon Ross static const uchar_t
52430b4c46SGordon Ross srvsvc_bind[] = {
53430b4c46SGordon Ross 0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
54430b4c46SGordon Ross 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
55430b4c46SGordon Ross 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
56430b4c46SGordon Ross 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
57430b4c46SGordon Ross 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
58430b4c46SGordon Ross 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
59430b4c46SGordon Ross 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
60430b4c46SGordon Ross 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
61430b4c46SGordon Ross 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
62430b4c46SGordon Ross
6385e6b674SGordon Ross /* This is a srvsvc "enum servers" call, in two parts */
64430b4c46SGordon Ross static const uchar_t
6585e6b674SGordon Ross srvsvc_enum1[] = {
66430b4c46SGordon Ross 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
6785e6b674SGordon Ross #define ENUM_RPCLEN_OFF 8
68430b4c46SGordon Ross /* V - RPC frag length */
69430b4c46SGordon Ross 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70430b4c46SGordon Ross /* ... and the operation number is: VVVV */
7185e6b674SGordon Ross 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00,
7285e6b674SGordon Ross #define ENUM_SLEN1_OFF 28
7385e6b674SGordon Ross #define ENUM_SLEN2_OFF 36
74430b4c46SGordon Ross /* server name, length 14 vv ... */
75430b4c46SGordon Ross 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
76430b4c46SGordon Ross 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
77430b4c46SGordon Ross /* UNC server here, i.e.: "\\192.168.1.6" */
78430b4c46SGordon Ross
7985e6b674SGordon Ross static const uchar_t
8085e6b674SGordon Ross srvsvc_enum2[] = {
8185e6b674SGordon Ross 0x01, 0x00, 0x00, 0x00,
8285e6b674SGordon Ross 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
8385e6b674SGordon Ross 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8485e6b674SGordon Ross 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
8585e6b674SGordon Ross
86430b4c46SGordon Ross static uchar_t sendbuf[1024];
8785e6b674SGordon Ross static uchar_t recvbuf[4096];
88430b4c46SGordon Ross
89*8329232eSGordon Ross /*
90*8329232eSGordon Ross * Print strings found in the buffer.
91*8329232eSGordon Ross */
92430b4c46SGordon Ross static void
pstrings(const uchar_t * buf,int len)93*8329232eSGordon Ross pstrings(const uchar_t *buf, int len)
94430b4c46SGordon Ross {
95*8329232eSGordon Ross const uchar_t *p = buf;
96*8329232eSGordon Ross uint16_t u2;
97*8329232eSGordon Ross boolean_t instr = B_FALSE;
98*8329232eSGordon Ross
99*8329232eSGordon Ross while (len > 2) {
100*8329232eSGordon Ross u2 = *p++;
101*8329232eSGordon Ross u2 |= (*p++) << 8;
102*8329232eSGordon Ross len -= 2;
103*8329232eSGordon Ross
104*8329232eSGordon Ross if ((u2 & 0xFF80) == 0 && isprint(u2)) {
105*8329232eSGordon Ross /* printable */
106*8329232eSGordon Ross instr = B_TRUE;
107*8329232eSGordon Ross putchar(u2);
108*8329232eSGordon Ross } else {
109*8329232eSGordon Ross /* not printalbe */
110*8329232eSGordon Ross if (instr)
111*8329232eSGordon Ross putchar('\n');
112*8329232eSGordon Ross instr = B_FALSE;
113430b4c46SGordon Ross }
114430b4c46SGordon Ross }
115*8329232eSGordon Ross if (instr)
116*8329232eSGordon Ross putchar('\n');
117430b4c46SGordon Ross }
118430b4c46SGordon Ross
119430b4c46SGordon Ross /*
120430b4c46SGordon Ross * Put a unicode UNC server name, including the null.
121430b4c46SGordon Ross * Quick-n-dirty, just for this test...
122430b4c46SGordon Ross */
123430b4c46SGordon Ross static int
put_uncserver(const char * s,uchar_t * buf)124430b4c46SGordon Ross put_uncserver(const char *s, uchar_t *buf)
125430b4c46SGordon Ross {
126430b4c46SGordon Ross uchar_t *p = buf;
127430b4c46SGordon Ross char c;
128430b4c46SGordon Ross
129430b4c46SGordon Ross *p++ = '\\'; *p++ = '\0';
130430b4c46SGordon Ross *p++ = '\\'; *p++ = '\0';
131430b4c46SGordon Ross
132430b4c46SGordon Ross do {
133430b4c46SGordon Ross c = *s++;
134430b4c46SGordon Ross if (c == '/')
135430b4c46SGordon Ross c = '\\';
136430b4c46SGordon Ross *p++ = c;
137430b4c46SGordon Ross *p++ = '\0';
138430b4c46SGordon Ross
139430b4c46SGordon Ross } while (c != 0);
140430b4c46SGordon Ross
141430b4c46SGordon Ross return (p - buf);
142430b4c46SGordon Ross }
143430b4c46SGordon Ross
144430b4c46SGordon Ross /*
145430b4c46SGordon Ross * Send the bind and read the ack.
146430b4c46SGordon Ross * This tests smb_fh_xactnp.
147430b4c46SGordon Ross */
148430b4c46SGordon Ross static int
do_bind(int fid)149430b4c46SGordon Ross do_bind(int fid)
150430b4c46SGordon Ross {
151430b4c46SGordon Ross int err, len, more;
152430b4c46SGordon Ross
153430b4c46SGordon Ross more = 0;
154430b4c46SGordon Ross len = sizeof (recvbuf);
155430b4c46SGordon Ross err = smb_fh_xactnp(fid,
156430b4c46SGordon Ross sizeof (srvsvc_bind), (char *)srvsvc_bind,
157430b4c46SGordon Ross &len, (char *)recvbuf, &more);
158430b4c46SGordon Ross if (err) {
159430b4c46SGordon Ross printf("xact bind, err=%d\n", err);
160430b4c46SGordon Ross return (err);
161430b4c46SGordon Ross }
162430b4c46SGordon Ross if (more > 0) {
163430b4c46SGordon Ross if (more > sizeof (recvbuf)) {
164430b4c46SGordon Ross printf("bogus more=%d\n", more);
165430b4c46SGordon Ross more = sizeof (recvbuf);
166430b4c46SGordon Ross }
167430b4c46SGordon Ross len = smb_fh_read(fid, 0,
168430b4c46SGordon Ross more, (char *)recvbuf);
169430b4c46SGordon Ross if (len == -1) {
170430b4c46SGordon Ross err = EIO;
17185e6b674SGordon Ross printf("read enum resp, err=%d\n", err);
172430b4c46SGordon Ross return (err);
173430b4c46SGordon Ross }
174430b4c46SGordon Ross }
175430b4c46SGordon Ross
176430b4c46SGordon Ross return (0);
177430b4c46SGordon Ross }
178430b4c46SGordon Ross
179430b4c46SGordon Ross static int
do_enum(char * server,int fid)180*8329232eSGordon Ross do_enum(char *server, int fid)
181430b4c46SGordon Ross {
18285e6b674SGordon Ross int err, len, rlen, wlen;
183430b4c46SGordon Ross uchar_t *p;
184430b4c46SGordon Ross
185430b4c46SGordon Ross /*
18685e6b674SGordon Ross * Build the enum request - three parts.
18785e6b674SGordon Ross * See above: srvsvc_enum1, srvsvc_enum2
188430b4c46SGordon Ross *
189430b4c46SGordon Ross * First part: RPC header, etc.
190430b4c46SGordon Ross */
191430b4c46SGordon Ross p = sendbuf;
19285e6b674SGordon Ross len = sizeof (srvsvc_enum1); /* 40 */
19385e6b674SGordon Ross memcpy(p, srvsvc_enum1, len);
194430b4c46SGordon Ross p += len;
195430b4c46SGordon Ross
196430b4c46SGordon Ross /* Second part: UNC server name */
197430b4c46SGordon Ross len = put_uncserver(server, p);
198430b4c46SGordon Ross p += len;
19985e6b674SGordon Ross sendbuf[ENUM_SLEN1_OFF] = len / 2;
20085e6b674SGordon Ross sendbuf[ENUM_SLEN2_OFF] = len / 2;
201430b4c46SGordon Ross
202430b4c46SGordon Ross /* Third part: level, etc. (align4) */
203430b4c46SGordon Ross for (len = (p - sendbuf) & 3; len; len--)
204430b4c46SGordon Ross *p++ = '\0';
20585e6b674SGordon Ross len = sizeof (srvsvc_enum2); /* 28 */
20685e6b674SGordon Ross memcpy(p, srvsvc_enum2, len);
20785e6b674SGordon Ross p += len;
208430b4c46SGordon Ross
209430b4c46SGordon Ross /*
210430b4c46SGordon Ross * Compute total length, and fixup RPC header.
211430b4c46SGordon Ross */
212430b4c46SGordon Ross len = p - sendbuf;
21385e6b674SGordon Ross sendbuf[ENUM_RPCLEN_OFF] = len;
214430b4c46SGordon Ross
215430b4c46SGordon Ross /*
21685e6b674SGordon Ross * Send the enum request, read the response.
217430b4c46SGordon Ross * This tests smb_fh_write, smb_fh_read.
218430b4c46SGordon Ross */
219430b4c46SGordon Ross wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
220430b4c46SGordon Ross if (wlen == -1) {
221430b4c46SGordon Ross err = errno;
22285e6b674SGordon Ross printf("write enum req, err=%d\n", err);
223430b4c46SGordon Ross return (err);
224430b4c46SGordon Ross }
225430b4c46SGordon Ross if (wlen != len) {
22685e6b674SGordon Ross printf("write enum req, short write %d\n", wlen);
227430b4c46SGordon Ross return (EIO);
228430b4c46SGordon Ross }
229430b4c46SGordon Ross
230430b4c46SGordon Ross rlen = smb_fh_read(fid, 0,
231430b4c46SGordon Ross sizeof (recvbuf), (char *)recvbuf);
232430b4c46SGordon Ross if (rlen == -1) {
233430b4c46SGordon Ross err = errno;
23485e6b674SGordon Ross printf("read enum resp, err=%d\n", err);
235430b4c46SGordon Ross return (err);
236430b4c46SGordon Ross }
237430b4c46SGordon Ross
238*8329232eSGordon Ross /*
239*8329232eSGordon Ross * Just dump strings found in the response data.
240*8329232eSGordon Ross * Skip the first 0x90 (RPC wrappers).
241*8329232eSGordon Ross */
242*8329232eSGordon Ross printf("enum strings\n");
243*8329232eSGordon Ross pstrings(recvbuf + 0x90, rlen - 0x90);
244430b4c46SGordon Ross
245430b4c46SGordon Ross return (0);
246430b4c46SGordon Ross }
247430b4c46SGordon Ross
248*8329232eSGordon Ross int
list_shares(struct smb_ctx * ctx)249*8329232eSGordon Ross list_shares(struct smb_ctx *ctx)
250430b4c46SGordon Ross {
251430b4c46SGordon Ross static char path[] = "/srvsvc";
252430b4c46SGordon Ross static uchar_t key[16];
253*8329232eSGordon Ross char *server = ctx->ct_srvname;
254430b4c46SGordon Ross int err, fd;
255430b4c46SGordon Ross
256430b4c46SGordon Ross printf("open pipe: %s\n", path);
257430b4c46SGordon Ross fd = smb_fh_open(ctx, path, O_RDWR);
258430b4c46SGordon Ross if (fd < 0) {
259430b4c46SGordon Ross perror(path);
260430b4c46SGordon Ross return (errno);
261430b4c46SGordon Ross }
262430b4c46SGordon Ross
263430b4c46SGordon Ross /* Test this too. */
264430b4c46SGordon Ross err = smb_fh_getssnkey(fd, key, sizeof (key));
265430b4c46SGordon Ross if (err) {
266430b4c46SGordon Ross printf("getssnkey: %d\n", err);
267430b4c46SGordon Ross goto out;
268430b4c46SGordon Ross }
269430b4c46SGordon Ross
270430b4c46SGordon Ross err = do_bind(fd);
271430b4c46SGordon Ross if (err) {
272430b4c46SGordon Ross printf("do_bind: %d\n", err);
273430b4c46SGordon Ross goto out;
274430b4c46SGordon Ross }
275*8329232eSGordon Ross err = do_enum(server, fd);
276430b4c46SGordon Ross if (err)
27785e6b674SGordon Ross printf("do_enum: %d\n", err);
278430b4c46SGordon Ross
279430b4c46SGordon Ross out:
280430b4c46SGordon Ross smb_fh_close(fd);
28185e6b674SGordon Ross return (0);
282430b4c46SGordon Ross }
283