2017-07-09 22:46:26 +03:00
# Unix SMB/CIFS implementation.
# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
# Copyright (C) Catalyst IT Ltd. 2017
#
# 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
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Tests that exercise auth logging for unsuccessful netlogon attempts .
NOTE : netlogon is only done once per session , so this file should only
test failed logons . Adding a successful case will potentially break
the other tests , depending on the order of execution .
"""
import samba . tests
import os
from samba import NTSTATUSError
from samba . samdb import SamDB
import samba . tests . auth_log_base
from samba . credentials import Credentials
from samba . dcerpc import netlogon
from samba . dcerpc . dcerpc import AS_SYSTEM_MAGIC_PATH_TOKEN
from samba . auth import system_session
from samba . tests import delete_force
from samba . dsdb import UF_WORKSTATION_TRUST_ACCOUNT , UF_PASSWD_NOTREQD
from samba . dcerpc . misc import SEC_CHAN_WKSTA
2017-07-18 00:03:17 +03:00
from samba . dcerpc . netlogon import NETLOGON_NEG_STRONG_KEYS
2018-11-05 12:38:23 +03:00
from samba . compat import get_string
2018-12-13 04:46:31 +03:00
from samba . dcerpc . windows_event_ids import (
EVT_ID_UNSUCCESSFUL_LOGON ,
EVT_LOGON_NETWORK
)
2017-07-09 22:46:26 +03:00
2018-04-30 01:35:25 +03:00
2017-07-09 22:46:26 +03:00
class AuthLogTestsNetLogonBadCreds ( samba . tests . auth_log_base . AuthLogTestBase ) :
def setUp ( self ) :
super ( AuthLogTestsNetLogonBadCreds , self ) . setUp ( )
2018-12-17 00:04:42 +03:00
self . lp = samba . tests . env_loadparm ( )
2017-07-09 22:46:26 +03:00
self . session = system_session ( )
self . ldb = SamDB (
session_info = self . session ,
lp = self . lp )
2018-12-17 00:04:42 +03:00
self . domain = os . environ [ " DOMAIN " ]
self . netbios_name = " NetLogonBad "
self . machinepass = " abcdefghij "
2017-07-09 22:46:26 +03:00
self . remoteAddress = AS_SYSTEM_MAGIC_PATH_TOKEN
2018-12-17 00:04:42 +03:00
self . base_dn = self . ldb . domain_dn ( )
self . dn = ( " cn= %s ,cn=users, %s " % ( self . netbios_name , self . base_dn ) )
2017-07-09 22:46:26 +03:00
2018-11-05 12:38:23 +03:00
utf16pw = get_string ( ' " ' + self . machinepass + ' " ' ) . encode ( ' utf-16-le ' )
2017-07-09 22:46:26 +03:00
self . ldb . add ( {
" dn " : self . dn ,
" objectclass " : " computer " ,
" sAMAccountName " : " %s $ " % self . netbios_name ,
" userAccountControl " :
str ( UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD ) ,
" unicodePwd " : utf16pw } )
def tearDown ( self ) :
super ( AuthLogTestsNetLogonBadCreds , self ) . tearDown ( )
delete_force ( self . ldb , self . dn )
2018-12-13 00:20:28 +03:00
def _test_netlogon ( self , name , pwd , status , checkFunction , event_id ) :
2017-07-09 22:46:26 +03:00
def isLastExpectedMessage ( msg ) :
return (
msg [ " type " ] == " Authentication " and
msg [ " Authentication " ] [ " serviceDescription " ] == " NETLOGON " and
msg [ " Authentication " ] [ " authDescription " ] ==
" ServerAuthenticate " and
2018-12-13 00:20:28 +03:00
msg [ " Authentication " ] [ " status " ] == status and
2018-12-13 04:46:31 +03:00
msg [ " Authentication " ] [ " eventId " ] == event_id and
msg [ " Authentication " ] [ " logonType " ] == EVT_LOGON_NETWORK )
2017-07-09 22:46:26 +03:00
machine_creds = Credentials ( )
machine_creds . guess ( self . get_loadparm ( ) )
machine_creds . set_secure_channel_type ( SEC_CHAN_WKSTA )
machine_creds . set_password ( pwd )
machine_creds . set_username ( name + " $ " )
try :
netlogon . netlogon ( " ncalrpc:[schannel] " ,
self . get_loadparm ( ) ,
machine_creds )
self . fail ( " NTSTATUSError not raised " )
except NTSTATUSError :
pass
messages = self . waitForMessages ( isLastExpectedMessage )
checkFunction ( messages )
def netlogon_check ( self , messages ) :
expected_messages = 4
self . assertEquals ( expected_messages ,
len ( messages ) ,
" Did not receive the expected number of messages " )
# Check the first message it should be an Authorization
msg = messages [ 0 ]
self . assertEquals ( " Authorization " , msg [ " type " ] )
self . assertEquals ( " DCE/RPC " ,
msg [ " Authorization " ] [ " serviceDescription " ] )
self . assertEquals ( " ncalrpc " , msg [ " Authorization " ] [ " authType " ] )
self . assertEquals ( " NONE " , msg [ " Authorization " ] [ " transportProtection " ] )
2018-04-30 00:13:58 +03:00
self . assertTrue ( self . is_guid ( msg [ " Authorization " ] [ " sessionId " ] ) )
2017-07-09 22:46:26 +03:00
def test_netlogon_bad_machine_name ( self ) :
self . _test_netlogon ( " bad_name " ,
self . machinepass ,
" NT_STATUS_NO_TRUST_SAM_ACCOUNT " ,
2018-12-13 00:20:28 +03:00
self . netlogon_check ,
EVT_ID_UNSUCCESSFUL_LOGON )
2017-07-09 22:46:26 +03:00
def test_netlogon_bad_password ( self ) :
self . _test_netlogon ( self . netbios_name ,
" badpass " ,
" NT_STATUS_ACCESS_DENIED " ,
2018-12-13 00:20:28 +03:00
self . netlogon_check ,
EVT_ID_UNSUCCESSFUL_LOGON )
2017-07-09 22:46:26 +03:00
def test_netlogon_password_DES ( self ) :
""" Logon failure that exercises the " DES " passwordType path.
"""
def isLastExpectedMessage ( msg ) :
return (
msg [ " type " ] == " Authentication " and
msg [ " Authentication " ] [ " serviceDescription " ] == " NETLOGON " and
msg [ " Authentication " ] [ " authDescription " ] ==
" ServerAuthenticate " and
2018-12-13 00:20:28 +03:00
msg [ " Authentication " ] [ " passwordType " ] == " DES " and
2018-12-17 00:04:42 +03:00
( msg [ " Authentication " ] [ " eventId " ] ==
EVT_ID_UNSUCCESSFUL_LOGON ) and
2018-12-13 04:46:31 +03:00
msg [ " Authentication " ] [ " logonType " ] == EVT_LOGON_NETWORK )
2017-07-09 22:46:26 +03:00
c = netlogon . netlogon ( " ncalrpc:[schannel] " , self . get_loadparm ( ) )
creds = netlogon . netr_Credential ( )
c . netr_ServerReqChallenge ( self . server , self . netbios_name , creds )
try :
c . netr_ServerAuthenticate3 ( self . server ,
self . netbios_name ,
SEC_CHAN_WKSTA ,
self . netbios_name ,
creds ,
0 )
except NTSTATUSError :
pass
self . waitForMessages ( isLastExpectedMessage )
def test_netlogon_password_HMAC_MD5 ( self ) :
""" Logon failure that exercises the " HMAC-MD5 " passwordType path.
"""
def isLastExpectedMessage ( msg ) :
return (
msg [ " type " ] == " Authentication " and
msg [ " Authentication " ] [ " serviceDescription " ] == " NETLOGON " and
msg [ " Authentication " ] [ " authDescription " ] ==
" ServerAuthenticate " and
2018-12-13 00:20:28 +03:00
msg [ " Authentication " ] [ " passwordType " ] == " HMAC-MD5 " and
2018-12-13 04:46:31 +03:00
( msg [ " Authentication " ] [ " eventId " ] ==
EVT_ID_UNSUCCESSFUL_LOGON ) and
msg [ " Authentication " ] [ " logonType " ] == EVT_LOGON_NETWORK )
2018-12-13 00:20:28 +03:00
2017-07-09 22:46:26 +03:00
c = netlogon . netlogon ( " ncalrpc:[schannel] " , self . get_loadparm ( ) )
creds = netlogon . netr_Credential ( )
c . netr_ServerReqChallenge ( self . server , self . netbios_name , creds )
try :
c . netr_ServerAuthenticate3 ( self . server ,
self . netbios_name ,
SEC_CHAN_WKSTA ,
self . netbios_name ,
creds ,
2017-07-18 00:03:17 +03:00
NETLOGON_NEG_STRONG_KEYS )
2017-07-09 22:46:26 +03:00
except NTSTATUSError :
pass
self . waitForMessages ( isLastExpectedMessage )