diff options
author | as200622 <none@none> | 2007-11-26 18:29:15 -0800 |
---|---|---|
committer | as200622 <none@none> | 2007-11-26 18:29:15 -0800 |
commit | 55bf511df53aad0fdb7eb3fa349f0308cc05234c (patch) | |
tree | a153d7bae39c0480da0107072553ce0b07b02f23 /usr/src/lib | |
parent | b3d911cb99b7e5dd9df4c81fd7b58a97c82d07db (diff) | |
download | illumos-gate-55bf511df53aad0fdb7eb3fa349f0308cc05234c.tar.gz |
6575640 rename/rmdir/remove on mixed file systems work incorrectly for mangled names
6582182 64-bit libraries
6588720 Unable to create new folder in autohome share from Solaris10u3 with UFS & ZFS.
6611820 Unable to map a SMB share on SPARC system.
6612193 Rework ADS client, DynDNS client and Auth IPC to use host principal
6614664 CIFS server should not request ctime changes
6614864 Security tab not available after a share is mapped on SPARC system
6614953 An error occurred while creating a notepad file on X86 32-bit system.
6616349 Sparc-Get error "input not UTF-8" and (Abort)(core dumped) in sharemgr with Korean resource name
6622828 Resolve unreferenced makefiles
6626833 SUNWsmbsu package issues with snv_77.
6627415 SmbCreateTemporary fails on SPARC
6627469 Unable to map SIDs to names for Windows Vista clients
6627471 Remove winpipe door server from name space
6628747 smbd crash and in maintenance state
6629402 The adjoin operation triggered by smbadm join CLI shouldn't overwrite the Kerberos keytab file.
6629410 SMB daemon should remove its ccache on refresh or restart
6629428 smb daemon crashes at smb_nic_clear_niclist+0x45(815ff10, 2)
6629797 sharemgr: Deleting an SMB resource that has an option leads to core dump
6630470 Get core in sharemgr:libshare_smb.so.1`smb_enable_service+0x78(2ec90, fe87c49c, 0, ff396000,17e54,6)
--HG--
rename : usr/src/uts/common/smbsrv/smb_secdesc.h => deleted_files/usr/src/uts/common/smbsrv/smb_secdesc.h
Diffstat (limited to 'usr/src/lib')
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 *)¶m->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(¶m->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, ¶m->handle, sizeof (logr_handle_t)); - if (hostname_len == 0) { - if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) { - bzero(¶m->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)¶m->ru; + param->address = (DWORD)(uintptr_t)¶m->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)¶m->ru; + param->address = (DWORD)(uintptr_t)¶m->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(×tamp); - 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) |