2011-10-07 10:24:12 +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 "auth/gensec/gensec.h"
2013-08-05 09:12:01 +04:00
# include "auth/gensec/gensec_internal.h"
2011-12-31 15:24:44 +04:00
# include "auth/common_auth.h"
2012-04-01 05:37:56 +04:00
# include "../lib/util/asn1.h"
2021-10-05 19:11:57 +03:00
# include "param/param.h"
# include "libds/common/roles.h"
2011-10-07 10:24:12 +04:00
2017-12-19 12:49:10 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_AUTH
2011-12-29 15:34:28 +04:00
NTSTATUS gensec_generate_session_info_pac ( TALLOC_CTX * mem_ctx ,
2011-12-28 10:48:45 +04:00
struct gensec_security * gensec_security ,
struct smb_krb5_context * smb_krb5_context ,
DATA_BLOB * pac_blob ,
const char * principal_string ,
const struct tsocket_address * remote_address ,
struct auth_session_info * * session_info )
{
uint32_t session_info_flags = 0 ;
2021-04-21 12:30:20 +03:00
struct auth4_context * auth_context = NULL ;
NTSTATUS status ;
2011-12-28 10:48:45 +04:00
if ( gensec_security - > want_features & GENSEC_FEATURE_UNIX_TOKEN ) {
session_info_flags | = AUTH_SESSION_INFO_UNIX_TOKEN ;
}
session_info_flags | = AUTH_SESSION_INFO_DEFAULT_GROUPS ;
if ( ! pac_blob ) {
2021-10-05 19:11:57 +03:00
enum server_role server_role =
lpcfg_server_role ( gensec_security - > settings - > lp_ctx ) ;
/*
* For any domain setup ( DC or member ) we require having
* a PAC , as the service ticket comes from an AD DC ,
* which will always provide a PAC , unless
* UF_NO_AUTH_DATA_REQUIRED is configured for our
* account , but that ' s just an invalid configuration ,
* the admin configured for us !
*
* As a legacy case , we still allow kerberos tickets from an MIT
* realm , but only in standalone mode . In that mode we ' ll only
* ever accept a kerberos authentication with a keytab file
* being explicitly configured via the ' keytab method ' option .
*/
if ( server_role ! = ROLE_STANDALONE ) {
DBG_WARNING ( " Unable to find PAC in ticket from %s, "
" failing to allow access \n " ,
principal_string ) ;
return NT_STATUS_NO_IMPERSONATION_TOKEN ;
2011-12-28 10:48:45 +04:00
}
2016-04-28 21:23:41 +03:00
DBG_NOTICE ( " Unable to find PAC for %s, resorting to local "
" user lookup \n " , principal_string ) ;
2011-12-28 10:48:45 +04:00
}
2021-04-21 12:30:20 +03:00
auth_context = gensec_security - > auth_context ;
if ( ( auth_context = = NULL ) | |
( auth_context - > generate_session_info_pac = = NULL ) ) {
DBG_ERR ( " Cannot generate a session_info without "
" the auth_context \n " ) ;
2011-12-29 04:46:41 +04:00
return NT_STATUS_INTERNAL_ERROR ;
2011-12-28 10:48:45 +04:00
}
2021-04-21 12:30:20 +03:00
status = auth_context - > generate_session_info_pac (
auth_context ,
mem_ctx ,
smb_krb5_context ,
pac_blob ,
principal_string ,
remote_address ,
session_info_flags ,
session_info ) ;
return status ;
2011-12-28 10:48:45 +04:00
}
2012-01-13 01:03:07 +04:00
2012-04-01 05:37:56 +04:00
/*
magic check a GSS - API wrapper packet for an Kerberos OID
*/
static bool gensec_gssapi_check_oid ( const DATA_BLOB * blob , const char * oid )
{
2014-09-19 23:41:22 +04:00
bool ret = false ;
2020-04-03 02:18:03 +03:00
struct asn1_data * data = asn1_init ( NULL , ASN1_MAX_TREE_DEPTH ) ;
2012-04-01 05:37:56 +04:00
if ( ! data ) return false ;
2014-09-19 23:41:22 +04:00
if ( ! asn1_load ( data , * blob ) ) goto err ;
if ( ! asn1_start_tag ( data , ASN1_APPLICATION ( 0 ) ) ) goto err ;
if ( ! asn1_check_OID ( data , oid ) ) goto err ;
2012-04-01 05:37:56 +04:00
2016-01-02 20:11:00 +03:00
ret = ! asn1_has_error ( data ) ;
2012-04-01 05:37:56 +04:00
2014-09-19 23:41:22 +04:00
err :
2012-04-01 05:37:56 +04:00
2014-09-19 23:41:22 +04:00
asn1_free ( data ) ;
2012-04-01 05:37:56 +04:00
return ret ;
}
/**
2023-03-14 10:50:34 +03:00
* Check if the packet is one for the KRB5 mechanism
2012-04-01 05:37:56 +04:00
*
* NOTE : This is a helper that can be employed by multiple mechanisms , do
* not make assumptions about the private_data
*
* @ param gensec_security GENSEC state , unused
* @ param in The request , as a DATA_BLOB
* @ return Error , INVALID_PARAMETER if it ' s not a packet for us
* or NT_STATUS_OK if the packet is ok .
*/
NTSTATUS gensec_magic_check_krb5_oid ( struct gensec_security * unused ,
const DATA_BLOB * blob )
{
if ( gensec_gssapi_check_oid ( blob , GENSEC_OID_KERBEROS5 ) ) {
return NT_STATUS_OK ;
} else {
return NT_STATUS_INVALID_PARAMETER ;
}
}
2016-12-30 19:54:12 +03:00
void gensec_child_want_feature ( struct gensec_security * gensec_security ,
uint32_t feature )
{
struct gensec_security * child_security = gensec_security - > child_security ;
gensec_security - > want_features | = feature ;
if ( child_security = = NULL ) {
return ;
}
gensec_want_feature ( child_security , feature ) ;
}
bool gensec_child_have_feature ( struct gensec_security * gensec_security ,
uint32_t feature )
{
struct gensec_security * child_security = gensec_security - > child_security ;
if ( feature & GENSEC_FEATURE_SIGN_PKT_HEADER ) {
/*
* All mechs with sub ( child ) mechs need to provide DCERPC
* header signing ! This is required because the negotiation
* of header signing is done before the authentication
* is completed .
*/
return true ;
}
if ( child_security = = NULL ) {
return false ;
}
return gensec_have_feature ( child_security , feature ) ;
}
NTSTATUS gensec_child_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 - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_unseal_packet ( gensec_security - > child_security ,
data , length ,
whole_pdu , pdu_length ,
sig ) ;
}
NTSTATUS gensec_child_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 - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_check_packet ( gensec_security - > child_security ,
data , length ,
whole_pdu , pdu_length ,
sig ) ;
}
NTSTATUS gensec_child_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 - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_seal_packet ( gensec_security - > child_security ,
mem_ctx ,
data , length ,
whole_pdu , pdu_length ,
sig ) ;
}
NTSTATUS gensec_child_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 - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_sign_packet ( gensec_security - > child_security ,
mem_ctx ,
data , length ,
whole_pdu , pdu_length ,
sig ) ;
}
NTSTATUS gensec_child_wrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
if ( gensec_security - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_wrap ( gensec_security - > child_security ,
mem_ctx , in , out ) ;
}
NTSTATUS gensec_child_unwrap ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
const DATA_BLOB * in ,
DATA_BLOB * out )
{
if ( gensec_security - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_unwrap ( gensec_security - > child_security ,
mem_ctx , in , out ) ;
}
size_t gensec_child_sig_size ( struct gensec_security * gensec_security ,
size_t data_size )
{
if ( gensec_security - > child_security = = NULL ) {
return 0 ;
}
return gensec_sig_size ( gensec_security - > child_security , data_size ) ;
}
size_t gensec_child_max_input_size ( struct gensec_security * gensec_security )
{
if ( gensec_security - > child_security = = NULL ) {
return 0 ;
}
return gensec_max_input_size ( gensec_security - > child_security ) ;
}
size_t gensec_child_max_wrapped_size ( struct gensec_security * gensec_security )
{
if ( gensec_security - > child_security = = NULL ) {
return 0 ;
}
return gensec_max_wrapped_size ( gensec_security - > child_security ) ;
}
NTSTATUS gensec_child_session_key ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * session_key )
{
if ( gensec_security - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_session_key ( gensec_security - > child_security ,
mem_ctx ,
session_key ) ;
}
NTSTATUS gensec_child_session_info ( struct gensec_security * gensec_security ,
TALLOC_CTX * mem_ctx ,
struct auth_session_info * * session_info )
{
if ( gensec_security - > child_security = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
return gensec_session_info ( gensec_security - > child_security ,
mem_ctx ,
session_info ) ;
}
NTTIME gensec_child_expire_time ( struct gensec_security * gensec_security )
{
if ( gensec_security - > child_security = = NULL ) {
return GENSEC_EXPIRE_TIME_INFINITY ;
}
return gensec_expire_time ( gensec_security - > child_security ) ;
}
const char * gensec_child_final_auth_type ( struct gensec_security * gensec_security )
{
if ( gensec_security - > child_security = = NULL ) {
return " NONE " ;
}
return gensec_final_auth_type ( gensec_security - > child_security ) ;
}