Skip to content

Commit a1e5cab

Browse files
committed
Add File with SIDs support. Refactored code
1 parent c12599c commit a1e5cab

File tree

6 files changed

+129
-81
lines changed

6 files changed

+129
-81
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go:
44
- master
55

66
install:
7-
- go get -d -v ./...
7+
- go get -t -v ./...
88

99
script:
1010
- go build ./...

Dockerfile

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ COPY --from=build-env /etc/passwd /etc/passwd
2020

2121
USER app
2222

23-
WORKDIR /app
23+
VOLUME /app/data
2424

25-
ENTRYPOINT ["./gosddl"]
25+
WORKDIR /app/data
26+
27+
ENTRYPOINT ["../gosddl"]

README.md

+13-5
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,32 @@ GoSDDL (Security Descriptor Definition Language)
22
===============================================
33

44
Converter from SDDL-string to user-friendly JSON. SDDL consist of four part: Owner, Primary Group, DACL, SACL.
5-
65
This converter works with two mode:
6+
77
1) Direct
88
2) API
99

10+
You can attach file with SIDs-Username for decoding with replacement SID to Username.
11+
You should attach file with option -f. File should store with format:
12+
13+
```sh
14+
S-1-XXXX,Username1
15+
S-1-YYYY,Username2
16+
```
17+
1018
Installing
1119
------------------------------------------------
1220

1321
To start using gosddl, install Go and run go get:
1422

15-
```go
23+
```sh
1624
$ go get -u github.com/MonaxGT/gosddl
1725
```
1826

1927
Direct usage example
2028
------------------------------------------------
2129

22-
```go
30+
```sh
2331
go run gosddl.go "D:(A;;GA;;;S-1-5-21-111111111-1111111111-1111111111-11111)(A;;GA;;;SY)(A;;GXGR;;;S-1-5-5-1-1111111111)(A;;GA;;;BA)"
2432

2533
{"owner":"","primary":"","dacl":[{"accountsid":"S-1-5-21-111111111-1111111111-1111111111-11111","aceType":"ACCESS ALLOWED","aceflags":[""],"rights":["GENERIC_ALL"],"objectguid":"","InheritObjectGuid":""},{"accountsid":"Local system","aceType":"ACCESS ALLOWED","aceflags":[""],"rights":["GENERIC_ALL"],"objectguid":"","InheritObjectGuid":""},{"accountsid":"S-1-5-5-1-1111111111","aceType":"ACCESS ALLOWED","aceflags":[""],"rights":["GENERIC_EXECUTE","GENERIC_READ"],"objectguid":"","InheritObjectGuid":""},{"accountsid":"Built-in administrators","aceType":"ACCESS ALLOWED","aceflags":[""],"rights":["GENERIC_ALL"],"objectguid":"","InheritObjectGuid":""}],"daclInheritFlags":null,"sacl":null,"saclInheritFlags":null}
@@ -28,7 +36,7 @@ go run gosddl.go "D:(A;;GA;;;S-1-5-21-111111111-1111111111-1111111111-11111)(A;;
2836
API usage example
2937
------------------------------------------------
3038

31-
```go
39+
```sh
3240
go run gosddl.go -api
3341

3442
curl 'http://127.0.0.1:8000/sddl/D:(A;;GA;;;S-1-5-21-111111111-1111111111-1111111111-11111)(A;;GA;;;SY)(A;;GXGR;;;S-1-5-5-1-1111111111)(A;;GA;;;BA)'
@@ -41,7 +49,7 @@ Additionally you can use Docker
4149
```docker
4250
docker build -t gosddl .
4351
docker run -d -p 8000:8000 gosddl -api
44-
docker run --rm -it gosddl "O:BAG:SYD:(D;;GA;;;AN)(D;;GA;;;BG)(A;;GA;;;SY)(A;;GA;;;BA)S:ARAI(AU;SAFA;DCLCRPCRSDWDWO;;;WD)"
52+
docker run --rm -it -v $PWD/store:/app/data gosddl "O:BAG:SYD:(D;;GA;;;AN)(D;;GA;;;BG)(A;;GA;;;SY)(A;;GA;;;BA)S:ARAI(AU;SAFA;DCLCRPCRSDWDWO;;;WD)"
4553
```
4654

4755
Links:

gosddl.go

+103-50
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,76 @@
11
package gosddl
22

33
import (
4+
"bufio"
5+
"flag"
46
"fmt"
57
"log"
8+
"os"
69
"strings"
10+
11+
"encoding/json"
712
)
813

9-
type entryACLInternal struct {
10-
AccountSid string `json:"accountSID"`
11-
AceType string `json:"aceType"`
12-
AceFlags []string `json:"aceFlags"`
13-
Rights []string `json:"rights"`
14-
ObjectGUID string `json:"objectGUID"`
15-
InheritObjectGUID string `json:"inheritObjectGUID"`
14+
// ACLProcessor main struct with methods
15+
type ACLProcessor struct {
16+
Rights Permissons
17+
File string
18+
}
19+
20+
type entryACL struct {
21+
AccountSid string `json:"accountSID,omitempty"`
22+
AceType string `json:"aceType,omitempty"`
23+
AceFlags []string `json:"aceFlags,omitempty"`
24+
Rights []string `json:"rights,omitempty"`
25+
ObjectGUID string `json:"objectGUID,omitempty"`
26+
InheritObjectGUID string `json:"inheritObjectGUID,omitempty"`
1627
}
1728

1829
type Permissons struct {
19-
Owner string `json:"owner"`
20-
Primary string `json:"primary"`
21-
Dacl []entryACLInternal `json:"dacl"`
22-
DaclInher []string `json:"daclInheritFlags"`
23-
Sacl []entryACLInternal `json:"sacl"`
24-
SaclInger []string `json:"saclInheritFlags"`
30+
Owner string `json:"owner,omitempty"`
31+
Primary string `json:"primary,omitempty"`
32+
Dacl []entryACL `json:"dacl,omitempty"`
33+
DaclInher []string `json:"daclInheritFlags,omitempty"`
34+
Sacl []entryACL `json:"sacl,omitempty"`
35+
SaclInger []string `json:"saclInheritFlags,omitempty"`
2536
}
2637

27-
// replace identification account: sid/wellkhownsid/usersid
28-
func sidReplace(str string) string {
38+
// checkSIDsFile check file of SIDs where data saved in SID,User
39+
func checkSIDsFile(filePath string, sid string) string {
40+
file, err := os.Open(filePath)
41+
if err != nil {
42+
log.Fatal(err)
43+
}
44+
defer file.Close()
45+
46+
scanner := bufio.NewScanner(file)
47+
for scanner.Scan() {
48+
if strings.Split(scanner.Text(), ",")[0] == sid {
49+
return strings.Split(scanner.Text(), ",")[1]
50+
}
51+
}
52+
if err := scanner.Err(); err != nil {
53+
log.Fatal(err)
54+
}
55+
return sid
56+
}
57+
58+
// sidReplace replace identification account: sid/wellkhownsid/usersid
59+
func (app *ACLProcessor) sidReplace(str string) string {
2960
if len(str) > 2 {
61+
3062
if x, ok := sddlWellKnownSidsRep[str]; ok {
3163
return x
32-
} else {
33-
return str
64+
} else if app.File != "" {
65+
return checkSIDsFile(app.File, str)
3466
}
35-
return replacer(sddlWellKnownSidsRep, str)[0]
67+
return str
3668
}
37-
return replacer(sddlSidsRep, str)[0]
69+
return app.replacer(sddlSidsRep, str)[0]
3870
}
3971

40-
// chunk string with 2 letters, add to array and then resolve
41-
func replacer(maps map[string]string, str string) []string {
72+
// replacer chunk string with 2 letters, add to array and then resolve
73+
func (app *ACLProcessor) replacer(maps map[string]string, str string) []string {
4274
var temp, result []string
4375
if len(str) > 2 {
4476
for j := 0; j < len(str)-1; j = j + 2 {
@@ -57,81 +89,83 @@ func replacer(maps map[string]string, str string) []string {
5789
return result
5890
}
5991

60-
// Base format ACL: (ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid)
61-
// Convert values from string to struct with replace strings
62-
func splitBodyACL(str string) entryACLInternal {
63-
temp := strings.Split(str, ";")
64-
return entryACLInternal{
65-
AceType: replacer(sddlAceType, temp[0])[0],
66-
AceFlags: replacer(sddlAceFlags, temp[1]),
67-
Rights: replacer(sddlRights, temp[2]),
68-
ObjectGUID: temp[3],
69-
InheritObjectGUID: temp[4],
70-
AccountSid: sidReplace(temp[5]),
92+
/* splitBodyACL Convert values from string to struct with replace strings
93+
Base format Rights: (ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid)
94+
*/
95+
func (app *ACLProcessor) splitBodyACL(str string) entryACL {
96+
splitACL := strings.Split(str, ";")
97+
return entryACL{
98+
AceType: app.replacer(sddlAceType, splitACL[0])[0],
99+
AceFlags: app.replacer(sddlAceFlags, splitACL[1]),
100+
Rights: app.replacer(sddlRights, splitACL[2]),
101+
ObjectGUID: splitACL[3],
102+
InheritObjectGUID: splitACL[4],
103+
AccountSid: app.sidReplace(splitACL[5]),
71104
}
72105
}
73106

74-
func splitBody(body string) []entryACLInternal {
75-
var entryACLInternalArr []entryACLInternal
107+
func (app *ACLProcessor) splitBody(body string) []entryACL {
108+
var entryACLInternalArr []entryACL
76109
for _, y := range strings.Split(body, "(") {
77110
if y != "" {
78111
ace := strings.TrimSuffix(y, ")")
79-
entryACLInternalArr = append(entryACLInternalArr, splitBodyACL(ace))
112+
entryACLInternalArr = append(entryACLInternalArr, app.splitBodyACL(ace))
80113
}
81114
}
82115
return entryACLInternalArr
83116
}
84117

85-
func (p *Permissons) parseBody(body string) ([]string, []entryACLInternal) {
118+
func (app *ACLProcessor) parseBody(body string) ([]string, []entryACL) {
86119
var inheritFlagArr []string
87-
var entryACLInternalArr []entryACLInternal
120+
var entryACLInternalArr []entryACL
88121
if strings.Index(body, "(") != 0 {
89122
inheritFlag := body[0:strings.Index(body, "(")]
90123
ace := body[strings.Index(body, "("):]
91124
if len(inheritFlag) > 2 {
92125
for j := 0; j < len(inheritFlag)-1; j = j + 2 {
93-
inheritFlagArr = append(inheritFlagArr, replacer(sddlInheritanceFlags, fmt.Sprintf("%s%s", string(inheritFlag[j]), string(inheritFlag[j+1])))[0])
126+
inheritFlagArr = append(inheritFlagArr, app.replacer(sddlInheritanceFlags, fmt.Sprintf("%s%s", string(inheritFlag[j]), string(inheritFlag[j+1])))[0])
94127
}
95128
}
96-
entryACLInternalArr = splitBody(ace)
129+
entryACLInternalArr = app.splitBody(ace)
97130
} else {
98-
entryACLInternalArr = splitBody(body)
131+
entryACLInternalArr = app.splitBody(body)
99132
}
100133
return inheritFlagArr, entryACLInternalArr
101134
}
102135

103-
func (p *Permissons) parseSDDL(sddrArr []string) {
136+
func (app *ACLProcessor) parseSDDL(sddrArr []string) {
104137
for _, y := range sddrArr {
105138
sddlSplit := strings.Split(y, ":")
106139
letter := sddlSplit[0]
107140
body := sddlSplit[1]
108141
switch letter {
109142
case "O":
110-
p.Owner = sidReplace(body)
143+
app.Rights.Owner = app.sidReplace(body)
111144
case "G":
112-
p.Primary = sidReplace(body)
145+
app.Rights.Primary = app.sidReplace(body)
113146
case "D":
114-
p.DaclInher, p.Dacl = p.parseBody(body)
147+
app.Rights.DaclInher, app.Rights.Dacl = app.parseBody(body)
115148
case "S":
116-
p.SaclInger, p.Sacl = p.parseBody(body)
149+
app.Rights.SaclInger, app.Rights.Sacl = app.parseBody(body)
117150
default:
118151
log.Fatal("Unresolved group")
119152
}
120153
}
121154

122155
}
123156

124-
// create slice objects from str to array of strings
125-
func (p *Permissons) sliceSDDL(indecs []int, str string) {
157+
// slice SDDL create slice objects from str to array of strings
158+
func (app *ACLProcessor) sliceSDDL(indecs []int, str string) {
126159
var sddlArr []string
127160
for i := 0; i < len(indecs)-1; i++ {
128161
sl := str[indecs[i]:indecs[i+1]]
129162
sddlArr = append(sddlArr, sl)
130163
}
131-
p.parseSDDL(sddlArr)
164+
app.parseSDDL(sddlArr)
132165
}
133166

134-
func (p *Permissons) FindGroupIndex(str string) {
167+
// FindGroupIndex used for find index of group Owner, Primary, DACL, SACL
168+
func (app *ACLProcessor) findGroupIndex(str string) {
135169
groups := []string{"O:", "G:", "D:", "S:"}
136170
var result []int
137171
for _, i := range groups {
@@ -140,5 +174,24 @@ func (p *Permissons) FindGroupIndex(str string) {
140174
}
141175
}
142176
result = append(result, len(str))
143-
p.sliceSDDL(result, str)
177+
app.sliceSDDL(result, str)
178+
}
179+
180+
// Processor main function in gosddl package
181+
func Processor(api bool, port string, file string) {
182+
var app ACLProcessor
183+
app.File = file
184+
if api {
185+
fmt.Println("API Interface started on port", port)
186+
app.httpHandler(port)
187+
} else if flag.Args() != nil {
188+
app.findGroupIndex(flag.Args()[0])
189+
body, err := json.Marshal(app.Rights)
190+
if err != nil {
191+
log.Fatal(err)
192+
}
193+
fmt.Println(string(body))
194+
} else {
195+
log.Fatal("You should give me SDDL string or use API mode")
196+
}
144197
}

http.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,23 @@ import (
88
"github.com/gorilla/mux"
99
)
1010

11-
var permisson Permissons
12-
1311
func getInfo(w http.ResponseWriter, r *http.Request) {
1412
json.NewEncoder(w).Encode("Hello")
1513
}
1614

17-
func decode(w http.ResponseWriter, r *http.Request) {
15+
func (app *ACLProcessor) decode(w http.ResponseWriter, r *http.Request) {
1816
params := mux.Vars(r)
1917
if params["sddl"] != "" {
2018
sddl := params["sddl"]
21-
permisson.FindGroupIndex(sddl)
22-
json.NewEncoder(w).Encode(permisson)
19+
app.findGroupIndex(sddl)
20+
json.NewEncoder(w).Encode(app.Rights)
2321
return
2422
}
2523
}
2624

27-
func HttpHandler(port string) {
25+
func (app *ACLProcessor) httpHandler(port string) {
2826
router := mux.NewRouter()
2927
router.HandleFunc("/sddl", getInfo).Methods("GET")
30-
router.HandleFunc("/sddl/{sddl}", decode).Methods("GET")
28+
router.HandleFunc("/sddl/{sddl}", app.decode).Methods("GET")
3129
log.Fatal(http.ListenAndServe(port, router))
3230
}

service/gosddl/main.go

+3-16
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,15 @@
11
package main
22

33
import (
4-
"encoding/json"
54
"flag"
6-
"fmt"
7-
"log"
85

96
"github.com/MonaxGT/gosddl"
107
)
118

129
func main() {
13-
var permisson gosddl.Permissons
14-
apiPtr := flag.Bool("api", false, "a bool")
10+
apiPtr := flag.Bool("api", false, "Use API mode")
1511
apiPortPtr := flag.String("port", ":8000", "Default port 8000")
12+
fileSIDs := flag.String("f", "", "File with users's SIDs")
1613
flag.Parse()
17-
if *apiPtr {
18-
fmt.Println("API Interface started on port", *apiPortPtr)
19-
gosddl.HttpHandler(*apiPortPtr)
20-
} else if flag.Args() != nil {
21-
permisson.FindGroupIndex(flag.Args()[0])
22-
b, err := json.Marshal(permisson)
23-
if err != nil {
24-
log.Fatal(err)
25-
}
26-
fmt.Println(string(b))
27-
}
14+
gosddl.Processor(*apiPtr, *apiPortPtr, *fileSIDs)
2815
}

0 commit comments

Comments
 (0)