3 # Monkeysphere Validation Agent, Perl version
4 # Copyright © 2010 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 use parent qw(HTTP::Server::Simple::CGI);
30 use POSIX qw(strftime);
33 '/' => { handler => \&noop,
34 methods => { 'GET' => 1 },
36 '/reviewcert' => { handler => \&reviewcert,
37 methods => { 'POST' => 1 },
39 '/extracerts' => { handler => \&extracerts,
40 methods => { 'POST' => 1 },
61 my $level = $loglevels{lc($ENV{MSVA_LOG_LEVEL})};
62 $level = $loglevels{info} if (! defined $level);
64 if ($loglevels{lc($msglevel)} <= $level) {
71 # start the server on port 8901
72 my $self = $class->SUPER::new(8901);
74 $self->{_gpg} = new Crypt::GPG;
76 bless ($self, $class);
83 return '200 OK', { available => JSON::true,
85 server => "MSVA-Perl 0.1" };
92 # FIXME: check SO_PEERCRED -- if this was a TCP socket, Linux
93 # might not be able to support SO_PEERCRED (even on the loopback),
94 # though apparently some kernels (Solaris?) are able to.
96 # another option in Linux would be to parse the contents of
97 # /proc/net/tcp to find the uid of the peer process based on that
100 my $path = $cgi->path_info();
101 my $handler = $dispatch{$path};
103 if (ref($handler) eq "HASH") {
104 if (! exists $handler->{methods}->{$cgi->request_method()}) {
105 printf("HTTP/1.0 405 Method not allowed\r\nAllow: %s\r\nDate: %s\r\n",
106 join(', ', keys(%{$handler->{methods}})),
107 strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time())));
108 } elsif (ref($handler->{handler}) ne "CODE") {
109 printf("HTTP/1.0 500 Server Error\r\nDate: %s\r\n",
110 strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time())));
113 my $ctype = $cgi->content_type();
114 msvalog('info', "Got %s %s (Content-Type: %s)\n", $cgi->request_method(), $path, defined $ctype ? $ctype : '**none supplied**');
115 if (defined $ctype) {
116 my @ctypes = split(/; */, $ctype);
117 $ctype = shift @ctypes;
118 if ($ctype eq 'application/json') {
119 $data = from_json($cgi->param('POSTDATA'));
123 my ($status, $object) = $handler->{handler}($data);
124 my $ret = to_json($object);
125 msvalog('info', "returning: %s\n", $ret);
126 printf("HTTP/1.0 %s\r\nDate: %s\r\nContent-Type: application/json\r\n\r\n%s",
128 strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time())),
132 printf("HTTP/1.0 404 Not Found -- not handled by Monkeysphere validation agent\r\nContent-Type: text/plain\r\nDate: %s\r\n\r\nHTTP/1.0 404 Not Found -- the path:\r\n %s\r\nis not handled by the MonkeySphere validation agent.\r\nPlease try one of the following paths instead:\r\n\r\n%s\r\n",
133 strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time())),
134 $path, ' * '.join("\r\n * ", keys %dispatch) );
140 return if !ref $data;
142 my $uid = $data->{context}.'://'.$data->{uid};
144 my $cert = Crypt::X509->new(cert => join('', map(chr, @{$data->{pkc}->{data}})));
146 msvalog('info', "cert subject: %s\n", $cert->subject_cn());
147 msvalog('info', "cert issuer: %s\n", $cert->issuer_cn());
149 my $ret = { valid => JSON::true,
150 message => sprintf('tried to validate "%s" through the OpenPGP Web of Trust', $uid) };
151 my $status = '200 match found, authentication details to follow';
153 return $status, $ret;
159 return '500 not yet implemented', { };
165 my $server = MSVA->new();