summaryrefslogtreecommitdiff
path: root/usr/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd')
-rw-r--r--usr/src/cmd/idmap/idmap/Makefile14
-rw-r--r--usr/src/cmd/idmap/idmap/idmap.c16
-rw-r--r--usr/src/cmd/idmap/idmap/namemaps.c1067
-rw-r--r--usr/src/cmd/idmap/idmap/namemaps.h62
-rw-r--r--usr/src/cmd/idmap/idmapd/idmap_config.c214
-rw-r--r--usr/src/cmd/idmap/idmapd/idmapd.c18
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c53
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_logon.c17
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c15
9 files changed, 1352 insertions, 124 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/cmd/idmap/idmap/namemaps.c b/usr/src/cmd/idmap/idmap/namemaps.c
new file mode 100644
index 0000000000..53c89f1554
--- /dev/null
+++ b/usr/src/cmd/idmap/idmap/namemaps.c
@@ -0,0 +1,1067 @@
+/*
+ * 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.
+ */
+
+
+#include <errno.h>
+#include <ldap.h>
+#include <sasl/sasl.h>
+#include <libintl.h>
+#include <strings.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "addisc.h"
+#include "libadutils.h"
+#include "idmap_priv.h"
+#include "ns_sldap.h"
+#include "namemaps.h"
+
+/* From adutils.c: */
+
+/* A single DS */
+struct idmap_nm_handle {
+ LDAP *ad; /* LDAP connection */
+ /* LDAP DS info */
+ char *ad_host;
+ int ad_port;
+
+ /* hardwired to SASL GSSAPI only for now */
+ char *saslmech;
+ unsigned saslflags;
+ char *windomain;
+ char *ad_unixuser_attr;
+ char *ad_unixgroup_attr;
+ char *nldap_winname_attr;
+ char *default_domain;
+ bool_t is_nldap;
+ bool_t is_ad;
+ int direction;
+ 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)
+{
+ if (from == NULL) {
+ na->type = NS_LDAP_AUTH_SASL;
+ na->tlstype = NS_LDAP_TLS_SASL;
+ na->saslmech = NS_LDAP_SASL_GSSAPI;
+ na->saslopt = NS_LDAP_SASLOPT_PRIV |
+ NS_LDAP_SASLOPT_INT;
+ return (IDMAP_SUCCESS);
+ }
+
+ if (strcasecmp(from, "simple") == 0) {
+ na->type = NS_LDAP_AUTH_SIMPLE;
+ na->tlstype = NS_LDAP_TLS_NONE;
+ na->saslmech = NS_LDAP_SASL_NONE;
+ na->saslopt = NS_LDAP_SASLOPT_NONE;
+ } else if (strcasecmp(from, "sasl/CRAM-MD5") == 0) {
+ na->type = NS_LDAP_AUTH_SASL;
+ na->tlstype = NS_LDAP_TLS_SASL;
+ na->saslmech = NS_LDAP_SASL_CRAM_MD5;
+ na->saslopt = NS_LDAP_SASLOPT_NONE;
+ } else if (strcasecmp(from, "sasl/DIGEST-MD5") == 0) {
+ na->type = NS_LDAP_AUTH_SASL;
+ na->tlstype = NS_LDAP_TLS_SASL;
+ na->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ na->saslopt = NS_LDAP_SASLOPT_NONE;
+ } else if (strcasecmp(from, "sasl/GSSAPI") == 0) {
+ na->type = NS_LDAP_AUTH_SASL;
+ na->tlstype = NS_LDAP_TLS_SASL;
+ na->saslmech = NS_LDAP_SASL_GSSAPI;
+ na->saslopt = NS_LDAP_SASLOPT_PRIV |
+ NS_LDAP_SASLOPT_INT;
+ } else if (strcasecmp(from, "tls:simple") == 0) {
+ na->type = NS_LDAP_AUTH_TLS;
+ na->tlstype = NS_LDAP_TLS_SIMPLE;
+ na->saslmech = NS_LDAP_SASL_NONE;
+ na->saslopt = NS_LDAP_SASLOPT_NONE;
+ } else if (strcasecmp(from, "tls:sasl/CRAM-MD5") == 0) {
+ na->type = NS_LDAP_AUTH_TLS;
+ na->tlstype = NS_LDAP_TLS_SASL;
+ na->saslmech = NS_LDAP_SASL_CRAM_MD5;
+ na->saslopt = NS_LDAP_SASLOPT_NONE;
+ } else if (strcasecmp(from, "tls:sasl/DIGEST-MD5") == 0) {
+ na->type = NS_LDAP_AUTH_TLS;
+ na->tlstype = NS_LDAP_TLS_SASL;
+ na->saslmech = NS_LDAP_SASL_DIGEST_MD5;
+ na->saslopt = NS_LDAP_SASLOPT_NONE;
+ } else {
+ namemap_log(
+ gettext("Invalid authentication method \"%s\" specified\n"),
+ from);
+ return (IDMAP_ERR_ARG);
+ }
+
+ return (IDMAP_SUCCESS);
+}
+
+
+
+static
+idmap_stat
+strings2cred(ns_cred_t *nsc, char *user, char *passwd, char *auth)
+{
+ idmap_stat rc;
+ (void) memset(nsc, 0, sizeof (ns_cred_t));
+
+ if ((rc = string2auth(auth, &nsc->auth)) != IDMAP_SUCCESS)
+ return (rc);
+
+ if (user != NULL) {
+ nsc->cred.unix_cred.userID = strdup(user);
+ if (nsc->cred.unix_cred.userID == NULL)
+ return (IDMAP_ERR_MEMORY);
+ }
+
+ if (passwd != NULL) {
+ nsc->cred.unix_cred.passwd = strdup(passwd);
+ if (nsc->cred.unix_cred.passwd == NULL) {
+ free(nsc->cred.unix_cred.userID);
+ return (IDMAP_ERR_MEMORY);
+ }
+ }
+
+ return (IDMAP_SUCCESS);
+}
+
+
+
+
+
+/*ARGSUSED*/
+static int
+idmap_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts)
+{
+ sasl_interact_t *interact;
+
+ if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
+ return (LDAP_PARAM_ERROR);
+
+ /* There should be no extra arguemnts for SASL/GSSAPI authentication */
+ for (interact = prompts; interact->id != SASL_CB_LIST_END;
+ interact++) {
+ interact->result = NULL;
+ interact->len = 0;
+ }
+ return (LDAP_SUCCESS);
+}
+
+static
+idmap_stat
+idmap_open_ad_conn(idmap_nm_handle_t *adh)
+{
+ int zero = 0;
+ int timeoutms = 30 * 1000;
+ int ldversion, ldap_rc;
+ idmap_stat rc = IDMAP_SUCCESS;
+
+ /* Open and bind an LDAP connection */
+ adh->ad = ldap_init(adh->ad_host, adh->ad_port);
+ if (adh->ad == NULL) {
+ 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;
+ }
+ ldversion = LDAP_VERSION3;
+ (void) ldap_set_option(adh->ad, LDAP_OPT_PROTOCOL_VERSION, &ldversion);
+ (void) ldap_set_option(adh->ad, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
+ (void) ldap_set_option(adh->ad, LDAP_OPT_TIMELIMIT, &zero);
+ (void) ldap_set_option(adh->ad, LDAP_OPT_SIZELIMIT, &zero);
+ (void) ldap_set_option(adh->ad, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms);
+ (void) ldap_set_option(adh->ad, LDAP_OPT_RESTART, LDAP_OPT_ON);
+ ldap_rc = ldap_sasl_interactive_bind_s(adh->ad, "" /* binddn */,
+ adh->saslmech, NULL, NULL, adh->saslflags, &idmap_saslcallback,
+ NULL);
+
+ if (ldap_rc != LDAP_SUCCESS) {
+ (void) ldap_unbind(adh->ad);
+ adh->ad = NULL;
+ 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;
+ }
+
+out:
+ return (rc);
+}
+
+static
+idmap_stat
+idmap_init_nldap(idmap_nm_handle_t *p)
+{
+/*
+ * For now, there is nothing to initialize in nldap. This is just to
+ * make it future-proof, especially standalone libsldap-proof
+ */
+ p->is_nldap = TRUE;
+ return (0);
+}
+
+static
+idmap_stat
+idmap_init_ad(idmap_nm_handle_t *p)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ idmap_ad_disc_ds_t *dc = NULL;
+ ad_disc_t ad_ctx;
+
+ ad_ctx = ad_disc_init();
+ if (ad_ctx == NULL) {
+ namemap_log(
+ gettext("AD autodiscovery initialization failed"));
+ return (IDMAP_ERR_INTERNAL);
+ }
+ ad_disc_refresh(ad_ctx);
+
+
+ /* Based on the supplied or default domain, find the proper AD: */
+ if (ad_disc_set_DomainName(ad_ctx, p->windomain)) {
+ rc = IDMAP_ERR_INTERNAL;
+ namemap_log(
+ gettext("Setting a domain name \"%s\" for autodiscovery"
+ " failed, most likely not enough memory"), p->windomain);
+ goto cleanup;
+ }
+
+ dc = ad_disc_get_DomainController(ad_ctx, AD_DISC_GLOBAL, NULL);
+ if (dc == NULL) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("A domain controller for the "
+ "domain \"%s\" not found."), p->windomain);
+ goto cleanup;
+ }
+
+
+ p->ad_port = dc->port;
+ p->ad_host = strdup(dc->host);
+
+ if (p->ad_host == NULL) {
+ rc = IDMAP_ERR_MEMORY;
+ goto cleanup;
+ }
+
+ p->saslflags = LDAP_SASL_INTERACTIVE;
+ p->saslmech = strdup("GSSAPI");
+
+ if (p->saslmech == NULL) {
+ rc = IDMAP_ERR_MEMORY;
+ goto cleanup;
+ }
+
+ rc = idmap_open_ad_conn(p);
+
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ p->is_ad = TRUE;
+
+cleanup:
+ ad_disc_fini(ad_ctx);
+ free(dc);
+ return (rc);
+}
+
+void
+idmap_fini_namemaps(idmap_nm_handle_t *p)
+{
+ if (p == NULL)
+ return;
+
+ if (p->ad_unixgroup_attr != NULL)
+ free(p->ad_unixgroup_attr);
+
+ if (p->ad_unixuser_attr != NULL)
+ free(p->ad_unixuser_attr);
+
+ if (p->nldap_winname_attr)
+ free(p->nldap_winname_attr);
+
+ if (p->windomain != NULL)
+ free(p->windomain);
+
+ if (p->default_domain != NULL)
+ free(p->default_domain);
+
+ if (p->saslmech != NULL)
+ free(p->saslmech);
+
+ if (p->ad_host != NULL)
+ free(p->ad_host);
+
+ if (p->nsc.cred.unix_cred.userID != NULL) {
+ free(p->nsc.cred.unix_cred.userID);
+ }
+
+ if (p->nsc.cred.unix_cred.passwd != NULL) {
+ /* No archeology: */
+ (void) memset(p->nsc.cred.unix_cred.passwd, 0,
+ strlen(p->nsc.cred.unix_cred.passwd));
+ free(p->nsc.cred.unix_cred.passwd);
+ }
+
+ if (p->ad)
+ (void) ldap_unbind(p->ad);
+ free(p);
+
+}
+
+
+
+idmap_stat
+idmap_init_namemaps(idmap_handle_t *handle, idmap_nm_handle_t **adh,
+ char *user, char *passwd, char *auth, char *windomain,
+ int direction)
+{
+ idmap_stat rc;
+ idmap_nm_handle_t *p;
+
+ p = (idmap_nm_handle_t *)calloc(1, sizeof (idmap_nm_handle_t));
+ if (p == NULL)
+ return (IDMAP_ERR_MEMORY);
+
+ rc = idmap_get_prop_str(handle, PROP_DEFAULT_DOMAIN,
+ &p->default_domain);
+ if (rc != IDMAP_SUCCESS) {
+ namemap_log(
+ gettext("Error obtaining default domain from idmapd (%s)"),
+ idmap_stat2string(NULL, rc));
+ goto cleanup;
+ }
+
+ rc = idmap_get_prop_str(handle, PROP_AD_UNIXUSER_ATTR,
+ &p->ad_unixuser_attr);
+ if (rc != IDMAP_SUCCESS) {
+ namemap_log(
+ gettext("Error obtaining AD unixuser attribute (%s)"),
+ idmap_stat2string(NULL, rc));
+ goto cleanup;
+ }
+
+ rc = idmap_get_prop_str(handle, PROP_AD_UNIXGROUP_ATTR,
+ &p->ad_unixgroup_attr);
+ if (rc != IDMAP_SUCCESS) {
+ namemap_log(
+ gettext("Error obtaining AD unixgroup attribute (%s)"),
+ idmap_stat2string(NULL, rc));
+ goto cleanup;
+ }
+
+
+ rc = idmap_get_prop_str(handle, PROP_NLDAP_WINNAME_ATTR,
+ &p->nldap_winname_attr);
+ if (rc != IDMAP_SUCCESS) {
+ namemap_log(
+ gettext("Error obtaining AD unixgroup attribute (%s)"),
+ idmap_stat2string(NULL, rc));
+ goto cleanup;
+ }
+
+ if (windomain != NULL) {
+ p->windomain = strdup(windomain);
+ if (p->windomain == NULL) {
+ rc = IDMAP_ERR_MEMORY;
+ goto cleanup;
+ }
+ } else if (!EMPTY_STRING(p->default_domain)) {
+ p->windomain = strdup(p->default_domain);
+ if (p->windomain == NULL) {
+ rc = IDMAP_ERR_MEMORY;
+ goto cleanup;
+ }
+ } else if (direction == IDMAP_DIRECTION_W2U) {
+ namemap_log(
+ gettext("Windows domain not given and idmapd daemon"
+ " didn't provide a default one"));
+ rc = IDMAP_ERR_ARG;
+ goto cleanup;
+ }
+
+ p->direction = direction;
+
+ if ((p->ad_unixuser_attr != NULL || p->ad_unixgroup_attr != NULL) &&
+ direction != IDMAP_DIRECTION_U2W) {
+ rc = idmap_init_ad(p);
+ if (rc != IDMAP_SUCCESS) {
+ goto cleanup;
+ }
+ }
+
+ if (p->nldap_winname_attr != NULL && direction != IDMAP_DIRECTION_W2U) {
+ rc = idmap_init_nldap(p);
+ if (rc != IDMAP_SUCCESS) {
+ goto cleanup;
+ }
+
+ rc = strings2cred(&p->nsc, user, passwd, auth);
+ if (rc != IDMAP_SUCCESS) {
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (rc == IDMAP_SUCCESS) {
+ *adh = p;
+ return (IDMAP_SUCCESS);
+ }
+
+ /* There was an error: */
+ idmap_fini_namemaps(*adh);
+ return (rc);
+}
+
+static
+char *
+dns2dn(const char *dns, const char *prefix)
+{
+ int num_lvl = 1;
+ char *buf;
+ const char *it, *new_it;
+
+ for (it = dns; it != NULL; it = strchr(it, '.')) {
+ it ++;
+ num_lvl ++;
+ }
+
+ buf = (char *)malloc(strlen(prefix) + strlen(dns) + 4 * num_lvl);
+ (void) strcpy(buf, prefix);
+
+
+ it = dns;
+ for (;;) {
+ new_it = strchr(it, '.');
+ (void) strcat(buf, "DC=");
+ if (new_it == NULL) {
+ (void) strcat(buf, it);
+ break;
+ } else {
+ (void) strncat(buf, it, new_it - it);
+ (void) strcat(buf, ",");
+ }
+
+ it = new_it + 1;
+ }
+
+ return (buf);
+}
+
+
+static
+idmap_stat
+extract_attribute(idmap_nm_handle_t *p, LDAPMessage *entry, char *name,
+ char **value)
+{
+ char **values = NULL;
+ idmap_stat rc = IDMAP_SUCCESS;
+ /* No value means it is not requested */
+ if (value == NULL)
+ return (IDMAP_SUCCESS);
+
+ values = ldap_get_values(p->ad, entry, name);
+ if (values == NULL || values[0] == NULL)
+ *value = NULL;
+ else {
+ *value = strdup(values[0]);
+ if (*value == NULL)
+ rc = IDMAP_ERR_MEMORY;
+ }
+errout:
+ ldap_value_free(values);
+ return (rc);
+}
+
+
+/* Split winname to its name and domain part */
+static
+idmap_stat
+split_fqwn(char *fqwn, char **name, char **domain)
+{
+ char *at;
+
+ *name = NULL;
+ *domain = NULL;
+
+ at = strchr(fqwn, '@');
+ if (at == NULL) {
+ at = strchr(fqwn, '\\');
+ }
+ if (at == NULL) {
+ /* There is no domain - leave domain NULL */
+ *name = strdup(fqwn);
+ if (*name == NULL)
+ goto errout;
+ return (IDMAP_SUCCESS);
+ }
+
+
+ *domain = strdup(at+1);
+ if (*domain == NULL)
+ goto errout;
+ *name = (char *)malloc(at - fqwn + 1);
+ if (*name == NULL)
+ goto errout;
+ (void) strlcpy(*name, fqwn, at - fqwn + 1);
+
+ if (*at == '\\') {
+ char *it = *name;
+ *name = *domain;
+ *domain = it;
+ }
+
+ return (IDMAP_SUCCESS);
+
+
+errout:
+ free(*name);
+ *name = NULL;
+ free(*domain);
+ *domain = NULL;
+ return (IDMAP_ERR_MEMORY);
+}
+
+static
+idmap_stat
+unixname2dn(idmap_nm_handle_t *p, char *unixname, int is_user, char **dn,
+ char **winname, char **windomain)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ int rc_ns;
+
+
+ char filter[255];
+ static const char *attribs[3];
+ ns_ldap_result_t *res;
+ ns_ldap_error_t *errorp = NULL;
+ char **attrs;
+
+
+ attribs[0] = p->nldap_winname_attr;
+ attribs[1] = "dn";
+ attribs[2] = NULL;
+
+ (void) snprintf(filter, sizeof (filter), is_user ? "uid=%s" : "cn=%s",
+ unixname);
+
+ rc_ns = __ns_ldap_list(is_user ? "passwd" : "group",
+ filter, NULL, attribs, NULL, 0, &res, &errorp, NULL, NULL);
+
+
+ if (rc_ns == NS_LDAP_NOTFOUND) {
+ 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) {
+ char *msg = "Cause unidentified";
+ if (errorp != NULL) {
+ (void) __ns_ldap_err2str(errorp->status, &msg);
+ }
+ namemap_log(gettext("Ldap list failed (%s)."), msg);
+ return (IDMAP_ERR_ARG);
+ }
+
+ if (res == NULL) {
+ namemap_log(gettext("User %s not found"), unixname);
+ return (IDMAP_ERR_ARG);
+ }
+
+ if (winname != NULL && windomain != NULL) {
+ attrs = __ns_ldap_getAttr(&res->entry[0],
+ p->nldap_winname_attr);
+ if (attrs != NULL && attrs[0] != NULL) {
+ rc = split_fqwn(attrs[0], winname, windomain);
+ } else {
+ *winname = *windomain = NULL;
+ }
+ }
+
+ if (dn != NULL) {
+ attrs = __ns_ldap_getAttr(&res->entry[0], "dn");
+ if (attrs == NULL || attrs[0] == NULL) {
+ namemap_log(gettext("dn for %s not found"),
+ unixname);
+ return (IDMAP_ERR_ARG);
+ }
+ *dn = strdup(attrs[0]);
+ }
+
+
+ return (rc);
+
+}
+
+#define FILTER "(sAMAccountName=%s)"
+
+/* Puts the values of attributes to unixuser and unixgroup, unless NULL */
+
+static
+idmap_stat
+winname2dn(idmap_nm_handle_t *p, char *winname,
+ int *is_wuser, char **dn, char **unixuser, char **unixgroup)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ char *base;
+ char *filter;
+ int flen;
+ char *attribs[4];
+ int i;
+ LDAPMessage *results = NULL;
+ LDAPMessage *entry;
+ int ldap_rc;
+
+ /* Query: */
+
+ base = dns2dn(p->windomain, "");
+ if (base == NULL) {
+ return (IDMAP_ERR_MEMORY);
+ }
+
+ i = 0;
+ attribs[i++] = "objectClass";
+ if (unixuser != NULL)
+ attribs[i++] = p->ad_unixuser_attr;
+ if (unixgroup != NULL)
+ attribs[i++] = p->ad_unixgroup_attr;
+ attribs[i] = NULL;
+
+ flen = snprintf(NULL, 0, FILTER, winname) + 1;
+ if ((filter = (char *)malloc(flen)) == NULL) {
+ free(base);
+ return (IDMAP_ERR_MEMORY);
+ }
+ (void) snprintf(filter, flen, FILTER, winname);
+
+ ldap_rc = ldap_search_s(p->ad, base, LDAP_SCOPE_SUBTREE, filter,
+ attribs, 0, &results);
+
+ free(base);
+ free(filter);
+
+ if (ldap_rc != LDAP_SUCCESS) {
+ 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);
+ }
+
+
+ for (entry = ldap_first_entry(p->ad, results), *dn = NULL;
+ entry != NULL;
+ entry = ldap_next_entry(p->ad, entry)) {
+ char **values = NULL;
+ int i = 0;
+ values = ldap_get_values(p->ad, entry, "objectClass");
+
+ if (values == NULL) {
+ (void) ldap_msgfree(results);
+ return (IDMAP_ERR_MEMORY);
+ }
+
+ for (i = 0; i < ldap_count_values(values); i++) {
+ /*
+ * is_wuser can be IDMAP_UNKNOWN, in that case we accept
+ * both User/Group
+ */
+ if (*is_wuser != IDMAP_NO &&
+ strcasecmp(values[i], "User") == 0 ||
+ *is_wuser != IDMAP_YES &&
+ strcasecmp(values[i], "Group") == 0) {
+ *dn = ldap_get_dn(p->ad, entry);
+ if (*dn == NULL) {
+ ldap_value_free(values);
+ (void) ldap_msgfree(results);
+ return (IDMAP_ERR_MEMORY);
+ }
+ *is_wuser = strcasecmp(values[i], "User") == 0
+ ? IDMAP_YES : IDMAP_NO;
+ break;
+ }
+ }
+
+ ldap_value_free(values);
+ if (*dn != NULL)
+ break;
+ }
+
+ if (*dn == NULL) {
+ 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);
+ return (IDMAP_ERR_NOTFOUND);
+ }
+
+ if (unixuser != NULL)
+ rc = extract_attribute(p, entry, p->ad_unixuser_attr,
+ unixuser);
+
+ if (rc == IDMAP_SUCCESS && unixgroup != NULL)
+ rc = extract_attribute(p, entry, p->ad_unixgroup_attr,
+ unixgroup);
+
+ (void) ldap_msgfree(results);
+
+ return (rc);
+}
+
+
+/* set the given attribute to the given value. If value is NULL, unset it */
+static
+idmap_stat
+idmap_ad_set(idmap_nm_handle_t *p, char *dn, char *attr, char *value)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ int ldap_rc;
+ char *new_values[2] = {NULL, NULL};
+ LDAPMod *mods[2] = {NULL, NULL};
+
+ mods[0] = (LDAPMod *)calloc(1, sizeof (LDAPMod));
+ mods[0]->mod_type = strdup(attr);
+ if (value != NULL) {
+ mods[0]->mod_op = LDAP_MOD_REPLACE;
+ new_values[0] = strdup(value);
+ mods[0]->mod_values = new_values;
+ } else {
+ mods[0]->mod_op = LDAP_MOD_DELETE;
+ mods[0]->mod_values = NULL;
+ }
+
+ ldap_rc = ldap_modify_s(p->ad, dn, mods);
+ if (ldap_rc != LDAP_SUCCESS) {
+ namemap_log(
+ gettext("Ldap modify of %s, attribute %s failed. (%s)"),
+ dn, attr, ldap_err2string(ldap_rc));
+ rc = IDMAP_ERR_INTERNAL;
+ }
+
+
+ ldap_mods_free(mods, 0);
+ return (rc);
+}
+
+
+/*
+ * This function takes the p argument just for the beauty of the symmetry
+ * with idmap_ad_set (and for future enhancements).
+ */
+static
+idmap_stat
+/* LINTED E_FUNC_ARG_UNUSED */
+idmap_nldap_set(idmap_nm_handle_t *p, ns_cred_t *nsc, char *dn, char *attr,
+ char *value, bool_t is_new, int is_user)
+{
+ int ldaprc;
+ ns_ldap_error_t *errorp = NULL;
+ ns_ldap_attr_t *attrs[2];
+
+
+
+ attrs[0] = (ns_ldap_attr_t *)malloc(sizeof (ns_ldap_attr_t));
+ if (attrs == NULL)
+ return (IDMAP_ERR_MEMORY);
+
+ attrs[0]->attrname = attr;
+
+ if (value != NULL) {
+ char **newattr = (char **)calloc(2, sizeof (char *));
+ if (newattr == NULL) {
+ free(attrs[0]);
+ return (IDMAP_ERR_MEMORY);
+ }
+ newattr[0] = value;
+ newattr[1] = NULL;
+
+ attrs[0]->attrvalue = newattr;
+ attrs[0]->value_count = 1;
+ } else {
+ attrs[0]->attrvalue = NULL;
+ attrs[0]->value_count = 0;
+ }
+
+
+ attrs[1] = NULL;
+
+ if (value == NULL) {
+ ldaprc = __ns_ldap_delAttr(
+ is_user == IDMAP_YES ? "passwd": "group",
+ dn, (const ns_ldap_attr_t * const *)attrs,
+ nsc, 0, &errorp);
+ } else if (is_new)
+ ldaprc = __ns_ldap_addAttr(
+ is_user == IDMAP_YES ? "passwd": "group",
+ dn, (const ns_ldap_attr_t * const *)attrs,
+ nsc, 0, &errorp);
+ else
+ ldaprc = __ns_ldap_repAttr(
+ is_user == IDMAP_YES ? "passwd": "group",
+ dn, (const ns_ldap_attr_t * const *)attrs,
+ nsc, 0, &errorp);
+
+ if (ldaprc != NS_LDAP_SUCCESS) {
+ char *msg = "Cause unidentified";
+ if (errorp != NULL) {
+ (void) __ns_ldap_err2str(errorp->status, &msg);
+ }
+ namemap_log(
+ gettext("__ns_ldap_addAttr/rep/delAttr failed (%s)"),
+ msg);
+ return (IDMAP_ERR_ARG);
+ }
+
+ return (IDMAP_SUCCESS);
+}
+
+idmap_stat
+idmap_set_namemap(idmap_nm_handle_t *p, char *winname, char *unixname,
+ int is_user, int is_wuser, int direction)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ char *dn = NULL;
+ char *oldwinname = NULL;
+ char *oldwindomain = NULL;
+
+ if (direction == IDMAP_DIRECTION_W2U) {
+ if (!p->is_ad) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("AD namemaps aren't set up."));
+ goto cleanup;
+ }
+
+ rc = winname2dn(p, winname, &is_wuser,
+ &dn, NULL, NULL);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr :
+ p->ad_unixgroup_attr, unixname);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ }
+
+
+ if (direction == IDMAP_DIRECTION_U2W) {
+ char *fullname;
+
+ if (!p->is_nldap) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("Native ldap namemaps aren't set up."));
+ goto cleanup;
+ }
+
+
+ rc = unixname2dn(p, unixname, is_user, &dn,
+ &oldwinname, &oldwindomain);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ if (p->windomain == NULL) {
+ fullname = strdup(winname);
+ if (fullname == NULL)
+ rc = IDMAP_ERR_MEMORY;
+ goto cleanup;
+ } else {
+ fullname = malloc(strlen(winname) +
+ strlen(p->windomain) + 2);
+ if (fullname == NULL) {
+ rc = IDMAP_ERR_MEMORY;
+ goto cleanup;
+ }
+
+ (void) snprintf(fullname,
+ strlen(winname) + strlen(p->windomain) + 2,
+ "%s\\%s", p->windomain, winname);
+ }
+ rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr,
+ fullname, oldwinname == NULL ? TRUE : FALSE, is_user);
+
+ free(fullname);
+ free(oldwindomain);
+ free(oldwinname);
+
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ }
+
+cleanup:
+ if (dn != NULL)
+ free(dn);
+
+ if (oldwindomain != NULL)
+ free(oldwindomain);
+
+ if (oldwinname != NULL)
+ free(oldwinname);
+
+ return (rc);
+
+}
+
+
+idmap_stat
+idmap_unset_namemap(idmap_nm_handle_t *p, char *winname, char *unixname,
+ int is_user, int is_wuser, int direction)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ char *dn = NULL;
+ char *oldwinname = NULL;
+ char *oldwindomain = NULL;
+
+ if (direction == IDMAP_DIRECTION_W2U) {
+ if (!p->is_ad) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("AD namemaps aren't set up."));
+ goto cleanup;
+ }
+
+ rc = winname2dn(p, winname, &is_wuser,
+ &dn, NULL, NULL);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ rc = idmap_ad_set(p, dn, is_user ? p->ad_unixuser_attr :
+ p->ad_unixgroup_attr, unixname);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ } else { /* direction == IDMAP_DIRECTION_U2W */
+ if (!p->is_nldap) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("Native ldap namemaps aren't set up."));
+ goto cleanup;
+ }
+
+ rc = unixname2dn(p, unixname, is_user, &dn, NULL, NULL);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ rc = idmap_nldap_set(p, &p->nsc, dn, p->nldap_winname_attr,
+ NULL, TRUE, is_user);
+ if (rc != IDMAP_SUCCESS)
+ goto cleanup;
+
+ }
+
+cleanup:
+ if (oldwindomain != NULL)
+ free(oldwindomain);
+ if (oldwinname != NULL)
+ free(oldwinname);
+ if (dn != NULL)
+ free(dn);
+ return (rc);
+}
+
+idmap_stat
+idmap_get_namemap(idmap_nm_handle_t *p, int *is_source_ad, char **winname,
+ char **windomain, int *is_wuser, char **unixuser, char **unixgroup)
+{
+ idmap_stat rc = IDMAP_SUCCESS;
+ char *dn = NULL;
+
+ *is_source_ad = IDMAP_UNKNOWN;
+ if (*winname != NULL) {
+ *is_source_ad = IDMAP_YES;
+
+ if (p->is_ad == NULL) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("AD namemaps are not active."));
+ goto cleanup;
+ /* In future maybe resolve winname and try nldap? */
+ }
+
+ rc = winname2dn(p, *winname, is_wuser, &dn, unixuser,
+ unixgroup);
+ if (rc != IDMAP_SUCCESS) {
+ namemap_log(
+ gettext("Winname %s@%s not found in AD."),
+ *winname, p->windomain);
+ }
+ } else if (*unixuser != NULL || *unixgroup != NULL) {
+ char *unixname;
+ int is_user;
+
+ *is_source_ad = IDMAP_NO;
+
+ if (p->is_nldap == NULL) {
+ rc = IDMAP_ERR_ARG;
+ namemap_log(
+ gettext("Native ldap namemaps aren't active."));
+ goto cleanup;
+ /* In future maybe resolve unixname and try AD? */
+ }
+
+ if (*unixuser != NULL) {
+ is_user = IDMAP_YES;
+ unixname = *unixuser;
+ } else if (*unixgroup != NULL) {
+ is_user = IDMAP_NO;
+ unixname = *unixgroup;
+ }
+
+ rc = unixname2dn(p, unixname, is_user, NULL, winname,
+ windomain);
+ if (rc != IDMAP_SUCCESS) {
+ namemap_log(
+ gettext("%s %s not found in native ldap."),
+ is_user == IDMAP_YES ? "UNIX user" : "UNIX group",
+ unixname);
+ goto cleanup;
+ }
+ } else {
+ rc = IDMAP_ERR_ARG;
+ goto cleanup;
+ }
+
+cleanup:
+ return (rc);
+}
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;