2010-01-26 19:56:16 +03:00
/*
Unix SMB / CIFS implementation .
PAC Glue between Samba and the KDC
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2005 - 2009
Copyright ( C ) Simo Sorce < idra @ samba . org > 2010
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"
2010-11-11 06:09:41 +03:00
# include "kdc/kdc-glue.h"
2010-01-26 19:56:16 +03:00
# include "kdc/pac-glue.h"
2016-05-20 10:48:41 +03:00
/*
* Given the right private pointer from hdb_samba4 ,
* get a PAC from the attached ldb messages .
*
* For PKINIT we also get pk_reply_key and can add PAC_CREDENTIAL_INFO .
*/
2010-01-26 19:56:16 +03:00
static krb5_error_code samba_wdc_get_pac ( void * priv , krb5_context context ,
struct hdb_entry_ex * client ,
2016-05-20 10:48:41 +03:00
const krb5_keyblock * pk_reply_key ,
2010-01-26 19:56:16 +03:00
krb5_pac * pac )
{
TALLOC_CTX * mem_ctx ;
2016-05-13 00:20:39 +03:00
DATA_BLOB * logon_blob = NULL ;
DATA_BLOB * cred_ndr = NULL ;
DATA_BLOB * * cred_ndr_ptr = NULL ;
DATA_BLOB _cred_blob = data_blob_null ;
DATA_BLOB * cred_blob = NULL ;
2016-05-13 01:13:33 +03:00
DATA_BLOB * upn_blob = NULL ;
2010-01-26 19:56:16 +03:00
krb5_error_code ret ;
NTSTATUS nt_status ;
2014-05-10 02:26:21 +04:00
struct samba_kdc_entry * skdc_entry =
talloc_get_type_abort ( client - > ctx ,
struct samba_kdc_entry ) ;
2010-01-26 19:56:16 +03:00
mem_ctx = talloc_named ( client - > ctx , 0 , " samba_get_pac context " ) ;
if ( ! mem_ctx ) {
return ENOMEM ;
}
2016-05-13 00:20:39 +03:00
if ( pk_reply_key ! = NULL ) {
cred_ndr_ptr = & cred_ndr ;
}
nt_status = samba_kdc_get_pac_blobs ( mem_ctx , skdc_entry ,
& logon_blob ,
2016-05-13 01:13:33 +03:00
cred_ndr_ptr ,
& upn_blob ) ;
2010-01-26 19:56:16 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
2016-05-13 00:20:39 +03:00
if ( pk_reply_key ! = NULL & & cred_ndr ! = NULL ) {
ret = samba_kdc_encrypt_pac_credentials ( context ,
pk_reply_key ,
cred_ndr ,
mem_ctx ,
& _cred_blob ) ;
if ( ret ! = 0 ) {
talloc_free ( mem_ctx ) ;
return ret ;
}
cred_blob = & _cred_blob ;
}
ret = samba_make_krb5_pac ( context , logon_blob , cred_blob ,
2016-05-13 01:13:33 +03:00
upn_blob , NULL , pac ) ;
2010-01-26 19:56:16 +03:00
talloc_free ( mem_ctx ) ;
return ret ;
}
2016-05-20 10:48:41 +03:00
static krb5_error_code samba_wdc_get_pac_compat ( void * priv , krb5_context context ,
struct hdb_entry_ex * client ,
krb5_pac * pac )
{
return samba_wdc_get_pac ( priv , context , client , NULL , pac ) ;
}
2010-01-26 19:56:16 +03:00
/* Resign (and reform, including possibly new groups) a PAC */
static krb5_error_code samba_wdc_reget_pac ( void * priv , krb5_context context ,
const krb5_principal client_principal ,
2011-06-28 16:46:49 +04:00
const krb5_principal delegated_proxy_principal ,
2010-01-26 19:56:16 +03:00
struct hdb_entry_ex * client ,
2010-09-28 07:13:28 +04:00
struct hdb_entry_ex * server ,
struct hdb_entry_ex * krbtgt ,
krb5_pac * pac )
2010-01-26 19:56:16 +03:00
{
2014-05-10 02:26:21 +04:00
struct samba_kdc_entry * p =
talloc_get_type_abort ( server - > ctx ,
struct samba_kdc_entry ) ;
2014-05-10 02:49:44 +04:00
struct samba_kdc_entry * krbtgt_skdc_entry =
talloc_get_type_abort ( krbtgt - > ctx ,
struct samba_kdc_entry ) ;
2010-01-26 19:56:16 +03:00
TALLOC_CTX * mem_ctx = talloc_named ( p , 0 , " samba_kdc_reget_pac context " ) ;
2016-01-07 19:25:26 +03:00
krb5_pac new_pac = NULL ;
DATA_BLOB * pac_blob = NULL ;
2016-05-13 01:13:33 +03:00
DATA_BLOB * upn_blob = NULL ;
2011-06-28 16:46:49 +04:00
DATA_BLOB * deleg_blob = NULL ;
2010-01-26 19:56:16 +03:00
krb5_error_code ret ;
NTSTATUS nt_status ;
2012-01-11 11:06:55 +04:00
struct PAC_SIGNATURE_DATA * pac_srv_sig ;
struct PAC_SIGNATURE_DATA * pac_kdc_sig ;
bool is_in_db , is_untrusted ;
2016-01-07 19:25:26 +03:00
size_t num_types = 0 ;
uint32_t * types = NULL ;
uint32_t forced_next_type = 0 ;
size_t i = 0 ;
ssize_t logon_info_idx = - 1 ;
ssize_t delegation_idx = - 1 ;
ssize_t logon_name_idx = - 1 ;
2016-05-13 01:13:33 +03:00
ssize_t upn_dns_info_idx = - 1 ;
2016-01-07 19:25:26 +03:00
ssize_t srv_checksum_idx = - 1 ;
ssize_t kdc_checksum_idx = - 1 ;
2010-01-26 19:56:16 +03:00
if ( ! mem_ctx ) {
return ENOMEM ;
}
/* The user account may be set not to want the PAC */
2014-05-10 01:26:42 +04:00
if ( ! samba_princ_needs_pac ( p ) ) {
2010-01-26 19:56:16 +03:00
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
2010-09-28 07:13:28 +04:00
/* If the krbtgt was generated by an RODC, and we are not that
* RODC , then we need to regenerate the PAC - we can ' t trust
* it */
2014-05-10 02:49:44 +04:00
ret = samba_krbtgt_is_in_db ( krbtgt_skdc_entry , & is_in_db , & is_untrusted ) ;
2012-01-11 11:06:55 +04:00
if ( ret ! = 0 ) {
talloc_free ( mem_ctx ) ;
return ret ;
}
if ( is_untrusted ) {
2014-05-10 02:26:21 +04:00
struct samba_kdc_entry * client_skdc_entry = NULL ;
2010-11-16 01:33:05 +03:00
if ( client = = NULL ) {
return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN ;
}
2014-05-10 02:26:21 +04:00
client_skdc_entry = talloc_get_type_abort ( client - > ctx ,
struct samba_kdc_entry ) ;
2016-05-13 01:13:33 +03:00
nt_status = samba_kdc_get_pac_blobs ( mem_ctx , client_skdc_entry ,
& pac_blob , NULL , & upn_blob ) ;
2010-09-28 07:13:28 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
} else {
pac_blob = talloc_zero ( mem_ctx , DATA_BLOB ) ;
if ( ! pac_blob ) {
talloc_free ( mem_ctx ) ;
return ENOMEM ;
}
2010-01-26 19:56:16 +03:00
2012-01-11 11:06:55 +04:00
pac_srv_sig = talloc_zero ( mem_ctx , struct PAC_SIGNATURE_DATA ) ;
if ( ! pac_srv_sig ) {
talloc_free ( mem_ctx ) ;
return ENOMEM ;
}
pac_kdc_sig = talloc_zero ( mem_ctx , struct PAC_SIGNATURE_DATA ) ;
if ( ! pac_kdc_sig ) {
talloc_free ( mem_ctx ) ;
return ENOMEM ;
}
2010-09-28 07:13:28 +04:00
nt_status = samba_kdc_update_pac_blob ( mem_ctx , context ,
2021-10-08 06:06:58 +03:00
krbtgt_skdc_entry - > kdc_db_ctx - > samdb ,
2012-01-11 11:06:55 +04:00
* pac , pac_blob ,
pac_srv_sig , pac_kdc_sig ) ;
2010-09-28 07:13:28 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " Building PAC failed: %s \n " ,
nt_errstr ( nt_status ) ) ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
2012-01-11 11:06:55 +04:00
if ( is_in_db ) {
/* Now check the KDC signature, fetching the correct key based on the enc type */
ret = kdc_check_pac ( context , pac_srv_sig - > signature , pac_kdc_sig , krbtgt ) ;
if ( ret ! = 0 ) {
DEBUG ( 1 , ( " PAC KDC signature failed to verify \n " ) ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}
}
2010-09-28 07:13:28 +04:00
}
2011-06-28 16:46:49 +04:00
if ( delegated_proxy_principal ) {
deleg_blob = talloc_zero ( mem_ctx , DATA_BLOB ) ;
if ( ! deleg_blob ) {
talloc_free ( mem_ctx ) ;
return ENOMEM ;
}
nt_status = samba_kdc_update_delegation_info_blob ( mem_ctx ,
context , * pac ,
server - > entry . principal ,
delegated_proxy_principal ,
deleg_blob ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 0 , ( " Building PAC failed: %s \n " ,
nt_errstr ( nt_status ) ) ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
}
2016-01-07 19:25:26 +03:00
/* Check the types of the given PAC */
ret = krb5_pac_get_types ( context , * pac , & num_types , & types ) ;
if ( ret ! = 0 ) {
talloc_free ( mem_ctx ) ;
return ret ;
}
2010-01-26 19:56:16 +03:00
2016-01-07 19:25:26 +03:00
for ( i = 0 ; i < num_types ; i + + ) {
switch ( types [ i ] ) {
case PAC_TYPE_LOGON_INFO :
if ( logon_info_idx ! = - 1 ) {
2021-10-06 06:40:21 +03:00
DEBUG ( 1 , ( " logon info type[% " PRIu32 " ] twice [%zd] and [%zu]: \n " ,
types [ i ] ,
logon_info_idx ,
i ) ) ;
2016-01-07 19:25:26 +03:00
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
logon_info_idx = i ;
break ;
case PAC_TYPE_CONSTRAINED_DELEGATION :
if ( delegation_idx ! = - 1 ) {
2021-10-06 06:40:21 +03:00
DEBUG ( 1 , ( " constrained delegation type[% " PRIu32 " ] twice [%zd] and [%zu]: \n " ,
types [ i ] ,
delegation_idx ,
i ) ) ;
2016-01-07 19:25:26 +03:00
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
delegation_idx = i ;
break ;
case PAC_TYPE_LOGON_NAME :
if ( logon_name_idx ! = - 1 ) {
2021-10-06 06:40:21 +03:00
DEBUG ( 1 , ( " logon name type[% " PRIu32 " ] twice [%zd] and [%zu]: \n " ,
types [ i ] ,
logon_name_idx ,
i ) ) ;
2016-01-07 19:25:26 +03:00
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
logon_name_idx = i ;
break ;
2016-05-13 01:13:33 +03:00
case PAC_TYPE_UPN_DNS_INFO :
if ( upn_dns_info_idx ! = - 1 ) {
2021-10-06 06:40:21 +03:00
DEBUG ( 1 , ( " upn dns info type[% " PRIu32 " ] twice [%zd] and [%zu]: \n " ,
types [ i ] ,
upn_dns_info_idx ,
i ) ) ;
2016-05-13 01:13:33 +03:00
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
upn_dns_info_idx = i ;
break ;
2016-01-07 19:25:26 +03:00
case PAC_TYPE_SRV_CHECKSUM :
if ( srv_checksum_idx ! = - 1 ) {
2021-10-06 06:40:21 +03:00
DEBUG ( 1 , ( " server checksum type[% " PRIu32 " ] twice [%zd] and [%zu]: \n " ,
types [ i ] ,
srv_checksum_idx ,
i ) ) ;
2016-01-07 19:25:26 +03:00
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
srv_checksum_idx = i ;
break ;
case PAC_TYPE_KDC_CHECKSUM :
if ( kdc_checksum_idx ! = - 1 ) {
2021-10-06 06:40:21 +03:00
DEBUG ( 1 , ( " kdc checksum type[% " PRIu32 " ] twice [%zd] and [%zu]: \n " ,
types [ i ] ,
kdc_checksum_idx ,
i ) ) ;
2016-01-07 19:25:26 +03:00
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
kdc_checksum_idx = i ;
break ;
default :
continue ;
}
}
if ( logon_info_idx = = - 1 ) {
DEBUG ( 1 , ( " PAC_TYPE_LOGON_INFO missing \n " ) ) ;
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
if ( logon_name_idx = = - 1 ) {
DEBUG ( 1 , ( " PAC_TYPE_LOGON_NAME missing \n " ) ) ;
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
if ( srv_checksum_idx = = - 1 ) {
DEBUG ( 1 , ( " PAC_TYPE_SRV_CHECKSUM missing \n " ) ) ;
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
if ( kdc_checksum_idx = = - 1 ) {
DEBUG ( 1 , ( " PAC_TYPE_KDC_CHECKSUM missing \n " ) ) ;
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return EINVAL ;
}
/* Build an updated PAC */
ret = krb5_pac_init ( context , & new_pac ) ;
if ( ret ! = 0 ) {
SAFE_FREE ( types ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}
for ( i = 0 ; ; ) {
const uint8_t zero_byte = 0 ;
krb5_data type_data ;
DATA_BLOB type_blob = data_blob_null ;
uint32_t type ;
if ( forced_next_type ! = 0 ) {
/*
* We need to inject possible missing types
*/
type = forced_next_type ;
forced_next_type = 0 ;
} else if ( i < num_types ) {
type = types [ i ] ;
i + + ;
} else {
break ;
}
switch ( type ) {
case PAC_TYPE_LOGON_INFO :
type_blob = * pac_blob ;
if ( delegation_idx = = - 1 & & deleg_blob ! = NULL ) {
/* inject CONSTRAINED_DELEGATION behind */
forced_next_type = PAC_TYPE_CONSTRAINED_DELEGATION ;
}
break ;
case PAC_TYPE_CONSTRAINED_DELEGATION :
if ( deleg_blob ! = NULL ) {
type_blob = * deleg_blob ;
}
break ;
2016-05-13 00:20:39 +03:00
case PAC_TYPE_CREDENTIAL_INFO :
/*
* Note that we copy the credential blob ,
* as it ' s only usable with the PKINIT based
* AS - REP reply key , it ' s only available on the
* host which did the AS - REQ / AS - REP exchange .
*
* This matches Windows 2008 R2 . . .
*/
break ;
2016-01-07 19:25:26 +03:00
case PAC_TYPE_LOGON_NAME :
/*
* this is generated in the main KDC code
* we just add a place holder here .
*/
type_blob = data_blob_const ( & zero_byte , 1 ) ;
2016-05-13 01:13:33 +03:00
if ( upn_dns_info_idx = = - 1 & & upn_blob ! = NULL ) {
/* inject UPN_DNS_INFO behind */
forced_next_type = PAC_TYPE_UPN_DNS_INFO ;
}
break ;
case PAC_TYPE_UPN_DNS_INFO :
/*
* Replace in the RODC case , otherwise
* upn_blob is NULL and we just copy .
*/
if ( upn_blob ! = NULL ) {
type_blob = * upn_blob ;
}
2016-01-07 19:25:26 +03:00
break ;
case PAC_TYPE_SRV_CHECKSUM :
/*
* this are generated in the main KDC code
* we just add a place holder here .
*/
type_blob = data_blob_const ( & zero_byte , 1 ) ;
break ;
case PAC_TYPE_KDC_CHECKSUM :
/*
* this are generated in the main KDC code
* we just add a place holders here .
*/
type_blob = data_blob_const ( & zero_byte , 1 ) ;
break ;
default :
/* just copy... */
break ;
}
if ( type_blob . length ! = 0 ) {
2016-08-26 12:57:30 +03:00
ret = smb_krb5_copy_data_contents ( & type_data ,
type_blob . data ,
type_blob . length ) ;
2016-01-07 19:25:26 +03:00
if ( ret ! = 0 ) {
SAFE_FREE ( types ) ;
krb5_pac_free ( context , new_pac ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}
} else {
ret = krb5_pac_get_buffer ( context , * pac ,
type , & type_data ) ;
if ( ret ! = 0 ) {
SAFE_FREE ( types ) ;
krb5_pac_free ( context , new_pac ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}
}
ret = krb5_pac_add_buffer ( context , new_pac ,
type , & type_data ) ;
2016-08-26 12:51:52 +03:00
smb_krb5_free_data_contents ( context , & type_data ) ;
2016-01-07 19:25:26 +03:00
if ( ret ! = 0 ) {
SAFE_FREE ( types ) ;
krb5_pac_free ( context , new_pac ) ;
talloc_free ( mem_ctx ) ;
return ret ;
}
}
SAFE_FREE ( types ) ;
/* We now replace the pac */
krb5_pac_free ( context , * pac ) ;
* pac = new_pac ;
2010-01-26 19:56:16 +03:00
talloc_free ( mem_ctx ) ;
return ret ;
}
2010-01-31 20:49:07 +03:00
static char * get_netbios_name ( TALLOC_CTX * mem_ctx , HostAddresses * addrs )
{
char * nb_name = NULL ;
2010-04-12 01:22:01 +04:00
size_t len ;
unsigned int i ;
2010-01-31 20:49:07 +03:00
for ( i = 0 ; addrs & & i < addrs - > len ; i + + ) {
if ( addrs - > val [ i ] . addr_type ! = KRB5_ADDRESS_NETBIOS ) {
continue ;
}
len = MIN ( addrs - > val [ i ] . address . length , 15 ) ;
nb_name = talloc_strndup ( mem_ctx ,
addrs - > val [ i ] . address . data , len ) ;
if ( nb_name ) {
break ;
}
}
2012-08-13 22:17:20 +04:00
if ( ( nb_name = = NULL ) | | ( nb_name [ 0 ] = = ' \0 ' ) ) {
2010-01-31 20:49:07 +03:00
return NULL ;
}
/* Strip space padding */
2012-08-13 22:17:20 +04:00
for ( len = strlen ( nb_name ) - 1 ;
( len > 0 ) & & ( nb_name [ len ] = = ' ' ) ;
- - len ) {
nb_name [ len ] = ' \0 ' ;
2010-01-31 20:49:07 +03:00
}
return nb_name ;
}
static krb5_data fill_krb5_data ( void * data , size_t length )
{
krb5_data kdata ;
kdata . data = data ;
kdata . length = length ;
return kdata ;
}
2014-05-15 11:13:06 +04:00
/* this function allocates 'data' using malloc.
* The caller is responsible for freeing it */
static void samba_kdc_build_edata_reply ( NTSTATUS nt_status , DATA_BLOB * e_data )
{
krb5_error_code ret = 0 ;
PA_DATA pa ;
unsigned char * buf ;
size_t len ;
if ( ! e_data )
return ;
e_data - > data = NULL ;
e_data - > length = 0 ;
pa . padata_type = KRB5_PADATA_PW_SALT ;
pa . padata_value . length = 12 ;
pa . padata_value . data = malloc ( pa . padata_value . length ) ;
if ( ! pa . padata_value . data ) {
e_data - > length = 0 ;
e_data - > data = NULL ;
return ;
}
SIVAL ( pa . padata_value . data , 0 , NT_STATUS_V ( nt_status ) ) ;
SIVAL ( pa . padata_value . data , 4 , 0 ) ;
SIVAL ( pa . padata_value . data , 8 , 1 ) ;
ASN1_MALLOC_ENCODE ( PA_DATA , buf , len , & pa , & len , ret ) ;
free ( pa . padata_value . data ) ;
if ( ret ) {
return ;
}
e_data - > data = buf ;
e_data - > length = len ;
return ;
}
2010-01-26 19:56:16 +03:00
static krb5_error_code samba_wdc_check_client_access ( void * priv ,
krb5_context context ,
krb5_kdc_configuration * config ,
hdb_entry_ex * client_ex , const char * client_name ,
hdb_entry_ex * server_ex , const char * server_name ,
KDC_REQ * req ,
krb5_data * e_data )
{
2010-01-31 20:49:07 +03:00
struct samba_kdc_entry * kdc_entry ;
2010-01-26 19:56:16 +03:00
bool password_change ;
2010-01-31 20:49:07 +03:00
char * workstation ;
NTSTATUS nt_status ;
2010-01-26 19:56:16 +03:00
2010-01-31 20:49:07 +03:00
kdc_entry = talloc_get_type ( client_ex - > ctx , struct samba_kdc_entry ) ;
password_change = ( server_ex & & server_ex - > entry . flags . change_pw ) ;
workstation = get_netbios_name ( ( TALLOC_CTX * ) client_ex - > ctx ,
req - > req_body . addresses ) ;
2010-01-26 19:56:16 +03:00
2010-01-31 20:49:07 +03:00
nt_status = samba_kdc_check_client_access ( kdc_entry ,
client_name ,
workstation ,
password_change ) ;
2010-01-26 19:56:16 +03:00
2010-01-31 20:49:07 +03:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
if ( NT_STATUS_EQUAL ( nt_status , NT_STATUS_NO_MEMORY ) ) {
return ENOMEM ;
2010-01-26 19:56:16 +03:00
}
2010-01-31 20:49:07 +03:00
if ( e_data ) {
DATA_BLOB data ;
2010-01-26 19:56:16 +03:00
2010-01-31 20:49:07 +03:00
samba_kdc_build_edata_reply ( nt_status , & data ) ;
* e_data = fill_krb5_data ( data . data , data . length ) ;
}
2010-01-26 19:56:16 +03:00
2010-01-31 20:49:07 +03:00
return samba_kdc_map_policy_err ( nt_status ) ;
2010-01-26 19:56:16 +03:00
}
2010-01-31 20:49:07 +03:00
/* Now do the standard Heimdal check */
return kdc_check_flags ( context , config ,
client_ex , client_name ,
server_ex , server_name ,
req - > msg_type = = krb_as_req ) ;
2010-01-26 19:56:16 +03:00
}
static krb5_error_code samba_wdc_plugin_init ( krb5_context context , void * * ptr )
{
* ptr = NULL ;
return 0 ;
}
static void samba_wdc_plugin_fini ( void * ptr )
{
return ;
}
struct krb5plugin_windc_ftable windc_plugin_table = {
2011-06-28 15:13:41 +04:00
. minor_version = KRB5_WINDC_PLUGIN_MINOR ,
2010-01-26 19:56:16 +03:00
. init = samba_wdc_plugin_init ,
. fini = samba_wdc_plugin_fini ,
2016-05-20 10:48:41 +03:00
. pac_generate = samba_wdc_get_pac_compat ,
2010-01-26 19:56:16 +03:00
. pac_verify = samba_wdc_reget_pac ,
. client_access = samba_wdc_check_client_access ,
2016-05-20 10:48:41 +03:00
. pac_pk_generate = samba_wdc_get_pac ,
2010-01-26 19:56:16 +03:00
} ;