Skip to content
Permalink
Browse files

Applied Debian and FreeBSD patches. Fixed reported Ubuntu bugs.

  • Loading branch information...
slicer69 authored and GerHobbelt committed May 17, 2014
1 parent 0e9e6b5 commit e31b18662976a0097c5a83b53f3a1978f13637b6
@@ -4,7 +4,73 @@ DENYHOSTS CHANGELOG
==================

- Forked code from DenyHosts (denyhosts.sf.net)
New project now maintained at ***********
New project now maintained at denyhost.sf.net

- Added private moduls patch from Marco Bertorello. Loads
modules from /usr/share/denyhosts

- Place config, lock and executable file in more
standard locations. Patch provided by Marco Bertorello.

- Fixed configuration (denyhosts.cfg-dist) to better support
Debian and Ubuntu. Patch supplied by Marco Nenciarini.

- Added warning to migrate switch. Patch provided by
Marco Bertorello.

- Avoid installing unwanted files (extra scripts and changelog).
Patch provided by Marco Nenciarini.

- Fix bug which would not recognize an attack on the root
user account. Patch provided by Kyle Willmon.

- Fix pattern matching bug (CVE-2007-4323).
Patch provided by Nico Golde.

- Added foreground mode for debugging.
Patch supplied by Marco Bertorello.

- Applied patch to fix plugin execution.
Patched provided by Marco Bertorello.

- Added patch to prevent DenyHosts from running with
a double --config switch.
Patch provided by Maro Bertorello.

- Convert path of "env" from /bin/env to /usr/bin/env
Patch provided by Kyle Willmon.

- Added patch to perform missing bounds check in Purge action.
Provided by Kyle Willmon.

- Added patch to include SYNC_PROXY_SERVER configuration option.
Provided by Kyle Willmon.

- Change HOSTNAME_LOOKUP to default to "NO". Will save time.
Also brings us into closer alignment with FreeBSD patches.

- Added /usr/sbin/nologin to restricted_from_passwd script.
Requirement from FreeBSD patch set.

- Added variable "ETC_DIR" which dictates the location of
configuration files. This should usually be set to
/etc or /usr/local/etc

- The restricted-usernames file is now loaded from the "ETC_DIR"
directory, rather than from "WORK_DIR" to avoid this
human-made configuration file from being over-writeen.
Closes Ubuntu bug #675034

- Confirm setting timestamp over-writes old tiemstamp file.
Closes Ubuntu bug #564476

- Applied advanced pattern check for authentication file which
takes into account alternative port numbers. Patch provided by
Helmut Grohne.

- Updated license and readme files.

- Updated help output from DenyHost script to include --config tip.



@@ -7,7 +7,6 @@

SECURE_LOG_OFFSET = "offset"
DENIED_TIMESTAMPS = "denied-timestamps"
#PARSED_DATES = "file_dates"

ABUSIVE_HOSTS_INVALID = "hosts"
ABUSIVE_HOSTS_VALID = "hosts-valid"
@@ -36,7 +35,7 @@
# Miscellaneous constants #
#################################################################################

CONFIG_FILE = "denyhosts.cfg" # default can be overridden on cmd line
CONFIG_FILE = "/etc/denyhosts.conf"

DENY_DELIMITER = "# DenyHosts:"
ENTRY_DELIMITER = " | "
@@ -41,14 +41,15 @@
class DenyHosts:
def __init__(self, logfile, prefs, lock_file,
ignore_offset=0, first_time=0,
noemail=0, daemon=0):
noemail=0, daemon=0, foreground=0):
self.__denied_hosts = {}
self.__prefs = prefs
self.__lock_file = lock_file
self.__first_time = first_time
self.__noemail = noemail
self.__report = Report(prefs.get("HOSTNAME_LOOKUP"), is_true(prefs['SYSLOG_REPORT']))
self.__daemon = daemon
self.__foreground = foreground
self.__sync_server = prefs.get('SYNC_SERVER')
self.__sync_upload = is_true(prefs.get("SYNC_UPLOAD"))
self.__sync_download = is_true(prefs.get("SYNC_DOWNLOAD"))
@@ -87,7 +88,7 @@ def __init__(self, logfile, prefs, lock_file,
info("Log file size has not changed. Nothing to do.")


if daemon:
if daemon and not foreground:
info("launching DenyHosts daemon (version %s)..." % VERSION)
#logging.getLogger().setLevel(logging.WARN)

@@ -101,6 +102,10 @@ def __init__(self, logfile, prefs, lock_file,
self.runDaemon(logfile, last_offset)
else:
die("Error creating daemon: %s (%d)" % (retCode[1], retCode[0]))
elif foreground:
info("launching DenyHosts (version %s)..." % VERSION)
self.__lock_file.remove()
self.runDaemon(logfile, last_offset)


def killDaemon(self, signum, frame):
@@ -438,7 +443,7 @@ def process_log(self, logfile, offset):
self.__report.add_section(msg, new_denied_hosts)
if self.__sync_server: self.sync_add_hosts(new_denied_hosts)
plugin_deny = self.__prefs.get('PLUGIN_DENY')
if plugin_deny: plugin.execute(plugin_deny, deny_hosts)
if plugin_deny: plugin.execute(plugin_deny, new_denied_hosts)

new_suspicious_logins = login_attempt.get_new_suspicious_logins()
if new_suspicious_logins:
@@ -56,10 +56,24 @@ def get_data(self):

class Migrate(DenyFileUtilBase):
def __init__(self, deny_file):
DenyFileUtilBase.__init__(self, deny_file, "migrate")
self.backup()
self.create_temp(self.get_data())
self.replace()
print ""
print "**** WARNING ****"
print "migrate switch will migrate ALL your entries in your HOSTS_DENY file"
print "and this can be potentially dangerous, if you have some entry that "
print "you won't purge"
print ""
print "If you don't understand, please type 'No' and"
print "read /usr/share/doc/denyhosts/README.Debian"
print "for more info"
print ""
response = raw_input("Are you sure that you want do this? (Yes/No)")
if response == "Yes":
DenyFileUtilBase.__init__(self, deny_file, "migrate")
self.backup()
self.create_temp(self.get_data())
self.replace()
else:
print "nothing done"

def create_temp(self, data):
try:
@@ -175,6 +189,11 @@ def create_temp(self, data):
fp.write(line)
continue
else:
if offset == num_lines:
warn("DenyHosts comment line at end of file")
fp.write(line)
continue

timestamp = None
try:
rest = line.lstrip(DENY_DELIMITER)
@@ -74,12 +74,14 @@ def __init__(self, path=None):
('BLOCK_SERVICE', False),
('PURGE_DENY', False),
('HOSTS_DENY', True),
('WORK_DIR', True))
('WORK_DIR', True),
('ETC_DIR', True))

# the paths for these keys will be converted to
# absolute pathnames (in the event they are relative)
# since the --daemon mode requires absolute pathnames
self.make_abs = ('WORK_DIR',
'ETC_DIR',
'LOCK_FILE',
'SECURE_LOG',
'HOSTS_DENY',
@@ -9,19 +9,19 @@
SSHD_FORMAT_REGEX = re.compile(r""".* (sshd.*:|\[sshd\]) (?P<message>.*)""")
#SSHD_FORMAT_REGEX = re.compile(r""".* sshd.*: (?P<message>.*)""")

FAILED_ENTRY_REGEX = re.compile(r"""Failed (?P<method>.*) for (?P<invalid>invalid user |illegal user )?(?P<user>.*?) .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
FAILED_ENTRY_REGEX = re.compile(r"""Failed (?P<method>\S*) for (?P<invalid>invalid user |illegal user )?(?P<user>.*) from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})( port \d+)?( ssh2)?$""")

FAILED_ENTRY_REGEX2 = re.compile(r"""(?P<invalid>(Illegal|Invalid)) user (?P<user>.*?) .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
FAILED_ENTRY_REGEX2 = re.compile(r"""(?P<invalid>(Illegal|Invalid)) user (?P<user>.*) from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$""")

FAILED_ENTRY_REGEX3 = re.compile(r"""Authentication failure for (?P<user>.*) .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")

FAILED_ENTRY_REGEX4 = re.compile(r"""Authentication failure for (?P<user>.*) .*from (?P<host>.*)""")

FAILED_ENTRY_REGEX5 = re.compile(r"""User (?P<user>.*) .*from (?P<host>.*) not allowed because none of user's groups are listed in AllowGroups""")
FAILED_ENTRY_REGEX5 = re.compile(r"""User (?P<user>.*) .*from (?P<host>.*) not allowed because none of user's groups are listed in AllowGroups$""")

FAILED_ENTRY_REGEX6 = re.compile(r"""Did not receive identification string .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")

FAILED_ENTRY_REGEX7 = re.compile(r"""User (?P<user>.*) not allowed because not listed in AllowUsers""")
FAILED_ENTRY_REGEX7 = re.compile(r"""User (?P<user>.*) from (?P<host>.*) not allowed because not listed in AllowUsers""")


# these are reserved for future versions
@@ -42,7 +42,7 @@
FAILED_ENTRY_REGEX_MAP[i] = rx


SUCCESSFUL_ENTRY_REGEX = re.compile(r"""Accepted (?P<method>.*) for (?P<user>.*?) from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
SUCCESSFUL_ENTRY_REGEX = re.compile(r"""Accepted (?P<method>\S+) for (?P<user>.*) from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})( port \d+)?( ssh2)?$""")

TIME_SPEC_REGEX = re.compile(r"""(?P<units>\d*)\s*(?P<period>[smhdwy])?""")

@@ -9,7 +9,7 @@

class Restricted:
def __init__(self, prefs):
self.filename = os.path.join(prefs['WORK_DIR'], RESTRICTED_USERNAMES)
self.filename = os.path.join(prefs['ETC_DIR'], RESTRICTED_USERNAMES)
self.__data = set()
self.load_restricted()

@@ -1,4 +1,5 @@
from xmlrpclib import ServerProxy
from xmlrpclib import ServerProxy, Transport
from httplib import HTTP
import logging
import os
import time
@@ -12,6 +13,21 @@ def get_plural(items):
if len(items) != 1: return "s"
else: return ""

class ProxiedTransport(Transport):
def set_proxy(self, proxy):
self.proxy = proxy

def make_connection(self, host):
self.realhost = host
h = HTTP(self.proxy)
return h

def send_request(self, connection, handler, request_body):
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))

def send_host(self, connection, host):
connection.putheader('Host', self.realhost)

class Sync:
def __init__(self, prefs):
self.__prefs = prefs
@@ -21,7 +37,9 @@ def __init__(self, prefs):

def xmlrpc_connect(self):
try:
self.__server = ServerProxy(self.__prefs.get('SYNC_SERVER'))
p = ProxiedTransport()
p.set_proxy(self.__prefs.get('SYNC_PROXY_SERVER'))
self.__server = ServerProxy(self.__prefs.get('SYNC_SERVER'), transport=p)
self.__connected = True
except Exception, e:
error(str(e))
@@ -1 +1 @@
VERSION="2.6"
VERSION="2.7"
@@ -1,7 +1,8 @@
DenyHosts is a utility developed by Phil Schwartz which aims to
DenyHost is a utility developed by Phil Schwartz
and currently maintained by Jesse Smith which aims to
thwart sshd (ssh server) brute force attacks.

Please refer to http://www.denyhosts.net/faq.html
Please refer to http://denyhost.sf.net

INSTALLATION:
=============
@@ -34,19 +35,14 @@ this, you may wish to install from souce instead.
ALL DISTRIBUTIONS
=================

Once you have installed DenyHosts, by default the directory
/usr/share/denyhosts will be created and a sample configuration
file will be copied into it. A sample daemon-control script will
also be copied into the /usr/share/denyhosts directory.

DenyHosts requires that a configuration file be created before
it can function. The sample configuration file denyhosts.cfg-dist
it can function. The sample configuration file denyhosts.conf
contains most of the possible settings and should be copied and
then edited as such:

# cp denyhosts.cfg-dist denyhosts.cfg
# cp denyhosts.conf /etc

# <edit> denyhosts.cfg
# <edit> /etc/denyhosts.conf

(where <edit> is your preferred text editor such as emacs, vi, etc)

48 TODO

This file was deleted.

@@ -11,9 +11,9 @@
#### Edit these to suit your configuration ####
###############################################

DENYHOSTS_BIN = "/usr/bin/denyhosts.py"
DENYHOSTS_LOCK = "/var/lock/subsys/denyhosts"
DENYHOSTS_CFG = "/usr/share/denyhosts/denyhosts.cfg"
DENYHOSTS_BIN = "/usr/sbin/denyhosts"
DENYHOSTS_LOCK = "/run/denyhosts.pid"
DENYHOSTS_CFG = "/etc/denyhosts.conf"

PYTHON_BIN = "/usr/bin/env python"

@@ -144,7 +144,8 @@ if __name__ == '__main__':

try:
if option in ('start', 'restart', 'condrestart'):
if '--config' not in args and '-c' not in args:
anystartswith = lambda prefix, xs: any(map(lambda x: x.startswith(prefix), xs))
if not anystartswith('--config', args) and '-c' not in args:
args.append("--config=%s" % DENYHOSTS_CFG)

cmd = cases[option]

0 comments on commit e31b186

Please sign in to comment.
You can’t perform that action at this time.