// createInvestigator creates an investigator into the database func createInvestigator(respWriter http.ResponseWriter, request *http.Request) { var err error opid := getOpID(request) loc := fmt.Sprintf("%s%s", ctx.Server.Host, request.URL.String()) resource := cljs.New(loc) defer func() { if e := recover(); e != nil { emsg := fmt.Sprintf("%v", e) ctx.Channels.Log <- mig.Log{OpID: opid, Desc: emsg}.Err() resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: emsg}) respond(500, resource, respWriter, request) } ctx.Channels.Log <- mig.Log{OpID: opid, Desc: "leaving createInvestigator()"}.Debug() }() var inv mig.Investigator err = request.ParseMultipartForm(20480) if err != nil { panic(err) } inv.Name = request.FormValue("name") if inv.Name == "" { panic("Investigator name must not be empty") } // publickey is stored in a multipart post form, extract it _, keyHeader, err := request.FormFile("publickey") if err != nil { panic(err) } keyReader, err := keyHeader.Open() if err != nil { panic(err) } inv.PublicKey, err = ioutil.ReadAll(keyReader) if err != nil { panic(err) } if len(inv.PublicKey) == 0 { panic("Investigator Public Key must not be empty") } // validate the public key and obtain a fingerprint from it inv.PGPFingerprint, err = pgp.LoadArmoredPubKey(inv.PublicKey) if err != nil { panic(err) } // create the investigator in database inv.ID, err = ctx.DB.InsertInvestigator(inv) if err != nil { panic(err) } ctx.Channels.Log <- mig.Log{OpID: opid, Desc: "Investigator created in database"} err = resource.AddItem(cljs.Item{ Href: fmt.Sprintf("%s/investigator?investigatorid=%.0f", ctx.Server.BaseURL, inv.ID), Data: []cljs.Data{{Name: "Investigator ID " + fmt.Sprintf("%.0f", inv.ID), Value: inv}}, }) respond(201, resource, respWriter, request) }
// authenticate is called prior to processing incoming requests. it implements the client // authentication logic, which mostly consist of validating GPG signed tokens and setting the // identity of the signer in the request context func authenticate(pass handler) handler { return func(w http.ResponseWriter, r *http.Request) { var ( err error inv mig.Investigator ) opid := getOpID(r) context.Set(r, opID, opid) if !ctx.Authentication.Enabled { inv.Name = "authdisabled" inv.ID = 0 goto authorized } if r.Header.Get("X-PGPAUTHORIZATION") == "" { inv.Name = "authmissing" inv.ID = -1 resource := cljs.New(fmt.Sprintf("%s%s", ctx.Server.Host, r.URL.String())) resource.SetError(cljs.Error{Code: fmt.Sprintf("%.0f", opid), Message: "X-PGPAUTHORIZATION header not found"}) respond(401, resource, w, r) return } inv, err = verifySignedToken(r.Header.Get("X-PGPAUTHORIZATION")) if err != nil { inv.Name = "authfailed" inv.ID = -1 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("Authorization verification failed with error '%v'", err)}) respond(401, resource, w, r) return } authorized: // store investigator identity in request context context.Set(r, authenticatedInvName, inv.Name) context.Set(r, authenticatedInvID, inv.ID) // accept request pass(w, r) } }