Skip to content

feat(ldap): Add Active Directory nested group matching and fix PHP LDAP auth errors#791

Merged
mastacontrola merged 19 commits intoFOGProject:dev-branchfrom
eduardomozart:ldap-nested-groups
Mar 2, 2026
Merged

feat(ldap): Add Active Directory nested group matching and fix PHP LDAP auth errors#791
mastacontrola merged 19 commits intoFOGProject:dev-branchfrom
eduardomozart:ldap-nested-groups

Conversation

@eduardomozart
Copy link
Copy Markdown
Contributor

@eduardomozart eduardomozart commented Feb 25, 2026

Description

This PR introduces support for nested group matching in Active Directory and resolves two PHP errors that could occur during the LDAP authentication process.

Features & Enhancements:

  • Nested Group Matching: Added a new configuration toggle in the LDAP plugin UI: Enable Nested Group Matching (Active Directory only). When enabled, the plugin leverages the LDAP_MATCHING_RULE_IN_CHAIN (1.2.840.113556.1.4.1941) OID. This allows FOG to properly authenticate users who are members of nested groups, rather than requiring direct membership.

Bug Fixes

  • Fixed "Use Group Matching" JS Toggle: Corrected an invalid DOM ID selector (#useGroupMatch to #groupmatch), removed broken .options property calls on the checkbox, and removed an erroneous e.preventDefault() that was preventing the checkbox from visually updating. The dependent fields now properly gray out when disabled.
  • Fixed PHP Fatal Error on connection close: In newer PHP versions, calling ldap_unbind() on an already closed LDAP object results in a Fatal Error (Uncaught Error: LDAP connection has already been closed). Removed a redundant @$this->unbind(); call inside _getAccessLevel() to prevent this crash when an authentication check fails.
  • Fixed Property Case Typo: Resolved a PHP Warning (Undefined property: stdClass::$SearchDN) on line 114 of ldapmanagementpage.class.php by correcting the property name to lowercase $searchDN.

Testing Performed

Authentication was tested across multiple scenarios to ensure both backward compatibility and new functionality work as expected:

  • Direct Membership (Nested Enabled): User is a direct member of the group -> Success
  • Direct Membership (Nested Disabled): User is a direct member of the group -> Success
  • Nested Membership (Nested Enabled): User is a member of a group that is a member of the target FOG group -> Success
  • Nested Membership (Nested Disabled): User is a member of a group that is a member of the target FOG group -> Fails (Expected behavior for standard LDAP queries)
  • Frontend UI: Toggling "Use Group Matching" correctly applies the readonly property, grays out the target elements (including the new nested match checkbox), and prevents the nested checkbox from being clicked.

Related Error Logs Addressed

PHP Warning Fixed:

[25-Feb-2026 22:49:16 UTC] PHP Warning:  Undefined property: stdClass::$SearchDN in /var/www/fog/lib/plugins/ldap/pages/ldapmanagementpage.class.php on line 114

PHP Fatal Error Fixed:

[26-Feb-2026 01:59:09 UTC] PHP Fatal error:  Uncaught Error: LDAP connection has already been closed in /var/www/fog/lib/plugins/ldap/class/ldap.class.php:125

eduardomozart and others added 6 commits February 11, 2026 19:33
Correct various typos, spacing and punctuation in UI/error strings and translations. Changes include: standardizing "Active Multicast Tasks" title; removing/adding punctuation in exception and status messages (accesscontrol, wolbroadcast, pending MAC report); fixing "LDAP Connection Name" spacing; and a large update to Portuguese translations (messages.po) including Project-Id, translator metadata, language tag and many corrected msgstr entries for consistency and clarity. These edits improve UI text accuracy and translation quality.
Introduce an enableNestedGroup option (lsEnableNestedGroup) throughout the LDAP plugin: mapping, DB schema, and UI checkbox. Add a userAccountControl check after binding to deny logins for disabled AD accounts. Implement nested group membership checks for Active Directory using the matching-rule-in-chain OID (1.2.840.113556.1.4.1941) against memberOf to detect admin/user group membership and return appropriate access levels, with a fallback to existing behavior. Bump plugin version to 1.5.5_2.
Introduce an enableNestedGroup option (lsEnableNestedGroup) throughout the LDAP plugin: mapping, DB schema, and UI checkbox. Add a userAccountControl check after binding to deny logins for disabled AD accounts. Implement nested group membership checks for Active Directory using the matching-rule-in-chain OID (1.2.840.113556.1.4.1941) against memberOf to detect admin/user group membership and return appropriate access levels, with a fallback to existing behavior. Bump plugin version to 1.5.5_2.
@eduardomozart eduardomozart marked this pull request as draft February 25, 2026 17:13
Eduardo Oliveira added 9 commits February 25, 2026 19:40
Add an "Enable Nested Group Matching (Active Directory only)" checkbox to the LDAP management form and persist its value. The patch reads enableNestedGroup from POST in both add and update flows and sets it on the LDAP object before saving. Changes made in packages/web/lib/plugins/ldap/pages/ldapmanagementpage.class.php.
Introduce $enableNestedGroup and $nestedGroupChecked to determine the nested-group checkbox state from POST input or the stored object setting. This ensures the LDAP management form reflects the enableNestedGroup value when rendering.
Rework LDAP nested-group handling and filter construction. Retrieve enableNestedGroup earlier and build distinct LDAP filters for Active Directory nested group matching using the memberOf recursion OID (1.2.840.113556.1.4.1941). Support multiple admin/user groups (explode/trim) and construct appropriate |-clauses via implode. Preserve non-nested legacy filter when nested matching is disabled. Overall cleanup removed the previous per-check early returns and centralized filter setup for admin and user group lookups.
Refactor LDAP plugin string concatenation for Active Directory nested-group filters in packages/web/lib/plugins/ldap/class/ldap.class.php. The change standardizes line breaks around concatenated filter parts, removes a redundant re-declaration of $grpMemAttr_forimplode, and cleans up whitespace for improved readability without altering behavior.
Escape the username when building LDAP search filters using $this->escape(..., LDAP_ESCAPE_FILTER) to prevent special-character injection. Also correct the sprintf templates and concatenation for AD nested group filters so the membership clauses are wrapped and combined properly (removes redundant parentheses and properly embeds the :1.2.840.113556.1.4.1941 matching rule). These changes improve security and correctness of LDAP/AD queries.
Replace dynamic $grpMemAttr usage with the literal 'memberOf' when building nested-group LDAP filters (using the 1.2.840.113556.1.4.1941 matching rule) to ensure correct Active Directory nested group matching. Also simplify a comment about checking userAccountControl after binding as the user.
Build correct LDAP filters for AD nested group membership by using name-based OR clauses and the memberOf matching rule with an escaped user DN; replaces previous string concatenation to avoid malformed filters. Removes a redundant unbind call. Also fix a casing typo in the LDAP management page (SearchDN -> searchDN) to use the correct property.
Replace duplicated if/else blocks for admin and user group filters with a single sprintf-based construction that conditionally appends the AD nested-group OID (:1.2.840.113556.1.4.1941:) when $enableNestedGroup is true. This simplifies the code by unifying filter generation for adminGroups and userGroups while preserving existing filter semantics and reusing $grpMemAttr_forimplode for group member concatenation.
@eduardomozart eduardomozart changed the title Ldap nested groups feat(ldap): Add Active Directory nested group matching and fix PHP auth errors Feb 26, 2026
@eduardomozart eduardomozart changed the title feat(ldap): Add Active Directory nested group matching and fix PHP auth errors feat(ldap): Add Active Directory nested group matching and fix PHP LDAP auth errors Feb 26, 2026
@eduardomozart eduardomozart marked this pull request as ready for review February 26, 2026 03:35
eduardomozart and others added 4 commits February 26, 2026 00:57
Removed Active Directory userAccountControl checks for account status.
PHP: Add support for nested group matching by appending the MS_MATCHING_RULE_IN_CHAIN OID (:1.2.840.113556.1.4.1941:) to group membership attributes when enableNestedGroup is true. Remove the Active Directory userAccountControl check (ACCOUNTDISABLE) that previously blocked logins.

JS: Adjust form handlers — stop using the select-based #useGroupMatch handler and switch to #groupmatch checkbox (passing its checked state). Include #nestedgroupmatch in the readonly/disabled toggling and enable/disable it appropriately. Minor cleanup: comment out e.preventDefault() calls so change events behave normally.
Prevent toggling the nested group checkbox when fields are readonly and unify readonly handling across group fields. Added a click handler on #nestedgroupmatch to stop changes if it's readonly, removed usage of .prop('disabled') for that control, and updated ldapUseGroupToggle to set .prop('readonly') for all relevant inputs (including #nestedgroupmatch) while applying visual cues (accent-color and cursor) to indicate the disabled-like state.
@mastacontrola mastacontrola merged commit b308baa into FOGProject:dev-branch Mar 2, 2026
@mastacontrola
Copy link
Copy Markdown
Member

I'm trusting the testing of this. I don't know exactly what this is requesting (just being honest) but i appreciate all the effort you have put in thus far. Goign to allow it as based on the coding I've seen nothing is too problematic in my eyes.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants