in gslib/utils/posix_util.py [0:0]
def ValidateFilePermissionAccess(url_str, uid=NA_ID, gid=NA_ID, mode=NA_MODE):
"""Validates that the user has file access if uid, gid, and mode are applied.
Args:
url_str: The path to the object for which this is validating.
uid: A POSIX user ID.
gid: A POSIX group ID.
mode: A 3-digit, number representing POSIX permissions, must be in base-8.
Returns:
A (bool, str) tuple, True if and only if it's safe to copy the file, and a
string containing details for the error.
"""
# Windows doesn't use the POSIX system for file permissions, so all files will
# validate.
if IS_WINDOWS:
return True, ''
uid_present = uid > NA_ID
gid_present = int(gid) > NA_ID
mode_present = mode > NA_MODE
# No need to perform validation if Posix attrs are not being preserved.
if not (uid_present or gid_present or mode_present):
return True, ''
# The root user on non-Windows systems can access files regardless of their
# permissions.
if os.geteuid() == 0:
return True, ''
mode_valid = ValidatePOSIXMode(int(str(mode), 8))
if mode_present:
if not mode_valid:
return False, 'Mode for %s won\'t allow read access.' % url_str
else:
# Calculate the default mode if the mode doesn't exist.
# Convert mode to a 3-digit, base-8 integer.
mode = int(SYSTEM_POSIX_MODE)
if uid_present:
try:
pwd.getpwuid(uid)
except (KeyError, OverflowError):
return (False, 'UID for %s doesn\'t exist on current system. uid: %d' %
(url_str, uid))
if gid_present:
try:
grp.getgrgid(gid)
except (KeyError, OverflowError):
return (False, 'GID for %s doesn\'t exist on current system. gid: %d' %
(url_str, gid))
# uid at this point must exist, but isn't necessarily the current user.
# Likewise, gid must also exist at this point.
uid_is_current_user = uid == os.getuid()
# By this point uid and gid must exist on the system. However, the uid might
# not match the current user's or the current user might not be a member of
# the group identified by gid. In this case, the 'other' byte of the
# permissions could provide sufficient access.
mode = int(str(mode), 8)
# Check that if the uid is not present and the gid and mode are, so that we
# won't orphan the file. For example if the mode is set to 007, we can orphan
# the file because the uid would default to the current user's ID and if the
# current user wouldn't have read access or better, the file will be orphaned
# even though they might otherwise have access through the gid or other bytes.
if not uid_present and gid_present and mode_present and not bool(mode & U_R):
return (False, 'Insufficient access with uid/gid/mode for %s, gid: %d, '
'mode: %s' % (url_str, gid, oct(mode)[-3:]))
if uid_is_current_user:
valid = bool(mode & U_R)
return (valid, '' if valid else
'Insufficient access with uid/gid/mode for %s, uid: %d, '
'mode: %s' % (url_str, uid, oct(mode)[-3:]))
elif int(gid) in USER_GROUPS:
valid = bool(mode & G_R)
return (valid, '' if valid else
'Insufficient access with uid/gid/mode for %s, gid: %d, '
'mode: %s' % (url_str, gid, oct(mode)[-3:]))
elif mode & O_R:
return True, ''
elif not uid_present and not gid_present and mode_valid:
return True, ''
return False, 'There was a problem validating %s.' % url_str