Skip to content

Commit

Permalink
Support for complex cross-realm scenarios (#1)
Browse files Browse the repository at this point in the history
* Set up test case for cross-ream support (jcmturner#130)

* Support for complex cross-realm scenarios

Co-authored-by: Ivan <[email protected]>
Co-authored-by: Sarthak Gupta <[email protected]>
Co-authored-by: xtian <[email protected]>

* Fix test case for cross-ream support

---------

Co-authored-by: Ivan <[email protected]>
Co-authored-by: Sarthak Gupta <[email protected]>
Co-authored-by: xtian <[email protected]>
  • Loading branch information
4 people authored May 29, 2024
1 parent db2a138 commit d911871
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 7 deletions.
1 change: 1 addition & 0 deletions .github/workflows/testingv8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
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
Expand Down
4 changes: 2 additions & 2 deletions v8/client/TGSExchange.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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
}
Expand Down
48 changes: 48 additions & 0 deletions v8/client/client_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
10 changes: 5 additions & 5 deletions v8/messages/KDCReq.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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")
}
Expand Down
8 changes: 8 additions & 0 deletions v8/test/testdata/test_vectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand All @@ -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
`
Expand Down

0 comments on commit d911871

Please sign in to comment.