APExchange_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. package service
  2. import (
  3. "encoding/hex"
  4. "strings"
  5. "testing"
  6. "time"
  7. "github.com/jcmturner/gokrb5/v8/client"
  8. "github.com/jcmturner/gokrb5/v8/config"
  9. "github.com/jcmturner/gokrb5/v8/credentials"
  10. "github.com/jcmturner/gokrb5/v8/iana/errorcode"
  11. "github.com/jcmturner/gokrb5/v8/iana/flags"
  12. "github.com/jcmturner/gokrb5/v8/iana/nametype"
  13. "github.com/jcmturner/gokrb5/v8/keytab"
  14. "github.com/jcmturner/gokrb5/v8/messages"
  15. "github.com/jcmturner/gokrb5/v8/test/testdata"
  16. "github.com/jcmturner/gokrb5/v8/types"
  17. "github.com/stretchr/testify/assert"
  18. )
  19. func TestVerifyAPREQ(t *testing.T) {
  20. t.Parallel()
  21. cl := getClient()
  22. sname := types.PrincipalName{
  23. NameType: nametype.KRB_NT_PRINCIPAL,
  24. NameString: []string{"HTTP", "host.test.gokrb5"},
  25. }
  26. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  27. kt := keytab.New()
  28. kt.Unmarshal(b)
  29. st := time.Now().UTC()
  30. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  31. sname, "TEST.GOKRB5",
  32. types.NewKrbFlags(),
  33. kt,
  34. 18,
  35. 1,
  36. st,
  37. st,
  38. st.Add(time.Duration(24)*time.Hour),
  39. st.Add(time.Duration(48)*time.Hour),
  40. )
  41. if err != nil {
  42. t.Fatalf("Error getting test ticket: %v", err)
  43. }
  44. APReq, err := messages.NewAPReq(
  45. tkt,
  46. sessionKey,
  47. newTestAuthenticator(*cl.Credentials),
  48. )
  49. if err != nil {
  50. t.Fatalf("Error getting test AP_REQ: %v", err)
  51. }
  52. h, _ := types.GetHostAddress("127.0.0.1:1234")
  53. s := NewSettings(kt, ClientAddress(h))
  54. ok, _, err := VerifyAPREQ(&APReq, s)
  55. if !ok || err != nil {
  56. t.Fatalf("Validation of AP_REQ failed when it should not have: %v", err)
  57. }
  58. }
  59. func TestVerifyAPREQWithPrincipalOverride(t *testing.T) {
  60. t.Parallel()
  61. cl := getClient()
  62. sname := types.PrincipalName{
  63. NameType: nametype.KRB_NT_PRINCIPAL,
  64. NameString: []string{"HTTP", "host.test.gokrb5"},
  65. }
  66. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  67. kt := keytab.New()
  68. kt.Unmarshal(b)
  69. st := time.Now().UTC()
  70. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  71. sname, "TEST.GOKRB5",
  72. types.NewKrbFlags(),
  73. kt,
  74. 18,
  75. 1,
  76. st,
  77. st,
  78. st.Add(time.Duration(24)*time.Hour),
  79. st.Add(time.Duration(48)*time.Hour),
  80. )
  81. if err != nil {
  82. t.Fatalf("Error getting test ticket: %v", err)
  83. }
  84. apReq, err := messages.NewAPReq(
  85. tkt,
  86. sessionKey,
  87. newTestAuthenticator(*cl.Credentials),
  88. )
  89. if err != nil {
  90. t.Fatalf("Error getting test AP_REQ: %v", err)
  91. }
  92. h, _ := types.GetHostAddress("127.0.0.1:1234")
  93. s := NewSettings(kt, ClientAddress(h), KeytabPrincipal("foo"))
  94. ok, _, err := VerifyAPREQ(&apReq, s)
  95. if ok || err == nil {
  96. t.Fatalf("Validation of AP_REQ should have failed")
  97. }
  98. if !strings.Contains(err.Error(), "Looking for [foo] realm") {
  99. t.Fatalf("Looking for wrong entity: %s", err.Error())
  100. }
  101. }
  102. func TestVerifyAPREQ_KRB_AP_ERR_BADMATCH(t *testing.T) {
  103. t.Parallel()
  104. cl := getClient()
  105. sname := types.PrincipalName{
  106. NameType: nametype.KRB_NT_PRINCIPAL,
  107. NameString: []string{"HTTP", "host.test.gokrb5"},
  108. }
  109. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  110. kt := keytab.New()
  111. kt.Unmarshal(b)
  112. st := time.Now().UTC()
  113. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  114. sname, "TEST.GOKRB5",
  115. types.NewKrbFlags(),
  116. kt,
  117. 18,
  118. 1,
  119. st,
  120. st,
  121. st.Add(time.Duration(24)*time.Hour),
  122. st.Add(time.Duration(48)*time.Hour),
  123. )
  124. if err != nil {
  125. t.Fatalf("Error getting test ticket: %v", err)
  126. }
  127. a := newTestAuthenticator(*cl.Credentials)
  128. a.CName = types.PrincipalName{
  129. NameType: nametype.KRB_NT_PRINCIPAL,
  130. NameString: []string{"BADMATCH"},
  131. }
  132. APReq, err := messages.NewAPReq(
  133. tkt,
  134. sessionKey,
  135. a,
  136. )
  137. if err != nil {
  138. t.Fatalf("Error getting test AP_REQ: %v", err)
  139. }
  140. h, _ := types.GetHostAddress("127.0.0.1:1234")
  141. s := NewSettings(kt, ClientAddress(h))
  142. ok, _, err := VerifyAPREQ(&APReq, s)
  143. if ok || err == nil {
  144. t.Fatal("Validation of AP_REQ passed when it should not have")
  145. }
  146. if _, ok := err.(messages.KRBError); ok {
  147. assert.Equal(t, errorcode.KRB_AP_ERR_BADMATCH, err.(messages.KRBError).ErrorCode, "Error code not as expected")
  148. } else {
  149. t.Fatalf("Error is not a KRBError: %v", err)
  150. }
  151. }
  152. func TestVerifyAPREQ_LargeClockSkew(t *testing.T) {
  153. t.Parallel()
  154. cl := getClient()
  155. sname := types.PrincipalName{
  156. NameType: nametype.KRB_NT_PRINCIPAL,
  157. NameString: []string{"HTTP", "host.test.gokrb5"},
  158. }
  159. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  160. kt := keytab.New()
  161. kt.Unmarshal(b)
  162. st := time.Now().UTC()
  163. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  164. sname, "TEST.GOKRB5",
  165. types.NewKrbFlags(),
  166. kt,
  167. 18,
  168. 1,
  169. st,
  170. st,
  171. st.Add(time.Duration(24)*time.Hour),
  172. st.Add(time.Duration(48)*time.Hour),
  173. )
  174. if err != nil {
  175. t.Fatalf("Error getting test ticket: %v", err)
  176. }
  177. a := newTestAuthenticator(*cl.Credentials)
  178. a.CTime = a.CTime.Add(time.Duration(-10) * time.Minute)
  179. APReq, err := messages.NewAPReq(
  180. tkt,
  181. sessionKey,
  182. a,
  183. )
  184. if err != nil {
  185. t.Fatalf("Error getting test AP_REQ: %v", err)
  186. }
  187. h, _ := types.GetHostAddress("127.0.0.1:1234")
  188. s := NewSettings(kt, ClientAddress(h))
  189. ok, _, err := VerifyAPREQ(&APReq, s)
  190. if ok || err == nil {
  191. t.Fatal("Validation of AP_REQ passed when it should not have")
  192. }
  193. if _, ok := err.(messages.KRBError); ok {
  194. assert.Equal(t, errorcode.KRB_AP_ERR_SKEW, err.(messages.KRBError).ErrorCode, "Error code not as expected")
  195. } else {
  196. t.Fatalf("Error is not a KRBError: %v", err)
  197. }
  198. }
  199. func TestVerifyAPREQ_Replay(t *testing.T) {
  200. t.Parallel()
  201. cl := getClient()
  202. sname := types.PrincipalName{
  203. NameType: nametype.KRB_NT_PRINCIPAL,
  204. NameString: []string{"HTTP", "host.test.gokrb5"},
  205. }
  206. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  207. kt := keytab.New()
  208. kt.Unmarshal(b)
  209. st := time.Now().UTC()
  210. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  211. sname, "TEST.GOKRB5",
  212. types.NewKrbFlags(),
  213. kt,
  214. 18,
  215. 1,
  216. st,
  217. st,
  218. st.Add(time.Duration(24)*time.Hour),
  219. st.Add(time.Duration(48)*time.Hour),
  220. )
  221. if err != nil {
  222. t.Fatalf("Error getting test ticket: %v", err)
  223. }
  224. APReq, err := messages.NewAPReq(
  225. tkt,
  226. sessionKey,
  227. newTestAuthenticator(*cl.Credentials),
  228. )
  229. if err != nil {
  230. t.Fatalf("Error getting test AP_REQ: %v", err)
  231. }
  232. h, _ := types.GetHostAddress("127.0.0.1:1234")
  233. s := NewSettings(kt, ClientAddress(h))
  234. ok, _, err := VerifyAPREQ(&APReq, s)
  235. if !ok || err != nil {
  236. t.Fatalf("Validation of AP_REQ failed when it should not have: %v", err)
  237. }
  238. // Replay
  239. ok, _, err = VerifyAPREQ(&APReq, s)
  240. if ok || err == nil {
  241. t.Fatal("Validation of AP_REQ passed when it should not have")
  242. }
  243. assert.IsType(t, messages.KRBError{}, err, "Error is not a KRBError")
  244. assert.Equal(t, errorcode.KRB_AP_ERR_REPEAT, err.(messages.KRBError).ErrorCode, "Error code not as expected")
  245. }
  246. func TestVerifyAPREQ_FutureTicket(t *testing.T) {
  247. t.Parallel()
  248. cl := getClient()
  249. sname := types.PrincipalName{
  250. NameType: nametype.KRB_NT_PRINCIPAL,
  251. NameString: []string{"HTTP", "host.test.gokrb5"},
  252. }
  253. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  254. kt := keytab.New()
  255. kt.Unmarshal(b)
  256. st := time.Now().UTC()
  257. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  258. sname, "TEST.GOKRB5",
  259. types.NewKrbFlags(),
  260. kt,
  261. 18,
  262. 1,
  263. st,
  264. st.Add(time.Duration(60)*time.Minute),
  265. st.Add(time.Duration(24)*time.Hour),
  266. st.Add(time.Duration(48)*time.Hour),
  267. )
  268. if err != nil {
  269. t.Fatalf("Error getting test ticket: %v", err)
  270. }
  271. a := newTestAuthenticator(*cl.Credentials)
  272. APReq, err := messages.NewAPReq(
  273. tkt,
  274. sessionKey,
  275. a,
  276. )
  277. if err != nil {
  278. t.Fatalf("Error getting test AP_REQ: %v", err)
  279. }
  280. h, _ := types.GetHostAddress("127.0.0.1:1234")
  281. s := NewSettings(kt, ClientAddress(h))
  282. ok, _, err := VerifyAPREQ(&APReq, s)
  283. if ok || err == nil {
  284. t.Fatal("Validation of AP_REQ passed when it should not have")
  285. }
  286. if _, ok := err.(messages.KRBError); ok {
  287. assert.Equal(t, errorcode.KRB_AP_ERR_TKT_NYV, err.(messages.KRBError).ErrorCode, "Error code not as expected")
  288. } else {
  289. t.Fatalf("Error is not a KRBError: %v", err)
  290. }
  291. }
  292. func TestVerifyAPREQ_InvalidTicket(t *testing.T) {
  293. t.Parallel()
  294. cl := getClient()
  295. sname := types.PrincipalName{
  296. NameType: nametype.KRB_NT_PRINCIPAL,
  297. NameString: []string{"HTTP", "host.test.gokrb5"},
  298. }
  299. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  300. kt := keytab.New()
  301. kt.Unmarshal(b)
  302. st := time.Now().UTC()
  303. f := types.NewKrbFlags()
  304. types.SetFlag(&f, flags.Invalid)
  305. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  306. sname, "TEST.GOKRB5",
  307. f,
  308. kt,
  309. 18,
  310. 1,
  311. st,
  312. st,
  313. st.Add(time.Duration(24)*time.Hour),
  314. st.Add(time.Duration(48)*time.Hour),
  315. )
  316. if err != nil {
  317. t.Fatalf("Error getting test ticket: %v", err)
  318. }
  319. APReq, err := messages.NewAPReq(
  320. tkt,
  321. sessionKey,
  322. newTestAuthenticator(*cl.Credentials),
  323. )
  324. if err != nil {
  325. t.Fatalf("Error getting test AP_REQ: %v", err)
  326. }
  327. h, _ := types.GetHostAddress("127.0.0.1:1234")
  328. s := NewSettings(kt, ClientAddress(h))
  329. ok, _, err := VerifyAPREQ(&APReq, s)
  330. if ok || err == nil {
  331. t.Fatal("Validation of AP_REQ passed when it should not have")
  332. }
  333. if _, ok := err.(messages.KRBError); ok {
  334. assert.Equal(t, errorcode.KRB_AP_ERR_TKT_NYV, err.(messages.KRBError).ErrorCode, "Error code not as expected")
  335. } else {
  336. t.Fatalf("Error is not a KRBError: %v", err)
  337. }
  338. }
  339. func TestVerifyAPREQ_ExpiredTicket(t *testing.T) {
  340. t.Parallel()
  341. cl := getClient()
  342. sname := types.PrincipalName{
  343. NameType: nametype.KRB_NT_PRINCIPAL,
  344. NameString: []string{"HTTP", "host.test.gokrb5"},
  345. }
  346. b, _ := hex.DecodeString(testdata.HTTP_KEYTAB)
  347. kt := keytab.New()
  348. kt.Unmarshal(b)
  349. st := time.Now().UTC()
  350. tkt, sessionKey, err := messages.NewTicket(cl.Credentials.CName(), cl.Credentials.Domain(),
  351. sname, "TEST.GOKRB5",
  352. types.NewKrbFlags(),
  353. kt,
  354. 18,
  355. 1,
  356. st,
  357. st,
  358. st.Add(time.Duration(-30)*time.Minute),
  359. st.Add(time.Duration(48)*time.Hour),
  360. )
  361. if err != nil {
  362. t.Fatalf("Error getting test ticket: %v", err)
  363. }
  364. a := newTestAuthenticator(*cl.Credentials)
  365. APReq, err := messages.NewAPReq(
  366. tkt,
  367. sessionKey,
  368. a,
  369. )
  370. if err != nil {
  371. t.Fatalf("Error getting test AP_REQ: %v", err)
  372. }
  373. h, _ := types.GetHostAddress("127.0.0.1:1234")
  374. s := NewSettings(kt, ClientAddress(h))
  375. ok, _, err := VerifyAPREQ(&APReq, s)
  376. if ok || err == nil {
  377. t.Fatal("Validation of AP_REQ passed when it should not have")
  378. }
  379. if _, ok := err.(messages.KRBError); ok {
  380. assert.Equal(t, errorcode.KRB_AP_ERR_TKT_EXPIRED, err.(messages.KRBError).ErrorCode, "Error code not as expected")
  381. } else {
  382. t.Fatalf("Error is not a KRBError: %v", err)
  383. }
  384. }
  385. func newTestAuthenticator(creds credentials.Credentials) types.Authenticator {
  386. auth, _ := types.NewAuthenticator(creds.Domain(), creds.CName())
  387. auth.GenerateSeqNumberAndSubKey(18, 32)
  388. //auth.Cksum = types.Checksum{
  389. // CksumType: chksumtype.GSSAPI,
  390. // Checksum: newAuthenticatorChksum([]int{GSS_C_INTEG_FLAG, GSS_C_CONF_FLAG}),
  391. //}
  392. return auth
  393. }
  394. func getClient() *client.Client {
  395. b, _ := hex.DecodeString(testdata.TESTUSER1_KEYTAB)
  396. kt := keytab.New()
  397. kt.Unmarshal(b)
  398. c, _ := config.NewFromString(testdata.TEST_KRB5CONF)
  399. cl := client.NewWithKeytab("testuser1", "TEST.GOKRB5", kt, c)
  400. return cl
  401. }