Skip to content

Commit

Permalink
Adding support for dynamic object creation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Macmod committed Dec 16, 2024
1 parent 931fe29 commit 0a11190
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 29 deletions.
118 changes: 95 additions & 23 deletions pkg/ldaputils/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"net"
"strconv"
"strings"

"github.com/Macmod/godap/v2/pkg/adidns"
Expand Down Expand Up @@ -551,55 +552,126 @@ func (lc *LDAPConn) DeleteObject(targetDN string) error {
return nil
}

func (lc *LDAPConn) AddGroup(objectName string, parentDN string) error {
// Basic templates for object creation
type AttrEntries map[string][]string

func GetGroupTemplate(objectName string) AttrEntries {
return AttrEntries{
"objectClass": []string{"top", "group"},
"cn": []string{objectName},
"sAMAccountName": []string{objectName},
}
}

func GetOUTemplate(objectName string) AttrEntries {
return AttrEntries{
"objectClass": []string{"top", "organizationalUnit"},
"cn": []string{objectName},
}
}

func GetContainerTemplate(objectName string) AttrEntries {
return AttrEntries{
"objectClass": []string{"top", "container"},
}
}

func GetComputerTemplate(objectName string) AttrEntries {
return AttrEntries{
"objectClass": []string{"top", "computer"},
"cn": []string{objectName},
"sAMAccountName": []string{objectName + "$"},
"userAccountControl": []string{"4096"},
}
}

func GetUserTemplate(objectName string, rootFQDN string) AttrEntries {
entries := AttrEntries{}

if rootFQDN != "" {
userPrincipalName := fmt.Sprintf("%s@%s", objectName, strings.ToLower(rootFQDN))
entries["userPrincipalName"] = []string{userPrincipalName}
}

return AttrEntries{
"objectClass": []string{"top", "person", "organizationalPerson", "user"},
"cn": []string{objectName},
"sAMAccountName": []string{objectName},
}
}

func AddEntriesToRequest(req *ldap.AddRequest, entries AttrEntries) {
for key, value := range entries {
req.Attribute(key, value)
}
}

func (lc *LDAPConn) AddGroup(objectName string, parentDN string, dynamicTTL int) error {
addRequest := ldap.NewAddRequest("CN="+objectName+","+parentDN, nil)
addRequest.Attribute("objectClass", []string{"top", "group"})
addRequest.Attribute("cn", []string{objectName})
addRequest.Attribute("sAMAccountName", []string{objectName})
groupTemplate := GetGroupTemplate(objectName)
if dynamicTTL > 0 {
groupTemplate["entryTTL"] = []string{strconv.Itoa(dynamicTTL)}
groupTemplate["objectClass"] = append(groupTemplate["objectClass"], "dynamicObject")
}

AddEntriesToRequest(addRequest, groupTemplate)
return lc.Conn.Add(addRequest)
}

func (lc *LDAPConn) AddOrganizationalUnit(objectName string, parentDN string) error {
func (lc *LDAPConn) AddOrganizationalUnit(objectName string, parentDN string, dynamicTTL int) error {
addRequest := ldap.NewAddRequest("OU="+objectName+","+parentDN, nil)
addRequest.Attribute("objectClass", []string{"top", "organizationalUnit"})
addRequest.Attribute("ou", []string{objectName})
ouTemplate := GetOUTemplate(objectName)
if dynamicTTL > 0 {
ouTemplate["entryTTL"] = []string{strconv.Itoa(dynamicTTL)}
ouTemplate["objectClass"] = append(ouTemplate["objectClass"], "dynamicObject")
}

AddEntriesToRequest(addRequest, ouTemplate)
return lc.Conn.Add(addRequest)
}

func (lc *LDAPConn) AddContainer(objectName string, parentDN string) error {
func (lc *LDAPConn) AddContainer(objectName string, parentDN string, dynamicTTL int) error {
addRequest := ldap.NewAddRequest("CN="+objectName+","+parentDN, nil)
addRequest.Attribute("objectClass", []string{"top", "container"})
containerTemplate := GetContainerTemplate(objectName)
if dynamicTTL > 0 {
containerTemplate["entryTTL"] = []string{strconv.Itoa(dynamicTTL)}
containerTemplate["objectClass"] = append(containerTemplate["objectClass"], "dynamicObject")
}

AddEntriesToRequest(addRequest, containerTemplate)
return lc.Conn.Add(addRequest)
}

func (lc *LDAPConn) AddComputer(objectName string, parentDN string) error {
func (lc *LDAPConn) AddComputer(objectName string, parentDN string, dynamicTTL int) error {
addRequest := ldap.NewAddRequest("CN="+objectName+","+parentDN, nil)
addRequest.Attribute("objectClass", []string{"top", "computer"})
addRequest.Attribute("cn", []string{objectName})
addRequest.Attribute("sAMAccountName", []string{objectName + "$"})
addRequest.Attribute("userAccountControl", []string{"4096"})
computerTemplate := GetComputerTemplate(objectName)
if dynamicTTL > 0 {
computerTemplate["entryTTL"] = []string{strconv.Itoa(dynamicTTL)}
computerTemplate["objectClass"] = append(computerTemplate["objectClass"], "dynamicObject")
}

AddEntriesToRequest(addRequest, computerTemplate)
return lc.Conn.Add(addRequest)
}

func (lc *LDAPConn) AddUser(objectName string, parentDN string) error {
func (lc *LDAPConn) AddUser(objectName string, parentDN string, dynamicTTL int) error {
addRequest := ldap.NewAddRequest("CN="+objectName+","+parentDN, nil)
addRequest.Attribute("objectClass", []string{"top", "person", "organizationalPerson", "user"})
addRequest.Attribute("cn", []string{objectName})
addRequest.Attribute("sAMAccountName", []string{objectName})

rootFQDN, err := lc.FindRootFQDN()

var userTemplate AttrEntries
if err == nil {
userPrincipalName := fmt.Sprintf("%s@%s", objectName, strings.ToLower(rootFQDN))
addRequest.Attribute(
"userPrincipalName",
[]string{userPrincipalName},
)
userTemplate = GetUserTemplate(objectName, rootFQDN)
} else {
userTemplate = GetUserTemplate(objectName, "")
}

if dynamicTTL > 0 {
userTemplate["entryTTL"] = []string{strconv.Itoa(dynamicTTL)}
userTemplate["objectClass"] = append(userTemplate["objectClass"], "dynamicObject")
}

AddEntriesToRequest(addRequest, userTemplate)
return lc.Conn.Add(addRequest)
}

Expand Down
19 changes: 13 additions & 6 deletions tui/explorer.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ func openCreateObjectForm(node *tview.TreeNode, done func()) {
createObjectForm := NewXForm().
AddDropDown("Object Type", []string{"OrganizationalUnit", "Container", "User", "Group", "Computer"}, 0, nil).
AddInputField("Object Name", "", 0, nil, nil).
AddInputField("Entry TTL", "-1", 0, nil, nil).
AddInputField("Parent DN", baseDN, 0, nil, nil)
createObjectForm.
SetInputCapture(handleEscape(treePanel))
Expand All @@ -304,19 +305,25 @@ func openCreateObjectForm(node *tview.TreeNode, done func()) {

objectName := createObjectForm.GetFormItemByLabel("Object Name").(*tview.InputField).GetText()

var err error = nil
entryTTL := createObjectForm.GetFormItemByLabel("Entry TTL").(*tview.InputField).GetText()
entryTTLInt, err := strconv.Atoi(entryTTL)
if err != nil {
entryTTLInt = -1
}

switch objectType {
case "OrganizationalUnit":
err = lc.AddOrganizationalUnit(objectName, baseDN)
err = lc.AddOrganizationalUnit(objectName, baseDN, entryTTLInt)
case "Container":
err = lc.AddContainer(objectName, baseDN)
err = lc.AddContainer(objectName, baseDN, entryTTLInt)
case "User":
err = lc.AddUser(objectName, baseDN)
err = lc.AddUser(objectName, baseDN, entryTTLInt)
case "Group":
err = lc.AddGroup(objectName, baseDN)
err = lc.AddGroup(objectName, baseDN, entryTTLInt)
case "Computer":
err = lc.AddComputer(objectName, baseDN)
err = lc.AddComputer(objectName, baseDN, entryTTLInt)
default:
err = fmt.Errorf("Invalid object type")
}

if err != nil {
Expand Down

0 comments on commit 0a11190

Please sign in to comment.