2006-04-27 19:50:13 +00:00
/*
Unix SMB / CIFS implementation .
Password and authentication handling
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2001 - 2004
Copyright ( C ) Gerald Carter 2003
Copyright ( C ) Stefan Metzmacher 2005
2009-07-16 18:28:58 -07:00
Copyright ( C ) Matthias Dieter Wallnöfer 2009
2006-04-27 19:50:13 +00: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 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2006-04-27 19:50:13 +00:00
( 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-04-27 19:50:13 +00:00
*/
# include "includes.h"
# include "system/time.h"
# include "auth/auth.h"
2007-11-16 20:12:00 +01:00
# include <ldb.h>
2006-04-27 19:50:13 +00:00
# include "dsdb/samdb/samdb.h"
# include "libcli/security/security.h"
2008-10-20 18:59:51 +02:00
# include "auth/auth_sam.h"
2010-02-16 15:49:29 +11:00
# include "dsdb/common/util.h"
2006-04-27 19:50:13 +00:00
2009-07-16 17:37:36 +10:00
# define KRBTGT_ATTRS \
/* required for the krb5 kdc */ \
" objectClass " , \
" sAMAccountName " , \
" userPrincipalName " , \
" servicePrincipalName " , \
" msDS-KeyVersionNumber " , \
2010-09-28 19:07:43 -07:00
" msDS-SecondaryKrbTgtNumber " , \
2010-06-24 10:03:29 +10:00
" msDS-SupportedEncryptionTypes " , \
2009-07-16 17:37:36 +10:00
" supplementalCredentials " , \
\
/* passwords */ \
" dBCSPwd " , \
" unicodePwd " , \
\
" userAccountControl " , \
" objectSid " , \
\
" pwdLastSet " , \
2010-09-28 19:07:43 -07:00
" accountExpires "
2009-07-16 17:37:36 +10:00
const char * krbtgt_attrs [ ] = {
2010-09-28 19:07:43 -07:00
KRBTGT_ATTRS , NULL
2009-07-16 17:37:36 +10:00
} ;
2006-04-27 19:50:13 +00:00
2009-07-16 17:37:36 +10:00
const char * server_attrs [ ] = {
2010-09-28 19:07:43 -07:00
KRBTGT_ATTRS , NULL
2009-07-16 17:37:36 +10:00
} ;
2006-04-27 19:50:13 +00:00
2009-07-16 17:37:36 +10:00
const char * user_attrs [ ] = {
KRBTGT_ATTRS ,
2006-04-27 19:50:13 +00:00
2007-07-27 06:31:12 +00:00
" logonHours " ,
2006-04-27 19:50:13 +00:00
/* check 'allowed workstations' */
" userWorkstations " ,
/* required for server_info, not access control: */
" displayName " ,
" scriptPath " ,
" profilePath " ,
" homeDirectory " ,
" homeDrive " ,
" lastLogon " ,
" lastLogoff " ,
" accountExpires " ,
" badPwdCount " ,
" logonCount " ,
" primaryGroupID " ,
2009-06-04 14:07:35 +10:00
" memberOf " ,
2006-04-27 19:50:13 +00:00
NULL ,
} ;
2007-07-27 06:31:12 +00:00
/****************************************************************************
Check if a user is allowed to logon at this time . Note this is the
servers local time , as logon hours are just specified as a weekly
bitmask .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-06 22:16:19 +00:00
static bool logon_hours_ok ( struct ldb_message * msg , const char * name_for_logs )
2007-07-27 06:31:12 +00:00
{
/* In logon hours first bit is Sunday from 12AM to 1AM */
const struct ldb_val * hours ;
struct tm * utctime ;
time_t lasttime ;
const char * asct ;
uint8_t bitmask , bitpos ;
hours = ldb_msg_find_ldb_val ( msg , " logonHours " ) ;
if ( ! hours ) {
DEBUG ( 5 , ( " logon_hours_ok: No hours restrictions for user %s \n " , name_for_logs ) ) ;
2007-10-06 22:16:19 +00:00
return true ;
2007-07-27 06:31:12 +00:00
}
if ( hours - > length ! = 168 / 8 ) {
DEBUG ( 5 , ( " logon_hours_ok: malformed logon hours restrictions for user %s \n " , name_for_logs ) ) ;
2007-10-06 22:16:19 +00:00
return true ;
2007-07-27 06:31:12 +00:00
}
lasttime = time ( NULL ) ;
utctime = gmtime ( & lasttime ) ;
if ( ! utctime ) {
DEBUG ( 1 , ( " logon_hours_ok: failed to get gmtime. Failing logon for user %s \n " ,
name_for_logs ) ) ;
2007-10-06 22:16:19 +00:00
return false ;
2007-07-27 06:31:12 +00:00
}
/* find the corresponding byte and bit */
bitpos = ( utctime - > tm_wday * 24 + utctime - > tm_hour ) % 168 ;
bitmask = 1 < < ( bitpos % 8 ) ;
if ( ! ( hours - > data [ bitpos / 8 ] & bitmask ) ) {
struct tm * t = localtime ( & lasttime ) ;
if ( ! t ) {
asct = " INVALID TIME " ;
} else {
asct = asctime ( t ) ;
if ( ! asct ) {
asct = " INVALID TIME " ;
}
}
DEBUG ( 1 , ( " logon_hours_ok: Account for user %s not allowed to "
" logon at this time (%s). \n " ,
name_for_logs , asct ) ) ;
2007-10-06 22:16:19 +00:00
return false ;
2007-07-27 06:31:12 +00:00
}
asct = asctime ( utctime ) ;
DEBUG ( 5 , ( " logon_hours_ok: user %s allowed to logon at this time (%s) \n " ,
name_for_logs , asct ? asct : " UNKNOWN TIME " ) ) ;
2007-10-06 22:16:19 +00:00
return true ;
2007-07-27 06:31:12 +00:00
}
2006-04-27 19:50:13 +00:00
/****************************************************************************
2010-02-21 17:33:28 +11:00
Do a specific test for a SAM_ACCOUNT being valid for this connection
2006-04-27 19:50:13 +00:00
( ie not disabled , expired and the like ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
_PUBLIC_ NTSTATUS authsam_account_ok ( TALLOC_CTX * mem_ctx ,
2009-05-26 12:31:39 +10:00
struct ldb_context * sam_ctx ,
uint32_t logon_parameters ,
struct ldb_dn * domain_dn ,
struct ldb_message * msg ,
const char * logon_workstation ,
const char * name_for_logs ,
2009-06-18 11:08:46 +10:00
bool allow_domain_trust ,
bool password_change )
2006-04-27 19:50:13 +00:00
{
uint16_t acct_flags ;
const char * workstation_list ;
NTTIME acct_expiry ;
NTTIME must_change_time ;
NTTIME now ;
DEBUG ( 4 , ( " authsam_account_ok: Checking SMB password for user %s \n " , name_for_logs ) ) ;
2008-02-28 08:50:00 +11:00
acct_flags = samdb_result_acct_flags ( sam_ctx , mem_ctx , msg , domain_dn ) ;
2006-04-27 19:50:13 +00:00
2008-03-25 15:25:13 +11:00
acct_expiry = samdb_result_account_expires ( msg ) ;
2008-02-29 08:47:42 +11:00
/* Check for when we must change this password, taking the
* userAccountControl flags into account */
2006-04-27 19:50:13 +00:00
must_change_time = samdb_result_force_password_change ( sam_ctx , mem_ctx ,
domain_dn , msg ) ;
2010-10-14 09:41:42 +02:00
workstation_list = ldb_msg_find_attr_as_string ( msg , " userWorkstations " , NULL ) ;
2006-04-27 19:50:13 +00:00
/* Quit if the account was disabled. */
if ( acct_flags & ACB_DISABLED ) {
2010-08-31 12:28:55 +10:00
DEBUG ( 2 , ( " authsam_account_ok: Account for user '%s' was disabled. \n " , name_for_logs ) ) ;
2006-04-27 19:50:13 +00:00
return NT_STATUS_ACCOUNT_DISABLED ;
}
/* Quit if the account was locked out. */
if ( acct_flags & ACB_AUTOLOCK ) {
2010-08-31 12:28:55 +10:00
DEBUG ( 2 , ( " authsam_account_ok: Account for user %s was locked out. \n " , name_for_logs ) ) ;
2006-04-27 19:50:13 +00:00
return NT_STATUS_ACCOUNT_LOCKED_OUT ;
}
/* Test account expire time */
unix_to_nt_time ( & now , time ( NULL ) ) ;
if ( now > acct_expiry ) {
2010-08-31 12:28:55 +10:00
DEBUG ( 2 , ( " authsam_account_ok: Account for user '%s' has expired. \n " , name_for_logs ) ) ;
2006-04-27 19:50:13 +00:00
DEBUG ( 3 , ( " authsam_account_ok: Account expired at '%s'. \n " ,
nt_time_string ( mem_ctx , acct_expiry ) ) ) ;
return NT_STATUS_ACCOUNT_EXPIRED ;
}
2009-06-18 11:08:46 +10:00
/* check for immediate expiry "must change at next logon" (but not if this is a password change request) */
if ( ( must_change_time = = 0 ) & & ! password_change ) {
2010-08-31 12:28:55 +10:00
DEBUG ( 2 , ( " sam_account_ok: Account for user '%s' password must change!. \n " ,
2008-02-28 08:50:00 +11:00
name_for_logs ) ) ;
return NT_STATUS_PASSWORD_MUST_CHANGE ;
}
2006-04-27 19:50:13 +00:00
2009-06-18 11:08:46 +10:00
/* check for expired password (but not if this is a password change request) */
if ( ( must_change_time < now ) & & ! password_change ) {
2010-08-31 12:28:55 +10:00
DEBUG ( 2 , ( " sam_account_ok: Account for user '%s' password expired!. \n " ,
2008-02-28 08:50:00 +11:00
name_for_logs ) ) ;
2010-08-31 12:28:55 +10:00
DEBUG ( 2 , ( " sam_account_ok: Password expired at '%s' unix time. \n " ,
2008-02-28 08:50:00 +11:00
nt_time_string ( mem_ctx , must_change_time ) ) ) ;
return NT_STATUS_PASSWORD_EXPIRED ;
2006-04-27 19:50:13 +00:00
}
/* Test workstation. Workstation list is comma separated. */
if ( logon_workstation & & workstation_list & & * workstation_list ) {
2007-10-06 22:16:19 +00:00
bool invalid_ws = true ;
2006-04-27 19:50:13 +00:00
int i ;
2008-10-12 00:56:56 +02:00
const char * * workstations = ( const char * * ) str_list_make ( mem_ctx , workstation_list , " , " ) ;
2006-04-27 19:50:13 +00:00
for ( i = 0 ; workstations & & workstations [ i ] ; i + + ) {
DEBUG ( 10 , ( " sam_account_ok: checking for workstation match '%s' and '%s' \n " ,
workstations [ i ] , logon_workstation ) ) ;
2007-07-30 08:58:39 +00:00
if ( strequal ( workstations [ i ] , logon_workstation ) ) {
2007-10-06 22:16:19 +00:00
invalid_ws = false ;
2006-04-27 19:50:13 +00:00
break ;
}
}
talloc_free ( workstations ) ;
if ( invalid_ws ) {
return NT_STATUS_INVALID_WORKSTATION ;
}
}
2007-07-27 06:31:12 +00:00
if ( ! logon_hours_ok ( msg , name_for_logs ) ) {
return NT_STATUS_INVALID_LOGON_HOURS ;
}
2008-12-04 15:09:21 +01:00
if ( ! allow_domain_trust ) {
if ( acct_flags & ACB_DOMTRUST ) {
DEBUG ( 2 , ( " sam_account_ok: Domain trust account %s denied by server \n " , name_for_logs ) ) ;
return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ;
}
2006-04-27 19:50:13 +00:00
}
if ( ! ( logon_parameters & MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT ) ) {
if ( acct_flags & ACB_SVRTRUST ) {
DEBUG ( 2 , ( " sam_account_ok: Server trust account %s denied by server \n " , name_for_logs ) ) ;
return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ;
}
}
if ( ! ( logon_parameters & MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT ) ) {
2009-09-17 15:15:58 -07:00
/* TODO: this fails with current solaris client. We
need to work with Gordon to work out why */
2006-04-27 19:50:13 +00:00
if ( acct_flags & ACB_WSTRUST ) {
DEBUG ( 4 , ( " sam_account_ok: Wksta trust account %s denied by server \n " , name_for_logs ) ) ;
return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ;
}
}
return NT_STATUS_OK ;
}
2009-07-16 18:28:58 -07:00
/* This function tests if a SID structure "sids" contains the SID "sid" */
2010-03-04 13:46:34 +01:00
static bool sids_contains_sid ( const struct dom_sid * * sids ,
const unsigned int num_sids ,
const struct dom_sid * sid )
2009-07-16 18:28:58 -07:00
{
2010-03-04 13:46:34 +01:00
unsigned int i ;
2009-07-16 18:28:58 -07:00
for ( i = 0 ; i < num_sids ; i + + ) {
if ( dom_sid_equal ( sids [ i ] , sid ) )
return true ;
}
return false ;
}
2010-04-13 12:00:06 +10:00
2009-07-16 18:28:58 -07:00
/*
2010-06-28 20:25:47 +02:00
* This function generates the transitive closure of a given SAM object " dn_val "
* ( it basically expands nested memberships ) .
* If the object isn ' t located in the " res_sids " structure yet and the
* " only_childs " flag is false , we add it to " res_sids " .
2009-08-04 17:09:29 +02:00
* Then we ' ve always to consider the " memberOf " attributes . We invoke the
2010-06-28 20:25:47 +02:00
* function recursively on each of it with the " only_childs " flag set to
2009-08-04 17:09:29 +02:00
* " false " .
2010-06-28 20:25:47 +02:00
* The " only_childs " flag is particularly useful if you have a user object and
* want to include all it ' s groups ( referenced with " memberOf " ) but not itself
* or considering if that object matches the filter .
2009-07-16 18:28:58 -07:00
*
2009-08-04 17:09:29 +02:00
* At the beginning " res_sids " should reference to a NULL pointer .
2009-07-16 18:28:58 -07:00
*/
2010-04-13 22:11:26 +10:00
NTSTATUS authsam_expand_nested_groups ( struct ldb_context * sam_ctx ,
struct ldb_val * dn_val , const bool only_childs , const char * filter ,
TALLOC_CTX * res_sids_ctx , struct dom_sid * * * res_sids ,
unsigned int * num_res_sids )
2009-07-16 18:28:58 -07:00
{
const char * const attrs [ ] = { " memberOf " , NULL } ;
2009-11-07 21:20:12 +01:00
unsigned int i ;
int ret ;
2009-07-16 18:28:58 -07:00
bool already_there ;
2010-04-13 22:11:26 +10:00
struct ldb_dn * dn ;
2010-05-21 15:02:22 +10:00
struct dom_sid sid ;
2009-07-16 18:28:58 -07:00
TALLOC_CTX * tmp_ctx ;
2010-06-29 14:52:43 +02:00
struct ldb_result * res ;
2009-07-16 18:28:58 -07:00
NTSTATUS status ;
2010-04-13 22:11:26 +10:00
const struct ldb_message_element * el ;
2009-07-16 18:28:58 -07:00
if ( * res_sids = = NULL ) {
* num_res_sids = 0 ;
}
2010-04-13 22:11:26 +10:00
tmp_ctx = talloc_new ( res_sids_ctx ) ;
dn = ldb_dn_from_ldb_val ( tmp_ctx , sam_ctx , dn_val ) ;
if ( dn = = NULL ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2009-07-16 18:28:58 -07:00
}
2010-06-28 10:45:04 -05:00
2010-05-21 15:02:22 +10:00
status = dsdb_get_extended_dn_sid ( dn , & sid , " SID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-06-29 14:52:43 +02:00
DEBUG ( 0 , ( __location__ " : when parsing DN %s we failed to find our SID component, so we cannot calculate the group token: %s \n " ,
2010-05-21 15:02:22 +10:00
ldb_dn_get_extended_linearized ( tmp_ctx , dn , 1 ) ,
nt_errstr ( status ) ) ) ;
2010-04-13 22:11:26 +10:00
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2010-08-14 19:55:30 +10:00
if ( ! sam_ctx ) {
DEBUG ( 0 , ( " No SAM available, cannot determine local groups \n " ) ) ;
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
2010-04-13 22:11:26 +10:00
if ( only_childs ) {
2010-06-29 14:52:43 +02:00
ret = dsdb_search_dn ( sam_ctx , tmp_ctx , & res , dn , attrs ,
DSDB_SEARCH_SHOW_EXTENDED_DN ) ;
2010-04-13 22:11:26 +10:00
} else {
2010-05-20 16:51:59 +10:00
/* This is an O(n^2) linear search */
already_there = sids_contains_sid ( ( const struct dom_sid * * ) * res_sids ,
2010-05-21 15:02:22 +10:00
* num_res_sids , & sid ) ;
2010-05-20 16:51:59 +10:00
if ( already_there ) {
return NT_STATUS_OK ;
}
2010-06-28 19:57:12 +02:00
ret = dsdb_search ( sam_ctx , tmp_ctx , & res , dn , LDB_SCOPE_BASE ,
attrs , DSDB_SEARCH_SHOW_EXTENDED_DN , " %s " ,
filter ) ;
2009-08-04 17:09:29 +02:00
}
2009-07-16 18:28:58 -07:00
2010-04-13 22:11:26 +10:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2009-07-16 18:28:58 -07:00
2010-04-13 22:11:26 +10:00
if ( ret ! = LDB_SUCCESS ) {
2009-07-16 18:28:58 -07:00
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2010-04-13 22:11:26 +10:00
/* We may get back 0 results, if the SID didn't match the filter - such as it wasn't a domain group, for example */
if ( res - > count ! = 1 ) {
2009-07-31 10:38:04 +02:00
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
2010-04-13 22:11:26 +10:00
/* We only apply this test once we know the SID matches the filter */
if ( ! only_childs ) {
* res_sids = talloc_realloc ( res_sids_ctx , * res_sids ,
struct dom_sid * , * num_res_sids + 1 ) ;
2010-05-21 16:01:34 +10:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( * res_sids , tmp_ctx ) ;
( * res_sids ) [ * num_res_sids ] = dom_sid_dup ( * res_sids , & sid ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( ( * res_sids ) [ * num_res_sids ] , tmp_ctx ) ;
2010-04-13 22:11:26 +10:00
+ + ( * num_res_sids ) ;
}
2009-07-16 18:28:58 -07:00
2010-04-13 22:11:26 +10:00
el = ldb_msg_find_element ( res - > msgs [ 0 ] , " memberOf " ) ;
for ( i = 0 ; el & & i < el - > num_values ; i + + ) {
status = authsam_expand_nested_groups ( sam_ctx , & el - > values [ i ] ,
false , filter , res_sids_ctx , res_sids , num_res_sids ) ;
2009-07-16 18:28:58 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( res ) ;
talloc_free ( tmp_ctx ) ;
return status ;
}
}
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}
_PUBLIC_ NTSTATUS authsam_make_server_info ( TALLOC_CTX * mem_ctx ,
struct ldb_context * sam_ctx ,
2007-12-03 15:53:17 +01:00
const char * netbios_name ,
2009-05-26 12:31:39 +10:00
const char * domain_name ,
struct ldb_dn * domain_dn ,
2007-12-03 15:53:17 +01:00
struct ldb_message * msg ,
2009-08-17 23:39:41 +02:00
DATA_BLOB user_sess_key ,
DATA_BLOB lm_sess_key ,
2010-03-04 13:48:17 +01:00
struct auth_serversupplied_info * * _server_info )
2006-04-27 19:50:13 +00:00
{
2009-07-16 18:28:58 -07:00
NTSTATUS status ;
2006-04-27 19:50:13 +00:00
struct auth_serversupplied_info * server_info ;
2010-04-13 22:11:26 +10:00
const char * str , * filter ;
2009-08-17 23:39:41 +02:00
/* SIDs for the account and his primary group */
2006-04-27 19:50:13 +00:00
struct dom_sid * account_sid ;
struct dom_sid * primary_group_sid ;
2010-04-13 22:11:26 +10:00
const char * primary_group_string ;
const char * primary_group_dn ;
DATA_BLOB primary_group_blob ;
2009-08-17 23:39:41 +02:00
/* SID structures for the expanded group memberships */
2010-04-13 22:11:26 +10:00
struct dom_sid * * groupSIDs = NULL ;
unsigned int num_groupSIDs = 0 , i ;
struct dom_sid * domain_sid ;
TALLOC_CTX * tmp_ctx ;
struct ldb_message_element * el ;
2006-04-27 19:50:13 +00:00
2009-08-17 23:39:41 +02:00
server_info = talloc ( mem_ctx , struct auth_serversupplied_info ) ;
NT_STATUS_HAVE_NO_MEMORY ( server_info ) ;
2006-04-27 19:50:13 +00:00
2010-04-13 22:11:26 +10:00
tmp_ctx = talloc_new ( server_info ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info , server_info ) ;
2006-04-27 19:50:13 +00:00
account_sid = samdb_result_dom_sid ( server_info , msg , " objectSid " ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( account_sid , server_info ) ;
2006-04-27 19:50:13 +00:00
2010-04-13 22:11:26 +10:00
status = dom_sid_split_rid ( tmp_ctx , account_sid , & domain_sid , NULL ) ;
2009-07-16 18:28:58 -07:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-08-17 23:39:41 +02:00
talloc_free ( server_info ) ;
2009-07-16 18:28:58 -07:00
return status ;
}
2010-04-13 22:11:26 +10:00
primary_group_sid = dom_sid_add_rid ( server_info ,
domain_sid ,
2010-10-14 09:41:42 +02:00
ldb_msg_find_attr_as_uint ( msg , " primaryGroupID " , ~ 0 ) ) ;
2010-04-13 22:11:26 +10:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( primary_group_sid , server_info ) ;
/* Filter out builtin groups from this token. We will search
* for builtin groups later , and not include them in the PAC
* on SamLogon validation info */
filter = talloc_asprintf ( tmp_ctx , " (&(objectClass=group)(!(groupType:1.2.840.113556.1.4.803:=%u))(groupType:1.2.840.113556.1.4.803:=%u)) " , GROUP_TYPE_BUILTIN_LOCAL_GROUP , GROUP_TYPE_SECURITY_ENABLED ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( filter , server_info ) ;
primary_group_string = dom_sid_string ( tmp_ctx , primary_group_sid ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( primary_group_string , server_info ) ;
primary_group_dn = talloc_asprintf ( tmp_ctx , " <SID=%s> " , primary_group_string ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( primary_group_dn , server_info ) ;
primary_group_blob = data_blob_string_const ( primary_group_dn ) ;
/* Expands the primary group - this function takes in
* memberOf - like values , so we fake one up with the
* < SID = S - . . . > format of DN and then let it expand
* them , as long as they meet the filter - so only
* domain groups , not builtin groups
*
* The primary group is still treated specially , so we set the
* ' only childs ' flag to true
*/
status = authsam_expand_nested_groups ( sam_ctx , & primary_group_blob , true , filter ,
server_info , & groupSIDs , & num_groupSIDs ) ;
2009-08-17 23:39:41 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( server_info ) ;
return status ;
}
2006-04-27 19:50:13 +00:00
2010-04-13 22:11:26 +10:00
/* Expands the additional groups */
el = ldb_msg_find_element ( msg , " memberOf " ) ;
for ( i = 0 ; el & & i < el - > num_values ; i + + ) {
/* This function takes in memberOf values and expands
* them , as long as they meet the filter - so only
* domain groups , not builtin groups */
status = authsam_expand_nested_groups ( sam_ctx , & el - > values [ i ] , false , filter ,
server_info , & groupSIDs , & num_groupSIDs ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( server_info ) ;
return status ;
2006-04-27 19:50:13 +00:00
}
2010-04-13 22:11:26 +10:00
}
2006-04-27 19:50:13 +00:00
server_info - > account_sid = account_sid ;
server_info - > primary_group_sid = primary_group_sid ;
server_info - > domain_groups = groupSIDs ;
2009-08-17 23:39:41 +02:00
server_info - > n_domain_groups = num_groupSIDs ;
2006-04-27 19:50:13 +00:00
2009-08-17 23:39:41 +02:00
server_info - > account_name = talloc_steal ( server_info ,
2010-10-14 09:41:42 +02:00
ldb_msg_find_attr_as_string ( msg , " sAMAccountName " , NULL ) ) ;
2006-04-27 19:50:13 +00:00
2009-05-26 12:31:39 +10:00
server_info - > domain_name = talloc_strdup ( server_info , domain_name ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > domain_name ,
server_info ) ;
2006-04-27 19:50:13 +00:00
2010-10-14 09:41:42 +02:00
str = ldb_msg_find_attr_as_string ( msg , " displayName " , " " ) ;
2006-04-27 19:50:13 +00:00
server_info - > full_name = talloc_strdup ( server_info , str ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > full_name , server_info ) ;
2006-04-27 19:50:13 +00:00
2010-10-14 09:41:42 +02:00
str = ldb_msg_find_attr_as_string ( msg , " scriptPath " , " " ) ;
2006-04-27 19:50:13 +00:00
server_info - > logon_script = talloc_strdup ( server_info , str ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > logon_script ,
server_info ) ;
2006-04-27 19:50:13 +00:00
2010-10-14 09:41:42 +02:00
str = ldb_msg_find_attr_as_string ( msg , " profilePath " , " " ) ;
2006-04-27 19:50:13 +00:00
server_info - > profile_path = talloc_strdup ( server_info , str ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > profile_path ,
server_info ) ;
2006-04-27 19:50:13 +00:00
2010-10-14 09:41:42 +02:00
str = ldb_msg_find_attr_as_string ( msg , " homeDirectory " , " " ) ;
2006-04-27 19:50:13 +00:00
server_info - > home_directory = talloc_strdup ( server_info , str ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > home_directory ,
server_info ) ;
2006-04-27 19:50:13 +00:00
2010-10-14 09:41:42 +02:00
str = ldb_msg_find_attr_as_string ( msg , " homeDrive " , " " ) ;
2006-04-27 19:50:13 +00:00
server_info - > home_drive = talloc_strdup ( server_info , str ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > home_drive , server_info ) ;
2006-04-27 19:50:13 +00:00
2007-12-03 15:53:17 +01:00
server_info - > logon_server = talloc_strdup ( server_info , netbios_name ) ;
2009-08-17 23:39:41 +02:00
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > logon_server ,
server_info ) ;
2006-04-27 19:50:13 +00:00
server_info - > last_logon = samdb_result_nttime ( msg , " lastLogon " , 0 ) ;
2009-08-01 14:02:58 +04:00
server_info - > last_logoff = samdb_result_last_logoff ( msg ) ;
2008-03-25 15:25:13 +11:00
server_info - > acct_expiry = samdb_result_account_expires ( msg ) ;
2009-08-17 23:39:41 +02:00
server_info - > last_password_change = samdb_result_nttime ( msg ,
" pwdLastSet " , 0 ) ;
2006-04-27 19:50:13 +00:00
server_info - > allow_password_change
= samdb_result_allow_password_change ( sam_ctx , mem_ctx ,
2009-08-17 23:39:41 +02:00
domain_dn , msg , " pwdLastSet " ) ;
2006-04-27 19:50:13 +00:00
server_info - > force_password_change
2009-08-17 23:39:41 +02:00
= samdb_result_force_password_change ( sam_ctx , mem_ctx ,
domain_dn , msg ) ;
2010-10-14 09:41:42 +02:00
server_info - > logon_count = ldb_msg_find_attr_as_uint ( msg , " logonCount " , 0 ) ;
server_info - > bad_password_count = ldb_msg_find_attr_as_uint ( msg , " badPwdCount " ,
2009-08-17 23:39:41 +02:00
0 ) ;
2006-04-27 19:50:13 +00:00
2008-02-28 08:50:00 +11:00
server_info - > acct_flags = samdb_result_acct_flags ( sam_ctx , mem_ctx ,
msg , domain_dn ) ;
2006-04-27 19:50:13 +00:00
2010-01-05 20:11:29 +01:00
server_info - > user_session_key = data_blob_talloc ( server_info ,
user_sess_key . data ,
user_sess_key . length ) ;
if ( user_sess_key . data ) {
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > user_session_key . data ,
server_info ) ;
}
server_info - > lm_session_key = data_blob_talloc ( server_info ,
lm_sess_key . data ,
lm_sess_key . length ) ;
if ( lm_sess_key . data ) {
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > lm_session_key . data ,
server_info ) ;
}
2006-04-27 19:50:13 +00:00
2010-09-25 19:14:42 -07:00
if ( server_info - > acct_flags & ACB_SVRTRUST ) {
/* the SID_NT_ENTERPRISE_DCS SID gets added into the
PAC */
server_info - > domain_groups = talloc_realloc ( server_info ,
server_info - > domain_groups ,
struct dom_sid * ,
server_info - > n_domain_groups + 1 ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > domain_groups , server_info ) ;
server_info - > domain_groups [ server_info - > n_domain_groups ] =
dom_sid_parse_talloc ( server_info - > domain_groups ,
SID_NT_ENTERPRISE_DCS ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > domain_groups [ server_info - > n_domain_groups ] ,
server_info ) ;
server_info - > n_domain_groups + + ;
}
2010-09-28 23:19:26 -07:00
if ( ( server_info - > acct_flags & ( ACB_PARTIAL_SECRETS_ACCOUNT | ACB_WSTRUST ) ) = =
( ACB_PARTIAL_SECRETS_ACCOUNT | ACB_WSTRUST ) ) {
/* the DOMAIN_RID_ENTERPRISE_READONLY_DCS PAC */
server_info - > domain_groups = talloc_realloc ( server_info ,
server_info - > domain_groups ,
struct dom_sid * ,
server_info - > n_domain_groups + 1 ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > domain_groups , server_info ) ;
server_info - > domain_groups [ server_info - > n_domain_groups ] =
dom_sid_add_rid ( server_info - > domain_groups , domain_sid ,
DOMAIN_RID_ENTERPRISE_READONLY_DCS ) ;
NT_STATUS_HAVE_NO_MEMORY_AND_FREE ( server_info - > domain_groups [ server_info - > n_domain_groups ] ,
server_info ) ;
server_info - > n_domain_groups + + ;
}
2007-10-06 22:16:19 +00:00
server_info - > authenticated = true ;
2006-04-27 19:50:13 +00:00
2010-04-13 22:11:26 +10:00
talloc_free ( tmp_ctx ) ;
2009-08-17 23:39:41 +02:00
* _server_info = server_info ;
2006-04-27 19:50:13 +00:00
return NT_STATUS_OK ;
}
2008-04-02 04:53:27 +02:00
NTSTATUS sam_get_results_principal ( struct ldb_context * sam_ctx ,
2006-04-27 19:50:13 +00:00
TALLOC_CTX * mem_ctx , const char * principal ,
2009-07-28 14:05:19 +10:00
const char * * attrs ,
2009-05-26 12:31:39 +10:00
struct ldb_dn * * domain_dn ,
2009-06-04 14:07:35 +10:00
struct ldb_message * * msg )
2006-04-27 19:50:13 +00:00
{
2009-05-26 12:31:39 +10:00
struct ldb_dn * user_dn ;
2006-04-27 19:50:13 +00:00
NTSTATUS nt_status ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
int ret ;
if ( ! tmp_ctx ) {
return NT_STATUS_NO_MEMORY ;
}
2009-07-28 14:05:19 +10:00
nt_status = crack_user_principal_name ( sam_ctx , tmp_ctx , principal ,
& user_dn , domain_dn ) ;
2006-04-27 19:50:13 +00:00
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_free ( tmp_ctx ) ;
return nt_status ;
}
/* pull the user attributes */
2010-02-16 15:49:29 +11:00
ret = dsdb_search_one ( sam_ctx , tmp_ctx , msg , user_dn ,
LDB_SCOPE_BASE , attrs , DSDB_SEARCH_SHOW_EXTENDED_DN , " (objectClass=*) " ) ;
2009-06-04 14:07:35 +10:00
if ( ret ! = LDB_SUCCESS ) {
2006-04-27 19:50:13 +00:00
talloc_free ( tmp_ctx ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2009-06-04 14:07:35 +10:00
talloc_steal ( mem_ctx , * msg ) ;
2009-05-26 12:31:39 +10:00
talloc_steal ( mem_ctx , * domain_dn ) ;
2006-04-27 19:50:13 +00:00
talloc_free ( tmp_ctx ) ;
return NT_STATUS_OK ;
}