The Samba-Bugzilla – Attachment 736 Details for
Bug 1913
account policies need to be replicated between dc's
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
move account_pol into passdb
samba3-account_pol_ldap_v5.diff (text/plain), 54.31 KB, created by
Guenther Deschner
on 2004-10-20 09:57:57 UTC
(
hide
)
Description:
move account_pol into passdb
Filename:
MIME Type:
Creator:
Guenther Deschner
Created:
2004-10-20 09:57:57 UTC
Size:
54.31 KB
patch
obsolete
>Index: source/Makefile.in >=================================================================== >--- source/Makefile.in (revision 3080) >+++ source/Makefile.in (working copy) >@@ -202,7 +202,7 @@ > lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \ > lib/md5.o lib/hmacmd5.o lib/iconv.o \ > nsswitch/wb_client.o $(WBCOMMON_OBJ) \ >- lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ >+ lib/pam_errors.o intl/lang_tdb.o \ > lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \ > lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \ > lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o >@@ -312,7 +312,8 @@ > PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ > passdb/util_sam_sid.o passdb/pdb_compat.o \ > passdb/privileges.o passdb/lookup_sid.o \ >- passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o >+ passdb/login_cache.o lib/account_pol.o \ >+ @PDB_STATIC@ passdb/pdb_sql.o > > XML_OBJ = passdb/pdb_xml.o > MYSQL_OBJ = passdb/pdb_mysql.o >@@ -507,7 +508,8 @@ > libsmb/libsmb_cache.o \ > $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ > $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \ >- $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) >+ $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ >+ $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(DUMMYROOT_OBJ) > > # This shared library is intended for linking with unit test programs > # to test Samba internals. It's called libbigballofmud.so to >@@ -583,13 +585,16 @@ > > SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ > $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \ >- $(PASSDB_GET_SET_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \ >- $(POPT_LIB_OBJ) $(DCUTIL_OBJ) $(LIBADS_OBJ) >+ $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \ >+ $(POPT_LIB_OBJ) $(DCUTIL_OBJ) $(LIBADS_OBJ) \ >+ $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(DUMMYROOT_OBJ) > >+ > SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ > $(PARAM_OBJ) \ >- $(UBIQX_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \ >- $(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) >+ $(UBIQX_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \ >+ $(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \ >+ $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(DUMMYROOT_OBJ) > > TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) > >Index: source/smbd/chgpasswd.c >=================================================================== >--- source/smbd/chgpasswd.c (revision 3080) >+++ source/smbd/chgpasswd.c (working copy) >@@ -947,7 +947,7 @@ > BOOL found = False; > int i, pwHisLen, curr_pwHisLen; > >- account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen); > if (pwHisLen == 0) { > return False; > } >@@ -1019,7 +1019,7 @@ > } > > /* FIXME: AP_MIN_PASSWORD_LEN and lp_min_passwd_length() need to be merged - gd */ >- if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { >+ if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { > DEBUG(1, ("user %s cannot change password - password too short\n", > username)); > DEBUGADD(1, (" account policy min password len = %d\n", min_len)); >Index: source/lib/account_pol.c >=================================================================== >--- source/lib/account_pol.c (revision 3080) >+++ source/lib/account_pol.c (working copy) >@@ -3,6 +3,7 @@ > * account policy storage > * Copyright (C) Jean François Micouleau 1998-2001. > * Copyright (C) Andrew Bartlett 2002 >+ * Copyright (C) Guenther Deschner 2004 > * > * 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 >@@ -20,65 +21,42 @@ > */ > > #include "includes.h" >-static TDB_CONTEXT *tdb; /* used for driver files */ >+static TDB_CONTEXT *tdb; /* used for account policies */ > > #define DATABASE_VERSION 1 >+#define AP_PREFIX "AP" >+#define AP_LASTSET "LAST_CACHE_UPDATE" >+#define AP_MIGRATED "ACCOUNT POLICIES WERE MIGRATED TO PASSDB" >+#define AP_TTL 60 /* allow entries to be cached for 60 seconds */ > >-/**************************************************************************** >- Open the account policy tdb. >-****************************************************************************/ >- >-BOOL init_account_policy(void) >-{ >- static pid_t local_pid; >- const char *vstring = "INFO/version"; >- uint32 version; >- >- if (tdb && local_pid == sys_getpid()) >- return True; >- tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); >- if (!tdb) { >- DEBUG(0,("Failed to open account policy database\n")); >- return False; >- } >- >- local_pid = sys_getpid(); >- >- /* handle a Samba upgrade */ >- tdb_lock_bystring(tdb, vstring,0); >- if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { >- tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); >- tdb_store_uint32(tdb, vstring, DATABASE_VERSION); >- >- account_policy_set(AP_MIN_PASSWORD_LEN, MINPASSWDLENGTH); /* 5 chars minimum */ >- account_policy_set(AP_PASSWORD_HISTORY, 0); /* don't keep any old password */ >- account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, 0); /* don't force user to logon */ >- account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)-1); /* don't expire */ >- account_policy_set(AP_MIN_PASSWORD_AGE, 0); /* 0 days */ >- account_policy_set(AP_LOCK_ACCOUNT_DURATION, 30); /* lockout for 30 minutes */ >- account_policy_set(AP_RESET_COUNT_TIME, 30); /* reset after 30 minutes */ >- account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, 0); /* don't lockout */ >- account_policy_set(AP_TIME_TO_LOGOUT, -1); /* don't force logout */ >- } >- tdb_unlock_bystring(tdb, vstring); >- >- return True; >-} >- >-static const struct { >+struct ap_table { > int field; > const char *string; >-} account_policy_names[] = { >- {AP_MIN_PASSWORD_LEN, "min password length"}, >- {AP_PASSWORD_HISTORY, "password history"}, >- {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"}, >- {AP_MAX_PASSWORD_AGE, "maximum password age"}, >- {AP_MIN_PASSWORD_AGE,"minimum password age"}, >- {AP_LOCK_ACCOUNT_DURATION, "lockout duration"}, >- {AP_RESET_COUNT_TIME, "reset count minutes"}, >- {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"}, >- {AP_TIME_TO_LOGOUT, "disconnect time"}, >- {0, NULL} >+ uint32 default_val; >+ BOOL cached; >+ const char *comment; >+}; >+ >+static const struct ap_table account_policies[] = { >+ {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, False, >+ "Minimal password length (default: 5)"}, >+ {AP_PASSWORD_HISTORY, "password history", 0, True, >+ "Length of Password History Entries (default: 0 => off)" }, >+ {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0, False, >+ "Force Users to logon for password change (default: 0 => off, 2 => on)"}, >+ {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32)-1, False, >+ "Maximum password age, in seconds (default: -1 => never expire passwords)"}, >+ {AP_MIN_PASSWORD_AGE,"minimum password age", 0, False, >+ "Minimal password age, in seconds (default: 0 => allow immediate password change)"}, >+ {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30, False, >+ "Lockout duration in minutes (default: 30)"}, >+ {AP_RESET_COUNT_TIME, "reset count minutes", 30, False, >+ "Reset time after lockout in minutes (default: 30)"}, >+ {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0, False, >+ "Lockout users after bad logon attempts (default: 0 => off)"}, >+ {AP_TIME_TO_LOGOUT, "disconnect time", -1, False, >+ "Disconnect Users outside logon hours (default: -1 => off, 0 => on)"}, >+ {0, NULL, 0, False, ""} > }; > > char *account_policy_names_list(void) >@@ -87,8 +65,8 @@ > int i; > size_t len = 0; > >- for (i=0; account_policy_names[i].string; i++) { >- len += strlen(account_policy_names[i].string) + 1; >+ for (i=0; account_policies[i].string; i++) { >+ len += strlen(account_policies[i].string) + 1; > } > len++; > nl = malloc(len); >@@ -96,10 +74,10 @@ > return NULL; > } > 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; >+ for (i=0; account_policies[i].string; i++) { >+ memcpy(p, account_policies[i].string, strlen(account_policies[i].string) + 1); >+ p[strlen(account_policies[i].string)] = '\n'; >+ p += strlen(account_policies[i].string) + 1; > } > *p = '\0'; > return nl; >@@ -109,64 +87,400 @@ > Get the account policy name as a string from its #define'ed number > ****************************************************************************/ > >-static const char *decode_account_policy_name(int field) >+const char *decode_account_policy_name(int field) > { > int i; >- for (i=0; account_policy_names[i].string; i++) { >- if (field == account_policy_names[i].field) >- return account_policy_names[i].string; >+ for (i=0; account_policies[i].string; i++) { >+ if (field == account_policies[i].field) >+ return account_policies[i].string; > } > return NULL; > > } > > /**************************************************************************** >+Get the account policy comment as a string from its #define'ed number >+****************************************************************************/ >+ >+const char *account_policy_get_comment(int field) >+{ >+ int i; >+ for (i=0; account_policies[i].string; i++) { >+ if (field == account_policies[i].field) >+ return account_policies[i].comment; >+ } >+ return NULL; >+ >+} >+ >+/**************************************************************************** > Get the account policy name as a string from its #define'ed number > ****************************************************************************/ > > int account_policy_name_to_fieldnum(const char *name) > { > int i; >- for (i=0; account_policy_names[i].string; i++) { >- if (strcmp(name, account_policy_names[i].string) == 0) >- return account_policy_names[i].field; >+ for (i=0; account_policies[i].string; i++) { >+ if (strcmp(name, account_policies[i].string) == 0) >+ return account_policies[i].field; > } > return 0; > > } > > /**************************************************************************** >+Update LAST-Set counter inside the cache > ****************************************************************************/ > >-BOOL account_policy_get(int field, uint32 *value) >+static BOOL account_policy_lastset(uint32 *value, BOOL update) > { >+ pstring key; >+ uint32 val = 0; >+ time_t now; >+ >+ slprintf(key, sizeof(key)-1, "%s", 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; >+} >+ >+static BOOL set_account_policy_lastset(void) >+{ >+ uint32 lastset; >+ return account_policy_lastset(&lastset, True); >+} >+ >+ >+/**************************************************************************** >+Update local tdb cache with entries from another passdb backend >+****************************************************************************/ >+ >+static BOOL update_account_policy_cache(void) >+{ >+ int tmp_val,i; >+ uint32 lastset; >+ >+ if (!account_policy_lastset(&lastset, False)) { >+ DEBUG(10,("failed to get last set timestamp from tdb\n")); >+ return False; >+ } >+ >+ if ((lastset + AP_TTL) > (uint32)time(NULL) ) { >+ DEBUG(10,("update_account_policy_cache: cache still valid. no update required\n")); >+ return True; >+ } >+ >+ DEBUG(10,("update_account_policy_cache: cache expired\n")); >+ >+ for (i=0; account_policies[i].string && (account_policies[i].cached == True); i++) { >+ >+ if (!pdb_get_account_policy(i, &tmp_val)) { >+ DEBUG(0,("could not get value for account policy from passdb\n")); >+ return False; >+ } >+ >+ if (!db_account_policy_set(i, tmp_val)) { >+ DEBUG(0,("failed to set account_policy in the local tdb cache\n")); >+ return False; >+ } >+ >+ DEBUG(10,("updated local cache for %s with value %d from passdb\n", >+ (char *)decode_account_policy_name(i), tmp_val)); >+ } >+ >+ return True; >+} >+ >+/**************************************************************************** >+Get default value for account policy >+****************************************************************************/ >+ >+BOOL account_policy_get_default(int account_policy, uint32 *val) >+{ >+ int i; >+ for (i=0; account_policies[i].field; i++) { >+ if (account_policies[i].field == account_policy) { >+ *val = account_policies[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 value for account policy >+****************************************************************************/ >+ >+static BOOL db_account_policy_set_default(int account_policy) >+{ >+ uint32 value; >+ if (!account_policy_get_default(account_policy, &value)) { >+ return False; >+ } >+ return db_account_policy_set(account_policy, value); >+} >+ >+/**************************************************************************** >+helper function to delete a single key inside the tdb >+****************************************************************************/ >+ >+static BOOL account_policy_delete(int field) >+{ >+ pstring key; > fstring name; >+ TDB_DATA kbuf; > >- if(!init_account_policy())return False; >+ if (!init_account_policy()) >+ return False; > >+ fstrcpy(name, decode_account_policy_name(field)); >+ if (!*name) { >+ DEBUG(1, ("Field %d is not a valid account policy type! Cannot delete.\n", field)); >+ return False; >+ } >+ >+ slprintf(key, sizeof(key), "%s", name); >+ >+ kbuf.dptr = key; >+ kbuf.dsize = strlen(key)+1; >+ >+ return tdb_delete(tdb, kbuf) == 0; >+ >+} >+ >+/**************************************************************************** >+Check migration status, set marker if required >+****************************************************************************/ >+ >+static BOOL already_migrated_account_policies(BOOL store_migration_status) >+{ >+ pstring key; >+ uint32 value; >+ >+ slprintf(key, sizeof(key)-1, "%s", AP_MIGRATED); >+ >+ if (tdb_fetch_uint32(tdb, key, &value)) { >+ return True; >+ } >+ >+ if (store_migration_status) { >+ >+ if (!tdb_store_uint32(tdb, key, 1)) { >+ DEBUG(1, ("tdb_store_uint32 failed for %s\n", key)); >+ return False; >+ } >+ return True; >+ } >+ >+ return False; >+} >+ >+/**************************************************************************** >+Migrate account policies to passdb >+****************************************************************************/ >+ >+static BOOL migrate_account_policies_to_passdb(void) >+{ >+ int i; >+ >+ if (already_migrated_account_policies(False)) { >+ return True; >+ } >+ >+ /* reuse the existing account policy tdb as default storage location >+ for all non-ldapsam passdb-backends. We rename the keys though and store >+ a marker after a successful migration */ >+ >+ DEBUG(1,("start migrating account policies into passdb\n")); >+ >+ for (i=1; decode_account_policy_name(i) != NULL; i++) { >+ >+ /* query all old keys in the tdb and then add to the new api via direct >+ pdb_set_account_policy()-calls. */ >+ >+ int tmp_val; >+ >+ if (!account_policy_get(i, &tmp_val)) { >+ DEBUG(0,("very weird: could not get value for account policy\n")); >+ return False; >+ } >+ >+ DEBUGADD(1,("\tmigrating account policy (#%d: %s with value: %d) to passdb\n", >+ i, (char *)decode_account_policy_name(i), tmp_val)); >+ >+ /* set policy via new passdb api */ >+ if (!pdb_set_account_policy(i, tmp_val)) { >+ DEBUG(0,("failed to set account_policy\n")); >+ return False; >+ } >+ >+ if (!account_policy_delete(i)) { >+ DEBUG(0,("failed to delete old account policy from the tdb.\n")); >+ return False; >+ } >+ >+ } >+ >+ if (!already_migrated_account_policies(True)) { >+ DEBUG(0,("could not store marker for account policy migration in the tdb\n")); >+ return False; >+ } >+ >+ DEBUGADD(1,("succesfully migrated account policies into passdb\n")); >+ >+ return True; >+} >+ >+/**************************************************************************** >+ Open the account policy tdb. >+****************************************************************************/ >+ >+BOOL init_account_policy(void) >+{ >+ static pid_t local_pid; >+ const char *vstring = "INFO/version"; >+ uint32 version; >+ >+ if (tdb && local_pid == sys_getpid()) >+ return True; >+ >+ tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); >+ if (!tdb) { >+ DEBUG(0,("Failed to open account policy database\n")); >+ return False; >+ } >+ >+ local_pid = sys_getpid(); >+ >+ /* handle a Samba upgrade */ >+ tdb_lock_bystring(tdb, vstring,0); >+ if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { >+ >+ tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); >+ tdb_store_uint32(tdb, vstring, DATABASE_VERSION); >+ >+ db_account_policy_set_default(AP_MIN_PASSWORD_LEN); >+ db_account_policy_set_default(AP_PASSWORD_HISTORY); >+ db_account_policy_set_default(AP_USER_MUST_LOGON_TO_CHG_PASS); >+ db_account_policy_set_default(AP_MAX_PASSWORD_AGE); >+ db_account_policy_set_default(AP_MIN_PASSWORD_AGE); >+ db_account_policy_set_default(AP_LOCK_ACCOUNT_DURATION); >+ db_account_policy_set_default(AP_RESET_COUNT_TIME); >+ db_account_policy_set_default(AP_BAD_ATTEMPT_LOCKOUT); >+ db_account_policy_set_default(AP_TIME_TO_LOGOUT); >+ >+ /* set "already migrated" reminder and cache timestamps */ >+ if (!already_migrated_account_policies(True)) { >+ return False; >+ } >+ >+ if (!set_account_policy_lastset()) { >+ return False; >+ } >+ >+ } >+ tdb_unlock_bystring(tdb, vstring); >+ >+ if (!migrate_account_policies_to_passdb()) { >+ DEBUG(0,("Could not migrate account policy tdb to passdb.\n")); >+ return False; >+ } >+ >+#if 0 >+ if (!update_account_policy_cache()) { >+ DEBUG(0,("failed to update local policy cache\n")); >+ return False; >+ } >+#endif >+ >+ return True; >+} >+ >+/**************************************************************************** >+****************************************************************************/ >+ >+static BOOL account_policy_get_internal(int field, uint32 *value, BOOL passdb_call) >+{ >+ fstring name; >+ pstring key; >+ >+ if (!init_account_policy()) >+ return False; >+ > *value = 0; > > fstrcpy(name, decode_account_policy_name(field)); > if (!*name) { >- DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); >+ DEBUG(1, ("account_policy_get_internal: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); > return False; > } >- if (!tdb_fetch_uint32(tdb, name, value)) { >- DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for efild %d (%s), returning 0", field, name)); >+ >+ slprintf(key, sizeof(key)-1, "%s/%s", AP_PREFIX, name); >+ >+ if (!tdb_fetch_uint32(tdb, passdb_call ? key : name, value)) { >+ DEBUG(1, ("account_policy_get_internal: tdb_fetch_uint32 failed for field %d (%s), returning 0\n", field, passdb_call ? key : name)); > return False; > } >- DEBUG(10,("account_policy_get: %s:%d\n", name, *value)); >+ DEBUG(10,("account_policy_get_internal: %s:%d\n", passdb_call ? key : name, *value)); > return True; > } > >+/**************************************************************************** >+Get an account policy from the tdb >+older tdb call, only used during migration >+****************************************************************************/ > >+BOOL account_policy_get(int field, uint32 *value) >+{ >+ return account_policy_get_internal(field, value, False); >+} >+ > /**************************************************************************** >+Get an account policy from the tdb >+passdb call > ****************************************************************************/ >-BOOL account_policy_set(int field, uint32 value) >+ >+BOOL db_account_policy_get(int field, uint32 *value) > { >+ return account_policy_get_internal(field, value, True); >+} >+ >+/**************************************************************************** >+Get an account policy from a (migrated tdb) >+****************************************************************************/ >+ >+BOOL db_account_policy_set(int field, uint32 value) >+{ > fstring name; >+ pstring key; > >- if(!init_account_policy())return False; >+ if (!init_account_policy()) >+ return False; > > fstrcpy(name, decode_account_policy_name(field)); > if (!*name) { >@@ -174,12 +488,74 @@ > return False; > } > >- if (!tdb_store_uint32(tdb, name, value)) { >- DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u", field, name, value)); >+ slprintf(key, sizeof(key)-1, "%s/%s", AP_PREFIX, name); >+ >+ if (!tdb_store_uint32(tdb, key, value)) { >+ DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u\n", field, key, value)); > return False; > } >+ DEBUG(10,("db_account_policy_set: %s:%d\n", key, value)); >+ return True; >+} > >- DEBUG(10,("account_policy_set: %s:%d\n", name, value)); >- >+/**************************************************************************** >+Set an account policy (set in the cache if a cached policy) >+****************************************************************************/ >+ >+BOOL cache_account_policy_set(int field, uint32 value) >+{ >+ int i; >+ uint32 lastset; >+ >+ for (i=0; account_policies[i].field; i++) { >+ >+ if (account_policies[i].field == field && >+ (account_policies[i].cached == True)) { >+ >+ DEBUG(10,("cache_account_policy_set: updating account pol cache\n")); >+ >+ if (!db_account_policy_set(field, value)) { >+ return False; >+ } >+ >+ if (!account_policy_lastset(&lastset, True)) { >+ DEBUG(10,("cache_account_policy_set: failed to call account_policies_lastset\n")); >+ return False; >+ } >+ >+ DEBUG(10,("cache_account_policy_set: cache will expire at: %s\n", http_timestring(lastset+AP_TTL))); >+ } >+ } >+ > return True; > } >+ >+/**************************************************************************** >+Get an account policy (get from the cache if a cached policy) >+****************************************************************************/ >+ >+BOOL cache_account_policy_get(int field, uint32 *value) >+{ >+ int i; >+ uint32 lastset; >+ >+ if (!account_policy_lastset(&lastset, False)) { >+ DEBUG(10,("cache_account_policy_get: failed to call account_policies_lastset\n")); >+ return False; >+ } >+ >+ if ((lastset + AP_TTL) < (uint32)time(NULL) ) { >+ DEBUG(10,("cache_account_policy_get: no valid cache entry (cache expired)\n")); >+ return False; >+ } >+ >+ for (i=0; account_policies[i].field; i++) { >+ if (account_policies[i].field == field && >+ (account_policies[i].cached == True)) { >+ return db_account_policy_get(field, value); >+ } >+ } >+ >+ return False; >+} >+ >Index: source/lib/smbldap.c >=================================================================== >--- source/lib/smbldap.c (revision 3080) >+++ source/lib/smbldap.c (working copy) >@@ -208,6 +208,15 @@ > { LDAP_ATTR_LIST_END, NULL } > }; > >+/* attributes used for account policies */ >+ >+ATTRIB_MAP_ENTRY acctpol_attr_list[] = { >+ { LDAP_ATTR_OBJCLASS, "objectClass" }, >+ { LDAP_ATTR_ACCOUNT_POLICY_NAME,"sambaAccountPolicyName" }, >+ { LDAP_ATTR_ACCOUNT_POLICY_VAL, "sambaAccountPolicyValue" }, >+ { LDAP_ATTR_LIST_END, NULL }, >+}; >+ > /********************************************************************** > perform a simple table lookup and return the attribute name > **********************************************************************/ >@@ -348,6 +357,8 @@ > int max_len) > { > char **values; >+ >+ DEBUG(0,("SUSE: attribute is: %s\n", attribute)); > > if ( !attribute ) > return False; >@@ -1232,6 +1243,85 @@ > } > > /********************************************************************** >+ Add the account-policies below the sambaDomain object to LDAP, >+ so we don't have to search for this stuff again. >+ >+ This is a once-add operation for now. >+*********************************************************************/ >+static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state, >+ const char *domain_name) >+{ >+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; >+ int i, ldap_op, policy_default, rc; >+ const char *policy_string = NULL; >+ const char *policy_comment = NULL; >+ pstring dn; >+ fstring policy_default_str; >+ >+ DEBUG(3,("Adding new account policies for domain\n")); >+ ldap_op = LDAP_MOD_ADD; >+ >+ for (i=1; decode_account_policy_name(i) != NULL; i++) { >+ LDAPMod **mods = NULL; >+ >+ policy_string = decode_account_policy_name(i); >+ if (!policy_string) { >+ DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n")); >+ return ntstatus; >+ } >+ >+ policy_comment = account_policy_get_comment(i); >+ if (!policy_comment) { >+ DEBUG(0,("add_new_domain_account_policies: no description for policy found\n")); >+ return ntstatus; >+ } >+ >+ if (!account_policy_get_default(i, &policy_default)) { >+ DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n")); >+ return ntstatus; >+ } >+ >+ slprintf(policy_default_str, sizeof(policy_default_str) - 1, "%i", policy_default); >+ >+ pstr_sprintf(dn, "%s=%s,%s=%s,%s", >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_NAME), policy_string, >+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), get_global_sam_name(), >+ lp_ldap_suffix()); >+ >+ smbldap_set_mod( &mods, ldap_op, "objectClass", LDAP_OBJ_ACCOUNT_POLICY ); >+ >+ smbldap_set_mod( &mods, ldap_op, >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_NAME), >+ policy_string); >+ >+ smbldap_set_mod( &mods, ldap_op, >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_VAL), >+ policy_default_str); >+ >+ smbldap_set_mod( &mods, ldap_op, "description", policy_comment); >+ >+ rc = smbldap_add(ldap_state, dn, mods); >+ >+ if (rc!=LDAP_SUCCESS) { >+ char *ld_error = NULL; >+ ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); >+ DEBUG(1,("failed to add account policy dn= %s with: %s\n\t%s\n", >+ dn, ldap_err2string(rc), >+ ld_error?ld_error:"unknown")); >+ SAFE_FREE(ld_error); >+ >+ ldap_mods_free(mods, True); >+ return ntstatus; >+ } >+ >+ DEBUG(2,("added: domain account policy = [%s] in the LDAP database\n", policy_string)); >+ ldap_mods_free(mods, True); >+ } >+ >+ return NT_STATUS_OK; >+} >+ >+/********************************************************************** > Add the sambaDomain to LDAP, so we don't have to search for this stuff > again. This is a once-add operation for now. > >@@ -1385,7 +1477,8 @@ > DEBUG(3, ("Got no domain info entries for domain\n")); > ldap_msgfree(*result); > *result = NULL; >- if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) { >+ if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name)) >+ && NT_STATUS_IS_OK(ret = add_new_domain_account_policies(ldap_state, domain_name))) { > return smbldap_search_domain_info(ldap_state, result, domain_name, False); > } > else { >Index: source/rpc_server/srv_samr_nt.c >=================================================================== >--- source/rpc_server/srv_samr_nt.c (revision 3080) >+++ source/rpc_server/srv_samr_nt.c (working copy) >@@ -2041,19 +2041,19 @@ > switch (q_u->switch_value) { > case 0x01: > >- account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp); >+ pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp); > min_pass_len = account_policy_temp; > >- account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp); > pass_hist = account_policy_temp; > >- account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); >+ pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); > flag = account_policy_temp; > >- account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp); >+ pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp); > u_expire = account_policy_temp; > >- account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp); >+ pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp); > u_min_age = account_policy_temp; > > unix_to_nt_time_abs(&nt_expire, u_expire); >@@ -2086,7 +2086,7 @@ > num_users, num_groups, num_aliases); > break; > case 0x03: >- account_policy_get(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout); >+ pdb_get_account_policy(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout); > unix_to_nt_time_abs(&nt_logout, u_logout); > > init_unk_info3(&ctr->info.inf3, nt_logout); >@@ -2101,13 +2101,13 @@ > init_unk_info7(&ctr->info.inf7); > break; > case 0x0c: >- account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); >+ pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); > u_lock_duration = account_policy_temp * 60; > >- account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp); >+ pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); > u_reset_time = account_policy_temp * 60; > >- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); >+ pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); > lockout = account_policy_temp; > > unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration); >@@ -4294,19 +4294,19 @@ > > switch (q_u->switch_value) { > case 0x01: >- account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp); >+ pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp); > min_pass_len = account_policy_temp; > >- account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp); > pass_hist = account_policy_temp; > >- account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); >+ pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); > flag = account_policy_temp; > >- account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp); >+ pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp); > u_expire = account_policy_temp; > >- account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp); >+ pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp); > u_min_age = account_policy_temp; > > unix_to_nt_time_abs(&nt_expire, u_expire); >@@ -4339,7 +4339,7 @@ > num_users, num_groups, num_aliases); > break; > case 0x03: >- account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp); >+ pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp); > u_logout = account_policy_temp; > > unix_to_nt_time_abs(&nt_logout, u_logout); >@@ -4356,13 +4356,13 @@ > init_unk_info7(&ctr->info.inf7); > break; > case 0x0c: >- account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); >+ pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); > u_lock_duration = account_policy_temp * 60; > >- account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp); >+ pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); > u_reset_time = account_policy_temp * 60; > >- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); >+ pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); > lockout = account_policy_temp; > > unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration); >@@ -4406,17 +4406,17 @@ > u_expire=nt_time_to_unix_abs(&q_u->ctr->info.inf1.expire); > u_min_age=nt_time_to_unix_abs(&q_u->ctr->info.inf1.min_passwordage); > >- account_policy_set(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password); >- account_policy_set(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history); >- account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag); >- account_policy_set(AP_MAX_PASSWORD_AGE, (int)u_expire); >- account_policy_set(AP_MIN_PASSWORD_AGE, (int)u_min_age); >+ pdb_set_account_policy(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password); >+ pdb_set_account_policy(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history); >+ pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag); >+ pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (int)u_expire); >+ pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (int)u_min_age); > break; > case 0x02: > break; > case 0x03: > u_logout=nt_time_to_unix_abs(&q_u->ctr->info.inf3.logout); >- account_policy_set(AP_TIME_TO_LOGOUT, (int)u_logout); >+ pdb_set_account_policy(AP_TIME_TO_LOGOUT, (int)u_logout); > break; > case 0x05: > break; >@@ -4428,9 +4428,9 @@ > u_lock_duration=nt_time_to_unix_abs(&q_u->ctr->info.inf12.duration)/60; > u_reset_time=nt_time_to_unix_abs(&q_u->ctr->info.inf12.reset_count)/60; > >- account_policy_set(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); >- account_policy_set(AP_RESET_COUNT_TIME, (int)u_reset_time); >- account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout); >+ pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); >+ pdb_set_account_policy(AP_RESET_COUNT_TIME, (int)u_reset_time); >+ pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout); > break; > default: > return NT_STATUS_INVALID_INFO_CLASS; >Index: source/passdb/pdb_ldap.c >=================================================================== >--- source/passdb/pdb_ldap.c (revision 3080) >+++ source/passdb/pdb_ldap.c (working copy) >@@ -722,7 +725,7 @@ > ZERO_STRUCT(smbntpwd); > } > >- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); > if (pwHistLen > 0){ > uint8 *pwhist = NULL; > int i; >@@ -1068,7 +1077,7 @@ > > if (need_update(sampass, PDB_PWHISTORY)) { > int pwHistLen = 0; >- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); > if (pwHistLen == 0) { > /* Remove any password history from the LDAP store. */ > memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */ >@@ -1133,7 +1144,7 @@ > uint16 badcount = pdb_get_bad_password_count(sampass); > time_t badtime = pdb_get_bad_password_time(sampass); > uint32 pol; >- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol); >+ pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol); > > DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n", > (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime)); >@@ -2804,6 +2819,247 @@ > return NT_STATUS_OK; > } > >+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, int *value) >+{ >+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; >+ LDAPMessage *result = NULL; >+ LDAPMessage *entry = NULL; >+ int count; >+ int rc; >+ pstring filter, base; >+ char **vals; >+ const char *policy_string = NULL; >+ >+ struct ldapsam_privates *ldap_state = >+ (struct ldapsam_privates *)methods->private_data; >+ >+ char *attrs[] = { >+ (char *)get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_NAME), >+ (char *)get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_VAL), >+ NULL >+ }; >+ >+ if (cache_account_policy_get(policy_index, value)) { >+ DEBUG(10,("ldapsam_get_account_policy: got valid value from cache\n")); >+ return NT_STATUS_OK; >+ } >+ >+ policy_string = decode_account_policy_name(policy_index); >+ if (!policy_string) { >+ DEBUG(0,("ldapsam_get_account_policy: invalid policy\n")); >+ return ntstatus; >+ } >+ >+ pstr_sprintf(filter, "(&(objectclass=%s)(%s=%s))", >+ LDAP_OBJ_ACCOUNT_POLICY, >+ get_attr_key2string(acctpol_attr_list, >+ LDAP_ATTR_ACCOUNT_POLICY_NAME), policy_string); >+ >+ pstr_sprintf(base, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), >+ get_global_sam_name(), lp_ldap_suffix()); >+ >+search: >+ rc = smbldap_search(ldap_state->smbldap_state, base, >+ LDAP_SCOPE_ONE, filter, attrs, 0, &result); >+ >+ if (rc != LDAP_SUCCESS) >+ return ntstatus; >+ >+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, >+ result); >+ >+ if (count < 1) { >+ int tmp_val; >+ BOOL found_tdb = False; >+ >+ DEBUG(3,("ldapsam_get_account_policy: no entry for that policy in ldap found\n")); >+ >+ /* do not fail here but warn */ >+ if (!account_policy_get(policy_index, &tmp_val) && !(db_account_policy_get(policy_index, &tmp_val))) { >+ /* already migrated ? */ >+ DEBUG(10,("ldapsam_get_account_policy: failed to get account_policy from tdb\n")); >+ } else { >+ DEBUG(10,("ldapsam_get_account_policy: reusing tdb value\n")); >+ found_tdb = True; >+ } >+ >+ if (!found_tdb && !account_policy_get_default(policy_index, &tmp_val)) { >+ DEBUG(1,("ldapsam_get_account_policy: failed to get default value for account_policy\n")); >+ ldap_msgfree(result); >+ return ntstatus; >+ } >+ >+ if (!pdb_set_account_policy(policy_index, tmp_val)) { >+ DEBUG(1,("ldapsam_get_account_policy: failed to set account_policy\n")); >+ ldap_msgfree(result); >+ return ntstatus; >+ } >+ >+ DEBUG(3,("ldapsam_get_account_policy: set account policy value based on %s value.\n", >+ found_tdb ? "tdb":"default")); >+ >+ ldap_msgfree(result); >+ goto search; >+ } >+ >+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); >+ >+ if (!entry) { >+ ldap_msgfree(result); >+ return NT_STATUS_UNSUCCESSFUL; >+ } >+ >+ vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_VAL)); >+ >+ if (vals == NULL) >+ goto out; >+ >+ *value = (uint32)atol(vals[0]); >+ >+ if (!cache_account_policy_set(policy_index, *value)) { >+ DEBUG(0,("failed to update local tdb as a cache\n")); >+ return ntstatus; >+ } >+ >+ ntstatus = NT_STATUS_OK; >+ >+out: >+ ldap_value_free(vals); >+ ldap_msgfree(result); >+ >+ return ntstatus; >+} >+ >+static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, int value) >+{ >+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; >+ LDAPMessage *result = NULL; >+ LDAPMessage *entry = NULL; >+ int count; >+ int rc; >+ pstring filter, base, dn; >+ int modop; >+ LDAPMod **mods = NULL; >+ fstring value_string; >+ char *old_dn = NULL; >+ const char *policy_string = NULL; >+ const char *policy_description = NULL; >+ >+ struct ldapsam_privates *ldap_state = >+ (struct ldapsam_privates *)methods->private_data; >+ >+ char *attrs[] = { >+ (char *)get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_NAME), >+ (char *)get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_VAL), >+ NULL >+ }; >+ >+ policy_string = decode_account_policy_name(policy_index); >+ if (!policy_string) { >+ DEBUG(0,("ldapsam_set_account_policy: invalid policy\n")); >+ return ntstatus; >+ } >+ >+ policy_description = account_policy_get_comment(policy_index); >+ if (!policy_description) { >+ DEBUG(0,("ldapsam_set_account_policy: no description for policy found\n")); >+ return ntstatus; >+ } >+ >+ pstr_sprintf(filter, "(&(objectclass=%s)(%s=%s))", >+ LDAP_OBJ_ACCOUNT_POLICY, >+ get_attr_key2string(acctpol_attr_list, >+ LDAP_ATTR_ACCOUNT_POLICY_NAME), policy_string); >+ >+ pstr_sprintf(base, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), >+ get_global_sam_name(), lp_ldap_suffix()); >+ >+ rc = smbldap_search(ldap_state->smbldap_state, base, >+ LDAP_SCOPE_ONE, filter, attrs, 0, &result); >+ >+ if (rc != LDAP_SUCCESS) >+ return ntstatus; >+ >+ count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); >+ >+ slprintf(value_string, sizeof(value_string) - 1, "%i", value); >+ >+ if (count == 1) { >+ >+ modop = LDAP_MOD_REPLACE; >+ >+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); >+ >+ if (!entry) { >+ ldap_msgfree(result); >+ return NT_STATUS_UNSUCCESSFUL; >+ } >+ >+ old_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); >+ if (!old_dn) { >+ ldap_msgfree(result); >+ return ntstatus; >+ } >+ >+ smbldap_set_mod(&mods, modop, >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_VAL), >+ value_string); >+ >+ rc = smbldap_modify(ldap_state->smbldap_state, old_dn, mods); >+ >+ } else { >+ >+ modop = LDAP_MOD_ADD; >+ >+ pstr_sprintf(dn, "%s=%s,%s=%s,%s", >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_NAME), policy_string, >+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), get_global_sam_name(), >+ lp_ldap_suffix()); >+ >+ smbldap_set_mod( &mods, modop, "objectClass", LDAP_OBJ_ACCOUNT_POLICY ); >+ >+ smbldap_make_mod( ldap_state->smbldap_state->ldap_struct, entry, &mods, >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_NAME), >+ policy_string); >+ >+ smbldap_make_mod( ldap_state->smbldap_state->ldap_struct, entry, &mods, >+ get_attr_key2string(acctpol_attr_list, LDAP_ATTR_ACCOUNT_POLICY_VAL), >+ value_string); >+ >+ smbldap_make_mod( ldap_state->smbldap_state->ldap_struct, entry, &mods, >+ "description", >+ policy_description); >+ >+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods); >+ } >+ >+ ldap_mods_free(mods, True); >+ ldap_msgfree(result); >+ >+ if (rc != LDAP_SUCCESS) { >+ char *ld_error = NULL; >+ ldap_get_option(ldap_state->smbldap_state->ldap_struct, >+ LDAP_OPT_ERROR_STRING,&ld_error); >+ >+ DEBUG(0, ("ldapsam_set_account_policy: Could not set account policy " >+ "for %s, error: %s (%s)\n", dn, ldap_err2string(rc), >+ ld_error?ld_error:"unknown")); >+ SAFE_FREE(ld_error); >+ SAFE_FREE(old_dn); >+ return ntstatus; >+ } >+ >+ SAFE_FREE(old_dn); >+ >+ if (!cache_account_policy_set(policy_index, value)) { >+ DEBUG(0,("failed to update local tdb as a cache\n")); >+ return ntstatus; >+ } >+ >+ return NT_STATUS_OK; >+} >+ > /********************************************************************** > Housekeeping > *********************************************************************/ >@@ -2857,6 +3113,9 @@ > (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry; > (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping; > >+ (*pdb_method)->get_account_policy = ldapsam_get_account_policy; >+ (*pdb_method)->set_account_policy = ldapsam_set_account_policy; >+ > /* TODO: Setup private data and free */ > > ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state)); >Index: source/passdb/passdb.c >=================================================================== >--- source/passdb/passdb.c (revision 3080) >+++ source/passdb/passdb.c (working copy) >@@ -1883,7 +1886,7 @@ > } > > /* Change from V1 is addition of password history field. */ >- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); > if (pwHistLen) { > char *pw_hist = malloc(pwHistLen * PW_HISTORY_ENTRY_LEN); > if (!pw_hist) { >@@ -2091,7 +2094,7 @@ > nt_pw_len = 0; > } > >- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); > nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len); > if (pwHistLen && nt_pw_hist && nt_pw_hist_len) { > nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN; >@@ -2278,8 +2281,8 @@ > return True; > } > >- if (!account_policy_get(AP_RESET_COUNT_TIME, &resettime)) { >- DEBUG(0, ("pdb_update_bad_password_count: account_policy_get failed.\n")); >+ if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) { >+ DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n")); > return False; > } > >@@ -2320,8 +2323,8 @@ > return True; > } > >- if (!account_policy_get(AP_LOCK_ACCOUNT_DURATION, &duration)) { >- DEBUG(0, ("pdb_update_autolock_flag: account_policy_get failed.\n")); >+ if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) { >+ DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n")); > return False; > } > >@@ -2369,9 +2372,9 @@ > return False; > > /* Retrieve the account lockout policy */ >- if (!account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, >+ if (!pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, > &account_policy_lockout)) { >- DEBUG(0, ("pdb_increment_bad_password_count: account_policy_get failed.\n")); >+ DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n")); > return False; > } > >Index: source/passdb/pdb_get_set.c >=================================================================== >--- source/passdb/pdb_get_set.c (revision 3080) >+++ source/passdb/pdb_get_set.c (working copy) >@@ -1141,7 +1142,7 @@ > if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) > return False; > >- if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) >+ if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) > || (expire==(uint32)-1) || (expire == 0)) { > if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED)) > return False; >@@ -1152,7 +1153,7 @@ > return False; > } > >- if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age) >+ if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age) > || (min_age==(uint32)-1)) { > if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED)) > return False; >@@ -1207,7 +1208,7 @@ > if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { > uchar *pwhistory; > uint32 pwHistLen; >- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); >+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); > if (pwHistLen != 0){ > uint32 current_history_len; > /* We need to make sure we don't have a race condition here - the >Index: source/passdb/pdb_interface.c >=================================================================== >--- source/passdb/pdb_interface.c (revision 3080) >+++ source/passdb/pdb_interface.c (working copy) >@@ -601,6 +601,35 @@ > enum_alias_memberships(context->pdb_methods, sid, aliases, > num); > } >+ >+static NTSTATUS context_get_account_policy(struct pdb_context *context, >+ int policy_index, int *value) >+{ >+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; >+ >+ if ((!context) || (!context->pdb_methods)) { >+ DEBUG(0, ("invalid pdb_context specified!\n")); >+ return ret; >+ } >+ >+ return context->pdb_methods->get_account_policy(context->pdb_methods, >+ policy_index, value); >+} >+ >+static NTSTATUS context_set_account_policy(struct pdb_context *context, >+ int policy_index, int value) >+{ >+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; >+ >+ if ((!context) || (!context->pdb_methods)) { >+ DEBUG(0, ("invalid pdb_context specified!\n")); >+ return ret; >+ } >+ >+ return context->pdb_methods->set_account_policy(context->pdb_methods, >+ policy_index, value); >+} >+ > > /****************************************************************** > Free and cleanup a pdb context, any associated data and anything >@@ -729,6 +758,9 @@ > (*context)->pdb_enum_aliasmem = context_enum_aliasmem; > (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; > >+ (*context)->pdb_get_account_policy = context_get_account_policy; >+ (*context)->pdb_set_account_policy = context_set_account_policy; >+ > (*context)->free_fn = free_pdb_context; > > return NT_STATUS_OK; >@@ -1139,6 +1171,30 @@ > aliases, num)); > } > >+BOOL pdb_get_account_policy(int policy_index, int *value) >+{ >+ struct pdb_context *pdb_context = pdb_get_static_context(False); >+ >+ if (!pdb_context) { >+ return False; >+ } >+ >+ return NT_STATUS_IS_OK(pdb_context-> >+ pdb_get_account_policy(pdb_context, policy_index, value)); >+} >+ >+BOOL pdb_set_account_policy(int policy_index, int value) >+{ >+ struct pdb_context *pdb_context = pdb_get_static_context(False); >+ >+ if (!pdb_context) { >+ return False; >+ } >+ >+ return NT_STATUS_IS_OK(pdb_context-> >+ pdb_set_account_policy(pdb_context, policy_index, value)); >+} >+ > /*************************************************************** > Initialize the static context (at smbd startup etc). > >@@ -1196,6 +1252,16 @@ > return; /* NT_STATUS_NOT_IMPLEMENTED; */ > } > >+static NTSTATUS pdb_default_get_account_policy(struct pdb_methods *methods, int policy_index, int *value) >+{ >+ return db_account_policy_get(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; >+} >+ >+static NTSTATUS pdb_default_set_account_policy(struct pdb_methods *methods, int policy_index, int value) >+{ >+ return db_account_policy_set(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; >+} >+ > NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) > { > *methods = talloc(mem_ctx, sizeof(struct pdb_methods)); >@@ -1232,6 +1298,8 @@ > (*methods)->del_aliasmem = pdb_default_del_aliasmem; > (*methods)->enum_aliasmem = pdb_default_enum_aliasmem; > (*methods)->enum_alias_memberships = pdb_default_alias_memberships; >+ (*methods)->get_account_policy = pdb_default_get_account_policy; >+ (*methods)->set_account_policy = pdb_default_set_account_policy; > > return NT_STATUS_OK; > } >Index: source/include/passdb.h >=================================================================== >--- source/include/passdb.h (revision 3080) >+++ source/include/passdb.h (working copy) >@@ -241,7 +241,7 @@ > * this SAMBA will load. Increment this if *ANY* changes are made to the interface. > */ > >-#define PASSDB_INTERFACE_VERSION 5 >+#define PASSDB_INTERFACE_VERSION 6 > > typedef struct pdb_context > { >@@ -327,6 +327,12 @@ > DOM_SID **aliases, > int *num); > >+ NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context, >+ int policy_index, int *value); >+ >+ NTSTATUS (*pdb_set_account_policy)(struct pdb_context *context, >+ int policy_index, int value); >+ > void (*free_fn)(struct pdb_context **); > > TALLOC_CTX *mem_ctx; >@@ -411,6 +417,12 @@ > const DOM_SID *sid, > DOM_SID **aliases, int *num); > >+ NTSTATUS (*get_account_policy)(struct pdb_methods *methods, >+ int policy_index, int *value); >+ >+ NTSTATUS (*set_account_policy)(struct pdb_methods *methods, >+ int policy_index, int value); >+ > void *private_data; /* Private data of some kind */ > > void (*free_private_data)(void **); >Index: source/include/smbldap.h >=================================================================== >--- source/include/smbldap.h (revision 3080) >+++ source/include/smbldap.h (working copy) >@@ -38,6 +38,7 @@ > #define LDAP_OBJ_IDPOOL "sambaUnixIdPool" > #define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry" > #define LDAP_OBJ_SID_ENTRY "sambaSidEntry" >+#define LDAP_OBJ_ACCOUNT_POLICY "sambaAccountPolicy" > > #define LDAP_OBJ_ACCOUNT "account" > #define LDAP_OBJ_POSIXACCOUNT "posixAccount" >@@ -97,6 +98,8 @@ > #define LDAP_ATTR_SID_LIST 40 > #define LDAP_ATTR_MOD_TIMESTAMP 41 > #define LDAP_ATTR_LOGON_HOURS 42 >+#define LDAP_ATTR_ACCOUNT_POLICY_NAME 43 >+#define LDAP_ATTR_ACCOUNT_POLICY_VAL 44 > > typedef struct _attrib_map_entry { > int attrib; >@@ -115,6 +118,7 @@ > extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[]; > extern ATTRIB_MAP_ENTRY idpool_attr_list[]; > extern ATTRIB_MAP_ENTRY sidmap_attr_list[]; >+extern ATTRIB_MAP_ENTRY acctpol_attr_list[]; > > /* Function declarations -- not included in proto.h so we don't > have to worry about LDAP structure types */ >Index: source/utils/pdbedit.c >=================================================================== >--- source/utils/pdbedit.c (revision 3080) >+++ source/utils/pdbedit.c (working copy) >@@ -119,6 +119,27 @@ > } > > /********************************************************* >+ Add all currently available account policy from tdb to one backend >+ ********************************************************/ >+ >+static int export_account_policies (struct pdb_context *in, struct pdb_context *out) >+{ >+ int i; >+ >+ for (i=1; decode_account_policy_name(i) != NULL; i++) { >+ uint32 policy_value; >+ if (NT_STATUS_IS_ERR(in->pdb_get_account_policy(in, i, &policy_value))) { >+ fprintf(stderr, "Can't get account policy from tdb\n"); >+ return -1; >+ } >+ out->pdb_set_account_policy(out, i, policy_value); >+ } >+ >+ return 0; >+} >+ >+ >+/********************************************************* > Print info from sam structure > **********************************************************/ > >@@ -639,6 +660,7 @@ > static char *backend_in = NULL; > static char *backend_out = NULL; > static BOOL transfer_groups = False; >+ static BOOL transfer_account_policies = False; > static BOOL force_initialised_password = False; > static char *logon_script = NULL; > static char *profile_path = NULL; >@@ -676,6 +698,7 @@ > {"import", 'i', POPT_ARG_STRING, &backend_in, 0, "import user accounts from this backend", NULL}, > {"export", 'e', POPT_ARG_STRING, &backend_out, 0, "export user accounts to this backend", NULL}, > {"group", 'g', POPT_ARG_NONE, &transfer_groups, 0, "use -i and -e for groups", NULL}, >+ {"policies", 'y', POPT_ARG_NONE, &transfer_account_policies, 0, "use -i and -e to move account policies between backends", NULL}, > {"account-policy", 'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL}, > {"value", 'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL}, > {"account-control", 'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL}, >@@ -770,13 +793,14 @@ > SAFE_FREE(apn); > exit(1); > } >- if (!account_policy_get(field, &value)) { >+ if (!pdb_get_account_policy(field, &value)) { > fprintf(stderr, "valid account policy, but unable to fetch value!\n"); >- exit(1); >+ if (!account_policy_value_set) >+ exit(1); > } > if (account_policy_value_set) { > printf("account policy value for %s was %u\n", account_policy, value); >- if (!account_policy_set(field, account_policy_value)) { >+ if (!pdb_set_account_policy(field, account_policy_value)) { > fprintf(stderr, "valid account policy, but unable to set value!\n"); > exit(1); > } >@@ -807,8 +831,11 @@ > } else { > bout = bdef; > } >- if (transfer_groups) { >+ if (transfer_account_policies) { > if (!(checkparms & BIT_USER)) >+ return export_account_policies(bin, bout); >+ } else if (transfer_groups) { >+ if (!(checkparms & BIT_USER)) > return export_groups(bin, bout); > } else { > if (checkparms & BIT_USER) >Index: examples/LDAP/samba.schema >=================================================================== >--- examples/LDAP/samba.schema (revision 2772) >+++ examples/LDAP/samba.schema (working copy) >@@ -389,7 +389,17 @@ > EQUALITY caseIgnoreIA5Match > SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) > >+attributetype ( 1.3.6.1.4.1.7165.2.1.56 NAME 'sambaAccountPolicyName' >+ DESC 'Account Policy Name' >+ EQUALITY caseIgnoreMatch >+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE ) > >+attributetype ( 1.3.6.1.4.1.7165.2.1.57 NAME 'sambaAccountPolicyValue' >+ DESC 'Account Policy Value' >+ EQUALITY integerMatch >+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) >+ >+ > ####################################################################### > ## objectClasses used by Samba 3.0 schema ## > ####################################################################### >@@ -478,3 +488,8 @@ > MUST ( sambaSID ) > MAY ( sambaPrivilegeList ) ) > >+objectclass ( 1.3.6.1.4.1.7165.2.2.15 NAME 'sambaAccountPolicy' SUP top STRUCTURAL >+ DESC 'Samba Account Policy' >+ MUST ( sambaAccountPolicyName $ sambaAccountPolicyValue ) >+ MAY ( description ) ) >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 1913
:
731
|
736
|
737