2012-04-10 13:09:20 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2009
2016-02-29 17:12:02 +03:00
Copyright ( C ) Andreas Schneider < asn @ samba . org > 2016
2012-04-10 13:09:20 +04: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
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/>.
*/
2009-07-27 16:04:26 +04:00
# include "includes.h"
# include "system/kerberos.h"
# include "auth/kerberos/kerberos.h"
2010-01-28 09:27:11 +03:00
# include "kdc/samba_kdc.h"
2012-04-10 13:09:20 +04:00
# include "libnet/libnet_export_keytab.h"
2009-07-27 16:04:26 +04:00
2016-02-29 17:12:02 +03:00
# include "kdc/db-glue.h"
# include "kdc/sdb.h"
2009-07-27 16:04:26 +04:00
2016-02-29 17:12:02 +03:00
static NTSTATUS sdb_kt_copy ( TALLOC_CTX * mem_ctx ,
krb5_context context ,
struct samba_kdc_db_context * db_ctx ,
const char * keytab_name ,
const char * principal ,
const char * * error_string )
{
struct sdb_entry_ex sentry = {
. free_entry = NULL ,
} ;
krb5_keytab keytab ;
krb5_error_code code = 0 ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
char * entry_principal = NULL ;
bool copy_one_principal = ( principal ! = NULL ) ;
krb5_data password ;
2009-07-27 16:04:26 +04:00
2016-08-29 11:42:57 +03:00
code = smb_krb5_kt_open_relative ( context ,
keytab_name ,
true , /* write_access */
& keytab ) ;
2016-02-29 17:12:02 +03:00
if ( code ! = 0 ) {
* error_string = talloc_asprintf ( mem_ctx ,
" Failed to open keytab: %s " ,
keytab_name ) ;
status = NT_STATUS_NO_SUCH_FILE ;
goto done ;
2009-07-27 16:04:26 +04:00
}
2016-04-17 17:28:00 +03:00
if ( copy_one_principal ) {
krb5_principal k5_princ ;
code = smb_krb5_parse_name ( context , principal , & k5_princ ) ;
if ( code ! = 0 ) {
* error_string = smb_get_krb5_error_message ( context ,
code ,
mem_ctx ) ;
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
code = samba_kdc_fetch ( context , db_ctx , k5_princ ,
SDB_F_GET_ANY , 0 , & sentry ) ;
krb5_free_principal ( context , k5_princ ) ;
} else {
code = samba_kdc_firstkey ( context , db_ctx , & sentry ) ;
}
for ( ; code = = 0 ; code = samba_kdc_nextkey ( context , db_ctx , & sentry ) ) {
2016-02-29 17:12:02 +03:00
int i ;
2009-07-27 16:04:26 +04:00
2016-02-29 17:12:02 +03:00
code = krb5_unparse_name ( context ,
sentry . entry . principal ,
& entry_principal ) ;
if ( code ! = 0 ) {
* error_string = smb_get_krb5_error_message ( context ,
code ,
mem_ctx ) ;
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2016-04-17 17:28:00 +03:00
if ( sentry . entry . keys . len = = 0 ) {
2016-02-29 17:12:02 +03:00
SAFE_FREE ( entry_principal ) ;
sdb_free_entry ( & sentry ) ;
sentry = ( struct sdb_entry_ex ) {
. free_entry = NULL ,
} ;
continue ;
}
for ( i = 0 ; i < sentry . entry . keys . len ; i + + ) {
struct sdb_key * s = & ( sentry . entry . keys . val [ i ] ) ;
krb5_enctype enctype ;
enctype = KRB5_KEY_TYPE ( & ( s - > key ) ) ;
password . length = KRB5_KEY_LENGTH ( & s - > key ) ;
password . data = ( char * ) KRB5_KEY_DATA ( & s - > key ) ;
DBG_INFO ( " smb_krb5_kt_add_entry for enctype=0x%04x \n " ,
( int ) enctype ) ;
code = smb_krb5_kt_add_entry ( context ,
keytab ,
sentry . entry . kvno ,
entry_principal ,
NULL ,
enctype ,
& password ,
true , /* no_salt */
false ) ; /* keeyp_old_entries */
if ( code ! = 0 ) {
status = NT_STATUS_UNSUCCESSFUL ;
* error_string = smb_get_krb5_error_message ( context ,
code ,
mem_ctx ) ;
DEBUG ( 0 , ( " smb_krb5_kt_add_entry failed code=%d, error = %s \n " ,
code , * error_string ) ) ;
goto done ;
}
}
2016-04-17 17:28:00 +03:00
if ( copy_one_principal ) {
2016-02-29 17:12:02 +03:00
break ;
}
SAFE_FREE ( entry_principal ) ;
sdb_free_entry ( & sentry ) ;
sentry = ( struct sdb_entry_ex ) {
. free_entry = NULL ,
} ;
}
if ( code ! = 0 & & code ! = SDB_ERR_NOENTRY ) {
* error_string = smb_get_krb5_error_message ( context ,
code ,
mem_ctx ) ;
status = NT_STATUS_NO_SUCH_USER ;
goto done ;
2009-07-27 16:04:26 +04:00
}
2016-02-29 17:12:02 +03:00
status = NT_STATUS_OK ;
done :
SAFE_FREE ( entry_principal ) ;
sdb_free_entry ( & sentry ) ;
return status ;
}
NTSTATUS libnet_export_keytab ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx , struct libnet_export_keytab * r )
{
krb5_error_code ret ;
struct smb_krb5_context * smb_krb5_context ;
struct samba_kdc_base_context * base_ctx ;
struct samba_kdc_db_context * db_ctx = NULL ;
const char * error_string = NULL ;
NTSTATUS status ;
2014-04-17 14:35:33 +04:00
ret = smb_krb5_init_context ( ctx , ctx - > lp_ctx , & smb_krb5_context ) ;
2009-07-27 16:04:26 +04:00
if ( ret ) {
return NT_STATUS_NO_MEMORY ;
}
2016-02-29 17:12:02 +03:00
base_ctx = talloc_zero ( mem_ctx , struct samba_kdc_base_context ) ;
if ( base_ctx = = NULL ) {
2009-07-27 16:04:26 +04:00
return NT_STATUS_NO_MEMORY ;
}
2016-02-29 17:12:02 +03:00
base_ctx - > ev_ctx = ctx - > event_ctx ;
base_ctx - > lp_ctx = ctx - > lp_ctx ;
status = samba_kdc_setup_db_ctx ( mem_ctx , base_ctx , & db_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2009-07-27 16:04:26 +04:00
}
2016-02-29 17:12:02 +03:00
if ( r - > in . principal ! = NULL ) {
DEBUG ( 0 , ( " Export one principal to %s \n " , r - > in . keytab_name ) ) ;
status = sdb_kt_copy ( mem_ctx ,
smb_krb5_context - > krb5_context ,
db_ctx ,
r - > in . keytab_name ,
r - > in . principal ,
& error_string ) ;
2011-11-29 05:47:40 +04:00
} else {
unlink ( r - > in . keytab_name ) ;
2016-02-29 17:12:02 +03:00
DEBUG ( 0 , ( " Export complete keytab to %s \n " , r - > in . keytab_name ) ) ;
status = sdb_kt_copy ( mem_ctx ,
smb_krb5_context - > krb5_context ,
db_ctx ,
r - > in . keytab_name ,
NULL ,
& error_string ) ;
2011-11-29 05:47:40 +04:00
}
2010-09-30 23:43:14 +04:00
2016-02-29 17:12:02 +03:00
talloc_free ( db_ctx ) ;
talloc_free ( base_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
r - > out . error_string = error_string ;
2009-07-27 16:04:26 +04:00
}
2016-02-29 17:12:02 +03:00
return status ;
2009-07-27 16:04:26 +04:00
}