// Attempt to obtain the loader key from the file system and override the // built-in secret func loadLoaderKey() error { fd, err := os.Open(getLoaderKeyfile()) if err != nil { if os.IsNotExist(err) { return nil } return err } defer fd.Close() buf, _, err := bufio.NewReader(fd).ReadLine() if err != nil { // Nothing in the loader key file if err == io.EOF { return nil } return err } // Also trim any leading and trailing spaces from the loader key LOADERKEY = strings.Trim(string(buf), " ") err = mig.ValidateLoaderPrefixAndKey(LOADERKEY) if err != nil { return err } ctx.LoaderKey = LOADERKEY return nil }
func hashAuthenticateLoader(lkey string) (ldr mig.LoaderEntry, err error) { err = mig.ValidateLoaderPrefixAndKey(lkey) if err != nil { return } prefix := lkey[:mig.LoaderPrefixLength] suppkey := lkey[mig.LoaderPrefixLength:] lad, err := ctx.DB.GetLoaderAuthDetails(prefix) if err != nil { return } tryhash, _, err := hashLoaderKey(suppkey, lad.Salt) if err != nil { return } if !bytes.Equal(tryhash, lad.Hash) { err = fmt.Errorf("Loader key authentication failed") return } ldr, err = ctx.DB.GetLoaderFromID(lad.ID) return }
// authenticateLoader is used to authenticate requests that are made to the // loader API endpoints. Rather than operate on GPG signatures, the // authentication instead uses the submitted loader key func authenticateLoader(pass handler) handler { return func(w http.ResponseWriter, r *http.Request) { var ( err error ldr mig.LoaderEntry ) opid := getOpID(r) context.Set(r, opID, opid) context.Set(r, apiRequestCategory, RequestCategoryLoader) lkey := r.Header.Get("X-LOADERKEY") if lkey == "" { resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: "X-LOADERKEY header not found"}) respond(http.StatusUnauthorized, resource, w, r) return } err = mig.ValidateLoaderPrefixAndKey(lkey) if err != nil { goto authfailed } ldr, err = hashAuthenticateLoader(lkey) if err != nil { goto authfailed } context.Set(r, loaderID, ldr.ID) context.Set(r, loaderName, ldr.Name) // accept request pass(w, r) return authfailed: context.Set(r, loaderName, "authfailed") resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: fmt.Sprintf("Loader authorization failed")}) respond(http.StatusUnauthorized, resource, w, r) } }