Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for complex cross-realm scenarios #1

Merged
merged 4 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading