From: Harlan Stenn Date: Wed, 13 Dec 2017 03:15:09 +0000 (-0800) Subject: [Bug 3405] update-leap.in: general cleanup, HTTPS support. Paul McMath. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39b949d4c4c5a266eb6740f4d424117a9842de41;p=thirdparty%2Fntp.git [Bug 3405] update-leap.in: general cleanup, HTTPS support. Paul McMath. bk: 5a309b3daepGVTxjAjOhRAKLiznY1g --- diff --git a/ChangeLog b/ChangeLog index 9bfe76719..5a4f576e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ - raised receive buffer size to 1200 * [Bug 3408] refclock_jjy.c: Avoid a wrong report of the coverity static analysis tool. +* [Bug 3405] update-leap.in: general cleanup, HTTPS support. Paul McMath. * [Bug 3399] NTP: linker error in 4.2.8p10 during Linux cross-compilation - initial patch by timeflies@mail2tor.com * [Bug 3398] tests fail with core dump diff --git a/NEWS b/NEWS index 0e95f428d..5cd1db36e 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,10 @@ -- + +update-leap needs: + Net::SSLeay + IO::Socket::SSL + +-- NTP 4.2.8p10 (Harlan Stenn , 2017/03/21) Focus: Security, Bug fixes, enhancements. diff --git a/scripts/update-leap/update-leap.in b/scripts/update-leap/update-leap.in index bd7ed1805..dd666046d 100755 --- a/scripts/update-leap/update-leap.in +++ b/scripts/update-leap/update-leap.in @@ -1,427 +1,473 @@ #! @PATH_PERL@ -w -# Copyright (C) 2015 Network Time Foundation +# Copyright (C) 2015, 2017 Network Time Foundation # Author: Harlan Stenn - +# +# General cleanup and https support: Paul McMath +# # Original shell version: # Copyright (C) 2014 Timothe Litt litt at acm dot org - +# # This script may be freely copied, used and modified providing that # this notice and the copyright statement are included in all copies # and derivative works. No warranty is offered, and use is entirely at # your own risk. Bugfixes and improvements would be appreciated by the # author. +######## BEGIN ######### use strict; +# Core modules use Digest::SHA qw(sha1_hex); +use File::Basename; use File::Copy qw(move); -use File::Fetch; +use File::Temp qw(tempfile); use Getopt::Long qw(:config auto_help no_ignore_case bundling); -use Sys::Syslog; +use Sys::Syslog qw(:standard :macros); -my $VERSION="1.003"; +# External modules +use HTTP::Tiny 0.056; +use Net::SSLeay 1.49; +use IO::Socket::SSL 1.56; -# leap-seconds file manager/updater +my $VERSION = '1.004'; -# ########## Default configuration ########## -# +my $RUN_DIR = '/tmp'; +my $RUN_UID = 0; +my $TMP_FILE; +my $TMP_FH; +my $FILE_MODE = 0644; + +######## DEFAULT CONFIGURATION ########## +# LEAP FILE SRC URIS +# HTTPS - (default) +# https://www.ietf.org/timezones/data/leap-seconds +# HTTP - No TLS/SSL - (not recommended) +# http://www.ietf.org/timezones/data/leap-seconds.list -my $CRONJOB = $ENV{'CRONJOB'}; -$CRONJOB = "" unless defined($CRONJOB); -my $LOGGER; -my $QUIET = ""; -my $VERBOSE = ""; - -# Where to get the file -# Choices: -# https://www.ietf.org/timezones/data/leap-seconds.list -# ftp://time.nist.gov/pub/leap-seconds.list -my $LEAPSRC="https://www.ietf.org/timezones/data/leap-seconds.list"; +my $LEAPSRC = 'https://www.ietf.org/timezones/data/leap-seconds.list'; my $LEAPFILE; # How many times to try to download new file -my $MAXTRIES=6; -my $INTERVAL=10; +my $MAXTRIES = 6; +my $INTERVAL = 10; -# Where to find ntp config file -my $NTPCONF="/etc/ntp.conf"; +my $NTPCONF='/etc/ntp.conf'; # How long (in days) before expiration to get updated file -my $PREFETCH="60"; +my $PREFETCH = 60; +my $EXPIRES; +my $FORCE; + +# Output Flags +my $QUIET; +my $DEBUG; +my $SYSLOG; +my $TOTERM; +my $LOGFAC = 'LOG_USER'; + +######### PARSE/SET OPTIONS ######### +my %SSL_OPTS; +my %SSL_ATTRS = ( + verify_SSL => 1, + SSL_options => \%SSL_OPTS, +); -# How to restart NTP - older NTP: service ntpd? try-restart | condrestart -# Recent NTP checks for new file daily, so there's nothing to do -my $RESTART=""; +our(%opt); -my $EXPIRES; -my $FORCE = ""; +GetOptions(\%opt, + 'C=s', + 'D=s', + 'e:60', + 'F', + 'f=s', + 'h', + 'i:10', + 'L=s', + 'l=s', + 'q', + 'r:6', + 's', + 't', + 'u=s', + 'v', + ); -# Where to put temporary copy before it's validated -my $TMPFILE="/tmp/leap-seconds.$$.tmp"; +$LOGFAC = $opt{l} if defined $opt{l}; +$LEAPSRC = $opt{u} if defined $opt{u}; +$LEAPFILE = $opt{L} if defined $opt{L}; +$PREFETCH = $opt{e} if defined $opt{e}; +$NTPCONF = $opt{f} if defined $opt{f}; +$MAXTRIES = $opt{r} if defined $opt{r}; +$INTERVAL = $opt{i} if defined $opt{i}; + +$FORCE = 1 if defined $opt{F}; +$DEBUG = 1 if defined $opt{v}; +$QUIET = 1 if defined $opt{q}; +$SYSLOG = 1 if defined $opt{s}; +$TOTERM = 1 if defined $opt{t}; + +$SSL_OPTS{SSL_ca_file} = $opt{C} if (defined($opt{C})); +$SSL_OPTS{SSL_ca_path} = $opt{D} if (defined($opt{D})); + +############### +## START MAIN +############### +my $PROG = basename($0); + +# Logging - Default is to use syslog(3) if STDOUT isn't +# connected to a tty. +if ($SYSLOG || !-t STDOUT) { + $SYSLOG = 1; + openlog($PROG, 'pid', $LOGFAC); +} +else { + $TOTERM = 1; +} -# Syslog facility -my $LOGFAC="daemon"; +$SIG{INT} = \&signal_catcher; +$SIG{TERM} = \&signal_catcher; +$SIG{QUIT} = \&signal_catcher; -# ########################################### +# Take some security precautions +close STDIN; -=item update-leap +if ($< != $RUN_UID) { + log_fatal(LOG_ERR, 'User ' . getpwuid($<) . " (UID $<) tried to run $PROG"); +} -Usage: $0 [options] [leapfile] +chdir $RUN_DIR || log_fatal("Failed to change dir to $RUN_DIR"); -Verifies and if necessary, updates leap-second definition file +# Show help +if (defined $opt{h}) { + show_help(); + exit 0; +} -All arguments are optional: Default (or current value) shown: - -s Specify the URL of the master copy to download - $LEAPSRC - -d Specify the filename on the local system - $LEAPFILE - -e Specify how long (in days) before expiration the file is to be - refreshed. Note that larger values imply more frequent refreshes. - "$PREFETCH" - -f Specify location of ntp.conf (used to make sure leapfile directive is - present and to default leapfile) - $NTPCONF - -F Force update even if current file is OK and not close to expiring. - -r Specify number of times to retry on get failure - $MAXTRIES - -i Specify number of minutes between retries - $INTERVAL - -l Use syslog for output (Implied if CRONJOB is set) - -L Don't use syslog for output - -P Specify the syslog facility for logging - $LOGFAC - -t Name of temporary file used in validation - $TMPFILE - -q Only report errors to stdout - -v Verbose output +if ($QUIET && $DEBUG) { + log_fatal(LOG_ERR, '-q and -d options mutually exclusive'); +} -The following options are not (yet) implemented in the perl version: - -4 Use only IPv4 - -6 Use only IPv6 - -c Command to restart NTP after installing a new file - - ntpd checks file daily - -p 4|6 - Prefer IPv4 or IPv6 (as specified) addresses, but use either - -z Specify path for utilities - $PATHLIST - -Z Only use system path +if ($LEAPFILE && $NTPCONF) { + log_fatal(LOG_ERR, '-L and -f options mutually exclusive'); +} -$0 will validate the file currently on the local system +# Parse ntp.conf for path to leapfile if not set by user +if (! $LEAPFILE) { -Ordinarily, the file is found using the "leapfile" directive in $NTPCONF. -However, an alternate location can be specified on the command line. + open my $LF, '<', $NTPCONF || log_fatal(LOG_ERR, "Can't open <$NTPCONF>: $!"); -If the file does not exist, is not valid, has expired, or is expiring soon, -a new copy will be downloaded. If the new copy validates, it is installed and -NTP is (optionally) restarted. + while (<$LF>) { + chomp; + $LEAPFILE = $1 if /^ *leapfile\s+"(\S+)"/; + } + close $LF; -If the current file is acceptable, no download or restart occurs. + if (! $LEAPFILE) { + log_fatal(LOG_ERR, "No leapfile directive in $NTPCONF; leapfile location not known"); + } +} --c can also be used to invoke another script to perform administrative -functions, e.g. to copy the file to other local systems. +-s $LEAPFILE || logger(LOG_DEBUG, "Leapfile $LEAPFILE is empty"); -This can be run as a cron job. As the file is rarely updated, and leap -seconds are announced at least one month in advance (usually longer), it -need not be run more frequently than about once every three weeks. +# Download new file if: +# 1. file doesn't exist +# 2. invoked w/ force flag (-F) +# 3. current file isn't valid +# 4. current file expired or expires soon -For cron-friendly behavior, define CRONJOB=1 in the crontab. +if ( !-e $LEAPFILE || $FORCE || ! verifySHA($LEAPFILE) || + ( $EXPIRES lt ( $PREFETCH * 86400 + time() ) )) { -Version $VERSION -=cut + for (my $try = 1; $try <= $MAXTRIES; $try++) { + logger(LOG_DEBUG, "Attempting download from $LEAPSRC, try $try.."); -# Default: Use syslog for logging if running under cron + ($TMP_FH, $TMP_FILE) = tempfile(UNLINK => 1, SUFFIX => '.list'); -my $SYSLOG = $CRONJOB; + if (retrieve_file($TMP_FH)) { -# Parse options + if ( verifySHA($TMP_FILE) ) { + move_file($TMP_FILE, $LEAPFILE); + chmod $FILE_MODE, $LEAPFILE; + logger(LOG_INFO, "Installed new $LEAPFILE from $LEAPSRC"); + } + else { + logger(LOG_ERR, "Downloaded file $TMP_FILE rejected -- saved for diagnosis"); + move_file($TMP_FILE, 'leap-seconds.list_corrupt'); + exit 1; + } + # Fall through + exit 0; + } -our(%opt); + # Failure + logger(LOG_INFO, "Download failed. Waiting $INTERVAL minutes before retrying..."); + sleep $INTERVAL * 60 ; + } -GetOptions(\%opt, - 'c=s', - 'e:60', - 'F', - 'f=s', - 'i:10', - 'L', - 'l', - 'P=s', - 'q', - 'r:6', - 's=s', - 't=s', - 'v' - ); + # Failed and out of retries + log_fatal(LOG_ERR, "Download from $LEAPSRC failed after $MAXTRIES attempts"); +} + +logger(LOG_INFO, "Not time to replace $LEAPFILE"); + +exit 0; -$LOGFAC=$opt{P} if (defined($opt{P})); -$LEAPSRC=$opt{s} if (defined($opt{s})); -$PREFETCH=$opt{e} if (defined($opt{e})); -$NTPCONF=$opt{f} if (defined($opt{f})); -$FORCE="Y" if (defined($opt{F})); -$RESTART=$opt{c} if (defined($opt{c})); -$MAXTRIES=$opt{r} if (defined($opt{r})); -$INTERVAL=$opt{i} if (defined($opt{i})); -$TMPFILE=$opt{t} if (defined($opt{t})); -$SYSLOG="Y" if (defined($opt{l})); -$SYSLOG="" if (defined($opt{L})); -$QUIET="Y" if (defined($opt{q})); -$VERBOSE="Y" if (defined($opt{v})); +######## SUB ROUTINES ######### +sub move_file { -# export PATH="$PATHLIST$PATH" + (my $src, my $dst) = @_; -# Handle logging + if ( move($src, $dst) ) { + logger(LOG_DEBUG, "Moved $src to $dst"); + } + else { + log_fatal(LOG_ERR, "Moving $src to $dst failed: $!"); + } +} -openlog($0, 'pid', $LOGFAC); +# Removes temp file if terminating signal recv'd +sub signal_catcher { + my $signame = shift; + + close $TMP_FH; + unlink $TMP_FILE; + log_fatal(LOG_INFO, "Recv'd SIG${signame}. Terminating."); +} + +sub log_fatal { + my ($p, $msg) = @_; + logger($p, $msg); + exit 1; +} sub logger { - my ($priority, $message) = @_; - - # "priority" "message" - # - # Stdout unless syslog specified or logger isn't available - # - if ($SYSLOG eq "" or $LOGGER eq "") { - if ($QUIET ne "" and ( $priority eq "info" or $priority eq "notice" or $priority eq "debug" ) ) { - return 0 + my ($p, $msg) = @_; + + # Suppress LOG_DEBUG msgs unless $DEBUG set + return if (!$DEBUG && $p eq LOG_DEBUG); + + # Suppress all but LOG_ERR msgs if $QUIET set + return if ($QUIET && $p ne LOG_ERR); + + if ($TOTERM) { + if ($p eq LOG_ERR) { # errors should go to STDERR + print STDERR "$msg\n"; + } + else { + print STDOUT "$msg\n"; } - printf "%s: $message\n", uc $priority; - return 0; } - # Also log to stdout if cron job && notice or higher - if (($CRONJOB ne "" and ($priority ne "info" ) and ($priority ne "debug" )) || ($VERBOSE ne "")) { - # Log to stderr as well - print STDERR "$0: $priority: $message\n"; + if ($SYSLOG) { + syslog($p, $msg) } - syslog($priority, $message); } -# Verify interval -# INTERVAL=$(( $INTERVAL *1 )) +################################# +# Connect to server and retrieve file +# +# Since we make as many as $MAXTRIES attempts to connect to the remote +# server to download the file, the network socket should be closed after +# each attempt, rather than let it be reused (because it may be in some +# unknown state). +# +# HTTP::Tiny doesn't export a method to explicitly close a connected +# socket, therefore, we instantiate the lexically scoped object in a +# function; when the function returns, the http object goes out of +# scope and is destroyed, closing the socket. +sub retrieve_file { + + my $fh = shift; + my $http; + + if ($LEAPSRC =~ /^https\S+/) { + $http = HTTP::Tiny->new(%SSL_ATTRS); + (my $ok, my $why) = $http->can_ssl; + log_fatal(LOG_ERR, "TLS/SSL config error: $why") if ! $ok; + } + else { + $http = HTTP::Tiny->new(); + } + + my $reply = $http->get($LEAPSRC); + + if ($reply->{success}) { + logger(LOG_DEBUG, "Download of $LEAPSRC succeeded"); + print $fh $reply->{content} || + log_fatal(LOG_ERR, "Couldn't write new file contents to temp file: $!"); + close $fh; + return 1; + } + else { + close $fh; + return 0; + } +} +######################## # Validate a leap-seconds file checksum # -# File format: (full description in files) -# # marks comments, except: -# #$ number : the NTP date of the last update -# #@ number : the NTP date that the file expires -# Date (seconds since 1900) leaps : leaps is the # of seconds to add for times >= Date +# File format: (full description in file) +# Pound sign (#) marks comments, EXCEPT: +# #$ number : the NTP date of the last update +# #@ number : the NTP date that the file expires +# #h hex hex hex hex hex : the SHA-1 checksum of the data & dates, +# excluding whitespace w/o leading zeroes +# +# Date (seconds since 1900) leaps : leaps is the # of seconds to add +# for times >= Date # Date lines have comments. -# #h hex hex hex hex hex is the SHA-1 checksum of the data & dates, excluding whitespace w/o leading zeroes # # Returns: -# 0 File is valid -# 1 Invalid Checksum -# 2 Expired +# 0 Invalid Checksum/Expired +# 1 File is valid sub verifySHA { - my ($file, $verbose) = @_; - my $raw = ""; - my $data = ""; + my $file = shift; + my $fh; + my $data; my $FSHA; + open $fh, '<', $file || log_fatal(LOG_ERR, "Can't open $file: $!"); + # Remove comments, except those that are markers for last update, # expires and hash - - unless (open(LF, $file)) { - warn "Can't open <$file>: $!\n"; - print "Will try and create that file.\n"; - return 1; - }; - while () { + while (<$fh>) { if (/^#\$/) { - $raw .= $_; - s/^..//; - $data .= $_; + s/^..//; + $data .= $_; } elsif (/^#\@/) { - $raw .= $_; - s/^..//; - $data .= $_; - s/\s+//g; - $EXPIRES = $_ - 2208988800; + s/^..//; + $data .= $_; + s/\s+//g; + $EXPIRES = $_ - 2208988800; } elsif (/^#h\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)/) { - chomp; - $raw .= $_; - $FSHA = sprintf("%08s%08s%08s%08s%08s", $1, $2, $3, $4, $5); + chomp; + $FSHA = sprintf("%08s%08s%08s%08s%08s", $1, $2, $3, $4, $5); } elsif (/^#/) { - # ignore it + # ignore it } elsif (/^\d/) { - s/#.*$//; - $raw .= $_; - $data .= $_; - } else { - chomp; - print "Unexpected line: <$_>\n"; + s/#.*$//; + $data .= $_; + } + else { + chomp; + print "Unexpected line: <$_>\n"; } } - close LF; + close $fh; + + if ( $EXPIRES < time() ) { + logger(LOG_DEBUG, 'File expired on ' . gmtime($EXPIRES)); + return 0; + } + + if (! $FSHA) { + logger(LOG_NOTICE, "no checksum record found in file"); + return 0; + } # Remove all white space $data =~ s/\s//g; # Compute the SHA hash of the data, removing the marker and filename # Computed in binary mode, which shouldn't matter since whitespace has been removed - my $DSHA = sha1_hex($data); - # Extract the file's hash. Restore any leading zeroes in hash segments. - - if ( ( "$FSHA" ne "" ) && ( $FSHA eq $DSHA ) ) { - if ( $verbose ne "" ) { - logger("info", "Checksum of $file validated"); - } - } else { - logger("error", "Checksum of $file is invalid:"); - $FSHA="(no checksum record found in file)" - if ( $FSHA eq ""); - logger("error", "EXPECTED: $FSHA"); - logger("error", "COMPUTED: $DSHA"); - return 1; - } - - # Check the expiration date, converting NTP epoch to Unix epoch used by date - - if ( $EXPIRES < time() ) { - logger("notice", "File expired on " . gmtime($EXPIRES)); - return 2; + if ($FSHA eq $DSHA) { + logger(LOG_DEBUG, "Checksum of $file validated"); + return 1; + } + else { + logger(LOG_NOTICE, "Checksum of $file is invalid EXPECTED: $FSHA COMPUTED: $DSHA"); + return 0; } - return 0; } -# Verify ntp.conf +sub show_help { +print <: $!\n"; -while () { - chomp; - if (/^ *leapfile\s+"(\S+)"/) { - $LEAPFILE = $1; - } -} -close LF; +Verifies and if necessary, updates leap-second definition file --s $LEAPFILE || warn "$NTPCONF specifies $LEAPFILE as a leapfile, which is empty.\n"; +All arguments are optional: Default (or current value) shown: + -C Absolute path to CA Cert (see SSL/TLS Considerations) + -D Path to a CAdir (see SSL/TLS Considerations) + -e Specify how long (in days) before expiration the file is to be + refreshed. Note that larger values imply more frequent refreshes. + $PREFETCH + -F Force update even if current file is OK and not close to expiring. + -f Absolute path ntp.conf file (default /etc/ntp.conf) + $NTPCONF + -h show help + -i Specify number of minutes between retries + $INTERVAL + -L Absolute path to leapfile on the local system + (overrides value in ntp.conf) + -l Specify the syslog(3) facility for logging + $LOGFAC + -q Only report errors (cannot be used with -v) + -r Specify number of attempts to retrieve file + $MAXTRIES + -s Send output to syslog(3) - implied if STDOUT has no tty or redirected + -t Send output to terminal - implied if STDOUT attached to terminal + -u Specify the URL of the master copy to download + $LEAPSRC + -v Verbose - show debug messages (cannot be used with -q) -# Allow placing the file someplace else - testing +The following options are not (yet) implemented in the perl version: + -4 Use only IPv4 + -6 Use only IPv6 + -c Command to restart NTP after installing a new file + - ntpd checks file daily + -p 4|6 + Prefer IPv4 or IPv6 (as specified) addresses, but use either -if ( defined $ARGV[0] ) { - if ( $ARGV[0] ne $LEAPFILE ) { - logger("notice", "Requested install to $ARGV[0], but $NTPCONF specifies $LEAPFILE"); - } - $LEAPFILE = $ARGV[0]; -} +$PROG will validate the file currently on the local system. -# Verify the current file -# If it is missing, doesn't validate or expired -# Or is expiring soon -# Download a new one - -if ( $FORCE ne "" || verifySHA($LEAPFILE, $VERBOSE) || ( $EXPIRES lt ( $PREFETCH * 86400 + time() ) )) { - my $TRY = 0; - my $ff = File::Fetch->new(uri => $LEAPSRC) || die "Fetch failed.\n"; - while (1) { - ++$TRY; - logger("info", "Attempting download from $LEAPSRC, try $TRY..") - if ($VERBOSE ne ""); - my $where = $ff->fetch( to => '/tmp' ); - - if ($where) { - logger("info", "Download of $LEAPSRC succeeded"); - - if ( verifySHA($where, $VERBOSE )) { - # There is no point in retrying, as the file on the - # server is almost certainly corrupt. - - logger("warning", "Downloaded file $where rejected -- saved for diagnosis"); - exit 1; - } +Ordinarily, the leapfile is found using the 'leapfile' directive in +$NTPCONF. However, an alternate location can be specified on the +command line with the -L flag. - # While the shell script version will set correct permissions - # on temporary file, for the perl version that's harder, so - # for now at least one should run this script as the - # appropriate user. - - # REFFILE="$LEAPFILE" - # if [ ! -f $LEAPFILE ]; then - # logger "notice" "$LEAPFILE was missing, creating new copy - check permissions" - # touch $LEAPFILE - # # Can't copy permissions from old file, copy from NTPCONF instead - # REFFILE="$NTPCONF" - # fi - # chmod --reference $REFFILE $TMPFILE - # chown --reference $REFFILE $TMPFILE - # ( which selinuxenabled && selinuxenabled && which chcon ) >/dev/null 2>&1 - # if [ $? == 0 ] ; then - # chcon --reference $REFFILE $TMPFILE - # fi - - # Replace current file with validated new one - - if ( move $where, $LEAPFILE ) { - logger("notice", "Installed new $LEAPFILE from $LEAPSRC"); - } else { - logger("error", "Install $where => $LEAPFILE failed -- saved for diagnosis: $!"); - exit 1; - } +If the leapfile does not exist, is not valid, has expired, or is +expiring soon, a new copy will be downloaded. If the new copy is +valid, it is installed. - # Restart NTP (or whatever else is specified) - - if ( $RESTART ne "" ) { - if ( $VERBOSE ne "" ) { - logger("info", "Attempting restart action: $RESTART"); - } - -# XXX - #R="$( 2>&1 $RESTART )" - #if [ $? -eq 0 ]; then - # logger "notice" "Restart action succeeded" - # if [ -n "$VERBOSE" -a -n "$R" ]; then - # logger "info" "$R" - # fi - #else - # logger "error" "Restart action failed" - # if [ -n "$R" ]; then - # logger "error" "$R" - # fi - # exit 2 - #fi - } - exit 0; - } +If the current file is acceptable, no download or restart occurs. - # Failed to download. See about trying again +This can be run as a cron job. As the file is rarely updated, and +leap seconds are announced at least one month in advance (usually +longer), it need not be run more frequently than about once every +three weeks. - # rm -f $TMPFILE - if ( $TRY ge $MAXTRIES ) { - last; - } - if ( $VERBOSE ne "" ) { - logger("info", "Waiting $INTERVAL minutes before retrying..."); - } - sleep $INTERVAL * 60 ; - } +SSL/TLS Considerations +----------------------- +The perl modules can usually locate the CA certificate used to verify +the peer's identity. - # Failed and out of retries +On BSDs, the default is typically the file /etc/ssl/certs.pem. On +Linux, the location is typically a path to a CAdir - a directory of +symlinks named according to a hash of the certificates' subject names. - logger("warning", "Download from $LEAPSRC failed after $TRY attempts"); - exit 1; -} +The -C or -D options are available to pass in a location if no CA cert +is found in the default location. -print "FORCE is <$FORCE>\n"; -print "verifySHA is " . verifySHA($LEAPFILE, "") . "\n"; -print "EXPIRES <$EXPIRES> vs ". ( $PREFETCH * 86400 + time() ) . "\n"; +External Dependencies +--------------------- +The following perl modules are required: +HTTP::Tiny - version >= 0.056 +IO::Socket::SSL - version >= 1.56 +NET::SSLeay - version >= 1.49 -logger("info", "Not time to replace $LEAPFILE"); +Version: $VERSION -exit 0; +EOF +} -# EOF