2010-01-12 11:05:16 -05:00
/*
2005-06-28 00:55:44 +00:00
Unix SMB / CIFS implementation .
2005-07-04 02:36:16 +00:00
Create and parse the krb5 PAC
2010-01-12 11:05:16 -05:00
2008-08-28 16:28:47 +10:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2005 , 2008
2005-06-28 00:55:44 +00:00
Copyright ( C ) Andrew Tridgell 2001
Copyright ( C ) Luke Howard 2002 - 2003
Copyright ( C ) Stefan Metzmacher 2004 - 2005
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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-06-28 00:55:44 +00:00
( at your option ) any later version .
2010-01-12 11:05:16 -05:00
2005-06-28 00:55:44 +00:00
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 .
2010-01-12 11:05:16 -05:00
2005-06-28 00:55:44 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-06-28 00:55:44 +00:00
*/
# include "includes.h"
# include "system/kerberos.h"
2008-08-28 16:28:47 +10:00
# include "auth/auth.h"
2005-06-28 00:55:44 +00:00
# include "auth/kerberos/kerberos.h"
# include "librpc/gen_ndr/ndr_krb5pac.h"
2011-02-10 14:12:51 +11:00
# include <ldb.h>
2007-12-10 04:33:29 +01:00
# include "auth/auth_sam_reply.h"
2013-10-15 15:06:57 -07:00
# include "auth/credentials/credentials.h"
2011-12-28 17:48:45 +11:00
# include "auth/kerberos/kerberos_util.h"
2012-03-31 22:09:22 -04:00
# include "auth/kerberos/pac_utils.h"
2005-06-28 00:55:44 +00:00
2005-06-29 13:55:09 +00:00
krb5_error_code kerberos_encode_pac ( TALLOC_CTX * mem_ctx ,
2005-08-05 00:41:53 +00:00
struct PAC_DATA * pac_data ,
krb5_context context ,
2006-11-11 15:11:21 +00:00
const krb5_keyblock * krbtgt_keyblock ,
const krb5_keyblock * service_keyblock ,
2010-01-12 11:05:16 -05:00
DATA_BLOB * pac )
2005-08-05 00:41:53 +00:00
{
NTSTATUS nt_status ;
krb5_error_code ret ;
2007-11-09 19:24:51 +01:00
enum ndr_err_code ndr_err ;
2005-08-05 00:41:53 +00:00
DATA_BLOB zero_blob = data_blob ( NULL , 0 ) ;
DATA_BLOB tmp_blob = data_blob ( NULL , 0 ) ;
struct PAC_SIGNATURE_DATA * kdc_checksum = NULL ;
struct PAC_SIGNATURE_DATA * srv_checksum = NULL ;
2018-11-20 17:03:17 +01:00
uint32_t i ;
2005-08-05 00:41:53 +00:00
/* First, just get the keytypes filled in (and lengths right, eventually) */
for ( i = 0 ; i < pac_data - > num_buffers ; i + + ) {
if ( pac_data - > buffers [ i ] . type ! = PAC_TYPE_KDC_CHECKSUM ) {
continue ;
}
2010-01-12 11:05:16 -05:00
kdc_checksum = & pac_data - > buffers [ i ] . info - > kdc_cksum ,
2012-05-03 17:10:53 +02:00
ret = smb_krb5_make_pac_checksum ( mem_ctx ,
& zero_blob ,
context ,
krbtgt_keyblock ,
& kdc_checksum - > type ,
& kdc_checksum - > signature ) ;
2005-08-05 00:41:53 +00:00
if ( ret ) {
2010-01-12 11:05:16 -05:00
DEBUG ( 2 , ( " making krbtgt PAC checksum failed: %s \n " ,
2005-08-05 00:41:53 +00:00
smb_get_krb5_error_message ( context , ret , mem_ctx ) ) ) ;
talloc_free ( pac_data ) ;
return ret ;
}
}
2010-01-12 11:05:16 -05:00
2005-08-05 00:41:53 +00:00
for ( i = 0 ; i < pac_data - > num_buffers ; i + + ) {
if ( pac_data - > buffers [ i ] . type ! = PAC_TYPE_SRV_CHECKSUM ) {
continue ;
}
2010-01-12 11:05:16 -05:00
srv_checksum = & pac_data - > buffers [ i ] . info - > srv_cksum ;
2012-05-03 17:10:53 +02:00
ret = smb_krb5_make_pac_checksum ( mem_ctx ,
& zero_blob ,
context ,
service_keyblock ,
& srv_checksum - > type ,
& srv_checksum - > signature ) ;
2005-08-05 00:41:53 +00:00
if ( ret ) {
2010-01-12 11:05:16 -05:00
DEBUG ( 2 , ( " making service PAC checksum failed: %s \n " ,
2005-08-05 00:41:53 +00:00
smb_get_krb5_error_message ( context , ret , mem_ctx ) ) ) ;
talloc_free ( pac_data ) ;
return ret ;
}
}
if ( ! kdc_checksum ) {
2023-07-31 16:17:16 +12:00
DEBUG ( 2 , ( " Invalid PAC constructed for signing, no KDC checksum present! \n " ) ) ;
2005-08-05 00:41:53 +00:00
return EINVAL ;
}
if ( ! srv_checksum ) {
2023-07-31 16:17:16 +12:00
DEBUG ( 2 , ( " Invalid PAC constructed for signing, no SRV checksum present! \n " ) ) ;
2005-08-05 00:41:53 +00:00
return EINVAL ;
}
/* But wipe out the actual signatures */
2005-09-10 10:39:45 +00:00
memset ( kdc_checksum - > signature . data , ' \0 ' , kdc_checksum - > signature . length ) ;
memset ( srv_checksum - > signature . data , ' \0 ' , srv_checksum - > signature . length ) ;
2005-08-05 00:41:53 +00:00
2010-01-12 11:05:16 -05:00
ndr_err = ndr_push_struct_blob ( & tmp_blob , mem_ctx ,
2008-01-01 22:05:05 -06:00
pac_data ,
2007-11-09 19:24:51 +01:00
( ndr_push_flags_fn_t ) ndr_push_PAC_DATA ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
nt_status = ndr_map_error2ntstatus ( ndr_err ) ;
2005-08-05 00:41:53 +00:00
DEBUG ( 1 , ( " PAC (presig) push failed: %s \n " , nt_errstr ( nt_status ) ) ) ;
talloc_free ( pac_data ) ;
return EINVAL ;
}
/* Then sign the result of the previous push, where the sig was zero'ed out */
2012-05-03 17:10:53 +02:00
ret = smb_krb5_make_pac_checksum ( mem_ctx ,
& tmp_blob ,
context ,
service_keyblock ,
& srv_checksum - > type ,
& srv_checksum - > signature ) ;
2005-08-05 00:41:53 +00:00
2019-07-05 10:24:53 +00:00
if ( ret ) {
DBG_WARNING ( " making krbtgt PAC srv_checksum failed: %s \n " ,
smb_get_krb5_error_message ( context , ret , mem_ctx ) ) ;
talloc_free ( pac_data ) ;
return ret ;
}
2005-08-05 00:41:53 +00:00
/* Then sign Server checksum */
2012-05-03 17:10:53 +02:00
ret = smb_krb5_make_pac_checksum ( mem_ctx ,
& srv_checksum - > signature ,
context ,
krbtgt_keyblock ,
& kdc_checksum - > type ,
& kdc_checksum - > signature ) ;
2005-08-05 00:41:53 +00:00
if ( ret ) {
2019-07-05 10:24:53 +00:00
DBG_WARNING ( " making krbtgt PAC kdc_checksum failed: %s \n " ,
smb_get_krb5_error_message ( context , ret , mem_ctx ) ) ;
2005-08-05 00:41:53 +00:00
talloc_free ( pac_data ) ;
return ret ;
}
2023-08-08 12:38:39 +12:00
/* And push it out again, this time to the world. This relies on deterministic pointer values */
2010-01-12 11:05:16 -05:00
ndr_err = ndr_push_struct_blob ( & tmp_blob , mem_ctx ,
2008-01-01 22:05:05 -06:00
pac_data ,
2007-11-09 19:24:51 +01:00
( ndr_push_flags_fn_t ) ndr_push_PAC_DATA ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
nt_status = ndr_map_error2ntstatus ( ndr_err ) ;
2005-08-05 00:41:53 +00:00
DEBUG ( 1 , ( " PAC (final) push failed: %s \n " , nt_errstr ( nt_status ) ) ) ;
talloc_free ( pac_data ) ;
return EINVAL ;
}
* pac = tmp_blob ;
return ret ;
}
krb5_error_code kerberos_create_pac ( TALLOC_CTX * mem_ctx ,
2011-02-08 16:53:13 +11:00
struct auth_user_info_dc * user_info_dc ,
2005-06-29 13:55:09 +00:00
krb5_context context ,
2006-11-11 15:11:21 +00:00
const krb5_keyblock * krbtgt_keyblock ,
const krb5_keyblock * service_keyblock ,
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-07 21:52:50 +00:00
krb5_principal client_principal ,
2005-08-26 11:52:35 +00:00
time_t tgs_authtime ,
2005-07-04 02:36:16 +00:00
DATA_BLOB * pac )
2005-06-29 13:55:09 +00:00
{
NTSTATUS nt_status ;
krb5_error_code ret ;
struct PAC_DATA * pac_data = talloc ( mem_ctx , struct PAC_DATA ) ;
2005-07-05 10:57:39 +00:00
struct netr_SamInfo3 * sam3 ;
2005-07-04 15:42:08 +00:00
union PAC_INFO * u_LOGON_INFO ;
struct PAC_LOGON_INFO * LOGON_INFO ;
union PAC_INFO * u_LOGON_NAME ;
struct PAC_LOGON_NAME * LOGON_NAME ;
union PAC_INFO * u_KDC_CHECKSUM ;
union PAC_INFO * u_SRV_CHECKSUM ;
2005-06-29 13:55:09 +00:00
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-07 21:52:50 +00:00
char * name ;
2010-01-12 11:05:16 -05:00
2005-07-04 02:36:16 +00:00
enum {
2005-07-04 15:42:08 +00:00
PAC_BUF_LOGON_INFO = 0 ,
2005-07-04 02:36:16 +00:00
PAC_BUF_LOGON_NAME = 1 ,
2005-07-05 10:57:39 +00:00
PAC_BUF_SRV_CHECKSUM = 2 ,
PAC_BUF_KDC_CHECKSUM = 3 ,
2005-07-04 02:36:16 +00:00
PAC_BUF_NUM_BUFFERS = 4
} ;
2005-06-29 13:55:09 +00:00
if ( ! pac_data ) {
return ENOMEM ;
}
2005-07-04 02:36:16 +00:00
pac_data - > num_buffers = PAC_BUF_NUM_BUFFERS ;
2005-06-29 13:55:09 +00:00
pac_data - > version = 0 ;
2010-01-12 11:05:16 -05:00
pac_data - > buffers = talloc_array ( pac_data ,
2005-06-29 13:55:09 +00:00
struct PAC_BUFFER ,
pac_data - > num_buffers ) ;
if ( ! pac_data - > buffers ) {
talloc_free ( pac_data ) ;
return ENOMEM ;
}
2005-07-04 02:36:16 +00:00
2005-07-04 15:42:08 +00:00
/* LOGON_INFO */
u_LOGON_INFO = talloc_zero ( pac_data - > buffers , union PAC_INFO ) ;
if ( ! u_LOGON_INFO ) {
talloc_free ( pac_data ) ;
return ENOMEM ;
}
pac_data - > buffers [ PAC_BUF_LOGON_INFO ] . type = PAC_TYPE_LOGON_INFO ;
pac_data - > buffers [ PAC_BUF_LOGON_INFO ] . info = u_LOGON_INFO ;
2005-06-29 13:55:09 +00:00
2005-07-04 15:42:08 +00:00
/* LOGON_NAME */
u_LOGON_NAME = talloc_zero ( pac_data - > buffers , union PAC_INFO ) ;
if ( ! u_LOGON_NAME ) {
talloc_free ( pac_data ) ;
return ENOMEM ;
}
pac_data - > buffers [ PAC_BUF_LOGON_NAME ] . type = PAC_TYPE_LOGON_NAME ;
pac_data - > buffers [ PAC_BUF_LOGON_NAME ] . info = u_LOGON_NAME ;
LOGON_NAME = & u_LOGON_NAME - > logon_name ;
/* SRV_CHECKSUM */
u_SRV_CHECKSUM = talloc_zero ( pac_data - > buffers , union PAC_INFO ) ;
if ( ! u_SRV_CHECKSUM ) {
talloc_free ( pac_data ) ;
return ENOMEM ;
}
pac_data - > buffers [ PAC_BUF_SRV_CHECKSUM ] . type = PAC_TYPE_SRV_CHECKSUM ;
pac_data - > buffers [ PAC_BUF_SRV_CHECKSUM ] . info = u_SRV_CHECKSUM ;
2005-07-05 10:57:39 +00:00
/* KDC_CHECKSUM */
u_KDC_CHECKSUM = talloc_zero ( pac_data - > buffers , union PAC_INFO ) ;
if ( ! u_KDC_CHECKSUM ) {
talloc_free ( pac_data ) ;
return ENOMEM ;
}
pac_data - > buffers [ PAC_BUF_KDC_CHECKSUM ] . type = PAC_TYPE_KDC_CHECKSUM ;
pac_data - > buffers [ PAC_BUF_KDC_CHECKSUM ] . info = u_KDC_CHECKSUM ;
2005-07-04 15:42:08 +00:00
/* now the real work begins... */
LOGON_INFO = talloc_zero ( u_LOGON_INFO , struct PAC_LOGON_INFO ) ;
if ( ! LOGON_INFO ) {
talloc_free ( pac_data ) ;
return ENOMEM ;
}
2022-09-27 14:51:54 +13:00
nt_status = auth_convert_user_info_dc_saminfo3 ( LOGON_INFO , user_info_dc ,
AUTH_INCLUDE_RESOURCE_GROUPS ,
2022-12-02 10:49:20 +13:00
& sam3 , NULL ) ;
2005-06-29 13:55:09 +00:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 1 , ( " Getting Samba info failed: %s \n " , nt_errstr ( nt_status ) ) ) ;
talloc_free ( pac_data ) ;
return EINVAL ;
}
2005-07-05 06:13:12 +00:00
u_LOGON_INFO - > logon_info . info = LOGON_INFO ;
2005-07-05 10:57:39 +00:00
LOGON_INFO - > info3 = * sam3 ;
2005-07-04 15:42:08 +00:00
2010-01-12 11:05:16 -05:00
ret = krb5_unparse_name_flags ( context , client_principal ,
2015-03-12 11:27:57 +13:00
KRB5_PRINCIPAL_UNPARSE_NO_REALM |
KRB5_PRINCIPAL_UNPARSE_DISPLAY ,
& name ) ;
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-07 21:52:50 +00:00
if ( ret ) {
return ret ;
}
LOGON_NAME - > account_name = talloc_strdup ( LOGON_NAME , name ) ;
free ( name ) ;
2005-08-26 11:52:35 +00:00
/*
this logon_time field is absolutely critical . This is what
r10066: This is the second in my patches to work on Samba4's kerberos support,
with an aim to make the code simpiler and more correct.
Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over
all keytypes)' code in gensec_krb5, we now follow the approach used in
gensec_gssapi, and use a keytab.
I have also done a lot of work in the GSSAPI code, to try and reduce
the diff between us and upstream heimdal. It was becoming hard to
track patches in this code, and I also want this patch (the DCE_STYLE
support) to be in a 'manageable' state for when lha considers it for
merging. (metze assures me it still has memory leak problems, but
I've started to address some of that).
This patch also includes a simple update of other code to current
heimdal, as well as changes we need for better PAC verification.
On the PAC side of things we now match windows member servers by
checking the name and authtime on an incoming PAC. Not generating these
right was the cause of the PAC pain, and so now both the main code and
torture test validate this behaviour.
One thing doesn't work with this patch:
- the sealing of RPC pipes with kerberos, Samba -> Samba seems
broken. I'm pretty sure this is related to AES, and the need to break
apart the gss_wrap interface.
Andrew Bartlett
(This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c)
2005-09-07 21:52:50 +00:00
caused all our PAC troubles : - )
2005-08-26 11:52:35 +00:00
*/
unix_to_nt_time ( & LOGON_NAME - > logon_time , tgs_authtime ) ;
2005-07-04 15:42:08 +00:00
2010-01-12 11:05:16 -05:00
ret = kerberos_encode_pac ( mem_ctx ,
pac_data ,
2005-08-05 00:41:53 +00:00
context ,
krbtgt_keyblock ,
service_keyblock ,
pac ) ;
2005-06-29 13:55:09 +00:00
talloc_free ( pac_data ) ;
return ret ;
}
2022-06-10 19:18:35 +12:00
static krb5_error_code kerberos_pac_buffer_present ( krb5_context context ,
2022-11-01 19:01:15 +13:00
const krb5_const_pac pac ,
2022-06-10 19:18:35 +12:00
uint32_t type )
{
# ifdef SAMBA4_USES_HEIMDAL
return krb5_pac_get_buffer ( context , pac , type , NULL ) ;
# else /* MIT */
krb5_error_code ret ;
krb5_data data ;
/*
* MIT won ' t let us pass NULL for the data parameter , so we are forced
* to allocate a new buffer and then immediately free it .
*/
ret = krb5_pac_get_buffer ( context , pac , type , & data ) ;
if ( ret = = 0 ) {
krb5_free_data_contents ( context , & data ) ;
}
return ret ;
# endif /* SAMBA4_USES_HEIMDAL */
}
2011-02-08 16:53:13 +11:00
krb5_error_code kerberos_pac_to_user_info_dc ( TALLOC_CTX * mem_ctx ,
2022-11-01 19:01:15 +13:00
krb5_const_pac pac ,
2011-02-08 16:53:13 +11:00
krb5_context context ,
struct auth_user_info_dc * * user_info_dc ,
2022-12-02 10:49:20 +13:00
const enum auth_group_inclusion group_inclusion ,
2011-02-08 16:53:13 +11:00
struct PAC_SIGNATURE_DATA * pac_srv_sig ,
2022-12-02 10:49:20 +13:00
struct PAC_SIGNATURE_DATA * pac_kdc_sig ,
struct PAC_DOMAIN_GROUP_MEMBERSHIP * * resource_groups )
2008-08-28 16:28:47 +10:00
{
NTSTATUS nt_status ;
enum ndr_err_code ndr_err ;
krb5_error_code ret ;
DATA_BLOB pac_logon_info_in , pac_srv_checksum_in , pac_kdc_checksum_in ;
krb5_data k5pac_logon_info_in , k5pac_srv_checksum_in , k5pac_kdc_checksum_in ;
2016-01-07 14:55:07 +01:00
DATA_BLOB pac_upn_dns_info_in ;
krb5_data k5pac_upn_dns_info_in ;
2008-08-28 16:28:47 +10:00
union PAC_INFO info ;
2016-01-07 14:55:07 +01:00
union PAC_INFO _upn_dns_info ;
2021-12-23 22:53:13 +01:00
struct PAC_UPN_DNS_INFO * upn_dns_info = NULL ;
2011-02-08 16:53:13 +11:00
struct auth_user_info_dc * user_info_dc_out ;
2023-09-21 14:20:29 +12:00
const struct PAC_DOMAIN_GROUP_MEMBERSHIP * resource_groups_in = NULL ;
struct PAC_DOMAIN_GROUP_MEMBERSHIP * resource_groups_out = NULL ;
2008-08-28 16:28:47 +10:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
return ENOMEM ;
}
2023-10-30 15:09:28 +13:00
if ( pac = = NULL ) {
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
2008-08-28 16:28:47 +10:00
ret = krb5_pac_get_buffer ( context , pac , PAC_TYPE_LOGON_INFO , & k5pac_logon_info_in ) ;
if ( ret ! = 0 ) {
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
pac_logon_info_in = data_blob_const ( k5pac_logon_info_in . data , k5pac_logon_info_in . length ) ;
2023-09-21 14:20:29 +12:00
ndr_err = ndr_pull_union_blob ( & pac_logon_info_in , tmp_ctx , & info ,
2008-08-28 16:28:47 +10:00
PAC_TYPE_LOGON_INFO ,
( ndr_pull_flags_fn_t ) ndr_pull_PAC_INFO ) ;
2016-08-26 11:51:52 +02:00
smb_krb5_free_data_contents ( context , & k5pac_logon_info_in ) ;
2016-01-07 15:01:16 +01:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2008-08-28 16:28:47 +10:00
nt_status = ndr_map_error2ntstatus ( ndr_err ) ;
DEBUG ( 0 , ( " can't parse the PAC LOGON_INFO: %s \n " , nt_errstr ( nt_status ) ) ) ;
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
2016-01-07 15:01:16 +01:00
if ( info . logon_info . info = = NULL ) {
DEBUG ( 0 , ( " can't parse the PAC LOGON_INFO: missing info pointer \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
2008-08-28 16:28:47 +10:00
2016-01-07 14:55:07 +01:00
ret = krb5_pac_get_buffer ( context , pac , PAC_TYPE_UPN_DNS_INFO ,
& k5pac_upn_dns_info_in ) ;
if ( ret = = ENOENT ) {
ZERO_STRUCT ( k5pac_upn_dns_info_in ) ;
ret = 0 ;
}
if ( ret ! = 0 ) {
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
pac_upn_dns_info_in = data_blob_const ( k5pac_upn_dns_info_in . data ,
k5pac_upn_dns_info_in . length ) ;
if ( pac_upn_dns_info_in . length ! = 0 ) {
ndr_err = ndr_pull_union_blob ( & pac_upn_dns_info_in , tmp_ctx ,
& _upn_dns_info ,
PAC_TYPE_UPN_DNS_INFO ,
( ndr_pull_flags_fn_t ) ndr_pull_PAC_INFO ) ;
2016-08-26 11:51:52 +02:00
smb_krb5_free_data_contents ( context , & k5pac_upn_dns_info_in ) ;
2016-01-07 14:55:07 +01:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
nt_status = ndr_map_error2ntstatus ( ndr_err ) ;
DEBUG ( 0 , ( " can't parse the PAC UPN_DNS_INFO: %s \n " ,
nt_errstr ( nt_status ) ) ) ;
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
upn_dns_info = & _upn_dns_info . upn_dns_info ;
}
2022-09-27 14:47:23 +13:00
/* Pull this right into the normal auth system structures */
2023-09-21 14:21:55 +12:00
nt_status = make_user_info_dc_pac ( tmp_ctx ,
2010-10-02 05:09:42 +10:00
info . logon_info . info ,
2016-01-07 14:55:07 +01:00
upn_dns_info ,
2022-12-02 10:49:20 +13:00
group_inclusion ,
2011-02-08 16:53:13 +11:00
& user_info_dc_out ) ;
2008-08-28 16:28:47 +10:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
2023-08-11 09:55:17 +12:00
DBG_ERR ( " make_user_info_dc_pac() failed - %s \n " ,
2021-12-23 22:53:13 +01:00
nt_errstr ( nt_status ) ) ;
NDR_PRINT_DEBUG ( PAC_LOGON_INFO , info . logon_info . info ) ;
if ( upn_dns_info ! = NULL ) {
NDR_PRINT_DEBUG ( PAC_UPN_DNS_INFO , upn_dns_info ) ;
}
2008-08-28 16:28:47 +10:00
talloc_free ( tmp_ctx ) ;
return EINVAL ;
}
2010-01-12 11:05:16 -05:00
2011-02-08 16:53:13 +11:00
if ( pac_srv_sig ) {
ret = krb5_pac_get_buffer ( context , pac , PAC_TYPE_SRV_CHECKSUM , & k5pac_srv_checksum_in ) ;
if ( ret ! = 0 ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2008-08-28 16:28:47 +10:00
2011-02-08 16:53:13 +11:00
pac_srv_checksum_in = data_blob_const ( k5pac_srv_checksum_in . data , k5pac_srv_checksum_in . length ) ;
ndr_err = ndr_pull_struct_blob ( & pac_srv_checksum_in , pac_srv_sig ,
pac_srv_sig ,
( ndr_pull_flags_fn_t ) ndr_pull_PAC_SIGNATURE_DATA ) ;
2016-08-26 11:51:52 +02:00
smb_krb5_free_data_contents ( context , & k5pac_srv_checksum_in ) ;
2011-02-08 16:53:13 +11:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
nt_status = ndr_map_error2ntstatus ( ndr_err ) ;
2022-09-27 14:47:33 +13:00
DEBUG ( 0 , ( " can't parse the server signature: %s \n " ,
2011-02-08 16:53:13 +11:00
nt_errstr ( nt_status ) ) ) ;
return EINVAL ;
}
2008-08-28 16:28:47 +10:00
}
2011-02-08 16:53:13 +11:00
if ( pac_kdc_sig ) {
ret = krb5_pac_get_buffer ( context , pac , PAC_TYPE_KDC_CHECKSUM , & k5pac_kdc_checksum_in ) ;
if ( ret ! = 0 ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-01-12 11:05:16 -05:00
2011-02-08 16:53:13 +11:00
pac_kdc_checksum_in = data_blob_const ( k5pac_kdc_checksum_in . data , k5pac_kdc_checksum_in . length ) ;
ndr_err = ndr_pull_struct_blob ( & pac_kdc_checksum_in , pac_kdc_sig ,
pac_kdc_sig ,
( ndr_pull_flags_fn_t ) ndr_pull_PAC_SIGNATURE_DATA ) ;
2016-08-26 11:51:52 +02:00
smb_krb5_free_data_contents ( context , & k5pac_kdc_checksum_in ) ;
2011-02-08 16:53:13 +11:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
nt_status = ndr_map_error2ntstatus ( ndr_err ) ;
DEBUG ( 0 , ( " can't parse the KDC signature: %s \n " ,
nt_errstr ( nt_status ) ) ) ;
return EINVAL ;
}
2008-08-28 16:28:47 +10:00
}
2022-06-10 19:18:35 +12:00
/*
* Based on the presence of a REQUESTER_SID PAC buffer , ascertain
* whether the ticket is a TGT . This helps the KDC and kpasswd service
* ensure they do not accept tickets meant for the other .
*
* This heuristic will fail for older Samba versions and Windows prior
* to Nov . 2021 updates , which lack support for the REQUESTER_SID PAC
* buffer .
*/
ret = kerberos_pac_buffer_present ( context , pac , PAC_TYPE_REQUESTER_SID ) ;
if ( ret = = ENOENT ) {
/* This probably isn't a TGT. */
user_info_dc_out - > ticket_type = TICKET_TYPE_NON_TGT ;
} else if ( ret ! = 0 ) {
talloc_free ( tmp_ctx ) ;
return ret ;
} else {
/* This probably is a TGT. */
user_info_dc_out - > ticket_type = TICKET_TYPE_TGT ;
}
2023-09-21 14:13:36 +12:00
/*
* If we have resource groups and the caller wants them returned , we
* oblige .
*/
2023-09-21 14:15:06 +12:00
resource_groups_in = & info . logon_info . info - > resource_groups ;
if ( resource_groups ! = NULL & & resource_groups_in - > groups . count ! = 0 ) {
2023-09-21 14:20:29 +12:00
resource_groups_out = talloc ( tmp_ctx , struct PAC_DOMAIN_GROUP_MEMBERSHIP ) ;
if ( resource_groups_out = = NULL ) {
talloc_free ( tmp_ctx ) ;
return ENOMEM ;
}
* resource_groups_out = ( struct PAC_DOMAIN_GROUP_MEMBERSHIP ) {
. domain_sid = talloc_steal ( resource_groups_out , resource_groups_in - > domain_sid ) ,
. groups = {
. count = resource_groups_in - > groups . count ,
. rids = talloc_steal ( resource_groups_out , resource_groups_in - > groups . rids ) ,
} ,
} ;
2023-09-21 14:13:36 +12:00
}
2023-09-21 14:21:55 +12:00
* user_info_dc = talloc_steal ( mem_ctx , user_info_dc_out ) ;
2023-09-21 14:20:29 +12:00
if ( resource_groups_out ! = NULL ) {
* resource_groups = talloc_steal ( mem_ctx , resource_groups_out ) ;
}
2010-01-12 11:05:16 -05:00
2008-08-28 16:28:47 +10:00
return 0 ;
}
2011-02-08 16:53:13 +11:00
NTSTATUS kerberos_pac_blob_to_user_info_dc ( TALLOC_CTX * mem_ctx ,
DATA_BLOB pac_blob ,
krb5_context context ,
struct auth_user_info_dc * * user_info_dc ,
struct PAC_SIGNATURE_DATA * pac_srv_sig ,
struct PAC_SIGNATURE_DATA * pac_kdc_sig )
2008-08-28 16:28:47 +10:00
{
krb5_error_code ret ;
krb5_pac pac ;
2010-01-12 11:05:16 -05:00
ret = krb5_pac_parse ( context ,
pac_blob . data , pac_blob . length ,
2008-08-28 16:28:47 +10:00
& pac ) ;
if ( ret ) {
2011-06-20 14:55:32 +10:00
return map_nt_error_from_unix_common ( ret ) ;
2008-08-28 16:28:47 +10:00
}
2022-12-02 10:49:20 +13:00
ret = kerberos_pac_to_user_info_dc ( mem_ctx ,
pac ,
context ,
user_info_dc ,
AUTH_INCLUDE_RESOURCE_GROUPS ,
pac_srv_sig ,
pac_kdc_sig ,
NULL ) ;
2008-08-28 16:28:47 +10:00
krb5_pac_free ( context , pac ) ;
if ( ret ) {
2011-06-20 14:55:32 +10:00
return map_nt_error_from_unix_common ( ret ) ;
2008-08-28 16:28:47 +10:00
}
return NT_STATUS_OK ;
}