keytab_test.go 8.2 KB

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