Readonly my $STRENGTH_USER => 'nobody';
Readonly my $STRENGTH_GROUP => 'nogroup';
+# Global boolean variable saying whether to log with syslog. This is set
+# based on the presence of the -q (--quiet) command-line option.
+my $SYSLOG = 1;
+
##############################################################################
# Utility functions
##############################################################################
# - error: an error message explaining the anomalous situation
#
# Values containing whitespace are quoted with double quotes, with any
-# internal double quotes doubled.
+# internal double quotes doubled. No logging will be done if $SYSLOG is
+# false.
#
# $principal - Principal for which we checked a password
# $error - The error message
# Returns: undef
sub log_error {
my ($principal, $error) = @_;
+ if (!$SYSLOG) {
+ return;
+ }
my $message = encode_log_message(
action => 'check',
principal => $principal,
# - reason: the reason for a rejection
#
# Values containing whitespace are quoted with double quotes, with any
-# internal double quotes doubled.
+# internal double quotes doubled. No logging will be done if $SYSLOG is
+# false.
#
# $principal - Principal for which we checked a password
# $result - "accepted" or "rejected" per above
# Returns: undef
sub log_result {
my ($principal, $result, $reason) = @_;
+ if (!$SYSLOG) {
+ return;
+ }
# Create the message.
my %message = (
# allows us to chain to another program that handles the actual strength
# checking prior to handling history.
#
+# $path - Password quality check program to run
# $principal - Principal attempting to change their password
# $password - The new password
#
# Throws: Text exception on failure to execute the program, or read or write
# from it or to it, or if it fails without an error
sub strength_check {
- my ($principal, $password) = @_;
+ my ($path, $principal, $password) = @_;
# Run the external quality checking program. If we're root, we'll run it
# as the strength checking user and group.
my $in = "principal: $principal\nnew-password: $password\nend\n";
my $init = sub { drop_privileges($STRENGTH_USER, $STRENGTH_GROUP) };
my ($out, $err);
- run([$STRENGTH_PROGRAM, $principal], \$in, \$out, \$err, init => $init);
+ run([$path, $principal], \$in, \$out, \$err, init => $init);
my $status = ($? >> 8);
# Check the results.
['database|d=s', 'Path to the history database, overriding the default'],
['help|h', 'Print usage message and exit'],
['manual|man|m', 'Print full manual and exit'],
+ ['quiet|q', 'Suppress logging to syslog'],
['stats|S=s', 'Path to hash of length statistics'],
['strength|s=s', 'Path to strength checking program to run'],
);
}
my $database = $opt->database || $HISTORY_PATH;
my $stats_db = $opt->stats || $LENGTH_STATS_PATH;
+my $strength = $opt->strength || $STRENGTH_PROGRAM;
# If asked to do benchmarking, ignore other arguments and just do that.
# Currently, we hard-code a 0.005-second granularity on our binary search.
}
# Open syslog for result reporting.
-openlog($0, 'pid', LOG_AUTH);
+if ($opt->quiet) {
+ $SYSLOG = 0;
+} else {
+ openlog($0, 'pid', LOG_AUTH);
+}
# Read the principal and password that we're supposed to check.
my ($password, $principal) = read_change_data(\*STDIN);
# Delegate to the external strength checking program.
-my ($okay, $error, $status) = strength_check($principal, $password);
+my ($okay, $error, $status) = strength_check($strength, $principal, $password);
if (!$okay) {
log_result($principal, 'rejected', $error);
warn "$error\n";
##############################################################################
=for stopwords
-heimdal-history heimdal-strength Heimdal -hm BerkeleyDB timestamps POSIX
+heimdal-history heimdal-strength Heimdal -hmq BerkeleyDB timestamps POSIX
whitespace API Allbery sublicense MERCHANTABILITY NONINFRINGEMENT syslog
pseudorandom JSON LDAP-compatible PBKDF2 SHA-256
=head1 SYNOPSIS
-B<heimdal-history> [B<-hm>] [B<-b> I<target-time>] [B<-d> I<database>]
+B<heimdal-history> [B<-hmq>] [B<-b> I<target-time>] [B<-d> I<database>]
[B<-S> I<length-stats-db>] [B<-s> I<strength-program>] [B<principal>]
=head1 DESCRIPTION
Display this manual and exit.
+=item B<-q>, B<--quiet>
+
+Suppress logging to syslog and only return the results on standard output
+and standard error. Primarily used for testing, since Heimdal won't pass
+this argument.
+
=item B<-S> I<length-stats-db>, B<--stats>=I<length-stats-db>
Use I<length-stats-db> as the database file for password length statistics