2002-08-19 07:17:03 +04:00
/*
Samba Unix / Linux SMB client library
net ads cldap functions
Copyright ( C ) 2001 Andrew Tridgell ( tridge @ samba . org )
2003-02-28 06:35:45 +03:00
Copyright ( C ) 2003 Jim McDonough ( jmcd @ us . ibm . com )
2008-05-07 17:49:09 +04:00
Copyright ( C ) 2008 Guenther Deschner ( gd @ samba . org )
2002-08-19 07:17:03 +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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2002-08-19 07:17:03 +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 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2002-08-19 07:17:03 +04:00
*/
# include "includes.h"
2002-08-19 19:59:14 +04:00
2002-08-19 07:17:03 +04:00
/*
do a cldap netlogon query
*/
2002-08-19 19:30:26 +04:00
static int send_cldap_netlogon ( int sock , const char * domain ,
const char * hostname , unsigned ntversion )
2002-08-19 07:17:03 +04:00
{
ASN1_DATA data ;
char ntver [ 4 ] ;
2003-05-20 17:51:43 +04:00
# ifdef CLDAP_USER_QUERY
char aac [ 4 ] ;
2002-08-19 07:17:03 +04:00
2003-05-20 17:51:43 +04:00
SIVAL ( aac , 0 , 0x00000180 ) ;
# endif
2002-08-19 19:30:26 +04:00
SIVAL ( ntver , 0 , ntversion ) ;
2002-08-19 07:17:03 +04:00
memset ( & data , 0 , sizeof ( data ) ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_Integer ( & data , 4 ) ;
asn1_push_tag ( & data , ASN1_APPLICATION ( 3 ) ) ;
asn1_write_OctetString ( & data , NULL , 0 ) ;
asn1_write_enumerated ( & data , 0 ) ;
asn1_write_enumerated ( & data , 0 ) ;
asn1_write_Integer ( & data , 0 ) ;
asn1_write_Integer ( & data , 0 ) ;
asn1_write_BOOLEAN2 ( & data , False ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 0 ) ) ;
2006-07-07 15:43:47 +04:00
if ( domain ) {
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_write_OctetString ( & data , " DnsDomain " , 9 ) ;
asn1_write_OctetString ( & data , domain , strlen ( domain ) ) ;
asn1_pop_tag ( & data ) ;
}
2002-08-19 07:17:03 +04:00
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_write_OctetString ( & data , " Host " , 4 ) ;
2002-08-19 19:30:26 +04:00
asn1_write_OctetString ( & data , hostname , strlen ( hostname ) ) ;
2002-08-19 07:17:03 +04:00
asn1_pop_tag ( & data ) ;
2003-05-20 17:51:43 +04:00
# ifdef CLDAP_USER_QUERY
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_write_OctetString ( & data , " User " , 4 ) ;
asn1_write_OctetString ( & data , " SAMBA$ " , 6 ) ;
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_write_OctetString ( & data , " AAC " , 4 ) ;
asn1_write_OctetString ( & data , aac , 4 ) ;
asn1_pop_tag ( & data ) ;
# endif
2002-08-19 07:17:03 +04:00
asn1_push_tag ( & data , ASN1_CONTEXT ( 3 ) ) ;
asn1_write_OctetString ( & data , " NtVer " , 5 ) ;
asn1_write_OctetString ( & data , ntver , 4 ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_push_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_write_OctetString ( & data , " NetLogon " , 8 ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
asn1_pop_tag ( & data ) ;
if ( data . has_error ) {
2006-05-13 05:29:04 +04:00
DEBUG ( 2 , ( " Failed to build cldap netlogon at offset %d \n " , ( int ) data . ofs ) ) ;
2002-08-19 07:17:03 +04:00
asn1_free ( & data ) ;
return - 1 ;
}
2003-03-18 02:04:03 +03:00
if ( write ( sock , data . data , data . length ) ! = ( ssize_t ) data . length ) {
2006-05-13 05:29:04 +04:00
DEBUG ( 2 , ( " failed to send cldap query (%s) \n " , strerror ( errno ) ) ) ;
2006-09-06 17:13:12 +04:00
asn1_free ( & data ) ;
2006-09-06 17:10:20 +04:00
return - 1 ;
2002-08-19 19:30:26 +04:00
}
asn1_free ( & data ) ;
return 0 ;
}
2006-05-13 03:20:39 +04:00
static SIG_ATOMIC_T gotalarm ;
/***************************************************************
Signal function to tell us we timed out .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void gotalarm_sig ( void )
{
gotalarm = 1 ;
}
2002-08-19 19:30:26 +04:00
/*
receive a cldap netlogon reply
*/
2008-04-21 21:47:13 +04:00
static int recv_cldap_netlogon ( TALLOC_CTX * mem_ctx ,
int sock ,
2008-05-07 17:49:09 +04:00
uint32_t * nt_version ,
union nbt_cldap_netlogon * * reply )
2002-08-19 19:30:26 +04:00
{
int ret ;
ASN1_DATA data ;
2007-05-14 16:16:20 +04:00
DATA_BLOB blob = data_blob_null ;
DATA_BLOB os1 = data_blob_null ;
DATA_BLOB os2 = data_blob_null ;
DATA_BLOB os3 = data_blob_null ;
2005-10-18 07:24:00 +04:00
int i1 ;
2006-09-03 03:06:21 +04:00
/* half the time of a regular ldap timeout, not less than 3 seconds. */
unsigned int al_secs = MAX ( 3 , lp_ldap_timeout ( ) / 2 ) ;
2008-05-07 17:49:09 +04:00
union nbt_cldap_netlogon * r = NULL ;
2002-08-19 19:30:26 +04:00
blob = data_blob ( NULL , 8192 ) ;
2006-07-17 19:00:49 +04:00
if ( blob . data = = NULL ) {
DEBUG ( 1 , ( " data_blob failed \n " ) ) ;
errno = ENOMEM ;
return - 1 ;
}
2002-08-19 19:30:26 +04:00
2006-05-13 03:20:39 +04:00
/* Setup timeout */
gotalarm = 0 ;
CatchSignal ( SIGALRM , SIGNAL_CAST gotalarm_sig ) ;
2006-09-03 03:06:21 +04:00
alarm ( al_secs ) ;
2006-05-13 03:20:39 +04:00
/* End setup timeout. */
2002-08-19 19:30:26 +04:00
ret = read ( sock , blob . data , blob . length ) ;
2002-08-23 02:50:57 +04:00
2006-05-13 03:20:39 +04:00
/* Teardown timeout. */
CatchSignal ( SIGALRM , SIGNAL_CAST SIG_IGN ) ;
alarm ( 0 ) ;
2002-08-19 19:30:26 +04:00
if ( ret < = 0 ) {
2006-05-13 05:29:04 +04:00
DEBUG ( 1 , ( " no reply received to cldap netlogon \n " ) ) ;
2006-07-17 19:00:49 +04:00
data_blob_free ( & blob ) ;
2002-08-19 19:30:26 +04:00
return - 1 ;
}
blob . length = ret ;
asn1_load ( & data , blob ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
2002-08-19 19:59:14 +04:00
asn1_read_Integer ( & data , & i1 ) ;
2002-08-19 19:30:26 +04:00
asn1_start_tag ( & data , ASN1_APPLICATION ( 4 ) ) ;
asn1_read_OctetString ( & data , & os1 ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_start_tag ( & data , ASN1_SEQUENCE ( 0 ) ) ;
asn1_read_OctetString ( & data , & os2 ) ;
asn1_start_tag ( & data , ASN1_SET ) ;
asn1_read_OctetString ( & data , & os3 ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
asn1_end_tag ( & data ) ;
2002-08-23 02:50:57 +04:00
if ( data . has_error ) {
2006-07-17 19:00:49 +04:00
data_blob_free ( & blob ) ;
2007-03-08 01:29:21 +03:00
data_blob_free ( & os1 ) ;
data_blob_free ( & os2 ) ;
data_blob_free ( & os3 ) ;
2006-06-22 03:43:33 +04:00
asn1_free ( & data ) ;
2006-05-13 05:29:04 +04:00
DEBUG ( 1 , ( " Failed to parse cldap reply \n " ) ) ;
2002-08-23 02:50:57 +04:00
return - 1 ;
}
2008-05-07 17:49:09 +04:00
r = TALLOC_ZERO_P ( mem_ctx , union nbt_cldap_netlogon ) ;
if ( ! r ) {
errno = ENOMEM ;
data_blob_free ( & os1 ) ;
data_blob_free ( & os2 ) ;
data_blob_free ( & os3 ) ;
data_blob_free ( & blob ) ;
2008-04-21 21:26:32 +04:00
return - 1 ;
2003-05-20 17:51:43 +04:00
}
2003-02-28 06:35:45 +03:00
2008-05-07 17:49:09 +04:00
if ( ! pull_mailslot_cldap_reply ( mem_ctx , & os3 , r , nt_version ) ) {
data_blob_free ( & os1 ) ;
data_blob_free ( & os2 ) ;
data_blob_free ( & os3 ) ;
data_blob_free ( & blob ) ;
TALLOC_FREE ( r ) ;
return - 1 ;
2008-04-21 21:26:32 +04:00
}
2002-08-19 19:59:14 +04:00
2002-08-19 19:30:26 +04:00
data_blob_free ( & os1 ) ;
data_blob_free ( & os2 ) ;
data_blob_free ( & os3 ) ;
data_blob_free ( & blob ) ;
2006-06-22 03:43:33 +04:00
asn1_free ( & data ) ;
2008-05-07 17:49:09 +04:00
if ( reply ) {
* reply = r ;
} else {
TALLOC_FREE ( r ) ;
}
2002-08-19 19:30:26 +04:00
return 0 ;
}
2006-05-12 19:17:35 +04:00
/*******************************************************************
do a cldap netlogon query . Always 389 / udp
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-04-21 21:47:13 +04:00
bool ads_cldap_netlogon ( TALLOC_CTX * mem_ctx ,
const char * server ,
const char * realm ,
2008-05-07 17:49:09 +04:00
uint32_t * nt_version ,
union nbt_cldap_netlogon * * reply )
2002-08-19 19:30:26 +04:00
{
int sock ;
int ret ;
2006-05-12 19:17:35 +04:00
sock = open_udp_socket ( server , LDAP_PORT ) ;
2002-08-19 07:17:03 +04:00
if ( sock = = - 1 ) {
2006-05-12 19:17:35 +04:00
DEBUG ( 2 , ( " ads_cldap_netlogon: Failed to open udp socket to %s \n " ,
server ) ) ;
return False ;
2002-08-19 07:17:03 +04:00
}
2008-05-07 17:49:09 +04:00
ret = send_cldap_netlogon ( sock , realm , global_myname ( ) , * nt_version ) ;
2002-08-19 19:30:26 +04:00
if ( ret ! = 0 ) {
2006-09-06 15:53:13 +04:00
close ( sock ) ;
2006-05-12 19:17:35 +04:00
return False ;
2002-08-19 19:30:26 +04:00
}
2008-05-07 17:49:09 +04:00
ret = recv_cldap_netlogon ( mem_ctx , sock , nt_version , reply ) ;
2002-08-19 19:30:26 +04:00
close ( sock ) ;
2002-08-19 19:59:14 +04:00
2002-08-23 02:50:57 +04:00
if ( ret = = - 1 ) {
2006-05-12 19:17:35 +04:00
return False ;
2002-08-23 02:50:57 +04:00
}
2006-05-12 19:17:35 +04:00
return True ;
2002-08-19 07:17:03 +04:00
}
2008-05-07 17:49:09 +04:00
/*******************************************************************
do a cldap netlogon query . Always 389 / udp
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool ads_cldap_netlogon_5 ( TALLOC_CTX * mem_ctx ,
const char * server ,
const char * realm ,
struct nbt_cldap_netlogon_5 * reply5 )
{
uint32_t nt_version = NETLOGON_VERSION_5 | NETLOGON_VERSION_5EX ;
union nbt_cldap_netlogon * reply = NULL ;
bool ret ;
ret = ads_cldap_netlogon ( mem_ctx , server , realm , & nt_version , & reply ) ;
if ( ! ret ) {
return false ;
}
if ( nt_version ! = ( NETLOGON_VERSION_5 | NETLOGON_VERSION_5EX ) ) {
return false ;
}
* reply5 = reply - > logon5 ;
return true ;
}