2 # -*- coding: ascii -*-
3 ###########################################################################
4 # clivepass, the login password utility for clive
5 # Copyright (C) 2008 Toni Gundogdu.
7 # This file is part of clive-utils.
9 # clivepass is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # clivepass is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with clivepass. If not, see <http://www.gnu.org/licenses/>.
21 ###########################################################################
28 binmode(STDOUT
, ":utf8");
30 use Digest
::MD5
qw(md5_hex); #!bsd
33 use MIME
::Base64
; #!bsd
37 use Getopt
::Long
qw(:config bundling);
43 # TODO: Add module prerequisites to INSTALL
45 my $VERSION = "2.0beta3";
46 my $CONFIGDIR = $ENV{CLIVEPASS_CONFIGDIR
}
47 || File
::Spec
->catfile($ENV{HOME
}, ".config/clivepass");
48 my $PASSWDFILE = File
::Spec
->catfile($CONFIGDIR, "passwd");
56 'add|a', 'get|g=s', 'manual|m', 'help|h', 'version|v' => \
&print_version
,
59 pod2usage
(-exitstatus
=> 0, -verbose
=> 1) if $opts{help
};
60 pod2usage
(-exitstatus
=> 0, -verbose
=> 2) if $opts{manual
};
65 my $passwd = Config
::Tiny
->read($PASSWDFILE);
66 my $phrase_hash = $passwd->{_
}->{phrase
};
68 my %ctx = ! $phrase_hash
69 ? create_passwd
($phrase_hash)
70 : verify_phrase
($passwd, $phrase_hash);
72 my $key = md5_hex
($ctx{phrase
});
75 add_login
(\
%ctx, $key);
76 } elsif ( $opts{get
} ) {
77 my $pwd = get_login
(\
%ctx, $key, $opts{get
});
79 print "found: $opts{get}=$pwd\n";
81 print STDERR
"error: login not found\n";
84 list_logins
(\
%ctx, $key);
89 my ( $phrase_hash ) = @_;
92 $phrase = getpass
("Enter passphrase: ") while ( ! $phrase );
94 my $passwd = Config
::Tiny
->new;
95 $passwd->{_
}->{phrase
} = unix_md5_crypt
($phrase, salt
(8));
96 $passwd->write($PASSWDFILE);
98 return ( passwd
=> $passwd, phrase
=> $phrase );
102 my ( $passwd, $phrase_hash ) = @_;
105 $phrase = getpass
("Enter passphrase: ") while ( ! $phrase );
107 if ( unix_md5_crypt
($phrase, $phrase_hash) ne $phrase_hash ) {
108 print STDERR
"invalid passphrase\n";
111 return ( passwd
=> $passwd, phrase
=> $phrase );
117 chomp(my $passwd = <STDIN
>);
124 my ($ctx, $key) = @_;
126 print "Enter username: ";
127 chomp(my $user = <STDIN
>);
129 my $pwd = getpass
("Enter password for $user: ");
130 $pwd = pack('a16', $pwd);
132 my $c = Crypt
::Twofish2
->new($key, Crypt
::Twofish2
::MODE_CBC
);
134 $ctx->{passwd
}->{login
}->{$user} = encode_base64
($c->encrypt($pwd));
135 $ctx->{passwd
}->write($PASSWDFILE);
139 my ($ctx, $key, $login) = @_;
140 foreach ( $ctx->{passwd
}->{login
} ) {
141 while ( my ($id, $pwd) = each(%{$_}) ) {
142 if ( $id eq $login ) {
143 my $c = Crypt
::Twofish2
->new($key, Crypt
::Twofish2
::MODE_CBC
);
144 return $c->decrypt(decode_base64
($pwd));
151 my ($ctx, $key) = @_;
153 foreach ( $ctx->{passwd
}->{login
} ) {
154 while ( my ($id, $pwd) = each(%{$_}) ) {
155 my $c = Crypt
::Twofish2
->new($key, Crypt
::Twofish2
::MODE_CBC
);
156 print "$id = " . $c->decrypt(decode_base64
($pwd)) . "\n";
162 my $perl_v = sprintf "%vd", $^V
;
164 "clivepass version $VERSION. Copyright (C) 2008 Toni Gundogdu.
168 * MIME::Base64/$MIME::Base64::VERSION\t\t* Config::Tiny/$Config::Tiny::VERSION
169 * Crypt::Salt/$Crypt::Salt::VERSION\t\t* Digest::MD5/$Digest::MD5::VERSION
170 * Crypt::PasswdMD5/$Crypt::PasswdMD5::VERSION\t* Crypt::Twofish2/$Crypt::Twofish2::VERSION
173 * Getopt::Long/$Getopt::Long::VERSION\t\t* Encode/$Encode::VERSION
174 * File::Spec/$File::Spec::VERSION\t\t* File::Find/$File::Find::VERSION
175 * Pod::Usage/$Pod::Usage::VERSION
177 This program comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of
178 clivepass under the terms of the GNU General Public License as published by the
179 Free Software Foundation, either version 3 of the License, or (at your option)
180 any later version. You should have received a copy of the General Public License
181 along with this program. If not, see http://www.gnu.org/licenses/.
189 clivepass - the login password utility for clive
193 clivepass [option]...
197 clivepass is an utility that can be used to create and change passwords
198 for websites used by L<clive(1)>. The passwords are encrypted and saved
199 along with the username information. The access is restricted by using a
204 If the utility is started without any options, it will prompt for the
205 passphrase and list all decrypted passwords to stdout.
215 =item B<-v --version>
217 Show version and exit.
221 Add a new password to the list.
223 =item B<-g --get=>I<username>
225 Return a decrypted password for the I<username> from the list.
226 The information is printed to stdout.
236 =item % clivepass -g myusername
242 By default, clivepass searches the ~/.config/clivepass directory for the
243 password file. The B<CLIVEPASS_CONFIGDIR> environment variable can be used
244 to override this behaviour.
248 =item ~/.config/clivepass/passwd
250 Password file. Contains the salted passphrase hash and login usernames and
255 L<clive(1)> L<clivescan(1)> L<clivefeed(1)>
259 Project: http://googlecode.com/p/clive-utils/
261 A clive-utils development repository can be obtained from:
263 % git clone git://repo.or.cz/clive-utils.git
269 Written by Toni Gundogdu <legatvs@gmail.com>