aboutsummaryrefslogtreecommitdiffstats
path: root/clip
diff options
context:
space:
mode:
authorVG <vg@devys.org>2017-11-06 09:38:44 +0100
committerVG <vg@devys.org>2017-11-06 09:38:44 +0100
commit34ad0bf48aa860e42c60660533bf2f003918c178 (patch)
treebb2760ff3dfcff470a073de8e44196a5c503da03 /clip
parent0cf7d57bdebd919b3ab185ae4c4de389b11481eb (diff)
downloadclip-master.tar.gz
clip-master.tar.bz2
clip-master.zip
Change secure_open for a more secure functionHEADmaster
By using a directory and directory file descriptors, we avoid hardlink and symlinks attacks.
Diffstat (limited to 'clip')
-rwxr-xr-xclip37
1 files changed, 18 insertions, 19 deletions
diff --git a/clip b/clip
index 09e28f4..df72a9a 100755
--- a/clip
+++ b/clip
@@ -19,6 +19,7 @@ Use content:
import contextlib
+import functools
import getpass
import os
import sys
@@ -28,32 +29,30 @@ class Error(Exception): pass
class SecurityError(Error): pass
-def fileno(filelike):
- if getattr(filelike, 'fileno'):
- return filelike.fileno()
- elif getattr(filelike, 'buffer'):
- return filelike.buffer.fileno()
- raise Error("fileno not found inside file-like object")
+@contextlib.contextmanager
+def secure_opendir(dirname):
+ os.makedirs(dirname, mode=0o700, exist_ok=True)
+ dfd = os.open(dirname, os.O_RDONLY | os.O_DIRECTORY)
+ try:
+ dir_stat = os.stat(dfd)
+ if (dir_stat.st_uid != os.getuid() or dir_stat.st_mode & 0o777 != 0o700):
+ raise SecurityError('Wrong directory permissions/owner')
+ yield dfd
+ finally:
+ os.close(dfd)
@contextlib.contextmanager
-def secure_open(path, mode='r', *l, **kw):
- if os.path.islink(path):
- raise SecurityError("The clipboard file can not be a symlink")
- real_mode = mode.replace('w', 'a')
- with open(path, real_mode, *l, **kw) as fo:
- if os.fstat(fileno(fo)) != os.stat(path):
- raise SecurityError("Intrusion might have been done on %s" % path)
- if 'w' in mode:
- os.lseek(fileno(fo), 0, os.SEEK_SET)
- os.ftruncate(fileno(fo), 0)
- os.fchmod(fileno(fo), 0o600)
- yield fo
+def secure_open(*l, **kw):
+ with secure_opendir(os.path.dirname(l[0])) as dfd:
+ _opener = functools.partial(os.open, dir_fd=dfd)
+ with open(*l, **kw, opener=_opener) as ffd:
+ yield ffd
if __name__ == '__main__':
os.umask(0o077)
- clipboard_filepath = '/dev/shm/%s-clipboard' % getpass.getuser()
+ clipboard_filepath = '/dev/shm/%s-clipboard/content' % getpass.getuser()
if(sys.stdin.isatty()):
# Should write clipboard contents out to stdout
try: