140 lines
3.4 KiB
Go
Executable File
140 lines
3.4 KiB
Go
Executable File
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
|
|
}
|