PWQUALITY(3)
π pwquality β the libpwquality API, explained bestie-to-bestie π
okay so you wanna talk to libpwquality directly?? periodt. this is the C API for checking and generating passwords, and it's genuinely iconic. grab a strawberry π and let's get into it.
β¨ NAME β¨
pwquality β literally the documentation for the libpwquality API. that's it, that's the whole name section, no notes. π
πΈ SYNOPSIS πΈ
first things first, you gotta include the header, no cap:
#include <pwquality.h>
and here's the whole squad of functions, in order, exactly as they live:
pwquality_settings_t *pwquality_default_settings(void);
void pwquality_free_settings(pwquality_settings_t *pwq);
int pwquality_read_config(pwquality_settings_t *pwq, const char *cfgfile,
void **auxerror);
int pwquality_set_option(pwquality_settings_t *pwq, const char *option);
int pwquality_set_int_value(pwquality_settings_t *pwq, int setting, int value);
int pwquality_set_str_value(pwquality_settings_t *pwq, int setting,
const char *value);
int pwquality_get_int_value(pwquality_settings_t *pwq, int setting, int *value);
int pwquality_get_str_value(pwquality_settings_t *pwq, int setting, const char **value);
int pwquality_generate(pwquality_settings_t *pwq, int entropy_bits,
char **password);
int pwquality_check(pwquality_settings_t *pwq, const char *password,
const char *oldpassword, const char *user, void **auxerror);
const char *pwquality_strerror(char *buf, size_t len, int errcode, void *auxerror);
like, look at that lineup. main character energy fr. π
π¦ DESCRIPTION π¦
starting out: settings objects
pwquality_default_settings() allocates and hands you back some default pwquality settings, which you then use in all the other library calls. it's giving starter pack. β¨
the allocated opaque structure has to be freed with pwquality_free_settings(). do not skip this, bestie, that's a leak and we don't do those. π
reading your config
pwquality_read_config() parses the configuration file β and if cfgfile is NULL, it just goes with the default one. if auxerror is not NULL, it might also hand back auxiliary error info, and you must pass that into pwquality_strerror(). don't lose it. π
New in 1.3.0: the library first tries to parse all *.conf configuration files from the <cfgfile>.d directory, if that directory exists. the order of parsing is what determines the values that end up in effect β the latest one wins. slay.
setting options like a pam module
pwquality_set_option() is the one you want when you're setting options the way they show up on a pam module command line, in the form opt=val. cute and convenient. π
getters and setters for days
the getter and setter functions for the individual integer and string setting values are:
pwquality_set_int_value()pwquality_set_str_value()pwquality_get_int_value()pwquality_get_str_value()
heads up about the string getter specifically: the caller must copy the string before making any other calls that can manipulate the pwq settings object. otherwise it's giving undefined chaos. π
generating passwords
pwquality_generate() generates a random password with entropy_bits of entropy, then checks it against your settings. the *password is allocated on the heap by the library (so yes, that's yours to deal with).
also, the entropy_bits value gets adjusted to fit within the PWQ_MIN_ENTROPY_BITS and PWQ_MAX_ENTROPY_BITS range before a password is generated. it self-corrects, we love a flexible queen. π
checking passwords
pwquality_check() checks the password against your settings. it returns either a score (a value between 0 and 100), a negative error number, and possibly also auxiliary error information that you must pass into pwquality_strerror().
the details, bestie:
oldpasswordis optional and can beNULL.useris used for checking the password against the user name and potentially otherpasswd(5)information β and it can beNULL.auxerrorcan beNULLβ in that case the auxiliary error information just isn't returned.- but if it is non-
NULL, then not passing the returned*auxerrorintopwquality_strerror()can lead to memory leaks. π so like. do that.
and here's the tea about scoring: the score of a password depends on the value of the setting PWQ_SETTING_MIN_LENGTH. if that's set higher, the score for the same passwords will be lower. yes, that's just how it works, iykyk.
turning errors into words
pwquality_strerror() translates the errcode and the auxerror auxiliary data into a localized text message. πΈ
- if
bufisNULL, the function uses an internal static buffer β which makes the function non-reentrant in that case. so watch out. - the returned pointer is not guaranteed to point to the
buf. rude, but true. - the function deallocates any eventual
auxerrordata passed into it, so it must not be called twice with the sameauxerrordata. once and done, periodt. π
β RETURN VALUES β
generally speaking, the functions that return int return 0 for success and negative values as a concrete PWQ_ERROR error code. and pwquality_strerror()? it doesn't allocate data, so it literally cannot fail. icon behavior. π«Ά
now, about the positive-or-zero score from pwquality_check():
do not use it for rejection of passwords!! it should only be used as an approximate indicator of the entropy present in the password.
the vibe check on those ranges:
0-30β low30-60β medium60-100β high
π EXAMPLE π
here's a typical use of the libpwquality API, exactly as it goes:
#include <pwquality.h>
...
pwquality_settings_t *pwq;
int rv;
void *auxerror;
char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
pwq = pwquality_default_settings();
if (pwq == NULL) {
fprintf(stderr, "Error: %s\n", pwquality_strerror(buf, sizeof(buf), PWQ_ERROR_MEM_ALLOC, NULL));
return -1;
}
if ((rv=pwquality_read_config(pwq, NULL, &auxerror)) != 0) {
pwquality_free_settings(pwq);
fprintf(stderr, "Error: %s\n", pwquality_strerror(buf, sizeof(buf), rv, auxerror));
return -1;
}
rv = pwquality_check(pwq, buf, NULL, user, &auxerror);
pwquality_free_settings(pwq);
if (rv >= 0) {
fprintf(stderr, "Password entropy score is: %d\n", rv);
} else {
fprintf(stderr, "Password is rejected with error: %s\n", pwquality_strerror(buf, sizeof(buf), rv, auxerror));
}
see how it frees the settings in every branch?? that's the whole game. π§
π SEE ALSO π
go read it, it's the whole vibe. π
π AUTHORS π
Tomas Mraz <tmraz@redhat.com> β the legend who made this happen.
and that's a wrap, bestie!! this page is from the Libpwquality API Manual, dated 2021-04-01, and it's brought to you by Red Hat, Inc. β PWQUALITY(3), signed, sealed, slayed. π
β¨π
π¦ where this page comes from
- alpine 3.24: libpwquality-doc 1.4.5-r6 Β· BSD-3-Clause
- centos-stream 10: libpwquality-devel 1.4.5-13.el10 Β· BSD-3-Clause OR GPL-2.0-or-later
- debian bookworm: libpwquality-dev 1.4.5-1+b1 Β· libpwquality OR GPL-2.0-or-later
- debian trixie: libpwquality-dev 1.4.5-5 Β· libpwquality OR GPL-2.0-or-later
- fedora 43: libpwquality-devel 1.4.5-14.fc43 Β· BSD-3-Clause OR GPL-2.0-or-later
- fedora 43: libpwquality-devel 1.4.5-14.fc43 Β· BSD-3-Clause OR GPL-2.0-or-later
- fedora 44: libpwquality-devel 1.4.5-15.fc44 Β· BSD-3-Clause OR GPL-2.0-or-later
- fedora 44: libpwquality-devel 1.4.5-15.fc44 Β· BSD-3-Clause OR GPL-2.0-or-later
- opensuse-leap 16.0: libpwquality1 1.4.5-160000.3.2 Β· BSD-3-Clause OR GPL-2.0-or-later
- opensuse-leap 16.0: libpwquality1 1.4.5-160000.3.2 Β· BSD-3-Clause OR GPL-2.0-or-later
- opensuse-leap 16.0: libpwquality1 1.4.5-160000.3.2 Β· BSD-3-Clause OR GPL-2.0-or-later
- opensuse-leap 16.0: libpwquality1 1.4.5-160000.3.2 Β· BSD-3-Clause OR GPL-2.0-or-later
- ubuntu noble: libpwquality-dev 1.4.5-3build1 Β· libpwquality OR GPL-2.0-or-later
- ubuntu questing: libpwquality-dev 1.4.5-5
- ubuntu resolute: libpwquality-dev 1.4.5-5build1 Β· libpwquality OR GPL-2.0-or-later
- ubuntu stonking: libpwquality-dev 1.4.5-5build1 Β· libpwquality OR GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms