diff --git a/conn.go b/conn.go index 4989ebd6a..f8ce768e1 100644 --- a/conn.go +++ b/conn.go @@ -3,6 +3,13 @@ package main import ( + "crypto" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/hex" + "encoding/pem" + "errors" "net/http" "strconv" @@ -61,6 +68,23 @@ func uploadHandler(c *gin.Context) { if commandline == "undefined" { commandline = "" } + + signature := c.PostForm("signature") + if signature == "" { + c.String(http.StatusBadRequest, "signature is required") + log.Error("signature is required") + return + } + + err := verifyCommandLine(commandline, signature) + + if err != nil { + c.String(http.StatusBadRequest, "signature is invalid") + log.Error("signature is invalid") + log.Error(err) + return + } + extraInfo.use_1200bps_touch, _ = strconv.ParseBool(c.PostForm("use_1200bps_touch")) extraInfo.wait_for_upload_port, _ = strconv.ParseBool(c.PostForm("wait_for_upload_port")) extraInfo.networkPort, _ = strconv.ParseBool(c.PostForm("network")) @@ -90,6 +114,23 @@ func uploadHandler(c *gin.Context) { } } +func verifyCommandLine(input string, signature string) error { + sign, _ := hex.DecodeString(signature) + block, _ := pem.Decode([]byte(*signatureKey)) + if block == nil { + return errors.New("invalid key") + } + key, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return err + } + rsaKey := key.(*rsa.PublicKey) + h := sha256.New() + h.Write([]byte(input)) + d := h.Sum(nil) + return rsa.VerifyPKCS1v15(rsaKey, crypto.SHA256, d, sign) +} + func wsHandler() *WsServer { server, err := socketio.NewServer(nil) if err != nil { diff --git a/main.go b/main.go index d9725f572..c5ae29c3f 100755 --- a/main.go +++ b/main.go @@ -43,6 +43,7 @@ var ( port string portSSL string origins = flag.String("origins", "", "Allowed origin list for CORS") + signatureKey = flag.String("signatureKey", "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvc0yZr1yUSen7qmE3cxF\nIE12rCksDnqR+Hp7o0nGi9123eCSFcJ7CkIRC8F+8JMhgI3zNqn4cUEn47I3RKD1\nZChPUCMiJCvbLbloxfdJrUi7gcSgUXrlKQStOKF5Iz7xv1M4XOP3JtjXLGo3EnJ1\npFgdWTOyoSrA8/w1rck4c/ISXZSinVAggPxmLwVEAAln6Itj6giIZHKvA2fL2o8z\nCeK057Lu8X6u2CG8tRWSQzVoKIQw/PKK6CNXCAy8vo4EkXudRutnEYHEJlPkVgPn\n2qP06GI+I+9zKE37iqj0k1/wFaCVXHXIvn06YrmjQw6I0dDj/60Wvi500FuRVpn9\ntwIDAQAB\n-----END PUBLIC KEY-----", "Pem-encoded public key to verify signed commandlines") address = flag.String("address", "127.0.0.1", "The address where to listen. Defaults to localhost") ) @@ -242,8 +243,7 @@ func main() { log.Printf("Error trying to bind to port: %v, so exiting...", err) continue } else { - ip := "0.0.0.0" - log.Print("Starting server and websocket (SSL) on " + ip + "" + port) + log.Print("Starting server and websocket (SSL) on " + *address + "" + port) break } } @@ -260,8 +260,7 @@ func main() { log.Printf("Error trying to bind to port: %v, so exiting...", err) continue } else { - ip := "0.0.0.0" - log.Print("Starting server and websocket on " + ip + "" + port) + log.Print("Starting server and websocket on " + *address + "" + port) break } }