package main import ( "crypto/openpgp" "epoint/logic" "fmt" "log" "net/http" "os" ) const ( addr = ":8080" rootdir = "docroot" seckey = "./key.sec" ) var serverkey *openpgp.Entity // todo: http header limit: 64K, body limit: 64K // Dummy initialization of serverkey func initkey() (err error) { f, err := os.Open(seckey) if err != nil { return } keys, err := openpgp.ReadKeyRing(f) if err != nil { f.Close() return } err = f.Close() if err != nil { return } serverkey = keys[0] err = os.MkdirAll(rootdir, 0755) if err != nil { return } f, err = os.Create(rootdir + "/serverkey") if err != nil { return } err = serverkey.Serialize(f) if err != nil { return } // TODO: make sure pubkey is replicated and available err = f.Sync() if err != nil { return } err = f.Close() return } func httpError(w http.ResponseWriter, code int, msg string) { log.Printf("error: %d %s", code, msg) http.Error(w, fmt.Sprintf("%d %s\n\n%s\n", code, http.StatusText(code), msg), code) } func httpReq(r *http.Request) string { err := r.ParseForm() form := "" if err != nil { form = err.Error() } else { a := []string{} for k := range r.Form { a = append(a, k) } form = fmt.Sprintf("%v", a) } return fmt.Sprintf("%s %s params:%s", r.Method, r.URL.Raw, form) } func defaultHandler(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.RemoteAddr, httpReq(r)) fmt.Fprintf(w, "not implemented: %s %s\n", r.Method, r.URL.Raw) } func submitHandler(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s", r.RemoteAddr, httpReq(r)) draft := r.FormValue("draft") debit := r.FormValue("debit") key := r.FormValue("key") switch { case draft != "": cert, err := logic.EvalDraft([]byte(draft), serverkey) if err != nil { msg := fmt.Sprintf("eval draft failed: %s", err) httpError(w, 404, msg) } else { w.Write(cert) } case debit != "": cert, err := logic.EvalDebitCert([]byte(debit), serverkey) if err != nil { msg := fmt.Sprintf("eval debit failed: %s", err) httpError(w, 404, msg) } else { w.Write(cert) } case key != "": err := logic.AddKeys([]byte(key)) if err != nil { msg := fmt.Sprintf("add keys failed: %s", err) httpError(w, 404, msg) } else { w.Write([]byte("ok\nTODO: create cert 1 here?")) } default: msg := fmt.Sprintf("expected key, draft or debit param, got: %s", httpReq(r)) httpError(w, 404, msg) } } func main() { err := initkey() if err != nil { log.Fatal(err) } err = logic.Init(rootdir) if err != nil { log.Fatal(err) } // TODO: url from key f, err := os.Create(rootdir + "/form.html") if err != nil { log.Fatal(err) } _, _ = fmt.Fprintf(f, `epoint-server submit form

epoint-server submit form

web form

submit one document at once

key:

draft:

debit:

command line

curl --data-urlencode name@path/to/file.txt host/submit
where 'name' is 'key', 'draft' or 'debit'. `, addr) _ = f.Close() // queries http.Handle("/", http.FileServer(http.Dir(rootdir))) // actions // withdraw, draw, deposit, process, clear http.HandleFunc("/submit", submitHandler) log.Printf("start service on %s, server key id: %X\n", addr, serverkey.PrimaryKey.Fingerprint) log.Fatal(http.ListenAndServe(addr, nil)) }