summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libshare/common/libshare.c19
-rw-r--r--usr/src/lib/libshare/common/libshare.h2
-rw-r--r--usr/src/lib/libshare/common/scfutil.c3
-rw-r--r--usr/src/lib/libshare/smb/libshare_smb.c62
-rw-r--r--usr/src/lib/smbsrv/Makefile.lib8
-rw-r--r--usr/src/lib/smbsrv/Makefile.smbsrv2
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/Makefile.com1
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/amd64/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers9
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/mlndr.c72
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c3
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c89
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/i386/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/sparc/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/Makefile.com1
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/amd64/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsalib.c50
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c39
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers2
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c2
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c44
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c27
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c25
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c3
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c53
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c2
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c34
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c6
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samlib.c149
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c3
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samr_open.c72
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c12
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c58
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/i386/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/sparc/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile10
-rw-r--r--usr/src/lib/smbsrv/libsmb/Makefile.com1
-rw-r--r--usr/src/lib/smbsrv/libsmb/amd64/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h5
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers4
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_cfg.c30
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_door_client.c94
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_info.c16
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_wins.c3
-rw-r--r--usr/src/lib/smbsrv/libsmb/i386/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libsmb/sparc/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libsmb/sparcv9/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libsmbns/Makefile.com1
-rw-r--r--usr/src/lib/smbsrv/libsmbns/amd64/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/libsmbns.h12
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/mapfile-vers3
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c483
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c180
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c51
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h6
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c157
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c10
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c57
-rw-r--r--usr/src/lib/smbsrv/libsmbns/i386/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libsmbns/sparc/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/Makefile.com1
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h21
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers11
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c270
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h31
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c197
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/i386/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile2
-rw-r--r--usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile4
72 files changed, 1383 insertions, 1179 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c
index 49104b2abe..5716ef931c 100644
--- a/usr/src/lib/libshare/common/libshare.c
+++ b/usr/src/lib/libshare/common/libshare.c
@@ -217,6 +217,15 @@ sa_errorstr(int err)
case SA_PATH_IS_PARENTDIR:
ret = dgettext(TEXT_DOMAIN, "path is parent of a share");
break;
+ case SA_KRB_KEYTAB_ERR:
+ ret = dgettext(TEXT_DOMAIN, "unable to remove the old keys"
+ " from the Kerberos keytab. Please manually remove"
+ " the old keys for your host principal prior to setting"
+ " the ads_domain property");
+ break;
+ case SA_NO_SERVICE:
+ ret = dgettext(TEXT_DOMAIN, "service is not running");
+ break;
default:
(void) snprintf(errstr, sizeof (errstr),
dgettext(TEXT_DOMAIN, "unknown %d"), err);
@@ -3603,6 +3612,7 @@ sa_remove_resource(sa_resource_t resource)
char *type;
int ret = SA_OK;
int transient = 0;
+ sa_optionset_t opt;
share = sa_get_resource_parent(resource);
type = sa_get_share_attr(share, "type");
@@ -3615,6 +3625,15 @@ sa_remove_resource(sa_resource_t resource)
sa_free_attr_string(type);
}
+ /* Disable the resource for all protocols. */
+ (void) sa_disable_resource(resource, NULL);
+
+ /* Remove any optionsets from the resource. */
+ for (opt = sa_get_optionset(resource, NULL);
+ opt != NULL;
+ opt = sa_get_next_optionset(opt))
+ (void) sa_destroy_optionset(opt);
+
/* Remove from the share */
xmlUnlinkNode((xmlNode *)resource);
xmlFreeNode((xmlNode *)resource);
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index bdac6a6d64..af6e2db2f8 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -85,6 +85,8 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */
#define SA_MULTIPLE_ERROR 26 /* multiple protocols reported error */
#define SA_PATH_IS_SUBDIR 27 /* check_path found path is subdir */
#define SA_PATH_IS_PARENTDIR 28 /* check_path found path is parent */
+#define SA_KRB_KEYTAB_ERR 29 /* fail to delete old keytab entries */
+#define SA_NO_SERVICE 30 /* service isn't running */
/* API Initialization */
#define SA_INIT_SHARE_API 0x0001 /* init share specific interface */
diff --git a/usr/src/lib/libshare/common/scfutil.c b/usr/src/lib/libshare/common/scfutil.c
index 344d3729bb..1c35d7d151 100644
--- a/usr/src/lib/libshare/common/scfutil.c
+++ b/usr/src/lib/libshare/common/scfutil.c
@@ -790,8 +790,9 @@ sa_share_props_from_pgroup(xmlNodePtr root, scfutilhandle_t *handle,
node = xmlNewChild(resource, NULL,
(xmlChar *)"optionset", NULL);
} else {
- /* this shouldn't happen */
+ /* This shouldn't happen. */
ret = SA_SYSTEM_ERR;
+ goto out;
}
} else {
/*
diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c
index aa30b46352..9aa98e9a37 100644
--- a/usr/src/lib/libshare/smb/libshare_smb.c
+++ b/usr/src/lib/libshare/smb/libshare_smb.c
@@ -84,6 +84,7 @@ static int smb_enable_resource(sa_resource_t);
static int smb_disable_resource(sa_resource_t);
static uint64_t smb_share_features(void);
static int smb_list_transient(sa_handle_t);
+static int smb_domain_change_event(char *new_domain);
/* size of basic format allocation */
#define OPT_CHUNK 1024
@@ -1037,6 +1038,7 @@ smb_enable_service(void)
(void) fprintf(stderr,
dgettext(TEXT_DOMAIN,
"%s failed to restart: %s\n"),
+ SMBD_DEFAULT_INSTANCE_FMRI,
scf_strerror(scf_error()));
return (SA_CONFIG_ERR);
}
@@ -1077,6 +1079,45 @@ smb_validate_proto_prop(int index, char *name, char *value)
}
/*
+ * smb_domain_change_event
+ *
+ * This function is called whenever ads_domain is changed via sharectl.
+ * It will make a door call to trigger the ADS domain change event.
+ */
+static int
+smb_domain_change_event(char *new_domain)
+{
+ char *orig_domain;
+ int rc = SA_OK;
+
+ orig_domain = smb_config_getenv(SMB_CI_ADS_DOMAIN);
+ if (orig_domain == NULL)
+ return (rc);
+
+ if (strcasecmp(orig_domain, new_domain) == 0) {
+ free(orig_domain);
+ return (rc);
+ }
+
+ if (!smb_isonline()) {
+ free(orig_domain);
+ return (SA_NO_SERVICE);
+ }
+
+ /*
+ * Clear the ADS_HOST_INFO cache
+ * and remove old keys from the
+ * Kerberos keytab.
+ */
+ if (smb_ads_domain_change_notify(orig_domain) != 0)
+ rc = SA_KRB_KEYTAB_ERR;
+
+ free(orig_domain);
+ return (rc);
+}
+
+
+/*
* smb_set_proto_prop(prop)
*
* check that prop is valid.
@@ -1089,6 +1130,7 @@ smb_set_proto_prop(sa_property_t prop)
char *name;
char *value;
int index = -1;
+ struct smb_proto_option_defs *opt;
name = sa_get_property_attr(prop, "type");
value = sa_get_property_attr(prop, "value");
@@ -1098,25 +1140,29 @@ smb_set_proto_prop(sa_property_t prop)
/* should test for valid value */
ret = smb_validate_proto_prop(index, name, value);
if (ret == SA_OK) {
+ opt = &smb_proto_options[index];
+ if ((opt->smb_index == SMB_CI_ADS_DOMAIN) &&
+ (ret = smb_domain_change_event(value))
+ != SA_OK)
+ goto cleanup;
+
/* Save to SMF */
- smb_config_setenv(
- smb_proto_options[index].smb_index, value);
+ smb_config_setenv(opt->smb_index, value);
/*
* Specialized refresh mechanisms can
* be flagged in the proto_options and
* processed here.
*/
- if (smb_proto_options[index].refresh &
- SMB_REFRESH_REFRESH)
- (void) smf_refresh_instance(
- SMBD_DEFAULT_INSTANCE_FMRI);
- else if (smb_proto_options[index].refresh &
- SMB_REFRESH_RESTART)
+ if (opt->refresh & SMB_REFRESH_REFRESH)
+ (void) smb_config_refresh();
+ else if (opt->refresh & SMB_REFRESH_RESTART)
(void) smf_restart_instance(
SMBD_DEFAULT_INSTANCE_FMRI);
}
}
}
+
+cleanup:
if (name != NULL)
sa_free_attr_string(name);
if (value != NULL)
diff --git a/usr/src/lib/smbsrv/Makefile.lib b/usr/src/lib/smbsrv/Makefile.lib
index abd5776bc9..625bde45c4 100644
--- a/usr/src/lib/smbsrv/Makefile.lib
+++ b/usr/src/lib/smbsrv/Makefile.lib
@@ -28,12 +28,14 @@
# Common Makefile definitions for smbsrv.
#
-# We reset the Makefile.lib macros ROOTLIBDIR to refer to usr/lib/smbsrv
-# We also install the userland library header files under /usr/include/smbsrv
+# We reset the Makefile.lib macros ROOTLIBDIR to refer to usr/lib/smbsrv.
+# For 64 bit, we reset ROOTLIBDIR64 to refer to usr/lib/smbsrv/$(MACH64).
+# We also install the userland library header files under /usr/include/smbsrv.
ROOTSMBHDRDIR= $(ROOTHDRDIR)/smbsrv
ROOTSMBHDRS= $(HDRS:%=$(ROOTSMBHDRDIR)/%)
ROOTLIBDIR = $(ROOT)/usr/lib/smbsrv
+ROOTLIBDIR64 = $(ROOT)/usr/lib/smbsrv/$(MACH64)
SRCDIR= ../common
NDLDIR= $(ROOT)/usr/include/smbsrv/ndl
@@ -41,8 +43,6 @@ LIBS= $(DYNLIB) $(LINTLIB)
C99MODE = -xc99=%all
C99LMODE = -Xc99=%all
CPPFLAGS += -I$(SRCDIR) -I.
-DYNFLAGS += -R/usr/lib/smbsrv
-DYNFLAGS64 += -R/usr/lib/smbsrv/$(MACH64)
LDLIBS32 += -L$(ROOT)/usr/lib/smbsrv
LDLIBS64 += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/smbsrv/Makefile.smbsrv b/usr/src/lib/smbsrv/Makefile.smbsrv
index 16d6ddfed1..aaa7149cbe 100644
--- a/usr/src/lib/smbsrv/Makefile.smbsrv
+++ b/usr/src/lib/smbsrv/Makefile.smbsrv
@@ -34,7 +34,7 @@ include ../../Makefile.lib
include ../Makefile.lib
SUBDIRS= $(MACH)
-#$(BUILD64)SUBDIRS += $(MACH64)
+$(BUILD64)SUBDIRS += $(MACH64)
HDRDIR= common
diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile.com b/usr/src/lib/smbsrv/libmlrpc/Makefile.com
index 86c7672546..cc5ba2923f 100644
--- a/usr/src/lib/smbsrv/libmlrpc/Makefile.com
+++ b/usr/src/lib/smbsrv/libmlrpc/Makefile.com
@@ -46,6 +46,7 @@ include ../../Makefile.lib
INCS += -I$(SRC)/common/smbsrv
+LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lsmb -lc
CPPFLAGS += $(INCS) -D_REENTRANT
diff --git a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile b/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile
+++ b/usr/src/lib/smbsrv/libmlrpc/amd64/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers
index 6858b4cea0..2f8fea95f3 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers
@@ -36,6 +36,7 @@ SUNWprivate {
mlrpc_c_bind;
mlrpc_c_call;
mlrpc_c_free_heap;
+ mlrpc_generic_call_stub;
mlrpc_heap_avail;
mlrpc_heap_create;
mlrpc_heap_destroy;
@@ -43,10 +44,12 @@ SUNWprivate {
mlrpc_heap_mkvcs;
mlrpc_heap_strsave;
mlrpc_heap_used;
+ mlrpc_lookup;
+ mlrpc_process;
mlrpc_register_service;
- mlsvc_lookup_context;
- mlsvc_rpc_process;
- mlsvc_rpc_release;
+ mlrpc_release;
+ ndr_mbstowcs;
+ ndr_mbtowc;
ndt__char;
ndt_s_wchar;
ndt__uchar;
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c b/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c
index 6d13d459b3..e81225ede8 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c
@@ -31,6 +31,7 @@
* complicated trees of data constructs between an RPC client and server.
*/
+#include <sys/byteorder.h>
#include <strings.h>
#include <assert.h>
#include <string.h>
@@ -1220,7 +1221,11 @@ mlndr_outer_string(struct ndr_reference *outer_ref)
}
first_is = 0;
- length_is = size_is;
+
+ if (mlnds->flags & MLNDS_F_NOTERM)
+ length_is = size_is - 1;
+ else
+ length_is = size_is;
if (!mlndr_outer_poke_sizing(outer_ref, 0, &size_is) ||
!mlndr_outer_poke_sizing(outer_ref, 4, &first_is) ||
@@ -1929,12 +1934,9 @@ mlndr_s_wchar(struct ndr_reference *encl_ref)
return (0);
} else if (count == 0) {
/*
- * If the input char is 0, mts_mbtowc
+ * If the input char is 0, mbtowc
* returns 0 without setting wide_char.
- * I'm not sure if this is the correct
- * behaviour for mts_mbtowc but for
- * now we need to set wide_char to 0
- * and assume a count of 1.
+ * Set wide_char to 0 and a count of 1.
*/
wide_char = *valp;
count = 1;
@@ -1963,3 +1965,61 @@ mlndr_s_wchar(struct ndr_reference *encl_ref)
return (1);
}
+
+/*
+ * Converts a multibyte character string to a little-endian, wide-char
+ * string. No more than nwchars wide characters are stored.
+ * A terminating null wide character is appended if there is room.
+ *
+ * Returns the number of wide characters converted, not counting
+ * any terminating null wide character. Returns -1 if an invalid
+ * multibyte character is encountered.
+ */
+size_t
+ndr_mbstowcs(struct mlndr_stream *mlnds, mts_wchar_t *wcs, const char *mbs,
+ size_t nwchars)
+{
+ mts_wchar_t *start = wcs;
+ int nbytes;
+
+ while (nwchars--) {
+ nbytes = ndr_mbtowc(mlnds, wcs, mbs, MTS_MB_CHAR_MAX);
+ if (nbytes < 0) {
+ *wcs = 0;
+ return ((size_t)-1);
+ }
+
+ if (*mbs == 0)
+ break;
+
+ ++wcs;
+ mbs += nbytes;
+ }
+
+ return (wcs - start);
+}
+
+/*
+ * Converts a multibyte character to a little-endian, wide-char, which
+ * is stored in wcharp. Up to nbytes bytes are examined.
+ *
+ * If mbchar is valid, returns the number of bytes processed in mbchar.
+ * If mbchar is invalid, returns -1. See also mts_mbtowc().
+ */
+/*ARGSUSED*/
+int
+ndr_mbtowc(struct mlndr_stream *mlnds, mts_wchar_t *wcharp,
+ const char *mbchar, size_t nbytes)
+{
+ int rc;
+
+ if ((rc = mts_mbtowc(wcharp, mbchar, nbytes)) < 0)
+ return (rc);
+
+#ifdef _BIG_ENDIAN
+ if (mlnds == NULL || NDR_MODE_MATCH(mlnds, NDR_MODE_RETURN_SEND))
+ *wcharp = BSWAP_16(*wcharp);
+#endif
+
+ return (rc);
+}
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c
index 9bce9469ea..0f58231251 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c
@@ -240,13 +240,12 @@ fault_exit:
return (rc);
}
-int
+void
mlrpc_c_free_heap(struct mlrpc_binding *mbind, mlrpc_heapref_t *heapref)
{
struct mlrpc_client *mcli = mbind->context;
(*mcli->xa_release)(mcli, heapref);
- return (0);
}
static void
diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c
index a5bf41a617..2f442937be 100644
--- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c
+++ b/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c
@@ -29,6 +29,7 @@
* Server side RPC handler.
*/
+#include <sys/byteorder.h>
#include <thread.h>
#include <synch.h>
#include <stdlib.h>
@@ -37,6 +38,7 @@
#include <time.h>
#include <smbsrv/libsmb.h>
+#include <smbsrv/libmlrpc.h>
#include <smbsrv/mlsvc.h>
#include <smbsrv/ndr.h>
#include <smbsrv/mlrpc.h>
@@ -53,14 +55,14 @@ static unsigned long mlrpc_frag_size = MLRPC_FRAG_SZ;
/*
* Context table.
*/
+#define CTXT_PIPE_SZ 65536
#define CTXT_TABLE_ENTRIES 128
static struct mlsvc_rpc_context context_table[CTXT_TABLE_ENTRIES];
-static mutex_t mlsvc_context_lock;
+static mutex_t mlrpc_context_lock;
static int mlrpc_s_process(struct mlrpc_xaction *);
static int mlrpc_s_bind(struct mlrpc_xaction *);
static int mlrpc_s_request(struct mlrpc_xaction *);
-static int mlrpc_generic_call_stub(struct mlrpc_xaction *);
static void mlrpc_reply_prepare_hdr(struct mlrpc_xaction *);
static int mlrpc_s_alter_context(struct mlrpc_xaction *);
static void mlrpc_reply_bind_ack(struct mlrpc_xaction *);
@@ -73,29 +75,27 @@ static int mlrpc_build_reply(struct mlrpc_xaction *);
* structure as the client side but we don't need to set up the client
* side info.
*/
-int
-mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe,
- smb_dr_user_ctx_t *user_ctx)
+struct mlsvc_rpc_context *
+mlrpc_process(int fid, smb_dr_user_ctx_t *user_ctx)
{
struct mlsvc_rpc_context *context;
struct mlrpc_xaction *mxa;
struct mlndr_stream *recv_mlnds;
struct mlndr_stream *send_mlnds;
unsigned char *pdu_base_addr;
+ char *data;
int datalen;
- if (inpipe == NULL || user_ctx == NULL)
- return (-1);
-
- context = mlsvc_lookup_context(inpipe->sp_pipeid);
- if (context == NULL)
- return (-1);
+ if ((context = mlrpc_lookup(fid)) == NULL)
+ return (NULL);
context->user_ctx = user_ctx;
+ data = context->inpipe->sp_data;
+ datalen = context->inpipe->sp_datalen;
mxa = (struct mlrpc_xaction *)malloc(sizeof (struct mlrpc_xaction));
if (mxa == NULL)
- return (-1);
+ return (NULL);
bzero(mxa, sizeof (struct mlrpc_xaction));
mxa->context = context;
@@ -103,30 +103,21 @@ mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe,
if ((mxa->heap = mlrpc_heap_create()) == NULL) {
free(mxa);
- return (-1);
+ return (NULL);
}
recv_mlnds = &mxa->recv_mlnds;
+ (void) mlnds_initialize(recv_mlnds, datalen, NDR_MODE_CALL_RECV,
+ mxa->heap);
- (void) mlnds_initialize(recv_mlnds, inpipe->sp_datalen,
- NDR_MODE_CALL_RECV, mxa->heap);
-
- bcopy(inpipe->sp_data, recv_mlnds->pdu_base_addr, inpipe->sp_datalen);
+ bcopy(data, recv_mlnds->pdu_base_addr, datalen);
send_mlnds = &mxa->send_mlnds;
- (void) mlnds_initialize(send_mlnds, 0,
- NDR_MODE_RETURN_SEND, mxa->heap);
+ (void) mlnds_initialize(send_mlnds, 0, NDR_MODE_RETURN_SEND, mxa->heap);
(void) mlrpc_s_process(mxa);
/*
- * copy into outpipe
- */
- datalen = send_mlnds->pdu_size_with_rpc_hdrs;
- *outpipe = calloc(1, sizeof (smb_pipe_t) + datalen);
- (*outpipe)->sp_datalen = datalen;
-
- /*
* Different pointers for single frag vs multi frag responses.
*/
if (send_mlnds->pdu_base_addr_with_rpc_hdrs)
@@ -134,12 +125,15 @@ mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe,
else
pdu_base_addr = send_mlnds->pdu_base_addr;
- bcopy((char *)pdu_base_addr, (*outpipe)->sp_data, datalen);
+ datalen = send_mlnds->pdu_size_with_rpc_hdrs;
+ context->outpipe->sp_datalen = datalen;
+ bcopy(pdu_base_addr, context->outpipe->sp_data, datalen);
+
mlnds_destruct(&mxa->recv_mlnds);
mlnds_destruct(&mxa->send_mlnds);
mlrpc_heap_destroy(mxa->heap);
free(mxa);
- return (datalen);
+ return (context);
}
/*
@@ -148,13 +142,13 @@ mlsvc_rpc_process(smb_pipe_t *inpipe, smb_pipe_t **outpipe,
* context table is full, return a null pointer.
*/
struct mlsvc_rpc_context *
-mlsvc_lookup_context(int fid)
+mlrpc_lookup(int fid)
{
struct mlsvc_rpc_context *context;
struct mlsvc_rpc_context *available = NULL;
int i;
- (void) mutex_lock(&mlsvc_context_lock);
+ (void) mutex_lock(&mlrpc_context_lock);
for (i = 0; i < CTXT_TABLE_ENTRIES; ++i) {
context = &context_table[i];
@@ -165,20 +159,33 @@ mlsvc_lookup_context(int fid)
}
if (context->fid == fid) {
- (void) mutex_unlock(&mlsvc_context_lock);
+ (void) mutex_unlock(&mlrpc_context_lock);
return (context);
}
}
if (available) {
bzero(available, sizeof (struct mlsvc_rpc_context));
+ available->inpipe = malloc(CTXT_PIPE_SZ);
+ available->outpipe = malloc(CTXT_PIPE_SZ);
+
+ if (available->inpipe == NULL || available->outpipe == NULL) {
+ free(available->inpipe);
+ free(available->outpipe);
+ bzero(available, sizeof (struct mlsvc_rpc_context));
+ (void) mutex_unlock(&mlrpc_context_lock);
+ return (NULL);
+ }
+
available->fid = fid;
+ available->inpipe->sp_pipeid = fid;
+ available->outpipe->sp_pipeid = fid;
mlrpc_binding_pool_initialize(&available->binding,
available->binding_pool, CTXT_N_BINDING_POOL);
}
- (void) mutex_unlock(&mlsvc_context_lock);
+ (void) mutex_unlock(&mlrpc_context_lock);
return (available);
}
@@ -187,23 +194,25 @@ mlsvc_lookup_context(int fid)
* with a fid when the client performs a close file.
*/
void
-mlsvc_rpc_release(int fid)
+mlrpc_release(int fid)
{
struct mlsvc_rpc_context *context;
int i;
- (void) mutex_lock(&mlsvc_context_lock);
+ (void) mutex_lock(&mlrpc_context_lock);
for (i = 0; i < CTXT_TABLE_ENTRIES; ++i) {
context = &context_table[i];
if (context->fid == fid) {
+ free(context->inpipe);
+ free(context->outpipe);
bzero(context, sizeof (struct mlsvc_rpc_context));
break;
}
}
- (void) mutex_unlock(&mlsvc_context_lock);
+ (void) mutex_unlock(&mlrpc_context_lock);
}
/*
@@ -509,7 +518,7 @@ mlrpc_s_request(struct mlrpc_xaction *mxa)
* should already exist at this point. The heap will also be available
* to the stub.
*/
-static int
+int
mlrpc_generic_call_stub(struct mlrpc_xaction *mxa)
{
struct mlrpc_binding *mbind = mxa->binding;
@@ -775,11 +784,11 @@ mlrpc_build_reply(struct mlrpc_xaction *mxa)
frag_data_size = frag_size - MLRPC_RSP_HDR_SIZE;
num_ext_frags = pdu_data_size / frag_data_size;
+
/*
- * if the outpipe is bigger than a frag_size, we need
- * to stretch the pipe and insert an RPC header at each
- * frag boundary. This outpipe gets chunked out in xdrlen
- * sizes for each trans request
+ * We may need to stretch the pipe and insert an RPC header
+ * at each frag boundary. The response will get chunked into
+ * xdrlen sizes for each trans request.
*/
mlnds->pdu_base_addr_with_rpc_hdrs
= malloc(pdu_size + (num_ext_frags * MLRPC_RSP_HDR_SIZE));
diff --git a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile b/usr/src/lib/smbsrv/libmlrpc/i386/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libmlrpc/i386/Makefile
+++ b/usr/src/lib/smbsrv/libmlrpc/i386/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile b/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile
+++ b/usr/src/lib/smbsrv/libmlrpc/sparc/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile b/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile
+++ b/usr/src/lib/smbsrv/libmlrpc/sparcv9/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libmlsvc/Makefile.com b/usr/src/lib/smbsrv/libmlsvc/Makefile.com
index e0c1ee5c4c..60f0c4f66d 100644
--- a/usr/src/lib/smbsrv/libmlsvc/Makefile.com
+++ b/usr/src/lib/smbsrv/libmlsvc/Makefile.com
@@ -77,6 +77,7 @@ include ../../Makefile.lib
INCS += -I$(SRC)/common/smbsrv
+LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lmlrpc -lsmbrdr -lsmb -lsmbns -lshare -lnsl -lc
SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \
diff --git a/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile b/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile
+++ b/usr/src/lib/smbsrv/libmlsvc/amd64/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c
index ca98eb8eab..8e2effc333 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c
@@ -36,6 +36,7 @@
#include <smbsrv/libsmb.h>
#include <smbsrv/libsmbns.h>
#include <smbsrv/libmlsvc.h>
+#include <smbsrv/libsmbrdr.h>
#include <smbsrv/lsalib.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/smbinfo.h>
@@ -60,8 +61,9 @@ lsa_query_primary_domain_info(void)
{
mlsvc_handle_t domain_handle;
DWORD status;
+ char *user = smbrdr_ipc_get_user();
- if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
+ if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0)
return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
status = lsar_query_info_policy(&domain_handle,
@@ -87,8 +89,9 @@ lsa_query_account_domain_info(void)
{
mlsvc_handle_t domain_handle;
DWORD status;
+ char *user = smbrdr_ipc_get_user();
- if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
+ if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0)
return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
status = lsar_query_info_policy(&domain_handle,
@@ -114,8 +117,9 @@ lsa_enum_trusted_domains(void)
mlsvc_handle_t domain_handle;
DWORD enum_context;
DWORD status;
+ char *user = smbrdr_ipc_get_user();
- if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
+ if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0)
return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
enum_context = 0;
@@ -318,8 +322,9 @@ int lsa_lookup_name(char *server, char *domain, char *account_name,
{
mlsvc_handle_t domain_handle;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle);
+ rc = lsar_open(server, domain, user, &domain_handle);
if (rc != 0)
return (-1);
@@ -340,8 +345,9 @@ DWORD lsa_lookup_name2(char *server, char *domain, char *account_name,
mlsvc_handle_t domain_handle;
DWORD status;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle);
+ rc = lsar_open(server, domain, user, &domain_handle);
if (rc != 0)
return (NT_STATUS_INVALID_PARAMETER);
@@ -378,8 +384,9 @@ lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *user_info)
{
mlsvc_handle_t domain_handle;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle);
+ rc = lsar_open(NULL, NULL, user, &domain_handle);
if (rc != 0)
return (-1);
@@ -401,8 +408,9 @@ lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info)
mlsvc_handle_t domain_handle;
DWORD status;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle);
+ rc = lsar_open(NULL, NULL, user, &domain_handle);
if (rc != 0)
return (NT_STATUS_INVALID_PARAMETER);
@@ -479,30 +487,12 @@ lsa_lookup_privs(char *server, char *account_name, char *target_name,
{
mlsvc_handle_t domain_handle;
int rc;
-#if 0
- mlsvc_handle_t account_handle;
- struct mslsa_sid *sid;
-
- lsa_lookup_name(0, 0, target_name, user_info);
+ char *user = smbrdr_ipc_get_user();
- sid = (struct mslsa_sid *)
- nt_sid_splice(user_info->domain_sid, user_info->rid);
-
- lsa_lookup_sid(server, account_name, (nt_sid_t *)sid, user_info);
-#endif
- if ((lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle)) != 0)
+ if ((lsar_open(NULL, NULL, user, &domain_handle)) != 0)
return (-1);
rc = lsa_list_accounts(&domain_handle);
-#if 0
- rc = lsar_open_account(&domain_handle, sid, &account_handle);
- if (rc == 0) {
- (void) lsar_enum_privs_account(&account_handle, user_info);
- (void) lsar_close(&account_handle);
- }
-
- free(sid);
-#endif
(void) lsar_close(&domain_handle);
return (rc);
}
@@ -523,8 +513,9 @@ lsa_list_privs(char *server, char *domain)
mlsvc_handle_t domain_handle;
int rc;
int i;
+ char *user = smbrdr_ipc_get_user();
- rc = lsar_open(MLSVC_IPC_ANON, server, domain, 0, 0, &domain_handle);
+ rc = lsar_open(server, domain, user, &domain_handle);
if (rc != 0)
return (NT_STATUS_INVALID_PARAMETER);
@@ -557,8 +548,9 @@ lsa_test(char *server, char *account_name)
{
mlsvc_handle_t domain_handle;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = lsar_open(MLSVC_IPC_ANON, 0, 0, 0, 0, &domain_handle);
+ rc = lsar_open(NULL, NULL, user, &domain_handle);
if (rc != 0)
return (-1);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c
index 57b1b62a97..10f77f49cf 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c
@@ -49,48 +49,31 @@
* domain information if the caller didn't supply a server name and a
* domain name.
*
+ * If username argument is NULL, an anonymous connection will be established.
+ * Otherwise, an authenticated connection will be established.
+ *
* On success 0 is returned. Otherwise a -ve error code.
*/
-int lsar_open(int ipc_mode, char *server, char *domain, char *username,
- char *password, mlsvc_handle_t *domain_handle)
+int lsar_open(char *server, char *domain, char *username,
+ mlsvc_handle_t *domain_handle)
{
smb_ntdomain_t *di;
int remote_os;
int remote_lm;
int rc;
- if ((di = smb_getdomaininfo(0)) == NULL)
- return (-1);
-
if (server == NULL || domain == NULL) {
- server = di->server;
- domain = di->domain;
- }
+ if ((di = smb_getdomaininfo(0)) == NULL)
+ return (-1);
- switch (ipc_mode) {
- case MLSVC_IPC_USER:
- /*
- * Use the supplied credentials.
- */
- rc = mlsvc_user_logon(server, domain, username, password);
- break;
-
- case MLSVC_IPC_ADMIN:
- /*
- * Use the resource domain administrator credentials.
- */
server = di->server;
domain = di->domain;
- username = smbrdr_ipc_get_user();
+ }
- rc = mlsvc_admin_logon(server, domain);
- break;
+ if (username == NULL)
+ username = MLSVC_ANON_USER;
- case MLSVC_IPC_ANON:
- default:
- rc = mlsvc_anonymous_logon(server, domain, &username);
- break;
- }
+ rc = mlsvc_logon(server, domain, username);
if (rc != 0)
return (-1);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
index e05f51b279..a294b0ef2e 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers
@@ -52,8 +52,8 @@ SUNWprivate {
lsa_query_account_domain_info;
lsa_enum_trusted_domains;
mlsvc_init;
- mlsvc_validate_user;
mlsvc_is_local_domain;
+ mlsvc_join;
nt_group_add;
nt_group_add_groupprivs;
nt_group_add_member_byname;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
index ac8cc3003c..de20a8c934 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
@@ -34,6 +34,8 @@
#include <smbsrv/libsmb.h>
#include <smbsrv/libsmbrdr.h>
+#include <smbsrv/ndr.h>
+#include <smbsrv/mlrpc.h>
#include <smbsrv/mlsvc_util.h>
static int mlsvc_xa_init(struct mlrpc_client *, struct mlrpc_xaction *,
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c
index 14c13a0315..4a6c80613d 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c
@@ -200,7 +200,6 @@ static mts_wchar_t wcs_hostname[MAXHOSTNAMELEN];
static int hostname_len = 0;
static mts_wchar_t wcs_srcname[MAX_SRCNAME_LEN];
static int srcname_len = 0;
-static int str_offs, sh_len;
/*
* logr_initialize
@@ -214,6 +213,7 @@ logr_initialize(void)
{
struct utsname name;
char *sysname;
+ int len;
if (uname(&name) < 0)
sysname = "Solaris";
@@ -221,6 +221,10 @@ logr_initialize(void)
sysname = name.sysname;
(void) strlcpy(logr_sysname, sysname, SYS_NMLN);
+ len = strlen(logr_sysname) + 1;
+ (void) mts_mbstowcs(wcs_srcname, logr_sysname, len);
+ srcname_len = len * sizeof (mts_wchar_t);
+
(void) mlrpc_register_service(&logr_service);
}
@@ -244,7 +248,7 @@ logr_s_EventLogClose(void *arg, struct mlrpc_xaction *mxa)
return (MLRPC_DRC_OK);
}
- data = (read_data_t *)(desc->discrim);
+ data = (read_data_t *)(uintptr_t)(desc->discrim);
free(data);
(void) mlsvc_put_handle((ms_handle_t *)&param->handle);
@@ -267,12 +271,16 @@ logr_s_EventLogOpen(void *arg, struct mlrpc_xaction *mxa)
struct logr_EventLogOpen *param = arg;
ms_handle_t *handle;
int log_enable = 0;
+ int len;
+ int rc;
smb_config_rdlock();
log_enable = smb_config_getyorn(SMB_CI_LOGR_ENABLE);
smb_config_unlock();
- if (log_enable == 0) {
+ rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1);
+
+ if (log_enable == 0 || rc != 0) {
bzero(&param->handle, sizeof (logr_handle_t));
param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
return (MLRPC_DRC_OK);
@@ -281,20 +289,9 @@ logr_s_EventLogOpen(void *arg, struct mlrpc_xaction *mxa)
handle = mlsvc_get_handle(MLSVC_IFSPEC_LOGR, LOGR_KEY, 0);
bcopy(handle, &param->handle, sizeof (logr_handle_t));
- if (hostname_len == 0) {
- if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) {
- bzero(&param->handle, sizeof (logr_handle_t));
- param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
- return (MLRPC_DRC_OK);
- }
-
- hostname_len = (strlen(hostname) + 1) * 2;
- (void) mts_mbstowcs(wcs_hostname, hostname, hostname_len / 2);
- srcname_len = (strlen(logr_sysname) + 1) * 2;
- (void) mts_mbstowcs(wcs_srcname, logr_sysname, srcname_len / 2);
- sh_len = srcname_len + hostname_len;
- str_offs = 12 * sizeof (DWORD) + 4 * sizeof (WORD) + sh_len;
- }
+ len = strlen(hostname) + 1;
+ (void) mts_mbstowcs(wcs_hostname, hostname, len);
+ hostname_len = len * sizeof (mts_wchar_t);
param->status = NT_STATUS_SUCCESS;
return (MLRPC_DRC_OK);
@@ -337,7 +334,7 @@ logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa)
return (MLRPC_DRC_OK);
}
- desc->discrim = (DWORD)data;
+ desc->discrim = (DWORD)(uintptr_t)data;
param->rec_num = data->tot_recnum;
param->status = NT_STATUS_SUCCESS;
return (MLRPC_DRC_OK);
@@ -362,7 +359,7 @@ logr_s_EventLogGetOldestRec(void *arg, struct mlrpc_xaction *mxa)
return (MLRPC_DRC_OK);
}
- data = (read_data_t *)desc->discrim;
+ data = (read_data_t *)(uintptr_t)desc->discrim;
param->oldest_rec = data->log.ix - data->tot_recnum;
param->status = NT_STATUS_SUCCESS;
return (MLRPC_DRC_OK);
@@ -413,8 +410,13 @@ log_get_entry(struct log_info *linfo, int entno)
static void
set_logrec(log_entry_t *le, DWORD recno, logr_record_t *rec)
{
+ int str_offs;
+ int sh_len;
int len;
+ sh_len = srcname_len + hostname_len;
+ str_offs = 12 * sizeof (DWORD) + 4 * sizeof (WORD) + sh_len;
+
rec->Length1 = sizeof (logr_record_t);
rec->Reserved = 0x654C664C;
rec->RecordNumber = recno;
@@ -469,14 +471,14 @@ logr_s_EventLogRead(void *arg, struct mlrpc_xaction *mxa)
return (MLRPC_DRC_OK);
}
- rdata = (read_data_t *)(desc->discrim);
+ rdata = (read_data_t *)(uintptr_t)(desc->discrim);
if (rdata == 0) {
if ((rdata = logr_get_snapshot()) == NULL) {
param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
return (MLRPC_DRC_OK);
}
- desc->discrim = (DWORD)rdata;
+ desc->discrim = (DWORD)(uintptr_t)rdata;
}
dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ? FWD : REW;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c
index 6aa4d716fe..4d770edbc1 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c
@@ -36,6 +36,7 @@
#include <grp.h>
#include <smbsrv/libsmb.h>
+#include <smbsrv/libmlrpc.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/mlsvc_util.h>
#include <smbsrv/ndl/lsarpc.ndl>
@@ -53,6 +54,8 @@ struct local_group_table {
char *name;
};
+static int lsarpc_call_stub(struct mlrpc_xaction *mxa);
+
static int lsarpc_s_CloseHandle(void *arg, struct mlrpc_xaction *);
static int lsarpc_s_QuerySecurityObject(void *arg, struct mlrpc_xaction *);
static int lsarpc_s_EnumAccounts(void *arg, struct mlrpc_xaction *);
@@ -117,9 +120,9 @@ static mlrpc_service_t lsarpc_service = {
"12345778-1234-abcd-ef000123456789ab", 0, /* abstract */
"8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */
0, /* no bind_instance_size */
- 0, /* no bind_req() */
- 0, /* no unbind_and_close() */
- 0, /* use generic_call_stub() */
+ NULL, /* no bind_req() */
+ NULL, /* no unbind_and_close() */
+ lsarpc_call_stub, /* call_stub() */
&TYPEINFO(lsarpc_interface), /* interface ti */
lsarpc_stub_table /* stub_table */
};
@@ -135,9 +138,9 @@ static mlrpc_service_t lsarpc_w2k_service = {
"3919286a-b10c-11d0-9ba800c04fd92ef5", 0, /* abstract */
"8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */
0, /* no bind_instance_size */
- 0, /* no bind_req() */
- 0, /* no unbind_and_close() */
- 0, /* use generic_call_stub() */
+ NULL, /* no bind_req() */
+ NULL, /* no unbind_and_close() */
+ lsarpc_call_stub, /* call_stub() */
&TYPEINFO(lsarpc_interface), /* interface ti */
lsarpc_stub_table /* stub_table */
};
@@ -159,6 +162,18 @@ lsarpc_initialize(void)
}
/*
+ * Custom call_stub to set the stream string policy.
+ */
+static int
+lsarpc_call_stub(struct mlrpc_xaction *mxa)
+{
+ MLNDS_SETF(&mxa->send_mlnds, MLNDS_F_NOTERM);
+ MLNDS_SETF(&mxa->recv_mlnds, MLNDS_F_NOTERM);
+
+ return (mlrpc_generic_call_stub(mxa));
+}
+
+/*
* lsarpc_s_OpenDomainHandle opnum=0x06
*
* This is a request to open the LSA (OpenPolicy and OpenPolicy2).
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c
index 3b51c05e71..6d22e62127 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c
@@ -36,6 +36,7 @@
#include <grp.h>
#include <smbsrv/libsmb.h>
+#include <smbsrv/libmlrpc.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/ntsid.h>
#include <smbsrv/smbinfo.h>
@@ -66,6 +67,8 @@
#define SAMR_BUILTIN_DOMAIN 0x80000003
#define SAMR_PRIMARY_DOMAIN 0x80000004
+static int samr_call_stub(struct mlrpc_xaction *mxa);
+
static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
struct mlrpc_xaction *);
@@ -79,9 +82,9 @@ static mlrpc_service_t samr_service = {
"12345778-1234-abcd-ef000123456789ac", 1, /* abstract */
"8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */
0, /* no bind_instance_size */
- 0, /* no bind_req() */
- 0, /* no unbind_and_close() */
- 0, /* use generic_call_stub() */
+ NULL, /* no bind_req() */
+ NULL, /* no unbind_and_close() */
+ samr_call_stub, /* call_stub() */
&TYPEINFO(samr_interface), /* interface ti */
samr_stub_table /* stub_table */
};
@@ -100,6 +103,18 @@ samr_initialize(void)
}
/*
+ * Custom call_stub to set the stream string policy.
+ */
+static int
+samr_call_stub(struct mlrpc_xaction *mxa)
+{
+ MLNDS_SETF(&mxa->send_mlnds, MLNDS_F_NOTERM);
+ MLNDS_SETF(&mxa->recv_mlnds, MLNDS_F_NOTERM);
+
+ return (mlrpc_generic_call_stub(mxa));
+}
+
+/*
* samr_s_ConnectAnon
*
* This is a request to connect to the local SAM database. We don't
@@ -435,7 +450,7 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa)
return (MLRPC_DRC_FAULT_REQUEST_OPNUM_INVALID);
};
- param->address = (DWORD)&param->ru;
+ param->address = (DWORD)(uintptr_t)&param->ru;
param->switch_value = param->info_level;
return (MLRPC_DRC_OK);
}
@@ -1140,7 +1155,7 @@ samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa)
goto query_alias_err;
};
- param->address = (DWORD)&param->ru;
+ param->address = (DWORD)(uintptr_t)&param->ru;
param->status = 0;
return (MLRPC_DRC_OK);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
index 2a9a1f52d0..26cd32ac5d 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c
@@ -512,7 +512,8 @@ srvsvc_s_NetShareSetInfo(void *arg, struct mlrpc_xaction *mxa)
struct mlsm_NetShareSetInfo *param = arg;
(void) memset(param, 0, sizeof (struct mlsm_NetShareSetInfo));
- param->parm_err_ptr = (DWORD)MLRPC_HEAP_MALLOC(mxa, sizeof (DWORD));
+ param->parm_err_ptr = (DWORD)(uintptr_t)MLRPC_HEAP_MALLOC(mxa,
+ sizeof (DWORD));
param->parm_err = 0;
smb_config_rdlock();
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
index 29cd3f058a..81e3893781 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
@@ -377,32 +377,15 @@ mlsvc_setadmin_user_info(smb_userinfo_t *user_info)
int
mlsvc_string_save(ms_string_t *ms, char *str, struct mlrpc_xaction *mxa)
{
- int length;
- char *p;
-
- if (ms == NULL || str == NULL || mxa == NULL)
+ if (str == NULL)
return (0);
- /*
- * Windows NT expects the name length to exclude the
- * terminating wchar null but doesn't care whether or
- * not the allosize includes it. Windows 2000 insists
- * that both the length and the allosize include the
- * wchar null.
- */
- length = mts_wcequiv_strlen(str);
- ms->allosize = length + sizeof (mts_wchar_t);
-
- if (mxa->context->user_ctx->du_native_os == NATIVE_OS_WIN2000)
- ms->length = ms->allosize;
- else
- ms->length = length;
+ ms->length = mts_wcequiv_strlen(str);
+ ms->allosize = ms->length + sizeof (mts_wchar_t);
- if ((p = MLRPC_HEAP_STRSAVE(mxa, str)) == NULL) {
+ if ((ms->str = MLRPC_HEAP_STRSAVE(mxa, str)) == NULL)
return (0);
- }
- ms->str = (LPTSTR)p;
return (1);
}
@@ -451,13 +434,12 @@ mlsvc_is_null_handle(mlsvc_handle_t *handle)
}
/*
- * mlsvc_validate_user
+ * mlsvc_join
*
* Returns NT status codes.
*/
DWORD
-mlsvc_validate_user(char *server, char *domain, char *plain_user,
- char *plain_text)
+mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text)
{
smb_auth_info_t auth;
smb_ntdomain_t *di;
@@ -487,7 +469,7 @@ mlsvc_validate_user(char *server, char *domain, char *plain_user,
return (status);
}
- erc = mlsvc_user_logon(server, domain, plain_user, plain_text);
+ erc = mlsvc_logon(server, domain, plain_user);
if (erc == AUTH_USER_GRANT) {
int isenabled;
@@ -496,20 +478,12 @@ mlsvc_validate_user(char *server, char *domain, char *plain_user,
isenabled = smb_config_getyorn(SMB_CI_ADS_ENABLE);
smb_config_unlock();
if (isenabled) {
- if (adjoin(machine_passwd,
- sizeof (machine_passwd)) == ADJOIN_SUCCESS) {
+ if (ads_join(plain_user, plain_text, machine_passwd,
+ sizeof (machine_passwd)) == ADJOIN_SUCCESS)
status = NT_STATUS_SUCCESS;
- } else {
+ else
status = NT_STATUS_UNSUCCESSFUL;
- }
} else {
- /*
- * Ensure that we don't have an old account in
- * this domain. There's no need to check the
- * return status.
- */
- (void) sam_remove_trust_account(server, domain);
-
if (mlsvc_user_getauth(server, plain_user, &auth)
!= 0) {
status = NT_STATUS_INVALID_PARAMETER;
@@ -526,13 +500,8 @@ mlsvc_validate_user(char *server, char *domain, char *plain_user,
}
if (status == NT_STATUS_SUCCESS) {
- smb_config_wrlock();
- if (smb_config_set(SMB_CI_MACHINE_PASSWD,
- machine_passwd) != 0) {
- smb_config_unlock();
+ if (smb_set_machine_pwd(machine_passwd) != 0)
return (NT_STATUS_UNSUCCESSFUL);
- }
- smb_config_unlock();
/*
* If we successfully create a trust account, we mark
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c
index bd2d5ee26f..9dd5696526 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c
@@ -356,7 +356,7 @@ winreg_s_QueryValue(void *arg, struct mlrpc_xaction *mxa)
pv->vc_first_is = 0;
pv->vc_length_is = slen;
/*LINTED E_BAD_PTR_CAST_ALIGN*/
- (void) mts_mbstowcs((mts_wchar_t *)pv->value, value, slen);
+ (void) ndr_mbstowcs(NULL, (mts_wchar_t *)pv->value, value, slen);
*param->type = 1;
*param->value_size = slen;
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c
index 2eb3e78bb7..1b26087fb8 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c
@@ -40,6 +40,7 @@
#include <ctype.h>
#include <smbsrv/libsmb.h>
+#include <smbsrv/libsmbrdr.h>
#include <smbsrv/mlsvc_util.h>
#include <smbsrv/ndl/netlogon.ndl>
#include <smbsrv/ntstatus.h>
@@ -74,7 +75,7 @@ netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags)
{
netr_info_t *netr_info;
int rc;
- DWORD random_challenge[2];
+ DWORD leout_rc[2];
netr_info = &netr_global_info;
bzero(netr_info, sizeof (netr_info_t));
@@ -88,10 +89,9 @@ netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags)
(void) snprintf(netr_info->server, sizeof (netr_info->server),
"\\\\%s", server);
- random_challenge[0] = random();
- random_challenge[1] = random();
-
- (void) memcpy(&netr_info->client_challenge, random_challenge,
+ LE_OUT32(&leout_rc[0], random());
+ LE_OUT32(&leout_rc[1], random());
+ (void) memcpy(&netr_info->client_challenge, leout_rc,
sizeof (struct netr_credential));
if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) {
@@ -118,12 +118,12 @@ netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle)
int remote_os = 0;
int remote_lm = 0;
int server_pdc;
- char *username;
+ char *user = smbrdr_ipc_get_user();
- if (mlsvc_anonymous_logon(server, domain, &username) != 0)
+ if (mlsvc_logon(server, domain, user) != 0)
return (-1);
- fid = mlsvc_open_pipe(server, domain, username, "\\NETLOGON");
+ fid = mlsvc_open_pipe(server, domain, user, "\\NETLOGON");
if (fid < 0)
return (-1);
@@ -293,7 +293,7 @@ netr_gen_session_key(netr_info_t *netr_info)
DWORD *server_challenge;
int rc;
char *machine_passwd;
- DWORD new_data[2];
+ DWORD le_data[2];
client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge;
server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge;
@@ -324,10 +324,10 @@ netr_gen_session_key(netr_info_t *netr_info)
data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]);
data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]);
- LE_OUT32(&new_data[0], data[0]);
- LE_OUT32(&new_data[1], data[1]);
+ LE_OUT32(&le_data[0], data[0]);
+ LE_OUT32(&le_data[1], data[1]);
- rc = smb_auth_DES(buffer, 8, md4hash, 8, (unsigned char *)new_data, 8);
+ rc = smb_auth_DES(buffer, 8, md4hash, 8, (unsigned char *)le_data, 8);
if (rc != SMBAUTH_SUCCESS)
return (rc);
@@ -369,15 +369,19 @@ netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge,
unsigned char buffer[8];
unsigned char partial_key[8];
DWORD data[2];
+ DWORD le_data[2];
DWORD *p;
int rc;
p = (DWORD *)(uintptr_t)challenge;
- data[0] = p[0] + LE_IN32(&timestamp);
- data[1] = p[1];
+ data[0] = LE_IN32(&p[0]) + timestamp;
+ data[1] = LE_IN32(&p[1]);
+
+ LE_OUT32(&le_data[0], data[0]);
+ LE_OUT32(&le_data[1], data[1]);
if (smb_auth_DES(buffer, 8, session_key, 8,
- (unsigned char *)data, 8) != SMBAUTH_SUCCESS)
+ (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS)
return (SMBAUTH_FAILURE);
bzero(partial_key, 8);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c
index d26d6f0dc7..93079001e9 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c
@@ -445,11 +445,7 @@ netr_setup_authenticator(netr_info_t *netr_info,
{
bzero(auth, sizeof (struct netr_authenticator));
-#ifdef _BIG_ENDIAN
- netr_info->timestamp = 0;
-#else
- netr_info->timestamp = time(0) << 8;
-#endif
+ netr_info->timestamp = time(0);
auth->timestamp = netr_info->timestamp;
if (netr_gen_credentials(netr_info->session_key,
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c
index aa75c2678e..ef303a8b21 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c
@@ -35,6 +35,7 @@
#include <alloca.h>
#include <smbsrv/libsmb.h>
+#include <smbsrv/libsmbrdr.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/ntaccess.h>
@@ -68,7 +69,7 @@ static int get_user_group_info(mlsvc_handle_t *, smb_userinfo_t *);
*/
int
sam_lookup_user_info(char *server, char *domain_name,
- char *account_name, char *password, smb_userinfo_t *user_info)
+ char *account_name, smb_userinfo_t *user_info)
{
mlsvc_handle_t samr_handle;
mlsvc_handle_t domain_handle;
@@ -86,35 +87,30 @@ sam_lookup_user_info(char *server, char *domain_name,
return (-1);
}
- rc = samr_open(MLSVC_IPC_USER, server, domain_name, account_name,
- password, SAM_LOOKUP_INFORMATION, &samr_handle);
- if (rc != 0)
- return (-1);
-#if 0
- rc = samr_lookup_domain(&samr_handle, domain_name, user_info);
+ rc = samr_open(server, domain_name, account_name,
+ SAM_LOOKUP_INFORMATION, &samr_handle);
if (rc != 0)
return (-1);
-#endif
sid = (struct samr_sid *)user_info->domain_sid;
status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION,
sid, &domain_handle);
if (status == 0) {
-#if 0
- (void) samr_lookup_domain_names(&domain_handle, account_name,
- user_info);
-#endif
access_mask = STANDARD_RIGHTS_EXECUTE | SAM_ACCESS_USER_READ;
- rc = samr_open_user(&domain_handle, access_mask,
+ status = samr_open_user(&domain_handle, access_mask,
user_info->rid, &user_handle);
- if (rc == 0) {
+ if (status == NT_STATUS_SUCCESS) {
(void) get_user_group_info(&user_handle, user_info);
(void) samr_close_handle(&user_handle);
+ } else {
+ rc = -1;
}
(void) samr_close_handle(&domain_handle);
+ } else {
+ rc = -1;
}
(void) samr_close_handle(&samr_handle);
@@ -182,6 +178,18 @@ sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth)
auth, SAMR_AF_WORKSTATION_TRUST_ACCOUNT, user_info);
mlsvc_free_user_info(user_info);
+
+
+ /*
+ * Based on network traces, a Windows 2000 client will
+ * always try to create the computer account first.
+ * If it existed, then check the user permission to join
+ * the domain.
+ */
+
+ if (status == NT_STATUS_USER_EXISTS)
+ status = sam_check_user(server, domain, account_name);
+
return (status);
}
@@ -211,9 +219,10 @@ sam_create_account(char *server, char *domain_name, char *account_name,
DWORD rid;
DWORD status;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = samr_open(MLSVC_IPC_ADMIN, server, domain_name, 0, 0,
- SAM_CONNECT_CREATE_ACCOUNT, &samr_handle);
+ rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT,
+ &samr_handle);
if (rc != 0) {
status = NT_STATUS_OPEN_FAILED;
@@ -272,7 +281,6 @@ sam_create_account(char *server, char *domain_name, char *account_name,
user_info);
if (rc == 0)
rid = user_info->rid;
- status = 0;
} else {
smb_tracef("SamCreateAccount[%s]: %s",
account_name, xlate_nt_status(status));
@@ -332,12 +340,13 @@ sam_delete_account(char *server, char *domain_name, char *account_name)
DWORD access_mask;
DWORD status;
int rc;
+ char *user = smbrdr_ipc_get_user();
if ((user_info = mlsvc_alloc_user_info()) == 0)
return (NT_STATUS_NO_MEMORY);
- rc = samr_open(MLSVC_IPC_ADMIN, server, domain_name, 0, 0,
- SAM_LOOKUP_INFORMATION, &samr_handle);
+ rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
+ &samr_handle);
if (rc != 0) {
mlsvc_free_user_info(user_info);
@@ -379,9 +388,9 @@ sam_delete_account(char *server, char *domain_name, char *account_name)
rid = user_info->rid;
access_mask = STANDARD_RIGHTS_EXECUTE | DELETE;
- rc = samr_open_user(&domain_handle, access_mask,
+ status = samr_open_user(&domain_handle, access_mask,
rid, &user_handle);
- if (rc == 0) {
+ if (status == NT_STATUS_SUCCESS) {
if (samr_delete_user(&user_handle) != 0)
(void) samr_close_handle(&user_handle);
}
@@ -396,6 +405,94 @@ sam_delete_account(char *server, char *domain_name, char *account_name)
}
/*
+ * sam_check_user
+ *
+ * Check to see if user have permission to access computer account.
+ * The user being checked is the specified user for joining the Solaris
+ * host to the domain.
+ */
+DWORD
+sam_check_user(char *server, char *domain_name, char *account_name)
+{
+ mlsvc_handle_t samr_handle;
+ mlsvc_handle_t domain_handle;
+ mlsvc_handle_t user_handle;
+ smb_userinfo_t *user_info;
+ struct samr_sid *sid;
+ DWORD rid;
+ DWORD access_mask;
+ DWORD status;
+ int rc;
+ char *user = smbrdr_ipc_get_user();
+
+ if ((user_info = mlsvc_alloc_user_info()) == 0)
+ return (NT_STATUS_NO_MEMORY);
+
+ rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
+ &samr_handle);
+
+ if (rc != 0) {
+ mlsvc_free_user_info(user_info);
+ return (NT_STATUS_OPEN_FAILED);
+ }
+
+ if (samr_handle.context->server_os == NATIVE_OS_WIN2000) {
+ nt_domain_t *ntdp;
+
+ if ((ntdp = nt_domain_lookup_name(domain_name)) == 0) {
+ (void) lsa_query_account_domain_info();
+ if ((ntdp = nt_domain_lookup_name(domain_name)) == 0) {
+ (void) samr_close_handle(&samr_handle);
+ return (NT_STATUS_NO_SUCH_DOMAIN);
+ }
+ }
+
+ sid = (struct samr_sid *)ntdp->sid;
+ } else {
+ if (samr_lookup_domain(&samr_handle, domain_name, user_info)
+ != 0) {
+ (void) samr_close_handle(&samr_handle);
+ mlsvc_free_user_info(user_info);
+ return (NT_STATUS_NO_SUCH_DOMAIN);
+ }
+
+ sid = (struct samr_sid *)user_info->domain_sid;
+ }
+
+ status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, sid,
+ &domain_handle);
+ if (status == 0) {
+ mlsvc_release_user_info(user_info);
+ status = samr_lookup_domain_names(&domain_handle, account_name,
+ user_info);
+
+ if (status == 0) {
+ rid = user_info->rid;
+
+ /*
+ * Win2000 client uses this access mask. The
+ * following SAMR user specific rights bits are
+ * set: set password, set attributes, and get
+ * attributes.
+ */
+
+ access_mask = 0xb0;
+
+ status = samr_open_user(&domain_handle,
+ access_mask, rid, &user_handle);
+ if (status == NT_STATUS_SUCCESS)
+ (void) samr_close_handle(&user_handle);
+ }
+
+ (void) samr_close_handle(&domain_handle);
+ }
+
+ (void) samr_close_handle(&samr_handle);
+ mlsvc_free_user_info(user_info);
+ return (status);
+}
+
+/*
* sam_lookup_name
*
* Lookup an account name in the SAM database on the specified domain
@@ -413,14 +510,15 @@ sam_lookup_name(char *server, char *domain_name, char *account_name,
struct samr_sid *domain_sid;
int rc;
DWORD status;
+ char *user = smbrdr_ipc_get_user();
*rid_ret = 0;
if ((user_info = mlsvc_alloc_user_info()) == 0)
return (NT_STATUS_NO_MEMORY);
- rc = samr_open(MLSVC_IPC_ANON, server, domain_name, 0, 0,
- SAM_LOOKUP_INFORMATION, &samr_handle);
+ rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
+ &samr_handle);
if (rc != 0) {
mlsvc_free_user_info(user_info);
@@ -469,9 +567,10 @@ sam_get_local_domains(char *server, char *domain_name)
mlsvc_handle_t samr_handle;
DWORD status;
int rc;
+ char *user = smbrdr_ipc_get_user();
- rc = samr_open(MLSVC_IPC_ANON, server, domain_name, 0, 0,
- SAM_ENUM_LOCAL_DOMAIN, &samr_handle);
+ rc = samr_open(server, domain_name, user, SAM_ENUM_LOCAL_DOMAIN,
+ &samr_handle);
if (rc != 0)
return (NT_STATUS_OPEN_FAILED);
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c
index 7eccd83e22..e20b6404d7 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c
@@ -523,7 +523,8 @@ samr_set_user_logon_hours(struct samr_SetUserInfo *sui)
(void) memset(sui->logon_hours.bitmap, 0xFF, SAMR_SET_USER_HOURS_SZ);
sui->info.ru.info23.logon_info.units = SAMR_HOURS_PER_WEEK;
- sui->info.ru.info23.logon_info.hours = (DWORD)sui->logon_hours.bitmap;
+ sui->info.ru.info23.logon_info.hours =
+ (DWORD)(uintptr_t)sui->logon_hours.bitmap;
}
/*
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c
index 38dca838cd..233acdf84d 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c
@@ -66,50 +66,32 @@ static DWORD samr_connect4(char *, char *, char *, DWORD, mlsvc_handle_t *);
* name. We store the remote server's native OS type - we may need it
* due to differences between platforms like NT and Windows 2000.
*
+ * If username argument is NULL, an anonymous connection will be established.
+ * Otherwise, an authenticated connection will be established.
+ *
* On success 0 is returned. Otherwise a -ve error code.
*/
int
-samr_open(int ipc_mode, char *server, char *domain, char *username,
- char *password, DWORD access_mask, mlsvc_handle_t *samr_handle)
+samr_open(char *server, char *domain, char *username, DWORD access_mask,
+ mlsvc_handle_t *samr_handle)
{
smb_ntdomain_t *di;
int remote_os;
int remote_lm;
int rc;
- if ((di = smb_getdomaininfo(0)) == NULL)
- return (-1);
-
if (server == NULL || domain == NULL) {
- server = di->server;
- domain = di->domain;
- }
-
- switch (ipc_mode) {
- case MLSVC_IPC_USER:
- /*
- * Use the supplied credentials.
- */
- rc = mlsvc_user_logon(server, domain, username, password);
- break;
+ if ((di = smb_getdomaininfo(0)) == NULL)
+ return (-1);
- case MLSVC_IPC_ADMIN:
- /*
- * Use the resource domain administrator credentials.
- */
server = di->server;
domain = di->domain;
- username = smbrdr_ipc_get_user();
-
- rc = mlsvc_admin_logon(server, domain);
- break;
-
- case MLSVC_IPC_ANON:
- default:
- rc = mlsvc_anonymous_logon(server, domain, &username);
- break;
}
+ if (username == NULL)
+ username = MLSVC_ANON_USER;
+ rc = mlsvc_logon(server, domain, username);
+
if (rc != 0)
return (-1);
@@ -483,18 +465,18 @@ samr_open_domain(mlsvc_handle_t *samr_handle, DWORD access_mask,
* Once you have a user handle it should be possible to query the SAM
* for information on that user.
*/
-int
+DWORD
samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, DWORD rid,
mlsvc_handle_t *user_handle)
{
struct samr_OpenUser arg;
struct mlsvc_rpc_context *context;
mlrpc_heapref_t heap;
- int opnum;
- int rc;
+ int opnum, rc;
+ DWORD status = NT_STATUS_SUCCESS;
if (mlsvc_is_null_handle(domain_handle) || user_handle == NULL)
- return (-1);
+ return (NT_STATUS_INVALID_PARAMETER);
context = domain_handle->context;
opnum = SAMR_OPNUM_OpenUser;
@@ -506,22 +488,22 @@ samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, DWORD rid,
(void) mlsvc_rpc_init(&heap);
rc = mlsvc_rpc_call(context, opnum, &arg, &heap);
- if (rc == 0) {
- if (arg.status != 0) {
- mlsvc_rpc_report_status(opnum, arg.status);
- rc = -1;
- } else {
- (void) memcpy(&user_handle->handle, &arg.user_handle,
- sizeof (ms_handle_t));
- user_handle->context = context;
+ if (rc != 0) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ } else if (arg.status != 0) {
+ mlsvc_rpc_report_status(opnum, arg.status);
+ status = NT_SC_VALUE(arg.status);
+ } else {
+ (void) memcpy(&user_handle->handle, &arg.user_handle,
+ sizeof (ms_handle_t));
+ user_handle->context = context;
- if (mlsvc_is_null_handle(user_handle))
- rc = -1;
- }
+ if (mlsvc_is_null_handle(user_handle))
+ status = NT_STATUS_INVALID_HANDLE;
}
mlsvc_rpc_free(context, &heap);
- return (rc);
+ return (status);
}
/*
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
index a9810bd538..6d0610add3 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c
@@ -370,6 +370,7 @@ smb_autohome_keysub(const char *name, char *buf, int buflen)
char key[SMB_AUTOHOME_KEYSIZ];
char *ampersand;
char *tmp;
+ int bufsize = buflen;
(void) strlcpy(key, buf, SMB_AUTOHOME_KEYSIZ);
@@ -378,6 +379,12 @@ smb_autohome_keysub(const char *name, char *buf, int buflen)
*tmp = '\0';
+ /*
+ * Substitution characters are not allowed in the key.
+ */
+ if (strpbrk(key, "?&") != NULL)
+ return (NULL);
+
if (strcmp(key, "*") == 0 && name != NULL)
(void) strlcpy(key, name, SMB_AUTOHOME_KEYSIZ);
@@ -387,8 +394,9 @@ smb_autohome_keysub(const char *name, char *buf, int buflen)
if ((tmp = strdup(ampersand + 1)) == NULL)
return (0);
- (void) strlcpy(ampersand, key, buflen);
- (void) strlcat(ampersand, tmp, buflen);
+ bufsize = buflen - (ampersand - buf);
+ (void) strlcpy(ampersand, key, bufsize);
+ (void) strlcat(ampersand, tmp, bufsize);
free(tmp);
}
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c
index aa9b12d241..3dca443d1a 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_client.c
@@ -58,48 +58,31 @@ static int srvsvc_net_remote_tod(char *, char *, struct timeval *, struct tm *);
* Ensure that an appropriate session and logon exists for the srvsvc
* client calls. Open and bind the RPC interface.
*
+ * If username argument is NULL, an anonymous connection will be established.
+ * Otherwise, an authenticated connection will be established.
+ *
* On success 0 is returned. Otherwise a -ve error code.
*/
-int
-srvsvc_open(int ipc_mode, char *server, char *domain, char *username,
- char *password, mlsvc_handle_t *handle, mlrpc_heapref_t *heapref)
+static int
+srvsvc_open(char *server, char *domain, char *username,
+ mlsvc_handle_t *handle, mlrpc_heapref_t *heapref)
{
smb_ntdomain_t *di;
int fid;
int rc;
- if ((di = smb_getdomaininfo(0)) == NULL)
- return (-1);
-
if (server == NULL || domain == NULL) {
- server = di->server;
- domain = di->domain;
- }
+ if ((di = smb_getdomaininfo(0)) == NULL)
+ return (-1);
- switch (ipc_mode) {
- case MLSVC_IPC_USER:
- /*
- * Use the supplied credentials.
- */
- rc = mlsvc_user_logon(server, domain, username, password);
- break;
-
- case MLSVC_IPC_ADMIN:
- /*
- * Use the resource domain administrator credentials.
- */
server = di->server;
domain = di->domain;
- username = smbrdr_ipc_get_user();
+ }
- rc = mlsvc_admin_logon(server, domain);
- break;
+ if (username == NULL)
+ username = MLSVC_ANON_USER;
- case MLSVC_IPC_ANON:
- default:
- rc = mlsvc_anonymous_logon(server, domain, &username);
- break;
- }
+ rc = mlsvc_logon(server, domain, username);
if (rc != 0)
return (-1);
@@ -145,18 +128,16 @@ srvsvc_net_share_get_info(char *server, char *domain, char *netname)
struct mslm_NetShareGetInfo0 *info0;
struct mslm_NetShareGetInfo1 *info1;
struct mslm_NetShareGetInfo2 *info2;
- int ipc_mode;
int len;
+ char *user = NULL;
if (netname == NULL)
return (-1);
if (srvsvc_info_level == 2)
- ipc_mode = MLSVC_IPC_ADMIN;
- else
- ipc_mode = MLSVC_IPC_ANON;
+ user = smbrdr_ipc_get_user();
- rc = srvsvc_open(ipc_mode, server, domain, 0, 0, &handle, &heap);
+ rc = srvsvc_open(server, domain, user, &handle, &heap);
if (rc != 0)
return (-1);
@@ -240,11 +221,12 @@ srvsvc_net_session_enum(char *server, char *domain, char *netname)
struct mslm_infonres infonres;
struct mslm_SESSION_INFO_1 *nsi1;
int len;
+ char *user = smbrdr_ipc_get_user();
if (netname == NULL)
return (-1);
- rc = srvsvc_open(MLSVC_IPC_ADMIN, server, domain, 0, 0, &handle, &heap);
+ rc = srvsvc_open(server, domain, user, &handle, &heap);
if (rc != 0)
return (-1);
@@ -305,11 +287,12 @@ srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level)
struct mslm_NetConnectInfo0 info0;
struct mslm_NetConnectInfoBuf1 *cib1;
int len;
+ char *user = smbrdr_ipc_get_user();
if (netname == NULL)
return (-1);
- rc = srvsvc_open(MLSVC_IPC_ADMIN, server, domain, 0, 0, &handle, &heap);
+ rc = srvsvc_open(server, domain, user, &handle, &heap);
if (rc != 0)
return (-1);
@@ -476,8 +459,9 @@ srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv,
int rc;
int opnum;
int len;
+ char *user = smbrdr_ipc_get_user();
- rc = srvsvc_open(MLSVC_IPC_ANON, server, domain, 0, 0, &handle, &heap);
+ rc = srvsvc_open(server, domain, user, &handle, &heap);
if (rc != 0)
return (-1);
diff --git a/usr/src/lib/smbsrv/libmlsvc/i386/Makefile b/usr/src/lib/smbsrv/libmlsvc/i386/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libmlsvc/i386/Makefile
+++ b/usr/src/lib/smbsrv/libmlsvc/i386/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile b/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile
+++ b/usr/src/lib/smbsrv/libmlsvc/sparc/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile b/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile
index a2f97019c8..e18b286b0a 100644
--- a/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile
+++ b/usr/src/lib/smbsrv/libmlsvc/sparcv9/Makefile
@@ -25,7 +25,17 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+# With the adition of BIND 8.3.3, the symbol table for 64 bit went over
+# the limit for Kpic, so we add -KPIC here, for just the 64 bit SPARC
+# library. This avoids compiling the 32-bit library with PIC unnecessarily.
+sparcv9_C_PICFLAGS = -K PIC
+sparcv9_CC_PICFLAGS = -KPIC
+
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com
index c479406282..3771f7d993 100644
--- a/usr/src/lib/smbsrv/libsmb/Makefile.com
+++ b/usr/src/lib/smbsrv/libsmb/Makefile.com
@@ -76,6 +76,7 @@ include ../../Makefile.lib
INCS += -I$(SRC)/common/smbsrv
+LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lidmap
CPPFLAGS += $(INCS) -D_REENTRANT
diff --git a/usr/src/lib/smbsrv/libsmb/amd64/Makefile b/usr/src/lib/smbsrv/libsmb/amd64/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libsmb/amd64/Makefile
+++ b/usr/src/lib/smbsrv/libsmb/amd64/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 44da30085d..510f68c20d 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -279,6 +279,7 @@ extern int smb_config_set_secmode(int secmode);
extern int smb_config_set_idmap_domain(char *value);
extern int smb_config_set_idmap_gc(char *value);
extern int smb_config_refresh_idmap(void);
+extern int smb_config_refresh(void);
/* smb_door_client.c */
typedef struct smb_joininfo {
@@ -292,8 +293,10 @@ typedef struct smb_joininfo {
extern int smbd_set_param(smb_cfg_id_t, char *);
extern int smbd_get_param(smb_cfg_id_t, char *);
extern int smbd_get_security_mode(int *);
+extern int smb_set_machine_pwd(char *);
extern int smbd_netbios_reconfig(void);
extern uint32_t smb_join(smb_joininfo_t *info);
+extern int smb_ads_domain_change_notify(char *);
#define SMB_DOMAIN_NOMACHINE_SID -1
@@ -305,7 +308,7 @@ extern int nt_domain_init(char *resource_domain, uint32_t secmode);
extern int smb_wins_allow_list(char *config_list, char *allow_list);
extern int smb_wins_exclude_list(char *config_list, char *exclude_list);
extern boolean_t smb_wins_is_excluded(in_addr_t ipaddr,
- unsigned long *exclude_list, int nexclude);
+ ipaddr_t *exclude_list, int nexclude);
extern void smb_wins_build_list(char *buf, uint32_t iplist[], int max_naddr);
extern int smb_wins_iplist(char *list, uint32_t iplist[], int max_naddr);
diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
index 05c89f93ff..3fa172f5d6 100644
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
@@ -108,6 +108,7 @@ SUNWprivate {
oemstounicodes;
rand_hash;
randomize;
+ smb_ads_domain_change_notify;
smb_auth_DES;
smb_auth_gen_session_key;
smb_auth_ntlm_hash;
@@ -125,12 +126,12 @@ SUNWprivate {
smb_config_getyorn;
smb_config_load;
smb_config_rdlock;
+ smb_config_refresh;
smb_config_refresh_idmap;
smb_config_secmode_fromstr;
smb_config_secmode_tostr;
smb_config_set;
smb_config_set_idmap_domain;
- smb_config_set_idmap_gc;
smb_config_set_secmode;
smb_config_setenv;
smb_config_setnum;
@@ -259,6 +260,7 @@ SUNWprivate {
smb_pwd_setcntl;
smb_pwd_setpasswd;
smb_set_domain_member;
+ smb_set_machine_pwd;
smb_setdomaininfo;
smb_smf_create_instance_pgroup;
smb_smf_create_service_pgroup;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
index 844789e367..84d95609e5 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
@@ -65,8 +65,7 @@ typedef struct smb_cfg_param {
/* idmap SMF fmri and Property Group */
#define IDMAP_FMRI_PREFIX "system/idmap"
#define MACHINE_SID "machine_sid"
-#define MAPPING_DOMAIN "mapping_domain"
-#define GLOBAL_CATALOG "global_catalog"
+#define IDMAP_DOMAIN "domain_name"
#define IDMAP_PG_NAME "config"
#define SMB_SECMODE_WORKGRP_STR "workgroup"
@@ -1014,25 +1013,13 @@ smb_config_get_localsid(void)
/*
* smb_config_set_idmap_domain
*
- * Set the "config/mapping_domain" parameter from IDMAP SMF repository.
+ * Set the "config/domain_name" parameter from IDMAP SMF repository.
*/
int
smb_config_set_idmap_domain(char *value)
{
return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
- MAPPING_DOMAIN, value));
-}
-
-/*
- * smb_config_set_idmap_gc
- *
- * Set the "config/global_catalog" parameter from IDMAP SMF repository.
- */
-int
-smb_config_set_idmap_gc(char *value)
-{
- return (smb_config_setenv_generic(IDMAP_FMRI_PREFIX, IDMAP_PG_NAME,
- GLOBAL_CATALOG, value));
+ IDMAP_DOMAIN, value));
}
/*
@@ -1050,6 +1037,17 @@ smb_config_refresh_idmap(void)
return (smf_refresh_instance(instance));
}
+/*
+ * smb_config_refresh
+ *
+ * Refresh SMB SMF service.
+ */
+int
+smb_config_refresh(void)
+{
+ return (smf_refresh_instance(SMBD_DEFAULT_INSTANCE_FMRI));
+}
+
int
smb_config_secmode_fromstr(char *secmode)
{
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c
index 7e09b237b3..06eeac365c 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c
@@ -36,6 +36,7 @@
#include <strings.h>
#include <stdlib.h>
#include <errno.h>
+#include <unistd.h>
#include <smbsrv/smbinfo.h>
#include <smbsrv/wintypes.h>
@@ -53,6 +54,7 @@ static char *smbd_desc[] = {
"SmbdGetParam",
"SmbdSetParam",
"SmbdNetbiosReconfig",
+ "SmbdAdsDomainChanged",
0
};
@@ -409,3 +411,95 @@ smbd_get_security_mode(int *mode)
*mode = smb_config_secmode_fromstr(buf);
return (rc);
}
+
+/*
+ * smb_ads_domain_change_notify
+ *
+ * When ADS domain has changed, this function is called to clear the
+ * ADS_HOST_INFO cache and remove the old keys from the Kerberos keytab.
+ */
+int
+smb_ads_domain_change_notify(char *dom)
+{
+ door_arg_t arg;
+ char *buf;
+ uint32_t used;
+ smb_dr_ctx_t *dec_ctx;
+ smb_dr_ctx_t *enc_ctx;
+ int status;
+ int rc;
+ int opcode = SMBD_DOOR_ADS_DOMAIN_CHANGED;
+
+ if (smbd_door_open(opcode) == -1) {
+ syslog(LOG_ERR, "%s: cannot open the door", smbd_desc[opcode]);
+ return (1);
+ }
+
+ buf = MEM_MALLOC("smb_door_client", SMBD_DOOR_SIZE);
+ if (!buf) {
+ syslog(LOG_ERR, "%s: resource shortage", smbd_desc[opcode]);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+ return (1);
+ }
+
+ enc_ctx = smb_dr_encode_start(buf, SMBD_DOOR_SIZE);
+ if (enc_ctx == 0) {
+ syslog(LOG_ERR, "%s: encode start failed", smbd_desc[opcode]);
+ MEM_FREE("smb_door_client", buf);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+ return (1);
+ }
+
+ smb_dr_put_uint32(enc_ctx, opcode);
+ smb_dr_put_string(enc_ctx, dom);
+
+ if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) {
+ syslog(LOG_ERR, "%s: Encode error %s",
+ smbd_desc[opcode], strerror(status));
+ MEM_FREE("smb_door_client", buf);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+ return (1);
+ }
+
+ arg.data_ptr = buf;
+ arg.data_size = used;
+ arg.desc_ptr = NULL;
+ arg.desc_num = 0;
+ arg.rbuf = buf;
+ arg.rsize = SMBD_DOOR_SIZE;
+
+ if (door_call(smb_door_fildes, &arg) < 0) {
+ syslog(LOG_ERR, "%s: Door call failed %s", smbd_desc[opcode],
+ strerror(errno));
+ MEM_FREE("smb_door_client", buf);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+ return (1);
+ }
+
+ dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size);
+ if (smbd_door_check_srv_status(opcode, dec_ctx) != 0) {
+ MEM_FREE("smb_door_client", buf);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+ return (1);
+ }
+ rc = smb_dr_get_uint32(dec_ctx);
+
+ if ((status = smb_dr_decode_finish(dec_ctx)) != 0) {
+ syslog(LOG_ERR, "%s: Decode error %s",
+ smbd_desc[opcode], strerror(status));
+ MEM_FREE("smb_door_client", buf);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+ return (1);
+ }
+ MEM_FREE("smb_door_client", buf);
+ (void) close(smb_door_fildes);
+ smb_door_fildes = -1;
+
+ return (rc);
+}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
index 24d7b1b3d1..d39eaf9208 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
@@ -112,6 +112,22 @@ smb_set_domain_member(int set)
}
/*
+ * smb_set_machine_pwd
+ *
+ * Returns 0 upon success. Otherwise, returns 1.
+ */
+int
+smb_set_machine_pwd(char *pwd)
+{
+ int rc;
+
+ smb_config_wrlock();
+ rc = smb_config_set(SMB_CI_MACHINE_PASSWD, pwd);
+ smb_config_unlock();
+ return (rc);
+}
+
+/*
* smb_getdomaininfo
*
* Returns a pointer to the cached domain data. The caller can specify
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_wins.c b/usr/src/lib/smbsrv/libsmb/common/smb_wins.c
index 09498abfca..eb3a5216f4 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_wins.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_wins.c
@@ -89,8 +89,7 @@ smb_wins_iplist(char *list, uint32_t iplist[], int max_naddr)
* Returns 1 if it's excluded, 0 if it's not.
*/
boolean_t
-smb_wins_is_excluded(in_addr_t ipaddr,
- unsigned long *exclude_list, int nexclude)
+smb_wins_is_excluded(in_addr_t ipaddr, ipaddr_t *exclude_list, int nexclude)
{
int i;
diff --git a/usr/src/lib/smbsrv/libsmb/i386/Makefile b/usr/src/lib/smbsrv/libsmb/i386/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libsmb/i386/Makefile
+++ b/usr/src/lib/smbsrv/libsmb/i386/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libsmb/sparc/Makefile b/usr/src/lib/smbsrv/libsmb/sparc/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libsmb/sparc/Makefile
+++ b/usr/src/lib/smbsrv/libsmb/sparc/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile
+++ b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libsmbns/Makefile.com b/usr/src/lib/smbsrv/libsmbns/Makefile.com
index 2166b2640d..f4a45a3cac 100644
--- a/usr/src/lib/smbsrv/libsmbns/Makefile.com
+++ b/usr/src/lib/smbsrv/libsmbns/Makefile.com
@@ -52,6 +52,7 @@ include ../../Makefile.lib
SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \
$(OBJS_SHARED:%.o=$(SRC)/common/smbsrv/%.c)
+LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lsmb -lgss -lldap -lresolv -lnsl -lsocket -lc
CPPFLAGS += -D_REENTRANT
diff --git a/usr/src/lib/smbsrv/libsmbns/amd64/Makefile b/usr/src/lib/smbsrv/libsmbns/amd64/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libsmbns/amd64/Makefile
+++ b/usr/src/lib/smbsrv/libsmbns/amd64/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h
index a05c197c35..01de8f7f02 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h
+++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h
@@ -43,7 +43,6 @@ extern "C" {
typedef struct ads_handle_s {
char *user; /* admin user to create share in ADS */
char *pwd; /* user password */
- char *container; /* user container in ADS */
char *domain; /* ADS domain */
char *domain_dn; /* domain in Distinquish Name format */
char *ip_addr; /* ip addr in string format */
@@ -60,18 +59,17 @@ typedef enum adjoin_status {
ADJOIN_ERR_GET_HANDLE,
ADJOIN_ERR_GEN_PASSWD,
ADJOIN_ERR_ADD_TRUST_ACCT,
+ ADJOIN_ERR_MOD_TRUST_ACCT,
ADJOIN_ERR_GET_ENCTYPES,
ADJOIN_ERR_GET_HOST_PRINC,
ADJOIN_ERR_INIT_KRB_CTX,
ADJOIN_ERR_GET_KRB_PRINC,
ADJOIN_ERR_KSETPWD,
- ADJOIN_ERR_MOD_TRUST_ACCT,
+ ADJOIN_ERR_UPDATE_CNTRL_ATTR,
ADJOIN_ERR_WRITE_KEYTAB,
ADJOIN_ERR_IDMAP_SET_DOMAIN,
- ADJOIN_ERR_IDMAP_SET_GC,
ADJOIN_ERR_IDMAP_REFRESH,
- ADJOIN_ERR_IDMAP_CCACHE,
-
+ ADJOIN_ERR_SMB_REFRESH,
ADJOIN_NUM_STATUS
} adjoin_status_t;
@@ -86,8 +84,8 @@ extern int ads_build_unc_name(char *, int, const char *, const char *);
extern int ads_lookup_share(ADS_HANDLE *, const char *, const char *, char *);
extern int ads_add_share(ADS_HANDLE *, const char *, const char *,
const char *);
-
-extern adjoin_status_t adjoin(char *, int);
+extern int ads_domain_change_notify_handler(char *);
+extern adjoin_status_t ads_join(char *, char *, char *, int);
extern char *adjoin_report_err(adjoin_status_t status);
/* DYNDNS functions */
diff --git a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers
index d20641252d..63cf1a8f5b 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers
@@ -27,11 +27,12 @@
SUNWprivate {
global:
- adjoin;
adjoin_report_err;
ads_add_share;
ads_build_unc_name;
ads_close;
+ ads_domain_change_notify_handler;
+ ads_join;
ads_lookup_share;
ads_open;
ads_publish_share;
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
index c57971e455..5ea03bbd41 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
@@ -47,6 +47,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+
#include <smbsrv/libsmbns.h>
#include <smbns_ads.h>
#include <smbns_dyndns.h>
@@ -56,6 +57,8 @@
#define ADS_MAXMSGLEN 512
#define ADS_HOST_PREFIX "host/"
#define ADS_COMPUTERS_CN "Computers"
+#define ADS_COMPUTER_NUM_ATTR 7
+#define ADS_SHARE_NUM_ATTR 3
/* current ADS server to communicate with */
ADS_HOST_INFO *ads_host_info = NULL;
@@ -72,19 +75,20 @@ static char *adjoin_errmsg[] = {
"ADJOIN failed to get handle.",
"ADJOIN failed to generate machine password.",
"ADJOIN failed to add workstation trust account.",
+ "ADJOIN failed to modify workstation trust account.",
"ADJOIN failed to get list of encryption types.",
"ADJOIN failed to get host principal.",
"ADJOIN failed to initialize kerberos context.",
- "ADJOIN failed to get kerberos principal.",
+ "ADJOIN failed to get Kerberos principal.",
"ADJOIN failed to set machine account password on AD.",
- "ADJOIN failed to modify workstation trust account.",
- "ADJOIN failed to write Keberos keytab file.",
- "ADJOIN failed to configure idmap(mapping domain).",
- "ADJOIN failed to configure idmap(global catalog).",
+ "ADJOIN failed to modify CONTROL attribute of the account.",
+ "ADJOIN failed to write Kerberos keytab file.",
+ "ADJOIN failed to configure domain_name property for idmapd.",
"ADJOIN failed to refresh idmap service."
- "ADJOIN failed to remove idmap ccache."
+ "ADJOIN failed to refresh SMB service."
};
+static ADS_HANDLE *ads_open_main(char *user, char *password);
static int ads_bind(ADS_HANDLE *);
static void ads_get_computer_dn(ADS_HANDLE *, char *, size_t);
static char *ads_get_host_principal(char *fqhost);
@@ -92,13 +96,15 @@ static char *ads_get_host_principal_w_realm(char *princ, char *domain);
static int ads_get_host_principals(char *fqhost, char *domain,
char **princ, char **princ_r);
static int ads_add_computer(ADS_HANDLE *ah);
+static int ads_modify_computer(ADS_HANDLE *ah);
static void ads_del_computer(ADS_HANDLE *ah);
+static int ads_computer_op(ADS_HANDLE *ah, int op);
static int ads_lookup_computer_n_attr(ADS_HANDLE *ah, char *attr, char **val);
-static int ads_modify_computer(ADS_HANDLE *ah, int des_only);
+static int ads_update_computer_cntrl_attr(ADS_HANDLE *ah, int des_only);
static krb5_kvno ads_lookup_computer_attr_kvno(ADS_HANDLE *ah);
static int ads_gen_machine_passwd(char *machine_passwd, int bufsz);
-static void ads_set_host_info(ADS_HOST_INFO *host);
static ADS_HOST_INFO *ads_get_host_info(void);
+static void ads_set_host_info(ADS_HOST_INFO *host);
/*
* ads_build_unc_name
@@ -728,8 +734,27 @@ ads_free_host_info(void)
/*
* ads_open
+ * Open a LDAP connection to an ADS server if the system is in domain mode.
+ * Acquire both Kerberos TGT and LDAP service tickets for the host principal.
+ *
+ * This function should only be called after the system is successfully joined
+ * to a domain.
+ */
+ADS_HANDLE *
+ads_open(void)
+{
+ uint32_t mode = smb_get_security_mode();
+
+ if (mode != SMB_SECMODE_DOMAIN)
+ return (NULL);
+
+ return (ads_open_main(NULL, NULL));
+}
+
+/*
+ * ads_open_main
* Open a LDAP connection to an ADS server.
- * If ADS is enabled and the administrative username, password, container, and
+ * If ADS is enabled and the administrative username, password, and
* ADS domain are defined then query DNS to find an ADS server if this is the
* very first call to this routine. After an ADS server is found then this
* server will be used everytime this routine is called until the system is
@@ -751,12 +776,11 @@ ads_free_host_info(void)
* ADS_HANDLE* : handle to ADS server
*/
ADS_HANDLE *
-ads_open(void)
+ads_open_main(char *user, char *password)
{
ADS_HANDLE *ah;
LDAP *ld;
int version = 3, ads_port, find_ads_retry;
- char *adminUser, *password, *container;
char domain[MAXHOSTNAMELEN];
int enable;
ADS_HOST_INFO *ads_host = NULL;
@@ -775,27 +799,10 @@ ads_open(void)
smb_config_unlock();
return (NULL);
}
- adminUser = smb_config_getstr(SMB_CI_ADS_USER);
- if (adminUser == NULL || *adminUser == 0) {
- syslog(LOG_ERR, "smb_ads: admin user is not set");
- smb_config_unlock();
- return (NULL);
- }
- password = smb_config_getstr(SMB_CI_ADS_PASSWD);
- if (password == NULL || *password == 0) {
- syslog(LOG_ERR, "smb_ads: admin user password is not set");
- smb_config_unlock();
- return (NULL);
- }
- container = smb_config_getstr(SMB_CI_ADS_USER_CONTAINER);
- if (container == NULL || *container == 0)
- container = "cn=Users";
site = smb_config_getstr(SMB_CI_ADS_SITE);
smb_config_unlock();
-
-
find_ads_retry = 0;
find_ads_host:
@@ -898,13 +905,11 @@ find_ads_host:
}
ah->ld = ld;
- ah->user = strdup(adminUser);
- ah->pwd = strdup(password);
- ah->container = strdup(container);
+ ah->user = (user) ? strdup(user) : NULL;
+ ah->pwd = (password) ? strdup(password) : NULL;
ah->domain = strdup(domain);
- if ((ah->user == NULL) || (ah->pwd == NULL) ||
- (ah->container == NULL) || (ah->domain == NULL)) {
+ if (ah->domain == NULL) {
ads_close(ah);
return (NULL);
}
@@ -966,7 +971,6 @@ ads_close(ADS_HANDLE *ah)
bzero(ah->pwd, len);
free(ah->pwd);
}
- free(ah->container);
free(ah->domain);
free(ah->domain_dn);
free(ah->hostname);
@@ -1001,16 +1005,16 @@ ads_display_stat(OM_uint32 maj, OM_uint32 min)
* free_attr
* Free memory allocated when publishing a share.
* Parameters:
- * addattrs: an array of LDAPMod pointers
+ * attrs: an array of LDAPMod pointers
* Returns:
* None
*/
static void
-free_attr(LDAPMod *addattrs[])
+free_attr(LDAPMod *attrs[])
{
int i;
- for (i = 0; addattrs[i]; i++) {
- free(addattrs[i]);
+ for (i = 0; attrs[i]; i++) {
+ free(attrs[i]);
}
}
@@ -1075,28 +1079,16 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context,
int *kinit_retry, int *do_acquire_cred)
{
OM_uint32 maj, min, time_rec;
- char service_name[ADS_MAXBUFLEN], *user_dn;
+ char service_name[ADS_MAXBUFLEN];
gss_buffer_desc send_tok, service_buf;
gss_name_t target_name;
gss_buffer_desc input;
gss_buffer_desc *inputptr;
struct berval cred;
OM_uint32 ret_flags;
- int stat, len;
+ int stat;
int gss_flags;
- /*
- * 6 additional bytes for the "cn=,, " and the null terminator
- */
- len = strlen(ah->user) + strlen(ah->container) +
- strlen(ah->domain_dn) + 6;
-
- if ((user_dn = (char *)malloc(len)) == NULL)
- return (-1);
-
- (void) snprintf(user_dn, len, "cn=%s,%s,%s", ah->user, ah->container,
- ah->domain_dn);
-
(void) snprintf(service_name, ADS_MAXBUFLEN, "ldap@%s", ah->hostname);
service_buf.value = service_name;
service_buf.length = strlen(service_name)+1;
@@ -1104,8 +1096,8 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context,
(gss_OID) gss_nt_service_name,
&target_name)) != GSS_S_COMPLETE) {
ads_display_stat(maj, min);
- (void) gss_release_oid(&min, &oid);
- free(user_dn);
+ if (oid != GSS_C_NO_OID)
+ (void) gss_release_oid(&min, &oid);
return (-1);
}
@@ -1119,9 +1111,9 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context,
gss_flags, inputptr, &send_tok,
&ret_flags, &time_rec, kinit_retry,
do_acquire_cred, &maj, "ads") == -1) {
- (void) gss_release_oid(&min, &oid);
+ if (oid != GSS_C_NO_OID)
+ (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
- free(user_dn);
return (-1);
}
@@ -1131,16 +1123,16 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context,
ber_bvfree(*sercred);
*sercred = NULL;
}
- stat = ldap_sasl_bind_s(ah->ld, user_dn, "GSSAPI",
+ stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI",
&cred, NULL, NULL, sercred);
if (stat != LDAP_SUCCESS &&
stat != LDAP_SASL_BIND_IN_PROGRESS) {
/* LINTED - E_SEC_PRINTF_VAR_FMT */
syslog(LOG_ERR, ldap_err2string(stat));
- (void) gss_release_oid(&min, &oid);
+ if (oid != GSS_C_NO_OID)
+ (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
(void) gss_release_buffer(&min, &send_tok);
- free(user_dn);
return (-1);
}
input.value = (*sercred)->bv_val;
@@ -1150,9 +1142,9 @@ ads_establish_sec_context(ADS_HANDLE *ah, gss_ctx_id_t *gss_context,
(void) gss_release_buffer(&min, &send_tok);
} while (maj != GSS_S_COMPLETE);
- (void) gss_release_oid(&min, &oid);
+ if (oid != GSS_C_NO_OID)
+ (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
- free(user_dn);
return (0);
}
@@ -1279,14 +1271,15 @@ ads_bind(ADS_HANDLE *ah)
OM_uint32 min;
gss_cred_id_t cred_handle;
gss_ctx_id_t gss_context;
- OM_uint32 maj;
gss_OID oid;
struct berval *sercred;
int kinit_retry, do_acquire_cred;
+ int rc = 0;
kinit_retry = 0;
do_acquire_cred = 0;
- acquire_cred:
+
+acquire_cred:
if (ads_acquire_cred(ah, &cred_handle, &oid, &kinit_retry))
return (-1);
@@ -1300,29 +1293,13 @@ ads_bind(ADS_HANDLE *ah)
}
return (-1);
}
+ rc = ads_negotiate_sec_layer(ah, gss_context, sercred);
- if (ads_negotiate_sec_layer(ah, gss_context, sercred)) {
+ if (cred_handle != GSS_C_NO_CREDENTIAL)
(void) gss_release_cred(&min, &cred_handle);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
- return (-1);
- }
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
- if ((maj = gss_release_cred(&min, &cred_handle))
- != GSS_S_COMPLETE) {
- syslog(LOG_ERR, "smb_ads: Can't release credential handle\n");
- ads_display_stat(maj, min);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
- return (-1);
- }
-
- if ((maj = gss_delete_sec_context(&min, &gss_context, NULL))
- != GSS_S_COMPLETE) {
- syslog(LOG_ERR, "smb_ads: Can't delete security context\n");
- ads_display_stat(maj, min);
- return (-1);
- }
-
- return (0);
+ return ((rc) ? -1 : 0);
}
/*
@@ -1347,12 +1324,11 @@ int
ads_add_share(ADS_HANDLE *ah, const char *adsShareName,
const char *unc_name, const char *adsContainer)
{
- LDAPMod *addattrs[3];
+ LDAPMod *attrs[ADS_SHARE_NUM_ATTR];
char *tmp1[5], *tmp2[5];
- int j = -1;
+ int j = 0;
char *share_dn;
char buf[ADS_MAXMSGLEN];
-
int len, ret;
len = 5 + strlen(adsShareName) + strlen(adsContainer) +
@@ -1365,37 +1341,44 @@ ads_add_share(ADS_HANDLE *ah, const char *adsShareName,
(void) snprintf(share_dn, len, "cn=%s,%s,%s", adsShareName,
adsContainer, ah->domain_dn);
- addattrs[++j] = (LDAPMod *)malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "objectClass";
+ for (j = 0; j < (ADS_SHARE_NUM_ATTR - 1); j++) {
+ attrs[j] = (LDAPMod *)malloc(sizeof (LDAPMod));
+ if (attrs[j] == NULL) {
+ free_attr(attrs);
+ free(share_dn);
+ return (-1);
+ }
+ }
+
+ j = 0;
+ attrs[j]->mod_op = LDAP_MOD_ADD;
+ attrs[j]->mod_type = "objectClass";
tmp1[0] = "top";
tmp1[1] = "leaf";
tmp1[2] = "connectionPoint";
tmp1[3] = "volume";
tmp1[4] = 0;
- addattrs[j]->mod_values = tmp1;
-
- addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "uNCName";
+ attrs[j]->mod_values = tmp1;
+ attrs[++j]->mod_op = LDAP_MOD_ADD;
+ attrs[j]->mod_type = "uNCName";
tmp2[0] = (char *)unc_name;
tmp2[1] = 0;
- addattrs[j]->mod_values = tmp2;
+ attrs[j]->mod_values = tmp2;
- addattrs[++j] = 0;
+ attrs[++j] = 0;
- if ((ret = ldap_add_s(ah->ld, share_dn, addattrs)) != LDAP_SUCCESS) {
+ if ((ret = ldap_add_s(ah->ld, share_dn, attrs)) != LDAP_SUCCESS) {
(void) snprintf(buf, ADS_MAXMSGLEN,
"ads_add_share: %s:", share_dn);
/* LINTED - E_SEC_PRINTF_VAR_FMT */
syslog(LOG_ERR, ldap_err2string(ret));
- free_attr(addattrs);
+ free_attr(attrs);
free(share_dn);
return (ret);
}
free(share_dn);
- free_attr(addattrs);
+ free_attr(attrs);
(void) snprintf(buf, ADS_MAXMSGLEN,
"Share %s has been added to ADS container: %s.\n", adsShareName,
@@ -1787,15 +1770,21 @@ ads_get_host_principal_w_realm(char *princ, char *domain)
* ads_get_host_principals
*
* If fqhost is NULL, this function will attempt to obtain fully qualified
- * hostname prior to generating the host principals.
+ * hostname prior to generating the host principals. If caller is not
+ * interested in getting the principal name without the Kerberos realm
+ * info, princ can be set to NULL.
*/
static int
ads_get_host_principals(char *fqhost, char *domain, char **princ,
char **princ_r)
{
char hostname[MAXHOSTNAMELEN];
+ char *p;
+
+ if (princ != NULL)
+ *princ = NULL;
- *princ = *princ_r = NULL;
+ *princ_r = NULL;
if (fqhost) {
(void) strlcpy(hostname, fqhost, MAXHOSTNAMELEN);
@@ -1804,16 +1793,19 @@ ads_get_host_principals(char *fqhost, char *domain, char **princ,
return (-1);
}
- if ((*princ = ads_get_host_principal(hostname)) == NULL) {
+ if ((p = ads_get_host_principal(hostname)) == NULL) {
return (-1);
}
- *princ_r = ads_get_host_principal_w_realm(*princ, domain);
+ *princ_r = ads_get_host_principal_w_realm(p, domain);
if (*princ_r == NULL) {
- free(*princ);
+ free(p);
return (-1);
}
+ if (princ != NULL)
+ *princ = p;
+
return (0);
}
@@ -1825,16 +1817,34 @@ ads_get_host_principals(char *fqhost, char *domain, char **princ,
static int
ads_add_computer(ADS_HANDLE *ah)
{
- LDAPMod *addattrs[7];
+ return (ads_computer_op(ah, LDAP_MOD_ADD));
+}
+
+/*
+ * ads_modify_computer
+ *
+ * Returns 0 upon success. Otherwise, returns -1.
+ */
+static int
+ads_modify_computer(ADS_HANDLE *ah)
+{
+ return (ads_computer_op(ah, LDAP_MOD_REPLACE));
+}
+
+static int
+ads_computer_op(ADS_HANDLE *ah, int op)
+{
+ LDAPMod *attrs[ADS_COMPUTER_NUM_ATTR];
char *oc_vals[6], *sam_val[2], *usr_val[2];
char *svc_val[2], *ctl_val[2], *fqh_val[2];
- int j = -1;
+ int j = 0;
int ret, usrctl_flags = 0;
char sam_acct[MAXHOSTNAMELEN + 1];
char fqhost[MAXHOSTNAMELEN];
char dn[ADS_DN_MAX];
char *user_principal, *svc_principal;
char usrctl_buf[16];
+ int max;
if (smb_getfqhostname(fqhost, MAXHOSTNAMELEN) != 0)
return (-1);
@@ -1847,75 +1857,96 @@ ads_add_computer(ADS_HANDLE *ah)
if (ads_get_host_principals(fqhost, ah->domain, &svc_principal,
&user_principal) == -1) {
syslog(LOG_ERR,
- "ads_add_computer: unable to get host principal");
+ "ads_computer_op: unable to get host principal");
return (-1);
}
ads_get_computer_dn(ah, dn, ADS_DN_MAX);
- addattrs[++j] = (LDAPMod *)malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "objectClass";
- oc_vals[0] = "top";
- oc_vals[1] = "person";
- oc_vals[2] = "organizationalPerson";
- oc_vals[3] = "user";
- oc_vals[4] = "computer";
- oc_vals[5] = 0;
- addattrs[j]->mod_values = oc_vals;
-
- addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "sAMAccountName";
+ max = (ADS_COMPUTER_NUM_ATTR - ((op != LDAP_MOD_ADD) ? 1 : 0));
+ for (j = 0; j < (max - 1); j++) {
+ attrs[j] = (LDAPMod *)malloc(sizeof (LDAPMod));
+ if (attrs[j] == NULL) {
+ free_attr(attrs);
+ free(user_principal);
+ free(svc_principal);
+ return (-1);
+ }
+ }
+ j = -1;
+ /* objectClass attribute is not modifiable. */
+ if (op == LDAP_MOD_ADD) {
+ attrs[++j]->mod_op = op;
+ attrs[j]->mod_type = "objectClass";
+ oc_vals[0] = "top";
+ oc_vals[1] = "person";
+ oc_vals[2] = "organizationalPerson";
+ oc_vals[3] = "user";
+ oc_vals[4] = "computer";
+ oc_vals[5] = 0;
+ attrs[j]->mod_values = oc_vals;
+ }
+
+ attrs[++j]->mod_op = op;
+ attrs[j]->mod_type = "sAMAccountName";
sam_val[0] = sam_acct;
sam_val[1] = 0;
- addattrs[j]->mod_values = sam_val;
-
-
- addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "userPrincipalName";
+ attrs[j]->mod_values = sam_val;
+ attrs[++j]->mod_op = op;
+ attrs[j]->mod_type = "userPrincipalName";
usr_val[0] = user_principal;
usr_val[1] = 0;
- addattrs[j]->mod_values = usr_val;
-
- addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "servicePrincipalName";
+ attrs[j]->mod_values = usr_val;
+ attrs[++j]->mod_op = op;
+ attrs[j]->mod_type = "servicePrincipalName";
svc_val[0] = svc_principal;
svc_val[1] = 0;
- addattrs[j]->mod_values = svc_val;
-
- addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "userAccountControl";
+ attrs[j]->mod_values = svc_val;
+ attrs[++j]->mod_op = op;
+ attrs[j]->mod_type = "userAccountControl";
usrctl_flags |= (ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
ADS_USER_ACCT_CTL_PASSWD_NOTREQD |
ADS_USER_ACCT_CTL_ACCOUNTDISABLE);
-
(void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", usrctl_flags);
ctl_val[0] = usrctl_buf;
ctl_val[1] = 0;
- addattrs[j]->mod_values = ctl_val;
- addattrs[++j] = (LDAPMod *) malloc(sizeof (LDAPMod));
- addattrs[j]->mod_op = LDAP_MOD_ADD;
- addattrs[j]->mod_type = "dNSHostName";
+ attrs[j]->mod_values = ctl_val;
+ attrs[++j]->mod_op = op;
+ attrs[j]->mod_type = "dNSHostName";
fqh_val[0] = fqhost;
fqh_val[1] = 0;
- addattrs[j]->mod_values = fqh_val;
- addattrs[++j] = 0;
+ attrs[j]->mod_values = fqh_val;
+
+ attrs[++j] = 0;
+
+ switch (op) {
+ case LDAP_MOD_ADD:
+ if ((ret = ldap_add_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
+ syslog(LOG_ERR, "ads_add_computer: %s",
+ ldap_err2string(ret));
+ ret = -1;
+ }
+ break;
+
+ case LDAP_MOD_REPLACE:
+ if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
+ syslog(LOG_ERR, "ads_modify_computer: %s",
+ ldap_err2string(ret));
+ ret = -1;
+ }
+ break;
- if ((ret = ldap_add_s(ah->ld, dn, addattrs)) != LDAP_SUCCESS) {
- syslog(LOG_ERR, "ads_add_computer: %s", ldap_err2string(ret));
+ default:
ret = -1;
+
}
- free_attr(addattrs);
+ free_attr(attrs);
free(user_principal);
free(svc_principal);
@@ -1978,8 +2009,7 @@ ads_lookup_computer_n_attr(ADS_HANDLE *ah, char *attr, char **val)
return (-1);
}
- (void) snprintf(filter, sizeof (filter),
- "(&(objectClass=computer)(sAMAccountName=%s))",
+ (void) snprintf(filter, sizeof (filter), "objectClass=computer",
tmpbuf);
if (ldap_search_s(ah->ld, dn, LDAP_SCOPE_BASE, filter, attrs, 0,
@@ -2031,7 +2061,7 @@ ads_find_computer(ADS_HANDLE *ah)
}
/*
- * ads_modify_computer
+ * ads_update_computer_cntrl_attr
*
* Modify the user account control attribute of an existing computer
* object on AD.
@@ -2039,7 +2069,7 @@ ads_find_computer(ADS_HANDLE *ah)
* Returns 0 on success. Otherwise, returns -1.
*/
static int
-ads_modify_computer(ADS_HANDLE *ah, int des_only)
+ads_update_computer_cntrl_attr(ADS_HANDLE *ah, int des_only)
{
LDAPMod *attrs[6];
char *ctl_val[2];
@@ -2090,7 +2120,7 @@ ads_lookup_computer_attr_kvno(ADS_HANDLE *ah)
char *val = NULL;
int kvno = 1;
- if (ads_lookup_computer_n_attr(ah, "ms-DS-KeyVersionNumber",
+ if (ads_lookup_computer_n_attr(ah, "msDS-KeyVersionNumber",
&val) == 1) {
if (val) {
kvno = atoi(val);
@@ -2135,11 +2165,49 @@ ads_gen_machine_passwd(char *machine_passwd, int bufsz)
}
/*
- * adjoin
+ * ads_domain_change_notify_handler
+ *
+ * Clear the host info cache and remove the old keys from the keytab
+ * as the ads_domain property has changed.
+ *
+ * domain - is the old ADS domain name.
+ */
+int
+ads_domain_change_notify_handler(char *domain)
+{
+ char *princ_r;
+ krb5_context ctx = NULL;
+ krb5_principal krb5princ;
+ int rc;
+
+ if (ads_get_host_principals(NULL, domain, NULL, &princ_r) == -1)
+ return (-1);
+
+ if (smb_krb5_ctx_init(&ctx) != 0) {
+ free(princ_r);
+ return (-1);
+ }
+
+ if (smb_krb5_get_principal(ctx, princ_r, &krb5princ) != 0) {
+ free(princ_r);
+ smb_krb5_ctx_fini(ctx);
+ return (-1);
+
+ }
+
+ rc = smb_krb5_remove_keytab_entries(ctx, krb5princ, SMBNS_KRB5_KEYTAB);
+ free(princ_r);
+ smb_krb5_ctx_fini(ctx);
+ ads_free_host_info();
+ return (rc);
+}
+
+/*
+ * ads_join
*
* Besides the NT-4 style domain join (using MS-RPC), CIFS server also
* provides the domain join using Kerberos Authentication, Keberos
- * Change & Set password, and LDAP protocols. Basically, adjoin
+ * Change & Set password, and LDAP protocols. Basically, AD join
* operation would require the following tickets to be acquired for the
* the user account that is provided for the domain join.
*
@@ -2160,36 +2228,16 @@ ads_gen_machine_passwd(char *machine_passwd, int bufsz)
* principal after the domain join operation.
*/
adjoin_status_t
-adjoin(char *machine_passwd, int len)
+ads_join(char *user, char *usr_passwd, char *machine_passwd, int len)
{
ADS_HANDLE *ah = NULL;
- krb5_enctype enctypes[10];
krb5_context ctx = NULL;
krb5_principal krb5princ;
krb5_kvno kvno;
- char *princ, *princ_r;
- int des_only, delete = 1, fini_krbctx = 1;
+ char *princ_r;
+ boolean_t des_only, delete = B_TRUE, fini_krbctx = B_TRUE;
adjoin_status_t rc = ADJOIN_SUCCESS;
- struct stat fstat;
-
- char *idmap_ccache = "/var/run/idmap/ccache";
-
- if ((ah = ads_open()) == NULL)
- return (ADJOIN_ERR_GET_HANDLE);
-
- if (ads_gen_machine_passwd(machine_passwd, len) != 0) {
- ads_close(ah);
- return (ADJOIN_ERR_GEN_PASSWD);
- }
-
- if (ads_find_computer(ah))
- ads_del_computer(ah);
-
- if (ads_add_computer(ah) != 0) {
- ads_close(ah);
- return (ADJOIN_ERR_ADD_TRUST_ACCT);
- }
-
+ boolean_t new_acct;
/*
* Call library functions that can be used to get
* the list of encryption algorithms available on the system.
@@ -2199,12 +2247,37 @@ adjoin(char *machine_passwd, int len)
* list of algorithms available on any system running Nevada
* by default.
*/
- enctypes[0] = ENCTYPE_DES_CBC_CRC;
- enctypes[1] = ENCTYPE_DES_CBC_MD5;
- enctypes[2] = ENCTYPE_ARCFOUR_HMAC;
- enctypes[3] = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
+ krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_ARCFOUR_HMAC, ENCTYPE_AES128_CTS_HMAC_SHA1_96};
+
+ if ((ah = ads_open_main(user, usr_passwd)) == NULL) {
+ (void) smb_config_refresh();
+ return (ADJOIN_ERR_GET_HANDLE);
+ }
+
+ if (ads_gen_machine_passwd(machine_passwd, len) != 0) {
+ ads_close(ah);
+ (void) smb_config_refresh();
+ return (ADJOIN_ERR_GEN_PASSWD);
+ }
- des_only = 0;
+ if (ads_find_computer(ah)) {
+ new_acct = B_FALSE;
+ if (ads_modify_computer(ah) != 0) {
+ ads_close(ah);
+ (void) smb_config_refresh();
+ return (ADJOIN_ERR_MOD_TRUST_ACCT);
+ }
+ } else {
+ new_acct = B_TRUE;
+ if (ads_add_computer(ah) != 0) {
+ ads_close(ah);
+ (void) smb_config_refresh();
+ return (ADJOIN_ERR_ADD_TRUST_ACCT);
+ }
+ }
+
+ des_only = B_FALSE;
/*
* If we are talking to a Longhorn server, we need to set up
@@ -2216,14 +2289,16 @@ adjoin(char *machine_passwd, int len)
* SmbSessionSetup request sent by SMB redirector.
*/
- if (ads_get_host_principals(NULL, ah->domain, &princ, &princ_r) == -1) {
- ads_del_computer(ah);
+ if (ads_get_host_principals(NULL, ah->domain, NULL, &princ_r) == -1) {
+ if (new_acct)
+ ads_del_computer(ah);
ads_close(ah);
+ (void) smb_config_refresh();
return (ADJOIN_ERR_GET_HOST_PRINC);
}
if (smb_krb5_ctx_init(&ctx) != 0) {
- fini_krbctx = 0;
+ fini_krbctx = B_FALSE;
rc = ADJOIN_ERR_INIT_KRB_CTX;
goto adjoin_cleanup;
}
@@ -2239,12 +2314,15 @@ adjoin(char *machine_passwd, int len)
}
kvno = ads_lookup_computer_attr_kvno(ah);
- if (ads_modify_computer(ah, des_only) != 0) {
- rc = ADJOIN_ERR_MOD_TRUST_ACCT;
+
+ if (ads_update_computer_cntrl_attr(ah, des_only) != 0) {
+ rc = ADJOIN_ERR_UPDATE_CNTRL_ATTR;
goto adjoin_cleanup;
}
- if (smb_krb5_write_keytab(ctx, krb5princ, "/etc/krb5/krb5.keytab", kvno,
- machine_passwd, enctypes, 4) != 0) {
+
+ if (smb_krb5_update_keytab_entries(ctx, krb5princ, SMBNS_KRB5_KEYTAB,
+ kvno, machine_passwd, enctypes,
+ (sizeof (enctypes) / sizeof (krb5_enctype))) != 0) {
rc = ADJOIN_ERR_WRITE_KEYTAB;
goto adjoin_cleanup;
}
@@ -2255,37 +2333,30 @@ adjoin(char *machine_passwd, int len)
goto adjoin_cleanup;
}
- if (smb_config_set_idmap_gc(ah->hostname) != 0) {
- rc = ADJOIN_ERR_IDMAP_SET_GC;
- goto adjoin_cleanup;
- }
-
/* Refresh IDMAP service */
if (smb_config_refresh_idmap() != 0) {
rc = ADJOIN_ERR_IDMAP_REFRESH;
goto adjoin_cleanup;
}
- /* Remove the idmap ccache */
- if (stat(idmap_ccache, &fstat) == 0) {
- if (remove(idmap_ccache) != 0) {
- rc = ADJOIN_ERR_IDMAP_CCACHE;
- goto adjoin_cleanup;
- }
- }
-
- delete = 0;
+ delete = B_FALSE;
adjoin_cleanup:
- if (delete)
+ if (new_acct && delete)
ads_del_computer(ah);
if (fini_krbctx)
smb_krb5_ctx_fini(ctx);
ads_close(ah);
- free(princ);
free(princ_r);
+ /*
+ * Don't mask other failure. Only reports SMF refresh
+ * failure if no other domain join failure.
+ */
+ if ((smb_config_refresh() != 0) && (rc == ADJOIN_SUCCESS))
+ rc = ADJOIN_ERR_SMB_REFRESH;
+
return (rc);
}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c
index 474adca09b..094c1b4946 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c
@@ -47,14 +47,12 @@
#include <net/if.h>
#include <smbns_dyndns.h>
-#include <smbns_krb.h>
/* internal use, in dyndns_add_entry */
#define DEL_NONE 2
/* Maximum retires if not authoritative */
#define MAX_AUTH_RETRIES 3
-
static int
dyndns_enabled(void)
{
@@ -63,8 +61,7 @@ dyndns_enabled(void)
smb_config_rdlock();
enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE);
smb_config_unlock();
-
- return ((enabled) ? 1 : 0);
+ return (enabled);
}
/*
@@ -620,55 +617,6 @@ dyndns_open_init_socket(int sock_type, unsigned long dest_addr, int port)
}
/*
- * dyndns_acquire_cred
- * This routine is used to acquire a GSS credential handle to a user's Kerberos
- * ticket-granting ticket (TGT) stored locally on the system. If getting a
- * handle fails, then a new TGT will be obtained again before trying to get a
- * handle once more.
- * The user's password is taken from the environment variable
- * lookup.dns.dynamic.passwd and is encrypted.
- * Paramaters:
- * kinit_retry: if 0 then a new TGT can be obtained before second attempt to
- * get a handle to TGT if first attempt fails
- * Returns:
- * user_name : name of user to get credential handle from
- * credHandle : handle to user's credential (TGT)
- * oid : contains Kerberos 5 object identifier
- * kinit_retry: 1 if a new TGT has been acquired in this routine, otherwise 0
- * -1 : error
- */
-static int
-dyndns_acquire_cred(gss_cred_id_t *credHandle, char *user_name,
- gss_OID *oid, int *kinit_retry)
-{
- char *p, pwd[100];
-
- smb_config_rdlock();
- p = smb_config_getstr(SMB_CI_ADS_USER);
- if (p == NULL || *p == 0) {
- syslog(LOG_ERR, "No user configured for "
- "secure dynamic DNS update.\n");
- smb_config_unlock();
- return (-1);
- }
- (void) strcpy(user_name, p);
-
- p = smb_config_getstr(SMB_CI_ADS_PASSWD);
- if (p == NULL || *p == 0) {
- syslog(LOG_ERR, "No password configured for "
- "secure dynamic DNS update.\n");
- smb_config_unlock();
- return (-1);
- }
- smb_config_unlock();
-
- (void) strcpy(pwd, p);
-
- return krb5_acquire_cred_kinit(user_name, pwd, credHandle,
- oid, kinit_retry, "dyndns");
-}
-
-/*
* dyndns_build_tkey_msg
* This routine is used to build the TKEY message to transmit GSS tokens
* during GSS security context establishment for secure DNS update. The
@@ -741,30 +689,18 @@ dyndns_build_tkey_msg(char *buf, char *key_name, uint16_t *id,
* processes the new token and then generates a new token to be sent to the
* GSS server. This cycle is continued until the security establishment is
* done. TCP is used to send and receive TKEY messages.
- * If gss_init_sec_context fails then a new TGT will be acquired so that
- * security establishment can be retry once more by the caller after getting
- * a handle to the new TGT (credential).
* Parameters:
- * credHandle : handle to credential
+ * cred_handle : handle to credential
* s : socket descriptor to DNS server
* key_name : TKEY key name
* dns_hostname: fully qualified DNS hostname
* oid : contains Kerberos 5 object identifier
- * user_name : name of user to perform DNS update
- * kinit_retry : if 0 and gss_init_sec_context fails then get new TGT so
- * the caller can restart doing security context establishment
* Returns:
* gss_context : handle to security context
- * kinit_retry : 1 if a new TGT has been acquired in this routine,
- * otherwise 0
- * do_acquire_cred: if 1 then caller will restart security context
- * establishment
- * -1 : error
*/
static int
-dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
- int s, char *key_name, char *dns_hostname, gss_OID oid, char *user_name,
- int *kinit_retry, int *do_acquire_cred)
+dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t cred_handle,
+ int s, char *key_name, char *dns_hostname, gss_OID oid)
{
uint16_t id, rid, rsz;
char buf[MAX_TCP_SIZE], buf2[MAX_TCP_SIZE];
@@ -778,34 +714,19 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
int gss_flags;
OM_uint32 ret_flags;
int buf_sz;
- char *p, pwd[100];
-
- smb_config_rdlock();
- p = smb_config_getstr(SMB_CI_ADS_PASSWD);
- if (p == NULL || *p == 0) {
- syslog(LOG_ERR, "No password configured for "
- "secure dynamic DNS update.\n");
- smb_config_unlock();
- return (-1);
- }
- smb_config_unlock();
- (void) strcpy(pwd, p);
service_sz = strlen(dns_hostname) + 5;
service_name = (char *)malloc(sizeof (char) * service_sz);
if (service_name == NULL) {
syslog(LOG_ERR, "Malloc failed for %d bytes ", service_sz);
- smb_config_unlock();
return (-1);
}
(void) snprintf(service_name, service_sz, "DNS@%s", dns_hostname);
service_buf.value = service_name;
service_buf.length = strlen(service_name)+1;
if ((maj = gss_import_name(&min, &service_buf,
- (gss_OID) gss_nt_service_name,
- &target_name)) != GSS_S_COMPLETE) {
+ GSS_C_NT_HOSTBASED_SERVICE, &target_name)) != GSS_S_COMPLETE) {
display_stat(maj, min);
- (void) gss_release_oid(&min, &oid);
(void) free(service_name);
return (-1);
}
@@ -816,11 +737,17 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG | GSS_C_REPLAY_FLAG |
GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG;
do {
- if (krb5_establish_sec_ctx_kinit(user_name, pwd, credHandle,
- gss_context, target_name, oid, gss_flags, inputptr,
- &out_tok, &ret_flags, &time_rec, kinit_retry,
- do_acquire_cred, &maj, "dyndns") == -1) {
- (void) gss_release_oid(&min, &oid);
+ maj = gss_init_sec_context(&min, cred_handle, gss_context,
+ target_name, oid, gss_flags, 0, NULL, inputptr, NULL,
+ &out_tok, &ret_flags, &time_rec);
+
+ if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
+ assert(gss_context);
+ if (*gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min,
+ gss_context, NULL);
+
+ display_stat(maj, min);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -830,7 +757,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
syslog(LOG_ERR, "dyndns: No GSS_C_REPLAY_FLAG\n");
if (out_tok.length > 0)
(void) gss_release_buffer(&min, &out_tok);
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -840,7 +766,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
syslog(LOG_ERR, "dyndns: No GSS_C_MUTUAL_FLAG\n");
if (out_tok.length > 0)
(void) gss_release_buffer(&min, &out_tok);
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -849,7 +774,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
if ((buf_sz = dyndns_build_tkey_msg(buf, key_name,
&id, &out_tok)) <= 0) {
(void) gss_release_buffer(&min, &out_tok);
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -858,7 +782,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
if (send(s, buf, buf_sz, 0) == -1) {
syslog(LOG_ERR, "dyndns: TKEY send error\n");
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -867,7 +790,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
if (recv(s, buf2, MAX_TCP_SIZE, 0) == -1) {
syslog(LOG_ERR, "dyndns: TKEY "
"reply recv error\n");
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -877,7 +799,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
syslog(LOG_ERR, "dyndns: Error in "
"TKEY reply: %d: ", ret);
dyndns_msg_err(ret);
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -885,7 +806,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
tmpptr = &buf2[2];
(void) dyndns_get_nshort(tmpptr, &rid);
if (id != rid) {
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (-1);
}
@@ -901,7 +821,6 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
} while (maj != GSS_S_COMPLETE);
- (void) gss_release_oid(&min, &oid);
(void) gss_release_name(&min, &target_name);
return (0);
@@ -910,13 +829,8 @@ dyndns_establish_sec_ctx(gss_ctx_id_t *gss_context, gss_cred_id_t credHandle,
/*
* dyndns_get_sec_context
* Get security context for secure dynamic DNS update. This routine opens
- * a TCP socket to the DNS server and calls routines to get a handle to a
- * locally cached user's credential and establish a security context with
- * the DNS server to perform secure dynamic DNS update. If getting security
- * context fails then a retry may be done after reobtaining new credential and
- * getting a new credential handle. If obtaining new credential has been
- * done earlier during getting a handle to credential then there is no need to
- * do a retry for security context.
+ * a TCP socket to the DNS server and establishes a security context with
+ * the DNS server using host principal to perform secure dynamic DNS update.
* Parameters:
* hostname: fully qualified hostname
* dns_ip : ip address of hostname in network byte order
@@ -930,14 +844,14 @@ static gss_ctx_id_t
dyndns_get_sec_context(const char *hostname, int dns_ip)
{
int s;
- gss_cred_id_t credHandle;
+ gss_cred_id_t cred_handle;
gss_ctx_id_t gss_context;
gss_OID oid;
- OM_uint32 min;
struct hostent *hentry;
- int kinit_retry, do_acquire_cred;
- char *key_name, dns_hostname[255], user_name[50];
+ char *key_name, dns_hostname[MAXHOSTNAMELEN];
+ cred_handle = GSS_C_NO_CREDENTIAL;
+ oid = GSS_C_NO_OID;
key_name = (char *)hostname;
hentry = gethostbyaddr((char *)&dns_ip, 4, AF_INET);
@@ -952,29 +866,11 @@ dyndns_get_sec_context(const char *hostname, int dns_ip)
return (NULL);
}
- kinit_retry = 0;
- do_acquire_cred = 0;
- acquire_cred:
-
- if (dyndns_acquire_cred(&credHandle, user_name, &oid, &kinit_retry)) {
- (void) close(s);
- return (NULL);
- }
-
- if (dyndns_establish_sec_ctx(&gss_context, credHandle, s, key_name,
- dns_hostname, oid, user_name, &kinit_retry, &do_acquire_cred)) {
- (void) gss_release_cred(&min, &credHandle);
- if (do_acquire_cred) {
- do_acquire_cred = 0;
- goto acquire_cred;
- }
- (void) close(s);
- return (NULL);
- }
+ if (dyndns_establish_sec_ctx(&gss_context, cred_handle, s, key_name,
+ dns_hostname, oid))
+ gss_context = NULL;
(void) close(s);
-
- (void) gss_release_cred(&min, &credHandle);
return (gss_context);
}
@@ -1367,7 +1263,8 @@ sec_retry_higher:
key_name = (char *)hostname;
if ((s2 = dyndns_open_init_socket(SOCK_DGRAM, dns_ip, 53)) < 0) {
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
+ if (gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
return (-1);
}
@@ -1376,7 +1273,8 @@ sec_retry_higher:
ip_addr, life_time, update_type, del_type,
key_name, &id, level)) <= 0) {
(void) close(s2);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
+ if (gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
return (-1);
}
@@ -1388,7 +1286,8 @@ sec_retry_higher:
GSS_S_COMPLETE) {
display_stat(maj, min);
(void) close(s2);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
+ if (gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
return (-1);
}
@@ -1397,7 +1296,8 @@ sec_retry_higher:
&out_mic, level)) <= 0) {
(void) close(s2);
(void) gss_release_buffer(&min, &out_mic);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
+ if (gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
return (-1);
}
@@ -1405,13 +1305,15 @@ sec_retry_higher:
if (dyndns_udp_send_recv(s2, buf, buf_sz, buf2)) {
(void) close(s2);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
+ if (gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
return (-1);
}
(void) close(s2);
- (void) gss_delete_sec_context(&min, &gss_context, NULL);
+ if (gss_context != GSS_C_NO_CONTEXT)
+ (void) gss_delete_sec_context(&min, &gss_context, NULL);
ret = buf2[3] & 0xf; /* error field in UDP */
@@ -1498,7 +1400,8 @@ dyndns_search_entry(int update_zone, const char *hostname, const char *ip_addr,
/*
* dyndns_add_remove_entry
- * Perform non-secure dynamic DNS update. If fail then tries secure update.
+ * Perform non-secure dynamic DNS update. If it fails and the system is in
+ * domain mode, secure update will be performed.
* This routine opens a UDP socket to the DNS sever, build the update request
* message, and sends the message to the DNS server. The response is received
* and check for error. If there is no error then the local NSS cached is
@@ -1603,8 +1506,9 @@ retry_higher:
return (-1);
}
- ret = dyndns_sec_add_remove_entry(update_zone, hostname,
- ip_addr, life_time, update_type, del_type, dns_str);
+ if (smb_get_security_mode() == SMB_SECMODE_DOMAIN)
+ ret = dyndns_sec_add_remove_entry(update_zone, hostname,
+ ip_addr, life_time, update_type, del_type, dns_str);
return (ret);
}
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c
index c1a2de7913..4fa2e34931 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c
@@ -53,6 +53,7 @@
*/
#include <kerberosv5/krb5.h>
#include <kerberosv5/com_err.h>
+#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
@@ -299,6 +300,9 @@ smb_kinit(char *user, char *passwd)
struct k5_data k5;
int authed_k5 = 0;
+ assert(user);
+ assert(passwd);
+
(void) memset(&opts, 0, sizeof (opts));
opts.action = INIT_PW;
opts.principal_name = strdup(user);
@@ -374,10 +378,18 @@ krb5_acquire_cred_kinit(char *user, char *pwd, gss_cred_id_t *cred_handle,
/*
* krb5_acquire_cred_kinit_main
*
- * This routine is called both by ADS and Dyn DNS modules to get a handle to
- * administrative user's credential stored locally on the system. The
- * credential is the TGT. If the attempt at getting handle fails then a second
- * attempt will be made after getting a new TGT.
+ * This routine is called by ADS module to get a handle to administrative
+ * user's credential stored locally on the system. The credential is the TGT.
+ * If the attempt at getting handle fails then a second attempt will be made
+ * after getting a new TGT.
+ *
+ * If there's no username then we must be using host credentials and we don't
+ * bother trying to acquire a credential for GSS_C_NO_NAME (which should be
+ * equivalent to using GSS_C_NO_CREDENTIAL, but it isn't in a very subtle way
+ * because mech_krb5 isn't so smart). Specifically mech_krb5 will try hard
+ * to get a non-expired TGT using the keytab if we're running as root (or fake
+ * it, using the special app_krb5_user_uid() function), but only when we use
+ * the default credential, as opposed to a credential for the default principal.
*
* Paramters:
* user : username to retrieve a handle to its credential
@@ -399,12 +411,15 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle,
gss_OID *oid, int *kinit_retry, char *caller_mod)
{
OM_uint32 maj, min;
- gss_name_t desired_name;
+ gss_name_t desired_name = GSS_C_NO_NAME;
gss_OID_set desired_mechs;
gss_buffer_desc oidstr, name_buf;
char str[50], user_name[50];
- acquire_cred:
+ *cred_handle = GSS_C_NO_CREDENTIAL;
+ *oid = GSS_C_NO_OID;
+ if (user == NULL || *user == '\0')
+ return (0);
/* Object Identifier for Kerberos 5 */
(void) strcpy(str, "{ 1 2 840 113554 1 2 2 }");
@@ -439,12 +454,10 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle,
return (-1);
}
+acquire_cred:
if ((maj = gss_acquire_cred(&min, desired_name, 0, desired_mechs,
GSS_C_INITIATE, cred_handle, NULL, NULL)) != GSS_S_COMPLETE) {
- if (!*kinit_retry) {
- (void) gss_release_oid(&min, oid);
- (void) gss_release_oid_set(&min, &desired_mechs);
- (void) gss_release_name(&min, &desired_name);
+ if (!*kinit_retry && pwd != NULL && *pwd != '\0') {
syslog(LOG_ERR, "%s: Retry kinit to "
"acquire credential.\n", caller_mod);
(void) smb_kinit(user, pwd);
@@ -455,9 +468,15 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle,
(void) gss_release_oid(&min, oid);
(void) gss_release_oid_set(&min, &desired_mechs);
(void) gss_release_name(&min, &desired_name);
+ if (pwd == NULL || *pwd == '\0') {
+ /* See above */
+ *cred_handle = GSS_C_NO_CREDENTIAL;
+ return (0);
+ }
return (-1);
}
}
+
(void) gss_release_oid_set(&min, &desired_mechs);
(void) gss_release_name(&min, &desired_name);
@@ -467,11 +486,11 @@ krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle,
/*
* krb5_establish_sec_ctx_kinit
*
- * This routine is called by both the ADS and Dyn DNS modules to establish a
- * security context before ADS or Dyn DNS updates are allowed. If establishing
- * a security context fails for any reason, a second attempt will be made after
- * a new TGT is obtained. This routine is called many time as needed until
- * a security context is established.
+ * This routine is called by the ADS module to establish a security
+ * context before ADS updates are allowed. If establishing a security context
+ * fails for any reason, a second attempt will be made after a new TGT is
+ * obtained. This routine is called many time as needed until a security
+ * context is established.
*
* The resources use for the security context must be released if security
* context establishment process fails.
@@ -527,7 +546,7 @@ krb5_establish_sec_ctx_kinit(char *user, char *pwd,
if (*gss_context != NULL)
(void) gss_delete_sec_context(&min, gss_context, NULL);
- if (!*kinit_retry) {
+ if ((user != NULL) && (pwd != NULL) && !*kinit_retry) {
syslog(LOG_ERR, "%s: Retry kinit to establish "
"security context.\n", caller_mod);
(void) smb_kinit(user, pwd);
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h
index 22028fcdb5..18d6696771 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h
@@ -35,6 +35,8 @@
extern "C" {
#endif
+#define SMBNS_KRB5_KEYTAB "/etc/krb5/krb5.keytab"
+
extern gss_OID gss_nt_user_name;
extern gss_OID gss_nt_machine_uid_name;
extern gss_OID gss_nt_string_uid_name;
@@ -53,7 +55,9 @@ void smb_krb5_ctx_fini(krb5_context ctx);
int smb_krb5_get_principal(krb5_context ctx, char *princ_str,
krb5_principal *princ);
int smb_krb5_setpwd(krb5_context ctx, krb5_principal princ, char *passwd);
-int smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ,
+int smb_krb5_remove_keytab_entries(krb5_context ctx, krb5_principal princ,
+ char *fname);
+int smb_krb5_update_keytab_entries(krb5_context ctx, krb5_principal princ,
char *fname, krb5_kvno kvno, char *passwd, krb5_enctype *enctypes,
int enctype_count);
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c
index a6c99799d1..83100131c2 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ksetpwd.c
@@ -34,14 +34,18 @@
#include <ctype.h>
#include <errno.h>
#include <syslog.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <kerberosv5/krb5.h>
+#include <kerberosv5/com_err.h>
+#include <smbns_krb.h>
+static int smb_krb5_open_wrfile(krb5_context ctx, char *fname,
+ krb5_keytab *kt);
static int smb_krb5_ktadd(krb5_context ctx, krb5_keytab kt,
const krb5_principal princ, krb5_enctype enctype, krb5_kvno kvno,
const char *pw);
+static krb5_error_code smb_krb5_ktremove(krb5_context ctx, krb5_keytab kt,
+ const krb5_principal princ);
+
/*
* smb_krb5_ctx_init
@@ -122,29 +126,18 @@ smb_krb5_setpwd(krb5_context ctx, krb5_principal princ, char *passwd)
}
/*
- * smb_krb5_write_keytab
+ * smb_krb5_open_wrfile
*
- * Write all the Kerberos keys to the keytab file.
- * Returns 0 on success. Otherwise, returns -1.
+ * Open the keytab file for writing.
+ * The keytab should be closed by calling krb5_kt_close().
*/
-int
-smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname,
- krb5_kvno kvno, char *passwd, krb5_enctype *enctypes, int enctype_count)
+static int
+smb_krb5_open_wrfile(krb5_context ctx, char *fname, krb5_keytab *kt)
{
- krb5_keytab kt = NULL;
char *ktname;
- int i, len;
- int rc = 0;
- struct stat fstat;
-
- if (stat(fname, &fstat) == 0) {
- if (remove(fname) != 0) {
- syslog(LOG_ERR, "smb_krb5_write_keytab: cannot remove"
- " existing keytab");
- return (-1);
- }
- }
+ int len;
+ *kt = NULL;
len = snprintf(NULL, 0, "WRFILE:%s", fname) + 1;
if ((ktname = malloc(len)) == NULL) {
syslog(LOG_ERR, "smb_krb5_write_keytab: resource shortage");
@@ -153,7 +146,7 @@ smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname,
(void) snprintf(ktname, len, "WRFILE:%s", fname);
- if (krb5_kt_resolve(ctx, ktname, &kt) != 0) {
+ if (krb5_kt_resolve(ctx, ktname, kt) != 0) {
syslog(LOG_ERR, "smb_krb5_write_keytab: failed to open/create "
"keytab %s\n", fname);
free(ktname);
@@ -161,6 +154,59 @@ smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname,
}
free(ktname);
+ return (0);
+}
+
+/*
+ * smb_krb5_remove_keytab_entries
+ *
+ * Remove the keys from the keytab for the specified principal.
+ */
+int
+smb_krb5_remove_keytab_entries(krb5_context ctx, krb5_principal princ,
+ char *fname)
+{
+ krb5_keytab kt = NULL;
+ int rc = 0;
+ krb5_error_code code;
+
+ if (smb_krb5_open_wrfile(ctx, fname, &kt) != 0)
+ return (-1);
+
+ if ((code = smb_krb5_ktremove(ctx, kt, princ)) != 0) {
+ syslog(LOG_ERR, "smb_krb5_remove_keytab_entries: %s",
+ error_message(code));
+ rc = -1;
+ }
+
+ krb5_kt_close(ctx, kt);
+ return (rc);
+}
+
+/*
+ * smb_krb5_update_keytab_entries
+ *
+ * Update the keys for the specified principal in the keytab.
+ * Returns 0 on success. Otherwise, returns -1.
+ */
+int
+smb_krb5_update_keytab_entries(krb5_context ctx, krb5_principal princ,
+ char *fname, krb5_kvno kvno, char *passwd, krb5_enctype *enctypes,
+ int enctype_count)
+{
+ krb5_keytab kt = NULL;
+ int rc = 0, i;
+ krb5_error_code code;
+
+ if (smb_krb5_open_wrfile(ctx, fname, &kt) != 0)
+ return (-1);
+
+ if ((code = smb_krb5_ktremove(ctx, kt, princ)) != 0) {
+ syslog(LOG_ERR, "smb_krb5_update_keytab_entries: %s",
+ error_message(code));
+ krb5_kt_close(ctx, kt);
+ return (-1);
+ }
for (i = 0; i < enctype_count; i++) {
if (smb_krb5_ktadd(ctx, kt, princ, enctypes[i], kvno, passwd)
@@ -171,13 +217,74 @@ smb_krb5_write_keytab(krb5_context ctx, krb5_principal princ, char *fname,
}
- if (kt != NULL)
- krb5_kt_close(ctx, kt);
-
+ krb5_kt_close(ctx, kt);
return (rc);
}
/*
+ * smb_krb5_ktremove
+ *
+ * Removes the old entries for the specified principal from the keytab.
+ *
+ * Returns 0 upon success. Otherwise, returns KRB5 error code.
+ */
+static krb5_error_code
+smb_krb5_ktremove(krb5_context ctx, krb5_keytab kt, const krb5_principal princ)
+{
+ krb5_keytab_entry entry;
+ krb5_kt_cursor cursor;
+ int code;
+
+ code = krb5_kt_get_entry(ctx, kt, princ, 0, 0, &entry);
+ if (code != 0) {
+ if (code == ENOENT || code == KRB5_KT_NOTFOUND)
+ return (0);
+
+ return (code);
+ }
+
+ krb5_kt_free_entry(ctx, &entry);
+
+ if ((code = krb5_kt_start_seq_get(ctx, kt, &cursor)) != 0)
+ return (code);
+
+ while ((code = krb5_kt_next_entry(ctx, kt, &entry, &cursor)) == 0) {
+ if (krb5_principal_compare(ctx, princ, entry.principal)) {
+
+ code = krb5_kt_end_seq_get(ctx, kt, &cursor);
+ if (code != 0) {
+ krb5_kt_free_entry(ctx, &entry);
+ return (code);
+ }
+
+ code = krb5_kt_remove_entry(ctx, kt, &entry);
+ if (code != 0) {
+ krb5_kt_free_entry(ctx, &entry);
+ return (code);
+ }
+
+ code = krb5_kt_start_seq_get(ctx, kt, &cursor);
+ if (code != 0) {
+ krb5_kt_free_entry(ctx, &entry);
+ return (code);
+ }
+
+ }
+ krb5_kt_free_entry(ctx, &entry);
+ }
+
+ if (code && code != KRB5_KT_END) {
+ (void) krb5_kt_end_seq_get(ctx, kt, &cursor);
+ return (code);
+ }
+
+ if ((code = krb5_kt_end_seq_get(ctx, kt, &cursor)))
+ return (code);
+
+ return (0);
+}
+
+/*
* smb_krb5_ktadd
*
* Add a Keberos key to the keytab file.
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c
index 2b2d20e3c3..b8de94a504 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c
@@ -2134,6 +2134,7 @@ smb_send_node_status_response(struct addr_entry *addr,
unsigned char *scan_end;
unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE];
net_cfg_t cfg;
+ boolean_t scan_done = B_FALSE;
bzero(&packet, sizeof (struct name_packet));
bzero(&answer, sizeof (struct resource_record));
@@ -2168,7 +2169,7 @@ smb_send_node_status_response(struct addr_entry *addr,
smb_config_rdlock();
max_connections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS);
smb_config_unlock();
- for (;;) {
+ while (!scan_done) {
if ((scan + 6) >= scan_end) {
packet.info |= NAME_NM_FLAGS_TC;
break;
@@ -2256,8 +2257,7 @@ smb_send_node_status_response(struct addr_entry *addr,
BE_OUT16(scan, 0); scan += 2;
- break;
- /*NOTREACHED*/
+ scan_done = B_TRUE;
}
answer.rdlength = scan - data;
return (smb_send_name_service_packet(addr, &packet));
@@ -4489,6 +4489,10 @@ smb_netbios_wins_config(char *ip)
{
uint32_t ipaddr;
+ /* Return if ip == NULL since this is the same as "" */
+ if (ip == NULL)
+ return;
+
ipaddr = inet_addr(ip);
if (ipaddr != INADDR_NONE) {
smb_nbns[nbns_num].flags = ADDR_FLAG_VALID;
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c
index 0aaf8338b4..6adeca1d50 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c
@@ -638,7 +638,7 @@ smb_nic_get_list(struct if_list **list)
int
smb_nic_build_network_structures(net_cfg_t **nc, int *number)
{
- char ** names = NULL;
+ char **names = NULL;
int res, numnics = 0;
int num_aliases = 0;
uint32_t uip;
@@ -680,14 +680,16 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
if (num_aliases == -1) {
(void) smb_nic_clear_name_list(names, numnics);
free (*nc);
+ *nc = NULL;
return (-1);
}
- (*nc)->aliases = (char **)malloc(
- (sizeof (char) * IP_ABITS) * num_aliases);
+ (*nc)->aliases = (char **)calloc(num_aliases,
+ (sizeof (char) * IP_ABITS));
if ((*nc)->aliases == NULL) {
(void) smb_nic_clear_name_list(names, numnics);
free (*nc);
+ *nc = NULL;
return (-1);
}
(void) strncpy((*nc)->ifname, names[i],
@@ -699,17 +701,19 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
(void) smb_nic_clear_name_list(names, numnics);
free ((*nc)->aliases);
free (*nc);
+ *nc = NULL;
return (-1);
}
(*nc)->ip = uip;
- if (smb_wins_is_excluded(uip, (ulong_t *)exclude,
- nexclude))
+ if (smb_wins_is_excluded(uip,
+ (ipaddr_t *)exclude, nexclude))
(*nc)->exclude = B_TRUE;
res = smb_nic_get_netmask((*nc)->ifname, &uip);
if (res == -1) { /* error retrieving netmask address */
(void) smb_nic_clear_name_list(names, numnics);
free ((*nc)->aliases);
free (*nc);
+ *nc = NULL;
return (-1);
}
(*nc)->mask = uip;
@@ -718,6 +722,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
(void) smb_nic_clear_name_list(names, numnics);
free ((*nc)->aliases);
free (*nc);
+ *nc = NULL;
return (-1);
}
(*nc)->broadcast = uip;
@@ -727,6 +732,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
(void) smb_nic_clear_name_list(names, numnics);
free ((*nc)->aliases);
free (*nc);
+ *nc = NULL;
return (-1);
}
res = smb_nic_flags((*nc)->ifname, &flags);
@@ -734,6 +740,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
(void) smb_nic_clear_name_list(names, numnics);
free ((*nc)->aliases);
free (*nc);
+ *nc = NULL;
return (-1);
}
(*nc)->flags = flags;
@@ -747,6 +754,7 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
(void) smb_nic_clear_name_list(names, numnics);
free ((*nc)->aliases);
free (*nc);
+ *nc = NULL;
return (-1);
}
@@ -761,16 +769,16 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number)
(char *)(list->next);
j++;
list = list->next;
+ }
}
+ k++;
+ *number = k; /* needed if we have to cleanup on fail */
+ j = 1;
+ (*nc)++; /* increment pointer */
}
- k++;
- j = 1;
- (*nc)++; /* increment pointer */
- }
} /* end for */
*nc = nc_array;
- *number = k;
(void) smb_nic_clear_name_list(names, numnics);
return (0);
}
@@ -958,9 +966,11 @@ smb_nic_clear_niclist(net_cfg_t *niclist, int amount)
for (i = 0; i < amount; i++) {
while (niclist[i].aliases[j] != NULL) {
free(niclist[i].aliases[j]);
+ niclist[i].aliases[j] = NULL;
j++;
}
free(niclist[i].aliases);
+ niclist[i].aliases = NULL;
j = 0;
}
free(niclist);
@@ -971,8 +981,13 @@ smb_nic_clear_niclist(net_cfg_t *niclist, int amount)
int
smb_nic_free_niclist(net_cfg_list_t *niclist)
{
- return (smb_nic_clear_niclist(niclist->net_cfg_list,
- niclist->net_cfg_cnt));
+ int ret;
+
+ ret = smb_nic_clear_niclist(niclist->net_cfg_list,
+ niclist->net_cfg_cnt);
+ niclist->net_cfg_list = NULL;
+ niclist->net_cfg_cnt = 0;
+ return (ret);
}
/*
@@ -1048,10 +1063,15 @@ smb_nic_unlock(void)
int
smb_nic_init()
{
+ int ret;
+
smb_nic_lock();
smb_nic_list.net_cfg_cnt = 0;
- (void) smb_nic_build_network_structures(&smb_nic_list.net_cfg_list,
+ smb_nic_list.net_cfg_list = NULL;
+ ret = smb_nic_build_network_structures(&smb_nic_list.net_cfg_list,
&smb_nic_list.net_cfg_cnt);
+ if (ret != 0)
+ (void) smb_nic_free_niclist(&smb_nic_list);
smb_nic_unlock();
return (0);
}
@@ -1062,18 +1082,21 @@ smb_nic_init()
void
smb_nic_build_info(void)
{
+ int ret;
+
smb_nic_lock();
if (smb_nic_list.net_cfg_list) {
(void) smb_nic_free_niclist(&smb_nic_list);
- smb_nic_list.net_cfg_list = NULL;
}
smb_nic_list.net_cfg_cnt = 0;
- (void) smb_nic_build_network_structures(&smb_nic_list.net_cfg_list,
+ ret = smb_nic_build_network_structures(&smb_nic_list.net_cfg_list,
&smb_nic_list.net_cfg_cnt);
- if (smb_nic_list.net_cfg_cnt == 0) {
+ if (ret != 0)
+ (void) smb_nic_free_niclist(&smb_nic_list);
+ if (smb_nic_list.net_cfg_cnt == 0)
syslog(LOG_ERR, "smb: No network interfaces are configured "
"smb server may not function properly");
- }
+
smb_nic_unlock();
}
diff --git a/usr/src/lib/smbsrv/libsmbns/i386/Makefile b/usr/src/lib/smbsrv/libsmbns/i386/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libsmbns/i386/Makefile
+++ b/usr/src/lib/smbsrv/libsmbns/i386/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libsmbns/sparc/Makefile b/usr/src/lib/smbsrv/libsmbns/sparc/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libsmbns/sparc/Makefile
+++ b/usr/src/lib/smbsrv/libsmbns/sparc/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile
+++ b/usr/src/lib/smbsrv/libsmbns/sparcv9/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libsmbrdr/Makefile.com b/usr/src/lib/smbsrv/libsmbrdr/Makefile.com
index 822331f26b..0586ba1034 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/Makefile.com
+++ b/usr/src/lib/smbsrv/libsmbrdr/Makefile.com
@@ -44,6 +44,7 @@ OBJECTS= $(OBJS_COMMON) $(OBJS_SHARED)
include ../../../Makefile.lib
include ../../Makefile.lib
+LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lsmb -lnsl -lsocket -lc
SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \
diff --git a/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile b/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile
+++ b/usr/src/lib/smbsrv/libsmbrdr/amd64/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h
index 846ac9d306..8d537650ac 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h
@@ -37,7 +37,7 @@ extern "C" {
/*
* Redirector IPC functions
*
- * The following functions are required by the mlsvc_validate_user to
+ * The following functions are required by the mlsvc_join to
* apply new authentication information for the authenticated IPC, rollback
* or commit the changes to the original authentication information.
*/
@@ -45,25 +45,12 @@ extern void smbrdr_ipc_set(char *, unsigned char *);
extern void smbrdr_ipc_commit(void);
extern void smbrdr_ipc_rollback(void);
extern int smbrdr_ipc_skip_lsa_query(void);
-extern int smbrdr_ipc_get_mode(void);
-extern void smbrdr_ipc_save_mode(char *val);
-extern unsigned smbrdr_ipc_get_flags(void);
-extern void smbrdr_ipc_set_fallback(void);
-extern void smbrdr_ipc_unset_fallback(void);
-extern int smbrdr_ipc_is_fallback(void);
-
-/*
- * Functions for obtaining the resource domain administrator credentials.
- */
extern char *smbrdr_ipc_get_user(void);
-extern char *smbrdr_ipc_get_passwd(void);
-extern int smbrdr_ipc_is_valid(void);
+extern unsigned char *smbrdr_ipc_get_passwd(void);
-/* Redirector LOGON functions */
-extern int mlsvc_anonymous_logon(char *, char *, char **);
-extern int mlsvc_user_logon(char *, char *, char *, char *);
-extern int mlsvc_admin_logon(char *, char *);
+/* Redirector LOGON function */
+extern int mlsvc_logon(char *, char *, char *);
extern int smbrdr_rpc_readx(int, char *, int);
diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers
index 0ea435ee55..b6902203ef 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers
@@ -27,35 +27,26 @@
SUNWprivate {
global:
- mlsvc_admin_logon;
- mlsvc_anonymous_logon;
mlsvc_check_sessions;
mlsvc_close_pipe;
mlsvc_disconnect;
mlsvc_echo;
mlsvc_install_pdc_cb;
mlsvc_locate_domain_controller;
+ mlsvc_logon;
mlsvc_open_pipe;
mlsvc_session_native_values;
mlsvc_user_getauth;
- mlsvc_user_logon;
smbrdr_dump_netuse;
smbrdr_dump_ofiles;
smbrdr_dump_sessions;
smbrdr_init;
- smbrdr_ipc_get_mode;
smbrdr_ipc_commit;
- smbrdr_ipc_get_flags;
smbrdr_ipc_get_user;
smbrdr_ipc_rollback;
smbrdr_ipc_set;
smbrdr_ipc_skip_lsa_query;
- smbrdr_ipc_is_fallback;
- smbrdr_ipc_is_valid;
smbrdr_ipc_get_passwd;
- smbrdr_ipc_save_mode;
- smbrdr_ipc_set_fallback;
- smbrdr_ipc_unset_fallback;
smbrdr_rpc_readx;
smbrdr_rpc_transact;
local:
diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c
index 908a439864..cbce43db5e 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c
@@ -44,17 +44,32 @@
#include <smbrdr.h>
#include <smbrdr_ipc_util.h>
-/*
- * The binary NTLM hash is 16 bytes. When it is converted to hexidecimal,
- * it will be at most twice as long.
- */
-#define SMBRDR_IPC_HEX_PASSWD_MAXLEN (SMBAUTH_HASH_SZ * 2) + 1
#define SMBRDR_IPC_GETDOMAIN_TIMEOUT 10000
static rwlock_t smbrdr_ipc_lock;
static smbrdr_ipc_t ipc_info;
static smbrdr_ipc_t orig_ipc_info;
+static int
+smbrdr_get_machine_pwd_hash(unsigned char *hash)
+{
+ char *pwd;
+ int rc = 0;
+
+ smb_config_rdlock();
+ pwd = smb_config_getstr(SMB_CI_MACHINE_PASSWD);
+ if (!pwd || *pwd == 0) {
+ smb_config_unlock();
+ return (-1);
+ }
+
+ if (smb_auth_ntlm_hash((char *)pwd, hash) != 0)
+ rc = -1;
+
+ smb_config_unlock();
+ return (rc);
+}
+
/*
* smbrdr_ipc_init
*
@@ -66,73 +81,39 @@ static smbrdr_ipc_t orig_ipc_info;
void
smbrdr_ipc_init(void)
{
- char *p;
+ int rc;
+ (void) rw_wrlock(&smbrdr_ipc_lock);
bzero(&ipc_info, sizeof (smbrdr_ipc_t));
bzero(&orig_ipc_info, sizeof (smbrdr_ipc_t));
- smb_config_rdlock();
- p = smb_config_getstr(SMB_CI_RDR_IPCMODE);
-
- if (!strncasecmp(p, IPC_MODE_AUTH, IPC_MODE_STRLEN)) {
- ipc_info.mode = MLSVC_IPC_ADMIN;
-
- p = smb_config_getstr(SMB_CI_RDR_IPCUSER);
- if (p)
- (void) strlcpy(ipc_info.user, p,
- MLSVC_ACCOUNT_NAME_MAX);
- else
- syslog(LOG_WARNING, "smbrdr: (ipc) no admin user name");
-
- p = smb_config_get(SMB_CI_RDR_IPCPWD);
- if (p) {
- if (strlen(p) != SMBRDR_IPC_HEX_PASSWD_MAXLEN - 1) {
- *ipc_info.passwd = 0;
- syslog(LOG_WARNING,
- "smbrdr: (ipc) invalid admin password");
- } else {
- (void) hextobin(p,
- SMBRDR_IPC_HEX_PASSWD_MAXLEN - 1,
- ipc_info.passwd, SMBAUTH_HASH_SZ);
- }
- } else {
- *ipc_info.passwd = 0;
- syslog(LOG_WARNING, "smbrdr: (ipc) no admin password");
- }
-
- } else {
- if (!strcasecmp(p, IPC_MODE_FALLBACK_ANON))
- ipc_info.flags |= IPC_FLG_FALLBACK_ANON;
-
- ipc_info.mode = MLSVC_IPC_ANON;
- (void) strlcpy(ipc_info.user, MLSVC_ANON_USER,
- MLSVC_ACCOUNT_NAME_MAX);
+ (void) smb_gethostname(ipc_info.user, MLSVC_ACCOUNT_NAME_MAX - 1, 0);
+ (void) strlcat(ipc_info.user, "$", MLSVC_ACCOUNT_NAME_MAX);
+ rc = smbrdr_get_machine_pwd_hash(ipc_info.passwd);
+ if (rc != 0)
*ipc_info.passwd = 0;
- }
- smb_config_unlock();
+ (void) rw_unlock(&smbrdr_ipc_lock);
+
}
/*
* smbrdr_ipc_set
*
* The given username and password hash will be applied to the
- * ipc_info which will be used by mlsvc_validate_user().
+ * ipc_info, which will be used for setting up the authenticated IPC
+ * channel during join domain.
*
- * If mlsvc_validate_user() succeeds, the calling function is responsible
- * for invoking smbrdr_ipc_commit() for updating the environment
- * variables. Otherwise, it should invoke smbrdr_ipc_rollback() to restore
- * the previous credentials.
+ * If domain join operation succeeds, smbrdr_ipc_commit() should be
+ * invoked to set the ipc_info with host credentials. Otherwise,
+ * smbrdr_ipc_rollback() should be called to restore the previous
+ * credentials.
*/
void
smbrdr_ipc_set(char *plain_user, unsigned char *passwd_hash)
{
(void) rw_wrlock(&smbrdr_ipc_lock);
- if (ipc_info.flags & IPC_FLG_FALLBACK_ANON)
- ipc_info.mode = MLSVC_IPC_ADMIN;
-
(void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user));
(void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ);
- ipc_info.flags |= IPC_FLG_NEED_VERIFY;
(void) rw_unlock(&smbrdr_ipc_lock);
}
@@ -140,39 +121,20 @@ smbrdr_ipc_set(char *plain_user, unsigned char *passwd_hash)
/*
* smbrdr_ipc_commit
*
- * Save the new admin credentials as environment variables.
- * The binary NTLM password hash is first converted to a
- * hex string before storing in the environment variable.
+ * Save the host credentials, which will be used for any authenticated
+ * IPC channel establishment after domain join.
*
- * The credentials also saved to the original IPC info as
- * rollback data in case the join domain process
- * fails in the future.
+ * The host credentials is also saved to the original IPC info as
+ * rollback data in case the join domain process fails in the future.
*/
void
smbrdr_ipc_commit()
{
- unsigned char hexpass[SMBRDR_IPC_HEX_PASSWD_MAXLEN];
-
(void) rw_wrlock(&smbrdr_ipc_lock);
- smb_config_wrlock();
- (void) smb_config_set(SMB_CI_RDR_IPCUSER, ipc_info.user);
- (void) bintohex(ipc_info.passwd, sizeof (ipc_info.passwd),
- (char *)hexpass, sizeof (hexpass));
- hexpass[SMBRDR_IPC_HEX_PASSWD_MAXLEN - 1] = 0;
- (void) smb_config_set(SMB_CI_RDR_IPCPWD, (char *)hexpass);
-
- ipc_info.flags &= ~IPC_FLG_NEED_VERIFY;
-
- if (ipc_info.flags & IPC_FLG_FALLBACK_ANON) {
- ipc_info.flags &= ~IPC_FLG_FALLBACK_ANON;
- ipc_info.mode = MLSVC_IPC_ADMIN;
- (void) smb_config_set(SMB_CI_RDR_IPCMODE, IPC_MODE_AUTH);
- syslog(LOG_DEBUG, "smbrdr: (ipc) Authenticated IPC "
- "connection has been restored");
- }
-
+ (void) smb_gethostname(ipc_info.user, MLSVC_ACCOUNT_NAME_MAX - 1, 0);
+ (void) strlcat(ipc_info.user, "$", MLSVC_ACCOUNT_NAME_MAX);
+ (void) smbrdr_get_machine_pwd_hash(ipc_info.passwd);
(void) memcpy(&orig_ipc_info, &ipc_info, sizeof (smbrdr_ipc_t));
- smb_config_unlock();
(void) rw_unlock(&smbrdr_ipc_lock);
}
@@ -189,29 +151,12 @@ smbrdr_ipc_rollback()
sizeof (ipc_info.user));
(void) memcpy(ipc_info.passwd, orig_ipc_info.passwd,
sizeof (ipc_info.passwd));
-
- ipc_info.flags &= ~IPC_FLG_NEED_VERIFY;
-
- if (ipc_info.flags & IPC_FLG_FALLBACK_ANON)
- ipc_info.mode = MLSVC_IPC_ANON;
(void) rw_unlock(&smbrdr_ipc_lock);
}
/*
* Get & Set functions
*/
-int
-smbrdr_ipc_get_mode()
-{
- int mode;
-
- (void) rw_rdlock(&smbrdr_ipc_lock);
- mode = ipc_info.mode;
- (void) rw_unlock(&smbrdr_ipc_lock);
-
- return (mode);
-}
-
char *
smbrdr_ipc_get_user()
{
@@ -223,10 +168,10 @@ smbrdr_ipc_get_user()
return (user);
}
-char *
+unsigned char *
smbrdr_ipc_get_passwd()
{
- char *passwd;
+ unsigned char *passwd;
(void) rw_rdlock(&smbrdr_ipc_lock);
passwd = ipc_info.passwd;
@@ -234,67 +179,6 @@ smbrdr_ipc_get_passwd()
return (passwd);
}
-unsigned
-smbrdr_ipc_get_flags()
-{
- unsigned flags;
-
- (void) rw_rdlock(&smbrdr_ipc_lock);
- flags = ipc_info.flags;
- (void) rw_unlock(&smbrdr_ipc_lock);
- return (flags);
-}
-
-void
-smbrdr_ipc_set_fallback()
-{
- (void) rw_wrlock(&smbrdr_ipc_lock);
- ipc_info.flags |= IPC_FLG_FALLBACK_ANON;
- (void) rw_unlock(&smbrdr_ipc_lock);
-}
-
-void
-smbrdr_ipc_unset_fallback()
-{
- (void) rw_wrlock(&smbrdr_ipc_lock);
- ipc_info.flags &= ~IPC_FLG_FALLBACK_ANON;
- (void) rw_unlock(&smbrdr_ipc_lock);
-}
-
-/*
- * Whether the smbrdr.ipc.mode is set to fallback,anon or not
- */
-int
-smbrdr_ipc_is_fallback()
-{
- int is_fallback;
-
- smb_config_rdlock();
- is_fallback = (!strcasecmp(smb_config_getstr(SMB_CI_RDR_IPCMODE),
- IPC_MODE_FALLBACK_ANON) ? 1 : 0);
- smb_config_unlock();
-
- return (is_fallback);
-}
-
-/*
- * smbrdr_ipc_save_mode
- *
- * Set the SMBRDR_IPC_MODE_ENV variable and update the
- * IPC mode of the cache.
- */
-void
-smbrdr_ipc_save_mode(char *val)
-{
- (void) rw_wrlock(&smbrdr_ipc_lock);
- smb_config_wrlock();
- (void) smb_config_set(SMB_CI_RDR_IPCMODE, val);
- ipc_info.mode = !strncasecmp(val, IPC_MODE_AUTH, IPC_MODE_STRLEN)
- ? MLSVC_IPC_ADMIN : MLSVC_IPC_ANON;
- smb_config_unlock();
- (void) rw_unlock(&smbrdr_ipc_lock);
-}
-
/*
* smbrdr_ipc_skip_lsa_query
*
@@ -305,17 +189,9 @@ smbrdr_ipc_save_mode(char *val)
int
smbrdr_ipc_skip_lsa_query()
{
- char *user, *pwd;
+ char *user;
+ unsigned char *pwd;
- if (ipc_info.mode != MLSVC_IPC_ADMIN)
- return (0);
-
- smb_config_rdlock();
- user = smb_config_get(SMB_CI_RDR_IPCUSER);
- pwd = smb_config_get(SMB_CI_RDR_IPCPWD);
- smb_config_unlock();
- if ((user == NULL) && pwd)
- return (1);
(void) rw_rdlock(&smbrdr_ipc_lock);
user = ipc_info.user;
@@ -324,59 +200,3 @@ smbrdr_ipc_skip_lsa_query()
return (!(*user && *pwd));
}
-
-static char *
-smbrdr_ipc_modestr(int mode)
-{
- switch (mode) {
- case MLSVC_IPC_ANON:
- return ("Anonymous");
-
- case MLSVC_IPC_ADMIN:
- return ("Authenticated");
-
- default:
- return ("Unknown");
- }
-}
-
-/*
- * For debugging purposes only.
- */
-void
-smbrdr_ipc_loginfo()
-{
- smbrdr_ipc_t tmp;
- smbrdr_ipc_t tmporg;
-
- (void) rw_rdlock(&smbrdr_ipc_lock);
- (void) memcpy(&tmp, &ipc_info, sizeof (smbrdr_ipc_t));
- (void) memcpy(&tmporg, &orig_ipc_info, sizeof (smbrdr_ipc_t));
- (void) rw_unlock(&smbrdr_ipc_lock);
-
- syslog(LOG_DEBUG, "smbrdr: current IPC info:");
- syslog(LOG_DEBUG, "\t%s (user=%s, flags:0x%X)",
- smbrdr_ipc_modestr(tmp.mode), tmp.user, tmp.flags);
-
- syslog(LOG_DEBUG, "smbrdr: original IPC info:");
- syslog(LOG_DEBUG, "\t%s (user=%s, flags:0x%X)",
- smbrdr_ipc_modestr(tmporg.mode), tmporg.user, tmporg.flags);
-}
-
-/*
- * smbrdr_ipc_is_valid
- *
- * Determine whether the ipc_info has been validated or not.
- *
- */
-int
-smbrdr_ipc_is_valid()
-{
- int isvalid;
-
- (void) rw_rdlock(&smbrdr_ipc_lock);
- isvalid = (ipc_info.flags & IPC_FLG_NEED_VERIFY) ? 0 : 1;
- (void) rw_unlock(&smbrdr_ipc_lock);
-
- return (isvalid);
-}
diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h
index a967e91b86..68df733f7c 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h
@@ -39,40 +39,15 @@
extern "C" {
#endif
-#define SMBRDR_IPC_MODE_ENV "smbrdr.ipc.mode"
-#define SMBRDR_IPC_USER_ENV "smbrdr.ipc.user"
-#define SMBRDR_IPC_PASSWD_ENV "smbrdr.ipc.passwd"
-
-#define IPC_MODE_STRLEN 4
-#define IPC_MODE_ANON "anon"
-#define IPC_MODE_AUTH "auth"
-#define IPC_MODE_FALLBACK_ANON "fallback,anon"
-
-#define IPC_FLG_FALLBACK_ANON 0x00000001
-#define IPC_FLG_NEED_VERIFY 0x00000002
-
/*
* smbrdr_ipc_t
*
- * This structure contains information regarding the IPC configuration,
- * as well as, the authentication info needed for connecting to the
- * IPC$ share if the IPC connection is configured to be authenticated.
- *
- * IPC connection to the Primary Domain Controller [PDC] can be
- * configured to be either anonymous or authenticated. Therefore,
- * the IPC mode will be set to either one of the following values:
- * MLSVC_IPC_ANON
- * MLSVC_IPC_ADMIN
- *
- * The IPC_FLG_FALLBACK_ANON can be set in flags field to indicate whether
- * a fallback from authenticated IPC to anonymous IPC has occurred. This
- * flag will be unset once the join domain operation succeeds.
+ * This structure contains credentials for establishing authenticated
+ * IPC connection.
*/
typedef struct {
- int mode;
char user[MLSVC_ACCOUNT_NAME_MAX];
- char passwd[SMBAUTH_HASH_SZ];
- unsigned flags;
+ unsigned char passwd[SMBAUTH_HASH_SZ];
} smbrdr_ipc_t;
diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c
index 7dee7e41d2..d33f253b29 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c
@@ -38,66 +38,58 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-
#include <smbsrv/libsmbrdr.h>
-
#include <smbsrv/ntstatus.h>
#include <smbsrv/smb.h>
#include <smbrdr_ipc_util.h>
#include <smbrdr.h>
-#define SMBRDR_PWD_NULL 0
-#define SMBRDR_PWD_USER 1
-#define SMBRDR_PWD_HASH 2
-
+static int mlsvc_anonymous_logon(char *domain_controller, char *domain_name);
+static int mlsvc_auth_logon(char *domain_controller, char *domain_name,
+ char *username, unsigned char *pwd_hash);
static int smbrdr_smb_session_setupandx(struct sdb_logon *logon);
static boolean_t smbrdr_logon_validate(char *server, char *username);
static struct sdb_logon *smbrdr_logon_init(struct sdb_session *session,
- char *username, char *pwd, int pwd_type);
-static int smbrdr_logon_user(char *server, char *username, char *pwd,
- int pwd_type);
+ char *username, unsigned char *pwd);
+static int smbrdr_logon_user(char *server, char *username, unsigned char *pwd);
static int smbrdr_authenticate(char *primary_domain, char *account_name,
- char *pwd, int pwd_type);
+ unsigned char *pwd);
/*
- * mlsvc_anonymous_logon
+ * mlsvc_logon
*
- * Set up an anonymous session. If the session to the resource domain
- * controller appears to be okay we shouldn't need to do anything here.
- * Otherwise we clean up the stale session and create a new one.
+ * If the username is NULL, an anonymous session will be established.
+ * Otherwise, an authenticated session will be established based on the
+ * specified credentials.
*/
int
-mlsvc_anonymous_logon(char *domain_controller, char *domain_name,
- char **username)
+mlsvc_logon(char *domain_controller, char *domain, char *username)
{
- int rc = 0;
+ int rc;
+ unsigned char *pwd_hash = NULL;
- if (username == NULL) {
- syslog(LOG_ERR, "smbrdr: (anon logon) %s",
- xlate_nt_status(NT_STATUS_INVALID_PARAMETER));
- return (-1);
+ if (username) {
+ pwd_hash = smbrdr_ipc_get_passwd();
+ rc = mlsvc_auth_logon(domain_controller, domain, username,
+ pwd_hash);
+ } else {
+ rc = mlsvc_anonymous_logon(domain_controller, domain);
}
- /*
- * if the system is configured to establish Authenticated IPC
- * connection to PDC
- */
- if (smbrdr_ipc_get_mode() == MLSVC_IPC_ADMIN) {
- rc = mlsvc_admin_logon(domain_controller, domain_name);
- /*
- * it is possible for the system to fallback to use
- * anonymous IPC
- */
- if (smbrdr_ipc_get_mode() != MLSVC_IPC_ADMIN)
- *username = MLSVC_ANON_USER;
- else
- *username = smbrdr_ipc_get_user();
-
- syslog(LOG_DEBUG, "smbrdr: (admin logon) %s", *username);
- return (rc);
- }
+ return (rc);
+}
- *username = MLSVC_ANON_USER;
+/*
+ * mlsvc_anonymous_logon
+ *
+ * Set up an anonymous session. If the session to the resource domain
+ * controller appears to be okay we shouldn't need to do anything here.
+ * Otherwise we clean up the stale session and create a new one.
+ */
+static int
+mlsvc_anonymous_logon(char *domain_controller, char *domain_name)
+{
+ int rc = 0;
if (smbrdr_logon_validate(domain_controller, MLSVC_ANON_USER))
/* session & user are good use them */
@@ -110,8 +102,7 @@ mlsvc_anonymous_logon(char *domain_controller, char *domain_name,
return (-1);
}
- if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0,
- SMBRDR_PWD_NULL) < 0) {
+ if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0) < 0) {
syslog(LOG_ERR, "smbrdr: (anon logon) logon failed");
rc = -1;
}
@@ -140,7 +131,7 @@ mlsvc_user_getauth(char *domain_controller, char *username,
}
/*
- * mlsvc_user_logon
+ * mlsvc_auth_logon
*
* Set up a user session. If the session to the resource domain controller
* appears to be okay we shouldn't need to do anything here. Otherwise we
@@ -148,44 +139,19 @@ mlsvc_user_getauth(char *domain_controller, char *username,
* established, we leave it intact. It should only need to be set up again
* due to an inactivity timeout or a domain controller reset.
*/
-int
-mlsvc_user_logon(char *domain_controller, char *domain_name, char *username,
- char *password)
+static int
+mlsvc_auth_logon(char *domain_controller, char *domain_name, char *username,
+ unsigned char *pwd_hash)
{
int erc;
- if (smbrdr_logon_validate(domain_controller, username))
- return (0);
-
- if (smbrdr_negotiate(domain_name) != 0) {
- syslog(LOG_ERR, "smbrdr: (user logon) negotiate failed");
+ if (username == NULL || *username == 0) {
+ syslog(LOG_ERR, "smbrdr: auth logon (no username)");
return (-1);
}
- erc = smbrdr_authenticate(domain_name, username, password,
- SMBRDR_PWD_USER);
-
- return ((erc == AUTH_USER_GRANT) ? 0 : -1);
-}
-
-/*
- * mlsvc_admin_logon
- *
- * Unlike mlsvc_user_logon, mlsvc_admin_logon doesn't take
- * any username or password as function arguments.
- */
-int
-mlsvc_admin_logon(char *domain_controller, char *domain_name)
-{
- char password[PASS_LEN + 1];
- int erc;
- char *username, *dummy;
-
- username = smbrdr_ipc_get_user();
- (void) memcpy(password, smbrdr_ipc_get_passwd(), SMBAUTH_HASH_SZ);
-
- if (*username == 0) {
- syslog(LOG_ERR, "smbrdr: admin logon (no admin user)");
+ if (!pwd_hash || *pwd_hash == 0) {
+ syslog(LOG_ERR, "smbrdr: auth logon (no password)");
return (-1);
}
@@ -197,24 +163,7 @@ mlsvc_admin_logon(char *domain_controller, char *domain_name)
return (-1);
}
- erc = smbrdr_authenticate(domain_name, username, password,
- SMBRDR_PWD_HASH);
-
- /*
- * Fallback to anonmyous IPC logon if the IPC password hash is no
- * longer valid. It happens when the administrator password has
- * been reset from the Domain Controller.
- */
- if (erc < 0 && smbrdr_ipc_is_valid()) {
- if (!smbrdr_ipc_is_fallback())
- syslog(LOG_DEBUG, "smbrdr: admin logon "
- "(fallback to anonymous IPC)");
- smbrdr_ipc_set_fallback();
- smbrdr_ipc_save_mode(IPC_MODE_FALLBACK_ANON);
- erc = mlsvc_anonymous_logon(domain_controller, domain_name,
- &dummy);
- }
-
+ erc = smbrdr_authenticate(domain_name, username, pwd_hash);
return ((erc == AUTH_USER_GRANT) ? 0 : -1);
}
@@ -231,7 +180,7 @@ mlsvc_admin_logon(char *domain_controller, char *domain_name)
*/
static int
smbrdr_authenticate(char *primary_domain, char *account_name,
- char *pwd, int pwd_type)
+ unsigned char *pwd)
{
smb_ntdomain_t *di;
@@ -267,7 +216,7 @@ smbrdr_authenticate(char *primary_domain, char *account_name,
return (-2);
}
- return (smbrdr_logon_user(di->server, account_name, pwd, pwd_type));
+ return (smbrdr_logon_user(di->server, account_name, pwd));
}
/*
@@ -284,14 +233,14 @@ smbrdr_authenticate(char *primary_domain, char *account_name,
* pointer will be returned.
*/
static int
-smbrdr_logon_user(char *server, char *username, char *pwd, int pwd_type)
+smbrdr_logon_user(char *server, char *username, unsigned char *pwd)
{
struct sdb_session *session;
struct sdb_logon *logon;
struct sdb_logon old_logon;
- if (server == 0 || username == 0 ||
- ((pwd == 0) && (pwd_type != SMBRDR_PWD_NULL))) {
+ if ((server == NULL) || (username == NULL) ||
+ ((strcmp(username, MLSVC_ANON_USER) != 0) && (pwd == NULL))) {
return (-1);
}
@@ -316,7 +265,7 @@ smbrdr_logon_user(char *server, char *username, char *pwd, int pwd_type)
old_logon = *logon;
}
- logon = smbrdr_logon_init(session, username, pwd, pwd_type);
+ logon = smbrdr_logon_init(session, username, pwd);
if (logon == 0) {
syslog(LOG_ERR, "smbrdr: (logon[%s]) resource shortage",
@@ -618,10 +567,10 @@ smbrdr_smb_logoff(struct sdb_logon *logon)
*/
static struct sdb_logon *
smbrdr_logon_init(struct sdb_session *session, char *username,
- char *pwd, int pwd_type)
+ unsigned char *pwd)
{
struct sdb_logon *logon;
- int smbrdr_lmcomplvl;
+ int smbrdr_lmcompl;
int rc;
logon = (struct sdb_logon *)malloc(sizeof (sdb_logon_t));
@@ -631,52 +580,28 @@ smbrdr_logon_init(struct sdb_session *session, char *username,
bzero(logon, sizeof (struct sdb_logon));
logon->session = session;
- if (strcmp(username, "IPC$") == 0)
- logon->type = SDB_LOGON_ANONYMOUS;
- else
- logon->type = SDB_LOGON_USER;
-
- (void) strlcpy(logon->username, username, MAX_ACCOUNT_NAME);
-
smb_config_rdlock();
- smbrdr_lmcomplvl = smb_config_getnum(SMB_CI_LM_LEVEL);
+ smbrdr_lmcompl = smb_config_getnum(SMB_CI_LM_LEVEL);
smb_config_unlock();
- switch (pwd_type) {
- case SMBRDR_PWD_USER:
- rc = smb_auth_set_info(username, pwd, 0, session->di.domain,
- session->challenge_key, session->challenge_len,
- smbrdr_lmcomplvl, &logon->auth);
-
- if (rc != 0) {
- free(logon);
- return (0);
- }
- break;
-
- case SMBRDR_PWD_HASH:
- rc = smb_auth_set_info(username, 0, (unsigned char *)pwd,
+ if (strcmp(username, "IPC$") == 0) {
+ logon->type = SDB_LOGON_ANONYMOUS;
+ logon->auth.ci_len = 1;
+ *(logon->auth.ci) = 0;
+ logon->auth.cs_len = 0;
+ } else {
+ logon->type = SDB_LOGON_USER;
+ rc = smb_auth_set_info(username, 0, pwd,
session->di.domain, session->challenge_key,
- session->challenge_len, smbrdr_lmcomplvl, &logon->auth);
+ session->challenge_len, smbrdr_lmcompl, &logon->auth);
if (rc != 0) {
free(logon);
return (0);
}
- break;
-
- case SMBRDR_PWD_NULL:
- logon->auth.ci_len = 1;
- *(logon->auth.ci) = 0;
- logon->auth.cs_len = 0;
- break;
-
- default:
- /* Unknown password type */
- free(logon);
- return (0);
}
+ (void) strlcpy(logon->username, username, MAX_ACCOUNT_NAME);
logon->state = SDB_LSTATE_INIT;
return (logon);
}
diff --git a/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile b/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile
+++ b/usr/src/lib/smbsrv/libsmbrdr/i386/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile b/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile
index f91f0270e9..710c9eb3dd 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile
+++ b/usr/src/lib/smbsrv/libsmbrdr/sparc/Makefile
@@ -27,4 +27,6 @@
include ../Makefile.com
+DYNFLAGS += -R/usr/lib/smbsrv
+
install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile
index a2f97019c8..b3c4916b0c 100644
--- a/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile
+++ b/usr/src/lib/smbsrv/libsmbrdr/sparcv9/Makefile
@@ -25,7 +25,11 @@
# ident "%Z%%M% %I% %E% SMI"
#
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
include ../Makefile.com
include ../../../Makefile.lib.64
+DYNFLAGS += -R/usr/lib/smbsrv/$(MACH64)
+
install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)