Message412495
getpass.getuser() checks the environment variables LOGNAME (login name), USER, LNAME, and USERNAME, in that order. In Windows, LOGNAME, USER, and LNAME have no conventional usage. I think there should be a strict mode that restricts getuser() to check only USERNAME in Windows and only LOGNAME in POSIX [1]. If the login variable isn't defined, it should fall back on using the system API, based on the user ID in POSIX and the logon ID in Windows.
For the fallback in Windows, the _winapi module could implement GetCurrentProcessToken(), GetTokenInformation(), and LsaGetLogonSessionData(). For TokenStatistics, return a dict with just "AuthenticationId". For LsaGetLogonSessionData(), return a dict with just "UserName". GetCurrentProcessToken() returns a pseudohandle (-4), which should not be closed.
For example, assuming _winapi wraps the required functions:
def getuser(strict=False):
"""Get the username from the environment or password database.
First try various environment variables. If strict, check only LOGNAME
in POSIX and only USERNAME in Windows. As a fallback, in POSIX get the
user name from the password database, and in Windows get the user name
from the logon-session data of the current process.
"""
posix = sys.platform != 'win32'
if strict:
names = ('LOGNAME',) if posix else ('USERNAME',)
else:
names = ('LOGNAME', 'USER', 'LNAME', 'USERNAME')
for name in names:
if user := os.environ.get(name):
return user
if posix:
import pwd
return pwd.getpwuid(os.getuid())[0]
import _winapi
logon_id = _winapi.GetTokenInformation(
_winapi.GetCurrentProcessToken(),
_winapi.TokenStatistics)['AuthenticationId']
return _winapi.LsaGetLogonSessionData(logon_id)['UserName']
Like WinAPI GetUserNameW(), the above fallback returns the logon user name instead of the account name of the token user. As far as I know, the user name and the account name only differ for the builtin service account logons "SYSTEM" (999) and "NETWORK SERVICE" (996), for which the user name is the machine security principal (i.e. the machine's NETBIOS name plus "$"). The user name of the builtin "LOCAL SERVICE" logon (997), on the other hand, is just the "LOCAL SERVICE" account name, since this account lacks network access.
Unlike GetUserNameW(), the above code uses the process token instead of the effective token. This is like POSIX getuid(), whereas what GetUserNameW() does is like geteuid(). getuser() could implement an `effective` option to return the effective user name. In Windows this would switch to calling GetCurrentThreadEffectiveToken() instead of GetCurrentProcessToken().
---
[1] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html |
|
Date |
User |
Action |
Args |
2022-02-04 05:55:34 | eryksun | set | recipients:
+ eryksun, paul.moore, tim.golden, zach.ware, steve.dower |
2022-02-04 05:55:34 | eryksun | set | messageid: <1643954134.16.0.436701246605.issue46631@roundup.psfhosted.org> |
2022-02-04 05:55:34 | eryksun | link | issue46631 messages |
2022-02-04 05:55:33 | eryksun | create | |
|