Files

116 lines
5.7 KiB
Go

package windows
import (
"testing"
rvboxv1 "github.com/rvbox/rvbox/gen/go/rvbox/v1"
)
func TestSelectExecutionContext_HP_WINCTX_02(t *testing.T) {
t.Parallel()
standard := active(TokenFacts{Usable: true, StandardOrFiltered: true})
full := active(TokenFacts{Usable: true, FullAdministrator: true})
cases := []struct {
name string
input SelectionInput
want ExecutionContext
attempts []ExecutionContext
}{
{"active standard normal", SelectionInput{ActiveSessions: []SessionCandidate{standard}}, ContextActiveUser, []ExecutionContext{ContextActiveUser}},
{"active full normal restricted", SelectionInput{ActiveSessions: []SessionCandidate{active(TokenFacts{Usable: true, FullAdministrator: true, RestrictedMediumAllowed: true})}}, ContextActiveUser, []ExecutionContext{ContextActiveUser}},
{"active linked admin elevated", SelectionInput{Elevated: true, ActiveSessions: []SessionCandidate{active(TokenFacts{Usable: true, LinkedFullAvailable: true})}}, ContextActiveUserElevated, []ExecutionContext{ContextActiveUserElevated}},
{"active full admin elevated", SelectionInput{Elevated: true, ActiveSessions: []SessionCandidate{full}}, ContextActiveUserElevated, []ExecutionContext{ContextActiveUserElevated}},
{"active elevation fallback", SelectionInput{Elevated: true, ActiveSessions: []SessionCandidate{standard}, ActiveSystemAvailable: true}, ContextActiveSystem, []ExecutionContext{ContextActiveUserElevated, ContextActiveSystem}},
{"active local system final fallback", SelectionInput{Elevated: true, ActiveSessions: []SessionCandidate{standard}, LocalSystemAvailable: true}, ContextLocalSystem, []ExecutionContext{ContextActiveUserElevated, ContextActiveSystem, ContextLocalSystem}},
{"no user normal", SelectionInput{LocalServiceAvailable: true}, ContextLocalService, []ExecutionContext{ContextLocalService}},
{"no user elevated", SelectionInput{Elevated: true, LocalSystemAvailable: true}, ContextLocalSystem, []ExecutionContext{ContextLocalSystem}},
}
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
got := Select(test.input)
if err := got.Validate(); err != nil {
t.Fatal(err)
}
if got.Effective == nil || got.Effective.Context != test.want {
t.Fatalf("effective = %+v, want %s", got.Effective, test.want)
}
if len(got.Attempts) != len(test.attempts) {
t.Fatalf("attempt count = %d, want %d", len(got.Attempts), len(test.attempts))
}
for index, want := range test.attempts {
if got.Attempts[index].Context != want {
t.Fatalf("attempt %d = %s, want %s", index, got.Attempts[index].Context, want)
}
}
if got.Effective.Context == ContextLocalSystem || got.Effective.Context == ContextLocalService {
if got.Effective.SessionID != nil || got.Effective.UserSID != "" || got.Effective.LogonSID != "" {
t.Fatalf("Session 0 identity leaked active-session fields: %+v", got.Effective)
}
}
})
}
_ = rvboxv1.ControlError_CODE_ELEVATION_UNAVAILABLE
}
func TestSelectExecutionContextBoundaries_BH_WINCTX_02(t *testing.T) {
t.Parallel()
standard := active(TokenFacts{Usable: true, StandardOrFiltered: true})
cases := []struct {
name string
input SelectionInput
wantCode rvboxv1.ControlError_Code
wantReason AttemptReason
wantTry []ExecutionContext
}{
{"normal active cannot downgrade full", SelectionInput{ActiveSessions: []SessionCandidate{active(TokenFacts{Usable: true, FullAdministrator: true})}, LocalServiceAvailable: true}, rvboxv1.ControlError_CODE_EXECUTION_CONTEXT_UNAVAILABLE, "", []ExecutionContext{ContextActiveUser}},
{"approval falls back", SelectionInput{Elevated: true, ActiveSessions: []SessionCandidate{active(TokenFacts{Usable: true, ApprovalPolicyRequired: true})}, ActiveSystemAvailable: false, LocalSystemAvailable: true}, 0, "", []ExecutionContext{ContextActiveUserElevated, ContextActiveSystem, ContextLocalSystem}},
{"ambiguous sessions use no user row", SelectionInput{Elevated: false, ActiveSessions: ambiguousSessions(standard.Token), LocalServiceAvailable: true}, 0, ReasonAmbiguousActiveSessions, []ExecutionContext{ContextLocalService}},
{"no user service unavailable", SelectionInput{}, rvboxv1.ControlError_CODE_EXECUTION_CONTEXT_UNAVAILABLE, ReasonNoUsableActiveSession, []ExecutionContext{ContextLocalService}},
{"no user elevated unavailable", SelectionInput{Elevated: true}, rvboxv1.ControlError_CODE_ELEVATION_UNAVAILABLE, ReasonNoUsableActiveSession, []ExecutionContext{ContextLocalSystem}},
}
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
got := Select(test.input)
if err := got.Validate(); err != nil {
t.Fatal(err)
}
if test.wantCode != 0 {
if got.Error == nil || got.Error.Code != test.wantCode {
t.Fatalf("error = %+v, want %s", got.Error, test.wantCode)
}
} else if got.Effective == nil {
t.Fatalf("selection failed: %+v", got.Error)
}
if got.NoActiveReason != test.wantReason {
t.Fatalf("no-active reason = %q, want %q", got.NoActiveReason, test.wantReason)
}
if len(got.Attempts) != len(test.wantTry) {
t.Fatalf("attempts = %+v", got.Attempts)
}
for index, want := range test.wantTry {
if got.Attempts[index].Context != want {
t.Fatalf("attempt %d = %s, want %s", index, got.Attempts[index].Context, want)
}
}
})
}
}
func active(token TokenFacts) SessionCandidate {
return SessionCandidate{SessionID: 1, Console: true, UserSID: "S-1-5-21-1", LogonSID: "S-1-5-5-1-2", Token: token}
}
func ambiguousSessions(token TokenFacts) []SessionCandidate {
first := active(token)
first.Console = false
second := active(token)
second.Console = false
second.SessionID = 2
second.UserSID = "S-1-5-21-2"
second.LogonSID = "S-1-5-5-2-3"
return []SessionCandidate{first, second}
}