Skip to content

Commit fdde50e

Browse files
Merge pull request #11371 from enj/enj/f/sspi
Implement SSPI Support on Windows (oc Kerberos)
2 parents a8ae00e + 919477b commit fdde50e

33 files changed

+3618
-63
lines changed

glide.lock

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

glide.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ import:
161161
# auth (for oc kerberos on linux + mac)
162162
- package: github.com/apcera/gssapi
163163
version: release-2.6.3
164+
# auth (for oc kerberos on windows)
165+
- package: github.com/alexbrainman/sspi
166+
version: e580b900e9f5657daa5473021296289be6da2661
164167
# new-app
165168
- package: github.com/joho/godotenv
166169
version: 6d367c18edf6ca7fd004efd6863e4c5728fa858e

pkg/oc/cli/cmd/version.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,13 @@ func (o VersionOptions) RunVersion() error {
113113
}
114114
if tokencmd.GSSAPIEnabled() {
115115
features = append(features, "GSSAPI")
116-
features = append(features, "Kerberos") // GSSAPI or SSPI
117-
features = append(features, "SPNEGO") // GSSAPI or SSPI
116+
}
117+
if tokencmd.SSPIEnabled() {
118+
features = append(features, "SSPI")
119+
}
120+
if tokencmd.GSSAPIEnabled() || tokencmd.SSPIEnabled() {
121+
features = append(features, "Kerberos")
122+
features = append(features, "SPNEGO")
118123
}
119124
fmt.Printf("features: %s\n", strings.Join(features, " "))
120125
}

pkg/oc/util/tokencmd/negotiate.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
"github.com/golang/glog"
1010
)
1111

12-
// Negotiater defines the minimal interface needed to interact with GSSAPI to perform a negotiate challenge/response
13-
type Negotiater interface {
12+
// Negotiator defines the minimal interface needed to interact with GSSAPI to perform a negotiate challenge/response
13+
type Negotiator interface {
1414
// Load gives the negotiator a chance to load any resources needed to handle a challenge/response sequence.
1515
// It may be invoked multiple times. If an error is returned, InitSecContext and IsComplete are not called, but Release() is.
1616
Load() error
@@ -28,11 +28,11 @@ type Negotiater interface {
2828
// NegotiateChallengeHandler manages a challenge negotiation session
2929
// it is single-host, single-use only, and not thread-safe
3030
type NegotiateChallengeHandler struct {
31-
negotiater Negotiater
31+
negotiator Negotiator
3232
}
3333

34-
func NewNegotiateChallengeHandler(negotiater Negotiater) ChallengeHandler {
35-
return &NegotiateChallengeHandler{negotiater: negotiater}
34+
func NewNegotiateChallengeHandler(negotiator Negotiator) ChallengeHandler {
35+
return &NegotiateChallengeHandler{negotiator: negotiator}
3636
}
3737

3838
func (c *NegotiateChallengeHandler) CanHandle(headers http.Header) bool {
@@ -41,7 +41,7 @@ func (c *NegotiateChallengeHandler) CanHandle(headers http.Header) bool {
4141
return false
4242
}
4343
// Make sure our negotiator can initialize
44-
if err := c.negotiater.Load(); err != nil {
44+
if err := c.negotiator.Load(); err != nil {
4545
return false
4646
}
4747
return true
@@ -55,7 +55,7 @@ func (c *NegotiateChallengeHandler) HandleChallenge(requestURL string, headers h
5555
}
5656

5757
// Process the token
58-
outgoingToken, err := c.negotiater.InitSecContext(requestURL, incomingToken)
58+
outgoingToken, err := c.negotiator.InitSecContext(requestURL, incomingToken)
5959
if err != nil {
6060
glog.V(5).Infof("InitSecContext returned error: %v", err)
6161
return nil, false, err
@@ -68,7 +68,7 @@ func (c *NegotiateChallengeHandler) HandleChallenge(requestURL string, headers h
6868
}
6969

7070
func (c *NegotiateChallengeHandler) CompleteChallenge(requestURL string, headers http.Header) error {
71-
if c.negotiater.IsComplete() {
71+
if c.negotiator.IsComplete() {
7272
return nil
7373
}
7474
glog.V(5).Infof("continue needed")
@@ -83,19 +83,19 @@ func (c *NegotiateChallengeHandler) CompleteChallenge(requestURL string, headers
8383
}
8484

8585
// Process the token
86-
_, err = c.negotiater.InitSecContext(requestURL, incomingToken)
86+
_, err = c.negotiator.InitSecContext(requestURL, incomingToken)
8787
if err != nil {
8888
glog.V(5).Infof("InitSecContext returned error during final negotiation: %v", err)
8989
return err
9090
}
91-
if !c.negotiater.IsComplete() {
91+
if !c.negotiator.IsComplete() {
9292
return errors.New("InitSecContext did not indicate final negotiation completed")
9393
}
9494
return nil
9595
}
9696

9797
func (c *NegotiateChallengeHandler) Release() error {
98-
return c.negotiater.Release()
98+
return c.negotiator.Release()
9999
}
100100

101101
const negotiateScheme = "negotiate"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package tokencmd
2+
3+
import (
4+
"errors"
5+
"net/url"
6+
)
7+
8+
func getServiceName(sep rune, requestURL string) (string, error) {
9+
u, err := url.Parse(requestURL)
10+
if err != nil {
11+
return "", err
12+
}
13+
14+
return "HTTP" + string(sep) + u.Hostname(), nil
15+
}
16+
17+
type negotiateUnsupported struct {
18+
error
19+
}
20+
21+
func newUnsupportedNegotiator(name string) Negotiator {
22+
return &negotiateUnsupported{error: errors.New(name + " support is not enabled")}
23+
}
24+
25+
func (n *negotiateUnsupported) Load() error {
26+
return n
27+
}
28+
29+
func (n *negotiateUnsupported) InitSecContext(requestURL string, challengeToken []byte) ([]byte, error) {
30+
return nil, n
31+
}
32+
33+
func (*negotiateUnsupported) IsComplete() bool {
34+
return false
35+
}
36+
37+
func (n *negotiateUnsupported) Release() error {
38+
return n
39+
}

pkg/oc/util/tokencmd/negotiator_gssapi.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ package tokencmd
44

55
import (
66
"errors"
7-
"net"
8-
"net/url"
97
"runtime"
108
"sync"
119
"time"
@@ -46,7 +44,7 @@ type gssapiNegotiator struct {
4644
complete bool
4745
}
4846

49-
func NewGSSAPINegotiator(principalName string) Negotiater {
47+
func NewGSSAPINegotiator(principalName string) Negotiator {
5048
return &gssapiNegotiator{principalName: principalName}
5149
}
5250

@@ -90,17 +88,11 @@ func (g *gssapiNegotiator) InitSecContext(requestURL string, challengeToken []by
9088
g.cred = lib.GSS_C_NO_CREDENTIAL
9189
}
9290

93-
u, err := url.Parse(requestURL)
91+
serviceName, err := getServiceName('@', requestURL)
9492
if err != nil {
9593
return nil, err
9694
}
9795

98-
hostname := u.Host
99-
if h, _, err := net.SplitHostPort(u.Host); err == nil {
100-
hostname = h
101-
}
102-
103-
serviceName := "HTTP@" + hostname
10496
glog.V(5).Infof("importing service name %s", serviceName)
10597
nameBuf, err := lib.MakeBufferString(serviceName)
10698
if err != nil {

pkg/oc/util/tokencmd/negotiator_gssapi_unsupported.go

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,10 @@
22

33
package tokencmd
44

5-
import "errors"
6-
75
func GSSAPIEnabled() bool {
86
return false
97
}
108

11-
type gssapiUnsupported struct{}
12-
13-
func NewGSSAPINegotiator(principalName string) Negotiater {
14-
return &gssapiUnsupported{}
15-
}
16-
17-
func (g *gssapiUnsupported) Load() error {
18-
return errors.New("GSSAPI support is not enabled")
19-
}
20-
func (g *gssapiUnsupported) InitSecContext(requestURL string, challengeToken []byte) (tokenToSend []byte, err error) {
21-
return nil, errors.New("GSSAPI support is not enabled")
22-
}
23-
func (g *gssapiUnsupported) IsComplete() bool {
24-
return false
25-
}
26-
func (g *gssapiUnsupported) Release() error {
27-
return errors.New("GSSAPI support is not enabled")
9+
func NewGSSAPINegotiator(string) Negotiator {
10+
return newUnsupportedNegotiator("GSSAPI")
2811
}

0 commit comments

Comments
 (0)