s3-account_policy: remove trailing whitespace.
[ira/wip.git] / source3 / lib / account_pol.c
index e6ef8dbbe4b3be3b93bed9d06aae54fc6fd118f2..4b63375e29271385f6fd32dcb376d7dc2ee0fa5a 100644 (file)
@@ -1,34 +1,32 @@
-/* 
+/*
  *  Unix SMB/CIFS implementation.
  *  account policy storage
  *  Copyright (C) Jean François Micouleau      1998-2001.
  *  Copyright (C) Andrew Bartlett              2002
  *  Copyright (C) Guenther Deschner            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
- *  the Free Software Foundation; either version 2 of the License, or
+ *  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, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
-static TDB_CONTEXT *tdb; 
+static struct db_context *db;
 
 /* 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 */
 
 #define DATABASE_VERSION       3
-#define AP_LASTSET             "LAST_CACHE_UPDATE"
 #define AP_TTL                 60
 
 
@@ -41,71 +39,67 @@ struct ap_table {
 };
 
 static const struct ap_table account_policy_names[] = {
-       {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, 
-               "Minimal password length (default: 5)", 
+       {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH,
+               "Minimal password length (default: 5)",
                "sambaMinPwdLength" },
 
        {AP_PASSWORD_HISTORY, "password history", 0,
-               "Length of Password History Entries (default: 0 => off)", 
+               "Length of Password History Entries (default: 0 => off)",
                "sambaPwdHistoryLength" },
-               
+
        {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" },
-       
+
        {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1,
-               "Maximum password age, in seconds (default: -1 => never expire passwords)", 
+               "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)", 
+               "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)", 
+               "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)", 
+               "Lockout users after bad logon attempts (default: 0 => off)",
                "sambaLockoutThreshold" },
-               
+
        {AP_TIME_TO_LOGOUT, "disconnect time", (uint32) -1,
-               "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", 
-               "sambaForceLogoff" }, 
-               
+               "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}
 };
 
-char *account_policy_names_list(void)
+void account_policy_names_list(const char ***names, int *num_names)
 {
-       char *nl, *p;
-       int i;
-       size_t len = 0;
+       const char **nl;
+       int i, count;
 
-       for (i=0; account_policy_names[i].string; i++) {
-               len += strlen(account_policy_names[i].string) + 1;
+       for (count=0; account_policy_names[count].string; count++) {
        }
-       len++;
-       nl = (char *)SMB_MALLOC(len);
+       nl = SMB_MALLOC_ARRAY(const char *, count);
        if (!nl) {
-               return NULL;
+               *num_names = 0;
+               return;
        }
-       p = nl;
        for (i=0; account_policy_names[i].string; i++) {
-               memcpy(p, account_policy_names[i].string, strlen(account_policy_names[i].string) + 1);
-               p[strlen(account_policy_names[i].string)] = '\n';
-               p += strlen(account_policy_names[i].string) + 1;
+               nl[i] = account_policy_names[i].string;
        }
-       *p = '\0';
-       return nl;
+       *num_names = count;
+       *names = nl;
+       return;
 }
 
 /****************************************************************************
@@ -168,55 +162,11 @@ int account_policy_name_to_fieldnum(const char *name)
        return 0;
 }
 
-/*****************************************************************************
-Update LAST-Set counter inside the cache
-*****************************************************************************/
-
-static BOOL account_policy_cache_timestamp(uint32 *value, BOOL update, 
-                                          const char *ap_name)
-{
-       pstring key;
-       uint32 val = 0;
-       time_t now;
-
-       if (ap_name == NULL)
-               return False;
-               
-       slprintf(key, sizeof(key)-1, "%s/%s", ap_name, AP_LASTSET);
-
-       if (!init_account_policy()) {
-               return False;
-       }
-
-       if (!tdb_fetch_uint32(tdb, key, &val) && !update) {
-               DEBUG(10,("failed to get last set timestamp of cache\n"));
-               return False;
-       }
-
-       *value = val;
-
-       DEBUG(10, ("account policy cache lastset was: %s\n", http_timestring(val)));
-
-       if (update) {
-
-               now = time(NULL);
-
-               if (!tdb_store_uint32(tdb, key, (uint32)now)) {
-                       DEBUG(1, ("tdb_store_uint32 failed for %s\n", key));
-                       return False;
-               }
-               DEBUG(10, ("account policy cache lastset now: %s\n", http_timestring(now)));
-               *value = now;
-       }
-
-       return True;
-}
-
 /*****************************************************************************
 Get default value for account policy
 *****************************************************************************/
 
-BOOL account_policy_get_default(int account_policy, uint32 *val)
+bool account_policy_get_default(int account_policy, uint32 *val)
 {
        int i;
        for (i=0; account_policy_names[i].field; i++) {
@@ -225,7 +175,7 @@ BOOL account_policy_get_default(int account_policy, uint32 *val)
                        return True;
                }
        }
-       DEBUG(0,("no default for account_policy index %d found. This should never happen\n", 
+       DEBUG(0,("no default for account_policy index %d found. This should never happen\n",
                account_policy));
        return False;
 }
@@ -234,12 +184,12 @@ BOOL account_policy_get_default(int account_policy, uint32 *val)
  Set default for a field if it is empty
 *****************************************************************************/
 
-static BOOL account_policy_set_default_on_empty(int account_policy)
+static bool account_policy_set_default_on_empty(int account_policy)
 {
 
        uint32 value;
 
-       if (!account_policy_get(account_policy, &value) && 
+       if (!account_policy_get(account_policy, &value) &&
            !account_policy_get_default(account_policy, &value)) {
                return False;
        }
@@ -251,48 +201,69 @@ static BOOL account_policy_set_default_on_empty(int account_policy)
  Open the account policy tdb.
 ***`*************************************************************************/
 
-BOOL init_account_policy(void)
+bool init_account_policy(void)
 {
 
        const char *vstring = "INFO/version";
        uint32 version;
        int i;
 
-       if (tdb) {
+       if (db != NULL) {
                return True;
        }
 
-       tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
-       if (!tdb) { /* the account policies files does not exist or open failed, try to create a new one */
-               tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
-               if (!tdb) {
+       db = db_open(NULL, state_path("account_policy.tdb"), 0, TDB_DEFAULT,
+                    O_RDWR, 0600);
+
+       if (db == NULL) { /* the account policies files does not exist or open
+                          * failed, try to create a new one */
+               db = db_open(NULL, state_path("account_policy.tdb"), 0,
+                            TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+               if (db == NULL) {
                        DEBUG(0,("Failed to open account policy database\n"));
                        return False;
                }
-               /* creation was successful */
-               /* add AP_MIGRATED_TO_PASSDB speacial key */
-               /* so that you do not need to migrate policies */
-               /* on brand new servers as it does not make sense */
-               account_policy_migrated(True);
+       }
+
+       version = dbwrap_fetch_int32(db, vstring);
+       if (version == DATABASE_VERSION) {
+               return true;
        }
 
        /* handle a Samba upgrade */
-       tdb_lock_bystring(tdb, vstring);
-       if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) {
 
-               tdb_store_uint32(tdb, vstring, DATABASE_VERSION);
+       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;
+               }
 
                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"));
-                               return False;
+                               goto cancel;
                        }
                }
        }
 
-       tdb_unlock_bystring(tdb, vstring);
-
        /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
 
        privilege_create_account( &global_sid_World );
@@ -310,16 +281,30 @@ BOOL init_account_policy(void)
                }
        }
 
+       if (db->transaction_commit(db) != 0) {
+               DEBUG(0, ("transaction_commit failed\n"));
+               TALLOC_FREE(db);
+               return false;
+       }
+
        return True;
+
+ cancel:
+       if (db->transaction_cancel(db)) {
+               smb_panic("transaction_cancel failed");
+       }
+       TALLOC_FREE(db);
+
+       return false;
 }
 
 /*****************************************************************************
-Get an account policy (from tdb) 
+Get an account policy (from tdb)
 *****************************************************************************/
 
-BOOL account_policy_get(int field, uint32 *value)
+bool account_policy_get(int field, uint32 *value)
 {
-       fstring name;
+       const char *name;
        uint32 regval;
 
        if (!init_account_policy()) {
@@ -330,17 +315,17 @@ BOOL account_policy_get(int field, uint32 *value)
                *value = 0;
        }
 
-       fstrcpy(name, decode_account_policy_name(field));
-       if (!*name) {
+       name = decode_account_policy_name(field);
+       if (name == NULL) {
                DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type!  Cannot get, returning 0.\n", field));
                return False;
        }
-       
-       if (!tdb_fetch_uint32(tdb, name, &regval)) {
+
+       if (!dbwrap_fetch_uint32(db, name, &regval)) {
                DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for field %d (%s), returning 0\n", field, name));
                return False;
        }
-       
+
        if (value) {
                *value = regval;
        }
@@ -351,41 +336,46 @@ BOOL account_policy_get(int field, uint32 *value)
 
 
 /****************************************************************************
-Set an account policy (in tdb) 
+Set an account policy (in tdb)
 ****************************************************************************/
 
-BOOL account_policy_set(int field, uint32 value)
+bool account_policy_set(int field, uint32 value)
 {
-       fstring name;
+       const char *name;
+       NTSTATUS status;
 
        if (!init_account_policy()) {
                return False;
        }
 
-       fstrcpy(name, decode_account_policy_name(field));
-       if (!*name) {
+       name = decode_account_policy_name(field);
+       if (name == NULL) {
                DEBUG(1, ("Field %d is not a valid account policy type!  Cannot set.\n", field));
                return False;
        }
 
-       if (!tdb_store_uint32(tdb, name, value)) {
-               DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u\n", field, name, value));
+       status = dbwrap_trans_store_uint32(db, name, value);
+       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)));
                return False;
        }
 
        DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value));
-       
+
        return True;
 }
 
 /****************************************************************************
-Set an account policy in the cache 
+Set an account policy in the cache
 ****************************************************************************/
 
-BOOL cache_account_policy_set(int field, uint32 value)
+bool cache_account_policy_set(int field, uint32 value)
 {
-       uint32 lastset;
        const char *policy_name = NULL;
+       char *cache_key = NULL;
+       char *cache_value = NULL;
+       bool ret = False;
 
        policy_name = decode_account_policy_name(field);
        if (policy_name == NULL) {
@@ -393,107 +383,72 @@ BOOL cache_account_policy_set(int field, uint32 value)
                return False;
        }
 
-       DEBUG(10,("cache_account_policy_set: updating account pol cache\n"));
-
-       if (!account_policy_set(field, value)) {
-               return False;
+       if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) {
+               DEBUG(0, ("asprintf failed\n"));
+               goto done;
        }
 
-       if (!account_policy_cache_timestamp(&lastset, True, policy_name)) 
-       {
-               DEBUG(10,("cache_account_policy_set: failed to get lastest cache update timestamp\n"));
-               return False;
+       if (asprintf(&cache_value, "%lu\n", (unsigned long)value) < 0) {
+               DEBUG(0, ("asprintf failed\n"));
+               goto done;
        }
 
-       DEBUG(10,("cache_account_policy_set: cache valid until: %s\n", http_timestring(lastset+AP_TTL)));
+       DEBUG(10,("cache_account_policy_set: updating account pol cache\n"));
+
+       ret = gencache_set(cache_key, cache_value, time(NULL)+AP_TTL);
 
-       return True;
+ done:
+       SAFE_FREE(cache_key);
+       SAFE_FREE(cache_value);
+       return ret;
 }
 
 /*****************************************************************************
-Check whether account policies have been migrated to passdb
+Get an account policy from the cache
 *****************************************************************************/
 
-BOOL account_policy_migrated(BOOL init)
+bool cache_account_policy_get(int field, uint32 *value)
 {
-       pstring key;
-       uint32 val;
-       time_t now;
-
-       slprintf(key, sizeof(key)-1, "AP_MIGRATED_TO_PASSDB");
-
-       if (!init_account_policy()) {
-               return False;
-       }
-
-       if (init) {
-               now = time(NULL);
-
-               if (!tdb_store_uint32(tdb, key, (uint32)now)) {
-                       DEBUG(1, ("tdb_store_uint32 failed for %s\n", key));
-                       return False;
-               }
-
-               return True;
-       }
+       const char *policy_name = NULL;
+       char *cache_key = NULL;
+       char *cache_value = NULL;
+       bool ret = False;
 
-       if (!tdb_fetch_uint32(tdb, key, &val)) {
+       policy_name = decode_account_policy_name(field);
+       if (policy_name == NULL) {
+               DEBUG(0,("cache_account_policy_set: no policy found\n"));
                return False;
        }
 
-       return True;
-}
-
-/*****************************************************************************
- Remove marker that informs that account policies have been migrated to passdb
-*****************************************************************************/
-
-BOOL remove_account_policy_migrated(void)
-{
-       if (!init_account_policy()) {
-               return False;
+       if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) {
+               DEBUG(0, ("asprintf failed\n"));
+               goto done;
        }
 
-       return tdb_delete_bystring(tdb, "AP_MIGRATED_TO_PASSDB");
-}
-
-
-/*****************************************************************************
-Get an account policy from the cache 
-*****************************************************************************/
-
-BOOL cache_account_policy_get(int field, uint32 *value)
-{
-       uint32 lastset;
-
-       if (!account_policy_cache_timestamp(&lastset, False, 
-                                           decode_account_policy_name(field))) 
-       {
-               DEBUG(10,("cache_account_policy_get: failed to get latest cache update timestamp\n"));
-               return False;
+       if (gencache_get(cache_key, &cache_value, NULL)) {
+               uint32 tmp = strtoul(cache_value, NULL, 10);
+               *value = tmp;
+               ret = True;
        }
 
-       if ((lastset + AP_TTL) < (uint32)time(NULL) ) {
-               DEBUG(10,("cache_account_policy_get: no valid cache entry (cache expired)\n"));
-               return False;
-       } 
-
-       return account_policy_get(field, value);
+ done:
+       SAFE_FREE(cache_key);
+       SAFE_FREE(cache_value);
+       return ret;
 }
 
-
 /****************************************************************************
 ****************************************************************************/
 
-TDB_CONTEXT *get_account_pol_tdb( void )
+struct db_context *get_account_pol_db( void )
 {
 
-       if ( !tdb ) {
+       if ( db == NULL ) {
                if ( !init_account_policy() ) {
                        return NULL;
                }
        }
 
-       return tdb;
+       return db;
 }