Various python cleanups -- note fix_private-bin.py is (still) broken

This commit is contained in:
Fred-Barclay 2018-11-19 17:45:11 -06:00
parent 7c903b45c2
commit a179c7dc91
No known key found for this signature in database
GPG key ID: 7338CE369A928102
5 changed files with 184 additions and 152 deletions

View file

@ -29,80 +29,84 @@ __license__ = "Unlicense"
import sys, os, glob, re
privRx=re.compile("^(?:#\s*)?private-bin")
privRx = re.compile("^(?:#\s*)?private-bin")
def fixSymlinkedBins(files, replMap):
"""
"""
Used to add filenames to private-bin directives of files if the ones present are mentioned in replMap
replMap is a dict where key is the marker filename and value is the filename to add
"""
rxs=dict()
for (old,new) in replMap.items():
rxs[old]=re.compile("\\b"+old+"\\b")
rxs[new]=re.compile("\\b"+new+"\\b")
#print(rxs)
rxs = dict()
for (old, new) in replMap.items():
rxs[old] = re.compile("\\b" + old + "\\b")
rxs[new] = re.compile("\\b" + new + "\\b")
#print(rxs)
for filename in files:
lines=None
with open(filename,"r") as file:
lines=file.readlines()
for filename in files:
lines = None
with open(filename, "r") as file:
lines = file.readlines()
shouldUpdate=False
for (i,line) in enumerate(lines):
if privRx.search(line):
for (old,new) in replMap.items():
if rxs[old].search(line) and not rxs[new].search(line):
lines[i]=rxs[old].sub(old+","+new, line)
shouldUpdate=True
print(lines[i])
shouldUpdate = False
for (i, line) in enumerate(lines):
if privRx.search(line):
for (old, new) in replMap.items():
if rxs[old].search(line) and not rxs[new].search(line):
lines[i] = rxs[old].sub(old + "," + new, line)
shouldUpdate = True
print(lines[i])
if shouldUpdate:
with open(filename, "w") as file:
file.writelines(lines)
pass
if shouldUpdate:
with open(filename,"w") as file:
file.writelines(lines)
pass
def createSetOfBinaries(files):
"""
"""
Creates a set of binaries mentioned in private-bin directives of files.
"""
s=set()
for filename in files:
lines=None
with open(filename,"r") as file:
for line in file:
if privRx.search(line):
bins=line.split(",")
bins[0]=bins[0].split(" ")[-1]
bins = [n.strip() for n in bins]
s=s|set(bins)
return s
s = set()
for filename in files:
lines = None
with open(filename, "r") as file:
for line in file:
if privRx.search(line):
bins = line.split(",")
bins[0] = bins[0].split(" ")[-1]
bins = [n.strip() for n in bins]
s = s | set(bins)
return s
def createSymlinkTable(binDirs, binariesSet):
"""
"""
creates a dict of symlinked binaries in the system where a key is a symlink name and value is a symlinked binary.
binDirs are folders to look into for binaries symlinks
binariesSet is a set of binaries to be checked if they are actually a symlinks
"""
m=dict()
toProcess=binariesSet
while len(toProcess)!=0:
additional=set()
for sh in toProcess:
for bD in binDirs:
p=bD+os.path.sep+sh
if os.path.exists(p):
if os.path.islink(p):
m[sh]=os.readlink(p)
additional.add(m[sh].split(" ")[0])
else:
pass
break
toProcess=additional
return m
m = dict()
toProcess = binariesSet
while len(toProcess) != 0:
additional = set()
for sh in toProcess:
for bD in binDirs:
p = bD + os.path.sep + sh
if os.path.exists(p):
if os.path.islink(p):
m[sh] = os.readlink(p)
additional.add(m[sh].split(" ")[0])
else:
pass
break
toProcess = additional
return m
def doTheFixes(profilesPath, binDirs):
"""
"""
Fixes private-bin in .profiles for firejail. The pipeline is as follows:
discover files -> discover mentioned binaries ->
discover the ones which are symlinks ->
@ -110,48 +114,60 @@ def doTheFixes(profilesPath, binDirs):
filter the ones can be fixed (we cannot fix the ones which are not in directories for binaries) ->
apply fix
"""
files=glob.glob(profilesPath+os.path.sep+"*.profile")
bins=createSetOfBinaries(files)
#print("The binaries used are:")
#print(bins)
stbl=createSymlinkTable(binDirs,bins)
print("The replacement table is:")
print(stbl)
stbl={a[0]:a[1] for a in stbl.items() if a[0].find(os.path.sep) < 0 and a[1].find(os.path.sep)<0}
print("Filtered replacement table is:")
print(stbl)
fixSymlinkedBins(files,stbl)
files = glob.glob(profilesPath + os.path.sep + "*.profile")
bins = createSetOfBinaries(files)
#print("The binaries used are:")
#print(bins)
stbl = createSymlinkTable(binDirs, bins)
print("The replacement table is:")
print(stbl)
stbl = {
a[0]: a[1]
for a in stbl.items()
if a[0].find(os.path.sep) < 0 and a[1].find(os.path.sep) < 0
}
print("Filtered replacement table is:")
print(stbl)
fixSymlinkedBins(files, stbl)
def printHelp():
print("python3 "+os.path.basename(__file__)+" <dir with .profile files>\nThe default dir is "+defaultProfilesPath+"\n"+doTheFixes.__doc__)
print("python3 " + os.path.basename(__file__) +
" <dir with .profile files>\nThe default dir is " +
defaultProfilesPath + "\n" + doTheFixes.__doc__)
def main():
"""The main function. Parses the commandline args, shows messages and calles the function actually doing the work."""
print(repr(sys.argv))
defaultProfilesPath="../etc"
if len(sys.argv)>2 or (len(sys.argv)==2 and (sys.argv[1] == '-h' or sys.argv[1] == '--help') ):
printHelp()
exit(1)
"""The main function. Parses the commandline args, shows messages and calles the function actually doing the work."""
print(repr(sys.argv))
defaultProfilesPath = "../etc"
if len(sys.argv) > 2 or (len(sys.argv) == 2 and
(sys.argv[1] == '-h' or sys.argv[1] == '--help')):
printHelp()
exit(1)
profilesPath=None
if len(sys.argv)==2:
if os.path.isdir(sys.argv[1]):
profilesPath=os.path.abspath(sys.argv[1])
else:
if os.path.exists(sys.argv[1]):
print(sys.argv[1]+" is not a dir")
else:
print(sys.argv[1]+" does not exist")
printHelp()
exit(1)
else:
print("Using default profiles dir: " + defaultProfilesPath)
profilesPath=defaultProfilesPath
profilesPath = None
if len(sys.argv) == 2:
if os.path.isdir(sys.argv[1]):
profilesPath = os.path.abspath(sys.argv[1])
else:
if os.path.exists(sys.argv[1]):
print(sys.argv[1] + " is not a dir")
else:
print(sys.argv[1] + " does not exist")
printHelp()
exit(1)
else:
print("Using default profiles dir: " + defaultProfilesPath)
profilesPath = defaultProfilesPath
binDirs = [
"/bin", "/usr/bin", "/usr/sbin", "/usr/local/bin", "/usr/local/sbin"
]
print("Binaries dirs are:")
print(binDirs)
doTheFixes(profilesPath, binDirs)
binDirs=["/bin","/usr/bin","/usr/sbin","/usr/local/bin","/usr/local/sbin"]
print("Binaries dirs are:")
print(binDirs)
doTheFixes(profilesPath, binDirs)
if __name__ == "__main__":
main()
main()

View file

@ -4,42 +4,46 @@
import os, re, shlex, subprocess, sys
def run(srcdir, args):
if srcdir: os.chdir(srcdir)
if srcdir: os.chdir(srcdir)
dry_run=False
escaped_args=[]
# We need to modify the list as we go. So be sure to copy the list to be iterated!
for a in args[:]:
if a.startswith('--prefix'):
# prefix should ALWAYS be /usr here. Discard user-set values
args.remove(a)
elif a == '--only-fix-mkdeb':
# for us, not configure
dry_run=True
args.remove(a)
else:
escaped_args.append(shlex.quote(a))
dry_run = False
escaped_args = []
# We need to modify the list as we go. So be sure to copy the list to be iterated!
for a in args[:]:
if a.startswith('--prefix'):
# prefix should ALWAYS be /usr here. Discard user-set values
args.remove(a)
elif a == '--only-fix-mkdeb':
# for us, not configure
dry_run = True
args.remove(a)
else:
escaped_args.append(shlex.quote(a))
# Fix up mkdeb.sh to include custom configure options.
with open('mkdeb.sh', 'rb') as f:
sh=str(f.read(), 'utf_8')
rx=re.compile(r'^\./configure\s.*$', re.M)
with open('mkdeb.sh', 'wb') as f:
f.write(bytes(rx.sub('./configure --prefix=/usr '+(' '.join(escaped_args)), sh), 'utf_8'))
# Fix up mkdeb.sh to include custom configure options.
with open('mkdeb.sh', 'rb') as f:
sh = str(f.read(), 'utf_8')
rx = re.compile(r'^\./configure\s.*$', re.M)
with open('mkdeb.sh', 'wb') as f:
f.write(
bytes(
rx.sub('./configure --prefix=/usr ' + (' '.join(escaped_args)),
sh), 'utf_8'))
if dry_run: return 0
if dry_run: return 0
# now run configure && make
if subprocess.call(['./configure', '--prefix=/usr']+args) == 0:
subprocess.call(['make', 'deb'])
# now run configure && make
if subprocess.call(['./configure', '--prefix=/usr'] + args) == 0:
subprocess.call(['make', 'deb'])
return 0
return 0
if __name__ == '__main__':
if len(sys.argv) == 2 and sys.argv[1] == '--help':
print('''Build a .deb of firejail with custom configure options
if len(sys.argv) == 2 and sys.argv[1] == '--help':
print('''Build a .deb of firejail with custom configure options
usage:
{script} [--fj-src=SRCDIR] [--only-fix-mkdeb] [CONFIGURE_OPTIONS [...]]
@ -51,24 +55,26 @@ usage:
--only-fix-mkdeb: don't run configure or make after modifying mkdeb.sh
CONFIGURE_OPTIONS: arguments for configure
'''.format(script=sys.argv[0]))
sys.exit(0)
else:
# Find the source directory
srcdir=None
args=sys.argv[1:]
for a in args:
if a.startswith('--fj-src='):
args.remove(a)
srcdir=a[9:]
break
if not(srcdir):
# srcdir not manually specified, try to auto-detect
srcdir=os.path.dirname(os.path.abspath(sys.argv[0]+'/..'))
if not(os.path.isfile(srcdir+'/mkdeb.sh')):
# Script is probably installed. Check the cwd.
if os.path.isfile('./mkdeb.sh'):
srcdir=None
else:
print('Error: Could not find the firejail source tree. Exiting.')
sys.exit(1)
sys.exit(run(srcdir, args))
sys.exit(0)
else:
# Find the source directory
srcdir = None
args = sys.argv[1:]
for a in args:
if a.startswith('--fj-src='):
args.remove(a)
srcdir = a[9:]
break
if not (srcdir):
# srcdir not manually specified, try to auto-detect
srcdir = os.path.dirname(os.path.abspath(sys.argv[0] + '/..'))
if not (os.path.isfile(srcdir + '/mkdeb.sh')):
# Script is probably installed. Check the cwd.
if os.path.isfile('./mkdeb.sh'):
srcdir = None
else:
print(
'Error: Could not find the firejail source tree. Exiting.'
)
sys.exit(1)
sys.exit(run(srcdir, args))

View file

@ -23,7 +23,7 @@ if sys.argv[1] == '-':
clipin_raw = sys.stdin.read()
else:
display = fjdisplay.getdisplay(sys.argv[1])
clipin_raw = subprocess.check_output(['xsel','-b','--display',display])
clipin_raw = subprocess.check_output(['xsel', '-b', '--display', display])
clipin = clipin_raw.strip()
@ -31,5 +31,6 @@ if sys.argv[2] == '-':
print(clipin)
else:
display = fjdisplay.getdisplay(sys.argv[2])
clipout = subprocess.Popen(['xsel','-b','-i','--display',display],stdin=subprocess.PIPE)
clipout = subprocess.Popen(['xsel', '-b', '-i', '--display', display],
stdin=subprocess.PIPE)
clipout.communicate(clipin)

View file

@ -8,23 +8,25 @@ usage = """fjdisplay.py name-of-firejail
returns the display in the form of ':NNN'
"""
def getfirejails():
output = subprocess.check_output(['firemon','--x11'])
output = subprocess.check_output(['firemon', '--x11'])
firejails = {}
name = ''
for line in output.split('\n'):
namematch = re.search('--name=(\w+\S*)',line)
namematch = re.search('--name=(\w+\S*)', line)
if namematch:
name = namematch.group(1)
displaymatch = re.search('DISPLAY (:\d+)',line)
name = namematch.group(1)
displaymatch = re.search('DISPLAY (:\d+)', line)
if displaymatch:
firejails[name] = displaymatch.group(1)
firejails[name] = displaymatch.group(1)
return firejails
def getdisplay(name):
firejails = getfirejails()
fjlist = '\n'.join(firejails.keys())
namere = re.compile('^'+name+'.*', re.MULTILINE)
namere = re.compile('^' + name + '.*', re.MULTILINE)
matchingjails = namere.findall(fjlist)
if len(matchingjails) == 1:
return firejails[matchingjails[0]]
@ -33,6 +35,7 @@ def getdisplay(name):
else:
raise NameError("ambiguous firejail name")
if __name__ == '__main__':
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) > 2:
print(usage)
@ -40,4 +43,4 @@ if __name__ == '__main__':
if len(sys.argv) == 1:
print(getfirejails())
if len(sys.argv) == 2:
print (getdisplay(sys.argv[1]))
print(getdisplay(sys.argv[1]))

View file

@ -6,20 +6,26 @@ import subprocess
usage = """usage: fjresize.py firejail-name displaysize
resize firejail xephyr windows.
fjdisplay.py with no other arguments will list running named firejails with displays.
fjdisplay.py with no other arguments will list running named firejails with
displays.
fjresize.py with only a firejail name will list valid resolutions.
names can be shortened as long its unambiguous.
names can be shortened as long as it's unambiguous.
note: you may need to move the xephyr window for the resize to take effect
example:
fjresize.py browser 1280x800
"""
if len(sys.argv) == 2:
out = subprocess.check_output(['xrandr','--display',fjdisplay.getdisplay(sys.argv[1])])
out = subprocess.check_output(
['xrandr', '--display',
fjdisplay.getdisplay(sys.argv[1])])
print(out)
elif len(sys.argv) == 3:
out = subprocess.check_output(['xrandr','--display',fjdisplay.getdisplay(sys.argv[1]),'--output','default','--mode',sys.argv[2]])
out = subprocess.check_output([
'xrandr', '--display',
fjdisplay.getdisplay(sys.argv[1]), '--output', 'default', '--mode',
sys.argv[2]
])
print(out)
else:
print(usage)