2005-09-22 22:35:08 +04:00
/*
Unix SMB / CIFS implementation .
Main winbindd samba3 server routines
Copyright ( C ) Stefan Metzmacher 2005
Copyright ( C ) Volker Lendecke 2005
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-09-22 22:35:08 +04: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-09-22 22:35:08 +04:00
*/
# include "includes.h"
# include "winbind/wb_server.h"
2006-01-12 12:38:35 +03:00
# include "smbd/service_stream.h"
# include "lib/stream/packet.h"
2010-01-17 12:21:21 +03:00
# include "lib/tsocket/tsocket.h"
2005-09-22 22:35:08 +04:00
2006-01-12 12:38:35 +03:00
/*
2006-07-26 09:19:36 +04:00
work out if a packet is complete for protocols that use a 32 bit host byte
2006-01-12 12:38:35 +03:00
order length
*/
2009-02-02 10:43:37 +03:00
NTSTATUS wbsrv_samba3_packet_full_request ( void * private_data , DATA_BLOB blob , size_t * size )
2005-09-22 22:35:08 +04:00
{
2006-01-12 12:38:35 +03:00
uint32_t * len ;
2011-07-26 04:51:31 +04:00
struct winbindd_request * req ;
2006-01-12 12:38:35 +03:00
if ( blob . length < 4 ) {
return STATUS_MORE_ENTRIES ;
}
len = ( uint32_t * ) blob . data ;
* size = ( * len ) ;
if ( * size > blob . length ) {
return STATUS_MORE_ENTRIES ;
}
2011-07-26 04:51:31 +04:00
if ( * size < sizeof ( req ) ) {
/* its not a valid winbind packet. We need to accept
it here , and wbsrv_samba3_pull_request ( ) will throw
it away */
return NT_STATUS_OK ;
}
/* now we need to cope with possible extra_data, which is
stuck on the end with no length prefix ! This is a very very
stupid protocol */
req = ( struct winbindd_request * ) blob . data ;
* size = ( * len ) + req - > extra_len ;
if ( * size > blob . length ) {
return STATUS_MORE_ENTRIES ;
}
2006-01-12 12:38:35 +03:00
return NT_STATUS_OK ;
2005-09-22 22:35:08 +04:00
}
2006-01-12 12:38:35 +03:00
2010-01-17 12:21:21 +03:00
NTSTATUS wbsrv_samba3_pull_request ( struct wbsrv_samba3_call * call )
2005-09-22 22:35:08 +04:00
{
2011-07-26 04:51:31 +04:00
if ( call - > in . length < sizeof ( * call - > request ) ) {
2005-11-30 06:20:25 +03:00
DEBUG ( 0 , ( " wbsrv_samba3_pull_request: invalid blob length %lu should be %lu \n "
2005-09-22 22:35:08 +04:00
" make sure you use the correct winbind client tools! \n " ,
2010-05-14 11:31:33 +04:00
( long ) call - > in . length , ( long ) sizeof ( * call - > request ) ) ) ;
2005-09-22 22:35:08 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2010-05-14 11:31:33 +04:00
call - > request = talloc_zero ( call , struct winbindd_request ) ;
NT_STATUS_HAVE_NO_MEMORY ( call - > request ) ;
2005-09-22 22:35:08 +04:00
/* the packet layout is the same as the in memory layout of the request, so just copy it */
2010-05-14 11:31:33 +04:00
memcpy ( call - > request , call - > in . data , sizeof ( * call - > request ) ) ;
2005-09-22 22:35:08 +04:00
2011-07-26 04:51:31 +04:00
if ( call - > in . length ! = sizeof ( * call - > request ) + call - > request - > extra_len ) {
DEBUG ( 0 , ( __location__ " : invalid extra_len %u should be %u \n " ,
call - > request - > extra_len , ( unsigned ) ( call - > in . length - sizeof ( * call - > request ) ) ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
/* there may be extra data */
if ( call - > request - > extra_len ! = 0 ) {
call - > request - > extra_data . data = talloc_size ( call - > request , call - > request - > extra_len + 1 ) ;
NT_STATUS_HAVE_NO_MEMORY ( call - > request - > extra_data . data ) ;
/* guarantee a nul termination, as many of the uses of
this field is for strings */
memcpy ( call - > request - > extra_data . data , call - > in . data + sizeof ( * call - > request ) ,
call - > request - > extra_len ) ;
call - > request - > extra_data . data [ call - > request - > extra_len ] = 0 ;
} else {
call - > request - > extra_data . data = NULL ;
}
2005-09-22 22:35:08 +04:00
return NT_STATUS_OK ;
}
2006-01-12 12:38:35 +03:00
NTSTATUS wbsrv_samba3_handle_call ( struct wbsrv_samba3_call * s3call )
2005-09-22 22:35:08 +04:00
{
2010-05-14 11:31:33 +04:00
DEBUG ( 10 , ( " Got winbind samba3 request %d \n " , s3call - > request - > cmd ) ) ;
s3call - > response = talloc_zero ( s3call , struct winbindd_response ) ;
NT_STATUS_HAVE_NO_MEMORY ( s3call - > request ) ;
2005-09-22 22:35:08 +04:00
2010-05-14 11:31:33 +04:00
s3call - > response - > length = sizeof ( * s3call - > response ) ;
2005-10-19 17:45:44 +04:00
2010-05-14 11:31:33 +04:00
switch ( s3call - > request - > cmd ) {
2005-09-22 22:35:08 +04:00
case WINBINDD_INTERFACE_VERSION :
return wbsrv_samba3_interface_version ( s3call ) ;
2005-09-26 17:42:42 +04:00
case WINBINDD_CHECK_MACHACC :
return wbsrv_samba3_check_machacc ( s3call ) ;
2005-09-22 22:35:08 +04:00
case WINBINDD_PING :
return wbsrv_samba3_ping ( s3call ) ;
2005-09-26 01:01:56 +04:00
2005-09-26 17:42:42 +04:00
case WINBINDD_INFO :
2005-10-15 01:41:08 +04:00
return wbsrv_samba3_info ( s3call ) ;
2005-09-26 17:42:42 +04:00
case WINBINDD_DOMAIN_NAME :
return wbsrv_samba3_domain_name ( s3call ) ;
case WINBINDD_NETBIOS_NAME :
return wbsrv_samba3_netbios_name ( s3call ) ;
case WINBINDD_PRIV_PIPE_DIR :
return wbsrv_samba3_priv_pipe_dir ( s3call ) ;
2005-10-03 21:36:49 +04:00
case WINBINDD_LOOKUPNAME :
return wbsrv_samba3_lookupname ( s3call ) ;
2005-10-09 16:13:05 +04:00
2005-10-19 17:45:44 +04:00
case WINBINDD_LOOKUPSID :
return wbsrv_samba3_lookupsid ( s3call ) ;
2005-10-09 16:13:05 +04:00
case WINBINDD_PAM_AUTH :
return wbsrv_samba3_pam_auth ( s3call ) ;
case WINBINDD_PAM_AUTH_CRAP :
return wbsrv_samba3_pam_auth_crap ( s3call ) ;
2005-10-16 02:01:15 +04:00
case WINBINDD_GETDCNAME :
return wbsrv_samba3_getdcname ( s3call ) ;
2005-10-16 16:43:09 +04:00
case WINBINDD_GETUSERDOMGROUPS :
return wbsrv_samba3_userdomgroups ( s3call ) ;
2005-10-19 17:45:44 +04:00
case WINBINDD_GETUSERSIDS :
return wbsrv_samba3_usersids ( s3call ) ;
2005-10-20 01:53:03 +04:00
2009-01-15 12:14:55 +03:00
case WINBINDD_LIST_GROUPS :
return wbsrv_samba3_list_groups ( s3call ) ;
2005-10-20 01:53:03 +04:00
case WINBINDD_LIST_TRUSTDOM :
return wbsrv_samba3_list_trustdom ( s3call ) ;
2005-11-10 06:48:56 +03:00
2007-08-16 14:40:04 +04:00
case WINBINDD_LIST_USERS :
return wbsrv_samba3_list_users ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_GETPWNAM :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_getpwnam ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_GETPWUID :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_getpwuid ( s3call ) ;
case WINBINDD_SETPWENT :
return wbsrv_samba3_setpwent ( s3call ) ;
case WINBINDD_GETPWENT :
return wbsrv_samba3_getpwent ( s3call ) ;
case WINBINDD_ENDPWENT :
return wbsrv_samba3_endpwent ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_GETGRNAM :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_getgrnam ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_GETGRGID :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_getgrgid ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_GETGROUPS :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_getgroups ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_SETGRENT :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_setgrent ( s3call ) ;
2005-11-10 06:48:56 +03:00
case WINBINDD_GETGRENT :
2007-06-29 15:07:19 +04:00
return wbsrv_samba3_getgrent ( s3call ) ;
case WINBINDD_ENDGRENT :
return wbsrv_samba3_endgrent ( s3call ) ;
2007-08-13 19:58:41 +04:00
case WINBINDD_SID_TO_UID :
case WINBINDD_DUAL_SID2UID :
return wbsrv_samba3_sid2uid ( s3call ) ;
case WINBINDD_SID_TO_GID :
case WINBINDD_DUAL_SID2GID :
return wbsrv_samba3_sid2gid ( s3call ) ;
2007-08-13 20:07:47 +04:00
case WINBINDD_UID_TO_SID :
case WINBINDD_DUAL_UID2SID :
return wbsrv_samba3_uid2sid ( s3call ) ;
2007-08-13 20:20:26 +04:00
case WINBINDD_GID_TO_SID :
case WINBINDD_DUAL_GID2SID :
return wbsrv_samba3_gid2sid ( s3call ) ;
2009-08-13 11:42:14 +04:00
case WINBINDD_DOMAIN_INFO :
return wbsrv_samba3_domain_info ( s3call ) ;
2010-03-03 23:29:15 +03:00
case WINBINDD_PAM_LOGOFF :
return wbsrv_samba3_pam_logoff ( s3call ) ;
2007-06-29 15:07:19 +04:00
2011-07-26 04:52:59 +04:00
case WINBINDD_SIDS_TO_XIDS :
return wbsrv_samba3_sids2xids ( s3call ) ;
2010-03-03 23:29:15 +03:00
/* Unimplemented commands */
2011-06-16 11:01:04 +04:00
case WINBINDD_GETPWSID :
case WINBINDD_PAM_CHAUTHTOK :
case WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP :
case WINBINDD_LOOKUPRIDS :
case WINBINDD_LOOKUPSIDS :
case WINBINDD_ALLOCATE_UID :
case WINBINDD_ALLOCATE_GID :
case WINBINDD_SHOW_SEQUENCE :
case WINBINDD_WINS_BYIP :
case WINBINDD_WINS_BYNAME :
case WINBINDD_GETGRLST :
case WINBINDD_GETSIDALIASES :
case WINBINDD_DSGETDCNAME :
case WINBINDD_INIT_CONNECTION :
case WINBINDD_DUAL_SIDS2XIDS :
case WINBINDD_DUAL_USERINFO :
case WINBINDD_DUAL_GETSIDALIASES :
case WINBINDD_DUAL_NDRCMD :
case WINBINDD_CCACHE_NTLMAUTH :
case WINBINDD_NUM_CMDS :
case WINBINDD_CHANGE_MACHACC :
case WINBINDD_PING_DC :
case WINBINDD_DC_INFO :
case WINBINDD_CCACHE_SAVE :
DEBUG ( 10 , ( " Unimplemented winbind samba3 request %d \n " ,
s3call - > request - > cmd ) ) ;
2005-11-10 06:48:56 +03:00
break ;
2005-09-22 22:35:08 +04:00
}
2010-05-14 11:31:33 +04:00
s3call - > response - > result = WINBINDD_ERROR ;
2005-09-22 22:35:08 +04:00
return NT_STATUS_OK ;
}
2010-01-17 12:21:21 +03:00
static NTSTATUS wbsrv_samba3_push_reply ( struct wbsrv_samba3_call * call )
2005-09-22 22:35:08 +04:00
{
uint8_t * extra_data ;
size_t extra_data_len = 0 ;
2010-05-14 11:31:33 +04:00
extra_data = ( uint8_t * ) call - > response - > extra_data . data ;
2007-09-07 19:35:18 +04:00
if ( extra_data ! = NULL ) {
2010-05-14 11:31:33 +04:00
extra_data_len = call - > response - > length -
sizeof ( * call - > response ) ;
2005-09-22 22:35:08 +04:00
}
2010-05-14 11:31:33 +04:00
call - > out = data_blob_talloc ( call , NULL , call - > response - > length ) ;
2010-01-17 12:21:21 +03:00
NT_STATUS_HAVE_NO_MEMORY ( call - > out . data ) ;
2005-09-22 22:35:08 +04:00
/* don't push real pointer values into sockets */
if ( extra_data ) {
2010-05-14 11:31:33 +04:00
call - > response - > extra_data . data = ( void * ) 0xFFFFFFFF ;
2005-09-22 22:35:08 +04:00
}
2010-05-14 11:31:33 +04:00
memcpy ( call - > out . data , call - > response , sizeof ( * call - > response ) ) ;
2005-09-22 22:35:08 +04:00
/* set back the pointer */
2010-05-14 11:31:33 +04:00
call - > response - > extra_data . data = extra_data ;
2005-09-22 22:35:08 +04:00
if ( extra_data ) {
2010-05-14 11:31:33 +04:00
memcpy ( call - > out . data + sizeof ( * call - > response ) ,
2010-01-17 12:21:21 +03:00
extra_data ,
extra_data_len ) ;
2005-09-22 22:35:08 +04:00
}
return NT_STATUS_OK ;
}
2006-01-12 12:38:35 +03:00
2010-01-17 12:21:21 +03:00
static void wbsrv_samba3_send_reply_done ( struct tevent_req * subreq ) ;
2006-01-12 12:38:35 +03:00
/*
* queue a wbsrv_call reply on a wbsrv_connection
* NOTE : that this implies talloc_free ( call ) ,
* use talloc_reference ( call ) if you need it after
* calling wbsrv_queue_reply
*/
NTSTATUS wbsrv_samba3_send_reply ( struct wbsrv_samba3_call * call )
{
2010-01-17 12:21:21 +03:00
struct wbsrv_connection * wbsrv_conn = call - > wbconn ;
struct tevent_req * subreq ;
2006-01-12 12:38:35 +03:00
NTSTATUS status ;
2010-01-17 12:21:21 +03:00
status = wbsrv_samba3_push_reply ( call ) ;
2006-01-12 12:38:35 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2010-06-26 21:43:51 +04:00
call - > out_iov [ 0 ] . iov_base = ( char * ) call - > out . data ;
2010-01-17 12:21:21 +03:00
call - > out_iov [ 0 ] . iov_len = call - > out . length ;
subreq = tstream_writev_queue_send ( call ,
wbsrv_conn - > conn - > event . ctx ,
wbsrv_conn - > tstream ,
wbsrv_conn - > send_queue ,
call - > out_iov , 1 ) ;
if ( subreq = = NULL ) {
wbsrv_terminate_connection ( wbsrv_conn , " wbsrv_call_loop: "
" no memory for tstream_writev_queue_send " ) ;
return NT_STATUS_NO_MEMORY ;
2006-01-12 12:38:35 +03:00
}
2010-01-17 12:21:21 +03:00
tevent_req_set_callback ( subreq , wbsrv_samba3_send_reply_done , call ) ;
2006-01-12 12:38:35 +03:00
return status ;
}
2010-01-17 12:21:21 +03:00
static void wbsrv_samba3_send_reply_done ( struct tevent_req * subreq )
{
struct wbsrv_samba3_call * call = tevent_req_callback_data ( subreq ,
struct wbsrv_samba3_call ) ;
int sys_errno ;
int rc ;
rc = tstream_writev_queue_recv ( subreq , & sys_errno ) ;
TALLOC_FREE ( subreq ) ;
if ( rc = = - 1 ) {
const char * reason ;
reason = talloc_asprintf ( call , " wbsrv_samba3_send_reply_done: "
" tstream_writev_queue_recv() - %d:%s " ,
sys_errno , strerror ( sys_errno ) ) ;
if ( reason = = NULL ) {
reason = " wbsrv_samba3_send_reply_done: "
" tstream_writev_queue_recv() failed " ;
}
wbsrv_terminate_connection ( call - > wbconn , reason ) ;
return ;
}
talloc_free ( call ) ;
}
NTSTATUS wbsrv_samba3_process ( struct wbsrv_samba3_call * call )
2006-01-12 12:38:35 +03:00
{
NTSTATUS status ;
2010-01-17 12:21:21 +03:00
status = wbsrv_samba3_pull_request ( call ) ;
2006-01-12 12:38:35 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2010-01-17 12:21:21 +03:00
2006-01-12 12:38:35 +03:00
status = wbsrv_samba3_handle_call ( call ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( call ) ;
return status ;
}
if ( call - > flags & WBSRV_CALL_FLAGS_REPLY_ASYNC ) {
return NT_STATUS_OK ;
}
status = wbsrv_samba3_send_reply ( call ) ;
return status ;
}