0001-01-01 02:30:17 +02:30
/*
0001-01-01 02:30:17 +02:30
* Unix SMB / CIFS implementation .
0001-01-01 02:30:17 +02:30
* account policy storage
* Copyright ( C ) Jean Fran <EFBFBD> ois Micouleau 1998 - 2001.
0001-01-01 02:30:17 +02:30
* Copyright ( C ) Andrew Bartlett 2002
2005-09-30 21:13:37 +04:00
* Copyright ( C ) Guenther Deschner 2004 - 2005
0001-01-01 02:30:17 +02:30
*
* 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-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
0001-01-01 02:30:17 +02:30
* ( 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 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
0001-01-01 02:30:17 +02:30
*/
# include "includes.h"
2008-03-28 14:09:56 +03:00
static struct db_context * db ;
0001-01-01 02:30:17 +02:30
2005-09-30 21:13:37 +04:00
/* cache all entries for 60 seconds for to save ldap-queries (cache is updated
* after this period if admins do not use pdbedit or usermanager but manipulate
* ldap directly ) - gd */
2005-01-10 21:29:52 +03:00
2005-09-30 21:13:37 +04:00
# define DATABASE_VERSION 3
# define AP_TTL 60
2005-02-12 03:51:31 +03:00
2005-09-30 21:13:37 +04:00
struct ap_table {
int field ;
const char * string ;
uint32 default_val ;
const char * description ;
const char * ldap_attr ;
} ;
2005-02-12 03:51:31 +03:00
2005-09-30 21:13:37 +04:00
static const struct ap_table account_policy_names [ ] = {
{ AP_MIN_PASSWORD_LEN , " min password length " , MINPASSWDLENGTH ,
" Minimal password length (default: 5) " ,
" sambaMinPwdLength " } ,
2005-02-12 03:51:31 +03:00
2005-09-30 21:13:37 +04:00
{ AP_PASSWORD_HISTORY , " password history " , 0 ,
" Length of Password History Entries (default: 0 => off) " ,
" sambaPwdHistoryLength " } ,
2005-02-12 03:51:31 +03:00
2005-09-30 21:13:37 +04:00
{ AP_USER_MUST_LOGON_TO_CHG_PASS , " user must logon to change password " , 0 ,
" Force Users to logon for password change (default: 0 => off, 2 => on) " ,
" sambaLogonToChgPwd " } ,
2005-02-12 03:51:31 +03:00
2005-09-30 21:13:37 +04:00
{ AP_MAX_PASSWORD_AGE , " maximum password age " , ( uint32 ) - 1 ,
" Maximum password age, in seconds (default: -1 => never expire passwords) " ,
" sambaMaxPwdAge " } ,
{ AP_MIN_PASSWORD_AGE , " minimum password age " , 0 ,
" Minimal password age, in seconds (default: 0 => allow immediate password change) " ,
" sambaMinPwdAge " } ,
{ AP_LOCK_ACCOUNT_DURATION , " lockout duration " , 30 ,
" Lockout duration in minutes (default: 30, -1 => forever) " ,
" sambaLockoutDuration " } ,
{ AP_RESET_COUNT_TIME , " reset count minutes " , 30 ,
" Reset time after lockout in minutes (default: 30) " ,
" sambaLockoutObservationWindow " } ,
{ AP_BAD_ATTEMPT_LOCKOUT , " bad lockout attempt " , 0 ,
" Lockout users after bad logon attempts (default: 0 => off) " ,
" sambaLockoutThreshold " } ,
2005-12-20 18:10:41 +03:00
{ AP_TIME_TO_LOGOUT , " disconnect time " , ( uint32 ) - 1 ,
2005-09-30 21:13:37 +04:00
" Disconnect Users outside logon hours (default: -1 => off, 0 => on) " ,
" sambaForceLogoff " } ,
{ AP_REFUSE_MACHINE_PW_CHANGE , " refuse machine password change " , 0 ,
" Allow Machine Password changes (default: 0 => off) " ,
" sambaRefuseMachinePwdChange " } ,
{ 0 , NULL , 0 , " " , NULL }
0001-01-01 02:30:17 +02:30
} ;
2006-12-01 17:54:31 +03:00
void account_policy_names_list ( const char * * * names , int * num_names )
{
const char * * nl ;
int i , count ;
2004-07-09 01:01:30 +04:00
2006-12-01 17:54:31 +03:00
for ( count = 0 ; account_policy_names [ count ] . string ; count + + ) {
2004-07-09 01:01:30 +04:00
}
2006-12-01 17:54:31 +03:00
nl = SMB_MALLOC_ARRAY ( const char * , count ) ;
2004-07-09 01:01:30 +04:00
if ( ! nl ) {
2006-12-01 17:54:31 +03:00
* num_names = 0 ;
return ;
2004-07-09 01:01:30 +04:00
}
for ( i = 0 ; account_policy_names [ i ] . string ; i + + ) {
2006-12-01 17:54:31 +03:00
nl [ i ] = account_policy_names [ i ] . string ;
2004-07-09 01:01:30 +04:00
}
2006-12-01 17:54:31 +03:00
* num_names = count ;
* names = nl ;
return ;
2004-07-09 01:01:30 +04:00
}
0001-01-01 02:30:17 +02:30
/****************************************************************************
Get the account policy name as a string from its # define ' ed number
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
const char * decode_account_policy_name ( int field )
0001-01-01 02:30:17 +02:30
{
int i ;
for ( i = 0 ; account_policy_names [ i ] . string ; i + + ) {
2005-12-20 18:10:41 +03:00
if ( field = = account_policy_names [ i ] . field ) {
0001-01-01 02:30:17 +02:30
return account_policy_names [ i ] . string ;
2005-12-20 18:10:41 +03:00
}
0001-01-01 02:30:17 +02:30
}
return NULL ;
2005-09-30 21:13:37 +04:00
}
/****************************************************************************
Get the account policy LDAP attribute as a string from its # define ' ed number
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
2005-09-30 21:13:37 +04:00
const char * get_account_policy_attr ( int field )
{
int i ;
for ( i = 0 ; account_policy_names [ i ] . field ; i + + ) {
2005-12-20 18:10:41 +03:00
if ( field = = account_policy_names [ i ] . field ) {
2005-09-30 21:13:37 +04:00
return account_policy_names [ i ] . ldap_attr ;
2005-12-20 18:10:41 +03:00
}
2005-09-30 21:13:37 +04:00
}
return NULL ;
}
/****************************************************************************
Get the account policy description as a string from its # define ' ed number
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * account_policy_get_desc ( int field )
{
int i ;
for ( i = 0 ; account_policy_names [ i ] . string ; i + + ) {
2005-12-20 18:10:41 +03:00
if ( field = = account_policy_names [ i ] . field ) {
2005-09-30 21:13:37 +04:00
return account_policy_names [ i ] . description ;
2005-12-20 18:10:41 +03:00
}
2005-09-30 21:13:37 +04:00
}
return NULL ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/****************************************************************************
0001-01-01 02:30:17 +02:30
Get the account policy name as a string from its # define ' ed number
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
0001-01-01 02:30:17 +02:30
int account_policy_name_to_fieldnum ( const char * name )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
int i ;
for ( i = 0 ; account_policy_names [ i ] . string ; i + + ) {
2005-12-20 18:10:41 +03:00
if ( strcmp ( name , account_policy_names [ i ] . string ) = = 0 ) {
0001-01-01 02:30:17 +02:30
return account_policy_names [ i ] . field ;
2005-12-20 18:10:41 +03:00
}
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
return 0 ;
2005-09-30 21:13:37 +04:00
}
/*****************************************************************************
Get default value for account policy
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool account_policy_get_default ( int account_policy , uint32 * val )
2005-09-30 21:13:37 +04:00
{
int i ;
for ( i = 0 ; account_policy_names [ i ] . field ; i + + ) {
if ( account_policy_names [ i ] . field = = account_policy ) {
* val = account_policy_names [ i ] . default_val ;
return True ;
}
}
DEBUG ( 0 , ( " no default for account_policy index %d found. This should never happen \n " ,
account_policy ) ) ;
return False ;
}
/*****************************************************************************
Set default for a field if it is empty
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool account_policy_set_default_on_empty ( int account_policy )
2005-09-30 21:13:37 +04:00
{
uint32 value ;
if ( ! account_policy_get ( account_policy , & value ) & &
! account_policy_get_default ( account_policy , & value ) ) {
return False ;
}
return account_policy_set ( account_policy , value ) ;
}
/*****************************************************************************
Open the account policy tdb .
* * * ` * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool init_account_policy ( void )
2005-09-30 21:13:37 +04:00
{
const char * vstring = " INFO/version " ;
uint32 version ;
int i ;
2008-03-28 14:09:56 +03:00
if ( db ! = NULL ) {
2005-09-30 21:13:37 +04:00
return True ;
2005-12-20 18:10:41 +03:00
}
2005-09-30 21:13:37 +04:00
2008-04-01 13:26:29 +04:00
db = db_open_trans ( NULL , state_path ( " account_policy.tdb " ) , 0 , TDB_DEFAULT ,
2008-03-28 14:09:56 +03:00
O_RDWR , 0600 ) ;
if ( db = = NULL ) { /* the account policies files does not exist or open
* failed , try to create a new one */
2008-04-01 13:26:29 +04:00
db = db_open_trans ( NULL , state_path ( " account_policy.tdb " ) , 0 ,
2008-03-28 14:09:56 +03:00
TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
if ( db = = NULL ) {
2006-07-11 22:01:26 +04:00
DEBUG ( 0 , ( " Failed to open account policy database \n " ) ) ;
return False ;
}
2005-09-30 21:13:37 +04:00
}
2008-03-28 14:09:56 +03:00
version = dbwrap_fetch_int32 ( db , vstring ) ;
if ( version = = DATABASE_VERSION ) {
return true ;
}
2005-09-30 21:13:37 +04:00
/* handle a Samba upgrade */
2008-03-28 14:09:56 +03:00
if ( db - > transaction_start ( db ) ! = 0 ) {
DEBUG ( 0 , ( " transaction_start failed \n " ) ) ;
TALLOC_FREE ( db ) ;
return false ;
}
version = dbwrap_fetch_int32 ( db , vstring ) ;
if ( version = = DATABASE_VERSION ) {
/*
* Race condition
*/
if ( db - > transaction_cancel ( db ) ) {
smb_panic ( " transaction_cancel failed " ) ;
}
return true ;
}
if ( version ! = DATABASE_VERSION ) {
if ( dbwrap_store_uint32 ( db , vstring , DATABASE_VERSION ) ! = 0 ) {
DEBUG ( 0 , ( " dbwrap_store_uint32 failed \n " ) ) ;
goto cancel ;
}
2005-09-30 21:13:37 +04:00
for ( i = 0 ; account_policy_names [ i ] . field ; i + + ) {
if ( ! account_policy_set_default_on_empty ( account_policy_names [ i ] . field ) ) {
DEBUG ( 0 , ( " failed to set default value in account policy tdb \n " ) ) ;
2008-03-28 14:09:56 +03:00
goto cancel ;
2005-09-30 21:13:37 +04:00
}
}
}
/* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
privilege_create_account ( & global_sid_World ) ;
privilege_create_account ( & global_sid_Builtin_Account_Operators ) ;
privilege_create_account ( & global_sid_Builtin_Server_Operators ) ;
privilege_create_account ( & global_sid_Builtin_Print_Operators ) ;
privilege_create_account ( & global_sid_Builtin_Backup_Operators ) ;
2006-03-15 08:50:52 +03:00
/* BUILTIN\Administrators get everything -- *always* */
2006-09-06 19:17:25 +04:00
if ( lp_enable_privileges ( ) ) {
if ( ! grant_all_privileges ( & global_sid_Builtin_Administrators ) ) {
DEBUG ( 1 , ( " init_account_policy: Failed to grant privileges "
" to BUILTIN \\ Administrators! \n " ) ) ;
}
2006-03-15 08:50:52 +03:00
}
2008-03-28 14:09:56 +03:00
if ( db - > transaction_commit ( db ) ! = 0 ) {
DEBUG ( 0 , ( " transaction_commit failed \n " ) ) ;
goto cancel ;
}
2005-09-30 21:13:37 +04:00
return True ;
2008-03-28 14:09:56 +03:00
cancel :
if ( db - > transaction_cancel ( db ) ) {
smb_panic ( " transaction_cancel failed " ) ;
}
TALLOC_FREE ( db ) ;
return false ;
2005-09-30 21:13:37 +04:00
}
/*****************************************************************************
Get an account policy ( from tdb )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-07-09 01:01:30 +04:00
2007-10-19 04:40:25 +04:00
bool account_policy_get ( int field , uint32 * value )
0001-01-01 02:30:17 +02:30
{
2006-09-10 02:27:06 +04:00
const char * name ;
2005-01-10 21:29:52 +03:00
uint32 regval ;
0001-01-01 02:30:17 +02:30
2005-12-20 18:10:41 +03:00
if ( ! init_account_policy ( ) ) {
2005-09-30 21:13:37 +04:00
return False ;
2005-12-20 18:10:41 +03:00
}
0001-01-01 02:30:17 +02:30
2005-12-20 18:10:41 +03:00
if ( value ) {
2005-01-10 21:29:52 +03:00
* value = 0 ;
2005-12-20 18:10:41 +03:00
}
0001-01-01 02:30:17 +02:30
2006-09-10 02:27:06 +04:00
name = decode_account_policy_name ( field ) ;
if ( name = = NULL ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 1 , ( " account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0. \n " , field ) ) ;
return False ;
}
2005-12-20 18:10:41 +03:00
2008-03-28 14:09:56 +03:00
if ( ! dbwrap_fetch_uint32 ( db , name , & regval ) ) {
2004-11-24 12:44:57 +03:00
DEBUG ( 1 , ( " account_policy_get: tdb_fetch_uint32 failed for field %d (%s), returning 0 \n " , field , name ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
2005-12-20 18:10:41 +03:00
if ( value ) {
2005-01-10 21:29:52 +03:00
* value = regval ;
2005-12-20 18:10:41 +03:00
}
2005-01-10 21:29:52 +03:00
2005-09-30 21:13:37 +04:00
DEBUG ( 10 , ( " account_policy_get: name: %s, val: %d \n " , name , regval ) ) ;
0001-01-01 02:30:17 +02:30
return True ;
}
/****************************************************************************
2005-09-30 21:13:37 +04:00
Set an account policy ( in tdb )
0001-01-01 02:30:17 +02:30
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
2007-10-19 04:40:25 +04:00
bool account_policy_set ( int field , uint32 value )
0001-01-01 02:30:17 +02:30
{
2006-09-10 02:27:06 +04:00
const char * name ;
2008-03-28 14:09:56 +03:00
NTSTATUS status ;
0001-01-01 02:30:17 +02:30
2005-12-20 18:10:41 +03:00
if ( ! init_account_policy ( ) ) {
2005-09-30 21:13:37 +04:00
return False ;
2005-12-20 18:10:41 +03:00
}
0001-01-01 02:30:17 +02:30
2006-09-10 02:27:06 +04:00
name = decode_account_policy_name ( field ) ;
if ( name = = NULL ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 1 , ( " Field %d is not a valid account policy type! Cannot set. \n " , field ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
0001-01-01 02:30:17 +02:30
}
2008-03-28 22:04:35 +03:00
status = dbwrap_trans_store_uint32 ( db , name , value ) ;
2008-03-28 14:09:56 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " store_uint32 failed for field %d (%s) on value "
" %u: %s \n " , field , name , value , nt_errstr ( status ) ) ) ;
0001-01-01 02:30:17 +02:30
return False ;
}
2005-09-30 21:13:37 +04:00
DEBUG ( 10 , ( " account_policy_set: name: %s, value: %d \n " , name , value ) ) ;
0001-01-01 02:30:17 +02:30
return True ;
}
2005-01-13 21:20:37 +03:00
2005-09-30 21:13:37 +04:00
/****************************************************************************
Set an account policy in the cache
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool cache_account_policy_set ( int field , uint32 value )
2005-09-30 21:13:37 +04:00
{
const char * policy_name = NULL ;
2006-09-10 02:27:06 +04:00
char * cache_key = NULL ;
char * cache_value = NULL ;
2007-10-19 04:40:25 +04:00
bool ret = False ;
2005-09-30 21:13:37 +04:00
policy_name = decode_account_policy_name ( field ) ;
if ( policy_name = = NULL ) {
DEBUG ( 0 , ( " cache_account_policy_set: no policy found \n " ) ) ;
return False ;
}
2006-09-10 02:27:06 +04:00
if ( asprintf ( & cache_key , " ACCT_POL/%s " , policy_name ) < 0 ) {
DEBUG ( 0 , ( " asprintf failed \n " ) ) ;
goto done ;
2005-12-20 18:10:41 +03:00
}
2006-09-10 02:27:06 +04:00
if ( asprintf ( & cache_value , " %lu \n " , ( unsigned long ) value ) < 0 ) {
DEBUG ( 0 , ( " asprintf failed \n " ) ) ;
goto done ;
2005-12-20 18:10:41 +03:00
}
2006-09-10 02:27:06 +04:00
DEBUG ( 10 , ( " cache_account_policy_set: updating account pol cache \n " ) ) ;
2005-12-20 18:10:41 +03:00
2006-09-10 02:27:06 +04:00
ret = gencache_set ( cache_key , cache_value , time ( NULL ) + AP_TTL ) ;
2005-12-20 18:10:41 +03:00
2006-09-10 02:27:06 +04:00
done :
SAFE_FREE ( cache_key ) ;
SAFE_FREE ( cache_value ) ;
return ret ;
2005-12-20 18:10:41 +03:00
}
2005-09-30 21:13:37 +04:00
/*****************************************************************************
Get an account policy from the cache
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool cache_account_policy_get ( int field , uint32 * value )
2005-09-30 21:13:37 +04:00
{
2006-09-10 02:27:06 +04:00
const char * policy_name = NULL ;
char * cache_key = NULL ;
char * cache_value = NULL ;
2007-10-19 04:40:25 +04:00
bool ret = False ;
2005-09-30 21:13:37 +04:00
2006-09-10 02:27:06 +04:00
policy_name = decode_account_policy_name ( field ) ;
if ( policy_name = = NULL ) {
DEBUG ( 0 , ( " cache_account_policy_set: no policy found \n " ) ) ;
2005-09-30 21:13:37 +04:00
return False ;
}
2006-09-10 02:27:06 +04:00
if ( asprintf ( & cache_key , " ACCT_POL/%s " , policy_name ) < 0 ) {
DEBUG ( 0 , ( " asprintf failed \n " ) ) ;
goto done ;
}
2005-09-30 21:13:37 +04:00
2006-09-10 02:27:06 +04:00
if ( gencache_get ( cache_key , & cache_value , NULL ) ) {
uint32 tmp = strtoul ( cache_value , NULL , 10 ) ;
* value = tmp ;
ret = True ;
}
2005-09-30 21:13:37 +04:00
2006-09-10 02:27:06 +04:00
done :
SAFE_FREE ( cache_key ) ;
SAFE_FREE ( cache_value ) ;
return ret ;
}
2005-09-30 21:13:37 +04:00
2005-01-13 21:20:37 +03:00
/****************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-28 14:09:56 +03:00
struct db_context * get_account_pol_db ( void )
2005-01-13 21:20:37 +03:00
{
2008-03-28 14:09:56 +03:00
if ( db ! = NULL ) {
2005-12-20 18:10:41 +03:00
if ( ! init_account_policy ( ) ) {
2005-01-13 21:20:37 +03:00
return NULL ;
2005-12-20 18:10:41 +03:00
}
2005-01-13 21:20:37 +03:00
}
2008-03-28 14:09:56 +03:00
return db ;
2005-01-13 21:20:37 +03:00
}