diff options
author | Gordon Ross <gwr@nexenta.com> | 2011-06-30 17:58:05 -0400 |
---|---|---|
committer | Gordon Ross <gwr@nexenta.com> | 2011-06-30 17:58:05 -0400 |
commit | 430b4c467020edf2445feb0c21db01c88b86243a (patch) | |
tree | d13826bc812dd8c21ad1b0629bdb756bc9cfd257 /usr/src/lib/libsmbfs/smb | |
parent | 9ecc7612020c1993e4dbadd3422a74b210279739 (diff) | |
download | illumos-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.c | 388 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/file.c | 211 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/keychain.c | 13 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/mapfile-vers | 10 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/print.c | 100 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/private.h | 5 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/rap.c | 4 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/rq.c | 5 |
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); } |