2004-09-13 14:36:59 +04:00
/*
Unix SMB / CIFS implementation .
2005-06-19 11:21:18 +04:00
2004-09-13 14:36:59 +04:00
LDAP server
2005-06-19 11:21:18 +04:00
Copyright ( C ) Andrew Tridgell 2005
2004-09-13 14:36:59 +04:00
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"
2005-02-03 14:56:03 +03:00
# include "lib/events/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"
2006-01-03 18:40:05 +03:00
# include "libcli/util/asn_1.h"
2004-11-02 09:52:59 +03:00
# include "ldap_server/ldap_server.h"
2005-06-19 11:21:18 +04:00
# include "smbd/service_task.h"
2005-01-30 03:54:57 +03:00
# include "smbd/service_stream.h"
2006-03-07 17:13:38 +03:00
# include "smbd/service.h"
2005-02-10 09:59:29 +03:00
# include "lib/socket/socket.h"
2005-06-19 11:21:18 +04:00
# include "lib/tls/tls.h"
2005-07-10 05:08:10 +04:00
# include "lib/messaging/irpc.h"
2005-11-10 04:41:47 +03:00
# include "lib/stream/packet.h"
2006-01-13 18:40:15 +03:00
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
2006-03-07 14:07:23 +03:00
# include "system/network.h"
# include "netif/netif.h"
2004-09-13 14:36:59 +04:00
/*
close the socket and shutdown a server_context
*/
2005-06-19 13:31:34 +04:00
static void ldapsrv_terminate_connection ( struct ldapsrv_connection * conn ,
const char * reason )
2004-09-13 14:36:59 +04:00
{
2005-12-08 13:23:56 +03:00
stream_terminate_connection ( conn - > connection , reason ) ;
2004-09-13 14:36:59 +04:00
}
2005-11-10 04:41:47 +03:00
/*
handle packet errors
*/
static void ldapsrv_error_handler ( void * private , NTSTATUS status )
{
struct ldapsrv_connection * conn = talloc_get_type ( private ,
struct ldapsrv_connection ) ;
ldapsrv_terminate_connection ( conn , nt_errstr ( status ) ) ;
}
2005-06-19 13:31:34 +04:00
/*
process a decoded ldap message
*/
static void ldapsrv_process_message ( struct ldapsrv_connection * conn ,
struct ldap_message * msg )
2004-09-13 14:36:59 +04:00
{
2005-06-19 13:31:34 +04:00
struct ldapsrv_call * call ;
2004-09-20 16:31:07 +04:00
NTSTATUS status ;
2005-06-19 13:31:34 +04:00
DATA_BLOB blob ;
BOOL enable_wrap = conn - > enable_wrap ;
2004-09-13 14:36:59 +04:00
2005-06-19 13:31:34 +04:00
call = talloc ( conn , struct ldapsrv_call ) ;
if ( ! call ) {
ldapsrv_terminate_connection ( conn , " no memory " ) ;
return ;
2004-10-28 08:00:43 +04:00
}
2005-06-19 13:31:34 +04:00
call - > request = talloc_steal ( call , msg ) ;
call - > conn = conn ;
call - > replies = NULL ;
2004-10-28 08:00:43 +04:00
2005-06-19 13:31:34 +04:00
/* make the call */
status = ldapsrv_do_call ( call ) ;
2005-06-19 11:21:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-06-19 13:31:34 +04:00
goto failed ;
2004-10-08 16:19:08 +04:00
}
2005-06-19 13:31:34 +04:00
blob = data_blob ( NULL , 0 ) ;
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
if ( call - > replies = = NULL ) {
talloc_free ( call ) ;
return ;
2004-10-28 08:00:43 +04:00
}
2005-06-19 13:31:34 +04:00
/* build all the replies into a single blob */
while ( call - > replies ) {
DATA_BLOB b ;
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
msg = call - > replies - > msg ;
2005-09-14 02:05:45 +04:00
if ( ! ldap_encode ( msg , & b , call ) ) {
2005-06-19 13:31:34 +04:00
DEBUG ( 0 , ( " Failed to encode ldap reply of type %d \n " , msg - > type ) ) ;
goto failed ;
}
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
status = data_blob_append ( call , & blob , b . data , b . length ) ;
2005-09-14 02:05:45 +04:00
data_blob_free ( & b ) ;
2005-06-19 13:31:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
DLIST_REMOVE ( call - > replies , call - > replies ) ;
2004-10-08 16:19:08 +04:00
}
2005-06-19 13:31:34 +04:00
/* possibly encrypt/sign the reply */
if ( enable_wrap ) {
DATA_BLOB wrapped ;
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
status = gensec_wrap ( conn - > gensec , call , & blob , & wrapped ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto failed ;
}
data_blob_free ( & blob ) ;
blob = data_blob_talloc ( call , NULL , wrapped . length + 4 ) ;
2005-06-26 07:29:26 +04:00
if ( blob . data = = NULL ) {
2005-06-19 13:31:34 +04:00
goto failed ;
}
RSIVAL ( blob . data , 0 , wrapped . length ) ;
memcpy ( blob . data + 4 , wrapped . data , wrapped . length ) ;
data_blob_free ( & wrapped ) ;
2004-10-08 16:19:08 +04:00
}
2005-11-10 04:41:47 +03:00
packet_send ( conn - > packet , blob ) ;
2005-06-19 13:31:34 +04:00
talloc_free ( call ) ;
return ;
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
failed :
talloc_free ( call ) ;
2004-10-08 16:19:08 +04:00
}
2004-09-13 14:36:59 +04:00
2005-06-19 13:31:34 +04:00
/*
2005-11-10 04:41:47 +03:00
decode the input buffer
2005-06-19 13:31:34 +04:00
*/
2005-11-10 04:41:47 +03:00
static NTSTATUS ldapsrv_decode_plain ( struct ldapsrv_connection * conn , DATA_BLOB blob )
2004-09-13 14:36:59 +04:00
{
2005-06-19 13:31:34 +04:00
struct asn1_data asn1 ;
2005-11-10 04:41:47 +03:00
struct ldap_message * msg = talloc ( conn , struct ldap_message ) ;
2004-10-10 02:00:00 +04:00
2005-11-10 04:41:47 +03:00
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
2004-10-08 16:19:08 +04:00
}
2005-11-10 04:41:47 +03:00
if ( ! asn1_load ( & asn1 , blob ) ) {
return NT_STATUS_NO_MEMORY ;
2004-10-08 16:19:08 +04:00
}
2005-11-10 04:41:47 +03:00
if ( ! ldap_decode ( & asn1 , msg ) ) {
asn1_free ( & asn1 ) ;
return NT_STATUS_LDAP ( LDAP_PROTOCOL_ERROR ) ;
2004-10-08 16:19:08 +04:00
}
2005-11-10 04:41:47 +03:00
data_blob_free ( & blob ) ;
ldapsrv_process_message ( conn , msg ) ;
2005-06-19 13:31:34 +04:00
asn1_free ( & asn1 ) ;
2005-11-10 04:41:47 +03:00
return NT_STATUS_OK ;
2005-06-19 13:31:34 +04:00
}
2004-10-08 16:19:08 +04:00
2005-06-19 13:31:34 +04:00
/*
2005-11-10 04:41:47 +03:00
decode / process wrapped data
2005-06-19 13:31:34 +04:00
*/
2005-11-10 04:41:47 +03:00
static NTSTATUS ldapsrv_decode_wrapped ( struct ldapsrv_connection * conn ,
DATA_BLOB blob )
2005-06-19 13:31:34 +04:00
{
2005-11-10 04:41:47 +03:00
DATA_BLOB wrapped , unwrapped ;
struct asn1_data asn1 ;
struct ldap_message * msg = talloc ( conn , struct ldap_message ) ;
NTSTATUS status ;
2004-09-13 14:36:59 +04:00
2005-11-10 04:41:47 +03:00
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2004-09-13 14:36:59 +04:00
2005-11-10 04:41:47 +03:00
wrapped = data_blob_const ( blob . data + 4 , blob . length - 4 ) ;
2004-09-13 14:36:59 +04:00
2005-11-10 04:41:47 +03:00
status = gensec_unwrap ( conn - > gensec , msg , & wrapped , & unwrapped ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NT_STATUS_LDAP ( LDAP_PROTOCOL_ERROR ) ;
}
2004-09-13 14:36:59 +04:00
2005-11-10 04:41:47 +03:00
data_blob_free ( & blob ) ;
2004-09-13 14:36:59 +04:00
2005-11-10 04:41:47 +03:00
if ( ! asn1_load ( & asn1 , unwrapped ) ) {
return NT_STATUS_LDAP ( LDAP_PROTOCOL_ERROR ) ;
}
2005-06-19 13:31:34 +04:00
2005-11-10 04:41:47 +03:00
while ( ldap_decode ( & asn1 , msg ) ) {
ldapsrv_process_message ( conn , msg ) ;
msg = talloc ( conn , struct ldap_message ) ;
2004-09-13 14:36:59 +04:00
}
2005-11-10 04:41:47 +03:00
if ( asn1 . ofs < asn1 . length ) {
return NT_STATUS_LDAP ( LDAP_PROTOCOL_ERROR ) ;
}
talloc_free ( msg ) ;
asn1_free ( & asn1 ) ;
return NT_STATUS_OK ;
2004-09-13 14:36:59 +04:00
}
2005-11-10 04:41:47 +03:00
/*
decode / process data
*/
static NTSTATUS ldapsrv_decode ( void * private , DATA_BLOB blob )
{
struct ldapsrv_connection * conn = talloc_get_type ( private ,
struct ldapsrv_connection ) ;
if ( conn - > enable_wrap ) {
return ldapsrv_decode_wrapped ( conn , blob ) ;
}
return ldapsrv_decode_plain ( conn , blob ) ;
}
2004-10-10 02:00:00 +04:00
2006-01-14 01:48:08 +03:00
/*
Idle timeout handler
*/
static void ldapsrv_conn_idle_timeout ( struct event_context * ev ,
struct timed_event * te ,
struct timeval t ,
void * private )
{
struct ldapsrv_connection * conn = talloc_get_type ( private , struct ldapsrv_connection ) ;
ldapsrv_terminate_connection ( conn , " Timeout. No requests after bind " ) ;
}
2004-09-13 14:36:59 +04:00
/*
called when a LDAP socket becomes readable
*/
2005-06-19 13:31:34 +04:00
static void ldapsrv_recv ( struct stream_connection * c , uint16_t flags )
2004-09-13 14:36:59 +04:00
{
2005-06-19 13:31:34 +04:00
struct ldapsrv_connection * conn =
talloc_get_type ( c - > private , struct ldapsrv_connection ) ;
2006-01-13 03:38:35 +03:00
2006-01-14 01:48:08 +03:00
if ( conn - > limits . ite ) { /* clean initial timeout if any */
2006-01-13 03:38:35 +03:00
talloc_free ( conn - > limits . ite ) ;
conn - > limits . ite = NULL ;
}
2006-01-14 01:48:08 +03:00
if ( conn - > limits . te ) { /* clean idle timeout if any */
talloc_free ( conn - > limits . te ) ;
conn - > limits . te = NULL ;
}
2005-11-10 04:41:47 +03:00
packet_recv ( conn - > packet ) ;
2006-01-14 01:48:08 +03:00
/* set idle timeout */
conn - > limits . te = event_add_timed ( c - > event . ctx , conn ,
timeval_current_ofs ( conn - > limits . conn_idle_time , 0 ) ,
ldapsrv_conn_idle_timeout , conn ) ;
2004-09-13 14:36:59 +04:00
}
2005-11-10 04:41:47 +03:00
/*
check if a blob is a complete ldap packet
handle wrapper or unwrapped connections
*/
NTSTATUS ldapsrv_complete_packet ( void * private , DATA_BLOB blob , size_t * size )
{
struct ldapsrv_connection * conn = talloc_get_type ( private ,
struct ldapsrv_connection ) ;
if ( conn - > enable_wrap ) {
return packet_full_request_u32 ( private , blob , size ) ;
}
return ldap_full_packet ( private , blob , size ) ;
}
2004-09-13 14:36:59 +04:00
/*
called when a LDAP socket becomes writable
*/
2005-06-19 13:31:34 +04:00
static void ldapsrv_send ( struct stream_connection * c , uint16_t flags )
2004-09-13 14:36:59 +04:00
{
2005-06-19 13:31:34 +04:00
struct ldapsrv_connection * conn =
talloc_get_type ( c - > private , struct ldapsrv_connection ) ;
2005-11-10 04:41:47 +03:00
packet_queue_run ( conn - > packet ) ;
2004-09-13 14:36:59 +04:00
}
2006-01-13 03:38:35 +03:00
static void ldapsrv_conn_init_timeout ( struct event_context * ev ,
struct timed_event * te ,
struct timeval t ,
void * private )
{
struct ldapsrv_connection * conn = talloc_get_type ( private , struct ldapsrv_connection ) ;
ldapsrv_terminate_connection ( conn , " Timeout. No requests after initial connection " ) ;
}
2006-01-13 18:40:15 +03:00
static int ldapsrv_load_limits ( struct ldapsrv_connection * conn )
{
TALLOC_CTX * tmp_ctx ;
const char * attrs [ ] = { " configurationNamingContext " , NULL } ;
const char * attrs2 [ ] = { " lDAPAdminLimits " , NULL } ;
const char * conf_dn_s ;
struct ldb_message_element * el ;
struct ldb_result * res = NULL ;
struct ldb_dn * basedn ;
struct ldb_dn * conf_dn ;
struct ldb_dn * policy_dn ;
int i , ret ;
/* set defaults limits in case of failure */
conn - > limits . initial_timeout = 120 ;
conn - > limits . conn_idle_time = 900 ;
conn - > limits . max_page_size = 1000 ;
conn - > limits . search_timeout = 120 ;
tmp_ctx = talloc_new ( conn ) ;
if ( tmp_ctx = = NULL ) {
return - 1 ;
}
basedn = ldb_dn_explode ( tmp_ctx , " " ) ;
if ( basedn = = NULL ) {
goto failed ;
}
ret = ldb_search ( conn - > ldb , basedn , LDB_SCOPE_BASE , NULL , attrs , & res ) ;
talloc_steal ( tmp_ctx , res ) ;
if ( ret ! = LDB_SUCCESS | | res - > count ! = 1 ) {
goto failed ;
}
conf_dn_s = ldb_msg_find_string ( res - > msgs [ 0 ] , " configurationNamingContext " , NULL ) ;
if ( conf_dn_s = = NULL ) {
goto failed ;
}
conf_dn = ldb_dn_explode ( tmp_ctx , conf_dn_s ) ;
if ( conf_dn = = NULL ) {
goto failed ;
}
policy_dn = ldb_dn_string_compose ( tmp_ctx , conf_dn , " CN=Default Query Policy,CN=Query-Policies,CN=Directory Service,CN=Windows NT,CN=Services " ) ;
if ( policy_dn = = NULL ) {
goto failed ;
}
ret = ldb_search ( conn - > ldb , policy_dn , LDB_SCOPE_BASE , NULL , attrs2 , & res ) ;
talloc_steal ( tmp_ctx , res ) ;
if ( ret ! = LDB_SUCCESS | | res - > count ! = 1 ) {
goto failed ;
}
el = ldb_msg_find_element ( res - > msgs [ 0 ] , " lDAPAdminLimits " ) ;
if ( el = = NULL ) {
goto failed ;
}
for ( i = 0 ; i < el - > num_values ; i + + ) {
char policy_name [ 256 ] ;
int policy_value , s ;
2006-03-03 11:23:57 +03:00
s = sscanf ( ( const char * ) el - > values [ i ] . data , " %255[^=]=%d " , policy_name , & policy_value ) ;
2006-01-13 18:40:15 +03:00
if ( ret ! = 2 | | policy_value = = 0 )
continue ;
if ( strcasecmp ( " InitRecvTimeout " , policy_name ) = = 0 ) {
conn - > limits . initial_timeout = policy_value ;
continue ;
}
if ( strcasecmp ( " MaxConnIdleTime " , policy_name ) = = 0 ) {
conn - > limits . conn_idle_time = policy_value ;
continue ;
}
if ( strcasecmp ( " MaxPageSize " , policy_name ) = = 0 ) {
conn - > limits . max_page_size = policy_value ;
continue ;
}
if ( strcasecmp ( " MaxQueryDuration " , policy_name ) = = 0 ) {
conn - > limits . search_timeout = policy_value ;
continue ;
}
}
return 0 ;
failed :
DEBUG ( 0 , ( " Failed to load ldap server query policies \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return - 1 ;
}
2004-09-13 14:36:59 +04:00
/*
initialise a server_context from a open socket and register a event handler
for reading from that socket
*/
2005-06-19 13:31:34 +04:00
static void ldapsrv_accept ( struct stream_connection * c )
2004-09-13 14:36:59 +04:00
{
2005-06-19 11:21:18 +04:00
struct ldapsrv_service * ldapsrv_service =
2005-06-19 13:31:34 +04:00
talloc_get_type ( c - > private , struct ldapsrv_service ) ;
struct ldapsrv_connection * conn ;
2006-01-03 03:10:15 +03:00
struct cli_credentials * server_credentials ;
2006-01-10 01:12:53 +03:00
struct socket_address * socket_address ;
2006-01-03 03:10:15 +03:00
NTSTATUS status ;
2005-06-19 15:10:15 +04:00
int port ;
2004-09-13 14:36:59 +04:00
2005-06-19 13:31:34 +04:00
conn = talloc_zero ( c , struct ldapsrv_connection ) ;
2005-09-08 15:26:05 +04:00
if ( ! conn ) {
stream_terminate_connection ( c , " ldapsrv_accept: out of memory " ) ;
return ;
}
2004-09-13 14:36:59 +04:00
2005-06-19 13:31:34 +04:00
conn - > enable_wrap = False ;
2005-11-10 04:41:47 +03:00
conn - > packet = NULL ;
2005-06-19 13:31:34 +04:00
conn - > connection = c ;
2005-09-08 15:26:05 +04:00
conn - > service = ldapsrv_service ;
2006-01-03 03:10:15 +03:00
2005-06-19 13:31:34 +04:00
c - > private = conn ;
2005-06-19 11:21:18 +04:00
2006-01-10 01:12:53 +03:00
socket_address = socket_get_my_addr ( c - > socket , conn ) ;
if ( ! socket_address ) {
ldapsrv_terminate_connection ( conn , " ldapsrv_accept: failed to obtain local socket address! " ) ;
return ;
}
port = socket_address - > port ;
talloc_free ( socket_address ) ;
2005-06-19 15:10:15 +04:00
2006-05-03 00:15:47 +04:00
if ( port = = 636 ) {
c - > socket = tls_init_server ( ldapsrv_service - > tls_params , c - > socket ,
c - > event . fde , NULL ) ;
if ( ! c - > socket ) {
ldapsrv_terminate_connection ( conn , " ldapsrv_accept: tls_init_server() failed " ) ;
return ;
}
2005-09-08 15:26:05 +04:00
}
2005-11-10 04:41:47 +03:00
conn - > packet = packet_init ( conn ) ;
if ( conn - > packet = = NULL ) {
ldapsrv_terminate_connection ( conn , " out of memory " ) ;
2005-12-08 13:23:56 +03:00
return ;
2005-11-10 04:41:47 +03:00
}
2006-04-29 13:20:22 +04:00
2005-11-10 04:41:47 +03:00
packet_set_private ( conn - > packet , conn ) ;
2006-05-03 00:15:47 +04:00
packet_set_socket ( conn - > packet , c - > socket ) ;
2005-11-10 04:41:47 +03:00
packet_set_callback ( conn - > packet , ldapsrv_decode ) ;
packet_set_full_request ( conn - > packet , ldapsrv_complete_packet ) ;
packet_set_error_handler ( conn - > packet , ldapsrv_error_handler ) ;
packet_set_event_context ( conn - > packet , c - > event . ctx ) ;
2005-11-14 06:45:57 +03:00
packet_set_fde ( conn - > packet , c - > event . fde ) ;
packet_set_serialise ( conn - > packet ) ;
2006-04-29 13:20:22 +04:00
/* Ensure we don't get packets until the database is ready below */
packet_recv_disable ( conn - > packet ) ;
server_credentials
= cli_credentials_init ( conn ) ;
if ( ! server_credentials ) {
stream_terminate_connection ( c , " Failed to init server credentials \n " ) ;
return ;
}
cli_credentials_set_conf ( server_credentials ) ;
status = cli_credentials_set_machine_account ( server_credentials ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
stream_terminate_connection ( c , talloc_asprintf ( conn , " Failed to obtain server credentials, perhaps a standalone server?: %s \n " , nt_errstr ( status ) ) ) ;
return ;
}
conn - > server_credentials = server_credentials ;
2005-11-10 04:41:47 +03:00
2005-10-07 15:31:45 +04:00
/* Connections start out anonymous */
if ( ! NT_STATUS_IS_OK ( auth_anonymous_session_info ( conn , & conn - > session_info ) ) ) {
ldapsrv_terminate_connection ( conn , " failed to setup anonymous session info " ) ;
2005-12-08 13:23:56 +03:00
return ;
2005-10-07 15:31:45 +04:00
}
2006-01-13 03:38:35 +03:00
if ( ! NT_STATUS_IS_OK ( ldapsrv_backend_Init ( conn ) ) ) {
ldapsrv_terminate_connection ( conn , " backend Init failed " ) ;
2005-12-08 13:23:56 +03:00
return ;
2005-10-07 15:31:45 +04:00
}
2006-01-13 18:40:15 +03:00
/* load limits from the conf partition */
ldapsrv_load_limits ( conn ) ; /* should we fail on error ? */
2005-10-07 15:31:45 +04:00
2006-01-13 03:38:35 +03:00
/* register the server */
2005-07-10 05:08:10 +04:00
irpc_add_name ( c - > msg_ctx , " ldap_server " ) ;
2006-01-13 03:38:35 +03:00
/* set connections limits */
conn - > limits . ite = event_add_timed ( c - > event . ctx , conn ,
timeval_current_ofs ( conn - > limits . initial_timeout , 0 ) ,
ldapsrv_conn_init_timeout , conn ) ;
2006-04-29 13:20:22 +04:00
packet_recv_enable ( conn - > packet ) ;
2004-09-13 14:36:59 +04:00
}
2005-01-30 03:54:57 +03:00
static const struct stream_server_ops ldap_stream_ops = {
2005-01-14 04:32:56 +03:00
. name = " ldap " ,
. accept_connection = ldapsrv_accept ,
. recv_handler = ldapsrv_recv ,
. send_handler = ldapsrv_send ,
} ;
2005-01-30 03:54:57 +03:00
/*
add a socket address to the list of events , one event per port
*/
2005-06-19 13:31:34 +04:00
static NTSTATUS add_socket ( struct event_context * event_context ,
const struct model_ops * model_ops ,
2005-01-30 03:54:57 +03:00
const char * address , struct ldapsrv_service * ldap_service )
2004-09-13 14:36:59 +04:00
{
2005-01-30 03:54:57 +03:00
uint16_t port = 389 ;
NTSTATUS status ;
status = stream_setup_socket ( event_context , model_ops , & ldap_stream_ops ,
" ipv4 " , address , & port , ldap_service ) ;
2005-06-19 11:21:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " ldapsrv failed to bind to %s:%u - %s \n " ,
address , port , nt_errstr ( status ) ) ) ;
}
2005-01-30 03:54:57 +03:00
2005-06-19 13:31:34 +04:00
if ( tls_support ( ldap_service - > tls_params ) ) {
/* add ldaps server */
port = 636 ;
status = stream_setup_socket ( event_context , model_ops , & ldap_stream_ops ,
" ipv4 " , address , & port , ldap_service ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " ldapsrv failed to bind to %s:%u - %s \n " ,
address , port , nt_errstr ( status ) ) ) ;
}
2005-06-19 11:21:18 +04:00
}
2005-06-19 13:31:34 +04:00
2005-10-17 15:32:20 +04:00
/* if we are a PDC, then also enable the global catalog server port, 3268 */
if ( lp_server_role ( ) = = ROLE_DOMAIN_PDC ) {
port = 3268 ;
status = stream_setup_socket ( event_context , model_ops , & ldap_stream_ops ,
" ipv4 " , address , & port , ldap_service ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " ldapsrv failed to bind to %s:%u - %s \n " ,
address , port , nt_errstr ( status ) ) ) ;
}
}
2005-06-19 11:21:18 +04:00
return status ;
2004-09-13 14:36:59 +04:00
}
2005-01-30 03:54:57 +03:00
/*
open the ldap server sockets
*/
2005-06-19 11:21:18 +04:00
static void ldapsrv_task_init ( struct task_server * task )
2005-01-30 03:54:57 +03:00
{
struct ldapsrv_service * ldap_service ;
NTSTATUS status ;
2004-09-13 14:36:59 +04:00
2006-03-09 20:48:41 +03:00
task_server_set_title ( task , " task[ldapsrv] " ) ;
2005-06-19 11:21:18 +04:00
ldap_service = talloc_zero ( task , struct ldapsrv_service ) ;
if ( ldap_service = = NULL ) goto failed ;
2005-01-30 03:54:57 +03:00
2005-06-19 11:21:18 +04:00
ldap_service - > tls_params = tls_initialise ( ldap_service ) ;
if ( ldap_service - > tls_params = = NULL ) goto failed ;
2005-01-30 03:54:57 +03: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 + + ) {
2005-02-10 06:22:47 +03:00
const char * address = iface_n_ip ( i ) ;
2005-06-19 11:21:18 +04:00
status = add_socket ( task - > event_ctx , task - > model_ops , address , ldap_service ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2005-01-30 03:54:57 +03:00
}
} else {
2005-06-19 11:21:18 +04:00
status = add_socket ( task - > event_ctx , task - > model_ops , lp_socket_address ( ) , ldap_service ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2005-01-30 03:54:57 +03:00
}
2005-06-19 11:21:18 +04:00
return ;
failed :
2005-06-26 03:53:14 +04:00
task_server_terminate ( task , " Failed to startup ldap server task " ) ;
2005-06-19 11:21:18 +04:00
}
/*
called on startup of the web server service It ' s job is to start
listening on all configured sockets
*/
static NTSTATUS ldapsrv_init ( struct event_context * event_context ,
const struct model_ops * model_ops )
{
return task_server_startup ( event_context , model_ops , ldapsrv_task_init ) ;
2004-09-13 14:36:59 +04:00
}
2005-01-30 03:54:57 +03:00
2004-09-13 14:36:59 +04:00
NTSTATUS server_service_ldap_init ( void )
{
2005-01-30 03:54:57 +03:00
return register_server_service ( " ldap " , ldapsrv_init ) ;
2004-09-13 14:36:59 +04:00
}