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 */ 21148c5f43SAlan Wright 22da6c28aaSamw /* 23148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 2412b65585SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 25da6c28aaSamw */ 26da6c28aaSamw 27da6c28aaSamw /* 28da6c28aaSamw * NETR SamLogon and SamLogoff RPC client functions. 29da6c28aaSamw */ 30da6c28aaSamw 31da6c28aaSamw #include <stdio.h> 32da6c28aaSamw #include <strings.h> 33da6c28aaSamw #include <stdlib.h> 34da6c28aaSamw #include <time.h> 35da6c28aaSamw #include <alloca.h> 36da6c28aaSamw #include <unistd.h> 37da6c28aaSamw #include <netdb.h> 388d7e4166Sjose borrego #include <thread.h> 39da6c28aaSamw 40da6c28aaSamw #include <smbsrv/libsmb.h> 418d7e4166Sjose borrego #include <smbsrv/libmlrpc.h> 428d7e4166Sjose borrego #include <smbsrv/libmlsvc.h> 43da6c28aaSamw #include <smbsrv/ndl/netlogon.ndl> 44da6c28aaSamw #include <smbsrv/netrauth.h> 45da6c28aaSamw #include <smbsrv/smbinfo.h> 46da6c28aaSamw #include <smbsrv/smb_token.h> 478d7e4166Sjose borrego #include <mlsvc.h> 48da6c28aaSamw 499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States #define NETLOGON_ATTEMPTS 2 509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static uint32_t netlogon_logon(smb_logon_t *, smb_token_t *); 527f667e74Sjose borrego static uint32_t netr_server_samlogon(mlsvc_handle_t *, netr_info_t *, char *, 539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_logon_t *, smb_token_t *); 54da6c28aaSamw static void netr_invalidate_chain(void); 559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void netr_interactive_samlogon(netr_info_t *, smb_logon_t *, 56da6c28aaSamw struct netr_logon_info1 *); 578d7e4166Sjose borrego static void netr_network_samlogon(ndr_heap_t *, netr_info_t *, 589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_logon_t *, struct netr_logon_info2 *); 599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static void netr_setup_identity(ndr_heap_t *, smb_logon_t *, 60da6c28aaSamw netr_logon_id_t *); 617f667e74Sjose borrego static boolean_t netr_isadmin(struct netr_validation_info3 *); 627f667e74Sjose borrego static uint32_t netr_setup_domain_groups(struct netr_validation_info3 *, 637f667e74Sjose borrego smb_ids_t *); 6412b65585SGordon Ross static uint32_t netr_setup_token_info3(struct netr_validation_info3 *, 6512b65585SGordon Ross smb_token_t *); 667f667e74Sjose borrego static uint32_t netr_setup_token_wingrps(struct netr_validation_info3 *, 677f667e74Sjose borrego smb_token_t *); 68da6c28aaSamw 69da6c28aaSamw /* 70da6c28aaSamw * Shared with netr_auth.c 71da6c28aaSamw */ 72da6c28aaSamw extern netr_info_t netr_global_info; 73da6c28aaSamw 749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static mutex_t netlogon_mutex; 759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static cond_t netlogon_cv; 769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t netlogon_busy = B_FALSE; 779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static boolean_t netlogon_abort = B_FALSE; 788d7e4166Sjose borrego 79da6c28aaSamw /* 8012b65585SGordon Ross * Helper for Kerberos authentication 8112b65585SGordon Ross */ 8212b65585SGordon Ross uint32_t 8312b65585SGordon Ross smb_decode_krb5_pac(smb_token_t *token, char *data, uint_t len) 8412b65585SGordon Ross { 8512b65585SGordon Ross struct krb5_validation_info info; 8612b65585SGordon Ross ndr_buf_t *nbuf; 8712b65585SGordon Ross uint32_t status = NT_STATUS_NO_MEMORY; 8812b65585SGordon Ross int rc; 8912b65585SGordon Ross 9012b65585SGordon Ross bzero(&info, sizeof (info)); 9112b65585SGordon Ross 9212b65585SGordon Ross /* Need to keep this until we're done with &info */ 9312b65585SGordon Ross nbuf = ndr_buf_init(&TYPEINFO(netr_interface)); 9412b65585SGordon Ross if (nbuf == NULL) 9512b65585SGordon Ross goto out; 9612b65585SGordon Ross 9712b65585SGordon Ross rc = ndr_buf_decode(nbuf, NDR_PTYPE_PAC, 9812b65585SGordon Ross NETR_OPNUM_decode_krb5_pac, data, len, &info); 9912b65585SGordon Ross if (rc != NDR_DRC_OK) { 10012b65585SGordon Ross status = RPC_NT_PROTOCOL_ERROR; 10112b65585SGordon Ross goto out; 10212b65585SGordon Ross } 10312b65585SGordon Ross 10412b65585SGordon Ross status = netr_setup_token_info3(&info.info3, token); 10512b65585SGordon Ross 10612b65585SGordon Ross /* Deal with the "resource groups"? */ 10712b65585SGordon Ross 10812b65585SGordon Ross 10912b65585SGordon Ross out: 11012b65585SGordon Ross if (nbuf != NULL) 11112b65585SGordon Ross ndr_buf_fini(nbuf); 11212b65585SGordon Ross 11312b65585SGordon Ross return (status); 11412b65585SGordon Ross } 11512b65585SGordon Ross 11612b65585SGordon Ross /* 11712b65585SGordon Ross * Code factored out of netr_setup_token() 11812b65585SGordon Ross */ 11912b65585SGordon Ross static uint32_t 12012b65585SGordon Ross netr_setup_token_info3(struct netr_validation_info3 *info3, 12112b65585SGordon Ross smb_token_t *token) 12212b65585SGordon Ross { 12312b65585SGordon Ross smb_sid_t *domsid; 12412b65585SGordon Ross 12512b65585SGordon Ross domsid = (smb_sid_t *)info3->LogonDomainId; 12612b65585SGordon Ross 12712b65585SGordon Ross token->tkn_user.i_sid = smb_sid_splice(domsid, 12812b65585SGordon Ross info3->UserId); 12912b65585SGordon Ross if (token->tkn_user.i_sid == NULL) 13012b65585SGordon Ross goto errout; 13112b65585SGordon Ross 13212b65585SGordon Ross token->tkn_primary_grp.i_sid = smb_sid_splice(domsid, 13312b65585SGordon Ross info3->PrimaryGroupId); 13412b65585SGordon Ross if (token->tkn_primary_grp.i_sid == NULL) 13512b65585SGordon Ross goto errout; 13612b65585SGordon Ross 13712b65585SGordon Ross if (info3->EffectiveName.str) { 13812b65585SGordon Ross token->tkn_account_name = 13912b65585SGordon Ross strdup((char *)info3->EffectiveName.str); 14012b65585SGordon Ross if (token->tkn_account_name == NULL) 14112b65585SGordon Ross goto errout; 14212b65585SGordon Ross } 14312b65585SGordon Ross 14412b65585SGordon Ross if (info3->LogonDomainName.str) { 14512b65585SGordon Ross token->tkn_domain_name = 14612b65585SGordon Ross strdup((char *)info3->LogonDomainName.str); 14712b65585SGordon Ross if (token->tkn_domain_name == NULL) 14812b65585SGordon Ross goto errout; 14912b65585SGordon Ross } 15012b65585SGordon Ross 15112b65585SGordon Ross return (netr_setup_token_wingrps(info3, token)); 15212b65585SGordon Ross errout: 15312b65585SGordon Ross return (NT_STATUS_INSUFF_SERVER_RESOURCES); 15412b65585SGordon Ross } 15512b65585SGordon Ross 15612b65585SGordon Ross /* 1579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Abort impending domain logon requests. 158da6c28aaSamw */ 1599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 1609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_logon_abort(void) 1619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States { 1629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_lock(&netlogon_mutex); 1639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (netlogon_busy && !netlogon_abort) 1649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States syslog(LOG_DEBUG, "logon abort"); 1659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netlogon_abort = B_TRUE; 1669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) cond_broadcast(&netlogon_cv); 1679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_unlock(&netlogon_mutex); 1689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 1699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States /* 1719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * This is the entry point for authenticating domain users. 1729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * 1739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * If we are not going to attempt to authenticate the user, 1749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * this function must return without updating the status. 1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * 1769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * If the user is successfully authenticated, we build an 1779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * access token and the status will be NT_STATUS_SUCCESS. 1789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Otherwise, the token contents are invalid. 1799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States */ 1809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void 1819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_logon_domain(smb_logon_t *user_info, smb_token_t *token) 182da6c28aaSamw { 1837f667e74Sjose borrego uint32_t status; 1849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int i; 1858d7e4166Sjose borrego 1869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (user_info->lg_secmode != SMB_SECMODE_DOMAIN) 1879fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return; 1888d7e4166Sjose borrego 1899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (user_info->lg_domain_type == SMB_DOMAIN_LOCAL) 1909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return; 1918d7e4166Sjose borrego 1929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States for (i = 0; i < NETLOGON_ATTEMPTS; ++i) { 1939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_lock(&netlogon_mutex); 1949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States while (netlogon_busy && !netlogon_abort) 1959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) cond_wait(&netlogon_cv, &netlogon_mutex); 1969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (netlogon_abort) { 1989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_unlock(&netlogon_mutex); 1999fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_info->lg_status = NT_STATUS_REQUEST_ABORTED; 2009fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States return; 2019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 2029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2039fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netlogon_busy = B_TRUE; 2049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_unlock(&netlogon_mutex); 2059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States status = netlogon_logon(user_info, token); 2079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_lock(&netlogon_mutex); 2099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netlogon_busy = B_FALSE; 2109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (netlogon_abort) 2119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States status = NT_STATUS_REQUEST_ABORTED; 2129fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) cond_signal(&netlogon_cv); 2139fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) mutex_unlock(&netlogon_mutex); 2149fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2159fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (status != NT_STATUS_CANT_ACCESS_DOMAIN_INFO) 2169fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2179fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 2189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (status != NT_STATUS_SUCCESS) 2209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States syslog(LOG_INFO, "logon[%s\\%s]: %s", user_info->lg_e_domain, 2219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_info->lg_e_username, xlate_nt_status(status)); 2229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_info->lg_status = status; 2248d7e4166Sjose borrego } 2258d7e4166Sjose borrego 2267f667e74Sjose borrego static uint32_t 2279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netlogon_logon(smb_logon_t *user_info, smb_token_t *token) 2288d7e4166Sjose borrego { 229da6c28aaSamw char resource_domain[SMB_PI_MAX_DOMAIN]; 230*b3700b07SGordon Ross char server[MAXHOSTNAMELEN]; 231da6c28aaSamw mlsvc_handle_t netr_handle; 232a0aa776eSAlan Wright smb_domainex_t di; 2337f667e74Sjose borrego uint32_t status; 2341fdeec65Sjoyce mcintosh int retries = 0; 235da6c28aaSamw 236dc20a302Sas200622 (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); 237da6c28aaSamw 238380acbbeSGordon Ross /* Avoid interfering with DC discovery. */ 239380acbbeSGordon Ross if (smb_ddiscover_wait() != 0 || 240380acbbeSGordon Ross !smb_domain_getinfo(&di)) { 241da6c28aaSamw netr_invalidate_chain(); 242da6c28aaSamw return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); 243da6c28aaSamw } 244da6c28aaSamw 245da6c28aaSamw do { 246*b3700b07SGordon Ross if (netr_open(di.d_dci.dc_name, di.d_primary.di_nbname, 247*b3700b07SGordon Ross &netr_handle) != 0) 248b1352070SAlan Wright return (NT_STATUS_OPEN_FAILED); 249da6c28aaSamw 250*b3700b07SGordon Ross if (di.d_dci.dc_name[0] != '\0' && 251*b3700b07SGordon Ross (*netr_global_info.server != '\0')) { 252c8ec8eeaSjose borrego (void) snprintf(server, sizeof (server), 253*b3700b07SGordon Ross "\\\\%s", di.d_dci.dc_name); 2541fdeec65Sjoyce mcintosh if (strncasecmp(netr_global_info.server, 2551fdeec65Sjoyce mcintosh server, strlen(server)) != 0) 2561fdeec65Sjoyce mcintosh netr_invalidate_chain(); 257c8ec8eeaSjose borrego } 258c8ec8eeaSjose borrego 2591fdeec65Sjoyce mcintosh if ((netr_global_info.flags & NETR_FLG_VALID) == 0 || 260faa1795aSjb150015 !smb_match_netlogon_seqnum()) { 261*b3700b07SGordon Ross status = netlogon_auth(di.d_dci.dc_name, &netr_handle, 262da6c28aaSamw NETR_FLG_NULL); 263da6c28aaSamw 264da6c28aaSamw if (status != 0) { 265da6c28aaSamw (void) netr_close(&netr_handle); 266da6c28aaSamw return (NT_STATUS_LOGON_FAILURE); 267da6c28aaSamw } 268da6c28aaSamw 269da6c28aaSamw netr_global_info.flags |= NETR_FLG_VALID; 270da6c28aaSamw } 271da6c28aaSamw 272da6c28aaSamw status = netr_server_samlogon(&netr_handle, 273*b3700b07SGordon Ross &netr_global_info, di.d_dci.dc_name, user_info, token); 274da6c28aaSamw 275da6c28aaSamw (void) netr_close(&netr_handle); 276da6c28aaSamw } while (status == NT_STATUS_INSUFFICIENT_LOGON_INFO && retries++ < 3); 277da6c28aaSamw 278da6c28aaSamw if (retries >= 3) 279da6c28aaSamw status = NT_STATUS_LOGON_FAILURE; 280da6c28aaSamw 281da6c28aaSamw return (status); 282da6c28aaSamw } 283da6c28aaSamw 2847f667e74Sjose borrego static uint32_t 2859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_setup_token(struct netr_validation_info3 *info3, smb_logon_t *user_info, 2867f667e74Sjose borrego netr_info_t *netr_info, smb_token_t *token) 287da6c28aaSamw { 288da6c28aaSamw char *username, *domain; 2898c10a865Sas200622 unsigned char rc4key[SMBAUTH_SESSION_KEY_SZ]; 2907f667e74Sjose borrego smb_sid_t *domsid; 2917f667e74Sjose borrego uint32_t status; 2927f667e74Sjose borrego char nbdomain[NETBIOS_NAME_SZ]; 293da6c28aaSamw 2947f667e74Sjose borrego domsid = (smb_sid_t *)info3->LogonDomainId; 295da6c28aaSamw 2967f667e74Sjose borrego token->tkn_user.i_sid = smb_sid_splice(domsid, info3->UserId); 2977f667e74Sjose borrego if (token->tkn_user.i_sid == NULL) 298da6c28aaSamw return (NT_STATUS_NO_MEMORY); 299da6c28aaSamw 3007f667e74Sjose borrego token->tkn_primary_grp.i_sid = smb_sid_splice(domsid, 3017f667e74Sjose borrego info3->PrimaryGroupId); 3027f667e74Sjose borrego if (token->tkn_primary_grp.i_sid == NULL) 303da6c28aaSamw return (NT_STATUS_NO_MEMORY); 304da6c28aaSamw 305da6c28aaSamw username = (info3->EffectiveName.str) 3069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ? (char *)info3->EffectiveName.str : user_info->lg_e_username; 3077f667e74Sjose borrego 3087f667e74Sjose borrego if (info3->LogonDomainName.str) { 3097f667e74Sjose borrego domain = (char *)info3->LogonDomainName.str; 3109fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } else if (*user_info->lg_e_domain != '\0') { 3119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States domain = user_info->lg_e_domain; 3127f667e74Sjose borrego } else { 3137f667e74Sjose borrego (void) smb_getdomainname(nbdomain, sizeof (nbdomain)); 3147f667e74Sjose borrego domain = nbdomain; 3157f667e74Sjose borrego } 316da6c28aaSamw 317da6c28aaSamw if (username) 3187f667e74Sjose borrego token->tkn_account_name = strdup(username); 319da6c28aaSamw if (domain) 3207f667e74Sjose borrego token->tkn_domain_name = strdup(domain); 321da6c28aaSamw 3227f667e74Sjose borrego if (token->tkn_account_name == NULL || token->tkn_domain_name == NULL) 323da6c28aaSamw return (NT_STATUS_NO_MEMORY); 324da6c28aaSamw 3257f667e74Sjose borrego status = netr_setup_token_wingrps(info3, token); 3267f667e74Sjose borrego if (status != NT_STATUS_SUCCESS) 3277f667e74Sjose borrego return (status); 328da6c28aaSamw 3298c10a865Sas200622 /* 3308c10a865Sas200622 * The UserSessionKey in NetrSamLogon RPC is obfuscated using the 331c8ec8eeaSjose borrego * session key obtained in the NETLOGON credential chain. 332c8ec8eeaSjose borrego * An 8 byte session key is zero extended to 16 bytes. This 16 byte 3338c10a865Sas200622 * key is the key to the RC4 algorithm. The RC4 byte stream is 3348c10a865Sas200622 * exclusively ored with the 16 byte UserSessionKey to recover 3358c10a865Sas200622 * the the clear form. 3368c10a865Sas200622 */ 33712b65585SGordon Ross if ((token->tkn_ssnkey.val = malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL) 3388c10a865Sas200622 return (NT_STATUS_NO_MEMORY); 33912b65585SGordon Ross token->tkn_ssnkey.len = SMBAUTH_SESSION_KEY_SZ; 3408c10a865Sas200622 bzero(rc4key, SMBAUTH_SESSION_KEY_SZ); 3412c1b14e5Sjose borrego bcopy(netr_info->session_key.key, rc4key, netr_info->session_key.len); 34212b65585SGordon Ross bcopy(info3->UserSessionKey.data, token->tkn_ssnkey.val, 3438c10a865Sas200622 SMBAUTH_SESSION_KEY_SZ); 34412b65585SGordon Ross rand_hash((unsigned char *)token->tkn_ssnkey.val, 3458c10a865Sas200622 SMBAUTH_SESSION_KEY_SZ, rc4key, SMBAUTH_SESSION_KEY_SZ); 3467f667e74Sjose borrego 347da6c28aaSamw return (NT_STATUS_SUCCESS); 348da6c28aaSamw } 349da6c28aaSamw 350da6c28aaSamw /* 351da6c28aaSamw * netr_server_samlogon 352da6c28aaSamw * 353da6c28aaSamw * NetrServerSamLogon RPC: interactive or network. It is assumed that 354da6c28aaSamw * we have already authenticated with the PDC. If everything works, 355da6c28aaSamw * we build a user info structure and return it, where the caller will 356da6c28aaSamw * probably build an access token. 357da6c28aaSamw * 358da6c28aaSamw * Returns an NT status. There are numerous possibilities here. 359da6c28aaSamw * For example: 360da6c28aaSamw * NT_STATUS_INVALID_INFO_CLASS 361da6c28aaSamw * NT_STATUS_INVALID_PARAMETER 362da6c28aaSamw * NT_STATUS_ACCESS_DENIED 363da6c28aaSamw * NT_STATUS_PASSWORD_MUST_CHANGE 364da6c28aaSamw * NT_STATUS_NO_SUCH_USER 365da6c28aaSamw * NT_STATUS_WRONG_PASSWORD 366da6c28aaSamw * NT_STATUS_LOGON_FAILURE 367da6c28aaSamw * NT_STATUS_ACCOUNT_RESTRICTION 368da6c28aaSamw * NT_STATUS_INVALID_LOGON_HOURS 369da6c28aaSamw * NT_STATUS_INVALID_WORKSTATION 370da6c28aaSamw * NT_STATUS_INTERNAL_ERROR 371da6c28aaSamw * NT_STATUS_PASSWORD_EXPIRED 372da6c28aaSamw * NT_STATUS_ACCOUNT_DISABLED 373da6c28aaSamw */ 3747f667e74Sjose borrego uint32_t 375da6c28aaSamw netr_server_samlogon(mlsvc_handle_t *netr_handle, netr_info_t *netr_info, 3769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char *server, smb_logon_t *user_info, smb_token_t *token) 377da6c28aaSamw { 378da6c28aaSamw struct netr_SamLogon arg; 379da6c28aaSamw struct netr_authenticator auth; 380da6c28aaSamw struct netr_authenticator ret_auth; 381da6c28aaSamw struct netr_logon_info1 info1; 382da6c28aaSamw struct netr_logon_info2 info2; 383da6c28aaSamw struct netr_validation_info3 *info3; 3848d7e4166Sjose borrego ndr_heap_t *heap; 385da6c28aaSamw int opnum; 386da6c28aaSamw int rc, len; 3877f667e74Sjose borrego uint32_t status; 388da6c28aaSamw 389da6c28aaSamw bzero(&arg, sizeof (struct netr_SamLogon)); 390da6c28aaSamw opnum = NETR_OPNUM_SamLogon; 391da6c28aaSamw 392da6c28aaSamw /* 393da6c28aaSamw * Should we get the server and hostname from netr_info? 394da6c28aaSamw */ 395da6c28aaSamw 3968d7e4166Sjose borrego len = strlen(server) + 4; 3978d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(netr_handle, len); 3988d7e4166Sjose borrego arg.hostname = ndr_rpc_malloc(netr_handle, NETBIOS_NAME_SZ); 3998d7e4166Sjose borrego if (arg.servername == NULL || arg.hostname == NULL) { 4008d7e4166Sjose borrego ndr_rpc_release(netr_handle); 4018d7e4166Sjose borrego return (NT_STATUS_INTERNAL_ERROR); 4028d7e4166Sjose borrego } 4038d7e4166Sjose borrego 4048d7e4166Sjose borrego (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 4058d7e4166Sjose borrego if (smb_getnetbiosname((char *)arg.hostname, NETBIOS_NAME_SZ) != 0) { 4068d7e4166Sjose borrego ndr_rpc_release(netr_handle); 407da6c28aaSamw return (NT_STATUS_INTERNAL_ERROR); 408da6c28aaSamw } 409da6c28aaSamw 410da6c28aaSamw rc = netr_setup_authenticator(netr_info, &auth, &ret_auth); 411da6c28aaSamw if (rc != SMBAUTH_SUCCESS) { 4128d7e4166Sjose borrego ndr_rpc_release(netr_handle); 413da6c28aaSamw return (NT_STATUS_INTERNAL_ERROR); 414da6c28aaSamw } 415da6c28aaSamw 416da6c28aaSamw arg.auth = &auth; 417da6c28aaSamw arg.ret_auth = &ret_auth; 418da6c28aaSamw arg.validation_level = NETR_VALIDATION_LEVEL3; 4199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States arg.logon_info.logon_level = user_info->lg_level; 4209fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States arg.logon_info.switch_value = user_info->lg_level; 421da6c28aaSamw 4228d7e4166Sjose borrego heap = ndr_rpc_get_heap(netr_handle); 4238d7e4166Sjose borrego 4249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States switch (user_info->lg_level) { 425da6c28aaSamw case NETR_INTERACTIVE_LOGON: 4269fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_setup_identity(heap, user_info, &info1.identity); 4279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_interactive_samlogon(netr_info, user_info, &info1); 428da6c28aaSamw arg.logon_info.ru.info1 = &info1; 429da6c28aaSamw break; 430da6c28aaSamw 431da6c28aaSamw case NETR_NETWORK_LOGON: 432f9bc6dadSDmitry.Savitsky@nexenta.com if (user_info->lg_challenge_key.len < 8 || 433f9bc6dadSDmitry.Savitsky@nexenta.com user_info->lg_challenge_key.val == NULL) { 434f9bc6dadSDmitry.Savitsky@nexenta.com ndr_rpc_release(netr_handle); 435f9bc6dadSDmitry.Savitsky@nexenta.com return (NT_STATUS_INVALID_PARAMETER); 436f9bc6dadSDmitry.Savitsky@nexenta.com } 4379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_setup_identity(heap, user_info, &info2.identity); 4389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_network_samlogon(heap, netr_info, user_info, &info2); 439da6c28aaSamw arg.logon_info.ru.info2 = &info2; 440da6c28aaSamw break; 441da6c28aaSamw 442da6c28aaSamw default: 4438d7e4166Sjose borrego ndr_rpc_release(netr_handle); 444da6c28aaSamw return (NT_STATUS_INVALID_PARAMETER); 445da6c28aaSamw } 446da6c28aaSamw 4478d7e4166Sjose borrego rc = ndr_rpc_call(netr_handle, opnum, &arg); 448da6c28aaSamw if (rc != 0) { 449da6c28aaSamw bzero(netr_info, sizeof (netr_info_t)); 450da6c28aaSamw status = NT_STATUS_INVALID_PARAMETER; 451da6c28aaSamw } else if (arg.status != 0) { 452da6c28aaSamw status = NT_SC_VALUE(arg.status); 453da6c28aaSamw 454da6c28aaSamw /* 455da6c28aaSamw * We need to validate the chain even though we have 456da6c28aaSamw * a non-zero status. If the status is ACCESS_DENIED 457da6c28aaSamw * this will trigger a new credential chain. However, 458da6c28aaSamw * a valid credential is returned with some status 459da6c28aaSamw * codes; for example, WRONG_PASSWORD. 460da6c28aaSamw */ 461da6c28aaSamw (void) netr_validate_chain(netr_info, arg.ret_auth); 462da6c28aaSamw } else { 463da6c28aaSamw status = netr_validate_chain(netr_info, arg.ret_auth); 464da6c28aaSamw if (status == NT_STATUS_INSUFFICIENT_LOGON_INFO) { 4658d7e4166Sjose borrego ndr_rpc_release(netr_handle); 466da6c28aaSamw return (status); 467da6c28aaSamw } 468da6c28aaSamw 469da6c28aaSamw info3 = arg.ru.info3; 4709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States status = netr_setup_token(info3, user_info, netr_info, token); 471da6c28aaSamw } 472da6c28aaSamw 4738d7e4166Sjose borrego ndr_rpc_release(netr_handle); 474da6c28aaSamw return (status); 475da6c28aaSamw } 476da6c28aaSamw 477da6c28aaSamw /* 478da6c28aaSamw * netr_interactive_samlogon 479da6c28aaSamw * 480da6c28aaSamw * Set things up for an interactive SamLogon. Copy the NT and LM 481da6c28aaSamw * passwords to the logon structure and hash them with the session 482da6c28aaSamw * key. 483da6c28aaSamw */ 484da6c28aaSamw static void 4859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_interactive_samlogon(netr_info_t *netr_info, smb_logon_t *user_info, 486da6c28aaSamw struct netr_logon_info1 *info1) 487da6c28aaSamw { 488da6c28aaSamw BYTE key[NETR_OWF_PASSWORD_SZ]; 489da6c28aaSamw 490da6c28aaSamw (void) memcpy(&info1->lm_owf_password, 4919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_info->lg_lm_password.val, sizeof (netr_owf_password_t)); 492da6c28aaSamw 493da6c28aaSamw (void) memcpy(&info1->nt_owf_password, 4949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_info->lg_nt_password.val, sizeof (netr_owf_password_t)); 495da6c28aaSamw 496da6c28aaSamw (void) memset(key, 0, NETR_OWF_PASSWORD_SZ); 4972c1b14e5Sjose borrego (void) memcpy(key, netr_info->session_key.key, 4982c1b14e5Sjose borrego netr_info->session_key.len); 499da6c28aaSamw 500da6c28aaSamw rand_hash((unsigned char *)&info1->lm_owf_password, 501da6c28aaSamw NETR_OWF_PASSWORD_SZ, key, NETR_OWF_PASSWORD_SZ); 502da6c28aaSamw 503da6c28aaSamw rand_hash((unsigned char *)&info1->nt_owf_password, 504da6c28aaSamw NETR_OWF_PASSWORD_SZ, key, NETR_OWF_PASSWORD_SZ); 505da6c28aaSamw } 506da6c28aaSamw 507da6c28aaSamw /* 508da6c28aaSamw * netr_network_samlogon 509da6c28aaSamw * 510da6c28aaSamw * Set things up for a network SamLogon. We provide a copy of the random 511da6c28aaSamw * challenge, that we sent to the client, to the domain controller. This 512da6c28aaSamw * is the key that the client will have used to encrypt the NT and LM 513da6c28aaSamw * passwords. Note that Windows 9x clients may not provide both passwords. 514da6c28aaSamw */ 515da6c28aaSamw /*ARGSUSED*/ 516da6c28aaSamw static void 5178d7e4166Sjose borrego netr_network_samlogon(ndr_heap_t *heap, netr_info_t *netr_info, 5189fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_logon_t *user_info, struct netr_logon_info2 *info2) 519da6c28aaSamw { 5202c1b14e5Sjose borrego uint32_t len; 5212c1b14e5Sjose borrego 522f9bc6dadSDmitry.Savitsky@nexenta.com if (user_info->lg_challenge_key.len >= 8 && 523f9bc6dadSDmitry.Savitsky@nexenta.com user_info->lg_challenge_key.val != 0) { 524f9bc6dadSDmitry.Savitsky@nexenta.com bcopy(user_info->lg_challenge_key.val, 525f9bc6dadSDmitry.Savitsky@nexenta.com info2->lm_challenge.data, 8); 526f9bc6dadSDmitry.Savitsky@nexenta.com } else { 527f9bc6dadSDmitry.Savitsky@nexenta.com bzero(info2->lm_challenge.data, 8); 528f9bc6dadSDmitry.Savitsky@nexenta.com } 529da6c28aaSamw 5309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((len = user_info->lg_nt_password.len) != 0) { 5319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ndr_heap_mkvcb(heap, user_info->lg_nt_password.val, len, 5328d7e4166Sjose borrego (ndr_vcbuf_t *)&info2->nt_response); 533da6c28aaSamw } else { 5342c1b14e5Sjose borrego bzero(&info2->nt_response, sizeof (netr_vcbuf_t)); 535da6c28aaSamw } 536da6c28aaSamw 5379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if ((len = user_info->lg_lm_password.len) != 0) { 5389fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ndr_heap_mkvcb(heap, user_info->lg_lm_password.val, len, 5398d7e4166Sjose borrego (ndr_vcbuf_t *)&info2->lm_response); 540da6c28aaSamw } else { 5412c1b14e5Sjose borrego bzero(&info2->lm_response, sizeof (netr_vcbuf_t)); 542da6c28aaSamw } 543da6c28aaSamw } 544da6c28aaSamw 545da6c28aaSamw /* 546da6c28aaSamw * netr_setup_authenticator 547da6c28aaSamw * 548da6c28aaSamw * Set up the request and return authenticators. A new credential is 549da6c28aaSamw * generated from the session key, the current client credential and 550da6c28aaSamw * the current time, i.e. 551da6c28aaSamw * 552da6c28aaSamw * NewCredential = Cred(SessionKey, OldCredential, time); 553da6c28aaSamw * 554da6c28aaSamw * The timestamp, which is used as a random seed, is stored in both 555da6c28aaSamw * the request and return authenticators. 556da6c28aaSamw * 557da6c28aaSamw * If any difficulties occur using the cryptographic framework, the 558da6c28aaSamw * function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is 559da6c28aaSamw * returned. 560da6c28aaSamw */ 561da6c28aaSamw int 562da6c28aaSamw netr_setup_authenticator(netr_info_t *netr_info, 563da6c28aaSamw struct netr_authenticator *auth, struct netr_authenticator *ret_auth) 564da6c28aaSamw { 565da6c28aaSamw bzero(auth, sizeof (struct netr_authenticator)); 566da6c28aaSamw 56755bf511dSas200622 netr_info->timestamp = time(0); 568da6c28aaSamw auth->timestamp = netr_info->timestamp; 569da6c28aaSamw 5702c1b14e5Sjose borrego if (netr_gen_credentials(netr_info->session_key.key, 571da6c28aaSamw &netr_info->client_credential, 572da6c28aaSamw netr_info->timestamp, 573da6c28aaSamw (netr_cred_t *)&auth->credential) != SMBAUTH_SUCCESS) 574da6c28aaSamw return (SMBAUTH_FAILURE); 575da6c28aaSamw 576da6c28aaSamw if (ret_auth) { 577da6c28aaSamw bzero(ret_auth, sizeof (struct netr_authenticator)); 578da6c28aaSamw ret_auth->timestamp = netr_info->timestamp; 579da6c28aaSamw } 580da6c28aaSamw 581da6c28aaSamw return (SMBAUTH_SUCCESS); 582da6c28aaSamw } 583da6c28aaSamw 584da6c28aaSamw /* 585da6c28aaSamw * Validate the returned credentials and update the credential chain. 586da6c28aaSamw * The server returns an updated client credential rather than a new 587da6c28aaSamw * server credential. The server uses (timestamp + 1) when generating 588da6c28aaSamw * the credential. 589da6c28aaSamw * 590da6c28aaSamw * Generate the new seed for the credential chain. The new seed is 591da6c28aaSamw * formed by adding (timestamp + 1) to the current client credential. 5927f667e74Sjose borrego * The only quirk is the uint32_t style addition. 593da6c28aaSamw * 594da6c28aaSamw * Returns NT_STATUS_INSUFFICIENT_LOGON_INFO if auth->credential is a 595da6c28aaSamw * NULL pointer. The Authenticator field of the SamLogon response packet 596da6c28aaSamw * sent by the Samba 3 PDC always return NULL pointer if the received 597da6c28aaSamw * SamLogon request is not immediately followed by the ServerReqChallenge 598da6c28aaSamw * and ServerAuthenticate2 requests. 599da6c28aaSamw * 600da6c28aaSamw * Returns NT_STATUS_SUCCESS if the server returned a valid credential. 601da6c28aaSamw * Otherwise we retirm NT_STATUS_UNSUCCESSFUL. 602da6c28aaSamw */ 6037f667e74Sjose borrego uint32_t 604da6c28aaSamw netr_validate_chain(netr_info_t *netr_info, struct netr_authenticator *auth) 605da6c28aaSamw { 606da6c28aaSamw netr_cred_t cred; 6077f667e74Sjose borrego uint32_t result = NT_STATUS_SUCCESS; 6087f667e74Sjose borrego uint32_t *dwp; 609da6c28aaSamw 610da6c28aaSamw ++netr_info->timestamp; 611da6c28aaSamw 6122c1b14e5Sjose borrego if (netr_gen_credentials(netr_info->session_key.key, 613da6c28aaSamw &netr_info->client_credential, 614da6c28aaSamw netr_info->timestamp, &cred) != SMBAUTH_SUCCESS) 615da6c28aaSamw return (NT_STATUS_INTERNAL_ERROR); 616da6c28aaSamw 617da6c28aaSamw if (&auth->credential == 0) { 618da6c28aaSamw /* 619da6c28aaSamw * If the validation fails, destroy the credential chain. 620da6c28aaSamw * This should trigger a new authentication chain. 621da6c28aaSamw */ 622da6c28aaSamw bzero(netr_info, sizeof (netr_info_t)); 623da6c28aaSamw return (NT_STATUS_INSUFFICIENT_LOGON_INFO); 624da6c28aaSamw } 625da6c28aaSamw 626da6c28aaSamw result = memcmp(&cred, &auth->credential, sizeof (netr_cred_t)); 627da6c28aaSamw if (result != 0) { 628da6c28aaSamw /* 629da6c28aaSamw * If the validation fails, destroy the credential chain. 630da6c28aaSamw * This should trigger a new authentication chain. 631da6c28aaSamw */ 632da6c28aaSamw bzero(netr_info, sizeof (netr_info_t)); 633da6c28aaSamw result = NT_STATUS_UNSUCCESSFUL; 634da6c28aaSamw } else { 635da6c28aaSamw /* 636da6c28aaSamw * Otherwise generate the next step in the chain. 637da6c28aaSamw */ 638da6c28aaSamw /*LINTED E_BAD_PTR_CAST_ALIGN*/ 6397f667e74Sjose borrego dwp = (uint32_t *)&netr_info->client_credential; 640da6c28aaSamw dwp[0] += netr_info->timestamp; 641da6c28aaSamw 642da6c28aaSamw netr_info->flags |= NETR_FLG_VALID; 643da6c28aaSamw } 644da6c28aaSamw 645da6c28aaSamw return (result); 646da6c28aaSamw } 647da6c28aaSamw 648da6c28aaSamw /* 649da6c28aaSamw * netr_invalidate_chain 650da6c28aaSamw * 651da6c28aaSamw * Mark the credential chain as invalid so that it will be recreated 652da6c28aaSamw * on the next attempt. 653da6c28aaSamw */ 654da6c28aaSamw static void 655da6c28aaSamw netr_invalidate_chain(void) 656da6c28aaSamw { 657da6c28aaSamw netr_global_info.flags &= ~NETR_FLG_VALID; 658da6c28aaSamw } 659da6c28aaSamw 660da6c28aaSamw /* 661da6c28aaSamw * netr_setup_identity 662da6c28aaSamw * 663da6c28aaSamw * Set up the client identity information. All of this information is 664da6c28aaSamw * specifically related to the client user and workstation attempting 665da6c28aaSamw * to access this system. It may not be in our primary domain. 666da6c28aaSamw * 667da6c28aaSamw * I don't know what logon_id is, it seems to be a unique identifier. 668da6c28aaSamw * Increment it before each use. 669da6c28aaSamw */ 670da6c28aaSamw static void 6719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States netr_setup_identity(ndr_heap_t *heap, smb_logon_t *user_info, 672da6c28aaSamw netr_logon_id_t *identity) 673da6c28aaSamw { 6748d7e4166Sjose borrego static mutex_t logon_id_mutex; 6758d7e4166Sjose borrego static uint32_t logon_id; 6768d7e4166Sjose borrego 6778d7e4166Sjose borrego (void) mutex_lock(&logon_id_mutex); 678da6c28aaSamw 679da6c28aaSamw if (logon_id == 0) 680da6c28aaSamw logon_id = 0xDCD0; 681da6c28aaSamw 682da6c28aaSamw ++logon_id; 6839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States user_info->lg_logon_id = logon_id; 684da6c28aaSamw 6858d7e4166Sjose borrego (void) mutex_unlock(&logon_id_mutex); 6868d7e4166Sjose borrego 68712b65585SGordon Ross /* 68812b65585SGordon Ross * [MS-APDS] 3.1.5.2 "NTLM Network Logon" says to set 68912b65585SGordon Ross * ParameterControl to the 'E' + 'K' bits. Those are: 69012b65585SGordon Ross * (1 << 5) | (1 << 11), a.k.a 69112b65585SGordon Ross */ 69212b65585SGordon Ross identity->parameter_control = 69312b65585SGordon Ross MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | 69412b65585SGordon Ross MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT; 695da6c28aaSamw identity->logon_id.LowPart = logon_id; 696da6c28aaSamw identity->logon_id.HighPart = 0; 697da6c28aaSamw 6989fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ndr_heap_mkvcs(heap, user_info->lg_domain, 6998d7e4166Sjose borrego (ndr_vcstr_t *)&identity->domain_name); 700da6c28aaSamw 7019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ndr_heap_mkvcs(heap, user_info->lg_username, 7028d7e4166Sjose borrego (ndr_vcstr_t *)&identity->username); 703da6c28aaSamw 704da6c28aaSamw /* 705da6c28aaSamw * Some systems prefix the client workstation name with \\. 706da6c28aaSamw * It doesn't seem to make any difference whether it's there 707da6c28aaSamw * or not. 708da6c28aaSamw */ 7099fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States ndr_heap_mkvcs(heap, user_info->lg_workstation, 7108d7e4166Sjose borrego (ndr_vcstr_t *)&identity->workstation); 711da6c28aaSamw } 7127f667e74Sjose borrego 7137f667e74Sjose borrego /* 7147f667e74Sjose borrego * Sets up domain, local and well-known group membership for the given 7157f667e74Sjose borrego * token. Two assumptions have been made here: 7167f667e74Sjose borrego * 7177f667e74Sjose borrego * a) token already contains a valid user SID so that group 7187f667e74Sjose borrego * memberships can be established 7197f667e74Sjose borrego * 7207f667e74Sjose borrego * b) token belongs to a domain user 7217f667e74Sjose borrego */ 7227f667e74Sjose borrego static uint32_t 7237f667e74Sjose borrego netr_setup_token_wingrps(struct netr_validation_info3 *info3, 7247f667e74Sjose borrego smb_token_t *token) 7257f667e74Sjose borrego { 7267f667e74Sjose borrego smb_ids_t tkn_grps; 7277f667e74Sjose borrego uint32_t status; 7287f667e74Sjose borrego 7297f667e74Sjose borrego tkn_grps.i_cnt = 0; 7307f667e74Sjose borrego tkn_grps.i_ids = NULL; 7317f667e74Sjose borrego 7327f667e74Sjose borrego status = netr_setup_domain_groups(info3, &tkn_grps); 7337f667e74Sjose borrego if (status != NT_STATUS_SUCCESS) { 7347f667e74Sjose borrego smb_ids_free(&tkn_grps); 7357f667e74Sjose borrego return (status); 7367f667e74Sjose borrego } 7377f667e74Sjose borrego 7387f667e74Sjose borrego status = smb_sam_usr_groups(token->tkn_user.i_sid, &tkn_grps); 7397f667e74Sjose borrego if (status != NT_STATUS_SUCCESS) { 7407f667e74Sjose borrego smb_ids_free(&tkn_grps); 7417f667e74Sjose borrego return (status); 7427f667e74Sjose borrego } 7437f667e74Sjose borrego 74429bd2886SAlan Wright if (netr_isadmin(info3)) 74529bd2886SAlan Wright token->tkn_flags |= SMB_ATF_ADMIN; 74629bd2886SAlan Wright 74729bd2886SAlan Wright status = smb_wka_token_groups(token->tkn_flags, &tkn_grps); 7487f667e74Sjose borrego if (status == NT_STATUS_SUCCESS) 7497f667e74Sjose borrego token->tkn_win_grps = tkn_grps; 7507f667e74Sjose borrego else 7517f667e74Sjose borrego smb_ids_free(&tkn_grps); 7527f667e74Sjose borrego 7537f667e74Sjose borrego return (status); 7547f667e74Sjose borrego } 7557f667e74Sjose borrego 7567f667e74Sjose borrego /* 7577f667e74Sjose borrego * Converts groups information in the returned structure by domain controller 7587f667e74Sjose borrego * (info3) to an internal representation (gids) 7597f667e74Sjose borrego */ 7607f667e74Sjose borrego static uint32_t 7617f667e74Sjose borrego netr_setup_domain_groups(struct netr_validation_info3 *info3, smb_ids_t *gids) 7627f667e74Sjose borrego { 7637f667e74Sjose borrego smb_sid_t *domain_sid; 7647f667e74Sjose borrego smb_id_t *ids; 7657f667e74Sjose borrego int i, total_cnt; 7667f667e74Sjose borrego 7677f667e74Sjose borrego if ((i = info3->GroupCount) == 0) 7687f667e74Sjose borrego i++; 7697f667e74Sjose borrego i += info3->SidCount; 7707f667e74Sjose borrego 7717f667e74Sjose borrego total_cnt = gids->i_cnt + i; 7727f667e74Sjose borrego 7737f667e74Sjose borrego gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t)); 7747f667e74Sjose borrego if (gids->i_ids == NULL) 7757f667e74Sjose borrego return (NT_STATUS_NO_MEMORY); 7767f667e74Sjose borrego 7777f667e74Sjose borrego domain_sid = (smb_sid_t *)info3->LogonDomainId; 7787f667e74Sjose borrego 7797f667e74Sjose borrego ids = gids->i_ids + gids->i_cnt; 7807f667e74Sjose borrego for (i = 0; i < info3->GroupCount; i++, gids->i_cnt++, ids++) { 7817f667e74Sjose borrego ids->i_sid = smb_sid_splice(domain_sid, info3->GroupIds[i].rid); 7827f667e74Sjose borrego if (ids->i_sid == NULL) 7837f667e74Sjose borrego return (NT_STATUS_NO_MEMORY); 7847f667e74Sjose borrego 7857f667e74Sjose borrego ids->i_attrs = info3->GroupIds[i].attributes; 7867f667e74Sjose borrego } 7877f667e74Sjose borrego 7887f667e74Sjose borrego if (info3->GroupCount == 0) { 7897f667e74Sjose borrego /* 7907f667e74Sjose borrego * if there's no global group should add the primary group. 7917f667e74Sjose borrego */ 7927f667e74Sjose borrego ids->i_sid = smb_sid_splice(domain_sid, info3->PrimaryGroupId); 7937f667e74Sjose borrego if (ids->i_sid == NULL) 7947f667e74Sjose borrego return (NT_STATUS_NO_MEMORY); 7957f667e74Sjose borrego 7967f667e74Sjose borrego ids->i_attrs = 0x7; 7977f667e74Sjose borrego gids->i_cnt++; 7987f667e74Sjose borrego ids++; 7997f667e74Sjose borrego } 8007f667e74Sjose borrego 8017f667e74Sjose borrego /* Add the extra SIDs */ 8027f667e74Sjose borrego for (i = 0; i < info3->SidCount; i++, gids->i_cnt++, ids++) { 8037f667e74Sjose borrego ids->i_sid = smb_sid_dup((smb_sid_t *)info3->ExtraSids[i].sid); 8047f667e74Sjose borrego if (ids->i_sid == NULL) 8057f667e74Sjose borrego return (NT_STATUS_NO_MEMORY); 8067f667e74Sjose borrego 8077f667e74Sjose borrego ids->i_attrs = info3->ExtraSids[i].attributes; 8087f667e74Sjose borrego } 8097f667e74Sjose borrego 8107f667e74Sjose borrego return (NT_STATUS_SUCCESS); 8117f667e74Sjose borrego } 8127f667e74Sjose borrego 8137f667e74Sjose borrego /* 8147f667e74Sjose borrego * Determines if the given user is the domain Administrator or a 8157f667e74Sjose borrego * member of Domain Admins 8167f667e74Sjose borrego */ 8177f667e74Sjose borrego static boolean_t 8187f667e74Sjose borrego netr_isadmin(struct netr_validation_info3 *info3) 8197f667e74Sjose borrego { 820a0aa776eSAlan Wright smb_domain_t di; 8217f667e74Sjose borrego int i; 8227f667e74Sjose borrego 823a0aa776eSAlan Wright if (!smb_domain_lookup_sid((smb_sid_t *)info3->LogonDomainId, &di)) 8247f667e74Sjose borrego return (B_FALSE); 8257f667e74Sjose borrego 826a0aa776eSAlan Wright if (di.di_type != SMB_DOMAIN_PRIMARY) 8277f667e74Sjose borrego return (B_FALSE); 8287f667e74Sjose borrego 8297f667e74Sjose borrego if ((info3->UserId == DOMAIN_USER_RID_ADMIN) || 8307f667e74Sjose borrego (info3->PrimaryGroupId == DOMAIN_GROUP_RID_ADMINS)) 8317f667e74Sjose borrego return (B_TRUE); 8327f667e74Sjose borrego 8337f667e74Sjose borrego for (i = 0; i < info3->GroupCount; i++) 8347f667e74Sjose borrego if (info3->GroupIds[i].rid == DOMAIN_GROUP_RID_ADMINS) 8357f667e74Sjose borrego return (B_TRUE); 8367f667e74Sjose borrego 8377f667e74Sjose borrego return (B_FALSE); 8387f667e74Sjose borrego } 839