PWQUALITY(3)

πŸ“¦
version 1.4.5 Β· 4 versions
, in alpine 3.24, centos-stream 10, debian bookworm, debian trixie, fedora 43, fedora 44, opensuse-leap 16.0, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– 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:

  • oldpassword is optional and can be NULL.
  • user is used for checking the password against the user name and potentially other passwd(5) information β€” and it can be NULL.
  • auxerror can be NULL β€” in that case the auxiliary error information just isn't returned.
  • but if it is non-NULL, then not passing the returned *auxerror into pwquality_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 buf is NULL, 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 auxerror data passed into it, so it must not be called twice with the same auxerror data. 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 β€” low
  • 30-60 β€” medium
  • 60-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