diff options
46 files changed, 1382 insertions, 532 deletions
diff --git a/usr/src/cmd/idmap/idmap/Makefile b/usr/src/cmd/idmap/idmap/Makefile index 44c2cf7dc7..fa12170f8a 100644 --- a/usr/src/cmd/idmap/idmap/Makefile +++ b/usr/src/cmd/idmap/idmap/Makefile @@ -19,12 +19,11 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # PROG = idmap -CLIENTOBJS = idmap.o idmap_engine.o +CLIENTOBJS = idmap.o idmap_engine.o namemaps.o # idmap_clnt.o CLIENTSRCS = $(CLIENTOBJS:%.o=%.c) POFILES = $(CLIENTOBJS:.o=.po) @@ -35,11 +34,16 @@ IDMAP_PROT_DIR = $(SRC)/head/rpcsvc include ../../Makefile.cmd POFILE = $(PROG)_all.po -LDLIBS += -lidmap +LDLIBS += -lidmap -ladutils -lsldap -lldap FILEMODE = 0555 -INCS += -I. -I../../../lib/libidmap/common -I$(IDMAP_PROT_DIR) +INCS += -I. \ + -I../../../lib/libidmap/common \ + -I../../../lib/libadutils/common \ + -I../../../lib/libsldap/common \ + -I$(IDMAP_PROT_DIR) +CFLAGS += $(CCVERBOSE) $(OBJS) := CPPFLAGS += $(INCS) -D_REENTRANT $(POFILE) := CPPFLAGS += $(INCS) diff --git a/usr/src/cmd/idmap/idmap/idmap.c b/usr/src/cmd/idmap/idmap/idmap.c index 7543f6acc9..57c6b3bfe5 100644 --- a/usr/src/cmd/idmap/idmap/idmap.c +++ b/usr/src/cmd/idmap/idmap/idmap.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -35,6 +34,8 @@ #include <note.h> #include "idmap_engine.h" #include "idmap_priv.h" +#include "namemaps.h" +#include "libadutils.h" /* Initialization values for pids/rids: */ @@ -3541,12 +3542,16 @@ cleanup: /* printflike */ +static void -/* LINTED E_FUNC_ARG_UNUSED */ -logger(int pri, const char *format, ...) +idmap_cli_logger(int pri, const char *format, ...) { + NOTE(ARGUNUSED(pri)) va_list args; + if (pri == LOG_DEBUG) + return; + va_start(args, format); (void) vfprintf(stderr, format, args); @@ -3567,7 +3572,8 @@ main(int argc, char *argv[]) (void) textdomain(TEXT_DOMAIN); /* Redirect logging */ - idmap_set_logger(logger); + idmap_set_logger(idmap_cli_logger); + adutils_set_logger(idmap_cli_logger); /* idmap_engine determines the batch_mode: */ rc = engine_init(sizeof (commands) / sizeof (cmd_ops_t), diff --git a/usr/src/lib/libidmap/common/namemaps.c b/usr/src/cmd/idmap/idmap/namemaps.c index 95e47ddd6c..53c89f1554 100644 --- a/usr/src/lib/libidmap/common/namemaps.c +++ b/usr/src/cmd/idmap/idmap/namemaps.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -30,27 +29,13 @@ #include <libintl.h> #include <strings.h> #include <syslog.h> +#include <stdarg.h> #include "addisc.h" #include "libadutils.h" -#include "idmap_impl.h" +#include "idmap_priv.h" #include "ns_sldap.h" - -/* - * syslog is the default logger. - * It can be overwritten by supplying a logger - * with idmap_set_logger() - */ -idmap_logger logger = syslog; - - -void -idmap_set_logger(idmap_logger funct) -{ - logger = funct; - adutils_set_logger(funct); -} - +#include "namemaps.h" /* From adutils.c: */ @@ -75,6 +60,19 @@ struct idmap_nm_handle { ns_cred_t nsc; }; +/* PRINTFLIKE1 */ +static +void +namemap_log(char *fmt, ...) +{ + va_list va; + + va_start(va, fmt); + (void) vfprintf(stderr, fmt, va); + va_end(va); + (void) fprintf(stderr, "\n"); +} + static idmap_stat string2auth(const char *from, ns_auth_t *na) @@ -125,7 +123,7 @@ string2auth(const char *from, ns_auth_t *na) na->saslmech = NS_LDAP_SASL_DIGEST_MD5; na->saslopt = NS_LDAP_SASLOPT_NONE; } else { - logger(LOG_ERR, + namemap_log( gettext("Invalid authentication method \"%s\" specified\n"), from); return (IDMAP_ERR_ARG); @@ -197,8 +195,9 @@ idmap_open_ad_conn(idmap_nm_handle_t *adh) /* Open and bind an LDAP connection */ adh->ad = ldap_init(adh->ad_host, adh->ad_port); if (adh->ad == NULL) { - logger(LOG_INFO, "ldap_init() to server " - "%s port %d failed. (%s)", CHECK_NULL(adh->ad_host), + namemap_log( + gettext("ldap_init() to server %s port %d failed. (%s)"), + CHECK_NULL(adh->ad_host), adh->ad_port, strerror(errno)); rc = IDMAP_ERR_INTERNAL; goto out; @@ -217,8 +216,9 @@ idmap_open_ad_conn(idmap_nm_handle_t *adh) if (ldap_rc != LDAP_SUCCESS) { (void) ldap_unbind(adh->ad); adh->ad = NULL; - logger(LOG_INFO, "ldap_sasl_interactive_bind_s() to server " - "%s port %d failed. (%s)", CHECK_NULL(adh->ad_host), + namemap_log( + gettext("ldap_sasl_interactive_bind_s() to server " + "%s port %d failed. (%s)"), CHECK_NULL(adh->ad_host), adh->ad_port, ldap_err2string(ldap_rc)); rc = IDMAP_ERR_INTERNAL; } @@ -249,7 +249,7 @@ idmap_init_ad(idmap_nm_handle_t *p) ad_ctx = ad_disc_init(); if (ad_ctx == NULL) { - logger(LOG_ERR, + namemap_log( gettext("AD autodiscovery initialization failed")); return (IDMAP_ERR_INTERNAL); } @@ -259,7 +259,7 @@ idmap_init_ad(idmap_nm_handle_t *p) /* Based on the supplied or default domain, find the proper AD: */ if (ad_disc_set_DomainName(ad_ctx, p->windomain)) { rc = IDMAP_ERR_INTERNAL; - logger(LOG_ERR, + namemap_log( gettext("Setting a domain name \"%s\" for autodiscovery" " failed, most likely not enough memory"), p->windomain); goto cleanup; @@ -268,7 +268,7 @@ idmap_init_ad(idmap_nm_handle_t *p) dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL, NULL); if (dc == NULL) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("A domain controller for the " "domain \"%s\" not found."), p->windomain); goto cleanup; @@ -365,7 +365,7 @@ idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, rc = idmap_get_prop_str(handle, PROP_DEFAULT_DOMAIN, &p->default_domain); if (rc != IDMAP_SUCCESS) { - logger(LOG_ERR, + namemap_log( gettext("Error obtaining default domain from idmapd (%s)"), idmap_stat2string(NULL, rc)); goto cleanup; @@ -374,7 +374,7 @@ idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, rc = idmap_get_prop_str(handle, PROP_AD_UNIXUSER_ATTR, &p->ad_unixuser_attr); if (rc != IDMAP_SUCCESS) { - logger(LOG_ERR, + namemap_log( gettext("Error obtaining AD unixuser attribute (%s)"), idmap_stat2string(NULL, rc)); goto cleanup; @@ -383,7 +383,7 @@ idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, rc = idmap_get_prop_str(handle, PROP_AD_UNIXGROUP_ATTR, &p->ad_unixgroup_attr); if (rc != IDMAP_SUCCESS) { - logger(LOG_ERR, + namemap_log( gettext("Error obtaining AD unixgroup attribute (%s)"), idmap_stat2string(NULL, rc)); goto cleanup; @@ -393,7 +393,7 @@ idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, rc = idmap_get_prop_str(handle, PROP_NLDAP_WINNAME_ATTR, &p->nldap_winname_attr); if (rc != IDMAP_SUCCESS) { - logger(LOG_ERR, + namemap_log( gettext("Error obtaining AD unixgroup attribute (%s)"), idmap_stat2string(NULL, rc)); goto cleanup; @@ -412,7 +412,7 @@ idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh, goto cleanup; } } else if (direction == IDMAP_DIRECTION_W2U) { - logger(LOG_ERR, + namemap_log( gettext("Windows domain not given and idmapd daemon" " didn't provide a default one")); rc = IDMAP_ERR_ARG; @@ -590,7 +590,7 @@ unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn, if (rc_ns == NS_LDAP_NOTFOUND) { - logger(LOG_ERR, is_user ? gettext("User \"%s\" not found.") + namemap_log(is_user ? gettext("User %s not found.") : gettext("Group %s not found."), unixname); return (IDMAP_ERR_NOTFOUND); } else if (rc_ns != NS_LDAP_SUCCESS) { @@ -598,12 +598,12 @@ unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn, if (errorp != NULL) { (void) __ns_ldap_err2str(errorp->status, &msg); } - logger(LOG_ERR, gettext("Ldap list failed (%s)."), msg); + namemap_log(gettext("Ldap list failed (%s)."), msg); return (IDMAP_ERR_ARG); } if (res == NULL) { - logger(LOG_ERR, gettext("User %s not found"), unixname); + namemap_log(gettext("User %s not found"), unixname); return (IDMAP_ERR_ARG); } @@ -620,7 +620,7 @@ unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn, if (dn != NULL) { attrs = __ns_ldap_getAttr(&res->entry[0], "dn"); if (attrs == NULL || attrs[0] == NULL) { - logger(LOG_ERR, gettext("dn for %s not found"), + namemap_log(gettext("dn for %s not found"), unixname); return (IDMAP_ERR_ARG); } @@ -680,8 +680,8 @@ winname2dn(idmap_nm_handle_t *p, char *winname, free(filter); if (ldap_rc != LDAP_SUCCESS) { - logger(LOG_ERR, - "Ldap query to server %s port %d failed. (%s)", + namemap_log( + gettext("Ldap query to server %s port %d failed. (%s)"), p->ad_host, p->ad_port, ldap_err2string(ldap_rc)); (void) ldap_msgfree(results); return (IDMAP_ERR_OTHER); @@ -727,7 +727,7 @@ winname2dn(idmap_nm_handle_t *p, char *winname, } if (*dn == NULL) { - logger(LOG_ERR, + namemap_log( *is_wuser == IDMAP_YES ? gettext("User %s@%s not found") : *is_wuser == IDMAP_NO ? gettext("Group %s@%s not found") : gettext("%s@%s not found"), winname, p->windomain); @@ -771,8 +771,8 @@ idmap_ad_set(idmap_nm_handle_t *p, char *dn, char *attr, char *value) ldap_rc = ldap_modify_s(p->ad, dn, mods); if (ldap_rc != LDAP_SUCCESS) { - logger(LOG_ERR, - "Ldap modify of %s, attribute %s failed. (%s)", + namemap_log( + gettext("Ldap modify of %s, attribute %s failed. (%s)"), dn, attr, ldap_err2string(ldap_rc)); rc = IDMAP_ERR_INTERNAL; } @@ -845,8 +845,9 @@ idmap_nldap_set(idmap_nm_handle_t *p, ns_cred_t *nsc, char *dn, char *attr, if (errorp != NULL) { (void) __ns_ldap_err2str(errorp->status, &msg); } - logger(LOG_ERR, gettext("__ns_ldap_addAttr/rep/delAttr" - " failed (%s)"), msg); + namemap_log( + gettext("__ns_ldap_addAttr/rep/delAttr failed (%s)"), + msg); return (IDMAP_ERR_ARG); } @@ -865,7 +866,7 @@ idmap_set_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, if (direction == IDMAP_DIRECTION_W2U) { if (!p->is_ad) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("AD namemaps aren't set up.")); goto cleanup; } @@ -888,7 +889,7 @@ idmap_set_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, if (!p->is_nldap) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("Native ldap namemaps aren't set up.")); goto cleanup; } @@ -955,7 +956,7 @@ idmap_unset_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, if (direction == IDMAP_DIRECTION_W2U) { if (!p->is_ad) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("AD namemaps aren't set up.")); goto cleanup; } @@ -973,7 +974,7 @@ idmap_unset_namemap(idmap_nm_handle_t *p, char *winname, char *unixname, } else { /* direction == IDMAP_DIRECTION_U2W */ if (!p->is_nldap) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("Native ldap namemaps aren't set up.")); goto cleanup; } @@ -1012,7 +1013,7 @@ idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname, if (p->is_ad == NULL) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("AD namemaps are not active.")); goto cleanup; /* In future maybe resolve winname and try nldap? */ @@ -1021,7 +1022,7 @@ idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname, rc = winname2dn(p, *winname, is_wuser, &dn, unixuser, unixgroup); if (rc != IDMAP_SUCCESS) { - logger(LOG_ERR, + namemap_log( gettext("Winname %s@%s not found in AD."), *winname, p->windomain); } @@ -1033,7 +1034,7 @@ idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname, if (p->is_nldap == NULL) { rc = IDMAP_ERR_ARG; - logger(LOG_ERR, + namemap_log( gettext("Native ldap namemaps aren't active.")); goto cleanup; /* In future maybe resolve unixname and try AD? */ @@ -1050,7 +1051,7 @@ idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname, rc = unixname2dn(p, unixname, is_user, NULL, winname, windomain); if (rc != IDMAP_SUCCESS) { - logger(LOG_ERR, + namemap_log( gettext("%s %s not found in native ldap."), is_user == IDMAP_YES ? "UNIX user" : "UNIX group", unixname); diff --git a/usr/src/cmd/idmap/idmap/namemaps.h b/usr/src/cmd/idmap/idmap/namemaps.h new file mode 100644 index 0000000000..4587406d6c --- /dev/null +++ b/usr/src/cmd/idmap/idmap/namemaps.h @@ -0,0 +1,62 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * Additional API for Identity Mapping Service + */ + +#ifndef NAMEMAPS_H +#define NAMEMAPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Directory based name map API + */ + +typedef struct idmap_nm_handle idmap_nm_handle_t; + +/* Set namemap */ +extern idmap_stat idmap_set_namemap(idmap_nm_handle_t *, char *, char *, + int, int, int); + +/* Unset namemap */ +extern idmap_stat idmap_unset_namemap(idmap_nm_handle_t *, char *, char *, + int, int, int); + +extern idmap_stat idmap_get_namemap(idmap_nm_handle_t *p, int *, char **, + char **, int *, char **, char **); + +extern void idmap_fini_namemaps(idmap_nm_handle_t *); + +extern idmap_stat idmap_init_namemaps(idmap_handle_t *, idmap_nm_handle_t **, + char *, char *, char *, char *, int); + +#ifdef __cplusplus +} +#endif + +#endif /* NAMEMAPS_H */ diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.c b/usr/src/cmd/idmap/idmapd/idmap_config.c index e11d0f8d47..c25f6da2fc 100644 --- a/usr/src/cmd/idmap/idmapd/idmap_config.c +++ b/usr/src/cmd/idmap/idmapd/idmap_config.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -50,6 +49,14 @@ #define RECONFIGURE 1 #define POKE_AUTO_DISCOVERY 2 +enum event_type { + EVENT_NOTHING, /* Woke up for no good reason */ + EVENT_TIMEOUT, /* Timeout expired */ + EVENT_ROUTING, /* An interesting routing event happened */ + EVENT_DEGRADE, /* An error occurred in the mainline */ + EVENT_REFRESH, /* SMF refresh */ +}; + /*LINTLIBRARY*/ @@ -893,8 +900,6 @@ enum_lookup(int value, struct enum_lookup_map *map) return ("(invalid)"); } -#define MAX_CHECK_TIME (20 * 60) - /* * Returns 1 if the PF_ROUTE socket event indicates that we should rescan the * interfaces. @@ -902,13 +907,13 @@ enum_lookup(int value, struct enum_lookup_map *map) * Shamelessly based on smb_nics_changed() and other PF_ROUTE uses in ON. */ static -int +boolean_t pfroute_event_is_interesting(int rt_sock) { int nbytes; int64_t msg[2048 / 8]; struct rt_msghdr *rtm; - int is_interesting = FALSE; + boolean_t is_interesting = B_FALSE; for (;;) { if ((nbytes = read(rt_sock, msg, sizeof (msg))) <= 0) @@ -922,7 +927,7 @@ pfroute_event_is_interesting(int rt_sock) case RTM_NEWADDR: case RTM_DELADDR: case RTM_IFINFO: - is_interesting = TRUE; + is_interesting = B_TRUE; break; default: break; @@ -932,131 +937,161 @@ pfroute_event_is_interesting(int rt_sock) } /* - * Returns 1 if SIGHUP has been received (see hup_handler() elsewhere) or if an - * interface address was added or removed; otherwise it returns 0. + * Wait for an event, and report what kind of event occurred. * - * Note that port_get() does not update its timeout argument when EINTR, unlike - * nanosleep(). We probably don't care very much here, but if we did care then - * we could always use a timer event and associate it with the same event port, - * then we could get accurate waiting regardless of EINTRs. + * Note that there are cases where we are awoken but don't care about + * the lower-level event. We can't just loop here because we can't + * readily calculate how long to sleep the next time. We return + * EVENT_NOTHING and let the caller loop. */ static -int -wait_for_event(int poke_is_interesting, struct timespec *timeoutp) +enum event_type +wait_for_event(struct timespec *timeoutp) { port_event_t pe; -retry: memset(&pe, 0, sizeof (pe)); if (port_get(idmapd_ev_port, &pe, timeoutp) != 0) { switch (errno) { case EINTR: - goto retry; + return (EVENT_NOTHING); case ETIME: /* Timeout */ - return (FALSE); + return (EVENT_TIMEOUT); default: /* EBADF, EBADFD, EFAULT, EINVAL (end of time?)? */ idmapdlog(LOG_ERR, "Event port failed: %s", strerror(errno)); exit(1); /* NOTREACHED */ - break; } } - if (pe.portev_source == PORT_SOURCE_USER && - pe.portev_events == POKE_AUTO_DISCOVERY) - return (poke_is_interesting ? TRUE : FALSE); - if (pe.portev_source == PORT_SOURCE_FD && pe.portev_object == rt_sock) { - /* PF_ROUTE socket read event, re-associate fd, handle event */ - if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, rt_sock, - POLLIN, NULL) != 0) { - idmapdlog(LOG_ERR, "Failed to re-associate the " - "routing socket with the event port: %s", - strerror(errno)); - exit(1); - } + switch (pe.portev_source) { + case 0: /* - * The network configuration may still be in flux. No matter, - * the resolver will re-transmit and timout if need be. + * This isn't documented, but seems to be what you get if + * the timeout is zero seconds and there are no events + * pending. */ - return (pfroute_event_is_interesting(rt_sock)); - } + return (EVENT_TIMEOUT); - if (pe.portev_source == PORT_SOURCE_USER && - pe.portev_events == RECONFIGURE) { - int rc; + case PORT_SOURCE_USER: + if (pe.portev_events == POKE_AUTO_DISCOVERY) + return (EVENT_DEGRADE); + if (pe.portev_events == RECONFIGURE) + return (EVENT_REFRESH); + break; - /* - * Blow away the ccache, we might have re-joined the - * domain or joined a new one - */ - (void) unlink(IDMAP_CACHEDIR "/ccache"); - /* HUP is the refresh method, so re-read SMF config */ - idmapdlog(LOG_INFO, "SMF refresh"); - rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER|CFG_LOG); - if (rc < -1) { - idmapdlog(LOG_ERR, "Fatal errors while reading " - "SMF properties"); - exit(1); - } else if (rc == -1) { - idmapdlog(LOG_WARNING, "Various errors " - "re-loading configuration may cause AD lookups " - "to fail"); + case PORT_SOURCE_FD: + if (pe.portev_object == rt_sock) { + /* + * PF_ROUTE socket read event: + * re-associate fd + * handle event + */ + if (port_associate(idmapd_ev_port, PORT_SOURCE_FD, + rt_sock, POLLIN, NULL) != 0) { + idmapdlog(LOG_ERR, "Failed to re-associate the " + "routing socket with the event port: %s", + strerror(errno)); + abort(); + } + /* + * The network configuration may still be in flux. + * No matter, the resolver will re-transmit and + * timeout if need be. + */ + if (pfroute_event_is_interesting(rt_sock)) { + idmapdlog(LOG_DEBUG, + "Interesting routing event"); + return (EVENT_ROUTING); + } else { + idmapdlog(LOG_DEBUG, + "Boring routing event"); + return (EVENT_NOTHING); + } } - return (FALSE); + /* Event on an FD other than the routing FD? Ignore it. */ + break; } - return (FALSE); + return (EVENT_NOTHING); } void * idmap_cfg_update_thread(void *arg) { - int ttl, changed, poke_is_interesting; - idmap_cfg_handles_t *handles = &_idmapdstate.cfg->handles; - ad_disc_t ad_ctx = handles->ad_ctx; - struct timespec timeout, *timeoutp; + const ad_disc_t ad_ctx = _idmapdstate.cfg->handles.ad_ctx; - poke_is_interesting = 1; - for (ttl = 0, changed = TRUE; ; ttl = ad_disc_get_TTL(ad_ctx)) { - /* - * If ttl < 0 then we can wait for an event without timing out. - * If idmapd needs to notice that the system has been joined to - * a Windows domain then idmapd needs to be refreshed. - */ - timeoutp = (ttl < 0) ? NULL : &timeout; - if (ttl > MAX_CHECK_TIME) - ttl = MAX_CHECK_TIME; - timeout.tv_sec = ttl; - timeout.tv_nsec = 0; - changed = wait_for_event(poke_is_interesting, timeoutp); - - /* - * If there are no interesting events, and this is not the first - * time through the loop, and we haven't waited the most that - * we're willing to wait, so do nothing but wait some more. - */ - if (changed == FALSE && ttl > 0 && ttl < MAX_CHECK_TIME) - continue; + for (;;) { + struct timespec timeout; + struct timespec *timeoutp; + int rc; + int ttl; (void) ad_disc_SubnetChanged(ad_ctx); - if (idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER) < -1) { + rc = idmap_cfg_load(_idmapdstate.cfg, CFG_DISCOVER); + if (rc < -1) { idmapdlog(LOG_ERR, "Fatal errors while reading " "SMF properties"); exit(1); + } else if (rc == -1) { + idmapdlog(LOG_WARNING, + "Errors re-loading configuration may cause AD " + "lookups to fail"); } - if (_idmapdstate.cfg->pgcfg.global_catalog == NULL || - _idmapdstate.cfg->pgcfg.global_catalog[0].host[0] == '\0') - poke_is_interesting = 1; - else - poke_is_interesting = 0; + /* + * Wait for an interesting event. Note that we might get + * boring events between interesting events. If so, we loop. + */ + for (;;) { + ttl = ad_disc_get_TTL(ad_ctx); + + if (ttl < 0) { + timeoutp = NULL; + } else { + timeoutp = &timeout; + timeout.tv_sec = ttl; + timeout.tv_nsec = 0; + } + + switch (wait_for_event(timeoutp)) { + case EVENT_NOTHING: + idmapdlog(LOG_DEBUG, "Boring event."); + continue; + case EVENT_REFRESH: + idmapdlog(LOG_INFO, "SMF refresh"); + /* + * Blow away the ccache, we might have + * re-joined the domain or joined a new one + */ + (void) unlink(IDMAP_CACHEDIR "/ccache"); + break; + case EVENT_DEGRADE: + idmapdlog(LOG_DEBUG, + "Service degraded"); + break; + case EVENT_TIMEOUT: + idmapdlog(LOG_DEBUG, "TTL expired"); + break; + case EVENT_ROUTING: + /* Already logged to DEBUG */ + break; + } + /* An interesting event! */ + break; + } } + /* + * Lint isn't happy with the concept of a function declared to + * return something, that doesn't return. Of course, merely adding + * the return isn't enough, because it's never reached... + */ /*NOTREACHED*/ return (NULL); } @@ -1356,6 +1391,8 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) idmap_trustedforest_t *trustedforests; ad_disc_domainsinforest_t *domainsinforest; + idmapdlog(LOG_DEBUG, "Running discovery."); + ad_disc_refresh(ad_ctx); if (pgcfg->default_domain == NULL) @@ -1524,6 +1561,9 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) "unable to discover Domains in the Forest"); if (pgcfg->trusted_domains == NULL) idmapdlog(LOG_DEBUG, "unable to discover Trusted Domains"); + + ad_disc_done(ad_ctx); + idmapdlog(LOG_DEBUG, "Discovery done."); } diff --git a/usr/src/cmd/idmap/idmapd/idmapd.c b/usr/src/cmd/idmap/idmapd/idmapd.c index 720b209240..5ea3292acd 100644 --- a/usr/src/cmd/idmap/idmapd/idmapd.c +++ b/usr/src/cmd/idmap/idmapd/idmapd.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -293,6 +292,7 @@ main(int argc, char **argv) (void) textdomain(TEXT_DOMAIN); idmap_set_logger(idmapdlog); + adutils_set_logger(idmapdlog); idmap_log_syslog(B_TRUE); idmap_log_stderr(_idmapdstate.daemon_mode ? -1 : LOG_DEBUG); @@ -488,13 +488,6 @@ degrade_svc(int poke_discovery, const char *reason) { const char *fmri; - /* - * If the config update thread is in a state where auto-discovery could - * be re-tried, then this will make it try it -- a sort of auto-refresh. - */ - if (poke_discovery) - idmap_cfg_poke_updates(); - membar_consumer(); if (degraded) return; @@ -509,6 +502,13 @@ degrade_svc(int poke_discovery, const char *reason) if ((fmri = get_fmri()) != NULL) (void) smf_degrade_instance(fmri, 0); + + /* + * If the config update thread is in a state where auto-discovery could + * be re-tried, then this will make it try it -- a sort of auto-refresh. + */ + if (poke_discovery) + idmap_cfg_poke_updates(); } void diff --git a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c index 7dc3eef535..e936029edc 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/list.h> @@ -45,10 +44,13 @@ #include <smbsrv/libsmbns.h> #include "smbd.h" +#define SMBD_ARG_MAGIC 0x53415247 /* 'SARG' */ + /* * Parameter for door operations. */ typedef struct smbd_arg { + uint32_t magic; list_node_t lnd; smb_doorhdr_t hdr; const char *opname; @@ -56,6 +58,8 @@ typedef struct smbd_arg { size_t datalen; char *rbuf; size_t rsize; + boolean_t response_ready; + boolean_t response_abort; uint32_t status; } smbd_arg_t; @@ -254,7 +258,6 @@ smbd_door_dispatch(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, hdr->dh_door_rc = SMB_DOP_SUCCESS; else hdr->dh_door_rc = SMB_DOP_NOT_CALLED; - } else { (void) smbd_door_dispatch_op(&dop_arg); } @@ -318,6 +321,7 @@ smbd_door_dispatch_async(smbd_arg_t *req_arg) } (void) mutex_lock(&smbd_doorsvc.sd_mutex); + arg->magic = SMBD_ARG_MAGIC; list_insert_tail(&smbd_doorsvc.sd_async_list, arg); ++smbd_doorsvc.sd_async_count; (void) mutex_unlock(&smbd_doorsvc.sd_mutex); @@ -346,9 +350,13 @@ static void smbd_door_release_async(smbd_arg_t *arg) { if (arg != NULL) { + assert(arg->magic == SMBD_ARG_MAGIC); + arg->magic = (uint32_t)~SMBD_ARG_MAGIC; + list_remove(&smbd_doorsvc.sd_async_list, arg); --smbd_doorsvc.sd_async_count; free(arg->data); + arg->data = NULL; free(arg); } } @@ -358,6 +366,10 @@ smbd_door_release_async(smbd_arg_t *arg) * - synchronous calls are invoked by direct function call * - asynchronous calls are invoked from a launched thread * + * If the kernel has attempted to collect a response before the op + * has completed, the arg will have been marked as response_abort + * and we can discard the response data and release the arg. + * * We send a notification when asynchronous (ASYNC) door calls * from the kernel (SYSSPACE) have completed. */ @@ -385,6 +397,17 @@ smbd_door_dispatch_op(void *thread_arg) if ((hdr->dh_flags & SMB_DF_SYSSPACE) && (hdr->dh_flags & SMB_DF_ASYNC)) { assert(hdr->dh_op != SMB_DR_ASYNC_RESPONSE); + + (void) mutex_lock(&smbd_doorsvc.sd_mutex); + if (arg->response_abort) { + free(arg->rbuf); + arg->rbuf = NULL; + smbd_door_release_async(arg); + } else { + arg->response_ready = B_TRUE; + } + (void) mutex_unlock(&smbd_doorsvc.sd_mutex); + (void) smb_kmod_event_notify(hdr->dh_txid); } @@ -484,6 +507,10 @@ smbd_dop_null(smbd_arg_t *arg) * Async response handler: setup the rbuf and rsize for the specified * transaction. This function is used by the kernel to collect the * response half of an asynchronous door call. + * + * If a door client attempts to collect a response before the op has + * completed (!response_ready), mark the arg as response_abort and + * set an error. The response will be discarded when the op completes. */ static int smbd_dop_async_response(smbd_arg_t *rsp_arg) @@ -495,7 +522,17 @@ smbd_dop_async_response(smbd_arg_t *rsp_arg) arg = list_head(arg_list); while (arg != NULL) { + assert(arg->magic == SMBD_ARG_MAGIC); + if (arg->hdr.dh_txid == rsp_arg->hdr.dh_txid) { + if (!arg->response_ready) { + arg->response_abort = B_TRUE; + rsp_arg->hdr.dh_door_rc = SMB_DOP_NOT_CALLED; + syslog(LOG_NOTICE, "doorsvc[%s]: %u not ready", + arg->opname, arg->hdr.dh_txid); + break; + } + rsp_arg->rbuf = arg->rbuf; rsp_arg->rsize = arg->rsize; arg->rbuf = NULL; @@ -514,7 +551,7 @@ smbd_dop_async_response(smbd_arg_t *rsp_arg) static int smbd_dop_user_nonauth_logon(smbd_arg_t *arg) { - uint32_t sid; + uint32_t sid = 0; if (smb_common_decode(arg->data, arg->datalen, xdr_uint32_t, &sid) != 0) @@ -527,7 +564,7 @@ smbd_dop_user_nonauth_logon(smbd_arg_t *arg) static int smbd_dop_user_auth_logoff(smbd_arg_t *arg) { - uint32_t sid; + uint32_t sid = 0; if (smb_common_decode(arg->data, arg->datalen, xdr_uint32_t, &sid) != 0) @@ -574,6 +611,8 @@ smbd_dop_lookup_name(smbd_arg_t *arg) lsa_account_t acct; char buf[MAXNAMELEN]; + bzero(&acct, sizeof (lsa_account_t)); + if (smb_common_decode(arg->data, arg->datalen, lsa_account_xdr, &acct) != 0) return (SMB_DOP_DECODE_ERROR); @@ -617,6 +656,8 @@ smbd_dop_lookup_sid(smbd_arg_t *arg) lsa_account_t acct; smb_sid_t *sid; + bzero(&acct, sizeof (lsa_account_t)); + if (smb_common_decode(arg->data, arg->datalen, lsa_account_xdr, &acct) != 0) return (SMB_DOP_DECODE_ERROR); @@ -653,6 +694,8 @@ smbd_dop_join(smbd_arg_t *arg) smb_joininfo_t jdi; uint32_t status; + bzero(&jdi, sizeof (smb_joininfo_t)); + if (smb_common_decode(arg->data, arg->datalen, smb_joininfo_xdr, &jdi) != 0) return (SMB_DOP_DECODE_ERROR); diff --git a/usr/src/cmd/smbsrv/smbd/smbd_logon.c b/usr/src/cmd/smbsrv/smbd/smbd_logon.c index 97f9e47b51..fe27e9cd7f 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/types.h> @@ -36,6 +35,9 @@ #include <bsm/adt.h> #include <bsm/adt_event.h> #include <bsm/audit_uevents.h> +#include <pwd.h> +#include <nss_dbdefs.h> +#include <sys/idmap.h> #include "smbd.h" @@ -212,11 +214,20 @@ smbd_user_auth_logoff(uint32_t audit_sid) smb_audit_t *entry; adt_session_data_t *ah; adt_event_data_t *event; + struct passwd pw; + char buf[NSS_LINELEN_PASSWD]; if ((entry = smbd_audit_unlink(audit_sid)) == NULL) return; - smb_autohome_remove(entry->sa_username); + if (IDMAP_ID_IS_EPHEMERAL(entry->sa_uid)) { + smb_autohome_remove(entry->sa_username); + } else { + if (getpwuid_r(entry->sa_uid, &pw, buf, sizeof (buf)) == NULL) + return; + + smb_autohome_remove(pw.pw_name); + } ah = entry->sa_handle; diff --git a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c index 5ec93bd59f..3792e23853 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -257,16 +256,12 @@ smbd_share_dispatch(void *cookie, char *ptr, size_t size, door_desc_t *dp, case SMB_SHROP_ENUM: esi.es_bufsize = smb_dr_get_ushort(dec_ctx); - esi.es_username = smb_dr_get_string(dec_ctx); - if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) { - smb_dr_free_string(esi.es_username); + esi.es_posix_uid = smb_dr_get_uint32(dec_ctx); + if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) goto decode_error; - } rc = smbd_share_enum(&esi); - smb_dr_free_string(esi.es_username); - smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS); smb_dr_put_uint32(enc_ctx, rc); if (rc == NERR_Success) { @@ -380,7 +375,7 @@ smbd_share_enum(smb_enumshare_info_t *esi) continue; if ((si->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { - if (strcasecmp(esi->es_username, si->shr_name) == 0) + if (esi->es_posix_uid == si->shr_uid) autohome_added = B_TRUE; else continue; @@ -417,7 +412,7 @@ smbd_share_enum(smb_enumshare_info_t *esi) continue; if ((si->shr_flags & SMB_SHRF_AUTOHOME) && !autohome_added) { - if (strcasecmp(esi->es_username, si->shr_name) == 0) + if (esi->es_posix_uid == si->shr_uid) autohome_added = B_TRUE; else continue; diff --git a/usr/src/common/smbsrv/smb_xdr.c b/usr/src/common/smbsrv/smb_xdr.c index 43276d0910..46d2e2ca49 100644 --- a/usr/src/common/smbsrv/smb_xdr.c +++ b/usr/src/common/smbsrv/smb_xdr.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/sunddi.h> @@ -236,7 +235,7 @@ smb_netuserinfo_xdr(XDR *xdrs, smb_netuserinfo_t *objp) { if (!xdr_uint64_t(xdrs, &objp->ui_session_id)) return (FALSE); - if (!xdr_uint16_t(xdrs, &objp->ui_uid)) + if (!xdr_uint16_t(xdrs, &objp->ui_smb_uid)) return (FALSE); if (!xdr_uint16_t(xdrs, &objp->ui_domain_len)) return (FALSE); @@ -246,6 +245,8 @@ smb_netuserinfo_xdr(XDR *xdrs, smb_netuserinfo_t *objp) return (FALSE); if (!xdr_string(xdrs, &objp->ui_account, ~0)) return (FALSE); + if (!xdr_uint32_t(xdrs, &objp->ui_posix_uid)) + return (FALSE); if (!xdr_uint16_t(xdrs, &objp->ui_workstation_len)) return (FALSE); if (!xdr_string(xdrs, &objp->ui_workstation, ~0)) diff --git a/usr/src/lib/libadutils/common/addisc.c b/usr/src/lib/libadutils/common/addisc.c index b32f9d7694..187981b5a2 100644 --- a/usr/src/lib/libadutils/common/addisc.c +++ b/usr/src/lib/libadutils/common/addisc.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -103,6 +102,16 @@ #include "adutils_impl.h" #include "addisc.h" +/* + * These set some sanity policies for discovery. After a discovery + * cycle, we will consider the results (successful or unsuccessful) + * to be valid for at least MINIMUM_TTL seconds, and for at most + * MAXIMUM_TTL seconds. Note that the caller is free to request + * discovery cycles sooner than MINIMUM_TTL if it has reason to believe + * that the situation has changed. + */ +#define MINIMUM_TTL (5 * 60) +#define MAXIMUM_TTL (20 * 60) enum ad_item_state { AD_STATE_INVALID = 0, /* The value is not valid */ @@ -127,7 +136,7 @@ typedef struct ad_item { enum ad_item_state state; enum ad_data_type type; void *value; - time_t ttl; + time_t expires; unsigned int version; /* Version is only changed */ /* if the value changes */ #define PARAM1 0 @@ -144,6 +153,8 @@ typedef struct ad_disc { ad_subnet_t *subnets; boolean_t subnets_changed; time_t subnets_last_check; + time_t expires_not_before; + time_t expires_not_after; ad_item_t domain_name; /* DNS hostname string */ ad_item_t domain_controller; /* Directory hostname and */ /* port array */ @@ -216,7 +227,7 @@ is_valid(ad_item_t *item) if (item->state == AD_STATE_FIXED) return (B_TRUE); if (item->state == AD_STATE_AUTO && - (item->ttl == 0 || item->ttl > time(NULL))) + (item->expires == 0 || item->expires > time(NULL))) return (B_TRUE); } return (B_FALSE); @@ -247,9 +258,9 @@ update_item(ad_item_t *item, void *value, enum ad_item_state state, item->state = state; if (ttl == 0) - item->ttl = 0; + item->expires = 0; else - item->ttl = time(NULL) + ttl; + item->expires = time(NULL) + ttl; } @@ -593,26 +604,6 @@ DN_to_DNS(const char *dn_name) } -/* Format the DN of an AD LDAP subnet object for some subnet */ -static char * -subnet_to_DN(const char *subnet, const char *baseDN) -{ - char *result; - int len; - - len = snprintf(NULL, 0, - "CN=%s,CN=Subnets,CN=Sites,%s", - subnet, baseDN) + 1; - - result = malloc(len); - if (result != NULL) - (void) snprintf(result, len, - "CN=%s,CN=Subnets,CN=Sites,%s", - subnet, baseDN); - return (result); -} - - /* Make a list of subnet object DNs from a list of subnets */ static char ** subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn) @@ -628,8 +619,9 @@ subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn) return (NULL); for (i = 0; subnets[i].subnet[0] != '\0'; i++) { - if ((results[i] = subnet_to_DN(subnets[i].subnet, base_dn)) - == NULL) { + (void) asprintf(&results[i], "CN=%s,CN=Subnets,CN=Sites,%s", + subnets[i].subnet, base_dn); + if (results[i] == NULL) { for (j = 0; j < i; j++) free(results[j]); free(results); @@ -828,7 +820,8 @@ err: * A utility function to bind to a Directory server */ -static LDAP* +static +LDAP * ldap_lookup_init(idmap_ad_disc_ds_t *ds) { int i; @@ -988,15 +981,17 @@ ldap_lookup_trusted_domains(LDAP **ld, idmap_ad_disc_ds_t *globalCatalog, if (partner != NULL && direction != NULL) { num++; - trusted_domains = realloc(trusted_domains, + void *tmp = realloc(trusted_domains, (num + 1) * sizeof (ad_disc_trusteddomains_t)); - if (trusted_domains == NULL) { + if (tmp == NULL) { + free(trusted_domains); ldap_value_free(partner); ldap_value_free(direction); ldap_msgfree(results); return (NULL); } + trusted_domains = tmp; /* Last element should be zero */ memset(&trusted_domains[num], 0, sizeof (ad_disc_trusteddomains_t)); @@ -1221,6 +1216,22 @@ ad_disc_refresh(ad_disc_t ctx) } +/* + * Called when the discovery cycle is done. Sets a master TTL + * that will avoid doing new time-based discoveries too soon after + * the last discovery cycle. Most interesting when the discovery + * cycle failed, because then the TTLs on the individual items will + * not be updated and may go stale. + */ +void +ad_disc_done(ad_disc_t ctx) +{ + time_t now = time(NULL); + + ctx->expires_not_before = now + MINIMUM_TTL; + ctx->expires_not_after = now + MAXIMUM_TTL; +} + /* Discover joined Active Directory domainName */ static ad_item_t * @@ -1425,12 +1436,13 @@ validate_SiteName(ad_disc_t ctx) return (NULL); if (!is_valid(&ctx->site_name) || - is_changed(&ctx->site_name, PARAM1, &ctx->domain_controller) || + is_changed(&ctx->site_name, PARAM1, domain_controller_item) || ctx->subnets == NULL || ctx->subnets_changed) { subnets = find_subnets(); ctx->subnets_last_check = time(NULL); update_required = B_TRUE; } else if (ctx->subnets_last_check + 60 < time(NULL)) { + /* NEEDSWORK magic constant 60 above */ subnets = find_subnets(); ctx->subnets_last_check = time(NULL); if (cmpsubnets(ctx->subnets, subnets) != 0) @@ -1471,6 +1483,8 @@ validate_SiteName(ad_disc_t ctx) forest_name = DN_to_DNS(config_naming_context + len); update_item(&ctx->forest_name, forest_name, AD_STATE_AUTO, 0); + update_version(&ctx->forest_name, PARAM1, + domain_controller_item); } } @@ -1495,6 +1509,8 @@ validate_SiteName(ad_disc_t ctx) site_name[len] = '\0'; update_item(&ctx->site_name, site_name, AD_STATE_AUTO, 0); + update_version(&ctx->site_name, PARAM1, + domain_controller_item); } } @@ -1997,17 +2013,33 @@ ad_disc_unset(ad_disc_t ctx) int ad_disc_get_TTL(ad_disc_t ctx) { + time_t expires; int ttl; - ttl = MIN_GT_ZERO(ctx->domain_controller.ttl, ctx->global_catalog.ttl); - ttl = MIN_GT_ZERO(ttl, ctx->site_domain_controller.ttl); - ttl = MIN_GT_ZERO(ttl, ctx->site_global_catalog.ttl); + expires = MIN_GT_ZERO(ctx->domain_controller.expires, + ctx->global_catalog.expires); + expires = MIN_GT_ZERO(expires, ctx->site_domain_controller.expires); + expires = MIN_GT_ZERO(expires, ctx->site_global_catalog.expires); - if (ttl == -1) + if (expires == -1) { return (-1); - ttl -= time(NULL); - if (ttl < 0) + } + + if (ctx->expires_not_before != 0 && + expires < ctx->expires_not_before) { + expires = ctx->expires_not_before; + } + + if (ctx->expires_not_after != 0 && + expires > ctx->expires_not_after) { + expires = ctx->expires_not_after; + } + + ttl = expires - time(NULL); + + if (ttl < 0) { return (0); + } return (ttl); } diff --git a/usr/src/lib/libadutils/common/addisc.h b/usr/src/lib/libadutils/common/addisc.h index faf3393523..c8a3ca17d2 100644 --- a/usr/src/lib/libadutils/common/addisc.h +++ b/usr/src/lib/libadutils/common/addisc.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _ADINFO_H @@ -125,6 +124,12 @@ ad_disc_set_GlobalCatalog(ad_disc_t ctx, */ void ad_disc_refresh(ad_disc_t); +/* + * This routine marks the end of a discovery cycle and sets + * the sanity limits on the time before the next cycle. + */ +void ad_disc_done(ad_disc_t); + /* This routine unsets all overridden values */ int ad_disc_unset(ad_disc_t ctx); diff --git a/usr/src/lib/libadutils/common/mapfile-vers b/usr/src/lib/libadutils/common/mapfile-vers index d7e1687ef2..e1e580bd9a 100644 --- a/usr/src/lib/libadutils/common/mapfile-vers +++ b/usr/src/lib/libadutils/common/mapfile-vers @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -67,6 +66,7 @@ SUNWprivate { ad_disc_compare_ds; ad_disc_compare_trusteddomains; ad_disc_compare_domainsinforest; + ad_disc_done; ad_disc_SubnetChanged; ad_disc_get_GlobalCatalog; ad_disc_set_GlobalCatalog; diff --git a/usr/src/lib/libidmap/Makefile.com b/usr/src/lib/libidmap/Makefile.com index c38ff0bd02..5f5f3363b0 100644 --- a/usr/src/lib/libidmap/Makefile.com +++ b/usr/src/lib/libidmap/Makefile.com @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -36,7 +35,6 @@ LINT_OBJECTS = \ idmap_api.o \ idmap_cache.o \ miscutils.o \ - namemaps.o \ utils.o OBJECTS = $(LINT_OBJECTS) \ @@ -46,18 +44,15 @@ include ../../Makefile.lib C99MODE = $(C99_ENABLE) LIBS = $(DYNLIB) $(LINTLIB) -LDLIBS += -lc -lldap -lsldap -lavl -ladutils -lnsl -CPPFLAGS += -I$(SRC)/lib/libsldap/common +LDLIBS += -lc -lavl -lnsl SRCDIR = ../common $(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) IDMAP_PROT_X = $(SRC)/uts/common/rpcsvc/idmap_prot.x -ADUTILS_DIR = $(SRC)/lib/libadutils/common - CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -I$(SRCDIR) -I$(ADUTILS_DIR) +CPPFLAGS += -D_REENTRANT -I$(SRCDIR) CLOBBERFILES += idmap_xdr.c diff --git a/usr/src/lib/libidmap/common/directory_helper.c b/usr/src/lib/libidmap/common/directory_helper.c index f98512d88e..a7c94f9aeb 100644 --- a/usr/src/lib/libidmap/common/directory_helper.c +++ b/usr/src/lib/libidmap/common/directory_helper.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -34,7 +33,6 @@ #include <stdio.h> #include <string.h> -#include <libadutils.h> #include <rpcsvc/idmap_prot.h> #include "directory.h" #include "directory_private.h" diff --git a/usr/src/lib/libidmap/common/idmap.h b/usr/src/lib/libidmap/common/idmap.h index f22fc43092..400f67c755 100644 --- a/usr/src/lib/libidmap/common/idmap.h +++ b/usr/src/lib/libidmap/common/idmap.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -54,7 +53,7 @@ typedef struct idmap_handle idmap_handle_t; typedef struct idmap_get_handle idmap_get_handle_t; /* Logger prototype which is based on syslog */ -typedef void (*idmap_logger)(int, const char *, ...); +typedef void (*idmap_logger_t)(int, const char *, ...); /* * Setup API @@ -132,7 +131,7 @@ extern idmap_stat idmap_getgidbywinname(const char *, const char *, /* Logger */ -extern void idmap_set_logger(idmap_logger funct); +extern void idmap_set_logger(idmap_logger_t funct); #ifdef __cplusplus } diff --git a/usr/src/lib/libidmap/common/idmap_api.c b/usr/src/lib/libidmap/common/idmap_api.c index c58e2c00cd..6566de1db9 100644 --- a/usr/src/lib/libidmap/common/idmap_api.c +++ b/usr/src/lib/libidmap/common/idmap_api.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -40,6 +39,7 @@ #include <dlfcn.h> #include <libintl.h> #include <ucontext.h> +#include <syslog.h> #include "idmap_impl.h" #include "idmap_cache.h" @@ -2581,3 +2581,18 @@ idmap_flush(idmap_handle_t *handle, idmap_flush_op op) } return (res); } + + +/* + * syslog is the default logger. + * It can be overwritten by supplying a logger + * with idmap_set_logger() + */ +idmap_logger_t logger = syslog; + + +void +idmap_set_logger(idmap_logger_t funct) +{ + logger = funct; +} diff --git a/usr/src/lib/libidmap/common/idmap_impl.h b/usr/src/lib/libidmap/common/idmap_impl.h index 570b69834c..0c4aba0abb 100644 --- a/usr/src/lib/libidmap/common/idmap_impl.h +++ b/usr/src/lib/libidmap/common/idmap_impl.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -129,12 +128,7 @@ extern idmap_stat _iter_get_next_list(int, idmap_iter_t *, void *, uchar_t **, size_t, xdrproc_t, xdrproc_t); extern idmap_stat _idmap_rpc2stat(CLIENT *); -extern idmap_stat idmap_get_prop_ds(idmap_handle_t *, idmap_prop_type, - idmap_ad_disc_ds_t *); -extern idmap_stat idmap_get_prop_str(idmap_handle_t *, idmap_prop_type, - char **); - -extern idmap_logger logger; +extern idmap_logger_t logger; #ifdef __cplusplus } diff --git a/usr/src/lib/libidmap/common/idmap_priv.h b/usr/src/lib/libidmap/common/idmap_priv.h index d044225730..c3a68b76c9 100644 --- a/usr/src/lib/libidmap/common/idmap_priv.h +++ b/usr/src/lib/libidmap/common/idmap_priv.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -65,29 +64,6 @@ typedef struct idmap_iter idmap_iter_t; /* - * Directory based name map API - */ - -typedef struct idmap_nm_handle idmap_nm_handle_t; - -/* Set namemap */ -extern idmap_stat idmap_set_namemap(idmap_nm_handle_t *, char *, char *, - int, int, int); - -/* Unset namemap */ -extern idmap_stat idmap_unset_namemap(idmap_nm_handle_t *, char *, char *, - int, int, int); - -extern idmap_stat idmap_get_namemap(idmap_nm_handle_t *p, int *, char **, - char **, int *, char **, char **); - -extern void idmap_fini_namemaps(idmap_nm_handle_t *); - -extern idmap_stat idmap_init_namemaps(idmap_handle_t *, idmap_nm_handle_t **, - char *, char *, char *, char *, int); - - -/* * Update API */ @@ -213,6 +189,11 @@ extern idmap_stat idmap_getext_sidbyuid(idmap_get_handle_t *, uid_t, int, extern idmap_stat idmap_getext_sidbygid(idmap_get_handle_t *, gid_t, int, char **, idmap_rid_t *, idmap_info *, idmap_stat *); +/* Properties */ +extern idmap_stat idmap_get_prop_ds(idmap_handle_t *, idmap_prop_type, + idmap_ad_disc_ds_t *); +extern idmap_stat idmap_get_prop_str(idmap_handle_t *, idmap_prop_type, + char **); #ifdef __cplusplus } diff --git a/usr/src/lib/libidmap/common/mapfile-vers b/usr/src/lib/libidmap/common/mapfile-vers index b0fc8c9cec..e52fa5da30 100644 --- a/usr/src/lib/libidmap/common/mapfile-vers +++ b/usr/src/lib/libidmap/common/mapfile-vers @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -61,7 +60,6 @@ SUNWprivate { directory_sid_from_user_name; idmap_cache_get_data; idmap_fini; - idmap_fini_namemaps; idmap_flush; idmap_free; idmap_getext_gidbysid; @@ -77,8 +75,9 @@ SUNWprivate { idmap_get_destroy; idmap_get_gidbysid; idmap_get_mappings; - idmap_get_namemap; idmap_get_pidbysid; + idmap_get_prop_ds; + idmap_get_prop_str; idmap_get_sidbygid; idmap_get_sidbyuid; idmap_get_u2w_mapping; @@ -88,7 +87,6 @@ SUNWprivate { idmap_info_free; idmap_info_mov; idmap_init; - idmap_init_namemaps; idmap_iter_destroy; idmap_iter_mappings; idmap_iter_namerules; @@ -96,7 +94,6 @@ SUNWprivate { idmap_iter_next_namerule; idmap_namerule_cpy; idmap_set_logger; - idmap_set_namemap; idmap_stat2string; idmap_stat4prot; idmap_string2stat; @@ -109,7 +106,6 @@ SUNWprivate { idmap_udt_get_error_index; idmap_udt_get_error_rule; idmap_udt_rm_namerule; - idmap_unset_namemap; memdup; sid_free; sid_from_le; diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index 0994b48bb5..2fd55603fa 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -2312,6 +2311,9 @@ disposition_validator(int index, char *value) * The properties are given as a list of name-value pair. * The name argument should be the optionset property name and the value * should be a valid value for the specified property. + * + * When calling this function for permanent shares, the caller must also + * call sa_commit_properties() to commit the changes to SMF. */ static int smb_update_optionset_props(sa_handle_t handle, sa_resource_t resource, @@ -2361,9 +2363,6 @@ smb_update_optionset_props(sa_handle_t handle, sa_resource_t resource, cur = nvlist_next_nvpair(nvl, cur); } - if (err == SA_OK) - err = sa_commit_properties(opts, 0); - return (err); } diff --git a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h b/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h index 5ab647c0eb..7a5f3627f7 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h +++ b/usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _LIBMLRPC_H @@ -159,18 +158,21 @@ extern "C" { #define NDR_DRC_FAULT_OUT_OF_MEMORY 0xF000 /* RPCHDR */ +#define NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH 0x81FF +#define NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT 0x83FF +#define NDR_DRC_FAULT_RPCHDR_DECODE_FAILED 0x86FF #define NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID 0xC0FF /* PARAM_0_INVALID */ -#define NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF /* PARAM_0_UNIMP */ +#define NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF /* PARAM_0_UNIMP */ /* Request */ #define NDR_DRC_FAULT_REQUEST_PCONT_INVALID 0xC000 /* PARAM_0_INVALID */ #define NDR_DRC_FAULT_REQUEST_OPNUM_INVALID 0xC100 /* PARAM_1_INVALID */ /* Bind */ +#define NDR_DRC_BINDING_MADE 0x000B /* OK */ #define NDR_DRC_FAULT_BIND_PCONT_BUSY 0xC00B /* PARAM_0_INVALID */ #define NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE 0xC10B /* PARAM_1_INVALID */ #define NDR_DRC_FAULT_BIND_NO_SLOTS 0x910B /* RESOURCE_1 */ -#define NDR_DRC_BINDING_MADE 0x000B /* OK */ /* API */ #define NDR_DRC_FAULT_API_SERVICE_INVALID 0xC0AA /* PARAM_0_INVALID */ @@ -502,7 +504,8 @@ void ndr_clnt_free_heap(ndr_client_t *); /* ndr_marshal.c */ ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *); void ndr_buf_fini(ndr_buf_t *); -int ndr_buf_decode(ndr_buf_t *, unsigned, const char *data, size_t, void *); +int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t, + void *); int ndr_decode_call(ndr_xa_t *, void *); int ndr_encode_return(ndr_xa_t *, void *); int ndr_encode_call(ndr_xa_t *, void *); diff --git a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c index 12fd0c0d52..a690dfb2e9 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <assert.h> @@ -37,6 +36,7 @@ static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN; #endif static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *); +static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *); static int ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum, @@ -122,10 +122,11 @@ ndr_buf_fini(ndr_buf_t *nbuf) * } */ int -ndr_buf_decode(ndr_buf_t *nbuf, unsigned opnum, const char *data, - size_t datalen, void *result) +ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum, + const char *data, size_t datalen, void *result) { ndr_common_header_t hdr; + ndr_pac_hdr_t pac_hdr; unsigned pdu_size_hint; int rc; @@ -145,12 +146,28 @@ ndr_buf_decode(ndr_buf_t *nbuf, unsigned opnum, const char *data, bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen); - rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr); - if (NDR_DRC_IS_FAULT(rc)) - return (rc); + switch (hdr_type) { + case NDR_PTYPE_COMMON: + rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr); + if (NDR_DRC_IS_FAULT(rc)) + return (rc); + + if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags)) + return (NDR_DRC_FAULT_DECODE_FAILED); + break; + + case NDR_PTYPE_PAC: + rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr); + if (NDR_DRC_IS_FAULT(rc)) + return (rc); - if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags)) - return (NDR_DRC_FAULT_DECODE_FAILED); + if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t)) + return (NDR_DRC_FAULT_DECODE_FAILED); + break; + + default: + return (NDR_ERR_UNIMPLEMENTED); + } rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti, result); @@ -244,7 +261,7 @@ ndr_decode_pdu_hdr(ndr_xa_t *mxa) * Verify the protocol version. */ if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0)) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_DECODE_FAILED)); + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); mxa->ptype = hdr->ptype; return (NDR_DRC_OK); @@ -259,21 +276,21 @@ ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) int byte_order; if (nds->m_op != NDR_M_OP_UNMARSHALL) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_MODE_MISMATCH)); + return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); /* * All PDU headers are at least this big */ rc = NDS_GROW_PDU(nds, sizeof (ndr_common_header_t), 0); if (!rc) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_RECEIVED_RUNT)); + return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT); /* * Peek at the first eight bytes to figure out what we're doing. */ rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0); if (!rc) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_DECODE_FAILED)); + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); /* * Check for ASCII as the character set. This is an ASCII @@ -281,7 +298,7 @@ ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) */ charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK; if (charset != NDR_REPLAB_CHAR_ASCII) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_DECODE_FAILED)); + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); /* * Set the byte swap flag if the PDU byte-order @@ -301,6 +318,45 @@ ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr) return (NDR_DRC_PTYPE_RPCHDR(rc)); } +static int +ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr) +{ + int rc; + + if (nds->m_op != NDR_M_OP_UNMARSHALL) + return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); + + /* + * All PDU headers are at least this big + */ + rc = NDS_GROW_PDU(nds, sizeof (ndr_pac_hdr_t), 0); + if (!rc) + return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT); + + /* + * Peek at the first eight bytes to figure out what we're doing. + */ + rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0); + if (!rc) + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); + + /* Must be set to 1 to indicate type serialization version 1. */ + if (hdr->common_hdr.version != 1) + return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED); + + /* + * Set the byte swap flag if the PDU byte-order + * is different from the local byte-order. + */ + nds->swap = + (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0; + + rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC, + &TYPEINFO(ndr_hdr), hdr); + + return (NDR_DRC_PTYPE_RPCHDR(rc)); +} + /* * Decode an RPC fragment header. Use ndr_decode_pdu_hdr() to process * the first fragment header then this function to process additional @@ -400,7 +456,7 @@ ndr_encode_pdu_hdr(ndr_xa_t *mxa) int rc; if (nds->m_op != NDR_M_OP_MARSHALL) - return (NDR_DRC_PTYPE_RPCHDR(NDR_DRC_FAULT_MODE_MISMATCH)); + return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH); ptype = hdr->ptype; if (ptype == NDR_PTYPE_REQUEST && diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c index e4c1f50eae..109a29801f 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -37,7 +36,7 @@ #include <unistd.h> #include <netdb.h> #include <assert.h> - +#include <grp.h> #include <smbsrv/libsmb.h> #include <smbsrv/libmlrpc.h> #include <smbsrv/libmlsvc.h> @@ -897,6 +896,193 @@ samr_s_OpenGroup(void *arg, ndr_xa_t *mxa) } /* + * samr_s_AddAliasMember + * + * Add a member to a local SAM group. + * The caller must supply a valid group handle. + * The member is specified by the sid in the request. + */ +static int +samr_s_AddAliasMember(void *arg, ndr_xa_t *mxa) +{ + struct samr_AddAliasMember *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + uint32_t rc; + uint32_t status = NT_STATUS_SUCCESS; + + if (param->sid == NULL) { + bzero(param, sizeof (struct samr_AddAliasMember)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER); + return (NDR_DRC_OK); + } + + if (!ndr_is_admin(mxa)) { + bzero(param, sizeof (struct samr_AddAliasMember)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + return (NDR_DRC_OK); + } + + + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { + bzero(param, sizeof (struct samr_AddAliasMember)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (NDR_DRC_OK); + } + + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_AddAliasMember)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + return (NDR_DRC_OK); + } + + rc = smb_lgrp_add_member(grp.sg_name, + (smb_sid_t *)param->sid, SidTypeUser); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_AddAliasMember)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + } + smb_lgrp_free(&grp); + + param->status = status; + return (NDR_DRC_OK); +} + +/* + * samr_s_DeleteAliasMember + * + * Delete a member from a local SAM group. + * The caller must supply a valid group handle. + * The member is specified by the sid in the request. + */ +static int +samr_s_DeleteAliasMember(void *arg, ndr_xa_t *mxa) +{ + struct samr_DeleteAliasMember *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + uint32_t rc; + uint32_t status = NT_STATUS_SUCCESS; + + if (param->sid == NULL) { + bzero(param, sizeof (struct samr_DeleteAliasMember)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER); + return (NDR_DRC_OK); + } + + if (!ndr_is_admin(mxa)) { + bzero(param, sizeof (struct samr_DeleteAliasMember)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + return (NDR_DRC_OK); + } + + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { + bzero(param, sizeof (struct samr_DeleteAliasMember)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (NDR_DRC_OK); + } + + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_DeleteAliasMember)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + return (NDR_DRC_OK); + } + + rc = smb_lgrp_del_member(grp.sg_name, + (smb_sid_t *)param->sid, SidTypeUser); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_DeleteAliasMember)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + } + smb_lgrp_free(&grp); + + param->status = status; + return (NDR_DRC_OK); +} + +/* + * samr_s_ListAliasMembers + * + * List members from a local SAM group. + * The caller must supply a valid group handle. + * A list of user SIDs in the specified group is returned to the caller. + */ +static int +samr_s_ListAliasMembers(void *arg, ndr_xa_t *mxa) +{ + struct samr_ListAliasMembers *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + smb_gsid_t *members; + struct samr_SidInfo info; + struct samr_SidList *user; + uint32_t num = 0, size; + int i; + uint32_t rc; + uint32_t status = NT_STATUS_SUCCESS; + + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { + bzero(param, sizeof (struct samr_ListAliasMembers)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (NDR_DRC_OK); + } + + bzero(&info, sizeof (struct samr_SidInfo)); + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_ListAliasMembers)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + return (NDR_DRC_OK); + } + + num = grp.sg_nmembers; + members = grp.sg_members; + size = num * sizeof (struct samr_SidList); + info.sidlist = NDR_MALLOC(mxa, size); + if (info.sidlist == NULL) { + bzero(param, sizeof (struct samr_ListAliasMembers)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + smb_lgrp_free(&grp); + return (NDR_DRC_OK); + } + + info.n_entry = num; + user = info.sidlist; + for (i = 0; i < num; i++) { + user->sid = (struct samr_sid *)NDR_SIDDUP(mxa, + members[i].gs_sid); + if (user->sid == NULL) { + bzero(param, sizeof (struct samr_ListAliasMembers)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + smb_lgrp_free(&grp); + return (NDR_DRC_OK); + } + user++; + } + smb_lgrp_free(&grp); + + param->info = info; + param->status = status; + return (NDR_DRC_OK); +} + +/* * samr_s_Connect * * This is a request to connect to the local SAM database. @@ -1220,7 +1406,7 @@ samr_s_OpenAlias(void *arg, ndr_xa_t *mxa) goto open_alias_err; } - if (param->access_mask != SAMR_ALIAS_ACCESS_GET_INFO) { + if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) { status = NT_STATUS_ACCESS_DENIED; goto open_alias_err; } @@ -1278,70 +1464,75 @@ open_alias_err: /* * samr_s_CreateDomainAlias * - * Creates a local group in the security database, which is the - * security accounts manager (SAM) - * For more information you can look at MSDN page for NetLocalGroupAdd. - * This RPC is used by CMC and right now it returns access denied. - * The peice of code that creates a local group doesn't get compiled. + * Create a local group in the security accounts manager (SAM) database. + * A local SAM group can only be added if a Solaris group already exists + * with the same name. On success, a valid group handle is returned. + * + * The caller must have administrator rights to execute this function. */ -/*ARGSUSED*/ static int samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa) { struct samr_CreateDomainAlias *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + uint32_t status = NT_STATUS_SUCCESS; + smb_group_t grp; + uint32_t rc; + char *gname; - if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) { bzero(param, sizeof (struct samr_CreateDomainAlias)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (NDR_DRC_OK); } - bzero(param, sizeof (struct samr_CreateDomainAlias)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (NDR_DRC_OK); - -#ifdef SAMR_SUPPORT_ADD_ALIAS - DWORD status = NT_STATUS_SUCCESS; - nt_group_t *grp; - char *alias_name; - - alias_name = param->alias_name.str; - if (alias_name == 0) { - status = NT_STATUS_INVALID_PARAMETER; - goto create_alias_err; + gname = (char *)param->alias_name.str; + if (gname == NULL) { + bzero(¶m->alias_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER); + return (NDR_DRC_OK); } - /* - * Check access mask. User should be member of - * Administrators or Account Operators local group. - */ - status = nt_group_add(alias_name, 0, - NT_GROUP_AF_ADD | NT_GROUP_AF_LOCAL); + if ((!ndr_is_admin(mxa)) || + ((param->access_mask & SAMR_ALIAS_ACCESS_WRITE_ACCOUNT) == 0)) { + bzero(¶m->alias_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + return (NDR_DRC_OK); + } - if (status != NT_STATUS_SUCCESS) - goto create_alias_err; + if (getgrnam(gname) == NULL) { + bzero(¶m->alias_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER); + return (NDR_DRC_OK); + } - grp = nt_group_getinfo(alias_name, RWLOCK_READER); - if (grp == NULL) { - status = NT_STATUS_INTERNAL_ERROR; - goto create_alias_err; + rc = smb_lgrp_add(gname, ""); + if (rc != SMB_LGRP_SUCCESS) { + bzero(¶m->alias_handle, sizeof (samr_handle_t)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + return (NDR_DRC_OK); } - (void) smb_sid_getrid(grp->sid, ¶m->rid); - nt_group_putinfo(grp); - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY, - param->rid); - bcopy(handle, ¶m->alias_handle, sizeof (samr_handle_t)); + rc = smb_lgrp_getbyname((char *)gname, &grp); + if (rc != SMB_LGRP_SUCCESS) { + bzero(¶m->alias_handle, sizeof (samr_handle_t)); + status = smb_lgrp_err_to_ntstatus(rc); + param->status = NT_SC_ERROR(status); + return (NDR_DRC_OK); + } - param->status = 0; - return (NDR_DRC_OK); + id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, SMB_DOMAIN_LOCAL, grp.sg_rid); + smb_lgrp_free(&grp); + if (id) { + bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t)); + param->status = status; + } else { + bzero(¶m->alias_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } -create_alias_err: - bzero(¶m->alias_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(status); return (NDR_DRC_OK); -#endif } /* @@ -1471,60 +1662,72 @@ query_alias_err: /* * samr_s_DeleteDomainAlias * - * Deletes a local group account and all its members from the - * security database, which is the security accounts manager (SAM) database. - * Only members of the Administrators or Account Operators local group can - * execute this function. - * For more information you can look at MSDN page for NetLocalGroupSetInfo. + * Deletes a local group in the security database, which is the + * security accounts manager (SAM). A valid group handle is returned + * to the caller upon success. * - * This RPC is used by CMC and right now it returns access denied. - * The peice of code that removes a local group doesn't get compiled. + * The caller must have administrator rights to execute this function. */ static int samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa) { struct samr_DeleteDomainAlias *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + ndr_handle_t *hd; + smb_group_t grp; + samr_keydata_t *data; + smb_domain_type_t gd_type; + uint32_t rid; + uint32_t rc; + uint32_t status = NT_STATUS_SUCCESS; - if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) { + if (!ndr_is_admin(mxa)) { bzero(param, sizeof (struct samr_DeleteDomainAlias)); - param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (NDR_DRC_OK); } - bzero(param, sizeof (struct samr_DeleteDomainAlias)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (NDR_DRC_OK); + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (NDR_DRC_OK); + } -#ifdef SAMR_SUPPORT_DEL_ALIAS - nt_group_t *grp; - char *alias_name; - DWORD status; + data = (samr_keydata_t *)hd->nh_data; + gd_type = (smb_domain_type_t)data->kd_type; + rid = data->kd_rid; - grp = nt_groups_lookup_rid(desc->discrim); - if (grp == 0) { - status = NT_STATUS_NO_SUCH_ALIAS; - goto delete_alias_err; - } + switch (gd_type) { + case SMB_DOMAIN_BUILTIN: + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED); + break; - alias_name = strdup(grp->name); - if (alias_name == 0) { - status = NT_STATUS_NO_MEMORY; - goto delete_alias_err; - } + case SMB_DOMAIN_LOCAL: + rc = smb_lgrp_getbyrid(rid, gd_type, &grp); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + status = smb_lgrp_err_to_ntstatus(rc); + status = NT_SC_ERROR(status); + break; + } - status = nt_group_delete(alias_name); - free(alias_name); - if (status != NT_STATUS_SUCCESS) - goto delete_alias_err; + rc = smb_lgrp_delete(grp.sg_name); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + status = smb_lgrp_err_to_ntstatus(rc); + status = NT_SC_ERROR(status); + } + smb_lgrp_free(&grp); + break; - param->status = 0; - return (NDR_DRC_OK); + default: + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS); + } -delete_alias_err: - param->status = NT_SC_ERROR(status); + param->status = status; return (NDR_DRC_OK); -#endif } /* @@ -1677,6 +1880,9 @@ static ndr_stub_table_t samr_stub_table[] = { { samr_s_DeleteDomainAlias, SAMR_OPNUM_DeleteDomainAlias }, { samr_s_EnumDomainAliases, SAMR_OPNUM_EnumDomainAliases }, { samr_s_EnumDomainGroups, SAMR_OPNUM_EnumDomainGroups }, + { samr_s_AddAliasMember, SAMR_OPNUM_AddAliasMember }, + { samr_s_DeleteAliasMember, SAMR_OPNUM_DeleteAliasMember }, + { samr_s_ListAliasMembers, SAMR_OPNUM_ListAliasMembers }, {0} }; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c index 47633a26d4..a82bbae956 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/param.h> @@ -28,9 +27,11 @@ #include <stdlib.h> #include <stdio.h> #include <pwd.h> +#include <nss_dbdefs.h> #include <assert.h> #include <strings.h> #include <sys/stat.h> +#include <sys/idmap.h> #include <smbsrv/libsmb.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/smbinfo.h> @@ -59,6 +60,7 @@ static void smb_autohome_setent(void); static void smb_autohome_endent(void); static smb_autohome_t *smb_autohome_getent(const char *); static void smb_autohome_parse_options(smb_share_t *); +static int smb_autohome_add_private(const char *, uid_t, gid_t); /* * Add an autohome share. See smb_autohome(4) for details. @@ -73,32 +75,85 @@ static void smb_autohome_parse_options(smb_share_t *); void smb_autohome_add(const smb_token_t *token) { + + char *username; + struct passwd pw; + char buf[NSS_LINELEN_PASSWD]; + uid_t uid; + gid_t gid; + + uid = token->tkn_user.i_id; + gid = token->tkn_primary_grp.i_id; + + if (IDMAP_ID_IS_EPHEMERAL(uid)) { + username = token->tkn_account_name; + assert(username); + } else { + if (getpwuid_r(uid, &pw, buf, sizeof (buf)) == NULL) { + syslog(LOG_ERR, "unable to determine name for " \ + "UID: %u\n", uid); + return; + } + username = pw.pw_name; + } + + if (smb_autohome_add_private(username, uid, gid) != NERR_Success) { + if (!smb_isstrlwr(username)) { + (void) smb_strlwr(username); + (void) smb_autohome_add_private(username, uid, gid); + } + } +} + +/* + * Remove an autohome share. + */ +void +smb_autohome_remove(const char *username) +{ + smb_share_t si; + + assert(username); + + if (smb_shr_get((char *)username, &si) == NERR_Success) { + if (si.shr_flags & SMB_SHRF_AUTOHOME) + (void) smb_shr_remove((char *)username); + } +} + +/* + * An autohome share is not created if a static share using the same name + * already exists. Autohome shares will be added for each login attempt. + * + * Calling smb_shr_get() may return the first argument in all lower case so + * a copy is passed in instead. + * + * We need to serialize calls to smb_autohome_lookup because it + * operates on the global smb_ai structure. + */ +static int +smb_autohome_add_private(const char *username, uid_t uid, gid_t gid) +{ static mutex_t autohome_mutex; smb_share_t si; smb_autohome_t *ai; - char *username = token->tkn_account_name; + char shr_name[MAXNAMELEN]; - assert(username); + (void) strlcpy(shr_name, username, sizeof (shr_name)); - if (smb_shr_get((char *)username, &si) == NERR_Success) { - /* - * A static share with this name already exists - */ + if (smb_shr_get(shr_name, &si) == NERR_Success) { if ((si.shr_flags & SMB_SHRF_AUTOHOME) == 0) - return; + return (NERR_Success); - /* - * autohome shares will be added for each login attempt - */ (void) smb_shr_add(&si); - return; + return (NERR_Success); } (void) mutex_lock(&autohome_mutex); if ((ai = smb_autohome_lookup(username)) == NULL) { (void) mutex_unlock(&autohome_mutex); - return; + return (NERR_ItemNotFound); } bzero(&si, sizeof (smb_share_t)); @@ -110,28 +165,12 @@ smb_autohome_add(const smb_token_t *token) (void) strlcpy(si.shr_cmnt, "Autohome", SMB_SHARE_CMNT_MAX); smb_autohome_parse_options(&si); si.shr_flags |= SMB_SHRF_TRANS | SMB_SHRF_AUTOHOME; - si.shr_uid = token->tkn_user.i_id; - si.shr_gid = token->tkn_primary_grp.i_id; + si.shr_uid = uid; + si.shr_gid = gid; (void) mutex_unlock(&autohome_mutex); - (void) smb_shr_add(&si); -} - -/* - * Remove an autohome share. - */ -void -smb_autohome_remove(const char *username) -{ - smb_share_t si; - - assert(username); - - if (smb_shr_get((char *)username, &si) == NERR_Success) { - if (si.shr_flags & SMB_SHRF_AUTOHOME) - (void) smb_shr_remove((char *)username); - } + return (smb_shr_add(&si)); } /* diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_quota.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_quota.c index 6d99db1764..9f3932d5d1 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_quota.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_quota.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include <stdio.h> #include <stdlib.h> @@ -132,7 +131,7 @@ typedef struct smb_quota_tree { static list_t smb_quota_fs_list; static boolean_t smb_quota_list_init = B_FALSE; static boolean_t smb_quota_shutdown = B_FALSE; -static mutex_t smb_quota_list_mutex; +static mutex_t smb_quota_list_mutex = DEFAULTMUTEX; static cond_t smb_quota_list_condvar; static uint32_t smb_quota_tree_cnt = 0; static int smb_quota_fini_timeout = 1; /* seconds */ @@ -238,7 +237,7 @@ smb_quota_fini(void) (void) cond_broadcast(&smb_quota_list_condvar); - while (smb_quota_tree_cnt != 0) { + while (!list_is_empty(&smb_quota_fs_list)) { qtree = list_head(&smb_quota_fs_list); while (qtree != NULL) { qtree_next = list_next(&smb_quota_fs_list, qtree); @@ -257,7 +256,7 @@ smb_quota_fini(void) qtree = qtree_next; } - if (smb_quota_tree_cnt != 0) { + if (!list_is_empty(&smb_quota_fs_list)) { if (cond_reltimedwait(&smb_quota_list_condvar, &smb_quota_list_mutex, &tswait) == ETIME) { syslog(LOG_WARNING, @@ -823,7 +822,7 @@ smb_quota_tree_create(const char *path) assert(MUTEX_HELD(&smb_quota_list_mutex)); - qtree = malloc(sizeof (smb_quota_tree_t)); + qtree = calloc(sizeof (smb_quota_tree_t), 1); if (qtree == NULL) return (NULL); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c index a2ce2eb8c0..5c7154b82d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -43,6 +42,7 @@ #include <unistd.h> #include <pwd.h> #include <signal.h> +#include <dirent.h> #include <smbsrv/libsmb.h> #include <smbsrv/libsmbns.h> @@ -55,6 +55,20 @@ #define SMB_SHR_ERROR_THRESHOLD 3 #define SMB_SHR_CSC_BUFSZ 64 +typedef struct smb_transient { + char *name; + char *cmnt; + char *path; + char drive; + boolean_t check; +} smb_transient_t; + +static smb_transient_t tshare[] = { + { "IPC$", "Remote IPC", NULL, '\0', B_FALSE }, + { "c$", "Default Share", SMB_CVOL, 'C', B_FALSE }, + { "vss$", "VSS", SMB_VSS, 'V', B_TRUE } +}; + static struct { char *value; uint32_t flag; @@ -117,6 +131,9 @@ static uint32_t smb_shr_cache_addent(smb_share_t *); static void smb_shr_cache_delent(char *); static void smb_shr_cache_freent(HT_ITEM *); +static boolean_t smb_shr_is_empty(const char *); +static boolean_t smb_shr_is_dot_or_dotdot(const char *); + /* * sharemgr functions */ @@ -219,16 +236,9 @@ static sema_t smb_proc_sem = DEFAULTSEMA; int smb_shr_start(void) { - int i; - static struct tshare { - char *name; - char *cmnt; - char *path; - } tshare[] = { - { "IPC$", "Remote IPC", NULL }, - { "c$", "Default Share", SMB_CVOL }, - { "vss$", "VSS Share", SMB_VSS } - }; + smb_transient_t *ts; + uint32_t nerr; + int i; (void) mutex_lock(&smb_sa_handle.sa_mtx); smb_sa_handle.sa_in_service = B_TRUE; @@ -238,8 +248,13 @@ smb_shr_start(void) return (ENOMEM); for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { - if (smb_shr_add_transient(tshare[i].name, - tshare[i].cmnt, tshare[i].path) != NERR_Success) + ts = &tshare[i]; + + if (ts->check && smb_shr_is_empty(ts->path)) + continue; + + nerr = smb_shr_add_transient(ts->name, ts->cmnt, ts->path); + if (nerr != NERR_Success) return (ENOMEM); } @@ -850,6 +865,68 @@ smb_shr_is_admin(char *sharename) return (B_FALSE); } +char +smb_shr_drive_letter(const char *path) +{ + smb_transient_t *ts; + int i; + + if (path == NULL) + return ('\0'); + + for (i = 0; i < sizeof (tshare)/sizeof (tshare[0]); ++i) { + ts = &tshare[i]; + + if (ts->path == NULL) + continue; + + if (strcasecmp(ts->path, path) == 0) + return (ts->drive); + } + + return ('\0'); +} + +/* + * Returns true if the specified directory is empty, + * otherwise returns false. + */ +static boolean_t +smb_shr_is_empty(const char *path) +{ + DIR *dirp; + struct dirent *dp; + + if (path == NULL) + return (B_TRUE); + + if ((dirp = opendir(path)) == NULL) + return (B_TRUE); + + while ((dp = readdir(dirp)) != NULL) { + if (!smb_shr_is_dot_or_dotdot(dp->d_name)) + return (B_FALSE); + } + + (void) closedir(dirp); + return (B_TRUE); +} + +/* + * Returns true if name is "." or "..", otherwise returns false. + */ +static boolean_t +smb_shr_is_dot_or_dotdot(const char *name) +{ + if (*name != '.') + return (B_FALSE); + + if ((name[1] == '\0') || (name[1] == '.' && name[2] == '\0')) + return (B_TRUE); + + return (B_FALSE); +} + /* * smb_shr_get_realpath * diff --git a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c index 8aee0c09e9..dba55e7ffb 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -47,6 +46,9 @@ #include <arpa/inet.h> #include <libshare.h> #include <libnvpair.h> +#include <sys/idmap.h> +#include <pwd.h> +#include <nss_dbdefs.h> #include <smbsrv/libsmb.h> #include <smbsrv/libmlsvc.h> #include <smbsrv/lmerr.h> @@ -2669,9 +2671,21 @@ static boolean_t srvsvc_add_autohome(ndr_xa_t *mxa, smb_svcenum_t *se, void *infop) { smb_netuserinfo_t *user = &mxa->pipe->np_user; - char *username = user->ui_account; + char *username; smb_share_t si; DWORD status; + struct passwd pw; + char buf[NSS_LINELEN_PASSWD]; + + if (IDMAP_ID_IS_EPHEMERAL(user->ui_posix_uid)) { + username = user->ui_account; + } else { + if (getpwuid_r(user->ui_posix_uid, &pw, buf, sizeof (buf)) == + NULL) + return (B_FALSE); + + username = pw.pw_name; + } if (smb_shr_get(username, &si) != NERR_Success) return (B_FALSE); @@ -2706,10 +2720,17 @@ srvsvc_share_mkpath(ndr_xa_t *mxa, char *path) { char tmpbuf[MAXPATHLEN]; char *p; + char drive_letter; if (strlen(path) == 0) return (NDR_STRDUP(mxa, path)); + drive_letter = smb_shr_drive_letter(path); + if (drive_letter != '\0') { + (void) snprintf(tmpbuf, MAXPATHLEN, "%c:\\", drive_letter); + return (NDR_STRDUP(mxa, tmpbuf)); + } + /* * Strip the volume name from the path (/vol1/home -> /home). */ diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 93a1371c07..a99b7eacf5 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _LIBSMB_H @@ -696,6 +695,7 @@ int smb_lgrp_del_member(char *, smb_sid_t *, uint16_t); int smb_lgrp_getbyname(char *, smb_group_t *); int smb_lgrp_getbyrid(uint32_t, smb_domain_type_t, smb_group_t *); void smb_lgrp_free(smb_group_t *); +uint32_t smb_lgrp_err_to_ntstatus(uint32_t); boolean_t smb_lgrp_is_member(smb_group_t *, smb_sid_t *); char *smb_lgrp_strerror(int); int smb_lgrp_iteropen(smb_giter_t *); diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index 5c6075131c..cb103606f1 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -18,8 +18,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -248,6 +247,7 @@ SUNWprivate { smb_lgrp_add_member; smb_lgrp_delete; smb_lgrp_del_member; + smb_lgrp_err_to_ntstatus; smb_lgrp_free; smb_lgrp_getbyname; smb_lgrp_getbyrid; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c index 257d23d33b..096526f20b 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <stdlib.h> @@ -937,6 +936,62 @@ smb_lgrp_strerror(int errnum) } /* + * smb_lgrp_err_to_ntstatus + * + * This routine maps Local group operation errors to NT Status error codes. + */ +uint32_t +smb_lgrp_err_to_ntstatus(uint32_t lgrp_err) +{ + int i; + static struct err_map { + uint32_t lgrp_err; + uint32_t nt_status; + } err_map[] = { + { SMB_LGRP_SUCCESS, NT_STATUS_SUCCESS }, + { SMB_LGRP_INVALID_ARG, NT_STATUS_INVALID_PARAMETER }, + { SMB_LGRP_INVALID_MEMBER, NT_STATUS_INVALID_MEMBER }, + { SMB_LGRP_INVALID_NAME, NT_STATUS_INVALID_PARAMETER }, + { SMB_LGRP_NOT_FOUND, NT_STATUS_NO_SUCH_ALIAS }, + { SMB_LGRP_EXISTS, NT_STATUS_ALIAS_EXISTS }, + { SMB_LGRP_NO_SID, NT_STATUS_INVALID_SID }, + { SMB_LGRP_NO_LOCAL_SID, NT_STATUS_INVALID_SID }, + { SMB_LGRP_SID_NOTLOCAL, NT_STATUS_INVALID_SID }, + { SMB_LGRP_WKSID, NT_STATUS_INVALID_SID }, + { SMB_LGRP_NO_MEMORY, NT_STATUS_NO_MEMORY }, + { SMB_LGRP_DB_ERROR, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_DBINIT_ERROR, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_INTERNAL_ERROR, NT_STATUS_INTERNAL_ERROR }, + { SMB_LGRP_MEMBER_IN_GROUP, NT_STATUS_MEMBER_IN_ALIAS }, + { SMB_LGRP_MEMBER_NOT_IN_GROUP, NT_STATUS_MEMBER_NOT_IN_ALIAS }, + { SMB_LGRP_NO_SUCH_PRIV, NT_STATUS_NO_SUCH_PRIVILEGE }, + { SMB_LGRP_NO_SUCH_DOMAIN, NT_STATUS_NO_SUCH_DOMAIN }, + { SMB_LGRP_PRIV_HELD, NT_STATUS_SUCCESS }, + { SMB_LGRP_PRIV_NOT_HELD, NT_STATUS_PRIVILEGE_NOT_HELD }, + { SMB_LGRP_BAD_DATA, NT_STATUS_DATA_ERROR }, + { SMB_LGRP_NO_MORE, NT_STATUS_NO_MORE_DATA }, + { SMB_LGRP_DBOPEN_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_DBEXEC_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_DBINIT_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_DOMLKP_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_DOMINS_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_INSERT_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_DELETE_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_UPDATE_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_LOOKUP_FAILED, NT_STATUS_INTERNAL_DB_ERROR }, + { SMB_LGRP_NOT_SUPPORTED, NT_STATUS_NOT_SUPPORTED }, + { SMB_LGRP_OFFLINE, NT_STATUS_INTERNAL_ERROR } + }; + + for (i = 0; i < sizeof (err_map)/sizeof (err_map[0]); ++i) { + if (err_map[i].lgrp_err == lgrp_err) + return (err_map[i].nt_status); + } + + return (NT_STATUS_INTERNAL_ERROR); +} + +/* * smb_lgrp_chkmember * * Determines valid account types for being member of diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c index 9e211368b3..0a8d570b3a 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/param.h> @@ -562,6 +561,7 @@ smb_ads_decode_host_ip(int addit_cnt, int ans_cnt, uchar_t **ptr, [IN6ADDRSZ-1-i] = *(*ptr+i); #endif ipaddr.a_family = AF_INET6; + *ptr += size; } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c index 247fa4c646..1ac6ff079a 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -798,7 +797,7 @@ smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa) } esi.es_buf = kmem_zalloc(esi.es_bufsize, KM_SLEEP); - esi.es_username = sr->uid_user->u_name; + esi.es_posix_uid = crgetuid(sr->uid_user->u_cred); (void) smb_kshare_enum(dhdl, &esi); /* client buffer size is not big enough to hold any shares */ diff --git a/usr/src/uts/common/fs/smbsrv/smb_kshare.c b/usr/src/uts/common/fs/smbsrv/smb_kshare.c index c770143c52..c65f69e814 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c +++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -128,14 +127,13 @@ smb_kshare_enum(door_handle_t dhdl, smb_enumshare_info_t *enuminfo) enuminfo->es_ntotal = enuminfo->es_nsent = 0; - door_bufsz = enuminfo->es_bufsize + strlen(enuminfo->es_username) - + sizeof (smb_enumshare_info_t); + door_bufsz = enuminfo->es_bufsize + sizeof (smb_enumshare_info_t); door_buf = kmem_alloc(door_bufsz, KM_SLEEP); enc_ctx = smb_dr_encode_start(door_buf, door_bufsz); smb_dr_put_uint32(enc_ctx, opcode); smb_dr_put_ushort(enc_ctx, enuminfo->es_bufsize); - smb_dr_put_string(enc_ctx, enuminfo->es_username); + smb_dr_put_uint32(enc_ctx, enuminfo->es_posix_uid); if (smb_dr_encode_finish(enc_ctx, &used) != 0) { kmem_free(door_buf, door_bufsz); diff --git a/usr/src/uts/common/fs/smbsrv/smb_kutil.c b/usr/src/uts/common/fs/smbsrv/smb_kutil.c index db15dec746..e6ddda8ef5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_kutil.c +++ b/usr/src/uts/common/fs/smbsrv/smb_kutil.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <sys/param.h> @@ -43,7 +42,6 @@ static kmem_cache_t *smb_dtor_cache; static boolean_t smb_llist_initialized = B_FALSE; -static void smb_llist_flush(smb_llist_t *); static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int); time_t tzh_leapcnt = 0; @@ -558,7 +556,7 @@ smb_llist_exit(smb_llist_t *ll) * call in case this leads to additional objects being posted to the delete * queue. */ -static void +void smb_llist_flush(smb_llist_t *ll) { smb_dtor_t *dtor; diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c index c2285bb818..c59b58a773 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_node.c +++ b/usr/src/uts/common/fs/smbsrv/smb_node.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * SMB Node State Machine @@ -1007,35 +1006,72 @@ smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen) * Determine the absolute pathname of 'node' within the share (tree). * For example if the node represents file "test1.txt" in directory * "dir1" the pathname would be: \dir1\test1.txt - * - * If node represents a named stream, construct the pathname for the - * associated unnamed stream then append the stream name. */ int smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree, char *buf, uint32_t buflen) { int rc; - vnode_t *vp; - (void) bzero(buf, buflen); + ASSERT(node); + ASSERT(tree); + ASSERT(tree->t_snode); - if (SMB_IS_STREAM(node)) - vp = node->n_unode->vp; - else - vp = node->vp; + rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen); + (void) strsubst(buf, '/', '\\'); + return (rc); +} - if (vp == tree->t_snode->vp) - return (0); +/* + * smb_node_getpath + * + * Determine the absolute pathname of 'node' from 'rootvp'. + * + * Using vnodetopath is only reliable for directory nodes (due to + * its reliance on the DNLC for non-directory nodes). Thus, if node + * represents a file, construct the pathname for the parent dnode + * and append filename. + * If node represents a named stream, construct the pathname for the + * associated unnamed stream and append the stream name. + * + * The pathname returned in buf will be '/' separated. + */ +int +smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen) +{ + int rc; + vnode_t *vp; + smb_node_t *unode, *dnode; + + unode = (SMB_IS_STREAM(node)) ? node->n_unode : node; + dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode; + + /* find path to directory node */ + vp = dnode->vp; + VN_HOLD(vp); + if (rootvp) { + VN_HOLD(rootvp); + rc = vnodetopath(rootvp, vp, buf, buflen, kcred); + VN_RELE(rootvp); + } else { + rc = vnodetopath(NULL, vp, buf, buflen, kcred); + } + VN_RELE(vp); - rc = vnodetopath(tree->t_snode->vp, vp, buf, buflen, kcred); - if (rc == 0) { - (void) strsubst(buf, '/', '\\'); + if (rc != 0) + return (rc); - if (SMB_IS_STREAM(node)) - (void) strlcat(buf, node->od_name, buflen); + /* append filename if necessary */ + if (!smb_node_is_dir(unode)) { + if (buf[strlen(buf) - 1] != '/') + (void) strlcat(buf, "/", buflen); + (void) strlcat(buf, unode->od_name, buflen); } + /* append named stream name if necessary */ + if (SMB_IS_STREAM(node)) + (void) strlcat(buf, node->od_name, buflen); + return (rc); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index 77e9df00a8..75e96791c1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -928,7 +927,7 @@ smb_ofile_close_and_next(smb_ofile_t *of) * Delete an ofile. * * Remove the ofile from the tree list before freeing resources - * associated with the odir. + * associated with the ofile. */ void smb_ofile_delete(void *arg) diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c index e40de1c54f..4dc99479a2 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -722,7 +721,13 @@ smb_query_pathname(smb_tree_t *tree, smb_node_t *node, boolean_t include_share, buflen -= len; } - rc = smb_node_getshrpath(node, tree, buf, buflen); + if (node == tree->t_snode) { + if (!include_share) + (void) strlcpy(buf, "\\", buflen); + return (0); + } + + rc = smb_node_getshrpath(node, tree, buf, buflen); return (rc); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c index 9609a8d780..9c62e05092 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_server.c +++ b/usr/src/uts/common/fs/smbsrv/smb_server.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -232,8 +231,6 @@ #define SMB_EVENT_TIMEOUT 45 /* seconds */ -#define SMB_REAPER_RATE_DEFAULT 4 - extern void smb_dispatch_kstat_init(void); extern void smb_dispatch_kstat_fini(void); extern void smb_reply_notify_change_request(smb_request_t *); @@ -1948,7 +1945,7 @@ smb_event_wait(smb_event_t *event) event->se_errno = 0; while (!(event->se_notified)) { - if (smb_event_debug && ((event->se_waittime % 10) == 0)) + if (smb_event_debug && ((event->se_waittime % 30) == 0)) cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)", event->se_txid, event->se_waittime); diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c index 3b5ff81244..641a83d01b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -330,6 +329,10 @@ smb_tree_release( ASSERT(tree->t_refcnt); tree->t_refcnt--; + /* flush the ofile and odir lists' delete queues */ + smb_llist_flush(&tree->t_ofile_list); + smb_llist_flush(&tree->t_odir_list); + if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0)) smb_user_post_tree(tree->t_user, tree); @@ -474,7 +477,7 @@ smb_tree_acl_access(smb_request_t *sr, const smb_share_t *si, vnode_t *pathvp, * An autohome share owner gets full access to the share. * Everyone else is denied access. */ - if (smb_strcasecmp(si->shr_name, user->u_name, 0) != 0) + if (si->shr_uid != crgetuid(cred)) *access = 0; return; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_user.c b/usr/src/uts/common/fs/smbsrv/smb_user.c index 6f57e1dadf..7217dedadb 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_user.c +++ b/usr/src/uts/common/fs/smbsrv/smb_user.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -364,6 +363,10 @@ smb_user_release( mutex_enter(&user->u_mutex); ASSERT(user->u_refcnt); user->u_refcnt--; + + /* flush the tree list's delete queue */ + smb_llist_flush(&user->u_tree_list); + switch (user->u_state) { case SMB_USER_STATE_LOGGED_OFF: if (user->u_refcnt == 0) @@ -892,9 +895,10 @@ smb_user_netinfo_init(smb_user_t *user, smb_netuserinfo_t *info) info->ui_native_os = session->native_os; info->ui_ipaddr = session->ipaddr; info->ui_numopens = session->s_file_cnt; - info->ui_uid = user->u_uid; + info->ui_smb_uid = user->u_uid; info->ui_logon_time = user->u_logon_time; info->ui_flags = user->u_flags; + info->ui_posix_uid = crgetuid(user->u_cred); info->ui_domain_len = user->u_domain_len; info->ui_domain = smb_mem_strdup(user->u_domain); diff --git a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl b/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl index cda9f296e5..f1ea15cf00 100644 --- a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl +++ b/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _RPCPDU_NDL_ @@ -129,10 +128,16 @@ typedef struct ndr_representation_label ndr_replab_t; /* * Flags in the RPC header for Connection-oriented PDU data types * (X/Open CAE Spec 12.6.3.1) + * + * MS-RPCE 2.2.2.3 PFC_SUPPORT_HEADER_SIGN + * For PDU types bind, bind_ack, alter_context and alter_context_resp, + * 0x04 means PFC_SUPPORT_HEADER_SIGN. + * For other PDU types 0x04 means PFC_PENDING_CANCEL. */ #define NDR_PFC_FIRST_FRAG 0x01 /* First fragment */ #define NDR_PFC_LAST_FRAG 0x02 /* Last framgent */ #define NDR_PFC_PENDING_CANCEL 0x04 /* Cancel was pending@sender*/ +#define NDR_PFC_SUPPORT_HEADER_SIGN NDR_PFC_PENDING_CANCEL #define NDR_PFC_RESERVED_1 0x08 /* */ #define NDR_PFC_CONC_MPX 0x10 /* supports concurrent muxing * of single connection */ @@ -141,13 +146,42 @@ typedef struct ndr_representation_label ndr_replab_t; #define NDR_PFC_MAYBE 0x40 /* "maybe" semantics req'ed*/ #define NDR_PFC_OBJECT_UUID 0x80 /* */ +/* + * Security Providers + * MS-RPCE 2.2.1.1.6 + */ +#define NDR_C_AUTHN_NONE 0x00 /* No authentication */ +#define NDR_C_AUTHN_GSS_NEGOTIATE 0x09 /* SPNEGO */ +#define NDR_C_AUTHN_WINNT 0x0A /* NTLM */ +#define NDR_C_AUTHN_GSS_KERBEROS 0x10 /* Kerberos */ +#define NDR_C_AUTHN_GSS_NETLOGON 0x44 /* Netlogon */ +#define NDR_C_AUTHN_GSS_DEFAULT 0xFF /* Default is NTLM */ + +/* + * Encoding protection levels + * X/Open CAE Spec 13.1.2.1 + * MS-RPCE 2.2.1.1.7 + */ +#define NDR_C_AUTHN_LEVEL_DEFAULT 0x00 /* Same as Connect */ +#define NDR_C_AUTHN_LEVEL_NONE 0x01 +#define NDR_C_AUTHN_LEVEL_CONNECT 0x02 +#define NDR_C_AUTHN_LEVEL_CALL 0x03 +#define NDR_C_AUTHN_LEVEL_PKT 0x04 +#define NDR_C_AUTHN_LEVEL_PKT_INTEGRITY 0x05 +#define NDR_C_AUTHN_LEVEL_PKT_PRIVACY 0x06 /* * Header common to all Connection-oriented RPC PDUs - **************************************************************** * (X/Open CAE Spec 12.6.3.1) */ _NO_REORDER_ +struct ndr_p_syntax_id { + ndr_uuid_t if_uuid; + DWORD if_version; +}; +typedef struct ndr_p_syntax_id ndr_p_syntax_id_t; + +_NO_REORDER_ struct ndr_common_header { BYTE rpc_vers; /* 00:01 5 */ BYTE rpc_vers_minor; /* 01:01 0 */ @@ -163,19 +197,86 @@ struct ndr_common_header { typedef struct ndr_common_header ndr_common_header_t; EXTERNTYPEINFO(ndr_common_header) +/* + * MS-RPCE 2.2.6 Type Serialization Version 1 extensions to IDL/+ pickle + * One header per serialization stream: the header must be little endian. + * The filler must be set to 0xcccccccc during marshaling and ignored + * during unmarshaling. + */ +_NO_REORDER_ +struct ndr_serialtype1_hdr { + BYTE version; /* 00:01 1 */ + BYTE endianness; /* 01:01 0=big, 1=little */ + WORD hdrlen; /* 02:02 8 */ + DWORD filler; /* 04:04 0xcccccccc */ + /* 8: */ +}; +typedef struct ndr_serialtype1_hdr ndr_serialtype1_hdr_t; +EXTERNTYPEINFO(ndr_serialtype1_hdr) /* - * A plethora of supporting types, only defined the ones we need - * (X/Open CAE Spec 12.6.3.1) + * Type Serialization Version 1 Private Header. + * A private header must precede a top-level NDR constructed type. */ -typedef WORD ndr_p_context_id_t; +_NO_REORDER_ +struct ndr_serialtype1_priv_hdr { + DWORD buflen; /* 00:04 */ + DWORD filler; /* 04:04 must be zero */ + /* 8: */ +}; +typedef struct ndr_serialtype1_priv_hdr ndr_serialtype1_priv_hdr_t; +EXTERNTYPEINFO(ndr_serialtype1_priv_hdr) +/* + * MS-RPCE 2.2.7 Type Serialization Version 2 extensions Version 1 (2.2.6). + * The header must be little endian. + * The endianinfo and reserved fields must be set to 0xcccccccc during + * marshaling and ignored during unmarshaling. + */ _NO_REORDER_ -struct ndr_p_syntax_id { - ndr_uuid_t if_uuid; - DWORD if_version; +struct ndr_serialtype2_hdr { + BYTE version; /* 00:01 1 */ + BYTE endianness; /* 01:01 0=big, 1=little */ + WORD hdrlen; /* 02:02 8 */ + DWORD endianinfo; /* 04:04 0xcccccccc */ + DWORD reserved[4]; /* 08:16 0xcccccccc */ + ndr_p_syntax_id_t transfer_syntax; /* 24:20 */ + ndr_p_syntax_id_t interface_id; /* 44:20 */ + /* 64: */ }; -typedef struct ndr_p_syntax_id ndr_p_syntax_id_t; +typedef struct ndr_serialtype2_hdr ndr_serialtype2_hdr_t; +EXTERNTYPEINFO(ndr_serialtype2_hdr) + +/* + * Type Serialization Version 2 Private Header. + * A private header must precede a top-level NDR constructed type. + */ +_NO_REORDER_ +struct ndr_serialtype2_priv_hdr { + DWORD buflen; /* 00:04 */ + DWORD filler[3]; /* 04:12 must be zero */ + /* 16: */ +}; +typedef struct ndr_serialtype2_priv_hdr ndr_serialtype2_priv_hdr_t; +EXTERNTYPEINFO(ndr_serialtype2_priv_hdr) + +/* + * This header comes before the NDR-encoded KERB_VALIDATION_INFO structure, + * which can be found in one of the info buffers of the PAC. + */ +_NO_REORDER_ +struct ndr_pac_hdr { + ndr_serialtype1_hdr_t common_hdr; + ndr_serialtype1_priv_hdr_t priv_hdr; + DWORD ref_pointer; +}; +typedef struct ndr_pac_hdr ndr_pac_hdr_t; +EXTERNTYPEINFO(ndr_pac_hdr) + +/* + * Supporting types (X/Open CAE Spec 12.6.3.1) + */ +typedef WORD ndr_p_context_id_t; _NO_REORDER_ struct ndr_p_cont_elem { @@ -205,19 +306,21 @@ typedef WORD ndr_p_cont_def_result_t; #define NDR_PCDR_USER_REJECTION 1 #define NDR_PCDR_PROVIDER_REJECTION 2 +/* + * Reasons for provider rejection. + * X/Open CAE Spec 12.6.3.1 + */ typedef WORD ndr_p_provider_reason_t; -#define NDR_PPR_REASON_NOT_SPECIFIED 0 -#define NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED 1 -#define NDR_PPR_PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED 2 -#define NDR_PPR_LOCAL_LIMIT_EXCEEDED 3 - +#define NDR_PPR_REASON_NOT_SPECIFIED 0 +#define NDR_PPR_ABSTRACT_SYNTAX_NOT_SUPPORTED 1 +#define NDR_PPR_PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED 2 +#define NDR_PPR_LOCAL_LIMIT_EXCEEDED 3 _NO_REORDER_ struct ndr_p_result { ndr_p_cont_def_result_t result; /* NDR_PCDR_... */ ndr_p_provider_reason_t reason; /* NDR_PPR_... */ - ndr_p_syntax_id_t transfer_syntax; /* 0-fill if - * result!=ACCEPT*/ + ndr_p_syntax_id_t transfer_syntax; /* 0-fill if result!=ACCEPT */ }; typedef struct ndr_p_result ndr_p_result_t; EXTERNTYPEINFO(ndr_p_result) @@ -245,6 +348,21 @@ struct ndr_port_any { typedef struct ndr_port_any ndr_port_any_t; EXTERNTYPEINFO(ndr_port_any) +/* + * Reasons for rejecting an association in the bind_nak PDU. + * X/Open CAE Spec 12.6.3.1 + * MS-RPCE 2.2.2.5 + */ +#define NDR_REASON_NOT_SPECIFIED 0 +#define NDR_TEMPORARY_CONGESTION 1 +#define NDR_LOCAL_LIMIT_EXCEEDED 2 +#define NDR_CALLED_PADDR_UNKNOWN 3 +#define NDR_PROTOCOL_VERSION_NOT_SUPPORTED 4 +#define NDR_DEFAULT_CONTEXT_NOT_SUPPORTED 5 +#define NDR_USER_DATA_NOT_READABLE 6 +#define NDR_NO_PSAP_AVAILABLE 7 +#define NDR_AUTH_TYPE_NOT_RECOGNIZED 8 +#define NDR_INAVLID_CHECKSUM 9 /* * Alter Context PDU (0x0E) @@ -498,7 +616,9 @@ typedef struct ndr_fault_hdr ndr_fault_hdr_t; #define NDR_PTYPE_COMMON 999 #define NDR_PTYPE_REQUEST_WITH 998 - +#define NDR_PTYPE_SERIALTYPE_V1 997 +#define NDR_PTYPE_SERIALTYPE_V2 996 +#define NDR_PTYPE_PAC 995 INTERFACE(0) union ndr_hdr { @@ -526,6 +646,15 @@ union ndr_hdr { CASE(NDR_PTYPE_ALTER_CONTEXT_RESP) struct ndr_alter_context_rsp_hdr alter_context_rsp_hdr; + CASE(NDR_PTYPE_SERIALTYPE_V1) + struct ndr_serialtype1_hdr serialtype1_hdr; + + CASE(NDR_PTYPE_SERIALTYPE_V2) + struct ndr_serialtype2_hdr serialtype2_hdr; + + CASE(NDR_PTYPE_PAC) + struct ndr_pac_hdr pac_hdr; + CASE(NDR_PTYPE_FAULT) struct ndr_fault_hdr fault_hdr; }; diff --git a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl index e08b06e626..44d86dcb19 100644 --- a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl +++ b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _MLSVC_SAM_NDL_ @@ -66,7 +65,7 @@ #define SAMR_OPNUM_DeleteDomainAlias 0x1e #define SAMR_OPNUM_AddAliasMember 0x1f #define SAMR_OPNUM_DeleteAliasMember 0x20 -#define SAMR_OPNUM_QueryAliasMember 0x21 +#define SAMR_OPNUM_ListAliasMembers 0x21 #define SAMR_OPNUM_OpenUser 0x22 #define SAMR_OPNUM_DeleteUser 0x23 #define SAMR_OPNUM_QueryUserInfo 0x24 @@ -185,13 +184,17 @@ #define SAMR_USER_ALL_UNDEFINED_MASK 0xC0000000 /* - * specific access rights which can be used in OpenAlias. - * extracted from Ethereal network analyzer + * Alias Access Mask values for SAMR + * Section 2.2.1.6 of MS-SAMR */ -#define SAMR_ALIAS_ACCESS_SET_INFO 0x00000010 -#define SAMR_ALIAS_ACCESS_GET_INFO 0x00000008 -#define SAMR_ALIAS_ACCESS_GET_MEMBERS 0x00000004 -#define SAMR_ALIAS_ACCESS_DEL_MEMBER 0x00000002 +#define SAMR_ALIAS_ACCESS_EXECUTE 0x00020008 +#define SAMR_ALIAS_ACCESS_WRITE 0x00020013 +#define SAMR_ALIAS_ACCESS_READ 0x00020004 +#define SAMR_ALIAS_ACCESS_ALL_ACCESS 0x000F001F +#define SAMR_ALIAS_ACCESS_WRITE_ACCOUNT 0x00000010 +#define SAMR_ALIAS_ACCESS_READ_INFO 0x00000008 +#define SAMR_ALIAS_ACCESS_LIST_MEMBERS 0x00000004 +#define SAMR_ALIAS_ACCESS_REMOVE_MEMBER 0x00000002 #define SAMR_ALIAS_ACCESS_ADD_MEMBER 0x00000001 #define SAMR_REVISION_1 1 /* Pre Windows 2000 */ @@ -669,7 +672,7 @@ struct samr_SetAliasInfo { OPERATION(SAMR_OPNUM_DeleteDomainAlias) struct samr_DeleteDomainAlias { - IN samr_handle_t alias_handle; + INOUT samr_handle_t alias_handle; OUT DWORD status; }; @@ -1126,6 +1129,45 @@ struct samr_StoreGroupInfo { OUT DWORD status; }; +/* + * AddAliasMember + */ +OPERATION(SAMR_OPNUM_AddAliasMember) +struct samr_AddAliasMember { + IN samr_handle_t alias_handle; + IN REFERENCE struct samr_sid *sid; + OUT DWORD status; +}; + +/* + * DeleteAliasMember + */ +OPERATION(SAMR_OPNUM_DeleteAliasMember) +struct samr_DeleteAliasMember { + IN samr_handle_t alias_handle; + IN REFERENCE struct samr_sid *sid; + OUT DWORD status; +}; + +struct samr_SidList { + struct samr_sid *sid; +}; + +struct samr_SidInfo { + DWORD n_entry; + SIZE_IS(n_entry) + struct samr_SidList *sidlist; +}; + +/* + * ListAliasMembers + */ +OPERATION(SAMR_OPNUM_ListAliasMembers) +struct samr_ListAliasMembers { + IN samr_handle_t alias_handle; + OUT struct samr_SidInfo info; + OUT DWORD status; +}; /* *********************************************************************** @@ -1410,6 +1452,12 @@ union samr_interface { struct samr_QueryUserGroups QueryUserGroups; CASE(SAMR_OPNUM_OpenGroup) struct samr_OpenGroup OpenGroup; + CASE(SAMR_OPNUM_AddAliasMember) + struct samr_AddAliasMember AddAliasMember; + CASE(SAMR_OPNUM_DeleteAliasMember) + struct samr_DeleteAliasMember DeleteAliasMember; + CASE(SAMR_OPNUM_ListAliasMembers) + struct samr_ListAliasMembers ListAliasMembers; CASE(SAMR_OPNUM_GetUserPwInfo) struct samr_GetUserPwInfo GetUserPwInfo; CASE(SAMR_OPNUM_CreateUser) diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index ae09a4d10e..b1bc982cf1 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -430,6 +429,7 @@ int smb_node_setattr(smb_request_t *, smb_node_t *, cred_t *, int smb_node_set_delete_on_close(smb_node_t *, cred_t *, uint32_t); void smb_node_reset_delete_on_close(smb_node_t *); boolean_t smb_node_file_is_readonly(smb_node_t *); +int smb_node_getpath(smb_node_t *, vnode_t *, char *, uint32_t); int smb_node_getmntpath(smb_node_t *, char *, uint32_t); int smb_node_getshrpath(smb_node_t *, smb_tree_t *, char *, uint32_t); @@ -690,6 +690,7 @@ void smb_llist_constructor(smb_llist_t *, size_t, size_t); void smb_llist_destructor(smb_llist_t *); void smb_llist_exit(smb_llist_t *); void smb_llist_post(smb_llist_t *, void *, smb_dtorproc_t); +void smb_llist_flush(smb_llist_t *); void smb_llist_insert_head(smb_llist_t *ll, void *obj); void smb_llist_insert_tail(smb_llist_t *ll, void *obj); void smb_llist_remove(smb_llist_t *ll, void *obj); diff --git a/usr/src/uts/common/smbsrv/smb_share.h b/usr/src/uts/common/smbsrv/smb_share.h index 1cc5ec87e2..679a740d81 100644 --- a/usr/src/uts/common/smbsrv/smb_share.h +++ b/usr/src/uts/common/smbsrv/smb_share.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SMB_SHARE_H @@ -225,7 +224,7 @@ typedef struct smb_shrlist { * This structure is a helper for building NetShareEnum response * in user space and send it back down to kernel. * - * es_username name of the user requesting the shares list which + * es_posix_uid UID of the user requesting the shares list which * is used to detect if the user has any autohome * es_bufsize size of the response buffer * es_buf pointer to the response buffer @@ -236,7 +235,7 @@ typedef struct smb_shrlist { * in the response buffer */ typedef struct smb_enumshare_info { - char *es_username; + uid_t es_posix_uid; uint16_t es_bufsize; char *es_buf; uint16_t es_ntotal; @@ -286,6 +285,7 @@ boolean_t smb_shr_exists(char *); int smb_shr_is_special(char *); boolean_t smb_shr_is_restricted(char *); boolean_t smb_shr_is_admin(char *); +char smb_shr_drive_letter(const char *); sa_handle_t smb_shr_sa_enter(void); void smb_shr_sa_exit(void); diff --git a/usr/src/uts/common/smbsrv/smb_xdr.h b/usr/src/uts/common/smbsrv/smb_xdr.h index 61f62df661..cebedb39c4 100644 --- a/usr/src/uts/common/smbsrv/smb_xdr.h +++ b/usr/src/uts/common/smbsrv/smb_xdr.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SMBSRV_SMB_XDR_H @@ -120,11 +119,12 @@ typedef struct smb_doorhdr { typedef struct smb_netuserinfo { uint64_t ui_session_id; - uint16_t ui_uid; + uint16_t ui_smb_uid; uint16_t ui_domain_len; char *ui_domain; uint16_t ui_account_len; char *ui_account; + uid_t ui_posix_uid; uint16_t ui_workstation_len; char *ui_workstation; smb_inaddr_t ui_ipaddr; |