Last active
July 25, 2022 15:55
-
-
Save rsperl/d3e63b07b47d37af28b992f5d51cefc5 to your computer and use it in GitHub Desktop.
manage bitmasks #go #ldap #snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bitmask | |
import "sort" | |
type Decoder struct { | |
Flags map[string]int | |
} | |
func NewDecoder(flags map[string]int) *Decoder { | |
return &Decoder{Flags: flags} | |
} | |
func (d *Decoder) GetFlags(b int) []string { | |
var flags []string | |
for n, v := range d.Flags { | |
if b&v != 0 { | |
flags = append(flags, n) | |
} | |
} | |
sort.Strings(flags) | |
return flags | |
} | |
func (d *Decoder) HasFlag(b int, flag string) (bool, bool) { | |
if val, ok := d.Flags[flag]; ok { | |
return b&val != 0, ok | |
} | |
return false, false | |
} | |
func (d *Decoder) HasFlags(b int, flags []string) (bool, bool) { | |
for _, f := range flags { | |
if val, ok := d.HasFlag(b, f); !val || !ok { | |
return val, ok | |
} | |
} | |
return true, true | |
} | |
func (d *Decoder) AddFlagsByName(b int, flags []string) (int, bool) { | |
for _, f := range flags { | |
if val, ok := d.Flags[f]; ok { | |
b |= val | |
} else { | |
return -1, false | |
} | |
} | |
return b, true | |
} | |
func (d *Decoder) RemoveFlagsByName(b int, flags []string) (int, bool) { | |
for _, f := range flags { | |
if val, ok := d.Flags[f]; ok { | |
b &^= val | |
} else { | |
return -1, false | |
} | |
} | |
return b, true | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bitmask_test | |
import ( | |
"fmt" | |
"testing" | |
"gitlab.sas.com/risugg/go-bitmask" | |
) | |
var flags = make(map[string]int) | |
func init() { | |
flags["Flag01"] = 1 | |
flags["Flag02"] = 2 | |
flags["Flag04"] = 4 | |
flags["Flag08"] = 8 | |
flags["Flag16"] = 16 | |
flags["Flag32"] = 32 | |
flags["Flag64"] = 64 | |
} | |
type GetFlagsCase struct { | |
UacValue int | |
Flags []string | |
} | |
var casesGotFlags = []GetFlagsCase{ | |
GetFlagsCase{ | |
UacValue: 3, | |
Flags: []string{"Flag01", "Flag02"}, | |
}, | |
GetFlagsCase{ | |
UacValue: 25, | |
Flags: []string{"Flag01", "Flag08", "Flag16"}, | |
}, | |
GetFlagsCase{ | |
UacValue: 57, | |
Flags: []string{"Flag01", "Flag08", "Flag16", "Flag32"}, | |
}, | |
} | |
func TestGetFlags(t *testing.T) { | |
decoder := bitmask.NewDecoder(flags) | |
for _, c := range casesGotFlags { | |
gotFlags := decoder.GetFlags(c.UacValue) | |
if !cmpSlices(gotFlags, c.Flags) { | |
t.Error(getError("got flags doesn't match exp flags", gotFlags, c.Flags)) | |
} | |
if yes, ok := decoder.HasFlags(c.UacValue, c.Flags); !ok || !yes { | |
t.Error("HasFlags failed") | |
} | |
} | |
} | |
type FlagsByNameCase struct { | |
OriginalBitmask int | |
Flags []string | |
NewBitmask int | |
} | |
var casesAddFlagsByName = []FlagsByNameCase{ | |
FlagsByNameCase{ | |
OriginalBitmask: 25, | |
Flags: []string{"Flag32", "Flag64"}, | |
NewBitmask: 121, | |
}, | |
FlagsByNameCase{ | |
OriginalBitmask: 1, | |
Flags: []string{"Flag32", "Flag32", "Flag64", "Flag02"}, | |
NewBitmask: 99, | |
}, | |
} | |
func TestNewDecoder(t *testing.T) { | |
decoder := bitmask.NewDecoder(flags) | |
fmt.Printf("%v\n", decoder) | |
} | |
func TestHasFlag(t *testing.T) { | |
decoder := bitmask.NewDecoder(flags) | |
if val, ok := decoder.HasFlag(24, "Flag08"); !ok || !val { | |
t.Error("HasFlag failed") | |
} | |
if val, ok := decoder.HasFlag(24, "Flag01"); !ok || val { | |
t.Error("HasFlag failed") | |
} | |
} | |
func TestHasFlags(t *testing.T) { | |
decoder := bitmask.NewDecoder(flags) | |
if val, ok := decoder.HasFlags(24, []string{"Flag08", "Flag16"}); !ok || !val { | |
t.Errorf("HasFlags expected true, true: val=%v, ok=%v", val, ok) | |
} | |
if val, ok := decoder.HasFlags(24, []string{"Flag02", "Flag08", "Flag16"}); !ok || val { | |
t.Error("HasFlags expected false, true: val=%v, ok=%v", val, ok) | |
} | |
} | |
func TestAddFlagsByName(t *testing.T) { | |
decoder := bitmask.NewDecoder(flags) | |
for _, c := range casesAddFlagsByName { | |
gotBitmask, ok := decoder.AddFlagsByName(c.OriginalBitmask, c.Flags) | |
if !ok { | |
t.Error("invalid flag passed") | |
} | |
if gotBitmask != c.NewBitmask { | |
t.Error(getError("did not add bitmasks", gotBitmask, c.NewBitmask)) | |
} | |
if val, ok := decoder.HasFlag(gotBitmask, c.Flags[0]); !ok || !val { | |
t.Error("HasFlag failed") | |
} | |
if yes, ok := decoder.HasFlags(gotBitmask, c.Flags); !ok || !yes { | |
t.Error("HasFlags failed") | |
} | |
gotBitmask, ok = decoder.RemoveFlagsByName(gotBitmask, c.Flags) | |
if !ok { | |
t.Error("tried to remove an invalid flag") | |
} | |
if gotBitmask != c.OriginalBitmask { | |
t.Error(getError("did not remove bitmasks", gotBitmask, c.OriginalBitmask)) | |
} | |
} | |
} | |
func TestRemoveFlagsByName(t *testing.T) { | |
decoder := bitmask.NewDecoder(flags) | |
val, ok := decoder.RemoveFlagsByName(24, []string{"Flag08"}) | |
if !ok || val != 16 { | |
t.Errorf("failed to remove flag by name: val=%d, ok=%v", val, ok) | |
} | |
} | |
func getError(msg string, got interface{}, exp interface{}) string { | |
msg = msg + "\ngot: %v\nexp: %v\n" | |
return fmt.Sprintf(msg, got, exp) | |
} | |
func cmpSlices(a []string, b []string) bool { | |
if a == nil && b == nil { | |
return true | |
} | |
if len(a) != len(b) { | |
return false | |
} | |
for i, _ := range a { | |
if a[i] != b[i] { | |
return false | |
} | |
} | |
return true | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package uac | |
import "gitlab.sas.com/risugg/go-bitmask" | |
type UacDecoder struct { | |
bitmask.Decoder | |
} | |
func NewUacDecoder() *UacDecoder { | |
f := make(map[string]int) | |
f["NO_AUTH_DATA_REQUIRED"] = 33554432 | |
f["PARTIAL_SECRETS_ACCOUNT"] = 67108864 | |
f["TRUSTED_TO_AUTH_FOR_DELEGATION"] = 16777216 | |
f["PASSWORD_EXPIRED"] = 8388608 | |
f["DONT_REQ_PREAUTH"] = 4194304 | |
f["USE_DES_KEY_ONLY"] = 2097152 | |
f["NOT_DELEGATED"] = 1048576 | |
f["TRUSTED_FOR_DELEGATION"] = 524288 | |
f["SMARTCARD_REQUIRED"] = 262144 | |
f["MNS_LOGON_ACCOUNT"] = 131072 | |
f["DONT_EXPIRE_PASSWORD"] = 65536 | |
f["SERVER_TRUST_ACCOUNT"] = 8192 | |
f["WORKSTATION_TRUST_ACCOUNT"] = 4096 | |
f["INTERDOMAIN_TRUST_ACCOUNT"] = 2048 | |
f["NORMAL_ACCOUNT"] = 512 | |
f["TEMP_DUPLICATE_ACCOUNT"] = 256 | |
f["ENCRYPTED_TEXT_PWD_ALLOWED"] = 128 | |
f["PASSWD_CANT_CHANGE"] = 64 | |
f["PASSWD_NOTREQD"] = 32 | |
f["LOCKOUT"] = 16 | |
f["HOMEDIR_REQUIRED"] = 8 | |
f["ACCOUNTDISABLE"] = 2 | |
f["SCRIPT"] = 1 | |
return &UacDecoder{*bitmask.NewDecoder(f)} | |
} | |
func (u *UacDecoder) IsDisabled(b int) (bool, bool) { | |
return u.HasFlag(b, "ACCOUNTDISABLE") | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package uac_test | |
import ( | |
"testing" | |
"gitlab.sas.com/risugg/go-uac" | |
) | |
func TestIsDisabled(t *testing.T) { | |
decoder := uac.NewUacDecoder() | |
if val, ok := decoder.IsDisabled(512); !ok || val { | |
t.Error("512 should not be reported as disabled") | |
} | |
if val, ok := decoder.IsDisabled(514); !ok || !val { | |
t.Error("514 should be reported as disabled") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment