xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c (revision 6432:98715880dd9e)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
225772Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
275331Samw 
285331Samw /*
295331Samw  * NETR challenge/response client functions.
305331Samw  *
315331Samw  * NT_STATUS_INVALID_PARAMETER
325331Samw  * NT_STATUS_NO_TRUST_SAM_ACCOUNT
335331Samw  * NT_STATUS_ACCESS_DENIED
345331Samw  */
355331Samw 
365331Samw #include <stdio.h>
375331Samw #include <stdlib.h>
385331Samw #include <strings.h>
395331Samw #include <unistd.h>
405331Samw #include <ctype.h>
415331Samw 
425331Samw #include <smbsrv/libsmb.h>
435521Sas200622 #include <smbsrv/libsmbrdr.h>
44*6432Sas200622 #include <smbsrv/libsmbns.h>
455331Samw #include <smbsrv/mlsvc_util.h>
465331Samw #include <smbsrv/ndl/netlogon.ndl>
475331Samw #include <smbsrv/ntstatus.h>
485331Samw #include <smbsrv/smbinfo.h>
495331Samw #include <smbsrv/mlsvc.h>
505331Samw #include <smbsrv/netrauth.h>
515331Samw 
525331Samw int netr_setup_authenticator(netr_info_t *, struct netr_authenticator *,
535331Samw     struct netr_authenticator *);
545331Samw DWORD netr_validate_chain(netr_info_t *, struct netr_authenticator *);
555331Samw 
565331Samw static int netr_server_req_challenge(mlsvc_handle_t *, netr_info_t *);
575331Samw static int netr_server_authenticate2(mlsvc_handle_t *, netr_info_t *);
585331Samw static int netr_gen_password(BYTE *, BYTE *, BYTE *);
595331Samw 
605331Samw /*
615331Samw  * Shared with netr_logon.c
625331Samw  */
635331Samw netr_info_t netr_global_info;
645331Samw 
655331Samw /*
665331Samw  * netlogon_auth
675331Samw  *
685331Samw  * This is the core of the NETLOGON authentication protocol.
695331Samw  * Do the challenge response authentication.
705331Samw  *
715331Samw  * Prior to calling this function, an anonymous session to the NETLOGON
725331Samw  * pipe on a domain controller(server) should have already been opened.
736139Sjb150015  *
746139Sjb150015  * Upon a successful NETLOGON credential chain establishment, the
756139Sjb150015  * netlogon sequence number will be set to match the kpasswd sequence
766139Sjb150015  * number.
776139Sjb150015  *
785331Samw  */
795331Samw DWORD
805331Samw netlogon_auth(char *server, mlsvc_handle_t *netr_handle, DWORD flags)
815331Samw {
825331Samw 	netr_info_t *netr_info;
835331Samw 	int rc;
845521Sas200622 	DWORD leout_rc[2];
855331Samw 
865331Samw 	netr_info = &netr_global_info;
875331Samw 	bzero(netr_info, sizeof (netr_info_t));
885331Samw 
895331Samw 	netr_info->flags |= flags;
905331Samw 
915331Samw 	rc = smb_getnetbiosname(netr_info->hostname, MLSVC_DOMAIN_NAME_MAX);
925331Samw 	if (rc != 0)
935331Samw 		return (NT_STATUS_UNSUCCESSFUL);
945331Samw 
955331Samw 	(void) snprintf(netr_info->server, sizeof (netr_info->server),
965331Samw 	    "\\\\%s", server);
975331Samw 
985521Sas200622 	LE_OUT32(&leout_rc[0], random());
995521Sas200622 	LE_OUT32(&leout_rc[1], random());
1005521Sas200622 	(void) memcpy(&netr_info->client_challenge, leout_rc,
1015331Samw 	    sizeof (struct netr_credential));
1025331Samw 
1035331Samw 	if ((rc = netr_server_req_challenge(netr_handle, netr_info)) == 0) {
1045331Samw 		rc = netr_server_authenticate2(netr_handle, netr_info);
1056139Sjb150015 		if (rc == 0) {
1066139Sjb150015 			smb_update_netlogon_seqnum();
1075331Samw 			netr_info->flags |= NETR_FLG_VALID;
1086139Sjb150015 
1096139Sjb150015 		}
1105331Samw 	}
1115331Samw 
112*6432Sas200622 	/*
113*6432Sas200622 	 * The NETLOGON credential chain establishment has unset
114*6432Sas200622 	 * both ServerPrincipalName and dNSHostName attributes of the
115*6432Sas200622 	 * workstation trust account. Those attributes will be updated
116*6432Sas200622 	 * here to avoid any Kerberos authentication errors from happening.
117*6432Sas200622 	 *
118*6432Sas200622 	 * Later, when NT4 domain controller is supported, we need to
119*6432Sas200622 	 * find a way to disable the following code.
120*6432Sas200622 	 */
121*6432Sas200622 	if (ads_update_attrs() == -1)
122*6432Sas200622 		syslog(LOG_DEBUG, "netlogon_auth: ServerPrincipalName"
123*6432Sas200622 		    " and dNSHostName attributes might have been unset.");
124*6432Sas200622 
1255331Samw 	return ((rc) ? NT_STATUS_UNSUCCESSFUL : NT_STATUS_SUCCESS);
1265331Samw }
1275331Samw 
1285331Samw /*
1295331Samw  * netr_open
1305331Samw  *
1315331Samw  * Open an anonymous session to the NETLOGON pipe on a domain
1325331Samw  * controller and bind to the NETR RPC interface. We store the
1335331Samw  * remote server's native OS type - we may need it due to
1345331Samw  * differences between versions of Windows.
1355331Samw  */
1365331Samw int
1375331Samw netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle)
1385331Samw {
1395331Samw 	int fid;
1405331Samw 	int remote_os = 0;
1415331Samw 	int remote_lm = 0;
1425331Samw 	int server_pdc;
1435521Sas200622 	char *user = smbrdr_ipc_get_user();
1445331Samw 
1455521Sas200622 	if (mlsvc_logon(server, domain, user) != 0)
1465331Samw 		return (-1);
1475331Samw 
1485521Sas200622 	fid = mlsvc_open_pipe(server, domain, user, "\\NETLOGON");
1495331Samw 	if (fid < 0)
1505331Samw 		return (-1);
1515331Samw 
1525331Samw 	if (mlsvc_rpc_bind(netr_handle, fid, "NETR") < 0) {
1535331Samw 		(void) mlsvc_close_pipe(fid);
1545331Samw 		return (-1);
1555331Samw 	}
1565331Samw 
1575331Samw 	(void) mlsvc_session_native_values(fid, &remote_os, &remote_lm,
1585331Samw 	    &server_pdc);
1595331Samw 	netr_handle->context->server_os = remote_os;
1605331Samw 	netr_handle->context->server_pdc = server_pdc;
1615331Samw 	return (0);
1625331Samw }
1635331Samw 
1645331Samw /*
1655331Samw  * netr_close
1665331Samw  *
1675331Samw  * Close a NETLOGON pipe and free the RPC context.
1685331Samw  */
1695331Samw int
1705331Samw netr_close(mlsvc_handle_t *netr_handle)
1715331Samw {
1725331Samw 	(void) mlsvc_close_pipe(netr_handle->context->fid);
1735331Samw 	free(netr_handle->context);
1745331Samw 	return (0);
1755331Samw }
1765331Samw 
1775331Samw /*
1785331Samw  * netr_server_req_challenge
1795331Samw  */
1805331Samw static int
1815331Samw netr_server_req_challenge(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
1825331Samw {
1835331Samw 	struct netr_ServerReqChallenge arg;
1845331Samw 	mlrpc_heapref_t heap;
1855331Samw 	int opnum;
1865331Samw 	int rc;
1875331Samw 
1885331Samw 	bzero(&arg, sizeof (struct netr_ServerReqChallenge));
1895331Samw 	opnum = NETR_OPNUM_ServerReqChallenge;
1905331Samw 
1915331Samw 	arg.servername = (unsigned char *)netr_info->server;
1925331Samw 	arg.hostname = (unsigned char *)netr_info->hostname;
1935331Samw 
1945331Samw 	(void) memcpy(&arg.client_challenge, &netr_info->client_challenge,
1955331Samw 	    sizeof (struct netr_credential));
1965331Samw 
1975331Samw 	(void) mlsvc_rpc_init(&heap);
1985331Samw 	rc = mlsvc_rpc_call(netr_handle->context, opnum, &arg, &heap);
1995331Samw 	if (rc == 0) {
2005331Samw 		if (arg.status != 0) {
2015331Samw 			mlsvc_rpc_report_status(opnum, arg.status);
2025331Samw 			rc = -1;
2035331Samw 		} else {
2045331Samw 			(void) memcpy(&netr_info->server_challenge,
2055331Samw 			    &arg.server_challenge,
2065331Samw 			    sizeof (struct netr_credential));
2075331Samw 		}
2085331Samw 	}
2095331Samw 
2105331Samw 	mlsvc_rpc_free(netr_handle->context, &heap);
2115331Samw 	return (rc);
2125331Samw }
2135331Samw 
2145331Samw /*
2155331Samw  * netr_server_authenticate2
2165331Samw  */
2175331Samw static int
2185331Samw netr_server_authenticate2(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
2195331Samw {
2205331Samw 	struct netr_ServerAuthenticate2 arg;
2215331Samw 	mlrpc_heapref_t heap;
2225331Samw 	int opnum;
2235331Samw 	int rc;
2245331Samw 	char account_name[MLSVC_DOMAIN_NAME_MAX * 2];
2255331Samw 
2265331Samw 	bzero(&arg, sizeof (struct netr_ServerAuthenticate2));
2275331Samw 	opnum = NETR_OPNUM_ServerAuthenticate2;
2285331Samw 
2295331Samw 	(void) snprintf(account_name, sizeof (account_name), "%s$",
2305331Samw 	    netr_info->hostname);
2315331Samw 
2325331Samw 	arg.servername = (unsigned char *)netr_info->server;
2335331Samw 	arg.account_name = (unsigned char *)account_name;
2345331Samw 	arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
2355331Samw 	arg.hostname = (unsigned char *)netr_info->hostname;
2365331Samw 	arg.negotiate_flags = NETR_NEGOTIATE_FLAGS;
2375331Samw 
2385331Samw 	smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n",
2395331Samw 	    netr_info->server, account_name, netr_info->hostname);
2405331Samw 
2415331Samw 	if (netr_gen_session_key(netr_info) != SMBAUTH_SUCCESS)
2425331Samw 		return (-1);
2435331Samw 
2445331Samw 	if (netr_gen_credentials(netr_info->session_key,
2455331Samw 	    &netr_info->client_challenge,
2465331Samw 	    0,
2475331Samw 	    &netr_info->client_credential) != SMBAUTH_SUCCESS) {
2485331Samw 		return (-1);
2495331Samw 	}
2505331Samw 
2515331Samw 	if (netr_gen_credentials(netr_info->session_key,
2525331Samw 	    &netr_info->server_challenge,
2535331Samw 	    0,
2545331Samw 	    &netr_info->server_credential) != SMBAUTH_SUCCESS) {
2555331Samw 		return (-1);
2565331Samw 	}
2575331Samw 
2585331Samw 	(void) memcpy(&arg.client_credential, &netr_info->client_credential,
2595331Samw 	    sizeof (struct netr_credential));
2605331Samw 
2615331Samw 	(void) mlsvc_rpc_init(&heap);
2625331Samw 
2635331Samw 	rc = mlsvc_rpc_call(netr_handle->context, opnum, &arg, &heap);
2645331Samw 	if (rc == 0) {
2655331Samw 		if (arg.status != 0) {
2665331Samw 			mlsvc_rpc_report_status(opnum, arg.status);
2675331Samw 			rc = -1;
2685331Samw 		} else {
2695331Samw 			rc = memcmp(&netr_info->server_credential,
2705331Samw 			    &arg.server_credential,
2715331Samw 			    sizeof (struct netr_credential));
2725331Samw 		}
2735331Samw 	}
2745331Samw 
2755331Samw 	mlsvc_rpc_free(netr_handle->context, &heap);
2765331Samw 	return (rc);
2775331Samw }
2785331Samw 
2795331Samw /*
2805331Samw  * netr_gen_session_key
2815331Samw  *
2825331Samw  * Generate a session key from the client and server challenges. The
2835331Samw  * algorithm is a two stage hash. For the first hash, the input is
2845331Samw  * the combination of the client and server challenges, the key is
2855331Samw  * the first 8 bytes of the password. The initial password is formed
2865331Samw  * using the NT password hash on the local hostname in lower case.
2875331Samw  * The result is stored in a temporary buffer.
2885331Samw  *
2895331Samw  *		input:	challenge
2905331Samw  *		key:	passwd lower 8 bytes
2915331Samw  *		output:	intermediate result
2925331Samw  *
2935331Samw  * For the second hash, the input is the result of the first hash and
2945331Samw  * the key is the last 8 bytes of the password.
2955331Samw  *
2965331Samw  *		input:	result of first hash
2975331Samw  *		key:	passwd upper 8 bytes
2985331Samw  *		output:	session_key
2995331Samw  *
3005331Samw  * The final output should be the session key.
3015331Samw  *
3025331Samw  *		FYI: smb_auth_DES(output, key, input)
3035331Samw  *
3045331Samw  * If any difficulties occur using the cryptographic framework, the
3055331Samw  * function returns SMBAUTH_FAILURE.  Otherwise SMBAUTH_SUCCESS is
3065331Samw  * returned.
3075331Samw  */
3085331Samw int
3095331Samw netr_gen_session_key(netr_info_t *netr_info)
3105331Samw {
3115331Samw 	unsigned char md4hash[32];
3125331Samw 	unsigned char buffer[8];
3135331Samw 	DWORD data[2];
3145331Samw 	DWORD *client_challenge;
3155331Samw 	DWORD *server_challenge;
3165331Samw 	int rc;
3175521Sas200622 	DWORD le_data[2];
3185331Samw 
3195331Samw 	client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge;
3205331Samw 	server_challenge = (DWORD *)(uintptr_t)&netr_info->server_challenge;
3215331Samw 	bzero(md4hash, 32);
3225331Samw 
3235331Samw 	/*
3245331Samw 	 * We should check (netr_info->flags & NETR_FLG_INIT) and use
3255331Samw 	 * the appropriate password but it isn't working yet.  So we
3265331Samw 	 * always use the default one for now.
3275331Samw 	 */
3285772Sas200622 	bzero(netr_info->password, sizeof (netr_info->password));
3295772Sas200622 	rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD,
3305772Sas200622 	    (char *)netr_info->password, sizeof (netr_info->password));
3315331Samw 
3325772Sas200622 	if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') {
3335331Samw 		return (-1);
3345331Samw 	}
3355331Samw 
3365772Sas200622 	rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash);
3375331Samw 
3385331Samw 	if (rc != SMBAUTH_SUCCESS)
3395331Samw 		return (SMBAUTH_FAILURE);
3405331Samw 
3415331Samw 	data[0] = LE_IN32(&client_challenge[0]) + LE_IN32(&server_challenge[0]);
3425331Samw 	data[1] = LE_IN32(&client_challenge[1]) + LE_IN32(&server_challenge[1]);
3435521Sas200622 	LE_OUT32(&le_data[0], data[0]);
3445521Sas200622 	LE_OUT32(&le_data[1], data[1]);
3455331Samw 
3465521Sas200622 	rc = smb_auth_DES(buffer, 8, md4hash, 8, (unsigned char *)le_data, 8);
3475331Samw 	if (rc != SMBAUTH_SUCCESS)
3485331Samw 		return (rc);
3495331Samw 
3505331Samw 	rc = smb_auth_DES(netr_info->session_key, 8, &md4hash[9], 8, buffer, 8);
3515331Samw 	return (rc);
3525331Samw }
3535331Samw 
3545331Samw /*
3555331Samw  * netr_gen_credentials
3565331Samw  *
3575331Samw  * Generate a set of credentials from a challenge and a session key.
3585331Samw  * The algorithm is a two stage hash. For the first hash, the
3595331Samw  * timestamp is added to the challenge and the result is stored in a
3605331Samw  * temporary buffer:
3615331Samw  *
3625331Samw  *		input:	challenge (including timestamp)
3635331Samw  *		key:	session_key
3645331Samw  *		output:	intermediate result
3655331Samw  *
3665331Samw  * For the second hash, the input is the result of the first hash and
3675331Samw  * a strange partial key is used:
3685331Samw  *
3695331Samw  *		input:	result of first hash
3705331Samw  *		key:	funny partial key
3715331Samw  *		output:	credentiails
3725331Samw  *
3735331Samw  * The final output should be an encrypted set of credentials.
3745331Samw  *
3755331Samw  *		FYI: smb_auth_DES(output, key, input)
3765331Samw  *
3775331Samw  * If any difficulties occur using the cryptographic framework, the
3785331Samw  * function returns SMBAUTH_FAILURE.  Otherwise SMBAUTH_SUCCESS is
3795331Samw  * returned.
3805331Samw  */
3815331Samw int
3825331Samw netr_gen_credentials(BYTE *session_key, netr_cred_t *challenge,
3835331Samw     DWORD timestamp, netr_cred_t *out_cred)
3845331Samw {
3855331Samw 	unsigned char buffer[8];
3865331Samw 	unsigned char partial_key[8];
3875331Samw 	DWORD data[2];
3885521Sas200622 	DWORD le_data[2];
3895331Samw 	DWORD *p;
3905331Samw 	int rc;
3915331Samw 
3925331Samw 	p = (DWORD *)(uintptr_t)challenge;
3935521Sas200622 	data[0] = LE_IN32(&p[0]) + timestamp;
3945521Sas200622 	data[1] = LE_IN32(&p[1]);
3955521Sas200622 
3965521Sas200622 	LE_OUT32(&le_data[0], data[0]);
3975521Sas200622 	LE_OUT32(&le_data[1], data[1]);
3985331Samw 
3995331Samw 	if (smb_auth_DES(buffer, 8, session_key, 8,
4005521Sas200622 	    (unsigned char *)le_data, 8) != SMBAUTH_SUCCESS)
4015331Samw 		return (SMBAUTH_FAILURE);
4025331Samw 
4035331Samw 	bzero(partial_key, 8);
4045331Samw 	partial_key[0] = session_key[7];
4055331Samw 
4065331Samw 	rc = smb_auth_DES((unsigned char *)out_cred, 8, partial_key, 8,
4075331Samw 	    buffer, 8);
4085331Samw 	return (rc);
4095331Samw }
4105331Samw 
4115331Samw /*
4125331Samw  * netr_server_password_set
4135331Samw  *
4145331Samw  * Attempt to change the trust account password for this system.
4155331Samw  *
4165331Samw  * Note that this call may legitimately fail if the registry on the
4175331Samw  * domain controller has been setup to deny attempts to change the
4185331Samw  * trust account password. In this case we should just continue to
4195331Samw  * use the original password.
4205331Samw  *
4215331Samw  * Possible status values:
4225331Samw  *	NT_STATUS_ACCESS_DENIED
4235331Samw  */
4245331Samw int
4255331Samw netr_server_password_set(mlsvc_handle_t *netr_handle, netr_info_t *netr_info)
4265331Samw {
4275331Samw 	struct netr_PasswordSet  arg;
4285331Samw 	mlrpc_heapref_t heap;
4295331Samw 	int opnum;
4305331Samw 	int rc;
4315331Samw 	BYTE new_password[NETR_OWF_PASSWORD_SZ];
4325331Samw 	char account_name[MLSVC_DOMAIN_NAME_MAX * 2];
4335331Samw 
4345331Samw 	bzero(&arg, sizeof (struct netr_PasswordSet));
4355331Samw 	opnum = NETR_OPNUM_ServerPasswordSet;
4365331Samw 
4375331Samw 	(void) snprintf(account_name, sizeof (account_name), "%s$",
4385331Samw 	    netr_info->hostname);
4395331Samw 
4405331Samw 	arg.servername = (unsigned char *)netr_info->server;
4415331Samw 	arg.account_name = (unsigned char *)account_name;
4425331Samw 	arg.account_type = NETR_WKSTA_TRUST_ACCOUNT_TYPE;
4435331Samw 	arg.hostname = (unsigned char *)netr_info->hostname;
4445331Samw 
4455331Samw 	/*
4465331Samw 	 * Set up the client side authenticator.
4475331Samw 	 */
4485331Samw 	if (netr_setup_authenticator(netr_info, &arg.auth, 0) !=
4495331Samw 	    SMBAUTH_SUCCESS) {
4505331Samw 		return (-1);
4515331Samw 	}
4525331Samw 
4535331Samw 	/*
4545331Samw 	 * Generate a new password from the old password.
4555331Samw 	 */
4565331Samw 	if (netr_gen_password(netr_info->session_key,
4575331Samw 	    netr_info->password, new_password) == SMBAUTH_FAILURE) {
4585331Samw 		return (-1);
4595331Samw 	}
4605331Samw 
4615331Samw 	(void) memcpy(&arg.uas_new_password, &new_password,
4625331Samw 	    NETR_OWF_PASSWORD_SZ);
4635331Samw 
4645331Samw 	(void) mlsvc_rpc_init(&heap);
4655331Samw 	rc = mlsvc_rpc_call(netr_handle->context, opnum, &arg, &heap);
4665331Samw 	if ((rc != 0) || (arg.status != 0)) {
4675331Samw 		mlsvc_rpc_report_status(opnum, arg.status);
4685331Samw 		mlsvc_rpc_free(netr_handle->context, &heap);
4695331Samw 		return (-1);
4705331Samw 	}
4715331Samw 
4725331Samw 	/*
4735331Samw 	 * Check the returned credentials.  The server returns the new
4745331Samw 	 * client credential rather than the new server credentiali,
4755331Samw 	 * as documented elsewhere.
4765331Samw 	 *
4775331Samw 	 * Generate the new seed for the credential chain.  Increment
4785331Samw 	 * the timestamp and add it to the client challenge.  Then we
4795331Samw 	 * need to copy the challenge to the credential field in
4805331Samw 	 * preparation for the next cycle.
4815331Samw 	 */
4825331Samw 	if (netr_validate_chain(netr_info, &arg.auth) == 0) {
4835331Samw 		/*
4845331Samw 		 * Save the new password.
4855331Samw 		 */
4865331Samw 		(void) memcpy(netr_info->password, new_password,
4875331Samw 		    NETR_OWF_PASSWORD_SZ);
4885331Samw 	}
4895331Samw 
4905331Samw 	mlsvc_rpc_free(netr_handle->context, &heap);
4915331Samw 	return (0);
4925331Samw }
4935331Samw 
4945331Samw /*
4955331Samw  * netr_gen_password
4965331Samw  *
4975331Samw  * Generate a new pasword from the old password  and the session key.
4985331Samw  * The algorithm is a two stage hash. The session key is used in the
4995331Samw  * first hash but only part of the session key is used in the second
5005331Samw  * hash.
5015331Samw  *
5025331Samw  * If any difficulties occur using the cryptographic framework, the
5035331Samw  * function returns SMBAUTH_FAILURE.  Otherwise SMBAUTH_SUCCESS is
5045331Samw  * returned.
5055331Samw  */
5065331Samw static int
5075331Samw netr_gen_password(BYTE *session_key, BYTE *old_password, BYTE *new_password)
5085331Samw {
5095331Samw 	unsigned char partial_key[8];
5105331Samw 	int rv;
5115331Samw 
5125331Samw 	rv = smb_auth_DES(new_password, 8, session_key, 8, old_password, 8);
5135331Samw 	if (rv != SMBAUTH_SUCCESS)
5145331Samw 		return (rv);
5155331Samw 
5165331Samw 	bzero(partial_key, 8);
5175331Samw 	partial_key[0] = session_key[7];
5185331Samw 
5195331Samw 	rv = smb_auth_DES(&new_password[8], 8, partial_key, 8,
5205331Samw 	    &old_password[8], 8);
5215331Samw 	return (rv);
5225331Samw }
523