#!/usr/bin/perl

=head1 NAME

parcimonie - privacy-friendly helper to refresh a GnuPG keyring

=head1 VERSION

Version 0.8.4

=head1 SYNOPSIS

B<parcimonie> [options]

=head1 DESCRIPTION

parcimonie is a daemon that slowly refreshes a GnuPG public keyring
from a keyserver.

Its refreshes one key at a time; between every key update, parcimonie
sleeps a random amount of time, long enough for the previously used Tor
circuit to expire.

This process is meant to make it hard for an attacker to correlate the
multiple performed key update operations.

See the design.mdwn document to learn more about the threat and risk
models parcimonie attempts to help coping with.

=head1 USAGE

1. Configure GnuPG to be able to use a keyserver.

You can skip this section if you already have configured a keyserver
in ~/.gnupg/gpg.conf.

Else, add to your gpg.conf something along these lines:

        keyserver hkp://pool.sks-keyservers.net

You obviously can choose your preferred keyserver here; if using
hkps:// (which would be our second choice behind hkpms://), your GnuPG
installation should support HKPS; on Debian systems, enabling such
support is done by installing the gnupg-curl package; see those web
pages for help with GnuPG hkps:// configuration:

	http://sks-keyservers.net/overview-of-pools.php#pool_hkps
        http://keys.indymedia.org/

You may want parcimonie to use a different keyserver than the one your
usual GnuPG invocations do. This can be achieved by passing to
parcimonie a command-line option such as:

        --gnupg-extra-arg "--keyserver=hkps://hkps.pool.sks-keyservers.net"

2. Run "parcimonie --verbose".

3. Check the output for misconfiguration or bugs.

4. Once happy, start the daemon without the --verbose option.
   Note: the Debian package automatically starts the daemon with your X session.
   For example, GNOME users can configure its startup from the
   "System -> Preferences -> Startup Applications" menu.

=head1 OPTIONS

The following command lists available options:

    parcimonie --help

=head2 Tor configuration vs. --minimum-lapse-time

In case you set the Tor MaxCircuitDirtiness setting yourself, you
probably want to pass parcimonie a matching --minimum-lapse-time
option so that subsequent key fetches use different Tor circuits.

Just make sure this remains true:

        minimum-lapse-time >= Tor MaxCircuitDirtiness

=head2 hkpms://

We recommend using hkpms; see http://web.monkeysphere.info/ for
details. When a hkpms:// keyserver is being used, one needs to do two
additional steps since gpgkeys_hkpms does not work in the torsocks
wrapped environment parcimonie uses by default to run gpg.

=head3 Torify gpgkeys_hkpms

Just add the following line to gpg.conf:

    keyserver-options http-proxy=socks://127.0.0.1:9050

=head3 Hey, parcimonie, gpg is already torified

Pass the --gnupg-already-torified switch to the parcimonie daemon
command-line. parcimonie will then rely on the keyserver-options
previously added to gpg.conf, and won't attempt to torify gpg
connections itself.

=head1 AUTHOR

intrigeri <intrigeri@boum.org>

=head1 LICENSE AND COPYRIGHT

Copyright (C) 2010-2013 intrigeri <intrigeri@boum.org>

Licensed under the same terms as Perl itself.

=head1 BUGS

Please report any bugs or feature requests to C<intrigeri at boum.org>.

=head1 SUPPORT

You can find documentation for parcimonie with the man command.

    man parcimonie


You can also look for information at:

=over 4

=item * parcimonie's homepage

L<https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/>

=back

=cut

use strict;
use warnings;

our $VERSION = '0.8.4';

use FindBin;
use lib "$FindBin::Bin/../lib";

use Env qw{@PATH};
unshift @PATH, "$FindBin::Bin";

use 5.10.0;

use Carp;
use Try::Tiny;

my $mu;
sub record_memory_usage { 1 }
sub report_memory_usage { 1 }

BEGIN {
    if (exists $ENV{REPORT_MEMORY_USAGE}
            && defined $ENV{REPORT_MEMORY_USAGE}
            && $ENV{REPORT_MEMORY_USAGE}) {
        try {
            require Memory::Usage;
        } catch {
            croak "Memory::Usage is needed when REPORT_MEMORY_USAGE is set."
        };
        $mu = Memory::Usage->new();
        no warnings 'redefine';
        *record_memory_usage = sub { $mu->record(shift) };
        *report_memory_usage = sub { $mu->dump() };
    }
}

$SIG{'INT'}  = $SIG{'TERM'} = sub { report_memory_usage(); exit(0); };
$SIG{'USR1'} = sub { report_memory_usage(); };

record_memory_usage('starting work');
record_memory_usage('before loading App::Parcimonie');
require App::Parcimonie;
App::Parcimonie->import();
record_memory_usage('after loading App::Parcimonie');

record_memory_usage('before loading App::Parcimonie::Daemon');
require App::Parcimonie::Daemon;
App::Parcimonie::Daemon->import();
record_memory_usage('after loading App::Parcimonie::Daemon');

App::Parcimonie::Daemon->new_with_options()->run;

report_memory_usage();
