2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
2008-05-05 13:21:18 +10:00
Authenticate by using a remote server
Copyright ( C ) Andrew Bartlett 2001 - 2002 , 2008
Copyright ( C ) Jelmer Vernooij 2002
Copyright ( C ) Stefan Metzmacher 2005
2003-08-13 01:53:07 +00: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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 01:53:07 +00: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 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
# include "includes.h"
2008-05-05 13:21:18 +10:00
# include "auth/auth.h"
# include "auth/credentials/credentials.h"
# include "libcli/security/security.h"
# include "libcli/smb_composite/smb_composite.h"
# include "param/param.h"
# include "libcli/resolve/resolve.h"
/* This version of 'security=server' rewirtten from scratch for Samba4
* libraries in 2008 */
static NTSTATUS server_want_check ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info )
2003-08-13 01:53:07 +00:00
{
2008-05-05 13:21:18 +10:00
return NT_STATUS_OK ;
}
/**
* The challenge from the target server , when operating in security = server
* */
2009-12-14 20:32:47 +11:00
static NTSTATUS server_get_challenge ( struct auth_method_context * ctx , TALLOC_CTX * mem_ctx , uint8_t chal [ 8 ] )
2008-05-05 13:21:18 +10:00
{
struct smb_composite_connect io ;
struct smbcli_options smb_options ;
const char * * host_list ;
NTSTATUS status ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
/* Make a connection to the target server, found by 'password server' in smb.conf */
2003-08-13 01:53:07 +00:00
2010-07-16 14:32:42 +10:00
lpcfg_smbcli_options ( ctx - > auth_ctx - > lp_ctx , & smb_options ) ;
2008-05-05 13:21:18 +10:00
/* Make a negprot, WITHOUT SPNEGO, so we get a challenge nice an easy */
io . in . options . use_spnego = false ;
/* Hope we don't get * (the default), as this won't work... */
2010-07-16 14:32:42 +10:00
host_list = lpcfg_passwordserver ( ctx - > auth_ctx - > lp_ctx ) ;
2008-05-05 13:21:18 +10:00
if ( ! host_list ) {
return NT_STATUS_INTERNAL_ERROR ;
2003-08-13 01:53:07 +00:00
}
2008-05-05 13:21:18 +10:00
io . in . dest_host = host_list [ 0 ] ;
if ( strequal ( io . in . dest_host , " * " ) ) {
return NT_STATUS_INTERNAL_ERROR ;
2003-08-13 01:53:07 +00:00
}
2010-07-16 14:32:42 +10:00
io . in . dest_ports = lpcfg_smb_ports ( ctx - > auth_ctx - > lp_ctx ) ;
io . in . socket_options = lpcfg_socket_options ( ctx - > auth_ctx - > lp_ctx ) ;
io . in . gensec_settings = lpcfg_gensec_settings ( mem_ctx , ctx - > auth_ctx - > lp_ctx ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
io . in . called_name = strupper_talloc ( mem_ctx , io . in . dest_host ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
/* We don't want to get as far as the session setup */
2008-08-01 15:19:27 +02:00
io . in . credentials = cli_credentials_init_anon ( mem_ctx ) ;
2008-08-01 17:22:54 +02:00
cli_credentials_set_workstation ( io . in . credentials ,
2010-07-16 14:32:42 +10:00
lpcfg_netbios_name ( ctx - > auth_ctx - > lp_ctx ) ,
2008-08-01 17:22:54 +02:00
CRED_SPECIFIED ) ;
2008-05-05 13:21:18 +10:00
io . in . service = NULL ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
io . in . workgroup = " " ; /* only used with SPNEGO, disabled above */
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
io . in . options = smb_options ;
2008-10-24 13:13:27 +02:00
2010-07-16 14:32:42 +10:00
lpcfg_smbcli_session_options ( ctx - > auth_ctx - > lp_ctx , & io . in . session_options ) ;
2003-08-13 01:53:07 +00:00
2010-07-16 14:32:42 +10:00
status = smb_composite_connect ( & io , mem_ctx , lpcfg_resolve_context ( ctx - > auth_ctx - > lp_ctx ) ,
2008-05-05 13:21:18 +10:00
ctx - > auth_ctx - > event_ctx ) ;
2008-08-01 15:53:01 +02:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2009-12-14 20:32:47 +11:00
if ( io . out . tree - > session - > transport - > negotiate . secblob . length ! = 8 ) {
return NT_STATUS_INTERNAL_ERROR ;
}
memcpy ( chal , io . out . tree - > session - > transport - > negotiate . secblob . data , 8 ) ;
2008-08-01 15:53:01 +02:00
ctx - > private_data = talloc_steal ( ctx , io . out . tree - > session ) ;
2008-05-05 13:21:18 +10:00
return NT_STATUS_OK ;
2003-08-13 01:53:07 +00:00
}
2008-05-05 13:21:18 +10:00
/**
* Return an error based on username
*
* This function allows the testing of obsure errors , as well as the generation
* of NT_STATUS - > DOS error mapping tables .
*
* This module is of no value to end - users .
*
* The password is ignored .
*
* @ return An NTSTATUS value based on the username
* */
static NTSTATUS server_check_password ( struct auth_method_context * ctx ,
TALLOC_CTX * mem_ctx ,
const struct auth_usersupplied_info * user_info ,
struct auth_serversupplied_info * * _server_info )
2003-08-13 01:53:07 +00:00
{
2008-05-05 13:21:18 +10:00
NTSTATUS nt_status ;
struct auth_serversupplied_info * server_info ;
struct cli_credentials * creds ;
struct smb_composite_sesssetup session_setup ;
struct smbcli_session * session = talloc_get_type ( ctx - > private_data , struct smbcli_session ) ;
creds = cli_credentials_init ( mem_ctx ) ;
NT_STATUS_HAVE_NO_MEMORY ( creds ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
cli_credentials_set_username ( creds , user_info - > client . account_name , CRED_SPECIFIED ) ;
cli_credentials_set_domain ( creds , user_info - > client . domain_name , CRED_SPECIFIED ) ;
switch ( user_info - > password_state ) {
case AUTH_PASSWORD_PLAIN :
cli_credentials_set_password ( creds , user_info - > password . plaintext ,
CRED_SPECIFIED ) ;
break ;
case AUTH_PASSWORD_HASH :
cli_credentials_set_nt_hash ( creds , user_info - > password . hash . nt ,
CRED_SPECIFIED ) ;
break ;
case AUTH_PASSWORD_RESPONSE :
cli_credentials_set_ntlm_response ( creds , & user_info - > password . response . lanman , & user_info - > password . response . nt , CRED_SPECIFIED ) ;
break ;
2003-08-13 01:53:07 +00:00
}
2008-05-05 13:21:18 +10:00
session_setup . in . sesskey = session - > transport - > negotiate . sesskey ;
session_setup . in . capabilities = session - > transport - > negotiate . capabilities ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
session_setup . in . credentials = creds ;
session_setup . in . workgroup = " " ; /* Only used with SPNEGO, which we are not doing */
2010-07-16 14:32:42 +10:00
session_setup . in . gensec_settings = lpcfg_gensec_settings ( session , ctx - > auth_ctx - > lp_ctx ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
/* Check password with remove server - this should be async some day */
nt_status = smb_composite_sesssetup ( session , & session_setup ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
2003-08-13 01:53:07 +00:00
}
2008-05-05 13:21:18 +10:00
server_info = talloc ( mem_ctx , struct auth_serversupplied_info ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > account_sid = dom_sid_parse_talloc ( server_info , SID_NT_ANONYMOUS ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > account_sid ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
/* is this correct? */
server_info - > primary_group_sid = dom_sid_parse_talloc ( server_info , SID_BUILTIN_GUESTS ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > primary_group_sid ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > n_domain_groups = 0 ;
server_info - > domain_groups = NULL ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
/* annoying, but the Anonymous really does have a session key,
and it is all zeros ! */
server_info - > user_session_key = data_blob ( NULL , 0 ) ;
server_info - > lm_session_key = data_blob ( NULL , 0 ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > account_name = talloc_strdup ( server_info , user_info - > client . account_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > account_name ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > domain_name = talloc_strdup ( server_info , user_info - > client . domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > domain_name ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > full_name = NULL ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > logon_script = talloc_strdup ( server_info , " " ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > logon_script ) ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > profile_path = talloc_strdup ( server_info , " " ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > profile_path ) ;
server_info - > home_directory = talloc_strdup ( server_info , " " ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > home_directory ) ;
server_info - > home_drive = talloc_strdup ( server_info , " " ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info - > home_drive ) ;
server_info - > last_logon = 0 ;
server_info - > last_logoff = 0 ;
server_info - > acct_expiry = 0 ;
server_info - > last_password_change = 0 ;
server_info - > allow_password_change = 0 ;
server_info - > force_password_change = 0 ;
server_info - > logon_count = 0 ;
server_info - > bad_password_count = 0 ;
server_info - > acct_flags = ACB_NORMAL ;
2003-08-13 01:53:07 +00:00
2008-05-05 13:21:18 +10:00
server_info - > authenticated = false ;
* _server_info = server_info ;
return nt_status ;
2003-08-13 01:53:07 +00:00
}
2008-05-05 13:21:18 +10:00
static const struct auth_operations server_auth_ops = {
. name = " server " ,
. get_challenge = server_get_challenge ,
. want_check = server_want_check ,
. check_password = server_check_password
} ;
_PUBLIC_ NTSTATUS auth_server_init ( void )
2003-08-13 01:53:07 +00:00
{
2008-05-05 13:21:18 +10:00
NTSTATUS ret ;
ret = auth_register ( & server_auth_ops ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 0 , ( " Failed to register 'server' auth backend! \n " ) ) ;
return ret ;
2003-08-13 01:53:07 +00:00
}
2008-05-05 13:21:18 +10:00
return ret ;
2003-08-13 01:53:07 +00:00
}