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-06-24 02:30:26 +04:00
# include "system/dir.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.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-01-14 05:01:19 +03:00
# define WINBINDD_DIR " / tmp / .winbindd / "
# define WINBINDD_ECHO_SOCKET WINBINDD_DIR"echo"
# define WINBINDD_ADDR_PREFIX "127.0.255."
# define WINBINDD_ECHO_ADDR WINBINDD_ADDR_PREFIX"1"
# define WINBINDD_ECHO_PORT 55555
2005-01-30 05:55:30 +03:00
/*
state of an open winbind connection
*/
struct wbserver_connection {
2005-09-08 15:26:05 +04:00
DATA_BLOB input ;
struct data_blob_list_item * send_queue ;
2005-01-30 05:55:30 +03:00
} ;
2005-01-14 05:01:19 +03:00
2005-01-30 05:55:30 +03:00
/*
called when we get a new connection
*/
static void winbind_accept ( struct stream_connection * conn )
2005-01-14 05:01:19 +03:00
{
2005-01-30 05:55:30 +03:00
struct wbserver_connection * wbconn ;
2005-01-14 05:01:19 +03:00
2005-01-30 05:55:30 +03:00
wbconn = talloc_zero ( conn , struct wbserver_connection ) ;
2005-09-08 15:26:05 +04:00
wbconn - > input = data_blob_talloc ( wbconn , NULL , 1024 ) ;
2005-01-30 05:55:30 +03:00
conn - > private = wbconn ;
}
2005-01-14 05:01:19 +03:00
2005-01-30 05:55:30 +03:00
/*
receive some data on a winbind connection
*/
2005-02-03 14:25:52 +03:00
static void winbind_recv ( struct stream_connection * conn , uint16_t flags )
2005-01-30 05:55:30 +03:00
{
struct wbserver_connection * wbconn = talloc_get_type ( conn - > private , struct wbserver_connection ) ;
2005-01-14 05:01:19 +03:00
NTSTATUS status ;
size_t nread ;
2005-09-08 15:26:05 +04:00
struct data_blob_list_item * q ;
2005-01-14 05:01:19 +03:00
2005-09-08 15:26:05 +04:00
status = socket_recv ( conn - > socket , wbconn - > input . data , wbconn - > input . length , & nread , 0 ) ;
2005-01-14 05:01:19 +03:00
if ( NT_STATUS_IS_ERR ( status ) ) {
DEBUG ( 10 , ( " socket_recv: %s \n " , nt_errstr ( status ) ) ) ;
2005-01-30 05:55:30 +03:00
stream_terminate_connection ( conn , " socket_recv: failed \n " ) ;
2005-01-14 05:01:19 +03:00
return ;
}
2005-01-30 05:55:30 +03:00
/* just reflect the data back down the socket */
2005-09-08 15:26:05 +04:00
q = talloc ( wbconn , struct data_blob_list_item ) ;
2005-01-30 05:55:30 +03:00
if ( q = = NULL ) {
stream_terminate_connection ( conn , " winbind_recv: out of memory \n " ) ;
2005-01-14 05:01:19 +03:00
return ;
}
2005-09-08 15:26:05 +04:00
q - > blob = data_blob_talloc ( q , wbconn - > input . data , nread ) ;
2005-01-30 05:55:30 +03:00
if ( q - > blob . data = = NULL ) {
stream_terminate_connection ( conn , " winbind_recv: out of memory \n " ) ;
2005-01-14 05:01:19 +03:00
return ;
}
2005-09-08 15:26:05 +04:00
DLIST_ADD_END ( wbconn - > send_queue , q , struct data_blob_list_item * ) ;
2005-01-14 05:01:19 +03:00
2005-02-03 05:35:52 +03:00
EVENT_FD_WRITEABLE ( conn - > event . fde ) ;
2005-01-14 05:01:19 +03:00
}
2005-01-30 05:55:30 +03:00
/*
called when we can write to a connection
*/
2005-02-03 14:25:52 +03:00
static void winbind_send ( struct stream_connection * conn , uint16_t flags )
2005-01-14 05:01:19 +03:00
{
2005-01-30 05:55:30 +03:00
struct wbserver_connection * wbconn = talloc_get_type ( conn - > private , struct wbserver_connection ) ;
2005-09-08 15:26:05 +04:00
while ( wbconn - > send_queue ) {
struct data_blob_list_item * q = wbconn - > send_queue ;
2005-01-30 05:55:30 +03:00
NTSTATUS status ;
size_t sendlen ;
status = socket_send ( conn - > socket , & q - > blob , & sendlen , 0 ) ;
if ( NT_STATUS_IS_ERR ( status ) ) {
DEBUG ( 10 , ( " socket_send() %s \n " , nt_errstr ( status ) ) ) ;
stream_terminate_connection ( conn , " socket_send: failed \n " ) ;
return ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return ;
}
q - > blob . length - = sendlen ;
q - > blob . data + = sendlen ;
if ( q - > blob . length = = 0 ) {
2005-09-08 15:26:05 +04:00
DLIST_REMOVE ( wbconn - > send_queue , q ) ;
2005-01-30 05:55:30 +03:00
talloc_free ( q ) ;
}
2005-01-14 05:01:19 +03:00
}
2005-02-03 05:35:52 +03:00
EVENT_FD_NOT_WRITEABLE ( conn - > event . fde ) ;
2005-01-14 05:01:19 +03:00
}
2005-01-30 05:55:30 +03:00
static const struct stream_server_ops winbind_stream_ops = {
2005-01-31 10:24:00 +03:00
. name = " winbind_echo " ,
2005-01-14 05:01:19 +03:00
. accept_connection = winbind_accept ,
. recv_handler = winbind_recv ,
. send_handler = winbind_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-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-06-26 03:53:14 +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
/* Make sure the directory for NCALRPC exists */
2005-02-10 09:36:30 +03:00
if ( ! directory_exist ( WINBINDD_DIR ) ) {
2005-01-14 05:01:19 +03:00
mkdir ( WINBINDD_DIR , 0755 ) ;
}
2005-01-30 05:55:30 +03:00
status = stream_setup_socket ( task - > event_ctx , model_ops , & winbind_stream_ops ,
" unix " , WINBINDD_ECHO_SOCKET , & port , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " service_setup_stream_socket(path=%s) failed - %s \n " ,
WINBINDD_ECHO_SOCKET , nt_errstr ( status ) ) ) ;
2005-06-26 03:53:14 +04:00
task_server_terminate ( task , " winbind Failed to find to ECHO unix socket " ) ;
2005-01-14 05:01:19 +03:00
return ;
}
port = WINBINDD_ECHO_PORT ;
2005-01-30 05:55:30 +03:00
status = stream_setup_socket ( task - > event_ctx , model_ops , & winbind_stream_ops ,
" ipv4 " , WINBINDD_ECHO_ADDR , & port , NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " service_setup_stream_socket(address=%s,port=%u) failed - %s \n " ,
WINBINDD_ECHO_ADDR , port , nt_errstr ( status ) ) ) ;
2005-06-26 03:53:14 +04:00
task_server_terminate ( task , " winbind Failed to find to ECHO tcp socket " ) ;
2005-01-14 05:01:19 +03:00
return ;
}
}
2005-01-30 05:55:30 +03:00
/*
initialise the winbind server
*/
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
}