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"
/*
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-09-13 14:36:59 +04:00
struct in_addr * ifip )
{
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-09-26 07:05:04 +04:00
char * ip_str = talloc_strdup ( service , inet_ntoa ( * ifip ) ) ;
2004-09-13 14:36:59 +04:00
2004-09-22 14:48:32 +04:00
srv_sock = service_setup_socket ( service , model_ops , ip_str , & port ) ;
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 + + ) {
struct in_addr * ifip = iface_n_ip ( i ) ;
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 {
struct in_addr * ifip ;
/* Just bind to lp_socket_address() (usually 0.0.0.0) */
2004-09-28 16:36:20 +04:00
ifip = interpret_addr2 ( service , lp_socket_address ( ) ) ;
2004-09-20 16:31:07 +04:00
add_socket ( service , model_ops , ifip ) ;
2004-09-13 14:36:59 +04:00
2004-09-28 16:36:20 +04:00
talloc_destroy ( 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-09-22 14:48:32 +04:00
static void consumed_from_buf ( struct rw_buffer * buf ,
size_t length )
{
memcpy ( buf - > data , buf - > data + length , buf - > length - length ) ;
buf - > length - = length ;
}
2004-09-13 14:36:59 +04:00
static BOOL append_to_buf ( struct rw_buffer * buf , uint8_t * data , size_t length )
{
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-09-13 14:36:59 +04:00
2004-09-20 16:31:07 +04:00
status = socket_recv ( sock , sock , & tmp_blob , 1024 , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " socket_recv: %s \n " , nt_errstr ( status ) ) ) ;
2004-09-13 14:36:59 +04:00
return False ;
2004-09-20 16:31:07 +04:00
}
ret = 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-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-09-20 16:31:07 +04:00
status = socket_send ( sock , sock , & tmp_blob , & sendlen , 0 ) ;
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-09-22 14:48:32 +04:00
consumed_from_buf ( buf , sendlen ) ;
2004-09-13 14:36:59 +04:00
return True ;
}
static void peek_into_read_buf ( struct rw_buffer * buf , uint8_t * * out ,
size_t * out_length )
{
* out = buf - > data ;
* out_length = buf - > length ;
}
static BOOL ldap_append_to_buf ( struct ldap_message * msg , struct rw_buffer * buf )
{
DATA_BLOB blob ;
BOOL res ;
if ( ! ldap_encode ( msg , & blob ) )
return False ;
res = append_to_buf ( buf , blob . data , blob . length ) ;
data_blob_free ( & blob ) ;
return res ;
}
2004-09-22 17:01:00 +04:00
struct ldapsrv_reply * ldapsrv_init_reply ( struct ldapsrv_call * call , enum ldap_request_tag type )
2004-09-22 14:48:32 +04:00
{
struct ldapsrv_reply * reply ;
reply = talloc_p ( call , struct ldapsrv_reply ) ;
if ( ! reply ) {
return NULL ;
}
reply - > prev = reply - > next = NULL ;
reply - > state = LDAPSRV_REPLY_STATE_NEW ;
reply - > msg . messageid = call - > request . messageid ;
reply - > msg . type = type ;
reply - > msg . mem_ctx = reply ;
return reply ;
}
2004-09-27 17:20:59 +04:00
NTSTATUS ldapsrv_queue_reply ( struct ldapsrv_call * call , struct ldapsrv_reply * reply )
2004-09-22 17:01:00 +04:00
{
DLIST_ADD_END ( call - > replies , reply , struct ldapsrv_reply * ) ;
2004-09-27 17:20:59 +04:00
return NT_STATUS_OK ;
2004-09-22 17:01:00 +04:00
}
struct ldapsrv_partition * ldapsrv_get_partition ( struct ldapsrv_connection * conn , const char * dn )
{
2004-09-27 17:20:59 +04:00
if ( strcasecmp ( " " , dn ) = = 0 ) {
2004-09-28 16:36:20 +04:00
return conn - > service - > rootDSE ;
2004-09-27 17:20:59 +04:00
}
2004-09-22 17:01:00 +04:00
2004-09-28 16:36:20 +04:00
return conn - > service - > default_partition ;
2004-09-22 17:01:00 +04:00
}
2004-09-27 17:20:59 +04:00
NTSTATUS ldapsrv_unwilling ( struct ldapsrv_call * call , int error )
2004-09-13 14:36:59 +04:00
{
2004-09-22 14:48:32 +04:00
struct ldapsrv_reply * reply ;
2004-09-13 14:36:59 +04:00
struct ldap_ExtendedResponse * r ;
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " Unwilling type[%d] id[%d] \n " , call - > request . type , call - > request . messageid ) ) ;
2004-09-13 14:36:59 +04:00
2004-09-22 14:48:32 +04:00
reply = ldapsrv_init_reply ( call , LDAP_TAG_ExtendedResponse ) ;
if ( ! reply ) {
2004-09-27 17:20:59 +04:00
return NT_STATUS_NO_MEMORY ;
2004-09-13 14:36:59 +04:00
}
2004-09-22 14:48:32 +04:00
r = & reply - > msg . r . ExtendedResponse ;
2004-09-13 14:36:59 +04:00
r - > response . resultcode = error ;
r - > response . dn = NULL ;
r - > response . errormessage = NULL ;
r - > response . referral = NULL ;
r - > name = NULL ;
r - > value . data = NULL ;
r - > value . length = 0 ;
2004-09-27 17:20:59 +04:00
return ldapsrv_queue_reply ( call , reply ) ;
2004-09-13 14:36:59 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_BindRequest ( struct ldapsrv_call * call )
2004-09-13 14:36:59 +04:00
{
2004-09-22 14:48:32 +04:00
struct ldap_BindRequest * req = & call - > request . r . BindRequest ;
struct ldapsrv_reply * reply ;
2004-09-13 14:36:59 +04:00
struct ldap_BindResponse * resp ;
2004-09-28 17:50:15 +04:00
DEBUG ( 10 , ( " BindRequest dn: %s \n " , req - > dn ) ) ;
2004-09-13 14:36:59 +04:00
2004-09-22 14:48:32 +04:00
reply = ldapsrv_init_reply ( call , LDAP_TAG_BindResponse ) ;
if ( ! reply ) {
2004-09-27 17:20:59 +04:00
return NT_STATUS_NO_MEMORY ;
2004-09-13 14:36:59 +04:00
}
2004-09-22 14:48:32 +04:00
resp = & reply - > msg . r . BindResponse ;
2004-09-13 14:36:59 +04:00
resp - > response . resultcode = 0 ;
resp - > response . dn = NULL ;
resp - > response . errormessage = NULL ;
resp - > response . referral = NULL ;
resp - > SASL . secblob = data_blob ( NULL , 0 ) ;
2004-09-27 17:20:59 +04:00
return ldapsrv_queue_reply ( call , reply ) ;
2004-09-13 14:36:59 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_UnbindRequest ( struct ldapsrv_call * call )
2004-09-13 14:36:59 +04:00
{
2004-09-22 17:01:00 +04:00
/* struct ldap_UnbindRequest *req = &call->request->r.UnbindRequest;*/
DEBUG ( 10 , ( " UnbindRequest \n " ) ) ;
2004-09-27 17:20:59 +04:00
return NT_STATUS_OK ;
2004-09-22 14:48:32 +04:00
}
2004-09-13 14:36:59 +04:00
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_SearchRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
struct ldap_SearchRequest * req = & call - > request . r . SearchRequest ;
2004-09-22 17:01:00 +04:00
struct ldapsrv_partition * part ;
2004-09-13 14:36:59 +04:00
2004-09-22 17:01:00 +04:00
DEBUG ( 10 , ( " SearchRequest " ) ) ;
DEBUGADD ( 10 , ( " basedn: %s " , req - > basedn ) ) ;
DEBUGADD ( 10 , ( " filter: %s \n " , req - > filter ) ) ;
2004-09-13 14:36:59 +04:00
2004-09-22 17:01:00 +04:00
part = ldapsrv_get_partition ( call - > conn , req - > basedn ) ;
2004-09-18 12:13:06 +04:00
2004-09-22 17:01:00 +04:00
if ( ! part - > ops - > Search ) {
2004-09-22 17:08:30 +04:00
struct ldap_Result * done ;
struct ldapsrv_reply * done_r ;
done_r = ldapsrv_init_reply ( call , LDAP_TAG_SearchResultDone ) ;
if ( ! done_r ) {
2004-09-27 17:20:59 +04:00
return NT_STATUS_NO_MEMORY ;
2004-09-22 17:08:30 +04:00
}
done = & done_r - > msg . r . SearchResultDone ;
2004-09-22 17:14:56 +04:00
done - > resultcode = 53 ;
2004-09-22 17:08:30 +04:00
done - > dn = NULL ;
done - > errormessage = NULL ;
done - > referral = NULL ;
2004-09-27 17:20:59 +04:00
return ldapsrv_queue_reply ( call , done_r ) ;
2004-09-13 14:36:59 +04:00
}
2004-09-27 17:20:59 +04:00
return part - > ops - > Search ( part , call , req ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_ModifyRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
2004-09-22 17:01:00 +04:00
struct ldap_ModifyRequest * req = & call - > request . r . ModifyRequest ;
struct ldapsrv_partition * part ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
DEBUG ( 10 , ( " ModifyRequest " ) ) ;
DEBUGADD ( 10 , ( " dn: %s " , req - > dn ) ) ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
part = ldapsrv_get_partition ( call - > conn , req - > dn ) ;
if ( ! part - > ops - > Modify ) {
2004-09-27 17:20:59 +04:00
return ldapsrv_unwilling ( call , 53 ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
return part - > ops - > Modify ( part , call , req ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_AddRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
2004-09-22 17:01:00 +04:00
struct ldap_AddRequest * req = & call - > request . r . AddRequest ;
struct ldapsrv_partition * part ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
DEBUG ( 10 , ( " AddRequest " ) ) ;
DEBUGADD ( 10 , ( " dn: %s " , req - > dn ) ) ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
part = ldapsrv_get_partition ( call - > conn , req - > dn ) ;
if ( ! part - > ops - > Add ) {
2004-09-27 17:20:59 +04:00
return ldapsrv_unwilling ( call , 53 ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
return part - > ops - > Add ( part , call , req ) ;
2004-09-13 14:36:59 +04:00
}
2004-09-27 19:40:12 +04:00
static NTSTATUS ldapsrv_DelRequest ( struct ldapsrv_call * call )
2004-09-13 14:36:59 +04:00
{
2004-09-27 19:40:12 +04:00
struct ldap_DelRequest * req = & call - > request . r . DelRequest ;
2004-09-22 17:01:00 +04:00
struct ldapsrv_partition * part ;
2004-09-22 14:48:32 +04:00
2004-09-27 19:40:12 +04:00
DEBUG ( 10 , ( " DelRequest " ) ) ;
2004-09-22 17:01:00 +04:00
DEBUGADD ( 10 , ( " dn: %s " , req - > dn ) ) ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
part = ldapsrv_get_partition ( call - > conn , req - > dn ) ;
2004-09-27 19:40:12 +04:00
if ( ! part - > ops - > Del ) {
2004-09-27 17:20:59 +04:00
return ldapsrv_unwilling ( call , 53 ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 19:40:12 +04:00
return part - > ops - > Del ( part , call , req ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_ModifyDNRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
2004-09-22 17:01:00 +04:00
struct ldap_ModifyDNRequest * req = & call - > request . r . ModifyDNRequest ;
struct ldapsrv_partition * part ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
DEBUG ( 10 , ( " ModifyDNRequrest " ) ) ;
DEBUGADD ( 10 , ( " dn: %s " , req - > dn ) ) ;
DEBUGADD ( 10 , ( " newrdn: %s " , req - > newrdn ) ) ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
part = ldapsrv_get_partition ( call - > conn , req - > dn ) ;
if ( ! part - > ops - > ModifyDN ) {
2004-09-27 17:20:59 +04:00
return ldapsrv_unwilling ( call , 53 ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
return part - > ops - > ModifyDN ( part , call , req ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_CompareRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
2004-09-22 17:01:00 +04:00
struct ldap_CompareRequest * req = & call - > request . r . CompareRequest ;
struct ldapsrv_partition * part ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
DEBUG ( 10 , ( " CompareRequest " ) ) ;
DEBUGADD ( 10 , ( " dn: %s " , req - > dn ) ) ;
2004-09-22 14:48:32 +04:00
2004-09-22 17:01:00 +04:00
part = ldapsrv_get_partition ( call - > conn , req - > dn ) ;
if ( ! part - > ops - > Compare ) {
2004-09-27 17:20:59 +04:00
return ldapsrv_unwilling ( call , 53 ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
return part - > ops - > Compare ( part , call , req ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_AbandonRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
2004-09-22 17:01:00 +04:00
/* struct ldap_AbandonRequest *req = &call->request.r.AbandonRequest;*/
DEBUG ( 10 , ( " AbandonRequest \n " ) ) ;
2004-09-27 17:20:59 +04:00
return NT_STATUS_OK ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_ExtendedRequest ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
2004-09-22 17:01:00 +04:00
/* struct ldap_ExtendedRequest *req = &call->request.r.ExtendedRequest;*/
2004-09-22 14:48:32 +04:00
struct ldapsrv_reply * reply ;
DEBUG ( 10 , ( " Extended \n " ) ) ;
reply = ldapsrv_init_reply ( call , LDAP_TAG_ExtendedResponse ) ;
if ( ! reply ) {
2004-09-27 17:20:59 +04:00
return NT_STATUS_NO_MEMORY ;
2004-09-22 14:48:32 +04:00
}
ZERO_STRUCT ( reply - > msg . r ) ;
2004-09-27 17:20:59 +04:00
return ldapsrv_queue_reply ( call , reply ) ;
2004-09-22 14:48:32 +04:00
}
2004-09-27 17:20:59 +04:00
static NTSTATUS ldapsrv_do_call ( struct ldapsrv_call * call )
2004-09-22 14:48:32 +04:00
{
switch ( call - > request . type ) {
2004-09-13 14:36:59 +04:00
case LDAP_TAG_BindRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_BindRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_UnbindRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_UnbindRequest ( call ) ;
2004-09-13 14:36:59 +04:00
case LDAP_TAG_SearchRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_SearchRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_ModifyRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_ModifyRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_AddRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_AddRequest ( call ) ;
2004-09-27 19:40:12 +04:00
case LDAP_TAG_DelRequest :
return ldapsrv_DelRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_ModifyDNRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_ModifyDNRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_CompareRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_CompareRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_AbandonRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_AbandonRequest ( call ) ;
2004-09-22 14:48:32 +04:00
case LDAP_TAG_ExtendedRequest :
2004-09-27 17:20:59 +04:00
return ldapsrv_ExtendedRequest ( call ) ;
2004-09-13 14:36:59 +04:00
default :
2004-09-27 17:20:59 +04:00
return ldapsrv_unwilling ( call , 2 ) ;
2004-09-13 14:36:59 +04:00
}
}
2004-09-27 17:20:59 +04:00
static 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 ) {
if ( ! ldap_append_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
}
/*
called when a LDAP socket becomes readable
*/
static void ldapsrv_recv ( struct server_connection * conn , time_t t ,
uint16_t flags )
{
struct ldapsrv_connection * ldap_conn = conn - > private_data ;
uint8_t * buf ;
int buf_length , msg_length ;
DATA_BLOB blob ;
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-09-20 16:31:07 +04:00
if ( ! read_into_buf ( conn - > socket , & ldap_conn - > in_buffer ) ) {
2004-09-13 14:36:59 +04:00
ldapsrv_terminate_connection ( ldap_conn , " read_into_buf() failed " ) ;
return ;
}
peek_into_read_buf ( & ldap_conn - > in_buffer , & buf , & buf_length ) ;
while ( buf_length > 0 ) {
2004-09-22 14:48:32 +04:00
peek_into_read_buf ( & ldap_conn - > in_buffer , & buf , & buf_length ) ;
2004-09-13 14:36:59 +04:00
/* 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 ;
2004-09-27 17:20:59 +04:00
/* TODO: we should use talloc_reference() here */
call - > session_info = ldap_conn - > session_info ;
2004-09-22 14:48:32 +04:00
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-09-22 14:48:32 +04:00
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-09-22 14:48:32 +04:00
if ( ldap_conn - > out_buffer . length > 0 ) {
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
*/
static void ldapsrv_send ( struct server_connection * conn , time_t t ,
uint16_t flags )
{
struct ldapsrv_connection * ldap_conn = conn - > private_data ;
DEBUG ( 10 , ( " ldapsrv_send \n " ) ) ;
2004-09-20 16:31:07 +04:00
if ( ! write_from_buf ( conn - > socket , & ldap_conn - > out_buffer ) ) {
2004-09-13 14:36:59 +04:00
ldapsrv_terminate_connection ( ldap_conn , " write_from_buf() failed " ) ;
return ;
}
2004-09-22 14:48:32 +04:00
if ( ldap_conn - > out_buffer . length = = 0 ) {
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
*/
static void ldapsrv_idle ( struct server_connection * conn , time_t t )
{
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 ;
}