2005-10-12 20:22:45 +00:00
/*
Unix SMB / CIFS implementation .
Authenticate a user
Copyright ( C ) Volker Lendecke 2005
2005-10-28 13:42:00 +00:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005
2005-10-12 20:22:45 +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
2005-10-12 20:22:45 +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/>.
2005-10-12 20:22:45 +00:00
*/
# include "includes.h"
# include "libcli/composite/composite.h"
# include "winbind/wb_server.h"
2005-11-05 09:34:07 +00:00
# include "smbd/service_task.h"
2006-11-07 00:48:36 +00:00
# include "auth/credentials/credentials.h"
2006-03-14 15:03:25 +00:00
# include "libcli/auth/libcli_auth.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/ndr_netlogon.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2005-10-12 20:22:45 +00:00
2005-10-31 06:01:55 +00:00
/* Oh, there is so much to keep an eye on when authenticating a user. Oh my! */
2005-10-12 20:22:45 +00:00
struct pam_auth_crap_state {
struct composite_context * ctx ;
2008-12-29 20:24:57 +01:00
struct tevent_context * event_ctx ;
2007-12-04 19:33:00 +01:00
struct loadparm_context * lp_ctx ;
2007-07-16 11:27:29 +00:00
struct winbind_SamLogon * req ;
2006-07-29 07:56:03 +00:00
char * unix_username ;
2005-10-12 20:22:45 +00:00
struct netr_NetworkInfo ninfo ;
struct netr_LogonSamLogon r ;
2007-07-16 11:27:29 +00:00
const char * user_name ;
const char * domain_name ;
2005-10-12 20:22:45 +00:00
struct netr_UserSessionKey user_session_key ;
struct netr_LMSessionKey lm_key ;
DATA_BLOB info3 ;
} ;
2005-11-05 09:34:07 +00:00
/*
* NTLM authentication .
2005-10-31 06:01:55 +00:00
*/
2007-07-16 11:27:29 +00:00
static void pam_auth_crap_recv_logon ( struct composite_context * ctx ) ;
2005-11-05 09:34:07 +00:00
struct composite_context * wb_cmd_pam_auth_crap_send ( TALLOC_CTX * mem_ctx ,
struct wbsrv_service * service ,
2005-10-31 04:17:51 +00:00
uint32_t logon_parameters ,
2005-10-14 21:05:45 +00:00
const char * domain ,
const char * user ,
const char * workstation ,
DATA_BLOB chal ,
DATA_BLOB nt_resp ,
DATA_BLOB lm_resp )
2005-10-12 20:22:45 +00:00
{
2005-11-05 09:34:07 +00:00
struct composite_context * result , * ctx ;
2005-10-12 20:22:45 +00:00
struct pam_auth_crap_state * state ;
2007-07-16 11:27:29 +00:00
struct netr_NetworkInfo * ninfo ;
DATA_BLOB tmp_nt_resp , tmp_lm_resp ;
2005-10-12 20:22:45 +00:00
2007-04-30 16:52:30 +00:00
result = composite_create ( mem_ctx , service - > task - > event_ctx ) ;
2005-11-05 09:34:07 +00:00
if ( result = = NULL ) goto failed ;
2005-10-12 20:22:45 +00:00
2005-11-05 09:34:07 +00:00
state = talloc ( result , struct pam_auth_crap_state ) ;
if ( state = = NULL ) goto failed ;
state - > ctx = result ;
2007-12-04 19:33:00 +01:00
state - > lp_ctx = service - > task - > lp_ctx ;
2005-11-05 09:34:07 +00:00
result - > private_data = state ;
2005-10-12 20:22:45 +00:00
2007-07-16 11:27:29 +00:00
state - > req = talloc ( state , struct winbind_SamLogon ) ;
state - > req - > in . logon_level = 2 ;
state - > req - > in . validation_level = 3 ;
ninfo = state - > req - > in . logon . network = talloc ( state , struct netr_NetworkInfo ) ;
if ( ninfo = = NULL ) goto failed ;
ninfo - > identity_info . account_name . string = talloc_strdup ( state , user ) ;
ninfo - > identity_info . domain_name . string = talloc_strdup ( state , domain ) ;
ninfo - > identity_info . parameter_control = logon_parameters ;
ninfo - > identity_info . logon_id_low = 0 ;
ninfo - > identity_info . logon_id_high = 0 ;
ninfo - > identity_info . workstation . string = talloc_strdup ( state , workstation ) ;
SMB_ASSERT ( chal . length = = sizeof ( ninfo - > challenge ) ) ;
memcpy ( ninfo - > challenge , chal . data ,
sizeof ( ninfo - > challenge ) ) ;
tmp_nt_resp = data_blob_talloc ( ninfo , nt_resp . data , nt_resp . length ) ;
if ( ( nt_resp . data ! = NULL ) & &
( tmp_nt_resp . data = = NULL ) ) goto failed ;
2005-10-31 04:17:51 +00:00
2007-07-16 11:27:29 +00:00
tmp_lm_resp = data_blob_talloc ( ninfo , lm_resp . data , lm_resp . length ) ;
if ( ( lm_resp . data ! = NULL ) & &
( tmp_lm_resp . data = = NULL ) ) goto failed ;
2005-10-12 20:22:45 +00:00
2007-07-16 11:27:29 +00:00
ninfo - > nt . length = tmp_nt_resp . length ;
ninfo - > nt . data = tmp_nt_resp . data ;
ninfo - > lm . length = tmp_lm_resp . length ;
ninfo - > lm . data = tmp_lm_resp . data ;
2005-10-12 20:22:45 +00:00
2006-07-28 11:51:07 +00:00
state - > unix_username = NULL ;
2007-07-16 11:27:29 +00:00
ctx = wb_sam_logon_send ( mem_ctx , service , state - > req ) ;
2005-11-05 09:34:07 +00:00
if ( ctx = = NULL ) goto failed ;
2007-07-16 11:27:29 +00:00
composite_continue ( result , ctx , pam_auth_crap_recv_logon , state ) ;
2005-11-05 09:34:07 +00:00
return result ;
2005-10-12 20:22:45 +00:00
failed :
2005-11-05 09:34:07 +00:00
talloc_free ( result ) ;
2005-10-12 20:22:45 +00:00
return NULL ;
}
2005-10-31 06:01:55 +00:00
/*
NTLM Authentication
Send of a SamLogon request to authenticate a user .
*/
2007-07-16 11:27:29 +00:00
static void pam_auth_crap_recv_logon ( struct composite_context * ctx )
2005-10-12 20:22:45 +00:00
{
2007-07-16 11:27:29 +00:00
DATA_BLOB tmp_blob ;
2007-11-09 19:24:51 +01:00
enum ndr_err_code ndr_err ;
2007-07-16 11:27:29 +00:00
struct netr_SamBaseInfo * base ;
2005-10-12 20:22:45 +00:00
struct pam_auth_crap_state * state =
2005-11-05 09:34:07 +00:00
talloc_get_type ( ctx - > async . private_data ,
struct pam_auth_crap_state ) ;
2007-07-16 11:27:29 +00:00
state - > ctx - > status = wb_sam_logon_recv ( ctx , state , state - > req ) ;
2007-07-15 10:46:34 +00:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-12 20:22:45 +00:00
2007-11-09 19:24:51 +01:00
ndr_err = ndr_push_struct_blob (
2008-02-25 12:51:55 +01:00
& tmp_blob , state , lp_iconv_convenience ( state - > lp_ctx ) ,
2008-01-01 22:05:05 -06:00
state - > req - > out . validation . sam3 ,
2005-10-12 20:22:45 +00:00
( ndr_push_flags_fn_t ) ndr_push_netr_SamInfo3 ) ;
2007-11-09 19:24:51 +01:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
state - > ctx - > status = ndr_map_error2ntstatus ( ndr_err ) ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
}
2005-10-31 06:01:55 +00:00
/* The Samba3 protocol is a bit broken (due to non-IDL
* heritage , so for compatability we must add a non - zero 4
* bytes to the info3 */
2005-10-12 20:22:45 +00:00
state - > info3 = data_blob_talloc ( state , NULL , tmp_blob . length + 4 ) ;
2005-11-05 09:34:07 +00:00
if ( composite_nomem ( state - > info3 . data , state - > ctx ) ) return ;
2005-10-12 20:22:45 +00:00
SIVAL ( state - > info3 . data , 0 , 1 ) ;
memcpy ( state - > info3 . data + 4 , tmp_blob . data , tmp_blob . length ) ;
2007-07-16 11:27:29 +00:00
base = & state - > req - > out . validation . sam3 - > base ;
2005-10-12 20:22:45 +00:00
state - > user_session_key = base - > key ;
state - > lm_key = base - > LMSessKey ;
2005-10-31 06:01:55 +00:00
/* Give the caller the most accurate username possible.
* Assists where case sensitive comparisons may be done by our
* ntlm_auth callers */
2005-10-28 13:42:00 +00:00
if ( base - > account_name . string ) {
state - > user_name = base - > account_name . string ;
talloc_steal ( state , base - > account_name . string ) ;
}
if ( base - > domain . string ) {
state - > domain_name = base - > domain . string ;
talloc_steal ( state , base - > domain . string ) ;
}
2006-07-28 11:51:07 +00:00
state - > unix_username = talloc_asprintf ( state , " %s%s%s " ,
state - > domain_name ,
2007-12-04 19:33:00 +01:00
lp_winbind_separator ( state - > lp_ctx ) ,
2006-07-28 11:51:07 +00:00
state - > user_name ) ;
if ( composite_nomem ( state - > unix_username , state - > ctx ) ) return ;
2005-11-05 09:34:07 +00:00
composite_done ( state - > ctx ) ;
2005-10-12 20:22:45 +00:00
}
2007-04-29 21:40:48 +00:00
/* Having received a NTLM authentication reply, parse out the useful
* reply data for the caller */
2005-10-14 21:05:45 +00:00
NTSTATUS wb_cmd_pam_auth_crap_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * info3 ,
struct netr_UserSessionKey * user_session_key ,
2005-10-28 13:42:00 +00:00
struct netr_LMSessionKey * lm_key ,
char * * unix_username )
2005-10-12 20:22:45 +00:00
{
2005-10-23 17:22:00 +00:00
struct pam_auth_crap_state * state =
talloc_get_type ( c - > private_data , struct pam_auth_crap_state ) ;
2005-10-12 20:22:45 +00:00
NTSTATUS status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
info3 - > length = state - > info3 . length ;
info3 - > data = talloc_steal ( mem_ctx , state - > info3 . data ) ;
* user_session_key = state - > user_session_key ;
* lm_key = state - > lm_key ;
2006-07-28 11:51:07 +00:00
* unix_username = talloc_steal ( mem_ctx , state - > unix_username ) ;
2005-10-12 20:22:45 +00:00
}
2005-10-23 17:22:00 +00:00
talloc_free ( state ) ;
2005-10-12 20:22:45 +00:00
return status ;
}
2007-04-29 21:40:48 +00:00
/* Handle plaintext authentication, by encrypting the password and
* then sending via the NTLM calls */
2005-10-28 13:42:00 +00:00
2005-11-05 09:34:07 +00:00
struct composite_context * wb_cmd_pam_auth_send ( TALLOC_CTX * mem_ctx ,
struct wbsrv_service * service ,
2008-04-15 16:29:13 +02:00
struct cli_credentials * credentials )
2005-10-28 13:42:00 +00:00
{
const char * workstation ;
NTSTATUS status ;
2008-04-15 16:29:13 +02:00
const char * user , * domain ;
2005-10-28 13:42:00 +00:00
DATA_BLOB chal , nt_resp , lm_resp , names_blob ;
int flags = CLI_CRED_NTLM_AUTH ;
2007-12-03 21:25:17 +01:00
if ( lp_client_lanman_auth ( service - > task - > lp_ctx ) ) {
2005-10-28 13:42:00 +00:00
flags | = CLI_CRED_LANMAN_AUTH ;
}
2007-12-03 21:25:17 +01:00
if ( lp_client_ntlmv2_auth ( service - > task - > lp_ctx ) ) {
2005-10-28 13:42:00 +00:00
flags | = CLI_CRED_NTLMv2_AUTH ;
}
2005-11-21 10:28:54 +00:00
DEBUG ( 5 , ( " wbsrv_samba3_pam_auth called \n " ) ) ;
2005-10-28 13:42:00 +00:00
2005-11-05 09:34:07 +00:00
chal = data_blob_talloc ( mem_ctx , NULL , 8 ) ;
2005-10-28 13:42:00 +00:00
if ( ! chal . data ) {
return NULL ;
}
generate_random_buffer ( chal . data , chal . length ) ;
2005-11-05 09:34:07 +00:00
cli_credentials_get_ntlm_username_domain ( credentials , mem_ctx ,
2005-10-28 13:42:00 +00:00
& user , & domain ) ;
/* for best compatability with multiple vitual netbios names
* on the host , this should be generated from the
* cli_credentials associated with the machine account */
workstation = cli_credentials_get_workstation ( credentials ) ;
2005-11-05 09:34:07 +00:00
names_blob = NTLMv2_generate_names_blob (
mem_ctx ,
cli_credentials_get_workstation ( credentials ) ,
cli_credentials_get_domain ( credentials ) ) ;
2005-10-28 13:42:00 +00:00
2005-11-05 09:34:07 +00:00
status = cli_credentials_get_ntlm_response (
credentials , mem_ctx , & flags , chal , names_blob ,
& lm_resp , & nt_resp , NULL , NULL ) ;
2005-10-28 13:42:00 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NULL ;
}
2005-11-05 09:34:07 +00:00
return wb_cmd_pam_auth_crap_send ( mem_ctx , service ,
2008-04-15 16:29:13 +02:00
MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT /* logon parameters */ ,
2005-11-05 09:34:07 +00:00
domain , user , workstation ,
chal , nt_resp , lm_resp ) ;
2005-10-28 13:42:00 +00:00
}
2009-10-02 22:17:42 +10:00
NTSTATUS wb_cmd_pam_auth_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * info3 ,
struct netr_UserSessionKey * user_session_key ,
struct netr_LMSessionKey * lm_key ,
char * * unix_username )
2005-10-28 13:42:00 +00:00
{
2009-10-02 22:17:42 +10:00
struct pam_auth_crap_state * state =
talloc_get_type ( c - > private_data , struct pam_auth_crap_state ) ;
NTSTATUS status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
if ( info3 ) {
info3 - > length = state - > info3 . length ;
info3 - > data = talloc_steal ( mem_ctx , state - > info3 . data ) ;
}
if ( user_session_key ) {
* user_session_key = state - > user_session_key ;
}
if ( lm_key ) {
* lm_key = state - > lm_key ;
}
if ( unix_username ) {
* unix_username = talloc_steal ( mem_ctx , state - > unix_username ) ;
}
}
talloc_free ( state ) ;
return status ;
2005-10-12 20:22:45 +00:00
}