2011-07-21 07:20:26 +04:00
/*
Unix SMB / CIFS implementation .
Generic Authentication Interface
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2006
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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "system/network.h"
2013-12-13 13:00:24 +04:00
# define TEVENT_DEPRECATED 1
2011-07-21 07:20:26 +04:00
# include <tevent.h>
# include "lib/tsocket/tsocket.h"
# include "lib/util/tevent_ntstatus.h"
# include "auth/gensec/gensec.h"
2013-08-05 09:12:01 +04:00
# include "auth/gensec/gensec_internal.h"
2014-02-12 15:08:19 +04:00
# include "librpc/gen_ndr/dcerpc.h"
2017-03-01 02:18:49 +03:00
# include "auth/common_auth.h"
2011-07-21 07:20:26 +04:00
2017-12-19 12:49:10 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_AUTH
2013-12-17 14:49:31 +04:00
_PRIVATE_ NTSTATUS gensec_may_reset_crypto ( struct gensec_security * gensec_security ,
bool full_reset )
{
if ( ! gensec_security - > ops - > may_reset_crypto ) {
return NT_STATUS_OK ;
}
return gensec_security - > ops - > may_reset_crypto ( gensec_security , full_reset ) ;
}
2011-07-21 07:20:26 +04:00
/*
wrappers for the gensec function pointers
*/
_PUBLIC_ NTSTATUS gensec_unseal_packet ( struct gensec_security * gensec_security ,
uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
const DATA_BLOB * sig )
{
if ( ! gensec_security - > ops - > unseal_packet ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
2015-06-19 15:46:53 +03:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-07-21 07:20:26 +04:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2015-06-19 15:46:53 +03:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_DCE_STYLE ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-07-21 07:20:26 +04:00
2011-07-21 13:10:15 +04:00
return gensec_security - > ops - > unseal_packet ( gensec_security ,
2011-07-21 07:20:26 +04:00
data , length ,
whole_pdu , pdu_length ,
sig ) ;
}
_PUBLIC_ NTSTATUS gensec_check_packet ( struct gensec_security * gensec_security ,
const uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
const DATA_BLOB * sig )
{
if ( ! gensec_security - > ops - > check_packet ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-07-21 13:10:15 +04:00
return gensec_security - > ops - > check_packet ( gensec_security , data , length , whole_pdu , pdu_length , sig ) ;
2011-07-21 07:20:26 +04:00
}
_PUBLIC_ NTSTATUS gensec_seal_packet ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
DATA_BLOB * sig )
{
if ( ! gensec_security - > ops - > seal_packet ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-10-15 07:56:01 +04:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2015-06-19 15:46:53 +03:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_DCE_STYLE ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-07-21 07:20:26 +04:00
return gensec_security - > ops - > seal_packet ( gensec_security , mem_ctx , data , length , whole_pdu , pdu_length , sig ) ;
}
_PUBLIC_ NTSTATUS gensec_sign_packet ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const uint8_t * data , size_t length ,
const uint8_t * whole_pdu , size_t pdu_length ,
DATA_BLOB * sig )
{
if ( ! gensec_security - > ops - > sign_packet ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_security - > ops - > sign_packet ( gensec_security , mem_ctx , data , length , whole_pdu , pdu_length , sig ) ;
}
_PUBLIC_ size_t gensec_sig_size ( struct gensec_security * gensec_security , size_t data_size )
{
if ( ! gensec_security - > ops - > sig_size ) {
return 0 ;
}
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
return 0 ;
}
2015-06-19 15:46:53 +03:00
if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_DCE_STYLE ) ) {
return 0 ;
}
}
2011-07-21 07:20:26 +04:00
return gensec_security - > ops - > sig_size ( gensec_security , data_size ) ;
}
2012-01-12 19:18:38 +04:00
_PUBLIC_ size_t gensec_max_wrapped_size ( struct gensec_security * gensec_security )
2011-07-21 07:20:26 +04:00
{
if ( ! gensec_security - > ops - > max_wrapped_size ) {
return ( 1 < < 17 ) ;
}
return gensec_security - > ops - > max_wrapped_size ( gensec_security ) ;
}
2012-01-12 19:18:38 +04:00
_PUBLIC_ size_t gensec_max_input_size ( struct gensec_security * gensec_security )
2011-07-21 07:20:26 +04:00
{
if ( ! gensec_security - > ops - > max_input_size ) {
return ( 1 < < 17 ) - gensec_sig_size ( gensec_security , 1 < < 17 ) ;
}
return gensec_security - > ops - > max_input_size ( gensec_security ) ;
}
_PUBLIC_ NTSTATUS gensec_wrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
if ( ! gensec_security - > ops - > wrap ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
return gensec_security - > ops - > wrap ( gensec_security , mem_ctx , in , out ) ;
}
_PUBLIC_ NTSTATUS gensec_unwrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
if ( ! gensec_security - > ops - > unwrap ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
return gensec_security - > ops - > unwrap ( gensec_security , mem_ctx , in , out ) ;
}
_PUBLIC_ NTSTATUS gensec_session_key ( struct gensec_security * gensec_security ,
2011-08-01 09:39:01 +04:00
TALLOC_CTX * mem_ctx ,
DATA_BLOB * session_key )
2011-07-21 07:20:26 +04:00
{
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SESSION_KEY ) ) {
return NT_STATUS_NO_USER_SESSION_KEY ;
}
2013-08-03 13:26:13 +04:00
if ( ! gensec_security - > ops - > session_key ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
2011-08-01 09:39:01 +04:00
return gensec_security - > ops - > session_key ( gensec_security , mem_ctx , session_key ) ;
2011-07-21 07:20:26 +04:00
}
2017-03-01 06:00:03 +03:00
const char * gensec_final_auth_type ( struct gensec_security * gensec_security )
{
if ( ! gensec_security - > ops - > final_auth_type ) {
return gensec_security - > ops - > name ;
}
return gensec_security - > ops - > final_auth_type ( gensec_security ) ;
}
2017-03-01 02:18:49 +03:00
/*
* Log details of a successful GENSEC authorization to a service .
*
* Only successful authorizations are logged , as only these call gensec_session_info ( )
*
* The service may later refuse authorization due to an ACL .
*
*/
static void log_successful_gensec_authz_event ( struct gensec_security * gensec_security ,
struct auth_session_info * session_info )
{
const struct tsocket_address * remote
= gensec_get_remote_address ( gensec_security ) ;
const struct tsocket_address * local
= gensec_get_local_address ( gensec_security ) ;
const char * service_description
= gensec_get_target_service_description ( gensec_security ) ;
2017-03-01 06:00:03 +03:00
const char * final_auth_type
= gensec_final_auth_type ( gensec_security ) ;
2017-03-06 04:10:17 +03:00
const char * transport_protection = NULL ;
if ( gensec_security - > want_features & GENSEC_FEATURE_SMB_TRANSPORT ) {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB ;
} else if ( gensec_security - > want_features & GENSEC_FEATURE_LDAPS_TRANSPORT ) {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS ;
} else if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_SEAL ;
} else if ( gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_SIGN ;
} else {
transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE ;
}
2017-03-24 05:18:46 +03:00
log_successful_authz_event ( gensec_security - > auth_context - > msg_ctx ,
gensec_security - > auth_context - > lp_ctx ,
remote , local ,
2017-03-01 06:00:03 +03:00
service_description ,
final_auth_type ,
2017-03-06 04:10:17 +03:00
transport_protection ,
2017-03-01 06:00:03 +03:00
session_info ) ;
2017-03-01 02:18:49 +03:00
}
2011-07-21 07:20:26 +04:00
/**
* Return the credentials of a logged on user , including session keys
* etc .
*
* Only valid after a successful authentication
*
2017-03-01 02:18:49 +03:00
* May only be called once per authentication . This will also make an
* authorization log entry , as it is already called by all the
* callers .
2011-07-21 07:20:26 +04:00
*
*/
_PUBLIC_ NTSTATUS gensec_session_info ( struct gensec_security * gensec_security ,
2011-08-01 09:39:01 +04:00
TALLOC_CTX * mem_ctx ,
struct auth_session_info * * session_info )
2011-07-21 07:20:26 +04:00
{
2017-03-01 02:18:49 +03:00
NTSTATUS status ;
2011-07-21 07:20:26 +04:00
if ( ! gensec_security - > ops - > session_info ) {
return NT_STATUS_NOT_IMPLEMENTED ;
}
2017-03-01 02:18:49 +03:00
status = gensec_security - > ops - > session_info ( gensec_security , mem_ctx , session_info ) ;
if ( NT_STATUS_IS_OK ( status ) & & ! gensec_security - > subcontext
& & ( gensec_security - > want_features & GENSEC_FEATURE_NO_AUTHZ_LOG ) = = 0 ) {
log_successful_gensec_authz_event ( gensec_security , * session_info ) ;
}
return status ;
2011-07-21 07:20:26 +04:00
}
2012-01-12 19:18:38 +04:00
_PUBLIC_ void gensec_set_max_update_size ( struct gensec_security * gensec_security ,
2011-12-24 04:14:26 +04:00
uint32_t max_update_size )
{
gensec_security - > max_update_size = max_update_size ;
}
2012-01-12 19:18:38 +04:00
_PUBLIC_ size_t gensec_max_update_size ( struct gensec_security * gensec_security )
2011-12-24 04:14:26 +04:00
{
if ( gensec_security - > max_update_size = = 0 ) {
return UINT32_MAX ;
}
return gensec_security - > max_update_size ;
}
2016-09-01 11:54:17 +03:00
static NTSTATUS gensec_verify_features ( struct gensec_security * gensec_security )
2015-12-15 17:08:43 +03:00
{
2018-10-31 17:55:57 +03:00
bool ok ;
2015-12-15 17:08:43 +03:00
/*
2016-09-01 11:54:17 +03:00
* gensec_want_feature ( GENSEC_FEATURE_SIGN )
* and
* gensec_want_feature ( GENSEC_FEATURE_SEAL )
* require these flags to be available .
2015-12-15 17:08:43 +03:00
*/
2016-09-01 11:54:17 +03:00
if ( gensec_security - > want_features & GENSEC_FEATURE_SIGN ) {
2015-12-15 17:08:43 +03:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
2016-06-13 06:42:25 +03:00
DEBUG ( 0 , ( " Did not manage to negotiate mandatory feature "
2016-09-01 11:54:17 +03:00
" SIGN \n " ) ) ;
2015-12-15 17:08:43 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
2016-09-01 11:54:17 +03:00
}
if ( gensec_security - > want_features & GENSEC_FEATURE_SEAL ) {
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SEAL ) ) {
2016-06-13 06:42:25 +03:00
DEBUG ( 0 , ( " Did not manage to negotiate mandatory feature "
2016-09-01 11:54:17 +03:00
" SEAL \n " ) ) ;
2015-12-15 17:08:43 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
2016-09-01 11:54:17 +03:00
if ( ! gensec_have_feature ( gensec_security , GENSEC_FEATURE_SIGN ) ) {
2016-06-13 06:42:25 +03:00
DEBUG ( 0 , ( " Did not manage to negotiate mandatory feature "
2016-09-01 11:54:17 +03:00
" SIGN for SEAL \n " ) ) ;
2015-12-15 17:08:43 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
}
2018-10-31 17:55:57 +03:00
if ( gensec_security - > dcerpc_auth_level < DCERPC_AUTH_LEVEL_PACKET ) {
return NT_STATUS_OK ;
}
ok = gensec_have_feature ( gensec_security ,
GENSEC_FEATURE_SIGN_PKT_HEADER ) ;
if ( ! ok ) {
DBG_ERR ( " backend [%s] does not support header signing! "
" auth_level[0x%x] \n " ,
gensec_security - > ops - > name ,
gensec_security - > dcerpc_auth_level ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
2015-12-15 17:08:43 +03:00
return NT_STATUS_OK ;
}
2017-06-15 01:05:29 +03:00
/**
* Next state function for the GENSEC state machine
*
* @ param gensec_security GENSEC State
* @ param out_mem_ctx The TALLOC_CTX for * out to be allocated on
* @ param in The request , as a DATA_BLOB
* @ param out The reply , as an talloc ( ) ed DATA_BLOB , on * out_mem_ctx
* @ return Error , MORE_PROCESSING_REQUIRED if a reply is sent ,
* or NT_STATUS_OK if the user is authenticated .
*/
_PUBLIC_ NTSTATUS gensec_update ( struct gensec_security * gensec_security ,
TALLOC_CTX * out_mem_ctx ,
const DATA_BLOB in , DATA_BLOB * out )
2011-07-21 07:20:26 +04:00
{
2011-10-15 06:17:33 +04:00
NTSTATUS status ;
2013-08-05 18:12:13 +04:00
TALLOC_CTX * frame = NULL ;
2017-06-15 01:05:29 +03:00
struct tevent_context * ev = NULL ;
2013-08-05 18:12:13 +04:00
struct tevent_req * subreq = NULL ;
bool ok ;
2011-10-15 06:17:33 +04:00
2017-05-11 15:22:27 +03:00
if ( gensec_security - > subcontext ) {
/*
* gensec modules are not allowed to call the sync version .
*/
return NT_STATUS_INTERNAL_ERROR ;
}
2013-08-05 18:12:13 +04:00
frame = talloc_stackframe ( ) ;
2017-06-15 01:05:29 +03:00
ev = samba_tevent_context_init ( frame ) ;
2013-12-13 13:00:24 +04:00
if ( ev = = NULL ) {
2017-06-15 01:05:29 +03:00
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2013-12-13 13:00:24 +04:00
}
2017-06-15 01:05:29 +03:00
/*
* TODO : remove this hack once the backends
* are fixed .
*/
tevent_loop_allow_nesting ( ev ) ;
2017-05-11 14:16:16 +03:00
subreq = gensec_update_send ( frame , ev , gensec_security , in ) ;
2013-08-05 18:12:13 +04:00
if ( subreq = = NULL ) {
2013-08-19 00:37:26 +04:00
status = NT_STATUS_NO_MEMORY ;
2013-08-05 18:12:13 +04:00
goto fail ;
}
ok = tevent_req_poll_ntstatus ( subreq , ev , & status ) ;
if ( ! ok ) {
goto fail ;
}
2017-05-11 14:16:16 +03:00
status = gensec_update_recv ( subreq , out_mem_ctx , out ) ;
2013-08-05 18:12:13 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2011-07-21 07:20:26 +04:00
}
struct gensec_update_state {
2013-08-05 18:12:13 +04:00
const struct gensec_security_ops * ops ;
2011-07-21 07:20:26 +04:00
struct gensec_security * gensec_security ;
2017-05-11 14:23:07 +03:00
NTSTATUS status ;
2011-07-21 07:20:26 +04:00
DATA_BLOB out ;
} ;
2017-05-11 14:28:10 +03:00
static void gensec_update_cleanup ( struct tevent_req * req ,
enum tevent_req_state req_state ) ;
2017-05-11 14:25:26 +03:00
static void gensec_update_done ( struct tevent_req * subreq ) ;
2013-08-05 18:12:13 +04:00
2011-07-21 07:20:26 +04:00
/**
* Next state function for the GENSEC state machine async version
*
* @ param mem_ctx The memory context for the request
* @ param ev The event context for the request
* @ param gensec_security GENSEC State
* @ param in The request , as a DATA_BLOB
*
* @ return The request handle or NULL on no memory failure
*/
_PUBLIC_ struct tevent_req * gensec_update_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct gensec_security * gensec_security ,
const DATA_BLOB in )
{
2017-05-11 14:25:26 +03:00
struct tevent_req * req = NULL ;
2011-07-21 07:20:26 +04:00
struct gensec_update_state * state = NULL ;
2017-05-11 14:25:26 +03:00
struct tevent_req * subreq = NULL ;
2011-07-21 07:20:26 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct gensec_update_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2013-08-05 18:12:13 +04:00
state - > ops = gensec_security - > ops ;
state - > gensec_security = gensec_security ;
2017-05-11 14:28:10 +03:00
if ( gensec_security - > update_busy_ptr ! = NULL ) {
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return tevent_req_post ( req , ev ) ;
}
2016-12-30 19:54:12 +03:00
if ( gensec_security - > child_security ! = NULL ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
}
2017-05-11 14:28:10 +03:00
gensec_security - > update_busy_ptr = & state - > gensec_security ;
tevent_req_set_cleanup_fn ( req , gensec_update_cleanup ) ;
2017-05-11 14:25:26 +03:00
subreq = state - > ops - > update_send ( state , ev , gensec_security , in ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2011-07-21 07:20:26 +04:00
return tevent_req_post ( req , ev ) ;
}
2017-05-11 14:25:26 +03:00
tevent_req_set_callback ( subreq , gensec_update_done , req ) ;
2011-07-21 07:20:26 +04:00
2017-07-20 16:42:58 +03:00
DBG_DEBUG ( " %s[%p]: subreq: %p \n " , state - > ops - > name ,
state - > gensec_security , subreq ) ;
2011-07-21 07:20:26 +04:00
return req ;
}
2017-05-11 14:28:10 +03:00
static void gensec_update_cleanup ( struct tevent_req * req ,
enum tevent_req_state req_state )
{
struct gensec_update_state * state =
tevent_req_data ( req ,
struct gensec_update_state ) ;
if ( state - > gensec_security = = NULL ) {
return ;
}
if ( state - > gensec_security - > update_busy_ptr = = & state - > gensec_security ) {
state - > gensec_security - > update_busy_ptr = NULL ;
}
state - > gensec_security = NULL ;
}
2017-05-11 14:25:26 +03:00
static void gensec_update_done ( struct tevent_req * subreq )
2013-08-05 18:12:13 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct gensec_update_state * state =
tevent_req_data ( req ,
struct gensec_update_state ) ;
NTSTATUS status ;
2017-07-20 16:42:58 +03:00
const char * debug_subreq = NULL ;
if ( CHECK_DEBUGLVL ( DBGLVL_DEBUG ) ) {
/*
* We need to call tevent_req_print ( )
* before calling the _recv function ,
* before tevent_req_received ( ) was called .
* in order to print the pointer value of
* the subreq state .
*/
debug_subreq = tevent_req_print ( state , subreq ) ;
}
2013-08-05 18:12:13 +04:00
status = state - > ops - > update_recv ( subreq , state , & state - > out ) ;
TALLOC_FREE ( subreq ) ;
2017-05-11 14:23:07 +03:00
state - > status = status ;
2017-07-20 16:42:58 +03:00
if ( GENSEC_UPDATE_IS_NTERROR ( status ) ) {
DBG_INFO ( " %s[%p]: %s%s%s \n " , state - > ops - > name ,
state - > gensec_security , nt_errstr ( status ) ,
debug_subreq ? " " : " " ,
debug_subreq ? debug_subreq : " " ) ;
tevent_req_nterror ( req , status ) ;
2017-05-11 14:23:07 +03:00
return ;
}
2017-07-20 16:42:58 +03:00
DBG_DEBUG ( " %s[%p]: %s %s \n " , state - > ops - > name ,
state - > gensec_security , nt_errstr ( status ) ,
debug_subreq ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
tevent_req_done ( req ) ;
2011-07-21 07:20:26 +04:00
return ;
}
2013-08-05 18:12:13 +04:00
/*
* Because callers using the
* gensec_start_mech_by_authtype ( ) never call
* gensec_want_feature ( ) , it isn ' t sensible for them
* to have to call gensec_have_feature ( ) manually , and
* these are not points of negotiation , but are
* asserted by the client
*/
2016-09-01 11:54:17 +03:00
status = gensec_verify_features ( state - > gensec_security ) ;
2015-12-15 17:08:43 +03:00
if ( tevent_req_nterror ( req , status ) ) {
return ;
2013-08-05 18:12:13 +04:00
}
2011-07-21 07:20:26 +04:00
tevent_req_done ( req ) ;
}
/**
* Next state function for the GENSEC state machine
*
* @ param req request state
* @ param out_mem_ctx The TALLOC_CTX for * out to be allocated on
* @ param out The reply , as an talloc ( ) ed DATA_BLOB , on * out_mem_ctx
* @ return Error , MORE_PROCESSING_REQUIRED if a reply is sent ,
* or NT_STATUS_OK if the user is authenticated .
*/
_PUBLIC_ NTSTATUS gensec_update_recv ( struct tevent_req * req ,
TALLOC_CTX * out_mem_ctx ,
DATA_BLOB * out )
{
struct gensec_update_state * state =
tevent_req_data ( req , struct gensec_update_state ) ;
NTSTATUS status ;
2017-05-11 14:23:07 +03:00
* out = data_blob_null ;
2011-07-21 07:20:26 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
2017-05-11 14:23:07 +03:00
tevent_req_received ( req ) ;
return status ;
2011-07-21 07:20:26 +04:00
}
* out = state - > out ;
talloc_steal ( out_mem_ctx , out - > data ) ;
2017-05-11 14:23:07 +03:00
status = state - > status ;
2011-07-21 07:20:26 +04:00
tevent_req_received ( req ) ;
return status ;
}
/**
* Set the requirement for a certain feature on the connection
*
*/
_PUBLIC_ void gensec_want_feature ( struct gensec_security * gensec_security ,
uint32_t feature )
{
if ( ! gensec_security - > ops | | ! gensec_security - > ops - > want_feature ) {
gensec_security - > want_features | = feature ;
return ;
}
gensec_security - > ops - > want_feature ( gensec_security , feature ) ;
}
/**
* Check the requirement for a certain feature on the connection
*
*/
_PUBLIC_ bool gensec_have_feature ( struct gensec_security * gensec_security ,
uint32_t feature )
{
2015-06-18 19:57:42 +03:00
if ( ! gensec_security - > ops | | ! gensec_security - > ops - > have_feature ) {
2011-07-21 07:20:26 +04:00
return false ;
}
/* We might 'have' features that we don't 'want', because the
* other end demanded them , or we can ' t neotiate them off */
return gensec_security - > ops - > have_feature ( gensec_security , feature ) ;
}
2012-03-03 07:32:45 +04:00
_PUBLIC_ NTTIME gensec_expire_time ( struct gensec_security * gensec_security )
{
if ( ! gensec_security - > ops - > expire_time ) {
return GENSEC_EXPIRE_TIME_INFINITY ;
}
return gensec_security - > ops - > expire_time ( gensec_security ) ;
}
2011-07-21 07:20:26 +04:00
/**
* Return the credentials structure associated with a GENSEC context
*
*/
_PUBLIC_ struct cli_credentials * gensec_get_credentials ( struct gensec_security * gensec_security )
{
if ( ! gensec_security ) {
return NULL ;
}
return gensec_security - > credentials ;
}
/**
* Set the target service ( such as ' http ' or ' host ' ) on a GENSEC context - ensures it is talloc ( ) ed
*
2017-02-20 03:32:47 +03:00
* This is used for Kerberos service principal name resolution .
2011-07-21 07:20:26 +04:00
*/
_PUBLIC_ NTSTATUS gensec_set_target_service ( struct gensec_security * gensec_security , const char * service )
{
gensec_security - > target . service = talloc_strdup ( gensec_security , service ) ;
if ( ! gensec_security - > target . service ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
_PUBLIC_ const char * gensec_get_target_service ( struct gensec_security * gensec_security )
{
if ( gensec_security - > target . service ) {
return gensec_security - > target . service ;
}
return " host " ;
}
2017-02-20 03:32:47 +03:00
/**
* Set the target service ( such as ' samr ' ) on an GENSEC context - ensures it is talloc ( ) ed .
*
* This is not the Kerberos service principal , instead this is a
* constant value that can be logged as part of authentication and
* authorization logging
*/
_PUBLIC_ NTSTATUS gensec_set_target_service_description ( struct gensec_security * gensec_security ,
const char * service )
{
gensec_security - > target . service_description = talloc_strdup ( gensec_security , service ) ;
if ( ! gensec_security - > target . service_description ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
_PUBLIC_ const char * gensec_get_target_service_description ( struct gensec_security * gensec_security )
{
if ( gensec_security - > target . service_description ) {
return gensec_security - > target . service_description ;
} else if ( gensec_security - > target . service ) {
return gensec_security - > target . service ;
}
return NULL ;
}
2011-07-21 07:20:26 +04:00
/**
* Set the target hostname ( suitable for kerberos resolutation ) on a GENSEC context - ensures it is talloc ( ) ed
*
*/
_PUBLIC_ NTSTATUS gensec_set_target_hostname ( struct gensec_security * gensec_security , const char * hostname )
{
gensec_security - > target . hostname = talloc_strdup ( gensec_security , hostname ) ;
if ( hostname & & ! gensec_security - > target . hostname ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
_PUBLIC_ const char * gensec_get_target_hostname ( struct gensec_security * gensec_security )
{
2017-02-17 22:47:12 +03:00
/* We allow the target hostname to be overridden for testing purposes */
2011-07-21 07:20:26 +04:00
if ( gensec_security - > settings - > target_hostname ) {
return gensec_security - > settings - > target_hostname ;
}
if ( gensec_security - > target . hostname ) {
return gensec_security - > target . hostname ;
}
/* We could add use the 'set sockaddr' call, and do a reverse
* lookup , but this would be both insecure ( compromising the
* way kerberos works ) and add DNS timeouts */
return NULL ;
}
/**
2011-10-24 13:07:32 +04:00
* Set ( and copy ) local and peer socket addresses onto a socket
2011-07-21 07:20:26 +04:00
* context on the GENSEC context .
*
* This is so that kerberos can include these addresses in
* cryptographic tokens , to avoid certain attacks .
*/
/**
* @ brief Set the local gensec address .
*
* @ param gensec_security The gensec security context to use .
*
* @ param remote The local address to set .
*
* @ return On success NT_STATUS_OK is returned or an NT_STATUS
* error .
*/
_PUBLIC_ NTSTATUS gensec_set_local_address ( struct gensec_security * gensec_security ,
const struct tsocket_address * local )
{
TALLOC_FREE ( gensec_security - > local_addr ) ;
if ( local = = NULL ) {
return NT_STATUS_OK ;
}
gensec_security - > local_addr = tsocket_address_copy ( local , gensec_security ) ;
if ( gensec_security - > local_addr = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
/**
* @ brief Set the remote gensec address .
*
* @ param gensec_security The gensec security context to use .
*
* @ param remote The remote address to set .
*
* @ return On success NT_STATUS_OK is returned or an NT_STATUS
* error .
*/
_PUBLIC_ NTSTATUS gensec_set_remote_address ( struct gensec_security * gensec_security ,
const struct tsocket_address * remote )
{
TALLOC_FREE ( gensec_security - > remote_addr ) ;
if ( remote = = NULL ) {
return NT_STATUS_OK ;
}
gensec_security - > remote_addr = tsocket_address_copy ( remote , gensec_security ) ;
if ( gensec_security - > remote_addr = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
/**
* @ brief Get the local address from a gensec security context .
*
* @ param gensec_security The security context to get the address from .
*
* @ return The address as tsocket_address which could be NULL if
* no address is set .
*/
_PUBLIC_ const struct tsocket_address * gensec_get_local_address ( struct gensec_security * gensec_security )
{
if ( gensec_security = = NULL ) {
return NULL ;
}
return gensec_security - > local_addr ;
}
/**
* @ brief Get the remote address from a gensec security context .
*
* @ param gensec_security The security context to get the address from .
*
* @ return The address as tsocket_address which could be NULL if
* no address is set .
*/
_PUBLIC_ const struct tsocket_address * gensec_get_remote_address ( struct gensec_security * gensec_security )
{
if ( gensec_security = = NULL ) {
return NULL ;
}
return gensec_security - > remote_addr ;
}
/**
* Set the target principal ( assuming it it known , say from the SPNEGO reply )
* - ensures it is talloc ( ) ed
*
*/
_PUBLIC_ NTSTATUS gensec_set_target_principal ( struct gensec_security * gensec_security , const char * principal )
{
gensec_security - > target . principal = talloc_strdup ( gensec_security , principal ) ;
if ( ! gensec_security - > target . principal ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
2012-01-12 19:18:38 +04:00
_PUBLIC_ const char * gensec_get_target_principal ( struct gensec_security * gensec_security )
2011-07-21 07:20:26 +04:00
{
if ( gensec_security - > target . principal ) {
return gensec_security - > target . principal ;
}
return NULL ;
}