diff options
author | Gordon Ross <Gordon.Ross@Sun.COM> | 2008-12-04 12:51:31 -0500 |
---|---|---|
committer | Gordon Ross <Gordon.Ross@Sun.COM> | 2008-12-04 12:51:31 -0500 |
commit | 9c9af2590af49bb395bc8d2eace0f2d4ea16d165 (patch) | |
tree | d7b65e8be9071e7f1a693ce58b136d1068ee496c | |
parent | fc3af78a71855c71878866a294572d00e6720533 (diff) | |
download | illumos-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
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, ×tamp); @@ -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. # |