summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libadutils/common/addisc.c108
-rw-r--r--usr/src/lib/libadutils/common/addisc.h9
-rw-r--r--usr/src/lib/libadutils/common/mapfile-vers4
-rw-r--r--usr/src/lib/libidmap/Makefile.com11
-rw-r--r--usr/src/lib/libidmap/common/directory_helper.c4
-rw-r--r--usr/src/lib/libidmap/common/idmap.h7
-rw-r--r--usr/src/lib/libidmap/common/idmap_api.c19
-rw-r--r--usr/src/lib/libidmap/common/idmap_impl.h10
-rw-r--r--usr/src/lib/libidmap/common/idmap_priv.h31
-rw-r--r--usr/src/lib/libidmap/common/mapfile-vers10
-rw-r--r--usr/src/lib/libidmap/common/namemaps.c1066
-rw-r--r--usr/src/lib/libshare/smb/libshare_smb.c9
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/libmlrpc.h13
-rw-r--r--usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c86
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c370
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c105
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_quota.c11
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/smb_share.c105
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c27
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h4
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers4
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c59
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c4
23 files changed, 740 insertions, 1336 deletions
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/libidmap/common/namemaps.c b/usr/src/lib/libidmap/common/namemaps.c
deleted file mode 100644
index 95e47ddd6c..0000000000
--- a/usr/src/lib/libidmap/common/namemaps.c
+++ /dev/null
@@ -1,1066 +0,0 @@
-/*
- * 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 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-#include <errno.h>
-#include <ldap.h>
-#include <sasl/sasl.h>
-#include <libintl.h>
-#include <strings.h>
-#include <syslog.h>
-
-#include "addisc.h"
-#include "libadutils.h"
-#include "idmap_impl.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);
-}
-
-
-/* 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;
-};
-
-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 {
- logger(LOG_ERR,
- 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) {
- logger(LOG_INFO, "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;
- logger(LOG_INFO, "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) {
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR, 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);
- }
- logger(LOG_ERR, gettext("Ldap list failed (%s)."), msg);
- return (IDMAP_ERR_ARG);
- }
-
- if (res == NULL) {
- logger(LOG_ERR, 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) {
- logger(LOG_ERR, 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) {
- logger(LOG_ERR,
- "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) {
- logger(LOG_ERR,
- *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) {
- logger(LOG_ERR,
- "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);
- }
- logger(LOG_ERR, 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;
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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;
- logger(LOG_ERR,
- 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) {
- logger(LOG_ERR,
- 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/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 *)&param->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 *)&param->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 *)&param->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 *)&param->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(&param->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(&param->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(&param->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(&param->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, &param->rid);
- nt_group_putinfo(grp);
- handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY,
- param->rid);
- bcopy(handle, &param->alias_handle, sizeof (samr_handle_t));
+ rc = smb_lgrp_getbyname((char *)gname, &grp);
+ if (rc != SMB_LGRP_SUCCESS) {
+ bzero(&param->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, &param->alias_handle, sizeof (samr_handle_t));
+ param->status = status;
+ } else {
+ bzero(&param->alias_handle, sizeof (samr_handle_t));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ }
-create_alias_err:
- bzero(&param->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 *)&param->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;
}
/*