diff --git a/CHANGES.md b/CHANGES.md index 250e0eab56..6290eb7cbb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Features * [#1168](https://github.com/java-native-access/jna/pull/1168): Add `c.s.j.p.win32.Kernel32#SetProcessAffinityMask` - [@dbwiddis](https://github.com/dbwiddis). * [#1169](https://github.com/java-native-access/jna/issues/1169): Wait for process in getLinuxLdPaths - [@rdesgroppes](https://github.com/rdesgroppes). * [#1178](https://github.com/java-native-access/jna/pull/1178): Add `c.s.j.p.win32.IPHlpAPI#GetTcpStatistics`, `c.s.j.p.win32.IPHlpAPI#GetUdpStatistics`, `c.s.j.p.win32.IPHlpAPI#GetTcpStatisticsEx` and `c.s.j.p.win32.IPHlpAPI#GetUdpStatisticsEx` - [@dbwiddis](https://github.com/dbwiddis). +* [#1191](https://github.com/java-native-access/jna/pull/1191): Add `c.s.j.p.win32.Advapi32Util#getTokenPrimaryGroup` - [@dbwiddis](https://github.com/dbwiddis). Bug Fixes --------- diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java index f4d650f3ca..2e6367541e 100755 --- a/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java @@ -63,6 +63,7 @@ import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.Advapi32Util.Account; import com.sun.jna.platform.win32.WinBase.FE_EXPORT_FUNC; import com.sun.jna.platform.win32.WinBase.FE_IMPORT_FUNC; import com.sun.jna.platform.win32.WinBase.FILETIME; @@ -86,6 +87,7 @@ import com.sun.jna.platform.win32.WinNT.SECURITY_IMPERSONATION_LEVEL; import com.sun.jna.platform.win32.WinNT.SID_AND_ATTRIBUTES; import com.sun.jna.platform.win32.WinNT.SID_NAME_USE; +import com.sun.jna.platform.win32.WinNT.TOKEN_PRIMARY_GROUP; import com.sun.jna.platform.win32.WinNT.TOKEN_TYPE; import com.sun.jna.platform.win32.WinReg.HKEY; import com.sun.jna.platform.win32.WinReg.HKEYByReference; @@ -475,6 +477,45 @@ public static Account[] getTokenGroups(HANDLE hToken) { return userGroups.toArray(new Account[0]); } + /** + * This function returns the primary group associated with a security token, + * such as a user token. + * + * @param hToken + * Token. + * @return Token primary group. + */ + public static Account getTokenPrimaryGroup(HANDLE hToken) { + // get token group information size + IntByReference tokenInformationLength = new IntByReference(); + if (Advapi32.INSTANCE.GetTokenInformation(hToken, WinNT.TOKEN_INFORMATION_CLASS.TokenPrimaryGroup, null, 0, + tokenInformationLength)) { + throw new RuntimeException("Expected GetTokenInformation to fail with ERROR_INSUFFICIENT_BUFFER"); + } + int rc = Kernel32.INSTANCE.GetLastError(); + if (rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) { + throw new Win32Exception(rc); + } + // get token group information + WinNT.TOKEN_PRIMARY_GROUP primaryGroup = new WinNT.TOKEN_PRIMARY_GROUP(tokenInformationLength.getValue()); + if (!Advapi32.INSTANCE.GetTokenInformation(hToken, WinNT.TOKEN_INFORMATION_CLASS.TokenPrimaryGroup, + primaryGroup, tokenInformationLength.getValue(), tokenInformationLength)) { + throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); + } + Account group; + try { + group = Advapi32Util.getAccountBySid(primaryGroup.PrimaryGroup); + } catch (Exception e) { + group = new Account(); + group.sid = primaryGroup.PrimaryGroup.getBytes(); + group.sidString = Advapi32Util.convertSidToStringSid(primaryGroup.PrimaryGroup); + group.name = group.sidString; + group.fqn = group.sidString; + group.accountType = SID_NAME_USE.SidTypeGroup; + } + return group; + } + /** * This function returns the information about the user who owns a security * token, diff --git a/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java b/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java index 25b611a182..aa3f79eb67 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/WinNT.java @@ -32,6 +32,7 @@ import com.sun.jna.PointerType; import com.sun.jna.Structure; import com.sun.jna.Structure.FieldOrder; +import com.sun.jna.platform.win32.WinNT.PSID; import com.sun.jna.Union; import com.sun.jna.ptr.ByReference; import com.sun.jna.win32.StdCallLibrary.StdCallCallback; @@ -427,6 +428,33 @@ public TOKEN_USER(int size) { } } + /** + * The TOKEN_PRIMARY_GROUP structure specifies a group security identifier (SID) + * for an access token. + */ + @FieldOrder({ "PrimaryGroup" }) + public static class TOKEN_PRIMARY_GROUP extends Structure { + /** + * A pointer to a SID structure representing a group that will become the + * primary group of any objects created by a process using this access token. + * The SID must be one of the group SIDs already in the token. + */ + public PSID.ByReference PrimaryGroup; + + public TOKEN_PRIMARY_GROUP() { + super(); + } + + public TOKEN_PRIMARY_GROUP(Pointer memory) { + super(memory); + read(); + } + + public TOKEN_PRIMARY_GROUP(int size) { + super(new Memory(size)); + } + } + /** * The TOKEN_GROUPS structure contains information about the group security * identifiers (SIDs) in an access token. diff --git a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32UtilTest.java b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32UtilTest.java index 5698198fd9..542e314c29 100755 --- a/contrib/platform/test/com/sun/jna/platform/win32/Advapi32UtilTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Advapi32UtilTest.java @@ -171,16 +171,24 @@ public void testGetUserGroups() { try { HANDLEByReference phUser = new HANDLEByReference(); try { - assertTrue(Advapi32.INSTANCE.LogonUser(userInfo.usri1_name, - null, userInfo.usri1_password, WinBase.LOGON32_LOGON_NETWORK, - WinBase.LOGON32_PROVIDER_DEFAULT, phUser)); + assertTrue(Advapi32.INSTANCE.LogonUser(userInfo.usri1_name, null, userInfo.usri1_password, + WinBase.LOGON32_LOGON_NETWORK, WinBase.LOGON32_PROVIDER_DEFAULT, phUser)); + Account primaryGroup = Advapi32Util.getTokenPrimaryGroup(phUser.getValue()); + assertTrue(primaryGroup.name.length() > 0); + assertTrue(primaryGroup.sidString.length() > 0); + assertTrue(primaryGroup.sid.length > 0); Account[] groups = Advapi32Util.getTokenGroups(phUser.getValue()); + boolean primaryGroupFound = false; assertTrue(groups.length > 0); - for(Account group : groups) { + for (Account group : groups) { assertTrue(group.name.length() > 0); assertTrue(group.sidString.length() > 0); assertTrue(group.sid.length > 0); + if (primaryGroup.name.equals(group.name)) { + primaryGroupFound = true; + } } + assertTrue("PrimaryGroup must be in group list", primaryGroupFound); } finally { HANDLE hUser = phUser.getValue(); if (!WinBase.INVALID_HANDLE_VALUE.equals(hUser)) {