diff --git a/debian/control b/debian/control index 45ba600e..6811b489 100644 --- a/debian/control +++ b/debian/control @@ -16,8 +16,9 @@ Package: sdwdate Architecture: all Depends: sudo, logrotate, bc, ruby | ruby-interpreter, ruby-inline, ruby-dev, - ruby-all-dev, gcc, libc6-dev, python-dateutil, - python-pysocks | python-socksipy, python, tor, ${misc:Depends} + ruby-all-dev, gcc, libc6-dev, python-dateutil, python-gevent, + python-pysocks | python-socksipy, python-guimessages, python, tor, + ${misc:Depends} Recommends: vbox-disable-timesync, timesanitycheck, bootclockrandomization, timesync Suggests: sdwdate-plugin-anon-shared-con-check, diff --git a/etc/apparmor.d/usr.lib.sdwdate.url_to_unixtime b/etc/apparmor.d/usr.lib.sdwdate.url_to_unixtime new file mode 100644 index 00000000..aba3034a --- /dev/null +++ b/etc/apparmor.d/usr.lib.sdwdate.url_to_unixtime @@ -0,0 +1,10 @@ +# Last Modified: Mon Sep 14 11:33:39 2015 +#include + +/usr/lib/sdwdate/url_to_unixtime { + #include + #include + + /usr/lib/sdwdate/url_to_unixtime r, + +} diff --git a/etc/sdwdate.d/30_default.conf b/etc/sdwdate.d/30_default.conf new file mode 100644 index 00000000..81413411 --- /dev/null +++ b/etc/sdwdate.d/30_default.conf @@ -0,0 +1,134 @@ +## This file is part of Whonix. +## Copyright (C) 2012 - 2014 Patrick Schleizer +## See the file COPYING for copying conditions. + +## Please use "/etc/sdwdate.d/50_user.conf" for your custom +## configuration, which will override the defaults found here. +## When sdwdate is updated, this file may be overwritten. + +## Proxy settings for non anonymous distributions. +## Uncomment for standard tor configuration (no stream isolation). +#PROXY_IP=127.0.0.1 +#PROXY_PORT=9050 + +## Allowed percentage of url failures common to every pool. +## If sdwdate frequently stops with "Maximum allowed number of failures" error, +## create a file "/etc/sdwdate.d/50_user.conf" overriding MAX_FAILURE_RATIO +## with a higher figure. +MAX_FAILURE_RATIO=0.34 + +## pool syntax +## "url.onion[:port]#comment" +## " +## url.onion[:port]#comment +## [url.onion[:port]#comment] +## [url.onion[:port]#comment] +## [...] +## " +## "url.onion[:port]#comment" +## ... + +## pool one. +## SecureDrop List +## info: +## Last updated Thu Oct 23 16:15:00 PDT 2014 +## Organization Landing Page Tor Hidden Service Address +## in use: +## https://freedom.press/securedrop/directory +## https://freedom.press/sites/default/files/securedrop_list.txt +## https://freedom.press/sites/default/files/securedrop_list.txt.asc +## https://freedom.press/sites/default/files/securedrop.asc +## removed because down: +## "bczjr6ciiblco5ti.onion#Forbes https://safesource.forbes.com bczjr6ciiblco5ti.onion" +## "l7rt5kabupal7eo7.onion#BayLeaks https://bayleaks.com l7rt5kabupal7eo7.onion" +## individual websites +SDWDATE_POOL_ONE=( + "dtsxnd3ykn32ywv6.onion#BalkanLeaks https://www.balkanleaks.eu dtsxnd3ykn32ywv6.onion" + "znig4bc5rlwyj4mz.onion#ExposeFacts https://exposefacts.org znig4bc5rlwyj4mz.onion" + "vtjkwwcq5osuo6uq.onion#Greenpeace New Zealand https://www.safesource.org.nz vtjkwwcq5osuo6uq.onion" + "33y6fjyhs3phzfjj.onion#The Guardian https://securedrop.theguardian.com 33y6fjyhs3phzfjj.onion" + "y6xjgkgwj47us5ca.onion#The Intercept https://firstlook.org/theintercept/securedrop y6xjgkgwj47us5ca.onion" + "strngbxhwyuu37a3.onion#The New Yorker https://projects.newyorker.com/strongbox strngbxhwyuu37a3.onion" + "swdi5ymnwmrqhycl.onion#NRKbeta https://nrkbeta.no/tips swdi5ymnwmrqhycl.onion" + "dqeasamlf3jld2kz.onion#Project On Gov't Oversight (POGO) https://securedrop.pogo.org dqeasamlf3jld2kz.onion" + "pubdrop4dw6rk3aq.onion#ProPublica https://securedrop.propublica.org pubdrop4dw6rk3aq.onion" + "hkjpnjbvhrxjvikd.onion#Radio24syv https://securedrop.radio24syv.dk hkjpnjbvhrxjvikd.onion" + "v6gdwmm7ed4oifvd.onion#Barton Gellman https://tcfmailvault.info v6gdwmm7ed4oifvd.onion" + "vbmwh445kf3fs2v4.onion#The Washington Post https://ssl.washingtonpost.com/securedrop vbmwh445kf3fs2v4.onion" + "poulsensqiv6ocq4.onion#Wired's Kevin Poulsen https://pressfreedomfoundation.org/about/tech/kevin-poulsen poulsensqiv6ocq4.onion" + "tigas3l7uusztiqu.onion#https://mike.tig.as tinkerer at ProPublica in New York" +) + +## pool two. +## Hosted by Thomas White List +## +## GlobalLeaks List +## info: +## https://en.wikipedia.org/wiki/GlobaLeaks#Implementations +## http://www.webcitation.org/6WBrtPlrq +## Name of organization Implementation date Category Tor Url Tor2web Url Country +## removed because down: +## Perun[23] 2012-April-7 Investigative Journalism Closed Closed Serbia +## "jeuhrnvdyr3xyqz3.onion#Internet Governance Transparency Initiative 2014-April-5 Transparency Activism jeuhrnvdyr3xyqz3.onion https://jeuhrnvdyr3xyqz3.tor2web.org Unknown" +## "ea433ils4wtprqbv.onion#EcuadorTransparente 2014-June-19 Transparency Activism ea433ils4wtprqbv.onion https://ea433ils4wtprqbv.tor2web.org/ Ecuador" +## "3qnry3qqjvc2u3c4.onion#ManxLeaks 2014-July-07 Transparency Activism 3qnry3qqjvc2u3c4.onion https://3qnry3qqjvc2u3c4.tor2web.org Isle of Man" +SDWDATE_POOL_TWO=( + [ + "atlas777hhh7mcs7.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "compass6vpxj32p3.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "globe223ezvh6bps.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "bbbbbb6qtmqg65g6.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "pppppptkftqqnfsq.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + ] + "w6csjytbrl273che.onion#Ljost[24][25] 2012-September-30 Transparency Activism w6csjytbrl273che.onion https://w6csjytbrl273che.tor2web.org/ Iceland" + "ak2uqfavwgmjrvtu.onion#MagyarLeaks[26] 2013-July-7 Investigative Journalism ak2uqfavwgmjrvtu.onion https://ak2uqfavwgmjrvtu.tor2web.org Hungary" + "yn6ocmvu4ok3k3al.onion#Publeaks [27][28] 2013-September-9 +40 National/Local Media Consortium yn6ocmvu4ok3k3al.onion https://secure.publeaks.nl Netherlands" + "acabtd4btrxjjrvr.onion#Pistajka 2013-September Anticorruption activism acabtd4btrxjjrvr.onion https://acabtd4btrxjjrvr.tor2web.org Serbia" + "5r4bjnjug3apqdii.onion#Irpileaks[29][30] 2013-October-7 Investigative Journalism 5r4bjnjug3apqdii.onion https://5r4bjnjug3apqdii.tor2web.org/ Italy" + "2dermafialks7aai.onion#Mafialeaks [31][32][33] 2013-November-5 Anti Mafia Activism 2dermafialks7aai.onion https://secure.mafialeaks.org Italy" + "ymi7h25hgp3bj63v.onion#InfodioLeaks 2014-January-28 Anticorruption Activism ymi7h25hgp3bj63v.onion https://ymi7h25hgp3bj63v.tor2web.org Venezuela" + "ppdz5djzpo3w5k2z.onion#WildLeaks [34][35][36][37][38][39] 2014-February-7 WildLife Crime Activism ppdz5djzpo3w5k2z.onion https://secure.wildleaks.org United States/Africa" + "pltloztihmfrg2sw.onion#Salzburger-Piratenpartei 2014-March-4 Activism pltloztihmfrg2sw.onion https://pltloztihmfrg2sw.tor2web.org Austria" + "ur5b2b4brz427ygh.onion#Nawaatleaks [40] 2014-March-27 Activism ur5b2b4brz427ygh.onion https://ur5b2b4brz427ygh.tor2web.org Tunisia" + "w6csjytbrl273che.onion#Filtrala [41][42] 2014-April-23 Anticorruption Activism w6csjytbrl273che.onion https://w6csjytbrl273che.tor2web.org/ Spain" + "abkjckdgoabr7bmm.onion#MediaDirect [43] 2014-May-11 Transparency Activism abkjckdgoabr7bmm.onion https://abkjckdgoabr7bmm.tor2web.org Australia" + "5r4bjnjug3apqdii.onion#ExpoLeaks[44] [45] [46] 2014-June-10 Investigative Journalism 5r4bjnjug3apqdii.onion https://5r4bjnjug3apqdii.tor2web.org/ Italy" + "bqs3dobnazs7h4u4.onion#ExtremeLeaks 2014-June-18 Investigative Journalism bqs3dobnazs7h4u4.onion https://www.extremeleaks.org/ Norway" + "fkut2p37apcg6l7f.onion#Allerta Anticorruzione[47][48] 2014-October-14 Anticorruption Activism fkut2p37apcg6l7f.onion https://alac.transparency.it Italy" + "6iolddfbfinntq2b.onion#Brussels Leaks 2014-October 24 Europe Focus Anticorruption Transparency Activism 6iolddfbfinntq2b.onion https://6iolddfbfinntq2b.tor2web.org Belgium" +) + +## pool three. +## info: +## individual websites +## riseup.net List +## https://help.riseup.net/en/tor#riseups-tor-hidden-services +## removed because down: +## "suw74isz7wqzpmgu.onion:80#https://www.wikileaks.org/wiki/WikiLeaks:Tor" +## removed because no http: +## "4cjw6cwpeaeppfqz.onion#xmpp.riseup.net: 4cjw6cwpeaeppfqz.onion (ports 5222, 5269)" +SDWDATE_POOL_THREE=( + "3g2upl4pq6kufc4m.onion#https://duck.co/forum/thread/1762/is-the-duckduckgo-hidden-service-legitimate" + "dju2peblv7upfz3q.onion#https://guardianproject.info/2014/10/16/reducing-metadata-leakage-from-software-updates/" + "msydqstlz2kzerdg.onion#https://ahmia.fi/address/msydqstlz2kzerdg" + "uj3wazyk5u4hnvtk.onion#https://thepiratebay.se/blog/238" + "bitmailendavkbec.onion#https://bitmessage.org/forum/index.php?topic=1556.0" + "wi7qkxyrdpu5cmvr.onion#Austici www.autistici.org/en/stuff/man_anon/tor.html" + "ic6au7wa3f6naxjq.onion#https://lists.gnupg.org/pipermail/gnupg-users/2014-April/049578.html" + [ + "nzh3fv6jc6jskki3.onion#help.riseup.net: nzh3fv6jc6jskki3.onion (port 443)" + "cwoiopiifrlzcuos.onion#black.riseup.net: cwoiopiifrlzcuos.onion (port 443)" + "zsolxunfmbfuq7wf.onion#imap.riseup.net: zsolxunfmbfuq7wf.onion (port 993)" + "yfm6sdhnfbulplsw.onion#labs.riseup.net: yfm6sdhnfbulplsw.onion (port 80, 443)" + "xpgylzydxykgdqyg.onion#lists.riseup.net: xpgylzydxykgdqyg.onion (port 80, 443)" + "zsolxunfmbfuq7wf.onion#mail.riseup.net: zsolxunfmbfuq7wf.onion (ports 443, 465, 587)" + "5jp7xtmox6jyoqd5.onion#pad.riseup.net: 5jp7xtmox6jyoqd5.onion (port 443) (note: only works with https://5jp7xtmox6jyoqd5.onion)" + "zsolxunfmbfuq7wf.onion#pop.riseup.net: zsolxunfmbfuq7wf.onion (port 995)" + "zsolxunfmbfuq7wf.onion#smtp.riseup.net: zsolxunfmbfuq7wf.onion (ports 465, 587)" + "j6uhdvbhz74oefxf.onion#user.riseup.net: j6uhdvbhz74oefxf.onion (port 80, 443)" + "7lvd7fa5yfbdqaii.onion#we.riseup.net: 7lvd7fa5yfbdqaii.onion (port 443)" + ] + "timaq4ygg2iegci7.onion#https://github.com/meejah/txtorcon http://txtorcon.readthedocs.org" + "344c6kbnjnljjzlz.onion#VFEmail https://www.vfemail.net" + "fncuwbiisyh6ak3i.onion#https://keybase.io/docs/command_line/tor" +) diff --git a/usr/bin/sdwdate b/usr/bin/sdwdate index bb2c1e27..9d49b341 100755 --- a/usr/bin/sdwdate +++ b/usr/bin/sdwdate @@ -1,60 +1,596 @@ -#!/bin/bash +#!/usr/bin/env python -## This file is part of Whonix. -## Copyright (C) 2012 - 2014 Patrick Schleizer -## See the file COPYING for copying conditions. +import sys +import logging +import signal +import os +import glob +import time +from datetime import datetime +import random +from random import randint +from subprocess import Popen, call, PIPE, check_output +import pickle +import re +from shutil import rmtree -#set -x +from sdwdate.remote_times import get_time_from_servers +from sdwdate.config import read_pools +from sdwdate.timesanitycheck import timesanitycheck +from sdwdate.proxy_settings import proxy_settings -set -e -set -o pipefail -set -o errtrace +from guimessages.translations import _translations -for i in /usr/lib/sdwdate/modules.d/*; do - if [ -f "$i" ]; then - ## If the last character is a ~, ignore that file, - ## because it was created by some editor, - ## which creates backup files. - if [ "${i: -1}" = "~" ]; then - continue - fi - ## Skipping files such as .dpkg-old and .dpkg-dist. - if ( echo "$i" | grep -q ".dpkg-" ); then - true "skip $i" - continue - fi - bash -n "$i" - source "$i" - fi -done -SCRIPTNAME="$(basename "$BASH_SOURCE")" -ownpid="$$" -ID="$ownpid" +class PreCheckVariables: + def __init__(self): + pass -## XXX: do not hardcode path to /var/run/sdwdate -if [ ! -f "/var/run/sdwdate/first_success" ]; then - SDW_MODE="startup" -else - SDW_MODE="restartup" -fi + run_prerequisite = False + prerequisite_path = '/usr/lib/anon-shared-helper-scripts/te_pe_tb_check' + if os.access(prerequisite_path, os.X_OK): + ## Create tenp dir for te_pe_tb_check. + temp_dir = check_output(["mktemp", "--directory"]).strip() + os.environ["TEMP_DIR"] = temp_dir + run_prerequisite = True -trap "sdwdate_error_handler" ERR -set +e +class Pool: + def __init__(self, pool): + self.url, self.comment = read_pools(pool, 'production') + self.url_random = [] + self.already_picked_index = [] + self.invalid_urls = 0 + self.done = False -trap "sdwdate_signal_sigint" SIGINT ## ctrl + c + @property + def url_range(self): + return len(self.url) -trap "sdwdate_signal_sigterm" SIGTERM + @property + def allowed_failures(self): + if os.path.exists('/etc/sdwdate.d/'): + files = sorted(glob.glob('/etc/sdwdate.d/*')) + for f in files: + with open(f) as conf: + lines = conf.readlines() + for line in lines: + if line.startswith('MAX_FAILURE_RATIO'): + failure_ratio = re.search(r'=(.*)', line).group(1) + return int(len(self.url) * float(failure_ratio)) + else: + return int(len(self.url) * 0.34) + return int(len(self.url) * 0.34) -trap "sdwdate_signal_sigusr1" SIGUSR1 -trap "sdwdate_signal_sighup" SIGHUP -## XXX: do not hardcode path to /var/run/sdwdate -## XXX: remove workaround during migration to systemd -echo "$ownpid" > "/var/run/sdwdate/pid" || echo "$ownpid" > "/var/run/sdwdate/pid_" +class Sdwdate: + def __init__(self): + self.iteration = 0 + self.number_of_pools = 3 -sdwdate_main ${1+"$@"} + self.pools = [Pool(pool) for pool in range(self.number_of_pools)] + ## Could get it here to prevent reading the file in sdwdate_loop for each Unreachable url. + #self.allowed_failures = [Pool(pool).allowed_failures for pool in range(self.number_of_pools)] + self.urls = [] + self.url_random = [] + self.valid_urls = [] + self.unixtimes = [] + self.pools_diff = [] + self.invalid_urls = [] + self.url_errors = [] -sdwdate_log "End." + self.median = 0 + self.range_nanoseconds = 999999999 + self.new_diff = 0 + self.newdiff_nanoseconds = 0 + + self.sclockadj_pid = 0 + + self.last_shell_date = '' + + self.first_success_path = '/var/run/sdwdate/first_success' + self.success_path = '/var/run/sdwdate/success' + self.status_path = '/var/run/sdwdate/status' + + self.success_icon = '/usr/share/icons/sdwdate-gui/Ambox_currentevent.svg.png' + self.busy_icon = '/usr/share/icons/sdwdate-gui/620px-Ambox_outdated.svg.png' + self.error_icon = '/usr/share/icons/sdwdate-gui/212px-Timeblock.svg.png' + + self.first_success = os.path.exists(self.first_success_path) + self.success = os.path.exists(self.success_path) + + self.status = {'icon': '', 'message': ''} + self.message = '' + + translations_path = '/usr/share/translations/sdwdate.yaml' + translation = _translations(translations_path, 'sdwdate') + self._ = translation.gettext + + self.proxy_ip, self.proxy_port = proxy_settings() + + @staticmethod + def general_proxy_error(pools): + ''' + This error occurs (at least) when Tor is not running. + ''' + returned_error = 'connect error: Connection closed unexpectedly' + if (pools[0] == returned_error and + pools[1] == returned_error and + pools[2] == returned_error): + return True + return False + + @staticmethod + def general_timeout_error(pools): + ''' + This error occurs (at least) when internet connection is down. + ''' + returned_error = 'Timeout' + if (pools[0] == returned_error and + pools[1] == returned_error and + pools[2] == returned_error): + return True + return False + + @staticmethod + def check_remote(remote, value): + ''' + Check returned value. True if numeric. + ''' + try: + n = int(value) + message = 'Remote status "%s", True' % remote + print(message) + logger.info(message) + return True + except ValueError: + message = 'Remote status "%s", False: %s' % (remote, value) + print(message) + logger.info(message) + return False + + def get_comment(self, remote): + ''' For logging the commnents, get the index of the url + to get it from pool.comment. + ''' + url_comment = '' + for url in self.pools: + try: + url_index = url.url.index(remote) + url_comment = url.comment[url_index] + except ValueError: + pass + return url_comment + + def time_sanity_check(self, unixtime): + status, time_one, time_two = timesanitycheck(unixtime) + + if status == 'sane': + self.message = (self._('tsc_1') + status + self._('tsc_2') + time_one) + # 'The clock is %s. Current time "%s".' % (status, time_one) + elif status == 'slow': + self.message = (self._('tsc_1') + status + self._('tsc_2') + time_one + + self._('slow_clock') + time_two) + self._('cause') + elif status == 'fast': + self.message = (self._('tsc_1') + status + self._('tsc_2') + time_one + + self._('fast_clock') + time_two) + self._('cause') + return status + + def build_median(self): + ''' + Get the median (not average) from the list of values. + ''' + diffs = sorted(self.pools_diff) + message = 'Pool differences, sorted: %s' % diffs + print(message) + logger.info(message) + self.median = diffs[(len(diffs) / 2)] + + def set_new_time(self): + ''' + Do not set time if diff = 0. + ''' + if self.median == 0: + message = 'Time difference = 0. Not setting time' + print(message) + logger.info(message) + return False + else: + return True + + def add_subtract_nanoseconds(self): + ''' + Could we replace this in sdwdate_loop pool_diff calculations? + -> int(web_time) - old_unixtime + ''' + signs = ['+', '-'] + sign = randint(0, 1) + nanoseconds = randint(0, self.range_nanoseconds) + seconds = float(nanoseconds) / 1000000000 + + if sign == 0: + self.new_diff = self.median + seconds + else: + self.new_diff = self.median - seconds + + self.newdiff_nanoseconds = int(self.new_diff * 1000000000) + + # print 'nanoseconds %s' % nanoseconds + message = 'Median time difference: %s' % self.median + print(message) + logger.info(message) + message = 'Seconds to add: %s %s' % (signs[sign], seconds) + print(message) + logger.info(message) + message = 'New time difference: %s' % self.new_diff + print(message) + logger.info(message) + + def run_sclockadj(self): + ''' + Set time with sneaky_clock_adjuster. + Should we use sclockadj_debug_helper? + ''' + if self.newdiff_nanoseconds > 0: + add_subtract = "--add" + else: + add_subtract = "--subtract" + cmd = [ + "sudo", + "INLINEDIR=/var/cache/sdwdate/sclockadj", + "/usr/lib/sdwdate/sclockadj", + "--no-debug", + "--no-verbose", + "--no-systohc", + "--no-first-wait", + "--move-min", "5000000", + "--move-max", "5000000", + "--wait-min", "1000000000", + "--wait-max", "1000000000", + add_subtract, str(abs(self.newdiff_nanoseconds))] + + ## Run sclockadj in a subshell. + sclockadj = Popen(cmd) + self.sclockadj_pid = sclockadj.pid + + message = 'Gradually adjusting the time by running sclockadj, PID=%s' % self.sclockadj_pid + print(message) + logger.info(message) + + ## Running sclockadj_debug_helper, in case... + ## May be read the last line to ensure sclockadj is running. + # cmd = ["sudo", "/usr/lib/sdwdate/sclockadj_debug_helper"] + ### Pipe stdout in subprocess. + # helper = Popen(cmd, stdout=PIPE) + ### Read the output. + # line = helper.stdout.read() + # print line + + def kill_sclockadj(self): + ''' + ''' + cmd = 'sudo /usr/lib/sdwdate/sclockadj_kill_helper ' + str(self.sclockadj_pid) + call(cmd, shell=True) + + def set_time_using_date(self): + old_unixtime = float('%.9f' % (time.time())) + message = 'Old unixttime: %s' % (str(old_unixtime)) + print(message) + logger.info(message) + + new_unixtime = float('%.9f' % (old_unixtime + self.new_diff)) + message = 'New unixtime %s' % (str(new_unixtime)) + print(message) + logger.info(message) + + ## Set new time. + cmd = 'sudo /bin/date --set @' + str(new_unixtime) + call(cmd, shell=True) + + message = 'Instantly setting the time by using command "%s"' % cmd + print(message) + logger.info(message) + + def strip_html(self, message): + ## New line for log. + tmp_message = re.sub('
', '\n', message) + ## Strip rmaining HTML. + return re.sub('<[^<]+?>', '', tmp_message) + + def write_status(self, *args): + self.status['icon'] = args[0] + self.status['message'] = args[1] + with open(self.status_path, 'wb') as f: + pickle.dump(self.status, f) + + def sdwdate_loop(self): + ''' + Check remotes. + Pick a random url in each pool, check the returned value. + Append valid urls if time is returned, otherwise restart a cycle + with a new random url, until every pool has a time value. + ''' + start_unixtime = time.time() + start_time = (datetime.strftime(datetime.fromtimestamp(start_unixtime), + '%a %b %d %H:%M:%S UTC %Y')) + message = ('Fetching remote times, start %s (unixtime %s)' + % (start_time, start_unixtime)) + print(message) + logger.info(message) + + current_unixtime = time.time() + time_sanity_check = self.time_sanity_check(current_unixtime) + stripped_message = self.strip_html(self.message) + + if time_sanity_check == 'sane': + logger.info(stripped_message) + else: + return self.error_icon, 'error' + + fetching_msg = self._('fetching') + restricted_msg = self._('restricted') + if self.success: + self.write_status(self.success_icon, fetching_msg) + logger.info(fetching_msg) + else: + if not self.first_success: + self.write_status(self.busy_icon, (fetching_msg + restricted_msg)) + logger.info(fetching_msg + restricted_msg) + else: + self.write_status(self.success_icon, fetching_msg) + logger.info(fetching_msg) + + while len(self.valid_urls) < self.number_of_pools: + self.iteration += 1 + message = 'Running sdwdate loop, iteration %s' % self.iteration + print(message) + logger.info(message) + + ## Clear the lists. + self.urls[:] = [] + self.url_random[:] = [] + + for pool in self.pools: + if not pool.done: + pool_range = pool.url_range + url_index = random.randrange(0, pool_range) + while url_index in pool.already_picked_index: + url_index = random.randrange(0, pool_range) + + pool.already_picked_index.append(url_index) + if len(pool.already_picked_index) >= pool_range: + pool_number = self.pools.index(pool) + 1 + self.message = self._('no_valid_time') + str(pool_number) + self._('restart') + logger.warning(self.message) + return self.error_icon, 'error' + + pool.url_random.append(pool.url[url_index]) + self.url_random.append(pool.url[url_index]) + + ## Fetch remotes. + if len(self.url_random) > 0: + message = 'Requested urls %s' % self.url_random + print(message) + logger.info(message) + + self.urls, self.returned_values = get_time_from_servers(self.url_random, + self.proxy_ip, + self.proxy_port) + + if len(self.urls) == 0: + self.message = self._('no_value_returned') + self._('restart') + return self.error_icon, 'error' + + message = 'Returned urls "%s"' % self.urls + print(message) + logger.info(message) + + else: + self.message = self._('list_not_built') + self._('restart') + return self.error_icon, 'error' + + if len(self.returned_values) > 2: + if self.general_proxy_error(self.returned_values): + self.message = self._('general_proxy_error') + print(message) + return self.error_icon, 'error' + if self.general_timeout_error(self.returned_values): + self.message = self._('general_timeout_error') + return self.error_icon, 'error' + + for i in range(len(self.urls)): + if self.check_remote(self.urls[i], self.returned_values[i]): + self.valid_urls.append(self.urls[i]) + self.unixtimes.append(self.returned_values[i]) + else: + self.invalid_urls.append(self.urls[i]) + self.url_errors.append(self.returned_values[i]) + for pool in self.pools: + if self.urls[i] in pool.url_random: + pool.invalid_urls += 1 + if pool.invalid_urls >= pool.allowed_failures: + self.message = (self._('max_pool_failures_1') + + str(self.pools.index(pool) + 1) + + ' (' + str(pool.invalid_urls) + ' of ' + + str(len(pool.url)) + ')' + + self._('max_pool_failures_2') + '
') + return self.error_icon, 'error' + + old_unixtime = (time.time()) + + for pool in self.pools: + if not pool.done: + for url in pool.url_random: + pool.done = url in self.valid_urls + if pool.done: + ## Values are returned randomly. Get the index of the url. + index = self.valid_urls.index(url) + ## Pool matching web time. + web_unixtime = int(self.unixtimes[index]) + sanitycheck_status = self.time_sanity_check(web_unixtime) + if sanitycheck_status == 'sane': + web_time = (datetime.strftime(datetime.fromtimestamp(web_unixtime), + '%a %b %d %H:%M:%S UTC %Y')) + pool_diff = int(web_unixtime) - int(old_unixtime) + self.pools_diff.append(pool_diff) + pool_number = self.pools.index(pool) + 1 + message = ('Pool %s last url: %s, web unixtime: %s, web time: %s, diff: %s seconds' + % (pool_number, url, web_unixtime, web_time, pool_diff)) + print(message) + logger.info(message) + else: + pool.done = False + del self.valid_urls[index] + self.invalid_urls.append(url) + message = ('%s: time sanity check failed, server time is %s' + % (url, sanitycheck_status)) + print message + logger.warning(message) + + message = 'Reachable urls:\n' + for url in self.valid_urls: + url_comment = self.get_comment(url) + message += '%s: "%s"\n' % (url, url_comment) + print(message.strip()) + logger.info(message.strip()) + + message = 'Unreachable urls:\n' + for url in self.invalid_urls: + url_comment = self.get_comment(url) + message += '%s: "%s"\n' % (url, url_comment) + print(message.strip()) + logger.info(message.strip()) + + end_unixtime = time.time() + end_time = (datetime.strftime(datetime.fromtimestamp(end_unixtime), + '%a %b %d %H:%M:%S UTC %Y')) + message = ('Fetching remote times, end %s (unixtime %s)' + % (end_time, end_unixtime)) + print(message) + logger.info(message) + + last_shell_date = check_output('date').strip() + self.message = self._('success_1') + last_shell_date + self._('success_2') + retrying_loop = False + return self.success_icon, 'success' + + +def signal_sigterm_handler(signum, frame): + # Inform sdwdate-gui + icon = sdwdate.error_icon + message = sdwdate._('user_kill') + stripped_message = re.sub('<[^<]+?>', '', message) + sdwdate.write_status(icon, message) + + if sdwdate.sclockadj_pid != 0: + sdwdate.kill_sclockadj() + ## Remove te_pe_tb_check temp directory. + pre_check = PreCheckVariables() + if pre_check.run_prerequisite: + rmtree(pre_check.temp_dir) + + logger.info(stripped_message) + sys.exit(143) + + +def prerequisite_check(): + pre_check = PreCheckVariables() + tor_status = False + message = '' + previous_messsage = '' + sdwdate = Sdwdate() + while not tor_status: + prerequisite_status = Popen(pre_check.prerequisite_path, + stdout=PIPE, + stderr=PIPE) + value, error = prerequisite_status.communicate() + if value == '': + tor_status = True + else: + message = 'Prerequsite check:
%s' % value.strip() + if message != previous_messsage: + previous_messsage = message + stripped_message = sdwdate.strip_html(message) + print stripped_message + logger.warning(stripped_message) + icon = sdwdate.error_icon + sdwdate.write_status(icon, message) + time.sleep(10) + + +if __name__ == "__main__": + ## When restarted from sdwdate-gui, allow sufficient time between + ## status changes. See related comment in sdwdate-gui. + time.sleep(0.2) + + pre_check = PreCheckVariables() + signal.signal(signal.SIGTERM, signal_sigterm_handler) + + logger = logging.getLogger('sdwdate.log') + logger.setLevel(logging.INFO) + formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + handler = logging.FileHandler('/var/log/sdwdate.log') + handler.setFormatter(formatter) + logger.addHandler(handler) + + self_pid = os.getpid() + pid_message = 'sdwdate started. PID %s' % self_pid + print pid_message + logger.info(pid_message) + sdwdate = Sdwdate() + proxy_message = ('Tor socks host: %s Tor socks port: %s' + % (sdwdate.proxy_ip, sdwdate.proxy_port)) + print proxy_message + logger.info(proxy_message) + + if pre_check.run_prerequisite: + prerequisite_check() + + while True: + sdwdate = Sdwdate() + icon, status = sdwdate.sdwdate_loop() + + if status == 'success': + sdwdate.build_median() + sdwdate.add_subtract_nanoseconds() + if sdwdate.set_new_time(): + if sdwdate.success: + sdwdate.run_sclockadj() + else: + sdwdate.set_time_using_date() + if not sdwdate.first_success: + f = open(sdwdate.first_success_path, 'w') + f.close() + + f = open(sdwdate.success_path, 'w') + f.close() + sleep_time = randint(60, 180) + log_level = 'info' + + elif status == 'error': + sleep_time = 10 + log_level = 'warning' + + message = (sdwdate.message + sdwdate._('sleeping') + + str(sleep_time) + sdwdate._('minutes')) + stripped_message = sdwdate.strip_html(message) + + sdwdate.write_status(icon, message) + + if log_level == 'info': + logger.info(stripped_message) + elif log_level == 'warning': + logger.warning(stripped_message) + + print(stripped_message) + + seconds_to_sleep = sleep_time * 60 + ## Using sh sleep in place of python's time.sleep(). + ## The latter uses the system clock for its inactive state time. + ## It becomes utterly confused when sclockadj is running. + cmd = 'sleep %s' % seconds_to_sleep + call(cmd, shell=True) + #time.sleep(seconds_to_sleep) + if sdwdate.sclockadj_pid != 0: + sdwdate.kill_sclockadj() diff --git a/usr/lib/python2.7/dist-packages/sdwdate/__init__.py b/usr/lib/python2.7/dist-packages/sdwdate/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/usr/lib/python2.7/dist-packages/sdwdate/__init__.py @@ -0,0 +1 @@ + diff --git a/usr/lib/python2.7/dist-packages/sdwdate/config.py b/usr/lib/python2.7/dist-packages/sdwdate/config.py new file mode 100644 index 00000000..ae027af9 --- /dev/null +++ b/usr/lib/python2.7/dist-packages/sdwdate/config.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python + +import os +import glob +import re +import random + +def sort_pool(pool, mode): + ## Check number of multi-line pool. + number_of_pool_multi = 0 + for i in range(len(pool)): + if pool[i] == ('['): + number_of_pool_multi += 1 + + ## Dynamically create multi-line lists. + multi_list_url = [[] for i in range(number_of_pool_multi)] + multi_list_comment = [[] for i in range(number_of_pool_multi)] + + ## Sort... + multi_line = False + multi_index = 0 + pool_single_url = [] + pool_single_comment = [] + + for i in range(len(pool)): + if multi_line and pool[i] == ']': + multi_line = False + multi_index = multi_index + 1 + + elif multi_line and pool[i].startswith('"'): + url = re.search(r'"(.*)#', pool[i]) + if url != None: + if mode == 'production': + multi_list_url[multi_index].append(url.group(1)) + elif mode == 'test': + pool_single_url.append(url.group(1)) + comment = re.search(r'#(.*)"', pool[i]) + if comment != None: + if mode == 'production': + multi_list_comment[multi_index].append(comment.group(1)) + elif mode == 'test': + pool_single_comment.append(comment.group(1)) + + elif pool[i] == '[': + multi_line = True + + elif pool[i].startswith('"'): + url = re.search(r'"(.*)#', pool[i]) + if url != None: + pool_single_url.append(url.group(1)) + comment = re.search(r'#(.*)"', pool[i]) + if comment != None: + pool_single_comment.append(comment.group(1)) + + ## Pick a random url in each multi-line pool, + ## append it to single url pool. + for i in range(number_of_pool_multi): + if mode == 'production': + single_ulr_index = random.sample(range(len(multi_list_url[i])), 1)[0] + single_url = multi_list_url[i][single_ulr_index] + single_comment = multi_list_comment[i][single_ulr_index] + pool_single_url.append(single_url) + pool_single_comment.append(single_comment) + + return(pool_single_url, pool_single_comment) + +def read_pools(pool, mode): + SDWDATE_POOL_ONE = False + SDWDATE_POOL_TWO = False + SDWDATE_POOL_THREE = False + + pool_one = [] + pool_two = [] + pool_three = [] + + pool_one_url = [] + pool_two_url = [] + pool_three_url = [] + + if os.path.exists('/etc/sdwdate.d/'): + files = sorted(glob.glob('/etc/sdwdate.d/*')) + + if files: + conf_found = False + for conf in files: + if not conf.endswith('~') and conf.count('.dpkg-') == 0: + conf_found = True + with open(conf) as c: + for line in c: + line = line.strip() + if line.startswith('SDWDATE_POOL_ONE'): + SDWDATE_POOL_ONE = True + + elif line.startswith('SDWDATE_POOL_TWO'): + SDWDATE_POOL_ONE = False + SDWDATE_POOL_TWO = True + + elif line.startswith('SDWDATE_POOL_THREE'): + SDWDATE_POOL_ONE = False + SDWDATE_POOL_TWO = False + SDWDATE_POOL_THREE = True + + elif SDWDATE_POOL_ONE and not line.startswith('##'): + pool_one.append(line) + + elif SDWDATE_POOL_TWO and not line.startswith('##'): + pool_two.append(line) + + elif SDWDATE_POOL_THREE and not line.startswith('##'): + pool_three.append(line) + + if not conf_found: + print('No valid file found in user configuration folder "/etc/sdwdate.d".') + + else: + print('No file found in user configuration folder "/etc/sdwdate.d".') + + else: + print('User configuration folder "/etc/sdwdate.d" does not exist.') + + pool_one_url, pool_one_comment = sort_pool(pool_one, mode) + pool_two_url , pool_two_comment = sort_pool(pool_two, mode) + pool_three_url, pool_three_comment = sort_pool(pool_three, mode) + + pool_url = [pool_one_url, pool_two_url, pool_three_url] + pool_comment = [pool_one_comment, pool_two_comment, pool_three_comment] + + return(pool_url[pool], + pool_comment[pool]) + + +if __name__ == "__main__": + read_pools() diff --git a/usr/lib/python2.7/dist-packages/sdwdate/proxy_settings.py b/usr/lib/python2.7/dist-packages/sdwdate/proxy_settings.py new file mode 100644 index 00000000..13657778 --- /dev/null +++ b/usr/lib/python2.7/dist-packages/sdwdate/proxy_settings.py @@ -0,0 +1,46 @@ +import os +import glob +import re +from subprocess import check_output + +def proxy_settings(): + ip_address = '' + port_number = '' + settings_path = '/usr/lib/anon-shared-helper-scripts/settings_echo' + + if os.path.exists('/etc/sdwdate.d/'): + files = sorted(glob.glob('/etc/sdwdate.d/*')) + for f in files: + with open(f) as conf: + lines = conf.readlines() + for line in lines: + if line.startswith('PROXY_IP'): + ip_address = re.search(r'=(.*)', line).group(1) + if line.startswith('PROXY_PORT'): + port_number = re.search(r'=(.*)', line).group(1) + + if (os.path.exists('/usr/share/whonix') and + os.access(settings_path, os.X_OK)): + proxy_settings = check_output(settings_path) + ip_address = re.search(r'TOR_CONTROL_HOST="(.*)"', proxy_settings).group(1) + elif ip_address != '': + ## ip_address = PROXY_IP + pass + else: + ip_address = '127.0.0.1' + + if os.path.exists('/usr/share/whonix'): + port_number = '9108' + elif port_number != '': + ## port_number = PROXY_PORT + pass + else: + port_number = '9050' + + #print 'ip %s port %s' % (ip_address, port_number) + return ip_address, port_number + +if __name__ == "__main__": + proxy_settings() + + diff --git a/usr/lib/python2.7/dist-packages/sdwdate/remote_times.py b/usr/lib/python2.7/dist-packages/sdwdate/remote_times.py new file mode 100644 index 00000000..9579fd4a --- /dev/null +++ b/usr/lib/python2.7/dist-packages/sdwdate/remote_times.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +## Copyright (C) 2015 troubadour +## Copyright (C) 2015 Patrick Schleizer +## See the file COPYING for copying conditions. + +import gevent +from gevent.subprocess import Popen, PIPE + +def get_time_from_servers(remotes, ip_address, port_number): + url_to_unixtime_path = '/usr/lib/sdwdate/url_to_unixtime' + + threads = [] + urls = [] + unix_times = [] + seconds = 10 + + ### Clear lists. + del threads[:] + del urls[:] + del unix_times[:] + + for i in range(len(remotes)): + threads.append(Popen([url_to_unixtime_path, + ip_address, + port_number, + remotes[i], + '80', + '0'], stdout=PIPE)) + + for i in range(len(threads)): + gevent.wait([threads[i]], timeout=seconds) + + for i in range(len(threads)): + if threads[i].poll() is not None: + urls.append(remotes[i]) + reply = threads[i].stdout.read() + unix_times.append(reply.strip()) + else: + urls.append(remotes[i]) + unix_times.append('Timeout') + + return urls, unix_times + +if __name__ == "__main__": + get_time_from_servers(remotes) \ No newline at end of file diff --git a/usr/lib/python2.7/dist-packages/sdwdate/timesanitycheck.py b/usr/lib/python2.7/dist-packages/sdwdate/timesanitycheck.py new file mode 100644 index 00000000..efce1b39 --- /dev/null +++ b/usr/lib/python2.7/dist-packages/sdwdate/timesanitycheck.py @@ -0,0 +1,39 @@ +import sys +import os, time +from datetime import datetime + +def timesanitycheck(unixtime): + whonix_build_file = '/usr/share/whonix/build_timestamp' + anondist_build_file = '/var/lib/anon-dist/build_version' + spare_file = '/usr/share/zoneinfo/UTC' + + if os.path.exists(whonix_build_file): + build_timestamp_file = whonix_build_file + elif os.path.exists(anondist_build_file): + build_timestamp_file = anondist_build_file + else: + build_timestamp_file = spare_file + + current_unixtime = unixtime + current_time = datetime.strftime(datetime.fromtimestamp(unixtime), '%a %b %d %H:%M:%S UTC %Y') + + build_time = time.strftime('%a %b %d %H:%M:%S UTC %Y', time.gmtime(os.path.getmtime(build_timestamp_file))) + build_unixtime = time.mktime(datetime.strptime(build_time, '%a %b %d %H:%M:%S UTC %Y').timetuple()) + + expiration_unixtime = 1999936800 + expiration_time = datetime.strftime(datetime.fromtimestamp(expiration_unixtime), '%a %b %d %H:%M:%S UTC %Y') + + if current_unixtime < build_unixtime: + status = 'slow' + time_one = current_time + time_two = build_time + elif current_unixtime > expiration_unixtime: + status = 'fast' + time_one = current_time + time_two = expiration_time + else: + status = 'sane' + time_one = current_time + time_two = '' + + return status, time_one, time_two diff --git a/usr/lib/sdwdate/modules.d/sdwdate b/usr/lib/sdwdate/modules.d/sdwdate deleted file mode 100755 index 3fe708f6..00000000 --- a/usr/lib/sdwdate/modules.d/sdwdate +++ /dev/null @@ -1,1712 +0,0 @@ -#!/bin/bash - -## This file is part of Whonix. -## Copyright (C) 2012 - 2014 Patrick Schleizer -## See the file COPYING for copying conditions. - -## CREDITS -## - sdwdate is a rewrite of tails_htp in bash -## - defaults taken from tails_htp -## - options inspired by tails_htp -## - log file layout inspired by tails_htp -## - sclockadj has been written by Jason Ayala (Jason@JasonAyala.com) - -## TODO: -## - implement --user - -sdwdate_usage() { - echo "\ -$SCRIPTNAME [-aDdlpqTux] [long options...] - -d --debug debug - --help print usage message and exit - -q --quiet quiet - -x --dont_set_date do not set the time (only show) - --no-move-forward do not move the time forward - --no-move-backwards do not move the time backwards - --systohc update hardware clock - -a --user_agent http user agent to use - -l --log_file log to this file rather than to STDOUT - -D --done_file create this file after one cycle of sdwdate - -T --success_file create this file after setting time successfully - --first_success_file create this file after setting time successfully for the first time - --pool_one distrusted hostnames - --pool_two distrusted hostnames - --pool_three distrusted hostnames - --allowed_per_pool_failure_ratio ratio (0.0-1.0) of allowed per-pool failure - --cache-dir cache directory - --temp-dir temporary directory - -p --proxy-ip proxy IP - -o --port-port proxy port - -i --interval continuously run every x minutes - --mininterval wait minimum between intervals - -r --randomize randomize interval - -n --noconfig ignore /etc/sdwdate.d/ config folder - --parsecmd_only_on_startup parse command line arguments only on startup - -w --dispatchpre exec before run - -y --dispatchprerequisite check before run - -x --dispatchpostsuccess exec after successful run - -z --dispatchpostfailure exec after unsuccessful run - -m --dispatchposterror exec when an error is caught - --dispatch_pre_one exec before run of url to unixtime tool - --dispatch_post_one exec after run of url to unixtime tool - --dispatch_pre_two exec before run of url to unixtime tool - --dispatch_post_two exec after run of url to unixtime tool - --dispatch_pre_three exec before first run of url to unixtime tool - --dispatch_post_three exec after run of url to unixtime tool - --nodonefileonerror do not create done file on error - --noexitonerror do not exit on error - --echo-unixtime echo remote unix time even when using --quiet" - -# -u --user userid to run as -} - -sdwdate_defaults() { - if [ "$DEBUG" = "" ]; then - DEBUG="0" - fi - - if [ "$USER" = "" ]; then - USER="" - fi - - if [ "$DONT_SET_DATE" = "" ]; then - DONT_SET_DATE="0" - fi - - if [ "$NO_MOVE_FORWARD" = "" ]; then - NO_MOVE_FORWARD=1 - fi - - if [ "$NO_MOVE_BACKWARDS" = "" ]; then - NO_MOVE_BACKWARDS=1 - fi - - if [ "$SYSTOHC" = "" ]; then - SYSTOHC=0 - SDWDATE_SCLOCKADJ_SYSTOHC="--nosystohc" - fi - - if [ "$LOG_FILE" = "" ]; then - LOG_FILE=~/.sdwdate/log - fi - - if [ "$DONE_FILE" = "" ]; then - DONE_FILE=~/.sdwdate/done - fi - - if [ "$SUCCESS_FILE" = "" ]; then - SUCCESS_FILE=~/.sdwdate/success - fi - - if [ "$FIRST_SUCCESS_FILE" = "" ]; then - FIRST_SUCCESS_FILE=~/.sdwdate/first_success - fi - - if [ "$ALLOWED_PER_POOL_FAILURE_RATIO" = "" ]; then - ALLOWED_PER_POOL_FAILURE_RATIO="0.34" - fi - - if [ "$TEMP_DIR" = "" ]; then - TEMP_DIR="$(mktemp --directory)" - fi - ## Export so plugins run by sdwdate can use it. - export TEMP_DIR - - if [ "$SDW_CACHE_DIR" = "" ]; then - SDW_CACHE_DIR="/var/cache/sdwdate/sclockadj" - fi - - if [ "$PROXY_IP" = "" ]; then - PROXY_IP="127.0.0.1" - fi - - if [ "$PROXY_PORT" = "" ]; then - PROXY_PORT="9050" - fi - - if [ "$INTERVAL" = "" ]; then - INTERVAL="" - fi - - if [ "$MIN_INTERVAL" = "" ]; then - MIN_INTERVAL="60" - fi - - if [ "$NOCONFIG" = "" ]; then - NOCONFIG="" - fi - - if [ "$PARSE_CMD_ONLY_ON_STARTUP" = "" ]; then - PARSE_CMD_ONLY_ON_STARTUP="" - fi - - if [ "$RANDOMIZE" = "" ]; then - RANDOMIZE="" - fi - - if [ "$DISPATCH_PREREQUISITE" = "" ]; then - DISPATCH_PREREQUISITE="true" - fi - - if [ "$DISPATCH_POST_ERROR" = "" ]; then - DISPATCH_POST_ERROR="exit 1" - fi - - if [ "$SDW_TOUCH_DONE_FILE_ON_ERROR" = "" ]; then - SDW_TOUCH_DONE_FILE_ON_ERROR="1" - fi - - if [ "$SDW_EXIT_ON_ERROR" = "" ]; then - SDW_EXIT_ON_ERROR="1" - fi - - if [ "$DISPATCH_PRE" = "" ]; then - DISPATCH_PRE="true" - fi - - if [ "$DISPATCH_POST_SUCCESS" = "" ]; then - DISPATCH_POST_SUCCESS="true" - fi - - if [ "$DISPATCH_POST_FAILURE" = "" ]; then - DISPATCH_POST_FAILURE="true" - fi - - if [ "$HTTP_USER_AGENT" = "" ]; then - HTTP_USER_AGENT="" - #HTTP_USER_AGENT="$(/usr/bin/getTorbuttonUserAgent)" - #HTTP_USER_AGENT="Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0" - fi - - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_STARTUP" = "" ]; then - SDWDATE_USE_SCLOCKADJ_WHEN_STARTUP="0" - fi - - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_RESTARTUP" = "" ]; then - SDWDATE_USE_SCLOCKADJ_WHEN_RESTARTUP="1" - fi - - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_DAEMON" = "" ]; then - SDWDATE_USE_SCLOCKADJ_WHEN_DAEMON="1" - fi - - if [ "$SDWDATE_SCLOCKADJ_VERBOSE" = "" ]; then - SDWDATE_SCLOCKADJ_VERBOSE="--no-verbose" - fi - - if [ "$SDWDATE_SCLOCKADJ_CHANGE_DATE" = "" ]; then - SDWDATE_SCLOCKADJ_CHANGE_DATE="--no-debug" - fi - - if [ "$SDWDATE_SCLOCKADJ_FIRST_WAIT" = "" ]; then - SDWDATE_SCLOCKADJ_FIRST_WAIT="--no-first-wait" - fi - - if [ "$SDWDATE_SCLOCKADJ_MOVE_MIN" = "" ]; then - SDWDATE_SCLOCKADJ_MOVE_MIN="500000" - fi - - if [ "$SDWDATE_SCLOCKADJ_MOVE_MAX" = "" ]; then - SDWDATE_SCLOCKADJ_MOVE_MAX="500000" - fi - - if [ "$SDWDATE_SCLOCKADJ_WAIT_MIN" = "" ]; then - SDWDATE_SCLOCKADJ_WAIT_MIN="1000000000" - fi - - if [ "$SDWDATE_SCLOCKADJ_WAIT_MAX" = "" ]; then - SDWDATE_SCLOCKADJ_WAIT_MAX="1000000000" - fi - - if [ "$ECHO_UNIX_TIME" = "" ]; then - ECHO_UNIX_TIME="false" - fi - - if [ "${SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_ONE]}" = "" ]; then - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_PRE - SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_ONE]="true" - fi - - if [ "${SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_ONE]}" = "" ]; then - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_POST - SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_ONE]="true" - fi - - if [ "${SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_TWO]}" = "" ]; then - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_PRE - SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_TWO]="true" - fi - - if [ "${SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_TWO]}" = "" ]; then - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_POST - SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_TWO]="true" - fi - - if [ "${SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_THREE]}" = "" ]; then - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_PRE - SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_THREE]="true" - fi - - if [ "${SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_THREE]}" = "" ]; then - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_POST - SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_THREE]="true" - fi - - if [ "$SDWDATE_POOL_ONE" = "" ]; then - declare -g SDWDATE_POOL_ONE - - SDWDATE_POOL_ONE=( - boum.org - chavez.indymedia.org - db.debian.org - debian.org - epic.org - mail.riseup.net - sarava.org - squat.net - tachanka.org - www.1984.is - www.eff.org - www.immerda.ch - www.privacyinternational.org - www.torproject.org - freedom.press - ) - fi - - if [ "$SDWDATE_POOL_TWO" = "" ]; then - declare -g SDWDATE_POOL_TWO - - SDWDATE_POOL_TWO=( - grc.com - www.tarsnap.com - wikileaks.org - pressfreedomfoundation.org - securedrop.theguardian.com - safesource.forbes.com - en.wikipedia.org - cve.mitre.org - duckduckgo.com - lkml.org - www.gnu.org - fsf.org - fsfe.org - defectivebydesign.org - www.kernel.org - opentechfund.org - firstlook.org - ) - fi - - if [ "$SDWDATE_POOL_THREE" = "" ]; then - declare -g SDWDATE_POOL_THREE - - SDWDATE_POOL_THREE=( - www.startpage.com - www.apache.org - www.centos.org - www.piratenpartei.de - www.torservers.net - www.accessnow.org - rsf.org - www.wauland.de - www.ccc.de - netzpolitik.org - privacyfoundation.ch - www.noisebridge.net - en.bitcoin.it - www.calyxinstitute.org - gnupg.org - gpgtools.org - schneier.com - ) - fi -} - -sdwdate_read_config_folder() { - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_PRE - declare -A -g SDWDATE_TIME_TOOL_DISPATCH_POST - - if [ "$NOCONFIG" = "1" ]; then - return 0 - fi - for i in /etc/sdwdate.d/*; do - if [ -f "$i" ]; then - ## If the last character is a ~, ignore that file, because it was created - ## by some editor, which creates backup files. - if [ "${i: -1}" = "~" ]; then - continue - fi - ## Skipping files such as .dpkg-old and .dpkg-dist. - if ( echo "$i" | grep -q ".dpkg-" ); then - true "skip $i" - continue - fi - local bash_n_exit_code bash_n_output - bash_n_exit_code="0" - bash_n_output="$(bash -n "$i" 2>&1)" || { bash_n_exit_code="$?" ; true; }; - if [ ! "$bash_n_exit_code" = "0" ]; then - sdwdate_error_handler "Invalid config file: $i -bash_n_exit_code: $bash_n_exit_code -bash_n_output: -$bash_n_output" || true - fi - source "$i" - fi - done -} - -sdwdate_parse_cmd_options() { - ## Thanks to: - ## http://mywiki.wooledge.org/BashFAQ/035 - - while : - do - case $1 in - -h | --help | -\?) - sdwdate_usage - exit 0 - ;; - -d | --debug) - DEBUG=1 - shift - ;; - -u | --user) - USER=$2 - RUN_AS="sudo -u $USER" - shift 2 - ;; - -x | --dont_set_date) - DONT_SET_DATE=1 - shift - ;; - --no-move-forward) - NO_MOVE_FORWARD=1 - shift - ;; - --no-move-backwards) - NO_MOVE_BACKWARDS=1 - shift - ;; - --systohc) - SYSTOHC=1 - SDWDATE_SCLOCKADJ_SYSTOHC="--systohc" - shift - ;; - -a | --user_agent) - HTTP_USER_AGENT=$2 - shift 2 - ;; - -l | --log_file) - LOG_FILE=$2 - shift 2 - ;; - -D | --done_file) - DONE_FILE=$2 - shift 2 - ;; - -T | --success_file) - SUCCESS_FILE=$2 - shift 2 - ;; - -T | --first_success_file) - FIRST_SUCCESS_FILE=$2 - shift 2 - ;; - -P | --pool_one) - SDWDATE_POOL_ONE=$2 - shift 2 - ;; - -N | --pool_two) - SDWDATE_POOL_TWO=$2 - shift 2 - ;; - -F | --pool_three) - SDWDATE_POOL_THREE=$2 - shift 2 - ;; - -A | --allowed_per_pool_failure_ratio) - ALLOWED_PER_POOL_FAILURE_RATIO=$2 - shift 2 - ;; - --cache-dir) - SDW_CACHE_DIR=$2 - shift 2 - ;; - --temp-dir) - TEMP_DIR=$2 - shift 2 - ;; - -p | --proxy-ip) - PROXY_IP=$2 - shift 2 - ;; - -o | --proxy-port) - PROXY_PORT=$2 - shift 2 - ;; - -i | --interval) - INTERVAL=$2 - shift 2 - ;; - --mininterval) - MIN_INTERVAL=$2 - shift 2 - ;; - -n | --noconfig) - NOCONFIG="1" - shift 1 - ;; - --parsecmd_only_on_startup) - PARSE_CMD_ONLY_ON_STARTUP="1" - shift 1 - ;; - -r | --randomize) - RANDOMIZE="1" - shift 1 - ;; - --timewarp-on-startup) - SDWDATE_USE_SCLOCKADJ_WHEN_STARTUP="0" - shift 1 - ;; - --timewarp-on-restartup) - SDWDATE_USE_SCLOCKADJ_WHEN_RESTARTUP="0" - shift 1 - ;; - --timewarp-on-daemon) - SDWDATE_USE_SCLOCKADJ_WHEN_DAEMON="0" - shift 1 - ;; - --sclockadj-on-startup) - SDWDATE_USE_SCLOCKADJ_WHEN_STARTUP="1" - shift 1 - ;; - --sclockadj-on-daemon) - SDWDATE_USE_SCLOCKADJ_WHEN_DAEMON="1" - shift 1 - ;; - --sclockadj-verbose) - SDWDATE_SCLOCKADJ_VERBOSE="--verbose" - shift 1 - ;; - --sclockadj-no-change-date) - SDWDATE_SCLOCKADJ_CHANGE_DATE="--debug" - shift 1 - ;; - --sclockadj-first-wait) - SDWDATE_SCLOCKADJ_FIRST_WAIT="--first-wait" - shift 1 - ;; - --sclockadj-move-min) - SDWDATE_SCLOCKADJ_MOVE_MIN=$2 - shift 2 - ;; - --sclockadj-move-max) - SDWDATE_SCLOCKADJ_MOVE_MAX=$2 - shift 2 - ;; - --sclockadj-wait-min) - SDWDATE_SCLOCKADJ_WAIT_MIN=$2 - shift 2 - ;; - --sclockadj-wait-max) - SDWDATE_SCLOCKADJ_WAIT_MAX=$2 - shift 2 - ;; - -y | --dispatchprerequisite) - DISPATCH_PREREQUISITE=$2 - shift 2 - ;; - -m | --dispatchposterror) - DISPATCH_POST_ERROR=$2 - shift 2 - ;; - --nodonefileonerror) - SDW_TOUCH_DONE_FILE_ON_ERROR="0" - shift 2 - ;; - --noexitonerror) - SDW_EXIT_ON_ERROR="0" - shift 2 - ;; - -w | --dispatchpre) - DISPATCH_PRE=$2 - shift 2 - ;; - -x | --dispatchpostsuccess) - DISPATCH_POST_SUCCESS=$2 - shift 2 - ;; - -z | --dispatchpostfailure) - DISPATCH_POST_FAILURE=$2 - shift 2 - ;; - --dispatch_pre_one) - SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_ONE]=$2 - shift 2 - ;; - --dispatch_post_one) - SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_ONE]=$2 - shift 2 - ;; - --dispatch_pre_two) - SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_TWO]=$2 - shift 2 - ;; - --dispatch_post_two) - SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_TWO]=$2 - shift 2 - ;; - --dispatch_pre_three) - SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_THREE]=$2 - shift 2 - ;; - --dispatch_post_three) - SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_THREE]=$2 - shift 2 - ;; - -q | --quiet) - QUIET=1 - shift - ;; - --echo-unixtime) - ECHO_UNIX_TIME=true - shift - ;; - --) - shift - break - ;; - -*) - sdwdate_log "$SCRIPTNAME unknown option: $1" >&2 - exit 1 - ;; - *) - break - ;; - esac - done - - ## If there are input files (for example) that follow the options, they - ## will remain in the "$@" positional parameters. -} - -sdwdate_preparation() { - mkdir --parents "$(dirname "$LOG_FILE")" - mkdir --parents "$(dirname "$DONE_FILE")" - mkdir --parents "$(dirname "$SUCCESS_FILE")" - mkdir --parents "$(dirname "$FIRST_SUCCESS_FILE")" - - rm --force "$DONE_FILE" - rm --force "$SUCCESS_FILE" - #rm --force "$FIRST_SUCCESS_FILE" - - declare -A -g sdwdate_download_tool_exit_code - declare -A -g SDWDATE_DOWNLOAD_TOOL_PID - declare -A -g SDWDATE_DOWNLOAD_TOOK_TIME - - if [ "$who_ami" = "" ]; then - ## Required for eventual plugins. - who_ami="$(whoami)" - fi - sdwdate_log "$FUNCNAME: who_ami is set to $who_ami." -} - -sdwdate_echo() { - if [ "$QUIET" = "1" ]; then - true - else - echo "$@" - fi -} - -sdwdate_write_log() { - ## Default, if the error happens before defaults are set and before config - ## files are read. - if [ "$LOG_FILE" = "" ]; then - LOG_FILE="/var/log/sdwdate.log" - fi - - if [ "$LOG_FILE" = "" ]; then - true - else - echo "$@" >> "$LOG_FILE" - fi -} - -sdwdate_log() { - if [ "$ID" = "" ] ; then - ID="No_ID" - fi - - local msg msg_string_length max_log_string_length - msg="$ID: $@" - msg_string_length="${#msg}" - max_log_string_length="500" - - if [ "$msg_string_length" -gt "$max_log_string_length" ]; then - ## Shorten excess length $msg to $max_log_string_length chars. - msg="${msg:0:$max_log_string_length}" - msg="${msg} ||| Shortened log msg string length!" - fi - - swddate_last_but_one_msg="$swddate_last_msg" - swddate_last_msg="$msg" - - sdwdate_echo "$msg" - sdwdate_write_log "$msg" -} - -sdwdate_no_duplicate_log() { - if [ ! -f "$LOG_FILE" ]; then - sdwdate_log "$@" - return 0 - fi - - if [ "$swddate_last_msg" = "$ID: $@" ]; then - return 0 - fi - if [ "$swddate_last_but_one_msg" = "$ID: $@" ]; then - return 0 - fi - - sdwdate_log "$@" -} - -sdwdate_error_handler() { - local exit_code="$?" - local error_cause error_text - error_text="$1" - if [ "$error_text" = "" ]; then - error_cause="$FUNCNAME signal ERR detected in line ${BASH_LINENO[0]} with BASH_COMMAND: -$BASH_COMMAND" - else - error_cause="$FUNCNAME called with error_text: -$error_text" - fi - - ## Default, if the error happens before defaults are set and before config - ## files are read. - if [ "$SDW_EXIT_ON_ERROR" = "" ]; then - SDW_EXIT_ON_ERROR="1" - fi - - local current_time - current_time="$(date)" || true - - local error_message - error_message="\ -############################################ -## Error detected! Please report this bug! # -## -## BASH_SOURCE: $BASH_SOURCE -## SDW_EXIT_ON_ERROR: $SDW_EXIT_ON_ERROR -## SDW_MODE: $SDW_MODE -## SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE -## current_time: $current_time -## -## exit_code: $exit_code -## error_cause: -$error_cause -############################################\ -" - - sdwdate_log "error_message: $error_message" || true - - error_message="\ -############################################

-## Error detected! Please report this bug! #

-##

-## BASH_SOURCE: $BASH_SOURCE

-## SDW_EXIT_ON_ERROR: $SDW_EXIT_ON_ERROR

-## SDW_MODE: $SDW_MODE

-## SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE

-## current_time: $current_time

-##

-## exit_code: $exit_code

-## error_cause:

-$error_cause

-############################################

\ -" - - local ret - if [ "$SDW_TOUCH_DONE_FILE_ON_ERROR" = "1" ]; then - touch "$DONE_FILE" - ret="$?" - if [ ! "$ret" = "0" ]; then - sdwdate_log "ERROR $BASH_SOURCE: Could not touch DONE_FILE: $DONE_FILE." || true - fi - fi - - sdwdate_dispatcher "DISPATCH_POST_ERROR" - - if [ "$SDW_EXIT_ON_ERROR" = "1" ]; then - sdwdate_log "$SCRIPTNAME (not timesync!): Error detected. Cleaning up..." || true - ## Check if function sdwdate_terminate_sclockadj is already available and - ## use it if available. - command_v_exit_code="0" - command -v sdwdate_terminate_sclockadj >/dev/null 2>&1 || { command_v_exit_code="$?" ; true; }; - if [ "$command_v_exit_code" = "0" ]; then - sdwdate_terminate_sclockadj || true - fi - SIGNAL_TYPE="ERR" - if [ "$(command -v "sdwdate_ex_funct")" ]; then - sdwdate_ex_funct || true - fi - sdwdate_log "$SCRIPTNAME (not timesync!): Error detected. Exiting." || true - exit 1 - else - sdwdate_log "$SCRIPTNAME (not timesync!): Error detected. Continuing." || true - fi -} - -sdwdate_sanity_tests() { - if [ "$ID" = "" ]; then - sdwdate_error_handler "Variable ID is empty." || true - fi - - command -v bash >/dev/null - command -v bc >/dev/null - command -v basename >/dev/null - command -v mktemp >/dev/null - command -v touch >/dev/null - command -v dirname >/dev/null - command -v awk >/dev/null - command -v date >/dev/null - ## Using GNU's printf instead of bash's printf. - command -v /usr/bin/printf >/dev/null - command -v od >/dev/null - command -v grep >/dev/null - command -v sudo >/dev/null - command -v shuf >/dev/null - command -v /usr/lib/sdwdate/sclockadj >/dev/null - command -v /sbin/hwclock >/dev/null - command -v /usr/lib/sdwdate/url_to_unixtime >/dev/null - command -v timeout >/dev/null - - test -e "/dev/random" - bash -n "$BASH_SOURCE" -} - -sdwdate_ex_funct() { - sdwdate_log "$SCRIPTNAME (not timesync!): signal $SIGNAL_TYPE received. Cleaning up..." - - if [ ! "$sleep_pid" = "" ]; then - kill -9 "$sleep_pid" || true - fi - - if [ ! "${SDWDATE_DOWNLOAD_TOOL_PID[$SDWDATE_CURRENT_POOL]}" = "" ]; then - kill -9 "${SDWDATE_DOWNLOAD_TOOL_PID[$SDWDATE_CURRENT_POOL]}" || true - fi - - if [ -d "$TEMP_DIR" ]; then - rm -r "$TEMP_DIR" - fi - - if [ ! "$DONE_FILE" = "" ]; then - touch "$DONE_FILE" - fi - sdwdate_log "$SCRIPTNAME (not timesync!): signal $SIGNAL_TYPE received. Exiting." -} - -sdwdate_signal_sigint() { - sdwdate_log "$SCRIPTNAME (not timesync!): signal SIGINT received..." - sdwdate_terminate_sclockadj - SIGNAL_TYPE="SIGINT" - sdwdate_ex_funct - exit 130 -} - -sdwdate_signal_sigterm() { - sdwdate_log "$SCRIPTNAME (not timesync!): signal SIGTERM received..." - sdwdate_terminate_sclockadj - SIGNAL_TYPE="SIGTERM" - sdwdate_ex_funct - exit 143 -} - -sdwdate_enable_debugging() { - ## usage: kill -sigusr1 pid - - if [ "$SDWDATE_DEBUG_TRACE_SET" ]; then - return 0 - fi - - set -x - - exec > >(tee -a "$LOG_FILE") - exec 2> >(tee -a "$LOG_FILE" >&2) - - set -o functrace - shopt -s extdebug - - #trap 'true "BASH_COMMAND: $BASH_COMMAND | FUNCNAME: ${FUNCNAME[1]} | BASH_LINENO: ${BASH_LINENO[0]} | BASH_SOURCE: ${BASH_SOURCE[1]}"' DEBUG - trap 'true "${FUNCNAME[1]}: $BASH_COMMAND"' DEBUG - - SDWDATE_DEBUG_TRACE_SET="1" -} - -sdwdate_signal_sigusr1() { - sdwdate_enable_debugging -} - -sdwdate_signal_sighup() { - SDW_MODE="sighup" -} - -sdwdate_pick_single_link_from_maybe_multi_lined_mirror_list() { - local maybe_multiple_lined_link number_lines_counter line - local line_without_spaces random_item_number number_lines random_line - maybe_multiple_lined_link="$@" - - ## {{ count lines without empty or lines with leading/trailing spaces. - number_lines_counter="0" - while read -r -d $'\n' line; do - line_without_spaces="${line// /}" - if [ "$line_without_spaces" = "" ]; then - ## Skipping empty or lines with leading/trailing spaces (such as '" '). - continue - fi - number_lines_counter="$(( $number_lines_counter + 1 ))" - done <<< "$maybe_multiple_lined_link" - ## }} - - ## {{ Generate random number between 1 (first line) and $number_lines_counter. - test -e "/dev/random" - random_item_number="$(shuf -i1-$number_lines_counter -n1 --random-source="/dev/random")" - ## }} - - ## {{ pick random line - number_lines="0" - while read -r -d $'\n' line; do - line_without_spaces="${line// /}" - if [ "$line_without_spaces" = "" ]; then - continue - fi - number_lines="$(( $number_lines + 1 ))" - if [ "$number_lines" = "$random_item_number" ]; then - true "link chosen $random_item_number / $number_lines_counter: $line" - random_line="$line" - break - fi - done <<< "$maybe_multiple_lined_link" - ## }} - - if [ "$random_line" = "" ]; then - sdwdate_error_handler "random_line was empty." - fi - - echo "$random_line" -} - -sdwdate_link_with_comments_to_processed_link() { - ## Example link_unprocessed: - ## atlas777hhh7mcs7.onion:80#Hosted by Thomas White. - - link_url_part="${link_unprocessed%"#"*}" - ## Examples link_url_part: - ## atlas777hhh7mcs7.onion:80 - ## atlas777hhh7mcs7.onion - link_comment_part="${link_unprocessed#*"#"}" - ## Example link_comment_part: - ## Hosted by Thomas White. - - if echo "$link_url_part" | grep -q ":" ; then - ## When link_url_part is for example: - ## atlas777hhh7mcs7.onion:80 - link_url="${link_url_part%":"*}" - link_port="${link_url_part#*":"}" - else - ## When link_url_part is for example: - ## atlas777hhh7mcs7.onion - link_url="$link_url_part" - link_port="80" - fi - - link_processed="${link_url}:${link_port}" - ## Example: - ## atlas777hhh7mcs7.onion:80 -} - -sdwdate_get_time_from_remote() { - sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]="0" - - local TIME_START - TIME_START="$(date +%s)" - - sdwdate_dispatcher "DISPATCH_PREREQUISITE" - - sdwdate_dispatcher "{SDWDATE_TIME_TOOL_DISPATCH_PRE[$SDWDATE_CURRENT_POOL]}" - - ## Sanity test. - touch "$TEMP_DIR/$SDWDATE_CURRENT_POOL" - rm "$TEMP_DIR/$SDWDATE_CURRENT_POOL" - touch "$TEMP_DIR/$SDWDATE_CURRENT_POOL.stderr" - rm "$TEMP_DIR/$SDWDATE_CURRENT_POOL.stderr" - - sdwdate_log "get : $link_processed | local time: $(date) | link_comment_part: $link_comment_part" - - timeout_after="180" - kill_after="10" - - ## Debugging. - #timeout_after="0.001" - #kill_after="0.001" - - timeout --kill-after="$kill_after" "$timeout_after" \ - "/usr/lib/sdwdate/url_to_unixtime" \ - "$PROXY_IP" \ - "$PROXY_PORT" \ - "$link_url" \ - "$link_port" \ - "false" \ - 1>"$TEMP_DIR/$SDWDATE_CURRENT_POOL" \ - 2>"$TEMP_DIR/$SDWDATE_CURRENT_POOL.stderr" \ - & - - SDWDATE_DOWNLOAD_TOOL_PID[$SDWDATE_CURRENT_POOL]="$!" - - sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]="0" - wait "${SDWDATE_DOWNLOAD_TOOL_PID[$SDWDATE_CURRENT_POOL]}" || { sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]="$?" ; true; }; - unset SDWDATE_DOWNLOAD_TOOL_PID[$SDWDATE_CURRENT_POOL] - - true "INFO: sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]: ${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]}" - - local TIME_END - TIME_END="$(date +%s)" - - true "SDWDATE_DOWNLOAD_TOOK_TIME[$SDWDATE_CURRENT_POOL]="\$\(\( $TIME_END - $TIME_START \)\)"" - SDWDATE_DOWNLOAD_TOOK_TIME[$SDWDATE_CURRENT_POOL]="$(( $TIME_END - $TIME_START ))" - - local stdout stderr - stdout="$(cat $TEMP_DIR/$SDWDATE_CURRENT_POOL)" || true - stderr="$(cat $TEMP_DIR/$SDWDATE_CURRENT_POOL.stderr)" || true - - if [ "${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]}" = "124" ]; then - sdwdate_log "result: $link_processed | local time: $(date) | status: failed | took: ${SDWDATE_DOWNLOAD_TOOK_TIME[$SDWDATE_CURRENT_POOL]}s | download_tool_exit_code: ${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]} | stdout: $stdout | stderr: $stderr | timeout_type: sigterm" - elif [ "${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]}" = "137" ]; then - sdwdate_log "result: $link_processed | local time: $(date) | status: failed | took: ${SDWDATE_DOWNLOAD_TOOK_TIME[$SDWDATE_CURRENT_POOL]}s | download_tool_exit_code: ${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]} | stdout: $stdout | stderr: $stderr | timeout_type: sigkill" - fi - - if [ ! "${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]}" = "0" ]; then - sdwdate_log "result: $link_processed | local time: $(date) | status: failed | took: ${SDWDATE_DOWNLOAD_TOOK_TIME[$SDWDATE_CURRENT_POOL]}s | download_tool_exit_code: ${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]} | stdout: $stdout | stderr: $stderr" - return 0 - fi - - test -f "$TEMP_DIR/$SDWDATE_CURRENT_POOL" - WEB_DATE_UNIXTIME="$stdout" - - local OLD_UNIXTIME - OLD_UNIXTIME="$(date +%s)" - - true "SDWDATE_TIME_DIFF[$SDWDATE_CURRENT_POOL]="\$\(\( $WEB_DATE_UNIXTIME - $OLD_UNIXTIME \)\)"" - SDWDATE_TIME_DIFF[$SDWDATE_CURRENT_POOL]="$(( $WEB_DATE_UNIXTIME - $OLD_UNIXTIME ))" - - sdwdate_log "result: $link_processed | local time: $(date) | status: success | took: ${SDWDATE_DOWNLOAD_TOOK_TIME[$SDWDATE_CURRENT_POOL]}s | diff: ${SDWDATE_TIME_DIFF[$SDWDATE_CURRENT_POOL]} second(s)" - - sdwdate_dispatcher "{SDWDATE_TIME_TOOL_DISPATCH_POST[$SDWDATE_CURRENT_POOL]}" - - return 0 -} - -sdwdate_loop() { - trap "sdwdate_error_handler" ERR - - eval "array=( - \"\${$SDWDATE_CURRENT_POOL[@]}\" - )" - - unset remember - declare -A -g remember - - while true; do - local array_length - array_length="${#array[@]}" - local array_length_remember - array_length_remember="${#remember[@]}" - - if [ "$array_length" = "0" ]; then - sdwdate_log "ERROR: $SDWDATE_CURRENT_POOL not configured!" - - ## Check, if we are running in daemon mode. - if [ "$INTERVAL" = "" ] || [ "$INTERVAL" = "0" ]; then - ## No daemon mode. - exit 1 - else - ## Daemon mode. - return 1 - fi - fi - - if [ "$array_length_remember" -ge "$array_length" ]; then - sdwdate_log "ERROR: No member of the $SDWDATE_CURRENT_POOL could be reached. (debugging information: array_length_remember: $array_length_remember | array_length: $array_length)" - - ## Check, if we are running in daemon mode. - if [ "$INTERVAL" = "" ] || [ "$INTERVAL" = "0" ]; then - ## No daemon mode. - exit 1 - else - ## Daemon mode. - return 1 - fi - fi - - local temp - temp="$(bc -l <<< "$array_length*$ALLOWED_PER_POOL_FAILURE_RATIO")" - ## adjust upward / downward - local allowed_member_failures - allowed_member_failures="$(/usr/bin/printf "%.f" "$temp")" - if [ "$allowed_member_failures" = "0" ]; then - allowed_member_failures="1" - fi - sdwdate_log "SDWDATE_CURRENT_POOL: $SDWDATE_CURRENT_POOL | array_length: $array_length | allowed_member_failures: $allowed_member_failures | temp: $temp | array_length_remember: $array_length_remember" - - if [ "$array_length_remember" -ge "$allowed_member_failures" ]; then - sdwdate_log "ERROR: $allowed_member_failures members of the $SDWDATE_CURRENT_POOL could not be reached. (debugging information: array_length_remember: $array_length_remember | allowed_member_failures: $allowed_member_failures)" - - ## Check, if we are running in daemon mode. - if [ "$INTERVAL" = "" ] || [ "$INTERVAL" = "0" ]; then - ## No daemon mode. - exit 1 - else - ## Daemon mode. - return 1 - fi - fi - - test -e "/dev/random" - local random_integer - random_integer="$(( ($(od -An -N2 -i "/dev/random") )%($array_length) ))" - - if [ "${remember[$random_integer]}" = "1" ]; then - continue - fi - - link_unprocessed="$(sdwdate_pick_single_link_from_maybe_multi_lined_mirror_list "${array[$random_integer]}")" - - ## sets: link_url_part - ## sets: link_comment_part - ## sets: link_url - ## sets: link_port - sdwdate_link_with_comments_to_processed_link "$link_unprocessed" - - ## sets: sdwdate_download_tool_exit_code - ## sets maybe: WEB_DATE_UNIXTIME - sdwdate_get_time_from_remote - - if [ ! "${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]}" = "0" ]; then - remember[$random_integer]=1 - continue - fi - - break - done - - unset remember - - return 0 -} - -sdwdate_pick() { - declare -A -g SDWDATE_RESULT - declare -A -g SDWDATE_TIME_DIFF - - for SDWDATE_CURRENT_POOL in SDWDATE_POOL_ONE SDWDATE_POOL_TWO SDWDATE_POOL_THREE; do - ## Temporarily disabling error handler. - ## Not using - ## || { sdwdate_loop_return="?"; true; }; - ## here, because then errors any errors caught in sdwdate_loop would be - ## ignored here. - trap "" ERR - sdwdate_loop "$SDWDATE_CURRENT_POOL" - sdwdate_loop_return="$?" - trap "sdwdate_error_handler" ERR - - ## Do not continue, if an error was caught. - if [ ! "$sdwdate_loop_return" = "0" ]; then - return 0 - fi - - SDWDATE_RESULT[$SDWDATE_CURRENT_POOL]="$WEB_DATE_UNIXTIME" - - true "INFO: SDWDATE_RESULT[$SDWDATE_CURRENT_POOL] = ${SDWDATE_RESULT[$SDWDATE_CURRENT_POOL]} | $(date --date "@${SDWDATE_RESULT[$SDWDATE_CURRENT_POOL]}")" - done -} - -sdwdate_build_median() { - local results results_list min max - results="${SDWDATE_TIME_DIFF[SDWDATE_POOL_ONE]} ${SDWDATE_TIME_DIFF[SDWDATE_POOL_TWO]} ${SDWDATE_TIME_DIFF[SDWDATE_POOL_THREE]}" - sdwdate_log "Results summary: \ -one: ${SDWDATE_TIME_DIFF[SDWDATE_POOL_ONE]} | \ -two: ${SDWDATE_TIME_DIFF[SDWDATE_POOL_TWO]} | \ -three: ${SDWDATE_TIME_DIFF[SDWDATE_POOL_THREE]} | \ -second(s)" - - ## Thanks to NotANumber - ## http://unix.stackexchange.com/a/93949 - results_list=( - $( - for item in $results; do - /usr/bin/printf "%d\n" "$item" - done | sort -n - ) - ) - min="${results_list[0]}" - max="${results_list[${#results_list[*]}-1]}" - SDWDATE_MEDIAN_TIME_SECONDS="${results_list[${#results_list[*]}/2]}" - - true "SDWDATE_MEDIAN_TIME_NANOSECONDS="\$\(\( $SDWDATE_MEDIAN_TIME_SECONDS \* 1000000000 \)\)"" - SDWDATE_MEDIAN_TIME_NANOSECONDS="$(( $SDWDATE_MEDIAN_TIME_SECONDS * 1000000000 ))" - - sdwdate_log "Min: $min | Max: $max | Median diff: $SDWDATE_MEDIAN_TIME_SECONDS second(s) [$SDWDATE_MEDIAN_TIME_NANOSECONDS nanosecond(s)]" - - local OLD_UNIXTIME - OLD_UNIXTIME="$(date +%s)" - true "NEW_UNIXTIME="\$\(\( $OLD_UNIXTIME + $SDWDATE_MEDIAN_TIME_SECONDS \)\)"" - NEW_UNIXTIME="$(( $OLD_UNIXTIME + $SDWDATE_MEDIAN_TIME_SECONDS ))" - - sdwdate_log "local unixtime : $(date +%s) | local time : $(date)" - sdwdate_log "remote unixtime: $NEW_UNIXTIME | remote time: $(date --date @${NEW_UNIXTIME})" - - if [ "$ECHO_UNIX_TIME" = "true" ]; then - echo "$NEW_UNIXTIME" - fi -} - -sdwdate_generate_nanoseconds() { - local ZERO_OR_ONE - ## Get a random 0 or 1. - ## Will use this to decide to use plus or minus. - ## - ## Thanks to - ## http://linux.byexamples.com/archives/128/generating-random-numbers/ - test -e "/dev/random" - ZERO_OR_ONE="$(( 0+($(od -An -N2 -i "/dev/random") )%(0+2) ))" - - if [ "$ZERO_OR_ONE" = "0" ]; then - NANOSECONDS_PLUS_OR_MINUS="-" - elif [ "$ZERO_OR_ONE" = "1" ]; then - NANOSECONDS_PLUS_OR_MINUS="+" - else - sdwdate_error_handler "ZERO_OR_ONE is neither 0 nor 1, it's: $ZERO_OR_ONE" || true - fi - - ## Create a random number between 0 and 999999999. - ## - ## Thanks to - ## https://stackoverflow.com/questions/22887891/how-can-i-get-a-random-dev-random-number-between-0-and-999999999-in-bash - test -e "/dev/random" - NANOSECONDS="$(shuf -i0-999999999 -n1 --random-source="/dev/random")" - - local extra_seconds_without_leading_zero extra_seconds - extra_seconds_without_leading_zero="$(bc -l <<< "scale=9 ; $NANOSECONDS / 1000000000")" - extra_seconds="$(printf '%3.9f\n' "$extra_seconds_without_leading_zero")" - - sdwdate_log "Made up random extra: ${NANOSECONDS_PLUS_OR_MINUS}${extra_seconds} second[s] [${NANOSECONDS_PLUS_OR_MINUS}${NANOSECONDS} nanosecond(s)]." -} - -sdwdate_log_time_before_setting_time() { - local SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_BEFORE_SETTING - SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_BEFORE_SETTING="$(date +%s.%N)" - local SDWDATE_NEW_DATE_BEFORE_SETTING - SDWDATE_NEW_DATE_BEFORE_SETTING="$(date)" - sdwdate_log "Time before setting: $SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_BEFORE_SETTING [$SDWDATE_NEW_DATE_BEFORE_SETTING]" -} - -sdwdate_log_time_after_setting_time() { - local SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_AFTER_SETTING - SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_AFTER_SETTING="$(date +%s.%N)" - local SDWDATE_NEW_DATE_AFTER_SETTING - SDWDATE_NEW_DATE_AFTER_SETTING="$(date)" - sdwdate_log "Time after setting using: $SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_AFTER_SETTING [$SDWDATE_NEW_DATE_AFTER_SETTING]" -} - -sdwdate_set_time_using_date() { - ## sets: NANOSECONDS - ## sets: NANOSECONDS_PLUS_OR_MINUS - sdwdate_generate_nanoseconds - - sdwdate_log_time_before_setting_time - - ## sets: SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL - sdwdate_get_move_time_nanoseonds_total - - local NEW_UNIXTIME_WITH_NANOSECONDS - NEW_UNIXTIME_WITH_NANOSECONDS="${NEW_UNIXTIME}000000000" - - local SDWDATE_MOVE_TIME_UNIXTIME_WITH_NANOSECONDS - true "SDWDATE_MOVE_TIME_UNIXTIME_WITH_NANOSECONDS="\$\(\( $NEW_UNIXTIME_WITH_NANOSECONDS $NANOSECONDS_PLUS_OR_MINUS $NANOSECONDS \)\)"" - SDWDATE_MOVE_TIME_UNIXTIME_WITH_NANOSECONDS="$(( $NEW_UNIXTIME_WITH_NANOSECONDS $NANOSECONDS_PLUS_OR_MINUS $NANOSECONDS ))" - - ## {{ SDWDATE_NEW_TIME_FORMATTED_FOR_DATE - - local first_ten last_nine first_ten_string_length last_nine_string_length - - ## unixtime - first_ten="${SDWDATE_MOVE_TIME_UNIXTIME_WITH_NANOSECONDS:0:10}" - - ## nanoseconds - last_nine="${SDWDATE_MOVE_TIME_UNIXTIME_WITH_NANOSECONDS:10:19}" - - first_ten_string_length="${#first_ten}" - last_nine_string_length="${#last_nine}" - - if [ ! "$first_ten_string_length" = "10" ]; then - sdwdate_error_handler "$FUNCNAME: first_ten: $first_ten | first_ten_string_length: $first_ten_string_length" || true - fi - - if [ ! "$last_nine_string_length" = "9" ]; then - sdwdate_error_handler "$FUNCNAME: last_nine: $last_nine | last_nine_string_length: $last_nine_string_length" || true - fi - - local SDWDATE_NEW_TIME_FORMATTED_FOR_DATE - ## unixtime.nanoseconds - SDWDATE_NEW_TIME_FORMATTED_FOR_DATE="$first_ten.$last_nine" - - ## Example SDWDATE_NEW_TIME_FORMATTED_FOR_DATE: - ## 1405043428.773182656 - - ## }} SDWDATE_NEW_TIME_FORMATTED_FOR_DATE - - sdwdate_log "Setting time using \`date\` to $SDWDATE_NEW_TIME_FORMATTED_FOR_DATE..." - - ## Set new time. Syntax: date --set @1396733199.112834496 - ## There is an exception in /etc/sudoers.d/sdwdate. - sudo /bin/date --set "@${SDWDATE_NEW_TIME_FORMATTED_FOR_DATE}" > /dev/null - - sdwdate_log_time_after_setting_time - - if [ "$SYSTOHC" = "1" ]; then - sudo /sbin/hwclock --systohc - fi -} - -sdwdate_terminate_sclockadj() { - if [ "$SDWDATE_SUBSHELL_SCLOCKADJ_PID" = "" ]; then - return 0 - fi - - local pid_still_running SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE - SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE="0" - pid_still_running="0" - kill -0 "$SDWDATE_SUBSHELL_SCLOCKADJ_PID" || { pid_still_running="$?" ; true; }; - - if [ "$pid_still_running" = "0" ]; then - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID still running. Terminating..." - kill -sigterm "$SDWDATE_SUBSHELL_SCLOCKADJ_PID" || true - wait "$SDWDATE_SUBSHELL_SCLOCKADJ_PID" || { SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE="$?" ; true; }; - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID Terminated. Exit code: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - else - wait "$SDWDATE_SUBSHELL_SCLOCKADJ_PID" || { SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE="$?" ; true; }; - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID no longer running. Exit code: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - fi - - ## Not required. - ## Done by function sdwdate_subshell_time_end. - #sdwdate_log_time_after_setting_time - - if [ "$SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" = "0" ]; then - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID exited with expected zero exit code: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - elif [ "$SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" = "130" ]; then - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID exited with expected non-zero exit code (sigint): $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - elif [ "$SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" = "143" ]; then - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID exited with expected non-zero exit code (sigterm): $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - else - sdwdate_log "$FUNCNAME: subshell for sclockadj with pid $SDWDATE_SUBSHELL_SCLOCKADJ_PID exited with unexpected non-zero exit code: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - SDWDATE_SUBSHELL_SCLOCKADJ_PID="" - ## Not using sdwdate_error_handler to prevent and endless loop. - sdwdate_error "$FUNCNAME: subshell for sclockadj exited with unexpected non-zero exit code: $SDWDATE_SUBSHELL_SCLOCKADJ_EXIT_CODE" - fi - SDWDATE_SUBSHELL_SCLOCKADJ_PID="" -} - -sdwdate_get_move_time_nanoseonds_total() { - local SDWDATE_MOVE_TIME_SECONDS_TOTAL first_char - - true "SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL="\$\(\( $SDWDATE_MEDIAN_TIME_NANOSECONDS $NANOSECONDS_PLUS_OR_MINUS $NANOSECONDS \)\)"" - SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL="$(( $SDWDATE_MEDIAN_TIME_NANOSECONDS $NANOSECONDS_PLUS_OR_MINUS $NANOSECONDS ))" - - SDWDATE_MOVE_TIME_SECONDS_TOTAL="$(bc -l <<< "scale=2 ; $SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL / 1000000000")" - SDWDATE_MOVE_TIME_SECONDS_TOTAL="$(printf '%.2f\n' "$SDWDATE_MOVE_TIME_SECONDS_TOTAL")" - - first_char=${SDWDATE_MOVE_TIME_SECONDS_TOTAL::1} - if [ ! "$first_char" = "-" ]; then - SDWDATE_MOVE_TIME_SECONDS_TOTAL="+$SDWDATE_MOVE_TIME_SECONDS_TOTAL" - fi - - sdwdate_log "require time change: $SDWDATE_MOVE_TIME_SECONDS_TOTAL second(s) [$SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL nanosecond(s)]" -} - -sdwdate_set_time_using_sclockadj() { - ## sets: NANOSECONDS - ## sets: NANOSECONDS_PLUS_OR_MINUS - sdwdate_generate_nanoseconds - - ## Not required. - ## Done by function sdwdate_subshell_time_start. - #sdwdate_log_time_before_setting_time - - ## sets: SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL - sdwdate_get_move_time_nanoseonds_total - - local first_char - first_char=${SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL::1} - - local sclockadj_add_or_subtract - if [ "$first_char" = "-" ]; then - local SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL_WITHOUT_SIGN - SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL_WITHOUT_SIGN="${SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL#?}" - sclockadj_add_or_subtract="--subtract $SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL_WITHOUT_SIGN" - else - sclockadj_add_or_subtract="--add $SDWDATE_MOVE_TIME_NANOSECONDS_TOTAL" - fi - - ## Setting the INLINEDIR environment variable for ruby-inline, that requires - ## a non-group writeable cache dir. - - local SDWDATE_SCLOCKADJ_COMMAND - ## There is an exception in /etc/sudoers.d/. - SDWDATE_SCLOCKADJ_COMMAND="\ - sudo \ - INLINEDIR=$SDW_CACHE_DIR \ - /usr/lib/sdwdate/sclockadj \ - $SDWDATE_SCLOCKADJ_VERBOSE \ - $SDWDATE_SCLOCKADJ_CHANGE_DATE \ - $SDWDATE_SCLOCKADJ_FIRST_WAIT \ - $SDWDATE_SCLOCKADJ_SYSTOHC \ - --move-min $SDWDATE_SCLOCKADJ_MOVE_MIN \ - --move-max $SDWDATE_SCLOCKADJ_MOVE_MAX \ - --wait-min $SDWDATE_SCLOCKADJ_WAIT_MIN \ - --wait-max $SDWDATE_SCLOCKADJ_WAIT_MAX \ - $sclockadj_add_or_subtract \ - " - - sdwdate_log "Launching into background: $SDWDATE_SCLOCKADJ_COMMAND" - - sclockadj_subshell_fifo="$TEMP_DIR/sclockadj.sclockadj_subshell_fifo" - rm --force "$sclockadj_subshell_fifo" - mkfifo "$sclockadj_subshell_fifo" - test -r "$sclockadj_subshell_fifo" - - { - sdwdate_subshell_time_start() { - SDWDATE_SUBSHELL_SCLOCKADJ_TIME_START="$(date +%s)" - local SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_BEFORE_SETTING - SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_BEFORE_SETTING="$(date +%s.%N)" - local SDWDATE_NEW_DATE_BEFORE_SETTING - SDWDATE_NEW_DATE_BEFORE_SETTING="$(date)" - echo "$FUNCNAME: Time before running sclockadj: $SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_BEFORE_SETTING [$SDWDATE_NEW_DATE_BEFORE_SETTING]" - } - - sdwdate_subshell_time_end() { - SDWDATE_SUBSHELL_SCLOCKADJ_TIME_END="$(date +%s)" - true "SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_SECONDS="\$\(\( $SDWDATE_SUBSHELL_SCLOCKADJ_TIME_END - $SDWDATE_SUBSHELL_SCLOCKADJ_TIME_START \)\)"" - SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_SECONDS="$(( $SDWDATE_SUBSHELL_SCLOCKADJ_TIME_END - $SDWDATE_SUBSHELL_SCLOCKADJ_TIME_START ))" - SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_MINUTES="$(bc -l <<< "scale=2 ; $SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_SECONDS / 60")" - SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_HOURS="$(bc -l <<< "scale=2 ; $SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_MINUTES / 60")" - ## Add leading zero. - SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_MINUTES="$(printf '%.2f\n' "$SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_MINUTES")" - SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_HOURS="$(printf '%.2f\n' "$SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_HOURS")" - echo "$FUNCNAME: was running for $SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_SECONDS s [~ $SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_MINUTES min] \ -[~ $SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_HOURS h]." - unset SDWDATE_SUBSHELL_SCLOCKADJ_TIME_START - unset SDWDATE_SUBSHELL_SCLOCKADJ_TIME_END - unset SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_SECONDS - unset SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_MINUTES - unset SDWDATE_SUBSHELL_SCLOCKADJ_TOOK_TIME_HOURS - local SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_AFTER_SETTING - SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_AFTER_SETTING="$(date +%s.%N)" - local SDWDATE_NEW_DATE_AFTER_SETTING - SDWDATE_NEW_DATE_AFTER_SETTING="$(date)" - echo "$FUNCNAME: Time after running sclockadj: $SDWDATE_NEW_UNIXTIME_AND_NANOSECONDS_AFTER_SETTING [$SDWDATE_NEW_DATE_AFTER_SETTING]" - } - - sdwdate_subshell_wait() { - echo "$FUNCNAME: Waiting for pid to finish SDWDATE_SCLOCKADJ_COMMAND_PID: $SDWDATE_SCLOCKADJ_COMMAND_PID" - SDWDATE_SCLOCKADJ_COMMAND_EXIT_CODE="0" - wait "$SDWDATE_SCLOCKADJ_COMMAND_PID" || { SDWDATE_SCLOCKADJ_COMMAND_EXIT_CODE="$?" ; true; }; - echo "$FUNCNAME: SDWDATE_SCLOCKADJ_COMMAND_PID: $SDWDATE_SCLOCKADJ_COMMAND_PID | SDWDATE_SCLOCKADJ_COMMAND_EXIT_CODE: $SDWDATE_SCLOCKADJ_COMMAND_EXIT_CODE" - } - - sdwdate_subshell_trap_sigterm() { - echo "$FUNCNAME: SIGTERM received." - ## Interrupted sdwdate_subshell_wait. - if [ "$SDWDATE_SCLOCKADJ_COMMAND_PID" = "" ]; then - return 0 - fi - ## There is a /etc/sudoers.d exception. - echo "$FUNCNAME: executing: sudo /usr/lib/sdwdate/sclockadj_kill_helper $SDWDATE_SCLOCKADJ_COMMAND_PID" - sclockadj_kill_helper_output="$(sudo /usr/lib/sdwdate/sclockadj_kill_helper "$SDWDATE_SCLOCKADJ_COMMAND_PID" 2>&1)" - echo "$FUNCNAME: sclockadj_kill_helper_output: $sclockadj_kill_helper_output" - unset sclockadj_kill_helper_output - } - - sdwdate_subshell_exit() { - echo "exit code: $SDWDATE_SCLOCKADJ_COMMAND_EXIT_CODE" - exit "$SDWDATE_SCLOCKADJ_COMMAND_EXIT_CODE" - } - - sdwdate_subshell_main() { - ## There is a /etc/sudoers.d exception. - #sudo /usr/lib/sdwdate/sclockadj_debug_helper || true - sdwdate_subshell_time_start - $SDWDATE_SCLOCKADJ_COMMAND 2>&1 & - SDWDATE_SCLOCKADJ_COMMAND_PID="$!" - sdwdate_subshell_wait ## Might get interrupted by signal sigterm. - sdwdate_subshell_time_end - sdwdate_subshell_exit - } - - trap "sdwdate_subshell_trap_sigterm" SIGTERM - - sdwdate_subshell_main - } > "$sclockadj_subshell_fifo" 2>&1 & - - SDWDATE_SUBSHELL_SCLOCKADJ_PID="$!" - sdwdate_log "Started subshell for sclockadj with pid: $SDWDATE_SUBSHELL_SCLOCKADJ_PID" - - { - sdwdate_log "sdwdate_subshell_read: start" - while read -r sclockadj_line; do - sdwdate_log "sdwdate_subshell_read: sclockadj reports: $sclockadj_line" - done < "$sclockadj_subshell_fifo" - sdwdate_log "sdwdate_subshell_read: end" - } & -} - -sdwdate_maybe_set_new_time() { - if [ "$DONT_SET_DATE" = "1" ]; then - return 0 - fi - - ## Do not needlessly try to change time, when there is no difference. - if [ "$SDWDATE_MEDIAN_TIME_SECONDS" = "0" ]; then - sdwdate_log "require time change: 0 second(s) [0 nanosecond(s)]" - sdwdate_log "No need to set clock." - return 0 - fi - - if [ "$NO_MOVE_FORWARD" = "1" ]; then - if [ "$SDWDATE_MEDIAN_TIME_SECONDS" -gt "0" ]; then - sdwdate_log "Not setting clock forward." - return 0 - fi - fi - - if [ "$NO_MOVE_BACKWARDS" = "1" ]; then - if [ "$SDWDATE_MEDIAN_TIME_SECONDS" -lt "0" ]; then - sdwdate_log "Not setting clock backwards." - return 0 - fi - fi - - if [ "$SDW_MODE" = "startup" ]; then - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_STARTUP" = "1" ]; then - sdwdate_set_time_using_sclockadj - else - sdwdate_set_time_using_date - fi - elif [ "$SDW_MODE" = "restartup" ]; then - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_RESTARTUP" = "1" ]; then - sdwdate_set_time_using_sclockadj - else - sdwdate_set_time_using_date - fi - elif [ "$SDW_MODE" = "sighup" ]; then - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_RESTARTUP" = "1" ]; then - sdwdate_set_time_using_sclockadj - else - sdwdate_set_time_using_date - fi - elif [ "$SDW_MODE" = "daemon" ]; then - if [ "$SDWDATE_USE_SCLOCKADJ_WHEN_DAEMON" = "1" ]; then - sdwdate_set_time_using_sclockadj - else - sdwdate_set_time_using_date - fi - else - sdwdate_error_handler 'Invalid SDW_MODE.' - fi -} - -sdwdate_failed() { - rm --force "$SUCCESS_FILE" - touch "$DONE_FILE" -} - -sdwdate_success() { - touch "$FIRST_SUCCESS_FILE" - touch "$SUCCESS_FILE" - touch "$DONE_FILE" -} - -sdwdate_dispatcher() { - local dispatcher_variable_name dispatcher_variable_content - - dispatcher_variable_name="$1" - dispatcher_variable_content="$(eval echo \"\$"$dispatcher_variable_name"\")" - - if [ "$dispatcher_variable_content" = "" ]; then - sdwdate_log "$dispatcher_variable_name dispatcher_variable_content is empty, skipping." - return 0 - fi - - if [ "$dispatcher_variable_name" = "DISPATCH_PREREQUISITE" ]; then - while true; do - sdwdate_no_duplicate_log "dispatching $dispatcher_variable_name (SDW_MODE: $SDW_MODE) (LD_PRELOAD: $LD_PRELOAD): $DISPATCH_PREREQUISITE" - - local prerequisite_exit_code - prerequisite_exit_code="0" - prerequisite_output="$(eval $dispatcher_variable_content 2>&1)" || { prerequisite_exit_code="${PIPESTATUS[0]}" ; true; }; - - true "prerequisite_exit_code: $prerequisite_exit_code" - true "prerequisite_output: $prerequisite_output" - - if [ "$prerequisite_exit_code" = "0" ]; then - ## Ok. - sdwdate_log "$dispatcher_variable_name exited $prerequisite_exit_code, continuing..." - break - elif [ "$prerequisite_exit_code" = "1" ]; then - ## Error. - sdwdate_error_handler "$dispatcher_variable_name exited $prerequisite_exit_code | $prerequisite_output | requested explicit exiting..." || true - elif [ "$prerequisite_exit_code" = "2" ]; then - ## Wait. - sdwdate_no_duplicate_log "$dispatcher_variable_name exited $prerequisite_exit_code | $prerequisite_output | waiting..." - sleep 10 & - sleep_pid="$!" - wait "$sleep_pid" || true - unset sleep_pid - else - ## Unexpected error. - sdwdate_error_handler "$dispatcher_variable_name exited $DISPATCH_PREREQUISITE, neither 0, 1, or 2. | $prerequisite_output | unexpected error, exiting..." || true - fi - done - return 0 - fi - - sdwdate_log "dispatching $dispatcher_variable_name (SDW_MODE: $SDW_MODE): $dispatcher_variable_content" - - if [ "$dispatcher_variable_name" = "DISPATCH_POST_ERROR" ]; then - sdwdate_log "SDW_EXIT_ON_ERROR: $SDW_EXIT_ON_ERROR" || true - eval_output="$(eval $dispatcher_variable_content 2>&1)" || true - #eval_output="$(eval bash -x $dispatcher_variable_content 2>&1)" || true - #sdwdate_write_log "eval_output: $eval_output" || true - sdwdate_log "dispatching $dispatcher_variable_name done." || true - else - eval_output="$(eval $dispatcher_variable_content 2>&1)" - #eval_output="$(eval bash -x $dispatcher_variable_content 2>&1)" - #sdwdate_write_log "eval_output: $eval_output" - sdwdate_log "dispatching $dispatcher_variable_name done." - fi -} - -sdwdate_error_test() { - if [ -f "/var/lib/sdw_error" ]; then - sdwdate_error_handler "Test file /var/lib/sdw_error to force test an error exists." || true - sleep 10 & - sleep_pid="$!" - wait "$sleep_pid" || true - unset sleep_pid - fi -} - -sdwdate_sleep() { - ## INTERVAL: in minutes - ## sleep: in seconds - - local minutes - if [ "$RANDOMIZE" = "1" ]; then - test -e "/dev/random" - minutes="$(( ($(od -An -N2 -i "/dev/random") )%($INTERVAL) ))" - if [ "$MIN_INTERVAL" -ge "$minutes" ]; then - true "minutes="\$\(\( $minutes + $MIN_INTERVAL \)\)"" - minutes="$(( $minutes + $MIN_INTERVAL ))" - fi - else - minutes="$INTERVAL" - fi - - local seconds - true "seconds="\$\(\( $minutes \* 60 \)\)"" - seconds="$(( $minutes * 60 ))" - - sdwdate_log "Sleeping for $minutes minutes. (RANDOMIZE: $RANDOMIZE)" - - sleep "$seconds" & - sleep_pid="$!" - wait "$sleep_pid" || true - unset sleep_pid -} - -sdwdate_maybe_read_config_folder() { - local grep_exit_code - grep_exit_code="$?" - echo "${1+"$@"}" | grep --quiet "\-\-noconfig" || { grep_exit_code="$?" ; true; }; - if [ "$grep_exit_code" = "0" ]; then - true "Found --noconfig, skip reading config folder." - else - ## Not found, let's read config folder. - sdwdate_read_config_folder - fi -} - -sdwdate_maybe_parse_cmd_options() { - if [ "$PARSE_CMD_ONLY_ON_STARTUP" = "1" ]; then - if [ "$ALREADY_PARSED_CDM_ON_STARTUP" = "1" ]; then - true "ALREADY_PARSED_CDM_ON_STARTUP is 1, not parsing cmd options again." - else - ALREADY_PARSED_CDM_ON_STARTUP="1" - sdwdate_parse_cmd_options - fi - else - sdwdate_parse_cmd_options ${1+"$@"} - fi -} - -sdwdate_maybe_sleep_or_exit() { - ## Check, if we are running in daemon mode. - if [ "$INTERVAL" = "" ] || [ "$INTERVAL" = "0" ]; then - ## No daemon mode. - exit 0 - else - ## Daemon mode. - SDW_MODE="daemon" - sdwdate_sleep - fi -} - -sdwdate_main() { - sdwdate_sanity_tests - - while true; do - sdwdate_maybe_read_config_folder ${1+"$@"} - sdwdate_maybe_parse_cmd_options ${1+"$@"} - sdwdate_defaults - sdwdate_log "Running sdwdate... pid: $$ | LD_PRELOAD: $LD_PRELOAD" - sdwdate_preparation - if [ "$DEBUG" = "1" ]; then - sdwdate_enable_debugging - fi - - sdwdate_terminate_sclockadj - - sdwdate_error_test - - sdwdate_dispatcher "DISPATCH_PRE" - - sdwdate_pick - - ## Do not continue, if an error was caught. - if [ ! "$sdwdate_loop_return" = "0" ]; then - sdwdate_failed - sdwdate_dispatcher "DISPATCH_POST_FAILURE" - else - sdwdate_build_median - sdwdate_maybe_set_new_time - sdwdate_success - sdwdate_dispatcher "DISPATCH_POST_SUCCESS" - fi - - sdwdate_maybe_sleep_or_exit - done -} diff --git a/usr/lib/sdwdate/url_to_unixtime b/usr/lib/sdwdate/url_to_unixtime index bb95dabb..277c71ba 100755 --- a/usr/lib/sdwdate/url_to_unixtime +++ b/usr/lib/sdwdate/url_to_unixtime @@ -12,8 +12,12 @@ import sys, socks from dateutil.parser import parse +import re # Test def data_to_date_string_start_position(data): + ## Test ######################## + #data = re.sub('Date', 'Rate', data) + ################################ date_string_start_position = data.find('Date:') if date_string_start_position == -1: @@ -22,9 +26,9 @@ def data_to_date_string_start_position(data): if date_string_start_position == -1: ## "Date:" not found. - print >> sys.stderr, 'Parsing HTTP header date failed.' - print >> sys.stderr, 'HTTP header data:\n%s' % (data) - sys.exit(3) + print 'Parsing HTTP header date failed.' + print 'HTTP header data:\n%s' % (data) + sys.exit() date_string_start_position = date_string_start_position + 6 return date_string_start_position @@ -33,17 +37,22 @@ def data_to_http_time(data, date_string_start_position): http_time = '' ## max accepted string length. http_time = data[date_string_start_position:date_string_start_position + 29].strip() - + ## Test ################### + #http_time = http_time[:28] + ########################### http_time_string_length = len(http_time) ## min string length = max string length. if http_time_string_length < 29: - print >> sys.stderr, 'HTTP header date string too short.' - print >> sys.stderr, 'HTTP header date length: %s' % http_time_string_length - print >> sys.stderr, 'HTTP header data:\n%s' % (data) - print >> sys.stderr, 'HTTP header date value: "%s"' % (http_time) - sys.exit(4) - + print 'HTTP header date string too short.' + print 'HTTP header date length: %s' % http_time_string_length + print 'HTTP header data:\n%s' % (data) + print 'HTTP header date value: "%s"' % (http_time) + sys.exit() + + ## Test, replace current hour with 30 ####### + #http_time = re.sub('11', '30', http_time) + ############################################# return http_time def unixtime_sanity_check(data, http_time, parsed_unixtime): @@ -51,26 +60,27 @@ def unixtime_sanity_check(data, http_time, parsed_unixtime): unixtime_digit = int(parsed_unixtime) except ValueError as e: - print >> sys.stderr, 'parsed_unixtime conversion failed!' - print >> sys.stderr, 'data: %s' % (data) - print >> sys.stderr, 'http_time: %s' % (http_time) - print >> sys.stderr, 'parsed_unixtime: %s' % (parsed_unixtime) - print >> sys.stderr, 'parsed_unixtime not numeric!' - sys.exit(6) + print 'parsed_unixtime conversion failed!' + print 'data: %s' % (data) + print 'http_time: %s' % (http_time) + print 'parsed_unixtime: %s' % (parsed_unixtime) + print 'parsed_unixtime not numeric!' + sys.exit() unixtime_string_length_is = len(parsed_unixtime) unixtime_string_length_max = 10 if unixtime_string_length_is > unixtime_string_length_max: - print >> sys.stderr, 'parsed_unixtime conversion failed!' - print >> sys.stderr, 'data: %s' % (data) - print >> sys.stderr, 'http_time: %s' % (http_time) - print >> sys.stderr, 'parsed_unixtime: %s' % (parsed_unixtime) - print >> sys.stderr, 'unixtime_string_length_is: %s' % (unixtime_string_length_is) - print >> sys.stderr, 'unixtime_string_length_max: %s' % (unixtime_string_length_max) - print >> sys.stderr, 'parsed_unixtime has excessive string length!' - sys.exit(7) - + print 'parsed_unixtime conversion failed!' + print 'data: %s' % (data) + print 'http_time: %s' % (http_time) + print 'parsed_unixtime: %s' % (parsed_unixtime) + print 'unixtime_string_length_is: %s' % (unixtime_string_length_is) + print 'unixtime_string_length_max: %s' % (unixtime_string_length_max) + print 'parsed_unixtime has excessive string length!' + sys.exit() + + #print >> sys.stderr, parsed_unixtime return parsed_unixtime def request_data_from_remote_server(socket_ip, socket_port, url, remote_port): @@ -81,13 +91,8 @@ def request_data_from_remote_server(socket_ip, socket_port, url, remote_port): s.connect((url, remote_port)) except Exception as e: - ## {{ wheezy compatibility - if str(e).startswith('__init__'): - print >> sys.stderr, 'connect error: URL "%s" not found.' % url - else: - ## }} - print >> sys.stderr, 'connect error: %s' % (e) - sys.exit(2) + print 'connect error: %s' % (e) + sys.exit() s.send('HEAD / HTTP/1.0\r\n\r\n') @@ -108,12 +113,16 @@ def http_time_to_parsed_unixtime(data, http_time): parsed_unixtime = parse(http_time).strftime('%s') except ValueError as e: - print >> sys.stderr, 'Parsing http_time from server failed!' - print >> sys.stderr, 'HTTP header data:\n%s' % (data) - print >> sys.stderr, 'http_time: %s' % (http_time) - print >> sys.stderr, 'dateutil ValueError: %s' % (e) - sys.exit(5) - + print 'Parsing http_time from server failed!' + print 'HTTP header data:\n%s' % (data) + print 'http_time: %s' % (http_time) + print 'dateutil ValueError: %s' % (e) + sys.exit() + + ## Tests ################################# + #parsed_unixtime = '%sA' % parsed_unixtime + #parsed_unixtime = '%s1' % parsed_unixtime + ########################################## return(parsed_unixtime) def parse_command_line_parameters(): @@ -125,17 +134,17 @@ def parse_command_line_parameters(): verbosity = sys.argv[5] except (IndexError) as e: - print >> sys.stderr, "Parsing command line parameter failed. | e: %s" % (e) - sys.exit(1) + print "Parsing command line parameter failed. | e: %s" % (e) + sys.exit() return(socket_ip, socket_port, url, remote_port, verbosity) def output_unixtime(data, http_time, parsed_unixtime, unixtime, verbosity): if verbosity == "true": - print >> sys.stderr, 'data: %s' % (data) - print >> sys.stderr, 'http_time: %s' % (http_time) - print >> sys.stderr, 'parsed_unixtime: %s' % (parsed_unixtime) - print "%s" % unixtime + print 'data: %s' % (data) + print 'http_time: %s' % (http_time) + print 'parsed_unixtime: %s' % (parsed_unixtime) + print '%s' % unixtime def main(): socket_ip, socket_port, url, remote_port, verbosity = parse_command_line_parameters() diff --git a/usr/lib/tmpfiles.d/sdwdate.conf b/usr/lib/tmpfiles.d/sdwdate.conf index 31832d73..db98265f 100644 --- a/usr/lib/tmpfiles.d/sdwdate.conf +++ b/usr/lib/tmpfiles.d/sdwdate.conf @@ -4,3 +4,4 @@ d /var/run/sdwdate 0775 sdwdate sdwdate f /var/log/sdwdate.log 0775 sdwdate sdwdate + diff --git a/usr/share/sdwdate/unit_test b/usr/share/sdwdate/unit_test index b2ecf702..4c73cba0 100755 --- a/usr/share/sdwdate/unit_test +++ b/usr/share/sdwdate/unit_test @@ -1,109 +1,40 @@ -#!/bin/bash +#!/usr/bin/env python + +import time +from sdwdate.remote_times import get_time_from_servers +from sdwdate.config import read_pools +from sdwdate.proxy_settings import proxy_settings + + +class Pool: + def __init__(self, pool): + self.urls, self.comments = read_pools(pool, 'test') + + +class CheckRemotes: + def __init__(self): + self.number_of_pools = 3 + self.pools = [Pool(pool) for pool in range(self.number_of_pools)] + self.urls = [] + self.returned_values = [] + self.proxy_ip, self.proxy_port = proxy_settings() + + def loop(self): + time_stamp = str(int(time.time())) + file_name = 'sdwate_remotes_check-%s' % (time_stamp) + f = open(file_name, 'a') + print 'Starting remotes check...' + for pool in self.pools: + self.urls, self.returned_values = get_time_from_servers(pool.urls, + self.proxy_ip, + self.proxy_port) + for url in range(len(self.urls)): + msg = 'pool %s url %s: %s' % (self.pools.index(pool) + 1, self.urls[url], self.returned_values[url]) + print msg + f.write('%s\n' % msg) + f.close() + +if __name__ == '__main__': + remotes = CheckRemotes() + remotes.loop() -#set -x - -echo "-------------------- Start Unit Test --------------------" - -set -e -set -o pipefail -set -o errtrace - -echo "-------------------- Begin Sourcing --------------------" - -for i in /usr/lib/sdwdate/modules.d/* /etc/sdwdate.d/*; do - if [ -f "$i" ]; then - ## If the last character is a ~, ignore that file, - ## because it was created by some editor, - ## which creates backup files. - if [ "${i: -1}" = "~" ]; then - continue - fi - ## Skipping files such as .dpkg-old and .dpkg-dist. - if ( echo "$i" | grep -q ".dpkg-" ); then - true "skip $i" - continue - fi - bash -n "$i" - source "$i" - fi -done - -echo "-------------------- End Sourcing --------------------" - -echo "-------------------- Begin Setup for Unit Test --------------------" - -sdwdate_error_handler() { - local exit_code="$?" - local error_cause error_text - error_text="$1" - if [ "$error_text" = "" ]; then - error_cause="$FUNCNAME signal ERR detected with BASH_COMMAND: -$BASH_COMMAND" - else - error_cause="$FUNCNAME called with error_text: -$error_text" - fi - exit 1 -} - -trap "sdwdate_error_handler" ERR - -sdwdate_log() { - true "$FUNCNAME (unit test): $@" -} - -sdwdate_no_duplicate_log() { - true "$FUNCNAME (unit test): $@" -} - -echo "-------------------- End Setup for Unit Test --------------------" - -echo "-------------------- Begin Unit Test 1 --------------------" - -download_unit_test() { - echo "-------------------- -------------------- --------------------" - - #sdwdate_defaults - - TEMP_DIR="/tmp/test" - SDWDATE_CURRENT_POOL="testpool" - mkdir --parents "$TEMP_DIR" - touch "$TEMP_DIR/$SDWDATE_CURRENT_POOL" - - declare -A -g sdwdate_download_tool_exit_code - declare -A -g SDWDATE_DOWNLOAD_TOOL_PID - declare -A -g SDWDATE_DOWNLOAD_TOOK_TIME - - for element in "${SDWDATE_POOL_ONE[@]}" "${SDWDATE_POOL_TWO[@]}" "${SDWDATE_POOL_THREE[@]}"; do - echo "element: $element" - number_lines_counter="0" - while read -r -d $'\n' line; do - line_without_spaces="${line// /}" - if [ "$line_without_spaces" = "" ]; then - ## Skipping empty or lines with leading/trailing spaces (such as '" '). - continue - fi - number_lines_counter="$(( $number_lines_counter + 1 ))" - - link_unprocessed="$(sdwdate_pick_single_link_from_maybe_multi_lined_mirror_list "$element")" - echo "link_unprocessed: $link_unprocessed" - - ## sets: link_url_part - ## sets: link_comment_part - ## sets: link_url - ## sets: link_port - sdwdate_link_with_comments_to_processed_link - - echo "\${link_url}:\${link_port}: ${link_url}:${link_port}" - sdwdate_get_time_from_remote - if [ ! "${sdwdate_download_tool_exit_code[$SDWDATE_CURRENT_POOL]}" = "0" ]; then - echo "FAILED : ${link_url}:${link_port}" - else - echo "SUCCESS: ${link_url}:${link_port}" - fi - echo "----------" - done < <( echo "$element" ) - done -} - -download_unit_test diff --git a/etc/sdwdate.d/30_sdwdate_default b/usr/share/test_d_files/40_pool_one_invalid similarity index 70% rename from etc/sdwdate.d/30_sdwdate_default rename to usr/share/test_d_files/40_pool_one_invalid index aa0fc330..4ee676e0 100644 --- a/etc/sdwdate.d/30_sdwdate_default +++ b/usr/share/test_d_files/40_pool_one_invalid @@ -234,25 +234,22 @@ SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_THREE]="" ## removed because down: ## "bczjr6ciiblco5ti.onion#Forbes https://safesource.forbes.com bczjr6ciiblco5ti.onion" ## "l7rt5kabupal7eo7.onion#BayLeaks https://bayleaks.com l7rt5kabupal7eo7.onion" -## "dtsxnd3ykn32ywv6.onion#BalkanLeaks https://www.balkanleaks.eu dtsxnd3ykn32ywv6.onion" -## "33y6fjyhs3phzfjj.onion#The Guardian https://securedrop.theguardian.com 33y6fjyhs3phzfjj.onion" -## "hkjpnjbvhrxjvikd.onion#Radio24syv https://securedrop.radio24syv.dk hkjpnjbvhrxjvikd.onion" ## individual websites SDWDATE_POOL_ONE=( - "znig4bc5rlwyj4mz.onion#ExposeFacts https://exposefacts.org znig4bc5rlwyj4mz.onion" - "vtjkwwcq5osuo6uq.onion#Greenpeace New Zealand https://www.safesource.org.nz vtjkwwcq5osuo6uq.onion" - "y6xjgkgwj47us5ca.onion#The Intercept https://firstlook.org/theintercept/securedrop y6xjgkgwj47us5ca.onion" - "strngbxhwyuu37a3.onion#The New Yorker https://projects.newyorker.com/strongbox strngbxhwyuu37a3.onion" - "swdi5ymnwmrqhycl.onion#NRKbeta https://nrkbeta.no/tips swdi5ymnwmrqhycl.onion" - "dqeasamlf3jld2kz.onion#Project On Gov't Oversight (POGO) https://securedrop.pogo.org dqeasamlf3jld2kz.onion" - "pubdrop4dw6rk3aq.onion#ProPublica https://securedrop.propublica.org pubdrop4dw6rk3aq.onion" - "v6gdwmm7ed4oifvd.onion#Barton Gellman https://tcfmailvault.info v6gdwmm7ed4oifvd.onion" - "vbmwh445kf3fs2v4.onion#The Washington Post https://ssl.washingtonpost.com/securedrop vbmwh445kf3fs2v4.onion" - "poulsensqiv6ocq4.onion#Wired's Kevin Poulsen https://pressfreedomfoundation.org/about/tech/kevin-poulsen poulsensqiv6ocq4.onion" - "tigas3l7uusztiqu.onion#https://mike.tig.as tinkerer at ProPublica in New York" - "gawker5oxtsc6fa7.onion#Gawker Media https://gawkermediagroup.com/securedrop" - "n572ltkg4nld3bsz.onion#The Globe and Mail https://sec.theglobeandmail.com/securedrop" - "udrciweihl4qe63p.onion#NEOSleaks https://neos.eu/leaks/" + "atsxnd3ykn32ywv6.onion#d BalkanLeaks https://www.balkanleaks.eu dtsxnd3ykn32ywv6.onion" + "anig4bc5rlwyj4mz.onion#z ExposeFacts https://exposefacts.org znig4bc5rlwyj4mz.onion" + "atjkwwcq5osuo6uq.onion#v Greenpeace New Zealand https://www.safesource.org.nz vtjkwwcq5osuo6uq.onion" + "a3y6fjyhs3phzfjj.onion#3 The Guardian https://securedrop.theguardian.com 33y6fjyhs3phzfjj.onion" + "a6xjgkgwj47us5ca.onion#y The Intercept https://firstlook.org/theintercept/securedrop y6xjgkgwj47us5ca.onion" +## "strngbxhwyuu37a3.onion#The New Yorker https://projects.newyorker.com/strongbox strngbxhwyuu37a3.onion" +## "swdi5ymnwmrqhycl.onion#NRKbeta https://nrkbeta.no/tips swdi5ymnwmrqhycl.onion" +## "dqeasamlf3jld2kz.onion#Project On Gov't Oversight (POGO) https://securedrop.pogo.org dqeasamlf3jld2kz.onion" +## "pubdrop4dw6rk3aq.onion#ProPublica https://securedrop.propublica.org pubdrop4dw6rk3aq.onion" +## "hkjpnjbvhrxjvikd.onion#Radio24syv https://securedrop.radio24syv.dk hkjpnjbvhrxjvikd.onion" +## "v6gdwmm7ed4oifvd.onion#Barton Gellman https://tcfmailvault.info v6gdwmm7ed4oifvd.onion" +## "vbmwh445kf3fs2v4.onion#The Washington Post https://ssl.washingtonpost.com/securedrop vbmwh445kf3fs2v4.onion" +## "poulsensqiv6ocq4.onion#Wired's Kevin Poulsen https://pressfreedomfoundation.org/about/tech/kevin-poulsen poulsensqiv6ocq4.onion" +## "tigas3l7uusztiqu.onion#https://mike.tig.as tinkerer at ProPublica in New York" ) ## pool two. @@ -268,30 +265,30 @@ SDWDATE_POOL_ONE=( ## "jeuhrnvdyr3xyqz3.onion#Internet Governance Transparency Initiative 2014-April-5 Transparency Activism jeuhrnvdyr3xyqz3.onion https://jeuhrnvdyr3xyqz3.tor2web.org Unknown" ## "ea433ils4wtprqbv.onion#EcuadorTransparente 2014-June-19 Transparency Activism ea433ils4wtprqbv.onion https://ea433ils4wtprqbv.tor2web.org/ Ecuador" ## "3qnry3qqjvc2u3c4.onion#ManxLeaks 2014-July-07 Transparency Activism 3qnry3qqjvc2u3c4.onion https://3qnry3qqjvc2u3c4.tor2web.org Isle of Man" -## bbbbbb6qtmqg65g6.onion:80#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html -## pppppptkftqqnfsq.onion:80#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html -## "yn6ocmvu4ok3k3al.onion#Publeaks [27][28] 2013-September-9 +40 National/Local Media Consortium yn6ocmvu4ok3k3al.onion https://secure.publeaks.nl Netherlands" -## "2dermafialks7aai.onion#Mafialeaks [31][32][33] 2013-November-5 Anti Mafia Activism 2dermafialks7aai.onion https://secure.mafialeaks.org Italy" -## "ymi7h25hgp3bj63v.onion#InfodioLeaks 2014-January-28 Anticorruption Activism ymi7h25hgp3bj63v.onion https://ymi7h25hgp3bj63v.tor2web.org Venezuela" -## "ur5b2b4brz427ygh.onion#Nawaatleaks [40] 2014-March-27 Activism ur5b2b4brz427ygh.onion https://ur5b2b4brz427ygh.tor2web.org Tunisia" -## "6iolddfbfinntq2b.onion#Brussels Leaks 2014-October 24 Europe Focus Anticorruption Transparency Activism 6iolddfbfinntq2b.onion https://6iolddfbfinntq2b.tor2web.org Belgium" SDWDATE_POOL_TWO=( - " - atlas777hhh7mcs7.onion:80#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html - compass6vpxj32p3.onion:80#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html - globe223ezvh6bps.onion:80#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html - " + [ + "atlas777hhh7mcs7.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "compass6vpxj32p3.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "globe223ezvh6bps.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "bbbbbb6qtmqg65g6.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + "pppppptkftqqnfsq.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" + ] "w6csjytbrl273che.onion#Ljost[24][25] 2012-September-30 Transparency Activism w6csjytbrl273che.onion https://w6csjytbrl273che.tor2web.org/ Iceland" "ak2uqfavwgmjrvtu.onion#MagyarLeaks[26] 2013-July-7 Investigative Journalism ak2uqfavwgmjrvtu.onion https://ak2uqfavwgmjrvtu.tor2web.org Hungary" + "yn6ocmvu4ok3k3al.onion#Publeaks [27][28] 2013-September-9 +40 National/Local Media Consortium yn6ocmvu4ok3k3al.onion https://secure.publeaks.nl Netherlands" "acabtd4btrxjjrvr.onion#Pistajka 2013-September Anticorruption activism acabtd4btrxjjrvr.onion https://acabtd4btrxjjrvr.tor2web.org Serbia" "5r4bjnjug3apqdii.onion#Irpileaks[29][30] 2013-October-7 Investigative Journalism 5r4bjnjug3apqdii.onion https://5r4bjnjug3apqdii.tor2web.org/ Italy" + "2dermafialks7aai.onionMafialeaks [31][32][33] 2013-November-5 Anti Mafia Activism 2dermafialks7aai.onion https://secure.mafialeaks.org Italy" + "ymi7h25hgp3bj63v.onion#InfodioLeaks 2014-January-28 Anticorruption Activism ymi7h25hgp3bj63v.onion https://ymi7h25hgp3bj63v.tor2web.org Venezuela" "ppdz5djzpo3w5k2z.onion#WildLeaks [34][35][36][37][38][39] 2014-February-7 WildLife Crime Activism ppdz5djzpo3w5k2z.onion https://secure.wildleaks.org United States/Africa" "pltloztihmfrg2sw.onion#Salzburger-Piratenpartei 2014-March-4 Activism pltloztihmfrg2sw.onion https://pltloztihmfrg2sw.tor2web.org Austria" + "ur5b2b4brz427ygh.onion#Nawaatleaks [40] 2014-March-27 Activism ur5b2b4brz427ygh.onion https://ur5b2b4brz427ygh.tor2web.org Tunisia" "w6csjytbrl273che.onion#Filtrala [41][42] 2014-April-23 Anticorruption Activism w6csjytbrl273che.onion https://w6csjytbrl273che.tor2web.org/ Spain" "abkjckdgoabr7bmm.onion#MediaDirect [43] 2014-May-11 Transparency Activism abkjckdgoabr7bmm.onion https://abkjckdgoabr7bmm.tor2web.org Australia" "5r4bjnjug3apqdii.onion#ExpoLeaks[44] [45] [46] 2014-June-10 Investigative Journalism 5r4bjnjug3apqdii.onion https://5r4bjnjug3apqdii.tor2web.org/ Italy" "bqs3dobnazs7h4u4.onion#ExtremeLeaks 2014-June-18 Investigative Journalism bqs3dobnazs7h4u4.onion https://www.extremeleaks.org/ Norway" "fkut2p37apcg6l7f.onion#Allerta Anticorruzione[47][48] 2014-October-14 Anticorruption Activism fkut2p37apcg6l7f.onion https://alac.transparency.it Italy" + "6iolddfbfinntq2b.onion#Brussels Leaks 2014-October 24 Europe Focus Anticorruption Transparency Activism 6iolddfbfinntq2b.onion https://6iolddfbfinntq2b.tor2web.org Belgium" ) ## pool three. @@ -304,32 +301,27 @@ SDWDATE_POOL_TWO=( ## removed because no http: ## "4cjw6cwpeaeppfqz.onion#xmpp.riseup.net: 4cjw6cwpeaeppfqz.onion (ports 5222, 5269)" SDWDATE_POOL_THREE=( - "3g2upl4pq6kufc4m.onion:80#https://duck.co/forum/thread/1762/is-the-duckduckgo-hidden-service-legitimate" - "dju2peblv7upfz3q.onion:80#https://guardianproject.info/2014/10/16/reducing-metadata-leakage-from-software-updates/" - "msydqstlz2kzerdg.onion:80#https://ahmia.fi/address/msydqstlz2kzerdg" - "uj3wazyk5u4hnvtk.onion:80#https://thepiratebay.se/blog/238" - "bitmailendavkbec.onion:80#https://bitmessage.org/forum/index.php?topic=1556.0" + "3g2upl4pq6kufc4m.onion#https://duck.co/forum/thread/1762/is-the-duckduckgo-hidden-service-legitimate" + "dju2peblv7upfz3q.onion#https://guardianproject.info/2014/10/16/reducing-metadata-leakage-from-software-updates/" + "msydqstlz2kzerdg.onion#https://ahmia.fi/address/msydqstlz2kzerdg" + "uj3wazyk5u4hnvtk.onion#https://thepiratebay.se/blog/238" + "bitmailendavkbec.onion#https://bitmessage.org/forum/index.php?topic=1556.0" "wi7qkxyrdpu5cmvr.onion#Austici www.autistici.org/en/stuff/man_anon/tor.html" "ic6au7wa3f6naxjq.onion#https://lists.gnupg.org/pipermail/gnupg-users/2014-April/049578.html" - " - nzh3fv6jc6jskki3.onion#help.riseup.net: nzh3fv6jc6jskki3.onion (port 443) - cwoiopiifrlzcuos.onion#black.riseup.net: cwoiopiifrlzcuos.onion (port 443) - zsolxunfmbfuq7wf.onion#imap.riseup.net: zsolxunfmbfuq7wf.onion (port 993) - yfm6sdhnfbulplsw.onion#labs.riseup.net: yfm6sdhnfbulplsw.onion (port 80, 443) - xpgylzydxykgdqyg.onion#lists.riseup.net: xpgylzydxykgdqyg.onion (port 80, 443) - zsolxunfmbfuq7wf.onion#mail.riseup.net: zsolxunfmbfuq7wf.onion (ports 443, 465, 587) - 5jp7xtmox6jyoqd5.onion:443#pad.riseup.net: 5jp7xtmox6jyoqd5.onion (port 443) (note: only works with https://5jp7xtmox6jyoqd5.onion) - zsolxunfmbfuq7wf.onion#pop.riseup.net: zsolxunfmbfuq7wf.onion (port 995) - zsolxunfmbfuq7wf.onion#smtp.riseup.net: zsolxunfmbfuq7wf.onion (ports 465, 587) - j6uhdvbhz74oefxf.onion#user.riseup.net: j6uhdvbhz74oefxf.onion (port 80, 443) - 7lvd7fa5yfbdqaii.onion#we.riseup.net: 7lvd7fa5yfbdqaii.onion (port 443) - " + [ + "nzh3fv6jc6jskki3.onion#help.riseup.net: nzh3fv6jc6jskki3.onion (port 443)" + "cwoiopiifrlzcuos.onion#black.riseup.net: cwoiopiifrlzcuos.onion (port 443)" + "zsolxunfmbfuq7wf.onion#imap.riseup.net: zsolxunfmbfuq7wf.onion (port 993)" + "yfm6sdhnfbulplsw.onion#labs.riseup.net: yfm6sdhnfbulplsw.onion (port 80, 443)" + "xpgylzydxykgdqyg.onion#lists.riseup.net: xpgylzydxykgdqyg.onion (port 80, 443)" + "zsolxunfmbfuq7wf.onion#mail.riseup.net: zsolxunfmbfuq7wf.onion (ports 443, 465, 587)" + "5jp7xtmox6jyoqd5.onion#pad.riseup.net: 5jp7xtmox6jyoqd5.onion (port 443) (note: only works with https://5jp7xtmox6jyoqd5.onion)" + "zsolxunfmbfuq7wf.onion#pop.riseup.net: zsolxunfmbfuq7wf.onion (port 995)" + "zsolxunfmbfuq7wf.onion#smtp.riseup.net: zsolxunfmbfuq7wf.onion (ports 465, 587)" + "j6uhdvbhz74oefxf.onion#user.riseup.net: j6uhdvbhz74oefxf.onion (port 80, 443)" + "7lvd7fa5yfbdqaii.onion#we.riseup.net: 7lvd7fa5yfbdqaii.onion (port 443)" + ] "timaq4ygg2iegci7.onion#https://github.com/meejah/txtorcon http://txtorcon.readthedocs.org" "344c6kbnjnljjzlz.onion#VFEmail https://www.vfemail.net" "fncuwbiisyh6ak3i.onion#https://keybase.io/docs/command_line/tor" - "wlchatc3pjwpli5r.onion#https://twitter.com/wikileaks/status/590907709387624450" - "nodd5fyasyj4jqgp.onion#http://www.thesun.co.uk/sol/homepage/news/6429126/The-Sun-Whistleblower-Charter.html" - "qubesosmamapaxpa.onion#https://www.qubes-os.org" - "intelexi7yo7mj7j.onion#https://intelexit.org" - "libraryxobbrbj33.onion#https://twitter.com/flexlibris/status/653351072069754880 https://libraryfreedomproject.org" ) diff --git a/usr/share/test_d_files/50_pool_two_invalid b/usr/share/test_d_files/50_pool_two_invalid new file mode 100644 index 00000000..5a1fd4dc --- /dev/null +++ b/usr/share/test_d_files/50_pool_two_invalid @@ -0,0 +1,327 @@ +## This file is part of Whonix. +## Copyright (C) 2012 - 2014 Patrick Schleizer +## See the file COPYING for copying conditions. + +## Please use "/etc/sdwdate.d/50_sdwdate_user" for your custom +## configuration, which will override the defaults found here. +## When sdwdate is updated, this file may be overwritten. + +## Bash Fragment. + +## Enable/disable debugging. +## 1 enabled. +## 2 disabled. +DEBUG=0 + +## Run as the following user name. +## Not implemented. Has no effect. +USER="" + +## Do or do not actually change the date/time after successfully fetching it. +## 0 set date. +## 1 do not set date. +DONT_SET_DATE=0 + +## do not move the time forward +## 0 disabled +## 1 enabled +NO_MOVE_FORWARD=0 + +## do not move the time backwards +## 0 disabled +## 1 enabled +NO_MOVE_BACKWARDS=0 + +## update hardware clock +## 0 disabled +## 1 enabled +SYSTOHC=0 + +## Log file. +LOG_FILE=/var/log/sdwdate.log + +## Done file. Will be created after run no matter if failure or success. +DONE_FILE=/var/run/sdwdate/done + +## Success file. Will only be created after a success. +SUCCESS_FILE=/var/run/sdwdate/success + +## First success file. Will be created after the first success. +FIRST_SUCCESS_FILE=/var/run/sdwdate/first_success + +## How many members per pool are allowed to fail. +## If too many members are not reachable, time will not be adjusted. +ALLOWED_PER_POOL_FAILURE_RATIO=0.34 + +## Temporary directory for file downloads. +## When not set, default to: TEMP_DIR="$(mktemp --directory)" +#TEMP_DIR="" + +## Cache dir. Must not include spaces. +SDW_CACHE_DIR="/var/cache/sdwdate/sclockadj" + +## proxy IP +PROXY_IP="127.0.0.1" + +## proxy port +PROXY_PORT="9050" + +## How often sdwdate should run in minutes. +## 0 disables it and sdwdate exits after run. +INTERVAL="180" + +## How many minutes should be waited before running sdwdate again. +## Only has an effect when RANDOMIZE is set to 1 as well. +MIN_INTERVAL="60" + +## Randomize the interval above. +## Minimum 60 minutes. +## Maximum $INTERVAL minutes. +## 0 disabled. +## 1 enabled. +RANDOMIZE="1" + +## Use sclockadj instead of /bin/date (which would produce clock jumps) when +## starting up. +## 0 sclockadj disabled +## 1 sclockadj enabled +## defaults to: 0 +SDWDATE_USE_SCLOCKADJ_WHEN_STARTUP="0" + +## Use sclockadj instead of /bin/date (which would produce clock jumps) when +## re-starting up when sdwdate succeeded at least once after boot. +## 0 sclockadj disabled +## 1 sclockadj enabled +## defaults to: 1 +SDWDATE_USE_SCLOCKADJ_WHEN_RESTARTUP="1" + +## Use sclockadj instead of /bin/date (which would produce clock jumps) when +## in daemon mode. +## 0 sclockadj disabled +## 1 sclockadj enabled +## defaults to: 1 +SDWDATE_USE_SCLOCKADJ_WHEN_DAEMON="1" + +## sclockadj verbose logging or not +## --no-verbose +## --verbose +## defaults to: --no-verbose +SDWDATE_SCLOCKADJ_VERBOSE="--no-verbose" + +## sclockadj change date or not +## --no-debug +## --debug +## defaults to: --no-debug (change date) +SDWDATE_SCLOCKADJ_CHANGE_DATE="--no-debug" + +## If sclockadj should wait before its first iteration. +## --no-first-wait +## --first-wait +## default to: --no-first-wait +SDWDATE_SCLOCKADJ_FIRST_WAIT="--no-first-wait" + +## Move clock minimum nanoseconds (except rest). +## defaults to: 500000 +## (500000 ns = 0.5 ms = 0.0005 s) +SDWDATE_SCLOCKADJ_MOVE_MIN="500000" + +## Move clock maximum nanoseconds (except rest). +## defaults to: 500000 +## (500000 ns = 0.5 ms = 0.0005 s) +SDWDATE_SCLOCKADJ_MOVE_MAX="500000" + +## Wait nanoseconds minimum before next iteration. +## defaults to: 1000000000 +## (1000000000 ns = 1000 ms = 1 s) +SDWDATE_SCLOCKADJ_WAIT_MIN="1000000000" + +## Wait nanoseconds maximum before next iteration. +## defaults to: 1000000000 +## (1000000000 ns = 1000 ms = 1 s) +SDWDATE_SCLOCKADJ_WAIT_MAX="1000000000" + +## This command will be `eval`uated before DISPATCH_PREREQUISITE and before running url to unixtime tool. +## sdwdate provides the $SDW_MODE variable, which is either set to +## - startup (when the sdwdate process is started) +## - daemon (when the sdwdate process finished one loop and will continue) +## When set to "", it will be skipped. +DISPATCH_PRE="" + +## Prerequisite before trying to connect to servers. +## This is supposed to be a command to be `eval`uated and to exit with code +## - 0, if sdwdate should continue. +## - 1, if sdwdate should terminate itself due to an expected error. +## - 2, if sdwdate should wait 10 seconds and then run the command again. +## - Anything else, if sdwdate should terminate itself due to an unexpected error. +## It may be useful to check if the network is already reachable. +## When set to "", it will be skipped. +DISPATCH_PREREQUISITE="" + +## This command will be `eval`uated when an unexpected error (bug) in sdwdate has been caught. +## sdwdate will provide the $error_message and $DONE_FILE variable. +## Remember to escape variables either using \$ or '$variable'. +## When set to "", it will be skipped. +DISPATCH_POST_ERROR="" + +## Create $DONE_FILE on error. +## 1 enabled. +## 0 disabled. +SDW_TOUCH_DONE_FILE_ON_ERROR="1" + +## Exit 1 on error. This will stop the daemon from running. +## 1 enabled. +## 0 disabled. +SDW_EXIT_ON_ERROR="1" + +## echo remote unix time even when using --quiet +## true - enabled. +## false - disabled. +ECHO_UNIX_TIME="false" + +## This command will be `eval`uated when sdwdate succeeded. +## When set to "", it will be skipped. +DISPATCH_POST_SUCCESS="" + +## This command will be `eval`uated when sdwdate failed. +## When set to "", it will be skipped. +DISPATCH_POST_FAILURE="" + +## This command will be `eval`uated before trying to connect to the pool one. +## When set to "", it will be skipped. +SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_ONE]="" + +## This command will be `eval`uated before after connecting to the pool one. +## When set to "", it will be skipped. +SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_ONE]="" + +## This command will be `eval`uated before trying to connect to the pool two. +## When set to "", it will be skipped. +SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_TWO]="" + +## This command will be `eval`uated before after connecting to the pool two. +## When set to "", it will be skipped. +SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_TWO]="" + +## This command will be `eval`uated before trying to connect to pool three. +## When set to "", it will be skipped. +SDWDATE_TIME_TOOL_DISPATCH_PRE[SDWDATE_POOL_THREE]="" + +## This command will be `eval`uated before trying after connecting to the pool three. +## When set to "", it will be skipped. +SDWDATE_TIME_TOOL_DISPATCH_POST[SDWDATE_POOL_THREE]="" + +## pool syntax +## "url.onion[:port]#comment" +## " +## url.onion[:port]#comment +## [url.onion[:port]#comment] +## [url.onion[:port]#comment] +## [...] +## " +## "url.onion[:port]#comment" +## ... + +## pool one. +## SecureDrop List +## info: +## Last updated Thu Oct 23 16:15:00 PDT 2014 +## Organization Landing Page Tor Hidden Service Address +## in use: +## https://freedom.press/securedrop/directory +## https://freedom.press/sites/default/files/securedrop_list.txt +## https://freedom.press/sites/default/files/securedrop_list.txt.asc +## https://freedom.press/sites/default/files/securedrop.asc +## removed because down: +## "bczjr6ciiblco5ti.onion#Forbes https://safesource.forbes.com bczjr6ciiblco5ti.onion" +## "l7rt5kabupal7eo7.onion#BayLeaks https://bayleaks.com l7rt5kabupal7eo7.onion" +## individual websites +SDWDATE_POOL_ONE=( + "dtsxnd3ykn32ywv6.onion#BalkanLeaks https://www.balkanleaks.eu dtsxnd3ykn32ywv6.onion" + "znig4bc5rlwyj4mz.onion#ExposeFacts https://exposefacts.org znig4bc5rlwyj4mz.onion" + "vtjkwwcq5osuo6uq.onion#Greenpeace New Zealand https://www.safesource.org.nz vtjkwwcq5osuo6uq.onion" + "33y6fjyhs3phzfjj.onion#The Guardian https://securedrop.theguardian.com 33y6fjyhs3phzfjj.onion" + "y6xjgkgwj47us5ca.onion#The Intercept https://firstlook.org/theintercept/securedrop y6xjgkgwj47us5ca.onion" + "strngbxhwyuu37a3.onion#The New Yorker https://projects.newyorker.com/strongbox strngbxhwyuu37a3.onion" + "swdi5ymnwmrqhycl.onion#NRKbeta https://nrkbeta.no/tips swdi5ymnwmrqhycl.onion" + "dqeasamlf3jld2kz.onion#Project On Gov't Oversight (POGO) https://securedrop.pogo.org dqeasamlf3jld2kz.onion" + "pubdrop4dw6rk3aq.onion#ProPublica https://securedrop.propublica.org pubdrop4dw6rk3aq.onion" + "hkjpnjbvhrxjvikd.onion#Radio24syv https://securedrop.radio24syv.dk hkjpnjbvhrxjvikd.onion" + "v6gdwmm7ed4oifvd.onion#Barton Gellman https://tcfmailvault.info v6gdwmm7ed4oifvd.onion" + "vbmwh445kf3fs2v4.onion#The Washington Post https://ssl.washingtonpost.com/securedrop vbmwh445kf3fs2v4.onion" + "poulsensqiv6ocq4.onion#Wired's Kevin Poulsen https://pressfreedomfoundation.org/about/tech/kevin-poulsen poulsensqiv6ocq4.onion" + "tigas3l7uusztiqu.onion#https://mike.tig.as tinkerer at ProPublica in New York" +) + +## pool two. +## Hosted by Thomas White List +## +## GlobalLeaks List +## info: +## https://en.wikipedia.org/wiki/GlobaLeaks#Implementations +## http://www.webcitation.org/6WBrtPlrq +## Name of organization Implementation date Category Tor Url Tor2web Url Country +## removed because down: +## Perun[23] 2012-April-7 Investigative Journalism Closed Closed Serbia +## "jeuhrnvdyr3xyqz3.onion#Internet Governance Transparency Initiative 2014-April-5 Transparency Activism jeuhrnvdyr3xyqz3.onion https://jeuhrnvdyr3xyqz3.tor2web.org Unknown" +## "ea433ils4wtprqbv.onion#EcuadorTransparente 2014-June-19 Transparency Activism ea433ils4wtprqbv.onion https://ea433ils4wtprqbv.tor2web.org/ Ecuador" +## "3qnry3qqjvc2u3c4.onion#ManxLeaks 2014-July-07 Transparency Activism 3qnry3qqjvc2u3c4.onion https://3qnry3qqjvc2u3c4.tor2web.org Isle of Man" +SDWDATE_POOL_TWO=( +## [ +## "atlas777hhh7mcs7.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" +## "compass6vpxj32p3.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" +## "globe223ezvh6bps.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" +## "bbbbbb6qtmqg65g6.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" +## "pppppptkftqqnfsq.onion#Hosted by Thomas White. https://www.whonix.org/pipermail/whonix-devel/2015-February/000297.html" +## ] +## "w6csjytbrl273che.onion#Ljost[24][25] 2012-September-30 Transparency Activism w6csjytbrl273che.onion https://w6csjytbrl273che.tor2web.org/ Iceland" +## "ak2uqfavwgmjrvtu.onion#MagyarLeaks[26] 2013-July-7 Investigative Journalism ak2uqfavwgmjrvtu.onion https://ak2uqfavwgmjrvtu.tor2web.org Hungary" + "an6ocmvu4ok3k3al.onion#Publeaks [27][28] 2013-September-9 +40 National/Local Media Consortium yn6ocmvu4ok3k3al.onion https://secure.publeaks.nl Netherlands" + "bcabtd4btrxjjrvr.onion#Pistajka 2013-September Anticorruption activism acabtd4btrxjjrvr.onion https://acabtd4btrxjjrvr.tor2web.org Serbia" + "ar4bjnjug3apqdii.onion#Irpileaks[29][30] 2013-October-7 Investigative Journalism 5r4bjnjug3apqdii.onion https://5r4bjnjug3apqdii.tor2web.org/ Italy" + "adermafialks7aai.onionMafialeaks [31][32][33] 2013-November-5 Anti Mafia Activism 2dermafialks7aai.onion https://secure.mafialeaks.org Italy" + "ami7h25hgp3bj63v.onion#InfodioLeaks 2014-January-28 Anticorruption Activism ymi7h25hgp3bj63v.onion https://ymi7h25hgp3bj63v.tor2web.org Venezuela" +## "ppdz5djzpo3w5k2z.onion#WildLeaks [34][35][36][37][38][39] 2014-February-7 WildLife Crime Activism ppdz5djzpo3w5k2z.onion https://secure.wildleaks.org United States/Africa" +## "pltloztihmfrg2sw.onion#Salzburger-Piratenpartei 2014-March-4 Activism pltloztihmfrg2sw.onion https://pltloztihmfrg2sw.tor2web.org Austria" +## "ur5b2b4brz427ygh.onion#Nawaatleaks [40] 2014-March-27 Activism ur5b2b4brz427ygh.onion https://ur5b2b4brz427ygh.tor2web.org Tunisia" +## "w6csjytbrl273che.onion#Filtrala [41][42] 2014-April-23 Anticorruption Activism w6csjytbrl273che.onion https://w6csjytbrl273che.tor2web.org/ Spain" +## "abkjckdgoabr7bmm.onion#MediaDirect [43] 2014-May-11 Transparency Activism abkjckdgoabr7bmm.onion https://abkjckdgoabr7bmm.tor2web.org Australia" +## "5r4bjnjug3apqdii.onion#ExpoLeaks[44] [45] [46] 2014-June-10 Investigative Journalism 5r4bjnjug3apqdii.onion https://5r4bjnjug3apqdii.tor2web.org/ Italy" +## "bqs3dobnazs7h4u4.onion#ExtremeLeaks 2014-June-18 Investigative Journalism bqs3dobnazs7h4u4.onion https://www.extremeleaks.org/ Norway" +## "fkut2p37apcg6l7f.onion#Allerta Anticorruzione[47][48] 2014-October-14 Anticorruption Activism fkut2p37apcg6l7f.onion https://alac.transparency.it Italy" +## "6iolddfbfinntq2b.onion#Brussels Leaks 2014-October 24 Europe Focus Anticorruption Transparency Activism 6iolddfbfinntq2b.onion https://6iolddfbfinntq2b.tor2web.org Belgium" +) + +## pool three. +## info: +## individual websites +## riseup.net List +## https://help.riseup.net/en/tor#riseups-tor-hidden-services +## removed because down: +## "suw74isz7wqzpmgu.onion:80#https://www.wikileaks.org/wiki/WikiLeaks:Tor" +## removed because no http: +## "4cjw6cwpeaeppfqz.onion#xmpp.riseup.net: 4cjw6cwpeaeppfqz.onion (ports 5222, 5269)" +SDWDATE_POOL_THREE=( + "3g2upl4pq6kufc4m.onion#https://duck.co/forum/thread/1762/is-the-duckduckgo-hidden-service-legitimate" + "dju2peblv7upfz3q.onion#https://guardianproject.info/2014/10/16/reducing-metadata-leakage-from-software-updates/" + "msydqstlz2kzerdg.onion#https://ahmia.fi/address/msydqstlz2kzerdg" + "uj3wazyk5u4hnvtk.onion#https://thepiratebay.se/blog/238" + "bitmailendavkbec.onion#https://bitmessage.org/forum/index.php?topic=1556.0" + "wi7qkxyrdpu5cmvr.onion#Austici www.autistici.org/en/stuff/man_anon/tor.html" + "ic6au7wa3f6naxjq.onion#https://lists.gnupg.org/pipermail/gnupg-users/2014-April/049578.html" + [ + "nzh3fv6jc6jskki3.onion#help.riseup.net: nzh3fv6jc6jskki3.onion (port 443)" + "cwoiopiifrlzcuos.onion#black.riseup.net: cwoiopiifrlzcuos.onion (port 443)" + "zsolxunfmbfuq7wf.onion#imap.riseup.net: zsolxunfmbfuq7wf.onion (port 993)" + "yfm6sdhnfbulplsw.onion#labs.riseup.net: yfm6sdhnfbulplsw.onion (port 80, 443)" + "xpgylzydxykgdqyg.onion#lists.riseup.net: xpgylzydxykgdqyg.onion (port 80, 443)" + "zsolxunfmbfuq7wf.onion#mail.riseup.net: zsolxunfmbfuq7wf.onion (ports 443, 465, 587)" + "5jp7xtmox6jyoqd5.onion#pad.riseup.net: 5jp7xtmox6jyoqd5.onion (port 443) (note: only works with https://5jp7xtmox6jyoqd5.onion)" + "zsolxunfmbfuq7wf.onion#pop.riseup.net: zsolxunfmbfuq7wf.onion (port 995)" + "zsolxunfmbfuq7wf.onion#smtp.riseup.net: zsolxunfmbfuq7wf.onion (ports 465, 587)" + "j6uhdvbhz74oefxf.onion#user.riseup.net: j6uhdvbhz74oefxf.onion (port 80, 443)" + "7lvd7fa5yfbdqaii.onion#we.riseup.net: 7lvd7fa5yfbdqaii.onion (port 443)" + ] + "timaq4ygg2iegci7.onion#https://github.com/meejah/txtorcon http://txtorcon.readthedocs.org" + "344c6kbnjnljjzlz.onion#VFEmail https://www.vfemail.net" + "fncuwbiisyh6ak3i.onion#https://keybase.io/docs/command_line/tor" +) diff --git a/usr/share/translations/sdwdate.yaml b/usr/share/translations/sdwdate.yaml new file mode 100644 index 00000000..f219018f --- /dev/null +++ b/usr/share/translations/sdwdate.yaml @@ -0,0 +1,32 @@ +sdwdate: + en: + fetching: 'Fetching remote times...' + restricted: '
Outgoing internet access is still restricted because initial time fetching is not done yet' + user_kill: 'Signal SIGTERM received. sdwdate stopped by user. ' + sleeping: '
Sleeping for ' + minutes: ' minutes.' + success_1: 'Last run (on ' + success_2: ') was successful.
' + + tsc_1: 'The clock is ' + tsc_2: '
Current time ' + slow_clock: ' is less than
the build timestamp ' + fast_clock: ' is greater than
the expiration timestamp ' + cause: '

Possible causes:
+ - the host clock is wrong -> shut down the VM, fix the clock in the host and restart the VM.
+ - the VM clok is wrong -> manually fix the clock. Restart tor if necessary.
+ - a host clock attack succeeded.
+ - a bios clock failure.
' + + no_valid_time: 'Time is not set: no valid time returned from pool
+ Possible causes:
- internet connection is down +
- tor is not running' + no_value_returned: 'No values returned from servers.' + list_not_built: 'Something is wrong. sdwdate could not build a list or urls.' + restart: '
Restart sdwdate. If the problem persists, please report this bug.
' + + general_proxy_error: 'General Proxy Error. Is Tor running?' + general_timeout_error: 'General Timeout Error. Internet connection might be down' + + max_pool_failures_1: 'Maximum allowed number of failures reached in pool ' + max_pool_failures_2: '. Giving up.
If the problem occurs too frequently, please report it.'