//go:build windows

package profile

import (
	"fmt"

	"golang.org/x/sys/windows"
)

// SecureRuntimeDir applies the protected runtime-state ACL to a directory.
func SecureRuntimeDir(path string) error {
	return setProtectedRuntimeDACL(path, windows.SUB_CONTAINERS_AND_OBJECTS_INHERIT)
}

// SecureRuntimeFile applies the protected runtime-state ACL to a file inside
// RuntimeDir. It is exported only for runtime-state owners such as the daemon.
func SecureRuntimeFile(path string) error {
	return setProtectedRuntimeDACL(path, windows.NO_INHERITANCE)
}

func setProtectedRuntimeDACL(path string, inheritance uint32) error {
	tokenUser, err := windows.GetCurrentProcessToken().GetTokenUser()
	if err != nil {
		return fmt.Errorf("get current user SID: %w", err)
	}
	systemSID, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
	if err != nil {
		return fmt.Errorf("create SYSTEM SID: %w", err)
	}

	sids := []*windows.SID{tokenUser.User.Sid}
	if !tokenUser.User.Sid.Equals(systemSID) {
		sids = append(sids, systemSID)
	}
	entries := make([]windows.EXPLICIT_ACCESS, 0, len(sids))
	for _, sid := range sids {
		entries = append(entries, windows.EXPLICIT_ACCESS{
			AccessPermissions: windows.GENERIC_ALL,
			AccessMode:        windows.SET_ACCESS,
			Inheritance:       inheritance,
			Trustee: windows.TRUSTEE{
				TrusteeForm:  windows.TRUSTEE_IS_SID,
				TrusteeType:  windows.TRUSTEE_IS_USER,
				TrusteeValue: windows.TrusteeValueFromSID(sid),
			},
		})
	}
	acl, err := windows.ACLFromEntries(entries, nil)
	if err != nil {
		return fmt.Errorf("build protected DACL: %w", err)
	}
	if err := windows.SetNamedSecurityInfo(
		path,
		windows.SE_FILE_OBJECT,
		windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
		nil,
		nil,
		acl,
		nil,
	); err != nil {
		return fmt.Errorf("set protected DACL: %w", err)
	}
	return nil
}
