summaryrefslogtreecommitdiff
path: root/usr/src/lib/smbsrv/libsmb/common/smb_domain.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/smbsrv/libsmb/common/smb_domain.c')
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_domain.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c
new file mode 100644
index 0000000000..22ea5e61fb
--- /dev/null
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c
@@ -0,0 +1,394 @@
+/*
+ * 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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file defines the NT domain environment values and the domain
+ * database interface. The database is a single linked list of
+ * structures containing domain type, name and SID information.
+ */
+
+#include <strings.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <synch.h>
+
+#include <smbsrv/smbinfo.h>
+#include <smbsrv/string.h>
+#include <smbsrv/ntsid.h>
+#include <smbsrv/alloc.h>
+
+#include <smbsrv/libsmb.h>
+
+
+static void nt_domain_unlist(nt_domain_t *);
+
+/*
+ * Valid domain type identifiers as text. This table must be kept
+ * in step with the nt_domain_type_t enum in ntdomain.h.
+ */
+static char *nt_domain_type_name[NT_DOMAIN_NUM_TYPES] = {
+ "null",
+ "builtin",
+ "local",
+ "primary",
+ "account",
+ "trusted",
+ "untrusted"
+};
+
+
+static rwlock_t nt_domain_lock;
+static nt_domain_t *nt_domain_list;
+
+/*
+ * nt_domain_init
+ *
+ * NT domain database one time initialization. This function should
+ * be called during module installation.
+ *
+ * Returns 0 on successful domain initialization. Less than zero otherwise.
+ */
+int
+nt_domain_init(char *resource_domain, uint32_t secmode)
+{
+ nt_domain_t *domain;
+ nt_sid_t *sid;
+ char *sidstr;
+ char *lsidstr;
+ char hostname[MAXHOSTNAMELEN];
+
+ if (rwlock_init(&nt_domain_lock, USYNC_THREAD, NULL))
+ return (SMB_DOMAIN_NODOMAIN_SID);
+
+ if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) {
+ (void) rwlock_destroy(&nt_domain_lock);
+ return (SMB_DOMAIN_NOMACHINE_SID);
+ }
+
+ lsidstr = smb_config_get_localsid();
+
+ if (lsidstr) {
+ sid = nt_sid_strtosid(lsidstr);
+
+ if (sid) {
+ domain = nt_domain_new(NT_DOMAIN_LOCAL, hostname, sid);
+ (void) nt_domain_add(domain);
+ free(sid);
+ }
+ free(lsidstr);
+ } else {
+ (void) rwlock_destroy(&nt_domain_lock);
+ return (SMB_DOMAIN_NOMACHINE_SID);
+ }
+
+ if (secmode == SMB_SECMODE_DOMAIN) {
+ sid = nt_sid_strtosid(NT_BUILTIN_DOMAIN_SIDSTR);
+ domain = nt_domain_new(NT_DOMAIN_BUILTIN, "BUILTIN", sid);
+ (void) nt_domain_add(domain);
+ free(sid);
+
+ smb_config_rdlock();
+ sidstr = smb_config_get(SMB_CI_DOMAIN_SID);
+ if (sidstr) {
+ sid = nt_sid_strtosid(sidstr);
+ smb_config_unlock();
+ domain = nt_domain_new(NT_DOMAIN_PRIMARY,
+ resource_domain, sid);
+ (void) nt_domain_add(domain);
+ free(sid);
+ } else {
+ smb_config_unlock();
+ (void) rwlock_destroy(&nt_domain_lock);
+ return (SMB_DOMAIN_NODOMAIN_SID);
+ }
+
+ }
+ return (0);
+}
+
+/*
+ * nt_domain_new
+ *
+ * Allocate and initialize a new domain structure. On success, a pointer to
+ * the new domain structure is returned. Otherwise a null pointer is returned.
+ */
+nt_domain_t *
+nt_domain_new(nt_domain_type_t type, char *name, nt_sid_t *sid)
+{
+ nt_domain_t *new_domain;
+
+ if ((name == NULL) || (sid == NULL))
+ return (NULL);
+
+ if (type == NT_DOMAIN_NULL || type >= NT_DOMAIN_NUM_TYPES)
+ return (NULL);
+
+ if ((new_domain = malloc(sizeof (nt_domain_t))) == NULL)
+ return (NULL);
+
+ bzero(new_domain, sizeof (nt_domain_t));
+ new_domain->type = type;
+ new_domain->name = strdup(name);
+ new_domain->sid = nt_sid_dup(sid);
+
+ return (new_domain);
+}
+
+/*
+ * nt_domain_delete
+ *
+ * Free the memory used by the specified domain structure.
+ */
+void
+nt_domain_delete(nt_domain_t *domain)
+{
+ if (domain) {
+ free(domain->name);
+ free(domain->sid);
+ free(domain);
+ }
+}
+
+
+/*
+ * nt_domain_add
+ *
+ * Add a domain structure to the global list. There is no checking
+ * for duplicates. If it's the primary domain, we save the SID in the
+ * environment. Returns a pointer to the new domain entry on success.
+ * Otherwise a null pointer is returned.
+ */
+nt_domain_t *
+nt_domain_add(nt_domain_t *new_domain)
+{
+ char *sidstr;
+
+ if (new_domain == NULL)
+ return (NULL);
+
+ (void) rw_wrlock(&nt_domain_lock);
+
+ new_domain->next = nt_domain_list;
+ nt_domain_list = new_domain;
+
+ if (new_domain->type == NT_DOMAIN_PRIMARY) {
+ sidstr = nt_sid_format(new_domain->sid);
+ smb_config_wrlock();
+ (void) smb_config_set(SMB_CI_DOMAIN_SID, sidstr);
+ smb_config_unlock();
+ free(sidstr);
+ }
+ (void) rw_unlock(&nt_domain_lock);
+
+ return (new_domain);
+}
+
+
+/*
+ * nt_domain_remove
+ *
+ * Remove a domain from the global list. The memory
+ * used by the structure is not freed.
+ */
+void
+nt_domain_remove(nt_domain_t *domain)
+{
+ (void) rw_wrlock(&nt_domain_lock);
+ nt_domain_unlist(domain);
+ (void) rw_unlock(&nt_domain_lock);
+}
+
+
+/*
+ * nt_domain_flush
+ *
+ * Flush all domains of the specified type from the list. This is
+ * useful for things like updating the list of trusted domains.
+ */
+void
+nt_domain_flush(nt_domain_type_t domain_type)
+{
+ nt_domain_t *domain = nt_domain_list;
+
+ (void) rw_wrlock(&nt_domain_lock);
+ while (domain) {
+ if (domain->type == domain_type) {
+ nt_domain_unlist(domain);
+ nt_domain_delete(domain);
+ domain = nt_domain_list;
+ continue;
+ }
+ domain = domain->next;
+ }
+ (void) rw_unlock(&nt_domain_lock);
+}
+
+/*
+ * nt_domain_xlat_type
+ *
+ * Translate a domain type into a text string.
+ */
+char *
+nt_domain_xlat_type(nt_domain_type_t domain_type)
+{
+ if (domain_type < NT_DOMAIN_NUM_TYPES)
+ return (nt_domain_type_name[domain_type]);
+ else
+ return ("unknown");
+}
+
+
+/*
+ * nt_domain_xlat_type_name
+ *
+ * Translate a domain type test string into a domain type.
+ */
+nt_domain_type_t
+nt_domain_xlat_type_name(char *type_name)
+{
+ int i;
+
+ for (i = 0; i < NT_DOMAIN_NUM_TYPES; ++i)
+ if (utf8_strcasecmp(nt_domain_type_name[i], type_name) == 0)
+ return (i);
+
+ return (NT_DOMAIN_NUM_TYPES);
+}
+
+
+/*
+ * nt_domain_lookup_name
+ *
+ * Lookup a domain by its domain name. If the domain is in the list,
+ * a pointer to it is returned. Otherwise a null pointer is returned.
+ */
+nt_domain_t *
+nt_domain_lookup_name(char *domain_name)
+{
+ nt_domain_t *domain = nt_domain_list;
+
+ (void) rw_rdlock(&nt_domain_lock);
+ while (domain) {
+ if (utf8_strcasecmp(domain->name, domain_name) == 0)
+ break;
+
+ domain = domain->next;
+ }
+ (void) rw_unlock(&nt_domain_lock);
+
+ return (domain);
+}
+
+
+/*
+ * nt_domain_lookup_sid
+ *
+ * Lookup a domain by its domain SID. If the domain is in the list,
+ * a pointer to it is returned. Otherwise a null pointer is returned.
+ */
+nt_domain_t *
+nt_domain_lookup_sid(nt_sid_t *domain_sid)
+{
+ nt_domain_t *domain = nt_domain_list;
+
+ (void) rw_rdlock(&nt_domain_lock);
+ while (domain) {
+ if (nt_sid_is_equal(domain->sid, domain_sid))
+ break;
+
+ domain = domain->next;
+ }
+ (void) rw_unlock(&nt_domain_lock);
+
+ return (domain);
+}
+
+
+/*
+ * nt_domain_lookupbytype
+ *
+ * Lookup a domain by its type. The first matching entry in the list
+ * is returned. Otherwise a null pointer is returned.
+ */
+nt_domain_t *
+nt_domain_lookupbytype(nt_domain_type_t type)
+{
+ nt_domain_t *domain = nt_domain_list;
+
+ (void) rw_rdlock(&nt_domain_lock);
+ while (domain) {
+ if (domain->type == type)
+ break;
+
+ domain = domain->next;
+ }
+ (void) rw_unlock(&nt_domain_lock);
+
+ return (domain);
+}
+
+
+/*
+ * nt_domain_local_sid
+ *
+ * Return a pointer to the local domain SID. Each system has a SID that
+ * represents the local domain, which is named after the local hostname.
+ * The local domain SID must exist.
+ */
+nt_sid_t *
+nt_domain_local_sid(void)
+{
+ nt_domain_t *domain = nt_domain_list;
+
+ (void) rw_rdlock(&nt_domain_lock);
+ while (domain) {
+ if (domain->type == NT_DOMAIN_LOCAL)
+ break;
+
+ domain = domain->next;
+ }
+ (void) rw_unlock(&nt_domain_lock);
+
+ return (domain->sid);
+}
+
+
+static void
+nt_domain_unlist(nt_domain_t *domain)
+{
+ nt_domain_t **ppdomain = &nt_domain_list;
+
+ while (*ppdomain) {
+ if (*ppdomain == domain) {
+ *ppdomain = domain->next;
+ domain->next = NULL;
+ return;
+ }
+ ppdomain = &(*ppdomain)->next;
+ }
+}