# HG changeset patch # User Gordon Ross # Date 1309471085 14400 # Node ID 96340372b72d9c3f6acec898279264796c269b81 # Parent a055831123f16ee3383dedbbeadce5aaa76e8762 1120 Use real file descriptors for smbfs named pipes. Reviewed by: Eric Schrock Reviewed by: Albert Lee Approved by: Garrett D'Amore diff -r a055831123f1 -r 96340372b72d exception_lists/copyright --- a/exception_lists/copyright Fri Jun 24 08:44:32 2011 -0700 +++ b/exception_lists/copyright Thu Jun 30 17:58:05 2011 -0400 @@ -18,8 +18,8 @@ # # CDDL HEADER END # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright 2010 Nexenta Systems, Inc. All rights reserved. # syntax: glob @@ -48,6 +48,7 @@ usr/src/cmd/krb5/ldap_util/kdb5_ldap_policy.h usr/src/cmd/krb5/ldap_util/kdb5_ldap_realm.h usr/src/cmd/krb5/ldap_util/kdb5_ldap_services.h +usr/src/cmd/smbsrv/smbd/eventlog.dll usr/src/common/bzip2/LICENSE usr/src/common/bzip2/Solaris.README.txt usr/src/common/bzip2/bzlib.h @@ -328,6 +329,7 @@ usr/src/lib/libkmsagent/common/SOAP/*.* usr/src/lib/librstp/common/*.[ch] usr/src/lib/librstp/common/[CRT]* +usr/src/uts/intel/nsmb/ioc_check.ref usr/src/uts/intel/os/splashimage.xpm usr/src/uts/common/gssapi/mechs/krb5/crypto/block_size.c usr/src/uts/common/gssapi/mechs/krb5/crypto/checksum_length.c @@ -354,4 +356,4 @@ usr/src/uts/common/gssapi/mechs/krb5/mech/util_seed.c usr/src/uts/common/gssapi/mechs/krb5/mech/util_seqnum.c usr/src/uts/common/gssapi/mechs/krb5/mech/val_cred.c -usr/src/cmd/smbsrv/smbd/eventlog.dll +usr/src/uts/sparc/nsmb/ioc_check.ref diff -r a055831123f1 -r 96340372b72d exception_lists/packaging --- a/exception_lists/packaging Fri Jun 24 08:44:32 2011 -0700 +++ b/exception_lists/packaging Thu Jun 30 17:58:05 2011 -0400 @@ -821,6 +821,7 @@ # usr/lib/fs/smbfs/chacl usr/lib/fs/smbfs/lsacl +usr/lib/fs/smbfs/testnp # # FC related files kernel/kmdb/fcip i386 diff -r a055831123f1 -r 96340372b72d usr/src/cmd/fs.d/smbclnt/Makefile --- a/usr/src/cmd/fs.d/smbclnt/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/fs.d/smbclnt/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -20,6 +20,7 @@ # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. # @@ -32,7 +33,7 @@ SUBDIRS_CATALOG= smbutil mount umount share SUBDIRS= $(SUBDIRS_CATALOG) chacl lsacl \ - smbiod smbiod-svc svc + smbiod smbiod-svc svc test # for messaging catalog files # diff -r a055831123f1 -r 96340372b72d usr/src/cmd/fs.d/smbclnt/smbutil/print.c --- a/usr/src/cmd/fs.d/smbclnt/smbutil/print.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/fs.d/smbclnt/smbutil/print.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -150,7 +151,7 @@ * Have the printer share connection. * Print the file. */ - snprintf(titlebuf, sizeof (titlebuf), "%s_%s", + snprintf(titlebuf, sizeof (titlebuf), "%s %s", ctx->ct_user, filename); error = print_file(ctx, titlebuf, file); @@ -185,13 +186,15 @@ print_file(smb_ctx_t *ctx, char *title, int file) { off_t offset; - int error, rcnt, wcnt; + int rcnt, wcnt; int setup_len = 0; /* No printer setup data */ int mode = MODE_GRAPHICS; /* treat as raw data */ - int fh = -1; + int error = 0; + int pfd = -1; - error = smb_printer_open(ctx, setup_len, mode, title, &fh); - if (error) { + pfd = smb_open_printer(ctx, title, setup_len, mode); + if (pfd < 0) { + error = errno; smb_error("could not open print job", error); return (error); } @@ -207,7 +210,7 @@ if (rcnt == 0) break; - wcnt = smb_fh_write(ctx, fh, offset, rcnt, databuf); + wcnt = smb_fh_write(pfd, offset, rcnt, databuf); if (wcnt < 0) { error = errno; smb_error("error writing spool file\n", error); @@ -221,6 +224,6 @@ offset += wcnt; } - (void) smb_printer_close(ctx, fh); + (void) smb_fh_close(pfd); return (error); } diff -r a055831123f1 -r 96340372b72d usr/src/cmd/fs.d/smbclnt/test/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fs.d/smbclnt/test/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -0,0 +1,58 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +FSTYPE= smbfs +LIBPROG= testnp +ROOTFS_PROG= $(LIBPROG) + +include ../../Makefile.fstype + +OBJS= $(LIBPROG).o +SRCS= $(LIBPROG).c $(FSLIBSRC) + +LDLIBS += -lsmbfs + +CFLAGS += $(CCVERBOSE) +C99MODE= $(C99_ENABLE) + +CLOBBERFILES += $(LIBPROG) + +# uncomment these for dbx debugging +#COPTFLAG = -g +#CTF_FLAGS = +#CTFCONVERT_O= +#CTFMERGE_LIB= + +all: $(ROOTFS_PROG) + +install: $(ROOTLIBFSTYPEPROG) + +lint: lint_SRCS + +clean: + $(RM) $(OBJS) + +.KEEP_STATE: diff -r a055831123f1 -r 96340372b72d usr/src/cmd/fs.d/smbclnt/test/testnp.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fs.d/smbclnt/test/testnp.c Thu Jun 30 17:58:05 2011 -0400 @@ -0,0 +1,416 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * Test program for the smbfs named pipe API. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * This is a quick hack for testing client-side named pipes. + * Its purpose is to test the ability to connect to a server, + * open a pipe, send and receive data. The "hack" aspect is + * the use of hand-crafted RPC messages, which allows testing + * of the named pipe API separately from the RPC libraries. + * + * I captured the two small name pipe messages sent when + * requesting a server info via RPC over /pipe/srvsvc and + * dropped them into the arrays below (bind and info). + * This program sends the two messages (with adjustments) + * and just dumps whatever comes back over the pipe. + * Use wireshark if you want to see decoded messages. + */ + +extern char *optarg; +extern int optind, opterr, optopt; + +/* This is a DCE/RPC bind call for "srvsvc". */ +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 }; + +/* This is a srvsvc "get server info" call, in two parts */ +static const uchar_t +srvsvc_info[] = { + 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, +#define INFO_RPCLEN_OFF 8 + /* V - RPC frag length */ + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* ... and the operation number is: VVVV */ + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00, +#define INFO_SLEN1_OFF 28 +#define INFO_SLEN2_OFF 36 + /* server name, length 14 vv ... */ + 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 }; + /* UNC server here, i.e.: "\\192.168.1.6" */ + +static uchar_t sendbuf[1024]; +static uchar_t recvbuf[1024]; +static char *server; + +static int pipetest(struct smb_ctx *); + +static void +testnp_usage(void) +{ + printf("usage: testnp [-d domain][-u user][-p passwd] server\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int c, error; + struct smb_ctx *ctx = NULL; + char *dom = NULL; + char *usr = NULL; + char *pw = NULL; + + while ((c = getopt(argc, argv, "vd:u:p:")) != -1) { + switch (c) { + case 'v': + smb_verbose = 1; + break; + + case 'd': + dom = optarg; + break; + case 'u': + usr = optarg; + break; + case 'p': + pw = optarg; + break; + case '?': + testnp_usage(); + break; + } + } + if (optind >= argc) + testnp_usage(); + server = argv[optind]; + + if (pw != NULL && (dom == NULL || usr == NULL)) { + fprintf(stderr, "%0: -p arg requires -d dom -u usr\n", + argv[0]); + testnp_usage(); + } + + /* + * This section is intended to demonstrate how an + * RPC client library might use this interface. + */ + error = smb_ctx_alloc(&ctx); + if (error) { + fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]); + goto out; + } + + /* + * Set server, share, domain, user + * (in the ctx handle). + */ + smb_ctx_setfullserver(ctx, server); + smb_ctx_setshare(ctx, "IPC$", USE_IPC); + if (dom) + smb_ctx_setdomain(ctx, dom, B_TRUE); + if (usr) + smb_ctx_setuser(ctx, usr, B_TRUE); + if (pw) + smb_ctx_setpassword(ctx, pw, NULL); + + + /* + * If this code were in smbutil or mount_smbfs, it would + * get system and $HOME/.nsmbrc settings here, like this: + */ +#if 0 + error = smb_ctx_readrc(ctx); + if (error) { + fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]); + goto out; + } +#endif + + /* + * Resolve the server address, + * setup derived defaults. + */ + error = smb_ctx_resolve(ctx); + if (error) { + fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]); + goto out; + } + + /* + * Get the session and tree. + */ + error = smb_ctx_get_ssn(ctx); + if (error) { + fprintf(stderr, "//%s: login failed, error %d\n", + server, error); + goto out; + } + error = smb_ctx_get_tree(ctx); + if (error) { + fprintf(stderr, "//%s/%s: tree connect failed, %d\n", + server, "IPC$", error); + goto out; + } + + /* + * Do some named pipe I/O. + */ + error = pipetest(ctx); + if (error) { + fprintf(stderr, "pipetest, %d\n", error); + goto out; + } + +out: + smb_ctx_free(ctx); + + return ((error) ? 1 : 0); +} + +static void +hexdump(const uchar_t *buf, int len) { + int ofs = 0; + + while (len--) { + if (ofs % 16 == 0) + printf("\n%02X: ", ofs); + printf("%02x ", *buf++); + ofs++; + } + printf("\n"); +} + +/* + * Put a unicode UNC server name, including the null. + * Quick-n-dirty, just for this test... + */ +static int +put_uncserver(const char *s, uchar_t *buf) +{ + uchar_t *p = buf; + int slashcnt = 0; + char c; + + *p++ = '\\'; *p++ = '\0'; + *p++ = '\\'; *p++ = '\0'; + + do { + c = *s++; + if (c == '/') + c = '\\'; + *p++ = c; + *p++ = '\0'; + + } while (c != 0); + + return (p - buf); +} + +/* Get a little-endian int. Just for testing. */ +static int +getint(const uchar_t *p) +{ + return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24)); +} + +/* + * Send the bind and read the ack. + * This tests smb_fh_xactnp. + */ +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 (smb_verbose) { + printf("bind ack, len=%d\n", len); + hexdump(recvbuf, len); + } + 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 info resp, err=%d\n", err); + return (err); + } + if (smb_verbose) { + printf("bind ack (more), len=%d\n", len); + hexdump(recvbuf, len); + } + } + + return (0); +} + +static int +do_info(int fid) +{ + int err, len, rlen, wlen, x; + uchar_t *p; + + /* + * Build the info request - two parts. + * See above: srvsvc_info + * + * First part: RPC header, etc. + */ + p = sendbuf; + len = sizeof (srvsvc_info); /* 40 */ + memcpy(p, srvsvc_info, len); + p += len; + + /* Second part: UNC server name */ + len = put_uncserver(server, p); + p += len; + sendbuf[INFO_SLEN1_OFF] = len / 2; + sendbuf[INFO_SLEN2_OFF] = len / 2; + + /* Third part: level, etc. (align4) */ + for (len = (p - sendbuf) & 3; len; len--) + *p++ = '\0'; + *p++ = 101; /* the "level" */ + *p++ = 0; *p++ = 0; *p++ = 0; + + /* + * Compute total length, and fixup RPC header. + */ + len = p - sendbuf; + sendbuf[INFO_RPCLEN_OFF] = len; + + /* + * Send the info request, read the response. + * This tests smb_fh_write, smb_fh_read. + */ + wlen = smb_fh_write(fid, 0, len, (char *)sendbuf); + if (wlen == -1) { + err = errno; + printf("write info req, err=%d\n", err); + return (err); + } + if (wlen != len) { + printf("write info 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 info resp, err=%d\n", err); + return (err); + } + + if (smb_verbose) { + printf("info recv, len=%d\n", rlen); + hexdump(recvbuf, rlen); + } + + x = getint(recvbuf + 4); + if (x != 0x10) { + printf("Data representation 0x%x not supported\n", x); + return (ENOTSUP); + } + printf("Platform Id: %d\n", getint(recvbuf + 0x20)); + printf("Version Major: %d\n", getint(recvbuf + 0x28)); + printf("Version Minor: %d\n", getint(recvbuf + 0x2c)); + printf("Srv type flags: 0x%x\n", getint(recvbuf + 0x30)); + + return (0); +} + +static int +pipetest(struct smb_ctx *ctx) +{ + static char path[] = "/srvsvc"; + static uchar_t key[16]; + int err, fd; + + printf("open pipe: %s\n", path); + fd = smb_fh_open(ctx, path, O_RDWR); + if (fd < 0) { + perror(path); + return (errno); + } + + /* Test this too. */ + 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_info(fd); + if (err) + printf("do_info: %d\n", err); + +out: + smb_fh_close(fd); + return (err); +} diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/common/modules/nsmb/nsmb.c --- a/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/common/modules/nsmb/nsmb.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -30,9 +31,9 @@ #include #include -#include "smb_conn.h" -#include "smb_rq.h" -#include "smb_pass.h" +#include +#include +#include #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */ #define OPT_RECURSE 0x0002 /* recursive display */ diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/common/modules/smbfs/smbfs.c --- a/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/common/modules/smbfs/smbfs.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -30,8 +31,8 @@ #include #include -#include "smbfs.h" -#include "smbfs_node.h" +#include +#include #define OPT_VERBOSE 0x0001 /* Be [-v]erbose in dcmd's */ diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/intel/amd64/nsmb/Makefile --- a/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -36,11 +37,10 @@ include ../../../Makefile.module -CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/netsmb +CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt CPPFLAGS += -I$(SRC)/uts/common -C99MODE= -xc99=%all -C99LMODE= -Xc99=%all +C99MODE= $(C99_ENABLE) # maybe not the best place for this, but # we need to create this directory. diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/intel/amd64/smbfs/Makefile --- a/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -36,9 +37,11 @@ include ../../../Makefile.module -CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/smbfs +CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt CPPFLAGS += -I$(SRC)/uts/common +C99MODE= $(C99_ENABLE) + # maybe not the best place for this, but # we need to create this directory. $(ROOTKMOD): diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/intel/ia32/nsmb/Makefile --- a/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -35,11 +36,10 @@ include ../../../Makefile.module -CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/netsmb +CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt CPPFLAGS += -I$(SRC)/uts/common -C99MODE= -xc99=%all -C99LMODE= -Xc99=%all +C99MODE= $(C99_ENABLE) # maybe not the best place for this, but # we need to create this directory. diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/intel/ia32/smbfs/Makefile --- a/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -35,9 +36,11 @@ include ../../../Makefile.module -CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/smbfs +CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt CPPFLAGS += -I$(SRC)/uts/common +C99MODE= $(C99_ENABLE) + # maybe not the best place for this, but # we need to create this directory. $(ROOTKMOD): diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/sparc/v9/nsmb/Makefile --- a/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -36,11 +37,10 @@ include ../../../Makefile.module -CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/netsmb +CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt CPPFLAGS += -I$(SRC)/uts/common -C99MODE= -xc99=%all -C99LMODE= -Xc99=%all +C99MODE= $(C99_ENABLE) # maybe not the best place for this, but # we need to create this directory. diff -r a055831123f1 -r 96340372b72d usr/src/cmd/mdb/sparc/v9/smbfs/Makefile --- a/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -36,9 +37,11 @@ include ../../../Makefile.module -CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/smbfs +CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt CPPFLAGS += -I$(SRC)/uts/common +C99MODE= $(C99_ENABLE) + # maybe not the best place for this, but # we need to create this directory. $(ROOTKMOD): diff -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/Makefile --- a/usr/src/lib/libsmbfs/Makefile Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/Makefile Thu Jun 30 17:58:05 2011 -0400 @@ -19,6 +19,7 @@ # CDDL HEADER END # # +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -29,7 +30,7 @@ include $(SRC)/lib/Makefile.lib -HDRS= smbfs_acl.h smbfs_api.h +HDRS= smbfs_acl.h smbfs_api.h smb_keychain.h HDRDIR= netsmb ROOTHDRDIR= $(ROOT)/usr/include/netsmb diff -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/netsmb/smb_keychain.h --- a/usr/src/lib/libsmbfs/netsmb/smb_keychain.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/netsmb/smb_keychain.h Thu Jun 30 17:58:05 2011 -0400 @@ -20,6 +20,7 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -27,8 +28,6 @@ #ifndef _SMB_KEYCHAIN_H #define _SMB_KEYCHAIN_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * External interface to the libsmbfs/netsmb keychain * storage mechanism. This interface is consumed by @@ -36,6 +35,10 @@ * and by the SMBFS PAM module. */ +#ifdef __cplusplus +extern "C" { +#endif + #define SMB_KEYCHAIN_SUCCESS 0 #define SMB_KEYCHAIN_BADPASSWD 300 #define SMB_KEYCHAIN_BADDOMAIN 301 @@ -47,6 +50,10 @@ int smbfs_keychain_add(uid_t uid, const char *domain, const char *user, const char *password); +/* Add an NT-hash (16-bytes) to the keychain. */ +int smbfs_keychain_addhash(uid_t uid, const char *domain, const char *user, + const uchar_t *nthash); + /* Delete a password from the keychain. */ int smbfs_keychain_del(uid_t uid, const char *domain, const char *user); @@ -79,4 +86,8 @@ smbfs_default_dom_usr(const char *home, const char *server, char *dom, int maxdom, char *usr, int maxusr); +#ifdef __cplusplus +} +#endif + #endif /* _SMB_KEYCHAIN_H */ diff -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/netsmb/smb_lib.h --- a/usr/src/lib/libsmbfs/netsmb/smb_lib.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/netsmb/smb_lib.h Thu Jun 30 17:58:05 2011 -0400 @@ -33,6 +33,7 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -108,6 +109,7 @@ int ct_shtype_req; /* share type wanted */ char *ct_origshare; char *ct_home; + char *ct_rpath; /* remote file name */ /* Connection setup SMB stuff. */ /* Strings from the SMB negotiate response. */ diff -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/netsmb/smbfs_api.h --- a/usr/src/lib/libsmbfs/netsmb/smbfs_api.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/netsmb/smbfs_api.h Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -28,8 +29,8 @@ #define _NETSMB_SMBFS_API_H /* - * Define the API exported to our commands and to the - * MS-style RPC-over-named-pipes library (mlrpc). + * Define the API exported to our commands and to + * libraries doing DCE-RPC over SMB named pipes. */ #include @@ -58,13 +59,14 @@ * Share type values for smb_ctx_new, _init * Based on NetUseAdd() USE_INFO_[12] _asg_type values * They also happen to match: STYPE_DISKTREE, etc. + * Note: these values appear on the wire. */ typedef enum { - USE_WILDCARD = -1, - USE_DISKDEV, - USE_SPOOLDEV, - USE_CHARDEV, - USE_IPC + USE_DISKDEV = 0, /* also STYPE_DISKTREE */ + USE_SPOOLDEV, /* also STYPE_PRINTQ */ + USE_CHARDEV, /* also STYPE_DEVICE */ + USE_IPC, /* also STYPE_IPC */ + USE_WILDCARD /* also STYPE_UNKNOWN */ } smb_use_shtype_t; /* @@ -115,7 +117,6 @@ int smb_ctx_flags2(struct smb_ctx *); int smb_ctx_resolve(struct smb_ctx *); int smb_ctx_get_ssn(struct smb_ctx *); -int smb_ctx_get_ssnkey(struct smb_ctx *, uchar_t *, size_t); int smb_ctx_get_tree(struct smb_ctx *); int smb_ctx_setauthflags(struct smb_ctx *, int); @@ -138,20 +139,18 @@ typedef void (*smb_ctx_close_hook_t)(struct smb_ctx *); void smb_ctx_set_close_hook(smb_ctx_close_hook_t); -int smb_fh_close(struct smb_ctx *ctx, int); -int smb_fh_open(struct smb_ctx *ctx, const char *, int, int *); -int smb_fh_read(struct smb_ctx *, int, off_t, size_t, char *); -int smb_fh_write(struct smb_ctx *, int, off_t, size_t, const char *); -int smb_fh_xactnp(struct smb_ctx *, int, int, const char *, +int smb_fh_close(int); +int smb_fh_open(struct smb_ctx *ctx, const char *, int); +int smb_fh_read(int, off_t, size_t, char *); +int smb_fh_write(int, off_t, size_t, const char *); +int smb_fh_xactnp(int, int, const char *, int *, char *, int *); +int smb_fh_getssnkey(int, uchar_t *, size_t); -int smb_iod_start(struct smb_ctx *); +int smb_open_printer(struct smb_ctx *, const char *, int, int); -int smb_t2_request(struct smb_ctx *, int, uint16_t *, const char *, - int, void *, int, void *, int *, void *, int *, void *, int *); - -int smb_printer_open(struct smb_ctx *, int, int, const char *, int *); -int smb_printer_close(struct smb_ctx *, int); +void smbfs_set_default_domain(const char *); +void smbfs_set_default_user(const char *); char *smb_strerror(int); diff -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/ctx.c --- a/usr/src/lib/libsmbfs/smb/ctx.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/ctx.c Thu Jun 30 17:58:05 2011 -0400 @@ -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 #include "charsets.h" -#include "spnego.h" -#include "derparse.h" #include "private.h" #include "ntlm.h" @@ -90,6 +89,14 @@ 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 @@ 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 @@ 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 @@ 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); - } + strlcpy(ctx->ct_domain, default_domain, + sizeof (ctx->ct_domain)); + strlcpy(ctx->ct_user, default_user, + sizeof (ctx->ct_user)); - /* - * 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); - - return (error); + return (0); } /* @@ -441,8 +430,14 @@ 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 @@ } } -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 @@ 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 @@ ctx->ct_minlevel = minlevel; ctx->ct_maxlevel = maxlevel; ctx->ct_shtype_req = sharetype; + ctx->ct_parsedlevel = SMBL_NONE; - 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) { + 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; + } + if (usr != NULL) { + if (*usr == '\0') { smb_error(dgettext(TEXT_DOMAIN, - "empty workgroup name"), 0); + "empty user name"), 0); error = EINVAL; goto out; } - error = smb_ctx_setdomain(ctx, unpercent(tmp), TRUE); - if (error) - goto out; - } - colon = (char *)p; - error = getsubstring(p, '@', p1, sizeof (tmp), &p); - if (!error) { if (ctx->ct_maxlevel < SMBL_VC) { smb_error(dgettext(TEXT_DOMAIN, "no user name required"), 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) { + error = smb_ctx_setuser(ctx, usr, TRUE); + if (error) + goto out; + } + if (pw != NULL) { + error = smb_ctx_setpassword(ctx, pw, TRUE); + if (error) + goto out; + } + + if (share != NULL) { + /* restore the slash */ + *share = '/'; + p = share + 1; + + /* Find the path part, if any. */ + path = strchr(p, '/'); + if (path) + *path = '\0'; + (void) unpercent(p); /* share component */ + + if (*p == '\0') { smb_error(dgettext(TEXT_DOMAIN, - "empty user name"), 0); + "empty share name"), 0); error = EINVAL; goto out; } - error = smb_ctx_setuser(ctx, unpercent(tmp), TRUE); + 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_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); - 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); } - } - if (*p1 == 0) { - smb_error(dgettext(TEXT_DOMAIN, "empty server name"), 0); + } else if (ctx->ct_minlevel >= SMBL_SHARE) { + smb_error(dgettext(TEXT_DOMAIN, "empty share 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; - -#ifdef SMB_ST_NONE - if (sharetype == SMB_ST_NONE) { - if (next) - *next = p; - error = 0; - goto out; - } -#endif - - 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) { - smb_error(dgettext(TEXT_DOMAIN, - "unexpected end of line"), 0); - goto out; - } - } - if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE && - !(ctx->ct_flags & SMBCF_BROWSEOK)) { - 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 @@ 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 @@ 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 @@ } 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 @@ } /* - * 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 @@ 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 @@ /* * 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 @@ * 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 @@ 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 @@ 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/file.c --- a/usr/src/lib/libsmbfs/smb/file.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/file.c Thu Jun 30 17:58:05 2011 -0400 @@ -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); + smbioc_ntcreate_t ioc; + int err, nmlen; + int new_fd = -1; + int32_t from_fd; - 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); + nmlen = strlen(path); + if (nmlen >= SMBIOC_MAX_NAME) { + err = EINVAL; + goto errout; + } + + /* + * 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) { + err = errno; + 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 - */ - 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; + 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 @@ * 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 @@ 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 = '\\'; + fd = smb_fh_ntcreate(ctx, ntpath, + req_acc, SMB_EFA_NORMAL, share_acc, open_disp, + NTCREATEX_OPTIONS_NON_DIRECTORY_FILE); - error = smb_fh_ntcreate(ctx, ntpath, 0, /* flags */ - req_acc, SMB_EFA_NORMAL, share_acc, open_disp, - NTCREATEX_OPTIONS_NON_DIRECTORY_FILE, - NTCREATEX_IMPERSONATION_IMPERSONATION, - fhp, NULL); free(ntpath); - - return (error); + 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 @@ * 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 @@ 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/keychain.c --- a/usr/src/lib/libsmbfs/smb/keychain.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/keychain.c Thu Jun 30 17:58:05 2011 -0400 @@ -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 @@ 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/mapfile-vers --- a/usr/src/lib/libsmbfs/smb/mapfile-vers Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/mapfile-vers Thu Jun 30 17:58:05 2011 -0400 @@ -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 @@ 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 @@ # # Functions to support named pipes smb_fh_close; + smb_fh_getssnkey; smb_fh_open; smb_fh_read; smb_fh_write; @@ -111,9 +112,8 @@ 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 @@ # 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/print.c --- a/usr/src/lib/libsmbfs/smb/print.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/print.c Thu Jun 30 17:58:05 2011 -0400 @@ -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 #include #include +#include #include #include #include #include +#include #include #include + #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); -} -/* - * Similar to smb_fh_close - */ -int -smb_printer_close(struct smb_ctx *ctx, int fh) -{ - struct smb_rq *rqp; - struct mbdata *mbp; - int 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); - 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/private.h --- a/usr/src/lib/libsmbfs/smb/private.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/private.h Thu Jun 30 17:58:05 2011 -0400 @@ -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_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 @@ 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/rap.c --- a/usr/src/lib/libsmbfs/smb/rap.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/rap.c Thu Jun 30 17:58:05 2011 -0400 @@ -1,4 +1,5 @@ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2000, Boris Popov * All rights reserved. * @@ -334,7 +335,8 @@ 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 -r a055831123f1 -r 96340372b72d usr/src/lib/libsmbfs/smb/rq.c --- a/usr/src/lib/libsmbfs/smb/rq.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/lib/libsmbfs/smb/rq.c Thu Jun 30 17:58:05 2011 -0400 @@ -1,4 +1,5 @@ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2000, Boris Popov * All rights reserved. * @@ -279,7 +280,7 @@ 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 @@ 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); } diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/offsets.in --- a/usr/src/uts/common/fs/smbclnt/netsmb/offsets.in Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/offsets.in Thu Jun 30 17:58:05 2011 -0400 @@ -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. \ @@ -57,11 +58,10 @@ ssn_srvname smbioc_oshare - sh_pwlen + sh_use + sh_type sh_name sh_pass - sh_type_req - sh_type_ret smbioc_tcon tc_flags @@ -114,7 +114,7 @@ smbioc_t2rq SIZEOF_SMBIOC_T2RQ ioc_setup ioc_setupcnt - ioc_name + ioc_name IOC_T2_NAME ioc_tparamcnt ioc_tdatacnt ioc_rparamcnt @@ -139,6 +139,19 @@ _ioc_offset _ioc_base +smbioc_ntcreate SIZEOF_NTCREATE + ioc_req_acc + ioc_efattr + ioc_share_acc + ioc_open_disp + ioc_creat_opts + ioc_name IOC_NTCR_NAME + +smbioc_printjob SIZEOF_PRINTJOB + ioc_setuplen + ioc_prmode + ioc_title + smbioc_pk SIZEOF_SMBIOC_PK pk_uid pk_dom diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -236,11 +237,10 @@ #define ss_lock ss_co.co_lock #define ss_flags ss_co.co_flags +#define ss_use ss_ioc.sh_use +#define ss_type ss_ioc.sh_type #define ss_name ss_ioc.sh_name -#define ss_pwlen ss_ioc.sh_pwlen #define ss_pass ss_ioc.sh_pass -#define ss_type_req ss_ioc.sh_type_req -#define ss_type_ret ss_ioc.sh_type_ret #define SMB_SS_LOCK(ssp) mutex_enter(&(ssp)->ss_lock) #define SMB_SS_UNLOCK(ssp) mutex_exit(&(ssp)->ss_lock) @@ -275,20 +275,19 @@ * Mostly used in: smb_dev.c, smb_usr.c */ typedef struct smb_dev { - int sd_opened; /* Opened or not */ - int sd_level; /* Future use */ + dev_info_t *sd_dip; /* ptr to dev_info node */ + struct cred *sd_cred; /* per dev credentails */ struct smb_vc *sd_vc; /* Reference to VC */ struct smb_share *sd_share; /* Reference to share if any */ + int sd_level; /* SMBL_VC, ... */ int sd_vcgenid; /* Generation of share or VC */ int sd_poll; /* Future use */ int sd_seq; /* Kind of minor number/instance no */ int sd_flags; /* State of connection */ #define NSMBFL_OPEN 0x0001 #define NSMBFL_IOD 0x0002 + int sd_smbfid; /* library read/write */ zoneid_t zoneid; /* Zone id */ - dev_info_t *smb_dip; /* ptr to dev_info node */ - void *sd_devfs; /* Dont know how to use this. but */ - struct cred *smb_cred; /* per dev credentails. Future use */ } smb_dev_t; extern const uint32_t nsmb_version; @@ -304,10 +303,15 @@ */ int smb_usr_get_flags2(smb_dev_t *sdp, intptr_t arg, int flags); int smb_usr_get_ssnkey(smb_dev_t *sdp, intptr_t arg, int flags); +int smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags); int smb_usr_simplerq(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr); int smb_usr_t2request(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr); + +int smb_usr_closefh(smb_dev_t *, cred_t *); int smb_usr_rw(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr); +int smb_usr_ntcreate(smb_dev_t *, intptr_t, int, cred_t *); +int smb_usr_printjob(smb_dev_t *, intptr_t, int, cred_t *); int smb_usr_get_ssn(smb_dev_t *, int, intptr_t, int, cred_t *); int smb_usr_drop_ssn(smb_dev_t *sdp, int cmd); @@ -378,14 +382,4 @@ void smb_share_invalidate(smb_share_t *ssp); int smb_share_tcon(smb_share_t *, smb_cred_t *); -/* - * SMB protocol level functions - */ -int smb_smb_echo(smb_vc_t *vcp, smb_cred_t *scred, int timo); -int smb_smb_treeconnect(smb_share_t *ssp, smb_cred_t *scred); -int smb_smb_treedisconnect(smb_share_t *ssp, smb_cred_t *scred); - -int smb_rwuio(smb_share_t *ssp, uint16_t fid, uio_rw_t rw, - uio_t *uiop, smb_cred_t *scred, int timo); - #endif /* _SMB_CONN_H */ diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -317,14 +318,9 @@ goto attach_failed; } - /* - * Need to see if this field is required. - * REVISIT - */ - sdp->smb_dip = dip; + sdp->sd_dip = dip; sdp->sd_seq = 0; - sdp->sd_opened = 1; - + sdp->sd_smbfid = -1; mutex_exit(&dev_lck); ddi_report_dev(dip); return (DDI_SUCCESS); @@ -397,6 +393,10 @@ err = smb_usr_get_ssnkey(sdp, arg, flags); break; + case SMBIOC_DUP_DEV: + err = smb_usr_dup_dev(sdp, arg, flags); + break; + case SMBIOC_REQUEST: err = smb_usr_simplerq(sdp, arg, flags, cr); break; @@ -410,6 +410,18 @@ err = smb_usr_rw(sdp, cmd, arg, flags, cr); break; + case SMBIOC_NTCREATE: + err = smb_usr_ntcreate(sdp, arg, flags, cr); + break; + + case SMBIOC_PRINTJOB: + err = smb_usr_printjob(sdp, arg, flags, cr); + break; + + case SMBIOC_CLOSEFH: + err = smb_usr_closefh(sdp, cr); + break; + case SMBIOC_SSN_CREATE: case SMBIOC_SSN_FIND: err = smb_usr_get_ssn(sdp, cmd, arg, flags, cr); @@ -523,9 +535,9 @@ return (ENXIO); } - sdp->sd_opened = 1; sdp->sd_seq = nsmb_minor; - sdp->smb_cred = cr; + sdp->sd_cred = cr; + sdp->sd_smbfid = -1; sdp->sd_flags |= NSMBFL_OPEN; sdp->zoneid = crgetzoneid(cr); mutex_exit(&dev_lck); @@ -570,12 +582,14 @@ { struct smb_vc *vcp; struct smb_share *ssp; - struct smb_cred scred; - smb_credinit(&scred, cr); + if (sdp->sd_smbfid != -1) + (void) smb_usr_closefh(sdp, cr); + ssp = sdp->sd_share; if (ssp != NULL) smb_share_rele(ssp); + vcp = sdp->sd_vc; if (vcp != NULL) { /* @@ -588,10 +602,69 @@ smb_vc_rele(vcp); } - smb_credrele(&scred); return (0); } +/* + * Helper for SMBIOC_DUP_DEV + * Duplicate state from the FD @arg ("from") onto + * the FD for this device instance. + */ +int +smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags) +{ + file_t *fp = NULL; + vnode_t *vp; + smb_dev_t *from_sdp; + dev_t dev; + int32_t ufd; + int err; + + /* Should be no VC */ + if (sdp->sd_vc != NULL) + return (EISCONN); + + /* + * Get from_sdp (what we will duplicate) + */ + if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags)) + return (EFAULT); + if ((fp = getf(ufd)) == NULL) + return (EBADF); + /* rele fp below */ + vp = fp->f_vnode; + dev = vp->v_rdev; + if (dev == 0 || dev == NODEV || + getmajor(dev) != nsmb_major) { + err = EINVAL; + goto out; + } + from_sdp = ddi_get_soft_state(statep, getminor(dev)); + if (from_sdp == NULL) { + err = EINVAL; + goto out; + } + + /* + * Duplicate VC and share references onto this FD. + */ + if ((sdp->sd_vc = from_sdp->sd_vc) != NULL) + smb_vc_hold(sdp->sd_vc); + if ((sdp->sd_share = from_sdp->sd_share) != NULL) + smb_share_hold(sdp->sd_share); + sdp->sd_level = from_sdp->sd_level; + err = 0; + +out: + if (fp) + releasef(ufd); + return (err); +} + + +/* + * Helper used by smbfs_mount + */ int smb_dev2share(int fd, struct smb_share **sspp) { @@ -604,12 +677,13 @@ if ((fp = getf(fd)) == NULL) return (EBADF); + /* rele fp below */ vp = fp->f_vnode; dev = vp->v_rdev; if (dev == 0 || dev == NODEV || getmajor(dev) != nsmb_major) { - err = EBADF; + err = EINVAL; goto out; } diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c Thu Jun 30 17:58:05 2011 -0400 @@ -33,6 +33,7 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -58,6 +59,8 @@ #include #include +#define STYPE_LEN 8 /* share type strings */ + /* * Largest size to use with LARGE_READ/LARGE_WRITE. * Specs say up to 64k data bytes, but Windows traffic @@ -88,6 +91,64 @@ static int smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); +/* + * Get the string representation of a share "use" type, + * as needed for the "service" in tree connect. + */ +static const char * +smb_share_typename(uint32_t stype) +{ + const char *p; + + switch (stype) { + case STYPE_DISKTREE: + p = "A:"; + break; + case STYPE_PRINTQ: + p = "LPT1:"; + break; + case STYPE_DEVICE: + p = "COMM"; + break; + case STYPE_IPC: + p = "IPC"; + break; + case STYPE_UNKNOWN: + default: + p = "?????"; + break; + } + return (p); +} + +/* + * Parse a share type name (inverse of above) + */ +static uint32_t +smb_share_parsetype(char *name) +{ + int stype; + + switch (*name) { + case 'A': /* A: */ + stype = STYPE_DISKTREE; + break; + case 'C': /* COMM */ + stype = STYPE_DEVICE; + break; + case 'I': /* IPC */ + stype = STYPE_IPC; + break; + case 'L': /* LPT: */ + stype = STYPE_PRINTQ; + break; + default: + stype = STYPE_UNKNOWN; + break; + } + return (stype); +} + int smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) { @@ -95,10 +156,12 @@ struct smb_rq *rqp = NULL; struct mbchain *mbp; struct mdchain *mdp; + const char *tname; char *pbuf, *unc_name = NULL; int error, tlen, plen, unc_len; uint16_t bcnt, options; uint8_t wc; + char stype_str[STYPE_LEN]; vcp = SSTOVC(ssp); @@ -127,12 +190,14 @@ vcp->vc_srvname, ssp->ss_name); SMBSDEBUG("unc_name: \"%s\"", unc_name); + /* - * The password is now pre-computed in the - * user-space helper process. + * Share-level password (pre-computed in user-space) + * MS-SMB 2.2.6 says this should be null terminated, + * and the pw length includes the null. */ - plen = ssp->ss_pwlen; pbuf = ssp->ss_pass; + plen = strlen(pbuf) + 1; /* * Build the request. @@ -161,8 +226,9 @@ * Put the type string (always ASCII), * including the null. */ - tlen = strlen(ssp->ss_type_req) + 1; - error = mb_put_mem(mbp, ssp->ss_type_req, tlen, MB_MSYSTEM); + tname = smb_share_typename(ssp->ss_use); + tlen = strlen(tname) + 1; + error = mb_put_mem(mbp, tname, tlen, MB_MSYSTEM); if (error) goto out; @@ -210,15 +276,17 @@ goto out; /* - * Get the returned share type string, - * i.e. "IPC" or whatever. Don't care - * if we get an error reading the type. + * Get the returned share type string, i.e. "IPC" or whatever. + * (See smb_share_typename, smb_share_parsetype). If we get + * an error reading the type, just say STYPE_UNKNOWN. */ - tlen = sizeof (ssp->ss_type_ret); - bzero(ssp->ss_type_ret, tlen--); + tlen = STYPE_LEN; + bzero(stype_str, tlen--); if (tlen > bcnt) tlen = bcnt; - md_get_mem(mdp, ssp->ss_type_ret, tlen, MB_MSYSTEM); + md_get_mem(mdp, stype_str, tlen, MB_MSYSTEM); + stype_str[tlen] = '\0'; + ssp->ss_type = smb_share_parsetype(stype_str); /* Success! */ SMB_SS_LOCK(ssp); @@ -281,6 +349,258 @@ } /* + * Modern create/open of file or directory. + */ +int +smb_smb_ntcreate( + struct smb_share *ssp, + struct mbchain *name_mb, + uint32_t cr_flags, /* create flags */ + uint32_t req_acc, /* requested access */ + uint32_t efa, /* ext. file attrs (DOS attr +) */ + uint32_t share_acc, + uint32_t open_disp, /* open disposition */ + uint32_t createopt, /* NTCREATEX_OPTIONS_ */ + uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */ + struct smb_cred *scrp, + uint16_t *fidp, /* returned FID */ + uint32_t *cr_act_p, /* optional create action */ + struct smbfattr *fap) /* optional attributes */ +{ + struct smb_rq rq, *rqp = &rq; + struct smb_vc *vcp = SSTOVC(ssp); + struct mbchain *mbp; + struct mdchain *mdp; + struct smbfattr fa; + uint64_t llongint; + uint32_t longint, createact; + uint16_t fid; + uint8_t wc; + int error; + + bzero(&fa, sizeof (fa)); + error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp); + if (error) + return (error); + smb_rq_getrequest(rqp, &mbp); + + /* Word parameters */ + smb_rq_wstart(rqp); + mb_put_uint8(mbp, 0xff); /* secondary command */ + mb_put_uint8(mbp, 0); /* MBZ */ + mb_put_uint16le(mbp, 0); /* offset to next command (none) */ + mb_put_uint8(mbp, 0); /* MBZ */ + mb_put_uint16le(mbp, name_mb->mb_count); + mb_put_uint32le(mbp, cr_flags); /* NTCREATEX_FLAGS_* */ + mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ + mb_put_uint32le(mbp, req_acc); + mb_put_uint64le(mbp, 0); /* "initial allocation size" */ + mb_put_uint32le(mbp, efa); + mb_put_uint32le(mbp, share_acc); + mb_put_uint32le(mbp, open_disp); + mb_put_uint32le(mbp, createopt); + mb_put_uint32le(mbp, impersonate); + mb_put_uint8(mbp, 0); /* security flags (?) */ + smb_rq_wend(rqp); + + /* + * Byte parameters: Just the path name, aligned. + * Note: mb_put_mbuf consumes mb_top, so clear it. + */ + smb_rq_bstart(rqp); + if (SMB_UNICODE_STRINGS(vcp)) + mb_put_padbyte(mbp); + mb_put_mbuf(mbp, name_mb->mb_top); + bzero(name_mb, sizeof (*name_mb)); + smb_rq_bend(rqp); + + /* + * Don't want to risk missing a successful + * open response, or we could "leak" FIDs. + */ + rqp->sr_flags |= SMBR_NOINTR_RECV; + error = smb_rq_simple_timed(rqp, smb_timo_open); + if (error) + goto done; + smb_rq_getreply(rqp, &mdp); + /* + * spec says 26 for word count, but 34 words are defined + * and observed from win2000 + */ + error = md_get_uint8(mdp, &wc); + if (error) + goto done; + if (wc != 26 && wc < 34) { + error = EBADRPC; + goto done; + } + md_get_uint8(mdp, NULL); /* secondary cmd */ + md_get_uint8(mdp, NULL); /* mbz */ + md_get_uint16le(mdp, NULL); /* andxoffset */ + md_get_uint8(mdp, NULL); /* oplock lvl granted */ + md_get_uint16le(mdp, &fid); /* file ID */ + md_get_uint32le(mdp, &createact); /* create_action */ + + md_get_uint64le(mdp, &llongint); /* creation time */ + smb_time_NT2local(llongint, &fa.fa_createtime); + md_get_uint64le(mdp, &llongint); /* access time */ + smb_time_NT2local(llongint, &fa.fa_atime); + md_get_uint64le(mdp, &llongint); /* write time */ + smb_time_NT2local(llongint, &fa.fa_mtime); + md_get_uint64le(mdp, &llongint); /* change time */ + smb_time_NT2local(llongint, &fa.fa_ctime); + + md_get_uint32le(mdp, &longint); /* attributes */ + fa.fa_attr = longint; + md_get_uint64le(mdp, &llongint); /* allocation size */ + fa.fa_allocsz = llongint; + md_get_uint64le(mdp, &llongint); /* EOF position */ + fa.fa_size = llongint; + + error = md_get_uint16le(mdp, NULL); /* file type */ + /* other stuff we don't care about */ + +done: + smb_rq_done(rqp); + if (error) + return (error); + + *fidp = fid; + if (cr_act_p) + *cr_act_p = createact; + if (fap) + *fap = fa; /* struct copy */ + + return (0); +} + +int +smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime, + struct smb_cred *scrp) +{ + struct smb_rq rq, *rqp = &rq; + struct mbchain *mbp; + long time; + int error; + + error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp); + if (error) + return (error); + smb_rq_getrequest(rqp, &mbp); + smb_rq_wstart(rqp); + mb_put_uint16le(mbp, fid); + if (mtime) { + int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz; + smb_time_local2server(mtime, sv_tz, &time); + } else { + time = 0; + } + mb_put_uint32le(mbp, time); + smb_rq_wend(rqp); + smb_rq_bstart(rqp); + smb_rq_bend(rqp); + + /* Make sure we send it... */ + rqp->sr_flags |= SMBR_NOINTR_SEND; + error = smb_rq_simple(rqp); + smb_rq_done(rqp); + return (error); +} + +int +smb_smb_open_prjob( + struct smb_share *ssp, + char *title, + uint16_t setuplen, + uint16_t mode, + struct smb_cred *scrp, + uint16_t *fidp) +{ + struct smb_rq rq, *rqp = &rq; + struct smb_vc *vcp = SSTOVC(ssp); + struct mbchain *mbp; + struct mdchain *mdp; + uint16_t fid; + uint8_t wc; + int error; + + error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN_PRINT_FILE, scrp); + if (error) + return (error); + smb_rq_getrequest(rqp, &mbp); + + /* Word parameters */ + smb_rq_wstart(rqp); + mb_put_uint16le(mbp, setuplen); + mb_put_uint16le(mbp, mode); + smb_rq_wend(rqp); + + /* + * Byte parameters: Just the title + */ + smb_rq_bstart(rqp); + mb_put_uint8(mbp, SMB_DT_ASCII); + error = smb_put_dstring(mbp, vcp, title, SMB_CS_NONE); + smb_rq_bend(rqp); + if (error) + goto done; + + /* + * Don't want to risk missing a successful + * open response, or we could "leak" FIDs. + */ + rqp->sr_flags |= SMBR_NOINTR_RECV; + error = smb_rq_simple_timed(rqp, smb_timo_open); + if (error) + goto done; + + smb_rq_getreply(rqp, &mdp); + error = md_get_uint8(mdp, &wc); + if (error || wc < 1) { + error = EBADRPC; + goto done; + } + error = md_get_uint16le(mdp, &fid); + +done: + smb_rq_done(rqp); + if (error) + return (error); + + *fidp = fid; + return (0); +} + +/* + * Like smb_smb_close, but for print shares. + */ +int +smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid, + struct smb_cred *scrp) +{ + struct smb_rq rq, *rqp = &rq; + struct mbchain *mbp; + int error; + + error = smb_rq_init(rqp, SSTOCP(ssp), + SMB_COM_CLOSE_PRINT_FILE, scrp); + if (error) + return (error); + smb_rq_getrequest(rqp, &mbp); + smb_rq_wstart(rqp); + mb_put_uint16le(mbp, fid); + smb_rq_wend(rqp); + smb_rq_bstart(rqp); + smb_rq_bend(rqp); + + /* Make sure we send it... */ + rqp->sr_flags |= SMBR_NOINTR_SEND; + error = smb_rq_simple(rqp); + smb_rq_done(rqp); + return (error); +} + +/* * Common function for read/write with UIO. * Called by netsmb smb_usr_rw, * smbfs_readvnode, smbfs_writevnode diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h Thu Jun 30 17:58:05 2011 -0400 @@ -33,6 +33,7 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -42,6 +43,7 @@ #include #include #include +#include /* Helper function for SMBERROR */ /*PRINTFLIKE3*/ @@ -84,6 +86,27 @@ struct smb_vc; /* + * These are the attributes we can get from the server via + * SMB commands such as TRANS2_QUERY_FILE_INFORMATION + * with info level SMB_QFILEINFO_ALL_INFO, and directory + * FindFirst/FindNext info. levels FIND_DIRECTORY_INFO + * and FIND_BOTH_DIRECTORY_INFO, etc. + * + * Values in this struct are always native endian, + * and times are converted converted to Unix form. + * Note: zero in any of the times means "unknown". + */ +typedef struct smbfattr { + timespec_t fa_createtime; /* Note, != ctime */ + timespec_t fa_atime; /* these 3 are like unix */ + timespec_t fa_mtime; + timespec_t fa_ctime; + u_offset_t fa_size; /* EOF position */ + u_offset_t fa_allocsz; /* Allocated size. */ + uint32_t fa_attr; /* Ext. file (DOS) attr */ +} smbfattr_t; + +/* * Tunable timeout values. See: smb_smb.c */ extern int smb_timo_notice; @@ -129,6 +152,39 @@ const uchar_t *, size_t); void smb_crypto_mech_init(void); + +/* + * SMB protocol level functions + */ +int smb_smb_echo(smb_vc_t *vcp, smb_cred_t *scred, int timo); +int smb_smb_treeconnect(smb_share_t *ssp, smb_cred_t *scred); +int smb_smb_treedisconnect(smb_share_t *ssp, smb_cred_t *scred); + +int +smb_smb_ntcreate(struct smb_share *ssp, struct mbchain *name_mb, + uint32_t crflag, uint32_t req_acc, uint32_t efa, uint32_t sh_acc, + uint32_t disp, uint32_t createopt, uint32_t impersonate, + struct smb_cred *scrp, uint16_t *fidp, + uint32_t *cr_act_p, struct smbfattr *fap); + +int smb_smb_close(struct smb_share *ssp, uint16_t fid, + struct timespec *mtime, struct smb_cred *scrp); + +int +smb_smb_open_prjob(struct smb_share *ssp, char *title, + uint16_t setuplen, uint16_t mode, + struct smb_cred *scrp, uint16_t *fidp); + +int smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid, + struct smb_cred *scrp); + +int smb_rwuio(smb_share_t *ssp, uint16_t fid, uio_rw_t rw, + uio_t *uiop, smb_cred_t *scred, int timo); + +/* + * time conversions + */ + void smb_time_init(void); void smb_time_fini(void); diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c --- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -199,8 +200,7 @@ out: if (rqp != NULL) smb_rq_done(rqp); /* free rqp */ - if (ioc != NULL) - kmem_free(ioc, sizeof (*ioc)); + kmem_free(ioc, sizeof (*ioc)); smb_credrele(&scred); return (err); @@ -239,14 +239,24 @@ goto out; } + /* + * Fill in the FID for libsmbfs transact named pipe. + */ + if (ioc->ioc_setupcnt > 1 && ioc->ioc_setup[1] == 0xFFFF) { + if (sdp->sd_vcgenid != ssp->ss_vcgenid) { + err = ESTALE; + goto out; + } + ioc->ioc_setup[1] = (uint16_t)sdp->sd_smbfid; + } + t2p = kmem_alloc(sizeof (*t2p), KM_SLEEP); err = smb_t2_init(t2p, SSTOCP(ssp), ioc->ioc_setup, ioc->ioc_setupcnt, &scred); if (err) goto out; - len = t2p->t2_setupcount = ioc->ioc_setupcnt; - if (len > 1) - t2p->t2_setupdata = ioc->ioc_setup; + t2p->t2_setupcount = ioc->ioc_setupcnt; + t2p->t2_setupdata = ioc->ioc_setup; /* This ioc member is a fixed-size array. */ if (ioc->ioc_name[0]) { @@ -319,8 +329,7 @@ smb_t2_done(t2p); kmem_free(t2p, sizeof (*t2p)); } - if (ioc != NULL) - kmem_free(ioc, sizeof (*ioc)); + kmem_free(ioc, sizeof (*ioc)); smb_credrele(&scred); return (err); @@ -352,7 +361,7 @@ smbioc_rw_t *ioc = NULL; struct iovec aiov[1]; struct uio auio; - u_int16_t fh; + uint16_t fh; int err; uio_rw_t rw; @@ -383,7 +392,14 @@ goto out; } - fh = ioc->ioc_fh; + /* + * If caller passes -1 in ioc_fh, then + * use the FID from SMBIOC_NTCREATE. + */ + if (ioc->ioc_fh == -1) + fh = (uint16_t)sdp->sd_smbfid; + else + fh = (uint16_t)ioc->ioc_fh; aiov[0].iov_base = ioc->ioc_base; aiov[0].iov_len = (size_t)ioc->ioc_cnt; @@ -407,8 +423,154 @@ (void) ddi_copyout(ioc, (void *)arg, sizeof (*ioc), flags); out: - if (ioc != NULL) - kmem_free(ioc, sizeof (*ioc)); + kmem_free(ioc, sizeof (*ioc)); + smb_credrele(&scred); + + return (err); +} + +/* + * Helper for nsmb_ioctl case + * SMBIOC_NTCREATE + */ +int +smb_usr_ntcreate(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) +{ + struct smb_cred scred; + struct mbchain name_mb; + struct smb_share *ssp; + smbioc_ntcreate_t *ioc = NULL; + uint16_t fid; + int err, nmlen; + + /* This ioctl requires a share. */ + if ((ssp = sdp->sd_share) == NULL) + return (ENOTCONN); + + /* Must not be already open. */ + if (sdp->sd_smbfid != -1) + return (EINVAL); + + mb_init(&name_mb); + smb_credinit(&scred, cr); + ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); + if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { + err = EFAULT; + goto out; + } + + /* Build name_mb */ + ioc->ioc_name[SMBIOC_MAX_NAME-1] = '\0'; + nmlen = strnlen(ioc->ioc_name, SMBIOC_MAX_NAME-1); + err = smb_put_dmem(&name_mb, SSTOVC(ssp), + ioc->ioc_name, nmlen, + SMB_CS_NONE, NULL); + if (err != 0) + goto out; + + /* Do the OtW open, save the FID. */ + err = smb_smb_ntcreate(ssp, &name_mb, + 0, /* create flags */ + ioc->ioc_req_acc, + ioc->ioc_efattr, + ioc->ioc_share_acc, + ioc->ioc_open_disp, + ioc->ioc_creat_opts, + NTCREATEX_IMPERSONATION_IMPERSONATION, + &scred, + &fid, + NULL, + NULL); + if (err != 0) + goto out; + + sdp->sd_smbfid = fid; + sdp->sd_vcgenid = ssp->ss_vcgenid; + +out: + kmem_free(ioc, sizeof (*ioc)); + smb_credrele(&scred); + mb_done(&name_mb); + + return (err); +} + +/* + * Helper for nsmb_ioctl case + * SMBIOC_PRINTJOB + */ +int +smb_usr_printjob(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr) +{ + struct smb_cred scred; + struct smb_share *ssp; + smbioc_printjob_t *ioc = NULL; + uint16_t fid; + int err; + + /* This ioctl requires a share. */ + if ((ssp = sdp->sd_share) == NULL) + return (ENOTCONN); + + /* The share must be a print queue. */ + if (ssp->ss_type != STYPE_PRINTQ) + return (EINVAL); + + /* Must not be already open. */ + if (sdp->sd_smbfid != -1) + return (EINVAL); + + smb_credinit(&scred, cr); + ioc = kmem_alloc(sizeof (*ioc), KM_SLEEP); + if (ddi_copyin((void *) arg, ioc, sizeof (*ioc), flags)) { + err = EFAULT; + goto out; + } + ioc->ioc_title[SMBIOC_MAX_NAME-1] = '\0'; + + /* Do the OtW open, save the FID. */ + err = smb_smb_open_prjob(ssp, ioc->ioc_title, + ioc->ioc_setuplen, ioc->ioc_prmode, + &scred, &fid); + if (err != 0) + goto out; + + sdp->sd_smbfid = fid; + sdp->sd_vcgenid = ssp->ss_vcgenid; + +out: + kmem_free(ioc, sizeof (*ioc)); + smb_credrele(&scred); + + return (err); +} + +/* + * Helper for nsmb_ioctl case + * SMBIOC_CLOSEFH + */ +int +smb_usr_closefh(smb_dev_t *sdp, cred_t *cr) +{ + struct smb_cred scred; + struct smb_share *ssp; + uint16_t fid; + int err; + + /* This ioctl requires a share. */ + if ((ssp = sdp->sd_share) == NULL) + return (ENOTCONN); + + if (sdp->sd_smbfid == -1) + return (0); + fid = (uint16_t)sdp->sd_smbfid; + sdp->sd_smbfid = -1; + + smb_credinit(&scred, cr); + if (ssp->ss_type == STYPE_PRINTQ) + err = smb_smb_close_prjob(ssp, fid, &scred); + else + err = smb_smb_close(ssp, fid, NULL, &scred); smb_credrele(&scred); return (err); @@ -514,8 +676,7 @@ /* Error path: rele hold from _findcreate */ smb_vc_rele(vcp); } - if (ossn != NULL) - kmem_free(ossn, sizeof (*ossn)); + kmem_free(ossn, sizeof (*ossn)); smb_credrele(&scred); return (error); @@ -583,8 +744,6 @@ */ tcon->tc_sh.sh_name[SMBIOC_MAX_NAME-1] = '\0'; tcon->tc_sh.sh_pass[SMBIOC_MAX_NAME-1] = '\0'; - tcon->tc_sh.sh_type_req[SMBIOC_STYPE_LEN-1] = '\0'; - bzero(tcon->tc_sh.sh_type_ret, SMBIOC_STYPE_LEN); if (cmd == SMBIOC_TREE_CONNECT) tcon->tc_opt |= SMBSOPT_CREATE; @@ -612,8 +771,7 @@ * the tree connect response, so they can * see if they got the requested type. */ - (void) memcpy(tcon->tc_sh.sh_type_ret, - ssp->ss_type_ret, SMBIOC_STYPE_LEN); + tcon->tc_sh.sh_type = ssp->ss_type; /* * The share has a hold from _tcon @@ -630,14 +788,12 @@ /* Error path: rele hold from _findcreate */ smb_share_rele(ssp); } - if (tcon) { - /* - * This structure may contain a - * cleartext password, so zap it. - */ - bzero(tcon, sizeof (*tcon)); - kmem_free(tcon, sizeof (*tcon)); - } + /* + * This structure may contain a + * cleartext password, so zap it. + */ + bzero(tcon, sizeof (*tcon)); + kmem_free(tcon, sizeof (*tcon)); smb_credrele(&scred); return (error); diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c --- a/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/netsmb/subr_mchain.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -109,9 +110,6 @@ * hurt transports that support larger frames. * 4K fits nicely in 3 Ethernet frames (3 * 1500) * leaving about 500 bytes for protocol headers. - * - * XXX: Would Ethernet drivers be happier - * (more efficient) if we used 1K here? */ #define MLEN 4096 @@ -543,14 +541,36 @@ int mb_put_mbuf(struct mbchain *mbp, mblk_t *m) { - mblk_t *mb; + mblk_t *nm, *tail_mb; + size_t size; /* See: linkb(9f) */ - for (mb = mbp->mb_cur; mb->b_cont; mb = mb->b_cont) - ; - mb->b_cont = m; - mbp->mb_cur = m; - mbp->mb_count += msgdsize(m); + tail_mb = mbp->mb_cur; + while (tail_mb->b_cont != NULL) + tail_mb = tail_mb->b_cont; + + /* + * Avoid small frags: Only link if the size of the + * new mbuf is larger than the space left in the last + * mblk of the chain (tail), otherwise just copy. + */ + while (m != NULL) { + size = MBLKL(m); + if (size > MBLKTAIL(tail_mb)) { + /* Link */ + tail_mb->b_cont = m; + mbp->mb_cur = m; + mbp->mb_count += msgdsize(m); + return (0); + } + /* Copy */ + bcopy(m->b_rptr, tail_mb->b_wptr, size); + tail_mb->b_wptr += size; + mbp->mb_count += size; + nm = unlinkb(m); + freeb(m); + m = nm; + } return (0); } diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_node.h Thu Jun 30 17:58:05 2011 -0400 @@ -33,6 +33,7 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,35 +48,13 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif /* - * These are the attributes we can get from the server via - * SMB commands such as TRANS2_QUERY_FILE_INFORMATION - * with info level SMB_QFILEINFO_ALL_INFO, and directory - * FindFirst/FindNext info. levels FIND_DIRECTORY_INFO - * and FIND_BOTH_DIRECTORY_INFO, etc. - * - * Values in this struct are always native endian, - * and times are converted converted to Unix form. - * Note: zero in any of the times means "unknown". - * - * XXX: Later, move this to nsmb - */ -typedef struct smbfattr { - timespec_t fa_createtime; /* Note, != ctime */ - timespec_t fa_atime; /* these 3 are like unix */ - timespec_t fa_mtime; - timespec_t fa_ctime; - u_offset_t fa_size; /* EOF position */ - u_offset_t fa_allocsz; /* Allocated size. */ - uint32_t fa_attr; /* Ext. file (DOS) attr */ -} smbfattr_t; - -/* * Cache whole directories (not yet) */ typedef struct rddir_cache { diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -273,7 +274,7 @@ if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) { mb_put_uint32le(mbp, 0); /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */ - error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); + error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\'); if (error) { smb_t2_done(t2p); return (error); @@ -800,7 +801,7 @@ mb_put_uint8(mbp, SMB_DT_ASCII); error = smbfs_fullpath(mbp, SSTOVC(ssp), np, - name, &nmlen, '\\'); + name, nmlen, '\\'); if (error) goto out; smb_rq_bend(rqp); @@ -865,7 +866,7 @@ smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &len, '\\'); + error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, len, '\\'); if (error) goto out; mb_put_uint8(mbp, SMB_DT_ASCII); @@ -1057,7 +1058,7 @@ mb_put_uint32le(mbp, 0); /* MBZ */ if (cmd == SMB_TRANS2_SET_PATH_INFORMATION) { - error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, '\\'); + error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\'); if (error != 0) goto out; } @@ -1096,21 +1097,6 @@ /* * Modern create/open of file or directory. - * - * If disp is ..._DISP_OPEN, or ...DISP_OPEN_IF, or... - * then this is an open attempt, and: - * If xattr then name is the stream to be opened at np, - * Else np should be opened. - * ...we won't touch *fidp, - * ...we will set or clear *attrcacheupdated. - * Else this is a creation attempt, and: - * If xattr then name is the stream to create at np, - * Else name is the thing to create under directory np. - * ...we will return *fidp, - * ...we won't touch *attrcacheupdated. - * - * Note, We use: disp = ...OPEN_IF, ...OVERWRITE_IF, etc. - * now too, which may or may not create a new object. */ int smbfs_smb_ntcreatex( @@ -1124,119 +1110,33 @@ uint32_t disp, /* open disposition */ uint32_t createopt, /* NTCREATEX_OPTIONS_ */ struct smb_cred *scrp, - uint16_t *fidp, - uint32_t *cr_act_p, /* create action */ - struct smbfattr *fap) /* optional */ + uint16_t *fidp, /* returned FID */ + uint32_t *cr_act_p, /* optional returned create action */ + struct smbfattr *fap) /* optional returned attributes */ { - struct smb_rq rq, *rqp = &rq; + struct mbchain name_mb; struct smb_share *ssp = np->n_mount->smi_share; - struct smb_vc *vcp = SSTOVC(ssp); - struct mbchain *mbp; - struct mdchain *mdp; - struct smbfattr fa; - uint8_t wc; - uint32_t longint, createact; - uint64_t llongint; - int error; - uint16_t fid, *namelenp; + int err; - bzero(&fa, sizeof (fa)); - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp); - if (error) - return (error); - smb_rq_getrequest(rqp, &mbp); - smb_rq_wstart(rqp); - mb_put_uint8(mbp, 0xff); /* secondary command */ - mb_put_uint8(mbp, 0); /* MBZ */ - mb_put_uint16le(mbp, 0); /* offset to next command (none) */ - mb_put_uint8(mbp, 0); /* MBZ */ - namelenp = (uint16_t *)mb_reserve(mbp, sizeof (uint16_t)); - /* - * XP to a W2K Server does not use NTCREATEX_FLAGS_OPEN_DIRECTORY - * for creating nor for opening a directory. Samba ignores the bit. - */ - mb_put_uint32le(mbp, 0); /* NTCREATEX_FLAGS_* */ - mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ - mb_put_uint32le(mbp, req_acc); - mb_put_uint64le(mbp, 0); /* "initial allocation size" */ - mb_put_uint32le(mbp, efa); - mb_put_uint32le(mbp, share_acc); - mb_put_uint32le(mbp, disp); - mb_put_uint32le(mbp, createopt); - mb_put_uint32le(mbp, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */ - mb_put_uint8(mbp, 0); /* security flags (?) */ - smb_rq_wend(rqp); - smb_rq_bstart(rqp); + mb_init(&name_mb); if (name == NULL) nmlen = 0; - error = smbfs_fullpath(mbp, vcp, np, name, &nmlen, - xattr ? ':' : '\\'); - if (error) - goto done; - *namelenp = htoles(nmlen); /* includes null */ - smb_rq_bend(rqp); - /* - * Don't want to risk missing a successful - * open response, or we could "leak" FIDs. - */ - rqp->sr_flags |= SMBR_NOINTR_RECV; - error = smb_rq_simple_timed(rqp, smb_timo_open); - if (error) - goto done; - smb_rq_getreply(rqp, &mdp); - /* - * spec says 26 for word count, but 34 words are defined - * and observed from win2000 - */ - error = md_get_uint8(mdp, &wc); - if (error) - goto done; - if (wc != 26 && wc != 34 && wc != 42) { - error = EBADRPC; - goto done; - } - md_get_uint8(mdp, NULL); /* secondary cmd */ - md_get_uint8(mdp, NULL); /* mbz */ - md_get_uint16le(mdp, NULL); /* andxoffset */ - md_get_uint8(mdp, NULL); /* oplock lvl granted */ - md_get_uint16le(mdp, &fid); /* file ID */ - md_get_uint32le(mdp, &createact); /* create_action */ + err = smbfs_fullpath(&name_mb, SSTOVC(ssp), + np, name, nmlen, xattr ? ':' : '\\'); + if (err) + goto out; - md_get_uint64le(mdp, &llongint); /* creation time */ - smb_time_NT2local(llongint, &fa.fa_createtime); - md_get_uint64le(mdp, &llongint); /* access time */ - smb_time_NT2local(llongint, &fa.fa_atime); - md_get_uint64le(mdp, &llongint); /* write time */ - smb_time_NT2local(llongint, &fa.fa_mtime); - md_get_uint64le(mdp, &llongint); /* change time */ - smb_time_NT2local(llongint, &fa.fa_ctime); - - md_get_uint32le(mdp, &longint); /* attributes */ - fa.fa_attr = longint; - - md_get_uint64le(mdp, &llongint); /* allocation size */ - fa.fa_allocsz = llongint; + err = smb_smb_ntcreate(ssp, &name_mb, + 0, /* NTCREATEX_FLAGS... */ + req_acc, efa, share_acc, disp, createopt, + NTCREATEX_IMPERSONATION_IMPERSONATION, + scrp, fidp, cr_act_p, fap); - md_get_uint64le(mdp, &llongint); /* EOF position */ - fa.fa_size = llongint; - - error = md_get_uint16le(mdp, NULL); /* file type */ - /* other stuff we don't care about */ +out: + mb_done(&name_mb); -done: - smb_rq_done(rqp); - if (error) - return (error); - - if (fidp) - *fidp = fid; - if (cr_act_p) - *cr_act_p = createact; - if (fap) - *fap = fa; /* struct copy */ - - return (0); + return (err); } static uint32_t @@ -1335,7 +1235,7 @@ smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, vcp, np, name, &nmlen, + error = smbfs_fullpath(mbp, vcp, np, name, nmlen, xattr ? ':' : '\\'); if (error) goto done; @@ -1514,41 +1414,14 @@ } int -smbfs_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime, - struct smb_cred *scrp) +smbfs_smb_close(struct smb_share *ssp, uint16_t fid, + struct timespec *mtime, struct smb_cred *scrp) { - struct smb_rq rq, *rqp = &rq; - struct mbchain *mbp; - long time; int error; - error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp); - if (error) - return (error); - smb_rq_getrequest(rqp, &mbp); - smb_rq_wstart(rqp); - mb_put_uint16le(mbp, fid); - if (mtime) { - int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz; - smb_time_local2server(mtime, sv_tz, &time); - } else - time = 0; - mb_put_uint32le(mbp, time); - smb_rq_wend(rqp); - smb_rq_bstart(rqp); - smb_rq_bend(rqp); + error = smb_smb_close(ssp, fid, mtime, scrp); /* - * We don't really care about the result here, but we - * do need to make sure we send this out, or we could - * "leak" open file handles on interrupt or timeout. - * The NOINTR_SEND flag makes this request immune to - * interrupt or timeout until the send is done. - */ - rqp->sr_flags |= SMBR_NOINTR_SEND; - error = smb_rq_simple(rqp); - smb_rq_done(rqp); - /* * ENOTCONN isn't interesting - if the connection is closed, * so are all our FIDs - and EIO is also not interesting, * as it means a forced unmount was done. (was ENXIO) @@ -1596,7 +1469,7 @@ smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &nmlen, + error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, nmlen, xattr ? ':' : '\\'); if (error) goto out; @@ -1680,7 +1553,7 @@ smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, &nmlen, + error = smbfs_fullpath(mbp, SSTOVC(ssp), np, name, nmlen, xattr ? ':' : '\\'); if (!error) { smb_rq_bend(rqp); @@ -1718,7 +1591,7 @@ * passed sep is ignored, so just pass sep=0. */ mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, 0); + error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, 0); if (error) goto out; @@ -1727,7 +1600,7 @@ */ sep = (src->n_flag & N_XATTR) ? ':' : '\\'; mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, sep); + error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, sep); if (error) goto out; @@ -1759,11 +1632,11 @@ smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, NULL, '\\'); + error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, '\\'); if (error) goto out; mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, &tnmlen, '\\'); + error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, '\\'); if (error) goto out; smb_rq_bend(rqp); @@ -1791,7 +1664,7 @@ smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, &len, '\\'); + error = smbfs_fullpath(mbp, SSTOVC(ssp), dnp, name, len, '\\'); if (!error) { smb_rq_bend(rqp); error = smb_rq_simple(rqp); @@ -1850,7 +1723,7 @@ smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); - error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, NULL, '\\'); + error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0, '\\'); if (!error) { smb_rq_bend(rqp); error = smb_rq_simple(rqp); @@ -1868,7 +1741,7 @@ struct mdchain *mdp; uint8_t wc, bt; uint16_t ec, dlen, bc; - int len, maxent, error, iseof = 0; + int maxent, error, iseof = 0; maxent = min(ctx->f_left, (vcp->vc_txmax - SMB_HDRLEN - 2*2) / SMB_DENTRYLEN); @@ -1889,9 +1762,8 @@ smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); /* buffer format */ if (ctx->f_flags & SMBFS_RDD_FINDFIRST) { - len = ctx->f_wclen; - error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, - &len, '\\'); + error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, + ctx->f_wildcard, ctx->f_wclen, '\\'); if (error) return (error); mb_put_uint8(mbp, SMB_DT_VARIABLE); @@ -2029,7 +1901,7 @@ struct mbchain *mbp; struct mdchain *mdp; uint16_t ecnt, eos, lno, flags; - int len, error; + int error; if (ctx->f_t2) { smb_t2_done(ctx->f_t2); @@ -2053,9 +1925,8 @@ mb_put_uint16le(mbp, flags); mb_put_uint16le(mbp, ctx->f_infolevel); mb_put_uint32le(mbp, 0); - len = ctx->f_wclen; - error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, ctx->f_wildcard, - &len, '\\'); + error = smbfs_fullpath(mbp, vcp, ctx->f_dnp, + ctx->f_wildcard, ctx->f_wclen, '\\'); if (error) return (error); } else { diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.c Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -66,19 +67,15 @@ */ int smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, - const char *name, int *lenp, u_int8_t sep) + const char *name, int nmlen, u_int8_t sep) { int caseopt = SMB_CS_NONE; - int error, len = 0; int unicode = (SMB_UNICODE_STRINGS(vcp)) ? 1 : 0; + int error; if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) caseopt |= SMB_CS_UPPER; - if (lenp) { - len = *lenp; - *lenp = 0; - } if (unicode) { error = mb_put_padbyte(mbp); if (error) @@ -87,7 +84,7 @@ error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, - caseopt, lenp); + caseopt, NULL); if (name) { /* * Special case at share root: @@ -116,14 +113,12 @@ error = mb_put_uint16le(mbp, sep); else error = mb_put_uint8(mbp, sep); - if (!error && lenp) - *lenp += (unicode + 1); if (error) return (error); } /* Put the name */ error = smb_put_dmem(mbp, vcp, - name, len, caseopt, lenp); + name, nmlen, caseopt, NULL); if (error) return (error); } @@ -132,8 +127,6 @@ error = mb_put_uint16le(mbp, 0); else error = mb_put_uint8(mbp, 0); - if (!error && lenp) - *lenp += (unicode + 1); return (error); } diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h --- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_subr.h Thu Jun 30 17:58:05 2011 -0400 @@ -33,6 +33,7 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,6 +43,8 @@ #include #include +#include +#include #if defined(DEBUG) || defined(lint) #define SMB_VNODE_DEBUG 1 @@ -196,7 +199,7 @@ struct smb_cred *scrp); int smbfs_smb_findclose(struct smbfs_fctx *ctx, struct smb_cred *scrp); int smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, - struct smbnode *dnp, const char *name, int *nmlenp, uint8_t sep); + struct smbnode *dnp, const char *name, int nmlen, uint8_t sep); int smbfs_smb_lookup(struct smbnode *dnp, const char **namep, int *nmlenp, struct smbfattr *fap, struct smb_cred *scrp); int smbfs_smb_hideit(struct smbnode *np, const char *name, int len, diff -r a055831123f1 -r 96340372b72d usr/src/uts/common/netsmb/smb_dev.h --- a/usr/src/uts/common/netsmb/smb_dev.h Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/common/netsmb/smb_dev.h Thu Jun 30 17:58:05 2011 -0400 @@ -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. */ @@ -71,7 +72,7 @@ * make them incompatible with an old driver. */ #define NSMB_VERMAJ 1 -#define NSMB_VERMIN 3900 +#define NSMB_VERMIN 4000 #define NSMB_VERSION (NSMB_VERMAJ * 100000 + NSMB_VERMIN) /* @@ -217,14 +218,11 @@ /* * Structure used with SMBIOC_TREE_FIND, _CONNECT */ -#define SMBIOC_STYPE_LEN 8 struct smbioc_oshare { - uint32_t sh_pwlen; + uint32_t sh_use; /* requested */ + uint32_t sh_type; /* returned */ char sh_name[SMBIOC_MAX_NAME]; char sh_pass[SMBIOC_MAX_NAME]; - /* share types, in ASCII form, i.e. "A:", "IPC", ... */ - char sh_type_req[SMBIOC_STYPE_LEN]; /* requested */ - char sh_type_ret[SMBIOC_STYPE_LEN]; /* returned */ }; typedef struct smbioc_oshare smbioc_oshare_t; @@ -342,7 +340,7 @@ } smbioc_flags_t; typedef struct smbioc_rw { - uint32_t ioc_fh; + int32_t ioc_fh; uint32_t ioc_cnt; lloff_t _ioc_offset; lptr_t _ioc_base; @@ -350,6 +348,21 @@ #define ioc_offset _ioc_offset._f #define ioc_base _ioc_base.lp_ptr +typedef struct smbioc_ntcreate { + uint32_t ioc_req_acc; + uint32_t ioc_efattr; + uint32_t ioc_share_acc; + uint32_t ioc_open_disp; + uint32_t ioc_creat_opts; + char ioc_name[SMBIOC_MAX_NAME]; +} smbioc_ntcreate_t; + +typedef struct smbioc_printjob { + uint16_t ioc_setuplen; + uint16_t ioc_prmode; + char ioc_title[SMBIOC_MAX_NAME]; +} smbioc_printjob_t; + /* Password Keychain (PK) support. */ typedef struct smbioc_pk { uid_t pk_uid; /* UID for PAM use */ @@ -375,11 +388,16 @@ SMBIOC_GETVERS = SMBIOC_BASE, /* keep first */ SMBIOC_FLAGS2, /* get hflags2 */ SMBIOC_GETSSNKEY, /* get SMB session key */ + SMBIOC_DUP_DEV, /* duplicate dev handle */ SMBIOC_REQUEST, /* simple request */ SMBIOC_T2RQ, /* trans2 request */ + SMBIOC_READ, /* read (pipe) */ SMBIOC_WRITE, /* write (pipe) */ + SMBIOC_NTCREATE, /* open or create */ + SMBIOC_PRINTJOB, /* open print job */ + SMBIOC_CLOSEFH, /* from ntcreate or printjob */ SMBIOC_SSN_CREATE, SMBIOC_SSN_FIND, diff -r a055831123f1 -r 96340372b72d usr/src/uts/intel/nsmb/ioc_check.ref --- a/usr/src/uts/intel/nsmb/ioc_check.ref Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/intel/nsmb/ioc_check.ref Thu Jun 30 17:58:05 2011 -0400 @@ -8,15 +8,12 @@ #define SSN_ID 0x8 #define SSN_SRVNAME 0x228 #define SSN_SRVNAME_INCR 0x1 -#define SH_PWLEN 0x0 -#define SH_NAME 0x4 +#define SH_USE 0x0 +#define SH_TYPE 0x4 +#define SH_NAME 0x8 #define SH_NAME_INCR 0x1 -#define SH_PASS 0x104 +#define SH_PASS 0x108 #define SH_PASS_INCR 0x1 -#define SH_TYPE_REQ 0x204 -#define SH_TYPE_REQ_INCR 0x1 -#define SH_TYPE_RET 0x20c -#define SH_TYPE_RET_INCR 0x1 #define TC_FLAGS 0x0 #define TC_OPT 0x4 #define TC_SH 0x8 @@ -61,8 +58,8 @@ #define IOC_SETUP 0x0 #define IOC_SETUP_INCR 0x2 #define IOC_SETUPCNT 0x8 -#define IOC_NAME 0xc -#define IOC_NAME_INCR 0x1 +#define IOC_T2_NAME 0xc +#define IOC_T2_NAME_INCR 0x1 #define IOC_TPARAMCNT 0x8c #define IOC_TDATACNT 0x8e #define IOC_RPARAMCNT 0x90 @@ -84,6 +81,19 @@ #define IOC_CNT 0x4 #define _IOC_OFFSET 0x8 #define _IOC_BASE 0x10 +#define SIZEOF_NTCREATE 0x114 +#define IOC_REQ_ACC 0x0 +#define IOC_EFATTR 0x4 +#define IOC_SHARE_ACC 0x8 +#define IOC_OPEN_DISP 0xc +#define IOC_CREAT_OPTS 0x10 +#define IOC_NTCR_NAME 0x14 +#define IOC_NTCR_NAME_INCR 0x1 +#define SIZEOF_PRINTJOB 0x104 +#define IOC_SETUPLEN 0x0 +#define IOC_PRMODE 0x2 +#define IOC_TITLE 0x4 +#define IOC_TITLE_INCR 0x1 #define SIZEOF_SMBIOC_PK 0x224 #define PK_UID 0x0 #define PK_DOM 0x4 diff -r a055831123f1 -r 96340372b72d usr/src/uts/sparc/nsmb/ioc_check.ref --- a/usr/src/uts/sparc/nsmb/ioc_check.ref Fri Jun 24 08:44:32 2011 -0700 +++ b/usr/src/uts/sparc/nsmb/ioc_check.ref Thu Jun 30 17:58:05 2011 -0400 @@ -8,15 +8,12 @@ #define SSN_ID 0x8 #define SSN_SRVNAME 0x228 #define SSN_SRVNAME_INCR 0x1 -#define SH_PWLEN 0x0 -#define SH_NAME 0x4 +#define SH_USE 0x0 +#define SH_TYPE 0x4 +#define SH_NAME 0x8 #define SH_NAME_INCR 0x1 -#define SH_PASS 0x104 +#define SH_PASS 0x108 #define SH_PASS_INCR 0x1 -#define SH_TYPE_REQ 0x204 -#define SH_TYPE_REQ_INCR 0x1 -#define SH_TYPE_RET 0x20c -#define SH_TYPE_RET_INCR 0x1 #define TC_FLAGS 0x0 #define TC_OPT 0x4 #define TC_SH 0x8 @@ -61,8 +58,8 @@ #define IOC_SETUP 0x0 #define IOC_SETUP_INCR 0x2 #define IOC_SETUPCNT 0x8 -#define IOC_NAME 0xc -#define IOC_NAME_INCR 0x1 +#define IOC_T2_NAME 0xc +#define IOC_T2_NAME_INCR 0x1 #define IOC_TPARAMCNT 0x8c #define IOC_TDATACNT 0x8e #define IOC_RPARAMCNT 0x90 @@ -84,6 +81,19 @@ #define IOC_CNT 0x4 #define _IOC_OFFSET 0x8 #define _IOC_BASE 0x10 +#define SIZEOF_NTCREATE 0x114 +#define IOC_REQ_ACC 0x0 +#define IOC_EFATTR 0x4 +#define IOC_SHARE_ACC 0x8 +#define IOC_OPEN_DISP 0xc +#define IOC_CREAT_OPTS 0x10 +#define IOC_NTCR_NAME 0x14 +#define IOC_NTCR_NAME_INCR 0x1 +#define SIZEOF_PRINTJOB 0x104 +#define IOC_SETUPLEN 0x0 +#define IOC_PRMODE 0x2 +#define IOC_TITLE 0x4 +#define IOC_TITLE_INCR 0x1 #define SIZEOF_SMBIOC_PK 0x224 #define PK_UID 0x0 #define PK_DOM 0x4