autoconf onak-mail.pl config
[onak.git] / onak-mail.pl.in
1 #!/usr/bin/perl -w
2 #
3 # onak-mail.pl - Mail processing interface for onak, an OpenPGP Keyserver.
4 #
5 # Written by Jonathan McDowell <noodles@earth.li>
6 # Copyright 2002 Project Purple
7 # Released under the GPL.
8 #
9
10 use strict;
11 use Fcntl ':flock';
12 use IPC::Open3;
13
14 my %config;
15
16 #
17 # readconfig
18 #
19 # Reads in our config file. Ignores any command it doesn't understand rather
20 # than having to list all the ones that are of no interest to us.
21 #
22 sub readconfig {
23
24         open(CONFIG, "@CONFIG@") or
25                 die "Can't read config file: $!";
26         
27         while (<CONFIG>) {
28                 if (/^#/ or /^$/) {
29                         # Ignore; comment line.
30                 } elsif (/^this_site (.*)/) {
31                         $config{'thissite'} = $1;
32                 } elsif (/^logfile (.*)/) {
33                         $config{'logfile'} = $1;
34                 } elsif (/^maintainer_email (.*)/) {
35                         $config{'adminemail'} = $1;
36                 } elsif (/^mail_delivery_client (.*)/) {
37                         $config{'mta'} = $1;
38                 } elsif (/^pks_bin_dir (.*)/) {
39                         $config{'pks_bin_dir'} = $1;
40                 } elsif (/^db_dir (.*)/) {
41                         $config{'db_dir'} = $1;
42                 } elsif (/^syncsite (.*)/) {
43                         push @{$config{'syncsites'}}, $1;
44                 }
45         }
46
47         close(CONFIG);
48
49         return;
50 }
51
52 #
53 # submitupdate
54 #
55 # Takes an armored OpenPGP stream and submits it to the keyserver. Returns the
56 # difference between what we just added and what we had before (ie the least
57 # data need to get from what we had to what we have).
58 #
59 sub submitupdate {
60         my @data = @_;
61         my (@errors, @mergedata);
62
63         open(LOCKFILE, '>'.$config{'db_dir'}.'/onak-mail.lck');
64         flock(LOCKFILE, LOCK_EX);
65         print LOCKFILE "$$";
66
67         open3(\*MERGEIN, \*MERGEOUT, \*MERGEERR,
68                 $config{'pks_bin_dir'}."/onak", "-u", "add");
69
70         print MERGEIN @data;
71         close MERGEIN;
72         @mergedata = <MERGEOUT>;
73         close MERGEOUT;
74         @errors = <MERGEERR>;
75         close MERGEERR;
76
77         flock(LOCKFILE, LOCK_UN);
78         close(LOCKFILE);
79
80         return @mergedata;
81 }
82
83 my ($inheader, %seenby, $subject, $from, $replyto, @body, @syncmail);
84
85 $inheader = 1;
86 $subject = "";
87 &readconfig;
88
89 while (<>) {
90         if ($inheader) {
91                 if (/^Subject:\s*(.*)\s*$/i) {
92                         $subject = $1;
93                 } elsif (/^X-KeyServer-Sent:\s*(.*)\s*$/i) {
94                         $seenby{$1} = 1;
95                 } elsif (/^From:\s*(.*)\s*$/i) {
96                         $from = $1;
97                 } elsif (/^Reply-To:\s*(.*)\s*$/i) {
98                         $replyto = $1;
99                 } elsif (/^$/) {
100                         $inheader = 0;
101                 }
102         }
103         if (!$inheader) {
104                 push @body, $_;
105         }
106 }
107 if (! defined($replyto)) {
108         $replyto = $from;
109 }
110
111 # HELP, ADD, INCREMENTAL, VERBOSE INDEX <keyid>, INDEX <keyid>, GET <keyid>,
112 # LAST <days>
113
114 if ($subject =~ /^INCREMENTAL$/i) {
115         my $site;
116         my $count;
117         my $i;
118         my @newupdate = submitupdate(@body);
119         my @time;
120
121         $count = 0;
122         foreach $i (@{$config{'syncsites'}}) {
123                 if (! defined($seenby{$i})) {
124                         $count++;
125                 }
126         }
127
128         open (LOG, ">>$config{'logfile'}");
129         @time = localtime(time);
130         print LOG "[";
131         print LOG sprintf "%02d/%02d/%04d %02d:%02d:%02d",
132                 $time[3], $time[4] + 1, $time[5] + 1900,
133                 $time[2], $time[1], $time[0];
134         print LOG "] onak-mail[$$]: Syncing with $count sites.\n";
135         close LOG;
136
137         if ((! defined($newupdate[0])) || $newupdate[0] eq '') {
138                 open (LOG, ">>$config{'logfile'}");
139                 print LOG "[";
140                 print LOG sprintf "%02d/%02d/%04d %02d:%02d:%02d",
141                         $time[3], $time[4] + 1, $time[5] + 1900,
142                         $time[2], $time[1], $time[0];
143                 print LOG "] onak-mail[$$]: Nothing to sync.\n";
144                 close LOG;
145                 $count = 0;
146         }
147
148         if ($count > 0) {
149                 open(MAIL, "|$config{mta}");
150                 print MAIL "From: $config{adminemail}\n";
151                 print MAIL "To: ";
152                 foreach $i (@{$config{'syncsites'}}) {
153                         if (! defined($seenby{$i})) {
154                                 print MAIL "$i";
155                                 $count--;
156                                 if ($count > 0) {
157                                         print MAIL ", ";
158                                 }
159                         }
160                 }
161                 print MAIL "\n";
162                 print MAIL "Subject: incremental\n";
163                 foreach $site (keys %seenby) {
164                         print MAIL "X-KeyServer-Sent: $site\n";
165                 }
166                 print MAIL "X-KeyServer-Sent: $config{thissite}\n";
167                 print MAIL "Precedence: list\n";
168                 print MAIL "MIME-Version: 1.0\n";
169                 print MAIL "Content-Type: application/pgp-keys\n";
170                 print MAIL "\n";
171                 print MAIL @newupdate;
172                 close MAIL;
173         }
174 } elsif ($subject =~ /^(VERBOSE )?INDEX (.*)$/i) {
175         my (@indexdata, $command);
176
177         $command = "index";
178         if (defined($1)) {
179                 $command = "vindex";
180         }
181
182         open3(\*INDEXIN, \*INDEXOUT, \*INDEXERR,
183                 $config{'pks_bin_dir'}."/onak", $command, "$2");
184         close INDEXIN;
185         @indexdata = <INDEXOUT>;
186         close INDEXOUT;
187         close INDEXERR;
188
189         open(MAIL, "|$config{mta}");
190         print MAIL "From: $config{adminemail}\n";
191         print MAIL "To: $replyto\n";
192         print MAIL "Subject: Reply to INDEX $2\n";
193         print MAIL "Precedence: list\n";
194         print MAIL "MIME-Version: 1.0\n";
195         print MAIL "Content-Type: text/plain\n";
196         print MAIL "\n";
197         print MAIL "Below follows the reply to your recent keyserver query:\n";
198         print MAIL "\n";
199         print MAIL @indexdata;
200         close MAIL;
201 }