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.
231ed6b69aSGordon Ross * Copyright 2013 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>
50da6c28aaSamw
51da6c28aaSamw #include <smbsrv/libsmbns.h>
52da6c28aaSamw #include <smbns_dyndns.h>
53da6c28aaSamw #include <smbns_krb.h>
54da6c28aaSamw
5596a62adaSjoyce mcintosh #define SMB_ADS_AF_UNKNOWN(x) (((x)->ipaddr.a_family != AF_INET) && \
5696a62adaSjoyce mcintosh ((x)->ipaddr.a_family != AF_INET6))
5796a62adaSjoyce mcintosh
5829bd2886SAlan Wright #define SMB_ADS_MAXBUFLEN 100
593db3f65cSamw #define SMB_ADS_DN_MAX 300
603db3f65cSamw #define SMB_ADS_MAXMSGLEN 512
613db3f65cSamw #define SMB_ADS_COMPUTERS_CN "Computers"
623db3f65cSamw #define SMB_ADS_COMPUTER_NUM_ATTR 8
633db3f65cSamw #define SMB_ADS_SHARE_NUM_ATTR 3
643db3f65cSamw #define SMB_ADS_SITE_MAX MAXHOSTNAMELEN
653db3f65cSamw
663db3f65cSamw #define SMB_ADS_MSDCS_SRV_DC_RR "_ldap._tcp.dc._msdcs"
673db3f65cSamw #define SMB_ADS_MSDCS_SRV_SITE_RR "_ldap._tcp.%s._sites.dc._msdcs"
683db3f65cSamw
693db3f65cSamw /*
703db3f65cSamw * domainControllerFunctionality
713db3f65cSamw *
723db3f65cSamw * This rootDSE attribute indicates the functional level of the DC.
733db3f65cSamw */
743db3f65cSamw #define SMB_ADS_ATTR_DCLEVEL "domainControllerFunctionality"
753db3f65cSamw #define SMB_ADS_DCLEVEL_W2K 0
763db3f65cSamw #define SMB_ADS_DCLEVEL_W2K3 2
773db3f65cSamw #define SMB_ADS_DCLEVEL_W2K8 3
78b1352070SAlan Wright #define SMB_ADS_DCLEVEL_W2K8_R2 4
793db3f65cSamw
803db3f65cSamw /*
813db3f65cSamw * msDs-supportedEncryptionTypes (Windows Server 2008 only)
823db3f65cSamw *
833db3f65cSamw * This attribute defines the encryption types supported by the system.
843db3f65cSamw * Encryption Types:
853db3f65cSamw * - DES cbc mode with CRC-32
863db3f65cSamw * - DES cbc mode with RSA-MD5
873db3f65cSamw * - ArcFour with HMAC/md5
883db3f65cSamw * - AES-128
893db3f65cSamw * - AES-256
903db3f65cSamw */
913db3f65cSamw #define SMB_ADS_ATTR_ENCTYPES "msDs-supportedEncryptionTypes"
923db3f65cSamw #define SMB_ADS_ENC_DES_CRC 1
933db3f65cSamw #define SMB_ADS_ENC_DES_MD5 2
943db3f65cSamw #define SMB_ADS_ENC_RC4 4
953db3f65cSamw #define SMB_ADS_ENC_AES128 8
963db3f65cSamw #define SMB_ADS_ENC_AES256 16
973db3f65cSamw
98148c5f43SAlan Wright static krb5_enctype w2k8enctypes[] = {
99148c5f43SAlan Wright ENCTYPE_AES256_CTS_HMAC_SHA1_96,
100148c5f43SAlan Wright ENCTYPE_AES128_CTS_HMAC_SHA1_96,
101148c5f43SAlan Wright ENCTYPE_ARCFOUR_HMAC,
102148c5f43SAlan Wright ENCTYPE_DES_CBC_CRC,
103148c5f43SAlan Wright ENCTYPE_DES_CBC_MD5,
104148c5f43SAlan Wright };
105148c5f43SAlan Wright
106148c5f43SAlan Wright static krb5_enctype pre_w2k8enctypes[] = {
107148c5f43SAlan Wright ENCTYPE_ARCFOUR_HMAC,
108148c5f43SAlan Wright ENCTYPE_DES_CBC_CRC,
109148c5f43SAlan Wright ENCTYPE_DES_CBC_MD5,
110148c5f43SAlan Wright };
111148c5f43SAlan Wright
1123db3f65cSamw #define SMB_ADS_ATTR_SAMACCT "sAMAccountName"
1133db3f65cSamw #define SMB_ADS_ATTR_UPN "userPrincipalName"
1143db3f65cSamw #define SMB_ADS_ATTR_SPN "servicePrincipalName"
1153db3f65cSamw #define SMB_ADS_ATTR_CTL "userAccountControl"
1163db3f65cSamw #define SMB_ADS_ATTR_DNSHOST "dNSHostName"
1173db3f65cSamw #define SMB_ADS_ATTR_KVNO "msDS-KeyVersionNumber"
118c8ec8eeaSjose borrego #define SMB_ADS_ATTR_DN "distinguishedName"
119da6c28aaSamw
120b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
12129bd2886SAlan Wright * UserAccountControl flags: manipulate user account properties.
12229bd2886SAlan Wright *
12329bd2886SAlan Wright * The hexadecimal value of the following property flags are based on MSDN
12429bd2886SAlan Wright * article # 305144.
12529bd2886SAlan Wright */
12629bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_SCRIPT 0x00000001
12729bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_ACCOUNTDISABLE 0x00000002
12829bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_HOMEDIR_REQUIRED 0x00000008
12929bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_LOCKOUT 0x00000010
13029bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_PASSWD_NOTREQD 0x00000020
13129bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_PASSWD_CANT_CHANGE 0x00000040
13229bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_ENCRYPTED_TEXT_PWD_ALLOWED 0x00000080
13329bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_TMP_DUP_ACCT 0x00000100
13429bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_NORMAL_ACCT 0x00000200
13529bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_INTERDOMAIN_TRUST_ACCT 0x00000800
13629bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT 0x00001000
13729bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_SRV_TRUST_ACCT 0x00002000
13829bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD 0x00010000
13929bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_MNS_LOGON_ACCT 0x00020000
14029bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_SMARTCARD_REQUIRED 0x00040000
14129bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION 0x00080000
14229bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_NOT_DELEGATED 0x00100000
14329bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_USE_DES_KEY_ONLY 0x00200000
14429bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_DONT_REQ_PREAUTH 0x00400000
14529bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_PASSWD_EXPIRED 0x00800000
14629bd2886SAlan Wright #define SMB_ADS_USER_ACCT_CTL_TRUSTED_TO_AUTH_FOR_DELEGATION 0x01000000
14729bd2886SAlan Wright
14829bd2886SAlan Wright /*
149b89a8333Snatalie li - Sun Microsystems - Irvine United States * Length of "dc=" prefix.
150b89a8333Snatalie li - Sun Microsystems - Irvine United States */
151b89a8333Snatalie li - Sun Microsystems - Irvine United States #define SMB_ADS_DN_PREFIX_LEN 3
152b89a8333Snatalie li - Sun Microsystems - Irvine United States
1537f667e74Sjose borrego static char *smb_ads_computer_objcls[] = {
1547f667e74Sjose borrego "top", "person", "organizationalPerson",
1557f667e74Sjose borrego "user", "computer", NULL
1567f667e74Sjose borrego };
1577f667e74Sjose borrego
1587f667e74Sjose borrego static char *smb_ads_share_objcls[] = {
1597f667e74Sjose borrego "top", "leaf", "connectionPoint", "volume", NULL
1607f667e74Sjose borrego };
1617f667e74Sjose borrego
162b89a8333Snatalie li - Sun Microsystems - Irvine United States /* Cached ADS server to communicate with */
163b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_info_t *smb_ads_cached_host_info = NULL;
164b89a8333Snatalie li - Sun Microsystems - Irvine United States static mutex_t smb_ads_cached_host_mtx;
165b89a8333Snatalie li - Sun Microsystems - Irvine United States
16629bd2886SAlan Wright /*
16729bd2886SAlan Wright * SMB ADS config cache is maintained to facilitate the detection of
16829bd2886SAlan Wright * changes in configuration that is relevant to AD selection.
16929bd2886SAlan Wright */
17029bd2886SAlan Wright typedef struct smb_ads_config {
17129bd2886SAlan Wright char c_site[SMB_ADS_SITE_MAX];
17229bd2886SAlan Wright smb_inaddr_t c_pdc;
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
198c8ec8eeaSjose borrego static smb_ads_handle_t *smb_ads_open_main(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 *);
210c8ec8eeaSjose borrego static smb_ads_host_info_t *smb_ads_select_dc(smb_ads_host_list_t *);
211b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_find_computer(smb_ads_handle_t *, char *);
212b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_getattr(LDAP *, LDAPMessage *,
213b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *);
214b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t smb_ads_get_qstat(smb_ads_handle_t *, LDAPMessage *,
215b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *);
21629bd2886SAlan Wright static boolean_t smb_ads_match_pdc(smb_ads_host_info_t *);
21729bd2886SAlan Wright static boolean_t smb_ads_is_sought_host(smb_ads_host_info_t *, char *);
21829bd2886SAlan Wright static boolean_t smb_ads_is_same_domain(char *, char *);
21929bd2886SAlan Wright static boolean_t smb_ads_is_pdc_configured(void);
22029bd2886SAlan Wright static smb_ads_host_info_t *smb_ads_dup_host_info(smb_ads_host_info_t *);
221fe1c642dSBill Krier static char *smb_ads_get_sharedn(const char *, const char *, const char *);
222148c5f43SAlan Wright static krb5_enctype *smb_ads_get_enctypes(int, int *);
223dc20a302Sas200622
224dc20a302Sas200622 /*
2253db3f65cSamw * smb_ads_init
226dc20a302Sas200622 *
22729bd2886SAlan Wright * Initializes the ADS config cache.
228dc20a302Sas200622 */
229dc20a302Sas200622 void
smb_ads_init(void)2303db3f65cSamw smb_ads_init(void)
231dc20a302Sas200622 {
23229bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
233b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_config_getstr(SMB_CI_ADS_SITE,
23429bd2886SAlan Wright smb_ads_cfg.c_site, SMB_ADS_SITE_MAX);
23529bd2886SAlan Wright (void) smb_config_getip(SMB_CI_DOMAIN_SRV, &smb_ads_cfg.c_pdc);
23629bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
23729bd2886SAlan Wright }
23829bd2886SAlan Wright
23929bd2886SAlan Wright void
smb_ads_fini(void)24029bd2886SAlan Wright smb_ads_fini(void)
24129bd2886SAlan Wright {
24229bd2886SAlan Wright smb_ads_free_cached_host();
243dc20a302Sas200622 }
244dc20a302Sas200622
245dc20a302Sas200622 /*
2463db3f65cSamw * smb_ads_refresh
247dc20a302Sas200622 *
24829bd2886SAlan Wright * This function will be called when smb/server SMF service is refreshed.
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(void)2533db3f65cSamw smb_ads_refresh(void)
254dc20a302Sas200622 {
2553db3f65cSamw char new_site[SMB_ADS_SITE_MAX];
25629bd2886SAlan Wright smb_inaddr_t new_pdc;
25729bd2886SAlan Wright boolean_t purge = B_FALSE;
258dc20a302Sas200622
25929bd2886SAlan Wright (void) smb_config_getstr(SMB_CI_ADS_SITE, new_site, SMB_ADS_SITE_MAX);
26029bd2886SAlan Wright (void) smb_config_getip(SMB_CI_DOMAIN_SRV, &new_pdc);
26129bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
262bbf6f00cSJordan Brown if (smb_strcasecmp(smb_ads_cfg.c_site, new_site, 0)) {
26329bd2886SAlan Wright (void) strlcpy(smb_ads_cfg.c_site, new_site, SMB_ADS_SITE_MAX);
26429bd2886SAlan Wright purge = B_TRUE;
26529bd2886SAlan Wright }
26629bd2886SAlan Wright
26729bd2886SAlan Wright smb_ads_cfg.c_pdc = new_pdc;
26829bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
26929bd2886SAlan Wright
27029bd2886SAlan Wright (void) mutex_lock(&smb_ads_cached_host_mtx);
27129bd2886SAlan Wright if (smb_ads_cached_host_info &&
27229bd2886SAlan Wright smb_ads_is_pdc_configured() &&
27329bd2886SAlan Wright !smb_ads_match_pdc(smb_ads_cached_host_info))
27429bd2886SAlan Wright purge = B_TRUE;
27529bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
27629bd2886SAlan Wright
27729bd2886SAlan Wright if (purge)
278b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
279dc20a302Sas200622 }
28029bd2886SAlan Wright
28129bd2886SAlan Wright
28229bd2886SAlan Wright
28329bd2886SAlan Wright static boolean_t
smb_ads_is_pdc_configured(void)28429bd2886SAlan Wright smb_ads_is_pdc_configured(void)
28529bd2886SAlan Wright {
28629bd2886SAlan Wright boolean_t configured;
28729bd2886SAlan Wright
28829bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
28929bd2886SAlan Wright configured = !smb_inet_iszero(&smb_ads_cfg.c_pdc);
29029bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
29129bd2886SAlan Wright
29229bd2886SAlan Wright return (configured);
293dc20a302Sas200622 }
294da6c28aaSamw
295da6c28aaSamw /*
2963db3f65cSamw * smb_ads_build_unc_name
297da6c28aaSamw *
298da6c28aaSamw * Construct the UNC name of the share object in the format of
299da6c28aaSamw * \\hostname.domain\shareUNC
300da6c28aaSamw *
301da6c28aaSamw * Returns 0 on success, -1 on error.
302da6c28aaSamw */
303da6c28aaSamw int
smb_ads_build_unc_name(char * unc_name,int maxlen,const char * hostname,const char * shareUNC)3043db3f65cSamw smb_ads_build_unc_name(char *unc_name, int maxlen,
305da6c28aaSamw const char *hostname, const char *shareUNC)
306da6c28aaSamw {
307dc20a302Sas200622 char my_domain[MAXHOSTNAMELEN];
308da6c28aaSamw
309dc20a302Sas200622 if (smb_getfqdomainname(my_domain, sizeof (my_domain)) != 0)
310da6c28aaSamw return (-1);
311da6c28aaSamw
312da6c28aaSamw (void) snprintf(unc_name, maxlen, "\\\\%s.%s\\%s",
313da6c28aaSamw hostname, my_domain, shareUNC);
314da6c28aaSamw return (0);
315da6c28aaSamw }
316da6c28aaSamw
317da6c28aaSamw /*
318c8ec8eeaSjose borrego * smb_ads_ldap_ping
3193db3f65cSamw *
320c8ec8eeaSjose borrego * This is used to bind to an ADS server to see
321c8ec8eeaSjose borrego * if it is still alive.
322c8ec8eeaSjose borrego *
323da6c28aaSamw * Returns:
324da6c28aaSamw * -1: error
325da6c28aaSamw * 0: successful
326da6c28aaSamw */
327da6c28aaSamw /*ARGSUSED*/
328da6c28aaSamw static int
smb_ads_ldap_ping(smb_ads_host_info_t * ads_host)329c8ec8eeaSjose borrego smb_ads_ldap_ping(smb_ads_host_info_t *ads_host)
330da6c28aaSamw {
331c8ec8eeaSjose borrego int ldversion = LDAP_VERSION3, status, timeoutms = 5 * 1000;
332c8ec8eeaSjose borrego LDAP *ld = NULL;
333c8ec8eeaSjose borrego
3347f667e74Sjose borrego ld = ldap_init(ads_host->name, ads_host->port);
335c8ec8eeaSjose borrego if (ld == NULL)
336c8ec8eeaSjose borrego return (-1);
337c8ec8eeaSjose borrego
338c8ec8eeaSjose borrego ldversion = LDAP_VERSION3;
339c8ec8eeaSjose borrego (void) ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion);
340c8ec8eeaSjose borrego /* setup TCP/IP connect timeout */
341c8ec8eeaSjose borrego (void) ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms);
342c8ec8eeaSjose borrego
343c8ec8eeaSjose borrego status = ldap_bind_s(ld, "", NULL, LDAP_AUTH_SIMPLE);
344c8ec8eeaSjose borrego
345c8ec8eeaSjose borrego if (status != LDAP_SUCCESS) {
346c8ec8eeaSjose borrego (void) ldap_unbind(ld);
347c8ec8eeaSjose borrego return (-1);
348c8ec8eeaSjose borrego }
349c8ec8eeaSjose borrego
350c8ec8eeaSjose borrego (void) ldap_unbind(ld);
351c8ec8eeaSjose borrego
352da6c28aaSamw return (0);
353da6c28aaSamw }
354da6c28aaSamw
355da6c28aaSamw /*
35629bd2886SAlan Wright * The cached ADS host is no longer valid if one of the following criteria
35729bd2886SAlan Wright * is satisfied:
358b89a8333Snatalie li - Sun Microsystems - Irvine United States *
35929bd2886SAlan Wright * 1) not in the specified domain
36029bd2886SAlan Wright * 2) not the sought host (if specified)
36129bd2886SAlan Wright * 3) not reachable
36229bd2886SAlan Wright *
36329bd2886SAlan Wright * The caller is responsible for acquiring the smb_ads_cached_host_mtx lock
36429bd2886SAlan Wright * prior to calling this function.
36529bd2886SAlan Wright *
36629bd2886SAlan Wright * Return B_TRUE if the cache host is still valid. Otherwise, return B_FALSE.
367da6c28aaSamw */
36829bd2886SAlan Wright static boolean_t
smb_ads_validate_cache_host(char * domain,char * srv)36929bd2886SAlan Wright smb_ads_validate_cache_host(char *domain, char *srv)
370da6c28aaSamw {
371b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!smb_ads_cached_host_info)
37229bd2886SAlan Wright return (B_FALSE);
37329bd2886SAlan Wright
37429bd2886SAlan Wright if (!smb_ads_is_same_domain(smb_ads_cached_host_info->name, domain))
37529bd2886SAlan Wright return (B_FALSE);
37629bd2886SAlan Wright
37729bd2886SAlan Wright if (smb_ads_ldap_ping(smb_ads_cached_host_info) == 0) {
37829bd2886SAlan Wright if (!srv)
37929bd2886SAlan Wright return (B_TRUE);
38029bd2886SAlan Wright
38129bd2886SAlan Wright if (smb_ads_is_sought_host(smb_ads_cached_host_info, srv))
38229bd2886SAlan Wright return (B_TRUE);
383da6c28aaSamw }
384da6c28aaSamw
38529bd2886SAlan Wright return (B_FALSE);
386da6c28aaSamw }
3873db3f65cSamw
388da6c28aaSamw /*
389b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_is_sought_host
390b89a8333Snatalie li - Sun Microsystems - Irvine United States *
391b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns true, if the sought host name matches the input host (host) name.
392b89a8333Snatalie li - Sun Microsystems - Irvine United States * The sought host is expected to be in Fully Qualified Domain Name (FQDN)
393b89a8333Snatalie li - Sun Microsystems - Irvine United States * format.
394b89a8333Snatalie li - Sun Microsystems - Irvine United States */
395b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t
smb_ads_is_sought_host(smb_ads_host_info_t * host,char * sought_host_name)396b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_is_sought_host(smb_ads_host_info_t *host, char *sought_host_name)
397b89a8333Snatalie li - Sun Microsystems - Irvine United States {
398b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((host == NULL) || (sought_host_name == NULL))
399b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
400b89a8333Snatalie li - Sun Microsystems - Irvine United States
401bbf6f00cSJordan Brown if (smb_strcasecmp(host->name, sought_host_name, 0))
402b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
403b89a8333Snatalie li - Sun Microsystems - Irvine United States
404b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_TRUE);
405b89a8333Snatalie li - Sun Microsystems - Irvine United States }
406b89a8333Snatalie li - Sun Microsystems - Irvine United States
407b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
408b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_match_hosts_same_domain
409b89a8333Snatalie li - Sun Microsystems - Irvine United States *
410b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns true, if the cached ADS host is in the same domain as the
411b89a8333Snatalie li - Sun Microsystems - Irvine United States * current (given) domain.
412b89a8333Snatalie li - Sun Microsystems - Irvine United States */
413b89a8333Snatalie li - Sun Microsystems - Irvine United States static boolean_t
smb_ads_is_same_domain(char * cached_host_name,char * current_domain)414b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_is_same_domain(char *cached_host_name, char *current_domain)
415b89a8333Snatalie li - Sun Microsystems - Irvine United States {
416b89a8333Snatalie li - Sun Microsystems - Irvine United States char *cached_host_domain;
417b89a8333Snatalie li - Sun Microsystems - Irvine United States
418b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((cached_host_name == NULL) || (current_domain == NULL))
419b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
420b89a8333Snatalie li - Sun Microsystems - Irvine United States
421b89a8333Snatalie li - Sun Microsystems - Irvine United States cached_host_domain = strchr(cached_host_name, '.');
422b89a8333Snatalie li - Sun Microsystems - Irvine United States if (cached_host_domain == NULL)
423b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
424b89a8333Snatalie li - Sun Microsystems - Irvine United States
425b89a8333Snatalie li - Sun Microsystems - Irvine United States ++cached_host_domain;
426bbf6f00cSJordan Brown if (smb_strcasecmp(cached_host_domain, current_domain, 0))
427b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_FALSE);
428b89a8333Snatalie li - Sun Microsystems - Irvine United States
429b89a8333Snatalie li - Sun Microsystems - Irvine United States return (B_TRUE);
430b89a8333Snatalie li - Sun Microsystems - Irvine United States }
431b89a8333Snatalie li - Sun Microsystems - Irvine United States
432b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
4333db3f65cSamw * smb_ads_skip_ques_sec
4343db3f65cSamw * Skips the question section.
4353db3f65cSamw */
4363db3f65cSamw static int
smb_ads_skip_ques_sec(int qcnt,uchar_t ** ptr,uchar_t * eom)4373db3f65cSamw smb_ads_skip_ques_sec(int qcnt, uchar_t **ptr, uchar_t *eom)
4383db3f65cSamw {
4393db3f65cSamw int i, len;
4403db3f65cSamw
4413db3f65cSamw for (i = 0; i < qcnt; i++) {
442b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((len = dn_skipname(*ptr, eom)) < 0)
4433db3f65cSamw return (-1);
444b89a8333Snatalie li - Sun Microsystems - Irvine United States
4453db3f65cSamw *ptr += len + QFIXEDSZ;
4463db3f65cSamw }
4473db3f65cSamw
4483db3f65cSamw return (0);
4493db3f65cSamw }
4503db3f65cSamw
4513db3f65cSamw /*
4523db3f65cSamw * smb_ads_decode_host_ans_sec
453c8ec8eeaSjose borrego * Decodes ADS hosts, priority, weight and port number from the answer
454c8ec8eeaSjose borrego * section based on the current buffer pointer.
4553db3f65cSamw */
4563db3f65cSamw static int
smb_ads_decode_host_ans_sec(int ans_cnt,uchar_t ** ptr,uchar_t * eom,uchar_t * buf,smb_ads_host_info_t * ads_host_list)4573db3f65cSamw smb_ads_decode_host_ans_sec(int ans_cnt, uchar_t **ptr, uchar_t *eom,
4583db3f65cSamw uchar_t *buf, smb_ads_host_info_t *ads_host_list)
4593db3f65cSamw {
4603db3f65cSamw int i, len;
4613db3f65cSamw smb_ads_host_info_t *ads_host;
4623db3f65cSamw
4633db3f65cSamw for (i = 0; i < ans_cnt; i++) {
4643db3f65cSamw ads_host = &ads_host_list[i];
4653db3f65cSamw
466b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((len = dn_skipname(*ptr, eom)) < 0)
4673db3f65cSamw return (-1);
468b89a8333Snatalie li - Sun Microsystems - Irvine United States
4693db3f65cSamw
4703db3f65cSamw *ptr += len;
4713db3f65cSamw
4723db3f65cSamw /* skip type, class, ttl */
4733db3f65cSamw *ptr += 8;
4743db3f65cSamw /* data size */
4753db3f65cSamw *ptr += 2;
4763db3f65cSamw
477c8ec8eeaSjose borrego /* Get priority, weight */
478c8ec8eeaSjose borrego /* LINTED: E_CONSTANT_CONDITION */
479c8ec8eeaSjose borrego NS_GET16(ads_host->priority, *ptr);
480c8ec8eeaSjose borrego /* LINTED: E_CONSTANT_CONDITION */
481c8ec8eeaSjose borrego NS_GET16(ads_host->weight, *ptr);
482c8ec8eeaSjose borrego
4833db3f65cSamw /* port */
4843db3f65cSamw /* LINTED: E_CONSTANT_CONDITION */
4853db3f65cSamw NS_GET16(ads_host->port, *ptr);
4863db3f65cSamw /* domain name */
4873db3f65cSamw len = dn_expand(buf, eom, *ptr, ads_host->name, MAXHOSTNAMELEN);
488b89a8333Snatalie li - Sun Microsystems - Irvine United States if (len < 0)
4893db3f65cSamw return (-1);
490b89a8333Snatalie li - Sun Microsystems - Irvine United States
4913db3f65cSamw *ptr += len;
4923db3f65cSamw }
4933db3f65cSamw
4943db3f65cSamw return (0);
4953db3f65cSamw }
4963db3f65cSamw
4973db3f65cSamw /*
4983db3f65cSamw * smb_ads_skip_auth_sec
4993db3f65cSamw * Skips the authority section.
5003db3f65cSamw */
5013db3f65cSamw static int
smb_ads_skip_auth_sec(int ns_cnt,uchar_t ** ptr,uchar_t * eom)5023db3f65cSamw smb_ads_skip_auth_sec(int ns_cnt, uchar_t **ptr, uchar_t *eom)
5033db3f65cSamw {
5043db3f65cSamw int i, len;
5053db3f65cSamw uint16_t size;
5063db3f65cSamw
5073db3f65cSamw for (i = 0; i < ns_cnt; i++) {
508b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((len = dn_skipname(*ptr, eom)) < 0)
5093db3f65cSamw return (-1);
510b89a8333Snatalie li - Sun Microsystems - Irvine United States
5113db3f65cSamw *ptr += len;
5123db3f65cSamw /* skip type, class, ttl */
5133db3f65cSamw *ptr += 8;
5143db3f65cSamw /* get len of data */
5153db3f65cSamw /* LINTED: E_CONSTANT_CONDITION */
5163db3f65cSamw NS_GET16(size, *ptr);
517b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((*ptr + size) > eom)
5183db3f65cSamw return (-1);
5193db3f65cSamw
5203db3f65cSamw *ptr += size;
5213db3f65cSamw }
5223db3f65cSamw
5233db3f65cSamw return (0);
5243db3f65cSamw }
5253db3f65cSamw
5263db3f65cSamw /*
527b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_decode_host_ip
528b89a8333Snatalie li - Sun Microsystems - Irvine United States *
5293db3f65cSamw * Decodes ADS hosts and IP Addresses from the additional section based
5303db3f65cSamw * on the current buffer pointer.
5313db3f65cSamw */
5323db3f65cSamw static int
smb_ads_decode_host_ip(int addit_cnt,int ans_cnt,uchar_t ** ptr,uchar_t * eom,uchar_t * buf,smb_ads_host_info_t * ads_host_list)533b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_decode_host_ip(int addit_cnt, int ans_cnt, uchar_t **ptr,
534b89a8333Snatalie li - Sun Microsystems - Irvine United States uchar_t *eom, uchar_t *buf, smb_ads_host_info_t *ads_host_list)
5353db3f65cSamw {
536b89a8333Snatalie li - Sun Microsystems - Irvine United States int i, j, len;
5377f667e74Sjose borrego smb_inaddr_t ipaddr;
538b89a8333Snatalie li - Sun Microsystems - Irvine United States char hostname[MAXHOSTNAMELEN];
539b89a8333Snatalie li - Sun Microsystems - Irvine United States char *name;
5407f667e74Sjose borrego uint16_t size = 0;
5413db3f65cSamw
5423db3f65cSamw for (i = 0; i < addit_cnt; i++) {
5433db3f65cSamw
5443db3f65cSamw /* domain name */
545b89a8333Snatalie li - Sun Microsystems - Irvine United States len = dn_expand(buf, eom, *ptr, hostname, MAXHOSTNAMELEN);
546b89a8333Snatalie li - Sun Microsystems - Irvine United States if (len < 0)
5473db3f65cSamw return (-1);
548b89a8333Snatalie li - Sun Microsystems - Irvine United States
5493db3f65cSamw *ptr += len;
5503db3f65cSamw
5513db3f65cSamw /* skip type, class, TTL, data len */
5527f667e74Sjose borrego *ptr += 8;
5533db3f65cSamw /* LINTED: E_CONSTANT_CONDITION */
5547f667e74Sjose borrego NS_GET16(size, *ptr);
5557f667e74Sjose borrego
556*b819cea2SGordon Ross if (size == NS_INADDRSZ) {
5577f667e74Sjose borrego /* LINTED: E_CONSTANT_CONDITION */
5587f667e74Sjose borrego NS_GET32(ipaddr.a_ipv4, *ptr);
5597f667e74Sjose borrego ipaddr.a_ipv4 = htonl(ipaddr.a_ipv4);
5607f667e74Sjose borrego ipaddr.a_family = AF_INET;
561*b819cea2SGordon Ross } else if (size == NS_IN6ADDRSZ) {
5627f667e74Sjose borrego #ifdef BIG_ENDIAN
563*b819cea2SGordon Ross bcopy(*ptr, &ipaddr.a_ipv6, NS_IN6ADDRSZ);
5647f667e74Sjose borrego #else
565*b819cea2SGordon Ross for (i = 0; i < NS_IN6ADDRSZ; i++)
5667f667e74Sjose borrego (uint8_t *)(ipaddr.a_ipv6)
567*b819cea2SGordon Ross [NS_IN6ADDRSZ-1-i] = *(*ptr+i);
5687f667e74Sjose borrego #endif
5697f667e74Sjose borrego ipaddr.a_family = AF_INET6;
570c5866007SKeyur Desai *ptr += size;
5717f667e74Sjose borrego }
5723db3f65cSamw
573b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
574b89a8333Snatalie li - Sun Microsystems - Irvine United States * find the host in the list of DC records from
575b89a8333Snatalie li - Sun Microsystems - Irvine United States * the answer section, that matches the host in the
576b89a8333Snatalie li - Sun Microsystems - Irvine United States * additional section, and set its IP address.
577b89a8333Snatalie li - Sun Microsystems - Irvine United States */
578b89a8333Snatalie li - Sun Microsystems - Irvine United States for (j = 0; j < ans_cnt; j++) {
579b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((name = ads_host_list[j].name) == NULL)
580b89a8333Snatalie li - Sun Microsystems - Irvine United States continue;
581bbf6f00cSJordan Brown if (smb_strcasecmp(name, hostname, 0) == 0) {
5827f667e74Sjose borrego ads_host_list[j].ipaddr = ipaddr;
583b89a8333Snatalie li - Sun Microsystems - Irvine United States }
5843db3f65cSamw }
5857f667e74Sjose borrego }
5863db3f65cSamw return (0);
5873db3f65cSamw }
5883db3f65cSamw
589b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
590b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_dup_host_info
591b89a8333Snatalie li - Sun Microsystems - Irvine United States *
592b89a8333Snatalie li - Sun Microsystems - Irvine United States * Duplicates the passed smb_ads_host_info_t structure.
593b89a8333Snatalie li - Sun Microsystems - Irvine United States * Caller must free memory allocated by this method.
594b89a8333Snatalie li - Sun Microsystems - Irvine United States *
595b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns a reference to the duplicated smb_ads_host_info_t structure.
596b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns NULL on error.
597b89a8333Snatalie li - Sun Microsystems - Irvine United States */
598b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_info_t *
smb_ads_dup_host_info(smb_ads_host_info_t * ads_host)599b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_dup_host_info(smb_ads_host_info_t *ads_host)
6003db3f65cSamw {
601b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *dup_host;
602b89a8333Snatalie li - Sun Microsystems - Irvine United States
603b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ads_host == NULL)
604b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
605b89a8333Snatalie li - Sun Microsystems - Irvine United States
606b89a8333Snatalie li - Sun Microsystems - Irvine United States dup_host = malloc(sizeof (smb_ads_host_info_t));
607b89a8333Snatalie li - Sun Microsystems - Irvine United States
608b89a8333Snatalie li - Sun Microsystems - Irvine United States if (dup_host != NULL)
609b89a8333Snatalie li - Sun Microsystems - Irvine United States bcopy(ads_host, dup_host, sizeof (smb_ads_host_info_t));
610b89a8333Snatalie li - Sun Microsystems - Irvine United States
611b89a8333Snatalie li - Sun Microsystems - Irvine United States return (dup_host);
612c8ec8eeaSjose borrego }
6133db3f65cSamw
614c8ec8eeaSjose borrego /*
615c8ec8eeaSjose borrego * smb_ads_hlist_alloc
616c8ec8eeaSjose borrego */
617a0aa776eSAlan Wright static smb_ads_host_list_t *
smb_ads_hlist_alloc(int count)618c8ec8eeaSjose borrego smb_ads_hlist_alloc(int count)
619c8ec8eeaSjose borrego {
620c8ec8eeaSjose borrego int size;
621c8ec8eeaSjose borrego smb_ads_host_list_t *hlist;
622c8ec8eeaSjose borrego
623b89a8333Snatalie li - Sun Microsystems - Irvine United States if (count == 0)
624b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
625b89a8333Snatalie li - Sun Microsystems - Irvine United States
626c8ec8eeaSjose borrego size = sizeof (smb_ads_host_info_t) * count;
627c8ec8eeaSjose borrego hlist = (smb_ads_host_list_t *)malloc(sizeof (smb_ads_host_list_t));
628c8ec8eeaSjose borrego if (hlist == NULL)
629c8ec8eeaSjose borrego return (NULL);
630c8ec8eeaSjose borrego
631c8ec8eeaSjose borrego hlist->ah_cnt = count;
632c8ec8eeaSjose borrego hlist->ah_list = (smb_ads_host_info_t *)malloc(size);
633c8ec8eeaSjose borrego if (hlist->ah_list == NULL) {
634c8ec8eeaSjose borrego free(hlist);
635c8ec8eeaSjose borrego return (NULL);
636c8ec8eeaSjose borrego }
637c8ec8eeaSjose borrego
638c8ec8eeaSjose borrego bzero(hlist->ah_list, size);
639c8ec8eeaSjose borrego return (hlist);
640c8ec8eeaSjose borrego }
641c8ec8eeaSjose borrego
642c8ec8eeaSjose borrego /*
643c8ec8eeaSjose borrego * smb_ads_hlist_free
644c8ec8eeaSjose borrego */
645c8ec8eeaSjose borrego static void
smb_ads_hlist_free(smb_ads_host_list_t * host_list)646c8ec8eeaSjose borrego smb_ads_hlist_free(smb_ads_host_list_t *host_list)
647c8ec8eeaSjose borrego {
648c8ec8eeaSjose borrego if (host_list == NULL)
649c8ec8eeaSjose borrego return;
650c8ec8eeaSjose borrego
651c8ec8eeaSjose borrego free(host_list->ah_list);
652c8ec8eeaSjose borrego free(host_list);
6533db3f65cSamw }
6543db3f65cSamw
6553db3f65cSamw /*
656b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_query_dns_server
657c8ec8eeaSjose borrego *
6583db3f65cSamw * This routine sends a DNS service location (SRV) query message to the
6593db3f65cSamw * DNS server via TCP to query it for a list of ADS server(s). Once a reply
660b89a8333Snatalie li - Sun Microsystems - Irvine United States * is received, the reply message is parsed to get the hostname. If there are IP
6613db3f65cSamw * addresses populated in the additional section then the additional section
6623db3f65cSamw * is parsed to obtain the IP addresses.
663da6c28aaSamw *
664da6c28aaSamw * The service location of _ldap._tcp.dc.msdcs.<ADS domain> is used to
665da6c28aaSamw * guarantee that Microsoft domain controllers are returned. Microsoft domain
666da6c28aaSamw * controllers are also ADS servers.
667da6c28aaSamw *
668da6c28aaSamw * The ADS hostnames are stored in the answer section of the DNS reply message.
6693db3f65cSamw * The IP addresses are stored in the additional section.
670da6c28aaSamw *
671da6c28aaSamw * The DNS reply message may be in compress formed. The compression is done
672da6c28aaSamw * on repeating domain name label in the message. i.e hostname.
673c8ec8eeaSjose borrego *
674b89a8333Snatalie li - Sun Microsystems - Irvine United States * Upon successful completion, host list of ADS server(s) is returned.
675da6c28aaSamw */
676b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_list_t *
smb_ads_query_dns_server(char * domain,char * msdcs_svc_name)677b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_query_dns_server(char *domain, char *msdcs_svc_name)
678da6c28aaSamw {
679b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_list_t *hlist = NULL;
6803db3f65cSamw int len, qcnt, ans_cnt, ns_cnt, addit_cnt;
6813db3f65cSamw uchar_t *ptr, *eom;
6823db3f65cSamw struct __res_state res_state;
6833db3f65cSamw union {
6843db3f65cSamw HEADER hdr;
6853db3f65cSamw uchar_t buf[NS_MAXMSG];
6863db3f65cSamw } msg;
687faa1795aSjb150015
6883db3f65cSamw bzero(&res_state, sizeof (struct __res_state));
6893db3f65cSamw if (res_ninit(&res_state) < 0)
690da6c28aaSamw return (NULL);
691da6c28aaSamw
6923db3f65cSamw /* use TCP */
6933db3f65cSamw res_state.options |= RES_USEVC;
694da6c28aaSamw
695b89a8333Snatalie li - Sun Microsystems - Irvine United States len = res_nquerydomain(&res_state, msdcs_svc_name, domain,
6963db3f65cSamw C_IN, T_SRV, msg.buf, sizeof (msg.buf));
6973db3f65cSamw
6983db3f65cSamw if (len < 0) {
699fc724630SAlan Wright syslog(LOG_NOTICE, "DNS query for %s failed: %s",
700b89a8333Snatalie li - Sun Microsystems - Irvine United States msdcs_svc_name, hstrerror(res_state.res_h_errno));
701b89a8333Snatalie li - Sun Microsystems - Irvine United States res_ndestroy(&res_state);
702b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
7033db3f65cSamw }
704b89a8333Snatalie li - Sun Microsystems - Irvine United States
7053db3f65cSamw if (len > sizeof (msg.buf)) {
706fc724630SAlan Wright syslog(LOG_NOTICE,
707fc724630SAlan Wright "DNS query for %s failed: too big", msdcs_svc_name);
708b89a8333Snatalie li - Sun Microsystems - Irvine United States res_ndestroy(&res_state);
709b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
7103db3f65cSamw }
7113db3f65cSamw
712b89a8333Snatalie li - Sun Microsystems - Irvine United States /* parse the reply, skip header and question sections */
7133db3f65cSamw ptr = msg.buf + sizeof (msg.hdr);
7143db3f65cSamw eom = msg.buf + len;
7153db3f65cSamw
7163db3f65cSamw /* check truncated message bit */
7173db3f65cSamw if (msg.hdr.tc)
718fc724630SAlan Wright syslog(LOG_NOTICE,
719fc724630SAlan Wright "DNS query for %s failed: truncated", msdcs_svc_name);
7203db3f65cSamw
7213db3f65cSamw qcnt = ntohs(msg.hdr.qdcount);
7223db3f65cSamw ans_cnt = ntohs(msg.hdr.ancount);
7233db3f65cSamw ns_cnt = ntohs(msg.hdr.nscount);
7243db3f65cSamw addit_cnt = ntohs(msg.hdr.arcount);
7253db3f65cSamw
7263db3f65cSamw if (smb_ads_skip_ques_sec(qcnt, &ptr, eom) != 0) {
7273db3f65cSamw res_ndestroy(&res_state);
728da6c28aaSamw return (NULL);
729da6c28aaSamw }
730da6c28aaSamw
731b89a8333Snatalie li - Sun Microsystems - Irvine United States hlist = smb_ads_hlist_alloc(ans_cnt);
732b89a8333Snatalie li - Sun Microsystems - Irvine United States if (hlist == NULL) {
7333db3f65cSamw res_ndestroy(&res_state);
734da6c28aaSamw return (NULL);
735da6c28aaSamw }
736da6c28aaSamw
737b89a8333Snatalie li - Sun Microsystems - Irvine United States /* walk through the answer section */
7383db3f65cSamw if (smb_ads_decode_host_ans_sec(ans_cnt, &ptr, eom, msg.buf,
739b89a8333Snatalie li - Sun Microsystems - Irvine United States hlist->ah_list) != 0) {
740b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_hlist_free(hlist);
7413db3f65cSamw res_ndestroy(&res_state);
742da6c28aaSamw return (NULL);
743da6c28aaSamw }
744da6c28aaSamw
745da6c28aaSamw /* check authority section */
746c8ec8eeaSjose borrego if (ns_cnt > 0) {
7473db3f65cSamw if (smb_ads_skip_auth_sec(ns_cnt, &ptr, eom) != 0) {
748b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_hlist_free(hlist);
7493db3f65cSamw res_ndestroy(&res_state);
7503db3f65cSamw return (NULL);
751da6c28aaSamw }
752c8ec8eeaSjose borrego }
753da6c28aaSamw
7540dcb3379Sjb150015 /*
7550dcb3379Sjb150015 * Check additional section to get IP address of ADS host.
7560dcb3379Sjb150015 */
757dc20a302Sas200622 if (addit_cnt > 0) {
758b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_decode_host_ip(addit_cnt, ans_cnt,
759b89a8333Snatalie li - Sun Microsystems - Irvine United States &ptr, eom, msg.buf, hlist->ah_list) != 0) {
760b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_hlist_free(hlist);
7613db3f65cSamw res_ndestroy(&res_state);
762da6c28aaSamw return (NULL);
763da6c28aaSamw }
764b89a8333Snatalie li - Sun Microsystems - Irvine United States }
765da6c28aaSamw
7663db3f65cSamw res_ndestroy(&res_state);
767b89a8333Snatalie li - Sun Microsystems - Irvine United States return (hlist);
768da6c28aaSamw }
769da6c28aaSamw
770da6c28aaSamw /*
771fc724630SAlan Wright * smb_ads_get_site_service
772b89a8333Snatalie li - Sun Microsystems - Irvine United States *
773fc724630SAlan Wright * Gets the msdcs SRV RR for the specified site.
774da6c28aaSamw */
775dc20a302Sas200622 static void
smb_ads_get_site_service(char * site_service,size_t len)776fc724630SAlan Wright smb_ads_get_site_service(char *site_service, size_t len)
777da6c28aaSamw {
77829bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
77929bd2886SAlan Wright if (*smb_ads_cfg.c_site == '\0')
780b89a8333Snatalie li - Sun Microsystems - Irvine United States *site_service = '\0';
781b89a8333Snatalie li - Sun Microsystems - Irvine United States else
782fc724630SAlan Wright (void) snprintf(site_service, len,
78329bd2886SAlan Wright SMB_ADS_MSDCS_SRV_SITE_RR, smb_ads_cfg.c_site);
784fc724630SAlan Wright
78529bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
786da6c28aaSamw }
787b89a8333Snatalie li - Sun Microsystems - Irvine United States
788b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
789b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_getipnodebyname
790b89a8333Snatalie li - Sun Microsystems - Irvine United States *
791b89a8333Snatalie li - Sun Microsystems - Irvine United States * This method gets the IP address by doing a host name lookup.
792b89a8333Snatalie li - Sun Microsystems - Irvine United States */
793b89a8333Snatalie li - Sun Microsystems - Irvine United States static int
smb_ads_getipnodebyname(smb_ads_host_info_t * hentry)794b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_getipnodebyname(smb_ads_host_info_t *hentry)
795b89a8333Snatalie li - Sun Microsystems - Irvine United States {
796b89a8333Snatalie li - Sun Microsystems - Irvine United States struct hostent *h;
797b89a8333Snatalie li - Sun Microsystems - Irvine United States int error;
798b89a8333Snatalie li - Sun Microsystems - Irvine United States
7997f667e74Sjose borrego switch (hentry->ipaddr.a_family) {
8007f667e74Sjose borrego case AF_INET6:
8017f667e74Sjose borrego h = getipnodebyname(hentry->name, hentry->ipaddr.a_family,
8027f667e74Sjose borrego AI_DEFAULT, &error);
803*b819cea2SGordon Ross if (h == NULL || h->h_length != NS_IN6ADDRSZ)
804b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1);
8057f667e74Sjose borrego break;
806b89a8333Snatalie li - Sun Microsystems - Irvine United States
8077f667e74Sjose borrego case AF_INET:
8087f667e74Sjose borrego h = getipnodebyname(hentry->name, hentry->ipaddr.a_family,
8097f667e74Sjose borrego 0, &error);
810*b819cea2SGordon Ross if (h == NULL || h->h_length != NS_INADDRSZ)
8117f667e74Sjose borrego return (-1);
8127f667e74Sjose borrego break;
813b89a8333Snatalie li - Sun Microsystems - Irvine United States
8147f667e74Sjose borrego default:
8157f667e74Sjose borrego return (-1);
8167f667e74Sjose borrego }
8177f667e74Sjose borrego bcopy(*(h->h_addr_list), &hentry->ipaddr.a_ip, h->h_length);
818b89a8333Snatalie li - Sun Microsystems - Irvine United States freehostent(h);
819b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0);
820b89a8333Snatalie li - Sun Microsystems - Irvine United States }
821b89a8333Snatalie li - Sun Microsystems - Irvine United States
822b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
82396a62adaSjoyce mcintosh * Checks the IP address to see if it is zero. If so, then do a host
82496a62adaSjoyce mcintosh * lookup by hostname to get the IP address based on the IP family.
82596a62adaSjoyce mcintosh *
82696a62adaSjoyce mcintosh * If the family is unknown then do a lookup by hostame based on the
82796a62adaSjoyce mcintosh * setting of the SMB_CI_IPV6_ENABLE property.
82896a62adaSjoyce mcintosh */
82996a62adaSjoyce mcintosh static int
smb_ads_set_ipaddr(smb_ads_host_info_t * hentry)83096a62adaSjoyce mcintosh smb_ads_set_ipaddr(smb_ads_host_info_t *hentry)
83196a62adaSjoyce mcintosh {
83296a62adaSjoyce mcintosh if (smb_inet_iszero(&hentry->ipaddr)) {
83396a62adaSjoyce mcintosh if (smb_ads_getipnodebyname(hentry) < 0)
83496a62adaSjoyce mcintosh return (-1);
83596a62adaSjoyce mcintosh } else if (SMB_ADS_AF_UNKNOWN(hentry)) {
83696a62adaSjoyce mcintosh hentry->ipaddr.a_family =
83796a62adaSjoyce mcintosh smb_config_getbool(SMB_CI_IPV6_ENABLE) ? AF_INET6 : AF_INET;
83896a62adaSjoyce mcintosh
83996a62adaSjoyce mcintosh if (smb_ads_getipnodebyname(hentry) < 0) {
84096a62adaSjoyce mcintosh hentry->ipaddr.a_family = 0;
84196a62adaSjoyce mcintosh return (-1);
84296a62adaSjoyce mcintosh }
84396a62adaSjoyce mcintosh }
84496a62adaSjoyce mcintosh
84596a62adaSjoyce mcintosh return (0);
84696a62adaSjoyce mcintosh }
84796a62adaSjoyce mcintosh
84896a62adaSjoyce mcintosh /*
849b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_find_host
850b89a8333Snatalie li - Sun Microsystems - Irvine United States *
85129bd2886SAlan Wright * Finds an ADS host in a given domain.
85229bd2886SAlan Wright *
85329bd2886SAlan Wright * If the cached host is valid, it will be used. Otherwise, a DC will
85429bd2886SAlan Wright * be selected based on the following criteria:
85529bd2886SAlan Wright *
85629bd2886SAlan Wright * 1) pdc (aka preferred DC) configuration
85729bd2886SAlan Wright * 2) AD site configuration - the scope of the DNS lookup will be
85829bd2886SAlan Wright * restricted to the specified site.
85929bd2886SAlan Wright * 3) DC on the same subnet
86029bd2886SAlan Wright * 4) DC with the lowest priority/highest weight
86129bd2886SAlan Wright *
86229bd2886SAlan Wright * The above items are listed in decreasing preference order. The selected
86329bd2886SAlan Wright * DC must be online.
86429bd2886SAlan Wright *
86529bd2886SAlan Wright * If this function is called during domain join, the specified kpasswd server
86629bd2886SAlan Wright * takes precedence over preferred DC, AD site, and so on.
867b89a8333Snatalie li - Sun Microsystems - Irvine United States *
868b89a8333Snatalie li - Sun Microsystems - Irvine United States * Parameters:
86929bd2886SAlan Wright * domain: fully-qualified domain name.
87029bd2886SAlan Wright * kpasswd_srv: fully-quailifed hostname of the kpasswd server.
871b89a8333Snatalie li - Sun Microsystems - Irvine United States *
872b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns:
87329bd2886SAlan Wright * A copy of the cached host info is returned. The caller is responsible
87429bd2886SAlan Wright * for deallocating the memory returned by this function.
875b89a8333Snatalie li - Sun Microsystems - Irvine United States */
876b89a8333Snatalie li - Sun Microsystems - Irvine United States /*ARGSUSED*/
877b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *
smb_ads_find_host(char * domain,char * kpasswd_srv)87829bd2886SAlan Wright smb_ads_find_host(char *domain, char *kpasswd_srv)
879b89a8333Snatalie li - Sun Microsystems - Irvine United States {
880b89a8333Snatalie li - Sun Microsystems - Irvine United States int i;
881b89a8333Snatalie li - Sun Microsystems - Irvine United States char site_service[MAXHOSTNAMELEN];
88229bd2886SAlan Wright smb_ads_host_list_t *hlist, *hlist2;
88329bd2886SAlan Wright smb_ads_host_info_t *hlistp = NULL, *host = NULL;
88429bd2886SAlan Wright smb_ads_host_info_t *found_kpasswd_srv = NULL;
88529bd2886SAlan Wright smb_ads_host_info_t *found_pdc = NULL;
886b89a8333Snatalie li - Sun Microsystems - Irvine United States
88729bd2886SAlan Wright if ((kpasswd_srv) && (*kpasswd_srv == '\0'))
88829bd2886SAlan Wright kpasswd_srv = NULL;
889b89a8333Snatalie li - Sun Microsystems - Irvine United States
89029bd2886SAlan Wright (void) mutex_lock(&smb_ads_cached_host_mtx);
89129bd2886SAlan Wright if (smb_ads_validate_cache_host(domain, kpasswd_srv)) {
89229bd2886SAlan Wright host = smb_ads_dup_host_info(smb_ads_cached_host_info);
89329bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
894b89a8333Snatalie li - Sun Microsystems - Irvine United States return (host);
895b89a8333Snatalie li - Sun Microsystems - Irvine United States }
896b89a8333Snatalie li - Sun Microsystems - Irvine United States
89729bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
898b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
899b89a8333Snatalie li - Sun Microsystems - Irvine United States
900b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
901b89a8333Snatalie li - Sun Microsystems - Irvine United States * First look for ADS hosts in ADS site if configured. Then try
902b89a8333Snatalie li - Sun Microsystems - Irvine United States * without ADS site info.
903b89a8333Snatalie li - Sun Microsystems - Irvine United States */
904fc724630SAlan Wright hlist = NULL;
905fc724630SAlan Wright smb_ads_get_site_service(site_service, MAXHOSTNAMELEN);
90629bd2886SAlan Wright
90729bd2886SAlan Wright /*
90829bd2886SAlan Wright * If we're given an AD, the DNS SRV RR lookup should not be restricted
90929bd2886SAlan Wright * to the specified site since there is no guarantee that the specified
91029bd2886SAlan Wright * AD is in the specified site.
91129bd2886SAlan Wright */
91229bd2886SAlan Wright if (*site_service != '\0' && !kpasswd_srv &&
91329bd2886SAlan Wright !smb_ads_is_pdc_configured())
914fc724630SAlan Wright hlist = smb_ads_query_dns_server(domain, site_service);
915b89a8333Snatalie li - Sun Microsystems - Irvine United States
916fc724630SAlan Wright if (!hlist)
917fc724630SAlan Wright hlist = smb_ads_query_dns_server(domain,
918fc724630SAlan Wright SMB_ADS_MSDCS_SRV_DC_RR);
919b89a8333Snatalie li - Sun Microsystems - Irvine United States
920b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((hlist == NULL) || (hlist->ah_list == NULL) || (hlist->ah_cnt == 0))
921b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
922b89a8333Snatalie li - Sun Microsystems - Irvine United States
92329bd2886SAlan Wright for (i = 0, hlistp = hlist->ah_list; i < hlist->ah_cnt; i++) {
92496a62adaSjoyce mcintosh if (smb_ads_set_ipaddr(&hlistp[i]) < 0)
925b89a8333Snatalie li - Sun Microsystems - Irvine United States continue;
926b89a8333Snatalie li - Sun Microsystems - Irvine United States
92729bd2886SAlan Wright if (smb_ads_is_sought_host(&hlistp[i], kpasswd_srv))
92829bd2886SAlan Wright found_kpasswd_srv = &hlistp[i];
92929bd2886SAlan Wright
93029bd2886SAlan Wright if (smb_ads_match_pdc(&hlistp[i]))
93129bd2886SAlan Wright found_pdc = &hlistp[i];
93229bd2886SAlan Wright }
93329bd2886SAlan Wright
93429bd2886SAlan Wright if (found_kpasswd_srv && smb_ads_ldap_ping(found_kpasswd_srv) == 0) {
93529bd2886SAlan Wright host = found_kpasswd_srv;
93629bd2886SAlan Wright goto update_cache;
93729bd2886SAlan Wright }
93829bd2886SAlan Wright
93929bd2886SAlan Wright if (found_pdc && smb_ads_ldap_ping(found_pdc) == 0) {
94029bd2886SAlan Wright host = found_pdc;
94129bd2886SAlan Wright goto update_cache;
94229bd2886SAlan Wright }
94329bd2886SAlan Wright
94429bd2886SAlan Wright /*
94529bd2886SAlan Wright * If the specified DC (kpasswd_srv or pdc) is not found, fallback
94629bd2886SAlan Wright * to find a DC in the specified AD site.
94729bd2886SAlan Wright */
94829bd2886SAlan Wright if (*site_service != '\0' &&
94929bd2886SAlan Wright (kpasswd_srv || smb_ads_is_pdc_configured())) {
95029bd2886SAlan Wright hlist2 = smb_ads_query_dns_server(domain, site_service);
95129bd2886SAlan Wright if (hlist2 && hlist2->ah_list && hlist2->ah_cnt != 0) {
952b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_hlist_free(hlist);
95329bd2886SAlan Wright hlist = hlist2;
95429bd2886SAlan Wright hlistp = hlist->ah_list;
95529bd2886SAlan Wright
95696a62adaSjoyce mcintosh for (i = 0; i < hlist->ah_cnt; i++)
95796a62adaSjoyce mcintosh (void) smb_ads_set_ipaddr(&hlistp[i]);
958b89a8333Snatalie li - Sun Microsystems - Irvine United States }
959b89a8333Snatalie li - Sun Microsystems - Irvine United States }
960b89a8333Snatalie li - Sun Microsystems - Irvine United States
961b89a8333Snatalie li - Sun Microsystems - Irvine United States /* Select DC from DC list */
96229bd2886SAlan Wright host = smb_ads_select_dc(hlist);
96329bd2886SAlan Wright
96429bd2886SAlan Wright update_cache:
96529bd2886SAlan Wright if (host) {
96629bd2886SAlan Wright (void) mutex_lock(&smb_ads_cached_host_mtx);
96729bd2886SAlan Wright if (!smb_ads_cached_host_info)
96829bd2886SAlan Wright smb_ads_cached_host_info = smb_ads_dup_host_info(host);
96929bd2886SAlan Wright host = smb_ads_dup_host_info(smb_ads_cached_host_info);
97029bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cached_host_mtx);
971b89a8333Snatalie li - Sun Microsystems - Irvine United States }
972b89a8333Snatalie li - Sun Microsystems - Irvine United States
973b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_hlist_free(hlist);
97429bd2886SAlan Wright return (host);
975b89a8333Snatalie li - Sun Microsystems - Irvine United States }
976b89a8333Snatalie li - Sun Microsystems - Irvine United States
977b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
978b89a8333Snatalie li - Sun Microsystems - Irvine United States * Return the number of dots in a string.
979b89a8333Snatalie li - Sun Microsystems - Irvine United States */
980b89a8333Snatalie li - Sun Microsystems - Irvine United States static int
smb_ads_count_dots(const char * s)981b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_count_dots(const char *s)
982b89a8333Snatalie li - Sun Microsystems - Irvine United States {
983b89a8333Snatalie li - Sun Microsystems - Irvine United States int ndots = 0;
984b89a8333Snatalie li - Sun Microsystems - Irvine United States
985b89a8333Snatalie li - Sun Microsystems - Irvine United States while (*s) {
986b89a8333Snatalie li - Sun Microsystems - Irvine United States if (*s++ == '.')
987b89a8333Snatalie li - Sun Microsystems - Irvine United States ndots++;
988b89a8333Snatalie li - Sun Microsystems - Irvine United States }
989b89a8333Snatalie li - Sun Microsystems - Irvine United States
990b89a8333Snatalie li - Sun Microsystems - Irvine United States return (ndots);
991b89a8333Snatalie li - Sun Microsystems - Irvine United States }
992b89a8333Snatalie li - Sun Microsystems - Irvine United States
993b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
994b89a8333Snatalie li - Sun Microsystems - Irvine United States * Convert a domain name in dot notation to distinguished name format,
995b89a8333Snatalie li - Sun Microsystems - Irvine United States * for example: sun.com -> dc=sun,dc=com.
996b89a8333Snatalie li - Sun Microsystems - Irvine United States *
997b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns a pointer to an allocated buffer containing the distinguished
998b89a8333Snatalie li - Sun Microsystems - Irvine United States * name.
999b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1000b89a8333Snatalie li - Sun Microsystems - Irvine United States static char *
smb_ads_convert_domain(const char * domain_name)1001b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_convert_domain(const char *domain_name)
1002b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1003b89a8333Snatalie li - Sun Microsystems - Irvine United States const char *s;
1004b89a8333Snatalie li - Sun Microsystems - Irvine United States char *dn_name;
1005b89a8333Snatalie li - Sun Microsystems - Irvine United States char buf[2];
1006b89a8333Snatalie li - Sun Microsystems - Irvine United States int ndots;
1007b89a8333Snatalie li - Sun Microsystems - Irvine United States int len;
1008b89a8333Snatalie li - Sun Microsystems - Irvine United States
1009b89a8333Snatalie li - Sun Microsystems - Irvine United States if (domain_name == NULL || *domain_name == 0)
1010b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
1011b89a8333Snatalie li - Sun Microsystems - Irvine United States
1012b89a8333Snatalie li - Sun Microsystems - Irvine United States ndots = smb_ads_count_dots(domain_name);
1013b89a8333Snatalie li - Sun Microsystems - Irvine United States ++ndots;
1014b89a8333Snatalie li - Sun Microsystems - Irvine United States len = strlen(domain_name) + (ndots * SMB_ADS_DN_PREFIX_LEN) + 1;
1015b89a8333Snatalie li - Sun Microsystems - Irvine United States
1016b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((dn_name = malloc(len)) == NULL)
1017b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
1018b89a8333Snatalie li - Sun Microsystems - Irvine United States
1019b89a8333Snatalie li - Sun Microsystems - Irvine United States bzero(dn_name, len);
1020b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcpy(dn_name, "dc=", len);
1021b89a8333Snatalie li - Sun Microsystems - Irvine United States
1022b89a8333Snatalie li - Sun Microsystems - Irvine United States buf[1] = '\0';
1023b89a8333Snatalie li - Sun Microsystems - Irvine United States s = domain_name;
1024b89a8333Snatalie li - Sun Microsystems - Irvine United States
1025b89a8333Snatalie li - Sun Microsystems - Irvine United States while (*s) {
1026b89a8333Snatalie li - Sun Microsystems - Irvine United States if (*s == '.') {
1027b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(dn_name, ",dc=", len);
1028b89a8333Snatalie li - Sun Microsystems - Irvine United States } else {
1029b89a8333Snatalie li - Sun Microsystems - Irvine United States buf[0] = *s;
1030b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(dn_name, buf, len);
1031b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1032b89a8333Snatalie li - Sun Microsystems - Irvine United States ++s;
1033b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1034b89a8333Snatalie li - Sun Microsystems - Irvine United States
1035b89a8333Snatalie li - Sun Microsystems - Irvine United States return (dn_name);
1036b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1037b89a8333Snatalie li - Sun Microsystems - Irvine United States
1038b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1039b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_free_cached_host
1040b89a8333Snatalie li - Sun Microsystems - Irvine United States *
1041b89a8333Snatalie li - Sun Microsystems - Irvine United States * Free the memory use by the global smb_ads_cached_host_info & set it to NULL.
1042b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1043b89a8333Snatalie li - Sun Microsystems - Irvine United States static void
smb_ads_free_cached_host(void)1044b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host(void)
1045b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1046b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) mutex_lock(&smb_ads_cached_host_mtx);
1047b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_cached_host_info) {
1048b89a8333Snatalie li - Sun Microsystems - Irvine United States free(smb_ads_cached_host_info);
1049b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_cached_host_info = NULL;
1050b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1051b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) mutex_unlock(&smb_ads_cached_host_mtx);
1052da6c28aaSamw }
1053da6c28aaSamw
1054da6c28aaSamw /*
10553db3f65cSamw * smb_ads_open
105655bf511dSas200622 * Open a LDAP connection to an ADS server if the system is in domain mode.
105755bf511dSas200622 * Acquire both Kerberos TGT and LDAP service tickets for the host principal.
105855bf511dSas200622 *
105955bf511dSas200622 * This function should only be called after the system is successfully joined
106055bf511dSas200622 * to a domain.
106155bf511dSas200622 */
10623db3f65cSamw smb_ads_handle_t *
smb_ads_open(void)10633db3f65cSamw smb_ads_open(void)
106455bf511dSas200622 {
1065dc20a302Sas200622 char domain[MAXHOSTNAMELEN];
106655bf511dSas200622
1067dc20a302Sas200622 if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
106855bf511dSas200622 return (NULL);
106955bf511dSas200622
1070dc20a302Sas200622 if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0)
1071dc20a302Sas200622 return (NULL);
1072dc20a302Sas200622
10733db3f65cSamw return (smb_ads_open_main(domain, NULL, NULL));
107455bf511dSas200622 }
107555bf511dSas200622
1076a0aa776eSAlan Wright static int
smb_ads_saslcallback(LDAP * ld,unsigned flags,void * defaults,void * prompts)1077a0aa776eSAlan Wright smb_ads_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts)
1078a0aa776eSAlan Wright {
1079a0aa776eSAlan Wright NOTE(ARGUNUSED(ld, defaults));
1080a0aa776eSAlan Wright sasl_interact_t *interact;
1081a0aa776eSAlan Wright
1082a0aa776eSAlan Wright if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE)
1083a0aa776eSAlan Wright return (LDAP_PARAM_ERROR);
1084a0aa776eSAlan Wright
1085a0aa776eSAlan Wright /* There should be no extra arguemnts for SASL/GSSAPI authentication */
1086a0aa776eSAlan Wright for (interact = prompts; interact->id != SASL_CB_LIST_END;
1087a0aa776eSAlan Wright interact++) {
1088a0aa776eSAlan Wright interact->result = NULL;
1089a0aa776eSAlan Wright interact->len = 0;
1090a0aa776eSAlan Wright }
1091a0aa776eSAlan Wright return (LDAP_SUCCESS);
1092a0aa776eSAlan Wright }
1093a0aa776eSAlan Wright
109455bf511dSas200622 /*
10953db3f65cSamw * smb_ads_open_main
1096da6c28aaSamw * Open a LDAP connection to an ADS server.
109755bf511dSas200622 * If ADS is enabled and the administrative username, password, and
1098da6c28aaSamw * ADS domain are defined then query DNS to find an ADS server if this is the
1099da6c28aaSamw * very first call to this routine. After an ADS server is found then this
1100da6c28aaSamw * server will be used everytime this routine is called until the system is
1101da6c28aaSamw * rebooted or the ADS server becomes unavailable then an ADS server will
11023db3f65cSamw * be queried again. After the connection is made then an ADS handle
1103da6c28aaSamw * is created to be returned.
1104da6c28aaSamw *
1105da6c28aaSamw * After the LDAP connection, the LDAP version will be set to 3 using
1106da6c28aaSamw * ldap_set_option().
1107da6c28aaSamw *
1108a0aa776eSAlan Wright * The LDAP connection is bound before the ADS handle is returned.
1109da6c28aaSamw * Parameters:
1110dc20a302Sas200622 * domain - fully-qualified domain name
1111dc20a302Sas200622 * user - the user account for whom the Kerberos TGT ticket and ADS
1112dc20a302Sas200622 * service tickets are acquired.
1113dc20a302Sas200622 * password - password of the specified user
1114dc20a302Sas200622 *
1115da6c28aaSamw * Returns:
1116da6c28aaSamw * NULL : can't connect to ADS server or other errors
11173db3f65cSamw * smb_ads_handle_t* : handle to ADS server
1118da6c28aaSamw */
11193db3f65cSamw static smb_ads_handle_t *
smb_ads_open_main(char * domain,char * user,char * password)11203db3f65cSamw smb_ads_open_main(char *domain, char *user, char *password)
1121da6c28aaSamw {
11223db3f65cSamw smb_ads_handle_t *ah;
1123da6c28aaSamw LDAP *ld;
1124b89a8333Snatalie li - Sun Microsystems - Irvine United States int version = 3;
11253db3f65cSamw smb_ads_host_info_t *ads_host = NULL;
1126a0aa776eSAlan Wright int rc;
1127a0aa776eSAlan Wright
1128a0aa776eSAlan Wright if (user != NULL) {
1129a0aa776eSAlan Wright if (smb_kinit(user, password) == 0)
1130a0aa776eSAlan Wright return (NULL);
1131a0aa776eSAlan Wright user = NULL;
1132a0aa776eSAlan Wright password = NULL;
1133a0aa776eSAlan Wright }
1134da6c28aaSamw
1135b89a8333Snatalie li - Sun Microsystems - Irvine United States ads_host = smb_ads_find_host(domain, NULL);
1136b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ads_host == NULL)
1137da6c28aaSamw return (NULL);
1138b89a8333Snatalie li - Sun Microsystems - Irvine United States
11393db3f65cSamw ah = (smb_ads_handle_t *)malloc(sizeof (smb_ads_handle_t));
114029bd2886SAlan Wright if (ah == NULL) {
114129bd2886SAlan Wright free(ads_host);
1142da6c28aaSamw return (NULL);
114329bd2886SAlan Wright }
114429bd2886SAlan Wright
11453db3f65cSamw (void) memset(ah, 0, sizeof (smb_ads_handle_t));
1146da6c28aaSamw
11477f667e74Sjose borrego if ((ld = ldap_init(ads_host->name, ads_host->port)) == NULL) {
1148b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
1149da6c28aaSamw free(ah);
115029bd2886SAlan Wright free(ads_host);
1151da6c28aaSamw return (NULL);
1152da6c28aaSamw }
1153da6c28aaSamw
1154da6c28aaSamw if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version)
1155da6c28aaSamw != LDAP_SUCCESS) {
1156b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_free_cached_host();
1157da6c28aaSamw free(ah);
115829bd2886SAlan Wright free(ads_host);
1159da6c28aaSamw (void) ldap_unbind(ld);
1160da6c28aaSamw return (NULL);
1161da6c28aaSamw }
1162da6c28aaSamw
1163c8ec8eeaSjose borrego (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
1164da6c28aaSamw ah->ld = ld;
1165da6c28aaSamw ah->domain = strdup(domain);
1166da6c28aaSamw
116755bf511dSas200622 if (ah->domain == NULL) {
11683db3f65cSamw smb_ads_close(ah);
116929bd2886SAlan Wright free(ads_host);
1170da6c28aaSamw return (NULL);
1171da6c28aaSamw }
1172da6c28aaSamw
11739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
11749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * ah->domain is often used for generating service principal name.
11759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Convert it to lower case for RFC 4120 section 6.2.1 conformance.
11769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
11779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(ah->domain);
11783db3f65cSamw ah->domain_dn = smb_ads_convert_domain(domain);
1179da6c28aaSamw if (ah->domain_dn == NULL) {
11803db3f65cSamw smb_ads_close(ah);
118129bd2886SAlan Wright free(ads_host);
1182da6c28aaSamw return (NULL);
1183da6c28aaSamw }
1184da6c28aaSamw
1185da6c28aaSamw ah->hostname = strdup(ads_host->name);
1186da6c28aaSamw if (ah->hostname == NULL) {
11873db3f65cSamw smb_ads_close(ah);
118829bd2886SAlan Wright free(ads_host);
1189da6c28aaSamw return (NULL);
1190da6c28aaSamw }
119129bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
119229bd2886SAlan Wright if (*smb_ads_cfg.c_site != '\0') {
119329bd2886SAlan Wright if ((ah->site = strdup(smb_ads_cfg.c_site)) == NULL) {
11943db3f65cSamw smb_ads_close(ah);
119529bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
119629bd2886SAlan Wright free(ads_host);
1197da6c28aaSamw return (NULL);
1198da6c28aaSamw }
1199da6c28aaSamw } else {
1200da6c28aaSamw ah->site = NULL;
1201da6c28aaSamw }
120229bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
1203da6c28aaSamw
1204a0aa776eSAlan Wright rc = ldap_sasl_interactive_bind_s(ah->ld, "", "GSSAPI", NULL, NULL,
1205a0aa776eSAlan Wright LDAP_SASL_INTERACTIVE, &smb_ads_saslcallback, NULL);
1206a0aa776eSAlan Wright if (rc != LDAP_SUCCESS) {
1207a0aa776eSAlan Wright syslog(LOG_ERR, "ldal_sasl_interactive_bind_s failed (%s)",
1208a0aa776eSAlan Wright ldap_err2string(rc));
12093db3f65cSamw smb_ads_close(ah);
121029bd2886SAlan Wright free(ads_host);
1211da6c28aaSamw return (NULL);
1212da6c28aaSamw }
1213da6c28aaSamw
121429bd2886SAlan Wright free(ads_host);
1215da6c28aaSamw return (ah);
1216da6c28aaSamw }
1217da6c28aaSamw
1218da6c28aaSamw /*
12193db3f65cSamw * smb_ads_close
1220da6c28aaSamw * Close connection to ADS server and free memory allocated for ADS handle.
1221da6c28aaSamw * LDAP unbind is called here.
1222da6c28aaSamw * Parameters:
1223da6c28aaSamw * ah: handle to ADS server
1224da6c28aaSamw * Returns:
1225da6c28aaSamw * void
1226da6c28aaSamw */
1227da6c28aaSamw void
smb_ads_close(smb_ads_handle_t * ah)12283db3f65cSamw smb_ads_close(smb_ads_handle_t *ah)
1229da6c28aaSamw {
1230da6c28aaSamw if (ah == NULL)
1231da6c28aaSamw return;
1232da6c28aaSamw /* close and free connection resources */
1233da6c28aaSamw if (ah->ld)
1234da6c28aaSamw (void) ldap_unbind(ah->ld);
1235da6c28aaSamw
1236da6c28aaSamw free(ah->domain);
1237da6c28aaSamw free(ah->domain_dn);
1238da6c28aaSamw free(ah->hostname);
1239da6c28aaSamw free(ah->site);
1240da6c28aaSamw free(ah);
1241da6c28aaSamw }
1242da6c28aaSamw
1243da6c28aaSamw /*
12443db3f65cSamw * smb_ads_alloc_attr
12456537f381Sas200622 *
12466537f381Sas200622 * Since the attrs is a null-terminated array, all elements
12476537f381Sas200622 * in the array (except the last one) will point to allocated
12486537f381Sas200622 * memory.
12496537f381Sas200622 */
12506537f381Sas200622 static int
smb_ads_alloc_attr(LDAPMod * attrs[],int num)12513db3f65cSamw smb_ads_alloc_attr(LDAPMod *attrs[], int num)
12526537f381Sas200622 {
12536537f381Sas200622 int i;
12546537f381Sas200622
12556537f381Sas200622 bzero(attrs, num * sizeof (LDAPMod *));
12566537f381Sas200622 for (i = 0; i < (num - 1); i++) {
12576537f381Sas200622 attrs[i] = (LDAPMod *)malloc(sizeof (LDAPMod));
12586537f381Sas200622 if (attrs[i] == NULL) {
12593db3f65cSamw smb_ads_free_attr(attrs);
12606537f381Sas200622 return (-1);
12616537f381Sas200622 }
12626537f381Sas200622 }
12636537f381Sas200622
12646537f381Sas200622 return (0);
12656537f381Sas200622 }
12666537f381Sas200622
12676537f381Sas200622 /*
12683db3f65cSamw * smb_ads_free_attr
1269da6c28aaSamw * Free memory allocated when publishing a share.
1270da6c28aaSamw * Parameters:
127155bf511dSas200622 * attrs: an array of LDAPMod pointers
1272da6c28aaSamw * Returns:
1273da6c28aaSamw * None
1274da6c28aaSamw */
1275da6c28aaSamw static void
smb_ads_free_attr(LDAPMod * attrs[])12763db3f65cSamw smb_ads_free_attr(LDAPMod *attrs[])
1277da6c28aaSamw {
1278da6c28aaSamw int i;
127955bf511dSas200622 for (i = 0; attrs[i]; i++) {
128055bf511dSas200622 free(attrs[i]);
1281da6c28aaSamw }
1282da6c28aaSamw }
1283da6c28aaSamw
1284da6c28aaSamw /*
1285fe1c642dSBill Krier * Returns share DN in an allocated buffer. The format of the DN is
1286fe1c642dSBill Krier * cn=<sharename>,<container RDNs>,<domain DN>
1287fe1c642dSBill Krier *
1288fe1c642dSBill Krier * If the domain DN is not included in the container parameter,
1289fe1c642dSBill Krier * then it will be appended to create the share DN.
1290fe1c642dSBill Krier *
1291fe1c642dSBill Krier * The caller must free the allocated buffer.
1292fe1c642dSBill Krier */
1293fe1c642dSBill Krier static char *
smb_ads_get_sharedn(const char * sharename,const char * container,const char * domain_dn)1294fe1c642dSBill Krier smb_ads_get_sharedn(const char *sharename, const char *container,
1295fe1c642dSBill Krier const char *domain_dn)
1296fe1c642dSBill Krier {
1297fe1c642dSBill Krier char *share_dn;
1298fe1c642dSBill Krier int rc, offset, container_len, domain_len;
1299fe1c642dSBill Krier boolean_t append_domain = B_TRUE;
1300fe1c642dSBill Krier
1301fe1c642dSBill Krier container_len = strlen(container);
1302fe1c642dSBill Krier domain_len = strlen(domain_dn);
1303fe1c642dSBill Krier
1304fe1c642dSBill Krier if (container_len >= domain_len) {
1305fe1c642dSBill Krier
1306fe1c642dSBill Krier /* offset to last domain_len characters */
1307fe1c642dSBill Krier offset = container_len - domain_len;
1308fe1c642dSBill Krier
1309fe1c642dSBill Krier if (smb_strcasecmp(container + offset,
1310fe1c642dSBill Krier domain_dn, domain_len) == 0)
1311fe1c642dSBill Krier append_domain = B_FALSE;
1312fe1c642dSBill Krier }
1313fe1c642dSBill Krier
1314fe1c642dSBill Krier if (append_domain)
1315fe1c642dSBill Krier rc = asprintf(&share_dn, "cn=%s,%s,%s", sharename,
1316fe1c642dSBill Krier container, domain_dn);
1317fe1c642dSBill Krier else
1318fe1c642dSBill Krier rc = asprintf(&share_dn, "cn=%s,%s", sharename,
1319fe1c642dSBill Krier container);
1320fe1c642dSBill Krier
1321fe1c642dSBill Krier return ((rc == -1) ? NULL : share_dn);
1322fe1c642dSBill Krier }
1323fe1c642dSBill Krier
1324fe1c642dSBill Krier /*
13253db3f65cSamw * smb_ads_add_share
13263db3f65cSamw * Call by smb_ads_publish_share to create share object in ADS.
1327da6c28aaSamw * This routine specifies the attributes of an ADS LDAP share object. The first
1328da6c28aaSamw * attribute and values define the type of ADS object, the share object. The
1329da6c28aaSamw * second attribute and value define the UNC of the share data for the share
1330da6c28aaSamw * object. The LDAP synchronous add command is used to add the object into ADS.
1331da6c28aaSamw * The container location to add the object needs to specified.
1332da6c28aaSamw * Parameters:
1333da6c28aaSamw * ah : handle to ADS server
1334da6c28aaSamw * adsShareName: name of share object to be created in ADS
1335da6c28aaSamw * shareUNC : share name on NetForce
1336da6c28aaSamw * adsContainer: location in ADS to create share object
1337da6c28aaSamw *
1338da6c28aaSamw * Returns:
1339da6c28aaSamw * -1 : error
1340da6c28aaSamw * 0 : success
1341da6c28aaSamw */
1342da6c28aaSamw int
smb_ads_add_share(smb_ads_handle_t * ah,const char * adsShareName,const char * unc_name,const char * adsContainer)13433db3f65cSamw smb_ads_add_share(smb_ads_handle_t *ah, const char *adsShareName,
1344da6c28aaSamw const char *unc_name, const char *adsContainer)
1345da6c28aaSamw {
13463db3f65cSamw LDAPMod *attrs[SMB_ADS_SHARE_NUM_ATTR];
134755bf511dSas200622 int j = 0;
1348da6c28aaSamw char *share_dn;
1349fe1c642dSBill Krier int ret;
13507f667e74Sjose borrego char *unc_names[] = {(char *)unc_name, NULL};
1351da6c28aaSamw
1352fe1c642dSBill Krier if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
1353fe1c642dSBill Krier ah->domain_dn)) == NULL)
1354da6c28aaSamw return (-1);
1355da6c28aaSamw
13563db3f65cSamw if (smb_ads_alloc_attr(attrs, SMB_ADS_SHARE_NUM_ATTR) != 0) {
135755bf511dSas200622 free(share_dn);
135855bf511dSas200622 return (-1);
135955bf511dSas200622 }
136055bf511dSas200622
136155bf511dSas200622 attrs[j]->mod_op = LDAP_MOD_ADD;
136255bf511dSas200622 attrs[j]->mod_type = "objectClass";
13637f667e74Sjose borrego attrs[j]->mod_values = smb_ads_share_objcls;
1364da6c28aaSamw
136555bf511dSas200622 attrs[++j]->mod_op = LDAP_MOD_ADD;
136655bf511dSas200622 attrs[j]->mod_type = "uNCName";
13677f667e74Sjose borrego attrs[j]->mod_values = unc_names;
1368da6c28aaSamw
136955bf511dSas200622 if ((ret = ldap_add_s(ah->ld, share_dn, attrs)) != LDAP_SUCCESS) {
13709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (ret == LDAP_NO_SUCH_OBJECT) {
13719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States syslog(LOG_ERR, "Failed to publish share %s in" \
13729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States " AD. Container does not exist: %s.\n",
13739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States adsShareName, share_dn);
13749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
13759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } else {
13769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States syslog(LOG_ERR, "Failed to publish share %s in" \
13779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States " AD: %s (%s).\n", adsShareName, share_dn,
13789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ldap_err2string(ret));
13799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
13803db3f65cSamw smb_ads_free_attr(attrs);
1381da6c28aaSamw free(share_dn);
1382da6c28aaSamw return (ret);
1383da6c28aaSamw }
1384da6c28aaSamw free(share_dn);
13853db3f65cSamw smb_ads_free_attr(attrs);
1386da6c28aaSamw
1387da6c28aaSamw return (0);
1388da6c28aaSamw }
1389da6c28aaSamw
1390da6c28aaSamw /*
13913db3f65cSamw * smb_ads_del_share
13923db3f65cSamw * Call by smb_ads_remove_share to remove share object from ADS. The container
1393da6c28aaSamw * location to remove the object needs to specified. The LDAP synchronous
1394da6c28aaSamw * delete command is used.
1395da6c28aaSamw * Parameters:
1396da6c28aaSamw * ah : handle to ADS server
1397da6c28aaSamw * adsShareName: name of share object in ADS to be removed
1398da6c28aaSamw * adsContainer: location of share object in ADS
1399da6c28aaSamw * Returns:
1400da6c28aaSamw * -1 : error
1401da6c28aaSamw * 0 : success
1402da6c28aaSamw */
1403da6c28aaSamw static int
smb_ads_del_share(smb_ads_handle_t * ah,const char * adsShareName,const char * adsContainer)14043db3f65cSamw smb_ads_del_share(smb_ads_handle_t *ah, const char *adsShareName,
1405da6c28aaSamw const char *adsContainer)
1406da6c28aaSamw {
1407b89a8333Snatalie li - Sun Microsystems - Irvine United States char *share_dn;
1408fe1c642dSBill Krier int ret;
1409da6c28aaSamw
1410fe1c642dSBill Krier if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
1411fe1c642dSBill Krier ah->domain_dn)) == NULL)
1412da6c28aaSamw return (-1);
1413da6c28aaSamw
1414da6c28aaSamw if ((ret = ldap_delete_s(ah->ld, share_dn)) != LDAP_SUCCESS) {
1415fc724630SAlan Wright smb_tracef("ldap_delete: %s", ldap_err2string(ret));
1416da6c28aaSamw free(share_dn);
1417da6c28aaSamw return (-1);
1418da6c28aaSamw }
1419da6c28aaSamw free(share_dn);
1420da6c28aaSamw
1421da6c28aaSamw return (0);
1422da6c28aaSamw }
1423da6c28aaSamw
1424da6c28aaSamw
1425da6c28aaSamw /*
14263db3f65cSamw * smb_ads_escape_search_filter_chars
1427da6c28aaSamw *
1428da6c28aaSamw * This routine will escape the special characters found in a string
1429da6c28aaSamw * that will later be passed to the ldap search filter.
1430da6c28aaSamw *
1431da6c28aaSamw * RFC 1960 - A String Representation of LDAP Search Filters
1432da6c28aaSamw * 3. String Search Filter Definition
1433da6c28aaSamw * If a value must contain one of the characters '*' OR '(' OR ')',
1434da6c28aaSamw * these characters
1435da6c28aaSamw * should be escaped by preceding them with the backslash '\' character.
1436da6c28aaSamw *
1437da6c28aaSamw * RFC 2252 - LDAP Attribute Syntax Definitions
1438da6c28aaSamw * a backslash quoting mechanism is used to escape
1439da6c28aaSamw * the following separator symbol character (such as "'", "$" or "#") if
1440da6c28aaSamw * it should occur in that string.
1441da6c28aaSamw */
1442da6c28aaSamw static int
smb_ads_escape_search_filter_chars(const char * src,char * dst)14433db3f65cSamw smb_ads_escape_search_filter_chars(const char *src, char *dst)
1444da6c28aaSamw {
14453db3f65cSamw int avail = SMB_ADS_MAXBUFLEN - 1; /* reserve a space for NULL char */
1446da6c28aaSamw
1447da6c28aaSamw if (src == NULL || dst == NULL)
1448da6c28aaSamw return (-1);
1449da6c28aaSamw
1450da6c28aaSamw while (*src) {
1451da6c28aaSamw if (!avail) {
1452da6c28aaSamw *dst = 0;
1453da6c28aaSamw return (-1);
1454da6c28aaSamw }
1455da6c28aaSamw
1456da6c28aaSamw switch (*src) {
1457da6c28aaSamw case '\\':
1458da6c28aaSamw case '\'':
1459da6c28aaSamw case '$':
1460da6c28aaSamw case '#':
1461da6c28aaSamw case '*':
1462da6c28aaSamw case '(':
1463da6c28aaSamw case ')':
1464da6c28aaSamw *dst++ = '\\';
1465da6c28aaSamw avail--;
1466da6c28aaSamw /* fall through */
1467da6c28aaSamw
1468da6c28aaSamw default:
1469da6c28aaSamw *dst++ = *src++;
1470da6c28aaSamw avail--;
1471da6c28aaSamw }
1472da6c28aaSamw }
1473da6c28aaSamw
1474da6c28aaSamw *dst = 0;
1475da6c28aaSamw
1476da6c28aaSamw return (0);
1477da6c28aaSamw }
1478da6c28aaSamw
1479da6c28aaSamw /*
14803db3f65cSamw * smb_ads_lookup_share
1481da6c28aaSamw * The search filter is set to search for a specific share name in the
1482da6c28aaSamw * specified ADS container. The LDSAP synchronous search command is used.
1483da6c28aaSamw * Parameters:
1484da6c28aaSamw * ah : handle to ADS server
1485da6c28aaSamw * adsShareName: name of share object in ADS to be searched
1486da6c28aaSamw * adsContainer: location of share object in ADS
1487da6c28aaSamw * Returns:
1488da6c28aaSamw * -1 : error
1489da6c28aaSamw * 0 : not found
1490da6c28aaSamw * 1 : found
1491da6c28aaSamw */
1492da6c28aaSamw int
smb_ads_lookup_share(smb_ads_handle_t * ah,const char * adsShareName,const char * adsContainer,char * unc_name)14933db3f65cSamw smb_ads_lookup_share(smb_ads_handle_t *ah, const char *adsShareName,
1494da6c28aaSamw const char *adsContainer, char *unc_name)
1495da6c28aaSamw {
14963db3f65cSamw char *attrs[4], filter[SMB_ADS_MAXBUFLEN];
1497da6c28aaSamw char *share_dn;
1498fe1c642dSBill Krier int ret;
1499da6c28aaSamw LDAPMessage *res;
15003db3f65cSamw char tmpbuf[SMB_ADS_MAXBUFLEN];
1501da6c28aaSamw
1502da6c28aaSamw if (adsShareName == NULL || adsContainer == NULL)
1503da6c28aaSamw return (-1);
1504da6c28aaSamw
1505fe1c642dSBill Krier if ((share_dn = smb_ads_get_sharedn(adsShareName, adsContainer,
1506fe1c642dSBill Krier ah->domain_dn)) == NULL)
1507da6c28aaSamw return (-1);
1508da6c28aaSamw
1509da6c28aaSamw res = NULL;
1510da6c28aaSamw attrs[0] = "cn";
1511da6c28aaSamw attrs[1] = "objectClass";
1512da6c28aaSamw attrs[2] = "uNCName";
1513da6c28aaSamw attrs[3] = NULL;
1514da6c28aaSamw
15153db3f65cSamw if (smb_ads_escape_search_filter_chars(unc_name, tmpbuf) != 0) {
1516da6c28aaSamw free(share_dn);
1517da6c28aaSamw return (-1);
1518da6c28aaSamw }
1519da6c28aaSamw
1520da6c28aaSamw (void) snprintf(filter, sizeof (filter),
1521da6c28aaSamw "(&(objectClass=volume)(uNCName=%s))", tmpbuf);
1522da6c28aaSamw
1523da6c28aaSamw if ((ret = ldap_search_s(ah->ld, share_dn,
1524da6c28aaSamw LDAP_SCOPE_BASE, filter, attrs, 0, &res)) != LDAP_SUCCESS) {
1525b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ret != LDAP_NO_SUCH_OBJECT)
1526fc724630SAlan Wright smb_tracef("%s: ldap_search: %s", share_dn,
1527fc724630SAlan Wright ldap_err2string(ret));
1528b89a8333Snatalie li - Sun Microsystems - Irvine United States
1529da6c28aaSamw (void) ldap_msgfree(res);
1530da6c28aaSamw free(share_dn);
1531da6c28aaSamw return (0);
1532da6c28aaSamw }
1533da6c28aaSamw
1534da6c28aaSamw (void) free(share_dn);
1535da6c28aaSamw
1536da6c28aaSamw /* no match is found */
1537da6c28aaSamw if (ldap_count_entries(ah->ld, res) == 0) {
1538da6c28aaSamw (void) ldap_msgfree(res);
1539da6c28aaSamw return (0);
1540da6c28aaSamw }
1541da6c28aaSamw
1542da6c28aaSamw /* free the search results */
1543da6c28aaSamw (void) ldap_msgfree(res);
1544da6c28aaSamw
1545da6c28aaSamw return (1);
1546da6c28aaSamw }
1547da6c28aaSamw
1548da6c28aaSamw /*
15493db3f65cSamw * smb_ads_publish_share
1550da6c28aaSamw * Publish share into ADS. If a share name already exist in ADS in the same
1551da6c28aaSamw * container then the existing share object is removed before adding the new
1552da6c28aaSamw * share object.
1553da6c28aaSamw * Parameters:
15543db3f65cSamw * ah : handle return from smb_ads_open
1555da6c28aaSamw * adsShareName: name of share to be added to ADS directory
1556da6c28aaSamw * shareUNC : name of share on client, can be NULL to use the same name
1557da6c28aaSamw * as adsShareName
1558da6c28aaSamw * adsContainer: location for share to be added in ADS directory, ie
1559da6c28aaSamw * ou=share_folder
1560da6c28aaSamw * uncType : use UNC_HOSTNAME to use hostname for UNC, use UNC_HOSTADDR
1561da6c28aaSamw * to use host ip addr for UNC.
1562da6c28aaSamw * Returns:
1563da6c28aaSamw * -1 : error
1564da6c28aaSamw * 0 : success
1565da6c28aaSamw */
1566da6c28aaSamw int
smb_ads_publish_share(smb_ads_handle_t * ah,const char * adsShareName,const char * shareUNC,const char * adsContainer,const char * hostname)15673db3f65cSamw smb_ads_publish_share(smb_ads_handle_t *ah, const char *adsShareName,
1568da6c28aaSamw const char *shareUNC, const char *adsContainer, const char *hostname)
1569da6c28aaSamw {
1570da6c28aaSamw int ret;
15713db3f65cSamw char unc_name[SMB_ADS_MAXBUFLEN];
1572da6c28aaSamw
1573da6c28aaSamw if (adsShareName == NULL || adsContainer == NULL)
1574da6c28aaSamw return (-1);
1575da6c28aaSamw
1576da6c28aaSamw if (shareUNC == 0 || *shareUNC == 0)
1577da6c28aaSamw shareUNC = adsShareName;
1578da6c28aaSamw
15793db3f65cSamw if (smb_ads_build_unc_name(unc_name, sizeof (unc_name),
1580b89a8333Snatalie li - Sun Microsystems - Irvine United States hostname, shareUNC) < 0)
1581da6c28aaSamw return (-1);
1582da6c28aaSamw
15833db3f65cSamw ret = smb_ads_lookup_share(ah, adsShareName, adsContainer, unc_name);
1584da6c28aaSamw
1585da6c28aaSamw switch (ret) {
1586da6c28aaSamw case 1:
15873db3f65cSamw (void) smb_ads_del_share(ah, adsShareName, adsContainer);
15883db3f65cSamw ret = smb_ads_add_share(ah, adsShareName, unc_name,
15893db3f65cSamw adsContainer);
1590da6c28aaSamw break;
1591da6c28aaSamw
1592da6c28aaSamw case 0:
15933db3f65cSamw ret = smb_ads_add_share(ah, adsShareName, unc_name,
15943db3f65cSamw adsContainer);
1595b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ret == LDAP_ALREADY_EXISTS)
1596da6c28aaSamw ret = -1;
1597b89a8333Snatalie li - Sun Microsystems - Irvine United States
1598da6c28aaSamw break;
1599da6c28aaSamw
1600da6c28aaSamw case -1:
1601da6c28aaSamw default:
1602da6c28aaSamw /* return with error code */
1603da6c28aaSamw ret = -1;
1604da6c28aaSamw }
1605da6c28aaSamw
1606da6c28aaSamw return (ret);
1607da6c28aaSamw }
1608da6c28aaSamw
1609da6c28aaSamw /*
16103db3f65cSamw * smb_ads_remove_share
1611da6c28aaSamw * Remove share from ADS. A search is done first before explicitly removing
1612da6c28aaSamw * the share.
1613da6c28aaSamw * Parameters:
16143db3f65cSamw * ah : handle return from smb_ads_open
1615da6c28aaSamw * adsShareName: name of share to be removed from ADS directory
1616da6c28aaSamw * adsContainer: location for share to be removed from ADS directory, ie
1617da6c28aaSamw * ou=share_folder
1618da6c28aaSamw * Returns:
1619da6c28aaSamw * -1 : error
1620da6c28aaSamw * 0 : success
1621da6c28aaSamw */
1622da6c28aaSamw int
smb_ads_remove_share(smb_ads_handle_t * ah,const char * adsShareName,const char * shareUNC,const char * adsContainer,const char * hostname)16233db3f65cSamw smb_ads_remove_share(smb_ads_handle_t *ah, const char *adsShareName,
16243db3f65cSamw const char *shareUNC, const char *adsContainer, const char *hostname)
1625da6c28aaSamw {
1626da6c28aaSamw int ret;
16273db3f65cSamw char unc_name[SMB_ADS_MAXBUFLEN];
1628da6c28aaSamw
1629da6c28aaSamw if (adsShareName == NULL || adsContainer == NULL)
1630da6c28aaSamw return (-1);
1631da6c28aaSamw if (shareUNC == 0 || *shareUNC == 0)
1632da6c28aaSamw shareUNC = adsShareName;
1633da6c28aaSamw
16343db3f65cSamw if (smb_ads_build_unc_name(unc_name, sizeof (unc_name),
1635b89a8333Snatalie li - Sun Microsystems - Irvine United States hostname, shareUNC) < 0)
1636da6c28aaSamw return (-1);
1637da6c28aaSamw
16383db3f65cSamw ret = smb_ads_lookup_share(ah, adsShareName, adsContainer, unc_name);
1639da6c28aaSamw if (ret == 0)
1640da6c28aaSamw return (0);
1641da6c28aaSamw if (ret == -1)
1642da6c28aaSamw return (-1);
1643da6c28aaSamw
16443db3f65cSamw return (smb_ads_del_share(ah, adsShareName, adsContainer));
1645da6c28aaSamw }
1646da6c28aaSamw
1647da6c28aaSamw /*
1648b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_get_default_comp_container_dn
1649da6c28aaSamw *
1650b89a8333Snatalie li - Sun Microsystems - Irvine United States * Build the distinguished name for the default computer conatiner (i.e. the
1651b89a8333Snatalie li - Sun Microsystems - Irvine United States * pre-defined Computers container).
1652da6c28aaSamw */
1653da6c28aaSamw static void
smb_ads_get_default_comp_container_dn(smb_ads_handle_t * ah,char * buf,size_t buflen)1654b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_container_dn(smb_ads_handle_t *ah, char *buf,
1655b89a8333Snatalie li - Sun Microsystems - Irvine United States size_t buflen)
1656da6c28aaSamw {
1657b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) snprintf(buf, buflen, "cn=%s,%s", SMB_ADS_COMPUTERS_CN,
1658b89a8333Snatalie li - Sun Microsystems - Irvine United States ah->domain_dn);
1659b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1660da6c28aaSamw
1661b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1662b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_get_default_comp_dn
1663b89a8333Snatalie li - Sun Microsystems - Irvine United States *
1664b89a8333Snatalie li - Sun Microsystems - Irvine United States * Build the distinguished name for this system.
1665b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1666b89a8333Snatalie li - Sun Microsystems - Irvine United States static void
smb_ads_get_default_comp_dn(smb_ads_handle_t * ah,char * buf,size_t buflen)1667b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_dn(smb_ads_handle_t *ah, char *buf, size_t buflen)
1668b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1669b89a8333Snatalie li - Sun Microsystems - Irvine United States char nbname[NETBIOS_NAME_SZ];
1670b89a8333Snatalie li - Sun Microsystems - Irvine United States char container_dn[SMB_ADS_DN_MAX];
1671b89a8333Snatalie li - Sun Microsystems - Irvine United States
1672b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getnetbiosname(nbname, sizeof (nbname));
1673b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_container_dn(ah, container_dn, SMB_ADS_DN_MAX);
1674b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) snprintf(buf, buflen, "cn=%s,%s", nbname, container_dn);
1675da6c28aaSamw }
1676da6c28aaSamw
1677da6c28aaSamw /*
16783db3f65cSamw * smb_ads_add_computer
1679da6c28aaSamw *
1680da6c28aaSamw * Returns 0 upon success. Otherwise, returns -1.
1681da6c28aaSamw */
1682da6c28aaSamw static int
smb_ads_add_computer(smb_ads_handle_t * ah,int dclevel,char * dn)1683c8ec8eeaSjose borrego smb_ads_add_computer(smb_ads_handle_t *ah, int dclevel, char *dn)
1684da6c28aaSamw {
1685c8ec8eeaSjose borrego return (smb_ads_computer_op(ah, LDAP_MOD_ADD, dclevel, dn));
168655bf511dSas200622 }
168755bf511dSas200622
168855bf511dSas200622 /*
16893db3f65cSamw * smb_ads_modify_computer
169055bf511dSas200622 *
169155bf511dSas200622 * Returns 0 upon success. Otherwise, returns -1.
169255bf511dSas200622 */
169355bf511dSas200622 static int
smb_ads_modify_computer(smb_ads_handle_t * ah,int dclevel,char * dn)1694c8ec8eeaSjose borrego smb_ads_modify_computer(smb_ads_handle_t *ah, int dclevel, char *dn)
169555bf511dSas200622 {
1696c8ec8eeaSjose borrego return (smb_ads_computer_op(ah, LDAP_MOD_REPLACE, dclevel, dn));
16973db3f65cSamw }
16983db3f65cSamw
16993db3f65cSamw /*
17003db3f65cSamw * smb_ads_get_dc_level
17013db3f65cSamw *
17023db3f65cSamw * Returns the functional level of the DC upon success.
17033db3f65cSamw * Otherwise, -1 is returned.
17043db3f65cSamw */
17053db3f65cSamw static int
smb_ads_get_dc_level(smb_ads_handle_t * ah)17063db3f65cSamw smb_ads_get_dc_level(smb_ads_handle_t *ah)
17073db3f65cSamw {
17083db3f65cSamw LDAPMessage *res, *entry;
17093db3f65cSamw char *attr[2];
17103db3f65cSamw char **vals;
17113db3f65cSamw int rc = -1;
17123db3f65cSamw
17133db3f65cSamw res = NULL;
17143db3f65cSamw attr[0] = SMB_ADS_ATTR_DCLEVEL;
17153db3f65cSamw attr[1] = NULL;
17163db3f65cSamw if (ldap_search_s(ah->ld, "", LDAP_SCOPE_BASE, NULL, attr,
17173db3f65cSamw 0, &res) != LDAP_SUCCESS) {
17183db3f65cSamw (void) ldap_msgfree(res);
17193db3f65cSamw return (-1);
17203db3f65cSamw }
17213db3f65cSamw
17223db3f65cSamw /* no match for the specified attribute is found */
17233db3f65cSamw if (ldap_count_entries(ah->ld, res) == 0) {
17243db3f65cSamw (void) ldap_msgfree(res);
17253db3f65cSamw return (-1);
17263db3f65cSamw }
17273db3f65cSamw
17283db3f65cSamw entry = ldap_first_entry(ah->ld, res);
17293db3f65cSamw if (entry) {
17303db3f65cSamw if ((vals = ldap_get_values(ah->ld, entry,
17313db3f65cSamw SMB_ADS_ATTR_DCLEVEL)) == NULL) {
17323db3f65cSamw /*
17333db3f65cSamw * Observed the values aren't populated
17343db3f65cSamw * by the Windows 2000 server.
17353db3f65cSamw */
17363db3f65cSamw (void) ldap_msgfree(res);
17373db3f65cSamw return (SMB_ADS_DCLEVEL_W2K);
17383db3f65cSamw }
17393db3f65cSamw
17403db3f65cSamw if (vals[0] != NULL)
17413db3f65cSamw rc = atoi(vals[0]);
17423db3f65cSamw
17433db3f65cSamw ldap_value_free(vals);
17443db3f65cSamw }
17453db3f65cSamw
17463db3f65cSamw (void) ldap_msgfree(res);
17473db3f65cSamw return (rc);
174855bf511dSas200622 }
174955bf511dSas200622
17509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /*
17519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * The fully-qualified hostname returned by this function is often used for
17529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * constructing service principal name. Return the fully-qualified hostname
17539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * in lower case for RFC 4120 section 6.2.1 conformance.
17549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */
175555bf511dSas200622 static int
smb_ads_getfqhostname(smb_ads_handle_t * ah,char * fqhost,int len)1756b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_getfqhostname(smb_ads_handle_t *ah, char *fqhost, int len)
1757b89a8333Snatalie li - Sun Microsystems - Irvine United States {
17589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(fqhost, len, SMB_CASE_LOWER) != 0)
1759b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1);
1760b89a8333Snatalie li - Sun Microsystems - Irvine United States
1761b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) snprintf(fqhost, len, "%s.%s", fqhost,
1762b89a8333Snatalie li - Sun Microsystems - Irvine United States ah->domain);
1763b89a8333Snatalie li - Sun Microsystems - Irvine United States
1764b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0);
1765b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1766b89a8333Snatalie li - Sun Microsystems - Irvine United States
1767b89a8333Snatalie li - Sun Microsystems - Irvine United States static int
smb_ads_computer_op(smb_ads_handle_t * ah,int op,int dclevel,char * dn)1768c8ec8eeaSjose borrego smb_ads_computer_op(smb_ads_handle_t *ah, int op, int dclevel, char *dn)
176955bf511dSas200622 {
17703db3f65cSamw LDAPMod *attrs[SMB_ADS_COMPUTER_NUM_ATTR];
1771148c5f43SAlan Wright char *sam_val[2];
1772148c5f43SAlan Wright char *ctl_val[2], *fqh_val[2];
17733db3f65cSamw char *encrypt_val[2];
17746537f381Sas200622 int j = -1;
1775da6c28aaSamw int ret, usrctl_flags = 0;
1776b89a8333Snatalie li - Sun Microsystems - Irvine United States char sam_acct[SMB_SAMACCT_MAXLEN];
1777da6c28aaSamw char fqhost[MAXHOSTNAMELEN];
1778da6c28aaSamw char usrctl_buf[16];
17793db3f65cSamw char encrypt_buf[16];
178055bf511dSas200622 int max;
1781148c5f43SAlan Wright smb_krb5_pn_set_t spn, upn;
1782da6c28aaSamw
1783b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getsamaccount(sam_acct, sizeof (sam_acct)) != 0)
1784da6c28aaSamw return (-1);
1785da6c28aaSamw
1786b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_getfqhostname(ah, fqhost, MAXHOSTNAMELEN))
1787b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1);
1788da6c28aaSamw
1789148c5f43SAlan Wright /* The SPN attribute is multi-valued and must be 1 or greater */
1790148c5f43SAlan Wright if (smb_krb5_get_pn_set(&spn, SMB_PN_SPN_ATTR, ah->domain) == 0)
17916537f381Sas200622 return (-1);
17926537f381Sas200622
1793148c5f43SAlan Wright /* The UPN attribute is single-valued and cannot be zero */
1794148c5f43SAlan Wright if (smb_krb5_get_pn_set(&upn, SMB_PN_UPN_ATTR, ah->domain) != 1) {
1795148c5f43SAlan Wright smb_krb5_free_pn_set(&spn);
1796148c5f43SAlan Wright smb_krb5_free_pn_set(&upn);
1797da6c28aaSamw return (-1);
1798da6c28aaSamw }
1799da6c28aaSamw
18003db3f65cSamw max = (SMB_ADS_COMPUTER_NUM_ATTR - ((op != LDAP_MOD_ADD) ? 1 : 0))
1801b1352070SAlan Wright - (dclevel >= SMB_ADS_DCLEVEL_W2K8 ? 0 : 1);
18026537f381Sas200622
18033db3f65cSamw if (smb_ads_alloc_attr(attrs, max) != 0) {
1804148c5f43SAlan Wright smb_krb5_free_pn_set(&spn);
1805148c5f43SAlan Wright smb_krb5_free_pn_set(&upn);
180655bf511dSas200622 return (-1);
180755bf511dSas200622 }
180855bf511dSas200622
180955bf511dSas200622 /* objectClass attribute is not modifiable. */
181055bf511dSas200622 if (op == LDAP_MOD_ADD) {
181155bf511dSas200622 attrs[++j]->mod_op = op;
181255bf511dSas200622 attrs[j]->mod_type = "objectClass";
18137f667e74Sjose borrego attrs[j]->mod_values = smb_ads_computer_objcls;
181455bf511dSas200622 }
1815da6c28aaSamw
181655bf511dSas200622 attrs[++j]->mod_op = op;
18173db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_SAMACCT;
1818da6c28aaSamw sam_val[0] = sam_acct;
1819da6c28aaSamw sam_val[1] = 0;
182055bf511dSas200622 attrs[j]->mod_values = sam_val;
1821da6c28aaSamw
182255bf511dSas200622 attrs[++j]->mod_op = op;
18233db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_UPN;
1824148c5f43SAlan Wright attrs[j]->mod_values = upn.s_pns;
1825da6c28aaSamw
182655bf511dSas200622 attrs[++j]->mod_op = op;
18273db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_SPN;
1828148c5f43SAlan Wright attrs[j]->mod_values = spn.s_pns;
1829da6c28aaSamw
183055bf511dSas200622 attrs[++j]->mod_op = op;
18313db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_CTL;
18323db3f65cSamw usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
18333db3f65cSamw SMB_ADS_USER_ACCT_CTL_PASSWD_NOTREQD |
18343db3f65cSamw SMB_ADS_USER_ACCT_CTL_ACCOUNTDISABLE);
1835da6c28aaSamw (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", usrctl_flags);
1836da6c28aaSamw ctl_val[0] = usrctl_buf;
1837da6c28aaSamw ctl_val[1] = 0;
183855bf511dSas200622 attrs[j]->mod_values = ctl_val;
1839da6c28aaSamw
184055bf511dSas200622 attrs[++j]->mod_op = op;
18413db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_DNSHOST;
1842da6c28aaSamw fqh_val[0] = fqhost;
1843da6c28aaSamw fqh_val[1] = 0;
184455bf511dSas200622 attrs[j]->mod_values = fqh_val;
1845da6c28aaSamw
18463db3f65cSamw /* enctypes support starting in Windows Server 2008 */
18473db3f65cSamw if (dclevel > SMB_ADS_DCLEVEL_W2K3) {
18483db3f65cSamw attrs[++j]->mod_op = op;
18493db3f65cSamw attrs[j]->mod_type = SMB_ADS_ATTR_ENCTYPES;
18503db3f65cSamw (void) snprintf(encrypt_buf, sizeof (encrypt_buf), "%d",
18513db3f65cSamw SMB_ADS_ENC_AES256 + SMB_ADS_ENC_AES128 + SMB_ADS_ENC_RC4 +
18523db3f65cSamw SMB_ADS_ENC_DES_MD5 + SMB_ADS_ENC_DES_CRC);
18533db3f65cSamw encrypt_val[0] = encrypt_buf;
18543db3f65cSamw encrypt_val[1] = 0;
18553db3f65cSamw attrs[j]->mod_values = encrypt_val;
18563db3f65cSamw }
18573db3f65cSamw
185855bf511dSas200622 switch (op) {
185955bf511dSas200622 case LDAP_MOD_ADD:
186055bf511dSas200622 if ((ret = ldap_add_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
1861fc724630SAlan Wright syslog(LOG_NOTICE, "ldap_add: %s",
186255bf511dSas200622 ldap_err2string(ret));
1863da6c28aaSamw ret = -1;
1864da6c28aaSamw }
186555bf511dSas200622 break;
1866da6c28aaSamw
186755bf511dSas200622 case LDAP_MOD_REPLACE:
186855bf511dSas200622 if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
1869fc724630SAlan Wright syslog(LOG_NOTICE, "ldap_modify: %s",
187055bf511dSas200622 ldap_err2string(ret));
187155bf511dSas200622 ret = -1;
187255bf511dSas200622 }
187355bf511dSas200622 break;
187455bf511dSas200622
187555bf511dSas200622 default:
187655bf511dSas200622 ret = -1;
187755bf511dSas200622
187855bf511dSas200622 }
187955bf511dSas200622
18803db3f65cSamw smb_ads_free_attr(attrs);
1881148c5f43SAlan Wright smb_krb5_free_pn_set(&spn);
1882148c5f43SAlan Wright smb_krb5_free_pn_set(&upn);
1883da6c28aaSamw
1884da6c28aaSamw return (ret);
1885da6c28aaSamw }
1886da6c28aaSamw
1887da6c28aaSamw /*
1888da6c28aaSamw * Delete an ADS computer account.
1889da6c28aaSamw */
1890da6c28aaSamw static void
smb_ads_del_computer(smb_ads_handle_t * ah,char * dn)1891c8ec8eeaSjose borrego smb_ads_del_computer(smb_ads_handle_t *ah, char *dn)
1892da6c28aaSamw {
1893da6c28aaSamw int rc;
1894da6c28aaSamw
18953db3f65cSamw if ((rc = ldap_delete_s(ah->ld, dn)) != LDAP_SUCCESS)
1896fc724630SAlan Wright smb_tracef("ldap_delete: %s", ldap_err2string(rc));
1897b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1898b89a8333Snatalie li - Sun Microsystems - Irvine United States
1899b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1900b89a8333Snatalie li - Sun Microsystems - Irvine United States * Gets the value of the given attribute.
1901b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1902b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t
smb_ads_getattr(LDAP * ld,LDAPMessage * entry,smb_ads_avpair_t * avpair)1903b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_getattr(LDAP *ld, LDAPMessage *entry, smb_ads_avpair_t *avpair)
1904b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1905b89a8333Snatalie li - Sun Microsystems - Irvine United States char **vals;
1906b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t rc = SMB_ADS_STAT_FOUND;
1907b89a8333Snatalie li - Sun Microsystems - Irvine United States
1908b89a8333Snatalie li - Sun Microsystems - Irvine United States assert(avpair);
1909b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair->avp_val = NULL;
1910b89a8333Snatalie li - Sun Microsystems - Irvine United States vals = ldap_get_values(ld, entry, avpair->avp_attr);
1911b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!vals)
1912b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1913b89a8333Snatalie li - Sun Microsystems - Irvine United States
1914b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!vals[0]) {
1915b89a8333Snatalie li - Sun Microsystems - Irvine United States ldap_value_free(vals);
1916b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1917b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1918b89a8333Snatalie li - Sun Microsystems - Irvine United States
1919b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair->avp_val = strdup(vals[0]);
1920b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!avpair->avp_val)
1921b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADS_STAT_ERR;
1922b89a8333Snatalie li - Sun Microsystems - Irvine United States
1923b89a8333Snatalie li - Sun Microsystems - Irvine United States ldap_value_free(vals);
1924b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1925b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1926b89a8333Snatalie li - Sun Microsystems - Irvine United States
1927b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1928b89a8333Snatalie li - Sun Microsystems - Irvine United States * Process query's result.
1929b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1930b89a8333Snatalie 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)1931b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_qstat(smb_ads_handle_t *ah, LDAPMessage *res,
1932b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t *avpair)
1933b89a8333Snatalie li - Sun Microsystems - Irvine United States {
1934b89a8333Snatalie li - Sun Microsystems - Irvine United States char fqhost[MAXHOSTNAMELEN];
1935b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t dnshost_avp;
1936b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t rc = SMB_ADS_STAT_FOUND;
1937b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAPMessage *entry;
1938b89a8333Snatalie li - Sun Microsystems - Irvine United States
1939b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_getfqhostname(ah, fqhost, MAXHOSTNAMELEN))
1940b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1941b89a8333Snatalie li - Sun Microsystems - Irvine United States
1942b89a8333Snatalie li - Sun Microsystems - Irvine United States if (ldap_count_entries(ah->ld, res) == 0)
1943b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
1944b89a8333Snatalie li - Sun Microsystems - Irvine United States
1945b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((entry = ldap_first_entry(ah->ld, res)) == NULL)
1946b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
1947b89a8333Snatalie li - Sun Microsystems - Irvine United States
1948b89a8333Snatalie li - Sun Microsystems - Irvine United States dnshost_avp.avp_attr = SMB_ADS_ATTR_DNSHOST;
1949b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_ads_getattr(ah->ld, entry, &dnshost_avp);
1950b89a8333Snatalie li - Sun Microsystems - Irvine United States
1951b89a8333Snatalie li - Sun Microsystems - Irvine United States switch (rc) {
1952b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_FOUND:
1953b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1954b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns SMB_ADS_STAT_DUP to avoid overwriting
1955b89a8333Snatalie li - Sun Microsystems - Irvine United States * the computer account of another system whose
1956b89a8333Snatalie li - Sun Microsystems - Irvine United States * NetBIOS name collides with that of the current
1957b89a8333Snatalie li - Sun Microsystems - Irvine United States * system.
1958b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1959b89a8333Snatalie li - Sun Microsystems - Irvine United States if (strcasecmp(dnshost_avp.avp_val, fqhost))
1960b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADS_STAT_DUP;
1961b89a8333Snatalie li - Sun Microsystems - Irvine United States
1962b89a8333Snatalie li - Sun Microsystems - Irvine United States free(dnshost_avp.avp_val);
1963b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1964b89a8333Snatalie li - Sun Microsystems - Irvine United States
1965b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_NOT_FOUND:
1966b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
1967b89a8333Snatalie li - Sun Microsystems - Irvine United States * Pre-created computer account doesn't have
1968b89a8333Snatalie li - Sun Microsystems - Irvine United States * the dNSHostname attribute. It's been observed
1969b89a8333Snatalie li - Sun Microsystems - Irvine United States * that the dNSHostname attribute is only set after
1970b89a8333Snatalie li - Sun Microsystems - Irvine United States * a successful domain join.
1971b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns SMB_ADS_STAT_FOUND as the account is
1972b89a8333Snatalie li - Sun Microsystems - Irvine United States * pre-created for the current system.
1973b89a8333Snatalie li - Sun Microsystems - Irvine United States */
1974b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADS_STAT_FOUND;
1975b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1976b89a8333Snatalie li - Sun Microsystems - Irvine United States
1977b89a8333Snatalie li - Sun Microsystems - Irvine United States default:
1978b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
1979b89a8333Snatalie li - Sun Microsystems - Irvine United States }
1980b89a8333Snatalie li - Sun Microsystems - Irvine United States
1981b89a8333Snatalie li - Sun Microsystems - Irvine United States if (rc != SMB_ADS_STAT_FOUND)
1982b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1983b89a8333Snatalie li - Sun Microsystems - Irvine United States
1984b89a8333Snatalie li - Sun Microsystems - Irvine United States if (avpair)
1985b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_ads_getattr(ah->ld, entry, avpair);
1986b89a8333Snatalie li - Sun Microsystems - Irvine United States
1987b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
1988b89a8333Snatalie li - Sun Microsystems - Irvine United States
1989da6c28aaSamw }
1990da6c28aaSamw
1991da6c28aaSamw /*
19923db3f65cSamw * smb_ads_lookup_computer_n_attr
1993da6c28aaSamw *
1994b89a8333Snatalie li - Sun Microsystems - Irvine United States * If avpair is NULL, checks the status of the specified computer account.
1995b89a8333Snatalie li - Sun Microsystems - Irvine United States * Otherwise, looks up the value of the specified computer account's attribute.
1996b89a8333Snatalie li - Sun Microsystems - Irvine United States * If found, the value field of the avpair will be allocated and set. The
1997b89a8333Snatalie li - Sun Microsystems - Irvine United States * caller should free the allocated buffer.
1998da6c28aaSamw *
1999da6c28aaSamw * Return:
2000b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_FOUND - if both the computer and the specified attribute is
2001b89a8333Snatalie li - Sun Microsystems - Irvine United States * found.
2002b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_NOT_FOUND - if either the computer or the specified attribute
2003b89a8333Snatalie li - Sun Microsystems - Irvine United States * is not found.
2004b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_DUP - if the computer account is already used by other systems
2005b89a8333Snatalie li - Sun Microsystems - Irvine United States * in the AD. This could happen if the hostname of multiple
2006b89a8333Snatalie li - Sun Microsystems - Irvine United States * systems resolved to the same NetBIOS name.
2007b89a8333Snatalie li - Sun Microsystems - Irvine United States * SMB_ADS_STAT_ERR - any failure.
2008da6c28aaSamw */
2009b89a8333Snatalie 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)2010b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_lookup_computer_n_attr(smb_ads_handle_t *ah, smb_ads_avpair_t *avpair,
2011c8ec8eeaSjose borrego int scope, char *dn)
2012da6c28aaSamw {
2013b89a8333Snatalie li - Sun Microsystems - Irvine United States char *attrs[3], filter[SMB_ADS_MAXBUFLEN];
2014b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAPMessage *res;
2015b89a8333Snatalie li - Sun Microsystems - Irvine United States char sam_acct[SMB_SAMACCT_MAXLEN], sam_acct2[SMB_SAMACCT_MAXLEN];
2016b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t rc;
2017da6c28aaSamw
2018b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getsamaccount(sam_acct, sizeof (sam_acct)) != 0)
2019b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
2020da6c28aaSamw
2021da6c28aaSamw res = NULL;
2022b89a8333Snatalie li - Sun Microsystems - Irvine United States attrs[0] = SMB_ADS_ATTR_DNSHOST;
2023da6c28aaSamw attrs[1] = NULL;
2024b89a8333Snatalie li - Sun Microsystems - Irvine United States attrs[2] = NULL;
2025da6c28aaSamw
2026b89a8333Snatalie li - Sun Microsystems - Irvine United States if (avpair) {
2027b89a8333Snatalie li - Sun Microsystems - Irvine United States if (!avpair->avp_attr)
2028b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
2029b89a8333Snatalie li - Sun Microsystems - Irvine United States
2030b89a8333Snatalie li - Sun Microsystems - Irvine United States attrs[1] = avpair->avp_attr;
2031b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2032b89a8333Snatalie li - Sun Microsystems - Irvine United States
2033b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_escape_search_filter_chars(sam_acct, sam_acct2) != 0)
2034b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_ERR);
2035da6c28aaSamw
2036c8ec8eeaSjose borrego (void) snprintf(filter, sizeof (filter),
2037b89a8333Snatalie li - Sun Microsystems - Irvine United States "(&(objectClass=computer)(%s=%s))", SMB_ADS_ATTR_SAMACCT,
2038b89a8333Snatalie li - Sun Microsystems - Irvine United States sam_acct2);
2039da6c28aaSamw
2040c8ec8eeaSjose borrego if (ldap_search_s(ah->ld, dn, scope, filter, attrs, 0,
2041da6c28aaSamw &res) != LDAP_SUCCESS) {
2042da6c28aaSamw (void) ldap_msgfree(res);
2043b89a8333Snatalie li - Sun Microsystems - Irvine United States return (SMB_ADS_STAT_NOT_FOUND);
2044da6c28aaSamw }
2045da6c28aaSamw
2046b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = smb_ads_get_qstat(ah, res, avpair);
2047da6c28aaSamw /* free the search results */
2048da6c28aaSamw (void) ldap_msgfree(res);
2049b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
2050da6c28aaSamw }
2051da6c28aaSamw
2052da6c28aaSamw /*
20533db3f65cSamw * smb_ads_find_computer
2054da6c28aaSamw *
2055c8ec8eeaSjose borrego * Starts by searching for the system's AD computer object in the default
2056c8ec8eeaSjose borrego * container (i.e. cn=Computers). If not found, searches the entire directory.
2057b89a8333Snatalie li - Sun Microsystems - Irvine United States * If found, 'dn' will be set to the distinguished name of the system's AD
2058b89a8333Snatalie li - Sun Microsystems - Irvine United States * computer object.
2059da6c28aaSamw */
2060b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_qstat_t
smb_ads_find_computer(smb_ads_handle_t * ah,char * dn)2061c8ec8eeaSjose borrego smb_ads_find_computer(smb_ads_handle_t *ah, char *dn)
2062da6c28aaSamw {
2063b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t stat;
2064b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t avpair;
2065c8ec8eeaSjose borrego
2066b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair.avp_attr = SMB_ADS_ATTR_DN;
2067b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_container_dn(ah, dn, SMB_ADS_DN_MAX);
2068b89a8333Snatalie li - Sun Microsystems - Irvine United States stat = smb_ads_lookup_computer_n_attr(ah, &avpair, LDAP_SCOPE_ONELEVEL,
2069b89a8333Snatalie li - Sun Microsystems - Irvine United States dn);
2070c8ec8eeaSjose borrego
2071b89a8333Snatalie li - Sun Microsystems - Irvine United States if (stat == SMB_ADS_STAT_NOT_FOUND) {
2072c8ec8eeaSjose borrego (void) strlcpy(dn, ah->domain_dn, SMB_ADS_DN_MAX);
2073b89a8333Snatalie li - Sun Microsystems - Irvine United States stat = smb_ads_lookup_computer_n_attr(ah, &avpair,
2074b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAP_SCOPE_SUBTREE, dn);
2075c8ec8eeaSjose borrego }
2076c8ec8eeaSjose borrego
2077b89a8333Snatalie li - Sun Microsystems - Irvine United States if (stat == SMB_ADS_STAT_FOUND) {
2078b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcpy(dn, avpair.avp_val, SMB_ADS_DN_MAX);
2079b89a8333Snatalie li - Sun Microsystems - Irvine United States free(avpair.avp_val);
2080b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2081b89a8333Snatalie li - Sun Microsystems - Irvine United States
2082b89a8333Snatalie li - Sun Microsystems - Irvine United States return (stat);
2083da6c28aaSamw }
2084da6c28aaSamw
2085da6c28aaSamw /*
20863db3f65cSamw * smb_ads_update_computer_cntrl_attr
2087da6c28aaSamw *
2088da6c28aaSamw * Modify the user account control attribute of an existing computer
2089da6c28aaSamw * object on AD.
2090da6c28aaSamw *
20917f667e74Sjose borrego * Returns LDAP error code.
2092da6c28aaSamw */
2093da6c28aaSamw static int
smb_ads_update_computer_cntrl_attr(smb_ads_handle_t * ah,int flags,char * dn)20947f667e74Sjose borrego smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *ah, int flags, char *dn)
2095da6c28aaSamw {
20966537f381Sas200622 LDAPMod *attrs[2];
2097da6c28aaSamw char *ctl_val[2];
20987f667e74Sjose borrego int ret = 0;
2099da6c28aaSamw char usrctl_buf[16];
2100da6c28aaSamw
21013db3f65cSamw if (smb_ads_alloc_attr(attrs, sizeof (attrs) / sizeof (LDAPMod *)) != 0)
21027f667e74Sjose borrego return (LDAP_NO_MEMORY);
21036537f381Sas200622
21046537f381Sas200622 attrs[0]->mod_op = LDAP_MOD_REPLACE;
21053db3f65cSamw attrs[0]->mod_type = SMB_ADS_ATTR_CTL;
2106da6c28aaSamw
21077f667e74Sjose borrego (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", flags);
2108da6c28aaSamw ctl_val[0] = usrctl_buf;
2109da6c28aaSamw ctl_val[1] = 0;
21106537f381Sas200622 attrs[0]->mod_values = ctl_val;
2111da6c28aaSamw if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
2112fc724630SAlan Wright syslog(LOG_NOTICE, "ldap_modify: %s", ldap_err2string(ret));
2113da6c28aaSamw }
2114da6c28aaSamw
21153db3f65cSamw smb_ads_free_attr(attrs);
2116da6c28aaSamw return (ret);
2117da6c28aaSamw }
2118da6c28aaSamw
2119da6c28aaSamw /*
21203db3f65cSamw * smb_ads_lookup_computer_attr_kvno
2121da6c28aaSamw *
2122da6c28aaSamw * Lookup the value of the Kerberos version number attribute of the computer
2123da6c28aaSamw * account.
2124da6c28aaSamw */
2125da6c28aaSamw static krb5_kvno
smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t * ah,char * dn)2126c8ec8eeaSjose borrego smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t *ah, char *dn)
2127da6c28aaSamw {
2128b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_avpair_t avpair;
2129da6c28aaSamw int kvno = 1;
2130da6c28aaSamw
2131b89a8333Snatalie li - Sun Microsystems - Irvine United States avpair.avp_attr = SMB_ADS_ATTR_KVNO;
2132b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_lookup_computer_n_attr(ah, &avpair,
2133b89a8333Snatalie li - Sun Microsystems - Irvine United States LDAP_SCOPE_BASE, dn) == SMB_ADS_STAT_FOUND) {
2134b89a8333Snatalie li - Sun Microsystems - Irvine United States kvno = atoi(avpair.avp_val);
2135b89a8333Snatalie li - Sun Microsystems - Irvine United States free(avpair.avp_val);
2136da6c28aaSamw }
2137da6c28aaSamw
2138da6c28aaSamw return (kvno);
2139da6c28aaSamw }
2140da6c28aaSamw
2141da6c28aaSamw /*
21423db3f65cSamw * smb_ads_join
2143da6c28aaSamw *
2144da6c28aaSamw * Besides the NT-4 style domain join (using MS-RPC), CIFS server also
2145da6c28aaSamw * provides the domain join using Kerberos Authentication, Keberos
214655bf511dSas200622 * Change & Set password, and LDAP protocols. Basically, AD join
2147da6c28aaSamw * operation would require the following tickets to be acquired for the
2148da6c28aaSamw * the user account that is provided for the domain join.
2149da6c28aaSamw *
2150da6c28aaSamw * 1) a Keberos TGT ticket,
2151da6c28aaSamw * 2) a ldap service ticket, and
2152da6c28aaSamw * 3) kadmin/changpw service ticket
2153da6c28aaSamw *
2154da6c28aaSamw * The ADS client first sends a ldap search request to find out whether
2155da6c28aaSamw * or not the workstation trust account already exists in the Active Directory.
2156da6c28aaSamw * The existing computer object for this workstation will be removed and
2157da6c28aaSamw * a new one will be added. The machine account password is randomly
21583db3f65cSamw * generated and set for the newly created computer object using KPASSWD
2159da6c28aaSamw * protocol (See RFC 3244). Once the password is set, our ADS client
2160da6c28aaSamw * finalizes the machine account by modifying the user acount control
2161da6c28aaSamw * attribute of the computer object. Kerberos keys derived from the machine
2162da6c28aaSamw * account password will be stored locally in /etc/krb5/krb5.keytab file.
2163da6c28aaSamw * That would be needed while acquiring Kerberos TGT ticket for the host
2164da6c28aaSamw * principal after the domain join operation.
2165da6c28aaSamw */
21663db3f65cSamw smb_adjoin_status_t
smb_ads_join(char * domain,char * user,char * usr_passwd,char * machine_passwd)21671ed6b69aSGordon Ross smb_ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd)
2168da6c28aaSamw {
21693db3f65cSamw smb_ads_handle_t *ah = NULL;
2170da6c28aaSamw krb5_context ctx = NULL;
2171148c5f43SAlan Wright krb5_principal *krb5princs = NULL;
2172da6c28aaSamw krb5_kvno kvno;
2173cbfb650aScp160787 boolean_t des_only, delete = B_TRUE;
21743db3f65cSamw smb_adjoin_status_t rc = SMB_ADJOIN_SUCCESS;
217555bf511dSas200622 boolean_t new_acct;
21767f667e74Sjose borrego int dclevel, num, usrctl_flags = 0;
2177b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_qstat_t qstat;
2178c8ec8eeaSjose borrego char dn[SMB_ADS_DN_MAX];
2179c28afb19SYuri Pankov char tmpfile[] = SMBNS_KRB5_KEYTAB_TMP;
2180148c5f43SAlan Wright int cnt;
2181148c5f43SAlan Wright smb_krb5_pn_set_t spns;
21823db3f65cSamw
21833db3f65cSamw krb5_enctype *encptr;
21843db3f65cSamw
21853db3f65cSamw if ((ah = smb_ads_open_main(domain, user, usr_passwd)) == NULL) {
2186faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
21873db3f65cSamw return (SMB_ADJOIN_ERR_GET_HANDLE);
218855bf511dSas200622 }
218955bf511dSas200622
21903db3f65cSamw if ((dclevel = smb_ads_get_dc_level(ah)) == -1) {
21913db3f65cSamw smb_ads_close(ah);
21923db3f65cSamw smb_ccache_remove(SMB_CCACHE_PATH);
21933db3f65cSamw return (SMB_ADJOIN_ERR_GET_DCLEVEL);
21943db3f65cSamw }
21953db3f65cSamw
2196b89a8333Snatalie li - Sun Microsystems - Irvine United States qstat = smb_ads_find_computer(ah, dn);
2197b89a8333Snatalie li - Sun Microsystems - Irvine United States switch (qstat) {
2198b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_FOUND:
219955bf511dSas200622 new_acct = B_FALSE;
2200c8ec8eeaSjose borrego if (smb_ads_modify_computer(ah, dclevel, dn) != 0) {
22013db3f65cSamw smb_ads_close(ah);
2202faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
22033db3f65cSamw return (SMB_ADJOIN_ERR_MOD_TRUST_ACCT);
220455bf511dSas200622 }
2205b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
2206b89a8333Snatalie li - Sun Microsystems - Irvine United States
2207b89a8333Snatalie li - Sun Microsystems - Irvine United States case SMB_ADS_STAT_NOT_FOUND:
220855bf511dSas200622 new_acct = B_TRUE;
2209b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_get_default_comp_dn(ah, dn, SMB_ADS_DN_MAX);
2210c8ec8eeaSjose borrego if (smb_ads_add_computer(ah, dclevel, dn) != 0) {
22113db3f65cSamw smb_ads_close(ah);
2212faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
22133db3f65cSamw return (SMB_ADJOIN_ERR_ADD_TRUST_ACCT);
221455bf511dSas200622 }
2215b89a8333Snatalie li - Sun Microsystems - Irvine United States break;
2216b89a8333Snatalie li - Sun Microsystems - Irvine United States
2217b89a8333Snatalie li - Sun Microsystems - Irvine United States default:
2218b89a8333Snatalie li - Sun Microsystems - Irvine United States if (qstat == SMB_ADS_STAT_DUP)
2219b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADJOIN_ERR_DUP_TRUST_ACCT;
2220b89a8333Snatalie li - Sun Microsystems - Irvine United States else
2221b89a8333Snatalie li - Sun Microsystems - Irvine United States rc = SMB_ADJOIN_ERR_TRUST_ACCT;
2222b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_close(ah);
2223b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ccache_remove(SMB_CCACHE_PATH);
2224b89a8333Snatalie li - Sun Microsystems - Irvine United States return (rc);
222555bf511dSas200622 }
222655bf511dSas200622
222755bf511dSas200622 des_only = B_FALSE;
2228da6c28aaSamw
2229da6c28aaSamw if (smb_krb5_ctx_init(&ctx) != 0) {
22303db3f65cSamw rc = SMB_ADJOIN_ERR_INIT_KRB_CTX;
2231da6c28aaSamw goto adjoin_cleanup;
2232da6c28aaSamw }
2233da6c28aaSamw
2234148c5f43SAlan Wright if (smb_krb5_get_pn_set(&spns, SMB_PN_KEYTAB_ENTRY, ah->domain) == 0) {
22353db3f65cSamw rc = SMB_ADJOIN_ERR_GET_SPNS;
2236da6c28aaSamw goto adjoin_cleanup;
2237da6c28aaSamw }
2238da6c28aaSamw
2239148c5f43SAlan Wright if (smb_krb5_get_kprincs(ctx, spns.s_pns, spns.s_cnt, &krb5princs)
2240148c5f43SAlan Wright != 0) {
2241148c5f43SAlan Wright smb_krb5_free_pn_set(&spns);
2242148c5f43SAlan Wright rc = SMB_ADJOIN_ERR_GET_SPNS;
2243148c5f43SAlan Wright goto adjoin_cleanup;
2244148c5f43SAlan Wright }
2245148c5f43SAlan Wright
2246148c5f43SAlan Wright cnt = spns.s_cnt;
2247148c5f43SAlan Wright smb_krb5_free_pn_set(&spns);
2248148c5f43SAlan Wright
22491ed6b69aSGordon Ross /* New machine_passwd was filled in by our caller. */
2250148c5f43SAlan Wright if (smb_krb5_setpwd(ctx, ah->domain, machine_passwd) != 0) {
22513db3f65cSamw rc = SMB_ADJOIN_ERR_KSETPWD;
2252da6c28aaSamw goto adjoin_cleanup;
2253da6c28aaSamw }
2254da6c28aaSamw
2255c8ec8eeaSjose borrego kvno = smb_ads_lookup_computer_attr_kvno(ah, dn);
225655bf511dSas200622
22577f667e74Sjose borrego /*
22587f667e74Sjose borrego * Only members of Domain Admins and Enterprise Admins can set
22597f667e74Sjose borrego * the TRUSTED_FOR_DELEGATION userAccountControl flag.
22607f667e74Sjose borrego */
22617f667e74Sjose borrego if (smb_ads_update_computer_cntrl_attr(ah,
2262037cac00Sjoyce mcintosh SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
22637f667e74Sjose borrego SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION, dn)
22647f667e74Sjose borrego == LDAP_INSUFFICIENT_ACCESS) {
22657f667e74Sjose borrego usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
22667f667e74Sjose borrego SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
22677f667e74Sjose borrego
2268fc724630SAlan Wright syslog(LOG_NOTICE, "Unable to set the "
22697f667e74Sjose borrego "TRUSTED_FOR_DELEGATION userAccountControl flag on "
22707f667e74Sjose borrego "the machine account in Active Directory. Please refer "
22717f667e74Sjose borrego "to the Troubleshooting guide for more information.");
22727f667e74Sjose borrego
22737f667e74Sjose borrego } else {
22747f667e74Sjose borrego usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
22757f667e74Sjose borrego SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION |
22767f667e74Sjose borrego SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
22777f667e74Sjose borrego }
22787f667e74Sjose borrego
22797f667e74Sjose borrego if (des_only)
22807f667e74Sjose borrego usrctl_flags |= SMB_ADS_USER_ACCT_CTL_USE_DES_KEY_ONLY;
22817f667e74Sjose borrego
22827f667e74Sjose borrego if (smb_ads_update_computer_cntrl_attr(ah, usrctl_flags, dn)
2283c8ec8eeaSjose borrego != 0) {
22843db3f65cSamw rc = SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR;
2285da6c28aaSamw goto adjoin_cleanup;
2286da6c28aaSamw }
228755bf511dSas200622
2288c28afb19SYuri Pankov if (mktemp(tmpfile) == NULL) {
2289c28afb19SYuri Pankov rc = SMB_ADJOIN_ERR_WRITE_KEYTAB;
2290c28afb19SYuri Pankov goto adjoin_cleanup;
2291c28afb19SYuri Pankov }
22928d7e4166Sjose borrego
2293148c5f43SAlan Wright encptr = smb_ads_get_enctypes(dclevel, &num);
2294148c5f43SAlan Wright if (smb_krb5_kt_populate(ctx, ah->domain, krb5princs, cnt,
2295148c5f43SAlan Wright tmpfile, kvno, machine_passwd, encptr, num) != 0) {
22963db3f65cSamw rc = SMB_ADJOIN_ERR_WRITE_KEYTAB;
2297da6c28aaSamw goto adjoin_cleanup;
2298da6c28aaSamw }
2299da6c28aaSamw
230055bf511dSas200622 delete = B_FALSE;
2301da6c28aaSamw adjoin_cleanup:
230255bf511dSas200622 if (new_acct && delete)
2303c8ec8eeaSjose borrego smb_ads_del_computer(ah, dn);
2304da6c28aaSamw
23053db3f65cSamw if (rc != SMB_ADJOIN_ERR_INIT_KRB_CTX) {
23063db3f65cSamw if (rc != SMB_ADJOIN_ERR_GET_SPNS)
2307148c5f43SAlan Wright smb_krb5_free_kprincs(ctx, krb5princs, cnt);
2308da6c28aaSamw smb_krb5_ctx_fini(ctx);
2309cbfb650aScp160787 }
2310da6c28aaSamw
23118d7e4166Sjose borrego /* commit keytab file */
23128d7e4166Sjose borrego if (rc == SMB_ADJOIN_SUCCESS) {
23138d7e4166Sjose borrego if (rename(tmpfile, SMBNS_KRB5_KEYTAB) != 0) {
23148d7e4166Sjose borrego (void) unlink(tmpfile);
23158d7e4166Sjose borrego rc = SMB_ADJOIN_ERR_COMMIT_KEYTAB;
23168d7e4166Sjose borrego }
23178d7e4166Sjose borrego } else {
23188d7e4166Sjose borrego (void) unlink(tmpfile);
23198d7e4166Sjose borrego }
23208d7e4166Sjose borrego
23213db3f65cSamw smb_ads_close(ah);
2322faa1795aSjb150015 smb_ccache_remove(SMB_CCACHE_PATH);
2323da6c28aaSamw return (rc);
2324da6c28aaSamw }
2325da6c28aaSamw
2326da6c28aaSamw /*
2327fc724630SAlan Wright * smb_ads_join_errmsg
2328da6c28aaSamw *
2329da6c28aaSamw * Display error message for the specific adjoin error code.
2330da6c28aaSamw */
2331fc724630SAlan Wright void
smb_ads_join_errmsg(smb_adjoin_status_t status)2332fc724630SAlan Wright smb_ads_join_errmsg(smb_adjoin_status_t status)
2333da6c28aaSamw {
2334fc724630SAlan Wright int i;
2335fc724630SAlan Wright struct xlate_table {
2336fc724630SAlan Wright smb_adjoin_status_t status;
2337fc724630SAlan Wright char *msg;
2338fc724630SAlan Wright } adjoin_table[] = {
2339fc724630SAlan Wright { SMB_ADJOIN_ERR_GET_HANDLE, "Failed to connect to an "
2340fc724630SAlan Wright "Active Directory server." },
234177191e87SShawn Emery { SMB_ADJOIN_ERR_GEN_PWD, "Failed to generate machine "
234277191e87SShawn Emery "password." },
2343fc724630SAlan Wright { SMB_ADJOIN_ERR_GET_DCLEVEL, "Unknown functional level of "
2344fc724630SAlan Wright "the domain controller. The rootDSE attribute named "
2345fc724630SAlan Wright "\"domainControllerFunctionality\" is missing from the "
2346fc724630SAlan Wright "Active Directory." },
2347fc724630SAlan Wright { SMB_ADJOIN_ERR_ADD_TRUST_ACCT, "Failed to create the "
2348fc724630SAlan Wright "workstation trust account." },
2349fc724630SAlan Wright { SMB_ADJOIN_ERR_MOD_TRUST_ACCT, "Failed to modify the "
2350fc724630SAlan Wright "workstation trust account." },
2351fc724630SAlan Wright { SMB_ADJOIN_ERR_DUP_TRUST_ACCT, "Failed to create the "
2352fc724630SAlan Wright "workstation trust account because its name is already "
2353fc724630SAlan Wright "in use." },
2354fc724630SAlan Wright { SMB_ADJOIN_ERR_TRUST_ACCT, "Error in querying the "
2355fc724630SAlan Wright "workstation trust account" },
2356fc724630SAlan Wright { SMB_ADJOIN_ERR_INIT_KRB_CTX, "Failed to initialize Kerberos "
2357fc724630SAlan Wright "context." },
2358fc724630SAlan Wright { SMB_ADJOIN_ERR_GET_SPNS, "Failed to get Kerberos "
2359fc724630SAlan Wright "principals." },
2360fc724630SAlan Wright { SMB_ADJOIN_ERR_KSETPWD, "Failed to set machine password." },
2361fc724630SAlan Wright { SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR, "Failed to modify "
2362fc724630SAlan Wright "userAccountControl attribute of the workstation trust "
2363fc724630SAlan Wright "account." },
2364fc724630SAlan Wright { SMB_ADJOIN_ERR_WRITE_KEYTAB, "Error in writing to local "
2365fc724630SAlan Wright "keytab file (i.e /etc/krb5/krb5.keytab)." },
2366fc724630SAlan Wright { SMB_ADJOIN_ERR_IDMAP_SET_DOMAIN, "Failed to update idmap "
2367fc724630SAlan Wright "configuration." },
2368fc724630SAlan Wright { SMB_ADJOIN_ERR_IDMAP_REFRESH, "Failed to refresh idmap "
2369fc724630SAlan Wright "service." },
2370fc724630SAlan Wright { SMB_ADJOIN_ERR_COMMIT_KEYTAB, "Failed to commit changes to "
2371fc724630SAlan Wright "local keytab file (i.e. /etc/krb5/krb5.keytab)." }
2372fc724630SAlan Wright };
2373da6c28aaSamw
2374fc724630SAlan Wright for (i = 0; i < sizeof (adjoin_table) / sizeof (adjoin_table[0]); i++) {
2375fc724630SAlan Wright if (adjoin_table[i].status == status)
2376fc724630SAlan Wright syslog(LOG_NOTICE, "%s", adjoin_table[i].msg);
2377fc724630SAlan Wright }
2378da6c28aaSamw }
2379c8ec8eeaSjose borrego
2380c8ec8eeaSjose borrego /*
238129bd2886SAlan Wright * smb_ads_match_pdc
2382b89a8333Snatalie li - Sun Microsystems - Irvine United States *
238329bd2886SAlan Wright * Returns B_TRUE if the given host's IP address matches the preferred DC's
238429bd2886SAlan Wright * IP address. Otherwise, returns B_FALSE.
2385b89a8333Snatalie li - Sun Microsystems - Irvine United States */
238629bd2886SAlan Wright static boolean_t
smb_ads_match_pdc(smb_ads_host_info_t * host)238729bd2886SAlan Wright smb_ads_match_pdc(smb_ads_host_info_t *host)
2388b89a8333Snatalie li - Sun Microsystems - Irvine United States {
238929bd2886SAlan Wright boolean_t match = B_FALSE;
2390b89a8333Snatalie li - Sun Microsystems - Irvine United States
239129bd2886SAlan Wright if (!host)
239229bd2886SAlan Wright return (match);
2393b89a8333Snatalie li - Sun Microsystems - Irvine United States
239429bd2886SAlan Wright (void) mutex_lock(&smb_ads_cfg.c_mtx);
239529bd2886SAlan Wright if (smb_inet_equal(&host->ipaddr, &smb_ads_cfg.c_pdc))
239629bd2886SAlan Wright match = B_TRUE;
239729bd2886SAlan Wright (void) mutex_unlock(&smb_ads_cfg.c_mtx);
2398b89a8333Snatalie li - Sun Microsystems - Irvine United States
239929bd2886SAlan Wright return (match);
2400b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2401b89a8333Snatalie li - Sun Microsystems - Irvine United States
2402b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
2403b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_select_dcfromsubnet
2404b89a8333Snatalie li - Sun Microsystems - Irvine United States *
2405b89a8333Snatalie li - Sun Microsystems - Irvine United States * This method walks the list of DCs and returns the first DC record that
2406b89a8333Snatalie li - Sun Microsystems - Irvine United States * responds to ldap ping and is in the same subnet as the host.
2407b89a8333Snatalie li - Sun Microsystems - Irvine United States *
2408b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns a pointer to the found DC record.
2409b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns NULL, on error or if no DC record is found.
2410b89a8333Snatalie li - Sun Microsystems - Irvine United States */
2411b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_info_t *
smb_ads_select_dcfromsubnet(smb_ads_host_list_t * hlist)2412b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_select_dcfromsubnet(smb_ads_host_list_t *hlist)
2413b89a8333Snatalie li - Sun Microsystems - Irvine United States {
2414b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *hentry;
2415b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_nic_t *lnic;
2416b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_niciter_t ni;
2417b89a8333Snatalie li - Sun Microsystems - Irvine United States size_t cnt;
2418b89a8333Snatalie li - Sun Microsystems - Irvine United States int i;
2419b89a8333Snatalie li - Sun Microsystems - Irvine United States
24209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_nic_getfirst(&ni) != SMB_NIC_SUCCESS)
2421b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
2422b89a8333Snatalie li - Sun Microsystems - Irvine United States do {
2423b89a8333Snatalie li - Sun Microsystems - Irvine United States lnic = &ni.ni_nic;
2424b89a8333Snatalie li - Sun Microsystems - Irvine United States cnt = hlist->ah_cnt;
2425b89a8333Snatalie li - Sun Microsystems - Irvine United States
2426b89a8333Snatalie li - Sun Microsystems - Irvine United States for (i = 0; i < cnt; i++) {
2427b89a8333Snatalie li - Sun Microsystems - Irvine United States hentry = &hlist->ah_list[i];
24287f667e74Sjose borrego if ((hentry->ipaddr.a_family == AF_INET) &&
24297f667e74Sjose borrego (lnic->nic_ip.a_family == AF_INET)) {
24307f667e74Sjose borrego if ((hentry->ipaddr.a_ipv4 &
24317f667e74Sjose borrego lnic->nic_mask) ==
24327f667e74Sjose borrego (lnic->nic_ip.a_ipv4 &
24337f667e74Sjose borrego lnic->nic_mask))
2434b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_ldap_ping(hentry) == 0)
2435b89a8333Snatalie li - Sun Microsystems - Irvine United States return (hentry);
2436b89a8333Snatalie li - Sun Microsystems - Irvine United States }
24377f667e74Sjose borrego }
24389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } while (smb_nic_getnext(&ni) == SMB_NIC_SUCCESS);
2439b89a8333Snatalie li - Sun Microsystems - Irvine United States
2440b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
2441b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2442b89a8333Snatalie li - Sun Microsystems - Irvine United States
2443b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
2444b89a8333Snatalie li - Sun Microsystems - Irvine United States * smb_ads_select_dcfromlist
2445b89a8333Snatalie li - Sun Microsystems - Irvine United States *
2446b89a8333Snatalie li - Sun Microsystems - Irvine United States * This method walks the list of DCs and returns the first DC that
2447b89a8333Snatalie li - Sun Microsystems - Irvine United States * responds to ldap ping.
2448b89a8333Snatalie li - Sun Microsystems - Irvine United States *
2449b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns a pointer to the found DC record.
2450b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns NULL if no DC record is found.
2451b89a8333Snatalie li - Sun Microsystems - Irvine United States */
2452b89a8333Snatalie li - Sun Microsystems - Irvine United States static smb_ads_host_info_t *
smb_ads_select_dcfromlist(smb_ads_host_list_t * hlist)2453b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_select_dcfromlist(smb_ads_host_list_t *hlist)
2454b89a8333Snatalie li - Sun Microsystems - Irvine United States {
2455b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *hentry;
2456b89a8333Snatalie li - Sun Microsystems - Irvine United States size_t cnt;
2457b89a8333Snatalie li - Sun Microsystems - Irvine United States int i;
2458b89a8333Snatalie li - Sun Microsystems - Irvine United States
2459b89a8333Snatalie li - Sun Microsystems - Irvine United States cnt = hlist->ah_cnt;
2460b89a8333Snatalie li - Sun Microsystems - Irvine United States for (i = 0; i < cnt; i++) {
2461b89a8333Snatalie li - Sun Microsystems - Irvine United States hentry = &hlist->ah_list[i];
2462b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_ldap_ping(hentry) == 0)
2463b89a8333Snatalie li - Sun Microsystems - Irvine United States return (hentry);
2464b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2465b89a8333Snatalie li - Sun Microsystems - Irvine United States
2466b89a8333Snatalie li - Sun Microsystems - Irvine United States return (NULL);
2467b89a8333Snatalie li - Sun Microsystems - Irvine United States }
2468b89a8333Snatalie li - Sun Microsystems - Irvine United States
2469b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
2470c8ec8eeaSjose borrego * smb_ads_dc_compare
2471c8ec8eeaSjose borrego *
2472c8ec8eeaSjose borrego * Comparision function for sorting host entries (SRV records of DC) via qsort.
2473b89a8333Snatalie li - Sun Microsystems - Irvine United States * RFC 2052/2782 are taken as reference, while implementing this algorithm.
2474b89a8333Snatalie li - Sun Microsystems - Irvine United States *
2475b89a8333Snatalie li - Sun Microsystems - Irvine United States * Domain Controllers(DCs) with lowest priority in their SRV DNS records
2476b89a8333Snatalie li - Sun Microsystems - Irvine United States * are selected first. If they have equal priorities, then DC with highest
2477b89a8333Snatalie li - Sun Microsystems - Irvine United States * weight in its SRV DNS record is selected. If the priority and weight are
2478b89a8333Snatalie li - Sun Microsystems - Irvine United States * both equal, then the DC at the top of the list is selected.
2479c8ec8eeaSjose borrego */
2480c8ec8eeaSjose borrego static int
smb_ads_dc_compare(const void * p,const void * q)2481c8ec8eeaSjose borrego smb_ads_dc_compare(const void *p, const void *q)
2482c8ec8eeaSjose borrego {
2483c8ec8eeaSjose borrego smb_ads_host_info_t *h1 = (smb_ads_host_info_t *)p;
2484c8ec8eeaSjose borrego smb_ads_host_info_t *h2 = (smb_ads_host_info_t *)q;
2485c8ec8eeaSjose borrego
2486c8ec8eeaSjose borrego if (h1->priority < h2->priority)
2487c8ec8eeaSjose borrego return (-1);
2488c8ec8eeaSjose borrego if (h1->priority > h2->priority)
2489c8ec8eeaSjose borrego return (1);
2490c8ec8eeaSjose borrego
2491c8ec8eeaSjose borrego /* Priorities are equal */
2492c8ec8eeaSjose borrego if (h1->weight < h2->weight)
2493c8ec8eeaSjose borrego return (1);
2494c8ec8eeaSjose borrego if (h1->weight > h2->weight)
2495c8ec8eeaSjose borrego return (-1);
2496c8ec8eeaSjose borrego
2497c8ec8eeaSjose borrego return (0);
2498c8ec8eeaSjose borrego }
2499c8ec8eeaSjose borrego
2500c8ec8eeaSjose borrego /*
2501c8ec8eeaSjose borrego * smb_ads_select_dc
2502c8ec8eeaSjose borrego *
2503b89a8333Snatalie li - Sun Microsystems - Irvine United States * The list of ADS hosts returned by ADS lookup, is sorted by lowest priority
2504b89a8333Snatalie li - Sun Microsystems - Irvine United States * and highest weight. On this sorted list, following additional rules are
2505b89a8333Snatalie li - Sun Microsystems - Irvine United States * applied, to select a DC.
2506c8ec8eeaSjose borrego *
2507b89a8333Snatalie li - Sun Microsystems - Irvine United States * - If there is a DC in the same subnet, then return the DC,
2508b89a8333Snatalie li - Sun Microsystems - Irvine United States * if it responds to ldap ping.
2509b89a8333Snatalie li - Sun Microsystems - Irvine United States * - Else, return first DC that responds to ldap ping.
2510b89a8333Snatalie li - Sun Microsystems - Irvine United States *
2511b89a8333Snatalie li - Sun Microsystems - Irvine United States * A reference to the host entry from input host list is returned.
2512c8ec8eeaSjose borrego *
2513c8ec8eeaSjose borrego * Returns NULL on error.
2514c8ec8eeaSjose borrego */
2515c8ec8eeaSjose borrego static smb_ads_host_info_t *
smb_ads_select_dc(smb_ads_host_list_t * hlist)2516c8ec8eeaSjose borrego smb_ads_select_dc(smb_ads_host_list_t *hlist)
2517c8ec8eeaSjose borrego {
2518b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_ads_host_info_t *hentry = NULL;
2519c8ec8eeaSjose borrego
2520b89a8333Snatalie li - Sun Microsystems - Irvine United States if (hlist->ah_cnt == 0)
2521c8ec8eeaSjose borrego return (NULL);
2522c8ec8eeaSjose borrego
2523b89a8333Snatalie li - Sun Microsystems - Irvine United States if (hlist->ah_cnt == 1) {
2524b89a8333Snatalie li - Sun Microsystems - Irvine United States hentry = hlist->ah_list;
2525b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_ads_ldap_ping(hentry) == 0)
2526b89a8333Snatalie li - Sun Microsystems - Irvine United States return (hentry);
2527c8ec8eeaSjose borrego }
2528c8ec8eeaSjose borrego
2529b89a8333Snatalie li - Sun Microsystems - Irvine United States /* Sort the list by priority and weight */
2530b89a8333Snatalie li - Sun Microsystems - Irvine United States qsort(hlist->ah_list, hlist->ah_cnt,
2531b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (smb_ads_host_info_t), smb_ads_dc_compare);
2532c8ec8eeaSjose borrego
2533b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((hentry = smb_ads_select_dcfromsubnet(hlist)) != NULL)
2534b89a8333Snatalie li - Sun Microsystems - Irvine United States return (hentry);
2535b89a8333Snatalie li - Sun Microsystems - Irvine United States
2536b89a8333Snatalie li - Sun Microsystems - Irvine United States if ((hentry = smb_ads_select_dcfromlist(hlist)) != NULL)
2537b89a8333Snatalie li - Sun Microsystems - Irvine United States return (hentry);
2538b89a8333Snatalie li - Sun Microsystems - Irvine United States
2539c8ec8eeaSjose borrego return (NULL);
2540c8ec8eeaSjose borrego }
25418d7e4166Sjose borrego
25428d7e4166Sjose borrego /*
25438d7e4166Sjose borrego * smb_ads_lookup_msdcs
25448d7e4166Sjose borrego *
25458d7e4166Sjose borrego * If server argument is set, try to locate the specified DC.
25468d7e4166Sjose borrego * If it is set to empty string, locate any DCs in the specified domain.
25478d7e4166Sjose borrego * Returns the discovered DC via buf.
25488d7e4166Sjose borrego *
25498d7e4166Sjose borrego * fqdn - fully-qualified domain name
25508d7e4166Sjose borrego * server - fully-qualifed hostname of a DC
25518d7e4166Sjose borrego * buf - the hostname of the discovered DC
25528d7e4166Sjose borrego */
25538d7e4166Sjose borrego boolean_t
smb_ads_lookup_msdcs(char * fqdn,char * server,char * buf,uint32_t buflen)25548d7e4166Sjose borrego smb_ads_lookup_msdcs(char *fqdn, char *server, char *buf, uint32_t buflen)
25558d7e4166Sjose borrego {
25568d7e4166Sjose borrego smb_ads_host_info_t *hinfo = NULL;
25578d7e4166Sjose borrego char *p;
25588d7e4166Sjose borrego char *sought_host;
25597f667e74Sjose borrego char ipstr[INET6_ADDRSTRLEN];
25608d7e4166Sjose borrego
25618d7e4166Sjose borrego if (!fqdn || !buf)
25628d7e4166Sjose borrego return (B_FALSE);
25638d7e4166Sjose borrego
256432b8d01aSChristopher Parker ipstr[0] = '\0';
25658d7e4166Sjose borrego *buf = '\0';
25668d7e4166Sjose borrego sought_host = (*server == 0 ? NULL : server);
25678d7e4166Sjose borrego if ((hinfo = smb_ads_find_host(fqdn, sought_host)) == NULL)
25688d7e4166Sjose borrego return (B_FALSE);
25698d7e4166Sjose borrego
257032b8d01aSChristopher Parker (void) smb_inet_ntop(&hinfo->ipaddr, ipstr,
257132b8d01aSChristopher Parker SMB_IPSTRLEN(hinfo->ipaddr.a_family));
257232b8d01aSChristopher Parker smb_tracef("msdcsLookupADS: %s [%s]", hinfo->name, ipstr);
25738d7e4166Sjose borrego
25748d7e4166Sjose borrego (void) strlcpy(buf, hinfo->name, buflen);
25758d7e4166Sjose borrego /*
25768d7e4166Sjose borrego * Remove the domain extension
25778d7e4166Sjose borrego */
25788d7e4166Sjose borrego if ((p = strchr(buf, '.')) != 0)
25798d7e4166Sjose borrego *p = '\0';
25808d7e4166Sjose borrego
258129bd2886SAlan Wright free(hinfo);
25828d7e4166Sjose borrego return (B_TRUE);
25838d7e4166Sjose borrego }
2584148c5f43SAlan Wright
2585148c5f43SAlan Wright static krb5_enctype *
smb_ads_get_enctypes(int dclevel,int * num)2586148c5f43SAlan Wright smb_ads_get_enctypes(int dclevel, int *num)
2587148c5f43SAlan Wright {
2588148c5f43SAlan Wright krb5_enctype *encptr;
2589148c5f43SAlan Wright
2590148c5f43SAlan Wright if (dclevel >= SMB_ADS_DCLEVEL_W2K8) {
2591148c5f43SAlan Wright *num = sizeof (w2k8enctypes) / sizeof (krb5_enctype);
2592148c5f43SAlan Wright encptr = w2k8enctypes;
2593148c5f43SAlan Wright } else {
2594148c5f43SAlan Wright *num = sizeof (pre_w2k8enctypes) / sizeof (krb5_enctype);
2595148c5f43SAlan Wright encptr = pre_w2k8enctypes;
2596148c5f43SAlan Wright }
2597148c5f43SAlan Wright
2598148c5f43SAlan Wright return (encptr);
2599148c5f43SAlan Wright }
2600