[patch] logon hours support

Richard Renard rrenard at idealx.com
Thu Aug 5 09:17:14 GMT 2004


hi list,


Here is a patch that gives samba3 support for logon hours.
tdb and ldap backend are working.
there is also a "-Z" flag added to pdbedit for resetting hours.

the logic is inspired from this mail
http://ma.ph-freiburg.de/tng/tng-technical/2003-04/msg00015.html

It needs some testing mostly about the daylight saving time stuff

missing is the "times" option to "net" allowing to set hours from 
command line.


Thanks,

Richard.
-- 
Richard Renard
rrenard at idealx.com
-------------- next part --------------
diff -ruN samba-3.0.5.orig/examples/LDAP/samba.schema samba-3.0.5/examples/LDAP/samba.schema
--- samba-3.0.5.orig/examples/LDAP/samba.schema	2004-07-20 18:28:24.000000000 +0200
+++ samba-3.0.5/examples/LDAP/samba.schema	2004-08-04 17:21:21.000000000 +0200
@@ -212,6 +212,11 @@
 	EQUALITY integerMatch
 	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
+attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME 'sambaLogonHours'
+	DESC 'Logon Hours'
+	EQUALITY caseIgnoreIA5Match
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{42} SINGLE-VALUE )
+
 
 ##
 ## string settings
@@ -329,7 +334,7 @@
                displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $
 	       sambaProfilePath $ description $ sambaUserWorkstations $
 	       sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial $
-	       sambaBadPasswordCount $ sambaBadPasswordTime))
+	       sambaBadPasswordCount $ sambaBadPasswordTime $ sambaLogonHours))
 
 ##
 ## Group mapping info
diff -ruN samba-3.0.5.orig/source/auth/auth_sam.c samba-3.0.5/source/auth/auth_sam.c
--- samba-3.0.5.orig/source/auth/auth_sam.c	2004-07-20 18:28:01.000000000 +0200
+++ samba-3.0.5/source/auth/auth_sam.c	2004-08-05 11:01:28.000000000 +0200
@@ -65,6 +65,51 @@
 				   lm_pw, nt_pw, user_sess_key, lm_sess_key);
 }
 
+static BOOL logon_hours_ok(SAM_ACCOUNT *sampass)
+{
+	/* There is a problem when setting hours from a client which is 
+	 * configured for a TZ that does not support DST, 
+	 * one must add an hour to its clock to match DST.
+	 * This is NT4's behavior. */
+	
+	/* Logon hours are stored in UTC, first bit is Sunday from 12AM to 1AM */
+	const uint8 *hours;
+	time_t systime;
+	struct tm *utctime;
+	extern int daylight;
+
+	uint8 mask, field, test, bitpos, byte = 0x0;
+	int wday, hour = 0;
+	
+	DEBUG(4,("logon_hours_ok: Checking logon hours password for user %s\n",pdb_get_username(sampass)));
+
+	tzset();
+	
+	systime = time(NULL);
+	utctime = gmtime(&systime);
+
+	wday = utctime->tm_wday;
+	hour = utctime->tm_hour;
+	
+	hours = pdb_get_hours(sampass);
+
+	/* FIXME: need to get the saving time offset, assumed to +1 for now */
+	if (daylight) hour += 1;
+
+	/* find the corresponding byte and bit */
+	bitpos = ((wday * 24 + hour)) % 168;
+	byte = bitpos / 8;
+	mask = 1 << (bitpos % 8);
+	field = hours[byte];
+
+	if (! (field & mask)) {
+		DEBUG(1,("logon_hours_ok: Account for user %s not allowed to logon at this time.\n", pdb_get_username(sampass)));
+		return False;
+	}
+	
+	return True;
+}
+
 
 /****************************************************************************
  Do a specific test for a SAM_ACCOUNT being vaild for this connection 
@@ -93,6 +138,11 @@
 		return NT_STATUS_ACCOUNT_LOCKED_OUT;
 	}
 
+	/* Quit if the account is not allowed to logon at this time. */
+	if (! logon_hours_ok(sampass)) {
+		return NT_STATUS_INVALID_LOGON_HOURS;
+	}
+ 
 	/* Test account expire time */
 	
 	kickoff_time = pdb_get_kickoff_time(sampass);
diff -ruN samba-3.0.5.orig/source/include/smbldap.h samba-3.0.5/source/include/smbldap.h
--- samba-3.0.5.orig/source/include/smbldap.h	2004-07-20 18:28:12.000000000 +0200
+++ samba-3.0.5/source/include/smbldap.h	2004-08-04 17:21:21.000000000 +0200
@@ -93,6 +93,7 @@
 #define LDAP_ATTR_LOGON_COUNT		36
 #define LDAP_ATTR_MUNGED_DIAL		37
 #define LDAP_ATTR_BAD_PASSWORD_TIME	38
+#define LDAP_ATTR_LOGON_HOURS           39
 
 #define LDAP_ATTR_SID_LIST              40
 
diff -ruN samba-3.0.5.orig/source/lib/smbldap.c samba-3.0.5/source/lib/smbldap.c
--- samba-3.0.5.orig/source/lib/smbldap.c	2004-07-20 18:28:04.000000000 +0200
+++ samba-3.0.5/source/lib/smbldap.c	2004-08-04 17:21:21.000000000 +0200
@@ -100,6 +100,7 @@
 	{ LDAP_ATTR_MUNGED_DIAL,	"sambaMungedDial"	},
 	{ LDAP_ATTR_BAD_PASSWORD_COUNT,	"sambaBadPasswordCount" },
 	{ LDAP_ATTR_BAD_PASSWORD_TIME,	"sambaBadPasswordTime" 	},
+	{ LDAP_ATTR_LOGON_HOURS,        "sambaLogonHours"       },
 	{ LDAP_ATTR_LIST_END,		NULL 			}
 };
 
diff -ruN samba-3.0.5.orig/source/passdb/passdb.c samba-3.0.5/source/passdb/passdb.c
--- samba-3.0.5.orig/source/passdb/passdb.c	2004-07-20 18:28:09.000000000 +0200
+++ samba-3.0.5/source/passdb/passdb.c	2004-08-04 17:21:21.000000000 +0200
@@ -605,6 +605,57 @@
 	return rid_offset;
 }
 
+/*************************************************************
+ Routine to set 42 hex hours characters from a 21 byte array.
+**************************************************************/
+
+void pdb_sethexhours(char *p, const unsigned char *hours)
+{
+	if (hours != NULL) {
+		int i;
+		for (i = 0; i < 21; i++)
+			slprintf(&p[i*2], 3, "%02X", hours[i]);
+	}
+	else
+	{
+		safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
+	}
+}
+
+/*************************************************************
+ Routine to get the 42 hex characters and turn them
+ into a 21 byte array.
+**************************************************************/
+
+BOOL pdb_gethexhours(const char *p, unsigned char *hours)
+{
+	int i;
+	unsigned char   lonybble, hinybble;
+	const char      *hexchars = "0123456789ABCDEF";
+	char           *p1, *p2;
+	
+	if (!p)
+		return (False);
+	
+	for (i = 0; i < 42; i += 2) {
+		hinybble = toupper(p[i]);
+		lonybble = toupper(p[i + 1]);
+
+		p1 = strchr(hexchars, hinybble);
+		p2 = strchr(hexchars, lonybble);
+
+		if (!p1 || !p2)
+			return (False);
+
+		hinybble = PTR_DIFF(p1, hexchars);
+		lonybble = PTR_DIFF(p2, hexchars);
+
+		hours[i / 2] = (hinybble << 4) | lonybble;
+	}
+	return (True);
+}
+
+
 /*******************************************************************
  Converts NT user RID to a UNIX uid.
  ********************************************************************/
diff -ruN samba-3.0.5.orig/source/passdb/pdb_ldap.c samba-3.0.5/source/passdb/pdb_ldap.c
--- samba-3.0.5.orig/source/passdb/pdb_ldap.c	2004-07-20 18:28:09.000000000 +0200
+++ samba-3.0.5/source/passdb/pdb_ldap.c	2004-08-04 17:21:21.000000000 +0200
@@ -708,6 +708,17 @@
 
 	pdb_set_hours_len(sampass, hours_len, PDB_SET);
 	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
+	
+	if(!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
+			get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_HOURS), temp)) {
+		/* leave as default */
+	} else {
+		pdb_gethexhours(temp, hours);
+		memset((char *)temp, '\0', strlen(temp) +1);
+		pdb_set_hours(sampass, hours, PDB_SET);
+		ZERO_STRUCT(hours);
+	}
+
 
 /*	pdb_set_munged_dial(sampass, munged_dial, PDB_SET); */
 	
@@ -738,8 +749,6 @@
 
 	/* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */
 
-	pdb_set_hours(sampass, hours, PDB_SET);
-
 	/* check the timestamp of the cache vs ldap entry */
 	if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state, 
 							    entry)))
@@ -993,7 +1002,15 @@
 		}
 	}
 
-	/* FIXME: Hours stuff goes in LDAP  */
+	if (need_update(sampass, PDB_HOURS)) {
+		const char *hours = pdb_get_hours(sampass);
+		if (hours) {
+			pdb_sethexhours(temp, hours);
+			smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+					get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_HOURS),
+					temp);
+		}
+	}
 
 	if (need_update(sampass, PDB_ACCTCTRL))
 		smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
diff -ruN samba-3.0.5.orig/source/utils/pdbedit.c samba-3.0.5/source/utils/pdbedit.c
--- samba-3.0.5.orig/source/utils/pdbedit.c	2004-07-20 18:28:15.000000000 +0200
+++ samba-3.0.5/source/utils/pdbedit.c	2004-08-04 17:23:22.000000000 +0200
@@ -49,6 +49,7 @@
 #define BIT_EXPORT	0x02000000
 #define BIT_FIX_INIT    0x04000000
 #define BIT_BADPWRESET	0x08000000
+#define BIT_LOGONHOURS	0x10000000
 
 #define MASK_ALWAYS_GOOD	0x0000001F
 #define MASK_USER_GOOD		0x00401F00
@@ -120,6 +121,9 @@
 	if (!sam_pwent) return -1;
 	
 	if (verbosity) {
+		pstring temp;
+		const uint8 *hours;
+		
 		printf ("Unix username:        %s\n", pdb_get_username(sam_pwent));
 		printf ("NT username:          %s\n", pdb_get_nt_username(sam_pwent));
 		printf ("Account Flags:        %s\n", pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent), NEW_PW_FORMAT_SPACE_PADDED_LEN));
@@ -160,6 +164,10 @@
 		printf ("Bad password count  : %d\n", 
 			pdb_get_bad_password_count(sam_pwent));
 		
+		hours = pdb_get_hours(sam_pwent);
+		pdb_sethexhours(temp, (const char *)hours);
+		printf ("Logon hours         : %s\n", temp);
+		
 	} else if (smbpwdstyle) {
 		char lm_passwd[33];
 		char nt_passwd[33];
@@ -298,7 +306,7 @@
 			  const char *drive, const char *script, 
 			  const char *profile, const char *account_control,
 			  const char *user_sid, const char *group_sid,
-			  const BOOL badpw)
+			  const BOOL badpw, const BOOL hours)
 {
 	SAM_ACCOUNT *sam_pwent=NULL;
 	BOOL ret;
@@ -374,6 +382,16 @@
 		pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED);
 		pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED);
 	}
+
+	if (hours) {
+		uint8 hours[MAX_HOURS_LEN];
+		uint32 hours_len;
+		
+		hours_len = pdb_get_hours_len(sam_pwent);
+		memset(hours, 0xff, hours_len);
+		
+		pdb_set_hours(sam_pwent, hours, PDB_CHANGED);
+	}
 	
 	if (NT_STATUS_IS_OK(in->pdb_update_sam_account (in, sam_pwent)))
 		print_user_info (in, username, True, False);
@@ -626,6 +644,7 @@
 	static long int account_policy_value = 0;
 	BOOL account_policy_value_set = False;
 	static BOOL badpw_reset = False;
+	static BOOL hours_reset = False;
 
 	struct pdb_context *bin;
 	struct pdb_context *bout;
@@ -657,6 +676,7 @@
 		{"account-control",	'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL},
 		{"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL},
 		{"bad-password-count-reset", 'z', POPT_ARG_NONE, &badpw_reset, 0, "reset bad password count", NULL},
+		{"logon-hours-reset", 'Z', POPT_ARG_NONE, &hours_reset, 0, "reset logon hours", NULL},
 		POPT_COMMON_SAMBA
 		POPT_TABLEEND
 	};
@@ -710,7 +730,8 @@
 			(account_policy_value_set ? BIT_ACCPOLVAL : 0) +
 			(backend_in ? BIT_IMPORT : 0) +
 			(backend_out ? BIT_EXPORT : 0) +
-			(badpw_reset ? BIT_BADPWRESET : 0);
+			(badpw_reset ? BIT_BADPWRESET : 0) +
+			(hours_reset ? BIT_LOGONHOURS : 0);
 
 	if (setparms & BIT_BACKEND) {
 		if (!NT_STATUS_IS_OK(make_pdb_context_string(&bdef, backend))) {
@@ -813,6 +834,12 @@
 		checkparms |= BIT_MODIFY;
 		checkparms &= ~BIT_BADPWRESET;
 	}
+
+	/* if logon hours is reset, must modify */
+	if (checkparms & BIT_LOGONHOURS) {
+		checkparms |= BIT_MODIFY;
+		checkparms &= ~BIT_LOGONHOURS;
+	}
 	
 	/* account operation */
 	if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || (checkparms & BIT_DELETE)) {
@@ -850,7 +877,7 @@
 					      logon_script,
 					      profile_path, account_control,
 					      user_sid, group_sid,
-					      badpw_reset);
+					      badpw_reset, hours_reset);
 		}
 	}
 


More information about the samba-technical mailing list