3 # usercert.cgi -- user push authentication certificate retrieval
4 # Copyright (c) 2013 Kyle J. McKay. All rights reserved.
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (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, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 my $mesg = shift || "<p>404 - Not found</p>";
33 my $gcgi = Girocco
::CGI
->new('User HTTPS Push Authentication Certificate');
41 my (undef,undef,undef,undef,undef,undef,undef,undef,undef,$mtime) = stat $fname;
49 open(FILE
, '<', $fname) or return undef;
50 my $contents = <FILE
>;
55 notfound
unless $Girocco::Config
::clientcert
&& $Girocco::Config
::clientkey
;
59 notfound
if $cgi->request_method() ne 'GET' && $cgi->request_method() ne 'HEAD';
60 notfound
"<p>Go away, bot.</p>" if $cgi->param('mail');
62 my $nick = $Girocco::Config
::nickname
;
64 my $name = $cgi->param('name');
65 $name =~ s/^\s*(.*?)\s*$/$1/ if $name;
66 my $line = $cgi->param('line');
67 $line =~ s/^\s*(.*?)\s*$/$1/ if $line;
68 my $view = $cgi->param('view');
69 $view =~ s/^\s*(.*?)\s*$/$1/ if $view;
71 notfound
if $cgi->path_info() && ($name || $line);
73 if ($cgi->path_info() =~ m
,/([^/]+)/([^/]+)/([^/]+)$,) {
74 my ($tn,$tl,$tp) = ($1,$2,$3);
75 if ("${nick}_${tn}_user_$tl.pem" eq $tp) {
81 notfound
unless $name && $line && $line =~ /^[1-9][0-9]*$/;
84 notfound
unless Girocco
::User
::valid_name
($name) && Girocco
::User
::does_exist
($name);
85 my $user = Girocco
::User
->load($name) or notfound
;
87 my @keys = split(/\r?\n/, $user->{keys});
88 $line <= @keys or notfound
;
89 my ($type, $bits, $fingerprint, $comment) = sshpub_validate
($keys[$line-1]);
90 $type && $type eq 'ssh-rsa' or notfound
;
92 my $sshkeys = jailed_file
($user->_sshkey_path);
93 my $kname = "${nick}_${name}_user_$line.pem";
94 my $sshcert = jailed_file
("/etc/sshcerts/$kname");
95 my $sshkeysmtime = mtime
($sshkeys);
96 notfound
unless $sshkeysmtime;
97 my $sshcertmtime = mtime
($sshcert);
98 if (!$sshcertmtime || $sshkeysmtime >= $sshcertmtime) {
101 "$Girocco::Config::basedir/bin/CACreateCert", "--quiet", "--client",
102 "--cert", $Girocco::Config
::clientcert
,
103 "--key", $Girocco::Config
::clientkey
,
106 push(@args, "--suffix", $Girocco::Config
::clientcertsuffix
)
107 if $Girocco::Config
::clientcertsuffix
;
109 open(PIPE
, "|-", @args) or notfound
;
110 print PIPE
$keys[$line-1], "\n";
111 close(PIPE
) or notfound
;
112 chmod(0664, $sshcert);
114 notfound
unless -r
$sshcert;
115 my $certdata = readfile
($sshcert);
116 notfound
unless $certdata;
118 $isviewonly = 0 + $view if $view && $view =~ /^[01]$/;
120 print "Content-Type: text/plain\r\n"
122 print "Content-Type: application/octet-stream\r\n";
123 print "Content-Disposition: attachment; filename=\"$kname\"\r\n";
126 print $certdata unless $cgi->request_method() eq 'HEAD';