// allowed implements the SPNEGO protocol. When the request is to be passed // through, it returns http.StatusOK and a valid gssapi CtxId object. // Otherwise, it sets the WWW-Authorization header as applicable, and returns // http.StatusUnathorized. func allowed(c *Context, w http.ResponseWriter, r *http.Request) ( ctx *gssapi.CtxId, code int, message string) { // returning a 401 with a challenge, but no token will make the client // initiate security context and re-submit with a non-empty Authorization negotiate, inputToken := spnego.CheckSPNEGONegotiate(c.Lib, r.Header, "Authorization") if !negotiate || inputToken.Length() == 0 { spnego.AddSPNEGONegotiate(w.Header(), "WWW-Authenticate", nil) return nil, http.StatusUnauthorized, "no input token provided" } ctx, srcName, _, outputToken, _, _, delegatedCredHandle, err := c.AcceptSecContext(c.GSS_C_NO_CONTEXT, c.credential, inputToken, c.GSS_C_NO_CHANNEL_BINDINGS) //TODO: special case handling of GSS_S_CONTINUE_NEEDED // but it doesn't change the logic, still fail if err != nil { //TODO: differentiate invalid tokens here and return a 403 //TODO: add a test for a bad and maybe an expired auth tokens return nil, http.StatusInternalServerError, err.Error() } srcName.Release() delegatedCredHandle.Release() spnego.AddSPNEGONegotiate(w.Header(), "WWW-Authenticate", outputToken) return ctx, http.StatusOK, "pass" }
func initClientContext(t *testing.T, method, path string, bodyf func(ctx *gssapi.CtxId) string) ( ctx *gssapi.CtxId, r *http.Request) { // establish a context ctx, _, token, _, _, err := c.InitSecContext( c.GSS_C_NO_CREDENTIAL, nil, prepareServiceName(t), c.GSS_C_NO_OID, 0, 0, c.GSS_C_NO_CHANNEL_BINDINGS, c.GSS_C_NO_BUFFER) defer token.Release() if err != nil { e, ok := err.(*gssapi.Error) if ok && e.Major.ContinueNeeded() { t.Fatal("Unexpected GSS_S_CONTINUE_NEEDED") } t.Fatal(err) } u := c.ServiceAddress + path if !strings.HasPrefix(u, "http://") { u = "http://" + u } body := io.Reader(nil) if bodyf != nil { body = bytes.NewBufferString(bodyf(ctx)) } r, err = http.NewRequest(method, u, body) if err != nil { t.Fatal(err) } spnego.AddSPNEGONegotiate(r.Header, "Authorization", token) return ctx, r }