Skip to content

Commit a6334c2

Browse files
committed
Added documentation and code to test if a account (User or Machine) has
been disabled in the AD
1 parent 6878dbd commit a6334c2

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

docs/installation/additional_integration.asciidoc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,44 @@ Validate with Ok and provide the account that will run this task (usually _DOMAI
199199
200200
==== Disabled Account
201201
202+
===== Preventing Authentication of Disabled Accounts via LDAP Filter
203+
204+
You can prevent disabled Active Directory accounts from authenticating through PacketFence by adding an LDAP filter that excludes accounts with the `ACCOUNTDISABLE` flag set.
205+
206+
In Active Directory, the `userAccountControl` attribute contains bitwise flags that indicate account properties. Bit 2 (`0x2`) corresponds to `ACCOUNTDISABLE`. The following LDAP filter uses the bitwise AND matching rule (`1.2.840.113556.1.4.803`) to check whether this bit is set, and excludes those accounts from search results:
207+
208+
----
209+
(!(userAccountControl:1.2.840.113556.1.4.803:=2))
210+
----
211+
212+
To configure this in PacketFence:
213+
214+
. Go to _Configuration -> Policies and Access Control -> Authentication Sources_.
215+
. Edit your Active Directory authentication source.
216+
. In the _Append search attributes LDAP filter_ field, paste the filter above.
217+
. Save the configuration.
218+
219+
With this filter in place, any LDAP search performed during authentication will automatically exclude disabled accounts, preventing them from authenticating.
220+
221+
NOTE: This is a *preventive* approach that blocks authentication at LDAP search time. It applies globally to all searches performed by this authentication source. To apply the check at the level of individual authentication rules instead, see the next section.
222+
223+
===== Filtering Disabled Accounts in Authentication Rules
224+
225+
You can also check the `userAccountControl` attribute directly in authentication rule conditions using the *has bit* and *not has bit* operators. These operators perform a bitwise AND check against the attribute value, which is the correct way to test individual flags in a bitmask attribute like `userAccountControl`.
226+
227+
To create a rule that rejects disabled accounts:
228+
229+
. Go to _Configuration -> Policies and Access Control -> Authentication Sources_.
230+
. Edit your Active Directory authentication source and open an authentication rule.
231+
. Add a condition: `userAccountControl` -> *not has bit* -> `2`.
232+
. Save the rule.
233+
234+
This condition excludes accounts that have the `ACCOUNTDISABLE` bit set (bit 2), regardless of what other flags are present in `userAccountControl`.
235+
236+
NOTE: Standard operators like _equals_ or _not equals_ perform a simple string comparison on the full `userAccountControl` value and are not suitable for bitmask attributes. Always use _has bit_ or _not has bit_ when checking individual flags.
237+
238+
===== Unregistering Nodes When an Account is Disabled (Event-Based)
239+
202240
Create the script `unreg_node_disabled_account.ps1` on the Windows Server with the following content:
203241
204242
----

html/pfappserver/root/src/globals/pfField.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ export const operatorMap = {
117117
ends: 'ends',
118118
matches_regexp: 'matches regexp',
119119
is_member_of: 'is member of',
120+
has_bit: 'has bit',
121+
not_has_bit: 'not has bit',
120122
}
121123

122124
export const pfFieldTypeOperators = {
@@ -132,7 +134,9 @@ export const pfFieldTypeOperators = {
132134
{ text: 'contains', value: operatorMap.contains },
133135
{ text: 'ends', value: operatorMap.ends },
134136
{ text: 'matches regexp', value: operatorMap.matches_regexp },
135-
{ text: 'is member of', value: operatorMap.is_member_of }
137+
{ text: 'is member of', value: operatorMap.is_member_of },
138+
{ text: 'has bit', value: operatorMap.has_bit },
139+
{ text: 'not has bit', value: operatorMap.not_has_bit }
136140
],
137141
[pfFieldType.LDAPFILTER]: [
138142
{ text: 'match filter', value: 'match filter' }

lib/pf/Authentication/Source/LDAPSource.pm

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,10 @@ sub ldap_filter_for_conditions {
697697
$str = "${attribute}=${value}*";
698698
} elsif ($operator eq $Conditions::ENDS) {
699699
$str = "${attribute}=*${value}";
700+
} elsif ($operator eq $Conditions::HAS_BIT) {
701+
$str = "${attribute}:1.2.840.113556.1.4.803:=${value}";
702+
} elsif ($operator eq $Conditions::NOT_HAS_BIT) {
703+
$str = "!(${attribute}:1.2.840.113556.1.4.803:=${value})";
700704
}
701705

702706
if ($str) {
@@ -801,7 +805,7 @@ sub _makefilter {
801805
return '(' . "$self->{'usernameattribute'}=$username" . ')';
802806
}
803807

804-
return $append_search;
808+
return "(&($self->{'usernameattribute'}=$username)" . $append_search . ")";
805809
}
806810

807811
sub lookupRole {

lib/pf/Authentication/constants.pm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ Readonly::Scalar our $IS_NOT => 'is not';
9797
Readonly::Scalar our $IS_AFTER => 'is after';
9898
Readonly::Scalar our $IS_MEMBER => 'is member of';
9999
Readonly::Scalar our $MATCH_FILTER => 'match filter';
100+
Readonly::Scalar our $HAS_BIT => 'has bit';
101+
Readonly::Scalar our $NOT_HAS_BIT => 'not has bit';
100102

101103
=item SUBSTRING, NUMBER, DATE, TIME
102104
@@ -138,7 +140,7 @@ Readonly::Hash our %OPERATORS =>
138140
$TIME => [$IS_BEFORE, $IS_AFTER],
139141
$TIME_PERIOD => [$IN_TIME_PERIOD],
140142
$CONNECTION => [$IS, $IS_NOT],
141-
$LDAP_ATTRIBUTE => [$IS, $STARTS, $EQUALS, $NOT_EQUALS, $CONTAINS, $NOT_CONTAINS, $ENDS, $MATCHES, $IS_MEMBER],
143+
$LDAP_ATTRIBUTE => [$IS, $STARTS, $EQUALS, $NOT_EQUALS, $CONTAINS, $NOT_CONTAINS, $ENDS, $MATCHES, $IS_MEMBER, $HAS_BIT, $NOT_HAS_BIT],
142144
$LDAP_FILTER => [$MATCH_FILTER],
143145
);
144146

0 commit comments

Comments
 (0)