2007-12-21 20:57:34 +03:00
/*
Unix SMB / CIFS implementation .
Winbind client API
Copyright ( C ) Gerald ( Jerry ) Carter 2007
2008-10-02 15:07:14 +04:00
Copyright ( C ) Guenther Deschner 2008
2009-12-21 23:50:43 +03:00
Copyright ( C ) Volker Lendecke 2009
2007-12-21 20:57:34 +03:00
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
This library 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
Library General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
/* Required Headers */
2009-06-05 00:32:21 +04:00
# include "replace.h"
2007-12-21 20:57:34 +03:00
# include "libwbclient.h"
2010-01-23 21:38:28 +03:00
# include "../winbind_client.h"
2007-12-21 20:57:34 +03:00
2008-12-09 15:18:06 +03:00
/* Authenticate a username/password pair */
2008-01-03 14:10:27 +03:00
wbcErr wbcAuthenticateUser ( const char * username ,
2007-12-21 20:57:34 +03:00
const char * password )
{
2008-02-15 12:46:19 +03:00
wbcErr wbc_status = WBC_ERR_SUCCESS ;
struct wbcAuthUserParams params ;
2007-12-21 20:57:34 +03:00
2008-02-15 12:46:19 +03:00
ZERO_STRUCT ( params ) ;
2007-12-21 20:57:34 +03:00
2008-02-15 12:46:19 +03:00
params . account_name = username ;
params . level = WBC_AUTH_USER_LEVEL_PLAIN ;
params . password . plaintext = password ;
2007-12-21 20:57:34 +03:00
2008-02-15 12:46:19 +03:00
wbc_status = wbcAuthenticateUserEx ( & params , NULL , NULL ) ;
2007-12-21 20:57:34 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
2008-01-03 14:10:27 +03:00
return wbc_status ;
2007-12-21 20:57:34 +03:00
}
2008-01-24 16:05:59 +03:00
static wbcErr wbc_create_auth_info ( TALLOC_CTX * mem_ctx ,
const struct winbindd_response * resp ,
struct wbcAuthUserInfo * * _i )
{
wbcErr wbc_status = WBC_ERR_SUCCESS ;
struct wbcAuthUserInfo * i ;
struct wbcDomainSid domain_sid ;
char * p ;
uint32_t sn = 0 ;
uint32_t j ;
i = talloc ( mem_ctx , struct wbcAuthUserInfo ) ;
BAIL_ON_PTR_ERROR ( i , wbc_status ) ;
i - > user_flags = resp - > data . auth . info3 . user_flgs ;
i - > account_name = talloc_strdup ( i , resp - > data . auth . info3 . user_name ) ;
BAIL_ON_PTR_ERROR ( i - > account_name , wbc_status ) ;
i - > user_principal = NULL ;
i - > full_name = talloc_strdup ( i , resp - > data . auth . info3 . full_name ) ;
BAIL_ON_PTR_ERROR ( i - > full_name , wbc_status ) ;
i - > domain_name = talloc_strdup ( i , resp - > data . auth . info3 . logon_dom ) ;
BAIL_ON_PTR_ERROR ( i - > domain_name , wbc_status ) ;
i - > dns_domain_name = NULL ;
i - > acct_flags = resp - > data . auth . info3 . acct_flags ;
memcpy ( i - > user_session_key ,
resp - > data . auth . user_session_key ,
sizeof ( i - > user_session_key ) ) ;
memcpy ( i - > lm_session_key ,
resp - > data . auth . first_8_lm_hash ,
sizeof ( i - > lm_session_key ) ) ;
i - > logon_count = resp - > data . auth . info3 . logon_count ;
i - > bad_password_count = resp - > data . auth . info3 . bad_pw_count ;
i - > logon_time = resp - > data . auth . info3 . logon_time ;
i - > logoff_time = resp - > data . auth . info3 . logoff_time ;
i - > kickoff_time = resp - > data . auth . info3 . kickoff_time ;
i - > pass_last_set_time = resp - > data . auth . info3 . pass_last_set_time ;
i - > pass_can_change_time = resp - > data . auth . info3 . pass_can_change_time ;
i - > pass_must_change_time = resp - > data . auth . info3 . pass_must_change_time ;
i - > logon_server = talloc_strdup ( i , resp - > data . auth . info3 . logon_srv ) ;
BAIL_ON_PTR_ERROR ( i - > logon_server , wbc_status ) ;
i - > logon_script = talloc_strdup ( i , resp - > data . auth . info3 . logon_script ) ;
BAIL_ON_PTR_ERROR ( i - > logon_script , wbc_status ) ;
i - > profile_path = talloc_strdup ( i , resp - > data . auth . info3 . profile_path ) ;
BAIL_ON_PTR_ERROR ( i - > profile_path , wbc_status ) ;
i - > home_directory = talloc_strdup ( i , resp - > data . auth . info3 . home_dir ) ;
BAIL_ON_PTR_ERROR ( i - > home_directory , wbc_status ) ;
i - > home_drive = talloc_strdup ( i , resp - > data . auth . info3 . dir_drive ) ;
BAIL_ON_PTR_ERROR ( i - > home_drive , wbc_status ) ;
i - > num_sids = 2 ;
i - > num_sids + = resp - > data . auth . info3 . num_groups ;
i - > num_sids + = resp - > data . auth . info3 . num_other_sids ;
i - > sids = talloc_array ( i , struct wbcSidWithAttr , i - > num_sids ) ;
BAIL_ON_PTR_ERROR ( i - > sids , wbc_status ) ;
wbc_status = wbcStringToSid ( resp - > data . auth . info3 . dom_sid ,
& domain_sid ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
# define _SID_COMPOSE(s, d, r, a) { \
( s ) . sid = d ; \
2008-05-23 15:59:53 +04:00
if ( ( s ) . sid . num_auths < WBC_MAXSUBAUTHS ) { \
2008-01-24 16:05:59 +03:00
( s ) . sid . sub_auths [ ( s ) . sid . num_auths + + ] = r ; \
} else { \
wbc_status = WBC_ERR_INVALID_SID ; \
BAIL_ON_WBC_ERROR ( wbc_status ) ; \
} \
( s ) . attributes = a ; \
} while ( 0 )
sn = 0 ;
_SID_COMPOSE ( i - > sids [ sn ] , domain_sid ,
resp - > data . auth . info3 . user_rid ,
0 ) ;
sn + + ;
_SID_COMPOSE ( i - > sids [ sn ] , domain_sid ,
resp - > data . auth . info3 . group_rid ,
0 ) ;
sn + + ;
2008-02-23 12:43:58 +03:00
p = ( char * ) resp - > extra_data . data ;
2008-01-24 16:05:59 +03:00
if ( ! p ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-01-24 16:05:59 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
for ( j = 0 ; j < resp - > data . auth . info3 . num_groups ; j + + ) {
uint32_t rid ;
uint32_t attrs ;
int ret ;
char * s = p ;
char * e = strchr ( p , ' \n ' ) ;
if ( ! e ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-01-24 16:05:59 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
e [ 0 ] = ' \0 ' ;
p = & e [ 1 ] ;
ret = sscanf ( s , " 0x%08X:0x%08X " , & rid , & attrs ) ;
if ( ret ! = 2 ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-01-24 16:05:59 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
_SID_COMPOSE ( i - > sids [ sn ] , domain_sid ,
rid , attrs ) ;
sn + + ;
}
for ( j = 0 ; j < resp - > data . auth . info3 . num_other_sids ; j + + ) {
uint32_t attrs ;
int ret ;
char * s = p ;
char * a ;
char * e = strchr ( p , ' \n ' ) ;
if ( ! e ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-01-24 16:05:59 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
e [ 0 ] = ' \0 ' ;
p = & e [ 1 ] ;
e = strchr ( s , ' : ' ) ;
if ( ! e ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-01-24 16:05:59 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
e [ 0 ] = ' \0 ' ;
a = & e [ 1 ] ;
ret = sscanf ( a , " 0x%08X " ,
& attrs ) ;
if ( ret ! = 1 ) {
2008-04-17 19:49:53 +04:00
wbc_status = WBC_ERR_INVALID_RESPONSE ;
2008-01-24 16:05:59 +03:00
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = wbcStringToSid ( s , & i - > sids [ sn ] . sid ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
i - > sids [ sn ] . attributes = attrs ;
sn + + ;
}
i - > num_sids = sn ;
* _i = i ;
i = NULL ;
done :
talloc_free ( i ) ;
return wbc_status ;
}
static wbcErr wbc_create_error_info ( TALLOC_CTX * mem_ctx ,
const struct winbindd_response * resp ,
struct wbcAuthErrorInfo * * _e )
{
wbcErr wbc_status = WBC_ERR_SUCCESS ;
struct wbcAuthErrorInfo * e ;
e = talloc ( mem_ctx , struct wbcAuthErrorInfo ) ;
BAIL_ON_PTR_ERROR ( e , wbc_status ) ;
e - > nt_status = resp - > data . auth . nt_status ;
e - > pam_error = resp - > data . auth . pam_error ;
e - > nt_string = talloc_strdup ( e , resp - > data . auth . nt_status_string ) ;
BAIL_ON_PTR_ERROR ( e - > nt_string , wbc_status ) ;
e - > display_string = talloc_strdup ( e , resp - > data . auth . error_string ) ;
BAIL_ON_PTR_ERROR ( e - > display_string , wbc_status ) ;
* _e = e ;
e = NULL ;
done :
talloc_free ( e ) ;
return wbc_status ;
}
2008-08-15 04:00:46 +04:00
static wbcErr wbc_create_password_policy_info ( TALLOC_CTX * mem_ctx ,
const struct winbindd_response * resp ,
struct wbcUserPasswordPolicyInfo * * _i )
{
wbcErr wbc_status = WBC_ERR_SUCCESS ;
struct wbcUserPasswordPolicyInfo * i ;
i = talloc ( mem_ctx , struct wbcUserPasswordPolicyInfo ) ;
BAIL_ON_PTR_ERROR ( i , wbc_status ) ;
i - > min_passwordage = resp - > data . auth . policy . min_passwordage ;
i - > min_length_password = resp - > data . auth . policy . min_length_password ;
i - > password_history = resp - > data . auth . policy . password_history ;
i - > password_properties = resp - > data . auth . policy . password_properties ;
i - > expire = resp - > data . auth . policy . expire ;
* _i = i ;
i = NULL ;
done :
talloc_free ( i ) ;
return wbc_status ;
}
2008-10-10 17:18:02 +04:00
static wbcErr wbc_create_logon_info ( TALLOC_CTX * mem_ctx ,
2009-04-01 16:22:05 +04:00
struct winbindd_response * resp ,
2008-10-10 17:18:02 +04:00
struct wbcLogonUserInfo * * _i )
{
wbcErr wbc_status = WBC_ERR_SUCCESS ;
struct wbcLogonUserInfo * i ;
i = talloc_zero ( mem_ctx , struct wbcLogonUserInfo ) ;
BAIL_ON_PTR_ERROR ( i , wbc_status ) ;
wbc_status = wbc_create_auth_info ( i , resp , & i - > info ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
2009-06-18 18:17:26 +04:00
if ( resp - > data . auth . krb5ccname & &
strlen ( resp - > data . auth . krb5ccname ) ) {
2008-10-10 17:18:02 +04:00
wbc_status = wbcAddNamedBlob ( & i - > num_blobs ,
& i - > blobs ,
" krb5ccname " ,
0 ,
( uint8_t * ) resp - > data . auth . krb5ccname ,
strlen ( resp - > data . auth . krb5ccname ) + 1 ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2009-06-18 18:17:26 +04:00
if ( resp - > data . auth . unix_username & &
strlen ( resp - > data . auth . unix_username ) ) {
2008-10-10 17:18:02 +04:00
wbc_status = wbcAddNamedBlob ( & i - > num_blobs ,
& i - > blobs ,
" unix_username " ,
0 ,
( uint8_t * ) resp - > data . auth . unix_username ,
strlen ( resp - > data . auth . unix_username ) + 1 ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
* _i = i ;
i = NULL ;
done :
if ( ! WBC_ERROR_IS_OK ( wbc_status ) & & i ) {
wbcFreeMemory ( i - > blobs ) ;
}
talloc_free ( i ) ;
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Authenticate with more detailed information */
2008-01-24 16:05:59 +03:00
wbcErr wbcAuthenticateUserEx ( const struct wbcAuthUserParams * params ,
struct wbcAuthUserInfo * * info ,
struct wbcAuthErrorInfo * * error )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
2008-02-15 12:30:15 +03:00
int cmd = 0 ;
2008-01-24 16:05:59 +03:00
struct winbindd_request request ;
struct winbindd_response response ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( error ) {
* error = NULL ;
}
if ( ! params ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2008-02-15 12:30:15 +03:00
if ( ! params - > account_name ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2008-01-24 16:05:59 +03:00
/* Initialize request */
switch ( params - > level ) {
case WBC_AUTH_USER_LEVEL_PLAIN :
2008-02-15 12:34:46 +03:00
cmd = WINBINDD_PAM_AUTH ;
request . flags = WBFLAG_PAM_INFO3_TEXT |
WBFLAG_PAM_USER_SESSION_KEY |
WBFLAG_PAM_LMKEY ;
if ( ! params - > password . plaintext ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > domain_name & & params - > domain_name [ 0 ] ) {
/* We need to get the winbind separator :-( */
struct winbindd_response sep_response ;
ZERO_STRUCT ( sep_response ) ;
wbc_status = wbcRequestResponse ( WINBINDD_INFO ,
NULL , & sep_response ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
snprintf ( request . data . auth . user ,
sizeof ( request . data . auth . user ) - 1 ,
" %s%c%s " ,
params - > domain_name ,
sep_response . data . info . winbind_separator ,
params - > account_name ) ;
} else {
strncpy ( request . data . auth . user ,
params - > account_name ,
sizeof ( request . data . auth . user ) - 1 ) ;
}
2008-10-10 17:13:14 +04:00
2008-02-15 12:34:46 +03:00
strncpy ( request . data . auth . pass ,
params - > password . plaintext ,
2008-05-27 18:40:44 +04:00
sizeof ( request . data . auth . pass ) - 1 ) ;
2008-01-24 16:05:59 +03:00
break ;
case WBC_AUTH_USER_LEVEL_HASH :
wbc_status = WBC_ERR_NOT_IMPLEMENTED ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
break ;
case WBC_AUTH_USER_LEVEL_RESPONSE :
cmd = WINBINDD_PAM_AUTH_CRAP ;
request . flags = WBFLAG_PAM_INFO3_TEXT |
WBFLAG_PAM_USER_SESSION_KEY |
WBFLAG_PAM_LMKEY ;
2008-02-15 12:30:15 +03:00
if ( params - > password . response . lm_length & &
2008-03-26 03:27:36 +03:00
! params - > password . response . lm_data ) {
2008-02-15 12:30:15 +03:00
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > password . response . lm_length = = 0 & &
params - > password . response . lm_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > password . response . nt_length & &
! params - > password . response . nt_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > password . response . nt_length = = 0 & &
params - > password . response . nt_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2008-01-24 16:05:59 +03:00
strncpy ( request . data . auth_crap . user ,
params - > account_name ,
sizeof ( request . data . auth_crap . user ) - 1 ) ;
2008-02-15 12:30:15 +03:00
if ( params - > domain_name ) {
strncpy ( request . data . auth_crap . domain ,
params - > domain_name ,
sizeof ( request . data . auth_crap . domain ) - 1 ) ;
}
2008-01-24 16:05:59 +03:00
if ( params - > workstation_name ) {
strncpy ( request . data . auth_crap . workstation ,
params - > workstation_name ,
sizeof ( request . data . auth_crap . workstation ) - 1 ) ;
}
request . data . auth_crap . logon_parameters =
params - > parameter_control ;
memcpy ( request . data . auth_crap . chal ,
params - > password . response . challenge ,
sizeof ( request . data . auth_crap . chal ) ) ;
request . data . auth_crap . lm_resp_len =
MIN ( params - > password . response . lm_length ,
sizeof ( request . data . auth_crap . lm_resp ) ) ;
2008-02-15 12:30:15 +03:00
if ( params - > password . response . lm_data ) {
memcpy ( request . data . auth_crap . lm_resp ,
params - > password . response . lm_data ,
request . data . auth_crap . lm_resp_len ) ;
}
2009-09-01 13:58:05 +04:00
request . data . auth_crap . nt_resp_len = params - > password . response . nt_length ;
if ( params - > password . response . nt_length > sizeof ( request . data . auth_crap . nt_resp ) ) {
request . flags | = WBFLAG_BIG_NTLMV2_BLOB ;
request . extra_len = params - > password . response . nt_length ;
request . extra_data . data = talloc_zero_array ( NULL , char , request . extra_len ) ;
if ( request . extra_data . data = = NULL ) {
wbc_status = WBC_ERR_NO_MEMORY ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
memcpy ( request . extra_data . data ,
params - > password . response . nt_data ,
request . data . auth_crap . nt_resp_len ) ;
} else if ( params - > password . response . nt_data ) {
2008-02-15 12:30:15 +03:00
memcpy ( request . data . auth_crap . nt_resp ,
params - > password . response . nt_data ,
request . data . auth_crap . nt_resp_len ) ;
}
2008-01-24 16:05:59 +03:00
break ;
2008-02-15 05:16:09 +03:00
default :
2008-03-27 13:51:31 +03:00
break ;
2008-01-24 16:05:59 +03:00
}
2008-02-15 12:30:15 +03:00
if ( cmd = = 0 ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
2008-10-10 17:13:14 +04:00
if ( params - > flags ) {
request . flags | = params - > flags ;
}
2008-01-24 16:05:59 +03:00
wbc_status = wbcRequestResponse ( cmd ,
& request ,
& response ) ;
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_AUTH_ERROR ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
BAIL_ON_WBC_ERROR ( wbc_status ) ;
if ( info ) {
wbc_status = wbc_create_auth_info ( NULL ,
& response ,
info ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2008-01-24 16:05:59 +03:00
2009-09-01 13:58:05 +04:00
talloc_free ( request . extra_data . data ) ;
2008-01-24 16:05:59 +03:00
return wbc_status ;
}
2008-04-17 01:35:12 +04:00
2008-12-09 15:18:06 +03:00
/* Trigger a verification of the trust credentials of a specific domain */
2008-04-17 01:35:12 +04:00
wbcErr wbcCheckTrustCredentials ( const char * domain ,
struct wbcAuthErrorInfo * * error )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
2009-10-06 19:45:24 +04:00
if ( domain ) {
strncpy ( request . domain_name , domain ,
sizeof ( request . domain_name ) - 1 ) ;
}
2008-04-17 01:35:12 +04:00
/* Send request */
wbc_status = wbcRequestResponse ( WINBINDD_CHECK_MACHACC ,
& request ,
& response ) ;
2008-08-15 15:53:23 +04:00
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_AUTH_ERROR ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2009-10-06 20:15:08 +04:00
/* Trigger a change of the trust credentials for a specific domain */
wbcErr wbcChangeTrustCredentials ( const char * domain ,
struct wbcAuthErrorInfo * * error )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( domain ) {
strncpy ( request . domain_name , domain ,
sizeof ( request . domain_name ) - 1 ) ;
}
/* Send request */
wbc_status = wbcRequestResponse ( WINBINDD_CHANGE_MACHACC ,
& request ,
& response ) ;
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_AUTH_ERROR ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2009-12-21 23:50:43 +03:00
/*
* Trigger a no - op NETLOGON call . Lightweight version of
* wbcCheckTrustCredentials
*/
wbcErr wbcPingDc ( const char * domain , struct wbcAuthErrorInfo * * error )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
if ( domain ) {
/*
* the current protocol doesn ' t support
* specifying a domain
*/
wbc_status = WBC_ERR_NOT_IMPLEMENTED ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
/* Send request */
wbc_status = wbcRequestResponse ( WINBINDD_PING_DC ,
& request ,
& response ) ;
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_AUTH_ERROR ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Trigger an extended logoff notification to Winbind for a specific user */
2008-08-15 15:53:23 +04:00
wbcErr wbcLogoffUserEx ( const struct wbcLogoffUserParams * params ,
struct wbcAuthErrorInfo * * error )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
int i ;
/* validate input */
if ( ! params | | ! params - > username ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( ( params - > num_blobs > 0 ) & & ( params - > blobs = = NULL ) ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( ( params - > num_blobs = = 0 ) & & ( params - > blobs ! = NULL ) ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . logoff . user , params - > username ,
sizeof ( request . data . logoff . user ) - 1 ) ;
for ( i = 0 ; i < params - > num_blobs ; i + + ) {
if ( strcasecmp ( params - > blobs [ i ] . name , " ccfilename " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data ) {
strncpy ( request . data . logoff . krb5ccname ,
( const char * ) params - > blobs [ i ] . blob . data ,
sizeof ( request . data . logoff . krb5ccname ) - 1 ) ;
}
continue ;
}
if ( strcasecmp ( params - > blobs [ i ] . name , " user_uid " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data ) {
memcpy ( & request . data . logoff . uid ,
params - > blobs [ i ] . blob . data ,
MIN ( params - > blobs [ i ] . blob . length ,
sizeof ( request . data . logoff . uid ) ) ) ;
}
continue ;
}
if ( strcasecmp ( params - > blobs [ i ] . name , " flags " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data ) {
memcpy ( & request . flags ,
params - > blobs [ i ] . blob . data ,
MIN ( params - > blobs [ i ] . blob . length ,
sizeof ( request . flags ) ) ) ;
}
continue ;
}
}
/* Send request */
wbc_status = wbcRequestResponse ( WINBINDD_PAM_LOGOFF ,
& request ,
& response ) ;
/* Take the response above and return it to the caller */
2008-04-17 01:35:12 +04:00
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_AUTH_ERROR ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-05-13 21:52:20 +04:00
2008-12-09 15:18:06 +03:00
/* Trigger a logoff notification to Winbind for a specific user */
2008-05-13 21:52:20 +04:00
wbcErr wbcLogoffUser ( const char * username ,
uid_t uid ,
const char * ccfilename )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
/* validate input */
if ( ! username ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . logoff . user , username ,
sizeof ( request . data . logoff . user ) - 1 ) ;
request . data . logoff . uid = uid ;
if ( ccfilename ) {
strncpy ( request . data . logoff . krb5ccname , ccfilename ,
sizeof ( request . data . logoff . krb5ccname ) - 1 ) ;
}
/* Send request */
wbc_status = wbcRequestResponse ( WINBINDD_PAM_LOGOFF ,
& request ,
& response ) ;
/* Take the response above and return it to the caller */
done :
return wbc_status ;
}
2008-08-15 04:00:46 +04:00
2008-12-09 15:18:06 +03:00
/* Change a password for a user with more detailed information upon failure */
2008-08-15 04:00:46 +04:00
wbcErr wbcChangeUserPasswordEx ( const struct wbcChangePasswordParams * params ,
struct wbcAuthErrorInfo * * error ,
enum wbcPasswordChangeRejectReason * reject_reason ,
struct wbcUserPasswordPolicyInfo * * policy )
{
struct winbindd_request request ;
struct winbindd_response response ;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
int cmd = 0 ;
/* validate input */
if ( ! params - > account_name ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( error ) {
* error = NULL ;
}
if ( policy ) {
* policy = NULL ;
}
if ( reject_reason ) {
* reject_reason = - 1 ;
}
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
switch ( params - > level ) {
case WBC_CHANGE_PASSWORD_LEVEL_PLAIN :
cmd = WINBINDD_PAM_CHAUTHTOK ;
if ( ! params - > account_name ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
strncpy ( request . data . chauthtok . user , params - > account_name ,
sizeof ( request . data . chauthtok . user ) - 1 ) ;
if ( params - > old_password . plaintext ) {
strncpy ( request . data . chauthtok . oldpass ,
params - > old_password . plaintext ,
sizeof ( request . data . chauthtok . oldpass ) - 1 ) ;
}
if ( params - > new_password . plaintext ) {
strncpy ( request . data . chauthtok . newpass ,
params - > new_password . plaintext ,
sizeof ( request . data . chauthtok . newpass ) - 1 ) ;
}
break ;
case WBC_CHANGE_PASSWORD_LEVEL_RESPONSE :
cmd = WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP ;
if ( ! params - > account_name | | ! params - > domain_name ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > old_password . response . old_lm_hash_enc_length & &
! params - > old_password . response . old_lm_hash_enc_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > old_password . response . old_lm_hash_enc_length = = 0 & &
params - > old_password . response . old_lm_hash_enc_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > old_password . response . old_nt_hash_enc_length & &
! params - > old_password . response . old_nt_hash_enc_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > old_password . response . old_nt_hash_enc_length = = 0 & &
params - > old_password . response . old_nt_hash_enc_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > new_password . response . lm_length & &
! params - > new_password . response . lm_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > new_password . response . lm_length = = 0 & &
params - > new_password . response . lm_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > new_password . response . nt_length & &
! params - > new_password . response . nt_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( params - > new_password . response . nt_length = = 0 & &
params - > new_password . response . nt_data ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
strncpy ( request . data . chng_pswd_auth_crap . user ,
params - > account_name ,
sizeof ( request . data . chng_pswd_auth_crap . user ) - 1 ) ;
strncpy ( request . data . chng_pswd_auth_crap . domain ,
params - > domain_name ,
sizeof ( request . data . chng_pswd_auth_crap . domain ) - 1 ) ;
if ( params - > new_password . response . nt_data ) {
memcpy ( request . data . chng_pswd_auth_crap . new_nt_pswd ,
params - > new_password . response . nt_data ,
request . data . chng_pswd_auth_crap . new_nt_pswd_len ) ;
request . data . chng_pswd_auth_crap . new_nt_pswd_len =
params - > new_password . response . nt_length ;
}
if ( params - > new_password . response . lm_data ) {
memcpy ( request . data . chng_pswd_auth_crap . new_lm_pswd ,
params - > new_password . response . lm_data ,
request . data . chng_pswd_auth_crap . new_lm_pswd_len ) ;
request . data . chng_pswd_auth_crap . new_lm_pswd_len =
params - > new_password . response . lm_length ;
}
if ( params - > old_password . response . old_nt_hash_enc_data ) {
memcpy ( request . data . chng_pswd_auth_crap . old_nt_hash_enc ,
params - > old_password . response . old_nt_hash_enc_data ,
request . data . chng_pswd_auth_crap . old_nt_hash_enc_len ) ;
request . data . chng_pswd_auth_crap . old_nt_hash_enc_len =
params - > old_password . response . old_nt_hash_enc_length ;
}
if ( params - > old_password . response . old_lm_hash_enc_data ) {
memcpy ( request . data . chng_pswd_auth_crap . old_lm_hash_enc ,
params - > old_password . response . old_lm_hash_enc_data ,
request . data . chng_pswd_auth_crap . old_lm_hash_enc_len ) ;
request . data . chng_pswd_auth_crap . old_lm_hash_enc_len =
params - > old_password . response . old_lm_hash_enc_length ;
}
break ;
default :
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
break ;
}
/* Send request */
wbc_status = wbcRequestResponse ( cmd ,
& request ,
& response ) ;
if ( WBC_ERROR_IS_OK ( wbc_status ) ) {
goto done ;
}
/* Take the response above and return it to the caller */
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
}
if ( policy ) {
wbc_status = wbc_create_password_policy_info ( NULL ,
& response ,
policy ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( reject_reason ) {
* reject_reason = response . data . auth . reject_reason ;
}
wbc_status = WBC_ERR_PWD_CHANGE_FAILED ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-12-09 15:18:06 +03:00
/* Change a password for a user */
2008-08-15 04:00:46 +04:00
wbcErr wbcChangeUserPassword ( const char * username ,
const char * old_password ,
const char * new_password )
{
wbcErr wbc_status = WBC_ERR_SUCCESS ;
struct wbcChangePasswordParams params ;
ZERO_STRUCT ( params ) ;
params . account_name = username ;
params . level = WBC_CHANGE_PASSWORD_LEVEL_PLAIN ;
params . old_password . plaintext = old_password ;
params . new_password . plaintext = new_password ;
wbc_status = wbcChangeUserPasswordEx ( & params ,
NULL ,
NULL ,
NULL ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
done :
return wbc_status ;
}
2008-10-10 17:18:02 +04:00
2008-12-09 15:18:06 +03:00
/* Logon a User */
2008-10-10 17:18:02 +04:00
wbcErr wbcLogonUser ( const struct wbcLogonUserParams * params ,
struct wbcLogonUserInfo * * info ,
struct wbcAuthErrorInfo * * error ,
struct wbcUserPasswordPolicyInfo * * policy )
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE ;
int cmd = 0 ;
struct winbindd_request request ;
struct winbindd_response response ;
uint32_t i ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( info ) {
* info = NULL ;
}
if ( error ) {
* error = NULL ;
}
if ( policy ) {
* policy = NULL ;
}
if ( ! params ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( ! params - > username ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( ( params - > num_blobs > 0 ) & & ( params - > blobs = = NULL ) ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( ( params - > num_blobs = = 0 ) & & ( params - > blobs ! = NULL ) ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
/* Initialize request */
cmd = WINBINDD_PAM_AUTH ;
request . flags = WBFLAG_PAM_INFO3_TEXT |
WBFLAG_PAM_USER_SESSION_KEY |
WBFLAG_PAM_LMKEY ;
if ( ! params - > password ) {
wbc_status = WBC_ERR_INVALID_PARAM ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
strncpy ( request . data . auth . user ,
params - > username ,
sizeof ( request . data . auth . user ) - 1 ) ;
strncpy ( request . data . auth . pass ,
params - > password ,
sizeof ( request . data . auth . pass ) - 1 ) ;
for ( i = 0 ; i < params - > num_blobs ; i + + ) {
if ( strcasecmp ( params - > blobs [ i ] . name , " krb5_cc_type " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data ) {
strncpy ( request . data . auth . krb5_cc_type ,
( const char * ) params - > blobs [ i ] . blob . data ,
sizeof ( request . data . auth . krb5_cc_type ) - 1 ) ;
}
continue ;
}
if ( strcasecmp ( params - > blobs [ i ] . name , " user_uid " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data ) {
memcpy ( & request . data . auth . uid ,
params - > blobs [ i ] . blob . data ,
MIN ( sizeof ( request . data . auth . uid ) ,
params - > blobs [ i ] . blob . length ) ) ;
}
continue ;
}
if ( strcasecmp ( params - > blobs [ i ] . name , " flags " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data ) {
uint32_t flags ;
memcpy ( & flags ,
params - > blobs [ i ] . blob . data ,
MIN ( sizeof ( flags ) ,
params - > blobs [ i ] . blob . length ) ) ;
request . flags | = flags ;
}
continue ;
}
if ( strcasecmp ( params - > blobs [ i ] . name , " membership_of " ) = = 0 ) {
if ( params - > blobs [ i ] . blob . data & &
params - > blobs [ i ] . blob . data [ 0 ] > 0 ) {
strncpy ( request . data . auth . require_membership_of_sid ,
( const char * ) params - > blobs [ i ] . blob . data ,
sizeof ( request . data . auth . require_membership_of_sid ) - 1 ) ;
}
continue ;
}
}
wbc_status = wbcRequestResponse ( cmd ,
& request ,
& response ) ;
if ( response . data . auth . nt_status ! = 0 ) {
if ( error ) {
wbc_status = wbc_create_error_info ( NULL ,
& response ,
error ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
wbc_status = WBC_ERR_AUTH_ERROR ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
BAIL_ON_WBC_ERROR ( wbc_status ) ;
if ( info ) {
wbc_status = wbc_create_logon_info ( NULL ,
& response ,
info ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
if ( policy ) {
wbc_status = wbc_create_password_policy_info ( NULL ,
& response ,
policy ) ;
BAIL_ON_WBC_ERROR ( wbc_status ) ;
}
done :
2010-01-23 21:38:28 +03:00
winbindd_free_response ( & response ) ;
2008-10-10 17:18:02 +04:00
return wbc_status ;
}
2008-11-23 17:16:17 +03:00
2008-12-09 15:18:06 +03:00
/* Authenticate a user with cached credentials */
2008-11-23 17:16:17 +03:00
wbcErr wbcCredentialCache ( struct wbcCredentialCacheParams * params ,
struct wbcCredentialCacheInfo * * info ,
struct wbcAuthErrorInfo * * error )
{
2010-01-24 18:44:15 +03:00
wbcErr status = WBC_ERR_UNKNOWN_FAILURE ;
struct wbcCredentialCacheInfo * result = NULL ;
struct winbindd_request request ;
struct winbindd_response response ;
struct wbcNamedBlob * initial_blob = NULL ;
struct wbcNamedBlob * challenge_blob = NULL ;
int i ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
if ( info ! = NULL ) {
* info = NULL ;
}
if ( error ! = NULL ) {
* error = NULL ;
}
if ( ( params = = NULL )
| | ( params - > account_name = = NULL )
| | ( params - > level ! = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP ) ) {
status = WBC_ERR_INVALID_PARAM ;
goto fail ;
}
if ( params - > domain_name ! = NULL ) {
status = wbcRequestResponse ( WINBINDD_INFO , NULL , & response ) ;
if ( ! WBC_ERROR_IS_OK ( status ) ) {
goto fail ;
}
snprintf ( request . data . ccache_ntlm_auth . user ,
sizeof ( request . data . ccache_ntlm_auth . user ) - 1 ,
" %s%c%s " , params - > domain_name ,
response . data . info . winbind_separator ,
params - > account_name ) ;
} else {
strncpy ( request . data . ccache_ntlm_auth . user ,
params - > account_name ,
sizeof ( request . data . ccache_ntlm_auth . user ) - 1 ) ;
}
request . data . ccache_ntlm_auth . uid = getuid ( ) ;
for ( i = 0 ; i < params - > num_blobs ; i + + ) {
if ( strcasecmp ( params - > blobs [ i ] . name , " initial_blob " ) = = 0 ) {
initial_blob = & params - > blobs [ i ] ;
break ;
}
if ( strcasecmp ( params - > blobs [ i ] . name , " challenge_blob " ) = = 0 ) {
challenge_blob = & params - > blobs [ i ] ;
break ;
}
}
request . data . ccache_ntlm_auth . initial_blob_len = 0 ;
request . data . ccache_ntlm_auth . challenge_blob_len = 0 ;
request . extra_len = 0 ;
if ( initial_blob ! = NULL ) {
request . data . ccache_ntlm_auth . initial_blob_len =
initial_blob - > blob . length ;
request . extra_len + = initial_blob - > blob . length ;
}
if ( challenge_blob ! = NULL ) {
request . data . ccache_ntlm_auth . challenge_blob_len =
challenge_blob - > blob . length ;
request . extra_len + = challenge_blob - > blob . length ;
}
if ( request . extra_len ! = 0 ) {
request . extra_data . data = talloc_array (
NULL , char , request . extra_len ) ;
if ( request . extra_data . data = = NULL ) {
status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
}
if ( initial_blob ! = NULL ) {
memcpy ( request . extra_data . data ,
initial_blob - > blob . data , initial_blob - > blob . length ) ;
}
if ( challenge_blob ! = NULL ) {
memcpy ( request . extra_data . data
+ request . data . ccache_ntlm_auth . initial_blob_len ,
challenge_blob - > blob . data ,
challenge_blob - > blob . length ) ;
}
status = wbcRequestResponse ( WINBINDD_CCACHE_NTLMAUTH , & request ,
& response ) ;
if ( ! WBC_ERROR_IS_OK ( status ) ) {
goto fail ;
}
result = talloc ( NULL , struct wbcCredentialCacheInfo ) ;
if ( result = = NULL ) {
status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
result - > num_blobs = 0 ;
result - > blobs = talloc ( result , struct wbcNamedBlob ) ;
if ( result - > blobs = = NULL ) {
status = WBC_ERR_NO_MEMORY ;
goto fail ;
}
status = wbcAddNamedBlob ( & result - > num_blobs , & result - > blobs ,
" auth_blob " , 0 ,
( uint8_t * ) response . extra_data . data ,
response . data . ccache_ntlm_auth . auth_blob_len ) ;
if ( ! WBC_ERROR_IS_OK ( status ) ) {
goto fail ;
}
status = wbcAddNamedBlob (
& result - > num_blobs , & result - > blobs , " session_key " , 0 ,
response . data . ccache_ntlm_auth . session_key ,
sizeof ( response . data . ccache_ntlm_auth . session_key ) ) ;
if ( ! WBC_ERROR_IS_OK ( status ) ) {
goto fail ;
}
winbindd_free_response ( & response ) ;
* info = result ;
return WBC_ERR_SUCCESS ;
fail :
TALLOC_FREE ( request . extra_data . data ) ;
winbindd_free_response ( & response ) ;
talloc_free ( result ) ;
return status ;
2008-11-23 17:16:17 +03:00
}
2010-01-09 22:20:36 +03:00
/* Authenticate a user with cached credentials */
wbcErr wbcCredentialSave ( const char * user , const char * password )
{
struct winbindd_request request ;
struct winbindd_response response ;
ZERO_STRUCT ( request ) ;
ZERO_STRUCT ( response ) ;
strncpy ( request . data . ccache_save . user , user ,
sizeof ( request . data . ccache_save . user ) - 1 ) ;
strncpy ( request . data . ccache_save . pass , password ,
sizeof ( request . data . ccache_save . pass ) - 1 ) ;
request . data . ccache_save . uid = getuid ( ) ;
return wbcRequestResponse ( WINBINDD_CCACHE_SAVE , & request , & response ) ;
}