2011-02-09 08:05:54 +03:00
/*
2005-06-29 17:55:09 +04:00
Unix SMB / CIFS implementation .
Convert a server info struct into the form for PAC and NETLOGON replies
2011-07-18 16:26:31 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2011
2005-06-29 17:55:09 +04:00
Copyright ( C ) Stefan Metzmacher < metze @ samba . org > 2005
2011-02-09 08:05:54 +03:00
2005-06-29 17:55:09 +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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-06-29 17:55:09 +04:00
( at your option ) any later version .
2011-02-09 08:05:54 +03:00
2005-06-29 17:55:09 +04: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 .
2011-02-09 08:05:54 +03:00
2005-06-29 17:55:09 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-06-29 17:55:09 +04:00
*/
# include "includes.h"
2011-02-09 08:05:54 +03:00
# include "librpc/gen_ndr/auth.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2008-10-20 20:59:51 +04:00
# include "auth/auth_sam_reply.h"
2005-06-29 17:55:09 +04:00
2011-02-08 08:53:13 +03:00
NTSTATUS auth_convert_user_info_dc_sambaseinfo ( TALLOC_CTX * mem_ctx ,
struct auth_user_info_dc * user_info_dc ,
2005-06-29 17:55:09 +04:00
struct netr_SamBaseInfo * * _sam )
{
2011-01-20 15:39:37 +03:00
NTSTATUS status ;
2011-02-08 08:53:13 +03:00
struct auth_user_info * info ;
2005-06-29 17:55:09 +04:00
struct netr_SamBaseInfo * sam = talloc_zero ( mem_ctx , struct netr_SamBaseInfo ) ;
NT_STATUS_HAVE_NO_MEMORY ( sam ) ;
2011-02-08 08:53:13 +03:00
if ( user_info_dc - > num_sids > PRIMARY_USER_SID_INDEX ) {
status = dom_sid_split_rid ( sam , & user_info_dc - > sids [ PRIMARY_USER_SID_INDEX ] ,
2011-01-20 15:39:37 +03:00
& sam - > domain_sid , & sam - > rid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
} else {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-02-08 08:53:13 +03:00
if ( user_info_dc - > num_sids > PRIMARY_GROUP_SID_INDEX ) {
status = dom_sid_split_rid ( NULL , & user_info_dc - > sids [ PRIMARY_GROUP_SID_INDEX ] ,
2011-01-20 15:39:37 +03:00
NULL , & sam - > primary_gid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
} else {
/* if we have to encode something like SYSTEM (with no
* second SID in the token ) then this is the only
* choice */
sam - > primary_gid = sam - > rid ;
}
2005-10-24 11:11:40 +04:00
2011-02-08 08:53:13 +03:00
info = user_info_dc - > info ;
sam - > last_logon = info - > last_logon ;
sam - > last_logoff = info - > last_logoff ;
sam - > acct_expiry = info - > acct_expiry ;
sam - > last_password_change = info - > last_password_change ;
sam - > allow_password_change = info - > allow_password_change ;
sam - > force_password_change = info - > force_password_change ;
sam - > account_name . string = info - > account_name ;
sam - > full_name . string = info - > full_name ;
sam - > logon_script . string = info - > logon_script ;
sam - > profile_path . string = info - > profile_path ;
sam - > home_directory . string = info - > home_directory ;
sam - > home_drive . string = info - > home_drive ;
sam - > logon_count = info - > logon_count ;
2011-02-09 02:46:21 +03:00
sam - > bad_password_count = info - > bad_password_count ;
2005-06-29 17:55:09 +04:00
sam - > groups . count = 0 ;
sam - > groups . rids = NULL ;
2011-02-08 08:53:13 +03:00
if ( user_info_dc - > num_sids > 2 ) {
2010-04-12 16:34:28 +04:00
size_t i ;
2005-06-29 17:55:09 +04:00
sam - > groups . rids = talloc_array ( sam , struct samr_RidWithAttribute ,
2011-02-08 08:53:13 +03:00
user_info_dc - > num_sids ) ;
2005-06-29 17:55:09 +04:00
if ( sam - > groups . rids = = NULL )
return NT_STATUS_NO_MEMORY ;
2011-02-08 08:53:13 +03:00
for ( i = 2 ; i < user_info_dc - > num_sids ; i + + ) {
struct dom_sid * group_sid = & user_info_dc - > sids [ i ] ;
2005-10-24 11:11:40 +04:00
if ( ! dom_sid_in_domain ( sam - > domain_sid , group_sid ) ) {
/* We handle this elsewhere */
continue ;
}
2005-06-29 17:55:09 +04:00
sam - > groups . rids [ sam - > groups . count ] . rid =
group_sid - > sub_auths [ group_sid - > num_auths - 1 ] ;
2011-02-09 08:05:54 +03:00
sam - > groups . rids [ sam - > groups . count ] . attributes =
2005-06-29 17:55:09 +04:00
SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ;
sam - > groups . count + = 1 ;
}
}
2007-12-11 12:18:10 +03:00
sam - > user_flags = 0 ; /* w2k3 uses NETLOGON_EXTRA_SIDS | NETLOGON_NTLMV2_ENABLED */
2011-02-08 08:53:13 +03:00
sam - > acct_flags = user_info_dc - > info - > acct_flags ;
sam - > logon_server . string = user_info_dc - > info - > logon_server ;
sam - > domain . string = user_info_dc - > info - > domain_name ;
2005-06-29 17:55:09 +04:00
ZERO_STRUCT ( sam - > unknown ) ;
ZERO_STRUCT ( sam - > key ) ;
2011-02-08 08:53:13 +03:00
if ( user_info_dc - > user_session_key . length = = sizeof ( sam - > key . key ) ) {
memcpy ( sam - > key . key , user_info_dc - > user_session_key . data , sizeof ( sam - > key . key ) ) ;
2005-06-29 17:55:09 +04:00
}
ZERO_STRUCT ( sam - > LMSessKey ) ;
2011-02-08 08:53:13 +03:00
if ( user_info_dc - > lm_session_key . length = = sizeof ( sam - > LMSessKey . key ) ) {
memcpy ( sam - > LMSessKey . key , user_info_dc - > lm_session_key . data ,
2005-06-29 17:55:09 +04:00
sizeof ( sam - > LMSessKey . key ) ) ;
}
2011-02-09 08:05:54 +03:00
2005-06-29 17:55:09 +04:00
* _sam = sam ;
return NT_STATUS_OK ;
2011-02-09 08:05:54 +03:00
}
2005-06-29 17:55:09 +04:00
2010-05-06 10:47:15 +04:00
/* Note that the validity of the _sam3 structure is only as long as
2011-02-08 08:53:13 +03:00
* the user_info_dc it was generated from */
NTSTATUS auth_convert_user_info_dc_saminfo3 ( TALLOC_CTX * mem_ctx ,
struct auth_user_info_dc * user_info_dc ,
2005-07-05 14:57:39 +04:00
struct netr_SamInfo3 * * _sam3 )
{
struct netr_SamBaseInfo * sam ;
struct netr_SamInfo3 * sam3 = talloc_zero ( mem_ctx , struct netr_SamInfo3 ) ;
2005-10-24 11:11:40 +04:00
NTSTATUS status ;
2010-04-12 16:34:28 +04:00
size_t i ;
2005-07-05 14:57:39 +04:00
NT_STATUS_HAVE_NO_MEMORY ( sam3 ) ;
2011-02-08 08:53:13 +03:00
status = auth_convert_user_info_dc_sambaseinfo ( sam3 , user_info_dc , & sam ) ;
2005-10-24 11:11:40 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-20 15:39:37 +03:00
talloc_free ( sam3 ) ;
2005-10-24 11:11:40 +04:00
return status ;
2005-08-04 03:14:38 +04:00
}
2005-10-24 11:11:40 +04:00
sam3 - > base = * sam ;
2005-07-05 14:57:39 +04:00
sam3 - > sidcount = 0 ;
sam3 - > sids = NULL ;
2011-02-09 08:05:54 +03:00
2005-10-24 11:11:40 +04:00
sam3 - > sids = talloc_array ( sam , struct netr_SidAttr ,
2011-02-08 08:53:13 +03:00
user_info_dc - > num_sids ) ;
2011-01-20 15:39:37 +03:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( sam3 - > sids , sam3 ) ;
/* We don't put the user and group SIDs in there */
2011-02-08 08:53:13 +03:00
for ( i = 2 ; i < user_info_dc - > num_sids ; i + + ) {
if ( dom_sid_in_domain ( sam - > domain_sid , & user_info_dc - > sids [ i ] ) ) {
2005-10-24 11:11:40 +04:00
continue ;
2005-07-05 14:57:39 +04:00
}
2011-02-08 08:53:13 +03:00
sam3 - > sids [ sam3 - > sidcount ] . sid = dom_sid_dup ( sam3 - > sids , & user_info_dc - > sids [ i ] ) ;
2011-01-20 15:39:37 +03:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( sam3 - > sids [ sam3 - > sidcount ] . sid , sam3 ) ;
2008-01-24 12:24:41 +03:00
sam3 - > sids [ sam3 - > sidcount ] . attributes =
2005-10-24 11:11:40 +04:00
SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ;
sam3 - > sidcount + = 1 ;
}
if ( sam3 - > sidcount ) {
sam3 - > base . user_flags | = NETLOGON_EXTRA_SIDS ;
} else {
sam3 - > sids = NULL ;
2005-07-05 14:57:39 +04:00
}
* _sam3 = sam3 ;
return NT_STATUS_OK ;
2011-02-09 08:05:54 +03:00
}
2005-07-05 14:57:39 +04:00
2009-01-21 12:43:15 +03:00
/**
2011-02-08 08:53:13 +03:00
* Make a user_info_dc struct from the info3 returned by a domain logon
2009-01-21 12:43:15 +03:00
*/
2011-02-08 08:53:13 +03:00
NTSTATUS make_user_info_dc_netlogon_validation ( TALLOC_CTX * mem_ctx ,
2009-01-21 12:43:15 +03:00
const char * account_name ,
uint16_t validation_level ,
union netr_Validation * validation ,
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * * _user_info_dc )
2009-01-21 12:43:15 +03:00
{
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * user_info_dc ;
struct auth_user_info * info ;
2009-01-21 12:43:15 +03:00
struct netr_SamBaseInfo * base = NULL ;
2010-04-12 16:34:28 +04:00
uint32_t i ;
2009-01-21 12:43:15 +03:00
switch ( validation_level ) {
case 2 :
if ( ! validation | | ! validation - > sam2 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
base = & validation - > sam2 - > base ;
break ;
case 3 :
if ( ! validation | | ! validation - > sam3 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
base = & validation - > sam3 - > base ;
break ;
case 6 :
if ( ! validation | | ! validation - > sam6 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
base = & validation - > sam6 - > base ;
break ;
default :
return NT_STATUS_INVALID_LEVEL ;
}
2011-02-08 08:53:13 +03:00
user_info_dc = talloc ( mem_ctx , struct auth_user_info_dc ) ;
NT_STATUS_HAVE_NO_MEMORY ( user_info_dc ) ;
2009-01-21 12:43:15 +03:00
/*
Here is where we should check the list of
2011-02-09 08:05:54 +03:00
trusted domains , and verify that the SID
2009-01-21 12:43:15 +03:00
matches .
*/
2011-01-20 15:39:37 +03:00
if ( ! base - > domain_sid ) {
DEBUG ( 0 , ( " Cannot operate on a Netlogon Validation without a domain SID " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2009-01-21 12:43:15 +03:00
2011-01-20 15:39:37 +03:00
/* The IDL layer would be a better place to check this, but to
* guard the integer addition below , we double - check */
if ( base - > groups . count > 65535 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2009-01-21 12:43:15 +03:00
2011-02-08 08:53:13 +03:00
user_info_dc - > num_sids = 2 ;
2009-01-21 12:43:15 +03:00
2011-02-08 08:53:13 +03:00
user_info_dc - > sids = talloc_array ( user_info_dc , struct dom_sid , user_info_dc - > num_sids + base - > groups . count ) ;
NT_STATUS_HAVE_NO_MEMORY ( user_info_dc - > sids ) ;
2011-01-20 15:39:37 +03:00
2011-02-08 08:53:13 +03:00
user_info_dc - > sids [ PRIMARY_USER_SID_INDEX ] = * base - > domain_sid ;
if ( ! sid_append_rid ( & user_info_dc - > sids [ PRIMARY_USER_SID_INDEX ] , base - > rid ) ) {
2011-01-20 15:39:37 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
2011-02-08 08:53:13 +03:00
user_info_dc - > sids [ PRIMARY_GROUP_SID_INDEX ] = * base - > domain_sid ;
if ( ! sid_append_rid ( & user_info_dc - > sids [ PRIMARY_GROUP_SID_INDEX ] , base - > primary_gid ) ) {
2011-01-20 15:39:37 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2009-01-21 12:43:15 +03:00
}
for ( i = 0 ; i < base - > groups . count ; i + + ) {
2011-02-08 08:53:13 +03:00
user_info_dc - > sids [ user_info_dc - > num_sids ] = * base - > domain_sid ;
if ( ! sid_append_rid ( & user_info_dc - > sids [ user_info_dc - > num_sids ] , base - > groups . rids [ i ] . rid ) ) {
2011-01-20 15:39:37 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
2011-02-08 08:53:13 +03:00
user_info_dc - > num_sids + + ;
2009-01-21 12:43:15 +03:00
}
/* Copy 'other' sids. We need to do sid filtering here to
2011-02-09 08:05:54 +03:00
prevent possible elevation of privileges . See :
2009-01-21 12:43:15 +03:00
http : //www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
*/
if ( validation_level = = 3 ) {
2011-02-08 08:53:13 +03:00
struct dom_sid * dgrps = user_info_dc - > sids ;
2011-01-20 15:39:37 +03:00
size_t sidcount ;
/* The IDL layer would be a better place to check this, but to
* guard the integer addition below , we double - check */
if ( validation - > sam3 - > sidcount > 65535 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2009-01-21 12:43:15 +03:00
2011-02-08 08:53:13 +03:00
sidcount = user_info_dc - > num_sids + validation - > sam3 - > sidcount ;
2009-01-21 12:43:15 +03:00
if ( validation - > sam3 - > sidcount > 0 ) {
2011-02-08 08:53:13 +03:00
dgrps = talloc_realloc ( user_info_dc , dgrps , struct dom_sid , sidcount ) ;
2009-01-21 12:43:15 +03:00
NT_STATUS_HAVE_NO_MEMORY ( dgrps ) ;
for ( i = 0 ; i < validation - > sam3 - > sidcount ; i + + ) {
2011-01-20 15:39:37 +03:00
if ( validation - > sam3 - > sids [ i ] . sid ) {
2011-02-08 08:53:13 +03:00
dgrps [ user_info_dc - > num_sids ] = * validation - > sam3 - > sids [ i ] . sid ;
user_info_dc - > num_sids + + ;
2011-01-20 15:39:37 +03:00
}
2009-01-21 12:43:15 +03:00
}
}
2011-02-08 08:53:13 +03:00
user_info_dc - > sids = dgrps ;
2009-01-21 12:43:15 +03:00
/* Where are the 'global' sids?... */
}
2011-02-08 08:53:13 +03:00
user_info_dc - > info = info = talloc_zero ( user_info_dc , struct auth_user_info ) ;
NT_STATUS_HAVE_NO_MEMORY ( user_info_dc - > info ) ;
2009-01-21 12:43:15 +03:00
if ( base - > account_name . string ) {
2011-02-08 08:53:13 +03:00
info - > account_name = talloc_reference ( info , base - > account_name . string ) ;
2009-01-21 12:43:15 +03:00
} else {
2011-02-08 08:53:13 +03:00
info - > account_name = talloc_strdup ( info , account_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > account_name ) ;
2009-01-21 12:43:15 +03:00
}
2011-02-08 08:53:13 +03:00
info - > domain_name = talloc_reference ( info , base - > domain . string ) ;
info - > full_name = talloc_reference ( info , base - > full_name . string ) ;
info - > logon_script = talloc_reference ( info , base - > logon_script . string ) ;
info - > profile_path = talloc_reference ( info , base - > profile_path . string ) ;
info - > home_directory = talloc_reference ( info , base - > home_directory . string ) ;
info - > home_drive = talloc_reference ( info , base - > home_drive . string ) ;
info - > logon_server = talloc_reference ( info , base - > logon_server . string ) ;
info - > last_logon = base - > last_logon ;
info - > last_logoff = base - > last_logoff ;
info - > acct_expiry = base - > acct_expiry ;
info - > last_password_change = base - > last_password_change ;
info - > allow_password_change = base - > allow_password_change ;
info - > force_password_change = base - > force_password_change ;
info - > logon_count = base - > logon_count ;
info - > bad_password_count = base - > bad_password_count ;
info - > acct_flags = base - > acct_flags ;
info - > authenticated = true ;
2009-01-21 12:43:15 +03:00
/* ensure we are never given NULL session keys */
if ( all_zero ( base - > key . key , sizeof ( base - > key . key ) ) ) {
2011-02-08 08:53:13 +03:00
user_info_dc - > user_session_key = data_blob ( NULL , 0 ) ;
2009-01-21 12:43:15 +03:00
} else {
2011-02-08 08:53:13 +03:00
user_info_dc - > user_session_key = data_blob_talloc ( user_info_dc , base - > key . key , sizeof ( base - > key . key ) ) ;
NT_STATUS_HAVE_NO_MEMORY ( user_info_dc - > user_session_key . data ) ;
2009-01-21 12:43:15 +03:00
}
if ( all_zero ( base - > LMSessKey . key , sizeof ( base - > LMSessKey . key ) ) ) {
2011-02-08 08:53:13 +03:00
user_info_dc - > lm_session_key = data_blob ( NULL , 0 ) ;
2009-01-21 12:43:15 +03:00
} else {
2011-02-08 08:53:13 +03:00
user_info_dc - > lm_session_key = data_blob_talloc ( user_info_dc , base - > LMSessKey . key , sizeof ( base - > LMSessKey . key ) ) ;
NT_STATUS_HAVE_NO_MEMORY ( user_info_dc - > lm_session_key . data ) ;
2009-01-21 12:43:15 +03:00
}
2011-02-08 08:53:13 +03:00
* _user_info_dc = user_info_dc ;
2009-01-21 12:43:15 +03:00
return NT_STATUS_OK ;
}
2010-10-01 23:09:42 +04:00
/**
2011-02-08 08:53:13 +03:00
* Make a user_info_dc struct from the PAC_LOGON_INFO supplied in the krb5 logon
2010-10-01 23:09:42 +04:00
*/
2011-02-08 08:53:13 +03:00
NTSTATUS make_user_info_dc_pac ( TALLOC_CTX * mem_ctx ,
2010-10-01 23:09:42 +04:00
struct PAC_LOGON_INFO * pac_logon_info ,
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * * _user_info_dc )
2010-10-01 23:09:42 +04:00
{
uint32_t i ;
NTSTATUS nt_status ;
union netr_Validation validation ;
2011-02-08 08:53:13 +03:00
struct auth_user_info_dc * user_info_dc ;
2010-10-01 23:09:42 +04:00
validation . sam3 = & pac_logon_info - > info3 ;
2011-02-08 08:53:13 +03:00
nt_status = make_user_info_dc_netlogon_validation ( mem_ctx , " " , 3 , & validation , & user_info_dc ) ;
2010-10-01 23:09:42 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
return nt_status ;
}
if ( pac_logon_info - > res_groups . count > 0 ) {
2011-01-20 15:39:37 +03:00
size_t sidcount ;
/* The IDL layer would be a better place to check this, but to
* guard the integer addition below , we double - check */
if ( pac_logon_info - > res_groups . count > 65535 ) {
2011-02-08 08:53:13 +03:00
talloc_free ( user_info_dc ) ;
2011-01-20 15:39:37 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
/*
Here is where we should check the list of
trusted domains , and verify that the SID
matches .
*/
if ( ! pac_logon_info - > res_group_dom_sid ) {
DEBUG ( 0 , ( " Cannot operate on a PAC without a resource domain SID " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2011-02-08 08:53:13 +03:00
sidcount = user_info_dc - > num_sids + pac_logon_info - > res_groups . count ;
user_info_dc - > sids
= talloc_realloc ( user_info_dc , user_info_dc - > sids , struct dom_sid , sidcount ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( user_info_dc - > sids , user_info_dc ) ;
2010-10-01 23:09:42 +04:00
for ( i = 0 ; pac_logon_info - > res_group_dom_sid & & i < pac_logon_info - > res_groups . count ; i + + ) {
2011-02-08 08:53:13 +03:00
user_info_dc - > sids [ user_info_dc - > num_sids ] = * pac_logon_info - > res_group_dom_sid ;
if ( ! sid_append_rid ( & user_info_dc - > sids [ user_info_dc - > num_sids ] ,
2011-01-20 15:39:37 +03:00
pac_logon_info - > res_groups . rids [ i ] . rid ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2011-02-08 08:53:13 +03:00
user_info_dc - > num_sids + + ;
2010-10-01 23:09:42 +04:00
}
}
2011-02-08 08:53:13 +03:00
* _user_info_dc = user_info_dc ;
2010-10-01 23:09:42 +04:00
return NT_STATUS_OK ;
}