jcifs.internal.dtyp.ACE Maven / Gradle / Ivy
Show all versions of jcifs-ng Show documentation
/*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jcifs.internal.dtyp;
import jcifs.Decodable;
import jcifs.internal.util.SMBUtil;
import jcifs.smb.SID;
import jcifs.util.Hexdump;
/**
* An Access Control Entry (ACE) is an element in a security descriptor
* such as those associated with files and directories. The Windows OS
* determines which users have the necessary permissions to access objects
* based on these entries.
*
* To fully understand the information exposed by this class a description
* of the access check algorithm used by Windows is required. The following
* is a basic description of the algorithm. For a more complete description
* we recommend reading the section on Access Control in Keith Brown's
* "The .NET Developer's Guide to Windows Security" (which is also
* available online).
*
* Direct ACEs are evaluated first in order. The SID of the user performing
* the operation and the desired access bits are compared to the SID
* and access mask of each ACE. If the SID matches, the allow/deny flags
* and access mask are considered. If the ACE is a "deny"
* ACE and any of the desired access bits match bits in the access
* mask of the ACE, the whole access check fails. If the ACE is an "allow"
* ACE and all of the bits in the desired access bits match bits in
* the access mask of the ACE, the access check is successful. Otherwise,
* more ACEs are evaluated until all desired access bits (combined)
* are "allowed". If all of the desired access bits are not "allowed"
* the then same process is repeated for inherited ACEs.
*
* For example, if user WNET\alice tries to open a file
* with desired access bits 0x00000003 (FILE_READ_DATA |
* FILE_WRITE_DATA) and the target file has the following security
* descriptor ACEs:
*
*
* Allow WNET\alice 0x001200A9 Direct
* Allow Administrators 0x001F01FF Inherited
* Allow SYSTEM 0x001F01FF Inherited
*
*
* the access check would fail because the direct ACE has an access mask
* of 0x001200A9 which doesn't have the
* FILE_WRITE_DATA bit on (bit 0x00000002). Actually, this isn't quite correct. If
* WNET\alice is in the local Administrators group the access check
* will succeed because the inherited ACE allows local Administrators
* both FILE_READ_DATA and FILE_WRITE_DATA access.
*
* @internal
*/
public class ACE implements jcifs.ACE, Decodable {
boolean allow;
int flags;
int access;
SID sid;
@Override
public boolean isAllow () {
return this.allow;
}
@Override
public boolean isInherited () {
return ( this.flags & FLAGS_INHERITED ) != 0;
}
@Override
public int getFlags () {
return this.flags;
}
@Override
public String getApplyToText () {
switch ( this.flags & ( FLAGS_OBJECT_INHERIT | FLAGS_CONTAINER_INHERIT | FLAGS_INHERIT_ONLY ) ) {
case 0x00:
return "This folder only";
case 0x03:
return "This folder, subfolders and files";
case 0x0B:
return "Subfolders and files only";
case 0x02:
return "This folder and subfolders";
case 0x0A:
return "Subfolders only";
case 0x01:
return "This folder and files";
case 0x09:
return "Files only";
}
return "Invalid";
}
@Override
public int getAccessMask () {
return this.access;
}
@Override
public SID getSID () {
return this.sid;
}
@Override
public int decode ( byte[] buf, int bi, int len ) {
this.allow = buf[ bi++ ] == (byte) 0x00;
this.flags = buf[ bi++ ] & 0xFF;
int size = SMBUtil.readInt2(buf, bi);
bi += 2;
this.access = SMBUtil.readInt4(buf, bi);
bi += 4;
this.sid = new SID(buf, bi);
return size;
}
void appendCol ( StringBuffer sb, String str, int width ) {
sb.append(str);
int count = width - str.length();
for ( int i = 0; i < count; i++ ) {
sb.append(' ');
}
}
/**
* Return a string represeting this ACE.
*
* Note: This function should probably be changed to return SDDL
* fragments but currently it does not.
*/
@Override
public String toString () {
StringBuffer sb = new StringBuffer();
sb.append(isAllow() ? "Allow " : "Deny ");
appendCol(sb, this.sid.toDisplayString(), 25);
sb.append(" 0x").append(Hexdump.toHexString(this.access, 8)).append(' ');
sb.append(isInherited() ? "Inherited " : "Direct ");
appendCol(sb, getApplyToText(), 34);
return sb.toString();
}
}