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