diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 2b3fc12a..d21a56ff 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -61,13 +61,14 @@ jobs: run: | sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq krb5-user sudo chmod 666 /etc/krb5.conf - sudo docker run -d -h ns.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -e "TEST_KDC_ADDR=${TEST_KDC_ADDR}" -e "TEST_HTTP_ADDR=${TEST_HTTP_ADDR}" -p ${DNSUTILS_OVERRIDE_NS}:53 -p ${DNSUTILS_OVERRIDE_NS}:53/udp --name dns jcmturner/gokrb5:dns - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 88:88 -p 88:88/udp -p 464:464 -p 464:464/udp --name krb5kdc jcmturner/gokrb5:kdc-centos-default - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 78:88 -p 78:88/udp --name krb5kdc-old jcmturner/gokrb5:kdc-older - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 98:88 -p 98:88/udp --name krb5kdc-latest jcmturner/gokrb5:kdc-latest - sudo docker run -d -h kdc.resdom.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 188:88 -p 188:88/udp --name krb5kdc-resdom jcmturner/gokrb5:kdc-resdom - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 58:88 -p 58:88/udp --name krb5kdc-shorttickets jcmturner/gokrb5:kdc-shorttickets - sudo docker run -d --add-host host.test.gokrb5:127.0.0.88 -v /etc/localtime:/etc/localtime:ro -p 80:80 -p 443:443 --name gokrb5-http jcmturner/gokrb5:http + sudo docker run -d -h ns.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -e "TEST_KDC_ADDR=${TEST_KDC_ADDR}" -e "TEST_HTTP_ADDR=${TEST_HTTP_ADDR}" -p ${DNSUTILS_OVERRIDE_NS}:53 -p ${DNSUTILS_OVERRIDE_NS}:53/udp --name dns ghcr.io/grafana/gokrb5-test:dns + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 88:88 -p 88:88/udp -p 464:464 -p 464:464/udp --name krb5kdc ghcr.io/grafana/gokrb5-test:kdc-centos-default + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 78:88 -p 78:88/udp --name krb5kdc-old ghcr.io/grafana/gokrb5-test:kdc-older + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 98:88 -p 98:88/udp --name krb5kdc-latest ghcr.io/grafana/gokrb5-test:kdc-latest + sudo docker run -d -h kdc.resdom.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 188:88 -p 188:88/udp --name krb5kdc-resdom ghcr.io/grafana/gokrb5-test:kdc-resdom + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 58:88 -p 58:88/udp --name krb5kdc-shorttickets ghcr.io/grafana/gokrb5-test:kdc-shorttickets + sudo docker run -d --add-host host.test.gokrb5:127.0.0.88 -v /etc/localtime:/etc/localtime:ro -p 80:80 -p 443:443 --name gokrb5-http ghcr.io/grafana/gokrb5-test:http + sleep 10 # Wait for the containers to be ready sudo sed -i 's/nameserver .*/nameserver '${DNS_IP}'/g' /etc/resolv.conf dig _kerberos._udp.TEST.GOKRB5 id: intgTestDeps diff --git a/.github/workflows/testingv8.yml b/.github/workflows/testingv8.yml index 7f3b4b2d..62e6230f 100644 --- a/.github/workflows/testingv8.yml +++ b/.github/workflows/testingv8.yml @@ -48,13 +48,15 @@ jobs: run: | sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq krb5-user sudo chmod 666 /etc/krb5.conf - sudo docker run -d -h ns.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -e "TEST_KDC_ADDR=${TEST_KDC_ADDR}" -e "TEST_HTTP_ADDR=${TEST_HTTP_ADDR}" -p ${DNSUTILS_OVERRIDE_NS}:53 -p ${DNSUTILS_OVERRIDE_NS}:53/udp --name dns jcmturner/gokrb5:dns - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 88:88 -p 88:88/udp -p 464:464 -p 464:464/udp --name krb5kdc jcmturner/gokrb5:kdc-centos-default - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 78:88 -p 78:88/udp --name krb5kdc-old jcmturner/gokrb5:kdc-older - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 98:88 -p 98:88/udp --name krb5kdc-latest jcmturner/gokrb5:kdc-latest - sudo docker run -d -h kdc.resdom.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 188:88 -p 188:88/udp --name krb5kdc-resdom jcmturner/gokrb5:kdc-resdom - sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 58:88 -p 58:88/udp --name krb5kdc-shorttickets jcmturner/gokrb5:kdc-shorttickets - sudo docker run -d --add-host host.test.gokrb5:127.0.0.88 -v /etc/localtime:/etc/localtime:ro -p 80:80 -p 443:443 --name gokrb5-http jcmturner/gokrb5:http + sudo docker run -d -h ns.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -e "TEST_KDC_ADDR=${TEST_KDC_ADDR}" -e "TEST_HTTP_ADDR=${TEST_HTTP_ADDR}" -p ${DNSUTILS_OVERRIDE_NS}:53 -p ${DNSUTILS_OVERRIDE_NS}:53/udp --name dns ghcr.io/grafana/gokrb5-test:dns + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 88:88 -p 88:88/udp -p 464:464 -p 464:464/udp --name krb5kdc ghcr.io/grafana/gokrb5-test:kdc-centos-default + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 78:88 -p 78:88/udp --name krb5kdc-old ghcr.io/grafana/gokrb5-test:kdc-older + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 98:88 -p 98:88/udp --name krb5kdc-latest ghcr.io/grafana/gokrb5-test:kdc-latest + sudo docker run -d -h kdc.resdom.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 188:88 -p 188:88/udp --name krb5kdc-resdom ghcr.io/grafana/gokrb5-test:kdc-resdom + sudo docker run -d -h kdc.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 58:88 -p 58:88/udp --name krb5kdc-shorttickets ghcr.io/grafana/gokrb5-test:kdc-shorttickets + sudo docker run -d -h kdc.sub.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -p 288:88 -p 288:88/udp --name krb5kdc-sub ghcr.io/grafana/gokrb5-test:kdc-sub + sudo docker run -d --add-host host.test.gokrb5:127.0.0.88 -v /etc/localtime:/etc/localtime:ro -p 80:80 -p 443:443 --name gokrb5-http ghcr.io/grafana/gokrb5-test:http + sleep 10 # Wait for the containers to be ready sudo sed -i 's/nameserver .*/nameserver '${DNS_IP}'/g' /etc/resolv.conf dig _kerberos._udp.TEST.GOKRB5 id: intgTestDeps diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dec2d63a..8608919e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -98,4 +98,4 @@ It is recommended to run tests with the ```-race``` argument. There are integration tests that run against various other network services such as KDCs, HTTP web servers, DNS servers, etc. To run these pass ```-tags=integration``` as an argument to the go test command. There are vagrant and docker resources available to spin up these network services. See the -[readme](https://github.com/jcmturner/gokrb5/blob/master/testenv/README.md) in the testenv directory for instructions. +[readme](https://github.com/grafana/gokrb5-test/blob/master/testenv/README.md) in the testenv directory for instructions. diff --git a/test/README.md b/test/README.md index b5e30715..d70280c3 100644 --- a/test/README.md +++ b/test/README.md @@ -1 +1 @@ -Source for integration test dependencies can be found at https://github.com/jcmturner/gokrb5-test \ No newline at end of file +Source for integration test dependencies can be found at https://github.com/grafana/gokrb5-test \ No newline at end of file diff --git a/v8/client/TGSExchange.go b/v8/client/TGSExchange.go index fd01342e..680568e3 100644 --- a/v8/client/TGSExchange.go +++ b/v8/client/TGSExchange.go @@ -10,7 +10,7 @@ import ( // TGSREQGenerateAndExchange generates the TGS_REQ and performs a TGS exchange to retrieve a ticket to the specified SPN. func (cl *Client) TGSREQGenerateAndExchange(spn types.PrincipalName, kdcRealm string, tgt messages.Ticket, sessionKey types.EncryptionKey, renewal bool) (tgsReq messages.TGSReq, tgsRep messages.TGSRep, err error) { - tgsReq, err = messages.NewTGSReq(cl.Credentials.CName(), kdcRealm, cl.Config, tgt, sessionKey, spn, renewal) + tgsReq, err = messages.NewTGSReq(cl.Credentials.CName(), cl.Credentials.Domain(), kdcRealm, cl.Config, tgt, sessionKey, spn, renewal) if err != nil { return tgsReq, tgsRep, krberror.Errorf(err, krberror.KRBMsgError, "TGS Exchange Error: failed to generate a new TGS_REQ") } @@ -60,7 +60,7 @@ func (cl *Client) TGSExchange(tgsReq messages.TGSReq, kdcRealm string, tgt messa return tgsReq, tgsRep, err } } - tgsReq, err = messages.NewTGSReq(cl.Credentials.CName(), realm, cl.Config, tgsRep.Ticket, tgsRep.DecryptedEncPart.Key, tgsReq.ReqBody.SName, tgsReq.Renewal) + tgsReq, err = messages.NewTGSReq(cl.Credentials.CName(), cl.Credentials.Domain(), realm, cl.Config, tgsRep.Ticket, tgsRep.DecryptedEncPart.Key, tgsReq.ReqBody.SName, tgsReq.Renewal) if err != nil { return tgsReq, tgsRep, err } diff --git a/v8/client/client_integration_test.go b/v8/client/client_integration_test.go index b0039070..b034284a 100644 --- a/v8/client/client_integration_test.go +++ b/v8/client/client_integration_test.go @@ -551,6 +551,54 @@ func TestClient_GetServiceTicket_Trusted_Resource_Domain(t *testing.T) { } } +// Login to the SUB.TEST.GOKRB5 domain and request service ticket for resource in the RESDOM.GOKRB5 domain. +// There is only trust between parent domain (TEST.GOKRB5) and the service domain (RESDOM.GOKRB5). +func TestClient_GetServiceTicket_Trusted_Resource_SubDomain(t *testing.T) { + test.Integration(t) + + c, err := config.NewFromString(testdata.KRB5_CONF) + if err != nil { + t.Fatalf("error reading krb5 config: %v\n", err) + } + + addr := os.Getenv("TEST_KDC_ADDR") + if addr == "" { + addr = testdata.KDC_IP_TEST_GOKRB5 + } + + for i, r := range c.Realms { + switch r.Realm { + case "TEST.GOKRB5": + c.Realms[i].KDC = []string{addr + ":" + testdata.KDC_PORT_TEST_GOKRB5} + case "SUB.TEST.GOKRB5": + c.Realms[i].KDC = []string{addr + ":" + testdata.KDC_PORT_TEST_GOKRB5_SUB} + case "RESDOM.GOKRB5": + c.Realms[i].KDC = []string{addr + ":" + testdata.KDC_PORT_TEST_GOKRB5_RESDOM} + } + } + + c.LibDefaults.DefaultRealm = "SUB.TEST.GOKRB5" + c.LibDefaults.DefaultTktEnctypes = []string{"aes256-cts-hmac-sha1-96"} + c.LibDefaults.DefaultTktEnctypeIDs = []int32{etypeID.ETypesByName["aes256-cts-hmac-sha1-96"]} + c.LibDefaults.DefaultTGSEnctypes = []string{"aes256-cts-hmac-sha1-96"} + c.LibDefaults.DefaultTGSEnctypeIDs = []int32{etypeID.ETypesByName["aes256-cts-hmac-sha1-96"]} + + cl := client.NewWithPassword("testuser1", "SUB.TEST.GOKRB5", "passwordvalue", c) + err = cl.Login() + if err != nil { + t.Fatalf("error on login: %v\n", err) + } + + spn := "HTTP/host.resdom.gokrb5" + tkt, key, err := cl.GetServiceTicket(spn) + if err != nil { + t.Fatalf("error getting service ticket: %v\n", err) + } + + assert.Equal(t, spn, tkt.SName.PrincipalNameString()) + assert.Equal(t, etypeID.ETypesByName["aes256-cts-hmac-sha1-96"], key.KeyType) +} + const ( kinitCmd = "kinit" kvnoCmd = "kvno" diff --git a/v8/messages/KDCReq.go b/v8/messages/KDCReq.go index 3745afed..20caae0b 100644 --- a/v8/messages/KDCReq.go +++ b/v8/messages/KDCReq.go @@ -154,12 +154,12 @@ func NewASReq(realm string, c *config.Config, cname, sname types.PrincipalName) } // NewTGSReq generates a new KRB_TGS_REQ struct. -func NewTGSReq(cname types.PrincipalName, kdcRealm string, c *config.Config, tgt Ticket, sessionKey types.EncryptionKey, sname types.PrincipalName, renewal bool) (TGSReq, error) { +func NewTGSReq(cname types.PrincipalName, paRealm, kdcRealm string, c *config.Config, tgt Ticket, sessionKey types.EncryptionKey, sname types.PrincipalName, renewal bool) (TGSReq, error) { a, err := tgsReq(cname, sname, kdcRealm, renewal, c) if err != nil { return a, err } - err = a.setPAData(tgt, sessionKey) + err = a.setPAData(paRealm, tgt, sessionKey) return a, err } @@ -171,7 +171,7 @@ func NewUser2UserTGSReq(cname types.PrincipalName, kdcRealm string, c *config.Co } a.ReqBody.AdditionalTickets = []Ticket{verifyingTGT} types.SetFlag(&a.ReqBody.KDCOptions, flags.EncTktInSkey) - err = a.setPAData(clientTGT, sessionKey) + err = a.setPAData(clientTGT.Realm, clientTGT, sessionKey) return a, err } @@ -226,7 +226,7 @@ func tgsReq(cname, sname types.PrincipalName, kdcRealm string, renewal bool, c * }, nil } -func (k *TGSReq) setPAData(tgt Ticket, sessionKey types.EncryptionKey) error { +func (k *TGSReq) setPAData(paRealm string, tgt Ticket, sessionKey types.EncryptionKey) error { // Marshal the request and calculate checksum b, err := k.ReqBody.Marshal() if err != nil { @@ -243,7 +243,7 @@ func (k *TGSReq) setPAData(tgt Ticket, sessionKey types.EncryptionKey) error { // Form PAData for TGS_REQ // Create authenticator - auth, err := types.NewAuthenticator(tgt.Realm, k.ReqBody.CName) + auth, err := types.NewAuthenticator(paRealm, k.ReqBody.CName) if err != nil { return krberror.Errorf(err, krberror.KRBMsgError, "error generating new authenticator") } diff --git a/v8/test/README.md b/v8/test/README.md index b5e30715..d70280c3 100644 --- a/v8/test/README.md +++ b/v8/test/README.md @@ -1 +1 @@ -Source for integration test dependencies can be found at https://github.com/jcmturner/gokrb5-test \ No newline at end of file +Source for integration test dependencies can be found at https://github.com/grafana/gokrb5-test \ No newline at end of file diff --git a/v8/test/testdata/test_vectors.go b/v8/test/testdata/test_vectors.go index 0f568ce8..0bcf585e 100644 --- a/v8/test/testdata/test_vectors.go +++ b/v8/test/testdata/test_vectors.go @@ -127,6 +127,7 @@ const ( KDC_PORT_TEST_GOKRB5 = "88" KDC_PORT_TEST_GOKRB5_LASTEST = "98" KDC_PORT_TEST_GOKRB5_RESDOM = "188" + KDC_PORT_TEST_GOKRB5_SUB = "288" KDC_PORT_TEST_GOKRB5_OLD = "78" KDC_PORT_TEST_GOKRB5_SHORTTICKETS = "58" @@ -153,6 +154,11 @@ const ( admin_server = 127.0.0.1:749 default_domain = test.gokrb5 } + SUB.TEST.GOKRB5 = { + kdc = 127.0.0.1:288 + admin_server = 127.0.0.1:749 + default_domain = sub.test.gokrb5 + } RESDOM.GOKRB5 = { kdc = 10.80.88.88:188 admin_server = 127.0.0.1:749 @@ -162,6 +168,8 @@ const ( [domain_realm] .test.gokrb5 = TEST.GOKRB5 test.gokrb5 = TEST.GOKRB5 + .sub.test.gokrb5 = SUB.TEST.GOKRB5 + sub.test.gokrb5 = SUB.TEST.GOKRB5 .resdom.gokrb5 = RESDOM.GOKRB5 resdom.gokrb5 = RESDOM.GOKRB5 `