Add support for file-descriptor-based socket server

(for NeoPG)
master
Roman Zeyde 6 years ago
parent bc691ae795
commit 912b1cde7a
No known key found for this signature in database
GPG Key ID: 87CAE5FA46917CBB

@ -202,11 +202,25 @@ def run_unlock(device_type, args):
log.info('unlocked %s device', d)
def _server_from_assuan_fd(env):
fd = os.environ.get('_assuan_connection_fd')
if fd is not None:
log.info('using fd=%r for UNIX socket server', fd)
return server.unix_domain_socket_server_from_fd(int(fd))
def _server_from_sock_path(env):
sock_path = keyring.get_agent_sock_path(env=env)
return server.unix_domain_socket_server(sock_path)
def run_agent(device_type):
"""Run a simple GPG-agent server."""
p = argparse.ArgumentParser()
p.add_argument('--homedir', default=os.environ.get('GNUPGHOME'))
p.add_argument('-v', '--verbose', default=0, action='count')
p.add_argument('--server', default=False, action='store_true',
help='Use stdin/stdout for communication with GPG.')
p.add_argument('--pin-entry-binary', type=str, default='pinentry',
help='Path to PIN entry UI helper.')
@ -225,22 +239,30 @@ def run_agent(device_type):
log.debug('pid: %d, parent pid: %d', os.getpid(), os.getppid())
try:
env = {'GNUPGHOME': args.homedir}
sock_path = keyring.get_agent_sock_path(env=env)
pubkey_bytes = keyring.export_public_keys(env=env)
device_type.ui = device.ui.UI(device_type=device_type,
config=vars(args))
with server.unix_domain_socket_server(sock_path) as sock:
handler = agent.Handler(device=device_type(),
pubkey_bytes=pubkey_bytes)
sock_server = _server_from_assuan_fd(os.environ)
if sock_server is None:
sock_server = _server_from_sock_path(env)
with sock_server as sock:
for conn in agent.yield_connections(sock):
handler = agent.Handler(device=device_type(),
pubkey_bytes=pubkey_bytes)
with contextlib.closing(conn):
try:
handler.handle(conn)
except agent.AgentStop:
log.info('stopping gpg-agent')
return
except IOError as e:
log.info('connection closed: %s', e)
return
except Exception as e: # pylint: disable=broad-except
log.exception('handler failed: %s', e)
except Exception as e: # pylint: disable=broad-except
log.exception('gpg-agent failed: %s', e)

@ -39,6 +39,35 @@ def unix_domain_socket_server(sock_path):
remove_file(sock_path)
class FDServer(object):
def __init__(self, fd):
self.fd = fd
self.sock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
def accept(self):
return self, None
def recv(self, n):
return self.sock.recv(n)
def sendall(self, data):
return self.sock.sendall(data)
def close(self):
pass
def settimeout(self, _):
pass
def getsockname(self):
return '<fd: {}>'.format(self.fd)
@contextlib.contextmanager
def unix_domain_socket_server_from_fd(fd):
yield FDServer(fd)
def handle_connection(conn, handler, mutex):
"""
Handle a single connection using the specified protocol handler in a loop.

Loading…
Cancel
Save