Skip to content

Commit

Permalink
use canonical name to derive SPN (#274)
Browse files Browse the repository at this point in the history
use canonical name to derive SPN. Test against G0 1.12
  • Loading branch information
jcmturner committed Mar 10, 2019
1 parent 95f6d33 commit 50a61c6
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 65 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ language: go
go:
- 1.10.x
- 1.11.x
- 1.12.x
- master

go_import_path: gopkg.in/jcmturner/gokrb5.v7
Expand All @@ -16,7 +17,7 @@ before_install:
- sudo apt-get install -yq krb5-user
- sudo chmod 666 /etc/krb5.conf
- go get -u golang.org/x/lint/golint
- docker run -d -h ns.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -e "TEST_KDC_ADDR=127.0.0.1" -p 53:53 -p 53:53/udp --name dns jcmturner/gokrb5:dns
- docker run -d -h ns.test.gokrb5 -v /etc/localtime:/etc/localtime:ro -e "TEST_KDC_ADDR=127.0.0.1" -e "TEST_HTTP_ADDR=127.0.0.1" -p 53:53 -p 53:53/udp --name dns jcmturner/gokrb5:dns
- 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
- 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
- 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
Expand All @@ -29,7 +30,7 @@ before_script:
- sudo sed -i 's/nameserver .*/nameserver 127.0.0.1/g' /etc/resolv.conf

env:
- INTEGRATION=1 TESTPRIVILEGED=1 TEST_KDC_ADDR=127.0.0.1 TEST_HTTP_URL="http://host.test.gokrb5" DNSUTILS_OVERRIDE_NS="127.0.0.1:53" DEBIAN_FRONTEND=noninteractive
- INTEGRATION=1 TESTPRIVILEGED=1 TEST_KDC_ADDR=127.0.0.1 TEST_HTTP_URL="http://cname.test.gokrb5" TEST_HTTP_ADDR="127.0.0.1" DNSUTILS_OVERRIDE_NS="127.0.0.1:53" DEBIAN_FRONTEND=noninteractive

script:
- test -z $(gofmt -s -d -l -e $GO_FILES | tee /dev/fd/2 | xargs | sed 's/\s//g') # Fail if a .go file hasn't been formatted with gofmt
Expand All @@ -41,7 +42,6 @@ script:

addons:
hosts:
- host.test.gokrb5
- kdc.test.gokrb5
- kdc.resdom.gokrb5

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![GoDoc](https://godoc.org/gopkg.in/jcmturner/gokrb5.v7?status.svg)](https://godoc.org/gopkg.in/jcmturner/gokrb5.v7) [![Go Report Card](https://goreportcard.com/badge/gopkg.in/jcmturner/gokrb5.v7)](https://goreportcard.com/report/gopkg.in/jcmturner/gokrb5.v7) [![Build Status](https://travis-ci.org/jcmturner/gokrb5.svg?branch=master)](https://travis-ci.org/jcmturner/gokrb5)

#### Go Version Support
![Go version](https://img.shields.io/badge/Go-1.12-brightgreen.svg)
![Go version](https://img.shields.io/badge/Go-1.11-brightgreen.svg)
![Go version](https://img.shields.io/badge/Go-1.10-brightgreen.svg)

Expand Down
11 changes: 10 additions & 1 deletion spnego/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"net/http/cookiejar"
"net/url"
Expand Down Expand Up @@ -138,8 +139,16 @@ func respUnauthorizedNegotiate(resp *http.Response) bool {
// To auto generate the SPN from the request object pass a null string "".
func SetSPNEGOHeader(cl *client.Client, r *http.Request, spn string) error {
if spn == "" {
spn = "HTTP/" + strings.SplitN(r.Host, ":", 2)[0]
h := strings.TrimSuffix(strings.SplitN(r.URL.Host, ":", 2)[0], ".")
name, err := net.LookupCNAME(h)
if err == nil {
// Underlyng canonical name should be used for SPN
h = strings.TrimSuffix(name, ".")
}
spn = "HTTP/" + h
r.Host = h
}
cl.Log("using SPN %s", spn)
s := SPNEGOClient(cl, spn)
err := s.AcquireCred()
if err != nil {
Expand Down
113 changes: 52 additions & 61 deletions spnego/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ import (
"gopkg.in/jcmturner/gokrb5.v7/config"
"gopkg.in/jcmturner/gokrb5.v7/keytab"
"gopkg.in/jcmturner/gokrb5.v7/service"
"gopkg.in/jcmturner/gokrb5.v7/test"
"gopkg.in/jcmturner/gokrb5.v7/test/testdata"
)

func TestClient_SetSPNEGOHeader(t *testing.T) {
if os.Getenv("INTEGRATION") != "1" {
t.Skip("Skipping integration test")
}
test.Integration(t)
b, _ := hex.DecodeString(testdata.TESTUSER1_KEYTAB)
kt := keytab.New()
kt.Unmarshal(b)
Expand All @@ -37,49 +36,46 @@ func TestClient_SetSPNEGOHeader(t *testing.T) {
addr = testdata.TEST_KDC_ADDR
}
c.Realms[0].KDC = []string{addr + ":" + testdata.TEST_KDC}
cl := client.NewClientWithKeytab("testuser1", "TEST.GOKRB5", kt, c)
l := log.New(os.Stderr, "SPNEGO Client:", log.LstdFlags)
cl := client.NewClientWithKeytab("testuser1", "TEST.GOKRB5", kt, c, client.Logger(l))

err := cl.Login()
if err != nil {
t.Fatalf("error on AS_REQ: %v\n", err)
}
url := os.Getenv("TEST_HTTP_URL")
if url == "" {
url = testdata.TEST_HTTP_URL
urls := []string{
"http://cname.test.gokrb5",
"http://host.test.gokrb5",
}
paths := []string{
"/modkerb/index.html",
"/modgssapi/index.html",
}
for _, p := range paths {
r, _ := http.NewRequest("GET", url+p, nil)
httpCl := http.DefaultClient
httpCl.CheckRedirect = func(req *http.Request, via []*http.Request) error {
t.Logf("http client redirect: %+v", *req)
return nil
}
httpResp, err := httpCl.Do(r)
if err != nil {
t.Fatalf("%s request error: %v", url+p, err)
}
assert.Equal(t, http.StatusUnauthorized, httpResp.StatusCode, "Status code in response to client with no SPNEGO not as expected")
err = SetSPNEGOHeader(cl, r, "HTTP/host.test.gokrb5")
if err != nil {
t.Fatalf("error setting client SPNEGO header: %v", err)
}
//t.Logf("Reqeust: %+v\n\n", *r)
httpResp, err = http.DefaultClient.Do(r)
if err != nil {
t.Fatalf("%s request error: %v\n", url+p, err)
//"/modgssapi/index.html",
}
for _, url := range urls {
for _, p := range paths {
r, _ := http.NewRequest("GET", url+p, nil)
httpResp, err := http.DefaultClient.Do(r)
if err != nil {
t.Fatalf("%s request error: %v", url+p, err)
}
assert.Equal(t, http.StatusUnauthorized, httpResp.StatusCode, "Status code in response to client with no SPNEGO not as expected")

err = SetSPNEGOHeader(cl, r, "")
if err != nil {
t.Fatalf("error setting client SPNEGO header: %v", err)
}

httpResp, err = http.DefaultClient.Do(r)
if err != nil {
t.Fatalf("%s request error: %v\n", url+p, err)
}
assert.Equal(t, http.StatusOK, httpResp.StatusCode, "Status code in response to client SPNEGO request not as expected")
}
assert.Equal(t, http.StatusOK, httpResp.StatusCode, "Status code in response to client SPNEGO request not as expected")
}
}

func TestSPNEGOHTTPClient(t *testing.T) {
if os.Getenv("INTEGRATION") != "1" {
t.Skip("Skipping integration test")
}
test.Integration(t)
b, _ := hex.DecodeString(testdata.TESTUSER1_KEYTAB)
kt := keytab.New()
kt.Unmarshal(b)
Expand All @@ -89,35 +85,38 @@ func TestSPNEGOHTTPClient(t *testing.T) {
addr = testdata.TEST_KDC_ADDR
}
c.Realms[0].KDC = []string{addr + ":" + testdata.TEST_KDC}
cl := client.NewClientWithKeytab("testuser1", "TEST.GOKRB5", kt, c)
l := log.New(os.Stderr, "SPNEGO Client:", log.LstdFlags)
cl := client.NewClientWithKeytab("testuser1", "TEST.GOKRB5", kt, c, client.Logger(l))

err := cl.Login()
if err != nil {
t.Fatalf("error on AS_REQ: %v\n", err)
}
url := os.Getenv("TEST_HTTP_URL")
if url == "" {
url = testdata.TEST_HTTP_URL
urls := []string{
"http://cname.test.gokrb5",
"http://host.test.gokrb5",
}
// This path issues a redirect which the http client will automatically follow.
// It should cause a replay issue if the negInit token is sent in the first instance.
paths := []string{
"/modgssapi", // This issues a redirect which the http client will automatically follow. Could cause a replay issue
"/redirect",
}
for _, p := range paths {
r, _ := http.NewRequest("GET", url+p, nil)
httpCl := http.DefaultClient
httpCl.CheckRedirect = func(req *http.Request, via []*http.Request) error {
t.Logf("http client redirect: %+v", *req)
return nil
}
spnegoCl := NewClient(cl, httpCl, "HTTP/host.test.gokrb5")
httpResp, err := spnegoCl.Do(r)
if err != nil {
t.Fatalf("%s request error: %v", url+p, err)
for _, url := range urls {
for _, p := range paths {
r, _ := http.NewRequest("GET", url+p, nil)
httpCl := http.DefaultClient
httpCl.CheckRedirect = func(req *http.Request, via []*http.Request) error {
t.Logf("http client redirect: %+v", *req)
return nil
}
spnegoCl := NewClient(cl, httpCl, "")
httpResp, err := spnegoCl.Do(r)
if err != nil {
t.Fatalf("%s request error: %v", url+p, err)
}
assert.Equal(t, http.StatusOK, httpResp.StatusCode, "Status code in response to client SPNEGO request not as expected")
}
assert.Equal(t, http.StatusOK, httpResp.StatusCode, "Status code in response to client SPNEGO request not as expected")
}
}

Expand All @@ -134,9 +133,7 @@ func TestService_SPNEGOKRB_NoAuthHeader(t *testing.T) {
}

func TestService_SPNEGOKRB_ValidUser(t *testing.T) {
if os.Getenv("INTEGRATION") != "1" {
t.Skip("Skipping integration test")
}
test.Integration(t)

s := httpServer()
defer s.Close()
Expand All @@ -156,9 +153,7 @@ func TestService_SPNEGOKRB_ValidUser(t *testing.T) {
}

func TestService_SPNEGOKRB_Replay(t *testing.T) {
if os.Getenv("INTEGRATION") != "1" {
t.Skip("Skipping integration test")
}
test.Integration(t)

s := httpServer()
defer s.Close()
Expand Down Expand Up @@ -215,9 +210,7 @@ func TestService_SPNEGOKRB_Replay(t *testing.T) {
}

func TestService_SPNEGOKRB_ReplayCache_Concurrency(t *testing.T) {
if os.Getenv("INTEGRATION") != "1" {
t.Skip("Skipping integration test")
}
test.Integration(t)

s := httpServer()
defer s.Close()
Expand Down Expand Up @@ -255,9 +248,7 @@ func TestService_SPNEGOKRB_ReplayCache_Concurrency(t *testing.T) {
}

func TestService_SPNEGOKRB_Upload(t *testing.T) {
if os.Getenv("INTEGRATION") != "1" {
t.Skip("Skipping integration test")
}
test.Integration(t)

s := httpServer()
defer s.Close()
Expand Down
1 change: 1 addition & 0 deletions test/testenv/docker/dns/files/named.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/bin/bash

sed -i "s/<TEST_KDC_ADDR>/${TEST_KDC_ADDR}/g" /var/named/data/db.test.gokrb5
sed -i "s/<TEST_HTTP_ADDR>/${TEST_HTTP_ADDR}/g" /var/named/data/db.test.gokrb5

/usr/sbin/named -g -c /etc/named.conf -u bind -4
2 changes: 2 additions & 0 deletions test/testenv/docker/dns/files/zone-files/db.test.gokrb5
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ kdc1a IN A <TEST_KDC_ADDR>
kdc1b IN A <TEST_KDC_ADDR>
kdc2a IN A <TEST_KDC_ADDR>
kdc2b IN A <TEST_KDC_ADDR>
host IN A <TEST_HTTP_ADDR>
cname IN CNAME host

0 comments on commit 50a61c6

Please sign in to comment.