netr_auth.c revision 2c1b14e51525da2c09064641416fc4aed457c72f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
*
* NT_STATUS_INVALID_PARAMETER
* NT_STATUS_NO_TRUST_SAM_ACCOUNT
* NT_STATUS_ACCESS_DENIED
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <ctype.h>
#include <security/cryptoki.h>
#include <smbsrv/libsmbrdr.h>
#include <smbsrv/libsmbns.h>
#include <smbsrv/mlsvc_util.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/netrauth.h>
#define NETR_SESSKEY_ZEROBUF_SZ 4
/* The DES algorithm uses a 56-bit encryption key. */
#define NETR_DESKEY_LEN 7
struct netr_authenticator *);
/*
* Shared with netr_logon.c
*/
/*
* netlogon_auth
*
* This is the core of the NETLOGON authentication protocol.
* Do the challenge response authentication.
*
* Prior to calling this function, an anonymous session to the NETLOGON
* pipe on a domain controller(server) should have already been opened.
*
* Upon a successful NETLOGON credential chain establishment, the
* netlogon sequence number will be set to match the kpasswd sequence
* number.
*
*/
{
int rc;
if (rc != 0)
return (NT_STATUS_UNSUCCESSFUL);
"\\\\%s", server);
sizeof (struct netr_credential));
if (rc == 0) {
}
}
/*
* The NETLOGON credential chain establishment has unset
* both ServerPrincipalName and dNSHostName attributes of the
* workstation trust account. Those attributes will be updated
* here to avoid any Kerberos authentication errors from happening.
*
* Later, when NT4 domain controller is supported, we need to
* find a way to disable the following code.
*/
if (smb_ads_update_attrs() == -1)
" and dNSHostName attributes might have been unset.");
}
/*
* netr_open
*
* Open an anonymous session to the NETLOGON pipe on a domain
* controller and bind to the NETR RPC interface. We store the
* remote server's native OS type - we may need it due to
* differences between versions of Windows.
*/
int
{
int fid;
int remote_os = 0;
int remote_lm = 0;
int server_pdc;
char *user = smbrdr_ipc_get_user();
return (-1);
if (fid < 0)
return (-1);
(void) mlsvc_close_pipe(fid);
return (-1);
}
&server_pdc);
return (0);
}
/*
* netr_close
*
* Close a NETLOGON pipe and free the RPC context.
*/
int
{
return (0);
}
/*
* netr_server_req_challenge
*/
static int
{
struct netr_ServerReqChallenge arg;
int opnum;
int rc;
sizeof (struct netr_credential));
(void) mlsvc_rpc_init(&heap);
if (rc == 0) {
rc = -1;
} else {
sizeof (struct netr_credential));
}
}
return (rc);
}
/*
* netr_server_authenticate2
*/
static int
{
struct netr_ServerAuthenticate2 arg;
int opnum;
int rc;
smb_tracef("server=[%s] account_name=[%s] hostname=[%s]\n",
return (-1);
} else {
return (-1);
}
&netr_info->client_challenge, 0,
return (-1);
}
&netr_info->server_challenge, 0,
return (-1);
}
sizeof (struct netr_credential));
(void) mlsvc_rpc_init(&heap);
if (rc == 0) {
rc = -1;
} else {
sizeof (struct netr_credential));
}
}
return (rc);
}
/*
* netr_gen_skey128
*
* Generate a 128-bit session key from the client and server challenges.
* See "Session-Key Computation" section of MS-NRPC document.
*/
int
{
unsigned char ntlmhash[SMBAUTH_HASH_SZ];
int rc = SMBAUTH_FAILURE;
unsigned char md5digest[MD_DIGEST_LEN];
unsigned char zerobuf[NETR_SESSKEY_ZEROBUF_SZ];
/*
* We should check (netr_info->flags & NETR_FLG_INIT) and use
* the appropriate password but it isn't working yet. So we
* always use the default one for now.
*/
return (SMBAUTH_FAILURE);
}
if (rc != SMBAUTH_SUCCESS)
return (SMBAUTH_FAILURE);
mechanism.pParameter = 0;
mechanism.ulParameterLen = 0;
return (SMBAUTH_FAILURE);
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
(void) C_CloseSession(hSession);
return (rc);
}
/*
* netr_gen_skey64
*
* Generate a 64-bit session key from the client and server challenges.
* See "Session-Key Computation" section of MS-NRPC document.
*
* The algorithm is a two stage hash. For the first hash, the input is
* the combination of the client and server challenges, the key is
* the first 7 bytes of the password. The initial password is formed
* using the NT password hash on the local hostname in lower case.
* The result is stored in a temporary buffer.
*
* input: challenge
* key: passwd lower 7 bytes
* output: intermediate result
*
* For the second hash, the input is the result of the first hash and
* the key is the last 7 bytes of the password.
*
* input: result of first hash
* key: passwd upper 7 bytes
* output: session_key
*
* The final output should be the session key.
*
* FYI: smb_auth_DES(output, key, input)
*
* If any difficulties occur using the cryptographic framework, the
* function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is
* returned.
*/
int
{
unsigned char md4hash[32];
unsigned char buffer[8];
int rc;
/*
* We should check (netr_info->flags & NETR_FLG_INIT) and use
* the appropriate password but it isn't working yet. So we
* always use the default one for now.
*/
return (SMBAUTH_FAILURE);
}
if (rc != SMBAUTH_SUCCESS)
return (SMBAUTH_FAILURE);
(unsigned char *)le_data, 8);
if (rc != SMBAUTH_SUCCESS)
return (rc);
8);
return (rc);
}
/*
* netr_gen_credentials
*
* Generate a set of credentials from a challenge and a session key.
* The algorithm is a two stage hash. For the first hash, the
* timestamp is added to the challenge and the result is stored in a
* temporary buffer:
*
* input: challenge (including timestamp)
* key: session_key
* output: intermediate result
*
* For the second hash, the input is the result of the first hash and
* a strange partial key is used:
*
* input: result of first hash
* key: funny partial key
* output: credentiails
*
* The final output should be an encrypted set of credentials.
*
* FYI: smb_auth_DES(output, key, input)
*
* If any difficulties occur using the cryptographic framework, the
* function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is
* returned.
*/
int
{
unsigned char buffer[8];
DWORD *p;
int rc;
return (SMBAUTH_FAILURE);
return (rc);
}
/*
* netr_server_password_set
*
* Attempt to change the trust account password for this system.
*
* Note that this call may legitimately fail if the registry on the
* domain controller has been setup to deny attempts to change the
* trust account password. In this case we should just continue to
* use the original password.
*
* Possible status values:
* NT_STATUS_ACCESS_DENIED
*/
int
{
struct netr_PasswordSet arg;
int opnum;
int rc;
/*
* Set up the client side authenticator.
*/
return (-1);
}
/*
* Generate a new password from the old password.
*/
return (-1);
}
(void) mlsvc_rpc_init(&heap);
return (-1);
}
/*
* Check the returned credentials. The server returns the new
* client credential rather than the new server credentiali,
* as documented elsewhere.
*
* Generate the new seed for the credential chain. Increment
* the timestamp and add it to the client challenge. Then we
* need to copy the challenge to the credential field in
* preparation for the next cycle.
*/
/*
* Save the new password.
*/
}
return (0);
}
/*
* netr_gen_password
*
* Generate a new pasword from the old password and the session key.
* The algorithm is a two stage hash. The session key is used in the
* first hash but only part of the session key is used in the second
* hash.
*
* If any difficulties occur using the cryptographic framework, the
* function returns SMBAUTH_FAILURE. Otherwise SMBAUTH_SUCCESS is
* returned.
*/
static int
{
int rv;
old_password, 8);
if (rv != SMBAUTH_SUCCESS)
return (rv);
return (rv);
}