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.
24c585f97bSMatt Barden  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
25*0ccfe583SMatt Barden  * Copyright 2023 RackTop Systems, Inc.
26da6c28aaSamw  */
27da6c28aaSamw 
28da6c28aaSamw /*
29da6c28aaSamw  * NETR challenge/response client functions.
30da6c28aaSamw  *
31da6c28aaSamw  * NT_STATUS_INVALID_PARAMETER
32da6c28aaSamw  * NT_STATUS_NO_TRUST_SAM_ACCOUNT
33da6c28aaSamw  * NT_STATUS_ACCESS_DENIED
34da6c28aaSamw  */
35da6c28aaSamw 
36da6c28aaSamw #include <stdio.h>
37da6c28aaSamw #include <stdlib.h>
38da6c28aaSamw #include <strings.h>
39da6c28aaSamw #include <unistd.h>
40da6c28aaSamw #include <ctype.h>
413db3f65cSamw #include <security/cryptoki.h>
423db3f65cSamw #include <security/pkcs11.h>
43da6c28aaSamw 
44da6c28aaSamw #include <smbsrv/libsmb.h>
456537f381Sas200622 #include <smbsrv/libsmbns.h>
468d7e4166Sjose borrego #include <smbsrv/libmlsvc.h>
47ce8560eeSMatt Barden #include <mlsvc.h>
48da6c28aaSamw #include <smbsrv/ndl/netlogon.ndl>
49da6c28aaSamw #include <smbsrv/smbinfo.h>
50da6c28aaSamw #include <smbsrv/netrauth.h>
51da6c28aaSamw 
523db3f65cSamw #define	NETR_SESSKEY_ZEROBUF_SZ		4
532c1b14e5Sjose borrego /* The DES algorithm uses a 56-bit encryption key. */
543db3f65cSamw #define	NETR_DESKEY_LEN			7
553db3f65cSamw 
56da6c28aaSamw int netr_setup_authenticator(netr_info_t *, struct netr_authenticator *,
57da6c28aaSamw     struct netr_authenticator *);
58da6c28aaSamw DWORD netr_validate_chain(netr_info_t *, struct netr_authenticator *);
59da6c28aaSamw 
60da6c28aaSamw static int netr_server_req_challenge(mlsvc_handle_t *, netr_info_t *);
61da6c28aaSamw static int netr_server_authenticate2(mlsvc_handle_t *, netr_info_t *);
62da6c28aaSamw static int netr_gen_password(BYTE *, BYTE *, BYTE *);
63da6c28aaSamw 
64da6c28aaSamw /*
65da6c28aaSamw  * Shared with netr_logon.c
66da6c28aaSamw  */
67ce8560eeSMatt Barden netr_info_t netr_global_info = {
68ce8560eeSMatt Barden 	.use_secure_rpc = B_TRUE,
69ce8560eeSMatt Barden 	.use_logon_ex = B_TRUE
70ce8560eeSMatt Barden };
71ce8560eeSMatt Barden extern ndr_auth_ctx_t netr_ssp_ctx;
72ce8560eeSMatt Barden 
73ce8560eeSMatt Barden /*
74ce8560eeSMatt Barden  * These flags control various parts of NetLogon RPC messages.
75ce8560eeSMatt Barden  * The default is 0 - setting a bit disables some feature.
76ce8560eeSMatt Barden  * They are set in smbd/netlogon_flags in svc:/network/smb/server.
77ce8560eeSMatt Barden  * These are set when smbd starts. Changing them requires
78ce8560eeSMatt Barden  * restarting smbd.
79ce8560eeSMatt Barden  *
80ce8560eeSMatt Barden  * These shouldn't be confused with either SamLogonEx's ExtraFlags,
81ce8560eeSMatt Barden  * or NetrServerAuthenticate's negotiate_flags.
82ce8560eeSMatt Barden  *
83ce8560eeSMatt Barden  * DISABLE_SECURE_RPC causes Netlogon to use unauthenticated RPC.
84ce8560eeSMatt Barden  * Note that the underlying transport is still authenticated and signed.
85ce8560eeSMatt Barden  *
86ce8560eeSMatt Barden  * DISABLE_RESP_VERIF instructs RPC authentication to ignore failures
87ce8560eeSMatt Barden  * when verifying responses.
88ce8560eeSMatt Barden  *
89ce8560eeSMatt Barden  * DISABLE_SAMLOGONEX causes Netlogon to always use SamLogon, which
90ce8560eeSMatt Barden  * makes use of Netlogon Authenticators.
91*0ccfe583SMatt Barden  *
92*0ccfe583SMatt Barden  * DISABLE_SEALING causes Netlogon to use Signing (integrity) instead of
93*0ccfe583SMatt Barden  * Sealing (privacy).
94ce8560eeSMatt Barden  */
95ce8560eeSMatt Barden #define	NETR_CFG_DISABLE_SECURE_RPC	0x00000001
96ce8560eeSMatt Barden #define	NETR_CFG_DISABLE_RESP_VERIF	0x00000002
97ce8560eeSMatt Barden #define	NETR_CFG_DISABLE_SAMLOGONEX	0x00000004
98*0ccfe583SMatt Barden #define	NETR_CFG_DISABLE_SEALING	0x00000008
99ce8560eeSMatt Barden 
100ce8560eeSMatt Barden void
netlogon_init_global(uint32_t flags)101ce8560eeSMatt Barden netlogon_init_global(uint32_t flags)
102ce8560eeSMatt Barden {
103ce8560eeSMatt Barden 	netr_global_info.use_secure_rpc =
104ce8560eeSMatt Barden 	    ((flags & NETR_CFG_DISABLE_SECURE_RPC) == 0);
105ce8560eeSMatt Barden 	netr_ssp_ctx.auth_verify_resp =
106ce8560eeSMatt Barden 	    ((flags & NETR_CFG_DISABLE_RESP_VERIF) == 0);
107ce8560eeSMatt Barden 	netr_global_info.use_logon_ex =
108ce8560eeSMatt Barden 	    ((flags & NETR_CFG_DISABLE_SAMLOGONEX) == 0);
109*0ccfe583SMatt Barden 	if ((flags & NETR_CFG_DISABLE_SEALING) != 0)
110*0ccfe583SMatt Barden 		netr_ssp_ctx.auth_level = NDR_C_AUTHN_LEVEL_PKT_INTEGRITY;
111ce8560eeSMatt Barden }
112ce8560eeSMatt Barden 
113ce8560eeSMatt Barden /*
114ce8560eeSMatt Barden  * AES-CFB8 has the odd property that 1/256 keys will encrypt
115ce8560eeSMatt Barden  * a full block of 0s to all 0s. In order to mitigate this, Windows DCs
116ce8560eeSMatt Barden  * now reject Challenges and Credentials where "none of the first 5 bytes
117ce8560eeSMatt Barden  * are unique" (i.e. [MS-NRPC] 3.1.4.1 "Session-Key Negotiation" Step 7).
118ce8560eeSMatt Barden  * This detects that condition so that we can avoid having our connection
119ce8560eeSMatt Barden  * rejected unexpectedly.
120ce8560eeSMatt Barden  *
121ce8560eeSMatt Barden  * I've interpreted this condition as 'amongst the first 5 bytes,
122ce8560eeSMatt Barden  * at least one must appear exactly once'.
123ce8560eeSMatt Barden  *
124ce8560eeSMatt Barden  * NOTE: Win2012r2 seems to only reject challenges whose first 5 bytes are 0.
125ce8560eeSMatt Barden  */
126ce8560eeSMatt Barden boolean_t
passes_dc_mitigation(uint8_t * buf)127ce8560eeSMatt Barden passes_dc_mitigation(uint8_t *buf)
128ce8560eeSMatt Barden {
129ce8560eeSMatt Barden 	int i, j;
130ce8560eeSMatt Barden 
131ce8560eeSMatt Barden 	for (i = 0; i < 5; i++) {
132ce8560eeSMatt Barden 		for (j = 0; j < 5; j++) {
133ce8560eeSMatt Barden 			if (i != j && buf[i] == buf[j])
134ce8560eeSMatt Barden 				break;
135ce8560eeSMatt Barden 		}
136ce8560eeSMatt Barden 
137ce8560eeSMatt Barden 		/* if this byte didn't match any other byte, this passes */
138ce8560eeSMatt Barden 		if (j == 5)
139ce8560eeSMatt Barden 			return (B_TRUE);
140ce8560eeSMatt Barden 	}
141ce8560eeSMatt Barden 
142ce8560eeSMatt Barden 	/* None of the bytes were unique - the check fails */
143ce8560eeSMatt Barden 	return (B_FALSE);
144ce8560eeSMatt Barden }
145da6c28aaSamw 
146da6c28aaSamw /*
147da6c28aaSamw  * netlogon_auth
148da6c28aaSamw  *
149da6c28aaSamw  * This is the core of the NETLOGON authentication protocol.
150da6c28aaSamw  * Do the challenge response authentication.
151da6c28aaSamw  *
152da6c28aaSamw  * Prior to calling this function, an anonymous session to the NETLOGON
153da6c28aaSamw  * pipe on a domain controller(server) should have already been opened.
154faa1795aSjb150015  *
155faa1795aSjb150015  * Upon a successful NETLOGON credential chain establishment, the
156faa1795aSjb150015  * netlogon sequence number will be set to match the kpasswd sequence
157faa1795aSjb150015  * number.
158faa1795aSjb150015  *
159da6c28aaSamw  */
160da6c28aaSamw DWORD
netlogon_auth(char * server,char * domain,DWORD flags)161ce8560eeSMatt Barden netlogon_auth(char *server, char *domain, DWORD flags)
162da6c28aaSamw {
163ce8560eeSMatt Barden 	mlsvc_handle_t netr_handle;
164da6c28aaSamw 	netr_info_t *netr_info;
165da6c28aaSamw 	int rc;
16655bf511dSas200622 	DWORD leout_rc[2];
167ce8560eeSMatt Barden 	boolean_t retry;
168ce8560eeSMatt Barden 	DWORD status;
169ce8560eeSMatt Barden 
170ce8560eeSMatt Barden 	/*
171ce8560eeSMatt Barden 	 * [MS-NRPC] 3.1.4.1 "Session-Key Negotiation"
172ce8560eeSMatt Barden 	 * Negotiation happens on an 'unprotected RPC channel'
173ce8560eeSMatt Barden 	 * (no RPC-level auth).
174ce8560eeSMatt Barden 	 */
175ce8560eeSMatt Barden 	status = netr_open(server, domain, &netr_handle);
176ce8560eeSMatt Barden 
177ce8560eeSMatt Barden 	if (status != 0) {
178ce8560eeSMatt Barden 		syslog(LOG_ERR, "netlogon_auth remote open failed (%s)",
179ce8560eeSMatt Barden 		    xlate_nt_status(status));
180ce8560eeSMatt Barden 		return (status);
181ce8560eeSMatt Barden 	}
182da6c28aaSamw 
183da6c28aaSamw 	netr_info = &netr_global_info;
184ce8560eeSMatt Barden 	bzero(&netr_info->session_key, sizeof (netr_info->session_key));
185*0ccfe583SMatt Barden 	bzero(&netr_info->rpc_seal_key, sizeof (netr_info->rpc_seal_key));
186ce8560eeSMatt Barden 	netr_info->flags = flags;
187da6c28aaSamw 
188b89a8333Snatalie li - Sun Microsystems - Irvine United States 	rc = smb_getnetbiosname(netr_info->hostname, NETBIOS_NAME_SZ);
189da6c28aaSamw 	if (rc != 0)
190ce8560eeSMatt Barden 		goto errout;
191da6c28aaSamw 
192b3700b07SGordon Ross 	/* server is our DC.  Note: normally an FQDN. */
193da6c28aaSamw 	(void) snprintf(netr_info->server, sizeof (netr_info->server),
194da6c28aaSamw 	    "\\\\%s", server);
195da6c28aaSamw 
196ce8560eeSMatt Barden 	/*
197ce8560eeSMatt Barden 	 * Domain (FQDN and NetBIOS) Name needed for Netlogon SSP-based
198ce8560eeSMatt Barden 	 * Secure RPC.
199ce8560eeSMatt Barden 	 */
200ce8560eeSMatt Barden 	rc = smb_getdomainname(netr_info->nb_domain,
201ce8560eeSMatt Barden 	    sizeof (netr_info->nb_domain));
202ce8560eeSMatt Barden 	if (rc != 0)
203ce8560eeSMatt Barden 		goto errout;
204ce8560eeSMatt Barden 
205ce8560eeSMatt Barden 	rc = smb_getfqdomainname(netr_info->fqdn_domain,
206ce8560eeSMatt Barden 	    sizeof (netr_info->fqdn_domain));
207ce8560eeSMatt Barden 	if (rc != 0)
208ce8560eeSMatt Barden 		goto errout;
209ce8560eeSMatt Barden 
210ce8560eeSMatt Barden 	/*
211ce8560eeSMatt Barden 	 * [MS-NRPC] 3.1.4.1 "Session-Key Negotiation" Step 7
212ce8560eeSMatt Barden 	 * Windows DCs will reject negotiate attempts if none of the first
213ce8560eeSMatt Barden 	 * 5 bytes of the Challenge are unique.
214ce8560eeSMatt Barden 	 * Keep retrying until we've generated one that satisfies this.
215ce8560eeSMatt Barden 	 */
216ce8560eeSMatt Barden 	do {
217ce8560eeSMatt Barden 		retry = B_FALSE;
218ce8560eeSMatt Barden 		LE_OUT32(&leout_rc[0], arc4random());
219ce8560eeSMatt Barden 		LE_OUT32(&leout_rc[1], arc4random());
22055bf511dSas200622 		(void) memcpy(&netr_info->client_challenge, leout_rc,
221da6c28aaSamw 		    sizeof (struct netr_credential));
222da6c28aaSamw 
223ce8560eeSMatt Barden 		if (!passes_dc_mitigation(netr_info->client_challenge.data))
224ce8560eeSMatt Barden 			retry = B_TRUE;
225ce8560eeSMatt Barden 	} while (retry);
226ce8560eeSMatt Barden 
227ce8560eeSMatt Barden 	if ((rc = netr_server_req_challenge(&netr_handle, netr_info)) == 0) {
228ce8560eeSMatt Barden 		rc = netr_server_authenticate2(&netr_handle, netr_info);
229faa1795aSjb150015 		if (rc == 0) {
2301ed6b69aSGordon Ross 			/*
2311ed6b69aSGordon Ross 			 * TODO: (later)  When joining a domain using a
2321ed6b69aSGordon Ross 			 * pre-created machine account, should do:
2331ed6b69aSGordon Ross 			 * netr_server_password_set(&netr_handle, netr_info);
2341ed6b69aSGordon Ross 			 * Nexenta issue 11960
2351ed6b69aSGordon Ross 			 */
236faa1795aSjb150015 			smb_update_netlogon_seqnum();
237da6c28aaSamw 			netr_info->flags |= NETR_FLG_VALID;
238faa1795aSjb150015 
239faa1795aSjb150015 		}
240da6c28aaSamw 	}
241da6c28aaSamw 
242ce8560eeSMatt Barden errout:
243ce8560eeSMatt Barden 	(void) netr_close(&netr_handle);
244ce8560eeSMatt Barden 
245da6c28aaSamw 	return ((rc) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_SUCCESS);
246da6c28aaSamw }
247da6c28aaSamw 
248da6c28aaSamw /*
249da6c28aaSamw  * netr_open
250da6c28aaSamw  *
2511fcced4cSJordan Brown  * Open an anonymous session to the NETLOGON pipe on a domain controller
2521fcced4cSJordan Brown  * and bind to the NETR RPC interface.
2531fcced4cSJordan Brown  *
2541fcced4cSJordan Brown  * We store the remote server information, which is used to drive Windows
2551fcced4cSJordan Brown  * version specific behavior.
256b3700b07SGordon Ross  *
257b3700b07SGordon Ross  * Returns 0 or NT status
258da6c28aaSamw  */
259b3700b07SGordon Ross DWORD
netr_open(char * server,char * domain,mlsvc_handle_t * netr_handle)260da6c28aaSamw netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle)
261da6c28aaSamw {
262a0aa776eSAlan Wright 	char user[SMB_USERNAME_MAXLEN];
263b3700b07SGordon Ross 	DWORD status;
264da6c28aaSamw 
265a0aa776eSAlan Wright 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
2661fcced4cSJordan Brown 
267b3700b07SGordon Ross 	status = ndr_rpc_bind(netr_handle, server, domain, user, "NETR");
268da6c28aaSamw 
269b3700b07SGordon Ross 	return (status);
270da6c28aaSamw }
271da6c28aaSamw 
272ce8560eeSMatt Barden uint32_t auth_context_id = 1;
273ce8560eeSMatt Barden 
274ce8560eeSMatt Barden DWORD
netr_open_secure(char * server,char * domain,mlsvc_handle_t * netr_handle)275ce8560eeSMatt Barden netr_open_secure(char *server, char *domain, mlsvc_handle_t *netr_handle)
276ce8560eeSMatt Barden {
277ce8560eeSMatt Barden 	char user[SMB_USERNAME_MAXLEN];
278ce8560eeSMatt Barden 	DWORD status;
279ce8560eeSMatt Barden 
280ce8560eeSMatt Barden 	smb_ipc_get_user(user, SMB_USERNAME_MAXLEN);
281ce8560eeSMatt Barden 
282ce8560eeSMatt Barden 	/*
283ce8560eeSMatt Barden 	 * If the server doesn't support SECURE_RPC_FLAG, or we've disabled
284ce8560eeSMatt Barden 	 * secure rpc (netr_global_info.use_secure_rpc), then SECURE_RPC_FLAG
285ce8560eeSMatt Barden 	 * won't be in the set of negotiated flags. Don't use SecureRPC if
286ce8560eeSMatt Barden 	 * that's the case.
287ce8560eeSMatt Barden 	 */
288ce8560eeSMatt Barden 	if ((netr_global_info.nego_flags & NETR_NEGO_SECURE_RPC_FLAG) != 0) {
289ce8560eeSMatt Barden 		netr_ssp_ctx.auth_context_id = auth_context_id++;
290ce8560eeSMatt Barden 		status = ndr_rpc_bind_secure(netr_handle, server, domain, user,
291ce8560eeSMatt Barden 		    "NETR", &netr_ssp_ctx);
292ce8560eeSMatt Barden 	} else {
293ce8560eeSMatt Barden 		status = ndr_rpc_bind(netr_handle, server, domain, user,
294ce8560eeSMatt Barden 		    "NETR");
295ce8560eeSMatt Barden 	}
296ce8560eeSMatt Barden 
297ce8560eeSMatt Barden 	return (status);
298ce8560eeSMatt Barden }
299ce8560eeSMatt Barden 
300da6c28aaSamw /*
301da6c28aaSamw  * netr_close
302da6c28aaSamw  *
303da6c28aaSamw  * Close a NETLOGON pipe and free the RPC context.
304da6c28aaSamw  */
305da6c28aaSamw int
netr_close(mlsvc_handle_t * netr_handle)306da6c28aaSamw netr_close(mlsvc_handle_t *netr_handle)
307da6c28aaSamw {
3088d7e4166Sjose borrego 	ndr_rpc_unbind(netr_handle);
309da6c28aaSamw 	return (0);
310da6c28aaSamw }
311da6c28aaSamw 
312da6c28aaSamw /*
313da6c28aaSamw  * netr_server_req_challenge
314da6c28aaSamw  */
315da6c28aaSamw static int
netr_server_req_challenge(mlsvc_handle_t * netr_handle,netr_info_t * netr_info)316da6c28aaSamw netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
317da6c28aaSamw {
318da6c28aaSamw 	struct netr_ServerReqChallenge arg;
319da6c28aaSamw 	int opnum;
320da6c28aaSamw 
321da6c28aaSamw 	bzero(&arg, sizeof (struct netr_ServerReqChallenge));
322da6c28aaSamw 	opnum = NETR_OPNUM_ServerReqChallenge;
323da6c28aaSamw 
324da6c28aaSamw 	arg.servername = (unsigned char *)netr_info->server;
325da6c28aaSamw 	arg.hostname = (unsigned char *)netr_info->hostname;
326da6c28aaSamw 
327da6c28aaSamw 	(void) memcpy(&arg.client_challenge, &netr_info->client_challenge,
328da6c28aaSamw 	    sizeof (struct netr_credential));
329da6c28aaSamw 
3308d7e4166Sjose borrego 	if (ndr_rpc_call(netr_handle, opnum, &arg) != 0)
3318d7e4166Sjose borrego 		return (-1);
3328d7e4166Sjose borrego 
333da6c28aaSamw 	if (arg.status != 0) {
3348d7e4166Sjose borrego 		ndr_rpc_status(netr_handle, opnum, arg.status);
3358d7e4166Sjose borrego 		ndr_rpc_release(netr_handle);
3368d7e4166Sjose borrego 		return (-1);
337da6c28aaSamw 	}
338da6c28aaSamw 
3398d7e4166Sjose borrego 	(void) memcpy(&netr_info->server_challenge, &arg.server_challenge,
3408d7e4166Sjose borrego 	    sizeof (struct netr_credential));
3418d7e4166Sjose borrego 
3428d7e4166Sjose borrego 	ndr_rpc_release(netr_handle);
3438d7e4166Sjose borrego 	return (0);
344da6c28aaSamw }
345da6c28aaSamw 
3463299f39fSGordon Ross uint32_t netr_server_auth2_flags =
347ce8560eeSMatt Barden     NETR_NEGO_BASE_FLAGS |
348ce8560eeSMatt Barden     NETR_NEGO_STRONGKEY_FLAG |
349ce8560eeSMatt Barden     NETR_NEGO_SECURE_RPC_FLAG;
3503299f39fSGordon Ross 
351da6c28aaSamw /*
352da6c28aaSamw  * netr_server_authenticate2
353da6c28aaSamw  */
354da6c28aaSamw static int
netr_server_authenticate2(mlsvc_handle_t * netr_handle,netr_info_t * netr_info)355da6c28aaSamw netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
356da6c28aaSamw {
357da6c28aaSamw 	struct netr_ServerAuthenticate2 arg;
358b3700b07SGordon Ross 	/* sizeof netr_info->hostname, + 1 for the '$' */
359b3700b07SGordon Ross 	char account_name[(NETBIOS_NAME_SZ * 2) + 1];
360da6c28aaSamw 	int opnum;
361da6c28aaSamw 	int rc;
362*0ccfe583SMatt Barden 	int i;
363da6c28aaSamw 
364da6c28aaSamw 	bzero(&arg, sizeof (struct netr_ServerAuthenticate2));
365da6c28aaSamw 	opnum = NETR_OPNUM_ServerAuthenticate2;
366da6c28aaSamw 
367da6c28aaSamw 	(void) snprintf(account_name, sizeof (account_name), "%s$",
368da6c28aaSamw 	    netr_info->hostname);
369da6c28aaSamw 
3702c1b14e5Sjose borrego 	smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n",
3712c1b14e5Sjose borrego 	    netr_info->server, account_name, netr_info->hostname);
3722c1b14e5Sjose borrego 
373da6c28aaSamw 	arg.servername = (unsigned char *)netr_info->server;
374da6c28aaSamw 	arg.account_name = (unsigned char *)account_name;
375da6c28aaSamw 	arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
376da6c28aaSamw 	arg.hostname = (unsigned char *)netr_info->hostname;
3773299f39fSGordon Ross 	arg.negotiate_flags = netr_server_auth2_flags;
378da6c28aaSamw 
379ce8560eeSMatt Barden 	/*
380ce8560eeSMatt Barden 	 * If we've disabled SecureRPC, remove it from our negotiate_flags
381ce8560eeSMatt Barden 	 * so that the returned flags don't include it. We won't later use
382ce8560eeSMatt Barden 	 * SecureRPC if the returned flags don't include the flag.
383ce8560eeSMatt Barden 	 */
384ce8560eeSMatt Barden 	if (!netr_global_info.use_secure_rpc)
385ce8560eeSMatt Barden 		arg.negotiate_flags &= ~NETR_NEGO_SECURE_RPC_FLAG;
386ce8560eeSMatt Barden 
387ce8560eeSMatt Barden 	if (arg.negotiate_flags & NETR_NEGO_STRONGKEY_FLAG) {
3882c1b14e5Sjose borrego 		if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS)
389da6c28aaSamw 			return (-1);
3902c1b14e5Sjose borrego 	} else {
3912c1b14e5Sjose borrego 		if (netr_gen_skey64(netr_info) != SMBAUTH_SUCCESS)
3922c1b14e5Sjose borrego 			return (-1);
3932c1b14e5Sjose borrego 	}
394da6c28aaSamw 
395ce8560eeSMatt Barden 	/*
396*0ccfe583SMatt Barden 	 * Calculate the 'XorKey' used to derive certain Netlogon SSP keys.
397*0ccfe583SMatt Barden 	 * This is used in [MS-NRPC] 3.3.4.2 "The Netlogon Signature Token".
398*0ccfe583SMatt Barden 	 */
399*0ccfe583SMatt Barden 	for (i = 0; i < netr_info->session_key.len; i++)
400*0ccfe583SMatt Barden 		netr_info->rpc_seal_key.key[i] =
401*0ccfe583SMatt Barden 		    netr_info->session_key.key[i] ^ 0xf0;
402*0ccfe583SMatt Barden 	netr_info->rpc_seal_key.len = netr_info->session_key.len;
403*0ccfe583SMatt Barden 
404*0ccfe583SMatt Barden 	/*
405ce8560eeSMatt Barden 	 * We can't 'fiddle' with anything here to prevent getting bitten by
406ce8560eeSMatt Barden 	 * ClientStoredCredential-based mitigations.
407ce8560eeSMatt Barden 	 *
408ce8560eeSMatt Barden 	 * If we're using SamLogonEx, we won't use authenticators unless
409ce8560eeSMatt Barden 	 * some other NetLogon command is implemented and used.
410ce8560eeSMatt Barden 	 */
4112c1b14e5Sjose borrego 	if (netr_gen_credentials(netr_info->session_key.key,
4122c1b14e5Sjose borrego 	    &netr_info->client_challenge, 0,
413ce8560eeSMatt Barden 	    &netr_info->client_credential, B_FALSE) != SMBAUTH_SUCCESS) {
414da6c28aaSamw 		return (-1);
415da6c28aaSamw 	}
416da6c28aaSamw 
4172c1b14e5Sjose borrego 	if (netr_gen_credentials(netr_info->session_key.key,
4182c1b14e5Sjose borrego 	    &netr_info->server_challenge, 0,
419ce8560eeSMatt Barden 	    &netr_info->server_credential, B_FALSE) != SMBAUTH_SUCCESS) {
420da6c28aaSamw 		return (-1);
421da6c28aaSamw 	}
422da6c28aaSamw 
423da6c28aaSamw 	(void) memcpy(&arg.client_credential, &netr_info->client_credential,
424da6c28aaSamw 	    sizeof (struct netr_credential));
425da6c28aaSamw 
4268d7e4166Sjose borrego 	if (ndr_rpc_call(netr_handle, opnum, &arg) != 0)
4278d7e4166Sjose borrego 		return (-1);
428da6c28aaSamw 
429da6c28aaSamw 	if (arg.status != 0) {
4308d7e4166Sjose borrego 		ndr_rpc_status(netr_handle, opnum, arg.status);
4318d7e4166Sjose borrego 		ndr_rpc_release(netr_handle);
4328d7e4166Sjose borrego 		return (-1);
433da6c28aaSamw 	}
434da6c28aaSamw 
435ce8560eeSMatt Barden 	/* The server returns the intersection of our flags and their flags. */
436ce8560eeSMatt Barden 	netr_info->nego_flags = arg.negotiate_flags;
437ce8560eeSMatt Barden 
4388d7e4166Sjose borrego 	rc = memcmp(&netr_info->server_credential, &arg.server_credential,
4398d7e4166Sjose borrego 	    sizeof (struct netr_credential));
4408d7e4166Sjose borrego 
4418d7e4166Sjose borrego 	ndr_rpc_release(netr_handle);
442da6c28aaSamw 	return (rc);
443da6c28aaSamw }
444da6c28aaSamw 
445da6c28aaSamw /*
4462c1b14e5Sjose borrego  * netr_gen_skey128
447da6c28aaSamw  *
4482c1b14e5Sjose borrego  * Generate a 128-bit session key from the client and server challenges.
4492c1b14e5Sjose borrego  * See "Session-Key Computation" section of MS-NRPC document.
450da6c28aaSamw  */
4513db3f65cSamw int
netr_gen_skey128(netr_info_t * netr_info)4522c1b14e5Sjose borrego netr_gen_skey128(netr_info_t *netr_info)
4533db3f65cSamw {
4543db3f65cSamw 	unsigned char ntlmhash[SMBAUTH_HASH_SZ];
4553db3f65cSamw 	int rc = SMBAUTH_FAILURE;
4563db3f65cSamw 	CK_RV rv;
4573db3f65cSamw 	CK_MECHANISM mechanism;
4583db3f65cSamw 	CK_SESSION_HANDLE hSession;
4593db3f65cSamw 	CK_ULONG diglen = MD_DIGEST_LEN;
4603db3f65cSamw 	unsigned char md5digest[MD_DIGEST_LEN];
4613db3f65cSamw 	unsigned char zerobuf[NETR_SESSKEY_ZEROBUF_SZ];
4623db3f65cSamw 
4633db3f65cSamw 	bzero(ntlmhash, SMBAUTH_HASH_SZ);
4643db3f65cSamw 	/*
4653db3f65cSamw 	 * We should check (netr_info->flags & NETR_FLG_INIT) and use
4663db3f65cSamw 	 * the appropriate password but it isn't working yet.  So we
4673db3f65cSamw 	 * always use the default one for now.
4683db3f65cSamw 	 */
4693db3f65cSamw 	bzero(netr_info->password, sizeof (netr_info->password));
4703db3f65cSamw 	rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD,
4713db3f65cSamw 	    (char *)netr_info->password, sizeof (netr_info->password));
4723db3f65cSamw 
4733db3f65cSamw 	if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') {
4743db3f65cSamw 		return (SMBAUTH_FAILURE);
4753db3f65cSamw 	}
4763db3f65cSamw 
4773db3f65cSamw 	rc = smb_auth_ntlm_hash((char *)netr_info->password, ntlmhash);
478c585f97bSMatt Barden 	if (rc != SMBAUTH_SUCCESS) {
479c585f97bSMatt Barden 		explicit_bzero(&netr_info->password,
480c585f97bSMatt Barden 		    sizeof (netr_info->password));
4813db3f65cSamw 		return (SMBAUTH_FAILURE);
482c585f97bSMatt Barden 	}
4833db3f65cSamw 
4843db3f65cSamw 	bzero(zerobuf, NETR_SESSKEY_ZEROBUF_SZ);
4853db3f65cSamw 
4863db3f65cSamw 	mechanism.mechanism = CKM_MD5;
4873db3f65cSamw 	mechanism.pParameter = 0;
4883db3f65cSamw 	mechanism.ulParameterLen = 0;
4893db3f65cSamw 
4903db3f65cSamw 	rv = SUNW_C_GetMechSession(mechanism.mechanism, &hSession);
491c585f97bSMatt Barden 	if (rv != CKR_OK) {
492c585f97bSMatt Barden 		rc = SMBAUTH_FAILURE;
493c585f97bSMatt Barden 		goto errout;
494c585f97bSMatt Barden 	}
4953db3f65cSamw 
4963db3f65cSamw 	rv = C_DigestInit(hSession, &mechanism);
4973db3f65cSamw 	if (rv != CKR_OK)
4983db3f65cSamw 		goto cleanup;
4993db3f65cSamw 
5003db3f65cSamw 	rv = C_DigestUpdate(hSession, (CK_BYTE_PTR)zerobuf,
5013db3f65cSamw 	    NETR_SESSKEY_ZEROBUF_SZ);
5023db3f65cSamw 	if (rv != CKR_OK)
5033db3f65cSamw 		goto cleanup;
5043db3f65cSamw 
5053db3f65cSamw 	rv = C_DigestUpdate(hSession,
5063db3f65cSamw 	    (CK_BYTE_PTR)netr_info->client_challenge.data, NETR_CRED_DATA_SZ);
5073db3f65cSamw 	if (rv != CKR_OK)
5083db3f65cSamw 		goto cleanup;
5093db3f65cSamw 
5103db3f65cSamw 	rv = C_DigestUpdate(hSession,
5113db3f65cSamw 	    (CK_BYTE_PTR)netr_info->server_challenge.data, NETR_CRED_DATA_SZ);
5123db3f65cSamw 	if (rv != CKR_OK)
5133db3f65cSamw 		goto cleanup;
5143db3f65cSamw 
5153db3f65cSamw 	rv = C_DigestFinal(hSession, (CK_BYTE_PTR)md5digest, &diglen);
5163db3f65cSamw 	if (rv != CKR_OK)
5173db3f65cSamw 		goto cleanup;
5183db3f65cSamw 
5193db3f65cSamw 	rc = smb_auth_hmac_md5(md5digest, diglen, ntlmhash, SMBAUTH_HASH_SZ,
5202c1b14e5Sjose borrego 	    netr_info->session_key.key);
5213db3f65cSamw 
5222c1b14e5Sjose borrego 	netr_info->session_key.len = NETR_SESSKEY128_SZ;
5233db3f65cSamw cleanup:
5243db3f65cSamw 	(void) C_CloseSession(hSession);
525c585f97bSMatt Barden 
526c585f97bSMatt Barden errout:
527c585f97bSMatt Barden 	explicit_bzero(&netr_info->password, sizeof (netr_info->password));
528c585f97bSMatt Barden 	explicit_bzero(ntlmhash, sizeof (ntlmhash));
529c585f97bSMatt Barden 
5303db3f65cSamw 	return (rc);
5313db3f65cSamw 
5323db3f65cSamw }
5332c1b14e5Sjose borrego /*
5342c1b14e5Sjose borrego  * netr_gen_skey64
5352c1b14e5Sjose borrego  *
5362c1b14e5Sjose borrego  * Generate a 64-bit session key from the client and server challenges.
5372c1b14e5Sjose borrego  * See "Session-Key Computation" section of MS-NRPC document.
5382c1b14e5Sjose borrego  *
5392c1b14e5Sjose borrego  * The algorithm is a two stage hash. For the first hash, the input is
5402c1b14e5Sjose borrego  * the combination of the client and server challenges, the key is
5412c1b14e5Sjose borrego  * the first 7 bytes of the password. The initial password is formed
5422c1b14e5Sjose borrego  * using the NT password hash on the local hostname in lower case.
5432c1b14e5Sjose borrego  * The result is stored in a temporary buffer.
5442c1b14e5Sjose borrego  *
5452c1b14e5Sjose borrego  *		input:	challenge
5462c1b14e5Sjose borrego  *		key:	passwd lower 7 bytes
5472c1b14e5Sjose borrego  *		output:	intermediate result
5482c1b14e5Sjose borrego  *
5492c1b14e5Sjose borrego  * For the second hash, the input is the result of the first hash and
5502c1b14e5Sjose borrego  * the key is the last 7 bytes of the password.
5512c1b14e5Sjose borrego  *
5522c1b14e5Sjose borrego  *		input:	result of first hash
5532c1b14e5Sjose borrego  *		key:	passwd upper 7 bytes
5542c1b14e5Sjose borrego  *		output:	session_key
5552c1b14e5Sjose borrego  *
5562c1b14e5Sjose borrego  * The final output should be the session key.
5572c1b14e5Sjose borrego  *
5582c1b14e5Sjose borrego  *		FYI: smb_auth_DES(output, key, input)
5592c1b14e5Sjose borrego  *
5602c1b14e5Sjose borrego  * If any difficulties occur using the cryptographic framework, the
5612c1b14e5Sjose borrego  * function returns SMBAUTH_FAILURE.  Otherwise SMBAUTH_SUCCESS is
5622c1b14e5Sjose borrego  * returned.
5632c1b14e5Sjose borrego  */
564da6c28aaSamw int
netr_gen_skey64(netr_info_t * netr_info)5652c1b14e5Sjose borrego netr_gen_skey64(netr_info_t *netr_info)
566da6c28aaSamw {
567da6c28aaSamw 	unsigned char md4hash[32];
568da6c28aaSamw 	unsigned char buffer[8];
569da6c28aaSamw 	DWORD data[2];
570da6c28aaSamw 	DWORD *client_challenge;
571da6c28aaSamw 	DWORD *server_challenge;
572da6c28aaSamw 	int rc;
57355bf511dSas200622 	DWORD le_data[2];
574da6c28aaSamw 
575da6c28aaSamw 	client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge;
576da6c28aaSamw 	server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge;
577da6c28aaSamw 	bzero(md4hash, 32);
578da6c28aaSamw 
579da6c28aaSamw 	/*
580da6c28aaSamw 	 * We should check (netr_info->flags & NETR_FLG_INIT) and use
581da6c28aaSamw 	 * the appropriate password but it isn't working yet.  So we
582da6c28aaSamw 	 * always use the default one for now.
583da6c28aaSamw 	 */
584dc20a302Sas200622 	bzero(netr_info->password, sizeof (netr_info->password));
585dc20a302Sas200622 	rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD,
586dc20a302Sas200622 	    (char *)netr_info->password, sizeof (netr_info->password));
587da6c28aaSamw 
588dc20a302Sas200622 	if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') {
5893db3f65cSamw 		return (SMBAUTH_FAILURE);
590da6c28aaSamw 	}
591da6c28aaSamw 
592dc20a302Sas200622 	rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash);
593da6c28aaSamw 
594c585f97bSMatt Barden 	if (rc != SMBAUTH_SUCCESS) {
595c585f97bSMatt Barden 		rc = SMBAUTH_FAILURE;
596c585f97bSMatt Barden 		goto out;
597c585f97bSMatt Barden 	}
598da6c28aaSamw 
599da6c28aaSamw 	data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]);
600da6c28aaSamw 	data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]);
60155bf511dSas200622 	LE_OUT32(&le_data[0], data[0]);
60255bf511dSas200622 	LE_OUT32(&le_data[1], data[1]);
6032c1b14e5Sjose borrego 	rc = smb_auth_DES(buffer, 8, md4hash, NETR_DESKEY_LEN,
6042c1b14e5Sjose borrego 	    (unsigned char *)le_data, 8);
605da6c28aaSamw 
606da6c28aaSamw 	if (rc != SMBAUTH_SUCCESS)
607c585f97bSMatt Barden 		goto out;
608da6c28aaSamw 
6092c1b14e5Sjose borrego 	netr_info->session_key.len = NETR_SESSKEY64_SZ;
6102c1b14e5Sjose borrego 	rc = smb_auth_DES(netr_info->session_key.key,
6112c1b14e5Sjose borrego 	    netr_info->session_key.len, &md4hash[9], NETR_DESKEY_LEN, buffer,
6122c1b14e5Sjose borrego 	    8);
6132c1b14e5Sjose borrego 
614c585f97bSMatt Barden out:
615c585f97bSMatt Barden 	explicit_bzero(&netr_info->password, sizeof (netr_info->password));
616c585f97bSMatt Barden 	explicit_bzero(md4hash, sizeof (md4hash));
617c585f97bSMatt Barden 	explicit_bzero(buffer, sizeof (buffer));
618da6c28aaSamw 	return (rc);
619da6c28aaSamw }
620da6c28aaSamw 
621da6c28aaSamw /*
622da6c28aaSamw  * netr_gen_credentials
623da6c28aaSamw  *
624da6c28aaSamw  * Generate a set of credentials from a challenge and a session key.
625da6c28aaSamw  * The algorithm is a two stage hash. For the first hash, the
626da6c28aaSamw  * timestamp is added to the challenge and the result is stored in a
627da6c28aaSamw  * temporary buffer:
628da6c28aaSamw  *
629da6c28aaSamw  *		input:	challenge (including timestamp)
630da6c28aaSamw  *		key:	session_key
631da6c28aaSamw  *		output:	intermediate result
632da6c28aaSamw  *
633da6c28aaSamw  * For the second hash, the input is the result of the first hash and
634da6c28aaSamw  * a strange partial key is used:
635da6c28aaSamw  *
636da6c28aaSamw  *		input:	result of first hash
637da6c28aaSamw  *		key:	funny partial key
638da6c28aaSamw  *		output:	credentiails
639da6c28aaSamw  *
640da6c28aaSamw  * The final output should be an encrypted set of credentials.
641da6c28aaSamw  *
642da6c28aaSamw  *		FYI: smb_auth_DES(output, key, input)
643da6c28aaSamw  *
644da6c28aaSamw  * If any difficulties occur using the cryptographic framework, the
645da6c28aaSamw  * function returns SMBAUTH_FAILURE.  Otherwise SMBAUTH_SUCCESS is
646da6c28aaSamw  * returned.
647da6c28aaSamw  */
648da6c28aaSamw int
netr_gen_credentials(BYTE * session_key,netr_cred_t * challenge,DWORD timestamp,netr_cred_t * out_cred,boolean_t retry)649da6c28aaSamw netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge,
650ce8560eeSMatt Barden     DWORD timestamp, netr_cred_t *out_cred, boolean_t retry)
651da6c28aaSamw {
652da6c28aaSamw 	unsigned char buffer[8];
653da6c28aaSamw 	DWORD data[2];
65455bf511dSas200622 	DWORD le_data[2];
655da6c28aaSamw 	DWORD *p;
656da6c28aaSamw 	int rc;
657da6c28aaSamw 
658da6c28aaSamw 	p = (DWORD *)(uintptr_t)challenge;
65955bf511dSas200622 	data[0] = LE_IN32(&p[0]) + timestamp;
66055bf511dSas200622 	data[1] = LE_IN32(&p[1]);
66155bf511dSas200622 
66255bf511dSas200622 	LE_OUT32(&le_data[0], data[0]);
66355bf511dSas200622 	LE_OUT32(&le_data[1], data[1]);
664da6c28aaSamw 
6653db3f65cSamw 	if (smb_auth_DES(buffer, 8, session_key, NETR_DESKEY_LEN,
66655bf511dSas200622 	    (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS)
667da6c28aaSamw 		return (SMBAUTH_FAILURE);
668da6c28aaSamw 
6693db3f65cSamw 	rc = smb_auth_DES(out_cred->data, 8, &session_key[NETR_DESKEY_LEN],
6703db3f65cSamw 	    NETR_DESKEY_LEN, buffer, 8);
671da6c28aaSamw 
672ce8560eeSMatt Barden 	/*
673ce8560eeSMatt Barden 	 * [MS-NRPC] 3.1.4.6 "Calling Methods Requiring Session-Key
674ce8560eeSMatt Barden 	 * Establishment" Step 6
675ce8560eeSMatt Barden 	 *
676ce8560eeSMatt Barden 	 * Windows DCs will reject authenticators if none of the first
677ce8560eeSMatt Barden 	 * 5 bytes of the ClientStoredCredential are unique.
678ce8560eeSMatt Barden 	 * Keep retrying until we've generated one that satisfies this,
679ce8560eeSMatt Barden 	 * but only if the caller can handle retries.
680ce8560eeSMatt Barden 	 */
681ce8560eeSMatt Barden 	if (retry && !passes_dc_mitigation(out_cred->data))
682ce8560eeSMatt Barden 		return (SMBAUTH_RETRY);
683ce8560eeSMatt Barden 
684da6c28aaSamw 	return (rc);
685da6c28aaSamw }
686da6c28aaSamw 
687da6c28aaSamw /*
688da6c28aaSamw  * netr_server_password_set
689da6c28aaSamw  *
690da6c28aaSamw  * Attempt to change the trust account password for this system.
691da6c28aaSamw  *
692da6c28aaSamw  * Note that this call may legitimately fail if the registry on the
693da6c28aaSamw  * domain controller has been setup to deny attempts to change the
694da6c28aaSamw  * trust account password. In this case we should just continue to
695da6c28aaSamw  * use the original password.
696da6c28aaSamw  *
697da6c28aaSamw  * Possible status values:
698da6c28aaSamw  *	NT_STATUS_ACCESS_DENIED
699da6c28aaSamw  */
700da6c28aaSamw int
netr_server_password_set(mlsvc_handle_t * netr_handle,netr_info_t * netr_info)701da6c28aaSamw netr_server_password_set(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
702da6c28aaSamw {
703da6c28aaSamw 	struct netr_PasswordSet  arg;
704da6c28aaSamw 	int opnum;
705da6c28aaSamw 	BYTE new_password[NETR_OWF_PASSWORD_SZ];
706b89a8333Snatalie li - Sun Microsystems - Irvine United States 	char account_name[NETBIOS_NAME_SZ * 2];
707da6c28aaSamw 
708da6c28aaSamw 	bzero(&arg, sizeof (struct netr_PasswordSet));
709da6c28aaSamw 	opnum = NETR_OPNUM_ServerPasswordSet;
710da6c28aaSamw 
711da6c28aaSamw 	(void) snprintf(account_name, sizeof (account_name), "%s$",
712da6c28aaSamw 	    netr_info->hostname);
713da6c28aaSamw 
714da6c28aaSamw 	arg.servername = (unsigned char *)netr_info->server;
715da6c28aaSamw 	arg.account_name = (unsigned char *)account_name;
7161ed6b69aSGordon Ross 	arg.sec_chan_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
717da6c28aaSamw 	arg.hostname = (unsigned char *)netr_info->hostname;
718da6c28aaSamw 
719da6c28aaSamw 	/*
720da6c28aaSamw 	 * Set up the client side authenticator.
721da6c28aaSamw 	 */
722da6c28aaSamw 	if (netr_setup_authenticator(netr_info, &arg.auth, 0) !=
723da6c28aaSamw 	    SMBAUTH_SUCCESS) {
724da6c28aaSamw 		return (-1);
725da6c28aaSamw 	}
726da6c28aaSamw 
727da6c28aaSamw 	/*
728da6c28aaSamw 	 * Generate a new password from the old password.
729da6c28aaSamw 	 */
7302c1b14e5Sjose borrego 	if (netr_gen_password(netr_info->session_key.key,
731da6c28aaSamw 	    netr_info->password, new_password) == SMBAUTH_FAILURE) {
732da6c28aaSamw 		return (-1);
733da6c28aaSamw 	}
734da6c28aaSamw 
7351ed6b69aSGordon Ross 	(void) memcpy(&arg.owf_password, &new_password,
736da6c28aaSamw 	    NETR_OWF_PASSWORD_SZ);
737da6c28aaSamw 
7388d7e4166Sjose borrego 	if (ndr_rpc_call(netr_handle, opnum, &arg) != 0)
7398d7e4166Sjose borrego 		return (-1);
7408d7e4166Sjose borrego 
7418d7e4166Sjose borrego 	if (arg.status != 0) {
7428d7e4166Sjose borrego 		ndr_rpc_status(netr_handle, opnum, arg.status);
7438d7e4166Sjose borrego 		ndr_rpc_release(netr_handle);
744da6c28aaSamw 		return (-1);
745da6c28aaSamw 	}
746da6c28aaSamw 
747da6c28aaSamw 	/*
748da6c28aaSamw 	 * Check the returned credentials.  The server returns the new
749da6c28aaSamw 	 * client credential rather than the new server credentiali,
750da6c28aaSamw 	 * as documented elsewhere.
751da6c28aaSamw 	 *
752da6c28aaSamw 	 * Generate the new seed for the credential chain.  Increment
753da6c28aaSamw 	 * the timestamp and add it to the client challenge.  Then we
754da6c28aaSamw 	 * need to copy the challenge to the credential field in
755da6c28aaSamw 	 * preparation for the next cycle.
756da6c28aaSamw 	 */
757da6c28aaSamw 	if (netr_validate_chain(netr_info, &arg.auth) == 0) {
758da6c28aaSamw 		/*
759da6c28aaSamw 		 * Save the new password.
760da6c28aaSamw 		 */
761da6c28aaSamw 		(void) memcpy(netr_info->password, new_password,
762da6c28aaSamw 		    NETR_OWF_PASSWORD_SZ);
763da6c28aaSamw 	}
764da6c28aaSamw 
7658d7e4166Sjose borrego 	ndr_rpc_release(netr_handle);
766da6c28aaSamw 	return (0);
767da6c28aaSamw }
768da6c28aaSamw 
769da6c28aaSamw /*
770da6c28aaSamw  * netr_gen_password
771da6c28aaSamw  *
772da6c28aaSamw  * Generate a new pasword from the old password  and the session key.
773da6c28aaSamw  * The algorithm is a two stage hash. The session key is used in the
774da6c28aaSamw  * first hash but only part of the session key is used in the second
775da6c28aaSamw  * hash.
776da6c28aaSamw  *
777da6c28aaSamw  * If any difficulties occur using the cryptographic framework, the
778da6c28aaSamw  * function returns SMBAUTH_FAILURE.  Otherwise SMBAUTH_SUCCESS is
779da6c28aaSamw  * returned.
780da6c28aaSamw  */
781da6c28aaSamw static int
netr_gen_password(BYTE * session_key,BYTE * old_password,BYTE * new_password)782da6c28aaSamw netr_gen_password(BYTE *session_key, BYTE *old_password, BYTE *new_password)
783da6c28aaSamw {
784da6c28aaSamw 	int rv;
785da6c28aaSamw 
7863db3f65cSamw 	rv = smb_auth_DES(new_password, 8, session_key, NETR_DESKEY_LEN,
7873db3f65cSamw 	    old_password, 8);
788da6c28aaSamw 	if (rv != SMBAUTH_SUCCESS)
789da6c28aaSamw 		return (rv);
790da6c28aaSamw 
7913db3f65cSamw 	rv = smb_auth_DES(&new_password[8], 8, &session_key[NETR_DESKEY_LEN],
7923db3f65cSamw 	    NETR_DESKEY_LEN, &old_password[8], 8);
793da6c28aaSamw 	return (rv);
794da6c28aaSamw }
7951ed6b69aSGordon Ross 
7961ed6b69aSGordon Ross /*
7971ed6b69aSGordon Ross  * Todo: need netr_server_password_set2()
7981ed6b69aSGordon Ross  * used by "unsecure join". (NX 11960)
7991ed6b69aSGordon Ross  */
800