Author: abartlet
Date: 2007-07-27 06:31:12 +0000 (Fri, 27 Jul 2007)
New Revision: 24061

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=24061

Log:
Anther part of bug #4823, which is that until now Samba4 didn't parse
the logon hours, even if set.

This code happily stolen from the great work in Samba3 :-)

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/auth/auth.h
   branches/SAMBA_4_0/source/auth/sam.c
   branches/SAMBA_4_0/source/kdc/hdb-ldb.c


Changeset:
Modified: branches/SAMBA_4_0/source/auth/auth.h
===================================================================
--- branches/SAMBA_4_0/source/auth/auth.h       2007-07-27 03:08:15 UTC (rev 
24060)
+++ branches/SAMBA_4_0/source/auth/auth.h       2007-07-27 06:31:12 UTC (rev 
24061)
@@ -21,6 +21,8 @@
 #ifndef _SAMBA_AUTH_H
 #define _SAMBA_AUTH_H
 
+extern const char *user_attrs[];
+
 union netr_Validation;
 struct netr_SamBaseInfo;
 struct netr_SamInfo3;

Modified: branches/SAMBA_4_0/source/auth/sam.c
===================================================================
--- branches/SAMBA_4_0/source/auth/sam.c        2007-07-27 03:08:15 UTC (rev 
24060)
+++ branches/SAMBA_4_0/source/auth/sam.c        2007-07-27 06:31:12 UTC (rev 
24061)
@@ -45,6 +45,7 @@
 
        "pwdLastSet",
        "accountExpires",
+       "logonHours",
        
        "objectSid",
 
@@ -67,9 +68,70 @@
 };
 
 const char *domain_ref_attrs[] =  {"nETBIOSName", "nCName", 
-                                         "dnsRoot", "objectClass", NULL};
+                                  "dnsRoot", "objectClass", NULL};
 
+/****************************************************************************
+ Check if a user is allowed to logon at this time. Note this is the
+ servers local time, as logon hours are just specified as a weekly
+ bitmask.
+****************************************************************************/
+                                                                               
                               
+static BOOL logon_hours_ok(struct ldb_message *msg, const char *name_for_logs)
+{
+       /* In logon hours first bit is Sunday from 12AM to 1AM */
+       const struct ldb_val *hours;
+       struct tm *utctime;
+       time_t lasttime;
+       const char *asct;
+       uint8_t bitmask, bitpos;
 
+       hours = ldb_msg_find_ldb_val(msg, "logonHours");
+       if (!hours) {
+               DEBUG(5,("logon_hours_ok: No hours restrictions for user %s\n", 
name_for_logs));
+               return True;
+       }
+
+       if (hours->length != 168/8) {
+               DEBUG(5,("logon_hours_ok: malformed logon hours restrictions 
for user %s\n", name_for_logs));
+               return True;            
+       }
+
+       lasttime = time(NULL);
+       utctime = gmtime(&lasttime);
+       if (!utctime) {
+               DEBUG(1, ("logon_hours_ok: failed to get gmtime. Failing logon 
for user %s\n",
+                       name_for_logs));
+               return False;
+       }
+
+       /* find the corresponding byte and bit */
+       bitpos = (utctime->tm_wday * 24 + utctime->tm_hour) % 168;
+       bitmask = 1 << (bitpos % 8);
+
+       if (! (hours->data[bitpos/8] & bitmask)) {
+               struct tm *t = localtime(&lasttime);
+               if (!t) {
+                       asct = "INVALID TIME";
+               } else {
+                       asct = asctime(t);
+                       if (!asct) {
+                               asct = "INVALID TIME";
+                       }
+               }
+               
+               DEBUG(1, ("logon_hours_ok: Account for user %s not allowed to "
+                         "logon at this time (%s).\n",
+                         name_for_logs, asct ));
+               return False;
+       }
+
+       asct = asctime(utctime);
+       DEBUG(5,("logon_hours_ok: user %s allowed to logon at this time (%s)\n",
+               name_for_logs, asct ? asct : "UNKNOWN TIME" ));
+
+       return True;
+}
+
 /****************************************************************************
  Do a specific test for a SAM_ACCOUNT being vaild for this connection 
  (ie not disabled, expired and the like).
@@ -164,6 +226,10 @@
                }
        }
        
+       if (!logon_hours_ok(msg, name_for_logs)) {
+               return NT_STATUS_INVALID_LOGON_HOURS;
+       }
+       
        if (acct_flags & ACB_DOMTRUST) {
                DEBUG(2,("sam_account_ok: Domain trust account %s denied by 
server\n", name_for_logs));
                return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;

Modified: branches/SAMBA_4_0/source/kdc/hdb-ldb.c
===================================================================
--- branches/SAMBA_4_0/source/kdc/hdb-ldb.c     2007-07-27 03:08:15 UTC (rev 
24060)
+++ branches/SAMBA_4_0/source/kdc/hdb-ldb.c     2007-07-27 06:31:12 UTC (rev 
24061)
@@ -54,29 +54,6 @@
 { HDB_LDB_ENT_TYPE_CLIENT, HDB_LDB_ENT_TYPE_SERVER, 
   HDB_LDB_ENT_TYPE_KRBTGT, HDB_LDB_ENT_TYPE_ANY };
 
-static const char * const krb5_attrs[] = {
-       "objectClass",
-       "sAMAccountName",
-
-       "userPrincipalName",
-       "servicePrincipalName",
-
-       "userAccountControl",
-
-       "pwdLastSet",
-       "accountExpires",
-
-       "whenCreated",
-       "whenChanged",
-
-       "msDS-KeyVersionNumber",
-
-       "unicodePwd",
-       "supplementalCredentials",
-
-       NULL
-};
-
 static const char *realm_ref_attrs[] = {
        "nCName", 
        "dnsRoot", 
@@ -615,7 +592,7 @@
        krb5_error_code ret;
        int lret;
        char *filter = NULL;
-       const char * const *princ_attrs = krb5_attrs;
+       const char * const *princ_attrs = user_attrs;
 
        char *short_princ;
        char *short_princ_talloc;
@@ -886,7 +863,7 @@
                }
                
                ldb_ret = gendb_search_dn((struct ldb_context *)db->hdb_db,
-                                         mem_ctx, user_dn, &msg, krb5_attrs);
+                                         mem_ctx, user_dn, &msg, user_attrs);
                
                if (ldb_ret != 1) {
                        return HDB_ERR_NOENTRY;
@@ -1083,7 +1060,7 @@
 
        lret = ldb_search(ldb_ctx, realm_dn,
                                 LDB_SCOPE_SUBTREE, "(objectClass=user)",
-                                krb5_attrs, &res);
+                                user_attrs, &res);
 
        if (lret != LDB_SUCCESS) {
                talloc_free(priv);

Reply via email to