2004-09-13 14:36:59 +04:00
/*
Unix SMB / CIFS implementation .
LDAP server
Copyright ( C ) Volker Lendecke 2004
Copyright ( C ) Stefan Metzmacher 2004
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 .
*/
# include "includes.h"
2004-11-02 15:15:17 +03:00
# include "events.h"
2004-11-02 05:57:18 +03:00
# include "auth/auth.h"
2004-11-02 09:42:15 +03:00
# include "dlinklist.h"
# include "asn_1.h"
2004-11-02 09:52:59 +03:00
# include "ldap_server/ldap_server.h"
2004-09-13 14:36:59 +04:00
/*
close the socket and shutdown a server_context
*/
2004-09-27 17:20:59 +04:00
static void ldapsrv_terminate_connection ( struct ldapsrv_connection * ldap_conn , const char * reason )
2004-09-13 14:36:59 +04:00
{
server_terminate_connection ( ldap_conn - > connection , reason ) ;
}
/*
add a socket address to the list of events , one event per port
*/
static void add_socket ( struct server_service * service ,
2004-09-20 16:31:07 +04:00
const struct model_ops * model_ops ,
2004-11-02 01:48:25 +03:00
struct ipv4_addr * ifip )
2004-09-13 14:36:59 +04:00
{
2004-09-22 14:48:32 +04:00
struct server_socket * srv_sock ;
2004-09-13 14:36:59 +04:00
uint16_t port = 389 ;
2004-11-02 01:48:25 +03:00
char * ip_str = talloc_strdup ( service , sys_inet_ntoa ( * ifip ) ) ;
2004-09-13 14:36:59 +04:00
2004-10-22 14:52:57 +04:00
srv_sock = service_setup_socket ( service , model_ops , " ipv4 " , ip_str , & port ) ;
2004-09-20 16:31:07 +04:00
2004-10-10 02:25:24 +04:00
port = 3268 ;
2004-10-22 14:52:57 +04:00
srv_sock = service_setup_socket ( service , model_ops , " ipv4 " , ip_str , & port ) ;
2004-10-10 02:25:24 +04:00
2004-09-20 16:31:07 +04:00
talloc_free ( ip_str ) ;
2004-09-13 14:36:59 +04:00
}
/****************************************************************************
Open the socket communication .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void ldapsrv_init ( struct server_service * service ,
const struct model_ops * model_ops )
{
2004-09-28 16:36:20 +04:00
struct ldapsrv_service * ldap_service ;
struct ldapsrv_partition * part ;
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " ldapsrv_init \n " ) ) ;
2004-09-13 14:36:59 +04:00
2004-09-28 16:36:20 +04:00
ldap_service = talloc_p ( service , struct ldapsrv_service ) ;
if ( ! ldap_service ) {
DEBUG ( 0 , ( " talloc_p(service, struct ldapsrv_service) failed \n " ) ) ;
return ;
}
ZERO_STRUCTP ( ldap_service ) ;
part = talloc_p ( ldap_service , struct ldapsrv_partition ) ;
if ( ! ldap_service ) {
DEBUG ( 0 , ( " talloc_p(ldap_service, struct ldapsrv_partition) failed \n " ) ) ;
return ;
}
part - > base_dn = " " ; /* RootDSE */
part - > ops = ldapsrv_get_rootdse_partition_ops ( ) ;
ldap_service - > rootDSE = part ;
DLIST_ADD_END ( ldap_service - > partitions , part , struct ldapsrv_partition * ) ;
part = talloc_p ( ldap_service , struct ldapsrv_partition ) ;
if ( ! ldap_service ) {
DEBUG ( 0 , ( " talloc_p(ldap_service, struct ldapsrv_partition) failed \n " ) ) ;
return ;
}
part - > base_dn = " * " ; /* default partition */
part - > ops = ldapsrv_get_sldb_partition_ops ( ) ;
ldap_service - > default_partition = part ;
DLIST_ADD_END ( ldap_service - > partitions , part , struct ldapsrv_partition * ) ;
service - > private_data = ldap_service ;
2004-09-13 14:36:59 +04:00
if ( lp_interfaces ( ) & & lp_bind_interfaces_only ( ) ) {
int num_interfaces = iface_count ( ) ;
int i ;
/* We have been given an interfaces line, and been
told to only bind to those interfaces . Create a
socket per interface and bind to only these .
*/
for ( i = 0 ; i < num_interfaces ; i + + ) {
2004-11-02 01:48:25 +03:00
struct ipv4_addr * ifip = iface_n_ip ( i ) ;
2004-09-13 14:36:59 +04:00
if ( ifip = = NULL ) {
DEBUG ( 0 , ( " ldapsrv_init: interface %d has NULL "
" IP address ! \n " , i ) ) ;
continue ;
}
2004-09-20 16:31:07 +04:00
add_socket ( service , model_ops , ifip ) ;
2004-09-13 14:36:59 +04:00
}
} else {
2004-11-02 01:48:25 +03:00
struct ipv4_addr ifip ;
2004-09-13 14:36:59 +04:00
/* Just bind to lp_socket_address() (usually 0.0.0.0) */
2004-10-27 07:15:42 +04:00
ifip = interpret_addr2 ( lp_socket_address ( ) ) ;
add_socket ( service , model_ops , & ifip ) ;
2004-09-13 14:36:59 +04:00
}
}
/* This rw-buf api is made to avoid memcpy. For now do that like mad... The
idea is to write into a circular list of buffers where the ideal case is
that a read ( 2 ) holds a complete request that is then thrown away
completely . */
2004-10-10 02:00:00 +04:00
void ldapsrv_consumed_from_buf ( struct rw_buffer * buf ,
2004-09-22 14:48:32 +04:00
size_t length )
{
memcpy ( buf - > data , buf - > data + length , buf - > length - length ) ;
buf - > length - = length ;
}
2004-10-08 16:19:08 +04:00
static void peek_into_read_buf ( struct rw_buffer * buf , uint8_t * * out ,
size_t * out_length )
{
* out = buf - > data ;
* out_length = buf - > length ;
}
2004-10-10 02:00:00 +04:00
BOOL ldapsrv_append_to_buf ( struct rw_buffer * buf , uint8_t * data , size_t length )
2004-09-13 14:36:59 +04:00
{
buf - > data = realloc ( buf - > data , buf - > length + length ) ;
if ( buf - > data = = NULL )
return False ;
memcpy ( buf - > data + buf - > length , data , length ) ;
buf - > length + = length ;
return True ;
}
2004-09-20 16:31:07 +04:00
static BOOL read_into_buf ( struct socket_context * sock , struct rw_buffer * buf )
2004-09-13 14:36:59 +04:00
{
2004-09-20 16:31:07 +04:00
NTSTATUS status ;
DATA_BLOB tmp_blob ;
BOOL ret ;
2004-10-28 08:00:43 +04:00
size_t nread ;
2004-09-13 14:36:59 +04:00
2004-10-28 08:00:43 +04:00
tmp_blob = data_blob_talloc ( sock , NULL , 1024 ) ;
if ( tmp_blob . data = = NULL ) {
return False ;
}
status = socket_recv ( sock , tmp_blob . data , tmp_blob . length , & nread , 0 ) ;
2004-10-28 12:36:23 +04:00
if ( NT_STATUS_IS_ERR ( status ) ) {
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " socket_recv: %s \n " , nt_errstr ( status ) ) ) ;
2004-10-28 08:00:43 +04:00
talloc_free ( tmp_blob . data ) ;
2004-09-13 14:36:59 +04:00
return False ;
2004-09-20 16:31:07 +04:00
}
2004-11-15 20:27:07 +03:00
tmp_blob . length = nread ;
2004-09-20 16:31:07 +04:00
2004-10-10 02:00:00 +04:00
ret = ldapsrv_append_to_buf ( buf , tmp_blob . data , tmp_blob . length ) ;
2004-09-13 14:36:59 +04:00
2004-09-20 16:31:07 +04:00
talloc_free ( tmp_blob . data ) ;
return ret ;
2004-09-13 14:36:59 +04:00
}
2004-10-08 16:19:08 +04:00
static BOOL ldapsrv_read_buf ( struct ldapsrv_connection * conn )
{
NTSTATUS status ;
DATA_BLOB tmp_blob ;
DATA_BLOB creds ;
BOOL ret ;
uint8_t * buf ;
2004-11-15 20:27:07 +03:00
size_t buf_length , sasl_length ;
2004-10-08 16:19:08 +04:00
struct socket_context * sock = conn - > connection - > socket ;
TALLOC_CTX * mem_ctx ;
2004-10-28 08:00:43 +04:00
size_t nread ;
2004-10-08 16:19:08 +04:00
2004-10-10 02:00:00 +04:00
if ( ! conn - > gensec | | ! conn - > session_info | |
2004-10-08 16:19:08 +04:00
! ( gensec_have_feature ( conn - > gensec , GENSEC_WANT_SIGN ) & &
gensec_have_feature ( conn - > gensec , GENSEC_WANT_SEAL ) ) ) {
return read_into_buf ( sock , & conn - > in_buffer ) ;
}
mem_ctx = talloc ( conn , 0 ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " no memory \n " ) ) ;
return False ;
}
2004-10-28 08:00:43 +04:00
tmp_blob = data_blob_talloc ( mem_ctx , NULL , 1024 ) ;
if ( tmp_blob . data = = NULL ) {
talloc_free ( mem_ctx ) ;
return False ;
}
status = socket_recv ( sock , tmp_blob . data , tmp_blob . length , & nread , 0 ) ;
2004-10-28 12:36:23 +04:00
if ( NT_STATUS_IS_ERR ( status ) ) {
2004-10-08 16:19:08 +04:00
DEBUG ( 10 , ( " socket_recv: %s \n " , nt_errstr ( status ) ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
2004-10-28 08:00:43 +04:00
tmp_blob . length = nread ;
2004-10-08 16:19:08 +04:00
2004-10-10 02:00:00 +04:00
ret = ldapsrv_append_to_buf ( & conn - > sasl_in_buffer , tmp_blob . data , tmp_blob . length ) ;
2004-10-08 16:19:08 +04:00
if ( ! ret ) {
talloc_free ( mem_ctx ) ;
return False ;
}
peek_into_read_buf ( & conn - > sasl_in_buffer , & buf , & buf_length ) ;
if ( buf_length < 4 ) {
/* not enough yet */
talloc_free ( mem_ctx ) ;
return True ;
}
sasl_length = RIVAL ( buf , 0 ) ;
if ( buf_length < ( 4 + sasl_length ) ) {
/* not enough yet */
talloc_free ( mem_ctx ) ;
return True ;
}
creds . data = buf + 4 ;
creds . length = gensec_sig_size ( conn - > gensec ) ;
if ( creds . length > sasl_length ) {
/* invalid packet? */
talloc_free ( mem_ctx ) ;
return False ;
}
tmp_blob . data = buf + ( 4 + creds . length ) ;
tmp_blob . length = ( 4 + sasl_length ) - ( 4 + creds . length ) ;
if ( gensec_have_feature ( conn - > gensec , GENSEC_WANT_SEAL ) ) {
status = gensec_unseal_packet ( conn - > gensec , mem_ctx ,
tmp_blob . data , tmp_blob . length ,
tmp_blob . data , tmp_blob . length ,
& creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " gensec_unseal_packet: %s \n " , nt_errstr ( status ) ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
} else {
status = gensec_check_packet ( conn - > gensec , mem_ctx ,
tmp_blob . data , tmp_blob . length ,
tmp_blob . data , tmp_blob . length ,
& creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " gensec_check_packet: %s \n " , nt_errstr ( status ) ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
}
2004-10-10 02:00:00 +04:00
ret = ldapsrv_append_to_buf ( & conn - > in_buffer , tmp_blob . data , tmp_blob . length ) ;
2004-10-08 16:19:08 +04:00
if ( ! ret ) {
talloc_free ( mem_ctx ) ;
return False ;
}
2004-10-10 02:00:00 +04:00
ldapsrv_consumed_from_buf ( & conn - > sasl_in_buffer , 4 + sasl_length ) ;
2004-10-08 16:19:08 +04:00
talloc_free ( mem_ctx ) ;
return ret ;
}
2004-09-20 16:31:07 +04:00
static BOOL write_from_buf ( struct socket_context * sock , struct rw_buffer * buf )
2004-09-13 14:36:59 +04:00
{
2004-09-20 16:31:07 +04:00
NTSTATUS status ;
DATA_BLOB tmp_blob ;
size_t sendlen ;
tmp_blob . data = buf - > data ;
tmp_blob . length = buf - > length ;
2004-09-13 14:36:59 +04:00
2004-10-28 08:00:43 +04:00
status = socket_send ( sock , & tmp_blob , & sendlen , 0 ) ;
2004-09-20 16:31:07 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " socket_send() %s \n " , nt_errstr ( status ) ) ) ;
2004-09-13 14:36:59 +04:00
return False ;
2004-09-20 16:31:07 +04:00
}
2004-10-10 02:00:00 +04:00
ldapsrv_consumed_from_buf ( buf , sendlen ) ;
2004-09-13 14:36:59 +04:00
return True ;
}
2004-10-08 16:19:08 +04:00
static BOOL ldapsrv_write_buf ( struct ldapsrv_connection * conn )
2004-09-13 14:36:59 +04:00
{
2004-10-08 16:19:08 +04:00
NTSTATUS status ;
DATA_BLOB tmp_blob ;
DATA_BLOB creds ;
DATA_BLOB sasl ;
size_t sendlen ;
BOOL ret ;
struct socket_context * sock = conn - > connection - > socket ;
TALLOC_CTX * mem_ctx ;
2004-10-10 02:00:00 +04:00
if ( ! conn - > gensec | | ! conn - > session_info | |
2004-10-08 16:19:08 +04:00
! ( gensec_have_feature ( conn - > gensec , GENSEC_WANT_SIGN ) & &
gensec_have_feature ( conn - > gensec , GENSEC_WANT_SEAL ) ) ) {
return write_from_buf ( sock , & conn - > out_buffer ) ;
}
mem_ctx = talloc ( conn , 0 ) ;
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " no memory \n " ) ) ;
return False ;
}
tmp_blob . data = conn - > out_buffer . data ;
tmp_blob . length = conn - > out_buffer . length ;
2004-10-10 02:00:00 +04:00
if ( tmp_blob . length = = 0 ) {
goto nodata ;
}
2004-10-08 16:19:08 +04:00
if ( gensec_have_feature ( conn - > gensec , GENSEC_WANT_SEAL ) ) {
status = gensec_seal_packet ( conn - > gensec , mem_ctx ,
tmp_blob . data , tmp_blob . length ,
tmp_blob . data , tmp_blob . length ,
& creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " gensec_seal_packet: %s \n " , nt_errstr ( status ) ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
} else {
status = gensec_sign_packet ( conn - > gensec , mem_ctx ,
tmp_blob . data , tmp_blob . length ,
tmp_blob . data , tmp_blob . length ,
& creds ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " gensec_sign_packet: %s \n " , nt_errstr ( status ) ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
}
sasl = data_blob_talloc ( mem_ctx , NULL , 4 + creds . length + tmp_blob . length ) ;
if ( ! sasl . data ) {
DEBUG ( 0 , ( " no memory \n " ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
RSIVAL ( sasl . data , 0 , creds . length + tmp_blob . length ) ;
memcpy ( sasl . data + 4 , creds . data , creds . length ) ;
memcpy ( sasl . data + 4 + creds . length , tmp_blob . data , tmp_blob . length ) ;
2004-10-10 02:00:00 +04:00
ret = ldapsrv_append_to_buf ( & conn - > sasl_out_buffer , sasl . data , sasl . length ) ;
2004-10-08 16:19:08 +04:00
if ( ! ret ) {
talloc_free ( mem_ctx ) ;
return False ;
}
2004-10-10 02:00:00 +04:00
ldapsrv_consumed_from_buf ( & conn - > out_buffer , tmp_blob . length ) ;
nodata :
tmp_blob . data = conn - > sasl_out_buffer . data ;
tmp_blob . length = conn - > sasl_out_buffer . length ;
2004-10-08 16:19:08 +04:00
2004-10-28 08:00:43 +04:00
status = socket_send ( sock , & tmp_blob , & sendlen , 0 ) ;
2004-10-08 16:19:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " socket_send() %s \n " , nt_errstr ( status ) ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
2004-10-10 02:00:00 +04:00
ldapsrv_consumed_from_buf ( & conn - > sasl_out_buffer , sendlen ) ;
2004-10-08 16:19:08 +04:00
talloc_free ( mem_ctx ) ;
return True ;
2004-09-13 14:36:59 +04:00
}
2004-10-10 02:00:00 +04:00
static BOOL ldap_encode_to_buf ( struct ldap_message * msg , struct rw_buffer * buf )
2004-09-13 14:36:59 +04:00
{
DATA_BLOB blob ;
BOOL res ;
if ( ! ldap_encode ( msg , & blob ) )
return False ;
2004-10-10 02:00:00 +04:00
res = ldapsrv_append_to_buf ( buf , blob . data , blob . length ) ;
2004-09-13 14:36:59 +04:00
data_blob_free ( & blob ) ;
return res ;
}
2004-10-10 02:00:00 +04:00
NTSTATUS ldapsrv_do_responses ( struct ldapsrv_connection * conn )
2004-09-13 14:36:59 +04:00
{
2004-09-22 14:48:32 +04:00
struct ldapsrv_call * call , * next_call = NULL ;
struct ldapsrv_reply * reply , * next_reply = NULL ;
2004-09-13 14:36:59 +04:00
2004-09-22 14:48:32 +04:00
for ( call = conn - > calls ; call ; call = next_call ) {
for ( reply = call - > replies ; reply ; reply = next_reply ) {
2004-10-10 02:00:00 +04:00
if ( ! ldap_encode_to_buf ( & reply - > msg , & conn - > out_buffer ) ) {
2004-09-27 17:20:59 +04:00
return NT_STATUS_FOOBAR ;
2004-09-22 14:48:32 +04:00
}
next_reply = reply - > next ;
DLIST_REMOVE ( call - > replies , reply ) ;
reply - > state = LDAPSRV_REPLY_STATE_SEND ;
talloc_free ( reply ) ;
}
next_call = call - > next ;
DLIST_REMOVE ( conn - > calls , call ) ;
call - > state = LDAPSRV_CALL_STATE_COMPLETE ;
talloc_free ( call ) ;
2004-09-13 14:36:59 +04:00
}
2004-09-27 17:20:59 +04:00
return NT_STATUS_OK ;
2004-09-13 14:36:59 +04:00
}
2004-10-10 02:00:00 +04:00
NTSTATUS ldapsrv_flush_responses ( struct ldapsrv_connection * conn )
{
return NT_STATUS_OK ;
}
2004-09-13 14:36:59 +04:00
/*
called when a LDAP socket becomes readable
*/
2004-11-03 13:09:48 +03:00
static void ldapsrv_recv ( struct server_connection * conn , struct timeval t ,
2004-09-13 14:36:59 +04:00
uint16_t flags )
{
struct ldapsrv_connection * ldap_conn = conn - > private_data ;
uint8_t * buf ;
2004-11-15 20:27:07 +03:00
size_t buf_length , msg_length ;
2004-09-13 14:36:59 +04:00
DATA_BLOB blob ;
2004-11-02 09:42:15 +03:00
struct asn1_data data ;
2004-09-22 14:48:32 +04:00
struct ldapsrv_call * call ;
2004-09-27 17:20:59 +04:00
NTSTATUS status ;
2004-09-13 14:36:59 +04:00
DEBUG ( 10 , ( " ldapsrv_recv \n " ) ) ;
2004-10-08 16:19:08 +04:00
if ( ! ldapsrv_read_buf ( ldap_conn ) ) {
ldapsrv_terminate_connection ( ldap_conn , " ldapsrv_read_buf() failed " ) ;
2004-09-13 14:36:59 +04:00
return ;
}
peek_into_read_buf ( & ldap_conn - > in_buffer , & buf , & buf_length ) ;
while ( buf_length > 0 ) {
/* LDAP Messages are always SEQUENCES */
if ( ! asn1_object_length ( buf , buf_length , ASN1_SEQUENCE ( 0 ) ,
& msg_length ) ) {
ldapsrv_terminate_connection ( ldap_conn , " asn1_object_length() failed " ) ;
return ;
}
if ( buf_length < msg_length ) {
/* Not enough yet */
break ;
}
/* We've got a complete LDAP request in the in-buffer, convert
* that to a ldap_message and put it into the incoming
* queue . */
blob . data = buf ;
blob . length = msg_length ;
if ( ! asn1_load ( & data , blob ) ) {
ldapsrv_terminate_connection ( ldap_conn , " asn1_load() failed " ) ;
return ;
}
2004-09-22 14:48:32 +04:00
call = talloc_p ( ldap_conn , struct ldapsrv_call ) ;
if ( ! call ) {
ldapsrv_terminate_connection ( ldap_conn , " no memory " ) ;
return ;
2004-09-13 14:36:59 +04:00
}
2004-09-22 14:48:32 +04:00
ZERO_STRUCTP ( call ) ;
call - > state = LDAPSRV_CALL_STATE_NEW ;
call - > conn = ldap_conn ;
call - > request . mem_ctx = call ;
2004-09-13 14:36:59 +04:00
2004-09-22 14:48:32 +04:00
if ( ! ldap_decode ( & data , & call - > request ) ) {
dump_data ( 0 , buf , msg_length ) ;
2004-09-28 16:36:20 +04:00
asn1_free ( & data ) ;
2004-09-22 14:48:32 +04:00
ldapsrv_terminate_connection ( ldap_conn , " ldap_decode() failed " ) ;
2004-09-13 14:36:59 +04:00
return ;
}
2004-09-28 16:36:20 +04:00
asn1_free ( & data ) ;
2004-09-22 14:48:32 +04:00
DLIST_ADD_END ( ldap_conn - > calls , call ,
struct ldapsrv_call * ) ;
2004-09-13 14:36:59 +04:00
2004-10-10 02:00:00 +04:00
ldapsrv_consumed_from_buf ( & ldap_conn - > in_buffer , msg_length ) ;
2004-09-13 14:36:59 +04:00
2004-09-27 17:20:59 +04:00
status = ldapsrv_do_call ( call ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ldapsrv_terminate_connection ( ldap_conn , " ldapsrv_do_call() failed " ) ;
return ;
}
2004-09-13 14:36:59 +04:00
peek_into_read_buf ( & ldap_conn - > in_buffer , & buf , & buf_length ) ;
}
2004-09-27 17:20:59 +04:00
status = ldapsrv_do_responses ( ldap_conn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
ldapsrv_terminate_connection ( ldap_conn , " ldapsrv_do_responses() failed " ) ;
return ;
}
2004-09-13 14:36:59 +04:00
2004-10-08 16:19:08 +04:00
if ( ( ldap_conn - > out_buffer . length > 0 ) | | ( ldap_conn - > sasl_out_buffer . length > 0 ) ) {
2004-09-22 14:48:32 +04:00
conn - > event . fde - > flags | = EVENT_FD_WRITE ;
}
2004-09-18 12:13:06 +04:00
2004-09-13 14:36:59 +04:00
return ;
}
/*
called when a LDAP socket becomes writable
*/
2004-11-03 13:09:48 +03:00
static void ldapsrv_send ( struct server_connection * conn , struct timeval t ,
2004-09-13 14:36:59 +04:00
uint16_t flags )
{
struct ldapsrv_connection * ldap_conn = conn - > private_data ;
DEBUG ( 10 , ( " ldapsrv_send \n " ) ) ;
2004-10-08 16:19:08 +04:00
if ( ! ldapsrv_write_buf ( ldap_conn ) ) {
ldapsrv_terminate_connection ( ldap_conn , " ldapsrv_write_buf() failed " ) ;
2004-09-13 14:36:59 +04:00
return ;
}
2004-10-08 16:19:08 +04:00
if ( ldap_conn - > out_buffer . length = = 0 & & ldap_conn - > sasl_out_buffer . length = = 0 ) {
2004-09-22 14:48:32 +04:00
conn - > event . fde - > flags & = ~ EVENT_FD_WRITE ;
}
2004-09-18 12:13:06 +04:00
2004-09-13 14:36:59 +04:00
return ;
}
/*
called when connection is idle
*/
2004-11-03 13:09:48 +03:00
static void ldapsrv_idle ( struct server_connection * conn , struct timeval t )
2004-09-13 14:36:59 +04:00
{
DEBUG ( 10 , ( " ldapsrv_idle: not implemented! \n " ) ) ;
return ;
}
static void ldapsrv_close ( struct server_connection * conn , const char * reason )
{
return ;
}
/*
initialise a server_context from a open socket and register a event handler
for reading from that socket
*/
static void ldapsrv_accept ( struct server_connection * conn )
{
struct ldapsrv_connection * ldap_conn ;
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " ldapsrv_accept \n " ) ) ;
2004-09-13 14:36:59 +04:00
2004-09-25 15:48:30 +04:00
ldap_conn = talloc_p ( conn , struct ldapsrv_connection ) ;
2004-09-13 14:36:59 +04:00
if ( ldap_conn = = NULL )
return ;
ZERO_STRUCTP ( ldap_conn ) ;
ldap_conn - > connection = conn ;
2004-09-28 16:36:20 +04:00
ldap_conn - > service = talloc_reference ( ldap_conn , conn - > service - > private_data ) ;
2004-09-13 14:36:59 +04:00
conn - > private_data = ldap_conn ;
2004-09-20 16:31:07 +04:00
2004-09-13 14:36:59 +04:00
return ;
}
/*
called on a fatal error that should cause this server to terminate
*/
static void ldapsrv_exit ( struct server_service * service , const char * reason )
{
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " ldapsrv_exit \n " ) ) ;
2004-09-13 14:36:59 +04:00
return ;
}
static const struct server_service_ops ldap_server_ops = {
. name = " ldap " ,
. service_init = ldapsrv_init ,
. accept_connection = ldapsrv_accept ,
. recv_handler = ldapsrv_recv ,
. send_handler = ldapsrv_send ,
. idle_handler = ldapsrv_idle ,
. close_connection = ldapsrv_close ,
. service_exit = ldapsrv_exit ,
} ;
const struct server_service_ops * ldapsrv_get_ops ( void )
{
return & ldap_server_ops ;
}
NTSTATUS server_service_ldap_init ( void )
{
return NT_STATUS_OK ;
}