#!/usr/bin/perl

=head1 NAME

parcimonie - privacy-friendly helper to refresh a GnuPG keyring

=head1 VERSION

Version 0.10.3

=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.

Skip this section if you already have configured a keyserver, or if
you have gnupg2 2.1.15-9 or newer installed (it comes with a sensible
default keyserver configuration).

If you are using GnuPG v2, add to ~/.gnupg/dirmngr.conf something like:

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

If are still using GnuPG v1, add to gpg.conf something like:

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

For hkps:// support with GnuPG v1, install the gnupg1-curl or
gnupg-curl package, whichever is available in your distribution.
Or switch to GnuPG v2.

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-2016 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<http://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/>

=back

=cut

use strict;
use warnings;

our $VERSION = '0.10.3';

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 }

my @options;

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() };
        push @options, ('memory_usage' => $mu);
    }
}

$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(@options)->run;

report_memory_usage();
