source: trunk/LATMOS-Accounts/bin/la-sql-crypt-passwd @ 1382

Last change on this file since 1382 was 1314, checked in by nanardon, 9 years ago

Improve la-sql-crypt-passwd:

  • don't set the password, only the RSA encrypted one
  • ask password two time before setting new key
  • add --delkey option to reset the features (but loosing password)
  • Property svn:executable set to *
  • Property svn:keywords set to Id Rev
File size: 5.1 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5use LATMOS::Accounts;
6use Getopt::Long;
7use Pod::Usage;
8use Term::ReadKey;
9use Crypt::RSA;
10
11=head1 NAME
12
13    la-crypt-passwd - Tools to managed rsa crypted password in LATMOS Account system
14
15=head1 SYNOPSIS
16
17    la-crypt-passwd [options] [--genkey|--regen] [--set BASE]
18
19=cut
20
21GetOptions(
22    'c|config=s' => \my $config,
23    'help'       => sub { pod2usage(0) },
24    'genkey'     => \my $genkey,
25    'regen'      => \my $regen,
26    'delkey'     => \my $delkey,
27    'set=s'      => \my $set,
28    'base=s'     => \my $base,
29    'u|user=s'   => \my @users,
30) or pod2usage();
31
32=head1 OPTIONS
33
34=over 4
35
36=item -c|--config configdir
37
38Use this configuration directory instead of the default one.
39
40=item --genkey
41
42Generate a RSA key and store it into database
43
44If one is already present, use regen to force generation of a new one
45
46=item --regen
47
48Like --genkey but a new key will replace the current one if already present.
49Stored password will be read and encrypted again using the new key.
50
51=item --delkey
52
53Delete the current peer key and all encrypted password stored.
54
55=item --base base
56
57Work on this specific base instead default one
58
59=item --set BASE
60
61Read password from database, decrypt it and then set it in BASE given as
62argument.
63
64=item -u|--user USER
65
66Set password only for this user (can be set multiple times).
67
68=back
69
70=cut
71
72my $LA = LATMOS::Accounts->new($config, noacl => 1);
73my $labase = $LA->base($base);
74$labase && $labase->load or die "Cannot load base";
75$labase->wexported(1);
76
77my $clear;
78
79sub get_clear_password {
80    $clear and return $clear;
81    my %encpasswd = $labase->get_rsa_password;
82    scalar(keys %encpasswd) or return {};
83    ReadMode('noecho');
84    print "Enter password for current passphrase: ";
85    my $password = ReadLine(0);
86    ReadMode 0;
87    print "\n";
88    printf "Trying to get current stored password (%d)\n", scalar(keys %encpasswd);
89    my $private_key = $labase->private_key($password) or
90        die "Cannot get private key\n";
91    my $rsa = new Crypt::RSA ES => 'PKCS1v15';
92    my %clear_passwd;
93    foreach (keys %encpasswd) {
94        my $clearp = $rsa->decrypt (
95                Cyphertext => $encpasswd{$_},
96                Key        => $private_key,
97                Armour     => 1,
98        );
99        if (defined $clearp) {
100            $clear_passwd{$_} = $clearp;
101        } else {
102            die "Cannot get password for $_, crypt module said :" . $rsa->errstr() .
103                "Was the password correct ?\n";
104        }
105    }
106    return \%clear_passwd;
107}
108
109if ($set) {
110    if (!$labase->get_global_value('rsa_private_key')) {
111        warn "No rsa key found in database\n";
112    }
113    my $destbase = $LA->base($set) or die "Cannot get base $set\n";
114    my $clearpasswd = get_clear_password();
115
116    my @userstoset = @users ? @users : keys %$clearpasswd;
117
118    foreach (@userstoset) {
119        $clearpasswd->{$_} or next;
120        my $obj = $destbase->get_object('user', $_) or do {
121            warn "Cannot find user $_ in destination base, need sync ?\n";
122            next;
123        };
124        $obj->set_password($clearpasswd->{$_}) and
125            print "Password set for $_\n";
126    }
127    $destbase->commit;
128} elsif ($regen || $genkey) {
129    if ($labase->get_global_value('rsa_private_key') && !$regen) {
130        die <<EOF;
131A rsa key were found in database please use --regen to force a new key
132generation. Notice this will force decrypt current stored password to encrypt
133them again
134EOF
135    }
136
137    my $clearpasswd = get_clear_password();
138
139    my $password;
140    while (1) {
141        ReadMode('noecho');
142        print "Enter password for new key: ";
143        $password = ReadLine(0);
144        print "\n";
145        print "Enter password again for new key: ";
146        my $password2 = ReadLine(0);
147        ReadMode 0;
148        print "\n";
149        if ($password eq $password2) {
150            last;
151        } else {
152            print "Password mismatch, try again:\n";
153        }
154    }
155
156    print "Generating new RSA key...\n";
157    my ($public, $private) = $labase->generate_rsa_key($password);
158
159    $labase->store_rsa_key($public, $private);
160    foreach (keys %$clearpasswd) {
161        my $obj = $labase->get_object('user', $_);
162        $obj->setCryptPassword($clearpasswd->{$_});
163    }
164    $labase->commit;
165} elsif ($delkey) {
166    if (! $labase->get_global_value('rsa_public_key')) {
167        die "There is no key in this base, not deleting nothing\n";
168    }
169    my %encpasswd = $labase->get_rsa_password;
170    print "Deleting password...\n";
171    foreach my $user (keys %encpasswd) {
172        my $ouser = $labase->get_object('user', $user) or next;
173        $ouser->set_c_fields('encryptedPassword' => undef) or
174            die "Cannot delete encryptedPassword attribute for $user\n";
175    }
176    $labase->set_global_value('rsa_public_key', undef);
177    $labase->set_global_value('rsa_private_key', undef);
178    $labase->commit;
179} else {
180    if ($labase->get_global_value('rsa_private_key')) {
181        my $clearpasswd = get_clear_password();
182        foreach (keys %$clearpasswd) {
183            printf("%s: %s\n", $_, $clearpasswd->{$_});
184        }
185    } else {
186        warn "No rsa key found in database\n";
187    }
188}
Note: See TracBrowser for help on using the repository browser.