blob: 89fd8a4c8d825162905fd3231f65a036f28f525e [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace Adldap\Models\Attributes;
4
5use ReflectionClass;
6
7/**
8 * The Account Control class.
9 *
10 * This class is for easily building a user account control value.
11 *
12 * @link https://support.microsoft.com/en-us/kb/305144
13 */
14class AccountControl
15{
16 const SCRIPT = 1;
17
18 const ACCOUNTDISABLE = 2;
19
20 const HOMEDIR_REQUIRED = 8;
21
22 const LOCKOUT = 16;
23
24 const PASSWD_NOTREQD = 32;
25
26 const ENCRYPTED_TEXT_PWD_ALLOWED = 128;
27
28 const TEMP_DUPLICATE_ACCOUNT = 256;
29
30 const NORMAL_ACCOUNT = 512;
31
32 const INTERDOMAIN_TRUST_ACCOUNT = 2048;
33
34 const WORKSTATION_TRUST_ACCOUNT = 4096;
35
36 const SERVER_TRUST_ACCOUNT = 8192;
37
38 const DONT_EXPIRE_PASSWORD = 65536;
39
40 const MNS_LOGON_ACCOUNT = 131072;
41
42 const SMARTCARD_REQUIRED = 262144;
43
44 const TRUSTED_FOR_DELEGATION = 524288;
45
46 const NOT_DELEGATED = 1048576;
47
48 const USE_DES_KEY_ONLY = 2097152;
49
50 const DONT_REQ_PREAUTH = 4194304;
51
52 const PASSWORD_EXPIRED = 8388608;
53
54 const TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216;
55
56 const PARTIAL_SECRETS_ACCOUNT = 67108864;
57
58 /**
59 * Stores the values to be added together to
60 * build the user account control integer.
61 *
62 * @var array
63 */
64 protected $values = [];
65
66 /**
67 * Constructor.
68 *
69 * @param int $flag
70 */
71 public function __construct($flag = null)
72 {
73 if (!is_null($flag)) {
74 $this->apply($flag);
75 }
76 }
77
78 /**
79 * Get the value when casted to string.
80 *
81 * @return string
82 */
83 public function __toString()
84 {
85 return (string) $this->getValue();
86 }
87
88 /**
89 * Get the value when casted to int.
90 *
91 * @return int
92 */
93 public function __toInt()
94 {
95 return $this->getValue();
96 }
97
98 /**
99 * Add the value to the account control values.
100 *
101 * @param int $value
102 *
103 * @return AccountControl
104 */
105 public function add($value)
106 {
107 // Use the value as a key so if the same value
108 // is used, it will always be overwritten
109 $this->values[$value] = $value;
110
111 return $this;
112 }
113
114 /**
115 * Remove the value from the account control.
116 *
117 * @param int $value
118 *
119 * @return $this
120 */
121 public function remove($value)
122 {
123 unset($this->values[$value]);
124
125 return $this;
126 }
127
128 /**
129 * Extract and apply the flag.
130 *
131 * @param int $flag
132 */
133 public function apply($flag)
134 {
135 $this->setValues($this->extractFlags($flag));
136 }
137
138 /**
139 * Determine if the current AccountControl object contains the given UAC flag(s).
140 *
141 * @param int $flag
142 *
143 * @return bool
144 */
145 public function has($flag)
146 {
147 // We'll extract the given flag into an array of possible flags, and
148 // see if our AccountControl object contains any of them.
149 $flagsUsed = array_intersect($this->extractFlags($flag), $this->values);
150
151 return in_array($flag, $flagsUsed);
152 }
153
154 /**
155 * The logon script will be run.
156 *
157 * @return AccountControl
158 */
159 public function runLoginScript()
160 {
161 return $this->add(static::SCRIPT);
162 }
163
164 /**
165 * The user account is locked.
166 *
167 * @return AccountControl
168 */
169 public function accountIsLocked()
170 {
171 return $this->add(static::LOCKOUT);
172 }
173
174 /**
175 * The user account is disabled.
176 *
177 * @return AccountControl
178 */
179 public function accountIsDisabled()
180 {
181 return $this->add(static::ACCOUNTDISABLE);
182 }
183
184 /**
185 * This is an account for users whose primary account is in another domain.
186 *
187 * This account provides user access to this domain, but not to any domain that
188 * trusts this domain. This is sometimes referred to as a local user account.
189 *
190 * @return AccountControl
191 */
192 public function accountIsTemporary()
193 {
194 return $this->add(static::TEMP_DUPLICATE_ACCOUNT);
195 }
196
197 /**
198 * This is a default account type that represents a typical user.
199 *
200 * @return AccountControl
201 */
202 public function accountIsNormal()
203 {
204 return $this->add(static::NORMAL_ACCOUNT);
205 }
206
207 /**
208 * This is a permit to trust an account for a system domain that trusts other domains.
209 *
210 * @return AccountControl
211 */
212 public function accountIsForInterdomain()
213 {
214 return $this->add(static::INTERDOMAIN_TRUST_ACCOUNT);
215 }
216
217 /**
218 * This is a computer account for a computer that is running Microsoft
219 * Windows NT 4.0 Workstation, Microsoft Windows NT 4.0 Server, Microsoft
220 * Windows 2000 Professional, or Windows 2000 Server and is a member of this domain.
221 *
222 * @return AccountControl
223 */
224 public function accountIsForWorkstation()
225 {
226 return $this->add(static::WORKSTATION_TRUST_ACCOUNT);
227 }
228
229 /**
230 * This is a computer account for a domain controller that is a member of this domain.
231 *
232 * @return AccountControl
233 */
234 public function accountIsForServer()
235 {
236 return $this->add(static::SERVER_TRUST_ACCOUNT);
237 }
238
239 /**
240 * This is an MNS logon account.
241 *
242 * @return AccountControl
243 */
244 public function accountIsMnsLogon()
245 {
246 return $this->add(static::MNS_LOGON_ACCOUNT);
247 }
248
249 /**
250 * (Windows 2000/Windows Server 2003) This account does
251 * not require Kerberos pre-authentication for logging on.
252 *
253 * @return AccountControl
254 */
255 public function accountDoesNotRequirePreAuth()
256 {
257 return $this->add(static::DONT_REQ_PREAUTH);
258 }
259
260 /**
261 * When this flag is set, it forces the user to log on by using a smart card.
262 *
263 * @return AccountControl
264 */
265 public function accountRequiresSmartCard()
266 {
267 return $this->add(static::SMARTCARD_REQUIRED);
268 }
269
270 /**
271 * (Windows Server 2008/Windows Server 2008 R2) The account is a read-only domain controller (RODC).
272 *
273 * This is a security-sensitive setting. Removing this setting from an RODC compromises security on that server.
274 *
275 * @return AccountControl
276 */
277 public function accountIsReadOnly()
278 {
279 return $this->add(static::PARTIAL_SECRETS_ACCOUNT);
280 }
281
282 /**
283 * The home folder is required.
284 *
285 * @return AccountControl
286 */
287 public function homeFolderIsRequired()
288 {
289 return $this->add(static::HOMEDIR_REQUIRED);
290 }
291
292 /**
293 * No password is required.
294 *
295 * @return AccountControl
296 */
297 public function passwordIsNotRequired()
298 {
299 return $this->add(static::PASSWD_NOTREQD);
300 }
301
302 /**
303 * The user cannot change the password. This is a permission on the user's object.
304 *
305 * For information about how to programmatically set this permission, visit the following link:
306 *
307 * @link http://msdn2.microsoft.com/en-us/library/aa746398.aspx
308 *
309 * @return AccountControl
310 */
311 public function passwordCannotBeChanged()
312 {
313 return $this->add(static::PASSWD_NOTREQD);
314 }
315
316 /**
317 * Represents the password, which should never expire on the account.
318 *
319 * @return AccountControl
320 */
321 public function passwordDoesNotExpire()
322 {
323 return $this->add(static::DONT_EXPIRE_PASSWORD);
324 }
325
326 /**
327 * (Windows 2000/Windows Server 2003) The user's password has expired.
328 *
329 * @return AccountControl
330 */
331 public function passwordIsExpired()
332 {
333 return $this->add(static::PASSWORD_EXPIRED);
334 }
335
336 /**
337 * The user can send an encrypted password.
338 *
339 * @return AccountControl
340 */
341 public function allowEncryptedTextPassword()
342 {
343 return $this->add(static::ENCRYPTED_TEXT_PWD_ALLOWED);
344 }
345
346 /**
347 * When this flag is set, the service account (the user or computer account)
348 * under which a service runs is trusted for Kerberos delegation.
349 *
350 * Any such service can impersonate a client requesting the service.
351 *
352 * To enable a service for Kerberos delegation, you must set this
353 * flag on the userAccountControl property of the service account.
354 *
355 * @return AccountControl
356 */
357 public function trustForDelegation()
358 {
359 return $this->add(static::TRUSTED_FOR_DELEGATION);
360 }
361
362 /**
363 * (Windows 2000/Windows Server 2003) The account is enabled for delegation.
364 *
365 * This is a security-sensitive setting. Accounts that have this option enabled
366 * should be tightly controlled. This setting lets a service that runs under the
367 * account assume a client's identity and authenticate as that user to other remote
368 * servers on the network.
369 *
370 * @return AccountControl
371 */
372 public function trustToAuthForDelegation()
373 {
374 return $this->add(static::TRUSTED_TO_AUTH_FOR_DELEGATION);
375 }
376
377 /**
378 * When this flag is set, the security context of the user is not delegated to a
379 * service even if the service account is set as trusted for Kerberos delegation.
380 *
381 * @return AccountControl
382 */
383 public function doNotTrustForDelegation()
384 {
385 return $this->add(static::NOT_DELEGATED);
386 }
387
388 /**
389 * (Windows 2000/Windows Server 2003) Restrict this principal to
390 * use only Data Encryption Standard (DES) encryption types for keys.
391 *
392 * @return AccountControl
393 */
394 public function useDesKeyOnly()
395 {
396 return $this->add(static::USE_DES_KEY_ONLY);
397 }
398
399 /**
400 * Get the account control value.
401 *
402 * @return int
403 */
404 public function getValue()
405 {
406 return array_sum($this->values);
407 }
408
409 /**
410 * Get the account control flag values.
411 *
412 * @return array
413 */
414 public function getValues()
415 {
416 return $this->values;
417 }
418
419 /**
420 * Set the account control values.
421 *
422 * @param array $flags
423 */
424 public function setValues(array $flags)
425 {
426 $this->values = $flags;
427 }
428
429 /**
430 * Get all possible account control flags.
431 *
432 * @return array
433 */
434 public function getAllFlags()
435 {
436 return (new ReflectionClass(__CLASS__))->getConstants();
437 }
438
439 /**
440 * Extracts the given flag into an array of flags used.
441 *
442 * @param int $flag
443 *
444 * @return array
445 */
446 public function extractFlags($flag)
447 {
448 $flags = [];
449
450 for ($i = 0; $i <= 26; $i++) {
451 if ((int) $flag & (1 << $i)) {
452 $flags[1 << $i] = 1 << $i;
453 }
454 }
455
456 return $flags;
457 }
458}