#!/usr/bin/env python3
"""su wrapper - always requires password, actually switches uid"""
import os, sys, getpass, pwd, struct, hashlib

def verify_shadow(username, password):
    """Verify password against /etc/shadow"""
    try:
        with open("/etc/shadow", "r") as f:
            for line in f:
                parts = line.strip().split(":")
                if len(parts) < 2 or parts[0] != username:
                    continue
                stored_hash = parts[1]
                if stored_hash in ("!", "*", "!!", ""):
                    return False  # account locked or no password
                # Use crypt.crypt to verify
                import crypt
                return crypt.crypt(password, stored_hash) == stored_hash
    except PermissionError:
        # Fallback: only root can read shadow, so if we get here non-root called us
        return False
    return False

def main():
    # Parse args: su [options] [user]
    args = sys.argv[1:]
    target = "root"
    login_shell = False
    for a in args:
        if a == "-" or a == "-l" or a == "--login":
            login_shell = True
        elif not a.startswith("-"):
            target = a
            break

    # Get target user info
    try:
        pw = pwd.getpwnam(target)
    except KeyError:
        print(f"su: user {target!r} does not exist", file=sys.stderr)
        sys.exit(1)

    # Always ask for password - no rootok bypass
    try:
        password = getpass.getpass(f"Password: ")
    except (EOFError, KeyboardInterrupt):
        print("\nsu: Authentication failure", file=sys.stderr)
        sys.exit(1)

    # Verify password
    if not verify_shadow(target, password):
        import time; time.sleep(2)  # anti-brute force delay
        print("su: Authentication failure", file=sys.stderr)
        sys.exit(1)

    # Authentication OK - now actually switch user
    try:
        import grp
        # Get supplementary groups for target user
        supp_groups = [g.gr_gid for g in grp.getgrall() if target in g.gr_mem]
        if pw.pw_gid not in supp_groups:
            supp_groups.insert(0, pw.pw_gid)
        os.setgroups(supp_groups)
        os.setgid(pw.pw_gid)
        os.setuid(pw.pw_uid)
    except OSError as e:
        print(f"su: cannot set user id: {e}", file=sys.stderr)
        sys.exit(1)

    # Set environment
    os.environ["HOME"]    = pw.pw_dir
    os.environ["USER"]    = pw.pw_name
    os.environ["LOGNAME"] = pw.pw_name
    os.environ["SHELL"]   = pw.pw_shell or "/bin/bash"
    if login_shell or "-" in sys.argv[1:]:
        # Login shell: clean environment
        os.environ["PATH"] = "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"

    # Change to home directory
    try:
        os.chdir(pw.pw_dir)
    except Exception:
        os.chdir("/")

    # Exec target shell
    shell = pw.pw_shell or "/bin/bash"
    shell_name = ("-" if login_shell else "") + os.path.basename(shell)
    try:
        os.execv(shell, [shell_name])
    except OSError as e:
        print(f"su: failed to execute {shell}: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
