diff --git a/README.md b/README.md index 8641429..545c0af 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,14 @@ # jake's keyserver This program pokes gpg when it receives a key. Then it does stuff to the output gpg produces and stores it in a postgres database. +This program is exceedingly fragile; thanks to it's reliance on GnuPG. + +On gpg-2.2.x and on gpg-2.4.x --with-colons flag on a file has differing outputs, 2.2.x omitting signature records but 2.4.x not omitting signature records. + +To show the signature records for 2.2.x gpg, one must import the key then run 'gpg --with-colons --list-sigs john@domain'. +On 2.4.x, --with-colons will show them without having to import the key. + +Due to this, I've opted to always import key, plug that output to a bunch of regexs, then delete them. Meaning, if you upload your own key while the program is running as your user, it will delete your own key. ## Features * 'Secret' upload path. @@ -10,6 +18,7 @@ This program pokes gpg when it receives a key. Then it does stuff to the output * Relevant Mojo/Mojolicious modules * Postgresql server * GnuPG +* A dedicated user (DO NOT RUN AS YOUR DAILY USER) ### Install on your distro Maybe it is packaged by your distro maintainers? @@ -24,9 +33,16 @@ apt install libmojolicious-perl libmojo-pg-perl ``` cpanm Mojolicious Mojo::Pg Mojo::File Mojo::Util ``` -Installing via cpan(m) will work because the Mojolicious devs are competent. +Installing via cpan(m) will work because the Mojolicious devs are competent (to be more specific, they opt to recreate everything, that way if a dependancy breaks because the author is ignoring issues or fucking DEAD there won't be permanently broken cpan repos that mojolicious depends on) ## To use +### Create a dedicated user to run this program +``` +sudo useradd --system -m /var/jjakkekeyserver --shell /bin/nologin jjakkekeyserver +sudo chmod 700 /var/jjakkekeyserver +sudo -u jjakkekeyserver --set-home gpg # gpg needs to create some files or it won't work right. press Ctrl + D to exit it. +``` + ### Create the config file ``` cp keyserver.conf.example keyserver.conf @@ -46,7 +62,7 @@ postgres=# grant all privileges on schema public to jjakkekeyserver; ### Start Program ``` -hypnotoad -f keyserver; # starts in foreground +sudo -u jjakkekeyserver hypnotoad -f keyserver; # -f = starts in foreground ``` ### Proxy diff --git a/keyserver b/keyserver index d3208f6..a94ff54 100755 --- a/keyserver +++ b/keyserver @@ -18,7 +18,6 @@ my $config = app->config; #my $cache = Mojo::Cache->new(max_keys => 5); my $start_time; my $magic_delimiter = '||,;,||'; -my $gpg_options = "--no-default-keyring --keyring /dev/null --dry-run"; my $tmpdir; my $pg = Mojo::Pg->new("postgresql://$config->{pguser}:$config->{pgpass}\@$config->{pghost}/$config->{pgdb}"); @@ -200,7 +199,7 @@ sub stats { #$cache->set(operations => ($cache->get('operations') + 1)); operation(); my $output = "jjakke's keyserver ($VERSION)\n\n"; - $output .= `gpg $gpg_options --version`; + $output .= `gpg --version`; $output =~ s/Home: (.*)/Home: [redacted]/g; $output .= "\n"; my $data = $pg->db->select('this_service', ['starttime', 'operations'])->array; @@ -269,21 +268,22 @@ sub add ($c) { syswrite $fh, $keytext, length $keytext; close $fh; - my $res = `gpg $gpg_options --with-colons --with-fingerprint --with-fingerprint $tmpfile`; + my $res = `gpg --with-colons --with-fingerprint --with-fingerprint --import --import-options import-show $tmpfile`; if ($? ne 0) { return $c->render(text=>"not accepting (gpg bugged out)", status=>422); } + my $fingerprint = (split(/:/, (grep(/^fpr:/, split(/\n/, $res)))[0]))[9]; + # --with-colons show more relevent data with an imported key. + $res = `gpg --with-colons --with-fingerprint --with-fingerprint --list-sigs $fingerprint`; + `gpg --batch --delete-keys --yes $fingerprint`; - # need to get 'version number' for machine readable format and - # this is the only way that I can think of. I really hate this. - # get the output then plug it to a bunch of regexes. - my $version = `gpg $gpg_options --list-packets $tmpfile`; + + my $version = `gpg --list-packets $tmpfile`; my @versions; my $record; my $nonext = 0; my $pub_count = 0; - for (split /\n/, $version) { - my $string = $_; + for my $string (split /\n/, $version) { if ($string =~ m/^(:[\w\s]*:)/) { $record = $1; $nonext = 1; @@ -438,16 +438,18 @@ sub insert_gpg_key ($fingerprint, $keyid, $version, $flags, $armored, $blob) { sub insert_gpg_uid ($id, @these_uids) { for my $uid (@these_uids) { - # 'magic_delimiter' but unfortunately has special meaning to split. + # 'magic_delimiter' but unfortunately has special meaning to split. my @the_actual_uid = split /\|\|\,\;\,\|\|/, $uid; # 0 = the string #my @the_actual_uid = split $magic_delimiter, $uid; # 0 = the string $the_actual_uid[0] = url_escape $the_actual_uid[0]; - my @meta = split /:/, $the_actual_uid[-1]; # 0 = creation, 1 = expiration, 2 = flags + my @meta; + @meta = split /:/, $the_actual_uid[-1] if (scalar @the_actual_uid >= 2); + #^ 0 = creation, 1 = expiration, 2 = flags $pg->db->insert('gpg_uid', { uid => $the_actual_uid[0], - creationdate => $meta[0], - expirationdate => $meta[1], - flags => $meta[2], + creationdate => $meta[0] || 0, + expirationdate => $meta[1] || undef, + flags => $meta[2] || '-', relatedto => $id }); } diff --git a/keyserver.conf.example b/keyserver.conf.example index adceba5..b83d89c 100644 --- a/keyserver.conf.example +++ b/keyserver.conf.example @@ -1,8 +1,9 @@ { hypnotoad => { listen => [ - 'http://127.0.0.55:8080' + 'http://127.0.0.55:8080' # .55 not .1 ], + pid_file => '/var/run/jjakkekeyserver.pid', workers => 6 }, pguser => 'jjakkekeyserver',