Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: allow to specify customsignatureKey in theconfig.ini#1024

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
dido18 merged 15 commits intomainfromfix-invalid-signature-with-custom-keys
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
15 commits
Select commitHold shift + click to select a range
a5be7b6
make the signaturePubKey overwritable
dido18Mar 25, 2025
dec684b
Add debug logging for signature key parsing and handle newline escape…
dido18Mar 25, 2025
5681091
Add MustParseRsaPublicKey function for parsing PEM formatted public keys
dido18Mar 26, 2025
497a640
Remove debug print statement for signature key and fix comment typo i…
dido18Mar 26, 2025
0711750
Add error logging for command verification and update comment for pub…
dido18Mar 26, 2025
be54150
trigger
dido18Mar 26, 2025
bfcd135
fix(release.yml) install go step for gon
dido18Mar 26, 2025
41e5275
Merge branch 'main' into fix-invalid-signature-with-custom-keys
dido18Mar 26, 2025
8a60882
refactor(main.go) remove unnecessary print statement in parseIni func…
dido18Mar 26, 2025
9601bc0
implement suggestions
dido18Mar 26, 2025
0f7a4fb
Update v2/pkgs/tools.go
dido18Mar 26, 2025
d9348ca
Update utilities/utilities.go
dido18Mar 26, 2025
27e570e
Update main.go
dido18Mar 26, 2025
27b7ce7
refactor(utilities): improve formatting in ParseRsaPublicKey function
dido18Mar 26, 2025
2237ff0
style(tools): align field declarations for improved readability
dido18Mar 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 81 additions & 77 deletionsconn.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,6 +19,7 @@ package main

import (
"bytes"
"crypto/rsa"
"encoding/json"
"errors"
"fmt"
Expand DownExpand Up@@ -79,111 +80,114 @@ type Upload struct {

var uploadStatusStr = "ProgrammerStatus"

func uploadHandler(c *gin.Context) {
data := new(Upload)
if err := c.BindJSON(data); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("err with the payload. %v", err.Error()))
return
}

log.Printf("%+v %+v %+v %+v %+v %+v", data.Port, data.Board, data.Rewrite, data.Commandline, data.Extra, data.Filename)

if data.Port == "" {
c.String(http.StatusBadRequest, "port is required")
return
}

if data.Board == "" {
c.String(http.StatusBadRequest, "board is required")
log.Error("board is required")
return
}

if !data.Extra.Network {
if data.Signature == "" {
c.String(http.StatusBadRequest, "signature is required")
func uploadHandler(pubKey *rsa.PublicKey) func(*gin.Context) {
return func(c *gin.Context) {
data := new(Upload)
if err := c.BindJSON(data); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("err with the payload. %v", err.Error()))
return
}

if data.Commandline == "" {
c.String(http.StatusBadRequest, "commandline is required for local board")
log.Printf("%+v %+v %+v %+v %+v %+v", data.Port, data.Board, data.Rewrite, data.Commandline, data.Extra, data.Filename)

if data.Port == "" {
c.String(http.StatusBadRequest, "port is required")
return
}

err := utilities.VerifyInput(data.Commandline, data.Signature)

if err != nil {
c.String(http.StatusBadRequest, "signature is invalid")
if data.Board == "" {
c.String(http.StatusBadRequest, "board is required")
log.Error("board is required")
return
}
}

buffer := bytes.NewBuffer(data.Hex)
if !data.Extra.Network {
if data.Signature == "" {
c.String(http.StatusBadRequest, "signature is required")
return
}

filePath, err := utilities.SaveFileonTempDir(data.Filename, buffer)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
if data.Commandline == "" {
c.String(http.StatusBadRequest, "commandline is required for local board")
return
}

tmpdir, err := os.MkdirTemp("", "extrafiles")
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
err := utilities.VerifyInput(data.Commandline, data.Signature, pubKey)

for _, extraFile := range data.ExtraFiles {
path, err := utilities.SafeJoin(tmpdir, extraFile.Filename)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
if err != nil {
log.WithField("err", err).Error("Error verifying the command")
c.String(http.StatusBadRequest, "signature is invalid")
return
}
}
log.Printf("Saving %s on %s", extraFile.Filename, path)

err = os.MkdirAll(filepath.Dir(path), 0744)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
buffer := bytes.NewBuffer(data.Hex)

err= os.WriteFile(path, extraFile.Hex, 0644)
filePath,err:= utilities.SaveFileonTempDir(data.Filename, buffer)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
}

if data.Rewrite != "" {
data.Board = data.Rewrite
}

go func() {
// Resolve commandline
commandline, err := upload.PartiallyResolve(data.Board, filePath, tmpdir, data.Commandline, data.Extra, Tools)
tmpdir, err := os.MkdirTemp("", "extrafiles")
if err != nil {
send(map[string]string{uploadStatusStr: "Error", "Msg":err.Error()})
c.String(http.StatusBadRequest,err.Error())
return
}

l := PLogger{Verbose: true}

// Upload
if data.Extra.Network {
err = errors.New("network upload is not supported anymore, pease use OTA instead")
} else {
send(map[string]string{uploadStatusStr: "Starting", "Cmd": "Serial"})
err = upload.Serial(data.Port, commandline, data.Extra, l)
for _, extraFile := range data.ExtraFiles {
path, err := utilities.SafeJoin(tmpdir, extraFile.Filename)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
log.Printf("Saving %s on %s", extraFile.Filename, path)

err = os.MkdirAll(filepath.Dir(path), 0744)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}

err = os.WriteFile(path, extraFile.Hex, 0644)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
}

// Handle result
if err != nil {
send(map[string]string{uploadStatusStr: "Error", "Msg": err.Error()})
return
if data.Rewrite != "" {
data.Board = data.Rewrite
}
send(map[string]string{uploadStatusStr: "Done", "Flash": "Ok"})
}()

c.String(http.StatusAccepted, "")
go func() {
// Resolve commandline
commandline, err := upload.PartiallyResolve(data.Board, filePath, tmpdir, data.Commandline, data.Extra, Tools)
if err != nil {
send(map[string]string{uploadStatusStr: "Error", "Msg": err.Error()})
return
}

l := PLogger{Verbose: true}

// Upload
if data.Extra.Network {
err = errors.New("network upload is not supported anymore, pease use OTA instead")
} else {
send(map[string]string{uploadStatusStr: "Starting", "Cmd": "Serial"})
err = upload.Serial(data.Port, commandline, data.Extra, l)
}

// Handle result
if err != nil {
send(map[string]string{uploadStatusStr: "Error", "Msg": err.Error()})
return
}
send(map[string]string{uploadStatusStr: "Done", "Flash": "Ok"})
}()

c.String(http.StatusAccepted, "")
}
}

// PLogger sends the info from the upload to the websocket
Expand Down
13 changes: 10 additions & 3 deletionsglobals/globals.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,8 +15,15 @@

package globals

// DefaultIndexURL is the default index url
var (
// SignatureKey is the public key used to verify commands and url sent by the builder
SignatureKey = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvc0yZr1yUSen7qmE3cxF\nIE12rCksDnqR+Hp7o0nGi9123eCSFcJ7CkIRC8F+8JMhgI3zNqn4cUEn47I3RKD1\nZChPUCMiJCvbLbloxfdJrUi7gcSgUXrlKQStOKF5Iz7xv1M4XOP3JtjXLGo3EnJ1\npFgdWTOyoSrA8/w1rck4c/ISXZSinVAggPxmLwVEAAln6Itj6giIZHKvA2fL2o8z\nCeK057Lu8X6u2CG8tRWSQzVoKIQw/PKK6CNXCAy8vo4EkXudRutnEYHEJlPkVgPn\n2qP06GI+I+9zKE37iqj0k1/wFaCVXHXIvn06YrmjQw6I0dDj/60Wvi500FuRVpn9\ntwIDAQAB\n-----END PUBLIC KEY-----"
// ArduinoSignaturePubKey is the public key used to verify commands and url sent by the builder
ArduinoSignaturePubKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvc0yZr1yUSen7qmE3cxF
IE12rCksDnqR+Hp7o0nGi9123eCSFcJ7CkIRC8F+8JMhgI3zNqn4cUEn47I3RKD1
ZChPUCMiJCvbLbloxfdJrUi7gcSgUXrlKQStOKF5Iz7xv1M4XOP3JtjXLGo3EnJ1
pFgdWTOyoSrA8/w1rck4c/ISXZSinVAggPxmLwVEAAln6Itj6giIZHKvA2fL2o8z
CeK057Lu8X6u2CG8tRWSQzVoKIQw/PKK6CNXCAy8vo4EkXudRutnEYHEJlPkVgPn
2qP06GI+I+9zKE37iqj0k1/wFaCVXHXIvn06YrmjQw6I0dDj/60Wvi500FuRVpn9
twIDAQAB
-----END PUBLIC KEY-----`
)
16 changes: 12 additions & 4 deletionsmain.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -81,7 +81,7 @@ var (
logDump = iniConf.String("log", "off", "off = (default)")
origins = iniConf.String("origins", "", "Allowed origin list for CORS")
portsFilterRegexp = iniConf.String("regex", "usb|acm|com", "Regular expression to filter serial port list")
signatureKey = iniConf.String("signatureKey", globals.SignatureKey, "Pem-encoded public key to verify signed commandlines")
signatureKey = iniConf.String("signatureKey", globals.ArduinoSignaturePubKey, "Pem-encoded public key to verify signed commandlines")
updateURL = iniConf.String("updateUrl", "", "")
verbose = iniConf.Bool("v", true, "show debug logging")
crashreport = iniConf.Bool("crashreport", false, "enable crashreport logging")
Expand DownExpand Up@@ -278,9 +278,17 @@ func loop() {
}
}

if signatureKey == nil || len(*signatureKey) == 0 {
log.Panicf("signature public key should be set")
}
signaturePubKey, err := utilities.ParseRsaPublicKey([]byte(*signatureKey))
if err != nil {
log.Panicf("cannot parse signature key '%s'. %s", *signatureKey, err)
}

// Instantiate Index and Tools
Index = index.Init(*indexURL, config.GetDataDir())
Tools = tools.New(config.GetDataDir(), Index, logger)
Tools = tools.New(config.GetDataDir(), Index, logger, signaturePubKey)

// see if we are supposed to wait 5 seconds
if *isLaunchSelf {
Expand DownExpand Up@@ -454,7 +462,7 @@ func loop() {
r.LoadHTMLFiles("templates/nofirefox.html")

r.GET("/", homeHandler)
r.POST("/upload", uploadHandler)
r.POST("/upload", uploadHandler(signaturePubKey))
r.GET("/socket.io/", socketHandler)
r.POST("/socket.io/", socketHandler)
r.Handle("WS", "/socket.io/", socketHandler)
Expand All@@ -464,7 +472,7 @@ func loop() {
r.POST("/update", updateHandler)

// Mount goa handlers
goa := v2.Server(config.GetDataDir().String(), Index)
goa := v2.Server(config.GetDataDir().String(), Index, signaturePubKey)
r.Any("/v2/*path", gin.WrapH(goa))

go func() {
Expand Down
10 changes: 6 additions & 4 deletionsmain_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,8 +30,10 @@ import (

"github.com/arduino/arduino-create-agent/config"
"github.com/arduino/arduino-create-agent/gen/tools"
"github.com/arduino/arduino-create-agent/globals"
"github.com/arduino/arduino-create-agent/index"
"github.com/arduino/arduino-create-agent/upload"
"github.com/arduino/arduino-create-agent/utilities"
v2 "github.com/arduino/arduino-create-agent/v2"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
Expand All@@ -54,7 +56,7 @@ func TestValidSignatureKey(t *testing.T) {

func TestUploadHandlerAgainstEvilFileNames(t *testing.T) {
r := gin.New()
r.POST("/", uploadHandler)
r.POST("/", uploadHandler(utilities.MustParseRsaPublicKey([]byte(globals.ArduinoSignaturePubKey))))
ts := httptest.NewServer(r)

uploadEvilFileName := Upload{
Expand DownExpand Up@@ -90,7 +92,7 @@ func TestUploadHandlerAgainstEvilFileNames(t *testing.T) {

func TestUploadHandlerAgainstBase64WithoutPaddingMustFail(t *testing.T) {
r := gin.New()
r.POST("/", uploadHandler)
r.POST("/", uploadHandler(utilities.MustParseRsaPublicKey([]byte(globals.ArduinoSignaturePubKey))))
ts := httptest.NewServer(r)
defer ts.Close()

Expand DownExpand Up@@ -119,7 +121,7 @@ func TestInstallToolV2(t *testing.T) {
Index := index.Init(indexURL, config.GetDataDir())

r := gin.New()
goa := v2.Server(config.GetDataDir().String(), Index)
goa := v2.Server(config.GetDataDir().String(), Index, utilities.MustParseRsaPublicKey([]byte(globals.ArduinoSignaturePubKey)))
r.Any("/v2/*path", gin.WrapH(goa))
ts := httptest.NewServer(r)

Expand DownExpand Up@@ -213,7 +215,7 @@ func TestInstalledHead(t *testing.T) {
Index := index.Init(indexURL, config.GetDataDir())

r := gin.New()
goa := v2.Server(config.GetDataDir().String(), Index)
goa := v2.Server(config.GetDataDir().String(), Index, utilities.MustParseRsaPublicKey([]byte(globals.ArduinoSignaturePubKey)))
r.Any("/v2/*path", gin.WrapH(goa))
ts := httptest.NewServer(r)

Expand Down
6 changes: 4 additions & 2 deletionstools/download_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,7 +21,9 @@ import (
"testing"
"time"

"github.com/arduino/arduino-create-agent/globals"
"github.com/arduino/arduino-create-agent/index"
"github.com/arduino/arduino-create-agent/utilities"
"github.com/arduino/arduino-create-agent/v2/pkgs"
"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
Expand DownExpand Up@@ -128,7 +130,7 @@ func TestDownload(t *testing.T) {
IndexFile: *paths.New("testdata", "test_tool_index.json"),
LastRefresh: time.Now(),
}
testTools := New(tempDirPath, &testIndex, func(msg string) { t.Log(msg) })
testTools := New(tempDirPath, &testIndex, func(msg string) { t.Log(msg) }, utilities.MustParseRsaPublicKey([]byte(globals.ArduinoSignaturePubKey)))

for _, tc := range testCases {
t.Run(tc.name+"-"+tc.version, func(t *testing.T) {
Expand DownExpand Up@@ -175,7 +177,7 @@ func TestCorruptedInstalled(t *testing.T) {
defer fileJSON.Close()
_, err = fileJSON.Write([]byte("Hello"))
require.NoError(t, err)
testTools := New(tempDirPath, &testIndex, func(msg string) { t.Log(msg) })
testTools := New(tempDirPath, &testIndex, func(msg string) { t.Log(msg) }, utilities.MustParseRsaPublicKey([]byte(globals.ArduinoSignaturePubKey)))
// Download the tool
err = testTools.Download("arduino-test", "avrdude", "6.3.0-arduino17", "keep")
require.NoError(t, err)
Expand Down
5 changes: 3 additions & 2 deletionstools/tools.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
package tools

import (
"crypto/rsa"
"encoding/json"
"path/filepath"
"strings"
Expand DownExpand Up@@ -55,14 +56,14 @@ type Tools struct {
// The New functions accept the directory to use to host the tools,
// an index (used to download the tools),
// and a logger to log the operations
func New(directory *paths.Path, index *index.Resource, logger func(msg string)) *Tools {
func New(directory *paths.Path, index *index.Resource, logger func(msg string), signPubKey *rsa.PublicKey) *Tools {
t := &Tools{
directory: directory,
index: index,
logger: logger,
installed: map[string]string{},
mutex: sync.RWMutex{},
tools: pkgs.New(index, directory.String(), "replace"),
tools: pkgs.New(index, directory.String(), "replace", signPubKey),
}
_ = t.readMap()
return t
Expand Down
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp