예제 #1
0
// AddSPNEGONegotiate adds a Negotiate header with the value of a serialized
// token to an http header.
func AddSPNEGONegotiate(h http.Header, name string, token *gssapi.Buffer) {
	if name == "" {
		return
	}

	v := "Negotiate"
	if token.Length() != 0 {
		data := token.Bytes()
		v = v + " " + base64.StdEncoding.EncodeToString(data)
	}
	h.Set(name, v)
}
예제 #2
0
func (g *gssapiNegotiator) InitSecContext(requestURL string, challengeToken []byte) (tokenToSend []byte, err error) {
	lib, err := g.loadLib()
	if err != nil {
		return nil, err
	}

	// Initialize our context if we haven't already
	if g.ctx == nil {

		if len(g.principalName) > 0 {
			// Get credentials for a specific principal
			glog.V(5).Infof("acquiring credentials for principal name %s", g.principalName)
			credBuffer, err := lib.MakeBufferString(g.principalName)
			if err != nil {
				return nil, err
			}
			defer credBuffer.Release()

			credName, err := credBuffer.Name(lib.GSS_KRB5_NT_PRINCIPAL_NAME)
			if err != nil {
				return nil, err
			}
			defer credName.Release()

			cred, _, _, err := lib.AcquireCred(credName, time.Duration(0), lib.GSS_C_NO_OID_SET, gssapi.GSS_C_INITIATE)
			if err != nil {
				glog.V(5).Infof("AcquireCred returned error: %v", err)
				return nil, err
			}
			g.cred = cred
		} else {
			// otherwise, express no opinion about the credentials and let gssapi decide
			g.cred = lib.GSS_C_NO_CREDENTIAL
		}

		u, err := url.Parse(requestURL)
		if err != nil {
			return nil, err
		}

		hostname := u.Host
		if h, _, err := net.SplitHostPort(u.Host); err == nil {
			hostname = h
		}

		serviceName := "HTTP@" + hostname
		glog.V(5).Infof("importing service name %s", serviceName)
		nameBuf, err := lib.MakeBufferString(serviceName)
		if err != nil {
			return nil, err
		}
		defer nameBuf.Release()

		name, err := nameBuf.Name(lib.GSS_C_NT_HOSTBASED_SERVICE)
		if err != nil {
			return nil, err
		}
		g.name = name
		g.ctx = lib.GSS_C_NO_CONTEXT
	}

	incomingTokenBuffer, err := lib.MakeBufferBytes(challengeToken)
	if err != nil {
		return nil, err
	}
	defer incomingTokenBuffer.Release()

	var outgoingToken *gssapi.Buffer
	g.ctx, _, outgoingToken, _, _, err = lib.InitSecContext(g.cred, g.ctx, g.name, lib.GSS_C_NO_OID, g.flags, time.Duration(0), lib.GSS_C_NO_CHANNEL_BINDINGS, incomingTokenBuffer)
	defer outgoingToken.Release()

	switch err {
	case nil:
		glog.V(5).Infof("InitSecContext returned GSS_S_COMPLETE")
		g.complete = true
		return outgoingToken.Bytes(), nil
	case gssapi.ErrContinueNeeded:
		glog.V(5).Infof("InitSecContext returned GSS_S_CONTINUE_NEEDED")
		g.complete = false
		return outgoingToken.Bytes(), nil
	default:
		glog.V(5).Infof("InitSecContext returned error: %v", err)
		return nil, err
	}
}