2005-05-10 06:01:25 +04:00
/*
Unix SMB / CIFS implementation .
cldap client library
Copyright ( C ) Andrew Tridgell 2005
2009-02-13 15:13:54 +03:00
Copyright ( C ) Stefan Metzmacher 2009
2005-05-10 06:01:25 +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-10 06:01:25 +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-10 06:01:25 +04:00
*/
/*
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"
2009-02-13 15:13:54 +03:00
# include <tevent.h>
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2009-03-18 19:43:11 +03:00
# include "../libcli/ldap/ldap_message.h"
# include "../libcli/ldap/ldap_ndr.h"
# include "../libcli/cldap/cldap.h"
2009-02-13 15:13:54 +03:00
# include "../lib/tsocket/tsocket.h"
2009-03-18 19:43:11 +03:00
# include "../libcli/security/dom_sid.h"
# include "../librpc/gen_ndr/ndr_nbt.h"
2009-02-13 15:13:54 +03:00
# include "../lib/util/asn1.h"
# include "../lib/util/tevent_ntstatus.h"
2005-05-10 06:01:25 +04:00
2009-03-18 19:43:11 +03:00
# undef strcasecmp
2005-05-10 06:01:25 +04:00
/*
2009-02-13 15:13:54 +03:00
context structure for operations on cldap packets
2005-05-10 06:01:25 +04:00
*/
2009-02-13 15:13:54 +03:00
struct cldap_socket {
/* the low level socket */
2009-03-29 01:31:01 +03:00
struct tdgram_context * sock ;
2009-02-13 15:13:54 +03:00
/*
* Are we in connected mode , which means
* we get ICMP errors back instead of timing
* out requests . And we can only send requests
* to the connected peer .
*/
bool connected ;
/* the queue for outgoing dgrams */
struct tevent_queue * send_queue ;
/* do we have an async tsocket_recvfrom request pending */
struct tevent_req * recv_subreq ;
struct {
/* a queue of pending search requests */
struct cldap_search_state * list ;
/* mapping from message_id to pending request */
struct idr_context * idr ;
} searches ;
/* what to do with incoming request packets */
struct {
2011-10-10 17:38:22 +04:00
struct tevent_context * ev ;
2009-02-13 15:13:54 +03:00
void ( * handler ) ( struct cldap_socket * ,
void * private_data ,
struct cldap_incoming * ) ;
void * private_data ;
} incoming ;
} ;
struct cldap_search_state {
struct cldap_search_state * prev , * next ;
struct {
2011-10-10 17:46:17 +04:00
struct tevent_context * ev ;
2009-02-13 15:13:54 +03:00
struct cldap_socket * cldap ;
} caller ;
int message_id ;
struct {
uint32_t idx ;
uint32_t delay ;
uint32_t count ;
struct tsocket_address * dest ;
DATA_BLOB blob ;
} request ;
struct {
struct cldap_incoming * in ;
struct asn1_data * asn1 ;
} response ;
struct tevent_req * req ;
} ;
static int cldap_socket_destructor ( struct cldap_socket * c )
2005-05-10 06:01:25 +04:00
{
2009-02-13 15:13:54 +03:00
while ( c - > searches . list ) {
struct cldap_search_state * s = c - > searches . list ;
DLIST_REMOVE ( c - > searches . list , s ) ;
ZERO_STRUCT ( s - > caller ) ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
talloc_free ( c - > recv_subreq ) ;
talloc_free ( c - > send_queue ) ;
talloc_free ( c - > sock ) ;
2005-05-10 06:01:25 +04:00
return 0 ;
}
2009-02-13 15:13:54 +03:00
static void cldap_recvfrom_done ( struct tevent_req * subreq ) ;
2007-05-21 16:47:18 +04:00
2009-02-13 15:13:54 +03:00
static bool cldap_recvfrom_setup ( struct cldap_socket * c )
{
2011-10-10 17:48:11 +04:00
struct tevent_context * ev ;
2009-02-13 15:13:54 +03:00
if ( c - > recv_subreq ) {
return true ;
2005-06-03 17:37:23 +04:00
}
2009-02-13 15:13:54 +03:00
if ( ! c - > searches . list & & ! c - > incoming . handler ) {
return true ;
2005-05-10 06:01:25 +04:00
}
2011-10-10 17:48:11 +04:00
ev = c - > incoming . ev ;
if ( ev = = NULL ) {
ev = c - > searches . list - > caller . ev ;
}
c - > recv_subreq = tdgram_recvfrom_send ( c , ev , c - > sock ) ;
2009-02-13 15:13:54 +03:00
if ( ! c - > recv_subreq ) {
return false ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
tevent_req_set_callback ( c - > recv_subreq , cldap_recvfrom_done , c ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
return true ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
static void cldap_recvfrom_stop ( struct cldap_socket * c )
{
if ( ! c - > recv_subreq ) {
2005-05-10 06:01:25 +04:00
return ;
}
2009-02-13 15:13:54 +03:00
if ( c - > searches . list | | c - > incoming . handler ) {
2005-06-15 04:27:51 +04:00
return ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
talloc_free ( c - > recv_subreq ) ;
c - > recv_subreq = NULL ;
}
2005-05-10 06:01:25 +04:00
2010-09-15 08:24:51 +04:00
static bool cldap_socket_recv_dgram ( struct cldap_socket * c ,
2009-02-13 15:13:54 +03:00
struct cldap_incoming * in ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
static void cldap_recvfrom_done ( struct tevent_req * subreq )
{
struct cldap_socket * c = tevent_req_callback_data ( subreq ,
struct cldap_socket ) ;
struct cldap_incoming * in = NULL ;
ssize_t ret ;
2010-09-15 08:24:51 +04:00
bool setup_done ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
c - > recv_subreq = NULL ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
in = talloc_zero ( c , struct cldap_incoming ) ;
if ( ! in ) {
goto nomem ;
2005-05-10 06:01:25 +04:00
}
2009-03-29 01:31:01 +03:00
ret = tdgram_recvfrom_recv ( subreq ,
& in - > recv_errno ,
in ,
& in - > buf ,
& in - > src ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( subreq ) ;
subreq = NULL ;
if ( ret > = 0 ) {
in - > len = ret ;
}
if ( ret = = - 1 & & in - > recv_errno = = 0 ) {
in - > recv_errno = EIO ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
/* this function should free or steal 'in' */
2010-09-15 08:24:51 +04:00
setup_done = cldap_socket_recv_dgram ( c , in ) ;
2009-02-13 15:13:54 +03:00
in = NULL ;
2005-05-10 06:01:25 +04:00
2010-09-15 08:24:51 +04:00
if ( ! setup_done & & ! cldap_recvfrom_setup ( c ) ) {
2009-02-13 15:13:54 +03:00
goto nomem ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
return ;
nomem :
talloc_free ( subreq ) ;
talloc_free ( in ) ;
2005-05-10 06:01:25 +04:00
}
/*
2009-02-13 15:13:54 +03:00
handle recv events on a cldap socket
2005-05-10 06:01:25 +04:00
*/
2010-09-15 08:24:51 +04:00
static bool cldap_socket_recv_dgram ( struct cldap_socket * c ,
2009-02-13 15:13:54 +03:00
struct cldap_incoming * in )
2005-05-10 06:01:25 +04:00
{
2009-02-13 15:13:54 +03:00
struct asn1_data * asn1 ;
void * p ;
struct cldap_search_state * search ;
2005-05-10 06:01:25 +04:00
NTSTATUS status ;
2009-02-13 15:13:54 +03:00
if ( in - > recv_errno ! = 0 ) {
goto error ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
asn1 = asn1_init ( in ) ;
if ( ! asn1 ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2016-01-04 12:30:35 +03:00
asn1_load_nocopy ( asn1 , in - > buf , in - > len ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
in - > ldap_msg = talloc ( in , struct ldap_message ) ;
if ( in - > ldap_msg = = NULL ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
/* this initial decode is used to find the message id */
status = ldap_decode ( asn1 , NULL , in - > ldap_msg ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto nterror ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
/* find the pending request */
p = idr_find ( c - > searches . idr , in - > ldap_msg - > messageid ) ;
if ( p = = NULL ) {
if ( ! c - > incoming . handler ) {
2011-11-10 17:43:55 +04:00
TALLOC_FREE ( in ) ;
return true ;
2009-02-13 15:13:54 +03:00
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
/* this function should free or steal 'in' */
c - > incoming . handler ( c , c - > incoming . private_data , in ) ;
2010-09-15 08:24:51 +04:00
return false ;
2009-02-13 15:13:54 +03:00
}
2005-05-10 06:01:25 +04:00
2011-11-10 17:43:55 +04:00
search = talloc_get_type_abort ( p , struct cldap_search_state ) ;
2009-02-13 15:13:54 +03:00
search - > response . in = talloc_move ( search , & in ) ;
2016-01-04 12:30:35 +03:00
2009-02-13 15:13:54 +03:00
search - > response . asn1 = asn1 ;
2016-01-04 12:30:35 +03:00
asn1_load_nocopy ( search - > response . asn1 ,
search - > response . in - > buf , search - > response . in - > len ) ;
2009-02-13 15:13:54 +03:00
2010-09-15 08:24:51 +04:00
DLIST_REMOVE ( c - > searches . list , search ) ;
2011-11-10 17:43:55 +04:00
if ( cldap_recvfrom_setup ( c ) ) {
tevent_req_done ( search - > req ) ;
return true ;
2010-09-15 08:24:51 +04:00
}
2011-11-10 17:43:55 +04:00
/*
* This request was ok , just defer the notify of the caller
* and then just fail the next request if needed
*/
tevent_req_defer_callback ( search - > req , search - > caller . ev ) ;
2009-02-13 15:13:54 +03:00
tevent_req_done ( search - > req ) ;
2011-11-10 17:43:55 +04:00
status = NT_STATUS_NO_MEMORY ;
/* in is NULL it this point */
goto nterror ;
2009-02-13 15:13:54 +03:00
nomem :
in - > recv_errno = ENOMEM ;
error :
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( in - > recv_errno ) ;
2009-02-13 15:13:54 +03:00
nterror :
2011-11-10 17:43:55 +04:00
TALLOC_FREE ( in ) ;
2009-02-13 15:13:54 +03:00
/* in connected mode the first pending search gets the error */
if ( ! c - > connected ) {
/* otherwise we just ignore the error */
2011-11-10 17:43:55 +04:00
return false ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
if ( ! c - > searches . list ) {
2011-11-10 17:43:55 +04:00
return false ;
2009-02-13 15:13:54 +03:00
}
2011-11-10 17:43:55 +04:00
/*
* We might called tevent_req_done ( ) for a successful
* search before , so we better deliver the failure
* after the success , that is why we better also
* use tevent_req_defer_callback ( ) here .
*/
tevent_req_defer_callback ( c - > searches . list - > req ,
c - > searches . list - > caller . ev ) ;
2009-02-13 15:13:54 +03:00
tevent_req_nterror ( c - > searches . list - > req , status ) ;
2010-09-15 08:24:51 +04:00
return false ;
2005-05-10 06:01:25 +04:00
}
/*
2009-02-13 15:13:54 +03:00
initialise a cldap_sock
2005-05-10 06:01:25 +04:00
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_socket_init ( TALLOC_CTX * mem_ctx ,
const struct tsocket_address * local_addr ,
const struct tsocket_address * remote_addr ,
struct cldap_socket * * _cldap )
2005-05-10 06:01:25 +04:00
{
2009-02-13 15:13:54 +03:00
struct cldap_socket * c = NULL ;
struct tsocket_address * any = NULL ;
2005-05-10 06:01:25 +04:00
NTSTATUS status ;
2009-02-13 15:13:54 +03:00
int ret ;
2011-10-21 11:49:30 +04:00
const char * fam = NULL ;
if ( local_addr = = NULL & & remote_addr = = NULL ) {
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
if ( remote_addr ) {
bool is_ipv4 ;
bool is_ipv6 ;
is_ipv4 = tsocket_address_is_inet ( remote_addr , " ipv4 " ) ;
is_ipv6 = tsocket_address_is_inet ( remote_addr , " ipv6 " ) ;
if ( is_ipv4 ) {
fam = " ipv4 " ;
} else if ( is_ipv6 ) {
fam = " ipv6 " ;
} else {
return NT_STATUS_INVALID_ADDRESS ;
}
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
c = talloc_zero ( mem_ctx , struct cldap_socket ) ;
if ( ! c ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
if ( ! local_addr ) {
2011-10-21 11:49:30 +04:00
/*
2011-10-21 18:11:41 +04:00
* Here we know the address family of the remote address .
2011-10-21 11:49:30 +04:00
*/
2011-10-21 18:11:41 +04:00
if ( fam = = NULL ) {
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
2011-10-21 11:49:30 +04:00
ret = tsocket_address_inet_from_strings ( c , fam ,
2009-02-13 15:13:54 +03:00
NULL , 0 ,
& any ) ;
if ( ret ! = 0 ) {
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
2009-02-13 15:13:54 +03:00
goto nterror ;
}
local_addr = any ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
c - > searches . idr = idr_init ( c ) ;
if ( ! c - > searches . idr ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-03-29 01:31:01 +03:00
ret = tdgram_inet_udp_socket ( local_addr , remote_addr ,
c , & c - > sock ) ;
2009-02-13 15:13:54 +03:00
if ( ret ! = 0 ) {
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
2009-02-13 15:13:54 +03:00
goto nterror ;
}
talloc_free ( any ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
if ( remote_addr ) {
c - > connected = true ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
c - > send_queue = tevent_queue_create ( c , " cldap_send_queue " ) ;
if ( ! c - > send_queue ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
talloc_set_destructor ( c , cldap_socket_destructor ) ;
* _cldap = c ;
return NT_STATUS_OK ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
nomem :
status = NT_STATUS_NO_MEMORY ;
nterror :
talloc_free ( c ) ;
return status ;
}
2005-05-10 06:01:25 +04:00
2005-05-11 08:48:30 +04:00
/*
setup a handler for incoming requests
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_set_incoming_handler ( struct cldap_socket * c ,
2011-10-10 17:38:22 +04:00
struct tevent_context * ev ,
2009-02-13 15:13:54 +03:00
void ( * handler ) ( struct cldap_socket * ,
void * private_data ,
struct cldap_incoming * ) ,
void * private_data )
2005-05-11 08:48:30 +04:00
{
2009-02-13 15:13:54 +03:00
if ( c - > connected ) {
return NT_STATUS_PIPE_CONNECTED ;
}
2011-10-10 17:38:22 +04:00
c - > incoming . ev = ev ;
2009-02-13 15:13:54 +03:00
c - > incoming . handler = handler ;
c - > incoming . private_data = private_data ;
if ( ! cldap_recvfrom_setup ( c ) ) {
ZERO_STRUCT ( c - > incoming ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-05-11 08:48:30 +04:00
return NT_STATUS_OK ;
}
2009-02-13 15:13:54 +03:00
struct cldap_reply_state {
struct tsocket_address * dest ;
DATA_BLOB blob ;
} ;
2009-03-29 01:31:01 +03:00
static void cldap_reply_state_destroy ( struct tevent_req * subreq ) ;
2009-02-13 15:13:54 +03:00
2005-05-10 06:01:25 +04:00
/*
2009-02-13 15:13:54 +03:00
queue a cldap reply for send
2005-05-10 06:01:25 +04:00
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_reply_send ( struct cldap_socket * cldap , struct cldap_reply * io )
2005-05-10 06:01:25 +04:00
{
2009-02-13 15:13:54 +03:00
struct cldap_reply_state * state = NULL ;
2005-06-15 04:27:51 +04:00
struct ldap_message * msg ;
2009-02-13 15:13:54 +03:00
DATA_BLOB blob1 , blob2 ;
NTSTATUS status ;
2009-03-29 01:31:01 +03:00
struct tevent_req * subreq ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
if ( cldap - > connected ) {
return NT_STATUS_PIPE_CONNECTED ;
}
2005-05-10 06:01:25 +04:00
2011-10-10 17:48:11 +04:00
if ( cldap - > incoming . ev = = NULL ) {
return NT_STATUS_INVALID_PIPE_STATE ;
}
2009-02-13 15:13:54 +03:00
if ( ! io - > dest ) {
return NT_STATUS_INVALID_ADDRESS ;
2007-05-22 04:43:10 +04:00
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
state = talloc ( cldap , struct cldap_reply_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( state ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
state - > dest = tsocket_address_copy ( io - > dest , state ) ;
if ( ! state - > dest ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
msg = talloc ( state , struct ldap_message ) ;
if ( ! msg ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
msg - > messageid = io - > messageid ;
2005-06-15 04:27:51 +04:00
msg - > controls = NULL ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
if ( io - > response ) {
msg - > type = LDAP_TAG_SearchResultEntry ;
msg - > r . SearchResultEntry = * io - > response ;
if ( ! ldap_encode ( msg , NULL , & blob1 , state ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto failed ;
}
} else {
blob1 = data_blob ( NULL , 0 ) ;
2005-06-13 13:10:17 +04:00
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
msg - > type = LDAP_TAG_SearchResultDone ;
msg - > r . SearchResultDone = * io - > result ;
if ( ! ldap_encode ( msg , NULL , & blob2 , state ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
2005-05-10 06:01:25 +04:00
goto failed ;
}
2009-02-13 15:13:54 +03:00
talloc_free ( msg ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
state - > blob = data_blob_talloc ( state , NULL , blob1 . length + blob2 . length ) ;
if ( ! state - > blob . data ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
memcpy ( state - > blob . data , blob1 . data , blob1 . length ) ;
memcpy ( state - > blob . data + blob1 . length , blob2 . data , blob2 . length ) ;
data_blob_free ( & blob1 ) ;
data_blob_free ( & blob2 ) ;
2009-03-29 01:31:01 +03:00
subreq = tdgram_sendto_queue_send ( state ,
2011-10-10 17:48:11 +04:00
cldap - > incoming . ev ,
2009-03-29 01:31:01 +03:00
cldap - > sock ,
cldap - > send_queue ,
state - > blob . data ,
state - > blob . length ,
state - > dest ) ;
if ( ! subreq ) {
2009-02-13 15:13:54 +03:00
goto nomem ;
}
/* the callback will just free the state, as we don't need a result */
2009-03-29 01:31:01 +03:00
tevent_req_set_callback ( subreq , cldap_reply_state_destroy , state ) ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
return NT_STATUS_OK ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
nomem :
status = NT_STATUS_NO_MEMORY ;
2005-05-10 06:01:25 +04:00
failed :
2009-02-13 15:13:54 +03:00
talloc_free ( state ) ;
return status ;
}
2009-03-29 01:31:01 +03:00
static void cldap_reply_state_destroy ( struct tevent_req * subreq )
2009-02-13 15:13:54 +03:00
{
2009-03-29 01:31:01 +03:00
struct cldap_reply_state * state = tevent_req_callback_data ( subreq ,
2009-02-13 15:13:54 +03:00
struct cldap_reply_state ) ;
/* we don't want to know the result here, we just free the state */
2009-03-29 01:31:01 +03:00
talloc_free ( subreq ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( state ) ;
}
static int cldap_search_state_destructor ( struct cldap_search_state * s )
{
if ( s - > caller . cldap ) {
2009-03-29 01:27:47 +03:00
if ( s - > message_id ! = - 1 ) {
idr_remove ( s - > caller . cldap - > searches . idr , s - > message_id ) ;
s - > message_id = - 1 ;
}
2009-02-13 15:13:54 +03:00
DLIST_REMOVE ( s - > caller . cldap - > searches . list , s ) ;
cldap_recvfrom_stop ( s - > caller . cldap ) ;
ZERO_STRUCT ( s - > caller ) ;
}
return 0 ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
static void cldap_search_state_queue_done ( struct tevent_req * subreq ) ;
static void cldap_search_state_wakeup_done ( struct tevent_req * subreq ) ;
2005-05-12 12:25:35 +04:00
/*
queue a cldap reply for send
*/
2009-02-13 15:13:54 +03:00
struct tevent_req * cldap_search_send ( TALLOC_CTX * mem_ctx ,
2011-10-10 17:46:17 +04:00
struct tevent_context * ev ,
struct cldap_socket * cldap ,
const struct cldap_search * io )
2005-05-12 12:25:35 +04:00
{
2009-02-13 15:13:54 +03:00
struct tevent_req * req , * subreq ;
struct cldap_search_state * state = NULL ;
2005-06-15 04:27:51 +04:00
struct ldap_message * msg ;
2009-02-13 15:13:54 +03:00
struct ldap_SearchRequest * search ;
struct timeval now ;
struct timeval end ;
uint32_t i ;
int ret ;
req = tevent_req_create ( mem_ctx , & state ,
struct cldap_search_state ) ;
if ( ! req ) {
return NULL ;
}
2011-10-10 17:46:17 +04:00
state - > caller . ev = ev ;
2009-02-13 15:13:54 +03:00
state - > req = req ;
state - > caller . cldap = cldap ;
2009-03-29 01:27:47 +03:00
state - > message_id = - 1 ;
talloc_set_destructor ( state , cldap_search_state_destructor ) ;
2009-02-13 15:13:54 +03:00
2016-10-17 20:07:23 +03:00
if ( state - > caller . cldap = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto post ;
}
2009-02-13 15:13:54 +03:00
if ( io - > in . dest_address ) {
if ( cldap - > connected ) {
tevent_req_nterror ( req , NT_STATUS_PIPE_CONNECTED ) ;
goto post ;
}
ret = tsocket_address_inet_from_strings ( state ,
2009-06-09 02:21:48 +04:00
" ip " ,
2009-02-13 15:13:54 +03:00
io - > in . dest_address ,
io - > in . dest_port ,
& state - > request . dest ) ;
if ( ret ! = 0 ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto post ;
}
} else {
if ( ! cldap - > connected ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_ADDRESS ) ;
goto post ;
}
state - > request . dest = NULL ;
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
state - > message_id = idr_get_new_random ( cldap - > searches . idr ,
state , UINT16_MAX ) ;
if ( state - > message_id = = - 1 ) {
tevent_req_nterror ( req , NT_STATUS_INSUFFICIENT_RESOURCES ) ;
goto post ;
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
msg = talloc ( state , struct ldap_message ) ;
if ( tevent_req_nomem ( msg , req ) ) {
goto post ;
2007-05-22 04:43:10 +04:00
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
msg - > messageid = state - > message_id ;
msg - > type = LDAP_TAG_SearchRequest ;
msg - > controls = NULL ;
search = & msg - > r . SearchRequest ;
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03: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 ;
search - > tree = ldb_parse_tree ( msg , io - > in . filter ) ;
if ( tevent_req_nomem ( search - > tree , req ) ) {
goto post ;
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
if ( ! ldap_encode ( msg , NULL , & state - > request . blob , state ) ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto post ;
}
talloc_free ( msg ) ;
state - > request . idx = 0 ;
state - > request . delay = 10 * 1000 * 1000 ;
state - > request . count = 3 ;
if ( io - > in . timeout > 0 ) {
state - > request . delay = io - > in . timeout * 1000 * 1000 ;
state - > request . count = io - > in . retries + 1 ;
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
now = tevent_timeval_current ( ) ;
end = now ;
for ( i = 0 ; i < state - > request . count ; i + + ) {
2011-06-01 06:50:08 +04:00
end = tevent_timeval_add ( & end , state - > request . delay / 1000000 ,
state - > request . delay % 1000000 ) ;
2005-05-12 12:25:35 +04:00
}
2011-10-10 17:48:11 +04:00
if ( ! tevent_req_set_endtime ( req , state - > caller . ev , end ) ) {
2009-02-13 15:13:54 +03:00
goto post ;
}
2005-05-12 12:25:35 +04:00
2009-03-29 01:31:01 +03:00
subreq = tdgram_sendto_queue_send ( state ,
2011-10-10 17:48:11 +04:00
state - > caller . ev ,
2009-03-29 01:31:01 +03:00
state - > caller . cldap - > sock ,
state - > caller . cldap - > send_queue ,
state - > request . blob . data ,
state - > request . blob . length ,
state - > request . dest ) ;
2009-02-13 15:13:54 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
goto post ;
2005-05-12 12:25:35 +04:00
}
2009-02-13 15:13:54 +03:00
tevent_req_set_callback ( subreq , cldap_search_state_queue_done , req ) ;
2005-05-12 12:25:35 +04:00
2016-02-05 13:32:18 +03:00
DLIST_ADD_END ( cldap - > searches . list , state ) ;
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
return req ;
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
post :
2011-10-10 17:48:11 +04:00
return tevent_req_post ( req , state - > caller . ev ) ;
2009-02-13 15:13:54 +03:00
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
static void cldap_search_state_queue_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct cldap_search_state * state = tevent_req_data ( req ,
struct cldap_search_state ) ;
ssize_t ret ;
int sys_errno = 0 ;
struct timeval next ;
2009-03-29 01:31:01 +03:00
ret = tdgram_sendto_queue_recv ( subreq , & sys_errno ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( subreq ) ;
if ( ret = = - 1 ) {
NTSTATUS status ;
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( sys_errno ) ;
2009-02-13 15:13:54 +03:00
DLIST_REMOVE ( state - > caller . cldap - > searches . list , state ) ;
ZERO_STRUCT ( state - > caller . cldap ) ;
tevent_req_nterror ( req , status ) ;
return ;
}
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
state - > request . idx + + ;
2005-05-12 12:25:35 +04:00
2009-02-13 15:13:54 +03:00
/* wait for incoming traffic */
if ( ! cldap_recvfrom_setup ( state - > caller . cldap ) ) {
2011-06-19 23:10:01 +04:00
tevent_req_oom ( req ) ;
2009-02-13 15:13:54 +03:00
return ;
}
if ( state - > request . idx > state - > request . count ) {
/* we just wait for the response or a timeout */
return ;
}
2011-06-01 06:50:08 +04:00
next = tevent_timeval_current_ofs ( state - > request . delay / 1000000 ,
state - > request . delay % 1000000 ) ;
2009-02-13 15:13:54 +03:00
subreq = tevent_wakeup_send ( state ,
2011-10-10 17:48:11 +04:00
state - > caller . ev ,
2009-02-13 15:13:54 +03:00
next ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , cldap_search_state_wakeup_done , req ) ;
}
static void cldap_search_state_wakeup_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct cldap_search_state * state = tevent_req_data ( req ,
struct cldap_search_state ) ;
bool ok ;
ok = tevent_wakeup_recv ( subreq ) ;
talloc_free ( subreq ) ;
if ( ! ok ) {
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
2009-03-29 01:31:01 +03:00
subreq = tdgram_sendto_queue_send ( state ,
2011-10-10 17:48:11 +04:00
state - > caller . ev ,
2009-03-29 01:31:01 +03:00
state - > caller . cldap - > sock ,
state - > caller . cldap - > send_queue ,
state - > request . blob . data ,
state - > request . blob . length ,
state - > request . dest ) ;
2009-02-13 15:13:54 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , cldap_search_state_queue_done , req ) ;
2005-05-12 12:25:35 +04:00
}
2005-05-10 06:01:25 +04:00
/*
receive a cldap reply
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_search_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
2005-05-10 06:01:25 +04:00
struct cldap_search * io )
{
2009-02-13 15:13:54 +03:00
struct cldap_search_state * state = tevent_req_data ( req ,
struct cldap_search_state ) ;
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
2009-02-13 15:13:54 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
goto failed ;
2005-05-10 06:01:25 +04:00
}
2005-06-15 04:27:51 +04:00
ldap_msg = talloc ( mem_ctx , struct ldap_message ) ;
2009-02-13 15:13:54 +03:00
if ( ! ldap_msg ) {
goto nomem ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
status = ldap_decode ( state - > response . asn1 , NULL , ldap_msg ) ;
2007-03-13 03:59:06 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-02-13 15:13:54 +03:00
goto failed ;
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 ) ;
2009-02-13 15:13:54 +03:00
if ( ! io - > out . response ) {
goto nomem ;
}
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 */
2009-02-13 15:13:54 +03:00
status = ldap_decode ( state - > response . asn1 , NULL , ldap_msg ) ;
2007-03-13 03:59:06 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-02-13 15:13:54 +03:00
goto failed ;
2005-05-10 06:01:25 +04:00
}
}
2005-06-15 04:27:51 +04:00
if ( ldap_msg - > type ! = LDAP_TAG_SearchResultDone ) {
2009-02-13 15:13:54 +03:00
status = NT_STATUS_LDAP ( LDAP_PROTOCOL_ERROR ) ;
goto failed ;
2005-05-10 06:01:25 +04:00
}
io - > out . result = talloc ( mem_ctx , struct ldap_Result ) ;
2009-02-13 15:13:54 +03:00
if ( ! io - > out . result ) {
goto nomem ;
}
2005-06-15 04:27:51 +04:00
* io - > out . result = ldap_msg - > r . SearchResultDone ;
2005-05-10 06:01:25 +04:00
2006-11-16 13:42:07 +03:00
if ( io - > out . result - > resultcode ! = LDAP_SUCCESS ) {
2009-02-13 15:13:54 +03:00
status = NT_STATUS_LDAP ( io - > out . result - > resultcode ) ;
goto failed ;
2006-11-16 13:42:07 +03:00
}
2009-02-13 15:13:54 +03:00
tevent_req_received ( req ) ;
2005-05-10 06:01:25 +04:00
return NT_STATUS_OK ;
2009-02-13 15:13:54 +03:00
nomem :
status = NT_STATUS_NO_MEMORY ;
failed :
tevent_req_received ( req ) ;
return status ;
2005-05-10 06:01:25 +04:00
}
/*
synchronous cldap search
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_search ( struct cldap_socket * cldap ,
TALLOC_CTX * mem_ctx ,
2005-05-10 06:01:25 +04:00
struct cldap_search * io )
{
2011-10-10 17:48:11 +04:00
TALLOC_CTX * frame ;
2009-02-13 15:13:54 +03:00
struct tevent_req * req ;
2011-10-10 17:48:11 +04:00
struct tevent_context * ev ;
2009-02-13 15:13:54 +03:00
NTSTATUS status ;
2011-10-10 17:48:11 +04:00
if ( cldap - > searches . list ) {
return NT_STATUS_PIPE_BUSY ;
}
if ( cldap - > incoming . handler ) {
2009-02-13 15:13:54 +03:00
return NT_STATUS_INVALID_PIPE_STATE ;
}
2011-10-10 17:48:11 +04:00
frame = talloc_stackframe ( ) ;
2013-02-18 12:06:29 +04:00
ev = samba_tevent_context_init ( frame ) ;
2011-10-10 17:48:11 +04:00
if ( ev = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
2009-02-13 15:13:54 +03:00
}
2005-05-10 06:01:25 +04:00
2011-10-10 17:48:11 +04:00
req = cldap_search_send ( mem_ctx , ev , cldap , io ) ;
if ( req = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-05-10 06:01:25 +04:00
2011-10-10 17:48:11 +04:00
if ( ! tevent_req_poll ( req , ev ) ) {
status = map_nt_error_from_unix_common ( errno ) ;
TALLOC_FREE ( frame ) ;
return status ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:08:49 +04:00
2009-02-13 15:13:54 +03:00
status = cldap_search_recv ( req , mem_ctx , io ) ;
2011-10-10 17:48:11 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
2009-02-13 15:13:54 +03:00
2011-10-10 17:48:11 +04:00
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
2009-02-13 15:13:54 +03:00
}
struct cldap_netlogon_state {
struct cldap_search search ;
} ;
2013-10-28 17:19:57 +04:00
char * cldap_netlogon_create_filter ( TALLOC_CTX * mem_ctx ,
const struct cldap_netlogon * io )
2005-05-10 06:01:25 +04:00
{
char * filter ;
2009-02-13 15:13:54 +03:00
2013-10-28 17:19:57 +04:00
filter = talloc_asprintf ( mem_ctx , " (&(NtVer=%s) " ,
ldap_encode_ndr_uint32 ( mem_ctx , io - > in . version ) ) ;
if ( filter = = NULL )
2009-02-13 15:13:54 +03:00
return NULL ;
2005-05-10 06:01:25 +04:00
2005-05-13 10:08:49 +04:00
if ( io - > in . user ) {
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (User=%s) " , io - > in . user ) ;
2013-10-28 17:19:57 +04:00
if ( filter = = NULL ) {
return NULL ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:28:22 +04:00
}
if ( io - > in . host ) {
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (Host=%s) " , io - > in . host ) ;
2013-10-28 17:19:57 +04:00
if ( filter = = NULL ) {
return NULL ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:28:22 +04:00
}
if ( io - > in . realm ) {
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (DnsDomain=%s) " , io - > in . realm ) ;
2013-10-28 17:19:57 +04:00
if ( filter = = NULL ) {
return NULL ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:08:49 +04:00
}
if ( io - > in . acct_control ! = - 1 ) {
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (AAC=%s) " ,
2013-10-28 17:19:57 +04:00
ldap_encode_ndr_uint32 ( mem_ctx , io - > in . acct_control ) ) ;
if ( filter = = NULL ) {
return NULL ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:08:49 +04:00
}
if ( io - > in . domain_sid ) {
2013-10-28 17:19:57 +04:00
struct dom_sid * sid = dom_sid_parse_talloc ( mem_ctx , io - > in . domain_sid ) ;
2014-09-26 15:25:41 +04:00
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (domainSid=%s) " ,
2013-10-28 17:19:57 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ) ;
if ( filter = = NULL ) {
return NULL ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:08:49 +04:00
}
if ( io - > in . domain_guid ) {
struct GUID guid ;
2013-12-10 20:47:50 +04:00
GUID_from_string ( io - > in . domain_guid , & guid ) ;
2014-09-26 15:25:41 +04:00
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " (DomainGuid=%s) " ,
2013-10-28 17:19:57 +04:00
ldap_encode_ndr_GUID ( mem_ctx , & guid ) ) ;
if ( filter = = NULL ) {
return NULL ;
2009-02-13 15:13:54 +03:00
}
2005-05-13 10:08:49 +04:00
}
2007-09-15 03:21:00 +04:00
filter = talloc_asprintf_append_buffer ( filter , " ) " ) ;
2013-10-28 17:19:57 +04:00
return filter ;
}
static void cldap_netlogon_state_done ( struct tevent_req * subreq ) ;
/*
queue a cldap netlogon for send
*/
struct tevent_req * cldap_netlogon_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cldap_socket * cldap ,
const struct cldap_netlogon * io )
{
struct tevent_req * req , * subreq ;
struct cldap_netlogon_state * state ;
char * filter ;
static const char * const attr [ ] = { " NetLogon " , NULL } ;
req = tevent_req_create ( mem_ctx , & state ,
struct cldap_netlogon_state ) ;
if ( ! req ) {
return NULL ;
}
filter = cldap_netlogon_create_filter ( state , io ) ;
2009-02-13 15:13:54 +03:00
if ( tevent_req_nomem ( filter , req ) ) {
goto post ;
}
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
if ( io - > in . dest_address ) {
state - > search . in . dest_address = talloc_strdup ( state ,
io - > in . dest_address ) ;
if ( tevent_req_nomem ( state - > search . in . dest_address , req ) ) {
goto post ;
}
state - > search . in . dest_port = io - > in . dest_port ;
} else {
state - > search . in . dest_address = NULL ;
state - > search . in . dest_port = 0 ;
}
state - > search . in . filter = filter ;
state - > search . in . attributes = attr ;
state - > search . in . timeout = 2 ;
state - > search . in . retries = 2 ;
2011-10-10 17:46:17 +04:00
subreq = cldap_search_send ( state , ev , cldap , & state - > search ) ;
2009-02-13 15:13:54 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
goto post ;
}
tevent_req_set_callback ( subreq , cldap_netlogon_state_done , req ) ;
2005-05-10 06:01:25 +04:00
return req ;
2009-02-13 15:13:54 +03:00
post :
2011-10-10 17:48:11 +04:00
return tevent_req_post ( req , ev ) ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
static void cldap_netlogon_state_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct cldap_netlogon_state * state = tevent_req_data ( req ,
struct cldap_netlogon_state ) ;
NTSTATUS status ;
status = cldap_search_recv ( subreq , state , & state - > search ) ;
talloc_free ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
2005-05-10 06:01:25 +04:00
/*
receive a cldap netlogon reply
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_netlogon_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
2005-05-10 06:01:25 +04:00
struct cldap_netlogon * io )
{
2009-02-13 15:13:54 +03:00
struct cldap_netlogon_state * state = tevent_req_data ( req ,
struct cldap_netlogon_state ) ;
2014-10-30 18:12:19 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2005-05-10 06:01:25 +04:00
DATA_BLOB * data ;
2009-02-13 15:13:54 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
goto failed ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
if ( state - > search . out . response = = NULL ) {
status = NT_STATUS_NOT_FOUND ;
goto failed ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
if ( state - > search . out . response - > num_attributes ! = 1 | |
strcasecmp ( state - > search . out . response - > attributes [ 0 ] . name , " netlogon " ) ! = 0 | |
state - > search . out . response - > attributes [ 0 ] . num_values ! = 1 | |
state - > search . out . response - > attributes [ 0 ] . values - > length < 2 ) {
status = NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
goto failed ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
data = state - > search . out . response - > attributes [ 0 ] . values ;
2005-05-10 06:01:25 +04:00
2009-02-13 15:13:54 +03:00
status = pull_netlogon_samlogon_response ( data , mem_ctx ,
2008-05-16 07:03:01 +04:00
& io - > out . netlogon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-02-13 15:13:54 +03:00
goto failed ;
2008-05-16 07:03:01 +04:00
}
2009-02-13 15:13:54 +03:00
2008-05-16 07:03:01 +04:00
if ( io - > in . map_response ) {
map_netlogon_samlogon_response ( & io - > out . netlogon ) ;
2005-05-10 06:01:25 +04:00
}
2009-02-13 15:13:54 +03:00
status = NT_STATUS_OK ;
failed :
tevent_req_received ( req ) ;
return status ;
2005-05-10 06:01:25 +04:00
}
/*
sync cldap netlogon search
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_netlogon ( struct cldap_socket * cldap ,
TALLOC_CTX * mem_ctx ,
struct cldap_netlogon * io )
2005-05-10 06:01:25 +04:00
{
2011-10-10 17:48:11 +04:00
TALLOC_CTX * frame ;
2009-02-13 15:13:54 +03:00
struct tevent_req * req ;
2011-10-10 17:48:11 +04:00
struct tevent_context * ev ;
2009-02-13 15:13:54 +03:00
NTSTATUS status ;
2011-10-10 17:48:11 +04:00
if ( cldap - > searches . list ) {
return NT_STATUS_PIPE_BUSY ;
}
if ( cldap - > incoming . handler ) {
2009-02-13 15:13:54 +03:00
return NT_STATUS_INVALID_PIPE_STATE ;
}
2011-10-10 17:48:11 +04:00
frame = talloc_stackframe ( ) ;
2013-02-18 12:06:29 +04:00
ev = samba_tevent_context_init ( frame ) ;
2011-10-10 17:48:11 +04:00
if ( ev = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
2009-02-13 15:13:54 +03:00
}
2011-10-10 17:48:11 +04:00
req = cldap_netlogon_send ( mem_ctx , ev , cldap , io ) ;
if ( req = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
2009-02-13 15:13:54 +03:00
2011-10-10 17:48:11 +04:00
if ( ! tevent_req_poll ( req , ev ) ) {
status = map_nt_error_from_unix_common ( errno ) ;
TALLOC_FREE ( frame ) ;
return status ;
2009-02-13 15:13:54 +03:00
}
2010-05-09 19:20:01 +04:00
status = cldap_netlogon_recv ( req , mem_ctx , io ) ;
2011-10-10 17:48:11 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( frame ) ;
return status ;
}
2009-02-13 15:13:54 +03:00
2011-10-10 17:48:11 +04:00
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
2005-05-10 06:01:25 +04:00
}
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 )
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_empty_reply ( struct cldap_socket * cldap ,
2005-05-12 12:25:35 +04:00
uint32_t message_id ,
2009-02-13 15:13:54 +03:00
struct tsocket_address * dest )
2005-05-12 12:25:35 +04:00
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_Result result ;
reply . messageid = message_id ;
2009-02-13 15:13:54 +03:00
reply . dest = dest ;
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 )
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_error_reply ( struct cldap_socket * cldap ,
2006-11-15 20:08:45 +03:00
uint32_t message_id ,
2009-02-13 15:13:54 +03:00
struct tsocket_address * dest ,
2006-11-15 20:08:45 +03:00
int resultcode ,
const char * errormessage )
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_Result result ;
reply . messageid = message_id ;
2009-02-13 15:13:54 +03:00
reply . dest = dest ;
2006-11-15 20:08:45 +03:00
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
*/
2009-02-13 15:13:54 +03:00
NTSTATUS cldap_netlogon_reply ( struct cldap_socket * cldap ,
2005-05-12 12:25:35 +04:00
uint32_t message_id ,
2009-02-13 15:13:54 +03:00
struct tsocket_address * dest ,
2005-05-12 12:25:35 +04:00
uint32_t version ,
2008-05-16 07:03:01 +04:00
struct netlogon_samlogon_response * netlogon )
2005-05-12 12:25:35 +04:00
{
NTSTATUS status ;
struct cldap_reply reply ;
struct ldap_SearchResEntry response ;
struct ldap_Result result ;
TALLOC_CTX * tmp_ctx = talloc_new ( cldap ) ;
DATA_BLOB blob ;
2009-02-13 15:13:54 +03:00
status = push_netlogon_samlogon_response ( & blob , tmp_ctx ,
2008-05-16 07:03:01 +04:00
netlogon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-02-13 15:13:54 +03:00
talloc_free ( tmp_ctx ) ;
2008-05-17 15:30:36 +04:00
return status ;
2008-05-16 07:03:01 +04:00
}
2005-05-12 12:25:35 +04:00
reply . messageid = message_id ;
2009-02-13 15:13:54 +03:00
reply . dest = dest ;
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 ;
}