2005-07-11 01:16:55 +00:00
/*
2008-10-27 11:35:07 +01:00
* Copyright ( c ) 1997 - 2001 Kungliga Tekniska Högskolan
* ( Royal Institute of Technology , Stockholm , Sweden ) .
* All rights reserved .
2005-07-11 01:16:55 +00:00
*
2008-10-27 11:35:07 +01:00
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
2005-07-11 01:16:55 +00:00
*
2008-10-27 11:35:07 +01:00
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
2005-07-11 01:16:55 +00:00
*
2008-10-27 11:35:07 +01:00
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2005-07-11 01:16:55 +00:00
*
2008-10-27 11:35:07 +01:00
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
2005-07-11 01:16:55 +00:00
*
2008-10-27 11:35:07 +01:00
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
2005-07-11 01:16:55 +00:00
*/
# include "kdc_locl.h"
struct timeval _kdc_now ;
krb5_error_code
_kdc_db_fetch ( krb5_context context ,
krb5_kdc_configuration * config ,
2006-05-07 04:51:30 +00:00
krb5_const_principal principal ,
unsigned flags ,
2016-05-17 13:45:11 +03:00
krb5uint32 * kvno_ptr ,
2006-11-07 06:59:56 +00:00
HDB * * db ,
2005-12-15 20:38:24 +00:00
hdb_entry_ex * * h )
2005-07-11 01:16:55 +00:00
{
2005-12-15 20:38:24 +00:00
hdb_entry_ex * ent ;
2010-11-12 12:31:33 +11:00
krb5_error_code ret = HDB_ERR_NOENTRY ;
2005-07-11 01:16:55 +00:00
int i ;
2010-10-02 16:32:56 +10:00
unsigned kvno = 0 ;
2014-12-17 16:55:34 +13:00
krb5_principal enterprise_principal = NULL ;
krb5_const_principal princ ;
* h = NULL ;
2010-09-28 13:07:53 +10:00
if ( kvno_ptr ) {
kvno = * kvno_ptr ;
flags | = HDB_F_KVNO_SPECIFIED ;
}
2005-07-11 01:16:55 +00:00
2014-12-17 16:55:34 +13:00
ent = calloc ( 1 , sizeof ( * ent ) ) ;
if ( ent = = NULL )
return krb5_enomem ( context ) ;
2005-07-11 01:16:55 +00:00
2014-12-17 16:55:34 +13:00
if ( principal - > name . name_type = = KRB5_NT_ENTERPRISE_PRINCIPAL ) {
if ( principal - > name . name_string . len ! = 1 ) {
ret = KRB5_PARSE_MALFORMED ;
krb5_set_error_message ( context , ret ,
" malformed request: "
" enterprise name with %d name components " ,
principal - > name . name_string . len ) ;
goto out ;
}
ret = krb5_parse_name ( context , principal - > name . name_string . val [ 0 ] ,
& enterprise_principal ) ;
if ( ret )
goto out ;
}
2009-06-30 12:11:14 +10:00
2014-12-17 16:55:34 +13:00
for ( i = 0 ; i < config - > num_db ; i + + ) {
2005-07-11 01:16:55 +00:00
ret = config - > db [ i ] - > hdb_open ( context , config - > db [ i ] , O_RDONLY , 0 ) ;
if ( ret ) {
2009-11-13 10:51:14 +11:00
const char * msg = krb5_get_error_message ( context , ret ) ;
kdc_log ( context , config , 0 , " Failed to open database: %s " , msg ) ;
krb5_free_error_message ( context , msg ) ;
2005-07-11 01:16:55 +00:00
continue ;
}
2009-06-30 12:11:14 +10:00
2014-12-17 16:57:40 +13:00
princ = principal ;
if ( ! ( config - > db [ i ] - > hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL ) & & enterprise_principal )
2014-12-17 16:55:34 +13:00
princ = enterprise_principal ;
2010-11-29 11:24:08 +11:00
ret = config - > db [ i ] - > hdb_fetch_kvno ( context ,
config - > db [ i ] ,
2014-12-17 16:55:34 +13:00
princ ,
2010-11-29 11:24:08 +11:00
flags | HDB_F_DECRYPT ,
kvno ,
ent ) ;
2005-07-11 01:16:55 +00:00
config - > db [ i ] - > hdb_close ( context , config - > db [ i ] ) ;
2014-12-17 16:55:34 +13:00
2015-01-21 11:45:45 +13:00
switch ( ret ) {
2015-02-10 14:37:29 +01:00
case HDB_ERR_WRONG_REALM :
/*
* the ent - > entry . principal just contains hints for the client
* to retry . This is important for enterprise principal routing
* between trusts .
*/
/* fall through */
2015-01-21 11:45:45 +13:00
case 0 :
2006-11-07 06:59:56 +00:00
if ( db )
* db = config - > db [ i ] ;
2005-07-11 01:16:55 +00:00
* h = ent ;
2014-12-17 16:55:34 +13:00
ent = NULL ;
goto out ;
2015-01-21 11:45:45 +13:00
case HDB_ERR_NOENTRY :
/* Check the other databases */
continue ;
default :
/*
* This is really important , because errors like
* HDB_ERR_NOT_FOUND_HERE ( used to indicate to Samba that
* the RODC on which this code is running does not have
* the key we need , and so a proxy to the KDC is required )
* have specific meaning , and need to be propogated up .
*/
goto out ;
2005-07-11 01:16:55 +00:00
}
}
2014-12-17 16:55:34 +13:00
2015-01-21 11:45:45 +13:00
if ( ret = = HDB_ERR_NOENTRY ) {
krb5_set_error_message ( context , ret , " no such entry found in hdb " ) ;
}
2014-12-17 16:55:34 +13:00
out :
krb5_free_principal ( context , enterprise_principal ) ;
2005-07-11 01:16:55 +00:00
free ( ent ) ;
2010-11-12 12:31:33 +11:00
return ret ;
2005-07-11 01:16:55 +00:00
}
void
2005-12-15 20:38:24 +00:00
_kdc_free_ent ( krb5_context context , hdb_entry_ex * ent )
2005-07-11 01:16:55 +00:00
{
hdb_free_entry ( context , ent ) ;
free ( ent ) ;
}
2006-11-07 06:59:56 +00:00
/*
* Use the order list of preferred encryption types and sort the
* available keys and return the most preferred key .
*/
krb5_error_code
_kdc_get_preferred_key ( krb5_context context ,
krb5_kdc_configuration * config ,
hdb_entry_ex * h ,
const char * name ,
krb5_enctype * enctype ,
Key * * key )
{
krb5_error_code ret ;
int i ;
2011-07-15 09:10:30 +02:00
if ( config - > use_strongest_server_key ) {
const krb5_enctype * p = krb5_kerberos_enctypes ( context ) ;
for ( i = 0 ; p [ i ] ! = ETYPE_NULL ; i + + ) {
if ( krb5_enctype_valid ( context , p [ i ] ) ! = 0 )
continue ;
ret = hdb_enctype2key ( context , & h - > entry , p [ i ] , key ) ;
if ( ret ! = 0 )
continue ;
if ( enctype ! = NULL )
* enctype = p [ i ] ;
return 0 ;
}
} else {
* key = NULL ;
for ( i = 0 ; i < h - > entry . keys . len ; i + + ) {
if ( krb5_enctype_valid ( context , h - > entry . keys . val [ i ] . key . keytype )
! = 0 )
continue ;
ret = hdb_enctype2key ( context , & h - > entry ,
h - > entry . keys . val [ i ] . key . keytype , key ) ;
if ( ret ! = 0 )
continue ;
if ( enctype ! = NULL )
* enctype = ( * key ) - > key . keytype ;
2006-11-07 06:59:56 +00:00
return 0 ;
}
}
2008-10-27 11:35:07 +01:00
krb5_set_error_message ( context , EINVAL ,
2008-08-01 07:08:51 +02:00
" No valid kerberos key found for %s " , name ) ;
2011-07-15 09:10:30 +02:00
return EINVAL ; /* XXX */
2006-11-07 06:59:56 +00:00
}