NetBSD/lib/libutil/pw_policy.3
elad 8d6270e665 Introduce pw_policy(3), an easily extendable way of defining password
policies and enforcing them in programs.

Man-page written with much help and tips from David Maxwell, Hubert
Feyrer, and Thomas Klausner.

This bumps libutil minor to 7.

XXX: Need default policy to go in /etc/passwd.conf, and integration
     into local/yp/PAM password changing code.

PR/10206.
2005-09-14 11:36:52 +00:00

297 lines
7.1 KiB
Groff

.\" $NetBSD: pw_policy.3,v 1.1 2005/09/14 11:36:52 elad Exp $
.\"
.\" Copyright 2005 Elad Efrat <elad@NetBSD.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. The name of the Author may not be used to endorse or promote
.\" products derived from this software without specific prior written
.\" permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd September 13, 2005
.Dt PW_POLICY 3
.Os
.Sh NAME
.Nm pw_policy_test
.Nd password policy enforcement
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In util.h
.Ft int
.Fn pw_policy_test "char *pw" "void *key" "int how"
.Sh DESCRIPTION
The
.Fn pw_policy_test
function checks if the password passed in
.Ar pw
follows the system's password policy as specified in
.Pa /etc/passwd.conf .
.Pp
Using
.Xr pw_getconf 3
terminology,
.Fn pw_policy_test
accepts a
.Ar key
to be used when searching
.Pa /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.
.Pp
To allow calling from various program contexts
and using various password policy retrieval schemes,
.Ar how
tells
.Fn pw_policy_test
how to treat
.Ar key .
.Pp
The value of
.Ar how
can be
.Dv PW_POLICY_BYSTRING
to indicate the passed
.Ar key
is to be used as a
.Ft char * ,
looking up the string it contains in
.Pa /etc/passwd.conf .
.Pp
If
.Ar how
is
.Dv PW_POLICY_BYPASSWD ,
.Ar key
is used as a
.Ft struct passwd * ,
first looking up the username in
.Ft pw_name ,
and if no key can be found, it will try the login class in
.Ft pw_class .
.Pp
Using the value
.Dv PW_POLICY_BYGROUP
for
.Ar how
will use
.Ar key
as a
.Ft struct group * ,
looking up the group name in
.Ft gr_name .
.Pp
If
.Ar key
is
.Dv NULL ,
or no specified key can be found, the default key,
.Dq pw_policy ,
is used.
If even the default key can't be found,
the password is accepted as no policy is defined.
.Sh BUILT-IN POLICY SYNTAX
Available built-in policy options include the following:
.Pp
.Bl -tag -width kungfuninja -compact
.It length
Length of the password.
.It uppercase
Number of upper-case characters in the password.
.It lowercase
Number of lower-case characters in the password.
.It digits
Number of digits in the password.
.It punctuation
Number of punctuation characters in the password.
.It nclasses
Number of different character classes in the password.
.It ntoggles
How often a user has to toggle between character classes in the password.
.El
.Pp
Options are used inside keys.
An option uses a format of
.Dq option = value .
For the built-in options, we use either
.Dq N
or
.Dq N-M
for the value.
.Pp
The first,
.Dq N
format, specifies a single length.
For example, the following option specifies that the password should
have exactly 3 upper-case characters:
.Bd -literal -offset indent
uppercase = 3
.Ed
.Pp
The second,
.Dq N-M
format, can be used to specify a range.
Forcing a policy for number of digits between 1 and 4 would be:
.Bd -literal -offset indent
digits = 1-4
.Ed
.Pp
The characters
.Sq 0
and
.Sq *
can also be used to indicate
.Dq not allowed
and
.Dq any number ,
respectively.
To illustrate, the following example states that the number of
punctuation characters should be at least two:
.Bd -literal -offset indent
punctuation = 2-*
.Ed
.Pp
No more than 7 digits:
.Bd -literal -offset indent
digits = *-7
.Ed
.Pp
Any number of lower-case characters:
.Bd -literal -offset indent
lowercase = *
.Ed
.Pp
Upper-case characters not allowed:
.Bd -literal -offset indent
uppercase = 0
.Ed
.Pp
To specify that the password must be at least 8 characters long:
.Bd -literal -offset indent
length = 8-*
.Ed
.Pp
Specifying a password must have at least 3 different character classes:
.Bd -literal -offset indent
nclasses = 3-*
.Ed
.Pp
And that the user must change character class every 2 characters:
.Bd -literal -offset indent
ntoggles = *-2
.Ed
.Sh RETURN VALUES
Upon success, meaning the password follows the specified policy,
.Fn pw_policy_test
will return 0.
.Pp
.Fn pw_policy_test
will fail and return any of the following if:
.Bl -tag -width Er
.It Bq Er EPERM
The password does not follow the specified policy.
.It Bq Er EFAULT
The password string provided is
.Dv NULL .
.It Bq Er ENOENT
.Pa /etc/passwd.conf
could not be found.
.It Bq Er EINVAL
.Ar how
has an invalid value.
.El
.Sh FILES
.Bl -tag -width /etc/passwd.conf -compact
.It Pa /etc/passwd.conf
password configuration file.
.El
.Sh EXAMPLES
To check if
.Ar the_password
follows the system's default password policy:
.Bd -literal -offset indent
error = pw_policy_test(the_password, NULL, 0);
if (error == EPERM)
(void)printf("Please refer to the password policy.\en");
.Ed
.Pp
To check if
.Ar the_password ,
entered by a user whose password database entry is in
.Ar pw_entry
follows the specified policy:
.Bd -literal -offset indent
error = pw_policy_test(the_password, pw_entry, PW_POLICY_BYPASSWD);
if (error == EPERM) {
(void)printf("Please refer to the password policy.\en");
return (EPERM);
}
.Ed
.Pp
Note that
.Fn pw_policy_test
will first look for a password policy for the username in
.Ar pw_entry-\*[Gt]pw_name ,
if not found, it will try looking for a policy for the login class in
.Ar pw_entry-\*[Gt]pw_class ,
and if it can't find such either it will fallback to the default key,
.Dq pw_policy .
.Pp
To handle cases where there is no
.Pa /etc/passwd.conf ,
it might be desired to fallback to an internal policy:
.Bd -literal -offset indent
error = pw_policy(the_password, NULL, 0);
if (error == ENOENT) {
/* No /etc/passwd.conf. Just check minimum length. */
if (strlen(the_password) \*[Lt] 8) {
(void)printf("Please use at least 8 chars.\en");
return (EPERM);
}
}
.Ed
.Pp
An example for a common default password policy in
.Pa /etc/passwd.conf :
.Bd -literal -offset indent
pw_policy:
length = 8-* # At least 8 characters long,
lowercase = 1-* # combining lowercase,
uppercase = 1-* # uppercase,
digits = 1-* # and digits.
punctuation = * # Punctuation is optional.
.Ed
.Pp
A different policy that might be used:
.Bd -literal -offset indent
nclasses = 3-* # At least 3 different character classes,
ntoggles = *-2 # not more than 2 same class in a row.
.Ed
.Sh SEE ALSO
.Xr pw_getconf 3 ,
.Xr passwd.conf 5
.Sh HISTORY
The
.Nm
function first appeared in
.Nx 4.0 .
.Sh AUTHORS
.An Elad Efrat
.Aq elad@NetBSD.org