static uint32_t netlogon_logon(smb_logon_t *user_info, smb_token_t *token) { char resource_domain[SMB_PI_MAX_DOMAIN]; char server[NETBIOS_NAME_SZ * 2]; mlsvc_handle_t netr_handle; smb_domainex_t di; uint32_t status; int retries = 0; (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); /* Avoid interfering with DC discovery. */ if (smb_ddiscover_wait() != 0 || !smb_domain_getinfo(&di)) { netr_invalidate_chain(); return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } do { if (netr_open(di.d_dc, di.d_primary.di_nbname, &netr_handle) != 0) return (NT_STATUS_OPEN_FAILED); if (di.d_dc && (*netr_global_info.server != '\0')) { (void) snprintf(server, sizeof (server), "\\\\%s", di.d_dc); if (strncasecmp(netr_global_info.server, server, strlen(server)) != 0) netr_invalidate_chain(); } if ((netr_global_info.flags & NETR_FLG_VALID) == 0 || !smb_match_netlogon_seqnum()) { status = netlogon_auth(di.d_dc, &netr_handle, NETR_FLG_NULL); if (status != 0) { (void) netr_close(&netr_handle); return (NT_STATUS_LOGON_FAILURE); } netr_global_info.flags |= NETR_FLG_VALID; } status = netr_server_samlogon(&netr_handle, &netr_global_info, di.d_dc, user_info, token); (void) netr_close(&netr_handle); } while (status == NT_STATUS_INSUFFICIENT_LOGON_INFO && retries++ < 3); if (retries >= 3) status = NT_STATUS_LOGON_FAILURE; return (status); }
/*ARGSUSED*/ static int smbadm_list(int argc, char **argv) { char domain[MAXHOSTNAMELEN]; char fqdn[MAXHOSTNAMELEN]; char srvname[MAXHOSTNAMELEN]; char modename[16]; int rc; smb_inaddr_t srvipaddr; char ipstr[INET6_ADDRSTRLEN]; rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename)); if (rc != SMBD_SMF_OK) { (void) fprintf(stderr, gettext("cannot determine the operational mode\n")); return (1); } if (smb_getdomainname(domain, sizeof (domain)) != 0) { (void) fprintf(stderr, gettext("failed to get the %s name\n"), modename); return (1); } if (strcmp(modename, "workgroup") == 0) { (void) printf(gettext("[*] [%s]\n"), domain); return (0); } (void) printf(gettext("[*] [%s]\n"), domain); if ((smb_getfqdomainname(fqdn, sizeof (fqdn)) == 0) && (*fqdn != '\0')) (void) printf(gettext("[*] [%s]\n"), fqdn); if ((smb_get_dcinfo(srvname, MAXHOSTNAMELEN, &srvipaddr) == NT_STATUS_SUCCESS) && (*srvname != '\0') && (!smb_inet_iszero(&srvipaddr))) { (void) smb_inet_ntop(&srvipaddr, ipstr, SMB_IPSTRLEN(srvipaddr.a_family)); (void) printf(gettext("\t[+%s.%s] [%s]\n"), srvname, fqdn, ipstr); } smb_domain_show(); return (0); }
/* * Some older clients (Windows 98) only handle the low byte * of the max workers value. If the low byte is less than * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN. */ void smb_load_kconfig(smb_kmod_cfg_t *kcfg) { struct utsname uts; int64_t citem; int rc; bzero(kcfg, sizeof (smb_kmod_cfg_t)); (void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem); kcfg->skc_maxworkers = (uint32_t)citem; if ((kcfg->skc_maxworkers & 0xFF) < SMB_PI_MAX_WORKERS_MIN) { kcfg->skc_maxworkers &= ~0xFF; kcfg->skc_maxworkers += SMB_PI_MAX_WORKERS_MIN; } (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem); kcfg->skc_keepalive = (uint32_t)citem; if ((kcfg->skc_keepalive != 0) && (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN)) kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN; (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem); kcfg->skc_maxconnections = (uint32_t)citem; kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON); kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE); kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD); kcfg->skc_netbios_enable = smb_config_getbool(SMB_CI_NETBIOS_ENABLE); kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE); kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE); kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE); kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE); kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS); kcfg->skc_max_protocol = smb_config_get_max_protocol(); kcfg->skc_secmode = smb_config_get_secmode(); rc = smb_config_getnum(SMB_CI_MAXIMUM_CREDITS, &citem); if (rc != SMBD_SMF_OK) citem = SMB_PI_MAX_CREDITS; if (citem < SMB_PI_MIN_CREDITS) citem = SMB_PI_MIN_CREDITS; if (citem > SMB_PI_MAX_CREDITS) citem = SMB_PI_MAX_CREDITS; kcfg->skc_maximum_credits = (uint16_t)citem; rc = smb_config_getnum(SMB_CI_INITIAL_CREDITS, &citem); if (rc != SMBD_SMF_OK) citem = SMB_PI_MIN_CREDITS; if (citem < SMB_PI_MIN_CREDITS) citem = SMB_PI_MIN_CREDITS; if (citem > kcfg->skc_maximum_credits) citem = kcfg->skc_maximum_credits; kcfg->skc_initial_credits = (uint16_t)citem; (void) smb_getdomainname(kcfg->skc_nbdomain, sizeof (kcfg->skc_nbdomain)); (void) smb_getfqdomainname(kcfg->skc_fqdn, sizeof (kcfg->skc_fqdn)); (void) smb_getnetbiosname(kcfg->skc_hostname, sizeof (kcfg->skc_hostname)); (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment, sizeof (kcfg->skc_system_comment)); smb_config_get_version(&kcfg->skc_version); kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0); if (smb_config_get_localuuid(kcfg->skc_machine_uuid) < 0) { syslog(LOG_ERR, "smb_load_kconfig: no machine_uuid"); uuid_generate_time(kcfg->skc_machine_uuid); } /* skc_negtok, skc_negtok_len: see smbd_authsvc.c */ (void) uname(&uts); (void) snprintf(kcfg->skc_native_os, sizeof (kcfg->skc_native_os), "%s %s %s", uts.sysname, uts.release, uts.version); (void) strlcpy(kcfg->skc_native_lm, "Native SMB service", sizeof (kcfg->skc_native_lm)); }
static uint32_t netr_setup_token(struct netr_validation_info3 *info3, smb_logon_t *user_info, netr_info_t *netr_info, smb_token_t *token) { char *username, *domain; unsigned char rc4key[SMBAUTH_SESSION_KEY_SZ]; smb_sid_t *domsid; uint32_t status; char nbdomain[NETBIOS_NAME_SZ]; domsid = (smb_sid_t *)info3->LogonDomainId; token->tkn_user.i_sid = smb_sid_splice(domsid, info3->UserId); if (token->tkn_user.i_sid == NULL) return (NT_STATUS_NO_MEMORY); token->tkn_primary_grp.i_sid = smb_sid_splice(domsid, info3->PrimaryGroupId); if (token->tkn_primary_grp.i_sid == NULL) return (NT_STATUS_NO_MEMORY); username = (info3->EffectiveName.str) ? (char *)info3->EffectiveName.str : user_info->lg_e_username; if (info3->LogonDomainName.str) { domain = (char *)info3->LogonDomainName.str; } else if (*user_info->lg_e_domain != '\0') { domain = user_info->lg_e_domain; } else { (void) smb_getdomainname(nbdomain, sizeof (nbdomain)); domain = nbdomain; } if (username) token->tkn_account_name = strdup(username); if (domain) token->tkn_domain_name = strdup(domain); if (token->tkn_account_name == NULL || token->tkn_domain_name == NULL) return (NT_STATUS_NO_MEMORY); status = netr_setup_token_wingrps(info3, token); if (status != NT_STATUS_SUCCESS) return (status); /* * The UserSessionKey in NetrSamLogon RPC is obfuscated using the * session key obtained in the NETLOGON credential chain. * An 8 byte session key is zero extended to 16 bytes. This 16 byte * key is the key to the RC4 algorithm. The RC4 byte stream is * exclusively ored with the 16 byte UserSessionKey to recover * the the clear form. */ if ((token->tkn_session_key = malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL) return (NT_STATUS_NO_MEMORY); bzero(rc4key, SMBAUTH_SESSION_KEY_SZ); bcopy(netr_info->session_key.key, rc4key, netr_info->session_key.len); bcopy(info3->UserSessionKey.data, token->tkn_session_key, SMBAUTH_SESSION_KEY_SZ); rand_hash((unsigned char *)token->tkn_session_key, SMBAUTH_SESSION_KEY_SZ, rc4key, SMBAUTH_SESSION_KEY_SZ); return (NT_STATUS_SUCCESS); }