2005-05-11 08:49:18 +04:00
/*
Unix SMB / CIFS implementation .
CLDAP server task
Copyright ( C ) Andrew Tridgell 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-05-11 08:49:18 +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-11 08:49:18 +04:00
*/
# include "includes.h"
# include "libcli/ldap/ldap.h"
# include "lib/socket/socket.h"
2005-07-10 05:08:10 +04:00
# include "lib/messaging/irpc.h"
2005-05-11 08:49:18 +04:00
# include "smbd/service_task.h"
2006-03-07 15:08:58 +03:00
# include "smbd/service.h"
2005-05-11 08:49:18 +04:00
# include "cldap_server/cldap_server.h"
2006-03-07 14:07:23 +03:00
# include "system/network.h"
2006-08-17 17:37:04 +04:00
# include "lib/socket/netif.h"
2006-11-16 13:47:15 +03:00
# include "lib/ldb/include/ldb.h"
# include "lib/ldb/include/ldb_errors.h"
# include "dsdb/samdb/samdb.h"
2007-11-16 22:12:00 +03:00
# include "ldb_wrap.h"
2006-11-16 13:47:15 +03:00
# include "auth/auth.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2005-05-11 08:49:18 +04:00
/*
handle incoming cldap requests
*/
static void cldapd_request_handler ( struct cldap_socket * cldap ,
struct ldap_message * ldap_msg ,
2006-01-10 01:12:53 +03:00
struct socket_address * src )
2005-05-11 08:49:18 +04:00
{
2005-05-12 12:28:07 +04:00
struct ldap_SearchRequest * search ;
2005-05-11 08:49:18 +04:00
if ( ldap_msg - > type ! = LDAP_TAG_SearchRequest ) {
DEBUG ( 0 , ( " Invalid CLDAP request type %d from %s:%d \n " ,
2006-01-10 01:12:53 +03:00
ldap_msg - > type , src - > addr , src - > port ) ) ;
2006-11-16 13:47:15 +03:00
cldap_error_reply ( cldap , ldap_msg - > messageid , src ,
LDAP_OPERATIONS_ERROR , " Invalid CLDAP request " ) ;
2005-05-11 08:49:18 +04:00
return ;
}
2005-05-12 12:28:07 +04:00
search = & ldap_msg - > r . SearchRequest ;
2006-11-16 13:47:15 +03:00
if ( strcmp ( " " , search - > basedn ) ! = 0 ) {
DEBUG ( 0 , ( " Invalid CLDAP basedn '%s' from %s:%d \n " ,
search - > basedn , src - > addr , src - > port ) ) ;
cldap_error_reply ( cldap , ldap_msg - > messageid , src ,
LDAP_OPERATIONS_ERROR , " Invalid CLDAP basedn " ) ;
return ;
}
if ( search - > scope ! = LDAP_SEARCH_SCOPE_BASE ) {
DEBUG ( 0 , ( " Invalid CLDAP scope %d from %s:%d \n " ,
search - > scope , src - > addr , src - > port ) ) ;
cldap_error_reply ( cldap , ldap_msg - > messageid , src ,
LDAP_OPERATIONS_ERROR , " Invalid CLDAP scope " ) ;
return ;
}
2005-05-12 12:28:07 +04:00
if ( search - > num_attributes = = 1 & &
strcasecmp ( search - > attributes [ 0 ] , " netlogon " ) = = 0 ) {
cldapd_netlogon_request ( cldap , ldap_msg - > messageid ,
2006-01-10 01:12:53 +03:00
search - > tree , src ) ;
2006-11-16 13:47:15 +03:00
return ;
2005-05-12 12:28:07 +04:00
}
2006-11-16 13:47:15 +03:00
cldapd_rootdse_request ( cldap , ldap_msg - > messageid ,
search , src ) ;
2005-05-11 08:49:18 +04:00
}
2005-05-12 12:28:07 +04:00
2005-05-11 08:49:18 +04:00
/*
start listening on the given address
*/
static NTSTATUS cldapd_add_socket ( struct cldapd_server * cldapd , const char * address )
{
struct cldap_socket * cldapsock ;
2006-01-10 01:12:53 +03:00
struct socket_address * socket_address ;
2005-05-11 08:49:18 +04:00
NTSTATUS status ;
2005-06-03 15:19:32 +04:00
/* listen for unicasts on the CLDAP port (389) */
2005-05-11 08:49:18 +04:00
cldapsock = cldap_socket_init ( cldapd , cldapd - > task - > event_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( cldapsock ) ;
2006-01-10 01:12:53 +03:00
socket_address = socket_address_from_strings ( cldapsock , cldapsock - > sock - > backend_name ,
2007-09-28 05:17:46 +04:00
address , lp_cldap_port ( global_loadparm ) ) ;
2006-01-10 01:12:53 +03:00
if ( ! socket_address ) {
talloc_free ( cldapsock ) ;
return NT_STATUS_NO_MEMORY ;
}
status = socket_listen ( cldapsock - > sock , socket_address , 0 , 0 ) ;
2005-05-11 08:49:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to bind to %s:%d - %s \n " ,
2007-09-28 05:17:46 +04:00
address , lp_cldap_port ( global_loadparm ) , nt_errstr ( status ) ) ) ;
2005-05-11 08:49:18 +04:00
talloc_free ( cldapsock ) ;
return status ;
}
2006-01-10 01:12:53 +03:00
talloc_free ( socket_address ) ;
2005-05-11 08:49:18 +04:00
cldap_set_incoming_handler ( cldapsock , cldapd_request_handler , cldapd ) ;
return NT_STATUS_OK ;
}
/*
setup our listening sockets on the configured network interfaces
*/
2006-03-07 14:07:23 +03:00
static NTSTATUS cldapd_startup_interfaces ( struct cldapd_server * cldapd )
2005-05-11 08:49:18 +04:00
{
int num_interfaces = iface_count ( ) ;
TALLOC_CTX * tmp_ctx = talloc_new ( cldapd ) ;
NTSTATUS status ;
/* if we are allowing incoming packets from any address, then
2005-05-12 12:28:07 +04:00
we need to bind to the wildcard address */
2007-09-28 05:17:46 +04:00
if ( ! lp_bind_interfaces_only ( global_loadparm ) ) {
2005-05-11 08:49:18 +04:00
status = cldapd_add_socket ( cldapd , " 0.0.0.0 " ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
} else {
int i ;
for ( i = 0 ; i < num_interfaces ; i + + ) {
const char * address = talloc_strdup ( tmp_ctx , iface_n_ip ( i ) ) ;
status = cldapd_add_socket ( cldapd , address ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
}
}
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
/*
startup the cldapd task
*/
static void cldapd_task_init ( struct task_server * task )
{
struct cldapd_server * cldapd ;
NTSTATUS status ;
if ( iface_count ( ) = = 0 ) {
2005-06-26 03:53:14 +04:00
task_server_terminate ( task , " cldapd: no network interfaces configured " ) ;
2005-05-11 08:49:18 +04:00
return ;
}
2007-11-14 00:26:24 +03:00
switch ( lp_server_role ( global_loadparm ) ) {
case ROLE_STANDALONE :
task_server_terminate ( task , " cldap_server: no CLDAP server required in standalone configuration " ) ;
return ;
case ROLE_DOMAIN_MEMBER :
task_server_terminate ( task , " cldap_server: no CLDAP server required in member server configuration " ) ;
return ;
case ROLE_DOMAIN_CONTROLLER :
/* Yes, we want an CLDAP server */
break ;
}
2006-03-09 20:48:41 +03:00
task_server_set_title ( task , " task[cldapd] " ) ;
2005-05-11 08:49:18 +04:00
cldapd = talloc ( task , struct cldapd_server ) ;
if ( cldapd = = NULL ) {
2005-06-26 03:53:14 +04:00
task_server_terminate ( task , " cldapd: out of memory " ) ;
2005-05-11 08:49:18 +04:00
return ;
}
cldapd - > task = task ;
2006-11-16 13:47:15 +03:00
cldapd - > samctx = samdb_connect ( cldapd , anonymous_session ( cldapd ) ) ;
if ( cldapd - > samctx = = NULL ) {
task_server_terminate ( task , " cldapd failed to open samdb " ) ;
return ;
}
2005-05-11 08:49:18 +04:00
/* start listening on the configured network interfaces */
status = cldapd_startup_interfaces ( cldapd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2005-06-26 03:53:14 +04:00
task_server_terminate ( task , " cldapd failed to setup interfaces " ) ;
2005-05-11 08:49:18 +04:00
return ;
}
2005-07-10 05:08:10 +04:00
irpc_add_name ( task - > msg_ctx , " cldap_server " ) ;
2005-05-11 08:49:18 +04:00
}
/*
initialise the cldapd server
*/
static NTSTATUS cldapd_init ( struct event_context * event_ctx , const struct model_ops * model_ops )
{
return task_server_startup ( event_ctx , model_ops , cldapd_task_init ) ;
}
/*
register ourselves as a available server
*/
NTSTATUS server_service_cldapd_init ( void )
{
return register_server_service ( " cldap " , cldapd_init ) ;
}