PW_POLICY(3)

NAME
pw_policy_load, pw_policy_test - password policy enforcement

LIBRARY
libutil

SYNOPSIS
#include <util.h>
pw_policy_t
pw_policy_load(void *key, int how);
int
pw_policy_test(pw_policy_t policy, char *pw);
void
pw_policy_free(pw_policy_t policy);

DESCRIPTION
The pw_policy_load(), pw_policy_test(), and pw_policy_free() functions are used as an interface to the system's password policy as specified in /etc/passwd.conf.

pw_policy_load() will load a password policy and return a pointer to a pw_policy_t containing it. It is the caller's responsibility to free this pointer using pw_policy_free().

Using pw_getconf(3) terminology, pw_policy_load() accepts a key to be used when searching /etc/passwd.conf for a password policy. This key contains various options describing different policies. Some built-in ones are described along with their syntax below.

To allow calling from various program contexts and using various password policy retrieval schemes, how tells pw_policy_load() how to treat key.

Possible values for how are:

PW_POLICY_BYSTRING
    key is used as a char *, looking up the string it contains in /etc/passwd.conf.

PW_POLICY_BYPASSWD
    key is used as a struct passwd *, first looking up the username in pw_name, and if no key can be found, it will try the login class in pw_class.

PW_POLICY_BYGROUP
    key is used as a struct group *, looking up the group name in gr_name.

If key is NULL, or no specified key can be found, the default key, “pw_policy”, is used. If even the default key can't be found, the password is accepted as no policy is defined.

pw_policy_test() can be used to check if the password in pw is compliant with the policy in policy.

BUILT-IN POLICY SYNTAX
Available built-in policy options include the following:

length
    Length of the password.
uppercase
    Number of upper-case characters in the password.
lowercase
    Number of lower-case characters in the password.
digits
    Number of digits in the password.
punctuation
    Number of punctuation characters in the password.
nclasses
    Number of different character classes in the password.
ntoggles
    How often a user has to toggle between character classes in the password.

Options are used inside keys. An option uses a format of “option = value”. For the built-in options, we use either “N” or “N-M” for the value.

The first, “N” format, specifies a single length. For example, the following option specifies that the password should have exactly 3 upper-case characters:

    uppercase = 3

The second, “N-M” format, can be used to specify a range. Forcing a policy for number of digits between 1 and 4 would be:

    digits = 1-4

The characters ‘0’ and ‘*’ can also be used to indicate “not allowed” and “any number”, respectively. To illustrate, the following example states that the number of punctuation characters should be at least two:

    punctuation = 2-*

No more than 7 digits:

    digits = *-7

Any number of lower-case characters:

    lowercase = *

Upper-case characters not allowed:

    uppercase = 0

To specify that the password must be at least 8 characters long:

    length = 8-*

Specifying a password must have at least 3 different character classes:

    nclasses = 3-*

And that the user must change character class every 2 characters:

    ntoggles = *-2

Note that when using the “nclasses” directive, the policy will be initialized to allow any number of characters from all classes. If desired, this should be overridden after the “nclasses” option.

RETURN VALUES
pw_policy_load() returns a pw_policy_t on success, or NULL on failure, in which case the errno variable will be set to any of the following values indicating the reason for the failure:

[ENOENT]
    The /etc/passwd.conf is missing.

[EINVAL]
    Invalid value for the how parameter or an invalid value in the password policy specification.

pw_policy_load() can also set errno to a value returned by the called handlers and/or malloc(3).

pw_policy_test() returns 0 if the password follows the policy, or -1 if it doesn't, errno can be set to any of the following values:

[EPERM]
    The password does not follow the password policy.

[EINVAL]
    NULL pointer was passed as the password.

In addition, errno can be set to any error code returned by the handlers.

FILES
/etc/passwd.conf
    password configuration file.

EXAMPLES
Declare a password policy storage:

    pw_policy_t policy;

Load the system global password policy into policy:

    policy = pw_policy_load(NULL, 0);
    if (policy == NULL)
    	errx(1, "Can't load password policy");

Load a policy for a user whose password database entry is in pw_entry into policy:

    policy = pw_policy_load(pw_entry, PW_POLICY_BYPASSWD);
    if (policy == NULL)
    	errx(1, "Can't load password policy for \"%s\"", pw_entry-pw_name);

Note that pw_policy_load() will first look for a password policy for the username in pw_entry-pw_name, if not found, it will try looking for a policy for the login class in pw_entry-pw_class, and if it can't find such either it will fallback to the default key, “pw_policy”.

Load the password policy for a group whose group database entry is in grent, into policy:

    policy = pw_policy_load(grent, PW_POLICY_BYGROUP);
    if (policy == NULL)
    	errx(1, "Can't load password policy for \"%s\"", grent-gr_name);

Check if the_password follows the policy in policy:

    if (pw_policy_test(policy, the_password) != 0)
    	warnx("Please refer to the password policy");

After finished using the password policy, free it:

    pw_policy_free(policy);

An example for a common default password policy in /etc/passwd.conf:

    pw_policy:
      length = 8-*		# At least 8 characters long,
      lowercase = 1-*	# combining lowercase,
      uppercase = 1-*	# uppercase,
      digits = 1-*		# and digits.
      punctuation = *	# Punctuation is optional.

A different policy that might be used:

      nclasses = 3-*	# At least 3 different character classes,
      ntoggles = *-2	# not more than 2 same class in a row.

SEE ALSO
pw_getconf(3), passwd.conf(5)

HISTORY
The pw_policy_load(), pw_policy_test(), and pw_policy_free() functions first appeared in NetBSD 4.0.

AUTHORS
Elad Efrat <elad@NetBSD.org>