Control PAM Access by Time with pam_time
You will add a time-based account check to one PAM service, with a rule that permits a named group of users only during a defined period. The examples use Linux-PAM 1.5.3 from Debian package libpam-modules:amd64 version 1.5.3-5ubuntu5.7. Allow about twenty minutes, plus a maintenance window if you are applying this to a real login service.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need root access to edit /etc/security/time.conf and the relevant file under /etc/pam.d. The module reads that configuration during an account check; it does not authenticate users. A malformed rule can deny access, so keep an existing root shell or console session open while testing.
1. Check the installed module and current configuration
These are ordinary, read-only checks:
$ dpkg-query -W -f='${Package} ${Version}\n' libpam-modules:amd64
libpam-modules:amd64 1.5.3-5ubuntu5.7
$ test -r /usr/lib/x86_64-linux-gnu/security/pam_time.so && echo 'pam_time module is present'
pam_time module is present
$ sudo sed -n '1,160p' /etc/security/time.conf
The default configuration file is /etc/security/time.conf. On this machine it contains comments and no active rules. Preserve any rules you find. PAM configuration is service-specific, so first identify the service that should be restricted, such as login, su or an application with its own file.
Checkpoint: record the exact PAM service name and keep the current contents of both files available for recovery.
2. Understand the four fields
Each active line in time.conf has this shape:
services;ttys;users;times
The service, terminal and user fields are logic lists. Use | for OR, & for AND, and prefix a token with ! for NOT. The simple wildcard * may be used only once in each of those fields. The time field uses two-letter day codes and a 24-hour range, for example MoFr0900-1700. Accepted day codes include Mo, Tu, We, Th, Fr, Sa, Su, Wk, Wd and Al.
All of the first three fields must match before a rule is active. A rule can therefore be narrower than its individual tokens suggest. A finish time earlier than the start time runs across midnight. Repeated day codes cancel each other, so do not write a day twice when you mean to include it.
3. Build a harmless test rule in a separate file
Do not edit the live file first. Create a temporary configuration owned by root, using a service and account that exist on your host. This example applies to the login service, any terminal beginning tty, and one placeholder account. It denies that account outside weekday working hours:
$ umask 077
$ cat > /tmp/pam-time-test.conf <<'EOF'
login;tty*;TEST_USER;!Wk0900-1700
EOF
$ sudo sed -n '1,20p' /tmp/pam-time-test.conf
login;tty*;TEST_USER;!Wk0900-1700
Replace TEST_USER with a real non-privileged test account before using the file. The leading ! means the rule matches anything except weekdays from 09:00 through 17:00. Because pam_time denies access when a matching rule says the time is disallowed, this line denies the selected account outside that window. It does not create the account, change its password or terminate an existing session.
Checkpoint: check the four semicolon-separated fields and the account spelling. A missing field, a wrong service name or an unexpected terminal name will make a test misleading.
4. Install the rule only after backing up the live file
This is a security-sensitive change and can affect logins. First make a dated backup, then append the reviewed rule with elevated privileges. Do not overwrite the file with an unreviewed heredoc:
$ sudo cp --preserve=mode,ownership,timestamps /etc/security/time.conf /etc/security/time.conf.bak
$ sudo sh -c 'cat /tmp/pam-time-test.conf >> /etc/security/time.conf'
$ sudo tail -n 5 /etc/security/time.conf
There is no separate daemon to reload. The module reads the file when the PAM account check runs. Existing sessions are not ended automatically; the manual explicitly warns that no daemon enforces the end of a session. Test a new account check, not only an already-open session.
5. Add pam_time to the service's account stack
Add one account line to the target service file, after backing it up. The module provides only the account type:
$ sudo cp --preserve=mode,ownership,timestamps /etc/pam.d/login /etc/pam.d/login.bak
$ sudoedit /etc/pam.d/login
Add this line in the account section:
account required pam_time.so
For a different service, edit that service's file instead of copying this line into every PAM stack. If your deployment uses an included account stack, understand the include order before adding a second check. The required control flag records a failure while allowing the rest of the stack to run; the final account result still denies access when this module returns PAM_PERM_DENIED.
To use another configuration path, pass the documented module option on the same line:
account required pam_time.so conffile=/etc/security/time.conf
That option overrides the default file. Keep the alternate file root-owned and readable by the PAM process. Do not add debug routinely: it writes diagnostic information to syslog. noaudit suppresses audit reporting for denied logins when audit support is available, which is a logging decision rather than a way to permit access.
6. Verify from a separate session and recover if needed
Open a second console or SSH session before testing. Use the test account and a service that actually reaches the edited PAM stack. If the current time is outside the allowed window, an account check should fail; if it is inside the window, it should pass. The exact prompt or error text belongs to the calling service, so check the command's exit status and the service log rather than expecting one universal message.
$ su - TEST_USER -c 'id -un'
$ printf 'status: %s\n' "$?"
status: 0
That successful result is meaningful only when the current time, terminal and service match the rule. If the check is denied unexpectedly, or you lose the test path, restore both backups immediately:
$ sudo cp --preserve=mode,ownership,timestamps /etc/security/time.conf.bak /etc/security/time.conf
$ sudo cp --preserve=mode,ownership,timestamps /etc/pam.d/login.bak /etc/pam.d/login
$ sudo tail -n 5 /etc/security/time.conf
$ sudo tail -n 12 /etc/pam.d/login
After the rule is confirmed, replace TEST_USER with the intended account or group expression and retest at both an allowed and a denied time. Keep the backup until the next maintenance cycle. Remove the temporary file only after the live configuration is verified:
$ rm -- /tmp/pam-time-test.conf
Done means
- The installed module and Linux-PAM package version were checked.
- The rule has four correct fields and matches the intended service, terminal and user.
- The live files were backed up before the PAM change.
- A new account check succeeded during an allowed period and was denied during a disallowed period.
- You know that existing sessions are not ended by pam_time.
- The rollback copies remain available until the change is trusted.