2008-05-17 03:52:47 +04:00
/*
Unix SMB / CIFS implementation .
helper functions for NAMED PIPE servers
Copyright ( C ) Stefan ( metze ) Metzmacher 2008
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2009-01-03 17:24:31 +03:00
# include <tevent.h>
2008-05-17 03:52:47 +04:00
# include "smbd/service.h"
# include "param/param.h"
2010-04-13 06:00:06 +04:00
# include "auth/auth.h"
2008-05-17 03:52:47 +04:00
# include "auth/session.h"
2009-01-21 12:43:15 +03:00
# include "auth/auth_sam_reply.h"
2010-02-04 19:03:04 +03:00
# include "lib/socket/socket.h"
# include "lib/tsocket/tsocket.h"
# include "libcli/util/tstream.h"
2008-05-17 03:52:47 +04:00
# include "librpc/gen_ndr/ndr_named_pipe_auth.h"
# include "system/passwd.h"
2010-02-04 19:03:04 +03:00
# include "system/network.h"
2009-04-21 06:55:42 +04:00
# include "libcli/raw/smb.h"
2011-02-09 06:22:16 +03:00
# include "auth/session.h"
2010-09-20 11:42:13 +04:00
# include "libcli/security/security.h"
2010-05-21 20:29:22 +04:00
# include "libcli/named_pipe_auth/npa_tstream.h"
2008-05-17 03:52:47 +04:00
struct named_pipe_socket {
const char * pipe_name ;
const char * pipe_path ;
const struct stream_server_ops * ops ;
void * private_data ;
} ;
2010-05-21 20:29:22 +04:00
static void named_pipe_accept_done ( struct tevent_req * subreq ) ;
2009-09-17 20:41:00 +04:00
2010-02-04 19:03:04 +03:00
static void named_pipe_accept ( struct stream_connection * conn )
{
2010-05-21 20:29:22 +04:00
struct tstream_context * plain_tstream ;
int fd ;
2010-02-04 19:03:04 +03:00
struct tevent_req * subreq ;
2010-05-21 20:29:22 +04:00
int ret ;
2010-02-04 19:03:04 +03:00
2010-05-21 20:29:22 +04:00
/* Let tstream take over fd operations */
2008-05-17 03:52:47 +04:00
2010-05-21 20:29:22 +04:00
fd = socket_get_fd ( conn - > socket ) ;
socket_set_flags ( conn - > socket , SOCKET_FLAG_NOCLOSE ) ;
2010-02-04 19:03:04 +03:00
TALLOC_FREE ( conn - > event . fde ) ;
2010-05-21 20:29:22 +04:00
TALLOC_FREE ( conn - > socket ) ;
2010-02-04 19:03:04 +03:00
2010-05-21 20:29:22 +04:00
ret = tstream_bsd_existing_socket ( conn , fd , & plain_tstream ) ;
if ( ret ! = 0 ) {
2010-02-04 19:03:04 +03:00
stream_terminate_connection ( conn ,
" named_pipe_accept: out of memory " ) ;
return ;
}
2010-02-04 19:03:04 +03:00
2010-05-21 20:29:22 +04:00
subreq = tstream_npa_accept_existing_send ( conn , conn - > event . ctx ,
plain_tstream ,
FILE_TYPE_MESSAGE_MODE_PIPE ,
0xff | 0x0400 | 0x0100 ,
4096 ) ;
2010-02-04 19:03:04 +03:00
if ( subreq = = NULL ) {
2010-05-21 20:29:22 +04:00
stream_terminate_connection ( conn ,
" named_pipe_accept: "
" no memory for tstream_npa_accept_existing_send " ) ;
2010-02-04 19:03:04 +03:00
return ;
}
2010-05-21 20:29:22 +04:00
tevent_req_set_callback ( subreq , named_pipe_accept_done , conn ) ;
2010-02-25 00:35:35 +03:00
}
2010-02-04 19:03:04 +03:00
2010-05-21 20:29:22 +04:00
static void named_pipe_accept_done ( struct tevent_req * subreq )
2008-05-17 03:52:47 +04:00
{
2010-05-21 20:29:22 +04:00
struct stream_connection * conn = tevent_req_callback_data ( subreq ,
struct stream_connection ) ;
struct named_pipe_socket * pipe_sock =
talloc_get_type ( conn - > private_data ,
struct named_pipe_socket ) ;
2017-03-10 01:38:56 +03:00
struct tsocket_address * remote_client_addr ;
char * remote_client_name ;
struct tsocket_address * local_server_addr ;
char * local_server_name ;
2011-02-09 06:22:16 +03:00
struct auth_session_info_transport * session_info_transport ;
2010-05-21 20:29:22 +04:00
const char * reason = NULL ;
TALLOC_CTX * tmp_ctx ;
int error ;
2010-04-26 15:56:06 +04:00
int ret ;
2008-05-17 03:52:47 +04:00
2010-05-21 20:29:22 +04:00
tmp_ctx = talloc_new ( conn ) ;
if ( ! tmp_ctx ) {
reason = " Out of memory! \n " ;
goto out ;
2010-02-04 19:03:04 +03:00
}
2010-05-21 20:29:22 +04:00
ret = tstream_npa_accept_existing_recv ( subreq , & error , tmp_ctx ,
2011-02-09 06:22:16 +03:00
& conn - > tstream ,
2017-03-10 01:38:56 +03:00
& remote_client_addr ,
& remote_client_name ,
& local_server_addr ,
& local_server_name ,
2011-02-09 06:22:16 +03:00
& session_info_transport ) ;
2010-02-04 19:03:04 +03:00
TALLOC_FREE ( subreq ) ;
2010-05-21 20:29:22 +04:00
if ( ret ! = 0 ) {
reason = talloc_asprintf ( conn ,
" tstream_npa_accept_existing_recv() "
" failed: %s " , strerror ( error ) ) ;
goto out ;
2008-05-17 03:52:47 +04:00
}
2017-03-10 01:38:56 +03:00
conn - > local_address = talloc_move ( conn , & local_server_addr ) ;
conn - > remote_address = talloc_move ( conn , & remote_client_addr ) ;
2017-02-20 02:01:37 +03:00
2017-09-11 02:39:39 +03:00
DBG_DEBUG ( " Accepted npa connection from %s. "
" Client: %s (%s). Server: %s (%s) \n " ,
tsocket_address_string ( conn - > remote_address , tmp_ctx ) ,
local_server_name ,
tsocket_address_string ( local_server_addr , tmp_ctx ) ,
remote_client_name ,
tsocket_address_string ( remote_client_addr , tmp_ctx ) ) ;
2010-05-21 20:29:22 +04:00
2011-02-09 06:22:16 +03:00
conn - > session_info = auth_session_info_from_transport ( conn , session_info_transport ,
conn - > lp_ctx ,
& reason ) ;
if ( ! conn - > session_info ) {
goto out ;
2010-02-04 19:03:04 +03:00
}
/*
* hand over to the real pipe implementation ,
* now that we have setup the transport session_info
*/
2010-05-21 20:29:22 +04:00
conn - > ops = pipe_sock - > ops ;
conn - > private_data = pipe_sock - > private_data ;
2010-02-04 19:03:04 +03:00
conn - > ops - > accept_connection ( conn ) ;
2017-09-11 02:39:39 +03:00
DBG_DEBUG ( " named pipe connection [%s] established \n " , conn - > ops - > name ) ;
2010-02-04 19:03:04 +03:00
2010-05-21 20:29:22 +04:00
talloc_free ( tmp_ctx ) ;
return ;
out :
talloc_free ( tmp_ctx ) ;
if ( ! reason ) {
reason = " Internal error " ;
}
stream_terminate_connection ( conn , reason ) ;
2008-05-17 03:52:47 +04:00
}
/*
2010-02-04 19:03:04 +03:00
called when a pipe socket becomes readable
2008-05-17 03:52:47 +04:00
*/
2010-02-04 19:03:04 +03:00
static void named_pipe_recv ( struct stream_connection * conn , uint16_t flags )
2008-05-17 03:52:47 +04:00
{
2010-05-21 20:29:22 +04:00
stream_terminate_connection ( conn , " named_pipe_recv: called " ) ;
2010-02-25 00:35:35 +03:00
}
/*
2010-02-04 19:03:04 +03:00
called when a pipe socket becomes writable
2010-02-25 00:35:35 +03:00
*/
2010-02-04 19:03:04 +03:00
static void named_pipe_send ( struct stream_connection * conn , uint16_t flags )
2010-02-25 00:35:35 +03:00
{
2010-05-21 20:29:22 +04:00
stream_terminate_connection ( conn , " named_pipe_send: called " ) ;
2008-05-17 03:52:47 +04:00
}
static const struct stream_server_ops named_pipe_stream_ops = {
. name = " named_pipe " ,
. accept_connection = named_pipe_accept ,
. recv_handler = named_pipe_recv ,
. send_handler = named_pipe_send ,
} ;
2010-11-15 02:12:22 +03:00
NTSTATUS tstream_setup_named_pipe ( TALLOC_CTX * mem_ctx ,
struct tevent_context * event_context ,
2010-05-21 20:29:22 +04:00
struct loadparm_context * lp_ctx ,
const struct model_ops * model_ops ,
const struct stream_server_ops * stream_ops ,
const char * pipe_name ,
2017-09-14 22:09:23 +03:00
void * private_data ,
void * process_context )
2008-05-17 03:52:47 +04:00
{
char * dirname ;
struct named_pipe_socket * pipe_sock ;
NTSTATUS status = NT_STATUS_NO_MEMORY ; ;
2010-11-15 02:12:22 +03:00
pipe_sock = talloc ( mem_ctx , struct named_pipe_socket ) ;
2008-05-17 03:52:47 +04:00
if ( pipe_sock = = NULL ) {
goto fail ;
}
/* remember the details about the pipe */
2015-06-29 13:28:03 +03:00
pipe_sock - > pipe_name = strlower_talloc ( pipe_sock , pipe_name ) ;
2008-05-17 03:52:47 +04:00
if ( pipe_sock - > pipe_name = = NULL ) {
goto fail ;
2011-05-08 12:29:27 +04:00
}
2014-07-27 21:18:09 +04:00
if ( ! directory_create_or_exist ( lpcfg_ncalrpc_dir ( lp_ctx ) , 0755 ) ) {
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
2017-09-11 02:39:39 +03:00
DBG_ERR ( " Failed to create ncalrpc pipe directory '%s' - %s \n " ,
lpcfg_ncalrpc_dir ( lp_ctx ) , nt_errstr ( status ) ) ;
2011-05-08 12:29:27 +04:00
goto fail ;
2008-05-17 03:52:47 +04:00
}
2010-07-16 08:32:42 +04:00
dirname = talloc_asprintf ( pipe_sock , " %s/np " , lpcfg_ncalrpc_dir ( lp_ctx ) ) ;
2008-05-17 03:52:47 +04:00
if ( dirname = = NULL ) {
goto fail ;
}
2013-01-08 17:21:23 +04:00
if ( ! directory_create_or_exist_strict ( dirname , geteuid ( ) , 0700 ) ) {
2011-06-20 08:55:32 +04:00
status = map_nt_error_from_unix_common ( errno ) ;
2017-09-11 02:39:39 +03:00
DBG_ERR ( " Failed to create stream pipe directory '%s' - %s \n " ,
dirname , nt_errstr ( status ) ) ;
2008-05-17 03:52:47 +04:00
goto fail ;
}
if ( strncmp ( pipe_name , " \\ pipe \\ " , 6 ) = = 0 ) {
pipe_name + = 6 ;
}
pipe_sock - > pipe_path = talloc_asprintf ( pipe_sock , " %s/%s " , dirname ,
pipe_name ) ;
if ( pipe_sock - > pipe_path = = NULL ) {
goto fail ;
}
talloc_free ( dirname ) ;
2010-05-21 20:29:22 +04:00
pipe_sock - > ops = stream_ops ;
pipe_sock - > private_data = private_data ;
2008-05-17 03:52:47 +04:00
2010-11-15 02:12:22 +03:00
status = stream_setup_socket ( pipe_sock ,
event_context ,
2008-05-17 03:52:47 +04:00
lp_ctx ,
model_ops ,
& named_pipe_stream_ops ,
" unix " ,
pipe_sock - > pipe_path ,
NULL ,
NULL ,
2017-09-14 22:09:23 +03:00
pipe_sock ,
process_context ) ;
2008-05-17 03:52:47 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
return NT_STATUS_OK ;
fail :
talloc_free ( pipe_sock ) ;
return status ;
}