]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/ssl/cert_valid.pl
Boilerplate: update copyright blurbs on Squid helpers
[thirdparty/squid.git] / helpers / ssl / cert_valid.pl
CommitLineData
a1f04d64
AR
1#!/usr/bin/perl -w
2#
3# A dummy SSL certificate validator helper that
4# echos back all the SSL errors sent by Squid.
5#
6
7use warnings;
4a77bb4e
CT
8use strict;
9use Getopt::Long;
10use Pod::Usage;
a1f04d64
AR
11use Crypt::OpenSSL::X509;
12use FileHandle;
4a77bb4e
CT
13use POSIX qw(strftime);
14
15my $debug = 0;
16my $help = 0;
17
18=pod
19
20=head1 NAME
21
22cert_valid.pl - A fake cert validation helper for Squid
23
24=head1 SYNOPSIS
25
26cert_valid.pl [-d | --debug] [-h | --help]
27
28=over 8
29
30=item B<-h | --help>
31
32brief help message
33
34=item B<-d | --debug>
35
36enable debug messages to stderr
37
38=back
a1f04d64 39
4a77bb4e 40=head1 DESCRIPTION
a1f04d64 41
4a77bb4e
CT
42Retrieves the SSL certificate error list from squid and echo back without any change.
43
44=head1 COPYRIGHT
45
ca02e0ec
AJ
46 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
47 *
48 * Squid software is distributed under GPLv2+ license and includes
49 * contributions from numerous individuals and organizations.
50 * Please see the COPYING and CONTRIBUTORS files for details.
51
4a77bb4e
CT
52(C) 2012 The Measurement Factory, Author: Tsantilas Christos
53
54This program is free software. You may redistribute copies of it under the
55terms of the GNU General Public License version 2, or (at your opinion) any
56later version.
57
58=cut
59
60GetOptions(
61 'help' => \$help,
62 'debug' => \$debug,
63 ) or pod2usage(1);
64
65pod2usage(1) if ($help);
a1f04d64
AR
66
67$|=1;
68while (<>) {
69 my $first_line = $_;
70 my @line_args = split;
71
72 if ($first_line =~ /^\s*$/) {
73 next;
74 }
75
76 my $response;
dd7167ea 77 my $haserror = 0;
4a77bb4e
CT
78 my $channelId = $line_args[0];
79 my $code = $line_args[1];
80 my $bodylen = $line_args[2];
81 my $body = $line_args[3] . "\n";
82 if ($channelId !~ /\d+/) {
83 $response = $channelId." BH message=\"This helper is concurrent and requires the concurrency option to be specified.\"\1";
84 } elsif ($bodylen !~ /\d+/) {
85 $response = $channelId." BH message=\"cert validator request syntax error \" \1";
86 } else {
a1f04d64
AR
87 my $readlen = length($body);
88 my %certs = ();
62a7607e 89 my %errors = ();
a1f04d64
AR
90 my @responseErrors = ();
91
92 while($readlen < $bodylen) {
93 my $t = <>;
94 if (defined $t) {
95 $body = $body . $t;
96 $readlen = length($body);
97 }
98 }
99
4a77bb4e
CT
100 print(STDERR logPrefix()."GOT ". "Code=".$code." $bodylen \n") if ($debug); #.$body;
101 my $hostname;
62a7607e 102 parseRequest($body, \$hostname, \%errors, \%certs);
4a77bb4e
CT
103 print(STDERR logPrefix()."Parse result: \n") if ($debug);
104 print(STDERR logPrefix()."\tFOUND host:".$hostname."\n") if ($debug);
105 print(STDERR logPrefix()."\tFOUND ERRORS:") if ($debug);
62a7607e
CT
106 foreach my $err (keys %errors) {
107 print(STDERR logPrefix().$errors{$err}{"name"}."/".$errors{$err}{"cert"}." ,") if ($debug);
a1f04d64 108 }
4a77bb4e
CT
109 print(STDERR "\n") if ($debug);
110 foreach my $key (keys %certs) {
a1f04d64 111 ## Use "perldoc Crypt::OpenSSL::X509" for X509 available methods.
4a77bb4e 112 print(STDERR logPrefix()."\tFOUND cert ".$key.": ".$certs{$key}->subject() . "\n") if ($debug);
a1f04d64
AR
113 }
114
115 #got the peer certificate ID. Assume that the peer certificate is the first one.
116 my $peerCertId = (keys %certs)[0];
117
118 # Echo back the errors: fill the responseErrors array with the errors we read.
62a7607e 119 foreach my $err (keys %errors) {
dd7167ea 120 $haserror = 1;
a1f04d64 121 appendError (\@responseErrors,
62a7607e 122 $errors{$err}{"name"}, #The error name
a1f04d64 123 "Checked by Cert Validator", # An error reason
62a7607e 124 $errors{$err}{"cert"} # The cert ID. We are always filling with the peer certificate.
a1f04d64
AR
125 );
126 }
127
128 $response = createResponse(\@responseErrors);
129 my $len = length($response);
dd7167ea 130 if ($haserror) {
4a77bb4e 131 $response = $channelId." ERR ".$len." ".$response."\1";
dd7167ea 132 } else {
4a77bb4e 133 $response = $channelId." OK ".$len." ".$response."\1";
dd7167ea 134 }
a1f04d64
AR
135 }
136
137 print $response;
4a77bb4e 138 print(STDERR logPrefix().">> ".$response."\n") if ($debug);
a1f04d64 139}
a1f04d64
AR
140
141sub trim
142{
143 my $s = shift;
144 $s =~ s/^\s+//;
145 $s =~ s/\s+$//;
146 return $s;
147}
148
149sub appendError
150{
151 my ($errorArrays) = shift;
152 my($errorName) = shift;
153 my($errorReason) = shift;
154 my($errorCert) = shift;
155 push @$errorArrays, { "error_name" => $errorName, "error_reason" => $errorReason, "error_cert" => $errorCert};
156}
157
158sub createResponse
159{
160 my ($responseErrors) = shift;
161 my $response="";
162 my $i = 0;
4a77bb4e 163 foreach my $err (@$responseErrors) {
a1f04d64
AR
164 $response=$response."error_name_".$i."=".$err->{"error_name"}."\n".
165 "error_reason_".$i."=".$err->{"error_reason"}."\n".
166 "error_cert_".$i."=".$err->{"error_cert"}."\n";
167 $i++;
168 }
169 return $response;
170}
171
172sub parseRequest
173{
174 my($request)=shift;
175 my $hostname = shift;
176 my $errors = shift;
177 my $certs = shift;
178 while ($request !~ /^\s*$/) {
179 $request = trim($request);
180 if ($request =~ /^host=/) {
181 my($vallen) = index($request, "\n");
182 my $host = substr($request, 5, $vallen - 5);
183 $$hostname = $host;
721fabb6 184 $request =~ s/^host=.*$//m;
a1f04d64 185 }
62a7607e 186 if ($request =~ /^cert_(\d+)=/) {
a1f04d64
AR
187 my $certId = "cert_".$1;
188 my($vallen) = index($request, "-----END CERTIFICATE-----") + length("-----END CERTIFICATE-----");
189 my $x509 = Crypt::OpenSSL::X509->new_from_string(substr($request, index($request, "-----BEGIN")));
190 $certs->{$certId} = $x509;
191 $request = substr($request, $vallen);
192 }
62a7607e
CT
193 elsif ($request =~ /^error_name_(\d+)=(.*)$/m) {
194 my $errorId = $1;
195 my $errorName = $2;
196 $request =~ s/^error_name_\d+=.*$//m;
197 $errors->{$errorId}{"name"} = $errorName;
198 }
199 elsif ($request =~ /^error_cert_(\d+)=(.*)$/m) {
200 my $errorId = $1;
201 my $certId = $2;
202 $request =~ s/^error_cert_\d+=.*$//m;
203 $errors->{$errorId}{"cert"} = $certId;
204 }
a1f04d64 205 else {
4a77bb4e 206 print(STDERR logPrefix()."ParseError on \"".$request."\"\n") if ($debug);
a1f04d64
AR
207 $request = "";# finish processing....
208 }
209 }
210}
4a77bb4e
CT
211
212
213sub logPrefix
214{
215 return strftime("%Y/%m/%d %H:%M:%S.0", localtime)." ".$0." ".$$." | " ;
216}