mlsvc_domain.c revision 7f667e74610492ddbce8ce60f52ece95d2401949
/*
* 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
* 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 <syslog.h>
#include <synch.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <resolv.h>
#include <netdb.h>
#include <assert.h>
#include <smbsrv/libsmbrdr.h>
#include <smbsrv/libsmbns.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/ntstatus.h>
#include <lsalib.h>
/*
* Domain cache states
*/
#define SMB_DCACHE_STATE_INVALID 0
#define SMB_DCACHE_STATE_UPDATING 1
#define SMB_DCACHE_STATE_VALID 2
typedef struct smb_domain_cache {
static smb_domain_cache_t smb_dcache;
/* functions to manipulate the domain cache */
static void smb_dcache_init(void);
static void smb_dcache_updating(void);
static void smb_dcache_invalid(void);
static void smb_dcache_valid(smb_domain_t *);
/*
* DC Locator
*/
#define SMB_DCLOCATOR_TIMEOUT 45
typedef struct smb_dclocator {
char sdl_domain[SMB_PI_MAX_DOMAIN];
char sdl_dc[MAXHOSTNAMELEN];
static smb_dclocator_t smb_dclocator;
static pthread_t smb_dclocator_thr;
static void *smb_dclocator_main(void *);
static void smb_domain_update_tabent(int, lsa_nt_domaininfo_t *);
static void smb_domain_populate_table(char *, char *);
/*
* ===================================================================
* API to initialize DC locator thread, trigger DC discovery, and
* ===================================================================
*/
/*
* smb_dclocator_init
*
* Initialization of the DC locator thread.
* Returns 0 on success, an error number if thread creation fails.
*/
int
smb_dclocator_init(void)
{
int rc;
(void) pthread_attr_init(&tattr);
smb_dclocator_main, 0);
(void) pthread_attr_destroy(&tattr);
return (rc);
}
/*
* smb_locate_dc
*
* This is the entry point for discovering a domain controller for the
* specified domain.
*
* The actual work of discovering a DC is handled by DC locator thread.
* All we do here is signal the request and wait for a DC or a timeout.
*
* Input parameters:
* domain - domain to be discovered (can either be NetBIOS or DNS domain)
* dc - preferred DC. If the preferred DC is set to empty string, it
* will attempt to discover any DC in the specified domain.
*
* Output parameter:
* dp - on success, dp will be filled with the discovered DC and domain
* information.
*/
{
int rc;
return (B_FALSE);
if (!smb_dclocator.sdl_locate) {
}
while (smb_dclocator.sdl_locate) {
break;
}
dp = &domain_info;
return (rc);
}
/*
* smb_domain_getinfo
*
* If the DC discovery process is underway, this function will wait on
* a condition variable until the state of SMB domain cache sets to
*
* Returns a copy of the domain cache.
*/
{
int err;
&to);
break;
}
} else {
}
return (rc);
}
/*
* =====================================================================
* Private functions used by DC locator thread to manipulate the domain
* cache.
* ======================================================================
*/
static void
smb_dcache_init(void)
{
}
/*
* Set the cache state to UPDATING
*/
static void
smb_dcache_updating(void)
{
}
/*
* Set the cache state to INVALID
*/
static void
smb_dcache_invalid(void)
{
}
/*
* Set the cache state to VALID and populate the cache
*/
static void
{
}
/*
* This function will update both the state and the contents of the
* SMB domain cache. If one attempts to set the state to
* SMB_DCACHE_STATE_UPDATING, the domain cache will be updated based
* on 'dp' argument. Otherwise, 'dp' is ignored.
*/
static void
{
switch (state) {
case SMB_DCACHE_STATE_INVALID:
break;
break;
case SMB_DCACHE_STATE_VALID:
break;
default:
return;
}
}
/*
* ==========================================================
* DC discovery functions
* ==========================================================
*/
/*
* smb_dclocator_main
*
* This is the DC discovery thread: it gets woken up whenever someone
* wants to locate a domain controller.
*
* The state of the SMB domain cache will be initialized to
* SMB_DCACHE_STATE_UPDATING when the discovery process starts and will be
* transitioned to SMB_DCACHE_STATE_VALID/INVALID depending on the outcome of
* the discovery.
*
* If the discovery process is underway, callers of smb_domain_getinfo()
* will wait on a condition variable until the state of SMB domain cache
*
* Upon success, the SMB domain cache will be populated with the discovered DC
* and domain info.
*/
/*ARGSUSED*/
static void *
smb_dclocator_main(void *arg)
{
char domain[SMB_PI_MAX_DOMAIN];
char sought_dc[MAXHOSTNAMELEN];
for (;;) {
while (!smb_dclocator.sdl_locate)
else
}
/*NOTREACHED*/
return (NULL);
}
/*
* smb_dc_discovery
*
* If FQDN is specified, DC discovery will be done via DNS query only.
* If NetBIOS name of a domain is specified, DC discovery thread will
* use netlogon protocol to locate a DC. Upon failure, it will
* try to resolve it via DNS, i.e. find out if it is the first label
* of a DNS domain name. If the corresponding DNS name is found, DC
* discovery will be done via DNS query.
*
* Once the domain controller is found, it then queries the DC for domain
* information. If the LSA queries fail, the domain information stored in
* SMF might be used to set the SMB domain cache if the the discovered domain
* is the same as the previously joined domain.
*
* If the fully-qualified domain name is derived from the DNS config
* file, the NetBIOS domain name specified by the user will be compared
* against the NetBIOS domain name obtained via LSA query. If there is
* a mismatch, the DC discovery will fail since the discovered DC is
* actually for another domain, whose first label of its FQDN somehow
* matches with the NetBIOS name of the domain we're interested in.
*/
static boolean_t
{
char derived_dnsdomain[MAXHOSTNAMELEN];
*derived_dnsdomain = '\0';
if (!SMB_IS_FQDN(domain)) {
return (B_FALSE);
}
if (!netlogon_ok && !smb_ads_lookup_msdcs(
return (B_FALSE);
!= NT_STATUS_SUCCESS) &&
return (B_FALSE);
if (*derived_dnsdomain != '\0' &&
return (B_FALSE);
/*
* Now that we get the fully-qualified DNS name of the
* domain via LSA query. Verifies ADS configuration
* if we previously locate a DC via NetBIOS. On success,
* ADS cache will be populated.
*/
if (netlogon_ok) {
return (B_FALSE);
}
return (B_TRUE);
}
/*
* Tries to find a matching DNS domain for the given NetBIOS domain
* name by checking the first label of system's configured DNS domains.
* If a match is found, it'll be returned in the passed buffer.
*/
static boolean_t
{
struct __res_state res_state;
int i;
char *entry, *p;
char first_label[MAXHOSTNAMELEN];
return (B_FALSE);
*buf = '\0';
return (B_FALSE);
*p = '\0';
}
break;
}
}
return (found);
}
/*
* smb_domain_query
*
* If the the NetBIOS name of an AD domain doesn't match with the
* first label of its fully-qualified DNS name, it is not possible
* to derive one name format from another.
* The missing domain info can be obtained via LSA query, DNS domain info.
*
* domain - either NetBIOS or fully-qualified domain name
*
*/
static uint32_t
{
if (rc == NT_STATUS_SUCCESS) {
sizeof (dp->d_nbdomain));
sizeof (dp->d_fqdomain));
}
return (rc);
}
/*
* smb_domain_populate_table
*
* Populates the domain tablele with primary, account and trusted
* domain info.
* domain - either NetBIOS or fully-qualified domain name.
*/
static void
{
int i;
== NT_STATUS_SUCCESS) {
}
== NT_STATUS_SUCCESS) {
}
== NT_STATUS_SUCCESS) {
}
}
}
static void
{
(void) nt_domain_add(entry);
}
/*
* smb_domain_use_config
*
* If the domain to be discovered matches the current domain (i.e the
* value of either domain or fqdn configuration), the output parameter
* 'dinfo' will be set to the information stored in SMF.
*/
static boolean_t
{
if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
return (B_FALSE);
if (SMB_IS_FQDN(domain)) {
} else {
}
if (use) {
sizeof (dinfo->d_nbdomain));
sizeof (dinfo->d_fqdomain));
}
return (use);
}