diff --git a/contrib/fix_private-bin.py b/contrib/fix_private-bin.py index 613a945a8..65bfba52d 100755 --- a/contrib/fix_private-bin.py +++ b/contrib/fix_private-bin.py @@ -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__)+" \nThe default dir is "+defaultProfilesPath+"\n"+doTheFixes.__doc__) + print("python3 " + os.path.basename(__file__) + + " \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() diff --git a/contrib/fj-mkdeb.py b/contrib/fj-mkdeb.py index 3cc13b758..89b4e46a9 100755 --- a/contrib/fj-mkdeb.py +++ b/contrib/fj-mkdeb.py @@ -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)) diff --git a/contrib/fjclip.py b/contrib/fjclip.py index b45959841..3d0c56dc6 100755 --- a/contrib/fjclip.py +++ b/contrib/fjclip.py @@ -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) diff --git a/contrib/fjdisplay.py b/contrib/fjdisplay.py index 3f409545f..7b2db549a 100755 --- a/contrib/fjdisplay.py +++ b/contrib/fjdisplay.py @@ -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])) diff --git a/contrib/fjresize.py b/contrib/fjresize.py index 4eb33f120..95b76259d 100755 --- a/contrib/fjresize.py +++ b/contrib/fjresize.py @@ -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)