summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbfs/smb
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2011-06-30 17:58:05 -0400
committerGordon Ross <gwr@nexenta.com>2011-06-30 17:58:05 -0400
commit430b4c467020edf2445feb0c21db01c88b86243a (patch)
treed13826bc812dd8c21ad1b0629bdb756bc9cfd257 /usr/src/lib/libsmbfs/smb
parent9ecc7612020c1993e4dbadd3422a74b210279739 (diff)
downloadillumos-joyent-430b4c467020edf2445feb0c21db01c88b86243a.tar.gz
1120 Use real file descriptors for smbfs named pipes.
Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Garrett D'Amore <garrett@nexenta.com>
Diffstat (limited to 'usr/src/lib/libsmbfs/smb')
-rw-r--r--usr/src/lib/libsmbfs/smb/ctx.c388
-rw-r--r--usr/src/lib/libsmbfs/smb/file.c211
-rw-r--r--usr/src/lib/libsmbfs/smb/keychain.c13
-rw-r--r--usr/src/lib/libsmbfs/smb/mapfile-vers10
-rw-r--r--usr/src/lib/libsmbfs/smb/print.c100
-rw-r--r--usr/src/lib/libsmbfs/smb/private.h5
-rw-r--r--usr/src/lib/libsmbfs/smb/rap.c4
-rw-r--r--usr/src/lib/libsmbfs/smb/rq.c5
8 files changed, 331 insertions, 405 deletions
diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c
index a4620bc457..5681aa7226 100644
--- a/usr/src/lib/libsmbfs/smb/ctx.c
+++ b/usr/src/lib/libsmbfs/smb/ctx.c
@@ -33,6 +33,7 @@
*/
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -64,8 +65,6 @@
#include <netsmb/smb_dev.h>
#include "charsets.h"
-#include "spnego.h"
-#include "derparse.h"
#include "private.h"
#include "ntlm.h"
@@ -90,6 +89,14 @@ int smb_debug, smb_verbose;
const char smbutil_std_opts[] = "ABCD:E:I:L:M:NO:P:U:R:S:T:W:";
/*
+ * Defaults for new contexts (connections to servers).
+ * These are set by smbfs_set_default_...
+ */
+static char default_domain[SMBIOC_MAX_NAME];
+static char default_user[SMBIOC_MAX_NAME];
+
+
+/*
* Give the RPC library a callback hook that will be
* called whenever we destroy or reinit an smb_ctx_t.
* The name rpc_cleanup_smbctx() is legacy, and was
@@ -206,7 +213,8 @@ dump_ctx(char *where, struct smb_ctx *ctx)
ctx->ct_origshare ? ctx->ct_origshare : "",
ctx->ct_shtype_req);
- /* dump_iod_work()? */
+ printf(" ct_home=\"%s\"\n", ctx->ct_home);
+ printf(" ct_rpath=\"%s\"\n", ctx->ct_rpath);
}
int
@@ -233,9 +241,7 @@ smb_ctx_alloc(struct smb_ctx **ctx_pp)
int
smb_ctx_init(struct smb_ctx *ctx)
{
- char pwbuf[NSS_BUFLEN_PASSWD];
- struct passwd pw;
- int error = 0;
+ int error;
bzero(ctx, sizeof (*ctx));
@@ -256,32 +262,15 @@ smb_ctx_init(struct smb_ctx *ctx)
ctx->ct_authflags = SMB_AT_DEFAULT;
ctx->ct_minauth = SMB_AT_DEFAULT;
- error = nb_ctx_setscope(ctx->ct_nb, "");
- if (error)
- return (error);
-
/*
- * if the user name is not specified some other way,
- * use the current user name (built-in default)
+ * Default domain, user, ...
*/
- if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) {
- error = smb_ctx_setuser(ctx, pw.pw_name, 0);
- if (error)
- return (error);
- ctx->ct_home = strdup(pw.pw_name);
- if (ctx->ct_home == NULL)
- return (ENOMEM);
- }
-
- /*
- * Set a built-in default domain (workgroup).
- * Using the Windows/NT default for now.
- */
- error = smb_ctx_setdomain(ctx, "WORKGROUP", 0);
- if (error)
- return (error);
+ strlcpy(ctx->ct_domain, default_domain,
+ sizeof (ctx->ct_domain));
+ strlcpy(ctx->ct_user, default_user,
+ sizeof (ctx->ct_user));
- return (error);
+ return (0);
}
/*
@@ -441,8 +430,14 @@ smb_ctx_done(struct smb_ctx *ctx)
freeaddrinfo(ctx->ct_addrinfo);
ctx->ct_addrinfo = NULL;
}
- if (ctx->ct_home)
+ if (ctx->ct_home) {
free(ctx->ct_home);
+ ctx->ct_home = NULL;
+ }
+ if (ctx->ct_rpath) {
+ free(ctx->ct_rpath);
+ ctx->ct_rpath = NULL;
+ }
if (ctx->ct_srv_OS) {
free(ctx->ct_srv_OS);
ctx->ct_srv_OS = NULL;
@@ -457,26 +452,9 @@ smb_ctx_done(struct smb_ctx *ctx)
}
}
-static int
-getsubstring(const char *p, uchar_t sep, char *dest, int maxlen,
- const char **next)
-{
- int len;
-
- maxlen--;
- for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) {
- if (*p == 0)
- return (EINVAL);
- *dest = *p;
- }
- *dest = 0;
- *next = *p ? p + 1 : p;
- return (0);
-}
-
/*
* Parse the UNC path. Here we expect something like
- * "//[workgroup;][user[:password]@]host[/share[/path]]"
+ * "//[[domain;]user[:password]@]host[/share[/path]]"
* See http://ietf.org/internet-drafts/draft-crhertel-smb-url-07.txt
* Values found here are marked as "from CMD".
*/
@@ -485,9 +463,9 @@ smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
int minlevel, int maxlevel, int sharetype,
const char **next)
{
- const char *p = unc;
- char *p1, *colon;
char tmp[1024];
+ char *host, *share, *path;
+ char *dom, *usr, *pw, *p;
int error;
/*
@@ -497,118 +475,146 @@ smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
ctx->ct_minlevel = minlevel;
ctx->ct_maxlevel = maxlevel;
ctx->ct_shtype_req = sharetype;
-
ctx->ct_parsedlevel = SMBL_NONE;
- if (*p++ != '/' || *p++ != '/') {
+
+ dom = usr = pw = host = NULL;
+
+ /* Work on a temporary copy, fix back slashes. */
+ strlcpy(tmp, unc, sizeof (tmp));
+ for (p = tmp; *p; p++)
+ if (*p == '\\')
+ *p = '/';
+
+ if (tmp[0] != '/' || tmp[1] != '/') {
smb_error(dgettext(TEXT_DOMAIN,
"UNC should start with '//'"), 0);
error = EINVAL;
goto out;
}
- p1 = tmp;
- error = getsubstring(p, ';', p1, sizeof (tmp), &p);
- if (!error) {
- if (*p1 == 0) {
- smb_error(dgettext(TEXT_DOMAIN,
- "empty workgroup name"), 0);
- error = EINVAL;
- goto out;
- }
- error = smb_ctx_setdomain(ctx, unpercent(tmp), TRUE);
+ p = tmp + 2; /* user@host... */
+
+ /* Find the share part, if any. */
+ share = strchr(p, '/');
+ if (share)
+ *share = '\0';
+ (void) unpercent(p); /* host component */
+
+ /*
+ * Parse the "host" stuff right to left:
+ * 1: trailing "@hostname" (or whole field)
+ * 2: trailing ":password"
+ * 3: trailing "domain;user" (or just user)
+ */
+ host = strrchr(p, '@');
+ if (host == NULL) {
+ host = p; /* no user@ prefix */
+ } else {
+ *host++ = '\0';
+
+ /* may have [[domain;]user[:passwd]] */
+ pw = strchr(p, ':');
+ if (pw)
+ *pw++ = '\0';
+ usr = strchr(p, ';');
+ if (usr) {
+ *usr++ = '\0';
+ dom = p;
+ } else
+ usr = p;
+ }
+
+ if (*host == '\0') {
+ smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0);
+ error = EINVAL;
+ goto out;
+ }
+ error = smb_ctx_setfullserver(ctx, host);
+ if (error)
+ goto out;
+ ctx->ct_parsedlevel = SMBL_VC;
+
+ if (dom != NULL) {
+ error = smb_ctx_setdomain(ctx, dom, TRUE);
if (error)
goto out;
}
- colon = (char *)p;
- error = getsubstring(p, '@', p1, sizeof (tmp), &p);
- if (!error) {
- if (ctx->ct_maxlevel < SMBL_VC) {
+ if (usr != NULL) {
+ if (*usr == '\0') {
smb_error(dgettext(TEXT_DOMAIN,
- "no user name required"), 0);
+ "empty user name"), 0);
error = EINVAL;
goto out;
}
- p1 = strchr(tmp, ':');
- if (p1) {
- colon += p1 - tmp;
- *p1++ = (char)0;
- error = smb_ctx_setpassword(ctx, unpercent(p1), TRUE);
- if (error)
- goto out;
- if (p - colon > 2)
- memset(colon+1, '*', p - colon - 2);
- }
- p1 = tmp;
- if (*p1 == 0) {
+ if (ctx->ct_maxlevel < SMBL_VC) {
smb_error(dgettext(TEXT_DOMAIN,
- "empty user name"), 0);
+ "no user name required"), 0);
error = EINVAL;
goto out;
}
- error = smb_ctx_setuser(ctx, unpercent(tmp), TRUE);
+ error = smb_ctx_setuser(ctx, usr, TRUE);
if (error)
goto out;
- ctx->ct_parsedlevel = SMBL_VC;
}
- error = getsubstring(p, '/', p1, sizeof (tmp), &p);
- if (error) {
- error = getsubstring(p, '\0', p1, sizeof (tmp), &p);
- if (error) {
- smb_error(dgettext(TEXT_DOMAIN,
- "no server name found"), 0);
+ if (pw != NULL) {
+ error = smb_ctx_setpassword(ctx, pw, TRUE);
+ if (error)
goto out;
- }
- }
- if (*p1 == 0) {
- smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0);
- error = EINVAL;
- goto out;
}
- /*
- * Save ct_fullserver without case conversion.
- */
- if (strchr(tmp, '%'))
- (void) unpercent(tmp);
- error = smb_ctx_setfullserver(ctx, tmp);
- if (error)
- goto out;
+ if (share != NULL) {
+ /* restore the slash */
+ *share = '/';
+ p = share + 1;
-#ifdef SMB_ST_NONE
- if (sharetype == SMB_ST_NONE) {
- if (next)
- *next = p;
- error = 0;
- goto out;
- }
-#endif
+ /* Find the path part, if any. */
+ path = strchr(p, '/');
+ if (path)
+ *path = '\0';
+ (void) unpercent(p); /* share component */
- if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
- smb_error(dgettext(TEXT_DOMAIN, "no share name required"), 0);
- error = EINVAL;
- goto out;
- }
- error = getsubstring(p, '/', p1, sizeof (tmp), &p);
- if (error) {
- error = getsubstring(p, '\0', p1, sizeof (tmp), &p);
- if (error) {
+ if (*p == '\0') {
smb_error(dgettext(TEXT_DOMAIN,
- "unexpected end of line"), 0);
+ "empty share name"), 0);
+ error = EINVAL;
goto out;
}
- }
- if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE &&
- !(ctx->ct_flags & SMBCF_BROWSEOK)) {
+ if (ctx->ct_maxlevel < SMBL_SHARE) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "no share name required"), 0);
+ error = EINVAL;
+ goto out;
+ }
+
+ /*
+ * Special case UNC names like:
+ * //host/PIPE/endpoint
+ * to have share: IPC$
+ */
+ if (strcasecmp(p, "PIPE") == 0) {
+ sharetype = USE_IPC;
+ p = "IPC$";
+ }
+ error = smb_ctx_setshare(ctx, p, sharetype);
+ if (error)
+ goto out;
+ ctx->ct_parsedlevel = SMBL_SHARE;
+
+ if (path) {
+ /* restore the slash */
+ *path = '/';
+ p = path + 1;
+ (void) unpercent(p); /* remainder */
+ free(ctx->ct_rpath);
+ ctx->ct_rpath = strdup(path);
+ }
+ } else if (ctx->ct_minlevel >= SMBL_SHARE) {
smb_error(dgettext(TEXT_DOMAIN, "empty share name"), 0);
error = EINVAL;
goto out;
}
+
if (next)
- *next = p;
- if (*p1 == 0) {
- error = 0;
- goto out;
- }
- error = smb_ctx_setshare(ctx, unpercent(p1), sharetype);
+ *next = NULL;
out:
if (error == 0 && smb_debug > 0)
@@ -1147,27 +1153,10 @@ smb_ctx_resolve(struct smb_ctx *ctx)
int
smb_open_driver()
{
- int err, fd;
- uint32_t version;
+ int fd;
fd = open("/dev/"NSMB_NAME, O_RDWR);
if (fd < 0) {
- err = errno;
- smb_error(dgettext(TEXT_DOMAIN,
- "failed to open driver"), err);
- return (-1);
- }
-
- /*
- * Check the driver version (paranoia)
- * Do this BEFORE any other ioctl calls.
- */
- if (ioctl(fd, SMBIOC_GETVERS, &version) < 0)
- version = 0;
- if (version != NSMB_VERSION) {
- smb_error(dgettext(TEXT_DOMAIN,
- "incorrect driver version"), 0);
- close(fd);
return (-1);
}
@@ -1180,7 +1169,8 @@ smb_open_driver()
int
smb_ctx_gethandle(struct smb_ctx *ctx)
{
- int fd;
+ int fd, err;
+ uint32_t version;
if (ctx->ct_dev_fd != -1) {
rpc_cleanup_smbctx(ctx);
@@ -1190,8 +1180,24 @@ smb_ctx_gethandle(struct smb_ctx *ctx)
}
fd = smb_open_driver();
- if (fd < 0)
+ if (fd < 0) {
+ err = errno;
+ smb_error(dgettext(TEXT_DOMAIN,
+ "failed to open driver"), err);
+ return (err);
+ }
+
+ /*
+ * Check the driver version (paranoia)
+ */
+ if (ioctl(fd, SMBIOC_GETVERS, &version) < 0)
+ version = 0;
+ if (version != NSMB_VERSION) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "incorrect driver version"), 0);
+ close(fd);
return (ENODEV);
+ }
ctx->ct_dev_fd = fd;
return (0);
@@ -1241,43 +1247,12 @@ smb_ctx_get_ssn(struct smb_ctx *ctx)
}
/*
- * Get the string representation of a share "use" type,
- * as needed for the "service" in tree connect.
- */
-static const char *
-smb_use_type_str(smb_use_shtype_t stype)
-{
- const char *pp;
-
- switch (stype) {
- default:
- case USE_WILDCARD:
- pp = "?????";
- break;
- case USE_DISKDEV:
- pp = "A:";
- break;
- case USE_SPOOLDEV:
- pp = "LPT1:";
- break;
- case USE_CHARDEV:
- pp = "COMM";
- break;
- case USE_IPC:
- pp = "IPC";
- break;
- }
- return (pp);
-}
-
-/*
* Find or create a tree connection
*/
int
smb_ctx_get_tree(struct smb_ctx *ctx)
{
smbioc_tcon_t *tcon = NULL;
- const char *stype;
int cmd, err = 0;
if (ctx->ct_dev_fd < 0 ||
@@ -1297,18 +1272,8 @@ smb_ctx_get_tree(struct smb_ctx *ctx)
strlcpy(tcon->tc_sh.sh_name, ctx->ct_origshare,
sizeof (tcon->tc_sh.sh_name));
- /*
- * Share password (unused - no share-level security)
- * MS-SMB 2.2.6 says this should be null terminated,
- * and the length includes the null. Did bzero above,
- * so just set length for the null.
- */
- tcon->tc_sh.sh_pwlen = 1;
-
/* The share "use" type. */
- stype = smb_use_type_str(ctx->ct_shtype_req);
- strlcpy(tcon->tc_sh.sh_type_req, stype,
- sizeof (tcon->tc_sh.sh_type_req));
+ tcon->tc_sh.sh_use = ctx->ct_shtype_req;
/*
* Todo: share passwords for share-level security.
@@ -1323,13 +1288,12 @@ smb_ctx_get_tree(struct smb_ctx *ctx)
/*
* Check the returned share type
*/
- DPRINT("ret. sh_type: \"%s\"", tcon->tc_sh.sh_type_ret);
+ DPRINT("ret. sh_type: \"%d\"", tcon->tc_sh.sh_type);
if (ctx->ct_shtype_req != USE_WILDCARD &&
- 0 != strcmp(stype, tcon->tc_sh.sh_type_ret)) {
+ ctx->ct_shtype_req != tcon->tc_sh.sh_type) {
smb_error(dgettext(TEXT_DOMAIN,
"%s: incompatible share type"),
0, ctx->ct_origshare);
- err = EINVAL;
}
out:
@@ -1360,12 +1324,12 @@ smb_ctx_flags2(struct smb_ctx *ctx)
* Must already have an active SMB session.
*/
int
-smb_ctx_get_ssnkey(struct smb_ctx *ctx, uchar_t *key, size_t len)
+smb_fh_getssnkey(int dev_fd, uchar_t *key, size_t len)
{
if (len < SMBIOC_HASH_SZ)
return (EINVAL);
- if (ioctl(ctx->ct_dev_fd, SMBIOC_GETSSNKEY, key) == -1)
+ if (ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1)
return (errno);
return (0);
@@ -1536,14 +1500,26 @@ smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
int
smb_ctx_readrc(struct smb_ctx *ctx)
{
- char *home;
+ char pwbuf[NSS_BUFLEN_PASSWD];
+ struct passwd pw;
char *sname = NULL;
int sname_max;
int err = 0;
- if ((home = getenv("HOME")) == NULL)
- home = ctx->ct_home;
- if ((err = smb_open_rcfile(home)) != 0) {
+ /*
+ * If the user name is not specified some other way,
+ * use the current user name. Also save the homedir.
+ * NB: ct_home=NULL is allowed, and we don't want to
+ * bail out with an error for a missing ct_home.
+ */
+ if (getpwuid_r(getuid(), &pw, pwbuf, sizeof (pwbuf)) != NULL) {
+ if (ctx->ct_user[0] == 0)
+ (void) smb_ctx_setuser(ctx, pw.pw_name, B_FALSE);
+ if (ctx->ct_home == NULL)
+ ctx->ct_home = strdup(pw.pw_dir);
+ }
+
+ if ((err = smb_open_rcfile(ctx->ct_home)) != 0) {
DPRINT("smb_open_rcfile, err=%d", err);
/* ignore any error here */
return (0);
@@ -1614,3 +1590,15 @@ done:
return (err);
}
+
+void
+smbfs_set_default_domain(const char *domain)
+{
+ strlcpy(default_domain, domain, sizeof (default_domain));
+}
+
+void
+smbfs_set_default_user(const char *user)
+{
+ strlcpy(default_user, user, sizeof (default_user));
+}
diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c
index 3c8184e8a1..1c09532d61 100644
--- a/usr/src/lib/libsmbfs/smb/file.c
+++ b/usr/src/lib/libsmbfs/smb/file.c
@@ -33,6 +33,7 @@
*/
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -62,133 +63,66 @@
#include "private.h"
int
-smb_fh_close(struct smb_ctx *ctx, int fh)
+smb_fh_close(int fd)
{
- struct smb_rq *rqp;
- struct mbdata *mbp;
- int error;
-
- error = smb_rq_init(ctx, SMB_COM_CLOSE, &rqp);
- if (error != 0)
- return (error);
- mbp = smb_rq_getrequest(rqp);
- smb_rq_wstart(rqp);
- mb_put_uint16le(mbp, (uint16_t)fh);
- mb_put_uint32le(mbp, 0); /* time stamp */
- smb_rq_wend(rqp);
- mb_put_uint16le(mbp, 0); /* byte count */
-
- error = smb_rq_simple(rqp);
- smb_rq_done(rqp);
-
- return (error);
+ return (close(fd));
}
int
smb_fh_ntcreate(
struct smb_ctx *ctx, char *path,
- int flags, int req_acc, int efattr,
- int share_acc, int open_disp,
- int create_opts, int impersonation,
- int *fhp, uint32_t *action_taken)
+ int req_acc, int efattr, int share_acc,
+ int open_disp, int create_opts)
{
- struct smb_rq *rqp;
- struct mbdata *mbp;
- char *pathsizep;
- int pathstart, pathsize;
- int error, flags2, uc;
- uint16_t fh;
- uint8_t wc;
-
- flags2 = smb_ctx_flags2(ctx);
- if (flags2 == -1)
- return (EIO);
- uc = flags2 & SMB_FLAGS2_UNICODE;
-
- error = smb_rq_init(ctx, SMB_COM_NT_CREATE_ANDX, &rqp);
- if (error != 0)
- return (error);
-
- mbp = smb_rq_getrequest(rqp);
- smb_rq_wstart(rqp);
- mb_put_uint16le(mbp, 0xff); /* secondary command */
- mb_put_uint16le(mbp, 0); /* offset to next command (none) */
- mb_put_uint8(mbp, 0); /* MBZ (pad?) */
- (void) mb_fit(mbp, 2, &pathsizep); /* path size - fill in below */
- mb_put_uint32le(mbp, flags); /* create flags (oplock) */
- mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */
- mb_put_uint32le(mbp, req_acc);
- mb_put_uint64le(mbp, 0); /* initial alloc. size */
- mb_put_uint32le(mbp, efattr); /* ext. file attributes */
- mb_put_uint32le(mbp, share_acc); /* share access mode */
- mb_put_uint32le(mbp, open_disp); /* open disposition */
- mb_put_uint32le(mbp, create_opts); /* create_options */
- mb_put_uint32le(mbp, impersonation);
- mb_put_uint8(mbp, 0); /* security flags (?) */
- smb_rq_wend(rqp);
- smb_rq_bstart(rqp);
- if (uc) {
- /*
- * We're about to put a unicode string. We know
- * we're misaligned at this point, and need to
- * save the mb_count at the start of the string,
- * not at the alignment padding placed before it.
- * So add the algnment padding by hand here.
- */
- mb_put_uint8(mbp, 0);
+ smbioc_ntcreate_t ioc;
+ int err, nmlen;
+ int new_fd = -1;
+ int32_t from_fd;
+
+ nmlen = strlen(path);
+ if (nmlen >= SMBIOC_MAX_NAME) {
+ err = EINVAL;
+ goto errout;
}
- pathstart = mbp->mb_count;
- mb_put_string(mbp, path, uc);
- smb_rq_bend(rqp);
-
- /* Now go back and fill in pathsizep */
- pathsize = mbp->mb_count - pathstart;
- pathsizep[0] = pathsize & 0xFF;
- pathsizep[1] = (pathsize >> 8);
-
- error = smb_rq_simple(rqp);
- if (error)
- goto out;
- mbp = smb_rq_getreply(rqp);
/*
- * spec says 26 for word count, but 34 words are defined
- * and observed from win2000
+ * Will represent this SMB-level open as a new
+ * open device handle. Get one, then duplicate
+ * the driver session and tree bindings.
*/
- error = md_get_uint8(mbp, &wc);
- if (error || wc < 26) {
- smb_error(dgettext(TEXT_DOMAIN,
- "%s: open failed, bad word count"), 0, path);
- error = EBADRPC;
- goto out;
+ new_fd = smb_open_driver();
+ if (new_fd < 0) {
+ err = errno;
+ goto errout;
+ }
+ from_fd = ctx->ct_dev_fd;
+ if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) {
+ err = errno;
+ goto errout;
}
- md_get_uint8(mbp, NULL); /* secondary cmd */
- md_get_uint8(mbp, NULL); /* mbz */
- md_get_uint16le(mbp, NULL); /* andxoffset */
- md_get_uint8(mbp, NULL); /* oplock lvl granted */
- md_get_uint16le(mbp, &fh); /* FID */
- md_get_uint32le(mbp, action_taken);
-#if 0 /* skip decoding the rest */
- md_get_uint64le(mbp, NULL); /* creation time */
- md_get_uint64le(mbp, NULL); /* access time */
- md_get_uint64le(mbp, NULL); /* write time */
- md_get_uint64le(mbp, NULL); /* change time */
- md_get_uint32le(mbp, NULL); /* attributes */
- md_get_uint64le(mbp, NULL); /* allocation size */
- md_get_uint64le(mbp, NULL); /* EOF */
- md_get_uint16le(mbp, NULL); /* file type */
- md_get_uint16le(mbp, NULL); /* device state */
- md_get_uint8(mbp, NULL); /* directory (boolean) */
-#endif
- /* success! */
- *fhp = fh;
- error = 0;
+ /*
+ * Do the SMB-level open with the new dev handle.
+ */
+ bzero(&ioc, sizeof (ioc));
+ strlcpy(ioc.ioc_name, path, SMBIOC_MAX_NAME);
+ ioc.ioc_req_acc = req_acc;
+ ioc.ioc_efattr = efattr;
+ ioc.ioc_share_acc = share_acc;
+ ioc.ioc_open_disp = open_disp;
+ ioc.ioc_creat_opts = create_opts;
+ if (ioctl(new_fd, SMBIOC_NTCREATE, &ioc) == -1) {
+ err = errno;
+ goto errout;
+ }
-out:
- smb_rq_done(rqp);
+ return (new_fd);
- return (error);
+errout:
+ if (new_fd != -1)
+ close(new_fd);
+ errno = err;
+ return (-1);
}
/*
@@ -196,10 +130,21 @@ out:
* Converts Unix-style open call to NTCreate.
*/
int
-smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag, int *fhp)
+smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag)
{
- int error, mode, open_disp, req_acc, share_acc;
+ int mode, open_disp, req_acc, share_acc;
char *p, *ntpath = NULL;
+ int fd = -1;
+
+ /*
+ * Convert Unix path to NT (backslashes)
+ */
+ ntpath = strdup(path);
+ if (ntpath == NULL)
+ return (-1); /* errno was set */
+ for (p = ntpath; *p; p++)
+ if (*p == '/')
+ *p = '\\';
/*
* Map O_RDONLY, O_WRONLY, O_RDWR
@@ -250,55 +195,43 @@ smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag, int *fhp)
open_disp = NTCREATEX_DISP_OPEN;
}
- /*
- * Convert Unix path to NT (backslashes)
- */
- ntpath = strdup(path);
- if (ntpath == NULL)
- return (ENOMEM);
- for (p = ntpath; *p; p++)
- if (*p == '/')
- *p = '\\';
-
- error = smb_fh_ntcreate(ctx, ntpath, 0, /* flags */
+ fd = smb_fh_ntcreate(ctx, ntpath,
req_acc, SMB_EFA_NORMAL, share_acc, open_disp,
- NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
- NTCREATEX_IMPERSONATION_IMPERSONATION,
- fhp, NULL);
- free(ntpath);
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE);
- return (error);
+ free(ntpath);
+ return (fd);
}
int
-smb_fh_read(struct smb_ctx *ctx, int fh, off_t offset, size_t count,
+smb_fh_read(int fd, off_t offset, size_t count,
char *dst)
{
struct smbioc_rw rwrq;
bzero(&rwrq, sizeof (rwrq));
- rwrq.ioc_fh = fh;
+ rwrq.ioc_fh = -1; /* tell driver to supply this */
rwrq.ioc_base = dst;
rwrq.ioc_cnt = count;
rwrq.ioc_offset = offset;
- if (ioctl(ctx->ct_dev_fd, SMBIOC_READ, &rwrq) == -1) {
+ if (ioctl(fd, SMBIOC_READ, &rwrq) == -1) {
return (-1);
}
return (rwrq.ioc_cnt);
}
int
-smb_fh_write(struct smb_ctx *ctx, int fh, off_t offset, size_t count,
+smb_fh_write(int fd, off_t offset, size_t count,
const char *src)
{
struct smbioc_rw rwrq;
bzero(&rwrq, sizeof (rwrq));
- rwrq.ioc_fh = fh;
+ rwrq.ioc_fh = -1; /* tell driver to supply this */
rwrq.ioc_base = (char *)src;
rwrq.ioc_cnt = count;
rwrq.ioc_offset = offset;
- if (ioctl(ctx->ct_dev_fd, SMBIOC_WRITE, &rwrq) == -1) {
+ if (ioctl(fd, SMBIOC_WRITE, &rwrq) == -1) {
return (-1);
}
return (rwrq.ioc_cnt);
@@ -313,7 +246,7 @@ smb_fh_write(struct smb_ctx *ctx, int fh, off_t offset, size_t count,
* and on output *rdlen is the received length.
*/
int
-smb_fh_xactnp(struct smb_ctx *ctx, int fh,
+smb_fh_xactnp(int fd,
int tdlen, const char *tdata, /* transmit */
int *rdlen, char *rdata, /* receive */
int *more)
@@ -322,10 +255,10 @@ smb_fh_xactnp(struct smb_ctx *ctx, int fh,
uint16_t setup[2];
setup[0] = TRANS_TRANSACT_NAMED_PIPE;
- setup[1] = fh;
+ setup[1] = 0xFFFF; /* driver replaces this */
rparamcnt = 0;
- err = smb_t2_request(ctx, 2, setup, "\\PIPE\\",
+ err = smb_t2_request(fd, 2, setup, "\\PIPE\\",
0, NULL, /* TX paramcnt, params */
tdlen, (void *)tdata,
&rparamcnt, NULL, /* no RX params */
diff --git a/usr/src/lib/libsmbfs/smb/keychain.c b/usr/src/lib/libsmbfs/smb/keychain.c
index c5cf319c21..fd9bcc9496 100644
--- a/usr/src/lib/libsmbfs/smb/keychain.c
+++ b/usr/src/lib/libsmbfs/smb/keychain.c
@@ -20,6 +20,7 @@
*/
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -173,6 +174,18 @@ smbfs_keychain_add(uid_t uid, const char *dom, const char *usr,
return (err);
}
+/* Variant of the above that takes an NT hash. */
+int
+smbfs_keychain_addhash(uid_t uid, const char *dom, const char *usr,
+ const uchar_t *nthash)
+{
+ static const uchar_t lmhash[SMBIOC_HASH_SZ] = { 0 };
+ int err, cmd = SMBIOC_PK_ADD;
+ err = smbfs_keychain_cmn(cmd, uid, dom, usr,
+ (uchar_t *)lmhash, (uchar_t *)nthash);
+ return (err);
+}
+
/* Delete a password from the keychain. */
int
smbfs_keychain_del(uid_t uid, const char *dom, const char *usr)
diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers
index b86cbf4a89..1c2a5d6fa9 100644
--- a/usr/src/lib/libsmbfs/smb/mapfile-vers
+++ b/usr/src/lib/libsmbfs/smb/mapfile-vers
@@ -18,6 +18,7 @@
# CDDL HEADER END
#
#
+# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
@@ -66,7 +67,6 @@ SYMBOL_VERSION SUNWprivate {
smb_ctx_flags2;
smb_ctx_free;
smb_ctx_get_ssn;
- smb_ctx_get_ssnkey;
smb_ctx_get_tree;
smb_ctx_gethandle;
smb_ctx_init;
@@ -97,6 +97,7 @@ SYMBOL_VERSION SUNWprivate {
#
# Functions to support named pipes
smb_fh_close;
+ smb_fh_getssnkey;
smb_fh_open;
smb_fh_read;
smb_fh_write;
@@ -111,9 +112,8 @@ SYMBOL_VERSION SUNWprivate {
smb_iod_work;
smb_lib_init;
smb_netshareenum; # will move to libnetapi
+ smb_open_printer;
smb_open_rcfile;
- smb_printer_open;
- smb_printer_close;
smb_simplecrypt;
smb_simpledecrypt;
smb_strerror;
@@ -141,11 +141,15 @@ SYMBOL_VERSION SUNWprivate {
#
smbfs_default_dom_usr;
smbfs_keychain_add;
+ smbfs_keychain_addhash;
smbfs_keychain_chk;
smbfs_keychain_del;
smbfs_keychain_del_everyone;
smbfs_keychain_del_owner;
+ smbfs_set_default_domain;
+ smbfs_set_default_user;
+
smbutil_std_opts;
local:
*;
diff --git a/usr/src/lib/libsmbfs/smb/print.c b/usr/src/lib/libsmbfs/smb/print.c
index 268c330a0b..c59bef81b4 100644
--- a/usr/src/lib/libsmbfs/smb/print.c
+++ b/usr/src/lib/libsmbfs/smb/print.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2000, Boris Popov
* All rights reserved.
*
@@ -41,82 +42,61 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
+#include <libintl.h>
#include <netsmb/smb.h>
#include <netsmb/smb_lib.h>
+
#include "private.h"
int
-smb_printer_open(struct smb_ctx *ctx, int setuplen, int mode,
- const char *ident, int *fhp)
+smb_open_printer(struct smb_ctx *ctx, const char *title,
+ int setuplen, int mode)
{
- struct smb_rq *rqp;
- struct mbdata *mbp;
- int error, flags2, uc;
- uint16_t fh;
- uint8_t wc;
-
- flags2 = smb_ctx_flags2(ctx);
- if (flags2 == -1)
- return (EIO);
- uc = flags2 & SMB_FLAGS2_UNICODE;
+ smbioc_printjob_t ioc;
+ int err, tlen, new_fd;
+ int32_t from_fd;
- error = smb_rq_init(ctx, SMB_COM_OPEN_PRINT_FILE, &rqp);
- if (error)
- return (error);
- mbp = smb_rq_getrequest(rqp);
- smb_rq_wstart(rqp);
- mb_put_uint16le(mbp, setuplen);
- mb_put_uint16le(mbp, mode);
- smb_rq_wend(rqp);
- smb_rq_bstart(rqp);
- mb_put_uint8(mbp, SMB_DT_ASCII);
- mb_put_string(mbp, ident, uc);
- smb_rq_bend(rqp);
- error = smb_rq_simple(rqp);
- if (error)
- goto out;
+ tlen = strlen(title);
+ if (tlen >= SMBIOC_MAX_NAME)
+ return (EINVAL);
- mbp = smb_rq_getreply(rqp);
- error = md_get_uint8(mbp, &wc);
- if (error || wc < 1) {
- error = EBADRPC;
- goto out;
+ /*
+ * Will represent this SMB-level open as a new
+ * open device handle. Get one, then duplicate
+ * the driver session and tree bindings.
+ */
+ new_fd = smb_open_driver();
+ if (new_fd < 0)
+ return (errno);
+ from_fd = ctx->ct_dev_fd;
+ if (ioctl(new_fd, SMBIOC_DUP_DEV, &from_fd) == -1) {
+ err = errno;
+ goto errout;
}
- md_get_uint16le(mbp, &fh);
- *fhp = fh;
- error = 0;
-out:
- smb_rq_done(rqp);
- return (error);
-}
+ /*
+ * Do the SMB-level open with the new dev handle.
+ */
+ bzero(&ioc, sizeof (ioc));
+ ioc.ioc_setuplen = setuplen;
+ ioc.ioc_prmode = mode;
+ strlcpy(ioc.ioc_title, title, SMBIOC_MAX_NAME);
-/*
- * Similar to smb_fh_close
- */
-int
-smb_printer_close(struct smb_ctx *ctx, int fh)
-{
- struct smb_rq *rqp;
- struct mbdata *mbp;
- int error;
-
- error = smb_rq_init(ctx, SMB_COM_CLOSE_PRINT_FILE, &rqp);
- if (error)
- return (error);
- mbp = smb_rq_getrequest(rqp);
- smb_rq_wstart(rqp);
- mb_put_uint16le(mbp, (uint16_t)fh);
- smb_rq_wend(rqp);
- mb_put_uint16le(mbp, 0); /* byte count */
+ if (ioctl(new_fd, SMBIOC_PRINTJOB, &ioc) == -1) {
+ err = errno;
+ goto errout;
+ }
- error = smb_rq_simple(rqp);
- smb_rq_done(rqp);
+ return (new_fd);
- return (error);
+errout:
+ close(new_fd);
+ errno = err;
+ return (-1);
}
diff --git a/usr/src/lib/libsmbfs/smb/private.h b/usr/src/lib/libsmbfs/smb/private.h
index e6124f2e57..febca40126 100644
--- a/usr/src/lib/libsmbfs/smb/private.h
+++ b/usr/src/lib/libsmbfs/smb/private.h
@@ -31,6 +31,7 @@
*/
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -110,6 +111,8 @@ int smb_rq_dmem(struct mbdata *, const char *, size_t);
int smb_rq_internal(struct smb_ctx *, struct smb_rq *);
void smb_rq_sign(struct smb_rq *);
int smb_rq_verify(struct smb_rq *);
+int smb_t2_request(int, int, uint16_t *, const char *,
+ int, void *, int, void *, int *, void *, int *, void *, int *);
/*
* This library extends the mchain.h function set a little.
@@ -170,6 +173,8 @@ char *smb_printb(char *, int, const struct smb_bitname *);
int smb_ctx_getaddr(struct smb_ctx *ctx);
int smb_ctx_gethandle(struct smb_ctx *ctx);
+int smb_iod_start(struct smb_ctx *);
+
int smb_ssn_send(struct smb_ctx *, struct mbdata *);
int smb_ssn_recv(struct smb_ctx *, struct mbdata *);
diff --git a/usr/src/lib/libsmbfs/smb/rap.c b/usr/src/lib/libsmbfs/smb/rap.c
index 98f35af5ff..09926d70f3 100644
--- a/usr/src/lib/libsmbfs/smb/rap.c
+++ b/usr/src/lib/libsmbfs/smb/rap.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2000, Boris Popov
* All rights reserved.
*
@@ -334,7 +335,8 @@ smb_rap_request(struct smb_rap *rap, struct smb_ctx *ctx)
rdatacnt = rap->r_rcvbuflen;
rparamcnt = rap->r_plen;
- error = smb_t2_request(ctx, 0, NULL, "\\PIPE\\LANMAN",
+ error = smb_t2_request(ctx->ct_dev_fd,
+ 0, NULL, "\\PIPE\\LANMAN",
rap->r_plen, rap->r_pbuf, /* int tparamcnt,void *tparam */
0, NULL, /* int tdatacnt, void *tdata */
&rparamcnt, rap->r_pbuf, /* rparamcnt, void *rparam */
diff --git a/usr/src/lib/libsmbfs/smb/rq.c b/usr/src/lib/libsmbfs/smb/rq.c
index 6045237393..c4e929eff9 100644
--- a/usr/src/lib/libsmbfs/smb/rq.c
+++ b/usr/src/lib/libsmbfs/smb/rq.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2000, Boris Popov
* All rights reserved.
*
@@ -279,7 +280,7 @@ smb_rq_simple(struct smb_rq *rqp)
int
-smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup,
+smb_t2_request(int dev_fd, int setupcount, uint16_t *setup,
const char *name,
int tparamcnt, void *tparam,
int tdatacnt, void *tdata,
@@ -311,7 +312,7 @@ smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup,
krq->ioc_rparam = rparam;
krq->ioc_rdata = rdata;
- if (ioctl(ctx->ct_dev_fd, SMBIOC_T2RQ, krq) == -1) {
+ if (ioctl(dev_fd, SMBIOC_T2RQ, krq) == -1) {
return (errno);
}