Commits

David Carr committed cde2970

windows-provider: fix user enumeration

NetUserEnum level 23 doesn't appear to be supported widely enough for use. NetApi32Util.getUsers doesn't pass FILTER_NORMAL_ACCOUNT, which includes a bunch of machine names and so forth, and slows it down a bunch. For now, I'm using level 1. A higher level will allow support for full names.

Comments (0)

Files changed (8)

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/ActiveDirectoryUserInformationSource.java

         UserInformationCollector collector = includeMemberGroupInformation ?
                 new UserWithGlobalGroupInformationCollector(this, serverName) :
                 new UserInformationCollector(this);
-        enumerateUserInfo23(serverName, collector);
+        enumerateUserInfo(serverName, collector);
         return collector.getUserInformationSet();
     }
 

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/LocalWindowsUserInformationSource.java

         UserInformationCollector collector = includeMemberGroupInformation ?
                 new UserWithLocalGroupInformationCollector(this) :
                 new UserInformationCollector(this);
-        enumerateUserInfo23(null, collector);
+        enumerateUserInfo(null, collector);
         return collector.getUserInformationSet();
     }
 

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/UserInfo23Recipient.java

-package us.carrclan.david.authc4j.windows.provider;
-
-import com.sun.jna.platform.win32.LMAccess;
-
-interface UserInfo23Recipient {
-    void receiveUserInfo(LMAccess.USER_INFO_23 userInfo);
-}

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/UserInfoRecipient.java

+package us.carrclan.david.authc4j.windows.provider;
+
+import com.sun.jna.platform.win32.LMAccess;
+
+interface UserInfoRecipient {
+    void receiveUserInfo(String name, String fullName);
+}

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/UserInformationCollector.java

 package us.carrclan.david.authc4j.windows.provider;
 
-import com.sun.jna.platform.win32.LMAccess;
 import us.carrclan.david.authc4j.api.GroupInformation;
 import us.carrclan.david.authc4j.api.ImmutableUserInformation;
 import us.carrclan.david.authc4j.api.UserInformation;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
-class UserInformationCollector implements UserInfo23Recipient {
+class UserInformationCollector implements UserInfoRecipient {
     private final Set<UserInformation> userInformationSet = new LinkedHashSet<>();
     private final UserInformationSource source;
 
     }
 
     @Override
-    public void receiveUserInfo(LMAccess.USER_INFO_23 userInfo) {
-        String shortName = getShortName(userInfo);
-        String longName = getLongName(userInfo);
-        Set<? extends GroupInformation> groups = getGroups(userInfo);
-        userInformationSet.add(new ImmutableUserInformation(source, shortName, longName, groups));
+    public void receiveUserInfo(String name, String fullName) {
+        Set<? extends GroupInformation> groups = getGroups(name);
+        userInformationSet.add(new ImmutableUserInformation(source, name, fullName, groups));
     }
 
-    private String getShortName(LMAccess.USER_INFO_23 userInfo) {
-        return userInfo.usri23_name.toString();
-    }
-
-    private String getLongName(LMAccess.USER_INFO_23 userInfo) {
-        return userInfo.usri23_full_name != null ? userInfo.usri23_full_name.toString() : null;
-    }
-
-    protected Set<? extends GroupInformation> getGroups(LMAccess.USER_INFO_23 userInfo) {
+    protected Set<? extends GroupInformation> getGroups(String userName) {
         return null;
     }
 

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/UserWithGlobalGroupInformationCollector.java

 package us.carrclan.david.authc4j.windows.provider;
 
-import com.sun.jna.platform.win32.LMAccess;
 import com.sun.jna.platform.win32.Netapi32Util;
 import us.carrclan.david.authc4j.api.GroupInformation;
 import us.carrclan.david.authc4j.api.ImmutableGroupInformation;
     }
 
     @Override
-    protected Set<? extends GroupInformation> getGroups(LMAccess.USER_INFO_23 userInfo) {
+    protected Set<? extends GroupInformation> getGroups(String userName) {
         Set<GroupInformation> groupInformationSet = new LinkedHashSet<>();
-        for (Netapi32Util.Group group : Netapi32Util.getGlobalGroups(serverName)) {
+        for (Netapi32Util.Group group : Netapi32Util.getUserGroups(userName, serverName)) {
             groupInformationSet.add(new ImmutableGroupInformation(getSource(), group.name));
         }
         return groupInformationSet;

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/UserWithLocalGroupInformationCollector.java

 package us.carrclan.david.authc4j.windows.provider;
 
-import com.sun.jna.platform.win32.LMAccess;
 import com.sun.jna.platform.win32.Netapi32Util;
 import us.carrclan.david.authc4j.api.GroupInformation;
 import us.carrclan.david.authc4j.api.ImmutableGroupInformation;
     }
 
     @Override
-    protected Set<? extends GroupInformation> getGroups(LMAccess.USER_INFO_23 userInfo) {
+    protected Set<? extends GroupInformation> getGroups(String userName) {
         Set<GroupInformation> groupInformationSet = new LinkedHashSet<>();
-        for (Netapi32Util.Group group : Netapi32Util.getLocalGroups()) {
+        for (Netapi32Util.Group group : Netapi32Util.getUserLocalGroups(userName)) {
             groupInformationSet.add(new ImmutableGroupInformation(getSource(), group.name));
         }
         return groupInformationSet;

windows-provider/src/main/java/us/carrclan/david/authc4j/windows/provider/WindowsUserInformationSource.java

     /**
      * Based on {@link Netapi32Util#getUsers}, but returns more information.
      */
-    protected static void enumerateUserInfo23(String serverName, UserInfo23Recipient recipient) {
+    protected static void enumerateUserInfo(String serverName, UserInfoRecipient recipient) {
         PointerByReference bufptr = new PointerByReference();
         IntByReference entriesRead = new IntByReference();
         IntByReference totalEntries = new IntByReference();
         try {
             int rc = Netapi32.INSTANCE.NetUserEnum(
-                    serverName, 23, 0, bufptr,
+                    serverName, 1, LMAccess.FILTER_NORMAL_ACCOUNT, bufptr,
                     LMCons.MAX_PREFERRED_LENGTH, entriesRead,
                     totalEntries, null);
             if (LMErr.NERR_Success != rc || bufptr.getValue() == Pointer.NULL) {
                 throw new Win32Exception(rc);
             }
-            LMAccess.USER_INFO_23 user = new LMAccess.USER_INFO_23(bufptr.getValue());
-            LMAccess.USER_INFO_23[] users = (LMAccess.USER_INFO_23[]) user.toArray(entriesRead.getValue());
-            for (LMAccess.USER_INFO_23 lu : users) {
-                recipient.receiveUserInfo(lu);
+            LMAccess.USER_INFO_1 user = new LMAccess.USER_INFO_1(bufptr.getValue());
+            LMAccess.USER_INFO_1[] users = (LMAccess.USER_INFO_1[]) user.toArray(entriesRead.getValue());
+            for (LMAccess.USER_INFO_1 lu : users) {
+                // TODO: support full name
+                recipient.receiveUserInfo(lu.usri1_name.toString(), null);
             }
         } finally {
             if (bufptr.getValue() != Pointer.NULL) {