diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2008-02-22 15:21:45 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2008-02-22 15:21:45 +0000 |
commit | 01b6cf18358af39b7544953899a8b55cc5ed2896 (patch) | |
tree | 81311295628150e64f19b2eae1a13e511b48c6ed | |
parent | a680b8e33654c3509da88cd5c8383c8cbd184696 (diff) | |
download | jackcess-01b6cf18358af39b7544953899a8b55cc5ed2896.tar.gz jackcess-01b6cf18358af39b7544953899a8b55cc5ed2896.zip |
user userIds from the file if possible when generating new table access control entries (fix #1898793)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@231 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r-- | src/changes/changes.xml | 5 | ||||
-rw-r--r-- | src/java/com/healthmarketscience/jackcess/Database.java | 90 |
2 files changed, 72 insertions, 23 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6913095..594943d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -13,6 +13,11 @@ Fix writing of large memo/ole fields. Apparently Access does not like "inline" fields longer than 64 bytes. </action> + <action dev="jahlborn" type="fix" issue="1898793"> + Fix generation of security access control entries. Use userIds + already existing in the database file instead of hard-coded userIds, + if possible. + </action> </release> <release version="1.1.11" date="2008-01-20"> <action dev="jahlborn" type="fix"> diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java index 9a6a980..3b5efb6 100644 --- a/src/java/com/healthmarketscience/jackcess/Database.java +++ b/src/java/com/healthmarketscience/jackcess/Database.java @@ -68,11 +68,13 @@ public class Database { private static final Log LOG = LogFactory.getLog(Database.class); - - private static final byte[] SID = new byte[2]; + + /** this is the default "userId" used if we cannot find existing info. this + seems to be some standard "Admin" userId for access files */ + private static final byte[] SYS_DEFAULT_SID = new byte[2]; static { - SID[0] = (byte) 0xA6; - SID[1] = (byte) 0x33; + SYS_DEFAULT_SID[0] = (byte) 0xA6; + SYS_DEFAULT_SID[1] = (byte) 0x33; } /** default value for the auto-sync value ({@code true}). this is slower, @@ -84,8 +86,11 @@ public class Database /** System catalog always lives on page 2 */ private static final int PAGE_SYSTEM_CATALOG = 2; - - private static final int ACM = 1048319; + + /** this is the access control bit field for created tables. the value used + is equivalent to full access (Visual Basic DAO PermissionEnum constant: + dbSecFullAccess) */ + private static final Integer SYS_FULL_ACCESS_ACM = 1048575; private static final String COL_ACM = "ACM"; /** System catalog column name of the date a system object was created */ @@ -187,6 +192,8 @@ public class Database private Table _systemCatalog; /** System access control entries table */ private Table _accessControlEntries; + /** SIDs to use for the ACEs added for new tables */ + private final List<byte[]> _newTableSIDs = new ArrayList<byte[]>(); /** * Open an existing Database. If the existing file is not writeable, the @@ -340,6 +347,16 @@ public class Database _tableParentId = (Integer) row.get(COL_ID); } } + + // check for required system values + if(_accessControlEntries == null) { + throw new IOException("Did not find required " + TABLE_SYSTEM_ACES + + " table"); + } + if(_tableParentId == null) { + throw new IOException("Did not find required parent table id"); + } + if (LOG.isDebugEnabled()) { LOG.debug("Finished reading system catalog. Tables: " + getTableNames()); @@ -355,8 +372,9 @@ public class Database _pageChannel.readPage(buffer, pageNum); byte pageType = buffer.get(); if (pageType != PageTypes.TABLE_DEF) { - throw new IOException("Looking for MSysACEs at page " + pageNum + - ", but page type is " + pageType); + throw new IOException("Looking for " + TABLE_SYSTEM_ACES + + " at page " + pageNum + + ", but page type is " + pageType); } _accessControlEntries = new Table(this, buffer, pageNum, "Access Control Entries"); @@ -484,23 +502,49 @@ public class Database * @param pageNumber Page number that contains the table definition */ private void addToAccessControlEntries(int pageNumber) throws IOException { - Object[] aceRow = new Object[_accessControlEntries.getColumns().size()]; - int idx = 0; - for (Iterator<Column> iter = _accessControlEntries.getColumns().iterator(); - iter.hasNext(); idx++) - { - Column col = iter.next(); - if (col.getName().equals(COL_ACM)) { - aceRow[idx] = ACM; - } else if (col.getName().equals(COL_F_INHERITABLE)) { - aceRow[idx] = Boolean.FALSE; - } else if (col.getName().equals(COL_OBJECT_ID)) { - aceRow[idx] = Integer.valueOf(pageNumber); - } else if (col.getName().equals(COL_SID)) { - aceRow[idx] = SID; + + if(_newTableSIDs.isEmpty()) { + initNewTableSIDs(); + } + + Column acmCol = _accessControlEntries.getColumn(COL_ACM); + Column inheritCol = _accessControlEntries.getColumn(COL_F_INHERITABLE); + Column objIdCol = _accessControlEntries.getColumn(COL_OBJECT_ID); + Column sidCol = _accessControlEntries.getColumn(COL_SID); + + // construct a collection of ACE entries mimicing those of our parent, the + // "Tables" system object + List<Object[]> aceRows = new ArrayList<Object[]>(_newTableSIDs.size()); + for(byte[] sid : _newTableSIDs) { + Object[] aceRow = new Object[_accessControlEntries.getColumns().size()]; + aceRow[acmCol.getColumnIndex()] = SYS_FULL_ACCESS_ACM; + aceRow[inheritCol.getColumnIndex()] = Boolean.FALSE; + aceRow[objIdCol.getColumnIndex()] = Integer.valueOf(pageNumber); + aceRow[sidCol.getColumnIndex()] = sid; + aceRows.add(aceRow); + } + _accessControlEntries.addRows(aceRows); + } + + /** + * Determines the collection of SIDs which need to be added to new tables. + */ + private void initNewTableSIDs() throws IOException + { + // search for ACEs matching the tableParentId. + // FIXME we could potentially use an index to do this, but index handling + // support is sketchy enough that i wouldn't want to trust it just now. + for(Map<String, Object> row : Cursor.createCursor(_accessControlEntries)) { + Integer objId = (Integer)row.get(COL_OBJECT_ID); + if(_tableParentId.equals(objId)) { + _newTableSIDs.add((byte[])row.get(COL_SID)); } } - _accessControlEntries.addRow(aceRow); + + if(_newTableSIDs.isEmpty()) { + // if all else fails, use the hard-coded default + _newTableSIDs.add(SYS_DEFAULT_SID); + } } /** |