package main import ( "encoding/json" "local/encryptor" "local/system/sysconf" "local/watchman/client/watchman" "log" "net/http" ) type API struct { conf sysconf.Conf enc encryptor.Encryptor storage *Storage junk map[string]string nextJunk string } func newAPI(conf sysconf.Conf) (*API, error) { store, err := newStorage() if err != nil { return nil, err } enc := encryptor.NewEncryptor("", "") if err := store.set(keyBucket, serviceName, enc.GetPublic()); err != nil { return nil, err } return &API{ storage: store, conf: conf, enc: enc, junk: make(map[string]string), nextJunk: encryptor.NewEncryptor("", "").GetPublic(), }, nil } func (api *API) ServeHTTP(w http.ResponseWriter, r *http.Request) { httpr := &HTTPRequest{w: w, r: r} action := httpr.PathAdvance() if action == "getpub" { api.pubKeyGet(httpr) return } if err := httpr.readBody(api.enc); err != nil { return } switch action { case "setpub": api.pubKeySet(httpr) case "push": api.push(httpr) case "pull": api.pull(httpr) default: w.WriteHeader(http.StatusNotFound) } } func (api *API) pubKeyGet(httpr *HTTPRequest) { body, err := httpr.limitReader() if err != nil { httpr.result(http.StatusRequestEntityTooLarge, err, nil) return } if len(body) == 0 { httpr.result(http.StatusBadRequest, nil, nil) return } // if asks for server pub, then return server pub if string(body) == serviceName { httpr.result(http.StatusOK, nil, api.enc.GetPublic()) return } // else if encrypted with server's pub, then return any if decrypted := api.enc.Decrypt(string(body)); decrypted != "" { if pub, err := api.storage.get(keyBucket, decrypted); err == nil { httpr.result(http.StatusOK, nil, pub) } httpr.result(http.StatusNotFound, nil, nil) return } // else return garbage if v, ok := api.junk[string(body)]; ok { httpr.result(secretError, nil, v) } else { api.junk[string(body)] = api.nextJunk httpr.result(secretError, nil, api.junk[string(body)]) go func() { api.nextJunk = encryptor.NewEncryptor("", "").GetPublic() }() } } func (api *API) pubKeySet(httpr *HTTPRequest) { var setRequest struct { Key string `json:"key"` ID string `json:"id"` } if err := json.Unmarshal([]byte(httpr.body), &setRequest); err != nil { httpr.result(http.StatusBadRequest, nil, nil) return } api.storage.set(keyBucket, setRequest.ID, setRequest.Key) } func (api *API) push(httpr *HTTPRequest) { var pack watchman.Package if err := json.Unmarshal([]byte(httpr.body), &pack); err != nil { httpr.result(http.StatusBadRequest, err, nil) return } if err := api.storage.set("objects", storePath(pack), httpr.body); err != nil { httpr.result(http.StatusInternalServerError, err, nil) return } httpr.result(http.StatusOK, nil, nil) } func (api *API) pull(httpr *HTTPRequest) { var pack watchman.Package if err := json.Unmarshal([]byte(httpr.body), &pack); err != nil { httpr.result(http.StatusBadRequest, err, nil) return } b, err := api.storage.get("objects", storePath(pack)) if err != nil { httpr.result(http.StatusNotFound, err, nil) return } enc := encryptor.NewEncryptor("", "") enc.SetSymmetric(string(pack.Packs[0])) encrypted := enc.Encrypt(string(b)) log.Print("returning content", string(b)) httpr.result(http.StatusOK, nil, encrypted) } func storePath(pack watchman.Package) string { return pack.ID + "_" + pack.Path }