// 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) }
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 } }