[LON-CAPA-cvs] cvs: loncom / LWPReq.pm Lond.pm loncapa_apache.conf lond lontrans.pm /cgi lonauthcgi.pm loncertstatus.pl /configuration SSL.pm /interface domainprefs.pm domainstatus.pm lonconfigsettings.pm /lonnet/perl lonnet.pm
raeburn
raeburn at source.lon-capa.org
Mon Jul 25 15:50:46 EDT 2016
raeburn Mon Jul 25 19:50:46 2016 EDT
Added files:
/loncom/cgi loncertstatus.pl
/loncom/configuration SSL.pm
Modified files:
/loncom LWPReq.pm Lond.pm lond lontrans.pm loncapa_apache.conf
/loncom/cgi lonauthcgi.pm
/loncom/interface domainprefs.pm domainstatus.pm
lonconfigsettings.pm
/loncom/lonnet/perl lonnet.pm
Log:
- Use Server Name Indication (SNI) and SSL when replicating content from
/raw/.
- Domain status screen has link to show status of LON-CAPA SSL certificates.
- "SSL" domain config for (a) "internal" LON-CAPA SSL connection to servers/VMs
in other domain, (b) Replication of domain's resources to other domains.
- Replication can use name-based virtual hosts with SSL, with verification of
client certificate (cert: /home/httpd/lonCerts/lonhostnamecert.pem, signed
by LON-CAPA CA, with Common Name of internal-<server hostname>, same IP address
as server hostname).
-------------- next part --------------
Index: loncom/LWPReq.pm
diff -u loncom/LWPReq.pm:1.1 loncom/LWPReq.pm:1.2
--- loncom/LWPReq.pm:1.1 Sat Jul 2 17:55:57 2016
+++ loncom/LWPReq.pm Mon Jul 25 19:49:45 2016
@@ -1,8 +1,8 @@
# The LearningOnline Network with CAPA
-# LON-CAPA wrapper for LWP UserAgent to accommodate certificate
+# LON-CAPA wrapper for LWP UserAgent to accommodate certification
# verification for SSL.
#
-# $Id: LWPReq.pm,v 1.1 2016/07/02 17:55:57 raeburn Exp $
+# $Id: LWPReq.pm,v 1.2 2016/07/25 19:49:45 raeburn Exp $
#
# The LearningOnline Network with CAPA
#
@@ -36,28 +36,63 @@
use LONCAPA::Configuration;
use IO::Socket::SSL();
use LWP::UserAgent();
+use LWP::UserAgent::DNS::Hosts();
+use Apache::lonnet;
sub makerequest {
- my ($request,$content,$perlvar,$timeout,$verifycert,$use_lc_ca,$debug) = @_;
+ my ($remotehostid,$request,$content,$perlvar,$timeout,$verifycert,$use_lc_ca,$debug) = @_;
unless (ref($perlvar) eq' HASH') {
$perlvar = LONCAPA::Configuration::read_conf('loncapa.conf');
}
- my ($certf,$keyf,$caf, at opts);
+ my ($certf,$keyf,$caf, at opts,$dns_set,$lonhost);
if (ref($perlvar) eq 'HASH') {
- $certf = $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetHostnameCertificate'};
- $keyf = $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetPrivateKey'};
- $caf = $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetCertificateAuthority'};
+ $lonhost = $perlvar->{'lonHostID'};
+ if ($perlvar->{'lonCertificateDirectory'}) {
+ if ($perlvar->{'lonnetHostnameCertificate'}) {
+ if (-e $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetHostnameCertificate'}) {
+ $certf = $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetHostnameCertificate'};
+ }
+ }
+ if ($perlvar->{'lonnetPrivateKey'}) {
+ if (-e $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetPrivateKey'}) {
+ $keyf = $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetPrivateKey'};
+ }
+ }
+ if ($perlvar->{'lonnetCertificateAuthority'}) {
+ if (-e $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetCertificateAuthority'}) {
+ $caf = $perlvar->{'lonCertificateDirectory'}.'/'.$perlvar->{'lonnetCertificateAuthority'};
+ }
+ }
+ }
}
if ($debug) {
$IO::Socket::SSL::DEBUG=$debug;
}
- my $response;
+ my ($response,$stdhostname,$remotehostname,$fn);
+ if ($request->uri =~ m{^https?://((?:internal\-|)([^/]+))(/raw/.+)$}) {
+ $remotehostname = $1;
+ $stdhostname = $2;
+ $fn = $3;
+ $dns_set = &setdns($remotehostid,$remotehostname);
+ unless ($remotehostname =~ /^internal\-/) {
+ if (($use_lc_ca && $certf && $keyf) &&
+ (&raw_redirected($remotehostid,$lonhost))) {
+ $remotehostname = 'internal-'.$stdhostname;
+ $request->uri('https://'.$remotehostname.$fn);
+ }
+ }
+ }
if (LWP::UserAgent->VERSION >= 6.00) {
my $ssl_opts;
if ($use_lc_ca && $certf && $keyf) {
$ssl_opts->{'SSL_use_cert'} = 1;
$ssl_opts->{'SSL_cert_file'} = $certf;
$ssl_opts->{'SSL_key_file'} = $keyf;
+ if ($dns_set && $remotehostname) {
+ if ($remotehostname =~ /^internal\-/) {
+ $ssl_opts->{'SSL_hostname'} = $remotehostname;
+ }
+ }
} else {
$ssl_opts->{'SSL_use_cert'} = 0;
}
@@ -65,7 +100,7 @@
$ssl_opts->{'verify_hostname'} = 1;
$ssl_opts->{'SSL_verify_mode'} = IO::Socket::SSL::SSL_VERIFY_PEER;
$ssl_opts->{'SSL_version'} = 'SSLv23:!SSLv3:!SSLv2';
- if ($use_lc_ca) {
+ if ($use_lc_ca) {
$ssl_opts->{'SSL_ca_file'} = $caf;
}
} else {
@@ -77,11 +112,30 @@
if ($timeout) {
$ua->timeout($timeout);
}
+ if ($use_lc_ca && $remotehostname && $fn) {
+ $ua->requests_redirectable(undef);
+ }
if ($content ne '') {
$response = $ua->request($request,$content);
} else {
$response = $ua->request($request);
}
+ if (($response->code eq '302') && ($fn) && ($remotehostname) &&
+ ($response->header('Location') eq 'https://internal-'.$stdhostname.$fn)) {
+ my $newurl = $response->header('Location');
+ unless ($dns_set) {
+ $dns_set = &setdns($remotehostid,$remotehostname);
+ }
+ if ($use_lc_ca && $certf && $keyf) {
+ $ssl_opts->{'SSL_hostname'} = 'internal-'.$stdhostname;
+ }
+ $request->uri($newurl);
+ if ($content ne '') {
+ $response = $ua->request($request,$content);
+ } else {
+ $response = $ua->request($request);
+ }
+ }
} else {
{
require Net::SSLGlue::LWP;
@@ -90,6 +144,11 @@
$Net::SSLGlue::LWP::SSLopts{'SSL_use_cert'} = 1;
$Net::SSLGlue::LWP::SSLopts{'SSL_cert_file'} = $certf;
$Net::SSLGlue::LWP::SSLopts{'SSL_key_file'} = $keyf;
+ if ($dns_set && $remotehostname) {
+ if ($remotehostname =~ /^internal\-/) {
+ $Net::SSLGlue::LWP::SSLopts{'SSL_hostname'} = $remotehostname;
+ }
+ }
} else {
$Net::SSLGlue::LWP::SSLopts{'SSL_use_cert'} = 0;
}
@@ -106,14 +165,94 @@
if ($timeout) {
$ua->timeout($timeout);
}
+ if ($use_lc_ca && $remotehostname && $fn) {
+ $ua->requests_redirectable(undef);
+ }
if ($content ne '') {
$response = $ua->request($request,$content);
} else {
$response = $ua->request($request);
}
+ if (($response->code eq '302') && ($fn) && ($remotehostname) &&
+ ($response->header('Location') eq 'https://internal-'.$stdhostname.$fn)) {
+ my $newurl = $response->header('Location');
+ unless ($dns_set) {
+ $dns_set = &setdns($remotehostid,$remotehostname);
+ }
+ $Net::SSLGlue::LWP::SSLopts{'SSL_hostname'} = 'internal-'.$stdhostname;
+ $request->uri($newurl);
+ if ($content ne '') {
+ $response = $ua->request($request,$content);
+ } else {
+ $response = $ua->request($request);
+ }
+ }
}
}
+ if ($dns_set) {
+ $dns_set = &unsetdns();
+ }
return $response;
}
+sub setdns {
+ my ($remotehostid,$remotehostname) = @_;
+ my $ip = &Apache::lonnet::get_host_ip($remotehostid);
+ if ($remotehostname =~ /^internal\-/) {
+ LWP::UserAgent::DNS::Hosts->register_host(
+ $remotehostname => $ip,
+ );
+ } else {
+ LWP::UserAgent::DNS::Hosts->register_host(
+ 'internal-'.$remotehostname => $ip,
+ );
+ }
+ LWP::UserAgent::DNS::Hosts->enable_override;
+ return 1;
+}
+
+sub unsetdns {
+ LWP::UserAgent::DNS::Hosts->clear_hosts();
+ return 0;
+}
+
+sub raw_redirected {
+ my ($remotehostid,$lonhost) = @_;
+ my $remhostname = &Apache::lonnet::hostname($remotehostid);
+ my $redirect;
+ if ($remhostname) {
+ my $remoterev = &Apache::lonnet::get_server_loncaparev(undef,$remotehostid);
+ my ($remmajor,$remminor) = ($remoterev =~ /^(\d+)\.(\d+)/);
+ if (($remmajor > 2) || (($remmajor == 2) && $remminor >= 12)) {
+ my $internet_names = &Apache::lonnet::get_internet_names($remotehostid);
+ if (ref($internet_names) eq 'ARRAY') {
+ my $intdom = &Apache::lonnet::internet_dom($lonhost);
+ unless (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ my $remhomeID = &Apache::lonnet::get_server_homeID($remhostname);
+ my $remhomedom = &Apache::lonnet::host_domain($remhomeID);
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($remhomedom);
+ my $replication = $domdefaults{'replication'};
+ if (ref($replication) eq 'HASH') {
+ if (ref($replication->{'reqcerts'}) eq 'ARRAY') {
+ if (grep(/^\Q$intdom\E$/,@{$replication->{'reqcerts'}})) {
+ $redirect = 1;
+ } else {
+ $redirect = 0;
+ }
+ }
+ if (ref($replication->{'noreqcerts'}) eq 'ARRAY') {
+ if (grep(/^\Q$intdom\E$/,@{$replication->{'noreqcerts'}})) {
+ $redirect = 0;
+ } else {
+ $redirect = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return $redirect;
+}
+
1;
Index: loncom/Lond.pm
diff -u loncom/Lond.pm:1.8 loncom/Lond.pm:1.9
--- loncom/Lond.pm:1.8 Fri May 22 21:14:59 2015
+++ loncom/Lond.pm Mon Jul 25 19:49:45 2016
@@ -1,6 +1,6 @@
# The LearningOnline Network
#
-# $Id: Lond.pm,v 1.8 2015/05/22 21:14:59 raeburn Exp $
+# $Id: Lond.pm,v 1.9 2016/07/25 19:49:45 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -37,6 +37,7 @@
use LONCAPA;
use Apache::lonnet;
use GDBM_File;
+use Crypt::OpenSSL::X509;
sub dump_with_regexp {
@@ -782,6 +783,85 @@
return $qresult;
}
+sub server_certs {
+ my ($perlvar) = @_;
+ my %pemfiles = (
+ key => 'lonnetPrivateKey',
+ host => 'lonnetCertificate',
+ hostname => 'lonnetHostnameCertificate',
+ ca => 'lonnetCertificateAuthority',
+ );
+ my (%md5hash,%info);
+ if (ref($perlvar) eq 'HASH') {
+ my $certsdir = $perlvar->{'lonCertificateDirectory'};
+ if (-d $certsdir) {
+ foreach my $key (keys(%pemfiles)) {
+ if ($perlvar->{$pemfiles{$key}}) {
+ my $file = $certsdir.'/'.$perlvar->{$pemfiles{$key}};
+ if (-e $file) {
+ if ($key eq 'key') {
+ if (open(PIPE,"openssl rsa -noout -in $file -check |")) {
+ my $check = <PIPE>;
+ close(PIPE);
+ chomp($check);
+ $info{$key}{'status'} = $check;
+ }
+ if (open(PIPE,"openssl rsa -noout -modulus -in $file | openssl md5 |")) {
+ $md5hash{$key} = <PIPE>;
+ close(PIPE);
+ }
+ } else {
+ if ($key eq 'ca') {
+ if (open(PIPE,"openssl verify -CAfile $file $file |")) {
+ my $check = <PIPE>;
+ close(PIPE);
+ chomp($check);
+ if ($check eq "$file: OK") {
+ $info{$key}{'status'} = 'ok';
+ } else {
+ $check =~ s/^\Q$file\E\:?\s*//;
+ $info{$key}{'status'} = $check;
+ }
+ }
+ } else {
+ if (open(PIPE,"openssl x509 -noout -modulus -in $file | openssl md5 |")) {
+ $md5hash{$key} = <PIPE>;
+ close(PIPE);
+ }
+ }
+ my $x509 = Crypt::OpenSSL::X509->new_from_file($file);
+ my @items = split(/,\s+/,$x509->subject());
+ foreach my $item (@items) {
+ my ($name,$value) = split(/=/,$item);
+ if ($name eq 'CN') {
+ $info{$key}{'cn'} = $value;
+ }
+ }
+ $info{$key}{'start'} = $x509->notBefore();
+ $info{$key}{'end'} = $x509->notAfter();
+ $info{$key}{'alg'} = $x509->sig_alg_name();
+ $info{$key}{'size'} = $x509->bit_length();
+ $info{$key}{'email'} = $x509->email();
+ }
+ }
+ }
+ }
+ }
+ }
+ foreach my $key ('host','hostname') {
+ if ($md5hash{$key}) {
+ if ($md5hash{$key} eq $md5hash{'key'}) {
+ $info{$key}{'status'} = 'ok';
+ }
+ }
+ }
+ my $result;
+ foreach my $key (keys(%info)) {
+ $result .= &escape($key).'='.&Apache::lonnet::freeze_escape($info{$key}).'&';
+ }
+ $result =~ s/\&$//;
+ return $result;
+}
1;
Index: loncom/lond
diff -u loncom/lond:1.522 loncom/lond:1.523
--- loncom/lond:1.522 Mon May 30 03:16:38 2016
+++ loncom/lond Mon Jul 25 19:49:45 2016
@@ -2,7 +2,7 @@
# The LearningOnline Network
# lond "LON Daemon" Server (port "LOND" 5663)
#
-# $Id: lond,v 1.522 2016/05/30 03:16:38 raeburn Exp $
+# $Id: lond,v 1.523 2016/07/25 19:49:45 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -41,7 +41,7 @@
#use Apache::File;
use POSIX;
use Crypt::IDEA;
-use LWP::UserAgent();
+use HTTP::Request;
use Digest::MD5 qw(md5_hex);
use GDBM_File;
use Authen::Krb5;
@@ -58,13 +58,14 @@
use Crypt::Eksblowfish::Bcrypt;
use Digest::SHA;
use Encode;
+use LONCAPA::LWPReq;
my $DEBUG = 0; # Non zero to enable debug log entries.
my $status='';
my $lastlog='';
-my $VERSION='$Revision: 1.522 $'; #' stupid emacs
+my $VERSION='$Revision: 1.523 $'; #' stupid emacs
my $remoteVERSION;
my $currenthostid="default";
my $currentdomainid;
@@ -667,10 +668,8 @@
$clientprotocol = 'http' if ($clientprotocol ne 'https');
my $url = '/adm/'.$filename;
$url =~ s{_}{/};
- my $ua=new LWP::UserAgent;
- $ua->timeout(60);
my $request=new HTTP::Request('GET',"$clientprotocol://$clienthost$url");
- my $response=$ua->request($request);
+ my $response = LONCAPA::LWPReq::makerequest($clientname,$request,'',\%perlvar,60,0);
if ($response->is_error()) {
&logthis('<font color="red"> Pushfile: unable to install '
.$tablefile." - error attempting to pull data. </font>");
@@ -1797,6 +1796,16 @@
}
®ister_handler("serverdistarch", \&server_distarch_handler, 0, 1, 0);
+sub server_certs_handler {
+ my ($cmd,$tail,$client) = @_;
+ my $userinput = "$cmd:$tail";
+ my $result;
+ my $result = &LONCAPA::Lond::server_certs(\%perlvar);
+ &Reply($client,\$result,$userinput);
+ return;
+}
+®ister_handler("servercerts", \&server_certs_handler, 0, 1, 0);
+
# Process a reinit request. Reinit requests that either
# lonc or lond be reinitialized so that an updated
# host.tab or domain.tab can be processed.
@@ -2331,9 +2340,8 @@
# FIXME: this should use the LWP mechanism, not internal alarms.
alarm(1200);
{
- my $ua=new LWP::UserAgent;
my $request=new HTTP::Request('GET',"$remoteurl");
- $response=$ua->request($request,$transname);
+ $response=&LONCAPA::LWPReq::makerequest($clientname,$request,$transname,\%perlvar,1200,0,1);
}
alarm(0);
if ($response->is_error()) {
@@ -2346,9 +2354,8 @@
# FIXME: isn't there an internal LWP mechanism for this?
alarm(120);
{
- my $ua=new LWP::UserAgent;
my $mrequest=new HTTP::Request('GET',$remoteurl.'.meta');
- my $mresponse=$ua->request($mrequest,$fname.'.meta');
+ my $mresponse = &LONCAPA::LWPReq::makerequest($clientname,$mrequest,$fname.'.meta',\%perlvar,120,0,1);
if ($mresponse->is_error()) {
unlink($fname.'.meta');
}
@@ -2423,11 +2430,15 @@
my $remoteurl=$clientprotocol.'://'.$clienthost.'/userfiles/'.$fname;
my $response;
Debug("Remote URL : $remoteurl Transfername $transname Destname: $destname");
- alarm(120);
+ alarm(1200);
{
- my $ua=new LWP::UserAgent;
my $request=new HTTP::Request('GET',"$remoteurl");
- $response=$ua->request($request,$transname);
+ my $verifycert = 1;
+ my @machine_ids = &Apache::lonnet::current_machine_ids();
+ if (grep(/^\Q$clientname\E$/, at machine_ids)) {
+ $verifycert = 0;
+ }
+ $response = &LONCAPA::LWPReq::makerequest($clientname,$request,$transname,\%perlvar,1200,$verifycert);
}
alarm(0);
if ($response->is_error()) {
Index: loncom/lontrans.pm
diff -u loncom/lontrans.pm:1.14 loncom/lontrans.pm:1.15
--- loncom/lontrans.pm:1.14 Fri Oct 21 16:03:06 2011
+++ loncom/lontrans.pm Mon Jul 25 19:49:45 2016
@@ -1,7 +1,7 @@
# The LearningOnline Network
# URL translation for User Files
#
-# $Id: lontrans.pm,v 1.14 2011/10/21 16:03:06 www Exp $
+# $Id: lontrans.pm,v 1.15 2016/07/25 19:49:45 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -29,16 +29,32 @@
package Apache::lontrans;
use strict;
-use Apache::Constants qw(:common :remotehost);
+use Apache::Constants qw(:common :remotehost REDIRECT);
use Apache::lonnet();
use Apache::File();
-use LONCAPA;
-
+use LONCAPA qw(:DEFAULT :match);
sub handler {
my $r = shift;
# FIXME line remove when mod_perl fixes BUG#4948
$r->notes->set('error-notes' => '');
+ if ($r->uri=~m{^/raw/}) {
+ my $host = $r->headers_in->get('Host');
+ if ($host) {
+ unless ($host =~ /^internal\-/) {
+ my $c = $r->connection;
+ if (ref($c)) {
+ my $remote_ip = $c->remote_ip;
+ my $lonhost = $r->dir_config('lonHostID');
+ if (&redirect_raw($remote_ip,$lonhost)) {
+ my $location = 'https://internal-'.$host.$r->uri;
+ $r->headers_out->set(Location => $location);
+ return REDIRECT;
+ }
+ }
+ }
+ }
+ }
if ($r->uri=~m|^(/raw)?/uploaded/|) {
my $fn = $r->uri();
$fn=~s/^\/raw//;
@@ -52,8 +68,59 @@
$r->filename(&propath($udom,$uname).
'/userfiles/'.(join('/', at ufile)));
}
- } else { return DECLINED; }
- return OK;
+ return OK;
+ } else {
+ return DECLINED;
+ }
+}
+
+sub redirect_raw {
+ my ($remote_ip,$lonhost) = @_;
+ my @remhostids = &Apache::lonnet::get_hosts_from_ip($remote_ip);
+ my $redirect;
+ while (@remhostids) {
+ my $try_server = pop(@remhostids);
+ my $remhostname = &Apache::lonnet::hostname($try_server);
+ if ($remhostname) {
+ my $remoterev = &Apache::lonnet::get_server_loncaparev(undef,$try_server);
+ my ($remmajor,$remminor) = ($remoterev =~ /^(\d+)\.(\d+)/);
+ if (($remmajor > 2) || (($remmajor == 2) && $remminor >= 12)) {
+ my $internet_names = &Apache::lonnet::get_internet_names($try_server);
+ if (ref($internet_names) eq 'ARRAY') {
+ my $intdom = &Apache::lonnet::internet_dom($lonhost);
+ unless (grep(/^\Q$intdom\E$/,@{$internet_names})) {
+ my $lonhostname = &Apache::lonnet::hostname($lonhost);
+ my $serverhomeID = &Apache::lonnet::get_server_homeID($lonhostname);
+ my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($serverhomedom);
+ my $replication = $domdefaults{'replication'};
+ if (ref($replication) eq 'HASH') {
+ my $remhomeID = &Apache::lonnet::get_server_homeID($remhostname);
+ my $remhomedom = &Apache::lonnet::host_domain($remhomeID);
+ my $remprimary = &Apache::lonnet::domain($remhomedom,'primary');
+ my $remintdom = &Apache::lonnet::internet_dom($remprimary);
+ if (ref($replication->{'certreq'}) eq 'ARRAY') {
+ if (grep(/^\Q$remintdom\E$/,@{$replication->{'certreq'}})) {
+ $redirect = 1;
+ } else {
+ $redirect = 0;
+ }
+ }
+ if (ref($replication->{'nocertreq'}) eq 'ARRAY') {
+ if (grep(/^\Q$remintdom\E$/,@{$replication->{'nocertreq'}})) {
+ $redirect = 0;
+ } else {
+ $redirect = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ last;
+ }
+ }
+ return $redirect;
}
1;
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.247 loncom/loncapa_apache.conf:1.248
--- loncom/loncapa_apache.conf:1.247 Fri Jul 1 20:00:07 2016
+++ loncom/loncapa_apache.conf Mon Jul 25 19:49:45 2016
@@ -2,7 +2,7 @@
## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
##
-# $Id: loncapa_apache.conf,v 1.247 2016/07/01 20:00:07 raeburn Exp $
+# $Id: loncapa_apache.conf,v 1.248 2016/07/25 19:49:45 raeburn Exp $
#
# LON-CAPA Section (extensions to httpd.conf daemon configuration)
@@ -1763,6 +1763,7 @@
PerlSetVar lonnetCertificateAuthority loncapaCA.pem
PerlSetVar lonnetCertificate lonhostcert.pem
+PerlSetVar lonnetHostnameCertificate lonhostnamecert.pem
#
# To generate the request for a certificate, and to negotiate the
Index: loncom/cgi/lonauthcgi.pm
diff -u loncom/cgi/lonauthcgi.pm:1.14 loncom/cgi/lonauthcgi.pm:1.15
--- loncom/cgi/lonauthcgi.pm:1.14 Mon May 4 15:43:57 2015
+++ loncom/cgi/lonauthcgi.pm Mon Jul 25 19:50:01 2016
@@ -1,7 +1,7 @@
#
# LON-CAPA authorization for cgi-bin scripts
#
-# $Id: lonauthcgi.pm,v 1.14 2015/05/04 15:43:57 raeburn Exp $
+# $Id: lonauthcgi.pm,v 1.15 2016/07/25 19:50:01 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -383,6 +383,7 @@
'checksums' => 'LON-CAPA Module Checking',
'diskusage' => 'Course/Community Disk Usage',
'clusterstatus' => 'Domain status',
+ 'certstatus' => 'LON-CAPA SSL Certificates Status',
'metadata_keywords' => 'Display Metadata Keywords',
'metadata_harvest' => 'Harvest Metadata Searches',
'takeoffline' => 'Offline - replace Log-in page',
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.274 loncom/interface/domainprefs.pm:1.275
--- loncom/interface/domainprefs.pm:1.274 Sun Jul 24 14:34:59 2016
+++ loncom/interface/domainprefs.pm Mon Jul 25 19:50:30 2016
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.274 2016/07/24 14:34:59 raeburn Exp $
+# $Id: domainprefs.pm,v 1.275 2016/07/25 19:50:30 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -169,6 +169,7 @@
use LONCAPA qw(:DEFAULT :match);
use LONCAPA::Enrollment;
use LONCAPA::lonauthcgi();
+use LONCAPA::SSL;
use File::Copy;
use Locale::Language;
use DateTime::TimeZone;
@@ -217,13 +218,13 @@
'serverstatuses','requestcourses','helpsettings',
'coursedefaults','usersessions','loadbalancing',
'requestauthor','selfenrollment','inststatus',
- 'ltitools'],$dom);
+ 'ltitools','ssl'],$dom);
my @prefs_order = ('rolecolors','login','defaults','quotas','autoenroll',
'autoupdate','autocreate','directorysrch','contacts',
'usercreation','selfcreation','usermodification','scantron',
'requestcourses','requestauthor','coursecategories',
'serverstatuses','helpsettings','coursedefaults',
- 'ltitools','selfenrollment','usersessions');
+ 'ltitools','selfenrollment','usersessions','ssl');
my %existing;
if (ref($domconfig{'loadbalancing'}) eq 'HASH') {
%existing = %{$domconfig{'loadbalancing'}};
@@ -482,7 +483,18 @@
print => \&print_ltitools,
modify => \&modify_ltitools,
},
-
+ 'ssl' =>
+ {text => 'LON-CAPA Network (SSL)',
+ help => 'Domain_Configuration_Network_SSL',
+ header => [{col1 => 'Server',
+ col2 => 'Certificate Status'},
+ {col1 => 'Connections to other servers',
+ col2 => 'Rules'},
+ {col1 => "Replicating domain's published content",
+ col2 => 'Rules'}],
+ print => \&print_ssl,
+ modify => \&modify_ssl,
+ },
);
if (keys(%servers) > 1) {
$prefs{'login'} = { text => 'Log-in page options',
@@ -658,6 +670,8 @@
$output = &modify_loadbalancing($dom,%domconfig);
} elsif ($action eq 'ltitools') {
$output = &modify_ltitools($r,$dom,$action,$lastactref,%domconfig);
+ } elsif ($action eq 'ssl') {
+ $output = &modify_ssl($dom,$lastactref,%domconfig);
}
return $output;
}
@@ -704,7 +718,7 @@
$rowtotal ++;
if (($action eq 'autoupdate') || ($action eq 'usercreation') || ($action eq 'selfcreation') ||
($action eq 'usermodification') || ($action eq 'defaults') || ($action eq 'coursedefaults') ||
- ($action eq 'selfenrollment') || ($action eq 'usersessions')) {
+ ($action eq 'selfenrollment') || ($action eq 'usersessions') || ($action eq 'ssl')) {
$output .= $item->{'print'}->('top',$dom,$settings,\$rowtotal);
} elsif ($action eq 'coursecategories') {
$output .= $item->{'print'}->('top',$dom,$item,$settings,\$rowtotal);
@@ -734,7 +748,8 @@
$rowtotal ++;
if (($action eq 'autoupdate') || ($action eq 'usercreation') ||
($action eq 'selfcreation') || ($action eq 'selfenrollment') ||
- ($action eq 'usersessions') || ($action eq 'coursecategories')) {
+ ($action eq 'usersessions') || ($action eq 'coursecategories') ||
+ ($action eq 'ssl')) {
if ($action eq 'coursecategories') {
$output .= &print_coursecategories('middle',$dom,$item,$settings,\$rowtotal);
$colspan = ' colspan="2"';
@@ -3795,8 +3810,8 @@
sub print_usersessions {
my ($position,$dom,$settings,$rowtotal) = @_;
my ($css_class,$datatable,%checked,%choices);
- my (%by_ip,%by_location, at intdoms);
- &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
+ my (%by_ip,%by_location, at intdoms, at instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
my @alldoms = &Apache::lonnet::all_domains();
my %serverhomes = %Apache::lonnet::serverhomeIDs;
@@ -3934,10 +3949,178 @@
return $datatable;
}
+sub print_ssl {
+ my ($position,$dom,$settings,$rowtotal) = @_;
+ my ($css_class,$datatable);
+ my $lonhost = '';
+ my $itemcount = 1;
+ if ($position eq 'top') {
+ my %domservers = &Apache::lonnet::get_servers($dom);
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td colspan="2">'.
+ &LONCAPA::SSL::print_certstatus(\%domservers,'web','domprefs').
+ '</td></tr>';
+ $itemcount ++;
+ } else {
+ my %titles = &ssl_titles();
+ my (%by_ip,%by_location, at intdoms, at instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+ my @alldoms = &Apache::lonnet::all_domains();
+ my %serverhomes = %Apache::lonnet::serverhomeIDs;
+ my @domservers = &Apache::lonnet::get_servers($dom);
+ my %servers = &Apache::lonnet::internet_dom_servers($dom);
+ my %altids = &id_for_thisdom(%servers);
+ if ($position eq 'middle') {
+ foreach my $type ('dom','intdom','other') {
+ my %checked;
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'><td>'.$titles{$type}.'</td>'.
+ '<td class="LC_right_item">';
+ my $skip;
+ if ($type eq 'dom') {
+ unless (keys(%servers) > 1) {
+ $datatable .= &mt('Nothing to set here, as there are no other servers/VMs');
+ $skip = 1;
+ }
+ }
+ if ($type eq 'intdom') {
+ unless (@instdoms > 1) {
+ $datatable .= &mt('Nothing to set here, as there are no other domains for this institution');
+ $skip = 1;
+ }
+ } elsif ($type eq 'other') {
+ if (keys(%by_location) == 0) {
+ $datatable .= &mt('Nothing to set here, as there are no other institutions');
+ $skip = 1;
+ }
+ }
+ unless ($skip) {
+ $checked{'yes'} = ' checked="checked"';
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{'connect'}) eq 'HASH') {
+ if ($settings->{'connect'}->{$type} =~ /^(no|req)$/) {
+ $checked{$1} = $checked{'yes'};
+ delete($checked{'yes'});
+ }
+ }
+ }
+ foreach my $option ('no','yes','req') {
+ $datatable .= '<span class="LC_nobreak"><label>'.
+ '<input type="radio" name="connect_'.$type.'" '.
+ 'value="'.$option.'"'.$checked{$option}.' />'.$titles{$option}.
+ '</label></span>'.(' 'x2);
+ }
+ }
+ $datatable .= '</td></tr>';
+ $itemcount ++;
+ }
+ } else {
+ my $numinrow = 5;
+ my $prefix = 'replication';
+ my @types = ('certreq','nocertreq');
+ my (%current,%checkedon,%checkedoff);
+ my @locations = sort(keys(%by_location));
+ foreach my $type (@types) {
+ $checkedon{$type} = '';
+ $checkedoff{$type} = ' checked="checked"';
+ }
+ if (ref($settings) eq 'HASH') {
+ if (ref($settings->{$prefix}) eq 'HASH') {
+ foreach my $key (keys(%{$settings->{$prefix}})) {
+ $current{$key} = $settings->{$prefix}{$key};
+ if (ref($current{$key}) eq 'ARRAY') {
+ $checkedon{$key} = ' checked="checked"';
+ $checkedoff{$key} = '';
+ }
+ }
+ }
+ }
+ if (@locations > 0) {
+ foreach my $type (@types) {
+ $css_class = $itemcount%2?' class="LC_odd_row"':'';
+ $datatable .= '<tr'.$css_class.'>
+ <td><span class="LC_nobreak LC_right_item">'.$titles{$type}.'</span><br />
+ <span class="LC_nobreak">
+ <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedoff{$type}.' value="0" />'.&mt('Not in use').'</label>
+ <label><input type="radio" name="'.$prefix.'_'.$type.'_inuse" '.$checkedon{$type}.' value="1" />'.&mt('In use').'</label></span></td><td>
+ <div><input type="button" value="'.&mt('check all').'" '.
+ 'onclick="javascript:checkAll(document.display.'.$prefix.'_'.$type.')"'.
+ ' />'.(' 'x2)."\n".
+ '<input type="button" value="'.&mt('uncheck all').'" '.
+ 'onclick="javascript:uncheckAll(document.display.'.$prefix.'_'.$type.')" />'.
+ "\n".
+ '</div><div><table>';
+ my $rem;
+ for (my $i=0; $i<@locations; $i++) {
+ my ($showloc,$value,$checkedtype);
+ if (ref($by_location{$locations[$i]}) eq 'ARRAY') {
+ my $ip = $by_location{$locations[$i]}->[0];
+ if (ref($by_ip{$ip}) eq 'ARRAY') {
+ $value = join(':',@{$by_ip{$ip}});
+ $showloc = join(', ',@{$by_ip{$ip}});
+ if (ref($current{$type}) eq 'ARRAY') {
+ foreach my $loc (@{$by_ip{$ip}}) {
+ if (grep(/^\Q$loc\E$/,@{$current{$type}})) {
+ $checkedtype = ' checked="checked"';
+ last;
+ }
+ }
+ }
+ }
+ }
+ $rem = $i%($numinrow);
+ if ($rem == 0) {
+ if ($i > 0) {
+ $datatable .= '</tr>';
+ }
+ $datatable .= '<tr>';
+ }
+ $datatable .= '<td class="LC_left_item">'.
+ '<span class="LC_nobreak"><label>'.
+ '<input type="checkbox" name="'.$prefix.'_'.$type.
+ '" value="'.$value.'"'.$checkedtype.' />'.$showloc.
+ '</label></span></td>';
+ }
+ $rem = @locations%($numinrow);
+ my $colsleft = $numinrow - $rem;
+ if ($colsleft > 1 ) {
+ $datatable .= '<td colspan="'.$colsleft.'" class="LC_left_item">'.
+ ' </td>';
+ } elsif ($colsleft == 1) {
+ $datatable .= '<td class="LC_left_item"> </td>';
+ }
+ $datatable .= '</tr></table></td></tr>';
+ $itemcount ++;
+ }
+ } else {
+ $datatable .= '<tr'.$css_class.'><td>'.&mt('Nothing to set here, as there are no other institutions').'</td></tr>';
+ $itemcount ++;
+ }
+ }
+ }
+ $$rowtotal += $itemcount;
+ return $datatable;
+}
+
+sub ssl_titles {
+ return &Apache::lonlocal::texthash (
+ dom => 'LON-CAPA servers/VMs from same domain',
+ intdom => 'LON-CAPA servers/VMs from same "internet" domain',
+ other => 'External LON-CAPA servers/VMs',
+ connect => 'Connections to other servers',
+ replication => 'Replicating content to other institutions',
+ certreq => 'Client certificate required, but specific domains exempt',
+ nocertreq => 'No client certificate required, except for specific domains',
+ no => 'SSL not used',
+ yes => 'SSL Optional (used if available)',
+ req => 'SSL Required',
+ );
+}
+
sub build_location_hashes {
- my ($intdoms,$by_ip,$by_location) = @_;
+ my ($intdoms,$by_ip,$by_location,$instdoms) = @_;
return unless((ref($intdoms) eq 'ARRAY') && (ref($by_ip) eq 'HASH') &&
- (ref($by_location) eq 'HASH'));
+ (ref($by_location) eq 'HASH') && (ref($instdoms) eq 'ARRAY'));
my %iphost = &Apache::lonnet::get_iphost();
my $primary_id = &Apache::lonnet::domain($env{'request.role.domain'},'primary');
my $primary_ip = &Apache::lonnet::get_host_ip($primary_id);
@@ -3954,7 +4137,13 @@
foreach my $id (@{$iphost{$ip}}) {
my $location = &Apache::lonnet::internet_dom($id);
if ($location) {
- next if (grep(/^\Q$location\E$/,@{$intdoms}));
+ if (grep(/^\Q$location\E$/,@{$intdoms})) {
+ my $dom = &Apache::lonnet::host_domain($id);
+ unless (grep(/^\Q$dom\E/,@{$instdoms})) {
+ push(@{$instdoms},$dom);
+ }
+ next;
+ }
if (ref($by_ip->{$ip}) eq 'ARRAY') {
unless(grep(/^\Q$location\E$/,@{$by_ip->{$ip}})) {
push(@{$by_ip->{$ip}},$location);
@@ -5872,9 +6061,9 @@
sub serverstatus_pages {
return ('userstatus','lonstatus','loncron','server-status','codeversions',
- 'checksums','clusterstatus','metadata_keywords','metadata_harvest',
- 'takeoffline','takeonline','showenv','toggledebug','ping','domconf',
- 'uniquecodes','diskusage','coursecatalog');
+ 'checksums','clusterstatus','certstatus','metadata_keywords',
+ 'metadata_harvest','takeoffline','takeonline','showenv','toggledebug',
+ 'ping','domconf','uniquecodes','diskusage','coursecatalog');
}
sub defaults_javascript {
@@ -12040,8 +12229,8 @@
);
my @prefixes = ('remote','hosted','spares');
my @lcversions = &Apache::lonnet::all_loncaparevs();
- my (%by_ip,%by_location, at intdoms);
- &build_location_hashes(\@intdoms,\%by_ip,\%by_location);
+ my (%by_ip,%by_location, at intdoms, at instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
my @locations = sort(keys(%by_location));
my (%defaultshash,%changes);
foreach my $prefix (@prefixes) {
@@ -12355,6 +12544,171 @@
return $resulttext;
}
+sub modify_ssl {
+ my ($dom,$lastactref,%domconfig) = @_;
+ my (%by_ip,%by_location, at intdoms, at instdoms);
+ &build_location_hashes(\@intdoms,\%by_ip,\%by_location,\@instdoms);
+ my @locations = sort(keys(%by_location));
+ my %servers = &Apache::lonnet::internet_dom_servers($dom);
+ my (%defaultshash,%changes);
+ my $action = 'ssl';
+ my @prefixes = ('connect','replication');
+ foreach my $prefix (@prefixes) {
+ $defaultshash{$action}{$prefix} = {};
+ }
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($dom,1);
+ my $resulttext;
+ my %iphost = &Apache::lonnet::get_iphost();
+ my @reptypes = ('certreq','nocertreq');
+ my @connecttypes = ('dom','intdom','other');
+ my %types = (
+ connect => \@connecttypes,
+ replication => \@reptypes,
+ );
+ my $action = 'ssl';
+ foreach my $prefix (sort(keys(%types))) {
+ foreach my $type (@{$types{$prefix}}) {
+ if ($prefix eq 'connect') {
+ my $value = 'yes';
+ if ($env{'form.'.$prefix.'_'.$type} =~ /^(no|req)$/) {
+ $value = $env{'form.'.$prefix.'_'.$type};
+ }
+ if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
+ if ($domconfig{$action}{$prefix}{$type} ne '') {
+ if ($value ne $domconfig{$action}{$prefix}{$type}) {
+ $changes{$prefix}{$type} = 1;
+ }
+ $defaultshash{$action}{$prefix}{$type} = $value;
+ } else {
+ $defaultshash{$action}{$prefix}{$type} = $value;
+ $changes{$prefix}{$type} = 1;
+ }
+ } else {
+ $defaultshash{$action}{$prefix}{$type} = $value;
+ $changes{$prefix}{$type} = 1;
+ }
+ if (($type eq 'dom') && (keys(%servers) == 1)) {
+ delete($changes{$prefix}{$type});
+ } elsif (($type eq 'intdom') && (@instdoms == 1)) {
+ delete($changes{$prefix}{$type});
+ } elsif (($type eq 'other') && (keys(%by_location) == 0)) {
+ delete($changes{$prefix}{$type});
+ }
+ } elsif ($prefix eq 'replication') {
+ if (@locations > 0) {
+ my $inuse = $env{'form.'.$prefix.'_'.$type.'_inuse'};
+ my @vals = &Apache::loncommon::get_env_multiple('form.'.$prefix.'_'.$type);
+ my @okvals;
+ foreach my $val (@vals) {
+ if ($val =~ /:/) {
+ my @items = split(/:/,$val);
+ foreach my $item (@items) {
+ if (ref($by_location{$item}) eq 'ARRAY') {
+ push(@okvals,$item);
+ }
+ }
+ } else {
+ if (ref($by_location{$val}) eq 'ARRAY') {
+ push(@okvals,$val);
+ }
+ }
+ }
+ @okvals = sort(@okvals);
+ if (ref($domconfig{$action}) eq 'HASH') {
+ if (ref($domconfig{$action}{$prefix}) eq 'HASH') {
+ if (ref($domconfig{$action}{$prefix}{$type}) eq 'ARRAY') {
+ if ($inuse == 0) {
+ $changes{$prefix}{$type} = 1;
+ } else {
+ $defaultshash{$action}{$prefix}{$type} = \@okvals;
+ my @changed = &Apache::loncommon::compare_arrays($domconfig{$action}{$prefix}{$type},$defaultshash{$action}{$prefix}{$type});
+ if (@changed > 0) {
+ $changes{$prefix}{$type} = 1;
+ }
+ }
+ } else {
+ if ($inuse == 1) {
+ $defaultshash{$action}{$prefix}{$type} = \@okvals;
+ $changes{$prefix}{$type} = 1;
+ }
+ }
+ } else {
+ if ($inuse == 1) {
+ $defaultshash{$action}{$prefix}{$type} = \@okvals;
+ $changes{$prefix}{$type} = 1;
+ }
+ }
+ } else {
+ if ($inuse == 1) {
+ $defaultshash{$action}{$prefix}{$type} = \@okvals;
+ $changes{$prefix}{$type} = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ my $nochgmsg = &mt('No changes made to LON-CAPA SSL settings');
+ if (keys(%changes) > 0) {
+ my $putresult = &Apache::lonnet::put_dom('configuration',\%defaultshash,
+ $dom);
+ if ($putresult eq 'ok') {
+ if (ref($defaultshash{$action}) eq 'HASH') {
+ if (ref($defaultshash{$action}{'replication'}) eq 'HASH') {
+ $domdefaults{'replication'} = $defaultshash{$action}{'replication'};
+ }
+ if (ref($defaultshash{$action}{'connect'}) eq 'HASH') {
+ $domdefaults{'connect'} = $domconfig{$action}{'connect'};
+ }
+ }
+ my $cachetime = 24*60*60;
+ &Apache::lonnet::do_cache_new('domdefaults',$dom,\%domdefaults,$cachetime);
+ if (ref($lastactref) eq 'HASH') {
+ $lastactref->{'domdefaults'} = 1;
+ }
+ if (keys(%changes) > 0) {
+ my %titles = &ssl_titles();
+ $resulttext = &mt('Changes made:').'<ul>';
+ foreach my $prefix (@prefixes) {
+ if (ref($changes{$prefix}) eq 'HASH') {
+ $resulttext .= '<li>'.$titles{$prefix}.'<ul>';
+ foreach my $type (@{$types{$prefix}}) {
+ if (defined($changes{$prefix}{$type})) {
+ my $newvalue;
+ if (ref($defaultshash{$action}) eq 'HASH') {
+ if (ref($defaultshash{$action}{$prefix})) {
+ if ($prefix eq 'connect') {
+ $newvalue = $titles{$defaultshash{$action}{$prefix}{$type}};
+ } elsif (ref($defaultshash{$action}{$prefix}{$type}) eq 'ARRAY') {
+ if (@{$defaultshash{$action}{$prefix}{$type}} > 0) {
+ $newvalue = join(', ',@{$defaultshash{$action}{$prefix}{$type}});
+ }
+ }
+ }
+ if ($newvalue eq '') {
+ $resulttext .= '<li>'.&mt('[_1] set to: none',$titles{$type}).'</li>';
+ } else {
+ $resulttext .= '<li>'.&mt('[_1] set to: [_2].',$titles{$type},$newvalue).'</li>';
+ }
+ }
+ }
+ }
+ $resulttext .= '</ul>';
+ }
+ }
+ } else {
+ $resulttext = $nochgmsg;
+ }
+ } else {
+ $resulttext = '<span class="LC_error">'.
+ &mt('An error occurred: [_1]',$putresult).'</span>';
+ }
+ } else {
+ $resulttext = $nochgmsg;
+ }
+ return $resulttext;
+}
+
sub modify_loadbalancing {
my ($dom,%domconfig) = @_;
my $primary_id = &Apache::lonnet::domain($dom,'primary');
Index: loncom/interface/domainstatus.pm
diff -u loncom/interface/domainstatus.pm:1.7 loncom/interface/domainstatus.pm:1.8
--- loncom/interface/domainstatus.pm:1.7 Mon Mar 17 02:36:56 2014
+++ loncom/interface/domainstatus.pm Mon Jul 25 19:50:30 2016
@@ -2,7 +2,7 @@
# Generate a menu page containing links to server status pages accessible
# to user.
#
-# $Id: domainstatus.pm,v 1.7 2014/03/17 02:36:56 raeburn Exp $
+# $Id: domainstatus.pm,v 1.8 2016/07/25 19:50:30 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -145,6 +145,15 @@
linktitle => $titles->{'clusterstatus'},
},
{
+ linktext => $linknames->{'certstatus'},
+ icon => '',
+ alttext => '',
+ #help => 'Domain_Coordination_Apache_Status',
+ url => '/cgi-bin/loncertstatus.pl',
+ permission => $candisplay->{'certstatus'},
+ linktitle => $titles->{'certstatus'},
+ },
+ {
linktext => $linknames->{'codeversions'},
icon => '',
alttext => '',
@@ -249,6 +258,7 @@
'lonstatus' => 'Connection Status',
'server-status' => 'Apache Server Status',
'clusterstatus' => 'Domain Status',
+ 'certstatus' => 'LON-CAPA SSL Certificates Status',
'codeversions' => 'LON-CAPA Modules',
'checksums' => 'Check for LON-CAPA Module changes',
'diskusage' => 'Display quotas and usage for Course/Community Content',
Index: loncom/interface/lonconfigsettings.pm
diff -u loncom/interface/lonconfigsettings.pm:1.31 loncom/interface/lonconfigsettings.pm:1.32
--- loncom/interface/lonconfigsettings.pm:1.31 Tue Jun 9 21:22:56 2015
+++ loncom/interface/lonconfigsettings.pm Mon Jul 25 19:50:30 2016
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: lonconfigsettings.pm,v 1.31 2015/06/09 21:22:56 damieng Exp $
+# $Id: lonconfigsettings.pm,v 1.32 2016/07/25 19:50:30 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -338,7 +338,7 @@
if ((ref($prefs_order) eq 'ARRAY') && (ref($prefs) eq 'HASH') && (ref($values) eq 'HASH')) {
if (@actions > 0) {
my $rowsum = 0;
- my (%output,%rowtotal, at items);
+ my (%output,%rowtotal, at items,$got_check_uncheck);
foreach my $item (@{$prefs_order}) {
if (grep(/^\Q$item\E$/, at actions)) {
push(@items,$item);
@@ -347,12 +347,15 @@
if (ref($values) eq 'HASH') {
$settings = $values->{$item};
}
- if ($item eq 'usersessions') {
- $r->print('<script type="text/javascript">'."\n".
- '// <![CDATA['."\n".
- &Apache::loncommon::check_uncheck_jscript()."\n".
- '// ]]>'."\n".
- '</script>'."\n");
+ if (($item eq 'usersessions') || ($item eq 'ssl')) {
+ unless ($got_check_uncheck) {
+ $r->print('<script type="text/javascript">'."\n".
+ '// <![CDATA['."\n".
+ &Apache::loncommon::check_uncheck_jscript()."\n".
+ '// ]]>'."\n".
+ '</script>'."\n");
+ $got_check_uncheck = 1;
+ }
} elsif ($item eq 'selfcreation') {
if (ref($values) eq 'HASH') {
$settings = $values->{'usercreation'};
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1314 loncom/lonnet/perl/lonnet.pm:1.1315
--- loncom/lonnet/perl/lonnet.pm:1.1314 Sun Jul 24 14:35:29 2016
+++ loncom/lonnet/perl/lonnet.pm Mon Jul 25 19:50:44 2016
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1314 2016/07/24 14:35:29 raeburn Exp $
+# $Id: lonnet.pm,v 1.1315 2016/07/25 19:50:44 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -229,6 +229,46 @@
return;
}
+sub get_servercerts_info {
+ my ($lonhost,$context) = @_;
+ my ($rep,$uselocal);
+ if (grep { $_ eq $lonhost } ¤t_machine_ids()) {
+ $uselocal = 1;
+ }
+ if (($context ne 'cgi') || $uselocal) {
+ my $distro = (split(/\:/,&get_server_distarch($lonhost)))[0];
+ if ($distro =~ /^(?:centos|redhat|scientific)(\d+)$/) {
+ if ($1 < 6) {
+ $uselocal = 0;
+ }
+ }
+ }
+ if ($uselocal) {
+ $rep = LONCAPA::Lond::server_certs(\%perlvar);
+ } else {
+ $rep=&reply('servercerts',$lonhost);
+ }
+ my ($result,%returnhash);
+ if (defined($lonhost)) {
+ if (!defined(&hostname($lonhost))) {
+ return;
+ }
+ }
+ if (($rep=~/^(refused|rejected|error)/) || ($rep eq 'con_lost') ||
+ ($rep eq 'unknown_cmd')) {
+ $result = $rep;
+ } else {
+ $result = 'ok';
+ my @pairs=split(/\&/,$rep);
+ foreach my $item (@pairs) {
+ my ($key,$value)=split(/=/,$item,2);
+ my $what = &unescape($key);
+ $returnhash{$what}=&thaw_unescape($value);
+ }
+ }
+ return ($result,\%returnhash);
+}
+
sub get_server_loncaparev {
my ($dom,$lonhost,$ignore_cache,$caller) = @_;
if (defined($lonhost)) {
@@ -2202,7 +2242,7 @@
'requestcourses','inststatus',
'coursedefaults','usersessions',
'requestauthor','selfenrollment',
- 'coursecategories','autoenroll'],$domain);
+ 'coursecategories','ssl','autoenroll'],$domain);
my @coursetypes = ('official','unofficial','community','textbook','placement');
if (ref($domconfig{'defaults'}) eq 'HASH') {
$domdefaults{'lang_def'} = $domconfig{'defaults'}{'lang_def'};
@@ -2328,6 +2368,14 @@
$domdefaults{'catunauth'} = $domconfig{'coursecategories'}{'unauth'};
}
}
+ if (ref($domconfig{'ssl'}) eq 'HASH') {
+ if (ref($domconfig{'ssl'}{'replication'}) eq 'HASH') {
+ $domdefaults{'replication'} = $domconfig{'ssl'}{'replication'};
+ }
+ if (ref($domconfig{'ssl'}{'connect'}) eq 'HASH') {
+ $domdefaults{'connect'} = $domconfig{'ssl'}{'connect'};
+ }
+ }
if (ref($domconfig{'autoenroll'}) eq 'HASH') {
$domdefaults{'autofailsafe'} = $domconfig{'autoenroll'}{'autofailsafe'};
}
Index: loncom/cgi/loncertstatus.pl
+++ loncom/cgi/loncertstatus.pl
#!/usr/bin/perl
$|=1;
# Displays status of LON-CAPA SSL certificates in /home/httpd/lonCerts
# on domain's servers.
#
# $Id: loncertstatus.pl,v 1.1 2016/07/25 19:50:01 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
use strict;
use lib '/home/httpd/lib/perl/';
use Apache::lonlocal();
use Apache::lonhtmlcommon;
use LONCAPA::Configuration();
use LONCAPA::loncgi();
use LONCAPA::lonauthcgi();
use LONCAPA::SSL();
my $perlvar=&LONCAPA::Configuration::read_conf('loncapa.conf');
my $lonhost;
if (ref($perlvar) eq 'HASH') {
my @reqd = qw(lonnetPrivateKey lonnetCertificate lonnetHostnameCertificate
lonnetCertificateAuthority lonCertificateDirectory);
$lonhost = $perlvar->{'lonHostID'};
foreach my $key (keys(%{$perlvar})) {
unless (grep(/^\Q$key\E$/, at reqd)) {
delete($perlvar->{$key});
}
}
}
print &LONCAPA::loncgi::cgi_header('text/html',1);
&main($lonhost);
sub main {
my ($lonhost) = @_;
my $machine_dom = &Apache::lonnet::host_domain($lonhost);
if (&LONCAPA::lonauthcgi::check_ipbased_access('certstatus')) {
&LONCAPA::loncgi::check_cookie_and_load_env();
} else {
if (!&LONCAPA::loncgi::check_cookie_and_load_env()) {
&Apache::lonlocal::get_language_handle();
print(&LONCAPA::loncgi::missing_cookie_msg());
return;
}
if (!&LONCAPA::lonauthcgi::can_view('certstatus')) {
&Apache::lonlocal::get_language_handle();
print(&LONCAPA::lonauthcgi::unauthorized_msg('certstatus'));
return;
}
}
my %domservers = &Apache::lonnet::get_servers($machine_dom);
&Apache::lonlocal::get_language_handle();
&Apache::lonhtmlcommon::add_breadcrumb(
{href=>"/cgi-bin/loncertstatus.pl",
text=>"LON-CAPA Certificate Status"});
print &Apache::loncommon::start_page('LON-CAPA SSL Certificates Status').
&Apache::lonhtmlcommon::breadcrumbs('SSL Certificates');
print &LONCAPA::SSL::print_certstatus(\%domservers,'web','cgi');
print &Apache::loncommon::end_page();
return;
}
Index: loncom/configuration/SSL.pm
+++ loncom/configuration/SSL.pm
# The LearningOnline Network with CAPA
# Checksum installed LON-CAPA modules and some configuration files
#
# $Id: SSL.pm,v 1.1 2016/07/25 19:50:16 raeburn Exp $
#
# The LearningOnline Network with CAPA
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
package LONCAPA::SSL;
use strict;
use lib '/home/httpd/lib/perl/';
use Apache::lonlocal();
use Apache::lonnet();
use Apache::loncommon();
use Apache::lonhtmlcommon();
use LONCAPA;
sub print_certstatus {
my ($servers,$target,$context) = @_;
return unless (ref($servers) eq 'HASH');
my $message;
my %lt = &Apache::lonlocal::texthash (
'file' => 'File',
'avai' => 'Available',
'yes' => 'Yes',
'no' => 'No',
'cn' => 'Common Name',
'start' => 'Valid From',
'end' => 'Valid To',
'alg' => 'Signature Algorithm',
'size' => 'Public Key Size',
'status' => 'Status',
'email' => 'E-mail',
'key' => 'Private Key',
'host' => 'Connections Certificate',
'hostname' => 'Replication Certificate',
'ca' => 'LON-CAPA CA Certificate',
);
my @files = qw(key host hostname ca);
my @fields = qw(status cn start end alg size email);
foreach my $server (sort(keys(%{$servers}))) {
my $hostname = &Apache::lonnet::hostname($server);
my ($result,$hashref) = &Apache::lonnet::get_servercerts_info($server,$context);
if ($result eq 'ok' && ref($hashref) eq 'HASH') {
if ($target eq 'web') {
$message .= "<fieldset><legend>$hostname ($server)</legend>".
&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row()."\n";
foreach my $item ('file','avai', at fields) {
$message .= '<th>'.$lt{$item}.'</th>';
}
$message .= &Apache::loncommon::end_data_table_header_row()."\n";
} else {
$message .= $server.':';
}
foreach my $file (@files) {
if ($target eq 'web') {
$message .= &Apache::loncommon::start_data_table_row()."\n".
'<td>'.$lt{$file}.'</td>';
} else {
$message .= $file.'=';
}
if (ref($hashref->{$file}) eq 'HASH') {
if ($target eq 'web') {
$message .= '<td>'.$lt{'yes'}.'</td>';
} else {
$message .= $lt{'yes'}.',';
}
foreach my $item (@fields) {
my $display = $hashref->{$file}->{$item};
if ($target eq 'web') {
if ($item eq 'status') {
$display = &Apache::lonhtmlcommon::confirm_success($display);
}
$message .= "<td>$display</td>";
} else {
$message .= "$display,";
}
}
} else {
if ($target eq 'web') {
$message .= '<td>'.$lt{'no'}.'<td>';
} else {
$message .= $lt{'no'}.',';
}
foreach my $item (@fields) {
if ($target eq 'web') {
$message .= '<td> </td>';
} else {
$message .= ',';
}
}
if ($target eq 'web') {
$message .= &Apache::loncommon::end_data_table_row()."\n";
} else {
$message =~ s/,$//;
$message .= '&';
}
}
}
if ($target eq 'web') {
$message .= &Apache::loncommon::end_data_table().'</fieldset>';
} else {
$message =~ s/\&$//;
}
$message .= "\n";
} else {
if ($target eq 'web') {
$message .= "$server error\n";
} else {
$message .= "$server error\n";
}
}
}
return $message;
}
1;
More information about the LON-CAPA-cvs
mailing list