18d7e4166Sjose borrego /* 28d7e4166Sjose borrego * CDDL HEADER START 38d7e4166Sjose borrego * 48d7e4166Sjose borrego * The contents of this file are subject to the terms of the 58d7e4166Sjose borrego * Common Development and Distribution License (the "License"). 68d7e4166Sjose borrego * You may not use this file except in compliance with the License. 78d7e4166Sjose borrego * 88d7e4166Sjose borrego * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98d7e4166Sjose borrego * or http://www.opensolaris.org/os/licensing. 108d7e4166Sjose borrego * See the License for the specific language governing permissions 118d7e4166Sjose borrego * and limitations under the License. 128d7e4166Sjose borrego * 138d7e4166Sjose borrego * When distributing Covered Code, include this CDDL HEADER in each 148d7e4166Sjose borrego * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158d7e4166Sjose borrego * If applicable, add the following below this CDDL HEADER, with the 168d7e4166Sjose borrego * fields enclosed by brackets "[]" replaced with your own identifying 178d7e4166Sjose borrego * information: Portions Copyright [yyyy] [name of copyright owner] 188d7e4166Sjose borrego * 198d7e4166Sjose borrego * CDDL HEADER END 208d7e4166Sjose borrego */ 21148c5f43SAlan Wright 228d7e4166Sjose borrego /* 23148c5f43SAlan Wright * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24*b3700b07SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 258d7e4166Sjose borrego */ 268d7e4166Sjose borrego 278d7e4166Sjose borrego #include <syslog.h> 288d7e4166Sjose borrego #include <synch.h> 298d7e4166Sjose borrego #include <pthread.h> 308d7e4166Sjose borrego #include <unistd.h> 318d7e4166Sjose borrego #include <string.h> 328d7e4166Sjose borrego #include <strings.h> 338d7e4166Sjose borrego #include <sys/errno.h> 348d7e4166Sjose borrego #include <sys/types.h> 358d7e4166Sjose borrego #include <netinet/in.h> 368d7e4166Sjose borrego #include <arpa/nameser.h> 378d7e4166Sjose borrego #include <resolv.h> 388d7e4166Sjose borrego #include <netdb.h> 398d7e4166Sjose borrego #include <assert.h> 408d7e4166Sjose borrego 418d7e4166Sjose borrego #include <smbsrv/libsmb.h> 428d7e4166Sjose borrego #include <smbsrv/libsmbns.h> 438d7e4166Sjose borrego #include <smbsrv/libmlsvc.h> 448d7e4166Sjose borrego 458d7e4166Sjose borrego #include <smbsrv/smbinfo.h> 468d7e4166Sjose borrego #include <lsalib.h> 47*b3700b07SGordon Ross #include <mlsvc.h> 488d7e4166Sjose borrego 498d7e4166Sjose borrego /* 508d7e4166Sjose borrego * DC Locator 518d7e4166Sjose borrego */ 52a0aa776eSAlan Wright #define SMB_DCLOCATOR_TIMEOUT 45 /* seconds */ 538d7e4166Sjose borrego #define SMB_IS_FQDN(domain) (strchr(domain, '.') != NULL) 548d7e4166Sjose borrego 558d7e4166Sjose borrego typedef struct smb_dclocator { 56*b3700b07SGordon Ross smb_dcinfo_t sdl_dci; /* .dc_name .dc_addr */ 578d7e4166Sjose borrego char sdl_domain[SMB_PI_MAX_DOMAIN]; 588d7e4166Sjose borrego boolean_t sdl_locate; 59*b3700b07SGordon Ross boolean_t sdl_bad_dc; 60*b3700b07SGordon Ross boolean_t sdl_cfg_chg; 618d7e4166Sjose borrego mutex_t sdl_mtx; 628d7e4166Sjose borrego cond_t sdl_cv; 638d7e4166Sjose borrego uint32_t sdl_status; 648d7e4166Sjose borrego } smb_dclocator_t; 658d7e4166Sjose borrego 668d7e4166Sjose borrego static smb_dclocator_t smb_dclocator; 678d7e4166Sjose borrego static pthread_t smb_dclocator_thr; 688d7e4166Sjose borrego 69a0aa776eSAlan Wright static void *smb_ddiscover_service(void *); 70a0aa776eSAlan Wright static uint32_t smb_ddiscover_qinfo(char *, char *, smb_domainex_t *); 71a0aa776eSAlan Wright static void smb_ddiscover_enum_trusted(char *, char *, smb_domainex_t *); 72a0aa776eSAlan Wright static uint32_t smb_ddiscover_use_config(char *, smb_domainex_t *); 73a0aa776eSAlan Wright static void smb_domainex_free(smb_domainex_t *); 74*b3700b07SGordon Ross static void smb_set_krb5_realm(char *); 758d7e4166Sjose borrego 768d7e4166Sjose borrego /* 778d7e4166Sjose borrego * =================================================================== 788d7e4166Sjose borrego * API to initialize DC locator thread, trigger DC discovery, and 798d7e4166Sjose borrego * get the discovered DC and/or domain information. 808d7e4166Sjose borrego * =================================================================== 818d7e4166Sjose borrego */ 828d7e4166Sjose borrego 838d7e4166Sjose borrego /* 848d7e4166Sjose borrego * Initialization of the DC locator thread. 858d7e4166Sjose borrego * Returns 0 on success, an error number if thread creation fails. 868d7e4166Sjose borrego */ 878d7e4166Sjose borrego int 888d7e4166Sjose borrego smb_dclocator_init(void) 898d7e4166Sjose borrego { 908d7e4166Sjose borrego pthread_attr_t tattr; 918d7e4166Sjose borrego int rc; 928d7e4166Sjose borrego 938d7e4166Sjose borrego (void) pthread_attr_init(&tattr); 948d7e4166Sjose borrego (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 958d7e4166Sjose borrego rc = pthread_create(&smb_dclocator_thr, &tattr, 96*b3700b07SGordon Ross smb_ddiscover_service, &smb_dclocator); 978d7e4166Sjose borrego (void) pthread_attr_destroy(&tattr); 988d7e4166Sjose borrego return (rc); 998d7e4166Sjose borrego } 1008d7e4166Sjose borrego 1018d7e4166Sjose borrego /* 1028d7e4166Sjose borrego * This is the entry point for discovering a domain controller for the 103*b3700b07SGordon Ross * specified domain. Called during join domain, and then periodically 104*b3700b07SGordon Ross * by smbd_dc_update (the "DC monitor" thread). 1058d7e4166Sjose borrego * 1068d7e4166Sjose borrego * The actual work of discovering a DC is handled by DC locator thread. 1078d7e4166Sjose borrego * All we do here is signal the request and wait for a DC or a timeout. 1088d7e4166Sjose borrego * 1098d7e4166Sjose borrego * Input parameters: 1108d7e4166Sjose borrego * domain - domain to be discovered (can either be NetBIOS or DNS domain) 1118d7e4166Sjose borrego * 1128d7e4166Sjose borrego * Output parameter: 1138d7e4166Sjose borrego * dp - on success, dp will be filled with the discovered DC and domain 1148d7e4166Sjose borrego * information. 115*b3700b07SGordon Ross * 1168d7e4166Sjose borrego * Returns B_TRUE if the DC/domain info is available. 1178d7e4166Sjose borrego */ 1188d7e4166Sjose borrego boolean_t 119*b3700b07SGordon Ross smb_locate_dc(char *domain, smb_domainex_t *dp) 1208d7e4166Sjose borrego { 1218d7e4166Sjose borrego int rc; 122*b3700b07SGordon Ross boolean_t rv; 1238d7e4166Sjose borrego timestruc_t to; 124a0aa776eSAlan Wright smb_domainex_t domain_info; 1258d7e4166Sjose borrego 126*b3700b07SGordon Ross if (domain == NULL || *domain == '\0') { 127*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_locate_dc NULL dom"); 128*b3700b07SGordon Ross smb_set_krb5_realm(NULL); 1298d7e4166Sjose borrego return (B_FALSE); 130*b3700b07SGordon Ross } 1318d7e4166Sjose borrego 1328d7e4166Sjose borrego (void) mutex_lock(&smb_dclocator.sdl_mtx); 1338d7e4166Sjose borrego 134*b3700b07SGordon Ross if (strcmp(smb_dclocator.sdl_domain, domain)) { 135*b3700b07SGordon Ross (void) strlcpy(smb_dclocator.sdl_domain, domain, 136*b3700b07SGordon Ross sizeof (smb_dclocator.sdl_domain)); 137*b3700b07SGordon Ross smb_dclocator.sdl_cfg_chg = B_TRUE; 138*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_locate_dc new dom=%s", domain); 139*b3700b07SGordon Ross smb_set_krb5_realm(domain); 140*b3700b07SGordon Ross } 141*b3700b07SGordon Ross 1428d7e4166Sjose borrego if (!smb_dclocator.sdl_locate) { 1438d7e4166Sjose borrego smb_dclocator.sdl_locate = B_TRUE; 1448d7e4166Sjose borrego (void) cond_broadcast(&smb_dclocator.sdl_cv); 1458d7e4166Sjose borrego } 1468d7e4166Sjose borrego 1478d7e4166Sjose borrego while (smb_dclocator.sdl_locate) { 1488d7e4166Sjose borrego to.tv_sec = SMB_DCLOCATOR_TIMEOUT; 1498d7e4166Sjose borrego to.tv_nsec = 0; 1508d7e4166Sjose borrego rc = cond_reltimedwait(&smb_dclocator.sdl_cv, 1518d7e4166Sjose borrego &smb_dclocator.sdl_mtx, &to); 1528d7e4166Sjose borrego 153*b3700b07SGordon Ross if (rc == ETIME) { 154*b3700b07SGordon Ross syslog(LOG_NOTICE, "smb_locate_dc timeout"); 155*b3700b07SGordon Ross rv = B_FALSE; 156*b3700b07SGordon Ross goto out; 157*b3700b07SGordon Ross } 158*b3700b07SGordon Ross } 159*b3700b07SGordon Ross if (smb_dclocator.sdl_status != 0) { 160*b3700b07SGordon Ross syslog(LOG_NOTICE, "smb_locate_dc status 0x%x", 161*b3700b07SGordon Ross smb_dclocator.sdl_status); 162*b3700b07SGordon Ross rv = B_FALSE; 163*b3700b07SGordon Ross goto out; 1648d7e4166Sjose borrego } 1658d7e4166Sjose borrego 1668d7e4166Sjose borrego if (dp == NULL) 1678d7e4166Sjose borrego dp = &domain_info; 168*b3700b07SGordon Ross rv = smb_domain_getinfo(dp); 16929bd2886SAlan Wright 170*b3700b07SGordon Ross out: 1718d7e4166Sjose borrego (void) mutex_unlock(&smb_dclocator.sdl_mtx); 1728d7e4166Sjose borrego 173*b3700b07SGordon Ross return (rv); 174*b3700b07SGordon Ross } 175*b3700b07SGordon Ross 176*b3700b07SGordon Ross /* 177*b3700b07SGordon Ross * Tell the domain discovery service to run again now, 178*b3700b07SGordon Ross * and assume changed configuration (i.e. a new DC). 179*b3700b07SGordon Ross * Like the first part of smb_locate_dc(). 180*b3700b07SGordon Ross * 181*b3700b07SGordon Ross * Note: This is called from the service refresh handler 182*b3700b07SGordon Ross * and the door handler to tell the ddiscover thread to 183*b3700b07SGordon Ross * request the new DC from idmap. Therefore, we must not 184*b3700b07SGordon Ross * trigger a new idmap discovery run from here, or that 185*b3700b07SGordon Ross * would start a ping-pong match. 186*b3700b07SGordon Ross */ 187*b3700b07SGordon Ross /* ARGSUSED */ 188*b3700b07SGordon Ross void 189*b3700b07SGordon Ross smb_ddiscover_refresh() 190*b3700b07SGordon Ross { 191*b3700b07SGordon Ross 192*b3700b07SGordon Ross (void) mutex_lock(&smb_dclocator.sdl_mtx); 193*b3700b07SGordon Ross 194*b3700b07SGordon Ross if (smb_dclocator.sdl_cfg_chg == B_FALSE) { 195*b3700b07SGordon Ross smb_dclocator.sdl_cfg_chg = B_TRUE; 196*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_refresh set cfg changed"); 197*b3700b07SGordon Ross } 198*b3700b07SGordon Ross if (!smb_dclocator.sdl_locate) { 199*b3700b07SGordon Ross smb_dclocator.sdl_locate = B_TRUE; 200*b3700b07SGordon Ross (void) cond_broadcast(&smb_dclocator.sdl_cv); 201*b3700b07SGordon Ross } 202*b3700b07SGordon Ross 203*b3700b07SGordon Ross (void) mutex_unlock(&smb_dclocator.sdl_mtx); 204*b3700b07SGordon Ross } 205*b3700b07SGordon Ross 206*b3700b07SGordon Ross /* 207*b3700b07SGordon Ross * Called by our client-side threads after they fail to connect to 208*b3700b07SGordon Ross * the DC given to them by smb_locate_dc(). This is often called 209*b3700b07SGordon Ross * after some delay, because the connection timeout delays these 210*b3700b07SGordon Ross * threads for a while, so it's quite common that the DC locator 211*b3700b07SGordon Ross * service has already started looking for a new DC. These late 212*b3700b07SGordon Ross * notifications should not continually restart the DC locator. 213*b3700b07SGordon Ross */ 214*b3700b07SGordon Ross void 215*b3700b07SGordon Ross smb_ddiscover_bad_dc(char *bad_dc) 216*b3700b07SGordon Ross { 217*b3700b07SGordon Ross 218*b3700b07SGordon Ross assert(bad_dc[0] != '\0'); 219*b3700b07SGordon Ross 220*b3700b07SGordon Ross (void) mutex_lock(&smb_dclocator.sdl_mtx); 221*b3700b07SGordon Ross 222*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_bad_dc, cur=%s, bad=%s", 223*b3700b07SGordon Ross smb_dclocator.sdl_dci.dc_name, bad_dc); 224*b3700b07SGordon Ross 225*b3700b07SGordon Ross if (strcmp(smb_dclocator.sdl_dci.dc_name, bad_dc)) { 226*b3700b07SGordon Ross /* 227*b3700b07SGordon Ross * The "bad" DC is no longer the current one. 228*b3700b07SGordon Ross * Probably a late "bad DC" report. 229*b3700b07SGordon Ross */ 230*b3700b07SGordon Ross goto out; 231*b3700b07SGordon Ross } 232*b3700b07SGordon Ross if (smb_dclocator.sdl_bad_dc) { 233*b3700b07SGordon Ross /* Someone already marked the current DC as "bad". */ 234*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_bad_dc repeat"); 235*b3700b07SGordon Ross goto out; 236*b3700b07SGordon Ross } 237*b3700b07SGordon Ross 238*b3700b07SGordon Ross /* 239*b3700b07SGordon Ross * Mark the current DC as "bad" and let the DC Locator 240*b3700b07SGordon Ross * run again if it's not already. 241*b3700b07SGordon Ross */ 242*b3700b07SGordon Ross syslog(LOG_INFO, "smb_ddiscover, bad DC: %s", bad_dc); 243*b3700b07SGordon Ross smb_dclocator.sdl_bad_dc = B_TRUE; 244*b3700b07SGordon Ross 245*b3700b07SGordon Ross /* In-line smb_ddiscover_kick */ 246*b3700b07SGordon Ross if (!smb_dclocator.sdl_locate) { 247*b3700b07SGordon Ross smb_dclocator.sdl_locate = B_TRUE; 248*b3700b07SGordon Ross (void) cond_broadcast(&smb_dclocator.sdl_cv); 249*b3700b07SGordon Ross } 250*b3700b07SGordon Ross 251*b3700b07SGordon Ross out: 252*b3700b07SGordon Ross (void) mutex_unlock(&smb_dclocator.sdl_mtx); 2538d7e4166Sjose borrego } 2548d7e4166Sjose borrego 2558d7e4166Sjose borrego /* 256380acbbeSGordon Ross * If domain discovery is running, wait for it to finish. 257380acbbeSGordon Ross */ 258380acbbeSGordon Ross int 259380acbbeSGordon Ross smb_ddiscover_wait(void) 260380acbbeSGordon Ross { 261380acbbeSGordon Ross timestruc_t to; 262380acbbeSGordon Ross int rc = 0; 263380acbbeSGordon Ross 264380acbbeSGordon Ross (void) mutex_lock(&smb_dclocator.sdl_mtx); 265380acbbeSGordon Ross 266380acbbeSGordon Ross if (smb_dclocator.sdl_locate) { 267380acbbeSGordon Ross to.tv_sec = SMB_DCLOCATOR_TIMEOUT; 268380acbbeSGordon Ross to.tv_nsec = 0; 269380acbbeSGordon Ross rc = cond_reltimedwait(&smb_dclocator.sdl_cv, 270380acbbeSGordon Ross &smb_dclocator.sdl_mtx, &to); 271380acbbeSGordon Ross } 272380acbbeSGordon Ross 273380acbbeSGordon Ross (void) mutex_unlock(&smb_dclocator.sdl_mtx); 274380acbbeSGordon Ross 275380acbbeSGordon Ross return (rc); 276380acbbeSGordon Ross } 277380acbbeSGordon Ross 278380acbbeSGordon Ross 279380acbbeSGordon Ross /* 2808d7e4166Sjose borrego * ========================================================== 2818d7e4166Sjose borrego * DC discovery functions 2828d7e4166Sjose borrego * ========================================================== 2838d7e4166Sjose borrego */ 2848d7e4166Sjose borrego 2858d7e4166Sjose borrego /* 286a0aa776eSAlan Wright * This is the domain and DC discovery service: it gets woken up whenever 287a0aa776eSAlan Wright * there is need to locate a domain controller. 2888d7e4166Sjose borrego * 28929bd2886SAlan Wright * Upon success, the SMB domain cache will be populated with the discovered 29029bd2886SAlan Wright * DC and domain info. 2918d7e4166Sjose borrego */ 2928d7e4166Sjose borrego /*ARGSUSED*/ 2938d7e4166Sjose borrego static void * 294a0aa776eSAlan Wright smb_ddiscover_service(void *arg) 2958d7e4166Sjose borrego { 296*b3700b07SGordon Ross smb_domainex_t dxi; 297*b3700b07SGordon Ross smb_dclocator_t *sdl = arg; 298*b3700b07SGordon Ross uint32_t status; 299*b3700b07SGordon Ross boolean_t bad_dc; 300*b3700b07SGordon Ross boolean_t cfg_chg; 3018d7e4166Sjose borrego 3028d7e4166Sjose borrego for (;;) { 303*b3700b07SGordon Ross /* 304*b3700b07SGordon Ross * Wait to be signaled for work by one of: 305*b3700b07SGordon Ross * smb_locate_dc(), smb_ddiscover_refresh(), 306*b3700b07SGordon Ross * smb_ddiscover_bad_dc() 307*b3700b07SGordon Ross */ 308*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_service waiting"); 3098d7e4166Sjose borrego 310*b3700b07SGordon Ross (void) mutex_lock(&sdl->sdl_mtx); 311*b3700b07SGordon Ross while (!sdl->sdl_locate) 312*b3700b07SGordon Ross (void) cond_wait(&sdl->sdl_cv, 313*b3700b07SGordon Ross &sdl->sdl_mtx); 3148d7e4166Sjose borrego 315*b3700b07SGordon Ross if (!smb_config_getbool(SMB_CI_DOMAIN_MEMB)) { 316*b3700b07SGordon Ross sdl->sdl_status = NT_STATUS_INVALID_SERVER_STATE; 317*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_service: " 318*b3700b07SGordon Ross "not a domain member"); 319*b3700b07SGordon Ross goto wait_again; 320*b3700b07SGordon Ross } 3218d7e4166Sjose borrego 322*b3700b07SGordon Ross /* 323*b3700b07SGordon Ross * Want to know if these change below. 324*b3700b07SGordon Ross * Note: mutex held here 325*b3700b07SGordon Ross */ 326*b3700b07SGordon Ross find_again: 327*b3700b07SGordon Ross bad_dc = sdl->sdl_bad_dc; 328*b3700b07SGordon Ross sdl->sdl_bad_dc = B_FALSE; 329*b3700b07SGordon Ross if (bad_dc) { 330*b3700b07SGordon Ross /* 331*b3700b07SGordon Ross * Need to clear the current DC name or 332*b3700b07SGordon Ross * ddiscover_bad_dc will keep setting bad_dc 333*b3700b07SGordon Ross */ 334*b3700b07SGordon Ross sdl->sdl_dci.dc_name[0] = '\0'; 335*b3700b07SGordon Ross } 336*b3700b07SGordon Ross cfg_chg = sdl->sdl_cfg_chg; 337*b3700b07SGordon Ross sdl->sdl_cfg_chg = B_FALSE; 3388d7e4166Sjose borrego 339*b3700b07SGordon Ross (void) mutex_unlock(&sdl->sdl_mtx); 340*b3700b07SGordon Ross 341*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_service running " 342*b3700b07SGordon Ross "cfg_chg=%d bad_dc=%d", (int)cfg_chg, (int)bad_dc); 343*b3700b07SGordon Ross 344*b3700b07SGordon Ross /* 345*b3700b07SGordon Ross * Clear the cached DC now so that we'll ask idmap again. 346*b3700b07SGordon Ross * If our current DC gave us errors, force rediscovery. 347*b3700b07SGordon Ross */ 348*b3700b07SGordon Ross smb_ads_refresh(bad_dc); 349*b3700b07SGordon Ross 350*b3700b07SGordon Ross /* 351*b3700b07SGordon Ross * Search for the DC, save the result. 352*b3700b07SGordon Ross */ 353*b3700b07SGordon Ross bzero(&dxi, sizeof (dxi)); 354*b3700b07SGordon Ross status = smb_ddiscover_main(sdl->sdl_domain, &dxi); 355*b3700b07SGordon Ross if (status == 0) 356*b3700b07SGordon Ross smb_domain_save(); 357*b3700b07SGordon Ross (void) mutex_lock(&sdl->sdl_mtx); 358*b3700b07SGordon Ross sdl->sdl_status = status; 359*b3700b07SGordon Ross if (status == 0) 360*b3700b07SGordon Ross sdl->sdl_dci = dxi.d_dci; 361*b3700b07SGordon Ross 362*b3700b07SGordon Ross /* 363*b3700b07SGordon Ross * Run again if either of cfg_chg or bad_dc 364*b3700b07SGordon Ross * was turned on during smb_ddiscover_main(). 365*b3700b07SGordon Ross * Note: mutex held here. 366*b3700b07SGordon Ross */ 367*b3700b07SGordon Ross if (sdl->sdl_bad_dc) { 368*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_service " 369*b3700b07SGordon Ross "restart because bad_dc was set"); 370*b3700b07SGordon Ross goto find_again; 371*b3700b07SGordon Ross } 372*b3700b07SGordon Ross if (sdl->sdl_cfg_chg) { 373*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_service " 374*b3700b07SGordon Ross "restart because cfg_chg was set"); 375*b3700b07SGordon Ross goto find_again; 376*b3700b07SGordon Ross } 377*b3700b07SGordon Ross 378*b3700b07SGordon Ross wait_again: 379*b3700b07SGordon Ross sdl->sdl_locate = B_FALSE; 380*b3700b07SGordon Ross sdl->sdl_bad_dc = B_FALSE; 381*b3700b07SGordon Ross sdl->sdl_cfg_chg = B_FALSE; 382*b3700b07SGordon Ross (void) cond_broadcast(&sdl->sdl_cv); 383*b3700b07SGordon Ross (void) mutex_unlock(&sdl->sdl_mtx); 3848d7e4166Sjose borrego } 3858d7e4166Sjose borrego 3868d7e4166Sjose borrego /*NOTREACHED*/ 3878d7e4166Sjose borrego return (NULL); 3888d7e4166Sjose borrego } 3898d7e4166Sjose borrego 3908d7e4166Sjose borrego /* 391*b3700b07SGordon Ross * Discovers a domain controller for the specified domain via DNS. 392*b3700b07SGordon Ross * After the domain controller is discovered successfully primary and 393*b3700b07SGordon Ross * trusted domain infromation will be queried using RPC queries. 394*b3700b07SGordon Ross * 395*b3700b07SGordon Ross * Caller should zero out *dxi before calling, and after a 396*b3700b07SGordon Ross * successful return should call: smb_domain_save() 39729bd2886SAlan Wright */ 398*b3700b07SGordon Ross uint32_t 399*b3700b07SGordon Ross smb_ddiscover_main(char *domain, smb_domainex_t *dxi) 40029bd2886SAlan Wright { 4011ed6b69aSGordon Ross uint32_t status; 40229bd2886SAlan Wright 403*b3700b07SGordon Ross if (domain[0] == '\0') { 404*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_main NULL domain"); 405*b3700b07SGordon Ross return (NT_STATUS_INTERNAL_ERROR); 4061ed6b69aSGordon Ross } 40729bd2886SAlan Wright 408*b3700b07SGordon Ross if (smb_domain_start_update() != SMB_DOMAIN_SUCCESS) { 409*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_main can't get lock"); 410*b3700b07SGordon Ross return (NT_STATUS_INTERNAL_ERROR); 411*b3700b07SGordon Ross } 41229bd2886SAlan Wright 413*b3700b07SGordon Ross status = smb_ads_lookup_msdcs(domain, &dxi->d_dci); 414*b3700b07SGordon Ross if (status != 0) { 415*b3700b07SGordon Ross syslog(LOG_DEBUG, "smb_ddiscover_main can't find DC (%s)", 416*b3700b07SGordon Ross xlate_nt_status(status)); 417*b3700b07SGordon Ross goto out; 418*b3700b07SGordon Ross } 419*b3700b07SGordon Ross 420*b3700b07SGordon Ross status = smb_ddiscover_qinfo(domain, dxi->d_dci.dc_name, dxi); 421*b3700b07SGordon Ross if (status != 0) { 422*b3700b07SGordon Ross syslog(LOG_DEBUG, 423*b3700b07SGordon Ross "smb_ddiscover_main can't get domain info (%s)", 424*b3700b07SGordon Ross xlate_nt_status(status)); 425*b3700b07SGordon Ross goto out; 426*b3700b07SGordon Ross } 427*b3700b07SGordon Ross 428*b3700b07SGordon Ross smb_domain_update(dxi); 429*b3700b07SGordon Ross 430*b3700b07SGordon Ross out: 431a0aa776eSAlan Wright smb_domain_end_update(); 43229bd2886SAlan Wright 433*b3700b07SGordon Ross /* Don't need the trusted domain list anymore. */ 434*b3700b07SGordon Ross smb_domainex_free(dxi); 43529bd2886SAlan Wright 4361ed6b69aSGordon Ross return (status); 43729bd2886SAlan Wright } 43829bd2886SAlan Wright 43929bd2886SAlan Wright /* 44029bd2886SAlan Wright * Obtain primary and trusted domain information using LSA queries. 4418d7e4166Sjose borrego * 4428d7e4166Sjose borrego * domain - either NetBIOS or fully-qualified domain name 4438d7e4166Sjose borrego */ 4448d7e4166Sjose borrego static uint32_t 445a0aa776eSAlan Wright smb_ddiscover_qinfo(char *domain, char *server, smb_domainex_t *dxi) 4468d7e4166Sjose borrego { 447*b3700b07SGordon Ross uint32_t ret, tmp; 4488d7e4166Sjose borrego 449*b3700b07SGordon Ross /* If we must return failure, use this first one. */ 450*b3700b07SGordon Ross ret = lsa_query_dns_domain_info(server, domain, &dxi->d_primary); 451*b3700b07SGordon Ross if (ret == NT_STATUS_SUCCESS) 452*b3700b07SGordon Ross goto success; 453*b3700b07SGordon Ross tmp = smb_ddiscover_use_config(domain, dxi); 454*b3700b07SGordon Ross if (tmp == NT_STATUS_SUCCESS) 455*b3700b07SGordon Ross goto success; 456*b3700b07SGordon Ross tmp = lsa_query_primary_domain_info(server, domain, &dxi->d_primary); 457*b3700b07SGordon Ross if (tmp == NT_STATUS_SUCCESS) 458*b3700b07SGordon Ross goto success; 45929bd2886SAlan Wright 460*b3700b07SGordon Ross /* All of the above failed. */ 461*b3700b07SGordon Ross return (ret); 4628d7e4166Sjose borrego 463*b3700b07SGordon Ross success: 464a0aa776eSAlan Wright smb_ddiscover_enum_trusted(domain, server, dxi); 465*b3700b07SGordon Ross return (NT_STATUS_SUCCESS); 4668d7e4166Sjose borrego } 4678d7e4166Sjose borrego 4688d7e4166Sjose borrego /* 46929bd2886SAlan Wright * Obtain trusted domains information using LSA queries. 4708d7e4166Sjose borrego * 4718d7e4166Sjose borrego * domain - either NetBIOS or fully-qualified domain name. 4728d7e4166Sjose borrego */ 4738d7e4166Sjose borrego static void 474a0aa776eSAlan Wright smb_ddiscover_enum_trusted(char *domain, char *server, smb_domainex_t *dxi) 4758d7e4166Sjose borrego { 476a0aa776eSAlan Wright smb_trusted_domains_t *list; 47729bd2886SAlan Wright uint32_t status; 4788d7e4166Sjose borrego 479a0aa776eSAlan Wright list = &dxi->d_trusted; 48029bd2886SAlan Wright status = lsa_enum_trusted_domains_ex(server, domain, list); 48129bd2886SAlan Wright if (status != NT_STATUS_SUCCESS) 48229bd2886SAlan Wright (void) lsa_enum_trusted_domains(server, domain, list); 4838d7e4166Sjose borrego } 4848d7e4166Sjose borrego 4858d7e4166Sjose borrego /* 4868d7e4166Sjose borrego * If the domain to be discovered matches the current domain (i.e the 487a0aa776eSAlan Wright * value of either domain or fqdn configuration), then get the primary 488a0aa776eSAlan Wright * domain information from SMF. 4898d7e4166Sjose borrego */ 49029bd2886SAlan Wright static uint32_t 491a0aa776eSAlan Wright smb_ddiscover_use_config(char *domain, smb_domainex_t *dxi) 4928d7e4166Sjose borrego { 4938d7e4166Sjose borrego boolean_t use; 494a0aa776eSAlan Wright smb_domain_t *dinfo; 4958d7e4166Sjose borrego 496a0aa776eSAlan Wright dinfo = &dxi->d_primary; 497a0aa776eSAlan Wright bzero(dinfo, sizeof (smb_domain_t)); 49829bd2886SAlan Wright 4998d7e4166Sjose borrego if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) 50029bd2886SAlan Wright return (NT_STATUS_UNSUCCESSFUL); 5018d7e4166Sjose borrego 50229bd2886SAlan Wright smb_config_getdomaininfo(dinfo->di_nbname, dinfo->di_fqname, 50329bd2886SAlan Wright NULL, NULL, NULL); 5048d7e4166Sjose borrego 50529bd2886SAlan Wright if (SMB_IS_FQDN(domain)) 506bbf6f00cSJordan Brown use = (smb_strcasecmp(dinfo->di_fqname, domain, 0) == 0); 50729bd2886SAlan Wright else 508bbf6f00cSJordan Brown use = (smb_strcasecmp(dinfo->di_nbname, domain, 0) == 0); 50929bd2886SAlan Wright 51029bd2886SAlan Wright if (use) 51129bd2886SAlan Wright smb_config_getdomaininfo(NULL, NULL, dinfo->di_sid, 51229bd2886SAlan Wright dinfo->di_u.di_dns.ddi_forest, 51329bd2886SAlan Wright dinfo->di_u.di_dns.ddi_guid); 51429bd2886SAlan Wright 51529bd2886SAlan Wright return ((use) ? NT_STATUS_SUCCESS : NT_STATUS_UNSUCCESSFUL); 5168d7e4166Sjose borrego } 5178d7e4166Sjose borrego 51829bd2886SAlan Wright static void 519a0aa776eSAlan Wright smb_domainex_free(smb_domainex_t *dxi) 52029bd2886SAlan Wright { 521a0aa776eSAlan Wright free(dxi->d_trusted.td_domains); 522*b3700b07SGordon Ross dxi->d_trusted.td_domains = NULL; 523*b3700b07SGordon Ross } 524*b3700b07SGordon Ross 525*b3700b07SGordon Ross static void 526*b3700b07SGordon Ross smb_set_krb5_realm(char *domain) 527*b3700b07SGordon Ross { 528*b3700b07SGordon Ross static char realm[MAXHOSTNAMELEN]; 529*b3700b07SGordon Ross 530*b3700b07SGordon Ross if (domain == NULL || domain[0] == '\0') { 531*b3700b07SGordon Ross (void) unsetenv("KRB5_DEFAULT_REALM"); 532*b3700b07SGordon Ross return; 533*b3700b07SGordon Ross } 534*b3700b07SGordon Ross 535*b3700b07SGordon Ross /* In case krb5.conf is not configured, set the default realm. */ 536*b3700b07SGordon Ross (void) strlcpy(realm, domain, sizeof (realm)); 537*b3700b07SGordon Ross (void) smb_strupr(realm); 538*b3700b07SGordon Ross 539*b3700b07SGordon Ross (void) setenv("KRB5_DEFAULT_REALM", realm, 1); 5408d7e4166Sjose borrego } 541