2010-04-12 00:37:08 +04:00
/*
Unix SMB / CIFS implementation .
Authentication utility functions
Copyright ( C ) Volker Lendecke 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"
2011-03-25 04:28:05 +03:00
# include "auth.h"
2016-12-27 15:52:00 +03:00
# include "lib/util_unixsids.h"
2010-05-18 02:16:40 +04:00
# include "../lib/crypto/arcfour.h"
2010-08-05 17:14:04 +04:00
# include "../librpc/gen_ndr/netlogon.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-01-11 17:08:41 +03:00
# include "rpc_client/util_netlogon.h"
2011-02-25 00:30:16 +03:00
# include "nsswitch/libwbclient/wbclient.h"
2013-12-13 22:08:34 +04:00
# include "lib/winbind_util.h"
2011-03-18 20:58:37 +03:00
# include "passdb.h"
2010-04-12 00:37:08 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_AUTH
/***************************************************************************
Make a server_info struct . Free with TALLOC_FREE ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct auth_serversupplied_info * make_server_info ( TALLOC_CTX * mem_ctx )
{
struct auth_serversupplied_info * result ;
2011-06-07 05:44:43 +04:00
result = talloc_zero ( mem_ctx , struct auth_serversupplied_info ) ;
2010-04-12 00:37:08 +04:00
if ( result = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return NULL ;
}
/* Initialise the uid and gid values to something non-zero
which may save us from giving away root access if there
is a bug in allocating these fields . */
result - > utok . uid = - 1 ;
result - > utok . gid = - 1 ;
2010-05-28 21:18:13 +04:00
2010-04-12 00:37:08 +04:00
return result ;
}
2010-04-11 17:25:55 +04:00
/****************************************************************************
2010-05-27 11:41:56 +04:00
inits a netr_SamInfo2 structure from an auth_serversupplied_info . sam2 must
already be initialized and is used as the talloc parent for its members .
2010-04-11 17:25:55 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-27 11:41:56 +04:00
NTSTATUS serverinfo_to_SamInfo2 ( struct auth_serversupplied_info * server_info ,
struct netr_SamInfo2 * sam2 )
2010-04-11 17:25:55 +04:00
{
2018-01-11 11:06:31 +03:00
struct netr_SamInfo3 * info3 = NULL ;
NTSTATUS status ;
2010-04-11 17:25:55 +04:00
2018-01-11 11:06:31 +03:00
status = copy_netr_SamInfo3 ( sam2 ,
server_info - > info3 ,
& info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2010-04-11 17:25:55 +04:00
}
2011-02-14 03:35:21 +03:00
if ( server_info - > session_key . length ) {
2010-05-27 11:41:56 +04:00
memcpy ( info3 - > base . key . key ,
2011-02-14 03:35:21 +03:00
server_info - > session_key . data ,
2010-05-27 11:41:56 +04:00
MIN ( sizeof ( info3 - > base . key . key ) ,
2011-02-14 03:35:21 +03:00
server_info - > session_key . length ) ) ;
2010-04-11 17:25:55 +04:00
}
if ( server_info - > lm_session_key . length ) {
2010-05-27 11:41:56 +04:00
memcpy ( info3 - > base . LMSessKey . key ,
2010-04-11 17:25:55 +04:00
server_info - > lm_session_key . data ,
2010-05-27 11:41:56 +04:00
MIN ( sizeof ( info3 - > base . LMSessKey . key ) ,
2010-04-11 17:25:55 +04:00
server_info - > lm_session_key . length ) ) ;
}
2010-05-27 11:41:56 +04:00
sam2 - > base = info3 - > base ;
2010-04-11 17:25:55 +04:00
return NT_STATUS_OK ;
}
/****************************************************************************
inits a netr_SamInfo3 structure from an auth_serversupplied_info . sam3 must
already be initialized and is used as the talloc parent for its members .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-15 19:24:08 +04:00
NTSTATUS serverinfo_to_SamInfo3 ( const struct auth_serversupplied_info * server_info ,
2010-04-11 17:25:55 +04:00
struct netr_SamInfo3 * sam3 )
{
2018-01-11 11:06:31 +03:00
struct netr_SamInfo3 * info3 = NULL ;
NTSTATUS status ;
2010-05-27 11:41:56 +04:00
2018-01-11 11:06:31 +03:00
status = copy_netr_SamInfo3 ( sam3 ,
server_info - > info3 ,
& info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2010-04-11 17:25:55 +04:00
}
2011-02-14 03:35:21 +03:00
if ( server_info - > session_key . length ) {
2010-05-27 11:41:56 +04:00
memcpy ( info3 - > base . key . key ,
2011-02-14 03:35:21 +03:00
server_info - > session_key . data ,
2010-05-27 11:41:56 +04:00
MIN ( sizeof ( info3 - > base . key . key ) ,
2011-02-14 03:35:21 +03:00
server_info - > session_key . length ) ) ;
2010-05-27 11:41:56 +04:00
}
if ( server_info - > lm_session_key . length ) {
memcpy ( info3 - > base . LMSessKey . key ,
server_info - > lm_session_key . data ,
MIN ( sizeof ( info3 - > base . LMSessKey . key ) ,
server_info - > lm_session_key . length ) ) ;
}
sam3 - > base = info3 - > base ;
2010-04-11 17:25:55 +04:00
sam3 - > sidcount = 0 ;
sam3 - > sids = NULL ;
return NT_STATUS_OK ;
}
/****************************************************************************
inits a netr_SamInfo6 structure from an auth_serversupplied_info . sam6 must
already be initialized and is used as the talloc parent for its members .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS serverinfo_to_SamInfo6 ( struct auth_serversupplied_info * server_info ,
struct netr_SamInfo6 * sam6 )
{
struct pdb_domain_info * dominfo ;
2018-01-11 11:06:31 +03:00
struct netr_SamInfo3 * info3 = NULL ;
NTSTATUS status ;
2010-04-11 17:25:55 +04:00
if ( ( pdb_capabilities ( ) & PDB_CAP_ADS ) = = 0 ) {
DEBUG ( 10 , ( " Not adding validation info level 6 "
" without ADS passdb backend \n " ) ) ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
dominfo = pdb_get_domain_info ( sam6 ) ;
if ( dominfo = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2018-01-11 11:06:31 +03:00
status = copy_netr_SamInfo3 ( sam6 ,
server_info - > info3 ,
& info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2010-04-11 17:25:55 +04:00
}
2011-02-14 03:35:21 +03:00
if ( server_info - > session_key . length ) {
2010-05-27 11:41:56 +04:00
memcpy ( info3 - > base . key . key ,
2011-02-14 03:35:21 +03:00
server_info - > session_key . data ,
2010-05-27 11:41:56 +04:00
MIN ( sizeof ( info3 - > base . key . key ) ,
2011-02-14 03:35:21 +03:00
server_info - > session_key . length ) ) ;
2010-05-27 11:41:56 +04:00
}
if ( server_info - > lm_session_key . length ) {
memcpy ( info3 - > base . LMSessKey . key ,
server_info - > lm_session_key . data ,
MIN ( sizeof ( info3 - > base . LMSessKey . key ) ,
server_info - > lm_session_key . length ) ) ;
}
sam6 - > base = info3 - > base ;
2010-04-11 17:25:55 +04:00
sam6 - > sidcount = 0 ;
sam6 - > sids = NULL ;
2010-04-12 16:49:14 +04:00
sam6 - > dns_domainname . string = talloc_strdup ( sam6 , dominfo - > dns_domain ) ;
if ( sam6 - > dns_domainname . string = = NULL ) {
2010-04-11 17:25:55 +04:00
return NT_STATUS_NO_MEMORY ;
}
2016-02-01 23:45:48 +03:00
sam6 - > principal_name . string = talloc_asprintf (
sam6 , " %s@%s " , sam6 - > base . account_name . string ,
sam6 - > dns_domainname . string ) ;
if ( sam6 - > principal_name . string = = NULL ) {
2010-04-11 17:25:55 +04:00
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
2010-05-27 10:07:33 +04:00
2010-05-28 21:18:13 +04:00
static NTSTATUS append_netr_SidAttr ( TALLOC_CTX * mem_ctx ,
struct netr_SidAttr * * sids ,
uint32_t * count ,
const struct dom_sid2 * asid ,
uint32_t attributes )
{
uint32_t t = * count ;
* sids = talloc_realloc ( mem_ctx , * sids , struct netr_SidAttr , t + 1 ) ;
if ( * sids = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2010-08-26 19:21:39 +04:00
( * sids ) [ t ] . sid = dom_sid_dup ( * sids , asid ) ;
2010-05-28 21:18:13 +04:00
if ( ( * sids ) [ t ] . sid = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
( * sids ) [ t ] . attributes = attributes ;
* count = t + 1 ;
return NT_STATUS_OK ;
}
2010-11-05 17:44:55 +03:00
/* Fills the samr_RidWithAttributeArray with the provided sids.
2010-05-28 21:18:13 +04:00
* If it happens that we have additional groups that do not belong
* to the domain , add their sids as extra sids */
static NTSTATUS group_sids_to_info3 ( struct netr_SamInfo3 * info3 ,
const struct dom_sid * sids ,
size_t num_sids )
2010-05-27 10:07:33 +04:00
{
2010-05-28 21:18:13 +04:00
uint32_t attributes = SE_GROUP_MANDATORY |
SE_GROUP_ENABLED_BY_DEFAULT |
SE_GROUP_ENABLED ;
struct samr_RidWithAttributeArray * groups ;
struct dom_sid * domain_sid ;
2010-05-27 10:07:33 +04:00
unsigned int i ;
2010-05-28 21:18:13 +04:00
NTSTATUS status ;
uint32_t rid ;
2010-05-27 10:07:33 +04:00
bool ok ;
2010-05-28 21:18:13 +04:00
domain_sid = info3 - > base . domain_sid ;
groups = & info3 - > base . groups ;
groups - > rids = talloc_array ( info3 ,
2010-05-27 10:07:33 +04:00
struct samr_RidWithAttribute , num_sids ) ;
if ( ! groups - > rids ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < num_sids ; i + + ) {
2010-05-28 21:18:13 +04:00
ok = sid_peek_check_rid ( domain_sid , & sids [ i ] , & rid ) ;
if ( ok ) {
/* store domain group rid */
2011-10-17 23:24:41 +04:00
groups - > rids [ groups - > count ] . rid = rid ;
groups - > rids [ groups - > count ] . attributes = attributes ;
2010-05-28 21:18:13 +04:00
groups - > count + + ;
continue ;
}
2010-05-27 10:07:33 +04:00
2010-05-28 21:18:13 +04:00
/* if this wasn't a domain sid, add it as extra sid */
status = append_netr_SidAttr ( info3 , & info3 - > sids ,
& info3 - > sidcount ,
& sids [ i ] , attributes ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2010-05-27 10:07:33 +04:00
}
return NT_STATUS_OK ;
}
2014-06-17 10:11:58 +04:00
/*
* Merge resource SIDs , if any , into the passed in info3 structure .
*/
static NTSTATUS merge_resource_sids ( const struct PAC_LOGON_INFO * logon_info ,
struct netr_SamInfo3 * info3 )
{
uint32_t i = 0 ;
2016-05-20 15:16:35 +03:00
const struct PAC_DOMAIN_GROUP_MEMBERSHIP * rg = NULL ;
2014-06-17 10:11:58 +04:00
2016-05-20 15:16:35 +03:00
if ( logon_info - > info3 . base . user_flags & NETLOGON_RESOURCE_GROUPS ) {
rg = & logon_info - > resource_groups ;
}
if ( rg = = NULL ) {
2014-06-17 10:11:58 +04:00
return NT_STATUS_OK ;
}
2016-05-20 15:16:35 +03:00
if ( rg - > domain_sid = = NULL ) {
DEBUG ( 10 , ( " Missing Resource Group Domain SID \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
/* The IDL layer would be a better place to check this, but to
* guard the integer addition below , we double - check */
if ( rg - > groups . count > 65535 ) {
DEBUG ( 10 , ( " Too much Resource Group RIDs %u \n " ,
( unsigned ) rg - > groups . count ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2014-06-17 10:11:58 +04:00
/*
* If there are any resource groups ( SID Compression ) add
* them to the extra sids portion of the info3 in the PAC .
*
* This makes the info3 look like it would if we got the info
* from the DC rather than the PAC .
*/
/*
* Construct a SID for each RID in the list and then append it
* to the info3 .
*/
2016-05-20 15:16:35 +03:00
for ( i = 0 ; i < rg - > groups . count ; i + + ) {
2014-06-17 10:11:58 +04:00
NTSTATUS status ;
struct dom_sid new_sid ;
2016-05-20 15:16:35 +03:00
uint32_t attributes = rg - > groups . rids [ i ] . attributes ;
2014-06-17 10:11:58 +04:00
sid_compose ( & new_sid ,
2016-05-20 15:16:35 +03:00
rg - > domain_sid ,
rg - > groups . rids [ i ] . rid ) ;
2014-06-17 10:11:58 +04:00
DEBUG ( 10 , ( " Adding SID %s to extra SIDS \n " ,
sid_string_dbg ( & new_sid ) ) ) ;
status = append_netr_SidAttr ( info3 , & info3 - > sids ,
& info3 - > sidcount ,
& new_sid ,
attributes ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " failed to append SID %s to extra SIDS: %s \n " ,
sid_string_dbg ( & new_sid ) ,
nt_errstr ( status ) ) ) ;
return status ;
}
}
return NT_STATUS_OK ;
}
/*
* Create a copy of an info3 struct from the struct PAC_LOGON_INFO ,
* then merge resource SIDs , if any , into it . If successful return
* the created info3 struct .
*/
NTSTATUS create_info3_from_pac_logon_info ( TALLOC_CTX * mem_ctx ,
const struct PAC_LOGON_INFO * logon_info ,
struct netr_SamInfo3 * * pp_info3 )
{
NTSTATUS status ;
2018-01-11 11:06:31 +03:00
struct netr_SamInfo3 * info3 = NULL ;
status = copy_netr_SamInfo3 ( mem_ctx ,
& logon_info - > info3 ,
& info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2014-06-17 10:11:58 +04:00
}
2018-01-11 11:06:31 +03:00
2014-06-17 10:11:58 +04:00
status = merge_resource_sids ( logon_info , info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( info3 ) ;
return status ;
}
* pp_info3 = info3 ;
return NT_STATUS_OK ;
}
2018-01-23 23:32:25 +03:00
/*
* Create a copy of an info6 struct from the PAC_UPN_DNS_INFO and PAC_LOGON_INFO
* then merge resource SIDs , if any , into it . If successful return the created
* info6 struct .
*/
NTSTATUS create_info6_from_pac ( TALLOC_CTX * mem_ctx ,
const struct PAC_LOGON_INFO * logon_info ,
const struct PAC_UPN_DNS_INFO * upn_dns_info ,
struct netr_SamInfo6 * * pp_info6 )
{
NTSTATUS status ;
struct netr_SamInfo6 * info6 = NULL ;
struct netr_SamInfo3 * info3 = NULL ;
info6 = talloc_zero ( mem_ctx , struct netr_SamInfo6 ) ;
if ( info6 = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = copy_netr_SamInfo3 ( info6 ,
& logon_info - > info3 ,
& info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( info6 ) ;
return status ;
}
status = merge_resource_sids ( logon_info , info3 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( info6 ) ;
return status ;
}
info6 - > base = info3 - > base ;
info6 - > sids = info3 - > sids ;
info6 - > sidcount = info3 - > sidcount ;
if ( upn_dns_info ! = NULL ) {
info6 - > dns_domainname . string = talloc_strdup ( info6 ,
upn_dns_info - > dns_domain_name ) ;
if ( info6 - > dns_domainname . string = = NULL ) {
TALLOC_FREE ( info6 ) ;
return NT_STATUS_NO_MEMORY ;
}
info6 - > principal_name . string = talloc_strdup ( info6 ,
upn_dns_info - > upn_name ) ;
if ( info6 - > principal_name . string = = NULL ) {
TALLOC_FREE ( info6 ) ;
return NT_STATUS_NO_MEMORY ;
}
}
* pp_info6 = info6 ;
return NT_STATUS_OK ;
}
2015-01-14 00:35:56 +03:00
/*
* Check if this is a " Unix Users " domain user , or a
* " Unix Groups " domain group , we need to handle it
* in a special way if that ' s the case .
*/
static NTSTATUS SamInfo3_handle_sids ( const char * username ,
const struct dom_sid * user_sid ,
const struct dom_sid * group_sid ,
struct netr_SamInfo3 * info3 ,
struct dom_sid * domain_sid ,
struct extra_auth_info * extra )
{
if ( sid_check_is_in_unix_users ( user_sid ) ) {
/* in info3 you can only set rids for the user and the
* primary group , and the domain sid must be that of
* the sam domain .
*
* Store a completely bogus value here .
* The real SID is stored in the extra sids .
* Other code will know to look there if ( - 1 ) is found
*/
info3 - > base . rid = ( uint32_t ) ( - 1 ) ;
sid_copy ( & extra - > user_sid , user_sid ) ;
DEBUG ( 10 , ( " Unix User found. Rid marked as "
" special and sid (%s) saved as extra sid \n " ,
sid_string_dbg ( user_sid ) ) ) ;
} else {
sid_copy ( domain_sid , user_sid ) ;
sid_split_rid ( domain_sid , & info3 - > base . rid ) ;
}
if ( is_null_sid ( domain_sid ) ) {
sid_copy ( domain_sid , get_global_sam_sid ( ) ) ;
}
/* check if this is a "Unix Groups" domain group,
* if so we need special handling */
if ( sid_check_is_in_unix_groups ( group_sid ) ) {
/* in info3 you can only set rids for the user and the
* primary group , and the domain sid must be that of
* the sam domain .
*
* Store a completely bogus value here .
* The real SID is stored in the extra sids .
* Other code will know to look there if ( - 1 ) is found
*/
info3 - > base . primary_gid = ( uint32_t ) ( - 1 ) ;
sid_copy ( & extra - > pgid_sid , group_sid ) ;
DEBUG ( 10 , ( " Unix Group found. Rid marked as "
" special and sid (%s) saved as extra sid \n " ,
sid_string_dbg ( group_sid ) ) ) ;
} else {
bool ok = sid_peek_check_rid ( domain_sid , group_sid ,
& info3 - > base . primary_gid ) ;
if ( ! ok ) {
DEBUG ( 1 , ( " The primary group domain sid(%s) does not "
" match the domain sid(%s) for %s(%s) \n " ,
sid_string_dbg ( group_sid ) ,
sid_string_dbg ( domain_sid ) ,
username ,
sid_string_dbg ( user_sid ) ) ) ;
return NT_STATUS_INVALID_SID ;
}
}
return NT_STATUS_OK ;
}
2010-05-27 10:07:33 +04:00
# define RET_NOMEM(ptr) do { \
if ( ! ptr ) { \
TALLOC_FREE ( info3 ) ; \
return NT_STATUS_NO_MEMORY ; \
} } while ( 0 )
NTSTATUS samu_to_SamInfo3 ( TALLOC_CTX * mem_ctx ,
struct samu * samu ,
const char * login_server ,
2010-05-28 21:18:13 +04:00
struct netr_SamInfo3 * * _info3 ,
struct extra_auth_info * extra )
2010-05-27 10:07:33 +04:00
{
struct netr_SamInfo3 * info3 ;
const struct dom_sid * user_sid ;
const struct dom_sid * group_sid ;
struct dom_sid domain_sid ;
struct dom_sid * group_sids ;
2011-02-21 12:30:28 +03:00
uint32_t num_group_sids = 0 ;
2010-05-27 10:07:33 +04:00
const char * tmp ;
gid_t * gids ;
NTSTATUS status ;
user_sid = pdb_get_user_sid ( samu ) ;
group_sid = pdb_get_group_sid ( samu ) ;
if ( ! user_sid | | ! group_sid ) {
DEBUG ( 1 , ( " Sam account is missing sids! \n " ) ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
info3 = talloc_zero ( mem_ctx , struct netr_SamInfo3 ) ;
if ( ! info3 ) {
return NT_STATUS_NO_MEMORY ;
}
2010-05-28 21:18:13 +04:00
ZERO_STRUCT ( domain_sid ) ;
2015-01-14 00:39:21 +03:00
status = SamInfo3_handle_sids ( pdb_get_username ( samu ) ,
user_sid ,
group_sid ,
info3 ,
& domain_sid ,
extra ) ;
2010-05-28 21:18:13 +04:00
2015-01-14 00:39:21 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( info3 ) ;
return status ;
2010-05-28 21:18:13 +04:00
}
2011-10-22 00:10:43 +04:00
unix_to_nt_time ( & info3 - > base . logon_time , pdb_get_logon_time ( samu ) ) ;
unix_to_nt_time ( & info3 - > base . logoff_time , get_time_t_max ( ) ) ;
unix_to_nt_time ( & info3 - > base . kickoff_time , get_time_t_max ( ) ) ;
2010-05-27 10:07:33 +04:00
unix_to_nt_time ( & info3 - > base . last_password_change ,
pdb_get_pass_last_set_time ( samu ) ) ;
unix_to_nt_time ( & info3 - > base . allow_password_change ,
pdb_get_pass_can_change_time ( samu ) ) ;
unix_to_nt_time ( & info3 - > base . force_password_change ,
pdb_get_pass_must_change_time ( samu ) ) ;
tmp = pdb_get_username ( samu ) ;
if ( tmp ) {
info3 - > base . account_name . string = talloc_strdup ( info3 , tmp ) ;
RET_NOMEM ( info3 - > base . account_name . string ) ;
}
tmp = pdb_get_fullname ( samu ) ;
if ( tmp ) {
info3 - > base . full_name . string = talloc_strdup ( info3 , tmp ) ;
RET_NOMEM ( info3 - > base . full_name . string ) ;
}
tmp = pdb_get_logon_script ( samu ) ;
if ( tmp ) {
info3 - > base . logon_script . string = talloc_strdup ( info3 , tmp ) ;
RET_NOMEM ( info3 - > base . logon_script . string ) ;
}
2010-06-11 16:25:27 +04:00
tmp = pdb_get_profile_path ( samu ) ;
2010-05-27 10:07:33 +04:00
if ( tmp ) {
info3 - > base . profile_path . string = talloc_strdup ( info3 , tmp ) ;
RET_NOMEM ( info3 - > base . profile_path . string ) ;
}
2010-06-11 16:25:27 +04:00
tmp = pdb_get_homedir ( samu ) ;
2010-05-27 10:07:33 +04:00
if ( tmp ) {
info3 - > base . home_directory . string = talloc_strdup ( info3 , tmp ) ;
RET_NOMEM ( info3 - > base . home_directory . string ) ;
}
2010-06-11 16:25:27 +04:00
tmp = pdb_get_dir_drive ( samu ) ;
2010-05-27 10:07:33 +04:00
if ( tmp ) {
info3 - > base . home_drive . string = talloc_strdup ( info3 , tmp ) ;
RET_NOMEM ( info3 - > base . home_drive . string ) ;
}
info3 - > base . logon_count = pdb_get_logon_count ( samu ) ;
info3 - > base . bad_password_count = pdb_get_bad_password_count ( samu ) ;
2011-10-22 00:10:43 +04:00
info3 - > base . logon_domain . string = talloc_strdup ( info3 ,
2011-09-16 17:45:47 +04:00
pdb_get_domain ( samu ) ) ;
2011-10-22 00:10:43 +04:00
RET_NOMEM ( info3 - > base . logon_domain . string ) ;
2011-09-16 17:45:47 +04:00
info3 - > base . domain_sid = dom_sid_dup ( info3 , & domain_sid ) ;
RET_NOMEM ( info3 - > base . domain_sid ) ;
2010-05-27 10:07:33 +04:00
status = pdb_enum_group_memberships ( mem_ctx , samu ,
& group_sids , & gids ,
& num_group_sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " Failed to get groups from sam account. \n " ) ) ;
TALLOC_FREE ( info3 ) ;
return status ;
}
2010-06-11 17:05:36 +04:00
if ( num_group_sids ) {
status = group_sids_to_info3 ( info3 , group_sids , num_group_sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( info3 ) ;
return status ;
}
2010-05-27 10:07:33 +04:00
}
/* We don't need sids and gids after the conversion */
TALLOC_FREE ( group_sids ) ;
TALLOC_FREE ( gids ) ;
num_group_sids = 0 ;
/* FIXME: should we add other flags ? */
info3 - > base . user_flags = NETLOGON_EXTRA_SIDS ;
if ( login_server ) {
info3 - > base . logon_server . string = talloc_strdup ( info3 , login_server ) ;
RET_NOMEM ( info3 - > base . logon_server . string ) ;
}
info3 - > base . acct_flags = pdb_get_acct_ctrl ( samu ) ;
* _info3 = info3 ;
return NT_STATUS_OK ;
}
2013-12-13 22:08:34 +04:00
NTSTATUS passwd_to_SamInfo3 ( TALLOC_CTX * mem_ctx ,
const char * unix_username ,
const struct passwd * pwd ,
2015-01-14 00:45:16 +03:00
struct netr_SamInfo3 * * pinfo3 ,
struct extra_auth_info * extra )
2013-12-13 22:08:34 +04:00
{
struct netr_SamInfo3 * info3 ;
NTSTATUS status ;
TALLOC_CTX * tmp_ctx ;
const char * domain_name = NULL ;
const char * user_name = NULL ;
struct dom_sid domain_sid ;
struct dom_sid user_sid ;
struct dom_sid group_sid ;
enum lsa_SidType type ;
uint32_t num_sids = 0 ;
struct dom_sid * user_sids = NULL ;
2014-02-28 19:57:23 +04:00
bool is_null ;
2013-12-13 22:08:34 +04:00
bool ok ;
tmp_ctx = talloc_stackframe ( ) ;
ok = lookup_name_smbconf ( tmp_ctx ,
unix_username ,
LOOKUP_NAME_ALL ,
& domain_name ,
& user_name ,
& user_sid ,
& type ) ;
if ( ! ok ) {
status = NT_STATUS_NO_SUCH_USER ;
goto done ;
}
if ( type ! = SID_NAME_USER ) {
status = NT_STATUS_NO_SUCH_USER ;
goto done ;
}
ok = winbind_lookup_usersids ( tmp_ctx ,
& user_sid ,
& num_sids ,
& user_sids ) ;
/* Check if winbind is running */
if ( ok ) {
/*
* Winbind is running and the first element of the user_sids
* is the primary group .
*/
if ( num_sids > 0 ) {
group_sid = user_sids [ 0 ] ;
}
} else {
/*
2013-12-13 22:19:02 +04:00
* Winbind is not running , try to create the group_sid from the
* passwd group id .
*/
/*
* This can lead to a primary group of S - 1 - 22 - 2 - XX which
* will be rejected by other Samba code .
2013-12-13 22:08:34 +04:00
*/
gid_to_sid ( & group_sid , pwd - > pw_gid ) ;
2015-11-18 00:05:10 +03:00
}
2013-12-13 22:19:02 +04:00
2015-11-18 00:05:10 +03:00
/*
* If we are a unix group , or a wellknown / builtin alias ,
* set the group_sid to the
* ' Domain Users ' RID of 513 which will always resolve to a
* name .
*/
if ( sid_check_is_in_unix_groups ( & group_sid ) | |
sid_check_is_in_builtin ( & group_sid ) | |
sid_check_is_in_wellknown_domain ( & group_sid ) ) {
if ( sid_check_is_in_unix_users ( & user_sid ) ) {
2013-12-13 22:19:02 +04:00
sid_compose ( & group_sid ,
get_global_sam_sid ( ) ,
DOMAIN_RID_USERS ) ;
2015-11-18 00:05:10 +03:00
} else {
sid_copy ( & domain_sid , & user_sid ) ;
sid_split_rid ( & domain_sid , NULL ) ;
sid_compose ( & group_sid ,
& domain_sid ,
DOMAIN_RID_USERS ) ;
2013-12-13 22:19:02 +04:00
}
2013-12-13 22:08:34 +04:00
}
/* Make sure we have a valid group sid */
2014-02-28 19:57:23 +04:00
is_null = is_null_sid ( & group_sid ) ;
if ( is_null ) {
2013-12-13 22:08:34 +04:00
status = NT_STATUS_NO_SUCH_USER ;
goto done ;
}
/* Construct a netr_SamInfo3 from the information we have */
info3 = talloc_zero ( tmp_ctx , struct netr_SamInfo3 ) ;
if ( ! info3 ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
info3 - > base . account_name . string = talloc_strdup ( info3 , unix_username ) ;
if ( info3 - > base . account_name . string = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
ZERO_STRUCT ( domain_sid ) ;
2015-01-14 00:45:16 +03:00
status = SamInfo3_handle_sids ( unix_username ,
& user_sid ,
& group_sid ,
info3 ,
& domain_sid ,
extra ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2013-12-13 22:08:34 +04:00
info3 - > base . domain_sid = dom_sid_dup ( info3 , & domain_sid ) ;
2015-01-14 00:49:36 +03:00
if ( info3 - > base . domain_sid = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2013-12-13 22:08:34 +04:00
ok = sid_peek_check_rid ( & domain_sid , & group_sid ,
& info3 - > base . primary_gid ) ;
if ( ! ok ) {
DEBUG ( 1 , ( " The primary group domain sid(%s) does not "
" match the domain sid(%s) for %s(%s) \n " ,
sid_string_dbg ( & group_sid ) ,
sid_string_dbg ( & domain_sid ) ,
unix_username ,
sid_string_dbg ( & user_sid ) ) ) ;
status = NT_STATUS_INVALID_SID ;
goto done ;
}
info3 - > base . acct_flags = ACB_NORMAL ;
if ( num_sids ) {
status = group_sids_to_info3 ( info3 , user_sids , num_sids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
}
* pinfo3 = talloc_steal ( mem_ctx , info3 ) ;
status = NT_STATUS_OK ;
done :
talloc_free ( tmp_ctx ) ;
return status ;
}