[LON-CAPA-cvs] cvs: loncom / Lond.pm /configuration SSL.pm

raeburn raeburn at source.lon-capa.org
Thu Jul 11 14:12:06 EDT 2019


raeburn		Thu Jul 11 18:12:06 2019 EDT

  Modified files:              
    /loncom	Lond.pm 
    /loncom/configuration	SSL.pm 
  Log:
  - Information about Certificate Revocations List included in SSL Certificates
    status report.  LONCAPA-prerequisites needs perl-Crypt-X509-CRL. 
  
  
-------------- next part --------------
Index: loncom/Lond.pm
diff -u loncom/Lond.pm:1.14 loncom/Lond.pm:1.15
--- loncom/Lond.pm:1.14	Sat Dec 22 17:06:02 2018
+++ loncom/Lond.pm	Thu Jul 11 18:12:01 2019
@@ -1,6 +1,6 @@
 # The LearningOnline Network
 #
-# $Id: Lond.pm,v 1.14 2018/12/22 17:06:02 raeburn Exp $
+# $Id: Lond.pm,v 1.15 2019/07/11 18:12:01 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -37,7 +37,9 @@
 use LONCAPA;
 use Apache::lonnet;
 use GDBM_File;
+use MIME::Base64;
 use Crypt::OpenSSL::X509;
+use Crypt::X509::CRL;
 use Crypt::PKCS10;
 
 sub dump_with_regexp {
@@ -819,25 +821,77 @@
                      host     => 'lonnetCertificate',
                      hostname => 'lonnetHostnameCertificate',
                      ca       => 'lonnetCertificateAuthority',
+                     crl      => 'lonnetCertRevocationList',
                    );
-    my (%md5hash,%expected_cn,%expired,%revoked,%wrongcn,%info,$crlfile);
+    my (%md5hash,%expected_cn,%expired,%revoked,%wrongcn,%info,$crlfile,$cafile,
+        %rvkcerts,$numrvk);
     %info = (
                 key => {},
                 ca  => {},
                 host => {},
                 hostname => {},
-            ); 
+                crl => {},
+            );
+    my @ordered = ('crl','key','ca','host','hostname');
     if (ref($perlvar) eq 'HASH') {
         $expected_cn{'host'} = $Apache::lonnet::serverhomeIDs{$hostname};
         $expected_cn{'hostname'} = 'internal-'.$hostname;
         my $certsdir = $perlvar->{'lonCertificateDirectory'};
         if (-d $certsdir) {
-            $crlfile = $certsdir.'/'.$perlvar->{'lonnetCertRevocationList'};
-            foreach my $key (keys(%pemfiles)) {
+            $crlfile = $certsdir.'/'.$perlvar->{$pemfiles{'crl'}};
+            $cafile = $certsdir.'/'.$perlvar->{$pemfiles{'ca'}};
+            foreach my $key (@ordered) {
                 if ($perlvar->{$pemfiles{$key}}) {
                     my $file = $certsdir.'/'.$perlvar->{$pemfiles{$key}};
                     if (-e $file) {
-                        if ($key eq 'key') {
+                        if ($key eq 'crl') {
+                             if ((-e $crlfile) && (-e $cafile)) {
+                                 if (open(PIPE,"openssl crl -in $crlfile -inform pem -CAfile $cafile -noout 2>&1 |")) {
+                                     my $crlstatus = <PIPE>;
+                                     close(PIPE);
+                                     chomp($crlstatus);
+                                     if ($crlstatus =~ /OK/) {
+                                         $info{$key}{'status'} = 'ok';
+                                         $info{$key}{'details'} = 'CRL valid for CA';
+                                     }
+                                 }
+                             }
+                             if (open(my $fh,'<',$crlfile)) {
+                                 my $pem_crl = '';
+                                 while (my $line=<$fh>) {
+                                     chomp($line);
+                                     next if ($line eq '-----BEGIN X509 CRL-----');
+                                     next if ($line eq '-----END X509 CRL-----');
+                                     $pem_crl .= $line;
+                                 }
+                                 close($fh);
+                                 my $der_crl = MIME::Base64::decode_base64($pem_crl);
+                                 if ($der_crl ne '') {
+                                     my $decoded = Crypt::X509::CRL->new( crl => $der_crl );
+                                     if ($decoded->error) {
+                                         $info{$key}{'status'} = 'error';
+                                     } elsif (ref($decoded)) {
+                                         $info{$key}{'start'} = $decoded->this_update;
+                                         $info{$key}{'end'} = $decoded->next_update;
+                                         $info{$key}{'alg'} = $decoded->SigEncAlg.' '.$decoded->SigHashAlg;
+                                         $info{$key}{'cn'} = $decoded->issuer_cn;
+                                         $info{$key}{'email'} = $decoded->issuer_email;
+                                         $info{$key}{'size'} = $decoded->signature_length;
+                                         my $rlref = $decoded->revocation_list;
+                                         if (ref($rlref) eq 'HASH') {
+                                             foreach my $key (keys(%{$rlref})) {
+                                                 my $hkey = sprintf("%X",$key);
+                                                 $rvkcerts{$hkey} = 1;
+                                             }
+                                             $numrvk = scalar(keys(%{$rlref}));
+                                             if ($numrvk) {
+                                                 $info{$key}{'details'} .= " ($numrvk revoked)"; 
+                                             }
+                                         }
+                                     }
+                                 }
+                            }
+                        } elsif ($key eq 'key') {
                             if (open(PIPE,"openssl rsa -noout -in $file -check |")) {
                                 my $check = <PIPE>;
                                 close(PIPE);
@@ -882,7 +936,7 @@
                             $info{$key}{'alg'} = $x509->sig_alg_name();
                             $info{$key}{'size'} = $x509->bit_length();
                             $info{$key}{'email'} = $x509->email();
-                            $info{$key}{'serial'} = $x509->serial();
+                            $info{$key}{'serial'} = uc($x509->serial());
                             $info{$key}{'issuerhash'} = $x509->issuer_hash();
                             if ($x509->checkend(0)) {
                                 $expired{$key} = 1;
@@ -891,15 +945,9 @@
                                 if ($info{$key}{'cn'} ne $expected_cn{$key}) {
                                     $wrongcn{$key} = 1;
                                 }
-                                if ((-e $crlfile) && ($info{$key}{'serial'} =~ /^\w+$/)) {
-                                    my $serial = $info{$key}{'serial'};
-                                    if (open(PIPE,"openssl crl -inform PEM -text -in $crlfile | grep $serial |")) {
-                                        my $result = <PIPE>;
-                                        close(PIPE);
-                                        chomp($result);
-                                        if ($result ne '') {
-                                            $revoked{$key} = 1;
-                                        }
+                                if (($numrvk) && ($info{$key}{'serial'})) {
+                                    if ($rvkcerts{$info{$key}{'serial'}}) {
+                                        $revoked{$key} = 1;
                                     }
                                 }
                             }
Index: loncom/configuration/SSL.pm
diff -u loncom/configuration/SSL.pm:1.9 loncom/configuration/SSL.pm:1.10
--- loncom/configuration/SSL.pm:1.9	Fri Apr 12 02:41:47 2019
+++ loncom/configuration/SSL.pm	Thu Jul 11 18:12:06 2019
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Checksum installed LON-CAPA modules and some configuration files
 #
-# $Id: SSL.pm,v 1.9 2019/04/12 02:41:47 raeburn Exp $
+# $Id: SSL.pm,v 1.10 2019/07/11 18:12:06 raeburn Exp $
 #
 # The LearningOnline Network with CAPA
 #
@@ -58,6 +58,7 @@
                  'key'      => 'Private Key',
                  'host'     => 'Connections Certificate',
                  'hostname' => 'Replication Certificate',
+                 'crl'      => 'Revocations List',
                  'ca'       => 'LON-CAPA CA Certificate',
                  'expired'  => 'Expired',
                  'future'   => 'Future validity',
@@ -67,7 +68,7 @@
                  'wrongcn'  => 'Incorrect CN',
                  'mismatch' => 'Mismatched Issuer',
     );
-    my @files = qw(key host hostname ca);
+    my @files = qw(key host hostname ca crl);
     my @fields = qw(status cn start end alg size email);
     foreach my $server (sort(keys(%{$servers}))) {
         my $hostname = $servers->{$server};
@@ -103,30 +104,30 @@
                     }
                     unless ($file eq 'key') {
                         if ($hashref->{$file}->{'end'} ne '') {
-                            my $dt = DateTime::Format::x509->parse_datetime($hashref->{$file}->{'end'});
-                            if (ref($dt)) {
-                                $endtime = $dt->epoch;
-                                if ($endtime < time) {
-                                    if ($target eq 'web') {
-                                        $dateinvalid = $lt{'expired'};
-                                    } else {
-                                        $dateinvalid = 'expired';
-                                    }
+                            if ($file eq 'crl') {
+                                $endtime = $hashref->{$file}->{'end'};
+                            } else {
+                                my $dt = DateTime::Format::x509->parse_datetime($hashref->{$file}->{'end'});
+                                if (ref($dt)) {
+                                    $endtime = $dt->epoch;
                                 }
                             }
+                            if (($endtime ne '') && ($endtime < time)) {
+                                $dateinvalid = 'expired';
+                            }
                         }
                         if ($hashref->{$file}->{'start'} ne '') {
-                            my $dt = DateTime::Format::x509->parse_datetime($hashref->{$file}->{'start'});
-                            if (ref($dt)) {
-                                $starttime = $dt->epoch;
-                                if ($starttime > time) {
-                                    unless ($dateinvalid) {
-                                        if ($target eq 'web') {
-                                            $dateinvalid = $lt{'future'};
-                                        } else {
-                                            $dateinvalid = 'future';
-                                        }
-                                    }
+                            if ($file eq 'crl') {
+                                $starttime = $hashref->{$file}->{'start'};
+                            } else {
+                                my $dt = DateTime::Format::x509->parse_datetime($hashref->{$file}->{'start'});
+                                if (ref($dt)) {
+                                    $starttime = $dt->epoch;
+                                }
+                            }
+                            if ($starttime > time) {
+                                unless ($dateinvalid) {
+                                    $dateinvalid = 'future';
                                 }
                             }
                         }
@@ -140,28 +141,56 @@
                                         $display = &Apache::lonhtmlcommon::confirm_success($display);
                                     }
                                 }
+                            } elsif ($file eq 'crl') {
+                                if ($dateinvalid) {
+                                    if (($target eq 'web') && (exists($lt{$dateinvalid}))) {
+                                        $display = $lt{$dateinvalid};
+                                    } else {  
+                                        $display = $dateinvalid;
+                                    }
+                                } elsif ($target eq 'web') {
+                                    if ($display ne '') {
+                                        $display = &Apache::lonhtmlcommon::confirm_success($display);
+                                    }
+                                    my $details = $hashref->{$file}->{details};
+                                    if ($details ne '') {
+                                        $display .= ' '.$details;
+                                    }
+                                }
                             } elsif ($file eq 'ca') {
                                 if ($dateinvalid) {
-                                    $display = $dateinvalid;
+                                    if (($target eq 'web') && (exists($lt{$dateinvalid}))) {
+                                        $display = $lt{$dateinvalid};
+                                    } else {
+                                        $display = $dateinvalid;
+                                    }
                                 } elsif ($target eq 'web') {
-                                    $display = &Apache::lonhtmlcommon::confirm_success($display);
+                                    if ($display ne '') {
+                                        $display = &Apache::lonhtmlcommon::confirm_success($display);
+                                    }
                                 }
                             } elsif ($display =~ /^ok/) {
                                 if ($dateinvalid) {
-                                    $display = $dateinvalid;
+                                    if (($target eq 'web') && (exists($lt{$dateinvalid}))) {
+                                        $display = $lt{$dateinvalid};
+                                    } else {
+                                        $display = $dateinvalid;
+                                    }
                                 } elsif ($target eq 'web') { 
                                     $display = &Apache::lonhtmlcommon::confirm_success($display);
                                 }
                             } elsif (($display eq 'nokey') || ($display eq 'otherkey') ||
                                      ($display eq 'revoked') || ($display eq 'expired') ||
-                                     ($display eq 'wrongcn') || ($display eq 'mismatch')) {
-                                if ($target eq 'web') {
+                                     ($display eq 'wrongcn') || ($display eq 'mismatch') ||
+                                     ($display eq '')) {
+                                if (($target eq 'web') && ($display ne '') && (exists($lt{$display}))) {
                                     $display = $lt{$display};
                                 }
                                 if (ref($hashref->{$file.'-csr'}) eq 'HASH') {
                                     if ($hashref->{$file.'-csr'}->{$item} eq 'ok') {
                                         if ($target eq 'web') {
-                                            $display .= '<br />'.&mt('(New request awaiting signature)');
+                                            $display .= (($display ne '')? '<br />':'').
+                                                        &mt('(New request awaiting signature)');
                                         }
                                         $csr{$file} = 1;
                                     }


More information about the LON-CAPA-cvs mailing list