[Samba] [PATCH] tdb multiple format

Aurélien Degrémont adegremont at idealx.com
Tue Sep 23 16:32:50 GMT 2003


Hi,

As I said yesterday, I worked on a solution for tdb format in order to
manage easily new fields for this format.

So I add small changes to init_sam_from_buffer and init_buffer_from_sam
in this purpose.
The data TDB_FORMAT_STRING became an array which contains the list of
the different fields format which exist.

When the tdb file is read, for each records, Samba will try the most
recent format defined into the sources and, if the data length doesn't
fit, he fallbacks to a previous format, and so on...until there is no
others formats availables.

With this method, we could add new fields at the end of the records and
preserve compatibility !
Each record will be read in its original format and be write into the
newest format. So, the tranformation is transparent.

The conversion, between different tdb versions, works in both directions.


The patch is not functionnal. It is just a proposition and I will finish
it if you agree. It is designed for passdb.c RC4 and add 2 fields (bad
pwd count, lock out time) which are not implemented (into other files),
are just here as examples.

I'm waiting for your comments :)

TIA

Aurélien Degrémont



-------------- next part --------------
--- ../samba-clean/source/passdb/passdb.c	Mon Sep 15 01:57:54 2003
+++ source/passdb/passdb.c	Tue Sep 23 16:55:46 2003
@@ -78,6 +78,7 @@
 	user->private.pass_can_change_time  = (time_t)0;
 	user->private.logoff_time           = 
 	user->private.kickoff_time          = 
+	user->private.lockout_time          = (time_t)0;
 	user->private.pass_must_change_time = get_time_t_max();
 	user->private.unknown_3 = 0x00ffffff; 	/* don't know */
 	user->private.logon_divs = 168; 	/* hours per week */
@@ -85,6 +86,7 @@
 	memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */
 	user->private.unknown_5 = 0x00000000; /* don't know */
 	user->private.unknown_6 = 0x000004ec; /* don't know */
+	user->private.bad_pwd_count = 0;
 
 	/* Some parts of samba strlen their pdb_get...() returns, 
 	   so this keeps the interface unchanged for now. */
@@ -1269,7 +1271,21 @@
  Marshall/unmarshall SAM_ACCOUNT structs.
  *********************************************************************/
 
-#define TDB_FORMAT_STRING       "ddddddBBBBBBBBBBBBddBBwdwdBdd"
+
+
+/** List of different formats **
+  They must be ordered by size.
+  The eldest is the first (index 0).
+  The newest is the last.
+ */
+const char * TDB_FORMAT_STRING[] = { 
+	"ddddddBBBBBBBBBBBBddBBwdwdBdd" , 	// Version 0
+	"ddddddBBBBBBBBBBBBddBBwdwdBdddd"  	// Version 1 (include bad password count et logon time)
+	};
+
+// Index of the most recent version	
+#define TDB_FORMAT_NEWEST_VERSION	1
+	
 
 /**********************************************************************
  Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
@@ -1284,6 +1300,7 @@
 	uint32	logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time;
@@ -1304,12 +1321,13 @@
 		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_5, unknown_6;
+	uint32	user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6, bad_pwd_count;
 	uint16	acct_ctrl, logon_divs;
 	uint8	*hours;
 	static uint8	*lm_pw_ptr, *nt_pw_ptr;
-	uint32		len = 0;
+	uint32		len = -1;
 	uint32		lm_pw_len, nt_pw_len, hourslen;
+	short int	format_version = TDB_FORMAT_NEWEST_VERSION;
 	BOOL ret = True;
 	
 	if(sampass == NULL || buf == NULL) {
@@ -1317,38 +1335,58 @@
 		return False;
 	}
 									
-	/* unpack the buffer into variables */
-	len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING,
-		&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_ptr,
-		&nt_pw_len, &nt_pw_ptr,
-		&acct_ctrl,
-		&unknown_3,
-		&logon_divs,
-		&hours_len,
-		&hourslen, &hours,
-		&unknown_5,
-		&unknown_6);
-		
+	/* Initialize the fields which could be non-initialized by the tdb_unpack() due to different tdb format */
+	bad_pwd_count = 0;
+	lockout_time = (time_t) 0;
+	
+	
+	/* try successively the tdb format */
+	while (len == -1 && format_version >= 0) {
+		
+		DEBUG(20, ("init_sam_from_buffer: try to use the version %d of tdb format for the record\n", format_version));
+		
+		/* unpack the buffer into variables */
+		len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING[format_version],
+			&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_ptr,
+			&nt_pw_len, &nt_pw_ptr,
+			&acct_ctrl,
+			&unknown_3,
+			&logon_divs,
+			&hours_len,
+			&hourslen, &hours,
+			&unknown_5,
+			&unknown_6,
+			&lockout_time,
+			&bad_pwd_count);
+	
+		/* If a error has occured, try the next format */
+		if (len == -1) {
+			format_version--;
+			DEBUG(20, ("init_sam_from_buffer: cannot use the tdb format version %d for the record\n",format_version));  
+		}
+	}
+
+				
 	if (len == -1)  {
 		ret = False;
 		goto done;
@@ -1427,6 +1465,9 @@
 	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
 	pdb_set_hours(sampass, hours, PDB_SET);
 
+	pdb_set_lockout_time(sampass, lockout_time, PDB_SET);
+	pdb_set_bad_pwd_count(sampass, bad_pwd_count, PDB_SET);
+
 done:
 
 	SAFE_FREE(username);
@@ -1460,11 +1501,12 @@
 	uint32	logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time;
 
-	uint32  user_rid, group_rid;
+	uint32  user_rid, group_rid, bad_pwd_count;
 
 	const char *username;
 	const char *domain;
@@ -1500,6 +1542,7 @@
 	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)pdb_get_lockout_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);
@@ -1598,10 +1641,11 @@
 	if (munged_dial)
 		munged_dial_len = strlen(munged_dial) +1;
 	else
-		munged_dial_len = 0;	
-		
+		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[TDB_FORMAT_NEWEST_VERSION],
 		logon_time,
 		logoff_time,
 		kickoff_time,
@@ -1630,7 +1674,9 @@
 		pdb_get_hours_len(sampass),
 		MAX_HOURS_LEN, pdb_get_hours(sampass),
 		pdb_get_unknown_5(sampass),
-		pdb_get_unknown_6(sampass));
+		pdb_get_unknown_6(sampass),
+		lockout_time,
+		pdb_get_bad_pwd_count(sampass));
 
 
 	if (size_only)
@@ -1643,7 +1689,7 @@
 	}
 	
 	/* 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[TDB_FORMAT_NEWEST_VERSION],
 		logon_time,
 		logoff_time,
 		kickoff_time,
@@ -1672,7 +1718,9 @@
 		pdb_get_hours_len(sampass),
 		MAX_HOURS_LEN, pdb_get_hours(sampass),
 		pdb_get_unknown_5(sampass),
-		pdb_get_unknown_6(sampass));
+		pdb_get_unknown_6(sampass),
+		lockout_time,
+		pdb_get_bad_pwd_count(sampass));
 	
 	
 	/* check to make sure we got it correct */
@@ -1732,5 +1780,3 @@
 
 	return True;
 }
-
-


More information about the samba mailing list