summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Ross <Gordon.Ross@Sun.COM>2008-12-04 12:51:31 -0500
committerGordon Ross <Gordon.Ross@Sun.COM>2008-12-04 12:51:31 -0500
commit9c9af2590af49bb395bc8d2eace0f2d4ea16d165 (patch)
treed7b65e8be9071e7f1a693ce58b136d1068ee496c
parentfc3af78a71855c71878866a294572d00e6720533 (diff)
downloadillumos-joyent-9c9af2590af49bb395bc8d2eace0f2d4ea16d165.tar.gz
6565868 Client should do packet signing
6673604 libshare_smbfs initprotofromdefaults() leaks memory 6684418 smbfs seems to ignore O_*SYNC open flags 6710493 smbfs doesn't interoperate with a MacOS share 6750718 move CIFS client kmdb modules to /usr/kernel/kmdb 6759403 various fixes for named-pipe support
-rw-r--r--usr/src/cmd/fs.d/smbclnt/mount/mount.c6
-rw-r--r--usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c42
-rw-r--r--usr/src/cmd/fs.d/smbclnt/smbutil/view.c4
-rw-r--r--usr/src/cmd/mdb/intel/amd64/nsmb/Makefile11
-rw-r--r--usr/src/cmd/mdb/intel/amd64/smbfs/Makefile10
-rw-r--r--usr/src/cmd/mdb/intel/ia32/nsmb/Makefile11
-rw-r--r--usr/src/cmd/mdb/intel/ia32/smbfs/Makefile10
-rw-r--r--usr/src/cmd/mdb/sparc/v9/nsmb/Makefile11
-rw-r--r--usr/src/cmd/mdb/sparc/v9/smbfs/Makefile10
-rw-r--r--usr/src/lib/libshare/common/libshare.c14
-rw-r--r--usr/src/lib/libshare/smbfs/libshare_smbfs.c155
-rw-r--r--usr/src/lib/libshare/smbfs/libshare_smbfs.h13
-rw-r--r--usr/src/lib/libsmbfs/Makefile.com5
-rw-r--r--usr/src/lib/libsmbfs/netsmb/nb_lib.h59
-rw-r--r--usr/src/lib/libsmbfs/netsmb/smb_lib.h136
-rw-r--r--usr/src/lib/libsmbfs/netsmb/smb_rap.h12
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_api.c3
-rw-r--r--usr/src/lib/libsmbfs/smb/acl_conv.c77
-rw-r--r--usr/src/lib/libsmbfs/smb/charsets.c173
-rw-r--r--usr/src/lib/libsmbfs/smb/charsets.h5
-rw-r--r--usr/src/lib/libsmbfs/smb/ctx.c66
-rw-r--r--usr/src/lib/libsmbfs/smb/file.c265
-rw-r--r--usr/src/lib/libsmbfs/smb/mapfile-vers56
-rw-r--r--usr/src/lib/libsmbfs/smb/mbuf.c49
-rw-r--r--usr/src/lib/libsmbfs/smb/nb_name.c3
-rw-r--r--usr/src/lib/libsmbfs/smb/nb_net.c126
-rw-r--r--usr/src/lib/libsmbfs/smb/nbns_rq.c36
-rw-r--r--usr/src/lib/libsmbfs/smb/netshareenum.c68
-rw-r--r--usr/src/lib/libsmbfs/smb/print.c3
-rw-r--r--usr/src/lib/libsmbfs/smb/private.h154
-rw-r--r--usr/src/lib/libsmbfs/smb/rap.c50
-rw-r--r--usr/src/lib/libsmbfs/smb/rcfile.c18
-rw-r--r--usr/src/lib/libsmbfs/smb/rq.c11
-rw-r--r--usr/src/lib/libsmbfs/smb/subr.c83
-rw-r--r--usr/src/lib/libsmbfs/smb/utf_str.c207
-rw-r--r--usr/src/pkgdefs/SUNWsmbfskr/prototype_com9
-rw-r--r--usr/src/pkgdefs/SUNWsmbfskr/prototype_i3867
-rw-r--r--usr/src/pkgdefs/SUNWsmbfskr/prototype_sparc5
-rw-r--r--usr/src/pkgdefs/SUNWsmbfsu/prototype_com9
-rw-r--r--usr/src/pkgdefs/SUNWsmbfsu/prototype_i38618
-rw-r--r--usr/src/pkgdefs/SUNWsmbfsu/prototype_sparc13
-rw-r--r--usr/src/uts/common/Makefile.files4
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c10
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h20
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_crypt.c442
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c5
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c31
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c72
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.h16
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c1206
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h20
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c32
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_io.c206
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c6
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c133
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c3
-rw-r--r--usr/src/uts/common/netsmb/smb_dev.h11
-rw-r--r--usr/src/uts/intel/smbfs/Makefile8
-rw-r--r--usr/src/uts/sparc/smbfs/Makefile8
59 files changed, 2523 insertions, 1733 deletions
diff --git a/usr/src/cmd/fs.d/smbclnt/mount/mount.c b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
index de15bcc8e2..a1a413d1e2 100644
--- a/usr/src/cmd/fs.d/smbclnt/mount/mount.c
+++ b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
@@ -33,12 +33,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/errno.h>
@@ -146,7 +144,6 @@ main(int argc, char *argv[])
struct smb_ctx sctx, *ctx = &sctx;
struct smbfs_args mdata;
struct stat st;
- extern void dropsuid();
int opt, error, mntflags;
struct mnttab mnt;
struct mnttab *mntp = &mnt;
@@ -159,7 +156,6 @@ main(int argc, char *argv[])
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
- dropsuid();
if (argc == 2) {
if (strcmp(argv[1], "-h") == 0) {
usage();
diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c b/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c
index 831247ba9d..ca5eeb425d 100644
--- a/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c
+++ b/usr/src/cmd/fs.d/smbclnt/smbutil/smbutil.c
@@ -1,4 +1,39 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <sys/param.h>
#include <sys/time.h>
@@ -100,12 +135,13 @@ main(int argc, char *argv[])
struct commands *cmd;
char *cp;
int opt;
- extern void dropsuid();
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
- dropsuid();
+#ifdef APPLE
+ dropsuid(); /* see libsmbfs */
+#endif
if (argc < 2)
help();
diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/view.c b/usr/src/cmd/fs.d/smbclnt/smbutil/view.c
index 1e2dbf4e4c..035d15132d 100644
--- a/usr/src/cmd/fs.d/smbclnt/smbutil/view.c
+++ b/usr/src/cmd/fs.d/smbclnt/smbutil/view.c
@@ -32,8 +32,6 @@
* $Id: view.c,v 1.9 2004/12/13 00:25:39 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/stat.h>
@@ -132,9 +130,11 @@ reauth:
gettext(shtype[sti]),
ep->remark ? ep->remark : "");
free(ep->netname);
+ free(ep->remark);
}
printf(gettext("\n%d shares listed from %d available\n"),
entries, total);
+
free(share_info);
smb_ctx_done(ctx);
#ifdef APPLE
diff --git a/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile b/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile
index abc6f621bc..96184f1cf0 100644
--- a/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile
+++ b/usr/src/cmd/mdb/intel/amd64/nsmb/Makefile
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-#pragma ident "%Z%%M% %I% %E% SMI"
-
MDBTGT = kvm
MODULE = nsmb.so
MODSRCS_DIR = ../../../common/modules/nsmb
@@ -32,6 +30,10 @@ MODSRCS = nsmb.c
include ../../../../Makefile.cmd
include ../../../../Makefile.cmd.64
include ../../Makefile.amd64
+
+# This kmod goes in /usr/kernel/kmdb
+ROOTKMOD = $(ROOT)/usr/kernel/kmdb$(MACHMODDIR)
+
include ../../../Makefile.module
CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/netsmb
@@ -39,3 +41,8 @@ CPPFLAGS += -I$(SRC)/uts/common
C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
+
+# maybe not the best place for this, but
+# we need to create this directory.
+$(ROOTKMOD):
+ $(INS.dir)
diff --git a/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile b/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile
index f15a826c2c..dafacf41ee 100644
--- a/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile
+++ b/usr/src/cmd/mdb/intel/amd64/smbfs/Makefile
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-#pragma ident "%Z%%M% %I% %E% SMI"
-
MDBTGT = kvm
MODULE = smbfs.so
MODSRCS_DIR = ../../../common/modules/smbfs
@@ -32,8 +30,16 @@ MODSRCS = smbfs.c
include ../../../../Makefile.cmd
include ../../../../Makefile.cmd.64
include ../../Makefile.amd64
+
+# This kmod goes in /usr/kernel/kmdb
+ROOTKMOD = $(ROOT)/usr/kernel/kmdb$(MACHMODDIR)
+
include ../../../Makefile.module
CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/smbfs
CPPFLAGS += -I$(SRC)/uts/common
+# maybe not the best place for this, but
+# we need to create this directory.
+$(ROOTKMOD):
+ $(INS.dir)
diff --git a/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile b/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile
index daa488704e..855c26b7b2 100644
--- a/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile
+++ b/usr/src/cmd/mdb/intel/ia32/nsmb/Makefile
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-#pragma ident "%Z%%M% %I% %E% SMI"
-
MDBTGT = kvm
MODULE = nsmb.so
MODSRCS_DIR = ../../../common/modules/nsmb
@@ -31,6 +29,10 @@ MODSRCS = nsmb.c
include ../../../../Makefile.cmd
include ../../Makefile.ia32
+
+# This kmod goes in /usr/kernel/kmdb
+ROOTKMOD = $(ROOT)/usr/kernel/kmdb
+
include ../../../Makefile.module
CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/netsmb
@@ -38,3 +40,8 @@ CPPFLAGS += -I$(SRC)/uts/common
C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
+
+# maybe not the best place for this, but
+# we need to create this directory.
+$(ROOTKMOD):
+ $(INS.dir)
diff --git a/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile b/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile
index 689769430a..b6ee845cc4 100644
--- a/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile
+++ b/usr/src/cmd/mdb/intel/ia32/smbfs/Makefile
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-#pragma ident "%Z%%M% %I% %E% SMI"
-
MDBTGT = kvm
MODULE = smbfs.so
MODSRCS_DIR = ../../../common/modules/smbfs
@@ -31,8 +29,16 @@ MODSRCS = smbfs.c
include ../../../../Makefile.cmd
include ../../Makefile.ia32
+
+# This kmod goes in /usr/kernel/kmdb
+ROOTKMOD = $(ROOT)/usr/kernel/kmdb
+
include ../../../Makefile.module
CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/smbfs
CPPFLAGS += -I$(SRC)/uts/common
+# maybe not the best place for this, but
+# we need to create this directory.
+$(ROOTKMOD):
+ $(INS.dir)
diff --git a/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile b/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile
index f9664c6c71..6ade1cc2f0 100644
--- a/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile
+++ b/usr/src/cmd/mdb/sparc/v9/nsmb/Makefile
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-#pragma ident "%Z%%M% %I% %E% SMI"
-
MDBTGT = kvm
MODULE = nsmb.so
MODSRCS_DIR = ../../../common/modules/nsmb
@@ -32,6 +30,10 @@ MODSRCS = nsmb.c
include ../../../../Makefile.cmd
include ../../../../Makefile.cmd.64
include ../../Makefile.sparcv9
+
+# This kmod goes in /usr/kernel/kmdb
+ROOTKMOD = $(ROOT)/usr/kernel/kmdb$(MACHMODDIR)
+
include ../../../Makefile.module
CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/netsmb
@@ -39,3 +41,8 @@ CPPFLAGS += -I$(SRC)/uts/common
C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
+
+# maybe not the best place for this, but
+# we need to create this directory.
+$(ROOTKMOD):
+ $(INS.dir)
diff --git a/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile b/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile
index 5bbd61da40..cc2aeaeff7 100644
--- a/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile
+++ b/usr/src/cmd/mdb/sparc/v9/smbfs/Makefile
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
-#pragma ident "%Z%%M% %I% %E% SMI"
-
MDBTGT = kvm
MODULE = smbfs.so
MODSRCS_DIR = ../../../common/modules/smbfs
@@ -32,8 +30,16 @@ MODSRCS = smbfs.c
include ../../../../Makefile.cmd
include ../../../../Makefile.cmd.64
include ../../Makefile.sparcv9
+
+# This kmod goes in /usr/kernel/kmdb
+ROOTKMOD = $(ROOT)/usr/kernel/kmdb$(MACHMODDIR)
+
include ../../../Makefile.module
CPPFLAGS += -I$(SRC)/uts/common/fs/smbclnt/smbfs
CPPFLAGS += -I$(SRC)/uts/common
+# maybe not the best place for this, but
+# we need to create this directory.
+$(ROOTKMOD):
+ $(INS.dir)
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 4333566a47..5a5625d5c6 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -3402,8 +3402,11 @@ sa_get_protocol_section(sa_protocol_properties_t propset, char *section)
char *proto;
proto = sa_get_optionset_attr(propset, "type");
- if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0)
+ if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0) {
+ if (proto != NULL)
+ sa_free_attr_string(proto);
return (propset);
+ }
for (node = node->children; node != NULL;
node = node->next) {
@@ -3423,6 +3426,8 @@ sa_get_protocol_section(sa_protocol_properties_t propset, char *section)
}
if (value != NULL)
xmlFree(value);
+ if (proto != NULL)
+ sa_free_attr_string(proto);
if (node != NULL && xmlStrcmp(node->name, (xmlChar *)"section") != 0) {
/*
* avoid a non option node -- it is possible to be a
@@ -3447,8 +3452,11 @@ sa_get_next_protocol_section(sa_property_t prop, char *find)
char *proto;
proto = sa_get_optionset_attr(prop, "type");
- if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0)
+ if ((sa_proto_get_featureset(proto) & SA_FEATURE_HAS_SECTIONS) == 0) {
+ if (proto != NULL)
+ sa_free_attr_string(proto);
return ((sa_property_t)NULL);
+ }
for (node = ((xmlNodePtr)prop)->next; node != NULL;
node = node->next) {
@@ -3469,6 +3477,8 @@ sa_get_next_protocol_section(sa_property_t prop, char *find)
}
if (value != NULL)
xmlFree(value);
+ if (proto != NULL)
+ sa_free_attr_string(proto);
return ((sa_property_t)node);
}
diff --git a/usr/src/lib/libshare/smbfs/libshare_smbfs.c b/usr/src/lib/libshare/smbfs/libshare_smbfs.c
index f572adcbcc..1d81fadfbe 100644
--- a/usr/src/lib/libshare/smbfs/libshare_smbfs.c
+++ b/usr/src/lib/libshare/smbfs/libshare_smbfs.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* SMB specific functions
*/
@@ -72,9 +70,7 @@ static int yes_no_validator(int, char *, char *);
static int ip_address_validator(int, char *, char *);
static int minauth_validator(int, char *, char *);
static int password_validator(int, char *, char *);
-#ifdef NOT_DEFINED
-static int nbscope_validator(int, char *, char *);
-#endif
+static int signing_validator(int, char *, char *);
int propset_changed = 0;
@@ -183,23 +179,9 @@ struct smbclnt_proto_option_defs smbclnt_proto_options[] = {
{ "workgroup", NULL, PROTO_OPT_WORKGROUP,
0, 0, MAX_VALUE_BUFLEN,
string_length_check_validator},
-#ifdef NOT_DEFINED
- { "nbscope", NULL, PROTO_OPT_NBSCOPE,
- 0, 0, MAX_VALUE_BUFLEN,
- nbscope_validator},
- { "nbtimeout", NULL, PROTO_OPT_NBTIMEOUT,
- 0, 0, 60,
- range_check_validator},
- { "retry_count", NULL, PROTO_OPT_RETRY_COUNT,
- 0, 0, 10,
- range_check_validator},
- { "use_negprot_domain", NULL, PROTO_OPT_USE_NEGPROT_DOMAIN,
- 0, 0, 0,
- yes_no_validator},
- { "charset", NULL, PROTO_OPT_CHARSETS,
+ { "signing", NULL, PROTO_OPT_SIGNING,
0, 0, MAX_VALUE_BUFLEN,
- ip_address_validator},
-#endif
+ signing_validator},
{NULL}
};
@@ -302,18 +284,21 @@ minauth_validator(int index, char *section, char *value)
return (SA_BAD_VALUE);
}
-#ifdef NOT_DEFINED
/*ARGSUSED*/
static int
-nbscope_validator(int index, char *section, char *value)
+signing_validator(int index, char *section, char *value)
{
- /*
- * XXX - not sure what's legal here. Looks like it's not
- * used in nb_name_encode() right now anyway.
- */
- return (SA_OK);
+ if (value == NULL)
+ return (SA_BAD_VALUE);
+ if (strlen(value) == 0)
+ return (SA_OK);
+ if (strcmp(value, "disabled") == 0 ||
+ strcmp(value, "enabled") == 0 ||
+ strcmp(value, "required") == 0)
+ return (SA_OK);
+ else
+ return (SA_BAD_VALUE);
}
-#endif
/*ARGSUSED*/
static int
@@ -366,84 +351,61 @@ smbclnt_config_load()
char *lastpgname = NULL, *pgname = NULL;
char *name = NULL, *value = NULL;
sa_property_t sect, node;
- int pending = 0;
-#ifdef DEBUG
- char *sectname = NULL;
-#endif
props = scf_simple_app_props_get(NULL, SMBC_DEFAULT_INSTANCE_FMRI);
if (props == NULL)
return (-1);
- while ((prop = (scf_simple_prop_t *)
- scf_simple_app_props_next(props, lastprop)) != NULL) {
+ for (;;) {
+ lastprop = prop;
+ prop = (scf_simple_prop_t *)
+ scf_simple_app_props_next(props, lastprop);
+ if (prop == NULL)
+ break;
/* Ignore properties that don't have our prefix */
pgname = scf_simple_prop_pgname(prop);
- if (strncmp("S-", pgname, 2) != 0) {
- lastprop = prop;
+ if (strncmp("S-", pgname, 2) != 0)
continue;
- }
- /* Note property group name changes, which mark sections */
+ /*
+ * Note property group name changes, which mark sections
+ *
+ * The memory allocated by sa_create_section is
+ * linked into the list of children under protoset,
+ * and will eventually be freed via that list.
+ */
if (lastpgname == NULL || strcmp(lastpgname, pgname) != 0) {
-#ifdef DEBUG
- if (pending)
- fprintf(stderr, "smbclnt_config_load: "
- "Ignoring empty section %s\n", sectname);
- fprintf(stderr, "smbclnt_config_load: new pg=%s\n",
- pgname);
-#endif
sect = sa_create_section(NULL, pgname+2);
(void) xmlSetProp(sect, (xmlChar *)"type",
(xmlChar *)SMBFS_PROTOCOL_NAME);
+ (void) sa_add_protocol_property(protoset, sect);
if (lastpgname)
free(lastpgname);
lastpgname = strdup(pgname);
- pending = 1;
}
name = scf_simple_prop_name(prop);
value = scf_simple_prop_next_astring(prop);
/* If we get a section name, apply it and consume it */
if (strncmp("section", name, 7) == 0 && value != NULL) {
-#ifdef DEBUG
- if (sectname)
- free(sectname);
- sectname = strdup(value);
- fprintf(stderr, "smbclnt_config_load: section=%s\n",
- sectname);
-#endif
(void) xmlSetProp(sect, (xmlChar *)"name",
(xmlChar *)value);
- lastprop = prop;
continue;
}
-#ifdef DEBUG
- fprintf(stderr, "pg=%s, sect=%s, nm=%s, val=%s\n",
- pgname, sectname ? sectname : "NULL", name, value);
-#endif
+
/*
- * If we have an ordinary property, add to the section.
- * Also, if this is the first ordinary property, we
- * can commit the non-empty section to the protoset.
+ * We have an ordinary property. Add to the section.
+ *
+ * The memory allocated by sa_create_property is
+ * linked into the list of children under "sect",
+ * and will eventually be freed via that list.
*/
node = sa_create_property(name, value);
(void) sa_add_protocol_property(sect, node);
- lastprop = prop;
- if (pending) {
- (void) sa_add_protocol_property(protoset, sect);
- pending = 0;
- }
}
scf_simple_app_props_free(props);
- if (pending) {
-#ifdef DEBUG
- fprintf(stderr, "smbclnt_config_load: "
- "Deleting empty section %s\n", sectname);
-#endif
- (void) smbfs_delete_property_group(lastpgname);
- }
+
if (lastpgname)
free(lastpgname);
return (0);
@@ -469,11 +431,11 @@ smbfs_save_propset()
int new = 0, nonnull = 0;
propset = sa_get_protocol_section(protoset, section);
- (void) strncpy(propgroup, SMBC_PG_PREFIX, SMBC_PG_PREFIX_LEN);
+ (void) strlcpy(propgroup, SMBC_PG_PREFIX, sizeof (propgroup));
propgroup[SMBC_PG_PREFIX_LEN] = '\0';
uu = sa_get_property_attr(propset, "extra");
if (uu != NULL) {
- (void) strncat(propgroup, uu, UUID_PRINTABLE_STRING_LENGTH);
+ (void) strlcat(propgroup, uu, sizeof (propgroup));
free(uu);
} else {
new = 1;
@@ -481,10 +443,6 @@ smbfs_save_propset()
uuid_generate(uuid);
uuid_unparse(uuid, &propgroup[SMBC_PG_PREFIX_LEN]);
}
-#ifdef DEBUG
- fprintf(stderr, "smbfs_save_propset: %s pgname=%s\n",
- new ? "new" : "old", propgroup);
-#endif
handle = smb_smf_scf_init(SMBC_FMRI_PREFIX);
if (handle == NULL) {
@@ -508,12 +466,6 @@ smbfs_save_propset()
for (i = PROTO_OPT_SECTION+1; i <= SMBC_OPT_MAX; i++) {
if ((smbclnt_proto_options[i].flags & SMBC_MODIFIED) == 0)
continue;
-#ifdef DEBUG
- fprintf(stderr, "smbfs_save_propset: saving "
- "i=%d/name=%s/value=%s\n", i,
- smbclnt_proto_options[i].name,
- smbclnt_proto_options[i].value);
-#endif
if (strcmp(smbclnt_proto_options[i].value, "") == 0)
ret = smb_smf_delete_property(handle,
smbclnt_proto_options[i].name);
@@ -533,12 +485,6 @@ smbfs_save_propset()
* Suppress new, null entries by not saving the section name.
*/
if (!new || nonnull) {
-#ifdef DEBUG
- fprintf(stderr, "smbfs_save_propset: saving "
- "i=%d/name=%s/value=%s\n", PROTO_OPT_SECTION,
- smbclnt_proto_options[PROTO_OPT_SECTION].name,
- smbclnt_proto_options[PROTO_OPT_SECTION].value);
-#endif
ret = smb_smf_set_string_property(handle,
smbclnt_proto_options[PROTO_OPT_SECTION].name,
smbclnt_proto_options[PROTO_OPT_SECTION].value);
@@ -621,6 +567,8 @@ smbfs_fini()
{
if (propset_changed)
(void) smbfs_save_propset();
+ xmlFreeNode(protoset);
+ protoset = NULL;
}
/*
@@ -665,18 +613,8 @@ smbfs_save_property(int index, char *section, char *value)
char *s;
if (index == PROTO_OPT_WORKGROUP) {
-#ifdef DEBUG
- fprintf(stderr, "smbfs_save_property: "
- "index %d being mapped to %d\n",
- index, PROTO_OPT_DOMAIN);
-#endif
index = PROTO_OPT_DOMAIN;
}
-#ifdef DEBUG
- fprintf(stderr, "smbfs_save_property: "
- "section=%s, index=%d, name=%s, value=%s\n",
- section, index, smbclnt_proto_options[index].name, value);
-#endif
propset_changed = 1;
s = strdup(section);
if (s == NULL)
@@ -729,6 +667,8 @@ smbfs_set_proto_prop(sa_property_t prop)
sa_free_attr_string(name);
if (value != NULL)
sa_free_attr_string(value);
+ if (section != NULL)
+ sa_free_attr_string(section);
return (ret);
}
@@ -763,12 +703,12 @@ smbfs_delete_section(char *section)
int ret = SA_SYSTEM_ERR;
propset = sa_get_protocol_section(protoset, section);
- (void) strncpy(propgroup, SMBC_PG_PREFIX, SMBC_PG_PREFIX_LEN);
+ (void) strlcpy(propgroup, SMBC_PG_PREFIX, sizeof (propgroup));
propgroup[SMBC_PG_PREFIX_LEN] = '\0';
uu = sa_get_property_attr(propset, "extra");
if (uu == NULL)
goto out;
- (void) strncat(propgroup, uu, UUID_PRINTABLE_STRING_LENGTH);
+ (void) strlcat(propgroup, uu, sizeof (propgroup));
free(uu);
if ((ret = smbfs_delete_property_group(propgroup)) != SMBC_SMF_OK)
goto out;
@@ -788,10 +728,6 @@ smbfs_delete_property_group(char *propgroup)
smb_scfhandle_t *handle = NULL;
int ret = SA_SYSTEM_ERR;
-#ifdef DEBUG
- fprintf(stderr, "smbfs_delete_property_group: pgname=%s\n", propgroup);
-#endif
-
handle = smb_smf_scf_init(SMBC_FMRI_PREFIX);
if (handle == NULL)
goto out;
@@ -806,8 +742,5 @@ smbfs_delete_property_group(char *propgroup)
ret = SA_OK;
out:
smb_smf_scf_fini(handle);
-#ifdef DEBUG
- fprintf(stderr, "smbfs_delete_property_group: returning %d\n", ret);
-#endif
return (ret);
}
diff --git a/usr/src/lib/libshare/smbfs/libshare_smbfs.h b/usr/src/lib/libshare/smbfs/libshare_smbfs.h
index 86cd831901..8f95e7de68 100644
--- a/usr/src/lib/libshare/smbfs/libshare_smbfs.h
+++ b/usr/src/lib/libshare/smbfs/libshare_smbfs.h
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* basic API declarations for share management
*/
@@ -60,16 +58,9 @@ extern struct smbclnt_proto_option_defs smbclnt_proto_options[];
#define PROTO_OPT_USER 8
#define PROTO_OPT_DOMAIN 9
#define PROTO_OPT_WORKGROUP 10
+#define PROTO_OPT_SIGNING 11
-#ifdef NOT_DEFINED
-#define PROTO_OPT_NBSCOPE 11
-#define PROTO_OPT_NBTIMEOUT 12
-#define PROTO_OPT_RETRY_COUNT 13
-#define PROTO_OPT_USE_NEGPROT_DOMAIN 14
-#define PROTO_OPT_CHARSETS 15
-#endif
-
-#define SMBC_OPT_MAX PROTO_OPT_WORKGROUP
+#define SMBC_OPT_MAX PROTO_OPT_SIGNING
/*
* Flags values
diff --git a/usr/src/lib/libsmbfs/Makefile.com b/usr/src/lib/libsmbfs/Makefile.com
index 9ffc1634ef..a2232234de 100644
--- a/usr/src/lib/libsmbfs/Makefile.com
+++ b/usr/src/lib/libsmbfs/Makefile.com
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# lib/libsmbfs/Makefile.com
LIBRARY= libsmbfs.a
@@ -55,7 +53,8 @@ OBJECTS=\
spnego.o \
spnegoparse.o \
subr.o \
- ui-sun.o
+ ui-sun.o \
+ utf_str.o
include $(SRC)/lib/Makefile.lib
diff --git a/usr/src/lib/libsmbfs/netsmb/nb_lib.h b/usr/src/lib/libsmbfs/netsmb/nb_lib.h
index 1c4100e17a..d2403edf75 100644
--- a/usr/src/lib/libsmbfs/netsmb/nb_lib.h
+++ b/usr/src/lib/libsmbfs/netsmb/nb_lib.h
@@ -32,11 +32,14 @@
* $Id: nb_lib.h,v 1.4 2004/12/11 05:23:58 lindak Exp $
*/
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
#ifndef _NETSMB_NB_LIB_H_
#define _NETSMB_NB_LIB_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Error codes
*/
@@ -98,69 +101,17 @@ typedef struct nbns_nr nbns_nr_t;
#define NBNS_GROUPFLG 0x8000
-/*
- * nbns request
- */
-struct nbns_rq {
- int nr_opcode;
- int nr_nmflags;
- int nr_rcode;
- int nr_qdcount;
- int nr_ancount;
- int nr_nscount;
- int nr_arcount;
- struct nb_name *nr_qdname;
- uint16_t nr_qdtype;
- uint16_t nr_qdclass;
- struct in_addr nr_dest; /* receiver of query */
- struct sockaddr_in nr_sender; /* sender of response */
- int nr_rpnmflags;
- int nr_rprcode;
- uint16_t nr_rpancount;
- uint16_t nr_rpnscount;
- uint16_t nr_rparcount;
- uint16_t nr_trnid;
- struct nb_ctx *nr_nbd;
- struct mbdata nr_rq;
- struct mbdata nr_rp;
- struct nb_ifdesc *nr_if;
- int nr_flags;
- int nr_fd;
- int nr_maxretry;
-};
-typedef struct nbns_rq nbns_rq_t;
-
-struct nb_ifdesc {
- int id_flags;
- struct in_addr id_addr;
- struct in_addr id_mask;
- char id_name[16]; /* actually IFNAMSIZ */
- struct nb_ifdesc *id_next;
-};
-typedef struct nb_ifdesc nb_ifdesc_t;
-
struct sockaddr;
#ifdef __cplusplus
extern "C" {
#endif
-int nb_name_len(struct nb_name *);
-/* new flag UCflag. 1=uppercase,0=don't */
-int nb_name_encode(struct nb_name *, uchar_t *);
-int nb_encname_len(const uchar_t *);
-
-int nb_snballoc(int namelen, struct sockaddr_nb **);
-void nb_snbfree(struct sockaddr *);
-int nb_sockaddr(struct sockaddr *, struct nb_name *, struct sockaddr_nb **);
-
int nb_resolvehost_in(const char *, struct sockaddr **);
int nbns_resolvename(const char *, struct nb_ctx *, struct sockaddr **);
int nbns_getnodestatus(struct sockaddr *targethost,
struct nb_ctx *ctx, char *system, char *workgroup);
int nb_getlocalname(char *name, size_t maxlen);
-int nb_enum_if(struct nb_ifdesc **);
-
const char *nb_strerror(int error);
int nb_ctx_create(struct nb_ctx **);
diff --git a/usr/src/lib/libsmbfs/netsmb/smb_lib.h b/usr/src/lib/libsmbfs/netsmb/smb_lib.h
index 7756ce2638..bec4a1c0b5 100644
--- a/usr/src/lib/libsmbfs/netsmb/smb_lib.h
+++ b/usr/src/lib/libsmbfs/netsmb/smb_lib.h
@@ -32,11 +32,14 @@
* $Id: smb_lib.h,v 1.21.82.2 2005/06/02 00:55:39 lindak Exp $
*/
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
#ifndef _NETSMB_SMB_LIB_H_
#define _NETSMB_SMB_LIB_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -65,47 +68,6 @@
#define SMB_NB_ERROR 0x20000
/*
- * These get/set macros do not handle mis-aligned data.
- * The data are all supposed to be aligned, but that's
- * up to the server. If we ever encounter a server that
- * doesn't obey this rule, a "strict alignment" client
- * (i.e. SPARC) may get an alignment trap in one of these.
- * If that ever happens, make these macros into functions
- * that can handle mis-aligned data. (Or catch traps.)
- */
-#define getb(buf, ofs) (((const uint8_t *)(buf))[ofs])
-#define setb(buf, ofs, val) (((uint8_t *)(buf))[ofs]) = val
-#define getbw(buf, ofs) ((uint16_t)(getb(buf, ofs)))
-#define getw(buf, ofs) (*((uint16_t *)(&((uint8_t *)(buf))[ofs])))
-#define getdw(buf, ofs) (*((uint32_t *)(&((uint8_t *)(buf))[ofs])))
-
-#ifdef _LITTLE_ENDIAN
-
-#define getwle(buf, ofs) (*((uint16_t *)(&((uint8_t *)(buf))[ofs])))
-#define getdle(buf, ofs) (*((uint32_t *)(&((uint8_t *)(buf))[ofs])))
-#define getwbe(buf, ofs) (ntohs(getwle(buf, ofs)))
-#define getdbe(buf, ofs) (ntohl(getdle(buf, ofs)))
-
-#define setwle(buf, ofs, val) getwle(buf, ofs) = val
-#define setwbe(buf, ofs, val) getwle(buf, ofs) = htons(val)
-#define setdle(buf, ofs, val) getdle(buf, ofs) = val
-#define setdbe(buf, ofs, val) getdle(buf, ofs) = htonl(val)
-
-#else /* _LITTLE_ENDIAN */
-
-#define getwbe(buf, ofs) (*((uint16_t *)(&((uint8_t *)(buf))[ofs])))
-#define getdbe(buf, ofs) (*((uint32_t *)(&((uint8_t *)(buf))[ofs])))
-#define getwle(buf, ofs) (BSWAP_16(getwbe(buf, ofs)))
-#define getdle(buf, ofs) (BSWAP_32(getdbe(buf, ofs)))
-
-#define setwbe(buf, ofs, val) getwbe(buf, ofs) = val
-#define setwle(buf, ofs, val) getwbe(buf, ofs) = BSWAP_16(val)
-#define setdbe(buf, ofs, val) getdbe(buf, ofs) = val
-#define setdle(buf, ofs, val) getdbe(buf, ofs) = BSWAP_32(val)
-
-#endif /* _LITTLE_ENDIAN */
-
-/*
* SMB work context. Used to store all values which are necessary
* to establish connection to an SMB server.
*/
@@ -124,11 +86,6 @@ struct smb_ctx {
struct smbioc_oshare ct_sh;
char *ct_origshare;
char *ct_home;
-#ifdef APPLE
- /* temporary automount hack */
- char **ct_xxx;
- int ct_maxxxx; /* max # to mount (-x arg) */
-#endif
void *ct_secblob;
int ct_secbloblen;
/* krb5 stuff: all anonymous struct pointers here. */
@@ -181,18 +138,6 @@ typedef struct smb_ctx smb_ctx_t;
#define SMB_ST_MAX STYPE_UNKNOWN
#define SMB_ST_NONE 0xff /* not a part of protocol */
-
-/*
- * request handling structures
- */
-struct mbuf {
- int m_len;
- int m_maxlen;
- char *m_data;
- struct mbuf *m_next;
-};
-typedef struct mbuf mbuf_t;
-
struct mbdata {
struct mbuf *mb_top;
struct mbuf *mb_cur;
@@ -201,24 +146,6 @@ struct mbdata {
};
typedef struct mbdata mbdata_t;
-#define M_ALIGNFACTOR (sizeof (long))
-#define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1))
-#define M_BASESIZE (sizeof (struct mbuf))
-#define M_MINSIZE (256 - M_BASESIZE)
-#define M_TOP(m) ((char *)(m) + M_BASESIZE)
-#define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len)
-#define mtod(m, t) ((t)(m)->m_data)
-
-struct smb_rq {
- uchar_t rq_cmd;
- struct mbdata rq_rq;
- struct mbdata rq_rp;
- struct smb_ctx *rq_ctx;
- int rq_wcount;
- int rq_bcount;
-};
-typedef struct smb_rq smb_rq_t;
-
struct smb_bitname {
uint_t bn_bit;
char *bn_name;
@@ -232,8 +159,6 @@ extern struct rcfile *smb_rc;
extern "C" {
#endif
-struct sockaddr;
-
int smb_lib_init(void);
int smb_open_driver(void);
int smb_open_rcfile(struct smb_ctx *ctx);
@@ -269,18 +194,14 @@ int smb_ctx_flags2(struct smb_ctx *);
int smb_smb_open_print_file(struct smb_ctx *, int, int, const char *, smbfh*);
int smb_smb_close_print_file(struct smb_ctx *, smbfh);
-int smb_read(struct smb_ctx *, smbfh, off_t, size_t, char *);
-int smb_write(struct smb_ctx *, smbfh, off_t, size_t, const char *);
-
-#define smb_rq_getrequest(rqp) (&(rqp)->rq_rq)
-#define smb_rq_getreply(rqp) (&(rqp)->rq_rp)
-
-int smb_rq_init(struct smb_ctx *, uchar_t, size_t, struct smb_rq **);
-void smb_rq_done(struct smb_rq *);
-void smb_rq_wend(struct smb_rq *);
-int smb_rq_simple(struct smb_rq *);
-int smb_rq_dmem(struct mbdata *, const char *, size_t);
-int smb_rq_dstring(struct mbdata *, const char *);
+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, smbfh fh);
+int smb_fh_open(struct smb_ctx *ctx, const char *, int, smbfh *);
+int smb_fh_read(struct smb_ctx *, smbfh, off_t, size_t, char *);
+int smb_fh_write(struct smb_ctx *, smbfh, off_t, size_t, const char *);
+int smb_fh_xactnp(struct smb_ctx *, smbfh, int, const char *,
+ int *, char *, int *);
int smb_t2_request(struct smb_ctx *, int, uint16_t *, const char *,
int, void *, int, void *, int *, void *, int *, void *, int *);
@@ -288,37 +209,6 @@ int smb_t2_request(struct smb_ctx *, int, uint16_t *, const char *,
void smb_simplecrypt(char *dst, const char *src);
int smb_simpledecrypt(char *dst, const char *src);
-int m_getm(struct mbuf *, size_t, struct mbuf **);
-int m_lineup(struct mbuf *, struct mbuf **);
-int mb_init(struct mbdata *, size_t);
-int mb_initm(struct mbdata *, struct mbuf *);
-int mb_done(struct mbdata *);
-int mb_fit(struct mbdata *mbp, size_t size, char **pp);
-int mb_put_uint8(struct mbdata *, uint8_t);
-int mb_put_uint16be(struct mbdata *, uint16_t);
-int mb_put_uint16le(struct mbdata *, uint16_t);
-int mb_put_uint32be(struct mbdata *, uint32_t);
-int mb_put_uint32le(struct mbdata *, uint32_t);
-int mb_put_uint64be(struct mbdata *, uint64_t);
-int mb_put_uint64le(struct mbdata *, uint64_t);
-int mb_put_mem(struct mbdata *, const char *, size_t);
-int mb_put_pstring(struct mbdata *mbp, const char *s);
-int mb_put_mbuf(struct mbdata *, struct mbuf *);
-
-int mb_get_uint8(struct mbdata *, uint8_t *);
-int mb_get_uint16(struct mbdata *, uint16_t *);
-int mb_get_uint16le(struct mbdata *, uint16_t *);
-int mb_get_uint16be(struct mbdata *, uint16_t *);
-int mb_get_uint32(struct mbdata *, uint32_t *);
-int mb_get_uint32be(struct mbdata *, uint32_t *);
-int mb_get_uint32le(struct mbdata *, uint32_t *);
-int mb_get_uint64(struct mbdata *, uint64_t *);
-int mb_get_uint64be(struct mbdata *, uint64_t *);
-int mb_get_uint64le(struct mbdata *, uint64_t *);
-int mb_get_mem(struct mbdata *, char *, size_t);
-
-extern uchar_t nls_lower[256], nls_upper[256];
-
int nls_setrecode(const char *, const char *);
int nls_setlocale(const char *);
char *nls_str_toext(char *, const char *);
diff --git a/usr/src/lib/libsmbfs/netsmb/smb_rap.h b/usr/src/lib/libsmbfs/netsmb/smb_rap.h
index 118861f633..bb85ef0f17 100644
--- a/usr/src/lib/libsmbfs/netsmb/smb_rap.h
+++ b/usr/src/lib/libsmbfs/netsmb/smb_rap.h
@@ -35,8 +35,6 @@
#ifndef _NETSMB_SMB_RAP_H_
#define _NETSMB_SMB_RAP_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
struct smb_rap {
char *r_sparam;
char *r_nparam;
@@ -54,13 +52,6 @@ struct smb_rap {
int r_entries;
};
-struct smb_share_info_1 {
- char shi1_netname[13];
- char shi1_pad;
- uint16_t shi1_type;
- uint32_t shi1_remark; /* char * */
-};
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -70,10 +61,9 @@ void smb_rap_done(struct smb_rap *);
int smb_rap_request(struct smb_rap *, struct smb_ctx *);
int smb_rap_setNparam(struct smb_rap *, int);
int smb_rap_setPparam(struct smb_rap *, void *);
+int smb_rap_getNparam(struct smb_rap *, long *);
int smb_rap_error(struct smb_rap *, int);
-int smb_rap_NetShareEnum(struct smb_ctx *, int, void *, int *, int *, int *);
-
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libsmbfs/smb/acl_api.c b/usr/src/lib/libsmbfs/smb/acl_api.c
index 2dc024e086..6c8552e75a 100644
--- a/usr/src/lib/libsmbfs/smb/acl_api.c
+++ b/usr/src/lib/libsmbfs/smb/acl_api.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* ACL API for smbfs
*/
@@ -54,6 +52,7 @@
#include <netsmb/smb_lib.h>
#include <netsmb/smbfs_acl.h>
#include <netsmb/smbfs_isec.h>
+#include "private.h"
/* Sanity check SD sizes */
#define MAX_RAW_SD_SIZE 32768
diff --git a/usr/src/lib/libsmbfs/smb/acl_conv.c b/usr/src/lib/libsmbfs/smb/acl_conv.c
index 2073bf47f5..ec77c8f3c5 100644
--- a/usr/src/lib/libsmbfs/smb/acl_conv.c
+++ b/usr/src/lib/libsmbfs/smb/acl_conv.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* ACL support for smbfs
*
@@ -59,6 +57,8 @@
#include <netsmb/smb_lib.h>
#include <netsmb/smbfs_acl.h>
#include <netsmb/smbfs_isec.h>
+#include <netsmb/mchain.h>
+#include "private.h"
#ifdef _KERNEL
#define MALLOC(size) kmem_alloc(size, KM_SLEEP)
@@ -179,6 +179,7 @@ ifree_ace(i_ntace_t *ace)
static int
mb_get_ace(mbdata_t *mbp, i_ntace_t **acep)
{
+ mbdata_t tmp_mb;
i_ntace_t *ace = NULL;
uint16_t ace_len;
int error;
@@ -187,13 +188,28 @@ mb_get_ace(mbdata_t *mbp, i_ntace_t **acep)
return (ENOMEM);
bzero(ace, sizeof (*ace));
- ERRCHK(mb_get_uint8(mbp, &ace->ace_type));
- ERRCHK(mb_get_uint8(mbp, &ace->ace_flags));
- ERRCHK(mb_get_uint16le(mbp, &ace_len));
- ERRCHK(mb_get_uint32le(mbp, &ace->ace_rights));
+ /*
+ * The ACE is realy variable length,
+ * with format determined by the type.
+ * XXX: This only decodes types 0-7
+ *
+ * There may also be padding after it, so
+ * decode the using a copy of the mbdata,
+ * and then consume the specified length.
+ */
+ tmp_mb = *mbp;
+
+ /* Fixed-size header */
+ ERRCHK(mb_get_uint8(&tmp_mb, &ace->ace_type));
+ ERRCHK(mb_get_uint8(&tmp_mb, &ace->ace_flags));
+ ERRCHK(mb_get_uint16le(&tmp_mb, &ace_len));
- ERRCHK(mb_get_sid(mbp, &ace->ace_sid));
- /* XXX: consume any ace_len not used? */
+ /* Variable-size body */
+ ERRCHK(mb_get_uint32le(&tmp_mb, &ace->ace_rights));
+ ERRCHK(mb_get_sid(&tmp_mb, &ace->ace_sid));
+
+ /* Now actually consume ace_len */
+ ERRCHK(mb_get_mem(mbp, NULL, ace_len));
/* Success! */
*acep = ace;
@@ -208,8 +224,7 @@ static int
mb_put_ace(mbdata_t *mbp, i_ntace_t *ace)
{
int cnt0, error;
- char *ace_len_p;
- uint16_t ace_len;
+ uint16_t ace_len, *ace_len_p;
if (ace == NULL)
return (EINVAL);
@@ -218,14 +233,13 @@ mb_put_ace(mbdata_t *mbp, i_ntace_t *ace)
ERRCHK(mb_put_uint8(mbp, ace->ace_type));
ERRCHK(mb_put_uint8(mbp, ace->ace_flags));
- ERRCHK(mb_fit(mbp, 2, &ace_len_p));
+ ERRCHK(mb_fit(mbp, 2, (char **)&ace_len_p));
ERRCHK(mb_put_uint32le(mbp, ace->ace_rights));
ERRCHK(mb_put_sid(mbp, ace->ace_sid));
ace_len = mbp->mb_count - cnt0;
- /* LINTED */
- setwle(ace_len_p, 0, ace_len);
+ *ace_len_p = htoles(ace_len);
/* Success! */
return (0);
@@ -295,7 +309,10 @@ mb_get_acl(mbdata_t *mbp, i_ntacl_t **aclp)
ERRCHK(mb_get_ace(mbp, acep));
acep++;
}
- /* XXX: consume any acl_len not used? */
+ /*
+ * There may be more data here, but
+ * the caller takes care of that.
+ */
/* Success! */
*aclp = acl;
@@ -311,8 +328,7 @@ mb_put_acl(mbdata_t *mbp, i_ntacl_t *acl)
{
i_ntace_t **acep;
uint8_t revision;
- char *acl_len_p;
- uint16_t acl_len;
+ uint16_t acl_len, *acl_len_p;
uint32_t *subauthp;
size_t aclsz;
int i, cnt0, error;
@@ -321,7 +337,7 @@ mb_put_acl(mbdata_t *mbp, i_ntacl_t *acl)
ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
- ERRCHK(mb_fit(mbp, 2, &acl_len_p));
+ ERRCHK(mb_fit(mbp, 2, (char **)&acl_len_p));
ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
@@ -333,8 +349,7 @@ mb_put_acl(mbdata_t *mbp, i_ntacl_t *acl)
/* Fill in acl_len_p */
acl_len = mbp->mb_count - cnt0;
- /* LINTED */
- setwle(acl_len_p, 0, acl_len);
+ *acl_len_p = htoles(acl_len);
/* Success! */
return (0);
@@ -441,7 +456,7 @@ errout:
int
mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd)
{
- char *owneroffp, *groupoffp, *sacloffp, *dacloffp;
+ uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
uint32_t owneroff, groupoff, sacloff, dacloff;
int cnt0, error;
@@ -451,10 +466,10 @@ mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd)
ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
ERRCHK(mb_put_uint16le(mbp, sd->sd_flags));
- ERRCHK(mb_fit(mbp, 4, &owneroffp));
- ERRCHK(mb_fit(mbp, 4, &groupoffp));
- ERRCHK(mb_fit(mbp, 4, &sacloffp));
- ERRCHK(mb_fit(mbp, 4, &dacloffp));
+ ERRCHK(mb_fit(mbp, 4, (char **)&owneroffp));
+ ERRCHK(mb_fit(mbp, 4, (char **)&groupoffp));
+ ERRCHK(mb_fit(mbp, 4, (char **)&sacloffp));
+ ERRCHK(mb_fit(mbp, 4, (char **)&dacloffp));
/*
* These could be marshalled in any order, but
@@ -478,14 +493,10 @@ mb_put_ntsd(mbdata_t *mbp, i_ntsd_t *sd)
}
/* Fill in the offsets */
- /* LINTED */
- setdle(owneroffp, 0, owneroff);
- /* LINTED */
- setdle(groupoffp, 0, groupoff);
- /* LINTED */
- setdle(sacloffp, 0, sacloff);
- /* LINTED */
- setdle(dacloffp, 0, dacloff);
+ *owneroffp = htolel(owneroff);
+ *groupoffp = htolel(groupoff);
+ *sacloffp = htolel(sacloff);
+ *dacloffp = htolel(dacloff);
/* Success! */
return (0);
@@ -816,7 +827,7 @@ smbfs_acl_sd2zfs(
idms = I_GetMappings(idmap_gh);
if (idms != IDMAP_SUCCESS) {
#ifdef DEBUG
- printf("idmap_get_mappings: rc=%d\n", rc);
+ printf("idmap_get_mappings: rc=%d\n", idms);
#endif
/* creative error choice */
error = EIDRM;
diff --git a/usr/src/lib/libsmbfs/smb/charsets.c b/usr/src/lib/libsmbfs/smb/charsets.c
index 7000be5416..81075a3a2f 100644
--- a/usr/src/lib/libsmbfs/smb/charsets.c
+++ b/usr/src/lib/libsmbfs/smb/charsets.c
@@ -21,7 +21,9 @@
*
* @APPLE_LICENSE_HEADER_END@
*/
-/* @(#)charsets.c *
+/* CSTYLED */
+/*
+ * @(#)charsets.c *
* (c) 2004 Apple Computer, Inc. All Rights Reserved
*
*
@@ -33,32 +35,20 @@
* 28-Nov-2004 Guy Harris New today
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
#include <iconv.h>
#include <langinfo.h>
#include <strings.h>
-#ifdef NOTPORTED
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreFoundation/CFStringDefaultEncoding.h>
-#include <CoreFoundation/CFStringEncodingConverter.h>
-#include <sys/mchain.h>
-#endif /* NOTPORTED */
-
#include <netsmb/smb_lib.h>
#include <netsmb/mchain.h>
#include "charsets.h"
-#ifdef NOTPORTED
-extern uid_t real_uid,eff_uid;
-#endif /* NOTPORTED */
-
/*
* On Solaris, we will need to do some rewriting to use our iconv
* routines for the conversions. For now, we're effectively
@@ -69,43 +59,47 @@ extern uid_t real_uid,eff_uid;
static unsigned
xtoi(char u)
{
- if (isdigit(u))
- return (u - '0');
- else if (islower(u))
- return (10 + u - 'a');
- else if (isupper(u))
- return (10 + u - 'A');
- return (16);
+ if (isdigit(u))
+ return (u - '0');
+ else if (islower(u))
+ return (10 + u - 'a');
+ else if (isupper(u))
+ return (10 + u - 'A');
+ return (16);
}
-/* Removes the "%" escape sequences from a URL component.
+/*
+ * Removes the "%" escape sequences from a URL component.
* See IETF RFC 2396.
*/
char *
-unpercent(char * component)
+unpercent(char *component)
{
- char c, *s;
- unsigned hi, lo;
+ char c, *s;
+ unsigned hi, lo;
- if (component)
- for (s = component; (c = *s) != 0; s++) {
- if (c != '%')
- continue;
- if ((hi = xtoi(s[1])) > 15 || (lo = xtoi(s[2])) > 15)
- continue; /* ignore invalid escapes */
- s[0] = hi*16 + lo;
- /*
- * This was strcpy(s + 1, s + 3);
- * But nowadays leftward overlapping copies are
- * officially undefined in C. Ours seems to
- * work or not depending upon alignment.
- */
- memmove(s+1, s+3, strlen(s+3) + 1);
- }
- return (component);
+ if (component == NULL)
+ return (component);
+
+ for (s = component; (c = *s) != 0; s++) {
+ if (c != '%')
+ continue;
+ if ((hi = xtoi(s[1])) > 15 || (lo = xtoi(s[2])) > 15)
+ continue; /* ignore invalid escapes */
+ s[0] = hi*16 + lo;
+ /*
+ * This was strcpy(s + 1, s + 3);
+ * But nowadays leftward overlapping copies are
+ * officially undefined in C. Ours seems to
+ * work or not depending upon alignment.
+ */
+ memmove(s+1, s+3, strlen(s+3) + 1);
+ }
+ return (component);
}
+/* BEGIN CSTYLED */
#ifdef NOTPORTED
static CFStringEncoding
get_windows_encoding_equivalent( void )
@@ -247,7 +241,7 @@ convert_wincs_to_utf8(const char *windows_string)
CFRelease(s);
return result;
#else /* NOTPORTED */
- return ((char*)windows_string);
+ return (strdup((char*)windows_string));
#endif /* NOTPORTED */
}
@@ -290,96 +284,15 @@ convert_utf8_to_wincs(const char *utf8_string)
CFRelease(s);
return result;
#else /* NOTPORTED */
- return ((char*)utf8_string);
+ return (strdup((char*)utf8_string));
#endif /* NOTPORTED */
}
+/* END CSTYLED */
/*
- * Convert little-endian Unicode string to UTF-8.
- * Converts the Unicode string to host byte order in place.
- */
-char *
-convert_leunicode_to_utf8(unsigned short *unicode_string)
-{
- unsigned short *unicode_charp, unicode_char;
- int len = 0;
-
- for (unicode_charp = unicode_string;
- (unicode_char = *unicode_charp) != 0;
- unicode_charp++) {
- *unicode_charp = letohs(unicode_char);
- len = len + 2;
- }
- return (convert_unicode_to_utf8(unicode_string, len));
-}
-
-char *
-convert_unicode_to_utf8(unsigned short *unicode_string, int len)
-{
- iconv_t cd;
- char from[BUFSIZ], to[BUFSIZ];
- char *tptr = NULL;
- const char *fptr;
- size_t ileft, oleft, ret;
-
- cd = iconv_open("UTF-8", "UTF-16");
- if (cd != (iconv_t)-1) {
- ileft = len;
- bcopy((char *)unicode_string, from, ileft);
- fptr = from;
- oleft = BUFSIZ;
- tptr = to;
- ret = iconv(cd, &fptr, &ileft, &tptr, &oleft);
- if (ret != (size_t)-1) {
- to[BUFSIZ-oleft] = '\0';
- tptr = to;
- } else {
- tptr = NULL;
- }
- (void) iconv_close(cd);
- }
- return (tptr);
-}
-
-/*
- * Convert UTF-8 string to little-endian Unicode.
+ * We replaced these routines for Solaris:
+ * convert_leunicode_to_utf8
+ * convert_unicode_to_utf8
+ * convert_utf8_to_leunicode
+ * with new code in: utf_str.c
*/
-unsigned short *
-convert_utf8_to_leunicode(const char *utf8_string)
-{
-#ifdef NOTPORTED
- CFStringRef s;
- CFIndex maxlen;
- unsigned short *result;
- CFRange range;
- int i;
-
- s = CFStringCreateWithCString(NULL, utf8_string,
- kCFStringEncodingUTF8);
- if (s == NULL) {
- smb_error("CFStringCreateWithCString for UTF-8 failed on \"%s\"", -1,
- utf8_string);
- return NULL;
- }
-
- maxlen = CFStringGetLength(s);
- result = malloc(2*(maxlen + 1));
- if (result == NULL) {
- smb_error("Couldn't allocate buffer for Unicode string for \"%s\" - skipping", -1,
- utf8_string);
- CFRelease(s);
- return NULL;
- }
- range.location = 0;
- range.length = maxlen;
- CFStringGetCharacters(s, range, result);
- for (i = 0; i < maxlen; i++)
- result[i] = CFSwapInt16HostToLittle(result[i]);
- result[maxlen] = 0;
- CFRelease(s);
- return result;
-#else /* NOTPORTED */
- /* LINTED */ /* XXX Really need to fix this! */
- return ((ushort_t *)utf8_string); /* XXX */
-#endif /* NOTPORTED */
-}
diff --git a/usr/src/lib/libsmbfs/smb/charsets.h b/usr/src/lib/libsmbfs/smb/charsets.h
index 5518afc783..c754425f37 100644
--- a/usr/src/lib/libsmbfs/smb/charsets.h
+++ b/usr/src/lib/libsmbfs/smb/charsets.h
@@ -34,15 +34,14 @@
* 28-Nov-2004 Guy Harris New today
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifndef __CHARSETS_H__
#define __CHARSETS_H__
extern char *convert_wincs_to_utf8(const char *windows_string);
extern char *convert_utf8_to_wincs(const char *utf8_string);
extern char *convert_leunicode_to_utf8(unsigned short *windows_string);
-extern char *convert_unicode_to_utf8(unsigned short *windows_string, int len);
+extern char *convert_unicode_to_utf8(unsigned short *windows_string);
extern unsigned short *convert_utf8_to_leunicode(const char *utf8_string);
+extern size_t unicode_strlen(const uint16_t *unicode_string);
#endif /* __CHARSETS_H__ */
diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c
index ae79686869..dfc86bd191 100644
--- a/usr/src/lib/libsmbfs/smb/ctx.c
+++ b/usr/src/lib/libsmbfs/smb/ctx.c
@@ -32,7 +32,10 @@
* $Id: ctx.c,v 1.32.70.2 2005/06/02 00:55:40 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -58,10 +61,6 @@
#include <kerberosv5/krb5.h>
#include <kerberosv5/com_err.h>
-extern uid_t real_uid, eff_uid;
-
-#define NB_NEEDRESOLVER
-
#include <netsmb/smb_lib.h>
#include <netsmb/netbios.h>
#include <netsmb/nb_lib.h>
@@ -71,6 +70,7 @@ extern uid_t real_uid, eff_uid;
#include <spnego.h>
#include "derparse.h"
+#include "private.h"
extern MECH_OID g_stcMechOIDList [];
@@ -80,20 +80,23 @@ extern MECH_OID g_stcMechOIDList [];
int smb_debug, smb_verbose;
/*
- * This used to call the DCE/RPC code.
- * We want more strict layering than this.
- * The redirector should simply export a
- * remote pipe API, comsumed by dce rpc.
- * Make it a no-op for now.
+ * 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
+ * originally a direct call into the RPC code.
*/
-#if 0
-#include <rpc_cleanup.h>
-#else
+static smb_ctx_close_hook_t close_hook;
static void
rpc_cleanup_smbctx(struct smb_ctx *ctx)
{
+ if (close_hook)
+ (*close_hook)(ctx);
+}
+void
+smb_ctx_set_close_hook(smb_ctx_close_hook_t hook)
+{
+ close_hook = hook;
}
-#endif
void
dump_ctx_flags(int flags)
@@ -229,7 +232,9 @@ smb_ctx_init(struct smb_ctx *ctx, int argc, char *argv[],
ctx->ct_minlevel = minlevel;
ctx->ct_maxlevel = maxlevel;
+ /* Fill in defaults */
ctx->ct_ssn.ioc_opt = SMBVOPT_CREATE | SMBVOPT_MINAUTH_NTLM;
+
ctx->ct_ssn.ioc_timeout = 15;
ctx->ct_ssn.ioc_retrycount = 4;
ctx->ct_ssn.ioc_owner = SMBM_ANY_OWNER;
@@ -1230,7 +1235,6 @@ smb_ctx_ioctl(struct smb_ctx *ctx, int inum, struct smbioc_lookup *rqp)
/* Note: No longer put length in outtok[0] */
/* *((int *)rqp->ioc_ssn.ioc_outtok) = (int)siz; */
- seteuid(eff_uid); /* restore setuid root briefly */
if (ioctl(ctx->ct_fd, inum, rqp) == -1) {
rc = errno;
goto out;
@@ -1255,7 +1259,6 @@ smb_ctx_ioctl(struct smb_ctx *ctx, int inum, struct smbioc_lookup *rqp)
if (ioctl(ctx->ct_fd, inum, rqp) == -1)
rc = errno;
out:
- seteuid(real_uid); /* and back to real user */
return (rc);
}
@@ -1890,7 +1893,6 @@ smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags)
/*
* Otherwise we're doing plain old NTLM
*/
- seteuid(eff_uid); /* restore setuid root briefly */
if ((ctx->ct_flags & SMBCF_SSNACTIVE) == 0) {
/*
* This is the magic that tells the driver to
@@ -1915,7 +1917,6 @@ smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags)
}
out:
- seteuid(real_uid); /* and back to real user */
if (failure) {
error = errno;
smb_error(dgettext(TEXT_DOMAIN,
@@ -1937,7 +1938,6 @@ smb_ctx_flags2(struct smb_ctx *ctx)
"can't get flags2 for a session"), errno);
return (-1);
}
- printf(dgettext(TEXT_DOMAIN, "Flags2 value is %d\n"), flags2);
return (flags2);
}
@@ -2030,6 +2030,34 @@ smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
}
}
+ rc_getstringptr(smb_rc, sname, "signing", &p);
+ if (p) {
+ /*
+ * "signing" was set in this section; override
+ * the current signing settings.
+ */
+ ctx->ct_ssn.ioc_opt &= ~SMBVOPT_SIGNING_MASK;
+ if (strcmp(p, "disabled") == 0) {
+ /* leave flags zero (expr for lint) */
+ (void) ctx->ct_ssn.ioc_opt;
+ } else if (strcmp(p, "enabled") == 0) {
+ ctx->ct_ssn.ioc_opt |=
+ SMBVOPT_SIGNING_ENABLED;
+ } else if (strcmp(p, "required") == 0) {
+ ctx->ct_ssn.ioc_opt |=
+ SMBVOPT_SIGNING_ENABLED |
+ SMBVOPT_SIGNING_REQUIRED;
+ } else {
+ /*
+ * Unknown "signing" value.
+ */
+ smb_error(dgettext(TEXT_DOMAIN,
+"invalid signing policy \"%s\" specified in the section %s"),
+ 0, p, sname);
+ return (EINVAL);
+ }
+ }
+
/*
* Domain name. Allow both keywords:
* "workgroup", "domain"
diff --git a/usr/src/lib/libsmbfs/smb/file.c b/usr/src/lib/libsmbfs/smb/file.c
index dd738e8d97..e7a02e77df 100644
--- a/usr/src/lib/libsmbfs/smb/file.c
+++ b/usr/src/lib/libsmbfs/smb/file.c
@@ -32,7 +32,10 @@
* $Id: file.c,v 1.4 2004/12/13 00:25:21 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -48,15 +51,230 @@
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
+#include <libintl.h>
#include <sys/types.h>
-extern uid_t real_uid, eff_uid;
+#include <sys/file.h>
#include <netsmb/smb_lib.h>
#include <cflib.h>
+#include "charsets.h"
+#include "private.h"
+
int
-smb_read(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count, char *dst)
+smb_fh_close(struct smb_ctx *ctx, smbfh fh)
+{
+ struct smb_rq *rqp;
+ struct mbdata *mbp;
+ int serr;
+
+ serr = smb_rq_init(ctx, SMB_COM_CLOSE, 0, &rqp);
+ if (serr != 0)
+ return (serr);
+ mbp = smb_rq_getrequest(rqp);
+ mb_put_uint16le(mbp, fh);
+ mb_put_uint32le(mbp, 0); /* time stamp */
+ smb_rq_wend(rqp);
+ serr = smb_rq_simple(rqp);
+ if (serr != 0) {
+ smb_rq_done(rqp);
+ return (serr);
+ }
+ mbp = smb_rq_getreply(rqp);
+ smb_rq_done(rqp);
+
+ return (serr);
+}
+
+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,
+ smbfh *fhp, uint32_t *action_taken)
+{
+ struct smb_rq *rqp;
+ struct mbdata *mbp;
+ uint8_t wc;
+ size_t pathlen, pathsize;
+ int error, flags2;
+ uint16_t *upath = NULL;
+
+ flags2 = smb_ctx_flags2(ctx);
+ if (flags2 == -1)
+ return (EIO);
+
+ error = smb_rq_init(ctx, SMB_COM_NT_CREATE_ANDX, 42, &rqp);
+ if (error != 0)
+ return (error);
+
+ if (flags2 & SMB_FLAGS2_UNICODE) {
+ upath = convert_utf8_to_leunicode(path);
+ if (upath == NULL) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "%s: failed converting to UCS-2"), 0, path);
+ error = EINVAL;
+ goto out;
+ }
+ pathlen = unicode_strlen(upath);
+ pathsize = (pathlen + 1) * 2;
+ } else {
+ pathlen = strlen(path);
+ pathsize = pathlen + 1;
+ }
+
+ mbp = smb_rq_getrequest(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, pathsize); /* path size (bytes) */
+ mb_put_uint32le(mbp, 0); /* 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, NTCREATEX_IMPERSONATION_IMPERSONATION); /* (?) */
+ mb_put_uint8(mbp, 0); /* security flags (?) */
+ smb_rq_wend(rqp);
+
+ /* XXX: Need a "put string" function. */
+ if (flags2 & SMB_FLAGS2_UNICODE) {
+ mb_put_uint8(mbp, 0); /* pad byte - align(2) for Unicode */
+ mb_put_mem(mbp, (char *)upath, pathsize);
+ } else
+ mb_put_mem(mbp, path, pathsize);
+
+ 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
+ */
+ wc = rqp->rq_wcount;
+ if (wc < 26) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "%s: open failed, bad word count"), 0, path);
+ error = EBADRPC;
+ goto out;
+ }
+ mb_get_uint8(mbp, NULL); /* secondary cmd */
+ mb_get_uint8(mbp, NULL); /* mbz */
+ mb_get_uint16le(mbp, NULL); /* andxoffset */
+ mb_get_uint8(mbp, NULL); /* oplock lvl granted */
+ mb_get_uint16le(mbp, fhp); /* FID */
+ mb_get_uint32le(mbp, action_taken);
+#if 0 /* skip decoding the rest */
+ mb_get_uint64le(mbp, NULL); /* creation time */
+ mb_get_uint64le(mbp, NULL); /* access time */
+ mb_get_uint64le(mbp, NULL); /* write time */
+ mb_get_uint64le(mbp, NULL); /* change time */
+ mb_get_uint32le(mbp, NULL); /* attributes */
+ mb_get_uint64le(mbp, NULL); /* allocation size */
+ mb_get_uint64le(mbp, NULL); /* EOF */
+ mb_get_uint16le(mbp, NULL); /* file type */
+ mb_get_uint16le(mbp, NULL); /* device state */
+ mb_get_uint8(mbp, NULL); /* directory (boolean) */
+#endif /* skip decoding */
+
+out:
+ if (upath)
+ free(upath);
+ smb_rq_done(rqp);
+
+ return (0);
+}
+
+/*
+ * Conveinence wrapper for smb_fh_ntcreate
+ * Converts Unix-style open call to NTCreate.
+ */
+int
+smb_fh_open(struct smb_ctx *ctx, const char *path, int oflag, smbfh *fhp)
+{
+ int error, mode, open_disp, req_acc, share_acc;
+ char *p, *ntpath = NULL;
+
+ /*
+ * Map O_RDONLY, O_WRONLY, O_RDWR
+ * to FREAD, FWRITE
+ */
+ mode = (oflag & 3) + 1;
+
+ /*
+ * Compute requested access, share access.
+ */
+ req_acc = (
+ STD_RIGHT_READ_CONTROL_ACCESS |
+ STD_RIGHT_SYNCHRONIZE_ACCESS);
+ share_acc = NTCREATEX_SHARE_ACCESS_NONE;
+ if (mode & FREAD) {
+ req_acc |= (
+ SA_RIGHT_FILE_READ_DATA |
+ SA_RIGHT_FILE_READ_EA |
+ SA_RIGHT_FILE_READ_ATTRIBUTES);
+ share_acc |= NTCREATEX_SHARE_ACCESS_READ;
+ }
+ if (mode & FWRITE) {
+ req_acc |= (
+ SA_RIGHT_FILE_WRITE_DATA |
+ SA_RIGHT_FILE_APPEND_DATA |
+ SA_RIGHT_FILE_WRITE_EA |
+ SA_RIGHT_FILE_WRITE_ATTRIBUTES);
+ share_acc |= NTCREATEX_SHARE_ACCESS_WRITE;
+ }
+
+ /*
+ * Compute open disposition
+ */
+ if (oflag & FCREAT) {
+ /* Creat if necessary. */
+ if (oflag & FEXCL) {
+ /* exclusive */
+ open_disp = NTCREATEX_DISP_CREATE;
+ } else if (oflag & FTRUNC)
+ open_disp = NTCREATEX_DISP_OVERWRITE_IF;
+ else
+ open_disp = NTCREATEX_DISP_OPEN_IF;
+ } else {
+ /* Not creating. */
+ if (oflag & FTRUNC)
+ open_disp = NTCREATEX_DISP_OVERWRITE;
+ else
+ open_disp = NTCREATEX_DISP_OPEN;
+ }
+
+ /*
+ * Convert Unix path to NT (backslashes)
+ */
+ ntpath = strdup(path);
+ if (ntpath == NULL)
+ return (ENOMEM);
+ for (p = ntpath; *p; p++)
+ if (*p == '/')
+ *p = '\\';
+
+ error = smb_fh_ntcreate(ctx, ntpath, 0, /* flags */
+ req_acc, SMB_EFA_NORMAL, share_acc, open_disp,
+ NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
+ NTCREATEX_IMPERSONATION_IMPERSONATION,
+ fhp, NULL);
+ free(ntpath);
+
+ return (error);
+}
+
+int
+smb_fh_read(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count,
+ char *dst)
{
struct smbioc_rw rwrq;
@@ -65,17 +283,14 @@ smb_read(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count, char *dst)
rwrq.ioc_base = dst;
rwrq.ioc_cnt = count;
rwrq.ioc_offset = offset;
- seteuid(eff_uid);
if (ioctl(ctx->ct_fd, SMBIOC_READ, &rwrq) == -1) {
- seteuid(real_uid); /* and back to real user */
return (-1);
}
- seteuid(real_uid); /* and back to real user */
return (rwrq.ioc_cnt);
}
int
-smb_write(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count,
+smb_fh_write(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count,
const char *src)
{
struct smbioc_rw rwrq;
@@ -85,11 +300,41 @@ smb_write(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count,
rwrq.ioc_base = (char *)src;
rwrq.ioc_cnt = count;
rwrq.ioc_offset = offset;
- seteuid(eff_uid);
if (ioctl(ctx->ct_fd, SMBIOC_WRITE, &rwrq) == -1) {
- seteuid(real_uid); /* and back to real user */
return (-1);
}
- seteuid(real_uid); /* and back to real user */
return (rwrq.ioc_cnt);
}
+
+/*
+ * Do a TRANSACT_NAMED_PIPE, which is basically just a
+ * pipe write and pipe read, all in one round trip.
+ *
+ * tdlen, tdata describe the data to send.
+ * rdlen, rdata on input describe the receive buffer,
+ * and on output *rdlen is the received length.
+ */
+int
+smb_fh_xactnp(struct smb_ctx *ctx, smbfh fh,
+ int tdlen, const char *tdata, /* transmit */
+ int *rdlen, char *rdata, /* receive */
+ int *more)
+{
+ int err, rparamcnt;
+ uint16_t setup[2];
+
+ setup[0] = TRANS_TRANSACT_NAMED_PIPE;
+ setup[1] = fh;
+ rparamcnt = 0;
+
+ err = smb_t2_request(ctx, 2, setup, "\\PIPE\\",
+ 0, NULL, /* TX paramcnt, params */
+ tdlen, (void *)tdata,
+ &rparamcnt, NULL, /* no RX params */
+ rdlen, rdata, more);
+
+ if (err)
+ *rdlen = 0;
+
+ return (err);
+}
diff --git a/usr/src/lib/libsmbfs/smb/mapfile-vers b/usr/src/lib/libsmbfs/smb/mapfile-vers
index f8f38ba6b0..b23d706b35 100644
--- a/usr/src/lib/libsmbfs/smb/mapfile-vers
+++ b/usr/src/lib/libsmbfs/smb/mapfile-vers
@@ -21,23 +21,32 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
SUNWprivate_1.0 {
global:
- dropsuid;
+ convert_leunicode_to_utf8;
+ convert_unicode_to_utf8;
+ convert_utf8_to_leunicode;
+ convert_utf8_to_unicode;
+ convert_utf8_to_wincs;
+ convert_wincs_to_utf8;
+
nb_ctx_create;
nb_ctx_done;
nb_ctx_readrcsection;
nb_ctx_resolve;
nb_ctx_setns;
nb_resolvehost_in;
+ nb_strerror;
nbns_getnodestatus;
nbns_resolvename;
+
+ nls_str_toloc;
nls_str_upper;
+
rc_close;
rc_open;
+
smb_ctx_done;
smb_ctx_flags2;
smb_ctx_init;
@@ -45,21 +54,48 @@ SUNWprivate_1.0 {
smb_ctx_opt;
smb_ctx_readrc;
smb_ctx_resolve;
+ smb_ctx_set_close_hook;
+
+ smb_ctx_setfullserver;
+ smb_ctx_setpassword;
+ smb_ctx_setserver;
smb_ctx_setshare;
+ smb_ctx_setsrvaddr;
+ smb_ctx_setuser;
+ smb_ctx_setworkgroup;
+
smb_ctx_tdis;
- smb_debug;
+ smb_debug = NODIRECT; # data
smb_error;
+#
+# Functions to support named pipes
+ smb_fh_close;
+ smb_fh_open;
+ smb_fh_read;
+ smb_fh_write;
+ smb_fh_xactnp;
+#
smb_getprogname;
smb_lib_init;
- smb_netshareenum;
+ smb_netshareenum; # will move to libnetapi
smb_open_rcfile;
smb_simplecrypt;
smb_simpledecrypt;
smb_strerror;
- smb_rc; # data
- smb_read;
- smb_write;
- smb_verbose;
+ smb_rc = NODIRECT; # data
+#
+# Functions to support the Remote Access Protocol (RAP)
+ smb_rap_create;
+ smb_rap_done;
+ smb_rap_error;
+ smb_rap_getNparam;
+ smb_rap_request;
+ smb_rap_setNparam;
+ smb_rap_setPparam;
+#
+ smb_verbose = NODIRECT; # data
+#
+# Functions to support Access Control Lists (ACLs)
smbfs_acl_free_sd;
smbfs_acl_get;
smbfs_acl_getsd;
@@ -68,12 +104,14 @@ SUNWprivate_1.0 {
smbfs_acl_set;
smbfs_acl_setsd;
smbfs_acl_zfs2sd;
+#
smbfs_default_dom_usr;
smbfs_keychain_add;
smbfs_keychain_chk;
smbfs_keychain_del;
smbfs_keychain_del_everyone;
smbfs_keychain_del_owner;
+
unpercent;
local:
*;
diff --git a/usr/src/lib/libsmbfs/smb/mbuf.c b/usr/src/lib/libsmbfs/smb/mbuf.c
index 6f08ce1def..2e995dad50 100644
--- a/usr/src/lib/libsmbfs/smb/mbuf.c
+++ b/usr/src/lib/libsmbfs/smb/mbuf.c
@@ -32,7 +32,10 @@
* $Id: mbuf.c,v 1.3 2004/12/13 00:25:22 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <sys/types.h>
#include <ctype.h>
@@ -48,6 +51,8 @@
#include <netsmb/smb_lib.h>
#include <netsmb/mchain.h>
+#include "private.h"
+
#ifdef APPLE
#define __func__ ""
#define MBERROR(format, args...) \
@@ -190,9 +195,6 @@ out:
/*
* Routines to put data in a buffer
*/
-#define MB_PUT(t) int error; t *p; \
- if ((error = mb_fit(mbp, sizeof (t), (char **)&p)) != 0) \
- return (error)
/*
* Check if object of size 'size' fit to the current position and
@@ -223,61 +225,50 @@ mb_fit(struct mbdata *mbp, size_t size, char **pp)
int
mb_put_uint8(struct mbdata *mbp, uint8_t x)
{
- MB_PUT(uint8_t);
- *p = x;
- return (0);
+ uint8_t y = x;
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
mb_put_uint16be(struct mbdata *mbp, uint16_t x)
{
- MB_PUT(uint16_t);
- /* LINTED */
- setwbe(p, 0, x);
- return (0);
+ uint16_t y = htobes(x);
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
mb_put_uint16le(struct mbdata *mbp, uint16_t x)
{
- MB_PUT(uint16_t);
- /* LINTED */
- setwle(p, 0, x);
- return (0);
+ uint16_t y = htoles(x);
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
mb_put_uint32be(struct mbdata *mbp, uint32_t x)
{
- MB_PUT(uint32_t);
- /* LINTED */
- setdbe(p, 0, x);
- return (0);
+ uint32_t y = htobel(x);
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
mb_put_uint32le(struct mbdata *mbp, uint32_t x)
{
- MB_PUT(uint32_t);
- /* LINTED */
- setdle(p, 0, x);
- return (0);
+ uint32_t y = htolel(x);
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
mb_put_uint64be(struct mbdata *mbp, uint64_t x)
{
- MB_PUT(uint64_t);
- *p = htobeq(x);
- return (0);
+ uint64_t y = htobeq(x);
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
mb_put_uint64le(struct mbdata *mbp, uint64_t x)
{
- MB_PUT(uint64_t);
- *p = htoleq(x);
- return (0);
+ uint64_t y = htoleq(x);
+ return (mb_put_mem(mbp, (char *)&y, sizeof (y)));
}
int
diff --git a/usr/src/lib/libsmbfs/smb/nb_name.c b/usr/src/lib/libsmbfs/smb/nb_name.c
index 1c631d73d1..af13efa7b4 100644
--- a/usr/src/lib/libsmbfs/smb/nb_name.c
+++ b/usr/src/lib/libsmbfs/smb/nb_name.c
@@ -32,8 +32,6 @@
* $Id: nb_name.c,v 1.11 2004/12/11 05:23:59 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/socket.h>
#include <ctype.h>
@@ -49,6 +47,7 @@
#include <netsmb/smb_lib.h>
#include <netsmb/nb_lib.h>
#include <netsmb/mchain.h>
+#include "private.h"
int
nb_snballoc(int namelen, struct sockaddr_nb **dst)
diff --git a/usr/src/lib/libsmbfs/smb/nb_net.c b/usr/src/lib/libsmbfs/smb/nb_net.c
index 7398cff0e0..29109c3093 100644
--- a/usr/src/lib/libsmbfs/smb/nb_net.c
+++ b/usr/src/lib/libsmbfs/smb/nb_net.c
@@ -32,8 +32,6 @@
* $Id: nb_net.c,v 1.8 2004/03/19 01:49:47 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
@@ -53,6 +51,12 @@
#include <netsmb/netbios.h>
#include <netsmb/smb_lib.h>
#include <netsmb/nb_lib.h>
+#include "private.h"
+
+/*
+ * General networking stuff, in spite of the names
+ * that imply they're specific to NetBIOS.
+ */
int
nb_getlocalname(char *name, size_t maxlen)
@@ -114,121 +118,3 @@ nb_resolvehost_in(const char *name, struct sockaddr **dest)
*dest = (struct sockaddr *)sinp;
return (0);
}
-
-#ifdef NOT_DEFINED
-int
-nb_enum_if(struct nb_ifdesc **iflist) {
- struct lifconf ifc;
- struct lifreq *ifrqp;
- struct nb_ifdesc *ifd;
- struct in_addr iaddr, imask;
- struct lifnum ifn;
- char *ifrdata, *iname;
- int s, rdlen, ifcnt, error, iflags, i;
-
- *iflist = NULL;
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s == -1)
- return (errno);
-
- /* Get number of interfaces. */
- ifn.lifn_family = AF_INET;
- ifn.lifn_flags = 0;
- ifn.lifn_count = 0;
- if (ioctl(s, SIOCGLIFNUM, &ifn) != 0) {
- error = errno;
- goto bad;
- }
-
- rdlen = ifn.lifn_count * sizeof (struct lifreq);
- ifrdata = malloc(rdlen);
- if (ifrdata == NULL) {
- error = ENOMEM;
- goto bad;
- }
- ifc.lifc_flags = 0;
- ifc.lifc_family = AF_INET;
- ifc.lifc_len = rdlen;
- ifc.lifc_buf = ifrdata;
- if (ioctl(s, SIOCGLIFCONF, &ifc) != 0) {
- error = errno;
- goto bad;
- }
- ifrqp = ifc.lifc_req;
- ifcnt = ifc.lifc_len / sizeof (struct lifreq);
- error = 0;
- for (i = 0; i < ifcnt; i++, ifrqp++) {
- /* XXX for now, avoid IP6 broadcast performance costs */
- if (ifrqp->lifr_addr.ss_family != AF_INET)
- continue;
- if (ioctl(s, SIOCGLIFFLAGS, ifrqp) != 0)
- continue;
- iflags = ifrqp->lifr_flags;
- if ((iflags & IFF_UP) == 0 || (iflags & IFF_BROADCAST) == 0)
- continue;
-
- if (ioctl(s, SIOCGLIFADDR, ifrqp) != 0 ||
- ifrqp->lifr_addr.ss_family != AF_INET) {
- continue;
- }
- iname = ifrqp->lifr_name;
- if (strlen(iname) >= sizeof (ifd->id_name))
- continue;
- iaddr = (*(struct sockaddr_in *)&ifrqp->lifr_addr).sin_addr;
-
- if (ioctl(s, SIOCGLIFNETMASK, ifrqp) != 0)
- continue;
- imask = ((struct sockaddr_in *)&ifrqp->lifr_addr)->sin_addr;
-
- ifd = malloc(sizeof (struct nb_ifdesc));
- if (ifd == NULL)
- return (ENOMEM);
- bzero(ifd, sizeof (struct nb_ifdesc));
- strcpy(ifd->id_name, iname);
- ifd->id_flags = iflags;
- ifd->id_addr = iaddr;
- ifd->id_mask = imask;
- ifd->id_next = *iflist;
- *iflist = ifd;
- }
-bad:
- free(ifrdata);
- close(s);
- return (error);
-}
-
-/*ARGSUSED*/
-int
-nbns_resolvename(const char *name, struct sockaddr **dest)
-{
- printf("NetBIOS name resolver is not included in this distribution.\n");
- printf("Please use '-I' option to specify an IP address of server.\n");
- return (EHOSTUNREACH);
-}
-
-int
-nb_hostlookup(struct nb_name *np, const char *server, const char *hint,
- struct sockaddr_nb **dst)
-{
- struct sockaddr_nb *snb;
- int error;
-
- error = nb_sockaddr(NULL, np, &snb);
- if (error)
- return (error);
- do {
- if (hint) {
- error = nb_resolvehost_in(host, snb);
- if (error)
- break;
- } else {
- error = nb_resolvename(server);
- }
- } while (0);
- if (!error) {
- *dst = snb;
- } else
- nb_snbfree(snb);
- return (error);
-}
-#endif
diff --git a/usr/src/lib/libsmbfs/smb/nbns_rq.c b/usr/src/lib/libsmbfs/smb/nbns_rq.c
index 17de0a103a..773466b7fa 100644
--- a/usr/src/lib/libsmbfs/smb/nbns_rq.c
+++ b/usr/src/lib/libsmbfs/smb/nbns_rq.c
@@ -32,8 +32,6 @@
* $Id: nbns_rq.c,v 1.9 2005/02/24 02:04:38 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
@@ -57,6 +55,40 @@
#include <netsmb/nb_lib.h>
#include <netsmb/mchain.h>
+#include "private.h"
+
+/*
+ * nbns request
+ */
+struct nbns_rq {
+ int nr_opcode;
+ int nr_nmflags;
+ int nr_rcode;
+ int nr_qdcount;
+ int nr_ancount;
+ int nr_nscount;
+ int nr_arcount;
+ struct nb_name *nr_qdname;
+ uint16_t nr_qdtype;
+ uint16_t nr_qdclass;
+ struct in_addr nr_dest; /* receiver of query */
+ struct sockaddr_in nr_sender; /* sender of response */
+ int nr_rpnmflags;
+ int nr_rprcode;
+ uint16_t nr_rpancount;
+ uint16_t nr_rpnscount;
+ uint16_t nr_rparcount;
+ uint16_t nr_trnid;
+ struct nb_ctx *nr_nbd;
+ struct mbdata nr_rq;
+ struct mbdata nr_rp;
+ struct nb_ifdesc *nr_if;
+ int nr_flags;
+ int nr_fd;
+ int nr_maxretry;
+};
+typedef struct nbns_rq nbns_rq_t;
+
static int nbns_rq_create(int opcode, struct nb_ctx *ctx,
struct nbns_rq **rqpp);
static void nbns_rq_done(struct nbns_rq *rqp);
diff --git a/usr/src/lib/libsmbfs/smb/netshareenum.c b/usr/src/lib/libsmbfs/smb/netshareenum.c
index 4da5fd17a2..2d7f9c2c3a 100644
--- a/usr/src/lib/libsmbfs/smb/netshareenum.c
+++ b/usr/src/lib/libsmbfs/smb/netshareenum.c
@@ -36,7 +36,10 @@
*/
/* END CSTYLED */
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <stdlib.h>
#include <string.h>
@@ -47,11 +50,11 @@
#include <netsmb/smb_lib.h>
#include <netsmb/smb_rap.h>
#include <netsmb/smb_netshareenum.h>
-#include "charsets.h"
+#include <smb/charsets.h>
#if 0 /* XXX see below */
#include <dce/exc_handling.h>
-#include <attrb.h>
+#include <rpc/attrb.h>
#include "srvsvc.h"
#endif
@@ -102,6 +105,7 @@ rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
return (EINVAL);
}
rpc_binding_from_string_binding(binding, &binding_h, &status);
+ rpc_string_free(&binding, (unsigned32 *)&free_status);
if (binding_status != rpc_s_ok) {
smb_error(dgettext(TEXT_DOMAIN,
"rpc_binding_from_string_binding failed with %d"), 0,
@@ -130,14 +134,12 @@ rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
}
strcpy(srvnamestr, "\\\\");
strcat(srvnamestr, addrstr);
-#ifdef NOTYETDEFINED
usrvnamestr = convert_utf8_to_leunicode(srvnamestr);
-#endif
- usrvnamestr = srvnamestr;
if (usrvnamestr == NULL) {
smb_error(dgettext(TEXT_DOMAIN,
"can't convert string for server address to Unicode"), 0);
rpc_binding_free(&binding_h, &free_status);
+ free(srvnamestr);
return (EINVAL);
}
if (!exceptions_initialized) {
@@ -200,16 +202,10 @@ rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
for (share = shares, elp = entry_list, i = 0; i < entries;
i++, share++) {
elp->type = share->shi1_type;
-#ifdef NOTYETDEFINED
elp->netname = convert_unicode_to_utf8(share->shi1_share);
-#endif
- elp->netname = share->shi1_share;
if (elp->netname == NULL)
goto fail;
-#ifdef NOTYETDEFINED
elp->remark = convert_unicode_to_utf8(share->shi1_remark);
-#endif
- elp->remark = share->shi1_remark;
if (elp->remark == NULL)
goto fail;
elp++;
@@ -261,6 +257,46 @@ cleanup_and_return:
}
#endif /* XXX */
+/*
+ * Enumerate shares using RAP
+ */
+
+struct smb_share_info_1 {
+ char shi1_netname[13];
+ char shi1_pad;
+ uint16_t shi1_type;
+ uint32_t shi1_remark; /* char * */
+};
+
+static int
+smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
+ int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
+{
+ struct smb_rap *rap;
+ long lval = -1;
+ int error;
+ char *pass;
+ int i;
+
+ error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
+ if (error)
+ return (error);
+ smb_rap_setNparam(rap, sLevel); /* W - sLevel */
+ smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */
+ smb_rap_setNparam(rap, *cbBuffer); /* L - cbBuffer */
+ error = smb_rap_request(rap, ctx);
+ if (error == 0) {
+ *pcEntriesRead = rap->r_entries;
+ error = smb_rap_getNparam(rap, &lval);
+ *pcTotalAvail = lval;
+ /* Copy the data length into the IN/OUT variable. */
+ *cbBuffer = rap->r_rcvbuflen;
+ }
+ error = smb_rap_error(rap, error);
+ smb_rap_done(rap);
+ return (error);
+}
+
static int
rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
struct share_info **entries_listp)
@@ -294,10 +330,7 @@ rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
i++, ep++) {
elp->type = letohs(ep->shi1_type);
ep->shi1_pad = '\0'; /* ensure null termination */
- elp->netname = strdup(ep->shi1_netname);
-#ifdef NOTYETDEFINED
elp->netname = convert_wincs_to_utf8(ep->shi1_netname);
-#endif
if (elp->netname == NULL)
continue; /* punt on this entry */
/*
@@ -305,10 +338,7 @@ rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
*/
if (ep->shi1_remark >= lbound && ep->shi1_remark < rbound) {
cp = (char *)rpbuf + ep->shi1_remark;
- elp->remark = cp;
-#ifdef NOTYETDEFINED
- elp->remark = nls_str_toloc(cp, cp);
-#endif
+ elp->remark = convert_wincs_to_utf8(cp);
} else
elp->remark = NULL;
elp++;
diff --git a/usr/src/lib/libsmbfs/smb/print.c b/usr/src/lib/libsmbfs/smb/print.c
index 7b87c06e41..e0b18e8c40 100644
--- a/usr/src/lib/libsmbfs/smb/print.c
+++ b/usr/src/lib/libsmbfs/smb/print.c
@@ -32,8 +32,6 @@
* $Id: print.c,v 1.1.1.3 2001/07/06 22:38:43 conrad Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/time.h>
@@ -50,6 +48,7 @@
#include <netsmb/smb_lib.h>
#include <cflib.h>
+#include "private.h"
int
smb_smb_open_print_file(struct smb_ctx *ctx, int setuplen, int mode,
diff --git a/usr/src/lib/libsmbfs/smb/private.h b/usr/src/lib/libsmbfs/smb/private.h
new file mode 100644
index 0000000000..6630ed160a
--- /dev/null
+++ b/usr/src/lib/libsmbfs/smb/private.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2000-2001 Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _PRIVATE_H
+#define _PRIVATE_H
+
+/*
+ * Private declarations for this library.
+ * Moved from smb_lib.h
+ */
+
+#include <inttypes.h>
+
+/*
+ * BSD-style mbuf simulation
+ */
+struct mbuf {
+ int m_len;
+ int m_maxlen;
+ char *m_data;
+ struct mbuf *m_next;
+};
+typedef struct mbuf mbuf_t;
+
+#if 0 /* in smb_lib.h */
+struct mbdata {
+ struct mbuf *mb_top;
+ struct mbuf *mb_cur;
+ char *mb_pos;
+ int mb_count;
+};
+typedef struct mbdata mbdata_t;
+#endif
+
+#define M_ALIGNFACTOR (sizeof (long))
+#define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1))
+#define M_BASESIZE (sizeof (struct mbuf))
+#define M_MINSIZE (256 - M_BASESIZE)
+#define M_TOP(m) ((char *)(m) + M_BASESIZE)
+#define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len)
+#define mtod(m, t) ((t)(m)->m_data)
+
+/*
+ * request handling structures
+ */
+struct smb_rq {
+ uchar_t rq_cmd;
+ struct mbdata rq_rq;
+ struct mbdata rq_rp;
+ struct smb_ctx *rq_ctx;
+ int rq_wcount;
+ int rq_bcount;
+};
+typedef struct smb_rq smb_rq_t;
+
+#define smb_rq_getrequest(rqp) (&(rqp)->rq_rq)
+#define smb_rq_getreply(rqp) (&(rqp)->rq_rp)
+
+int smb_rq_init(struct smb_ctx *, uchar_t, size_t, struct smb_rq **);
+void smb_rq_done(struct smb_rq *);
+void smb_rq_wend(struct smb_rq *);
+int smb_rq_simple(struct smb_rq *);
+int smb_rq_dmem(struct mbdata *, const char *, size_t);
+int smb_rq_dstring(struct mbdata *, const char *);
+
+
+/*
+ * Message compose/parse
+ */
+
+int m_getm(struct mbuf *, size_t, struct mbuf **);
+int m_lineup(struct mbuf *, struct mbuf **);
+int mb_init(struct mbdata *, size_t);
+int mb_initm(struct mbdata *, struct mbuf *);
+int mb_done(struct mbdata *);
+int mb_fit(struct mbdata *mbp, size_t size, char **pp);
+int mb_put_uint8(struct mbdata *, uint8_t);
+int mb_put_uint16be(struct mbdata *, uint16_t);
+int mb_put_uint16le(struct mbdata *, uint16_t);
+int mb_put_uint32be(struct mbdata *, uint32_t);
+int mb_put_uint32le(struct mbdata *, uint32_t);
+int mb_put_uint64be(struct mbdata *, uint64_t);
+int mb_put_uint64le(struct mbdata *, uint64_t);
+int mb_put_mem(struct mbdata *, const char *, size_t);
+int mb_put_pstring(struct mbdata *mbp, const char *s);
+int mb_put_mbuf(struct mbdata *, struct mbuf *);
+
+int mb_get_uint8(struct mbdata *, uint8_t *);
+int mb_get_uint16(struct mbdata *, uint16_t *);
+int mb_get_uint16le(struct mbdata *, uint16_t *);
+int mb_get_uint16be(struct mbdata *, uint16_t *);
+int mb_get_uint32(struct mbdata *, uint32_t *);
+int mb_get_uint32be(struct mbdata *, uint32_t *);
+int mb_get_uint32le(struct mbdata *, uint32_t *);
+int mb_get_uint64(struct mbdata *, uint64_t *);
+int mb_get_uint64be(struct mbdata *, uint64_t *);
+int mb_get_uint64le(struct mbdata *, uint64_t *);
+int mb_get_mem(struct mbdata *, char *, size_t);
+
+/*
+ * Network stuff (NetBIOS and otherwise)
+ */
+
+int nb_name_len(struct nb_name *);
+/* new flag UCflag. 1=uppercase,0=don't */
+int nb_name_encode(struct nb_name *, uchar_t *);
+int nb_encname_len(const uchar_t *);
+
+int nb_snballoc(int namelen, struct sockaddr_nb **);
+void nb_snbfree(struct sockaddr *);
+int nb_sockaddr(struct sockaddr *, struct nb_name *, struct sockaddr_nb **);
+
+int nbns_resolvename(const char *, struct nb_ctx *, struct sockaddr **);
+int nbns_getnodestatus(struct sockaddr *targethost,
+ struct nb_ctx *ctx, char *system, char *workgroup);
+int nb_getlocalname(char *name, size_t maxlen);
+
+extern uchar_t nls_lower[256], nls_upper[256];
+
+#endif /* _PRIVATE_H */
diff --git a/usr/src/lib/libsmbfs/smb/rap.c b/usr/src/lib/libsmbfs/smb/rap.c
index 00ccbd54a2..3a9e785191 100644
--- a/usr/src/lib/libsmbfs/smb/rap.c
+++ b/usr/src/lib/libsmbfs/smb/rap.c
@@ -34,8 +34,6 @@
* This is very simple implementation of RAP protocol.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/stat.h>
@@ -52,6 +50,7 @@
#include <netsmb/mchain.h>
#include <netsmb/smb_lib.h>
#include <netsmb/smb_rap.h>
+#include "private.h"
static int
smb_rap_parserqparam(const char *s, char **next, int *rlen)
@@ -166,23 +165,28 @@ smb_rap_rqparam_z(struct smb_rap *rap, const char *value)
static int
smb_rap_rqparam(struct smb_rap *rap, char ptype, char plen, int value)
{
- char *p = rap->r_npbuf;
int len = 0;
uint_t uv = (uint_t)value;
+ uint32_t *lp;
+ uint16_t *sp;
+ char *p;
switch (ptype) {
case 'L':
case 'W':
/* LINTED */
- setwle(p, 0, uv);
- len = 2;
+ sp = (uint16_t *)rap->r_npbuf;
+ *sp = htoles(uv);
+ len = sizeof (*sp);
break;
case 'D':
/* LINTED */
- setdle(p, 0, uv);
- len = 4;
+ lp = (uint32_t *)rap->r_npbuf;
+ *lp = htolel(uv);
+ len = sizeof (*lp);
break;
case 'b':
+ p = rap->r_npbuf;
memset(p, uv, plen);
len = plen;
default:
@@ -293,7 +297,7 @@ smb_rap_setPparam(struct smb_rap *rap, void *value)
return (0);
}
-static int
+int
smb_rap_getNparam(struct smb_rap *rap, long *value)
{
char *p = rap->r_nparam;
@@ -436,33 +440,3 @@ smb_rap_error(struct smb_rap *rap, int error)
return (0);
return (rap->r_result | SMB_RAP_ERROR);
}
-
-/* todo: move this function to libnetapi */
-int
-smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
- int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
-{
- struct smb_rap *rap;
- long lval = -1;
- int error;
- char *pass;
- int i;
-
- error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
- if (error)
- return (error);
- smb_rap_setNparam(rap, sLevel); /* W - sLevel */
- smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */
- smb_rap_setNparam(rap, *cbBuffer); /* L - cbBuffer */
- error = smb_rap_request(rap, ctx);
- if (error == 0) {
- *pcEntriesRead = rap->r_entries;
- error = smb_rap_getNparam(rap, &lval);
- *pcTotalAvail = lval;
- /* Copy the data length into the IN/OUT variable. */
- *cbBuffer = rap->r_rcvbuflen;
- }
- error = smb_rap_error(rap, error);
- smb_rap_done(rap);
- return (error);
-}
diff --git a/usr/src/lib/libsmbfs/smb/rcfile.c b/usr/src/lib/libsmbfs/smb/rcfile.c
index 498b91c0d8..3f5a87435d 100644
--- a/usr/src/lib/libsmbfs/smb/rcfile.c
+++ b/usr/src/lib/libsmbfs/smb/rcfile.c
@@ -32,8 +32,6 @@
* $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <fcntl.h>
#include <sys/types.h>
#include <sys/queue.h>
@@ -51,6 +49,7 @@
#include <cflib.h>
#include "rcfile_priv.h"
+extern int smb_debug;
SLIST_HEAD(rcfile_head, rcfile);
static struct rcfile_head pf_head = {NULL};
@@ -312,15 +311,19 @@ set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp,
new = eval_minauth(ptr);
if (new >= now) {
#ifdef DEBUG
- printf("set_value: rejecting %s=%s from %s\n",
- rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF");
+ if (smb_debug)
+ printf(
+ "set_value: rejecting %s=%s from %s\n",
+ rkp->rk_name, ptr, home_nsmbrc ?
+ "user file" : "SMF");
#endif
return;
}
}
#ifdef DEBUG
- printf("set_value: applying %s=%s from %s\n",
- rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF");
+ if (smb_debug)
+ printf("set_value: applying %s=%s from %s\n",
+ rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF");
#endif
rkp->rk_value = strdup(ptr);
}
@@ -393,7 +396,8 @@ rc_parse(struct rcfile *rcp)
if (home_nsmbrc &&
(strcmp(buf, "nbns") == 0 ||
strcmp(buf, "nbns_enable") == 0 ||
- strcmp(buf, "nbns_broadcast") == 0)) {
+ strcmp(buf, "nbns_broadcast") == 0 ||
+ strcmp(buf, "signing") == 0)) {
fprintf(stderr, dgettext(TEXT_DOMAIN,
"option %s may not be set "
"in user .nsmbrc file\n"), buf);
diff --git a/usr/src/lib/libsmbfs/smb/rq.c b/usr/src/lib/libsmbfs/smb/rq.c
index c31c271819..6390a3c157 100644
--- a/usr/src/lib/libsmbfs/smb/rq.c
+++ b/usr/src/lib/libsmbfs/smb/rq.c
@@ -32,8 +32,6 @@
* $Id: rq.c,v 1.4 2004/12/13 00:25:23 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -50,8 +48,7 @@
#include <libintl.h>
#include <netsmb/smb_lib.h>
-
-extern uid_t real_uid, eff_uid;
+#include "private.h"
int
@@ -149,15 +146,12 @@ smb_rq_simple(struct smb_rq *rqp)
mbp = smb_rq_getreply(rqp);
krq.ioc_rpbufsz = mbp->mb_top->m_maxlen;
krq.ioc_rpbuf = mtod(mbp->mb_top, char *);
- seteuid(eff_uid);
if (ioctl(rqp->rq_ctx->ct_fd, SMBIOC_REQUEST, &krq) == -1) {
- seteuid(real_uid); /* and back to real user */
return (errno);
}
mbp->mb_top->m_len = krq.ioc_rwc * 2 + krq.ioc_rbc;
rqp->rq_wcount = krq.ioc_rwc;
rqp->rq_bcount = krq.ioc_rbc;
- seteuid(real_uid); /* and back to real user */
return (0);
}
@@ -197,9 +191,7 @@ smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup,
krq->ioc_rparam = rparam;
krq->ioc_rdata = rdata;
- seteuid(eff_uid);
if (ioctl(ctx->ct_fd, SMBIOC_T2RQ, krq) == -1) {
- seteuid(real_uid); /* and back to real user */
return (errno);
}
@@ -207,7 +199,6 @@ smb_t2_request(struct smb_ctx *ctx, int setupcount, uint16_t *setup,
*rdatacnt = krq->ioc_rdatacnt;
*buffer_oflow = (krq->ioc_rpflags2 & SMB_FLAGS2_ERR_STATUS) &&
(krq->ioc_error == NT_STATUS_BUFFER_OVERFLOW);
- seteuid(real_uid); /* and back to real user */
free(krq);
return (0);
}
diff --git a/usr/src/lib/libsmbfs/smb/subr.c b/usr/src/lib/libsmbfs/smb/subr.c
index 46842d730f..36a3c30ed9 100644
--- a/usr/src/lib/libsmbfs/smb/subr.c
+++ b/usr/src/lib/libsmbfs/smb/subr.c
@@ -32,14 +32,9 @@
* $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/param.h>
#include <sys/types.h>
#include <sys/errno.h>
-#include <sys/syscall.h>
-#include <sys/wait.h>
-#include <sys/debug.h>
+#include <sys/time.h>
#include <unistd.h>
#include <ctype.h>
@@ -224,7 +219,8 @@ smb_open_rcfile(struct smb_ctx *ctx)
fprintf(stderr, dgettext(TEXT_DOMAIN,
"Can't open %s: %s\n"), fn, smb_strerror(errno));
#ifdef DEBUG
- dump_props("after reading global repository");
+ if (smb_debug)
+ dump_props("after reading global repository");
#endif
home = getenv("HOME");
@@ -244,7 +240,8 @@ smb_open_rcfile(struct smb_ctx *ctx)
}
home_nsmbrc = 0;
#ifdef DEBUG
- dump_props("after reading user settings");
+ if (smb_debug)
+ dump_props("after reading user settings");
#endif
if (smb_rc == NULL) {
return (ENOENT);
@@ -306,76 +303,6 @@ smb_simpledecrypt(char *dst, const char *src)
return (0);
}
-
-static int
-safe_execv(char *args[])
-{
- int pid;
- int status;
-
- pid = fork();
- if (pid == 0) {
- (void) execv(args[0], args);
- /* Changed from errx() to fprintf(stderr) -Pavan */
- fprintf(stderr, dgettext(TEXT_DOMAIN,
- "%s: execv %s failed, %s\n"), __progname,
- args[0], smb_strerror(errno));
- }
- if (pid == -1) {
- fprintf(stderr, dgettext(TEXT_DOMAIN, "%s: fork failed, %s\n"),
- __progname, smb_strerror(errno));
- return (1);
- }
- if (wait4(pid, &status, 0, NULL) != pid) {
- fprintf(stderr, dgettext(TEXT_DOMAIN,
- "%s: BUG executing %s command\n"), __progname, args[0]);
- return (1);
- } else if (!WIFEXITED(status)) {
- fprintf(stderr, dgettext(TEXT_DOMAIN,
- "%s: %s command aborted by signal %d\n"),
- __progname, args[0], WTERMSIG(status));
- return (1);
- } else if (WEXITSTATUS(status)) {
- fprintf(stderr, dgettext(TEXT_DOMAIN,
- "%s: %s command failed, exit status %d: %s\n"),
- __progname, args[0], WEXITSTATUS(status),
- smb_strerror(WEXITSTATUS(status)));
- return (1);
- }
- return (0);
-}
-
-
-void
-dropsuid()
-{
- /* drop setuid root privs asap */
- eff_uid = geteuid();
- real_uid = getuid();
- seteuid(real_uid);
-}
-
-
-#define KEXTLOAD_COMMAND "/sbin/kextload"
-#define FS_KEXT_DIR "/System/Library/Extensions/smbfs.kext"
-#define FULL_KEXTNAME "com.apple.filesystems.smbfs"
-
-
-int
-loadsmbvfs()
-{
- char *kextargs[] = {KEXTLOAD_COMMAND, FS_KEXT_DIR, NULL};
- int error = 0;
-
- /*
- * temporarily revert to root (required for kextload)
- */
- seteuid(eff_uid);
- error = safe_execv(kextargs);
- seteuid(real_uid); /* and back to real user */
- return (error);
-}
-
#undef __progname
char *__progname = NULL;
diff --git a/usr/src/lib/libsmbfs/smb/utf_str.c b/usr/src/lib/libsmbfs/smb/utf_str.c
new file mode 100644
index 0000000000..e80b1180f2
--- /dev/null
+++ b/usr/src/lib/libsmbfs/smb/utf_str.c
@@ -0,0 +1,207 @@
+/*
+ * 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Unicode conversions (yet more)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <iconv.h>
+#include <libintl.h>
+
+#include <sys/u8_textprep.h>
+
+#include <netsmb/smb_lib.h>
+#include "charsets.h"
+
+
+/*
+ * Number of unicode symbols in the string,
+ * not including the 2-byte null terminator.
+ * (multiply by two for storage size)
+ */
+size_t
+unicode_strlen(const uint16_t *us)
+{
+ size_t len = 0;
+ while (*us++)
+ len++;
+ return (len);
+}
+
+static char *convert_ucs2xx_to_utf8(iconv_t, const uint16_t *);
+
+/*
+ * Convert (native) Unicode string to UTF-8.
+ * Returns allocated memory.
+ */
+char *
+convert_unicode_to_utf8(uint16_t *us)
+{
+ static iconv_t cd1 = (iconv_t)-1;
+
+ /* Get conversion descriptor (to, from) */
+ if (cd1 == (iconv_t)-1)
+ cd1 = iconv_open("UTF-8", "UCS-2");
+
+ return (convert_ucs2xx_to_utf8(cd1, us));
+}
+
+/*
+ * Convert little-endian Unicode string to UTF-8.
+ * Returns allocated memory.
+ */
+char *
+convert_leunicode_to_utf8(unsigned short *us)
+{
+ static iconv_t cd2 = (iconv_t)-1;
+
+ /* Get conversion descriptor (to, from) */
+ if (cd2 == (iconv_t)-1)
+ cd2 = iconv_open("UTF-8", "UCS-2LE");
+
+ return (convert_ucs2xx_to_utf8(cd2, us));
+}
+
+static char *
+convert_ucs2xx_to_utf8(iconv_t cd, const uint16_t *us)
+{
+ char *obuf, *optr;
+ const char *iptr;
+ size_t ileft, obsize, oleft, ret;
+
+ if (cd == (iconv_t)-1) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "iconv_open(UTF-8/UCS-2)"), -1);
+ return (NULL);
+ }
+
+ iptr = (const char *)us;
+ ileft = unicode_strlen(us);
+ ileft *= 2; /* now bytes */
+
+ /* Worst-case output size is 2x input size. */
+ oleft = ileft * 2;
+ obsize = oleft + 2; /* room for null */
+ obuf = malloc(obsize);
+ if (!obuf)
+ return (NULL);
+ optr = obuf;
+
+ ret = iconv(cd, &iptr, &ileft, &optr, &oleft);
+ *optr = '\0';
+ if (ret == (size_t)-1) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "iconv(%s) failed"), errno, obuf);
+ }
+ if (ileft) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "iconv(%s) failed"), -1, obuf);
+ /*
+ * XXX: What's better? return NULL?
+ * The truncated string? << for now
+ */
+ }
+
+ return (obuf);
+}
+
+static uint16_t *convert_utf8_to_ucs2xx(iconv_t, const char *);
+
+/*
+ * Convert UTF-8 string to Unicode.
+ * Returns allocated memory.
+ */
+uint16_t *
+convert_utf8_to_unicode(const char *utf8_string)
+{
+ static iconv_t cd3 = (iconv_t)-1;
+
+ /* Get conversion descriptor (to, from) */
+ if (cd3 == (iconv_t)-1)
+ cd3 = iconv_open("UCS-2", "UTF-8");
+ return (convert_utf8_to_ucs2xx(cd3, utf8_string));
+}
+
+/*
+ * Convert UTF-8 string to little-endian Unicode.
+ * Returns allocated memory.
+ */
+uint16_t *
+convert_utf8_to_leunicode(const char *utf8_string)
+{
+ static iconv_t cd4 = (iconv_t)-1;
+
+ /* Get conversion descriptor (to, from) */
+ if (cd4 == (iconv_t)-1)
+ cd4 = iconv_open("UCS-2LE", "UTF-8");
+ return (convert_utf8_to_ucs2xx(cd4, utf8_string));
+}
+
+static uint16_t *
+convert_utf8_to_ucs2xx(iconv_t cd, const char *utf8_string)
+{
+ uint16_t *obuf, *optr;
+ const char *iptr;
+ size_t ileft, obsize, oleft, ret;
+
+ if (cd == (iconv_t)-1) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "iconv_open(UCS-2/UTF-8)"), -1);
+ return (NULL);
+ }
+
+ iptr = utf8_string;
+ ileft = strlen(iptr);
+
+ /* Worst-case output size is 2x input size. */
+ oleft = ileft * 2;
+ obsize = oleft + 2; /* room for null */
+ obuf = malloc(obsize);
+ if (!obuf)
+ return (NULL);
+ optr = obuf;
+
+ ret = iconv(cd, &iptr, &ileft, (char **)&optr, &oleft);
+ *optr = '\0';
+ if (ret == (size_t)-1) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "iconv(%s) failed"), errno, utf8_string);
+ }
+ if (ileft) {
+ smb_error(dgettext(TEXT_DOMAIN,
+ "iconv(%s) failed"), -1, utf8_string);
+ /*
+ * XXX: What's better? return NULL?
+ * The truncated string? << for now
+ */
+ }
+
+ return (obuf);
+}
diff --git a/usr/src/pkgdefs/SUNWsmbfskr/prototype_com b/usr/src/pkgdefs/SUNWsmbfskr/prototype_com
index 413dabf008..71e791051d 100644
--- a/usr/src/pkgdefs/SUNWsmbfskr/prototype_com
+++ b/usr/src/pkgdefs/SUNWsmbfskr/prototype_com
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -46,5 +44,8 @@ i postinstall
#
# SUNWsmbfskr
#
-d none kernel 755 root sys
-d none kernel/kmdb 755 root sys
+
+# This package now delivers NO binaries.
+# It just does preremove/postinstall.
+# Could we move those to SUNSsmbfsr
+# and eliminate this package?
diff --git a/usr/src/pkgdefs/SUNWsmbfskr/prototype_i386 b/usr/src/pkgdefs/SUNWsmbfskr/prototype_i386
index 0e53bffbd4..a1f4b55b3e 100644
--- a/usr/src/pkgdefs/SUNWsmbfskr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWsmbfskr/prototype_i386
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -46,8 +44,3 @@
#
# SUNWsmbfskr
#
-f none kernel/kmdb/nsmb 555 root sys
-f none kernel/kmdb/smbfs 555 root sys
-d none kernel/kmdb/amd64 755 root sys
-f none kernel/kmdb/amd64/nsmb 555 root sys
-f none kernel/kmdb/amd64/smbfs 555 root sys
diff --git a/usr/src/pkgdefs/SUNWsmbfskr/prototype_sparc b/usr/src/pkgdefs/SUNWsmbfskr/prototype_sparc
index 2d70a10095..33039668f1 100644
--- a/usr/src/pkgdefs/SUNWsmbfskr/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWsmbfskr/prototype_sparc
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -46,6 +44,3 @@
#
# SUNWsmbfskr
#
-d none kernel/kmdb/sparcv9 755 root sys
-f none kernel/kmdb/sparcv9/nsmb 555 root sys
-f none kernel/kmdb/sparcv9/smbfs 555 root sys
diff --git a/usr/src/pkgdefs/SUNWsmbfsu/prototype_com b/usr/src/pkgdefs/SUNWsmbfsu/prototype_com
index 972f84fd80..985c9cecb4 100644
--- a/usr/src/pkgdefs/SUNWsmbfsu/prototype_com
+++ b/usr/src/pkgdefs/SUNWsmbfsu/prototype_com
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -45,13 +43,16 @@ i depend
#
d none usr 755 root sys
+
d none usr/bin 755 root bin
f none usr/bin/smbutil 555 root bin
+
d none usr/kernel 755 root sys
-d none usr/kernel/fs 755 root sys
-d none usr/kernel/sys 755 root sys
d none usr/kernel/drv 755 root sys
f none usr/kernel/drv/nsmb.conf 644 root sys
+d none usr/kernel/fs 755 root sys
+d none usr/kernel/kmdb 755 root sys
+
d none usr/lib 755 root bin
d none usr/lib/fs 755 root sys
d none usr/lib/fs/smbfs 755 root sys
diff --git a/usr/src/pkgdefs/SUNWsmbfsu/prototype_i386 b/usr/src/pkgdefs/SUNWsmbfsu/prototype_i386
index 9d2dbebc7f..7bbcd48bf5 100644
--- a/usr/src/pkgdefs/SUNWsmbfsu/prototype_i386
+++ b/usr/src/pkgdefs/SUNWsmbfsu/prototype_i386
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -46,16 +44,20 @@
# SUNWsmbfsu
#
-f none usr/kernel/fs/smbfs 755 root sys
-l none usr/kernel/sys/smbfs=../../kernel/fs/smbfs
-d none usr/kernel/fs/amd64 755 root sys
-f none usr/kernel/fs/amd64/smbfs 755 root sys
-d none usr/kernel/sys/amd64 755 root sys
-l none usr/kernel/sys/amd64/smbfs=../../../kernel/fs/amd64/smbfs
f none usr/kernel/drv/nsmb 755 root sys
d none usr/kernel/drv/amd64 755 root sys
f none usr/kernel/drv/amd64/nsmb 755 root sys
+f none usr/kernel/fs/smbfs 755 root sys
+d none usr/kernel/fs/amd64 755 root sys
+f none usr/kernel/fs/amd64/smbfs 755 root sys
+
+f none usr/kernel/kmdb/nsmb 555 root sys
+f none usr/kernel/kmdb/smbfs 555 root sys
+d none usr/kernel/kmdb/amd64 755 root sys
+f none usr/kernel/kmdb/amd64/nsmb 555 root sys
+f none usr/kernel/kmdb/amd64/smbfs 555 root sys
+
d none usr/lib/amd64 755 root bin
f none usr/lib/amd64/libsmbfs.so.1 755 root bin
d none usr/lib/fs/smbfs/amd64 755 root sys
diff --git a/usr/src/pkgdefs/SUNWsmbfsu/prototype_sparc b/usr/src/pkgdefs/SUNWsmbfsu/prototype_sparc
index 71f3c41e9c..101a77834f 100644
--- a/usr/src/pkgdefs/SUNWsmbfsu/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWsmbfsu/prototype_sparc
@@ -22,8 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
# This required package information file contains a list of package contents.
# The 'pkgmk' command uses this file to identify the contents of a package
# and their location on the development machine when building the package.
@@ -46,13 +44,16 @@
# SUNWsmbfsu
#
-d none usr/kernel/fs/sparcv9 755 root sys
-f none usr/kernel/fs/sparcv9/smbfs 755 root sys
-d none usr/kernel/sys/sparcv9 755 root sys
-l none usr/kernel/sys/sparcv9/smbfs=../../../kernel/fs/sparcv9/smbfs
d none usr/kernel/drv/sparcv9 755 root sys
f none usr/kernel/drv/sparcv9/nsmb 755 root sys
+d none usr/kernel/fs/sparcv9 755 root sys
+f none usr/kernel/fs/sparcv9/smbfs 755 root sys
+
+d none usr/kernel/kmdb/sparcv9 755 root sys
+f none usr/kernel/kmdb/sparcv9/nsmb 555 root sys
+f none usr/kernel/kmdb/sparcv9/smbfs 555 root sys
+
d none usr/lib/sparcv9 755 root bin
f none usr/lib/sparcv9/libsmbfs.so.1 755 root bin
d none usr/lib/fs/smbfs/sparcv9 755 root sys
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index a2259e9e54..2a54074941 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1163,8 +1163,8 @@ NSMB_OBJS += smb_conn.o smb_crypt.o smb_dev.o smb_iod.o \
smb_usr.o smb_subrs.o subr_mchain.o smb_pass.o
SMBFS_OBJS += smbfs_vfsops.o smbfs_vnops.o smbfs_node.o \
- smbfs_acl.o smbfs_client.o smbfs_io.o \
- smbfs_smb.o smbfs_subr.o smbfs_subr2.o \
+ smbfs_acl.o smbfs_client.o smbfs_smb.o \
+ smbfs_subr.o smbfs_subr2.o \
smbfs_rwlock.o smbfs_xattr.o
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
index af3a4a39b2..42475923d3 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
@@ -710,13 +710,6 @@ smb_vc_setup(struct smb_vcspec *vcspec, struct smb_cred *scred,
/* Just save all the SMBVOPT_ options. */
vcp->vc_vopt = vcspec->optflags;
- /* Cleared if nego response shows antique server! */
- vcp->vc_hflags2 |= SMB_FLAGS2_KNOWS_LONG_NAMES;
-
- /* XXX: Odd place for this. */
- if (vcspec->optflags & SMBVOPT_EXT_SEC)
- vcp->vc_hflags2 |= SMB_FLAGS2_EXT_SEC;
-
if (is_ss) {
/* Called from smb_sm_ssnsetup */
@@ -943,6 +936,9 @@ smb_vc_free(struct smb_connobj *cp)
if (vcp->vc_negtok)
kmem_free(vcp->vc_negtok, vcp->vc_negtoklen);
+ if (vcp->vc_mackey != NULL)
+ kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
+
cv_destroy(&vcp->iod_exit);
rw_destroy(&vcp->iod_rqlock);
sema_destroy(&vcp->vc_sendlock);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
index e2a55b970d..4662acd111 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h
@@ -40,8 +40,6 @@
#ifndef _SMB_CONN_H
#define _SMB_CONN_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/t_lock.h>
#include <sys/queue.h> /* for SLIST below */
#include <sys/uio.h>
@@ -69,16 +67,19 @@ typedef struct smb_cred {
* Many of these were duplicates of SMBVOPT_ flags
* and we now keep those too instead of merging
* them into vc_flags.
+ *
+ * Careful here: In smb_smb_negotiate, we clear ALL OF
+ * vc_flags except: SMBV_GONE, SMBV_RECONNECTING
*/
+#define SMBV_RECONNECTING 0x0002 /* conn in process of reconnection */
#define SMBV_LONGNAMES 0x0004 /* conn configured to use long names */
#define SMBV_ENCRYPT 0x0008 /* server demands encrypted password */
#define SMBV_WIN95 0x0010 /* used to apply bugfixes for this OS */
#define SMBV_NT4 0x0020 /* used when NT4 issues invalid resp */
-#define SMBV_RECONNECTING 0x0040 /* conn in process of reconnection */
-/* 0x0200 unused - was SMBV_FAILED */
-#define SMBV_UNICODE 0x0400 /* conn configured to use Unicode */
-#define SMBV_EXT_SEC 0x0800 /* conn to use extended security */
+#define SMBV_UNICODE 0x0040 /* conn configured to use Unicode */
+#define SMBV_EXT_SEC 0x0080 /* conn to use extended security */
+#define SMBV_WILL_SIGN 0x0100 /* negotiated signing */
/*
* Note: the common "obj" level uses this GONE flag by
@@ -245,7 +246,10 @@ typedef struct smb_vc {
char *vc_pass; /* password for usl case */
uchar_t vc_lmhash[SMB_PWH_MAX];
uchar_t vc_nthash[SMB_PWH_MAX];
-
+ uint8_t *vc_mackey; /* MAC key */
+ int vc_mackeylen; /* length of MAC key */
+ uint32_t vc_seqno; /* my next sequence number - */
+ /* - serialized by iod_rqlock */
uint_t vc_timo; /* default request timeout */
int vc_maxvcs; /* maximum number of VC per conn */
@@ -266,7 +270,7 @@ typedef struct smb_vc {
struct smb_tran_desc *vc_tdesc;
int vc_chlen; /* actual challenge length */
uchar_t vc_challenge[SMB_MAXCHALLENGELEN];
- uint16_t vc_mid; /* multiplex id */
+ uint16_t vc_mid; /* multiplex id */
int vc_vopt; /* local options SMBVOPT_ */
struct smb_sopt vc_sopt; /* server options */
struct smb_cred vc_scred; /* used in reconnect procedure */
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_crypt.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_crypt.c
index 64057080b9..10d77644de 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_crypt.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_crypt.c
@@ -32,7 +32,10 @@
* $Id: smb_crypt.c,v 1.13 2005/01/26 23:50:50 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <sys/param.h>
#include <sys/systm.h>
@@ -47,21 +50,41 @@
#include <sys/crypto/api.h>
#include <sys/crypto/common.h>
#include <sys/cmn_err.h>
+#include <sys/stream.h>
+#include <sys/strsun.h>
+#include <sys/sdt.h>
#include <netsmb/smb_osdep.h>
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
#include <netsmb/smb_dev.h>
+#include <netsmb/smb_rq.h>
+
+#ifdef DEBUG
+/*
+ * Set this to a small number to debug sequence numbers
+ * that seem to get out of step.
+ */
+int nsmb_signing_fudge = 0;
+#endif
-static uchar_t N8[] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+/* Mechanism definitions */
+static crypto_mechanism_t crypto_mech_md5 = { CRYPTO_MECH_INVALID };
+static crypto_mechanism_t crypto_mech_des = { CRYPTO_MECH_INVALID };
+
+void
+smb_crypto_mech_init(void)
+{
+ crypto_mech_des.cm_type = crypto_mech2id(SUN_CKM_DES_ECB);
+ crypto_mech_md5.cm_type = crypto_mech2id(SUN_CKM_MD5);
+}
static void
-smb_E(const uchar_t *key, uchar_t *data, uchar_t *dest)
+smb_E(const uchar_t *key, const uchar_t *data, uchar_t *dest)
{
int rv;
uchar_t kk[8];
- crypto_mechanism_t mech;
crypto_data_t d1, d2;
crypto_key_t keyt;
@@ -97,13 +120,10 @@ smb_E(const uchar_t *key, uchar_t *data, uchar_t *dest)
d2.cd_raw.iov_len = 8;
d2.cd_raw.iov_base = (void *)dest;
- mech.cm_type = crypto_mech2id(SUN_CKM_DES_ECB);
- if (mech.cm_type == CRYPTO_MECH_INVALID)
- cmn_err(CE_NOTE, "Invalid algorithm\n");
- mech.cm_param = NULL;
- mech.cm_param_len = 0;
+ /* Checked this in callers */
+ ASSERT(crypto_mech_des.cm_type != CRYPTO_MECH_INVALID);
- rv = crypto_encrypt(&mech, &d1, &keyt, NULL, &d2, NULL);
+ rv = crypto_encrypt(&crypto_mech_des, &d1, &keyt, NULL, &d2, NULL);
if (rv != CRYPTO_SUCCESS)
SMBSDEBUG("crypto_encrypt failed.\n");
}
@@ -114,8 +134,18 @@ smb_E(const uchar_t *key, uchar_t *data, uchar_t *dest)
void
smb_oldlm_hash(const char *apwd, uchar_t *lmhash)
{
+ static const uchar_t N8[] = "KGS!@#$%";
uchar_t P14[14+1];
+ /* In case we error out. */
+ bzero(lmhash, 21);
+
+ /* Note ASSERT in smb_E */
+ if (crypto_mech_des.cm_type == CRYPTO_MECH_INVALID) {
+ SMBSDEBUG("crypto_mech_des invalid\n");
+ return;
+ }
+
/* Convert apwd to upper case, zero extend. */
bzero(P14, sizeof (P14));
smb_toupper(apwd, (char *)P14, 14);
@@ -123,7 +153,6 @@ smb_oldlm_hash(const char *apwd, uchar_t *lmhash)
/*
* lmhash = concat(Ex(P14, N8), zeros(5));
*/
- bzero(lmhash, 21);
smb_E(P14, N8, lmhash);
smb_E(P14 + 7, N8, lmhash + 8);
}
@@ -136,9 +165,18 @@ smb_oldlm_hash(const char *apwd, uchar_t *lmhash)
* is computed by the caller, this is used for both.
*/
int
-smb_lmresponse(const uchar_t *hash, uchar_t *C8, uchar_t *RN)
+smb_lmresponse(const uchar_t *hash, const uchar_t *C8, uchar_t *RN)
{
+ /* In case we error out. */
+ bzero(RN, 24);
+
+ /* Note ASSERT in smb_E */
+ if (crypto_mech_des.cm_type == CRYPTO_MECH_INVALID) {
+ SMBSDEBUG("crypto_mech_des invalid\n");
+ return (ENOTSUP);
+ }
+
smb_E(hash, C8, RN);
smb_E(hash + 7, C8, RN + 8);
smb_E(hash + 14, C8, RN + 16);
@@ -233,56 +271,392 @@ HMACT64(const uchar_t *key, size_t key_len, const uchar_t *data,
}
/*
- * Compute an NTLMv2 response given the 21 byte NTLM(v1) hash,
- * the user name, the destination workgroup/domain name,
- * a challenge, and the blob.
+ * Compute an NTLMv2 hash given the NTLMv1 hash, the user name,
+ * the destination machine or domain name, and a challenge.
*/
-int
-smb_ntlmv2response(const uchar_t *v1hash, const uchar_t *user,
- const uchar_t *destination, uchar_t *C8, const uchar_t *blob,
- size_t bloblen, uchar_t **RN, size_t *RNlen)
+void
+smb_ntlmv2hash(const uchar_t *v1hash, const char *user,
+ const char *destination, uchar_t *v2hash)
{
u_int16_t *uniuser, *unidest;
size_t uniuserlen, unidestlen;
- uchar_t v2hash[16];
- size_t len;
+ size_t uniuser_sz, unidest_sz;
+ int len;
size_t datalen;
- uchar_t *data, *data1;
- size_t v2resplen;
- uchar_t *v2resp;
+ uchar_t *data;
/*
- * v2hash=HMACT64(v1hash, 16, concat(upcase(user), upcase(destination))
+ * v2hash = HMACT64(v1hash, 16, concat(upcase(user), upcase(dest))
+ * where "dest" is the domain or server name ("target name")
* We assume that user and destination are supplied to us as
* upper-case UTF-8.
*/
len = strlen((char *)user);
- uniuser = kmem_alloc(len * sizeof (u_int16_t) + 1, KM_SLEEP);
+ uniuser_sz = (len + 1) * sizeof (u_int16_t);
+ uniuser = kmem_alloc(uniuser_sz, KM_SLEEP);
uniuserlen = smb_strtouni(uniuser, (char *)user, len,
UCONV_IGNORE_NULL);
+
len = strlen((char *)destination);
- unidest = kmem_alloc(len * sizeof (u_int16_t) + 1, KM_SLEEP);
+ unidest_sz = (len + 1) * sizeof (u_int16_t);
+ unidest = kmem_alloc(unidest_sz, KM_SLEEP);
unidestlen = smb_strtouni(unidest, (char *)destination, len,
UCONV_IGNORE_NULL);
+
datalen = uniuserlen + unidestlen;
data = kmem_alloc(datalen, KM_SLEEP);
bcopy(uniuser, data, uniuserlen);
bcopy(unidest, data + uniuserlen, unidestlen);
- kmem_free(uniuser, strlen((char *)user) * sizeof (u_int16_t) + 1);
- kmem_free(unidest, len * sizeof (u_int16_t) + 1);
+ kmem_free(uniuser, uniuser_sz);
+ kmem_free(unidest, unidest_sz);
+
HMACT64(v1hash, 16, data, datalen, v2hash);
kmem_free(data, datalen);
+}
+
+/*
+ * Compute an NTLMv2 response given the 16 byte NTLMv2 hash,
+ * a challenge, and the blob.
+ */
+int
+smb_ntlmv2response(const uchar_t *v2hash, const uchar_t *C8,
+ const uchar_t *blob, size_t bloblen, uchar_t **RN, size_t *RNlen)
+{
+ size_t datalen;
+ uchar_t *data;
+ size_t v2resplen;
+ uchar_t *v2resp;
datalen = 8 + bloblen;
- data1 = kmem_alloc(datalen, KM_SLEEP);
- bcopy(C8, data1, 8);
- bcopy(blob, data1 + 8, bloblen);
+ data = kmem_alloc(datalen, KM_SLEEP);
+ bcopy(C8, data, 8);
+ bcopy(blob, data + 8, bloblen);
v2resplen = 16 + bloblen;
v2resp = kmem_alloc(v2resplen, KM_SLEEP);
- HMACT64(v2hash, 16, data1, datalen, v2resp);
- kmem_free(data1, datalen);
+ HMACT64(v2hash, 16, data, datalen, v2resp);
+ kmem_free(data, datalen);
bcopy(blob, v2resp + 16, bloblen);
*RN = v2resp;
*RNlen = v2resplen;
+
+ return (0);
+}
+
+/*
+ * Calculate NTLMv2 message authentication code (MAC) key for
+ * this VC and store it in vc_mackey (allocated here).
+ *
+ * The MAC key is the concatenation of the 16 byte session key
+ * and the NT response.
+ *
+ * XXX: Should factor out computation of the session key
+ * from both this and the next function, and then use a
+ * common function to compute the MAC key (which then
+ * can do simple concatenation). Later.
+ */
+int
+smb_calcv2mackey(struct smb_vc *vcp, const uchar_t *v2hash,
+ const uchar_t *ntresp, size_t resplen)
+{
+ uchar_t sesskey[16];
+
+ if (vcp->vc_mackey != NULL) {
+ SMBSDEBUG("Already have MAC key!\n");
+ return (0);
+ }
+
+ /* session key uses only 1st 16 bytes of ntresp */
+ HMACT64(v2hash, 16, ntresp, (size_t)16, sesskey);
+
+ vcp->vc_mackeylen = 16 + resplen;
+ vcp->vc_mackey = kmem_alloc(vcp->vc_mackeylen, KM_SLEEP);
+ /* Free in: smb_vc_free, smb_smb_negotiate */
+
+ bcopy(sesskey, vcp->vc_mackey, 16);
+ bcopy(ntresp, vcp->vc_mackey + 16, (int)resplen);
+
+#ifdef DTRACE_PROBE
+ DTRACE_PROBE2(smb_mac_key, (char *), vcp->vc_mackey,
+ int, vcp->vc_mackeylen);
+#endif
+
+ return (0);
+}
+
+/*
+ * Calculate message authentication code (MAC) key for virtual circuit.
+ * The MAC key is the concatenation of the 16 byte session key
+ * and the 24 byte challenge response.
+ */
+/*ARGSUSED*/
+int
+smb_calcmackey(struct smb_vc *vcp, const uchar_t *v2hash,
+ const uchar_t *ntresp, size_t resplen)
+{
+ MD4_CTX md4;
+
+ if (vcp->vc_mackey != NULL) {
+ SMBSDEBUG("Already have MAC key!\n");
+ return (0);
+ }
+
+ vcp->vc_mackeylen = 16 + 24;
+ vcp->vc_mackey = kmem_alloc(vcp->vc_mackeylen, KM_SLEEP);
+ /* Free in: smb_vc_free, smb_smb_negotiate */
+
+ /*
+ * Calculate session key:
+ */
+ MD4Init(&md4);
+ MD4Update(&md4, vcp->vc_nthash, 16);
+ MD4Final(vcp->vc_mackey, &md4);
+
+ /* Response to challenge. */
+ bcopy(ntresp, vcp->vc_mackey + 16, 24);
+
+#ifdef DTRACE_PROBE
+ DTRACE_PROBE2(smb_mac_key, (char *), vcp->vc_mackey,
+ int, vcp->vc_mackeylen);
+#endif
+
+ return (0);
+}
+
+#define SMBSIGLEN 8 /* SMB signature length */
+#define SMBSIGOFF 14 /* SMB signature offset */
+
+/*
+ * Compute HMAC-MD5 of packet data, using the stored MAC key.
+ *
+ * See similar code for the server side:
+ * uts/common/fs/smbsrv/smb_signing.c : smb_sign_calc
+ */
+static int
+smb_compute_MAC(struct smb_vc *vcp, mblk_t *mp,
+ uint32_t seqno, uchar_t *signature)
+{
+ crypto_context_t crypto_ctx;
+ crypto_data_t key;
+ crypto_data_t data;
+ crypto_data_t digest;
+ uchar_t mac[16];
+ int status;
+ /*
+ * This union is a little bit of trickery to:
+ * (1) get the sequence number int aligned, and
+ * (2) reduce the number of digest calls, at the
+ * cost of a copying 32 bytes instead of 8.
+ * Both sides of this union are 2+32 bytes.
+ */
+ union {
+ struct {
+ uint8_t skip[2]; /* not used - just alignment */
+ uint8_t raw[SMB_HDRLEN]; /* header length (32) */
+ } r;
+ struct {
+ uint8_t skip[2]; /* not used - just alignment */
+ uint8_t hdr[SMBSIGOFF]; /* sig. offset (14) */
+ uint32_t sig[2]; /* MAC signature, aligned! */
+ uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */
+ } s;
+ } smbhdr;
+
+ ASSERT(mp != NULL);
+ ASSERT(MBLKL(mp) >= SMB_HDRLEN);
+ ASSERT(vcp->vc_mackey != NULL);
+
+ /*
+ * Make an aligned copy of the SMB header
+ * and fill in the sequence number.
+ */
+ bcopy(mp->b_rptr, smbhdr.r.raw, SMB_HDRLEN);
+ smbhdr.s.sig[0] = htolel(seqno);
+ smbhdr.s.sig[1] = 0;
+
+ /*
+ * Compute the MAC: MD5(concat(Key, message))
+ */
+ if (crypto_mech_md5.cm_type == CRYPTO_MECH_INVALID) {
+ SMBSDEBUG("crypto_mech_md5 invalid\n");
+ return (CRYPTO_MECHANISM_INVALID);
+ }
+ status = crypto_digest_init(&crypto_mech_md5, &crypto_ctx, 0);
+ if (status != CRYPTO_SUCCESS)
+ return (status);
+
+ /* Digest the MAC Key */
+ key.cd_format = CRYPTO_DATA_RAW;
+ key.cd_offset = 0;
+ key.cd_length = vcp->vc_mackeylen;
+ key.cd_miscdata = 0;
+ key.cd_raw.iov_base = (char *)vcp->vc_mackey;
+ key.cd_raw.iov_len = vcp->vc_mackeylen;
+ status = crypto_digest_update(crypto_ctx, &key, 0);
+ if (status != CRYPTO_SUCCESS)
+ return (status);
+
+ /* Digest the (copied) SMB header */
+ data.cd_format = CRYPTO_DATA_RAW;
+ data.cd_offset = 0;
+ data.cd_length = SMB_HDRLEN;
+ data.cd_miscdata = 0;
+ data.cd_raw.iov_base = (char *)smbhdr.r.raw;
+ data.cd_raw.iov_len = SMB_HDRLEN;
+ status = crypto_digest_update(crypto_ctx, &data, 0);
+ if (status != CRYPTO_SUCCESS)
+ return (status);
+
+ /* Digest rest of the SMB message. */
+ data.cd_format = CRYPTO_DATA_MBLK;
+ data.cd_offset = SMB_HDRLEN;
+ data.cd_length = msgdsize(mp) - SMB_HDRLEN;
+ data.cd_miscdata = 0;
+ data.cd_mp = mp;
+ status = crypto_digest_update(crypto_ctx, &data, 0);
+ if (status != CRYPTO_SUCCESS)
+ return (status);
+
+ /* Final */
+ digest.cd_format = CRYPTO_DATA_RAW;
+ digest.cd_offset = 0;
+ digest.cd_length = sizeof (mac);
+ digest.cd_miscdata = 0;
+ digest.cd_raw.iov_base = (char *)mac;
+ digest.cd_raw.iov_len = sizeof (mac);
+ status = crypto_digest_final(crypto_ctx, &digest, 0);
+ if (status != CRYPTO_SUCCESS)
+ return (status);
+
+ /*
+ * Finally, store the signature.
+ * (first 8 bytes of the mac)
+ */
+ if (signature)
+ bcopy(mac, signature, SMBSIGLEN);
+
+ return (0);
+}
+
+/*
+ * Sign a request with HMAC-MD5.
+ */
+int
+smb_rq_sign(struct smb_rq *rqp)
+{
+ struct smb_vc *vcp = rqp->sr_vc;
+ mblk_t *mp = rqp->sr_rq.mb_top;
+ uint8_t *sigloc;
+ int status;
+
+ /*
+ * Our mblk allocation ensures this,
+ * but just in case...
+ */
+ if (MBLKL(mp) < SMB_HDRLEN) {
+ if (!pullupmsg(mp, SMB_HDRLEN))
+ return (0);
+ }
+ sigloc = mp->b_rptr + SMBSIGOFF;
+
+ if (vcp->vc_mackey == NULL) {
+ /*
+ * Signing is required, but we have no key yet
+ * fill in with the magic fake signing value.
+ * This happens with SPNEGO, NTLMSSP, ...
+ */
+ bcopy("BSRSPLY", sigloc, 8);
+ return (0);
+ }
+
+ /*
+ * This will compute the MAC and store it
+ * directly into the message at sigloc.
+ */
+ status = smb_compute_MAC(vcp, mp, rqp->sr_seqno, sigloc);
+ if (status != CRYPTO_SUCCESS) {
+ SMBSDEBUG("Crypto error %d", status);
+ bzero(sigloc, SMBSIGLEN);
+ return (ENOTSUP);
+ }
return (0);
}
+
+/*
+ * Verify reply signature.
+ */
+int
+smb_rq_verify(struct smb_rq *rqp)
+{
+ struct smb_vc *vcp = rqp->sr_vc;
+ mblk_t *mp = rqp->sr_rp.md_top;
+ uint8_t sigbuf[SMBSIGLEN];
+ uint8_t *sigloc;
+ int status;
+ int fudge;
+
+ /*
+ * Note vc_mackey and vc_mackeylen gets initialized by
+ * smb_smb_ssnsetup.
+ */
+ if (vcp->vc_mackey == NULL) {
+ SMBSDEBUG("no mac key\n");
+ return (0);
+ }
+
+ /*
+ * Let caller deal with empty reply or short messages by
+ * returning zero. Caller will fail later, in parsing.
+ */
+ if (mp == NULL) {
+ SMBSDEBUG("empty reply\n");
+ return (0);
+ }
+ if (MBLKL(mp) < SMB_HDRLEN) {
+ if (!pullupmsg(mp, SMB_HDRLEN))
+ return (0);
+ }
+ sigloc = mp->b_rptr + SMBSIGOFF;
+
+ SMBSDEBUG("sr_rseqno = 0x%x\n", rqp->sr_rseqno);
+
+ status = smb_compute_MAC(vcp, mp, rqp->sr_rseqno, sigbuf);
+ if (status != CRYPTO_SUCCESS) {
+ SMBSDEBUG("Crypto error %d", status);
+ /*
+ * If we can't compute a MAC, then there's
+ * no point trying other seqno values.
+ */
+ return (EBADRPC);
+ }
+
+ /*
+ * Compare the computed signature with the
+ * one found in the message (at sigloc)
+ */
+ if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0)
+ return (0);
+
+ SMBSDEBUG("BAD signature, MID=0x%x\n", rqp->sr_mid);
+
+#ifdef DEBUG
+ /*
+ * For diag purposes, we check whether the client/server idea
+ * of the sequence # has gotten a bit out of sync.
+ */
+ for (fudge = 1; fudge <= nsmb_signing_fudge; fudge++) {
+ smb_compute_MAC(vcp, mp, rqp->sr_rseqno + fudge, sigbuf);
+ if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0)
+ break;
+ smb_compute_MAC(vcp, mp, rqp->sr_rseqno - fudge, sigbuf);
+ if (bcmp(sigbuf, sigloc, SMBSIGLEN) == 0) {
+ fudge = -fudge;
+ break;
+ }
+ }
+ if (fudge <= nsmb_signing_fudge) {
+ SMBSDEBUG("sr_rseqno=%d, but %d would have worked\n",
+ rqp->sr_rseqno, rqp->sr_rseqno + fudge);
+ }
+#endif
+ return (EBADRPC);
+}
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
index 6f2a1f16a3..29795281f4 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
@@ -165,7 +165,7 @@ static struct dev_ops nsmb_ops = {
static struct modldrv nsmb_modldrv = {
&mod_driverops, /* Driver module */
- "SMBFS network driver",
+ "SMBFS network driver v" NSMB_VER_STR,
&nsmb_ops /* Driver ops */
};
@@ -196,6 +196,9 @@ _init(void)
/* Initialize password Key chain DB. */
smb_pkey_init();
+ /* Initialize crypto mechanisms. */
+ smb_crypto_mech_init();
+
zone_key_create(&nsmb_zone_key, NULL, nsmb_zone_shutdown,
nsmb_zone_destroy);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c
index 966bb09d74..b1c9c1d342 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_iod.c
@@ -285,7 +285,7 @@ smb_iod_disconnect(struct smb_vc *vcp)
* Send one request.
*
* Called by _addrq (for internal requests)
- * and by _sendall (via _addrq, _waitrq)
+ * and _sendall (via _addrq, _multirq, _waitrq)
*/
static int
smb_iod_sendrq(struct smb_rq *rqp)
@@ -322,7 +322,6 @@ smb_iod_sendrq(struct smb_rq *rqp)
}
if (rqp->sr_sendcnt == 0) {
-
*rqp->sr_rquid = htoles(vcp->vc_smbuid);
/*
@@ -362,6 +361,14 @@ smb_iod_sendrq(struct smb_rq *rqp)
*rqp->sr_rqtid =
htoles(ssp ? ssp->ss_tid : SMB_TID_UNKNOWN);
mb_fixhdr(&rqp->sr_rq);
+
+ /*
+ * Sign the message now that we're finally done
+ * filling in the SMB header fields, etc.
+ */
+ if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
+ smb_rq_sign(rqp);
+ }
}
if (rqp->sr_sendcnt++ >= 60/SMBSBTIMO) { /* one minute */
smb_iod_rqprocessed(rqp, rqp->sr_lerror, SMBR_RESTART);
@@ -716,6 +723,16 @@ smb_iod_addrq(struct smb_rq *rqp)
* Note lock order: iod_rqlist, vc_sendlock
*/
rw_enter(&vcp->iod_rqlock, RW_WRITER);
+ if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
+ /*
+ * We're signing requests and verifying
+ * signatures on responses. Set the
+ * sequence numbers of the request and
+ * response here, used in smb_rq_verify.
+ */
+ rqp->sr_seqno = vcp->vc_seqno++;
+ rqp->sr_rseqno = vcp->vc_seqno++;
+ }
TAILQ_INSERT_HEAD(&vcp->iod_rqlist, rqp, sr_link);
rw_downgrade(&vcp->iod_rqlock);
@@ -758,6 +775,16 @@ smb_iod_addrq(struct smb_rq *rqp)
rw_enter(&vcp->iod_rqlock, RW_WRITER);
+ if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
+ /*
+ * We're signing requests and verifying
+ * signatures on responses. Set the
+ * sequence numbers of the request and
+ * response here, used in smb_rq_verify.
+ */
+ rqp->sr_seqno = vcp->vc_seqno++;
+ rqp->sr_rseqno = vcp->vc_seqno++;
+ }
TAILQ_INSERT_TAIL(&vcp->iod_rqlist, rqp, sr_link);
/* iod_rqlock/WRITER protects iod_newrq */
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
index a7834f65e4..e73b159e1b 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
@@ -31,13 +31,12 @@
*
* $Id: smb_rq.c,v 1.29 2005/02/11 01:44:17 lindak Exp $
*/
+
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kmem.h>
@@ -48,11 +47,7 @@
#include <sys/cmn_err.h>
#include <sys/sdt.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -139,11 +134,10 @@ smb_rq_new(struct smb_rq *rqp, uchar_t cmd)
mb_put_mem(mbp, SMB_SIGNATURE, SMB_SIGLEN, MB_MSYSTEM);
mb_put_uint8(mbp, cmd);
mb_put_uint32le(mbp, 0);
- mb_put_uint8(mbp, vcp->vc_hflags);
- if (cmd == SMB_COM_TRANSACTION || cmd == SMB_COM_TRANSACTION_SECONDARY)
- mb_put_uint16le(mbp, (vcp->vc_hflags2 & ~SMB_FLAGS2_UNICODE));
- else
- mb_put_uint16le(mbp, vcp->vc_hflags2);
+ rqp->sr_rqflags = vcp->vc_hflags;
+ mb_put_uint8(mbp, rqp->sr_rqflags);
+ rqp->sr_rqflags2 = vcp->vc_hflags2;
+ mb_put_uint16le(mbp, rqp->sr_rqflags2);
mb_put_mem(mbp, tzero, 12, MB_MSYSTEM);
ptr = mb_reserve(mbp, sizeof (u_int16_t));
/*LINTED*/
@@ -449,6 +443,20 @@ smb_rq_reply(struct smb_rq *rqp)
error = smb_iod_waitrq(rqp);
if (error)
return (error);
+
+ /*
+ * If the request was signed, validate the
+ * signature on the response.
+ */
+ if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
+ error = smb_rq_verify(rqp);
+ if (error)
+ return (error);
+ }
+
+ /*
+ * Parse the SMB header
+ */
error = md_get_uint32(mdp, &tdw);
if (error)
return (error);
@@ -603,13 +611,8 @@ smb_t2_done(struct smb_t2rq *t2p)
md_done(&t2p->t2_rdata);
mutex_destroy(&t2p->t2_lock);
cv_destroy(&t2p->t2_cond);
-#ifdef NOTYETRESOLVED
if (t2p->t2_flags & SMBT2_ALLOCED)
kmem_free(t2p, sizeof (*t2p));
-#endif
- if (t2p) {
- kmem_free(t2p, sizeof (*t2p));
- }
}
u_int32_t
@@ -920,7 +923,7 @@ smb_t2_request_int(struct smb_t2rq *t2p)
mblk_t *m;
struct smb_rq *rqp;
int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i;
- int error, doff, poff, txdcount, txpcount, nmlen;
+ int error, doff, poff, txdcount, txpcount, nmlen, nmsize;
m = t2p->t2_tparam.mb_top;
if (m) {
@@ -941,7 +944,7 @@ smb_t2_request_int(struct smb_t2rq *t2p)
leftdcount = totdcount;
leftpcount = totpcount;
txmax = vcp->vc_txmax;
- error = smb_rq_alloc(t2p->t2_source, t2p->t_name[0] ?
+ error = smb_rq_alloc(t2p->t2_source, t2p->t_name ?
SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp);
if (error)
return (error);
@@ -962,12 +965,21 @@ smb_t2_request_int(struct smb_t2rq *t2p)
len = mb_fixhdr(mbp);
/*
- * now we have known packet size as
- * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + strlen(name) + 1),
- * and need to decide which parts should go into the first request
+ * Now we know the size of the trans overhead stuff:
+ * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + nmsize),
+ * where nmsize is the OTW size of the name, including
+ * the unicode null terminator and any alignment.
+ * Use this to decide which parts (and how much)
+ * can go into this request: params, data
*/
- nmlen = t2p->t_name ? strlen(t2p->t_name) : 0;
- len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmlen + 1);
+ nmlen = t2p->t_name ? t2p->t_name_len : 0;
+ nmsize = nmlen + 1; /* null term. */
+ if (SMB_UNICODE_STRINGS(vcp)) {
+ nmsize *= 2;
+ /* we know put_dmem will need to align */
+ nmsize += 1;
+ }
+ len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmsize);
if (len + leftpcount > txmax) {
txpcount = min(leftpcount, txmax - len);
poff = len;
@@ -998,10 +1010,14 @@ smb_t2_request_int(struct smb_t2rq *t2p)
}
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
- /* TDUNICODE */
- if (t2p->t_name)
- mb_put_mem(mbp, t2p->t_name, nmlen, MB_MSYSTEM);
- mb_put_uint8(mbp, 0); /* terminating zero */
+ if (t2p->t_name) {
+ /* Put the string and terminating null. */
+ smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1,
+ SMB_CS_NONE, NULL);
+ } else {
+ /* nmsize accounts for padding, char size. */
+ mb_put_mem(mbp, NULL, nmsize, MB_MZERO);
+ }
len = mb_fixhdr(mbp);
if (txpcount) {
mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.h
index 2e90252405..7359b42049 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.h
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.h
@@ -31,11 +31,15 @@
*
* $Id: smb_rq.h,v 1.9 2005/01/22 22:20:58 lindak Exp $
*/
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
#ifndef _NETSMB_SMB_RQ_H_
#define _NETSMB_SMB_RQ_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <netsmb/mchain.h>
#include <sys/queue.h>
@@ -81,7 +85,9 @@ struct smb_rq {
struct smb_vc *sr_vc;
struct smb_share *sr_share;
struct _kthread *sr_owner;
- ushort_t sr_mid;
+ ushort_t sr_mid;
+ uint32_t sr_seqno; /* Seq. no. of request */
+ uint32_t sr_rseqno; /* Seq. no. of reply */
struct mbchain sr_rq;
uchar_t sr_cmd;
uint8_t sr_rqflags;
@@ -123,7 +129,9 @@ struct smb_t2rq {
uint16_t t2_maxpcount; /* max param bytes to return */
uint16_t t2_maxdcount; /* max data bytes to return */
uint16_t t2_fid; /* for T2 request */
- char t_name[128]; /* for T, should be zero for T2 */
+ char *t_name; /* for T, must be NULL for T2 */
+ int t_name_len; /* t_name string length */
+ int t_name_maxlen; /* t_name allocated size */
int t2_flags; /* SMBT2_ */
struct mbchain t2_tparam; /* parameters to transmit */
struct mbchain t2_tdata; /* data to transmit */
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
index 5f54b7c38f..3412109a68 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
@@ -37,8 +37,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* various SMB requests. Most of the routines merely packs data into mbufs.
*/
@@ -86,10 +84,21 @@ int smb_timo_read = 45;
int smb_timo_write = 60; /* was SMBWRTTIMO */
int smb_timo_append = 90;
+/*
+ * Debug/test feature to disable NTMLv2.
+ * Set this to zero to skip NTLMv2
+ */
+int nsmb_enable_ntlmv2 = 1;
+
static int smb_smb_read(struct smb_share *ssp, u_int16_t fid,
- int *len, int *rresid, uio_t *uiop, struct smb_cred *scred, int timo);
+ uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
static int smb_smb_write(struct smb_share *ssp, u_int16_t fid,
- int *len, int *rresid, uio_t *uiop, struct smb_cred *scred, int timo);
+ uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
+
+static int smb_smb_readx(struct smb_share *ssp, u_int16_t fid,
+ uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
+static int smb_smb_writex(struct smb_share *ssp, u_int16_t fid,
+ uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
struct smb_dialect {
int d_id;
@@ -183,20 +192,45 @@ smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
char *servercs;
void *servercshandle = NULL;
void *localcshandle = NULL;
+ int negotiated_signing = 0;
u_int16_t toklen;
- vcp->vc_hflags = SMB_FLAGS_CASELESS; /* XXX on Unix? */
/*
- * Make sure SMB_FLAGS2_UNICODE is "off" so mb_put_dstring
- * marshalls the dialect strings in plain ascii.
+ * We set various flags below to keep track of
+ * interesting things we learn from negotiation.
+ * Clear all the flags except these two, which
+ * are operational rather than protocol info.
*/
- vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
- vcp->vc_hflags2 |= SMB_FLAGS2_ERR_STATUS;
-
SMB_VC_LOCK(vcp);
- vcp->vc_flags &= ~(SMBV_ENCRYPT);
+ vcp->vc_flags &= (SMBV_GONE | SMBV_RECONNECTING);
SMB_VC_UNLOCK(vcp);
+ /*
+ * Now vc_hflags and vc_hflags2. Careful with this:
+ * Leave SMB_FLAGS2_UNICODE off so mb_put_dstring
+ * marshalls the dialect strings in plain ascii.
+ * We'll turn that on below, if appropriate.
+ *
+ * Note: These flags are marshalled into the request
+ * when we call smb_rq_alloc, so changing them after
+ * this point does not affect THIS request.
+ */
+ vcp->vc_hflags = SMB_FLAGS_CASELESS;
+ vcp->vc_hflags2 = (SMB_FLAGS2_ERR_STATUS |
+ SMB_FLAGS2_KNOWS_LONG_NAMES);
+
+ /* User-level may ask for extended security. */
+ if (vcp->vc_vopt & SMBVOPT_EXT_SEC)
+ vcp->vc_hflags2 |= SMB_FLAGS2_EXT_SEC;
+
+ /* Also clear any old key (for reconnect) */
+ if (vcp->vc_mackey != NULL) {
+ kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
+ vcp->vc_mackey = NULL;
+ vcp->vc_mackeylen = 0;
+ vcp->vc_seqno = 0;
+ }
+
sp = &vcp->vc_sopt;
bzero(sp, sizeof (struct smb_sopt));
error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
@@ -261,10 +295,64 @@ smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
error = md_get_uint16le(mdp, &bc);
if (error)
break;
- if (sp->sv_sm & SMB_SM_SIGS_REQUIRE)
- SMBERROR("server configuration requires "
- "packet signing, which we dont support: "
- "sp->sv_sm %d\n", sp->sv_sm);
+
+ /* BEGIN CSTYLED */
+ /*
+ * Will we do SMB signing? Or block the connection?
+ * The table below describes this logic. References:
+ * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3]
+ * http://msdn.microsoft.com/en-us/library/cc212511.aspx
+ * http://msdn.microsoft.com/en-us/library/cc212929.aspx
+ *
+ * Srv/Cli | Required | Enabled | If Required | Disabled
+ * ------------+----------+------------+-------------+-----------
+ * Required | Signed | Signed | Signed | Blocked [1]
+ * ------------+----------+------------+-------------+-----------
+ * Enabled | Signed | Signed | Not Signed | Not Signed
+ * ------------+----------+------------+-------------+-----------
+ * If Required | Signed | Not Signed | Not Signed | Not Signed
+ * ------------+----------+------------+-------------+-----------
+ * Disabled | Blocked | Not Signed | Not Signed | Not Signed
+ *
+ * [1] Like Windows 2003 and later, we don't really implement
+ * the "Disabled" setting. Instead we implement "If Required",
+ * so we always sign if the server requires signing.
+ */
+ /* END CSTYLED */
+
+ if (sp->sv_sm & SMB_SM_SIGS_REQUIRE) {
+ /*
+ * Server requires signing.
+ */
+ negotiated_signing = 1;
+ } else if (sp->sv_sm & SMB_SM_SIGS) {
+ /*
+ * Server enables signing (client's option).
+ * If enabled locally, do signing.
+ */
+ if (vcp->vc_vopt & SMBVOPT_SIGNING_ENABLED)
+ negotiated_signing = 1;
+ /* else not signing. */
+ } else {
+ /*
+ * Server does not support signing.
+ * If we "require" it, bail now.
+ */
+ if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
+ SMBERROR("Client requires signing "
+ "but server has it disabled.\n");
+ error = EBADRPC;
+ break;
+ }
+ }
+ SMBSDEBUG("Security signatures: %d\n",
+ negotiated_signing);
+ if (negotiated_signing) {
+ SMB_VC_LOCK(vcp);
+ vcp->vc_flags |= SMBV_WILL_SIGN;
+ SMB_VC_UNLOCK(vcp);
+ }
+
if (sp->sv_caps & SMB_CAP_UNICODE) {
SMB_VC_LOCK(vcp);
vcp->vc_flags |= SMBV_UNICODE;
@@ -484,9 +572,7 @@ smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
* Max read/write sizes, WITHOUT overhead.
* This is just the payload size, so we must
* leave room for the SMB headers, etc.
- *
- * With CAP_LARGE_xxx, always use 60k.
- * Otherwise use the vc_txmax value, but
+ * This is just the vc_txmax value, but
* reduced and rounded down. Tricky bit:
*
* Servers typically give us a value that's
@@ -497,14 +583,8 @@ smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
* then round down to a 512 byte multiple.
*/
x = (vcp->vc_txmax - 68) & 0xFE00;
- if (sp->sv_caps & SMB_CAP_LARGE_READX)
- vcp->vc_rxmax = SMB_MAX_LARGE_RW_SIZE;
- else
- vcp->vc_rxmax = x;
- if (sp->sv_caps & SMB_CAP_LARGE_WRITEX)
- vcp->vc_wxmax = SMB_MAX_LARGE_RW_SIZE;
- else
- vcp->vc_wxmax = x;
+ vcp->vc_rxmax = x;
+ vcp->vc_wxmax = x;
SMBSDEBUG("TZ = %d\n", sp->sv_tz);
SMBSDEBUG("CAPS = %x\n", sp->sv_caps);
@@ -615,7 +695,8 @@ add_name_to_blob(uchar_t *blobnames, struct smb_vc *vcp, const uchar_t *name,
}
static uchar_t *
-make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, size_t *bloblen)
+make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce,
+ size_t *bloblen, size_t *blob_allocsz)
{
uchar_t *blob;
size_t blobsize;
@@ -646,11 +727,9 @@ make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, size_t *bloblen)
srvlen = strlen(vcp->vc_srvname);
blobsize = sizeof (struct ntlmv2_blobhdr)
+ 3*sizeof (struct ntlmv2_namehdr) + 4 + 2*domainlen + 2*srvlen;
- blob = kmem_zalloc(blobsize, KM_SLEEP);
- /*LINTED*/
- ASSERT(blob == (uchar_t *)((struct ntlmv2_blobhdr *)blob));
- /*LINTED*/
- blobhdr = (struct ntlmv2_blobhdr *)blob;
+ *blob_allocsz = blobsize;
+ blobhdr = kmem_zalloc(blobsize, KM_SLEEP);
+ blob = (uchar_t *)blobhdr;
blobhdr->header = htolel(0x00000101);
gethrestime(&now);
smb_time_local2NT(&now, 0, &timestamp);
@@ -669,20 +748,10 @@ make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, size_t *bloblen)
}
/*
- * See radar 4134676. This define helps us avoid how a certain old server
- * grants limited Guest access when we try NTLMv2, but works fine with NTLM.
- * The fingerprint we are looking for here is DOS error codes and no-Unicode.
- * Note XP grants Guest access but uses Unicode and NT error codes.
- */
-#define smb_antique(rqp) (!((rqp)->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) && \
- !((rqp)->sr_rpflags2 & SMB_FLAGS2_UNICODE))
-
-/*
* When not doing Kerberos, we can try, in order:
*
* NTLMv2
- * NTLM with the ASCII password not upper-cased
- * NTLM with the ASCII password upper-cased
+ * NTLM (and maybe LM)
*
* if the server supports encrypted passwords, or
*
@@ -691,9 +760,14 @@ make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, size_t *bloblen)
*
* if it doesn't.
*/
-#define STATE_NTLMV2 0
-#define STATE_NOUCPW 1
-#define STATE_UCPW 2
+typedef enum {
+ ClearUC, /* Cleartext p/w, upper case */
+ ClearMC, /* Cleartext p/w, mixed case */
+ NTLMv1,
+ NTLMv2,
+ ExtSec, /* Extended Security (Kerberos) */
+ NullSes /* Null session (keep last) */
+} authtype_t;
int
smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
@@ -704,22 +778,24 @@ smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
u_int8_t wc;
int minauth;
smb_uniptr unipp = NULL, ntencpass = NULL;
- char *pp = NULL, *up = NULL, *ucup = NULL, *ucdp = NULL;
- char *pbuf = NULL;
+ char *pp = NULL, *up = NULL, *ucup = NULL;
+ char *ucdp = vcp->vc_domain; /* already upper case */
char *encpass = NULL;
int error = 0;
- size_t plen = 0, uniplen = 0, uniplen2 = 0, tmplen;
- size_t ucup_sl = 0, ucdp_sl = 0;
- int state;
- size_t ntlmv2_bloblen;
+ size_t plen = 0, plen_alloc = 0;
+ size_t uniplen = 0, uniplen_alloc = 0;
+ size_t ucup_sl = 0;
+ authtype_t authtype;
+ size_t ntlmv2_bloblen, ntlmv2_blob_allocsz;
uchar_t *ntlmv2_blob;
u_int64_t client_nonce;
u_int32_t caps;
u_int16_t bl; /* BLOB length */
- u_int16_t saveflags2 = vcp->vc_hflags2;
- void * savetoserver = vcp->vc_toserver;
+ u_int16_t bc; /* byte count */
u_int16_t action;
+ u_int16_t rpflags2;
int declinedguest = 0;
+ uchar_t v2hash[16];
static const char NativeOS[] = "Solaris";
static const char LanMan[] = "NETSMB";
/*
@@ -732,244 +808,304 @@ smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
SMB_CAP_UNICODE |
SMB_CAP_LARGE_FILES |
SMB_CAP_NT_SMBS |
- SMB_CAP_STATUS32 |
- SMB_CAP_LARGE_READX |
- SMB_CAP_LARGE_WRITEX;
+ SMB_CAP_STATUS32;
caps = vcp->vc_sopt.sv_caps & caps_mask;
-
- /* No unicode unless server supports and encryption on */
- if (!((vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) &&
- (vcp->vc_flags & SMBV_UNICODE))) {
- vcp->vc_hflags2 &= 0xffff - SMB_FLAGS2_UNICODE;
- vcp->vc_toserver = 0;
- }
-
minauth = vcp->vc_vopt & SMBVOPT_MINAUTH;
- if (vcp->vc_intok) {
- if (vcp->vc_intoklen > 65536 ||
- !(vcp->vc_hflags2 & SMB_FLAGS2_EXT_SEC) ||
- SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) {
- error = EINVAL;
- goto ssn_exit;
+
+ /*
+ * This function tries authentication types in a
+ * sequence going stronger to weaker, until it
+ * succeeds or runs into "minauth" and fails.
+ *
+ * Extended security is a special case because
+ * fall-back requires a return to user-level and
+ * a new connection, new SMB negotiate, etc.
+ * Null session is also special - no fall-back.
+ *
+ * Otherwise if the server supports encryption,
+ * try NTLMv2, then NTLM, etc.
+ */
+ if (vcp->vc_intok)
+ authtype = ExtSec;
+ else if (vcp->vc_username[0] == '\0')
+ authtype = NullSes;
+ else if ((vcp->vc_sopt.sv_sm & SMB_SM_USER) == 0) {
+ /* Share-level security. */
+ authtype = NullSes;
+ } else {
+ /* Have SMB_SM_USER. Encryption? */
+ if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
+ if (nsmb_enable_ntlmv2)
+ authtype = NTLMv2;
+ else
+ authtype = NTLMv1;
+ } else {
+ /*
+ * This is normally disallowed
+ * by the minauth check below.
+ */
+ authtype = ClearMC;
}
- vcp->vc_smbuid = 0;
}
/*
- * Try only plain text passwords.
+ * If server does not support encryption,
+ * disable unicode too. (Spec. for this?)
*/
- if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
- state = STATE_NTLMV2; /* try NTLMv2 first */
- } else {
- state = STATE_NOUCPW; /* try plain-text mixed-case first */
+ if ((vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) == 0) {
+ if (vcp->vc_flags & SMBV_UNICODE) {
+ vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
+ vcp->vc_toserver = 0;
+ }
}
+
again:
+ SMBSDEBUG("authtype = %d\n", authtype);
- if (!vcp->vc_intok)
- vcp->vc_smbuid = SMB_UID_UNKNOWN;
+ /*
+ * Now disallow auth. types that fall below
+ * the minimum strength configured.
+ * We hold no kmem here.
+ */
+ switch (minauth) {
- if (!vcp->vc_intok) {
- /*
- * We're not doing extended security, which, for
- * now, means we're not doing Kerberos.
- * Fail if the minimum authentication level is
- * Kerberos.
- */
- if (minauth >= SMBVOPT_MINAUTH_KERBEROS) {
+ case SMBVOPT_MINAUTH_NONE:
+ break;
+
+ case SMBVOPT_MINAUTH_LM:
+ case SMBVOPT_MINAUTH_NTLM:
+ if (authtype < NTLMv1) {
error = EAUTH;
goto ssn_exit;
}
- if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
- /*
- * Server wants encrypted passwords.
- */
- if (state > STATE_NTLMV2) {
- /*
- * We tried NTLMv2 in STATE_NTLMV2.
- * Shall we allow fallback? (to NTLM)
- */
- if (minauth >= SMBVOPT_MINAUTH_NTLMV2) {
- error = EAUTH;
- goto ssn_exit;
- }
- }
- if (state > STATE_NOUCPW) {
- /*
- * We tried NTLM in STATE_NOUCPW.
- * No need to try it again.
- */
- error = EAUTH;
- goto ssn_exit;
- }
- } else {
- /*
- * Plain-text passwords.
- * Fail if the minimum authentication level is
- * LM or better.
- */
- if (minauth > SMBVOPT_MINAUTH_NTLM) {
- error = EAUTH;
- goto ssn_exit;
- }
+ break;
+
+ case SMBVOPT_MINAUTH_NTLMV2:
+ if (authtype < NTLMv2) {
+ error = EAUTH;
+ goto ssn_exit;
}
- }
+ break;
- error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
- scred, &rqp);
- if (error)
+ case SMBVOPT_MINAUTH_KERBEROS:
+ if (authtype < ExtSec) {
+ error = EAUTH;
+ goto ssn_exit;
+ }
+ break;
+
+ default:
+ SMBSDEBUG("bad minauth 0x%x\n", minauth);
+ error = EAUTH;
goto ssn_exit;
+ }
/*
- * Domain name must be upper-case, as that's what's used
- * when computing LMv2 and NTLMv2 responses - and, for NTLMv2,
- * the domain name in the request has to be upper-cased as well.
- * (That appears not to be the case for the user name. Go
- * figure.)
- *
- * don't need to uppercase domain string. It's already uppercase UTF-8.
+ * See comment in smb_iod_sendrq()
+ * about vc_smbuid initialization.
*/
+ vcp->vc_smbuid = SMB_UID_UNKNOWN;
- ucdp_sl = strlen(vcp->vc_domain);
- ucdp = kmem_zalloc(ucdp_sl + 1, KM_SLEEP);
- memcpy(ucdp, vcp->vc_domain, ucdp_sl + 1);
+ /*
+ * Within this switch, we may allocate either or both:
+ * encpass, ntencpass (len: plen_alloc, uniplen_alloc)
+ * and will free these below (see the label "bad")
+ */
+ switch (authtype) {
- if (vcp->vc_intok) {
- caps |= SMB_CAP_EXT_SECURITY;
- } else if (!(vcp->vc_sopt.sv_sm & SMB_SM_USER)) {
+ case ExtSec:
/*
- * In the share security mode password will be used
- * only in the tree authentication
+ * With extended security, the whole blob is
+ * passed in from user-level (vc_intok)
*/
+ ASSERT(vcp->vc_intok != NULL);
+ caps |= SMB_CAP_EXT_SECURITY;
+ /* XXX Need Session Key */
+ if (vcp->vc_intoklen > 65536 ||
+ !(vcp->vc_hflags2 & SMB_FLAGS2_EXT_SEC) ||
+ SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) {
+ /* We hold no kmem here. */
+ error = EINVAL;
+ goto ssn_exit;
+ }
+ vcp->vc_smbuid = 0;
+ break;
+
+ case NullSes:
pp = "";
plen = 1;
unipp = &smb_unieol;
uniplen = sizeof (smb_unieol);
- } else {
- pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP);
- if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) {
- if (state == STATE_NTLMV2) {
- /*
- * Compute the LMv2 and NTLMv2 responses,
- * derived from the challenge, the user name,
- * the domain/workgroup into which we're
- * logging, and the Unicode password.
- */
+ break;
- /*
- * Construct the client nonce by getting
- * a bunch of random data.
- */
- (void) random_get_pseudo_bytes((void *)
- &client_nonce, sizeof (client_nonce));
+ case NTLMv2:
+ /*
+ * Compute the LMv2 and NTLMv2 responses,
+ * derived from the challenge, the user name,
+ * the domain/workgroup into which we're
+ * logging, and the Unicode password.
+ */
- /*
- * Convert the user name to upper-case, as
- * that's what's used when computing LMv2
- * and NTLMv2 responses.
- */
- ucup_sl = strlen(vcp->vc_username);
- ucup = kmem_alloc(ucup_sl + 1, KM_SLEEP);
- smb_toupper((const char *)vcp->vc_username,
- ucup, ucup_sl);
- ucup[ucup_sl] = '\0';
+ /*
+ * Construct the client nonce by getting
+ * a bunch of random data.
+ */
+ (void) random_get_pseudo_bytes((void *)
+ &client_nonce, sizeof (client_nonce));
- /*
- * Compute the LMv2 response, derived
- * from the server challenge, the
- * user name, the domain/workgroup
- * into which we're logging, the
- * client nonce, and the NT hash.
- */
- smb_ntlmv2response(vcp->vc_nthash,
- (uchar_t *)ucup, (uchar_t *)ucdp,
- vcp->vc_challenge,
- (uchar_t *)&client_nonce, 8,
- (uchar_t **)&encpass, &plen);
- pp = encpass;
+ /*
+ * Convert the user name to upper-case, as
+ * that's what's used when computing LMv2
+ * and NTLMv2 responses.
+ */
+ ucup_sl = strlen(vcp->vc_username);
+ ucup = kmem_alloc(ucup_sl + 1, KM_SLEEP);
+ smb_toupper((const char *)vcp->vc_username,
+ ucup, ucup_sl);
+ ucup[ucup_sl] = '\0';
- /*
- * Construct the blob.
- */
- ntlmv2_blob = make_ntlmv2_blob(vcp,
- client_nonce, &ntlmv2_bloblen);
+ /*
+ * Compute the NTLMv2 hash, which is
+ * derived from the NTLMv1 hash and
+ * the upper-case user + domain.
+ */
+ smb_ntlmv2hash(vcp->vc_nthash,
+ ucup, ucdp, v2hash);
- /*
- * Compute the NTLMv2 response, derived
- * from the server challenge, the
- * user name, the domain/workgroup
- * into which we're logging, the
- * blob, and the NT hash.
- */
- smb_ntlmv2response(vcp->vc_nthash,
- (uchar_t *)ucup, (uchar_t *)ucdp,
- vcp->vc_challenge,
- ntlmv2_blob, ntlmv2_bloblen,
- (uchar_t **)&ntencpass, &uniplen);
- uniplen2 = uniplen;
- unipp = ntencpass;
- tmplen = plen;
-
- kmem_free(ucup, ucup_sl + 1);
- kmem_free((char *)ntlmv2_blob,
- sizeof (struct ntlmv2_blobhdr) +
- 3 * sizeof (struct ntlmv2_namehdr) +
- 4 +
- 2 * strlen(vcp->vc_domain) +
- 2 * strlen(vcp->vc_srvname));
- } else {
- plen = 24;
- encpass = kmem_zalloc(plen, KM_SLEEP);
- /*
- * Compute the LM response, derived
- * from the challenge and the ASCII
- * password.
- */
- if (minauth < SMBVOPT_MINAUTH_NTLM) {
- smb_lmresponse(vcp->vc_lmhash,
- vcp->vc_challenge,
- (uchar_t *)encpass);
- }
- pp = encpass;
+ /*
+ * Compute the LMv2 response, derived from
+ * the v2hash, the server challenge, and
+ * the client nonce (random bits).
+ * Note: kmem_alloc encpass (plen)
+ */
+ smb_ntlmv2response(v2hash,
+ vcp->vc_challenge,
+ (uchar_t *)&client_nonce, 8,
+ (uchar_t **)&encpass, &plen);
+ plen_alloc = plen;
+ pp = encpass;
- /*
- * Compute the NTLM response, derived from
- * the challenge and the NT hash.
- */
- uniplen = 24;
- uniplen2 = uniplen;
- ntencpass = kmem_alloc(uniplen, KM_SLEEP);
- smb_lmresponse(vcp->vc_nthash,
- vcp->vc_challenge,
- (uchar_t *)ntencpass);
- unipp = ntencpass;
- }
- } else {
- /*
- * We try w/o uppercasing first so Samba mixed case
- * passwords work. If that fails, we come back and
- * try uppercasing to satisfy OS/2 and Windows for
- * Workgroups.
- */
- get_ascii_password(vcp, (state == STATE_UCPW), pbuf);
- plen = strlen(pbuf) + 1;
- pp = pbuf;
- uniplen = plen * 2;
- uniplen2 = uniplen;
- ntencpass = kmem_alloc(uniplen, KM_SLEEP);
- (void) smb_strtouni(ntencpass, smb_vc_getpass(vcp),
- 0, 0);
- plen--;
- /*
- * The uniplen is zeroed because Samba cannot deal
- * with this 2nd cleartext password. This Samba
- * "bug" is actually a workaround for problems in
- * Microsoft clients.
- */
- uniplen = 0; /* -= 2 */
- unipp = ntencpass;
+ /*
+ * Construct the blob.
+ * Note: kmem_alloc ntlmv2_blob
+ */
+ ntlmv2_blob = make_ntlmv2_blob(vcp,
+ client_nonce, &ntlmv2_bloblen,
+ &ntlmv2_blob_allocsz);
+
+ /*
+ * Compute the NTLMv2 response, derived
+ * from the server challenge, the
+ * user name, the domain/workgroup
+ * into which we're logging, the
+ * blob, and the v2 hash.
+ * Note: kmem_alloc ntencpass (uniplen)
+ */
+ smb_ntlmv2response(v2hash,
+ vcp->vc_challenge,
+ ntlmv2_blob, ntlmv2_bloblen,
+ (uchar_t **)&ntencpass, &uniplen);
+ uniplen_alloc = uniplen;
+ unipp = ntencpass;
+
+ /*
+ * If we negotiated signing, compute the MAC key
+ * and start signing messages, but only on the
+ * first non-null session login.
+ */
+ if ((vcp->vc_flags & SMBV_WILL_SIGN) &&
+ !(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) {
+ vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
+ smb_calcv2mackey(vcp, v2hash,
+ (uchar_t *)ntencpass, uniplen);
}
- }
+ kmem_free(ucup, ucup_sl + 1);
+ kmem_free(ntlmv2_blob, ntlmv2_blob_allocsz);
+ break;
+
+ case NTLMv1:
+ /*
+ * Compute the LM response, derived
+ * from the challenge and the ASCII
+ * password. (If minauth allows it.)
+ */
+ plen_alloc = plen = 24;
+ encpass = kmem_zalloc(plen, KM_SLEEP);
+ if (minauth < SMBVOPT_MINAUTH_NTLM) {
+ smb_lmresponse(vcp->vc_lmhash,
+ vcp->vc_challenge,
+ (uchar_t *)encpass);
+ }
+ pp = encpass;
+
+ /*
+ * Compute the NTLM response, derived from
+ * the challenge and the NT hash.
+ */
+ uniplen_alloc = uniplen = 24;
+ ntencpass = kmem_alloc(uniplen, KM_SLEEP);
+ smb_lmresponse(vcp->vc_nthash,
+ vcp->vc_challenge,
+ (uchar_t *)ntencpass);
+ unipp = ntencpass;
+
+ /*
+ * If we negotiated signing, compute the MAC key
+ * and start signing messages, but only on the
+ * first non-null session login.
+ */
+ if ((vcp->vc_flags & SMBV_WILL_SIGN) &&
+ !(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) {
+ vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
+ smb_calcmackey(vcp, vcp->vc_nthash,
+ (uchar_t *)ntencpass, uniplen);
+ }
+ break;
+
+ case ClearMC:
+ case ClearUC:
+ /*
+ * We try w/o uppercasing first so Samba mixed case
+ * passwords work. If that fails, we come back and
+ * try uppercasing to satisfy OS/2 and Windows for
+ * Workgroups.
+ */
+ plen_alloc = plen = SMB_MAXPASSWORDLEN + 1;
+ encpass = kmem_zalloc(plen, KM_SLEEP);
+ get_ascii_password(vcp, (authtype == ClearUC), encpass);
+ plen = strlen(encpass) + 1;
+ pp = encpass;
+ uniplen_alloc = uniplen = plen * 2;
+ ntencpass = kmem_alloc(uniplen, KM_SLEEP);
+ (void) smb_strtouni(ntencpass, smb_vc_getpass(vcp), 0, 0);
+ plen--;
+ /*
+ * The uniplen is zeroed because Samba cannot deal
+ * with this 2nd cleartext password. This Samba
+ * "bug" is actually a workaround for problems in
+ * Microsoft clients.
+ */
+ uniplen = 0; /* -= 2 */
+ unipp = ntencpass;
+ break;
+
+ default:
+ ASSERT(0);
+ error = EAUTH;
+ goto ssn_exit;
+
+ } /* switch authtype */
+
+
+ error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
+ scred, &rqp);
+ if (error)
+ goto bad;
+
+ /*
+ * Build the request.
+ */
smb_rq_wstart(rqp);
mbp = &rqp->sr_rq;
up = vcp->vc_username;
@@ -1020,18 +1156,6 @@ again:
smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE); /* OS */
smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE); /* LAN Mgr */
smb_rq_bend(rqp);
- if (ntencpass) {
- kmem_free(ntencpass, uniplen2);
- ntencpass = NULL;
- }
- if (encpass) {
- kmem_free(encpass, 24);
- encpass = NULL;
- }
- if (ucdp) {
- kmem_free(ucdp, ucdp_sl + 1);
- ucdp = NULL;
- }
/*
* This request should not wait for
@@ -1041,84 +1165,158 @@ again:
error = smb_rq_simple_timed(rqp, SMBSSNSETUPTIMO);
SMBSDEBUG("%d\n", error);
if (error) {
- if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnoaccess)
+ if (rqp->sr_errclass == ERRDOS &&
+ rqp->sr_serror == ERRnoaccess)
error = EAUTH;
if (!(rqp->sr_errclass == ERRDOS &&
rqp->sr_serror == ERRmoredata))
goto bad;
}
+
+ /*
+ * Parse the reply
+ */
+ rpflags2 = rqp->sr_rpflags2;
vcp->vc_smbuid = rqp->sr_rpuid;
smb_rq_getreply(rqp, &mdp);
- do {
- error = md_get_uint8(mdp, &wc);
+ error = md_get_uint8(mdp, &wc);
+ if (error)
+ goto bad;
+ error = EBADRPC;
+ if (vcp->vc_intok) {
+ if (wc != 4)
+ goto bad;
+ } else if (wc != 3)
+ goto bad;
+ md_get_uint8(mdp, NULL); /* secondary cmd */
+ md_get_uint8(mdp, NULL); /* mbz */
+ md_get_uint16le(mdp, NULL); /* andxoffset */
+ md_get_uint16le(mdp, &action); /* action */
+ if (vcp->vc_intok)
+ md_get_uint16le(mdp, &bl); /* ext security */
+ md_get_uint16le(mdp, &bc); /* byte count */
+ if (vcp->vc_intok) {
+ vcp->vc_outtoklen = bl;
+ vcp->vc_outtok = kmem_alloc(bl, KM_SLEEP);
+ error = md_get_mem(mdp, vcp->vc_outtok, bl, MB_MSYSTEM);
if (error)
- break;
- error = EBADRPC;
- if (vcp->vc_intok) {
- if (wc != 4)
- break;
- } else if (wc != 3)
- break;
- md_get_uint8(mdp, NULL); /* secondary cmd */
- md_get_uint8(mdp, NULL); /* mbz */
- md_get_uint16le(mdp, NULL); /* andxoffset */
- md_get_uint16le(mdp, &action); /* action */
- if (vcp->vc_intok)
- md_get_uint16le(mdp, &bl); /* ext security */
- md_get_uint16le(mdp, NULL); /* byte count */
- if (vcp->vc_intok) {
- vcp->vc_outtoklen = bl;
- vcp->vc_outtok = kmem_alloc(bl, KM_SLEEP);
- error = md_get_mem(mdp, vcp->vc_outtok, bl, MB_MSYSTEM);
- if (error)
- break;
+ goto bad;
+ }
+
+ /*
+ * Server OS, LANMGR, & Domain follow here.
+ * XXX: Should store these strings (later).
+ *
+ * Windows systems do not suport CAP_LARGE_...
+ * when signing is enabled, so adjust sv_caps.
+ * Match first 8 characters of server's OS
+ * with the UCS-2LE string: "Windows "
+ */
+ if (bc > 16) {
+ static const char WindowsU[16] =
+ "W\0i\0n\0d\0o\0w\0s\0 ";
+ char osbuf[16];
+
+ /* align(2) */
+ if (((uintptr_t)mdp->md_pos) & 1)
+ md_get_uint8(mdp, NULL);
+
+ bzero(osbuf, sizeof (osbuf));
+ md_get_mem(mdp, osbuf, sizeof (osbuf), MB_MSYSTEM);
+ if (0 == bcmp(WindowsU, osbuf, sizeof (osbuf))) {
+ SMBSDEBUG("Server is Windows\n");
+ if (vcp->vc_flags & SMBV_WILL_SIGN) {
+ SMBSDEBUG("disable CAP_LARGE_(r/w)\n");
+ vcp->vc_sopt.sv_caps &=
+ ~(SMB_CAP_LARGE_READX
+ | SMB_CAP_LARGE_WRITEX);
+ }
}
- /* server OS, LANMGR, & Domain here */
- error = 0;
- /*LINTED*/
- } while (0);
+ }
+
+ /* success! */
+ error = 0;
+
bad:
+
+ /*
+ * When authentication fails and we're (possibly) doing
+ * fall-back to another method, we have to reset things.
+ */
+ if (error && vcp->vc_mackey) {
+ vcp->vc_hflags2 &= ~SMB_FLAGS2_SECURITY_SIGNATURE;
+ kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
+ vcp->vc_mackey = NULL;
+ vcp->vc_mackeylen = 0;
+ vcp->vc_seqno = 0;
+ }
+
+ if (rqp) {
+ smb_rq_done(rqp);
+ rqp = NULL;
+ }
if (encpass) {
- kmem_free(encpass, tmplen);
+ kmem_free(encpass, plen_alloc);
encpass = NULL;
}
- if (pbuf) {
- kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1);
- pbuf = NULL;
+ if (ntencpass) {
+ kmem_free(ntencpass, uniplen_alloc);
+ ntencpass = NULL;
}
- if (vcp->vc_sopt.sv_sm & SMB_SM_USER && !vcp->vc_intok &&
- (error || (*up != '\0' && action & SMB_ACT_GUEST &&
- state == STATE_NTLMV2 && smb_antique(rqp)))) {
+
+ /*
+ * Shall we try again with another auth type?
+ * Note: We hold no kmem here.
+ */
+ switch (authtype) {
+
+ case NullSes:
+ case ExtSec:
+ /* Error or not, we're done. (no fallback) */
+ break;
+
+ case NTLMv2:
/*
* We're doing user-level authentication (so we are actually
* sending authentication stuff over the wire), and we're
* not doing extended security, and the stuff we tried
* failed (or we we're trying to login a real user but
* got granted guest access instead.)
+ *
+ * See radar 4134676. This check works around the way a
+ * certain old server grants limited Guest access when we
+ * try NTLMv2, but works fine with NTLM. The fingerprint
+ * we are looking for is DOS error codes and no-Unicode.
+ * Note XP grants Guest access but uses Unicode and
+ * NT error codes.
*/
- if (!error)
+ if (error == 0 && (action & SMB_ACT_GUEST) &&
+ !(rpflags2 & SMB_FLAGS2_ERR_STATUS) &&
+ !(rpflags2 & SMB_FLAGS2_UNICODE)) {
+ /* force fallback */
declinedguest = 1;
- /*
- * Should we try the next type of authentication?
- */
- if (state < STATE_UCPW) {
- /*
- * Yes, we still have more to try.
- */
- state++;
- smb_rq_done(rqp);
+ error = EAUTH;
+ }
+ /* FALLTHROUGH */
+ case NTLMv1:
+ case ClearMC:
+ if (error) {
+ authtype = authtype - 1;
goto again;
}
+ break;
+
+ case ClearUC:
+ default:
+ /* no more fallbacks */
+ break;
}
- smb_rq_done(rqp);
ssn_exit:
if (error && declinedguest)
SMBERROR("we declined ntlmv2 guest access. errno will be %d\n",
error);
- /* Restore things we changed and return */
- vcp->vc_hflags2 = saveflags2;
- vcp->vc_toserver = savetoserver;
+
return (error);
}
@@ -1370,30 +1568,117 @@ smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
return (error);
}
-static int
-smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
- uio_t *uiop, struct smb_cred *scred, int timo)
+/*
+ * Common function for read/write with UIO.
+ * Called by netsmb smb_usr_rw,
+ * smbfs_readvnode, smbfs_writevnode
+ */
+int
+smb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw,
+ uio_t *uiop, smb_cred_t *scred, int timo)
{
struct smb_vc *vcp = SSTOVC(ssp);
+ ssize_t save_resid;
+ uint32_t len, rlen, maxlen;
+ int error = 0;
+ int (*iofun)(struct smb_share *, uint16_t, uint32_t *,
+ uio_t *, smb_cred_t *, int);
+
+ /*
+ * Determine which function to use,
+ * and the transfer size per call.
+ */
+ if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) {
+ /*
+ * Using NT LM 0.12, so readx, writex.
+ * Make sure we can represent the offset.
+ */
+ if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 &&
+ (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
+ return (EFBIG);
+
+ if (rw == UIO_READ) {
+ iofun = smb_smb_readx;
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
+ maxlen = SMB_MAX_LARGE_RW_SIZE;
+ else
+ maxlen = vcp->vc_rxmax;
+ } else { /* UIO_WRITE */
+ iofun = smb_smb_writex;
+ if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
+ maxlen = SMB_MAX_LARGE_RW_SIZE;
+ else
+ maxlen = vcp->vc_wxmax;
+ }
+ } else {
+ /*
+ * Using the old SMB_READ and SMB_WRITE so
+ * we're limited to 32-bit offsets, etc.
+ * XXX: Someday, punt the old dialects.
+ */
+ if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
+ return (EFBIG);
+
+ if (rw == UIO_READ) {
+ iofun = smb_smb_read;
+ maxlen = vcp->vc_rxmax;
+ } else { /* UIO_WRITE */
+ iofun = smb_smb_write;
+ maxlen = vcp->vc_wxmax;
+ }
+ }
+
+ save_resid = uiop->uio_resid;
+ while (uiop->uio_resid > 0) {
+ /* Lint: uio_resid may be 64-bits */
+ rlen = len = (uint32_t)min(maxlen, uiop->uio_resid);
+
+ SMBSDEBUG("rw=%d, off %lld, len %d\n",
+ rw, uiop->uio_loffset, len);
+
+ error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo);
+
+ /*
+ * Note: the iofun called uio_update, so
+ * not doing that here as one might expect.
+ *
+ * Quit the loop either on error, or if we
+ * transferred less then requested.
+ */
+ if (error || (rlen < len))
+ break;
+
+ timo = 0; /* only first I/O should wait */
+ }
+ if (error && (save_resid != uiop->uio_resid)) {
+ /*
+ * Stopped on an error after having
+ * successfully transferred data.
+ * Suppress this error.
+ */
+ SMBSDEBUG("error %d suppressed\n", error);
+ error = 0;
+ }
+
+ return (error);
+}
+
+static int
+smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
+ uio_t *uiop, smb_cred_t *scred, int timo)
+{
struct smb_rq *rqp;
struct mbchain *mbp;
struct mdchain *mdp;
- u_int8_t wc;
int error;
- u_int16_t residhi, residlo, off, doff;
- u_int32_t resid;
+ uint32_t offlo, offhi, rlen;
+ uint16_t lenhi, lenlo, off, doff;
+ uint8_t wc;
- if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) == 0) {
- /* Fall back to the old cmd. */
- return (smb_smb_read(ssp, fid, len, rresid, uiop,
- scred, timo));
- }
- if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0) {
- /* Have ReadX but not large files? */
- if ((uiop->uio_loffset + *len) > UINT32_MAX)
- return (EFBIG);
- }
- *len = min(*len, vcp->vc_rxmax);
+ lenhi = (uint16_t)(*lenp >> 16);
+ lenlo = (uint16_t)*lenp;
+ offhi = (uint32_t)(uiop->uio_loffset >> 32);
+ offlo = (uint32_t)uiop->uio_loffset;
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
if (error)
@@ -1404,13 +1689,13 @@ smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
mb_put_uint8(mbp, 0); /* MBZ */
mb_put_uint16le(mbp, 0); /* offset to secondary */
mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
- mb_put_uint32le(mbp, (u_int32_t)(uiop->uio_offset));
- mb_put_uint16le(mbp, (u_int16_t)*len); /* MaxCount */
- mb_put_uint16le(mbp, (u_int16_t)*len); /* MinCount */
- /* (only indicates blocking) */
- mb_put_uint32le(mbp, (unsigned)*len >> 16); /* MaxCountHigh */
- mb_put_uint16le(mbp, (u_int16_t)*len); /* Remaining ("obsolete") */
- mb_put_uint32le(mbp, (u_int32_t)((uiop->uio_loffset) >> 32));
+ mb_put_uint32le(mbp, offlo); /* offset (low part) */
+ mb_put_uint16le(mbp, lenlo); /* MaxCount */
+ mb_put_uint16le(mbp, 1); /* MinCount */
+ /* (only indicates blocking) */
+ mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */
+ mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */
+ mb_put_uint32le(mbp, offhi); /* offset (high part) */
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
@@ -1421,46 +1706,44 @@ smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
if (error)
break;
smb_rq_getreply(rqp, &mdp);
- off = SMB_HDRLEN;
md_get_uint8(mdp, &wc);
- off++;
if (wc != 12) {
error = EBADRPC;
break;
}
md_get_uint8(mdp, NULL);
- off++;
md_get_uint8(mdp, NULL);
- off++;
md_get_uint16le(mdp, NULL);
- off += 2;
md_get_uint16le(mdp, NULL);
- off += 2;
md_get_uint16le(mdp, NULL); /* data compaction mode */
- off += 2;
md_get_uint16le(mdp, NULL);
- off += 2;
- md_get_uint16le(mdp, &residlo);
- off += 2;
+ md_get_uint16le(mdp, &lenlo); /* data len ret. */
md_get_uint16le(mdp, &doff); /* data offset */
- off += 2;
- md_get_uint16le(mdp, &residhi);
- off += 2;
- resid = (residhi << 16) | residlo;
+ md_get_uint16le(mdp, &lenhi);
+ rlen = (lenhi << 16) | lenlo;
md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
- off += 4*2;
md_get_uint16le(mdp, NULL); /* ByteCount */
- off += 2;
+ /*
+ * Does the data offset indicate padding?
+ * Add up the gets above, we have:
+ */
+ off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */
if (doff > off) /* pad byte(s)? */
md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
- if (resid == 0) {
- *rresid = resid;
+ if (rlen == 0) {
+ *lenp = rlen;
break;
}
- error = md_get_uio(mdp, uiop, resid);
+ /* paranoid */
+ if (rlen > *lenp) {
+ SMBSDEBUG("bad server! rlen %d, len %d\n",
+ rlen, *lenp);
+ rlen = *lenp;
+ }
+ error = md_get_uio(mdp, uiop, rlen);
if (error)
break;
- *rresid = resid;
+ *lenp = rlen;
/*LINTED*/
} while (0);
smb_rq_done(rqp);
@@ -1468,28 +1751,21 @@ smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
}
static int
-smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
- uio_t *uiop, struct smb_cred *scred, int timo)
+smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
+ uio_t *uiop, smb_cred_t *scred, int timo)
{
- struct smb_vc *vcp = SSTOVC(ssp);
struct smb_rq *rqp;
struct mbchain *mbp;
struct mdchain *mdp;
int error;
- u_int8_t wc;
- u_int16_t resid;
+ uint32_t offlo, offhi, rlen;
+ uint16_t lenhi, lenlo;
+ uint8_t wc;
- if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) == 0) {
- /* Fall back to the old cmd. */
- return (smb_smb_write(ssp, fid, len, rresid, uiop,
- scred, timo));
- }
- if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0) {
- /* Have WriteX but not large files? */
- if ((uiop->uio_loffset + *len) > UINT32_MAX)
- return (EFBIG);
- }
- *len = min(*len, vcp->vc_wxmax);
+ lenhi = (uint16_t)(*lenp >> 16);
+ lenlo = (uint16_t)*lenp;
+ offhi = (uint32_t)(uiop->uio_loffset >> 32);
+ offlo = (uint32_t)uiop->uio_loffset;
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
if (error)
@@ -1500,19 +1776,19 @@ smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
mb_put_uint8(mbp, 0); /* MBZ */
mb_put_uint16le(mbp, 0); /* offset to secondary */
mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
- mb_put_uint32le(mbp, (u_int32_t)(uiop->uio_offset));
+ mb_put_uint32le(mbp, offlo); /* offset (low part) */
mb_put_uint32le(mbp, 0); /* MBZ (timeout) */
mb_put_uint16le(mbp, 0); /* !write-thru */
mb_put_uint16le(mbp, 0);
- mb_put_uint16le(mbp, (u_int16_t)((unsigned)*len >> 16));
- mb_put_uint16le(mbp, (u_int16_t)*len);
+ mb_put_uint16le(mbp, lenhi);
+ mb_put_uint16le(mbp, lenlo);
mb_put_uint16le(mbp, 64); /* data offset from header start */
- mb_put_uint32le(mbp, (u_int32_t)((uiop->uio_loffset) >> 32));
+ mb_put_uint32le(mbp, offhi); /* offset (high part) */
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
do {
- mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */
- error = mb_put_uio(mbp, uiop, *len);
+ mb_put_uint8(mbp, 0); /* pad byte */
+ error = mb_put_uio(mbp, uiop, *lenp);
if (error)
break;
smb_rq_bend(rqp);
@@ -1527,19 +1803,14 @@ smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
error = EBADRPC;
break;
}
- md_get_uint8(mdp, NULL);
- md_get_uint8(mdp, NULL);
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, &resid); /* actually is # written */
- *rresid = resid;
- /*
- * if LARGE_WRITEX then there's one more bit of # written
- */
- if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)) {
- md_get_uint16le(mdp, NULL);
- md_get_uint16le(mdp, &resid);
- *rresid |= (int)(resid & 1) << 16;
- }
+ md_get_uint8(mdp, NULL); /* andx cmd */
+ md_get_uint8(mdp, NULL); /* reserved */
+ md_get_uint16le(mdp, NULL); /* andx offset */
+ md_get_uint16le(mdp, &lenlo); /* data len ret. */
+ md_get_uint16le(mdp, NULL); /* remaining */
+ md_get_uint16le(mdp, &lenhi);
+ rlen = (lenhi << 16) | lenlo;
+ *lenp = rlen;
/*LINTED*/
} while (0);
@@ -1548,20 +1819,23 @@ smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
}
static int
-smb_smb_read(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
- uio_t *uiop, struct smb_cred *scred, int timo)
+smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
+ uio_t *uiop, smb_cred_t *scred, int timo)
{
struct smb_rq *rqp;
struct mbchain *mbp;
struct mdchain *mdp;
- u_int16_t resid, bc;
- u_int8_t wc;
- int error, rlen;
+ int error;
+ uint32_t off32;
+ uint16_t bc, cnt, dlen, rcnt, todo;
+ uint8_t wc;
- /* This cmd is limited to 32-bit offsets. */
- if ((uiop->uio_loffset + *len) > UINT32_MAX)
- return (EFBIG);
- *len = rlen = min(*len, SSTOVC(ssp)->vc_rxmax);
+ ASSERT(uiop->uio_loffset <= UINT32_MAX);
+ off32 = (uint32_t)uiop->uio_loffset;
+ ASSERT(*lenp <= UINT16_MAX);
+ cnt = (uint16_t)*lenp;
+ /* This next is an "estimate" of planned reads. */
+ todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
if (error)
@@ -1569,9 +1843,9 @@ smb_smb_read(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
- mb_put_uint16le(mbp, (u_int16_t)rlen);
- mb_put_uint32le(mbp, (u_int32_t)uiop->uio_offset);
- mb_put_uint16le(mbp, (u_int16_t)min(uiop->uio_resid, 0xffff));
+ mb_put_uint16le(mbp, cnt);
+ mb_put_uint32le(mbp, off32);
+ mb_put_uint16le(mbp, todo);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
@@ -1587,19 +1861,30 @@ smb_smb_read(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
error = EBADRPC;
break;
}
- md_get_uint16le(mdp, &resid);
- md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
- md_get_uint16le(mdp, &bc);
- md_get_uint8(mdp, NULL); /* ignore buffer type */
- md_get_uint16le(mdp, &resid);
- if (resid == 0) {
- *rresid = resid;
+ md_get_uint16le(mdp, &rcnt); /* ret. count */
+ md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */
+ md_get_uint16le(mdp, &bc); /* byte count */
+ md_get_uint8(mdp, NULL); /* buffer format */
+ md_get_uint16le(mdp, &dlen); /* data len */
+ if (dlen < rcnt) {
+ SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
+ (int)dlen, (int)rcnt);
+ rcnt = dlen;
+ }
+ if (rcnt == 0) {
+ *lenp = 0;
break;
}
- error = md_get_uio(mdp, uiop, resid);
+ /* paranoid */
+ if (rcnt > cnt) {
+ SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
+ (int)rcnt, (int)cnt);
+ rcnt = cnt;
+ }
+ error = md_get_uio(mdp, uiop, (int)rcnt);
if (error)
break;
- *rresid = resid;
+ *lenp = (int)rcnt;
/*LINTED*/
} while (0);
smb_rq_done(rqp);
@@ -1607,20 +1892,23 @@ smb_smb_read(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
}
static int
-smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
- uio_t *uiop, struct smb_cred *scred, int timo)
+smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
+ uio_t *uiop, smb_cred_t *scred, int timo)
{
struct smb_rq *rqp;
struct mbchain *mbp;
struct mdchain *mdp;
- u_int16_t resid;
- u_int8_t wc;
int error;
+ uint32_t off32;
+ uint16_t cnt, rcnt, todo;
+ uint8_t wc;
- /* This cmd is limited to 32-bit offsets. */
- if ((uiop->uio_loffset + *len) > UINT32_MAX)
- return (EFBIG);
- *len = resid = min(*len, SSTOVC(ssp)->vc_wxmax);
+ ASSERT(uiop->uio_loffset <= UINT32_MAX);
+ off32 = (uint32_t)uiop->uio_loffset;
+ ASSERT(*lenp <= UINT16_MAX);
+ cnt = (uint16_t)*lenp;
+ /* This next is an "estimate" of planned writes. */
+ todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
if (error)
@@ -1628,15 +1916,15 @@ smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM);
- mb_put_uint16le(mbp, resid);
- mb_put_uint32le(mbp, (u_int32_t)uiop->uio_offset);
- mb_put_uint16le(mbp, (u_int16_t)min(uiop->uio_resid, 0xffff));
+ mb_put_uint16le(mbp, cnt);
+ mb_put_uint32le(mbp, off32);
+ mb_put_uint16le(mbp, todo);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
mb_put_uint8(mbp, SMB_DT_DATA);
- mb_put_uint16le(mbp, resid);
+ mb_put_uint16le(mbp, cnt);
do {
- error = mb_put_uio(mbp, uiop, resid);
+ error = mb_put_uio(mbp, uiop, *lenp);
if (error)
break;
smb_rq_bend(rqp);
@@ -1651,70 +1939,14 @@ smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid,
error = EBADRPC;
break;
}
- md_get_uint16le(mdp, &resid);
- *rresid = resid;
+ md_get_uint16le(mdp, &rcnt);
+ *lenp = rcnt;
/*LINTED*/
} while (0);
smb_rq_done(rqp);
return (error);
}
-/*
- * Common function for read/write with UIO.
- * Called by netsmb smb_usr_rw,
- * smbfs_readvnode, smbfs_writevnode
- */
-int
-smb_rwuio(struct smb_share *ssp, u_int16_t fid, uio_rw_t rw,
- uio_t *uiop, struct smb_cred *scred, int timo)
-{
- ssize_t old_resid, tsize;
- offset_t old_offset;
- int len, resid;
- int error = 0;
-
- old_offset = uiop->uio_loffset;
- old_resid = tsize = uiop->uio_resid;
-
- while (tsize > 0) {
- /* Lint: tsize may be 64-bits */
- len = SMB_MAX_LARGE_RW_SIZE;
- if (len > tsize)
- len = (int)tsize;
-
- if (rw == UIO_READ)
- error = smb_smb_readx(ssp, fid, &len, &resid, uiop,
- scred, timo);
- else
- error = smb_smb_writex(ssp, fid, &len, &resid, uiop,
- scred, timo);
- if (error)
- break;
-
- if (resid < len) {
- error = EIO;
- break;
- }
-
- tsize -= resid;
- timo = 0; /* only first write is special */
- }
-
- if (error) {
- /*
- * Errors can happen in copyin/copyout, the rpc, etc. so
- * they imply resid is unreliable. The only safe thing is
- * to pretend zero bytes made it. We needn't restore the
- * iovs because callers don't depend on them in error
- * paths - uio_resid and uio_offset are what matter.
- */
- uiop->uio_loffset = old_offset;
- uiop->uio_resid = old_resid;
- }
-
- return (error);
-}
-
static u_int32_t smbechoes = 0;
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
index eb5895f702..2ed6272a87 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_subr.h
@@ -40,8 +40,6 @@
#ifndef _NETSMB_SMB_SUBR_H_
#define _NETSMB_SMB_SUBR_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/cmn_err.h>
#include <sys/lock.h>
#include <sys/note.h>
@@ -125,12 +123,12 @@ void *smb_zmalloc(unsigned long size);
void smb_oldlm_hash(const char *apwd, uchar_t *hash);
void smb_ntlmv1hash(const char *apwd, uchar_t *hash);
+void smb_ntlmv2hash(const uchar_t *v1hash, const char *user,
+ const char *destination, uchar_t *v2hash);
-int smb_lmresponse(const uchar_t *hash, uchar_t *C8, uchar_t *RN);
-int smb_ntlmresponse(const uchar_t *hash, uchar_t *C8, uchar_t *RN);
-int smb_ntlmv2response(const uchar_t *hash, const uchar_t *user,
- const uchar_t *destination, uchar_t *C8, const uchar_t *blob,
- size_t bloblen, uchar_t **RN, size_t *RNlen);
+int smb_lmresponse(const uchar_t *hash, const uchar_t *C8, uchar_t *RN);
+int smb_ntlmv2response(const uchar_t *hash, const uchar_t *C8,
+ const uchar_t *blob, size_t bloblen, uchar_t **RN, size_t *RNlen);
int smb_maperror(int eclass, int eno);
uint32_t smb_maperr32(uint32_t eno);
int smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp,
@@ -146,4 +144,12 @@ struct sockaddr *smb_dup_sockaddr(struct sockaddr *sa);
void smb_free_sockaddr(struct sockaddr *sa);
int smb_toupper(const char *, char *, size_t);
+int smb_rq_sign(struct smb_rq *);
+int smb_rq_verify(struct smb_rq *);
+int smb_calcv2mackey(struct smb_vc *, const uchar_t *,
+ const uchar_t *, size_t);
+int smb_calcmackey(struct smb_vc *, const uchar_t *,
+ const uchar_t *, size_t);
+void smb_crypto_mech_init(void);
+
#endif /* !_NETSMB_SMB_SUBR_H_ */
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
index 886c7aadd1..3dffae55c8 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_usr.c
@@ -32,7 +32,10 @@
* $Id: smb_usr.c,v 1.15 2004/12/13 00:25:18 lindak Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
#include <sys/param.h>
#include <sys/kmem.h>
@@ -44,12 +47,7 @@
#include <sys/socket.h>
#include <sys/cmn_err.h>
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#include <sys/smb_iconv.h>
-#else
#include <netsmb/smb_osdep.h>
-#endif
#include <netsmb/smb.h>
#include <netsmb/smb_conn.h>
@@ -409,10 +407,6 @@ smb_usr_t2request(struct smb_share *ssp, smbioc_t2rq_t *dp,
if (dp->ioc_setupcnt > SMB_MAXSETUPWORDS)
return (EINVAL);
-
- t2p = (struct smb_t2rq *)kmem_alloc(sizeof (struct smb_t2rq), KM_SLEEP);
- if (t2p == NULL)
- return (ENOMEM);
error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup, dp->ioc_setupcnt,
scred);
if (error)
@@ -420,12 +414,14 @@ smb_usr_t2request(struct smb_share *ssp, smbioc_t2rq_t *dp,
len = t2p->t2_setupcount = dp->ioc_setupcnt;
if (len > 1)
t2p->t2_setupdata = dp->ioc_setup;
- if (dp->ioc_name) {
- bcopy(dp->ioc_name, t2p->t_name, 128);
- if (t2p->t_name == NULL) {
- error = ENOMEM;
- goto bad;
- }
+ /* This ioc member is a fixed-size array. */
+ if (dp->ioc_name[0]) {
+ t2p->t_name_maxlen = SMBIOC_T2RQ_MAXNAME;
+ t2p->t_name = kmem_alloc(t2p->t_name_maxlen, KM_SLEEP);
+ bcopy(dp->ioc_name, t2p->t_name, t2p->t_name_maxlen);
+ /* Get the string length - carefully! */
+ t2p->t_name[t2p->t_name_maxlen - 1] = '\0';
+ t2p->t_name_len = strlen(t2p->t_name);
}
t2p->t2_maxscount = 0;
t2p->t2_maxpcount = dp->ioc_rparamcnt;
@@ -484,6 +480,10 @@ smb_usr_t2request(struct smb_share *ssp, smbioc_t2rq_t *dp,
} else
dp->ioc_rdatacnt = 0;
bad:
+ if (t2p->t_name) {
+ kmem_free(t2p->t_name, t2p->t_name_maxlen);
+ t2p->t_name = NULL;
+ }
smb_t2_done(t2p);
return (error);
}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_io.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_io.c
deleted file mode 100644
index b813026f5e..0000000000
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_io.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2000-2001, Boris Popov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Boris Popov.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: smbfs_io.c,v 1.41.38.1 2005/05/27 02:35:28 lindak Exp $
- *
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/vnode.h>
-#include <sys/proc.h>
-#include <sys/fcntl.h>
-#include <sys/mount.h>
-#include <sys/dirent.h>
-#include <sys/syslog.h>
-#include <sys/file.h>
-
-#ifdef APPLE
-#include <sys/smb_apple.h>
-#else
-#include <netsmb/smb_osdep.h>
-#endif
-
-#include <netsmb/smb.h>
-#include <netsmb/smb_conn.h>
-#include <netsmb/smb_subr.h>
-
-#include <smbfs/smbfs.h>
-#include <smbfs/smbfs_node.h>
-#include <smbfs/smbfs_subr.h>
-
-/* XXX: This file should go away, after more work in _vnops.c */
-
-int
-smbfs_readvnode(vnode_t *vp, uio_t *uiop, cred_t *cr,
- struct vattr *vap)
-{
- smbmntinfo_t *smp = VTOSMI(vp);
- struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
- int error;
- int requestsize;
- size_t remainder;
-
- /* shared lock for n_fid use in smb_rwuio */
- ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
-
- if (vp->v_type != VREG) {
- SMBVDEBUG("only VREG supported\n");
- return (EIO);
- }
- if (uiop->uio_resid == 0)
- return (0);
- if (uiop->uio_loffset < 0)
- return (EINVAL);
-#ifdef NOT_YET
- if ((uiop->uio_loffset + uiop->uio_resid) > smp->nm_maxfilesize)
- return (EFBIG);
-#endif
-
- smb_credinit(&scred, curproc, cr);
-
- /* XXX: Update n_size maybe? */
- (void) smbfs_smb_flush(np, &scred);
-
- if (uiop->uio_loffset >= vap->va_size) {
- /* if offset is beyond EOF, read nothing */
- error = 0;
- goto out;
- }
-
- /* pin requestsize to EOF */
- requestsize = min(uiop->uio_resid,
- (vap->va_size - uiop->uio_loffset));
-
- /* subtract requestSize from uio_resid and save remainder */
- remainder = uiop->uio_resid - requestsize;
-
- /* adjust size of read */
- uiop->uio_resid = requestsize;
-
- error = smb_rwuio(smp->smi_share, np->n_fid, UIO_READ, uiop,
- &scred, smb_timo_read);
-
- /* set remaining uio_resid */
- uiop->uio_resid = uiop->uio_resid + remainder;
-
-out:
- smb_credrele(&scred);
-
- return (error);
-}
-
-int
-smbfs_writevnode(vnode_t *vp, uio_t *uiop,
- cred_t *cr, int ioflag, int timo)
-{
- smbmntinfo_t *smp = VTOSMI(vp);
- struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
- int error = 0;
-
- /* shared lock for n_fid use in smb_rwuio */
- ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
-
- if (vp->v_type != VREG) {
- SMBVDEBUG("only VREG supported\n");
- return (EIO);
- }
- SMBVDEBUG("ofs=%lld,resid=%d\n", uiop->uio_loffset,
- (int)uiop->uio_resid);
- if (uiop->uio_loffset < 0)
- return (EINVAL);
-#ifdef NOT_YET
- if (uiop->uio_loffset + uiop->uio_resid > smp->nm_maxfilesize)
- return (EFBIG);
-#endif
- if (ioflag & (FAPPEND | FSYNC)) {
- if (np->n_flag & NMODIFIED) {
- smbfs_attr_cacheremove(np);
- /* XXX: smbfs_vinvalbuf? */
- }
- if (ioflag & FAPPEND) {
- struct vattr vattr;
- /*
- * File size can be changed by another client
- */
- error = smbfsgetattr(vp, &vattr, cr);
- if (error)
- return (error);
- mutex_enter(&np->r_statelock);
- uiop->uio_loffset = np->n_size;
- mutex_exit(&np->r_statelock);
- }
- }
- if (uiop->uio_resid == 0)
- return (0);
-
- smb_credinit(&scred, curproc, cr);
-
- /*
- * Darwin had code here to zero-extend using
- * smb_write requests. Not needed.
- *
- * Use a longer timeout when appending.
- * This ignores the passed-in timo value,
- * but that was just a constant anyway.
- * XXX: remove passed in timo arg later.
- */
- timo = smb_timo_write;
- if ((uiop->uio_loffset + uiop->uio_resid) > np->n_size)
- timo = smb_timo_append;
- error = smb_rwuio(smp->smi_share, np->n_fid, UIO_WRITE, uiop,
- &scred, timo);
-
- mutex_enter(&np->r_statelock);
- np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
- mutex_exit(&np->r_statelock);
-
- smb_credrele(&scred);
-
- SMBVDEBUG("after: ofs=%lld,resid=%d\n", uiop->uio_loffset,
- (int)uiop->uio_resid);
- if (!error) {
- mutex_enter(&np->r_statelock);
- if (uiop->uio_loffset > (offset_t)np->n_size)
- np->n_size = (len_t)uiop->uio_loffset;
- mutex_exit(&np->r_statelock);
- }
- return (error);
-}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
index 1a7a22bbe1..95019bf34f 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_smb.c
@@ -37,8 +37,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/time.h>
@@ -804,10 +802,8 @@ smbfs_smb_flush(struct smbnode *np, struct smb_cred *scrp)
if (!(np->n_flag & NFLUSHWIRE))
return (0);
- if (np->r_count == 0)
+ if (np->n_fidrefs == 0)
return (0); /* not open */
- if (np->r_vnode->v_type != VREG)
- return (0); /* not a file */
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
if (error)
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
index 1713538614..0cf171a6eb 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
@@ -533,12 +533,15 @@ static int
smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
caller_context_t *ct)
{
- int error;
- struct vattr va;
smbmntinfo_t *smi;
smbnode_t *np;
+ struct smb_cred scred;
+ struct vattr va;
/* u_offset_t off; */
/* offset_t diff; */
+ offset_t endoff;
+ ssize_t past_eof;
+ int error;
np = VTOSMB(vp);
smi = VTOSMI(vp);
@@ -566,27 +569,44 @@ smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
uiop->uio_loffset + uiop->uio_resid < 0)
return (EINVAL);
- /* Shared lock for n_fid use in smbfs_readvnode */
- if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
- return (EINTR);
-
/* get vnode attributes from server */
va.va_mask = AT_SIZE | AT_MTIME;
if (error = smbfsgetattr(vp, &va, cr))
- goto out;
+ return (error);
- /* should probably update mtime with mtime from server here */
+ /* Update mtime with mtime from server here? */
+
+ /* if offset is beyond EOF, read nothing */
+ if (uiop->uio_loffset >= va.va_size)
+ return (0);
/*
- * Darwin had a loop here that handled paging stuff.
- * Solaris does paging differently, so no loop needed.
+ * Limit the read to the remaining file size.
+ * Do this by temporarily reducing uio_resid
+ * by the amount the lies beyoned the EOF.
*/
- error = smbfs_readvnode(vp, uiop, cr, &va);
+ endoff = uiop->uio_loffset + uiop->uio_resid;
+ if (endoff > va.va_size) {
+ past_eof = (ssize_t)(endoff - va.va_size);
+ uiop->uio_resid -= past_eof;
+ } else
+ past_eof = 0;
-out:
+ /* Shared lock for n_fid use in smb_rwuio */
+ if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
+ return (EINTR);
+ smb_credinit(&scred, curproc, cr);
+
+ error = smb_rwuio(smi->smi_share, np->n_fid, UIO_READ, uiop,
+ &scred, smb_timo_read);
+
+ smb_credrele(&scred);
smbfs_rw_exit(&np->r_lkserlock);
- return (error);
+ /* undo adjustment of resid */
+ uiop->uio_resid += past_eof;
+
+ return (error);
}
@@ -595,10 +615,13 @@ static int
smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
caller_context_t *ct)
{
- int error;
smbmntinfo_t *smi;
smbnode_t *np;
- int timo = SMBWRTTIMO;
+ struct smb_cred scred;
+ struct vattr va;
+ offset_t endoff, limit;
+ ssize_t past_limit;
+ int error, timo;
np = VTOSMB(vp);
smi = VTOSMI(vp);
@@ -617,20 +640,86 @@ smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr,
if (uiop->uio_resid == 0)
return (0);
- /* Shared lock for n_fid use in smbfs_writevnode */
+ /*
+ * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC)
+ */
+ if (ioflag & (FAPPEND | FSYNC)) {
+ if (np->n_flag & NMODIFIED) {
+ smbfs_attr_cacheremove(np);
+ /* XXX: smbfs_vinvalbuf? */
+ }
+ }
+ if (ioflag & FAPPEND) {
+ /*
+ * File size can be changed by another client
+ */
+ va.va_mask = AT_SIZE;
+ if (error = smbfsgetattr(vp, &va, cr))
+ return (error);
+ uiop->uio_loffset = va.va_size;
+ }
+
+ /*
+ * Like NFS3, just check for 63-bit overflow.
+ */
+ endoff = uiop->uio_loffset + uiop->uio_resid;
+ if (uiop->uio_loffset < 0 || endoff < 0)
+ return (EINVAL);
+
+ /*
+ * Check to make sure that the process will not exceed
+ * its limit on file size. It is okay to write up to
+ * the limit, but not beyond. Thus, the write which
+ * reaches the limit will be short and the next write
+ * will return an error.
+ *
+ * So if we're starting at or beyond the limit, EFBIG.
+ * Otherwise, temporarily reduce resid to the amount
+ * the falls after the limit.
+ */
+ limit = uiop->uio_llimit;
+ if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
+ limit = MAXOFFSET_T;
+ if (uiop->uio_loffset >= limit)
+ return (EFBIG);
+ if (endoff > limit) {
+ past_limit = (ssize_t)(endoff - limit);
+ uiop->uio_resid -= past_limit;
+ } else
+ past_limit = 0;
+
+ /* Timeout: longer for append. */
+ timo = smb_timo_write;
+ if (endoff > np->n_size)
+ timo = smb_timo_append;
+
+ /* Shared lock for n_fid use in smb_rwuio */
if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp)))
return (EINTR);
+ smb_credinit(&scred, curproc, cr);
+ error = smb_rwuio(smi->smi_share, np->n_fid, UIO_WRITE, uiop,
+ &scred, timo);
- /*
- * Darwin had a loop here that handled paging stuff.
- * Solaris does paging differently, so no loop needed.
- */
- error = smbfs_writevnode(vp, uiop, cr, ioflag, timo);
+ if (error == 0) {
+ mutex_enter(&np->r_statelock);
+ np->n_flag |= (NFLUSHWIRE | NATTRCHANGED);
+ if (uiop->uio_loffset > (offset_t)np->n_size)
+ np->n_size = (len_t)uiop->uio_loffset;
+ mutex_exit(&np->r_statelock);
+ if (ioflag & (FSYNC|FDSYNC)) {
+ /* Don't error the I/O if this fails. */
+ (void) smbfs_smb_flush(np, &scred);
+ }
+ }
+ smb_credrele(&scred);
smbfs_rw_exit(&np->r_lkserlock);
- return (error);
+ /* undo adjustment of resid */
+ uiop->uio_resid += past_limit;
+
+ return (error);
}
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
index 19cfc44282..4760576731 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
@@ -24,8 +24,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Functions supporting Solaris Extended Attributes,
* used to provide access to CIFS "named streams".
@@ -44,7 +42,6 @@
#include <sys/stat.h>
#include <sys/cmn_err.h>
#include <sys/dnlc.h>
-#include <sys/vfs_opreg.h>
#include <sys/u8_textprep.h>
#include <netsmb/smb_osdep.h>
diff --git a/usr/src/uts/common/netsmb/smb_dev.h b/usr/src/uts/common/netsmb/smb_dev.h
index 8bcbb5de98..ac09858c7d 100644
--- a/usr/src/uts/common/netsmb/smb_dev.h
+++ b/usr/src/uts/common/netsmb/smb_dev.h
@@ -40,8 +40,6 @@
#ifndef _NETSMB_DEV_H_
#define _NETSMB_DEV_H_
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This file defines an internal ABI for the "nsmb" driver,
* particularly the various data structures passed to ioctl.
@@ -137,6 +135,11 @@
#define SMBVOPT_EXT_SEC 0x0020 /* extended security negotiation */
#define SMBVOPT_USE_KEYCHAIN 0x0040 /* get p/w from keychain */
#define SMBVOPT_KC_DOMAIN 0x0080 /* keychain lookup uses domain */
+
+#define SMBVOPT_SIGNING_ENABLED 0x0100 /* sign if server agrees */
+#define SMBVOPT_SIGNING_REQUIRED 0x0200 /* signing required */
+#define SMBVOPT_SIGNING_MASK 0x0300 /* all signing bits */
+
/* XXX: How about a separate field for these? */
#define SMBVOPT_MINAUTH 0x7000 /* min. auth. level (mask) */
#define SMBVOPT_MINAUTH_NONE 0x0000 /* any authentication OK */
@@ -272,10 +275,12 @@ typedef struct smbioc_rq {
(offsetof(smbioc_rq_t, _ioc_twords))
+#define SMBIOC_T2RQ_MAXNAME 128
+
typedef struct smbioc_t2rq {
uint16_t ioc_setup[SMB_MAXSETUPWORDS];
int32_t ioc_setupcnt;
- char ioc_name[128];
+ char ioc_name[SMBIOC_T2RQ_MAXNAME];
ushort_t ioc_tparamcnt;
ushort_t ioc_tdatacnt;
ushort_t ioc_rparamcnt;
diff --git a/usr/src/uts/intel/smbfs/Makefile b/usr/src/uts/intel/smbfs/Makefile
index aff87ca8de..ed15103d1c 100644
--- a/usr/src/uts/intel/smbfs/Makefile
+++ b/usr/src/uts/intel/smbfs/Makefile
@@ -24,8 +24,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-#
# This makefile drives the production of the smbfs (Server
# message block file system) kernel module.
#
@@ -44,7 +42,6 @@ MODULE = smbfs
OBJECTS = $(SMBFS_OBJS:%=$(OBJS_DIR)/%)
LINTS = $(SMBFS_OBJS:%.o=$(LINTS_DIR)/%.ln)
ROOTMODULE = $(USR_FS_DIR)/$(MODULE)
-ROOTLINK = $(USR_SYS_DIR)/$(MODULE)
#
# Include common rules.
@@ -56,7 +53,7 @@ include $(UTSBASE)/intel/Makefile.intel
#
ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
#
# Overrides.
@@ -89,9 +86,6 @@ clean.lint: $(CLEAN_LINT_DEPS)
install: $(INSTALL_DEPS)
-$(ROOTLINK): $(USR_SYS_DIR) $(ROOTMODULE)
- -$(RM) $@; ln $(ROOTMODULE) $@
-
#
# Include common targets.
#
diff --git a/usr/src/uts/sparc/smbfs/Makefile b/usr/src/uts/sparc/smbfs/Makefile
index 6f837768a5..fdf1007440 100644
--- a/usr/src/uts/sparc/smbfs/Makefile
+++ b/usr/src/uts/sparc/smbfs/Makefile
@@ -24,8 +24,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
-#
# This makefile drives the production of the smbfs (Server
# message block file system) kernel module.
#
@@ -44,7 +42,6 @@ MODULE = smbfs
OBJECTS = $(SMBFS_OBJS:%=$(OBJS_DIR)/%)
LINTS = $(SMBFS_OBJS:%.o=$(LINTS_DIR)/%.ln)
ROOTMODULE = $(USR_FS_DIR)/$(MODULE)
-ROOTLINK = $(USR_SYS_DIR)/$(MODULE)
#
# Include common rules.
@@ -56,7 +53,7 @@ include $(UTSBASE)/sparc/Makefile.sparc
#
ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK)
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
#
# Overrides.
@@ -89,9 +86,6 @@ clean.lint: $(CLEAN_LINT_DEPS)
install: $(INSTALL_DEPS)
-$(ROOTLINK): $(USR_SYS_DIR) $(ROOTMODULE)
- -$(RM) $@; ln $(ROOTMODULE) $@
-
#
# Include common targets.
#