apparmor/Tools/aa-unconfined

105 lines
No EOL
4 KiB
Python

#!/usr/bin/python
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License as published by the Free Software Foundation.
#
# 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.
#
# ----------------------------------------------------------------------
import argparse
import gettext
import locale
import os
import re
import sys
from apparmor.common import init_translations
init_translations()
import apparmor.aa as apparmor
#gettext.bindtextdomain('apparmor-utils', '/usr/share/locale/')#/%s/LC_MESSAGES/apparmor-utils.mo' % locale.getlocale()[0])
#gettext.textdomain('apparmor-utils')
#_ = gettext.gettext
#gettext.translation('apparmor-utils','./Trans/')
#gettext.install('apparmor-utils')
#print(os.path.join('/usr/share/locale', locale.getlocale()[0], 'LC_MESSAGES', '%s.mo' %
# 'apparmor-utils'))
#_ = gettext.translation('apparmor-utils', '/usr/share/locale', [locale.getlocale()[0]]).gettext
#gettext.find
parser = argparse.ArgumentParser(description=_('Lists unconfined processes having tcp or udp ports'))
parser.add_argument('--paranoid', action='store_true', help=_('scan all processes from /proc'))
args = parser.parse_args()
paranoid = args.paranoid
aa_mountpoint = apparmor.check_for_apparmor()
if not aa_mountpoint:
raise apparmor.AppArmorException(_('It seems AppArmor was not started. Please enable AppArmor and try again.'))
pids = []
if paranoid:
pids = list(filter(lambda x: re.search('^\d+$', x), apparmor.get_subdirectories('/proc')))
else:
regex_tcp_udp = re.compile('^(tcp|udp)\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\s+)\s+(\d+)\/(\S+)')
import subprocess
if sys.version_info < (3,0):
output = subprocess.check_output('LANG=C netstat -nlp', shell=True).split('\n')
else:
#Python3 needs to translate a stream of bytes to string with specified encoding
output = str(subprocess.check_output('LANG=C netstat -nlp', shell=True), encoding='utf8').split('\n')
for line in output:
match = regex_tcp_udp.search(line)
if match:
pids.append(match.groups()[4])
# We can safely remove duplicate pid's?
pids = list(map(lambda x: int(x), set(pids)))
for pid in sorted(pids):
try:
prog = os.readlink('/proc/%s/exe'%pid)
except:
continue
attr = None
if os.path.exists('/proc/%s/attr/current'%pid):
with apparmor.open_file_read('/proc/%s/attr/current'%pid) as current:
for line in current:
if line.startswith('/') or line.startswith('null'):
attr = line.strip()
cmdline = apparmor.cmd(['cat', '/proc/%s/cmdline'%pid])[1]
pname = cmdline.split('\0')[0]
if '/' in pname and pname != prog:
pname = '(%s)'%pname
else:
pname = ''
regex_interpreter = re.compile('^(/usr)?/bin/(python|perl|bash|dash|sh)$')
if not attr:
if regex_interpreter.search(prog):
cmdline = re.sub('\x00', ' ', cmdline)
cmdline = re.sub('\s+$', '', cmdline).strip()
apparmor.UI_Info(_('%s %s (%s) not confined\n')%(pid, prog, cmdline))
else:
if pname and pname[-1] == ')':
pname += ' '
apparmor.UI_Info(_('%s %s %snot confined\n')%(pid, prog, pname))
else:
if regex_interpreter.search(prog):
cmdline = re.sub('\0', ' ', cmdline)
cmdline = re.sub('\s+$', '', cmdline).strip()
apparmor.UI_Info(_("%s %s (%s) confined by '%s'\n")%(pid, prog, cmdline, attr))
else:
if pname and pname[-1] == ')':
pname += ' '
apparmor.UI_Info(_("%s %s %sconfined by '%s'\n")%(pid, prog, pname, attr))