xref: /titanic_53/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c (revision b3700b074e637f8c6991b70754c88a2cfffb246b)
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