-
-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathgodap.go
More file actions
149 lines (129 loc) · 6.07 KB
/
godap.go
File metadata and controls
149 lines (129 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"fmt"
"log"
"github.com/Macmod/godap/v2/tui"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
var acceptableAuthFlagSets = []map[string]bool{
{"username": true, "password": true},
{"username": true, "passfile": true},
{"username": true, "hash": true},
{"username": true, "hashfile": true},
{"kerberos": true},
{"crt": true, "key": true},
{"pfx": true},
}
func validateFlagSet(cmd *cobra.Command) error {
used := make(map[string]bool)
cmd.Flags().Visit(func(f *pflag.Flag) {
used[f.Name] = true
})
matches := 0
partials := 0
for _, candidateSet := range acceptableAuthFlagSets {
if containsAll(used, candidateSet) {
if matches > 0 {
return fmt.Errorf("Invalid authentication flags: mixed flags from multiple acceptable sets\nPlease use only one of {-u,-p},{-u,--passfile},{-u,-H},{-u,--hashfile},{-k},{--crt,--key},{--pfx}\nor none of these for anonymous binds.")
}
matches++
} else if intersects(used, candidateSet) {
partials++
}
}
if matches == 0 && partials > 0 {
return fmt.Errorf("Invalid authentication flags: missing required flags\nPlease use only one of {-u,-p},{-u,--passfile},{-u,-H},{-u,--hashfile},{-k},{--crt,--key},{--pfx}\nor none of these for anonymous binds.")
}
return nil
}
func keys(m map[string]bool) []string {
var out []string
for k := range m {
out = append(out, "--"+k)
}
return out
}
func containsAll(provided, required map[string]bool) bool {
for k := range required {
if !provided[k] {
return false
}
}
return true
}
func intersects(setA, setB map[string]bool) bool {
for k := range setA {
if setB[k] {
return true
}
}
return false
}
func main() {
rootCmd := &cobra.Command{
Use: "godap <server address>",
Short: "A complete TUI for LDAP.",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
err := validateFlagSet(cmd)
if err != nil {
log.Fatalf(fmt.Sprint(err))
}
tui.LdapServer = args[0]
if tui.LdapPort == 0 {
if tui.Ldaps {
tui.LdapPort = 636
} else {
tui.LdapPort = 389
}
}
tui.SetupApp()
},
}
rootCmd.Flags().IntVarP(&tui.LdapPort, "port", "P", 0, "LDAP server port")
rootCmd.Flags().StringVarP(&tui.LdapUsername, "username", "u", "", "LDAP username")
rootCmd.Flags().StringVarP(&tui.LdapPassword, "password", "p", "", "LDAP password")
rootCmd.Flags().StringVarP(&tui.LdapPasswordFile, "passfile", "", "", "Path to a file containing the LDAP password (or - for stdin)")
rootCmd.Flags().StringVarP(&tui.DomainName, "domain", "d", "", "Domain for NTLM / Kerberos authentication")
rootCmd.Flags().StringVarP(&tui.NtlmHash, "hash", "H", "", "NTLM hash")
rootCmd.Flags().BoolVarP(&tui.Kerberos, "kerberos", "k", false, "Use Kerberos ticket for authentication (CCACHE specified via KRB5CCNAME environment variable)")
rootCmd.Flags().StringVarP(&tui.TargetSpn, "spn", "t", "", "Target SPN to use for Kerberos bind (usually ldap/dchostname)")
rootCmd.Flags().StringVarP(&tui.NtlmHashFile, "hashfile", "", "", "Path to a file containing the NTLM hash (or - for stdin)")
rootCmd.Flags().StringVarP(&tui.RootDN, "rootDN", "r", "", "Initial root DN")
rootCmd.Flags().StringVarP(&tui.SearchFilter, "filter", "f", "(objectClass=*)", "Initial LDAP search filter")
rootCmd.Flags().BoolVarP(&tui.Emojis, "emojis", "E", true, "Prefix objects with emojis")
rootCmd.Flags().BoolVarP(&tui.Colors, "colors", "C", true, "Colorize objects")
rootCmd.Flags().BoolVarP(&tui.FormatAttrs, "format", "F", true, "Format attributes into human-readable values")
rootCmd.Flags().BoolVarP(&tui.ExpandAttrs, "expand", "A", true, "Expand multi-value attributes")
rootCmd.Flags().IntVarP(&tui.AttrLimit, "limit", "L", 20, "Number of attribute values to render for multi-value attributes when -expand is set true")
rootCmd.Flags().BoolVarP(&tui.CacheEntries, "cache", "M", true, "Keep loaded entries in memory while the program is open and don't query them again")
rootCmd.Flags().BoolVarP(&tui.Deleted, "deleted", "D", false, "Include deleted objects in all queries performed")
rootCmd.Flags().Int32VarP(&tui.Timeout, "timeout", "T", 10, "Timeout for LDAP connections in seconds")
rootCmd.Flags().BoolVarP(&tui.LoadSchema, "schema", "s", false, "Load schema GUIDs from the LDAP server during initialization")
rootCmd.Flags().Uint32VarP(&tui.PagingSize, "paging", "G", 800, "Default paging size for regular queries")
rootCmd.Flags().BoolVarP(&tui.Insecure, "insecure", "I", false, "Skip TLS verification for LDAPS/StartTLS")
rootCmd.Flags().BoolVarP(&tui.Ldaps, "ldaps", "S", false, "Use LDAPS for initial connection")
rootCmd.Flags().StringVarP(&tui.SocksServer, "socks", "x", "", "Use a SOCKS proxy for initial connection")
rootCmd.Flags().StringVarP(&tui.KdcHost, "kdc", "", "", "Address of the KDC to use with Kerberos authentication (optional: only if the KDC differs from the specified LDAP server)")
rootCmd.Flags().StringVarP(&tui.TimeFormat, "timefmt", "", "", "Time format for LDAP timestamps")
rootCmd.Flags().StringVarP(&tui.CertFile, "crt", "", "", "Path to a file containing the certificate to use for the bind")
rootCmd.Flags().StringVarP(&tui.KeyFile, "key", "", "", "Path to a file containing the private key to use for the bind")
rootCmd.Flags().StringVarP(&tui.PfxFile, "pfx", "", "", "Path to a file containing the PFX to use for the bind")
rootCmd.Flags().StringVarP(&tui.AttrSort, "attrsort", "", "none", "Sort attributes by name (none, asc, desc)")
rootCmd.Flags().IntVarP(&tui.TimeOffset, "offset", "", 0, "Offset in hours to apply to formatted timestamps")
rootCmd.Flags().StringVarP(&tui.ExportDir, "exportdir", "", "data", "Custom directory to save godap exports taken with Ctrl+S")
rootCmd.Flags().StringVarP(&tui.BackendFlavor, "backend", "b", "msad", "LDAP backend flavor (msad, basic or auto)")
versionCmd := &cobra.Command{
Use: "version",
Short: "Print the version number of the application",
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(tui.GodapVer)
},
}
rootCmd.AddCommand(versionCmd)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
}
}