]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/cert_validators/fake/security_fake_certverify.pl.in
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / security / cert_validators / fake / security_fake_certverify.pl.in
1 #!@PERL@
2
3 use warnings;
4 use strict;
5 use Getopt::Long;
6 use Pod::Usage;
7 use Crypt::OpenSSL::X509;
8 use FileHandle;
9 use POSIX qw(strftime);
10
11 my $debug = 0;
12 my $help = 0;
13
14 =pod
15
16 =head1 NAME
17
18 security_fake_certverify - A fake cert validation helper for Squid
19
20 =head1 SYNOPSIS
21
22 security_fake_certverify [-d | --debug] [-h | --help]
23
24 =head1 DESCRIPTION
25
26 Retrieves the SSL certificate error list from Squid and echo back without any change.
27
28 =head1 OPTIONS
29
30 =over 8
31
32 =item B<-h | --help>
33
34 brief help message
35
36 =item B<-d | --debug>
37
38 enable debug messages to stderr
39
40 =back
41
42 =head1 AUTHOR
43
44 This program and documentation was written by
45 I<Christos Tsantilas <chtsanti@users.sourceforge.net>>
46
47 =head1 COPYRIGHT
48
49 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
50 *
51 * Squid software is distributed under GPLv2+ license and includes
52 * contributions from numerous individuals and organizations.
53 * Please see the COPYING and CONTRIBUTORS files for details.
54
55 (C) 2012 The Measurement Factory, Author: Tsantilas Christos
56
57 This program is free software. You may redistribute copies of it under the
58 terms of the GNU General Public License version 2, or (at your opinion) any
59 later version.
60
61 =head1 QUESTIONS
62
63 Questions on the usage of this program can be sent to the I<Squid Users mailing list <squid-users@lists.squid-cache.org>>
64
65 =head1 REPORTING BUGS
66
67 Bug reports need to be made in English.
68 See http://wiki.squid-cache.org/SquidFaq/BugReporting for details of what you need to include with your bug report.
69
70 Report bugs or bug fixes using http://bugs.squid-cache.org/
71
72 Report serious security bugs to I<Squid Bugs <squid-bugs@lists.squid-cache.org>>
73
74 Report ideas for new improvements to the I<Squid Developers mailing list <squid-dev@lists.squid-cache.org>>
75
76 =head1 SEE ALSO
77
78 squid (8), GPL (7),
79
80 The Squid FAQ wiki http://wiki.squid-cache.org/SquidFaq
81
82 The Squid Configuration Manual http://www.squid-cache.org/Doc/config/
83
84 =cut
85
86 GetOptions(
87 'help' => \$help,
88 'debug' => \$debug,
89 ) or pod2usage(1);
90
91 pod2usage(1) if ($help);
92
93 $|=1;
94 while (<>) {
95 my $first_line = $_;
96 my @line_args = split;
97
98 if ($first_line =~ /^\s*$/) {
99 next;
100 }
101
102 my $response;
103 my $haserror = 0;
104 my $channelId = $line_args[0];
105 my $code = $line_args[1];
106 my $bodylen = $line_args[2];
107 my $body = $line_args[3] . "\n";
108 if ($channelId !~ /\d+/) {
109 $response = $channelId." BH message=\"This helper is concurrent and requires the concurrency option to be specified.\"\1";
110 } elsif ($bodylen !~ /\d+/) {
111 $response = $channelId." BH message=\"cert validator request syntax error \" \1";
112 } else {
113 my $readlen = length($body);
114 my %certs = ();
115 my %errors = ();
116 my @responseErrors = ();
117
118 while($readlen < $bodylen) {
119 my $t = <>;
120 if (defined $t) {
121 $body = $body . $t;
122 $readlen = length($body);
123 }
124 }
125
126 print(STDERR logPrefix()."GOT ". "Code=".$code." $bodylen \n") if ($debug); #.$body;
127 my $hostname;
128 my $sslVersion = "-";
129 my $sslCipher = "-";
130 parseRequest($body, \$hostname, \$sslVersion, \$sslCipher, \%errors, \%certs);
131 print(STDERR logPrefix()."Parse result: \n") if ($debug);
132 print(STDERR logPrefix()."\tFOUND host:".$hostname."\n") if ($debug);
133 print(STDERR logPrefix()."\tFOUND ssl version:".$sslVersion."\n") if ($debug);
134 print(STDERR logPrefix()."\tFOUND ssl cipher:".$sslCipher."\n") if ($debug);
135 print(STDERR logPrefix()."\tFOUND ERRORS:") if ($debug);
136 foreach my $err (keys %errors) {
137 print(STDERR logPrefix().$errors{$err}{"name"}."/".$errors{$err}{"cert"}." ,") if ($debug);
138 }
139 print(STDERR "\n") if ($debug);
140 foreach my $key (keys %certs) {
141 ## Use "perldoc Crypt::OpenSSL::X509" for X509 available methods.
142 print(STDERR logPrefix()."\tFOUND cert ".$key.": ".$certs{$key}->subject() . "\n") if ($debug);
143 }
144
145 #got the peer certificate ID. Assume that the peer certificate is the first one.
146 my $peerCertId = (keys %certs)[0];
147
148 # Echo back the errors: fill the responseErrors array with the errors we read.
149 foreach my $err (keys %errors) {
150 $haserror = 1;
151 appendError (\@responseErrors,
152 $errors{$err}{"name"}, #The error name
153 "Checked by Cert Validator", # An error reason
154 $errors{$err}{"cert"} # The cert ID. We are always filling with the peer certificate.
155 );
156 }
157
158 $response = createResponse(\@responseErrors);
159 my $len = length($response);
160 if ($haserror) {
161 $response = $channelId." ERR ".$len." ".$response."\1";
162 } else {
163 $response = $channelId." OK ".$len." ".$response."\1";
164 }
165 }
166
167 print $response;
168 print(STDERR logPrefix().">> ".$response."\n") if ($debug);
169 }
170
171 sub trim
172 {
173 my $s = shift;
174 $s =~ s/^\s+//;
175 $s =~ s/\s+$//;
176 return $s;
177 }
178
179 sub appendError
180 {
181 my ($errorArrays) = shift;
182 my($errorName) = shift;
183 my($errorReason) = shift;
184 my($errorCert) = shift;
185 push @$errorArrays, { "error_name" => $errorName, "error_reason" => $errorReason, "error_cert" => $errorCert};
186 }
187
188 sub createResponse
189 {
190 my ($responseErrors) = shift;
191 my $response="";
192 my $i = 0;
193 foreach my $err (@$responseErrors) {
194 $response=$response."error_name_".$i."=".$err->{"error_name"}."\n".
195 "error_reason_".$i."=".$err->{"error_reason"}."\n".
196 "error_cert_".$i."=".$err->{"error_cert"}."\n";
197 $i++;
198 }
199 return $response;
200 }
201
202 sub parseRequest
203 {
204 my($request)=shift;
205 my $hostname = shift;
206 my $sslVersion = shift;
207 my $sslCipher = shift;
208 my $errors = shift;
209 my $certs = shift;
210 while ($request !~ /^\s*$/) {
211 $request = trim($request);
212 if ($request =~ /^host=/) {
213 my($vallen) = index($request, "\n");
214 my $host = substr($request, 5, $vallen - 5);
215 $$hostname = $host;
216 $request =~ s/^host=.*$//m;
217 }
218 if ($request =~ s/^proto_version=(.*?)$//m) {
219 $$sslVersion = $1;
220 }
221 if ($request =~ s/^cipher=(.*?)$//m) {
222 $$sslCipher = $1;
223 }
224 if ($request =~ /^cert_(\d+)=/) {
225 my $certId = "cert_".$1;
226 my($vallen) = index($request, "-----END CERTIFICATE-----") + length("-----END CERTIFICATE-----");
227 my $x509 = Crypt::OpenSSL::X509->new_from_string(substr($request, index($request, "-----BEGIN")));
228 $certs->{$certId} = $x509;
229 $request = substr($request, $vallen);
230 }
231 elsif ($request =~ /^error_name_(\d+)=(.*)$/m) {
232 my $errorId = $1;
233 my $errorName = $2;
234 $request =~ s/^error_name_\d+=.*$//m;
235 $errors->{$errorId}{"name"} = $errorName;
236 }
237 elsif ($request =~ /^error_cert_(\d+)=(.*)$/m) {
238 my $errorId = $1;
239 my $certId = $2;
240 $request =~ s/^error_cert_\d+=.*$//m;
241 $errors->{$errorId}{"cert"} = $certId;
242 }
243 else {
244 print(STDERR logPrefix()."ParseError on \"".$request."\"\n") if ($debug);
245 $request = "";# finish processing....
246 }
247 }
248 }
249
250
251 sub logPrefix
252 {
253 return strftime("%Y/%m/%d %H:%M:%S.0", localtime)." ".$0." ".$$." | " ;
254 }