Skip to content

Commit

Permalink
Improvements to attributes panel behavior, deleting attribute values,…
Browse files Browse the repository at this point in the history
… Ctrl+D to pivot to the DACL, remove object from group feature, search objects by name, refactored theme.go and many bugfixes.
  • Loading branch information
Macmod committed Nov 5, 2024
1 parent f9adebc commit a032811
Show file tree
Hide file tree
Showing 17 changed files with 575 additions and 385 deletions.
83 changes: 43 additions & 40 deletions README.md

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
# TODO (priority)

* Feature: Support deleting specific attribute values (not the entire attribute)
* Feature: Modify ADIDNS dnsZones and dnsNodes
* Feature: Options to manipulate (edit/create/delete) gpLinks visually
* Feature: Load initial cache from file
* Feature: Modify ADIDNS dnsZones and dnsNodes

# TODO (later)

* Feature: Improve object creation form (implement customizations)
* Feature: Custom themes
* Feature: Customizable keybindings
* Feature: Load initial cache from file
* Wish: Add tests for core functions to make sure everything is in order
* Wish: Mini tool to convert godap exports into bloodhound dumps
* Wish: Monitor object for real-time changes (DirSync/SyncRepl)
Expand Down
31 changes: 21 additions & 10 deletions pkg/ldaputils/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import (

// Basic LDAP connection type
type LDAPConn struct {
Conn *ldap.Conn
PagingSize uint32
RootDN string
Conn *ldap.Conn
PagingSize uint32
RootDN string
DefaultRootDN string
}

func (lc *LDAPConn) UpgradeToTLS(tlsConfig *tls.Config) error {
Expand Down Expand Up @@ -236,7 +237,7 @@ func (lc *LDAPConn) QueryGroupMembers(groupDN string) (group []*ldap.Entry, err
ldapQuery := fmt.Sprintf("(memberOf=%s)", ldap.EscapeFilter(groupDN))

search := ldap.NewSearchRequest(
lc.RootDN,
lc.DefaultRootDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
ldapQuery,
[]string{"sAMAccountName", "objectCategory"},
Expand Down Expand Up @@ -273,7 +274,7 @@ func (lc *LDAPConn) QueryUserGroups(userName string) ([]*ldap.Entry, error) {
samOrDn, _ := SamOrDN(userName)

search := ldap.NewSearchRequest(
lc.RootDN,
lc.DefaultRootDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
samOrDn,
[]string{"memberOf"},
Expand Down Expand Up @@ -496,7 +497,7 @@ func (lc *LDAPConn) GetADIDNSZones(name string, isForest bool) ([]adidns.DNSZone
zoneContainer = "ForestDNSZones"
}

queryDN := fmt.Sprintf("CN=MicrosoftDNS,DC=%s,%s", zoneContainer, lc.RootDN)
queryDN := fmt.Sprintf("CN=MicrosoftDNS,DC=%s,%s", zoneContainer, lc.DefaultRootDN)
queryFilter := "(objectClass=dnsZone)"
if name != "" {
queryFilter = fmt.Sprintf("(&%s(name=%s))", queryFilter, ldap.EscapeFilter(name))
Expand Down Expand Up @@ -580,7 +581,7 @@ func (lc *LDAPConn) GetADIDNSNodes(zoneDN string) ([]adidns.DNSNode, error) {
records = append(records, *dnsRec)
}

nodes = append(nodes, adidns.DNSNode{nodeDN, nodeName, records})
nodes = append(nodes, adidns.DNSNode{DN: nodeDN, Name: nodeName, Records: records})
}

return nodes, nil
Expand Down Expand Up @@ -679,6 +680,16 @@ func (lc *LDAPConn) DeleteAttribute(targetDN string, attributeToDelete string) e
return err
}

func (lc *LDAPConn) DeleteAttributeValues(targetDN string, targetAttribute string, valuesToDelete []string) error {
var err error

modifyRequest := ldap.NewModifyRequest(targetDN, nil)
modifyRequest.Delete(targetAttribute, valuesToDelete)

err = lc.Conn.Modify(modifyRequest)
return err
}

func (lc *LDAPConn) MoveObject(sourceDN string, targetDN string) error {
var err error

Expand Down Expand Up @@ -809,7 +820,7 @@ func (lc *LDAPConn) FindSIDForObject(object string) (SID string, err error) {
found := false
wellKnownSID := ""
for key, val := range WellKnownSIDsMap {
if strings.ToLower(val) == strings.ToLower(object) {
if strings.EqualFold(val, object) {
found = true
wellKnownSID = key
}
Expand All @@ -830,15 +841,15 @@ func (lc *LDAPConn) FindSIDForObject(object string) (SID string, err error) {
}

func (lc *LDAPConn) FindSamForSID(SID string) (resolvedSID string, err error) {
for entry, _ := range WellKnownSIDsMap {
for entry := range WellKnownSIDsMap {
if SID == entry {
return WellKnownSIDsMap[entry], nil
}
}

query := fmt.Sprintf("(objectSID=%s)", SID)
searchReq := ldap.NewSearchRequest(
lc.RootDN,
lc.DefaultRootDN,
ldap.ScopeWholeSubtree, 0, 0, 0, false,
query,
[]string{},
Expand Down
86 changes: 0 additions & 86 deletions pkg/ldaputils/colors.go

This file was deleted.

2 changes: 1 addition & 1 deletion pkg/ldaputils/formats.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func FormatLDAPAttribute(attr *ldap.EntryAttribute, timeFormat string) []string
formattedEntries = []string{}

uacFlagKeys := make([]int, 0)
for k, _ := range UacFlags {
for k := range UacFlags {
uacFlagKeys = append(uacFlagKeys, k)
}
sort.Ints(uacFlagKeys)
Expand Down
124 changes: 62 additions & 62 deletions pkg/ldaputils/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,28 @@ type flagDesc struct {
}

var UacFlags = map[int]flagDesc{
UAC_SCRIPT: flagDesc{"Script", ""},
UAC_ACCOUNTDISABLE: flagDesc{"Disabled", "Enabled"},
UAC_HOMEDIR_REQUIRED: flagDesc{"HomeDirRequired", ""},
UAC_LOCKOUT: flagDesc{"LockedOut", ""},
UAC_PASSWD_NOTREQD: flagDesc{"PwdNotRequired", ""},
UAC_PASSWD_CANT_CHANGE: flagDesc{"CannotChangePwd", ""},
UAC_ENCRYPTED_TEXT_PWD_ALLOWED: flagDesc{"EncryptedTextPwdAllowed", ""},
UAC_TEMP_DUPLICATE_ACCOUNT: flagDesc{"TmpDuplicateAccount", ""},
UAC_NORMAL_ACCOUNT: flagDesc{"NormalAccount", ""},
UAC_INTERDOMAIN_TRUST_ACCOUNT: flagDesc{"InterdomainTrustAccount", ""},
UAC_WORKSTATION_TRUST_ACCOUNT: flagDesc{"WorkstationTrustAccount", ""},
UAC_SERVER_TRUST_ACCOUNT: flagDesc{"ServerTrustAccount", ""},
UAC_DONT_EXPIRE_PASSWORD: flagDesc{"DoNotExpirePwd", ""},
UAC_MNS_LOGON_ACCOUNT: flagDesc{"MNSLogonAccount", ""},
UAC_SMARTCARD_REQUIRED: flagDesc{"SmartcardRequired", ""},
UAC_TRUSTED_FOR_DELEGATION: flagDesc{"TrustedForDelegation", ""},
UAC_NOT_DELEGATED: flagDesc{"NotDelegated", ""},
UAC_USE_DES_KEY_ONLY: flagDesc{"UseDESKeyOnly", ""},
UAC_DONT_REQ_PREAUTH: flagDesc{"DoNotRequirePreauth", ""},
UAC_PASSWORD_EXPIRED: flagDesc{"PwdExpired", "PwdNotExpired"},
UAC_TRUSTED_TO_AUTH_FOR_DELEGATION: flagDesc{"TrustedToAuthForDelegation", ""},
UAC_PARTIAL_SECRETS_ACCOUNT: flagDesc{"PartialSecretsAccount", ""},
UAC_SCRIPT: {"Script", ""},
UAC_ACCOUNTDISABLE: {"Disabled", "Enabled"},
UAC_HOMEDIR_REQUIRED: {"HomeDirRequired", ""},
UAC_LOCKOUT: {"LockedOut", ""},
UAC_PASSWD_NOTREQD: {"PwdNotRequired", ""},
UAC_PASSWD_CANT_CHANGE: {"CannotChangePwd", ""},
UAC_ENCRYPTED_TEXT_PWD_ALLOWED: {"EncryptedTextPwdAllowed", ""},
UAC_TEMP_DUPLICATE_ACCOUNT: {"TmpDuplicateAccount", ""},
UAC_NORMAL_ACCOUNT: {"NormalAccount", ""},
UAC_INTERDOMAIN_TRUST_ACCOUNT: {"InterdomainTrustAccount", ""},
UAC_WORKSTATION_TRUST_ACCOUNT: {"WorkstationTrustAccount", ""},
UAC_SERVER_TRUST_ACCOUNT: {"ServerTrustAccount", ""},
UAC_DONT_EXPIRE_PASSWORD: {"DoNotExpirePwd", ""},
UAC_MNS_LOGON_ACCOUNT: {"MNSLogonAccount", ""},
UAC_SMARTCARD_REQUIRED: {"SmartcardRequired", ""},
UAC_TRUSTED_FOR_DELEGATION: {"TrustedForDelegation", ""},
UAC_NOT_DELEGATED: {"NotDelegated", ""},
UAC_USE_DES_KEY_ONLY: {"UseDESKeyOnly", ""},
UAC_DONT_REQ_PREAUTH: {"DoNotRequirePreauth", ""},
UAC_PASSWORD_EXPIRED: {"PwdExpired", "PwdNotExpired"},
UAC_TRUSTED_TO_AUTH_FOR_DELEGATION: {"TrustedToAuthForDelegation", ""},
UAC_PARTIAL_SECRETS_ACCOUNT: {"PartialSecretsAccount", ""},
}

var SDControlFlags = map[int]string{
Expand Down Expand Up @@ -166,49 +166,49 @@ type LibQuery struct {
}

var PredefinedLdapQueries = map[string][]LibQuery{
"Enum": []LibQuery{
LibQuery{"All Organizational Units", "(objectCategory=organizationalUnit)"},
LibQuery{"All Containers", "(objectCategory=container)"},
LibQuery{"All Groups", "(objectCategory=group)"},
LibQuery{"All Computers", "(objectClass=computer)"},
LibQuery{"All Users", "(&(objectCategory=person)(objectClass=user))"},
LibQuery{"All Objects", "(objectClass=*)"},
"Enum": {
{"All Organizational Units", "(objectCategory=organizationalUnit)"},
{"All Containers", "(objectCategory=container)"},
{"All Groups", "(objectCategory=group)"},
{"All Computers", "(objectClass=computer)"},
{"All Users", "(&(objectCategory=person)(objectClass=user))"},
{"All Objects", "(objectClass=*)"},
},
"Users": []LibQuery{
LibQuery{"Recently Created Users", "(&(objectCategory=user)(whenCreated>=<timestamp1d>))"},
LibQuery{"Users With Description", "(&(objectCategory=user)(description=*))"},
LibQuery{"Users Without Email", "(&(objectCategory=user)(!(mail=*)))"},
LibQuery{"Likely Service Users", "(&(objectCategory=user)(sAMAccountName=*svc*))"},
LibQuery{"Disabled Users", "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=2))"},
LibQuery{"Expired Users", "(&(objectCategory=user)(accountExpires<=<timestamp>))"},
LibQuery{"Users With Sensitive Infos", "(&(objectCategory=user)(|(telephoneNumber=*)(pager=*)(homePhone=*)(mobile=*)(info=*)(streetAddress=*)))"},
LibQuery{"Inactive Users", "(&(objectCategory=user)(lastLogonTimestamp<=<timestamp30d>))"},
"Users": {
{"Recently Created Users", "(&(objectCategory=user)(whenCreated>=<timestamp1d>))"},
{"Users With Description", "(&(objectCategory=user)(description=*))"},
{"Users Without Email", "(&(objectCategory=user)(!(mail=*)))"},
{"Likely Service Users", "(&(objectCategory=user)(sAMAccountName=*svc*))"},
{"Disabled Users", "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=2))"},
{"Expired Users", "(&(objectCategory=user)(accountExpires<=<timestamp>))"},
{"Users With Sensitive Infos", "(&(objectCategory=user)(|(telephoneNumber=*)(pager=*)(homePhone=*)(mobile=*)(info=*)(streetAddress=*)))"},
{"Inactive Users", "(&(objectCategory=user)(lastLogonTimestamp<=<timestamp30d>))"},
},
"Computers": []LibQuery{
LibQuery{"Domain Controllers", "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"},
LibQuery{"Non-DC Servers", "(&(objectCategory=computer)(operatingSystem=*server*)(!(userAccountControl:1.2.840.113556.1.4.803:=8192)))"},
LibQuery{"Non-Server Computers", "(&(objectCategory=computer)(!(operatingSystem=*server*))(!(userAccountControl:1.2.840.113556.1.4.803:=8192)))"},
LibQuery{"Stale Computers", "(&(objectCategory=computer)(!lastLogonTimestamp=*))"},
LibQuery{"Computers With Outdated OS", "(&(objectCategory=computer)(|(operatingSystem=*Server 2008*)(operatingSystem=*Server 2003*)(operatingSystem=*Windows XP*)(operatingSystem=*Windows 7*)))"},
"Computers": {
{"Domain Controllers", "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))"},
{"Non-DC Servers", "(&(objectCategory=computer)(operatingSystem=*server*)(!(userAccountControl:1.2.840.113556.1.4.803:=8192)))"},
{"Non-Server Computers", "(&(objectCategory=computer)(!(operatingSystem=*server*))(!(userAccountControl:1.2.840.113556.1.4.803:=8192)))"},
{"Stale Computers", "(&(objectCategory=computer)(!lastLogonTimestamp=*))"},
{"Computers With Outdated OS", "(&(objectCategory=computer)(|(operatingSystem=*Server 2008*)(operatingSystem=*Server 2003*)(operatingSystem=*Windows XP*)(operatingSystem=*Windows 7*)))"},
},
"Security": []LibQuery{
LibQuery{"Domain Admins", "(&(objectCategory=user)(memberOf=CN=Domain Admins,CN=Users,DC=domain,DC=com))"},
LibQuery{"Administrators", "(&(objectCategory=user)(memberOf=CN=Administrators,CN=Builtin,DC=domain,DC=com))"},
LibQuery{"High Privilege Users", "(&(objectCategory=user)(adminCount=1))"},
LibQuery{"Users With SPN", "(&(objectCategory=user)(servicePrincipalName=*))"},
LibQuery{"Users With SIDHistory", "(&(objectCategory=person)(objectClass=user)(sidHistory=*))"},
LibQuery{"KrbPreauth Disabled Users", "(&(objectCategory=person)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"},
LibQuery{"KrbPreauth Disabled Computers", "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"},
LibQuery{"Constrained Delegation Objects", "(msDS-AllowedToDelegateTo=*)"},
LibQuery{"Unconstrained Delegation Objects", "(userAccountControl:1.2.840.113556.1.4.803:=524288)"},
LibQuery{"RBCD Objects", "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)"},
LibQuery{"Not Trusted For Delegation", "(&(samaccountname=*)(userAccountControl:1.2.840.113556.1.4.803:=1048576))"},
LibQuery{"Shadow Credentials Targets", "(msDS-KeyCredentialLink=*)"},
LibQuery{"Must Change Password Users", "(&(objectCategory=person)(objectClass=user)(pwdLastSet=0)(!(useraccountcontrol:1.2.840.113556.1.4.803:=2)))"},
LibQuery{"Password Never Changed Users", "(&(objectCategory=user)(pwdLastSet=0))"},
LibQuery{"Never Expire Password Users", "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))"},
LibQuery{"Empty Password Users", "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=32))"},
LibQuery{"LockedOut Users", "(&(objectCategory=user)(lockoutTime>=1))"},
"Security": {
{"Domain Admins", "(&(objectCategory=user)(memberOf=CN=Domain Admins,CN=Users,DC=domain,DC=com))"},
{"Administrators", "(&(objectCategory=user)(memberOf=CN=Administrators,CN=Builtin,DC=domain,DC=com))"},
{"High Privilege Users", "(&(objectCategory=user)(adminCount=1))"},
{"Users With SPN", "(&(objectCategory=user)(servicePrincipalName=*))"},
{"Users With SIDHistory", "(&(objectCategory=person)(objectClass=user)(sidHistory=*))"},
{"KrbPreauth Disabled Users", "(&(objectCategory=person)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"},
{"KrbPreauth Disabled Computers", "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"},
{"Constrained Delegation Objects", "(msDS-AllowedToDelegateTo=*)"},
{"Unconstrained Delegation Objects", "(userAccountControl:1.2.840.113556.1.4.803:=524288)"},
{"RBCD Objects", "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)"},
{"Not Trusted For Delegation", "(&(samaccountname=*)(userAccountControl:1.2.840.113556.1.4.803:=1048576))"},
{"Shadow Credentials Targets", "(msDS-KeyCredentialLink=*)"},
{"Must Change Password Users", "(&(objectCategory=person)(objectClass=user)(pwdLastSet=0)(!(useraccountcontrol:1.2.840.113556.1.4.803:=2)))"},
{"Password Never Changed Users", "(&(objectCategory=user)(pwdLastSet=0))"},
{"Never Expire Password Users", "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))"},
{"Empty Password Users", "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=32))"},
{"LockedOut Users", "(&(objectCategory=user)(lockoutTime>=1))"},
},
}

Expand Down
Loading

0 comments on commit a032811

Please sign in to comment.