tor: Fixes for APT transport setup

- When Deb822 formatted source files are present, error out and don't
  show as enabled.

- When /etc/apt/sources.list.d/*.sources files are present, error out
  and don't show as enabled.

- Handle files /etc/apt/sources.list.d/*.list.

- Workaround Augeas lens not understanding '[options]' in sources.list.
This commit is contained in:
Sunil Mohan Adapa 2015-09-04 15:31:55 +05:30
parent 09f64f6a4b
commit bff8dd5a5c
2 changed files with 100 additions and 17 deletions

View File

@ -22,16 +22,15 @@ Configuration helper for the Tor service
""" """
import argparse import argparse
import augeas
import codecs import codecs
import os import os
import re import re
import socket import socket
from plinth import action_utils from plinth import action_utils
from plinth.modules.tor.tor import get_augeas, get_real_apt_uri_path, \
iter_apt_uris, APT_TOR_PREFIX
APT_SOURCES_URI_PATH = '/files/etc/apt/sources.list/*/uri'
APT_TOR_PREFIX = 'tor+'
TOR_CONFIG = '/etc/tor/torrc' TOR_CONFIG = '/etc/tor/torrc'
TOR_STATE_FILE = '/var/lib/tor/state' TOR_STATE_FILE = '/var/lib/tor/state'
TOR_AUTH_COOKIE = '/var/run/tor/control.authcookie' TOR_AUTH_COOKIE = '/var/run/tor/control.authcookie'
@ -204,21 +203,36 @@ def subcommand_get_ports(_):
def subcommand_enable_apt_transport_tor(_): def subcommand_enable_apt_transport_tor(_):
"""Enable package download over Tor.""" """Enable package download over Tor."""
aug = augeas.Augeas() try:
for uri_path in aug.match(APT_SOURCES_URI_PATH): aug = get_augeas()
except Exception:
# If there was an error, don't proceed
print('Error: Unable to understand sources format.')
exit(1)
for uri_path in iter_apt_uris(aug):
uri_path = get_real_apt_uri_path(aug, uri_path)
uri = aug.get(uri_path) uri = aug.get(uri_path)
if not uri.startswith(APT_TOR_PREFIX): if uri.startswith('http://') or uri.startswith('https://'):
aug.set(uri_path, APT_TOR_PREFIX + uri) aug.set(uri_path, APT_TOR_PREFIX + uri)
aug.save() aug.save()
def subcommand_disable_apt_transport_tor(_): def subcommand_disable_apt_transport_tor(_):
"""Disable package download over Tor.""" """Disable package download over Tor."""
aug = augeas.Augeas() try:
for uri_path in aug.match(APT_SOURCES_URI_PATH): aug = get_augeas()
except Exception:
# Disable what we can, so APT is not unusable.
pass
for uri_path in iter_apt_uris(aug):
uri_path = get_real_apt_uri_path(aug, uri_path)
uri = aug.get(uri_path) uri = aug.get(uri_path)
if uri.startswith(APT_TOR_PREFIX): if uri.startswith(APT_TOR_PREFIX):
aug.set(uri_path, uri[len(APT_TOR_PREFIX):]) aug.set(uri_path, uri[len(APT_TOR_PREFIX):])
aug.save() aug.save()

View File

@ -24,13 +24,17 @@ from django import forms
from django.contrib import messages from django.contrib import messages
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from gettext import gettext as _ from gettext import gettext as _
import glob
import itertools
from plinth import actions from plinth import actions
from plinth import action_utils from plinth import action_utils
from plinth import cfg from plinth import cfg
from plinth import package from plinth import package
from plinth.errors import ActionError
APT_SOURCES_URI_PATH = '/files/etc/apt/sources.list/*/uri' APT_SOURCES_URI_PATHS = ('/files/etc/apt/sources.list/*/uri',
'/files/etc/apt/sources.list.d/*/*/uri')
APT_TOR_PREFIX = 'tor+' APT_TOR_PREFIX = 'tor+'
@ -91,6 +95,78 @@ def index(request):
'form': form}) 'form': form})
def get_augeas():
"""Return an instance of Augeaus for processing APT configuration."""
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Aptsources/lens', 'Aptsources.lns')
aug.set('/augeas/load/Aptsources/incl[last() + 1]', '/etc/apt/sources.list')
aug.set('/augeas/load/Aptsources/incl[last() + 1]',
'/etc/apt/sources.list.d/*.list')
aug.load()
# Currently, augeas does not handle Deb822 format, it error out.
if aug.match('/augeas/files/etc/apt/sources.list/error') or \
aug.match('/augeas/files/etc/apt/sources.list.d//error'):
raise Exception('Error parsing sources list')
# Starting with Apt 1.1, /etc/apt/sources.list.d/*.sources will
# contain files with Deb822 format. If they are found, error out
# for now. XXX: Provide proper support Deb822 format with a new
# Augeas lens.
if glob.glob('/etc/apt/sources.list.d/*.sources'):
raise Exception('Can not handle Deb822 source files')
return aug
def iter_apt_uris(aug):
"""Iterate over all the APT source URIs."""
return itertools.chain.from_iterable([aug.match(path)
for path in APT_SOURCES_URI_PATHS])
def get_real_apt_uri_path(aug, path):
"""Return the actual path which contains APT URL.
XXX: This is a workaround for Augeas bug parsing Apt source files
with '[options]'. Remove this workaround after Augeas lens is
fixed.
"""
uri = aug.get(path)
if uri[0] == '[':
parent_path = path.rsplit('/', maxsplit=1)[0]
skipped = False
for child_path in aug.match(parent_path + '/*')[1:]:
if skipped:
return child_path
value = aug.get(child_path)
if value[-1] == ']':
skipped = True
return path
def is_apt_transport_tor_enabled():
"""Return whether APT is set to download packages over Tor."""
try:
aug = get_augeas()
except Exception:
# If there was an error with parsing or there are Deb822
# files.
return False
for uri_path in iter_apt_uris(aug):
uri_path = get_real_apt_uri_path(aug, uri_path)
uri = aug.get(uri_path)
if not uri.startswith(APT_TOR_PREFIX) and \
(uri.startswith('http://') or uri.startswith('https://')):
return False
return True
def get_status(): def get_status():
"""Return the current status""" """Return the current status"""
output = actions.superuser_run('tor', ['get-ports']) output = actions.superuser_run('tor', ['get-ports'])
@ -119,20 +195,13 @@ def get_status():
hs_hostname = hs_info[0] hs_hostname = hs_info[0]
hs_ports = hs_info[1] hs_ports = hs_info[1]
apt_transport_tor_enabled = False
aug = augeas.Augeas()
for uri_path in aug.match(APT_SOURCES_URI_PATH):
if aug.get(uri_path).startswith(APT_TOR_PREFIX):
apt_transport_tor_enabled = True
break
return {'enabled': action_utils.service_is_enabled('tor'), return {'enabled': action_utils.service_is_enabled('tor'),
'is_running': action_utils.service_is_running('tor'), 'is_running': action_utils.service_is_running('tor'),
'ports': ports, 'ports': ports,
'hs_enabled': hs_enabled, 'hs_enabled': hs_enabled,
'hs_hostname': hs_hostname, 'hs_hostname': hs_hostname,
'hs_ports': hs_ports, 'hs_ports': hs_ports,
'apt_transport_tor_enabled': apt_transport_tor_enabled} 'apt_transport_tor_enabled': is_apt_transport_tor_enabled()}
def _apply_changes(request, old_status, new_status): def _apply_changes(request, old_status, new_status):