diff options
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) |