From d4c09627277e34e0424e2e2e6b95f48d0ca4574f Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 9 Feb 2023 08:49:15 +0100 Subject: [PATCH] Delay UID change after loop start Listening to a port < 1024 without `--nosetuid` leads to a permission error. The UID change is done too early: we should first open the port, then change the UID. Fixes https://github.com/aio-libs/aiosmtpd/issues/304 --- aiosmtpd/main.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/aiosmtpd/main.py b/aiosmtpd/main.py index 166484ca..dfc86382 100644 --- a/aiosmtpd/main.py +++ b/aiosmtpd/main.py @@ -217,22 +217,6 @@ def parseargs(args: Optional[Sequence[str]] = None) -> Tuple[ArgumentParser, Nam def main(args: Optional[Sequence[str]] = None) -> None: parser, args = parseargs(args=args) - if args.setuid: # pragma: on-win32 - if pwd is None: - print( - 'Cannot import module "pwd"; try running with -n option.', - file=sys.stderr, - ) - sys.exit(1) - nobody = pwd.getpwnam("nobody").pw_uid - try: - os.setuid(nobody) - except PermissionError: - print( - 'Cannot setuid "nobody"; try running with -n option.', file=sys.stderr - ) - sys.exit(1) - if args.tlscert and args.tlskey: tls_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) tls_context.check_hostname = False @@ -279,6 +263,24 @@ def main(args: Optional[Sequence[str]] = None) -> None: log.debug(f"server_loop = {server_loop}") log.info("Server is listening on %s:%s", args.host, args.port) + # Change the UID after opening the port. This allows listening on port < 1024 without any + # system tweak. + if args.setuid: # pragma: on-win32 + if pwd is None: + print( + 'Cannot import module "pwd"; try running with -n option.', + file=sys.stderr, + ) + sys.exit(1) + nobody = pwd.getpwnam("nobody").pw_uid + try: + os.setuid(nobody) + except PermissionError: + print( + 'Cannot setuid "nobody"; try running with -n option.', file=sys.stderr + ) + sys.exit(1) + # Signal handlers are only supported on *nix, so just ignore the failure # to set this on Windows. with suppress(NotImplementedError):