func()

in sddl/sddlString.go [91:208]


func (a *ACLList) PortableString() string {
	output := a.Flags

	for _, v := range a.ACLEntries {
		output += "("

		for k, s := range v.Sections {
			// Append a ; after the last section
			if k > 0 {
				output += ";"
			}

			if k == 5 {
				// This section is a lone SID, so we can make a call to windows and translate it.
				tx, err := translateSID(strings.TrimSpace(s))

				if err != nil {
					output += s
				} else {
					output += tx
				}
			} else if k == 6 {
				// This section will potentially have SIDs unless it's not a conditional ACE.
				// They're identifiable as they're inside a literal SID container. ex "SID(S-1-1-0)"

				workingString := ""
				lastAddPoint := 0
				if v.Sections[0] == "XA" || v.Sections[0] == "XD" || v.Sections[0] == "XU" || v.Sections[0] == "ZA" {
					// We shouldn't do any replacing if we're inside of a string.
					// In order to handle this, we'll handle it as a list of events that occur.

					stringEntries := StringRegex.FindAllStringIndex(s, -1)
					sidEntries := LiteralSIDRegex.FindAllStringIndex(s, -1)
					eventMap := map[int]int{} // 1 = string start, 2 = string end, 3 = SID start, 4 = SID end.
					eventList := make([]int, 0)
					inString := false
					SIDStart := -1
					processSID := false

					// Register string beginnings and ends
					for _, v := range stringEntries {
						eventMap[v[0]] = 1
						eventMap[v[1]] = 2
						eventList = append(eventList, v...)
					}

					// Register SID beginnings and ends
					for _, v := range sidEntries {
						eventMap[v[0]] = 3
						eventMap[v[1]] = 4
						eventList = append(eventList, v...)
					}

					// sort the list
					sort.Ints(eventList)

					// Traverse it.
					// Handle any SIDs outside of strings.
					for _, v := range eventList {
						event := eventMap[v]

						switch event {
						case 1: // String start
							inString = true
							// Add everything prior to this
							workingString += s[lastAddPoint:v]
							lastAddPoint = v
						case 2:
							inString = false
							// Add everything prior to this
							workingString += s[lastAddPoint:v]
							lastAddPoint = v
						case 3:
							processSID = !inString
							SIDStart = v
							// If we're going to process this SID, add everything prior to this.
							if processSID {
								workingString += s[lastAddPoint:v]
								lastAddPoint = v
							}
						case 4:
							if processSID {
								// We have to process the sid string now.
								sidString := strings.TrimSuffix(strings.TrimPrefix(s[SIDStart:v], "SID("), ")")

								tx, err := translateSID(strings.TrimSpace(sidString))

								// It seems like we should probably still add the string if we error out.
								// However, this just gets handled exactly like we're not processing the SID.
								// When the next event happens, we just add everything to the string, including the original SID.
								if err == nil {
									workingString += "SID(" + tx + ")"
									lastAddPoint = v
								}
							}
						}
					}
				}

				if workingString != "" {
					if lastAddPoint != len(s) {
						workingString += s[lastAddPoint:]
					}

					s = workingString
				}

				output += s
			} else {
				output += s
			}
		}

		output += ")"
	}

	return strings.TrimSpace(output)
}