diff options
Diffstat (limited to 'source4/auth')
-rw-r--r-- | source4/auth/auth.h | 2 | ||||
-rw-r--r-- | source4/auth/sam.c | 68 |
2 files changed, 69 insertions, 1 deletions
diff --git a/source4/auth/auth.h b/source4/auth/auth.h index 8dce7bbd5b..c694141373 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -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; diff --git a/source4/auth/sam.c b/source4/auth/sam.c index 681576c1c7..2fb0a239ff 100644 --- a/source4/auth/sam.c +++ b/source4/auth/sam.c @@ -45,6 +45,7 @@ const char *user_attrs[] = { "pwdLastSet", "accountExpires", + "logonHours", "objectSid", @@ -67,8 +68,69 @@ const char *user_attrs[] = { }; 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 @@ -164,6 +226,10 @@ _PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, } } + 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; |