1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
221fdeec65Sjoyce mcintosh * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23adee6784SGordon Ross * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
246a23a4b8SGordon Ross * Copyright 2021 RackTop Systems, Inc.
25da6c28aaSamw */
26da6c28aaSamw
27da6c28aaSamw /*
28da6c28aaSamw * Utility functions to support the RPC interface library.
29da6c28aaSamw */
30da6c28aaSamw
31da6c28aaSamw #include <stdio.h>
32da6c28aaSamw #include <stdarg.h>
33da6c28aaSamw #include <strings.h>
34da6c28aaSamw #include <unistd.h>
35da6c28aaSamw #include <netdb.h>
36da6c28aaSamw #include <stdlib.h>
37da6c28aaSamw #include <sys/time.h>
38da6c28aaSamw #include <sys/systm.h>
39b819cea2SGordon Ross #include <note.h>
40fc724630SAlan Wright #include <syslog.h>
41da6c28aaSamw
42da6c28aaSamw #include <smbsrv/libsmb.h>
43da6c28aaSamw #include <smbsrv/libsmbns.h>
44da6c28aaSamw #include <smbsrv/libmlsvc.h>
45adee6784SGordon Ross #include <smb/ntaccess.h>
46da6c28aaSamw #include <smbsrv/smbinfo.h>
47b3700b07SGordon Ross #include <smbsrv/netrauth.h>
48ed9aabc7SGordon Ross #include <libsmbrdr.h>
498d7e4166Sjose borrego #include <lsalib.h>
508d7e4166Sjose borrego #include <samlib.h>
51b3700b07SGordon Ross #include <mlsvc.h>
52da6c28aaSamw
531ed6b69aSGordon Ross static DWORD
541ed6b69aSGordon Ross mlsvc_join_rpc(smb_domainex_t *dxi,
556a23a4b8SGordon Ross char *admin_user, char *admin_pw,
566a23a4b8SGordon Ross char *machine_name, char *machine_pw);
571ed6b69aSGordon Ross static DWORD
581ed6b69aSGordon Ross mlsvc_join_noauth(smb_domainex_t *dxi,
596a23a4b8SGordon Ross char *machine_name, char *machine_pw);
601ed6b69aSGordon Ross
61975041ddSGordon Ross /*
62975041ddSGordon Ross * This is called by smbd_dc_update just after we've learned about a
63975041ddSGordon Ross * new domain controller. Make sure we can authenticate with this DC.
64975041ddSGordon Ross */
65faa1795aSjb DWORD
mlsvc_netlogon(char * server,char * domain)66faa1795aSjb mlsvc_netlogon(char *server, char *domain)
67faa1795aSjb {
68faa1795aSjb DWORD status;
69faa1795aSjb
70975041ddSGordon Ross status = smb_netlogon_check(server, domain);
71b3700b07SGordon Ross if (status != NT_STATUS_SUCCESS) {
72b3700b07SGordon Ross syslog(LOG_NOTICE, "Failed to establish NETLOGON "
73b3700b07SGordon Ross "credential chain with DC: %s (%s)", server,
74b3700b07SGordon Ross xlate_nt_status(status));
75b3700b07SGordon Ross syslog(LOG_NOTICE, "The machine account information on the "
76b3700b07SGordon Ross "domain controller does not match the local storage.");
77b3700b07SGordon Ross syslog(LOG_NOTICE, "To correct this, use 'smbadm join'");
78b3700b07SGordon Ross }
79b3700b07SGordon Ross
80faa1795aSjb return (status);
81faa1795aSjb }
82faa1795aSjb
83da6c28aaSamw /*
841ed6b69aSGordon Ross * Join the specified domain. The method varies depending on whether
851ed6b69aSGordon Ross * we're using "secure join" (using an administrative account to join)
861ed6b69aSGordon Ross * or "unsecure join" (using a pre-created machine account). In the
871ed6b69aSGordon Ross * latter case, the machine account is created "by hand" before this
881ed6b69aSGordon Ross * machine attempts to join, and we just change the password from the
891ed6b69aSGordon Ross * (weak) default password for a new machine account to a random one.
90eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States *
91da6c28aaSamw * Returns NT status codes.
92da6c28aaSamw */
93b3700b07SGordon Ross void
mlsvc_join(smb_joininfo_t * info,smb_joinres_t * res)94b3700b07SGordon Ross mlsvc_join(smb_joininfo_t *info, smb_joinres_t *res)
95da6c28aaSamw {
96b3700b07SGordon Ross static unsigned char zero_hash[SMBAUTH_HASH_SZ];
971ed6b69aSGordon Ross char machine_name[SMB_SAMACCT_MAXLEN];
981ed6b69aSGordon Ross char machine_pw[NETR_MACHINE_ACCT_PASSWD_MAX];
991ed6b69aSGordon Ross unsigned char passwd_hash[SMBAUTH_HASH_SZ];
1006a23a4b8SGordon Ross char addrbuf[INET6_ADDRSTRLEN];
101b3700b07SGordon Ross smb_domainex_t dxi;
102b3700b07SGordon Ross smb_domain_t *di = &dxi.d_primary;
103*857c33c4SGordon Ross char *container;
104*857c33c4SGordon Ross char *username;
105da6c28aaSamw DWORD status;
1061ed6b69aSGordon Ross int rc;
107da6c28aaSamw
108b3700b07SGordon Ross bzero(&dxi, sizeof (dxi));
109b3700b07SGordon Ross
110*857c33c4SGordon Ross if (info->container_name[0] != '\0')
111*857c33c4SGordon Ross container = info->container_name;
112*857c33c4SGordon Ross else
113*857c33c4SGordon Ross container = NULL;
114*857c33c4SGordon Ross if (info->domain_username[0] != '\0')
115*857c33c4SGordon Ross username = info->domain_username;
116*857c33c4SGordon Ross else
117*857c33c4SGordon Ross username = NULL;
118*857c33c4SGordon Ross
1191ed6b69aSGordon Ross /*
1201ed6b69aSGordon Ross * Domain join support: AD (Kerberos+LDAP) or MS-RPC?
1211ed6b69aSGordon Ross */
1221ed6b69aSGordon Ross boolean_t ads_enabled = smb_config_get_ads_enable();
123da6c28aaSamw
124b3700b07SGordon Ross if (smb_getsamaccount(machine_name, sizeof (machine_name)) != 0) {
125b3700b07SGordon Ross res->status = NT_STATUS_INVALID_COMPUTER_NAME;
126b3700b07SGordon Ross return;
127b3700b07SGordon Ross }
128eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States
1291ed6b69aSGordon Ross (void) smb_gen_random_passwd(machine_pw, sizeof (machine_pw));
130da6c28aaSamw
1311ed6b69aSGordon Ross /*
132b3700b07SGordon Ross * Ensure that any previous membership of this domain has
133b3700b07SGordon Ross * been cleared from the environment before we start. This
134b3700b07SGordon Ross * will ensure that we don't attempt a NETLOGON_SAMLOGON
135b3700b07SGordon Ross * when attempting to find the PDC.
1361ed6b69aSGordon Ross */
137b3700b07SGordon Ross (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE);
138b3700b07SGordon Ross
139*857c33c4SGordon Ross if (username != NULL) {
140b3700b07SGordon Ross (void) smb_auth_ntlm_hash(info->domain_passwd, passwd_hash);
141*857c33c4SGordon Ross smb_ipc_set(username, passwd_hash);
142*857c33c4SGordon Ross syslog(LOG_INFO, "smbd: joining with user %s", username);
143b3700b07SGordon Ross } else {
144b3700b07SGordon Ross smb_ipc_set(MLSVC_ANON_USER, zero_hash);
1456a23a4b8SGordon Ross syslog(LOG_INFO, "smbd: joining with anonymous");
146b3700b07SGordon Ross }
147b3700b07SGordon Ross
148b3700b07SGordon Ross /*
149b3700b07SGordon Ross * Tentatively set the idmap domain to the one we're joining,
150b3700b07SGordon Ross * so that the DC locator in idmap knows what to look for.
151b3700b07SGordon Ross * Ditto the SMB server domain.
152b3700b07SGordon Ross */
153b3700b07SGordon Ross if (smb_config_set_idmap_domain(info->domain_name) != 0)
154b3700b07SGordon Ross syslog(LOG_NOTICE, "Failed to set idmap domain name");
155b3700b07SGordon Ross if (smb_config_refresh_idmap() != 0)
156b3700b07SGordon Ross syslog(LOG_NOTICE, "Failed to refresh idmap service");
1576a23a4b8SGordon Ross syslog(LOG_INFO, "smbd: set idmap domain %s", info->domain_name);
158b3700b07SGordon Ross
159b3700b07SGordon Ross /* Clear DNS local (ADS) lookup cache. */
160b3700b07SGordon Ross smb_ads_refresh(B_FALSE);
161b3700b07SGordon Ross
162b3700b07SGordon Ross /*
163b3700b07SGordon Ross * Locate a DC for this domain. Intentionally bypass the
164b3700b07SGordon Ross * ddiscover service here because we're still joining.
165b3700b07SGordon Ross * This also allows better reporting of any failures.
166b3700b07SGordon Ross */
167b3700b07SGordon Ross status = smb_ads_lookup_msdcs(info->domain_name, &dxi.d_dci);
168b3700b07SGordon Ross if (status != NT_STATUS_SUCCESS) {
169b3700b07SGordon Ross syslog(LOG_ERR,
170b3700b07SGordon Ross "smbd: failed to locate AD server for domain %s (%s)",
171b3700b07SGordon Ross info->domain_name, xlate_nt_status(status));
172b3700b07SGordon Ross goto out;
173b3700b07SGordon Ross }
174b3700b07SGordon Ross
175b3700b07SGordon Ross /*
176b3700b07SGordon Ross * Found a DC. Report what we found along with the return status
177b3700b07SGordon Ross * so that admin will know which AD server we were talking to.
178b3700b07SGordon Ross */
179b3700b07SGordon Ross (void) strlcpy(res->dc_name, dxi.d_dci.dc_name, MAXHOSTNAMELEN);
1806a23a4b8SGordon Ross if (smb_inet_ntop(&dxi.d_dci.dc_addr,
1816a23a4b8SGordon Ross addrbuf, sizeof (addrbuf)) == NULL)
1826a23a4b8SGordon Ross strcpy(addrbuf, "?");
1836a23a4b8SGordon Ross syslog(LOG_INFO, "smbd: found AD server %s (%s)",
1846a23a4b8SGordon Ross dxi.d_dci.dc_name, addrbuf);
185dc20a302Sas
186b3700b07SGordon Ross /*
187b3700b07SGordon Ross * Domain discovery needs to authenticate with the AD server.
188b3700b07SGordon Ross * Disconnect any existing connection with the domain controller
189b3700b07SGordon Ross * to make sure we won't use any prior authentication context
190b3700b07SGordon Ross * our redirector might have.
191b3700b07SGordon Ross */
192b3700b07SGordon Ross mlsvc_disconnect(dxi.d_dci.dc_name);
193b3700b07SGordon Ross
194b3700b07SGordon Ross /*
195b3700b07SGordon Ross * Get the domain policy info (domain SID etc).
196b3700b07SGordon Ross * Here too, bypass the smb_ddiscover_service.
197b3700b07SGordon Ross */
198b3700b07SGordon Ross status = smb_ddiscover_main(info->domain_name, &dxi);
199b3700b07SGordon Ross if (status != NT_STATUS_SUCCESS) {
200b3700b07SGordon Ross syslog(LOG_ERR,
201b3700b07SGordon Ross "smbd: failed getting domain info for %s (%s)",
202b3700b07SGordon Ross info->domain_name, xlate_nt_status(status));
203b3700b07SGordon Ross goto out;
204b3700b07SGordon Ross }
205b3700b07SGordon Ross /*
206b3700b07SGordon Ross * After a successful smbd_ddiscover_main() call
207b3700b07SGordon Ross * we should call smb_domain_save() to update the
208b3700b07SGordon Ross * data shown by smbadm list. Do that at the end,
209b3700b07SGordon Ross * only if all goes well with joining the domain.
210b3700b07SGordon Ross */
211b3700b07SGordon Ross
2126a23a4b8SGordon Ross /*
2136a23a4b8SGordon Ross * Log info about the domain from ddiscover
2146a23a4b8SGordon Ross */
2156a23a4b8SGordon Ross syslog(LOG_INFO, "smbd_join: domain FQN=%s", di->di_fqname);
2166a23a4b8SGordon Ross syslog(LOG_INFO, "smbd_join: domain NBN=%s", di->di_nbname);
2176a23a4b8SGordon Ross syslog(LOG_INFO, "smbd_join: domain SID=%s", di->di_sid);
2186a23a4b8SGordon Ross
219b3700b07SGordon Ross /*
220b3700b07SGordon Ross * Create or update our machine account on the DC.
221b3700b07SGordon Ross * A non-null user means we do "secure join".
222b3700b07SGordon Ross */
223*857c33c4SGordon Ross if (username != NULL) {
2241ed6b69aSGordon Ross /*
2251ed6b69aSGordon Ross * If enabled, try to join using AD Services.
2261ed6b69aSGordon Ross */
2271ed6b69aSGordon Ross status = NT_STATUS_UNSUCCESSFUL;
2281ed6b69aSGordon Ross if (ads_enabled) {
2296a23a4b8SGordon Ross syslog(LOG_INFO, "use_ads=true (LDAP join)");
230*857c33c4SGordon Ross res->join_err = smb_ads_join(di->di_fqname, container,
231b3700b07SGordon Ross info->domain_username, info->domain_passwd,
232b3700b07SGordon Ross machine_pw);
233b3700b07SGordon Ross if (res->join_err == SMB_ADS_SUCCESS) {
2341ed6b69aSGordon Ross status = NT_STATUS_SUCCESS;
235da6c28aaSamw }
236b3700b07SGordon Ross } else {
2376a23a4b8SGordon Ross syslog(LOG_INFO, "use_ads=false (RPC join)");
238b3700b07SGordon Ross
239b3700b07SGordon Ross /*
240b3700b07SGordon Ross * If ADS was disabled, join using RPC.
241b3700b07SGordon Ross */
242b3700b07SGordon Ross status = mlsvc_join_rpc(&dxi,
243b3700b07SGordon Ross info->domain_username,
244b3700b07SGordon Ross info->domain_passwd,
2451ed6b69aSGordon Ross machine_name, machine_pw);
246da6c28aaSamw }
2471ed6b69aSGordon Ross
248da6c28aaSamw } else {
2491ed6b69aSGordon Ross /*
2501ed6b69aSGordon Ross * Doing "Unsecure join" (pre-created account)
2511ed6b69aSGordon Ross */
252b3700b07SGordon Ross status = mlsvc_join_noauth(&dxi, machine_name, machine_pw);
253da6c28aaSamw }
254da6c28aaSamw
2551ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS)
2561ed6b69aSGordon Ross goto out;
2571ed6b69aSGordon Ross
2581ed6b69aSGordon Ross /*
2591ed6b69aSGordon Ross * Make sure we can authenticate using the
2601ed6b69aSGordon Ross * (new, or updated) machine account.
2611ed6b69aSGordon Ross */
2621ed6b69aSGordon Ross (void) smb_auth_ntlm_hash(machine_pw, passwd_hash);
2631ed6b69aSGordon Ross smb_ipc_set(machine_name, passwd_hash);
264b3700b07SGordon Ross rc = smbrdr_logon(dxi.d_dci.dc_name, di->di_nbname, machine_name);
2651ed6b69aSGordon Ross if (rc != 0) {
2661ed6b69aSGordon Ross syslog(LOG_NOTICE, "Authenticate with "
2671ed6b69aSGordon Ross "new/updated machine account: %s",
2681ed6b69aSGordon Ross strerror(rc));
269b3700b07SGordon Ross res->join_err = SMB_ADJOIN_ERR_AUTH_NETLOGON;
2701ed6b69aSGordon Ross status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2711ed6b69aSGordon Ross goto out;
2721ed6b69aSGordon Ross }
2731ed6b69aSGordon Ross
2741ed6b69aSGordon Ross /*
275b3700b07SGordon Ross * Store the new machine account password, and
276b3700b07SGordon Ross * SMB_CI_DOMAIN_MEMB etc.
2771ed6b69aSGordon Ross */
278b3700b07SGordon Ross rc = smb_setdomainprops(NULL, dxi.d_dci.dc_name, machine_pw);
2791ed6b69aSGordon Ross if (rc != 0) {
2801ed6b69aSGordon Ross syslog(LOG_NOTICE,
2811ed6b69aSGordon Ross "Failed to save machine account password");
282b3700b07SGordon Ross res->join_err = SMB_ADJOIN_ERR_STORE_PROPS;
2831ed6b69aSGordon Ross status = NT_STATUS_INTERNAL_DB_ERROR;
2841ed6b69aSGordon Ross goto out;
2851ed6b69aSGordon Ross }
2861ed6b69aSGordon Ross
2871ed6b69aSGordon Ross /*
288b3700b07SGordon Ross * Update idmap config?
289b3700b07SGordon Ross * Already set the domain_name above.
2901ed6b69aSGordon Ross */
2911ed6b69aSGordon Ross
2921ed6b69aSGordon Ross /*
293b3700b07SGordon Ross * Save the SMB server config. Sets: SMB_CI_DOMAIN_*
294b3700b07SGordon Ross * Should unify SMB vs idmap configs.
2951ed6b69aSGordon Ross */
296b3700b07SGordon Ross smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
297b3700b07SGordon Ross di->di_sid,
298b3700b07SGordon Ross di->di_u.di_dns.ddi_forest,
299b3700b07SGordon Ross di->di_u.di_dns.ddi_guid);
300b3700b07SGordon Ross smb_ipc_commit();
301b3700b07SGordon Ross smb_domain_save();
302b3700b07SGordon Ross
3031ed6b69aSGordon Ross status = 0;
3041ed6b69aSGordon Ross
3051ed6b69aSGordon Ross out:
306b3700b07SGordon Ross
307b3700b07SGordon Ross if (status != 0) {
308b3700b07SGordon Ross /*
309b3700b07SGordon Ross * Undo the tentative domain settings.
310b3700b07SGordon Ross */
311b3700b07SGordon Ross (void) smb_config_set_idmap_domain("");
312b3700b07SGordon Ross (void) smb_config_refresh_idmap();
313b3700b07SGordon Ross smb_ipc_rollback();
314b3700b07SGordon Ross }
315b3700b07SGordon Ross
3161ed6b69aSGordon Ross /* Avoid leaving cleartext passwords around. */
3171ed6b69aSGordon Ross bzero(machine_pw, sizeof (machine_pw));
3181ed6b69aSGordon Ross bzero(passwd_hash, sizeof (passwd_hash));
3191ed6b69aSGordon Ross
320b3700b07SGordon Ross res->status = status;
3211ed6b69aSGordon Ross }
3221ed6b69aSGordon Ross
3231ed6b69aSGordon Ross static DWORD
mlsvc_join_rpc(smb_domainex_t * dxi,char * admin_user,char * admin_pw,char * machine_name,char * machine_pw)3241ed6b69aSGordon Ross mlsvc_join_rpc(smb_domainex_t *dxi,
3256a23a4b8SGordon Ross char *admin_user, char *admin_pw,
3266a23a4b8SGordon Ross char *machine_name, char *machine_pw)
3271ed6b69aSGordon Ross {
3281ed6b69aSGordon Ross mlsvc_handle_t samr_handle;
3291ed6b69aSGordon Ross mlsvc_handle_t domain_handle;
3301ed6b69aSGordon Ross mlsvc_handle_t user_handle;
3311ed6b69aSGordon Ross smb_account_t ainfo;
332b3700b07SGordon Ross char *server = dxi->d_dci.dc_name;
3331ed6b69aSGordon Ross smb_domain_t *di = &dxi->d_primary;
3341ed6b69aSGordon Ross DWORD account_flags;
3351ed6b69aSGordon Ross DWORD rid;
3361ed6b69aSGordon Ross DWORD status;
3371ed6b69aSGordon Ross int rc;
3381ed6b69aSGordon Ross
3391ed6b69aSGordon Ross /* Caller did smb_ipc_set() so we don't need the pw for now. */
3401ed6b69aSGordon Ross _NOTE(ARGUNUSED(admin_pw));
3411ed6b69aSGordon Ross
3421ed6b69aSGordon Ross rc = samr_open(server, di->di_nbname, admin_user,
3431ed6b69aSGordon Ross MAXIMUM_ALLOWED, &samr_handle);
3441ed6b69aSGordon Ross if (rc != 0) {
3451ed6b69aSGordon Ross syslog(LOG_NOTICE, "sam_connect to server %s failed", server);
3461ed6b69aSGordon Ross return (RPC_NT_SERVER_UNAVAILABLE);
3471ed6b69aSGordon Ross }
3481ed6b69aSGordon Ross /* have samr_handle */
3491ed6b69aSGordon Ross
3501ed6b69aSGordon Ross status = samr_open_domain(&samr_handle, MAXIMUM_ALLOWED,
3511ed6b69aSGordon Ross (struct samr_sid *)di->di_binsid, &domain_handle);
3521ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS)
3531ed6b69aSGordon Ross goto out_samr_handle;
3541ed6b69aSGordon Ross /* have domain_handle */
3551ed6b69aSGordon Ross
3561ed6b69aSGordon Ross account_flags = SAMR_AF_WORKSTATION_TRUST_ACCOUNT;
3571ed6b69aSGordon Ross status = samr_create_user(&domain_handle, machine_name,
3581ed6b69aSGordon Ross account_flags, &rid, &user_handle);
3591ed6b69aSGordon Ross if (status == NT_STATUS_USER_EXISTS) {
3601ed6b69aSGordon Ross status = samr_lookup_domain_names(&domain_handle,
3611ed6b69aSGordon Ross machine_name, &ainfo);
3621ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS)
3631ed6b69aSGordon Ross goto out_domain_handle;
3641ed6b69aSGordon Ross status = samr_open_user(&domain_handle, MAXIMUM_ALLOWED,
3651ed6b69aSGordon Ross ainfo.a_rid, &user_handle);
3661ed6b69aSGordon Ross }
3671ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS) {
3681ed6b69aSGordon Ross syslog(LOG_NOTICE,
369b3700b07SGordon Ross "smbd: failed to open machine account (%s)",
3701ed6b69aSGordon Ross xlate_nt_status(status));
3711ed6b69aSGordon Ross goto out_domain_handle;
3721ed6b69aSGordon Ross }
3731ed6b69aSGordon Ross
3741ed6b69aSGordon Ross /*
3751ed6b69aSGordon Ross * The account exists, and we have user_handle open
3761ed6b69aSGordon Ross * on that account. Set the password and flags.
3771ed6b69aSGordon Ross */
3781ed6b69aSGordon Ross
3791ed6b69aSGordon Ross status = netr_set_user_password(&user_handle, machine_pw);
3801ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS) {
3811ed6b69aSGordon Ross syslog(LOG_NOTICE,
382b3700b07SGordon Ross "smbd: failed to set machine account password (%s)",
3831ed6b69aSGordon Ross xlate_nt_status(status));
3841ed6b69aSGordon Ross goto out_user_handle;
3851ed6b69aSGordon Ross }
3861ed6b69aSGordon Ross
3871ed6b69aSGordon Ross account_flags |= SAMR_AF_DONT_EXPIRE_PASSWD;
3881ed6b69aSGordon Ross status = netr_set_user_control(&user_handle, account_flags);
3891ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS) {
3901ed6b69aSGordon Ross syslog(LOG_NOTICE,
3911ed6b69aSGordon Ross "Set machine account control flags: %s",
3921ed6b69aSGordon Ross xlate_nt_status(status));
3931ed6b69aSGordon Ross goto out_user_handle;
3941ed6b69aSGordon Ross }
3951ed6b69aSGordon Ross
3961ed6b69aSGordon Ross out_user_handle:
3971ed6b69aSGordon Ross (void) samr_close_handle(&user_handle);
3981ed6b69aSGordon Ross out_domain_handle:
3991ed6b69aSGordon Ross (void) samr_close_handle(&domain_handle);
4001ed6b69aSGordon Ross out_samr_handle:
4011ed6b69aSGordon Ross (void) samr_close_handle(&samr_handle);
4021ed6b69aSGordon Ross
4031ed6b69aSGordon Ross return (status);
4041ed6b69aSGordon Ross }
4051ed6b69aSGordon Ross
4061ed6b69aSGordon Ross /*
4071ed6b69aSGordon Ross * Doing "Unsecure join" (using a pre-created machine account).
4081ed6b69aSGordon Ross * All we need to do is change the password from the default
4091ed6b69aSGordon Ross * to a random string.
4101ed6b69aSGordon Ross *
4111ed6b69aSGordon Ross * Note: this is a work in progres. Nexenta issue 11960
4121ed6b69aSGordon Ross * (allow joining an AD domain using a pre-created computer account)
4131ed6b69aSGordon Ross * It turns out that to change the machine account password,
4141ed6b69aSGordon Ross * we need to use a different RPC call, performed over the
4151ed6b69aSGordon Ross * NetLogon secure channel. (See netr_server_password_set2)
4161ed6b69aSGordon Ross */
4171ed6b69aSGordon Ross static DWORD
mlsvc_join_noauth(smb_domainex_t * dxi,char * machine_name,char * machine_pw)4181ed6b69aSGordon Ross mlsvc_join_noauth(smb_domainex_t *dxi,
4196a23a4b8SGordon Ross char *machine_name, char *machine_pw)
4201ed6b69aSGordon Ross {
4211ed6b69aSGordon Ross char old_pw[SMB_SAMACCT_MAXLEN];
4221ed6b69aSGordon Ross DWORD status;
4231ed6b69aSGordon Ross
4241ed6b69aSGordon Ross /*
4251ed6b69aSGordon Ross * Compose the current (default) password for the
4261ed6b69aSGordon Ross * pre-created machine account, which is just the
4271ed6b69aSGordon Ross * account name in lower case, truncated to 14
4281ed6b69aSGordon Ross * characters.
4291ed6b69aSGordon Ross */
4301ed6b69aSGordon Ross if (smb_gethostname(old_pw, sizeof (old_pw), SMB_CASE_LOWER) != 0)
4311ed6b69aSGordon Ross return (NT_STATUS_INTERNAL_ERROR);
4321ed6b69aSGordon Ross old_pw[14] = '\0';
4331ed6b69aSGordon Ross
434b3700b07SGordon Ross status = netr_change_password(dxi->d_dci.dc_name, machine_name,
4351ed6b69aSGordon Ross old_pw, machine_pw);
4361ed6b69aSGordon Ross if (status != NT_STATUS_SUCCESS) {
4371ed6b69aSGordon Ross syslog(LOG_NOTICE,
4381ed6b69aSGordon Ross "Change machine account password: %s",
4391ed6b69aSGordon Ross xlate_nt_status(status));
4401ed6b69aSGordon Ross }
441da6c28aaSamw return (status);
442da6c28aaSamw }
443a0aa776eSAlan Wright
444a0aa776eSAlan Wright void
mlsvc_disconnect(const char * server)445a0aa776eSAlan Wright mlsvc_disconnect(const char *server)
446a0aa776eSAlan Wright {
447a0aa776eSAlan Wright smbrdr_disconnect(server);
448a0aa776eSAlan Wright }
4493299f39fSGordon Ross
4503299f39fSGordon Ross /*
4513299f39fSGordon Ross * A few more helper functions for RPC services.
4523299f39fSGordon Ross */
4533299f39fSGordon Ross
4543299f39fSGordon Ross /*
4553299f39fSGordon Ross * Check whether or not the specified user has administrator privileges,
4563299f39fSGordon Ross * i.e. is a member of Domain Admins or Administrators.
4573299f39fSGordon Ross * Returns true if the user is an administrator, otherwise returns false.
4583299f39fSGordon Ross */
4593299f39fSGordon Ross boolean_t
ndr_is_admin(ndr_xa_t * xa)4603299f39fSGordon Ross ndr_is_admin(ndr_xa_t *xa)
4613299f39fSGordon Ross {
4623299f39fSGordon Ross smb_netuserinfo_t *ctx = xa->pipe->np_user;
4633299f39fSGordon Ross
4643299f39fSGordon Ross return (ctx->ui_flags & SMB_ATF_ADMIN);
4653299f39fSGordon Ross }
4663299f39fSGordon Ross
4673299f39fSGordon Ross /*
4683299f39fSGordon Ross * Check whether or not the specified user has power-user privileges,
4693299f39fSGordon Ross * i.e. is a member of Domain Admins, Administrators or Power Users.
4703299f39fSGordon Ross * This is typically required for operations such as managing shares.
4713299f39fSGordon Ross * Returns true if the user is a power user, otherwise returns false.
4723299f39fSGordon Ross */
4733299f39fSGordon Ross boolean_t
ndr_is_poweruser(ndr_xa_t * xa)4743299f39fSGordon Ross ndr_is_poweruser(ndr_xa_t *xa)
4753299f39fSGordon Ross {
4763299f39fSGordon Ross smb_netuserinfo_t *ctx = xa->pipe->np_user;
4773299f39fSGordon Ross
4783299f39fSGordon Ross return ((ctx->ui_flags & SMB_ATF_ADMIN) ||
4793299f39fSGordon Ross (ctx->ui_flags & SMB_ATF_POWERUSER));
4803299f39fSGordon Ross }
4813299f39fSGordon Ross
4823299f39fSGordon Ross int32_t
ndr_native_os(ndr_xa_t * xa)4833299f39fSGordon Ross ndr_native_os(ndr_xa_t *xa)
4843299f39fSGordon Ross {
4853299f39fSGordon Ross smb_netuserinfo_t *ctx = xa->pipe->np_user;
4863299f39fSGordon Ross
4873299f39fSGordon Ross return (ctx->ui_native_os);
4883299f39fSGordon Ross }
489