]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - helpers/ssl/cert_valid.pl
SourceFormat Enforcement
[thirdparty/squid.git] / helpers / ssl / cert_valid.pl
old mode 100644 (file)
new mode 100755 (executable)
index 78fa31d..3ddd8cb
@@ -5,16 +5,64 @@
 #
 
 use warnings;
-# TODO:
-# use strict;
-
+use strict;
+use Getopt::Long;
+use Pod::Usage;
 use Crypt::OpenSSL::X509;
 use FileHandle;
+use POSIX qw(strftime);
+
+my $debug = 0;
+my $help = 0;
+
+=pod
+
+=head1 NAME
+
+cert_valid.pl - A fake cert validation helper for Squid
+
+=head1 SYNOPSIS
+
+cert_valid.pl [-d | --debug] [-h | --help]
+
+=over 8
+
+=item  B<-h | --help>
+
+brief help message
+
+=item B<-d | --debug>
+
+enable debug messages to stderr
+
+=back
+
+=head1 DESCRIPTION
+
+Retrieves the SSL certificate error list from squid and echo back without any change.
 
-my $LOGFILE = "/tmp/ssl_cert_valid.log";
+=head1 COPYRIGHT
 
-open(LOG, ">>$LOGFILE") or die("Cannot open logfile $LOGFILE, stopped");
-LOG->autoflush(1);
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+
+(C) 2012 The Measurement Factory, Author: Tsantilas Christos
+
+This program is free software. You may redistribute copies of it under the
+terms of the GNU General Public License version 2, or (at your opinion) any
+later version.
+
+=cut
+
+GetOptions(
+    'help' => \$help,
+    'debug' => \$debug,
+    ) or pod2usage(1);
+
+pod2usage(1) if ($help);
 
 $|=1;
 while (<>) {
@@ -27,13 +75,18 @@ while (<>) {
 
     my $response;
     my $haserror = 0;
-    my $code = $line_args[0];
-    my $bodylen = $line_args[1];
-    my $body = $line_args[2] . "\n";
-    if ($bodylen =~ /\d+/) {
+    my $channelId = $line_args[0];
+    my $code = $line_args[1];
+    my $bodylen = $line_args[2];
+    my $body = $line_args[3] . "\n";
+    if ($channelId !~ /\d+/) {
+        $response = $channelId." BH message=\"This helper is  concurrent and requires the concurrency option to be specified.\"\1";
+    } elsif ($bodylen !~ /\d+/) {
+        $response = $channelId." BH message=\"cert validator request syntax error \" \1";
+    } else {
         my $readlen = length($body);
         my %certs = ();
-        my @errors = ();
+        my %errors = ();
         my @responseErrors = ();
 
         while($readlen < $bodylen) {
@@ -44,48 +97,50 @@ while (<>) {
             }
         }
 
-        print LOG "GOT ". "Code=".$code." $bodylen \n"; #.$body;
-        parseRequest($body, \$hostname, \@errors, \%certs);
-        print LOG " Parse result: \n";
-        print LOG "\tFOUND host:".$hostname."\n";
-        print LOG "\tFOUND ERRORS:";
-        foreach $err(@errors) {
-            print LOG "$err ,";
+        print(STDERR logPrefix()."GOT ". "Code=".$code." $bodylen \n") if ($debug); #.$body;
+        my $hostname;
+        my $sslVersion = "-";
+        my $sslCipher = "-";
+        parseRequest($body, \$hostname, \$sslVersion, \$sslCipher, \%errors, \%certs);
+        print(STDERR logPrefix()."Parse result: \n") if ($debug);
+        print(STDERR logPrefix()."\tFOUND host:".$hostname."\n") if ($debug);
+        print(STDERR logPrefix()."\tFOUND ssl version:".$sslVersion."\n") if ($debug);
+        print(STDERR logPrefix()."\tFOUND ssl cipher:".$sslCipher."\n") if ($debug);
+        print(STDERR logPrefix()."\tFOUND ERRORS:") if ($debug);
+        foreach my $err (keys %errors) {
+            print(STDERR logPrefix().$errors{$err}{"name"}."/".$errors{$err}{"cert"}." ,")  if ($debug);
         }
-        print LOG "\n";
-        foreach $key (keys %certs) {
+        print(STDERR "\n") if ($debug);
+        foreach my $key (keys %certs) {
             ## Use "perldoc Crypt::OpenSSL::X509" for X509 available methods.
-            print LOG "\tFOUND cert ".$key.": ".$certs{$key}->subject() . "\n";
+            print(STDERR logPrefix()."\tFOUND cert ".$key.": ".$certs{$key}->subject() . "\n") if ($debug);
         }
 
         #got the peer certificate ID. Assume that the peer certificate is the first one.
         my $peerCertId = (keys %certs)[0];
 
         # Echo back the errors: fill the responseErrors array  with the errors we read.
-        foreach $err (@errors) {
+        foreach my $err (keys %errors) {
             $haserror = 1;
             appendError (\@responseErrors, 
-                         $err, #The error name
+                         $errors{$err}{"name"}, #The error name
                          "Checked by Cert Validator", # An error reason
-                         $peerCertId # The cert ID. We are always filling with the peer certificate.
+                         $errors{$err}{"cert"} # The cert ID. We are always filling with the peer certificate.
                 );
         }
 
         $response = createResponse(\@responseErrors);
         my $len = length($response);
         if ($haserror) {
-            $response = "ERR ".$len." ".$response."\1";
+            $response = $channelId." ERR ".$len." ".$response."\1";
         } else {
-            $response = "OK ".$len." ".$response."\1";
+            $response = $channelId." OK ".$len." ".$response."\1";
         }
-    } else {
-        $response = "BH 0 \1";
     }
 
     print $response;
-    print LOG ">> ".$response;
+    print(STDERR logPrefix().">> ".$response."\n") if ($debug);
 }
-close(LOG);
 
 sub trim
 {
@@ -109,7 +164,7 @@ sub createResponse
     my ($responseErrors) = shift;
     my $response="";
     my $i = 0;
-    foreach $err (@$responseErrors) {
+    foreach my $err (@$responseErrors) {
         $response=$response."error_name_".$i."=".$err->{"error_name"}."\n".
             "error_reason_".$i."=".$err->{"error_reason"}."\n".
             "error_cert_".$i."=".$err->{"error_cert"}."\n";
@@ -122,6 +177,8 @@ sub parseRequest
 {
     my($request)=shift;
     my $hostname = shift;
+    my $sslVersion = shift;
+    my $sslCipher = shift;
     my $errors = shift;
     my $certs = shift;
     while ($request !~ /^\s*$/) {
@@ -130,24 +187,42 @@ sub parseRequest
             my($vallen) = index($request, "\n");
             my $host = substr($request, 5, $vallen - 5);
             $$hostname = $host;
-            $request =~ s/^host=.*\n//;
+            $request =~ s/^host=.*$//m;
         }
-        if ($request =~ /^errors=/) {
-            my($vallen) = index($request, "\n");
-            my $listerrors = substr($request, 7, $vallen - 7);
-            @$errors = split /,/, $listerrors;
-            $request =~ s/^errors=.*\n//;
+        if ($request =~ s/^proto_version=(.*?)$//m) {
+            $$sslVersion = $1;
         }
-        elsif ($request =~ /^cert_(\d+)=/) {
+        if ($request =~ s/^cipher=(.*?)$//m) {
+            $$sslCipher = $1;
+        }
+        if ($request =~ /^cert_(\d+)=/) {
             my $certId = "cert_".$1;
             my($vallen) = index($request, "-----END CERTIFICATE-----") + length("-----END CERTIFICATE-----");
             my $x509 = Crypt::OpenSSL::X509->new_from_string(substr($request, index($request, "-----BEGIN")));
             $certs->{$certId} = $x509;
             $request = substr($request, $vallen);
         }
+        elsif ($request =~ /^error_name_(\d+)=(.*)$/m) {
+            my $errorId = $1;
+            my $errorName = $2;
+            $request =~ s/^error_name_\d+=.*$//m;
+            $errors->{$errorId}{"name"} = $errorName;
+        }
+        elsif ($request =~ /^error_cert_(\d+)=(.*)$/m) {
+            my $errorId = $1;
+            my $certId = $2;
+            $request =~ s/^error_cert_\d+=.*$//m;
+            $errors->{$errorId}{"cert"} = $certId;
+        }
         else {
-            print LOG "ParseError on \"".$request."\"\n";
+            print(STDERR logPrefix()."ParseError on \"".$request."\"\n") if ($debug);
             $request = "";# finish processing....
         }
     }
 }
+
+
+sub logPrefix
+{
+  return strftime("%Y/%m/%d %H:%M:%S.0", localtime)." ".$0." ".$$." | " ;
+}