2005-05-10 06:01:25 +04:00
/*
Unix SMB / CIFS implementation .
cldap client library
Copyright ( C ) Andrew Tridgell 2005
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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
see RFC1798 for details of CLDAP
basic properties
- carried over UDP on port 389
- request and response matched by message ID
- request consists of only a single searchRequest element
- response can be in one of two forms
- a single searchResponse , followed by a searchResult
- a single searchResult
*/
# include "includes.h"
# include "lib/events/events.h"
2006-08-30 15:29:34 +04:00
# include "lib/util/dlinklist.h"
2005-05-10 06:01:25 +04:00
# include "libcli/ldap/ldap.h"
# include "libcli/cldap/cldap.h"
# include "lib/socket/socket.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_nbt.h"
2005-05-10 06:01:25 +04:00
/*
destroy a pending request
*/
2006-05-24 11:34:11 +04:00
static int cldap_request_destructor ( struct cldap_request * req )
2005-05-10 06:01:25 +04:00
{
if ( req - > state = = CLDAP_REQUEST_SEND ) {
DLIST_REMOVE ( req - > cldap - > send_queue , req ) ;
}
2005-05-12 12:25:35 +04:00
if ( ! req - > is_reply & & req - > message_id ! = 0 ) {
2005-05-10 06:01:25 +04:00
idr_remove ( req - > cldap - > idr , req - > message_id ) ;
req - > message_id = 0 ;
}
return 0 ;
}
/*
handle recv events on a cldap socket
*/
static void cldap_socket_recv ( struct cldap_socket * cldap )
{
TALLOC_CTX * tmp_ctx = talloc_new ( cldap ) ;
NTSTATUS status ;
2006-01-10 01:12:53 +03:00
struct socket_address * src ;
2005-05-10 06:01:25 +04:00
DATA_BLOB blob ;
2005-06-03 17:37:23 +04:00
size_t nread , dsize ;
2005-05-10 06:01:25 +04:00
struct asn1_data asn1 ;
2005-06-15 04:27:51 +04:00
struct ldap_message * ldap_msg ;
2005-05-10 06:01:25 +04:00
struct cldap_request * req ;
2005-06-03 17:37:23 +04:00
status = socket_pending ( cldap - > sock , & dsize ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return ;
}
blob = data_blob_talloc ( tmp_ctx , NULL , dsize ) ;
2005-05-10 06:01:25 +04:00
if ( blob . data = = NULL ) {
talloc_free ( tmp_ctx ) ;
return ;
}
2006-04-30 09:58:31 +04:00
status = socket_recvfrom ( cldap - > sock , blob . data , blob . length , & nread ,
2006-01-10 01:12:53 +03:00
tmp_ctx , & src ) ;
2005-05-10 06:01:25 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return ;
}
blob . length = nread ;
DEBUG ( 2 , ( " Received cldap packet of length %d from %s:%d \n " ,
2006-01-10 01:12:53 +03:00
( int ) blob . length , src - > addr , src - > port ) ) ;
2005-05-10 06:01:25 +04:00
if ( ! asn1_load ( & asn1 , blob ) ) {
DEBUG ( 2 , ( " Failed to setup for asn.1 decode \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return ;
}
talloc_steal ( tmp_ctx , asn1 . data ) ;
2005-06-15 04:27:51 +04:00
ldap_msg = talloc ( tmp_ctx , struct ldap_message ) ;
if ( ldap_msg = = NULL ) {
talloc_free ( tmp_ctx ) ;
return ;
}
2005-05-10 06:01:25 +04:00
/* this initial decode is used to find the message id */
2007-03-13 03:59:06 +03:00
status = ldap_decode ( & asn1 , ldap_msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " Failed to decode ldap message: %s \n " , nt_errstr ( status ) ) ) ;
2005-05-10 06:01:25 +04:00
talloc_free ( tmp_ctx ) ;
return ;
}
/* find the pending request */
2005-06-15 04:27:51 +04:00
req = idr_find ( cldap - > idr , ldap_msg - > messageid ) ;
2005-05-10 06:01:25 +04:00
if ( req = = NULL ) {
2005-05-11 08:48:30 +04:00
if ( cldap - > incoming . handler ) {
2006-01-10 01:12:53 +03:00
cldap - > incoming . handler ( cldap , ldap_msg , src ) ;
2005-05-11 08:48:30 +04:00
} else {
DEBUG ( 2 , ( " Mismatched cldap reply %u from %s:%d \n " ,
2006-01-10 01:12:53 +03:00
ldap_msg - > messageid , src - > addr , src - > port ) ) ;
2005-05-11 08:48:30 +04:00
}
2005-05-10 06:01:25 +04:00
talloc_free ( tmp_ctx ) ;
return ;
}
req - > asn1 = asn1 ;
talloc_steal ( req , asn1 . data ) ;
req - > asn1 . ofs = 0 ;
req - > state = CLDAP_REQUEST_DONE ;
talloc_free ( req - > te ) ;
talloc_free ( tmp_ctx ) ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
}
/*
handle request timeouts
*/
static void cldap_request_timeout ( struct event_context * event_ctx ,
struct timed_event * te , struct timeval t ,
void * private )
{
struct cldap_request * req = talloc_get_type ( private , struct cldap_request ) ;
/* possibly try again */
if ( req - > num_retries ! = 0 ) {
size_t len = req - > encoded . length ;
req - > num_retries - - ;
2006-04-30 09:58:31 +04:00
socket_sendto ( req - > cldap - > sock , & req - > encoded , & len ,
2006-01-10 01:12:53 +03:00
req - > dest ) ;
2005-05-10 06:01:25 +04:00
req - > te = event_add_timed ( req - > cldap - > event_ctx , req ,
timeval_current_ofs ( req - > timeout , 0 ) ,
cldap_request_timeout , req ) ;
return ;
}
2007-04-05 11:37:21 +04:00
req - > state = CLDAP_REQUEST_ERROR ;
req - > status = NT_STATUS_IO_TIMEOUT ;
2005-05-10 06:01:25 +04:00
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
}
/*
handle send events on a cldap socket
*/
static void cldap_socket_send ( struct cldap_socket * cldap )
{
struct cldap_request * req ;
NTSTATUS status ;
while ( ( req = cldap - > send_queue ) ) {
size_t len ;
len = req - > encoded . length ;
2006-04-30 09:58:31 +04:00
status = socket_sendto ( cldap - > sock , & req - > encoded , & len ,
2006-01-10 01:12:53 +03:00
req - > dest ) ;
2005-05-10 06:01:25 +04:00
if ( NT_STATUS_IS_ERR ( status ) ) {
2007-04-05 11:37:21 +04:00
DEBUG ( 0 , ( " Failed to send cldap request of length %u to %s:%d \n " ,
2006-01-10 01:12:53 +03:00
( unsigned ) req - > encoded . length , req - > dest - > addr , req - > dest - > port ) ) ;
2005-05-10 06:01:25 +04:00
DLIST_REMOVE ( cldap - > send_queue , req ) ;
2007-04-05 11:37:21 +04:00
req - > state = CLDAP_REQUEST_ERROR ;
req - > status = status ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
2005-05-10 06:01:25 +04:00
continue ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) return ;
DLIST_REMOVE ( cldap - > send_queue , req ) ;
2005-05-12 12:25:35 +04:00
if ( req - > is_reply ) {
talloc_free ( req ) ;
} else {
req - > state = CLDAP_REQUEST_WAIT ;
2005-05-10 06:01:25 +04:00
2005-05-12 12:25:35 +04:00
req - > te = event_add_timed ( cldap - > event_ctx , req ,
timeval_current_ofs ( req - > timeout , 0 ) ,
cldap_request_timeout , req ) ;
2005-05-10 06:01:25 +04:00
2005-05-12 12:25:35 +04:00
EVENT_FD_READABLE ( cldap - > fde ) ;
}
2005-05-10 06:01:25 +04:00
}
EVENT_FD_NOT_WRITEABLE ( cldap - > fde ) ;
return ;
}
/*
handle fd events on a cldap_socket
*/
static void cldap_socket_handler ( struct event_context * ev , struct fd_event * fde ,
uint16_t flags , void * private )
{
struct cldap_socket * cldap = talloc_get_type ( private , struct cldap_socket ) ;
if ( flags & EVENT_FD_WRITE ) {
cldap_socket_send ( cldap ) ;
2005-06-11 07:53:39 +04:00
}
if ( flags & EVENT_FD_READ ) {
2005-05-10 06:01:25 +04:00
cldap_socket_recv ( cldap ) ;
}
}
/*
initialise a cldap_socket . The event_ctx is optional , if provided
then operations will use that event context
*/
struct cldap_socket * cldap_socket_init ( TALLOC_CTX * mem_ctx ,
struct event_context * event_ctx )
{
struct cldap_socket * cldap ;
NTSTATUS status ;
cldap = talloc ( mem_ctx , struct cldap_socket ) ;
if ( cldap = = NULL ) goto failed ;
if ( event_ctx = = NULL ) {
cldap - > event_ctx = event_context_init ( cldap ) ;
} else {
cldap - > event_ctx = talloc_reference ( cldap , event_ctx ) ;
}
if ( cldap - > event_ctx = = NULL ) goto failed ;
cldap - > idr = idr_init ( cldap ) ;
if ( cldap - > idr = = NULL ) goto failed ;
status = socket_create ( " ip " , SOCKET_TYPE_DGRAM , & cldap - > sock , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
talloc_steal ( cldap , cldap - > sock ) ;
cldap - > fde = event_add_fd ( cldap - > event_ctx , cldap ,
socket_get_fd ( cldap - > sock ) , 0 ,
cldap_socket_handler , cldap ) ;
cldap - > send_queue = NULL ;
2005-05-11 08:48:30 +04:00
cldap - > incoming . handler = NULL ;
2005-05-10 06:01:25 +04:00
return cldap ;
failed :
talloc_free ( cldap ) ;
return NULL ;
}
2005-05-11 08:48:30 +04:00
/*
setup a handler for incoming requests
*/
NTSTATUS cldap_set_incoming_handler ( struct cldap_socket * cldap ,
void ( * handler ) ( struct cldap_socket * , struct ldap_message * ,
2006-01-10 01:12:53 +03:00
struct socket_address * ) ,
2005-05-11 08:48:30 +04:00
void * private )
{
cldap - > incoming . handler = handler ;
cldap - > incoming . private = private ;
EVENT_FD_READABLE ( cldap - > fde ) ;
return NT_STATUS_OK ;
}
2005-05-10 06:01:25 +04:00
/*
queue a cldap request for send
*/
struct cldap_request * cldap_search_send ( struct cldap_socket * cldap ,
struct cldap_search * io )
{
2005-06-15 04:27:51 +04:00
struct ldap_message * msg ;
2005-05-10 06:01:25 +04:00
struct cldap_request * req ;
struct ldap_SearchRequest * search ;
req = talloc_zero ( cldap , struct cldap_request ) ;
if ( req = = NULL ) goto failed ;
req - > cldap = cldap ;
req - > state = CLDAP_REQUEST_SEND ;
req - > timeout = io - > in . timeout ;
req - > num_retries = io - > in . retries ;
2005-05-12 12:25:35 +04:00
req - > is_reply = False ;
2005-05-10 06:01:25 +04:00
2006-01-10 01:12:53 +03:00
req - > dest = socket_address_from_strings ( req , cldap - > sock - > backend_name ,
io - > in . dest_address , lp_cldap_port ( ) ) ;
if ( ! req - > dest ) goto failed ;
2005-05-10 06:01:25 +04:00
req - > message_id = idr_get_new_random ( cldap - > idr , req , UINT16_MAX ) ;
if ( req - > message_id = = - 1 ) goto failed ;
talloc_set_destructor ( req , cldap_request_destructor ) ;
2005-06-15 04:27:51 +04:00
msg = talloc ( req , struct ldap_message ) ;
if ( msg = = NULL ) goto failed ;
msg - > messageid = req - > message_id ;
msg - > type = LDAP_TAG_SearchRequest ;
msg - > controls = NULL ;
search = & msg - > r . SearchRequest ;
2005-05-10 06:01:25 +04:00
search - > basedn = " " ;
search - > scope = LDAP_SEARCH_SCOPE_BASE ;
search - > deref = LDAP_DEREFERENCE_NEVER ;
search - > timelimit = 0 ;
search - > sizelimit = 0 ;
search - > attributesonly = False ;
search - > num_attributes = str_list_length ( io - > in . attributes ) ;
search - > attributes = io - > in . attributes ;
2005-06-13 13:10:17 +04:00
search - > tree = ldb_parse_tree ( req , io - > in . filter ) ;
if ( search - > tree = = NULL ) {
goto failed ;
}
2005-05-10 06:01:25 +04:00
2005-09-14 02:05:45 +04:00
if ( ! ldap_encode ( msg , & req - > encoded , req ) ) {
2005-05-10 06:01:25 +04:00
DEBUG ( 0 , ( " Failed to encode cldap message to %s:%d \n " ,
2006-01-10 01:12:53 +03:00
req - > dest - > addr , req - > dest - > port ) ) ;
2005-05-10 06:01:25 +04:00
goto failed ;
}
DLIST_ADD_END ( cldap - > send_queue , req , struct cldap_request * ) ;
EVENT_FD_WRITEABLE ( cldap - > fde ) ;
return req ;
failed :
talloc_free ( req ) ;
return NULL ;
}
2005-05-12 12:25:35 +04:00
/*
queue a cldap reply for send
*/
NTSTATUS cldap_reply_send ( struct cldap_socket * cldap , struct cldap_reply * io )
{
2005-06-15 04:27:51 +04:00
struct ldap_message * msg ;
2005-05-12 12:25:35 +04:00
struct cldap_request * req ;
DATA_BLOB blob1 , blob2 ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
req = talloc_zero ( cldap , struct cldap_request ) ;
if ( req = = NULL ) goto failed ;
req - > cldap = cldap ;
req - > state = CLDAP_REQUEST_SEND ;
req - > is_reply = True ;
2006-01-10 01:12:53 +03:00
req - > dest = io - > dest ;
if ( talloc_reference ( req , io - > dest ) = = NULL ) goto failed ;
2005-05-12 12:25:35 +04:00
talloc_set_destructor ( req , cldap_request_destructor ) ;
2005-06-15 04:27:51 +04:00
msg = talloc ( req , struct ldap_message ) ;
if ( msg = = NULL ) goto failed ;
msg - > messageid = io - > messageid ;
msg - > controls = NULL ;
2005-05-12 12:25:35 +04:00
if ( io - > response ) {
2005-06-15 04:27:51 +04:00
msg - > type = LDAP_TAG_SearchResultEntry ;
msg - > r . SearchResultEntry = * io - > response ;
2005-05-12 12:25:35 +04:00
2005-09-14 02:05:45 +04:00
if ( ! ldap_encode ( msg , & blob1 , req ) ) {
2005-05-12 12:25:35 +04:00
DEBUG ( 0 , ( " Failed to encode cldap message to %s:%d \n " ,
2006-01-10 01:12:53 +03:00
req - > dest - > addr , req - > dest - > port ) ) ;
2005-05-12 12:25:35 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
goto failed ;
}
} else {
blob1 = data_blob ( NULL , 0 ) ;
}
2005-06-15 04:27:51 +04:00
msg - > type = LDAP_TAG_SearchResultDone ;
msg - > r . SearchResultDone = * io - > result ;
2005-05-12 12:25:35 +04:00
2005-09-14 02:05:45 +04:00
if ( ! ldap_encode ( msg , & blob2 , req ) ) {
2005-05-12 12:25:35 +04:00
DEBUG ( 0 , ( " Failed to encode cldap message to %s:%d \n " ,
2006-01-10 01:12:53 +03:00
req - > dest - > addr , req - > dest - > port ) ) ;
2005-05-12 12:25:35 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
goto failed ;
}
req - > encoded = data_blob_talloc ( req , NULL , blob1 . length + blob2 . length ) ;
if ( req - > encoded . data = = NULL ) goto failed ;
memcpy ( req - > encoded . data , blob1 . data , blob1 . length ) ;
memcpy ( req - > encoded . data + blob1 . length , blob2 . data , blob2 . length ) ;
DLIST_ADD_END ( cldap - > send_queue , req , struct cldap_request * ) ;
EVENT_FD_WRITEABLE ( cldap - > fde ) ;
return NT_STATUS_OK ;
failed :
talloc_free ( req ) ;
return status ;
}
2005-05-10 06:01:25 +04:00
/*
receive a cldap reply
*/
NTSTATUS cldap_search_recv ( struct cldap_request * req ,
TALLOC_CTX * mem_ctx ,
struct cldap_search * io )
{
2005-06-15 04:27:51 +04:00
struct ldap_message * ldap_msg ;
2007-03-13 03:59:06 +03:00
NTSTATUS status ;
2005-05-10 06:01:25 +04:00
if ( req = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
while ( req - > state < CLDAP_REQUEST_DONE ) {
if ( event_loop_once ( req - > cldap - > event_ctx ) ! = 0 ) {
talloc_free ( req ) ;
return NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
}
}
2007-04-05 11:37:21 +04:00
if ( req - > state = = CLDAP_REQUEST_ERROR ) {
status = req - > status ;
2005-05-10 06:01:25 +04:00
talloc_free ( req ) ;
2007-04-05 11:37:21 +04:00
return status ;
2005-05-10 06:01:25 +04:00
}
2005-06-15 04:27:51 +04:00
ldap_msg = talloc ( mem_ctx , struct ldap_message ) ;
NT_STATUS_HAVE_NO_MEMORY ( ldap_msg ) ;
2005-05-10 06:01:25 +04:00
2007-03-13 03:59:06 +03:00
status = ldap_decode ( & req - > asn1 , ldap_msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " Failed to decode cldap search reply: %s \n " , nt_errstr ( status ) ) ) ;
2005-05-10 06:01:25 +04:00
talloc_free ( req ) ;
2007-03-13 03:59:06 +03:00
return status ;
2005-05-10 06:01:25 +04:00
}
ZERO_STRUCT ( io - > out ) ;
/* the first possible form has a search result in first place */
2005-06-15 04:27:51 +04:00
if ( ldap_msg - > type = = LDAP_TAG_SearchResultEntry ) {
2005-05-10 06:01:25 +04:00
io - > out . response = talloc ( mem_ctx , struct ldap_SearchResEntry ) ;
NT_STATUS_HAVE_NO_MEMORY ( io - > out . response ) ;
2005-06-15 04:27:51 +04:00
* io - > out . response = ldap_msg - > r . SearchResultEntry ;
2005-05-10 06:01:25 +04:00
/* decode the 2nd part */
2007-03-13 03:59:06 +03:00
status = ldap_decode ( & req - > asn1 , ldap_msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " Failed to decode cldap search result entry: %s \n " , nt_errstr ( status ) ) ) ;
2005-05-10 06:01:25 +04:00
talloc_free ( req ) ;
2007-03-13 03:59:06 +03:00
return status ;
2005-05-10 06:01:25 +04:00
}
}
2005-06-15 04:27:51 +04:00
if ( ldap_msg - > type ! = LDAP_TAG_SearchResultDone ) {
2005-05-10 06:01:25 +04:00
talloc_free ( req ) ;
2006-11-16 13:42:07 +03:00
return NT_STATUS_LDAP ( LDAP_PROTOCOL_ERROR ) ;
2005-05-10 06:01:25 +04:00
}
io - > out . result = talloc ( mem_ctx , struct ldap_Result ) ;
NT_STATUS_HAVE_NO_MEMORY ( io - > out . result ) ;
2005-06-15 04:27:51 +04:00
* io - > out . result = ldap_msg - > r . SearchResultDone ;
2005-05-10 06:01:25 +04:00
talloc_free ( req ) ;
2006-11-16 13:42:07 +03:00
if ( io - > out . result - > resultcode ! = LDAP_SUCCESS ) {
return NT_STATUS_LDAP ( io - > out . result - > resultcode ) ;
}
2005-05-10 06:01:25 +04:00
return NT_STATUS_OK ;
}
/*
synchronous cldap search
*/
NTSTATUS cldap_search ( struct cldap_socket * cldap ,
TALLOC_CTX * mem_ctx ,
struct cldap_search * io )
{
struct cldap_request * req = cldap_search_send ( cldap , io ) ;
return cldap_search_recv ( req , mem_ctx , io ) ;
}
2005-05-13 10:08:49 +04:00
2005-05-10 06:01:25 +04:00
/*
queue a cldap netlogon for send
*/
struct cldap_request * cldap_netlogon_send ( struct cldap_socket * cldap ,
struct cldap_netlogon * io )
{
struct cldap_search search ;
char * filter ;
struct cldap_request * req ;
const char * attr [ ] = { " NetLogon " , NULL } ;
2005-05-13 10:08:49 +04:00
TALLOC_CTX * tmp_ctx = talloc_new ( cldap ) ;
2005-05-10 06:01:25 +04:00
2005-05-13 10:28:22 +04:00
filter = talloc_asprintf ( tmp_ctx , " (&(NtVer=%s) " ,
2005-05-13 10:08:49 +04:00
ldap_encode_ndr_uint32 ( tmp_ctx , io - > in . version ) ) ;
if ( filter = = NULL ) goto failed ;
if ( io - > in . user ) {
filter = talloc_asprintf_append ( filter , " (User=%s) " , io - > in . user ) ;
2005-05-13 10:28:22 +04:00
if ( filter = = NULL ) goto failed ;
}
if ( io - > in . host ) {
filter = talloc_asprintf_append ( filter , " (Host=%s) " , io - > in . host ) ;
if ( filter = = NULL ) goto failed ;
}
if ( io - > in . realm ) {
filter = talloc_asprintf_append ( filter , " (DnsDomain=%s) " , io - > in . realm ) ;
if ( filter = = NULL ) goto failed ;
2005-05-13 10:08:49 +04:00
}
if ( io - > in . acct_control ! = - 1 ) {
filter = talloc_asprintf_append ( filter , " (AAC=%s) " ,
ldap_encode_ndr_uint32 ( tmp_ctx , io - > in . acct_control ) ) ;
2005-05-13 10:28:22 +04:00
if ( filter = = NULL ) goto failed ;
2005-05-13 10:08:49 +04:00
}
if ( io - > in . domain_sid ) {
struct dom_sid * sid = dom_sid_parse_talloc ( tmp_ctx , io - > in . domain_sid ) ;
if ( sid = = NULL ) goto failed ;
filter = talloc_asprintf_append ( filter , " (domainSid=%s) " ,
ldap_encode_ndr_dom_sid ( tmp_ctx , sid ) ) ;
2005-05-13 10:28:22 +04:00
if ( filter = = NULL ) goto failed ;
2005-05-13 10:08:49 +04:00
}
if ( io - > in . domain_guid ) {
struct GUID guid ;
NTSTATUS status ;
status = GUID_from_string ( io - > in . domain_guid , & guid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
filter = talloc_asprintf_append ( filter , " (DomainGuid=%s) " ,
ldap_encode_ndr_GUID ( tmp_ctx , & guid ) ) ;
2005-05-13 10:28:22 +04:00
if ( filter = = NULL ) goto failed ;
2005-05-13 10:08:49 +04:00
}
filter = talloc_asprintf_append ( filter , " ) " ) ;
if ( filter = = NULL ) goto failed ;
2005-05-10 06:01:25 +04:00
search . in . dest_address = io - > in . dest_address ;
search . in . filter = filter ;
search . in . attributes = attr ;
search . in . timeout = 2 ;
search . in . retries = 2 ;
req = cldap_search_send ( cldap , & search ) ;
2005-05-13 10:08:49 +04:00
talloc_free ( tmp_ctx ) ;
2005-05-10 06:01:25 +04:00
return req ;
2005-05-13 10:08:49 +04:00
failed :
talloc_free ( tmp_ctx ) ;
return NULL ;
2005-05-10 06:01:25 +04:00
}
/*
receive a cldap netlogon reply
*/
NTSTATUS cldap_netlogon_recv ( struct cldap_request * req ,
TALLOC_CTX * mem_ctx ,
struct cldap_netlogon * io )
{
NTSTATUS status ;
struct cldap_search search ;
DATA_BLOB * data ;
status = cldap_search_recv ( req , mem_ctx , & search ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( search . out . response = = NULL ) {
2005-05-13 10:08:49 +04:00
return NT_STATUS_NOT_FOUND ;
2005-05-10 06:01:25 +04:00
}
if ( search . out . response - > num_attributes ! = 1 | |
strcasecmp ( search . out . response - > attributes [ 0 ] . name , " netlogon " ) ! = 0 | |
search . out . response - > attributes [ 0 ] . num_values ! = 1 | |
search . out . response - > attributes [ 0 ] . values - > length < 2 ) {
return NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
}
data = search . out . response - > attributes [ 0 ] . values ;
2005-05-11 03:33:56 +04:00
status = ndr_pull_union_blob ( data , mem_ctx , & io - > out . netlogon ,
io - > in . version & 0xF ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_cldap_netlogon ) ;
2005-05-10 06:01:25 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " cldap failed to parse netlogon response of type 0x%02x \n " ,
SVAL ( data - > data , 0 ) ) ) ;
dump_data ( 10 , data - > data , data - > length ) ;
}
return status ;
}
/*
sync cldap netlogon search
*/
NTSTATUS cldap_netlogon ( struct cldap_socket * cldap ,
TALLOC_CTX * mem_ctx , struct cldap_netlogon * io )
{
struct cldap_request * req = cldap_netlogon_send ( cldap , io ) ;
return cldap_netlogon_recv ( req , mem_ctx , io ) ;
}
2005-05-12 12:25:35 +04:00
/*
send an empty reply ( used on any error , so the client doesn ' t keep waiting
or send the bad request again )
*/
NTSTATUS cldap_empty_reply ( struct cldap_socket * cldap ,
uint32_t message_id ,
2006-01-10 01:12:53 +03:00
struct socket_address * src )
2005-05-12 12:25:35 +04:00
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_Result result ;
reply . messageid = message_id ;
2006-01-10 01:12:53 +03:00
reply . dest = src ;
2005-05-12 12:25:35 +04:00
reply . response = NULL ;
reply . result = & result ;
ZERO_STRUCT ( result ) ;
status = cldap_reply_send ( cldap , & reply ) ;
return status ;
}
2006-11-15 20:08:45 +03:00
/*
send an error reply ( used on any error , so the client doesn ' t keep waiting
or send the bad request again )
*/
NTSTATUS cldap_error_reply ( struct cldap_socket * cldap ,
uint32_t message_id ,
struct socket_address * src ,
int resultcode ,
const char * errormessage )
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_Result result ;
reply . messageid = message_id ;
reply . dest = src ;
reply . response = NULL ;
reply . result = & result ;
ZERO_STRUCT ( result ) ;
result . resultcode = resultcode ;
result . errormessage = errormessage ;
status = cldap_reply_send ( cldap , & reply ) ;
return status ;
}
2005-05-12 12:25:35 +04:00
/*
send a netlogon reply
*/
NTSTATUS cldap_netlogon_reply ( struct cldap_socket * cldap ,
uint32_t message_id ,
2006-01-10 01:12:53 +03:00
struct socket_address * src ,
2005-05-12 12:25:35 +04:00
uint32_t version ,
union nbt_cldap_netlogon * netlogon )
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_SearchResEntry response ;
struct ldap_Result result ;
TALLOC_CTX * tmp_ctx = talloc_new ( cldap ) ;
DATA_BLOB blob ;
status = ndr_push_union_blob ( & blob , tmp_ctx , netlogon , version & 0xF ,
( ndr_push_flags_fn_t ) ndr_push_nbt_cldap_netlogon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return status ;
}
reply . messageid = message_id ;
2006-01-10 01:12:53 +03:00
reply . dest = src ;
2005-05-12 12:25:35 +04:00
reply . response = & response ;
reply . result = & result ;
ZERO_STRUCT ( result ) ;
response . dn = " " ;
response . num_attributes = 1 ;
2005-06-15 05:02:53 +04:00
response . attributes = talloc ( tmp_ctx , struct ldb_message_element ) ;
2005-05-12 12:25:35 +04:00
NT_STATUS_HAVE_NO_MEMORY ( response . attributes ) ;
response . attributes - > name = " netlogon " ;
response . attributes - > num_values = 1 ;
response . attributes - > values = & blob ;
status = cldap_reply_send ( cldap , & reply ) ;
talloc_free ( tmp_ctx ) ;
return status ;
}