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
2005-10-28 17:42:00 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005
2005-09-22 22:35:08 +04: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"
# include "nsswitch/winbindd_nss.h"
# include "winbind/wb_server.h"
2005-09-26 01:01:56 +04:00
# include "winbind/wb_async_helpers.h"
# include "libcli/composite/composite.h"
2006-02-23 18:52:24 +03:00
# include "version.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/netlogon.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-03-07 16:36:26 +03:00
# include "auth/pam_errors.h"
2005-09-22 22:35:08 +04:00
2005-10-31 08:45:19 +03:00
/*
Send off the reply to an async Samba3 query , handling filling in the PAM , NTSTATUS and string errors .
*/
2005-10-31 07:17:51 +03:00
static void wbsrv_samba3_async_auth_epilogue ( NTSTATUS status ,
struct wbsrv_samba3_call * s3call )
2005-10-23 15:21:15 +04:00
{
2005-10-31 07:17:51 +03:00
struct winbindd_response * resp = & s3call - > response ;
2005-10-23 15:21:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
resp - > result = WINBINDD_ERROR ;
WBSRV_SAMBA3_SET_STRING ( resp - > data . auth . nt_status_string ,
nt_errstr ( status ) ) ;
WBSRV_SAMBA3_SET_STRING ( resp - > data . auth . error_string ,
2005-10-31 07:17:51 +03:00
get_friendly_nt_error_msg ( status ) ) ;
} else {
resp - > result = WINBINDD_OK ;
}
resp - > data . auth . pam_error = nt_status_to_pam ( status ) ;
resp - > data . auth . nt_status = NT_STATUS_V ( status ) ;
2006-01-12 12:38:35 +03:00
wbsrv_samba3_send_reply ( s3call ) ;
2005-10-31 07:17:51 +03:00
}
2005-10-31 08:45:19 +03:00
/*
Send of a generic reply to a Samba3 query
*/
2005-10-31 07:17:51 +03:00
static void wbsrv_samba3_async_epilogue ( NTSTATUS status ,
struct wbsrv_samba3_call * s3call )
{
struct winbindd_response * resp = & s3call - > response ;
if ( NT_STATUS_IS_OK ( status ) ) {
resp - > result = WINBINDD_OK ;
} else {
resp - > result = WINBINDD_ERROR ;
2005-10-23 15:21:15 +04:00
}
2006-01-12 12:38:35 +03:00
wbsrv_samba3_send_reply ( s3call ) ;
2005-10-23 15:21:15 +04:00
}
2005-10-31 08:45:19 +03:00
/*
Boilerplate commands , simple queries without network traffic
*/
2005-09-22 22:35:08 +04:00
NTSTATUS wbsrv_samba3_interface_version ( struct wbsrv_samba3_call * s3call )
{
s3call - > response . result = WINBINDD_OK ;
s3call - > response . data . interface_version = WINBIND_INTERFACE_VERSION ;
return NT_STATUS_OK ;
}
2005-09-26 17:42:42 +04:00
NTSTATUS wbsrv_samba3_info ( struct wbsrv_samba3_call * s3call )
{
s3call - > response . result = WINBINDD_OK ;
s3call - > response . data . info . winbind_separator = * lp_winbind_separator ( ) ;
2005-10-23 15:21:15 +04:00
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . info . samba_version ,
SAMBA_VERSION_STRING ) ;
2005-09-26 17:42:42 +04:00
return NT_STATUS_OK ;
}
NTSTATUS wbsrv_samba3_domain_name ( struct wbsrv_samba3_call * s3call )
{
s3call - > response . result = WINBINDD_OK ;
2005-10-23 15:21:15 +04:00
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . domain_name ,
lp_workgroup ( ) ) ;
2005-09-26 17:42:42 +04:00
return NT_STATUS_OK ;
}
NTSTATUS wbsrv_samba3_netbios_name ( struct wbsrv_samba3_call * s3call )
{
s3call - > response . result = WINBINDD_OK ;
2005-10-23 15:21:15 +04:00
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . netbios_name ,
lp_netbios_name ( ) ) ;
2005-09-26 17:42:42 +04:00
return NT_STATUS_OK ;
}
2005-09-22 22:35:08 +04:00
NTSTATUS wbsrv_samba3_priv_pipe_dir ( struct wbsrv_samba3_call * s3call )
{
s3call - > response . result = WINBINDD_OK ;
2005-10-23 15:21:15 +04:00
s3call - > response . extra_data =
smbd_tmp_path ( s3call , WINBINDD_SAMBA3_PRIVILEGED_SOCKET ) ;
2005-09-22 22:35:08 +04:00
NT_STATUS_HAVE_NO_MEMORY ( s3call - > response . extra_data ) ;
return NT_STATUS_OK ;
}
NTSTATUS wbsrv_samba3_ping ( struct wbsrv_samba3_call * s3call )
{
s3call - > response . result = WINBINDD_OK ;
return NT_STATUS_OK ;
}
2005-09-26 01:01:56 +04:00
2005-11-06 02:46:57 +03:00
#if 0
2005-10-31 08:45:19 +03:00
/*
Validate that we have a working pipe to the domain controller .
Return any NT error found in the process
*/
2005-10-08 20:25:00 +04:00
static void checkmachacc_recv_creds ( struct composite_context * ctx ) ;
2005-10-03 17:46:11 +04:00
NTSTATUS wbsrv_samba3_check_machacc ( struct wbsrv_samba3_call * s3call )
2005-09-26 01:01:56 +04:00
{
2005-10-01 20:36:04 +04:00
struct composite_context * ctx ;
2005-10-08 20:25:00 +04:00
DEBUG ( 5 , ( " wbsrv_samba3_check_machacc called \n " ) ) ;
2005-10-01 20:36:04 +04:00
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
2005-10-10 00:32:24 +04:00
ctx = wb_cmd_checkmachacc_send ( s3call - > call ) ;
2005-10-08 20:25:00 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
2005-10-01 20:36:04 +04:00
2005-10-08 20:25:00 +04:00
ctx - > async . fn = checkmachacc_recv_creds ;
2005-10-01 20:36:04 +04:00
ctx - > async . private_data = s3call ;
2005-10-08 20:25:00 +04:00
s3call - > call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
return NT_STATUS_OK ;
2005-09-26 01:01:56 +04:00
}
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
static void checkmachacc_recv_creds ( struct composite_context * ctx )
2005-10-03 17:46:11 +04:00
{
struct wbsrv_samba3_call * s3call =
2005-10-08 20:25:00 +04:00
talloc_get_type ( ctx - > async . private_data ,
2005-10-03 17:46:11 +04:00
struct wbsrv_samba3_call ) ;
NTSTATUS status ;
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
2005-10-10 00:32:24 +04:00
status = wb_cmd_checkmachacc_recv ( ctx ) ;
2005-10-23 15:21:15 +04:00
2005-10-31 07:17:51 +03:00
wbsrv_samba3_async_auth_epilogue ( status , s3call ) ;
2005-09-26 01:01:56 +04:00
}
2005-11-06 02:46:57 +03:00
# endif
2005-10-03 21:36:49 +04:00
2005-10-31 08:45:19 +03:00
/*
Find the name of a suitable domain controller , by query on the
netlogon pipe to the DC .
*/
2005-10-16 02:01:15 +04:00
static void getdcname_recv_dc ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_getdcname ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
2005-10-19 17:45:44 +04:00
struct wbsrv_service * service =
2006-01-12 12:38:35 +03:00
s3call - > wbconn - > listen_socket - > service ;
2005-10-16 02:01:15 +04:00
DEBUG ( 5 , ( " wbsrv_samba3_getdcname called \n " ) ) ;
2005-11-05 12:34:07 +03:00
ctx = wb_cmd_getdcname_send ( s3call , service ,
2005-10-16 02:01:15 +04:00
s3call - > request . domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
ctx - > async . fn = getdcname_recv_dc ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-16 02:01:15 +04:00
return NT_STATUS_OK ;
}
static void getdcname_recv_dc ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
const char * dcname ;
NTSTATUS status ;
status = wb_cmd_getdcname_recv ( ctx , s3call , & dcname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
s3call - > response . result = WINBINDD_OK ;
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . dc_name , dcname ) ;
2005-10-16 16:43:09 +04:00
done :
2005-10-23 15:21:15 +04:00
wbsrv_samba3_async_epilogue ( status , s3call ) ;
2005-10-16 16:43:09 +04:00
}
2005-10-31 08:45:19 +03:00
/*
Lookup a user ' s domain groups
*/
2005-10-16 16:43:09 +04:00
static void userdomgroups_recv_groups ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_userdomgroups ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
struct dom_sid * sid ;
DEBUG ( 5 , ( " wbsrv_samba3_userdomgroups called \n " ) ) ;
sid = dom_sid_parse_talloc ( s3call , s3call - > request . data . sid ) ;
if ( sid = = NULL ) {
DEBUG ( 5 , ( " Could not parse sid %s \n " ,
s3call - > request . data . sid ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-10-19 17:45:44 +04:00
ctx = wb_cmd_userdomgroups_send (
2006-01-12 12:38:35 +03:00
s3call , s3call - > wbconn - > listen_socket - > service , sid ) ;
2005-10-16 16:43:09 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
ctx - > async . fn = userdomgroups_recv_groups ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-16 16:43:09 +04:00
return NT_STATUS_OK ;
}
static void userdomgroups_recv_groups ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
int i , num_sids ;
struct dom_sid * * sids ;
char * sids_string ;
NTSTATUS status ;
status = wb_cmd_userdomgroups_recv ( ctx , s3call , & num_sids , & sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
sids_string = talloc_strdup ( s3call , " " ) ;
if ( sids_string = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < num_sids ; i + + ) {
sids_string = talloc_asprintf_append (
sids_string , " %s \n " , dom_sid_string ( s3call , sids [ i ] ) ) ;
}
if ( sids_string = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
s3call - > response . result = WINBINDD_OK ;
s3call - > response . extra_data = sids_string ;
s3call - > response . length + = strlen ( sids_string ) + 1 ;
s3call - > response . data . num_entries = num_sids ;
2005-10-16 02:01:15 +04:00
done :
2005-10-23 15:21:15 +04:00
wbsrv_samba3_async_epilogue ( status , s3call ) ;
2005-10-16 02:01:15 +04:00
}
2005-10-31 08:45:19 +03:00
/*
Lookup the list of SIDs for a user
*/
2005-10-19 17:45:44 +04:00
static void usersids_recv_sids ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_usersids ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
struct dom_sid * sid ;
DEBUG ( 5 , ( " wbsrv_samba3_usersids called \n " ) ) ;
sid = dom_sid_parse_talloc ( s3call , s3call - > request . data . sid ) ;
if ( sid = = NULL ) {
DEBUG ( 5 , ( " Could not parse sid %s \n " ,
s3call - > request . data . sid ) ) ;
return NT_STATUS_NO_MEMORY ;
}
ctx = wb_cmd_usersids_send (
2006-01-12 12:38:35 +03:00
s3call , s3call - > wbconn - > listen_socket - > service , sid ) ;
2005-10-19 17:45:44 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
ctx - > async . fn = usersids_recv_sids ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-19 17:45:44 +04:00
return NT_STATUS_OK ;
}
static void usersids_recv_sids ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
int i , num_sids ;
struct dom_sid * * sids ;
char * sids_string ;
NTSTATUS status ;
status = wb_cmd_usersids_recv ( ctx , s3call , & num_sids , & sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
sids_string = talloc_strdup ( s3call , " " ) ;
if ( sids_string = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < num_sids ; i + + ) {
sids_string = talloc_asprintf_append (
sids_string , " %s \n " , dom_sid_string ( s3call , sids [ i ] ) ) ;
if ( sids_string = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
}
s3call - > response . result = WINBINDD_OK ;
s3call - > response . extra_data = sids_string ;
s3call - > response . length + = strlen ( sids_string ) ;
s3call - > response . data . num_entries = num_sids ;
/* Hmmmm. Nasty protocol -- who invented the zeros between the
* SIDs ? Hmmm . Could have been me - - vl */
while ( * sids_string ! = ' \0 ' ) {
if ( ( * sids_string ) = = ' \n ' ) {
* sids_string = ' \0 ' ;
}
sids_string + = 1 ;
}
done :
2005-10-23 15:21:15 +04:00
wbsrv_samba3_async_epilogue ( status , s3call ) ;
2005-10-19 17:45:44 +04:00
}
2005-10-31 08:45:19 +03:00
/*
Lookup a DOMAIN \ \ user style name , and return a SID
*/
2005-10-07 23:08:51 +04:00
static void lookupname_recv_sid ( struct composite_context * ctx ) ;
2005-10-03 21:36:49 +04:00
NTSTATUS wbsrv_samba3_lookupname ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
2005-10-19 17:45:44 +04:00
struct wbsrv_service * service =
2006-01-12 12:38:35 +03:00
s3call - > wbconn - > listen_socket - > service ;
2005-10-03 21:36:49 +04:00
DEBUG ( 5 , ( " wbsrv_samba3_lookupname called \n " ) ) ;
2005-10-31 23:28:08 +03:00
ctx = wb_cmd_lookupname_send ( s3call , service ,
2005-10-19 17:45:44 +04:00
s3call - > request . data . name . dom_name ,
2005-10-08 20:25:00 +04:00
s3call - > request . data . name . name ) ;
2005-10-03 21:36:49 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
/* setup the callbacks */
2005-10-08 20:25:00 +04:00
ctx - > async . fn = lookupname_recv_sid ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-03 21:36:49 +04:00
return NT_STATUS_OK ;
}
2005-10-07 23:08:51 +04:00
static void lookupname_recv_sid ( struct composite_context * ctx )
{
2005-10-08 20:25:00 +04:00
struct wbsrv_samba3_call * s3call =
2005-10-07 23:08:51 +04:00
talloc_get_type ( ctx - > async . private_data ,
2005-10-08 20:25:00 +04:00
struct wbsrv_samba3_call ) ;
2005-10-07 23:08:51 +04:00
struct wb_sid_object * sid ;
2005-10-08 20:25:00 +04:00
NTSTATUS status ;
2005-10-07 23:08:51 +04:00
2005-10-08 20:25:00 +04:00
status = wb_cmd_lookupname_recv ( ctx , s3call , & sid ) ;
2005-10-07 23:08:51 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
2005-10-08 20:25:00 +04:00
s3call - > response . result = WINBINDD_OK ;
s3call - > response . data . sid . type = sid - > type ;
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . sid . sid ,
dom_sid_string ( s3call , sid - > sid ) ) ;
2005-10-07 23:08:51 +04:00
done :
2005-10-23 15:21:15 +04:00
wbsrv_samba3_async_epilogue ( status , s3call ) ;
2005-10-07 23:08:51 +04:00
}
2005-10-09 16:13:05 +04:00
2005-10-31 08:45:19 +03:00
/*
Lookup a SID , and return a DOMAIN \ \ user style name
*/
2005-10-19 17:45:44 +04:00
static void lookupsid_recv_name ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_lookupsid ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
struct wbsrv_service * service =
2006-01-12 12:38:35 +03:00
s3call - > wbconn - > listen_socket - > service ;
2005-10-19 17:45:44 +04:00
struct dom_sid * sid ;
DEBUG ( 5 , ( " wbsrv_samba3_lookupsid called \n " ) ) ;
sid = dom_sid_parse_talloc ( s3call , s3call - > request . data . sid ) ;
if ( sid = = NULL ) {
DEBUG ( 5 , ( " Could not parse sid %s \n " ,
s3call - > request . data . sid ) ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-10-31 23:28:08 +03:00
ctx = wb_cmd_lookupsid_send ( s3call , service , sid ) ;
2005-10-19 17:45:44 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
/* setup the callbacks */
ctx - > async . fn = lookupsid_recv_name ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-19 17:45:44 +04:00
return NT_STATUS_OK ;
}
static void lookupsid_recv_name ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
struct wb_sid_object * sid ;
NTSTATUS status ;
status = wb_cmd_lookupsid_recv ( ctx , s3call , & sid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
s3call - > response . result = WINBINDD_OK ;
s3call - > response . data . name . type = sid - > type ;
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . name . dom_name ,
sid - > domain ) ;
WBSRV_SAMBA3_SET_STRING ( s3call - > response . data . name . name , sid - > name ) ;
done :
2005-10-23 15:21:15 +04:00
wbsrv_samba3_async_epilogue ( status , s3call ) ;
2005-10-19 17:45:44 +04:00
}
2005-10-31 08:45:19 +03:00
/*
Challenge - response authentication . This interface is used by
ntlm_auth and the smbd auth subsystem to pass NTLM authentication
requests along a common pipe to the domain controller .
The return value ( in the async reply ) may include the ' info3 '
( effectivly most things you would want to know about the user ) , or
the NT and LM session keys seperated .
*/
2005-10-15 01:05:45 +04:00
static void pam_auth_crap_recv ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_pam_auth_crap ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
2005-11-05 12:34:07 +03:00
struct wbsrv_service * service =
2006-01-12 12:38:35 +03:00
s3call - > wbconn - > listen_socket - > service ;
2005-10-13 00:22:45 +04:00
DATA_BLOB chal , nt_resp , lm_resp ;
DEBUG ( 5 , ( " wbsrv_samba3_pam_auth_crap called \n " ) ) ;
2005-10-31 07:17:51 +03:00
chal . data = s3call - > request . data . auth_crap . chal ;
chal . length = sizeof ( s3call - > request . data . auth_crap . chal ) ;
nt_resp . data = ( uint8_t * ) s3call - > request . data . auth_crap . nt_resp ;
nt_resp . length = s3call - > request . data . auth_crap . nt_resp_len ;
lm_resp . data = ( uint8_t * ) s3call - > request . data . auth_crap . lm_resp ;
lm_resp . length = s3call - > request . data . auth_crap . lm_resp_len ;
2005-10-13 00:22:45 +04:00
2005-10-15 01:05:45 +04:00
ctx = wb_cmd_pam_auth_crap_send (
2005-11-05 12:34:07 +03:00
s3call , service ,
2005-10-31 07:17:51 +03:00
s3call - > request . data . auth_crap . logon_parameters ,
2005-10-15 01:41:08 +04:00
s3call - > request . data . auth_crap . domain ,
s3call - > request . data . auth_crap . user ,
2005-10-15 01:05:45 +04:00
s3call - > request . data . auth_crap . workstation ,
chal , nt_resp , lm_resp ) ;
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
ctx - > async . fn = pam_auth_crap_recv ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-15 01:05:45 +04:00
return NT_STATUS_OK ;
}
static void pam_auth_crap_recv ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
NTSTATUS status ;
DATA_BLOB info3 ;
struct netr_UserSessionKey user_session_key ;
struct netr_LMSessionKey lm_key ;
2005-10-28 17:42:00 +04:00
char * unix_username ;
2005-10-15 01:05:45 +04:00
status = wb_cmd_pam_auth_crap_recv ( ctx , s3call , & info3 ,
2005-10-28 17:42:00 +04:00
& user_session_key , & lm_key , & unix_username ) ;
2005-10-15 01:05:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
if ( s3call - > request . flags & WBFLAG_PAM_USER_SESSION_KEY ) {
memcpy ( s3call - > response . data . auth . user_session_key ,
& user_session_key . key ,
sizeof ( s3call - > response . data . auth . user_session_key ) ) ;
}
if ( s3call - > request . flags & WBFLAG_PAM_INFO3_NDR ) {
s3call - > response . extra_data = info3 . data ;
s3call - > response . length + = info3 . length ;
}
if ( s3call - > request . flags & WBFLAG_PAM_LMKEY ) {
memcpy ( s3call - > response . data . auth . first_8_lm_hash ,
lm_key . key ,
sizeof ( s3call - > response . data . auth . first_8_lm_hash ) ) ;
}
2005-10-28 17:42:00 +04:00
if ( s3call - > request . flags & WBFLAG_PAM_UNIX_NAME ) {
s3call - > response . extra_data = unix_username ;
s3call - > response . length + = strlen ( unix_username ) + 1 ;
}
done :
2005-10-31 07:17:51 +03:00
wbsrv_samba3_async_auth_epilogue ( status , s3call ) ;
2005-10-28 17:42:00 +04:00
}
2005-10-31 08:45:19 +03:00
/* Helper function: Split a domain\\user string into it's parts,
* because the client supplies it as one string */
2005-10-28 17:42:00 +04:00
static BOOL samba3_parse_domuser ( TALLOC_CTX * mem_ctx , const char * domuser ,
char * * domain , char * * user )
{
char * p = strchr ( domuser , * lp_winbind_separator ( ) ) ;
if ( p = = NULL ) {
* domain = talloc_strdup ( mem_ctx , lp_workgroup ( ) ) ;
} else {
* domain = talloc_strndup ( mem_ctx , domuser ,
PTR_DIFF ( p , domuser ) ) ;
domuser = p + 1 ;
}
* user = talloc_strdup ( mem_ctx , domuser ) ;
return ( ( * domain ! = NULL ) & & ( * user ! = NULL ) ) ;
}
2005-10-31 08:45:19 +03:00
/* Plaintext authentication
This interface is used by ntlm_auth in it ' s ' basic ' authentication
mode , as well as by pam_winbind to authenticate users where we are
given a plaintext password .
*/
2005-10-28 17:42:00 +04:00
static void pam_auth_recv ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_pam_auth ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
2005-11-05 12:34:07 +03:00
struct wbsrv_service * service =
2006-01-12 12:38:35 +03:00
s3call - > wbconn - > listen_socket - > service ;
2005-10-28 17:42:00 +04:00
char * user , * domain ;
2005-11-05 12:34:07 +03:00
2005-10-28 17:42:00 +04:00
if ( ! samba3_parse_domuser ( s3call ,
s3call - > request . data . auth . user ,
& domain , & user ) ) {
return NT_STATUS_NO_SUCH_USER ;
}
2005-11-05 12:34:07 +03:00
ctx = wb_cmd_pam_auth_send ( s3call , service , domain , user ,
s3call - > request . data . auth . pass ) ;
2005-10-28 17:42:00 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
ctx - > async . fn = pam_auth_recv ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-28 17:42:00 +04:00
return NT_STATUS_OK ;
}
static void pam_auth_recv ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
NTSTATUS status ;
status = wb_cmd_pam_auth_recv ( ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
2005-10-15 01:05:45 +04:00
done :
2005-10-31 07:17:51 +03:00
wbsrv_samba3_async_auth_epilogue ( status , s3call ) ;
2005-10-09 16:13:05 +04:00
}
2005-10-20 01:53:03 +04:00
2005-10-31 08:45:19 +03:00
/*
List trusted domains
*/
2005-10-20 01:53:03 +04:00
static void list_trustdom_recv_doms ( struct composite_context * ctx ) ;
NTSTATUS wbsrv_samba3_list_trustdom ( struct wbsrv_samba3_call * s3call )
{
struct composite_context * ctx ;
struct wbsrv_service * service =
2006-01-12 12:38:35 +03:00
s3call - > wbconn - > listen_socket - > service ;
2005-10-20 01:53:03 +04:00
DEBUG ( 5 , ( " wbsrv_samba3_list_trustdom called \n " ) ) ;
2005-11-05 12:34:07 +03:00
ctx = wb_cmd_list_trustdoms_send ( s3call , service ) ;
2005-10-20 01:53:03 +04:00
NT_STATUS_HAVE_NO_MEMORY ( ctx ) ;
ctx - > async . fn = list_trustdom_recv_doms ;
ctx - > async . private_data = s3call ;
2006-01-12 12:38:35 +03:00
s3call - > flags | = WBSRV_CALL_FLAGS_REPLY_ASYNC ;
2005-10-20 01:53:03 +04:00
return NT_STATUS_OK ;
}
static void list_trustdom_recv_doms ( struct composite_context * ctx )
{
struct wbsrv_samba3_call * s3call =
talloc_get_type ( ctx - > async . private_data ,
struct wbsrv_samba3_call ) ;
int i , num_domains ;
struct wb_dom_info * * domains ;
NTSTATUS status ;
char * result ;
status = wb_cmd_list_trustdoms_recv ( ctx , s3call , & num_domains ,
& domains ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
result = talloc_strdup ( s3call , " " ) ;
if ( result = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < num_domains ; i + + ) {
result = talloc_asprintf_append (
result , " %s \\ %s \\ %s " ,
domains [ i ] - > name , domains [ i ] - > name ,
dom_sid_string ( s3call , domains [ i ] - > sid ) ) ;
}
if ( result = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
s3call - > response . result = WINBINDD_OK ;
if ( num_domains > 0 ) {
s3call - > response . extra_data = result ;
s3call - > response . length + = strlen ( result ) + 1 ;
}
done :
2005-10-23 15:21:15 +04:00
wbsrv_samba3_async_epilogue ( status , s3call ) ;
2005-10-20 01:53:03 +04:00
}