2005-05-12 12:28:07 +04:00
/*
Unix SMB / CIFS implementation .
CLDAP server - netlogon handling
Copyright ( C ) Andrew Tridgell 2005
2008-05-17 06:41:42 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2008
2005-05-12 12:28:07 +04: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
2005-05-12 12:28:07 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-05-12 12:28:07 +04:00
*/
# include "includes.h"
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2005-05-12 12:28:07 +04:00
# include "lib/events/events.h"
# include "smbd/service_task.h"
# include "cldap_server/cldap_server.h"
2006-03-18 18:42:57 +03:00
# include "librpc/gen_ndr/ndr_misc.h"
2008-04-14 13:54:50 +04:00
# include "libcli/ldap/ldap_ndr.h"
2008-05-17 06:41:42 +04:00
# include "libcli/security/security.h"
2005-12-28 18:38:36 +03:00
# include "dsdb/samdb/samdb.h"
# include "auth/auth.h"
2007-11-16 22:12:00 +03:00
# include "ldb_wrap.h"
2006-03-07 14:07:23 +03:00
# include "system/network.h"
2006-08-17 17:37:04 +04:00
# include "lib/socket/netif.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2009-02-13 15:13:54 +03:00
# include "../lib/tsocket/tsocket.h"
2011-02-24 03:23:53 +03:00
# include "libds/common/flag_mapping.h"
2009-02-13 15:13:54 +03:00
2005-05-12 12:28:07 +04:00
/*
fill in the cldap netlogon union for a given version
*/
2008-05-17 06:41:42 +04:00
NTSTATUS fill_netlogon_samlogon_response ( struct ldb_context * sam_ctx ,
TALLOC_CTX * mem_ctx ,
const char * domain ,
2008-05-17 14:53:29 +04:00
const char * netbios_domain ,
2008-05-17 06:41:42 +04:00
struct dom_sid * domain_sid ,
const char * domain_guid ,
const char * user ,
2008-05-21 06:37:36 +04:00
uint32_t acct_control ,
2008-05-17 06:41:42 +04:00
const char * src_address ,
uint32_t version ,
struct loadparm_context * lp_ctx ,
2010-04-27 17:39:57 +04:00
struct netlogon_samlogon_response * netlogon ,
bool fill_on_blank_request )
2005-05-12 12:28:07 +04:00
{
2006-08-19 02:20:13 +04:00
const char * dom_attrs [ ] = { " objectGUID " , NULL } ;
2008-05-21 06:37:36 +04:00
const char * none_attrs [ ] = { NULL } ;
2009-05-26 06:31:39 +04:00
struct ldb_result * dom_res = NULL , * user_res = NULL ;
2007-11-14 00:30:33 +03:00
int ret ;
2010-07-16 08:32:42 +04:00
const char * * services = lpcfg_server_services ( lp_ctx ) ;
2005-05-12 12:28:07 +04:00
uint32_t server_type ;
const char * pdc_name ;
struct GUID domain_uuid ;
const char * dns_domain ;
2010-04-12 17:02:10 +04:00
const char * forest_domain ;
2005-05-12 12:28:07 +04:00
const char * pdc_dns_name ;
const char * flatname ;
2006-11-13 22:12:47 +03:00
const char * server_site ;
const char * client_site ;
2005-05-12 12:28:07 +04:00
const char * pdc_ip ;
2009-05-26 06:31:39 +04:00
struct ldb_dn * domain_dn = NULL ;
2007-12-12 00:23:14 +03:00
struct interface * ifaces ;
2010-09-14 09:48:19 +04:00
bool user_known , am_rodc ;
2008-08-21 10:09:42 +04:00
NTSTATUS status ;
2005-05-12 12:28:07 +04:00
2010-04-13 17:18:02 +04:00
/* the domain parameter could have an optional trailing "." */
2005-05-16 15:17:57 +04:00
if ( domain & & domain [ strlen ( domain ) - 1 ] = = ' . ' ) {
2005-05-12 13:03:14 +04:00
domain = talloc_strndup ( mem_ctx , domain , strlen ( domain ) - 1 ) ;
2010-04-13 11:25:26 +04:00
NT_STATUS_HAVE_NO_MEMORY ( domain ) ;
2005-05-12 13:03:14 +04:00
}
2010-04-13 17:18:02 +04:00
/* Lookup using long or short domainname */
2010-07-16 08:32:42 +04:00
if ( domain & & ( strcasecmp_m ( domain , lpcfg_dnsdomain ( lp_ctx ) ) = = 0 ) ) {
2009-05-26 06:31:39 +04:00
domain_dn = ldb_get_default_basedn ( sam_ctx ) ;
2006-06-15 03:32:19 +04:00
}
2010-07-16 08:32:42 +04:00
if ( netbios_domain & & ( strcasecmp_m ( netbios_domain , lpcfg_sam_name ( lp_ctx ) ) = = 0 ) ) {
2009-05-26 06:31:39 +04:00
domain_dn = ldb_get_default_basedn ( sam_ctx ) ;
}
if ( domain_dn ) {
2010-04-13 17:18:02 +04:00
const char * domain_identifier = domain ! = NULL ? domain
: netbios_domain ;
2009-05-26 06:31:39 +04:00
ret = ldb_search ( sam_ctx , mem_ctx , & dom_res ,
domain_dn , LDB_SCOPE_BASE , dom_attrs ,
" objectClass=domain " ) ;
2008-05-17 14:53:29 +04:00
if ( ret ! = LDB_SUCCESS ) {
2010-04-13 17:18:02 +04:00
DEBUG ( 2 , ( " Error finding domain '%s'/'%s' in sam: %s \n " ,
domain_identifier ,
ldb_dn_get_linearized ( domain_dn ) ,
ldb_errstring ( sam_ctx ) ) ) ;
2008-05-17 14:53:29 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
2009-05-26 06:31:39 +04:00
}
if ( dom_res - > count ! = 1 ) {
2010-04-13 17:18:02 +04:00
DEBUG ( 2 , ( " Error finding domain '%s'/'%s' in sam \n " ,
domain_identifier ,
ldb_dn_get_linearized ( domain_dn ) ) ) ;
2008-05-17 14:53:29 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
}
}
2010-04-13 17:18:02 +04:00
/* Lookup using GUID or SID */
if ( ( dom_res = = NULL ) & & ( domain_guid | | domain_sid ) ) {
2008-05-17 06:41:42 +04:00
if ( domain_guid ) {
2008-08-21 10:09:42 +04:00
struct GUID binary_guid ;
struct ldb_val guid_val ;
/* By this means, we ensure we don't have funny stuff in the GUID */
status = GUID_from_string ( domain_guid , & binary_guid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* And this gets the result into the binary format we want anyway */
2009-12-10 06:31:52 +03:00
status = GUID_to_ndr_blob ( & binary_guid , mem_ctx , & guid_val ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2008-08-21 10:09:42 +04:00
}
2008-09-23 22:30:06 +04:00
ret = ldb_search ( sam_ctx , mem_ctx , & dom_res ,
2008-05-17 06:41:42 +04:00
NULL , LDB_SCOPE_SUBTREE ,
dom_attrs ,
2008-08-22 14:50:07 +04:00
" (&(objectCategory=DomainDNS)(objectGUID=%s)) " ,
2008-08-21 10:09:42 +04:00
ldb_binary_encode ( mem_ctx , guid_val ) ) ;
2008-05-17 06:41:42 +04:00
} else { /* domain_sid case */
2008-08-21 10:09:42 +04:00
struct dom_sid * sid ;
struct ldb_val sid_val ;
enum ndr_err_code ndr_err ;
/* Rather than go via the string, just push into the NDR form */
2010-05-09 19:20:01 +04:00
ndr_err = ndr_push_struct_blob ( & sid_val , mem_ctx , & sid ,
2008-08-21 10:09:42 +04:00
( ndr_push_flags_fn_t ) ndr_push_dom_sid ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2008-09-23 22:30:06 +04:00
ret = ldb_search ( sam_ctx , mem_ctx , & dom_res ,
2008-05-17 06:41:42 +04:00
NULL , LDB_SCOPE_SUBTREE ,
dom_attrs ,
2010-09-14 00:39:50 +04:00
" (&(objectCategory=DomainDNS)(objectSid=%s)) " ,
2008-08-21 10:09:42 +04:00
ldb_binary_encode ( mem_ctx , sid_val ) ) ;
2008-05-17 06:41:42 +04:00
}
2007-11-14 00:30:33 +03:00
if ( ret ! = LDB_SUCCESS ) {
2010-04-13 17:18:02 +04:00
DEBUG ( 2 , ( " Unable to find a correct reference to GUID '%s' or SID '%s' in sam: %s \n " ,
2008-05-17 06:41:42 +04:00
domain_guid , dom_sid_string ( mem_ctx , domain_sid ) ,
ldb_errstring ( sam_ctx ) ) ) ;
2007-11-14 00:30:33 +03:00
return NT_STATUS_NO_SUCH_DOMAIN ;
} else if ( dom_res - > count = = 1 ) {
2009-05-26 06:31:39 +04:00
/* Ok, now just check it is our domain */
2010-04-13 17:18:02 +04:00
if ( ldb_dn_compare ( ldb_get_default_basedn ( sam_ctx ) ,
dom_res - > msgs [ 0 ] - > dn ) ! = 0 ) {
DEBUG ( 2 , ( " The GUID '%s' or SID '%s' doesn't identify our domain \n " ,
domain_guid ,
dom_sid_string ( mem_ctx , domain_sid ) ) ) ;
2006-06-15 03:32:19 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
}
2010-04-13 17:18:02 +04:00
} else {
DEBUG ( 2 , ( " Unable to find a correct reference to GUID '%s' or SID '%s' in sam \n " ,
domain_guid , dom_sid_string ( mem_ctx , domain_sid ) ) ) ;
2007-11-14 00:30:33 +03:00
return NT_STATUS_NO_SUCH_DOMAIN ;
2006-06-15 03:32:19 +04:00
}
2005-05-12 12:28:07 +04:00
}
2010-04-27 17:39:57 +04:00
if ( dom_res = = NULL & & fill_on_blank_request ) {
/* blank inputs gives our domain - tested against
w2k8r2 . Without this ADUC on Win7 won ' t start */
domain_dn = ldb_get_default_basedn ( sam_ctx ) ;
ret = ldb_search ( sam_ctx , mem_ctx , & dom_res ,
domain_dn , LDB_SCOPE_BASE , dom_attrs ,
" objectClass=domain " ) ;
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 2 , ( " Error finding domain '%s'/'%s' in sam: %s \n " ,
2010-07-16 08:32:42 +04:00
lpcfg_dnsdomain ( lp_ctx ) ,
2010-04-27 17:39:57 +04:00
ldb_dn_get_linearized ( domain_dn ) ,
ldb_errstring ( sam_ctx ) ) ) ;
return NT_STATUS_NO_SUCH_DOMAIN ;
}
}
if ( dom_res = = NULL ) {
2011-03-01 00:04:29 +03:00
DEBUG ( 2 , ( __location__ " : Unable to get domain information with no inputs \n " ) ) ;
2005-08-03 22:30:21 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
}
2008-05-21 06:37:36 +04:00
/* work around different inputs for not-specified users */
if ( ! user ) {
user = " " ;
}
/* Enquire about any valid username with just a CLDAP packet -
* if kerberos didn ' t also do this , the security folks would
* scream . . . */
if ( user [ 0 ] ) { \
/* Only allow some bits to be enquired: [MS-ATDS] 7.3.3.2 */
if ( acct_control = = ( uint32_t ) - 1 ) {
acct_control = 0 ;
}
acct_control = acct_control & ( ACB_TEMPDUP | ACB_NORMAL | ACB_DOMTRUST | ACB_WSTRUST | ACB_SVRTRUST ) ;
/* We must exclude disabled accounts, but otherwise do the bitwise match the client asked for */
2008-09-23 22:30:06 +04:00
ret = ldb_search ( sam_ctx , mem_ctx , & user_res ,
2008-05-21 06:37:36 +04:00
dom_res - > msgs [ 0 ] - > dn , LDB_SCOPE_SUBTREE ,
none_attrs ,
" (&(objectClass=user)(samAccountName=%s) "
" (!(userAccountControl: " LDB_OID_COMPARATOR_AND " :=%u)) "
" (userAccountControl: " LDB_OID_COMPARATOR_OR " :=%u)) " ,
2008-08-21 10:09:42 +04:00
ldb_binary_encode_string ( mem_ctx , user ) ,
2009-06-12 17:20:48 +04:00
UF_ACCOUNTDISABLE , ds_acb2uf ( acct_control ) ) ;
2008-05-21 06:37:36 +04:00
if ( ret ! = LDB_SUCCESS ) {
2010-04-13 17:29:12 +04:00
DEBUG ( 2 , ( " Unable to find reference to user '%s' with ACB 0x%8x under %s: %s \n " ,
2008-05-21 06:37:36 +04:00
user , acct_control , ldb_dn_get_linearized ( dom_res - > msgs [ 0 ] - > dn ) ,
ldb_errstring ( sam_ctx ) ) ) ;
return NT_STATUS_NO_SUCH_USER ;
} else if ( user_res - > count = = 1 ) {
user_known = true ;
} else {
user_known = false ;
}
} else {
user_known = true ;
}
2005-05-12 12:28:07 +04:00
server_type =
2009-10-02 05:52:16 +04:00
DS_SERVER_DS | DS_SERVER_TIMESERV |
2010-09-14 09:48:19 +04:00
DS_SERVER_CLOSEST |
2009-10-02 05:52:16 +04:00
DS_SERVER_GOOD_TIMESERV ;
#if 0
/* w2k8-r2 as a DC does not claim these */
server_type | = DS_DNS_CONTROLLER | DS_DNS_DOMAIN ;
# endif
2005-05-12 12:28:07 +04:00
2008-05-17 06:41:42 +04:00
if ( samdb_is_pdc ( sam_ctx ) ) {
2009-10-02 05:52:16 +04:00
server_type | = DS_SERVER_PDC ;
2010-04-22 11:53:25 +04:00
}
if ( dsdb_functional_level ( sam_ctx ) > = DS_DOMAIN_FUNCTION_2008 ) {
server_type | = DS_SERVER_FULL_SECRET_DOMAIN_6 ;
2008-01-03 15:00:38 +03:00
}
2008-05-17 06:41:42 +04:00
if ( samdb_is_gc ( sam_ctx ) ) {
2009-10-02 05:52:16 +04:00
server_type | = DS_SERVER_GC ;
2008-01-07 09:47:01 +03:00
}
2005-05-12 12:28:07 +04:00
if ( str_list_check ( services , " ldap " ) ) {
2009-10-02 05:52:16 +04:00
server_type | = DS_SERVER_LDAP ;
2005-05-12 12:28:07 +04:00
}
2005-06-08 03:06:24 +04:00
if ( str_list_check ( services , " kdc " ) ) {
2009-10-02 05:52:16 +04:00
server_type | = DS_SERVER_KDC ;
2005-06-08 03:06:24 +04:00
}
2010-09-15 03:19:47 +04:00
if ( samdb_rodc ( sam_ctx , & am_rodc ) = = LDB_SUCCESS & & ! am_rodc ) {
2010-09-14 09:48:19 +04:00
server_type | = DS_SERVER_WRITABLE ;
}
2009-10-02 05:52:16 +04:00
#if 0
/* w2k8-r2 as a sole DC does not claim this */
2010-04-13 10:41:10 +04:00
if ( ldb_dn_compare ( ldb_get_root_basedn ( sam_ctx ) , ldb_get_default_basedn ( sam_ctx ) ) = = 0 ) {
2009-10-02 05:52:16 +04:00
server_type | = DS_DNS_FOREST_ROOT ;
2008-08-20 06:45:41 +04:00
}
2009-10-02 05:52:16 +04:00
# endif
2008-08-20 06:45:41 +04:00
2010-04-13 17:45:29 +04:00
pdc_name = talloc_asprintf ( mem_ctx , " \\ \\ %s " ,
2010-07-16 08:32:42 +04:00
lpcfg_netbios_name ( lp_ctx ) ) ;
2010-04-13 11:25:26 +04:00
NT_STATUS_HAVE_NO_MEMORY ( pdc_name ) ;
2007-11-14 00:30:33 +03:00
domain_uuid = samdb_result_guid ( dom_res - > msgs [ 0 ] , " objectGUID " ) ;
2010-07-16 08:32:42 +04:00
dns_domain = lpcfg_dnsdomain ( lp_ctx ) ;
2010-04-12 17:02:10 +04:00
forest_domain = samdb_forest_name ( sam_ctx , mem_ctx ) ;
2010-04-13 11:25:26 +04:00
NT_STATUS_HAVE_NO_MEMORY ( forest_domain ) ;
2005-05-12 12:28:07 +04:00
pdc_dns_name = talloc_asprintf ( mem_ctx , " %s.%s " ,
2007-09-28 05:17:46 +04:00
strlower_talloc ( mem_ctx ,
2010-07-16 08:32:42 +04:00
lpcfg_netbios_name ( lp_ctx ) ) ,
2005-06-08 03:06:24 +04:00
dns_domain ) ;
2010-04-13 11:25:26 +04:00
NT_STATUS_HAVE_NO_MEMORY ( pdc_dns_name ) ;
2010-07-16 08:32:42 +04:00
flatname = lpcfg_workgroup ( lp_ctx ) ;
2009-10-18 13:59:11 +04:00
server_site = samdb_server_site_name ( sam_ctx , mem_ctx ) ;
2010-04-13 17:45:29 +04:00
NT_STATUS_HAVE_NO_MEMORY ( server_site ) ;
2010-04-11 15:17:05 +04:00
client_site = samdb_client_site_name ( sam_ctx , mem_ctx ,
src_address , NULL ) ;
NT_STATUS_HAVE_NO_MEMORY ( client_site ) ;
2011-05-02 09:57:19 +04:00
load_interface_list ( mem_ctx , lpcfg_interfaces ( lp_ctx ) , & ifaces ) ;
2010-04-27 12:22:25 +04:00
/*
* TODO : the caller should pass the address which the client
* used to trigger this call , as the client is able to reach
* this ip .
*/
if ( src_address ) {
2011-05-02 09:57:19 +04:00
pdc_ip = iface_list_best_ip ( ifaces , src_address ) ;
2010-04-27 12:22:25 +04:00
} else {
2011-05-02 09:57:19 +04:00
pdc_ip = iface_list_n_ip ( ifaces , 0 ) ;
2010-04-27 12:22:25 +04:00
}
2005-05-12 12:28:07 +04:00
ZERO_STRUCTP ( netlogon ) ;
2008-05-21 06:37:36 +04:00
/* check if either of these bits is present */
if ( version & ( NETLOGON_NT_VERSION_5EX | NETLOGON_NT_VERSION_5EX_WITH_IP ) ) {
2008-05-17 14:53:29 +04:00
uint32_t extra_flags = 0 ;
2008-05-17 06:41:42 +04:00
netlogon - > ntver = NETLOGON_NT_VERSION_5EX ;
/* could check if the user exists */
2008-05-21 06:37:36 +04:00
if ( user_known ) {
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5_ex . command = LOGON_SAM_LOGON_RESPONSE_EX ;
2008-05-17 14:53:29 +04:00
} else {
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5_ex . command = LOGON_SAM_LOGON_USER_UNKNOWN_EX ;
2008-05-17 14:53:29 +04:00
}
2010-04-27 18:32:46 +04:00
netlogon - > data . nt5_ex . pdc_name = pdc_name ;
netlogon - > data . nt5_ex . user_name = user ;
2010-04-27 18:56:36 +04:00
netlogon - > data . nt5_ex . domain_name = flatname ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5_ex . domain_uuid = domain_uuid ;
2010-04-12 17:02:10 +04:00
netlogon - > data . nt5_ex . forest = forest_domain ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5_ex . dns_domain = dns_domain ;
netlogon - > data . nt5_ex . pdc_dns_name = pdc_dns_name ;
netlogon - > data . nt5_ex . server_site = server_site ;
netlogon - > data . nt5_ex . client_site = client_site ;
2008-05-17 06:41:42 +04:00
if ( version & NETLOGON_NT_VERSION_5EX_WITH_IP ) {
/* Clearly this needs to be fixed up for IPv6 */
extra_flags = NETLOGON_NT_VERSION_5EX_WITH_IP ;
2008-10-14 17:43:04 +04:00
netlogon - > data . nt5_ex . sockaddr . sockaddr_family = 2 ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5_ex . sockaddr . pdc_ip = pdc_ip ;
netlogon - > data . nt5_ex . sockaddr . remaining = data_blob_talloc_zero ( mem_ctx , 8 ) ;
2008-05-17 06:41:42 +04:00
}
2010-04-27 18:32:46 +04:00
netlogon - > data . nt5_ex . server_type = server_type ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5_ex . nt_version = NETLOGON_NT_VERSION_1 | NETLOGON_NT_VERSION_5EX | extra_flags ;
netlogon - > data . nt5_ex . lmnt_token = 0xFFFF ;
netlogon - > data . nt5_ex . lm20_token = 0xFFFF ;
2008-05-17 06:41:42 +04:00
} else if ( version & NETLOGON_NT_VERSION_5 ) {
netlogon - > ntver = NETLOGON_NT_VERSION_5 ;
/* could check if the user exists */
2008-05-21 06:37:36 +04:00
if ( user_known ) {
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5 . command = LOGON_SAM_LOGON_RESPONSE ;
2008-05-17 14:53:29 +04:00
} else {
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5 . command = LOGON_SAM_LOGON_USER_UNKNOWN ;
2008-05-17 14:53:29 +04:00
}
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5 . pdc_name = pdc_name ;
netlogon - > data . nt5 . user_name = user ;
netlogon - > data . nt5 . domain_name = flatname ;
netlogon - > data . nt5 . domain_uuid = domain_uuid ;
2010-04-12 17:02:10 +04:00
netlogon - > data . nt5 . forest = forest_domain ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt5 . dns_domain = dns_domain ;
netlogon - > data . nt5 . pdc_dns_name = pdc_dns_name ;
netlogon - > data . nt5 . pdc_ip = pdc_ip ;
netlogon - > data . nt5 . server_type = server_type ;
netlogon - > data . nt5 . nt_version = NETLOGON_NT_VERSION_1 | NETLOGON_NT_VERSION_5 ;
netlogon - > data . nt5 . lmnt_token = 0xFFFF ;
netlogon - > data . nt5 . lm20_token = 0xFFFF ;
2008-05-17 14:53:29 +04:00
} else /* (version & NETLOGON_NT_VERSION_1) and all other cases */ {
2008-05-17 06:41:42 +04:00
netlogon - > ntver = NETLOGON_NT_VERSION_1 ;
/* could check if the user exists */
2008-05-21 06:37:36 +04:00
if ( user_known ) {
2008-10-02 10:09:25 +04:00
netlogon - > data . nt4 . command = LOGON_SAM_LOGON_RESPONSE ;
2008-05-17 14:53:29 +04:00
} else {
2008-10-02 10:09:25 +04:00
netlogon - > data . nt4 . command = LOGON_SAM_LOGON_USER_UNKNOWN ;
2008-05-17 14:53:29 +04:00
}
2010-04-27 18:56:36 +04:00
netlogon - > data . nt4 . pdc_name = pdc_name ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt4 . user_name = user ;
2010-04-27 18:56:36 +04:00
netlogon - > data . nt4 . domain_name = flatname ;
2008-10-02 10:09:25 +04:00
netlogon - > data . nt4 . nt_version = NETLOGON_NT_VERSION_1 ;
netlogon - > data . nt4 . lmnt_token = 0xFFFF ;
netlogon - > data . nt4 . lm20_token = 0xFFFF ;
2005-05-12 12:28:07 +04:00
}
return NT_STATUS_OK ;
}
/*
handle incoming cldap requests
*/
2009-02-13 15:13:54 +03:00
void cldapd_netlogon_request ( struct cldap_socket * cldap ,
struct cldapd_server * cldapd ,
TALLOC_CTX * tmp_ctx ,
2005-05-12 12:28:07 +04:00
uint32_t message_id ,
2005-06-13 13:10:17 +04:00
struct ldb_parse_tree * tree ,
2009-02-13 15:13:54 +03:00
struct tsocket_address * src )
2005-05-12 12:28:07 +04:00
{
2009-11-07 23:20:56 +03:00
unsigned int i ;
2005-05-12 12:28:07 +04:00
const char * domain = NULL ;
const char * host = NULL ;
2005-07-12 13:40:34 +04:00
const char * user = NULL ;
2005-05-13 09:29:41 +04:00
const char * domain_guid = NULL ;
2010-04-27 20:07:09 +04:00
struct dom_sid * domain_sid = NULL ;
2005-05-13 09:29:41 +04:00
int acct_control = - 1 ;
2005-05-12 12:28:07 +04:00
int version = - 1 ;
2008-05-17 06:41:42 +04:00
struct netlogon_samlogon_response netlogon ;
2005-05-12 12:28:07 +04:00
NTSTATUS status = NT_STATUS_INVALID_PARAMETER ;
2005-06-13 10:06:29 +04:00
if ( tree - > operation ! = LDB_OP_AND ) goto failed ;
2005-05-12 12:28:07 +04:00
/* extract the query elements */
for ( i = 0 ; i < tree - > u . list . num_elements ; i + + ) {
2005-06-13 10:06:29 +04:00
struct ldb_parse_tree * t = tree - > u . list . elements [ i ] ;
2005-07-19 13:09:00 +04:00
if ( t - > operation ! = LDB_OP_EQUALITY ) goto failed ;
if ( strcasecmp ( t - > u . equality . attr , " DnsDomain " ) = = 0 ) {
2005-05-12 12:28:07 +04:00
domain = talloc_strndup ( tmp_ctx ,
2006-03-15 13:28:35 +03:00
( const char * ) t - > u . equality . value . data ,
2005-07-19 13:09:00 +04:00
t - > u . equality . value . length ) ;
2005-05-12 12:28:07 +04:00
}
2005-07-19 13:09:00 +04:00
if ( strcasecmp ( t - > u . equality . attr , " Host " ) = = 0 ) {
2005-05-12 12:28:07 +04:00
host = talloc_strndup ( tmp_ctx ,
2006-03-15 13:28:35 +03:00
( const char * ) t - > u . equality . value . data ,
2005-07-19 13:09:00 +04:00
t - > u . equality . value . length ) ;
2005-05-12 12:28:07 +04:00
}
2005-07-19 13:09:00 +04:00
if ( strcasecmp ( t - > u . equality . attr , " DomainGuid " ) = = 0 ) {
2005-05-16 15:17:57 +04:00
NTSTATUS enc_status ;
struct GUID guid ;
enc_status = ldap_decode_ndr_GUID ( tmp_ctx ,
2005-07-19 13:09:00 +04:00
t - > u . equality . value , & guid ) ;
2005-05-16 15:17:57 +04:00
if ( NT_STATUS_IS_OK ( enc_status ) ) {
domain_guid = GUID_string ( tmp_ctx , & guid ) ;
}
2005-05-13 09:29:41 +04:00
}
2005-07-19 13:09:00 +04:00
if ( strcasecmp ( t - > u . equality . attr , " DomainSid " ) = = 0 ) {
2010-04-27 20:07:09 +04:00
enum ndr_err_code ndr_err ;
domain_sid = talloc ( tmp_ctx , struct dom_sid ) ;
if ( domain_sid = = NULL ) {
goto failed ;
}
ndr_err = ndr_pull_struct_blob ( & t - > u . equality . value ,
2010-05-09 19:20:01 +04:00
domain_sid , domain_sid ,
2010-04-27 20:07:09 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_dom_sid ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
talloc_free ( domain_sid ) ;
goto failed ;
}
2005-05-13 09:29:41 +04:00
}
2005-07-19 13:09:00 +04:00
if ( strcasecmp ( t - > u . equality . attr , " User " ) = = 0 ) {
2005-05-12 13:03:14 +04:00
user = talloc_strndup ( tmp_ctx ,
2006-03-15 13:28:35 +03:00
( const char * ) t - > u . equality . value . data ,
2005-07-19 13:09:00 +04:00
t - > u . equality . value . length ) ;
2005-05-12 13:03:14 +04:00
}
2005-07-19 13:09:00 +04:00
if ( strcasecmp ( t - > u . equality . attr , " NtVer " ) = = 0 & &
t - > u . equality . value . length = = 4 ) {
version = IVAL ( t - > u . equality . value . data , 0 ) ;
2005-05-12 12:28:07 +04:00
}
2005-07-19 13:09:00 +04:00
if ( strcasecmp ( t - > u . equality . attr , " AAC " ) = = 0 & &
t - > u . equality . value . length = = 4 ) {
acct_control = IVAL ( t - > u . equality . value . data , 0 ) ;
2005-05-13 09:29:41 +04:00
}
2005-05-12 12:28:07 +04:00
}
2010-04-27 20:07:09 +04:00
if ( ( domain = = NULL ) & & ( domain_guid = = NULL ) & & ( domain_sid = = NULL ) ) {
2010-07-16 08:32:42 +04:00
domain = lpcfg_dnsdomain ( cldapd - > task - > lp_ctx ) ;
2005-05-16 15:17:57 +04:00
}
if ( version = = - 1 ) {
2005-05-12 12:28:07 +04:00
goto failed ;
}
2005-05-18 08:18:19 +04:00
DEBUG ( 5 , ( " cldap netlogon query domain=%s host=%s user=%s version=%d guid=%s \n " ,
2005-05-16 15:17:57 +04:00
domain , host , user , version , domain_guid ) ) ;
2005-05-12 12:28:07 +04:00
2010-04-27 20:07:09 +04:00
status = fill_netlogon_samlogon_response ( cldapd - > samctx , tmp_ctx ,
domain , NULL , domain_sid ,
domain_guid ,
2009-02-13 15:13:54 +03:00
user , acct_control ,
tsocket_address_inet_addr_string ( src , tmp_ctx ) ,
2010-04-27 20:07:09 +04:00
version , cldapd - > task - > lp_ctx ,
& netlogon , false ) ;
2005-05-12 12:28:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
2010-05-09 19:20:01 +04:00
status = cldap_netlogon_reply ( cldap , message_id , src , version , & netlogon ) ;
2005-05-12 12:28:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
return ;
failed :
2005-06-19 00:32:21 +04:00
DEBUG ( 2 , ( " cldap netlogon query failed domain=%s host=%s version=%d - %s \n " ,
2005-05-12 12:28:07 +04:00
domain , host , version , nt_errstr ( status ) ) ) ;
2009-02-13 15:13:54 +03:00
cldap_empty_reply ( cldap , message_id , src ) ;
2005-05-12 12:28:07 +04:00
}