2012-12-07 04:05:00 +04:00
/*
2003-12-01 07:13:43 +03:00
Unix SMB / CIFS implementation .
code to manipulate domain credentials
Copyright ( C ) Andrew Tridgell 1997 - 2003
2004-05-15 11:51:38 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004
2012-12-07 04:05:00 +04:00
2003-12-01 07:13:43 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-12-01 07:13:43 +03:00
( at your option ) any later version .
2012-12-07 04:05:00 +04:00
2003-12-01 07:13:43 +03:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2012-12-07 04:05:00 +04:00
2003-12-01 07:13:43 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-12-01 07:13:43 +03:00
*/
# include "includes.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2023-07-19 22:04:53 +03:00
# include "librpc/gen_ndr/ndr_schannel.h"
2006-03-25 21:47:47 +03:00
# include "libcli/auth/libcli_auth.h"
2010-08-23 18:02:23 +04:00
# include "../libcli/security/dom_sid.h"
2020-09-16 17:17:29 +03:00
# include "lib/util/util_str_escape.h"
2003-12-01 07:13:43 +03:00
2019-06-26 07:41:05 +03:00
# include "lib/crypto/gnutls_helpers.h"
2018-10-10 16:37:18 +03:00
# include <gnutls/gnutls.h>
# include <gnutls/crypto.h>
2024-10-28 19:51:21 +03:00
# undef netlogon_creds_des_encrypt
# undef netlogon_creds_des_decrypt
# undef netlogon_creds_arcfour_crypt
# undef netlogon_creds_aes_encrypt
# undef netlogon_creds_aes_decrypt
2020-09-16 17:15:26 +03:00
bool netlogon_creds_is_random_challenge ( const struct netr_Credential * challenge )
{
/*
* If none of the first 5 bytes of the client challenge is unique , the
* server MUST fail session - key negotiation without further processing
* of the following steps .
*/
if ( challenge - > data [ 1 ] = = challenge - > data [ 0 ] & &
challenge - > data [ 2 ] = = challenge - > data [ 0 ] & &
challenge - > data [ 3 ] = = challenge - > data [ 0 ] & &
challenge - > data [ 4 ] = = challenge - > data [ 0 ] )
{
return false ;
}
return true ;
}
2024-10-29 20:02:19 +03:00
static NTSTATUS netlogon_creds_no_step_check ( struct netlogon_creds_CredentialState * creds ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
bool * skip )
{
* skip = false ;
if ( creds = = NULL ) {
return NT_STATUS_ACCESS_DENIED ;
}
/*
* Only if ServerAuthenticateKerberos ( ) was
* used the content of the netr_Authenticator
* values are not checked .
*
* It is independent from the
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH flag .
*/
if ( creds - > authenticate_kerberos ) {
if ( auth_type ! = DCERPC_AUTH_TYPE_KRB5 ) {
return NT_STATUS_ACCESS_DENIED ;
}
if ( auth_level ! = DCERPC_AUTH_LEVEL_PRIVACY ) {
return NT_STATUS_ACCESS_DENIED ;
}
* skip = true ;
}
return NT_STATUS_OK ;
}
static NTSTATUS netlogon_creds_no_buffer_crypt ( struct netlogon_creds_CredentialState * creds ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
bool * skip )
{
* skip = false ;
if ( creds = = NULL ) {
return NT_STATUS_ACCESS_DENIED ;
}
if ( creds - > authenticate_kerberos ) {
if ( auth_type ! = DCERPC_AUTH_TYPE_KRB5 ) {
return NT_STATUS_ACCESS_DENIED ;
}
if ( auth_level ! = DCERPC_AUTH_LEVEL_PRIVACY ) {
return NT_STATUS_ACCESS_DENIED ;
}
}
/*
* Even if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH is
* negotiated within ServerAuthenticate3 ( )
* encryption on application buffers is skipped .
*
* Also ServerAuthenticateKerberos ( ) without
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH uses
* encryption with a random session key .
*/
if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH ) {
if ( auth_level ! = DCERPC_AUTH_LEVEL_PRIVACY ) {
return NT_STATUS_ACCESS_DENIED ;
}
* skip = true ;
}
return NT_STATUS_OK ;
}
2020-09-16 17:04:57 +03:00
void netlogon_creds_random_challenge ( struct netr_Credential * challenge )
{
ZERO_STRUCTP ( challenge ) ;
2020-09-16 17:15:26 +03:00
while ( ! netlogon_creds_is_random_challenge ( challenge ) ) {
generate_random_buffer ( challenge - > data , sizeof ( challenge - > data ) ) ;
}
2020-09-16 17:04:57 +03:00
}
2019-11-13 12:13:53 +03:00
static NTSTATUS netlogon_creds_step_crypt ( struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * in ,
struct netr_Credential * out )
2009-08-25 13:25:47 +04:00
{
2019-11-14 01:16:09 +03:00
NTSTATUS status ;
2019-11-20 17:41:02 +03:00
int rc ;
2024-10-29 20:02:19 +03:00
if ( creds - > authenticate_kerberos ) {
/*
* The caller should have checked this already . . .
*/
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
2009-08-27 19:28:35 +04:00
if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
2019-03-01 19:33:01 +03:00
memcpy ( out - > data , in - > data , sizeof ( out - > data ) ) ;
2009-08-27 19:28:35 +04:00
2019-11-14 01:16:09 +03:00
status = netlogon_creds_aes_encrypt ( creds ,
out - > data ,
sizeof ( out - > data ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-08-27 19:28:35 +04:00
} else {
2019-11-20 17:41:02 +03:00
rc = des_crypt112 ( out - > data , in - > data , creds - > session_key , SAMBA_GNUTLS_ENCRYPT ) ;
if ( rc ! = 0 ) {
return gnutls_error_to_ntstatus ( rc ,
NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2009-08-27 19:28:35 +04:00
}
2019-11-13 12:13:53 +03:00
return NT_STATUS_OK ;
2009-08-25 13:25:47 +04:00
}
2003-12-01 15:41:54 +03:00
/*
2004-06-04 03:15:16 +04:00
initialise the credentials state for old - style 64 bit session keys
2003-12-02 01:13:11 +03:00
this call is made after the netr_ServerReqChallenge call
2003-12-01 15:41:54 +03:00
*/
2019-11-13 11:41:18 +03:00
static NTSTATUS netlogon_creds_init_64bit ( struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const struct samr_Password * machine_password )
2003-12-01 07:13:43 +03:00
{
2004-05-25 20:24:13 +04:00
uint32_t sum [ 2 ] ;
2004-05-25 21:50:17 +04:00
uint8_t sum2 [ 8 ] ;
2019-11-08 19:49:48 +03:00
int rc ;
2003-12-01 07:13:43 +03:00
sum [ 0 ] = IVAL ( client_challenge - > data , 0 ) + IVAL ( server_challenge - > data , 0 ) ;
sum [ 1 ] = IVAL ( client_challenge - > data , 4 ) + IVAL ( server_challenge - > data , 4 ) ;
SIVAL ( sum2 , 0 , sum [ 0 ] ) ;
SIVAL ( sum2 , 4 , sum [ 1 ] ) ;
2018-12-03 17:42:03 +03:00
ZERO_ARRAY ( creds - > session_key ) ;
2003-12-01 07:13:43 +03:00
2019-11-08 19:49:48 +03:00
rc = des_crypt128 ( creds - > session_key , sum2 , machine_password - > hash ) ;
if ( rc ! = 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2019-11-13 11:41:18 +03:00
return NT_STATUS_OK ;
2004-06-04 03:15:16 +04:00
}
/*
initialise the credentials state for ADS - style 128 bit session keys
this call is made after the netr_ServerReqChallenge call
*/
2018-12-06 16:49:40 +03:00
static NTSTATUS netlogon_creds_init_128bit ( struct netlogon_creds_CredentialState * creds ,
2009-04-06 16:53:01 +04:00
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const struct samr_Password * machine_password )
2004-06-04 03:15:16 +04:00
{
2018-10-26 15:59:58 +03:00
uint8_t zero [ 4 ] = { 0 } ;
2023-11-23 09:24:27 +03:00
uint8_t tmp [ gnutls_hash_get_len ( GNUTLS_DIG_MD5 ) ] ;
2018-10-26 15:59:58 +03:00
gnutls_hash_hd_t hash_hnd = NULL ;
int rc ;
2004-06-04 03:15:16 +04:00
2018-12-03 17:42:03 +03:00
ZERO_ARRAY ( creds - > session_key ) ;
2004-06-04 03:15:16 +04:00
2018-10-26 15:59:58 +03:00
rc = gnutls_hash_init ( & hash_hnd , GNUTLS_DIG_MD5 ) ;
if ( rc < 0 ) {
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HASH_NOT_SUPPORTED ) ;
2018-10-26 15:59:58 +03:00
}
rc = gnutls_hash ( hash_hnd , zero , sizeof ( zero ) ) ;
if ( rc < 0 ) {
gnutls_hash_deinit ( hash_hnd , NULL ) ;
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HASH_NOT_SUPPORTED ) ;
2018-10-26 15:59:58 +03:00
}
rc = gnutls_hash ( hash_hnd , client_challenge - > data , 8 ) ;
if ( rc < 0 ) {
gnutls_hash_deinit ( hash_hnd , NULL ) ;
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HASH_NOT_SUPPORTED ) ;
2018-10-26 15:59:58 +03:00
}
rc = gnutls_hash ( hash_hnd , server_challenge - > data , 8 ) ;
if ( rc < 0 ) {
gnutls_hash_deinit ( hash_hnd , NULL ) ;
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HASH_NOT_SUPPORTED ) ;
2018-10-26 15:59:58 +03:00
}
gnutls_hash_deinit ( hash_hnd , tmp ) ;
/* This doesn't require HMAC MD5 RFC2104 as the hash is only 16 bytes */
rc = gnutls_hmac_fast ( GNUTLS_MAC_MD5 ,
machine_password - > hash ,
sizeof ( machine_password - > hash ) ,
tmp ,
sizeof ( tmp ) ,
creds - > session_key ) ;
ZERO_ARRAY ( tmp ) ;
2018-12-06 16:49:40 +03:00
if ( rc < 0 ) {
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HASH_NOT_SUPPORTED ) ;
2018-12-06 16:49:40 +03:00
}
return NT_STATUS_OK ;
2009-08-25 13:25:47 +04:00
}
2004-06-04 03:15:16 +04:00
2009-08-27 19:28:35 +04:00
/*
initialise the credentials state for AES / HMAC - SHA256 - style 128 bit session keys
this call is made after the netr_ServerReqChallenge call
*/
2018-12-04 11:13:31 +03:00
static NTSTATUS netlogon_creds_init_hmac_sha256 ( struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const struct samr_Password * machine_password )
2009-08-27 19:28:35 +04:00
{
2018-10-10 16:37:18 +03:00
gnutls_hmac_hd_t hmac_hnd = NULL ;
2023-11-23 09:24:51 +03:00
uint8_t digest [ gnutls_hmac_get_len ( GNUTLS_MAC_SHA256 ) ] ;
2018-10-10 16:37:18 +03:00
int rc ;
2009-08-27 19:28:35 +04:00
2018-12-03 17:42:03 +03:00
ZERO_ARRAY ( creds - > session_key ) ;
2009-08-27 19:28:35 +04:00
2018-10-10 16:37:18 +03:00
rc = gnutls_hmac_init ( & hmac_hnd ,
GNUTLS_MAC_SHA256 ,
machine_password - > hash ,
sizeof ( machine_password - > hash ) ) ;
if ( rc < 0 ) {
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
2018-10-10 16:37:18 +03:00
}
rc = gnutls_hmac ( hmac_hnd ,
client_challenge - > data ,
8 ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
2018-10-10 16:37:18 +03:00
}
rc = gnutls_hmac ( hmac_hnd ,
server_challenge - > data ,
8 ) ;
if ( rc < 0 ) {
gnutls_hmac_deinit ( hmac_hnd , NULL ) ;
2019-06-11 16:11:30 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_HMAC_NOT_SUPPORTED ) ;
2018-10-10 16:37:18 +03:00
}
gnutls_hmac_deinit ( hmac_hnd , digest ) ;
2009-08-27 19:28:35 +04:00
memcpy ( creds - > session_key , digest , sizeof ( creds - > session_key ) ) ;
2018-10-10 16:37:18 +03:00
ZERO_ARRAY ( digest ) ;
2018-12-04 11:13:31 +03:00
return NT_STATUS_OK ;
2009-08-27 19:28:35 +04:00
}
2019-11-13 11:44:32 +03:00
static NTSTATUS netlogon_creds_first_step ( struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge )
2009-08-25 13:25:47 +04:00
{
2019-11-13 12:13:53 +03:00
NTSTATUS status ;
status = netlogon_creds_step_crypt ( creds ,
client_challenge ,
& creds - > client ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-08-25 13:25:47 +04:00
2019-11-13 12:13:53 +03:00
status = netlogon_creds_step_crypt ( creds ,
server_challenge ,
& creds - > server ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2003-12-02 01:13:11 +03:00
2003-12-02 05:15:33 +03:00
creds - > seed = creds - > client ;
2019-11-13 11:44:32 +03:00
return NT_STATUS_OK ;
2003-12-02 05:15:33 +03:00
}
/*
2003-12-02 06:06:21 +03:00
step the credentials to the next element in the chain , updating the
current client and server credentials and the seed
2003-12-02 05:15:33 +03:00
*/
2019-11-13 12:12:41 +03:00
static NTSTATUS netlogon_creds_step ( struct netlogon_creds_CredentialState * creds )
2003-12-02 05:15:33 +03:00
{
struct netr_Credential time_cred ;
2019-11-13 12:12:41 +03:00
NTSTATUS status ;
2003-12-02 05:15:33 +03:00
2024-10-29 20:02:19 +03:00
if ( creds - > authenticate_kerberos ) {
/* This is only called on the client side */
generate_nonce_buffer ( creds - > seed . data ,
ARRAY_SIZE ( creds - > seed . data ) ) ;
generate_nonce_buffer ( creds - > client . data ,
ARRAY_SIZE ( creds - > client . data ) ) ;
generate_nonce_buffer ( creds - > server . data ,
ARRAY_SIZE ( creds - > server . data ) ) ;
return NT_STATUS_OK ;
}
2012-12-07 04:05:00 +04:00
DEBUG ( 5 , ( " \t seed %08x:%08x \n " ,
2003-12-02 05:15:33 +03:00
IVAL ( creds - > seed . data , 0 ) , IVAL ( creds - > seed . data , 4 ) ) ) ;
SIVAL ( time_cred . data , 0 , IVAL ( creds - > seed . data , 0 ) + creds - > sequence ) ;
SIVAL ( time_cred . data , 4 , IVAL ( creds - > seed . data , 4 ) ) ;
DEBUG ( 5 , ( " \t seed+time %08x:%08x \n " , IVAL ( time_cred . data , 0 ) , IVAL ( time_cred . data , 4 ) ) ) ;
2019-11-13 12:13:53 +03:00
status = netlogon_creds_step_crypt ( creds ,
& time_cred ,
& creds - > client ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2003-12-02 05:15:33 +03:00
2012-12-07 04:05:00 +04:00
DEBUG ( 5 , ( " \t CLIENT %08x:%08x \n " ,
2003-12-02 05:15:33 +03:00
IVAL ( creds - > client . data , 0 ) , IVAL ( creds - > client . data , 4 ) ) ) ;
SIVAL ( time_cred . data , 0 , IVAL ( creds - > seed . data , 0 ) + creds - > sequence + 1 ) ;
SIVAL ( time_cred . data , 4 , IVAL ( creds - > seed . data , 4 ) ) ;
2012-12-07 04:05:00 +04:00
DEBUG ( 5 , ( " \t seed+time+1 %08x:%08x \n " ,
2003-12-02 05:15:33 +03:00
IVAL ( time_cred . data , 0 ) , IVAL ( time_cred . data , 4 ) ) ) ;
2019-11-13 12:13:53 +03:00
status = netlogon_creds_step_crypt ( creds , & time_cred , & creds - > server ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2003-12-01 07:13:43 +03:00
2012-12-07 04:05:00 +04:00
DEBUG ( 5 , ( " \t SERVER %08x:%08x \n " ,
2003-12-02 05:15:33 +03:00
IVAL ( creds - > server . data , 0 ) , IVAL ( creds - > server . data , 4 ) ) ) ;
creds - > seed = time_cred ;
2019-11-13 12:12:41 +03:00
return NT_STATUS_OK ;
2003-12-01 07:13:43 +03:00
}
2004-11-11 07:32:01 +03:00
/*
DES encrypt a 8 byte LMSessionKey buffer using the Netlogon session key
*/
2024-10-28 17:52:13 +03:00
static NTSTATUS netlogon_creds_des_encrypt_LMKey ( struct netlogon_creds_CredentialState * creds ,
2019-11-07 14:53:52 +03:00
struct netr_LMSessionKey * key )
2004-11-11 07:32:01 +03:00
{
2019-11-07 14:53:52 +03:00
int rc ;
2004-11-11 07:32:01 +03:00
struct netr_LMSessionKey tmp ;
2019-11-07 14:53:52 +03:00
rc = des_crypt56_gnutls ( tmp . key , key - > key , creds - > session_key , SAMBA_GNUTLS_ENCRYPT ) ;
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2004-11-11 07:32:01 +03:00
* key = tmp ;
2019-11-07 14:53:52 +03:00
return NT_STATUS_OK ;
2004-11-11 07:32:01 +03:00
}
/*
DES decrypt a 8 byte LMSessionKey buffer using the Netlogon session key
*/
2024-10-28 17:52:13 +03:00
static NTSTATUS netlogon_creds_des_decrypt_LMKey ( struct netlogon_creds_CredentialState * creds ,
2019-11-07 14:53:52 +03:00
struct netr_LMSessionKey * key )
2004-11-11 07:32:01 +03:00
{
2019-11-07 14:53:52 +03:00
int rc ;
2004-11-11 07:32:01 +03:00
struct netr_LMSessionKey tmp ;
2019-11-07 14:53:52 +03:00
rc = des_crypt56_gnutls ( tmp . key , key - > key , creds - > session_key , SAMBA_GNUTLS_DECRYPT ) ;
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2004-11-11 07:32:01 +03:00
* key = tmp ;
2019-11-07 14:53:52 +03:00
return NT_STATUS_OK ;
2004-11-11 07:32:01 +03:00
}
2004-05-09 16:42:18 +04:00
/*
DES encrypt a 16 byte password buffer using the session key
*/
2019-11-20 18:02:16 +03:00
NTSTATUS netlogon_creds_des_encrypt ( struct netlogon_creds_CredentialState * creds ,
struct samr_Password * pass )
2004-05-09 16:42:18 +04:00
{
2004-06-04 15:58:46 +04:00
struct samr_Password tmp ;
2019-11-20 18:02:16 +03:00
int rc ;
rc = des_crypt112_16 ( tmp . hash , pass - > hash , creds - > session_key , SAMBA_GNUTLS_ENCRYPT ) ;
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2004-05-09 16:42:18 +04:00
* pass = tmp ;
2019-11-20 18:02:16 +03:00
return NT_STATUS_OK ;
2004-05-09 16:42:18 +04:00
}
2004-05-17 01:30:48 +04:00
/*
DES decrypt a 16 byte password buffer using the session key
*/
2019-11-20 18:02:16 +03:00
NTSTATUS netlogon_creds_des_decrypt ( struct netlogon_creds_CredentialState * creds ,
struct samr_Password * pass )
2004-05-17 01:30:48 +04:00
{
2004-06-04 15:58:46 +04:00
struct samr_Password tmp ;
2019-11-20 18:02:16 +03:00
int rc ;
rc = des_crypt112_16 ( tmp . hash , pass - > hash , creds - > session_key , SAMBA_GNUTLS_DECRYPT ) ;
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc , NT_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ) ;
}
2004-05-17 01:30:48 +04:00
* pass = tmp ;
2019-11-20 18:02:16 +03:00
return NT_STATUS_OK ;
2004-05-17 01:30:48 +04:00
}
2004-05-09 16:42:18 +04:00
/*
ARCFOUR encrypt / decrypt a password buffer using the session key
*/
2019-05-29 15:46:17 +03:00
NTSTATUS netlogon_creds_arcfour_crypt ( struct netlogon_creds_CredentialState * creds ,
uint8_t * data ,
size_t len )
2004-05-09 16:42:18 +04:00
{
2019-01-31 13:28:02 +03:00
gnutls_cipher_hd_t cipher_hnd = NULL ;
gnutls_datum_t session_key = {
. data = creds - > session_key ,
. size = sizeof ( creds - > session_key ) ,
} ;
int rc ;
2003-12-02 01:13:11 +03:00
2019-01-31 13:28:02 +03:00
rc = gnutls_cipher_init ( & cipher_hnd ,
GNUTLS_CIPHER_ARCFOUR_128 ,
& session_key ,
NULL ) ;
if ( rc < 0 ) {
2019-05-29 15:46:17 +03:00
return gnutls_error_to_ntstatus ( rc ,
NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
2019-01-31 13:28:02 +03:00
}
2019-05-29 15:46:17 +03:00
rc = gnutls_cipher_encrypt ( cipher_hnd ,
data ,
len ) ;
2019-01-31 13:28:02 +03:00
gnutls_cipher_deinit ( cipher_hnd ) ;
2019-05-29 15:46:17 +03:00
if ( rc < 0 ) {
return gnutls_error_to_ntstatus ( rc ,
NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
}
return NT_STATUS_OK ;
2004-05-09 16:42:18 +04:00
}
2003-12-02 06:06:21 +03:00
2012-11-30 00:23:30 +04:00
/*
AES encrypt a password buffer using the session key
*/
2019-05-29 17:38:09 +03:00
NTSTATUS netlogon_creds_aes_encrypt ( struct netlogon_creds_CredentialState * creds ,
uint8_t * data ,
size_t len )
2012-11-30 00:23:30 +04:00
{
2019-03-01 19:41:11 +03:00
gnutls_cipher_hd_t cipher_hnd = NULL ;
gnutls_datum_t key = {
. data = creds - > session_key ,
. size = sizeof ( creds - > session_key ) ,
} ;
uint32_t iv_size =
gnutls_cipher_get_iv_size ( GNUTLS_CIPHER_AES_128_CFB8 ) ;
uint8_t _iv [ iv_size ] ;
gnutls_datum_t iv = {
. data = _iv ,
. size = iv_size ,
} ;
int rc ;
ZERO_ARRAY ( _iv ) ;
rc = gnutls_cipher_init ( & cipher_hnd ,
GNUTLS_CIPHER_AES_128_CFB8 ,
& key ,
& iv ) ;
if ( rc < 0 ) {
2019-05-29 17:38:09 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
2019-03-01 19:41:11 +03:00
}
rc = gnutls_cipher_encrypt ( cipher_hnd , data , len ) ;
gnutls_cipher_deinit ( cipher_hnd ) ;
if ( rc < 0 ) {
2019-05-29 17:38:09 +03:00
return gnutls_error_to_ntstatus ( rc , NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
2019-03-01 19:41:11 +03:00
}
2019-05-29 17:38:09 +03:00
return NT_STATUS_OK ;
2012-11-30 00:23:30 +04:00
}
/*
AES decrypt a password buffer using the session key
*/
2019-08-16 03:34:28 +03:00
NTSTATUS netlogon_creds_aes_decrypt ( struct netlogon_creds_CredentialState * creds , uint8_t * data , size_t len )
2012-11-30 00:23:30 +04:00
{
2019-03-18 17:13:08 +03:00
gnutls_cipher_hd_t cipher_hnd = NULL ;
gnutls_datum_t key = {
. data = creds - > session_key ,
. size = sizeof ( creds - > session_key ) ,
} ;
uint32_t iv_size =
gnutls_cipher_get_iv_size ( GNUTLS_CIPHER_AES_128_CFB8 ) ;
uint8_t _iv [ iv_size ] ;
gnutls_datum_t iv = {
. data = _iv ,
. size = iv_size ,
} ;
int rc ;
ZERO_ARRAY ( _iv ) ;
rc = gnutls_cipher_init ( & cipher_hnd ,
GNUTLS_CIPHER_AES_128_CFB8 ,
& key ,
& iv ) ;
if ( rc < 0 ) {
2019-08-16 03:34:28 +03:00
return gnutls_error_to_ntstatus ( rc ,
NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
2019-03-18 17:13:08 +03:00
}
rc = gnutls_cipher_decrypt ( cipher_hnd , data , len ) ;
gnutls_cipher_deinit ( cipher_hnd ) ;
if ( rc < 0 ) {
2019-08-16 03:34:28 +03:00
return gnutls_error_to_ntstatus ( rc ,
NT_STATUS_CRYPTO_SYSTEM_INVALID ) ;
2019-03-18 17:13:08 +03:00
}
2019-08-16 03:34:28 +03:00
return NT_STATUS_OK ;
2012-11-30 00:23:30 +04:00
}
2024-10-16 18:47:22 +03:00
static struct netlogon_creds_CredentialState *
netlogon_creds_alloc ( TALLOC_CTX * mem_ctx ,
const char * client_account ,
const char * client_computer_name ,
uint16_t secure_channel_type ,
uint32_t client_requested_flags ,
const struct dom_sid * client_sid ,
uint32_t negotiate_flags )
2003-12-01 07:13:43 +03:00
{
2024-10-16 18:47:22 +03:00
struct netlogon_creds_CredentialState * creds = NULL ;
2024-10-02 20:06:59 +03:00
struct timeval tv = timeval_current ( ) ;
NTTIME now = timeval_to_nttime ( & tv ) ;
2024-12-11 12:14:44 +03:00
const char * name = NULL ;
2012-12-07 04:05:00 +04:00
2024-10-16 18:47:22 +03:00
creds = talloc_zero ( mem_ctx , struct netlogon_creds_CredentialState ) ;
if ( creds = = NULL ) {
2009-04-06 16:53:01 +04:00
return NULL ;
}
2012-12-07 04:05:00 +04:00
2024-10-16 18:47:22 +03:00
if ( client_sid = = NULL ) {
creds - > sequence = tv . tv_sec ;
}
2004-06-04 03:15:16 +04:00
creds - > negotiate_flags = negotiate_flags ;
2012-12-19 16:53:23 +04:00
creds - > secure_channel_type = secure_channel_type ;
2004-06-04 03:15:16 +04:00
2009-04-06 16:53:01 +04:00
creds - > computer_name = talloc_strdup ( creds , client_computer_name ) ;
if ( ! creds - > computer_name ) {
talloc_free ( creds ) ;
return NULL ;
}
creds - > account_name = talloc_strdup ( creds , client_account ) ;
if ( ! creds - > account_name ) {
talloc_free ( creds ) ;
return NULL ;
}
2024-11-15 18:24:25 +03:00
creds - > client_requested_flags = client_requested_flags ;
creds - > auth_time = now ;
2024-10-16 18:47:22 +03:00
if ( client_sid ! = NULL ) {
2024-11-15 18:24:25 +03:00
creds - > client_sid = * client_sid ;
2024-10-16 18:47:22 +03:00
} else {
2024-11-15 18:24:25 +03:00
creds - > client_sid = global_sid_NULL ;
2024-10-16 18:47:22 +03:00
}
2024-12-11 12:14:44 +03:00
name = talloc_get_name ( creds ) ;
_talloc_keep_secret ( creds , name ) ;
2024-10-16 18:47:22 +03:00
return creds ;
}
2024-10-29 20:02:19 +03:00
struct netlogon_creds_CredentialState * netlogon_creds_kerberos_init ( TALLOC_CTX * mem_ctx ,
const char * client_account ,
const char * client_computer_name ,
uint16_t secure_channel_type ,
uint32_t client_requested_flags ,
const struct dom_sid * client_sid ,
uint32_t negotiate_flags )
{
struct netlogon_creds_CredentialState * creds = NULL ;
creds = netlogon_creds_alloc ( mem_ctx ,
client_account ,
client_computer_name ,
secure_channel_type ,
client_requested_flags ,
client_sid ,
negotiate_flags ) ;
if ( creds = = NULL ) {
return NULL ;
}
/*
* Some Windows versions used
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* as a dummy flag in ServerAuthenticate3 ,
* so we should not use
* NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* for any logic decisions .
*
* So we use a dedicated bool that
* is only set if ServerAuthenticateKerberos
* was really used . And for that we assert
* that NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* is set too .
*/
creds - > authenticate_kerberos = true ;
/*
* This should not be required , but we better
* make sure we would not use a zero session key . . .
*
* It seems that ' s what Windows is also doing . . .
* as the values in netr_ServerPasswordGet ( ) are
* encrypted in random ways if NETLOGON_NEG_SUPPORTS_KERBEROS_AUTH
* is missing in netr_ServerAuthenticateKerberos ( ) .
*/
generate_nonce_buffer ( creds - > session_key ,
ARRAY_SIZE ( creds - > session_key ) ) ;
generate_nonce_buffer ( creds - > seed . data ,
ARRAY_SIZE ( creds - > seed . data ) ) ;
generate_nonce_buffer ( creds - > client . data ,
ARRAY_SIZE ( creds - > client . data ) ) ;
generate_nonce_buffer ( creds - > server . data ,
ARRAY_SIZE ( creds - > server . data ) ) ;
return creds ;
}
2024-10-16 18:47:22 +03:00
/*****************************************************************
The above functions are common to the client and server interface
next comes the client specific functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
initialise the credentials chain and return the first client
credentials
*/
struct netlogon_creds_CredentialState * netlogon_creds_client_init ( TALLOC_CTX * mem_ctx ,
const char * client_account ,
const char * client_computer_name ,
uint16_t secure_channel_type ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const struct samr_Password * machine_password ,
struct netr_Credential * initial_credential ,
uint32_t client_requested_flags ,
uint32_t negotiate_flags )
{
struct netlogon_creds_CredentialState * creds = NULL ;
NTSTATUS status ;
creds = netlogon_creds_alloc ( mem_ctx ,
client_account ,
client_computer_name ,
secure_channel_type ,
client_requested_flags ,
NULL , /* client_sid */
negotiate_flags ) ;
if ( ! creds ) {
return NULL ;
}
2024-10-02 20:06:59 +03:00
2004-06-04 03:15:16 +04:00
dump_data_pw ( " Client chall " , client_challenge - > data , sizeof ( client_challenge - > data ) ) ;
dump_data_pw ( " Server chall " , server_challenge - > data , sizeof ( server_challenge - > data ) ) ;
2004-06-05 07:14:59 +04:00
dump_data_pw ( " Machine Pass " , machine_password - > hash , sizeof ( machine_password - > hash ) ) ;
2004-06-04 03:15:16 +04:00
2009-08-27 19:28:35 +04:00
if ( negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
2018-12-04 11:13:31 +03:00
status = netlogon_creds_init_hmac_sha256 ( creds ,
client_challenge ,
server_challenge ,
machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2009-08-27 19:28:35 +04:00
} else if ( negotiate_flags & NETLOGON_NEG_STRONG_KEYS ) {
2018-12-06 16:49:40 +03:00
status = netlogon_creds_init_128bit ( creds ,
client_challenge ,
server_challenge ,
machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2004-06-04 03:15:16 +04:00
} else {
2019-11-13 11:41:18 +03:00
status = netlogon_creds_init_64bit ( creds ,
client_challenge ,
server_challenge ,
machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2004-06-04 03:15:16 +04:00
}
2019-11-13 11:44:32 +03:00
status = netlogon_creds_first_step ( creds ,
client_challenge ,
server_challenge ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2009-08-25 13:25:47 +04:00
2004-06-04 03:15:16 +04:00
dump_data_pw ( " Session key " , creds - > session_key , 16 ) ;
dump_data_pw ( " Credential " , creds - > client . data , 8 ) ;
2003-12-02 05:15:33 +03:00
* initial_credential = creds - > client ;
2009-04-06 16:53:01 +04:00
return creds ;
2003-12-02 05:15:33 +03:00
}
2003-12-01 07:13:43 +03:00
2004-05-17 01:30:48 +04:00
/*
step the credentials to the next element in the chain , updating the
current client and server credentials and the seed
2012-12-07 04:05:00 +04:00
produce the next authenticator in the sequence ready to send to
2004-05-17 01:30:48 +04:00
the server
*/
2019-11-13 11:52:53 +03:00
NTSTATUS
netlogon_creds_client_authenticator ( struct netlogon_creds_CredentialState * creds ,
struct netr_Authenticator * next )
2012-12-07 04:05:00 +04:00
{
2013-12-17 22:55:12 +04:00
uint32_t t32n = ( uint32_t ) time ( NULL ) ;
2019-11-13 12:12:41 +03:00
NTSTATUS status ;
2013-12-17 22:55:12 +04:00
/*
* we always increment and ignore an overflow here
*/
2004-05-17 01:30:48 +04:00
creds - > sequence + = 2 ;
2013-12-17 22:55:12 +04:00
if ( t32n > creds - > sequence ) {
/*
* we may increment more
*/
creds - > sequence = t32n ;
} else {
uint32_t d = creds - > sequence - t32n ;
if ( d > = INT32_MAX ) {
/*
* got an overflow of time_t vs . uint32_t
*/
creds - > sequence = t32n ;
}
}
2019-11-13 12:12:41 +03:00
status = netlogon_creds_step ( creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-05-17 01:30:48 +04:00
next - > cred = creds - > client ;
next - > timestamp = creds - > sequence ;
2019-11-13 11:52:53 +03:00
return NT_STATUS_OK ;
2004-05-17 01:30:48 +04:00
}
2003-12-02 05:15:33 +03:00
/*
check that a credentials reply from a server is correct
*/
2024-10-29 11:54:42 +03:00
NTSTATUS netlogon_creds_client_verify ( struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * received_credentials ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
2003-12-02 05:15:33 +03:00
{
2024-10-29 20:02:19 +03:00
NTSTATUS status ;
bool skip_crypto = false ;
status = netlogon_creds_no_step_check ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( skip_crypto ) {
return NT_STATUS_OK ;
}
2012-12-07 04:05:00 +04:00
if ( ! received_credentials | |
2022-05-11 03:07:43 +03:00
! mem_equal_const_time ( received_credentials - > data , creds - > server . data , 8 ) ) {
2003-12-01 15:41:54 +03:00
DEBUG ( 2 , ( " credentials check failed \n " ) ) ;
2024-10-29 11:54:42 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
return NT_STATUS_OK ;
}
bool netlogon_creds_client_check ( struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * received_credentials )
{
enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE ;
enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE ;
NTSTATUS status ;
status = netlogon_creds_client_verify ( creds ,
received_credentials ,
auth_type ,
auth_level ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-10-07 02:28:14 +04:00
return false ;
2003-12-01 07:13:43 +03:00
}
2024-10-29 11:54:42 +03:00
2007-10-07 02:28:14 +04:00
return true ;
2003-12-02 01:13:11 +03:00
}
2003-12-01 07:13:43 +03:00
2003-12-02 03:31:54 +03:00
2004-05-15 11:51:38 +04:00
/*****************************************************************
The above functions are common to the client and server interface
next comes the server specific functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
check that a credentials reply from a server is correct
*/
2009-04-06 16:53:01 +04:00
static bool netlogon_creds_server_check_internal ( const struct netlogon_creds_CredentialState * creds ,
const struct netr_Credential * received_credentials )
2004-05-15 11:51:38 +04:00
{
2022-05-11 03:07:43 +03:00
if ( ! mem_equal_const_time ( received_credentials - > data , creds - > client . data , 8 ) ) {
2004-05-15 11:51:38 +04:00
DEBUG ( 2 , ( " credentials check failed \n " ) ) ;
dump_data_pw ( " client creds " , creds - > client . data , 8 ) ;
dump_data_pw ( " calc creds " , received_credentials - > data , 8 ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-05-15 11:51:38 +04:00
}
2007-10-07 02:28:14 +04:00
return true ;
2004-05-15 11:51:38 +04:00
}
2009-04-06 16:53:01 +04:00
/*
initialise the credentials chain and return the first server
credentials
*/
2012-12-07 04:05:00 +04:00
struct netlogon_creds_CredentialState * netlogon_creds_server_init ( TALLOC_CTX * mem_ctx ,
2009-04-06 16:53:01 +04:00
const char * client_account ,
2012-12-07 04:05:00 +04:00
const char * client_computer_name ,
2009-04-06 16:53:01 +04:00
uint16_t secure_channel_type ,
const struct netr_Credential * client_challenge ,
const struct netr_Credential * server_challenge ,
const struct samr_Password * machine_password ,
2015-03-19 18:26:03 +03:00
const struct netr_Credential * credentials_in ,
2009-04-06 16:53:01 +04:00
struct netr_Credential * credentials_out ,
2024-10-02 20:06:59 +03:00
uint32_t client_requested_flags ,
2024-10-02 19:46:43 +03:00
const struct dom_sid * client_sid ,
2009-04-06 16:53:01 +04:00
uint32_t negotiate_flags )
{
2024-10-16 18:47:22 +03:00
struct netlogon_creds_CredentialState * creds = NULL ;
2019-11-13 11:39:19 +03:00
NTSTATUS status ;
2020-09-16 17:17:29 +03:00
bool ok ;
2012-12-07 04:05:00 +04:00
2024-10-16 18:47:22 +03:00
creds = netlogon_creds_alloc ( mem_ctx ,
client_account ,
client_computer_name ,
secure_channel_type ,
client_requested_flags ,
client_sid ,
negotiate_flags ) ;
2009-04-06 16:53:01 +04:00
if ( ! creds ) {
return NULL ;
}
2012-12-07 04:05:00 +04:00
2009-08-27 19:28:35 +04:00
dump_data_pw ( " Client chall " , client_challenge - > data , sizeof ( client_challenge - > data ) ) ;
dump_data_pw ( " Server chall " , server_challenge - > data , sizeof ( server_challenge - > data ) ) ;
dump_data_pw ( " Machine Pass " , machine_password - > hash , sizeof ( machine_password - > hash ) ) ;
2020-09-16 17:17:29 +03:00
ok = netlogon_creds_is_random_challenge ( client_challenge ) ;
if ( ! ok ) {
DBG_WARNING ( " CVE-2020-1472(ZeroLogon): "
" non-random client challenge rejected for "
" client_account[%s] client_computer_name[%s] \n " ,
log_escape ( mem_ctx , client_account ) ,
log_escape ( mem_ctx , client_computer_name ) ) ;
dump_data ( DBGLVL_WARNING ,
client_challenge - > data ,
sizeof ( client_challenge - > data ) ) ;
talloc_free ( creds ) ;
return NULL ;
}
2009-08-27 19:28:35 +04:00
if ( negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
2018-12-04 11:13:31 +03:00
status = netlogon_creds_init_hmac_sha256 ( creds ,
client_challenge ,
server_challenge ,
machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2009-08-27 19:28:35 +04:00
} else if ( negotiate_flags & NETLOGON_NEG_STRONG_KEYS ) {
2019-11-13 11:39:19 +03:00
status = netlogon_creds_init_128bit ( creds ,
client_challenge ,
server_challenge ,
machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2009-04-06 16:53:01 +04:00
} else {
2019-11-13 11:41:18 +03:00
status = netlogon_creds_init_64bit ( creds ,
client_challenge ,
server_challenge ,
machine_password ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2009-04-06 16:53:01 +04:00
}
2019-11-13 11:44:32 +03:00
status = netlogon_creds_first_step ( creds ,
client_challenge ,
server_challenge ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( creds ) ;
return NULL ;
}
2009-08-25 13:25:47 +04:00
2009-08-27 19:28:35 +04:00
dump_data_pw ( " Session key " , creds - > session_key , 16 ) ;
dump_data_pw ( " Client Credential " , creds - > client . data , 8 ) ;
dump_data_pw ( " Server Credential " , creds - > server . data , 8 ) ;
dump_data_pw ( " Credentials in " , credentials_in - > data , sizeof ( credentials_in - > data ) ) ;
2009-04-06 16:53:01 +04:00
/* And before we leak information about the machine account
* password , check that they got the first go right */
if ( ! netlogon_creds_server_check_internal ( creds , credentials_in ) ) {
talloc_free ( creds ) ;
return NULL ;
}
* credentials_out = creds - > server ;
2009-08-27 19:28:35 +04:00
dump_data_pw ( " Credentials out " , credentials_out - > data , sizeof ( credentials_out - > data ) ) ;
2009-04-06 16:53:01 +04:00
return creds ;
}
NTSTATUS netlogon_creds_server_step_check ( struct netlogon_creds_CredentialState * creds ,
2015-03-19 18:26:03 +03:00
const struct netr_Authenticator * received_authenticator ,
2024-10-29 11:46:07 +03:00
struct netr_Authenticator * return_authenticator ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
2004-05-17 01:30:48 +04:00
{
2019-11-13 12:12:41 +03:00
NTSTATUS status ;
2024-10-29 20:02:19 +03:00
bool skip_crypto = false ;
2019-11-13 12:12:41 +03:00
2005-01-03 09:23:02 +03:00
if ( ! received_authenticator | | ! return_authenticator ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2024-10-29 20:02:19 +03:00
status = netlogon_creds_no_step_check ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ZERO_STRUCTP ( return_authenticator ) ;
return status ;
}
if ( skip_crypto ) {
ZERO_STRUCTP ( return_authenticator ) ;
return NT_STATUS_OK ;
2005-01-10 15:30:13 +03:00
}
2004-05-17 01:30:48 +04:00
creds - > sequence = received_authenticator - > timestamp ;
2019-11-13 12:12:41 +03:00
status = netlogon_creds_step ( creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ZERO_STRUCTP ( return_authenticator ) ;
return status ;
}
2009-04-06 16:53:01 +04:00
if ( netlogon_creds_server_check_internal ( creds , & received_authenticator - > cred ) ) {
2004-05-17 01:30:48 +04:00
return_authenticator - > cred = creds - > server ;
2013-12-17 22:35:37 +04:00
return_authenticator - > timestamp = 0 ;
2005-01-03 09:23:02 +03:00
return NT_STATUS_OK ;
2004-05-17 01:30:48 +04:00
} else {
ZERO_STRUCTP ( return_authenticator ) ;
2005-01-03 09:23:02 +03:00
return NT_STATUS_ACCESS_DENIED ;
2004-05-17 01:30:48 +04:00
}
}
2005-10-09 16:38:23 +04:00
2019-05-29 15:39:34 +03:00
static NTSTATUS netlogon_creds_crypt_samlogon_validation ( struct netlogon_creds_CredentialState * creds ,
uint16_t validation_level ,
union netr_Validation * validation ,
2024-10-28 14:43:44 +03:00
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
2019-05-29 15:39:34 +03:00
bool do_encrypt )
2005-10-09 16:38:23 +04:00
{
2005-10-09 17:03:52 +04:00
struct netr_SamBaseInfo * base = NULL ;
2019-05-29 15:46:17 +03:00
NTSTATUS status ;
2024-10-29 20:02:19 +03:00
bool skip_crypto = false ;
2013-04-24 14:36:04 +04:00
if ( validation = = NULL ) {
2019-05-29 15:39:34 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2013-04-24 14:36:04 +04:00
}
2005-10-09 16:38:23 +04:00
switch ( validation_level ) {
case 2 :
2005-10-09 17:03:52 +04:00
if ( validation - > sam2 ) {
base = & validation - > sam2 - > base ;
}
2005-10-09 16:38:23 +04:00
break ;
case 3 :
2005-10-09 17:03:52 +04:00
if ( validation - > sam3 ) {
base = & validation - > sam3 - > base ;
}
2005-10-09 16:38:23 +04:00
break ;
2024-11-18 21:50:22 +03:00
case 5 :
/* NetlogonValidationGenericInfo2 */
if ( validation - > generic ! = NULL & &
validation - > generic - > length = = 0 )
{
/*
* For " Kerberos "
* KERB_VERIFY_PAC_REQUEST there ' s
* not response , so there ' s nothing
* to encrypt .
*/
return NT_STATUS_OK ;
}
/*
* We don ' t know if encryption is
* required or not yet .
*
* We would have to do tests
* with DIGEST_VALIDATION_RESP
*
* But as we don ' t support that
* yet , we just return an error
* for now .
*/
log_stack_trace ( ) ;
return NT_STATUS_INTERNAL_ERROR ;
2005-10-09 16:38:23 +04:00
case 6 :
2005-10-09 17:03:52 +04:00
if ( validation - > sam6 ) {
base = & validation - > sam6 - > base ;
}
2005-10-09 16:38:23 +04:00
break ;
2024-11-21 16:16:12 +03:00
case 7 :
/* NetlogonValidationTicketLogon */
return NT_STATUS_OK ;
2005-10-09 17:03:52 +04:00
default :
/* If we can't find it, we can't very well decrypt it */
2019-05-29 15:39:34 +03:00
return NT_STATUS_INVALID_INFO_CLASS ;
2005-10-09 16:38:23 +04:00
}
2005-10-09 17:03:52 +04:00
if ( ! base ) {
2019-05-29 15:39:34 +03:00
return NT_STATUS_INVALID_INFO_CLASS ;
2005-10-09 17:03:52 +04:00
}
2024-10-29 20:02:19 +03:00
status = netlogon_creds_no_buffer_crypt ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2023-07-20 06:09:42 +03:00
/* find and decrypt the session keys, return in parameters above */
2024-10-29 20:02:19 +03:00
if ( skip_crypto | | validation_level = = 6 ) {
2005-10-09 16:38:23 +04:00
/* they aren't encrypted! */
2012-12-07 15:38:16 +04:00
} else if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
2024-10-29 20:02:19 +03:00
/*
* Don ' t crypt an all - zero key , it would give away
* the NETLOGON pipe session key
*
* But for ServerAuthenticateKerberos we don ' t care
* as we use a random key
*/
if ( creds - > authenticate_kerberos | |
! all_zero ( base - > key . key , sizeof ( base - > key . key ) ) ) {
2013-06-14 11:47:50 +04:00
if ( do_encrypt ) {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_encrypt (
creds ,
base - > key . key ,
sizeof ( base - > key . key ) ) ;
2012-12-14 17:18:40 +04:00
} else {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_decrypt (
creds ,
base - > key . key ,
sizeof ( base - > key . key ) ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2012-12-14 17:18:40 +04:00
}
2012-12-07 15:38:16 +04:00
}
2024-10-29 20:02:19 +03:00
if ( creds - > authenticate_kerberos | |
! all_zero ( base - > LMSessKey . key ,
2016-12-31 15:45:51 +03:00
sizeof ( base - > LMSessKey . key ) ) ) {
2013-06-14 11:47:50 +04:00
if ( do_encrypt ) {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_encrypt (
creds ,
base - > LMSessKey . key ,
sizeof ( base - > LMSessKey . key ) ) ;
2012-12-14 17:18:40 +04:00
} else {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_decrypt (
creds ,
base - > LMSessKey . key ,
sizeof ( base - > LMSessKey . key ) ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2012-12-14 17:18:40 +04:00
}
2012-12-07 15:38:16 +04:00
}
2005-10-09 16:38:23 +04:00
} else if ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
2024-10-29 20:02:19 +03:00
/*
* Don ' t crypt an all - zero key , it would give away
* the NETLOGON pipe session key
*
* But for ServerAuthenticateKerberos we don ' t care
* as we use a random key
*/
if ( creds - > authenticate_kerberos | |
! all_zero ( base - > key . key , sizeof ( base - > key . key ) ) ) {
2019-05-29 15:46:17 +03:00
status = netlogon_creds_arcfour_crypt ( creds ,
base - > key . key ,
sizeof ( base - > key . key ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2005-10-09 16:38:23 +04:00
}
2012-12-07 04:05:00 +04:00
2024-10-29 20:02:19 +03:00
if ( creds - > authenticate_kerberos | |
! all_zero ( base - > LMSessKey . key ,
2016-12-31 15:45:51 +03:00
sizeof ( base - > LMSessKey . key ) ) ) {
2019-05-29 15:46:17 +03:00
status = netlogon_creds_arcfour_crypt ( creds ,
base - > LMSessKey . key ,
sizeof ( base - > LMSessKey . key ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2005-10-09 16:38:23 +04:00
}
} else {
2024-10-29 20:02:19 +03:00
/*
* Don ' t crypt an all - zero key , it would give away
* the NETLOGON pipe session key
*
* But for ServerAuthenticateKerberos we don ' t care
* as we use a random key
*/
if ( creds - > authenticate_kerberos | |
! all_zero ( base - > LMSessKey . key ,
2016-12-31 15:45:51 +03:00
sizeof ( base - > LMSessKey . key ) ) ) {
2013-06-14 11:47:50 +04:00
if ( do_encrypt ) {
2019-11-07 14:53:52 +03:00
status = netlogon_creds_des_encrypt_LMKey ( creds ,
& base - > LMSessKey ) ;
2012-12-14 17:18:40 +04:00
} else {
2019-11-07 14:53:52 +03:00
status = netlogon_creds_des_decrypt_LMKey ( creds ,
& base - > LMSessKey ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2012-12-14 17:18:40 +04:00
}
2005-10-09 16:38:23 +04:00
}
}
2019-05-29 15:39:34 +03:00
return NT_STATUS_OK ;
2012-12-07 04:05:00 +04:00
}
2009-04-06 16:53:01 +04:00
2019-05-29 15:35:20 +03:00
NTSTATUS netlogon_creds_decrypt_samlogon_validation ( struct netlogon_creds_CredentialState * creds ,
uint16_t validation_level ,
2024-10-28 14:43:44 +03:00
union netr_Validation * validation ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
2012-12-14 17:18:40 +04:00
{
2019-05-29 15:39:34 +03:00
return netlogon_creds_crypt_samlogon_validation ( creds ,
validation_level ,
validation ,
2024-10-28 14:43:44 +03:00
auth_type ,
auth_level ,
2019-05-29 15:39:34 +03:00
false ) ;
2012-12-14 17:18:40 +04:00
}
2019-05-29 15:25:57 +03:00
NTSTATUS netlogon_creds_encrypt_samlogon_validation ( struct netlogon_creds_CredentialState * creds ,
uint16_t validation_level ,
2024-10-28 14:43:44 +03:00
union netr_Validation * validation ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
2012-12-14 17:18:40 +04:00
{
2019-05-29 15:39:34 +03:00
return netlogon_creds_crypt_samlogon_validation ( creds ,
validation_level ,
validation ,
2024-10-28 14:43:44 +03:00
auth_type ,
auth_level ,
2019-05-29 15:39:34 +03:00
true ) ;
2012-12-14 17:18:40 +04:00
}
2019-05-29 17:51:01 +03:00
static NTSTATUS netlogon_creds_crypt_samlogon_logon ( struct netlogon_creds_CredentialState * creds ,
enum netr_LogonInfoClass level ,
union netr_LogonLevel * logon ,
2024-10-28 14:55:12 +03:00
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
2019-05-29 17:51:01 +03:00
bool do_encrypt )
2013-04-25 19:01:00 +04:00
{
2019-05-29 15:46:17 +03:00
NTSTATUS status ;
2024-10-29 20:02:19 +03:00
bool skip_crypto = false ;
status = netlogon_creds_no_buffer_crypt ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2019-05-29 15:46:17 +03:00
2013-04-25 19:01:00 +04:00
if ( logon = = NULL ) {
2019-05-29 17:51:01 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2013-04-25 19:01:00 +04:00
}
switch ( level ) {
case NetlogonInteractiveInformation :
case NetlogonInteractiveTransitiveInformation :
case NetlogonServiceInformation :
case NetlogonServiceTransitiveInformation :
if ( logon - > password = = NULL ) {
2019-05-29 17:51:01 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2013-04-25 19:01:00 +04:00
}
2024-10-29 20:02:19 +03:00
if ( skip_crypto ) {
break ;
}
2013-04-25 19:01:00 +04:00
if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
uint8_t * h ;
h = logon - > password - > lmpassword . hash ;
2016-12-31 15:45:51 +03:00
if ( ! all_zero ( h , 16 ) ) {
2014-02-27 12:40:03 +04:00
if ( do_encrypt ) {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_encrypt (
creds ,
h ,
16 ) ;
2013-04-25 19:01:00 +04:00
} else {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_decrypt (
creds ,
h ,
16 ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2013-04-25 19:01:00 +04:00
}
}
h = logon - > password - > ntpassword . hash ;
2016-12-31 15:45:51 +03:00
if ( ! all_zero ( h , 16 ) ) {
2014-02-27 12:40:03 +04:00
if ( do_encrypt ) {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_encrypt ( creds ,
h ,
16 ) ;
2013-04-25 19:01:00 +04:00
} else {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_decrypt ( creds ,
h ,
16 ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2013-04-25 19:01:00 +04:00
}
}
} else if ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
uint8_t * h ;
h = logon - > password - > lmpassword . hash ;
2016-12-31 15:45:51 +03:00
if ( ! all_zero ( h , 16 ) ) {
2019-05-29 15:46:17 +03:00
status = netlogon_creds_arcfour_crypt ( creds ,
h ,
16 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2013-04-25 19:01:00 +04:00
}
h = logon - > password - > ntpassword . hash ;
2016-12-31 15:45:51 +03:00
if ( ! all_zero ( h , 16 ) ) {
2019-05-29 15:46:17 +03:00
status = netlogon_creds_arcfour_crypt ( creds ,
h ,
16 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2013-04-25 19:01:00 +04:00
}
} else {
struct samr_Password * p ;
p = & logon - > password - > lmpassword ;
2016-12-31 15:45:51 +03:00
if ( ! all_zero ( p - > hash , 16 ) ) {
2014-02-27 12:40:03 +04:00
if ( do_encrypt ) {
2019-11-20 18:02:16 +03:00
status = netlogon_creds_des_encrypt ( creds , p ) ;
2013-04-25 19:01:00 +04:00
} else {
2019-11-20 18:02:16 +03:00
status = netlogon_creds_des_decrypt ( creds , p ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2013-04-25 19:01:00 +04:00
}
}
p = & logon - > password - > ntpassword ;
2016-12-31 15:45:51 +03:00
if ( ! all_zero ( p - > hash , 16 ) ) {
2014-02-27 12:40:03 +04:00
if ( do_encrypt ) {
2019-11-20 18:02:16 +03:00
status = netlogon_creds_des_encrypt ( creds , p ) ;
2013-04-25 19:01:00 +04:00
} else {
2019-11-20 18:02:16 +03:00
status = netlogon_creds_des_decrypt ( creds , p ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2013-04-25 19:01:00 +04:00
}
}
}
break ;
case NetlogonNetworkInformation :
case NetlogonNetworkTransitiveInformation :
break ;
case NetlogonGenericInformation :
if ( logon - > generic = = NULL ) {
2019-05-29 17:51:01 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2013-04-25 19:01:00 +04:00
}
2024-10-29 20:02:19 +03:00
if ( skip_crypto ) {
break ;
}
2013-04-25 19:01:00 +04:00
if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
2014-02-27 12:40:03 +04:00
if ( do_encrypt ) {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_encrypt (
creds ,
logon - > generic - > data ,
logon - > generic - > length ) ;
2013-04-25 19:01:00 +04:00
} else {
2019-08-16 04:55:49 +03:00
status = netlogon_creds_aes_decrypt (
creds ,
logon - > generic - > data ,
logon - > generic - > length ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2013-04-25 19:01:00 +04:00
}
} else if ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
2019-05-29 15:46:17 +03:00
status = netlogon_creds_arcfour_crypt ( creds ,
logon - > generic - > data ,
logon - > generic - > length ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2024-10-29 20:02:19 +03:00
} else if ( auth_level ! = DCERPC_AUTH_LEVEL_PRIVACY ) {
/*
* Using DES to verify kerberos tickets makes no sense ,
* but if the connection is encrypted we don ' t care . . .
*/
2024-10-28 18:54:48 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2013-04-25 19:01:00 +04:00
}
break ;
2024-11-21 16:16:12 +03:00
case NetlogonTicketLogonInformation :
break ;
2013-04-25 19:01:00 +04:00
}
2019-05-29 17:51:01 +03:00
return NT_STATUS_OK ;
2013-04-25 19:01:00 +04:00
}
2019-05-29 17:49:29 +03:00
NTSTATUS netlogon_creds_decrypt_samlogon_logon ( struct netlogon_creds_CredentialState * creds ,
enum netr_LogonInfoClass level ,
2024-10-28 14:55:12 +03:00
union netr_LogonLevel * logon ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
2013-04-25 19:01:00 +04:00
{
2024-10-28 14:55:12 +03:00
return netlogon_creds_crypt_samlogon_logon ( creds ,
level ,
logon ,
auth_type ,
auth_level ,
false ) ;
2013-04-25 19:01:00 +04:00
}
2019-05-29 17:46:36 +03:00
NTSTATUS netlogon_creds_encrypt_samlogon_logon ( struct netlogon_creds_CredentialState * creds ,
enum netr_LogonInfoClass level ,
2024-10-28 14:55:12 +03:00
union netr_LogonLevel * logon ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
2013-04-25 19:01:00 +04:00
{
2024-10-28 14:55:12 +03:00
return netlogon_creds_crypt_samlogon_logon ( creds ,
level ,
logon ,
auth_type ,
auth_level ,
true ) ;
2013-04-25 19:01:00 +04:00
}
2024-10-28 15:03:37 +03:00
static NTSTATUS netlogon_creds_crypt_samr_Password (
struct netlogon_creds_CredentialState * creds ,
struct samr_Password * pass ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
bool do_encrypt )
{
2024-10-29 20:02:19 +03:00
NTSTATUS status ;
bool skip_crypto = false ;
status = netlogon_creds_no_buffer_crypt ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( skip_crypto ) {
return NT_STATUS_OK ;
}
2024-10-28 15:03:37 +03:00
if ( all_zero ( pass - > hash , ARRAY_SIZE ( pass - > hash ) ) ) {
return NT_STATUS_OK ;
}
/*
* Even with NETLOGON_NEG_SUPPORTS_AES or
* NETLOGON_NEG_ARCFOUR this uses DES
*/
if ( do_encrypt ) {
return netlogon_creds_des_encrypt ( creds , pass ) ;
}
return netlogon_creds_des_decrypt ( creds , pass ) ;
}
NTSTATUS netlogon_creds_decrypt_samr_Password ( struct netlogon_creds_CredentialState * creds ,
struct samr_Password * pass ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
{
return netlogon_creds_crypt_samr_Password ( creds ,
pass ,
auth_type ,
auth_level ,
false ) ;
}
NTSTATUS netlogon_creds_encrypt_samr_Password ( struct netlogon_creds_CredentialState * creds ,
struct samr_Password * pass ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
{
return netlogon_creds_crypt_samr_Password ( creds ,
pass ,
auth_type ,
auth_level ,
true ) ;
}
2024-10-28 15:12:24 +03:00
static NTSTATUS netlogon_creds_crypt_samr_CryptPassword (
struct netlogon_creds_CredentialState * creds ,
struct samr_CryptPassword * pass ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
bool do_encrypt )
{
2024-10-29 20:02:19 +03:00
NTSTATUS status ;
bool skip_crypto = false ;
status = netlogon_creds_no_buffer_crypt ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( skip_crypto ) {
return NT_STATUS_OK ;
}
2024-10-28 15:12:24 +03:00
if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
if ( do_encrypt ) {
return netlogon_creds_aes_encrypt ( creds ,
pass - > data ,
ARRAY_SIZE ( pass - > data ) ) ;
}
return netlogon_creds_aes_decrypt ( creds ,
pass - > data ,
ARRAY_SIZE ( pass - > data ) ) ;
}
2024-10-29 20:02:19 +03:00
if ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
return netlogon_creds_arcfour_crypt ( creds ,
pass - > data ,
ARRAY_SIZE ( pass - > data ) ) ;
}
/*
* Using DES to verify to encrypt the password makes no sense ,
* but if the connection is encrypted we don ' t care . . .
*/
if ( auth_level ! = DCERPC_AUTH_LEVEL_PRIVACY ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return NT_STATUS_OK ;
2024-10-28 15:12:24 +03:00
}
NTSTATUS netlogon_creds_decrypt_samr_CryptPassword ( struct netlogon_creds_CredentialState * creds ,
struct samr_CryptPassword * pass ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
{
return netlogon_creds_crypt_samr_CryptPassword ( creds ,
pass ,
auth_type ,
auth_level ,
false ) ;
}
NTSTATUS netlogon_creds_encrypt_samr_CryptPassword ( struct netlogon_creds_CredentialState * creds ,
struct samr_CryptPassword * pass ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
{
return netlogon_creds_crypt_samr_CryptPassword ( creds ,
pass ,
auth_type ,
auth_level ,
true ) ;
}
2024-10-28 15:13:50 +03:00
static NTSTATUS netlogon_creds_crypt_SendToSam (
struct netlogon_creds_CredentialState * creds ,
uint8_t * opaque_data ,
size_t opaque_length ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level ,
bool do_encrypt )
{
2024-10-29 20:02:19 +03:00
NTSTATUS status ;
bool skip_crypto = false ;
status = netlogon_creds_no_buffer_crypt ( creds ,
auth_type ,
auth_level ,
& skip_crypto ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( skip_crypto ) {
return NT_STATUS_OK ;
}
2024-10-28 15:13:50 +03:00
if ( creds - > negotiate_flags & NETLOGON_NEG_SUPPORTS_AES ) {
if ( do_encrypt ) {
return netlogon_creds_aes_encrypt ( creds ,
opaque_data ,
opaque_length ) ;
}
return netlogon_creds_aes_decrypt ( creds ,
opaque_data ,
opaque_length ) ;
}
2024-10-29 20:02:19 +03:00
if ( creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
return netlogon_creds_arcfour_crypt ( creds ,
opaque_data ,
opaque_length ) ;
}
/*
* Using DES to verify to encrypt the data makes no sense ,
* but if the connection is encrypted we don ' t care . . .
*/
if ( auth_level ! = DCERPC_AUTH_LEVEL_PRIVACY ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return NT_STATUS_OK ;
2024-10-28 15:13:50 +03:00
}
NTSTATUS netlogon_creds_decrypt_SendToSam ( struct netlogon_creds_CredentialState * creds ,
uint8_t * opaque_data ,
size_t opaque_length ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
{
return netlogon_creds_crypt_SendToSam ( creds ,
opaque_data ,
opaque_length ,
auth_type ,
auth_level ,
false ) ;
}
NTSTATUS netlogon_creds_encrypt_SendToSam ( struct netlogon_creds_CredentialState * creds ,
uint8_t * opaque_data ,
size_t opaque_length ,
enum dcerpc_AuthType auth_type ,
enum dcerpc_AuthLevel auth_level )
{
return netlogon_creds_crypt_SendToSam ( creds ,
opaque_data ,
opaque_length ,
auth_type ,
auth_level ,
true ) ;
}
2013-04-24 14:53:27 +04:00
union netr_LogonLevel * netlogon_creds_shallow_copy_logon ( TALLOC_CTX * mem_ctx ,
enum netr_LogonInfoClass level ,
const union netr_LogonLevel * in )
{
union netr_LogonLevel * out ;
if ( in = = NULL ) {
return NULL ;
}
out = talloc ( mem_ctx , union netr_LogonLevel ) ;
if ( out = = NULL ) {
return NULL ;
}
* out = * in ;
switch ( level ) {
case NetlogonInteractiveInformation :
case NetlogonInteractiveTransitiveInformation :
case NetlogonServiceInformation :
case NetlogonServiceTransitiveInformation :
if ( in - > password = = NULL ) {
return out ;
}
out - > password = talloc ( out , struct netr_PasswordInfo ) ;
if ( out - > password = = NULL ) {
talloc_free ( out ) ;
return NULL ;
}
* out - > password = * in - > password ;
return out ;
case NetlogonNetworkInformation :
case NetlogonNetworkTransitiveInformation :
break ;
case NetlogonGenericInformation :
if ( in - > generic = = NULL ) {
return out ;
}
out - > generic = talloc ( out , struct netr_GenericInfo ) ;
if ( out - > generic = = NULL ) {
talloc_free ( out ) ;
return NULL ;
}
* out - > generic = * in - > generic ;
if ( in - > generic - > data = = NULL ) {
return out ;
}
if ( in - > generic - > length = = 0 ) {
return out ;
}
out - > generic - > data = talloc_memdup ( out - > generic ,
in - > generic - > data ,
in - > generic - > length ) ;
if ( out - > generic - > data = = NULL ) {
talloc_free ( out ) ;
return NULL ;
}
return out ;
2024-11-21 16:16:12 +03:00
case NetlogonTicketLogonInformation :
break ;
2013-04-24 14:53:27 +04:00
}
return out ;
}
2010-08-23 18:02:23 +04:00
/*
copy a netlogon_creds_CredentialState struct
*/
2017-09-07 13:34:03 +03:00
struct netlogon_creds_CredentialState * netlogon_creds_copy (
TALLOC_CTX * mem_ctx ,
const struct netlogon_creds_CredentialState * creds_in )
2010-08-23 18:02:23 +04:00
{
struct netlogon_creds_CredentialState * creds = talloc_zero ( mem_ctx , struct netlogon_creds_CredentialState ) ;
2023-07-19 22:04:53 +03:00
enum ndr_err_code ndr_err ;
2010-08-23 18:02:23 +04:00
if ( ! creds ) {
return NULL ;
}
2023-07-19 22:04:53 +03:00
ndr_err = ndr_deepcopy_struct ( netlogon_creds_CredentialState ,
creds_in , creds , creds ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
TALLOC_FREE ( creds ) ;
2010-08-23 18:02:23 +04:00
return NULL ;
}
return creds ;
}