Browse Source

HPCC-22254 Cannot enumerate LDAP file/wu scopes on 389DirectoryServer

Unable to enumerate file/wu scopes on 389DirectoryServer, because they are
not saved in the "canonicalname" attribute. This PR extracts them from the
"entrydn" attribute for 389DS, and parses them into an array to be reported
back to ECLWatch

Signed-off-by: Russ Whitehead <william.whitehead@lexisnexisrisk.com>
Russ Whitehead 6 years ago
parent
commit
ecb4f70488
1 changed files with 55 additions and 14 deletions
  1. 55 14
      system/security/LdapSecurity/ldapconnection.cpp

+ 55 - 14
system/security/LdapSecurity/ldapconnection.cpp

@@ -6187,9 +6187,23 @@ private:
         LdapUtils::normalizeDn(basedn ? basedn : m_ldapconfig->getResourceBasedn(rtype), m_ldapconfig->getBasedn(), basednbuf);
         basednbuf.toLowerCase();//Will look something like "ou=files,ou=dataland_ecl,dc=internal,dc=sds". Lowercase ensures proper strstr with StringArray elements below
 
+        //Extract OU path from basedn ("ou=files,ou=dataland_ecl")
+        StringBuffer baseOU(basednbuf);
+        {
+            const char * pDC = strstr(baseOU.str(), ",dc=");
+            if (pDC)
+                baseOU.setLength(pDC - baseOU.str());//strip out trailing "dc=" portion
+        }
+
         Owned<ILdapConnection> lconn = m_connections->getConnection();
         LDAP* ld = ((CLdapConnection*)lconn.get())->getLd();
-        char *attrs[] = {"canonicalName", NULL};
+
+        char *attrs[2];
+        if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
+            attrs[0] = "canonicalName";
+        else
+            attrs[0] = "entrydn";//389DirectoryServer
+        attrs[1] = nullptr;
 
         //Call LDAP to get the complete OU tree underneath basdnbuf
         CPagedLDAPSearch pagedSrch(ld, m_ldapconfig->getLdapTimeout(), (char*)basednbuf.str(), LDAP_SCOPE_SUBTREE, "objectClass=*", attrs);
@@ -6207,24 +6221,51 @@ private:
                     const char* val = vals.queryCharValue(0);
                     if(val)//this check probably isn't necessary since hasValues(), but could prevent a core
                     {
-                        //Build filescope from everything below the file scope basedn
-                        StringArray OUarray;
-                        OUarray.appendList(val,"/",true);//create StringArray of OU elements. LDAP returns them in the form "internal.sds/files/dataland_ecl/hpccinternal/roxieuser
-
-                        //Find index of first StringArray item NOT in base search string (basednbuf)
-                        int curr = 1;//skip the first element, which are the combined domains. So "dc=internal,dc=sds" will appear here as "internal.sds"
-                        int end = OUarray.ordinality();
-                        for (; curr < end; curr++)
+                        StringArray OUarray;//array to contain OU elements, most nested first (ie  roxieuser, hpccinternal)
+                        if(m_ldapconfig->getServerType() == ACTIVE_DIRECTORY)
+                        {
+                            //Build filescope from everything below the basedn
+                            OUarray.appendList(val,"/",true);//create StringArray of OU elements. LDAP returns them in the form "internal.sds/files/dataland_ecl/hpccinternal/roxieuser
+
+                            //Remove all domain and basedn elements
+                            OUarray.remove(0, false);//remove domain element
+                            while (OUarray.ordinality())
+                            {
+                                VStringBuffer theOU("ou=%s,", OUarray.item(0));
+                                theOU.toLowerCase();//Lowercase to ensure proper strstr within basednbuf
+                                if (nullptr != strstr(basednbuf.str(), theOU.str()))//search baseDN for OU substring
+                                    OUarray.remove(0, false);//remove baseDn element
+                                else
+                                    break;
+                            }
+                        }
+                        else
                         {
-                            VStringBuffer theOU("ou=%s,",OUarray.item(curr));
-                            theOU.toLowerCase();//Lowercase to ensure proper strstr within basednbuf
-                            if (nullptr == strstr(basednbuf.str(), theOU.str()))//search baseDN for OU substring
-                                break;//found first element not in baseDN
+                            //389DirectoryServer, attribute returned in the form "ou=roxieuser,ou=hpccinternal,ou=files,ou=dataland_ecl,dc=risk,dc=regn,dc=net"
+                            StringBuffer ouStr(val);
+                            ouStr.toLowerCase();
+
+                            //strip out trailing "dc=" portion
+                            const char * pDC = strstr(ouStr.str(), ",dc=");
+                            if (pDC)
+                                ouStr.setLength(pDC - ouStr.str());
+
+                            ouStr.replaceString(baseOU, nullptr);//strip out baseDN (ou=files,ou=dataland_ecl)
+                            StringArray tmpOUarray;
+                            if (!ouStr.isEmpty())
+                            {
+                                ouStr.replaceString("ou=", nullptr);//strip out all "ou=" strings
+                                tmpOUarray.appendList(ouStr, ",");//create array of OU entries
+
+                                //Populate OUarray in opposite order
+                                for (int curr = tmpOUarray.ordinality() - 1; curr >= 0; curr--)
+                                    OUarray.append(tmpOUarray.item(curr));
+                            }
                         }
 
                         //build OU string with remaining elements in the form "hpccinternal::roxieuser"
                         StringBuffer sb;
-                        for (; curr < end; curr++)
+                        for (int curr = 0; curr < OUarray.ordinality(); curr++)
                         {
                             sb.appendf("%s%s", sb.isEmpty() ? "" : "::", OUarray.item(curr));
                         }