Relocated a few functions

N2009_11_14_FIXES
jpandre 2008-04-17 16:14:59 +00:00
parent 0af78a2c5f
commit eb519fee8c
1 changed files with 301 additions and 301 deletions

View File

@ -274,6 +274,246 @@ static const char ownersidbytes[] = {
static const SID *ownersid = (const SID*)ownersidbytes;
/*
* Determine the size of a SID
*/
static int sid_size(const SID * sid)
{
return (sid->sub_authority_count * 4 + 8);
}
/*
* Test whether two SID are equal
*/
static BOOL same_sid(const SID *first, const SID *second)
{
int size;
size = sid_size(first);
return ((sid_size(second) == size)
&& !memcmp(first, second, size));
}
/*
* Test whether a SID means "world user"
* Local users group also recognized as world
*/
static int is_world_sid(const SID * usid)
{
return (
/* check whether S-1-1-0 : world */
((usid->sub_authority_count == 1)
&& (usid->identifier_authority.high_part == cpu_to_be32(0))
&& (usid->identifier_authority.low_part == cpu_to_be32(1))
&& (usid->sub_authority[0] == 0))
/* check whether S-1-5-32-545 : local user */
|| ((usid->sub_authority_count == 2)
&& (usid->identifier_authority.high_part == cpu_to_be32(0))
&& (usid->identifier_authority.low_part == cpu_to_be32(5))
&& (usid->sub_authority[0] == cpu_to_le32(32))
&& (usid->sub_authority[1] == cpu_to_le32(545)))
);
}
/*
* Test whether a SID means "some user (or group)"
* Currently we only check for S-1-5-21... but we should
* probably test for other configurations
*/
static int is_user_sid(const SID * usid)
{
return ((usid->sub_authority_count == 5)
&& (usid->identifier_authority.high_part == cpu_to_be32(0))
&& (usid->identifier_authority.low_part == cpu_to_be32(5))
&& (usid->sub_authority[0] == cpu_to_le32(21)));
}
/*
* Determine the size of a security attribute
* whatever the order of fields
*/
static unsigned int attr_size(const char *attr)
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const ACL *pdacl;
const ACL *psacl;
const SID *psid;
unsigned int offdacl;
unsigned int offsacl;
unsigned int offowner;
unsigned int offgroup;
unsigned int endsid;
unsigned int endsacl;
unsigned int attrsz;
/*
* First check DACL, which is the last field in all descriptors
* we build, and in most descriptors built by Windows
* however missing for "DR Watson"
*/
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
/* find end of DACL */
offdacl = le32_to_cpu(phead->dacl);
if (offdacl) {
pdacl = (const ACL*)&attr[offdacl];
attrsz = offdacl + le16_to_cpu(pdacl->size);
} else
attrsz = 0;
offowner = le32_to_cpu(phead->owner);
if (offowner >= attrsz) {
/* find end of USID */
psid = (const SID*)&attr[offowner];
endsid = offowner + sid_size(psid);
attrsz = endsid;
}
offgroup = le32_to_cpu(phead->group);
if (offgroup >= attrsz) {
/* find end of GSID */
psid = (const SID*)&attr[offgroup];
endsid = offgroup + sid_size(psid);
if (endsid > attrsz) attrsz = endsid;
}
offsacl = le32_to_cpu(phead->sacl);
if (offsacl >= attrsz) {
/* find end of SACL */
offsacl = le32_to_cpu(phead->sacl);
psacl = (const ACL*)&attr[offsacl];
endsacl = offsacl + le16_to_cpu(psacl->size);
if (endsacl > attrsz)
attrsz = endsacl;
}
return (attrsz);
}
/*
* Do sanity checks on a SID read from storage
* (just check revision and number of authorities)
*/
static BOOL valid_sid(const SID *sid)
{
return ((sid->revision == SID_REVISION)
&& (sid->sub_authority_count >= 1)
&& (sid->sub_authority_count <= 8));
}
/*
* Check whether a SID is acceptable for an implicit
* mapping pattern.
* It should have been already checked it is a valid user SID.
*
* The last authority reference has to be >= 1000 (Windows usage)
* and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits
* from a gid an be inserted with no overflow.
*/
static BOOL valid_pattern(const SID *sid)
{
int cnt;
u32 auth;
cnt = sid->sub_authority_count;
auth = le32_to_cpu(sid->sub_authority[cnt-1]);
return ((auth >= 1000) && (auth <= 0x7fffffff));
}
/*
* Do sanity checks on security descriptors read from storage
* basically, we make sure that every field holds within
* allocated storage
* Should not be called with a NULL argument
* returns TRUE if considered safe
* if not, error should be logged by caller
*/
static BOOL valid_securattr(const char *securattr, unsigned int attrsz)
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const ACL *pacl;
const ACCESS_ALLOWED_ACE *pace;
unsigned int offdacl;
unsigned int offace;
unsigned int acecnt;
unsigned int acesz;
unsigned int nace;
BOOL ok;
ok = TRUE;
/*
* first check overall size if within allocation range
* and a DACL is present
* and owner and group SID are valid
*/
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
offdacl = le32_to_cpu(phead->dacl);
pacl = (const ACL*)&securattr[offdacl];
/*
* size check occurs before the above pointers are used
*
* "DR Watson" standard directory on WinXP has an
* old revision and no DACL though SE_DACL_PRESENT is set
*/
if ((attrsz >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
&& (attr_size(securattr) <= attrsz)
&& (phead->revision == SECURITY_DESCRIPTOR_REVISION)
&& phead->owner
&& phead->group
&& !(phead->owner & cpu_to_le32(3))
&& !(phead->group & cpu_to_le32(3))
&& !(phead->dacl & cpu_to_le32(3))
&& !(phead->sacl & cpu_to_le32(3))
&& valid_sid((const SID*)&securattr[le32_to_cpu(phead->owner)])
&& valid_sid((const SID*)&securattr[le32_to_cpu(phead->group)])
/*
* if there is an ACL, as indicated by offdacl,
* require SE_DACL_PRESENT
* but "Dr Watson" has SE_DACL_PRESENT though no DACL
*/
&& (!offdacl
|| ((pacl->revision == ACL_REVISION)
&& (phead->control & SE_DACL_PRESENT)))) {
/*
* For each ACE, check it is within limits
* and contains a valid SID
* "DR Watson" has no DACL
*/
if (offdacl) {
acecnt = le16_to_cpu(pacl->ace_count);
offace = offdacl + sizeof(ACL);
for (nace = 0; (nace < acecnt) && ok; nace++) {
/* be sure the beginning is within range */
if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > attrsz)
ok = FALSE;
else {
pace = (const ACCESS_ALLOWED_ACE*)
&securattr[offace];
acesz = le16_to_cpu(pace->size);
if (((offace + acesz) > attrsz)
|| !valid_sid(&pace->sid))
ok = FALSE;
offace += acesz;
}
}
}
} else
ok = FALSE;
return (ok);
}
/**
* ntfs_guid_is_zero - check if a GUID is zero
* @guid: [IN] guid to check
@ -541,246 +781,6 @@ static unsigned long atoul(const char *p)
return (v);
}
/*
* Determine the size of a SID
*/
static int sid_size(const SID * sid)
{
return (sid->sub_authority_count * 4 + 8);
}
/*
* Test whether two SID are equal
*/
static BOOL same_sid(const SID *first, const SID *second)
{
int size;
size = sid_size(first);
return ((sid_size(second) == size)
&& !memcmp(first, second, size));
}
/*
* Test whether a SID means "world user"
* Local users group also recognized as world
*/
static int is_world_sid(const SID * usid)
{
return (
/* check whether S-1-1-0 : world */
((usid->sub_authority_count == 1)
&& (usid->identifier_authority.high_part == cpu_to_be32(0))
&& (usid->identifier_authority.low_part == cpu_to_be32(1))
&& (usid->sub_authority[0] == 0))
/* check whether S-1-5-32-545 : local user */
|| ((usid->sub_authority_count == 2)
&& (usid->identifier_authority.high_part == cpu_to_be32(0))
&& (usid->identifier_authority.low_part == cpu_to_be32(5))
&& (usid->sub_authority[0] == cpu_to_le32(32))
&& (usid->sub_authority[1] == cpu_to_le32(545)))
);
}
/*
* Test whether a SID means "some user (or group)"
* Currently we only check for S-1-5-21... but we should
* probably test for other configurations
*/
static int is_user_sid(const SID * usid)
{
return ((usid->sub_authority_count == 5)
&& (usid->identifier_authority.high_part == cpu_to_be32(0))
&& (usid->identifier_authority.low_part == cpu_to_be32(5))
&& (usid->sub_authority[0] == cpu_to_le32(21)));
}
/*
* Determine the size of a security attribute
* whatever the order of fields
*/
static unsigned int attr_size(const char *attr)
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const ACL *pdacl;
const ACL *psacl;
const SID *psid;
unsigned int offdacl;
unsigned int offsacl;
unsigned int offowner;
unsigned int offgroup;
unsigned int endsid;
unsigned int endsacl;
unsigned int attrsz;
/*
* First check DACL, which is the last field in all descriptors
* we build, and in most descriptors built by Windows
* however missing for "DR Watson"
*/
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
/* find end of DACL */
offdacl = le32_to_cpu(phead->dacl);
if (offdacl) {
pdacl = (const ACL*)&attr[offdacl];
attrsz = offdacl + le16_to_cpu(pdacl->size);
} else
attrsz = 0;
offowner = le32_to_cpu(phead->owner);
if (offowner >= attrsz) {
/* find end of USID */
psid = (const SID*)&attr[offowner];
endsid = offowner + sid_size(psid);
attrsz = endsid;
}
offgroup = le32_to_cpu(phead->group);
if (offgroup >= attrsz) {
/* find end of GSID */
psid = (const SID*)&attr[offgroup];
endsid = offgroup + sid_size(psid);
if (endsid > attrsz) attrsz = endsid;
}
offsacl = le32_to_cpu(phead->sacl);
if (offsacl >= attrsz) {
/* find end of SACL */
offsacl = le32_to_cpu(phead->sacl);
psacl = (const ACL*)&attr[offsacl];
endsacl = offsacl + le16_to_cpu(psacl->size);
if (endsacl > attrsz)
attrsz = endsacl;
}
return (attrsz);
}
/*
* Do sanity checks on a SID read from storage
* (just check revision and number of authorities)
*/
static BOOL valid_sid(const SID *sid)
{
return ((sid->revision == SID_REVISION)
&& (sid->sub_authority_count >= 1)
&& (sid->sub_authority_count <= 8));
}
/*
* Check whether a SID is acceptable for an implicit
* mapping pattern.
* It should have been already checked it is a valid user SID.
*
* The last authority reference has to be >= 1000 (Windows usage)
* and <= 0x7fffffff, so that 30 bits from a uid and 30 more bits
* from a gid an be inserted with no overflow.
*/
static BOOL valid_pattern(const SID *sid)
{
int cnt;
u32 auth;
cnt = sid->sub_authority_count;
auth = le32_to_cpu(sid->sub_authority[cnt-1]);
return ((auth >= 1000) && (auth <= 0x7fffffff));
}
/*
* Do sanity checks on security descriptors read from storage
* basically, we make sure that every field holds within
* allocated storage
* Should not be called with a NULL argument
* returns TRUE if considered safe
* if not, error should be logged by caller
*/
static BOOL valid_securattr(const char *securattr, unsigned int attrsz)
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const ACL *pacl;
const ACCESS_ALLOWED_ACE *pace;
unsigned int offdacl;
unsigned int offace;
unsigned int acecnt;
unsigned int acesz;
unsigned int nace;
BOOL ok;
ok = TRUE;
/*
* first check overall size if within allocation range
* and a DACL is present
* and owner and group SID are valid
*/
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
offdacl = le32_to_cpu(phead->dacl);
pacl = (const ACL*)&securattr[offdacl];
/*
* size check occurs before the above pointers are used
*
* "DR Watson" standard directory on WinXP has an
* old revision and no DACL though SE_DACL_PRESENT is set
*/
if ((attrsz >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
&& (attr_size(securattr) <= attrsz)
&& (phead->revision == SECURITY_DESCRIPTOR_REVISION)
&& phead->owner
&& phead->group
&& !(phead->owner & cpu_to_le32(3))
&& !(phead->group & cpu_to_le32(3))
&& !(phead->dacl & cpu_to_le32(3))
&& !(phead->sacl & cpu_to_le32(3))
&& valid_sid((const SID*)&securattr[le32_to_cpu(phead->owner)])
&& valid_sid((const SID*)&securattr[le32_to_cpu(phead->group)])
/*
* if there is an ACL, as indicated by offdacl,
* require SE_DACL_PRESENT
* but "Dr Watson" has SE_DACL_PRESENT though no DACL
*/
&& (!offdacl
|| ((pacl->revision == ACL_REVISION)
&& (phead->control & SE_DACL_PRESENT)))) {
/*
* For each ACE, check it is within limits
* and contains a valid SID
* "DR Watson" has no DACL
*/
if (offdacl) {
acecnt = le16_to_cpu(pacl->ace_count);
offace = offdacl + sizeof(ACL);
for (nace = 0; (nace < acecnt) && ok; nace++) {
/* be sure the beginning is within range */
if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > attrsz)
ok = FALSE;
else {
pace = (const ACCESS_ALLOWED_ACE*)
&securattr[offace];
acesz = le16_to_cpu(pace->size);
if (((offace + acesz) > attrsz)
|| !valid_sid(&pace->sid))
ok = FALSE;
offace += acesz;
}
}
}
} else
ok = FALSE;
return (ok);
}
/*
* Build an internal representation of a SID
* Returns a copy in allocated memory if it succeeds
@ -2682,67 +2682,6 @@ static char *build_secur_descr(mode_t mode,
return (newattr);
}
/*
* Get the security descriptor associated to a file
*
* Either :
* - read the security descriptor attribute (v1.x format)
* - or find the descriptor in $Secure:$SDS (v3.x format)
*
* in both case, sanity checks are done on the attribute and
* the descriptor can be assumed safe
*
* The returned descriptor is dynamically allocated and has to be freed
*/
static char *getsecurityattr(ntfs_volume *vol,
const char *path, ntfs_inode *ni)
{
SII_INDEX_KEY securid;
char *securattr;
s64 readallsz;
/*
* Warning : in some situations, after fixing by chkdsk,
* v3_Extensions are marked present (long standard informations)
* with a default security descriptor inserted in an
* attribute
*/
if (test_nino_flag(ni, v3_Extensions)
&& vol->secure_ni && ni->security_id) {
/* get v3.x descriptor in $Secure */
securid.security_id = ni->security_id;
securattr = retrievesecurityattr(vol,securid);
if (!securattr)
ntfs_log_error("Bad security descriptor for 0x%lx\n",
(long)le32_to_cpu(ni->security_id));
} else {
/* get v1.x security attribute */
readallsz = 0;
securattr = ntfs_attr_readall(ni, AT_SECURITY_DESCRIPTOR,
AT_UNNAMED, 0, &readallsz);
if (securattr && !valid_securattr(securattr, readallsz)) {
ntfs_log_error("Bad security descriptor for %s\n",
path);
free(securattr);
securattr = (char*)NULL;
}
}
if (!securattr) {
/*
* in some situations, there is no security
* descriptor, and chkdsk does not detect or fix
* anything. This could be a normal situation.
* When this happens, simulate a descriptor with
* minimum rights, so that a real descriptor can
* be created by chown or chmod
*/
ntfs_log_error("No security descriptor found for %s\n",path);
securattr = build_secur_descr(0, 0, adminsid, adminsid);
}
return (securattr);
}
/*
* Create a mode_t permission set
* from owner, group and world grants as represented in ACEs
@ -3180,6 +3119,67 @@ static int build_permissions(const char *securattr,
return (perm);
}
/*
* Get the security descriptor associated to a file
*
* Either :
* - read the security descriptor attribute (v1.x format)
* - or find the descriptor in $Secure:$SDS (v3.x format)
*
* in both case, sanity checks are done on the attribute and
* the descriptor can be assumed safe
*
* The returned descriptor is dynamically allocated and has to be freed
*/
static char *getsecurityattr(ntfs_volume *vol,
const char *path, ntfs_inode *ni)
{
SII_INDEX_KEY securid;
char *securattr;
s64 readallsz;
/*
* Warning : in some situations, after fixing by chkdsk,
* v3_Extensions are marked present (long standard informations)
* with a default security descriptor inserted in an
* attribute
*/
if (test_nino_flag(ni, v3_Extensions)
&& vol->secure_ni && ni->security_id) {
/* get v3.x descriptor in $Secure */
securid.security_id = ni->security_id;
securattr = retrievesecurityattr(vol,securid);
if (!securattr)
ntfs_log_error("Bad security descriptor for 0x%lx\n",
(long)le32_to_cpu(ni->security_id));
} else {
/* get v1.x security attribute */
readallsz = 0;
securattr = ntfs_attr_readall(ni, AT_SECURITY_DESCRIPTOR,
AT_UNNAMED, 0, &readallsz);
if (securattr && !valid_securattr(securattr, readallsz)) {
ntfs_log_error("Bad security descriptor for %s\n",
path);
free(securattr);
securattr = (char*)NULL;
}
}
if (!securattr) {
/*
* in some situations, there is no security
* descriptor, and chkdsk does not detect or fix
* anything. This could be a normal situation.
* When this happens, simulate a descriptor with
* minimum rights, so that a real descriptor can
* be created by chown or chmod
*/
ntfs_log_error("No security descriptor found for %s\n",path);
securattr = build_secur_descr(0, 0, adminsid, adminsid);
}
return (securattr);
}
/*
* Get permissions to access a file
* Takes into account the relation of user to file (owner, group, ...)