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 /*
22c5866007SKeyur Desai * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw
26da6c28aaSamw #include <sys/param.h>
27da6c28aaSamw #include <ldap.h>
28da6c28aaSamw #include <stdlib.h>
29da6c28aaSamw #include <sys/types.h>
30da6c28aaSamw #include <sys/socket.h>
31da6c28aaSamw #include <netinet/in.h>
32da6c28aaSamw #include <arpa/inet.h>
33da6c28aaSamw #include <sys/time.h>
34da6c28aaSamw #include <netdb.h>
35da6c28aaSamw #include <pthread.h>
36da6c28aaSamw #include <unistd.h>
37da6c28aaSamw #include <arpa/nameser.h>
38da6c28aaSamw #include <resolv.h>
39da6c28aaSamw #include <sys/synch.h>
40da6c28aaSamw #include <string.h>
41da6c28aaSamw #include <strings.h>
42da6c28aaSamw #include <fcntl.h>
43da6c28aaSamw #include <sys/types.h>
44da6c28aaSamw #include <sys/stat.h>
45b89a8333Snatalie li - Sun Microsystems - Irvine United States #include <assert.h>
46a0aa776eSAlan Wright #include <sasl/sasl.h>
47a0aa776eSAlan Wright #include <note.h>
4877191e87SShawn Emery #include <errno.h>
4977191e87SShawn Emery #include <cryptoutil.h>
50*b3700b07SGordon Ross #include <ads/dsgetdc.h>
51da6c28aaSamw
52da6c28aaSamw #include <smbsrv/libsmbns.h>
53da6c28aaSamw #include <smbns_dyndns.h>
54da6c28aaSamw #include <smbns_krb.h>
55da6c28aaSamw
5696a62adaSjoyce mcintosh #define SMB_ADS_AF_UNKNOWN(x) (((x)->ipaddr.a_family != AF_INET) && \
5796a62adaSjoyce mcintosh ((x)->ipaddr.a_family != AF_INET6))
5896a62adaSjoyce mcintosh
5929bd2886SAlan Wright #define SMB_ADS_MAXBUFLEN 100
603db3f65cSamw #define SMB_ADS_DN_MAX 300
613db3f65cSamw #define SMB_ADS_MAXMSGLEN 512
623db3f65cSamw #define SMB_ADS_COMPUTERS_CN "Computers"
633db3f65cSamw #define SMB_ADS_COMPUTER_NUM_ATTR 8
643db3f65cSamw #define SMB_ADS_SHARE_NUM_ATTR 3
653db3f65cSamw #define SMB_ADS_SITE_MAX MAXHOSTNAMELEN
663db3f65cSamw
673db3f65cSamw #define SMB_ADS_MSDCS_SRV_DC_RR "_ldap._tcp.dc._msdcs"
683db3f65cSamw #define SMB_ADS_MSDCS_SRV_SITE_RR "_ldap._tcp.%s._sites.dc._msdcs"
693db3f65cSamw
703db3f65cSamw /*
713db3f65cSamw * domainControllerFunctionality
723db3f65cSamw *
733db3f65cSamw * This rootDSE attribute indicates the functional level of the DC.
743db3f65cSamw */
753db3f65cSamw #define SMB_ADS_ATTR_DCLEVEL "domainControllerFunctionality"
763db3f65cSamw #define SMB_ADS_DCLEVEL_W2K 0
773db3f65cSamw #define SMB_ADS_DCLEVEL_W2K3 2
783db3f65cSamw #define SMB_ADS_DCLEVEL_W2K8 3
79b1352070SAlan Wright #define SMB_ADS_DCLEVEL_W2K8_R2 4
803db3f65cSamw
813db3f65cSamw /*
823db3f65cSamw * msDs-supportedEncryptionTypes (Windows Server 2008 only)
833db3f65cSamw *
843db3f65cSamw * This attribute defines the encryption types supported by the system.
853db3f65cSamw * Encryption Types:
863db3f65cSamw * - DES cbc mode with CRC-32
873db3f65cSamw * - DES cbc mode with RSA-MD5
883db3f65cSamw * - ArcFour with HMAC/md5
893db3f65cSamw * - AES-128
903db3f65cSamw * - AES-256
913db3f65cSamw */
923db3f65cSamw #define SMB_ADS_ATTR_ENCTYPES "msDs-supportedEncryptionTypes"
933db3f65cSamw #define SMB_ADS_ENC_DES_CRC 1
943db3f65cSamw #define SMB_ADS_ENC_DES_MD5 2
953db3f65cSamw #define SMB_ADS_ENC_RC4 4
963db3f65cSamw #define SMB_ADS_ENC_AES128 8
973db3f65cSamw #define SMB_ADS_ENC_AES256 16
983db3f65cSamw
99148c5f43SAlan Wright static krb5_enctype w2k8enctypes[] = {
100148c5f43SAlan Wright ENCTYPE_AES256_CTS_HMAC_SHA1_96,
101148c5f43SAlan Wright ENCTYPE_AES128_CTS_HMAC_SHA1_96,
102148c5f43SAlan Wright ENCTYPE_ARCFOUR_HMAC,
103148c5f43SAlan Wright ENCTYPE_DES_CBC_CRC,
104148c5f43SAlan Wright ENCTYPE_DES_CBC_MD5,
105148c5f43SAlan Wright };
106148c5f43SAlan Wright
107148c5f43SAlan Wright static krb5_enctype pre_w2k8enctypes[] = {
108148c5f43SAlan Wright ENCTYPE_ARCFOUR_HMAC,
109148c5f43SAlan Wright ENCTYPE_DES_CBC_CRC,
110148c5f43SAlan Wright ENCTYPE_DES_CBC_MD5,
111148c5f43SAlan Wright };
112148c5f43SAlan Wright
1133db3f65cSamw #define SMB_ADS_ATTR_SAMACCT "sAMAccountName"
1143db3f65cSamw #define SMB_ADS_ATTR_UPN "userPrincipalName"
1153db3f65cSamw #define SMB_ADS_ATTR_SPN "servicePrincipalName"
1163db3f65cSamw #define SMB_ADS_ATTR_CTL "userAccountControl"
1173db3f65cSamw #define SMB_ADS_ATTR_DNSHOST "dNSHostName"
1183db3f65cSamw #define SMB_ADS_ATTR_KVNO "msDS-KeyVersionNumber"
119c8ec8eeaSjose borrego #define SMB_ADS_ATTR_DN "distinguishedName"
120da6c28aaSamw
121b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
12229bd2886SAlan Wright * UserAccountControl flags: manipulate user account properties.
12329bd2886SAlan Wright *
12429bd2886SAlan Wright * The hexadecimal value of the following property flags are based on MSDN
12529bd2886SAlan Wright * article # 305144.
12629bd2886SAlan Wright */
12729bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_SCRIPT 0x00000001
12829bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_ACCOUNTDISABLE 0x00000002
12929bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_HOMEDIR_REQUIRED 0x00000008
13029bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_LOCKOUT 0x00000010
13129bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_PASSWD_NOTREQD 0x00000020
13229bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_PASSWD_CANT_CHANGE 0x00000040
13329bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_ENCRYPTED_TEXT_PWD_ALLOWED 0x00000080
13429bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_TMP_DUP_ACCT 0x00000100
13529bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_NORMAL_ACCT 0x00000200
13629bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_INTERDOMAIN_TRUST_ACCT 0x00000800
13729bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT 0x00001000
13829bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_SRV_TRUST_ACCT 0x00002000
13929bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD 0x00010000
14029bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_MNS_LOGON_ACCT 0x00020000
14129bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_SMARTCARD_REQUIRED 0x00040000
14229bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION 0x00080000
14329bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_NOT_DELEGATED 0x00100000
14429bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_USE_DES_KEY_ONLY 0x00200000
14529bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_DONT_REQ_PREAUTH 0x00400000
14629bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_PASSWD_EXPIRED 0x00800000
14729bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_TRUSTED_TO_AUTH_FOR_DELEGATION 0x01000000
14829bd2886SAlan Wright
14929bd2886SAlan Wright /*
150b89a8333Snatalie li - Sun Microsystems - Irvine United States * Length of "dc=" prefix.
151b89a8333Snatalie li - Sun Microsystems - Irvine United States */
152b89a8333Snatalie li - Sun Microsystems - Irvine United States #define SMB_ADS_DN_PREFIX_LEN 3
153b89a8333Snatalie li - Sun Microsystems - Irvine United States
1547f667e74Sjose borrego static char *smb_ads_computer_objcls[] = {
1557f667e74Sjose borrego "top", "person", "organizationalPerson",
1567f667e74Sjose borrego "user", "computer", NULL
1577f667e74Sjose borrego };
1587f667e74Sjose borrego
1597f667e74Sjose borrego static char *smb_ads_share_objcls[] = {
1607f667e74Sjose borrego "top", "leaf", "connectionPoint", "volume", NULL
1617f667e74Sjose borrego };
1627f667e74Sjose borrego
163b89a8333Snatalie li - Sun Microsystems - Irvine United States /* Cached ADS server to communicate with */
164b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_info_t *smb_ads_cached_host_info = NULL;
165b89a8333Snatalie li - Sun Microsystems - Irvine United States static mutex_t smb_ads_cached_host_mtx;
166b89a8333Snatalie li - Sun Microsystems - Irvine United States
16729bd2886SAlan Wright /*
16829bd2886SAlan Wright * SMB ADS config cache is maintained to facilitate the detection of
16929bd2886SAlan Wright * changes in configuration that is relevant to AD selection.
17029bd2886SAlan Wright */
17129bd2886SAlan Wright typedef struct smb_ads_config {
17229bd2886SAlan Wright char c_site[SMB_ADS_SITE_MAX];
17329bd2886SAlan Wright mutex_t c_mtx;
17429bd2886SAlan Wright } smb_ads_config_t;
17529bd2886SAlan Wright
17629bd2886SAlan Wright static smb_ads_config_t smb_ads_cfg;
17729bd2886SAlan Wright
178dc20a302Sas200622
179b89a8333Snatalie li - Sun Microsystems - Irvine United States /* attribute/value pair */
180b89a8333Snatalie li - Sun Microsystems - Irvine United States typedef struct smb_ads_avpair {
181b89a8333Snatalie li - Sun Microsystems - Irvine United States char *avp_attr;
182b89a8333Snatalie li - Sun Microsystems - Irvine United States char *avp_val;
183b89a8333Snatalie li - Sun Microsystems - Irvine United States } smb_ads_avpair_t;
184b89a8333Snatalie li - Sun Microsystems - Irvine United States
185b89a8333Snatalie li - Sun Microsystems - Irvine United States /* query status */
186b89a8333Snatalie li - Sun Microsystems - Irvine United States typedef enum smb_ads_qstat {
187b89a8333Snatalie li - Sun Microsystems - Irvine United States SMB_ADS_STAT_ERR = -2,
188b89a8333Snatalie li - Sun Microsystems - Irvine United States SMB_ADS_STAT_DUP,
189b89a8333Snatalie li - Sun Microsystems - Irvine United States SMB_ADS_STAT_NOT_FOUND,
190b89a8333Snatalie li - Sun Microsystems - Irvine United States SMB_ADS_STAT_FOUND
191b89a8333Snatalie li - Sun Microsystems - Irvine United States } smb_ads_qstat_t;
192b89a8333Snatalie li - Sun Microsystems - Irvine United States
19329bd2886SAlan Wright typedef struct smb_ads_host_list {
19429bd2886SAlan Wright int ah_cnt;
19529bd2886SAlan Wright smb_ads_host_info_t *ah_list;
19629bd2886SAlan Wright } smb_ads_host_list_t;
19729bd2886SAlan Wright
198*b3700b07SGordon Ross static int smb_ads_open_main(smb_ads_handle_t **, char *, char *, char *);
199c8ec8eeaSjose borrego static int smb_ads_add_computer(smb_ads_handle_t *, int, char *);
200c8ec8eeaSjose borrego static int smb_ads_modify_computer(smb_ads_handle_t *, int, char *);
201c8ec8eeaSjose borrego static int smb_ads_computer_op(smb_ads_handle_t *, int, int, char *);
202b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_lookup_computer_n_attr(smb_ads_handle_t *,
203b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *, int, char *);
204c8ec8eeaSjose borrego static int smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *, int, char *);
205c8ec8eeaSjose borrego static krb5_kvno smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t *, char *);
206b89a8333Snatalie li - Sun Microsystems - Irvine United States static void smb_ads_free_cached_host(void);
207c8ec8eeaSjose borrego static int smb_ads_alloc_attr(LDAPMod **, int);
208c8ec8eeaSjose borrego static void smb_ads_free_attr(LDAPMod **);
209c8ec8eeaSjose borrego static int smb_ads_get_dc_level(smb_ads_handle_t *);
210b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_find_computer(smb_ads_handle_t *, char *);
211b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_getattr(LDAP *, LDAPMessage *,
212b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *);
213b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_get_qstat(smb_ads_handle_t *, LDAPMessage *,
214b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *);
21529bd2886SAlan Wright static boolean_t smb_ads_is_same_domain(char *, char *);
21629bd2886SAlan Wright static smb_ads_host_info_t *smb_ads_dup_host_info(smb_ads_host_info_t *);
217fe1c642dSBill Krier static char *smb_ads_get_sharedn(const char *, const char *, const char *);
218148c5f43SAlan Wright static krb5_enctype *smb_ads_get_enctypes(int, int *);
219dc20a302Sas200622
220dc20a302Sas200622 /*
2213db3f65cSamw * smb_ads_init
222dc20a302Sas200622 *
22329bd2886SAlan Wright * Initializes the ADS config cache.
224dc20a302Sas200622 */
225dc20a302Sas200622 void
smb_ads_init(void)2263db3f65cSamw smb_ads_init(void)
227dc20a302Sas200622 {
22829bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
229b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_config_getstr(SMB_CI_ADS_SITE,
23029bd2886SAlan Wright smb_ads_cfg.c_site, SMB_ADS_SITE_MAX);
23129bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
232*b3700b07SGordon Ross
233*b3700b07SGordon Ross /* Force -lads to load, for dtrace. */
234*b3700b07SGordon Ross DsFreeDcInfo(NULL);
23529bd2886SAlan Wright }
23629bd2886SAlan Wright
23729bd2886SAlan Wright void
smb_ads_fini(void)23829bd2886SAlan Wright smb_ads_fini(void)
23929bd2886SAlan Wright {
24029bd2886SAlan Wright smb_ads_free_cached_host();
241dc20a302Sas200622 }
242dc20a302Sas200622
243dc20a302Sas200622 /*
2443db3f65cSamw * smb_ads_refresh
245dc20a302Sas200622 *
24629bd2886SAlan Wright * This function will be called when smb/server SMF service is refreshed.
247*b3700b07SGordon Ross * (See smbd_join.c)
248*b3700b07SGordon Ross *
24929bd2886SAlan Wright * Clearing the smb_ads_cached_host_info would allow the next DC
25029bd2886SAlan Wright * discovery process to pick up an AD based on the new AD configuration.
251dc20a302Sas200622 */
252dc20a302Sas200622 void
smb_ads_refresh(boolean_t force_rediscovery)253*b3700b07SGordon Ross smb_ads_refresh(boolean_t force_rediscovery)
254dc20a302Sas200622 {
2553db3f65cSamw char new_site[SMB_ADS_SITE_MAX];
256dc20a302Sas200622
25729bd2886SAlan Wright (void) smb_config_getstr(SMB_CI_ADS_SITE, new_site, SMB_ADS_SITE_MAX);
25829bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
25929bd2886SAlan Wright (void) strlcpy(smb_ads_cfg.c_site, new_site, SMB_ADS_SITE_MAX);
26029bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
26129bd2886SAlan Wright
262b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
263*b3700b07SGordon Ross
264*b3700b07SGordon Ross if (force_rediscovery) {
265*b3700b07SGordon Ross (void) _DsForceRediscovery(NULL, 0);
266*b3700b07SGordon Ross }
267dc20a302Sas200622 }
26829bd2886SAlan Wright
26929bd2886SAlan Wright
270da6c28aaSamw /*
2713db3f65cSamw * smb_ads_build_unc_name
272da6c28aaSamw *
273da6c28aaSamw * Construct the UNC name of the share object in the format of
274da6c28aaSamw * \\hostname.domain\shareUNC
275da6c28aaSamw *
276da6c28aaSamw * Returns 0 on success, -1 on error.
277da6c28aaSamw */
278da6c28aaSamw int
smb_ads_build_unc_name(char * unc_name,int maxlen,const char * hostname,const char * shareUNC)2793db3f65cSamw smb_ads_build_unc_name(char *unc_name, int maxlen,
280da6c28aaSamw const char *hostname, const char *shareUNC)
281da6c28aaSamw {
282dc20a302Sas200622 char my_domain[MAXHOSTNAMELEN];
283da6c28aaSamw
284dc20a302Sas200622 if (smb_getfqdomainname(my_domain, sizeof (my_domain)) != 0)
285da6c28aaSamw return (-1);
286da6c28aaSamw
287da6c28aaSamw (void) snprintf(unc_name, maxlen, "\\\\%s.%s\\%s",
288da6c28aaSamw hostname, my_domain, shareUNC);
289da6c28aaSamw return (0);
290da6c28aaSamw }
291da6c28aaSamw
292da6c28aaSamw /*
29329bd2886SAlan Wright * The cached ADS host is no longer valid if one of the following criteria
29429bd2886SAlan Wright * is satisfied:
295b89a8333Snatalie li - Sun Microsystems - Irvine United States *
29629bd2886SAlan Wright * 1) not in the specified domain
29729bd2886SAlan Wright * 2) not the sought host (if specified)
29829bd2886SAlan Wright * 3) not reachable
29929bd2886SAlan Wright *
30029bd2886SAlan Wright * The caller is responsible for acquiring the smb_ads_cached_host_mtx lock
30129bd2886SAlan Wright * prior to calling this function.
30229bd2886SAlan Wright *
30329bd2886SAlan Wright * Return B_TRUE if the cache host is still valid. Otherwise, return B_FALSE.
304da6c28aaSamw */
30529bd2886SAlan Wright static boolean_t
smb_ads_validate_cache_host(char * domain)306*b3700b07SGordon Ross smb_ads_validate_cache_host(char *domain)
307da6c28aaSamw {
308b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!smb_ads_cached_host_info)
30929bd2886SAlan Wright return (B_FALSE);
31029bd2886SAlan Wright
31129bd2886SAlan Wright if (!smb_ads_is_same_domain(smb_ads_cached_host_info->name, domain))
31229bd2886SAlan Wright return (B_FALSE);
31329bd2886SAlan Wright
314b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_TRUE);
315b89a8333Snatalie li - Sun Microsystems - Irvine United States }
316b89a8333Snatalie li - Sun Microsystems - Irvine United States
317b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
318b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_match_hosts_same_domain
319b89a8333Snatalie li - Sun Microsystems - Irvine United States *
320b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns true, if the cached ADS host is in the same domain as the
321b89a8333Snatalie li - Sun Microsystems - Irvine United States * current (given) domain.
322b89a8333Snatalie li - Sun Microsystems - Irvine United States */
323b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t
smb_ads_is_same_domain(char * cached_host_name,char * current_domain)324b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_is_same_domain(char *cached_host_name, char *current_domain)
325b89a8333Snatalie li - Sun Microsystems - Irvine United States {
326b89a8333Snatalie li - Sun Microsystems - Irvine United States char *cached_host_domain;
327b89a8333Snatalie li - Sun Microsystems - Irvine United States
328b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((cached_host_name == NULL) || (current_domain == NULL))
329b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
330b89a8333Snatalie li - Sun Microsystems - Irvine United States
331b89a8333Snatalie li - Sun Microsystems - Irvine United States cached_host_domain = strchr(cached_host_name, '.');
332b89a8333Snatalie li - Sun Microsystems - Irvine United States if (cached_host_domain == NULL)
333b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
334b89a8333Snatalie li - Sun Microsystems - Irvine United States
335b89a8333Snatalie li - Sun Microsystems - Irvine United States ++cached_host_domain;
336bbf6f00cSJordan Brown if (smb_strcasecmp(cached_host_domain, current_domain, 0))
337b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
338b89a8333Snatalie li - Sun Microsystems - Irvine United States
339b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_TRUE);
340b89a8333Snatalie li - Sun Microsystems - Irvine United States }
341b89a8333Snatalie li - Sun Microsystems - Irvine United States
342b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
343b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_dup_host_info
344b89a8333Snatalie li - Sun Microsystems - Irvine United States *
345b89a8333Snatalie li - Sun Microsystems - Irvine United States * Duplicates the passed smb_ads_host_info_t structure.
346b89a8333Snatalie li - Sun Microsystems - Irvine United States * Caller must free memory allocated by this method.
347b89a8333Snatalie li - Sun Microsystems - Irvine United States *
348b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns a reference to the duplicated smb_ads_host_info_t structure.
349b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns NULL on error.
350b89a8333Snatalie li - Sun Microsystems - Irvine United States */
351b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_info_t *
smb_ads_dup_host_info(smb_ads_host_info_t * ads_host)352b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_dup_host_info(smb_ads_host_info_t *ads_host)
3533db3f65cSamw {
354b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *dup_host;
355b89a8333Snatalie li - Sun Microsystems - Irvine United States
356b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ads_host == NULL)
357b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
358b89a8333Snatalie li - Sun Microsystems - Irvine United States
359b89a8333Snatalie li - Sun Microsystems - Irvine United States dup_host = malloc(sizeof (smb_ads_host_info_t));
360b89a8333Snatalie li - Sun Microsystems - Irvine United States
361b89a8333Snatalie li - Sun Microsystems - Irvine United States if (dup_host != NULL)
362b89a8333Snatalie li - Sun Microsystems - Irvine United States bcopy(ads_host, dup_host, sizeof (smb_ads_host_info_t));
363b89a8333Snatalie li - Sun Microsystems - Irvine United States
364b89a8333Snatalie li - Sun Microsystems - Irvine United States return (dup_host);
365c8ec8eeaSjose borrego }
3663db3f65cSamw
367c8ec8eeaSjose borrego /*
368b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_find_host
369b89a8333Snatalie li - Sun Microsystems - Irvine United States *
37029bd2886SAlan Wright * Finds an ADS host in a given domain.
37129bd2886SAlan Wright *
37229bd2886SAlan Wright * If the cached host is valid, it will be used. Otherwise, a DC will
37329bd2886SAlan Wright * be selected based on the following criteria:
37429bd2886SAlan Wright *
37529bd2886SAlan Wright * 1) pdc (aka preferred DC) configuration
37629bd2886SAlan Wright * 2) AD site configuration - the scope of the DNS lookup will be
37729bd2886SAlan Wright * restricted to the specified site.
37829bd2886SAlan Wright * 3) DC on the same subnet
37929bd2886SAlan Wright * 4) DC with the lowest priority/highest weight
38029bd2886SAlan Wright *
38129bd2886SAlan Wright * The above items are listed in decreasing preference order. The selected
38229bd2886SAlan Wright * DC must be online.
38329bd2886SAlan Wright *
38429bd2886SAlan Wright * If this function is called during domain join, the specified kpasswd server
38529bd2886SAlan Wright * takes precedence over preferred DC, AD site, and so on.
386b89a8333Snatalie li - Sun Microsystems - Irvine United States *
387b89a8333Snatalie li - Sun Microsystems - Irvine United States * Parameters:
38829bd2886SAlan Wright * domain: fully-qualified domain name.
389b89a8333Snatalie li - Sun Microsystems - Irvine United States *
390b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns:
39129bd2886SAlan Wright * A copy of the cached host info is returned. The caller is responsible
39229bd2886SAlan Wright * for deallocating the memory returned by this function.
393b89a8333Snatalie li - Sun Microsystems - Irvine United States */
394b89a8333Snatalie li - Sun Microsystems - Irvine United States /*ARGSUSED*/
395b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *
smb_ads_find_host(char * domain)396*b3700b07SGordon Ross smb_ads_find_host(char *domain)
397b89a8333Snatalie li - Sun Microsystems - Irvine United States {
398*b3700b07SGordon Ross smb_ads_host_info_t *host = NULL;
399*b3700b07SGordon Ross DOMAIN_CONTROLLER_INFO *dci = NULL;
400*b3700b07SGordon Ross struct sockaddr_storage *ss;
401*b3700b07SGordon Ross uint32_t flags = DS_DS_FLAG;
402*b3700b07SGordon Ross uint32_t status;
403*b3700b07SGordon Ross int tries;
404b89a8333Snatalie li - Sun Microsystems - Irvine United States
40529bd2886SAlan Wright (void) mutex_lock(&smb_ads_cached_host_mtx);
406*b3700b07SGordon Ross if (smb_ads_validate_cache_host(domain)) {
40729bd2886SAlan Wright host = smb_ads_dup_host_info(smb_ads_cached_host_info);
40829bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
409b89a8333Snatalie li - Sun Microsystems - Irvine United States return (host);
410b89a8333Snatalie li - Sun Microsystems - Irvine United States }
411b89a8333Snatalie li - Sun Microsystems - Irvine United States
41229bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
413b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
414b89a8333Snatalie li - Sun Microsystems - Irvine United States
415b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
416*b3700b07SGordon Ross * The _real_ DC Locator is over in idmapd.
417*b3700b07SGordon Ross * Door call over there to get it.
418b89a8333Snatalie li - Sun Microsystems - Irvine United States */
419*b3700b07SGordon Ross tries = 15;
420*b3700b07SGordon Ross again:
421*b3700b07SGordon Ross status = _DsGetDcName(
422*b3700b07SGordon Ross NULL, /* ComputerName */
423*b3700b07SGordon Ross domain,
424*b3700b07SGordon Ross NULL, /* DomainGuid */
425*b3700b07SGordon Ross NULL, /* SiteName */
426*b3700b07SGordon Ross flags,
427*b3700b07SGordon Ross &dci);
428*b3700b07SGordon Ross switch (status) {
429*b3700b07SGordon Ross case 0:
430*b3700b07SGordon Ross break;
43129bd2886SAlan Wright /*
432*b3700b07SGordon Ross * We can see these errors when joining a domain, if we race
433*b3700b07SGordon Ross * asking idmap for the DC before it knows the new domain.
43429bd2886SAlan Wright */
435*b3700b07SGordon Ross case NT_STATUS_NO_SUCH_DOMAIN: /* Specified domain unknown */
436*b3700b07SGordon Ross case NT_STATUS_INVALID_SERVER_STATE: /* not in domain mode. */
437*b3700b07SGordon Ross if (--tries > 0) {
438*b3700b07SGordon Ross (void) sleep(1);
439*b3700b07SGordon Ross goto again;
440*b3700b07SGordon Ross }
441*b3700b07SGordon Ross /* FALLTHROUGH */
442*b3700b07SGordon Ross case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND:
443*b3700b07SGordon Ross case NT_STATUS_CANT_WAIT: /* timeout over in idmap */
444*b3700b07SGordon Ross default:
445b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
44629bd2886SAlan Wright }
44729bd2886SAlan Wright
448*b3700b07SGordon Ross host = calloc(1, sizeof (*host));
449*b3700b07SGordon Ross if (host == NULL)
450*b3700b07SGordon Ross goto out;
451*b3700b07SGordon Ross
452*b3700b07SGordon Ross (void) strlcpy(host->name, dci->DomainControllerName, MAXHOSTNAMELEN);
453*b3700b07SGordon Ross ss = (void *)dci->_sockaddr;
454*b3700b07SGordon Ross switch (ss->ss_family) {
455*b3700b07SGordon Ross case AF_INET: {
456*b3700b07SGordon Ross struct sockaddr_in *sin = (void *)ss;
457*b3700b07SGordon Ross host->port = ntohs(sin->sin_port);
458*b3700b07SGordon Ross host->ipaddr.a_family = AF_INET;
459*b3700b07SGordon Ross (void) memcpy(&host->ipaddr.a_ipv4, &sin->sin_addr,
460*b3700b07SGordon Ross sizeof (in_addr_t));
461*b3700b07SGordon Ross break;
462*b3700b07SGordon Ross }
463*b3700b07SGordon Ross case AF_INET6: {
464*b3700b07SGordon Ross struct sockaddr_in6 *sin6 = (void *)ss;
465*b3700b07SGordon Ross host->port = ntohs(sin6->sin6_port);
466*b3700b07SGordon Ross host->ipaddr.a_family = AF_INET6;
467*b3700b07SGordon Ross (void) memcpy(&host->ipaddr.a_ipv6, &sin6->sin6_addr,
468*b3700b07SGordon Ross sizeof (in6_addr_t));
469*b3700b07SGordon Ross break;
470*b3700b07SGordon Ross }
471*b3700b07SGordon Ross default:
472*b3700b07SGordon Ross syslog(LOG_ERR, "no addr for DC %s",
473*b3700b07SGordon Ross dci->DomainControllerName);
474*b3700b07SGordon Ross free(host);
475*b3700b07SGordon Ross host = NULL;
476*b3700b07SGordon Ross goto out;
47729bd2886SAlan Wright }
47829bd2886SAlan Wright
47929bd2886SAlan Wright (void) mutex_lock(&smb_ads_cached_host_mtx);
48029bd2886SAlan Wright if (!smb_ads_cached_host_info)
48129bd2886SAlan Wright smb_ads_cached_host_info = smb_ads_dup_host_info(host);
48229bd2886SAlan Wright host = smb_ads_dup_host_info(smb_ads_cached_host_info);
48329bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
484b89a8333Snatalie li - Sun Microsystems - Irvine United States
485*b3700b07SGordon Ross out:
486*b3700b07SGordon Ross DsFreeDcInfo(dci);
48729bd2886SAlan Wright return (host);
488b89a8333Snatalie li - Sun Microsystems - Irvine United States }
489b89a8333Snatalie li - Sun Microsystems - Irvine United States
490b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
491b89a8333Snatalie li - Sun Microsystems - Irvine United States * Return the number of dots in a string.
492b89a8333Snatalie li - Sun Microsystems - Irvine United States */
493b89a8333Snatalie li - Sun Microsystems - Irvine United States static int
smb_ads_count_dots(const char * s)494b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_count_dots(const char *s)
495b89a8333Snatalie li - Sun Microsystems - Irvine United States {
496b89a8333Snatalie li - Sun Microsystems - Irvine United States int ndots = 0;
497b89a8333Snatalie li - Sun Microsystems - Irvine United States
498b89a8333Snatalie li - Sun Microsystems - Irvine United States while (*s) {
499b89a8333Snatalie li - Sun Microsystems - Irvine United States if (*s++ == '.')
500b89a8333Snatalie li - Sun Microsystems - Irvine United States ndots++;
501b89a8333Snatalie li - Sun Microsystems - Irvine United States }
502b89a8333Snatalie li - Sun Microsystems - Irvine United States
503b89a8333Snatalie li - Sun Microsystems - Irvine United States return (ndots);
504b89a8333Snatalie li - Sun Microsystems - Irvine United States }
505b89a8333Snatalie li - Sun Microsystems - Irvine United States
506b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
507b89a8333Snatalie li - Sun Microsystems - Irvine United States * Convert a domain name in dot notation to distinguished name format,
508b89a8333Snatalie li - Sun Microsystems - Irvine United States * for example: sun.com -> dc=sun,dc=com.
509b89a8333Snatalie li - Sun Microsystems - Irvine United States *
510b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns a pointer to an allocated buffer containing the distinguished
511b89a8333Snatalie li - Sun Microsystems - Irvine United States * name.
512b89a8333Snatalie li - Sun Microsystems - Irvine United States */
513b89a8333Snatalie li - Sun Microsystems - Irvine United States static char *
smb_ads_convert_domain(const char * domain_name)514b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_convert_domain(const char *domain_name)
515b89a8333Snatalie li - Sun Microsystems - Irvine United States {
516b89a8333Snatalie li - Sun Microsystems - Irvine United States const char *s;
517b89a8333Snatalie li - Sun Microsystems - Irvine United States char *dn_name;
518b89a8333Snatalie li - Sun Microsystems - Irvine United States char buf[2];
519b89a8333Snatalie li - Sun Microsystems - Irvine United States int ndots;
520b89a8333Snatalie li - Sun Microsystems - Irvine United States int len;
521b89a8333Snatalie li - Sun Microsystems - Irvine United States
522b89a8333Snatalie li - Sun Microsystems - Irvine United States if (domain_name == NULL || *domain_name == 0)
523b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
524b89a8333Snatalie li - Sun Microsystems - Irvine United States
525b89a8333Snatalie li - Sun Microsystems - Irvine United States ndots = smb_ads_count_dots(domain_name);
526b89a8333Snatalie li - Sun Microsystems - Irvine United States ++ndots;
527b89a8333Snatalie li - Sun Microsystems - Irvine United States len = strlen(domain_name) + (ndots * SMB_ADS_DN_PREFIX_LEN) + 1;
528b89a8333Snatalie li - Sun Microsystems - Irvine United States
529b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((dn_name = malloc(len)) == NULL)
530b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
531b89a8333Snatalie li - Sun Microsystems - Irvine United States
532b89a8333Snatalie li - Sun Microsystems - Irvine United States bzero(dn_name, len);
533b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcpy(dn_name, "dc=", len);
534b89a8333Snatalie li - Sun Microsystems - Irvine United States
535b89a8333Snatalie li - Sun Microsystems - Irvine United States buf[1] = '\0';
536b89a8333Snatalie li - Sun Microsystems - Irvine United States s = domain_name;
537b89a8333Snatalie li - Sun Microsystems - Irvine United States
538b89a8333Snatalie li - Sun Microsystems - Irvine United States while (*s) {
539b89a8333Snatalie li - Sun Microsystems - Irvine United States if (*s == '.') {
540b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(dn_name, ",dc=", len);
541b89a8333Snatalie li - Sun Microsystems - Irvine United States } else {
542b89a8333Snatalie li - Sun Microsystems - Irvine United States buf[0] = *s;
543b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(dn_name, buf, len);
544b89a8333Snatalie li - Sun Microsystems - Irvine United States }
545b89a8333Snatalie li - Sun Microsystems - Irvine United States ++s;
546b89a8333Snatalie li - Sun Microsystems - Irvine United States }
547b89a8333Snatalie li - Sun Microsystems - Irvine United States
548b89a8333Snatalie li - Sun Microsystems - Irvine United States return (dn_name);
549b89a8333Snatalie li - Sun Microsystems - Irvine United States }
550b89a8333Snatalie li - Sun Microsystems - Irvine United States
551b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
552b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_free_cached_host
553b89a8333Snatalie li - Sun Microsystems - Irvine United States *
554b89a8333Snatalie li - Sun Microsystems - Irvine United States * Free the memory use by the global smb_ads_cached_host_info & set it to NULL.
555b89a8333Snatalie li - Sun Microsystems - Irvine United States */
556b89a8333Snatalie li - Sun Microsystems - Irvine United States static void
smb_ads_free_cached_host(void)557b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host(void)
558b89a8333Snatalie li - Sun Microsystems - Irvine United States {
559b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) mutex_lock(&smb_ads_cached_host_mtx);
560b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_cached_host_info) {
561b89a8333Snatalie li - Sun Microsystems - Irvine United States free(smb_ads_cached_host_info);
562b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_cached_host_info = NULL;
563b89a8333Snatalie li - Sun Microsystems - Irvine United States }
564b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) mutex_unlock(&smb_ads_cached_host_mtx);
565da6c28aaSamw }
566da6c28aaSamw
567da6c28aaSamw /*
5683db3f65cSamw * smb_ads_open
56955bf511dSas200622 * Open a LDAP connection to an ADS server if the system is in domain mode.
57055bf511dSas200622 * Acquire both Kerberos TGT and LDAP service tickets for the host principal.
57155bf511dSas200622 *
57255bf511dSas200622 * This function should only be called after the system is successfully joined
57355bf511dSas200622 * to a domain.
57455bf511dSas200622 */
5753db3f65cSamw smb_ads_handle_t *
smb_ads_open(void)5763db3f65cSamw smb_ads_open(void)
57755bf511dSas200622 {
578dc20a302Sas200622 char domain[MAXHOSTNAMELEN];
579*b3700b07SGordon Ross smb_ads_handle_t *h;
580*b3700b07SGordon Ross smb_ads_status_t err;
58155bf511dSas200622
582dc20a302Sas200622 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
58355bf511dSas200622 return (NULL);
58455bf511dSas200622
585dc20a302Sas200622 if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0)
586dc20a302Sas200622 return (NULL);
587dc20a302Sas200622
588*b3700b07SGordon Ross err = smb_ads_open_main(&h, domain, NULL, NULL);
589*b3700b07SGordon Ross if (err != 0) {
590*b3700b07SGordon Ross smb_ads_log_errmsg(err);
591*b3700b07SGordon Ross return (NULL);
592*b3700b07SGordon Ross }
593*b3700b07SGordon Ross
594*b3700b07SGordon Ross return (h);
59555bf511dSas200622 }
59655bf511dSas200622
597a0aa776eSAlan Wright static int
smb_ads_saslcallback(LDAP * ld,unsigned flags,void * defaults,void * prompts)598a0aa776eSAlan Wright smb_ads_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts)
599a0aa776eSAlan Wright {
600a0aa776eSAlan Wright NOTE(ARGUNUSED(ld, defaults));
601a0aa776eSAlan Wright sasl_interact_t *interact;
602a0aa776eSAlan Wright
603a0aa776eSAlan Wright if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
604a0aa776eSAlan Wright return (LDAP_PARAM_ERROR);
605a0aa776eSAlan Wright
606a0aa776eSAlan Wright /* There should be no extra arguemnts for SASL/GSSAPI authentication */
607a0aa776eSAlan Wright for (interact = prompts; interact->id != SASL_CB_LIST_END;
608a0aa776eSAlan Wright interact++) {
609a0aa776eSAlan Wright interact->result = NULL;
610a0aa776eSAlan Wright interact->len = 0;
611a0aa776eSAlan Wright }
612a0aa776eSAlan Wright return (LDAP_SUCCESS);
613a0aa776eSAlan Wright }
614a0aa776eSAlan Wright
61555bf511dSas200622 /*
6163db3f65cSamw * smb_ads_open_main
617da6c28aaSamw * Open a LDAP connection to an ADS server.
61855bf511dSas200622 * If ADS is enabled and the administrative username, password, and
619da6c28aaSamw * ADS domain are defined then query DNS to find an ADS server if this is the
620da6c28aaSamw * very first call to this routine. After an ADS server is found then this
621da6c28aaSamw * server will be used everytime this routine is called until the system is
622da6c28aaSamw * rebooted or the ADS server becomes unavailable then an ADS server will
6233db3f65cSamw * be queried again. After the connection is made then an ADS handle
624da6c28aaSamw * is created to be returned.
625da6c28aaSamw *
626da6c28aaSamw * After the LDAP connection, the LDAP version will be set to 3 using
627da6c28aaSamw * ldap_set_option().
628da6c28aaSamw *
629a0aa776eSAlan Wright * The LDAP connection is bound before the ADS handle is returned.
630da6c28aaSamw * Parameters:
631dc20a302Sas200622 * domain - fully-qualified domain name
632dc20a302Sas200622 * user - the user account for whom the Kerberos TGT ticket and ADS
633dc20a302Sas200622 * service tickets are acquired.
634dc20a302Sas200622 * password - password of the specified user
635dc20a302Sas200622 *
636da6c28aaSamw * Returns:
637da6c28aaSamw * NULL : can't connect to ADS server or other errors
6383db3f65cSamw * smb_ads_handle_t* : handle to ADS server
639da6c28aaSamw */
640*b3700b07SGordon Ross static int
smb_ads_open_main(smb_ads_handle_t ** hp,char * domain,char * user,char * password)641*b3700b07SGordon Ross smb_ads_open_main(smb_ads_handle_t **hp, char *domain, char *user,
642*b3700b07SGordon Ross char *password)
643da6c28aaSamw {
6443db3f65cSamw smb_ads_handle_t *ah;
645da6c28aaSamw LDAP *ld;
646b89a8333Snatalie li - Sun Microsystems - Irvine United States int version = 3;
6473db3f65cSamw smb_ads_host_info_t *ads_host = NULL;
648*b3700b07SGordon Ross int err, rc;
649*b3700b07SGordon Ross
650*b3700b07SGordon Ross *hp = NULL;
651a0aa776eSAlan Wright
652a0aa776eSAlan Wright if (user != NULL) {
653*b3700b07SGordon Ross err = smb_kinit(domain, user, password);
654*b3700b07SGordon Ross if (err != 0)
655*b3700b07SGordon Ross return (err);
656a0aa776eSAlan Wright user = NULL;
657a0aa776eSAlan Wright password = NULL;
658a0aa776eSAlan Wright }
659da6c28aaSamw
660*b3700b07SGordon Ross ads_host = smb_ads_find_host(domain);
661b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ads_host == NULL)
662*b3700b07SGordon Ross return (SMB_ADS_CANT_LOCATE_DC);
663b89a8333Snatalie li - Sun Microsystems - Irvine United States
6643db3f65cSamw ah = (smb_ads_handle_t *)malloc(sizeof (smb_ads_handle_t));
66529bd2886SAlan Wright if (ah == NULL) {
66629bd2886SAlan Wright free(ads_host);
667*b3700b07SGordon Ross return (ENOMEM);
66829bd2886SAlan Wright }
66929bd2886SAlan Wright
6703db3f65cSamw (void) memset(ah, 0, sizeof (smb_ads_handle_t));
671da6c28aaSamw
6727f667e74Sjose borrego if ((ld = ldap_init(ads_host->name, ads_host->port)) == NULL) {
673*b3700b07SGordon Ross syslog(LOG_ERR, "smbns: ldap_init failed");
674b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
675da6c28aaSamw free(ah);
67629bd2886SAlan Wright free(ads_host);
677*b3700b07SGordon Ross return (SMB_ADS_LDAP_INIT);
678da6c28aaSamw }
679da6c28aaSamw
680da6c28aaSamw if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version)
681da6c28aaSamw != LDAP_SUCCESS) {
682b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
683da6c28aaSamw free(ah);
68429bd2886SAlan Wright free(ads_host);
685da6c28aaSamw (void) ldap_unbind(ld);
686*b3700b07SGordon Ross return (SMB_ADS_LDAP_SETOPT);
687da6c28aaSamw }
688da6c28aaSamw
689c8ec8eeaSjose borrego (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
690da6c28aaSamw ah->ld = ld;
691da6c28aaSamw ah->domain = strdup(domain);
692da6c28aaSamw
69355bf511dSas200622 if (ah->domain == NULL) {
6943db3f65cSamw smb_ads_close(ah);
69529bd2886SAlan Wright free(ads_host);
696*b3700b07SGordon Ross return (SMB_ADS_LDAP_SETOPT);
697da6c28aaSamw }
698da6c28aaSamw
6999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
7009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * ah->domain is often used for generating service principal name.
7019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Convert it to lower case for RFC 4120 section 6.2.1 conformance.
7029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
7039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(ah->domain);
7043db3f65cSamw ah->domain_dn = smb_ads_convert_domain(domain);
705da6c28aaSamw if (ah->domain_dn == NULL) {
7063db3f65cSamw smb_ads_close(ah);
70729bd2886SAlan Wright free(ads_host);
708*b3700b07SGordon Ross return (SMB_ADS_LDAP_SET_DOM);
709da6c28aaSamw }
710da6c28aaSamw
711da6c28aaSamw ah->hostname = strdup(ads_host->name);
712da6c28aaSamw if (ah->hostname == NULL) {
7133db3f65cSamw smb_ads_close(ah);
71429bd2886SAlan Wright free(ads_host);
715*b3700b07SGordon Ross return (ENOMEM);
716da6c28aaSamw }
71729bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
71829bd2886SAlan Wright if (*smb_ads_cfg.c_site != '\0') {
71929bd2886SAlan Wright if ((ah->site = strdup(smb_ads_cfg.c_site)) == NULL) {
7203db3f65cSamw smb_ads_close(ah);
72129bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
72229bd2886SAlan Wright free(ads_host);
723*b3700b07SGordon Ross return (ENOMEM);
724da6c28aaSamw }
725da6c28aaSamw } else {
726da6c28aaSamw ah->site = NULL;
727da6c28aaSamw }
72829bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
729da6c28aaSamw
730a0aa776eSAlan Wright rc = ldap_sasl_interactive_bind_s(ah->ld, "", "GSSAPI", NULL, NULL,
731a0aa776eSAlan Wright LDAP_SASL_INTERACTIVE, &smb_ads_saslcallback, NULL);
732a0aa776eSAlan Wright if (rc != LDAP_SUCCESS) {
733*b3700b07SGordon Ross syslog(LOG_ERR, "smbns: ldap_sasl_..._bind_s failed (%s)",
734a0aa776eSAlan Wright ldap_err2string(rc));
7353db3f65cSamw smb_ads_close(ah);
73629bd2886SAlan Wright free(ads_host);
737*b3700b07SGordon Ross return (SMB_ADS_LDAP_SASL_BIND);
738da6c28aaSamw }
739da6c28aaSamw
74029bd2886SAlan Wright free(ads_host);
741*b3700b07SGordon Ross *hp = ah;
742*b3700b07SGordon Ross
743*b3700b07SGordon Ross return (SMB_ADS_SUCCESS);
744da6c28aaSamw }
745da6c28aaSamw
746da6c28aaSamw /*
7473db3f65cSamw * smb_ads_close
748da6c28aaSamw * Close connection to ADS server and free memory allocated for ADS handle.
749da6c28aaSamw * LDAP unbind is called here.
750da6c28aaSamw * Parameters:
751da6c28aaSamw * ah: handle to ADS server
752da6c28aaSamw * Returns:
753da6c28aaSamw * void
754da6c28aaSamw */
755da6c28aaSamw void
smb_ads_close(smb_ads_handle_t * ah)7563db3f65cSamw smb_ads_close(smb_ads_handle_t *ah)
757da6c28aaSamw {
758da6c28aaSamw if (ah == NULL)
759da6c28aaSamw return;
760da6c28aaSamw /* close and free connection resources */
761da6c28aaSamw if (ah->ld)
762da6c28aaSamw (void) ldap_unbind(ah->ld);
763da6c28aaSamw
764da6c28aaSamw free(ah->domain);
765da6c28aaSamw free(ah->domain_dn);
766da6c28aaSamw free(ah->hostname);
767da6c28aaSamw free(ah->site);
768da6c28aaSamw free(ah);
769da6c28aaSamw }
770da6c28aaSamw
771da6c28aaSamw /*
7723db3f65cSamw * smb_ads_alloc_attr
7736537f381Sas200622 *
7746537f381Sas200622 * Since the attrs is a null-terminated array, all elements
7756537f381Sas200622 * in the array (except the last one) will point to allocated
7766537f381Sas200622 * memory.
7776537f381Sas200622 */
7786537f381Sas200622 static int
smb_ads_alloc_attr(LDAPMod * attrs[],int num)7793db3f65cSamw smb_ads_alloc_attr(LDAPMod *attrs[], int num)
7806537f381Sas200622 {
7816537f381Sas200622 int i;
7826537f381Sas200622
7836537f381Sas200622 bzero(attrs, num * sizeof (LDAPMod *));
7846537f381Sas200622 for (i = 0; i < (num - 1); i++) {
7856537f381Sas200622 attrs[i] = (LDAPMod *)malloc(sizeof (LDAPMod));
7866537f381Sas200622 if (attrs[i] == NULL) {
7873db3f65cSamw smb_ads_free_attr(attrs);
7886537f381Sas200622 return (-1);
7896537f381Sas200622 }
7906537f381Sas200622 }
7916537f381Sas200622
7926537f381Sas200622 return (0);
7936537f381Sas200622 }
7946537f381Sas200622
7956537f381Sas200622 /*
7963db3f65cSamw * smb_ads_free_attr
797da6c28aaSamw * Free memory allocated when publishing a share.
798da6c28aaSamw * Parameters:
79955bf511dSas200622 * attrs: an array of LDAPMod pointers
800da6c28aaSamw * Returns:
801da6c28aaSamw * None
802da6c28aaSamw */
803da6c28aaSamw static void
smb_ads_free_attr(LDAPMod * attrs[])8043db3f65cSamw smb_ads_free_attr(LDAPMod *attrs[])
805da6c28aaSamw {
806da6c28aaSamw int i;
80755bf511dSas200622 for (i = 0; attrs[i]; i++) {
80855bf511dSas200622 free(attrs[i]);
809da6c28aaSamw }
810da6c28aaSamw }
811da6c28aaSamw
812da6c28aaSamw /*
813fe1c642dSBill Krier * Returns share DN in an allocated buffer. The format of the DN is
814fe1c642dSBill Krier * cn=<sharename>,<container RDNs>,<domain DN>
815fe1c642dSBill Krier *
816fe1c642dSBill Krier * If the domain DN is not included in the container parameter,
817fe1c642dSBill Krier * then it will be appended to create the share DN.
818fe1c642dSBill Krier *
819fe1c642dSBill Krier * The caller must free the allocated buffer.
820fe1c642dSBill Krier */
821fe1c642dSBill Krier static char *
smb_ads_get_sharedn(const char * sharename,const char * container,const char * domain_dn)822fe1c642dSBill Krier smb_ads_get_sharedn(const char *sharename, const char *container,
823fe1c642dSBill Krier const char *domain_dn)
824fe1c642dSBill Krier {
825fe1c642dSBill Krier char *share_dn;
826fe1c642dSBill Krier int rc, offset, container_len, domain_len;
827fe1c642dSBill Krier boolean_t append_domain = B_TRUE;
828fe1c642dSBill Krier
829fe1c642dSBill Krier container_len = strlen(container);
830fe1c642dSBill Krier domain_len = strlen(domain_dn);
831fe1c642dSBill Krier
832fe1c642dSBill Krier if (container_len >= domain_len) {
833fe1c642dSBill Krier
834fe1c642dSBill Krier /* offset to last domain_len characters */
835fe1c642dSBill Krier offset = container_len - domain_len;
836fe1c642dSBill Krier
837fe1c642dSBill Krier if (smb_strcasecmp(container + offset,
838fe1c642dSBill Krier domain_dn, domain_len) == 0)
839fe1c642dSBill Krier append_domain = B_FALSE;
840fe1c642dSBill Krier }
841fe1c642dSBill Krier
842fe1c642dSBill Krier if (append_domain)
843fe1c642dSBill Krier rc = asprintf(&share_dn, "cn=%s,%s,%s", sharename,
844fe1c642dSBill Krier container, domain_dn);
845fe1c642dSBill Krier else
846fe1c642dSBill Krier rc = asprintf(&share_dn, "cn=%s,%s", sharename,
847fe1c642dSBill Krier container);
848fe1c642dSBill Krier
849fe1c642dSBill Krier return ((rc == -1) ? NULL : share_dn);
850fe1c642dSBill Krier }
851fe1c642dSBill Krier
852fe1c642dSBill Krier /*
8533db3f65cSamw * smb_ads_add_share
8543db3f65cSamw * Call by smb_ads_publish_share to create share object in ADS.
855da6c28aaSamw * This routine specifies the attributes of an ADS LDAP share object. The first
856da6c28aaSamw * attribute and values define the type of ADS object, the share object. The
857da6c28aaSamw * second attribute and value define the UNC of the share data for the share
858da6c28aaSamw * object. The LDAP synchronous add command is used to add the object into ADS.
859da6c28aaSamw * The container location to add the object needs to specified.
860da6c28aaSamw * Parameters:
861da6c28aaSamw * ah : handle to ADS server
862da6c28aaSamw * adsShareName: name of share object to be created in ADS
863da6c28aaSamw * shareUNC : share name on NetForce
864da6c28aaSamw * adsContainer: location in ADS to create share object
865da6c28aaSamw *
866da6c28aaSamw * Returns:
867da6c28aaSamw * -1 : error
868da6c28aaSamw * 0 : success
869da6c28aaSamw */
870da6c28aaSamw int
smb_ads_add_share(smb_ads_handle_t * ah,const char * adsShareName,const char * unc_name,const char * adsContainer)8713db3f65cSamw smb_ads_add_share(smb_ads_handle_t *ah, const char *adsShareName,
872da6c28aaSamw const char *unc_name, const char *adsContainer)
873da6c28aaSamw {
8743db3f65cSamw LDAPMod *attrs[SMB_ADS_SHARE_NUM_ATTR];
87555bf511dSas200622 int j = 0;
876da6c28aaSamw char *share_dn;
877fe1c642dSBill Krier int ret;
8787f667e74Sjose borrego char *unc_names[] = {(char *)unc_name, NULL};
879da6c28aaSamw
880fe1c642dSBill Krier if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
881fe1c642dSBill Krier ah->domain_dn)) == NULL)
882da6c28aaSamw return (-1);
883da6c28aaSamw
8843db3f65cSamw if (smb_ads_alloc_attr(attrs, SMB_ADS_SHARE_NUM_ATTR) != 0) {
88555bf511dSas200622 free(share_dn);
88655bf511dSas200622 return (-1);
88755bf511dSas200622 }
88855bf511dSas200622
88955bf511dSas200622 attrs[j]->mod_op = LDAP_MOD_ADD;
89055bf511dSas200622 attrs[j]->mod_type = "objectClass";
8917f667e74Sjose borrego attrs[j]->mod_values = smb_ads_share_objcls;
892da6c28aaSamw
89355bf511dSas200622 attrs[++j]->mod_op = LDAP_MOD_ADD;
89455bf511dSas200622 attrs[j]->mod_type = "uNCName";
8957f667e74Sjose borrego attrs[j]->mod_values = unc_names;
896da6c28aaSamw
89755bf511dSas200622 if ((ret = ldap_add_s(ah->ld, share_dn, attrs)) != LDAP_SUCCESS) {
8989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (ret == LDAP_NO_SUCH_OBJECT) {
8999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States syslog(LOG_ERR, "Failed to publish share %s in" \
9009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States " AD. Container does not exist: %s.\n",
9019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States adsShareName, share_dn);
9029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
9039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } else {
9049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States syslog(LOG_ERR, "Failed to publish share %s in" \
9059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States " AD: %s (%s).\n", adsShareName, share_dn,
9069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ldap_err2string(ret));
9079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
9083db3f65cSamw smb_ads_free_attr(attrs);
909da6c28aaSamw free(share_dn);
910da6c28aaSamw return (ret);
911da6c28aaSamw }
912da6c28aaSamw free(share_dn);
9133db3f65cSamw smb_ads_free_attr(attrs);
914da6c28aaSamw
915da6c28aaSamw return (0);
916da6c28aaSamw }
917da6c28aaSamw
918da6c28aaSamw /*
9193db3f65cSamw * smb_ads_del_share
9203db3f65cSamw * Call by smb_ads_remove_share to remove share object from ADS. The container
921da6c28aaSamw * location to remove the object needs to specified. The LDAP synchronous
922da6c28aaSamw * delete command is used.
923da6c28aaSamw * Parameters:
924da6c28aaSamw * ah : handle to ADS server
925da6c28aaSamw * adsShareName: name of share object in ADS to be removed
926da6c28aaSamw * adsContainer: location of share object in ADS
927da6c28aaSamw * Returns:
928da6c28aaSamw * -1 : error
929da6c28aaSamw * 0 : success
930da6c28aaSamw */
931da6c28aaSamw static int
smb_ads_del_share(smb_ads_handle_t * ah,const char * adsShareName,const char * adsContainer)9323db3f65cSamw smb_ads_del_share(smb_ads_handle_t *ah, const char *adsShareName,
933da6c28aaSamw const char *adsContainer)
934da6c28aaSamw {
935b89a8333Snatalie li - Sun Microsystems - Irvine United States char *share_dn;
936fe1c642dSBill Krier int ret;
937da6c28aaSamw
938fe1c642dSBill Krier if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
939fe1c642dSBill Krier ah->domain_dn)) == NULL)
940da6c28aaSamw return (-1);
941da6c28aaSamw
942da6c28aaSamw if ((ret = ldap_delete_s(ah->ld, share_dn)) != LDAP_SUCCESS) {
943fc724630SAlan Wright smb_tracef("ldap_delete: %s", ldap_err2string(ret));
944da6c28aaSamw free(share_dn);
945da6c28aaSamw return (-1);
946da6c28aaSamw }
947da6c28aaSamw free(share_dn);
948da6c28aaSamw
949da6c28aaSamw return (0);
950da6c28aaSamw }
951da6c28aaSamw
952da6c28aaSamw
953da6c28aaSamw /*
9543db3f65cSamw * smb_ads_escape_search_filter_chars
955da6c28aaSamw *
956da6c28aaSamw * This routine will escape the special characters found in a string
957da6c28aaSamw * that will later be passed to the ldap search filter.
958da6c28aaSamw *
959da6c28aaSamw * RFC 1960 - A String Representation of LDAP Search Filters
960da6c28aaSamw * 3. String Search Filter Definition
961da6c28aaSamw * If a value must contain one of the characters '*' OR '(' OR ')',
962da6c28aaSamw * these characters
963da6c28aaSamw * should be escaped by preceding them with the backslash '\' character.
964da6c28aaSamw *
965da6c28aaSamw * RFC 2252 - LDAP Attribute Syntax Definitions
966da6c28aaSamw * a backslash quoting mechanism is used to escape
967da6c28aaSamw * the following separator symbol character (such as "'", "$" or "#") if
968da6c28aaSamw * it should occur in that string.
969da6c28aaSamw */
970da6c28aaSamw static int
smb_ads_escape_search_filter_chars(const char * src,char * dst)9713db3f65cSamw smb_ads_escape_search_filter_chars(const char *src, char *dst)
972da6c28aaSamw {
9733db3f65cSamw int avail = SMB_ADS_MAXBUFLEN - 1; /* reserve a space for NULL char */
974da6c28aaSamw
975da6c28aaSamw if (src == NULL || dst == NULL)
976da6c28aaSamw return (-1);
977da6c28aaSamw
978da6c28aaSamw while (*src) {
979da6c28aaSamw if (!avail) {
980da6c28aaSamw *dst = 0;
981da6c28aaSamw return (-1);
982da6c28aaSamw }
983da6c28aaSamw
984da6c28aaSamw switch (*src) {
985da6c28aaSamw case '\\':
986da6c28aaSamw case '\'':
987da6c28aaSamw case '$':
988da6c28aaSamw case '#':
989da6c28aaSamw case '*':
990da6c28aaSamw case '(':
991da6c28aaSamw case ')':
992da6c28aaSamw *dst++ = '\\';
993da6c28aaSamw avail--;
994da6c28aaSamw /* fall through */
995da6c28aaSamw
996da6c28aaSamw default:
997da6c28aaSamw *dst++ = *src++;
998da6c28aaSamw avail--;
999da6c28aaSamw }
1000da6c28aaSamw }
1001da6c28aaSamw
1002da6c28aaSamw *dst = 0;
1003da6c28aaSamw
1004da6c28aaSamw return (0);
1005da6c28aaSamw }
1006da6c28aaSamw
1007da6c28aaSamw /*
10083db3f65cSamw * smb_ads_lookup_share
1009da6c28aaSamw * The search filter is set to search for a specific share name in the
1010da6c28aaSamw * specified ADS container. The LDSAP synchronous search command is used.
1011da6c28aaSamw * Parameters:
1012da6c28aaSamw * ah : handle to ADS server
1013da6c28aaSamw * adsShareName: name of share object in ADS to be searched
1014da6c28aaSamw * adsContainer: location of share object in ADS
1015da6c28aaSamw * Returns:
1016da6c28aaSamw * -1 : error
1017da6c28aaSamw * 0 : not found
1018da6c28aaSamw * 1 : found
1019da6c28aaSamw */
1020da6c28aaSamw int
smb_ads_lookup_share(smb_ads_handle_t * ah,const char * adsShareName,const char * adsContainer,char * unc_name)10213db3f65cSamw smb_ads_lookup_share(smb_ads_handle_t *ah, const char *adsShareName,
1022da6c28aaSamw const char *adsContainer, char *unc_name)
1023da6c28aaSamw {
10243db3f65cSamw char *attrs[4], filter[SMB_ADS_MAXBUFLEN];
1025da6c28aaSamw char *share_dn;
1026fe1c642dSBill Krier int ret;
1027da6c28aaSamw LDAPMessage *res;
10283db3f65cSamw char tmpbuf[SMB_ADS_MAXBUFLEN];
1029da6c28aaSamw
1030da6c28aaSamw if (adsShareName == NULL || adsContainer == NULL)
1031da6c28aaSamw return (-1);
1032da6c28aaSamw
1033fe1c642dSBill Krier if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
1034fe1c642dSBill Krier ah->domain_dn)) == NULL)
1035da6c28aaSamw return (-1);
1036da6c28aaSamw
1037da6c28aaSamw res = NULL;
1038da6c28aaSamw attrs[0] = "cn";
1039da6c28aaSamw attrs[1] = "objectClass";
1040da6c28aaSamw attrs[2] = "uNCName";
1041da6c28aaSamw attrs[3] = NULL;
1042da6c28aaSamw
10433db3f65cSamw if (smb_ads_escape_search_filter_chars(unc_name, tmpbuf) != 0) {
1044da6c28aaSamw free(share_dn);
1045da6c28aaSamw return (-1);
1046da6c28aaSamw }
1047da6c28aaSamw
1048da6c28aaSamw (void) snprintf(filter, sizeof (filter),
1049da6c28aaSamw "(&(objectClass=volume)(uNCName=%s))", tmpbuf);
1050da6c28aaSamw
1051da6c28aaSamw if ((ret = ldap_search_s(ah->ld, share_dn,
1052da6c28aaSamw LDAP_SCOPE_BASE, filter, attrs, 0, &res)) != LDAP_SUCCESS) {
1053b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ret != LDAP_NO_SUCH_OBJECT)
1054fc724630SAlan Wright smb_tracef("%s: ldap_search: %s", share_dn,
1055fc724630SAlan Wright ldap_err2string(ret));
1056b89a8333Snatalie li - Sun Microsystems - Irvine United States
1057da6c28aaSamw (void) ldap_msgfree(res);
1058da6c28aaSamw free(share_dn);
1059da6c28aaSamw return (0);
1060da6c28aaSamw }
1061da6c28aaSamw
1062da6c28aaSamw (void) free(share_dn);
1063da6c28aaSamw
1064da6c28aaSamw /* no match is found */
1065da6c28aaSamw if (ldap_count_entries(ah->ld, res) == 0) {
1066da6c28aaSamw (void) ldap_msgfree(res);
1067da6c28aaSamw return (0);
1068da6c28aaSamw }
1069da6c28aaSamw
1070da6c28aaSamw /* free the search results */
1071da6c28aaSamw (void) ldap_msgfree(res);
1072da6c28aaSamw
1073da6c28aaSamw return (1);
1074da6c28aaSamw }
1075da6c28aaSamw
1076da6c28aaSamw /*
10773db3f65cSamw * smb_ads_publish_share
1078da6c28aaSamw * Publish share into ADS. If a share name already exist in ADS in the same
1079da6c28aaSamw * container then the existing share object is removed before adding the new
1080da6c28aaSamw * share object.
1081da6c28aaSamw * Parameters:
10823db3f65cSamw * ah : handle return from smb_ads_open
1083da6c28aaSamw * adsShareName: name of share to be added to ADS directory
1084da6c28aaSamw * shareUNC : name of share on client, can be NULL to use the same name
1085da6c28aaSamw * as adsShareName
1086da6c28aaSamw * adsContainer: location for share to be added in ADS directory, ie
1087da6c28aaSamw * ou=share_folder
1088da6c28aaSamw * uncType : use UNC_HOSTNAME to use hostname for UNC, use UNC_HOSTADDR
1089da6c28aaSamw * to use host ip addr for UNC.
1090da6c28aaSamw * Returns:
1091da6c28aaSamw * -1 : error
1092da6c28aaSamw * 0 : success
1093da6c28aaSamw */
1094da6c28aaSamw int
smb_ads_publish_share(smb_ads_handle_t * ah,const char * adsShareName,const char * shareUNC,const char * adsContainer,const char * hostname)10953db3f65cSamw smb_ads_publish_share(smb_ads_handle_t *ah, const char *adsShareName,
1096da6c28aaSamw const char *shareUNC, const char *adsContainer, const char *hostname)
1097da6c28aaSamw {
1098da6c28aaSamw int ret;
10993db3f65cSamw char unc_name[SMB_ADS_MAXBUFLEN];
1100da6c28aaSamw
1101da6c28aaSamw if (adsShareName == NULL || adsContainer == NULL)
1102da6c28aaSamw return (-1);
1103da6c28aaSamw
1104da6c28aaSamw if (shareUNC == 0 || *shareUNC == 0)
1105da6c28aaSamw shareUNC = adsShareName;
1106da6c28aaSamw
11073db3f65cSamw if (smb_ads_build_unc_name(unc_name, sizeof (unc_name),
1108b89a8333Snatalie li - Sun Microsystems - Irvine United States hostname, shareUNC) < 0)
1109da6c28aaSamw return (-1);
1110da6c28aaSamw
11113db3f65cSamw ret = smb_ads_lookup_share(ah, adsShareName, adsContainer, unc_name);
1112da6c28aaSamw
1113da6c28aaSamw switch (ret) {
1114da6c28aaSamw case 1:
11153db3f65cSamw (void) smb_ads_del_share(ah, adsShareName, adsContainer);
11163db3f65cSamw ret = smb_ads_add_share(ah, adsShareName, unc_name,
11173db3f65cSamw adsContainer);
1118da6c28aaSamw break;
1119da6c28aaSamw
1120da6c28aaSamw case 0:
11213db3f65cSamw ret = smb_ads_add_share(ah, adsShareName, unc_name,
11223db3f65cSamw adsContainer);
1123b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ret == LDAP_ALREADY_EXISTS)
1124da6c28aaSamw ret = -1;
1125b89a8333Snatalie li - Sun Microsystems - Irvine United States
1126da6c28aaSamw break;
1127da6c28aaSamw
1128da6c28aaSamw case -1:
1129da6c28aaSamw default:
1130da6c28aaSamw /* return with error code */
1131da6c28aaSamw ret = -1;
1132da6c28aaSamw }
1133da6c28aaSamw
1134da6c28aaSamw return (ret);
1135da6c28aaSamw }
1136da6c28aaSamw
1137da6c28aaSamw /*
11383db3f65cSamw * smb_ads_remove_share
1139da6c28aaSamw * Remove share from ADS. A search is done first before explicitly removing
1140da6c28aaSamw * the share.
1141da6c28aaSamw * Parameters:
11423db3f65cSamw * ah : handle return from smb_ads_open
1143da6c28aaSamw * adsShareName: name of share to be removed from ADS directory
1144da6c28aaSamw * adsContainer: location for share to be removed from ADS directory, ie
1145da6c28aaSamw * ou=share_folder
1146da6c28aaSamw * Returns:
1147da6c28aaSamw * -1 : error
1148da6c28aaSamw * 0 : success
1149da6c28aaSamw */
1150da6c28aaSamw int
smb_ads_remove_share(smb_ads_handle_t * ah,const char * adsShareName,const char * shareUNC,const char * adsContainer,const char * hostname)11513db3f65cSamw smb_ads_remove_share(smb_ads_handle_t *ah, const char *adsShareName,
11523db3f65cSamw const char *shareUNC, const char *adsContainer, const char *hostname)
1153da6c28aaSamw {
1154da6c28aaSamw int ret;
11553db3f65cSamw char unc_name[SMB_ADS_MAXBUFLEN];
1156da6c28aaSamw
1157da6c28aaSamw if (adsShareName == NULL || adsContainer == NULL)
1158da6c28aaSamw return (-1);
1159da6c28aaSamw if (shareUNC == 0 || *shareUNC == 0)
1160da6c28aaSamw shareUNC = adsShareName;
1161da6c28aaSamw
11623db3f65cSamw if (smb_ads_build_unc_name(unc_name, sizeof (unc_name),
1163b89a8333Snatalie li - Sun Microsystems - Irvine United States hostname, shareUNC) < 0)
1164da6c28aaSamw return (-1);
1165da6c28aaSamw
11663db3f65cSamw ret = smb_ads_lookup_share(ah, adsShareName, adsContainer, unc_name);
1167da6c28aaSamw if (ret == 0)
1168da6c28aaSamw return (0);
1169da6c28aaSamw if (ret == -1)
1170da6c28aaSamw return (-1);
1171da6c28aaSamw
11723db3f65cSamw return (smb_ads_del_share(ah, adsShareName, adsContainer));
1173da6c28aaSamw }
1174da6c28aaSamw
1175da6c28aaSamw /*
1176b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_get_default_comp_container_dn
1177da6c28aaSamw *
1178b89a8333Snatalie li - Sun Microsystems - Irvine United States * Build the distinguished name for the default computer conatiner (i.e. the
1179b89a8333Snatalie li - Sun Microsystems - Irvine United States * pre-defined Computers container).
1180da6c28aaSamw */
1181da6c28aaSamw static void
smb_ads_get_default_comp_container_dn(smb_ads_handle_t * ah,char * buf,size_t buflen)1182b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_container_dn(smb_ads_handle_t *ah, char *buf,
1183b89a8333Snatalie li - Sun Microsystems - Irvine United States size_t buflen)
1184da6c28aaSamw {
1185b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) snprintf(buf, buflen, "cn=%s,%s", SMB_ADS_COMPUTERS_CN,
1186b89a8333Snatalie li - Sun Microsystems - Irvine United States ah->domain_dn);
1187b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1188da6c28aaSamw
1189b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1190b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_get_default_comp_dn
1191b89a8333Snatalie li - Sun Microsystems - Irvine United States *
1192b89a8333Snatalie li - Sun Microsystems - Irvine United States * Build the distinguished name for this system.
1193b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1194b89a8333Snatalie li - Sun Microsystems - Irvine United States static void
smb_ads_get_default_comp_dn(smb_ads_handle_t * ah,char * buf,size_t buflen)1195b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_dn(smb_ads_handle_t *ah, char *buf, size_t buflen)
1196b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1197b89a8333Snatalie li - Sun Microsystems - Irvine United States char nbname[NETBIOS_NAME_SZ];
1198b89a8333Snatalie li - Sun Microsystems - Irvine United States char container_dn[SMB_ADS_DN_MAX];
1199b89a8333Snatalie li - Sun Microsystems - Irvine United States
1200b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getnetbiosname(nbname, sizeof (nbname));
1201b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_container_dn(ah, container_dn, SMB_ADS_DN_MAX);
1202b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) snprintf(buf, buflen, "cn=%s,%s", nbname, container_dn);
1203da6c28aaSamw }
1204da6c28aaSamw
1205da6c28aaSamw /*
12063db3f65cSamw * smb_ads_add_computer
1207da6c28aaSamw *
1208da6c28aaSamw * Returns 0 upon success. Otherwise, returns -1.
1209da6c28aaSamw */
1210da6c28aaSamw static int
smb_ads_add_computer(smb_ads_handle_t * ah,int dclevel,char * dn)1211c8ec8eeaSjose borrego smb_ads_add_computer(smb_ads_handle_t *ah, int dclevel, char *dn)
1212da6c28aaSamw {
1213c8ec8eeaSjose borrego return (smb_ads_computer_op(ah, LDAP_MOD_ADD, dclevel, dn));
121455bf511dSas200622 }
121555bf511dSas200622
121655bf511dSas200622 /*
12173db3f65cSamw * smb_ads_modify_computer
121855bf511dSas200622 *
121955bf511dSas200622 * Returns 0 upon success. Otherwise, returns -1.
122055bf511dSas200622 */
122155bf511dSas200622 static int
smb_ads_modify_computer(smb_ads_handle_t * ah,int dclevel,char * dn)1222c8ec8eeaSjose borrego smb_ads_modify_computer(smb_ads_handle_t *ah, int dclevel, char *dn)
122355bf511dSas200622 {
1224c8ec8eeaSjose borrego return (smb_ads_computer_op(ah, LDAP_MOD_REPLACE, dclevel, dn));
12253db3f65cSamw }
12263db3f65cSamw
12273db3f65cSamw /*
12283db3f65cSamw * smb_ads_get_dc_level
12293db3f65cSamw *
12303db3f65cSamw * Returns the functional level of the DC upon success.
12313db3f65cSamw * Otherwise, -1 is returned.
12323db3f65cSamw */
12333db3f65cSamw static int
smb_ads_get_dc_level(smb_ads_handle_t * ah)12343db3f65cSamw smb_ads_get_dc_level(smb_ads_handle_t *ah)
12353db3f65cSamw {
12363db3f65cSamw LDAPMessage *res, *entry;
12373db3f65cSamw char *attr[2];
12383db3f65cSamw char **vals;
12393db3f65cSamw int rc = -1;
12403db3f65cSamw
12413db3f65cSamw res = NULL;
12423db3f65cSamw attr[0] = SMB_ADS_ATTR_DCLEVEL;
12433db3f65cSamw attr[1] = NULL;
12443db3f65cSamw if (ldap_search_s(ah->ld, "", LDAP_SCOPE_BASE, NULL, attr,
12453db3f65cSamw 0, &res) != LDAP_SUCCESS) {
12463db3f65cSamw (void) ldap_msgfree(res);
12473db3f65cSamw return (-1);
12483db3f65cSamw }
12493db3f65cSamw
12503db3f65cSamw /* no match for the specified attribute is found */
12513db3f65cSamw if (ldap_count_entries(ah->ld, res) == 0) {
12523db3f65cSamw (void) ldap_msgfree(res);
12533db3f65cSamw return (-1);
12543db3f65cSamw }
12553db3f65cSamw
12563db3f65cSamw entry = ldap_first_entry(ah->ld, res);
12573db3f65cSamw if (entry) {
12583db3f65cSamw if ((vals = ldap_get_values(ah->ld, entry,
12593db3f65cSamw SMB_ADS_ATTR_DCLEVEL)) == NULL) {
12603db3f65cSamw /*
12613db3f65cSamw * Observed the values aren't populated
12623db3f65cSamw * by the Windows 2000 server.
12633db3f65cSamw */
12643db3f65cSamw (void) ldap_msgfree(res);
12653db3f65cSamw return (SMB_ADS_DCLEVEL_W2K);
12663db3f65cSamw }
12673db3f65cSamw
12683db3f65cSamw if (vals[0] != NULL)
12693db3f65cSamw rc = atoi(vals[0]);
12703db3f65cSamw
12713db3f65cSamw ldap_value_free(vals);
12723db3f65cSamw }
12733db3f65cSamw
12743db3f65cSamw (void) ldap_msgfree(res);
12753db3f65cSamw return (rc);
127655bf511dSas200622 }
127755bf511dSas200622
12789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
12799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * The fully-qualified hostname returned by this function is often used for
12809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * constructing service principal name. Return the fully-qualified hostname
12819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * in lower case for RFC 4120 section 6.2.1 conformance.
12829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
128355bf511dSas200622 static int
smb_ads_getfqhostname(smb_ads_handle_t * ah,char * fqhost,int len)1284b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_getfqhostname(smb_ads_handle_t *ah, char *fqhost, int len)
1285b89a8333Snatalie li - Sun Microsystems - Irvine United States {
12869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(fqhost, len, SMB_CASE_LOWER) != 0)
1287b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1);
1288b89a8333Snatalie li - Sun Microsystems - Irvine United States
1289b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) snprintf(fqhost, len, "%s.%s", fqhost,
1290b89a8333Snatalie li - Sun Microsystems - Irvine United States ah->domain);
1291b89a8333Snatalie li - Sun Microsystems - Irvine United States
1292b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0);
1293b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1294b89a8333Snatalie li - Sun Microsystems - Irvine United States
1295b89a8333Snatalie li - Sun Microsystems - Irvine United States static int
smb_ads_computer_op(smb_ads_handle_t * ah,int op,int dclevel,char * dn)1296c8ec8eeaSjose borrego smb_ads_computer_op(smb_ads_handle_t *ah, int op, int dclevel, char *dn)
129755bf511dSas200622 {
12983db3f65cSamw LDAPMod *attrs[SMB_ADS_COMPUTER_NUM_ATTR];
1299148c5f43SAlan Wright char *sam_val[2];
1300148c5f43SAlan Wright char *ctl_val[2], *fqh_val[2];
13013db3f65cSamw char *encrypt_val[2];
13026537f381Sas200622 int j = -1;
1303da6c28aaSamw int ret, usrctl_flags = 0;
1304b89a8333Snatalie li - Sun Microsystems - Irvine United States char sam_acct[SMB_SAMACCT_MAXLEN];
1305da6c28aaSamw char fqhost[MAXHOSTNAMELEN];
1306da6c28aaSamw char usrctl_buf[16];
13073db3f65cSamw char encrypt_buf[16];
130855bf511dSas200622 int max;
1309148c5f43SAlan Wright smb_krb5_pn_set_t spn, upn;
1310da6c28aaSamw
1311b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getsamaccount(sam_acct, sizeof (sam_acct)) != 0)
1312da6c28aaSamw return (-1);
1313da6c28aaSamw
1314b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_getfqhostname(ah, fqhost, MAXHOSTNAMELEN))
1315b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1);
1316da6c28aaSamw
1317148c5f43SAlan Wright /* The SPN attribute is multi-valued and must be 1 or greater */
1318148c5f43SAlan Wright if (smb_krb5_get_pn_set(&spn, SMB_PN_SPN_ATTR, ah->domain) == 0)
13196537f381Sas200622 return (-1);
13206537f381Sas200622
1321148c5f43SAlan Wright /* The UPN attribute is single-valued and cannot be zero */
1322148c5f43SAlan Wright if (smb_krb5_get_pn_set(&upn, SMB_PN_UPN_ATTR, ah->domain) != 1) {
1323148c5f43SAlan Wright smb_krb5_free_pn_set(&spn);
1324148c5f43SAlan Wright smb_krb5_free_pn_set(&upn);
1325da6c28aaSamw return (-1);
1326da6c28aaSamw }
1327da6c28aaSamw
13283db3f65cSamw max = (SMB_ADS_COMPUTER_NUM_ATTR - ((op != LDAP_MOD_ADD) ? 1 : 0))
1329b1352070SAlan Wright - (dclevel >= SMB_ADS_DCLEVEL_W2K8 ? 0 : 1);
13306537f381Sas200622
13313db3f65cSamw if (smb_ads_alloc_attr(attrs, max) != 0) {
1332148c5f43SAlan Wright smb_krb5_free_pn_set(&spn);
1333148c5f43SAlan Wright smb_krb5_free_pn_set(&upn);
133455bf511dSas200622 return (-1);
133555bf511dSas200622 }
133655bf511dSas200622
133755bf511dSas200622 /* objectClass attribute is not modifiable. */
133855bf511dSas200622 if (op == LDAP_MOD_ADD) {
133955bf511dSas200622 attrs[++j]->mod_op = op;
134055bf511dSas200622 attrs[j]->mod_type = "objectClass";
13417f667e74Sjose borrego attrs[j]->mod_values = smb_ads_computer_objcls;
134255bf511dSas200622 }
1343da6c28aaSamw
134455bf511dSas200622 attrs[++j]->mod_op = op;
13453db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_SAMACCT;
1346da6c28aaSamw sam_val[0] = sam_acct;
1347da6c28aaSamw sam_val[1] = 0;
134855bf511dSas200622 attrs[j]->mod_values = sam_val;
1349da6c28aaSamw
135055bf511dSas200622 attrs[++j]->mod_op = op;
13513db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_UPN;
1352148c5f43SAlan Wright attrs[j]->mod_values = upn.s_pns;
1353da6c28aaSamw
135455bf511dSas200622 attrs[++j]->mod_op = op;
13553db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_SPN;
1356148c5f43SAlan Wright attrs[j]->mod_values = spn.s_pns;
1357da6c28aaSamw
135855bf511dSas200622 attrs[++j]->mod_op = op;
13593db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_CTL;
13603db3f65cSamw usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
13613db3f65cSamw SMB_ADS_USER_ACCT_CTL_PASSWD_NOTREQD |
13623db3f65cSamw SMB_ADS_USER_ACCT_CTL_ACCOUNTDISABLE);
1363da6c28aaSamw (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", usrctl_flags);
1364da6c28aaSamw ctl_val[0] = usrctl_buf;
1365da6c28aaSamw ctl_val[1] = 0;
136655bf511dSas200622 attrs[j]->mod_values = ctl_val;
1367da6c28aaSamw
136855bf511dSas200622 attrs[++j]->mod_op = op;
13693db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_DNSHOST;
1370da6c28aaSamw fqh_val[0] = fqhost;
1371da6c28aaSamw fqh_val[1] = 0;
137255bf511dSas200622 attrs[j]->mod_values = fqh_val;
1373da6c28aaSamw
13743db3f65cSamw /* enctypes support starting in Windows Server 2008 */
13753db3f65cSamw if (dclevel > SMB_ADS_DCLEVEL_W2K3) {
13763db3f65cSamw attrs[++j]->mod_op = op;
13773db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_ENCTYPES;
13783db3f65cSamw (void) snprintf(encrypt_buf, sizeof (encrypt_buf), "%d",
13793db3f65cSamw SMB_ADS_ENC_AES256 + SMB_ADS_ENC_AES128 + SMB_ADS_ENC_RC4 +
13803db3f65cSamw SMB_ADS_ENC_DES_MD5 + SMB_ADS_ENC_DES_CRC);
13813db3f65cSamw encrypt_val[0] = encrypt_buf;
13823db3f65cSamw encrypt_val[1] = 0;
13833db3f65cSamw attrs[j]->mod_values = encrypt_val;
13843db3f65cSamw }
13853db3f65cSamw
138655bf511dSas200622 switch (op) {
138755bf511dSas200622 case LDAP_MOD_ADD:
138855bf511dSas200622 if ((ret = ldap_add_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
1389fc724630SAlan Wright syslog(LOG_NOTICE, "ldap_add: %s",
139055bf511dSas200622 ldap_err2string(ret));
1391da6c28aaSamw ret = -1;
1392da6c28aaSamw }
139355bf511dSas200622 break;
1394da6c28aaSamw
139555bf511dSas200622 case LDAP_MOD_REPLACE:
139655bf511dSas200622 if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
1397fc724630SAlan Wright syslog(LOG_NOTICE, "ldap_modify: %s",
139855bf511dSas200622 ldap_err2string(ret));
139955bf511dSas200622 ret = -1;
140055bf511dSas200622 }
140155bf511dSas200622 break;
140255bf511dSas200622
140355bf511dSas200622 default:
140455bf511dSas200622 ret = -1;
140555bf511dSas200622
140655bf511dSas200622 }
140755bf511dSas200622
14083db3f65cSamw smb_ads_free_attr(attrs);
1409148c5f43SAlan Wright smb_krb5_free_pn_set(&spn);
1410148c5f43SAlan Wright smb_krb5_free_pn_set(&upn);
1411da6c28aaSamw
1412da6c28aaSamw return (ret);
1413da6c28aaSamw }
1414da6c28aaSamw
1415da6c28aaSamw /*
1416da6c28aaSamw * Delete an ADS computer account.
1417da6c28aaSamw */
1418da6c28aaSamw static void
smb_ads_del_computer(smb_ads_handle_t * ah,char * dn)1419c8ec8eeaSjose borrego smb_ads_del_computer(smb_ads_handle_t *ah, char *dn)
1420da6c28aaSamw {
1421da6c28aaSamw int rc;
1422da6c28aaSamw
14233db3f65cSamw if ((rc = ldap_delete_s(ah->ld, dn)) != LDAP_SUCCESS)
1424fc724630SAlan Wright smb_tracef("ldap_delete: %s", ldap_err2string(rc));
1425b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1426b89a8333Snatalie li - Sun Microsystems - Irvine United States
1427b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1428b89a8333Snatalie li - Sun Microsystems - Irvine United States * Gets the value of the given attribute.
1429b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1430b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t
smb_ads_getattr(LDAP * ld,LDAPMessage * entry,smb_ads_avpair_t * avpair)1431b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_getattr(LDAP *ld, LDAPMessage *entry, smb_ads_avpair_t *avpair)
1432b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1433b89a8333Snatalie li - Sun Microsystems - Irvine United States char **vals;
1434b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t rc = SMB_ADS_STAT_FOUND;
1435b89a8333Snatalie li - Sun Microsystems - Irvine United States
1436b89a8333Snatalie li - Sun Microsystems - Irvine United States assert(avpair);
1437b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair->avp_val = NULL;
1438b89a8333Snatalie li - Sun Microsystems - Irvine United States vals = ldap_get_values(ld, entry, avpair->avp_attr);
1439b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!vals)
1440b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1441b89a8333Snatalie li - Sun Microsystems - Irvine United States
1442b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!vals[0]) {
1443b89a8333Snatalie li - Sun Microsystems - Irvine United States ldap_value_free(vals);
1444b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1445b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1446b89a8333Snatalie li - Sun Microsystems - Irvine United States
1447b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair->avp_val = strdup(vals[0]);
1448b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!avpair->avp_val)
1449b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADS_STAT_ERR;
1450b89a8333Snatalie li - Sun Microsystems - Irvine United States
1451b89a8333Snatalie li - Sun Microsystems - Irvine United States ldap_value_free(vals);
1452b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1453b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1454b89a8333Snatalie li - Sun Microsystems - Irvine United States
1455b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1456b89a8333Snatalie li - Sun Microsystems - Irvine United States * Process query's result.
1457b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1458b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t
smb_ads_get_qstat(smb_ads_handle_t * ah,LDAPMessage * res,smb_ads_avpair_t * avpair)1459b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_qstat(smb_ads_handle_t *ah, LDAPMessage *res,
1460b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *avpair)
1461b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1462b89a8333Snatalie li - Sun Microsystems - Irvine United States char fqhost[MAXHOSTNAMELEN];
1463b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t dnshost_avp;
1464b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t rc = SMB_ADS_STAT_FOUND;
1465b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAPMessage *entry;
1466b89a8333Snatalie li - Sun Microsystems - Irvine United States
1467b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_getfqhostname(ah, fqhost, MAXHOSTNAMELEN))
1468b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1469b89a8333Snatalie li - Sun Microsystems - Irvine United States
1470b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ldap_count_entries(ah->ld, res) == 0)
1471b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1472b89a8333Snatalie li - Sun Microsystems - Irvine United States
1473b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((entry = ldap_first_entry(ah->ld, res)) == NULL)
1474b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1475b89a8333Snatalie li - Sun Microsystems - Irvine United States
1476b89a8333Snatalie li - Sun Microsystems - Irvine United States dnshost_avp.avp_attr = SMB_ADS_ATTR_DNSHOST;
1477b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_ads_getattr(ah->ld, entry, &dnshost_avp);
1478b89a8333Snatalie li - Sun Microsystems - Irvine United States
1479b89a8333Snatalie li - Sun Microsystems - Irvine United States switch (rc) {
1480b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_FOUND:
1481b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1482b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns SMB_ADS_STAT_DUP to avoid overwriting
1483b89a8333Snatalie li - Sun Microsystems - Irvine United States * the computer account of another system whose
1484b89a8333Snatalie li - Sun Microsystems - Irvine United States * NetBIOS name collides with that of the current
1485b89a8333Snatalie li - Sun Microsystems - Irvine United States * system.
1486b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1487b89a8333Snatalie li - Sun Microsystems - Irvine United States if (strcasecmp(dnshost_avp.avp_val, fqhost))
1488b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADS_STAT_DUP;
1489b89a8333Snatalie li - Sun Microsystems - Irvine United States
1490b89a8333Snatalie li - Sun Microsystems - Irvine United States free(dnshost_avp.avp_val);
1491b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1492b89a8333Snatalie li - Sun Microsystems - Irvine United States
1493b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_NOT_FOUND:
1494b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1495b89a8333Snatalie li - Sun Microsystems - Irvine United States * Pre-created computer account doesn't have
1496b89a8333Snatalie li - Sun Microsystems - Irvine United States * the dNSHostname attribute. It's been observed
1497b89a8333Snatalie li - Sun Microsystems - Irvine United States * that the dNSHostname attribute is only set after
1498b89a8333Snatalie li - Sun Microsystems - Irvine United States * a successful domain join.
1499b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns SMB_ADS_STAT_FOUND as the account is
1500b89a8333Snatalie li - Sun Microsystems - Irvine United States * pre-created for the current system.
1501b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1502b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADS_STAT_FOUND;
1503b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1504b89a8333Snatalie li - Sun Microsystems - Irvine United States
1505b89a8333Snatalie li - Sun Microsystems - Irvine United States default:
1506b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1507b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1508b89a8333Snatalie li - Sun Microsystems - Irvine United States
1509b89a8333Snatalie li - Sun Microsystems - Irvine United States if (rc != SMB_ADS_STAT_FOUND)
1510b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1511b89a8333Snatalie li - Sun Microsystems - Irvine United States
1512b89a8333Snatalie li - Sun Microsystems - Irvine United States if (avpair)
1513b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_ads_getattr(ah->ld, entry, avpair);
1514b89a8333Snatalie li - Sun Microsystems - Irvine United States
1515b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1516b89a8333Snatalie li - Sun Microsystems - Irvine United States
1517da6c28aaSamw }
1518da6c28aaSamw
1519da6c28aaSamw /*
15203db3f65cSamw * smb_ads_lookup_computer_n_attr
1521da6c28aaSamw *
1522b89a8333Snatalie li - Sun Microsystems - Irvine United States * If avpair is NULL, checks the status of the specified computer account.
1523b89a8333Snatalie li - Sun Microsystems - Irvine United States * Otherwise, looks up the value of the specified computer account's attribute.
1524b89a8333Snatalie li - Sun Microsystems - Irvine United States * If found, the value field of the avpair will be allocated and set. The
1525b89a8333Snatalie li - Sun Microsystems - Irvine United States * caller should free the allocated buffer.
1526da6c28aaSamw *
1527da6c28aaSamw * Return:
1528b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_FOUND - if both the computer and the specified attribute is
1529b89a8333Snatalie li - Sun Microsystems - Irvine United States * found.
1530b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_NOT_FOUND - if either the computer or the specified attribute
1531b89a8333Snatalie li - Sun Microsystems - Irvine United States * is not found.
1532b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_DUP - if the computer account is already used by other systems
1533b89a8333Snatalie li - Sun Microsystems - Irvine United States * in the AD. This could happen if the hostname of multiple
1534b89a8333Snatalie li - Sun Microsystems - Irvine United States * systems resolved to the same NetBIOS name.
1535b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_ERR - any failure.
1536da6c28aaSamw */
1537b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t
smb_ads_lookup_computer_n_attr(smb_ads_handle_t * ah,smb_ads_avpair_t * avpair,int scope,char * dn)1538b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_lookup_computer_n_attr(smb_ads_handle_t *ah, smb_ads_avpair_t *avpair,
1539c8ec8eeaSjose borrego int scope, char *dn)
1540da6c28aaSamw {
1541b89a8333Snatalie li - Sun Microsystems - Irvine United States char *attrs[3], filter[SMB_ADS_MAXBUFLEN];
1542b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAPMessage *res;
1543b89a8333Snatalie li - Sun Microsystems - Irvine United States char sam_acct[SMB_SAMACCT_MAXLEN], sam_acct2[SMB_SAMACCT_MAXLEN];
1544b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t rc;
1545da6c28aaSamw
1546b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getsamaccount(sam_acct, sizeof (sam_acct)) != 0)
1547b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1548da6c28aaSamw
1549da6c28aaSamw res = NULL;
1550b89a8333Snatalie li - Sun Microsystems - Irvine United States attrs[0] = SMB_ADS_ATTR_DNSHOST;
1551da6c28aaSamw attrs[1] = NULL;
1552b89a8333Snatalie li - Sun Microsystems - Irvine United States attrs[2] = NULL;
1553da6c28aaSamw
1554b89a8333Snatalie li - Sun Microsystems - Irvine United States if (avpair) {
1555b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!avpair->avp_attr)
1556b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1557b89a8333Snatalie li - Sun Microsystems - Irvine United States
1558b89a8333Snatalie li - Sun Microsystems - Irvine United States attrs[1] = avpair->avp_attr;
1559b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1560b89a8333Snatalie li - Sun Microsystems - Irvine United States
1561b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_escape_search_filter_chars(sam_acct, sam_acct2) != 0)
1562b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1563da6c28aaSamw
1564c8ec8eeaSjose borrego (void) snprintf(filter, sizeof (filter),
1565b89a8333Snatalie li - Sun Microsystems - Irvine United States "(&(objectClass=computer)(%s=%s))", SMB_ADS_ATTR_SAMACCT,
1566b89a8333Snatalie li - Sun Microsystems - Irvine United States sam_acct2);
1567da6c28aaSamw
1568c8ec8eeaSjose borrego if (ldap_search_s(ah->ld, dn, scope, filter, attrs, 0,
1569da6c28aaSamw &res) != LDAP_SUCCESS) {
1570da6c28aaSamw (void) ldap_msgfree(res);
1571b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1572da6c28aaSamw }
1573da6c28aaSamw
1574b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_ads_get_qstat(ah, res, avpair);
1575da6c28aaSamw /* free the search results */
1576da6c28aaSamw (void) ldap_msgfree(res);
1577b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1578da6c28aaSamw }
1579da6c28aaSamw
1580da6c28aaSamw /*
15813db3f65cSamw * smb_ads_find_computer
1582da6c28aaSamw *
1583c8ec8eeaSjose borrego * Starts by searching for the system's AD computer object in the default
1584c8ec8eeaSjose borrego * container (i.e. cn=Computers). If not found, searches the entire directory.
1585b89a8333Snatalie li - Sun Microsystems - Irvine United States * If found, 'dn' will be set to the distinguished name of the system's AD
1586b89a8333Snatalie li - Sun Microsystems - Irvine United States * computer object.
1587da6c28aaSamw */
1588b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t
smb_ads_find_computer(smb_ads_handle_t * ah,char * dn)1589c8ec8eeaSjose borrego smb_ads_find_computer(smb_ads_handle_t *ah, char *dn)
1590da6c28aaSamw {
1591b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t stat;
1592b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t avpair;
1593c8ec8eeaSjose borrego
1594b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair.avp_attr = SMB_ADS_ATTR_DN;
1595b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_container_dn(ah, dn, SMB_ADS_DN_MAX);
1596b89a8333Snatalie li - Sun Microsystems - Irvine United States stat = smb_ads_lookup_computer_n_attr(ah, &avpair, LDAP_SCOPE_ONELEVEL,
1597b89a8333Snatalie li - Sun Microsystems - Irvine United States dn);
1598c8ec8eeaSjose borrego
1599b89a8333Snatalie li - Sun Microsystems - Irvine United States if (stat == SMB_ADS_STAT_NOT_FOUND) {
1600c8ec8eeaSjose borrego (void) strlcpy(dn, ah->domain_dn, SMB_ADS_DN_MAX);
1601b89a8333Snatalie li - Sun Microsystems - Irvine United States stat = smb_ads_lookup_computer_n_attr(ah, &avpair,
1602b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAP_SCOPE_SUBTREE, dn);
1603c8ec8eeaSjose borrego }
1604c8ec8eeaSjose borrego
1605b89a8333Snatalie li - Sun Microsystems - Irvine United States if (stat == SMB_ADS_STAT_FOUND) {
1606b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcpy(dn, avpair.avp_val, SMB_ADS_DN_MAX);
1607b89a8333Snatalie li - Sun Microsystems - Irvine United States free(avpair.avp_val);
1608b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1609b89a8333Snatalie li - Sun Microsystems - Irvine United States
1610b89a8333Snatalie li - Sun Microsystems - Irvine United States return (stat);
1611da6c28aaSamw }
1612da6c28aaSamw
1613da6c28aaSamw /*
16143db3f65cSamw * smb_ads_update_computer_cntrl_attr
1615da6c28aaSamw *
1616da6c28aaSamw * Modify the user account control attribute of an existing computer
1617da6c28aaSamw * object on AD.
1618da6c28aaSamw *
16197f667e74Sjose borrego * Returns LDAP error code.
1620da6c28aaSamw */
1621da6c28aaSamw static int
smb_ads_update_computer_cntrl_attr(smb_ads_handle_t * ah,int flags,char * dn)16227f667e74Sjose borrego smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *ah, int flags, char *dn)
1623da6c28aaSamw {
16246537f381Sas200622 LDAPMod *attrs[2];
1625da6c28aaSamw char *ctl_val[2];
16267f667e74Sjose borrego int ret = 0;
1627da6c28aaSamw char usrctl_buf[16];
1628da6c28aaSamw
16293db3f65cSamw if (smb_ads_alloc_attr(attrs, sizeof (attrs) / sizeof (LDAPMod *)) != 0)
16307f667e74Sjose borrego return (LDAP_NO_MEMORY);
16316537f381Sas200622
16326537f381Sas200622 attrs[0]->mod_op = LDAP_MOD_REPLACE;
16333db3f65cSamw attrs[0]->mod_type = SMB_ADS_ATTR_CTL;
1634da6c28aaSamw
16357f667e74Sjose borrego (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", flags);
1636da6c28aaSamw ctl_val[0] = usrctl_buf;
1637da6c28aaSamw ctl_val[1] = 0;
16386537f381Sas200622 attrs[0]->mod_values = ctl_val;
1639da6c28aaSamw if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
1640fc724630SAlan Wright syslog(LOG_NOTICE, "ldap_modify: %s", ldap_err2string(ret));
1641da6c28aaSamw }
1642da6c28aaSamw
16433db3f65cSamw smb_ads_free_attr(attrs);
1644da6c28aaSamw return (ret);
1645da6c28aaSamw }
1646da6c28aaSamw
1647da6c28aaSamw /*
16483db3f65cSamw * smb_ads_lookup_computer_attr_kvno
1649da6c28aaSamw *
1650da6c28aaSamw * Lookup the value of the Kerberos version number attribute of the computer
1651da6c28aaSamw * account.
1652da6c28aaSamw */
1653da6c28aaSamw static krb5_kvno
smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t * ah,char * dn)1654c8ec8eeaSjose borrego smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t *ah, char *dn)
1655da6c28aaSamw {
1656b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t avpair;
1657da6c28aaSamw int kvno = 1;
1658da6c28aaSamw
1659b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair.avp_attr = SMB_ADS_ATTR_KVNO;
1660b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_lookup_computer_n_attr(ah, &avpair,
1661b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAP_SCOPE_BASE, dn) == SMB_ADS_STAT_FOUND) {
1662b89a8333Snatalie li - Sun Microsystems - Irvine United States kvno = atoi(avpair.avp_val);
1663b89a8333Snatalie li - Sun Microsystems - Irvine United States free(avpair.avp_val);
1664da6c28aaSamw }
1665da6c28aaSamw
1666da6c28aaSamw return (kvno);
1667da6c28aaSamw }
1668da6c28aaSamw
1669da6c28aaSamw /*
16703db3f65cSamw * smb_ads_join
1671da6c28aaSamw *
1672da6c28aaSamw * Besides the NT-4 style domain join (using MS-RPC), CIFS server also
1673da6c28aaSamw * provides the domain join using Kerberos Authentication, Keberos
167455bf511dSas200622 * Change & Set password, and LDAP protocols. Basically, AD join
1675da6c28aaSamw * operation would require the following tickets to be acquired for the
1676da6c28aaSamw * the user account that is provided for the domain join.
1677da6c28aaSamw *
1678da6c28aaSamw * 1) a Keberos TGT ticket,
1679da6c28aaSamw * 2) a ldap service ticket, and
1680da6c28aaSamw * 3) kadmin/changpw service ticket
1681da6c28aaSamw *
1682da6c28aaSamw * The ADS client first sends a ldap search request to find out whether
1683da6c28aaSamw * or not the workstation trust account already exists in the Active Directory.
1684da6c28aaSamw * The existing computer object for this workstation will be removed and
1685da6c28aaSamw * a new one will be added. The machine account password is randomly
16863db3f65cSamw * generated and set for the newly created computer object using KPASSWD
1687da6c28aaSamw * protocol (See RFC 3244). Once the password is set, our ADS client
1688da6c28aaSamw * finalizes the machine account by modifying the user acount control
1689da6c28aaSamw * attribute of the computer object. Kerberos keys derived from the machine
1690da6c28aaSamw * account password will be stored locally in /etc/krb5/krb5.keytab file.
1691da6c28aaSamw * That would be needed while acquiring Kerberos TGT ticket for the host
1692da6c28aaSamw * principal after the domain join operation.
1693da6c28aaSamw */
1694*b3700b07SGordon Ross smb_ads_status_t
smb_ads_join(char * domain,char * user,char * usr_passwd,char * machine_passwd)16951ed6b69aSGordon Ross smb_ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd)
1696da6c28aaSamw {
16973db3f65cSamw smb_ads_handle_t *ah = NULL;
1698da6c28aaSamw krb5_context ctx = NULL;
1699148c5f43SAlan Wright krb5_principal *krb5princs = NULL;
1700da6c28aaSamw krb5_kvno kvno;
1701*b3700b07SGordon Ross boolean_t delete = B_TRUE;
1702*b3700b07SGordon Ross smb_ads_status_t rc;
170355bf511dSas200622 boolean_t new_acct;
17047f667e74Sjose borrego int dclevel, num, usrctl_flags = 0;
1705b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t qstat;
1706c8ec8eeaSjose borrego char dn[SMB_ADS_DN_MAX];
1707c28afb19SYuri Pankov char tmpfile[] = SMBNS_KRB5_KEYTAB_TMP;
1708*b3700b07SGordon Ross int cnt, x;
1709148c5f43SAlan Wright smb_krb5_pn_set_t spns;
17103db3f65cSamw krb5_enctype *encptr;
17113db3f65cSamw
1712*b3700b07SGordon Ross rc = smb_ads_open_main(&ah, domain, user, usr_passwd);
1713*b3700b07SGordon Ross if (rc != 0) {
1714faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
1715*b3700b07SGordon Ross return (rc);
171655bf511dSas200622 }
171755bf511dSas200622
17183db3f65cSamw if ((dclevel = smb_ads_get_dc_level(ah)) == -1) {
17193db3f65cSamw smb_ads_close(ah);
17203db3f65cSamw smb_ccache_remove(SMB_CCACHE_PATH);
17213db3f65cSamw return (SMB_ADJOIN_ERR_GET_DCLEVEL);
17223db3f65cSamw }
17233db3f65cSamw
1724b89a8333Snatalie li - Sun Microsystems - Irvine United States qstat = smb_ads_find_computer(ah, dn);
1725b89a8333Snatalie li - Sun Microsystems - Irvine United States switch (qstat) {
1726b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_FOUND:
172755bf511dSas200622 new_acct = B_FALSE;
1728c8ec8eeaSjose borrego if (smb_ads_modify_computer(ah, dclevel, dn) != 0) {
17293db3f65cSamw smb_ads_close(ah);
1730faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
17313db3f65cSamw return (SMB_ADJOIN_ERR_MOD_TRUST_ACCT);
173255bf511dSas200622 }
1733b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1734b89a8333Snatalie li - Sun Microsystems - Irvine United States
1735b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_NOT_FOUND:
173655bf511dSas200622 new_acct = B_TRUE;
1737b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_dn(ah, dn, SMB_ADS_DN_MAX);
1738c8ec8eeaSjose borrego if (smb_ads_add_computer(ah, dclevel, dn) != 0) {
17393db3f65cSamw smb_ads_close(ah);
1740faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
17413db3f65cSamw return (SMB_ADJOIN_ERR_ADD_TRUST_ACCT);
174255bf511dSas200622 }
1743b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1744b89a8333Snatalie li - Sun Microsystems - Irvine United States
1745b89a8333Snatalie li - Sun Microsystems - Irvine United States default:
1746b89a8333Snatalie li - Sun Microsystems - Irvine United States if (qstat == SMB_ADS_STAT_DUP)
1747b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADJOIN_ERR_DUP_TRUST_ACCT;
1748b89a8333Snatalie li - Sun Microsystems - Irvine United States else
1749b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADJOIN_ERR_TRUST_ACCT;
1750b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_close(ah);
1751b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ccache_remove(SMB_CCACHE_PATH);
1752b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
175355bf511dSas200622 }
175455bf511dSas200622
1755da6c28aaSamw if (smb_krb5_ctx_init(&ctx) != 0) {
17563db3f65cSamw rc = SMB_ADJOIN_ERR_INIT_KRB_CTX;
1757da6c28aaSamw goto adjoin_cleanup;
1758da6c28aaSamw }
1759da6c28aaSamw
1760148c5f43SAlan Wright if (smb_krb5_get_pn_set(&spns, SMB_PN_KEYTAB_ENTRY, ah->domain) == 0) {
17613db3f65cSamw rc = SMB_ADJOIN_ERR_GET_SPNS;
1762da6c28aaSamw goto adjoin_cleanup;
1763da6c28aaSamw }
1764da6c28aaSamw
1765148c5f43SAlan Wright if (smb_krb5_get_kprincs(ctx, spns.s_pns, spns.s_cnt, &krb5princs)
1766148c5f43SAlan Wright != 0) {
1767148c5f43SAlan Wright smb_krb5_free_pn_set(&spns);
1768148c5f43SAlan Wright rc = SMB_ADJOIN_ERR_GET_SPNS;
1769148c5f43SAlan Wright goto adjoin_cleanup;
1770148c5f43SAlan Wright }
1771148c5f43SAlan Wright
1772148c5f43SAlan Wright cnt = spns.s_cnt;
1773148c5f43SAlan Wright smb_krb5_free_pn_set(&spns);
1774148c5f43SAlan Wright
17751ed6b69aSGordon Ross /* New machine_passwd was filled in by our caller. */
1776148c5f43SAlan Wright if (smb_krb5_setpwd(ctx, ah->domain, machine_passwd) != 0) {
17773db3f65cSamw rc = SMB_ADJOIN_ERR_KSETPWD;
1778da6c28aaSamw goto adjoin_cleanup;
1779da6c28aaSamw }
1780da6c28aaSamw
1781c8ec8eeaSjose borrego kvno = smb_ads_lookup_computer_attr_kvno(ah, dn);
178255bf511dSas200622
17837f667e74Sjose borrego /*
17847f667e74Sjose borrego * Only members of Domain Admins and Enterprise Admins can set
17857f667e74Sjose borrego * the TRUSTED_FOR_DELEGATION userAccountControl flag.
1786*b3700b07SGordon Ross * Try to set this, but don't fail the join if we can't.
1787*b3700b07SGordon Ross * Look into just removing this...
17887f667e74Sjose borrego */
1789*b3700b07SGordon Ross usrctl_flags = (
1790037cac00Sjoyce mcintosh SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
17917f667e74Sjose borrego SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION |
17927f667e74Sjose borrego SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
1793*b3700b07SGordon Ross set_ctl_again:
1794*b3700b07SGordon Ross x = smb_ads_update_computer_cntrl_attr(ah, usrctl_flags, dn);
1795*b3700b07SGordon Ross if (x != LDAP_SUCCESS && (usrctl_flags &
1796*b3700b07SGordon Ross SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION) != 0) {
1797*b3700b07SGordon Ross syslog(LOG_NOTICE, "Unable to set the "
1798*b3700b07SGordon Ross "TRUSTED_FOR_DELEGATION userAccountControl flag on the "
1799*b3700b07SGordon Ross "machine account in Active Directory. It may be necessary "
1800*b3700b07SGordon Ross "to set that via Active Directory administration.");
1801*b3700b07SGordon Ross usrctl_flags &=
1802*b3700b07SGordon Ross ~SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION;
1803*b3700b07SGordon Ross goto set_ctl_again;
18047f667e74Sjose borrego }
1805*b3700b07SGordon Ross if (x != LDAP_SUCCESS) {
18063db3f65cSamw rc = SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR;
1807da6c28aaSamw goto adjoin_cleanup;
1808da6c28aaSamw }
180955bf511dSas200622
1810c28afb19SYuri Pankov if (mktemp(tmpfile) == NULL) {
1811c28afb19SYuri Pankov rc = SMB_ADJOIN_ERR_WRITE_KEYTAB;
1812c28afb19SYuri Pankov goto adjoin_cleanup;
1813c28afb19SYuri Pankov }
18148d7e4166Sjose borrego
1815148c5f43SAlan Wright encptr = smb_ads_get_enctypes(dclevel, &num);
1816148c5f43SAlan Wright if (smb_krb5_kt_populate(ctx, ah->domain, krb5princs, cnt,
1817148c5f43SAlan Wright tmpfile, kvno, machine_passwd, encptr, num) != 0) {
18183db3f65cSamw rc = SMB_ADJOIN_ERR_WRITE_KEYTAB;
1819da6c28aaSamw goto adjoin_cleanup;
1820da6c28aaSamw }
1821da6c28aaSamw
182255bf511dSas200622 delete = B_FALSE;
1823*b3700b07SGordon Ross rc = SMB_ADS_SUCCESS;
1824*b3700b07SGordon Ross
1825da6c28aaSamw adjoin_cleanup:
182655bf511dSas200622 if (new_acct && delete)
1827c8ec8eeaSjose borrego smb_ads_del_computer(ah, dn);
1828da6c28aaSamw
18293db3f65cSamw if (rc != SMB_ADJOIN_ERR_INIT_KRB_CTX) {
18303db3f65cSamw if (rc != SMB_ADJOIN_ERR_GET_SPNS)
1831148c5f43SAlan Wright smb_krb5_free_kprincs(ctx, krb5princs, cnt);
1832da6c28aaSamw smb_krb5_ctx_fini(ctx);
1833cbfb650aScp160787 }
1834da6c28aaSamw
18358d7e4166Sjose borrego /* commit keytab file */
1836*b3700b07SGordon Ross if (rc == SMB_ADS_SUCCESS) {
18378d7e4166Sjose borrego if (rename(tmpfile, SMBNS_KRB5_KEYTAB) != 0) {
18388d7e4166Sjose borrego (void) unlink(tmpfile);
18398d7e4166Sjose borrego rc = SMB_ADJOIN_ERR_COMMIT_KEYTAB;
18408d7e4166Sjose borrego }
18418d7e4166Sjose borrego } else {
18428d7e4166Sjose borrego (void) unlink(tmpfile);
18438d7e4166Sjose borrego }
18448d7e4166Sjose borrego
18453db3f65cSamw smb_ads_close(ah);
1846faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
1847da6c28aaSamw return (rc);
1848da6c28aaSamw }
1849da6c28aaSamw
1850fc724630SAlan Wright struct xlate_table {
1851*b3700b07SGordon Ross int err;
1852*b3700b07SGordon Ross const char const *msg;
1853*b3700b07SGordon Ross };
1854*b3700b07SGordon Ross
1855*b3700b07SGordon Ross static const struct xlate_table
1856*b3700b07SGordon Ross adjoin_table[] = {
1857*b3700b07SGordon Ross { SMB_ADS_SUCCESS, "Success" },
1858*b3700b07SGordon Ross { SMB_ADS_KRB5_INIT_CTX,
1859*b3700b07SGordon Ross "Failed creating a Kerberos context." },
1860*b3700b07SGordon Ross { SMB_ADS_KRB5_CC_DEFAULT,
1861*b3700b07SGordon Ross "Failed to resolve default credential cache." },
1862*b3700b07SGordon Ross { SMB_ADS_KRB5_PARSE_PRINCIPAL,
1863*b3700b07SGordon Ross "Failed parsing the user principal name." },
1864*b3700b07SGordon Ross { SMB_ADS_KRB5_GET_INIT_CREDS_PW,
1865*b3700b07SGordon Ross "Failed getting initial credentials. (Wrong password?)" },
1866*b3700b07SGordon Ross { SMB_ADS_KRB5_CC_INITIALIZE,
1867*b3700b07SGordon Ross "Failed initializing the credential cache." },
1868*b3700b07SGordon Ross { SMB_ADS_KRB5_CC_STORE_CRED,
1869*b3700b07SGordon Ross "Failed to update the credential cache." },
1870*b3700b07SGordon Ross { SMB_ADS_CANT_LOCATE_DC,
1871*b3700b07SGordon Ross "Failed to locate a domain controller." },
1872*b3700b07SGordon Ross { SMB_ADS_LDAP_INIT,
1873*b3700b07SGordon Ross "Failed to create an LDAP handle." },
1874*b3700b07SGordon Ross { SMB_ADS_LDAP_SETOPT,
1875*b3700b07SGordon Ross "Failed to set an LDAP option." },
1876*b3700b07SGordon Ross { SMB_ADS_LDAP_SET_DOM,
1877*b3700b07SGordon Ross "Failed to set the LDAP handle DN." },
1878*b3700b07SGordon Ross { SMB_ADS_LDAP_SASL_BIND,
1879*b3700b07SGordon Ross "Failed to bind the LDAP handle. "
1880*b3700b07SGordon Ross "Usually indicates an authentication problem." },
1881*b3700b07SGordon Ross
1882*b3700b07SGordon Ross { SMB_ADJOIN_ERR_GEN_PWD,
1883*b3700b07SGordon Ross "Failed to generate machine password." },
1884fc724630SAlan Wright { SMB_ADJOIN_ERR_GET_DCLEVEL, "Unknown functional level of "
1885fc724630SAlan Wright "the domain controller. The rootDSE attribute named "
1886fc724630SAlan Wright "\"domainControllerFunctionality\" is missing from the "
1887fc724630SAlan Wright "Active Directory." },
1888fc724630SAlan Wright { SMB_ADJOIN_ERR_ADD_TRUST_ACCT, "Failed to create the "
1889fc724630SAlan Wright "workstation trust account." },
1890fc724630SAlan Wright { SMB_ADJOIN_ERR_MOD_TRUST_ACCT, "Failed to modify the "
1891fc724630SAlan Wright "workstation trust account." },
1892fc724630SAlan Wright { SMB_ADJOIN_ERR_DUP_TRUST_ACCT, "Failed to create the "
1893fc724630SAlan Wright "workstation trust account because its name is already "
1894fc724630SAlan Wright "in use." },
1895fc724630SAlan Wright { SMB_ADJOIN_ERR_TRUST_ACCT, "Error in querying the "
1896fc724630SAlan Wright "workstation trust account" },
1897fc724630SAlan Wright { SMB_ADJOIN_ERR_INIT_KRB_CTX, "Failed to initialize Kerberos "
1898fc724630SAlan Wright "context." },
1899fc724630SAlan Wright { SMB_ADJOIN_ERR_GET_SPNS, "Failed to get Kerberos "
1900fc724630SAlan Wright "principals." },
1901fc724630SAlan Wright { SMB_ADJOIN_ERR_KSETPWD, "Failed to set machine password." },
1902fc724630SAlan Wright { SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR, "Failed to modify "
1903fc724630SAlan Wright "userAccountControl attribute of the workstation trust "
1904fc724630SAlan Wright "account." },
1905fc724630SAlan Wright { SMB_ADJOIN_ERR_WRITE_KEYTAB, "Error in writing to local "
1906fc724630SAlan Wright "keytab file (i.e /etc/krb5/krb5.keytab)." },
1907fc724630SAlan Wright { SMB_ADJOIN_ERR_IDMAP_SET_DOMAIN, "Failed to update idmap "
1908fc724630SAlan Wright "configuration." },
1909fc724630SAlan Wright { SMB_ADJOIN_ERR_IDMAP_REFRESH, "Failed to refresh idmap "
1910fc724630SAlan Wright "service." },
1911fc724630SAlan Wright { SMB_ADJOIN_ERR_COMMIT_KEYTAB, "Failed to commit changes to "
1912*b3700b07SGordon Ross "local keytab file (i.e. /etc/krb5/krb5.keytab)." },
1913*b3700b07SGordon Ross { SMB_ADJOIN_ERR_AUTH_NETLOGON,
1914*b3700b07SGordon Ross "Failed to authenticate using the new computer account." },
1915*b3700b07SGordon Ross { SMB_ADJOIN_ERR_STORE_PROPS,
1916*b3700b07SGordon Ross "Failed to store computer account information locally." },
1917*b3700b07SGordon Ross { 0, NULL }
1918fc724630SAlan Wright };
1919da6c28aaSamw
1920c8ec8eeaSjose borrego /*
1921*b3700b07SGordon Ross * smb_ads_strerror
1922b89a8333Snatalie li - Sun Microsystems - Irvine United States *
1923*b3700b07SGordon Ross * Lookup an error message for the specific adjoin error code.
1924b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1925*b3700b07SGordon Ross const char *
smb_ads_strerror(int err)1926*b3700b07SGordon Ross smb_ads_strerror(int err)
1927b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1928*b3700b07SGordon Ross const struct xlate_table *xt;
1929b89a8333Snatalie li - Sun Microsystems - Irvine United States
1930*b3700b07SGordon Ross if (err > 0 && err < SMB_ADS_ERRNO_GAP)
1931*b3700b07SGordon Ross return (strerror(err));
1932b89a8333Snatalie li - Sun Microsystems - Irvine United States
1933*b3700b07SGordon Ross for (xt = adjoin_table; xt->msg; xt++)
1934*b3700b07SGordon Ross if (xt->err == err)
1935*b3700b07SGordon Ross return (xt->msg);
1936b89a8333Snatalie li - Sun Microsystems - Irvine United States
1937*b3700b07SGordon Ross return ("Unknown error code.");
1938b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1939b89a8333Snatalie li - Sun Microsystems - Irvine United States
1940*b3700b07SGordon Ross void
smb_ads_log_errmsg(smb_ads_status_t err)1941*b3700b07SGordon Ross smb_ads_log_errmsg(smb_ads_status_t err)
1942b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1943*b3700b07SGordon Ross const char *s = smb_ads_strerror(err);
1944*b3700b07SGordon Ross syslog(LOG_NOTICE, "%s", s);
1945b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1946b89a8333Snatalie li - Sun Microsystems - Irvine United States
19478d7e4166Sjose borrego
19488d7e4166Sjose borrego /*
19498d7e4166Sjose borrego * smb_ads_lookup_msdcs
19508d7e4166Sjose borrego *
19518d7e4166Sjose borrego * If server argument is set, try to locate the specified DC.
19528d7e4166Sjose borrego * If it is set to empty string, locate any DCs in the specified domain.
19538d7e4166Sjose borrego * Returns the discovered DC via buf.
19548d7e4166Sjose borrego *
19558d7e4166Sjose borrego * fqdn - fully-qualified domain name
1956*b3700b07SGordon Ross * dci - the name and address of the found DC
19578d7e4166Sjose borrego */
1958*b3700b07SGordon Ross uint32_t
smb_ads_lookup_msdcs(char * fqdn,smb_dcinfo_t * dci)1959*b3700b07SGordon Ross smb_ads_lookup_msdcs(char *fqdn, smb_dcinfo_t *dci)
19608d7e4166Sjose borrego {
19618d7e4166Sjose borrego smb_ads_host_info_t *hinfo = NULL;
19627f667e74Sjose borrego char ipstr[INET6_ADDRSTRLEN];
19638d7e4166Sjose borrego
1964*b3700b07SGordon Ross if (!fqdn || !dci)
1965*b3700b07SGordon Ross return (NT_STATUS_INTERNAL_ERROR);
19668d7e4166Sjose borrego
196732b8d01aSChristopher Parker ipstr[0] = '\0';
1968*b3700b07SGordon Ross if ((hinfo = smb_ads_find_host(fqdn)) == NULL)
1969*b3700b07SGordon Ross return (NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
19708d7e4166Sjose borrego
197132b8d01aSChristopher Parker (void) smb_inet_ntop(&hinfo->ipaddr, ipstr,
197232b8d01aSChristopher Parker SMB_IPSTRLEN(hinfo->ipaddr.a_family));
197332b8d01aSChristopher Parker smb_tracef("msdcsLookupADS: %s [%s]", hinfo->name, ipstr);
19748d7e4166Sjose borrego
1975*b3700b07SGordon Ross (void) strlcpy(dci->dc_name, hinfo->name, sizeof (dci->dc_name));
1976*b3700b07SGordon Ross dci->dc_addr = hinfo->ipaddr;
19778d7e4166Sjose borrego
197829bd2886SAlan Wright free(hinfo);
1979*b3700b07SGordon Ross return (NT_STATUS_SUCCESS);
19808d7e4166Sjose borrego }
1981148c5f43SAlan Wright
1982148c5f43SAlan Wright static krb5_enctype *
smb_ads_get_enctypes(int dclevel,int * num)1983148c5f43SAlan Wright smb_ads_get_enctypes(int dclevel, int *num)
1984148c5f43SAlan Wright {
1985148c5f43SAlan Wright krb5_enctype *encptr;
1986148c5f43SAlan Wright
1987148c5f43SAlan Wright if (dclevel >= SMB_ADS_DCLEVEL_W2K8) {
1988148c5f43SAlan Wright *num = sizeof (w2k8enctypes) / sizeof (krb5_enctype);
1989148c5f43SAlan Wright encptr = w2k8enctypes;
1990148c5f43SAlan Wright } else {
1991148c5f43SAlan Wright *num = sizeof (pre_w2k8enctypes) / sizeof (krb5_enctype);
1992148c5f43SAlan Wright encptr = pre_w2k8enctypes;
1993148c5f43SAlan Wright }
1994148c5f43SAlan Wright
1995148c5f43SAlan Wright return (encptr);
1996148c5f43SAlan Wright }
1997