2007-10-02 23:50:53 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-11-09 19:40:38 +03:00
Samba utility functions
Copyright ( C ) Andrew Tridgell 1992 - 1998
2002-01-13 14:13:54 +03:00
Copyright ( C ) Tim Potter 2000 - 2001
2007-10-04 00:43:55 +04:00
Copyright ( C ) Jeremy Allison 1992 - 2007
2007-10-02 23:50:53 +04:00
1998-11-09 19:40:38 +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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-11-09 19:40:38 +03:00
( at your option ) any later version .
2007-10-02 23:50:53 +04:00
1998-11-09 19:40:38 +03:00
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 .
2007-10-02 23:50:53 +04:00
1998-11-09 19:40:38 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-11-09 19:40:38 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2014-07-17 14:58:34 +04:00
# include "../lib/util/memcache.h"
2010-08-26 11:58:09 +04:00
# include "../lib/async_req/async_sock.h"
2010-10-01 12:08:15 +04:00
# include "../lib/util/select.h"
2011-05-02 06:20:21 +04:00
# include "lib/socket/interfaces.h"
2011-04-28 19:38:09 +04:00
# include "../lib/util/tevent_unix.h"
# include "../lib/util/tevent_ntstatus.h"
2011-06-08 16:50:20 +04:00
# include "../lib/tsocket/tsocket.h"
2015-10-12 16:57:34 +03:00
# include "lib/util/sys_rw.h"
# include "lib/util/sys_rw_data.h"
2022-10-21 17:45:35 +03:00
# include "source3/lib/util_tsock.h"
1998-11-09 19:40:38 +03:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Determine if a file descriptor is in fact a socket .
1998-11-09 19:40:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-10-11 05:25:16 +04:00
bool is_a_socket ( int fd )
1998-11-09 19:40:38 +03:00
{
2004-05-05 07:03:38 +04:00
int v ;
socklen_t l ;
2002-07-15 14:35:28 +04:00
l = sizeof ( int ) ;
return ( getsockopt ( fd , SOL_SOCKET , SO_TYPE , ( char * ) & v , & l ) = = 0 ) ;
1998-11-09 19:40:38 +03:00
}
/****************************************************************************
2009-09-07 08:38:50 +04:00
Read data from a file descriptor with a timout in msec .
1999-12-13 16:27:58 +03:00
mincount = if timeout , minimum to read before returning
maxcount = number to be read .
time_out = timeout in milliseconds
2009-09-07 08:38:50 +04:00
NB . This can be called with a non - socket fd , don ' t change
sys_read ( ) to sys_recv ( ) or other socket call .
1998-11-09 19:40:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-09-07 08:38:50 +04:00
NTSTATUS read_fd_with_timeout ( int fd , char * buf ,
2008-01-26 01:43:50 +03:00
size_t mincnt , size_t maxcnt ,
unsigned int time_out ,
size_t * size_ret )
1998-11-09 19:40:38 +03:00
{
2011-02-08 19:57:12 +03:00
int pollrtn ;
2002-01-13 15:33:42 +03:00
ssize_t readret ;
size_t nread = 0 ;
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
/* just checking .... */
if ( maxcnt < = 0 )
2008-01-24 21:17:14 +03:00
return NT_STATUS_OK ;
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
/* Blocking read */
2005-06-14 02:26:08 +04:00
if ( time_out = = 0 ) {
if ( mincnt = = 0 ) {
mincnt = maxcnt ;
}
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
while ( nread < mincnt ) {
2009-09-07 08:38:50 +04:00
readret = sys_read ( fd , buf + nread , maxcnt - nread ) ;
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
if ( readret = = 0 ) {
2009-09-07 08:38:50 +04:00
DEBUG ( 5 , ( " read_fd_with_timeout: "
2007-10-02 23:50:53 +04:00
" blocking read. EOF from client. \n " ) ) ;
2008-01-24 21:17:14 +03:00
return NT_STATUS_END_OF_FILE ;
2002-01-13 15:33:42 +03:00
}
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
if ( readret = = - 1 ) {
2010-08-18 13:17:52 +04:00
return map_nt_error_from_unix ( errno ) ;
2002-01-13 15:33:42 +03:00
}
nread + = readret ;
}
2008-01-24 21:17:14 +03:00
goto done ;
2002-01-13 15:33:42 +03:00
}
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
/* Most difficult - timeout read */
2007-10-02 23:50:53 +04:00
/* If this is ever called on a disk file and
2002-01-13 15:33:42 +03:00
mincnt is greater then the filesize then
2007-10-02 23:50:53 +04:00
system performance will suffer severely as
2002-01-13 15:33:42 +03:00
select always returns true on disk files */
2007-10-02 23:50:53 +04:00
for ( nread = 0 ; nread < mincnt ; ) {
2011-02-08 19:57:12 +03:00
int revents ;
2007-10-02 23:50:53 +04:00
2011-02-08 19:57:12 +03:00
pollrtn = poll_intr_one_fd ( fd , POLLIN | POLLHUP , time_out ,
& revents ) ;
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
/* Check if error */
2011-02-08 19:57:12 +03:00
if ( pollrtn = = - 1 ) {
2010-08-18 13:17:52 +04:00
return map_nt_error_from_unix ( errno ) ;
2002-01-13 15:33:42 +03:00
}
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
/* Did we timeout ? */
2011-02-08 19:57:12 +03:00
if ( ( pollrtn = = 0 ) | |
( ( revents & ( POLLIN | POLLHUP | POLLERR ) ) = = 0 ) ) {
2009-09-07 08:38:50 +04:00
DEBUG ( 10 , ( " read_fd_with_timeout: timeout read. "
2007-10-02 23:50:53 +04:00
" select timed out. \n " ) ) ;
2008-01-24 21:17:14 +03:00
return NT_STATUS_IO_TIMEOUT ;
2002-01-13 15:33:42 +03:00
}
2007-10-02 23:50:53 +04:00
2009-09-07 08:38:50 +04:00
readret = sys_read ( fd , buf + nread , maxcnt - nread ) ;
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
if ( readret = = 0 ) {
/* we got EOF on the file descriptor */
2009-09-07 08:38:50 +04:00
DEBUG ( 5 , ( " read_fd_with_timeout: timeout read. "
2007-10-02 23:50:53 +04:00
" EOF from client. \n " ) ) ;
2008-01-24 21:17:14 +03:00
return NT_STATUS_END_OF_FILE ;
2002-01-13 15:33:42 +03:00
}
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
if ( readret = = - 1 ) {
2008-01-24 21:17:14 +03:00
return map_nt_error_from_unix ( errno ) ;
2002-01-13 15:33:42 +03:00
}
2007-10-02 23:50:53 +04:00
2002-01-13 15:33:42 +03:00
nread + = readret ;
}
2007-10-02 23:50:53 +04:00
2008-01-24 21:17:14 +03:00
done :
2002-01-13 15:33:42 +03:00
/* Return the number we got */
2008-01-24 21:17:14 +03:00
if ( size_ret ) {
* size_ret = nread ;
}
return NT_STATUS_OK ;
}
2008-01-26 01:41:48 +03:00
/****************************************************************************
2009-09-07 08:38:50 +04:00
Read data from an fd , reading exactly N bytes .
NB . This can be called with a non - socket fd , don ' t add dependencies
on socket calls .
2008-01-26 01:41:48 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-11-19 17:06:49 +03:00
NTSTATUS read_data_ntstatus ( int fd , char * buffer , size_t N )
2008-01-24 21:17:14 +03:00
{
2010-08-15 17:30:21 +04:00
return read_fd_with_timeout ( fd , buffer , N , N , 0 , NULL ) ;
1998-11-09 19:40:38 +03:00
}
/****************************************************************************
2003-07-17 01:06:21 +04:00
Read 4 bytes of a smb packet and return the smb length of the packet .
Store the result in the buffer .
This version of the function will return a length of zero on receiving
a keepalive packet .
Timeout is in milliseconds .
1998-11-09 19:40:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-25 23:24:48 +03:00
NTSTATUS read_smb_length_return_keepalive ( int fd , char * inbuf ,
unsigned int timeout ,
size_t * len )
1998-11-09 19:40:38 +03:00
{
2002-07-15 14:35:28 +04:00
int msg_type ;
2008-01-25 23:02:52 +03:00
NTSTATUS status ;
2009-09-07 08:38:50 +04:00
status = read_fd_with_timeout ( fd , inbuf , 4 , 4 , timeout , NULL ) ;
2008-01-25 23:02:52 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-25 23:24:48 +03:00
return status ;
2008-01-25 11:21:44 +03:00
}
1998-11-09 19:40:38 +03:00
2008-01-25 23:24:48 +03:00
* len = smb_len ( inbuf ) ;
2008-01-25 11:21:44 +03:00
msg_type = CVAL ( inbuf , 0 ) ;
1998-11-09 19:40:38 +03:00
2011-07-12 10:53:30 +04:00
if ( msg_type = = NBSSkeepalive ) {
2008-01-25 11:21:44 +03:00
DEBUG ( 5 , ( " Got keepalive packet \n " ) ) ;
2002-07-15 14:35:28 +04:00
}
1998-11-09 19:40:38 +03:00
2008-02-06 00:17:20 +03:00
DEBUG ( 10 , ( " got smb length of %lu \n " , ( unsigned long ) ( * len ) ) ) ;
1998-11-09 19:40:38 +03:00
2008-01-25 23:24:48 +03:00
return NT_STATUS_OK ;
1998-11-09 19:40:38 +03:00
}
/****************************************************************************
2008-05-28 20:31:42 +04:00
Read an smb from a fd .
2007-10-02 23:50:53 +04:00
The timeout is in milliseconds .
2003-07-17 01:06:21 +04:00
This function will return on receipt of a session keepalive packet .
2007-05-16 04:07:38 +04:00
maxlen is the max number of bytes to return , not including the 4 byte
2008-05-28 20:31:42 +04:00
length . If zero it means buflen limit .
2003-10-22 01:19:00 +04:00
Doesn ' t check the MAC on signed packets .
1998-11-09 19:40:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-05-28 20:31:42 +04:00
NTSTATUS receive_smb_raw ( int fd , char * buffer , size_t buflen , unsigned int timeout ,
2008-01-26 01:54:22 +03:00
size_t maxlen , size_t * p_len )
1998-11-09 19:40:38 +03:00
{
2008-01-25 23:24:48 +03:00
size_t len ;
NTSTATUS status ;
1998-11-09 19:40:38 +03:00
2008-01-25 23:24:48 +03:00
status = read_smb_length_return_keepalive ( fd , buffer , timeout , & len ) ;
2002-02-24 00:03:21 +03:00
2008-01-25 23:24:48 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-08-15 17:40:08 +04:00
DEBUG ( 0 , ( " read_fd_with_timeout failed, read "
" error = %s. \n " , nt_errstr ( status ) ) ) ;
2008-01-26 01:54:22 +03:00
return status ;
2001-05-24 23:28:22 +04:00
}
1998-11-09 19:40:38 +03:00
2008-05-28 20:31:42 +04:00
if ( len > buflen ) {
2007-10-02 23:50:53 +04:00
DEBUG ( 0 , ( " Invalid packet length! (%lu bytes). \n " ,
( unsigned long ) len ) ) ;
2008-05-28 20:31:42 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2001-05-24 23:28:22 +04:00
}
if ( len > 0 ) {
2007-05-16 04:07:38 +04:00
if ( maxlen ) {
len = MIN ( len , maxlen ) ;
}
2009-09-07 08:38:50 +04:00
status = read_fd_with_timeout (
2008-01-26 01:41:48 +03:00
fd , buffer + 4 , len , len , timeout , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-08-15 17:40:08 +04:00
DEBUG ( 0 , ( " read_fd_with_timeout failed, read error = "
" %s. \n " , nt_errstr ( status ) ) ) ;
2008-01-26 01:54:22 +03:00
return status ;
2001-05-24 23:28:22 +04:00
}
2007-10-02 23:50:53 +04:00
/* not all of samba3 properly checks for packet-termination
* of strings . This ensures that we don ' t run off into
* empty space . */
2005-05-27 21:47:24 +04:00
SSVAL ( buffer + 4 , len , 0 ) ;
2001-05-24 23:28:22 +04:00
}
2008-01-26 01:54:22 +03:00
* p_len = len ;
return NT_STATUS_OK ;
2003-10-22 01:19:00 +04:00
}
2021-02-12 23:27:19 +03:00
/*
* Open a socket of the specified type , port , and address for incoming data .
*
* Return sock or - errno
*/
int open_socket_in (
int type ,
const struct sockaddr_storage * paddr ,
uint16_t port ,
bool rebind )
2001-08-26 23:11:33 +04:00
{
2021-02-12 23:27:19 +03:00
struct samba_sockaddr addr = {
. sa_socklen = sizeof ( struct sockaddr_storage ) ,
. u . ss = * paddr ,
} ;
int ret , sock = - 1 ;
int val = rebind ? 1 : 0 ;
bool ok ;
2021-08-17 14:39:24 +03:00
switch ( addr . u . sa . sa_family ) {
case AF_INET6 :
addr . sa_socklen = sizeof ( struct sockaddr_in6 ) ;
break ;
case AF_INET :
addr . sa_socklen = sizeof ( struct sockaddr_in ) ;
break ;
}
2021-02-12 23:27:19 +03:00
ok = samba_sockaddr_set_port ( & addr , port ) ;
if ( ! ok ) {
ret = - EINVAL ;
DBG_DEBUG ( " samba_sockaddr_set_port failed \n " ) ;
goto fail ;
2007-10-25 01:16:54 +04:00
}
2021-02-12 23:27:19 +03:00
sock = socket ( addr . u . ss . ss_family , type , 0 ) ;
if ( sock = = - 1 ) {
ret = - errno ;
DBG_DEBUG ( " socket() failed: %s \n " , strerror ( errno ) ) ;
goto fail ;
2007-10-25 01:16:54 +04:00
}
2001-08-26 23:11:33 +04:00
2021-02-12 23:27:19 +03:00
ret = setsockopt (
sock , SOL_SOCKET , SO_REUSEADDR , ( char * ) & val , sizeof ( val ) ) ;
if ( ret = = - 1 ) {
ret = - errno ;
DBG_DEBUG ( " setsockopt(SO_REUSEADDR) failed: %s \n " ,
strerror ( errno ) ) ;
goto fail ;
2001-08-26 23:11:33 +04:00
}
2001-08-26 08:16:51 +04:00
2000-02-17 01:48:19 +03:00
# ifdef SO_REUSEPORT
2021-02-12 23:27:19 +03:00
ret = setsockopt (
sock , SOL_SOCKET , SO_REUSEPORT , ( char * ) & val , sizeof ( val ) ) ;
if ( ret = = - 1 ) {
ret = - errno ;
DBG_DEBUG ( " setsockopt(SO_REUSEPORT) failed: %s \n " ,
strerror ( errno ) ) ;
goto fail ;
2001-08-26 23:11:33 +04:00
}
2021-02-12 23:27:19 +03:00
# endif /* SO_REUSEPORT */
1998-11-09 19:40:38 +03:00
2011-04-23 13:29:51 +04:00
# ifdef HAVE_IPV6
/*
* As IPV6_V6ONLY is the default on some systems ,
* we better try to be consistent and always use it .
*
* This also avoids using IPv4 via AF_INET6 sockets
* and makes sure % I never resolves to a ' : : ffff : 192.168 .0 .1 '
* string .
*/
2021-02-12 23:27:19 +03:00
if ( addr . u . ss . ss_family = = AF_INET6 ) {
val = 1 ;
2011-04-23 13:29:51 +04:00
2021-02-12 23:27:19 +03:00
ret = setsockopt (
sock ,
IPPROTO_IPV6 ,
IPV6_V6ONLY ,
( const void * ) & val ,
sizeof ( val ) ) ;
2011-04-23 13:29:51 +04:00
if ( ret = = - 1 ) {
2021-02-12 23:27:19 +03:00
ret = - errno ;
DBG_DEBUG ( " setsockopt(IPV6_V6ONLY) failed: %s \n " ,
strerror ( errno ) ) ;
goto fail ;
2011-04-23 13:29:51 +04:00
}
}
# endif
2001-08-26 23:11:33 +04:00
/* now we've got a socket - we need to bind it */
2021-02-12 23:27:19 +03:00
ret = bind ( sock , & addr . u . sa , addr . sa_socklen ) ;
if ( ret = = - 1 ) {
char addrstr [ INET6_ADDRSTRLEN ] ;
ret = - errno ;
print_sockaddr ( addrstr , sizeof ( addrstr ) , & addr . u . ss ) ;
DBG_DEBUG ( " bind for %s port % " PRIu16 " failed: %s \n " ,
addrstr ,
port ,
strerror ( - ret ) ) ;
goto fail ;
2001-08-26 23:11:33 +04:00
}
1998-11-09 19:40:38 +03:00
2021-02-12 23:27:19 +03:00
DBG_DEBUG ( " bind succeeded on port % " PRIu16 " \n " , port ) ;
return sock ;
fail :
if ( sock ! = - 1 ) {
close ( sock ) ;
sock = - 1 ;
}
return ret ;
2001-08-26 23:11:33 +04:00
}
1998-11-09 19:40:38 +03:00
2009-01-03 21:50:05 +03:00
struct open_socket_out_state {
int fd ;
2013-02-18 13:00:26 +04:00
struct tevent_context * ev ;
2009-01-03 21:50:05 +03:00
struct sockaddr_storage ss ;
socklen_t salen ;
uint16_t port ;
2015-06-29 20:00:55 +03:00
struct tevent_req * connect_subreq ;
2009-01-03 21:50:05 +03:00
} ;
2009-02-22 21:49:18 +03:00
static void open_socket_out_connected ( struct tevent_req * subreq ) ;
2009-01-03 21:50:05 +03:00
2015-06-29 20:00:55 +03:00
static void open_socket_out_cleanup ( struct tevent_req * req ,
enum tevent_req_state req_state )
2009-01-03 21:50:05 +03:00
{
2015-06-29 20:00:55 +03:00
struct open_socket_out_state * state =
tevent_req_data ( req , struct open_socket_out_state ) ;
/*
* Make sure that the async_connect_send subreq has a chance to reset
* fcntl before the socket goes away .
*/
TALLOC_FREE ( state - > connect_subreq ) ;
if ( req_state = = TEVENT_REQ_DONE ) {
/*
* we keep the socket open for the caller to use
*/
return ;
}
if ( state - > fd ! = - 1 ) {
close ( state - > fd ) ;
state - > fd = - 1 ;
2009-01-03 21:50:05 +03:00
}
}
1998-11-09 19:40:38 +03:00
/****************************************************************************
2003-07-17 01:06:21 +04:00
Create an outgoing socket . timeout is in milliseconds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2009-02-26 14:34:39 +03:00
struct tevent_req * open_socket_out_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 13:00:26 +04:00
struct tevent_context * ev ,
2009-02-26 14:34:39 +03:00
const struct sockaddr_storage * pss ,
uint16_t port ,
int timeout )
1998-11-09 19:40:38 +03:00
{
2007-10-25 01:16:54 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
2020-02-26 15:21:15 +03:00
struct tevent_req * req ;
2009-01-03 21:50:05 +03:00
struct open_socket_out_state * state ;
NTSTATUS status ;
2020-02-26 15:21:15 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct open_socket_out_state ) ;
if ( req = = NULL ) {
2009-01-03 21:50:05 +03:00
return NULL ;
}
state - > ev = ev ;
state - > ss = * pss ;
state - > port = port ;
state - > salen = - 1 ;
state - > fd = socket ( state - > ss . ss_family , SOCK_STREAM , 0 ) ;
if ( state - > fd = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
2020-02-26 15:27:32 +03:00
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
2009-01-03 21:50:05 +03:00
}
2015-06-29 20:00:55 +03:00
2020-02-26 15:21:15 +03:00
tevent_req_set_cleanup_fn ( req , open_socket_out_cleanup ) ;
2009-01-03 21:50:05 +03:00
2018-11-27 12:15:39 +03:00
if ( ( timeout ! = 0 ) & &
! tevent_req_set_endtime (
2020-02-26 15:21:15 +03:00
req , ev , timeval_current_ofs_msec ( timeout ) ) ) {
2020-02-26 15:27:32 +03:00
tevent_req_oom ( req ) ;
return tevent_req_post ( req , ev ) ;
2003-07-17 01:06:21 +04:00
}
1998-11-09 19:40:38 +03:00
2007-10-25 01:16:54 +04:00
# if defined(HAVE_IPV6)
if ( pss - > ss_family = = AF_INET6 ) {
2009-01-03 21:50:05 +03:00
struct sockaddr_in6 * psa6 ;
psa6 = ( struct sockaddr_in6 * ) & state - > ss ;
2007-10-25 01:16:54 +04:00
psa6 - > sin6_port = htons ( port ) ;
2009-01-03 21:50:05 +03:00
if ( psa6 - > sin6_scope_id = = 0
& & IN6_IS_ADDR_LINKLOCAL ( & psa6 - > sin6_addr ) ) {
setup_linklocal_scope_id (
( struct sockaddr * ) & ( state - > ss ) ) ;
2007-10-26 05:28:36 +04:00
}
2009-01-03 21:50:05 +03:00
state - > salen = sizeof ( struct sockaddr_in6 ) ;
2007-10-25 01:16:54 +04:00
}
# endif
if ( pss - > ss_family = = AF_INET ) {
2009-01-03 21:50:05 +03:00
struct sockaddr_in * psa ;
psa = ( struct sockaddr_in * ) & state - > ss ;
2007-10-25 01:16:54 +04:00
psa - > sin_port = htons ( port ) ;
2009-01-03 21:50:05 +03:00
state - > salen = sizeof ( struct sockaddr_in ) ;
2007-10-25 01:16:54 +04:00
}
1998-11-09 19:40:38 +03:00
2009-06-06 02:47:53 +04:00
if ( pss - > ss_family = = AF_UNIX ) {
state - > salen = sizeof ( struct sockaddr_un ) ;
}
2009-01-03 21:50:05 +03:00
print_sockaddr ( addr , sizeof ( addr ) , & state - > ss ) ;
DEBUG ( 3 , ( " Connecting to %s at port %u \n " , addr , ( unsigned int ) port ) ) ;
2015-06-29 20:00:55 +03:00
state - > connect_subreq = async_connect_send (
state , state - > ev , state - > fd , ( struct sockaddr * ) & state - > ss ,
state - > salen , NULL , NULL , NULL ) ;
2020-02-26 15:27:32 +03:00
if ( tevent_req_nomem ( state - > connect_subreq , NULL ) ) {
return tevent_req_post ( req , ev ) ;
}
2015-06-29 20:00:55 +03:00
tevent_req_set_callback ( state - > connect_subreq ,
2020-02-26 15:21:15 +03:00
open_socket_out_connected , req ) ;
return req ;
2009-01-03 21:50:05 +03:00
}
2007-10-02 23:50:53 +04:00
2009-02-22 21:49:18 +03:00
static void open_socket_out_connected ( struct tevent_req * subreq )
2009-01-03 21:50:05 +03:00
{
2009-02-28 23:44:30 +03:00
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
struct open_socket_out_state * state =
tevent_req_data ( req , struct open_socket_out_state ) ;
2009-02-22 21:49:18 +03:00
int ret ;
2009-01-03 21:50:05 +03:00
int sys_errno ;
2003-07-17 01:06:21 +04:00
2009-02-22 21:49:18 +03:00
ret = async_connect_recv ( subreq , & sys_errno ) ;
2009-01-03 21:50:05 +03:00
TALLOC_FREE ( subreq ) ;
2015-06-29 20:00:55 +03:00
state - > connect_subreq = NULL ;
2009-02-22 21:49:18 +03:00
if ( ret = = 0 ) {
2009-02-26 14:34:39 +03:00
tevent_req_done ( req ) ;
2009-01-03 21:50:05 +03:00
return ;
}
2009-02-26 14:34:39 +03:00
tevent_req_nterror ( req , map_nt_error_from_unix ( sys_errno ) ) ;
2009-01-03 21:50:05 +03:00
}
2009-02-26 14:34:39 +03:00
NTSTATUS open_socket_out_recv ( struct tevent_req * req , int * pfd )
2009-01-03 21:50:05 +03:00
{
2009-02-28 23:44:30 +03:00
struct open_socket_out_state * state =
tevent_req_data ( req , struct open_socket_out_state ) ;
2009-02-26 14:34:39 +03:00
NTSTATUS status ;
2009-01-03 21:50:05 +03:00
2009-02-26 14:34:39 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
2015-08-14 13:54:00 +03:00
tevent_req_received ( req ) ;
2009-02-26 14:34:39 +03:00
return status ;
2009-01-03 21:50:05 +03:00
}
* pfd = state - > fd ;
state - > fd = - 1 ;
2015-08-14 13:54:00 +03:00
tevent_req_received ( req ) ;
2009-01-03 21:50:05 +03:00
return NT_STATUS_OK ;
}
2011-04-13 19:35:44 +04:00
/**
* @ brief open a socket
*
* @ param pss a struct sockaddr_storage defining the address to connect to
* @ param port to connect to
* @ param timeout in MILLISECONDS
* @ param pfd file descriptor returned
*
* @ return NTSTATUS code
*/
2009-01-03 21:50:05 +03:00
NTSTATUS open_socket_out ( const struct sockaddr_storage * pss , uint16_t port ,
int timeout , int * pfd )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 13:00:26 +04:00
struct tevent_context * ev ;
2009-02-26 14:34:39 +03:00
struct tevent_req * req ;
2009-01-03 21:50:05 +03:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2013-02-18 12:10:34 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-01-03 21:50:05 +03:00
if ( ev = = NULL ) {
goto fail ;
2003-07-17 01:06:21 +04:00
}
1998-11-09 19:40:38 +03:00
2009-01-03 21:50:05 +03:00
req = open_socket_out_send ( frame , ev , pss , port , timeout ) ;
if ( req = = NULL ) {
goto fail ;
}
2009-02-26 14:34:39 +03:00
if ( ! tevent_req_poll ( req , ev ) ) {
status = NT_STATUS_INTERNAL_ERROR ;
goto fail ;
2009-01-03 21:50:05 +03:00
}
status = open_socket_out_recv ( req , pfd ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
1998-11-09 19:40:38 +03:00
}
2009-01-04 03:45:06 +03:00
struct open_socket_out_defer_state {
2013-02-18 13:00:26 +04:00
struct tevent_context * ev ;
2009-01-04 03:45:06 +03:00
struct sockaddr_storage ss ;
uint16_t port ;
int timeout ;
int fd ;
} ;
2009-03-16 20:43:57 +03:00
static void open_socket_out_defer_waited ( struct tevent_req * subreq ) ;
2009-02-26 14:34:39 +03:00
static void open_socket_out_defer_connected ( struct tevent_req * subreq ) ;
2009-01-04 03:45:06 +03:00
2009-03-16 21:15:26 +03:00
struct tevent_req * open_socket_out_defer_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 13:00:26 +04:00
struct tevent_context * ev ,
2009-03-16 21:15:26 +03:00
struct timeval wait_time ,
const struct sockaddr_storage * pss ,
uint16_t port ,
int timeout )
2009-01-04 03:45:06 +03:00
{
2009-03-16 21:15:26 +03:00
struct tevent_req * req , * subreq ;
2009-01-04 03:45:06 +03:00
struct open_socket_out_defer_state * state ;
2009-03-16 21:15:26 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct open_socket_out_defer_state ) ;
if ( req = = NULL ) {
2009-01-04 03:45:06 +03:00
return NULL ;
}
state - > ev = ev ;
state - > ss = * pss ;
state - > port = port ;
state - > timeout = timeout ;
2009-03-16 20:43:57 +03:00
subreq = tevent_wakeup_send (
state , ev ,
timeval_current_ofs ( wait_time . tv_sec , wait_time . tv_usec ) ) ;
2009-01-04 03:45:06 +03:00
if ( subreq = = NULL ) {
goto fail ;
}
2009-03-16 21:15:26 +03:00
tevent_req_set_callback ( subreq , open_socket_out_defer_waited , req ) ;
return req ;
2009-01-04 03:45:06 +03:00
fail :
2009-03-16 21:15:26 +03:00
TALLOC_FREE ( req ) ;
2009-01-04 03:45:06 +03:00
return NULL ;
}
2009-03-16 20:43:57 +03:00
static void open_socket_out_defer_waited ( struct tevent_req * subreq )
2009-01-04 03:45:06 +03:00
{
2009-03-16 21:15:26 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct open_socket_out_defer_state * state = tevent_req_data (
req , struct open_socket_out_defer_state ) ;
2009-02-01 18:32:02 +03:00
bool ret ;
2009-01-04 03:45:06 +03:00
2009-03-16 20:43:57 +03:00
ret = tevent_wakeup_recv ( subreq ) ;
2009-01-04 03:45:06 +03:00
TALLOC_FREE ( subreq ) ;
2009-02-01 18:32:02 +03:00
if ( ! ret ) {
2009-03-16 21:15:26 +03:00
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
2009-01-04 03:45:06 +03:00
return ;
}
2009-03-16 20:43:57 +03:00
subreq = open_socket_out_send ( state , state - > ev , & state - > ss ,
state - > port , state - > timeout ) ;
2009-03-16 21:15:26 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
2009-01-04 03:45:06 +03:00
return ;
}
2009-03-16 20:43:57 +03:00
tevent_req_set_callback ( subreq , open_socket_out_defer_connected , req ) ;
2009-01-04 03:45:06 +03:00
}
2009-02-26 14:34:39 +03:00
static void open_socket_out_defer_connected ( struct tevent_req * subreq )
2009-01-04 03:45:06 +03:00
{
2009-03-16 21:15:26 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct open_socket_out_defer_state * state = tevent_req_data (
req , struct open_socket_out_defer_state ) ;
2009-01-04 03:45:06 +03:00
NTSTATUS status ;
status = open_socket_out_recv ( subreq , & state - > fd ) ;
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-03-16 21:15:26 +03:00
tevent_req_nterror ( req , status ) ;
2009-01-04 03:45:06 +03:00
return ;
}
2009-03-16 21:15:26 +03:00
tevent_req_done ( req ) ;
2009-01-04 03:45:06 +03:00
}
2009-03-16 21:15:26 +03:00
NTSTATUS open_socket_out_defer_recv ( struct tevent_req * req , int * pfd )
2009-01-04 03:45:06 +03:00
{
2009-03-16 21:15:26 +03:00
struct open_socket_out_defer_state * state = tevent_req_data (
req , struct open_socket_out_defer_state ) ;
2009-01-04 03:45:06 +03:00
NTSTATUS status ;
2009-03-16 21:15:26 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
2009-01-04 03:45:06 +03:00
return status ;
}
* pfd = state - > fd ;
state - > fd = - 1 ;
return NT_STATUS_OK ;
}
2007-10-13 00:38:04 +04:00
/*******************************************************************
Return the IP addr of the remote end of a socket as a string .
Optionally return the struct sockaddr_storage .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * get_peer_addr_internal ( int fd ,
2007-11-04 04:41:26 +03:00
char * addr_buf ,
size_t addr_buf_len ,
2008-10-23 21:53:15 +04:00
struct sockaddr * pss ,
2007-10-13 00:38:04 +04:00
socklen_t * plength )
{
struct sockaddr_storage ss ;
socklen_t length = sizeof ( ss ) ;
2007-11-07 23:48:58 +03:00
strlcpy ( addr_buf , " 0.0.0.0 " , addr_buf_len ) ;
2007-10-13 00:38:04 +04:00
if ( fd = = - 1 ) {
return addr_buf ;
}
if ( pss = = NULL ) {
2008-10-23 21:53:15 +04:00
pss = ( struct sockaddr * ) & ss ;
2007-10-13 00:38:04 +04:00
plength = & length ;
}
if ( getpeername ( fd , ( struct sockaddr * ) pss , plength ) < 0 ) {
2010-03-26 17:14:35 +03:00
int level = ( errno = = ENOTCONN ) ? 2 : 0 ;
DEBUG ( level , ( " getpeername failed. Error was %s \n " ,
strerror ( errno ) ) ) ;
2007-10-13 00:38:04 +04:00
return addr_buf ;
}
2007-10-25 01:16:54 +04:00
print_sockaddr_len ( addr_buf ,
2007-11-04 06:27:59 +03:00
addr_buf_len ,
2007-10-13 00:38:04 +04:00
pss ,
* plength ) ;
return addr_buf ;
}
1998-11-09 19:40:38 +03:00
/*******************************************************************
2003-07-17 01:06:21 +04:00
Matchname - determine if host name matches IP address . Used to
confirm a hostname lookup to prevent spoof attacks .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-13 00:38:04 +04:00
static bool matchname ( const char * remotehost ,
2008-10-23 21:53:15 +04:00
const struct sockaddr * pss ,
2007-10-13 00:38:04 +04:00
socklen_t len )
1998-11-09 19:40:38 +03:00
{
2007-10-13 00:38:04 +04:00
struct addrinfo * res = NULL ;
struct addrinfo * ailist = NULL ;
char addr_buf [ INET6_ADDRSTRLEN ] ;
2007-10-16 03:11:48 +04:00
bool ret = interpret_string_addr_internal ( & ailist ,
remotehost ,
AI_ADDRCONFIG | AI_CANONNAME ) ;
2007-10-13 00:38:04 +04:00
2007-10-16 03:11:48 +04:00
if ( ! ret | | ailist = = NULL ) {
2007-10-13 00:38:04 +04:00
DEBUG ( 3 , ( " matchname: getaddrinfo failed for "
" name %s [%s] \n " ,
remotehost ,
gai_strerror ( ret ) ) ) ;
2007-10-11 05:25:16 +04:00
return false ;
2007-10-02 23:50:53 +04:00
}
2000-04-11 17:55:53 +04:00
/*
2007-10-13 00:38:04 +04:00
* Make sure that getaddrinfo ( ) returns the " correct " host name .
2000-04-11 17:55:53 +04:00
*/
2007-10-02 23:50:53 +04:00
2007-10-16 03:11:48 +04:00
if ( ailist - > ai_canonname = = NULL | |
( ! strequal ( remotehost , ailist - > ai_canonname ) & &
2007-10-13 00:38:04 +04:00
! strequal ( remotehost , " localhost " ) ) ) {
DEBUG ( 0 , ( " matchname: host name/name mismatch: %s != %s \n " ,
remotehost ,
2007-10-16 03:11:48 +04:00
ailist - > ai_canonname ?
ailist - > ai_canonname : " (NULL) " ) ) ;
freeaddrinfo ( ailist ) ;
2007-10-11 05:25:16 +04:00
return false ;
1998-11-09 19:40:38 +03:00
}
2007-10-02 23:50:53 +04:00
2000-04-11 17:55:53 +04:00
/* Look up the host address in the address list we just got. */
2007-10-16 03:11:48 +04:00
for ( res = ailist ; res ; res = res - > ai_next ) {
if ( ! res - > ai_addr ) {
2007-10-13 00:38:04 +04:00
continue ;
}
2008-12-03 10:29:57 +03:00
if ( sockaddr_equal ( ( const struct sockaddr * ) res - > ai_addr ,
2011-05-06 00:42:05 +04:00
( const struct sockaddr * ) pss ) ) {
2007-10-16 03:11:48 +04:00
freeaddrinfo ( ailist ) ;
2007-10-11 05:25:16 +04:00
return true ;
2007-10-13 00:38:04 +04:00
}
1998-11-09 19:40:38 +03:00
}
2007-10-02 23:50:53 +04:00
2000-04-11 17:55:53 +04:00
/*
* The host name does not map to the original host address . Perhaps
* someone has compromised a name server . More likely someone botched
* it , but that could be dangerous , too .
*/
2007-10-02 23:50:53 +04:00
2007-10-13 00:38:04 +04:00
DEBUG ( 0 , ( " matchname: host name/address mismatch: %s != %s \n " ,
2007-10-25 01:16:54 +04:00
print_sockaddr_len ( addr_buf ,
2007-10-13 00:38:04 +04:00
sizeof ( addr_buf ) ,
pss ,
len ) ,
2007-10-16 03:11:48 +04:00
ailist - > ai_canonname ? ailist - > ai_canonname : " (NULL) " ) ) ;
2007-10-13 00:38:04 +04:00
2007-10-16 03:11:48 +04:00
if ( ailist ) {
freeaddrinfo ( ailist ) ;
}
2007-10-11 05:25:16 +04:00
return false ;
2000-04-11 17:55:53 +04:00
}
2008-01-03 04:37:39 +03:00
/*******************************************************************
Deal with the singleton cache .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct name_addr_pair {
struct sockaddr_storage ss ;
const char * name ;
} ;
/*******************************************************************
Lookup a name / addr pair . Returns memory allocated from memcache .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool lookup_nc ( struct name_addr_pair * nc )
{
DATA_BLOB tmp ;
ZERO_STRUCTP ( nc ) ;
if ( ! memcache_lookup (
NULL , SINGLETON_CACHE ,
2008-10-13 07:20:26 +04:00
data_blob_string_const_null ( " get_peer_name " ) ,
2008-01-03 04:37:39 +03:00
& tmp ) ) {
return false ;
}
memcpy ( & nc - > ss , tmp . data , sizeof ( nc - > ss ) ) ;
nc - > name = ( const char * ) tmp . data + sizeof ( nc - > ss ) ;
return true ;
}
/*******************************************************************
Save a name / addr pair .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void store_nc ( const struct name_addr_pair * nc )
{
DATA_BLOB tmp ;
size_t namelen = strlen ( nc - > name ) ;
2008-01-03 12:24:45 +03:00
tmp = data_blob ( NULL , sizeof ( nc - > ss ) + namelen + 1 ) ;
2008-01-03 04:37:39 +03:00
if ( ! tmp . data ) {
return ;
}
memcpy ( tmp . data , & nc - > ss , sizeof ( nc - > ss ) ) ;
memcpy ( tmp . data + sizeof ( nc - > ss ) , nc - > name , namelen + 1 ) ;
memcache_add ( NULL , SINGLETON_CACHE ,
2008-10-13 07:20:26 +04:00
data_blob_string_const_null ( " get_peer_name " ) ,
2008-01-03 04:37:39 +03:00
tmp ) ;
2008-01-03 12:24:45 +03:00
data_blob_free ( & tmp ) ;
2008-01-03 04:37:39 +03:00
}
2007-11-07 23:48:58 +03:00
1998-11-09 19:40:38 +03:00
/*******************************************************************
2003-07-17 01:06:21 +04:00
Return the IP addr of the remote end of a socket as a string .
1998-11-09 19:40:38 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-07-17 01:06:21 +04:00
2007-11-04 04:41:26 +03:00
const char * get_peer_addr ( int fd , char * addr , size_t addr_len )
1998-11-09 19:40:38 +03:00
{
2007-11-04 04:41:26 +03:00
return get_peer_addr_internal ( fd , addr , addr_len , NULL , NULL ) ;
1998-11-09 19:40:38 +03:00
}
2000-01-03 22:19:48 +03:00
2011-06-08 16:50:20 +04:00
int get_remote_hostname ( const struct tsocket_address * remote_address ,
char * * name ,
TALLOC_CTX * mem_ctx )
{
char name_buf [ MAX_DNS_NAME_LENGTH ] ;
char tmp_name [ MAX_DNS_NAME_LENGTH ] ;
struct name_addr_pair nc ;
struct sockaddr_storage ss ;
2011-07-06 11:37:04 +04:00
ssize_t len ;
2011-06-08 16:50:20 +04:00
int rc ;
if ( ! lp_hostname_lookups ( ) ) {
nc . name = tsocket_address_inet_addr_string ( remote_address ,
mem_ctx ) ;
if ( nc . name = = NULL ) {
return - 1 ;
}
len = tsocket_address_bsd_sockaddr ( remote_address ,
( struct sockaddr * ) & nc . ss ,
sizeof ( struct sockaddr_storage ) ) ;
if ( len < 0 ) {
return - 1 ;
}
store_nc ( & nc ) ;
lookup_nc ( & nc ) ;
if ( nc . name = = NULL ) {
* name = talloc_strdup ( mem_ctx , " UNKNOWN " ) ;
} else {
* name = talloc_strdup ( mem_ctx , nc . name ) ;
}
return 0 ;
}
lookup_nc ( & nc ) ;
ZERO_STRUCT ( ss ) ;
len = tsocket_address_bsd_sockaddr ( remote_address ,
( struct sockaddr * ) & ss ,
sizeof ( struct sockaddr_storage ) ) ;
if ( len < 0 ) {
return - 1 ;
}
/* it might be the same as the last one - save some DNS work */
if ( sockaddr_equal ( ( struct sockaddr * ) & ss , ( struct sockaddr * ) & nc . ss ) ) {
if ( nc . name = = NULL ) {
* name = talloc_strdup ( mem_ctx , " UNKNOWN " ) ;
} else {
* name = talloc_strdup ( mem_ctx , nc . name ) ;
}
return 0 ;
}
/* Look up the remote host name. */
rc = sys_getnameinfo ( ( struct sockaddr * ) & ss ,
len ,
name_buf ,
sizeof ( name_buf ) ,
NULL ,
0 ,
0 ) ;
if ( rc < 0 ) {
char * p ;
p = tsocket_address_inet_addr_string ( remote_address , mem_ctx ) ;
if ( p = = NULL ) {
return - 1 ;
}
DEBUG ( 1 , ( " getnameinfo failed for %s with error %s \n " ,
p ,
gai_strerror ( rc ) ) ) ;
strlcpy ( name_buf , p , sizeof ( name_buf ) ) ;
2011-07-06 11:39:08 +04:00
TALLOC_FREE ( p ) ;
2011-06-08 16:50:20 +04:00
} else {
if ( ! matchname ( name_buf , ( struct sockaddr * ) & ss , len ) ) {
DEBUG ( 0 , ( " matchname failed on %s \n " , name_buf ) ) ;
strlcpy ( name_buf , " UNKNOWN " , sizeof ( name_buf ) ) ;
}
}
strlcpy ( tmp_name , name_buf , sizeof ( tmp_name ) ) ;
alpha_strcpy ( name_buf , tmp_name , " _-. " , sizeof ( name_buf ) ) ;
if ( strstr ( name_buf , " .. " ) ) {
strlcpy ( name_buf , " UNKNOWN " , sizeof ( name_buf ) ) ;
}
nc . name = name_buf ;
nc . ss = ss ;
store_nc ( & nc ) ;
lookup_nc ( & nc ) ;
if ( nc . name = = NULL ) {
2015-07-27 00:02:57 +03:00
* name = talloc_strdup ( mem_ctx , " UNKNOWN " ) ;
2011-06-08 16:50:20 +04:00
} else {
* name = talloc_strdup ( mem_ctx , nc . name ) ;
}
return 0 ;
}
2002-01-13 14:13:54 +03:00
/*******************************************************************
Create protected unix domain socket .
2003-02-08 00:59:51 +03:00
Some unixes cannot set permissions on a ux - dom - sock , so we
2002-01-13 14:13:54 +03:00
have to make sure that the directory contains the protection
2003-02-08 00:59:51 +03:00
permissions instead .
2002-01-13 14:13:54 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-08 00:59:51 +03:00
2002-01-13 14:13:54 +03:00
int create_pipe_sock ( const char * socket_dir ,
2002-07-15 14:35:28 +04:00
const char * socket_name ,
mode_t dir_perms )
2002-01-13 14:13:54 +03:00
{
2002-09-25 19:19:00 +04:00
# ifdef HAVE_UNIXSOCKET
2003-02-08 00:59:51 +03:00
struct sockaddr_un sunaddr ;
2013-01-09 12:02:54 +04:00
bool ok ;
2013-06-18 04:02:56 +04:00
int sock = - 1 ;
mode_t old_umask ;
2007-11-12 08:45:55 +03:00
char * path = NULL ;
2019-10-18 11:11:13 +03:00
size_t path_len ;
2007-10-02 23:50:53 +04:00
2013-06-18 04:02:56 +04:00
old_umask = umask ( 0 ) ;
2013-01-09 12:02:54 +04:00
ok = directory_create_or_exist_strict ( socket_dir ,
sec_initial_uid ( ) ,
dir_perms ) ;
if ( ! ok ) {
2013-06-18 04:02:56 +04:00
goto out_close ;
2003-02-08 00:59:51 +03:00
}
2007-10-02 23:50:53 +04:00
2003-02-08 00:59:51 +03:00
/* Create the socket file */
sock = socket ( AF_UNIX , SOCK_STREAM , 0 ) ;
2007-10-02 23:50:53 +04:00
2003-02-08 00:59:51 +03:00
if ( sock = = - 1 ) {
2007-11-12 08:45:55 +03:00
DEBUG ( 0 , ( " create_pipe_sock: socket error %s \n " ,
strerror ( errno ) ) ) ;
goto out_close ;
2003-02-08 00:59:51 +03:00
}
2007-10-02 23:50:53 +04:00
2008-02-25 17:24:49 +03:00
if ( asprintf ( & path , " %s/%s " , socket_dir , socket_name ) = = - 1 ) {
2007-11-12 08:45:55 +03:00
goto out_close ;
}
2007-10-02 23:50:53 +04:00
2003-02-08 00:59:51 +03:00
unlink ( path ) ;
memset ( & sunaddr , 0 , sizeof ( sunaddr ) ) ;
sunaddr . sun_family = AF_UNIX ;
2019-10-18 11:11:13 +03:00
path_len = strlcpy ( sunaddr . sun_path , path , sizeof ( sunaddr . sun_path ) ) ;
if ( path_len > sizeof ( sunaddr . sun_path ) ) {
DBG_ERR ( " Refusing to attempt to create pipe socket "
" %s. Path is longer than permitted for a "
" unix domain socket. It would truncate to "
" %s \n " ,
path ,
sunaddr . sun_path ) ;
goto out_close ;
}
2007-10-02 23:50:53 +04:00
2003-02-08 00:59:51 +03:00
if ( bind ( sock , ( struct sockaddr * ) & sunaddr , sizeof ( sunaddr ) ) = = - 1 ) {
DEBUG ( 0 , ( " bind failed on pipe socket %s: %s \n " , path ,
strerror ( errno ) ) ) ;
goto out_close ;
}
2007-10-02 23:50:53 +04:00
2007-11-12 08:45:55 +03:00
SAFE_FREE ( path ) ;
2013-06-18 04:02:56 +04:00
umask ( old_umask ) ;
2003-02-08 00:59:51 +03:00
return sock ;
out_close :
2007-11-12 08:45:55 +03:00
SAFE_FREE ( path ) ;
2008-02-18 02:43:46 +03:00
if ( sock ! = - 1 )
close ( sock ) ;
2003-02-08 00:59:51 +03:00
2013-06-18 04:02:56 +04:00
umask ( old_umask ) ;
2003-02-08 00:59:51 +03:00
return - 1 ;
2002-09-25 19:19:00 +04:00
# else
DEBUG ( 0 , ( " create_pipe_sock: No Unix sockets on this system \n " ) ) ;
return - 1 ;
# endif /* HAVE_UNIXSOCKET */
2002-01-13 14:13:54 +03:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
/****************************************************************************
Get my own canonical name , including domain .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-09 04:25:45 +03:00
const char * get_mydnsfullname ( void )
2007-10-16 03:11:48 +04:00
{
2008-01-03 04:37:39 +03:00
struct addrinfo * res = NULL ;
char my_hostname [ HOST_NAME_MAX ] ;
bool ret ;
DATA_BLOB tmp ;
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
if ( memcache_lookup ( NULL , SINGLETON_CACHE ,
2008-10-13 07:20:26 +04:00
data_blob_string_const_null ( " get_mydnsfullname " ) ,
2008-01-03 04:37:39 +03:00
& tmp ) ) {
SMB_ASSERT ( tmp . length > 0 ) ;
return ( const char * ) tmp . data ;
}
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
/* get my host name */
if ( gethostname ( my_hostname , sizeof ( my_hostname ) ) = = - 1 ) {
DEBUG ( 0 , ( " get_mydnsfullname: gethostname failed \n " ) ) ;
return NULL ;
}
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
/* Ensure null termination. */
my_hostname [ sizeof ( my_hostname ) - 1 ] = ' \0 ' ;
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
ret = interpret_string_addr_internal ( & res ,
2007-11-09 04:25:45 +03:00
my_hostname ,
2008-01-03 04:37:39 +03:00
AI_ADDRCONFIG | AI_CANONNAME ) ;
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
if ( ! ret | | res = = NULL ) {
DEBUG ( 3 , ( " get_mydnsfullname: getaddrinfo failed for "
" name %s [%s] \n " ,
my_hostname ,
gai_strerror ( ret ) ) ) ;
return NULL ;
}
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
/*
* Make sure that getaddrinfo ( ) returns the " correct " host name .
*/
2007-10-16 03:11:48 +04:00
2008-01-03 04:37:39 +03:00
if ( res - > ai_canonname = = NULL ) {
DEBUG ( 3 , ( " get_mydnsfullname: failed to get "
" canonical name for %s \n " ,
my_hostname ) ) ;
2007-10-16 03:11:48 +04:00
freeaddrinfo ( res ) ;
2008-01-03 04:37:39 +03:00
return NULL ;
}
/* This copies the data, so we must do a lookup
* afterwards to find the value to return .
*/
memcache_add ( NULL , SINGLETON_CACHE ,
2008-10-13 07:20:26 +04:00
data_blob_string_const_null ( " get_mydnsfullname " ) ,
data_blob_string_const_null ( res - > ai_canonname ) ) ;
2008-01-03 04:37:39 +03:00
if ( ! memcache_lookup ( NULL , SINGLETON_CACHE ,
2008-10-13 07:20:26 +04:00
data_blob_string_const_null ( " get_mydnsfullname " ) ,
2008-01-03 04:37:39 +03:00
& tmp ) ) {
2008-01-21 20:01:55 +03:00
tmp = data_blob_talloc ( talloc_tos ( ) , res - > ai_canonname ,
strlen ( res - > ai_canonname ) + 1 ) ;
2007-10-16 03:11:48 +04:00
}
2008-01-03 04:37:39 +03:00
2008-01-21 15:18:38 +03:00
freeaddrinfo ( res ) ;
2008-01-03 04:37:39 +03:00
return ( const char * ) tmp . data ;
2007-10-16 03:11:48 +04:00
}
2011-03-24 22:11:02 +03:00
/************************************************************
Is this my ip address ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool is_my_ipaddr ( const char * ipaddr_str )
{
struct sockaddr_storage ss ;
struct iface_struct * nics ;
int i , n ;
if ( ! interpret_string_addr ( & ss , ipaddr_str , AI_NUMERICHOST ) ) {
return false ;
}
2011-05-17 03:08:48 +04:00
if ( is_zero_addr ( & ss ) ) {
return false ;
2011-03-24 22:11:02 +03:00
}
2011-05-17 03:08:48 +04:00
if ( ismyaddr ( ( struct sockaddr * ) & ss ) | |
is_loopback_addr ( ( struct sockaddr * ) & ss ) ) {
return true ;
2011-03-24 22:11:02 +03:00
}
n = get_interfaces ( talloc_tos ( ) , & nics ) ;
for ( i = 0 ; i < n ; i + + ) {
if ( sockaddr_equal ( ( struct sockaddr * ) & nics [ i ] . ip , ( struct sockaddr * ) & ss ) ) {
TALLOC_FREE ( nics ) ;
return true ;
}
}
TALLOC_FREE ( nics ) ;
return false ;
}
2007-10-11 05:25:16 +04:00
/************************************************************
2007-10-16 03:11:48 +04:00
Is this my name ?
2007-10-11 05:25:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool is_myname_or_ipaddr ( const char * s )
{
2007-11-09 04:25:45 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
char * name = NULL ;
const char * dnsname ;
char * servername = NULL ;
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
if ( ! s ) {
2007-10-11 05:25:16 +04:00
return false ;
2007-10-13 08:50:41 +04:00
}
2007-10-11 05:25:16 +04:00
2021-02-24 23:30:59 +03:00
/* Sanitize the string from '\\name' */
2007-11-09 04:25:45 +03:00
name = talloc_strdup ( ctx , s ) ;
if ( ! name ) {
return false ;
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
servername = strrchr_m ( name , ' \\ ' ) ;
if ( ! servername ) {
2007-10-11 05:25:16 +04:00
servername = name ;
2007-10-16 03:11:48 +04:00
} else {
2007-10-11 05:25:16 +04:00
servername + + ;
2007-10-16 03:11:48 +04:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
/* Optimize for the common case */
2011-06-09 09:31:03 +04:00
if ( strequal ( servername , lp_netbios_name ( ) ) ) {
2007-10-11 05:25:16 +04:00
return true ;
2007-10-16 03:11:48 +04:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
/* Check for an alias */
if ( is_myname ( servername ) ) {
2007-10-11 05:25:16 +04:00
return true ;
2007-10-16 03:11:48 +04:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
/* Check for loopback */
if ( strequal ( servername , " 127.0.0.1 " ) | |
strequal ( servername , " ::1 " ) ) {
2007-10-11 05:25:16 +04:00
return true ;
2007-10-16 03:11:48 +04:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
if ( strequal ( servername , " localhost " ) ) {
2007-10-11 05:25:16 +04:00
return true ;
2007-10-16 03:11:48 +04:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
/* Maybe it's my dns name */
2007-11-09 04:25:45 +03:00
dnsname = get_mydnsfullname ( ) ;
if ( dnsname & & strequal ( servername , dnsname ) ) {
return true ;
2007-10-16 03:11:48 +04:00
}
2007-10-11 05:25:16 +04:00
2007-10-16 03:11:48 +04:00
/* Maybe its an IP address? */
if ( is_ipaddress ( servername ) ) {
2011-03-24 22:11:02 +03:00
return is_my_ipaddr ( servername ) ;
}
2007-10-11 05:25:16 +04:00
2011-03-24 22:11:02 +03:00
/* Handle possible CNAME records - convert to an IP addr. list. */
{
/* Use DNS to resolve the name, check all addresses. */
struct addrinfo * p = NULL ;
struct addrinfo * res = NULL ;
2009-04-08 14:47:10 +04:00
2011-03-24 22:11:02 +03:00
if ( ! interpret_string_addr_internal ( & res ,
servername ,
AI_ADDRCONFIG ) ) {
2007-10-16 03:11:48 +04:00
return false ;
}
2007-10-11 05:25:16 +04:00
2011-03-24 22:11:02 +03:00
for ( p = res ; p ; p = p - > ai_next ) {
char addr [ INET6_ADDRSTRLEN ] ;
struct sockaddr_storage ss ;
ZERO_STRUCT ( ss ) ;
memcpy ( & ss , p - > ai_addr , p - > ai_addrlen ) ;
print_sockaddr ( addr ,
sizeof ( addr ) ,
& ss ) ;
if ( is_my_ipaddr ( addr ) ) {
freeaddrinfo ( res ) ;
2007-10-11 05:25:16 +04:00
return true ;
}
}
2011-03-24 22:11:02 +03:00
freeaddrinfo ( res ) ;
2007-10-11 05:25:16 +04:00
}
2007-10-16 03:11:48 +04:00
/* No match */
2007-10-11 05:25:16 +04:00
return false ;
}
2009-04-05 21:58:20 +04:00
2011-02-07 18:55:16 +03:00
int poll_one_fd ( int fd , int events , int timeout , int * revents )
{
2013-12-05 02:31:10 +04:00
struct pollfd pfd ;
2011-02-07 18:55:16 +03:00
int ret ;
2013-12-05 02:31:10 +04:00
pfd . fd = fd ;
pfd . events = events ;
2011-02-07 18:55:16 +03:00
2013-12-05 02:31:10 +04:00
ret = poll ( & pfd , 1 , timeout ) ;
2011-02-07 18:55:16 +03:00
/*
* Assign whatever poll did , even in the ret < = 0 case .
*/
2013-12-05 02:31:10 +04:00
* revents = pfd . revents ;
2011-02-07 18:55:16 +03:00
return ret ;
}
2011-02-08 19:33:59 +03:00
int poll_intr_one_fd ( int fd , int events , int timeout , int * revents )
{
struct pollfd pfd ;
int ret ;
pfd . fd = fd ;
pfd . events = events ;
ret = sys_poll_intr ( & pfd , 1 , timeout ) ;
if ( ret < = 0 ) {
* revents = 0 ;
return ret ;
}
* revents = pfd . revents ;
return 1 ;
}