2 keyring/backends/file.py | 85 ++++++++++++++++++++++-------------------------
3 1 file changed, 41 insertions(+), 44 deletions(-)
5 --- a/keyring/backends/file.py
6 +++ b/keyring/backends/file.py
7 @@ -18,6 +18,7 @@ from ..backend import KeyringBackend
8 from ..util import platform_, properties
9 from ..util.escape import escape as escape_for_ini
10 from oslo_concurrency import lockutils
11 +from tempfile import mkstemp
14 lockfile = "keyringlock"
15 @@ -102,11 +103,9 @@ class BaseKeyring(FileBacked, KeyringBac
17 password_base64 = base64.encodestring(password_encrypted).decode()
19 - lockdir = os.path.dirname(self.file_path)
21 - with lockutils.lock(lockfile,external=True,lock_path=lockdir):
23 + keyringdir = os.path.dirname(self.file_path)
25 + with lockutils.lock(lockfile, external=True, lock_path=keyringdir):
28 # Load the keyring from the disk
29 @@ -121,16 +120,20 @@ class BaseKeyring(FileBacked, KeyringBac
30 config.add_section(service)
31 config.set(service, username, password_base64)
33 - # Save the keyring back to the file
34 - storage_root = os.path.dirname(self.file_path)
35 - tmpfile = "tmpfile.%s" % os.getpid()
36 - with open(storage_root + "/" + tmpfile, 'w') as config_file:
37 - config.write(config_file)
38 - # copy will overwrite but move will not
39 - shutil.copy(storage_root + "/" + tmpfile,self.file_path)
40 - # wipe out tmpfile here
41 - os.remove(storage_root + "/" + tmpfile)
42 + # remove any residual temporary files here
44 + for tmpfile in glob.glob("%s/tmp*" % keyringdir):
47 + logging.warning("_check_file: tmpfile removal failed")
49 + # Write the keyring to a temp file, then move the new file
50 + # to avoid overwriting the existing inode
51 + (fd, fname) = mkstemp(dir=keyringdir)
52 + with os.fdopen(fd, "w") as config_file:
53 + config.write(config_file)
54 + os.chmod(fname, os.stat(self.file_path).st_mode)
55 + shutil.move(fname, self.file_path)
58 def _ensure_file_path(self):
59 @@ -167,8 +170,8 @@ class BaseKeyring(FileBacked, KeyringBac
60 service = escape_for_ini(service)
61 username = escape_for_ini(username)
63 - lockdir = os.path.dirname(self.file_path)
64 - with lockutils.lock(lockfile,external=True,lock_path=lockdir):
65 + keyringdir = os.path.dirname(self.file_path)
66 + with lockutils.lock(lockfile, external=True, lock_path=keyringdir):
67 config = configparser.RawConfigParser()
68 if os.path.exists(self.file_path):
69 config.read(self.file_path)
70 @@ -177,15 +180,21 @@ class BaseKeyring(FileBacked, KeyringBac
71 raise PasswordDeleteError("Password not found")
72 except configparser.NoSectionError:
73 raise PasswordDeleteError("Password not found")
75 - storage_root = os.path.dirname(self.file_path)
76 - tmpfile = "tmpfile.%s" % os.getpid()
77 - with open(storage_root + "/" + tmpfile, 'w') as config_file:
79 + # remove any residual temporary files here
81 + for tmpfile in glob.glob("%s/tmp*" % keyringdir):
84 + logging.warning("_check_file: tmpfile removal failed")
86 + # Write the keyring to a temp file, then move the new file
87 + # to avoid overwriting the existing inode
88 + (fd, fname) = mkstemp(dir=keyringdir)
89 + with os.fdopen(fd, "w") as config_file:
90 config.write(config_file)
91 - # copy will overwrite but move will not
92 - shutil.copy(storage_root + "/" + tmpfile,self.file_path)
94 - os.remove(storage_root + "/" + tmpfile)
95 + os.chmod(fname, os.stat(self.file_path).st_mode)
96 + shutil.move(fname, self.file_path)
99 class PlaintextKeyring(BaseKeyring):
100 @@ -294,27 +303,15 @@ class EncryptedKeyring(Encrypted, BaseKe
104 - lockdir = os.path.dirname(self.file_path)
105 - # lock access to the file_path here, make sure it's not being written
106 - # to while while we're checking for keyring-setting
107 - with lockutils.lock(lockfile,external=True,lock_path=lockdir):
108 - config = configparser.RawConfigParser()
109 - config.read(self.file_path)
112 - escape_for_ini('keyring-setting'),
113 - escape_for_ini('password reference'),
115 - except (configparser.NoSectionError, configparser.NoOptionError):
118 - # remove any residual temporary files here
120 - for tmpfile in glob.glob(os.path.dirname(self.file_path) + "/" + "tmpfile.*"):
123 - logging.warning("_check_file: tmpfile removal failed")
125 + config = configparser.RawConfigParser()
126 + config.read(self.file_path)
129 + escape_for_ini('keyring-setting'),
130 + escape_for_ini('password reference'),
132 + except (configparser.NoSectionError, configparser.NoOptionError):