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"
2009-02-13 15:13:54 +03:00
# include <talloc.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"
2011-02-10 06:12:51 +03:00
# include <ldb.h>
# include <ldb_errors.h>
2006-11-16 13:47:15 +03:00
# 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"
2009-02-13 15:13:54 +03:00
# include "../lib/tsocket/tsocket.h"
2015-12-28 22:01:54 +03:00
# include "libds/common/roles.h"
2005-05-11 08:49:18 +04:00
2011-03-19 02:45:45 +03:00
NTSTATUS server_service_cldapd_init ( void ) ;
2005-05-11 08:49:18 +04:00
/*
handle incoming cldap requests
*/
2009-02-13 15:13:54 +03:00
static void cldapd_request_handler ( struct cldap_socket * cldap ,
void * private_data ,
struct cldap_incoming * in )
2005-05-11 08:49:18 +04:00
{
2009-02-13 15:13:54 +03:00
struct cldapd_server * cldapd = talloc_get_type ( private_data ,
struct cldapd_server ) ;
2005-05-12 12:28:07 +04:00
struct ldap_SearchRequest * search ;
2009-02-13 15:13:54 +03:00
2013-12-05 02:53:14 +04:00
if ( in - > ldap_msg - > type = = LDAP_TAG_AbandonRequest ) {
DEBUG ( 10 , ( " Got (and ignoring) CLDAP AbandonRequest from %s. " ,
tsocket_address_string ( in - > src , in ) ) ) ;
talloc_free ( in ) ;
return ;
}
2009-02-13 15:13:54 +03:00
if ( in - > ldap_msg - > type ! = LDAP_TAG_SearchRequest ) {
DEBUG ( 0 , ( " Invalid CLDAP request type %d from %s \n " ,
in - > ldap_msg - > type ,
tsocket_address_string ( in - > src , in ) ) ) ;
cldap_error_reply ( cldap , in - > ldap_msg - > messageid , in - > src ,
2006-11-16 13:47:15 +03:00
LDAP_OPERATIONS_ERROR , " Invalid CLDAP request " ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( in ) ;
2005-05-11 08:49:18 +04:00
return ;
}
2005-05-12 12:28:07 +04:00
2009-02-13 15:13:54 +03:00
search = & in - > ldap_msg - > r . SearchRequest ;
2005-05-12 12:28:07 +04:00
2006-11-16 13:47:15 +03:00
if ( strcmp ( " " , search - > basedn ) ! = 0 ) {
2009-02-13 15:13:54 +03:00
DEBUG ( 0 , ( " Invalid CLDAP basedn '%s' from %s \n " ,
search - > basedn ,
tsocket_address_string ( in - > src , in ) ) ) ;
cldap_error_reply ( cldap , in - > ldap_msg - > messageid , in - > src ,
2006-11-16 13:47:15 +03:00
LDAP_OPERATIONS_ERROR , " Invalid CLDAP basedn " ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( in ) ;
2006-11-16 13:47:15 +03:00
return ;
}
if ( search - > scope ! = LDAP_SEARCH_SCOPE_BASE ) {
2009-02-13 15:13:54 +03:00
DEBUG ( 0 , ( " Invalid CLDAP scope %d from %s \n " ,
search - > scope ,
tsocket_address_string ( in - > src , in ) ) ) ;
cldap_error_reply ( cldap , in - > ldap_msg - > messageid , in - > src ,
2006-11-16 13:47:15 +03:00
LDAP_OPERATIONS_ERROR , " Invalid CLDAP scope " ) ;
2009-02-13 15:13:54 +03:00
talloc_free ( in ) ;
2006-11-16 13:47:15 +03:00
return ;
}
2009-02-13 15:13:54 +03:00
cldapd_rootdse_request ( cldap , cldapd , in ,
in - > ldap_msg - > messageid ,
search , in - > src ) ;
talloc_free ( in ) ;
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
*/
2007-12-02 23:32:08 +03:00
static NTSTATUS cldapd_add_socket ( struct cldapd_server * cldapd , struct loadparm_context * lp_ctx ,
const char * address )
2005-05-11 08:49:18 +04:00
{
struct cldap_socket * cldapsock ;
2009-02-13 15:13:54 +03:00
struct tsocket_address * socket_address ;
2005-05-11 08:49:18 +04:00
NTSTATUS status ;
2009-02-13 15:13:54 +03:00
int ret ;
ret = tsocket_address_inet_from_strings ( cldapd ,
" ip " ,
address ,
2010-07-16 08:32:42 +04:00
lpcfg_cldap_port ( lp_ctx ) ,
2009-02-13 15:13:54 +03:00
& socket_address ) ;
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
DEBUG ( 0 , ( " invalid address %s:%d - %s:%s \n " ,
2010-07-16 08:32:42 +04:00
address , lpcfg_cldap_port ( lp_ctx ) ,
2009-02-13 15:13:54 +03:00
gai_strerror ( ret ) , nt_errstr ( status ) ) ) ;
return status ;
2006-01-10 01:12:53 +03:00
}
2009-02-13 15:13:54 +03:00
/* listen for unicasts on the CLDAP port (389) */
status = cldap_socket_init ( cldapd ,
socket_address ,
NULL ,
& cldapsock ) ;
2005-05-11 08:49:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-02-13 15:13:54 +03:00
DEBUG ( 0 , ( " Failed to bind to %s - %s \n " ,
tsocket_address_string ( socket_address , socket_address ) ,
nt_errstr ( status ) ) ) ;
talloc_free ( socket_address ) ;
2005-05-11 08:49:18 +04:00
return status ;
}
2006-01-10 01:12:53 +03:00
talloc_free ( socket_address ) ;
2011-10-10 17:38:22 +04:00
cldap_set_incoming_handler ( cldapsock , cldapd - > task - > event_ctx ,
cldapd_request_handler , cldapd ) ;
2005-05-11 08:49:18 +04:00
return NT_STATUS_OK ;
}
/*
setup our listening sockets on the configured network interfaces
*/
2007-12-12 00:23:14 +03:00
static NTSTATUS cldapd_startup_interfaces ( struct cldapd_server * cldapd , struct loadparm_context * lp_ctx ,
struct interface * ifaces )
2005-05-11 08:49:18 +04:00
{
2010-06-18 20:57:38 +04:00
int i , num_interfaces ;
2005-05-11 08:49:18 +04:00
TALLOC_CTX * tmp_ctx = talloc_new ( cldapd ) ;
NTSTATUS status ;
2011-05-02 09:57:19 +04:00
num_interfaces = iface_list_count ( ifaces ) ;
2007-12-12 00:23:14 +03:00
2005-05-11 08:49:18 +04:00
/* 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 */
2010-07-16 08:32:42 +04:00
if ( ! lpcfg_bind_interfaces_only ( lp_ctx ) ) {
2014-06-05 23:32:30 +04:00
int num_binds = 0 ;
2014-02-27 13:28:23 +04:00
char * * wcard = iface_list_wildcard ( cldapd ) ;
2011-05-12 14:35:02 +04:00
NT_STATUS_HAVE_NO_MEMORY ( wcard ) ;
for ( i = 0 ; wcard [ i ] ; i + + ) {
status = cldapd_add_socket ( cldapd , lp_ctx , wcard [ i ] ) ;
2014-06-05 23:32:30 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
num_binds + + ;
}
2011-05-12 14:35:02 +04:00
}
talloc_free ( wcard ) ;
2014-06-05 23:32:30 +04:00
if ( num_binds = = 0 ) {
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
2008-10-03 08:55:26 +04:00
}
/* now we have to also listen on the specific interfaces,
so that replies always come from the right IP */
for ( i = 0 ; i < num_interfaces ; i + + ) {
2011-05-02 09:57:19 +04:00
const char * address = talloc_strdup ( tmp_ctx , iface_list_n_ip ( ifaces , i ) ) ;
2008-10-03 08:55:26 +04:00
status = cldapd_add_socket ( cldapd , lp_ctx , address ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2005-05-11 08:49:18 +04:00
}
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 ;
2007-12-12 00:23:14 +03:00
struct interface * ifaces ;
2011-06-02 09:40:28 +04:00
load_interface_list ( task , task - > lp_ctx , & ifaces ) ;
2005-05-11 08:49:18 +04:00
2011-05-02 09:57:19 +04:00
if ( iface_list_count ( ifaces ) = = 0 ) {
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " cldapd: no network interfaces configured " , false ) ;
2005-05-11 08:49:18 +04:00
return ;
}
2010-07-16 08:32:42 +04:00
switch ( lpcfg_server_role ( task - > lp_ctx ) ) {
2007-11-14 00:26:24 +03:00
case ROLE_STANDALONE :
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " cldap_server: no CLDAP server required in standalone configuration " ,
false ) ;
2007-11-14 00:26:24 +03:00
return ;
case ROLE_DOMAIN_MEMBER :
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " cldap_server: no CLDAP server required in member server configuration " ,
false ) ;
2007-11-14 00:26:24 +03:00
return ;
2012-06-10 16:08:20 +04:00
case ROLE_ACTIVE_DIRECTORY_DC :
2007-11-14 00:26:24 +03:00
/* 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 ) {
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " cldapd: out of memory " , true ) ;
2005-05-11 08:49:18 +04:00
return ;
}
cldapd - > task = task ;
2010-10-10 19:00:45 +04:00
cldapd - > samctx = samdb_connect ( cldapd , task - > event_ctx , task - > lp_ctx , system_session ( task - > lp_ctx ) , 0 ) ;
2006-11-16 13:47:15 +03:00
if ( cldapd - > samctx = = NULL ) {
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " cldapd failed to open samdb " , true ) ;
2006-11-16 13:47:15 +03:00
return ;
}
2005-05-11 08:49:18 +04:00
/* start listening on the configured network interfaces */
2007-12-12 00:23:14 +03:00
status = cldapd_startup_interfaces ( cldapd , task - > lp_ctx , ifaces ) ;
2005-05-11 08:49:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-09-19 05:05:55 +04:00
task_server_terminate ( task , " cldapd failed to setup interfaces " , true ) ;
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
}
/*
register ourselves as a available server
*/
NTSTATUS server_service_cldapd_init ( void )
{
2008-02-04 13:58:29 +03:00
return register_server_service ( " cldap " , cldapd_task_init ) ;
2005-05-11 08:49:18 +04:00
}