3
3
import argparse
4
4
import getpass
5
5
import hashlib
6
+ import fcntl
6
7
import os
7
8
import re
8
9
import socket
21
22
DOCUMENTATION = """
22
23
lookup: keepass
23
24
author: Victor Zemtsov <[email protected] >
24
- version_added: '0.7.1 '
25
+ version_added: '0.7.2 '
25
26
short_description: Fetching data from KeePass file
26
27
description:
27
28
- This lookup returns a value of a property of a KeePass entry
@@ -88,7 +89,9 @@ def run(self, terms, variables=None, **kwargs):
88
89
socket_path = _keepass_socket_path (var_dbx )
89
90
lock_file_ = socket_path + ".lock"
90
91
91
- if not os .path .isfile (lock_file_ ):
92
+ try :
93
+ os .open (lock_file_ , os .O_RDWR )
94
+ except FileNotFoundError :
92
95
cmd = [
93
96
"/usr/bin/env" ,
94
97
"python3" ,
@@ -189,7 +192,6 @@ def _keepass_socket(kdbx, kdbx_key, sock_path, ttl=60, kdbx_password=None):
189
192
"""
190
193
tmp_files = []
191
194
try :
192
- os .umask (0o177 )
193
195
with socket .socket (socket .AF_UNIX , socket .SOCK_STREAM ) as s :
194
196
s .bind (sock_path )
195
197
s .listen (1 )
@@ -240,6 +242,9 @@ def _keepass_socket(kdbx, kdbx_key, sock_path, ttl=60, kdbx_password=None):
240
242
else :
241
243
conn .send (_resp ("password" , 1 ))
242
244
break
245
+ elif cmd == "password" :
246
+ conn .send (_resp ("password" , 0 ))
247
+ break
243
248
244
249
# CMD: fetch
245
250
# Read data from decrypted KeePass file
@@ -404,6 +409,20 @@ def _keepass_socket_path(dbx_path):
404
409
return "%s/ansible-keepass-%s.sock" % (tempdir , suffix [:8 ])
405
410
406
411
412
+ def lock (kdbx_sock_path ):
413
+ fd = os .open (kdbx_sock_path + ".lock" , os .O_RDWR | os .O_CREAT | os .O_TRUNC )
414
+
415
+ try :
416
+ # The LOCK_EX means that only one process can hold the lock
417
+ # The LOCK_NB means that the fcntl.flock() is not blocking
418
+ # https://docs.python.org/3/library/fcntl.html#fcntl.flock
419
+ fcntl .flock (fd , fcntl .LOCK_EX | fcntl .LOCK_NB )
420
+ except (IOError , OSError ):
421
+ return None
422
+
423
+ return fd
424
+
425
+
407
426
if __name__ == "__main__" :
408
427
arg_parser = argparse .ArgumentParser ()
409
428
arg_parser .add_argument ("kdbx" , type = str )
@@ -413,24 +432,23 @@ def _keepass_socket_path(dbx_path):
413
432
arg_parser .add_argument ("--ask-pass" , action = "store_true" )
414
433
args = arg_parser .parse_args ()
415
434
416
- kdbx = os .path .realpath (os .path .expanduser (os .path .expandvars (args .kdbx )))
435
+ arg_kdbx = os .path .realpath (os .path .expanduser (os .path .expandvars (args .kdbx )))
417
436
if args .key :
418
- key = os .path .realpath (os .path .expanduser (os .path .expandvars (args .key )))
437
+ arg_key = os .path .realpath (os .path .expanduser (os .path .expandvars (args .key )))
419
438
else :
420
- key = None
439
+ arg_key = None
421
440
422
441
if args .kdbx_sock :
423
- kdbx_sock = args .kdbx_sock
442
+ arg_kdbx_sock = args .kdbx_sock
424
443
else :
425
- kdbx_sock = _keepass_socket_path (kdbx )
444
+ arg_kdbx_sock = _keepass_socket_path (arg_kdbx )
426
445
427
446
password = None
428
447
if args .ask_pass :
429
448
password = getpass .getpass ("Password: " )
430
449
if isinstance (password , bytes ):
431
450
password = password .decode (sys .stdin .encoding )
432
451
433
- lock_file = kdbx_sock + ".lock"
434
- if not os .path .isfile (lock_file ):
435
- open (lock_file , "a" ).close ()
436
- _keepass_socket (kdbx , key , kdbx_sock , args .ttl , password )
452
+ os .umask (0o177 )
453
+ if lock (arg_kdbx_sock ):
454
+ _keepass_socket (arg_kdbx , arg_key , arg_kdbx_sock , args .ttl , password )
0 commit comments