smbd_join.c revision faa1795a28a5c712eed6d0a3f84d98c368a316c6
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#pragma ident "%Z%%M% %I% %E% SMI"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Maximum time to wait for a domain controller (30 seconds).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Flags used in conjunction with the location and query condition
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * variables.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct smb_netlogon_info {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb/* NT4 domain support is not yet available. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Inline convenience function to find out if the domain information is
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * valid. The caller can decide whether or not to wait.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Retrieve the kpasswd server from krb5.conf.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (-1);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb /* Weed out any comment text */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smbd_join
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Joins the specified domain/workgroup
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb (void) smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kpasswd_domain,
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as " old keys from the Kerberos keytab. "
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as "Please remove the old keys for your "
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as "host principal.");
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, info->domain_name);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Ensure that any previous membership of this domain has
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * been cleared from the environment before we start. This
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will ensure that we don't attempt a NETLOGON_SAMLOGON
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * when attempting to find the PDC.
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) strlcpy(plain_user, info->domain_username, sizeof (plain_user));
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as (void) smb_resolve_netbiosname(info->domain_name, nbt_domain,
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as if (smb_resolve_fqdn(info->domain_name, fqdn, sizeof (fqdn)) != 1) {
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as syslog(LOG_ERR, "smbd: fully-qualified domain name is unknown");
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as syslog(LOG_ERR, "smbd: unable to remove the old keys from the"
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as " Kerberos keytab. Please remove the old keys for your "
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as "host principal.");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (smb_auth_ntlm_hash(plain_passwd, passwd_hash) != SMBAUTH_SUCCESS) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "smbd: could not compute ntlm hash for '%s'",
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb "controller information for '%s'",
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb "specified domain controller information "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Temporary delay before creating
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the workstation trust account.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_ERR, "smbd: failed locating domain controller for %s",
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * smbd_locate_dc
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is the entry point for discovering a domain controller for the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specified domain. The caller may block here for around 30 seconds if
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the system has to go to the network and find a domain controller.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Sometime it would be good to change this to smb_locate_pdc and allow
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the caller to specify whether or not he wants to wait for a response.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The actual work of discovering a DC is handled by other threads.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * All we do here is signal the request and wait for a DC or a timeout.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * domain - domain to be discovered
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * dc - preferred DC. If the preferred DC is set to empty string, it
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * will attempt to discover any DC in the specified domain.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns B_TRUE if a domain controller is available.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((smb_netlogon_info.snli_flags & SMB_NETLF_LOCATE_DC) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) cond_broadcast(&smb_netlogon_info.snli_locate_cv);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (smb_netlogon_info.snli_flags & SMB_NETLF_LOCATE_DC) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = cond_reltimedwait(&smb_netlogon_info.snli_locate_cv,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&smb_netlogon_info.snli_locate_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_init
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Initialization of the DC browser and LSA monitor threads.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns 0 on success, an error number if thread creation fails.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_dc_browser
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is the DC browser thread: it gets woken up whenever someone
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wants to locate a domain controller.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * With the introduction of Windows 2000, NetBIOS is no longer a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * requirement for NT domains. If NetBIOS has been disabled on the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * network there will be no browsers and we won't get any response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to netlogon requests. So we try to find a DC controller via ADS
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * first. If ADS is disabled or the DNS query fails, we drop back
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to the netlogon protocol.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This function will block for up to 30 seconds waiting for the PDC
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to be discovered. Sometime it would be good to change this to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_locate_pdc and allow the caller to specify whether or not he
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wants to wait for a response.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while ((smb_netlogon_info.snli_flags & SMB_NETLF_LOCATE_DC) ==
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&smb_netlogon_info.snli_locate_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) strlcpy(resource_domain, smb_netlogon_info.snli_domain,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb (void) strlcpy(dc, smb_netlogon_info.snli_dc, MAXHOSTNAMELEN);
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* Try to locate a DC via NetBIOS */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) cond_broadcast(&smb_netlogon_info.snli_locate_cv);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) mutex_unlock(&smb_netlogon_info.snli_locate_mtx);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Notify the LSA monitor to update the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * primary and trusted domain information.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) cond_broadcast(&smb_netlogon_info.snli_query_cv);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*NOTREACHED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_lsa_monitor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This monitor should run as a separate thread. It waits on a condition
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * variable until someone indicates that the LSA domain information needs
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to be refreshed. It then queries the DC for the NT domain information:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * primary, account and trusted domains. The condition variable should be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * signaled whenever a DC is selected.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Note that the LSA query calls require the DC information and this task
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * may end up blocked on the DC location protocol, which is why this
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * monitor is run as a separate thread. This should only happen if the DC
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * goes down immediately after we located it.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*ARGSUSED*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (;;) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while ((smb_netlogon_info.snli_flags & SMB_NETLF_LSA_QUERY) ==
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Skip the LSA query if Authenticated IPC is supported
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and the credential is not yet set.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "NetlogonLSAMonitor: query "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "account info failed");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "NetlogonLSAMonitor: enum "
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "trusted domain failed");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "NetlogonLSAMonitor: update failed");
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*NOTREACHED*/
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * smb_set_netlogon_cred
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * If the system is joined to an AD domain via kclient, SMB daemon will need
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * to establish the NETLOGON credential chain.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Since the kclient has updated the machine password stored in SMF
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * repository, the cached ipc_info must be updated accordingly by calling
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * smbrdr_ipc_commit.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Due to potential replication delays in a multiple DC environment, the
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * NETLOGON rpc request must be sent to the DC, to which the KPASSWD request
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * is sent. If the DC discovered by the SMB daemon is different than the
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * kpasswd server, the current connection with the DC will be torn down
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * and a DC discovery process will be triggered to locate the kpasswd
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * If joining a new domain, the domain_name property must be set after a
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * successful credential chain setup.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb (void) smb_config_getstr(SMB_CI_KPASSWD_SRV, kpasswd_srv,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * If the domain join initiated by smbadm join CLI is in
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * progress, don't do anything.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb (void) smb_gethostname(sam_acct, MLSVC_ACCOUNT_NAME_MAX - 1, 0);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb (void) smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kpasswd_domain,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb strncasecmp(kpasswd_domain, dp->domain, strlen(dp->domain))) {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * DC discovery will be triggered if the domain info is not
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * currently cached or the SMB daemon has previously discovered a DC
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * that is different than the kpasswd server.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (new_domain || strcasecmp(dp->server, kpasswd_srv) != 0) {
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb syslog(LOG_ERR, "NETLOGON credential chain establishment"
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb " failed");