svn commit: r235791 - user/des/fbce/lib/FBCE/Script
Dag-Erling Smorgrav
des at FreeBSD.org
Tue May 22 16:40:21 UTC 2012
Author: des
Date: Tue May 22 16:40:20 2012
New Revision: 235791
URL: http://svn.freebsd.org/changeset/base/235791
Log:
Add commands to set users' names and generate passwords.
Modified:
user/des/fbce/lib/FBCE/Script/User.pm
Modified: user/des/fbce/lib/FBCE/Script/User.pm
==============================================================================
--- user/des/fbce/lib/FBCE/Script/User.pm Tue May 22 16:39:38 2012 (r235790)
+++ user/des/fbce/lib/FBCE/Script/User.pm Tue May 22 16:40:20 2012 (r235791)
@@ -4,6 +4,7 @@ use Moose;
use MooseX::Types::Common::Numeric qw/PositiveInt/;
use MooseX::Types::Moose qw/Str Bool Int/;
use FBCE;
+use Archive::Tar;
use LWP::UserAgent;
use namespace::autoclean;
@@ -29,6 +30,9 @@ our %lwp_options = (
# Cutoff URLs for various repos
sub cutoff_url($) { "http://people.freebsd.org/~peter/$_[0].cutoff.txt" }
+# Name of password tarball
+our $pwtar = 'fbce-passwords.tgz';
+
#
# Download and parse Peter Wemm's cutoff list for a specific repo
#
@@ -98,10 +102,10 @@ sub cmd_list(@) {
'name');
foreach my $person ($persons->all()) {
printf("%-16s%-8s%-8s%s\n",
- $person->login(),
- $person->active() ? 'yes' : 'no',
- $person->admin() ? 'yes' : 'no',
- $person->name());
+ $person->login,
+ $person->active ? 'yes' : 'no',
+ $person->admin ? 'yes' : 'no',
+ $person->name);
}
}
@@ -114,6 +118,7 @@ sub cmd_smash(@) {
my $persons = FBCE->model('FBCE::Person')->search();
my $schema = $persons->result_source()->schema();
$schema->txn_do(sub {
+ $persons->reset();
while (my $person = $persons->next) {
$person->update({ active => 0 });
}
@@ -164,6 +169,143 @@ sub cmd_pull(@) {
});
}
+#
+# Set each user's realname column based on their gecos
+#
+sub cmd_gecos(@) {
+ my ($self, $pwfn) = @_;
+
+ my %gecos;
+
+ # read passwd file
+ $pwfn //= "/etc/passwd";
+ open(my $pwfh, '<', $pwfn)
+ or die("$pwfn: $!\n");
+ warn("reading names from $pwfn\n")
+ if $self->debug;
+ while (<$pwfh>) {
+ chomp($_);
+ my @pwent = split(':', $_);
+ next unless @pwent == 7;
+ next unless $pwent[4] =~ m/^([^,]+)/;
+ $gecos{$pwent[0]} = $1;
+ }
+ close($pwfh);
+
+ # update the database
+ my $persons = FBCE->model('FBCE::Person')->
+ search({}, { order_by => 'login' });
+ my $schema = $persons->result_source()->schema();
+ my $n;
+ $schema->txn_do(sub {
+ warn("setting names in the database\n")
+ if $self->debug;
+ $n = 0;
+ $persons->reset();
+ while (my $person = $persons->next) {
+ my $login = $person->login;
+ my $gecos = $gecos{$login};
+ next unless $gecos;
+ next if $person->realname;
+ $person->update({ realname => $gecos });
+ ++$n;
+ }
+ warn("$n record(s) updated\n")
+ if $self->debug;
+ });
+}
+
+#
+# Use sysutils/pwgen2 to generate random passwords
+#
+sub pwgen($$;$) {
+ my ($self, $n, $len) = @_;
+
+ $len ||= 12;
+ warn("generating $n $len-character passwords\n")
+ if $self->debug;
+
+ # Set up a pipe and fork a child
+ my $pid = open(my $pipe, '-|');
+ if (!defined($pid)) {
+ # fork failed
+ die("fork(): $!\n");
+ } elsif ($pid == 0) {
+ # child process - run pwgen
+ # ugh hardcoded...
+ exec('/usr/local/bin/pwgen', '-can', $len, $n);
+ die("child: exec(): $!\n");
+ }
+
+ # read output from child
+ my @passwords;
+ while (<$pipe>) {
+ m/^([0-9A-Za-z]{$len})$/
+ or die("invalid output from pwgen\n");
+ push(@passwords, $1);
+ }
+
+ # check exit status
+ if (waitpid($pid, 0) != $pid) {
+ if ($? & 0xff) {
+ die(sprintf("pwgen caught signal %d\n", $? & 0x7f));
+ } elsif ($? >> 8) {
+ die(sprintf("pwgen exited with code %d\n", $? >> 8));
+ } else {
+ die("waitpid(): $!\n");
+ }
+ }
+ close($pipe);
+
+ # sanity check and we're done
+ die(sprintf("expected %d passwords, got %d\n", $n, @passwords))
+ unless @passwords == $n;
+ warn("got $n passwords as expected\n")
+ if $self->debug;
+ return @passwords;
+}
+
+#
+# Generate passwords for all users. Use with caution!
+#
+sub cmd_pwgen(@) {
+ my ($self, @users) = @_;
+
+ # please don't overwrite an existing password tarball...
+ die("$pwtar exists, delete or move and try again\n")
+ if -e $pwtar;
+
+ # generate enough passwords for everybody
+ my $persons = FBCE->model('FBCE::Person')->
+ search({ password => '*' }, { order_by => 'login' });
+ my $n = $persons->count();
+ my @passwords = $self->pwgen($n);
+
+ # create the archive
+ my $tar = Archive::Tar->new();
+
+ # update the database and the archive
+ my $schema = $persons->result_source()->schema();
+ $schema->txn_do(sub {
+ warn("setting the passwords in the database\n")
+ if $self->debug;
+ $persons->reset();
+ while (my $person = $persons->next) {
+ my ($login, $password) = ($person->login, shift(@passwords));
+ # printf("%s\t%s\n", $person->login, $password);
+ warn("setting password for $login\n")
+ if $self->debug;
+ $person->set_password($password);
+ $tar->add_data("$login/election-password", "$password\n",
+ { uname => $login, gname => $login });
+ }
+ warn("writing the tar file\n")
+ if $self->debug;
+ $tar->write($pwtar, COMPRESS_GZIP)
+ or die($tar->error());
+ });
+}
+
sub run($) {
my ($self) = @_;
@@ -178,6 +320,10 @@ sub run($) {
$self->cmd_smash(@{$self->extra_argv});
} elsif ($command eq 'pull') {
$self->cmd_pull(@{$self->extra_argv});
+ } elsif ($command eq 'gecos') {
+ $self->cmd_gecos(@{$self->extra_argv});
+ } elsif ($command eq 'pwgen') {
+ $self->cmd_pwgen(@{$self->extra_argv});
} else {
die("unrecognized command.\n");
}
More information about the svn-src-user
mailing list