github.com/jcmturner/gokrb5/v8@v8.4.4/keytab/keytab_test.go (about) 1 package keytab 2 3 import ( 4 "encoding/base64" 5 "encoding/binary" 6 "encoding/hex" 7 "os" 8 "path/filepath" 9 "testing" 10 "time" 11 12 "github.com/jcmturner/gokrb5/v8/iana/etypeID" 13 "github.com/jcmturner/gokrb5/v8/iana/nametype" 14 "github.com/jcmturner/gokrb5/v8/test/testdata" 15 "github.com/jcmturner/gokrb5/v8/types" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 func TestUnmarshal(t *testing.T) { 20 t.Parallel() 21 b, _ := hex.DecodeString(testdata.KEYTAB_TESTUSER1_TEST_GOKRB5) 22 kt := New() 23 err := kt.Unmarshal(b) 24 if err != nil { 25 t.Fatalf("Error parsing keytab data: %v\n", err) 26 } 27 assert.Equal(t, uint8(2), kt.version, "Keytab version not as expected") 28 assert.Equal(t, uint32(1), kt.Entries[0].KVNO, "KVNO not as expected") 29 assert.Equal(t, uint8(1), kt.Entries[0].KVNO8, "KVNO8 not as expected") 30 assert.Equal(t, time.Unix(1505669592, 0), kt.Entries[0].Timestamp, "Timestamp not as expected") 31 assert.Equal(t, int32(17), kt.Entries[0].Key.KeyType, "Key's EType not as expected") 32 assert.Equal(t, "698c4df8e9f60e7eea5a21bf4526ad25", hex.EncodeToString(kt.Entries[0].Key.KeyValue), "Key material not as expected") 33 assert.Equal(t, int16(1), kt.Entries[0].Principal.NumComponents, "Number of components in principal not as expected") 34 assert.Equal(t, int32(1), kt.Entries[0].Principal.NameType, "Name type of principal not as expected") 35 assert.Equal(t, "TEST.GOKRB5", kt.Entries[0].Principal.Realm, "Realm of principal not as expected") 36 assert.Equal(t, "testuser1", kt.Entries[0].Principal.Components[0], "Component in principal not as expected") 37 } 38 39 func TestMarshal(t *testing.T) { 40 t.Parallel() 41 b, _ := hex.DecodeString(testdata.KEYTAB_TESTUSER1_TEST_GOKRB5) 42 kt := New() 43 err := kt.Unmarshal(b) 44 if err != nil { 45 t.Fatalf("Error parsing keytab data: %v\n", err) 46 } 47 mb, err := kt.Marshal() 48 if err != nil { 49 t.Fatalf("Error marshaling: %v", err) 50 } 51 assert.Equal(t, b, mb, "Marshaled bytes not the same as input bytes") 52 err = kt.Unmarshal(mb) 53 if err != nil { 54 t.Fatalf("Error parsing marshaled bytes: %v", err) 55 } 56 } 57 58 func TestLoad(t *testing.T) { 59 t.Parallel() 60 f := "test/testdata/testuser1.testtab" 61 cwd, _ := os.Getwd() 62 dir := os.Getenv("TRAVIS_BUILD_DIR") 63 if dir != "" { 64 f = dir + "/" + f 65 } else if filepath.Base(cwd) == "keytab" { 66 f = "../" + f 67 } 68 kt, err := Load(f) 69 if err != nil { 70 t.Fatalf("could not load keytab: %v", err) 71 } 72 assert.Equal(t, uint8(2), kt.version, "keytab version not as expected") 73 assert.Equal(t, 12, len(kt.Entries), "keytab entry count not as expected: %+v", *kt) 74 for _, e := range kt.Entries { 75 if e.Principal.Realm != "TEST.GOKRB5" { 76 t.Error("principal realm not as expected") 77 } 78 if e.Principal.NameType != int32(1) { 79 t.Error("name type not as expected") 80 } 81 if e.Principal.NumComponents != int16(1) { 82 t.Error("number of component not as expected") 83 } 84 if len(e.Principal.Components) != 1 { 85 t.Error("number of component not as expected") 86 } 87 if e.Principal.Components[0] != "testuser1" { 88 t.Error("principal components not as expected") 89 } 90 if e.Timestamp.IsZero() { 91 t.Error("entry timestamp incorrect") 92 } 93 if e.KVNO == uint32(0) { 94 t.Error("entry kvno not as expected") 95 } 96 if e.KVNO8 == uint8(0) { 97 t.Error("entry kvno8 not as expected") 98 } 99 } 100 } 101 102 // This test provides inputs to readBytes that previously 103 // caused a panic. 104 func TestReadBytes(t *testing.T) { 105 var endian binary.ByteOrder 106 endian = binary.BigEndian 107 p := 0 108 109 if _, err := readBytes(nil, &p, 1, &endian); err == nil { 110 t.Fatal("err should be populated because s was given that exceeds array length") 111 } 112 if _, err := readBytes(nil, &p, -1, &endian); err == nil { 113 t.Fatal("err should be given because negative s was given") 114 } 115 } 116 117 func TestUnmarshalPotentialPanics(t *testing.T) { 118 kt := New() 119 120 // Test a good keytab with bad bytes to unmarshal. These should 121 // return errors, but not panic. 122 if err := kt.Unmarshal(nil); err == nil { 123 t.Fatal("should have errored, input is absent") 124 } 125 if err := kt.Unmarshal([]byte{}); err == nil { 126 t.Fatal("should have errored, input is empty") 127 } 128 // Incorrect first byte. 129 if err := kt.Unmarshal([]byte{4}); err == nil { 130 t.Fatal("should have errored, input isn't long enough") 131 } 132 // First byte, but no further content. 133 if err := kt.Unmarshal([]byte{5}); err == nil { 134 t.Fatal("should have errored, input isn't long enough") 135 } 136 } 137 138 // cxf testing stuff 139 func TestBadKeytabs(t *testing.T) { 140 badPayloads := make([]string, 3) 141 badPayloads = append(badPayloads, "BQIwMDAwMDA=") 142 badPayloads = append(badPayloads, "BQIAAAAwAAEACjAwMDAwMDAwMDAAIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw") 143 badPayloads = append(badPayloads, "BQKAAAAA") 144 for _, v := range badPayloads { 145 decodedKt, _ := base64.StdEncoding.DecodeString(v) 146 parsedKt := new(Keytab) 147 parsedKt.Unmarshal(decodedKt) 148 } 149 } 150 151 func TestKeytabEntriesUser(t *testing.T) { 152 153 // Load known-good keytab generated with ktutil 154 ktutilb64 := "BQIAAABGAAEAC0VYQU1QTEUuT1JHAAR1c2VyAAAAAV5ePQAfABIAIG6I6ys5Me8XyS54Ck7kIfFBH/WxBOP3W1DdE/ntBPnGAAAAHwAAADYAAQALRVhBTVBMRS5PUkcABHVzZXIAAAABXl49AB8AEQAQm7fVug9VRBJVhEGjHyN3EgAAAB8AAAA2AAEAC0VYQU1QTEUuT1JHAAR1c2VyAAAAAV5ePQAfABcAEBENDFHhRNNvt+T54BL7uIgAAAAf" 155 ktutilbytes, err := base64.StdEncoding.DecodeString(ktutilb64) 156 if err != nil { 157 t.Errorf("Could not parse b64 ktutil keytab: %s", err) 158 } 159 ktutil := new(Keytab) 160 err = ktutil.Unmarshal(ktutilbytes) 161 if err != nil { 162 t.Fatalf("Could not load ktutil-generated keytab: %s", err) 163 } 164 165 // Generate the same keytab with gokrb5 166 var ts time.Time = ktutil.Entries[0].Timestamp 167 var encTypes []int32 = []int32{ 168 etypeID.AES256_CTS_HMAC_SHA1_96, 169 etypeID.AES128_CTS_HMAC_SHA1_96, 170 etypeID.RC4_HMAC, 171 } 172 173 kt := New() 174 for _, et := range encTypes { 175 err = kt.AddEntry("user", "EXAMPLE.ORG", "hello123", ts, uint8(31), et) 176 if err != nil { 177 t.Errorf("Error adding entry to keytab: %s", err) 178 } 179 } 180 generated, err := kt.Marshal() 181 if err != nil { 182 t.Errorf("Error marshalling generated keytab: %s", err) 183 } 184 185 // Compare content 186 assert.Equal(t, generated, ktutilbytes, "Service keytab doesn't match ktutil keytab") 187 } 188 189 func TestKeytabEntriesService(t *testing.T) { 190 191 // Load known-good keytab generated with ktutil 192 ktutilb64 := "BQIAAABXAAIAC0VYQU1QTEUuT1JHAARIVFRQAA93d3cuZXhhbXBsZS5vcmcAAAABXl49ggoAEgAgOCSpM5CdiZQn1+rUtLtt6sTrg5Saw1DXJMai7vDWJ0QAAAAKAAAARwACAAtFWEFNUExFLk9SRwAESFRUUAAPd3d3LmV4YW1wbGUub3JnAAAAAV5ePYIKABEAEDpczoDyER1jscz0RWkThCMAAAAKAAAARwACAAtFWEFNUExFLk9SRwAESFRUUAAPd3d3LmV4YW1wbGUub3JnAAAAAV5ePYIKABcAELP27YfH0Th5rD+GtJkQmXQAAAAK" 193 ktutilbytes, err := base64.StdEncoding.DecodeString(ktutilb64) 194 if err != nil { 195 t.Errorf("Could not parse b64 ktutil keytab: %s", err) 196 } 197 ktutil := new(Keytab) 198 err = ktutil.Unmarshal(ktutilbytes) 199 if err != nil { 200 t.Errorf("Could not load ktutil-generated keytab: %s", err) 201 } 202 203 // Generate the same keytab with gokrb5 204 var ts time.Time = ktutil.Entries[0].Timestamp 205 var encTypes []int32 = []int32{ 206 etypeID.AES256_CTS_HMAC_SHA1_96, 207 etypeID.AES128_CTS_HMAC_SHA1_96, 208 etypeID.RC4_HMAC, 209 } 210 211 kt := New() 212 for _, et := range encTypes { 213 err = kt.AddEntry("HTTP/www.example.org", "EXAMPLE.ORG", "hello456", ts, uint8(10), et) 214 if err != nil { 215 t.Errorf("Error adding entry to keytab: %s", err) 216 } 217 } 218 generated, err := kt.Marshal() 219 if err != nil { 220 t.Errorf("Error marshalling generated keytab: %s", err) 221 } 222 223 // Compare content 224 assert.Equal(t, generated, ktutilbytes, "Service keytab doesn't match ktutil keytab") 225 } 226 227 func TestKeytab_GetEncryptionKey(t *testing.T) { 228 princ := "HTTP/princ.test.gokrb5" 229 realm := "TEST.GOKRB5" 230 231 kt := New() 232 kt.AddEntry(princ, realm, "abcdefg", time.Unix(100, 0), 1, 18) 233 kt.AddEntry(princ, realm, "abcdefg", time.Unix(200, 0), 2, 18) 234 kt.AddEntry(princ, realm, "abcdefg", time.Unix(300, 0), 3, 18) 235 kt.AddEntry(princ, realm, "abcdefg", time.Unix(400, 0), 4, 18) 236 kt.AddEntry(princ, realm, "abcdefg", time.Unix(350, 0), 5, 18) 237 kt.AddEntry("HTTP/other.test.gokrb5", realm, "abcdefg", time.Unix(500, 0), 5, 18) 238 239 pn := types.NewPrincipalName(nametype.KRB_NT_PRINCIPAL, princ) 240 241 _, kvno, err := kt.GetEncryptionKey(pn, realm, 0, 18) 242 if err != nil { 243 t.Error(err) 244 } 245 assert.Equal(t, 4, kvno) 246 _, kvno, err = kt.GetEncryptionKey(pn, realm, 3, 18) 247 if err != nil { 248 t.Error(err) 249 } 250 assert.Equal(t, 3, kvno) 251 }