Skip to content

Instantly share code, notes, and snippets.

@Bill-Stewart
Last active August 10, 2023 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Bill-Stewart/59041ea5c988d0706ce358ab9cfe0474 to your computer and use it in GitHub Desktop.
Save Bill-Stewart/59041ea5c988d0706ce358ab9cfe0474 to your computer and use it in GitHub Desktop.
UserAccountControl.hta
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<!--
UserAccountControl.hta Written by Bill Stewart (bstewart AT iname.com)
Provides a simple GUI for examining and toggling individual bits for the
Active Directory userAccountControl attribute.
Enter the userAccountControl attribute into the box at the top of the form
and click the 'Calculate' button. The checkboxes that correspond to the
entered value will be selected. To enter the value as hex, prefix it with
'0x' (e.g., 0x200). When you click 'Calculate', the text box will be
converted to decimal and the hex value will be below it.
You can also click the checkboxes for individual bits and the
userAccountControl value at the top of the form will be updated to reflect
the selected checkboxes.
The 'LDAP filter matching rule OID' option lets you select the
LDAP_MATCHING_RULE_BIT_AND or LDAP_MATCHING_RULE_BIT_OR OID matching rule for
an LDAP query, and 'LDAP filter string' provides the string for easy copy and
paste to an LDAP query.
References:
* https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
* https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/dd302fd1-0aa7-406b-ad91-2a6b35738557
* https://learn.microsoft.com/en-us/windows/win32/adsi/search-filter-syntax
Version history:
1.0 (2022-10-11)
* Initial version.
1.1 (2022-10-12)
* Fixed: Checkbox state could get out-of-sync with value.
* Improved: Flag descriptions.
1.2 (2022-11-28)
* Added LDAP matching rule OID (AND/OR) for easy copy/paste for LDAP queries.
1.2.1 (2023-01-27)
* Bug fix (unintential global variable).
-->
<head>
<hta:application id="htainfo"
applicationName="UserAccountControl.hta"
version="1.2.1"
/>
<title>userAccountControl Attribute Calculator</title>
<style type="text/css">
body {
background-color: menu;
font-family: sans-serif;
font-size: 10pt;
}
.btn {
width: 75px;
}
.center {
margin-left: auto;
margin-right: auto;
}
.padleft {
padding-left: 10px;
}
.right {
padding-left: 10px;
text-align: right;
}
th {
text-align: left;
border-bottom: 1px solid gray;
}
</style>
<script language="JavaScript">
// Defines the application window's size
var APP_WIDTH = 870,
APP_HEIGHT = 688;
var CHECKBOX_IDS = [
"00000002", // ACCOUNTDISABLE
"00000008", // HOMEDIR_REQUIRED
"00000010", // LOCKOUT
"00000020", // PASSWD_NOTREQD
"00000040", // PASSWD_CANT_CHANGE
"00000080", // ENCRYPTED_TEXT_PWD_ALLOWED
"00000100", // TEMP_DUPLICATE_ACCOUNT
"00000200", // NORMAL_ACCOUNT
"00000800", // INTERDOMAIN_TRUST_ACCOUNT
"00001000", // WORKSTATION_TRUST_ACCOUNT
"00002000", // SERVER_TRUST_ACCOUNT
"00010000", // DONT_EXPIRE_PASSWORD
"00020000", // MNS_LOGON_ACCOUNT
"00040000", // SMARTCARD_REQUIRED
"00080000", // TRUSTED_FOR_DELEGATION
"00100000", // NOT_DELEGATED
"00200000", // USE_DES_KEY_ONLY
"00400000", // DONT_REQ_PREAUTH
"00800000", // PASSWORD_EXPIRED
"01000000", // TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
"02000000", // NO_AUTH_DATA_REQUIRED
"04000000" // PARTIAL_SECRETS_ACCOUNT
];
// Global state variable for whether current entered value is vaid
var ValidValue = true;
// Returns a specified document element by it's id
function id(element) {
return document.getElementById(element);
}
// Returns the specified string with leading and trailing whitespace removed
function trim(string) {
return string.replace(/(^\s*)|(\s*$)/g, "");
}
function onHelp() {
window.alert("Application: " + id("htainfo").applicationName + "\n" +
"Version: " + id("htainfo").version + "\n" +
"Author: Bill Stewart (bstewart AT iname.com)");
}
function changeOIDType() {
var prefix = "(userAccountControl:1.2.840.113556.1.4.";
var value = ValidValue ? id("value").value : "0";
if ( id("oidtype").value == "AND" ) {
id("oidtext").value = prefix + "803:=" + value + ")";
}
else {
id("oidtext").value = prefix + "804:=" + value + ")";
}
}
function initialize() {
window.resizeTo(APP_WIDTH,APP_HEIGHT);
window.moveTo((screen.width - APP_WIDTH) / 2,(screen.height - APP_HEIGHT) / 2);
id("value").select();
id("value").focus();
changeOIDType();
}
function clearCheckboxes() {
for ( var i = 0; i < CHECKBOX_IDS.length; i++ ) {
id(CHECKBOX_IDS[i]).checked = false;
}
}
function clearForm() {
id("value").value = "0";
id("hexvalue").value = "0x0";
changeOIDType();
clearCheckboxes();
}
function calculate() {
var entry = trim(id("value").value);
if ( entry.substring(0,2).toLowerCase() != "0x" ) {
// Trim leading zeros to prevent octal interpretation
while ( entry.charAt(0) == "0" ) {
entry = entry.substring(1);
}
if ( entry == "" ) {
entry = "0";
}
}
var value = parseInt(entry);
if ( isNaN(value) ) {
window.alert("Unable to parse value as a number");
id("value").select();
id("value").focus();
return;
}
// Select checkboxes for matching bits
for ( var i = 0; i < CHECKBOX_IDS.length; i++ ) {
var bit = parseInt(id(CHECKBOX_IDS[i]).value);
id(CHECKBOX_IDS[i]).checked = (value & bit) == bit;
}
// Validate if value matches selected checkboxes (otherwise not valid)
var result = 0;
for ( i = 0; i < CHECKBOX_IDS.length; i++ ) {
if ( id(CHECKBOX_IDS[i]).checked ) {
result |= parseInt(id(CHECKBOX_IDS[i]).value);
}
}
ValidValue = value == result;
if ( ! ValidValue ) {
clearCheckboxes();
window.alert("Value not valid");
}
// Update text fields
id("value").value = parseInt(value,10).toString();
id("hexvalue").value = "0x" + value.toString(0x10).toUpperCase();
changeOIDType();
id("value").select();
id("value").focus();
}
// Updates value display based on checkboxes
function toggleBit() {
var value = 0;
for ( var i = 0; i < CHECKBOX_IDS.length; i++ ) {
var bit = parseInt(id(CHECKBOX_IDS[i]).value,10);
if ( id(CHECKBOX_IDS[i]).checked ) {
value |= bit; // set bit if checkbox checked
}
else {
value &= ~ bit; // clear bit if checkbox not checked
}
}
// Accommodate 32-bit overflow
if ( value < 0 ) {
value += Math.pow(2,32);
}
ValidValue = true; // Value is valid now
id("value").value = value.toString();
id("hexvalue").value = "0x" + value.toString(0x10).toUpperCase();
changeOIDType();
}
</script>
</head>
<body onload="initialize();" onhelp="onHelp();">
<table border="0" cellpadding="0" cellspacing="0" style="margin-left: 95px;">
<tr>
<td>
userAccountControl attribute value:
</td>
<td class="padleft">
<input type="text" id="value" style="width: 100px;" value="0" />
</td>
<td class="padleft">
<input type="submit" value="Calculate" class="btn" onclick="calculate();" />
</td>
</tr>
<tr>
<td class="right">
Hex:
</td>
<td class="padleft">
<input type="text" id="hexvalue" style="background-color: menu; width: 100px;" value="0x0" readonly="readonly" />
</td>
<td>
</td>
</tr>
</table>
<div style="padding-top: 10px;"></div>
<table border="0" cellpadding="0" cellspacing="0" style="margin-left: 113px;">
<tr>
<td class="right">
LDAP filter matching rule OID:
</td>
<td class="padleft">
<select id="oidtype" style="width: 106px;" onchange="changeOIDType();">
<option value="AND">AND</option>
<option value="OR">OR</option>
</select>
</td>
</tr>
<tr>
<td class="right">
LDAP filter string:
</td>
<td class="padleft">
<input type="text" id="oidtext" style="background-color: menu; width: 340px;" readonly="readonly" />
</td>
</tr>
</table>
<div style="padding-top: 15px;"></div>
<table id="main" border="0" cellpadding="0" cellspacing="0">
<tr>
<th></th>
<th>Account Setting</th>
<th class="padleft">Hex</th>
<th class="right">Dec</th>
<th class="padleft">Description</th>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000002" value="2"></td>
<td><label for="00000002">ACCOUNTDISABLE</label></td>
<td class="padleft">0x00000002</td>
<td class="right">2</td>
<td class="padleft">Account is disabled</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000008" value="8"></td>
<td><label for="00000008">HOMEDIR_REQUIRED</label></td>
<td class="padleft">0x00000008</td>
<td class="right">8</td>
<td class="padleft">Home directory required</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000010" value="16"></td>
<td><label for="00000010">LOCKOUT</label></td>
<td class="padleft">0x00000010</td>
<td class="right">16</td>
<td class="padleft">Account is locked out</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000020" value="32"></td>
<td><label for="00000020">PASSWD_NOTREQD</label></td>
<td class="padleft">0x00000020</td>
<td class="right">32</td>
<td class="padleft">Password is not required</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000040" value="64"></td>
<td><label for="00000040">PASSWD_CANT_CHANGE</label></td>
<td class="padleft">0x00000040</td>
<td class="right">64</td>
<td class="padleft">User cannot change password (N/A for domain accounts)</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000080" value="128"></td>
<td><label for="00000080">ENCRYPTED_TEXT_PWD_ALLOWED</label></td>
<td class="padleft">0x00000080</td>
<td class="right">128</td>
<td class="padleft">Store password using reversible encryption</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000100" value="256"></td>
<td><label for="00000100">TEMP_DUPLICATE_ACCOUNT</label></td>
<td class="padleft">0x00000100</td>
<td class="right">256</td>
<td class="padleft">Primary user account is in another domain</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000200" value="512"></td>
<td><label for="00000200">NORMAL_ACCOUNT</label></td>
<td class="padleft">0x00000200</td>
<td class="right">512</td>
<td class="padleft">Normal user account</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00000800" value="2048"></td>
<td><label for="00000800">INTERDOMAIN_TRUST_ACCOUNT</label></td>
<td class="padleft">0x00000800</td>
<td class="right">2048</td>
<td class="padleft">Trust account</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00001000" value="4096"></td>
<td><label for="00001000">WORKSTATION_TRUST_ACCOUNT</label></td>
<td class="padleft">0x00001000</td>
<td class="right">4096</td>
<td class="padleft">Non-domain controller computer account</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00002000" value="8192"></td>
<td><label for="00002000">SERVER_TRUST_ACCOUNT</label></td>
<td class="padleft">0x00002000</td>
<td class="right">8192</td>
<td class="padleft">Domain controller computer account</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00010000" value="65536"></td>
<td><label for="00010000">DONT_EXPIRE_PASSWORD</label></td>
<td class="padleft">0x00010000</td>
<td class="right">65536</td>
<td class="padleft">Password never expires</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00020000" value="131072"></td>
<td><label for="00020000">MNS_LOGON_ACCOUNT</label></td>
<td class="padleft">0x00020000</td>
<td class="right">131072</td>
<td class="padleft">Majority Node Set (MNS) logon account</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00040000" value="262144"></td>
<td><label for="00040000">SMARTCARD_REQUIRED</label></td>
<td class="padleft">0x00040000</td>
<td class="right">262144</td>
<td class="padleft">Smart card is required for interactive logon</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00080000" value="524288"></td>
<td><label for="00080000">TRUSTED_FOR_DELEGATION</label></td>
<td class="padleft">0x00080000</td>
<td class="right">524288</td>
<td class="padleft">Account is trusted for Kerberos delegation to any service</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00100000" value="1048576"></td>
<td><label for="00100000">NOT_DELEGATED</label></td>
<td class="padleft">0x00100000</td>
<td class="right">1048576</td>
<td class="padleft">Account is sensitive and cannot be delegated</td>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00200000" value="2097152"></td>
<td><label for="00200000">USE_DES_KEY_ONLY</label></td>
<td class="padleft">0x00200000</td>
<td class="right">2097152</td>
<td class="padleft">Use only Kerberos DES encryption types for this account</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00400000" value="4194304"></td>
<td><label for="00400000">DONT_REQ_PREAUTH</label></td>
<td class="padleft">0x00400000</td>
<td class="right">4194304</td>
<td class="padleft">Do not require Kerberos preauthentication</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="00800000" value="8388608"></td>
<td><label for="00800000">PASSWORD_EXPIRED</label></td>
<td class="padleft">0x00800000</td>
<td class="right">8388608</td>
<td class="padleft">Password is expired (N/A for domain accounts)</strong></td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="01000000" value="16777216"></td>
<td><label for="01000000">TRUSTED_TO_AUTH_FOR_DELEGATION</label></td>
<td class="padleft">0x01000000</td>
<td class="right">16777216</td>
<td class="padleft">Account running as service gets forwardable Kerberos service ticket</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="02000000" value="33554432"></td>
<td><label for="02000000">NO_AUTH_DATA_REQUIRED</label></td>
<td class="padleft">0x02000000</td>
<td class="right">33554432</td>
<td class="padleft">Omit Kerberos "Privilege Attribute Certificate" (PAC) data</td>
</tr>
<tr>
<td><input type="checkbox" onclick="toggleBit();" id="04000000" value="67108864"></td>
<td><label for="04000000">PARTIAL_SECRETS_ACCOUNT</label></td>
<td class="padleft">0x04000000</td>
<td class="right">67108864</td>
<td class="padleft">Read-only domain controller (RODC) computer account</td>
</tr>
</table>
<div style="padding-top: 15px; text-align: right;">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<input type="button" value="Clear" class="btn" onclick="clearForm();" />&nbsp;
<input type="button" value="Close" class="btn" onclick="window.close();" />
</td>
</tr>
</table>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment