static struct samr_sid * sam_get_domain_sid(mlsvc_handle_t *samr_handle, char *server, char *domain_name) { smb_sid_t *sid = NULL; smb_domainex_t domain; if (ndr_rpc_server_os(samr_handle) == NATIVE_OS_WIN2000) { if (!smb_domain_getinfo(&domain)) { if (lsa_query_account_domain_info(server, domain_name, &domain.d_primary) != NT_STATUS_SUCCESS) return (NULL); } sid = smb_sid_fromstr(domain.d_primary.di_sid); } else { sid = samr_lookup_domain(samr_handle, domain_name); } return ((struct samr_sid *)sid); }
/*ARGSUSED*/ int lsa_lookup_privs(char *account_name, char *target_name, smb_account_t *ainfo) { mlsvc_handle_t domain_handle; int rc; smb_domainex_t dinfo; char user[SMB_USERNAME_MAXLEN]; smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (!smb_domain_getinfo(&dinfo)) return (-1); if ((lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user, &domain_handle)) != 0) return (-1); rc = lsa_list_accounts(&domain_handle); (void) lsar_close(&domain_handle); return (rc); }
/* * samr_open * * Wrapper round samr_connect to ensure that we connect using the server * and domain. We default to the resource domain if the caller doesn't * supply a server name and a domain name. * * If username argument is NULL, an anonymous connection will be established. * Otherwise, an authenticated connection will be established. * * On success 0 is returned. Otherwise a -ve error code. */ int samr_open(char *server, char *domain, char *username, DWORD access_mask, mlsvc_handle_t *samr_handle) { smb_domainex_t di; int rc; if (server == NULL || domain == NULL) { if (!smb_domain_getinfo(&di)) return (-1); server = di.d_dc; domain = di.d_primary.di_nbname; } if (username == NULL) username = MLSVC_ANON_USER; rc = samr_connect(server, domain, username, access_mask, samr_handle); return (rc); }
/* * Bind to the the SRVSVC. * * If username argument is NULL, an anonymous connection will be established. * Otherwise, an authenticated connection will be established. */ static int srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle) { smb_domainex_t di; if (server == NULL || domain == NULL) { if (!smb_domain_getinfo(&di)) return (-1); server = di.d_dc; domain = di.d_primary.di_nbname; } if (username == NULL) username = MLSVC_ANON_USER; if (ndr_rpc_bind(handle, server, domain, username, "SRVSVC") < 0) return (-1); return (0); }
static uint32_t lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo) { mlsvc_handle_t domain_handle; uint32_t status; smb_domainex_t dinfo; char user[SMB_USERNAME_MAXLEN]; smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (!smb_domain_getinfo(&dinfo)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user, &domain_handle) != 0) return (NT_STATUS_INVALID_PARAMETER); status = lsar_lookup_sids(&domain_handle, sid, ainfo); (void) lsar_close(&domain_handle); return (status); }
/* * Synchronize the local system clock with the domain controller. */ void srvsvc_timesync(void) { smb_domainex_t di; struct timeval tv; struct tm tm; time_t tsecs; if (!smb_domain_getinfo(&di)) return; if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm) != 0) return; if (settimeofday(&tv, 0)) smb_tracef("unable to set system time"); tsecs = time(0); (void) localtime_r(&tsecs, &tm); smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec)); }
/* * This is the entry point for discovering a domain controller for the * specified domain. * * The actual work of discovering a DC is handled by DC locator thread. * All we do here is signal the request and wait for a DC or a timeout. * * Input parameters: * domain - domain to be discovered (can either be NetBIOS or DNS domain) * dc - preferred DC. If the preferred DC is set to empty string, it * will attempt to discover any DC in the specified domain. * * Output parameter: * dp - on success, dp will be filled with the discovered DC and domain * information. * Returns B_TRUE if the DC/domain info is available. */ boolean_t smb_locate_dc(char *domain, char *dc, smb_domainex_t *dp) { int rc; timestruc_t to; smb_domainex_t domain_info; if (domain == NULL || *domain == '\0') return (B_FALSE); (void) mutex_lock(&smb_dclocator.sdl_mtx); if (!smb_dclocator.sdl_locate) { smb_dclocator.sdl_locate = B_TRUE; (void) strlcpy(smb_dclocator.sdl_domain, domain, SMB_PI_MAX_DOMAIN); (void) strlcpy(smb_dclocator.sdl_dc, dc, MAXHOSTNAMELEN); (void) cond_broadcast(&smb_dclocator.sdl_cv); } while (smb_dclocator.sdl_locate) { to.tv_sec = SMB_DCLOCATOR_TIMEOUT; to.tv_nsec = 0; rc = cond_reltimedwait(&smb_dclocator.sdl_cv, &smb_dclocator.sdl_mtx, &to); if (rc == ETIME) break; } if (dp == NULL) dp = &domain_info; rc = smb_domain_getinfo(dp); (void) mutex_unlock(&smb_dclocator.sdl_mtx); return (rc); }
krb5_error_code _krb5_override_service_locator( void *arg0, enum locate_service_type svc, const char *realm, int socktype, int family, int (*cbfunc)(void *, int, struct sockaddr *), void *cbdata) { _NOTE(ARGUNUSED(arg0)) smb_domainex_t dxi; int rc = KRB5_PLUGIN_NO_HANDLE; short port; /* * Is this a service we want to override? */ switch (svc) { case locate_service_kdc: case locate_service_master_kdc: port = htons(KRB5_DEFAULT_PORT); break; case locate_service_kadmin: port = htons(DEFAULT_KADM5_PORT); break; case locate_service_kpasswd: port = htons(DEFAULT_KPASSWD_PORT); break; case locate_service_krb524: default: return (rc); } /* * What's my domain? Note: have to get this in a way * that works while join domain is underway. */ if (!smb_domain_getinfo(&dxi)) { smbd_report("_krb5_override_service_locator " "failed getting domain info"); return (KRB5_ERR_HOST_REALM_UNKNOWN); } /* * Is this a realm we want to override? */ if (0 != strcasecmp(realm, dxi.d_primary.di_fqname)) { syslog(LOG_DEBUG, "_krb5_override_service_locator, " "realm=%s, fqdn=%s", realm, dxi.d_primary.di_fqname); return (rc); } /* * Yes, this is our domain. Have a DC? */ if (dxi.d_dci.dc_name[0] == '\0' || dxi.d_dci.dc_addr.a_family == 0) return (KRB5_REALM_CANT_RESOLVE); switch (family) { case AF_UNSPEC: break; /* OK */ case AF_INET: case AF_INET6: if (family == dxi.d_dci.dc_addr.a_family) break; /* OK */ /* else fallthrough */ default: return (KRB5_ERR_NO_SERVICE); } /* * Provide the service address we have. */ switch (dxi.d_dci.dc_addr.a_family) { case AF_INET: { struct sockaddr_in sin; (void) memset(&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_port = port; (void) memcpy(&sin.sin_addr, &dxi.d_dci.dc_addr.a_ipv4, sizeof (sin.sin_addr)); rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin); /* rc from cbfunc is special. */ if (rc) rc = ENOMEM; break; } case AF_INET6: { struct sockaddr_in6 sin6; (void) memset(&sin6, 0, sizeof (sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_port = port; (void) memcpy(&sin6.sin6_addr, &dxi.d_dci.dc_addr.a_ipv6, sizeof (sin6.sin6_addr)); rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin6); /* rc from cbfunc is special. */ if (rc) rc = ENOMEM; break; } default: rc = KRB5_ERR_NO_SERVICE; break; } return (rc); }