#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libintl.h>
#include <ctype.h>
#include <netsmb/smb_lib.h>
static const uchar_t
srvsvc_bind[] = {
0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
static const uchar_t
srvsvc_enum1[] = {
0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
#define ENUM_RPCLEN_OFF 8
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00,
#define ENUM_SLEN1_OFF 28
#define ENUM_SLEN2_OFF 36
0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
static const uchar_t
srvsvc_enum2[] = {
0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
static uchar_t sendbuf[1024];
static uchar_t recvbuf[4096];
static void
pstrings(const uchar_t *buf, int len)
{
const uchar_t *p = buf;
uint16_t u2;
boolean_t instr = B_FALSE;
while (len > 2) {
u2 = *p++;
u2 |= (*p++) << 8;
len -= 2;
if ((u2 & 0xFF80) == 0 && isprint(u2)) {
instr = B_TRUE;
putchar(u2);
} else {
if (instr)
putchar('\n');
instr = B_FALSE;
}
}
if (instr)
putchar('\n');
}
static int
put_uncserver(const char *s, uchar_t *buf)
{
uchar_t *p = buf;
char c;
*p++ = '\\'; *p++ = '\0';
*p++ = '\\'; *p++ = '\0';
do {
c = *s++;
if (c == '/')
c = '\\';
*p++ = c;
*p++ = '\0';
} while (c != 0);
return (p - buf);
}
static int
do_bind(int fid)
{
int err, len, more;
more = 0;
len = sizeof (recvbuf);
err = smb_fh_xactnp(fid,
sizeof (srvsvc_bind), (char *)srvsvc_bind,
&len, (char *)recvbuf, &more);
if (err) {
printf("xact bind, err=%d\n", err);
return (err);
}
if (more > 0) {
if (more > sizeof (recvbuf)) {
printf("bogus more=%d\n", more);
more = sizeof (recvbuf);
}
len = smb_fh_read(fid, 0,
more, (char *)recvbuf);
if (len == -1) {
err = EIO;
printf("read enum resp, err=%d\n", err);
return (err);
}
}
return (0);
}
static int
do_enum(char *server, int fid)
{
int err, len, rlen, wlen;
uchar_t *p;
p = sendbuf;
len = sizeof (srvsvc_enum1);
memcpy(p, srvsvc_enum1, len);
p += len;
len = put_uncserver(server, p);
p += len;
sendbuf[ENUM_SLEN1_OFF] = len / 2;
sendbuf[ENUM_SLEN2_OFF] = len / 2;
for (len = (p - sendbuf) & 3; len; len--)
*p++ = '\0';
len = sizeof (srvsvc_enum2);
memcpy(p, srvsvc_enum2, len);
p += len;
len = p - sendbuf;
sendbuf[ENUM_RPCLEN_OFF] = len;
wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
if (wlen == -1) {
err = errno;
printf("write enum req, err=%d\n", err);
return (err);
}
if (wlen != len) {
printf("write enum req, short write %d\n", wlen);
return (EIO);
}
rlen = smb_fh_read(fid, 0,
sizeof (recvbuf), (char *)recvbuf);
if (rlen == -1) {
err = errno;
printf("read enum resp, err=%d\n", err);
return (err);
}
printf("enum strings\n");
pstrings(recvbuf + 0x90, rlen - 0x90);
return (0);
}
int
list_shares(struct smb_ctx *ctx)
{
static char path[] = "/srvsvc";
static uchar_t key[16];
char *server = ctx->ct_srvname;
int err, fd;
printf("open pipe: %s\n", path);
fd = smb_fh_open(ctx, path, O_RDWR);
if (fd < 0) {
perror(path);
return (errno);
}
err = smb_fh_getssnkey(fd, key, sizeof (key));
if (err) {
printf("getssnkey: %d\n", err);
goto out;
}
err = do_bind(fd);
if (err) {
printf("do_bind: %d\n", err);
goto out;
}
err = do_enum(server, fd);
if (err)
printf("do_enum: %d\n", err);
out:
smb_fh_close(fd);
return (0);
}