da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
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 *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
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 *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
1fdeec650620e8498c06f832ea4bd2292f7e9632joyce mcintosh * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Utility functions to support the RPC interface library.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdio.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdarg.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <strings.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <unistd.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <netdb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdlib.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/time.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/systm.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <note.h>
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright#include <syslog.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/libsmb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/libsmbns.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/libmlsvc.h>
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross#include <smbsrv/ntaccess.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/smbinfo.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <smbsrv/netrauth.h>
ed9aabc708901eb85fb058aacbd851c0fd958a16Gordon Ross#include <libsmbrdr.h>
8d7e41661dc4633488e93b13363137523ce59977jose borrego#include <lsalib.h>
8d7e41661dc4633488e93b13363137523ce59977jose borrego#include <samlib.h>
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross#include <mlsvc.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossstatic DWORD
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossmlsvc_join_rpc(smb_domainex_t *dxi,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char *admin_user, char *admin_pw,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char *machine_name, char *machine_pw);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossstatic DWORD
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossmlsvc_join_noauth(smb_domainex_t *dxi,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char *machine_name, char *machine_pw);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbDWORD
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbmlsvc_netlogon(char *server, char *domain)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb{
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb mlsvc_handle_t netr_handle;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb DWORD status;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = netr_open(server, domain, &netr_handle);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (status != 0) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE, "Failed to connect to %s "
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "for domain %s (%s)", server, domain,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross xlate_nt_status(status));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return (status);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb }
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = netlogon_auth(server, &netr_handle, NETR_FLG_INIT);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (status != NT_STATUS_SUCCESS) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_NOTICE, "Failed to establish NETLOGON "
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "credential chain with DC: %s (%s)", server,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross xlate_nt_status(status));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_NOTICE, "The machine account information on the "
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "domain controller does not match the local storage.");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_NOTICE, "To correct this, use 'smbadm join'");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) netr_close(&netr_handle);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return (status);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb}
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Join the specified domain. The method varies depending on whether
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * we're using "secure join" (using an administrative account to join)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * or "unsecure join" (using a pre-created machine account). In the
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * latter case, the machine account is created "by hand" before this
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * machine attempts to join, and we just change the password from the
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * (weak) default password for a new machine account to a random one.
eb1d736b1c19f6abeee90c921a9320b67fedd016afshin salek ardakani - Sun Microsystems - Irvine United States *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns NT status codes.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossvoid
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Rossmlsvc_join(smb_joininfo_t *info, smb_joinres_t *res)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross static unsigned char zero_hash[SMBAUTH_HASH_SZ];
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char machine_name[SMB_SAMACCT_MAXLEN];
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char machine_pw[NETR_MACHINE_ACCT_PASSWD_MAX];
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross unsigned char passwd_hash[SMBAUTH_HASH_SZ];
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_domainex_t dxi;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_domain_t *di = &dxi.d_primary;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DWORD status;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross bzero(&dxi, sizeof (dxi));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Domain join support: AD (Kerberos+LDAP) or MS-RPC?
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross boolean_t ads_enabled = smb_config_get_ads_enable();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (smb_getsamaccount(machine_name, sizeof (machine_name)) != 0) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = NT_STATUS_INVALID_COMPUTER_NAME;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross return;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
eb1d736b1c19f6abeee90c921a9320b67fedd016afshin salek ardakani - Sun Microsystems - Irvine United States
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross (void) smb_gen_random_passwd(machine_pw, sizeof (machine_pw));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Ensure that any previous membership of this domain has
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * been cleared from the environment before we start. This
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * will ensure that we don't attempt a NETLOGON_SAMLOGON
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * when attempting to find the PDC.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (info->domain_username[0] != '\0') {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) smb_auth_ntlm_hash(info->domain_passwd, passwd_hash);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_ipc_set(info->domain_username, passwd_hash);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross } else {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_ipc_set(MLSVC_ANON_USER, zero_hash);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Tentatively set the idmap domain to the one we're joining,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * so that the DC locator in idmap knows what to look for.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Ditto the SMB server domain.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (smb_config_set_idmap_domain(info->domain_name) != 0)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_NOTICE, "Failed to set idmap domain name");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (smb_config_refresh_idmap() != 0)
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_NOTICE, "Failed to refresh idmap service");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /* Clear DNS local (ADS) lookup cache. */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_ads_refresh(B_FALSE);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Locate a DC for this domain. Intentionally bypass the
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * ddiscover service here because we're still joining.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * This also allows better reporting of any failures.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = smb_ads_lookup_msdcs(info->domain_name, &dxi.d_dci);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (status != NT_STATUS_SUCCESS) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_ERR,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "smbd: failed to locate AD server for domain %s (%s)",
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross info->domain_name, xlate_nt_status(status));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross goto out;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Found a DC. Report what we found along with the return status
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * so that admin will know which AD server we were talking to.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) strlcpy(res->dc_name, dxi.d_dci.dc_name, MAXHOSTNAMELEN);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_INFO, "smbd: found AD server %s", dxi.d_dci.dc_name);
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Domain discovery needs to authenticate with the AD server.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Disconnect any existing connection with the domain controller
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * to make sure we won't use any prior authentication context
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * our redirector might have.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross mlsvc_disconnect(dxi.d_dci.dc_name);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Get the domain policy info (domain SID etc).
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Here too, bypass the smb_ddiscover_service.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = smb_ddiscover_main(info->domain_name, &dxi);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (status != NT_STATUS_SUCCESS) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_ERR,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "smbd: failed getting domain info for %s (%s)",
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross info->domain_name, xlate_nt_status(status));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross goto out;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * After a successful smbd_ddiscover_main() call
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * we should call smb_domain_save() to update the
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * data shown by smbadm list. Do that at the end,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * only if all goes well with joining the domain.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Create or update our machine account on the DC.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * A non-null user means we do "secure join".
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (info->domain_username[0] != '\0') {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * If enabled, try to join using AD Services.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = NT_STATUS_UNSUCCESSFUL;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (ads_enabled) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->join_err = smb_ads_join(di->di_fqname,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross info->domain_username, info->domain_passwd,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross machine_pw);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (res->join_err == SMB_ADS_SUCCESS) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = NT_STATUS_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross } else {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross syslog(LOG_DEBUG, "use_ads=false (do RPC join)");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * If ADS was disabled, join using RPC.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = mlsvc_join_rpc(&dxi,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross info->domain_username,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross info->domain_passwd,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross machine_name, machine_pw);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Doing "Unsecure join" (pre-created account)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = mlsvc_join_noauth(&dxi, machine_name, machine_pw);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Make sure we can authenticate using the
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * (new, or updated) machine account.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross (void) smb_auth_ntlm_hash(machine_pw, passwd_hash);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross smb_ipc_set(machine_name, passwd_hash);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross rc = smbrdr_logon(dxi.d_dci.dc_name, di->di_nbname, machine_name);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (rc != 0) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE, "Authenticate with "
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross "new/updated machine account: %s",
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross strerror(rc));
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->join_err = SMB_ADJOIN_ERR_AUTH_NETLOGON;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Store the new machine account password, and
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * SMB_CI_DOMAIN_MEMB etc.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross rc = smb_setdomainprops(NULL, dxi.d_dci.dc_name, machine_pw);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (rc != 0) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross "Failed to save machine account password");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->join_err = SMB_ADJOIN_ERR_STORE_PROPS;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = NT_STATUS_INTERNAL_DB_ERROR;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Update idmap config?
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Already set the domain_name above.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Save the SMB server config. Sets: SMB_CI_DOMAIN_*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Should unify SMB vs idmap configs.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross di->di_sid,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross di->di_u.di_dns.ddi_forest,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross di->di_u.di_dns.ddi_guid);
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_ipc_commit();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_domain_save();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = 0;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossout:
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross if (status != 0) {
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross /*
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross * Undo the tentative domain settings.
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross */
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) smb_config_set_idmap_domain("");
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross (void) smb_config_refresh_idmap();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross smb_ipc_rollback();
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross }
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /* Avoid leaving cleartext passwords around. */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross bzero(machine_pw, sizeof (machine_pw));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross bzero(passwd_hash, sizeof (passwd_hash));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross res->status = status;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross}
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossstatic DWORD
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossmlsvc_join_rpc(smb_domainex_t *dxi,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char *admin_user, char *admin_pw,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char *machine_name, char *machine_pw)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross{
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross mlsvc_handle_t samr_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross mlsvc_handle_t domain_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross mlsvc_handle_t user_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross smb_account_t ainfo;
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross char *server = dxi->d_dci.dc_name;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross smb_domain_t *di = &dxi->d_primary;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross DWORD account_flags;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross DWORD rid;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross DWORD status;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross int rc;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /* Caller did smb_ipc_set() so we don't need the pw for now. */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross _NOTE(ARGUNUSED(admin_pw));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross rc = samr_open(server, di->di_nbname, admin_user,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross MAXIMUM_ALLOWED, &samr_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (rc != 0) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE, "sam_connect to server %s failed", server);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross return (RPC_NT_SERVER_UNAVAILABLE);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /* have samr_handle */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = samr_open_domain(&samr_handle, MAXIMUM_ALLOWED,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross (struct samr_sid *)di->di_binsid, &domain_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out_samr_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /* have domain_handle */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross account_flags = SAMR_AF_WORKSTATION_TRUST_ACCOUNT;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = samr_create_user(&domain_handle, machine_name,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross account_flags, &rid, &user_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status == NT_STATUS_USER_EXISTS) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = samr_lookup_domain_names(&domain_handle,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross machine_name, &ainfo);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out_domain_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = samr_open_user(&domain_handle, MAXIMUM_ALLOWED,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross ainfo.a_rid, &user_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "smbd: failed to open machine account (%s)",
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross xlate_nt_status(status));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out_domain_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * The account exists, and we have user_handle open
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * on that account. Set the password and flags.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = netr_set_user_password(&user_handle, machine_pw);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE,
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross "smbd: failed to set machine account password (%s)",
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross xlate_nt_status(status));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out_user_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross account_flags |= SAMR_AF_DONT_EXPIRE_PASSWD;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross status = netr_set_user_control(&user_handle, account_flags);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross "Set machine account control flags: %s",
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross xlate_nt_status(status));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross goto out_user_handle;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossout_user_handle:
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross (void) samr_close_handle(&user_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossout_domain_handle:
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross (void) samr_close_handle(&domain_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossout_samr_handle:
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross (void) samr_close_handle(&samr_handle);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross return (status);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross}
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross/*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Doing "Unsecure join" (using a pre-created machine account).
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * All we need to do is change the password from the default
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * to a random string.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross *
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Note: this is a work in progres. Nexenta issue 11960
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * (allow joining an AD domain using a pre-created computer account)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * It turns out that to change the machine account password,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * we need to use a different RPC call, performed over the
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * NetLogon secure channel. (See netr_server_password_set2)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossstatic DWORD
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Rossmlsvc_join_noauth(smb_domainex_t *dxi,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char *machine_name, char *machine_pw)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross{
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross char old_pw[SMB_SAMACCT_MAXLEN];
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross DWORD status;
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross /*
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * Compose the current (default) password for the
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * pre-created machine account, which is just the
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * account name in lower case, truncated to 14
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross * characters.
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross */
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (smb_gethostname(old_pw, sizeof (old_pw), SMB_CASE_LOWER) != 0)
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross return (NT_STATUS_INTERNAL_ERROR);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross old_pw[14] = '\0';
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross
b3700b074e637f8c6991b70754c88a2cfffb246bGordon Ross status = netr_change_password(dxi->d_dci.dc_name, machine_name,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross old_pw, machine_pw);
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross if (status != NT_STATUS_SUCCESS) {
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross syslog(LOG_NOTICE,
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross "Change machine account password: %s",
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross xlate_nt_status(status));
1ed6b69a5ca1ca3ee5e9a4931f74e2237c7e1c9fGordon Ross }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (status);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightvoid
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wrightmlsvc_disconnect(const char *server)
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright{
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright smbrdr_disconnect(server);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright}