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 --manual and __END__
44 # TODO: Add module prerequisites to INSTALL
46 my $VERSION = "2.0beta3";
47 my $CONFIGDIR = $ENV{CLIVEPASS_CONFIGDIR
}
48 || File
::Spec
->catfile($ENV{HOME
}, ".config/clivepass");
49 my $PASSWDFILE = File
::Spec
->catfile($CONFIGDIR, "passwd");
57 'add|a', 'get|g=s', 'manual|m', 'help|h', 'version|v' => \
&print_version
,
60 pod2usage
(-exitstatus
=> 0, -verbose
=> 1) if $opts{help
};
61 pod2usage
(-exitstatus
=> 0, -verbose
=> 2) if $opts{manual
};
66 my $passwd = Config
::Tiny
->read($PASSWDFILE);
67 my $phrase_hash = $passwd->{_
}->{phrase
};
69 my %ctx = ! $phrase_hash
70 ? create_passwd
($phrase_hash)
71 : verify_phrase
($passwd, $phrase_hash);
73 my $key = md5_hex
($ctx{phrase
});
76 add_login
(\
%ctx, $key);
77 } elsif ( $opts{get
} ) {
78 my $pwd = get_login
(\
%ctx, $key, $opts{get
});
80 print "found: $opts{get}=$pwd\n";
82 print STDERR
"error: login not found\n";
85 list_logins
(\
%ctx, $key);
90 my ( $phrase_hash ) = @_;
93 $phrase = getpass
("Enter passphrase: ") while ( ! $phrase );
95 my $passwd = Config
::Tiny
->new;
96 $passwd->{_
}->{phrase
} = unix_md5_crypt
($phrase, salt
(8));
97 $passwd->write($PASSWDFILE);
99 return ( passwd
=> $passwd, phrase
=> $phrase );
103 my ( $passwd, $phrase_hash ) = @_;
106 $phrase = getpass
("Enter passphrase: ") while ( ! $phrase );
108 if ( unix_md5_crypt
($phrase, $phrase_hash) ne $phrase_hash ) {
109 print STDERR
"invalid passphrase\n";
112 return ( passwd
=> $passwd, phrase
=> $phrase );
118 chomp(my $passwd = <STDIN
>);
125 my ($ctx, $key) = @_;
127 print "Enter username: ";
128 chomp(my $user = <STDIN
>);
130 my $pwd = getpass
("Enter password for $user: ");
131 $pwd = pack('a16', $pwd);
133 my $c = Crypt
::Twofish2
->new($key, Crypt
::Twofish2
::MODE_CBC
);
135 $ctx->{passwd
}->{login
}->{$user} = encode_base64
($c->encrypt($pwd));
136 $ctx->{passwd
}->write($PASSWDFILE);
140 my ($ctx, $key, $login) = @_;
141 foreach ( $ctx->{passwd
}->{login
} ) {
142 while ( my ($id, $pwd) = each(%{$_}) ) {
143 if ( $id eq $login ) {
144 my $c = Crypt
::Twofish2
->new($key, Crypt
::Twofish2
::MODE_CBC
);
145 return $c->decrypt(decode_base64
($pwd));
152 my ($ctx, $key) = @_;
154 foreach ( $ctx->{passwd
}->{login
} ) {
155 while ( my ($id, $pwd) = each(%{$_}) ) {
156 my $c = Crypt
::Twofish2
->new($key, Crypt
::Twofish2
::MODE_CBC
);
157 print "$id = " . $c->decrypt(decode_base64
($pwd)) . "\n";
163 my $perl_v = sprintf "%vd", $^V
;
165 "clivepass version $VERSION. Copyright (C) 2008 Toni Gundogdu.
169 * MIME::Base64/$MIME::Base64::VERSION\t\t* Config::Tiny/$Config::Tiny::VERSION
170 * Crypt::Salt/$Crypt::Salt::VERSION\t\t* Digest::MD5/$Digest::MD5::VERSION
171 * Crypt::PasswdMD5/$Crypt::PasswdMD5::VERSION\t* Crypt::Twofish2/$Crypt::Twofish2::VERSION
174 * Getopt::Long/$Getopt::Long::VERSION\t\t* Encode/$Encode::VERSION
175 * File::Spec/$File::Spec::VERSION\t\t* File::Find/$File::Find::VERSION
176 * Pod::Usage/$Pod::Usage::VERSION
178 This program comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of
179 clivepass under the terms of the GNU General Public License as published by the
180 Free Software Foundation, either version 3 of the License, or (at your option)
181 any later version. You should have received a copy of the General Public License
182 along with this program. If not, see http://www.gnu.org/licenses/.
190 clivepass - the login password utility for clive
194 clivepass [option]...
198 clivepass is an utility that can be used to create and change passwords
199 for websites used by L<clive(1)>. The passwords are encrypted and saved
200 along with the username information. The access is restricted by using a
205 If the utility is started without any options, it will prompt for the
206 passphrase and list all decrypted passwords to stdout.
216 =item B<-v --version>
218 Show version and exit.
222 Add a new password to the list.
224 =item B<-g --get=>I<username>
226 Return a decrypted password for the I<username> from the list.
227 The information is printed to stdout.
237 =item % clivepass -g myusername
243 By default, clivepass searches the ~/.config/clivepass directory for the
244 password file. The B<CLIVEPASS_CONFIGDIR> environment variable can be used
245 to override this behaviour.
249 =item ~/.config/clivepass/passwd
251 Password file. Contains the salted passphrase hash and login usernames and
256 L<clive(1)> L<clivescan(1)> L<clivefeed(1)>
260 Project: http://googlecode.com/p/clive-utils/
262 A clive-utils development repository can be obtained from:
264 % git clone git://repo.or.cz/clive-utils.git
270 Written by Toni Gundogdu <legatvs@gmail.com>