2005-04-08 08:57:09 +00:00
/*
Unix SMB / CIFS implementation .
NBT datagram netlogon server
Copyright ( C ) Andrew Tridgell 2005
2008-05-17 13:24:29 +10:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2008
2005-04-08 08:57:09 +00: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 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-04-08 08:57:09 +00:00
( 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-04-08 08:57:09 +00:00
*/
# include "includes.h"
# include "nbt_server/nbt_server.h"
# include "lib/socket/socket.h"
2011-02-10 14:12:51 +11:00
# include <ldb.h>
2005-12-28 15:38:36 +00:00
# include "dsdb/samdb/samdb.h"
# include "auth/auth.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2020-11-20 15:27:17 +01:00
# include "samba/service_task.h"
2013-11-05 20:39:56 +01:00
# include "dsdb/samdb/ldb_modules/util.h"
2008-05-17 20:53:29 +10:00
# include "libcli/security/security.h"
2008-10-20 18:59:51 +02:00
# include "nbt_server/dgram/proto.h"
2015-12-28 19:01:54 +00:00
# include "libds/common/roles.h"
2005-04-08 08:57:09 +00:00
2005-04-10 23:09:38 +00:00
/*
reply to a GETDC request
*/
2018-02-17 17:16:07 +01:00
static NTSTATUS nbtd_netlogon_getdc ( struct nbtd_server * nbtsrv ,
2018-02-17 17:25:03 +01:00
struct nbt_name * dst_name ,
2018-02-17 17:05:09 +01:00
struct nbt_netlogon_packet * netlogon ,
TALLOC_CTX * mem_ctx ,
2018-02-17 21:02:41 +01:00
struct nbt_netlogon_response * * presponse ,
char * * preply_mailslot )
2005-04-10 23:09:38 +00:00
{
struct nbt_netlogon_response_from_pdc * pdc ;
2005-08-03 18:30:21 +00:00
struct ldb_context * samctx ;
2018-02-17 21:02:41 +01:00
struct nbt_netlogon_response * response = NULL ;
char * reply_mailslot = NULL ;
2005-04-10 23:09:38 +00:00
2008-05-17 20:53:29 +10:00
/* only answer getdc requests on the PDC or LOGON names */
2018-02-17 17:25:03 +01:00
if ( ( dst_name - > type ! = NBT_NAME_PDC ) & &
( dst_name - > type ! = NBT_NAME_LOGON ) ) {
2018-02-17 17:05:09 +01:00
return NT_STATUS_NOT_SUPPORTED ;
2005-04-10 23:09:38 +00:00
}
2018-02-17 17:16:07 +01:00
samctx = nbtsrv - > sam_ctx ;
2009-06-01 13:42:51 +10:00
2018-02-17 17:16:07 +01:00
if ( lpcfg_server_role ( nbtsrv - > task - > lp_ctx ) ! = ROLE_ACTIVE_DIRECTORY_DC
2009-05-26 12:31:39 +10:00
| | ! samdb_is_pdc ( samctx ) ) {
2008-05-17 20:53:29 +10:00
DEBUG ( 2 , ( " Not a PDC, so not processing LOGON_PRIMARY_QUERY \n " ) ) ;
2018-02-17 17:05:09 +01:00
return NT_STATUS_NOT_SUPPORTED ;
2008-05-17 20:53:29 +10:00
}
2018-02-17 17:25:03 +01:00
if ( strcasecmp_m ( dst_name - > name ,
lpcfg_workgroup ( nbtsrv - > task - > lp_ctx ) ) ! = 0 ) {
2018-02-17 17:22:11 +01:00
DBG_INFO ( " GetDC requested for a domain %s that we don't "
2018-02-17 17:25:03 +01:00
" host \n " , dst_name - > name ) ;
2018-02-17 17:05:09 +01:00
return NT_STATUS_NOT_SUPPORTED ;
2005-08-03 18:30:21 +00:00
}
2018-02-17 21:02:41 +01:00
reply_mailslot = talloc_strdup (
mem_ctx , netlogon - > req . pdc . mailslot_name ) ;
if ( reply_mailslot = = NULL ) {
goto nomem ;
}
2005-04-10 23:09:38 +00:00
/* setup a GETDC reply */
2018-02-17 17:05:09 +01:00
response = talloc_zero ( mem_ctx , struct nbt_netlogon_response ) ;
if ( response = = NULL ) {
2018-02-17 21:02:41 +01:00
goto nomem ;
2018-02-17 17:05:09 +01:00
}
response - > response_type = NETLOGON_GET_PDC ;
pdc = & response - > data . get_pdc ;
2005-04-10 23:09:38 +00:00
2008-05-17 13:24:29 +10:00
pdc - > command = NETLOGON_RESPONSE_FROM_PDC ;
2018-02-17 17:05:09 +01:00
pdc - > pdc_name = talloc_strdup (
2018-02-17 17:16:07 +01:00
response , lpcfg_netbios_name ( nbtsrv - > task - > lp_ctx ) ) ;
2018-02-17 17:05:09 +01:00
if ( pdc - > pdc_name = = NULL ) {
2018-02-17 21:02:41 +01:00
goto nomem ;
2018-02-17 17:05:09 +01:00
}
2005-04-10 23:09:38 +00:00
pdc - > unicode_pdc_name = pdc - > pdc_name ;
2018-02-17 17:05:09 +01:00
pdc - > domain_name = talloc_strdup (
2018-02-17 17:16:07 +01:00
response , lpcfg_workgroup ( nbtsrv - > task - > lp_ctx ) ) ;
2018-02-17 17:05:09 +01:00
if ( pdc - > domain_name = = NULL ) {
2018-02-17 21:02:41 +01:00
goto nomem ;
2018-02-17 17:05:09 +01:00
}
2005-04-10 23:09:38 +00:00
pdc - > nt_version = 1 ;
pdc - > lmnt_token = 0xFFFF ;
pdc - > lm20_token = 0xFFFF ;
2018-02-17 17:05:09 +01:00
* presponse = response ;
2018-02-17 21:02:41 +01:00
* preply_mailslot = reply_mailslot ;
2018-02-17 17:05:09 +01:00
return NT_STATUS_OK ;
2018-02-17 21:02:41 +01:00
nomem :
TALLOC_FREE ( response ) ;
TALLOC_FREE ( reply_mailslot ) ;
return NT_STATUS_NO_MEMORY ;
2005-04-10 23:09:38 +00:00
}
2005-04-14 07:40:23 +00:00
/*
reply to a ADS style GETDC request
*/
2018-02-17 17:05:09 +01:00
static NTSTATUS nbtd_netlogon_samlogon (
2018-02-17 17:18:29 +01:00
struct nbtd_server * nbtsrv ,
2018-02-17 17:33:32 +01:00
struct nbt_name * dst_name ,
2018-02-17 17:05:09 +01:00
const struct socket_address * src ,
struct nbt_netlogon_packet * netlogon ,
TALLOC_CTX * mem_ctx ,
2018-02-17 21:02:41 +01:00
struct nbt_netlogon_response * * presponse ,
char * * preply_mailslot )
2005-04-14 07:40:23 +00:00
{
struct ldb_context * samctx ;
2018-02-17 20:04:23 +01:00
struct dom_sid * sid = NULL ;
2018-02-17 21:02:41 +01:00
struct nbt_netlogon_response * response = NULL ;
char * reply_mailslot = NULL ;
2008-05-17 13:24:29 +10:00
NTSTATUS status ;
2005-04-14 07:40:23 +00:00
/* only answer getdc requests on the PDC or LOGON names */
2018-02-17 17:33:32 +01:00
if ( ( dst_name - > type ! = NBT_NAME_PDC ) & &
( dst_name - > type ! = NBT_NAME_LOGON ) ) {
2018-02-17 17:05:09 +01:00
return NT_STATUS_NOT_SUPPORTED ;
2005-04-14 07:40:23 +00:00
}
2018-02-17 17:18:29 +01:00
samctx = nbtsrv - > sam_ctx ;
2005-04-14 07:40:23 +00:00
2018-02-17 20:04:23 +01:00
if ( netlogon - > req . logon . sid_size ! = 0 ) {
2008-05-17 13:24:29 +10:00
sid = & netlogon - > req . logon . sid ;
2005-08-03 18:30:21 +00:00
}
2018-02-17 21:02:41 +01:00
reply_mailslot = talloc_strdup (
mem_ctx , netlogon - > req . logon . mailslot_name ) ;
if ( reply_mailslot = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2018-02-17 17:05:09 +01:00
response = talloc_zero ( mem_ctx , struct nbt_netlogon_response ) ;
if ( response = = NULL ) {
2018-02-17 21:02:41 +01:00
TALLOC_FREE ( reply_mailslot ) ;
2018-02-17 17:05:09 +01:00
return NT_STATUS_NO_MEMORY ;
}
response - > response_type = NETLOGON_SAMLOGON ;
status = fill_netlogon_samlogon_response (
2018-02-17 17:33:32 +01:00
samctx , response , NULL , dst_name - > name , sid , NULL ,
2018-02-17 17:05:09 +01:00
netlogon - > req . logon . user_name ,
netlogon - > req . logon . acct_control , src - > addr ,
2018-02-17 17:18:29 +01:00
netlogon - > req . logon . nt_version , nbtsrv - > task - > lp_ctx ,
2018-02-17 17:05:09 +01:00
& response - > data . samlogon , false ) ;
2008-05-17 13:24:29 +10:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2018-10-18 05:55:04 +02:00
struct dom_sid_buf buf ;
2018-02-17 20:06:36 +01:00
2018-02-17 17:33:32 +01:00
DBG_NOTICE ( " NBT netlogon query failed domain=%s sid=%s "
2018-10-18 05:55:04 +02:00
" version=%d - %s \n " ,
dst_name - > name ,
dom_sid_str_buf ( sid , & buf ) ,
netlogon - > req . logon . nt_version ,
nt_errstr ( status ) ) ;
2018-02-17 21:02:41 +01:00
TALLOC_FREE ( reply_mailslot ) ;
2018-02-17 17:05:09 +01:00
TALLOC_FREE ( response ) ;
return status ;
2005-04-14 07:40:23 +00:00
}
2018-02-17 17:05:09 +01:00
* presponse = response ;
2018-02-17 21:02:41 +01:00
* preply_mailslot = reply_mailslot ;
2018-02-17 17:05:09 +01:00
return NT_STATUS_OK ;
2005-04-14 07:40:23 +00:00
}
2018-02-17 21:02:41 +01:00
static NTSTATUS nbtd_mailslot_netlogon_reply (
struct nbtd_interface * iface ,
struct nbt_dgram_packet * packet ,
struct socket_address * src ,
TALLOC_CTX * mem_ctx ,
struct nbt_netlogon_response * * presponse ,
char * * preply_mailslot )
2005-04-08 08:57:09 +00:00
{
2018-02-17 21:02:41 +01:00
struct nbt_netlogon_packet * netlogon ;
struct nbt_name * dst_name = & packet - > data . msg . dest_name ;
struct nbt_netlogon_response * response = NULL ;
2005-04-10 23:09:38 +00:00
struct nbtd_iface_name * iname ;
2018-02-17 21:02:41 +01:00
char * reply_mailslot = NULL ;
NTSTATUS status ;
2005-04-08 08:57:09 +00:00
2005-04-10 23:09:38 +00:00
/*
see if the we are listening on the destination netbios name
*/
2018-02-17 21:02:41 +01:00
iname = nbtd_find_iname ( iface , dst_name , 0 ) ;
2005-04-10 23:09:38 +00:00
if ( iname = = NULL ) {
2018-02-17 21:02:41 +01:00
return NT_STATUS_BAD_NETWORK_NAME ;
}
netlogon = talloc ( mem_ctx , struct nbt_netlogon_packet ) ;
if ( netlogon = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2005-04-10 23:09:38 +00:00
}
2018-02-17 20:42:19 +01:00
status = dgram_mailslot_netlogon_parse_request ( netlogon , packet ,
netlogon ) ;
2018-02-17 21:02:41 +01:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
2005-04-08 08:57:09 +00:00
2005-04-10 23:09:38 +00:00
switch ( netlogon - > command ) {
2008-05-17 13:24:29 +10:00
case LOGON_PRIMARY_QUERY :
2018-02-17 21:02:41 +01:00
status = nbtd_netlogon_getdc (
iface - > nbtsrv , & packet - > data . msg . dest_name ,
netlogon , mem_ctx , & response , & reply_mailslot ) ;
2005-04-10 23:09:38 +00:00
break ;
2008-05-17 13:24:29 +10:00
case LOGON_SAM_LOGON_REQUEST :
2018-02-17 17:33:32 +01:00
status = nbtd_netlogon_samlogon (
iface - > nbtsrv , & packet - > data . msg . dest_name , src ,
2018-02-17 21:02:41 +01:00
netlogon , mem_ctx , & response , & reply_mailslot ) ;
2005-04-14 07:40:23 +00:00
break ;
2005-04-10 23:09:38 +00:00
default :
2018-02-17 21:02:41 +01:00
DEBUG ( 2 , ( " unknown netlogon op %d from %s:%d \n " ,
2005-10-14 12:56:13 +00:00
netlogon - > command , src - > addr , src - > port ) ) ;
2005-05-05 11:14:12 +00:00
NDR_PRINT_DEBUG ( nbt_netlogon_packet , netlogon ) ;
2018-02-17 17:05:09 +01:00
status = NT_STATUS_NOT_SUPPORTED ;
2005-04-10 23:09:38 +00:00
break ;
}
2018-02-17 21:02:41 +01:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_DEBUG ( " Calculating reply failed: %s \n " ,
nt_errstr ( status ) ) ;
goto failed ;
}
* presponse = response ;
* preply_mailslot = reply_mailslot ;
return NT_STATUS_OK ;
failed :
TALLOC_FREE ( reply_mailslot ) ;
TALLOC_FREE ( netlogon ) ;
return status ;
}
/*
handle incoming netlogon mailslot requests
*/
void nbtd_mailslot_netlogon_handler ( struct dgram_mailslot_handler * dgmslot ,
struct nbt_dgram_packet * packet ,
struct socket_address * src )
{
NTSTATUS status = NT_STATUS_NO_MEMORY ;
struct nbtd_interface * iface =
talloc_get_type ( dgmslot - > private_data , struct nbtd_interface ) ;
struct nbtd_interface * reply_iface = nbtd_find_reply_iface (
iface , src - > addr , false ) ;
struct nbt_netlogon_response * response = NULL ;
char * reply_mailslot = NULL ;
if ( reply_iface - > ip_address = = NULL ) {
DBG_WARNING ( " Could not obtain own IP address for datagram "
" socket \n " ) ;
return ;
}
status = nbtd_mailslot_netlogon_reply (
iface , packet , src , dgmslot , & response , & reply_mailslot ) ;
2018-02-17 17:05:09 +01:00
if ( NT_STATUS_IS_OK ( status ) ) {
dgram_mailslot_netlogon_reply (
reply_iface - > dgmsock , packet ,
lpcfg_netbios_name ( iface - > nbtsrv - > task - > lp_ctx ) ,
2018-02-17 21:02:41 +01:00
reply_mailslot , response ) ;
2018-02-17 17:05:09 +01:00
}
2018-02-17 21:02:41 +01:00
TALLOC_FREE ( response ) ;
TALLOC_FREE ( reply_mailslot ) ;
2005-04-08 08:57:09 +00:00
}