Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for systemd-based distributions #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.idea
MANIFEST
dist
venv/
40 changes: 33 additions & 7 deletions knockknock-daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
"""

import os, sys, pwd, grp

from knockknock.LogEntry import LogEntry
from knockknock.LogFile import LogFile
from knockknock.Profiles import Profiles
from knockknock.PortOpener import PortOpener
from knockknock.DaemonConfiguration import DaemonConfiguration
Expand All @@ -48,6 +45,25 @@ def checkConfiguration():
print "/etc/knockknock.d/profiles/ does not exist. You need to setup your profiles first..."
sys.exit(3)

# Retreive the system init type from /proc
with open('/proc/1/status', 'r') as f:
global initprocname
initprocname = f.readline().split()[1]

# Verify whether or not the python-systemd dependency is required as well
# as whether or not it is fulfilled (optimistically written with python3
# support)
if (sys.version_info > (3, 0)):
import importlib
if initprocname == "systemd" and importlib.util.find_spec("systemd") is None:
print "Your init system was detected as systemd but the python systemd module is not installed. You need to install it first..."
sys.exit(3)
else:
import pkgutil
if initprocname == "systemd" and pkgutil.find_loader("systemd") is None:
print "Your init system was detected as systemd but the python systemd module is not installed. You need to install it first..."
sys.exit(3)

def dropPrivileges():
nobody = pwd.getpwnam('nobody')
adm = grp.getgrnam('adm')
Expand All @@ -62,10 +78,20 @@ def handleFirewall(input, config):

def handleKnocks(output, profiles, config):
dropPrivileges()

logFile = LogFile('/var/log/kern.log')
# Attempt to determine logging source here (since it shouldn't require
# elevated privileges to verify this information) based on the system
# init process
if initprocname == "systemd":
from knockknock.LogJournald import JournalReader
logSource = JournalReader()
elif initprocname in ["init", "preinit"]:
from knockknock.LogFile import LogFile
logSource = LogFile('/var/log/kern.log')
else:
print "Failed to find logging source for your init system. Exiting"
sys.exit(3)
portOpener = PortOpener(output, config.getDelay())
knockWatcher = KnockWatcher(config, logFile, profiles, portOpener)
knockWatcher = KnockWatcher(config, logSource, profiles, portOpener)

knockWatcher.tailAndProcess()

Expand All @@ -90,6 +116,6 @@ def main(argv):
else:
os.close(output)
handleFirewall(os.fdopen(input, 'r'), config)

if __name__ == '__main__':
main(sys.argv[1:])
54 changes: 54 additions & 0 deletions knockknock/LogJournald.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""
Journald log reader event loop for knockknock-daemon.

Contains the JournalReader class which takes no parameters and has 1 method:
(tail)
"""
# Copyright (c) 2015 Jason Ritzke
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
#

import select
import time
from systemd import journal


class JournalReader:
"""
Journald reader for knockknock-daemon.

Takes no parameters on initialization. Has a single event loop method
called tail that yields new messages in the kernel log.
"""

def __init__(self):
"""Initalization method for JournalReader class."""
self.j = journal.Reader()
self.j.seek_tail()
self.j.add_match('_TRANSPORT=kernel')
self.p = select.poll()
self.p.register(self.j, self.j.get_events())

def tail(self):
"""Generator that yields messages from the kernel log."""
while True:
self.p.poll()
line = self.j.get_next()
if 'MESSAGE' not in line:
time.sleep(.25)
else:
yield line['MESSAGE']