[LON-CAPA-cvs] cvs: loncom / CrCA.pl
raeburn
raeburn at source.lon-capa.org
Mon Dec 31 23:43:47 EST 2018
raeburn Tue Jan 1 04:43:47 2019 EDT
Added files:
/loncom CrCA.pl
Log:
- Script to create a Certificate Authority (CA) for a LON-CAPA cluster.
-------------- next part --------------
Index: loncom/CrCA.pl
+++ loncom/CrCA.pl
#!/usr/bin/perl
use strict;
use Sys::Hostname::FQDN();
use Term::ReadKey;
use Locale::Country;
use Crypt::OpenSSL::X509;
use DateTime::Format::x509;
use File::Slurp;
use Cwd;
#
# Expected structure
#
# /lonca
# opensslca.cnf
# cacert.pem
# index.txt
# /certs
# /crl
# /private
# /requests
#
print(<<END);
****** SSL Certificate Authority *****
If you are running your own cluster of LON-CAPA nodes you will need to
create a Certificate Authority (CA) for your cluster. You will then use
the CA to sign LON-CAPA SSL certificate signing requests generated by
the nodes in your cluster.
LON-CAPA SSL Certificates can be used in two different contexts:
(a) if you configure LON-CAPA to use a secure channel for exchange of
the shared encryption key when establishing an "internal" LON-CAPA
connection between nodes in your cluster, and (b) if you configure
LON-CAPA to use client SSL certificate validation when one node replicates
content from library node(s) in your cluster.
Although a LON-CAPA cluster may contain multiple domains and/or multiple
library nodes, there will only be one LON-CAPA certificate authority (CA)
for the cluster. The CA certificate signing infrastructure need not be
housed on a LON-CAPA node; it can instead be installed on a separate
Linux instance. The instance housing the CA infrastructure needs to
have the following Linux packages installed:
openssl
perl
and the following perl modules from CPAN installed:
Term::ReadKey
Sys::Hostname::FQDN
Locale::Country
Crypt::OpenSSL::X509
DateTime::Format::x509
File::Slurp
You need to decide on a directory you wish to use to hold the
CA infrastructure. If necessary you should create a new directory.
Then move this script (CrCA.pl) to that directory, and run it with
the command: perl CrCA.pl
The script will create any required subdirectories (and files)
within that directory, if they do not already exist.
You will need to provide a password to be used for the openssl CA key
which will be stored in the /private subdirectory, and will be used
when signing certificate signing requests to create LON-CAPA certificates
for use in the cluster.
END
#Proceed?
my ($dir,$hostname,%data);
# Check if required subdirectories exist in current directory.
$dir = Cwd::getcwd();
if (-e "$dir/lonca") {
if ((!-d "$dir/lonca") && (-f "$dir/lonca")) {
print "A lonca directory is required, but there is an existing file of that name.\n".
"Please either delete the lonca file, or change to a different directory, and ".
"create the CA infrastructure there.\n";
exit;
}
} else {
mkdir("$dir/lonca",0700);
system('chown root:root '."$dir/lonca");
}
if (-d "$dir/lonca") {
foreach my $subdir ('certs','crl','private','requests') {
if (!-d "$dir/lonca/$subdir") {
if (-f "$dir/lonca/$subdir") {
print "A $subdir sub-directory is required, but there is an existing file of that name.\n".
"Please either delete or move the $subdir file, then run this script again.\n";
exit;
} else {
mkdir("$dir/lonca/$subdir",0700);
system('chown root:root '."$dir/lonca/$subdir");
}
}
}
} else {
print "A lonca directory is required, but no directory exists\n";
exit;
}
if (-e "$dir/lonca/opensslca.conf") {
# retrieve existing config file and verify that if contains the required fields.
%data = &parse_config("$dir/lonca/opensslca.conf");
my %update = &confirm_config(%data);
my %changes;
foreach my $field ('clustername','organization','email','country','state','city','days','crldays') {
if ($data{$field} ne $update{$field}) {
$changes{$field} = $update{$field};
}
}
if (keys(%changes)) {
&save_config_changes("$dir/lonca/opensslca.conf",\%changes);
}
} else {
print(<<END);
****** Certificate Authority Configuration File *****
A configuration file: $dir/lonca/opensslca.conf will be created.
The following information will be included:
Country, State/Province, City, Cluster Name, Organizational Name, E-mail address, CA certificate lifetime (days), Default certificate lifetime (days), CRL re-creation interval (days)
END
$hostname = Sys::Hostname::FQDN::fqdn();
if ($hostname eq '') {
$hostname =&get_hostname();
} else {
print "Hostname detected: $hostname. Is that correct? [Y/n]";
if (!&get_user_selection(1)) {
$hostname =&get_hostname();
}
}
my %fieldname = (
city => 'City',
state => 'State or Province',
clustername => 'Cluster name',
organization => 'Organization name',
);
my ($clustername,$organization,$country,$state,$city,$email,$cadays,$clusterhostname,$days,$crldays);
$clusterhostname = $hostname;
$country = &get_country($hostname);
print "Enter state or province name\n";
$state = &get_info($fieldname{'state'});
print "Enter city name\n";
$city = &get_info($fieldname{'city'});
$email = &get_camail();
print 'Enter a name for this LON-CAPA cluster, e.g., "Lon-CAPA learning network"'."\n".
'This name will be included as the Common Name for the CA certificate.'."\n";
$clustername = &get_info($fieldname{'clustername'});
print 'Enter the organization name for this LON-CAPA cluster, e.g., "Lon CAPA certification authority"'."\n".
'This name will be included as the Oraganization for the CA certificate.'."\n";
$organization = &get_info($fieldname{'organization'});
print "Enter the lifetime (in days) for the CA root certificate distributed to all nodes, e.g., 3650\n";
$cadays = &get_days();
print "Enter the default lifetime (in days) for each certificate created/signed by the CA for individual nodes, e.g., 3650\n";
$days = &get_days();
print "Enter the re-creation interval (in days) for the CA's certificate revocation list (CRL), e.g., 180\n";
$crldays = &get_days();
if (open(my $fh,'>',"$dir/lonca/opensslca.conf")) {
print $fh <<"END";
[ ca ]
default_ca = loncapa
[ loncapa ]
dir = $dir/lonca
certificate = $dir/lonca/cacert.pem
database = $dir/lonca/index.txt
new_certs_dir = $dir/lonca/certs
private_key = $dir/lonca/private/cakey.pem
serial = $dir/lonca/serial
default_crl_days = $crldays
default_days = $days
default_md = sha256
policy = loncapa_policy
x509_extensions = certificate_extensions
[ loncapa_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = supplied
emailAddress = supplied
organizationName = supplied
organizationalUnitName = optional
[ certificate_extensions ]
basicConstraints = CA:false
crlDistributionPoints = URI:http://$clusterhostname/adm/dns/loncapaCAcrl
[ req ]
default_bits = 2048
distinguished_name = loncapa_ca
x509_extensions = loncapa_ca_extensions
[ loncapa_ca ]
commonName = $clustername
localityName = $city
stateOrProvinceName = $state
countryName = $country
emailAddress = $email
organizationName = $organization
[ loncapa_ca_extensions ]
basicConstraints = CA:true
[ crl_ext ]
authorityKeyIdentifier=keyid:always,issuer:always
END
} else {
print 'Error: failed to wtite to '."$dir/lonca/opensslca.conf. Exiting.\n";
exit;
}
%data = &parse_config("$dir/lonca/opensslca.conf");
my %update = &confirm_config(%data);
my %changes;
foreach my $field ('clustername','organization','email','country','state','city','days','crldays') {
if ($data{$field} ne $update{$field}) {
$changes{$field} = $update{$field};
}
}
if (keys(%changes)) {
&save_config_changes("$dir/lonca/opensslca.conf",\%changes);
}
}
my $sslkeypass;
if (-e "$dir/lonca/private/cakey.pem") {
my ($keyok,$try);
print "CA key aleady exists\n";
$try = 1;
while (!$keyok && $try) {
$sslkeypass = &get_password('Enter the password for the CA key');
if ($sslkeypass ne '') {
open(PIPE,"openssl rsa -noout -in lonca/private/cakey.pem -passin pass:$sslkeypass -check |");
my $check = <PIPE>;
close(PIPE);
chomp($check);
if ($check eq 'RSA key ok') {
$keyok = 1;
last;
} else {
print "CA key check failed. Try again? [Y/n]";
if (!&get_user_selection(1)) {
$try = 0;
}
}
}
}
unless ($keyok) {
print "CA key check failed. Create a new key? [Y/n]";
if (&get_user_selection(1)) {
$sslkeypass = &get_new_sslkeypass();
# generate SSL key
unless (&make_key("$dir/lonca/private",$sslkeypass)) {
print "Failed to create CA key\n";
exit;
}
} else {
exit;
}
}
} else {
$sslkeypass = &get_new_sslkeypass();
# generate SSL key
unless (&make_key("$dir/lonca/private",$sslkeypass)) {
print "Failed to create CA key\n";
exit;
}
}
if (-e "$dir/lonca/cacert.pem") {
print "A CA certificate exists\n";
open(PIPE,"openssl pkey -in $dir/lonca/private/cakey.pem -passin pass:$sslkeypass -pubout -outform der | sha256sum |");
my $hashfromkey = <PIPE>;
close(PIPE);
chomp($hashfromkey);
open(PIPE,"openssl x509 -in $dir/lonca/cacert.pem -pubkey | openssl pkey -pubin -pubout -outform der | sha256sum |");
my $hashfromcert = <PIPE>;
close(PIPE);
chomp($hashfromcert);
if ($hashfromkey eq $hashfromcert) {
my ($now,$starttime,$endtime,$status,%cert);
my $x509 = Crypt::OpenSSL::X509->new_from_file("$dir/lonca/cacert.pem");
my @items = split(/,\s+/,$x509->subject());
foreach my $item (@items) {
my ($name,$value) = split(/=/,$item);
if ($name eq 'CN') {
$cert{'cn'} = $value;
}
}
$cert{'start'} = $x509->notBefore();
$cert{'end'} = $x509->notAfter();
$cert{'alg'} = $x509->sig_alg_name();
$cert{'size'} = $x509->bit_length();
$cert{'email'} = $x509->email();
my $dt = DateTime::Format::x509->parse_datetime($cert{'start'});
if (ref($dt)) {
$starttime = $dt->epoch;
}
$dt = DateTime::Format::x509->parse_datetime($cert{'end'});
if (ref($dt)) {
$endtime = $dt->epoch;
}
$now = time;
if (($starttime ne '') && ($endtime ne '')) {
if ($endtime <= $now) {
$status = 'previous';
print "Current CA certificate expired $cert{'end'}\n";
} elsif ($starttime > $now) {
$status = 'future';
print "Current CA certificate will be valid after $cert{'start'}\n";
} else {
$status eq 'active';
print "Current CA certificate valid until $cert{'end'}".' '.
"Signature Algorithm: $cert{'alg'}; Public Key size: $cert{'size'}\n";
}
if ($status eq 'previous') {
print 'Create a new certificate? [Y/n]';
if (&get_user_selection(1)) {
unless (&make_ca_cert("$dir/lonca/private","$dir/lonca",$sslkeypass)) {
print "Failed to create CA cert\n";
exit;
}
}
}
} else {
print "Could not determine validity of current CA certificate\n";
exit;
}
}
} else {
unless (&make_ca_cert("$dir/lonca/private","$dir/lonca",$sslkeypass)) {
print "Failed to create CA cert\n";
exit;
}
}
if (!-e "$dir/lonca/index.txt") {
File::Slurp::write_file("$dir/lonca/index.txt");
}
if (-e "$dir/lonca/index.txt") {
my $mode = 0600;
chmod $mode, "$dir/lonca/index.txt";
} else {
print "lonca/index.txt file is missing\n";
exit;
}
# echo 1000 > serial
unless (-e "$dir/lonca/crl/loncapaCAcrl.pem") {
open(PIPE,"openssl ca -gencrl -keyfile $dir/lonca/private/cakey.pem -cert $dir/lonca/cacert.pem -out $dir".
"/lonca/crl/loncapaCAcrl.pem -config $dir/lonca/opensslca.conf -passin pass:$sslkeypass |");
close(PIPE);
if (-e "$dir/lonca/crl/loncapaCAcrl.pem") {
print "Certificate Revocation List created\n";
}
}
if (-e "$dir/lonca/crl/loncapaCAcrl.pem") {
open(PIPE,"openssl crl -in $dir/lonca/crl/loncapaCAcrl.pem -inform pem -CAfile $dir/lonca/cacert.pem -noout 2>&1 |");
my $revoked = <PIPE>;
close(PIPE);
chomp($revoked);
print "Revocation certificate status: $revoked\n";
# Create a new one?
}
sub cafield_to_key {
my %mapping = (
city => 'localityName',
state => 'stateOrProvinceName',
country => 'countryName',
email => 'emailAddress',
organization => 'organizationName',
clustername => 'commonName',
);
return %mapping;
}
sub field_to_key {
my %mapping = (
days => 'default_days',
crldays => 'default_crl_days',
);
}
sub parse_config {
my ($filepath) = @_;
my (%fields,%data);
if (open(my $fh,'<',$filepath)) {
my $currsection;
while(<$fh>) {
chomp();
s/(^\s+|\s+$)//g;
if (/^\[\s*([^\s]+)\s*\]/) {
$currsection = $1;
} elsif (/^([^=]+)=([^=]+)$/) {
my ($key,$value) = ($1,$2);
$key =~ s/\s+$//;
$value =~ s/^\s+//;
if ($currsection ne '') {
$fields{$currsection}{$key} = $value;
}
}
}
close($fh);
}
if (ref($fields{'loncapa_ca'}) eq 'HASH') {
my %ca_mapping = &cafield_to_key();
foreach my $key (keys(%ca_mapping)) {
$data{$key} = $fields{'loncapa_ca'}{$ca_mapping{$key}};
}
}
if (ref($fields{'loncapa'}) eq 'HASH') {
my %mapping = &field_to_key();
foreach my $key (keys(%mapping)) {
$data{$key} = $fields{'loncapa'}{$mapping{$key}};
}
}
return %data;
}
sub save_config_changes {
my ($filepath,$updated) = @_;
return unless (ref($updated) eq 'HASH');
my %mapping = &field_to_key();
my %ca_mapping = &cafield_to_key();
my %revmapping = reverse(%mapping);
my %rev_ca_mapping = reverse(%ca_mapping);
my $lines;
if (open(my $fh,'<',$filepath)) {
my $currsection;
while(<$fh>) {
my $line = $_;
chomp();
s/(^\s+|\s+$)//g;
my $newline;
if (/^\[\s*([^\s]+)\s*\]/) {
$currsection = $1;
} elsif (/^([^=]+)=([^=]*)$/) {
my ($origkey,$origvalue) = ($1,$2);
my ($key,$value) = ($origkey,$origvalue);
$key =~ s/\s+$//;
$value =~ s/^\s+//;
if ($currsection eq 'loncapa_ca') {
if ((exists($rev_ca_mapping{$key})) && (exists($updated->{$rev_ca_mapping{$key}}))) {
if ($value eq '') {
if ($origvalue eq '') {
$origvalue = ' ';
}
$origvalue .= $updated->{$rev_ca_mapping{$key}};
} else {
$origvalue =~ s/\Q$value\E/$updated->{$rev_ca_mapping{$key}}/;
}
$newline = $origkey.'='.$origvalue."\n";
}
} elsif ($currsection eq 'loncapa') {
if ((exists($revmapping{$key})) && (exists($updated->{$revmapping{$key}}))) {
if ($value eq '') {
if ($origvalue eq '') {
$origvalue = ' ';
}
$origvalue .= $updated->{$revmapping{$key}};
} else {
$origvalue =~ s/\Q$value\E/$updated->{$revmapping{$key}}/;
}
$newline = $origkey.'='.$origvalue."\n";
}
}
}
if ($newline) {
$lines .= $newline;
} else {
$lines .= $line;
}
}
close($fh);
if (open(my $fout,'>',$filepath)) {
print $fout $lines;
close($fout);
} else {
print "Error: failed to open '$filepath' for writing\n";
}
}
return;
}
#
# get_hostname() prompts the user to provide the server's hostname.
#
# If invalid input is provided, the routine is called recursively
# until, a valid hostname is provided.
#
sub get_hostname {
my $hostname;
print 'Enter the hostname of this server, e.g., loncapa.somewhere.edu'."\n";
my $choice = <STDIN>;
chomp($choice);
$choice =~ s/(^\s+|\s+$)//g;
if ($choice eq '') {
print "Hostname you entered was either blank or contanied only white space.\n";
} elsif ($choice =~ /^[\w\.\-]+$/) {
$hostname = $choice;
} else {
print "Hostname you entered was invalid -- a hostname may only contain letters, numbers, - and .\n";
}
while ($hostname eq '') {
$hostname = &get_hostname();
}
print "\n";
return $hostname;
}
sub get_new_sslkeypass {
my $sslkeypass;
my $flag=0;
# get password for SSL key
while (!$flag) {
$sslkeypass = &make_passphrase();
if ($sslkeypass) {
$flag = 1;
} else {
print "Invalid input (a password is required for the CA key).\n";
}
}
return $sslkeypass;
}
sub make_passphrase {
my ($got_passwd,$firstpass,$secondpass,$passwd);
my $maxtries = 10;
my $trial = 0;
while ((!$got_passwd) && ($trial < $maxtries)) {
$firstpass = &get_password('Enter a password for the CA key (at least 6 characters long)');
if (length($firstpass) < 6) {
print('Password too short.'."\n".
'Please choose a password with at least six characters.'."\n".
'Please try again.'."\n");
} elsif (length($firstpass) > 30) {
print('Password too long.'."\n".
'Please choose a password with no more than thirty characters.'."\n".
'Please try again.'."\n");
} else {
my $pbad=0;
foreach (split(//,$firstpass)) {if ((ord($_)<32)||(ord($_)>126)){$pbad=1;}}
if ($pbad) {
print('Password contains invalid characters.'."\n".
'Password must consist of standard ASCII characters.'."\n".
'Please try again.'."\n");
} else {
$secondpass = &get_password('Enter password a second time');
if ($firstpass eq $secondpass) {
$got_passwd = 1;
$passwd = $firstpass;
} else {
print('Passwords did not match.'."\n".
'Please try again.'."\n");
}
}
}
$trial ++;
}
return $passwd;
}
sub get_password {
my ($prompt) = @_;
local $| = 1;
print $prompt.': ';
my $newpasswd = '';
ReadMode 'raw';
my $key;
while(ord($key = ReadKey(0)) != 10) {
if(ord($key) == 127 || ord($key) == 8) {
chop($newpasswd);
print "\b \b";
} elsif(!ord($key) < 32) {
$newpasswd .= $key;
print '*';
}
}
ReadMode 'normal';
print "\n";
return $newpasswd;
}
#
# make_key() generates CA root key
#
sub make_key {
my ($keydir,$sslkeypass) = @_;
# generate SSL key
my $created;
if (($keydir ne '') && ($sslkeypass ne '')) {
if (-f "$keydir/cakey.pem") {
my $mode = 0600;
chmod $mode, "$keydir/cakey.pem";
}
open(PIPE,"openssl genrsa -aes256 -passout pass:$sslkeypass -out $keydir/cakey.pem 2048 2>&1 |");
close(PIPE);
if (-f "$keydir/cakey.pem") {
my $mode = 0400;
chmod $mode, "$keydir/cakey.pem";
$created= 1;
}
} else {
print "Key creation failed. Missing one or more of: certificates directory, key name\n";
}
return $created;
}
#
# make_ca_cert() generates CA root certificate
#
sub make_ca_cert {
my ($keydir,$certdir,$sslkeypass) = @_;
# generate SSL cert for CA
my $created;
if ((-d $keydir) && (-d $certdir) && ($sslkeypass ne '')) {
my $cmd = "openssl req -x509 -key $keydir/cakey.pem -passin pass:$sslkeypass -new -batch -config $certdir/opensslca.conf -out $certdir/cacert.pem";
print "Calling ||$cmd||\n";
open(PIPE,"openssl req -x509 -key $keydir/cakey.pem -passin pass:$sslkeypass -new -batch -config $certdir/opensslca.conf -out $certdir/cacert.pem |");
close(PIPE);
if (-f "$certdir/cacert.pem") {
my $mode = 0600;
chmod $mode, "$certdir/cacert.pem";
# chmod $mode, "$certdir/careq.pem";
# open(PIPE,"openssl ca -create_serial -out $certdir/cacert.pem -days 3650 -keyfile $keydir/cakey.pem -selfsign -config ./openssl.cnf -infiles $certdir/careq.pem |");
# close(PIPE);
# if (-f "$certdir/cacert.pem") {
# my $mode = 0600;
# chmod $mode, "$certdir/cacert.pem";
# }
$created= 1;
}
} else {
print "Creation of CA root certificate failed. Missing one or more of: CA directory, CA key directory, or CA passphrase.\n";
}
return $created;
}
sub get_camail {
my $camail;
my $flag=0;
# get Certificate Authority E-mail
while (!$flag) {
print(<<END);
Enter e-mail address of Certificate Authority.
END
my $choice=<>;
chomp($choice);
if (($choice ne '') && ($choice =~ /^[^\@]+\@[^\@]+$/)) {
$camail=$choice;
$flag=1;
} else {
print "Invalid input (a valid email address is required).\n";
}
}
return $camail;
}
sub ssl_info {
print(<<END);
****** Information about Country, State or Province and City *****
A two-letter country code, e.g., US, CA, DE etc. as defined by ISO 3166,
is required. A state or province, and a city are also required.
This locality information is included in two SSL certificates used internally
by LON-CAPA, unless you are running standalone.
If your server will be part of either the production or development
clusters, then the certificate will need to be signed by the official
LON-CAPA Certificate Authority (CA). If you will be running your own
cluster then the cluster will need to create its own CA.
END
}
sub get_country {
my ($desiredhostname) = @_;
# get Country
my ($posscountry,$country);
if ($desiredhostname =~ /\.(edu|com|org)$/) {
$posscountry = 'us';
} else {
($posscountry) = ($desiredhostname =~ /\.(a-z){2}$/);
}
if ($posscountry) {
my $countrydesc = &Locale::Country::code2country($posscountry);
if ($countrydesc eq '') {
undef($posscountry);
}
}
my $flag=0;
while (!$flag) {
if ($posscountry) {
$posscountry = uc($posscountry);
print "Enter Two-Letter Country Code [$posscountry]:\n";
} else {
print "Enter the Two-Letter Country Code:\n";
}
my $choice=<STDIN>;
chomp($choice);
if ($choice ne '') {
if (&Locale::Country::code2country(lc($choice))) {
$country=uc($choice);
$flag=1;
} else {
print "Invalid input -- a valid two letter country code is required\n";
}
} elsif (($choice eq '') && ($posscountry ne '')) {
$country = $posscountry;
$flag = 1;
} else {
print "Invalid input -- a country code is required\n";
}
}
return $country;
}
sub get_info {
my ($typename) = @_;
my $value;
my $choice = <STDIN>;
chomp($choice);
$choice =~ s/(^\s+|\s+$)//g;
if ($choice eq '') {
print "$typename you entered was either blank or contained only white space.\n";
} else {
$value = $choice;
}
while ($value eq '') {
$value = &get_info($typename);
}
print "\n";
return $value;
}
sub get_days {
my $value;
my $choice = <STDIN>;
chomp($choice);
$choice =~ s/(^\s+|\s+$)//g;
if ($choice eq '') {
print "The value you entered was either blank or contained only white space.\n";
} elsif ($choice !~ /^\d+$/) {
print "The value you entered contained invalid characters -- you must enter just an integer.\n";
} else {
$value = $choice;
}
while ($value eq '') {
$value = &get_days();
}
print "\n";
return $value;
}
sub confirm_config {
my (%data) = @_;
my $flag = 0;
while (!$flag) {
print(<<END);
The cluster name, organization name, country, state and city will be
included in the CA certificate
1) Cluster Name: $data{'clustername'}
2) Organization Name: $data{'organization'}
3) Country: $data{'country'}
4) State or Province: $data{'state'}
5) City: $data{'city'}
6) E-mail: $data{'email'}
7) CA certificate lifetime (days): $data{'cadays'}
8) Default certificate lifetime for issued certs (days): $data{'days'}
9) CRL recreation interval (days): $data{'crldays'}
10) Everything is correct up above
Enter a choice of 1-9 to change, otherwise enter 10:
END
my $choice=<STDIN>;
chomp($choice);
if ($choice == 1) {
print(<<END);
1) Cluster Name: $data{'clustername'}
Enter new value:
END
my $choice2=<STDIN>;
chomp($choice2);
$data{'clustername'}=$choice2;
chomp($choice2);
$data{'organization'}=$choice2;
} elsif ($choice == 3) {
print(<<END);
3) Country: $data{'country'}
Enter new value (this should be a two-character code, e,g, US, CA, DE):
END
my $choice2=<STDIN>;
chomp($choice2);
$data{'country'} = uc($choice2);
} elsif ($choice == 4) {
print(<<END);
4) State or Province: $data{'state'}
Enter new value:
END
my $choice2=<>;
chomp($choice2);
$data{'state'}=$choice2;
} elsif ($choice == 5) {
print(<<END);
5) City: $data{'city'}
Enter new value:
END
my $choice2=<>;
chomp($choice2);
$data{'city'}=$choice2;
} elsif ($choice == 6) {
print(<<END);
6) E-mail: $data{'email'}
Enter new value:
END
my $choice2=<>;
chomp($choice2);
$data{'email'}=$choice2;
} elsif ($choice == 7) {
print(<<END);
7) CA Root Certificate lifetime: $data{'cadays'}
Enter new value:
END
my $choice2=<>;
chomp($choice2);
$choice2 =~ s/\D//g;
$data{'cadays'}=$choice2;
} elsif ($choice == 8) {
print(<<END);
8) Default certificate lifetime: $data{'days'}
Enter new value:
END
my $choice2=<>;
chomp($choice2);
$choice2 =~ s/\D//g;
$data{'days'}=$choice2;
} elsif ($choice == 9) {
print(<<END);
9) CRL re-creation interval: $data{'crldays'}
Enter new value:
END
my $choice2=<>;
chomp($choice2);
$choice2 =~ s/\D//g;
$data{'crldays'}=$choice2;
} elsif ($choice == 10) {
$flag=1;
foreach my $key (keys(%data)) {
$data{$key} =~ s{/}{ }g;
}
} else {
print "Invalid input.\n";
}
}
return %data;
}
sub get_user_selection {
my ($defaultrun) = @_;
my $do_action = 0;
my $choice = <STDIN>;
chomp($choice);
$choice =~ s/(^\s+|\s+$)//g;
my $yes = 'y';
if ($defaultrun) {
if (($choice eq '') || ($choice =~ /^\Q$yes\E/i)) {
$do_action = 1;
}
} else {
if ($choice =~ /^\Q$yes\E/i) {
$do_action = 1;
}
}
return $do_action;
}
More information about the LON-CAPA-cvs
mailing list