> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/ask/flat/chapter-29-security/di-29.2-jie-zhang-hu-ren-zheng-an-quan.md).

# 29.2 Account Authentication Security

FreeBSD implements account security management through the **/etc/master.passwd** master password file and the `pam_unix.so` authentication module. This section covers the password database generation process, account locking and nologin-based login prevention, SHA-512 hash verification, and pam\_passwdqc password policy configuration.

## Password File Directory Structure

**/etc/master.passwd** is the master password file, readable only by root, containing users' encrypted passwords.

**/etc/passwd** is retained only for compatibility, automatically generated by pwd\_mkdb(8), with the password field replaced by `*`.

```sh
/etc/master.passwd
|  |
        |  pwd_mkdb(8)
        v
----------------------------
    Database generation process
----------------------------
|  |
|  |
        v              v              v
/etc/pwd.db     /etc/spwd.db     /etc/passwd
(db(3) format)  (db(3) format)   (ASCII password compatibility file)
(no password)   (contains password) (no password)
```

To ensure data consistency, **all password files should not be manually edited**; use tools such as vipw(8), chpass(1), or pw(8) to make modifications.

## Preventing Login

The primary measure to protect a system is to audit accounts and disable all accounts that do not need to log in.

> **Discussion**
>
> > Ensure that `root` has a strong password, rotate it regularly, and never share this password.
>
> This advice is popular but carries security risks:
>
> * Strong passwords are complex and difficult to remember, causing users to rely on insecure storage methods (such as paper notes or text files), which paradoxically increases security risks.
> * Regular password changes increase management difficulty, and the trustworthiness of "password management tools" themselves is also difficult to guarantee.
> * Key-based authentication provides some security assurance, but if a key is lost, identity verification becomes more complex.
> * Multi-factor authentication (MFA) can enhance security, but if the dependent device is lost or the application is uninstalled, similar problems arise.

There are two methods to deny account login, as described below.

First, lock the account. The following demonstrates how to lock the account `ykla`:

```sh
# pw lock ykla
```

After locking, user `ykla` attempts to log in:

```sh
FreeBSD/amd64 (ykla) (ttyv1)

login: ykla
Password:
Login incorrect
login:
```

Another user attempts to switch to `ykla`:

```sh
# su ykla
su: Sorry
```

> **Warning**
>
> Never attempt to lock the root account.
>
> ```sh
> ykla@ykla:~ $ su
> Password:
> su: Sorry
> ```
>
> Otherwise, you may need to enter single-user mode to recover.

Unlock user `ykla`:

```sh
# pw unlock ykla
```

Second, set the shell to **/usr/sbin/nologin** to prevent login. When a user attempts to log in, the nologin shell prevents the system from assigning a shell.

Only root has the authority to change other users' shells:

```sh
# chsh -s /usr/sbin/nologin ykla
```

User `ykla` is prevented from logging in, with the same effect as the previous example.

To restore login access, reassign the sh shell to user `ykla`:

```sh
# chsh -s sh ykla
```

> **Warning**
>
> Never attempt to assign **/usr/sbin/nologin** to the root account.

## Password Hashing

Since passwords must be used, they should be sufficiently complex and encrypted with a strong hashing mechanism before being stored in the password database. FreeBSD's `crypt()` library supports multiple algorithms including SHA-256, SHA-512, and Blowfish.

The default SHA-512 should not be downgraded to a weaker hashing algorithm, nor is it recommended to replace it with Blowfish. The Blowfish algorithm is not part of the AES family and does not comply with Federal Information Processing Standards (FIPS) requirements; some environments may fail compliance audits.

### Viewing the Hash Algorithm Used for the Current User's Password

To confirm the hash algorithm used by a user, the root user can check the corresponding hash value in the FreeBSD password database. Each hash value begins with a symbol indicating the type of hashing mechanism used to encrypt the password:

```sh
$number$salt$hash
```

| Hash Algorithm | Prefix Identifier     |
| -------------- | --------------------- |
| DES            | No number             |
| MD5            | `$1$`                 |
| bcrypt         | `$2a` / `$2b` / `$2y` |
| NT-Hash        | `$3$`                 |
| SHA-256        | `$5$`                 |
| SHA-512        | `$6$`                 |

Number 4 is unused.

In this example, `ykla`'s password starts with `$6$`, indicating the use of the default SHA-512 algorithm.

```sh
# grep ykla /etc/master.passwd
```

Note that the password database stores encrypted hash values, not the original passwords. The output should resemble the following:

```sh
ykla:$6$SqMJXrv5aC6Wq.by$nmbZs078aHNBVyh9noLFouJsGHyFSvQIzH0W4zpdfXuPtGtt.FHgWfXDHVBa.g9P0eZ32UwfByzRKdVnTaO7W.:1001:1001::0:0:User &:/home/ykla:/bin/sh
```

### Setting the Default Password Hash in the Login Class

The default value for `passwd_format` is **sha512**. Valid values include `blf`, `sha256`, `sha512` (recommended), as well as `des`, `md5`, `nth` (used only for compatibility with legacy password files and should not be actively chosen; see crypt(3)).

Run the following command to check the current hashing mechanism:

```sh
# grep passwd_format /etc/login.conf
```

The output should resemble the following:

```ini
    :passwd_format=sha512:\
#   :passwd_format=des:\ # This is a comment line and can be ignored
```

For example, to switch to Blowfish, modify the line to:

```ini
:passwd_format=blf:\
```

Then, you must run `cap_mkdb` to update the login.conf database:

```sh
# cap_mkdb /etc/login.conf
```

Note that this change does not affect existing password hashes. That is, all users need to run `passwd` to change their password once for the new algorithm to take effect.

### Password Policy Enforcement

Implementing strong password policies for local accounts is a fundamental system security configuration. FreeBSD uses the built-in Pluggable Authentication Modules (PAM) to control password length, strength, and complexity.

This section uses the `pam_passwdqc` module (which takes effect when users change their passwords) to set minimum and maximum password lengths and enforce mixed character types.

> **Discussion**
>
> Mandatory requirements for mixed character passwords, password rotation, and disallowing common words as complexity rules are no longer considered best security practices.
>
> Analyze these two security philosophies.

To configure, first switch to the root user, then uncomment the line containing `pam_passwdqc.so` in the **/etc/pam.d/passwd** file.

```sh
#
#
# PAM configuration for the "passwd" service
#

# passwd(1) does not use the auth, account or session services.

# password
#password       requisite       pam_passwdqc.so         enforce=users # Remove the # at the beginning of the line to enable this module
password        required        pam_unix.so             no_warn try_first_pass nullok
```

Then edit the line according to the policy: disable the first through third password classes (including passphrases), only allow four-character-class passwords (>=10 characters) or three-character-class passwords (>=12 characters); new and old passwords must not be similar; allow a maximum of 3 retries; enforce only for regular users (root is not constrained).

```ini
password        requisite       pam_passwdqc.so         min=disabled,disabled,disabled,12,10 similar=deny retry=3 enforce=users
```

Parameter meanings:

`min=disabled,disabled,disabled,12,10` corresponds to five password complexity levels:

| No. | Character Class Requirement      | Minimum Length | Status   |
| --- | -------------------------------- | -------------- | -------- |
| 1   | Only one character class         | \u2014         | Disabled |
| 2   | Only two character classes       | \u2014         | Disabled |
| 3   | **Passphrase**                   | \u2014         | Disabled |
| 4   | Includes three character classes | 12 characters  | Enabled  |
| 5   | Includes four character classes  | 10 characters  | Enabled  |

Character classes include: digits, lowercase letters, uppercase letters, and other characters. Non-ASCII characters that cannot be classified are treated as non-digit classes.

After saving the file, users will see a prompt similar to the following when changing their password:

```sh
$ passwd
```

The output should resemble the following:

```
Changing local password for ykla
Old Password:

You can now choose the new password.
A valid password should be a mix of upper and lower case letters,
digits and other characters.  You can use a 12 character long
password with characters from at least 3 of these 4 classes, or
a 10 character long password containing characters from all the
classes.  Characters that form a common pattern are discarded by
the check.
Alternatively, if noone else can see your terminal now, you can
pick this as your password: "embark,France_list".
```

If the password does not comply with the policy, the system rejects it and displays a warning, for example:

```sh
Weak password: too short.
```

Users can make multiple attempts within the configured retry count.

If an organization requires passwords to expire periodically, FreeBSD can set the `passwordtime` parameter in the user's login class in **/etc/login.conf**.

The `default` login class includes an example:

```ini
#       :passwordtime=90d:\
```

To set a 90-day expiration for this login class, remove the comment character (`#`), save, and then run:

```sh
# cap_mkdb /etc/login.conf
```

To set a password change date (password aging, the password must be changed before the specified date) for a single user `ykla`, pass both the date (or number of days until expiration) and the username to `pw`:

```sh
# pw usermod -p 31-05-2026 -n ykla
```

The date is set in the format day, month, year (`dd-mmm-yy[yy]`, where the month can be a number or letter abbreviation).

To remove the password change date restriction, set it to 0:

```sh
# pw usermod -p 0 -n ykla
```

> **Note**
>
> `-p` sets the password change date (password aging), which is a different concept from account expiration. To set an account expiration time, use the `-e` parameter.

From today, set the specified user ykla's account to expire in 30 days:

```sh
# pw usermod ykla -e +30d
```

From today, set the specified user ykla's account to expire in one year:

```sh
# pw usermod ykla -e +1y
```

## Exercises

1. In FreeBSD, the password hash value stored in the **/etc/master.passwd** file begins with the `$6$` prefix. Research and explain the hash algorithm corresponding to this prefix, and compare its security with the `$2b$` prefix.
2. After locking a test account using the `pw lock` command, attempt to log in via both a local terminal and SSH, and record the differences in the error messages from the two attempts.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/ask/flat/chapter-29-security/di-29.2-jie-zhang-hu-ren-zheng-an-quan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
