2002-06-25 02:29:09 +00:00
/*
Unix SMB / CIFS implementation .
kerberos utility library
Copyright ( C ) Andrew Tridgell 2001
Copyright ( C ) Remus Koos 2001
2003-03-17 22:46:12 +00:00
Copyright ( C ) Luke Howard 2003
2005-09-30 17:13:37 +00:00
Copyright ( C ) Guenther Deschner 2003 , 2005
2003-09-03 00:45:15 +00:00
Copyright ( C ) Jim McDonough ( jmcd @ us . ibm . com ) 2003
2005-09-30 17:13:37 +00:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2005
2007-03-15 19:18:18 +00:00
Copyright ( C ) Jeremy Allison 2007
2002-06-25 02:29:09 +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-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2002-06-25 02:29:09 +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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# ifdef HAVE_KRB5
2004-08-12 20:27:09 +00:00
# if !defined(HAVE_KRB5_PRINC_COMPONENT)
const krb5_data * krb5_princ_component ( krb5_context , krb5_principal , int ) ;
# endif
2004-06-22 00:48:59 +00:00
/**********************************************************************************
Try to verify a ticket using the system keytab . . . the system keytab has kvno - 1 entries , so
it ' s more like what microsoft does . . . see comment in utils / net_ads . c in the
ads_keytab_add_entry function for details .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-15 19:18:18 +00:00
static BOOL ads_keytab_verify_ticket ( krb5_context context ,
krb5_auth_context auth_context ,
const DATA_BLOB * ticket ,
krb5_ticket * * pp_tkt ,
krb5_keyblock * * keyblock ,
krb5_error_code * perr )
2004-06-22 00:48:59 +00:00
{
krb5_error_code ret = 0 ;
BOOL auth_ok = False ;
krb5_keytab keytab = NULL ;
2005-03-12 01:28:10 +00:00
krb5_kt_cursor kt_cursor ;
krb5_keytab_entry kt_entry ;
char * valid_princ_formats [ 7 ] = { NULL , NULL , NULL , NULL , NULL , NULL , NULL } ;
char * entry_princ_s = NULL ;
fstring my_name , my_fqdn ;
2004-10-30 01:32:05 +00:00
int i ;
2005-03-12 01:28:10 +00:00
int number_matched_principals = 0 ;
2007-03-15 19:18:18 +00:00
krb5_data packet ;
* pp_tkt = NULL ;
* keyblock = NULL ;
* perr = 0 ;
2005-03-12 01:28:10 +00:00
/* Generate the list of principal names which we expect
* clients might want to use for authenticating to the file
* service . We allow name $ , { host , cifs } / { name , fqdn , name . REALM } . */
fstrcpy ( my_name , global_myname ( ) ) ;
my_fqdn [ 0 ] = ' \0 ' ;
name_to_fqdn ( my_fqdn , global_myname ( ) ) ;
asprintf ( & valid_princ_formats [ 0 ] , " %s$@%s " , my_name , lp_realm ( ) ) ;
asprintf ( & valid_princ_formats [ 1 ] , " host/%s@%s " , my_name , lp_realm ( ) ) ;
asprintf ( & valid_princ_formats [ 2 ] , " host/%s@%s " , my_fqdn , lp_realm ( ) ) ;
asprintf ( & valid_princ_formats [ 3 ] , " host/%s.%s@%s " , my_name , lp_realm ( ) , lp_realm ( ) ) ;
asprintf ( & valid_princ_formats [ 4 ] , " cifs/%s@%s " , my_name , lp_realm ( ) ) ;
asprintf ( & valid_princ_formats [ 5 ] , " cifs/%s@%s " , my_fqdn , lp_realm ( ) ) ;
asprintf ( & valid_princ_formats [ 6 ] , " cifs/%s.%s@%s " , my_name , lp_realm ( ) , lp_realm ( ) ) ;
ZERO_STRUCT ( kt_entry ) ;
ZERO_STRUCT ( kt_cursor ) ;
2004-06-24 20:37:23 +00:00
2007-06-29 08:58:03 +00:00
ret = smb_krb5_open_keytab ( context , NULL , False , & keytab ) ;
2004-06-22 00:48:59 +00:00
if ( ret ) {
2007-06-29 08:58:03 +00:00
DEBUG ( 1 , ( " ads_keytab_verify_ticket: smb_krb5_open_keytab failed (%s) \n " , error_message ( ret ) ) ) ;
2004-06-22 00:48:59 +00:00
goto out ;
}
2005-03-12 01:28:10 +00:00
/* Iterate through the keytab. For each key, if the principal
* name case - insensitively matches one of the allowed formats ,
* try verifying the ticket using that principal . */
2004-10-30 01:32:05 +00:00
2005-03-12 01:28:10 +00:00
ret = krb5_kt_start_seq_get ( context , keytab , & kt_cursor ) ;
if ( ret ) {
DEBUG ( 1 , ( " ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s) \n " , error_message ( ret ) ) ) ;
goto out ;
}
2007-02-27 13:27:31 +00:00
while ( ! auth_ok & & ( krb5_kt_next_entry ( context , keytab , & kt_entry , & kt_cursor ) = = 0 ) ) {
ret = smb_krb5_unparse_name ( context , kt_entry . principal , & entry_princ_s ) ;
if ( ret ) {
DEBUG ( 1 , ( " ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s) \n " ,
error_message ( ret ) ) ) ;
goto out ;
}
2005-03-12 01:28:10 +00:00
2007-02-27 13:31:42 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( valid_princ_formats ) ; i + + ) {
if ( ! strequal ( entry_princ_s , valid_princ_formats [ i ] ) ) {
continue ;
}
number_matched_principals + + ;
2007-03-15 19:18:18 +00:00
packet . length = ticket - > length ;
packet . data = ( char * ) ticket - > data ;
2007-02-27 13:31:42 +00:00
* pp_tkt = NULL ;
2007-03-15 19:18:18 +00:00
ret = krb5_rd_req_return_keyblock_from_keytab ( context , & auth_context , & packet ,
2007-02-27 13:31:42 +00:00
kt_entry . principal , keytab ,
NULL , pp_tkt , keyblock ) ;
if ( ret ) {
DEBUG ( 10 , ( " ads_keytab_verify_ticket: "
" krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s \n " ,
entry_princ_s , error_message ( ret ) ) ) ;
/* workaround for MIT:
* as krb5_ktfile_get_entry will explicitly
* close the krb5_keytab as soon as krb5_rd_req
* has sucessfully decrypted the ticket but the
* ticket is not valid yet ( due to clockskew )
* there is no point in querying more keytab
* entries - Guenther */
if ( ret = = KRB5KRB_AP_ERR_TKT_NYV | |
2007-03-15 19:18:18 +00:00
ret = = KRB5KRB_AP_ERR_TKT_EXPIRED | |
ret = = KRB5KRB_AP_ERR_SKEW ) {
2007-02-27 13:27:31 +00:00
break ;
2005-03-12 01:28:10 +00:00
}
2007-02-27 13:31:42 +00:00
} else {
DEBUG ( 3 , ( " ads_keytab_verify_ticket: "
" krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s \n " ,
entry_princ_s ) ) ;
auth_ok = True ;
break ;
2005-03-12 01:28:10 +00:00
}
2007-02-27 13:27:31 +00:00
}
2005-03-12 01:28:10 +00:00
2007-02-27 13:27:31 +00:00
/* Free the name we parsed. */
SAFE_FREE ( entry_princ_s ) ;
2005-03-12 01:28:10 +00:00
2007-02-27 13:27:31 +00:00
/* Free the entry we just read. */
smb_krb5_kt_free_entry ( context , & kt_entry ) ;
ZERO_STRUCT ( kt_entry ) ;
}
krb5_kt_end_seq_get ( context , keytab , & kt_cursor ) ;
2004-10-30 01:32:05 +00:00
2005-03-12 01:28:10 +00:00
ZERO_STRUCT ( kt_cursor ) ;
2004-10-30 01:32:05 +00:00
2005-03-12 01:28:10 +00:00
out :
2005-09-13 21:26:25 +00:00
2007-02-27 13:31:42 +00:00
for ( i = 0 ; i < ARRAY_SIZE ( valid_princ_formats ) ; i + + ) {
2005-09-13 21:26:25 +00:00
SAFE_FREE ( valid_princ_formats [ i ] ) ;
}
2005-03-12 01:28:10 +00:00
if ( ! auth_ok ) {
if ( ! number_matched_principals ) {
DEBUG ( 3 , ( " ads_keytab_verify_ticket: no keytab principals matched expected file service name. \n " ) ) ;
} else {
DEBUG ( 3 , ( " ads_keytab_verify_ticket: krb5_rd_req failed for all %d matched keytab principals \n " ,
number_matched_principals ) ) ;
}
}
2004-10-30 01:32:05 +00:00
2006-04-24 15:57:54 +00:00
SAFE_FREE ( entry_princ_s ) ;
2004-06-22 00:48:59 +00:00
2005-03-12 01:28:10 +00:00
{
krb5_keytab_entry zero_kt_entry ;
ZERO_STRUCT ( zero_kt_entry ) ;
if ( memcmp ( & zero_kt_entry , & kt_entry , sizeof ( krb5_keytab_entry ) ) ) {
smb_krb5_kt_free_entry ( context , & kt_entry ) ;
2004-06-22 00:48:59 +00:00
}
}
2004-10-30 01:32:05 +00:00
2005-03-12 01:28:10 +00:00
{
krb5_kt_cursor zero_csr ;
ZERO_STRUCT ( zero_csr ) ;
if ( ( memcmp ( & kt_cursor , & zero_csr , sizeof ( krb5_kt_cursor ) ) ! = 0 ) & & keytab ) {
krb5_kt_end_seq_get ( context , keytab , & kt_cursor ) ;
}
2004-06-22 00:48:59 +00:00
}
if ( keytab ) {
krb5_kt_close ( context , keytab ) ;
}
2007-03-15 19:18:18 +00:00
* perr = ret ;
2004-06-22 00:48:59 +00:00
return auth_ok ;
}
/**********************************************************************************
Try to verify a ticket using the secrets . tdb .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-15 19:18:18 +00:00
static krb5_error_code ads_secrets_verify_ticket ( krb5_context context ,
krb5_auth_context auth_context ,
krb5_principal host_princ ,
const DATA_BLOB * ticket ,
krb5_ticket * * pp_tkt ,
krb5_keyblock * * keyblock ,
krb5_error_code * perr )
2004-06-22 00:48:59 +00:00
{
krb5_error_code ret = 0 ;
BOOL auth_ok = False ;
char * password_s = NULL ;
krb5_data password ;
2007-06-13 20:49:20 +00:00
krb5_enctype enctypes [ ] = {
# if defined(ENCTYPE_ARCFOUR_HMAC)
ENCTYPE_ARCFOUR_HMAC ,
# endif
ENCTYPE_DES_CBC_CRC ,
ENCTYPE_DES_CBC_MD5 ,
ENCTYPE_NULL
} ;
2007-03-15 19:18:18 +00:00
krb5_data packet ;
2004-06-22 00:48:59 +00:00
int i ;
2007-03-15 19:18:18 +00:00
* pp_tkt = NULL ;
* keyblock = NULL ;
* perr = 0 ;
2006-07-11 18:45:22 +00:00
2004-06-22 00:48:59 +00:00
if ( ! secrets_init ( ) ) {
DEBUG ( 1 , ( " ads_secrets_verify_ticket: secrets_init failed \n " ) ) ;
2007-03-15 19:18:18 +00:00
* perr = KRB5_CONFIG_CANTOPEN ;
2004-06-22 00:48:59 +00:00
return False ;
}
password_s = secrets_fetch_machine_password ( lp_workgroup ( ) , NULL , NULL ) ;
if ( ! password_s ) {
DEBUG ( 1 , ( " ads_secrets_verify_ticket: failed to fetch machine password \n " ) ) ;
2007-03-15 19:18:18 +00:00
* perr = KRB5_LIBOS_CANTREADPWD ;
2004-06-22 00:48:59 +00:00
return False ;
}
password . data = password_s ;
password . length = strlen ( password_s ) ;
/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
2007-03-15 19:18:18 +00:00
packet . length = ticket - > length ;
packet . data = ( char * ) ticket - > data ;
2004-06-22 00:48:59 +00:00
/* We need to setup a auth context with each possible encoding type in turn. */
for ( i = 0 ; enctypes [ i ] ; i + + ) {
krb5_keyblock * key = NULL ;
2004-12-07 18:25:53 +00:00
if ( ! ( key = SMB_MALLOC_P ( krb5_keyblock ) ) ) {
2007-03-15 19:18:18 +00:00
ret = ENOMEM ;
2004-06-22 00:48:59 +00:00
goto out ;
}
if ( create_kerberos_key_from_string ( context , host_princ , & password , key , enctypes [ i ] ) ) {
SAFE_FREE ( key ) ;
continue ;
}
krb5_auth_con_setuseruserkey ( context , auth_context , key ) ;
2007-03-15 19:18:18 +00:00
if ( ! ( ret = krb5_rd_req ( context , & auth_context , & packet ,
2004-06-22 00:48:59 +00:00
NULL ,
NULL , NULL , pp_tkt ) ) ) {
DEBUG ( 10 , ( " ads_secrets_verify_ticket: enc type [%u] decrypted message ! \n " ,
( unsigned int ) enctypes [ i ] ) ) ;
auth_ok = True ;
2005-09-30 17:13:37 +00:00
krb5_copy_keyblock ( context , key , keyblock ) ;
krb5_free_keyblock ( context , key ) ;
2004-06-22 00:48:59 +00:00
break ;
}
2006-03-20 10:05:51 +00:00
2004-06-22 00:48:59 +00:00
DEBUG ( ( ret ! = KRB5_BAD_ENCTYPE ) ? 3 : 10 ,
( " ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s \n " ,
( unsigned int ) enctypes [ i ] , error_message ( ret ) ) ) ;
2005-09-30 17:13:37 +00:00
2006-03-20 10:05:51 +00:00
/* successfully decrypted but ticket is just not valid at the moment */
if ( ret = = KRB5KRB_AP_ERR_TKT_NYV | |
2007-03-15 19:18:18 +00:00
ret = = KRB5KRB_AP_ERR_TKT_EXPIRED | |
ret = = KRB5KRB_AP_ERR_SKEW ) {
2006-03-20 10:05:51 +00:00
break ;
}
2005-09-30 17:13:37 +00:00
krb5_free_keyblock ( context , key ) ;
2004-06-22 00:48:59 +00:00
}
out :
SAFE_FREE ( password_s ) ;
2007-03-15 19:18:18 +00:00
* perr = ret ;
2004-06-22 00:48:59 +00:00
return auth_ok ;
}
/**********************************************************************************
Verify an incoming ticket and parse out the principal name and
authorization_data if available .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 17:13:37 +00:00
NTSTATUS ads_verify_ticket ( TALLOC_CTX * mem_ctx ,
2007-03-15 19:18:18 +00:00
const char * realm ,
time_t time_offset ,
const DATA_BLOB * ticket ,
char * * principal ,
PAC_DATA * * pac_data ,
2003-03-17 22:46:12 +00:00
DATA_BLOB * ap_rep ,
2007-06-13 20:49:20 +00:00
DATA_BLOB * session_key ,
BOOL use_replay_cache )
2002-06-25 02:29:09 +00:00
{
2003-07-12 00:27:22 +00:00
NTSTATUS sret = NT_STATUS_LOGON_FAILURE ;
2005-10-11 16:27:05 +00:00
NTSTATUS pac_ret ;
2005-09-30 17:13:37 +00:00
DATA_BLOB auth_data ;
2003-07-12 00:27:22 +00:00
krb5_context context = NULL ;
2002-06-25 02:29:09 +00:00
krb5_auth_context auth_context = NULL ;
krb5_data packet ;
krb5_ticket * tkt = NULL ;
2003-07-12 00:27:22 +00:00
krb5_rcache rcache = NULL ;
2005-09-30 17:13:37 +00:00
krb5_keyblock * keyblock = NULL ;
time_t authtime ;
2007-03-15 19:18:18 +00:00
krb5_error_code ret = 0 ;
2007-06-13 21:59:39 +00:00
int flags = 0 ;
2004-06-22 00:48:59 +00:00
krb5_principal host_princ = NULL ;
2005-09-30 17:13:37 +00:00
krb5_const_principal client_principal = NULL ;
2003-07-12 00:27:22 +00:00
char * host_princ_s = NULL ;
2003-02-19 15:48:12 +00:00
BOOL auth_ok = False ;
2007-03-15 19:18:18 +00:00
BOOL got_replay_mutex = False ;
2005-09-30 17:13:37 +00:00
BOOL got_auth_data = False ;
2002-06-25 02:29:09 +00:00
2003-07-12 00:27:22 +00:00
ZERO_STRUCT ( packet ) ;
2005-09-30 17:13:37 +00:00
ZERO_STRUCT ( auth_data ) ;
2007-03-15 19:18:18 +00:00
* principal = NULL ;
* pac_data = NULL ;
2007-05-14 12:16:20 +00:00
* ap_rep = data_blob_null ;
* session_key = data_blob_null ;
2003-07-12 00:27:22 +00:00
2004-06-22 00:48:59 +00:00
initialize_krb5_error_table ( ) ;
2002-06-25 02:29:09 +00:00
ret = krb5_init_context ( & context ) ;
if ( ret ) {
2003-07-29 00:31:44 +00:00
DEBUG ( 1 , ( " ads_verify_ticket: krb5_init_context failed (%s) \n " , error_message ( ret ) ) ) ;
2002-06-25 02:29:09 +00:00
return NT_STATUS_LOGON_FAILURE ;
}
2006-05-09 19:02:26 +00:00
if ( time_offset ! = 0 ) {
krb5_set_real_time ( context , time ( NULL ) + time_offset , 0 ) ;
}
2003-08-14 21:07:49 +00:00
ret = krb5_set_default_realm ( context , realm ) ;
2002-06-25 02:29:09 +00:00
if ( ret ) {
2003-07-29 00:31:44 +00:00
DEBUG ( 1 , ( " ads_verify_ticket: krb5_set_default_realm failed (%s) \n " , error_message ( ret ) ) ) ;
2003-07-12 00:27:22 +00:00
goto out ;
2002-06-25 02:29:09 +00:00
}
2003-07-12 00:27:22 +00:00
/* This whole process is far more complex than I would
2002-06-25 02:29:09 +00:00
like . We have to go through all this to allow us to store
the secret internally , instead of using / etc / krb5 . keytab */
2003-07-12 00:27:22 +00:00
2002-06-25 02:29:09 +00:00
ret = krb5_auth_con_init ( context , & auth_context ) ;
if ( ret ) {
2003-07-29 00:31:44 +00:00
DEBUG ( 1 , ( " ads_verify_ticket: krb5_auth_con_init failed (%s) \n " , error_message ( ret ) ) ) ;
2003-07-12 00:27:22 +00:00
goto out ;
2002-06-25 02:29:09 +00:00
}
2007-06-13 20:49:20 +00:00
krb5_auth_con_getflags ( context , auth_context , & flags ) ;
if ( ! use_replay_cache ) {
/* Disable default use of a replay cache */
flags & = ~ KRB5_AUTH_CONTEXT_DO_TIME ;
krb5_auth_con_setflags ( context , auth_context , flags ) ;
}
2004-11-02 02:21:26 +00:00
asprintf ( & host_princ_s , " %s$ " , global_myname ( ) ) ;
2007-03-15 19:18:18 +00:00
if ( ! host_princ_s ) {
goto out ;
}
2004-11-02 02:21:26 +00:00
strlower_m ( host_princ_s ) ;
2006-04-24 15:57:54 +00:00
ret = smb_krb5_parse_name ( context , host_princ_s , & host_princ ) ;
2002-06-25 02:29:09 +00:00
if ( ret ) {
2006-04-24 15:57:54 +00:00
DEBUG ( 1 , ( " ads_verify_ticket: smb_krb5_parse_name(%s) failed (%s) \n " ,
2003-07-29 00:31:44 +00:00
host_princ_s , error_message ( ret ) ) ) ;
2003-07-12 00:27:22 +00:00
goto out ;
}
2004-06-22 00:48:59 +00:00
2007-06-13 20:49:20 +00:00
if ( use_replay_cache ) {
/* Lock a mutex surrounding the replay as there is no
locking in the MIT krb5 code surrounding the replay
cache . . . */
2004-06-22 00:48:59 +00:00
2007-06-13 20:49:20 +00:00
if ( ! grab_server_mutex ( " replay cache mutex " ) ) {
DEBUG ( 1 , ( " ads_verify_ticket: unable to protect "
" replay cache with mutex. \n " ) ) ;
ret = KRB5_CC_IO ;
goto out ;
}
2004-06-22 00:48:59 +00:00
2007-06-13 20:49:20 +00:00
got_replay_mutex = True ;
2004-01-06 23:57:12 +00:00
2007-06-13 20:49:20 +00:00
/* JRA. We must set the rcache here. This will prevent
replay attacks . */
ret = krb5_get_server_rcache ( context ,
krb5_princ_component ( context , host_princ , 0 ) ,
& rcache ) ;
if ( ret ) {
DEBUG ( 1 , ( " ads_verify_ticket: krb5_get_server_rcache "
" failed (%s) \n " , error_message ( ret ) ) ) ;
goto out ;
}
2003-07-12 00:27:22 +00:00
2007-06-13 20:49:20 +00:00
ret = krb5_auth_con_setrcache ( context , auth_context , rcache ) ;
if ( ret ) {
DEBUG ( 1 , ( " ads_verify_ticket: krb5_auth_con_setrcache "
" failed (%s) \n " , error_message ( ret ) ) ) ;
goto out ;
}
2003-07-12 00:27:22 +00:00
}
2007-06-13 20:49:20 +00:00
/* Try secrets.tdb first and fallback to the krb5.keytab if
necessary */
2002-06-25 02:29:09 +00:00
2007-06-13 20:49:20 +00:00
auth_ok = ads_secrets_verify_ticket ( context , auth_context , host_princ ,
ticket , & tkt , & keyblock , & ret ) ;
2003-02-19 15:48:12 +00:00
2007-06-13 20:49:20 +00:00
if ( ! auth_ok & & lp_use_kerberos_keytab ( ) ) {
auth_ok = ads_keytab_verify_ticket ( context , auth_context ,
ticket , & tkt , & keyblock , & ret ) ;
}
2003-07-29 21:32:36 +00:00
2007-06-13 20:49:20 +00:00
if ( use_replay_cache ) {
release_server_mutex ( ) ;
got_replay_mutex = False ;
2005-09-30 17:13:37 +00:00
#if 0
2007-06-13 20:49:20 +00:00
/* Heimdal leaks here, if we fix the leak, MIT crashes */
if ( rcache ) {
krb5_rc_close ( context , rcache ) ;
}
2005-09-30 17:13:37 +00:00
# endif
2007-06-13 20:49:20 +00:00
}
2005-09-30 17:13:37 +00:00
2003-02-19 15:48:12 +00:00
if ( ! auth_ok ) {
2003-07-29 00:31:44 +00:00
DEBUG ( 3 , ( " ads_verify_ticket: krb5_rd_req with auth failed (%s) \n " ,
2002-06-25 02:29:09 +00:00
error_message ( ret ) ) ) ;
2007-03-15 19:18:18 +00:00
/* Try map the error return in case it's something like
* a clock skew error .
*/
sret = krb5_to_nt_status ( ret ) ;
if ( NT_STATUS_IS_OK ( sret ) | | NT_STATUS_EQUAL ( sret , NT_STATUS_UNSUCCESSFUL ) ) {
sret = NT_STATUS_LOGON_FAILURE ;
}
DEBUG ( 10 , ( " ads_verify_ticket: returning error %s \n " ,
nt_errstr ( sret ) ) ) ;
2003-07-12 00:27:22 +00:00
goto out ;
2006-03-23 17:32:21 +00:00
}
authtime = get_authtime_from_tkt ( tkt ) ;
client_principal = get_principal_from_tkt ( tkt ) ;
2002-06-25 02:29:09 +00:00
2003-03-17 22:46:12 +00:00
ret = krb5_mk_rep ( context , auth_context , & packet ) ;
if ( ret ) {
2003-07-29 00:31:44 +00:00
DEBUG ( 3 , ( " ads_verify_ticket: Failed to generate mutual authentication reply (%s) \n " ,
2003-03-17 22:46:12 +00:00
error_message ( ret ) ) ) ;
2003-07-12 00:27:22 +00:00
goto out ;
2003-03-17 22:46:12 +00:00
}
* ap_rep = data_blob ( packet . data , packet . length ) ;
2007-03-15 19:18:18 +00:00
if ( packet . data ) {
kerberos_free_data_contents ( context , & packet ) ;
ZERO_STRUCT ( packet ) ;
}
2003-03-17 22:46:12 +00:00
2003-07-25 23:15:30 +00:00
get_krb5_smb_session_key ( context , auth_context , session_key , True ) ;
2004-01-06 23:57:12 +00:00
dump_data_pw ( " SMB session key (from ticket) \n " , session_key - > data , session_key - > length ) ;
2003-03-17 22:46:12 +00:00
2003-02-19 15:48:12 +00:00
#if 0
file_save ( " /tmp/ticket.dat " , ticket - > data , ticket - > length ) ;
# endif
2005-11-22 10:22:59 +00:00
/* continue when no PAC is retrieved or we couldn't decode the PAC
( like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set , or
Kerberos tickets encrypted using a DES key ) - Guenther */
2002-06-25 02:29:09 +00:00
2005-09-30 17:13:37 +00:00
got_auth_data = get_auth_data_from_tkt ( mem_ctx , & auth_data , tkt ) ;
if ( ! got_auth_data ) {
DEBUG ( 3 , ( " ads_verify_ticket: did not retrieve auth data. continuing without PAC \n " ) ) ;
}
if ( got_auth_data & & pac_data ! = NULL ) {
2005-10-11 16:27:05 +00:00
pac_ret = decode_pac_data ( mem_ctx , & auth_data , context , keyblock , client_principal , authtime , pac_data ) ;
if ( ! NT_STATUS_IS_OK ( pac_ret ) ) {
DEBUG ( 3 , ( " ads_verify_ticket: failed to decode PAC_DATA: %s \n " , nt_errstr ( pac_ret ) ) ) ;
* pac_data = NULL ;
2005-09-30 17:13:37 +00:00
}
data_blob_free ( & auth_data ) ;
2003-04-16 16:57:01 +00:00
}
2002-06-25 02:29:09 +00:00
#if 0
2005-09-30 17:13:37 +00:00
# if defined(HAVE_KRB5_TKT_ENC_PART2)
/* MIT */
2002-06-25 02:29:09 +00:00
if ( tkt - > enc_part2 ) {
2003-03-17 22:46:12 +00:00
file_save ( " /tmp/authdata.dat " ,
2002-06-25 02:29:09 +00:00
tkt - > enc_part2 - > authorization_data [ 0 ] - > contents ,
tkt - > enc_part2 - > authorization_data [ 0 ] - > length ) ;
2003-09-03 00:45:15 +00:00
}
2005-09-30 17:13:37 +00:00
# else
/* Heimdal */
if ( tkt - > ticket . authorization_data ) {
file_save ( " /tmp/authdata.dat " ,
tkt - > ticket . authorization_data - > val - > ad_data . data ,
tkt - > ticket . authorization_data - > val - > ad_data . length ) ;
}
# endif
2002-06-25 02:29:09 +00:00
# endif
2006-04-24 15:57:54 +00:00
if ( ( ret = smb_krb5_unparse_name ( context , client_principal , principal ) ) ) {
DEBUG ( 3 , ( " ads_verify_ticket: smb_krb5_unparse_name failed (%s) \n " ,
2002-06-25 02:29:09 +00:00
error_message ( ret ) ) ) ;
2003-07-12 00:27:22 +00:00
sret = NT_STATUS_LOGON_FAILURE ;
goto out ;
}
sret = NT_STATUS_OK ;
out :
2004-06-22 00:48:59 +00:00
if ( got_replay_mutex ) {
2004-02-03 03:23:18 +00:00
release_server_mutex ( ) ;
2004-06-22 00:48:59 +00:00
}
2004-02-03 03:23:18 +00:00
2004-06-22 00:48:59 +00:00
if ( ! NT_STATUS_IS_OK ( sret ) ) {
2005-09-30 17:13:37 +00:00
data_blob_free ( & auth_data ) ;
2004-06-22 00:48:59 +00:00
}
2003-07-12 00:27:22 +00:00
2004-06-22 00:48:59 +00:00
if ( ! NT_STATUS_IS_OK ( sret ) ) {
2003-03-17 22:46:12 +00:00
data_blob_free ( ap_rep ) ;
2004-06-22 00:48:59 +00:00
}
2003-07-12 00:27:22 +00:00
2004-06-22 00:48:59 +00:00
if ( host_princ ) {
2004-01-06 23:57:12 +00:00
krb5_free_principal ( context , host_princ ) ;
2004-06-22 00:48:59 +00:00
}
2004-01-06 23:57:12 +00:00
2005-09-30 17:13:37 +00:00
if ( keyblock ) {
krb5_free_keyblock ( context , keyblock ) ;
}
2004-06-22 00:48:59 +00:00
if ( tkt ! = NULL ) {
2003-08-25 09:13:20 +00:00
krb5_free_ticket ( context , tkt ) ;
2004-06-22 00:48:59 +00:00
}
2003-08-15 01:46:09 +00:00
SAFE_FREE ( host_princ_s ) ;
2003-07-12 00:27:22 +00:00
2004-06-22 00:48:59 +00:00
if ( auth_context ) {
2003-03-17 22:46:12 +00:00
krb5_auth_con_free ( context , auth_context ) ;
2004-06-22 00:48:59 +00:00
}
2002-06-25 02:29:09 +00:00
2004-06-22 00:48:59 +00:00
if ( context ) {
2003-07-12 00:27:22 +00:00
krb5_free_context ( context ) ;
2004-06-22 00:48:59 +00:00
}
2003-03-17 22:46:12 +00:00
2003-07-12 00:27:22 +00:00
return sret ;
2002-06-25 02:29:09 +00:00
}
2003-03-17 22:46:12 +00:00
# endif /* HAVE_KRB5 */