github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/winlocal/samreg/userinfo_test.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package samreg
    16  
    17  import (
    18  	"errors"
    19  	"slices"
    20  	"strings"
    21  	"testing"
    22  )
    23  
    24  func TestUsername(t *testing.T) {
    25  	tests := []struct {
    26  		name        string
    27  		userVBuffer []byte
    28  		userF       *userF
    29  		want        string
    30  		wantErr     bool
    31  		wantErrText string
    32  	}{
    33  		{
    34  			name:        "returns_username",
    35  			userVBuffer: []byte(strings.Repeat("\x00", 16) + "\x08" + strings.Repeat("\x00", 187) + "\x42\x00\x43\x00\x44\x00\x45\x00"),
    36  			want:        "BCDE",
    37  		},
    38  		{
    39  			name:        "userV_parse_failure_returns_error",
    40  			userVBuffer: []byte(strings.Repeat("\xFF", 0xCC)),
    41  			wantErr:     true,
    42  			wantErrText: errReadOutOfBounds.Error(),
    43  		},
    44  	}
    45  
    46  	for _, tc := range tests {
    47  		t.Run(tc.name, func(t *testing.T) {
    48  			userV, err := newUserV(tc.userVBuffer, "irrelevant")
    49  			if err != nil {
    50  				t.Fatalf("Failed to create userV for tests: %v", err)
    51  			}
    52  
    53  			userinfo := UserInfo{
    54  				userV: userV,
    55  				userF: tc.userF,
    56  			}
    57  
    58  			got, gotErr := userinfo.Username()
    59  			if (gotErr != nil) != tc.wantErr {
    60  				t.Errorf("Username(): unexpected error: %v", gotErr)
    61  			}
    62  
    63  			if tc.wantErr {
    64  				if !strings.Contains(gotErr.Error(), tc.wantErrText) {
    65  					t.Errorf("Username(): unexpected error, got: %v, want: %v", gotErr, tc.wantErr)
    66  				}
    67  
    68  				return
    69  			}
    70  
    71  			if got != tc.want {
    72  				t.Errorf("Username(): got %v, want %v", got, tc.want)
    73  			}
    74  		})
    75  	}
    76  }
    77  
    78  func TestEnabled(t *testing.T) {
    79  	tests := []struct {
    80  		name    string
    81  		userV   *userV
    82  		userF   *userF
    83  		want    bool
    84  		wantErr error
    85  	}{
    86  		{
    87  			name:  "user_enabled_returns_true",
    88  			userV: nil,
    89  			userF: newUserF([]byte(strings.Repeat("A", 56)+"\x00"), "irrelevant"),
    90  			want:  true,
    91  		},
    92  		{
    93  			name:  "user_disabled_returns_false",
    94  			userV: nil,
    95  			userF: newUserF([]byte(strings.Repeat("A", 56)+"\x01"), "irrelevant"),
    96  			want:  false,
    97  		},
    98  		{
    99  			name:    "userF_parsing_failure_returns_error",
   100  			userV:   nil,
   101  			userF:   newUserF([]byte(""), "irrelevant"),
   102  			wantErr: errUserFTooShort,
   103  		},
   104  	}
   105  
   106  	for _, tc := range tests {
   107  		t.Run(tc.name, func(t *testing.T) {
   108  			userinfo := UserInfo{
   109  				userV: tc.userV,
   110  				userF: tc.userF,
   111  			}
   112  
   113  			got, gotErr := userinfo.Enabled()
   114  			if !errors.Is(gotErr, tc.wantErr) {
   115  				t.Errorf("Enabled(): unexpected error, got: %v, want: %v", gotErr, tc.wantErr)
   116  			}
   117  
   118  			if tc.wantErr != nil {
   119  				return
   120  			}
   121  
   122  			if got != tc.want {
   123  				t.Errorf("Enabled(): got %v, want %v", got, tc.want)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestHashes(t *testing.T) {
   130  	tests := []struct {
   131  		name        string
   132  		userVBuffer []byte
   133  		rid         string
   134  		syskey      []byte
   135  		wantLM      []byte
   136  		wantNT      []byte
   137  		wantErr     bool
   138  		wantErrText string
   139  	}{
   140  		{
   141  			name:        "hash_with_RC4_succeeds",
   142  			rid:         "000003E9",
   143  			userVBuffer: []byte("\x00\x00\x00\x00\xd4\x00\x00\x00\x02\x00\x01\x00\xd4\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\xe8\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\xfc\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x10\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x14\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x80\xb4\x00\x00\x00\xc4\x00\x00\x00\x14\x00\x00\x00\x44\x00\x00\x00\x02\x00\x30\x00\x02\x00\x00\x00\x02\xc0\x14\x00\x44\x00\x05\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\xc0\x14\x00\xff\xff\x1f\x00\x01\x01\x00\x00\x00\x00\x00\x05\x07\x00\x00\x00\x02\x00\x70\x00\x04\x00\x00\x00\x00\x00\x14\x00\x5b\x03\x02\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x24\x02\x00\x00\x00\x00\x24\x00\x44\x00\x02\x00\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xee\x9d\xd5\xc6\x43\xed\x3f\x53\x2e\xc8\x5e\x0a\xe9\x03\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x6c\x00\x6d\x00\x75\x00\x73\x00\x65\x00\x72\x00\x01\x02\x00\x00\x07\x00\x00\x00\x03\x00\x01\x00\x0c\x4b\x53\xdf\x15\xed\xf9\xeb\x41\x05\xfe\xca\x48\x02\x70\x55\x03\x00\x01\x00\x72\x10\xad\x76\x18\xf1\x1f\x38\x49\x24\x6d\x13\x38\x15\x8b\x03\x03\x00\x01\x00\x03\x00\x01\x00"),
   144  			syskey:      []byte("\x3d\x21\x2c\xe8\xa2\xda\x83\x43\xbd\xad\x1e\xf2\xcf\xb6\xb3\x1c"),
   145  			wantLM:      []byte("\xe5\x2c\xac\x67\x41\x9a\x9a\x22\x66\x43\x45\x14\x0a\x85\x2f\x61"),
   146  			wantNT:      []byte("\x58\xa4\x78\x13\x5a\x93\xac\x3b\xf0\x58\xa5\xea\x0e\x8f\xdb\x71"),
   147  		},
   148  		{
   149  			name:        "hash_with_RC4_only_NTLM_succeeds",
   150  			rid:         "000001F4",
   151  			userVBuffer: []byte("\x00\x00\x00\x00\xbc\x00\x00\x00\x02\x00\x01\x00\xbc\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x15\x00\x00\x00\xa8\x00\x00\x00\x5c\x01\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x64\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x68\x01\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x80\x9c\x00\x00\x00\xac\x00\x00\x00\x14\x00\x00\x00\x44\x00\x00\x00\x02\x00\x30\x00\x02\x00\x00\x00\x02\xc0\x14\x00\x44\x00\x05\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\xc0\x14\x00\xff\xff\x1f\x00\x01\x01\x00\x00\x00\x00\x00\x05\x07\x00\x00\x00\x02\x00\x58\x00\x03\x00\x00\x00\x00\x00\x14\x00\x5b\x03\x02\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x00\x00\x24\x00\x44\x00\x02\x00\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xee\x9d\xd5\xc6\x43\xed\x3f\x53\x2e\xc8\x5e\x0a\xf4\x01\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x41\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00\x72\x00\x61\x00\x74\x00\x6f\x00\x72\x00\x64\x00\x42\x00\x75\x00\x69\x00\x6c\x00\x74\x00\x2d\x00\x69\x00\x6e\x00\x20\x00\x61\x00\x63\x00\x63\x00\x6f\x00\x75\x00\x6e\x00\x74\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x61\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00\x65\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x63\x00\x6f\x00\x6d\x00\x70\x00\x75\x00\x74\x00\x65\x00\x72\x00\x2f\x00\x64\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x01\x00\x01\x02\x00\x00\x07\x00\x00\x00\x03\x00\x01\x00\x03\x00\x01\x00\xed\x92\x87\x92\x78\x3b\x69\x2c\x21\x37\x49\xbc\xdb\xe3\x1a\xf5\x03\x00\x01\x00\x03\x00\x01\x00"),
   152  			syskey:      []byte("\x3d\x21\x2c\xe8\xa2\xda\x83\x43\xbd\xad\x1e\xf2\xcf\xb6\xb3\x1c"),
   153  			wantLM:      []byte(""),
   154  			wantNT:      []byte("\x58\xa4\x78\x13\x5a\x93\xac\x3b\xf0\x58\xa5\xea\x0e\x8f\xdb\x71"),
   155  		},
   156  		{
   157  			name:        "hash_with_AES_succeeds",
   158  			rid:         "000003EA",
   159  			userVBuffer: []byte("\x00\x00\x00\x00\x0c\x01\x00\x00\x03\x00\x01\x00\x0c\x01\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x01\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x20\x01\x00\x00\x38\x00\x00\x00\x00\x00\x00\x00\x58\x01\x00\x00\x38\x00\x00\x00\x00\x00\x00\x00\x90\x01\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\xa8\x01\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x80\xec\x00\x00\x00\xfc\x00\x00\x00\x14\x00\x00\x00\x44\x00\x00\x00\x02\x00\x30\x00\x02\x00\x00\x00\x02\xc0\x14\x00\x44\x00\x05\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\xc0\x14\x00\xff\xff\x1f\x00\x01\x01\x00\x00\x00\x00\x00\x05\x07\x00\x00\x00\x02\x00\xa8\x00\x05\x00\x00\x00\x00\x00\x14\x00\x5b\x03\x02\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x24\x02\x00\x00\x00\x00\x38\x00\x1b\x03\x02\x00\x01\x0a\x00\x00\x00\x00\x00\x0f\x03\x00\x00\x00\x00\x04\x00\x00\xde\xa2\x28\x67\x21\x3e\xd2\xaf\x19\xad\x5d\x79\xb0\xc1\x07\x29\x27\x56\xfc\x20\xd8\xad\x66\xf6\x10\xf2\x68\xfa\xdf\x2a\xf8\x0f\x00\x00\x24\x00\x44\x00\x02\x00\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xed\xfd\x54\x5c\x76\xc8\xf0\x10\x1c\xda\xe3\x70\xea\x03\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x6c\x00\x6d\x00\x75\x00\x73\x00\x65\x00\x72\x00\x01\x02\x00\x00\x07\x00\x00\x00\x02\x00\x02\x00\x10\x00\x00\x00\x6a\xea\xb0\x62\x73\x97\xf9\xd0\x0d\x5d\x50\xcc\x3d\xef\xa8\xec\xed\xa9\x97\x59\x01\xe9\xa0\x17\x91\x9f\x8d\xf2\x52\x01\xd9\x6f\x69\x0f\x88\xe0\x2c\xe9\x22\x81\x9b\xf4\x14\x8f\x4b\xf9\x26\x8c\x02\x00\x02\x00\x10\x00\x00\x00\x86\xc1\x0a\xea\xc7\x24\x06\xdb\xb2\x9f\x09\x42\x87\xcf\xab\xbd\xed\xb0\x32\x75\xfb\x5d\xaf\x0a\xff\x48\xe3\x91\x51\x28\xff\xaa\x20\x93\xb3\x55\x53\xf1\x7d\x23\xde\xe0\xa6\xac\xaa\x27\x1e\xdd\x02\x00\x02\x00\x00\x00\x00\x00\x4e\x4d\xe5\x26\xdc\x17\xfa\x6f\x26\xb1\x59\xa6\xec\x09\x94\xae\x02\x00\x02\x00\x00\x00\x00\x00\x4b\x5e\x9a\x54\xa0\xc5\x6c\x8a\x07\x4e\x31\xfa\xf0\x62\xd1\xef"),
   160  			syskey:      []byte("\xfc\xde\xe8\x3a\xc6\xc1\x4b\x28\xf5\x26\x50\x1f\xc6\xe8\xbb\xc3"),
   161  			wantLM:      []byte("\xe5\x2c\xac\x67\x41\x9a\x9a\x22\x66\x43\x45\x14\x0a\x85\x2f\x61"),
   162  			wantNT:      []byte("\x58\xa4\x78\x13\x5a\x93\xac\x3b\xf0\x58\xa5\xea\x0e\x8f\xdb\x71"),
   163  		},
   164  		{
   165  			name:        "hash_with_AES_only_NTLM_succeeds",
   166  			rid:         "000001F4",
   167  			userVBuffer: []byte("\x00\x00\x00\x00\xf4\x00\x00\x00\x03\x00\x01\x00\xf4\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x01\x00\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x15\x00\x00\x00\xa8\x00\x00\x00\x94\x01\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x9c\x01\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\xb4\x01\x00\x00\x38\x00\x00\x00\x00\x00\x00\x00\xec\x01\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x04\x02\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x80\xd4\x00\x00\x00\xe4\x00\x00\x00\x14\x00\x00\x00\x44\x00\x00\x00\x02\x00\x30\x00\x02\x00\x00\x00\x02\xc0\x14\x00\x44\x00\x05\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\xc0\x14\x00\xff\xff\x1f\x00\x01\x01\x00\x00\x00\x00\x00\x05\x07\x00\x00\x00\x02\x00\x90\x00\x04\x00\x00\x00\x00\x00\x14\x00\x5b\x03\x02\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x00\x00\x38\x00\x1b\x03\x02\x00\x01\x0a\x00\x00\x00\x00\x00\x0f\x03\x00\x00\x00\x00\x04\x00\x00\xde\xa2\x28\x67\x21\x3e\xd2\xaf\x19\xad\x5d\x79\xb0\xc1\x07\x29\x27\x56\xfc\x20\xd8\xad\x66\xf6\x10\xf2\x68\xfa\xdf\x2a\xf8\x0f\x00\x00\x24\x00\x44\x00\x02\x00\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xed\xfd\x54\x5c\x76\xc8\xf0\x10\x1c\xda\xe3\x70\xf4\x01\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x41\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00\x72\x00\x61\x00\x74\x00\x6f\x00\x72\x00\x64\x00\x42\x00\x75\x00\x69\x00\x6c\x00\x74\x00\x2d\x00\x69\x00\x6e\x00\x20\x00\x61\x00\x63\x00\x63\x00\x6f\x00\x75\x00\x6e\x00\x74\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x61\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00\x65\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x63\x00\x6f\x00\x6d\x00\x70\x00\x75\x00\x74\x00\x65\x00\x72\x00\x2f\x00\x64\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb2\xb9\x06\x01\x02\x00\x00\x07\x00\x00\x00\x02\x00\x02\x00\x00\x00\x00\x00\x36\xf4\xab\xc3\x1a\x2c\xf9\x76\x09\xa4\xcb\xbb\xe4\xbc\xac\x1c\x02\x00\x02\x00\x10\x00\x00\x00\xa3\x28\x48\xec\x7d\x73\x12\xec\x81\xeb\x50\xd0\x65\x09\x55\xd4\x48\xf2\xb6\x8b\xd9\x06\xa2\xbd\xb2\xaf\x39\x1c\xe2\x60\x44\x56\x6b\x80\x62\xb6\x55\xf4\x2b\x05\x9d\xfb\x5c\x68\x55\x4a\x5b\xc3\x02\x00\x02\x00\x00\x00\x00\x00\xf4\x62\x28\xbc\x7b\xf3\x36\xe7\xaf\x0f\x7d\xf4\x88\xd6\x78\x07\x02\x00\x02\x00\x00\x00\x00\x00\x0f\x24\x35\xc2\x94\x02\xd9\x4f\x28\xe0\xe7\x92\x86\x92\xde\x0b"),
   168  			syskey:      []byte("\xfc\xde\xe8\x3a\xc6\xc1\x4b\x28\xf5\x26\x50\x1f\xc6\xe8\xbb\xc3"),
   169  			wantLM:      []byte(""),
   170  			wantNT:      []byte("\x58\xa4\x78\x13\x5a\x93\xac\x3b\xf0\x58\xa5\xea\x0e\x8f\xdb\x71"),
   171  		},
   172  		{
   173  			name:        "userV_parsing_failure_returns_error",
   174  			rid:         "000001F4",
   175  			userVBuffer: []byte(strings.Repeat("\x00", 0xCC)),
   176  			wantErr:     true,
   177  			wantErrText: errNoHashInfoFound.Error(),
   178  		},
   179  		{
   180  			name:        "decryption_failures_return_error",
   181  			rid:         "",
   182  			userVBuffer: []byte("\x00\x00\x00\x00\xbc\x00\x00\x00\x02\x00\x01\x00\xbc\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd8\x00\x00\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x01\x00\x00\x15\x00\x00\x00\xa8\x00\x00\x00\x5c\x01\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x64\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x68\x01\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x7c\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x14\x80\x9c\x00\x00\x00\xac\x00\x00\x00\x14\x00\x00\x00\x44\x00\x00\x00\x02\x00\x30\x00\x02\x00\x00\x00\x02\xc0\x14\x00\x44\x00\x05\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x02\xc0\x14\x00\xff\xff\x1f\x00\x01\x01\x00\x00\x00\x00\x00\x05\x07\x00\x00\x00\x02\x00\x58\x00\x03\x00\x00\x00\x00\x00\x14\x00\x5b\x03\x02\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x18\x00\xff\x07\x0f\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x00\x00\x24\x00\x44\x00\x02\x00\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xee\x9d\xd5\xc6\x43\xed\x3f\x53\x2e\xc8\x5e\x0a\xf4\x01\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x41\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00\x72\x00\x61\x00\x74\x00\x6f\x00\x72\x00\x64\x00\x42\x00\x75\x00\x69\x00\x6c\x00\x74\x00\x2d\x00\x69\x00\x6e\x00\x20\x00\x61\x00\x63\x00\x63\x00\x6f\x00\x75\x00\x6e\x00\x74\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x61\x00\x64\x00\x6d\x00\x69\x00\x6e\x00\x69\x00\x73\x00\x74\x00\x65\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x63\x00\x6f\x00\x6d\x00\x70\x00\x75\x00\x74\x00\x65\x00\x72\x00\x2f\x00\x64\x00\x6f\x00\x6d\x00\x61\x00\x69\x00\x6e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x01\x00\x01\x02\x00\x00\x07\x00\x00\x00\x03\x00\x01\x00\x03\x00\x01\x00\xed\x92\x87\x92\x78\x3b\x69\x2c\x21\x37\x49\xbc\xdb\xe3\x1a\xf5\x03\x00\x01\x00\x03\x00\x01\x00"),
   183  			wantErr:     true,
   184  			wantErrText: errInvalidRIDSize.Error(),
   185  		},
   186  	}
   187  
   188  	for _, tc := range tests {
   189  		t.Run(tc.name, func(t *testing.T) {
   190  			userV, err := newUserV(tc.userVBuffer, tc.rid)
   191  			if err != nil {
   192  				t.Fatalf("Failed to create userV for tests: %v", err)
   193  			}
   194  
   195  			userinfo := UserInfo{
   196  				rid:   tc.rid,
   197  				userV: userV,
   198  			}
   199  
   200  			gotLM, gotNT, gotErr := userinfo.Hashes(tc.syskey)
   201  			if (gotErr != nil) != tc.wantErr {
   202  				t.Errorf("Hashes(): unexpected error: %v", gotErr)
   203  			}
   204  
   205  			if tc.wantErr {
   206  				if !strings.Contains(gotErr.Error(), tc.wantErrText) {
   207  					t.Errorf("Hashes(): unexpected error, got: %v, want: %v", gotErr, tc.wantErr)
   208  				}
   209  
   210  				return
   211  			}
   212  
   213  			if !slices.Equal(gotLM, tc.wantLM) {
   214  				t.Errorf("Hashes(): got LM hash %x, want %x", gotLM, tc.wantLM)
   215  			}
   216  
   217  			if !slices.Equal(gotNT, tc.wantNT) {
   218  				t.Errorf("Hashes(): got NT hash %x, want %x", gotNT, tc.wantNT)
   219  			}
   220  		})
   221  	}
   222  }