Projects/Password quality pluggable interface
Contents
Purpose
This project is to create a pluggable interface for password quality checking. This interface will make use of the framework described in Projects/Plugin_support_improvements.
Scope
Password quality modules will be able to make use of:
- The realm configured dictionary.
- The principal name.
- The new password.
- The name of the password policy associated with the principal, if any.
To preserve the simplicity of the interface, modules will not have convenient access to:
- The information in the password policy.
- The principal's database entry.
- Current or historical keys used by the principal.
If necessary, modules can look up this information in the KDB by making use of the krb5_context passed to them.
Interface
The pluggable interface will have the following methods:
/* An abstract type for password quality module data. */ typedef struct krb5_pwqual_moddata_st *krb5_pwqual_moddata;
/* Optional: Initialize module data. dictfile is the realm's configured * dictionary filename. */ typedef krb5_error_code (*krb5_pwqual_open_fn)(krb5_context context, const char *dict_file, krb5_pwqual_moddata *data);
/* * Mandatory: Check a password for the principal princ, which has an associated * password policy named policy_name (or no associated policy if policy_name is * NULL). The parameter languages, if not NULL, contains a null-terminated * list of client-specified language tags as defined in RFC 5646. The method * should return one of the following errors if the password fails quality * standards: * * - KADM5_PASS_Q_TOOSHORT: password should be longer * - KADM5_PASS_Q_CLASS: password must have more character classes * - KADM5_PASS_Q_DICT: password contains dictionary words * - KADM5_PASS_Q_GENERIC: unspecified quality failure * * The module should also set an extended error message with * krb5_set_error_message(). The message may be localized according to one of * the language tags in languages. */ typedef krb5_error_code (*krb5_pwqual_check_fn)(krb5_context context, krb5_pwqual_moddata data, const char *password, const char *policy_name, krb5_principal princ, const char **languages);
/* Optional: Release resources used by module data. */ typedef void (*krb5_pwqual_close_fn)(krb5_context context, krb5_pwqual_moddata data);
/* Password quality plugin vtable for major version 1. */ typedef struct krb5_pwqual_vtable_st { krb5_pwqual_open_fn open; krb5_pwqual_check_fn check; krb5_pwqual_close_fn close; /* Minor version 1 ends here. */ } *krb5_pwqual_vtable;
Consumer API
The consumer API used by libkadm5srv has the following types and functions:
/* A pwqual_handle represents a password quality plugin module. */ typedef struct pwqual_handle_st *pwqual_handle;
/* Load all available password quality plugin modules, perform resource binding * of the realm's dictionary file, and store the result into *handles_out. Free * the result with k5_pwqual_free_handles. */ krb5_error_code k5_pwqual_load(krb5_context context, const char *dict_file, pwqual_handle **handles_out);
/* Release a handle list allocated by k5_pwqual_load. */ void k5_pwqual_free_handles(krb5_context context, pwqual_handle *handles);
/* Check a password using a password quality plugin module. */ krb5_error_code k5_pwqual_check(krb5_context context, pwqual_handle handle, const char *password, const char *policy_name, krb5_principal princ);
No wrappers are provided for the open or close methods because they are considered to be part of resource binding, and thus are taken care of by the _load and _free_handles functions.
Built-In Modules
The following modules will replace current built-in mechanisms for checking password quality. These can be disabled through plugin configuration.
- empty: Prohibits empty passwords, whether or not the principal has a password policy.
- princ: Prohibits passwords matching components of the principal name. Only operable if the principal has a password policy.
- hesiod: Prohibits passwords matching the GECOS fields of Hesiod password information for components of the principal name. Only operable if the principal has a password policy and the Kerberos tree was built with Hesiod support.
- dict: Prohibits passwords matching words in the realm's dictionary file. Only operable if the principal has a password policy and the realm has a configured dictionary file.
Two other built-in mechanisms for checking password policy exist: enforcement of the password policy's minimum length and minimum number of character classes, and checking the new password against the current and historical key information. These mechanisms are out of scope for the pluggable interface.
Implementation Plan
Work will take place on the plugins2 branch. The following will be added to create the pluggable interface:
- A public, installed header file <krb5/pwqual_plugin.h>.
- An interface ID number defined in k5-int.h.
- An interface name defined in the table in lib/krb5/krb/plugin.c.
The consumer API and built-in modules will be part of libkadm5srv in the following files:
- server_internal.h: Declarations for consumer API.
- pwqual.c: Consumer API loader function and wrapper functions.
- pwqual_empty.c: Module for rejecting empty passwords.
- pwqual_princ.c: Module for checking against principal components.
- pwqual_hesiod.c: Module for checking against Hesiod GECOS information.
- pwqual_dict.c: Module for checking against realm dictionary file.
server_init.c and server_misc.c will be modified to use the consumer API.
Testing
The existing test suite should exercise the built-in plugins and the consumer API. Dynamic plugin functionality will be manually tested by modifying Russ Allbery's krb5-strength package to use the pluggable interface and verifying that it works.