Decoding windows claims for user login names and AD groups
Code Review https://codereview.appspot.com/11071043/
diff --git a/lib/plexi b/lib/plexi
index 85c51d5..b4a81e0 160000
--- a/lib/plexi
+++ b/lib/plexi
@@ -1 +1 @@
-Subproject commit 85c51d5e9df59e3c7c188c1264b72c82c418c863
+Subproject commit b4a81e0f8b4e5437bb222b84ef8b06b1be4a2c35
diff --git a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
index 449ea8e..a9a6888 100644
--- a/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
+++ b/src/com/google/enterprise/adaptor/sharepoint/SharePointAdaptor.java
@@ -176,6 +176,10 @@
 
   private static final int LIST_READ_SECURITY_ENABLED = 2;
 
+  private static final String IDENTITY_CLAIMS_PREFIX = "i:0";
+
+  private static final String OTHER_CLAIMS_PREFIX = "c:0";
+
   private static final Logger log
       = Logger.getLogger(SharePointAdaptor.class.getName());
 
@@ -1060,10 +1064,10 @@
       return allowAnonymousRead;
     }
 
-    private boolean isDenyAnonymousAcessOnVirtualServer(VirtualServer vs) { 
+    private boolean isDenyAnonymousAcessOnVirtualServer(VirtualServer vs) {
       long anonymousDenyMask
           =  vs.getPolicies().getAnonymousDenyMask().longValue();
-      if ((LIST_ITEM_MASK & anonymousDenyMask) != 0) {   
+      if ((LIST_ITEM_MASK & anonymousDenyMask) != 0) {
         return true;
       }
       // Anonymous access is denied if deny read policy is specified for any
@@ -1616,6 +1620,27 @@
       return !"Unchanged".equals(change) && !"Delete".equals(change);
     }
 
+    private String decodeClaim(String loginName, String name
+        , boolean isDomainGroup) {
+      if (!loginName.startsWith(IDENTITY_CLAIMS_PREFIX)
+          && !loginName.startsWith(OTHER_CLAIMS_PREFIX)) {
+        return isDomainGroup ? name : loginName;
+      }
+      // AD User
+      if (loginName.startsWith("i:0#.w|")) {
+        return loginName.substring(7);
+      // AD Group
+      } else if (loginName.startsWith("c:0+.w|")) {
+        return name;
+      } else if (loginName.equals("c:0(.s|true")) {
+        return "Everyone";
+      } else if (loginName.equals("c:0!.s|windows")) {
+        return "NT AUTHORITY\\authenticated users";
+      }
+      log.log(Level.WARNING, "Unsupported claims value {0}", loginName);
+      return null;
+    }
+
     private MemberIdMapping retrieveMemberIdMapping() throws IOException {
       log.entering("SiteAdaptor", "retrieveMemberIdMapping");
       Site site = siteDataClient.getContentSite();
@@ -1626,10 +1651,19 @@
       }
       Map<Integer, String> userMap = new HashMap<Integer, String>();
       for (UserDescription user : site.getWeb().getUsers().getUser()) {
-        if (user.getIsDomainGroup() == TrueFalseType.TRUE) {
-          groupMap.put(user.getID(), user.getName().intern());
+        boolean isDomainGroup = (user.getIsDomainGroup() == TrueFalseType.TRUE);
+        String userName
+            = decodeClaim(user.getLoginName(), user.getName(), isDomainGroup);
+        if (userName == null) {
+          log.log(Level.WARNING,
+              "Unable to determine login name. Skipping user with ID {0}",
+              user.getID());
+          continue;
+        }
+        if (isDomainGroup) {
+          groupMap.put(user.getID(), userName.intern());
         } else {
-          userMap.put(user.getID(), user.getLoginName().intern());
+          userMap.put(user.getID(), userName.intern());
         }
       }
       MemberIdMapping mapping = new MemberIdMapping(userMap, groupMap);
@@ -1658,7 +1692,18 @@
         return mapping;
       }
       for (User user : siteUsers.getUsers().getUser()) {
-        userMap.put((int) user.getID(), user.getLoginName());
+        boolean isDomainGroup = (user.getIsDomainGroup()
+            == com.microsoft.schemas.sharepoint.soap.directory.TrueFalseType.TRUE);
+        String userName =
+            decodeClaim(user.getLoginName(), user.getName(), isDomainGroup);
+
+        if (userName == null) {
+          log.log(Level.WARNING,
+              "Unable to determine login name. Skipping user with ID {0}",
+              user.getID());
+          continue;
+        }
+        userMap.put((int) user.getID(), userName.intern());
       }
       mapping = new MemberIdMapping(userMap, groupMap);
       log.exiting("SiteAdaptor", "retrieveSiteUserMapping", mapping);
diff --git a/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java b/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
index 74b2b16..df9f2de 100644
--- a/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
+++ b/test/com/google/enterprise/adaptor/sharepoint/SharePointAdaptorTest.java
@@ -474,6 +474,44 @@
         response.getAcl());
   }
 
+    @Test
+  public void testGetDocContentSiteCollectionWithClaims() throws Exception {
+    String permissions = "<permission memberid='11' mask='756052856929' />"
+        + "<permission memberid='12' mask='756052856929' />"
+        + "<permission memberid='13' mask='756052856929' />"
+        + "<permission memberid='14' mask='756052856929' /></permissions>";
+    SiteDataFactory siteDataFactory = MockSiteDataFactory.blank()
+        .endpoint(VS_ENDPOINT, MockSiteData.blank()
+            .register(VS_CONTENT_EXCHANGE)
+            .register(SITES_SITECOLLECTION_SAW_EXCHANGE))
+        .endpoint(SITES_SITECOLLECTION_ENDPOINT, MockSiteData.blank()
+            .register(SITES_SITECOLLECTION_URLSEG_EXCHANGE)
+            .register(SITES_SITECOLLECTION_S_CONTENT_EXCHANGE
+              .replaceInContent("</permissions>", permissions))
+            .register(SITES_SITECOLLECTION_SC_CONTENT_EXCHANGE
+              .replaceInContent("</permissions>", permissions)));
+
+    
+    adaptor = new SharePointAdaptor(siteDataFactory,
+        new UnsupportedUserGroupFactory(), new UnsupportedHttpClient(),
+        executorFactory);
+    adaptor.init(new MockAdaptorContext(config, null));
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    GetContentsRequest request = new GetContentsRequest(
+        new DocId("http://localhost:1/sites/SiteCollection"));
+    GetContentsResponse response = new GetContentsResponse(baos);
+    adaptor.getDocContent(request, response);
+    assertEquals(new Acl.Builder()
+        .setEverythingCaseInsensitive()
+        .setInheritFrom(new DocId(""))
+        .setInheritanceType(Acl.InheritanceType.PARENT_OVERRIDES)
+        .setPermitUsers(users("GDC-PSL\\spuser1", "GSA-CONNECTORS\\User1"))
+        .setPermitGroups(groups("chinese1 Members", "chinese1 Owners",
+            "chinese1 Visitors", "GSA-CONNECTORS\\domain users",
+            "Everyone", "NT AUTHORITY\\authenticated users")).build(),
+        response.getAcl());
+  }
+
   public void testGetDocContentSiteCollectionNoIndex() throws Exception {
     SiteDataFactory siteDataFactory = MockSiteDataFactory.blank()
         .endpoint(VS_ENDPOINT, MockSiteData.blank()
diff --git a/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-s.xml b/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-s.xml
index 19256c7..d0980a1 100644
--- a/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-s.xml
+++ b/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-s.xml
@@ -18,6 +18,18 @@
 <User ID="2" Sid="S-1-5-21-736914693-3137354690-2813686979-1130"
  Name="spuser1" LoginName="GDC-PSL\spuser1" Email=""
  Notes="" IsSiteAdmin="True" IsDomainGroup="False" />
+<User ID="11" Sid="" Name="Everyone" LoginName="c:0(.s|true"
+ IsSiteAdmin="False" IsDomainGroup="True" Flags="0" UserKey="c:0(.s|true" />
+<User ID="12" Sid="" Name="GSA-CONNECTORS\domain users"
+ LoginName="c:0+.w|s-1-5-21-3993744865-3521423997-1479072767-513"
+ IsSiteAdmin="False" IsDomainGroup="True" Flags="0"
+ UserKey="c:0+.w|s-1-5-21-3993744865-3521423997-1479072767-513" />
+<User ID="13" Sid="" Name="NT AUTHORITY\authenticated users"
+ LoginName="c:0!.s|windows" IsSiteAdmin="False" IsDomainGroup="True"
+ Flags="0" UserKey="c:0!.s|windows" />
+<User ID="14" Sid="" Name="User1" LoginName="i:0#.w|gsa-connectors\user1"
+ IsSiteAdmin="False" IsDomainGroup="False" Flags="0"
+ UserKey="i:0).w|s-1-5-21-3993744865-3521423997-1479072767-1720" />
 </Users>
 <ACL><permissions>
 <permission memberid='2' mask='9223372036854775807' />
diff --git a/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-sc.xml b/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-sc.xml
index 9ead575..fa3ab6b 100644
--- a/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-sc.xml
+++ b/test/com/google/enterprise/adaptor/sharepoint/spresponses/sites-SiteCollection-sc.xml
@@ -54,6 +54,18 @@
 <User ID="6" Sid="S-1-5-21-736914693-3137354690-2813686979-1132"
  Name="spuser2" LoginName="GDC-PSL\spuser2" Email=""
  Notes="" IsSiteAdmin="False" IsDomainGroup="False" />
+<User ID="11" Sid="" Name="Everyone" LoginName="c:0(.s|true"
+ IsSiteAdmin="False" IsDomainGroup="True" Flags="0" UserKey="c:0(.s|true" />
+<User ID="12" Sid="" Name="GSA-CONNECTORS\domain users"
+ LoginName="c:0+.w|s-1-5-21-3993744865-3521423997-1479072767-513"
+ IsSiteAdmin="False" IsDomainGroup="True" Flags="0"
+ UserKey="c:0+.w|s-1-5-21-3993744865-3521423997-1479072767-513" />
+<User ID="13" Sid="" Name="NT AUTHORITY\authenticated users"
+ LoginName="c:0!.s|windows" IsSiteAdmin="False" IsDomainGroup="True"
+ Flags="0" UserKey="c:0!.s|windows" />
+<User ID="14" Sid="" Name="User1" LoginName="i:0#.w|gsa-connectors\user1"
+ IsSiteAdmin="False" IsDomainGroup="False" Flags="0"
+ UserKey="i:0).w|s-1-5-21-3993744865-3521423997-1479072767-1720" />
 </Users>
 <ACL><permissions>
 <permission memberid='2' mask='206292717568' />