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
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-10 09:59:29 +03:00
# include "lib/socket/socket.h"
2005-01-30 05:55:30 +03:00
# include "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"
# 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"
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
*/
2006-01-12 12:38:35 +03:00
static void wbsrv_recv_error ( void * private , NTSTATUS status )
{
struct wbsrv_connection * wbconn = talloc_get_type ( private , struct wbsrv_connection ) ;
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
{
2006-01-12 12:38:35 +03:00
struct wbsrv_listen_socket * listen_socket = talloc_get_type ( conn - > private ,
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 ;
conn - > private = 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
{
2006-01-12 12:38:35 +03:00
struct wbsrv_connection * wbconn = talloc_get_type ( conn - > private ,
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
{
2006-01-12 12:38:35 +03:00
struct wbsrv_connection * wbconn = talloc_get_type ( conn - > private ,
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
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 . */
model_ops = process_model_byname ( " single " ) ;
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 */
if ( ! directory_create_or_exist ( lp_winbindd_socket_directory ( ) , geteuid ( ) , 0755 ) ) {
task_server_terminate ( task ,
" Cannot create winbindd pipe directory " ) ;
return ;
2005-01-14 05:01:19 +03:00
}
2005-09-22 22:35:08 +04:00
service = talloc_zero ( task , struct wbsrv_service ) ;
if ( ! service ) goto nomem ;
service - > task = task ;
2005-11-06 02:46:57 +03:00
service - > primary_sid = secrets_get_domain_sid ( service ,
lp_workgroup ( ) ) ;
if ( service - > primary_sid = = NULL ) {
task_server_terminate (
task , nt_errstr ( NT_STATUS_CANT_ACCESS_DOMAIN_INFO ) ) ;
2005-10-09 16:50:35 +04:00
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 " ,
lp_winbindd_socket_directory ( ) ,
WINBINDD_SAMBA3_SOCKET ) ;
2005-09-22 22:35:08 +04:00
if ( ! listen_socket - > socket_path ) goto nomem ;
listen_socket - > service = service ;
listen_socket - > privileged = False ;
2005-09-21 00:54:25 +04:00
status = stream_setup_socket ( task - > event_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 ,
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 ;
2005-10-09 12:32:06 +04:00
listen_socket - > socket_path =
smbd_tmp_path ( listen_socket ,
WINBINDD_SAMBA3_PRIVILEGED_SOCKET ) ;
2005-09-22 22:35:08 +04:00
if ( ! listen_socket - > socket_path ) goto nomem ;
listen_socket - > service = service ;
listen_socket - > privileged = True ;
status = stream_setup_socket ( task - > event_ctx , model_ops ,
& wbsrv_ops , " unix " ,
2005-10-09 12:32:06 +04:00
listen_socket - > socket_path , & port ,
listen_socket ) ;
2005-09-22 22:35:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto listen_failed ;
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 ;
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
/*
initialise the winbind server
*/
2005-10-09 12:32:06 +04:00
static NTSTATUS winbind_init ( struct event_context * event_ctx ,
const struct model_ops * model_ops )
2005-01-14 05:01:19 +03:00
{
2005-01-30 05:55:30 +03:00
return task_server_startup ( event_ctx , model_ops , winbind_task_init ) ;
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 )
{
2005-01-30 05:55:30 +03:00
return register_server_service ( " winbind " , winbind_init ) ;
2005-01-14 05:01:19 +03:00
}