xref: /titanic_52/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c (revision b3700b074e637f8c6991b70754c88a2cfffb246b)
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