#!/usr/bin/perl use 5.010_000; use warnings; use strict; =head1 NAME fripost-passwd - Change password of user =head1 SYNOPSIS B [B<--verbose>] [B<--debug>] [B<--pretend>] [I] [B<--password=>I] =head1 DESCRIPTION B changes the password of I, unless B<--pretend> is set. If I or I are not given, the user is prompted for them. If I is not fully qualified, C is appended. If I is not an existing username, B raises an error. =head1 OPTIONS =over 8 =item B<--pretend> Only simulates the insertion. (But still query the LDAP server to ensure that I is a known user.) =item B<--password=>I By default, the user is prompted for his/her new password, which is hashed, salted and then added to the LDAP entry. By using B<--password>, I is inserted RAW in the database. This can be useful if the user does not want to give the clear copy but only a hash, for example. =item B<--server_host=>I The LDAP URI to connect to. Defaults to C. =item B<--bind_dn=>I The Distinguished Name (DN) to bind to the LDAP directory. (If not set, B binds anonymously.) The default value is read from the configuration file, see B. =item B<--bind_pw=>I The password to to bind with. The default value is read from the configuration file, see B. =item B<--base_dn=>I The root DN for everything done by B. The default value is read from the configuration file, see B. =item B<-v>, B<--verbose> Verbose mode. =item B<--debug> Debug mode. =back =head1 CONFIGURATION The configuration is read from the file C<$HOME/.fripost.yml>. Valid keys include: =over 4 =item I The LDAP URI to connect to. It has to be set, either in the configuration file, or using the command line option B<--server_host>. =item I The Distinguished Name (DN) to bind to the LDAP directory. (If not set, B binds anonymously.) =item I The password to to bind with. =item I The root DN for everything done by B. =back =cut # TODO: add flag --reset to automatically generate a new password and # send it to the user (in case he/she has forgotten the password). use FindBin qw($Bin); use lib "$Bin/lib"; use Env qw /HOME/; use File::Spec::Functions; use Fripost::Password; use Fripost::Prompt; use Fripost::Schema; use Getopt::Long qw /:config noauto_abbrev no_ignore_case gnu_compat bundling permute nogetopt_compat auto_version auto_help/; use Pod::Usage; use YAML::Syck; ## Get command line options our $conf = LoadFile( catfile ($HOME, '.fripost.yml') ); GetOptions( 'server_host=s' => \$conf->{server_host}, 'base_dn=s' => \$conf->{base_dn}, 'bind_dn=s' => \$conf->{bind_dn}, 'bind_pw=s' => \$conf->{bind_pw}, 'pretend' => \$conf->{pretend}, 'debug' => \$conf->{debug}, 'v|verbose' => \$conf->{verbose}, 'password=s' => \$conf->{password}, 'man' => sub { pod2usage(-exitstatus => 0, -verbose => 2) } ) or pod2usage(2); sub vsay { say STDERR @_ if $conf->{verbose} || $conf->{debug}; } # Connect to the LDAP server my $ldap = Fripost::Schema->new( $conf ); my $username; if (defined $ARGV[0]) { $username = fix_username ($ARGV[0]); Email::Valid->address($username) or die "Error: `" .$username. "' is not a valid e-mail.\n"; } else { $username = prompt_email("Username: ", 'is_user'); } my $password = $conf->{password}; $password //= hash( prompt_password() ); # Ensure that the user exists. my $domain = (split /\@/, $username, 2)[1]; die "Error: Unknown domain `" .$domain. "'.\n" unless $ldap->domain->search({ domain => $domain })->count; die "Error: Unknown user `" .$username. "'.\n" unless $ldap->user->search({ username => $username })->count; if ($conf->{pretend}) { vsay "Nothing to do since we are pretending..."; exit 0; } # Change the password. $ldap->user->passwd({ username => $username, userPassword => $password }); say "Updated password for $username."; $ldap->unbind(); =head1 AUTHOR Stefan Kangas C<< >> Guilhem Moulin C<< >> =head1 COPYRIGHT Copyright 2010 Stefan Kangas. Copyright 2012 Guilhem Moulin. =head1 LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as perl itself. =cut