2005-01-14 05:01:19 +03:00
/*
Unix SMB / CIFS implementation .
Main winbindd server routines
Copyright ( C ) Stefan Metzmacher 2005
2005-01-30 05:55:30 +03:00
Copyright ( C ) Andrew Tridgell 2005
2005-01-14 05:01:19 +03:00
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-01-14 05:01:19 +03: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-01-14 05:01:19 +03:00
*/
# include "includes.h"
2005-02-10 09:59:29 +03:00
# include "lib/socket/socket.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2005-02-03 14:56:03 +03:00
# include "lib/events/events.h"
2005-01-30 05:55:30 +03:00
# include "smbd/service_task.h"
2006-03-07 14:07:23 +03:00
# include "smbd/process_model.h"
2005-01-30 05:55:30 +03:00
# include "smbd/service_stream.h"
2005-09-21 01:37:10 +04:00
# include "nsswitch/winbind_nss_config.h"
2005-09-22 22:35:08 +04:00
# include "winbind/wb_server.h"
2006-01-12 12:38:35 +03:00
# include "lib/stream/packet.h"
2006-03-07 15:08:58 +03:00
# include "smbd/service.h"
2006-11-06 19:11:52 +03:00
# include "param/secrets.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2005-01-14 05:01:19 +03:00
2005-09-22 22:35:08 +04:00
void wbsrv_terminate_connection ( struct wbsrv_connection * wbconn , const char * reason )
{
stream_terminate_connection ( wbconn - > conn , reason ) ;
}
2005-01-14 05:01:19 +03:00
2005-01-30 05:55:30 +03:00
/*
2006-01-12 12:38:35 +03:00
called on a tcp recv error
2005-01-30 05:55:30 +03:00
*/
2009-02-02 10:43:37 +03:00
static void wbsrv_recv_error ( void * private_data , NTSTATUS status )
2006-01-12 12:38:35 +03:00
{
2009-02-02 10:43:37 +03:00
struct wbsrv_connection * wbconn = talloc_get_type ( private_data , struct wbsrv_connection ) ;
2006-01-12 12:38:35 +03:00
wbsrv_terminate_connection ( wbconn , nt_errstr ( status ) ) ;
}
2005-09-22 22:35:08 +04:00
static void wbsrv_accept ( struct stream_connection * conn )
2005-01-14 05:01:19 +03:00
{
2009-02-02 12:30:03 +03:00
struct wbsrv_listen_socket * listen_socket = talloc_get_type ( conn - > private_data ,
2006-01-12 12:38:35 +03:00
struct wbsrv_listen_socket ) ;
2005-09-22 22:35:08 +04:00
struct wbsrv_connection * wbconn ;
2005-01-14 05:01:19 +03:00
2005-09-22 22:35:08 +04:00
wbconn = talloc_zero ( conn , struct wbsrv_connection ) ;
if ( ! wbconn ) {
2006-01-12 12:38:35 +03:00
stream_terminate_connection ( conn , " wbsrv_accept: out of memory " ) ;
2005-01-14 05:01:19 +03:00
return ;
}
2006-01-12 12:38:35 +03:00
wbconn - > conn = conn ;
wbconn - > listen_socket = listen_socket ;
2007-12-04 01:33:22 +03:00
wbconn - > lp_ctx = listen_socket - > service - > task - > lp_ctx ;
2009-02-02 12:30:03 +03:00
conn - > private_data = wbconn ;
2005-01-14 05:01:19 +03:00
2006-01-12 12:38:35 +03:00
wbconn - > packet = packet_init ( wbconn ) ;
if ( wbconn - > packet = = NULL ) {
wbsrv_terminate_connection ( wbconn , " wbsrv_accept: out of memory " ) ;
2005-09-21 00:54:25 +04:00
return ;
}
2006-01-12 12:38:35 +03:00
packet_set_private ( wbconn - > packet , wbconn ) ;
packet_set_socket ( wbconn - > packet , conn - > socket ) ;
packet_set_callback ( wbconn - > packet , wbsrv_samba3_process ) ;
packet_set_full_request ( wbconn - > packet , wbsrv_samba3_packet_full_request ) ;
packet_set_error_handler ( wbconn - > packet , wbsrv_recv_error ) ;
packet_set_event_context ( wbconn - > packet , conn - > event . ctx ) ;
packet_set_fde ( wbconn - > packet , conn - > event . fde ) ;
packet_set_serialise ( wbconn - > packet ) ;
2005-09-21 00:54:25 +04:00
}
2005-09-22 22:35:08 +04:00
/*
2006-01-12 12:38:35 +03:00
receive some data on a winbind connection
*/
static void wbsrv_recv ( struct stream_connection * conn , uint16_t flags )
2005-09-21 00:54:25 +04:00
{
2009-02-02 12:30:03 +03:00
struct wbsrv_connection * wbconn = talloc_get_type ( conn - > private_data ,
2006-01-12 12:38:35 +03:00
struct wbsrv_connection ) ;
packet_recv ( wbconn - > packet ) ;
2005-09-21 00:54:25 +04:00
}
2005-09-22 22:35:08 +04:00
/*
called when we can write to a connection
*/
static void wbsrv_send ( struct stream_connection * conn , uint16_t flags )
2005-09-21 00:54:25 +04:00
{
2009-02-02 12:30:03 +03:00
struct wbsrv_connection * wbconn = talloc_get_type ( conn - > private_data ,
2006-01-12 12:38:35 +03:00
struct wbsrv_connection ) ;
packet_queue_run ( wbconn - > packet ) ;
2005-09-21 00:54:25 +04:00
}
2005-09-22 22:35:08 +04:00
static const struct stream_server_ops wbsrv_ops = {
2006-01-12 12:38:35 +03:00
. name = " winbind samba3 protocol " ,
2005-09-22 22:35:08 +04:00
. accept_connection = wbsrv_accept ,
. recv_handler = wbsrv_recv ,
. send_handler = wbsrv_send
} ;
2005-01-30 05:55:30 +03:00
/*
startup the winbind task
*/
static void winbind_task_init ( struct task_server * task )
2005-01-14 05:01:19 +03:00
{
uint16_t port = 1 ;
2005-01-30 05:55:30 +03:00
const struct model_ops * model_ops ;
NTSTATUS status ;
2005-09-22 22:35:08 +04:00
struct wbsrv_service * service ;
struct wbsrv_listen_socket * listen_socket ;
2005-01-14 05:01:19 +03:00
2006-03-09 20:48:41 +03:00
task_server_set_title ( task , " task[winbind] " ) ;
2005-01-30 05:55:30 +03:00
/* within the winbind task we want to be a single process, so
ask for the single process model ops and pass these to the
stream_setup_socket ( ) call . */
2008-09-22 20:15:24 +04:00
model_ops = process_model_startup ( task - > event_ctx , " single " ) ;
2005-01-30 05:55:30 +03:00
if ( ! model_ops ) {
2005-10-09 12:32:06 +04:00
task_server_terminate ( task ,
" Can't find 'single' process model_ops " ) ;
2005-01-30 05:55:30 +03:00
return ;
}
2005-01-14 05:01:19 +03:00
2006-01-31 03:48:57 +03:00
/* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
2007-12-02 21:27:49 +03:00
if ( ! directory_create_or_exist ( lp_winbindd_socket_directory ( task - > lp_ctx ) , geteuid ( ) , 0755 ) ) {
2006-01-31 03:48:57 +03:00
task_server_terminate ( task ,
" Cannot create winbindd pipe directory " ) ;
return ;
2005-01-14 05:01:19 +03:00
}
2008-06-28 16:02:19 +04:00
/* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
if ( ! directory_create_or_exist ( lp_winbindd_privileged_socket_directory ( task - > lp_ctx ) , geteuid ( ) , 0750 ) ) {
task_server_terminate ( task ,
" Cannot create winbindd privileged pipe directory " ) ;
return ;
}
2005-09-22 22:35:08 +04:00
service = talloc_zero ( task , struct wbsrv_service ) ;
if ( ! service ) goto nomem ;
service - > task = task ;
2008-12-05 18:53:44 +03:00
status = wbsrv_setup_domains ( service ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
task_server_terminate ( task , nt_errstr ( status ) ) ;
2005-10-09 16:50:35 +04:00
return ;
}
2008-04-17 14:23:44 +04:00
service - > idmap_ctx = idmap_init ( service , task - > event_ctx , task - > lp_ctx ) ;
2008-02-18 16:33:58 +03:00
if ( service - > idmap_ctx = = NULL ) {
task_server_terminate ( task , " Failed to load idmap database " ) ;
return ;
}
2005-09-22 22:35:08 +04:00
/* setup the unprivileged samba3 socket */
listen_socket = talloc ( service , struct wbsrv_listen_socket ) ;
if ( ! listen_socket ) goto nomem ;
2006-01-31 03:48:57 +03:00
listen_socket - > socket_path = talloc_asprintf ( listen_socket , " %s/%s " ,
2007-12-02 21:27:49 +03:00
lp_winbindd_socket_directory ( task - > lp_ctx ) ,
2006-01-31 03:48:57 +03:00
WINBINDD_SAMBA3_SOCKET ) ;
2005-09-22 22:35:08 +04:00
if ( ! listen_socket - > socket_path ) goto nomem ;
listen_socket - > service = service ;
2007-10-02 02:13:02 +04:00
listen_socket - > privileged = false ;
2008-01-06 04:03:43 +03:00
status = stream_setup_socket ( task - > event_ctx , task - > lp_ctx , model_ops ,
2005-09-22 22:35:08 +04:00
& wbsrv_ops , " unix " ,
2005-10-09 12:32:06 +04:00
listen_socket - > socket_path , & port ,
2007-12-06 18:54:34 +03:00
lp_socket_options ( task - > lp_ctx ) ,
2005-10-09 12:32:06 +04:00
listen_socket ) ;
2005-09-22 22:35:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto listen_failed ;
/* setup the privileged samba3 socket */
listen_socket = talloc ( service , struct wbsrv_listen_socket ) ;
if ( ! listen_socket ) goto nomem ;
2008-09-10 08:08:40 +04:00
listen_socket - > socket_path
= service - > priv_socket_path
= talloc_asprintf ( listen_socket , " %s/%s " ,
2008-06-28 16:02:19 +04:00
lp_winbindd_privileged_socket_directory ( task - > lp_ctx ) ,
WINBINDD_SAMBA3_SOCKET ) ;
if ( ! listen_socket - > socket_path ) goto nomem ;
2005-09-22 22:35:08 +04:00
if ( ! listen_socket - > socket_path ) goto nomem ;
listen_socket - > service = service ;
2007-10-02 02:13:02 +04:00
listen_socket - > privileged = true ;
2008-01-06 04:03:43 +03:00
status = stream_setup_socket ( task - > event_ctx , task - > lp_ctx , model_ops ,
2005-09-22 22:35:08 +04:00
& wbsrv_ops , " unix " ,
2005-10-09 12:32:06 +04:00
listen_socket - > socket_path , & port ,
2007-12-06 18:54:34 +03:00
lp_socket_options ( task - > lp_ctx ) ,
2005-10-09 12:32:06 +04:00
listen_socket ) ;
2005-09-22 22:35:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto listen_failed ;
2006-07-31 19:38:18 +04:00
status = wbsrv_init_irpc ( service ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto irpc_failed ;
2005-09-22 22:35:08 +04:00
return ;
listen_failed :
DEBUG ( 0 , ( " stream_setup_socket(path=%s) failed - %s \n " ,
listen_socket - > socket_path , nt_errstr ( status ) ) ) ;
task_server_terminate ( task , nt_errstr ( status ) ) ;
return ;
2006-07-31 19:38:18 +04:00
irpc_failed :
DEBUG ( 0 , ( " wbsrv_init_irpc() failed - %s \n " ,
nt_errstr ( status ) ) ) ;
task_server_terminate ( task , nt_errstr ( status ) ) ;
return ;
2005-09-22 22:35:08 +04:00
nomem :
task_server_terminate ( task , nt_errstr ( NT_STATUS_NO_MEMORY ) ) ;
return ;
2005-01-14 05:01:19 +03:00
}
2005-01-30 05:55:30 +03:00
/*
register ourselves as a available server
*/
2005-01-14 05:01:19 +03:00
NTSTATUS server_service_winbind_init ( void )
{
2008-02-04 13:58:29 +03:00
return register_server_service ( " winbind " , winbind_task_init ) ;
2005-01-14 05:01:19 +03:00
}