summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-11-03 23:59:45 +0000
committerJeremy Allison <jra@samba.org>2003-11-03 23:59:45 +0000
commit3d7fe188813371e2683dc0e47a4a3e14aaf61194 (patch)
tree171192db0f940cf243be0e114e21b1025b5a8c23 /source3/passdb
parentc8e7fc1fcd988d55ab9480c63109f3665c147962 (diff)
downloadsamba-3d7fe188813371e2683dc0e47a4a3e14aaf61194.tar.gz
samba-3d7fe188813371e2683dc0e47a4a3e14aaf61194.tar.bz2
samba-3d7fe188813371e2683dc0e47a4a3e14aaf61194.zip
TDBSAM update code from Aur?lien Degr?mont <adegremont@idealx.com>.
Adds support for an additional field (uint32) which represents the lockout duration. I think this should be stored as an abolute UNIX time_t that specifies when the lockout should end - set it when the lockout is imposed. This new code also updates the on disk tdb version on load. Being merged into HEAD so Simo can add any other changes he wants before being back-ported to SAMBA_3_0. Jeremy. (This used to be commit 0eea3f22aba25c1d0a8800bb1725238422cb30eb)
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/passdb.c452
-rw-r--r--source3/passdb/pdb_tdb.c184
2 files changed, 620 insertions, 16 deletions
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 9d8f600eea..48f7546394 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -1288,7 +1288,8 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_
Marshall/unmarshall SAM_ACCOUNT structs.
*********************************************************************/
-#define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
+#define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
/**********************************************************************
Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
@@ -1296,6 +1297,21 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_
BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
{
+ return(init_sam_from_buffer_v1(sampass, buf, buflen));
+}
+
+/**********************************************************************
+ Intialize a BYTE buffer from a SAM_ACCOUNT struct
+ *********************************************************************/
+
+uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
+{
+ return(init_buffer_from_sam_v1(buf, sampass, size_only));
+}
+
+
+BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+{
/* times are stored as 32bit integer
take care on system with 64bit wide time_t
@@ -1338,7 +1354,7 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
}
/* unpack the buffer into variables */
- len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING,
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0,
&logon_time,
&logoff_time,
&kickoff_time,
@@ -1468,11 +1484,425 @@ done:
return ret;
}
-/**********************************************************************
- Intialize a BYTE buffer from a SAM_ACCOUNT struct
- *********************************************************************/
-uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
+uint32 init_buffer_from_sam_v0 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
+{
+ size_t len, buflen;
+
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+
+ uint32 user_rid, group_rid;
+
+ const char *username;
+ const char *domain;
+ const char *nt_username;
+ const char *dir_drive;
+ const char *unknown_str;
+ const char *munged_dial;
+ const char *fullname;
+ const char *homedir;
+ const char *logon_script;
+ const char *profile_path;
+ const char *acct_desc;
+ const char *workstations;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ const uint8 *lm_pw;
+ const uint8 *nt_pw;
+ uint32 lm_pw_len = 16;
+ uint32 nt_pw_len = 16;
+
+ /* do we have a valid SAM_ACCOUNT pointer? */
+ if (sampass == NULL) {
+ DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n"));
+ return -1;
+ }
+
+ *buf = NULL;
+ buflen = 0;
+
+ logon_time = (uint32)pdb_get_logon_time(sampass);
+ logoff_time = (uint32)pdb_get_logoff_time(sampass);
+ kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
+ pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
+ pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
+ pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
+
+ user_rid = pdb_get_user_rid(sampass);
+ group_rid = pdb_get_group_rid(sampass);
+
+ username = pdb_get_username(sampass);
+ if (username)
+ username_len = strlen(username) +1;
+ else
+ username_len = 0;
+
+ domain = pdb_get_domain(sampass);
+ if (domain)
+ domain_len = strlen(domain) +1;
+ else
+ domain_len = 0;
+
+ nt_username = pdb_get_nt_username(sampass);
+ if (nt_username)
+ nt_username_len = strlen(nt_username) +1;
+ else
+ nt_username_len = 0;
+
+ fullname = pdb_get_fullname(sampass);
+ if (fullname)
+ fullname_len = strlen(fullname) +1;
+ else
+ fullname_len = 0;
+
+ /*
+ * Only updates fields which have been set (not defaults from smb.conf)
+ */
+
+ if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE))
+ dir_drive = pdb_get_dir_drive(sampass);
+ else
+ dir_drive = NULL;
+ if (dir_drive)
+ dir_drive_len = strlen(dir_drive) +1;
+ else
+ dir_drive_len = 0;
+
+ if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME))
+ homedir = pdb_get_homedir(sampass);
+ else
+ homedir = NULL;
+ if (homedir)
+ homedir_len = strlen(homedir) +1;
+ else
+ homedir_len = 0;
+
+ if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT))
+ logon_script = pdb_get_logon_script(sampass);
+ else
+ logon_script = NULL;
+ if (logon_script)
+ logon_script_len = strlen(logon_script) +1;
+ else
+ logon_script_len = 0;
+
+ if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE))
+ profile_path = pdb_get_profile_path(sampass);
+ else
+ profile_path = NULL;
+ if (profile_path)
+ profile_path_len = strlen(profile_path) +1;
+ else
+ profile_path_len = 0;
+
+ lm_pw = pdb_get_lanman_passwd(sampass);
+ if (!lm_pw)
+ lm_pw_len = 0;
+
+ nt_pw = pdb_get_nt_passwd(sampass);
+ if (!nt_pw)
+ nt_pw_len = 0;
+
+ acct_desc = pdb_get_acct_desc(sampass);
+ if (acct_desc)
+ acct_desc_len = strlen(acct_desc) +1;
+ else
+ acct_desc_len = 0;
+
+ workstations = pdb_get_workstations(sampass);
+ if (workstations)
+ workstations_len = strlen(workstations) +1;
+ else
+ workstations_len = 0;
+
+ unknown_str = NULL;
+ unknown_str_len = 0;
+
+ munged_dial = pdb_get_munged_dial(sampass);
+ if (munged_dial)
+ munged_dial_len = strlen(munged_dial) +1;
+ else
+ munged_dial_len = 0;
+
+ /* one time to get the size needed */
+ len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V0,
+ logon_time,
+ logoff_time,
+ kickoff_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time,
+ username_len, username,
+ domain_len, domain,
+ nt_username_len, nt_username,
+ fullname_len, fullname,
+ homedir_len, homedir,
+ dir_drive_len, dir_drive,
+ logon_script_len, logon_script,
+ profile_path_len, profile_path,
+ acct_desc_len, acct_desc,
+ workstations_len, workstations,
+ unknown_str_len, unknown_str,
+ munged_dial_len, munged_dial,
+ user_rid,
+ group_rid,
+ lm_pw_len, lm_pw,
+ nt_pw_len, nt_pw,
+ pdb_get_acct_ctrl(sampass),
+ pdb_get_unknown_3(sampass),
+ pdb_get_logon_divs(sampass),
+ pdb_get_hours_len(sampass),
+ MAX_HOURS_LEN, pdb_get_hours(sampass),
+ pdb_get_bad_password_count(sampass),
+ pdb_get_logon_count(sampass),
+ pdb_get_unknown_6(sampass));
+
+
+ if (size_only)
+ return buflen;
+
+ /* malloc the space needed */
+ if ( (*buf=(uint8*)malloc(len)) == NULL) {
+ DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n"));
+ return (-1);
+ }
+
+ /* now for the real call to tdb_pack() */
+ buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V0,
+ logon_time,
+ logoff_time,
+ kickoff_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time,
+ username_len, username,
+ domain_len, domain,
+ nt_username_len, nt_username,
+ fullname_len, fullname,
+ homedir_len, homedir,
+ dir_drive_len, dir_drive,
+ logon_script_len, logon_script,
+ profile_path_len, profile_path,
+ acct_desc_len, acct_desc,
+ workstations_len, workstations,
+ unknown_str_len, unknown_str,
+ munged_dial_len, munged_dial,
+ user_rid,
+ group_rid,
+ lm_pw_len, lm_pw,
+ nt_pw_len, nt_pw,
+ pdb_get_acct_ctrl(sampass),
+ pdb_get_unknown_3(sampass),
+ pdb_get_logon_divs(sampass),
+ pdb_get_hours_len(sampass),
+ MAX_HOURS_LEN, pdb_get_hours(sampass),
+ pdb_get_bad_password_count(sampass),
+ pdb_get_logon_count(sampass),
+ pdb_get_unknown_6(sampass));
+
+
+ /* check to make sure we got it correct */
+ if (buflen != len) {
+ DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n",
+ (unsigned long)buflen, (unsigned long)len));
+ /* error */
+ SAFE_FREE (*buf);
+ return (-1);
+ }
+
+ return (buflen);
+}
+
+
+BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+{
+
+ /* times are stored as 32bit integer
+ take care on system with 64bit wide time_t
+ --SSS */
+ uint32 logon_time,
+ logoff_time,
+ kickoff_time,
+ lockout_time,
+ pass_last_set_time,
+ pass_can_change_time,
+ pass_must_change_time;
+ char *username;
+ char *domain;
+ char *nt_username;
+ char *dir_drive;
+ char *unknown_str;
+ char *munged_dial;
+ char *fullname;
+ char *homedir;
+ char *logon_script;
+ char *profile_path;
+ char *acct_desc;
+ char *workstations;
+ uint32 username_len, domain_len, nt_username_len,
+ dir_drive_len, unknown_str_len, munged_dial_len,
+ fullname_len, homedir_len, logon_script_len,
+ profile_path_len, acct_desc_len, workstations_len;
+
+ uint32 user_rid, group_rid, unknown_3, hours_len, unknown_6;
+ uint16 acct_ctrl, logon_divs;
+ uint16 bad_password_count, logon_count;
+ uint8 *hours;
+ static uint8 *lm_pw_ptr, *nt_pw_ptr;
+ uint32 len = 0;
+ uint32 lm_pw_len, nt_pw_len, hourslen;
+ BOOL ret = True;
+
+ if(sampass == NULL || buf == NULL) {
+ DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n"));
+ return False;
+ }
+
+ /* unpack the buffer into variables */
+ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1,
+ &logon_time,
+ &logoff_time,
+ &kickoff_time,
+ &lockout_time,
+ &pass_last_set_time,
+ &pass_can_change_time,
+ &pass_must_change_time,
+ &username_len, &username,
+ &domain_len, &domain,
+ &nt_username_len, &nt_username,
+ &fullname_len, &fullname,
+ &homedir_len, &homedir,
+ &dir_drive_len, &dir_drive,
+ &logon_script_len, &logon_script,
+ &profile_path_len, &profile_path,
+ &acct_desc_len, &acct_desc,
+ &workstations_len, &workstations,
+ &unknown_str_len, &unknown_str,
+ &munged_dial_len, &munged_dial,
+ &user_rid,
+ &group_rid,
+ &lm_pw_len, &lm_pw_ptr,
+ &nt_pw_len, &nt_pw_ptr,
+ &acct_ctrl,
+ &unknown_3,
+ &logon_divs,
+ &hours_len,
+ &hourslen, &hours,
+ &bad_password_count,
+ &logon_count,
+ &unknown_6);
+
+ if (len == -1) {
+ ret = False;
+ goto done;
+ }
+
+ pdb_set_logon_time(sampass, logon_time, PDB_SET);
+ pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
+ pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+ pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
+ pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
+ pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
+
+ pdb_set_username(sampass, username, PDB_SET);
+ pdb_set_domain(sampass, domain, PDB_SET);
+ pdb_set_nt_username(sampass, nt_username, PDB_SET);
+ pdb_set_fullname(sampass, fullname, PDB_SET);
+
+ if (homedir) {
+ pdb_set_homedir(sampass, homedir, PDB_SET);
+ }
+ else {
+ pdb_set_homedir(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
+ PDB_DEFAULT);
+ }
+
+ if (dir_drive)
+ pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
+ else {
+ pdb_set_dir_drive(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()),
+ PDB_DEFAULT);
+ }
+
+ if (logon_script)
+ pdb_set_logon_script(sampass, logon_script, PDB_SET);
+ else {
+ pdb_set_logon_script(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
+ PDB_DEFAULT);
+ }
+
+ if (profile_path) {
+ pdb_set_profile_path(sampass, profile_path, PDB_SET);
+ } else {
+ pdb_set_profile_path(sampass,
+ talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()),
+ PDB_DEFAULT);
+ }
+
+ pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
+ pdb_set_workstations(sampass, workstations, PDB_SET);
+ pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
+
+ if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
+ if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
+ if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
+ ret = False;
+ goto done;
+ }
+ }
+
+ pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
+ pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
+ pdb_set_unknown_3(sampass, unknown_3, PDB_SET);
+ pdb_set_hours_len(sampass, hours_len, PDB_SET);
+ pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
+ pdb_set_logon_count(sampass, logon_count, PDB_SET);
+ pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
+ pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
+ pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+ pdb_set_hours(sampass, hours, PDB_SET);
+
+done:
+
+ SAFE_FREE(username);
+ SAFE_FREE(domain);
+ SAFE_FREE(nt_username);
+ SAFE_FREE(fullname);
+ SAFE_FREE(homedir);
+ SAFE_FREE(dir_drive);
+ SAFE_FREE(logon_script);
+ SAFE_FREE(profile_path);
+ SAFE_FREE(acct_desc);
+ SAFE_FREE(workstations);
+ SAFE_FREE(munged_dial);
+ SAFE_FREE(unknown_str);
+ SAFE_FREE(hours);
+
+ return ret;
+}
+
+
+uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only)
{
size_t len, buflen;
@@ -1482,6 +1912,7 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_
uint32 logon_time,
logoff_time,
kickoff_time,
+ lockout_time,
pass_last_set_time,
pass_can_change_time,
pass_must_change_time;
@@ -1522,6 +1953,7 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_
logon_time = (uint32)pdb_get_logon_time(sampass);
logoff_time = (uint32)pdb_get_logoff_time(sampass);
kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
+ lockout_time = (uint32)0;
pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
@@ -1623,10 +2055,11 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_
munged_dial_len = 0;
/* one time to get the size needed */
- len = tdb_pack(NULL, 0, TDB_FORMAT_STRING,
+ len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V1,
logon_time,
logoff_time,
kickoff_time,
+ lockout_time,
pass_last_set_time,
pass_can_change_time,
pass_must_change_time,
@@ -1666,10 +2099,11 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_
}
/* now for the real call to tdb_pack() */
- buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING,
+ buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V1,
logon_time,
logoff_time,
kickoff_time,
+ lockout_time,
pass_last_set_time,
pass_can_change_time,
pass_must_change_time,
@@ -1756,5 +2190,3 @@ BOOL get_free_rid_range(uint32 *low, uint32 *high)
return True;
}
-
-
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index c9a84f3242..966682563c 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -37,10 +37,12 @@ static int tdbsam_debug_level = DBGC_ALL;
#endif
+#define TDBSAM_VERSION 1 /* Most recent TDBSAM version */
#define PDB_VERSION "20010830"
#define PASSDB_FILE_NAME "passdb.tdb"
#define USERPREFIX "USER_"
#define RIDPREFIX "RID_"
+#define tdbsamver_t int32
struct tdbsam_privates {
TDB_CONTEXT *passwd_tdb;
@@ -50,6 +52,176 @@ struct tdbsam_privates {
const char *tdbsam_location;
};
+/**
+ * Convert old TDBSAM to the latest version.
+ * @param pdb_tdb A pointer to the opened TDBSAM file which must be converted.
+ * This file must be opened with read/write access.
+ * @param from Current version of the TDBSAM file.
+ * @return True if the conversion has been successful, false otherwise.
+ **/
+
+static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from)
+{
+ const char * vstring = "INFO/version";
+ SAM_ACCOUNT *user = NULL;
+ const char *prefix = USERPREFIX;
+ TDB_DATA data, key, old_key;
+ uint8 *buf = NULL;
+ BOOL ret;
+
+ if (pdb_tdb == NULL) {
+ DEBUG(0,("tdbsam_convert: Bad TDB Context pointer.\n"));
+ return False;
+ }
+
+ /* handle a Samba upgrade */
+ tdb_lock_bystring(pdb_tdb, vstring, 0);
+
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) {
+ DEBUG(0,("tdbsam_convert: cannot initialized a SAM_ACCOUNT.\n"));
+ return False;
+ }
+
+ /* Enumerate all records and convert them */
+ key = tdb_firstkey(pdb_tdb);
+
+ while (key.dptr) {
+
+ /* skip all non-USER entries (eg. RIDs) */
+ while ((key.dsize != 0) && (strncmp(key.dptr, prefix, strlen (prefix)))) {
+ old_key = key;
+ /* increment to next in line */
+ key = tdb_nextkey(pdb_tdb, key);
+ SAFE_FREE(old_key.dptr);
+ }
+
+ if (key.dptr) {
+
+ /* read from tdbsam */
+ data = tdb_fetch(pdb_tdb, key);
+ if (!data.dptr) {
+ DEBUG(0,("tdbsam_convert: database entry not found: %s.\n",key.dptr));
+ return False;
+ }
+
+ if (!NT_STATUS_IS_OK(pdb_reset_sam(user))) {
+ DEBUG(0,("tdbsam_convert: cannot reset SAM_ACCOUNT.\n"));
+ SAFE_FREE(data.dptr);
+ return False;
+ }
+
+ /* unpack the buffer from the former format */
+ DEBUG(10,("tdbsam_convert: Try unpacking a record with (key:%s) (version:%d)\n", key.dptr, from));
+ switch (from) {
+ case 0:
+ ret = init_sam_from_buffer_v0(user, (uint8 *)data.dptr, data.dsize);
+ break;
+ case 1:
+ ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize);
+ break;
+ default:
+ /* unknown tdbsam version */
+ ret = False;
+ }
+ if (!ret) {
+ DEBUG(0,("tdbsam_convert: Bad SAM_ACCOUNT entry returned from TDB (key:%s) (version:%d)\n", key.dptr, from));
+ SAFE_FREE(data.dptr);
+ return False;
+ }
+
+ /* pack from the buffer into the new format */
+ DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from));
+ if ((data.dsize=init_buffer_from_sam (&buf, user, False)) == -1) {
+ DEBUG(0,("tdbsam_convert: cannot pack the SAM_ACCOUNT into the new format\n"));
+ SAFE_FREE(data.dptr);
+ return False;
+ }
+ data.dptr = (char *)buf;
+
+ /* Store the buffer inside the TDBSAM */
+ if (tdb_store(pdb_tdb, key, data, TDB_MODIFY) != TDB_SUCCESS) {
+ DEBUG(0,("tdbsam_convert: cannot store the SAM_ACCOUNT (key:%s) in new format\n",key.dptr));
+ SAFE_FREE(data.dptr);
+ return False;
+ }
+
+ SAFE_FREE(data.dptr);
+
+ /* increment to next in line */
+ old_key = key;
+ key = tdb_nextkey(pdb_tdb, key);
+ SAFE_FREE(old_key.dptr);
+ }
+
+ }
+
+ pdb_free_sam(&user);
+
+ /* upgrade finished */
+ tdb_store_int32(pdb_tdb, vstring, TDBSAM_VERSION);
+ tdb_unlock_bystring(pdb_tdb, vstring);
+
+ return(True);
+}
+
+/**
+ * Open the TDB passwd database, check version and convert it if needed.
+ * @param name filename of the tdbsam file.
+ * @param open_flags file access mode.
+ * @return a TDB_CONTEXT handle on the tdbsam file.
+ **/
+
+static TDB_CONTEXT * tdbsam_tdbopen (const char *name, int open_flags)
+{
+ TDB_CONTEXT *pdb_tdb;
+ tdbsamver_t version;
+
+ /* Try to open tdb passwd */
+ if (!(pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, open_flags, 0600)))
+ return NULL;
+
+ /* Check the version */
+ version = (tdbsamver_t) tdb_fetch_int32(pdb_tdb, "INFO/version");
+ if (version == -1)
+ version = 0; /* Version not found, assume version 0 */
+
+ /* Compare the version */
+ if (version > TDBSAM_VERSION) {
+ /* Version more recent than the latest known */
+ DEBUG(0, ("TDBSAM version unknown: %d\n", version));
+ tdb_close(pdb_tdb);
+ pdb_tdb = NULL;
+ }
+ else if (version < TDBSAM_VERSION) {
+ /* Older version, must be converted */
+ DEBUG(1, ("TDBSAM version too old (%d), trying to convert it.\n", version));
+
+ /* Reopen the pdb file with read-write access if needed */
+ if (!(open_flags & O_RDWR)) {
+ DEBUG(10, ("tdbsam_tdbopen: TDB file opened with read only access, reopen it with read-write access.\n"));
+ tdb_close(pdb_tdb);
+ pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, (open_flags & 07777770) | O_RDWR, 0600);
+ }
+
+ /* Convert */
+ if (!tdbsam_convert(pdb_tdb, version)){
+ DEBUG(0, ("tdbsam_tdbopen: Error when trying to convert tdbsam: %s\n",name));
+ tdb_close(pdb_tdb);
+ pdb_tdb = NULL;
+ } else {
+ DEBUG(1, ("TDBSAM converted successfully.\n"));
+ }
+
+ /* Reopen the pdb file as it must be */
+ if (!(open_flags & O_RDWR)) {
+ tdb_close(pdb_tdb);
+ pdb_tdb = tdb_open_log(name, 0, TDB_DEFAULT, open_flags, 0600);
+ }
+ }
+
+ return pdb_tdb;
+}
+
/***************************************************************
Open the TDB passwd database for SAM account enumeration.
****************************************************************/
@@ -59,7 +231,7 @@ static NTSTATUS tdbsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data;
/* Open tdb passwd */
- if (!(tdb_state->passwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
+ if (!(tdb_state->passwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, update?(O_RDWR|O_CREAT):O_RDONLY)))
{
DEBUG(0, ("Unable to open/create TDB passwd\n"));
return NT_STATUS_UNSUCCESSFUL;
@@ -179,7 +351,7 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT
key.dsize = strlen(keystr) + 1;
/* open the accounts TDB */
- if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
+ if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
if (errno == ENOENT) {
/*
@@ -251,7 +423,7 @@ static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT
key.dsize = strlen (keystr) + 1;
/* open the accounts TDB */
- if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
+ if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) {
DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
return nt_status;
}
@@ -265,6 +437,7 @@ static NTSTATUS tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT
return nt_status;
}
+
fstrcpy(name, data.dptr);
SAFE_FREE(data.dptr);
@@ -299,7 +472,7 @@ static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_AC
strlower_m(name);
/* open the TDB */
- if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR, 0600))) {
+ if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR))) {
DEBUG(0, ("Unable to open TDB passwd!"));
return nt_status;
}
@@ -363,7 +536,7 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd,
/* open the account TDB passwd*/
- pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
+ pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT);
if (!pwd_tdb) {
DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n",
@@ -519,4 +692,3 @@ NTSTATUS pdb_tdbsam_init(void)
{
return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
}
-